From eda007e71a2d86ed0f404cba1b0c4475a53563a4 Mon Sep 17 00:00:00 2001 From: Ralph Metzler Date: Tue, 31 May 2016 16:46:02 +0200 Subject: [PATCH] more T2 statistics info --- frontends/cxd2843.c | 276 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 274 insertions(+), 2 deletions(-) diff --git a/frontends/cxd2843.c b/frontends/cxd2843.c index d7014e7..a23359c 100644 --- a/frontends/cxd2843.c +++ b/frontends/cxd2843.c @@ -332,7 +332,7 @@ static inline u32 MulDiv32(u32 a, u32 b, u32 c) static int read_tps(struct cxd_state *state, u8 *tps) { if (state->last_status != 0x1f) - return 0; + return -1; freeze_regst(state); readregst_unlocked(state, 0x10, 0x2f, tps, 7); @@ -340,6 +340,63 @@ static int read_tps(struct cxd_state *state, u8 *tps) return 0; } +/* Read DVBT2 OFDM Info */ +/* OFDMInfo[0] [5] OFDM_MIXED */ +/* OFDMInfo[0] [4] OFDM_MISO */ +/* OFDMInfo[0] [2:0] OFDM_FFTSIZE[2:0] */ +/* OFDMInfo[1] [6:4] OFDM_GI[2:0] */ +/* OFDMInfo[1] [2:0] OFDM_PP[2:0] */ +/* OFDMInfo[2] [4] OFDM_BWT_EXT */ +/* OFDMInfo[2] [3:0] OFDM_PAPR[3:0] */ +/* OFDMInfo[3] [3:0] OFDM_NDSYM[11:8] */ +/* OFDMInfo[4] [7:0] OFDM_NDSYM[7:0] */ + +static int read_t2_ofdm_info(struct cxd_state *state, u8 *ofdm) +{ + if (state->last_status != 0x1f) + return -1; + + freeze_regst(state); + readregst_unlocked(state, 0x20, 0x5c, ofdm, 5); + unfreeze_regst(state); + return 0; +} + +/* Read DVBT2 QAM, + Data PLP + 0 [7:0] L1POST_PLP_ID[7:0] + 1 [2:0] L1POST_PLP_TYPE[2:0] + 2 [4:0] L1POST_PLP_PAYLOAD_TYPE[4:0] + 3 [0] L1POST_FF_FLAG + 4 [2:0] L1POST_FIRST_RF_IDX[2:0] + 5 [7:0] L1POST_FIRST_FRAME_IDX[7:0] + 6 [7:0] L1POST_PLP_GROUP_ID[7:0] + 7 [2:0] L1POST_PLP_COD[2:0] + 8 [2:0] L1POST_PLP_MOD[2:0] + 9 [0] L1POST_PLP_ROTATION + 10 [1:0] L1POST_PLP_FEC_TYPE[1:0] + 11 [1:0] L1POST_PLP_NUM_BLOCKS_MAX[9:8] + 12 [7:0] L1POST_PLP_NUM_BLOCKS_MAX[7:0] + 13 [7:0] L1POST_FRAME_INTERVAL[7:0] + 14 [7:0] L1POST_TIME_IL_LENGTH[7:0] + 15 [0] L1POST_TIME_IL_TYPE + 16 [0] L1POST_IN_BAND_FLAG + 17 [7:0] L1POST_RESERVED_1[15:8] + 18 [7:0] L1POST_RESERVED_1[7:0] + 19-37 same for common PLP +*/ + +static int read_t2_tlp_info(struct cxd_state *state, u8 off, u8 count, u8 *tlp) +{ + if (state->last_status != 0x1f) + return -1; + + freeze_regst(state); + readregst_unlocked(state, 0x22, 0x54 + off, tlp, count); + unfreeze_regst(state); + return 0; +} + static void Active_to_Sleep(struct cxd_state *state) { if (state->state <= Sleep) @@ -1316,6 +1373,12 @@ static int read_status(struct dvb_frontend *fe, fe_status_t *status) if (rdata & 0x20) *status |= 0x1f; } + if (*status == 0x1f && state->FirstTimeLock) { + readregst(state, 0x40, 0x19, &rdata, 1); + rdata &= 0x07; + state->BERScaleMax = ( rdata < 2 ) ? 18 : 19; + state->FirstTimeLock = 0; + } break; case ActiveT: readregst(state, 0x10, 0x10, &rdata, 1); @@ -1326,6 +1389,16 @@ static int read_status(struct dvb_frontend *fe, fe_status_t *status) if (rdata & 0x20) *status |= 0x1f; } + if (*status == 0x1f && state->FirstTimeLock) { + u8 tps[7]; + + read_tps(state, tps); + state->BERScaleMax = + (((tps[0] >> 6) & 0x03) < 2 ) ? 17 : 18; + if ((tps[0] & 7) < 2) + state->BERScaleMax--; + state->FirstTimeLock = 0; + } break; case ActiveT2: readregst(state, 0x20, 0x10, &rdata, 1); @@ -1372,6 +1445,12 @@ static int read_status(struct dvb_frontend *fe, fe_status_t *status) if (rdata & 0x01) *status |= 0x18; } + if (*status == 0x1f && state->FirstTimeLock) { + /* readregst(state, 0x40, 0x19, &rdata, 1); */ + /* rdata &= 0x07; */ + /* state->BERScaleMax = ( rdata < 2 ) ? 18 : 19; */ + state->FirstTimeLock = 0; + } break; default: break; @@ -1410,8 +1489,44 @@ static int get_ber_t(struct cxd_state *state, u32 *n, u32 *d) static int get_ber_t2(struct cxd_state *state, u32 *n, u32 *d) { + u8 BERRegs[4]; + u8 Scale; + u8 FECType; + u8 CodeRate; + static const u32 nBCHBitsLookup[2][8] = { + /* R1_2 R3_5 R2_3 R3_4 R4_5 R5_6 R1_3 R2_5 */ + {7200, 9720, 10800, 11880, 12600, 13320, 5400, 6480}, /* 16K FEC */ + {32400, 38880, 43200, 48600, 51840, 54000, 21600, 25920} /* 64k FEC */ + }; + *n = 0; *d = 1; + freeze_regst(state); + readregst(state, 0x24, 0x40, BERRegs, 4); + readregst(state, 0x22, 0x5e, &FECType, 1); + readregst(state, 0x22, 0x5b, &CodeRate, 1); + + FECType &= 0x03; + CodeRate &= 0x07; + unfreeze_regst(state); + if (FECType > 1) + return 0; + + + readregst(state, 0x20, 0x72, &Scale, 1); + Scale &= 0x0F; + if (BERRegs[0] & 0x01) { + state->LastBERNominator = (((u32) BERRegs[1] & 0x3F) << 16) | + (((u32) BERRegs[2]) << 8) | BERRegs[3]; + state->LastBERDenominator = nBCHBitsLookup[FECType][CodeRate] << Scale; + if (state->LastBERNominator < 256 && + Scale < state->BERScaleMax) { + writebitst(state, 0x20, 0x72, Scale + 1, 0x0F); + } else if (state->LastBERNominator > 512 && Scale > 8) + writebitst(state, 0x20, 0x72, Scale - 1, 0x0F); + } + *n = state->LastBERNominator; + *d = state->LastBERDenominator; return 0; } @@ -1508,10 +1623,62 @@ static int read_signal_strength(struct dvb_frontend *fe, u16 *strength) } #if 0 ++NTSTATUS CCXD2843ER::GetT2PLPIds(DD_T2_PLPIDS* pT2_PLPIDS) + { + NTSTATUS status = STATUS_SUCCESS; +- *pReturned = 0; ++ + if( m_DemodState != ActiveT2 ) return STATUS_NOT_IMPLEMENTED; +- if( m_LastLockStatus < TSLock || m_LastLockStatus == Unlock ) return status; ++ if( m_LastLockStatus < TSLock ) return status; + + do + { ++ BYTE tmp; ++ + CHK_ERROR(FreezeRegsT()); + ++ CHK_ERROR(ReadRegT(0x20,0x5C,&tmp)); // OFDM Info ++ ++ if( tmp & 0x20 ) pT2_PLPIDS->Flags |= DD_T2_PLPIDS_FEF; ++ if( m_T2Profile == T2P_Lite ) pT2_PLPIDS->Flags |= DD_T2_PLPIDS_LITE; ++ ++ CHK_ERROR(ReadRegT(0x22,0x54,&tmp)); ++ pT2_PLPIDS->PLPID = tmp; ++ ++ CHK_ERROR(ReadRegT(0x22,0x54 + 19 + 13,&tmp)); // Interval ++ if( tmp > 0 ) ++ { ++ CHK_ERROR(ReadRegT(0x22,0x54 + 19,&tmp)); ++ pT2_PLPIDS->CommonPLPID = tmp; ++ } ++ + BYTE nPids = 0; + CHK_ERROR(ReadRegT(0x22,0x7F,&nPids)); + +- pValues[0] = nPids; +- if( nPids >= nValues ) nPids = BYTE(nValues-1); ++ pT2_PLPIDS->NumPLPS = nPids; ++ CHK_ERROR(ReadRegT(0x22,0x80,&pT2_PLPIDS->PLPList[0], nPids > 128 ? 128 : nPids)); + +- CHK_ERROR(ReadRegT(0x22,0x80,&pValues[1], nPids > 128 ? 128 : nPids)); +- + if( nPids > 128 ) + { +- CHK_ERROR(ReadRegT(0x23,0x10,&pValues[129], nPids - 128)); ++ CHK_ERROR(ReadRegT(0x23,0x10,&pT2_PLPIDS->PLPList[128], nPids - 128)); + } + +- *pReturned = nPids + 1; ++ + } + while(0); + UnFreezeRegsT(); + static void GetPLPIds(struct cxd_state *state, u32 nValues, u8 *Values, u32 *Returned) { - u8 nPids = 0; + u8 nPids = 0, tmp; *Returned = 0; if (state->state != ActiveT2) @@ -1737,6 +1904,110 @@ static int get_algo(struct dvb_frontend *fe) return DVBFE_ALGO_HW; } +static int get_fe_t2(struct cxd_state *state) +{ + struct dvb_frontend *fe = &state->frontend; + struct dtv_frontend_properties *p = &fe->dtv_property_cache; + u8 ofdm[5], modcod[2]; + + freeze_regst(state); + readregst_unlocked(state, 0x20, 0x5c, ofdm, 5); + readregst_unlocked(state, 0x22, 0x5b, &modcod, 2); + unfreeze_regst(state); + + switch (modcod[0] & 0x07) { + case 0: + p->fec_inner = FEC_1_2; + break; + case 1: + p->fec_inner = FEC_3_5; + break; + case 2: + p->fec_inner = FEC_2_3; + break; + case 3: + p->fec_inner = FEC_3_4; + break; + case 4: + p->fec_inner = FEC_4_5; + break; + case 5: + p->fec_inner = FEC_5_6; + break; + case 6: + p->fec_inner = FEC_1_3; + break; + case 7: + p->fec_inner = FEC_2_5; + break; + } + + switch (modcod[1] & 0x07) { + case 0: + p->modulation = QPSK; + break; + case 1: + p->modulation = QAM_16; + break; + case 2: + p->modulation = QAM_64; + break; + case 3: + p->modulation = QAM_256; + break; + } + + switch (ofdm[0] & 0x07) { + case 0: + p->transmission_mode = TRANSMISSION_MODE_2K; + break; + case 1: + p->transmission_mode = TRANSMISSION_MODE_8K; + break; + case 2: + p->transmission_mode = TRANSMISSION_MODE_4K; + break; + case 3: + p->transmission_mode = TRANSMISSION_MODE_1K; + break; + case 4: + p->transmission_mode = TRANSMISSION_MODE_16K; + break; + case 5: + p->transmission_mode = TRANSMISSION_MODE_32K; + break; + case 6: + p->transmission_mode = TRANSMISSION_MODE_64K; + break; + } + + switch ((ofdm[1] >> 4) & 0x07) { + case 0: + p->guard_interval = GUARD_INTERVAL_1_32; + break; + case 1: + p->guard_interval = GUARD_INTERVAL_1_16; + break; + case 2: + p->guard_interval = GUARD_INTERVAL_1_8; + break; + case 3: + p->guard_interval = GUARD_INTERVAL_1_4; + break; + case 4: + p->guard_interval = GUARD_INTERVAL_1_128; + break; + case 5: + p->guard_interval = GUARD_INTERVAL_19_128; + break; + case 6: + p->guard_interval = GUARD_INTERVAL_19_256; + break; + } + + return 0; +} + static int get_fe_t(struct cxd_state *state) { struct dvb_frontend *fe = &state->frontend; @@ -1864,6 +2135,7 @@ static int get_frontend(struct dvb_frontend *fe) get_fe_t(state); break; case ActiveT2: + get_fe_t2(state); break; case ActiveC: get_fe_c(state);