+ switch(DecodeTag->state) {
+ case STATE_TAG_SOF_LOW:
+ // waiting for 12 times low (11 times low is accepted as well)
+ if (amplitude < NOISE_THRESHOLD) {
+ DecodeTag->posCount++;
+ } else {
+ if (DecodeTag->posCount > 10) {
+ DecodeTag->posCount = 1;
+ DecodeTag->sum1 = 0;
+ DecodeTag->state = STATE_TAG_SOF_HIGH;
+ } else {
+ DecodeTag->posCount = 0;
+ }
+ }
+ break;
+
+ case STATE_TAG_SOF_HIGH:
+ // waiting for 10 times high. Take average over the last 8
+ if (amplitude > NOISE_THRESHOLD) {
+ DecodeTag->posCount++;
+ if (DecodeTag->posCount > 2) {
+ DecodeTag->sum1 += amplitude; // keep track of average high value
+ }
+ if (DecodeTag->posCount == 10) {
+ DecodeTag->sum1 >>= 4; // calculate half of average high value (8 samples)
+ DecodeTag->state = STATE_TAG_SOF_HIGH_END;
+ }
+ } else { // high phase was too short
+ DecodeTag->posCount = 1;
+ DecodeTag->state = STATE_TAG_SOF_LOW;
+ }
+ break;
+
+ case STATE_TAG_SOF_HIGH_END:
+ // waiting for a falling edge
+ if (amplitude < DecodeTag->sum1) { // signal drops below 50% average high: a falling edge
+ DecodeTag->lastBit = SOF_PART1; // detected 1st part of SOF (12 samples low and 12 samples high)
+ DecodeTag->shiftReg = 0;
+ DecodeTag->bitCount = 0;
+ DecodeTag->len = 0;
+ DecodeTag->sum1 = amplitude;
+ DecodeTag->sum2 = 0;
+ DecodeTag->posCount = 2;
+ DecodeTag->state = STATE_TAG_RECEIVING_DATA;
+ LED_C_ON();
+ } else {
+ DecodeTag->posCount++;
+ if (DecodeTag->posCount > 13) { // high phase too long
+ DecodeTag->posCount = 0;
+ DecodeTag->state = STATE_TAG_SOF_LOW;
+ LED_C_OFF();
+ }
+ }
+ break;
+
+ case STATE_TAG_RECEIVING_DATA:
+ if (DecodeTag->posCount == 1) {
+ DecodeTag->sum1 = 0;
+ DecodeTag->sum2 = 0;
+ }
+ if (DecodeTag->posCount <= 4) {
+ DecodeTag->sum1 += amplitude;
+ } else {
+ DecodeTag->sum2 += amplitude;
+ }
+ if (DecodeTag->posCount == 8) {
+ int32_t corr_1 = DecodeTag->sum2 - DecodeTag->sum1;
+ int32_t corr_0 = -corr_1;
+ int32_t corr_EOF = (DecodeTag->sum1 + DecodeTag->sum2) / 2;
+ if (corr_EOF > corr_0 && corr_EOF > corr_1) {
+ if (DecodeTag->lastBit == LOGIC0) { // this was already part of EOF
+ DecodeTag->state = STATE_TAG_EOF;
+ } else {
+ DecodeTag->posCount = 0;
+ DecodeTag->state = STATE_TAG_SOF_LOW;
+ LED_C_OFF();
+ }
+ } else if (corr_1 > corr_0) {
+ // logic 1
+ if (DecodeTag->lastBit == SOF_PART1) { // still part of SOF
+ DecodeTag->lastBit = SOF_PART2; // SOF completed
+ } else {
+ DecodeTag->lastBit = LOGIC1;
+ DecodeTag->shiftReg >>= 1;
+ DecodeTag->shiftReg |= 0x80;
+ DecodeTag->bitCount++;
+ if (DecodeTag->bitCount == 8) {
+ DecodeTag->output[DecodeTag->len] = DecodeTag->shiftReg;
+ DecodeTag->len++;
+ if (DecodeTag->len > DecodeTag->max_len) {
+ // buffer overflow, give up
+ DecodeTag->posCount = 0;
+ DecodeTag->state = STATE_TAG_SOF_LOW;
+ LED_C_OFF();
+ }
+ DecodeTag->bitCount = 0;
+ DecodeTag->shiftReg = 0;
+ }
+ }
+ } else {
+ // logic 0
+ if (DecodeTag->lastBit == SOF_PART1) { // incomplete SOF
+ DecodeTag->posCount = 0;
+ DecodeTag->state = STATE_TAG_SOF_LOW;
+ LED_C_OFF();
+ } else {
+ DecodeTag->lastBit = LOGIC0;
+ DecodeTag->shiftReg >>= 1;
+ DecodeTag->bitCount++;
+ if (DecodeTag->bitCount == 8) {
+ DecodeTag->output[DecodeTag->len] = DecodeTag->shiftReg;
+ DecodeTag->len++;
+ if (DecodeTag->len > DecodeTag->max_len) {
+ // buffer overflow, give up
+ DecodeTag->posCount = 0;
+ DecodeTag->state = STATE_TAG_SOF_LOW;
+ LED_C_OFF();
+ }
+ DecodeTag->bitCount = 0;
+ DecodeTag->shiftReg = 0;
+ }
+ }
+ }
+ DecodeTag->posCount = 0;
+ }
+ DecodeTag->posCount++;
+ break;