hello-dmx: working basic dmx output using DmxSimple's frame-timing inline assembler code
/*
* DMX output.
*
* See doc/dmx.txt for the RX-485 bus protocol details...
*/
#include <avr/io.h>
#include <util/delay.h>
#include "stdlib.h"
// debug
#define DEBUG_DDR DDRB
#define DEBUG_PORT PORTB
#define DEBUG_LED 0
void led_init ()
{
sbi(&DEBUG_DDR, DEBUG_LED);
}
void led_on ()
{
sbi(&DEBUG_PORT, DEBUG_LED);
}
void led_off ()
{
cbi(&DEBUG_PORT, DEBUG_LED);
}
void led_toggle ()
{
xbi(&DEBUG_PORT, DEBUG_LED);
}
// DMX
#define DMX_DDR DDRB
#define DMX_PORT PORTB
#define DMX_DATA 3 // SPI MOSI
// baud rate: 250k = 4µs / bit
#define DMX_BAUD (250 * 1000)
#define DMX_US 4
// CPU cycles / bit: 64 @ 16Mhz
#define DMX_CYCLES (F_CPU / DMX_BAUD)
void dmx_init ()
{
// dmx data out: idle (high)
sbi(&DMX_PORT, DMX_DATA);
sbi(&DMX_DDR, DMX_DATA);
}
static inline void dmx_high ()
{
sbi(&DMX_PORT, DMX_DATA);
}
static inline void dmx_low ()
{
cbi(&DMX_PORT, DMX_DATA);
}
#define dmx_pause(bits) _delay_us((DMX_US * bits))
static void dmx_break ()
{
// break
dmx_low();
dmx_pause(22);
// mark-after-break (MAB)
dmx_high();
dmx_pause(2);
}
#include "dmx_frame.c"
static void dmx_packet (byte r, byte g, byte b)
{
dmx_break();
dmx_frame(0);
dmx_frame(0); // control
dmx_frame(r);
dmx_frame(g);
dmx_frame(b);
dmx_frame(0); // madness
}
void main ()
{
led_init();
dmx_init();
// dmx
while (true) {
dmx_packet(0x00, 0x00, 0xff);
dmx_pause(100);
led_toggle();
}
}