static void decode_rs(struct image_proc_ctx *ctx) { struct image *fcx = ctx->ctx; int j, rv; uint8_t data[fcx->rs_n + fcx->roots]; uint64_t i; assert(sizeof(data) == FEC_RSM); for (i = ctx->start; i < ctx->end; i += fcx->rs_n) { for (j = 0; j < fcx->rs_n; ++j) { data[j] = image_get_interleaved_byte(i + j, fcx); } memcpy(&data[fcx->rs_n], &fcx->fec[ctx->fec_pos], fcx->roots); rv = decode_rs_char(ctx->rs, data, NULL, 0); if (rv < 0) { FATAL("failed to recover [%" PRIu64 ", %" PRIu64 ")\n", i, i + fcx->rs_n); } else if (rv > 0) { /* copy corrected data to output */ for (j = 0; j < fcx->rs_n; ++j) { image_set_interleaved_byte(i + j, fcx, data[j]); } ctx->rv += rv; } ctx->fec_pos += fcx->roots; } }
//unsigned int void fec_rs_decode(fec _q, unsigned int _dec_msg_len, unsigned char *_msg_enc, unsigned char *_msg_dec) { // validate input if (_dec_msg_len == 0) { fprintf(stderr,"error: fec_rs_encode(), input lenght must be > 0\n"); exit(1); } // re-allocate resources if necessary fec_rs_setlength(_q, _dec_msg_len); // set erasures, error locations to zero memset(_q->errlocs, 0x00, _q->nn*sizeof(unsigned char)); memset(_q->derrlocs, 0x00, _q->nn*sizeof(unsigned char)); _q->erasures = 0; unsigned int i; unsigned int n0=0; unsigned int n1=0; unsigned int block_size = _q->dec_block_len; //int derrors; // number of decoder errors for (i=0; i<_q->num_blocks; i++) { // the last block is smaller by the residual block length if (i == _q->num_blocks-1) block_size -= _q->res_block_len; // copy sequence memmove(_q->tblock, &_msg_enc[n0], _q->enc_block_len*sizeof(unsigned char)); // decode block //derrors = decode_rs_char(_q->rs, _q->tblock, _q->derrlocs, _q->erasures); // copy result memmove(&_msg_dec[n1], _q->tblock, block_size*sizeof(unsigned char)); // increment counters n0 += _q->enc_block_len; n1 += block_size; } // sanity check assert( n0 == _q->num_enc_bytes ); assert( n1 == _q->num_dec_bytes ); }
/** * @brief XXX * @param code * @param sizeIdx * @param fix * @return DMTX_SUCCESS | DMTX_FAILURE */ static int DecodeCheckErrors(unsigned char *code, int sizeIdx, int fix) { int i, j; int interleavedBlocks; int blockErrorWords; int blockTotalWords; int blockMaxCorrectable; struct rs *rs; int fixedErr, fixedErrSum; unsigned char data[255]; interleavedBlocks = dmtxGetSymbolAttribute(DmtxSymAttribInterleavedBlocks, sizeIdx); blockErrorWords = dmtxGetSymbolAttribute(DmtxSymAttribBlockErrorWords, sizeIdx); blockTotalWords = dmtxGetSymbolAttribute(DmtxSymAttribBlockTotalWords, sizeIdx); blockMaxCorrectable = dmtxGetSymbolAttribute(DmtxSymAttribBlockMaxCorrectable, sizeIdx); rs = init_rs_char(blockErrorWords, 255 - blockTotalWords); if(rs == NULL) return DMTX_FAILURE; fixedErrSum = 0; for(i = 0; i < interleavedBlocks; i++) { for(j = 0; j < blockTotalWords; j++) data[j] = code[j*interleavedBlocks+i]; fixedErr = decode_rs_char(rs, data, NULL, 0, fix); if(fixedErr < 0 || fixedErr > blockMaxCorrectable) { free_rs_char(rs); return DMTX_FAILURE; } fixedErrSum += fixedErr; for(j = 0; j < blockTotalWords; j++) code[j*interleavedBlocks+i] = data[j]; } free_rs_char(rs); if(fix >= 0 && fixedErrSum > fix) return DMTX_FAILURE; return DMTX_SUCCESS; }
int main(){ unsigned char block[255]; int i; void *rs; struct rusage start,finish; double extime; int trials = 10000; for(i=0;i<223;i++) block[i] = 0x01; rs = init_rs_char(8,0x187,112,11,32,0); encode_rs_char(rs,block,&block[223]); getrusage(RUSAGE_SELF,&start); for(i=0;i<trials;i++){ #if 0 block[0] ^= 0xff; /* Introduce an error */ block[2] ^= 0xff; /* Introduce an error */ #endif decode_rs_char(rs,block,NULL,0); } getrusage(RUSAGE_SELF,&finish); extime = finish.ru_utime.tv_sec - start.ru_utime.tv_sec + 1e-6*(finish.ru_utime.tv_usec - start.ru_utime.tv_usec); printf("Execution time for %d Reed-Solomon blocks using general decoder: %.2f sec\n",trials,extime); printf("decoder speed: %g bits/s\n",trials*223*8/extime); encode_rs_8(block,&block[223],0); getrusage(RUSAGE_SELF,&start); for(i=0;i<trials;i++){ #if 0 block[0] ^= 0xff; /* Introduce an error */ block[2] ^= 0xff; /* Introduce an error */ #endif decode_rs_8(block,NULL,0,0); } getrusage(RUSAGE_SELF,&finish); extime = finish.ru_utime.tv_sec - start.ru_utime.tv_sec + 1e-6*(finish.ru_utime.tv_usec - start.ru_utime.tv_usec); printf("Execution time for %d Reed-Solomon blocks using CCSDS decoder: %.2f sec\n",trials,extime); printf("decoder speed: %g bits/s\n",trials*223*8/extime); exit(0); }
void test_char() { int nn = 255; int roots = 8; int kk = nn - roots; int i; int r; int nerr = 0; unsigned char block[nn]; unsigned char blocktmp[nn]; int pad = 215; void *rs; printf("Using RS(%d, %d), it means words of %d 8-bit symbols and %d redundant symbols\n", nn, kk, kk - pad, roots); rs = init_rs_char(8, 0x187, 112, 11, roots, pad); memset(block, 0, nn); for (i = 0; i < kk - pad; ++i) block[i] = 'a' + i % 26; dump_buf("dump-before", block, nn); encode_rs_char(rs, block, &block[kk - pad]); dump_buf("dump-after", block, nn); do { nerr ++; memcpy(blocktmp, block, nn); for (i = 0; i < nerr; ++i) blocktmp[i] = ~blocktmp[i]; if (nerr == 16) dump_buf("dump-decode-16-before", blocktmp, nn); r = decode_rs_char(rs, blocktmp, NULL, 0); if (nerr == 16) dump_buf("dump-decode-16-after", blocktmp, nn); printf("decode with %d bad symbols returns %d\n", nerr, r); } while (r >= 0 && nerr < 18); }
int main(int argc, char *argv[]) { int i, len, l; char *str = NULL, strbuf[2*BFSIZE+1]; FILE *fp = NULL; rs = init_rs_char( 8, 0x11d, 0, 1, R, 0); // fec.c rs_init_RS255(); // bch_ecc.c if (argc < 2) { fp = stdin; str = fgets(strbuf, 2*BFSIZE, fp); } else { str = argv[1]; } while (str) { len = strlen(str)/2; if (len > BFSIZE) return -1; for (i = 0; i < BFSIZE; i++) data[i] = 0; for (i = 0; i < N; i++) codeword1[i] = codeword2[i] = 0; for (i = 0; i < len; i++) { l = sscanf(str+2*i, "%2hhx", data+i); if (l < 1) {/*len = i;*/} } cfg = detect(data, len); if ( cfg.typ == 92 ) { for (i = 0; i < cfg.msglen; i++) codeword1[K-1-i] = data[cfg.msgpos+i]; for (i = 0; i < R; i++) codeword1[N-1-i] = data[cfg.parpos+i]; for (i = 0; i < N; i++) cw1[i] = codeword1[N-1-i]; errors1 = decode_rs_char(rs, codeword1, errpos1, 0); errs1 = rs_decode(cw1, err_pos1, err_val1); if (fp == NULL) { printf("RS%d\n", cfg.typ); printf("codeword\n"); printf("errors: %d\n", errors1); if (errors1 > 0) { printf("pos: "); for (i = 0; i < errors1; i++) printf(" %d", errpos1[i]); printf("\n"); } for (i = 0; i < N; i++) printf("%02X", codeword1[i]); printf("\n"); printf("frame:\n"); } for (i = 0; i < cfg.hdrlen; i++) frame[i] = data[i]; for (i = 0; i < cfg.msglen; i++) frame[cfg.msgpos+i] = codeword1[K-1-i]; for (i = 0; i < R; i++) frame[cfg.parpos+i] = codeword1[N-1-i]; for (i = 0; i < cfg.frmlen; i++) printf("%02x", frame[i]); printf("\n"); for (i = 0; i < N; i++) { if (cw1[i] != codeword1[N-1-i]) { printf("diff[%3d]: cw: %02x codeword: %02x\n", i, cw1[i], codeword1[N-1-i]); } } } else if ( cfg.typ == 41 ) { for (i = 0; i < cfg.msglen; i++) { codeword1[K-1-i] = data[cfg.msgpos+ 2*i]; codeword2[K-1-i] = data[cfg.msgpos+1+2*i]; } for (i = 0; i < R; i++) { codeword1[N-1-i] = data[cfg.parpos+ i]; codeword2[N-1-i] = data[cfg.parpos+R+i]; } for (i = 0; i < N; i++) cw1[i] = codeword1[N-1-i]; for (i = 0; i < N; i++) cw2[i] = codeword2[N-1-i]; errors1 = decode_rs_char(rs, codeword1, errpos1, 0); errors2 = decode_rs_char(rs, codeword2, errpos2, 0); errs1 = rs_decode(cw1, err_pos1, err_val1); errs2 = rs_decode(cw2, err_pos2, err_val2); if (fp == NULL) { printf("RS%d\n", cfg.typ); printf("codeword1\n"); printf("errors: %d\n", errors1); if (errors1 > 0) { printf("pos: "); for (i = 0; i < errors1; i++) printf(" %d", errpos1[i]); printf("\n"); } for (i = 0; i < N; i++) printf("%02X", codeword1[i]); printf("\n"); printf("codeword2\n"); printf("errors: %d\n", errors2); if (errors2 > 0) { printf("pos: "); for (i = 0; i < errors2; i++) printf(" %d", errpos2[i]); printf("\n"); } for (i = 0; i < N; i++) printf("%02X", codeword2[i]); printf("\n"); printf("frame:\n"); } for (i = 0; i < cfg.hdrlen; i++) frame[i] = data[i]; for (i = 0; i < R; i++) { frame[cfg.parpos+ i] = codeword1[N-1-i]; frame[cfg.parpos+R+i] = codeword2[N-1-i]; } for (i = 0; i < cfg.msglen; i++) { frame[cfg.msgpos+ 2*i] = codeword1[K-1-i]; frame[cfg.msgpos+1+2*i] = codeword2[K-1-i]; } for (i = 0; i < cfg.frmlen; i++) printf("%02x", frame[i]); printf("\n"); for (i = 0; i < N; i++) { if (cw1[i] != codeword1[N-1-i]) { printf("diff[%3d]: cw1: %02x codeword1: %02x\n", i, cw1[i], codeword1[N-1-i]); } } for (i = 0; i < N; i++) { if (cw2[i] != codeword2[N-1-i]) { printf("diff[%3d]: cw2: %02x codeword2: %02x\n", i, cw2[i], codeword2[N-1-i]); } } } if (fp) str = fgets(strbuf, 2*BFSIZE, fp); else str = NULL; } return 0; }
/* reads and decodes a single block starting from `offset', returns the number of bytes corrected in `errors' */ static int __ecc_read(fec_handle *f, void *rs, uint8_t *dest, uint64_t offset, bool use_erasures, uint8_t *ecc_data, size_t *errors) { check(offset % FEC_BLOCKSIZE == 0); ecc_info *e = &f->ecc; /* reverse interleaving: calculate the RS block that includes the requested offset */ uint64_t rsb = offset - (offset / (e->rounds * FEC_BLOCKSIZE)) * e->rounds * FEC_BLOCKSIZE; int data_index = -1; int erasures[e->rsn]; int neras = 0; /* verity is required to check for erasures */ check(!use_erasures || f->verity.hash); for (int i = 0; i < e->rsn; ++i) { uint64_t interleaved = fec_ecc_interleave(rsb * e->rsn + i, e->rsn, e->rounds); if (interleaved == offset) { data_index = i; } /* copy raw data to reconstruct the RS block */ uint8_t bbuf[FEC_BLOCKSIZE]; if (unlikely(interleaved >= e->start) || is_zero(f, interleaved)) { memset(bbuf, 0, FEC_BLOCKSIZE); } else { if (!raw_pread(f, bbuf, FEC_BLOCKSIZE, interleaved)) { error("failed to read: %s", strerror(errno)); return -1; } if (use_erasures && neras <= e->roots && is_erasure(f, interleaved, bbuf)) { erasures[neras++] = i; } } for (int j = 0; j < FEC_BLOCKSIZE; ++j) { ecc_data[j * FEC_RSM + i] = bbuf[j]; } } check(data_index >= 0); size_t nerrs = 0; uint8_t copy[FEC_RSM]; for (int i = 0; i < FEC_BLOCKSIZE; ++i) { /* copy parity data */ if (!raw_pread(f, &ecc_data[i * FEC_RSM + e->rsn], e->roots, e->start + (i + rsb) * e->roots)) { error("failed to read ecc data: %s", strerror(errno)); return -1; } /* for debugging decoding failures, because decode_rs_char can mangle ecc_data */ if (unlikely(use_erasures)) { memcpy(copy, &ecc_data[i * FEC_RSM], FEC_RSM); } /* decode */ int rc = decode_rs_char(rs, &ecc_data[i * FEC_RSM], erasures, neras); if (unlikely(rc < 0)) { if (use_erasures) { error("RS block %" PRIu64 ": decoding failed (%d erasures)", rsb, neras); dump("raw RS block", rsb, copy, FEC_RSM); } else if (!f->verity.hash) { warn("RS block %" PRIu64 ": decoding failed", rsb); } else { debug("RS block %" PRIu64 ": decoding failed", rsb); } errno = EIO; return -1; } else if (unlikely(rc > 0)) { check(rc <= (use_erasures ? e->roots : e->roots / 2)); nerrs += rc; } dest[i] = ecc_data[i * FEC_RSM + data_index]; } if (nerrs) { warn("RS block %" PRIu64 ": corrected %zu errors", rsb, nerrs); *errors += nerrs; } return FEC_BLOCKSIZE; }