terom@65: #include terom@65: terom@65: // DMX terom@98: #define DMX_DDR DDRD terom@98: #define DMX_PORT PORTD terom@98: #define DMX_DATA 2 terom@65: terom@65: // baud rate: 250k = 4µs / bit terom@65: #define DMX_BAUD (250 * 1000) terom@65: #define DMX_US 4 terom@65: terom@65: // CPU cycles / bit: 64 @ 16Mhz terom@65: #define DMX_CYCLES (F_CPU / DMX_BAUD) terom@65: terom@65: void dmx_init () terom@65: { terom@65: // dmx data out: idle (high) terom@65: sbi(&DMX_PORT, DMX_DATA); terom@65: sbi(&DMX_DDR, DMX_DATA); terom@65: } terom@65: terom@65: static inline void dmx_high () terom@65: { terom@65: sbi(&DMX_PORT, DMX_DATA); terom@65: } terom@65: terom@65: static inline void dmx_low () terom@65: { terom@65: cbi(&DMX_PORT, DMX_DATA); terom@65: } terom@65: terom@65: #define dmx_pause(bits) _delay_us((DMX_US * bits)) terom@65: terom@65: static void dmx_break () terom@65: { terom@65: // break terom@65: dmx_low(); terom@65: dmx_pause(22); terom@65: terom@65: // mark-after-break (MAB) terom@65: dmx_high(); terom@101: dmx_pause(3); // min 2, recommended 3 terom@65: } terom@65: terom@65: #include "dmx_frame.c" terom@65: terom@101: /* terom@101: * Send out a full DMX packet, including the start-code frame and a frame for each channel given. terom@101: * terom@101: * Uses 3-bit mark-times between frames, since some fixtures don't seem happy with 2-bit mark-times. terom@101: */ terom@66: static void dmx_packet (byte count, byte *out) terom@65: { terom@65: dmx_break(); terom@65: dmx_frame(0); terom@101: dmx_pause(1); // MTBF 2+1 = 3 terom@65: terom@66: for (byte i = 0; i < count; i++) { terom@66: dmx_frame(out[i]); terom@101: terom@101: // MTBF 2+1 = 3 terom@101: dmx_pause(1); terom@66: } terom@65: }