//modified from https://github.com/pololu/pololu-led-strip-avr
#define F_CPU 16000000
#define LED_STRIP_PORT PORTD
#define LED_STRIP_DDR DDRD
#define LED_STRIP_PIN 6
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <stdint.h>
typedef struct ACRGB{
uint8_t red, green, blue;
} ACRGB;
void __attribute__((noinline)) writeLeds(ACRGB * colors, uint16_t count){
LED_STRIP_PORT &= ~(1<<LED_STRIP_PIN);
LED_STRIP_DDR |= (1<<LED_STRIP_PIN);
cli();
while (count--)
{
asm volatile (
"ld __tmp_reg__, %a0+\n"
"ld __tmp_reg__, %a0\n"
"rcall send_led_strip_byte%=\n"
"ld __tmp_reg__, -%a0\n"
"rcall send_led_strip_byte%=\n"
"ld __tmp_reg__, %a0+\n"
"ld __tmp_reg__, %a0+\n"
"ld __tmp_reg__, %a0+\n"
"rcall send_led_strip_byte%=\n"
"rjmp led_strip_asm_end%=\n"
"send_led_strip_byte%=:\n"
"rcall send_led_strip_bit%=\n"
"rcall send_led_strip_bit%=\n"
"rcall send_led_strip_bit%=\n"
"rcall send_led_strip_bit%=\n"
"rcall send_led_strip_bit%=\n"
"rcall send_led_strip_bit%=\n"
"rcall send_led_strip_bit%=\n"
"rcall send_led_strip_bit%=\n"
"ret\n"
"send_led_strip_bit%=:\n"
#if F_CPU == 8000000
"rol __tmp_reg__\n"
#endif
"sbi %2, %3\n"
#if F_CPU != 8000000
"rol __tmp_reg__\n"
#endif
#if F_CPU == 16000000
"nop\n" "nop\n"
#elif F_CPU == 20000000
"nop\n" "nop\n" "nop\n" "nop\n"
#elif F_CPU != 8000000
#error "Unsupported F_CPU"
#endif
"brcs .+2\n" "cbi %2, %3\n"
#if F_CPU == 8000000
"nop\n" "nop\n"
#elif F_CPU == 16000000
"nop\n" "nop\n" "nop\n" "nop\n" "nop\n"
#elif F_CPU == 20000000
"nop\n" "nop\n" "nop\n" "nop\n" "nop\n"
"nop\n" "nop\n"
#endif
"brcc .+2\n" "cbi %2, %3\n"
"ret\n"
"led_strip_asm_end%=: "
: "=b" (colors)
: "0" (colors),
"I" (_SFR_IO_ADDR(LED_STRIP_PORT)),
"I" (LED_STRIP_PIN)
);
}
sei();
_delay_us(80);
}
uint8_t R,G,B;
double fmap(double x, double in_min, double in_max, double out_min, double out_max) {
return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}
void HSVtoRGB(float H, float S,float V){
H = fmap(H, 0, 255, 0, 360);
S = fmap(S, 0, 255, 0, 100);
V = fmap(V, 0, 255, 0, 100);
if(H>360 || H<0 || S>100 || S<0 || V>100 || V<0){
return;
}
float s = S/100;
float v = V/100;
float C = s*v;
float X = C*(1-abs(fmod(H/60.0, 2)-1));
float m = v-C;
float r,g,b;
if(H >= 0 && H < 60){
r = C,g = X,b = 0;
}
else if(H >= 60 && H < 120){
r = X,g = C,b = 0;
}
else if(H >= 120 && H < 180){
r = 0,g = C,b = X;
}
else if(H >= 180 && H < 240){
r = 0,g = X,b = C;
}
else if(H >= 240 && H < 300){
r = X,g = 0,b = C;
}
else{
r = C,g = 0,b = X;
}
R = (r+m)*255;
G = (g+m)*255;
B = (b+m)*255;
}
#define NUM_LEDS 60
ACRGB leds[NUM_LEDS];
uint8_t hue = 0;
int main(){
while (1){
for (uint16_t i = 0; i < NUM_LEDS; i++){
HSVtoRGB(hue, 255, 255);
leds[i] = {R,G,B};
}
writeLeds(leds, NUM_LEDS);
hue++;
_delay_ms(5);
}
}