#include //#include #include "pitches.h" //================================= // распиновка // модуль приемника ARDUINO // WL101-341/331 mini // // VIN 5V // DO любой D2 // GND GND // // тиристор // VCC D3 // GND GND // // пищалка // красный D8 // черный GND #define RX 2 #define RESET_EEPROM false // set to true when first upload byte NUMKEYS = 0; byte keys[100][5]; //============= Прошитые ключи ===================// //const byte NUMKEYS = 3; //byte keys[NUMKEYS][4] = {{0x7C,0xCA,0x28,0x08}, // {0x20,0x00,0x00,0x00}, // {0x25,0x00,0x00,0x00}}; //=================================================// volatile byte level=255; volatile unsigned long last, len; byte p_level, n, /*byte_key, */byte_btn; unsigned long p_len, p_len_prev; const byte tyrPin = 3; const byte ledPin = 13; unsigned long currentTime; boolean SwState = false; unsigned long listenProgTime, progModeTime; boolean listenProgBegin = false, progMode = false, isOurKey; byte listenProgCnt = 0; struct { byte state; unsigned long TE; byte pre_count, data[8], dat_bit; } keeloq; 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; } } void dump_hex(byte *buf, byte bits) { byte a; Serial.print(" "); 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 save_key(byte n, byte k1, byte k2, byte k3, byte keybtn) { eeprom_write_byte(4*n+1, k1); eeprom_write_byte(4*n+2, k2); eeprom_write_byte(4*n+3, k3); //keybtn = low 4 bits = permanent part of serial // high 4 bits = pressed buttons eeprom_write_byte(4*n+4, keybtn); keys[n][0] = k1; keys[n][1] = k2; keys[n][2] = k3; keys[n][3] = keybtn; } void setup() { Serial.begin(115200); while(!Serial); if( RESET_EEPROM ) // для первичной прошивки запишем ключи устанавлива RESET_EEPROM = true { NUMKEYS = 3; eeprom_write_byte(0, NUMKEYS); save_key(0, 0x7C,0xCA,0x28,0x88); save_key(1, 0x20,0x00,0x00,0x80); save_key(2, 0x25,0x00,0x00,0x80); } NUMKEYS = eeprom_read_byte(0); for(n = 0; n 10) { play_ready(); progMode = true; progModeTime = millis(); } } byte saved_btn = keys[n][4]& 0xF0; // if((keeloq.data[7]&0x80)==0x80) // теперь не только вторая кнопка может быть if((keeloq.data[7]&saved_btn)==saved_btn) { // Serial.print(" #2 - light on"); // не обязательно теперь вторая кнопка digitalWrite(ledPin, HIGH); currentTime = millis(); SwState = true; } if((keeloq.data[7]&0x40)==0x40) { Serial.println(" #4 - light force off"); // на тех пультах где есть эта кнопка - будет возможность форсированно выключать SwState = false; digitalWrite(ledPin, LOW); } } } if(!isOurKey) { Serial.println("NOT OUR KEY!"); if(progMode) { Serial.print(" prog mode = must save key: "); if(NUMKEYS < 100) { save_key(NUMKEYS, keeloq.data[4],keeloq.data[5],keeloq.data[6],keeloq.data[7]); NUMKEYS++; eeprom_update_byte(0, NUMKEYS); play_win(); } else { Serial.print(" prog mode = but 100 keys limit reached :( "); play_StarWars(); } } } } }