//#define CLAS_O_DEBUG namespace clas_o { enum { UNKNOWN, T0, T1, T2, T3, OK, DONE }; unsigned char state = UNKNOWN; uint32_t x_data; uint8_t x_numBits; void resetDecoder () { x_data = 0; x_numBits = 0; state = UNKNOWN; } static boolean isDone() { return state == DONE; } static void done () { state = DONE; } static void gotBit (uint8_t value) { x_numBits++; x_data = (x_data << 1) + (value & 0x01); state = OK; } static int16_t decode (uint16_t width) { if( state != UNKNOWN ) { #ifdef CLAS_O_DEBUG Serial.print(width); Serial.print(" - "); #endif } switch (state) { case UNKNOWN: // Start of frame if ( (3500) <= width && width <= (4000) ) { #ifdef CLAS_O_DEBUG Serial.print(width); Serial.print(" - "); #endif state = T0; } else { return -1; // error, reset } break; case T0: // First half of pulse : HIGH around 230us if ( x_numBits == 32 ) { // end of frame state = DONE; x_data = (x_data >> 8); // Mask away some bits at the end return 1; } else if ( 340 <= width && width <= 560 ) { state = T1; } else { if ( x_numBits == 0 && (3500 <= width && width <= 4000) ) { state = T0; } else { #ifdef CLAS_O_DEBUG Serial.println(" X1X "); #endif return -1; // error, reset } } break; case T1: if ( 800 <= width && width <= 1000 ) { gotBit(0); } else if ( 1640 <= width && width <= 1940 ) { gotBit(1); } else { #ifdef CLAS_O_DEBUG Serial.println(" X2X "); #endif return -1; // error, reset } state = T0; break; } return 0; } boolean nextPulse( uint16_t width ) { if ( width > 0 ) { if (state != DONE) switch (decode(width)) { case -1: resetDecoder(); break; case 1: done(); break; } } return isDone(); } }