1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2025-01-18 12:52:44 +01:00
RIOT/cpu/stm32/periph/dac.c
Joshua DeWeese 11344241b8 cpu/stm32/periph/dac: optimize setting DAC
The current implmentation right shifted the 16 bit value passed into
`dac_set()` down to the 12 bits that the DAC is actually capable of.
This patch drops the shift and instead writes the 16 bit value to the
DAC's left aligned 12 bit wide data holding register.
2023-05-01 16:17:25 -04:00

121 lines
2.6 KiB
C

/*
* Copyright (C) 2014 Simon Brummer
* 2015-2016 Freie Universität Berlin
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @ingroup cpu_stm32
* @ingroup drivers_periph_dac
* @{
*
* @file
* @brief Low-level DAC driver implementation
*
* @author Simon Brummer <simon.brummer@haw-hamburg.de>
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
*
* @}
*/
#include "cpu.h"
#include "assert.h"
#include "periph/dac.h"
/* DAC channel enable bits */
#ifdef DAC_CR_EN2
#define EN_MASK (DAC_CR_EN1 | DAC_CR_EN2)
#else
#define EN_MASK (DAC_CR_EN1)
#endif
/* get RCC bit */
#ifdef RCC_APB1ENR_DAC1EN
#define RCC_BIT (RCC_APB1ENR_DAC1EN)
#else
#define RCC_BIT (RCC_APB1ENR_DACEN)
#endif
/* deduct DAC device from given line channel */
static inline DAC_TypeDef *dev(dac_t line)
{
#if defined(DAC2)
return (dac_config[line].chan > 1) ? DAC2 : DAC1;
#elif defined (DAC1)
(void) line;
return DAC1;
#else
(void) line;
return DAC;
#endif
}
int8_t dac_init(dac_t line)
{
if (line >= DAC_NUMOF) {
return DAC_NOLINE;
}
/* configure pin */
gpio_init_analog(dac_config[line].pin);
/* reset output and enable the line's channel */
dac_poweron(line);
dac_set(line, 0);
return DAC_OK;
}
void dac_set(dac_t line, uint16_t value)
{
assert(line < DAC_NUMOF);
#ifdef DAC_DHR12L2_DACC2DHR
if (dac_config[line].chan & 0x01) {
dev(line)->DHR12L2 = value;
}
else {
dev(line)->DHR12L1 = value;
}
#else
dev(line)->DHR12L1 = value;
#endif
}
void dac_poweron(dac_t line)
{
assert(line < DAC_NUMOF);
/* enable the DAC's clock */
#if defined(DAC2)
periph_clk_en(APB1, (dac_config[line].chan > 1) ?
RCC_APB1ENR_DAC2EN : RCC_APB1ENR_DAC1EN);
#else
periph_clk_en(APB1, RCC_BIT);
#endif
/* enable corresponding DAC channel */
dev(line)->CR |= (1 << (16 * (dac_config[line].chan & 0x01)));
}
void dac_poweroff(dac_t line)
{
assert(line < DAC_NUMOF);
/* disable corresponding channel */
dev(line)->CR &= ~(1 << (16 * (dac_config[line].chan & 0x01)));
/* disable the DAC's clock in case no channel is active anymore */
if (!(dev(line)->CR & EN_MASK)) {
#if defined(DAC2)
periph_clk_dis(APB1, (dac_config[line].chan > 1) ?
RCC_APB1ENR_DAC2EN : RCC_APB1ENR_DAC1EN);
#else
periph_clk_dis(APB1, RCC_BIT);
#endif
}
}