Merge pull request #1316 from kpurusho/master

Drivers for SAMD21
pull/1323/head
Martin Kojtal 2015-09-07 09:46:11 +01:00
commit 748fea3057
39 changed files with 2623 additions and 30 deletions

View File

@ -22,8 +22,11 @@ extern "C" {
typedef enum {
PortA = 0,
PortB = 1,
PortC = 2
PortB,
#if defined(TARGET_SAMR21G18A)
PortC,
#endif
PortMax
} PortName;
#ifdef __cplusplus

View File

@ -0,0 +1,158 @@
/* mbed Microcontroller Library
* Copyright (c) 2006-2013 ARM Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef MBED_PERIPHERALNAMES_H
#define MBED_PERIPHERALNAMES_H
#include <compiler.h>
#include "cmsis.h"
#include "PinNames.h"
#ifdef __cplusplus
extern "C" {
#endif
#define _SERCOM_SPI_NAME(n, unused) \
SPI##n,
#define _SERCOM_PAD_NAME(n, pad) \
SERCOM##n##_PAD##pad = ((n & 0xF) | ((pad & 0xF) << 4)),
#define _SERCOM_I2C_NAME(n, unused) \
I2C##n,
typedef enum {
UART_0 = (int)0x42000800UL, // Base address of SERCOM0
UART_1 = (int)0x42000C00UL, // Base address of SERCOM1
UART_2 = (int)0x42001000UL, // Base address of SERCOM2
UART_3 = (int)0x42001400UL, // Base address of SERCOM3
UART_4 = (int)0x42001800UL, // Base address of SERCOM4
UART_5 = (int)0x42001C00UL // Base address of SERCOM5
} UARTName;
typedef enum {
ADC_0 = 0x0ul,
ADC_1 = 0x1ul,
ADC_2 = 0x2ul,
ADC_3 = 0x3ul,
ADC_4 = 0x4ul,
ADC_5 = 0x5ul,
ADC_6 = 0x6ul,
ADC_7 = 0x7ul,
ADC_8 = 0x8ul,
ADC_9 = 0x8ul,
ADC_10 = 0xAul,
ADC_11 = 0xBul,
ADC_12 = 0xCul,
ADC_13 = 0xDul,
ADC_14 = 0xEul,
ADC_15 = 0xFul,
ADC_16 = 0x10ul,
ADC_17 = 0x11ul,
ADC_18 = 0x12ul,
ADC_19 = 0x13ul
} ADCName;
typedef enum {
DAC_0 = 0x42004800UL
} DACName;
typedef enum { // for each channel
EXTINT_0 = 0,
EXTINT_1,
EXTINT_2,
EXTINT_3,
EXTINT_4,
EXTINT_5,
EXTINT_6,
EXTINT_7,
EXTINT_8,
EXTINT_9,
EXTINT_10,
EXTINT_11,
EXTINT_12,
EXTINT_13,
EXTINT_14,
EXTINT_15
} EXTINTName;
typedef enum {
MREPEAT(SERCOM_INST_NUM, _SERCOM_SPI_NAME, ~)
} SPIName;
typedef enum {
MREPEAT(SERCOM_INST_NUM, _SERCOM_I2C_NAME, ~)
} I2CName;
typedef enum {
/* Pad 0 definitions */
MREPEAT(SERCOM_INST_NUM, _SERCOM_PAD_NAME, 0)
/* Pad 1 definitions */
MREPEAT(SERCOM_INST_NUM, _SERCOM_PAD_NAME, 1)
/* Pad 2 definitions */
MREPEAT(SERCOM_INST_NUM, _SERCOM_PAD_NAME, 2)
/* Pad 3 definitions */
MREPEAT(SERCOM_INST_NUM, _SERCOM_PAD_NAME, 3)
} SercomPadName;
typedef enum {
PWM_0 = (0x42002000UL), /**< \brief (TCC0) APB Base Address */
PWM_1 = (0x42002400UL), /**< \brief (TCC1) APB Base Address */
PWM_2 = (0x42002800UL), /**< \brief (TCC2) APB Base Address */
} PWMName;
struct pwm_pin_channel {
PinName pin;
PWMName pwm;
uint8_t channel_index;
};
#define STDIO_UART_TX USBTX
#define STDIO_UART_RX USBRX
#define STDIO_UART UART_3
// Default peripherals
#define MBED_SPI0 PA18, PA16, PA19, PA17
#define MBED_UART0 PA04, PA05
#define MBED_UARTUSB USBTX, USBRX
#define MBED_I2C0 PA08, PA09
#define MBED_ANALOGOUT0 PA02
#define MBED_ANALOGIN0 PA03
#define MBED_ANALOGIN1 PA08
#define MBED_ANALOGIN2 PB09
#define MBED_ANALOGIN3 PA04
#define MBED_ANALOGIN4 PA05
#define MBED_ANALOGIN5 PA06
#define MBED_ANALOGIN7 PA07
#define MBED_ANALOGIN8 PB00
#define MBED_ANALOGIN9 PB01
#define MBED_PWMOUT0 PA18
#define MBED_PWMOUT1 PA19
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,286 @@
/* mbed Microcontroller Library
* Copyright (c) 2006-2013 ARM Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "PeripheralPins.h"
/************ADC***************/
const PinMap PinMap_ADC[] = {
{PA02, ADC_0, 1},
{PA03, ADC_1, 1},
{PB08, ADC_2, 1},
{PB09, ADC_3, 1},
{PA04, ADC_4, 1},
{PA05, ADC_5, 1},
{PA06, ADC_6, 1},
{PA07, ADC_7, 1},
{PB00, ADC_8, 1},
{PB01, ADC_9, 1},
{PB02, ADC_10, 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},
{PA09, ADC_17, 1},
{PA10, ADC_18, 1},
{PA11, ADC_19, 1},
/* Not connected */
{NC , NC , NC}
};
/************DAC***************/
const PinMap PinMap_DAC[] = {
{PA02, DAC_0, 1},
/* Not connected */
{NC , NC , NC}
};
/************SERCOM Pins***********/
const PinMap PinMap_SERCOM_PAD[] = {
{PA00, SERCOM1_PAD0, 3},
{PA01, SERCOM1_PAD1, 3},
{PA04, SERCOM0_PAD0, 3},
{PA05, SERCOM0_PAD1, 3},
{PA06, SERCOM0_PAD2, 3},
{PA07, SERCOM0_PAD3, 3},
{PA08, SERCOM0_PAD0, 2},
{PA09, SERCOM0_PAD1, 2},
{PA10, SERCOM0_PAD2, 2},
{PA11, SERCOM0_PAD3, 2},
{PA12, SERCOM2_PAD0, 2},
{PA13, SERCOM2_PAD1, 2},
{PA14, SERCOM2_PAD2, 2},
{PA15, SERCOM2_PAD3, 2},
{PA16, SERCOM1_PAD0, 2},
{PA17, SERCOM1_PAD1, 2},
{PA18, SERCOM1_PAD2, 2},
{PA19, SERCOM1_PAD3, 2},
{PA20, SERCOM3_PAD2, 3},
{PA21, SERCOM3_PAD3, 3},
{PA22, SERCOM3_PAD0, 2},
{PA23, SERCOM3_PAD1, 2},
{PA24, SERCOM3_PAD2, 2},
{PA25, SERCOM3_PAD3, 2},
{PA30, SERCOM1_PAD2, 3},
{PA31, SERCOM1_PAD3, 3},
{PB00, SERCOM5_PAD2, 3},
{PB01, SERCOM5_PAD3, 3},
{PB02, SERCOM5_PAD0, 3},
{PB03, SERCOM5_PAD1, 3},
{PB08, SERCOM4_PAD0, 3},
{PB09, SERCOM4_PAD1, 3},
{PB10, SERCOM4_PAD2, 3},
{PB11, SERCOM4_PAD3, 3},
{PB12, SERCOM4_PAD0, 2},
{PB13, SERCOM4_PAD1, 2},
{PB14, SERCOM4_PAD2, 2},
{PB15, SERCOM4_PAD3, 2},
{PB16, SERCOM5_PAD0, 2},
{PB17, SERCOM5_PAD1, 2},
{PB22, SERCOM5_PAD2, 3},
{PB23, SERCOM5_PAD3, 3},
{PB30, SERCOM5_PAD0, 3},
{PB31, SERCOM5_PAD1, 3},
/* Not connected */
{NC , NC , NC}
};
/*******SERCOM Pins extended*******/
const PinMap PinMap_SERCOM_PADEx[] = {
{PA08, SERCOM2_PAD0, 3},
{PA09, SERCOM2_PAD1, 3},
{PA10, SERCOM2_PAD2, 3},
{PA11, SERCOM2_PAD3, 3},
{PA12, SERCOM4_PAD0, 3},
{PA13, SERCOM4_PAD1, 3},
{PA14, SERCOM4_PAD2, 3},
{PA15, SERCOM4_PAD3, 3},
{PA16, SERCOM3_PAD0, 3},
{PA17, SERCOM3_PAD1, 3},
{PA18, SERCOM3_PAD2, 3},
{PA19, SERCOM3_PAD3, 3},
{PA20, SERCOM5_PAD2, 2},
{PA21, SERCOM5_PAD3, 2},
{PA22, SERCOM5_PAD0, 3},
{PA23, SERCOM5_PAD1, 3},
{PA24, SERCOM5_PAD2, 3},
{PA25, SERCOM5_PAD3, 3},
/* Not connected */
{NC , NC , NC}
};
/************PWM***************/
const PinMap PinMap_PWM[] = {
{PA00, PWM_2, 4},
{PA01, PWM_2, 4},
{PA04, PWM_0, 4},
{PA05, PWM_0, 4},
{PA06, PWM_1, 4},
{PA07, PWM_1, 4},
{PA08, PWM_1, 5},
{PA09, PWM_1, 5},
{PA10, PWM_1, 4},
{PA11, PWM_1, 4},
{PA12, PWM_2, 4},
{PA13, PWM_2, 4},
{PA14, PWM_0, 5},
{PA15, PWM_0, 5},
{PA16, PWM_2, 4},
{PA17, PWM_2, 4},
{PA18, PWM_0, 5},
{PA19, PWM_0, 5},
{PA20, PWM_0, 5},
{PA21, PWM_0, 5},
{PA22, PWM_0, 5},
{PA23, PWM_0, 5},
{PA24, PWM_1, 5},
{PA25, PWM_1, 5},
{PA30, PWM_1, 4},
{PA31, PWM_1, 4},
{PB10, PWM_0, 5},
{PB11, PWM_0, 5},
{PB12, PWM_0, 5},
{PB13, PWM_0, 5},
{PB16, PWM_0, 5},
{PB17, PWM_0, 5},
{PB30, PWM_1, 5},
{PB31, PWM_1, 5},
/* Not connected */
{NC , NC , NC}
};
/**********EXTINT*************/
const PinMap PinMap_EXTINT[] = {
{PA16, EXTINT_0, 0},
{PB00, EXTINT_0, 0},
{PB16, EXTINT_0, 0},
{PA00, EXTINT_0, 0},
{PA17, EXTINT_1, 0},
{PB01, EXTINT_1, 0},
{PB17, EXTINT_1, 0},
{PA01, EXTINT_1, 0},
{PA18, EXTINT_2, 0},
{PA02, EXTINT_2, 0},
{PB02, EXTINT_2, 0},
{PA03, EXTINT_3, 0},
{PA19, EXTINT_3, 0},
{PB03, EXTINT_3, 0},
{PA04, EXTINT_4, 0},
{PA20, EXTINT_4, 0},
{PB04, EXTINT_4, 0},
{PA05, EXTINT_5, 0},
{PA21, EXTINT_5, 0},
{PB05, EXTINT_5, 0},
{PA06, EXTINT_6, 0},
{PA22, EXTINT_6, 0},
{PB06, EXTINT_6, 0},
{PB22, EXTINT_6, 0},
{PA07, EXTINT_7, 0},
{PA23, EXTINT_7, 0},
{PB07, EXTINT_7, 0},
{PB23, EXTINT_7, 0},
{PA28, EXTINT_8, 0},
{PB08, EXTINT_8, 0},
{PA09, EXTINT_9, 0},
{PB09, EXTINT_9, 0},
{PA10, EXTINT_10, 0},
{PA30, EXTINT_10, 0},
{PB10, EXTINT_10, 0},
{PA11, EXTINT_11, 0},
{PA31, EXTINT_11, 0},
{PB11, EXTINT_11, 0},
{PA12, EXTINT_12, 0},
{PA24, EXTINT_12, 0},
{PB12, EXTINT_12, 0},
{PA13, EXTINT_13, 0},
{PA25, EXTINT_13, 0},
{PB13, EXTINT_13, 0},
{PB14, EXTINT_14, 0},
{PB30, EXTINT_14, 0},
{PA14, EXTINT_14, 0},
{PA15, EXTINT_15, 0},
{PA27, EXTINT_15, 0},
{PB15, EXTINT_15, 0},
{PB31, EXTINT_15, 0},
/* Not connected */
{NC , NC , NC}
};
const struct pwm_pin_channel pwn_pins[] = {
{PA00, PWM_2, 0},
{PA01, PWM_2, 1},
{PA04, PWM_0, 0},
{PA05, PWM_0, 1},
{PA06, PWM_1, 0},
{PA07, PWM_1, 1},
{PA08, PWM_1, 2},
{PA09, PWM_1, 3},
{PA10, PWM_1, 0},
{PA11, PWM_1, 1},
{PA12, PWM_2, 0},
{PA13, PWM_2, 1},
{PA14, PWM_0, 4},
{PA15, PWM_0, 5},
{PA16, PWM_2, 0},
{PA17, PWM_2, 1},
{PA18, PWM_0, 2},
{PA19, PWM_0, 3},
{PA20, PWM_0, 6},
{PA21, PWM_0, 7},
{PA22, PWM_0, 4},
{PA23, PWM_0, 5},
{PA24, PWM_1, 2},
{PA25, PWM_1, 3},
{PA30, PWM_1, 0},
{PA31, PWM_1, 1},
{PB10, PWM_0, 4},
{PB11, PWM_0, 5},
{PB12, PWM_0, 6},
{PB13, PWM_0, 7},
{PB16, PWM_0, 4},
{PB17, PWM_0, 5},
{PB30, PWM_1, 2},
{PB31, PWM_1, 3},
/* Not connected */
{NC , NC , NC}
};

