From 5b3bd67fb9c780d51b25b5304589b1aab0a1e8a7 Mon Sep 17 00:00:00 2001 From: henryk Date: Sat, 1 Mar 2008 20:24:22 +0000 Subject: Add pwm led code from sniffonly branch git-svn-id: https://svn.openpcd.org:2342/trunk@435 6dc7ffe9-61d6-0310-9af1-9938baff3ed1 --- openpicc/application/led.c | 127 ++++++++++++++++++++++++++++++++++++++------- 1 file changed, 108 insertions(+), 19 deletions(-) (limited to 'openpicc/application/led.c') diff --git a/openpicc/application/led.c b/openpicc/application/led.c index cab12b1..df13d21 100644 --- a/openpicc/application/led.c +++ b/openpicc/application/led.c @@ -3,6 +3,7 @@ * OpenBeacon.org - LED support * * Copyright 2007 Milosch Meriac + * Copyright 2008 Henryk Plötz * *************************************************************** @@ -27,43 +28,102 @@ #include #include #include "led.h" + +#include "gammatable.inc" + /**********************************************************************/ #define BLINK_TIME 5 +#define PWM_PERIOD GAMMA_MAX +const struct channel_definition { + int channel_no; + enum { PERIPH_NONE=0, PERIPH_A, PERIPH_B} periph; + AT91PS_PWMC_CH channel; +} +pwm_channels[] = { + [0] = {0, PERIPH_A, AT91C_BASE_PWMC_CH0}, + [1] = {1, PERIPH_A, AT91C_BASE_PWMC_CH1}, + [2] = {2, PERIPH_A, AT91C_BASE_PWMC_CH2}, + [7] = {3, PERIPH_B, AT91C_BASE_PWMC_CH3}, + [11] = {0, PERIPH_B, AT91C_BASE_PWMC_CH0}, + [12] = {1, PERIPH_B, AT91C_BASE_PWMC_CH1}, + [13] = {2, PERIPH_B, AT91C_BASE_PWMC_CH2}, + [14] = {3, PERIPH_B, AT91C_BASE_PWMC_CH3}, + [23] = {0, PERIPH_B, AT91C_BASE_PWMC_CH0}, + [24] = {1, PERIPH_B, AT91C_BASE_PWMC_CH1}, + [25] = {2, PERIPH_B, AT91C_BASE_PWMC_CH2}, +}; -void vLedSetRed(bool_t on) +static const struct channel_definition* find_channel(unsigned int led) +{ + unsigned int pos = ffs(led); + if(pos==0) return 0; + + if(pos-1 >= sizeof(pwm_channels) / sizeof(pwm_channels[0]) ) return 0; + if(pwm_channels[pos-1].periph == PERIPH_NONE) return 0; + return &pwm_channels[pos-1]; +} + +// Brightness is in per thousand +void vLedSetBrightness(unsigned int led, int brightness) +{ + const struct channel_definition *c = find_channel(led); + if(c==0) return; + + if(brightness < 0) brightness = 0; + if(brightness > GAMMA_LEN-1) brightness = GAMMA_LEN-1; + + int duty = gammatable[brightness]; + if(duty > 1) { + c->channel->PWMC_CUPDR = duty; + if(c->periph == PERIPH_A) { + AT91F_PIO_CfgPeriph(AT91C_BASE_PIOA, led, 0); + } else if(c->periph == PERIPH_B) { + AT91F_PIO_CfgPeriph(AT91C_BASE_PIOA, 0, led); + } + } else { + vLedSet(led, 0); + } +} + +void vLedSet(int led, bool_t on) { if(on) - AT91F_PIO_ClearOutput( AT91C_BASE_PIOA, LED_RED ); + AT91F_PIO_ClearOutput( AT91C_BASE_PIOA, led ); else - AT91F_PIO_SetOutput( AT91C_BASE_PIOA, LED_RED ); + AT91F_PIO_SetOutput( AT91C_BASE_PIOA, led ); + AT91F_PIO_CfgOutput( AT91C_BASE_PIOA, led ); +} + +void vLedBlink(int led) +{ + volatile int i=0; + vLedSet(led, 1); + for(i=0; iperiph == PERIPH_A) { + AT91F_PIO_CfgPeriph(AT91C_BASE_PIOA, led, 0); + } else if(c->periph == PERIPH_B) { + AT91F_PIO_CfgPeriph(AT91C_BASE_PIOA, 0, led); + } else + return; + + // Configure channel: clock = MCK, period = PWM_PERIOD, CPOL=1, duty cycle variable + c->channel->PWMC_CMR = 0x0 | AT91C_PWMC_CPOL; + c->channel->PWMC_CDTYR = 1; + c->channel->PWMC_CPRDR = PWM_PERIOD; + + AT91C_BASE_PWMC->PWMC_ENA = (1<<(c->channel_no)); + vLedSetBrightness(led, 0); +} + void vLedInit(void) { // turn off LED's - AT91F_PIO_CfgOutput( AT91C_BASE_PIOA, LED_MASK ); - AT91F_PIO_SetOutput( AT91C_BASE_PIOA, LED_MASK ); + AT91F_PIO_CfgOutput( AT91C_BASE_PIOA, LED_RED | LED_GREEN ); + AT91F_PIO_SetOutput( AT91C_BASE_PIOA, LED_RED | LED_GREEN ); + + AT91F_PMC_EnablePeriphClock(AT91C_BASE_PMC, + ((unsigned int) 1 << AT91C_ID_PWMC)); + + init_led_pwm(LED_GREEN); + init_led_pwm(LED_RED); } -- cgit v1.2.3