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

Dependencies:   TextLCD mbed

Committer:
charly
Date:
Thu Apr 07 19:54:09 2011 +0000
Revision:
1:fc72e0bdb693
Parent:
0:96794c9fc5a3
Reorganized and created classes for RFM12B and ETH-Comfort

Who changed what in which revision?

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