Files
leuchtstoff/main.c
2026-05-22 23:49:19 +02:00

127 lines
3.1 KiB
C

#include <avr/interrupt.h>
#include <avr/io.h>
#include <stdbool.h>
#include <stdint.h>
#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;
void uart3_init(void) {
// Set baud rate for 250000 (F_CPU must be set accordingly).
// Formula UBRR = F_CPU/(16*baud)-1 ; For high speed use U2X - but DMX
// typically uses normal mode. For F_CPU = 16MHz: UBRR =
// 16,000,000/(16*250000)-1 = 3 We'll enable UBRR3 with 3 for 16MHz; adjust if
// F_CPU differs.
uint16_t ubrr = 3;
UBRR3H = (uint8_t)(ubrr >> 8);
UBRR3L = (uint8_t)ubrr;
// Enable receiver and RX complete interrupt
UCSR3B = (1 << RXEN3) | (1 << RXCIE3);
// Set frame format: 8 data, 2 stop bits (USBS3 = 1)
UCSR3C = (1 << USBS3) | (1 << UCSZ31) | (1 << UCSZ30);
// Note: parity default is none (UPM bits = 0)
}
ISR(USART3_RX_vect) {
PORTE |= 1 << 4;
uint8_t status = UCSR3A;
uint8_t data = UDR3; // reading UDR clears the receive flag
// If framing error -> likely BREAK (line held low longer than a byte time)
if (status & (1 << FE3)) {
// Break detected: start of new DMX packet
receiving = true;
dmx_index = 0;
dmx_frame_ready = false;
return; // discard this byte (it's break/MAF)
}
if (!receiving) {
// Not currently inside a DMX frame; ignore bytes until we detect break
return;
}
// DMX: first byte after break is START CODE (usually 0); then channel
// data 1..512
if (dmx_index == 0) {
// start code
// Optionally check for start code == 0, otherwise may discard or handle RDM
// etc. We'll accept any start code but only store channels.
dmx_index++; // move to channel 1 next
return;
}
// dmx_index corresponds to channel number
if (dmx_index <= DMX_CHANNELS) {
dmx_data[dmx_index] = data;
dmx_index++;
if (dmx_index > DMX_CHANNELS) {
// Received full frame
dmx_frame_ready = true;
receiving = false; // wait for next break
}
} else {
// Overflow (more bytes than expected) — treat as end and wait for next
// break
dmx_frame_ready = true;
receiving = false;
}
}
int main(void) {
// Example CPU freq assumption: 16 MHz. If different, adjust UBRR in
// uart3_init.
DDRE |= 1 << 4;
cli();
uart3_init();
// Optional: initialize array
for (uint16_t i = 1; i <= DMX_CHANNELS; ++i)
dmx_data[i] = 0;
sei();
// Main loop: react to finished frames
while (1) {
if (dmx_frame_ready) {
// Example: use channel 1..512 from dmx_data
// Process dmx_data here. This is a single buffer; if processing takes
// long, consider double-buffering to avoid race with ISR.
// After consuming, clear flag
dmx_frame_ready = false;
}
// if (dmx_data[1])
// PORTE |= 1 << 4;
// else
// PORTE &= ~(1 << 4);
// Other application code...
}
return 0;
}
// #include <avr/io.h>
// #include <util/delay.h>
//
// int main(void) {
// DDRE = 1 << 4;
//
// while (1) {
// PORTE ^= 1 << 4;
// _delay_ms(500);
// }
// }