diff options
-rw-r--r-- | src/main.c | 92 | ||||
-rw-r--r-- | src/main.h | 7 | ||||
-rw-r--r-- | src/tm1637.c | 40 |
3 files changed, 105 insertions, 34 deletions
@@ -3,6 +3,9 @@ #include "main.h" #include "tm1637.h" +#define SECOND (1e3) +#define LONG_PRESS_DURATION (300) + const unsigned short leds[] = {PINOUT_LED_1, PINOUT_LED_2, PINOUT_LED_3, PINOUT_LED_4}; volatile bool led_direction = false; @@ -84,10 +87,8 @@ void interrupt_setup() { * 0 or 1 which indicates if the LED should be turned on (1) or off (0). */ void led_write(int num, int on) { - int pin = leds[num]; - GPIOB->ODR ^= (((GPIOB->ODR & (1 << pin)) >> pin) ^ on) << pin; - // GPIOB->ODR &= ~(1 << leds[num]); - // GPIOB->ODR |= (on << leds[num]); + GPIOB->ODR &= ~(1 << leds[num]); + GPIOB->ODR |= (on << leds[num]); } /* @@ -118,10 +119,6 @@ void next_led() { led_write(led, 1); } -void dumb_delay() { - for(unsigned long i = 0; i < 50e3; i++); -} - /** * This function uses timer 3 to generate a blocking delay of <milliseconds>. * It uses the channel 1 capture/compare register to check if the time (in @@ -135,6 +132,7 @@ void timer_delay(unsigned short millis) { } void timer_display(unsigned int minutes, unsigned int seconds, bool colon) { + tm1637_dispcfg(pot_read() / 512, 1); // 512 = 2**12 / 8; [0,4096]->[0,8] tm1637_segmentsend(0, tm1637_font[minutes / 10]); tm1637_segmentsend(1, tm1637_font[minutes % 10] | (colon * TM1637_COLON)); tm1637_segmentsend(2, tm1637_font[seconds / 10]); @@ -148,20 +146,78 @@ int main() { unsigned int minutes = 0; unsigned int seconds = 0; + bool pause = false; + button_state state = up_idle; + bool reverse = false; + unsigned short led = 0; + + // timers + unsigned long millis_stopwatch = 0; + unsigned long millis_looplicht = 0; + unsigned long millis_button_dn = 0; + + bool long_press = false; tm1637_dispcfg(7, 1); while (1) { - timer_delay(500); - timer_display(minutes, seconds, false); - timer_delay(500); - timer_display(minutes, seconds, true); - - seconds++; - if (seconds >= 60) { - seconds = 0; - minutes++; - if (minutes >= 100) minutes = 0; + uint8_t button_now = button_read(); + switch(state) { + case up_idle: { + state = button_now ? down_edge : up_idle; + millis_button_dn = 0; + break; + } + case down_edge: { + state = button_now ? down_idle : up_idle; + millis_button_dn = 1; + break; + } + case down_idle: { + state = button_now ? down_idle : up_edge; + millis_button_dn++; + break; + } + case up_edge: { + state = button_now ? down_idle : up_idle; + long_press = millis_button_dn >= LONG_PRESS_DURATION; + + if (!long_press) pause = !pause; + else { + pause = true; + minutes = 0; + seconds = 0; + millis_stopwatch = 0; + } + break; + } + } + if (millis_stopwatch % 50 == 0) timer_display(minutes, seconds, millis_stopwatch > (SECOND / 2)); + + if (millis_stopwatch == SECOND) { + seconds++; + if (seconds >= 60) { + seconds = 0; + minutes++; + if (minutes >= 100) minutes = 0; + } + millis_stopwatch = 0; } + + unsigned int delay_amount = 50 + pot_read(); + if (millis_looplicht >= delay_amount) { + for(int j = 0; j < 4; j++) led_write(j, 0); + + // calculate next led index + led = (led + ((2 * reverse) - 1)) & 0b11; + + led_write(led, 1); + + millis_looplicht = 0; + } + + timer_delay(1); + millis_looplicht++; + if (!pause) millis_stopwatch++; } } @@ -24,3 +24,10 @@ void dumb_delay(); void timer_delay(unsigned short millis); int main(); +typedef enum { + up_idle = 0, + down_edge = 1, + down_idle = 2, + up_edge = 3, +} button_state; + diff --git a/src/tm1637.c b/src/tm1637.c index 9cc79d6..d4a4e44 100644 --- a/src/tm1637.c +++ b/src/tm1637.c @@ -33,17 +33,6 @@ void _tm1637_pin_write(uint32_t pin, bool state) { GPIOA->ODR ^= (((GPIOA->ODR & (1 << pin)) >> pin) ^ state) << pin; } -void tm1637_begin() { - _tm1637_GPIOMODE_gp_output(); - - // general purpose output mode for clk - GPIOA->MODER &= ~(0b11 << (PINOUT_DISP_CLK * 2)); - GPIOA->MODER |= (0b01 << (PINOUT_DISP_CLK * 2)); - - _tm1637_pin_write(PINOUT_DISP_CLK, 1); - _tm1637_pin_write(PINOUT_DISP_DIO, 1); -} - void _tm1637_start() { _tm1637_pin_write(PINOUT_DISP_DIO, 0); } @@ -54,13 +43,15 @@ void _tm1637_stop() { } bool _tm1637_ack() { + bool ack = false; _tm1637_pin_write(PINOUT_DISP_CLK, 0); _tm1637_pin_write(PINOUT_DISP_DIO, 0); _tm1637_GPIOMODE_open_drain(); + ack = (GPIOA->IDR & (1 << PINOUT_DISP_DIO)) == 0; _tm1637_pin_write(PINOUT_DISP_CLK, 1); _tm1637_pin_write(PINOUT_DISP_CLK, 0); _tm1637_GPIOMODE_gp_output(); - return true; + return ack; } /** @@ -70,7 +61,6 @@ bool _tm1637_ack() { */ TM1637Sequence _tm1637_send(TM1637Sequence command) { TM1637Sequence response = { .data = 0, .length = 0 }; - _tm1637_start(); for (uint32_t byte = 0; byte < command.length; byte++) { @@ -79,11 +69,10 @@ TM1637Sequence _tm1637_send(TM1637Sequence command) { _tm1637_pin_write(PINOUT_DISP_DIO, (command.data[byte] & (1 << bit)) >> bit); _tm1637_pin_write(PINOUT_DISP_CLK, 1); } - //TODO: confirm ack - /*bool ack =*/ _tm1637_ack(); + bool ack = _tm1637_ack(); + if (!ack) byte -= 1; } - // stop condition _tm1637_stop(); return response; @@ -111,3 +100,22 @@ void tm1637_segmentsend(uint8_t segment, uint8_t data) { }; _tm1637_send(seq); } + +void _tm1637_clear() { + for (unsigned int x = 0; x < 4; x++) + tm1637_segmentsend(x, 0); +} + +void tm1637_begin() { + _tm1637_GPIOMODE_gp_output(); + + // general purpose output mode for clk + GPIOA->MODER &= ~(0b11 << (PINOUT_DISP_CLK * 2)); + GPIOA->MODER |= (0b01 << (PINOUT_DISP_CLK * 2)); + + _tm1637_pin_write(PINOUT_DISP_CLK, 1); + _tm1637_pin_write(PINOUT_DISP_DIO, 1); + + _tm1637_clear(); +} + |