From: simimeie Date: Sat, 26 Jun 2010 19:08:18 +0000 (+0000) Subject: - add LED control with PWM X-Git-Url: http://git.rrze.uni-erlangen.de/gitweb/?a=commitdiff_plain;h=17aea8ef6cd47a0469e248a4e7325bcde394ea51;p=moodlight.git - add LED control with PWM - add infrared control - just displaying when the IR receiver pin toggles for now. - some minor text corrections to the console and support for setting LED brightness from there. - add new files to Makefile --- diff --git a/Makefile b/Makefile index d91c875..d78c6e4 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.1 2010/06/26 12:28:08 simimeie Exp $ +# $Id: Makefile,v 1.2 2010/06/26 19:08:18 simimeie Exp $ # Makefile for HaWo Moodlight CC = avr-gcc @@ -27,7 +27,7 @@ CPUFREQ = 8000000UL # desired baudrate of serial debug console BAUDRATE = 9600UL -SRCS = console.c main.c +SRCS = console.c ledpwm.c ircontrol.c main.c PROG = moodlight # compiler flags diff --git a/console.c b/console.c index a8445cb..140765c 100644 --- a/console.c +++ b/console.c @@ -1,4 +1,4 @@ -/* $Id: console.c,v 1.1 2010/06/26 12:28:08 simimeie Exp $ +/* $Id: console.c,v 1.2 2010/06/26 19:08:18 simimeie Exp $ * Functions for a serial console. */ @@ -8,7 +8,9 @@ #include #include #include +#include #include "console.h" +#include "ledpwm.h" /* PD0 is RXD, PD1 is TXD, but we don't need to address them manually */ @@ -27,14 +29,14 @@ static uint8_t escstatus = 0; static prog_uint8_t CRLF[] = "\r\n"; static prog_uint8_t WELCOMEMSG[] = "\r\n"\ "\r\n ******************************************"\ - "\r\n * universal mainboard v1 *"\ - "\r\n * (C) Michael 'PoempelFox' Meier 05/2010 *"\ + "\r\n * HaWo Moodlight v0 (prototype) *"\ + "\r\n * (C) Michael 'PoempelFox' Meier 06/2010 *"\ "\r\n ******************************************"\ "\r\n"\ "\r\nProcessor: atmega328"\ "\r\nAVR-libc: " __AVR_LIBC_VERSION_STRING__ " (" __AVR_LIBC_DATE_STRING__ ")"\ "\r\nSoftware Version 0.1, Compiled " __DATE__ " " __TIME__; -static prog_uint8_t PROMPT[] = "\r\nroot@mbv1# "; +static prog_uint8_t PROMPT[] = "\r\nroot@moodlight# "; /* Handler for TXC (TX Complete) IRQ */ ISR(USART_TX_vect) { @@ -260,6 +262,7 @@ ISR(USART_RX_vect) { console_printpgm_noirq_P(PSTR("\r\n motd repeat welcome message")); console_printpgm_noirq_P(PSTR("\r\n showpins [x] shows the avrs inputpins")); console_printpgm_noirq_P(PSTR("\r\n status show status / counters")); + console_printpgm_noirq_P(PSTR("\r\n [rgb] n sets the brightness of the red / green / blue LED to n")); /* console_printpgm_noirq_P(PSTR("\r\n save saves settings to EEPROM")); */ } else if (strcmp_P(inputbuf, PSTR("motd")) == 0) { console_printpgm_noirq_P(WELCOMEMSG); @@ -319,6 +322,24 @@ ISR(USART_RX_vect) { } else if (strcmp_P(inputbuf, PSTR("status")) == 0) { console_printpgm_noirq_P(PSTR("Current status:\r\n")); console_printpgm_noirq_P(PSTR("none. nothing implemented yet.")); + } else if (strncmp_P(inputbuf, PSTR("r "), 2) == 0) { + uint8_t v; + v = strtoul(&inputbuf[2], NULL, 0); + ledpwm_setled(LEDPWM_REDLED, v); + console_printpgm_P(PSTR("brightness of RED LED set to 0x")); + console_printhex8(v); + } else if (strncmp_P(inputbuf, PSTR("g "), 2) == 0) { + uint8_t v; + v = strtoul(&inputbuf[2], NULL, 0); + ledpwm_setled(LEDPWM_GREENLED, v); + console_printpgm_P(PSTR("brightness of GREEN LED set to 0x")); + console_printhex8(v); + } else if (strncmp_P(inputbuf, PSTR("b "), 2) == 0) { + uint8_t v; + v = strtoul(&inputbuf[2], NULL, 0); + ledpwm_setled(LEDPWM_BLUELED, v); + console_printpgm_P(PSTR("brightness of BLUE LED set to 0x")); + console_printhex8(v); #ifdef JOKECMDS } else if (strncmp_P(inputbuf, PSTR("ls"), 2) == 0) { console_printpgm_noirq_P(PSTR("Total 4711\r\n")); diff --git a/ircontrol.c b/ircontrol.c new file mode 100644 index 0000000..cf7e494 --- /dev/null +++ b/ircontrol.c @@ -0,0 +1,29 @@ +/* $Id: ircontrol.c,v 1.1 2010/06/26 19:08:18 simimeie Exp $ + * Functions for the infrared receiver + * + * The infrared receiver is connected to PB0 / PCINT0. + */ + +#include +#include +#include "ircontrol.h" +#include "console.h" + +ISR(PCINT0_vect) { + uint8_t v = PINB & _BV(PB0); + if (v) { + console_printpgm_P(PSTR("!1!")); + } else { + console_printpgm_P(PSTR("!0!")); + } +} + +void ircontrol_init(void) +{ + /* Activate pullup */ + PORTB |= _BV(PB0); + /* enable PCINT0 */ + PCICR |= _BV(PCIE0); + /* Enable pin change interrupt 0 (=PB0) in pcint0 */ + PCMSK0 |= _BV(PCINT0); +} diff --git a/ircontrol.h b/ircontrol.h new file mode 100644 index 0000000..b1a42ef --- /dev/null +++ b/ircontrol.h @@ -0,0 +1,11 @@ +/* $Id: ircontrol.h,v 1.1 2010/06/26 19:08:18 simimeie Exp $ + * Functions for the infrared receiver + */ + +#ifndef _IRCONTROL_H_ +#define _IRCONTROL_H_ + +/* Init infrared receiver (pins) */ +void ircontrol_init(void); + +#endif /* _IRCONTROL_H_ */ diff --git a/ledpwm.c b/ledpwm.c new file mode 100644 index 0000000..dfc26d6 --- /dev/null +++ b/ledpwm.c @@ -0,0 +1,96 @@ +/* $Id: ledpwm.c,v 1.1 2010/06/26 19:08:18 simimeie Exp $ + * Functions for led brightness control via PWM (pulse width modulation). + */ + +#include +#include "ledpwm.h" + +/* Select between Phase correct PWM and Fast PWM mode. + * setting this to 1 selects phase correct mode, everything else is Fast PWM. */ +#define PHASECORRECTPWM 1 +/* + * Our hardware connections are as follows: + * Red -> PD6 / OC0A + * Green -> PD5 / OC0B + * Blue -> PD3 / OC2B + */ +void ledpwm_init(void) +{ + /* Set OC2B, OC0A and OC0B to output */ + DDRD |= _BV(PD3) | _BV(PD5) | _BV(PD6); + /* Set compare output mode for OC2B in timer counter control register: */ +#if (PHASECORRECTPWM == 1) + /* select phase correct PWM mode (1). WGM2 bit is 0 so we don't need to touch TCCR2B. */ + TCCR2A |= _BV(COM2B1) | _BV(WGM20); +#else /* not PHASECORRECTPWM */ + /* set output at BOTTOM (=0), clear it on compare match. + * select fast PWM mode 3. WGM2 bit is 0 so we don't need to touch TCCR2B. */ + TCCR2A |= _BV(COM2B1) | _BV(WGM20) /*| _BV(WGM21)*/; +#endif /* PHASECORRECTPWM */ + /* select clock source: cpu clock without prescaler. */ + TCCR2B |= _BV(CS20); + /* Default brightness: PWM 0 */ + OCR2B = 0; + /* Set compare output mode for OC0A and OC0B in timer counter control register: */ +#if (PHASECORRECTPWM == 1) + /* select phase correct PWM mode (1). WGM2 bit is 0 so we don't need to touch TCCR0B. */ + TCCR0A |= _BV(COM0A1) | _BV(COM0B1) | _BV(WGM00); +#else /* not PHASECORRECTPWM */ + /* set output at BOTTOM (=0), clear it on compare match. + * select fast PWM mode 3. WGM2 bit is 0 so we don't need to touch TCCR0B. */ + TCCR0A |= _BV(COM0A1) | _BV(COM0B1) | _BV(WGM00) | _BV(WGM01); +#endif /* PHASECORRECTPWM */ + /* select clock source: i/o clock without prescaler. */ + TCCR0B |= _BV(CS20); + /* Default brightness: PWM 0 */ + OCR0A = 0; + OCR0B = 0; +} + +/* In none-phase-correct PWM mode, This function does some mapping of + * the values: + * 0 really turns the LED off. + * 1 is an PWM value of 0, which still lets the LED glimmer. + * 2 to 254 are mapped to PWM 3 to 253 (always one less!) + * 255 is mapped to PWM 255. + * So there is no way to set PWM 254, but you cannot visually see the + * difference to 253 or 255 anyways... + * In phase-correct PWM mode there does not need to be a mapping, 0 means off. + */ +void ledpwm_setled(uint8_t led, uint8_t val) +{ +#if (PHASECORRECTPWM == 1) + switch (led) { + case LEDPWM_REDLED: OCR0A = val; break; + case LEDPWM_GREENLED: OCR0B = val; break; + case LEDPWM_BLUELED: OCR2B = val; break; + }; +#else /* not PHASECORRECTPWM */ + if (val == 0) { + switch (led) { + case LEDPWM_REDLED: DDRD &= (uint8_t)~_BV(PD6); + break; + case LEDPWM_GREENLED: DDRD &= (uint8_t)~_BV(PD5); + break; + case LEDPWM_BLUELED: DDRD &= (uint8_t)~_BV(PD3); + break; + }; + } else { + val -= 1; + if (val == 254) { + val = 255; + } + switch (led) { + case LEDPWM_REDLED: DDRD |= _BV(PD6); + OCR0A = val; + break; + case LEDPWM_GREENLED: DDRD |= _BV(PD5); + OCR0B = val; + break; + case LEDPWM_BLUELED: DDRD |= _BV(PD3); + OCR2B = val; + break; + }; + } +#endif /* PHASECORRECTPWM */ +} diff --git a/ledpwm.h b/ledpwm.h new file mode 100644 index 0000000..2b9dc2f --- /dev/null +++ b/ledpwm.h @@ -0,0 +1,18 @@ +/* $Id: ledpwm.h,v 1.1 2010/06/26 19:08:18 simimeie Exp $ + * Functions for led brightness control via PWM (pulse width modulation). + */ + +#ifndef _LEDPWM_H_ +#define _LEDPWM_H_ + +#define LEDPWM_REDLED 1 +#define LEDPWM_GREENLED 2 +#define LEDPWM_BLUELED 3 + +/* Init PWM (pins and timers) */ +void ledpwm_init(void); + +/* Set brightness for a certain LED */ +void ledpwm_setled(uint8_t led, uint8_t val); + +#endif /* _LEDPWM_H_ */ diff --git a/main.c b/main.c index 3073f33..3b8e373 100644 --- a/main.c +++ b/main.c @@ -1,4 +1,4 @@ -/* $Id: main.c,v 1.1 2010/06/26 12:28:08 simimeie Exp $ +/* $Id: main.c,v 1.2 2010/06/26 19:08:18 simimeie Exp $ * Main file for the HaWo moodlight. * This is the main file that glues it all together. It also contains all * functionality that is too small to require an extra file. @@ -16,6 +16,8 @@ #include #include "console.h" +#include "ledpwm.h" +#include "ircontrol.h" /* #include "eepromdata.h" */ uint8_t mcusr_mirror __attribute__ ((section (".noinit"))); @@ -33,7 +35,7 @@ void get_mcusr(void) { int main(void) { - uint8_t i; + uint8_t i = 0; /* Load settings from EEPROM */ #if 0 @@ -42,6 +44,8 @@ int main(void) /* Initialize stuff */ console_init(); + ledpwm_init(); + ircontrol_init(); wdt_enable(WDTO_2S); @@ -61,5 +65,11 @@ int main(void) while (1) { /* We should never exit */ wdt_reset(); + /* i++; + console_printhex8(i); + ledpwm_setled(LEDPWM_REDLED, i); + ledpwm_setled(LEDPWM_GREENLED, i+128); + ledpwm_setled(LEDPWM_BLUELED, 255-i); + _delay_ms(500); */ } }