/* This program 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 program 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 this program. If not, see . * */ /* Copyright (c) 2016 King Kévin */ /* standard libraries */ #include // standard integer types #include // standard I/O facilities #include // standard utilities #include // standard streams #include // error number utilities /* STM32 (including CM3) libraries */ #include // real-time control clock library #include // general purpose input output library #include // vector table definition #include // Cortex M3 utilities #include // interrupt utilities #include // external interrupt utilities /* own libraries */ #include "global.h" // board definitions #include "usart.h" // USART utilities #include "usb_cdcacm.h" // USB CDC ACM utilities #include "led_ws2812b.h" // WS2812b LEDs utilities /* flag set in interrupts to be processed in main task */ volatile bool button_flag = false; // button has been pressed // the number of ticks in one second #define TICKS_PER_SECOND 255 /* I can't do the following in define because how defines are stored would cause an integer overflow in the arithmetics */ const uint32_t ticks_second = TICKS_PER_SECOND; // the number of ticks in one second const uint32_t ticks_minute = 60*TICKS_PER_SECOND; // the number of ticks in one minute const uint32_t ticks_hour = 60*60*TICKS_PER_SECOND; // the number of ticks in one hour const uint32_t ticks_midday = 12*60*60*TICKS_PER_SECOND; // the number of ticks in one midday (12 hours) uint8_t clock_leds[WS2812B_LEDS*3] = {0}; // RGB values for the WS2812b clock LEDs /* default output (i.e. for printf) */ int _write(int file, char *ptr, int len) { int i; if (file == STDOUT_FILENO || file == STDERR_FILENO) { for (i = 0; i < len; i++) { if (ptr[i] == '\n') { // add carrier return before line feed. this is recommended for most UART terminals usart_putchar_nonblocking('\r'); // a second line feed doesn't break the display cdcacm_putchar('\r'); // a second line feed doesn't break the display } usart_putchar_nonblocking(ptr[i]); // send byte over USART cdcacm_putchar(ptr[i]); // send byte over USB } return i; } errno = EIO; return -1; } /* switch on LED */ void led_on(void) { #ifdef SYSTEM_BOARD gpio_clear(LED_PORT, LED_PIN); #elif MAPLE_MINI gpio_set(LED_PORT, LED_PIN); #endif } /* switch off LED */ void led_off(void) { #ifdef SYSTEM_BOARD gpio_set(LED_PORT, LED_PIN); #elif MAPLE_MINI gpio_clear(LED_PORT, LED_PIN); #endif } /* toggle LED */ void led_toggle(void) { gpio_toggle(LED_PORT, LED_PIN); } /* switch off all clock LEDs */ static void clock_clear(void) { // set all colors of all LEDs to 0 for (uint16_t i=0; i=WS2812B_LEDS*255 || led_minute>=WS2812B_LEDS*255) { // a calculation error occurred return; } // show hours and minutes on LEDs if (led_hour>led_minute) { // show hours in blue (and clear other LEDs) for (uint16_t led=0; led=0xff) { // full hours clock_leds[led*3+2] = 0xff; } else { // running hours clock_leds[led*3+2] = led_hour; } led_hour -= clock_leds[led*3+2]; } // show minutes in green (override hours) for (uint16_t led=0; led0; led++) { clock_leds[led*3+0] = 0; if (led_minute>=0xff) { // full minutes clock_leds[led*3+1] = 0xff; } else { // running minutes clock_leds[led*3+1] = led_minute; } led_minute -= clock_leds[led*3+1]; clock_leds[led*3+2] = 0; } } else { // show minutes in green (and clear other LEDs) for (uint16_t led=0; led=0xff) { // full minutes clock_leds[led*3+1] = 0xff; } else { // running minutes clock_leds[led*3+1] = led_minute; } led_minute -= clock_leds[led*3+1]; clock_leds[led*3+2] = 0; } // show hours in blue (override minutes) for (uint16_t led=0; led0; led++) { clock_leds[led*3+0] = 0; clock_leds[led*3+1] = 0; if (led_hour>=0xff) { // full hours clock_leds[led*3+2] = 0xff; } else { // running hours clock_leds[led*3+2] = led_hour; } led_hour -= clock_leds[led*3+2]; } } uint16_t led_second = (WS2812B_LEDS*(time%ticks_minute))/ticks_minute; // get LED for seconds uint8_t brightness_second = (255*(time%ticks_second))/ticks_second; // get brightness for seconds // set second LED clock_leds[led_second*3+0] = brightness_second; clock_leds[led_second*3+1] = 0; clock_leds[led_second*3+2] = 0; // set previous LED clock_leds[((led_second-1)%WS2812B_LEDS)*3+0] = 0xff-brightness_second; clock_leds[((led_second-1)%WS2812B_LEDS)*3+1] = 0; clock_leds[((led_second-1)%WS2812B_LEDS)*3+2] = 0; } /* set the LEDs */ static void leds_set(void) { for (uint16_t i=0; i