123 lines
2.7 KiB
C
123 lines
2.7 KiB
C
#include <avr/interrupt.h>
|
|
#include <avr/io.h>
|
|
#include <stdbool.h>
|
|
#include <stdint.h>
|
|
#include <stdio.h>
|
|
|
|
#define F_CPU 16000000UL
|
|
#define DMX_CHANNELS 512
|
|
|
|
volatile uint8_t dmx_data[DMX_CHANNELS + 1]; // 1..512
|
|
volatile uint16_t dmx_index = 0;
|
|
volatile bool dmx_frame_ready = false;
|
|
volatile bool receiving = false;
|
|
|
|
extern void output_dmx_channels_1_24(void);
|
|
|
|
/* --- USART3 (DMX) init & ISR --- */
|
|
void uart3_init(void) {
|
|
// uint16_t ubrr = (F_CPU / (16UL * 250000UL)) - 1; // 250000 baud
|
|
// UBRR3H = (uint8_t)(ubrr >> 8);
|
|
// UBRR3L = (uint8_t)ubrr;
|
|
UBRR3L = 3;
|
|
UCSR3B = (1 << RXEN3) | (1 << RXCIE3);
|
|
UCSR3C = (1 << USBS3) | (1 << UCSZ31) | (1 << UCSZ30); // 8N2
|
|
}
|
|
|
|
ISR(USART3_RX_vect) {
|
|
uint8_t status = UCSR3A;
|
|
uint8_t data = UDR3;
|
|
|
|
if (status & (1 << FE3)) {
|
|
// Break detected: start new DMX packet
|
|
receiving = true;
|
|
dmx_index = 0;
|
|
dmx_frame_ready = false;
|
|
return;
|
|
}
|
|
|
|
if (!receiving)
|
|
return;
|
|
|
|
if (dmx_index == 0) {
|
|
// start code (usually 0) - ignore/store as needed
|
|
dmx_index++; // next byte will be channel 1
|
|
return;
|
|
}
|
|
|
|
if (dmx_index <= DMX_CHANNELS) {
|
|
dmx_data[dmx_index] = data;
|
|
dmx_index++;
|
|
if (dmx_index > DMX_CHANNELS) {
|
|
dmx_frame_ready = true;
|
|
receiving = false;
|
|
}
|
|
} else {
|
|
dmx_frame_ready = true;
|
|
receiving = false;
|
|
}
|
|
}
|
|
|
|
/* --- USART0 (printf/debug) init & putchar --- */
|
|
void uart0_init(uint32_t baud) {
|
|
// uint16_t ubrr = (uint16_t)((F_CPU / (16UL * baud)) - 1UL);
|
|
// UBRR0H = (uint8_t)(ubrr >> 8);
|
|
// UBRR0L = (uint8_t)ubrr;
|
|
UBRR0L = 8;
|
|
UCSR0B = (1 << TXEN0); // enable transmitter
|
|
UCSR0C = (1 << UCSZ01) | (1 << UCSZ00); // 8 data, 1 stop, no parity
|
|
}
|
|
|
|
int uart0_putchar(char c, FILE *stream) {
|
|
if (c == '\n')
|
|
uart0_putchar('\r', stream); // CRLF
|
|
while (!(UCSR0A & (1 << UDRE0)))
|
|
; // wait until buffer empty
|
|
UDR0 = (uint8_t)c;
|
|
return 0;
|
|
}
|
|
|
|
/* Create a FILE stream for stdout */
|
|
static FILE uart0_stdout =
|
|
FDEV_SETUP_STREAM(uart0_putchar, NULL, _FDEV_SETUP_WRITE);
|
|
|
|
int main(void) {
|
|
cli();
|
|
|
|
DDRJ |= 1 << 5; // enable rs485 receiver
|
|
|
|
uart3_init();
|
|
uart0_init(115200); // debug baud
|
|
|
|
// Hook stdout to UART0
|
|
stdout = &uart0_stdout;
|
|
|
|
// init DMX buffer
|
|
for (uint16_t i = 1; i <= DMX_CHANNELS; ++i)
|
|
dmx_data[i] = 0;
|
|
|
|
sei();
|
|
|
|
// Example usage
|
|
printf("DMX receiver started\r\n");
|
|
|
|
while (1) {
|
|
if (dmx_frame_ready) {
|
|
// Example debug: print first 8 channels
|
|
printf("DMX frame received. Ch1..8: ");
|
|
for (uint8_t i = 1; i <= 8; ++i) {
|
|
printf("%u ", dmx_data[i]);
|
|
}
|
|
printf("\r\n");
|
|
|
|
dmx_frame_ready = false;
|
|
}
|
|
|
|
output_dmx_channels_1_24();
|
|
|
|
// other app code...
|
|
}
|
|
|
|
return 0;
|
|
}
|