From d8092ae891d96da4bf6daac37a6588150e6a724e Mon Sep 17 00:00:00 2001 From: Lars-Dominik Braun Date: Tue, 27 May 2014 15:02:33 +0200 Subject: pwm: Initial LED PWM --- Makefile | 5 ++-- main.c | 22 +++++++----------- pwm.c | 81 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ pwm.h | 11 +++++++++ 4 files changed, 103 insertions(+), 16 deletions(-) create mode 100644 pwm.c create mode 100644 pwm.h diff --git a/Makefile b/Makefile index 8996720..1c28676 100644 --- a/Makefile +++ b/Makefile @@ -1,9 +1,10 @@ MCU = atmega88 +CFLAGS=-Os all: sanduhr.hex -sanduhr.elf: main.c i2c.c i2c.h uart.c uart.h timer.c timer.h gyro.c gyro.h accel.c accel.h common.h speaker.c speaker.h - avr-gcc -std=gnu99 -mmcu=$(MCU) -Os -o $@ $^ +sanduhr.elf: main.c i2c.c i2c.h uart.c uart.h timer.c timer.h gyro.c gyro.h accel.c accel.h common.h speaker.c speaker.h pwm.c pwm.h + avr-gcc -std=gnu99 -mmcu=$(MCU) $(CFLAGS) -o $@ $^ sanduhr.hex: sanduhr.elf avr-objcopy -O ihex -R .eeprom $< $@ diff --git a/main.c b/main.c index 84aa75e..015abc3 100644 --- a/main.c +++ b/main.c @@ -14,19 +14,7 @@ #include "gyro.h" #include "accel.h" #include "speaker.h" - -static void ledInit () { - /* set led1,led2 to output */ - DDRB |= (1 << PB6) | (1 << PB7); - /* set led3,led4,led5,led6 to output */ - DDRD |= (1 << PD2) | (1 << PD3) | (1 << PD4) | (1 << PD5); -} - -/* show data with leds */ -static void ledShow (const unsigned char val) { - PORTB = (PORTB & ~((1 << PB6) | (1 << PB7))) | ((val & 0x3) << PB6); - PORTD = (PORTD & ~((1 << PD2) | (1 << PD3) | (1 << PD4) | (1 << PD5))) | (((val >> 2) & 0xf) << PD2); -} +#include "pwm.h" static void cpuInit () { /* enter change prescaler mode */ @@ -45,12 +33,12 @@ static void cpuInit () { int main () { cpuInit (); - ledInit (); twInit (); uartInit (); gyroInit (); accelInit (); speakerInit (); + pwmInit (); set_sleep_mode (SLEEP_MODE_IDLE); printf ("initialization done\n"); @@ -59,6 +47,7 @@ int main () { sei (); gyroStart (); accelStart (); + pwmStart (); #if 0 speakerStart (); @@ -70,6 +59,10 @@ int main () { bool checkGyro = false; while (1) { while (!timerHit ()) { + for (uint8_t i = 0; i < 6; i++) { + pwmSetBrightness (i, abs (gyroGetZTicks ())); + } + /* round-robin to prevent starvation */ if (checkGyro) { gyroProcess (); @@ -97,6 +90,7 @@ int main () { #endif } timerStop (); + pwmStop (); printf ("stopped\n"); diff --git a/pwm.c b/pwm.c new file mode 100644 index 0000000..eaaa5af --- /dev/null +++ b/pwm.c @@ -0,0 +1,81 @@ +/* LED pwm, uses timer0 + * XXX: this works, but we should use non-linear steps + */ + +#include +#include +#include + +#include "speaker.h" + +#define PWM_STEPS 16 + +/* inverse brightness; 0 is max brightness, PWM_STEPS off */ +static uint8_t invbrightness[6]; +static uint8_t count = 0; + +ISR(TIMER0_COMPA_vect) { + if (count == 0) { + /* switch off all LEDs */ + PORTB = PORTB & ~((1 << PB6) | (1 << PB7)); + PORTD = PORTD & ~((1 << PD2) | (1 << PD3) | (1 << PD4) | (1 << PD5)); + } else { + uint8_t pb = 0, pd = 0; + if (count > invbrightness[0]) { + pb |= (1 << PB6); + } + if (count > invbrightness[1]) { + pb |= (1 << PB7); + } + if (count > invbrightness[2]) { + pd |= (1 << PD2); + } + if (count > invbrightness[3]) { + pd |= (1 << PD3); + } + if (count > invbrightness[4]) { + pd |= (1 << PD4); + } + if (count > invbrightness[5]) { + pd |= (1 << PD5); + } + /* actually set them */ + PORTB |= pb; + PORTD |= pd; + } + ++count; + if (count >= PWM_STEPS) { + count = 0; + } +} + +void pwmInit () { + /* set led1,led2 to output */ + DDRB |= (1 << PB6) | (1 << PB7); + /* set led3,led4,led5,led6 to output */ + DDRD |= (1 << PD2) | (1 << PD3) | (1 << PD4) | (1 << PD5); +} + +void pwmStart () { + /* reset timer value */ + TCNT0 = 0; + /* set ctc timer0 (part 1) */ + TCCR0A = 0; + /* enable compare match interrupt */ + TIMSK0 = (1 << OCIE0A); + /* compare value; interrupt on every tick */ + OCR0A = 0; + /* io clock with 8 prescaler (>8 is too slow and starts flickering); ctc + * (part 2) */ + TCCR0B = (1 << CS01) | (1 << WGM02); +} + +void pwmStop () { + /* zero clock source */ + TCCR0B = 0; +} + +void pwmSetBrightness (const uint8_t i, const uint8_t b) { + invbrightness[i] = b; +} + diff --git a/pwm.h b/pwm.h new file mode 100644 index 0000000..eeb93c6 --- /dev/null +++ b/pwm.h @@ -0,0 +1,11 @@ +#ifndef PWM_H +#define PWM_H + +#include +void pwmInit (); +void pwmStart (); +void pwmStop (); +void pwmSetBrightness (const uint8_t i, const uint8_t b); + +#endif /* PWM_H */ + -- cgit v1.2.3