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

Committer:
charly
Date:
Wed Apr 27 19:02:00 2011 +0000
Revision:
0:b79cb3278583

        

Who changed what in which revision?

UserRevisionLine numberNew contents of line
charly 0:b79cb3278583 1 /** module for receiving data from eth comfort window sensor by ELV(R) with a RFM12 transceiver module by Hope
charly 0:b79cb3278583 2
charly 0:b79cb3278583 3 Details see discussion on http://www.mikrocontroller.net/topic/172034
charly 0:b79cb3278583 4 Frequenz 868,3
charly 0:b79cb3278583 5 Modulation FSK
charly 0:b79cb3278583 6 Hub +/- 15kHz
charly 0:b79cb3278583 7 Datenrate 10kbit Manchester
charly 0:b79cb3278583 8
charly 0:b79cb3278583 9 das Protokoll ist Machester codiert
charly 0:b79cb3278583 10 0x7e zz ll aa aa aa cmd crc crc
charly 0:b79cb3278583 11
charly 0:b79cb3278583 12 zz ist ein fortlaufender Zaehler
charly 0:b79cb3278583 13 ll die Blocklaenge 10,20,30 (20 = 9 Byte, 10= 10Byte ,30= ?)
charly 0:b79cb3278583 14 aa 3 Byte Adresse
charly 0:b79cb3278583 15 cmd der Befehl
charly 0:b79cb3278583 16 crc 16 bit checksumme
charly 0:b79cb3278583 17
charly 0:b79cb3278583 18 die Reihenfolge der Bits im Byte ist verdreht.
charly 0:b79cb3278583 19
charly 0:b79cb3278583 20 */
charly 0:b79cb3278583 21 /*!
charly 0:b79cb3278583 22 * \file eth_comfort.cpp
charly 0:b79cb3278583 23 * \brief Read the messages from the ETH-Radio-Shutter
charly 0:b79cb3278583 24 * \author Karl Zweimüller based on code from WED 6.9.2009
charly 0:b79cb3278583 25 */
charly 0:b79cb3278583 26
charly 0:b79cb3278583 27
charly 0:b79cb3278583 28 #include "eth_comfort.h"
charly 0:b79cb3278583 29
charly 0:b79cb3278583 30 /* orig AVR-values
charly 0:b79cb3278583 31 #define BIT_MAX 0x90
charly 0:b79cb3278583 32 #define BIT_MIN 0x10
charly 0:b79cb3278583 33 #define LEN_2T 0x44
charly 0:b79cb3278583 34 */
charly 0:b79cb3278583 35
charly 0:b79cb3278583 36 //working: 300-80-200
charly 0:b79cb3278583 37 // nominal values are: 208-104-208 for 9600 bits/sec
charly 0:b79cb3278583 38 #define BIT_MAX 300 // maximum allowed time for one or two bits high or low
charly 0:b79cb3278583 39 #define BIT_MIN 80 // minimum allowed time for one or two bits high or low
charly 0:b79cb3278583 40 #define LEN_2T 200 // time-value to differentiate one or two bit length
charly 0:b79cb3278583 41
charly 0:b79cb3278583 42
charly 0:b79cb3278583 43 // Timer for bit-length-measurement
charly 0:b79cb3278583 44 Timer BitTime;
charly 0:b79cb3278583 45
charly 0:b79cb3278583 46
charly 0:b79cb3278583 47 eth_comfort::eth_comfort(PinName mosi, PinName miso, PinName sclk, PinName nsel, PinName rxdata, PinName rxled) {
charly 0:b79cb3278583 48
charly 0:b79cb3278583 49 rfm12b_spi = new rfm12b(mosi,miso,sclk,nsel,rxdata);
charly 0:b79cb3278583 50
charly 0:b79cb3278583 51 // the ReceiveLED
charly 0:b79cb3278583 52 rxLED = new DigitalOut(rxled);
charly 0:b79cb3278583 53
charly 0:b79cb3278583 54 // init the eth_receiver
charly 0:b79cb3278583 55 init();
charly 0:b79cb3278583 56
charly 0:b79cb3278583 57 // Interrupt on every bit-change
charly 0:b79cb3278583 58 rfm12b_spi->attachISR(this, &eth_comfort::ISR);
charly 0:b79cb3278583 59
charly 0:b79cb3278583 60 // Init the RFM12B
charly 0:b79cb3278583 61 rfm12b_spi->RFM_init();
charly 0:b79cb3278583 62
charly 0:b79cb3278583 63 };
charly 0:b79cb3278583 64 //-------------------------------------------------------------------------
charly 0:b79cb3278583 65 // calcCRC16r()
charly 0:b79cb3278583 66 //-------------------------------------------------------------------------
charly 0:b79cb3278583 67 /**
charly 0:b79cb3278583 68 * @brief calculate reverse CRC
charly 0:b79cb3278583 69 * @param c 16bit value for crc
charly 0:b79cb3278583 70 * @param crc old crc value
charly 0:b79cb3278583 71 * @param mask crc polynom
charly 0:b79cb3278583 72 * @return crc value
charly 0:b79cb3278583 73 */
charly 0:b79cb3278583 74 uint16_t eth_comfort::calcCRC16r( uint16_t c,uint16_t crc, uint16_t mask) { // reverse crc!!!!!!
charly 0:b79cb3278583 75 uint8_t i;
charly 0:b79cb3278583 76 for (i=0;i<8;i++) {
charly 0:b79cb3278583 77 if ((crc ^ c) & 1) {
charly 0:b79cb3278583 78 crc=(crc>>1)^mask;
charly 0:b79cb3278583 79 } else crc>>=1;
charly 0:b79cb3278583 80 c>>=1;
charly 0:b79cb3278583 81 };
charly 0:b79cb3278583 82 return(crc);
charly 0:b79cb3278583 83 }
charly 0:b79cb3278583 84
charly 0:b79cb3278583 85 // initialize eth_receiver
charly 0:b79cb3278583 86 void eth_comfort::init() {
charly 0:b79cb3278583 87
charly 0:b79cb3278583 88 rbyte=0;
charly 0:b79cb3278583 89 bit_cnt=0;
charly 0:b79cb3278583 90 buffer_cnt=0;
charly 0:b79cb3278583 91 decode=0;
charly 0:b79cb3278583 92 pack_ok=0;
charly 0:b79cb3278583 93
charly 0:b79cb3278583 94 // start timer for bit-length-measurement
charly 0:b79cb3278583 95 BitTime.start();
charly 0:b79cb3278583 96 message_received = false;
charly 0:b79cb3278583 97 // init the buffer
charly 0:b79cb3278583 98 last_message.cnt = 0;
charly 0:b79cb3278583 99 last_message.len = 0;
charly 0:b79cb3278583 100 last_message.adr = 0;
charly 0:b79cb3278583 101 last_message.cmd = 0;
charly 0:b79cb3278583 102 last_message.data = 0;
charly 0:b79cb3278583 103 last_message.xdata = 0;
charly 0:b79cb3278583 104 last_message.crc = 0;
charly 0:b79cb3278583 105
charly 0:b79cb3278583 106 new_message = last_message;
charly 0:b79cb3278583 107 }
charly 0:b79cb3278583 108
charly 0:b79cb3278583 109
charly 0:b79cb3278583 110 // is a new message readable
charly 0:b79cb3278583 111 bool eth_comfort::readable() {
charly 0:b79cb3278583 112 return(message_received);
charly 0:b79cb3278583 113 }
charly 0:b79cb3278583 114
charly 0:b79cb3278583 115 // read a eth-messsage
charly 0:b79cb3278583 116 eth_message eth_comfort::getMessage() {
charly 0:b79cb3278583 117 if (readable()) {
charly 0:b79cb3278583 118 last_message = new_message;
charly 0:b79cb3278583 119 message_received = false;
charly 0:b79cb3278583 120 return(new_message);
charly 0:b79cb3278583 121 } else
charly 0:b79cb3278583 122 // we should return nothing here!
charly 0:b79cb3278583 123 return(last_message);
charly 0:b79cb3278583 124 }
charly 0:b79cb3278583 125
charly 0:b79cb3278583 126 /** ISR Interrupt routine for received data
charly 0:b79cb3278583 127 * triggers on every pin change high/low and low/high
charly 0:b79cb3278583 128 * does all the encoding of the signal including manchester decoding!
charly 0:b79cb3278583 129 * as the eth doesn't send a good signal, which the rfm12 could decode for himself
charly 0:b79cb3278583 130 * didn't test for myself - just got the code from someone else and ported to mbed!
charly 0:b79cb3278583 131 */
charly 0:b79cb3278583 132 void eth_comfort::ISR() { // pin change on rxin ->interrupt
charly 0:b79cb3278583 133 //led2=!led2;
charly 0:b79cb3278583 134 b=BitTime.read_us(); // time since last change
charly 0:b79cb3278583 135 BitTime.reset();
charly 0:b79cb3278583 136
charly 0:b79cb3278583 137 if ((b>BIT_MAX)||(b<BIT_MIN)) { // is bit time in range?
charly 0:b79cb3278583 138 state=0;
charly 0:b79cb3278583 139 } else {
charly 0:b79cb3278583 140
charly 0:b79cb3278583 141
charly 0:b79cb3278583 142 if (state==0) { // wait for first bitchange 2T
charly 0:b79cb3278583 143 if (b>LEN_2T)state=1;
charly 0:b79cb3278583 144 //if((rxin)!=0)state=0; // level should be low
charly 0:b79cb3278583 145 } else if (state<=10) { // wait for 5 fullbit without bitchange 10 shortbits
charly 0:b79cb3278583 146 if (b<LEN_2T)state++;
charly 0:b79cb3278583 147 else state=1; // bitchange found back to state 1
charly 0:b79cb3278583 148 } else if (state==11) { // now expecting bitchange (last bit in 7e is 0)
charly 0:b79cb3278583 149 if (b<LEN_2T) {
charly 0:b79cb3278583 150 state=0; // no bitchange -> back to search
charly 0:b79cb3278583 151 };
charly 0:b79cb3278583 152 state=20; // now we found 7e sync finished
charly 0:b79cb3278583 153 rbyte=0x7e; // set shift value to 0
charly 0:b79cb3278583 154 bit_cnt=8; // clear bitcounter
charly 0:b79cb3278583 155 buffer_cnt=0; // clear buffercounter
charly 0:b79cb3278583 156 bcnt=0;
charly 0:b79cb3278583 157 lastbit=0;
charly 0:b79cb3278583 158
charly 0:b79cb3278583 159 } else if (state==20) {
charly 0:b79cb3278583 160 if (b>LEN_2T) { // check for bitchange
charly 0:b79cb3278583 161 if (lastbit!=0) {
charly 0:b79cb3278583 162 rbyte=(rbyte>>1); // last bit was 1 new is 0
charly 0:b79cb3278583 163 bcnt=0;
charly 0:b79cb3278583 164 lastbit=0;
charly 0:b79cb3278583 165 } else {
charly 0:b79cb3278583 166 rbyte=(rbyte>>1)|0x80; // last bit was 0 new is 1
charly 0:b79cb3278583 167 bcnt++;
charly 0:b79cb3278583 168 lastbit=1;
charly 0:b79cb3278583 169 }
charly 0:b79cb3278583 170 state=20; // fullbit compleate
charly 0:b79cb3278583 171 bit_cnt++; // increase bit counter
charly 0:b79cb3278583 172 } else {
charly 0:b79cb3278583 173 state=21; // bit is halfbit, wait for next halfbit
charly 0:b79cb3278583 174 };
charly 0:b79cb3278583 175 } else if (state==21) { // no bitchange
charly 0:b79cb3278583 176 if (b<LEN_2T) { // next bit must be a halfbit
charly 0:b79cb3278583 177 if (lastbit==0) {
charly 0:b79cb3278583 178 rbyte=(rbyte>>1); // last bit was 0 new is 0
charly 0:b79cb3278583 179 lastbit=0;
charly 0:b79cb3278583 180 bcnt=0;
charly 0:b79cb3278583 181 } else {
charly 0:b79cb3278583 182 rbyte=(rbyte>>1)|0x80; // last bit was 1 new is 1
charly 0:b79cb3278583 183 lastbit=1;
charly 0:b79cb3278583 184 bcnt++;
charly 0:b79cb3278583 185 }
charly 0:b79cb3278583 186 state=20;
charly 0:b79cb3278583 187 bit_cnt++;
charly 0:b79cb3278583 188 } else {
charly 0:b79cb3278583 189 state=0; // bit is no halfbit -> Manchester violation
charly 0:b79cb3278583 190 // state=20;
charly 0:b79cb3278583 191 };
charly 0:b79cb3278583 192 } else if (state==22) { // after 5 bit 1 skip one bit 0
charly 0:b79cb3278583 193 if (b>LEN_2T) { // check for bitchange (next bit 0)
charly 0:b79cb3278583 194 lastbit=0;
charly 0:b79cb3278583 195 state=20;
charly 0:b79cb3278583 196 } else {
charly 0:b79cb3278583 197
charly 0:b79cb3278583 198 lastbit=1;
charly 0:b79cb3278583 199 //state=11;
charly 0:b79cb3278583 200 state=21;
charly 0:b79cb3278583 201 }
charly 0:b79cb3278583 202 bcnt=0;
charly 0:b79cb3278583 203
charly 0:b79cb3278583 204
charly 0:b79cb3278583 205 }
charly 0:b79cb3278583 206 if (bcnt==5)state=22;
charly 0:b79cb3278583 207
charly 0:b79cb3278583 208 if (bit_cnt>7) { // wait for 8 bits
charly 0:b79cb3278583 209 buf[buffer_cnt]=rbyte; // save value into buffer
charly 0:b79cb3278583 210 if (buffer_cnt<1020) {
charly 0:b79cb3278583 211 buffer_cnt++;
charly 0:b79cb3278583 212 };
charly 0:b79cb3278583 213 pack_ok=1; // set receiveflag
charly 0:b79cb3278583 214 bit_cnt=0; // clear bitcounter
charly 0:b79cb3278583 215 *rxLED = ! *rxLED; //show received byte
charly 0:b79cb3278583 216 //////////////////////////////////////////////////////////////////////////////////////////////////////////
charly 0:b79cb3278583 217 //here we received another byte
charly 0:b79cb3278583 218
charly 0:b79cb3278583 219 // we have to check if we are ready with the message
charly 0:b79cb3278583 220 if (buffer_cnt>8) {
charly 0:b79cb3278583 221 if (buf[2]==0x10) blocklength=10;
charly 0:b79cb3278583 222 else if (buf[2]==0x20) blocklength=9;
charly 0:b79cb3278583 223 else blocklength=99;
charly 0:b79cb3278583 224 j=0;
charly 0:b79cb3278583 225 crc_ok = false;
charly 0:b79cb3278583 226 for (i=0;i<=buffer_cnt;i++) {
charly 0:b79cb3278583 227 //pc.printf("%02X ",buf[i]);
charly 0:b79cb3278583 228 j++;
charly 0:b79cb3278583 229 if (j==blocklength) {
charly 0:b79cb3278583 230 //check crc
charly 0:b79cb3278583 231 if (blocklength==9) {
charly 0:b79cb3278583 232 crc=0xbdb7;
charly 0:b79cb3278583 233 for (k=0;k<7;k++) { // crc over first 7 byte
charly 0:b79cb3278583 234 crc=calcCRC16r(buf[k],crc,0x8408);
charly 0:b79cb3278583 235 }
charly 0:b79cb3278583 236 //swap the two crc-bytes
charly 0:b79cb3278583 237 swapped = ((crc >> 8) & 0xff) | ((crc << 8) & 0xff00);
charly 0:b79cb3278583 238 //pc.printf("CRC: %04X ",swapped);
charly 0:b79cb3278583 239 if (((buf[7]<<8) | buf[8]) == swapped) crc_ok = true;
charly 0:b79cb3278583 240 else crc_ok = false;
charly 0:b79cb3278583 241 //pc.printf("%s", (crc_ok==true) ? "OK" : "Not OK");
charly 0:b79cb3278583 242 if (crc_ok) {
charly 0:b79cb3278583 243 /*
charly 0:b79cb3278583 244 pc.printf("\n\rCounter: %02X\n\r",buf[1]);
charly 0:b79cb3278583 245 pc.printf( " Dev-ID: %02X %02X %02X\n\r",buf[3],buf[4],buf[5]);
charly 0:b79cb3278583 246 //pc.printf( "Battery: %s\n\r", (buf[6]&0x80 != 0x00) ? "WEAK" : "GOOD");
charly 0:b79cb3278583 247 pc.printf( "Window : %s\n\r\n\r", (buf[6]&0x01 != 0x00) ? "OPEN" : "CLOSE");
charly 0:b79cb3278583 248 lcd.cls();
charly 0:b79cb3278583 249 lcd.printf("#:%02X ID: %02X%02X%02X\n",buf[1],buf[3],buf[4],buf[5]);
charly 0:b79cb3278583 250 lcd.printf("Window : %s\n", (buf[6]&0x01 != 0x00) ? "OPEN" : "CLOSE");
charly 0:b79cb3278583 251 */
charly 0:b79cb3278583 252
charly 0:b79cb3278583 253 // insert buf into message
charly 0:b79cb3278583 254 new_message.cnt = buf[1];
charly 0:b79cb3278583 255 new_message.len = buf[2];
charly 0:b79cb3278583 256 new_message.adr = buf[3]<<16 | buf[4]<<8 | buf[5];
charly 0:b79cb3278583 257 new_message.cmd = buf[6];
charly 0:b79cb3278583 258 new_message.data = buf[7];
charly 0:b79cb3278583 259 new_message.xdata = 0;
charly 0:b79cb3278583 260 new_message.crc = swapped;
charly 0:b79cb3278583 261
charly 0:b79cb3278583 262 //is the new message different from the old message?
charly 0:b79cb3278583 263 // or is another sender on air?
charly 0:b79cb3278583 264 if ((new_message.cnt != last_message.cnt) || (new_message.adr != last_message.adr)) {
charly 0:b79cb3278583 265 last_message = new_message;
charly 0:b79cb3278583 266 message_received = true;
charly 0:b79cb3278583 267 }
charly 0:b79cb3278583 268
charly 0:b79cb3278583 269 } //crc_ok
charly 0:b79cb3278583 270 } //block_length = 9
charly 0:b79cb3278583 271 } //j==blocklength
charly 0:b79cb3278583 272 } //for
charly 0:b79cb3278583 273
charly 0:b79cb3278583 274
charly 0:b79cb3278583 275 //start receive from beginning
charly 0:b79cb3278583 276 buffer_cnt=0;
charly 0:b79cb3278583 277 bit_cnt=0;
charly 0:b79cb3278583 278 startbit=0;
charly 0:b79cb3278583 279 state=0;
charly 0:b79cb3278583 280 //pc.printf("\n\r-----------------------------\n\r");
charly 0:b79cb3278583 281 //clear the buffer
charly 0:b79cb3278583 282 for (i=0;i<1023;i++)buf[i]=0;
charly 0:b79cb3278583 283 *rxLED = 0; //turn off receive led
charly 0:b79cb3278583 284 } //buffer_cnt >8
charly 0:b79cb3278583 285 //////////////////////////////////////////////////////////////////////////////////////////////////////////
charly 0:b79cb3278583 286 //
charly 0:b79cb3278583 287 }
charly 0:b79cb3278583 288 }
charly 0:b79cb3278583 289
charly 0:b79cb3278583 290 }
charly 0:b79cb3278583 291
charly 0:b79cb3278583 292
charly 0:b79cb3278583 293
charly 0:b79cb3278583 294