1 /* $Id: ledpwm.c,v 1.4 2010/07/25 20:40:44 simimeie Exp $
2 * Functions for led brightness control via PWM (pulse width modulation).
6 #include <avr/interrupt.h>
10 * Our hardware connections on the first prototype are as follows:
13 * Blue -> PD3 (OC2B) CHANGED umgeloetet durch Julian jetzt PD7
14 * In the next hardware revision this will be:
26 uint8_t ledpwm_re = 0xff, ledpwm_gr = 0xff, ledpwm_bl = 0xff;
27 uint8_t ledpwm_bri = 128;
29 volatile uint16_t ledpwm_val[3] = { 0x8000, 0x8000, 0x8000 };
30 volatile uint16_t ledpwm_curoreg = 0;
32 /* To do a 16-bit write, the high byte must be written before the low byte.
33 * For a 16-bit read, the low byte must be read before the high byte */
34 static void ledpwm_programnextstep(void) {
35 uint16_t nextval = 0xffff;
37 for (i = 0; i < 3; i++) {
38 if ((ledpwm_val[i] > ledpwm_curoreg) && (ledpwm_val[i] <= nextval)) {
39 nextval = ledpwm_val[i];
42 OCR1AH = nextval >> 8;
43 OCR1AL = nextval & 0xff;
44 ledpwm_curoreg = nextval;
47 /* This gets called from timers.c which holds the 'main' (interrupt)
48 * handler for the timer1 overflow. */
49 void ledpwm_TIMER1OVF_hook(void) {
50 /* Turn on all LEDs */
51 if (ledpwm_val[LEDPWM_REDLED] > 0) {
52 LEDPORT |= _BV(LEDPINR);
54 if (ledpwm_val[LEDPWM_GREENLED] > 0) {
55 LEDPORT |= _BV(LEDPING);
57 if (ledpwm_val[LEDPWM_BLUELED] > 0) {
58 LEDPORT |= _BV(LEDPINB);
61 ledpwm_programnextstep();
64 /* Called on compare match */
65 ISR(TIMER1_COMPA_vect)
67 if (ledpwm_val[LEDPWM_REDLED] <= ledpwm_curoreg) {
68 LEDPORT &= (uint8_t)~_BV(LEDPINR);
70 if (ledpwm_val[LEDPWM_GREENLED] <= ledpwm_curoreg) {
71 LEDPORT &= (uint8_t)~_BV(LEDPING);
73 if (ledpwm_val[LEDPWM_BLUELED] <= ledpwm_curoreg) {
74 LEDPORT &= (uint8_t)~_BV(LEDPINB);
76 ledpwm_programnextstep();
79 void ledpwm_init(void) {
80 /* Set our Port Pins to output */
81 LEDDDR |= _BV(LEDPINR) | _BV(LEDPING) | _BV(LEDPINB);
82 /* DO NOT initialize TIMER1 frequency and overflow interrupt.
83 * timers.c already does that. */
84 /* Enable TIMER1 output compare interrupt A */
85 TIMSK1 |= _BV(OCIE1A);
86 ledpwm_programnextstep();
89 void ledpwm_setled(uint8_t led, uint16_t val) {
90 if (led > 2) { return; /* ignore invalid values */ }
91 ledpwm_val[led] = val;
92 ledpwm_programnextstep();
95 void ledpwm_set(uint8_t red, uint8_t green, uint8_t blue, uint8_t br) {
96 ledpwm_val[LEDPWM_REDLED] = red * br;
97 ledpwm_val[LEDPWM_GREENLED] = green * br;
98 ledpwm_val[LEDPWM_BLUELED] = blue * br;
99 ledpwm_programnextstep();