From feb4e55bbd02412b93f0612737e575cc131ead6f Mon Sep 17 00:00:00 2001 From: MightyPork Date: Tue, 23 Dec 2014 11:38:44 +0100 Subject: [PATCH] alive color wheel --- devel/colorchase/Makefile | 166 ++++++++++++++++++++++++++++++++++++++ devel/colorchase/lib | 1 + devel/colorchase/main.c | 116 ++++++++++++++++++++++++++ devel/lib/calc.h | 16 ++-- devel/lib/colors.h | 4 +- 5 files changed, 294 insertions(+), 9 deletions(-) create mode 100644 devel/colorchase/Makefile create mode 120000 devel/colorchase/lib create mode 100644 devel/colorchase/main.c diff --git a/devel/colorchase/Makefile b/devel/colorchase/Makefile new file mode 100644 index 0000000..82a8c47 --- /dev/null +++ b/devel/colorchase/Makefile @@ -0,0 +1,166 @@ + +MCU = atmega328p + +F_CPU = 16000000 + +LFUSE = 0xFF +HFUSE = 0xDE +EFUSE = 0x05 + +MAIN = main.c + +## If you've split your program into multiple files, +## include the additional .c source (in same directory) here +## (and include the .h files in your foo.c) +LOCAL_SOURCE = + +## Here you can link to one more directory (and multiple .c files) +# EXTRA_SOURCE_DIR = ../AVR-Programming-Library/ +EXTRA_SOURCE_DIR = +EXTRA_SOURCE_FILES = + + + +##########------------------------------------------------------########## +########## Programmer Defaults ########## +########## Set up once, then forget about it ########## +########## (Can override. See bottom of file.) ########## +##########------------------------------------------------------########## +#19200 +PROGRAMMER_TYPE = arduino +PROGRAMMER_ARGS = -b 57600 -P /dev/ttyUSB0 + + +##########------------------------------------------------------########## +########## Makefile Magic! ########## +########## Summary: ########## +########## We want a .hex file ########## +########## Compile source files into .elf ########## +########## Convert .elf file into .hex ########## +########## You shouldn't need to edit below. ########## +##########------------------------------------------------------########## + +## Defined programs / locations +CC = avr-gcc +OBJCOPY = avr-objcopy +OBJDUMP = avr-objdump +AVRSIZE = avr-size +AVRDUDE = sudo avrdude + +## Compilation options, type man avr-gcc if you're curious. +CFLAGS = -std=gnu99 -mmcu=$(MCU) -DF_CPU=$(F_CPU)UL -I. -I$(EXTRA_SOURCE_DIR) +CFLAGS += -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums +CFLAGS += -Wall -Wno-main -Wno-strict-prototypes -Wno-comment +CFLAGS += -g2 -Wextra -pedantic -Wfatal-errors +CFLAGS += -ffunction-sections -fdata-sections -Wl,--gc-sections -Wl,--relax + +CFLAGS_BUILD = $(CFLAGS) -Os + +# CFLAGS += -lm +## CFLAGS += -Wl,-u,vfprintf -lprintf_flt -lm ## for floating-point printf +## CFLAGS += -Wl,-u,vfprintf -lprintf_min ## for smaller printf + +## Lump target and extra source files together +TARGET = $(strip $(basename $(MAIN))) +SRC1 = $(TARGET).c +SRC = $(SRC1) +EXTRA_SOURCE = $(addprefix $(EXTRA_SOURCE_DIR), $(EXTRA_SOURCE_FILES)) +SRC += $(EXTRA_SOURCE) +SRC += $(LOCAL_SOURCE) + +## List of all header files +HEADERS = $(SRC:.c=.h) + +## For every .c file, compile an .o object file +OBJ = $(SRC:.c=.o) + +## Generic Makefile targets. (Only .hex file is necessary) +all: $(TARGET).hex size +pre: $(TARGET).pre + +%.hex: %.elf + $(OBJCOPY) -R .eeprom -O ihex $< $@ + +%.elf: $(SRC) + $(CC) $(CFLAGS_BUILD) $(SRC) --output $@ + +%.pre: $(SRC1) + $(CC) $(CFLAGS) -E $(SRC1) --output $@ + +%.eeprom: %.elf + $(OBJCOPY) -j .eeprom --change-section-lma .eeprom=0 -O ihex $< $@ + +debug: + @echo + @echo "Source files:" $(SRC) + @echo "MCU, F_CPU, BAUD:" $(MCU), $(F_CPU), $(BAUD) + @echo + +# Optionally create listing file from .elf +# This creates approximate assembly-language equivalent of your code. +# Useful for debugging time-sensitive bits, +# or making sure the compiler does what you want. +disassemble: $(TARGET).lst + +dis: disassemble +lst: disassemble + +eeprom: $(TARGET).eeprom + +%.lst: %.elf + $(OBJDUMP) -S $< > $@ + +# Optionally show how big the resulting program is +size: $(TARGET).elf + $(AVRSIZE) -C --mcu=$(MCU) $(TARGET).elf + +clean: + rm -f $(TARGET).elf $(TARGET).hex $(TARGET).obj \ + $(TARGET).o $(TARGET).d $(TARGET).eep $(TARGET).lst \ + $(TARGET).lss $(TARGET).sym $(TARGET).map $(TARGET)~ \ + $(TARGET).eeprom + +squeaky_clean: + rm -f *.elf *.hex *.obj *.o *.d *.eep *.lst *.lss *.sym *.map *~ + + +##########------------------------------------------------------########## +########## Programmer-specific details ########## +########## Flashing code to AVR using avrdude ########## +##########------------------------------------------------------########## + +flash: $(TARGET).hex + $(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) $(PROGRAMMER_ARGS) -U flash:w:$< + +flash_eeprom: $(TARGET).eeprom + $(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) $(PROGRAMMER_ARGS) -U eeprom:w:$< + +terminal: + $(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) $(PROGRAMMER_ARGS) -nt + + +flash_arduino: PROGRAMMER_TYPE = arduino +flash_arduino: PROGRAMMER_ARGS = +flash_arduino: flash + +flash_dragon_isp: PROGRAMMER_TYPE = dragon_isp +flash_dragon_isp: PROGRAMMER_ARGS = +flash_dragon_isp: flash + + +##########------------------------------------------------------########## +########## Fuse settings and suitable defaults ########## +##########------------------------------------------------------########## + +## Generic +FUSE_STRING = -U lfuse:w:$(LFUSE):m -U hfuse:w:$(HFUSE):m -U efuse:w:$(EFUSE):m + +fuses: + $(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) \ + $(PROGRAMMER_ARGS) $(FUSE_STRING) +show_fuses: + $(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) $(PROGRAMMER_ARGS) -nv + +## Called with no extra definitions, sets to defaults +set_default_fuses: FUSE_STRING = -U lfuse:w:$(LFUSE):m -U hfuse:w:$(HFUSE):m -U efuse:w:$(EFUSE):m +set_default_fuses: fuses diff --git a/devel/colorchase/lib b/devel/colorchase/lib new file mode 120000 index 0000000..dc598c5 --- /dev/null +++ b/devel/colorchase/lib @@ -0,0 +1 @@ +../lib \ No newline at end of file diff --git a/devel/colorchase/main.c b/devel/colorchase/main.c new file mode 100644 index 0000000..ac3a90c --- /dev/null +++ b/devel/colorchase/main.c @@ -0,0 +1,116 @@ +#include +#include +#include +#include +#include + +#include "lib/meta.h" +#include "lib/arduino_pins.h" +#include "lib/calc.h" +#include "lib/colors.h" +#include "lib/ws2812.h" + +#define WS1 D10 + +void render(); +void init_karts(); +void move_karts(); + + +void SECTION(".init8") init_io() +{ + // led strip data + as_output(WS1); + + // setup timer 10 ms + TCCR0A = _BV(WGM01); // CTC + TCCR0B = _BV(CS02) | _BV(CS00); // prescaler 512 + OCR0A = 100; // interrupt every 10 ms 156 + sbi(TIMSK0, OCIE0A); + sei(); +} + +/** timer 0 interrupt vector */ +ISR(TIMER0_COMPA_vect) +{ + move_karts(); + render(); +} + + +/** Unsigned int range struct */ +typedef struct { + uint8_t a; + uint8_t b; + int8_t dir; + uint8_t steptime; + uint8_t stepcnt; + xrgb_t color; +} kart_t; + +#define BLACK xrgb(0,0,0) + +#define karts_len 6 +#define screen_len 72 +kart_t karts[karts_len]; +xrgb_t screen[screen_len]; + + +void init_karts() +{ + karts[0] = (kart_t) { .a=0, .b=17, .dir=1, .steptime=2, .stepcnt=0, .color=xrgb(50, 0, 0) }; + karts[1] = (kart_t) { .a=10, .b=19, .dir=1, .steptime=3, .stepcnt=0, .color=xrgb(0, 50, 0) }; + karts[2] = (kart_t) { .a=20, .b=29, .dir=1, .steptime=7, .stepcnt=0, .color=xrgb(0, 0, 50) }; + karts[3] = (kart_t) { .a=40, .b=52, .dir=-1, .steptime=2, .stepcnt=0, .color=xrgb(50, 0, 50) }; + karts[4] = (kart_t) { .a=50, .b=69, .dir=-1, .steptime=11, .stepcnt=0, .color=xrgb(0, 20, 20) }; + karts[5] = (kart_t) { .a=25, .b=37, .dir=-1, .steptime=1, .stepcnt=0, .color=xrgb(60, 30, 0) }; + karts[5] = (kart_t) { .a=17, .b=25, .dir=1, .steptime=5, .stepcnt=0, .color=xrgb(25, 25, 0) }; +} + + +void move_karts() +{ + for (uint8_t j = 0; j < karts_len; j++) { + if (++karts[j].stepcnt >= karts[j].steptime) { + // move yo ass + + if (karts[j].dir > 0) { + inc_wrap(karts[j].a, 0, screen_len - 1); + inc_wrap(karts[j].b, 0, screen_len - 1); + } else { + dec_wrap(karts[j].a, 0, screen_len - 1); + dec_wrap(karts[j].b, 0, screen_len - 1); + } + + karts[j].stepcnt = 0; + } + } +} + + +void render() +{ + // build the screen + + // for each pixel + for (uint8_t i = 0; i < screen_len; i++) { + screen[i] = BLACK; + // for each kart + for (uint8_t j = 0; j < karts_len; j++) { + if (in_range_wrap(i, karts[j].a, karts[j].b)) { + screen[i] = add_xrgb(screen[i], karts[j].color); + } + } + } + + for (uint8_t i = 0; i < screen_len; i++) { + ws_send_xrgb(WS1, screen[i]); + } +} + + +void main() +{ + init_karts(); + while(1) {} // Timer interrupts do the rest +} diff --git a/devel/lib/calc.h b/devel/lib/calc.h index d2602bb..df04dac 100644 --- a/devel/lib/calc.h +++ b/devel/lib/calc.h @@ -5,16 +5,10 @@ */ // if max, go to zero. Else increment. -#define inc_wrap(var, max) do { if ((var) >= (max)) { (var)=0; } else { (var)++; } } while(0) +#define inc_wrap(var, min, max) do { if ((var) >= (max)) { (var)=min; } else { (var)++; } } while(0) // If zero, go to max. Else decrement, -#define dec_wrap(var, max) do { if ((var) > 0) { (var)--; } else { (var)=(max); } } while(0) - -// Check if value is in range A..B or B..A -#define in_range(x, low, high) (((low) < (high)) && ((x) > (low) && (x) < (high))) || (((low) > (high)) && ((x) < (low) || (x) > (high))) - -// Check if value is in range A..B. If B < A, matches all outside B..A -#define in_range_wrap(x, low, high) (((low) < (high)) && ((x) > (low) && (x) < (high))) || (((low) > (high)) && ((x) > (low) || (x) < (high))) +#define dec_wrap(var, min, max) do { if ((var) > min) { (var)--; } else { (var)=(max); } } while(0) // === general bit manipulation with register === #define sbi(reg, bit) do { (reg) |= (1 << (uint8_t)(bit)); } while(0) @@ -38,3 +32,9 @@ #define set_bit_p(reg, bit, value) write_bit_p(reg_p, bit, value) #define toggle_bit_p(reg_p, bit) do { *(reg_p) ^= (1 << (uint8_t)(bit)); } while(0) + +// Check if value is in range A..B or B..A +#define in_range(x, low, high) (((low) < (high)) && ((x) > (low) && (x) < (high))) || (((low) > (high)) && ((x) < (low) || (x) > (high))) + +// Check if value is in range A..B. If B < A, matches all outside B..A +#define in_range_wrap(x, low, high) (((low) < (high)) && ((x) > (low) && (x) < (high))) || (((low) > (high)) && ((x) > (low) || (x) < (high))) diff --git a/devel/lib/colors.h b/devel/lib/colors.h index 454923b..fe3a7ec 100644 --- a/devel/lib/colors.h +++ b/devel/lib/colors.h @@ -16,7 +16,7 @@ typedef uint16_t rgb12_t; typedef uint8_t rgb6_t; -#define xrgb(rr, gg, bb) { .r = ((uint8_t)(rr)), .g = ((uint8_t)(gg)), .b = ((uint8_t)(bb)) } +#define xrgb(rr, gg, bb) ((xrgb_t) { .r = ((uint8_t)(rr)), .g = ((uint8_t)(gg)), .b = ((uint8_t)(bb)) }) #define xrgb_r(c) ((uint8_t)(c.r)) #define xrgb_g(c) ((uint8_t)(c.g)) #define xrgb_b(c) ((uint8_t)(c.b)) @@ -55,3 +55,5 @@ typedef uint8_t rgb6_t; #define rgb6_b(c) ((((rgb6_t) (c)) & 0x3) << 6) #define rgb6_xrgb(c) xrgb(rgb6_r(c), rgb6_g(c), rgb6_b(c)) #define rgb6_rgb24(c) rgb24(rgb6_r(c), rgb6_g(c), rgb6_b(c)) + +#define add_xrgb(x, y) ((xrgb_t) { (((y).r > (255 - (x).r)) ? 255 : ((x).r + (y).r)), (((y).g > (255 - (x).g)) ? 255 : ((x).g + (y).g)), (((y).b > 255 - (x).b) ? 255 : ((x).b + (y).b)) })