View File

@ -0,0 +1,40 @@
/* mbed Microcontroller Library
* Copyright (c) 2006-2013 ARM Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef MBED_PERIPHERALPINS_H
#define MBED_PERIPHERALPINS_H
#include "pinmap.h"
#include "PeripheralNames.h"
/************ADC***************/
extern const PinMap PinMap_ADC[];
/************DAC***************/
extern const PinMap PinMap_DAC[];
/*********SERCOM*************/
extern const PinMap PinMap_SERCOM_PAD[];
extern const PinMap PinMap_SERCOM_PADEx[];
/************PWM***************/
extern const PinMap PinMap_PWM[];
/**********EXTINT*************/
extern const PinMap PinMap_EXTINT[];
#endif

View File

@ -0,0 +1,109 @@
/* mbed Microcontroller Library
* Copyright (c) 2013 Nordic Semiconductor
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef MBED_PINNAMES_H
#define MBED_PINNAMES_H
#include "cmsis.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef enum {
PIN_INPUT,
PIN_OUTPUT,
PIN_INPUT_OUTPUT //pin state can be set and read back
} PinDirection;
typedef enum {
PA00 = 0,
PA01 = 1,
PA02 = 2,
PA03 = 3,
PA04 = 4,
PA05 = 5,
PA06 = 6,
PA07 = 7,
PA08 = 8,
PA09 = 9,
PA10 = 10,
PA11 = 11,
PA12 = 12,
PA13 = 13,
PA14 = 14,
PA15 = 15,
PA16 = 16,
PA17 = 17,
PA18 = 18,
PA19 = 19,
PA20 = 20,
PA21 = 21,
PA22 = 22,
PA23 = 23,
PA24 = 24,
PA25 = 25,
PA27 = 27,
PA28 = 28,
PA30 = 30,
PA31 = 31,
PB00 = 32,
PB01 = 33,
PB02 = 34,
PB03 = 35,
PB04 = 36,
PB05 = 37,
PB06 = 38,
PB07 = 39,
PB08 = 40,
PB09 = 41,
PB10 = 42,
PB11 = 43,
PB12 = 44,
PB13 = 45,
PB14 = 46,
PB15 = 47,
PB16 = 48,
PB17 = 49,
PB22 = 54,
PB23 = 55,
PB30 = 62,
PB31 = 63,
USBTX = PA22,
USBRX = PA23,
LED1 = PB30,
LED2 = PB30,
LED3 = PB30,
LED4 = PB30,
// Not connected
NC = (int)0xFFFFFFFF
} PinName;
typedef enum {
PullNone = 0,
PullUp = 1,
PullDown = 2,
PullDefault = PullUp
} PinMode;
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,110 @@
/* mbed Microcontroller Library
* Copyright (c) 2006-2013 ARM Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "mbed_assert.h"
#include "analogout_api.h"
#include "cmsis.h"
#include "pinmap.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)
{
MBED_ASSERT(obj);
if (g_sys_init == 0) {
system_init();
g_sys_init = 1;
}
struct dac_config config_dac;
struct dac_chan_config config_dac_chan;
uint32_t pos_input;
pos_input = pinmap_find_peripheral(pin, PinMap_DAC);
MBED_ASSERT(pos_input != NC);
obj->dac = DAC_0;
dac_get_config_defaults(&config_dac);
dac_init(&dac_instance, (Dac *)DAC_0, &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);
}
void analogout_free(dac_t *obj)
{
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); /*PA02 is the only DAC pin available*/
}
void analogout_write(dac_t *obj, float value)
{
MBED_ASSERT(obj);
uint16_t count_val = 0;
if (value < 0.0f) {
count_val = 0;
} else if (value > 1.0f) {
count_val = MAX_VAL_10BIT;
} else {
count_val = (uint16_t)(value * (float)MAX_VAL_10BIT);
}
dac_chan_write(&dac_instance, DAC_CHANNEL_0, count_val);
}
void analogout_write_u16(dac_t *obj, uint16_t value)
{
MBED_ASSERT(obj);
uint16_t count_val;
count_val = (uint16_t)((value * (float)MAX_VAL_10BIT) / 0xFFFF); /*Normalization to the value 0xFFFF*/
dac_chan_write(&dac_instance, DAC_CHANNEL_0, count_val);
}
static uint32_t data_reg_read(dac_t *obj)
{
Dac *const dac_module = (Dac *)obj->dac;
return (uint32_t)dac_module->DATA.reg;
}
float analogout_read(dac_t *obj)
{
MBED_ASSERT(obj);
uint32_t data_val = data_reg_read(obj);
return data_val/(float)MAX_VAL_10BIT;
}
uint16_t analogout_read_u16(dac_t *obj)
{
MBED_ASSERT(obj);
uint32_t data_val = data_reg_read(obj);
return (uint16_t)((data_val / (float)MAX_VAL_10BIT) * 0xFFFF); /*Normalization to the value 0xFFFF*/
}

