Programm for decoding radio-signals sent by a ETH-Window-Shutter-Contact, received with a RFM12B-module

Dependencies:   TextLCD mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers eth_comfort.cpp Source File

eth_comfort.cpp

Go to the documentation of this file.
00001 /** module for receiving data from eth comfort window sensor by ELV(R) with a RFM12 transceiver module by Hope
00002 
00003   Details see discussion on http://www.mikrocontroller.net/topic/172034
00004   Frequenz 868,3
00005   Modulation FSK
00006   Hub +/- 15kHz
00007   Datenrate 10kbit Manchester
00008 
00009   das Protokoll ist Machester codiert
00010   0x7e zz ll aa aa aa cmd crc crc
00011 
00012   zz ist ein fortlaufender Zaehler
00013   ll die Blocklaenge 10,20,30 (20 = 9 Byte, 10= 10Byte ,30= ?)
00014   aa 3 Byte Adresse
00015   cmd der Befehl
00016   crc 16 bit checksumme
00017 
00018   die Reihenfolge der Bits im Byte ist verdreht.
00019 
00020 */
00021 /*!
00022  * \file       eth_comfort.cpp
00023  * \brief      Read the messages from the ETH-Radio-Shutter
00024  * \author     Karl Zweimüller based on code from WED 6.9.2009
00025  */
00026 
00027 
00028 #include "eth_comfort.h"
00029 
00030 /* orig AVR-values
00031 #define BIT_MAX 0x90
00032 #define BIT_MIN 0x10
00033 #define LEN_2T 0x44
00034 */
00035 
00036 //working: 300-80-200
00037 // nominal values are: 208-104-208 for 9600 bits/sec
00038 #define BIT_MAX 300                         // maximum allowed time for one or two bits high or low
00039 #define BIT_MIN 80                          // minimum allowed time for one or two bits high or low
00040 #define LEN_2T 200                          // time-value to differentiate one or two bit length
00041 
00042 
00043 // Timer for bit-length-measurement
00044 Timer BitTime;
00045 
00046 
00047 eth_comfort::eth_comfort(PinName mosi, PinName miso, PinName sclk, PinName nsel, PinName rxdata, PinName rxled) {
00048 
00049     rfm12b_spi = new rfm12b(mosi,miso,sclk,nsel,rxdata);
00050 
00051     // the ReceiveLED
00052     rxLED = new DigitalOut(rxled);
00053 
00054     // init the eth_receiver
00055     init();
00056 
00057     // Interrupt on every bit-change
00058     rfm12b_spi->attachISR(this, &eth_comfort::ISR);
00059 
00060     // Init the RFM12B
00061     rfm12b_spi->RFM_init();
00062 
00063 };
00064 //-------------------------------------------------------------------------
00065 // calcCRC16r()
00066 //-------------------------------------------------------------------------
00067 /**
00068  * @brief calculate reverse CRC
00069  * @param c 16bit value for crc
00070  * @param crc old crc value
00071  * @param mask crc polynom
00072  * @return crc value
00073  */
00074 uint16_t eth_comfort::calcCRC16r( uint16_t c,uint16_t crc, uint16_t mask) { // reverse crc!!!!!!
00075     uint8_t  i;
00076     for (i=0;i<8;i++) {
00077         if ((crc ^ c) & 1) {
00078             crc=(crc>>1)^mask;
00079         } else crc>>=1;
00080         c>>=1;
00081     };
00082     return(crc);
00083 }
00084 
00085 // initialize eth_receiver
00086 void eth_comfort::init() {
00087 
00088     rbyte=0;
00089     bit_cnt=0;
00090     buffer_cnt=0;
00091     decode=0;
00092     pack_ok=0;
00093 
00094     // start timer for bit-length-measurement
00095     BitTime.start();
00096     message_received = false;
00097     // init the buffer
00098     last_message.cnt = 0;
00099     last_message.len = 0;
00100     last_message.adr = 0;
00101     last_message.cmd = 0;
00102     last_message.data = 0;
00103     last_message.xdata = 0;
00104     last_message.crc = 0;
00105 
00106     new_message = last_message;
00107 }
00108 
00109 
00110 // is a new message readable
00111 bool eth_comfort::readable() {
00112     return(message_received);
00113 }
00114 
00115 // read a eth-messsage
00116 eth_message eth_comfort::getMessage() {
00117     if (readable()) {
00118         last_message = new_message;
00119         message_received = false;
00120         return(new_message);
00121     } else
00122         // we should return nothing here!
00123         return(last_message);
00124 }
00125 
00126 /** ISR Interrupt routine for received data
00127   * triggers on every pin change high/low and low/high
00128   * does all the encoding of the signal including manchester decoding!
00129   * as the eth doesn't send a good signal, which the rfm12 could decode for himself
00130   * didn't test for myself - just got the code from someone else and ported to mbed!
00131 */
00132 void eth_comfort::ISR() {  // pin change on rxin ->interrupt
00133     //led2=!led2;
00134     b=BitTime.read_us();                                      // time since last change
00135     BitTime.reset();
00136 
00137     if ((b>BIT_MAX)||(b<BIT_MIN)) {                           // is bit time in range?
00138         state=0;
00139     } else {
00140 
00141 
00142         if (state==0) {                                // wait for first bitchange 2T
00143             if (b>LEN_2T)state=1;
00144             //if((rxin)!=0)state=0;                      // level should be low
00145         } else if (state<=10) {                         // wait for 5 fullbit without bitchange 10 shortbits
00146             if (b<LEN_2T)state++;
00147             else state=1;                              // bitchange found back to state 1
00148         } else if (state==11) {                         // now expecting bitchange (last bit in 7e is 0)
00149             if (b<LEN_2T) {
00150                 state=0;                               // no bitchange -> back to search
00151             };
00152             state=20;                                  // now we found 7e sync finished
00153             rbyte=0x7e;                                // set shift value to 0
00154             bit_cnt=8;                                 // clear bitcounter
00155             buffer_cnt=0;                              // clear buffercounter
00156             bcnt=0;
00157             lastbit=0;
00158 
00159         } else if (state==20) {
00160             if (b>LEN_2T) {                              // check for bitchange
00161                 if (lastbit!=0) {
00162                     rbyte=(rbyte>>1);                     // last bit was 1 new is 0
00163                     bcnt=0;
00164                     lastbit=0;
00165                 } else {
00166                     rbyte=(rbyte>>1)|0x80;              // last bit was 0 new is 1
00167                     bcnt++;
00168                     lastbit=1;
00169                 }
00170                 state=20;                                // fullbit compleate
00171                 bit_cnt++;                            // increase bit counter
00172             } else {
00173                 state=21;                                // bit is halfbit, wait for next halfbit
00174             };
00175         } else if (state==21) {                         // no bitchange
00176             if (b<LEN_2T) {                              // next bit must be a halfbit
00177                 if (lastbit==0) {
00178                     rbyte=(rbyte>>1);  // last bit was 0 new is 0
00179                     lastbit=0;
00180                     bcnt=0;
00181                 } else {
00182                     rbyte=(rbyte>>1)|0x80;              // last bit was 1 new is 1
00183                     lastbit=1;
00184                     bcnt++;
00185                 }
00186                 state=20;
00187                 bit_cnt++;
00188             } else {
00189                 state=0;                            // bit is no halfbit -> Manchester violation
00190                 // state=20;
00191             };
00192         } else if (state==22) {                         // after 5 bit 1 skip one bit 0
00193             if (b>LEN_2T) {                              // check for bitchange (next bit 0)
00194                 lastbit=0;
00195                 state=20;
00196             } else {
00197 
00198                 lastbit=1;
00199                 //state=11;
00200                 state=21;
00201             }
00202             bcnt=0;
00203 
00204 
00205         }
00206         if (bcnt==5)state=22;
00207 
00208         if (bit_cnt>7) {                              // wait for 8 bits
00209             buf[buffer_cnt]=rbyte;                    // save value into buffer
00210             if (buffer_cnt<1020) {
00211                 buffer_cnt++;
00212             };
00213             pack_ok=1;                                // set receiveflag
00214             bit_cnt=0;                                // clear bitcounter
00215             *rxLED = ! *rxLED;                              //show received byte
00216             //////////////////////////////////////////////////////////////////////////////////////////////////////////
00217             //here we received another byte
00218 
00219             // we have to check  if we are ready with the message
00220             if (buffer_cnt>8) {
00221                 if     (buf[2]==0x10) blocklength=10;
00222                 else if (buf[2]==0x20) blocklength=9;
00223                 else                  blocklength=99;
00224                 j=0;
00225                 crc_ok = false;
00226                 for (i=0;i<=buffer_cnt;i++) {
00227                     //pc.printf("%02X ",buf[i]);
00228                     j++;
00229                     if (j==blocklength) {
00230                         //check crc
00231                         if (blocklength==9) {
00232                             crc=0xbdb7;
00233                             for (k=0;k<7;k++) {                         // crc over first 7 byte
00234                                 crc=calcCRC16r(buf[k],crc,0x8408);
00235                             }
00236                             //swap the two crc-bytes
00237                             swapped = ((crc >> 8) & 0xff) | ((crc << 8) & 0xff00);
00238                             //pc.printf("CRC: %04X ",swapped);
00239                             if (((buf[7]<<8) | buf[8]) == swapped) crc_ok = true;
00240                             else crc_ok = false;
00241                             //pc.printf("%s", (crc_ok==true) ? "OK" : "Not OK");
00242                             if (crc_ok) {
00243                                 /*
00244                                 pc.printf("\n\rCounter: %02X\n\r",buf[1]);
00245                                 pc.printf(    " Dev-ID: %02X %02X %02X\n\r",buf[3],buf[4],buf[5]);
00246                                 //pc.printf(    "Battery: %s\n\r", (buf[6]&0x80 != 0x00) ? "WEAK" : "GOOD");
00247                                 pc.printf(    "Window : %s\n\r\n\r", (buf[6]&0x01 != 0x00) ? "OPEN" : "CLOSE");
00248                                 lcd.cls();
00249                                 lcd.printf("#:%02X ID: %02X%02X%02X\n",buf[1],buf[3],buf[4],buf[5]);
00250                                 lcd.printf("Window : %s\n", (buf[6]&0x01 != 0x00) ? "OPEN" : "CLOSE");
00251                                 */
00252 
00253                                 // insert buf into message
00254                                 new_message.cnt = buf[1];
00255                                 new_message.len = buf[2];
00256                                 new_message.adr = buf[3]<<16 | buf[4]<<8 | buf[5];
00257                                 new_message.cmd = buf[6];
00258                                 new_message.data = buf[7];
00259                                 new_message.xdata = 0;
00260                                 new_message.crc = swapped;
00261 
00262                                 //is the new message different from the old message?
00263                                 if (new_message.cnt != last_message.cnt) {
00264                                     last_message = new_message;
00265                                     message_received = true;
00266                                 }
00267 
00268                             } //crc_ok
00269                         } //block_length = 9
00270                     } //j==blocklength
00271                 } //for
00272 
00273 
00274                 //start receive from beginning
00275                 buffer_cnt=0;
00276                 bit_cnt=0;
00277                 startbit=0;
00278                 state=0;
00279                 //pc.printf("\n\r-----------------------------\n\r");
00280                 //clear the buffer
00281                 for (i=0;i<1023;i++)buf[i]=0;
00282                 *rxLED = 0;           //turn off receive led
00283             } //buffer_cnt >8
00284             //////////////////////////////////////////////////////////////////////////////////////////////////////////
00285             //
00286         }
00287     }
00288 
00289 }
00290 
00291 
00292 
00293