/*
* Per-frame timing-critical bit-banging.
*
* Shamelessly stolen from
* http://code.google.com/p/tinkerit/source/browse/trunk/DmxSimple/DmxSimple.cpp
*
* Copyright (c) 2008-2009 Peter Knight, Tinker.it!
*
* Consumes approx. 11 * 64 ~= 705 clock cycles
* Leaves the line idle (high) on return.
*/
void dmx_frame (volatile byte value)
{
uint8_t bitCount, delCount;
__asm__ volatile (
"cli\n"
"ld __tmp_reg__,%a[dmxPort]\n"
"and __tmp_reg__,%[outMask]\n"
"st %a[dmxPort],__tmp_reg__\n"
"ldi %[bitCount],11\n" // 11 bit intervals per transmitted byte
"rjmp bitLoop%=\n" // Delay 2 clock cycles.
"bitLoop%=:\n"\
"ldi %[delCount],%[delCountVal]\n"
"delLoop%=:\n"
"nop\n"
"dec %[delCount]\n"
"brne delLoop%=\n"
"ld __tmp_reg__,%a[dmxPort]\n"
"and __tmp_reg__,%[outMask]\n"
"sec\n"
"ror %[value]\n"
"brcc sendzero%=\n"
"or __tmp_reg__,%[outBit]\n"
"sendzero%=:\n"
"st %a[dmxPort],__tmp_reg__\n"
"dec %[bitCount]\n"
"brne bitLoop%=\n"
"sei\n"
:
[bitCount] "=&d" (bitCount),
[delCount] "=&d" (delCount)
:
[dmxPort] "e" (&DMX_PORT),
[outMask] "r" (~(1 << DMX_DATA)),
[outBit] "r" ((1 << DMX_DATA)),
[delCountVal] "M" (F_CPU/1000000-3),
[value] "r" (value)
);
}