diff options
| 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 | 
| commit | ada3d4fa86e6f178c8281f1cf7a5c55f8961accb (patch) | |
| tree | def3f0c4749c4018b436ec66601cb11ff620ab08 | |
| parent | 1bc8544204ae4a75ed8b4c76cee9fa3bd9d505d6 (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/Makefile | 2 | ||||
| -rw-r--r-- | openpcd/firmware/src/pwm.c | 94 | ||||
| -rw-r--r-- | openpcd/firmware/src/pwm.h | 11 | 
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 | 
