spacepaste

  1.  
  2. /****************************************************************************
  3. * *
  4. * RFM12 basierte, drahtlose RS232 Verbindung *
  5. * *
  6. * Version 1.51 *
  7. * *
  8. * � by Benedikt *
  9. * *
  10. * Email: benedikt83 �t gmx.net *
  11. * *
  12. ****************************************************************************
  13. * *
  14. * Die Fusebits aus externen Takt einstellen, wenn die 10MHz vom RFM12 *
  15. * verwendet werden. Die BOD auf 2,6V einstellen und aktivieren. *
  16. * *
  17. ****************************************************************************
  18. * *
  19. * Die Software darf frei kopiert und ver�ndert werden, solange sie nicht *
  20. * ohne meine Erlaubnis f�r kommerzielle Zwecke eingesetzt wird. *
  21. * *
  22. ***************************************************************************/
  23. #include <avr/io.h>
  24. #include <avr/interrupt.h>
  25. #include <avr/pgmspace.h>
  26. #include <avr/eeprom.h>
  27. #include <stdlib.h>
  28. #include <portbits.h>
  29. #include "global.h"
  30. #include "uart.h"
  31. #include "rf12.h"
  32. #include "leds.h"
  33. #define F_CPU 10000000UL
  34. #include <util/delay.h>
  35. //#define DEBUG // anstelle der empfangenen Daten f�r jede Aktion den Status ausgeben
  36. #define USE_SOFTCONFIG // Konfiguration �ber ein einfaches Men� (auskommentieren wenn nicht verwendet), nicht zusammen mit DIPSWITCH verwenden
  37. //#define USE_DIPSWITCH // DIP Schalter/Jumper an PortC 0-4 (auskommentieren wenn nicht verwendet), nicht zusammen mit SOFTCONFIG verwenden
  38. #define CHANNEL 2 // Sende/Empfangskanal (0-3) (nur g�ltig wenn kein DIP Schalter verwendet wird)
  39. #define RF_BAUDRATE 20000 // Baudrate des RFM12 (nur g�ltig wenn kein DIP Schalter verwendet wird)
  40. #define UART_BAUDRATE 19200 // Baudrate des UARTs (nur g�ltig wenn kein DIP Schalter verwendet wird)
  41. #define CONFIG_BAUD 19200 // Baudrate des UARTs (nur g�ltig im Config Mode)
  42. #define MAX_BUF 128 // Paket Gr��e in Bytes (maximal 250, siehe auch rf12.c)
  43. #define TX_TIMEOUT 150 // Maximale Wartezeit auf Daten in ms (max 500)
  44. #define ANSWER_TIMEOUT 10 // Maximale Wartezeit auf die Best�tigung der Daten in ms (max 500)
  45. #define RETRY 15 // Maximale Anzahl an Sendeversuchen
  46. // 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!
  47. #define CONFIG PIND_4 // Pin f�r Config Jumper (DDR beachten)
  48. volatile unsigned char delaycnt;
  49. unsigned char rxbuf[MAX_BUF+1]; // Puffer f�r empfangene Daten
  50. unsigned char txbuf[MAX_BUF+1]; // Puffer f�r zu sendende Daten
  51. unsigned char flags, tx_cnt, tx_id, tx_status, retrans_cnt;
  52. #ifdef USE_SOFTCONFIG
  53. unsigned long uart_baud, rf_baud;
  54. unsigned char channel;
  55. #endif
  56. #define WAITFORACK 1
  57. void rx_packet(void);
  58. void tx_packet(unsigned char retrans);
  59. void load_settings(void);
  60. void save_settings(void);
  61. void configmode(void);
  62. unsigned long read_number(unsigned long min, unsigned long max);
  63. void show_number(unsigned long val);
  64. int main(void)
  65. {
  66. #ifdef USE_SOFTCONFIG
  67. PORTD=255;
  68. DDRD=230;
  69. DDRC=255;
  70. #else
  71. PORTD=15;
  72. PORTC=255;
  73. DDRD=242;
  74. #endif
  75. sei();
  76. rf12_init(); // ein paar Register setzen (z.B. CLK auf 10MHz)
  77. #ifdef USE_DIPSWITCH
  78. unsigned char c;
  79. unsigned short baud_uart, baud_rf;
  80. c=PINC&7;
  81. if (c==0)
  82. { baud_rf=4000;
  83. baud_uart=UART_BAUD_SELECT(1200, F_CPU);
  84. }
  85. else if (c==1)
  86. { baud_rf=4000;
  87. baud_uart=UART_BAUD_SELECT(2400, F_CPU);
  88. }
  89. else if (c==2)
  90. { baud_rf=8000;
  91. baud_uart=UART_BAUD_SELECT(4800, F_CPU);
  92. }
  93. else if (c==3)
  94. { baud_rf=15000;
  95. baud_uart=UART_BAUD_SELECT(9600, F_CPU);
  96. }
  97. else if (c==4)
  98. { baud_rf=25000;
  99. baud_uart=UART_BAUD_SELECT(19200, F_CPU);
  100. }
  101. else if (c==5)
  102. { baud_rf=30000;
  103. baud_uart=UART_BAUD_SELECT(28800, F_CPU);
  104. }
  105. else if (c==6)
  106. { baud_rf=40000;
  107. baud_uart=UART_BAUD_SELECT(38400, F_CPU);
  108. }
  109. else if (c==7)
  110. { baud_rf=60000;
  111. baud_uart=UART_BAUD_SELECT(57600, F_CPU);
  112. }
  113. c=(PINC&24)/8;
  114. uart_init(baud_uart);
  115. rf12_config(baud_rf, c, 0, QUIET); // Baudrate, Kanal (0-3), Leistung (0=max, 7=min), Umgebungsbedingungen (QUIET, NORMAL, NOISY)
  116. #else
  117. #ifdef USE_SOFTCONFIG
  118. load_settings();
  119. if (!CONFIG)
  120. configmode();
  121. uart_init(UART_BAUD_SELECT(uart_baud, F_CPU));
  122. rf12_config(rf_baud, channel, 0, QUIET); // Baudrate, Kanal (0-3), Leistung (0=max, 7=min), Umgebungsbedingungen (QUIET, NORMAL, NOISY)
  123. #else
  124. uart_init(UART_BAUD_SELECT(UART_BAUDRATE, F_CPU));
  125. rf12_config(RF_BAUDRATE, CHANNEL, 0, QUIET); // Baudrate, Kanal (0-3), Leistung (0=max, 7=min), Umgebungsbedingungen (QUIET, NORMAL, NOISY)
  126. #endif
  127. #endif
  128. TCCR1A=0;
  129. TCCR1B=(1<<WGM12)|1;
  130. OCR1A=((F_CPU+2500)/500)-1;
  131. TIMSK=(1<<OCIE1A);
  132. rf12_rxmode();
  133. for (;;)
  134. { if (rf12_data()) // Daten im RF12 RX Puffer ?
  135. { rx_packet();
  136. }
  137. if (!(flags&WAITFORACK)) // Puffer nur dann f�llen, wenn die alten Daten aus dem Puffer wirklich angekommen sind
  138. { if (uart_data()) // Daten im UART RX Puffer ?
  139. { if (!tx_cnt)
  140. delaycnt=TX_TIMEOUT/2; // Nach dem ersten Byte: timeout starten
  141. txbuf[tx_cnt++]=uart_getchar();
  142. }
  143. if ((tx_cnt>=MAX_BUF)||((tx_cnt)&&(delaycnt==0))) // Puffer voll, oder timeout seit erstem Byte im Puffer vorbei ? -> senden
  144. { tx_status=0; // zu sendender Status
  145. tx_packet(0); // erstmaliger Transfer
  146. #ifdef DEBUG
  147. uart_putc('t');
  148. #endif
  149. }
  150. }
  151. else if (delaycnt==0) // Timeout: Daten nochmal senden
  152. { LED_RETRANS=1;
  153. if (retrans_cnt)
  154. { retrans_cnt--;
  155. tx_packet(1); // retransmit
  156. #ifdef DEBUG
  157. uart_putc('r');
  158. #endif
  159. }
  160. else // Versuche abgelaufen
  161. { LED_ERR=1; // -> Fehler LED an
  162. tx_cnt=0; // -> Daten verwerfen
  163. tx_id++;
  164. flags&=~WAITFORACK; // Daten als OK markieren
  165. #ifdef DEBUG
  166. uart_putc('e');
  167. #endif
  168. }
  169. }
  170. }
  171. }
  172. void rx_packet(void)
  173. { static unsigned char rx_lastid=255;
  174. unsigned char rx_cnt,i, rx_id, status;
  175. rx_cnt=rf12_rxdata(rxbuf, &status, &rx_id); // komplettes Paket empfangen
  176. if (rx_cnt<=MAX_BUF) // Daten g�ltig (d.h. kein CRC Fehler) ?
  177. { if (status&RECEIVED_OK) // Empfangsbest�tigung ?
  178. { flags&=~WAITFORACK; // -> "Warten auf Best�tigung"-Flag l�schen
  179. tx_cnt=0; // -> Daten als gesendet markieren
  180. tx_id++;
  181. LED_RETRANS=0;
  182. LED_ERR=0;
  183. #ifdef DEBUG
  184. uart_putc('a');
  185. #endif
  186. }
  187. if (rx_cnt) // Daten empfangen
  188. { tx_status=RECEIVED_OK; // zu sendender Status
  189. #ifdef DEBUG
  190. uart_putc('p');
  191. #endif
  192. tx_packet(0); // Empfangsbest�tigung senden
  193. retrans_cnt=RETRY; // Retry Counter neu starten
  194. if (rx_id!=rx_lastid) // Handelt es sich um neue Daten ?
  195. {
  196. #ifndef DEBUG
  197. for (i=0; i<rx_cnt; i++) // Daten weiterleiten
  198. uart_putc(rxbuf[i]);
  199. #endif
  200. rx_lastid=rx_id; // Aktuelle ID speichern
  201. }
  202. }
  203. }
  204. else
  205. {
  206. #ifdef DEBUG
  207. uart_putc('n');
  208. #endif
  209. }
  210. }
  211. void tx_packet(unsigned char retrans)
  212. {
  213. rf12_stoprx(); // auf TX umschalten
  214. if ((!retrans)&&((flags&WAITFORACK)||(tx_cnt==0))) // es wird noch auf eine Antwort vom Paket gewartet oder es sind keine Daten zu senden
  215. { rf12_txdata(txbuf, 0, tx_status, 0); // -> kein komplettes neues Paket, sondern nur Status senden
  216. #ifdef DEBUG
  217. uart_putc('s');
  218. #endif
  219. }
  220. else
  221. { rf12_txdata(txbuf, tx_cnt, tx_status, tx_id); // komplettes Paket senden
  222. flags|=WAITFORACK; // auf ACK warten
  223. delaycnt=ANSWER_TIMEOUT/2; // Timeout Counter neu starten
  224. if (!retrans) // erstmalige �bertragung ?
  225. retrans_cnt=RETRY; // -> Retry Counter neu starten
  226. #ifdef DEBUG
  227. uart_putc('d');
  228. #endif
  229. }
  230. rf12_rxmode(); // wieder auf RX umschalten
  231. }
  232. #ifdef USE_SOFTCONFIG
  233. void load_settings(void)
  234. {
  235. if (eeprom_read_byte((void *)1)!=0xAA)
  236. { rf_baud=RF_BAUDRATE;
  237. uart_baud=UART_BAUDRATE;
  238. channel=CHANNEL;
  239. save_settings();
  240. }
  241. channel=eeprom_read_byte((void *)2);
  242. eeprom_read_block(&rf_baud,(void *)3,4);
  243. eeprom_read_block(&uart_baud,(void *)7,4);
  244. }
  245. void save_settings(void)
  246. {
  247. eeprom_write_byte((void *)1,0xAA);
  248. eeprom_write_byte((void *)2,channel);
  249. eeprom_write_block(&rf_baud,(void *)3,4);
  250. eeprom_write_block(&uart_baud,(void *)7,4);
  251. }
  252. void configmode(void)
  253. { unsigned char c;
  254. uart_init(UART_BAUD_SELECT(CONFIG_BAUD, F_CPU));
  255. for(;;)
  256. { uart_puts_P("\r\n\r\n");
  257. uart_puts_P("RFM12 RS232 bridge v1.2\r\n");
  258. uart_puts_P("(c) by Benedikt\r\n");
  259. uart_puts_P("Config Menue\r\n\r\n");
  260. uart_puts_P("Current Settings:\r\n");
  261. uart_puts_P("\r\nRS232 baudrate: ");
  262. show_number(uart_baud);
  263. uart_puts_P("\r\nRFM12 baudrate: ");
  264. show_number(rf_baud);
  265. uart_puts_P("\r\nchannel: ");
  266. show_number(channel);
  267. uart_puts_P("\r\n\r\n");
  268. uart_puts_P("(1) set RS232 baudrate\r\n");
  269. uart_puts_P("(2) set RFM12 baudrate\r\n");
  270. uart_puts_P("(3) set RFM12 channel\r\n");
  271. uart_puts_P("\r\n");
  272. uart_puts_P("(0) exit menu without saving\r\n");
  273. uart_puts_P("(s) exit menu and save settings\r\n");
  274. uart_puts_P("\r\n");
  275. for(;;)
  276. { c=uart_getchar();
  277. if (c=='0')
  278. return;
  279. else if (c=='s')
  280. { uart_puts_P("saved !\r\nLeaving config mode...\r\n");
  281. save_settings();
  282. _delay_ms(10);
  283. return;
  284. }
  285. else if (c=='1')
  286. { uart_puts_P("Enter RS232 baudrate (300-150000)\r\n");
  287. uart_baud=read_number(300,150000);
  288. break;
  289. }
  290. else if (c=='2')
  291. { uart_puts_P("Enter RFM12 baudrate (700-65000)\r\n");
  292. rf_baud=read_number(700,65000);
  293. break;
  294. }
  295. else if (c=='3')
  296. { uart_puts_P("Enter RFM12 channel (0-3)\r\n");
  297. channel=read_number(0,3);
  298. break;
  299. }
  300. else
  301. break;
  302. }
  303. }
  304. }
  305. void show_number(unsigned long val)
  306. { unsigned char i;
  307. char s[8]={32,32,32,32,32,32,32,0};
  308. i=6;
  309. do
  310. { s[i--]=val%10+'0';
  311. }
  312. while (val/=10);
  313. s[7]=0;
  314. uart_puts(s);
  315. }
  316. unsigned long read_number(unsigned long min, unsigned long max)
  317. { unsigned long number;
  318. unsigned char c,i;
  319. for (;;)
  320. { number=0;
  321. for (i=0;i<6;i++)
  322. { c=uart_getchar();
  323. if ((c==10)||(c==13)||(c==32))
  324. break;
  325. if ((c>='0')&&(c<='9'))
  326. { uart_putc(c);
  327. number=number*10+(c-'0');
  328. }
  329. }
  330. if ((number>=min)&&(number<=max))
  331. break;
  332. uart_puts_P("Number out of range, try again !\r\n");
  333. }
  334. return number;
  335. }
  336. #endif
  337. ISR(SIG_OUTPUT_COMPARE1A) // 500Hz Interrupt
  338. {
  339. if (delaycnt)
  340. delaycnt--;
  341. }
  342.