From 0f1f1ebd1a3e3f35aa559a463ae321d226f6fb75 Mon Sep 17 00:00:00 2001 From: Karl Palsson Date: Tue, 26 Jan 2021 22:31:06 +0000 Subject: [PATCH] stm32:dac: Fix waveform generation apis These were broken earlier, with no sane way of passing in correctly shifted values, and didn't match examples. Noticed while merging: https://github.com/libopencm3/libopencm3/pull/1281 --- .../libopencm3/stm32/common/dac_common_all.h | 15 +++-- lib/stm32/common/dac_common_all.c | 67 ++++++++++--------- 2 files changed, 44 insertions(+), 38 deletions(-) diff --git a/include/libopencm3/stm32/common/dac_common_all.h b/include/libopencm3/stm32/common/dac_common_all.h index 069d6a65..6508d899 100644 --- a/include/libopencm3/stm32/common/dac_common_all.h +++ b/include/libopencm3/stm32/common/dac_common_all.h @@ -103,9 +103,11 @@ specific memorymap.h header before including this header file.*/ /** MAMP2[3:0]: DAC channel2 mask/amplitude selector field position */ #define DAC_CR_MAMP2_SHIFT 24 -/** WAVE2[1:0]: DAC channel2 noise/triangle wave generation enable */ +/** Wave generation mode mask size */ +#define DAC_CR_WAVEx_MASK 0x3 + +/** WAVE2[1:0]: DAC channel2 wave generation mode*/ #define DAC_CR_WAVE2_SHIFT 22 -#define DAC_CR_WAVE2_MASK 0x3 /** EN2: DAC channel2 enable */ #define DAC_CR_EN2 (1 << 16) @@ -123,9 +125,8 @@ specific memorymap.h header before including this header file.*/ /** MAMP Mask/Amplitude selector field size */ #define DAC_CR_MAMPx_MASK 0xf -/** WAVEn[1:0]: DAC channel1 noise/triangle wave generation enable */ +/** WAVE1[1:0]: DAC channel1 wave generation mode */ #define DAC_CR_WAVE1_SHIFT 6 -#define DAC_CR_WAVE1_MASK 0x3 /** EN1: DAC channel1 enable */ #define DAC_CR_EN1 (1 << 0) @@ -238,7 +239,9 @@ enum dac_align { DAC_ALIGN_LEFT12, }; -/** DAC waveform generation options. */ +/** DAC waveform generation options. + * Not all wave shapes are available on all parts. + */ enum dac_wave { DAC_WAVE_DISABLE = 0, DAC_WAVE_NOISE = 1, @@ -257,7 +260,7 @@ void dac_dma_disable(uint32_t dac, int channel); void dac_trigger_enable(uint32_t dac, int channel); void dac_trigger_disable(uint32_t dac, int channel); void dac_set_trigger_source(uint32_t dac, uint32_t source); -void dac_set_waveform_generation(uint32_t dac, enum dac_wave wave); +void dac_set_waveform_generation(uint32_t dac, int channel, enum dac_wave wave); void dac_disable_waveform_generation(uint32_t dac, int channel); void dac_set_waveform_characteristics(uint32_t dac, int channel, int mamp); void dac_load_data_buffer_single(uint32_t dac, uint16_t data, diff --git a/lib/stm32/common/dac_common_all.c b/lib/stm32/common/dac_common_all.c index 6b88d10a..ba0d77ad 100644 --- a/lib/stm32/common/dac_common_all.c +++ b/lib/stm32/common/dac_common_all.c @@ -66,8 +66,8 @@ sent out. GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, GPIO4); rcc_periph_clock_enable(RCC_DAC); dac_disable(DAC1, DAC_CHANNEL1); - dac_set_waveform_characteristics(DAC1, DAC_CR_MAMP1_8); - dac_set_waveform_generation(DAC1, DAC_CR_WAVE1_NOISE); + dac_set_waveform_characteristics(DAC1, DAC_CHANNEL1, DAC_CR_MAMP1_8); + dac_set_waveform_generation(DAC1, DAC_CHANNEL1, DAC_CR_WAVE1_NOISE); dac_enable(DAC1, DAC_CHANNEL1); dac_set_trigger_source(DAC1, DAC_CR_TSEL1_SW); dac_load_data_buffer_single(DAC1, 0, DAC_ALIGN_RIGHT12, DAC_CHANNEL1); @@ -289,46 +289,49 @@ void dac_set_trigger_source(uint32_t dac, uint32_t source) DAC_CR(dac) |= source; } -/** @brief Enable and Set DAC Channel Waveform Generation. - -Enable the digital to analog converter waveform generation as either -pseudo-random noise or triangular wave. These signals are superimposed on -existing output values in the DAC output registers. - -@note The DAC trigger must be enabled for this to work. -@param[in] dac the base address of the DAC. @ref dac_reg_base -@param[in] wave enum ::dac_wave. Taken from @ref dac_wave1_en or @ref -dac_wave2_en or a logical OR of one of each of these to set both channels -simultaneously. -*/ -void dac_set_waveform_generation(uint32_t dac, enum dac_wave wave) +/** + * Set DAC Channel Waveform Generation mode for one or both channels. + * These signals are superimposed on existing output values in the + * DAC output registers. Waveform can be disabled, noise, triangular, + * or sawtooth, depending on family. + * @note The DAC trigger must be enabled for this to work. + * @param[in] dac the base address of the DAC. @ref dac_reg_base + * @param[in] channel one or both, @ref dac_channel_id + * @param[in] wave enum ::dac_wave. mode for channel + */ +void dac_set_waveform_generation(uint32_t dac, int channel, enum dac_wave wave) { - DAC_CR(dac) |= wave; -} - -/** @brief Disable DAC Channel Waveform Generation. - -Disable a digital to analog converter channel superimposed waveform generation. - -@param[in] dac the base address of the DAC. @ref dac_reg_base -@param[in] channel with DAC mask. @ref dac_channel_id -*/ -void dac_disable_waveform_generation(uint32_t dac, int channel) -{ - switch (channel) { + uint32_t reg = DAC_CR(dac); + switch(channel) { case DAC_CHANNEL1: - DAC_CR(dac) &= ~(DAC_CR_WAVE1_MASK << DAC_CR_WAVE1_SHIFT); + reg &= ~(DAC_CR_WAVEx_MASK << DAC_CR_WAVE1_SHIFT); + reg |= wave << DAC_CR_WAVE1_SHIFT; break; case DAC_CHANNEL2: - DAC_CR(dac) &= ~(DAC_CR_WAVE2_MASK << DAC_CR_WAVE2_SHIFT); + reg &= ~(DAC_CR_WAVEx_MASK << DAC_CR_WAVE2_SHIFT); + reg |= wave << DAC_CR_WAVE2_SHIFT; break; case DAC_CHANNEL_BOTH: - DAC_CR(dac) &= ~(DAC_CR_WAVE1_MASK << DAC_CR_WAVE1_SHIFT) - | ~(DAC_CR_WAVE2_MASK << DAC_CR_WAVE2_SHIFT); + reg &= ~(DAC_CR_WAVEx_MASK << DAC_CR_WAVE1_SHIFT) + | ~(DAC_CR_WAVEx_MASK << DAC_CR_WAVE2_SHIFT); + reg |= wave << DAC_CR_WAVE1_SHIFT; + reg |= wave << DAC_CR_WAVE2_SHIFT; break; default: break; } + DAC_CR(dac) = reg; +} + +/** + * Disable DAC Channel Waveform Generation. + * @note this is equivalent to @ref dac_set_waveform_generation (dac, channel, DAC_WAVE_DISABLE) + * @param[in] dac the base address of the DAC. @ref dac_reg_base + * @param[in] channel with DAC mask. @ref dac_channel_id + */ +void dac_disable_waveform_generation(uint32_t dac, int channel) +{ + dac_set_waveform_generation(dac, channel, DAC_WAVE_DISABLE); } /** @brief Set DAC Channel LFSR Mask or Triangle Wave Amplitude.