Program for decoding radio-signals sent by a ETH-Window-Shutter-Contact, received with a RFM12B-module. The messages are sent to KNX via a freebus rs-interface. Details see http://mbed.org/users/charly/notebook/connecting-a-radio-window-shutter-contact-to-knx/
Dependencies: TextLCD mbed ConfigFile
eth_comfort.cpp
- Committer:
- charly
- Date:
- 2011-04-27
- Revision:
- 0:b79cb3278583
File content as of revision 0:b79cb3278583:
/** module for receiving data from eth comfort window sensor by ELV(R) with a RFM12 transceiver module by Hope Details see discussion on http://www.mikrocontroller.net/topic/172034 Frequenz 868,3 Modulation FSK Hub +/- 15kHz Datenrate 10kbit Manchester das Protokoll ist Machester codiert 0x7e zz ll aa aa aa cmd crc crc zz ist ein fortlaufender Zaehler ll die Blocklaenge 10,20,30 (20 = 9 Byte, 10= 10Byte ,30= ?) aa 3 Byte Adresse cmd der Befehl crc 16 bit checksumme die Reihenfolge der Bits im Byte ist verdreht. */ /*! * \file eth_comfort.cpp * \brief Read the messages from the ETH-Radio-Shutter * \author Karl Zweimüller based on code from WED 6.9.2009 */ #include "eth_comfort.h" /* orig AVR-values #define BIT_MAX 0x90 #define BIT_MIN 0x10 #define LEN_2T 0x44 */ //working: 300-80-200 // nominal values are: 208-104-208 for 9600 bits/sec #define BIT_MAX 300 // maximum allowed time for one or two bits high or low #define BIT_MIN 80 // minimum allowed time for one or two bits high or low #define LEN_2T 200 // time-value to differentiate one or two bit length // Timer for bit-length-measurement Timer BitTime; eth_comfort::eth_comfort(PinName mosi, PinName miso, PinName sclk, PinName nsel, PinName rxdata, PinName rxled) { rfm12b_spi = new rfm12b(mosi,miso,sclk,nsel,rxdata); // the ReceiveLED rxLED = new DigitalOut(rxled); // init the eth_receiver init(); // Interrupt on every bit-change rfm12b_spi->attachISR(this, ð_comfort::ISR); // Init the RFM12B rfm12b_spi->RFM_init(); }; //------------------------------------------------------------------------- // calcCRC16r() //------------------------------------------------------------------------- /** * @brief calculate reverse CRC * @param c 16bit value for crc * @param crc old crc value * @param mask crc polynom * @return crc value */ uint16_t eth_comfort::calcCRC16r( uint16_t c,uint16_t crc, uint16_t mask) { // reverse crc!!!!!! uint8_t i; for (i=0;i<8;i++) { if ((crc ^ c) & 1) { crc=(crc>>1)^mask; } else crc>>=1; c>>=1; }; return(crc); } // initialize eth_receiver void eth_comfort::init() { rbyte=0; bit_cnt=0; buffer_cnt=0; decode=0; pack_ok=0; // start timer for bit-length-measurement BitTime.start(); message_received = false; // init the buffer last_message.cnt = 0; last_message.len = 0; last_message.adr = 0; last_message.cmd = 0; last_message.data = 0; last_message.xdata = 0; last_message.crc = 0; new_message = last_message; } // is a new message readable bool eth_comfort::readable() { return(message_received); } // read a eth-messsage eth_message eth_comfort::getMessage() { if (readable()) { last_message = new_message; message_received = false; return(new_message); } else // we should return nothing here! return(last_message); } /** ISR Interrupt routine for received data * triggers on every pin change high/low and low/high * does all the encoding of the signal including manchester decoding! * as the eth doesn't send a good signal, which the rfm12 could decode for himself * didn't test for myself - just got the code from someone else and ported to mbed! */ void eth_comfort::ISR() { // pin change on rxin ->interrupt //led2=!led2; b=BitTime.read_us(); // time since last change BitTime.reset(); if ((b>BIT_MAX)||(b<BIT_MIN)) { // is bit time in range? state=0; } else { if (state==0) { // wait for first bitchange 2T if (b>LEN_2T)state=1; //if((rxin)!=0)state=0; // level should be low } else if (state<=10) { // wait for 5 fullbit without bitchange 10 shortbits if (b<LEN_2T)state++; else state=1; // bitchange found back to state 1 } else if (state==11) { // now expecting bitchange (last bit in 7e is 0) if (b<LEN_2T) { state=0; // no bitchange -> back to search }; state=20; // now we found 7e sync finished rbyte=0x7e; // set shift value to 0 bit_cnt=8; // clear bitcounter buffer_cnt=0; // clear buffercounter bcnt=0; lastbit=0; } else if (state==20) { if (b>LEN_2T) { // check for bitchange if (lastbit!=0) { rbyte=(rbyte>>1); // last bit was 1 new is 0 bcnt=0; lastbit=0; } else { rbyte=(rbyte>>1)|0x80; // last bit was 0 new is 1 bcnt++; lastbit=1; } state=20; // fullbit compleate bit_cnt++; // increase bit counter } else { state=21; // bit is halfbit, wait for next halfbit }; } else if (state==21) { // no bitchange if (b<LEN_2T) { // next bit must be a halfbit if (lastbit==0) { rbyte=(rbyte>>1); // last bit was 0 new is 0 lastbit=0; bcnt=0; } else { rbyte=(rbyte>>1)|0x80; // last bit was 1 new is 1 lastbit=1; bcnt++; } state=20; bit_cnt++; } else { state=0; // bit is no halfbit -> Manchester violation // state=20; }; } else if (state==22) { // after 5 bit 1 skip one bit 0 if (b>LEN_2T) { // check for bitchange (next bit 0) lastbit=0; state=20; } else { lastbit=1; //state=11; state=21; } bcnt=0; } if (bcnt==5)state=22; if (bit_cnt>7) { // wait for 8 bits buf[buffer_cnt]=rbyte; // save value into buffer if (buffer_cnt<1020) { buffer_cnt++; }; pack_ok=1; // set receiveflag bit_cnt=0; // clear bitcounter *rxLED = ! *rxLED; //show received byte ////////////////////////////////////////////////////////////////////////////////////////////////////////// //here we received another byte // we have to check if we are ready with the message if (buffer_cnt>8) { if (buf[2]==0x10) blocklength=10; else if (buf[2]==0x20) blocklength=9; else blocklength=99; j=0; crc_ok = false; for (i=0;i<=buffer_cnt;i++) { //pc.printf("%02X ",buf[i]); j++; if (j==blocklength) { //check crc if (blocklength==9) { crc=0xbdb7; for (k=0;k<7;k++) { // crc over first 7 byte crc=calcCRC16r(buf[k],crc,0x8408); } //swap the two crc-bytes swapped = ((crc >> 8) & 0xff) | ((crc << 8) & 0xff00); //pc.printf("CRC: %04X ",swapped); if (((buf[7]<<8) | buf[8]) == swapped) crc_ok = true; else crc_ok = false; //pc.printf("%s", (crc_ok==true) ? "OK" : "Not OK"); if (crc_ok) { /* pc.printf("\n\rCounter: %02X\n\r",buf[1]); pc.printf( " Dev-ID: %02X %02X %02X\n\r",buf[3],buf[4],buf[5]); //pc.printf( "Battery: %s\n\r", (buf[6]&0x80 != 0x00) ? "WEAK" : "GOOD"); pc.printf( "Window : %s\n\r\n\r", (buf[6]&0x01 != 0x00) ? "OPEN" : "CLOSE"); lcd.cls(); lcd.printf("#:%02X ID: %02X%02X%02X\n",buf[1],buf[3],buf[4],buf[5]); lcd.printf("Window : %s\n", (buf[6]&0x01 != 0x00) ? "OPEN" : "CLOSE"); */ // insert buf into message new_message.cnt = buf[1]; new_message.len = buf[2]; new_message.adr = buf[3]<<16 | buf[4]<<8 | buf[5]; new_message.cmd = buf[6]; new_message.data = buf[7]; new_message.xdata = 0; new_message.crc = swapped; //is the new message different from the old message? // or is another sender on air? if ((new_message.cnt != last_message.cnt) || (new_message.adr != last_message.adr)) { last_message = new_message; message_received = true; } } //crc_ok } //block_length = 9 } //j==blocklength } //for //start receive from beginning buffer_cnt=0; bit_cnt=0; startbit=0; state=0; //pc.printf("\n\r-----------------------------\n\r"); //clear the buffer for (i=0;i<1023;i++)buf[i]=0; *rxLED = 0; //turn off receive led } //buffer_cnt >8 ////////////////////////////////////////////////////////////////////////////////////////////////////////// // } } }