diff --git a/boards/arduino-due/Makefile.features b/boards/arduino-due/Makefile.features index 6e911845de..336368630c 100644 --- a/boards/arduino-due/Makefile.features +++ b/boards/arduino-due/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_pwm diff --git a/boards/arduino-due/include/arduino_pinmap.h b/boards/arduino-due/include/arduino_pinmap.h index 821fc8c218..4b2197919f 100644 --- a/boards/arduino-due/include/arduino_pinmap.h +++ b/boards/arduino-due/include/arduino_pinmap.h @@ -132,6 +132,14 @@ extern "C" { #define ARDUINO_A11 ADC_LINE(13) /** @} */ +/** + * @name Mapping of Arduino DAC pins to RIOT DAC lines + * @{ + */ +#define ARDUINO_DAC0 DAC_LINE(0) +#define ARDUINO_DAC1 DAC_LINE(1) +/** @} */ + #ifdef __cplusplus } #endif diff --git a/cpu/sam3/include/periph_cpu.h b/cpu/sam3/include/periph_cpu.h index 117e772d38..f8553ac08f 100644 --- a/cpu/sam3/include/periph_cpu.h +++ b/cpu/sam3/include/periph_cpu.h @@ -89,6 +89,19 @@ typedef uint32_t gpio_t; */ #define ADC_NUMOF (16U) +/** + * @brief DAC configuration, valid for all boards using this CPU + * + * The sam3 has a fixed mapping of DAC pins and a fixed number of DAC channels, + * so this DAC configuration is valid for all boards using this CPU. No need for + * any board specific configuration. + * + * The sam3's DAC channels are mapped to the following fixed pins: + * - line 0 (ch0): PB15 + * - line 1 (ch1): PB16 + */ +#define DAC_NUMOF (2U) + #ifndef DOXYGEN /** * @brief Override GPIO modes diff --git a/cpu/sam3/periph/dac.c b/cpu/sam3/periph/dac.c new file mode 100644 index 0000000000..98074a4e99 --- /dev/null +++ b/cpu/sam3/periph/dac.c @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2017 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_sam3 + * @{ + * + * @file + * @brief Low-level DAC driver implementation + * + * @author Hauke Petersen + * + * @} + */ + +#include "cpu.h" +#include "assert.h" +#include "periph/dac.h" + +#define WP_KEY (0x444143) +#define PMC_BIT (1 << (ID_DACC - 32)) + +#ifndef DAC_STARTUP +#define DAC_STARTUP (DACC_MR_STARTUP_1984) +#endif +#ifndef DAC_REFRESH +#define DAC_REFRESH (DACC_MR_REFRESH(128)) +#endif + +int8_t dac_init(dac_t line) +{ + assert(line < DAC_NUMOF); + + /* power on DACC peripheral */ + PMC->PMC_PCER1 = PMC_BIT; + + /* unlock DACC registers */ + DACC->DACC_WPMR = DACC_WPMR_WPKEY(WP_KEY); + /* configure mode register */ + DACC->DACC_MR = (DAC_STARTUP | DACC_MR_TAG_EN | DAC_REFRESH); + /* enable the selected channel/line */ + DACC->DACC_CHER = (1 << line); + /* set line initially to 0 volts -> this will startup the channel and the + * channel is ready after the defined number of startup cycles + * (DAC_STARTUP) have passed */ + dac_set(line, 0); + + return 0; +} + +void dac_set(dac_t line, uint16_t value) +{ + assert(line < DAC_NUMOF); + + DACC->DACC_CDR = ((value >> 4) | (line << 12)); +} + +void dac_poweron(dac_t line) +{ + assert(line < DAC_NUMOF); + + PMC->PMC_PCER1 = (1 << (ID_DACC - 32)); + DACC->DACC_CHER = PMC_BIT; +} + +void dac_poweroff(dac_t line) +{ + assert(line < DAC_NUMOF); + + DACC->DACC_CHDR = (1 << line); + if (!(DACC->DACC_CHSR)) { + PMC->PMC_PCDR1 = PMC_BIT; + } +}