View File

@ -23,14 +23,15 @@
#define DEVICE_INTERRUPTIN 1
#define DEVICE_ANALOGIN 1
#define DEVICE_ANALOGOUT 0
#define DEVICE_ANALOGOUT 1
#define DEVICE_SERIAL 1
#define DEVICE_SERIAL_FC 1
#define DEVICE_SERIAL_ASYNCH 1
#define DEVICE_I2C 0
#define DEVICE_I2CSLAVE 0
#define DEVICE_I2C 1
#define DEVICE_I2CSLAVE 1
#define DEVICE_I2C_ASYNCH 1
#define DEVICE_SPI 1
#define DEVICE_SPISLAVE 1

View File

@ -161,10 +161,9 @@ void analogin_init(analogin_t *obj, PinName pin)
adc_init(&adc_instance, ADC, &(obj->config_adc));
adc_enable(&adc_instance);
init_flag = 1;
} else { // pin muxing
adc_configure_ain_pin(obj->config_adc.positive_input);
adc_configure_ain_pin(obj->config_adc.negative_input);
}
adc_configure_ain_pin(obj->config_adc.positive_input);
adc_configure_ain_pin(obj->config_adc.negative_input);
}
uint16_t analogin_read_u16(analogin_t *obj)

View File

@ -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 */

