Merge pull request #608 from tannewt/analog
ports/atmel-samd: Re-enable analogio
This commit is contained in:
commit
af566e1135
|
@ -168,7 +168,9 @@ endif
|
|||
SRC_ASF := \
|
||||
gcc/gcc/startup_$(CHIP_FAMILY).c \
|
||||
gcc/system_$(CHIP_FAMILY).c \
|
||||
hal/src/hal_adc_sync.c \
|
||||
hal/src/hal_atomic.c \
|
||||
hal/src/hal_dac_sync.c \
|
||||
hal/src/hal_delay.c \
|
||||
hal/src/hal_flash.c \
|
||||
hal/src/hal_i2c_m_sync.c \
|
||||
|
@ -177,7 +179,9 @@ SRC_ASF := \
|
|||
hal/src/hal_spi_m_sync.c \
|
||||
hal/src/hal_timer.c \
|
||||
hal/src/hal_usb_device.c \
|
||||
hpl/adc/hpl_adc.c \
|
||||
hpl/core/hpl_init.c \
|
||||
hpl/dac/hpl_dac.c \
|
||||
hpl/gclk/hpl_gclk.c \
|
||||
hpl/nvmctrl/hpl_nvmctrl.c \
|
||||
hpl/pm/hpl_pm.c \
|
||||
|
@ -265,10 +269,10 @@ SRC_COMMON_HAL = \
|
|||
os/__init__.c \
|
||||
storage/__init__.c \
|
||||
time/__init__.c \
|
||||
# analogio/__init__.c \
|
||||
analogio/__init__.c \
|
||||
analogio/AnalogIn.c \
|
||||
analogio/AnalogOut.c \
|
||||
audiobusio/__init__.c \
|
||||
# audiobusio/__init__.c \
|
||||
audiobusio/PDMIn.c \
|
||||
audioio/__init__.c \
|
||||
audioio/AudioOut.c \
|
||||
|
|
|
@ -0,0 +1,296 @@
|
|||
/* Auto-generated config file hpl_adc_config.h */
|
||||
#ifndef HPL_ADC_CONFIG_H
|
||||
#define HPL_ADC_CONFIG_H
|
||||
|
||||
// <<< Use Configuration Wizard in Context Menu >>>
|
||||
|
||||
#ifndef CONF_ADC_0_ENABLE
|
||||
#define CONF_ADC_0_ENABLE 1
|
||||
#endif
|
||||
|
||||
// <h> Basic Configuration
|
||||
|
||||
// <o> Conversion resolution
|
||||
// <0x0=>12-bit
|
||||
// <0x1=>16-bit (averaging must be enabled)
|
||||
// <0x2=>10-bit
|
||||
// <0x3=>8-bit
|
||||
// <i> Defines the bit resolution for the ADC sample values (RESSEL)
|
||||
// <id> adc_resolution
|
||||
#ifndef CONF_ADC_0_RESSEL
|
||||
#define CONF_ADC_0_RESSEL 0x0
|
||||
#endif
|
||||
|
||||
// <o> Reference Selection
|
||||
// <0x0=>1.0V voltage reference
|
||||
// <0x1=>1/1.48 VDDANA
|
||||
// <0x2=>1/2 VDDANA (only for VDDANA > 2.0V)
|
||||
// <0x3=>External reference A
|
||||
// <0x4=>External reference B
|
||||
// <i> Select the reference for the ADC (REFSEL)
|
||||
// <id> adc_reference
|
||||
#ifndef CONF_ADC_0_REFSEL
|
||||
#define CONF_ADC_0_REFSEL 0x2
|
||||
#endif
|
||||
|
||||
// <o> Prescaler configuration
|
||||
// <0x0=>Peripheral clock divided by 4
|
||||
// <0x1=>Peripheral clock divided by 8
|
||||
// <0x2=>Peripheral clock divided by 16
|
||||
// <0x3=>Peripheral clock divided by 32
|
||||
// <0x4=>Peripheral clock divided by 64
|
||||
// <0x5=>Peripheral clock divided by 128
|
||||
// <0x6=>Peripheral clock divided by 256
|
||||
// <0x7=>Peripheral clock divided by 512
|
||||
// <i> These bits define the ADC clock relative to the peripheral clock (PRESCALER)
|
||||
// <id> adc_prescaler
|
||||
#ifndef CONF_ADC_0_PRESCALER
|
||||
#define CONF_ADC_0_PRESCALER 0x3
|
||||
#endif
|
||||
|
||||
// <q> Free Running Mode
|
||||
// <i> When enabled, the ADC is in free running mode and a new conversion will be initiated when a previous conversion completes. (FREERUN)
|
||||
// <id> adc_freerunning_mode
|
||||
#ifndef CONF_ADC_0_FREERUN
|
||||
#define CONF_ADC_0_FREERUN 0
|
||||
#endif
|
||||
|
||||
// <q> Differential Mode
|
||||
// <i> In differential mode, the voltage difference between the MUXPOS and MUXNEG inputs will be converted by the ADC. (DIFFMODE)
|
||||
// <id> adc_differential_mode
|
||||
#ifndef CONF_ADC_0_DIFFMODE
|
||||
#define CONF_ADC_0_DIFFMODE 0
|
||||
#endif
|
||||
|
||||
// <o> Positive Mux Input Selection
|
||||
// <0x00=>ADC AIN0 pin
|
||||
// <0x01=>ADC AIN1 pin
|
||||
// <0x02=>ADC AIN2 pin
|
||||
// <0x03=>ADC AIN3 pin
|
||||
// <0x04=>ADC AIN4 pin
|
||||
// <0x05=>ADC AIN5 pin
|
||||
// <0x06=>ADC AIN6 pin
|
||||
// <0x07=>ADC AIN7 pin
|
||||
// <0x08=>ADC AIN8 pin
|
||||
// <0x09=>ADC AIN9 pin
|
||||
// <0x0A=>ADC AIN10 pin
|
||||
// <0x0B=>ADC AIN11 pin
|
||||
// <0x0C=>ADC AIN12 pin
|
||||
// <0x0D=>ADC AIN13 pin
|
||||
// <0x0E=>ADC AIN14 pin
|
||||
// <0x0F=>ADC AIN15 pin
|
||||
// <0x10=>ADC AIN16 pin
|
||||
// <0x11=>ADC AIN17 pin
|
||||
// <0x12=>ADC AIN18 pin
|
||||
// <0x13=>ADC AIN19 pin
|
||||
// <0x18=>Temperature reference
|
||||
// <0x19=>Bandgap voltage
|
||||
// <0x1A=>1/4 scaled core supply
|
||||
// <0x1B=>1/4 scaled I/O supply
|
||||
// <0x1C=>DAC output
|
||||
// <i> These bits define the Mux selection for the positive ADC input. (MUXPOS)
|
||||
// <id> adc_pinmux_positive
|
||||
#ifndef CONF_ADC_0_MUXPOS
|
||||
#define CONF_ADC_0_MUXPOS 0x02
|
||||
#endif
|
||||
|
||||
// <o> Negative Mux Input Selection
|
||||
// <0x00=>ADC AIN0 pin
|
||||
// <0x01=>ADC AIN1 pin
|
||||
// <0x02=>ADC AIN2 pin
|
||||
// <0x03=>ADC AIN3 pin
|
||||
// <0x04=>ADC AIN4 pin
|
||||
// <0x05=>ADC AIN5 pin
|
||||
// <0x06=>ADC AIN6 pin
|
||||
// <0x07=>ADC AIN7 pin
|
||||
// <0x18=>Internal ground
|
||||
// <0x19=>I/O ground
|
||||
// <i> These bits define the Mux selection for the negative ADC input. (MUXNEG)
|
||||
// <id> adc_pinmux_negative
|
||||
#ifndef CONF_ADC_0_MUXNEG
|
||||
#define CONF_ADC_0_MUXNEG 0x18
|
||||
#endif
|
||||
|
||||
// </h>
|
||||
|
||||
// <e> Advanced Configuration
|
||||
// <id> adc_advanced_settings
|
||||
#ifndef CONF_ADC_0_ADVANCED_CONFIG
|
||||
#define CONF_ADC_0_ADVANCED_CONFIG 0
|
||||
#endif
|
||||
|
||||
// <q> Run in standby
|
||||
// <i> Indicates whether the ADC will continue running in standby sleep mode or not (RUNSTDBY)
|
||||
// <id> adc_arch_runstdby
|
||||
#ifndef CONF_ADC_0_RUNSTDBY
|
||||
#define CONF_ADC_0_RUNSTDBY 0
|
||||
#endif
|
||||
|
||||
// <q>Debug Run
|
||||
// <i> If enabled, the ADC is running if the CPU is halted by an external debugger. (DBGRUN)
|
||||
// <id> adc_arch_dbgrun
|
||||
#ifndef CONF_ADC_0_DBGRUN
|
||||
#define CONF_ADC_0_DBGRUN 0
|
||||
#endif
|
||||
|
||||
// <q> Left-Adjusted Result
|
||||
// <i> When enabled, the ADC conversion result is left-adjusted in the RESULT register. The high byte of the 12-bit result will be present in the upper part of the result register. (LEFTADJ)
|
||||
// <id> adc_arch_leftadj
|
||||
#ifndef CONF_ADC_0_LEFTADJ
|
||||
#define CONF_ADC_0_LEFTADJ 0
|
||||
#endif
|
||||
|
||||
// <q> Reference Buffer Offset Compensation Enable
|
||||
// <i> The accuracy of the gain stage can be increased by enabling the reference buffer offset compensation. This will decrease the input impedance and thus increase the start-up time of the reference. (REFCOMP)
|
||||
// <id> adc_arch_refcomp
|
||||
#ifndef CONF_ADC_0_REFCOMP
|
||||
#define CONF_ADC_0_REFCOMP 0
|
||||
#endif
|
||||
|
||||
// <q> Digital Correction Logic Enabled
|
||||
// <i> When enabled, the ADC conversion result in the RESULT register is then corrected for gain and offset based on the values in the GAINCAL and OFFSETCAL registers. (CORREN)
|
||||
// <id> adc_arch_corren
|
||||
#ifndef CONF_ADC_0_CORREN
|
||||
#define CONF_ADC_0_CORREN 0
|
||||
#endif
|
||||
|
||||
// <o> Offset Correction Value <0-4095>
|
||||
// <i> If the digital correction logic is enabled (CTRLB.CORREN = 1), these bits define how the ADC conversion result is compensated for offset error before being written to the Result register. (OFFSETCORR)
|
||||
// <id> adc_arch_offsetcorr
|
||||
#ifndef CONF_ADC_0_OFFSETCORR
|
||||
#define CONF_ADC_0_OFFSETCORR 0
|
||||
#endif
|
||||
|
||||
// <o> Gain Correction Value <0-4095>
|
||||
// <i> If the digital correction logic is enabled (CTRLB.CORREN = 1), these bits define how the ADC conversion result is compensated for gain error before being written to the result register. (GAINCORR)
|
||||
// <id> adc_arch_gaincorr
|
||||
#ifndef CONF_ADC_0_GAINCORR
|
||||
#define CONF_ADC_0_GAINCORR 0
|
||||
#endif
|
||||
|
||||
// <o> Gain Factor Selection
|
||||
// <0x0=>1x
|
||||
// <0x1=>2x
|
||||
// <0x2=>4x
|
||||
// <0x3=>8x
|
||||
// <0x4=>16x
|
||||
// <0xF=>1/2x
|
||||
// <i> These bits set the gain factor of the ADC gain stage. (GAIN)
|
||||
// <id> adc_arch_gain
|
||||
#ifndef CONF_ADC_0_GAIN
|
||||
#define CONF_ADC_0_GAIN 0x0
|
||||
#endif
|
||||
|
||||
// <o> Adjusting Result / Division Coefficient <0-7>
|
||||
// <i> These bits define the division coefficient in 2n steps. (ADJRES)
|
||||
// <id> adc_arch_adjres
|
||||
#ifndef CONF_ADC_0_ADJRES
|
||||
#define CONF_ADC_0_ADJRES 0x0
|
||||
#endif
|
||||
|
||||
// <o.0..10> Number of Samples to be Collected
|
||||
// <0x0=>1 sample
|
||||
// <0x1=>2 samples
|
||||
// <0x2=>4 samples
|
||||
// <0x3=>8 samples
|
||||
// <0x4=>16 samples
|
||||
// <0x5=>32 samples
|
||||
// <0x6=>64 samples
|
||||
// <0x7=>128 samples
|
||||
// <0x8=>256 samples
|
||||
// <0x9=>512 samples
|
||||
// <0xA=>1024 samples
|
||||
// <i> Define how many samples should be added together.The result will be available in the Result register (SAMPLENUM)
|
||||
// <id> adc_arch_samplenum
|
||||
#ifndef CONF_ADC_0_SAMPLENUM
|
||||
#define CONF_ADC_0_SAMPLENUM 0x0
|
||||
#endif
|
||||
|
||||
// <o> Sampling Time Length <0-63>
|
||||
// <i> These bits control the ADC sampling time in number of half CLK_ADC cycles, depending of the prescaler value, thus controlling the ADC input impedance. (SAMPLEN)
|
||||
// <id> adc_arch_samplen
|
||||
#ifndef CONF_ADC_0_SAMPLEN
|
||||
#define CONF_ADC_0_SAMPLEN 0
|
||||
#endif
|
||||
|
||||
// <o> Window Monitor Mode
|
||||
// <0x0=>No window mode
|
||||
// <0x1=>Mode 1: RESULT above lower threshold
|
||||
// <0x2=>Mode 2: RESULT beneath upper threshold
|
||||
// <0x3=>Mode 3: RESULT inside lower and upper threshold
|
||||
// <0x4=>Mode 4: RESULT outside lower and upper threshold
|
||||
// <i> These bits enable and define the window monitor mode. (WINMODE)
|
||||
// <id> adc_arch_winmode
|
||||
#ifndef CONF_ADC_0_WINMODE
|
||||
#define CONF_ADC_0_WINMODE 0x0
|
||||
#endif
|
||||
|
||||
// <o> Window Monitor Lower Threshold <0-65535>
|
||||
// <i> If the window monitor is enabled, these bits define the lower threshold value. (WINLT)
|
||||
// <id> adc_arch_winlt
|
||||
#ifndef CONF_ADC_0_WINLT
|
||||
#define CONF_ADC_0_WINLT 0
|
||||
#endif
|
||||
|
||||
// <o> Window Monitor Upper Threshold <0-65535>
|
||||
// <i> If the window monitor is enabled, these bits define the lower threshold value. (WINUT)
|
||||
// <id> adc_arch_winut
|
||||
#ifndef CONF_ADC_0_WINUT
|
||||
#define CONF_ADC_0_WINUT 0
|
||||
#endif
|
||||
|
||||
// <o> Number of Input Channels Included in Scan <0-15>
|
||||
// <i>This register gives the number of input sources included in pin scan. The number of input sources included is INPUTSCAN + 1. 0 disables the input scan feature. (INPUTSCAN)
|
||||
// <id> adc_arch_inputscan
|
||||
#ifndef CONF_ADC_0_INPUTSCAN
|
||||
#define CONF_ADC_0_INPUTSCAN 0
|
||||
#endif
|
||||
|
||||
// <o> Positive Mux Setting Offset <0-15>
|
||||
// <i>When inputscan is enabled this value define the pin offset, which means that the actual input pin sampled is the muxpos pin + input offset. (INPUTOFFSET)
|
||||
// <id> adc_arch_inputoffset
|
||||
#ifndef CONF_ADC_0_INPUTOFFSET
|
||||
#define CONF_ADC_0_INPUTOFFSET 0
|
||||
#endif
|
||||
|
||||
// </e>
|
||||
|
||||
// <e> Event Control
|
||||
// <id> adc_arch_event_settings
|
||||
#ifndef CONF_ADC_0_EVENT_CONFIG
|
||||
#define CONF_ADC_0_EVENT_CONFIG 0
|
||||
#endif
|
||||
|
||||
// <q> Window Monitor Event Out
|
||||
// <i> Enables event output on window event (WINMONEO)
|
||||
// <id> adc_arch_winmoneo
|
||||
#ifndef CONF_ADC_0_WINMONEO
|
||||
#define CONF_ADC_0_WINMONEO 0
|
||||
#endif
|
||||
|
||||
// <q> Result Ready Event Out
|
||||
// <i> Enables event output on result ready event (RESRDEO)
|
||||
// <id> adc_arch_resrdyeo
|
||||
#ifndef CONF_ADC_0_RESRDYEO
|
||||
#define CONF_ADC_0_RESRDYEO 0
|
||||
#endif
|
||||
|
||||
// <q> Trigger Synchronization On Event
|
||||
// <i> Trigger a flush operation and a new conversion on event in (SYNCEI)
|
||||
// <id> adc_arch_syncei
|
||||
#ifndef CONF_ADC_0_SYNCEI
|
||||
#define CONF_ADC_0_SYNCEI 0
|
||||
#endif
|
||||
|
||||
// <q> Trigger Conversion On Event
|
||||
// <i> Trigger a conversion on event. (STARTEI)
|
||||
// <id> adc_arch_startei
|
||||
#ifndef CONF_ADC_0_STARTEI
|
||||
#define CONF_ADC_0_STARTEI 0
|
||||
#endif
|
||||
|
||||
// </e>
|
||||
|
||||
// <<< end of configuration section >>>
|
||||
|
||||
#endif // HPL_ADC_CONFIG_H
|
|
@ -0,0 +1,86 @@
|
|||
/* Auto-generated config file hpl_dac_config.h */
|
||||
#ifndef HPL_DAC_CONFIG_H
|
||||
#define HPL_DAC_CONFIG_H
|
||||
|
||||
// <<< Use Configuration Wizard in Context Menu >>>
|
||||
|
||||
// <h> Basic configuration
|
||||
// <o> Reference Selection
|
||||
// <0x00=> Internal 1.0v reference
|
||||
// <0x01=> AVCC
|
||||
// <0x02=> External reference
|
||||
// <id> dac_arch_refsel
|
||||
#ifndef CONF_DAC_REFSEL
|
||||
#define CONF_DAC_REFSEL 1
|
||||
#endif
|
||||
// </h>
|
||||
|
||||
// <e> Advanced Configuration
|
||||
// <id> dac_advanced_settings
|
||||
#ifndef CONF_DAC_ADVANCED_CONFIG
|
||||
#define CONF_DAC_ADVANCED_CONFIG 0
|
||||
#endif
|
||||
|
||||
// <q> Run in standby
|
||||
// <i> Indicates whether the DAC will continue running in standby sleep mode or not
|
||||
// <id> dac_arch_runstdby
|
||||
#ifndef CONF_DAC_RUNSTDBY
|
||||
#define CONF_DAC_RUNSTDBY 0
|
||||
#endif
|
||||
|
||||
// <q> Bypass DATABUF Write Protection
|
||||
// <i> Indicate whether DATABUF write protection is bypass
|
||||
// <id> dac_arch_bdwp
|
||||
#ifndef CONF_DAC_BDWP
|
||||
#define CONF_DAC_BDWP 0
|
||||
#endif
|
||||
|
||||
// <q> Voltage Pump Disable
|
||||
// <i> Indicate whether voltage pump is disable or not
|
||||
// <id> dac_arch_vpd
|
||||
#ifndef CONF_DAC_VPD
|
||||
#define CONF_DAC_VPD 0
|
||||
#endif
|
||||
|
||||
// <q> Left Adjusted Data
|
||||
// <i> Indicate how the data is adjusted in the Data and Data Buffer register
|
||||
// <id> dac_arch_leftadj
|
||||
#ifndef CONF_DAC_LEFTADJ
|
||||
#define CONF_DAC_LEFTADJ 1
|
||||
#endif
|
||||
|
||||
// <q> Internal Output Enable
|
||||
// <i> Indicate whether internal output is enable or not
|
||||
// <id> dac_arch_ioen
|
||||
#ifndef CONF_DAC_IOEN
|
||||
#define CONF_DAC_IOEN 0
|
||||
#endif
|
||||
|
||||
// <q> External Output Enable
|
||||
// <i> Indicate whether external output is enable or not
|
||||
// <id> dac_arch_eoen
|
||||
#ifndef CONF_DAC_EOEN
|
||||
#define CONF_DAC_EOEN 1
|
||||
#endif
|
||||
|
||||
// </e>
|
||||
|
||||
// <h> Event configuration
|
||||
// <q> Data Buffer Empty Event Output
|
||||
// <i> Indicate whether Data Buffer Empty Event is enabled and generated when the Data Buffer register is empty or not
|
||||
// <id> dac_arch_emptyeo
|
||||
#ifndef CONF_DAC_EMPTYEO
|
||||
#define CONF_DAC_EMPTYEO 0
|
||||
#endif
|
||||
|
||||
// <q> Start Conversion on Event Input
|
||||
// <i> Indicate whether Start Conversion is enabled and data are loaded from the Data Buffer register to the Data register upon event reception or not
|
||||
// <id> dac_arch_startei
|
||||
#ifndef CONF_DAC_STARTEI
|
||||
#define CONF_DAC_STARTEI 0
|
||||
#endif
|
||||
// </h>
|
||||
|
||||
// <<< end of configuration section >>>
|
||||
|
||||
#endif // HPL_DAC_CONFIG_H
|
|
@ -0,0 +1,303 @@
|
|||
/* Auto-generated config file hpl_adc_config.h */
|
||||
#ifndef HPL_ADC_CONFIG_H
|
||||
#define HPL_ADC_CONFIG_H
|
||||
|
||||
// <<< Use Configuration Wizard in Context Menu >>>
|
||||
|
||||
#ifndef CONF_ADC_0_ENABLE
|
||||
#define CONF_ADC_0_ENABLE 1
|
||||
#endif
|
||||
|
||||
// <h> Basic Configuration
|
||||
|
||||
// <o> Conversion Result Resolution
|
||||
// <0x0=>12-bit
|
||||
// <0x1=>16-bit (averaging must be enabled)
|
||||
// <0x2=>10-bit
|
||||
// <0x3=>8-bit
|
||||
// <i> Defines the bit resolution for the ADC sample values (RESSEL)
|
||||
// <id> adc_resolution
|
||||
#ifndef CONF_ADC_0_RESSEL
|
||||
#define CONF_ADC_0_RESSEL 0x0
|
||||
#endif
|
||||
|
||||
// <o> Reference Selection
|
||||
// <0x0=>Internal bandgap reference
|
||||
// <0x2=>1/2 VDDANA (only for VDDANA > 2.0V)
|
||||
// <0x3=>VDDANA
|
||||
// <0x4=>External reference A
|
||||
// <0x5=>External reference B
|
||||
// <0x6=>External reference C
|
||||
// <i> Select the reference for the ADC (REFSEL)
|
||||
// <id> adc_reference
|
||||
#ifndef CONF_ADC_0_REFSEL
|
||||
#define CONF_ADC_0_REFSEL 0x0
|
||||
#endif
|
||||
|
||||
// <o> Prescaler configuration
|
||||
// <0x0=>Peripheral clock divided by 2
|
||||
// <0x1=>Peripheral clock divided by 4
|
||||
// <0x2=>Peripheral clock divided by 8
|
||||
// <0x3=>Peripheral clock divided by 16
|
||||
// <0x4=>Peripheral clock divided by 32
|
||||
// <0x5=>Peripheral clock divided by 64
|
||||
// <0x6=>Peripheral clock divided by 128
|
||||
// <0x7=>Peripheral clock divided by 256
|
||||
// <i> These bits define the ADC clock relative to the peripheral clock (PRESCALER)
|
||||
// <id> adc_prescaler
|
||||
#ifndef CONF_ADC_0_PRESCALER
|
||||
#define CONF_ADC_0_PRESCALER 0x3
|
||||
#endif
|
||||
|
||||
// <q> Free Running Mode
|
||||
// <i> When enabled, the ADC is in free running mode and a new conversion will be initiated when a previous conversion completes. (FREERUN)
|
||||
// <id> adc_freerunning_mode
|
||||
#ifndef CONF_ADC_0_FREERUN
|
||||
#define CONF_ADC_0_FREERUN 0
|
||||
#endif
|
||||
|
||||
// <q> Differential Mode
|
||||
// <i> In differential mode, the voltage difference between the MUXPOS and MUXNEG inputs will be converted by the ADC. (DIFFMODE)
|
||||
// <id> adc_differential_mode
|
||||
#ifndef CONF_ADC_0_DIFFMODE
|
||||
#define CONF_ADC_0_DIFFMODE 0
|
||||
#endif
|
||||
|
||||
// <o> Positive Mux Input Selection
|
||||
// <0x00=>ADC AIN0 pin
|
||||
// <0x01=>ADC AIN1 pin
|
||||
// <0x02=>ADC AIN2 pin
|
||||
// <0x03=>ADC AIN3 pin
|
||||
// <0x04=>ADC AIN4 pin
|
||||
// <0x05=>ADC AIN5 pin
|
||||
// <0x06=>ADC AIN6 pin
|
||||
// <0x07=>ADC AIN7 pin
|
||||
// <0x08=>ADC AIN8 pin
|
||||
// <0x09=>ADC AIN9 pin
|
||||
// <0x0A=>ADC AIN10 pin
|
||||
// <0x0B=>ADC AIN11 pin
|
||||
// <0x0C=>ADC AIN12 pin
|
||||
// <0x0D=>ADC AIN13 pin
|
||||
// <0x0E=>ADC AIN14 pin
|
||||
// <0x0F=>ADC AIN15 pin
|
||||
// <0x18=>1/4 scaled core supply
|
||||
// <0x19=>1/4 Scaled VBAT Supply
|
||||
// <0x1A=>1/4 scaled I/O supply
|
||||
// <0x1B=>Bandgap voltage
|
||||
// <0x1C=>Temperature reference (PTAT)
|
||||
// <0x1D=>Temperature reference (CTAT)
|
||||
// <0x1E=>DAC Output
|
||||
// <i> These bits define the Mux selection for the positive ADC input. (MUXPOS)
|
||||
// <id> adc_pinmux_positive
|
||||
#ifndef CONF_ADC_0_MUXPOS
|
||||
#define CONF_ADC_0_MUXPOS 0x0
|
||||
#endif
|
||||
|
||||
// <o> Negative Mux Input Selection
|
||||
// <0x00=>ADC AIN0 pin
|
||||
// <0x01=>ADC AIN1 pin
|
||||
// <0x02=>ADC AIN2 pin
|
||||
// <0x03=>ADC AIN3 pin
|
||||
// <0x04=>ADC AIN4 pin
|
||||
// <0x05=>ADC AIN5 pin
|
||||
// <0x06=>ADC AIN6 pin
|
||||
// <0x07=>ADC AIN7 pin
|
||||
// <0x18=>Internal ground
|
||||
// <0x19=>I/O ground
|
||||
// <i> These bits define the Mux selection for the negative ADC input. (MUXNEG)
|
||||
// <id> adc_pinmux_negative
|
||||
#ifndef CONF_ADC_0_MUXNEG
|
||||
#define CONF_ADC_0_MUXNEG 0x0
|
||||
#endif
|
||||
|
||||
// </h>
|
||||
|
||||
// <e> Advanced Configuration
|
||||
// <id> adc_advanced_settings
|
||||
#ifndef CONF_ADC_0_ADVANCED
|
||||
#define CONF_ADC_0_ADVANCED 0
|
||||
#endif
|
||||
|
||||
// <q> Run in standby
|
||||
// <i> Indicates whether the ADC will continue running in standby sleep mode or not (RUNSTDBY)
|
||||
// <id> adc_arch_runstdby
|
||||
#ifndef CONF_ADC_0_RUNSTDBY
|
||||
#define CONF_ADC_0_RUNSTDBY 0
|
||||
#endif
|
||||
|
||||
// <q>Debug Run
|
||||
// <i> If enabled, the ADC is running if the CPU is halted by an external debugger. (DBGRUN)
|
||||
// <id> adc_arch_dbgrun
|
||||
#ifndef CONF_ADC_0_DBGRUN
|
||||
#define CONF_ADC_0_DBGRUN 0
|
||||
#endif
|
||||
|
||||
// <q> On Demand Control
|
||||
// <i> Will keep the ADC peripheral running if requested by other peripherals (ONDEMAND)
|
||||
// <id> adc_arch_ondemand
|
||||
#ifndef CONF_ADC_0_ONDEMAND
|
||||
#define CONF_ADC_0_ONDEMAND 0
|
||||
#endif
|
||||
|
||||
// <q> Left-Adjusted Result
|
||||
// <i> When enabled, the ADC conversion result is left-adjusted in the RESULT register. The high byte of the 12-bit result will be present in the upper part of the result register. (LEFTADJ)
|
||||
// <id> adc_arch_leftadj
|
||||
#ifndef CONF_ADC_0_LEFTADJ
|
||||
#define CONF_ADC_0_LEFTADJ 0
|
||||
#endif
|
||||
|
||||
// <q> Reference Buffer Offset Compensation Enable
|
||||
// <i> The accuracy of the gain stage can be increased by enabling the reference buffer offset compensation. This will decrease the input impedance and thus increase the start-up time of the reference. (REFCOMP)
|
||||
// <id> adc_arch_refcomp
|
||||
#ifndef CONF_ADC_0_REFCOMP
|
||||
#define CONF_ADC_0_REFCOMP 0
|
||||
#endif
|
||||
|
||||
// <q>Comparator Offset Compensation Enable
|
||||
// <i> This bit indicates whether the Comparator Offset Compensation is enabled or not (OFFCOMP)
|
||||
// <id> adc_arch_offcomp
|
||||
#ifndef CONF_ADC_0_OFFCOMP
|
||||
#define CONF_ADC_0_OFFCOMP 0
|
||||
#endif
|
||||
|
||||
// <q> Digital Correction Logic Enabled
|
||||
// <i> When enabled, the ADC conversion result in the RESULT register is then corrected for gain and offset based on the values in the GAINCAL and OFFSETCAL registers. (CORREN)
|
||||
// <id> adc_arch_corren
|
||||
#ifndef CONF_ADC_0_CORREN
|
||||
#define CONF_ADC_0_CORREN 0
|
||||
#endif
|
||||
|
||||
// <o> Offset Correction Value <0-4095>
|
||||
// <i> If the digital correction logic is enabled (CTRLB.CORREN = 1), these bits define how the ADC conversion result is compensated for offset error before being written to the Result register. (OFFSETCORR)
|
||||
// <id> adc_arch_offsetcorr
|
||||
#ifndef CONF_ADC_0_OFFSETCORR
|
||||
#define CONF_ADC_0_OFFSETCORR 0
|
||||
#endif
|
||||
|
||||
// <o> Gain Correction Value <0-4095>
|
||||
// <i> If the digital correction logic is enabled (CTRLB.CORREN = 1), these bits define how the ADC conversion result is compensated for gain error before being written to the result register. (GAINCORR)
|
||||
// <id> adc_arch_gaincorr
|
||||
#ifndef CONF_ADC_0_GAINCORR
|
||||
#define CONF_ADC_0_GAINCORR 0
|
||||
#endif
|
||||
|
||||
// <o> Adjusting Result / Division Coefficient <0-7>
|
||||
// <i> These bits define the division coefficient in 2n steps. (ADJRES)
|
||||
// <id> adc_arch_adjres
|
||||
#ifndef CONF_ADC_0_ADJRES
|
||||
#define CONF_ADC_0_ADJRES 0x0
|
||||
#endif
|
||||
|
||||
// <o.0..10> Number of Samples to be Collected
|
||||
// <0x0=>1 sample
|
||||
// <0x1=>2 samples
|
||||
// <0x2=>4 samples
|
||||
// <0x3=>8 samples
|
||||
// <0x4=>16 samples
|
||||
// <0x5=>32 samples
|
||||
// <0x6=>64 samples
|
||||
// <0x7=>128 samples
|
||||
// <0x8=>256 samples
|
||||
// <0x9=>512 samples
|
||||
// <0xA=>1024 samples
|
||||
// <i> Define how many samples should be added together.The result will be available in the Result register (SAMPLENUM)
|
||||
// <id> adc_arch_samplenum
|
||||
#ifndef CONF_ADC_0_SAMPLENUM
|
||||
#define CONF_ADC_0_SAMPLENUM 0x0
|
||||
#endif
|
||||
|
||||
// <o> Sampling Time Length <0-63>
|
||||
// <i> These bits control the ADC sampling time in number of half CLK_ADC cycles, depending of the prescaler value, thus controlling the ADC input impedance. (SAMPLEN)
|
||||
// <id> adc_arch_samplen
|
||||
#ifndef CONF_ADC_0_SAMPLEN
|
||||
#define CONF_ADC_0_SAMPLEN 0
|
||||
#endif
|
||||
|
||||
// <o> Window Monitor Mode
|
||||
// <0x0=>No window mode
|
||||
// <0x1=>Mode 1: RESULT above lower threshold
|
||||
// <0x2=>Mode 2: RESULT beneath upper threshold
|
||||
// <0x3=>Mode 3: RESULT inside lower and upper threshold
|
||||
// <0x4=>Mode 4: RESULT outside lower and upper threshold
|
||||
// <i> These bits enable and define the window monitor mode. (WINMODE)
|
||||
// <id> adc_arch_winmode
|
||||
#ifndef CONF_ADC_0_WINMODE
|
||||
#define CONF_ADC_0_WINMODE 0x0
|
||||
#endif
|
||||
|
||||
// <o> Window Monitor Lower Threshold <0-65535>
|
||||
// <i> If the window monitor is enabled, these bits define the lower threshold value. (WINLT)
|
||||
// <id> adc_arch_winlt
|
||||
#ifndef CONF_ADC_0_WINLT
|
||||
#define CONF_ADC_0_WINLT 0
|
||||
#endif
|
||||
|
||||
// <o> Window Monitor Upper Threshold <0-65535>
|
||||
// <i> If the window monitor is enabled, these bits define the lower threshold value. (WINUT)
|
||||
// <id> adc_arch_winut
|
||||
#ifndef CONF_ADC_0_WINUT
|
||||
#define CONF_ADC_0_WINUT 0
|
||||
#endif
|
||||
|
||||
// <o> Bitmask for positive input sequence <0-4294967295>
|
||||
// <i> Use this parameter to input the bitmask for positive input sequence control (refer to datasheet for the device).
|
||||
// <id> adc_arch_seqen
|
||||
#ifndef CONF_ADC_0_SEQEN
|
||||
#define CONF_ADC_0_SEQEN 0x0
|
||||
#endif
|
||||
|
||||
// </e>
|
||||
|
||||
// <e> Event Control
|
||||
// <id> adc_arch_event_settings
|
||||
#ifndef CONF_ADC_0_EVENT_CONTROL
|
||||
#define CONF_ADC_0_EVENT_CONTROL 0
|
||||
#endif
|
||||
|
||||
// <q> Window Monitor Event Out
|
||||
// <i> Enables event output on window event (WINMONEO)
|
||||
// <id> adc_arch_winmoneo
|
||||
#ifndef CONF_ADC_0_WINMONEO
|
||||
#define CONF_ADC_0_WINMONEO 0
|
||||
#endif
|
||||
|
||||
// <q> Result Ready Event Out
|
||||
// <i> Enables event output on result ready event (RESRDEO)
|
||||
// <id> adc_arch_resrdyeo
|
||||
#ifndef CONF_ADC_0_RESRDYEO
|
||||
#define CONF_ADC_0_RESRDYEO 0
|
||||
#endif
|
||||
|
||||
// <q> Invert flush Event Signal
|
||||
// <i> Invert the flush event input signal (FLUSHINV)
|
||||
// <id> adc_arch_flushinv
|
||||
#ifndef CONF_ADC_0_FLUSHINV
|
||||
#define CONF_ADC_0_FLUSHINV 0
|
||||
#endif
|
||||
|
||||
// <q> Trigger Flush On Event
|
||||
// <i> Trigger an ADC pipeline flush on event (FLUSHEI)
|
||||
// <id> adc_arch_flushei
|
||||
#ifndef CONF_ADC_0_FLUSHEI
|
||||
#define CONF_ADC_0_FLUSHEI 0
|
||||
#endif
|
||||
|
||||
// <q> Invert Start Conversion Event Signal
|
||||
// <i> Invert the start conversion event input signal (STARTINV)
|
||||
// <id> adc_arch_startinv
|
||||
#ifndef CONF_ADC_0_STARTINV
|
||||
#define CONF_ADC_0_STARTINV 0
|
||||
#endif
|
||||
|
||||
// <q> Trigger Conversion On Event
|
||||
// <i> Trigger a conversion on event. (STARTEI)
|
||||
// <id> adc_arch_startei
|
||||
#ifndef CONF_ADC_0_STARTEI
|
||||
#define CONF_ADC_0_STARTEI 0
|
||||
#endif
|
||||
|
||||
// </e>
|
||||
|
||||
// <<< end of configuration section >>>
|
||||
|
||||
#endif // HPL_ADC_CONFIG_H
|
|
@ -0,0 +1,169 @@
|
|||
/* Auto-generated config file hpl_dac_config.h */
|
||||
#ifndef HPL_DAC_CONFIG_H
|
||||
#define HPL_DAC_CONFIG_H
|
||||
|
||||
// <<< Use Configuration Wizard in Context Menu >>>
|
||||
|
||||
// <h> Basic configuration
|
||||
// <o> Reference Selection
|
||||
// <0x00=> Unbuffered external voltage reference
|
||||
// <0x01=> Voltage supply
|
||||
// <0x02=> Buffered external voltage reference
|
||||
// <0x03=> Internal bandgap reference
|
||||
// <id> dac_arch_refsel
|
||||
#ifndef CONF_DAC_REFSEL
|
||||
#define CONF_DAC_REFSEL 0
|
||||
#endif
|
||||
|
||||
// <q> Differential mode
|
||||
// <i> Indicates whether the differential mode is enabled or not
|
||||
// <id> dac_arch_diff
|
||||
#ifndef CONF_DAC_DIFF
|
||||
#define CONF_DAC_DIFF 0
|
||||
#endif
|
||||
// </h>
|
||||
|
||||
// <e> Advanced Configuration
|
||||
// <id> dac_advanced_settings
|
||||
#ifndef CONF_DAC_ADVANCED_CONFIG
|
||||
#define CONF_DAC_ADVANCED_CONFIG 0
|
||||
#endif
|
||||
|
||||
// <q> Debug Run
|
||||
// <i> Indicate whether running when CPU is halted
|
||||
// <id> adc_arch_dbgrun
|
||||
#ifndef CONF_DAC_DBGRUN
|
||||
#define CONF_DAC_DBGRUN 1
|
||||
#endif
|
||||
|
||||
// <h> Channel 0 configuration
|
||||
// <q> Left Adjusted Data
|
||||
// <i> Indicate how the data is adjusted in the Data and Data Buffer register
|
||||
// <id> dac0_arch_leftadj
|
||||
#ifndef CONF_DAC0_LEFTADJ
|
||||
#define CONF_DAC0_LEFTADJ 1
|
||||
#endif
|
||||
|
||||
// <o> Current control
|
||||
// <0=> GCLK_DAC <= 1.2MHz (100kSPS)
|
||||
// <1=> 1.2MHz < GCLK_DAC <= 6MHz (500kSPS)
|
||||
// <2=> 6MHz < GCLK_DAC <= 12MHz (1MSPS)
|
||||
// <i> This defines the current in output buffer according to conversion rate
|
||||
// <id> dac0_arch_cctrl
|
||||
#ifndef CONF_DAC0_CCTRL
|
||||
#define CONF_DAC0_CCTRL 1
|
||||
#endif
|
||||
|
||||
// <q> Run in standby
|
||||
// <i> Indicates whether the DAC channel will continue running in standby sleep mode or not
|
||||
// <id> dac0_arch_runstdby
|
||||
#ifndef CONF_DAC0_RUNSTDBY
|
||||
#define CONF_DAC0_RUNSTDBY 0
|
||||
#endif
|
||||
|
||||
// <q> Dithering Mode
|
||||
// <i> Indicate whether dithering mode is enabled
|
||||
// <id> dac0_arch_ditrher
|
||||
#ifndef CONF_DAC0_DITHER
|
||||
#define CONF_DAC0_DITHER 0
|
||||
#endif
|
||||
|
||||
// <o> Refresh period <0x00-0xFF>
|
||||
// <i> This defines the refresh period. If it is 0, the refresh mode is disabled, else the refresh period is: value * 500us
|
||||
// <id> dac0_arch_refresh
|
||||
#ifndef CONF_DAC0_REFRESH
|
||||
#define CONF_DAC0_REFRESH 0
|
||||
#endif
|
||||
// </h>
|
||||
// <h> Channel 1 configuration
|
||||
// <q> Left Adjusted Data
|
||||
// <i> Indicate how the data is adjusted in the Data and Data Buffer register
|
||||
// <id> dac1_arch_leftadj
|
||||
#ifndef CONF_DAC1_LEFTADJ
|
||||
#define CONF_DAC1_LEFTADJ 1
|
||||
#endif
|
||||
|
||||
// <o> Current control
|
||||
// <0=> GCLK_DAC <= 1.2MHz (100kSPS)
|
||||
// <1=> 1.2MHz < GCLK_DAC <= 6MHz (500kSPS)
|
||||
// <2=> 6MHz < GCLK_DAC <= 12MHz (1MSPS)
|
||||
// <i> This defines the current in output buffer according to conversion rate
|
||||
// <id> dac1_arch_cctrl
|
||||
#ifndef CONF_DAC1_CCTRL
|
||||
#define CONF_DAC1_CCTRL 1
|
||||
#endif
|
||||
|
||||
// <q> Run in standby
|
||||
// <i> Indicates whether the DAC channel will continue running in standby sleep mode or not
|
||||
// <id> dac1_arch_runstdby
|
||||
#ifndef CONF_DAC1_RUNSTDBY
|
||||
#define CONF_DAC1_RUNSTDBY 0
|
||||
#endif
|
||||
|
||||
// <q> Dithering Mode
|
||||
// <i> Indicate whether dithering mode is enabled
|
||||
// <id> dac1_arch_ditrher
|
||||
#ifndef CONF_DAC1_DITHER
|
||||
#define CONF_DAC1_DITHER 0
|
||||
#endif
|
||||
|
||||
// <o> Refresh period <0x00-0xFF>
|
||||
// <i> This defines the refresh period. If it is 0, the refresh mode is disabled, else the refresh period is: value * 500us
|
||||
// <id> dac1_arch_refresh
|
||||
#ifndef CONF_DAC1_REFRESH
|
||||
#define CONF_DAC1_REFRESH 0
|
||||
#endif
|
||||
// </h>
|
||||
|
||||
// <h> Event configuration
|
||||
// <o> Inversion of DAC 0 event
|
||||
// <0=> Detection on rising edge pf the input event
|
||||
// <1=> Detection on falling edge pf the input event
|
||||
// <i> This defines the edge detection of the input event
|
||||
// <id> dac_arch_invei0
|
||||
#ifndef CONF_DAC_INVEI0
|
||||
#define CONF_DAC_INVEI0 0
|
||||
#endif
|
||||
|
||||
// <q> Data Buffer of DAC 0 Empty Event Output
|
||||
// <i> Indicate whether Data Buffer Empty Event is enabled and generated when the Data Buffer register is empty or not
|
||||
// <id> dac_arch_emptyeo_0
|
||||
#ifndef CONF_DAC_EMPTYEO0
|
||||
#define CONF_DAC_EMPTYEO0 0
|
||||
#endif
|
||||
|
||||
// <q> Start Conversion Event Input DAC 0
|
||||
// <i> Indicate whether Start input event is enabled
|
||||
// <id> dac_arch_startei_0
|
||||
#ifndef CONF_DAC_STARTEI0
|
||||
#define CONF_DAC_STARTEI0 0
|
||||
#endif
|
||||
// <o> Inversion of DAC 1 event
|
||||
// <0=> Detection on rising edge pf the input event
|
||||
// <1=> Detection on falling edge pf the input event
|
||||
// <i> This defines the edge detection of the input event
|
||||
// <id> dac_arch_invei1
|
||||
#ifndef CONF_DAC_INVEI1
|
||||
#define CONF_DAC_INVEI1 0
|
||||
#endif
|
||||
|
||||
// <q> Data Buffer of DAC 1 Empty Event Output
|
||||
// <i> Indicate whether Data Buffer Empty Event is enabled and generated when the Data Buffer register is empty or not
|
||||
// <id> dac_arch_emptyeo_1
|
||||
#ifndef CONF_DAC_EMPTYEO1
|
||||
#define CONF_DAC_EMPTYEO1 0
|
||||
#endif
|
||||
|
||||
// <q> Start Conversion Event Input DAC 1
|
||||
// <i> Indicate whether Start input event is enabled
|
||||
// <id> dac_arch_startei_1
|
||||
#ifndef CONF_DAC_STARTEI1
|
||||
#define CONF_DAC_STARTEI1 0
|
||||
#endif
|
||||
|
||||
// </h>
|
||||
// </e>
|
||||
|
||||
// <<< end of configuration section >>>
|
||||
|
||||
#endif // HPL_DAC_CONFIG_H
|
|
@ -33,19 +33,40 @@
|
|||
#include "py/runtime.h"
|
||||
#include "py/binary.h"
|
||||
#include "py/mphal.h"
|
||||
|
||||
#include "shared-bindings/analogio/AnalogIn.h"
|
||||
|
||||
#include "asf/sam0/drivers/adc/adc.h"
|
||||
#include "samd21_pins.h"
|
||||
#include "atmel_start_pins.h"
|
||||
#include "hal/include/hal_adc_sync.h"
|
||||
#include "hpl/gclk/hpl_gclk_base.h"
|
||||
|
||||
#ifdef SAMD21
|
||||
#include "hpl/pm/hpl_pm_base.h"
|
||||
#endif
|
||||
|
||||
void common_hal_analogio_analogin_construct(analogio_analogin_obj_t* self,
|
||||
const mcu_pin_obj_t *pin) {
|
||||
if (!pin->has_adc) {
|
||||
uint8_t adc_index;
|
||||
uint8_t adc_channel = 0xff;
|
||||
for (adc_index = 0; adc_index < NUM_ADC_PER_PIN; adc_index++) {
|
||||
// TODO(tannewt): Only use ADC0 on the SAMD51 when touch isn't being
|
||||
// used.
|
||||
if (pin->adc_input[adc_index] != 0xff) {
|
||||
adc_channel = pin->adc_input[adc_index];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (adc_channel == 0xff) {
|
||||
// No ADC function on that pin
|
||||
mp_raise_ValueError("Pin does not have ADC capabilities");
|
||||
}
|
||||
claim_pin(pin);
|
||||
|
||||
gpio_set_pin_function(pin->pin, GPIO_PIN_FUNCTION_B);
|
||||
|
||||
static Adc* adc_insts[] = ADC_INSTS;
|
||||
self->instance = adc_insts[adc_index];
|
||||
self->channel = adc_channel;
|
||||
self->pin = pin;
|
||||
}
|
||||
|
||||
|
@ -68,21 +89,62 @@ uint16_t common_hal_analogio_analogin_get_value(analogio_analogin_obj_t *self) {
|
|||
// Something else might have used the ADC in a different way,
|
||||
// so we completely re-initialize it.
|
||||
|
||||
struct adc_config config_adc;
|
||||
adc_get_config_defaults(&config_adc);
|
||||
// Turn the clocks on.
|
||||
#ifdef SAMD51
|
||||
if (self->instance == ADC0) {
|
||||
hri_mclk_set_APBDMASK_ADC0_bit(MCLK);
|
||||
hri_gclk_write_PCHCTRL_reg(GCLK, ADC0_GCLK_ID, GCLK_PCHCTRL_GEN_GCLK1_Val | (1 << GCLK_PCHCTRL_CHEN_Pos));
|
||||
} else if (self->instance == ADC1) {
|
||||
hri_mclk_set_APBDMASK_ADC1_bit(MCLK);
|
||||
hri_gclk_write_PCHCTRL_reg(GCLK, ADC1_GCLK_ID, GCLK_PCHCTRL_GEN_GCLK1_Val | (1 << GCLK_PCHCTRL_CHEN_Pos));
|
||||
}
|
||||
#endif
|
||||
|
||||
config_adc.reference = ADC_REFERENCE_INTVCC1;
|
||||
config_adc.gain_factor = ADC_GAIN_FACTOR_DIV2;
|
||||
config_adc.positive_input = self->pin->adc_input;
|
||||
config_adc.resolution = ADC_RESOLUTION_12BIT;
|
||||
// Default input clock is GCLK0 (48 MHz)
|
||||
// 48Mhz / 32 = 1.5MHz. Max ADC clock is 2.1MHz
|
||||
config_adc.clock_prescaler = ADC_CLOCK_PRESCALER_DIV32;
|
||||
#ifdef SAMD21
|
||||
_pm_enable_bus_clock(PM_BUS_APBC, ADC);
|
||||
_gclk_enable_channel(ADC_GCLK_ID, GCLK_CLKCTRL_GEN_GCLK0_Val);
|
||||
#endif
|
||||
|
||||
struct adc_module adc_instance;
|
||||
// ADC must have been disabled before adc_init() is called.
|
||||
adc_init(&adc_instance, ADC, &config_adc);
|
||||
adc_enable(&adc_instance);
|
||||
struct adc_sync_descriptor adc;
|
||||
adc_sync_init(&adc, self->instance, (void *)NULL);
|
||||
adc_sync_set_reference(&adc, ADC_REFCTRL_REFSEL_INTVCC1_Val);
|
||||
adc_sync_set_resolution(&adc, ADC_CTRLB_RESSEL_12BIT_Val);
|
||||
|
||||
#ifdef SAMD21
|
||||
adc_sync_set_channel_gain(&adc, self->channel, ADC_INPUTCTRL_GAIN_DIV2_Val);
|
||||
|
||||
// Load the factory calibration
|
||||
hri_adc_write_CALIB_BIAS_CAL_bf(ADC, (*((uint32_t*) ADC_FUSES_BIASCAL_ADDR) & ADC_FUSES_BIASCAL_Msk) >> ADC_FUSES_BIASCAL_Pos);
|
||||
// Bits 7:5
|
||||
uint16_t linearity = ((*((uint32_t*) ADC_FUSES_LINEARITY_1_ADDR) & ADC_FUSES_LINEARITY_1_Msk) >> ADC_FUSES_LINEARITY_1_Pos) << 5;
|
||||
// Bits 4:0
|
||||
linearity |= (*((uint32_t*) ADC_FUSES_LINEARITY_0_ADDR) & ADC_FUSES_LINEARITY_0_Msk) >> ADC_FUSES_LINEARITY_0_Pos;
|
||||
hri_adc_write_CALIB_LINEARITY_CAL_bf(ADC, linearity);
|
||||
#endif
|
||||
|
||||
// SAMD51 has a CALIB register but doesn't have documented fuses for them.
|
||||
#ifdef SAMD51
|
||||
uint8_t biasrefbuf;
|
||||
uint8_t biasr2r;
|
||||
uint8_t biascomp;
|
||||
if (self->instance == ADC0) {
|
||||
biasrefbuf = ((*(uint32_t*) ADC0_FUSES_BIASREFBUF_ADDR) & ADC0_FUSES_BIASREFBUF_Msk) >> ADC0_FUSES_BIASREFBUF_Pos;
|
||||
biasr2r = ((*(uint32_t*) ADC0_FUSES_BIASR2R_ADDR) & ADC0_FUSES_BIASR2R_Msk) >> ADC0_FUSES_BIASR2R_Pos;
|
||||
biascomp = ((*(uint32_t*) ADC0_FUSES_BIASCOMP_ADDR) & ADC0_FUSES_BIASCOMP_Msk) >> ADC0_FUSES_BIASCOMP_Pos;
|
||||
} else {
|
||||
biasrefbuf = ((*(uint32_t*) ADC1_FUSES_BIASREFBUF_ADDR) & ADC1_FUSES_BIASREFBUF_Msk) >> ADC1_FUSES_BIASREFBUF_Pos;
|
||||
biasr2r = ((*(uint32_t*) ADC1_FUSES_BIASR2R_ADDR) & ADC1_FUSES_BIASR2R_Msk) >> ADC1_FUSES_BIASR2R_Pos;
|
||||
biascomp = ((*(uint32_t*) ADC1_FUSES_BIASCOMP_ADDR) & ADC1_FUSES_BIASCOMP_Msk) >> ADC1_FUSES_BIASCOMP_Pos;
|
||||
}
|
||||
hri_adc_write_CALIB_BIASREFBUF_bf(self->instance, biasrefbuf);
|
||||
hri_adc_write_CALIB_BIASR2R_bf(self->instance, biasr2r);
|
||||
hri_adc_write_CALIB_BIASCOMP_bf(self->instance, biascomp);
|
||||
#endif
|
||||
|
||||
adc_sync_enable_channel(&adc, self->channel);
|
||||
|
||||
// We need to set the inputs because the above channel enable only enables the ADC.
|
||||
adc_sync_set_inputs(&adc, self->channel, ADC_INPUTCTRL_MUXNEG_GND_Val, self->channel);
|
||||
|
||||
// Read twice and discard first result, as recommended in section 14 of
|
||||
// http://www.atmel.com/images/Atmel-42645-ADC-Configurations-with-Examples_ApplicationNote_AT11481.pdf
|
||||
|
@ -90,28 +152,13 @@ uint16_t common_hal_analogio_analogin_get_value(analogio_analogin_obj_t *self) {
|
|||
// like voltage reference / ADC channel change"
|
||||
// Empirical observation shows the first reading is quite different than subsequent ones.
|
||||
|
||||
uint16_t data;
|
||||
enum status_code status;
|
||||
uint16_t value;
|
||||
adc_sync_read_channel(&adc, self->channel, ((uint8_t*) &value), 2);
|
||||
adc_sync_read_channel(&adc, self->channel, ((uint8_t*) &value), 2);
|
||||
|
||||
adc_start_conversion(&adc_instance);
|
||||
do {
|
||||
status = adc_read(&adc_instance, &data);
|
||||
} while (status == STATUS_BUSY);
|
||||
if (status == STATUS_ERR_OVERFLOW) {
|
||||
mp_raise_RuntimeError("ADC result overwritten before reading");
|
||||
}
|
||||
|
||||
adc_start_conversion(&adc_instance);
|
||||
do {
|
||||
status = adc_read(&adc_instance, &data);
|
||||
} while (status == STATUS_BUSY);
|
||||
if (status == STATUS_ERR_OVERFLOW) {
|
||||
mp_raise_RuntimeError("ADC result overwritten before reading");
|
||||
}
|
||||
|
||||
adc_disable(&adc_instance);
|
||||
// Scale to 16 bits. In the future we might make this be this be under API control.
|
||||
return data * 16;
|
||||
adc_sync_deinit(&adc);
|
||||
// Shift the value to be 16 bit.
|
||||
return value << 4;
|
||||
}
|
||||
|
||||
float common_hal_analogio_analogin_get_reference_voltage(analogio_analogin_obj_t *self) {
|
||||
|
|
|
@ -34,6 +34,8 @@
|
|||
typedef struct {
|
||||
mp_obj_base_t base;
|
||||
const mcu_pin_obj_t * pin;
|
||||
Adc* instance;
|
||||
uint8_t channel;
|
||||
} analogio_analogin_obj_t;
|
||||
|
||||
void analogin_reset(void);
|
||||
|
|
|
@ -31,32 +31,72 @@
|
|||
#include "py/runtime.h"
|
||||
|
||||
#include "shared-bindings/analogio/AnalogOut.h"
|
||||
#include "shared-bindings/microcontroller/Pin.h"
|
||||
|
||||
#include "asf/sam0/drivers/dac/dac.h"
|
||||
#include "samd21_pins.h"
|
||||
#include "atmel_start_pins.h"
|
||||
#include "hal/include/hal_dac_sync.h"
|
||||
#include "hpl/gclk/hpl_gclk_base.h"
|
||||
|
||||
#ifdef SAMD21
|
||||
#include "hpl/pm/hpl_pm_base.h"
|
||||
#endif
|
||||
|
||||
#ifdef SAMD51
|
||||
#include "samd51_pins.h"
|
||||
#endif
|
||||
|
||||
void common_hal_analogio_analogout_construct(analogio_analogout_obj_t* self,
|
||||
const mcu_pin_obj_t *pin) {
|
||||
if (pin->pin != PIN_PA02) {
|
||||
if (pin->pin != PIN_PA02
|
||||
#ifdef SAMD51
|
||||
&& pin->pin != PIN_PA05
|
||||
#endif
|
||||
) {
|
||||
mp_raise_ValueError("AnalogOut not supported on given pin");
|
||||
return;
|
||||
}
|
||||
struct dac_config config_dac;
|
||||
dac_get_config_defaults(&config_dac);
|
||||
config_dac.reference = DAC_REFERENCE_AVCC;
|
||||
enum status_code status = dac_init(&self->dac_instance, DAC, &config_dac);
|
||||
if (status != STATUS_OK) {
|
||||
|
||||
self->channel = 0;
|
||||
#ifdef SAMD51
|
||||
if (pin->pin == PIN_PA05) {
|
||||
self->channel = 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef SAMD51
|
||||
hri_mclk_set_APBDMASK_DAC_bit(MCLK);
|
||||
hri_gclk_write_PCHCTRL_reg(GCLK, DAC_GCLK_ID, GCLK_PCHCTRL_GEN_GCLK5_Val | (1 << GCLK_PCHCTRL_CHEN_Pos));
|
||||
#endif
|
||||
|
||||
#ifdef SAMD21
|
||||
_pm_enable_bus_clock(PM_BUS_APBC, DAC);
|
||||
_gclk_enable_channel(DAC_GCLK_ID, GCLK_CLKCTRL_GEN_GCLK0_Val);
|
||||
#endif
|
||||
|
||||
// Don't double init the DAC on the SAMD51 when both outputs are in use. We use the free state
|
||||
// of each output pin to determine DAC state.
|
||||
int32_t result = ERR_NONE;
|
||||
#ifdef SAMD51
|
||||
if (!common_hal_mcu_pin_is_free(&pin_PA02) || !common_hal_mcu_pin_is_free(&pin_PA05)) {
|
||||
#endif
|
||||
// Fake the descriptor if the DAC is already initialized.
|
||||
self->descriptor.device.hw = DAC;
|
||||
#ifdef SAMD51
|
||||
} else {
|
||||
#endif
|
||||
result = dac_sync_init(&self->descriptor, DAC);
|
||||
#ifdef SAMD51
|
||||
}
|
||||
#endif
|
||||
if (result != ERR_NONE) {
|
||||
mp_raise_OSError(MP_EIO);
|
||||
return;
|
||||
}
|
||||
claim_pin(pin);
|
||||
|
||||
struct dac_chan_config config_analogout_chan;
|
||||
dac_chan_get_config_defaults(&config_analogout_chan);
|
||||
dac_chan_set_config(&self->dac_instance, DAC_CHANNEL_0, &config_analogout_chan);
|
||||
dac_chan_enable(&self->dac_instance, DAC_CHANNEL_0);
|
||||
gpio_set_pin_function(pin->pin, GPIO_PIN_FUNCTION_B);
|
||||
|
||||
dac_enable(&self->dac_instance);
|
||||
dac_sync_enable_channel(&self->descriptor, self->channel);
|
||||
}
|
||||
|
||||
bool common_hal_analogio_analogout_deinited(analogio_analogout_obj_t *self) {
|
||||
|
@ -67,14 +107,35 @@ void common_hal_analogio_analogout_deinit(analogio_analogout_obj_t *self) {
|
|||
if (common_hal_analogio_analogout_deinited(self)) {
|
||||
return;
|
||||
}
|
||||
dac_disable(&self->dac_instance);
|
||||
dac_chan_disable(&self->dac_instance, DAC_CHANNEL_0);
|
||||
dac_sync_disable_channel(&self->descriptor, self->channel);
|
||||
reset_pin(PIN_PA02);
|
||||
// Only deinit the DAC on the SAMD51 if both outputs are free.
|
||||
#ifdef SAMD51
|
||||
if (common_hal_mcu_pin_is_free(&pin_PA02) && common_hal_mcu_pin_is_free(&pin_PA05)) {
|
||||
#endif
|
||||
dac_sync_deinit(&self->descriptor);
|
||||
#ifdef SAMD51
|
||||
}
|
||||
#endif
|
||||
self->deinited = true;
|
||||
// TODO(tannewt): Turn off the DAC clocks to save power.
|
||||
}
|
||||
|
||||
void common_hal_analogio_analogout_set_value(analogio_analogout_obj_t *self,
|
||||
uint16_t value) {
|
||||
// Input is 16 bit but we only support 10 bit so we shift the input.
|
||||
dac_chan_write(&self->dac_instance, DAC_CHANNEL_0, value >> 6);
|
||||
// Input is 16 bit so make sure and set LEFTADJ to 1 to it takes the top
|
||||
// bits. This is currently done in asf4_conf/*/hpl_dac_config.h.
|
||||
dac_sync_write(&self->descriptor, self->channel, &value, 1);
|
||||
}
|
||||
|
||||
void analogout_reset(void) {
|
||||
#ifdef SAMD21
|
||||
while (DAC->STATUS.reg & DAC_STATUS_SYNCBUSY) {}
|
||||
#endif
|
||||
#ifdef SAMD51
|
||||
while (DAC->SYNCBUSY.reg & DAC_SYNCBUSY_SWRST) {}
|
||||
#endif
|
||||
DAC->CTRLA.reg |= DAC_CTRLA_SWRST;
|
||||
|
||||
// TODO(tannewt): Turn off the DAC clocks to save power.
|
||||
}
|
||||
|
|
|
@ -29,14 +29,17 @@
|
|||
|
||||
#include "common-hal/microcontroller/Pin.h"
|
||||
|
||||
#include "asf/sam0/drivers/dac/dac.h"
|
||||
#include "hal/include/hal_dac_sync.h"
|
||||
|
||||
#include "py/obj.h"
|
||||
|
||||
typedef struct {
|
||||
mp_obj_base_t base;
|
||||
struct dac_module dac_instance;
|
||||
struct dac_sync_descriptor descriptor;
|
||||
uint8_t channel;
|
||||
bool deinited;
|
||||
} analogio_analogout_obj_t;
|
||||
|
||||
void analogout_reset(void);
|
||||
|
||||
#endif // MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_ANALOGIO_ANALOGOUT_H
|
||||
|
|
|
@ -212,14 +212,13 @@ extern const struct _mp_obj_module_t usb_hid_module;
|
|||
|
||||
// Disabled for now.
|
||||
// { MP_OBJ_NEW_QSTR(MP_QSTR_touchio), (mp_obj_t)&touchio_module },
|
||||
// { MP_OBJ_NEW_QSTR(MP_QSTR_analogio), (mp_obj_t)&analogio_module },
|
||||
|
||||
// { MP_OBJ_NEW_QSTR(MP_QSTR_gamepad),(mp_obj_t)&gamepad_module },
|
||||
// { MP_OBJ_NEW_QSTR(MP_QSTR__stage), (mp_obj_t)&stage_module },
|
||||
// { MP_OBJ_NEW_QSTR(MP_QSTR_usb_hid),(mp_obj_t)&usb_hid_module },
|
||||
|
||||
|
||||
#define MICROPY_PORT_BUILTIN_MODULES \
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_analogio), (mp_obj_t)&analogio_module }, \
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_board), (mp_obj_t)&board_module }, \
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_busio), (mp_obj_t)&busio_module }, \
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_digitalio), (mp_obj_t)&digitalio_module }, \
|
||||
|
|
|
@ -43,7 +43,8 @@
|
|||
#include "hri/hri_rstc_d51.h"
|
||||
#endif
|
||||
|
||||
|
||||
#include "common-hal/analogio/AnalogIn.h"
|
||||
#include "common-hal/analogio/AnalogOut.h"
|
||||
#include "common-hal/microcontroller/Pin.h"
|
||||
#include "tick.h"
|
||||
|
||||
|
@ -207,16 +208,14 @@ void reset_port(void) {
|
|||
// pulseout_reset();
|
||||
// pwmout_reset();
|
||||
// #endif
|
||||
//
|
||||
// analogin_reset();
|
||||
//
|
||||
|
||||
analogin_reset();
|
||||
|
||||
// #ifdef CIRCUITPY_GAMEPAD_TICKS
|
||||
// gamepad_reset();
|
||||
// #endif
|
||||
//
|
||||
// // Wait for the DAC to sync then reset.
|
||||
// while (DAC->STATUS.reg & DAC_STATUS_SYNCBUSY) {}
|
||||
// DAC->CTRLA.reg |= DAC_CTRLA_SWRST;
|
||||
analogout_reset();
|
||||
|
||||
reset_all_pins();
|
||||
//
|
||||
|
@ -276,9 +275,9 @@ void reset_port(void) {
|
|||
*/
|
||||
__attribute__((used)) void HardFault_Handler(void)
|
||||
{
|
||||
while (true) {
|
||||
while (true) {
|
||||
asm("");
|
||||
}
|
||||
}
|
||||
for (uint32_t i = 0; i < 100000; i++) {
|
||||
asm("noop;");
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue