diff options
Diffstat (limited to 'dali.c')
-rw-r--r-- | dali.c | 117 |
1 files changed, 117 insertions, 0 deletions
@@ -0,0 +1,117 @@ +static uint16_t dali_word; +static uint8_t dali_subctr, dali_state, dali_bit; +static uint8_t dali_prevpin; + +ISR(TIMER0_COMPA_vect) +{ + uint8_t inv = 1, data; + + TCNT0 = 0; + + if (PIND & D_DALII) { + PORTD |= (1 << D_LED2); + } else { + PORTD &= ~(1 << D_LED2); + } + + data = (PIND >> D_DALII) & 1; + if (dali_state == 0 && data) { + uart_puts("dali rxbegin\n"); + dali_state = 17; + dali_subctr = 4; + dali_word = 1; + } + + /* really simple CDR - resync clock on edge. + * this is ABSOLUTELY neccessary. */ + if (dali_state >= 16 && (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; + + switch (dali_state) { + /* idle */ + case 0: + return; + + /* write */ + /* 1 + 2: start bit */ + case 1: + uart_puts("dali["); + uart_puthex(dali_word >> 8); + uart_puthex(dali_word & 0xff); + uart_puts("]\n"); + + PORTD |= (1 << D_DALIO); + dali_state++; + return; + case 2: + PORTD &= ~(1 << D_DALIO); + dali_state = 4; + dali_bit = 0; + return; + case 4: + inv = 0; + case 5: + 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 = 6; + break; + case 6: + PORTD &= ~(1 << D_DALIO); + dali_state = 0; + uart_puts("dali sent\n"); + return; + + /* read */ + case 16: + dali_word <<= 1; + dali_word |= 1 - data; + dali_state = 17; + if (dali_word & 0x1000) { + dali_state = 0; + dali_word >>= 3; + + uart_puts("dali_rx "); + uart_puthex(dali_word & 0xff); + uart_puts("\n"); + } + break; + case 17: + dali_state = 16; + break; + } +} + +static void dali_init(void) +{ + PORTD |= (1 << D_DALII); + PORTD &= ~(1 << D_DALIO); + + dali_subctr = 0; + dali_state = 0; + 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 +} |