1 /* $Id: ledpwm.c,v 1.1 2010/06/26 19:08:18 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
12 * Our hardware connections are as follows:
17 void ledpwm_init(void)
19 /* Set OC2B, OC0A and OC0B to output */
20 DDRD |= _BV(PD3) | _BV(PD5) | _BV(PD6);
21 /* Set compare output mode for OC2B in timer counter control register: */
22 #if (PHASECORRECTPWM == 1)
23 /* select phase correct PWM mode (1). WGM2 bit is 0 so we don't need to touch TCCR2B. */
24 TCCR2A |= _BV(COM2B1) | _BV(WGM20);
25 #else /* not PHASECORRECTPWM */
26 /* set output at BOTTOM (=0), clear it on compare match.
27 * select fast PWM mode 3. WGM2 bit is 0 so we don't need to touch TCCR2B. */
28 TCCR2A |= _BV(COM2B1) | _BV(WGM20) /*| _BV(WGM21)*/;
29 #endif /* PHASECORRECTPWM */
30 /* select clock source: cpu clock without prescaler. */
32 /* Default brightness: PWM 0 */
34 /* Set compare output mode for OC0A and OC0B in timer counter control register: */
35 #if (PHASECORRECTPWM == 1)
36 /* select phase correct PWM mode (1). WGM2 bit is 0 so we don't need to touch TCCR0B. */
37 TCCR0A |= _BV(COM0A1) | _BV(COM0B1) | _BV(WGM00);
38 #else /* not PHASECORRECTPWM */
39 /* set output at BOTTOM (=0), clear it on compare match.
40 * select fast PWM mode 3. WGM2 bit is 0 so we don't need to touch TCCR0B. */
41 TCCR0A |= _BV(COM0A1) | _BV(COM0B1) | _BV(WGM00) | _BV(WGM01);
42 #endif /* PHASECORRECTPWM */
43 /* select clock source: i/o clock without prescaler. */
45 /* Default brightness: PWM 0 */
50 /* In none-phase-correct PWM mode, This function does some mapping of
52 * 0 really turns the LED off.
53 * 1 is an PWM value of 0, which still lets the LED glimmer.
54 * 2 to 254 are mapped to PWM 3 to 253 (always one less!)
55 * 255 is mapped to PWM 255.
56 * So there is no way to set PWM 254, but you cannot visually see the
57 * difference to 253 or 255 anyways...
58 * In phase-correct PWM mode there does not need to be a mapping, 0 means off.
60 void ledpwm_setled(uint8_t led, uint8_t val)
62 #if (PHASECORRECTPWM == 1)
64 case LEDPWM_REDLED: OCR0A = val; break;
65 case LEDPWM_GREENLED: OCR0B = val; break;
66 case LEDPWM_BLUELED: OCR2B = val; break;
68 #else /* not PHASECORRECTPWM */
71 case LEDPWM_REDLED: DDRD &= (uint8_t)~_BV(PD6);
73 case LEDPWM_GREENLED: DDRD &= (uint8_t)~_BV(PD5);
75 case LEDPWM_BLUELED: DDRD &= (uint8_t)~_BV(PD3);
84 case LEDPWM_REDLED: DDRD |= _BV(PD6);
87 case LEDPWM_GREENLED: DDRD |= _BV(PD5);
90 case LEDPWM_BLUELED: DDRD |= _BV(PD3);
95 #endif /* PHASECORRECTPWM */