summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author(no author) <(no author)@6dc7ffe9-61d6-0310-9af1-9938baff3ed1>2006-08-03 15:51:03 +0000
committer(no author) <(no author)@6dc7ffe9-61d6-0310-9af1-9938baff3ed1>2006-08-03 15:51:03 +0000
commitc604e0c239023726463f317076d31502273d9c11 (patch)
treef93867c3993c395634a3381a8cd8d3a4ce945b2b
parent3866f9839a61f117f9def7926b50eac9a5888eef (diff)
- change from PA23 to PA0
- specify duty cycle in percent - fix timing calculations git-svn-id: https://svn.openpcd.org:2342/trunk@73 6dc7ffe9-61d6-0310-9af1-9938baff3ed1
-rw-r--r--openpcd/firmware/src/pwm.c36
1 files changed, 28 insertions, 8 deletions
diff --git a/openpcd/firmware/src/pwm.c b/openpcd/firmware/src/pwm.c
index 90653f9..fd11e7c 100644
--- a/openpcd/firmware/src/pwm.c
+++ b/openpcd/firmware/src/pwm.c
@@ -8,12 +8,21 @@
#include <AT91SAM7.h>
#include <sys/types.h>
#include <errno.h>
+#include "dbgu.h"
#define Hz
#define kHz *1000 Hz
#define MHz *1000 kHz
#define MCLK (48 MHz)
+#if 1
+#define DEBUGPWM DEBUGPCRF
+#else
+#define DEBUGPWM(x, args...)
+#endif
+
+static AT91PS_PWMC pwm = AT91C_BASE_PWMC;
+
/* find highest bit set. returns bit (32..1) or 0 in case no bit set */
static int fhs(u_int32_t val)
{
@@ -36,15 +45,16 @@ int pwm_freq_set(int channel, u_int32_t freq)
* 48MHz/261120 = 183Hz */
u_int32_t overall_div;
u_int32_t presc_total;
- u_int32_t cpre = 0;
- u_int8_t cprd;
+ u_int8_t cpre = 0;
+ u_int16_t cprd;
if (freq > MCLK)
return -ERANGE;
overall_div = MCLK / freq;
+ DEBUGPCRF("mclk=%u, freq=%u, overall_div=%u", MCLK, freq, overall_div);
- if (overall_div > 0x7ffff) {
+ if (overall_div > 0x7fff) {
/* divisor is larger than half the maximum CPRD register, we
* have to configure prescalers */
presc_total = overall_div >> 15;
@@ -59,7 +69,9 @@ int pwm_freq_set(int channel, u_int32_t freq)
} else
cprd = overall_div;
- AT91F_PWMC_CfgChannel(AT91C_BASE_PWMC, channel, cpre, 0, cprd);
+ DEBUGPCRF("cpre=%u, cprd=%u", cpre, cprd);
+ AT91F_PWMC_CfgChannel(AT91C_BASE_PWMC, channel,
+ cpre|AT91C_PWMC_CPOL, cprd, 1);
return 0;
}
@@ -74,15 +86,23 @@ void pwm_stop(int channel)
AT91F_PWMC_StopChannel(AT91C_BASE_PWMC, (1 << channel));
}
-void pwm_duty(int channel, u_int16_t duty)
+void pwm_duty_set_percent(int channel, u_int16_t duty)
{
- AT91F_PWMC_UpdateChannel(AT91C_BASE_PWMC, channel, duty);
+ u_int32_t tmp = pwm->PWMC_CH[channel].PWMC_CPRDR & 0xffff;
+
+ tmp = tmp << 16; /* extend value by 2^16 */
+ tmp = tmp / 100; /* tmp = 1 % of extended cprd */
+ tmp = duty * tmp; /* tmp = 'duty' % of extended cprd */
+ tmp = tmp >> 16; /* un-extend tmp (divide by 2^16) */
+
+ DEBUGPWM("Writing %u to Update register\n", tmp);
+ AT91F_PWMC_UpdateChannel(AT91C_BASE_PWMC, channel, tmp);
}
void pwm_init(void)
{
- /* Set PA23 ti Peripheral B (PWM0) */
- AT91F_PIO_CfgPeriph(AT91C_BASE_PIOA, 0, AT91C_PA23_PWM0);
+ /* Set PA0 to Peripheral A (PWM0) */
+ AT91F_PIO_CfgPeriph(AT91C_BASE_PIOA, AT91C_PA0_PWM0, 0);
/* Enable Clock for PWM controller */
AT91F_PWMC_CfgPMC();
personal git repositories of Harald Welte. Your mileage may vary