View File

@ -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;
}

View File

@ -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&reg; | SMART ARM&reg;-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 */

View File

@ -0,0 +1,195 @@
/**
* \file
*
* \brief SAM D21 System Interrupt Driver
*
* Copyright (C) 2013-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 SYSTEM_INTERRUPT_FEATURES_H_INCLUDED
#define SYSTEM_INTERRUPT_FEATURES_H_INCLUDED
#if !defined(__DOXYGEN__)
/* Generates a interrupt vector table enum list entry for a given module type
and index (e.g. "SYSTEM_INTERRUPT_MODULE_TC0 = TC0_IRQn,"). */
# define _MODULE_IRQn(n, module) \
SYSTEM_INTERRUPT_MODULE_##module##n = module##n##_IRQn,
/* Generates interrupt vector table enum list entries for all instances of a
given module type on the selected device. */
# define _SYSTEM_INTERRUPT_MODULES(name) \
MREPEAT(name##_INST_NUM, _MODULE_IRQn, name)
# define _SYSTEM_INTERRUPT_IPSR_MASK 0x0000003f
# define _SYSTEM_INTERRUPT_PRIORITY_MASK 0x00000003
# define _SYSTEM_INTERRUPT_EXTERNAL_VECTOR_START 0
# define _SYSTEM_INTERRUPT_SYSTICK_PRI_POS 30
#endif
/**
* \addtogroup asfdoc_sam0_system_interrupt_group
* @{
*/
/**
* \brief Table of possible system interrupt/exception vector numbers.
*
* Table of all possible interrupt and exception vector indexes within the
* SAMD21 device. Check peripherals configuration in SAMD21 datasheet for
* available vector index for specific device.
*
*/
#if defined(__DOXYGEN__)
/** \note The actual enumeration name is "system_interrupt_vector". */
enum system_interrupt_vector_samd21 {
#else
enum system_interrupt_vector {
#endif
/** Interrupt vector index for a NMI interrupt. */
SYSTEM_INTERRUPT_NON_MASKABLE = NonMaskableInt_IRQn,
/** Interrupt vector index for a Hard Fault memory access exception. */
SYSTEM_INTERRUPT_HARD_FAULT = HardFault_IRQn,
/** Interrupt vector index for a Supervisor Call exception. */
SYSTEM_INTERRUPT_SV_CALL = SVCall_IRQn,
/** Interrupt vector index for a Pending Supervisor interrupt. */
SYSTEM_INTERRUPT_PENDING_SV = PendSV_IRQn,
/** Interrupt vector index for a System Tick interrupt. */
SYSTEM_INTERRUPT_SYSTICK = SysTick_IRQn,
/** Interrupt vector index for a Power Manager peripheral interrupt. */
SYSTEM_INTERRUPT_MODULE_PM = PM_IRQn,
/** Interrupt vector index for a System Control peripheral interrupt. */
SYSTEM_INTERRUPT_MODULE_SYSCTRL = SYSCTRL_IRQn,
/** Interrupt vector index for a Watch Dog peripheral interrupt. */
SYSTEM_INTERRUPT_MODULE_WDT = WDT_IRQn,
/** Interrupt vector index for a Real Time Clock peripheral interrupt. */
SYSTEM_INTERRUPT_MODULE_RTC = RTC_IRQn,
/** Interrupt vector index for an External Interrupt peripheral interrupt. */
SYSTEM_INTERRUPT_MODULE_EIC = EIC_IRQn,
/** Interrupt vector index for a Non Volatile Memory Controller interrupt. */
SYSTEM_INTERRUPT_MODULE_NVMCTRL = NVMCTRL_IRQn,
/** Interrupt vector index for a Direct Memory Access interrupt. */
SYSTEM_INTERRUPT_MODULE_DMA = DMAC_IRQn,
#if defined(__DOXYGEN__) || defined(ID_USB)
/** Interrupt vector index for a Universal Serial Bus interrupt. */
SYSTEM_INTERRUPT_MODULE_USB = USB_IRQn,
#endif
/** Interrupt vector index for an Event System interrupt. */
SYSTEM_INTERRUPT_MODULE_EVSYS = EVSYS_IRQn,
#if defined(__DOXYGEN__)
/** Interrupt vector index for a SERCOM peripheral interrupt.
*
* Each specific device may contain several SERCOM peripherals; each module
* instance will have its own entry in the table, with the instance number
* substituted for "n" in the entry name (e.g.
* \c SYSTEM_INTERRUPT_MODULE_SERCOM0).
*/
SYSTEM_INTERRUPT_MODULE_SERCOMn = SERCOMn_IRQn,
/** Interrupt vector index for a Timer/Counter Control peripheral interrupt.
*
* Each specific device may contain several TCC peripherals; each module
* instance will have its own entry in the table, with the instance number
* substituted for "n" in the entry name (e.g.
* \c SYSTEM_INTERRUPT_MODULE_TCC0).
*/
SYSTEM_INTERRUPT_MODULE_TCCn = TCCn_IRQn,
/** Interrupt vector index for a Timer/Counter peripheral interrupt.
*
* Each specific device may contain several TC peripherals; each module
* instance will have its own entry in the table, with the instance number
* substituted for "n" in the entry name (e.g.
* \c SYSTEM_INTERRUPT_MODULE_TC3).
*/
SYSTEM_INTERRUPT_MODULE_TCn = TCn_IRQn,
#else
_SYSTEM_INTERRUPT_MODULES(SERCOM)
_SYSTEM_INTERRUPT_MODULES(TCC)
SYSTEM_INTERRUPT_MODULE_TC3 = TC3_IRQn,
SYSTEM_INTERRUPT_MODULE_TC4 = TC4_IRQn,
SYSTEM_INTERRUPT_MODULE_TC5 = TC5_IRQn,
# if defined(ID_TC6)
SYSTEM_INTERRUPT_MODULE_TC6 = TC6_IRQn,
# endif
# if defined(ID_TC7)
SYSTEM_INTERRUPT_MODULE_TC7 = TC7_IRQn,
# endif
#endif
#if defined(__DOXYGEN__) || defined(ID_ADC)
/** Interrupt vector index for an Analog-to-Digital peripheral interrupt. */
SYSTEM_INTERRUPT_MODULE_ADC = ADC_IRQn,
#endif
#if defined(__DOXYGEN__) || defined(ID_AC)
/** Interrupt vector index for an Analog Comparator peripheral interrupt. */
SYSTEM_INTERRUPT_MODULE_AC = AC_IRQn,
#endif
#if defined(__DOXYGEN__) || defined(ID_DAC)
/** Interrupt vector index for a Digital-to-Analog peripheral interrupt. */
SYSTEM_INTERRUPT_MODULE_DAC = DAC_IRQn,
#endif
#if defined(__DOXYGEN__) || defined(ID_PTC)
/** Interrupt vector index for a Peripheral Touch Controller peripheral
* interrupt. */
SYSTEM_INTERRUPT_MODULE_PTC = PTC_IRQn,
#endif
#if defined(__DOXYGEN__) || defined(ID_I2S)
/** Interrupt vector index for a Inter-IC Sound Interface peripheral
* interrupt. */
SYSTEM_INTERRUPT_MODULE_I2S = I2S_IRQn,
#endif
#if defined(__DOXYGEN__) || defined(ID_AC1)
/** Interrupt vector index for an Analog Comparator 1 peripheral interrupt. */
SYSTEM_INTERRUPT_MODULE_AC1 = AC1_IRQn,
#endif
};
/** @} */
#endif

View File

@ -28,6 +28,10 @@
#include "i2c_slave.h"
#include "dma_api.h"
#if DEVICE_ANALOGOUT
#include "dac.h"
#endif
#ifdef __cplusplus
extern "C" {
#endif
@ -69,10 +73,15 @@ struct serial_s {
struct analogin_s {
ADCName adc;
struct adc_module adc_instance;
struct adc_config config_adc;
};
#if DEVICE_ANALOGOUT
struct dac_s {
DACName dac;
};
#endif
struct pwmout_s {
struct tcc_module tcc;
PinName pin;

View File

@ -18,15 +18,18 @@
#include "gpio_api.h"
#include "port.h"
#if defined(TARGET_SAMR21G18A) // mask to be define for other targets
#if defined(TARGET_SAMR21G18A)
#define PORTA_MASK 0xDBDFFFF3 // mask for available pins in Port A
#define PORTB_MASK 0xC0C3C30D // mask for available pins in Port B
#define PORTC_MASK 0x000D0000 // mask for available pins in Port C
#elif defined(TARGET_SAMD21J18A)
#define PORTA_MASK 0xDBFFFFFF // mask for available pins in Port A
#define PORTB_MASK 0xC0C3FFFF // mask for available pins in Port B
#endif
uint32_t start_pin(PortName port)
{
if(port <= 2) { /* PortC value is 2*/
if(port < PortMax) { /* PortC value is 2*/
return port * 32;
} else {
return NC;
@ -63,9 +66,11 @@ void port_init(port_t *obj, PortName port, int mask, PinDirection dir)
case PortB:
obj->mask = (uint32_t)mask & PORTB_MASK;
break;
#if defined(TARGET_SAMR21G18A)
case PortC:
obj->mask = (uint32_t)mask & PORTC_MASK;
break;
#endif
default:
return;
}

View File

@ -133,10 +133,9 @@ uint32_t serial_find_mux_settings (serial_t *obj)
if ((pSERIAL_S(obj)->pins[USART_RXFLOW_INDEX] == NC) && (pSERIAL_S(obj)->pins[USART_TXFLOW_INDEX] == NC)) {
if (pinpad[USART_TX_INDEX] == 0) {
mux_setting |= SERCOM_USART_CTRLA_TXPO(0);
} else if(pinpad[USART_RX_INDEX] == 2) {
} else if(pinpad[USART_TX_INDEX] == 2) {
mux_setting |= SERCOM_USART_CTRLA_TXPO(1);
} else {
mux_setting = mux_setting; // dummy condition
}
} else { // for hardware flow control and uart // expecting the tx in pad 0, rts in pad2 and cts in pad 3
if((pinpad[USART_TX_INDEX] == 0) && (pinpad[USART_RXFLOW_INDEX]/*rts pin*/ == 2) && (pinpad[USART_TXFLOW_INDEX] /*cts pin*/ == 3)) {

View File

@ -54,6 +54,10 @@ AnalogOut out(PA_5);
AnalogIn in(AIN_7P);
AnalogOut out(AOUT_DO);
#elif defined(TARGET_SAMD21J18A)
AnalogIn in(PA04);
AnalogOut out(PA02);
#else
AnalogIn in(p17);
AnalogOut out(p18);

View File

@ -5,6 +5,10 @@
BusOut bus1(PA06, PA07, PA13, PA28, PA18, PA19, PA22, PA23, PA16, PA17, PA05, PA04);
BusOut bus2(PB03, PB22, PB02, PB23);
#elif defined(TARGET_SAMD21J18A)
BusOut bus1(PA06, PA07, PA13, PA28, PA18, PA19, PA22, PA23, PA16, PA17, PA05, PA04);
BusOut bus2(PB03, PB22, PB02, PB23);
#else
BusOut bus1(D0, D1, D2, D3, D4, D5, D6, D7, D8, D9, D10, D11, D12, D13, D14, D15);
BusOut bus2(A5, A4, A3, A2, A1, A0);

View File

@ -58,7 +58,7 @@ DigitalIn in(PC1);
DigitalOut out(PE10);
DigitalIn in(PC1);
#elif defined(TARGET_SAMR21G18A)
#elif defined(TARGET_SAMR21G18A) || defined(TARGET_SAMD21J18A)
DigitalOut out(PA06);
DigitalIn in(PA07);

View File

@ -58,7 +58,7 @@ DigitalInOut d2(PC1);
DigitalInOut d1(PE10);
DigitalInOut d2(PC1);
#elif defined(TARGET_SAMR21G18A)
#elif defined(TARGET_SAMR21G18A) || defined(TARGET_SAMD21J18A)
DigitalInOut d1(PA06);
DigitalInOut d2(PA07);

View File

@ -14,6 +14,13 @@
#define FLOW_CONTROL_CTS PA07
#define RTS_CHECK_PIN PB03
#elif defined(TARGET_SAMD21J18A)
#define UART_TX PA22
#define UART_RX PA23
#define FLOW_CONTROL_RTS PA24
#define FLOW_CONTROL_CTS PA25
#define RTS_CHECK_PIN PB03
#else
#error This test is not supported on this target
#endif

View File

@ -26,6 +26,10 @@ I2C i2c(TEST_SDA_PIN, TEST_SCL_PIN);
#define TEST_SDA_PIN PA16
#define TEST_SCL_PIN PA17
I2C i2c(TEST_SDA_PIN, TEST_SCL_PIN);
#elif defined(TARGET_SAMD21J18A)
#define TEST_SDA_PIN PA08
#define TEST_SCL_PIN PA09
I2C i2c(TEST_SDA_PIN, TEST_SCL_PIN);
#else
I2C i2c(p28, p27);
#endif

View File

@ -10,6 +10,8 @@ I2CSlave slave(PTE0, PTE1);
I2CSlave slave(p9, p10);
#elif defined(TARGET_SAMR21G18A)
I2CSlave slave(PA16, PA17);
#elif defined(TARGET_SAMD21J18A)
I2CSlave slave(PA08, PA09);
#else
I2CSlave slave(p28, p27);
#endif

View File

@ -11,7 +11,7 @@
#define TIMER_IRQ LPTimer_IRQn
#elif defined(TARGET_LPC2368) || defined(TARGET_LPC2460)
#define TIMER_IRQ TIMER3_IRQn
#elif defined(TARGET_SAMR21G18A)
#elif defined(TARGET_SAMR21G18A) || defined(TARGET_SAMD21J18A)
#define TIMER_IRQ TC4_IRQn
#else
#error This test can't run on this target.

View File

@ -87,7 +87,7 @@ void in_handler() {
#define PIN_OUT PE10
#define PIN_IN PC1
#elif defined(TARGET_SAMR21G18A)
#elif defined(TARGET_SAMR21G18A) || defined(TARGET_SAMD21J18A)
#define PIN_OUT PA06
#define PIN_IN PA07

View File

@ -42,6 +42,20 @@ InterruptIn button9(PA15);
DigitalOut led(LED1);
DigitalOut flash(PA22); /*1 LED Available*/
#elif defined(TARGET_SAMD21J18A)
InterruptIn button (PA15); /*SW0*/
InterruptIn button1(PA16);
InterruptIn button2(PB01);
InterruptIn button3(PA18);
InterruptIn button4(PA03);
InterruptIn button5(PA04);
InterruptIn button6(PA05);
InterruptIn button7(PA06);
InterruptIn button8(PA07);
InterruptIn button9(PA28);
DigitalOut led(LED1);
DigitalOut flash(PA27); /*1 LED Available*/
#else
InterruptIn button(p30);
InterruptIn button1(p29);

View File

@ -1,6 +1,6 @@
#include "mbed.h"
#if defined(TARGET_SAMR21G18A)
#if defined(TARGET_SAMR21G18A) || defined(TARGET_SAMD21J18A)
DigitalOut out(PA06);
#else
DigitalOut out(p5);

View File

@ -129,13 +129,13 @@
#define P2_2 (1 << 2) // PC2
#define PORT_2 PortC
#elif defined(TARGET_SAMR21G18A)
#elif defined(TARGET_SAMR21G18A) || defined(TARGET_SAMD21J18A)
#define P1_1 (1 << 6) /*PA06*/
#define P1_2 (1 << 7) /*PA07*/
#define PORT_1 PortA
#define P2_1 (1 << 2) /*PA02*/
#define P2_2 (1 << 3) /*PA03*/
#define P2_1 (1 << 2) /*PB02*/
#define P2_2 (1 << 3) /*PB03*/
#define PORT_2 PortB
#endif

View File

@ -30,6 +30,12 @@
# define LED2 0
# define LED3 0
# define LED4 0
# elif defined(TARGET_SAMD21J18A)
# define LED_PORT PortB
# define LED1 (1 << 30) /*PB30*/
# define LED2 0
# define LED3 0
# define LED4 0
# endif
#define LED_MASK (LED1|LED2|LED3|LED4)

View File

@ -129,13 +129,13 @@
#define P2_2 (1 << 2) // PC2
#define PORT_2 PortC
#elif defined(TARGET_SAMR21G18A)
#elif defined(TARGET_SAMR21G18A) || defined(TARGET_SAMD21J18A)
#define P1_1 (1 << 6) /*PA06*/
#define P1_2 (1 << 7) /*PA07*/
#define PORT_1 PortA
#define P2_1 (1 << 2) /*PA02*/
#define P2_2 (1 << 3) /*PA03*/
#define P2_1 (1 << 2) /*PB02*/
#define P2_2 (1 << 3) /*PB03*/
#define PORT_2 PortB
#endif

View File

@ -166,14 +166,14 @@ int main() {
printf("Initialize PWM on pin P1.2 with duty cycle: %.2f\n", pwm_1.read());
printf("Initialize PWM on pin P1.3 with duty cycle: %.2f\n", pwm_2.read());
#elif defined(TARGET_SAMR21G18A)
PwmOut pwm(PA19);
#elif defined(TARGET_SAMR21G18A) || defined(TARGET_SAMD21J18A)
PwmOut pwm(LED1);
pwm.period_ms(1000);
pwm.write(value);
float result = floor(pwm.read() * 100 + 0.5) / 100; // round it to 0.xx
printf("Initialize PWM on pin LED0 with duty cycle: %.2f\n", result);
printf("Initialize PWM on pin LED1 with duty cycle: %.2f\n", result);
notify_completion(result == value ? true : false);
#else

View File

@ -28,7 +28,7 @@
#elif defined (TARGET_DISCO_F407VG)
#define TEST_LED LED1
#elif defined(TARGET_SAMR21G18A)
#elif defined(TARGET_SAMR21G18A) || defined(TARGET_SAMD21J18A)
#define TEST_LED LED1
#else

View File

@ -6,7 +6,7 @@ Serial pc(USBTX, USBRX);
Serial uart(P4_22, P4_23);
#elif defined(TARGET_MAXWSNENV)
Serial uart(P0_1, P0_0);
#elif defined(TARGET_SAMR21G18A)
#elif defined(TARGET_SAMR21G18A) || defined(TARGET_SAMD21J18A)
Serial uart(PA16, PA17);
#else
Serial uart(p9, p10);

View File

@ -8,6 +8,8 @@ InterruptIn wkp(D0);
InterruptIn wkp(P0_16);
#elif defined(TARGET_SAMR21G18A)
InterruptIn wkp(PA28);
#elif defined(TARGET_SAMD21J18A)
InterruptIn wkp(PA15);
#else
InterruptIn wkp(p14);
#endif

View File

@ -3,6 +3,9 @@
#if defined(TARGET_SAMR21G18A)
SPI spi(PB22, PB02, PB23); // mosi, miso, sclk
DigitalOut latchpin(PB03);
#elif defined(TARGET_SAMD21J18A)
SPI spi(PA18, PA16, PA19); // mosi, miso, sclk
DigitalOut latchpin(PA17);
#else
SPI spi(p11, p12, p13);
DigitalOut latchpin(p10);

View File

@ -25,6 +25,9 @@ DigitalOut cs(PE13);
#elif defined(TARGET_SAMR21G18A)
SPI spi(PB22, PB02, PB23); // mosi, miso, sclk
DigitalOut cs(PB03);
#elif defined(TARGET_SAMD21J18A)
SPI spi(PA18, PA16, PA19); // mosi, miso, sclk
DigitalOut cs(PA17);
#else
SPI spi(p5, p6, p7); // mosi, miso, sclk
DigitalOut cs(p8);

View File

@ -12,6 +12,8 @@ SPISlave device(D11, D12, D13, D10); // mosi, miso, sclk, ssel
SPISlave device(dp2, dp1, dp6, dp25); // mosi, miso, sclk, ssel
#elif defined(TARGET_SAMR21G18A)
SPISlave device(PB22, PB02, PB23, PB03); // mosi, miso, sclk, ssel
#elif defined(TARGET_SAMD21J18A)
SPISlave device(PA18, PA16, PA19, PA17); // mosi, miso, sclk, ssel
#else
SPISlave device(p5, p6, p7, p8); // mosi, miso, sclk, ssel
#endif

View File

@ -6,7 +6,7 @@
#include "cmsis_nvic.h"
#include <string.h>
#if defined(TARGET_SAMR21G18A)
#if defined(TARGET_SAMR21G18A) || defined(TARGET_SAMD21J18A)
#define PIN_IN (PA06)
#define PIN_OUT (PA07)
#define NUM_VECTORS (16+28)

View File

@ -99,6 +99,7 @@ class GccArm(Exporter):
'NZ32SC151',
'SAMR21G18A',
'TEENSY3_1',
'SAMD21J18A',
]
DOT_IN_RELATIVE_PATH = True

View File

@ -1566,6 +1566,15 @@ class SAMR21G18A(Target):
self.supported_toolchains = ["GCC_ARM"]
self.default_toolchain = "GCC_ARM"
class SAMD21J18A(Target):
def __init__(self):
Target.__init__(self)
self.core = "Cortex-M0+"
self.extra_labels = ['Atmel', 'SAM_CortexM0+', 'SAMD21']
self.macros = ['__SAMD21J18A__', 'I2C_MASTER_CALLBACK_MODE=true', 'EXTINT_CALLBACK_MODE=true', 'USART_CALLBACK_MODE=true', 'TC_ASYNC=true']
self.supported_toolchains = ["GCC_ARM"]
self.default_toolchain = "GCC_ARM"
# Get a single instance for each target
TARGETS = [
@ -1717,7 +1726,9 @@ TARGETS = [
### WIZnet ###
WIZWIKI_W7500(),
### Atmel ###
SAMR21G18A(),
SAMD21J18A(),
]
# Map each target name to its unique instance