Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- //
- // (C)opyright yoyolb - 2014/08/05
- // Version 0.1
- //
- // Tested with Arduino UNO and:
- // - RX module RR3-433 (433.92 MHz) => port A1
- // - TX module RT4-433 (433.92 MHz) => port A0
- //
- // Modified by jondoe - 2015/01/01
- // Link to used RF-Modules: http://www.amazon.de/gp/product/B00OLI93IC
- //
- #define PORT_TX A0
- #define PORT 2 // Arduino UNO = A1
- // To store pulse length, in microseconds
- volatile word pulse;
- // Interrupt handler
- #if defined(__AVR_ATmega1280__)
- void ext_int_1(void) {
- #else
- ISR(ANALOG_COMP_vect) {
- #endif
- static word last;
- // determine the pulse length in microseconds, for either polarity
- pulse = micros() - last;
- last += pulse;
- }
- void setup () {
- Serial.begin(115200);
- Serial.println("\n[SomfyDecoder]");
- pinMode(PORT_TX, OUTPUT);
- digitalWrite(PORT_TX, 0);
- #if !defined(__AVR_ATmega1280__)
- pinMode(PORT, INPUT); // use the AIO pin
- digitalWrite(PORT, 1); // enable pull-up
- // use analog comparator to switch at 1.1V bandgap transition
- ACSR = _BV(ACBG) | _BV(ACI) | _BV(ACIE);
- // set ADC mux to the proper port
- ADCSRA &= ~ bit(ADEN);
- ADCSRB |= bit(ACME);
- ADMUX = PORT - 1;
- #else
- attachInterrupt(1, ext_int_1, CHANGE);
- DDRE &= ~_BV(PE5);
- PORTE &= ~_BV(PE5);
- #endif
- }
- // Microseconds
- const word k_tempo_wakeup_pulse = 9415;
- const word k_tempo_wakeup_silence = 89565;
- const word k_tempo_synchro_hw = 2416;
- const word k_tempo_synchro_hw_min = 2416*0.7;
- const word k_tempo_synchro_hw_max = 2416*1.3;
- const word k_tempo_synchro_sw = 4550;
- const word k_tempo_synchro_sw_min = 4550*0.7;
- const word k_tempo_synchro_sw_max = 4550*1.3;
- const word k_tempo_half_symbol = 604;
- const word k_tempo_half_symbol_min = 604*0.7;
- const word k_tempo_half_symbol_max = 604*1.3;
- const word k_tempo_symbol = 1208;
- const word k_tempo_symbol_min = 1208*0.7;
- const word k_tempo_symbol_max = 1208*1.3;
- const word k_tempo_inter_frame_gap = 30415;
- class CCodecSomfyRTS {
- public:
- enum t_status {
- k_waiting_synchro,
- k_receiving_data,
- k_complete
- };
- public:
- CCodecSomfyRTS();
- t_status pulse(word p);
- bool decode();
- bool transmit(byte cmd, unsigned long rolling_code, unsigned long address);
- protected:
- t_status _status;
- byte _cpt_synchro_hw;
- byte _cpt_bits;
- byte _previous_bit;
- bool _waiting_half_symbol;
- byte _payload[7];
- };
- CCodecSomfyRTS::CCodecSomfyRTS()
- : _status(k_waiting_synchro)
- , _cpt_synchro_hw(0)
- , _cpt_bits(0)
- , _previous_bit(0)
- , _waiting_half_symbol(false) {
- for(int i=0; i<7; ++i) _payload[i] = 0;
- }
- CCodecSomfyRTS::t_status CCodecSomfyRTS::pulse(word p) {
- switch(_status) {
- case k_waiting_synchro:
- if (p > k_tempo_synchro_hw_min && p < k_tempo_synchro_hw_max) {
- ++_cpt_synchro_hw;
- }
- else if (p > k_tempo_synchro_sw_min && p < k_tempo_synchro_sw_max && _cpt_synchro_hw >= 4) {
- _cpt_bits = 0;
- _previous_bit = 0;
- _waiting_half_symbol = false;
- for(int i=0; i<7; ++i) _payload[i] = 0;
- _status = k_receiving_data;
- } else {
- _cpt_synchro_hw = 0;
- }
- break;
- case k_receiving_data:
- if (p > k_tempo_symbol_min && p < k_tempo_symbol_max && !_waiting_half_symbol) {
- _previous_bit = 1 - _previous_bit;
- _payload[_cpt_bits/8] += _previous_bit << (7 - _cpt_bits%8);
- ++_cpt_bits;
- } else if (p > k_tempo_half_symbol_min && p < k_tempo_half_symbol_max) {
- if (_waiting_half_symbol) {
- _waiting_half_symbol = false;
- _payload[_cpt_bits/8] += _previous_bit << (7 - _cpt_bits%8);
- ++_cpt_bits;
- } else {
- _waiting_half_symbol = true;
- }
- } else {
- _cpt_synchro_hw = 0;
- _status = k_waiting_synchro;
- }
- break;
- default:
- Serial.println("Internal error !");
- break;
- }
- t_status retval = _status;
- if (_status == k_receiving_data && _cpt_bits == 56) {
- retval = k_complete;
- decode();
- _status = k_waiting_synchro;
- }
- return retval;
- }
- bool CCodecSomfyRTS::decode() {
- // Dé-obfuscation
- byte frame[7];
- frame[0] = _payload[0];
- for(int i = 1; i < 7; ++i) frame[i] = _payload[i] ^ _payload[i-1];
- Serial.print("Payload: ");
- for(int i = 0; i < 7; ++i) Serial.print(frame[i], HEX);
- Serial.println("");
- // Verification du checksum
- byte cksum = 0;
- for(int i = 0; i < 7; ++i) cksum = cksum ^ frame[i] ^ (frame[i] >> 4);
- cksum = cksum & 0x0F;
- if (cksum != 0) Serial.println("Checksum incorrect !");
- // Touche de controle
- switch(frame[1] & 0xF0) {
- case 0x10: Serial.println("My"); break;
- case 0x20: Serial.println("Up"); break;
- case 0x40: Serial.println("Down"); break;
- case 0x80: Serial.println("Prog"); break;
- default: Serial.println("???"); break;
- }
- // Rolling code
- unsigned long rolling_code = (frame[2] << 8) + frame[3];
- Serial.print("Rolling code: "); Serial.println(rolling_code);
- // Adresse
- unsigned long address = ((unsigned long)frame[4] << 16) + (frame[5] << 8) + frame[6];
- }
- bool CCodecSomfyRTS::transmit(byte cmd, unsigned long rolling_code, unsigned long address) {
- // Construction de la trame claire
- byte data[7];
- data[0] = 0xA1;
- data[1] = cmd << 4;
- data[2] = (rolling_code & 0xFF00) >> 8;
- data[3] = rolling_code & 0x00FF;
- data[4] = (address & 0xFF00) >> 16;
- data[5] = (address & 0xFF00) >> 8;
- data[6] = address & 0x00FF;
- // Calcul du checksum
- byte cksum = 0;
- for(int i = 0; i < 7; ++i) cksum = cksum ^ data[i] ^ (data[i] >> 4);
- data[1] = data[1] + (cksum & 0x0F);
- Serial.print("Sending: ");
- for(int i = 0; i < 7; ++i) Serial.print(data[i], HEX);
- Serial.print(" ... ");
- // Obsufscation
- for(int i = 1; i < 7; ++i) data[i] = data[i] ^ data[i-1];
- // Emission wakeup, synchro hardware et software
- digitalWrite(PORT_TX, 1);
- delayMicroseconds(k_tempo_wakeup_pulse);
- digitalWrite(PORT_TX, 0);
- delayMicroseconds(k_tempo_wakeup_silence);
- for(int i=0; i<7; ++i) {
- digitalWrite(PORT_TX, 1);
- delayMicroseconds(k_tempo_synchro_hw);
- digitalWrite(PORT_TX, 0);
- delayMicroseconds(k_tempo_synchro_hw);
- }
- digitalWrite(PORT_TX, 1);
- delayMicroseconds(k_tempo_synchro_sw);
- digitalWrite(PORT_TX, 0);
- delayMicroseconds(k_tempo_half_symbol);
- // Emission des donnees
- for(int i=0; i<56;++i) {
- byte bit_to_transmit = (data[i/8] >> (7 - i%8)) & 0x01;
- if (bit_to_transmit == 0) {
- digitalWrite(PORT_TX, 1);
- delayMicroseconds(k_tempo_half_symbol);
- digitalWrite(PORT_TX, 0);
- delayMicroseconds(k_tempo_half_symbol);
- }
- else
- {
- digitalWrite(PORT_TX, 0);
- delayMicroseconds(k_tempo_half_symbol);
- digitalWrite(PORT_TX, 1);
- delayMicroseconds(k_tempo_half_symbol);
- }
- }
- digitalWrite(PORT_TX, 0);
- delayMicroseconds(k_tempo_inter_frame_gap);
- Serial.println("Done.");
- }
- int bufferCount;
- char buffer[80];
- void loop() {
- static CCodecSomfyRTS codecSomfyRTS;
- static word cpt = 0;
- cli();
- word p = pulse;
- pulse = 0;
- sei();
- // example: Send to serial: U457,0x6832203#
- while(Serial.available()) {
- char ch = Serial.read();
- buffer[bufferCount] = ch;
- bufferCount++;
- if (ch == '#') {
- byte cmd;
- switch(buffer[0]) {
- case 'U':
- cmd = 0x20;
- break;
- case 'D':
- cmd = 0x40;
- break;
- case 'M':
- cmd = 0x10;
- break;
- case 'P':
- cmd = 0x80;
- break;
- }
- int comma;
- int hash;
- for( int i = 1; i < sizeof(buffer); ++i ) {
- if(buffer[i] == ',') {
- comma = i;
- }else if(buffer[i] == '#') {
- hash = i;
- }
- }
- char temp1[(comma-1)];
- memcpy(&temp1, &buffer[1], (comma-1) * sizeof(char));
- unsigned long roll_code = atoi(temp1);
- char temp2[8];
- memcpy(&temp2, &buffer[comma+1], sizeof(temp2));
- unsigned long address = strtol(temp2,NULL,16);
- codecSomfyRTS.transmit(cmd, roll_code, address);
- bufferCount = 0;
- memset(buffer, 0, sizeof(buffer));
- }
- }
- if (p != 0) {
- codecSomfyRTS.pulse(p);
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement