You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

244 lines
7.2 KiB

  1. /***************************************************************************
  2. * Copyright (C) 11/2014 by Olaf Rempel *
  3. * razzor@kopf-tisch.de *
  4. * *
  5. * This program is free software; you can redistribute it and/or modify *
  6. * it under the terms of the GNU General Public License as published by *
  7. * the Free Software Foundation; version 2 of the License, *
  8. * *
  9. * This program is distributed in the hope that it will be useful, *
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of *
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
  12. * GNU General Public License for more details. *
  13. * *
  14. * You should have received a copy of the GNU General Public License *
  15. * along with this program; if not, write to the *
  16. * Free Software Foundation, Inc., *
  17. * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
  18. ***************************************************************************/
  19. #include <avr/io.h>
  20. #include <avr/interrupt.h>
  21. #include <avr/boot.h>
  22. #include <avr/pgmspace.h>
  23. #include <string.h>
  24. #include "target.h"
  25. #include "rfm12.h"
  26. #include "uart.h"
  27. /* *********************************************************************** */
  28. #define BRIDGE_CMD_IDLE 0x00
  29. #define BRIDGE_CMD_TRANSMIT 'T'
  30. #define BRIDGE_CMD_RECEIVE 'R'
  31. #define BRIDGE_CMD_VERSION 'V'
  32. #define BRIDGE_CAUSE_SUCCESS 0x00
  33. #define BRIDGE_CAUSE_TIMEOUT 0x01
  34. #define BRIDGE_CAUSE_NOT_SUPPORTED 0xF0
  35. #define BRIDGE_CAUSE_INVALID_PARAMETER 0xF1
  36. #define BRIDGE_CAUSE_UNSPECIFIED_ERROR 0xFF
  37. /* *********************************************************************** */
  38. static uint8_t led_timer;
  39. volatile static uint8_t clock_tick;
  40. ISR(TIMER0_OVF_vect)
  41. {
  42. TCNT0 = TIMER_RELOAD;
  43. clock_tick = 1;
  44. } /* TIMER0_OVF_vect */
  45. /*
  46. * For newer devices the watchdog timer remains active even after a
  47. * system reset. So disable it as soon as possible.
  48. * automagically called on startup
  49. */
  50. void disable_wdt_timer(void) __attribute__((naked, section(".init3")));
  51. void disable_wdt_timer(void)
  52. {
  53. MCUSR = 0;
  54. WDTCSR = (1<<WDCE) | (1<<WDE);
  55. WDTCSR = (0<<WDE);
  56. } /* disable_wdt_timer */
  57. int main(void) __attribute__ ((noreturn));
  58. int main(void)
  59. {
  60. /* init LEDs */
  61. LED_INIT();
  62. /* timer0, FCPU/64, overflow interrupt */
  63. TCCR0B = (1<<CS01) | (1<<CS00);
  64. TIMSK0 = (1<<TOIE0);
  65. uart_init();
  66. rfm12_init(RFM12_ADDRESS);
  67. sei();
  68. uint8_t command = BRIDGE_CMD_IDLE;
  69. uint8_t timeout = 0;
  70. uint8_t datalen = 0;
  71. uint8_t bcnt = 0;
  72. while (1)
  73. {
  74. if (clock_tick)
  75. {
  76. clock_tick = 0;
  77. if (led_timer > 0)
  78. {
  79. LED_ON();
  80. led_timer--;
  81. }
  82. else
  83. {
  84. LED_OFF();
  85. }
  86. /* do periodic work (wait for 5 ticks silence before start TX) */
  87. rfm12_tick(5);
  88. if (timeout != 0)
  89. {
  90. timeout--;
  91. }
  92. }
  93. uint8_t rx_count = uart_rx_count();
  94. if ((command == BRIDGE_CMD_IDLE) && (rx_count != 0))
  95. {
  96. command = uart_getc();
  97. datalen = 0;
  98. timeout = 0;
  99. bcnt = 1;
  100. switch (command)
  101. {
  102. case 'R':
  103. timeout = 200;
  104. case 'T':
  105. case 'V':
  106. break;
  107. default:
  108. uart_putc(command);
  109. uart_putc(BRIDGE_CAUSE_NOT_SUPPORTED);
  110. uart_putc(0x00);
  111. command = BRIDGE_CMD_IDLE;
  112. break;
  113. }
  114. }
  115. else if ((bcnt == 1) && (rx_count != 0))
  116. {
  117. datalen = uart_getc();
  118. bcnt++;
  119. }
  120. else
  121. {
  122. if ((command == BRIDGE_CMD_TRANSMIT) & (bcnt == 2) && (rx_count == datalen))
  123. {
  124. struct rfm12_packet * pkt = rfm12_get_txpkt();
  125. if (pkt == (void *)0)
  126. {
  127. uart_putc(command);
  128. uart_putc(BRIDGE_CAUSE_UNSPECIFIED_ERROR);
  129. uart_putc(0x00);
  130. }
  131. else
  132. {
  133. pkt->dest_address = uart_getc();
  134. pkt->source_address = uart_getc();
  135. pkt->data_length = uart_getc();
  136. pkt->header_checksum = uart_getc();
  137. datalen -= 4;
  138. uint8_t i = 0;
  139. while (datalen--)
  140. {
  141. pkt->data[i++] = uart_getc();
  142. }
  143. rfm12_start_tx();
  144. led_timer = 5;
  145. uart_putc(command);
  146. uart_putc(BRIDGE_CAUSE_SUCCESS);
  147. uart_putc(0x00);
  148. }
  149. command = BRIDGE_CMD_IDLE;
  150. }
  151. else if ((command == BRIDGE_CMD_RECEIVE) && (bcnt == 2))
  152. {
  153. if ((datalen != 0) && (rx_count != 0))
  154. {
  155. datalen--;
  156. uart_getc();
  157. }
  158. else if (timeout == 0)
  159. {
  160. uart_putc(command);
  161. uart_putc(BRIDGE_CAUSE_TIMEOUT);
  162. uart_putc(0);
  163. command = BRIDGE_CMD_IDLE;
  164. }
  165. else
  166. {
  167. struct rfm12_packet *pkt = rfm12_get_rxpkt();
  168. if (pkt)
  169. {
  170. uint8_t i;
  171. led_timer = 5;
  172. uart_putc(command);
  173. uart_putc(BRIDGE_CAUSE_SUCCESS);
  174. uart_putc(pkt->data_length + 4);
  175. uart_putc(pkt->dest_address);
  176. uart_putc(pkt->source_address);
  177. uart_putc(pkt->data_length);
  178. uart_putc(pkt->header_checksum);
  179. for (i = 0; i < pkt->data_length; i++)
  180. {
  181. uart_putc(pkt->data[i]);
  182. }
  183. command = BRIDGE_CMD_IDLE;
  184. }
  185. }
  186. }
  187. else if ((command == BRIDGE_CMD_VERSION) && (bcnt == 2))
  188. {
  189. if ((datalen != 0) && (rx_count != 0))
  190. {
  191. datalen--;
  192. uart_getc();
  193. }
  194. else
  195. {
  196. uart_putc(command);
  197. uart_putc(BRIDGE_CAUSE_SUCCESS);
  198. uart_putc(16);
  199. uart_putstr("funkbridge v0.99");
  200. command = BRIDGE_CMD_IDLE;
  201. }
  202. }
  203. }
  204. }
  205. } /* main */