//#define TELLDUS_DEBUG //#define TELLDUS_RECORDER namespace telldus { enum { T0, T1, T2, OK, DONE }; static unsigned char state = T0; uint64_t x_data; uint8_t x_numBits; uint32_t meanPulseWidth = 0; uint8_t meanPulseWidthCnt = 0; void resetDecoder () { x_data = 0; x_numBits = 0; state = T0; meanPulseWidth = 0; meanPulseWidthCnt = 0; } 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 ) { static uint16_t firstPulse=0; #ifdef TELLDUS_RECORDER static uint8_t recTrigger=0; static uint16_t recorder[200]; static uint8_t recIdx = 0; recorder[recIdx] = width; recIdx++; if(recIdx==200) recIdx=0; if( recTrigger > 1 ) recTrigger--; if( recTrigger == 1 ) { recTrigger=0; for(uint8_t i=0; i<200;i++) { Serial.print("-"); Serial.print(recorder[recIdx]); recIdx++; if(recIdx==200) recIdx=0; } Serial.println(""); } #endif switch( state ) { case T0: // First half of pulse : HIGH around 910 if( x_numBits == 48 || (width > 5000 && x_numBits>=42) ) { // end of frame #ifdef TELLDUS_RECORDER recTrigger = 6; #endif meanPulseWidth /= meanPulseWidthCnt; state = DONE; return 1; } else if ( 780 <= width && width <= 1100 ) { firstPulse = width; state = T1; } else { #ifdef TELLDUS_DEBUG if( x_numBits > 0 ) { Serial.print(" E "); Serial.print(x_numBits); Serial.print(" ("); Serial.print(width); Serial.println("- )"); } #endif return -1; // error, reset } break; case T1: if( 360 <= width && width <= 640 ) { // 410 gotBit(1); #ifdef TELLDUS_DEBUG Serial.print(" ("); Serial.print(firstPulse); Serial.print("-"); Serial.print(width); Serial.print(") "); #endif } else if ( 1280 <= width && width <= 1560 ) { // 1290 #ifdef TELLDUS_DEBUG Serial.print(" ("); Serial.print(firstPulse); Serial.print("-"); Serial.print(width); Serial.print(") "); #endif gotBit(0); meanPulseWidth += width; meanPulseWidthCnt++; } else { #ifdef TELLDUS_DEBUG if( x_numBits > 0 ) { Serial.print(" E "); Serial.print(x_numBits); Serial.print(" ("); Serial.print(firstPulse); Serial.print("-"); Serial.print(width); Serial.println(")"); } #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(); } }