mirror of https://github.com/ARMmbed/mbed-os.git
* updated systeminit checking for analoguein apis.
* updated with tested code for analogueout apis. * updated objects for analaguein and analaogueout.pull/1316/head
parent
ecfc96f57c
commit
013b71a56f
|
@ -44,7 +44,9 @@ typedef enum {
|
||||||
UART_5 = (int)0x42001C00UL // Base address of SERCOM5
|
UART_5 = (int)0x42001C00UL // Base address of SERCOM5
|
||||||
} UARTName;
|
} UARTName;
|
||||||
|
|
||||||
typedef enum { // for each input control mux 4,5,6,7,16,17,10,11 used in R21
|
typedef enum {
|
||||||
|
ADC_0 = 0x0ul,
|
||||||
|
ADC_1 = 0x1ul,
|
||||||
ADC_2 = 0x2ul,
|
ADC_2 = 0x2ul,
|
||||||
ADC_3 = 0x3ul,
|
ADC_3 = 0x3ul,
|
||||||
ADC_4 = 0x4ul,
|
ADC_4 = 0x4ul,
|
||||||
|
@ -52,14 +54,23 @@ typedef enum { // for each input control mux 4,5,6,7,16,17,10,11 used in R21
|
||||||
ADC_6 = 0x6ul,
|
ADC_6 = 0x6ul,
|
||||||
ADC_7 = 0x7ul,
|
ADC_7 = 0x7ul,
|
||||||
ADC_8 = 0x8ul,
|
ADC_8 = 0x8ul,
|
||||||
|
ADC_9 = 0x8ul,
|
||||||
ADC_10 = 0xAul,
|
ADC_10 = 0xAul,
|
||||||
ADC_11 = 0xBul,
|
ADC_11 = 0xBul,
|
||||||
|
ADC_12 = 0xCul,
|
||||||
|
ADC_13 = 0xDul,
|
||||||
|
ADC_14 = 0xEul,
|
||||||
|
ADC_15 = 0xFul,
|
||||||
ADC_16 = 0x10ul,
|
ADC_16 = 0x10ul,
|
||||||
ADC_17 = 0x11ul,
|
ADC_17 = 0x11ul,
|
||||||
ADC_18 = 0x12ul,
|
ADC_18 = 0x12ul,
|
||||||
ADC_19 = 0x13ul
|
ADC_19 = 0x13ul
|
||||||
} ADCName;
|
} ADCName;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
DAC_0 = 0x42004800UL
|
||||||
|
} DACName;
|
||||||
|
|
||||||
typedef enum { // for each channel
|
typedef enum { // for each channel
|
||||||
EXTINT_0 = 0,
|
EXTINT_0 = 0,
|
||||||
EXTINT_1,
|
EXTINT_1,
|
||||||
|
|
|
@ -18,6 +18,8 @@
|
||||||
|
|
||||||
/************ADC***************/
|
/************ADC***************/
|
||||||
const PinMap PinMap_ADC[] = {
|
const PinMap PinMap_ADC[] = {
|
||||||
|
{PA02, ADC_0, 1},
|
||||||
|
{PA03, ADC_1, 1},
|
||||||
{PB08, ADC_2, 1},
|
{PB08, ADC_2, 1},
|
||||||
{PB09, ADC_3, 1},
|
{PB09, ADC_3, 1},
|
||||||
{PA04, ADC_4, 1},
|
{PA04, ADC_4, 1},
|
||||||
|
@ -25,8 +27,13 @@ const PinMap PinMap_ADC[] = {
|
||||||
{PA06, ADC_6, 1},
|
{PA06, ADC_6, 1},
|
||||||
{PA07, ADC_7, 1},
|
{PA07, ADC_7, 1},
|
||||||
{PB00, ADC_8, 1},
|
{PB00, ADC_8, 1},
|
||||||
|
{PB01, ADC_9, 1},
|
||||||
{PB02, ADC_10, 1},
|
{PB02, ADC_10, 1},
|
||||||
{PB03, ADC_11, 1},
|
{PB03, ADC_11, 1},
|
||||||
|
{PB04, ADC_12, 1},
|
||||||
|
{PB05, ADC_13, 1},
|
||||||
|
{PB06, ADC_14, 1},
|
||||||
|
{PB07, ADC_15, 1},
|
||||||
{PA08, ADC_16, 1},
|
{PA08, ADC_16, 1},
|
||||||
{PA09, ADC_17, 1},
|
{PA09, ADC_17, 1},
|
||||||
{PA10, ADC_18, 1},
|
{PA10, ADC_18, 1},
|
||||||
|
@ -36,6 +43,14 @@ const PinMap PinMap_ADC[] = {
|
||||||
{NC , NC , NC}
|
{NC , NC , NC}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/************DAC***************/
|
||||||
|
const PinMap PinMap_DAC[] = {
|
||||||
|
{PA02, DAC_0, 1},
|
||||||
|
|
||||||
|
/* Not connected */
|
||||||
|
{NC , NC , NC}
|
||||||
|
};
|
||||||
|
|
||||||
/************SERCOM Pins***********/
|
/************SERCOM Pins***********/
|
||||||
const PinMap PinMap_SERCOM_PAD[] = {
|
const PinMap PinMap_SERCOM_PAD[] = {
|
||||||
{PA00, SERCOM1_PAD0, 3},
|
{PA00, SERCOM1_PAD0, 3},
|
||||||
|
|
|
@ -23,7 +23,10 @@
|
||||||
/************ADC***************/
|
/************ADC***************/
|
||||||
extern const PinMap PinMap_ADC[];
|
extern const PinMap PinMap_ADC[];
|
||||||
|
|
||||||
//*********SERCOM*************/
|
/************DAC***************/
|
||||||
|
extern const PinMap PinMap_DAC[];
|
||||||
|
|
||||||
|
/*********SERCOM*************/
|
||||||
extern const PinMap PinMap_SERCOM_PAD[];
|
extern const PinMap PinMap_SERCOM_PAD[];
|
||||||
extern const PinMap PinMap_SERCOM_PADEx[];
|
extern const PinMap PinMap_SERCOM_PADEx[];
|
||||||
|
|
||||||
|
|
|
@ -19,36 +19,89 @@
|
||||||
#include "cmsis.h"
|
#include "cmsis.h"
|
||||||
#include "pinmap.h"
|
#include "pinmap.h"
|
||||||
#include "PeripheralPins.h"
|
#include "PeripheralPins.h"
|
||||||
|
#include "dac.h"
|
||||||
|
|
||||||
|
struct dac_module dac_instance;
|
||||||
|
extern uint8_t g_sys_init;
|
||||||
|
|
||||||
|
#define MAX_VAL_10BIT 0x03FF
|
||||||
|
|
||||||
void analogout_init(dac_t *obj, PinName pin)
|
void analogout_init(dac_t *obj, PinName pin)
|
||||||
{
|
{
|
||||||
|
MBED_ASSERT(obj);
|
||||||
|
if (g_sys_init == 0) {
|
||||||
|
system_init();
|
||||||
|
g_sys_init = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void analogout_free(dac_t *obj) {}
|
struct dac_chan_config config_dac_chan;
|
||||||
|
uint32_t pos_input = 0;
|
||||||
|
pos_input = pinmap_find_peripheral(pin, PinMap_DAC);
|
||||||
|
MBED_ASSERT(pos_input != NC);
|
||||||
|
|
||||||
static inline void dac_write(dac_t *obj, int value)
|
obj->dac = DAC_0;
|
||||||
{
|
|
||||||
|
dac_get_config_defaults(&(obj->config_dac));
|
||||||
|
dac_init(&dac_instance, DAC, &(obj->config_dac));
|
||||||
|
|
||||||
|
dac_chan_get_config_defaults(&config_dac_chan);
|
||||||
|
dac_chan_set_config(&dac_instance, DAC_CHANNEL_0, &config_dac_chan);
|
||||||
|
dac_chan_enable(&dac_instance, DAC_CHANNEL_0);
|
||||||
|
|
||||||
|
dac_enable(&dac_instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int dac_read(dac_t *obj)
|
void analogout_free(dac_t *obj)
|
||||||
{
|
{
|
||||||
return 0;
|
MBED_ASSERT(obj);
|
||||||
|
struct system_pinmux_config pin_conf;
|
||||||
|
|
||||||
|
dac_disable(&dac_instance);
|
||||||
|
pin_conf.direction = SYSTEM_PINMUX_PIN_DIR_INPUT;
|
||||||
|
pin_conf.input_pull = SYSTEM_PINMUX_PIN_PULL_UP;
|
||||||
|
pin_conf.powersave = false;
|
||||||
|
pin_conf.mux_position = SYSTEM_PINMUX_GPIO;
|
||||||
|
system_pinmux_pin_set_config(PA02, &pin_conf); /*PA04 is the only DAC pin available*/
|
||||||
}
|
}
|
||||||
|
|
||||||
void analogout_write(dac_t *obj, float value)
|
void analogout_write(dac_t *obj, float value)
|
||||||
{
|
{
|
||||||
|
MBED_ASSERT(obj);
|
||||||
|
uint32_t count_val = 0;
|
||||||
|
if (value < 0.0) {
|
||||||
|
count_val = 0;
|
||||||
|
} else if (value > 1.0) {
|
||||||
|
count_val = (uint32_t)MAX_VAL_10BIT;
|
||||||
|
} else {
|
||||||
|
count_val = (uint32_t) (value * (float)MAX_VAL_10BIT);
|
||||||
|
}
|
||||||
|
dac_chan_write(&dac_instance, DAC_CHANNEL_0, (uint16_t)count_val);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void analogout_write_u16(dac_t *obj, uint16_t value)
|
void analogout_write_u16(dac_t *obj, uint16_t value)
|
||||||
{
|
{
|
||||||
|
MBED_ASSERT(obj);
|
||||||
|
uint32_t count_val;
|
||||||
|
count_val = (uint32_t)((value * (float)MAX_VAL_10BIT) / 0xFFFF); /*Normalization to the value 0xFFFF*/
|
||||||
|
dac_chan_write(&dac_instance, DAC_CHANNEL_0, (uint16_t)count_val);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
float analogout_read(dac_t *obj)
|
float analogout_read(dac_t *obj)
|
||||||
{
|
{
|
||||||
return 0.0;
|
MBED_ASSERT(obj);
|
||||||
|
uint32_t data_val = 0;
|
||||||
|
Dac *const dac_module = (uint32_t)obj->dac;
|
||||||
|
data_val = dac_module->DATA.reg;
|
||||||
|
return data_val/(float)MAX_VAL_10BIT;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t analogout_read_u16(dac_t *obj)
|
uint16_t analogout_read_u16(dac_t *obj)
|
||||||
{
|
{
|
||||||
return 0;
|
MBED_ASSERT(obj);
|
||||||
|
uint32_t data_val = 0;
|
||||||
|
Dac *const dac_module = (uint32_t)obj->dac;
|
||||||
|
data_val = dac_module->DATA.reg;
|
||||||
|
return (uint16_t)((data_val /MAX_VAL_10BIT) * 0xFFFF); /*Normalization to the value 0xFFFF*/
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,207 @@
|
||||||
|
/**
|
||||||
|
* \file
|
||||||
|
*
|
||||||
|
* \brief SAM Peripheral Digital-to-Analog Converter Driver
|
||||||
|
*
|
||||||
|
* Copyright (C) 2012-2015 Atmel Corporation. All rights reserved.
|
||||||
|
*
|
||||||
|
* \asf_license_start
|
||||||
|
*
|
||||||
|
* \page License
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* 3. The name of Atmel may not be used to endorse or promote products derived
|
||||||
|
* from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* 4. This software may only be redistributed and used in connection with an
|
||||||
|
* Atmel microcontroller product.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||||
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||||
|
* EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
|
||||||
|
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||||
|
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||||
|
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* \asf_license_stop
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
|
||||||
|
*/
|
||||||
|
#ifndef DAC_H_INCLUDED
|
||||||
|
#define DAC_H_INCLUDED
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <compiler.h>
|
||||||
|
#include <clock.h>
|
||||||
|
#include <gclk.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \addtogroup asfdoc_sam0_dac_group
|
||||||
|
*
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Define DAC features set according to different device families.
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
#if (SAMD21 || SAMD10 || SAMD11 || SAMDA1)
|
||||||
|
# define FEATURE_DAC_DATABUF_WRITE_PROTECTION
|
||||||
|
#endif
|
||||||
|
/**@}*/
|
||||||
|
|
||||||
|
#ifndef DAC_TIMEOUT
|
||||||
|
# define DAC_TIMEOUT 0xFFFF
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if DAC_CALLBACK_MODE == true
|
||||||
|
# include <system_interrupt.h>
|
||||||
|
|
||||||
|
/** Forward definition of the device instance. */
|
||||||
|
struct dac_module;
|
||||||
|
|
||||||
|
#if !defined(__DOXYGEN__)
|
||||||
|
extern struct dac_module *_dac_instances[DAC_INST_NUM];
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/** Type definition for a DAC module callback function. */
|
||||||
|
typedef void (*dac_callback_t)(uint8_t channel);
|
||||||
|
|
||||||
|
/** Enum for the possible callback types for the DAC module. */
|
||||||
|
enum dac_callback {
|
||||||
|
/** Callback type for when a DAC channel data empty condition occurs
|
||||||
|
* (requires event triggered mode) */
|
||||||
|
DAC_CALLBACK_DATA_EMPTY,
|
||||||
|
|
||||||
|
/** Callback type for when a DAC channel data underrun condition occurs
|
||||||
|
* (requires event triggered mode) */
|
||||||
|
DAC_CALLBACK_DATA_UNDERRUN,
|
||||||
|
|
||||||
|
/** Callback type for when a DAC channel write buffer job complete (requires
|
||||||
|
* event triggered mode) */
|
||||||
|
DAC_CALLBACK_TRANSFER_COMPLETE,
|
||||||
|
#if !defined(__DOXYGEN__)
|
||||||
|
DAC_CALLBACK_N,
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <dac_feature.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \name Configuration and Initialization
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
bool dac_is_syncing(
|
||||||
|
struct dac_module *const dev_inst);
|
||||||
|
|
||||||
|
void dac_get_config_defaults(
|
||||||
|
struct dac_config *const config);
|
||||||
|
|
||||||
|
enum status_code dac_init(
|
||||||
|
struct dac_module *const dev_inst,
|
||||||
|
Dac *const module,
|
||||||
|
struct dac_config *const config);
|
||||||
|
|
||||||
|
void dac_reset(
|
||||||
|
struct dac_module *const dev_inst);
|
||||||
|
|
||||||
|
void dac_enable(
|
||||||
|
struct dac_module *const dev_inst);
|
||||||
|
|
||||||
|
void dac_disable(
|
||||||
|
struct dac_module *const dev_inst);
|
||||||
|
|
||||||
|
void dac_enable_events(
|
||||||
|
struct dac_module *const module_inst,
|
||||||
|
struct dac_events *const events);
|
||||||
|
|
||||||
|
void dac_disable_events(
|
||||||
|
struct dac_module *const module_inst,
|
||||||
|
struct dac_events *const events);
|
||||||
|
|
||||||
|
/** @} */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \name Configuration and Initialization (Channel)
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
void dac_chan_get_config_defaults(
|
||||||
|
struct dac_chan_config *const config);
|
||||||
|
|
||||||
|
void dac_chan_set_config(
|
||||||
|
struct dac_module *const dev_inst,
|
||||||
|
const enum dac_channel channel,
|
||||||
|
struct dac_chan_config *const config);
|
||||||
|
|
||||||
|
void dac_chan_enable(
|
||||||
|
struct dac_module *const dev_inst,
|
||||||
|
enum dac_channel channel);
|
||||||
|
|
||||||
|
void dac_chan_disable(
|
||||||
|
struct dac_module *const dev_inst,
|
||||||
|
enum dac_channel channel);
|
||||||
|
|
||||||
|
/** @} */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \name Channel Data Management
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
enum status_code dac_chan_write(
|
||||||
|
struct dac_module *const dev_inst,
|
||||||
|
enum dac_channel channel,
|
||||||
|
const uint16_t data);
|
||||||
|
|
||||||
|
enum status_code dac_chan_write_buffer_wait(
|
||||||
|
struct dac_module *const module_inst,
|
||||||
|
enum dac_channel channel,
|
||||||
|
uint16_t *buffer,
|
||||||
|
uint32_t length);
|
||||||
|
|
||||||
|
/** @} */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \name Status Management
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
uint32_t dac_get_status(
|
||||||
|
struct dac_module *const module_inst);
|
||||||
|
void dac_clear_status(
|
||||||
|
struct dac_module *const module_inst,
|
||||||
|
uint32_t status_flags);
|
||||||
|
|
||||||
|
/** @} */
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/** @} */
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* DAC_H_INCLUDED */
|
|
@ -0,0 +1,774 @@
|
||||||
|
/**
|
||||||
|
* \file
|
||||||
|
*
|
||||||
|
* \brief SAM Peripheral Digital-to-Analog Converter Driver
|
||||||
|
*
|
||||||
|
* Copyright (C) 2012-2015 Atmel Corporation. All rights reserved.
|
||||||
|
*
|
||||||
|
* \asf_license_start
|
||||||
|
*
|
||||||
|
* \page License
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* 3. The name of Atmel may not be used to endorse or promote products derived
|
||||||
|
* from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* 4. This software may only be redistributed and used in connection with an
|
||||||
|
* Atmel microcontroller product.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||||
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||||
|
* EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
|
||||||
|
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||||
|
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||||
|
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* \asf_license_stop
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
|
||||||
|
*/
|
||||||
|
#include "dac.h"
|
||||||
|
#include <system.h>
|
||||||
|
#include <pinmux.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \internal Writes a DAC configuration to the hardware module.
|
||||||
|
*
|
||||||
|
* Writes out a given configuration to the hardware module.
|
||||||
|
*
|
||||||
|
* \param[out] module_inst Pointer to the DAC software instance struct
|
||||||
|
* \param[in] config Pointer to the configuration struct
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static void _dac_set_config(
|
||||||
|
struct dac_module *const module_inst,
|
||||||
|
struct dac_config *const config)
|
||||||
|
{
|
||||||
|
/* Sanity check arguments */
|
||||||
|
Assert(module_inst);
|
||||||
|
Assert(config);
|
||||||
|
Assert(module_inst->hw);
|
||||||
|
|
||||||
|
Dac *const dac_module = module_inst->hw;
|
||||||
|
|
||||||
|
/* Set selected DAC output to be enabled when enabling the module */
|
||||||
|
module_inst->output = config->output;
|
||||||
|
module_inst->start_on_event = false;
|
||||||
|
|
||||||
|
uint32_t new_ctrla = 0;
|
||||||
|
uint32_t new_ctrlb = 0;
|
||||||
|
|
||||||
|
/* Enable DAC in standby sleep mode if configured */
|
||||||
|
if (config->run_in_standby) {
|
||||||
|
new_ctrla |= DAC_CTRLA_RUNSTDBY;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set reference voltage */
|
||||||
|
new_ctrlb |= config->reference;
|
||||||
|
|
||||||
|
/* Left adjust data if configured */
|
||||||
|
if (config->left_adjust) {
|
||||||
|
new_ctrlb |= DAC_CTRLB_LEFTADJ;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef FEATURE_DAC_DATABUF_WRITE_PROTECTION
|
||||||
|
/* Bypass DATABUF write protection if configured */
|
||||||
|
if (config->databuf_protection_bypass) {
|
||||||
|
new_ctrlb |= DAC_CTRLB_BDWP;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Voltage pump disable if configured */
|
||||||
|
if (config->voltage_pump_disable) {
|
||||||
|
new_ctrlb |= DAC_CTRLB_VPD;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Apply the new configuration to the hardware module */
|
||||||
|
dac_module->CTRLA.reg = new_ctrla;
|
||||||
|
|
||||||
|
while (dac_is_syncing(module_inst)) {
|
||||||
|
/* Wait until the synchronization is complete */
|
||||||
|
}
|
||||||
|
|
||||||
|
dac_module->CTRLB.reg = new_ctrlb;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Determines if the hardware module(s) are currently synchronizing to the bus.
|
||||||
|
*
|
||||||
|
* Checks to see if the underlying hardware peripheral module(s) are currently
|
||||||
|
* synchronizing across multiple clock domains to the hardware bus, This
|
||||||
|
* function can be used to delay further operations on a module until such time
|
||||||
|
* that it is ready, to prevent blocking delays for synchronization in the
|
||||||
|
* user application.
|
||||||
|
*
|
||||||
|
* \param[in] dev_inst Pointer to the DAC software instance struct
|
||||||
|
*
|
||||||
|
* \return Synchronization status of the underlying hardware module(s).
|
||||||
|
*
|
||||||
|
* \retval true If the module synchronization is ongoing
|
||||||
|
* \retval false If the module has completed synchronization
|
||||||
|
*/
|
||||||
|
bool dac_is_syncing(
|
||||||
|
struct dac_module *const dev_inst)
|
||||||
|
{
|
||||||
|
/* Sanity check arguments */
|
||||||
|
Assert(dev_inst);
|
||||||
|
|
||||||
|
Dac *const dac_module = dev_inst->hw;
|
||||||
|
|
||||||
|
#if (SAMC21)
|
||||||
|
if (dac_module->SYNCBUSY.reg) {
|
||||||
|
#else
|
||||||
|
if (dac_module->STATUS.reg & DAC_STATUS_SYNCBUSY) {
|
||||||
|
#endif
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Initializes a DAC configuration structure to defaults.
|
||||||
|
*
|
||||||
|
* Initializes a given DAC configuration structure to a set of
|
||||||
|
* known default values. This function should be called on any new
|
||||||
|
* instance of the configuration structures before being modified by the
|
||||||
|
* user application.
|
||||||
|
*
|
||||||
|
* The default configuration is as follows:
|
||||||
|
* \li 1V from internal bandgap reference
|
||||||
|
* \li Drive the DAC output to the VOUT pin
|
||||||
|
* \li Right adjust data
|
||||||
|
* \li GCLK generator 0 (GCLK main) clock source
|
||||||
|
* \li The output buffer is disabled when the chip enters STANDBY sleep
|
||||||
|
* mode
|
||||||
|
*
|
||||||
|
* \param[out] config Configuration structure to initialize to default values
|
||||||
|
*/
|
||||||
|
void dac_get_config_defaults(
|
||||||
|
struct dac_config *const config)
|
||||||
|
{
|
||||||
|
/* Sanity check arguments */
|
||||||
|
Assert(config);
|
||||||
|
|
||||||
|
/* Default configuration values */
|
||||||
|
config->reference = DAC_REFERENCE_INT1V;
|
||||||
|
config->output = DAC_OUTPUT_EXTERNAL;
|
||||||
|
config->left_adjust = false;
|
||||||
|
#ifdef FEATURE_DAC_DATABUF_WRITE_PROTECTION
|
||||||
|
config->databuf_protection_bypass = false;
|
||||||
|
#endif
|
||||||
|
config->voltage_pump_disable = false;
|
||||||
|
config->clock_source = GCLK_GENERATOR_0;
|
||||||
|
config->run_in_standby = false;
|
||||||
|
#if (SAMC21)
|
||||||
|
config->dither_mode = false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Initialize the DAC device struct.
|
||||||
|
*
|
||||||
|
* Use this function to initialize the Digital to Analog Converter. Resets the
|
||||||
|
* underlying hardware module and configures it.
|
||||||
|
*
|
||||||
|
* \note The DAC channel must be configured separately.
|
||||||
|
*
|
||||||
|
* \param[out] module_inst Pointer to the DAC software instance struct
|
||||||
|
* \param[in] module Pointer to the DAC module instance
|
||||||
|
* \param[in] config Pointer to the config struct, created by the user
|
||||||
|
* application
|
||||||
|
*
|
||||||
|
* \return Status of initialization.
|
||||||
|
* \retval STATUS_OK Module initiated correctly
|
||||||
|
* \retval STATUS_ERR_DENIED If module is enabled
|
||||||
|
* \retval STATUS_BUSY If module is busy resetting
|
||||||
|
*/
|
||||||
|
enum status_code dac_init(
|
||||||
|
struct dac_module *const module_inst,
|
||||||
|
Dac *const module,
|
||||||
|
struct dac_config *const config)
|
||||||
|
{
|
||||||
|
/* Sanity check arguments */
|
||||||
|
Assert(module_inst);
|
||||||
|
Assert(module);
|
||||||
|
Assert(config);
|
||||||
|
|
||||||
|
/* Initialize device instance */
|
||||||
|
module_inst->hw = module;
|
||||||
|
|
||||||
|
/* Turn on the digital interface clock */
|
||||||
|
#if (SAMC21)
|
||||||
|
system_apb_clock_set_mask(SYSTEM_CLOCK_APB_APBC, MCLK_APBCMASK_DAC);
|
||||||
|
#else
|
||||||
|
system_apb_clock_set_mask(SYSTEM_CLOCK_APB_APBC, PM_APBCMASK_DAC);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Check if module is enabled. */
|
||||||
|
if (module->CTRLA.reg & DAC_CTRLA_ENABLE) {
|
||||||
|
return STATUS_ERR_DENIED;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if reset is in progress. */
|
||||||
|
if (module->CTRLA.reg & DAC_CTRLA_SWRST) {
|
||||||
|
return STATUS_BUSY;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Configure GCLK channel and enable clock */
|
||||||
|
struct system_gclk_chan_config gclk_chan_conf;
|
||||||
|
system_gclk_chan_get_config_defaults(&gclk_chan_conf);
|
||||||
|
gclk_chan_conf.source_generator = config->clock_source;
|
||||||
|
system_gclk_chan_set_config(DAC_GCLK_ID, &gclk_chan_conf);
|
||||||
|
system_gclk_chan_enable(DAC_GCLK_ID);
|
||||||
|
|
||||||
|
/* MUX the DAC VOUT pin */
|
||||||
|
struct system_pinmux_config pin_conf;
|
||||||
|
system_pinmux_get_config_defaults(&pin_conf);
|
||||||
|
|
||||||
|
/* Set up the DAC VOUT pin */
|
||||||
|
pin_conf.mux_position = MUX_PA02B_DAC_VOUT;
|
||||||
|
pin_conf.direction = SYSTEM_PINMUX_PIN_DIR_INPUT;
|
||||||
|
pin_conf.input_pull = SYSTEM_PINMUX_PIN_PULL_NONE;
|
||||||
|
system_pinmux_pin_set_config(PIN_PA02B_DAC_VOUT, &pin_conf);
|
||||||
|
|
||||||
|
/* Write configuration to module */
|
||||||
|
_dac_set_config(module_inst, config);
|
||||||
|
|
||||||
|
/* Store reference selection for later use */
|
||||||
|
module_inst->reference = config->reference;
|
||||||
|
|
||||||
|
#if DAC_CALLBACK_MODE == true
|
||||||
|
for (uint8_t i = 0; i < DAC_CALLBACK_N; i++) {
|
||||||
|
module_inst->callback[i] = NULL;
|
||||||
|
};
|
||||||
|
|
||||||
|
_dac_instances[0] = module_inst;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return STATUS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Resets the DAC module.
|
||||||
|
*
|
||||||
|
* This function will reset the DAC module to its power on default values and
|
||||||
|
* disable it.
|
||||||
|
*
|
||||||
|
* \param[in] module_inst Pointer to the DAC software instance struct
|
||||||
|
*/
|
||||||
|
void dac_reset(
|
||||||
|
struct dac_module *const module_inst)
|
||||||
|
{
|
||||||
|
/* Sanity check arguments */
|
||||||
|
Assert(module_inst);
|
||||||
|
Assert(module_inst->hw);
|
||||||
|
|
||||||
|
Dac *const dac_module = module_inst->hw;
|
||||||
|
|
||||||
|
while (dac_is_syncing(module_inst)) {
|
||||||
|
/* Wait until the synchronization is complete */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Software reset the module */
|
||||||
|
dac_module->CTRLA.reg |= DAC_CTRLA_SWRST;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Enable the DAC module.
|
||||||
|
*
|
||||||
|
* Enables the DAC interface and the selected output. If any internal reference
|
||||||
|
* is selected it will be enabled.
|
||||||
|
*
|
||||||
|
* \param[in] module_inst Pointer to the DAC software instance struct
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void dac_enable(
|
||||||
|
struct dac_module *const module_inst)
|
||||||
|
{
|
||||||
|
/* Sanity check arguments */
|
||||||
|
Assert(module_inst);
|
||||||
|
Assert(module_inst->hw);
|
||||||
|
|
||||||
|
Dac *const dac_module = module_inst->hw;
|
||||||
|
|
||||||
|
/* Enable selected output */
|
||||||
|
dac_module->CTRLB.reg |= module_inst->output;
|
||||||
|
|
||||||
|
while (dac_is_syncing(module_inst)) {
|
||||||
|
/* Wait until the synchronization is complete */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Enable the module */
|
||||||
|
dac_module->CTRLA.reg |= DAC_CTRLA_ENABLE;
|
||||||
|
|
||||||
|
/* Enable internal bandgap reference if selected in the configuration */
|
||||||
|
if (module_inst->reference == DAC_REFERENCE_INT1V) {
|
||||||
|
#if (SAMC21)
|
||||||
|
system_voltage_reference_enable(SYSTEM_VOLTAGE_REFERENCE_OUTPUT);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(dac_module->CTRLA.reg & DAC_CTRLA_ENABLE) {
|
||||||
|
while(! (dac_module->STATUS.reg & DAC_STATUS_READY)) {
|
||||||
|
};
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
system_voltage_reference_enable(SYSTEM_VOLTAGE_REFERENCE_BANDGAP);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Disable the DAC module.
|
||||||
|
*
|
||||||
|
* Disables the DAC interface and the output buffer.
|
||||||
|
*
|
||||||
|
* \param[in] module_inst Pointer to the DAC software instance struct
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void dac_disable(
|
||||||
|
struct dac_module *const module_inst)
|
||||||
|
{
|
||||||
|
/* Sanity check arguments */
|
||||||
|
Assert(module_inst);
|
||||||
|
Assert(module_inst->hw);
|
||||||
|
|
||||||
|
Dac *const dac_module = module_inst->hw;
|
||||||
|
|
||||||
|
/* Wait until the synchronization is complete */
|
||||||
|
while (dac_is_syncing(module_inst)) {
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Disable DAC */
|
||||||
|
dac_module->CTRLA.reg &= ~DAC_CTRLA_ENABLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Enables a DAC event input or output.
|
||||||
|
*
|
||||||
|
* Enables one or more input or output events to or from the DAC module. See
|
||||||
|
* \ref dac_events "here" for a list of events this module supports.
|
||||||
|
*
|
||||||
|
* \note Events cannot be altered while the module is enabled.
|
||||||
|
*
|
||||||
|
* \param[in] module_inst Software instance for the DAC peripheral
|
||||||
|
* \param[in] events Struct containing flags of events to enable
|
||||||
|
*/
|
||||||
|
void dac_enable_events(
|
||||||
|
struct dac_module *const module_inst,
|
||||||
|
struct dac_events *const events)
|
||||||
|
{
|
||||||
|
/* Sanity check arguments */
|
||||||
|
Assert(module_inst);
|
||||||
|
Assert(module_inst->hw);
|
||||||
|
Assert(events);
|
||||||
|
|
||||||
|
Dac *const dac_module = module_inst->hw;
|
||||||
|
|
||||||
|
uint32_t event_mask = 0;
|
||||||
|
|
||||||
|
#if(SAMC21)
|
||||||
|
/* Configure Enable Inversion of input event */
|
||||||
|
if (events->generate_event_on_chan_falling_edge) {
|
||||||
|
event_mask |= DAC_EVCTRL_INVEI;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Configure Buffer Empty event */
|
||||||
|
if (events->generate_event_on_buffer_empty) {
|
||||||
|
event_mask |= DAC_EVCTRL_EMPTYEO;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Configure Conversion Start event */
|
||||||
|
if (events->on_event_start_conversion) {
|
||||||
|
event_mask |= DAC_EVCTRL_STARTEI;
|
||||||
|
module_inst->start_on_event = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
dac_module->EVCTRL.reg |= event_mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Disables a DAC event input or output.
|
||||||
|
*
|
||||||
|
* Disables one or more input or output events to or from the DAC module. See
|
||||||
|
* \ref dac_events "here" for a list of events this module supports.
|
||||||
|
*
|
||||||
|
* \note Events cannot be altered while the module is enabled.
|
||||||
|
*
|
||||||
|
* \param[in] module_inst Software instance for the DAC peripheral
|
||||||
|
* \param[in] events Struct containing flags of events to disable
|
||||||
|
*/
|
||||||
|
void dac_disable_events(
|
||||||
|
struct dac_module *const module_inst,
|
||||||
|
struct dac_events *const events)
|
||||||
|
{
|
||||||
|
/* Sanity check arguments */
|
||||||
|
Assert(module_inst);
|
||||||
|
Assert(module_inst->hw);
|
||||||
|
Assert(events);
|
||||||
|
|
||||||
|
Dac *const dac_module = module_inst->hw;
|
||||||
|
|
||||||
|
uint32_t event_mask = 0;
|
||||||
|
|
||||||
|
/* Configure Buffer Empty event */
|
||||||
|
if (events->generate_event_on_buffer_empty) {
|
||||||
|
event_mask |= DAC_EVCTRL_EMPTYEO;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Configure Conversion Start event */
|
||||||
|
if (events->on_event_start_conversion) {
|
||||||
|
event_mask |= DAC_EVCTRL_STARTEI;
|
||||||
|
module_inst->start_on_event = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
dac_module->EVCTRL.reg &= ~event_mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Initializes a DAC channel configuration structure to defaults.
|
||||||
|
*
|
||||||
|
* Initializes a given DAC channel configuration structure to a set of
|
||||||
|
* known default values. This function should be called on any new
|
||||||
|
* instance of the configuration structures before being modified by the
|
||||||
|
* user application.
|
||||||
|
*
|
||||||
|
* The default configuration is as follows:
|
||||||
|
* \li Start Conversion Event Input enabled
|
||||||
|
* \li Start Data Buffer Empty Event Output disabled
|
||||||
|
*
|
||||||
|
* \param[out] config Configuration structure to initialize to default values
|
||||||
|
*/
|
||||||
|
void dac_chan_get_config_defaults(
|
||||||
|
struct dac_chan_config *const config)
|
||||||
|
{
|
||||||
|
/* Sanity check arguments */
|
||||||
|
Assert(config);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Writes a DAC channel configuration to the hardware module.
|
||||||
|
*
|
||||||
|
* Writes a given channel configuration to the hardware module.
|
||||||
|
*
|
||||||
|
* \note The DAC device instance structure must be initialized before calling
|
||||||
|
* this function.
|
||||||
|
*
|
||||||
|
* \param[in] module_inst Pointer to the DAC software instance struct
|
||||||
|
* \param[in] channel Channel to configure
|
||||||
|
* \param[in] config Pointer to the configuration struct
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void dac_chan_set_config(
|
||||||
|
struct dac_module *const module_inst,
|
||||||
|
const enum dac_channel channel,
|
||||||
|
struct dac_chan_config *const config)
|
||||||
|
{
|
||||||
|
/* No channel support yet */
|
||||||
|
UNUSED(channel);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Enable a DAC channel.
|
||||||
|
*
|
||||||
|
* Enables the selected DAC channel.
|
||||||
|
*
|
||||||
|
* \param[in] module_inst Pointer to the DAC software instance struct
|
||||||
|
* \param[in] channel Channel to enable
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void dac_chan_enable(
|
||||||
|
struct dac_module *const module_inst,
|
||||||
|
enum dac_channel channel)
|
||||||
|
{
|
||||||
|
/* No channel support yet */
|
||||||
|
UNUSED(channel);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Disable a DAC channel.
|
||||||
|
*
|
||||||
|
* Disables the selected DAC channel.
|
||||||
|
*
|
||||||
|
* \param[in] module_inst Pointer to the DAC software instance struct
|
||||||
|
* \param[in] channel Channel to disable
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void dac_chan_disable(
|
||||||
|
struct dac_module *const module_inst,
|
||||||
|
enum dac_channel channel)
|
||||||
|
{
|
||||||
|
/* No channel support yet */
|
||||||
|
UNUSED(channel);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Enable the output buffer.
|
||||||
|
*
|
||||||
|
* Enables the output buffer and drives the DAC output to the VOUT pin.
|
||||||
|
*
|
||||||
|
* \param[in] module_inst Pointer to the DAC software instance struct
|
||||||
|
* \param[in] channel DAC channel to alter
|
||||||
|
*/
|
||||||
|
void dac_chan_enable_output_buffer(
|
||||||
|
struct dac_module *const module_inst,
|
||||||
|
enum dac_channel channel)
|
||||||
|
{
|
||||||
|
/* Sanity check arguments */
|
||||||
|
Assert(module_inst);
|
||||||
|
Assert(module_inst->hw);
|
||||||
|
|
||||||
|
/* No channel support yet */
|
||||||
|
UNUSED(channel);
|
||||||
|
|
||||||
|
Dac *const dac_module = module_inst->hw;
|
||||||
|
|
||||||
|
/* Enable output buffer */
|
||||||
|
dac_module->CTRLB.reg |= DAC_OUTPUT_EXTERNAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Disable the output buffer.
|
||||||
|
*
|
||||||
|
* Disables the output buffer.
|
||||||
|
*
|
||||||
|
* \note The output buffer(s) should be disabled when a channel's output is not
|
||||||
|
* currently needed, as it will draw current even if the system is in
|
||||||
|
* sleep mode.
|
||||||
|
*
|
||||||
|
* \param[in] module_inst Pointer to the DAC software instance struct
|
||||||
|
* \param[in] channel DAC channel to alter
|
||||||
|
*/
|
||||||
|
void dac_chan_disable_output_buffer(
|
||||||
|
struct dac_module *const module_inst,
|
||||||
|
enum dac_channel channel)
|
||||||
|
{
|
||||||
|
/* Sanity check arguments*/
|
||||||
|
Assert(module_inst);
|
||||||
|
Assert(module_inst->hw);
|
||||||
|
|
||||||
|
/* No channel support yet */
|
||||||
|
UNUSED(channel);
|
||||||
|
|
||||||
|
Dac *const dac_module = module_inst->hw;
|
||||||
|
|
||||||
|
/* Disable output buffer */
|
||||||
|
dac_module->CTRLB.reg &= ~DAC_OUTPUT_EXTERNAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Write to the DAC.
|
||||||
|
*
|
||||||
|
* This function writes to the DATA or DATABUF register.
|
||||||
|
* If the conversion is not event-triggered, the data will be written to
|
||||||
|
* the DATA register and the conversion will start.
|
||||||
|
* If the conversion is event-triggered, the data will be written to DATABUF
|
||||||
|
* and transferred to the DATA register and converted when a Start Conversion
|
||||||
|
* Event is issued.
|
||||||
|
* Conversion data must be right or left adjusted according to configuration
|
||||||
|
* settings.
|
||||||
|
* \note To be event triggered, the enable_start_on_event must be
|
||||||
|
* enabled in the configuration.
|
||||||
|
*
|
||||||
|
* \param[in] module_inst Pointer to the DAC software device struct
|
||||||
|
* \param[in] channel DAC channel to write to
|
||||||
|
* \param[in] data Conversion data
|
||||||
|
*
|
||||||
|
* \return Status of the operation.
|
||||||
|
* \retval STATUS_OK If the data was written
|
||||||
|
*/
|
||||||
|
enum status_code dac_chan_write(
|
||||||
|
struct dac_module *const module_inst,
|
||||||
|
enum dac_channel channel,
|
||||||
|
const uint16_t data)
|
||||||
|
{
|
||||||
|
/* Sanity check arguments */
|
||||||
|
Assert(module_inst);
|
||||||
|
Assert(module_inst->hw);
|
||||||
|
|
||||||
|
/* No channel support yet */
|
||||||
|
UNUSED(channel);
|
||||||
|
|
||||||
|
Dac *const dac_module = module_inst->hw;
|
||||||
|
|
||||||
|
/* Wait until the synchronization is complete */
|
||||||
|
while (dac_is_syncing(module_inst)) {
|
||||||
|
};
|
||||||
|
|
||||||
|
if (module_inst->start_on_event) {
|
||||||
|
/* Write the new value to the buffered DAC data register */
|
||||||
|
dac_module->DATABUF.reg = data;
|
||||||
|
} else {
|
||||||
|
/* Write the new value to the DAC data register */
|
||||||
|
dac_module->DATA.reg = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
return STATUS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Write to the DAC.
|
||||||
|
*
|
||||||
|
* This function converts a specific number of digital data.
|
||||||
|
* The conversion should be event-triggered, the data will be written to DATABUF
|
||||||
|
* and transferred to the DATA register and converted when a Start Conversion
|
||||||
|
* Event is issued.
|
||||||
|
* Conversion data must be right or left adjusted according to configuration
|
||||||
|
* settings.
|
||||||
|
* \note To be event triggered, the enable_start_on_event must be
|
||||||
|
* enabled in the configuration.
|
||||||
|
*
|
||||||
|
* \param[in] module_inst Pointer to the DAC software device struct
|
||||||
|
* \param[in] channel DAC channel to write to
|
||||||
|
* \param[in] buffer Pointer to the digital data write buffer to be converted
|
||||||
|
* \param[in] length Length of the write buffer
|
||||||
|
*
|
||||||
|
* \return Status of the operation.
|
||||||
|
* \retval STATUS_OK If the data was written or no data conversion required
|
||||||
|
* \retval STATUS_ERR_UNSUPPORTED_DEV The DAC is not configured as using event trigger
|
||||||
|
* \retval STATUS_BUSY The DAC is busy to convert
|
||||||
|
*/
|
||||||
|
enum status_code dac_chan_write_buffer_wait(
|
||||||
|
struct dac_module *const module_inst,
|
||||||
|
enum dac_channel channel,
|
||||||
|
uint16_t *buffer,
|
||||||
|
uint32_t length)
|
||||||
|
{
|
||||||
|
/* Sanity check arguments */
|
||||||
|
Assert(module_inst);
|
||||||
|
Assert(module_inst->hw);
|
||||||
|
|
||||||
|
/* No channel support yet */
|
||||||
|
UNUSED(channel);
|
||||||
|
|
||||||
|
Dac *const dac_module = module_inst->hw;
|
||||||
|
|
||||||
|
/* Wait until the synchronization is complete */
|
||||||
|
while (dac_is_syncing(module_inst)) {
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Zero length request */
|
||||||
|
if (length == 0) {
|
||||||
|
/* No data to be converted */
|
||||||
|
return STATUS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if DAC_CALLBACK_MODE == true
|
||||||
|
/* Check if busy */
|
||||||
|
if (module_inst->job_status == STATUS_BUSY) {
|
||||||
|
return STATUS_BUSY;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Only support event triggered conversion */
|
||||||
|
if (module_inst->start_on_event == false) {
|
||||||
|
return STATUS_ERR_UNSUPPORTED_DEV;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Blocks while buffer is being transferred */
|
||||||
|
while (length--) {
|
||||||
|
/* Convert one data */
|
||||||
|
dac_chan_write(module_inst, channel, buffer[length]);
|
||||||
|
|
||||||
|
/* Wait until Transmit is complete or timeout */
|
||||||
|
for (uint32_t i = 0; i <= DAC_TIMEOUT; i++) {
|
||||||
|
if (dac_module->INTFLAG.reg & DAC_INTFLAG_EMPTY) {
|
||||||
|
break;
|
||||||
|
} else if (i == DAC_TIMEOUT) {
|
||||||
|
return STATUS_ERR_TIMEOUT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return STATUS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Retrieves the current module status
|
||||||
|
*
|
||||||
|
* Checks the status of the module and returns it as a bitmask of status
|
||||||
|
* flags.
|
||||||
|
*
|
||||||
|
* \param[in] module_inst Pointer to the DAC software device struct
|
||||||
|
*
|
||||||
|
* \return Bitmask of status flags.
|
||||||
|
*
|
||||||
|
* \retval DAC_STATUS_CHANNEL_0_EMPTY Data has been transferred from DATABUF
|
||||||
|
* to DATA by a start conversion event
|
||||||
|
* and DATABUF is ready for new data
|
||||||
|
* \retval DAC_STATUS_CHANNEL_0_UNDERRUN A start conversion event has occurred
|
||||||
|
* when DATABUF is empty
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
uint32_t dac_get_status(
|
||||||
|
struct dac_module *const module_inst)
|
||||||
|
{
|
||||||
|
/* Sanity check arguments */
|
||||||
|
Assert(module_inst);
|
||||||
|
Assert(module_inst->hw);
|
||||||
|
|
||||||
|
Dac *const dac_module = module_inst->hw;
|
||||||
|
|
||||||
|
uint8_t intflags = dac_module->INTFLAG.reg;
|
||||||
|
uint32_t status_flags = 0;
|
||||||
|
|
||||||
|
if (intflags & DAC_INTFLAG_EMPTY) {
|
||||||
|
status_flags |= DAC_STATUS_CHANNEL_0_EMPTY;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (intflags & DAC_INTFLAG_UNDERRUN) {
|
||||||
|
status_flags |= DAC_STATUS_CHANNEL_0_UNDERRUN;
|
||||||
|
}
|
||||||
|
|
||||||
|
return status_flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Clears a module status flag
|
||||||
|
*
|
||||||
|
* Clears the given status flag of the module.
|
||||||
|
*
|
||||||
|
* \param[in] module_inst Pointer to the DAC software device struct
|
||||||
|
* \param[in] status_flags Bit mask of status flags to clear
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void dac_clear_status(
|
||||||
|
struct dac_module *const module_inst,
|
||||||
|
uint32_t status_flags)
|
||||||
|
{
|
||||||
|
/* Sanity check arguments */
|
||||||
|
Assert(module_inst);
|
||||||
|
Assert(module_inst->hw);
|
||||||
|
|
||||||
|
Dac *const dac_module = module_inst->hw;
|
||||||
|
|
||||||
|
uint32_t intflags = 0;
|
||||||
|
|
||||||
|
if (status_flags & DAC_STATUS_CHANNEL_0_EMPTY) {
|
||||||
|
intflags |= DAC_INTFLAG_EMPTY;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status_flags & DAC_STATUS_CHANNEL_0_UNDERRUN) {
|
||||||
|
intflags |= DAC_INTFLAG_UNDERRUN;
|
||||||
|
}
|
||||||
|
|
||||||
|
dac_module->INTFLAG.reg = intflags;
|
||||||
|
}
|
|
@ -0,0 +1,635 @@
|
||||||
|
/**
|
||||||
|
* \file
|
||||||
|
*
|
||||||
|
* \brief SAM Peripheral Digital-to-Analog Converter Driver
|
||||||
|
*
|
||||||
|
* Copyright (C) 2012-2015 Atmel Corporation. All rights reserved.
|
||||||
|
*
|
||||||
|
* \asf_license_start
|
||||||
|
*
|
||||||
|
* \page License
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* 3. The name of Atmel may not be used to endorse or promote products derived
|
||||||
|
* from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* 4. This software may only be redistributed and used in connection with an
|
||||||
|
* Atmel microcontroller product.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||||
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||||
|
* EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
|
||||||
|
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||||
|
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||||
|
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* \asf_license_stop
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
|
||||||
|
*/
|
||||||
|
#ifndef DAC_FEATURE_H_INCLUDED
|
||||||
|
#define DAC_FEATURE_H_INCLUDED
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \defgroup asfdoc_sam0_dac_group SAM Digital-to-Analog Driver (DAC)
|
||||||
|
*
|
||||||
|
* This driver for Atmel® | SMART ARM®-based microcontrollers provides an interface for the conversion of
|
||||||
|
* digital values to analog voltage. The following driver API modes are covered
|
||||||
|
* by this manual:
|
||||||
|
*
|
||||||
|
* - Polled APIs
|
||||||
|
* \if DAC_CALLBACK_MODE
|
||||||
|
* - Callback APIs
|
||||||
|
* \endif
|
||||||
|
*
|
||||||
|
* The following peripherals are used by this module:
|
||||||
|
* - DAC (Digital-to-Analog Converter)
|
||||||
|
*
|
||||||
|
* The following devices can use this module:
|
||||||
|
* - Atmel | SMART SAM D20/D21
|
||||||
|
* - Atmel | SMART SAM D10/D11
|
||||||
|
* - Atmel | SMART SAM DA0/DA1
|
||||||
|
* - Atmel | SMART SAM C21
|
||||||
|
*
|
||||||
|
* The outline of this documentation is as follows:
|
||||||
|
* - \ref asfdoc_sam0_dac_prerequisites
|
||||||
|
* - \ref asfdoc_sam0_dac_module_overview
|
||||||
|
* - \ref asfdoc_sam0_dac_special_considerations
|
||||||
|
* - \ref asfdoc_sam0_dac_extra_info
|
||||||
|
* - \ref asfdoc_sam0_dac_examples
|
||||||
|
* - \ref asfdoc_sam0_dac_api_overview
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* \section asfdoc_sam0_dac_prerequisites Prerequisites
|
||||||
|
*
|
||||||
|
* There are no prerequisites for this module.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* \section asfdoc_sam0_dac_module_overview Module Overview
|
||||||
|
*
|
||||||
|
* The Digital-to-Analog converter converts a digital value to analog voltage.
|
||||||
|
* The SAM DAC module has one channel with 10-bit resolution,
|
||||||
|
* and is capable of converting up to 350k samples per second (ksps).
|
||||||
|
*
|
||||||
|
* A common use of DAC is to generate audio signals by connecting the DAC
|
||||||
|
* output to a speaker, or to generate a reference voltage; either for an
|
||||||
|
* external circuit or an internal peripheral such as the Analog Comparator.
|
||||||
|
*
|
||||||
|
* After being set up, the DAC will convert new digital values written to the
|
||||||
|
* conversion data register (DATA) to an analog value either on the VOUT pin of
|
||||||
|
* the device, or internally for use as an input to the AC, ADC, and other analog
|
||||||
|
* modules.
|
||||||
|
*
|
||||||
|
* Writing the DATA register will start a new conversion. It is also possible
|
||||||
|
* to trigger the conversion from the event system.
|
||||||
|
*
|
||||||
|
* A simplified block diagram of the DAC can be seen in
|
||||||
|
* \ref asfdoc_sam0_dac_module_block_diagram "the figure below".
|
||||||
|
*
|
||||||
|
* \anchor asfdoc_sam0_dac_module_block_diagram
|
||||||
|
* \image html dac_block_diagram.svg "DAC Block Diagram"
|
||||||
|
*
|
||||||
|
* \subsection asfdoc_sam0_dac_conversion_range Conversion Range
|
||||||
|
* The conversion range is between GND and the selected voltage reference.
|
||||||
|
* Available voltage references are:
|
||||||
|
* \li AVCC voltage reference
|
||||||
|
* \li Internal 1V reference (INT1V)
|
||||||
|
* \li External voltage reference (AREF)
|
||||||
|
*
|
||||||
|
* \note Internal references will be enabled by the driver, but not disabled.
|
||||||
|
* Any reference not used by the application should be disabled by the application.
|
||||||
|
*
|
||||||
|
* The output voltage from a DAC channel is given as:
|
||||||
|
* \f[
|
||||||
|
* V_{OUT} = \frac{DATA}{0x3FF} \times VREF
|
||||||
|
* \f]
|
||||||
|
*
|
||||||
|
* \subsection asfdoc_sam0_dac_conversion Conversion
|
||||||
|
* The digital value written to the conversion data register (DATA) will be
|
||||||
|
* converted to an analog value.
|
||||||
|
* Writing the DATA register will start a new conversion.
|
||||||
|
* It is also possible to write the conversion data to the DATABUF register,
|
||||||
|
* the writing of the DATA register can then be triggered from the event
|
||||||
|
* system, which will load the value from DATABUF to DATA.
|
||||||
|
*
|
||||||
|
* \subsection asfdoc_sam0_dac_analog_output Analog Output
|
||||||
|
* The analog output value can be output to either the VOUT pin or internally,
|
||||||
|
* but not both at the same time.
|
||||||
|
*
|
||||||
|
* \subsubsection asfdoc_sam0_dac_analog_output_external External Output
|
||||||
|
* The output buffer must be enabled in order to drive the DAC output to the
|
||||||
|
* VOUT pin. Due to the output buffer, the DAC has high drive strength, and is
|
||||||
|
* capable of driving both resistive and capacitive loads, as well as loads
|
||||||
|
* which combine both.
|
||||||
|
*
|
||||||
|
* \subsubsection asfdoc_sam0_dac_analog_output_internal Internal Output
|
||||||
|
* The analog value can be internally available for use as input to the
|
||||||
|
* AC or ADC modules.
|
||||||
|
*
|
||||||
|
* \subsection asfdoc_sam0_dac_events Events
|
||||||
|
* Events generation and event actions are configurable in the DAC.
|
||||||
|
* The DAC has one event line input and one event output: <i>Start Conversion</i>
|
||||||
|
* and <i>Data Buffer Empty</i>.
|
||||||
|
*
|
||||||
|
* If the Start Conversion input event is enabled in the module configuration,
|
||||||
|
* an incoming event will load data from the data buffer to the data register
|
||||||
|
* and start a new conversion. This method synchronizes conversions with
|
||||||
|
* external events (such as those from a timer module) and ensures regular and
|
||||||
|
* fixed conversion intervals.
|
||||||
|
*
|
||||||
|
* If the Data Buffer Empty output event is enabled in the module configuration,
|
||||||
|
* events will be generated when the DAC data buffer register becomes empty and
|
||||||
|
* new data can be loaded to the buffer.
|
||||||
|
*
|
||||||
|
* \note The connection of events between modules requires the use of the
|
||||||
|
* \ref asfdoc_sam0_events_group "SAM Event System Driver (EVENTS)"
|
||||||
|
* to route output event of one module to the the input event of another.
|
||||||
|
* For more information on event routing, refer to the event driver
|
||||||
|
* documentation.
|
||||||
|
*
|
||||||
|
* \subsection asfdoc_sam0_dac_data_adjust Left and Right Adjusted Values
|
||||||
|
* The 10-bit input value to the DAC is contained in a 16-bit register. This
|
||||||
|
* can be configured to be either left or right adjusted. In
|
||||||
|
* \ref asfdoc_sam0_dac_module_adj_modes "the figure below" both options are
|
||||||
|
* shown, and the position of the most (MSB) and the least (LSB) significant bits
|
||||||
|
* are indicated. The unused bits should always be written to zero.
|
||||||
|
*
|
||||||
|
* \anchor asfdoc_sam0_dac_module_adj_modes
|
||||||
|
* \dot
|
||||||
|
* digraph {
|
||||||
|
* subgraph cluster_right {
|
||||||
|
* msbl [label="MSB", shape=none, group="msbl"];
|
||||||
|
* lsbl [label="LSB", shape=none];
|
||||||
|
* node [shape=none];
|
||||||
|
* color="white";
|
||||||
|
* reg_left [label=<
|
||||||
|
* <table cellspacing="0" cellpadding="2" width="100%">
|
||||||
|
* <tr>
|
||||||
|
* <td port="msb">15</td>
|
||||||
|
* <td>14</td>
|
||||||
|
* <td>13</td>
|
||||||
|
* <td>12</td>
|
||||||
|
* <td>11</td>
|
||||||
|
* <td>10</td>
|
||||||
|
* <td>9</td>
|
||||||
|
* <td>8</td>
|
||||||
|
* <td>7</td>
|
||||||
|
* <td port="lsb">6</td>
|
||||||
|
* <td>5</td>
|
||||||
|
* <td>4</td>
|
||||||
|
* <td>3</td>
|
||||||
|
* <td>2</td>
|
||||||
|
* <td>1</td>
|
||||||
|
* <td>0</td>
|
||||||
|
* </tr>
|
||||||
|
* <tr>
|
||||||
|
* <td COLSPAN="10"> DATA[9:0] </td>
|
||||||
|
* <td BGCOLOR="lightgray"> </td>
|
||||||
|
* <td BGCOLOR="lightgray"> </td>
|
||||||
|
* <td BGCOLOR="lightgray"> </td>
|
||||||
|
* <td BGCOLOR="lightgray"> </td>
|
||||||
|
* <td BGCOLOR="lightgray"> </td>
|
||||||
|
* <td BGCOLOR="lightgray"> </td>
|
||||||
|
* </tr>
|
||||||
|
* </table>
|
||||||
|
* >];
|
||||||
|
* msbl -> reg_left:msb:n;
|
||||||
|
* lsbl -> reg_left:lsb;
|
||||||
|
* label ="Left adjusted.\n";
|
||||||
|
* }
|
||||||
|
* subgraph cluster_left {
|
||||||
|
* rankdir=TB;
|
||||||
|
* msb [label="MSB", shape=none];
|
||||||
|
* lsb [label="LSB", shape=none];
|
||||||
|
* color="white";
|
||||||
|
* node [shape=none];
|
||||||
|
* reg_right [label=<
|
||||||
|
* <table cellspacing="0" cellpadding="2">
|
||||||
|
* <tr>
|
||||||
|
* <td>15</td>
|
||||||
|
* <td>14</td>
|
||||||
|
* <td>13</td>
|
||||||
|
* <td>12</td>
|
||||||
|
* <td>11</td>
|
||||||
|
* <td>10</td>
|
||||||
|
* <td port="msb">9</td>
|
||||||
|
* <td>8</td>
|
||||||
|
* <td>7</td>
|
||||||
|
* <td>6</td>
|
||||||
|
* <td>5</td>
|
||||||
|
* <td>4</td>
|
||||||
|
* <td>3</td>
|
||||||
|
* <td>2</td>
|
||||||
|
* <td>1</td>
|
||||||
|
* <td port="lsb">0</td>
|
||||||
|
* </tr>
|
||||||
|
* <tr>
|
||||||
|
* <td BGCOLOR="lightgray"></td>
|
||||||
|
* <td BGCOLOR="lightgray"></td>
|
||||||
|
* <td BGCOLOR="lightgray"></td>
|
||||||
|
* <td BGCOLOR="lightgray"></td>
|
||||||
|
* <td BGCOLOR="lightgray"></td>
|
||||||
|
* <td BGCOLOR="lightgray"></td>
|
||||||
|
* <td COLSPAN="10"> DATA[9:0] </td>
|
||||||
|
* </tr>
|
||||||
|
* </table>
|
||||||
|
* >];
|
||||||
|
* msb -> reg_right:msb;
|
||||||
|
* lsb -> reg_right:lsb:n;
|
||||||
|
* label = "Right adjusted.\n";
|
||||||
|
* graph [shape=none];
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* \enddot
|
||||||
|
*
|
||||||
|
* \subsection asfdoc_sam0_dac_clk_sources Clock Sources
|
||||||
|
* The clock for the DAC interface (CLK_DAC) is generated by the Power Manager.
|
||||||
|
* This clock is turned on by default, and can be enabled and disabled in the
|
||||||
|
* Power Manager.
|
||||||
|
*
|
||||||
|
* Additionally, an asynchronous clock source (GCLK_DAC) is required.
|
||||||
|
* These clocks are normally disabled by default. The selected clock source
|
||||||
|
* must be enabled in the Power Manager before it can be used by the DAC.
|
||||||
|
* The DAC core operates asynchronously from the user interface and
|
||||||
|
* peripheral bus. As a consequence, the DAC needs two clock cycles of both
|
||||||
|
* CLK_DAC and GCLK_DAC to synchronize the values written to some of the
|
||||||
|
* control and data registers.
|
||||||
|
* The oscillator source for the GCLK_DAC clock is selected in the System
|
||||||
|
* Control Interface (SCIF).
|
||||||
|
*
|
||||||
|
* \section asfdoc_sam0_dac_special_considerations Special Considerations
|
||||||
|
*
|
||||||
|
* \subsection asfdoc_sam0_dac_special_considerations_output_buffer Output Driver
|
||||||
|
* The DAC can only do conversions in Active or Idle modes. However, if the
|
||||||
|
* output buffer is enabled it will draw current even if the system is in
|
||||||
|
* sleep mode. Therefore, always make sure that the output buffer is not
|
||||||
|
* enabled when it is not needed, to ensure minimum power consumption.
|
||||||
|
*
|
||||||
|
* \subsection asfdoc_sam0_dac_special_considerations_conversion_time Conversion Time
|
||||||
|
* DAC conversion time is approximately 2.85µs. The user must ensure that new
|
||||||
|
* data is not written to the DAC before the last conversion is complete.
|
||||||
|
* Conversions should be triggered by a periodic event from a Timer/Counter or
|
||||||
|
* another peripheral.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* \section asfdoc_sam0_dac_extra_info Extra Information
|
||||||
|
*
|
||||||
|
* For extra information, see \ref asfdoc_sam0_dac_extra. This includes:
|
||||||
|
* - \ref asfdoc_sam0_dac_extra_acronyms
|
||||||
|
* - \ref asfdoc_sam0_dac_extra_dependencies
|
||||||
|
* - \ref asfdoc_sam0_dac_extra_errata
|
||||||
|
* - \ref asfdoc_sam0_dac_extra_history
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* \section asfdoc_sam0_dac_examples Examples
|
||||||
|
*
|
||||||
|
* For a list of examples related to this driver, see
|
||||||
|
* \ref asfdoc_sam0_dac_exqsg.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* \section asfdoc_sam0_dac_api_overview API Overview
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <compiler.h>
|
||||||
|
#include <clock.h>
|
||||||
|
#include <gclk.h>
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \name DAC Status Flags
|
||||||
|
*
|
||||||
|
* DAC status flags, returned by \ref dac_get_status() and cleared by
|
||||||
|
* \ref dac_clear_status().
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** Data Buffer Empty Channel 0 - Set when data is transferred from DATABUF
|
||||||
|
* to DATA by a start conversion event and DATABUF is ready for new data.
|
||||||
|
*/
|
||||||
|
#define DAC_STATUS_CHANNEL_0_EMPTY (1UL << 0)
|
||||||
|
|
||||||
|
/** Under-run Channel 0 - Set when a start conversion event occurs when
|
||||||
|
* DATABUF is empty.
|
||||||
|
*/
|
||||||
|
#define DAC_STATUS_CHANNEL_0_UNDERRUN (1UL << 1)
|
||||||
|
|
||||||
|
/** @} */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief DAC reference voltage enum.
|
||||||
|
*
|
||||||
|
* Enum for the possible reference voltages for the DAC.
|
||||||
|
*/
|
||||||
|
enum dac_reference {
|
||||||
|
/** 1V from the internal band-gap reference.*/
|
||||||
|
DAC_REFERENCE_INT1V = DAC_CTRLB_REFSEL(0),
|
||||||
|
/** Analog V<SUB>CC</SUB> as reference. */
|
||||||
|
DAC_REFERENCE_AVCC = DAC_CTRLB_REFSEL(1),
|
||||||
|
/** External reference on AREF. */
|
||||||
|
DAC_REFERENCE_AREF = DAC_CTRLB_REFSEL(2),
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief DAC output selection enum.
|
||||||
|
*
|
||||||
|
* Enum for the DAC output selection.
|
||||||
|
*/
|
||||||
|
enum dac_output {
|
||||||
|
/** DAC output to VOUT pin */
|
||||||
|
DAC_OUTPUT_EXTERNAL = DAC_CTRLB_EOEN,
|
||||||
|
/** DAC output as internal reference */
|
||||||
|
DAC_OUTPUT_INTERNAL = DAC_CTRLB_IOEN,
|
||||||
|
/** No output */
|
||||||
|
DAC_OUTPUT_NONE = 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief DAC channel selection enum.
|
||||||
|
*
|
||||||
|
* Enum for the DAC channel selection.
|
||||||
|
*/
|
||||||
|
enum dac_channel {
|
||||||
|
/** DAC output channel 0. */
|
||||||
|
DAC_CHANNEL_0,
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief DAC software device instance structure.
|
||||||
|
*
|
||||||
|
* DAC software instance structure, used to retain software state information
|
||||||
|
* of an associated hardware module instance.
|
||||||
|
*
|
||||||
|
* \note The fields of this structure should not be altered by the user
|
||||||
|
* application; they are reserved for module-internal use only.
|
||||||
|
*/
|
||||||
|
struct dac_module {
|
||||||
|
#if !defined(__DOXYGEN__)
|
||||||
|
/** DAC hardware module. */
|
||||||
|
Dac *hw;
|
||||||
|
/** DAC output selection. */
|
||||||
|
enum dac_output output;
|
||||||
|
/** Reference selection. */
|
||||||
|
enum dac_reference reference;
|
||||||
|
/** DAC event selection. */
|
||||||
|
bool start_on_event;
|
||||||
|
# if DAC_CALLBACK_MODE == true
|
||||||
|
/** Pointer to buffer used for ADC results. */
|
||||||
|
volatile uint16_t *job_buffer;
|
||||||
|
/** Remaining number of conversions in current job. */
|
||||||
|
volatile uint16_t remaining_conversions;
|
||||||
|
/** Transferred number of conversions in current job. */
|
||||||
|
volatile uint16_t transferred_conversions;
|
||||||
|
/** DAC callback enable. */
|
||||||
|
bool callback_enable[DAC_CALLBACK_N];
|
||||||
|
/** DAC registered callback functions. */
|
||||||
|
dac_callback_t callback[DAC_CALLBACK_N];
|
||||||
|
/** Holds the status of the ongoing or last conversion job. */
|
||||||
|
volatile enum status_code job_status;
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief DAC configuration structure.
|
||||||
|
*
|
||||||
|
* Configuration structure for a DAC instance. This structure should be
|
||||||
|
* initialized by the \ref dac_get_config_defaults()
|
||||||
|
* function before being modified by the user application.
|
||||||
|
*/
|
||||||
|
struct dac_config {
|
||||||
|
/** Reference voltage. */
|
||||||
|
enum dac_reference reference;
|
||||||
|
/** Select DAC output. */
|
||||||
|
enum dac_output output;
|
||||||
|
/** Left adjusted data. */
|
||||||
|
bool left_adjust;
|
||||||
|
/** GCLK generator used to clock the peripheral. */
|
||||||
|
enum gclk_generator clock_source;
|
||||||
|
#ifdef FEATURE_DAC_DATABUF_WRITE_PROTECTION
|
||||||
|
/** Bypass DATABUF write protection. */
|
||||||
|
bool databuf_protection_bypass;
|
||||||
|
#endif
|
||||||
|
/** Voltage pump disable. */
|
||||||
|
bool voltage_pump_disable;
|
||||||
|
/**
|
||||||
|
* The DAC behaves as in normal mode when the chip enters STANDBY sleep
|
||||||
|
* mode.
|
||||||
|
*/
|
||||||
|
bool run_in_standby;
|
||||||
|
#if (SAMC21)
|
||||||
|
/** Dither mode enable data. */
|
||||||
|
bool dither_mode;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief DAC event enable/disable structure.
|
||||||
|
*
|
||||||
|
* Event flags for the DAC module. This is used to enable and
|
||||||
|
* disable events via \ref dac_enable_events() and \ref dac_disable_events().
|
||||||
|
*/
|
||||||
|
struct dac_events {
|
||||||
|
/** Start a new DAC conversion. */
|
||||||
|
bool on_event_start_conversion;
|
||||||
|
/** Enable event generation on data buffer empty. */
|
||||||
|
bool generate_event_on_buffer_empty;
|
||||||
|
#if (SAMC21)
|
||||||
|
/** Enable the falling edge of the input event for DAC1. */
|
||||||
|
bool generate_event_on_chan_falling_edge;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief DAC channel configuration structure
|
||||||
|
*
|
||||||
|
* Configuration for a DAC channel. This structure should be initialized by the
|
||||||
|
* \ref dac_chan_get_config_defaults() function before being modified by the
|
||||||
|
* user application.
|
||||||
|
*/
|
||||||
|
struct dac_chan_config {
|
||||||
|
#if !defined(__DOXYGEN__)
|
||||||
|
/** Dummy value to ensure the struct has at least one member. */
|
||||||
|
uint8_t _dummy;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \name Configuration and Initialization (Channel)
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
void dac_chan_enable_output_buffer(
|
||||||
|
struct dac_module *const dev_inst,
|
||||||
|
const enum dac_channel channel);
|
||||||
|
|
||||||
|
void dac_chan_disable_output_buffer(
|
||||||
|
struct dac_module *const dev_inst,
|
||||||
|
const enum dac_channel channel);
|
||||||
|
|
||||||
|
/** @} */
|
||||||
|
|
||||||
|
/** @} */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \page asfdoc_sam0_dac_extra Extra Information for DAC Driver
|
||||||
|
*
|
||||||
|
* \section asfdoc_sam0_dac_extra_acronyms Acronyms
|
||||||
|
* The table below presents the acronyms used in this module:
|
||||||
|
*
|
||||||
|
* <table>
|
||||||
|
* <tr>
|
||||||
|
* <th>Acronym</th>
|
||||||
|
* <th>Description</th>
|
||||||
|
* </tr>
|
||||||
|
* <tr>
|
||||||
|
* <td>ADC</td>
|
||||||
|
* <td>Analog-to-Digital Converter</td>
|
||||||
|
* </tr>
|
||||||
|
* <tr>
|
||||||
|
* <td>AC</td>
|
||||||
|
* <td>Analog Comparator</td>
|
||||||
|
* </tr>
|
||||||
|
* <tr>
|
||||||
|
* <td>DAC</td>
|
||||||
|
* <td>Digital-to-Analog Converter</td>
|
||||||
|
* </tr>
|
||||||
|
* <tr>
|
||||||
|
* <td>LSB</td>
|
||||||
|
* <td>Least Significant Bit</td>
|
||||||
|
* </tr>
|
||||||
|
* <tr>
|
||||||
|
* <td>MSB</td>
|
||||||
|
* <td>Most Significant Bit</td>
|
||||||
|
* </tr>
|
||||||
|
* <tr>
|
||||||
|
* <td>DMA</td>
|
||||||
|
* <td>Direct Memory Access</td>
|
||||||
|
* </tr>
|
||||||
|
* </table>
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* \section asfdoc_sam0_dac_extra_dependencies Dependencies
|
||||||
|
* This driver has the following dependencies:
|
||||||
|
*
|
||||||
|
* - \ref asfdoc_sam0_system_pinmux_group "System Pin Multiplexer Driver"
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* \section asfdoc_sam0_dac_extra_errata Errata
|
||||||
|
* There are no errata related to this driver.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* \section asfdoc_sam0_dac_extra_history Module History
|
||||||
|
* An overview of the module history is presented in the table below, with
|
||||||
|
* details on the enhancements and fixes made to the module since its first
|
||||||
|
* release. The current version of this corresponds to the newest version in
|
||||||
|
* the table.
|
||||||
|
*
|
||||||
|
* <table>
|
||||||
|
* <tr>
|
||||||
|
* <th>Changelog</th>
|
||||||
|
* </tr>
|
||||||
|
* <tr>
|
||||||
|
* <td>Add configuration for using 14-bit hardware dithering (SAMC21 support)</td>
|
||||||
|
* </tr>
|
||||||
|
* <tr>
|
||||||
|
* <td>Added new configuration parameters \c databuf_protection_bypass,
|
||||||
|
* \c voltage_pump_disable. Added new callback functions
|
||||||
|
* \c dac_chan_write_buffer_wait,
|
||||||
|
* \c dac_chan_write_buffer_job, \c dac_chan_write_job,
|
||||||
|
* \c dac_get_job_status, \c dac_abort_job and new callback type
|
||||||
|
* \c DAC_CALLBACK_TRANSFER_COMPLETE for DAC conversion job</td>
|
||||||
|
* </tr>
|
||||||
|
* <tr>
|
||||||
|
* <td>Initial Release</td>
|
||||||
|
* </tr>
|
||||||
|
* </table>
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \page asfdoc_sam0_dac_exqsg Examples for DAC Driver
|
||||||
|
*
|
||||||
|
* This is a list of the available Quick Start guides (QSGs) and example
|
||||||
|
* applications for \ref asfdoc_sam0_dac_group. QSGs are simple examples with
|
||||||
|
* step-by-step instructions to configure and use this driver in a selection of
|
||||||
|
* use cases. Note that a QSG can be compiled as a standalone application or be
|
||||||
|
* added to the user application.
|
||||||
|
*
|
||||||
|
* - \subpage asfdoc_sam0_dac_basic_use_case
|
||||||
|
* \if DAC_CALLBACK_MODE
|
||||||
|
* - \subpage asfdoc_sam0_dac_basic_use_case_callback
|
||||||
|
* \endif
|
||||||
|
* \if DAC_DMA_USE_MODE_SELECTION
|
||||||
|
* - \subpage asfdoc_sam0_adc_dma_use_case_dac_in_dma
|
||||||
|
* \endif
|
||||||
|
*
|
||||||
|
* \if DAC_DMA_USE_MODE_SELECTION
|
||||||
|
* \page asfdoc_sam0_adc_dma_use_case_dac_in_dma Quick Start Guide for Using DMA with ADC/DAC
|
||||||
|
* For this examples, see
|
||||||
|
* \ref asfdoc_sam0_adc_dma_use_case
|
||||||
|
* \endif
|
||||||
|
*
|
||||||
|
* \page asfdoc_sam0_dac_document_revision_history Document Revision History
|
||||||
|
*
|
||||||
|
* <table>
|
||||||
|
* <tr>
|
||||||
|
* <th>Doc. Rev.</td>
|
||||||
|
* <th>Date</td>
|
||||||
|
* <th>Comments</td>
|
||||||
|
* </tr>
|
||||||
|
* <tr>
|
||||||
|
* <td>42110E</td>
|
||||||
|
* <td>06/2015</td>
|
||||||
|
* <td>Add SAMC21 and SAMDAx support</td>
|
||||||
|
* </tr>
|
||||||
|
* <tr>
|
||||||
|
* <td>42110D</td>
|
||||||
|
* <td>12/2014</td>
|
||||||
|
* <td>Add SAMD10/D11 support</td>
|
||||||
|
* </tr>
|
||||||
|
* <tr>
|
||||||
|
* <td>42110C</td>
|
||||||
|
* <td>01/2014</td>
|
||||||
|
* <td>Add SAMD21 support</td>
|
||||||
|
* </tr>
|
||||||
|
* <tr>
|
||||||
|
* <td>42110B</td>
|
||||||
|
* <td>06/2013</td>
|
||||||
|
* <td>Added additional documentation on the event system. Corrected
|
||||||
|
* documentation typos.</td>
|
||||||
|
* </tr>
|
||||||
|
* <tr>
|
||||||
|
* <td>42110A</td>
|
||||||
|
* <td>06/2013</td>
|
||||||
|
* <td>Initial document release</td>
|
||||||
|
* </tr>
|
||||||
|
* </table>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* DAC_FEATURE_H_INCLUDED */
|
||||||
|
|
|
@ -28,6 +28,10 @@
|
||||||
#include "i2c_slave.h"
|
#include "i2c_slave.h"
|
||||||
#include "dma_api.h"
|
#include "dma_api.h"
|
||||||
|
|
||||||
|
#if DEVICE_ANALOGOUT
|
||||||
|
#include "dac.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
@ -69,10 +73,16 @@ struct serial_s {
|
||||||
|
|
||||||
struct analogin_s {
|
struct analogin_s {
|
||||||
ADCName adc;
|
ADCName adc;
|
||||||
struct adc_module adc_instance;
|
|
||||||
struct adc_config config_adc;
|
struct adc_config config_adc;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#if DEVICE_ANALOGOUT
|
||||||
|
struct dac_s {
|
||||||
|
DACName dac;
|
||||||
|
struct dac_config config_dac;
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
struct pwmout_s {
|
struct pwmout_s {
|
||||||
struct tcc_module tcc;
|
struct tcc_module tcc;
|
||||||
PinName pin;
|
PinName pin;
|
||||||
|
|
Loading…
Reference in New Issue