summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author(no author) <(no author)@6dc7ffe9-61d6-0310-9af1-9938baff3ed1>2006-08-03 10:00:21 +0000
committer(no author) <(no author)@6dc7ffe9-61d6-0310-9af1-9938baff3ed1>2006-08-03 10:00:21 +0000
commitada3d4fa86e6f178c8281f1cf7a5c55f8961accb (patch)
treedef3f0c4749c4018b436ec66601cb11ff620ab08
parent1bc8544204ae4a75ed8b4c76cee9fa3bd9d505d6 (diff)
add code for PWM controller
git-svn-id: https://svn.openpcd.org:2342/trunk@71 6dc7ffe9-61d6-0310-9af1-9938baff3ed1
-rw-r--r--openpcd/firmware/Makefile2
-rw-r--r--openpcd/firmware/src/pwm.c94
-rw-r--r--openpcd/firmware/src/pwm.h11
3 files changed, 106 insertions, 1 deletions
diff --git a/openpcd/firmware/Makefile b/openpcd/firmware/Makefile
index c9c793e..247dcd5 100644
--- a/openpcd/firmware/Makefile
+++ b/openpcd/firmware/Makefile
@@ -74,7 +74,7 @@ SRC =
# use file-extension c for "c-only"-files
SRCARM = lib/lib_AT91SAM7.c src/pcd_enumerate.c src/fifo.c src/dbgu.c \
src/led.c src/rc632.c src/rc632_highlevel.c src/req_ctx.c \
- src/trigger.c src/main.c src/syscalls.c \
+ src/trigger.c src/main.c src/syscalls.c src/pwm.c \
src/$(TARGET).c src/start/Cstartup_SAM7.c
SRCARM += src/rfid_layer2_iso14443a.c
diff --git a/openpcd/firmware/src/pwm.c b/openpcd/firmware/src/pwm.c
new file mode 100644
index 0000000..90653f9
--- /dev/null
+++ b/openpcd/firmware/src/pwm.c
@@ -0,0 +1,94 @@
+/* AT91SAM7 PWM routines for OpenPCD / OpenPICC
+ *
+ * (C) 2006 by Harald Welte <hwelte@hmw-consulting.de>
+ *
+ */
+
+#include <lib_AT91SAM7.h>
+#include <AT91SAM7.h>
+#include <sys/types.h>
+#include <errno.h>
+
+#define Hz
+#define kHz *1000 Hz
+#define MHz *1000 kHz
+#define MCLK (48 MHz)
+
+/* find highest bit set. returns bit (32..1) or 0 in case no bit set */
+static int fhs(u_int32_t val)
+{
+ int i;
+
+ for (i = 32; i > 0; i--) {
+ if (val & (1 << (i-1)))
+ return i;
+ }
+
+ return 0;
+}
+
+/* set frequency of PWM signal to freq */
+int pwm_freq_set(int channel, u_int32_t freq)
+{
+ /* in order to get maximum resolution, the pre-scaler must be set to
+ * something like freq << 16. However, the mimimum pre-scaled frequency
+ * we can get is MCLK (48MHz), the minimum is MCLK/(1024*255) =
+ * 48MHz/261120 = 183Hz */
+ u_int32_t overall_div;
+ u_int32_t presc_total;
+ u_int32_t cpre = 0;
+ u_int8_t cprd;
+
+ if (freq > MCLK)
+ return -ERANGE;
+
+ overall_div = MCLK / freq;
+
+ if (overall_div > 0x7ffff) {
+ /* divisor is larger than half the maximum CPRD register, we
+ * have to configure prescalers */
+ presc_total = overall_div >> 15;
+
+ /* find highest 2^n fitting in prescaler (highest bit set) */
+ cpre = fhs(presc_total);
+ if (cpre > 0) {
+ /* subtract one, because of fhs semantics */
+ cpre--;
+ }
+ cprd = overall_div / (1 << cpre);
+ } else
+ cprd = overall_div;
+
+ AT91F_PWMC_CfgChannel(AT91C_BASE_PWMC, channel, cpre, 0, cprd);
+
+ return 0;
+}
+
+void pwm_start(int channel)
+{
+ AT91F_PWMC_StartChannel(AT91C_BASE_PWMC, (1 << channel));
+}
+
+void pwm_stop(int channel)
+{
+ AT91F_PWMC_StopChannel(AT91C_BASE_PWMC, (1 << channel));
+}
+
+void pwm_duty(int channel, u_int16_t duty)
+{
+ AT91F_PWMC_UpdateChannel(AT91C_BASE_PWMC, channel, duty);
+}
+
+void pwm_init(void)
+{
+ /* Set PA23 ti Peripheral B (PWM0) */
+ AT91F_PIO_CfgPeriph(AT91C_BASE_PIOA, 0, AT91C_PA23_PWM0);
+
+ /* Enable Clock for PWM controller */
+ AT91F_PWMC_CfgPMC();
+}
+
+void pwm_fini(void)
+{
+ AT91F_PMC_DisablePeriphClock(AT91C_BASE_PMC, (1 << AT91C_ID_PWMC));
+}
diff --git a/openpcd/firmware/src/pwm.h b/openpcd/firmware/src/pwm.h
new file mode 100644
index 0000000..c41d74a
--- /dev/null
+++ b/openpcd/firmware/src/pwm.h
@@ -0,0 +1,11 @@
+#ifndef _PWM_H
+#define _PWM_H
+
+extern void pwm_freq_set(int channel, u_int32_t freq);
+extern void pwm_start(int channel);
+extern void pwm_stop(int channel);
+extern void pwm_duty(int channel, u_int16_t duty);
+extern void pwm_init(void);
+extern void pwm_fini(void);
+
+#endif
personal git repositories of Harald Welte. Your mileage may vary