diff options
-rw-r--r-- | can.c | 2 | ||||
-rw-r--r-- | dali2.c | 252 |
2 files changed, 253 insertions, 1 deletions
@@ -22,7 +22,7 @@ const uint8_t __signature[3] __attribute__((section (".signature"), used)) = #define D_LED1 5 #define D_LED2 6 -#include "dali.c" +#include "dali2.c" #define spi_ss(x) PORTB = ((x) << B_SS) | 0x3; @@ -0,0 +1,252 @@ +#define DALI_INVALID 0xa0cc + +enum dali_state { + DALI_IDLE = 0, + DALI_SPACE, // 1 + DALI_DEAD_SPACE, // 2 + + DALI_RX_SBIT, // 3 + DALI_RX_DATA, // 4 + + DALI_TX_SBIT0, // 5 + DALI_TX_SBIT1, // 6 + DALI_TX_0, // 7 + DALI_TX_1, // 8 + DALI_TX_STOP, // 9 +}; +static volatile uint8_t dali_state; + +static volatile uint8_t dali_rx; +static volatile bool dali_rx_avail; + +static volatile uint16_t dali_tx; +static volatile bool dali_tx_rq; + +#define XBUF 48 +static uint8_t dbuf[XBUF], sbuf[XBUF], dbufpos; + +#define dali_s_listening() (dali_state <= DALI_SPACE) +#define dali_s_cdr() (dali_state == DALI_RX_DATA) + +#define DEBUG 0 + +ISR(TIMER0_COMPA_vect) +{ + static uint8_t history = 0; +#define hist_size 5 +#define hist_mask ((1 << hist_size) - 1) +#define hist_majority_1() (((history | (history + 1)) & hist_mask) == hist_mask) +#define hist_majority_0() (((history & (history - 1)) & hist_mask) == 0) + + static uint8_t bitpos = 0; + static uint8_t rx_prevstate_errs, rx_data; + + static uint16_t tx_data; + + uint8_t bit = 0; + static uint8_t subsamp = 0; + + subsamp++; + subsamp &= 7; + + /* CTC mode didn't work, CBA to debug */ + TCNT0 = 0; + + history <<= 1; + history |= (PIND >> D_DALII) & 1; + + /* + * subsamp 1 2 3 4 5 6 7 0 || + * ^ state trigger + * /edge/ <----------- stable / sample ----------> + */ + if (dali_s_cdr()) { + if (subsamp >= 3 && subsamp <= 5 && ((history & 0x0f) == 0x03 || (history & 0x0f) == 0x0c)) { +// uart_puts("<CDR>"); + subsamp = 4; + } + } + if (dali_s_listening() && hist_majority_1()) { + rx_prevstate_errs = dali_state; + dali_state = DALI_RX_SBIT; + subsamp = 1; + } + + if (subsamp) + return; + + if (dali_state != DALI_IDLE && dbufpos < XBUF) { + sbuf[dbufpos] = dali_state; + dbuf[dbufpos++] = history; + } + + switch (dali_state) { + case DALI_SPACE: + case DALI_DEAD_SPACE: + if (bitpos > 0) { + bitpos--; + return; + } + dali_state = DALI_IDLE; + case DALI_IDLE: + break; + + case DALI_RX_SBIT: + if (!hist_majority_0()) { + uart_puts("<FSE>"); + dali_state = rx_prevstate_errs; + return; + } + dali_state = DALI_RX_DATA; + rx_prevstate_errs = 0; + rx_data = 0; + bitpos = 0; + break; + + case DALI_RX_DATA: + if (!(hist_majority_1() || hist_majority_0())) { + rx_prevstate_errs++; + uart_puts("<MJE>"); + bit = 0; + } else + bit = hist_majority_1(); + + if (bitpos & 1) { + if (bit == (rx_data & 1)) { + rx_prevstate_errs++; + uart_puts("<MAF>"); + } + } else { + rx_data <<= 1; + rx_data |= bit; + } + bitpos++; + if (bitpos == 16) { + bitpos = 20; + dali_state = DALI_DEAD_SPACE; + if (!rx_prevstate_errs) { + dali_rx = rx_data; + dali_rx_avail = 1; + } + } + break; + + case DALI_TX_SBIT0: + bit = 1; + dali_state = DALI_TX_SBIT1; + break; + case DALI_TX_SBIT1: + bit = 0; + dali_state = DALI_TX_0; + break; + case DALI_TX_0: + if (bitpos == 16) { + bitpos = 8; + dali_state = DALI_TX_STOP; + PORTD |= (1 << D_DALIO); + } else { + bit = (tx_data & (1 << (15 - bitpos))) ? 1 : 0; + dali_state = DALI_TX_1; + } + break; + case DALI_TX_1: + bit = (tx_data & (1 << (15 - bitpos))) ? 0 : 1; + bitpos++; + dali_state = DALI_TX_0; + break; + + case DALI_TX_STOP: + if (bitpos == 0) { + dali_tx_rq = 0; + bitpos = 25; + dali_state = DALI_SPACE; + } else + bitpos--; + break; + } + + if ((dali_state == DALI_TX_SBIT1) || (dali_state == DALI_TX_0) || (dali_state == DALI_TX_1)) { + if (bit) { + PORTD &= ~(1 << D_DALIO); + } else { + PORTD |= (1 << D_DALIO); + } + } +#if DEBUG + if (dali_state != DALI_IDLE || bitpos != 0) + uart_puts("\n"); +#endif + + if (dali_state == DALI_IDLE && dali_tx_rq) { + tx_data = dali_tx; + bitpos = 0; + dali_tx = DALI_INVALID; + dali_tx_rq = 2; + dali_state = DALI_TX_SBIT0; + subsamp = 7; + } +} + +static void dali_send(uint16_t word) +{ + uart_wait(); + uart_puts("\n\n\ndali_send "); + uart_puthex(word >> 8); + uart_puthex(word & 0xff); + uart_puts("\n"); + uart_wait(); + dbufpos = 0; + + dali_rx_avail = 0; + dali_tx = word; + asm volatile ("" ::: "memory"); + dali_tx_rq = 1; + while (dali_tx_rq || dali_state != DALI_IDLE) { + asm volatile ("" ::: "memory"); + } + + uart_wait(); + uart_puts("dali_sent "); + uart_puthex(word >> 8); + uart_puthex(word & 0xff); + uart_puts(" "); + if (dali_rx_avail) + uart_puthex(dali_rx); + else + uart_puts("norx"); + uart_puts("\n"); + uart_wait(); + for (uint8_t x = 0; x < dbufpos; x++) + uart_puthex(sbuf[x]); + uart_puts("\n"); + uart_wait(); + for (uint8_t x = 0; x < dbufpos; x++) + uart_puthex(dbuf[x]); + uart_puts("\n"); + uart_wait(); + +} + +static void dali_twice(uint16_t word) +{ + dali_send(word); + dali_send(word); +} + +static void dali_init(void) +{ + PORTD |= (1 << D_DALII) | (1 << D_DALIO); + + dali_state = DALI_IDLE; + dali_tx_rq = 0; + dali_rx_avail = 0; + + TIFR0 = (1 << OCF0A); + TCNT0 = 0; + OCR0A = 52; // 8 MHz / 8 / 52 = 19230. + asm volatile ("" ::: "memory"); + TIMSK0 = (1 << OCIE0A); + TCCR0A = 0; + asm volatile ("" ::: "memory"); + TCCR0B = (0 << CS02) | (1 << CS01) | (0 << CS00); // 8 MHz / 8 = 1MHz +} |