-
- /****************************************************************************
- * *
- * 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 <avr/io.h>
- #include <avr/interrupt.h>
- #include <avr/pgmspace.h>
- #include <avr/eeprom.h>
- #include <stdlib.h>
- #include <portbits.h>
- #include "global.h"
- #include "uart.h"
- #include "rf12.h"
- #include "leds.h"
-
- #define F_CPU 10000000UL
- #include <util/delay.h>
-
- //#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<<WGM12)|1;
- OCR1A=((F_CPU+2500)/500)-1;
- TIMSK=(1<<OCIE1A);
-
- rf12_rxmode();
-
- for (;;)
- { if (rf12_data()) // Daten im RF12 RX Puffer ?
- { rx_packet();
- }
- if (!(flags&WAITFORACK)) // Puffer nur dann f�llen, wenn die alten Daten aus dem Puffer wirklich angekommen sind
- { if (uart_data()) // Daten im UART RX Puffer ?
- { if (!tx_cnt)
- delaycnt=TX_TIMEOUT/2; // Nach dem ersten Byte: timeout starten
- txbuf[tx_cnt++]=uart_getchar();
- }
- if ((tx_cnt>=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<rx_cnt; i++) // Daten weiterleiten
- uart_putc(rxbuf[i]);
- #endif
- rx_lastid=rx_id; // Aktuelle ID speichern
- }
- }
- }
- else
- {
- #ifdef DEBUG
- uart_putc('n');
- #endif
- }
- }
-
- void tx_packet(unsigned char retrans)
- {
- rf12_stoprx(); // auf TX umschalten
- if ((!retrans)&&((flags&WAITFORACK)||(tx_cnt==0))) // es wird noch auf eine Antwort vom Paket gewartet oder es sind keine Daten zu senden
- { rf12_txdata(txbuf, 0, tx_status, 0); // -> 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--;
- }
-