/**************************************************************************** * * * RFM12 basierte, drahtlose RS232 Verbindung * * * * Version 1.51 * * * * � by Benedikt * * * * Email: benedikt83 �t gmx.net * * * **************************************************************************** * * * Die Fusebits aus externen Takt einstellen, wenn die 10MHz vom RFM12 * * verwendet werden. Die BOD auf 2,6V einstellen und aktivieren. * * * **************************************************************************** * * * Die Software darf frei kopiert und ver�ndert werden, solange sie nicht * * ohne meine Erlaubnis f�r kommerzielle Zwecke eingesetzt wird. * * * ***************************************************************************/ #include #include #include #include #include #include #include "global.h" #include "uart.h" #include "rf12.h" #include "leds.h" #define F_CPU 10000000UL #include //#define DEBUG // anstelle der empfangenen Daten f�r jede Aktion den Status ausgeben #define USE_SOFTCONFIG // Konfiguration �ber ein einfaches Men� (auskommentieren wenn nicht verwendet), nicht zusammen mit DIPSWITCH verwenden //#define USE_DIPSWITCH // DIP Schalter/Jumper an PortC 0-4 (auskommentieren wenn nicht verwendet), nicht zusammen mit SOFTCONFIG verwenden #define CHANNEL 2 // Sende/Empfangskanal (0-3) (nur g�ltig wenn kein DIP Schalter verwendet wird) #define RF_BAUDRATE 20000 // Baudrate des RFM12 (nur g�ltig wenn kein DIP Schalter verwendet wird) #define UART_BAUDRATE 19200 // Baudrate des UARTs (nur g�ltig wenn kein DIP Schalter verwendet wird) #define CONFIG_BAUD 19200 // Baudrate des UARTs (nur g�ltig im Config Mode) #define MAX_BUF 128 // Paket Gr��e in Bytes (maximal 250, siehe auch rf12.c) #define TX_TIMEOUT 150 // Maximale Wartezeit auf Daten in ms (max 500) #define ANSWER_TIMEOUT 10 // Maximale Wartezeit auf die Best�tigung der Daten in ms (max 500) #define RETRY 15 // Maximale Anzahl an Sendeversuchen // define USE_868 in der rf12.c zum Umschalten zwischen 433 (auskommentiert) und 868MHz (aktiv) verwenden! Bei der 868MHz Version ist die Einhaltung der maximalen Sendedauer bei den einzelnen Kan�len zu beachten! #define CONFIG PIND_4 // Pin f�r Config Jumper (DDR beachten) volatile unsigned char delaycnt; unsigned char rxbuf[MAX_BUF+1]; // Puffer f�r empfangene Daten unsigned char txbuf[MAX_BUF+1]; // Puffer f�r zu sendende Daten unsigned char flags, tx_cnt, tx_id, tx_status, retrans_cnt; #ifdef USE_SOFTCONFIG unsigned long uart_baud, rf_baud; unsigned char channel; #endif #define WAITFORACK 1 void rx_packet(void); void tx_packet(unsigned char retrans); void load_settings(void); void save_settings(void); void configmode(void); unsigned long read_number(unsigned long min, unsigned long max); void show_number(unsigned long val); int main(void) { #ifdef USE_SOFTCONFIG PORTD=255; DDRD=230; DDRC=255; #else PORTD=15; PORTC=255; DDRD=242; #endif sei(); rf12_init(); // ein paar Register setzen (z.B. CLK auf 10MHz) #ifdef USE_DIPSWITCH unsigned char c; unsigned short baud_uart, baud_rf; c=PINC&7; if (c==0) { baud_rf=4000; baud_uart=UART_BAUD_SELECT(1200, F_CPU); } else if (c==1) { baud_rf=4000; baud_uart=UART_BAUD_SELECT(2400, F_CPU); } else if (c==2) { baud_rf=8000; baud_uart=UART_BAUD_SELECT(4800, F_CPU); } else if (c==3) { baud_rf=15000; baud_uart=UART_BAUD_SELECT(9600, F_CPU); } else if (c==4) { baud_rf=25000; baud_uart=UART_BAUD_SELECT(19200, F_CPU); } else if (c==5) { baud_rf=30000; baud_uart=UART_BAUD_SELECT(28800, F_CPU); } else if (c==6) { baud_rf=40000; baud_uart=UART_BAUD_SELECT(38400, F_CPU); } else if (c==7) { baud_rf=60000; baud_uart=UART_BAUD_SELECT(57600, F_CPU); } c=(PINC&24)/8; uart_init(baud_uart); rf12_config(baud_rf, c, 0, QUIET); // Baudrate, Kanal (0-3), Leistung (0=max, 7=min), Umgebungsbedingungen (QUIET, NORMAL, NOISY) #else #ifdef USE_SOFTCONFIG load_settings(); if (!CONFIG) configmode(); uart_init(UART_BAUD_SELECT(uart_baud, F_CPU)); rf12_config(rf_baud, channel, 0, QUIET); // Baudrate, Kanal (0-3), Leistung (0=max, 7=min), Umgebungsbedingungen (QUIET, NORMAL, NOISY) #else uart_init(UART_BAUD_SELECT(UART_BAUDRATE, F_CPU)); rf12_config(RF_BAUDRATE, CHANNEL, 0, QUIET); // Baudrate, Kanal (0-3), Leistung (0=max, 7=min), Umgebungsbedingungen (QUIET, NORMAL, NOISY) #endif #endif TCCR1A=0; TCCR1B=(1<=MAX_BUF)||((tx_cnt)&&(delaycnt==0))) // Puffer voll, oder timeout seit erstem Byte im Puffer vorbei ? -> senden { tx_status=0; // zu sendender Status tx_packet(0); // erstmaliger Transfer #ifdef DEBUG uart_putc('t'); #endif } } else if (delaycnt==0) // Timeout: Daten nochmal senden { LED_RETRANS=1; if (retrans_cnt) { retrans_cnt--; tx_packet(1); // retransmit #ifdef DEBUG uart_putc('r'); #endif } else // Versuche abgelaufen { LED_ERR=1; // -> Fehler LED an tx_cnt=0; // -> Daten verwerfen tx_id++; flags&=~WAITFORACK; // Daten als OK markieren #ifdef DEBUG uart_putc('e'); #endif } } } } void rx_packet(void) { static unsigned char rx_lastid=255; unsigned char rx_cnt,i, rx_id, status; rx_cnt=rf12_rxdata(rxbuf, &status, &rx_id); // komplettes Paket empfangen if (rx_cnt<=MAX_BUF) // Daten g�ltig (d.h. kein CRC Fehler) ? { if (status&RECEIVED_OK) // Empfangsbest�tigung ? { flags&=~WAITFORACK; // -> "Warten auf Best�tigung"-Flag l�schen tx_cnt=0; // -> Daten als gesendet markieren tx_id++; LED_RETRANS=0; LED_ERR=0; #ifdef DEBUG uart_putc('a'); #endif } if (rx_cnt) // Daten empfangen { tx_status=RECEIVED_OK; // zu sendender Status #ifdef DEBUG uart_putc('p'); #endif tx_packet(0); // Empfangsbest�tigung senden retrans_cnt=RETRY; // Retry Counter neu starten if (rx_id!=rx_lastid) // Handelt es sich um neue Daten ? { #ifndef DEBUG for (i=0; i kein komplettes neues Paket, sondern nur Status senden #ifdef DEBUG uart_putc('s'); #endif } else { rf12_txdata(txbuf, tx_cnt, tx_status, tx_id); // komplettes Paket senden flags|=WAITFORACK; // auf ACK warten delaycnt=ANSWER_TIMEOUT/2; // Timeout Counter neu starten if (!retrans) // erstmalige �bertragung ? retrans_cnt=RETRY; // -> Retry Counter neu starten #ifdef DEBUG uart_putc('d'); #endif } rf12_rxmode(); // wieder auf RX umschalten } #ifdef USE_SOFTCONFIG void load_settings(void) { if (eeprom_read_byte((void *)1)!=0xAA) { rf_baud=RF_BAUDRATE; uart_baud=UART_BAUDRATE; channel=CHANNEL; save_settings(); } channel=eeprom_read_byte((void *)2); eeprom_read_block(&rf_baud,(void *)3,4); eeprom_read_block(&uart_baud,(void *)7,4); } void save_settings(void) { eeprom_write_byte((void *)1,0xAA); eeprom_write_byte((void *)2,channel); eeprom_write_block(&rf_baud,(void *)3,4); eeprom_write_block(&uart_baud,(void *)7,4); } void configmode(void) { unsigned char c; uart_init(UART_BAUD_SELECT(CONFIG_BAUD, F_CPU)); for(;;) { uart_puts_P("\r\n\r\n"); uart_puts_P("RFM12 RS232 bridge v1.2\r\n"); uart_puts_P("(c) by Benedikt\r\n"); uart_puts_P("Config Menue\r\n\r\n"); uart_puts_P("Current Settings:\r\n"); uart_puts_P("\r\nRS232 baudrate: "); show_number(uart_baud); uart_puts_P("\r\nRFM12 baudrate: "); show_number(rf_baud); uart_puts_P("\r\nchannel: "); show_number(channel); uart_puts_P("\r\n\r\n"); uart_puts_P("(1) set RS232 baudrate\r\n"); uart_puts_P("(2) set RFM12 baudrate\r\n"); uart_puts_P("(3) set RFM12 channel\r\n"); uart_puts_P("\r\n"); uart_puts_P("(0) exit menu without saving\r\n"); uart_puts_P("(s) exit menu and save settings\r\n"); uart_puts_P("\r\n"); for(;;) { c=uart_getchar(); if (c=='0') return; else if (c=='s') { uart_puts_P("saved !\r\nLeaving config mode...\r\n"); save_settings(); _delay_ms(10); return; } else if (c=='1') { uart_puts_P("Enter RS232 baudrate (300-150000)\r\n"); uart_baud=read_number(300,150000); break; } else if (c=='2') { uart_puts_P("Enter RFM12 baudrate (700-65000)\r\n"); rf_baud=read_number(700,65000); break; } else if (c=='3') { uart_puts_P("Enter RFM12 channel (0-3)\r\n"); channel=read_number(0,3); break; } else break; } } } void show_number(unsigned long val) { unsigned char i; char s[8]={32,32,32,32,32,32,32,0}; i=6; do { s[i--]=val%10+'0'; } while (val/=10); s[7]=0; uart_puts(s); } unsigned long read_number(unsigned long min, unsigned long max) { unsigned long number; unsigned char c,i; for (;;) { number=0; for (i=0;i<6;i++) { c=uart_getchar(); if ((c==10)||(c==13)||(c==32)) break; if ((c>='0')&&(c<='9')) { uart_putc(c); number=number*10+(c-'0'); } } if ((number>=min)&&(number<=max)) break; uart_puts_P("Number out of range, try again !\r\n"); } return number; } #endif ISR(SIG_OUTPUT_COMPARE1A) // 500Hz Interrupt { if (delaycnt) delaycnt--; }