/*============================================================================== rf12.h HOPE RF12 FSK Transceiver Library Written by Ervin Jung (2010) Based on: HOPE RF, RF12B programming guide -------------------------------------------------------------------------------- This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, 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, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. In other words, you are welcome to use, share and improve this program. You are forbidden to forbid anyone else to use, share and improve what you give them. Help stamp out software-hoarding! As a special exception, if you link this library with other files, some of which are compiled with SDCC, to produce an executable, this library does not by itself cause the resulting executable to be covered by the GNU General Public License. This exception does not however invalidate any other reasons why the executable file might be covered by the GNU General Public License. -------------------------------------------------------------------------------- defaults: PIC RF12 ----_------ ---------- RB7 + --------------> + SDI RB6 + <-------------- + SDO RB5 + --------------> + SCK RB4 + --------------> + nSEL RB3 + --------------> + Reset (To do (Optional)) INT2/RB2 + <-------------- + nIRQ ----------- ---------- -------------------------------------------------------------------------------- #define RF12_BUFFER_SIZE 16 #define RF12_TX_ENABLED #include <rf12.h> RF12_FRAME Frame; // to write rf12_init_tx(); Frame.Sender = 0x10; Frame.Dest = 0x20; strcpy(Frame.Data, "Hello World!"); rf12_tx_send(&Frame); // read #define RF12_BUFFER_SIZE 16 #define RF12_RX_ENABLED #define MY_ID 0x20; rf12_init_rx(); if(rf12_rx_read(&Frame) == RF12_CHECKSUM_OK) { if(Frame.Dest == MY_ID) { printf(Frame.Data); } } //*** read by interrupt *** #define RF12_BUFFER_SIZE 16 #define RF12_RX_ENABLED #define RF12_RX_INTERRUPT rf12_init_rx(); while (1) { if(rf12_rx_data_status) { rf12_rx_led_on(); printf("RawData: "); for(j=0; j < sizeof(RF12_PACKET); j++) printf("%02X", RF12_PACKET.Raw[j]); if(rf12_rx_data_status == RF12_RX_DATA_CHK_OK) printf("\r\nCHK OK!"); else printf("\r\nCHK FAILED!"); printf("\r\n\r\n"); rf12_rx_data_invalidate(); rf12_rx_led_off(); } } -------------------------------------------------------------------------------- config for 18F2550 Internal 8Mhz, MCLR_OFF void main(void) { OSCCON = 0x72; init(); .. } #define FOSC 8000000 code char at __CONFIG1L config1l = 0xff & _PLLDIV_NO_DIVIDE__4MHZ_INPUT__1L & _CPUDIV__OSC1_OSC2_SRC___1__96MHZ_PLL_SRC___2__1L & _USBPLL_CLOCK_SRC_FROM_OSC1_OSC2_1L; code char at __CONFIG1H config1h = 0xff & _OSC_INTOSC__USB_HS_1H & _FCMEN_ON_1H & _IESO_ON_1H; code char at __CONFIG2L config2l = 0xff & _PUT_ON_2L & _BODEN_ON_2L & _BODENV_2_0V_2L & _VREGEN_ON_2L; code char at __CONFIG2H config2h = 0xff & _WDT_DISABLED_CONTROLLED_2H & _WDTPS_1_32768_2H; code char at __CONFIG3H config3h = 0xff & _CCP2MUX_RC1_3H & _PBADEN_PORTB_4_0__CONFIGURED_AS_DIGITAL_I_O_ON_RESET_3H & _LPT1OSC_ON_3H & _MCLRE_MCLR_OFF_RE3_ON_3H; code char at __CONFIG4L config4l = 0xff & _STVR_OFF_4L & _LVP_OFF_4L & _ENICPORT_OFF_4L & _ENHCPU_OFF_4L & _BACKBUG_OFF_4L; code char at __CONFIG5L config5l = 0xff & _CP_0_OFF_5L & _CP_1_OFF_5L & _CP_2_OFF_5L & _CP_3_OFF_5L; code char at __CONFIG5H config5h = 0xff & _CPB_OFF_5H; code char at __CONFIG6L config6l = 0xff & _WRT_0_OFF_6L & _WRT_1_OFF_6L & _WRT_2_OFF_6L & _WRT_3_OFF_6L; code char at __CONFIG6H config6h = 0xff & _WRTB_OFF_6H & _WRTC_OFF_6H & _WRTD_OFF_6H; code char at __CONFIG7L config7l = 0xff & _EBTR_0_OFF_7L & _EBTR_1_OFF_7L & _EBTR_2_OFF_7L & _EBTR_3_OFF_7L; code char at __CONFIG7H config7h = 0xff & _EBTRB_OFF_7H; #endif ==============================================================================*/ #ifndef __RF12_H__ #define __RF12_H__ //SDI #define SDI_TRIS() TRISBbits.TRISB7=0 #define SDI_PIN(x) LATBbits.LATB7=x //SDO #define SDO_TRIS() TRISBbits.TRISB6=1 #define SDO_PIN() PORTBbits.RB6 //SCK #define SCK_TRIS() TRISBbits.TRISB5=0 #define SCK_PIN(x) LATBbits.LATB5=x //nSEL #define nSEL_TRIS() TRISBbits.TRISB4=0 #define nSEL_PIN(x) LATBbits.LATB4=x #define RESET_TRIS() TRISBbits.TRISB2=0 #define RESET_PIN(x) LATBbits.LATB3=x //nIRQ #ifdef RF12_RX_INTERRUPT #define nIRQ_TRIS() TRISBbits.TRISB2=1 #define nIRQ_PIN() PORTBbits.RB2 #else #define nIRQ_TRIS() TRISBbits.TRISB2=1 #define nIRQ_PIN() PORTBbits.RB2 #endif //TX LED #define rf12_tx_led_init() TRISAbits.TRISA0 = 0 #define rf12_tx_led_on() LATAbits.LATA0 = 1 #define rf12_tx_led_off() LATAbits.LATA0 = 0 //RX LED #define rf12_rx_led_init() TRISAbits.TRISA0 = 0 #define rf12_rx_led_on() LATAbits.LATA0 = 1 #define rf12_rx_led_off() LATAbits.LATA0 = 0 //FAIL LED #define rf12_fail_led_init() TRISAbits.TRISA1 = 0 #define rf12_fail_led_on() LATAbits.LATA1 = 1 #define rf12_fail_led_off() LATAbits.LATA1 = 0 // BUFFER SIZE #ifndef RF12_BUFFER_SIZE #define RF12_BUFFER_SIZE 16 #endif typedef union { struct { unsigned char Sender; // Sender ID unsigned char Dest; // Destination ID unsigned char Data[RF12_BUFFER_SIZE]; unsigned int Checksum; }; struct { unsigned char Raw[RF12_BUFFER_SIZE + sizeof(char) * 2 + sizeof(int)]; }; } RF12_FRAME; #define RF12_RX_DATA_INVALID 0 #define RF12_RX_DATA_CHK_OK 1 #define RF12_RX_DATA_CHK_FAILED 2 RF12_FRAME RF12_PACKET; unsigned char rf12_rx_data_index = 0; unsigned char rf12_rx_data_status = RF12_RX_DATA_INVALID; unsigned int rf12_rx_fail_count = 0; #define RF12_BROADCAST_ADDR 1 #define RF12_TIMEOUT 20000 #define RF12_EXPIRED 0 #ifdef RF12_RX_INTERRUPT #include <signal.h> #define rf12_rx_interrupt_enable() INTCON3bits.INT2IE = 1 #define rf12_rx_interrupt_disable() INTCON3bits.INT2IE = 0 #endif static void rf12_write0(void){ SCK_PIN(0); _asm NOP _endasm; SDI_PIN(0); _asm NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP _endasm; SCK_PIN(1); _asm NOP _endasm; } static void rf12_write1(void){ SCK_PIN(0); _asm NOP _endasm; SDI_PIN(1); _asm NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP _endasm; SCK_PIN(1); _asm NOP _endasm; } void rf12_write_cmd(int cmd) { char n = 16; SCK_PIN(0); nSEL_PIN(0); while(n--) { if(cmd & 0x8000) rf12_write1(); else rf12_write0(); cmd = cmd << 1; } SCK_PIN(0); nSEL_PIN(1); } #ifdef RF12_RX_ENABLED unsigned char rf12_read_fifo(void) { unsigned char i; unsigned char result = 0; SCK_PIN(0); SDI_PIN(0); nSEL_PIN(0); for(i = 0;i < 16; i++) { SCK_PIN(1); _asm NOP NOP _endasm; SCK_PIN(0); _asm NOP NOP _endasm; } for(i = 0;i < 8; i++) { result = result << 1; if(SDO_PIN()) result |= 1; SCK_PIN(1); _asm NOP NOP _endasm; SCK_PIN(0); _asm NOP NOP _endasm; } nSEL_PIN(1); return result; } #endif //#ifdef RF12_RX_ENABLED #ifdef RF12_RX_ENABLED void rf12_reset_fifo() { rf12_write_cmd(0xCA80); rf12_write_cmd(0xCA83); } #endif //#ifdef RF12_RX_ENABLED #ifdef RF12_RX_ENABLED void rf12_rx_data_invalidate() { rf12_reset_fifo(); while(!nIRQ_PIN()) { rf12_read_fifo(); } rf12_rx_data_index = 0; rf12_rx_data_status = RF12_RX_DATA_INVALID; } #endif //#ifdef RF12_RX_ENABLED #ifdef RF12_TX_ENABLED void rf12_write_byte(unsigned int adata) { unsigned char RGIT = 0; unsigned int temp = 0xB800; temp |= adata; loop: SCK_PIN(0); nSEL_PIN(0); SDI_PIN(0); SCK_PIN(1); if(SDO_PIN()) RGIT = 1; else RGIT = 0; SCK_PIN(0); SDI_PIN(1); nSEL_PIN(1); if(RGIT == 0) { goto loop; } else { RGIT = 0; rf12_write_cmd(temp); } } #endif //#ifdef RF12_TX_ENABLED #ifdef RF12_TX_ENABLED void rf12_tx_send(RF12_FRAME * Frame) { unsigned char i; unsigned int chk = 0; #ifdef rf12_tx_led_on rf12_tx_led_on(); #endif rf12_write_cmd(0x8228); delay_us(4); rf12_write_cmd(0x8238); _asm NOP NOP _endasm; rf12_write_byte(0xAA); rf12_write_byte(0xAA); rf12_write_byte(0xAA); rf12_write_byte(0x2D); rf12_write_byte(0xD4); rf12_write_byte(Frame->Sender); chk += Frame->Sender; rf12_write_byte(Frame->Dest); chk += Frame->Dest; for(i = 0; i < sizeof(Frame->Data); i++) { rf12_write_byte(Frame->Data[i]); chk += Frame->Data[i]; } rf12_write_byte(chk); rf12_write_byte(chk >> 8); rf12_write_byte(0xAA); rf12_write_byte(0xAA); rf12_write_cmd(0x8208); #ifdef rf12_tx_led_off rf12_tx_led_off(); #endif } #endif //#ifdef RF12_TX_ENABLED void rf12_init_io_pins(void) { #ifdef rf12_rx_led_init rf12_rx_led_init(); #endif #ifdef rf12_tx_led_init rf12_tx_led_init(); #endif #ifdef rf12_fail_led_init rf12_tx_led_init(); #endif SDI_TRIS(); SDO_TRIS(); SCK_TRIS(); nSEL_TRIS(); RESET_TRIS(); nIRQ_TRIS(); } #ifdef RF12_RX_INTERRUPT SIGHANDLER(int2_handler){ unsigned char i; unsigned int chk = 0; if(!rf12_rx_data_status) { rf12_rx_led_on(); RF12_PACKET.Raw[rf12_rx_data_index++] = rf12_read_fifo(); rf12_rx_data_status = RF12_RX_DATA_INVALID; if(rf12_rx_data_index > (sizeof(RF12_FRAME))) { for(i=0; i < (sizeof(RF12_FRAME) - sizeof(RF12_PACKET.Checksum)); i++) chk += RF12_PACKET.Raw[i]; if(RF12_PACKET.Checksum == chk){ rf12_rx_data_status = RF12_RX_DATA_CHK_OK; rf12_fail_led_off(); } else { rf12_rx_data_status = RF12_RX_DATA_CHK_FAILED; rf12_fail_led_on(); rf12_rx_fail_count++; //Todo: Restet RF12 RESET_PIN(1); } } rf12_rx_led_off(); } INTCON3bits.INT2IF = 0; } DEF_INTHIGH(high_handler) DEF_HANDLER(SIG_INT2, int2_handler); END_DEF DEF_INTLOW(low_handler) DEF_HANDLER(SIG_INT2, int2_handler); END_DEF #endif #ifdef RF12_RX_ENABLED void rf12_init_rx() { rf12_init_io_pins(); //Interrupt #ifdef RF12_RX_INTERRUPT INTCON3bits.INT2IF = 0; INTCON2bits.INTEDG2 = 0; INTCON3bits.INT2IE = 1; INTCONbits.GIE = 1; #endif nSEL_PIN(1); SDI_PIN(1); SCK_PIN(0); rf12_write_cmd(0x80D8);//enable register,433MHz,12.5pF rf12_write_cmd(0x82D8);//enable receive,!PA rf12_write_cmd(0xA640); rf12_write_cmd(0xC647); rf12_write_cmd(0x94A0);//VDI,FAST,134kHz,0dBm,-103dBm rf12_write_cmd(0xC2AC); rf12_write_cmd(0XCC77); rf12_write_cmd(0xC49B); rf12_write_cmd(0x9850);//!mp,9810=30kHz,MAX OUT rf12_write_cmd(0xE000);//NOT USE rf12_write_cmd(0xC800);//NOT USE rf12_write_cmd(0xC000);//1.0MHz,2. rf12_rx_data_invalidate(); } #endif //#ifdef RF12_RX_ENABLED #ifdef RF12_TX_ENABLED void rf12_tx_init(void){ rf12_init_io_pins(); nSEL_PIN(1); SDI_PIN(1); SCK_PIN(0); rf12_write_cmd(0x80d8); rf12_write_cmd(0x8208); rf12_write_cmd(0xA640); rf12_write_cmd(0xc647); rf12_write_cmd(0xcc77); rf12_write_cmd(0x94a0); rf12_write_cmd(0xc2ac); rf12_write_cmd(0xca80); rf12_write_cmd(0xca83); rf12_write_cmd(0xc49b); rf12_write_cmd(0x9850); rf12_write_cmd(0xe000); rf12_write_cmd(0xc80e); rf12_write_cmd(0xc000); } #endif //#ifdef RF12_TX_ENABLED #ifndef RF12_RX_INTERRUPT unsigned char rf12_rx_read(RF12_FRAME * Frame) { unsigned char index = 0; unsigned int chk = 0; unsigned char i; int timeout = RF12_TIMEOUT; while(timeout) { if(!nIRQ_PIN()){ #ifdef rf12_rx_led_on rf12_rx_led_on(); #endif Frame->Raw[index++] = rf12_read_fifo(); if(index > (sizeof(RF12_FRAME))) { for(i=0; i < (sizeof(RF12_FRAME) - sizeof(Frame->Checksum)); i++) chk += Frame->Raw[i]; rf12_reset_fifo(); #ifdef rf12_rx_led_off rf12_rx_led_off(); #endif if(Frame->Checksum == chk) return RF12_RX_DATA_CHK_OK; return RF12_RX_DATA_CHK_FAILED; } timeout = RF12_TIMEOUT; } timeout--; } rf12_reset_fifo(); #ifdef rf12_rx_led_off rf12_rx_led_off(); #endif LATAbits.LATA0 = 0; return RF12_EXPIRED; } #endif //#ifndef RF12_RX_INTERRUPT #endif // __rf12_H__