/* led.c */ /* binwatch - Tiny binary wristwatch. {{{ * * Copyright (C) 2010 Nicolas Schodet * * 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 2 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, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * Contact : * Web: http://ni.fr.eu.org/ * Email: * }}} */ #include "common.h" #include "modules/utils/utils.h" #include "io.h" #include "led.h" #include "button.h" #include "power.h" /** Time a led is lit. */ #define LED_UP_MS 0.05 #define LED_DOWN_MS (0.5 - LED_UP_MS) /** Mask of used bits. */ #define LED_MASK 0b111010 struct led_t { uint8_t ddr; uint8_t port; }; struct led_t led_tab[] = { /* 432 1 432 1 */ { 0b001010, 0b000010 }, /* M0 */ { 0b001010, 0b001000 }, /* M1 */ { 0b010010, 0b000010 }, /* M2 */ { 0b010010, 0b010000 }, /* M3 */ { 0b100010, 0b000010 }, /* M4 */ { 0b100010, 0b100000 }, /* M5 */ { 0b011000, 0b001000 }, /* H0 */ { 0b011000, 0b010000 }, /* H1 */ { 0b101000, 0b001000 }, /* H2 */ { 0b101000, 0b100000 }, /* H3 */ }; uint16_t led_circle[] = { 0b0001000000, 0b0010000000, 0b0100000000, 0b1000000000, 0b0000100000, 0b0000010000, 0b0000001000, 0b0000000100, 0b0000000010, 0b0000000001, }; void led_init (void) { /* Activate pull-up. */ PORTB |= LED_MASK; } void led_display (uint16_t leds, uint16_t duration) { uint8_t portb, ddrb; uint8_t l; uint16_t i, mask; portb = PORTB & ~LED_MASK; ddrb = DDRB & ~LED_MASK; for (i = 0; i < duration; i++) { for (l = 0, mask = 1; l < UTILS_COUNT (led_tab); l++, mask <<= 1) { /* Turn on if selected. */ if (leds & mask) { PORTB = portb | led_tab[l].port; DDRB = ddrb | led_tab[l].ddr; } power_delay_ms (LED_UP_MS); /* Turn off, leds are too bright. */ DDRB = ddrb; PORTB = portb | LED_MASK; power_delay_ms (LED_DOWN_MS); /* Stop now if button is pressed, it disturbs leds. */ if (button_pressed ()) return; } } } void led_no_pull_up (void) { PORTB = (PORTB & ~LED_MASK) | IO_BV (BUTTON_IO); } static void led_animate_trace_ccw (uint16_t leds, uint16_t speed) { uint8_t l; uint16_t trace = 0; for (l = 0; l < UTILS_COUNT (led_tab); l++) { led_display (trace | led_circle[l], speed); trace = trace | (leds & led_circle[l]); } } void led_animate (uint16_t leds, uint8_t animation, uint16_t speed) { switch (animation) { case LED_ANIMATION_TRACE_CCW: led_animate_trace_ccw (leds, speed); break; } }