]>
Commit | Line | Data |
---|---|---|
6c58993d | 1 | /* $Id: ledpwm.c,v 1.5 2010/08/08 17:06:11 simimeie Exp $ |
17aea8ef | 2 | * Functions for led brightness control via PWM (pulse width modulation). |
3 | */ | |
4 | ||
5 | #include <avr/io.h> | |
4307b86a | 6 | #include <avr/interrupt.h> |
17aea8ef | 7 | #include "ledpwm.h" |
8 | ||
17aea8ef | 9 | /* |
4307b86a | 10 | * Our hardware connections on the first prototype are as follows: |
11 | * Red -> PD6 (OC0A) | |
12 | * Green -> PD5 (OC0B) | |
13 | * Blue -> PD3 (OC2B) CHANGED umgeloetet durch Julian jetzt PD7 | |
14 | * In the next hardware revision this will be: | |
15 | * Red -> PC3 | |
16 | * Green -> PC2 | |
17 | * Blue -> PC1 | |
17aea8ef | 18 | */ |
ddf1553f | 19 | |
4307b86a | 20 | #define LEDPORT PORTD |
21 | #define LEDDDR DDRD | |
22 | #define LEDPINR 6 | |
23 | #define LEDPING 5 | |
24 | #define LEDPINB 7 | |
25 | ||
ddf1553f | 26 | uint8_t ledpwm_re = 0xff, ledpwm_gr = 0xff, ledpwm_bl = 0xff; |
27 | uint8_t ledpwm_bri = 128; | |
4307b86a | 28 | /* Internal */ |
29 | volatile uint16_t ledpwm_val[3] = { 0x8000, 0x8000, 0x8000 }; | |
30 | volatile uint16_t ledpwm_curoreg = 0; | |
ddf1553f | 31 | |
4307b86a | 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; | |
6c58993d | 36 | uint16_t tmp1 = ledpwm_curoreg; /* Copy so the compiler can place it into |
37 | * a register despite the volatile. */ | |
4307b86a | 38 | uint8_t i; |
39 | for (i = 0; i < 3; i++) { | |
6c58993d | 40 | if ((ledpwm_val[i] > tmp1) && (ledpwm_val[i] <= nextval)) { |
4307b86a | 41 | nextval = ledpwm_val[i]; |
42 | } | |
43 | } | |
6c58993d | 44 | /* tmp1 now reused */ |
45 | tmp1 = TCNT1L; | |
46 | tmp1 |= (uint16_t)TCNT1H << 8; | |
47 | if ((tmp1 + 30) > nextval) { /* 30 cycles is more or less a guess. | |
48 | * This needs to be set to the number of cycles the code takes from | |
49 | * here until the iret. */ | |
50 | nextval = tmp1 + 30; | |
51 | } | |
4307b86a | 52 | OCR1AH = nextval >> 8; |
53 | OCR1AL = nextval & 0xff; | |
54 | ledpwm_curoreg = nextval; | |
17aea8ef | 55 | } |
56 | ||
4307b86a | 57 | /* This gets called from timers.c which holds the 'main' (interrupt) |
58 | * handler for the timer1 overflow. */ | |
59 | void ledpwm_TIMER1OVF_hook(void) { | |
60 | /* Turn on all LEDs */ | |
61 | if (ledpwm_val[LEDPWM_REDLED] > 0) { | |
62 | LEDPORT |= _BV(LEDPINR); | |
63 | } | |
64 | if (ledpwm_val[LEDPWM_GREENLED] > 0) { | |
65 | LEDPORT |= _BV(LEDPING); | |
66 | } | |
67 | if (ledpwm_val[LEDPWM_BLUELED] > 0) { | |
68 | LEDPORT |= _BV(LEDPINB); | |
69 | } | |
70 | ledpwm_curoreg = 0; | |
71 | ledpwm_programnextstep(); | |
72 | } | |
73 | ||
74 | /* Called on compare match */ | |
75 | ISR(TIMER1_COMPA_vect) | |
17aea8ef | 76 | { |
6c58993d | 77 | uint8_t orval = 0x00; |
78 | if (ledpwm_val[LEDPWM_REDLED] > ledpwm_curoreg) { | |
79 | orval |= _BV(LEDPINR); | |
4307b86a | 80 | } |
6c58993d | 81 | if (ledpwm_val[LEDPWM_GREENLED] > ledpwm_curoreg) { |
82 | orval |= _BV(LEDPING); | |
4307b86a | 83 | } |
6c58993d | 84 | if (ledpwm_val[LEDPWM_BLUELED] > ledpwm_curoreg) { |
85 | orval |= _BV(LEDPINB); | |
17aea8ef | 86 | } |
6c58993d | 87 | LEDPORT = (LEDPORT & (uint8_t)~(_BV(LEDPINR) | _BV(LEDPING) | _BV(LEDPINB))) | orval; |
4307b86a | 88 | ledpwm_programnextstep(); |
89 | } | |
90 | ||
91 | void ledpwm_init(void) { | |
92 | /* Set our Port Pins to output */ | |
93 | LEDDDR |= _BV(LEDPINR) | _BV(LEDPING) | _BV(LEDPINB); | |
94 | /* DO NOT initialize TIMER1 frequency and overflow interrupt. | |
95 | * timers.c already does that. */ | |
96 | /* Enable TIMER1 output compare interrupt A */ | |
97 | TIMSK1 |= _BV(OCIE1A); | |
4307b86a | 98 | } |
99 | ||
100 | void ledpwm_setled(uint8_t led, uint16_t val) { | |
101 | if (led > 2) { return; /* ignore invalid values */ } | |
102 | ledpwm_val[led] = val; | |
17aea8ef | 103 | } |
de0e300b | 104 | |
105 | void ledpwm_set(uint8_t red, uint8_t green, uint8_t blue, uint8_t br) { | |
4307b86a | 106 | ledpwm_val[LEDPWM_REDLED] = red * br; |
107 | ledpwm_val[LEDPWM_GREENLED] = green * br; | |
108 | ledpwm_val[LEDPWM_BLUELED] = blue * br; | |
de0e300b | 109 | } |