diff --git a/event.c b/event.c index 3ae1286..38d5f7b 100644 --- a/event.c +++ b/event.c @@ -23,7 +23,6 @@ /* *********************************************************************** */ #define EVENT_COUNT 16 -#define TIMER_COUNT 8 static struct event_entry events[EVENT_COUNT]; static volatile uint8_t event_in_idx; diff --git a/event.h b/event.h index c5429f1..b728463 100644 --- a/event.h +++ b/event.h @@ -12,11 +12,13 @@ struct event_entry #define EVENT_TYPE_EMPTY 0x00 #define EVENT_TYPE_GENERIC 0x01 -#define EVENT_TYPE_INPUT 0x02 -#define EVENT_TYPE_PWM_COMMAND 0x03 -#define EVENT_TYPE_PWM_VALUE 0x04 -#define EVENT_TYPE_TIMER_SET 0x05 -#define EVENT_TYPE_TIMER_ELAPSED 0x06 +#define EVENT_TYPE_INPUT_SWITCH 0x10 +#define EVENT_TYPE_INPUT_BUTTON 0x11 +#define EVENT_TYPE_INPUT_INCDEC 0x12 +#define EVENT_TYPE_PWM_COMMAND 0x18 +#define EVENT_TYPE_PWM_VALUE 0x19 +#define EVENT_TYPE_TIMER_SET 0xF0 +#define EVENT_TYPE_TIMER_ELAPSED 0xF1 /* *********************************************************************** */ diff --git a/funk_proto.h b/funk_proto.h index 0916b45..cc25d55 100644 --- a/funk_proto.h +++ b/funk_proto.h @@ -1,6 +1,8 @@ #ifndef __FUNK_PROTO_H__ #define __FUNK_PROTO_H__ +#include + /* *********************************************************************** */ /* @@ -12,8 +14,6 @@ * - initiator increases seqnum and sends request again * - commands have 2bit req/resp/ind/conf encoding * - single window - * - multi master should be supported (for lights talking to each other) - * * * - firmware has modules, that communicate through "events" * - INPUT modules (button/quadencoder) send events to all other (!INPUT) modules @@ -22,9 +22,6 @@ * - communication receives all events and can send to anyone * - configuration in eeprom(?) to enable which events shall be send (and to who) * - * - or is there a register service? - * - need to detect if device is restarted and register again - * * - support to switch to bootloader * - support forward to mpm/twi * @@ -48,6 +45,8 @@ #define MSG_CMD_DESCRIPTION_RESPONSE (MSG_TYPE_RESPONSE | 0x02) /* 0xC2 */ #define MSG_CMD_CONTROL_REQUEST (MSG_TYPE_REQUEST | 0x03) /* 0x03 */ #define MSG_CMD_CONTROL_RESPONSE (MSG_TYPE_RESPONSE | 0x03) /* 0xC3 */ +#define MSG_CMD_REGISTER_REQUEST (MSG_TYPE_REQUEST | 0x04) /* 0x04 */ +#define MSG_CMD_REGISTER_RESPONSE (MSG_TYPE_RESPONSE | 0x04) /* 0xC4 */ #define MSG_CMD_EVENT_INDICATION (MSG_TYPE_INDICATION | 0x03) /* 0x83 */ #define MSG_CMD_EVENT_CONFIRMATION (MSG_TYPE_CONFIRMATION | 0x03) /* 0x43 */ @@ -67,6 +66,9 @@ #define CAUSE_INVALID_PARAMETER 0xF1 #define CAUSE_UNSPECIFIED_ERROR 0xFF +#define DESCRIPTION_TYPE_CONTROL 0x01 +#define DESCRIPTION_TYPE_EVENT 0x02 + #define BOOTMODE_BOOTLOADER 0x00 #define BOOTMODE_APPLICATION 0x80 @@ -75,92 +77,151 @@ /* *********************************************************************** */ +/* +* Send a Description Request to a Light +* - type is "Control" or "Event" +* - num is number of controls or events +*/ +struct _description_request +{ + uint8_t type; + uint8_t num; +} __attribute__ ((__packed__)); + + +/* +* Send a Description Response to the master +* - type is Control or Event +* - num is number of controls or event +* - max_num is the max number of controls or events +* - data_type is used in Control_req / Event_ind +* - data_num is used in Control_req / Event_ind +* - data_desc is short ASCII name of that control/event +*/ +struct _description_response +{ + uint8_t type; + uint8_t num; + uint8_t max_num; + uint8_t data_type; + uint8_t data_num; + uint8_t data_desc[16]; +} __attribute__ ((__packed__)); + + +/* +* Send a Control Request to a Light +* - data_type is "button_press", "abs_dim_value", "step_up/down" +* - data_num is button_numer or channel ID of light +* - data is for abs values, width is encoded in ctrl_type +*/ +struct _control_request +{ + uint8_t data_type; + uint8_t data_num; + uint16_t data_value; +} __attribute__ ((__packed__)); + + +/* +* Response for Control Request +* just repeat the type & num +* cause is in header +*/ +struct _control_response +{ + uint8_t data_type; + uint8_t data_num; +} __attribute__ ((__packed__)); + + +/* + * Register a Event + * - data_type is "button_press", "movement detected", "step up/down" + * - data_num is button number or channel ID + * - enable is true/false + */ +struct _register_request +{ + uint8_t data_type; + uint8_t data_num; + uint8_t enable; +} __attribute__ ((__packed__)); + + +/* + * Response for Register Request + * - data_type is "button_press", "movement detected", "step up/down" + * - data_num is button number or channel ID + * - data_value is last known value + */ +struct _register_response +{ + uint8_t data_type; + uint8_t data_num; + uint16_t data_value; +} __attribute__ ((__packed__)); + + +/* + * Send a Event to Master + * - data_type is "button_press", "movement detected", "step up/down" + * - data_num is button number or channel ID + * - data is for abs values, width is encoded in ctrl_type + */ + struct _event_indication +{ + uint8_t data_type; + uint8_t data_num; + uint16_t data_value; +} __attribute__ ((__packed__)); + + +/* +* Confirmation of event indication +* just repeat the type & num +* cause is in header +*/ +struct _event_confirmation +{ + uint8_t data_type; + uint8_t data_num; +} __attribute__ ((__packed__)); + + struct rfm12_msg { uint8_t command; /* MSG_CMD_* */ uint8_t seqnum; uint8_t cause; /* CAUSE_* */ - union { - /* - * Send a Description Request to a Light - * - type is "Control" or "Event" - * - num is 1-based number of controls or events - */ - struct { /* MSG_CMD_DESCRIPTION_REQUEST */ - uint8_t type; - uint8_t num; - } desc_req; + union + { + /* application messages */ - /* - * Send a Description Response to the master - * - type is Control or Event - * - num is 1-based number of controls or event - * - max_num is the max number of controls or events - * - data_type is used in Control_req / Event_ind - * - data_num is used in Control_req / Event_ind - * - data_desc is short ASCII name of that control/event - */ - struct { /* MSG_CMD_DESCRIPTION_RESPONSE */ - uint8_t type; - uint8_t num; - uint8_t max_num; - uint8_t data_type; - uint8_t data_num; - uint8_t data_desc[16]; - } desc_rsp; + /* MSG_CMD_DESCRIPTION_REQUEST */ + struct _description_request desc_req; - /* - * Send a Control Request to a Light - * - data_type is "button_press", "abs_dim_value", "step_up/down" - * - data_num is button_numer or channel ID of light - * - data is for abs values, width is encoded in ctrl_type - */ - struct { /* MSG_CMD_CONTROL_REQUEST */ - uint8_t data_type; - uint8_t data_num; - union { - uint8_t u8[4]; - uint16_t u16[2]; - uint32_t u32; - } data; - } ctrl_req; + /* MSG_CMD_DESCRIPTION_RESPONSE */ + struct _description_response desc_rsp; - /* - * Response for Control Response - * just repeat the type & num - * cause is in header - */ - struct { /* MSG_CMD_CONTROL_RESPONSE */ - uint8_t data_type; - uint8_t data_num; - } ctrl_rsp; + /* MSG_CMD_CONTROL_REQUEST */ + struct _control_request ctrl_req; - /* - * Send a Event to Master - * - data_type is "button_press", "movement detected", "step up/down" - * - data_num is button number or channel ID - * - data is for abs values, width is encoded in ctrl_type - */ - struct { /* MSG_CMD_EVENT_INDICATION */ - uint8_t data_type; - uint8_t data_num; - union { - uint8_t u8[4]; - uint16_t u16[2]; - uint32_t u32; - } data; - } evt_ind; + /* MSG_CMD_CONTROL_RESPONSE */ + struct _control_response ctrl_rsp; - /* - * Confirmation of event indication - * just repeat the type & num - * cause is in header - */ - struct { /* MSG_CMD_EVENT_CONFIRMATION */ - uint8_t data_type; - uint8_t data_num; - } evt_cnf; + /* MSG_CMD_REGISTER_REQUEST */ + struct _register_request reg_req; + + /* MSG_CMD_REGISTER_RESPONSE */ + struct _register_response reg_rsp; + + /* MSG_CMD_EVENT_INDICATION */ + struct _event_indication evt_ind; + + /* MSG_CMD_EVENT_CONFIRMATION */ + struct _event_confirmation evt_cnf; /* bootloader messages */ @@ -193,7 +254,7 @@ struct rfm12_msg uint8_t data[32]; } write_req; } p; -}; +} __attribute__ ((__packed__)); /* *********************************************************************** */ diff --git a/funkstuff.c b/funkstuff.c index 5d162f8..6f0440e 100644 --- a/funkstuff.c +++ b/funkstuff.c @@ -33,6 +33,22 @@ #include "funk_proto.h" #include "target.h" +#define ARRAY_SIZE(x) (sizeof(x) / sizeof(*x)) + +/* *********************************************************************** */ + +static const struct _description_response control_desc[] PROGMEM = { + { DESCRIPTION_TYPE_CONTROL, 0xFF, 0xFF, EVENT_TYPE_PWM_COMMAND, EVENT_NUM_PWM_CH0, "Door Light Cmd" }, + { DESCRIPTION_TYPE_CONTROL, 0xFF, 0xFF, EVENT_TYPE_PWM_COMMAND, EVENT_NUM_PWM_CH1, "Wall Light Cmd" }, + { DESCRIPTION_TYPE_CONTROL, 0xFF, 0xFF, EVENT_TYPE_PWM_VALUE, EVENT_NUM_PWM_CH0, "Door Light Val" }, + { DESCRIPTION_TYPE_CONTROL, 0xFF, 0xFF, EVENT_TYPE_PWM_VALUE, EVENT_NUM_PWM_CH1, "Wall Light Val" }, +}; + +static const struct _description_response event_desc[] PROGMEM = { + { DESCRIPTION_TYPE_EVENT, 0xFF, 0xFF, EVENT_TYPE_INPUT_BUTTON, EVENT_NUM_INPUT_BUTTON, "Wall Button" }, + { DESCRIPTION_TYPE_EVENT, 0xFF, 0xFF, EVENT_TYPE_INPUT_SWITCH, EVENT_NUM_INPUT_DOOR, "Door Switch" }, +}; + /* *********************************************************************** */ #define LED_RX 0 @@ -73,19 +89,6 @@ static void led_tick(void) } } /* led_tick */ -static void uart_event_handler(struct event_entry *event) -{ - /* output all events on UART */ - uart_putstr_p(PSTR("evt: ")); - uart_put_hex(event->type); - uart_putc(' '); - uart_put_hex(event->num); - uart_putc(' '); - uart_put_hex(event->value >> 8); - uart_put_hex(event->value & 0xFF); - uart_putstr("\r\n"); -} /* uart_event_handler */ - /* * For newer devices the watchdog timer remains active even after a @@ -136,8 +139,17 @@ int main(void) struct event_entry *event = event_get(); if (event->type != EVENT_TYPE_EMPTY) { - uart_event_handler(event); - +#if 0 + /* output all events on UART */ + uart_putstr_p(PSTR("evt: ")); + uart_put_hex(event->type); + uart_putc(' '); + uart_put_hex(event->num); + uart_putc(' '); + uart_put_hex(event->value >> 8); + uart_put_hex(event->value & 0xFF); + uart_putstr("\r\n"); +#endif switch (event->type) { case EVENT_TYPE_PWM_COMMAND: @@ -145,7 +157,7 @@ int main(void) pwm_event_handler(event); break; - case EVENT_TYPE_INPUT: + case EVENT_TYPE_INPUT_INCDEC: if (event->num == EVENT_NUM_INPUT_QUAD) { if (event->value == EVENT_VALUE_INPUT_QUAD_DEC) @@ -163,7 +175,10 @@ int main(void) ); } } - else if (event->num == EVENT_NUM_INPUT_BUTTON) + break; + + case EVENT_TYPE_INPUT_BUTTON: + if (event->num == EVENT_NUM_INPUT_BUTTON) { if (event->value == EVENT_VALUE_INPUT_BUTTON_PRESSED) { @@ -173,7 +188,10 @@ int main(void) ); } } - else if (event->num == EVENT_NUM_INPUT_DOOR) + break; + + case EVENT_TYPE_INPUT_SWITCH: + if (event->num == EVENT_NUM_INPUT_DOOR) { if (event->value == EVENT_VALUE_INPUT_DOOR_CLOSED) { @@ -238,6 +256,7 @@ int main(void) struct rfm12_msg *req_msg = (struct rfm12_msg *)req_pkt->data; struct rfm12_msg *rsp_msg = (struct rfm12_msg *)rsp_pkt->data; +#if 0 /* retransmitted request -> retransmit response */ if ((req_pkt->source_address == rsp_pkt->dest_address) && ((req_msg->command & MSG_CMD_MASK) == (rsp_msg->command & MSG_CMD_MASK)) && @@ -255,6 +274,7 @@ int main(void) continue; } +#endif rsp_pkt->dest_address = req_pkt->source_address; rsp_pkt->data_length = 3; @@ -262,6 +282,7 @@ int main(void) rsp_msg->seqnum = req_msg->seqnum; rsp_msg->cause = CAUSE_SUCCESS; + uint8_t i; switch (req_msg->command) { case MSG_CMD_SWITCHAPP_REQUEST: @@ -275,6 +296,59 @@ int main(void) } break; + case MSG_CMD_DESCRIPTION_REQUEST: + if ((req_msg->p.desc_req.type == DESCRIPTION_TYPE_CONTROL) && + (req_msg->p.desc_req.num < ARRAY_SIZE(control_desc)) + ) + { + memcpy_P(&rsp_msg->p.desc_rsp, + &control_desc[req_msg->p.desc_req.num], + sizeof(struct _description_response)); + + rsp_msg->p.desc_rsp.num = req_msg->p.desc_req.num; + rsp_msg->p.desc_rsp.max_num = ARRAY_SIZE(control_desc) -1; + rsp_pkt->data_length += sizeof(struct _description_response); + } + else if ((req_msg->p.desc_req.type == DESCRIPTION_TYPE_EVENT) && + (req_msg->p.desc_req.num < ARRAY_SIZE(event_desc)) + ) + { + memcpy_P(&rsp_msg->p.desc_rsp, + &event_desc[req_msg->p.desc_req.num], + sizeof(struct _description_response)); + + rsp_msg->p.desc_rsp.num = req_msg->p.desc_req.num; + rsp_msg->p.desc_rsp.max_num = ARRAY_SIZE(event_desc) -1; + rsp_pkt->data_length += sizeof(struct _description_response); + } + else + { + rsp_msg->cause = CAUSE_INVALID_PARAMETER; + } + break; + + case MSG_CMD_CONTROL_REQUEST: + rsp_msg->cause = CAUSE_INVALID_PARAMETER; + + for (i = 0; i < ARRAY_SIZE(control_desc); i++) + { + if ((pgm_read_byte(&control_desc[i].data_type) == req_msg->p.ctrl_req.data_type) && + (pgm_read_byte(&control_desc[i].data_num) == req_msg->p.ctrl_req.data_num) + ) + { + event_queue(req_msg->p.ctrl_req.data_type, + req_msg->p.ctrl_req.data_num, + req_msg->p.ctrl_req.data_value); + + rsp_msg->cause = CAUSE_SUCCESS; + rsp_msg->p.ctrl_rsp.data_type = req_msg->p.ctrl_req.data_type; + rsp_msg->p.ctrl_rsp.data_num = req_msg->p.ctrl_req.data_num; + rsp_pkt->data_length += sizeof(struct _control_response); + break; + } + } + break; + default: rsp_msg->cause = CAUSE_NOT_SUPPORTED; break; diff --git a/input.c b/input.c index 125802f..106c6c7 100644 --- a/input.c +++ b/input.c @@ -36,19 +36,14 @@ static uint8_t input_old_state[2]; /* *********************************************************************** */ -static void input_send_event(uint8_t channel, uint8_t state) +static void input_send_event(uint8_t type, uint8_t num, uint8_t state) { - if ((channel != EVENT_NUM_INPUT_BUTTON) && (channel != EVENT_NUM_INPUT_DOOR)) + if ((debounce_timer[num] == 0) && (state != input_old_state[num])) { - return; - } + event_queue(type, num, state); - if ((debounce_timer[channel -2] == 0) && (state != input_old_state[channel -2])) - { - event_queue(EVENT_TYPE_INPUT, channel, state); - - debounce_timer[channel -2] = INPUT_DEBOUNCE_TIMER; - input_old_state[channel -2] = state; + debounce_timer[num] = INPUT_DEBOUNCE_TIMER; + input_old_state[num] = state; } } /* input_send_event */ @@ -102,12 +97,16 @@ ISR(PCINT1_vect) /* quadruple decoder switch changed */ else if (pcint & (1< 0) + if (debounce_timer[EVENT_NUM_INPUT_BUTTON] > 0) { - debounce_timer[0]--; - if (debounce_timer[0] == 0) + debounce_timer[EVENT_NUM_INPUT_BUTTON]--; + if (debounce_timer[EVENT_NUM_INPUT_BUTTON] == 0) { - input_send_event(EVENT_NUM_INPUT_BUTTON, !!(PINC & (1< 0) + if (debounce_timer[EVENT_NUM_INPUT_DOOR] > 0) { - debounce_timer[1]--; - if (debounce_timer[1] == 0) + debounce_timer[EVENT_NUM_INPUT_DOOR]--; + if (debounce_timer[EVENT_NUM_INPUT_DOOR] == 0) { - input_send_event(EVENT_NUM_INPUT_DOOR, !!(PINC & (1< #include "event.h" +#include "timer.h" /* *********************************************************************** */ -#define TIMER_COUNT 2 - static uint16_t timers[TIMER_COUNT]; /* *********************************************************************** */ diff --git a/timer.h b/timer.h index 624dfad..3a928fc 100644 --- a/timer.h +++ b/timer.h @@ -4,6 +4,7 @@ /* *********************************************************************** */ #define TIMER_DOOR_CLOSE_DELAY 0 +#define TIMER_COUNT 2 /* *********************************************************************** */