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.
 
 
 

430 lines
16 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/wdt.h>
  22. #include <avr/pgmspace.h>
  23. #include <string.h> /* memcpy() */
  24. #include "event.h"
  25. #include "input.h"
  26. #include "pwm.h"
  27. #include "rfm12.h"
  28. #include "timer.h"
  29. #include "uart.h"
  30. #include "funk_proto.h"
  31. #include "target.h"
  32. #define ARRAY_SIZE(x) (sizeof(x) / sizeof(*x))
  33. /* *********************************************************************** */
  34. static const struct _description_response control_desc[] PROGMEM = {
  35. { DESCRIPTION_TYPE_CONTROL, 0xFF, 0xFF, EVENT_TYPE_PWM_COMMAND, EVENT_NUM_PWM_CH0, "door/pwm_cmd" },
  36. { DESCRIPTION_TYPE_CONTROL, 0xFF, 0xFF, EVENT_TYPE_PWM_COMMAND, EVENT_NUM_PWM_CH1, "wall/pwm_cmd" },
  37. { DESCRIPTION_TYPE_CONTROL, 0xFF, 0xFF, EVENT_TYPE_PWM_VALUE, EVENT_NUM_PWM_CH0, "door/pwm_set" },
  38. { DESCRIPTION_TYPE_CONTROL, 0xFF, 0xFF, EVENT_TYPE_PWM_VALUE, EVENT_NUM_PWM_CH1, "wall/pwm_set" },
  39. };
  40. static const struct _description_response event_desc[] PROGMEM = {
  41. // { DESCRIPTION_TYPE_EVENT, 0xFF, 0xFF, EVENT_TYPE_INPUT_BUTTON, EVENT_NUM_INPUT_BUTTON, "wall/input" },
  42. // { DESCRIPTION_TYPE_EVENT, 0xFF, 0xFF, EVENT_TYPE_INPUT_SWITCH, EVENT_NUM_INPUT_DOOR, "door/input" },
  43. { DESCRIPTION_TYPE_EVENT, 0xFF, 0xFF, EVENT_TYPE_PWM_STATUS, EVENT_NUM_PWM_CH0, "door/pwm" },
  44. { DESCRIPTION_TYPE_EVENT, 0xFF, 0xFF, EVENT_TYPE_PWM_STATUS, EVENT_NUM_PWM_CH1, "wall/pwm" },
  45. };
  46. #define EVT_DATA_STATE_FREE 0x00
  47. #define EVT_DATA_STATE_REGISTERED 0x01
  48. #define EVT_DATA_STATE_UPDATE 0x02
  49. #define EVT_DATA_STATE_WAIT4CONF 0x04
  50. struct _event_data
  51. {
  52. uint8_t state; // free/registered/wait4conf/retrigger
  53. uint8_t dest_address;
  54. uint16_t data_value; // type/num via event_desc with same idx
  55. };
  56. static struct _event_data event_data[2];
  57. static uint8_t event_idx;
  58. static uint8_t rtx_count;
  59. /* *********************************************************************** */
  60. #define LED_RX 0
  61. #define LED_TX 1
  62. static uint8_t led[2];
  63. static void led_tick(void)
  64. {
  65. if (led[LED_RX] > 0)
  66. {
  67. led[LED_RX]--;
  68. LED_GN_ON();
  69. }
  70. else
  71. {
  72. LED_GN_OFF();
  73. }
  74. if (led[LED_TX] > 0)
  75. {
  76. led[LED_TX]--;
  77. LED_RT_ON();
  78. }
  79. else
  80. {
  81. LED_RT_OFF();
  82. }
  83. } /* led_tick */
  84. /*
  85. * For newer devices the watchdog timer remains active even after a
  86. * system reset. So disable it as soon as possible.
  87. * automagically called on startup
  88. */
  89. void disable_wdt_timer(void) __attribute__((naked, section(".init3")));
  90. void disable_wdt_timer(void)
  91. {
  92. MCUSR = 0;
  93. WDTCSR = (1<<WDCE) | (1<<WDE);
  94. WDTCSR = (0<<WDE);
  95. } /* disable_wdt_timer */
  96. int main(void)
  97. {
  98. LED_INIT();
  99. timer_init();
  100. uart_init();
  101. input_init();
  102. pwm_init();
  103. rfm12_init(RFM12_ADDRESS);
  104. sei();
  105. uart_putstr_p(PSTR("init\r\n"));
  106. while (1)
  107. {
  108. if (timer_check(1))
  109. {
  110. /* do periodic work (wait for 5 ticks silence before start TX) */
  111. rfm12_tick(5);
  112. led_tick();
  113. }
  114. struct event_entry *event = event_get();
  115. if (event->type != EVENT_TYPE_EMPTY)
  116. {
  117. #if 0
  118. /* output all events on UART */
  119. uart_putstr_p(PSTR("evt: "));
  120. uart_put_hex(event->type);
  121. uart_putc(' ');
  122. uart_put_hex(event->num);
  123. uart_putc(' ');
  124. uart_put_hex(event->value >> 8);
  125. uart_put_hex(event->value & 0xFF);
  126. uart_putstr("\r\n");
  127. #endif
  128. switch (event->type)
  129. {
  130. case EVENT_TYPE_PWM_COMMAND:
  131. case EVENT_TYPE_PWM_VALUE:
  132. pwm_event_handler(event);
  133. break;
  134. case EVENT_TYPE_INPUT_INCDEC:
  135. if (event->num == EVENT_NUM_INPUT_QUAD)
  136. {
  137. if (event->value == EVENT_VALUE_INPUT_QUAD_DEC)
  138. {
  139. event_queue(EVENT_TYPE_PWM_COMMAND,
  140. EVENT_NUM_PWM_CH1,
  141. EVENT_VALUE_PWM_DEC);
  142. }
  143. else if (event->value == EVENT_VALUE_INPUT_QUAD_INC)
  144. {
  145. event_queue(EVENT_TYPE_PWM_COMMAND,
  146. EVENT_NUM_PWM_CH1,
  147. EVENT_VALUE_PWM_INC);
  148. }
  149. }
  150. break;
  151. case EVENT_TYPE_INPUT_BUTTON:
  152. if (event->num == EVENT_NUM_INPUT_BUTTON)
  153. {
  154. if (event->value == EVENT_VALUE_INPUT_BUTTON_PRESSED)
  155. {
  156. event_queue(EVENT_TYPE_PWM_COMMAND,
  157. EVENT_NUM_PWM_CH1,
  158. EVENT_VALUE_PWM_TOGGLE);
  159. }
  160. }
  161. break;
  162. case EVENT_TYPE_INPUT_SWITCH:
  163. if (event->num == EVENT_NUM_INPUT_DOOR)
  164. {
  165. if (event->value == EVENT_VALUE_INPUT_DOOR_CLOSED)
  166. {
  167. event_queue(EVENT_TYPE_PWM_COMMAND,
  168. EVENT_NUM_PWM_CH0,
  169. EVENT_VALUE_PWM_KEEP);
  170. event_queue(EVENT_TYPE_TIMER_SET,
  171. EVENT_NUM_TIMER_DOOR_CLOSE_DELAY,
  172. 2000);
  173. }
  174. else if (event->value == EVENT_VALUE_INPUT_DOOR_OPEN)
  175. {
  176. event_queue(EVENT_TYPE_PWM_COMMAND,
  177. EVENT_NUM_PWM_CH0,
  178. EVENT_VALUE_PWM_FADE_MAX);
  179. event_queue(EVENT_TYPE_TIMER_SET,
  180. EVENT_NUM_TIMER_DOOR_CLOSE_DELAY,
  181. 0);
  182. }
  183. }
  184. break;
  185. case EVENT_TYPE_TIMER_SET:
  186. timer_event_handler(event);
  187. break;
  188. case EVENT_TYPE_TIMER_ELAPSED:
  189. if ((event->num == EVENT_NUM_TIMER_DEBOUNCE1) ||
  190. (event->num == EVENT_NUM_TIMER_DEBOUNCE2)
  191. )
  192. {
  193. input_event_handler(event);
  194. }
  195. else if (event->num == EVENT_NUM_TIMER_DOOR_CLOSE_DELAY)
  196. {
  197. event_queue(EVENT_TYPE_PWM_COMMAND,
  198. EVENT_NUM_PWM_CH0,
  199. EVENT_VALUE_PWM_FADE_MIN);
  200. }
  201. break;
  202. default:
  203. break;
  204. }
  205. uint8_t i;
  206. for (i = 0; i < ARRAY_SIZE(event_desc); i++)
  207. {
  208. if ((pgm_read_byte(&event_desc[i].data_type) == event->type) &&
  209. (pgm_read_byte(&event_desc[i].data_num) == event->num)
  210. )
  211. {
  212. event_data[i].data_value = event->value;
  213. if (event_data[i].state & EVT_DATA_STATE_REGISTERED)
  214. {
  215. event_data[i].state |= EVT_DATA_STATE_UPDATE;
  216. }
  217. }
  218. }
  219. event_clear();
  220. }
  221. /* get RX data */
  222. struct rfm12_packet *rx_pkt = rfm12_get_rxpkt();
  223. if (rx_pkt != NULL)
  224. {
  225. led[LED_RX] = 5;
  226. struct rfm12_msg *rx_msg = (struct rfm12_msg *)rx_pkt->data;
  227. if ((rx_msg->command & MSG_TYPE_MASK) == MSG_TYPE_REQUEST)
  228. {
  229. struct rfm12_packet *rsp_pkt = rfm12_get_txpkt();
  230. if (rsp_pkt == NULL)
  231. {
  232. rfm12_clear_rx();
  233. continue;
  234. }
  235. struct rfm12_msg *rsp_msg = (struct rfm12_msg *)rsp_pkt->data;
  236. rsp_pkt->dest_address = rx_pkt->source_address;
  237. rsp_pkt->data_length = 3;
  238. rsp_msg->command = rx_msg->command | MSG_TYPE_RESPONSE;
  239. rsp_msg->seqnum = rx_msg->seqnum;
  240. rsp_msg->cause = CAUSE_SUCCESS;
  241. uint8_t i;
  242. switch (rx_msg->command)
  243. {
  244. case MSG_CMD_SWITCHAPP_REQUEST:
  245. if (rx_msg->p.switchapp.app == BOOTMODE_BOOTLOADER)
  246. {
  247. wdt_enable(WDTO_15MS);
  248. }
  249. else if (rx_msg->p.switchapp.app != BOOTMODE_APPLICATION)
  250. {
  251. rsp_msg->cause = CAUSE_INVALID_PARAMETER;
  252. }
  253. break;
  254. case MSG_CMD_DESCRIPTION_REQUEST:
  255. if ((rx_msg->p.desc_req.type == DESCRIPTION_TYPE_CONTROL) &&
  256. (rx_msg->p.desc_req.num < ARRAY_SIZE(control_desc))
  257. )
  258. {
  259. memcpy_P(&rsp_msg->p.desc_rsp,
  260. &control_desc[rx_msg->p.desc_req.num],
  261. sizeof(struct _description_response));
  262. rsp_msg->p.desc_rsp.num = rx_msg->p.desc_req.num;
  263. rsp_msg->p.desc_rsp.max_num = ARRAY_SIZE(control_desc) -1;
  264. rsp_pkt->data_length += sizeof(struct _description_response);
  265. }
  266. else if ((rx_msg->p.desc_req.type == DESCRIPTION_TYPE_EVENT) &&
  267. (rx_msg->p.desc_req.num < ARRAY_SIZE(event_desc))
  268. )
  269. {
  270. memcpy_P(&rsp_msg->p.desc_rsp,
  271. &event_desc[rx_msg->p.desc_req.num],
  272. sizeof(struct _description_response));
  273. rsp_msg->p.desc_rsp.num = rx_msg->p.desc_req.num;
  274. rsp_msg->p.desc_rsp.max_num = ARRAY_SIZE(event_desc) -1;
  275. rsp_pkt->data_length += sizeof(struct _description_response);
  276. }
  277. else
  278. {
  279. rsp_msg->cause = CAUSE_INVALID_PARAMETER;
  280. }
  281. break;
  282. case MSG_CMD_CONTROL_REQUEST:
  283. rsp_msg->cause = CAUSE_INVALID_PARAMETER;
  284. for (i = 0; i < ARRAY_SIZE(control_desc); i++)
  285. {
  286. if ((pgm_read_byte(&control_desc[i].data_type) == rx_msg->p.ctrl_req.data_type) &&
  287. (pgm_read_byte(&control_desc[i].data_num) == rx_msg->p.ctrl_req.data_num)
  288. )
  289. {
  290. event_queue(rx_msg->p.ctrl_req.data_type,
  291. rx_msg->p.ctrl_req.data_num,
  292. rx_msg->p.ctrl_req.data_value);
  293. rsp_msg->cause = CAUSE_SUCCESS;
  294. rsp_msg->p.ctrl_rsp.data_type = rx_msg->p.ctrl_req.data_type;
  295. rsp_msg->p.ctrl_rsp.data_num = rx_msg->p.ctrl_req.data_num;
  296. rsp_pkt->data_length += sizeof(struct _control_response);
  297. break;
  298. }
  299. }
  300. break;
  301. case MSG_CMD_REGISTER_REQUEST:
  302. rsp_msg->cause = CAUSE_INVALID_PARAMETER;
  303. for (i = 0; i < ARRAY_SIZE(event_desc); i++)
  304. {
  305. if ((pgm_read_byte(&event_desc[i].data_type) == rx_msg->p.reg_req.data_type) &&
  306. (pgm_read_byte(&event_desc[i].data_num) == rx_msg->p.reg_req.data_num)
  307. )
  308. {
  309. if (rx_msg->p.reg_req.enable)
  310. {
  311. event_data[i].state |= EVT_DATA_STATE_REGISTERED;
  312. event_data[i].dest_address = rx_pkt->source_address;
  313. }
  314. else
  315. {
  316. event_data[i].state |= ~(EVT_DATA_STATE_REGISTERED | EVT_DATA_STATE_UPDATE);
  317. }
  318. rsp_msg->cause = CAUSE_SUCCESS;
  319. rsp_msg->p.reg_rsp.data_type = rx_msg->p.reg_req.data_type;
  320. rsp_msg->p.reg_rsp.data_num = rx_msg->p.reg_req.data_num;
  321. rsp_msg->p.reg_rsp.data_value = event_data[i].data_value;
  322. rsp_pkt->data_length += sizeof(struct _register_response);
  323. break;
  324. }
  325. }
  326. break;
  327. default:
  328. rsp_msg->cause = CAUSE_NOT_SUPPORTED;
  329. break;
  330. }
  331. /* RX packet no longer needed */
  332. rfm12_clear_rx();
  333. /* transmit response */
  334. if (rfm12_start_tx())
  335. {
  336. led[LED_TX] = 5;
  337. }
  338. }
  339. else if ((rx_msg->command & MSG_TYPE_MASK) == MSG_TYPE_CONFIRMATION)
  340. {
  341. uint8_t i;
  342. switch (rx_msg->command)
  343. {
  344. case MSG_CMD_EVENT_CONFIRMATION:
  345. for (i = 0; i < ARRAY_SIZE(event_desc); i++)
  346. {
  347. if ((pgm_read_byte(&event_desc[i].data_type) == rx_msg->p.evt_cnf.data_type) &&
  348. (pgm_read_byte(&event_desc[i].data_num) == rx_msg->p.evt_cnf.data_num)
  349. )
  350. {
  351. if (event_data[i].state & EVT_DATA_STATE_WAIT4CONF)
  352. {
  353. event_data[i].state &= ~(EVT_DATA_STATE_WAIT4CONF);
  354. event_idx++;
  355. if (event_idx == ARRAY_SIZE(event_desc))
  356. {
  357. event_idx = 0;
  358. }
  359. }
  360. }
  361. }
  362. break;
  363. default:
  364. break;
  365. }
  366. /* RX packet no longer needed */
  367. rfm12_clear_rx();
  368. }
  369. }
  370. }
  371. return 0;
  372. } /* main */