-
Notifications
You must be signed in to change notification settings - Fork 72
Core api update analog io #352
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
12 commits
Select commit
Hold shift + click to select a range
a470185
variants/xmc4700: Reactivate pin definition for analog.
LinjingZhang 2c1a25d
cores/xmc: Checkpoint working dac in analog.
LinjingZhang 0452325
cores/xmc: Add working analo module.
LinjingZhang 28279e2
tests/test_config.h: Update for analogio tests.
LinjingZhang e5f3f64
arduino-core-tests: Update to main.
LinjingZhang 000451e
cores/xmc: Improve macro defines for analogIO.
LinjingZhang 2ff06e2
variants: Change all ENABLED and DISABLED macro to false and true.
LinjingZhang ceb5b82
cores/xmc: Clean up analog module.
LinjingZhang c5113a7
docs: Adding doc for analogIO.
LinjingZhang 72d6bf9
tests/: Update test_config for analog tests.
LinjingZhang ce88161
tests: Update arduino-core-tests with dac tests and fix.
LinjingZhang ac53ff2
ci-matrix-config.yml: Add analog example.
LinjingZhang File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,282 @@ | ||
//**************************************************************************** | ||
// @File: wiring_analog.cpp | ||
// @Brief: Analog and PWM/DAC API implementation for XMC Arduino core | ||
//**************************************************************************** | ||
#include "Arduino.h" | ||
|
||
//**************************************************************************** | ||
// @Defines | ||
//**************************************************************************** | ||
#define ADC_CONVERSION_GROUP 0 | ||
#define ADC_MIN_RESOLUTION 8 | ||
#define ADC_MAX_READ_RESOLUTION 12 | ||
#define ANALOG_MAX_WRITE_RESOLUTION 16 | ||
|
||
//**************************************************************************** | ||
// @Global Variables | ||
//**************************************************************************** | ||
static XMC_VADC_CHANNEL_REF_t analog_reference = DEFAULT; | ||
static uint8_t _readResolution = 10; | ||
static uint8_t _writeResolution = 8; | ||
uint16_t _readMaximum = 1023; | ||
uint16_t _writeMaximum = 255; | ||
static bool vadc_inited = false; | ||
|
||
//**************************************************************************** | ||
// @Function: scan_map_table | ||
// @Brief: Lookup table for pin to resource mapping | ||
//**************************************************************************** | ||
int16_t scan_map_table(const uint8_t table[][2], uint8_t pin) { | ||
int16_t i = 0; | ||
while (table[i][0] != 255) { | ||
if (table[i][0] == pin) | ||
break; | ||
i++; | ||
} | ||
if (table[i][0] != 255) | ||
return table[i][1]; | ||
return -1; | ||
} | ||
|
||
//**************************************************************************** | ||
// @Function: analogReference | ||
// @Brief: Sets the ADC reference voltage type. Only default (Varef = Vdda) is available. | ||
//**************************************************************************** | ||
void analogReference(uint8_t mode) { | ||
switch (mode) { | ||
case DEFAULT: | ||
analog_reference = XMC_VADC_CHANNEL_REF_INTREF; | ||
break; | ||
default: | ||
// Invalid mode, do nothing | ||
break; | ||
} | ||
} | ||
|
||
//**************************************************************************** | ||
// @Function: analogWriteResolution | ||
// @Brief: Sets the resolution for analogWrite (PWM/DAC) | ||
//**************************************************************************** | ||
void analogWriteResolution(int res) { | ||
if (res > ANALOG_MAX_WRITE_RESOLUTION) { | ||
_writeResolution = ANALOG_MAX_WRITE_RESOLUTION; | ||
} else if (res < ADC_MIN_RESOLUTION) { | ||
_writeResolution = ADC_MIN_RESOLUTION; | ||
} else { | ||
_writeResolution = res; | ||
} | ||
_writeMaximum = (uint16_t)(((uint32_t)1U << _writeResolution) - 1); | ||
} | ||
|
||
//**************************************************************************** | ||
// @Function: analogWrite | ||
// @Brief: Outputs PWM or DAC value to the specified pin | ||
//**************************************************************************** | ||
void analogWrite(pin_size_t pinNumber, int value) { | ||
uint32_t compare_reg = 0; | ||
int16_t resource; | ||
if (value < 0 || value > _writeMaximum) | ||
return; | ||
// Check if the pin supports PWM4 | ||
resource = scan_map_table(mapping_pin_PWM4, pinNumber); | ||
if (resource >= 0) { | ||
XMC_PWM4_t *pwm4 = &mapping_pwm4[resource]; | ||
if (!(pwm4->enabled)) { | ||
// Slice not yet initialized | ||
XMC_CCU4_SLICE_COMPARE_CONFIG_t pwm_config; | ||
memset(&pwm_config, 0, sizeof(XMC_CCU4_SLICE_COMPARE_CONFIG_t)); | ||
pwm_config.passive_level = XMC_CCU4_SLICE_OUTPUT_PASSIVE_LEVEL_HIGH; | ||
pwm_config.prescaler_initval = pwm4->prescaler; | ||
XMC_CCU4_Init(pwm4->ccu, XMC_CCU4_SLICE_MCMS_ACTION_TRANSFER_PR_CR); | ||
XMC_CCU4_SLICE_CompareInit(pwm4->slice, &pwm_config); | ||
XMC_CCU4_EnableClock(pwm4->ccu, pwm4->slice_num); | ||
XMC_CCU4_SLICE_SetTimerPeriodMatch(pwm4->slice, pwm4->period_timer_val); | ||
pwm4->enabled = true; | ||
} | ||
if (value != 0) | ||
compare_reg = ((value + 1) * (pwm4->period_timer_val + 1)) >> _writeResolution; | ||
XMC_CCU4_SLICE_SetTimerCompareMatch(pwm4->slice, compare_reg); | ||
XMC_CCU4_EnableShadowTransfer(pwm4->ccu, (CCU4_GCSS_S0SE_Msk << (4 * pwm4->slice_num))); | ||
XMC_GPIO_SetMode(pwm4->port_pin.port, pwm4->port_pin.pin, | ||
(XMC_GPIO_MODE_t)(XMC_GPIO_MODE_OUTPUT_PUSH_PULL | pwm4->port_mode)); | ||
XMC_CCU4_SLICE_StartTimer(pwm4->slice); | ||
|
||
return; | ||
} | ||
#if defined(CCU8V2) || defined(CCU8V1) | ||
// Check if the pin supports PWM8 | ||
else if ((resource = scan_map_table(mapping_pin_PWM8, pinNumber)) >= 0) { | ||
XMC_PWM8_t *pwm8 = &mapping_pwm8[resource]; | ||
if (!(pwm8->enabled)) { | ||
// Slice not yet initialized | ||
XMC_CCU8_SLICE_COMPARE_CONFIG_t pwm_config; | ||
memset(&pwm_config, 0, sizeof(XMC_CCU8_SLICE_COMPARE_CONFIG_t)); | ||
pwm_config.passive_level_out0 = XMC_CCU8_SLICE_OUTPUT_PASSIVE_LEVEL_HIGH; | ||
pwm_config.passive_level_out1 = XMC_CCU8_SLICE_OUTPUT_PASSIVE_LEVEL_HIGH; | ||
pwm_config.passive_level_out2 = XMC_CCU8_SLICE_OUTPUT_PASSIVE_LEVEL_HIGH; | ||
pwm_config.passive_level_out3 = XMC_CCU8_SLICE_OUTPUT_PASSIVE_LEVEL_HIGH; | ||
pwm_config.prescaler_initval = pwm8->prescaler; | ||
XMC_CCU8_Init(pwm8->ccu, XMC_CCU8_SLICE_MCMS_ACTION_TRANSFER_PR_CR); | ||
XMC_CCU8_SLICE_CompareInit(pwm8->slice, &pwm_config); | ||
XMC_CCU8_EnableClock(pwm8->ccu, pwm8->slice_num); | ||
XMC_CCU8_SLICE_SetTimerPeriodMatch(pwm8->slice, pwm8->period_timer_val); | ||
pwm8->enabled = true; | ||
} | ||
if (value != 0) | ||
compare_reg = ((value + 1) * (pwm8->period_timer_val + 1)) >> _writeResolution; | ||
XMC_CCU8_SLICE_SetTimerCompareMatch(pwm8->slice, pwm8->slice_channel, compare_reg); | ||
XMC_CCU8_EnableShadowTransfer(pwm8->ccu, CCU8_GCSS_S0SE_Msk << (4 * pwm8->slice_num)); | ||
XMC_GPIO_SetMode(pwm8->port_pin.port, pwm8->port_pin.pin, | ||
(XMC_GPIO_MODE_t)(XMC_GPIO_MODE_OUTPUT_PUSH_PULL | pwm8->port_mode)); | ||
XMC_CCU8_SLICE_StartTimer(pwm8->slice); | ||
return; | ||
} | ||
#endif | ||
#ifdef DAC | ||
// Check if the pin supports DAC | ||
else if ((resource = scan_map_table(mapping_pin_DAC, pinNumber)) >= 0) { | ||
XMC_ARD_DAC_t *dac = &(mapping_dac[resource]); | ||
XMC_DAC_Enable(dac->group); | ||
XMC_DAC_CH_EnableOutput(dac->group, dac->channel); | ||
XMC_DAC_CH_StartSingleValueMode(dac->group, dac->channel); | ||
uint16_t dacValue = | ||
map(value, 0, (0b10 << _writeResolution) - 1, 0, (0b10 << dac->resolution) - 1); | ||
XMC_DAC_CH_Write(dac->group, dac->channel, dacValue); | ||
return; | ||
} | ||
#endif | ||
// If not found, do nothing | ||
return; | ||
} | ||
|
||
//**************************************************************************** | ||
// @Function: wiring_analog_init | ||
// @Brief: Initializes VADC and related analog resources (runs only once) | ||
//**************************************************************************** | ||
void wiring_analog_init(void) { | ||
if (vadc_inited) | ||
return; | ||
vadc_inited = true; | ||
/* Initialization data of VADC Global resources */ | ||
XMC_VADC_GLOBAL_CONFIG_t vadc_global_config; | ||
memset(&vadc_global_config, 0, sizeof(XMC_VADC_GLOBAL_CONFIG_t)); | ||
vadc_global_config.class0.conversion_mode_standard = XMC_VADC_CONVMODE_12BIT; | ||
vadc_global_config.class1.conversion_mode_standard = XMC_VADC_CONVMODE_12BIT; | ||
|
||
XMC_VADC_BACKGROUND_CONFIG_t vadc_background_config = {0}; | ||
|
||
/* Provide clock to VADC and initialize the VADC global registers. */ | ||
XMC_VADC_GLOBAL_Init(VADC, &vadc_global_config); | ||
|
||
#if (XMC_VADC_GROUP_AVAILABLE == 1U) | ||
// ADC grouping | ||
XMC_VADC_GROUP_CONFIG_t vadc_group_config; | ||
memset(&vadc_group_config, 0, sizeof(XMC_VADC_GROUP_CONFIG_t)); | ||
vadc_group_config.class0.conversion_mode_standard = XMC_VADC_CONVMODE_12BIT; | ||
vadc_group_config.class1.conversion_mode_standard = XMC_VADC_CONVMODE_12BIT; | ||
|
||
/* Initialize Group */ | ||
XMC_VADC_GROUP_Init(VADC_G0, &vadc_group_config); | ||
XMC_VADC_GROUP_Init(VADC_G1, &vadc_group_config); | ||
|
||
/* Switch on the converter of the Group*/ | ||
XMC_VADC_GROUP_SetPowerMode(VADC_G0, XMC_VADC_GROUP_POWERMODE_NORMAL); | ||
XMC_VADC_GROUP_SetPowerMode(VADC_G1, XMC_VADC_GROUP_POWERMODE_NORMAL); | ||
|
||
#if (XMC_VADC_MAXIMUM_NUM_GROUPS > 2) | ||
/* Initialize Group */ | ||
XMC_VADC_GROUP_Init(VADC_G2, &vadc_group_config); | ||
XMC_VADC_GROUP_Init(VADC_G3, &vadc_group_config); | ||
|
||
/* Switch on the converter of the Group*/ | ||
XMC_VADC_GROUP_SetPowerMode(VADC_G2, XMC_VADC_GROUP_POWERMODE_NORMAL); | ||
XMC_VADC_GROUP_SetPowerMode(VADC_G3, XMC_VADC_GROUP_POWERMODE_NORMAL); | ||
#endif | ||
|
||
#endif | ||
/* Calibrate the VADC. Make sure you do this after all used VADC groups | ||
are set to normal operation mode. */ | ||
XMC_VADC_GLOBAL_StartupCalibration(VADC); | ||
|
||
/* Initialize the background source hardware. The gating mode is set to | ||
ignore to pass external triggers unconditionally.*/ | ||
XMC_VADC_GLOBAL_BackgroundInit(VADC, &vadc_background_config); | ||
|
||
/* Dummy read of ALL analogue inputs to ensure ALL analogue channels are | ||
started in background scanning mode, otherwise first readings at least | ||
will always be zero on reading an analogue input. */ | ||
for (uint8_t chan = 0; chan < NUM_ANALOG_INPUTS; chan++) | ||
analogRead(chan); | ||
|
||
// Additional Initialization of DAC starting here | ||
} | ||
|
||
//**************************************************************************** | ||
// @Function: analogReadResolution | ||
// @Brief: Sets the resolution for analogRead (ADC) | ||
//**************************************************************************** | ||
void analogReadResolution(int res) { | ||
if (res > ADC_MAX_READ_RESOLUTION) { | ||
_readResolution = ADC_MAX_READ_RESOLUTION; | ||
} else if (res < ADC_MIN_RESOLUTION) { | ||
_readResolution = ADC_MIN_RESOLUTION; | ||
} else { | ||
_readResolution = res; | ||
} | ||
_readMaximum = (uint16_t)(((uint32_t)1U << _readResolution) - 1); | ||
} | ||
|
||
//**************************************************************************** | ||
// @Function: analogRead | ||
// @Brief: Reads the analog value from the specified pin | ||
//**************************************************************************** | ||
int analogRead(pin_size_t pinNumber) { | ||
|
||
wiring_analog_init(); | ||
uint32_t value; | ||
|
||
value = 0xFFFFFFFF; | ||
if (pinNumber < NUM_ANALOG_INPUTS) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Copilot uses AI. Check for mistakes. Positive FeedbackNegative Feedback |
||
XMC_ADC_t *adc = &mapping_adc[pinNumber]; | ||
|
||
#if (XMC_VADC_GROUP_AVAILABLE == 1U) | ||
// ADC grouping | ||
if (!(adc->enabled)) { | ||
XMC_VADC_CHANNEL_CONFIG_t vadc_gobal_channel_config; | ||
memset(&vadc_gobal_channel_config, 0, sizeof(XMC_VADC_CHANNEL_CONFIG_t)); | ||
vadc_gobal_channel_config.input_class = XMC_VADC_CHANNEL_CONV_GROUP_CLASS1; | ||
vadc_gobal_channel_config.result_reg_number = adc->result_reg_num; | ||
vadc_gobal_channel_config.alias_channel = XMC_VADC_CHANNEL_ALIAS_DISABLED; | ||
|
||
XMC_VADC_RESULT_CONFIG_t vadc_gobal_result_config = {.g_rcr = 0}; | ||
/* Configure a channel belonging to the aforesaid conversion kernel */ | ||
XMC_VADC_GROUP_ChannelInit(adc->group, adc->channel_num, &vadc_gobal_channel_config); | ||
/* Configure a result resource belonging to the aforesaid conversion kernel */ | ||
XMC_VADC_GROUP_ResultInit(adc->group, adc->result_reg_num, &vadc_gobal_result_config); | ||
/* Add channel into the Background Request Source Channel Select Register */ | ||
XMC_VADC_GLOBAL_BackgroundAddChannelToSequence(VADC, (uint32_t)adc->group_num, | ||
(uint32_t)adc->channel_num); | ||
} | ||
/* Start conversion manually using load event trigger*/ | ||
XMC_VADC_GLOBAL_BackgroundTriggerConversion(VADC); | ||
value = XMC_VADC_GROUP_GetResult(adc->group, adc->result_reg_num); | ||
#else | ||
// XMC1100 no ADC grouping | ||
if (!(adc->enabled)) | ||
/* Add a channel to the background source. */ | ||
VADC->BRSSEL[ADC_CONVERSION_GROUP] = (uint32_t)(1U << adc->channel_num); | ||
// Generates conversion request | ||
XMC_VADC_GLOBAL_BackgroundTriggerConversion(VADC); | ||
|
||
// Wait until conversion is ready | ||
while (((value = XMC_VADC_GLOBAL_GetDetailedResult(VADC)) & VADC_GLOBRES_VF_Msk) == 0u) | ||
; | ||
#endif | ||
value = ((value & VADC_GLOBRES_RESULT_Msk) >> (ADC_MAX_READ_RESOLUTION - _readResolution)); | ||
} | ||
return value; | ||
} | ||
|
||
//**************************************************************************** | ||
// END OF FILE | ||
//**************************************************************************** |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is no longer called anywhere?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is called in analogRead(), since it only initialize ADC