+
+//=============================================================================
+// An ISO15693 decoder for reader commands.
+//
+// This function is called 4 times per bit (every 2 subcarrier cycles).
+// Subcarrier frequency fs is 848kHz, 1/fs = 1,18us, i.e. function is called every 2,36us
+// LED handling:
+// LED B -> ON once we have received the SOF and are expecting the rest.
+// LED B -> OFF once we have received EOF or are in error state or unsynced
+//
+// Returns: true if we received a EOF
+// false if we are still waiting for some more
+//=============================================================================
+
+typedef struct DecodeReader {
+ enum {
+ STATE_READER_UNSYNCD,
+ STATE_READER_AWAIT_1ST_FALLING_EDGE_OF_SOF,
+ STATE_READER_AWAIT_1ST_RISING_EDGE_OF_SOF,
+ STATE_READER_AWAIT_2ND_FALLING_EDGE_OF_SOF,
+ STATE_READER_AWAIT_2ND_RISING_EDGE_OF_SOF,
+ STATE_READER_AWAIT_END_OF_SOF_1_OUT_OF_4,
+ STATE_READER_RECEIVE_DATA_1_OUT_OF_4,
+ STATE_READER_RECEIVE_DATA_1_OUT_OF_256,
+ STATE_READER_RECEIVE_JAMMING
+ } state;
+ enum {
+ CODING_1_OUT_OF_4,
+ CODING_1_OUT_OF_256
+ } Coding;
+ uint8_t shiftReg;
+ uint8_t bitCount;
+ int byteCount;
+ int byteCountMax;
+ int posCount;
+ int sum1, sum2;
+ uint8_t *output;
+ uint8_t jam_search_len;
+ uint8_t *jam_search_string;
+} DecodeReader_t;
+
+
+static void DecodeReaderInit(DecodeReader_t* DecodeReader, uint8_t *data, uint16_t max_len, uint8_t jam_search_len, uint8_t *jam_search_string) {
+ DecodeReader->output = data;
+ DecodeReader->byteCountMax = max_len;
+ DecodeReader->state = STATE_READER_UNSYNCD;
+ DecodeReader->byteCount = 0;
+ DecodeReader->bitCount = 0;
+ DecodeReader->posCount = 1;
+ DecodeReader->shiftReg = 0;
+ DecodeReader->jam_search_len = jam_search_len;
+ DecodeReader->jam_search_string = jam_search_string;
+}
+
+
+static void DecodeReaderReset(DecodeReader_t* DecodeReader) {
+ DecodeReader->state = STATE_READER_UNSYNCD;
+}
+
+
+static int inline __attribute__((always_inline)) Handle15693SampleFromReader(bool bit, DecodeReader_t *DecodeReader) {
+ switch (DecodeReader->state) {
+ case STATE_READER_UNSYNCD:
+ // wait for unmodulated carrier
+ if (bit) {
+ DecodeReader->state = STATE_READER_AWAIT_1ST_FALLING_EDGE_OF_SOF;
+ }
+ break;
+
+ case STATE_READER_AWAIT_1ST_FALLING_EDGE_OF_SOF:
+ if (!bit) {
+ // we went low, so this could be the beginning of a SOF
+ DecodeReader->posCount = 1;
+ DecodeReader->state = STATE_READER_AWAIT_1ST_RISING_EDGE_OF_SOF;
+ }
+ break;
+
+ case STATE_READER_AWAIT_1ST_RISING_EDGE_OF_SOF:
+ DecodeReader->posCount++;
+ if (bit) { // detected rising edge
+ if (DecodeReader->posCount < 4) { // rising edge too early (nominally expected at 5)
+ DecodeReader->state = STATE_READER_AWAIT_1ST_FALLING_EDGE_OF_SOF;
+ } else { // SOF
+ DecodeReader->state = STATE_READER_AWAIT_2ND_FALLING_EDGE_OF_SOF;
+ }
+ } else {
+ if (DecodeReader->posCount > 5) { // stayed low for too long
+ DecodeReaderReset(DecodeReader);
+ } else {
+ // do nothing, keep waiting
+ }
+ }
+ break;
+
+ case STATE_READER_AWAIT_2ND_FALLING_EDGE_OF_SOF:
+ DecodeReader->posCount++;
+ if (!bit) { // detected a falling edge
+ if (DecodeReader->posCount < 20) { // falling edge too early (nominally expected at 21 earliest)
+ DecodeReaderReset(DecodeReader);
+ } else if (DecodeReader->posCount < 23) { // SOF for 1 out of 4 coding
+ DecodeReader->Coding = CODING_1_OUT_OF_4;
+ DecodeReader->state = STATE_READER_AWAIT_2ND_RISING_EDGE_OF_SOF;
+ } else if (DecodeReader->posCount < 28) { // falling edge too early (nominally expected at 29 latest)
+ DecodeReaderReset(DecodeReader);
+ } else { // SOF for 1 out of 256 coding
+ DecodeReader->Coding = CODING_1_OUT_OF_256;
+ DecodeReader->state = STATE_READER_AWAIT_2ND_RISING_EDGE_OF_SOF;
+ }
+ } else {
+ if (DecodeReader->posCount > 29) { // stayed high for too long
+ DecodeReader->state = STATE_READER_AWAIT_1ST_FALLING_EDGE_OF_SOF;
+ } else {
+ // do nothing, keep waiting
+ }
+ }
+ break;
+
+ case STATE_READER_AWAIT_2ND_RISING_EDGE_OF_SOF:
+ DecodeReader->posCount++;
+ if (bit) { // detected rising edge
+ if (DecodeReader->Coding == CODING_1_OUT_OF_256) {
+ if (DecodeReader->posCount < 32) { // rising edge too early (nominally expected at 33)
+ DecodeReader->state = STATE_READER_AWAIT_1ST_FALLING_EDGE_OF_SOF;
+ } else {
+ DecodeReader->posCount = 1;
+ DecodeReader->bitCount = 0;
+ DecodeReader->byteCount = 0;
+ DecodeReader->sum1 = 1;
+ DecodeReader->state = STATE_READER_RECEIVE_DATA_1_OUT_OF_256;
+ LED_B_ON();
+ }
+ } else { // CODING_1_OUT_OF_4
+ if (DecodeReader->posCount < 24) { // rising edge too early (nominally expected at 25)
+ DecodeReader->state = STATE_READER_AWAIT_1ST_FALLING_EDGE_OF_SOF;
+ } else {
+ DecodeReader->posCount = 1;
+ DecodeReader->state = STATE_READER_AWAIT_END_OF_SOF_1_OUT_OF_4;
+ }
+ }
+ } else {
+ if (DecodeReader->Coding == CODING_1_OUT_OF_256) {
+ if (DecodeReader->posCount > 34) { // signal stayed low for too long
+ DecodeReaderReset(DecodeReader);
+ } else {
+ // do nothing, keep waiting
+ }
+ } else { // CODING_1_OUT_OF_4
+ if (DecodeReader->posCount > 26) { // signal stayed low for too long
+ DecodeReaderReset(DecodeReader);
+ } else {
+ // do nothing, keep waiting
+ }
+ }
+ }
+ break;
+
+ case STATE_READER_AWAIT_END_OF_SOF_1_OUT_OF_4:
+ DecodeReader->posCount++;
+ if (bit) {
+ if (DecodeReader->posCount == 9) {
+ DecodeReader->posCount = 1;
+ DecodeReader->bitCount = 0;
+ DecodeReader->byteCount = 0;
+ DecodeReader->sum1 = 1;
+ DecodeReader->state = STATE_READER_RECEIVE_DATA_1_OUT_OF_4;
+ LED_B_ON();
+ } else {
+ // do nothing, keep waiting
+ }
+ } else { // unexpected falling edge
+ DecodeReaderReset(DecodeReader);
+ }
+ break;
+
+ case STATE_READER_RECEIVE_DATA_1_OUT_OF_4:
+ DecodeReader->posCount++;
+ if (DecodeReader->posCount == 1) {
+ DecodeReader->sum1 = bit?1:0;
+ } else if (DecodeReader->posCount <= 4) {
+ if (bit) DecodeReader->sum1++;
+ } else if (DecodeReader->posCount == 5) {
+ DecodeReader->sum2 = bit?1:0;
+ } else {
+ if (bit) DecodeReader->sum2++;
+ }
+ if (DecodeReader->posCount == 8) {
+ DecodeReader->posCount = 0;
+ if (DecodeReader->sum1 <= 1 && DecodeReader->sum2 >= 3) { // EOF
+ LED_B_OFF(); // Finished receiving
+ DecodeReaderReset(DecodeReader);
+ if (DecodeReader->byteCount != 0) {
+ return true;
+ }
+ } else if (DecodeReader->sum1 >= 3 && DecodeReader->sum2 <= 1) { // detected a 2bit position
+ DecodeReader->shiftReg >>= 2;
+ DecodeReader->shiftReg |= (DecodeReader->bitCount << 6);
+ }
+ if (DecodeReader->bitCount == 15) { // we have a full byte
+ DecodeReader->output[DecodeReader->byteCount++] = DecodeReader->shiftReg;
+ if (DecodeReader->byteCount > DecodeReader->byteCountMax) {
+ // buffer overflow, give up
+ LED_B_OFF();
+ DecodeReaderReset(DecodeReader);
+ }
+ DecodeReader->bitCount = 0;
+ DecodeReader->shiftReg = 0;
+ if (DecodeReader->byteCount == DecodeReader->jam_search_len) {
+ if (!memcmp(DecodeReader->output, DecodeReader->jam_search_string, DecodeReader->jam_search_len)) {
+ LED_D_ON();
+ FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER | FPGA_HF_READER_MODE_SEND_JAM);
+ DecodeReader->state = STATE_READER_RECEIVE_JAMMING;
+ }
+ }
+ } else {
+ DecodeReader->bitCount++;
+ }
+ }
+ break;
+
+ case STATE_READER_RECEIVE_DATA_1_OUT_OF_256:
+ DecodeReader->posCount++;
+ if (DecodeReader->posCount == 1) {
+ DecodeReader->sum1 = bit?1:0;
+ } else if (DecodeReader->posCount <= 4) {
+ if (bit) DecodeReader->sum1++;
+ } else if (DecodeReader->posCount == 5) {
+ DecodeReader->sum2 = bit?1:0;
+ } else if (bit) {
+ DecodeReader->sum2++;
+ }
+ if (DecodeReader->posCount == 8) {
+ DecodeReader->posCount = 0;
+ if (DecodeReader->sum1 <= 1 && DecodeReader->sum2 >= 3) { // EOF
+ LED_B_OFF(); // Finished receiving
+ DecodeReaderReset(DecodeReader);
+ if (DecodeReader->byteCount != 0) {
+ return true;
+ }
+ } else if (DecodeReader->sum1 >= 3 && DecodeReader->sum2 <= 1) { // detected the bit position
+ DecodeReader->shiftReg = DecodeReader->bitCount;
+ }
+ if (DecodeReader->bitCount == 255) { // we have a full byte
+ DecodeReader->output[DecodeReader->byteCount++] = DecodeReader->shiftReg;
+ if (DecodeReader->byteCount > DecodeReader->byteCountMax) {
+ // buffer overflow, give up
+ LED_B_OFF();
+ DecodeReaderReset(DecodeReader);
+ }
+ if (DecodeReader->byteCount == DecodeReader->jam_search_len) {
+ if (!memcmp(DecodeReader->output, DecodeReader->jam_search_string, DecodeReader->jam_search_len)) {
+ LED_D_ON();
+ FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER | FPGA_HF_READER_MODE_SEND_JAM);
+ DecodeReader->state = STATE_READER_RECEIVE_JAMMING;
+ }
+ }
+ }
+ DecodeReader->bitCount++;
+ }
+ break;
+
+ case STATE_READER_RECEIVE_JAMMING:
+ DecodeReader->posCount++;
+ if (DecodeReader->Coding == CODING_1_OUT_OF_4) {
+ if (DecodeReader->posCount == 7*16) { // 7 bits jammed
+ FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER | FPGA_HF_READER_MODE_SNOOP_AMPLITUDE); // stop jamming
+ // FpgaDisableTracing();
+ LED_D_OFF();
+ } else if (DecodeReader->posCount == 8*16) {
+ DecodeReader->posCount = 0;
+ DecodeReader->output[DecodeReader->byteCount++] = 0x00;
+ DecodeReader->state = STATE_READER_RECEIVE_DATA_1_OUT_OF_4;
+ }
+ } else {
+ if (DecodeReader->posCount == 7*256) { // 7 bits jammend
+ FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER | FPGA_HF_READER_MODE_SNOOP_AMPLITUDE); // stop jamming
+ LED_D_OFF();
+ } else if (DecodeReader->posCount == 8*256) {
+ DecodeReader->posCount = 0;
+ DecodeReader->output[DecodeReader->byteCount++] = 0x00;
+ DecodeReader->state = STATE_READER_RECEIVE_DATA_1_OUT_OF_256;
+ }
+ }
+ break;
+
+ default:
+ LED_B_OFF();
+ DecodeReaderReset(DecodeReader);
+ break;
+ }
+
+ return false;