From 4c02e99566c4c277bb37e8b3040154b2a0a30f03 Mon Sep 17 00:00:00 2001 From: Savanni D'Gerinel Date: Thu, 14 Jul 2022 18:21:40 -0400 Subject: [PATCH] Start building timing and animation code --- dio/dio.h | 2 +- lantern/main.c | 68 +++++++++++++++++++++++++++++++++++++++++++++++++ sk9822/sk9822.c | 5 ++++ sk9822/sk9822.h | 2 ++ timer/timer.h | 56 ++++++++++++++++++++++++++++++++++++++++ 5 files changed, 132 insertions(+), 1 deletion(-) create mode 100644 timer/timer.h diff --git a/dio/dio.h b/dio/dio.h index 7baab60..9e7628d 100644 --- a/dio/dio.h +++ b/dio/dio.h @@ -51,7 +51,7 @@ inline void dio_set(dio_t *line, bool value) { } } -inline int dio_read(dio_t *line) { +inline uint8_t dio_read(dio_t *line) { return (*(line->pin) & _BV(line->addr)) > 0; } diff --git a/lantern/main.c b/lantern/main.c index ff25e46..0590460 100644 --- a/lantern/main.c +++ b/lantern/main.c @@ -12,7 +12,75 @@ You should have received a copy of the GNU General Public License along with thi #include #include +#include + +#define FPS 15 +#define ANIMATION_DELAY 1000 / 15 + +uint8_t bound (uint8_t value, uint8_t min, uint8_t max) { + if (value < min) { + return min; + } else if (value > max) { + return max; + } else { + return value; + } +} + +void flash_status(dio_t *light) { + dio_set(light, 1); + _delay_ms(100); + dio_set(light, 0); +} int main(void) { + dio_t status_light = { .ddr = &DDRC, .port = &PORTC, .pin = &PINC, .addr = 7 }; + dio_set_direction(&status_light, LINE_OUT); + + dio_t buttons[4] = { + { .ddr = &DDRB, .port = &PORTB, .pin = &PINB, .addr = 5 }, + { .ddr = &DDRB, .port = &PORTB, .pin = &PINB, .addr = 6 }, + { .ddr = &DDRB, .port = &PORTB, .pin = &PINB, .addr = 7 }, + { .ddr = &DDRD, .port = &PORTD, .pin = &PIND, .addr = 6 }, + }; + for (int i = 0; i < 4; i++) { + dio_set_direction(&buttons[i], LINE_IN); + } + + sk9822_t lights = { + .data_pin = { .ddr = &DDRD, .port = &PORTD, .pin = &PIND, .addr = 1 }, + .clock_pin = { .ddr = &DDRD, .port = &PORTD, .pin = &PIND, .addr = 0 } + }; + + rgb_t colors[3] = { + { .brightness = 1, .r = 128, .g = 0, .b = 0, }, + { .brightness = 1, .r = 0, .g = 128, .b = 0, }, + { .brightness = 1, .r = 0, .g = 0, .b = 128, }, + }; + + sk9822_init(&lights); + sk9822_send(&lights, colors, 3); + + int flash_recovery = 0; + + set_sleep_mode(SLEEP_MODE_PWR_DOWN); + + while (1) { + if (flash_recovery == 0) { + uint8_t value = dio_read(&buttons[0]); + if (value != 0) { + flash_status(&status_light); + flash_recovery = 128; + } + } else { + colors[0] = (rgb_t){ .brightness = bound(flash_recovery / 4, 1, 31), .r = 128 + flash_recovery, .g = flash_recovery * 2, .b = flash_recovery * 2 }, + colors[1] = (rgb_t){ .brightness = bound(flash_recovery / 4, 1, 31), .r = flash_recovery * 2, .g = 128 + flash_recovery, .b = flash_recovery * 2 }, + colors[2] = (rgb_t){ .brightness = bound(flash_recovery / 4, 1, 31), .r = flash_recovery * 2, .g = flash_recovery * 2, .b = 128 + flash_recovery }, + sk9822_send(&lights, colors, 3); + flash_recovery -= 2; + } + _delay_ms(ANIMATION_DELAY); + } + return 0; } diff --git a/sk9822/sk9822.c b/sk9822/sk9822.c index 544b381..f7d0c83 100644 --- a/sk9822/sk9822.c +++ b/sk9822/sk9822.c @@ -35,6 +35,11 @@ void send_term(dio_t data_pin, dio_t clock_pin) { send_byte(data_pin, clock_pin, 0xff); } +void sk9822_init(sk9822_t *lights) { + dio_set_direction(&lights->data_pin, LINE_OUT); + dio_set_direction(&lights->clock_pin, LINE_OUT); +} + void sk9822_send(sk9822_t *lights, rgb_t * pixels, uint8_t count) { send_start(lights->data_pin, lights->clock_pin); for (uint8_t i = 0; i < count; i++) { diff --git a/sk9822/sk9822.h b/sk9822/sk9822.h index bb4c3f6..d990264 100644 --- a/sk9822/sk9822.h +++ b/sk9822/sk9822.h @@ -28,6 +28,8 @@ typedef struct SK9822 { dio_t clock_pin; } sk9822_t; +void sk9822_init(sk9822_t *lights); + void sk9822_send(sk9822_t *lights, rgb_t *pixels, uint8_t count); #endif diff --git a/timer/timer.h b/timer/timer.h new file mode 100644 index 0000000..5969553 --- /dev/null +++ b/timer/timer.h @@ -0,0 +1,56 @@ +/* +Copyright 2022, Savanni D'Gerinel + +This file is part of Savanni's AVR library. + +This AVR library is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +This AVR library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with Lumeto. If not, see . +*/ + +#ifndef __TIMER_H__ +#define __TIMER_H__ + +#include + +// ATmega16U4/32U4 Datasheet, table 14.4, page 133 +typedef enum { + normal, + pwm_phasecorrect_8bit, + pwm_phasecorrect_9bit, + pwm_phasecorrect_10bit, + ctc, + fast_pwm_8bit, + fast_pwm_9bit, + fast_pwm_10bit, + pwm_phase_and_frequency_correct_icrtop, + pwm_phase_and_frequency_correct_ocrtop, + pwm_phase_correct_icrtop, + pwm_phase_correct_ocrtop, + ctc_icr, + fast_pwm_icrtop, + fast_pwm_ocrtop, +} timer_mode_t; + +// Clock prescaler selector, ATmega16U4/32U4 Datasheet, table 14.5, page 1354p +typedef enum { + none, + clk_1, + clk_8, + clk_64, + clk_256, + clk_1024, + external_falling_edge, + external_rising_edge, +} clock_select_t; + +typedef struct { + volatile uint8_t count_msb; + volatile uint8_t count_lsb; + volatile uint8_t top_msb; + volatile uint8_t top_lsb; +} timer_16bit_t; + +#endif