diff options
-rw-r--r-- | CMakeLists.txt | 6 | ||||
-rw-r--r-- | NEWS | 26 | ||||
-rw-r--r-- | src/ufodecode-private.h | 3 | ||||
-rw-r--r-- | src/ufodecode.c | 101 | ||||
-rw-r--r-- | src/ufodecode.h | 76 | ||||
-rw-r--r-- | test/ipedec.c | 153 |
6 files changed, 246 insertions, 119 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 8ae2e1c..8e80ac6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,11 +1,11 @@ cmake_minimum_required(VERSION 2.8) set(TARNAME "libufodecode") -set(LIBUFODECODE_API_VERSION "0.1.0") -set(LIBUFODECODE_ABI_VERSION "0.1.0") +set(LIBUFODECODE_API_VERSION "0.2.0") +set(LIBUFODECODE_ABI_VERSION "0.2.0") set(LIBUFODECODE_ABI_MAJOR_VERSION "0") -set(PACKAGE_VERSION "0.1.0") +set(PACKAGE_VERSION "0.2.0") set(PACKAGE_NAME "${TARNAME}") set(PACKAGE_TARNAME "${TARNAME}") set(PACKAGE_STRING "${PACKAGE_NAME} ${PACKAGE_VERSION}") @@ -0,0 +1,26 @@ +Changes in ufodecode 0.2.0 +========================== + +Name change +----------- + +In accordance to the rest of the software, the type names changed from +`ufo_decoder_t` to `UfoDecoder`. Moreover there is no typedef for pointers to +`UfoDecoder` structures. + + +API breakage +------------ + +To simplify debugging, all status data is passed from the decoded frame to the +caller of `ufo_decoder_decode_frame()` and `ufo_decoder_get_next_frame()` by +means of the new `UfoDecoderMeta` structure as defined in `ufodecode.h`. + + +Minor changes +------------- + +- The decoder supports version 4 and 5 of the UFO camera frame format. +- `ipedec` now has a proper command line interface. +- `ipedec` prints the frame meta data when using the verbose command line switch + (`-v` or `--verbose`). diff --git a/src/ufodecode-private.h b/src/ufodecode-private.h index 4d0eb9b..c948ae8 100644 --- a/src/ufodecode-private.h +++ b/src/ufodecode-private.h @@ -3,13 +3,12 @@ #include <stdbool.h> -struct ufo_decoder_t { +struct _UfoDecoder { int32_t height; uint32_t width; uint32_t *raw; size_t num_bytes; uint32_t current_pos; - uint32_t old_time_stamp; }; diff --git a/src/ufodecode.c b/src/ufodecode.c index efb7970..dd32695 100644 --- a/src/ufodecode.c +++ b/src/ufodecode.c @@ -69,20 +69,19 @@ typedef struct { * \return A new decoder instance that can be used to iterate over the frames * using ufo_decoder_get_next_frame. */ -ufo_decoder +UfoDecoder * ufo_decoder_new (int32_t height, uint32_t width, uint32_t *raw, size_t num_bytes) { if (width % IPECAMERA_PIXELS_PER_CHANNEL) return NULL; - ufo_decoder decoder = malloc(sizeof(struct ufo_decoder_t)); + UfoDecoder *decoder = malloc(sizeof(UfoDecoder)); if (decoder == NULL) return NULL; decoder->width = width; decoder->height = height; - decoder->old_time_stamp = 0; ufo_decoder_set_raw_data(decoder, raw, num_bytes); return decoder; } @@ -90,10 +89,10 @@ ufo_decoder_new (int32_t height, uint32_t width, uint32_t *raw, size_t num_bytes /** * \brief Release decoder instance * - * \param decoder An ufo_decoder instance + * \param decoder An UfoDecoder instance */ void -ufo_decoder_free(ufo_decoder decoder) +ufo_decoder_free(UfoDecoder *decoder) { free(decoder); } @@ -101,12 +100,12 @@ ufo_decoder_free(ufo_decoder decoder) /** * \brief Set raw data stream * - * \param decoder An ufo_decoder instance + * \param decoder An UfoDecoder instance * \param raw Raw data stream * \param num_bytes Size of data stream buffer in bytes */ void -ufo_decoder_set_raw_data(ufo_decoder decoder, uint32_t *raw, size_t num_bytes) +ufo_decoder_set_raw_data(UfoDecoder *decoder, uint32_t *raw, size_t num_bytes) { decoder->raw = raw; decoder->num_bytes = num_bytes; @@ -114,9 +113,8 @@ ufo_decoder_set_raw_data(ufo_decoder decoder, uint32_t *raw, size_t num_bytes) } static int -ufo_decode_frame_channels_v0(ufo_decoder decoder, +ufo_decode_frame_channels_v0(UfoDecoder *decoder, uint16_t *pixel_buffer, - uint16_t *cmask, uint32_t *raw, size_t num_words, size_t *offset) @@ -159,9 +157,6 @@ ufo_decode_frame_channels_v0(ufo_decoder decoder, CHECK_FLAG("row number, only %i rows requested", row < num_rows, row, num_rows); CHECK_FLAG("pixel size, only 10 bits are supported", bpp == 10, bpp); CHECK_FLAG("channel, limited by %zu output channels", channel < cpl, channel, cpl); - CHECK_FLAG("channel (line %i), duplicate entry", - (!cmask) || (cmask[row] & (1<<channel_order[channel])) == 0, - channel_order[channel], row); #endif if ((row > num_rows) || (channel > cpl) || (pixels > IPECAMERA_PIXELS_PER_CHANNEL)) @@ -170,9 +165,6 @@ ufo_decode_frame_channels_v0(ufo_decoder decoder, channel = channel_order[channel]; int base = row * IPECAMERA_WIDTH + channel * IPECAMERA_PIXELS_PER_CHANNEL; - if (cmask) - cmask[row] |= (1 << channel); - /* "Correct" missing pixel */ if ((row < 2) && (pixels == (IPECAMERA_PIXELS_PER_CHANNEL - 1))) { pixel_buffer[base] = 0; @@ -259,9 +251,8 @@ ufo_decode_frame_channels_v0(ufo_decoder decoder, } static int -ufo_decode_frame_channels_v4(ufo_decoder decoder, +ufo_decode_frame_channels_v4(UfoDecoder *decoder, uint16_t *pixel_buffer, - uint16_t *cmask, uint32_t *raw, size_t num_words, size_t num_rows, @@ -307,9 +298,6 @@ ufo_decode_frame_channels_v4(ufo_decoder decoder, CHECK_FLAG("pixel size, only 10 bits are supported", bpp == 10, bpp); CHECK_FLAG("channel, limited by %zu output channels", channel < channels_per_row, channel, channels_per_row); - CHECK_FLAG("channel (line %i), duplicate entry", - (!cmask) || (cmask[row] & (1 << channel_order[channel])) == 0, - channel_order[channel], row); #endif if ((channel > channels_per_row) || (pixels > IPECAMERA_PIXELS_PER_CHANNEL)) @@ -318,9 +306,6 @@ ufo_decode_frame_channels_v4(ufo_decoder decoder, channel = channel_order[channel]; int base = row * IPECAMERA_WIDTH + channel * IPECAMERA_PIXELS_PER_CHANNEL; - if (cmask) - cmask[row] |= (1 << channel); - /* "Correct" missing pixel */ if ((row < 2) && (pixels == (IPECAMERA_PIXELS_PER_CHANNEL - 1))) { pixel_buffer[base] = 0; @@ -407,9 +392,8 @@ ufo_decode_frame_channels_v4(ufo_decoder decoder, } static int -ufo_decode_frame_channels_v5(ufo_decoder decoder, +ufo_decode_frame_channels_v5(UfoDecoder *decoder, uint16_t *pixel_buffer, - uint16_t *cmask, uint32_t *raw, size_t num_words, size_t num_rows, @@ -549,25 +533,21 @@ void ufo_deinterlace_weave(const uint16_t *in1, const uint16_t *in2, uint16_t *o * * This function tries to decode the supplied data * - * \param decoder An ufo_decoder instance + * \param decoder An UfoDecoder instance * \param raw Raw data stream * \param num_bytes Size of data stream buffer in bytes * \param pixels If pointer with NULL content is passed, a new buffer is * allocated otherwise, this user-supplied buffer is used. * \param frame_number Frame number as reported in the header * \param time_stamp Time stamp of the frame as reported in the header - * \paran cmask Change-mask * * \return number of decoded bytes or 0 in case of error */ -size_t ufo_decoder_decode_frame(ufo_decoder decoder, - uint32_t *raw, - size_t num_bytes, - uint16_t *pixels, - uint32_t *num_rows, - uint32_t *frame_number, - uint32_t *time_stamp, - uint16_t *cmask) +size_t ufo_decoder_decode_frame(UfoDecoder *decoder, + uint32_t *raw, + size_t num_bytes, + uint16_t *pixels, + UfoDecoderMeta *meta) { int err = 0; size_t pos = 0; @@ -591,19 +571,22 @@ size_t ufo_decoder_decode_frame(ufo_decoder decoder, case 0: CHECK_VALUE(raw[pos++], 0x56666666); CHECK_VALUE(raw[pos] >> 28, 0x5); - *frame_number = raw[pos++] & 0xFFFFFFF; + meta->frame_number = raw[pos++] & 0xFFFFFFF; CHECK_VALUE(raw[pos] >> 28, 0x5); - *time_stamp = raw[pos++] & 0xFFFFFFF; + meta->time_stamp = raw[pos++] & 0xFFFFFFF; break; case 4: case 5: CHECK_VALUE(raw[pos] >> 28, 0x5); - rows_per_frame = raw[pos] & 0x7FF; + meta->cmosis_start_address = (raw[pos] >> 21) & 0x1FF; + meta->n_skipped_rows = (raw[pos] >> 15) & 0x3F; + meta->n_rows = rows_per_frame = raw[pos] & 0x7FF; pos++; - *frame_number = raw[pos++] & 0x1FFFFFF; + + meta->frame_number = raw[pos++] & 0x1FFFFFF; CHECK_VALUE(raw[pos] >> 24, 0x50); - *time_stamp = raw[pos++] & 0xFFFFFF; + meta->time_stamp = raw[pos++] & 0xFFFFFF; break; default: @@ -616,13 +599,13 @@ size_t ufo_decoder_decode_frame(ufo_decoder decoder, #else switch (version) { case 0: - *frame_number = raw[pos + 6] & 0xFFFFFFF; - *time_stamp = raw[pos + 7] & 0xFFFFFFF; + meta->frame_number = raw[pos + 6] & 0xFFFFFFF; + meta->time_stamp = raw[pos + 7] & 0xFFFFFFF; break; case 4: case 5: - *frame_number = raw[pos + 6] & 0x1FFFFFF; - *time_stamp = raw[pos + 7] & 0xFFFFFF; + meta->frame_number = raw[pos + 6] & 0x1FFFFFF; + meta->time_stamp = raw[pos + 7] & 0xFFFFFF; break; default: fprintf(stderr, "Unsupported data format detected\n"); @@ -632,17 +615,15 @@ size_t ufo_decoder_decode_frame(ufo_decoder decoder, pos += 8; #endif - *num_rows = rows_per_frame; - switch (version) { case 0: - err = ufo_decode_frame_channels_v0(decoder, pixels, cmask, raw + pos, num_words - pos - 8, &advance); + err = ufo_decode_frame_channels_v0(decoder, pixels, raw + pos, num_words - pos - 8, &advance); break; case 4: - err = ufo_decode_frame_channels_v4(decoder, pixels, cmask, raw + pos, num_words - pos - 8, rows_per_frame, &advance); + err = ufo_decode_frame_channels_v4(decoder, pixels, raw + pos, num_words - pos - 8, rows_per_frame, &advance); break; case 5: - err = ufo_decode_frame_channels_v5(decoder, pixels, cmask, raw + pos, num_words - pos - 8, rows_per_frame, &advance); + err = ufo_decode_frame_channels_v5(decoder, pixels, raw + pos, num_words - pos - 8, rows_per_frame, &advance); break; default: break; @@ -655,10 +636,11 @@ size_t ufo_decoder_decode_frame(ufo_decoder decoder, #ifdef CHECKS CHECK_VALUE(raw[pos++], 0x0AAAAAAA); + + meta->status1.bits = raw[pos++]; + meta->status2.bits = raw[pos++]; + meta->status3.bits = raw[pos++]; pos++; - pos++; /* 0x840dffff expected */ - pos++; /* 0x0f001001 expected */ - pos++; /* 0x28000111 explains problems if status2 is wrong */ pos++; CHECK_VALUE(raw[pos++], 0x00000000); CHECK_VALUE(raw[pos++], 0x01111111); @@ -678,24 +660,20 @@ size_t ufo_decoder_decode_frame(ufo_decoder decoder, * This function tries to decode the next frame in the currently set raw data * stream. * - * \param decoder An ufo_decoder instance + * \param decoder An UfoDecoder instance * \param pixels If pointer with NULL content is passed, a new buffer is * allocated otherwise, this user-supplied buffer is used. * \param num_rows Number of actual decoded rows * \param frame_number Frame number as reported in the header * \param time_stamp Time stamp of the frame as reported in the header - * \paran cmask Change-mask * * \return 0 in case of no error, EIO if end of stream was reached, ENOMEM if * NULL was passed but no memory could be allocated, EILSEQ if data stream is * corrupt and EFAULT if pixels is a NULL-pointer. */ -int ufo_decoder_get_next_frame(ufo_decoder decoder, - uint16_t **pixels, - uint32_t *num_rows, - uint32_t *frame_number, - uint32_t *time_stamp, - uint16_t *cmask) +int ufo_decoder_get_next_frame(UfoDecoder *decoder, + uint16_t **pixels, + UfoDecoderMeta *meta) { uint32_t *raw = decoder->raw; size_t pos = decoder->current_pos; @@ -720,8 +698,7 @@ int ufo_decoder_get_next_frame(ufo_decoder decoder, while ((pos < num_words) && (raw[pos] != 0x51111111)) pos++; - advance = ufo_decoder_decode_frame(decoder, raw + pos, decoder->num_bytes - - pos, *pixels, num_rows, frame_number, time_stamp, cmask); + advance = ufo_decoder_decode_frame(decoder, raw + pos, decoder->num_bytes - pos, *pixels, meta); /* * On error, advance is 0 but we have to advance at least a bit to net get diff --git a/src/ufodecode.h b/src/ufodecode.h index bce17ec..38ea85a 100644 --- a/src/ufodecode.h +++ b/src/ufodecode.h @@ -3,34 +3,82 @@ #include <inttypes.h> -typedef struct ufo_decoder_t *ufo_decoder; +typedef struct _UfoDecoder UfoDecoder; + +typedef struct { + unsigned dummy1:2; + unsigned fsm_master_readout:4; + unsigned dummy2:4; + unsigned fsm_daq:4; + unsigned pixel_full:1; + unsigned control_lock:1; + unsigned data_lock:16; +} UfoDecoderStatus1; + +typedef struct { + unsigned end_of_frames:1; + unsigned busy_or:1; + unsigned busy_ddr:1; + unsigned busy_interl:1; + unsigned error_status:4; /* What the heck? */ + unsigned data_fifo_read_count:10; + unsigned data_fifo_full:1; + unsigned data_fifo_empty:1; + unsigned dummy:2; + unsigned ddr_fifo_write_count:8; + unsigned ddr_fifo_full:1; + unsigned ddr_fifo_empty:1; +} UfoDecoderStatus2; + +typedef struct { + unsigned dummy:2; + unsigned row_counter:10; + unsigned pixel_counter:8; + unsigned ddr_read:4; + unsigned ddr_write:4; + unsigned ddr_arbiter:4; +} UfoDecoderStatus3; + +typedef struct { + uint32_t frame_number; + uint32_t time_stamp; + uint32_t n_rows; + uint8_t n_skipped_rows; + uint16_t cmosis_start_address; + union { + uint32_t bits; + UfoDecoderStatus1 desc; + } status1; + union { + uint32_t bits; + UfoDecoderStatus2 desc; + } status2; + union { + uint32_t bits; + UfoDecoderStatus3 desc; + } status3; +} UfoDecoderMeta; #ifdef __cplusplus extern "C" { #endif -ufo_decoder ufo_decoder_new (int32_t height, +UfoDecoder *ufo_decoder_new (int32_t height, uint32_t width, uint32_t *raw, size_t num_bytes); -void ufo_decoder_free (ufo_decoder decoder); -size_t ufo_decoder_decode_frame (ufo_decoder decoder, +void ufo_decoder_free (UfoDecoder *decoder); +size_t ufo_decoder_decode_frame (UfoDecoder *decoder, uint32_t *raw, size_t num_bytes, uint16_t *pixels, - uint32_t *num_rows, - uint32_t *frame_number, - uint32_t *time_stamp, - uint16_t *cmask); -void ufo_decoder_set_raw_data (ufo_decoder decoder, + UfoDecoderMeta *meta); +void ufo_decoder_set_raw_data (UfoDecoder *decoder, uint32_t *raw, size_t num_bytes); -int ufo_decoder_get_next_frame (ufo_decoder decoder, +int ufo_decoder_get_next_frame (UfoDecoder *decoder, uint16_t **pixels, - uint32_t *num_rows, - uint32_t *frame_number, - uint32_t *time_stamp, - uint16_t *cmask); + UfoDecoderMeta *meta_data); void ufo_deinterlace_interpolate (const uint16_t *frame_in, uint16_t *frame_out, int width, diff --git a/test/ipedec.c b/test/ipedec.c index d357ca3..8059276 100644 --- a/test/ipedec.c +++ b/test/ipedec.c @@ -8,8 +8,8 @@ #include <getopt.h> #include <ufodecode.h> - -static int read_raw_file(const char *filename, char **buffer, size_t *length) +static int +read_raw_file(const char *filename, char **buffer, size_t *length) { FILE *fp = fopen(filename, "rb"); if (fp == NULL) @@ -35,7 +35,8 @@ static int read_raw_file(const char *filename, char **buffer, size_t *length) return 0; } -static void usage(void) +static void +usage(void) { printf("usage: ipedec [--num-rows=ROWS] [--clear-frame] FILE [FILE ...]\n\ Options:\n\ @@ -45,74 +46,150 @@ Options:\n\ -c, --clear-frame Clear the frame for each iteration\n"); } -static void process_file(const char *filename, int rows, int clear_frame, int verbose) +static void +print_meta_data (UfoDecoderMeta *meta) +{ + printf(" frame_number = %i\n", meta->frame_number); + printf(" time_stamp = %i\n", meta->time_stamp); + printf(" n_rows = %i\n", meta->n_rows); + printf(" n_skipped_rows = %i\n", meta->n_skipped_rows); + + printf(" status1\n"); + printf(" fsm_master_readout = %i\n", meta->status1.desc.fsm_master_readout); + printf(" fsm_daq = %i\n", meta->status1.desc.fsm_daq); + printf(" pixel_full = %i\n", meta->status1.desc.pixel_full); + printf(" control_lock = %i\n", meta->status1.desc.control_lock); + printf(" data_lock = %i\n", meta->status1.desc.data_lock); + + printf(" status2\n"); + printf(" end_of_frames = %i\n", meta->status2.desc.end_of_frames); + printf(" busy_or = %i\n", meta->status2.desc.busy_or); + printf(" busy_ddr = %i\n", meta->status2.desc.busy_ddr); + printf(" busy_interl = %i\n", meta->status2.desc.busy_interl); + printf(" error_status = %i\n", meta->status2.desc.error_status); + printf(" data_fifo_read_count = %i\n", meta->status2.desc.data_fifo_read_count); + printf(" data_fifo_full = %i\n", meta->status2.desc.data_fifo_full); + printf(" data_fifo_empty = %i\n", meta->status2.desc.data_fifo_empty); + printf(" ddr_fifo_write_count = %i\n", meta->status2.desc.ddr_fifo_write_count); + printf(" ddr_fifo_full = %i\n", meta->status2.desc.ddr_fifo_full); + printf(" ddr_fifo_empty = %i\n", meta->status2.desc.ddr_fifo_empty); + + printf(" status3\n"); + printf(" row_counter = %i\n", meta->status3.desc.row_counter); + printf(" pixel_counter = %i\n", meta->status3.desc.pixel_counter); + printf(" ddr_read = %i\n", meta->status3.desc.ddr_read); + printf(" ddr_write = %i\n", meta->status3.desc.ddr_write); + printf(" ddr_arbiter = %i\n", meta->status3.desc.ddr_arbiter); + printf("\n"); +} + +typedef struct { + struct timeval start; + long seconds; + long useconds; +} Timer; + +static Timer * +timer_new (void) +{ + Timer *t = (Timer *) malloc (sizeof (Timer)); + t->seconds = t->useconds = 0L; + return t; +} + +static void +timer_destroy (Timer *t) +{ + free (t); +} + +static void +timer_start (Timer *t) +{ + gettimeofday(&t->start, NULL); +} + +static void +timer_stop (Timer *t) +{ + struct timeval end; + + gettimeofday(&end, NULL); + t->seconds += end.tv_sec - t->start.tv_sec; + t->useconds += end.tv_usec - t->start.tv_usec; +} + +static void +process_file(const char *filename, int rows, int clear_frame, int verbose) { - char *buffer = NULL; - size_t num_bytes = 0; - int err = 0; - uint16_t *pixels = (uint16_t *) malloc(2048 * 1088 * sizeof(uint16_t)); - uint32_t num_rows, frame_number, time_stamp, old_time_stamp = 0; - int num_frames = 0; - struct timeval start, end; - long seconds = 0L, useconds = 0L; - int error = read_raw_file(filename, &buffer, &num_bytes); + UfoDecoder *decoder; + UfoDecoderMeta meta = {0}; + Timer *timer; + char *buffer; + size_t num_bytes; + int error; + uint16_t *pixels; + uint32_t time_stamp, old_time_stamp; + int n_frames = 0; + FILE *fp; + char output_name[256]; + + error = read_raw_file(filename, &buffer, &num_bytes); if (error) { fprintf(stderr, "Error reading %s: %s\n", filename, strerror(error)); return; } - ufo_decoder decoder = ufo_decoder_new(rows, 2048, (uint32_t *) buffer, num_bytes); + decoder = ufo_decoder_new(rows, 2048, (uint32_t *) buffer, num_bytes); - if (!decoder) { + if (decoder == NULL) { fprintf(stderr, "Failed to initialize decoder\n"); return; } - char output_name[256]; snprintf(output_name, 256, "%s.raw", filename); - FILE *fp = fopen(output_name, "wb"); + fp = fopen(output_name, "wb"); if (!fp) { fprintf(stderr, "Failed to open file for writing\n"); return; } - while (err != EIO) { + timer = timer_new (); + pixels = (uint16_t *) malloc(2048 * 1088 * sizeof(uint16_t)); + n_frames = 0; + + while (error != EIO) { if (clear_frame) memset(pixels, 0, 2048 * 1088 * sizeof(uint16_t)); - gettimeofday(&start, NULL); - err = ufo_decoder_get_next_frame(decoder, &pixels, &num_rows, &frame_number, &time_stamp, NULL); - gettimeofday(&end, NULL); - - if (verbose) { - int time_stamp_diff = 80 * (time_stamp - old_time_stamp); - - if (time_stamp_diff != 0) - printf(" %d\t %d\n", 1000000000 / time_stamp_diff, num_rows); + timer_start (timer); + error = ufo_decoder_get_next_frame(decoder, &pixels, &meta); + timer_stop (timer); - old_time_stamp = time_stamp; - } + if (!error) { + if (verbose) { + printf("Status for frame %i\n", n_frames); + print_meta_data (&meta); + } - if (!err) { - num_frames++; - seconds += end.tv_sec - start.tv_sec; - useconds += end.tv_usec - start.tv_usec; + n_frames++; fwrite(pixels, sizeof(uint16_t), 2048 * 1088, fp); } - else if (err != EIO) - fprintf(stderr, "Failed to decode frame %i\n", num_frames); + else if (error != EIO) + fprintf(stderr, "Failed to decode frame %i\n", n_frames); } fclose(fp); - float mtime = seconds * 1000.0 + useconds / 1000.0; - printf("Decoded %i frames in %.5fms\n", num_frames, mtime); + float mtime = timer->seconds * 1000.0 + timer->useconds / 1000.0; + printf("Decoded %i frames in %.5fms\n", n_frames, mtime); free(pixels); - ufo_decoder_free(decoder); free(buffer); + timer_destroy (timer); + ufo_decoder_free(decoder); } int main(int argc, char const* argv[]) |