diff options
-rw-r--r-- | dali.c | 160 |
1 files changed, 0 insertions, 160 deletions
@@ -1,160 +0,0 @@ -/* invalid command, used as default/do-nothing value - * 101CCCCX == special commands, X must be 1. - * X is 0 below => invalid - */ -#define DALI_INVALID 0xa000 - -static uint16_t dali_word, dali_sendq; -static uint8_t dali_subctr, dali_state, dali_bit; -static uint8_t dali_prevpin; - -enum dali_state { - DALI_IDLE = 0, - DALI_TX_SPACE, - - DALI_TX_STARTBIT1, - DALI_TX_STARTBIT2, - - DALI_TX_LEFT = 4, - DALI_TX_RIGHT, - DALI_TX_STOP, - - DALI_RX_LEFT = 8, - DALI_RX_RIGHT, -}; - -ISR(TIMER0_COMPA_vect) -{ - uint8_t inv = 1, data; - - TCNT0 = 0; /* CTC mode didn't work, CBA to debug */ - - data = (PIND >> D_DALII) & 1; - if (dali_state <= DALI_TX_SPACE && data) { - dali_state = DALI_RX_LEFT; - dali_subctr = 4; - dali_word = 1; - } - - /* really simple CDR - resync clock on edge. - * this is ABSOLUTELY neccessary. */ - if (dali_state >= DALI_RX_LEFT && (dali_prevpin ^ data)) { - if (dali_subctr >= 2 && dali_subctr <= 5) - dali_subctr = 4; - } - dali_prevpin = data; - - dali_subctr++; - dali_subctr &= 7; - if (dali_subctr) - return; - - /* this code runs @ 2400 Hz */ - - /********** actual state processing *********/ - - switch (dali_state) { - /* idle */ - case DALI_IDLE: - if (dali_sendq != DALI_INVALID) { - dali_word = dali_sendq; - dali_sendq = DALI_INVALID; - dali_state = DALI_TX_STARTBIT1; - } - return; - - case DALI_TX_SPACE: - /* 12 ms inter-command spacing */ - if (dali_bit > 28) - dali_state = DALI_IDLE; - dali_bit++; - return; - - /* write */ - /* 1 + 2: start bit */ - case DALI_TX_STARTBIT1: - uart_puts("dali["); - uart_puthex(dali_word >> 8); - uart_puthex(dali_word & 0xff); - uart_puts("]\n"); - - PORTD |= (1 << D_DALIO); - dali_state = DALI_TX_STARTBIT2; - return; - case DALI_TX_STARTBIT2: - PORTD &= ~(1 << D_DALIO); - dali_state = DALI_TX_LEFT; - dali_bit = 0; - return; - case DALI_TX_LEFT: - inv = 0; - case DALI_TX_RIGHT: - dali_state ^= 1; - - data = (dali_word >> (15 - dali_bit)) & 1; - data ^= inv; - if (data) - PORTD |= (1 << D_DALIO); - else - PORTD &= ~(1 << D_DALIO); - - if (inv) - dali_bit++; - if (dali_bit == 16) - dali_state = DALI_TX_STOP; - break; - case DALI_TX_STOP: - PORTD &= ~(1 << D_DALIO); - dali_state = DALI_IDLE; - uart_puts("dali sent\n"); - return; - - /* read */ - case DALI_RX_RIGHT: - dali_word <<= 1; - dali_word |= 1 - data; - dali_state = DALI_RX_LEFT; - if (dali_word & 0x1000) { - dali_state = DALI_IDLE; - dali_word >>= 3; - - uart_puts("dali_rx "); - uart_puthex(dali_word & 0xff); - uart_puts("\n"); - } - break; - case DALI_RX_LEFT: - dali_state = DALI_RX_RIGHT; - break; - } -} - -static void dali_send(uint16_t word) -{ - cli(); - dali_sendq = word; - sei(); -} - -static bool dali_queue_busy(void) -{ - asm volatile ("" : : : "memory"); - return dali_sendq != DALI_INVALID; -} - -static void dali_init(void) -{ - PORTD |= (1 << D_DALII); - PORTD &= ~(1 << D_DALIO); - - dali_subctr = 0; - dali_state = DALI_IDLE; - dali_prevpin = 0; - - TCNT0 = 0; - OCR0A = 52; // 8 MHz / 8 / 52 = 19230. - TIMSK0 = (1 << OCIE0A); - TIFR0 = (1 << OCF0A); - TCCR0A = 0; - TCCR0B = (0 << CS02) | (1 << CS01) | (0 << CS00); // 8 MHz / 8 = 1MHz -} |