src/hello-dmx.c
author Tero Marttila <terom@paivola.fi>
Sun, 06 Apr 2014 18:25:55 +0300
changeset 62 2d68a76322cb
child 65 625f34328820
permissions -rw-r--r--
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();
    }
}