diff options
| -rw-r--r-- | src/ufodecode.c | 253 | ||||
| -rw-r--r-- | src/ufodecode.h | 3 | ||||
| -rw-r--r-- | test/ipedec.c | 2 | 
3 files changed, 158 insertions, 100 deletions
diff --git a/src/ufodecode.c b/src/ufodecode.c index 43085d7..6f3f299 100644 --- a/src/ufodecode.c +++ b/src/ufodecode.c @@ -17,6 +17,13 @@  #define IPECAMERA_PIXELS_PER_CHANNEL    128     /**< Number of pixels per channel */  #define IPECAMERA_WIDTH (IPECAMERA_NUM_CHANNELS * IPECAMERA_PIXELS_PER_CHANNEL) /**< Total pixel width of row */ +#define IPECAMERA_MODE_16_CHAN_IO	0 +#define IPECAMERA_MODE_4_CHAN_IO	2 + +#define IPECAMERA_MODE_12_BIT_ADC	2 +#define IPECAMERA_MODE_11_BIT_ADC	1 +#define IPECAMERA_MODE_10_BIT_ADC	0 +  typedef struct {      unsigned int pixel_number : 8;      unsigned int row_number : 12; @@ -113,10 +120,10 @@ ufo_decoder_set_raw_data(UfoDecoder *decoder, uint32_t *raw, size_t num_bytes)  }  static int -ufo_decode_frame_channels_v0(UfoDecoder     *decoder,  -                             uint16_t       *pixel_buffer,  -                             uint32_t       *raw,  -                             size_t          num_words,  +ufo_decode_frame_channels_v0(UfoDecoder     *decoder, +                             uint16_t       *pixel_buffer, +                             uint32_t       *raw, +                             size_t          num_words,                               size_t         *offset)  {      static int channel_order[IPECAMERA_NUM_CHANNELS] = { 15, 13, 14, 12, 10, 8, 11, 7, 9, 6, 5, 2, 4, 3, 0, 1 }; @@ -171,7 +178,7 @@ ufo_decode_frame_channels_v0(UfoDecoder     *decoder,              /* base++; */          }  #ifdef CHECKS -        else  +        else              CHECK_FLAG("number of pixels, %i is expected", pixels == IPECAMERA_PIXELS_PER_CHANNEL, pixels, IPECAMERA_PIXELS_PER_CHANNEL);  #endif @@ -218,9 +225,9 @@ ufo_decode_frame_channels_v0(UfoDecoder     *decoder,          for (int i = 1 ; i < bytes; i++) {              data = raw[i];  #ifdef DEBUG -            header = (data >> 30) & 0x03;    +            header = (data >> 30) & 0x03;              CHECK_FLAG("raw data magic", header == 3, header); -            if (err)  +            if (err)                  return err;  #endif              pixel_buffer[base++] = (data >> 20) & 0x3FF; @@ -234,7 +241,7 @@ ufo_decode_frame_channels_v0(UfoDecoder     *decoder,          header = (data >> 30) & 0x03;          CHECK_FLAG("raw data magic", header == 3, header);          CHECK_FLAG("raw footer magic", (data & 0x3FF) == 0x55, (data & 0x3FF)); -        if (err)  +        if (err)              return err;  #endif @@ -252,10 +259,10 @@ ufo_decode_frame_channels_v0(UfoDecoder     *decoder,  static int  ufo_decode_frame_channels_v4(UfoDecoder     *decoder, -                             uint16_t       *pixel_buffer,  -                             uint32_t       *raw,  -                             size_t          num_words,  -                             size_t          num_rows,  +                             uint16_t       *pixel_buffer, +                             uint32_t       *raw, +                             size_t          num_words, +                             size_t          num_rows,                               size_t         *offset)  {      static const int channel_order[IPECAMERA_NUM_CHANNELS] = { 15, 13, 14, 12, 10, 8, 11, 7, 9, 6, 5, 2, 4, 3, 0, 1 }; @@ -355,9 +362,9 @@ ufo_decode_frame_channels_v4(UfoDecoder     *decoder,          for (int i = 1 ; i < bytes; i++) {              data = raw[i];  #ifdef DEBUG -            header = (data >> 30) & 0x03;    +            header = (data >> 30) & 0x03;              CHECK_FLAG("raw data magic", header == 3, header); -            if (err)  +            if (err)                  return err;  #endif              pixel_buffer[base++] = (data >> 20) & 0x3FF; @@ -371,7 +378,7 @@ ufo_decode_frame_channels_v4(UfoDecoder     *decoder,          header = (data >> 30) & 0x03;          CHECK_FLAG("raw data magic", header == 3, header);          CHECK_FLAG("raw footer magic", (data & 0x3FF) == 0x55, (data & 0x3FF)); -        if (err)  +        if (err)              return err;  #endif @@ -388,12 +395,13 @@ ufo_decode_frame_channels_v4(UfoDecoder     *decoder,  }  static int -ufo_decode_frame_channels_v5(UfoDecoder     *decoder,  -                             uint16_t       *pixel_buffer,  -                             uint32_t       *raw,  -                             size_t          num_words,  -                             size_t          num_rows,  -                             size_t         *offset) +ufo_decode_frame_channels_v5(UfoDecoder     *decoder, +                             uint16_t       *pixel_buffer, +                             uint32_t       *raw, +                             size_t          num_words, +                             size_t          num_rows, +                             size_t         *offset, +                             uint8_t         output_mode)  {      payload_header_v5 *header;      size_t base = 0, index = 0; @@ -401,7 +409,7 @@ ufo_decode_frame_channels_v5(UfoDecoder     *decoder,      header = (payload_header_v5 *) &raw[base]; -    if (header->pixel_size == 12) { +    if (output_mode == IPECAMERA_MODE_4_CHAN_IO) {          while (raw[base] != 0xAAAAAAA) {              header = (payload_header_v5 *) &raw[base];              index = header->row_number * IPECAMERA_WIDTH + header->pixel_number; @@ -416,7 +424,7 @@ ufo_decode_frame_channels_v5(UfoDecoder     *decoder,                  pixel_buffer[index + (12+off)*IPECAMERA_PIXELS_PER_CHANNEL] = 0xfff & (raw[base+1] >> 16);              }              else { -                off++;  +                off++;                  if (header->magic == 0xc0)                      off = 0; @@ -425,34 +433,66 @@ ufo_decode_frame_channels_v5(UfoDecoder     *decoder,              base += 6;          }      } -    else if (header->pixel_size == 10) { +    else { /*if (output_mode == IPECAMERA_MODE_16_CHAN_IO)*/          while (raw[base] != 0xAAAAAAA) {              header = (payload_header_v5 *) &raw[base];              index = header->row_number * IPECAMERA_WIDTH + header->pixel_number;              /* Skip header + two zero-filled words */ -            base += 3; - -            pixel_buffer[index + 15*IPECAMERA_PIXELS_PER_CHANNEL] = 0x3ff & (raw[base] >> 22); -            pixel_buffer[index + 13*IPECAMERA_PIXELS_PER_CHANNEL] = 0x3ff & (raw[base] >> 12); -            pixel_buffer[index + 14*IPECAMERA_PIXELS_PER_CHANNEL] = 0x3ff & (raw[base] >> 2); -            pixel_buffer[index + 12*IPECAMERA_PIXELS_PER_CHANNEL] = ((0x3 & raw[base]) << 8) | (0x3ff & (raw[base+1] >> 24)); -            pixel_buffer[index + 10*IPECAMERA_PIXELS_PER_CHANNEL] = 0x3ff & (raw[base+1] >> 14); -            pixel_buffer[index +  8*IPECAMERA_PIXELS_PER_CHANNEL] = 0x3ff & (raw[base+1] >> 4); -            pixel_buffer[index + 11*IPECAMERA_PIXELS_PER_CHANNEL] = ((0xf & raw[base+1]) << 6) | (0x3ff & (raw[base+2] >> 26)); -            pixel_buffer[index +  7*IPECAMERA_PIXELS_PER_CHANNEL] = 0x3ff & (raw[base+2] >> 16); -            pixel_buffer[index +  9*IPECAMERA_PIXELS_PER_CHANNEL] = 0x3ff & (raw[base+2] >> 6); -            pixel_buffer[index +  6*IPECAMERA_PIXELS_PER_CHANNEL] = ((0x3f & raw[base+2]) << 4) | (0x3ff & (raw[base+3] >> 28)); -            pixel_buffer[index +  5*IPECAMERA_PIXELS_PER_CHANNEL] = 0x3ff & (raw[base+3] >> 18); -            pixel_buffer[index +  2*IPECAMERA_PIXELS_PER_CHANNEL] = 0x3ff & (raw[base+3] >> 8); -            pixel_buffer[index +  4*IPECAMERA_PIXELS_PER_CHANNEL] = ((0xff & raw[base+3]) << 2) | (0x3ff & (raw[base+4] >> 30)); -            pixel_buffer[index +  3*IPECAMERA_PIXELS_PER_CHANNEL] = 0x3ff & (raw[base+4] >> 20); -            pixel_buffer[index +  0*IPECAMERA_PIXELS_PER_CHANNEL] = 0x3ff & (raw[base+4] >> 10); -            pixel_buffer[index +  1*IPECAMERA_PIXELS_PER_CHANNEL] = 0x3ff & raw[base+4]; -            base += 5; +            /* +                        base += 3; +                        pixel_buffer[index + 15*IPECAMERA_PIXELS_PER_CHANNEL] = 0x3ff & (raw[base] >> 22); +                        pixel_buffer[index + 13*IPECAMERA_PIXELS_PER_CHANNEL] = 0x3ff & (raw[base] >> 12); +                        pixel_buffer[index + 14*IPECAMERA_PIXELS_PER_CHANNEL] = 0x3ff & (raw[base] >> 2); +                        pixel_buffer[index + 12*IPECAMERA_PIXELS_PER_CHANNEL] = ((0x3 & raw[base]) << 8) | (0x3ff & (raw[base+1] >> 24)); +                        pixel_buffer[index + 10*IPECAMERA_PIXELS_PER_CHANNEL] = 0x3ff & (raw[base+1] >> 14); +                        pixel_buffer[index +  8*IPECAMERA_PIXELS_PER_CHANNEL] = 0x3ff & (raw[base+1] >> 4); +                        pixel_buffer[index + 11*IPECAMERA_PIXELS_PER_CHANNEL] = ((0xf & raw[base+1]) << 6) | (0x3ff & (raw[base+2] >> 26)); +                        pixel_buffer[index +  7*IPECAMERA_PIXELS_PER_CHANNEL] = 0x3ff & (raw[base+2] >> 16); +                        pixel_buffer[index +  9*IPECAMERA_PIXELS_PER_CHANNEL] = 0x3ff & (raw[base+2] >> 6); +                        pixel_buffer[index +  6*IPECAMERA_PIXELS_PER_CHANNEL] = ((0x3f & raw[base+2]) << 4) | (0x3ff & (raw[base+3] >> 28)); +                        pixel_buffer[index +  5*IPECAMERA_PIXELS_PER_CHANNEL] = 0x3ff & (raw[base+3] >> 18); +                        pixel_buffer[index +  2*IPECAMERA_PIXELS_PER_CHANNEL] = 0x3ff & (raw[base+3] >> 8); +                        pixel_buffer[index +  4*IPECAMERA_PIXELS_PER_CHANNEL] = ((0xff & raw[base+3]) << 2) | (0x3ff & (raw[base+4] >> 30)); +                        pixel_buffer[index +  3*IPECAMERA_PIXELS_PER_CHANNEL] = 0x3ff & (raw[base+4] >> 20); +                        pixel_buffer[index +  0*IPECAMERA_PIXELS_PER_CHANNEL] = 0x3ff & (raw[base+4] >> 10); +                        pixel_buffer[index +  1*IPECAMERA_PIXELS_PER_CHANNEL] = 0x3ff & raw[base+4]; +                        base += 5; +            */ + +            base += 2; + +            if (header->magic != 0xc0) { +                pixel_buffer[index + 15*IPECAMERA_PIXELS_PER_CHANNEL] = 0x3ff & (raw[base] >> 20); +                pixel_buffer[index + 13*IPECAMERA_PIXELS_PER_CHANNEL] = 0x3ff & (raw[base] >> 8); +                pixel_buffer[index + 14*IPECAMERA_PIXELS_PER_CHANNEL] = (0xff & raw[base]) << 4 | (raw[base+1] >> 28); +                pixel_buffer[index + 12*IPECAMERA_PIXELS_PER_CHANNEL] = 0x3ff & (raw[base+1] >> 16); +                pixel_buffer[index + 10*IPECAMERA_PIXELS_PER_CHANNEL] = 0x3ff & (raw[base+1] >> 4); +                pixel_buffer[index +  8*IPECAMERA_PIXELS_PER_CHANNEL] = ((0xf & raw[base+1]) << 8) | (raw[base+2] >> 24); +                pixel_buffer[index + 11*IPECAMERA_PIXELS_PER_CHANNEL] = 0x3ff & (raw[base+2] >> 12); +                pixel_buffer[index +  7*IPECAMERA_PIXELS_PER_CHANNEL] = 0x3ff & raw[base+2]; +                pixel_buffer[index +  9*IPECAMERA_PIXELS_PER_CHANNEL] = 0x3ff & (raw[base+3] >> 20); +                pixel_buffer[index +  6*IPECAMERA_PIXELS_PER_CHANNEL] = 0x3ff & (raw[base+3] >> 8); +                pixel_buffer[index +  5*IPECAMERA_PIXELS_PER_CHANNEL] = (0xff & raw[base+3]) << 4 | (raw[base+4] >> 28); +                pixel_buffer[index +  2*IPECAMERA_PIXELS_PER_CHANNEL] = 0x3ff & (raw[base+4] >> 16); +                pixel_buffer[index +  4*IPECAMERA_PIXELS_PER_CHANNEL] = 0x3ff & (raw[base+4] >> 4); +                pixel_buffer[index +  3*IPECAMERA_PIXELS_PER_CHANNEL] = ((0xf & raw[base+4]) << 8) | (raw[base+5] >> 24); +                pixel_buffer[index +  0*IPECAMERA_PIXELS_PER_CHANNEL] = 0x3ff & (raw[base+5] >> 12); +                pixel_buffer[index +  1*IPECAMERA_PIXELS_PER_CHANNEL] = 0x3ff & raw[base+5]; +            } +            else { +                off++; + +                if (header->magic == 0xc0) +                    off = 0; +            } + +            base += 6; +          }      } +      *offset = base;      return 0;  } @@ -473,7 +513,7 @@ void ufo_deinterlace_interpolate(const uint16_t *in, uint16_t *out, int width, i          memcpy(out, in + row*width, row_size_bytes);          out += width; -        /* Interpolate between source row and row+1 */  +        /* Interpolate between source row and row+1 */          for (int x = 0; x < width; x++)              out[x] = (int) (0.5 * in[row*width + x] + 0.5 * in[(row+1)*width + x]); @@ -497,9 +537,9 @@ void ufo_deinterlace_weave(const uint16_t *in1, const uint16_t *in2, uint16_t *o  {      const size_t row_size_bytes = width * sizeof(uint16_t);      for (int row = 0; row < height; row++) { -        memcpy(out, in1 + row*width, row_size_bytes);  +        memcpy(out, in1 + row*width, row_size_bytes);          out += width; -        memcpy(out, in2 + row*width, row_size_bytes);  +        memcpy(out, in2 + row*width, row_size_bytes);          out += width;      }  } @@ -520,9 +560,9 @@ void ufo_deinterlace_weave(const uint16_t *in1, const uint16_t *in2, uint16_t *o   * \return number of decoded bytes or 0 in case of error   */  size_t ufo_decoder_decode_frame(UfoDecoder      *decoder, -                                uint32_t        *raw,  -                                size_t           num_bytes,  -                                uint16_t        *pixels,  +                                uint32_t        *raw, +                                size_t           num_bytes, +                                uint16_t        *pixels,                                  UfoDecoderMeta  *meta)  {      int err = 0; @@ -544,65 +584,78 @@ size_t ufo_decoder_decode_frame(UfoDecoder      *decoder,      CHECK_VALUE(raw[pos++], 0x55555555);      switch (version) { -        case 0: -            CHECK_VALUE(raw[pos++], 0x56666666); -            CHECK_VALUE(raw[pos] >> 28, 0x5); -            meta->frame_number = raw[pos++] & 0xFFFFFFF; -            CHECK_VALUE(raw[pos] >> 28, 0x5); -            meta->time_stamp = raw[pos++] & 0xFFFFFFF; -            break; - -        case 4: -        case 5: -            CHECK_VALUE(raw[pos] >> 28, 0x5); -            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++; +    case 0: +        CHECK_VALUE(raw[pos++], 0x56666666); +        CHECK_VALUE(raw[pos] >> 28, 0x5); +        meta->frame_number = raw[pos++] & 0xFFFFFFF; +        CHECK_VALUE(raw[pos] >> 28, 0x5); +        meta->time_stamp = raw[pos++] & 0xFFFFFFF; +        break; + +    case 4: +    case 5: +        CHECK_VALUE(raw[pos] >> 28, 0x5); +        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++; -            meta->frame_number = raw[pos++] & 0x1FFFFFF; -            CHECK_VALUE(raw[pos] >> 24, 0x50); -            meta->time_stamp = raw[pos++] & 0xFFFFFF; -            break; +        meta->frame_number = raw[pos++] & 0x1FFFFFF; +        CHECK_VALUE(raw[pos] >> 28, 0x5); +        meta->time_stamp = raw[pos] & 0xFFFFFF; +        meta->output_mode = (raw[pos] >> 24) & 0x3; +        meta->adc_resolution = (raw[pos] >> 26) & 0x3; +        pos++; + +        if ((meta->output_mode != IPECAMERA_MODE_4_CHAN_IO)&&(meta->output_mode != IPECAMERA_MODE_16_CHAN_IO)) { +#ifdef DEBUG +            fprintf(stderr, "Output mode 0x%lx is not supported\n", meta->output_mode); +#endif +            return EILSEQ; +        } +        break; -        default: -            fprintf(stderr, "Unsupported data format detected\n"); -            return 0; +    default: +        fprintf(stderr, "Unsupported data format detected\n"); +        return 0;      } -    if (err)  +    if (err)          return 0;  #else      switch (version) { -        case 0: -            meta->frame_number = raw[pos + 6] & 0xFFFFFFF; -            meta->time_stamp = raw[pos + 7] & 0xFFFFFFF; -            break; -        case 4: -        case 5: -            meta->frame_number = raw[pos + 6] & 0x1FFFFFF; -            meta->time_stamp = raw[pos + 7] & 0xFFFFFF; -            break; -        default: -            fprintf(stderr, "Unsupported data format detected\n"); -            return 0; +    case 0: +        meta->frame_number = raw[pos + 6] & 0xFFFFFFF; +        meta->time_stamp = raw[pos + 7] & 0xFFFFFFF; +        break; +    case 4: +    case 5: +        meta->frame_number = raw[pos + 6] & 0x1FFFFFF; +        meta->time_stamp = raw[pos + 7] & 0xFFFFFF; +        meta->output_mode = (raw[pos + 7] >> 24) & 0x3; +        meta->adc_resolution = (raw[pos + 7] >> 26) & 0x3; + +        break; +    default: +        fprintf(stderr, "Unsupported data format detected\n"); +        return 0;      }      pos += 8;  #endif      switch (version) { -        case 0: -            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, raw + pos, num_words - pos - 8, rows_per_frame, &advance); -            break; -        case 5: -            err = ufo_decode_frame_channels_v5(decoder, pixels, raw + pos, num_words - pos - 8, rows_per_frame, &advance); -            break; -        default: -            break; +    case 0: +        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, raw + pos, num_words - pos - 8, rows_per_frame, &advance); +        break; +    case 5: +        err = ufo_decode_frame_channels_v5(decoder, pixels, raw + pos, num_words - pos - 8, rows_per_frame, &advance, meta->output_mode); +        break; +    default: +        break;      }      if (err) @@ -621,7 +674,7 @@ size_t ufo_decoder_decode_frame(UfoDecoder      *decoder,      CHECK_VALUE(raw[pos++], 0x00000000);      CHECK_VALUE(raw[pos++], 0x01111111); -    if (err)  +    if (err)          return 0;  #else      pos += 8; @@ -634,7 +687,7 @@ size_t ufo_decoder_decode_frame(UfoDecoder      *decoder,   * \brief Iterate and decode next frame   *   * This function tries to decode the next frame in the currently set raw data - * stream.  + * stream.   *   * \param decoder An UfoDecoder instance   * \param pixels If pointer with NULL content is passed, a new buffer is @@ -647,8 +700,8 @@ size_t ufo_decoder_decode_frame(UfoDecoder      *decoder,   * 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(UfoDecoder     *decoder,  -                               uint16_t      **pixels,  +int ufo_decoder_get_next_frame(UfoDecoder     *decoder, +                               uint16_t      **pixels,                                 UfoDecoderMeta *meta)  {      uint32_t *raw = decoder->raw; @@ -660,7 +713,7 @@ int ufo_decoder_get_next_frame(UfoDecoder     *decoder,          return 0;      if (pos >= num_words) -        return EIO;  +        return EIO;      if (num_words < 16)          return EILSEQ; diff --git a/src/ufodecode.h b/src/ufodecode.h index 7c2f098..228bec3 100644 --- a/src/ufodecode.h +++ b/src/ufodecode.h @@ -45,6 +45,9 @@ typedef struct {      uint32_t        n_rows;      uint8_t         n_skipped_rows;      uint16_t        cmosis_start_address; +    uint8_t         output_mode; +    uint8_t         adc_resolution; +      union {          uint32_t            bits;          UfoDecoderStatus1   desc; diff --git a/test/ipedec.c b/test/ipedec.c index 56236ce..c9eceb3 100644 --- a/test/ipedec.c +++ b/test/ipedec.c @@ -51,6 +51,8 @@ print_meta_data (UfoDecoderMeta *meta)  {      printf("  frame_number    = %i\n", meta->frame_number);      printf("  time_stamp      = %i\n", meta->time_stamp); +    printf("  output_mode     = %i\n", meta->output_mode); +    printf("  adc_resolution  = %i\n", meta->adc_resolution);      printf("  n_rows          = %i\n", meta->n_rows);      printf("  n_skipped_rows  = %i\n", meta->n_skipped_rows);  | 
