- add eepromdata.h
[moodlight.git] / ledpwm.c
CommitLineData
de0e300b 1/* $Id: ledpwm.c,v 1.3 2010/07/10 07:34:51 simimeie Exp $
17aea8ef 2 * Functions for led brightness control via PWM (pulse width modulation).
3 */
4
5#include <avr/io.h>
6#include "ledpwm.h"
7
8/* Select between Phase correct PWM and Fast PWM mode.
9 * setting this to 1 selects phase correct mode, everything else is Fast PWM. */
10#define PHASECORRECTPWM 1
ddf1553f 11
17aea8ef 12/*
13 * Our hardware connections are as follows:
14 * Red -> PD6 / OC0A
15 * Green -> PD5 / OC0B
16 * Blue -> PD3 / OC2B
17 */
ddf1553f 18
19uint8_t ledpwm_re = 0xff, ledpwm_gr = 0xff, ledpwm_bl = 0xff;
20uint8_t ledpwm_bri = 128;
21
17aea8ef 22void ledpwm_init(void)
23{
24 /* Set OC2B, OC0A and OC0B to output */
de0e300b 25 DDRD |= _BV(3) | _BV(5) | _BV(6);
17aea8ef 26 /* Set compare output mode for OC2B in timer counter control register: */
27#if (PHASECORRECTPWM == 1)
28 /* select phase correct PWM mode (1). WGM2 bit is 0 so we don't need to touch TCCR2B. */
29 TCCR2A |= _BV(COM2B1) | _BV(WGM20);
30#else /* not PHASECORRECTPWM */
31 /* set output at BOTTOM (=0), clear it on compare match.
32 * select fast PWM mode 3. WGM2 bit is 0 so we don't need to touch TCCR2B. */
33 TCCR2A |= _BV(COM2B1) | _BV(WGM20) /*| _BV(WGM21)*/;
34#endif /* PHASECORRECTPWM */
35 /* select clock source: cpu clock without prescaler. */
36 TCCR2B |= _BV(CS20);
37 /* Default brightness: PWM 0 */
38 OCR2B = 0;
39 /* Set compare output mode for OC0A and OC0B in timer counter control register: */
40#if (PHASECORRECTPWM == 1)
41 /* select phase correct PWM mode (1). WGM2 bit is 0 so we don't need to touch TCCR0B. */
42 TCCR0A |= _BV(COM0A1) | _BV(COM0B1) | _BV(WGM00);
43#else /* not PHASECORRECTPWM */
44 /* set output at BOTTOM (=0), clear it on compare match.
45 * select fast PWM mode 3. WGM2 bit is 0 so we don't need to touch TCCR0B. */
46 TCCR0A |= _BV(COM0A1) | _BV(COM0B1) | _BV(WGM00) | _BV(WGM01);
47#endif /* PHASECORRECTPWM */
48 /* select clock source: i/o clock without prescaler. */
49 TCCR0B |= _BV(CS20);
50 /* Default brightness: PWM 0 */
51 OCR0A = 0;
52 OCR0B = 0;
53}
54
55/* In none-phase-correct PWM mode, This function does some mapping of
56 * the values:
57 * 0 really turns the LED off.
58 * 1 is an PWM value of 0, which still lets the LED glimmer.
59 * 2 to 254 are mapped to PWM 3 to 253 (always one less!)
60 * 255 is mapped to PWM 255.
61 * So there is no way to set PWM 254, but you cannot visually see the
62 * difference to 253 or 255 anyways...
63 * In phase-correct PWM mode there does not need to be a mapping, 0 means off.
64 */
65void ledpwm_setled(uint8_t led, uint8_t val)
66{
67#if (PHASECORRECTPWM == 1)
68 switch (led) {
69 case LEDPWM_REDLED: OCR0A = val; break;
70 case LEDPWM_GREENLED: OCR0B = val; break;
71 case LEDPWM_BLUELED: OCR2B = val; break;
72 };
73#else /* not PHASECORRECTPWM */
74 if (val == 0) {
75 switch (led) {
de0e300b 76 case LEDPWM_REDLED: DDRD &= (uint8_t)~_BV(6);
17aea8ef 77 break;
de0e300b 78 case LEDPWM_GREENLED: DDRD &= (uint8_t)~_BV(5);
17aea8ef 79 break;
de0e300b 80 case LEDPWM_BLUELED: DDRD &= (uint8_t)~_BV(3);
17aea8ef 81 break;
82 };
83 } else {
84 val -= 1;
85 if (val == 254) {
86 val = 255;
87 }
88 switch (led) {
de0e300b 89 case LEDPWM_REDLED: DDRD |= _BV(6);
17aea8ef 90 OCR0A = val;
91 break;
de0e300b 92 case LEDPWM_GREENLED: DDRD |= _BV(5);
17aea8ef 93 OCR0B = val;
94 break;
de0e300b 95 case LEDPWM_BLUELED: DDRD |= _BV(3);
17aea8ef 96 OCR2B = val;
97 break;
98 };
99 }
100#endif /* PHASECORRECTPWM */
101}
de0e300b 102
103void ledpwm_set(uint8_t red, uint8_t green, uint8_t blue, uint8_t br) {
104 ledpwm_setled(LEDPWM_REDLED, (((uint16_t)red * br) / 255));
105 ledpwm_setled(LEDPWM_GREENLED,(((uint16_t)green * br) / 255));
106 ledpwm_setled(LEDPWM_BLUELED, (((uint16_t)blue * br) / 255));
107}
This page took 0.055657 seconds and 4 git commands to generate.