static void compareRS(unsigned char data[]) { int i, j; RS *rs; int spec[5]; int dl, el; unsigned char ecc_expected[256], ecc_rscodec[256]; for(i = 1; i <= QRSPEC_VERSION_MAX; i++) { for(j = QR_ECLEVEL_L; j <= QR_ECLEVEL_H; j++) { QRspec_getEccSpec(i, (QRecLevel)j, spec); dl = QRspec_rsDataCodes1(spec); el = QRspec_rsEccCodes1(spec); rs = init_rs(8, 0x11d, 0, 1, el, 255 - dl - el); RSECC_encode(dl, el, data, ecc_rscodec); encode_rs_char(rs, data, ecc_expected); assert_zero(memcmp(ecc_expected, ecc_rscodec, el), "Invalid ECC found: length %d.\n", el); free_rs_char(rs); dl = QRspec_rsDataCodes2(spec); el = QRspec_rsEccCodes2(spec); if(dl != 0) { rs = init_rs(8, 0x11d, 0, 1, el, 255 - dl - el); RSECC_encode(dl, el, data, ecc_rscodec); encode_rs_char(rs, data, ecc_expected); assert_zero(memcmp(ecc_expected, ecc_rscodec, el), "Invalid ECC found: length %d.\n", el); free_rs_char(rs); } } } }
/** * @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; }
// Set dec_msg_len, re-allocating resources as necessary. Effectively, it // divides the input message into several blocks and allows the decoder to // pad each block appropraitely. // // For example : if we are using the 8-bit code, // nroots = 32 // nn = 255 // kk = 223 // Let _dec_msg_len = 1024, then // num_blocks = ceil(1024/223) // = ceil(4.5919) // = 5 // dec_block_len = ceil(1024/num_blocks) // = ceil(204.8) // = 205 // enc_block_len = dec_block_len + nroots // = 237 // res_block_len = mod(num_blocks*dec_block_len,_dec_msg_len) // = mod(5*205,1024) // = mod(1025,1024) // = 1 (cannot evenly divide input sequence) // pad = kk - dec_block_len // = 223 - 205 // = 18 // // Thus, the 1024-byte input message is broken into 5 blocks, the first // four have a length 205, and the last block has a length 204 (which is // externally padded to 205, e.g. res_block_len = 1). This code adds 32 // parity symbols, so each block is extended to 237 bytes. libfec auto- // matically extends the internal data to 255 bytes by padding with 18 // symbols. Therefore, the final output length is 237 * 5 = 1185 symbols. void fec_rs_setlength(fec _q, unsigned int _dec_msg_len) { // return if length has not changed if (_dec_msg_len == _q->num_dec_bytes) return; // reset lengths _q->num_dec_bytes = _dec_msg_len; div_t d; // compute the total number of blocks necessary: ceil(num_dec_bytes / kk) d = div(_q->num_dec_bytes, _q->kk); _q->num_blocks = d.quot + (d.rem==0 ? 0 : 1); // compute the decoded block length: ceil(num_dec_bytes / num_blocks) d = div(_dec_msg_len, _q->num_blocks); _q->dec_block_len = d.quot + (d.rem == 0 ? 0 : 1); // compute the encoded block length: dec_block_len + nroots _q->enc_block_len = _q->dec_block_len + _q->nroots; // compute the residual padding symbols in the last block: // mod(num_blocks*dec_block_len, num_dec_bytes) _q->res_block_len = (_q->num_blocks*_q->dec_block_len) % _q->num_dec_bytes; // compute the internal libfec padding factor: kk - dec_block_len _q->pad = _q->kk - _q->dec_block_len; // compute the final encoded block length: enc_block_len * num_blocks _q->num_enc_bytes = _q->enc_block_len * _q->num_blocks; #if VERBOSE_FEC_RS printf("dec_msg_len : %u\n", _q->num_dec_bytes); printf("num_blocks : %u\n", _q->num_blocks); printf("dec_block_len : %u\n", _q->dec_block_len); printf("enc_block_len : %u\n", _q->enc_block_len); printf("res_block_len : %u\n", _q->res_block_len); printf("pad : %u\n", _q->pad); printf("enc_msg_len : %u\n", _q->num_enc_bytes); #endif // delete old decoder if necessary if (_q->rs != NULL) free_rs_char(_q->rs); // Reed-Solomon specific decoding _q->rs = init_rs_char(_q->symsize, _q->genpoly, _q->fcs, _q->prim, _q->nroots, _q->pad); }
int main(){ void *handle; int errs,terrs; int i; terrs = 0; srandom(time(NULL)); printf("Testing fixed (255,223) RS codec..."); fflush(stdout); errs = exercise_8(10); terrs += errs; if(errs == 0){ printf("OK\n"); } printf("Testing CCSDS standard (255,223) RS codec..."); fflush(stdout); errs = exercise_ccsds(10); terrs += errs; if(errs == 0){ printf("OK\n"); } for(i=0;Tab[i].symsize != 0;i++){ int nn,kk; nn = (1<<Tab[i].symsize) - 1; kk = nn - Tab[i].nroots; printf("Testing (%d,%d) RS codec...",nn,kk); fflush(stdout); if(Tab[i].symsize <= 8){ if((handle = init_rs_char(Tab[i].symsize,Tab[i].genpoly,Tab[i].fcs,Tab[i].prim,Tab[i].nroots)) == NULL){ printf("init_rs_char failed!\n"); continue; } errs = exercise_char(handle,Tab[i].ntrials); } else { if((handle = init_rs_int(Tab[i].symsize,Tab[i].genpoly,Tab[i].fcs,Tab[i].prim,Tab[i].nroots)) == NULL){ printf("init_rs_int failed!\n"); continue; } errs = exercise_int(handle,Tab[i].ntrials); } terrs += errs; if(errs == 0){ printf("OK\n"); } free_rs_char(handle); } if(terrs == 0) printf("All codec tests passed!\n"); exit(0); }
void fec_rs_destroy(fec _q) { // delete internal Reed-Solomon decoder object free_rs_char(_q->rs); // delete internal memory arrays free(_q->tblock); free(_q->errlocs); free(_q->derrlocs); // delete fec object free(_q); }