summaryrefslogtreecommitdiff
path: root/lightctrl.c
diff options
context:
space:
mode:
authorDavid Lamparter <equinox@diac24.net>2012-09-20 11:03:21 +0200
committerDavid Lamparter <equinox@diac24.net>2012-09-20 11:03:21 +0200
commit415ca2037b3cefc64ee59279950fe85fa679e3cd (patch)
tree78c0836b73a6d3d642c5d9c6de20fa9a92818885 /lightctrl.c
parent8901251abbec6d08a13912bab774a0b32c05f16f (diff)
lightctrl: implement discovery protocol
Diffstat (limited to 'lightctrl.c')
-rw-r--r--lightctrl.c182
1 files changed, 147 insertions, 35 deletions
diff --git a/lightctrl.c b/lightctrl.c
index 0a46805..2a82ad3 100644
--- a/lightctrl.c
+++ b/lightctrl.c
@@ -31,38 +31,152 @@ const uint8_t __signature[3] __attribute__((section (".signature"), used)) =
#include "can.c"
#include "wdt.c"
-static void can_rx_exec(void)
+#define CANA_DALI_BASE 0x440
+
+static uint16_t ctr = 0;
+
+static void can_handle_light(uint16_t sublab_addr)
{
- if (can_rx_addr.b[0] == 0xcc
- && (can_rx_addr.b[1] & 0xfb) == 0x08
- && can_rx_addr.b[2] == 0x04) {
-
- uint8_t base = can_rx_addr.b[3], len = can_rx_dlc & 0x4f, pos;
-
- for (pos = 0; pos < len; pos++) {
- uint8_t dst = base + pos, val;
- if (dst < 0x40 || dst >= 0x80)
- continue;
- dst -= 0x40;
- val = can_rx_data[pos];
- if (val == 0xff)
- val = 0xfe;
-
- uart_puts("-- SET ");
- uart_puthex(dst);
- uart_puts(" = ");
- uart_puthex(val);
- uart_puts("\n");
-
- if (!val) {
- // dim_state = 0;
- dali_send((dst << 9) | 0x100);
- } else {
- // if (!dim_state && can_rx_data[0])
- dali_send((dst << 9) | 0x108);
- dali_send((dst << 9) | val);
- }
+ /* - 7 allows overlapping writes to a nonaligned address.
+ * "base" below will start out at 0xf9~0xff in that case */
+
+ if (sublab_addr < CANA_DALI_BASE - 7)
+ return;
+
+ uint8_t base = sublab_addr - CANA_DALI_BASE, len = can_rx_len(), pos;
+ for (pos = 0; pos < len; pos++) {
+ uint8_t dst = base + pos, val;
+ if (dst >= 0x40)
+ continue;
+ val = can_rx_data[pos];
+ if (val == 0xff)
+ val = 0xfe;
+
+ uart_puts("++ SET ");
+ uart_puthex(dst);
+ uart_puts(" = ");
+ uart_puthex(val);
+ uart_puts("\n");
+
+ if (!val) {
+ // dim_state = 0;
+ dali_send((dst << 9) | 0x100);
+ } else {
+ // if (!dim_state && can_rx_data[0])
+ dali_send((dst << 9) | 0x108);
+ dali_send((dst << 9) | val);
+ }
+ }
+
+ /* resync clock for immediate ACK */
+ ctr = 500;
+}
+
+const uint8_t dalidisc_page0[6] PROGMEM = {0x01, 0x01, 0x00, 0x01, 0x00, 0x00};
+const uint8_t dalidisc_page8[4] PROGMEM = {'D', 'A', 'L', 'I'};
+
+static uint8_t dali_grab_value(uint8_t busaddr, uint8_t cmd)
+{
+ dali_send(0x100 | (busaddr << 9) | cmd);
+ return dali_rx_avail ? dali_rx : 0xff;
+}
+
+static void can_handle_disco(uint16_t sublab_addr)
+{
+ wdt_reset();
+
+ if (sublab_addr < CANA_DALI_BASE)
+ return;
+
+ uint8_t addr = sublab_addr - CANA_DALI_BASE;
+ uint8_t page = can_rx_sublab_disco_page();
+ uint8_t buf[8];
+
+ if (!can_rx_ext_rr()) {
+ uart_puts("nRR\n");
+ switch (page) {
+ case 5:
+ if (can_rx_len() != 2)
+ return;
+ dali_send((can_rx_data[0] << 8) | can_rx_data[1]);
+ can_send(CANA_DISCOVERY_F(page, sublab_addr), !!dali_rx_avail, (uint8_t *)&dali_rx);
+ return;
}
+ return;
+ }
+
+#define loadpgm(what) for (uint8_t c = 0; c < sizeof(what); c++) buf[c] = pgm_read_byte(what + c);
+ switch (page) {
+ case 0:
+ loadpgm(dalidisc_page0);
+ can_send(CANA_DISCOVERY_F(page, sublab_addr), sizeof(dalidisc_page0), buf);
+ return;
+ case 6:
+ /* page 6:
+ * VERSION NUMBER
+ * DEVICE TYPE
+ * PHYSICAL MIN LEVEL
+ * RANDOM ADDRESS H
+ * RANDOM ADDRESS M
+ * RANDOM ADDRESS L
+ */
+ buf[0] = dali_grab_value(addr, 0x97);
+ buf[1] = dali_grab_value(addr, 0x99);
+ buf[2] = dali_grab_value(addr, 0x9a);
+ buf[3] = dali_grab_value(addr, 0xc2);
+ buf[4] = dali_grab_value(addr, 0xc3);
+ buf[5] = dali_grab_value(addr, 0xc4);
+ can_send(CANA_DISCOVERY_F(page, sublab_addr), 6, buf);
+ return;
+
+ case 7:
+ /* page 7:
+ * ACTUAL DIM LEVEL
+ * MAX LEVEL
+ * MIN LEVEL
+ * POWER ON LEVEL
+ * SYSTEM FAILURE LEVEL
+ * FADE RATE, FADE TIME (2x 4 bit)
+ * STATUS
+ * SHORT ADDRESS (or 0xff if no device)
+ */
+ for (uint8_t offs = 0; offs < 6; offs++)
+ buf[offs] = dali_grab_value(addr, 0xa0 + offs);
+
+ buf[6] = dali_grab_value(addr, 0x90);
+ dali_send(0x191 | (addr << 9));
+ buf[7] = dali_rx_avail ? addr : 0xff;
+
+ can_send(CANA_DISCOVERY_F(page, sublab_addr), 8, buf);
+ return;
+ case 8:
+ loadpgm(dalidisc_page8);
+ can_send(CANA_DISCOVERY_F(page, sublab_addr), sizeof(dalidisc_page8), buf);
+ return;
+ default:
+ can_send(CANA_DISCOVERY_F(page, sublab_addr), 0, NULL);
+ }
+}
+
+static void can_rx_exec(void)
+{
+ uint16_t sublab_addr, sublab_proto;
+
+ if (!can_rx_isext())
+ return;
+
+ sublab_addr = can_rx_sublab_addr();
+ if (sublab_addr >= CANA_DALI_BASE + 64)
+ return;
+
+ sublab_proto = can_rx_sublab_proto();
+ switch (sublab_proto) {
+ case 0xcc08:
+ can_handle_light(sublab_addr);
+ return;
+ case 0x4c08:
+ can_handle_disco(sublab_addr);
+ return;
}
}
@@ -107,8 +221,6 @@ int main(void)
dali_search();
- uint16_t ctr = 0;
-
while (1) {
wdt_reset();
if (canint) {
@@ -158,11 +270,11 @@ int main(void)
} else
uart_puts("-- ");
uart_puts("\n");
- can_send(0xe6080440 + base, dlc, buffer);
+ can_send(CANA_SENSOR_F(CANA_DALI_BASE + base), dlc, buffer);
}
break;
case 1024:
- can_send(0xe7000000, 8, (uint8_t *)&dalistat);
+ can_send(CANA_DEBUG, 8, (uint8_t *)&dalistat);
uart_puttick();
uart_puts("dali stats: ");
@@ -176,7 +288,7 @@ int main(void)
uart_puts(" mch-err\n");
break;
case 1536:
- can_send(0xcc08047f, 1, (uint8_t *)&dim_state);
+ can_send(CANA_LIGHT_F(0, CANA_DALI_BASE + 0x3f), 1, (uint8_t *)&dim_state);
break;
}
}