+               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_UNSYNCD;
+                               } else { // SOF
+                                       DecodeReader->state = STATE_READER_AWAIT_2ND_FALLING_EDGE_OF_SOF;
+                               }
+                       } else {
+                               if(DecodeReader->posCount > 5) { // stayed low for too long
+                                       DecodeReader->state = STATE_READER_UNSYNCD;
+                               } 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)
+                                       DecodeReader->state = STATE_READER_UNSYNCD;
+                               } 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)
+                                       DecodeReader->state = STATE_READER_UNSYNCD;
+                               } else {                                 // SOF for 1 out of 4 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_UNSYNCD;
+                               } 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_UNSYNCD;
+                                       } 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_UNSYNCD;
+                                       } else {
+                                               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
+                                               DecodeReader->state = STATE_READER_UNSYNCD;
+                                       } else {
+                                               // do nothing, keep waiting
+                                       }
+                               } else { // CODING_1_OUT_OF_4
+                                       if (DecodeReader->posCount > 26) { // signal stayed low for too long
+                                               DecodeReader->state = STATE_READER_UNSYNCD;
+                                       } else {
+                                               // do nothing, keep waiting
+                                       }
+                               }
+                       }
+                       break;
+
+               case STATE_READER_AWAIT_END_OF_SOF_1_OUT_OF_4:
+                       DecodeReader->posCount++;
+                       if (bit) {
+                               if (DecodeReader->posCount == 33) {
+                                       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
+                               DecodeReader->state = STATE_READER_UNSYNCD;
+                       }
+                       break;
+
+               case STATE_READER_RECEIVE_DATA_1_OUT_OF_4:
+                       DecodeReader->posCount++;
+                       if (DecodeReader->posCount == 1) {
+                               DecodeReader->sum1 = bit;
+                       } else if (DecodeReader->posCount <= 4) {
+                               DecodeReader->sum1 += bit;
+                       } else if (DecodeReader->posCount == 5) {
+                               DecodeReader->sum2 = bit;
+                       } else {
+                               DecodeReader->sum2 += bit;
+                       }
+                       if (DecodeReader->posCount == 8) {
+                               DecodeReader->posCount = 0;
+                               int corr10 = DecodeReader->sum1 - DecodeReader->sum2;
+                               int corr01 = DecodeReader->sum2 - DecodeReader->sum1;
+                               int corr11 = (DecodeReader->sum1 + DecodeReader->sum2) / 2;
+                               if (corr01 > corr11 && corr01 > corr10) { // EOF
+                                       LED_B_OFF(); // Finished receiving
+                                       DecodeReader->state = STATE_READER_UNSYNCD;
+                                       if (DecodeReader->byteCount != 0) {
+                                               return true;
+                                       }
+                               }
+                               if (corr10 > corr11) { // 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();
+                                               DecodeReader->state = STATE_READER_UNSYNCD;
+                                       }
+                                       DecodeReader->bitCount = 0;
+                               } else {
+                                       DecodeReader->bitCount++;
+                               }
+                       }
+                       break;
+
+               case STATE_READER_RECEIVE_DATA_1_OUT_OF_256:
+                       DecodeReader->posCount++;
+                       if (DecodeReader->posCount == 1) {
+                               DecodeReader->sum1 = bit;
+                       } else if (DecodeReader->posCount <= 4) {
+                               DecodeReader->sum1 += bit;
+                       } else if (DecodeReader->posCount == 5) {
+                               DecodeReader->sum2 = bit;
+                       } else {
+                               DecodeReader->sum2 += bit;
+                       }
+                       if (DecodeReader->posCount == 8) {
+                               DecodeReader->posCount = 0;
+                               int corr10 = DecodeReader->sum1 - DecodeReader->sum2;
+                               int corr01 = DecodeReader->sum2 - DecodeReader->sum1;
+                               int corr11 = (DecodeReader->sum1 + DecodeReader->sum2) / 2;
+                               if (corr01 > corr11 && corr01 > corr10) { // EOF
+                                       LED_B_OFF(); // Finished receiving
+                                       DecodeReader->state = STATE_READER_UNSYNCD;
+                                       if (DecodeReader->byteCount != 0) {
+                                               return true;
+                                       }
+                               }
+                               if (corr10 > corr11) { // 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();
+                                               DecodeReader->state = STATE_READER_UNSYNCD;
+                                       }
+                               }
+                               DecodeReader->bitCount++;
+                       }
+                       break;
+
+               default:
+                       LED_B_OFF();
+                       DecodeReader->state = STATE_READER_UNSYNCD;
+                       break;