#define RX 2 volatile byte level=255; volatile unsigned long last, len; byte p_level; unsigned long p_len, p_len_prev; struct { byte state; unsigned long TE; byte pre_count, data[8], dat_bit; } keeloq; struct { byte state; byte pre_count, data[8], dat_bit; } starline; struct { uint8_t state; uint8_t data[3], dat_bit; } came; void setbit(byte *data, byte n) { data[n/8]|=1<<(n%8); } #define KL_MIN_PRE_COUNT 4 #define KL_MAX_TE 500 #define KL_MIN_TE 300 #define KL_MAX_BITS 64 void process_keeloq() { switch(keeloq.state) { case 0: if(p_level) break; keeloq.state=1; keeloq.pre_count=0; break; case 1: //pre+hdr if(p_len>=KL_MIN_TE && p_len<=KL_MAX_TE) keeloq.pre_count++; else if(!p_level && p_len>=KL_MIN_TE*10 && p_len<=KL_MAX_TE*10 && keeloq.pre_count>=KL_MIN_PRE_COUNT) { keeloq.TE=p_len/10; keeloq.state=2; keeloq.dat_bit=0; keeloq.data[0]=0x00; keeloq.data[1]=0x00; keeloq.data[2]=0x00; keeloq.data[3]=0x00; keeloq.data[4]=0x00; keeloq.data[5]=0x00; keeloq.data[6]=0x00; keeloq.data[7]=0x00; } else { keeloq.state=0; break; } break; case 2: //dat if(!p_level) break; if(p_lenkeeloq.TE*3) { keeloq.state=0; break; } if(p_len<=keeloq.TE+keeloq.TE/2) setbit(keeloq.data, keeloq.dat_bit); if(++keeloq.dat_bit==KL_MAX_BITS) keeloq.state=100; break; } } #define SL_MIN_PRE_COUNT 4 #define SL_MAX_PRE 1150 #define SL_MIN_PRE 850 #define SL_MAX_ZERO 350 #define SL_MIN_ZERO 100 #define SL_MAX_ONE 700 #define SL_MIN_ONE 400 #define SL_MIN_BITS 16 #define SL_MAX_BITS 64 void process_starline() { byte b; switch(starline.state) { case 0: if(p_level) break; starline.state=1; starline.pre_count=0; break; case 1: //pre if(p_len>=SL_MIN_PRE && p_len<=SL_MAX_PRE) starline.pre_count++; else if(p_len=SL_MIN_PRE_COUNT) { starline.state=2; starline.dat_bit=0; starline.data[0]=0x00; starline.data[1]=0x00; starline.data[2]=0x00; starline.data[3]=0x00; starline.data[4]=0x00; starline.data[5]=0x00; starline.data[6]=0x00; starline.data[7]=0x00; } else { starline.state=0; break; } break; case 2: //dat if(p_level) break; if(p_len_prev>=SL_MIN_ONE && p_len_prev<=SL_MAX_ONE && p_len>=SL_MIN_ONE && p_len<=SL_MAX_ONE) b=1; else if(p_len_prev>=SL_MIN_ZERO && p_len_prev<=SL_MAX_ZERO && p_len>=SL_MIN_ZERO && p_len<=SL_MAX_ZERO) b=0; else { if(starline.dat_bit>=SL_MIN_BITS) starline.state=100; else starline.state=0; break; } if(b) setbit(starline.data, starline.dat_bit); if(++starline.dat_bit==SL_MAX_BITS) starline.state=100; break; } } #define TIMER_DIV #define CM_MAX_TE 450 #define CM_MIN_TE 250 #define CM_BITS12 12 #define CM_BITS24 24 void process_came() { unsigned char b; switch(came.state) { case 0: if(p_level) break; came.state=1; break; case 1: //start if(!p_level) break; if(p_len>CM_MIN_TE && p_len<=CM_MAX_TE) { came.dat_bit=0; came.data[0]=0x00; came.data[1]=0x00; came.data[2]=0x00; came.state=2; } else came.state=0; break; case 2: //dat if(p_level) { if(came.dat_bit==CM_BITS24) { came.state=0; break; } if(p_len_prev<=CM_MAX_TE && p_len_prev>=CM_MIN_TE && p_len<=CM_MAX_TE*2 && p_len>=CM_MIN_TE*2) b=0; else if(p_len_prev<=CM_MAX_TE*2 && p_len_prev>=CM_MIN_TE*2 && p_len<=CM_MAX_TE && p_len>=CM_MIN_TE) b=1; else { came.state=0; break; } if(b) setbit(came.data, came.dat_bit); came.dat_bit++; break; } else { if((p_len>5000) && (came.dat_bit==CM_BITS12 || came.dat_bit==CM_BITS24)) came.state=100; } break; } } void print_time() { unsigned long time = millis(); char tbs[32]; int dys = time / 86400000; int hr = (time - dys*86400000) / 3600000; int mn = (time - dys*86400000 - hr * 3600000) / 60000; int sc = (time - dys*86400000 - hr * 3600000 - mn * 60000) / 1000; sprintf(tbs, "[ %02dd %02dh %02dm %02ds]: ", dys, hr, mn, sc); /* Serial.print("["); Serial.print(hr); Serial.print("h"); Serial.print(mn); Serial.print("m"); Serial.print(sc); Serial.print("s"); Serial.print("]: "); */ Serial.print(tbs); } void dump_hex(byte *buf, byte bits) { byte a; for(a=0; a<(bits+7)/8; a++) { if(buf[a]<=0x0f) Serial.print('0'); Serial.print(buf[a], HEX); Serial.print(" "); } Serial.println(""); } void rx_int() { if(level!=255) return; len=micros()-last; last=micros(); if(digitalRead(RX)==HIGH) level=0; else level=1; } void setup() { attachInterrupt(0, rx_int, CHANGE); Serial.begin(115200); while(!Serial); Serial.println("STARLINE, CAME and KEELOQ receiver"); Serial.println(""); interrupts(); } byte a; void loop() { if(level!=255) { noInterrupts(); p_level=level; p_len=len; len=0; level=255; interrupts(); process_keeloq(); process_starline(); process_came(); p_len_prev=p_len; } if(keeloq.state==100) { Serial.print("KEELOQ: "); dump_hex(keeloq.data, 64); keeloq.state=0; } if(came.state==100) { print_time(); Serial.print("CAME: "); dump_hex(came.data, 24); came.state=0; } if(starline.state==100) { Serial.print("STARLINE["); Serial.print(starline.dat_bit); Serial.print("]: "); dump_hex(starline.data, starline.dat_bit); starline.state=0; } }