Karl Zweimüller
/
eth_comfort_test
Programm for decoding radio-signals sent by a ETH-Window-Shutter-Contact, received with a RFM12B-module
Revision 0:96794c9fc5a3, committed 2011-03-02
- Comitter:
- charly
- Date:
- Wed Mar 02 20:46:57 2011 +0000
- Child:
- 1:fc72e0bdb693
- Commit message:
- Initial pre-beta version
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/TextLCD.lib Wed Mar 02 20:46:57 2011 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/simon/code/TextLCD/#44f34c09bd37
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/eth_comfort.cpp Wed Mar 02 20:46:57 2011 +0000 @@ -0,0 +1,204 @@ +/** 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. + +*/ + + +// WED 6.9.2009 +// extended and adapeted to mbed by Karl Zweimueller 1/2011 + + +#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 + + +volatile uint16_t b; + +volatile uint8_t transmit,bit_cnt; +volatile uint16_t buffer_cnt; + + +volatile unsigned char old ; +volatile uint8_t rbyte; + +volatile uint8_t buf[1024]; +volatile uint8_t pack_ok,startbit; +volatile uint8_t decode,bcnt,lastbit; +volatile uint8_t state; + +// Timer for bit-length-measurement +Timer BitTime; + +//------------------------------------------------------------------------- +// 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 calcCRC16r( uint16_t c,uint16_t crc, uint16_t mask) // reverser 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_init() +{ + // start timer for bit-length-measurement + BitTime.start(); + +} + +// +// +// + +/** 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 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 + led3= !led3; //show received byte + + // + }; + }; + +} + + + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/eth_comfort.h Wed Mar 02 20:46:57 2011 +0000 @@ -0,0 +1,45 @@ +#ifndef ETH_COMFORT_H +#define ETH_COMFORT_H + +#include "mbed.h" + + + + +extern volatile uint8_t transmit,start,phase,bit_cnt,data; +extern volatile uint16_t buffer_cnt; + + +extern volatile unsigned char old ; + +extern volatile uint8_t rbyte; + +extern volatile uint8_t buf[1024]; +extern volatile uint8_t pack_ok,startbit; +extern volatile uint8_t decode,bcnt,lastbit; +extern volatile uint8_t state; + +struct eth_message{ + uint8_t cnt; + uint8_t len; + uint32_t adr; + uint8_t cmd; + uint8_t data; + uint8_t xdata; + uint16_t crc; +}; + +// led3 shows received bits +extern DigitalOut led3; + +// calcualte the crc for eth +uint16_t calcCRC16r( uint16_t c,uint16_t crc, uint16_t mask); + +// initialize eth_comfort-receiver +void eth_init(); + +// interupt-routine for received data +void ISR(); + +#endif +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Wed Mar 02 20:46:57 2011 +0000 @@ -0,0 +1,143 @@ +#include "mbed.h" + +#include "TextLCD.h" + +TextLCD lcd(p30, p29, p28, p27, p26, p25, TextLCD::LCD16x2); // rs, e, d0-d3 + +#include "eth_comfort.h" +#include "rfm.h" +#include "rfm12b.h" + +rfm12b rfm12b_spi(p11, p12, p13, p14, p18); // mosi, miso, sclk, cs, rxdata + + +Serial pc(USBTX, USBRX); // tx, rx + +// mbed LEDs +DigitalOut led1(LED1); +DigitalOut led2(LED2); +DigitalOut led3(LED3); +DigitalOut led4(LED4); + + + +//--------------------------------------------------------------------- + +void init(void) +{ + + + rbyte=0; + bit_cnt=0; + buffer_cnt=0; + + decode=0; + + pack_ok=0; // this will be set by ISR, when byte was received + + + // init the eth_receiver + eth_init(); + + // Interrupt on every bit-change + rfm12b_spi.attachISR(&ISR); + + // Init the RFM12B + rfm12b_spi.RFM_init(); + +} + +//--------------------------------------------------------------------- +// +//--------------------------------------------------------------------- + +int main() +{ +uint8_t blocklength=0; +unsigned int i,j=0,k; +unsigned long timeout=0; +unsigned long tick=0; +uint16_t crc, swapped; +bool crc_ok = false; + + pc.baud(115200); + + pc.printf("\n\rConnected to mbed\n\r"); + lcd.printf("Hello!\n"); + + init(); + + // state =start + startbit=0; + do{ + + if (pack_ok==1){ + timeout=0; + pack_ok=0; + j=0; + }; + if(timeout<10000){ + timeout++; + } + else if(timeout==10000){ + 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"); + } + } + pc.printf("\n\r"); + } + } + + + //start receive from beginning + buffer_cnt=0; + bit_cnt=0; + timeout++; + startbit=0; + state=0; + + pc.printf("\n\r-----------------------------\n\r"); + for(i=0;i<1023;i++)buf[i]=0; + }; + timeout = 0; + }; + tick++; + //delay_ms(100); + if(tick>=2000000){ + tick=0; + led1= !led1; + led3=0; // reset receive-led + }; +}while(1==1); + +} + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed.bld Wed Mar 02 20:46:57 2011 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/mbed_official/code/mbed/builds/63bcd7ba4912
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rfm.h Wed Mar 02 20:46:57 2011 +0000 @@ -0,0 +1,502 @@ +/* + * Open HR20 + * + * target: ATmega169 @ 4 MHz in Honnywell Rondostat HR20E + * + * compiler: WinAVR-20071221 + * avr-libc 1.6.0 + * GCC 4.2.2 + * + * copyright: 2008 Dario Carluccio (hr20-at-carluccio-dot-de) + * 2008 Jiri Dobry (jdobry-at-centrum-dot-cz) + * 2008 Mario Fischer (MarioFischer-at-gmx-dot-net) + * 2007 Michael Smola (Michael-dot-Smola-at-gmx-dot-net) + * + * license: This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see http:*www.gnu.org/licenses + */ + +/*! + * \file rfm.h + * \brief functions to control the RFM12 Radio Transceiver Module + * \author Mario Fischer <MarioFischer-at-gmx-dot-net>; Michael Smola <Michael-dot-Smola-at-gmx-dot-net> + * \date $Date: 2010/04/17 17:57:02 $ + * $Rev: 260 $ + */ + +//#pragma once // multi-iclude prevention. gcc knows this pragma +#ifndef rfm_H +#define rfm_H + + +#define RFM_SPI_16(OUTVAL) rfm_spi16(OUTVAL) //<! a function that gets a uint16_t (clocked out value) and returns a uint16_t (clocked in value) + +#define RFM_CLK_OUTPUT 0 + + +#define RFM_TESTPIN_INIT +#define RFM_TESTPIN_ON +#define RFM_TESTPIN_OFF +#define RFM_TESTPIN_TOG + +#define RFM_CONFIG_DISABLE 0x00 //<! RFM_CONFIG_*** are combinable flags, what the RFM shold do +#define RFM_CONFIG_BROADCASTSTATUS 0x01 //<! Flag that enables the HR20's status broadcast every minute + +#define RFM_CONFIG_ENABLEALL 0xff + + +/////////////////////////////////////////////////////////////////////////////// +// +// RFM status bits +// +/////////////////////////////////////////////////////////////////////////////// + +// Interrupt bits, latched //////////////////////////////////////////////////// + +#define RFM_STATUS_FFIT 0x8000 // RX FIFO reached the progr. number of bits + // Cleared by any FIFO read method + +#define RFM_STATUS_RGIT 0x8000 // TX register is ready to receive + // Cleared by TX write + +#define RFM_STATUS_POR 0x4000 // Power On reset + // Cleared by read status + +#define RFM_STATUS_RGUR 0x2000 // TX register underrun, register over write + // Cleared by read status + +#define RFM_STATUS_FFOV 0x2000 // RX FIFO overflow + // Cleared by read status + +#define RFM_STATUS_WKUP 0x1000 // Wake up timer overflow + // Cleared by read status + +#define RFM_STATUS_EXT 0x0800 // Interupt changed to low + // Cleared by read status + +#define RFM_STATUS_LBD 0x0400 // Low battery detect + +// Status bits //////////////////////////////////////////////////////////////// + +#define RFM_STATUS_FFEM 0x0200 // FIFO is empty +#define RFM_STATUS_ATS 0x0100 // TX mode: Strong enough RF signal +#define RFM_STATUS_RSSI 0x0100 // RX mode: signal strength above programmed limit +#define RFM_STATUS_DQD 0x0080 // Data Quality detector output +#define RFM_STATUS_CRL 0x0040 // Clock recovery lock +#define RFM_STATUS_ATGL 0x0020 // Toggling in each AFC cycle + +/////////////////////////////////////////////////////////////////////////////// +// +// 1. Configuration Setting Command +// +/////////////////////////////////////////////////////////////////////////////// + +#define RFM_CONFIG 0x8000 + +#define RFM_CONFIG_EL 0x8080 // Enable TX Register +#define RFM_CONFIG_EF 0x8040 // Enable RX FIFO buffer +#define RFM_CONFIG_BAND_315 0x8000 // Frequency band +#define RFM_CONFIG_BAND_433 0x8010 +#define RFM_CONFIG_BAND_868 0x8020 +#define RFM_CONFIG_BAND_915 0x8030 +#define RFM_CONFIG_X_8_5pf 0x8000 // Crystal Load Capacitor +#define RFM_CONFIG_X_9_0pf 0x8001 +#define RFM_CONFIG_X_9_5pf 0x8002 +#define RFM_CONFIG_X_10_0pf 0x8003 +#define RFM_CONFIG_X_10_5pf 0x8004 +#define RFM_CONFIG_X_11_0pf 0x8005 +#define RFM_CONFIG_X_11_5pf 0x8006 +#define RFM_CONFIG_X_12_0pf 0x8007 +#define RFM_CONFIG_X_12_5pf 0x8008 +#define RFM_CONFIG_X_13_0pf 0x8009 +#define RFM_CONFIG_X_13_5pf 0x800A +#define RFM_CONFIG_X_14_0pf 0x800B +#define RFM_CONFIG_X_14_5pf 0x800C +#define RFM_CONFIG_X_15_0pf 0x800D +#define RFM_CONFIG_X_15_5pf 0x800E +#define RFM_CONFIG_X_16_0pf 0x800F + +/////////////////////////////////////////////////////////////////////////////// +// +// 2. Power Management Command +// +/////////////////////////////////////////////////////////////////////////////// + +#define RFM_POWER_MANAGEMENT 0x8200 + +#define RFM_POWER_MANAGEMENT_ER 0x8280 // Enable receiver +#define RFM_POWER_MANAGEMENT_EBB 0x8240 // Enable base band block +#define RFM_POWER_MANAGEMENT_ET 0x8220 // Enable transmitter +#define RFM_POWER_MANAGEMENT_ES 0x8210 // Enable synthesizer +#define RFM_POWER_MANAGEMENT_EX 0x8208 // Enable crystal oscillator +#define RFM_POWER_MANAGEMENT_EB 0x8204 // Enable low battery detector +#define RFM_POWER_MANAGEMENT_EW 0x8202 // Enable wake-up timer +#define RFM_POWER_MANAGEMENT_DC 0x8201 // Disable clock output of CLK pin + +#ifndef RFM_CLK_OUTPUT + #error RFM_CLK_OUTPUT must be defined to 0 or 1 +#endif +#if RFM_CLK_OUTPUT + #define RFM_TX_ON_PRE() RFM_SPI_16( \ + RFM_POWER_MANAGEMENT_ES | \ + RFM_POWER_MANAGEMENT_EX ) + #define RFM_TX_ON() RFM_SPI_16( \ + RFM_POWER_MANAGEMENT_ET | \ + RFM_POWER_MANAGEMENT_ES | \ + RFM_POWER_MANAGEMENT_EX ) + #define RFM_RX_ON() RFM_SPI_16( \ + RFM_POWER_MANAGEMENT_ER | \ + RFM_POWER_MANAGEMENT_EBB | \ + RFM_POWER_MANAGEMENT_ES | \ + RFM_POWER_MANAGEMENT_EX ) + #define RFM_OFF() RFM_SPI_16( \ + RFM_POWER_MANAGEMENT_EX ) +#else + #define RFM_TX_ON_PRE() RFM_SPI_16( \ + RFM_POWER_MANAGEMENT_DC | \ + RFM_POWER_MANAGEMENT_ES | \ + RFM_POWER_MANAGEMENT_EX ) + #define RFM_TX_ON() RFM_SPI_16( \ + RFM_POWER_MANAGEMENT_DC | \ + RFM_POWER_MANAGEMENT_ET | \ + RFM_POWER_MANAGEMENT_ES | \ + RFM_POWER_MANAGEMENT_EX ) + #define RFM_RX_ON() RFM_SPI_16( \ + RFM_POWER_MANAGEMENT_DC | \ + RFM_POWER_MANAGEMENT_ER | \ + RFM_POWER_MANAGEMENT_EBB | \ + RFM_POWER_MANAGEMENT_ES | \ + RFM_POWER_MANAGEMENT_EX ) + #define RFM_OFF() RFM_SPI_16(RFM_POWER_MANAGEMENT_DC) +#endif +/////////////////////////////////////////////////////////////////////////////// +// +// 3. Frequency Setting Command +// +/////////////////////////////////////////////////////////////////////////////// + +#define RFM_FREQUENCY 0xA000 + +#define RFM_FREQ_315Band(v) (uint16_t)((v/10.0-31)*4000) +#define RFM_FREQ_433Band(v) (uint16_t)((v/10.0-43)*4000) +#define RFM_FREQ_868Band(v) (uint16_t)((v/20.0-43)*4000) +#define RFM_FREQ_915Band(v) (uint16_t)((v/30.0-30)*4000) + +/////////////////////////////////////////////////////////////////////////////// +// +// 4. Data Rate Command +// +///////////////////////////////////////////////////////////////////////////////// + +#define RFM_BAUD_RATE 9600 + +#define RFM_DATA_RATE 0xC600 + +#define RFM_DATA_RATE_CS 0xC680 +#define RFM_DATA_RATE_4800 0xC647 +#define RFM_DATA_RATE_9600 0xC623 +#define RFM_DATA_RATE_19200 0xC611 +#define RFM_DATA_RATE_38400 0xC608 +#define RFM_DATA_RATE_57600 0xC605 + +#define RFM_SET_DATARATE(baud) ( ((baud)<5400) ? (RFM_DATA_RATE_CS|((43104/(baud))-1)) : (RFM_DATA_RATE|((344828UL/(baud))-1)) ) + +/////////////////////////////////////////////////////////////////////////////// +// +// 5. Receiver Control Command +// +/////////////////////////////////////////////////////////////////////////////// + +#define RFM_RX_CONTROL 0x9000 + +#define RFM_RX_CONTROL_P20_INT 0x9000 // Pin20 = ExternalInt +#define RFM_RX_CONTROL_P20_VDI 0x9400 // Pin20 = VDI out + +#define RFM_RX_CONTROL_VDI_FAST 0x9000 // fast VDI Response time +#define RFM_RX_CONTROL_VDI_MED 0x9100 // medium +#define RFM_RX_CONTROL_VDI_SLOW 0x9200 // slow +#define RFM_RX_CONTROL_VDI_ON 0x9300 // Always on + +#define RFM_RX_CONTROL_BW_400 0x9020 // bandwidth 400kHz +#define RFM_RX_CONTROL_BW_340 0x9040 // bandwidth 340kHz +#define RFM_RX_CONTROL_BW_270 0x9060 // bandwidth 270kHz +#define RFM_RX_CONTROL_BW_200 0x9080 // bandwidth 200kHz +#define RFM_RX_CONTROL_BW_134 0x90A0 // bandwidth 134kHz +#define RFM_RX_CONTROL_BW_67 0x90C0 // bandwidth 67kHz + +#define RFM_RX_CONTROL_GAIN_0 0x9000 // LNA gain 0db +#define RFM_RX_CONTROL_GAIN_6 0x9008 // LNA gain -6db +#define RFM_RX_CONTROL_GAIN_14 0x9010 // LNA gain -14db +#define RFM_RX_CONTROL_GAIN_20 0x9018 // LNA gain -20db + +#define RFM_RX_CONTROL_RSSI_103 0x9000 // DRSSI threshold -103dbm +#define RFM_RX_CONTROL_RSSI_97 0x9001 // DRSSI threshold -97dbm +#define RFM_RX_CONTROL_RSSI_91 0x9002 // DRSSI threshold -91dbm +#define RFM_RX_CONTROL_RSSI_85 0x9003 // DRSSI threshold -85dbm +#define RFM_RX_CONTROL_RSSI_79 0x9004 // DRSSI threshold -79dbm +#define RFM_RX_CONTROL_RSSI_73 0x9005 // DRSSI threshold -73dbm +//#define RFM_RX_CONTROL_RSSI_67 0x9006 // DRSSI threshold -67dbm // RF12B reserved +//#define RFM_RX_CONTROL_RSSI_61 0x9007 // DRSSI threshold -61dbm // RF12B reserved + +#define RFM_RX_CONTROL_BW(baud) (((baud)<8000) ? \ + RFM_RX_CONTROL_BW_67 : \ + ( \ + ((baud)<30000) ? \ + RFM_RX_CONTROL_BW_134 : \ + RFM_RX_CONTROL_BW_200 \ + )) + +/////////////////////////////////////////////////////////////////////////////// +// +// 6. Data Filter Command +// +/////////////////////////////////////////////////////////////////////////////// + +#define RFM_DATA_FILTER 0xC228 + +#define RFM_DATA_FILTER_AL 0xC2A8 // clock recovery auto-lock +#define RFM_DATA_FILTER_ML 0xC268 // clock recovery fast mode +#define RFM_DATA_FILTER_DIG 0xC228 // data filter type digital +#define RFM_DATA_FILTER_ANALOG 0xC238 // data filter type analog +#define RFM_DATA_FILTER_DQD(level) (RFM_DATA_FILTER | (level & 0x7)) + +/////////////////////////////////////////////////////////////////////////////// +// +// 7. FIFO and Reset Mode Command +// +/////////////////////////////////////////////////////////////////////////////// + +#define RFM_FIFO 0xCA00 + +#define RFM_FIFO_AL 0xCA04 // FIFO Start condition sync-word/always +#define RFM_FIFO_FF 0xCA02 // Enable FIFO fill +#define RFM_FIFO_DR 0xCA01 // Disable hi sens reset mode +#define RFM_FIFO_IT(level) (RFM_FIFO | (( (level) & 0xF)<<4)) + +#define RFM_FIFO_OFF() RFM_SPI_16(RFM_FIFO_IT(8) | RFM_FIFO_DR) +#define RFM_FIFO_ON() RFM_SPI_16(RFM_FIFO_IT(8) | RFM_FIFO_FF | RFM_FIFO_DR) + +///////////////////////////////////////////////////////////////////////////// +// +// 8. Receiver FIFO Read +// +///////////////////////////////////////////////////////////////////////////// + +#define RFM_READ_FIFO() (RFM_SPI_16(0xB000) & 0xFF) + +///////////////////////////////////////////////////////////////////////////// +// +// 9. AFC Command +// +///////////////////////////////////////////////////////////////////////////// + +#define RFM_AFC 0xC400 + +#define RFM_AFC_EN 0xC401 +#define RFM_AFC_OE 0xC402 +#define RFM_AFC_FI 0xC404 +#define RFM_AFC_ST 0xC408 + +// Limits the value of the frequency offset register to the next values: + +#define RFM_AFC_RANGE_LIMIT_NO 0xC400 // 0: No restriction +#define RFM_AFC_RANGE_LIMIT_15_16 0xC410 // 1: +15 fres to -16 fres +#define RFM_AFC_RANGE_LIMIT_7_8 0xC420 // 2: +7 fres to -8 fres +#define RFM_AFC_RANGE_LIMIT_3_4 0xC430 // 3: +3 fres to -4 fres + +// fres=2.5 kHz in 315MHz and 433MHz Bands +// fres=5.0 kHz in 868MHz Band +// fres=7.5 kHz in 915MHz Band + +#define RFM_AFC_AUTO_OFF 0xC400 // 0: Auto mode off (Strobe is controlled by microcontroller) +#define RFM_AFC_AUTO_ONCE 0xC440 // 1: Runs only once after each power-up +#define RFM_AFC_AUTO_VDI 0xC480 // 2: Keep the foffset only during receiving(VDI=high) +#define RFM_AFC_AUTO_INDEPENDENT 0xC4C0 // 3: Keep the foffset value independently trom the state of the VDI signal + +/////////////////////////////////////////////////////////////////////////////// +// +// 10. TX Configuration Control Command +// +/////////////////////////////////////////////////////////////////////////////// + +#define RFM_TX_CONTROL 0x9800 + +#define RFM_TX_CONTROL_POW_0 0x9800 +#define RFM_TX_CONTROL_POW_3 0x9801 +#define RFM_TX_CONTROL_POW_6 0x9802 +#define RFM_TX_CONTROL_POW_9 0x9803 +#define RFM_TX_CONTROL_POW_12 0x9804 +#define RFM_TX_CONTROL_POW_15 0x9805 +#define RFM_TX_CONTROL_POW_18 0x9806 +#define RFM_TX_CONTROL_POW_21 0x9807 +#define RFM_TX_CONTROL_MOD_15 0x9800 +#define RFM_TX_CONTROL_MOD_30 0x9810 +#define RFM_TX_CONTROL_MOD_45 0x9820 +#define RFM_TX_CONTROL_MOD_60 0x9830 +#define RFM_TX_CONTROL_MOD_75 0x9840 +#define RFM_TX_CONTROL_MOD_90 0x9850 +#define RFM_TX_CONTROL_MOD_105 0x9860 +#define RFM_TX_CONTROL_MOD_120 0x9870 +#define RFM_TX_CONTROL_MOD_135 0x9880 +#define RFM_TX_CONTROL_MOD_150 0x9890 +#define RFM_TX_CONTROL_MOD_165 0x98A0 +#define RFM_TX_CONTROL_MOD_180 0x98B0 +#define RFM_TX_CONTROL_MOD_195 0x98C0 +#define RFM_TX_CONTROL_MOD_210 0x98D0 +#define RFM_TX_CONTROL_MOD_225 0x98E0 +#define RFM_TX_CONTROL_MOD_240 0x98F0 +#define RFM_TX_CONTROL_MP 0x9900 + +#define RFM_TX_CONTROL_MOD(baud) (((baud)<8000) ? \ + RFM_TX_CONTROL_MOD_45 : \ + ( \ + ((baud)<20000) ? \ + RFM_TX_CONTROL_MOD_60 : \ + ( \ + ((baud)<30000) ? \ + RFM_TX_CONTROL_MOD_75 : \ + ( \ + ((baud)<40000) ? \ + RFM_TX_CONTROL_MOD_90 : \ + RFM_TX_CONTROL_MOD_120 \ + ) \ + ) \ + )) + +///////////////////////////////////////////////////////////////////////////// +// +// 11. Transmitter Register Write Command +// +///////////////////////////////////////////////////////////////////////////// + +//#define RFM_WRITE(byte) RFM_SPI_16(0xB800 | ((byte) & 0xFF)) +#define RFM_WRITE(byte) RFM_SPI_16(0xB800 | (byte) ) + +/////////////////////////////////////////////////////////////////////////////// +// +// 12. Wake-up Timer Command +// +/////////////////////////////////////////////////////////////////////////////// + +#define RFM_WAKEUP_TIMER 0xE000 +#define RFM_WAKEUP_SET(time) RFM_SPI_16(RFM_WAKEUP_TIMER | (time)) + +#define RFM_WAKEUP_480s (RFM_WAKEUP_TIMER |(11 << 8)| 234) +#define RFM_WAKEUP_240s (RFM_WAKEUP_TIMER |(10 << 8)| 234) +#define RFM_WAKEUP_120s (RFM_WAKEUP_TIMER |(9 << 8)| 234) +#define RFM_WAKEUP_119s (RFM_WAKEUP_TIMER |(9 << 8)| 232) + +#define RFM_WAKEUP_60s (RFM_WAKEUP_TIMER |(8 << 8) | 235) +#define RFM_WAKEUP_59s (RFM_WAKEUP_TIMER |(8 << 8) | 230) + +#define RFM_WAKEUP_30s (RFM_WAKEUP_TIMER |(7 << 8) | 235) +#define RFM_WAKEUP_29s (RFM_WAKEUP_TIMER |(7 << 8) | 227) + +#define RFM_WAKEUP_8s (RFM_WAKEUP_TIMER |(5 << 8) | 250) +#define RFM_WAKEUP_7s (RFM_WAKEUP_TIMER |(5 << 8) | 219) +#define RFM_WAKEUP_6s (RFM_WAKEUP_TIMER |(6 << 8) | 94) +#define RFM_WAKEUP_5s (RFM_WAKEUP_TIMER |(5 << 8) | 156) +#define RFM_WAKEUP_4s (RFM_WAKEUP_TIMER |(5 << 8) | 125) +#define RFM_WAKEUP_1s (RFM_WAKEUP_TIMER |(2 << 8) | 250) +#define RFM_WAKEUP_900ms (RFM_WAKEUP_TIMER |(2 << 8) | 225) +#define RFM_WAKEUP_800ms (RFM_WAKEUP_TIMER |(2 << 8) | 200) +#define RFM_WAKEUP_700ms (RFM_WAKEUP_TIMER |(2 << 8) | 175) +#define RFM_WAKEUP_600ms (RFM_WAKEUP_TIMER |(2 << 8) | 150) +#define RFM_WAKEUP_500ms (RFM_WAKEUP_TIMER |(2 << 8) | 125) +#define RFM_WAKEUP_400ms (RFM_WAKEUP_TIMER |(2 << 8) | 100) +#define RFM_WAKEUP_300ms (RFM_WAKEUP_TIMER |(2 << 8) | 75) +#define RFM_WAKEUP_200ms (RFM_WAKEUP_TIMER |(2 << 8) | 50) +#define RFM_WAKEUP_100ms (RFM_WAKEUP_TIMER |(2 << 8) | 25) + +/////////////////////////////////////////////////////////////////////////////// +// +// 13. Low Duty-Cycle Command +// +/////////////////////////////////////////////////////////////////////////////// + +#define RFM_LOW_DUTY_CYCLE 0xC800 + +/////////////////////////////////////////////////////////////////////////////// +// +// 14. Low Battery Detector Command +// +/////////////////////////////////////////////////////////////////////////////// + +#define RFM_LOW_BATT_DETECT 0xC000 +#define RFM_LOW_BATT_DETECT_D_1MHZ 0xC000 +#define RFM_LOW_BATT_DETECT_D_1_25MHZ 0xC020 +#define RFM_LOW_BATT_DETECT_D_1_66MHZ 0xC040 +#define RFM_LOW_BATT_DETECT_D_2MHZ 0xC060 +#define RFM_LOW_BATT_DETECT_D_2_5MHZ 0xC080 +#define RFM_LOW_BATT_DETECT_D_3_33MHZ 0xC0A0 +#define RFM_LOW_BATT_DETECT_D_5MHZ 0xC0C0 +#define RFM_LOW_BATT_DETECT_D_10MHZ 0xC0E0 + +/////////////////////////////////////////////////////////////////////////////// +// +// 15. Status Read Command +// +/////////////////////////////////////////////////////////////////////////////// + +#define RFM_READ_STATUS() RFM_SPI_16(0x0000) +#define RFM_READ_STATUS_FFIT() SPI_1 (0x00) +#define RFM_READ_STATUS_RGIT RFM_READ_STATUS_FFIT + +/////////////////////////////////////////////////////////////////////////////// + +#include <stdint.h> +void RFM_init(void); +uint16_t rfm_spi16(uint16_t outval); + +/////////////////////////////////////////////////////////////////////////////// + +// RFM air protocol flags: + +#define RFMPROTO_FLAGS_BITASK_PACKETTYPE 0b11000000 //!< the uppermost 2 bits of the flags field encode the packettype +#define RFMPROTO_FLAGS_PACKETTYPE_BROADCAST 0b00000000 //!< broadcast packettype (message from hr20, protocol; step 1) +#define RFMPROTO_FLAGS_PACKETTYPE_COMMAND 0b01000000 //!< command packettype (message to hr20, protocol; step 2) +#define RFMPROTO_FLAGS_PACKETTYPE_REPLY 0b10000000 //!< reply packettype (message from hr20, protocol; step 3) +#define RFMPROTO_FLAGS_PACKETTYPE_SPECIAL 0b11000000 //!< currently unused packettype + +#define RFMPROTO_FLAGS_BITASK_DEVICETYPE 0b00011111 //!< the lowermost 5 bytes denote the device type. this way other sensors and actors may coexist +#define RFMPROTO_FLAGS_DEVICETYPE_OPENHR20 0b00010100 //!< topen HR20 device type. 10100 is for decimal 20 + +#define RFMPROTO_IS_PACKETTYPE_BROADCAST(FLAGS) ( RFMPROTO_FLAGS_PACKETTYPE_BROADCAST == ((FLAGS) & RFMPROTO_FLAGS_BITASK_PACKETTYPE) ) +#define RFMPROTO_IS_PACKETTYPE_COMMAND(FLAGS) ( RFMPROTO_FLAGS_PACKETTYPE_COMMAND == ((FLAGS) & RFMPROTO_FLAGS_BITASK_PACKETTYPE) ) +#define RFMPROTO_IS_PACKETTYPE_REPLY(FLAGS) ( RFMPROTO_FLAGS_PACKETTYPE_REPLY == ((FLAGS) & RFMPROTO_FLAGS_BITASK_PACKETTYPE) ) +#define RFMPROTO_IS_PACKETTYPE_SPECIAL(FLAGS) ( RFMPROTO_FLAGS_PACKETTYPE_SPECIAL == ((FLAGS) & RFMPROTO_FLAGS_BITASK_PACKETTYPE) ) +#define RFMPROTO_IS_DEVICETYPE_OPENHR20(FLAGS) ( RFMPROTO_FLAGS_DEVICETYPE_OPENHR20 == ((FLAGS) & RFMPROTO_FLAGS_BITASK_DEVICETYPE) ) + +/////////////////////////////////////////////////////////////////////////////// + +// RFM send and receive buffer: + +#define RFM_FRAME_MAX 80 + +typedef enum {rfmmode_stop=0, + rfmmode_start_tx=1, + rfmmode_tx=2, + rfmmode_tx_done=3, + rfmmode_rx=4, + rfmmode_rx_owf=5, + } rfm_mode_t; + +extern uint8_t rfm_framebuf[RFM_FRAME_MAX]; +extern uint8_t rfm_framesize; +extern uint8_t rfm_framepos; +extern rfm_mode_t rfm_mode; + +#define rfm_start_tx() +// (rfm_mode=rfmmode_start_tx) + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rfm12b.cpp Wed Mar 02 20:46:57 2011 +0000 @@ -0,0 +1,144 @@ +#include "mbed.h" +#include "rfm12b.h" +#include "rfm.h" + +/** Class rfm12b for RFM12B transceiver module + http://www.hoperf.com/rf_fsk/rfm12b.htm +*/ + +/** rfm12b object +*/ +rfm12b::rfm12b(PinName mosi, PinName miso, PinName sclk, PinName nsel, PinName rxdata){ + + rfm12b_spi = new SPI(mosi, miso, sclk); // mosi, miso, sclk + cs = new DigitalOut(nsel); // nsel for chipselect + m_pinRXData = new InterruptIn(rxdata); // rxData- generates interrupts + + init_spi(); // init the spi-device +} + + /** init the spi-communication + */ +void rfm12b::init_spi(){ + // Setup the spi for 16 bit data : 1RW-bit 7 adressbit, 8 databit + // second edge capture, with a 5MHz clock rate + rfm12b_spi->format(16,0); + rfm12b_spi->frequency(5000000); +} + +/////////////////////////////////////////////////////////////////////////////// +// +// Initialise RF module +// This are parameters for ETH Comfort by ELV +/////////////////////////////////////////////////////////////////////////////// +void rfm12b::RFM_init(void) +{ + + // 0. Init the SPI backend + //RFM_TESTPIN_INIT; + + //RFM_READ_STATUS(); + + // 1. Configuration Setting Command + RFM_SPI_16( + //RFM_CONFIG_EL | + //RFM_CONFIG_EF | + RFM_CONFIG_BAND_868 | + RFM_CONFIG_X_11_0pf + ); + + // 2. Power Management Command + //RFM_SPI_16( + // RFM_POWER_MANAGEMENT // switch all off + // ); + + // 3. Frequency Setting Command + RFM_SPI_16( + RFM_FREQUENCY | + RFM_FREQ_868Band(868.30) + ); + + // 4. Data Rate Command + RFM_SPI_16(RFM_DATA_RATE_9600); + + // 5. Receiver Control Command + RFM_SPI_16( + RFM_RX_CONTROL_P20_VDI | + RFM_RX_CONTROL_VDI_FAST | + //RFM_RX_CONTROL_BW(RFM_BAUD_RATE) | + RFM_RX_CONTROL_BW_134 | + RFM_RX_CONTROL_GAIN_0 | + RFM_RX_CONTROL_RSSI_73 + ); + + // 6. Data Filter Command + RFM_SPI_16( + //RFM_DATA_FILTER_AL | + //RFM_DATA_FILTER_ML | + //RFM_DATA_FILTER_DQD(3) + RFM_DATA_FILTER_ANALOG + ); + + // 7. FIFO and Reset Mode Command + RFM_SPI_16( + RFM_FIFO_IT(8) | + RFM_FIFO_DR + ); + + // 8. Receiver FIFO Read + + // 9. AFC Command + RFM_SPI_16( + RFM_AFC_AUTO_VDI | + RFM_AFC_RANGE_LIMIT_7_8 | + RFM_AFC_EN | + RFM_AFC_OE | + RFM_AFC_FI + ); + + // 10. TX Configuration Control Command + RFM_SPI_16( + RFM_TX_CONTROL_MOD_30 | + RFM_TX_CONTROL_POW_0 + ); + + // 11. Transmitter Register Write Command + + // 12. Wake-Up Timer Command + + // 13. Low Duty-Cycle Command + + // 14. Low Battery Detector Command + + //RFM_SPI_16( + // RFM_LOW_BATT_DETECT | + // 3 // 2.2V + v * 0.1V + // ); + + // 15. Status Read Command + //RFM_SPI_16(RFM_TX_ON()); + RFM_SPI_16(RFM_RX_ON()); + +} + +/////////////////////////////////////////////////////////////////////////////// + + + +/** write and read 16 bit to device +*/ +uint16_t rfm12b::rfm_spi16(uint16_t outval){ + + uint16_t readval; + // Select the device by seting chip select low + cs->write(0); + wait_ms(1); // wait before going on + //write and read + readval = rfm12b_spi->write(outval); + // Deselect the device + cs->write(1); + wait_ms(1); // wait before going on + return(readval); +} + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rfm12b.h Wed Mar 02 20:46:57 2011 +0000 @@ -0,0 +1,59 @@ +#ifndef rfm12B_H +#define rfm12B_H + +#include <mbed.h> + +typedef unsigned char Byte; // used to be uint8_t : something a byte wide, whatever .... + +/** This Class handles a rfm12b transceiver + * see http://www.hoperf.com/rf_fsk/rfm12b.htm + * +*/ +class rfm12b +{ +public: + /** Create a rfm12b object + * + * @param mosi SPI-Interface. One of the 2 PSI-Interfaces of mbed. Pin p5 or p11 + * @param miso SPI-Interface. One of the 2 PSI-Interfaces of mbed. Pin p6 or p12 + * @param sclk SPI-Interface. One of the 2 PSI-Interfaces of mbed. Pin p7 or p13 + * @param nsel Chip-Select. A Digial Output of mbed + * @param rxdata Data-Pin for received data. A DigitalIn of mbed + */ + rfm12b(PinName mosi, PinName miso, PinName sclk, PinName nsel, PinName rxdata); + + /** init the spi-interface + */ + void init_spi(); + + /** initialize the device + */ + void RFM_init(void); + + /** write and read 16 bit + */ + uint16_t rfm_spi16(uint16_t outval); + + /** attach a function to be called when the data-pin changes from 0->1 and from 1->0 + * this function has to do all the decoding + * keep this function short, as no interrrupts can occour within + * + * @param fptr Pointer to callback-function + */ + void attachISR(void (*fptr)(void)) { + m_pinRXData->fall(fptr); + m_pinRXData->rise(fptr); + } + + +private: + + + DigitalOut *cs; //chipselect + InterruptIn *m_pinRXData; //rx data pin + SPI *rfm12b_spi; //spi-interface + + +}; + +#endif