109 lines
2.9 KiB
C
109 lines
2.9 KiB
C
#include <avr/interrupt.h>
|
|
# include "ws2812.h"
|
|
|
|
// inline void write_zero(dio_t *pin, uint8_t hi, uint8_t low) {
|
|
// uint8_t *val;
|
|
// uint8_t *hi_reg;
|
|
// uint8_t *low_reg;
|
|
// __asm__ __volatile__ (
|
|
// "ldd %[hi_reg], %[hi]\n"
|
|
// "ldd %[low_reg], %[low]\n"
|
|
// "ldd %[val], %[pin]\n"
|
|
// "or %[val], %[hi_reg]\n"
|
|
// "std %[pin], %[val]\n"
|
|
// "nop\n"
|
|
// "nop\n"
|
|
// "and %[val], %[hi_reg]\n"
|
|
// "std %[pin], %[val]\n"
|
|
// "nop\n"
|
|
// "nop\n"
|
|
// "nop\n"
|
|
// /* Need another 5 cycles */
|
|
// : [val] "=r" (val), [hi_reg] "=r" (hi_reg), [low_reg] "=r" (low_reg)
|
|
// : [pin] "m" (pin->port), [hi] "m" (hi), [low] "m" (low)
|
|
// );
|
|
// }
|
|
|
|
|
|
// inline void write_one(dio_t *port, uint8_t hi, uint8_t low) {
|
|
// __asm__ __volatile__ (
|
|
// "or %0, %1\n"
|
|
// "nop\n"
|
|
// "nop\n"
|
|
// "nop\n"
|
|
// "nop\n"
|
|
// "nop\n"
|
|
// "nop\n"
|
|
// "and %0, %1\n"
|
|
// /* Need another 5 cycles */
|
|
// : /* no outputs */
|
|
// : "m" (port->port),
|
|
// "m" (hi),
|
|
// "m" (low)
|
|
// );
|
|
// }
|
|
|
|
inline void write_byte(dio_t *pin, uint8_t hi, uint8_t low, const uint8_t value) {
|
|
uint8_t *state_r;
|
|
uint8_t *hi_r;
|
|
uint8_t *low_r;
|
|
uint8_t *counter;
|
|
|
|
__asm__ __volatile__ (
|
|
"ldi r16, 8\n"
|
|
"ldi r17, %[value]\n"
|
|
"ldd %[hi_r], %[hi]\n"
|
|
"ldd %[low_r], %[low]\n"
|
|
"ldd %[state_r], %[pin]\n"
|
|
|
|
"L_%=: " "lsl __tmp_reg__\n"
|
|
"brbs I_%=\n"
|
|
"or %[state_r], %[hi_r]\n"
|
|
"nop\n"
|
|
"nop\n"
|
|
"and %[state_r], %[low_r]\n"
|
|
"nop\n"
|
|
"nop\n"
|
|
"nop\n"
|
|
"rjmp J_%=\n"
|
|
|
|
"I_%=: "
|
|
"brbs I_%=\n"
|
|
"or %[state_r], %[hi_r]\n"
|
|
"nop\n"
|
|
"nop\n"
|
|
"nop\n"
|
|
"nop\n"
|
|
"nop\n"
|
|
"and %[state_r], %[low_r]\n"
|
|
|
|
"J_%=: " "dec %[counter]\n"
|
|
"cpi %[counter], 0\n"
|
|
"brne L_%="
|
|
|
|
: [state_r] "=r" (state_r),
|
|
[hi_r] "=r" (hi_r),
|
|
[low_r] "=r" (low_r),
|
|
[counter] "=r" (counter)
|
|
|
|
: [pin] "m" (pin->port),
|
|
[hi] "m" (hi),
|
|
[low] "m" (low),
|
|
[value] "m" (value)
|
|
);
|
|
}
|
|
|
|
|
|
void np_write_rgb(dio_t *pin, const rgb_t *pixels, uint8_t length) {
|
|
cli();
|
|
uint8_t hi = 1 << pin->addr;
|
|
uint8_t low = ~hi;
|
|
for (int idx = 0; idx < length; idx++) {
|
|
write_byte(pin, hi, low, pixels[idx].r);
|
|
write_byte(pin, hi, low, pixels[idx].g);
|
|
write_byte(pin, hi, low, pixels[idx].b);
|
|
}
|
|
sei();
|
|
}
|
|
|