[PCF7931] draft continue with refactoring ReadPCF7931()

still not done with DemodPCF7931(). But now including changes in  ReadPCF7931().
They work tightly together.
Trying to resolve some issues and bugs. Basically it seems to work and
my results are consistent. However, they still deviate from what I get if
I do analyze the signal using lf read and data commands.

still some issues somewhere.
This commit is contained in:
tinooo 2025-02-14 14:40:00 +01:00 committed by Tino
commit 2da713eba9
2 changed files with 152 additions and 162 deletions

View file

@ -30,6 +30,8 @@
size_t DemodPCF7931(uint8_t **outBlocks, bool ledcontrol) { size_t DemodPCF7931(uint8_t **outBlocks, bool ledcontrol) {
const uint8_t DECIMATION = 4;
// 2021 iceman, memor // 2021 iceman, memor
uint8_t bits[256] = {0x00}; uint8_t bits[256] = {0x00};
uint8_t blocks[8][16]; uint8_t blocks[8][16];
@ -45,114 +47,102 @@ size_t DemodPCF7931(uint8_t **outBlocks, bool ledcontrol) {
// which is ~17.xxx samples. round up. and clamp to this value. // which is ~17.xxx samples. round up. and clamp to this value.
// TODO: Doublecheck why this is being limited? // TODO: Doublecheck why this is being limited?
g_GraphTraceLen = (g_GraphTraceLen > 18000) ? 18000 : g_GraphTraceLen; // g_GraphTraceLen = (g_GraphTraceLen > 18000) ? 18000 : g_GraphTraceLen;
BigBuf_Clear_keep_EM();
LFSetupFPGAForADC(LF_DIVISOR_125, true);
// DoAcquisition_default(0, true, ledcontrol);
// sample with decimation of 2 --> This means double the values can be sampled.
// this is needed to get a complete frame in the buffer (64 * 8 * 16 * 8 + 8*PMC(~380)) = ~68.000 samples. Buffer is only 41.xxx
// with decimation 2, buffer will be twice as big.
DoAcquisition(DECIMATION, 8, 0, 0, false, 0, 0, 0, ledcontrol);
uint8_t j; uint8_t j;
uint8_t half_switch; uint8_t half_switch;
uint8_t bitPos; // max 128 bit in one block. if more, then there is an error and PMC was not found. uint8_t bitPos; // max 128 bit in one block. if more, then there is an error and PMC was not found.
uint16_t sample; // to keep track of the current sample that is being analyzed uint32_t sample; // to keep track of the current sample that is being analyzed
uint16_t samplePosLastEdge; uint32_t samplePosLastEdge;
uint16_t samplePosCurrentEdge; uint32_t samplePosCurrentEdge;
uint8_t lastClockDuration; // used to store the duration of the last "clock", for decoding. clock may not be the correct term, maybe bit is better. The duration between two edges is meant uint8_t lastClockDuration; // used to store the duration of the last "clock", for decoding. clock may not be the correct term, maybe bit is better. The duration between two edges is meant
uint8_t beforeLastClockDuration; // store the clock duration of the cycle before the last Clock duration. Basically clockduration -2 uint8_t beforeLastClockDuration; // store the clock duration of the cycle before the last Clock duration. Basically clockduration -2
const uint8_t clock = 64; const uint8_t clock = 64/DECIMATION; // this actually is 64, but since samples are decimated by 2, clock is also /2
const uint8_t tolerance = clock / 8; const uint8_t tolerance = clock / 8;
const uint8_t _16T0 = clock/4; const uint8_t _16T0 = clock/4;
const uint8_t _32T0 = clock/2; const uint8_t _32T0 = clock/2;
const uint8_t _64T0 = clock; const uint8_t _64T0 = clock;
int block_done; const uint16_t pmc16T0Len = (128 + 127 + 16 + 32 + 33 + 16) * clock/64; // calculating the two possible pmc lengths, based on the clock. -4 at the end is to make sure not to increment too far
int warnings = 0; const uint16_t pmc32T0Len = (128 + 127 + 16 + 32 + 33 ) * clock/64;
uint8_t block_done;
size_t num_blocks = 0; size_t num_blocks = 0;
// int lmin = 64, lmax = 192; // used for some thresholds to identify high/low uint8_t threshold = 50; // threshold to filter out noise, from an actual edge.
uint8_t threshold = 30; // threshold to filter out noise, from an actual edge. EdgeType expectedNextEdge = FALLING; // direction in which the next edge is expected should go.
EdgeType expectedNextEdge = UNDEFINED; // direction in which the next edge is expected should go.
BigBuf_Clear_keep_EM();
LFSetupFPGAForADC(LF_DIVISOR_125, true);
DoAcquisition_default(0, true, ledcontrol);
sample = 1;
while (sample < g_GraphTraceLen && expectedNextEdge==UNDEFINED) {
// find falling edge
if ((dest[sample] + threshold) < dest[sample-1]) {
expectedNextEdge = RISING; // current edge is falling, so next has to be rising
// find rising edge
} else if ((dest[sample] - threshold) > dest[sample-1]){
expectedNextEdge = FALLING; // current edge is rising, so next has to be falling
}
sample++;
}
samplePosLastEdge = sample++;
half_switch = 0; half_switch = 0;
samplePosLastEdge = 0;
block_done = 0; block_done = 0;
bitPos = 0; bitPos = 0;
lastClockDuration=0; lastClockDuration=0;
// dont reset sample here. we've already found the last edge. continue from here for (sample = 1 ; sample < g_GraphTraceLen; sample++) {
for ( ; sample < g_GraphTraceLen; sample++) {
if (sample%4 == 0){
// Dbprintf("dest[%d]: %d, bitPos: %d",sample, dest[sample], bitPos);
}
// condition is searching for the next edge, in the expected diretion. // condition is searching for the next edge, in the expected diretion.
if ( ((dest[sample] + threshold) < dest[sample-1] && expectedNextEdge == FALLING ) || if ( ((dest[sample] + threshold) < dest[sample-1] && expectedNextEdge == FALLING ) ||
((dest[sample] - threshold) > dest[sample-1] && expectedNextEdge == RISING )) { ((dest[sample] - threshold) > dest[sample-1] && expectedNextEdge == RISING )) {
//okay, next falling/rising edge found //okay, next falling/rising edge found
expectedNextEdge = (expectedNextEdge == FALLING) ? RISING : FALLING; //toggle the next expected edge expectedNextEdge = (expectedNextEdge == FALLING) ? RISING : FALLING; //toggle the next expected edge
samplePosCurrentEdge = sample; samplePosCurrentEdge = sample;
beforeLastClockDuration = lastClockDuration; // save the previous clock duration for PMC recognition beforeLastClockDuration = lastClockDuration; // save the previous clock duration for PMC recognition
lastClockDuration = samplePosCurrentEdge - samplePosLastEdge; lastClockDuration = samplePosCurrentEdge - samplePosLastEdge;
samplePosLastEdge = sample; samplePosLastEdge = sample;
// Dbprintf("%d, %d, edge found, len: %d, nextEdge: %d", sample, dest[sample], lastClockDuration*DECIMATION, expectedNextEdge);
// Switch depending on lastClockDuration length: // Switch depending on lastClockDuration length:
// Tolerance is 1/8 of clock rate (arbitrary)
// 16T0 // 16T0
if (ABS(lastClockDuration - _16T0) < tolerance) { if (ABS(lastClockDuration - _16T0) < tolerance) {
//tollerance is missing for PMC!! TODO // if the clock before also was 16T0, it is a PMC!
// if the clock before was 16, it is indicating a PMC - check this
if (ABS(beforeLastClockDuration - _16T0) < tolerance) { if (ABS(beforeLastClockDuration - _16T0) < tolerance) {
// It's a PMC // It's a PMC
Dbprintf(_GREEN_("PMC 16T0 FOUND:") " bitPos: %d, sample: %d", bitPos, sample); Dbprintf(_GREEN_("PMC 16T0 FOUND:") " bitPos: %d, sample: %d", bitPos, sample);
sample += (128 + 127 + 16 + 32 + 33 + 16) - 1; // move to the sample after PMC sample += pmc16T0Len; // move to the sample after PMC
expectedNextEdge = FALLING;
samplePosLastEdge = sample; samplePosLastEdge = sample;
block_done = 1; block_done = 1;
// TODO: Not sure if sample need to set expected next edge?
} }
// 32TO // 32TO
} else if (ABS(lastClockDuration - _32T0) < tolerance) { } else if (ABS(lastClockDuration - _32T0) < tolerance) {
// if the clock before was 16, it is indicating a PMC - check this // if the clock before also was 16T0, it is a PMC!
if (ABS(beforeLastClockDuration - _16T0) < tolerance) { if (ABS(beforeLastClockDuration - _16T0) < tolerance) {
// It's a PMC ! // It's a PMC !
Dbprintf(_GREEN_("PMC 32T0 FOUND:") " bitPos: %d, sample: %d", bitPos, sample); Dbprintf(_GREEN_("PMC 32T0 FOUND:") " bitPos: %d, sample: %d", bitPos, sample);
sample += (128 + 127 + 16 + 32 + 33) - 1; // move to the sample after PMC
sample += pmc32T0Len; // move to the sample after PMC
expectedNextEdge = FALLING;
samplePosLastEdge = sample; samplePosLastEdge = sample;
block_done = 1; block_done = 1;
// TODO: Not sure if sample need to set expected next edge? // if no pmc, then its a normal bit.
// Check if its the second time, the edge changed if yes, then the bit is 0
// if no pmc, then its a normal bit. Check if its the second time, the edge changed
// if yes, then the bit is 0
} else if (half_switch == 1) { } else if (half_switch == 1) {
bits[bitPos] = 0; bits[bitPos] = 0;
// reset the edge counter to 0 // reset the edge counter to 0
half_switch = 0; half_switch = 0;
bitPos++; bitPos++;
// so it is the first time the edge changed. No bit value will be set here, bit if the // if it is the first time the edge changed. No bit value will be set here, bit if the
// edge changes again, it will be. see case above. // edge changes again, it will be. see case above.
} else } else
half_switch++; half_switch++;
@ -165,19 +155,17 @@ size_t DemodPCF7931(uint8_t **outBlocks, bool ledcontrol) {
// Error // Error
} else { } else {
Dbprintf(_RED_("ELSE error case") " bitPos: %d, sample: %d", bitPos, sample); // some Error. maybe check tolerances.
if (++warnings > 10) { // likeley to happen in the first block.
Dbprintf(_RED_("ERROR in demodulation") " Length last clock: %d - check threshold/tolerance/signal. Toss block", lastClockDuration*DECIMATION);
if (g_dbglevel >= DBG_EXTENDED) { // Toss this block.
Dbprintf("Error: too many detection errors, aborting"); block_done = 1;
}
return 0;
}
} }
if (block_done == 1) { if (block_done == 1) {
Dbprintf(_YELLOW_("Block Done") " bitPos: %d, sample: %d", bitPos, sample); // Dbprintf(_YELLOW_("Block Done") " bitPos: %d, sample: %d", bitPos, sample);
// check if it is a complete block. If bitpos <128, it means that we did not receive // check if it is a complete block. If bitpos <128, it means that we did not receive
// a complete block. E.g. at the first start of a transmission. // a complete block. E.g. at the first start of a transmission.
// only save if a complete block is being received. // only save if a complete block is being received.
@ -202,6 +190,8 @@ size_t DemodPCF7931(uint8_t **outBlocks, bool ledcontrol) {
half_switch = 0; half_switch = 0;
} }
}else {
// Dbprintf("%d, %d", sample, dest[sample]);
} }
// one block only holds 16byte (=128 bit) and then comes the PMC. so if more bit are found than 129, there must be an issue and PMC has not been identfied... // one block only holds 16byte (=128 bit) and then comes the PMC. so if more bit are found than 129, there must be an issue and PMC has not been identfied...
@ -211,12 +201,8 @@ size_t DemodPCF7931(uint8_t **outBlocks, bool ledcontrol) {
bitPos = 0; bitPos = 0;
} }
// Todo: No idea, why blocks 4 is checked..
if (num_blocks == 4) {
Dbprintf(_RED_("we should never get here!!!") " at sample: %d", sample);
break;
}
} }
memcpy(outBlocks, blocks, 16 * num_blocks); memcpy(outBlocks, blocks, 16 * num_blocks);
return num_blocks; return num_blocks;
} }
@ -265,23 +251,29 @@ void ReadPCF7931(bool ledcontrol) {
Dbprintf("ReadPCF7931()=========="); Dbprintf("ReadPCF7931()==========");
uint8_t maxBlocks = 8; // readable blocks
int found_blocks = 0; // successfully read blocks int found_blocks = 0; // successfully read blocks
int max_blocks = 8; // readable blocks
uint8_t memory_blocks[8][17]; // PCF content // TODO: Why 17 byte len? 16 should be good.
uint8_t single_blocks[8][17]; // PFC blocks with unknown position uint8_t memory_blocks[maxBlocks][17]; // PCF content
uint8_t single_blocks[maxBlocks][17]; // PFC blocks with unknown position
uint8_t tmp_blocks[4][16]; // temporary read buffer
int single_blocks_cnt = 0; int single_blocks_cnt = 0;
size_t n; // transmitted blocks size_t n; // transmitted blocks
uint8_t tmp_blocks[4][16]; // temporary read buffer
uint8_t found_0_1 = 0; // flag: blocks 0 and 1 were found //uint8_t found_0_1 = 0; // flag: blocks 0 and 1 were found
int errors = 0; // error counter int errors = 0; // error counter
int tries = 0; // tries counter int tries = 0; // tries counter
// reuse lenghts and consts to properly clear
memset(memory_blocks, 0, 8 * 17 * sizeof(uint8_t)); memset(memory_blocks, 0, 8 * 17 * sizeof(uint8_t));
memset(single_blocks, 0, 8 * 17 * sizeof(uint8_t)); memset(single_blocks, 0, 8 * 17 * sizeof(uint8_t));
int i = 0, j = 0; int i = 0;
//j = 0;
do { do {
Dbprintf("ReadPCF7931() -- DO LOOP =========="); Dbprintf("ReadPCF7931() -- DO LOOP ==========");
@ -294,15 +286,13 @@ void ReadPCF7931(bool ledcontrol) {
// exit if no block is received // exit if no block is received
if (errors >= 10 && found_blocks == 0 && single_blocks_cnt == 0) { if (errors >= 10 && found_blocks == 0 && single_blocks_cnt == 0) {
Dbprintf("[!!] Error, no tag or bad tag");
if (g_dbglevel >= DBG_INFO)
Dbprintf("[!!] Error, no tag or bad tag");
return; return;
} }
// exit if too many errors during reading // exit if too many tries without finding the first block
if (tries > 50 && (2 * errors > tries)) { if (tries > 10) {
Dbprintf("End after 10 tries");
if (g_dbglevel >= DBG_INFO) { if (g_dbglevel >= DBG_INFO) {
Dbprintf("[!!] Error reading the tag, only partial content"); Dbprintf("[!!] Error reading the tag, only partial content");
} }
@ -310,93 +300,94 @@ void ReadPCF7931(bool ledcontrol) {
goto end; goto end;
} }
// our logic breaks if we don't get at least two blocks // // our logic breaks if we don't get at least two blocks
if (n < 2) { // if (n < 2) {
// skip if all 0s block or no blocks // // skip if all 0s block or no blocks
if (n == 0 || !memcmp(tmp_blocks[0], "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 16)) // if (n == 0 || !memcmp(tmp_blocks[0], "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 16))
continue; // continue;
// add block to single blocks list // // add block to single blocks list
if (single_blocks_cnt < max_blocks) { // if (single_blocks_cnt < maxBlocks) {
for (i = 0; i < single_blocks_cnt; ++i) { // for (i = 0; i < single_blocks_cnt; ++i) {
if (!memcmp(single_blocks[i], tmp_blocks[0], 16)) { // if (!memcmp(single_blocks[i], tmp_blocks[0], 16)) {
j = 1; // j = 1;
break; // break;
} // }
} // }
if (j != 1) { // if (j != 1) {
memcpy(single_blocks[single_blocks_cnt], tmp_blocks[0], 16); // memcpy(single_blocks[single_blocks_cnt], tmp_blocks[0], 16);
print_result("got single block", single_blocks[single_blocks_cnt], 16); // print_result("got single block", single_blocks[single_blocks_cnt], 16);
single_blocks_cnt++; // single_blocks_cnt++;
} // }
j = 0; // j = 0;
} // }
++tries; // ++tries;
continue; // continue;
} // }
if (g_dbglevel >= DBG_EXTENDED) // Dbprintf("(dbg) got %d blocks (%d/%d found) (%d tries, %d errors)", n, found_blocks, (maxBlocks == 0 ? found_blocks : maxBlocks), tries, errors);
Dbprintf("(dbg) got %d blocks (%d/%d found) (%d tries, %d errors)", n, found_blocks, (max_blocks == 0 ? found_blocks : max_blocks), tries, errors); // if (g_dbglevel >= DBG_EXTENDED)
// Dbprintf("(dbg) got %d blocks (%d/%d found) (%d tries, %d errors)", n, found_blocks, (maxBlocks == 0 ? found_blocks : maxBlocks), tries, errors);
for (i = 0; i < n; ++i) { for (i = 0; i < n; ++i) {
print_result("got consecutive blocks", tmp_blocks[i], 16); print_result("got consecutive blocks", tmp_blocks[i], 16);
} }
i = 0; // i = 0;
if (!found_0_1) { // if (!found_0_1) {
while (i < n - 1) { // while (i < n - 1) {
if (IsBlock0PCF7931(tmp_blocks[i]) && IsBlock1PCF7931(tmp_blocks[i + 1])) { // if (IsBlock0PCF7931(tmp_blocks[i]) && IsBlock1PCF7931(tmp_blocks[i + 1])) {
found_0_1 = 1; // found_0_1 = 1;
memcpy(memory_blocks[0], tmp_blocks[i], 16); // memcpy(memory_blocks[0], tmp_blocks[i], 16);
memcpy(memory_blocks[1], tmp_blocks[i + 1], 16); // memcpy(memory_blocks[1], tmp_blocks[i + 1], 16);
memory_blocks[0][ALLOC] = memory_blocks[1][ALLOC] = 1; // memory_blocks[0][ALLOC] = memory_blocks[1][ALLOC] = 1;
// block 1 tells how many blocks are going to be sent // // block 1 tells how many blocks are going to be sent
max_blocks = MAX((memory_blocks[1][14] & 0x7f), memory_blocks[1][15]) + 1; // maxBlocks = MAX((memory_blocks[1][14] & 0x7f), memory_blocks[1][15]) + 1;
found_blocks = 2; // found_blocks = 2;
Dbprintf("Found blocks 0 and 1. PCF is transmitting %d blocks.", max_blocks); // Dbprintf("Found blocks 0 and 1. PCF is transmitting %d blocks.", maxBlocks);
// handle the following blocks // // handle the following blocks
for (j = i + 2; j < n; ++j) { // for (j = i + 2; j < n; ++j) {
memcpy(memory_blocks[found_blocks], tmp_blocks[j], 16); // memcpy(memory_blocks[found_blocks], tmp_blocks[j], 16);
memory_blocks[found_blocks][ALLOC] = 1; // memory_blocks[found_blocks][ALLOC] = 1;
++found_blocks; // ++found_blocks;
} // }
break; // break;
} // }
++i; // ++i;
} // }
} else { // } else {
// Trying to re-order blocks // // Trying to re-order blocks
// Look for identical block in memory blocks // // Look for identical block in memory blocks
while (i < n - 1) { // while (i < n - 1) {
// skip all zeroes blocks // // skip all zeroes blocks
if (memcmp(tmp_blocks[i], "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 16)) { // if (memcmp(tmp_blocks[i], "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 16)) {
for (j = 1; j < max_blocks - 1; ++j) { // for (j = 1; j < maxBlocks - 1; ++j) {
if (!memcmp(tmp_blocks[i], memory_blocks[j], 16) && !memory_blocks[j + 1][ALLOC]) { // if (!memcmp(tmp_blocks[i], memory_blocks[j], 16) && !memory_blocks[j + 1][ALLOC]) {
memcpy(memory_blocks[j + 1], tmp_blocks[i + 1], 16); // memcpy(memory_blocks[j + 1], tmp_blocks[i + 1], 16);
memory_blocks[j + 1][ALLOC] = 1; // memory_blocks[j + 1][ALLOC] = 1;
if (++found_blocks >= max_blocks) goto end; // if (++found_blocks >= maxBlocks) goto end;
} // }
} // }
} // }
if (memcmp(tmp_blocks[i + 1], "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 16)) { // if (memcmp(tmp_blocks[i + 1], "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 16)) {
for (j = 0; j < max_blocks; ++j) { // for (j = 0; j < maxBlocks; ++j) {
if (!memcmp(tmp_blocks[i + 1], memory_blocks[j], 16) && !memory_blocks[(j == 0 ? max_blocks : j) - 1][ALLOC]) { // if (!memcmp(tmp_blocks[i + 1], memory_blocks[j], 16) && !memory_blocks[(j == 0 ? maxBlocks : j) - 1][ALLOC]) {
if (j == 0) { // if (j == 0) {
memcpy(memory_blocks[max_blocks - 1], tmp_blocks[i], 16); // memcpy(memory_blocks[maxBlocks - 1], tmp_blocks[i], 16);
memory_blocks[max_blocks - 1][ALLOC] = 1; // memory_blocks[maxBlocks - 1][ALLOC] = 1;
} else { // } else {
memcpy(memory_blocks[j - 1], tmp_blocks[i], 16); // memcpy(memory_blocks[j - 1], tmp_blocks[i], 16);
memory_blocks[j - 1][ALLOC] = 1; // memory_blocks[j - 1][ALLOC] = 1;
} // }
if (++found_blocks >= max_blocks) goto end; // if (++found_blocks >= maxBlocks) goto end;
} // }
} // }
} // }
++i; // ++i;
} // }
} // }
++tries; ++tries;
if (BUTTON_PRESS()) { if (BUTTON_PRESS()) {
if (g_dbglevel >= DBG_EXTENDED) if (g_dbglevel >= DBG_EXTENDED)
@ -404,13 +395,13 @@ void ReadPCF7931(bool ledcontrol) {
goto end; goto end;
} }
} while (found_blocks < max_blocks); } while (found_blocks < maxBlocks);
end: end:
Dbprintf("-----------------------------------------"); Dbprintf("-----------------------------------------");
Dbprintf("Memory content:"); Dbprintf("Memory content:");
Dbprintf("-----------------------------------------"); Dbprintf("-----------------------------------------");
for (i = 0; i < max_blocks; ++i) { for (i = 0; i < maxBlocks; ++i) {
if (memory_blocks[i][ALLOC]) if (memory_blocks[i][ALLOC])
print_result("Block", memory_blocks[i], 16); print_result("Block", memory_blocks[i], 16);
else else
@ -418,7 +409,7 @@ end:
} }
Dbprintf("-----------------------------------------"); Dbprintf("-----------------------------------------");
if (found_blocks < max_blocks) { if (found_blocks < maxBlocks) {
Dbprintf("-----------------------------------------"); Dbprintf("-----------------------------------------");
Dbprintf("Blocks with unknown position:"); Dbprintf("Blocks with unknown position:");
Dbprintf("-----------------------------------------"); Dbprintf("-----------------------------------------");

View file

@ -20,7 +20,6 @@
typedef enum{ typedef enum{
UNDEFINED,
FALLING, FALLING,
RISING RISING
} EdgeType; } EdgeType;