1 /* $Id: ledpwm.c,v 1.2 2010/06/30 19:39:28 simimeie Exp $
2 * Functions for led brightness control via PWM (pulse width modulation).
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
13 * Our hardware connections are as follows:
19 uint8_t ledpwm_re = 0xff, ledpwm_gr = 0xff, ledpwm_bl = 0xff;
20 uint8_t ledpwm_bri = 128;
22 void ledpwm_init(void)
24 /* Set OC2B, OC0A and OC0B to output */
25 DDRD |= _BV(PD3) | _BV(PD5) | _BV(PD6);
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. */
37 /* Default brightness: PWM 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. */
50 /* Default brightness: PWM 0 */
55 /* In none-phase-correct PWM mode, This function does some mapping of
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.
65 void ledpwm_setled(uint8_t led, uint8_t val)
67 #if (PHASECORRECTPWM == 1)
69 case LEDPWM_REDLED: OCR0A = val; break;
70 case LEDPWM_GREENLED: OCR0B = val; break;
71 case LEDPWM_BLUELED: OCR2B = val; break;
73 #else /* not PHASECORRECTPWM */
76 case LEDPWM_REDLED: DDRD &= (uint8_t)~_BV(PD6);
78 case LEDPWM_GREENLED: DDRD &= (uint8_t)~_BV(PD5);
80 case LEDPWM_BLUELED: DDRD &= (uint8_t)~_BV(PD3);
89 case LEDPWM_REDLED: DDRD |= _BV(PD6);
92 case LEDPWM_GREENLED: DDRD |= _BV(PD5);
95 case LEDPWM_BLUELED: DDRD |= _BV(PD3);
100 #endif /* PHASECORRECTPWM */