diff options
Diffstat (limited to 'libmaple')
-rw-r--r-- | libmaple/dac.c | 89 | ||||
-rw-r--r-- | libmaple/dac.h | 121 |
2 files changed, 141 insertions, 69 deletions
diff --git a/libmaple/dac.c b/libmaple/dac.c index 63a96ac..54b555b 100644 --- a/libmaple/dac.c +++ b/libmaple/dac.c @@ -23,7 +23,6 @@ *****************************************************************************/ #include "libmaple.h" -#include "rcc.h" #include "gpio.h" #include "dac.h" @@ -31,35 +30,81 @@ * @brief DAC peripheral routines. */ -/* This numbering follows the registers (1-indexed) */ -#define DAC_CH1 1 -#define DAC_CH2 2 +dac_dev dac = { + .regs = DAC_BASE, +}; +const dac_dev *DAC = &dac; -DAC_Map *dac = (DAC_Map*)(DAC_BASE); - -/* Sets up the DAC peripheral */ -void dac_init(void) { +/** + * @brief Initialize the digital to analog converter + * @param flags Flags: + * DAC_CH1: Enable channel 1 + * DAC_CH2: Enable channel 2 + * @sideeffect May set PA4 or PA5 to INPUT_ANALOG + */ +void dac_init(uint32 flags) { /* First turn on the clock */ rcc_clk_enable(RCC_DAC); + rcc_reset_dev(RCC_DAC); - /* Then setup ANALOG mode on PA4 and PA5 */ - gpio_set_mode(GPIOA_BASE, 4, CNF_INPUT_ANALOG); - gpio_set_mode(GPIOA_BASE, 5, CNF_INPUT_ANALOG); + if (flags & DAC_CH1) { + dac_enable_channel(1); + } - /* Then do register stuff. Default does no triggering, and - * buffered output, so all good. */ - dac->CR = DAC_CR_EN1 | DAC_CR_EN2; + if (flags & DAC_CH2) { + dac_enable_channel(2); + } } -void dac_write(uint8 chan, uint16 val) { - switch(chan) { - case DAC_CH1: - dac->DHR12R1 = 0x0FFF & val; +/** + * @brief Write a 12-bit value to the DAC to output + * @param channel channel to select (1 or 2) + * @param val value to write + */ +void dac_write_channel(uint8 channel, uint16 val) { + switch(channel) { + case 1: + DAC->regs->DHR12R1 = DAC_DHR12R1_DACC1DHR & val; + break; + case 2: + DAC->regs->DHR12R2 = DAC_DHR12R2_DACC2DHR & val; + break; + } +} + +/** + * @brief Enable a DAC channel + * @param channel channel to enable, either 1 or 2 + * @sideeffect May change pin mode of PA4 or PA5 + */ +void dac_enable_channel(uint8 channel) { + /* + * Setup ANALOG mode on PA4 and PA5. This mapping is consistent across + * all STM32 chips with a DAC. See RM008 12.2. + */ + switch (channel) { + case 1: + gpio_set_mode(GPIOA_BASE, 4, GPIO_MODE_INPUT_ANALOG); + DAC->regs->CR |= DAC_CR_EN1; + break; + case 2: + gpio_set_mode(GPIOA_BASE, 5, GPIO_MODE_INPUT_ANALOG); + DAC->regs->CR |= DAC_CR_EN2; + break; + } +} + +/** + * @brief Disable a DAC channel + * @param channel channel to disable, either 1 or 2 + */ +void dac_disable_channel(uint8 channel) { + switch (channel) { + case 1: + DAC->regs->CR &= ~DAC_CR_EN1; break; - case DAC_CH2: - dac->DHR12R2 = 0x0FFF & val; + case 2: + DAC->regs->CR &= ~DAC_CR_EN2; break; - default: - ASSERT(0); // can't happen } } diff --git a/libmaple/dac.h b/libmaple/dac.h index 340a49a..3148809 100644 --- a/libmaple/dac.h +++ b/libmaple/dac.h @@ -22,88 +22,115 @@ * THE SOFTWARE. *****************************************************************************/ -/* - * See ../notes/dac.txt for more info - */ - /** * @file dac.h + * @brief Digital to analog converter header file + * See notes/dac.txt for more info */ #ifndef _DAC_H_ #define _DAC_H_ +#include "rcc.h" + #ifdef __cplusplus extern "C"{ #endif -#define DAC_BASE 0x40007400 - -typedef struct { - volatile uint32 CR; - volatile uint32 SWTRIGR; - volatile uint32 DHR12R1; - volatile uint32 DHR12L1; - volatile uint32 DHR8R1; - volatile uint32 DHR12R2; - volatile uint32 DHR12L2; - volatile uint32 DHR8R2; - volatile uint32 DHR12RD; - volatile uint32 DHR12LD; - volatile uint32 DHR8RD; - volatile uint32 DOR1; - volatile uint32 DOR2; -} DAC_Map; - -/* There's only one DAC, so expose it. */ -extern DAC_Map *dac; - -// And here are the register bit ranges -#define DAC_CR_EN1 BIT(0) -#define DAC_CR_BOFF1 BIT(1) -#define DAC_CR_TEN1 BIT(2) -#define DAC_CR_TSEL1 (BIT(3) | BIT(4) | BIT(5)) -#define DAC_CR_WAVE1 (BIT(6) | BIT(7)) -#define DAC_CR_MAMP1 (BIT(8) | BIT(9) | BIT(10) | BIT(11)) -#define DAC_CR_DMAEN1 BIT(12) -#define DAC_CR_EN2 BIT(16) -#define DAC_CR_BOFF2 BIT(17) -#define DAC_CR_TEN2 BIT(18) -#define DAC_CR_TSEL2 (BIT(19) | BIT(20) | BIT(21)) -#define DAC_CR_WAVE2 (BIT(22) | BIT(23)) -#define DAC_CR_MAMP2 (BIT(24) | BIT(25) | BIT(26) | BIT(27)) -#define DAC_CR_DMAEN2 BIT(28) - -#define DAC_SWTRIGR_SWTRIG1 BIT(0) -#define DAC_SWTRIGR_SWTRIG2 BIT(1) +typedef struct dac_reg_map { + __io uint32 CR; ///< Control register + __io uint32 SWTRIGR; ///< Software trigger register + __io uint32 DHR12R1; ///< Channel 1 12-bit right aligned data holding register + __io uint32 DHR12L1; ///< Channel 1 12-bit left aligned data holding register + __io uint32 DHR8R1; ///< Channel 1 8-bit left aligned data holding register + __io uint32 DHR12R2; ///< Channel 2 12-bit right aligned data holding register + __io uint32 DHR12L2; ///< Channel 2 12-bit left aligned data holding register + __io uint32 DHR8R2; ///< Channel 2 8-bit left aligned data holding register + __io uint32 DHR12RD; ///< Dual DAC 12-bit right aligned data holding register + __io uint32 DHR12LD; ///< Dual DAC 12-bit left aligned data holding register + __io uint32 DHR8RD; ///< Dual DAC 8-bit left aligned data holding register + __io uint32 DOR1; ///< Channel 1 data output register + __io uint32 DOR2; ///< Channel 2 data output register +} dac_reg_map; + +typedef struct dac_dev { + dac_reg_map *regs; +} dac_dev; + +extern const dac_dev *DAC; +/* + * DAC peripheral base address + */ +#define DAC_BASE ((dac_reg_map*)0x40007400) + +/* + * Register bit definitions and masks + */ + +/* Control register */ +#define DAC_CR_EN1 BIT(0) // Channel 1 enable +#define DAC_CR_BOFF1 BIT(1) // Channel 1 output buffer disable +#define DAC_CR_TEN1 BIT(2) // Channel 1 trigger enable +#define DAC_CR_TSEL1 (0x7 << 3) // Channel 1 trigger selection +#define DAC_CR_WAVE1 (0x3 << 6) // Channel 1 noise/triangle wave generationg enable +#define DAC_CR_MAMP1 (0xF << 8) // Channel 1 mask/amplitude selector +#define DAC_CR_DMAEN1 BIT(12) // Channel 1 DMA enable +#define DAC_CR_EN2 BIT(16) // Channel 2 enable +#define DAC_CR_BOFF2 BIT(17) // Channel 2 output buffer disable +#define DAC_CR_TEN2 BIT(18) // Channel 2 trigger enable +#define DAC_CR_TSEL2 (0x7 << 19) // Channel 2 trigger selection +#define DAC_CR_WAVE2 (0x3 << 22) // Channel 2 noise/triangle wave generationg enable +#define DAC_CR_MAMP2 (0xF << 24) // Channel 2 mask/amplitude selector +#define DAC_CR_DMAEN2 BIT(28) // Channel 2 DMA enable + +/* Software trigger register */ +#define DAC_SWTRIGR_SWTRIG1 BIT(0) // Channel 1 software trigger +#define DAC_SWTRIGR_SWTRIG2 BIT(1) // Channel 2 software trigger + +/* Channel 1 12-bit right aligned data holding register */ #define DAC_DHR12R1_DACC1DHR 0x00000FFF +/* Channel 1 12-bit left aligned data holding register */ #define DAC_DHR12L1_DACC1DHR 0x0000FFF0 +/* Channel 1 8-bit left aligned data holding register */ #define DAC_DHR8R1_DACC1DHR 0x000000FF +/* Channel 2 12-bit right aligned data holding register */ #define DAC_DHR12R2_DACC2DHR 0x00000FFF +/* Channel 2 12-bit left aligned data holding register */ #define DAC_DHR12L2_DACC2DHR 0x0000FFF0 +/* Channel 2 8-bit left aligned data holding register */ #define DAC_DHR8R2_DACC2DHR 0x000000FF +/* Dual DAC 12-bit right aligned data holding register */ #define DAC_DHR12RD_DACC1DHR 0x00000FFF #define DAC_DHR12RD_DACC2DHR 0x0FFF0000 +/* Dual DAC 12-bit left aligned data holding register */ #define DAC_DHR12LD_DACC1DHR 0x0000FFF0 #define DAC_DHR12LD_DACC2DHR 0xFFF00000 +/* Dual DAC 8-bit left aligned data holding register */ #define DAC_DHR8RD_DACC1DHR 0x000000FF #define DAC_DHR8RD_DACC2DHR 0x0000FF00 -#define DAC_DOR1 0x00000FFF +/* Channel 1 data output register */ +#define DAC_DOR1_DACC1DOR 0x00000FFF + +/* Channel 1 data output register */ +#define DAC_DOR2_DACC2DOR 0x00000FFF -#define DAC_DOR2 0x00000FFF +#define DAC_CH1 0x1 +#define DAC_CH2 0x2 +void dac_init(uint32 flags); -void dac_init(void); -void dac_write(uint8 chan, uint16 val); +void dac_write_channel(uint8 channel, uint16 val); +void dac_enable_channel(uint8 channel); +void dac_disable_channel(uint8 channel); #ifdef __cplusplus } // extern "C" |