diff --git a/boards/frdm-k64f/include/periph_conf.h b/boards/frdm-k64f/include/periph_conf.h index 95404a8359..c93ebd5a33 100644 --- a/boards/frdm-k64f/include/periph_conf.h +++ b/boards/frdm-k64f/include/periph_conf.h @@ -117,9 +117,17 @@ static const adc_conf_t adc_config[] = { /** @} */ /** -* @name PWM configuration -* @{ -*/ + * @name DAC configuration + * @{ + */ +#define DAC_CONFIG {} +#define DAC_NUMOF 0 +/** @} */ + +/** + * @name PWM configuration + * @{ + */ #define PWM_NUMOF (1U) #define PWM_0_EN 1 #define PWM_MAX_CHANNELS 8 diff --git a/boards/mulle/Makefile.features b/boards/mulle/Makefile.features index b02397ab89..9b5794461b 100644 --- a/boards/mulle/Makefile.features +++ b/boards/mulle/Makefile.features @@ -1,6 +1,7 @@ # Put defined MCU peripherals here (in alphabetical order) FEATURES_PROVIDED += periph_adc FEATURES_PROVIDED += periph_cpuid +FEATURES_PROVIDED += periph_dac FEATURES_PROVIDED += periph_gpio FEATURES_PROVIDED += periph_hwrng FEATURES_PROVIDED += periph_i2c diff --git a/boards/mulle/include/periph_conf.h b/boards/mulle/include/periph_conf.h index d0368fedd8..d14ebbfe27 100644 --- a/boards/mulle/include/periph_conf.h +++ b/boards/mulle/include/periph_conf.h @@ -135,7 +135,6 @@ extern "C" /** @} */ - /** * @name ADC configuration * @{ @@ -164,6 +163,18 @@ static const adc_conf_t adc_config[] = { #define ADC_NUMOF (sizeof(adc_config) / sizeof(adc_config[0])) /** @} */ +/** + * @name DAC configuration + * @{ + */ + +#define DAC_CONFIG { \ + { DAC0, (uint32_t volatile *)BITBAND_REGADDR(SIM->SCGC2, SIM_SCGC2_DAC0_SHIFT) }, \ + } +#define DAC_NUMOF 1 + +/** @} */ + /** * @name PWM configuration * @{ diff --git a/boards/pba-d-01-kw2x/include/periph_conf.h b/boards/pba-d-01-kw2x/include/periph_conf.h index 0419e2944f..14acd41c0e 100644 --- a/boards/pba-d-01-kw2x/include/periph_conf.h +++ b/boards/pba-d-01-kw2x/include/periph_conf.h @@ -133,6 +133,14 @@ static const adc_conf_t adc_config[] = { #define ADC_NUMOF (sizeof(adc_config) / sizeof(adc_config[0])) /** @} */ +/** + * @name DAC configuration + * @{ + */ +#define DAC_CONFIG {} +#define DAC_NUMOF 0 +/** @} */ + /** * @name PWM configuration * @{ diff --git a/cpu/kinetis_common/include/periph_cpu.h b/cpu/kinetis_common/include/periph_cpu.h index 9a872219fb..ff1f62417d 100644 --- a/cpu/kinetis_common/include/periph_cpu.h +++ b/cpu/kinetis_common/include/periph_cpu.h @@ -148,6 +148,16 @@ typedef struct { uint8_t chan; /**< ADC channel */ } adc_conf_t; +/** + * @brief CPU specific DAC configuration + */ +typedef struct { + /** DAC device base pointer */ + DAC_Type *dev; + /** Pointer to module clock gate bit in bitband region, use BITBAND_REGADDR() */ + uint32_t volatile *clk_gate; +} dac_conf_t; + /** * @brief CPU internal function for initializing PORTs * diff --git a/cpu/kinetis_common/periph/dac.c b/cpu/kinetis_common/periph/dac.c new file mode 100644 index 0000000000..cf3eaf4998 --- /dev/null +++ b/cpu/kinetis_common/periph/dac.c @@ -0,0 +1,98 @@ +/* + * Copyright (C) 2016 Eistec AB + * + * 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_kinetis_common_dac + * + * @{ + * + * @file + * @brief Low-level DAC driver implementation + * + * This driver uses the 12-bit in-CPU DAC module. The 6-bit digital-to-analog + * converter inside the CMP module is _not_ used by this implementation. + * + * @author Joakim NohlgÄrd + * + * @} + */ + +#include + +#include "cpu.h" +#include "periph/dac.h" +#include "periph_conf.h" + +static const dac_conf_t dac_config[] = DAC_CONFIG; + +int8_t dac_init(dac_t line) +{ + DAC_Type *dac; + if ((unsigned int)line >= DAC_NUMOF) { + return -1; + } + + dac = dac_config[line].dev; + + /* Enable module clock */ + *(dac_config[line].clk_gate) = 1; + + /* Select VDDA as voltage reference */ + dac->C0 = (DAC_C0_DACRFS_MASK); + + /* Disable DMA and buffering */ + dac->C1 = 0; + dac->C2 = 0; + + /* Power on */ + dac_poweron(line); + + /* Set output value to zero */ + dac_set(line, 0); + return 0; +} + +void dac_set(dac_t line, uint16_t value) +{ + DAC_Type *dac; + + if ((unsigned int)line >= DAC_NUMOF) { + return; + } + + dac = dac_config[line].dev; + + /* Scale to 12 bit */ + value = value >> ((sizeof(value) * 8) - 12); + + dac->DAT[0].DATH = ((value >> 8) & 0xff); + dac->DAT[0].DATL = (value & 0xff); +} + +static inline void _dac_set_power(dac_t line, uint8_t value) +{ + DAC_Type *dac; + + if ((unsigned int)line >= DAC_NUMOF) { + return; + } + + dac = dac_config[line].dev; + + BITBAND_REG8(dac->C0, DAC_C0_DACEN_SHIFT) = value; +} + +void dac_poweron(dac_t line) +{ + _dac_set_power(line, 1); +} + +void dac_poweroff(dac_t line) +{ + _dac_set_power(line, 0); +}