diff --git a/drivers/rx/README b/drivers/rx/README index bbb2bcca..b3cbab0c 100644 --- a/drivers/rx/README +++ b/drivers/rx/README @@ -91,3 +91,7 @@ Patch List: * Add the header file Impacted files: drivers/rx/rdp/src/r_bsp/mcu/rx130/mcu_clocks.h + + * Remove unsed variables to fix build warnings + Impacted files: + drivers/rx/rdp/src/r_s12ad_rx/src/targets/rx261/r_s12ad_rx261.c diff --git a/drivers/rx/rdp/src/r_s12ad_rx/src/targets/rx261/r_s12ad_rx261.c b/drivers/rx/rdp/src/r_s12ad_rx/src/targets/rx261/r_s12ad_rx261.c new file mode 100644 index 00000000..cb2e270c --- /dev/null +++ b/drivers/rx/rdp/src/r_s12ad_rx/src/targets/rx261/r_s12ad_rx261.c @@ -0,0 +1,1223 @@ +/*********************************************************************************************************************** +* Copyright (c) 2021 Renesas Electronics Corporation and/or its affiliates +* +* SPDX-License-Identifier: BSD-3-Clause +***********************************************************************************************************************/ +/*********************************************************************************************************************** +* File Name : r_s12ad_rx261.c +* Description : Primary source code for 12-bit A/D Converter driver. +***********************************************************************************************************************/ +/********************************************************************************************************************** +* History : DD.MM.YYYY Version Description +* 30.07.2021 1.00 Initial Release. +* 20.03.2025 5.41 Changed the disclaimer in program sources. +***********************************************************************************************************************/ + +/*********************************************************************************************************************** +Includes , "Project Includes" +***********************************************************************************************************************/ +/* Includes board and MCU related header files. */ +#include +#include "platform.h" + +#if defined (BSP_MCU_RX261) +#include "r_s12ad_rx_config.h" +#include "r_s12ad_rx_private.h" +#include "r_s12ad_rx_if.h" + +/*********************************************************************************************************************** +Macro definitions +***********************************************************************************************************************/ + +/*********************************************************************************************************************** +Typedef definitions +***********************************************************************************************************************/ +typedef R_BSP_VOLATILE_EVENACCESS struct st_s12ad aregs_t; + +/*********************************************************************************************************************** +Private global variables and functions +***********************************************************************************************************************/ + +/* In RAM */ +extern adc_ctrl_t g_dcb; + +/* In ROM. A/D Data Register pointers */ +volatile uint16_t R_BSP_EVENACCESS_SFR * const gp_dreg_ptrs[ADC_REG_MAX+1] = + { &S12AD.ADDR0, /* channel 0 */ + &S12AD.ADDR1, /* channel 1 */ + &S12AD.ADDR2, /* channel 2 */ + &S12AD.ADDR3, /* channel 3 */ + &S12AD.ADDR4, /* channel 4 */ + &S12AD.ADDR5, /* channel 5 */ + &S12AD.ADDR6, /* channel 6 */ + &S12AD.ADDR7, /* channel 7 */ + &S12AD.ADDR8, /* channel 8 */ + &S12AD.ADDR16, /* channel 16 */ + &S12AD.ADDR17, /* channel 17 */ + &S12AD.ADDR18, /* channel 18 */ + &S12AD.ADDR19, /* channel 19 */ + &S12AD.ADDR20, /* channel 20 */ + &S12AD.ADDR21, /* channel 21 */ + &S12AD.ADDR22, /* channel 22 */ + &S12AD.ADDR23, /* channel 23 */ + &S12AD.ADDR24, /* channel 24 */ + &S12AD.ADDR25, /* channel 25 */ + &S12AD.ADDR26, /* channel 26 */ + &S12AD.ADDR27, /* channel 27 */ + &S12AD.ADDR28, /* channel 28 */ + &S12AD.ADDR29, /* channel 29 */ + &S12AD.ADDR30, /* channel 30 */ + &S12AD.ADDR31, /* channel 31 */ + &S12AD.ADTSDR, /* temperature sensor */ + &S12AD.ADOCDR, /* voltage sensor */ + &S12AD.ADDBLDR, /* Data Duplication register */ + &S12AD.ADRD.WORD /* self-diagnosis register */ + }; + + +/* In ROM. Sample State (SST) Register pointers */ +/* 8-bit register pointers */ +volatile uint8_t R_BSP_EVENACCESS_SFR * const gp_sreg_ptrs[ADC_SST_REG_MAX+1] = + { &S12AD.ADSSTR0, /* channel 0 */ + &S12AD.ADSSTR1, /* channel 1 */ + &S12AD.ADSSTR2, /* channel 2 */ + &S12AD.ADSSTR3, + &S12AD.ADSSTR4, + &S12AD.ADSSTR5, + &S12AD.ADSSTR6, + &S12AD.ADSSTR7, /* channel 7 */ + &S12AD.ADSSTR8, /* channel 8 */ + &S12AD.ADSSTRL, /* channels 16 to 31 */ + &S12AD.ADSSTRT, /* temperature sensor output */ + &S12AD.ADSSTRO /* internal voltage reference */ + }; + + +#if ADC_CFG_PARAM_CHECKING_ENABLE == 1 +static adc_err_t adc_check_open_cfg(adc_mode_t const mode, + adc_cfg_t * const p_cfg, + void (* const p_callback)(void *p_args)); + +static adc_err_t adc_check_scan_config(adc_ch_cfg_t *p_config); +#endif + +static adc_err_t adc_configure_scan(adc_ch_cfg_t *p_config); +static void adc_enable_s12gbadi(void); +static adc_err_t adc_en_comparator_level0(adc_cmpwin_t *p_cmpwin); +static uint32_t adc_get_and_clr_cmpi_flags(void); + + +/****************************************************************************** +* Function Name: adc_open +* Description : This function applies power to the A/D peripheral, sets the +* operational mode, trigger sources, interrupt priority, and +* configurations common to all channels and sensors. If interrupt +* priority is non-zero, the function takes a callback function +* pointer for notifying the user at interrupt level whenever a +* scan has completed. +* +* Arguments : unit - +* Ignored for rx130. Pass 0 for this argument. +* mode - +* Operational mode (see enumeration below) +* p_cfg- +* Pointer to configuration structure (see below) +* p_callback- +* Optional pointer to function called from interrupt when +* a scan completes +* Return Value : ADC_SUCCESS- +* Successful +* ADC_ERR_AD_LOCKED- +* Open() call is in progress elsewhere +* ADC_ERR_AD_NOT_CLOSED- +* Peripheral is still running in another mode; Perform +* R_ADC_Close() first +* ADC_ERR_INVALID_ARG- +* mode or element of p_cfg structure has invalid value. +* ADC_ERR_ILLEGAL_ARG- +* an argument is illegal based upon mode +* ADC_ERR_MISSING_PTR- +* p_cfg pointer is FIT_NO_PTR/NULL +*******************************************************************************/ +adc_err_t adc_open(uint8_t const unit, + adc_mode_t const mode, + adc_cfg_t * const p_cfg, + void (* const p_callback)(void *p_args)) +{ + aregs_t *p_regs; + volatile uint16_t u16_dummy; /* Dummy read for "1" change to "0".(read first) */ + volatile uint8_t u8_dummy; /* Dummy read for "1" change to "0".(read first) */ + +#if ((R_BSP_VERSION_MAJOR == 5) && (R_BSP_VERSION_MINOR >= 30)) || (R_BSP_VERSION_MAJOR >= 6) + bsp_int_ctrl_t int_ctrl; +#endif + +#if ADC_CFG_PARAM_CHECKING_ENABLE == 1 + adc_err_t err; + + if ((NULL == p_cfg) || (FIT_NO_PTR == p_cfg)) + { + return ADC_ERR_MISSING_PTR; + } + + err = adc_check_open_cfg(mode, p_cfg, p_callback); + if (ADC_SUCCESS != err) + { + return err; + } +#endif + + /* ENSURE OPEN() NOT ALREADY IN PROGRESS */ + if (true == g_dcb.opened) + { + return ADC_ERR_AD_NOT_CLOSED; + } + if (R_BSP_HardwareLock(BSP_LOCK_S12AD) == false) + { + return ADC_ERR_AD_LOCKED; + } + + /* APPLY POWER TO PERIPHERAL */ + R_BSP_RegisterProtectDisable(BSP_REG_PROTECT_LPC_CGC_SWR); + +#if ((R_BSP_VERSION_MAJOR == 5) && (R_BSP_VERSION_MINOR >= 30)) || (R_BSP_VERSION_MAJOR >= 6) + R_BSP_InterruptControl(BSP_INT_SRC_EMPTY, BSP_INT_CMD_FIT_INTERRUPT_DISABLE, &int_ctrl); +#endif + MSTP(S12AD) = 0; +#if ((R_BSP_VERSION_MAJOR == 5) && (R_BSP_VERSION_MINOR >= 30)) || (R_BSP_VERSION_MAJOR >= 6) + R_BSP_InterruptControl(BSP_INT_SRC_EMPTY, BSP_INT_CMD_FIT_INTERRUPT_ENABLE, &int_ctrl); +#endif + + R_BSP_RegisterProtectEnable(BSP_REG_PROTECT_LPC_CGC_SWR); + + /* Get S12AD register address */ + p_regs = (aregs_t *)&S12AD; + p_regs->ADCSR.WORD = p_regs->ADCSR.WORD & 0x0400; + p_regs->ADEXICR.WORD = 0; //Don't convert Temp Sensor and Internal Reference + + p_regs->ADANSA0.WORD = 0; + p_regs->ADANSA1.WORD = 0; + p_regs->ADANSB0.WORD = 0; + p_regs->ADANSB1.WORD = 0; + + p_regs->ADADS0.WORD = 0; + p_regs->ADADS1.WORD = 0; + + p_regs->ADADC.BYTE = 0; + + p_regs->ADCER.WORD = 0; + p_regs->ADSTRGR.WORD = 0; + + p_regs->ADSSTR0 = 0x0d; + p_regs->ADSSTR1 = 0x0d; + p_regs->ADSSTR2 = 0x0d; + p_regs->ADSSTR3 = 0x0d; + p_regs->ADSSTR4 = 0x0d; + p_regs->ADSSTR5 = 0x0d; + p_regs->ADSSTR6 = 0x0d; + p_regs->ADSSTR7 = 0x0d; + p_regs->ADSSTR8 = 0x0d; + p_regs->ADSSTRL = 0x0d; + p_regs->ADSSTRT = 0x0d; + p_regs->ADSSTRO = 0x0d; + + p_regs->ADDISCR.BYTE = 0; + p_regs->ADELCCR.BYTE = 0; + p_regs->ADGSPCR.WORD = 0; + + p_regs->ADCMPCR.WORD = 0; + p_regs->ADCMPANSR0.WORD = 0; + p_regs->ADCMPANSR1.WORD = 0; + p_regs->ADCMPANSER.BYTE = 0; + p_regs->ADCMPLR0.WORD = 0; + p_regs->ADCMPLR1.WORD = 0; + + p_regs->ADCMPLER.BYTE = 0; + + p_regs->ADCMPDR0 = 0; + p_regs->ADCMPDR1 = 0; + u16_dummy = p_regs->ADCMPSR0.WORD; + p_regs->ADCMPSR0.WORD = 0; /* target bit clear by read-modify-write */ + u16_dummy = p_regs->ADCMPSR1.WORD; + p_regs->ADCMPSR1.WORD = 0; /* target bit clear by read-modify-write */ + + u8_dummy = p_regs->ADCMPSER.BYTE; + p_regs->ADCMPSER.BYTE = 0; /* target bit clear by read-modify-write */ + p_regs->ADHVREFCNT.BYTE = 0; + + p_regs->ADCMPBNSR.BYTE = 0; + p_regs->ADWINLLB = 0; + p_regs->ADWINULB = 0; + u8_dummy = p_regs->ADCMPBSR.BYTE; + p_regs->ADCMPBSR.BYTE = 0; /* target bit clear by read-modify-write */ + p_regs->ADBUFEN.BYTE = 0; + p_regs->ADBUFPTR.BYTE = 0; + + /* SET MODE RELATED REGISTER FIELDS */ + g_dcb.mode = mode; + + if ((ADC_MODE_SS_MULTI_CH_GROUPED == mode) + ||(ADC_MODE_SS_MULTI_CH_GROUPED_DBLTRIG_A == mode)) + { + p_regs->ADCSR.BIT.ADCS = ADC_ADCS_GROUP_SCAN; + } + else + { + if ((ADC_MODE_CONT_ONE_CH == mode) || (ADC_MODE_CONT_MULTI_CH == mode)) + { + p_regs->ADCSR.BIT.ADCS = ADC_ADCS_CONT_SCAN; + } // other modes have ADCS=0 + } + + if ((ADC_MODE_SS_ONE_CH_DBLTRIG == mode) + || (ADC_MODE_SS_MULTI_CH_GROUPED_DBLTRIG_A == mode)) + { + p_regs->ADCSR.BIT.DBLE = 1; // enable double trigger + } + + /* SET TRIGGER AND INTERRUPT PRIORITY REGISTER FIELDS */ + if (ADC_TRIG_SOFTWARE != p_cfg->trigger) + { + p_regs->ADSTRGR.BIT.TRSA = p_cfg->trigger; + } + + if (ADC_TRIG_ASYNC_ADTRG == p_cfg->trigger) + { + p_regs->ADCSR.BIT.EXTRG = 1; // set ext trigger for async trigger + } + + if (ADC_ADCS_GROUP_SCAN == p_regs->ADCSR.BIT.ADCS) + { + p_regs->ADSTRGR.BIT.TRSB = p_cfg->trigger_groupb; + IPR(S12AD,GBADI) = p_cfg->priority_groupb; + } + + IPR(S12AD,S12ADI0) = p_cfg->priority; + + /* SET REGISTER FIELDS FOR REMAINING PARAMETERS */ + p_regs->ADCER.BIT.ADRFMT = (ADC_ALIGN_LEFT == p_cfg->alignment) ? 1 : 0; + p_regs->ADCER.BIT.ACE = (ADC_CLEAR_AFTER_READ_ON == p_cfg->clearing) ? 1 : 0; + p_regs->ADADC.BYTE = p_cfg->add_cnt; + + /* SET THE A/D CONVERSION OPERATING SPEED. */ + p_regs->ADHVREFCNT.BIT.ADSLP = 1; // Set the sleep bit to enter standby mode. + R_BSP_SoftwareDelay(1, BSP_DELAY_MICROSECS); // Wait at least 0.2us + + /* Set the A/D conversion speed select bit: 0=High Speed, 1=low current */ + p_regs->ADCSR.BIT.ADHSC = (ADC_CONVERT_CURRENT_LOW == p_cfg->conv_speed) ? 1 : 0; + R_BSP_SoftwareDelay(5, BSP_DELAY_MICROSECS); // Wait at least 4.8us + p_regs->ADHVREFCNT.BIT.ADSLP = 0; // Clear sleep bit for normal operation + R_BSP_SoftwareDelay(1, BSP_DELAY_MICROSECS); // Wait at least 1us + + p_regs->ADCCR.BIT.CCS = (ADC_CONVERT_2CYCLES == p_cfg->conv_cycle) ? 1 : 0; + + /* SAVE CALLBACK FUNCTION POINTER */ + g_dcb.p_callback = p_callback; + + /* MARK DRIVER AS OPENED */ + g_dcb.opened = true; + R_BSP_HardwareUnlock(BSP_LOCK_S12AD); + + return ADC_SUCCESS; +} /* End of function adc_open() */ + + +/****************************************************************************** +* Function Name: adc_check_open_cfg +* Description : If Parameter Checking is enabled, this function will simply +* validate the parameters passed to the adc_open function. +** Arguments :mode - +* Operational mode (see enumeration below) +* p_cfg- +* Pointer to configuration structure (see below) +* p_callback- +* Optional pointer to function called from interrupt when +* a scan completes +* Return Value : ADC_SUCCESS- +* Successful +* ADC_ERR_INVALID_ARG- +* mode or element of p_cfg structure has invalid value. +* ADC_ERR_ILLEGAL_ARG- +* an argument is illegal based upon mode +*******************************************************************************/ +#if (ADC_CFG_PARAM_CHECKING_ENABLE == 1) +static adc_err_t adc_check_open_cfg(adc_mode_t const mode, + adc_cfg_t * const p_cfg, + void (* const p_callback)(void *p_args)) +{ + + /* Check for valid argument values */ + if (p_cfg->priority > BSP_MCU_IPL_MAX) // priority is not enum value(can't check by a Compiler) + { + return ADC_ERR_INVALID_ARG; + } + + /* If interrupt driven, must have callback function */ + if ((0 != p_cfg->priority) + && ((NULL == p_callback) || (FIT_NO_FUNC == p_callback))) + { + return ADC_ERR_ILLEGAL_ARG; + } + + /* In double trigger mode, SW and async triggers not allowed */ + if ((ADC_MODE_SS_ONE_CH_DBLTRIG == mode) + && ((ADC_TRIG_SOFTWARE == p_cfg->trigger) || (ADC_TRIG_ASYNC_ADTRG == p_cfg->trigger))) + { + return ADC_ERR_ILLEGAL_ARG; + } + + /* Group checking; only synchronous triggers allowed; must be unique */ + if ((ADC_MODE_SS_MULTI_CH_GROUPED == mode) || (ADC_MODE_SS_MULTI_CH_GROUPED_DBLTRIG_A == mode)) + { + if ((ADC_TRIG_ASYNC_ADTRG == p_cfg->trigger) + || (ADC_TRIG_ASYNC_ADTRG == p_cfg->trigger_groupb) + || (p_cfg->trigger == p_cfg->trigger_groupb) + || (ADC_TRIG_SOFTWARE == p_cfg->trigger) + || (ADC_TRIG_SOFTWARE == p_cfg->trigger_groupb)) + { + return ADC_ERR_ILLEGAL_ARG; + } + + if (p_cfg->priority_groupb > BSP_MCU_IPL_MAX) + { + return ADC_ERR_INVALID_ARG; + } + + if ((0 != p_cfg->priority_groupb) // Interrupt driven, must have callback function + && ((NULL == p_callback) || (FIT_NO_FUNC == p_callback))) + { + return ADC_ERR_ILLEGAL_ARG; + } + } + + return ADC_SUCCESS; +} /* End of function adc_check_open_cfg() */ +#endif /* ADC_CFG_PARAM_CHECKING_ENABLE == 1 */ + + +/****************************************************************************** +* Function Name: adc_control +* Description : This function provides commands for enabling channels and +* sensors and for runtime operations. These include enabling/ +* disabling trigger sources and interrupts, initiating a +* software trigger, and checking for scan completion. +* +* NOTE: Enabling a channel or a sensor, or setting the sample state count reg +* cannot be done while the ADCSR.ADST bit is set (conversion in progress). +* Because these commands should only be called once during initialization +* before triggers are enabled, this should not be an issue. Registers +* with this restriction include ADANSA0, ADANSA1, ADANSB0, ADANSB1, +* ADADC, ADADS0, ADADS1, ADSSTRx, ADEXICR, ADCMPCR, ADCMPANSR0, +* ADCMPANSR1, ADCMPANSER, ADCMPLR0, ADCMPLR1, ADCMPLER, ADCMPDR0, +* ADCMPDR1, and some bits in ADCSR, ADCMPCR, ADGSPCR. +* No runtime operational sequence checking of any kind is performed. +* +* Arguments : unit - +* Ignored for rx130. Pass 0 for this argument. +* cmd- +* Command to run +* p_args- +* Pointer to optional configuration structure +* Return Value : ADC_SUCCESS- +* Successful +* ADC_ERR_MISSING_PTR- +* p_args pointer is FIT_NO_PTR/NULL when required as an argument +* ADC_ERR_INVALID_ARG- +* cmd or element of p_args structure has invalid value. +* ADC_ERR_ILLEGAL_ARG- +* argument is illegal based upon rest of configuration +* ADC_ERR_SCAN_NOT_DONE- +* The requested scan has not completed +* ADC_ERR_TRIG_ENABLED - +* Cannot configure comparator because a scan is running +* ADC_ERR_CONDITION_NOT_MET - +* No chans/sensors passed comparator condition +* ADC_ERR_UNKNOWN +* Did not receive expected hardware response +*******************************************************************************/ +adc_err_t adc_control(uint8_t const unit, + adc_cmd_t const cmd, + void * const p_args) +{ + adc_err_t err=ADC_SUCCESS; + adc_sst_t *p_sample; + adc_dda_t *p_charge; + adc_cmpwin_t *p_cmpwin; + + /* Get S12AD register address */ + aregs_t *p_regs = (aregs_t *)&S12AD; + uint32_t flags; + + /* DO UNIVERSAL PARAMETER CHECKING */ +#if (ADC_CFG_PARAM_CHECKING_ENABLE == 1) + if ((NULL == p_args) || (FIT_NO_PTR == p_args)) + { + if ((ADC_CMD_SET_DDA_STATE_CNT == cmd) + || (ADC_CMD_SET_SAMPLE_STATE_CNT == cmd) + || (ADC_CMD_ENABLE_CHANS == cmd) + || (ADC_CMD_EN_COMPARATOR_LEVEL == cmd) + || (ADC_CMD_EN_COMPARATOR_WINDOW == cmd) + || (ADC_CMD_CHECK_CONDITION_MET == cmd)) + { + return ADC_ERR_MISSING_PTR; + } + } +#endif + + /* PROCESS INDIVIDUAL COMMANDS */ + switch (cmd) + { + case ADC_CMD_USE_VREFH0: + S12AD.ADHVREFCNT.BIT.HVSEL = 1; + break; + + case ADC_CMD_USE_VREFL0: + S12AD.ADHVREFCNT.BIT.LVSEL = 1; + break; + + /* Set up Disconnect Detection Assist*/ + case ADC_CMD_SET_DDA_STATE_CNT: + + /* Disconnection Detection Assist (DDA) */ + p_charge = (adc_dda_t *)p_args; //Get the command arguments +#if (ADC_CFG_PARAM_CHECKING_ENABLE == 1) + if (ADC_DDA_OFF != p_charge->method) + { + + /* Cannot have temp sensor output or V-reference conversion enabled and Disconnect Detection enabled. */ + if ((p_charge->num_states < ADC_DDA_STATE_CNT_MIN) + || (p_charge->num_states > ADC_DDA_STATE_CNT_MAX) + || ((p_regs->ADEXICR.WORD & 0x0300) != 0)) // Temp sensor or V-ref enabled + { + return ADC_ERR_ILLEGAL_ARG; + } + } +#endif + if (ADC_DDA_OFF == p_charge->method) + { + p_regs->ADDISCR.BYTE = 0; //Disable Disconnect Detection Assist + } + else + { + + /* NOTE: Using Disconnect Detection Assist adds num_states x (#chans) ADCLKS to scan time */ + p_regs->ADDISCR.BYTE = (uint8_t)((ADC_DDA_PRECHARGE == p_charge->method) ? 0x10 : 0); + p_regs->ADDISCR.BYTE |= p_charge->num_states; + } + break; + + case ADC_CMD_SET_SAMPLE_STATE_CNT: + p_sample = (adc_sst_t *)p_args; //Get the command arguments +#if ADC_CFG_PARAM_CHECKING_ENABLE == 1 + if (p_sample->num_states < ADC_SST_CNT_MIN) + { + return ADC_ERR_INVALID_ARG; + } +#endif + *(gp_sreg_ptrs)[p_sample->reg_id] = p_sample->num_states; + break; + + case ADC_CMD_ENABLE_CHANS: + + /* Cast from void pointer to adc_ch_cfg_t */ + err = adc_configure_scan((adc_ch_cfg_t *)p_args); + break; + + case ADC_CMD_EN_COMPARATOR_LEVEL: + + /* Cast from void pointer to adc_cmpwin_t */ + p_cmpwin = (adc_cmpwin_t *)p_args; + p_regs->ADCMPCR.BIT.WCMPE = 0; // Disable the window function. Compare level + + err = adc_en_comparator_level0(p_cmpwin); + break; + + case ADC_CMD_ENABLE_TEMP_SENSOR: +#if ADC_CFG_PARAM_CHECKING_ENABLE == 1 + if (ADC_MODE_SS_TEMPERATURE != g_dcb.mode) + { + return ADC_ERR_ILLEGAL_ARG; + } +#endif + S12AD.ADEXICR.BIT.TSSA = 1; // select temperature output on Single scan mode + if (ADC_ADD_OFF != S12AD.ADADC.BIT.ADC) + { + S12AD.ADEXICR.BIT.TSSAD = 1; // enable addition + } + adc_enable_s12adi0(); // setup interrupt handling + break; + + case ADC_CMD_ENABLE_VOLT_SENSOR: +#if ADC_CFG_PARAM_CHECKING_ENABLE == 1 + if (ADC_MODE_SS_INT_REF_VOLT != g_dcb.mode) + { + return ADC_ERR_ILLEGAL_ARG; + } +#endif + S12AD.ADEXICR.BIT.OCSA = 1; // select internal reference voltage output on Single scan mode + if (ADC_ADD_OFF != S12AD.ADADC.BIT.ADC) + { + S12AD.ADEXICR.BIT.OCSAD = 1; // enable addition + } + adc_enable_s12adi0(); // setup interrupt handling + break; + + case ADC_CMD_EN_COMPARATOR_WINDOW: + + /* Cast from void pointer to adc_cmpwin_t */ + p_cmpwin = (adc_cmpwin_t *)p_args; +#if ADC_CFG_PARAM_CHECKING_ENABLE == 1 + if (p_cmpwin->level_lo > p_cmpwin->level_hi) + { + return ADC_ERR_ILLEGAL_ARG; + } +#endif + p_regs->ADCMPCR.BIT.WCMPE = 1; // Enable window function + + err = adc_en_comparator_level0(p_cmpwin); + break; + + /* Enable A/D conversion to be started by synchronous or asynchronous trigger */ + case ADC_CMD_ENABLE_TRIG: + p_regs->ADCSR.BIT.TRGE = 1; // enable sync/async triggers + break; + + /* Disable A/D conversion to be started by synchronous or asynchronous trigger */ + case ADC_CMD_DISABLE_TRIG: + p_regs->ADCSR.BIT.TRGE = 0; // disable sync/async triggers + break; + + /* Start the A/D conversion process */ + case ADC_CMD_SCAN_NOW: + if (0 == p_regs->ADCSR.BIT.ADST) + { + PORTB.PODR.BIT.B6 = ~PORTB.PODR.BIT.B6; + p_regs->ADCSR.BIT.ADST = 1; + } + else + { + err = ADC_ERR_SCAN_NOT_DONE; + } + break; + + /* Check for completion of the current scan. */ + case ADC_CMD_CHECK_SCAN_DONE: + if (1 == p_regs->ADCSR.BIT.ADST) + { + err = ADC_ERR_SCAN_NOT_DONE; + } + break; + + /* Check for completion of the current scan. */ + case ADC_CMD_CHECK_SCAN_DONE_GROUPA: + if (1 == IR(S12AD,S12ADI0)) + { + IR(S12AD,S12ADI0) = 0; + } + else + { + err = ADC_ERR_SCAN_NOT_DONE; + } + break; + + /* Check for completion of the current groupB scan. */ + case ADC_CMD_CHECK_SCAN_DONE_GROUPB: + if (1 == IR(S12AD,GBADI)) + { + IR(S12AD,GBADI) = 0; + } + else + { + err = ADC_ERR_SCAN_NOT_DONE; + } + break; + + case ADC_CMD_CHECK_CONDITION_MET: + flags = adc_get_and_clr_cmpi_flags(); + if (0 == flags) + { + err = ADC_ERR_CONDITION_NOT_MET; + } + + /* Cast from void pointer to uint32_t */ + *((uint32_t *)p_args) = flags; + break; + + case ADC_CMD_ENABLE_INT: + p_regs->ADCSR.BIT.ADIE = 1; // Enable Scan End Interrupt (S12ADI0) + break; + + case ADC_CMD_DISABLE_INT: + p_regs->ADCSR.BIT.ADIE = 0; // Disable Scan End Interrupt (S12ADI0) + break; + + case ADC_CMD_ENABLE_INT_GROUPB: + p_regs->ADCSR.BIT.GBADIE = 1; // Enable Group B Scan End Interrupt (GBADI) + break; + + case ADC_CMD_DISABLE_INT_GROUPB: + p_regs->ADCSR.BIT.GBADIE = 0; // Disable Group B Scan End Interrupt (GBADI) + break; + + default: + err = ADC_ERR_INVALID_ARG; + break; + } + + return err; +} /* End of function adc_control() */ + +/****************************************************************************** +* Function Name: adc_en_comparator_level0 +* Description : This function sets up the comparator for level0 threshold +* : compare. The processing is identical for window except +* : for the setting of the window enable bit and the level1 +* : value (ADCMPDR1). +* : +* Arguments : p_cmpwin - +* : Pointer to comparator level/window compare structure +* : +* Return Value :ADC_SUCCESS- +* : Successful +* : ADC_ERR_INVALID_ARG- +* : reg_id contains an invalid value. +* : ADC_ERR_ILLEGAL_ARG- +* : an argument is illegal based upon rest of configuration +* : ADC_ERR_TRIG_ENABLED - +* : Cannot configure comparator while scans are running +* : +*******************************************************************************/ +static adc_err_t adc_en_comparator_level0(adc_cmpwin_t *p_cmpwin) +{ + + /* Get S12AD register address */ + aregs_t *p_regs = (aregs_t *)&S12AD; + +#if ADC_CFG_PARAM_CHECKING_ENABLE == 1 +#if BSP_PACKAGE_PINS == 100 + if ((p_cmpwin->compare_mask & 0x0000F800) != 0) +#elif BSP_PACKAGE_PINS == 80 + if ((p_cmpwin->compare_mask & 0xF8C0F800) != 0) +#elif BSP_PACKAGE_PINS == 64 + if ((p_cmpwin->compare_mask & 0xFFC0F800) != 0) +#elif BSP_PACKAGE_PINS == 48 + if ((p_cmpwin->compare_mask & 0xFFE1F818) != 0) +#endif + { + return ADC_ERR_INVALID_ARG; + } + if ((p_cmpwin->inside_window_mask | p_cmpwin->compare_mask) + != p_cmpwin->compare_mask) // checking compare channel combination + { + return ADC_ERR_INVALID_ARG; + } + if (1 == p_regs->ADCSR.BIT.DBLE) // Comparison disable when Double trigger mode + { + return ADC_ERR_INVALID_ARG; + } + if (0 != p_regs->ADCER.BIT.DIAGM) // Comparison disable when Self-diagnosis mode + { + return ADC_ERR_INVALID_ARG; + } + if ((ADC_MODE_SS_TEMPERATURE == g_dcb.mode) && (ADC_MASK_TEMP != p_cmpwin->compare_mask)) // checking use channel + { + return ADC_ERR_INVALID_ARG; + } + if ((ADC_MODE_SS_INT_REF_VOLT == g_dcb.mode) && (ADC_MASK_VOLT != p_cmpwin->compare_mask)) // checking use channel + { + return ADC_ERR_INVALID_ARG; + } +#endif + + if (1 == p_regs->ADCSR.BIT.TRGE) + { + return ADC_ERR_TRIG_ENABLED; // ADST must be 0 to configure comparator + } + + /* CONFIGURE COMPARATOR */ + if (true == p_cmpwin->windowa_enable) // COMPARATOR A + { + p_regs->ADCMPCR.BIT.CMPAE = 0; // Compare window A operation is disabled + + p_regs->ADCMPDR0 = p_cmpwin->level_lo; // set lo end of window or set level + if (1 == p_regs->ADCMPCR.BIT.WCMPE) + { + p_regs->ADCMPDR1 = p_cmpwin->level_hi; // set hi end of window + } + + p_regs->ADCMPANSR0.WORD = p_cmpwin->compare_mask & 0x01FF; // Select channels to compare. Channels 0 to 8. + p_regs->ADCMPLR0.WORD = p_cmpwin->inside_window_mask & 0x01FF; // Select the CoMPare Level. Channels 0 to 8. + + S12AD.ADCMPANSR1.WORD = (p_cmpwin->compare_mask>>16) & 0xFFFF; // Select channels to compare. 16 to 31. + S12AD.ADCMPLR1.WORD = (p_cmpwin->inside_window_mask>>16) & 0xFFFF; + + S12AD.ADCMPANSER.BIT.CMPTSA = (p_cmpwin->compare_mask & ADC_MASK_TEMP) ? 1 : 0; + S12AD.ADCMPANSER.BIT.CMPOCA = (p_cmpwin->compare_mask & ADC_MASK_VOLT) ? 1 : 0; + + S12AD.ADCMPLER.BIT.CMPLTSA = (p_cmpwin->inside_window_mask & ADC_MASK_TEMP) ? 1 : 0; + S12AD.ADCMPLER.BIT.CMPLOCA = (p_cmpwin->inside_window_mask & ADC_MASK_VOLT) ? 1 : 0; + + p_regs->ADCMPCR.BIT.CMPAE = 1; // Compare window A operation is enabled + } + else + { + p_regs->ADCMPCR.BIT.CMPAE = 0; // Compare window A operation is disabled + } + + return ADC_SUCCESS; +} /* End of function adc_en_comparator_level0() */ + +/***************************************************************************** +* Function Name: adc_get_and_clr_cmpi_flags +* Description : Returns flags for all channels/sensors that met comparator +* condition and clears the flags for next interrupt. +* Arguments : none +* Return Value : channels/sensors that met comparator condition +******************************************************************************/ +static uint32_t adc_get_and_clr_cmpi_flags(void) +{ + uint32_t flags; + + /* Get flags for channels AN00 to AN07 */ + flags = (uint32_t)S12AD.ADCMPSR0.WORD; + S12AD.ADCMPSR0.WORD = 0; + + /* Get flags for channels AN16 to AN31 */ + flags |= ((uint32_t)S12AD.ADCMPSR1.WORD << 16); + S12AD.ADCMPSR1.WORD = 0; + + /* Get flags for Temperature sensor and internal Voltage Reference */ + flags |= ((1 == S12AD.ADCMPSER.BIT.CMPSTTSA) ? ADC_MASK_TEMP : 0); + flags |= ((1 == S12AD.ADCMPSER.BIT.CMPSTOCA) ? ADC_MASK_VOLT : 0); + S12AD.ADCMPSER.BYTE = 0; + + return flags; +} /* End of function adc_get_and_clr_cmpi_flags() */ + +/****************************************************************************** +* Function Name: adc_configure_scan +* Description : This function does extensive checking on channel mask +* settings based upon operational mode. Mask registers are +* initialized and interrupts enabled in peripheral. Interrupts +* are also enabled in ICU if corresponding priority is not 0. +* +* Arguments : p_config - +* Pointer to channel config structure containing masks +* Return Value : ADC_SUCCESS- +* Successful +*******************************************************************************/ +static adc_err_t adc_configure_scan(adc_ch_cfg_t *p_config) +{ + uint16_t i=0; + uint32_t tmp_mask=0; + + /* Get S12AD register address */ + aregs_t *p_regs = (aregs_t *)&S12AD; + uint16_t trig_a; + uint16_t trig_b; + +#if ADC_CFG_PARAM_CHECKING_ENABLE == 1 + adc_err_t err; + + err = adc_check_scan_config(p_config); + if (ADC_SUCCESS != err) + { + return err; + } +#endif /* ADC_CFG_PARAM_CHECKING_ENABLE == 1 */ + + /* SET MASKS FOR CHANNELS AND SENSORS */ + /* Select the channels from among Ch0 to Ch7 for conversion */ + p_regs->ADANSA0.WORD = (uint16_t) (p_config->chan_mask & 0x01FF); //CH0 to CH8 + p_regs->ADANSB0.WORD = (uint16_t) (p_config->chan_mask_groupb & 0x01FF); //CH0 to CH8 + + /* Select the channels for Addition/Averaging (ch0 to ch7) */ + p_regs->ADADS0.WORD = (uint16_t) (p_config->add_mask & 0x01FF); //CH0 to CH8 + + /* Select the channels from among Ch16 to Ch31 for conversion */ + S12AD.ADANSA1.WORD = (uint16_t) ((p_config->chan_mask >> 16) & 0xFFFF); //CH16 to CH31 + + /* Select the channels from among Ch16 to Ch31 for conversion */ + S12AD.ADANSB1.WORD = (uint16_t) ((p_config->chan_mask_groupb >> 16) & 0xFFFF); + + /* Select the channels for Addition/Averaging (Ch16 to Ch31) */ + S12AD.ADADS1.WORD = (uint16_t) ((p_config->add_mask >> 16) & 0xFFFF); + + /* SET GROUP A PRIORITY ACTION (not interrupt priority!) */ + + if (ADC_GRPA_PRIORITY_OFF != p_config->priority_groupa) + { + trig_a = p_regs->ADSTRGR.BIT.TRSA; // save TRSA + trig_b = p_regs->ADSTRGR.BIT.TRSB; // save TRSB + p_regs->ADSTRGR.BIT.TRSA = ADC_TRIG_NONE; + p_regs->ADSTRGR.BIT.TRSB = ADC_TRIG_NONE; + if (ADC_TRIG_NONE != p_regs->ADSTRGR.BIT.TRSA) // bus wait for ADSTRGR write + { + R_BSP_NOP(); + } + if (ADC_TRIG_NONE != p_regs->ADSTRGR.BIT.TRSB) // bus wait for ADSTRGR write + { + R_BSP_NOP(); + } + + p_regs->ADGSPCR.WORD = p_config->priority_groupa; + + p_regs->ADSTRGR.BIT.TRSA = trig_a; // restore TRSA + if (1 != p_regs->ADGSPCR.BIT.GBRP) + { + p_regs->ADSTRGR.BIT.TRSB = trig_b; // restore TRSB + } + } + else + { + p_regs->ADGSPCR.WORD = p_config->priority_groupa; + } + + /* SET SELF DIAGNOSIS REGISTERS (VIRTUAL CHANNEL) */ + if (ADC_DIAG_OFF == p_config->diag_method) + { + p_regs->ADCER.BIT.DIAGM = 0; + } + else + { + + /* NOTE: Using Self Diagnosis adds 15(resolution) + (ch0 SST) ADCLKS to scan time. + (ch0 can still be used with self diagnosis on) */ + if (ADC_DIAG_ROTATE_VOLTS == p_config->diag_method) + { + p_regs->ADCER.BIT.DIAGLD = 0; //Rotate test voltages + p_regs->ADCER.BIT.DIAGVAL = 1; //Start with 0 V + } + else + { + + /* Make sure DIAGVAL bits are not zero before setting the DIAGLD bit */ + p_regs->ADCER.BIT.DIAGVAL = (uint8_t)(p_config->diag_method & 0x3); //Select diag. voltage + p_regs->ADCER.BIT.DIAGLD = 1; //Do not rotate test voltages + } + p_regs->ADCER.BIT.DIAGM = 1; //Enable self diagnosis + } + + /* SET DOUBLE TRIGGER CHANNEL */ + if (1 == p_regs->ADCSR.BIT.DBLE) // If double-trigger mode is already selected. + { + tmp_mask = p_config->chan_mask; // tmp_mask is non-Group/Group A chans + + /* WAIT_LOOP */ + while (tmp_mask >>= 1) // determine bit/ch number + { + i++; + } + p_regs->ADCSR.BIT.DBLANS = i; + } + + p_regs->ADELCCR.BIT.ELCC = p_config->signal_elc; + + /* ENABLE INTERRUPTS */ + adc_enable_s12adi0(); + if (ADC_ADCS_GROUP_SCAN == p_regs->ADCSR.BIT.ADCS) + { + adc_enable_s12gbadi(); + } + + return ADC_SUCCESS; +} /* End of function adc_configure_scan() */ + + +/****************************************************************************** +* Function Name: adc_check_scan_config +* Description : This function does extensive checking on channel mask +* settings based upon operational mode. +* +* NOTE: A negative number is stored in two's complement form. +* A quick way to change a binary number into two's complement is to +* start at the right (LSB) and moving left, don't change any bits +* until after the first "1" is reached. +* Number 2's complement +* 0010 0110 1101 1010 +* Another way is to do a 1's complement on the number, then add 1 to that. +* Number 1's complement + 1 +* 0010 0110 1101 1001 1101 1010 +* +* Arguments : p_config +* Pointer to channel config structure containing masks +* Return Value : ADC_SUCCESS- +* Successful +* ADC_ERR_INVALID_ARG- +* reg_id contains an invalid value. +* ADC_ERR_ILLEGAL_ARG- +* an argument is illegal based upon rest of configuration +*******************************************************************************/ +#if ADC_CFG_PARAM_CHECKING_ENABLE == 1 +static adc_err_t adc_check_scan_config(adc_ch_cfg_t *p_config) +{ + uint32_t tmp_mask=0; + + /* Get S12AD register address */ + aregs_t *p_regs = (aregs_t *)&S12AD; + + /* Verify at least one bonded channel is selected */ + if ((0 == p_config->chan_mask) +#if BSP_PACKAGE_PINS == 80 + || ((p_config->chan_mask & 0xF8C0F800) != 0) +#elif BSP_PACKAGE_PINS == 64 + || ((p_config->chan_mask & 0xFFC0F800) != 0) +#elif BSP_PACKAGE_PINS == 48 + || ((p_config->chan_mask & 0xFFE1F818) != 0) +#endif + || ((ADC_MODE_SS_TEMPERATURE == g_dcb.mode) && (ADC_MASK_TEMP != p_config->chan_mask)) + || ((ADC_MODE_SS_INT_REF_VOLT == g_dcb.mode) && (ADC_MASK_VOLT != p_config->chan_mask))) + { + return ADC_ERR_INVALID_ARG; + } + + /* Verify at least one unique bonded channel is selected for Group B + * and GroupA priority setting is valid. + */ + if (ADC_ADCS_GROUP_SCAN == p_regs->ADCSR.BIT.ADCS) + { + if ((0 == p_config->chan_mask_groupb) +#if BSP_PACKAGE_PINS == 80 + || ((p_config->chan_mask_groupb & 0xF8C0F800) != 0) +#elif BSP_PACKAGE_PINS == 64 + || ((p_config->chan_mask_groupb & 0xFFC0F800) != 0) +#elif BSP_PACKAGE_PINS == 48 + || ((p_config->chan_mask_groupb & 0xFFE1F818) != 0) +#endif + || ((ADC_MODE_SS_TEMPERATURE == g_dcb.mode) && (ADC_MASK_TEMP != p_config->chan_mask_groupb)) + || ((ADC_MODE_SS_INT_REF_VOLT == g_dcb.mode) && (ADC_MASK_VOLT != p_config->chan_mask_groupb))) + { + return ADC_ERR_INVALID_ARG; + } + else if ((p_config->chan_mask & p_config->chan_mask_groupb) != 0) + { + return ADC_ERR_ILLEGAL_ARG; // same chan in both groups + } + else + { + tmp_mask = p_config->chan_mask_groupb; + } + } + else + { + + /* for addition mask checking */ + if (0 != p_config->chan_mask_groupb) + { + return ADC_ERR_INVALID_ARG; + } + + /* PGS bit must be set when group scan mode */ + if (ADC_GRPA_PRIORITY_OFF != p_config->priority_groupa) + { + return ADC_ERR_INVALID_ARG; + } + } + + /* If sensors specified, verify in legal configuation */ + if ((ADC_MODE_SS_TEMPERATURE == g_dcb.mode) || (ADC_MODE_SS_INT_REF_VOLT == g_dcb.mode)) + { + if ((1 == S12AD.ADCSR.BIT.DBLE) // Select double trigger mode + || (0 != S12AD.ADDISCR.BYTE)) // disconnect detection assist enabled + { + return ADC_ERR_ILLEGAL_ARG; + } + } + + /* Addition mask should not include bits from inactive channels */ + if (ADC_ADD_OFF != p_regs->ADADC.BIT.ADC) + { + tmp_mask |= p_config->chan_mask; // tmp_mask is Group A and B combined + + /* Bit-AND with 1s-complement */ + if ((p_config->add_mask & (~tmp_mask)) != 0) + { + return ADC_ERR_INVALID_ARG; + } + } + else + { + + /* WARNING! Other features messed up if add_mask is non-zero when addition is turned off! */ + p_config->add_mask = 0; + } + + /* Verify only 1 bit is set in default/Group A mask */ + if ((ADC_MODE_SS_ONE_CH == g_dcb.mode) + || (ADC_MODE_CONT_ONE_CH == g_dcb.mode) + || (1 == p_regs->ADCSR.BIT.DBLE)) // double trigger mode + { + tmp_mask = p_config->chan_mask; // tmp_mask is non-Group/Group A chans + + /* Bit-AND with 2s-complement (see note in function header) */ + if ((tmp_mask & ((~tmp_mask) + 1)) != tmp_mask) + { + return ADC_ERR_ILLEGAL_ARG; + } + } + + if ((ADC_DIAG_OFF != p_config->diag_method) + && ((0 != p_regs->ADADC.BIT.ADC) // addition + || (1 == p_regs->ADCSR.BIT.DBLE))) // double trigger mode + { + return ADC_ERR_ILLEGAL_ARG; + } + + return ADC_SUCCESS; +} /* End of function adc_check_scan_config() */ +#endif/* ADC_CFG_PARAM_CHECKING_ENABLE == 1 */ + + +/****************************************************************************** +* Function Name: adc_enable_s12gbadi +* Description : This function clears the S12GBADI interrupt flag and enables +* interrupts in the peripheral (for IR flag usage). If priority +* is not 0, interrupts are enabled in the ICU. +* NOTE: This has nothing to do with enabling triggers. +* Arguments : none +* Return Value : none +*******************************************************************************/ +static void adc_enable_s12gbadi(void) +{ + IR(S12AD,GBADI) = 0; // clear flag + S12AD.ADCSR.BIT.GBADIE = 1; // enable in peripheral + if (0 != IPR(S12AD,GBADI)) + { + R_BSP_InterruptRequestEnable(VECT(S12AD,GBADI)); // enable in ICU + } +} /* End of function adc_enable_s12gbadi() */ + + +/****************************************************************************** +* Function Name: adc_close +* Description : This is the RX130 implementation of R_ADC_Close(). +* This function ends any scan in progress, disables interrupts, +* and removes power to the A/D peripheral. +* Arguments : unit - This argument is ignored for the RX130. +* Return Value : ADC_SUCCESS - Successful +* ADC_ERR_INVALID_ARG - unit contains an invalid value. +*******************************************************************************/ +adc_err_t adc_close(uint8_t const unit) +{ + uint32_t adc_wait_microsecs; + + /* Get S12AD register address */ + aregs_t *p_regs = (aregs_t *)&S12AD; + +#if ((R_BSP_VERSION_MAJOR == 5) && (R_BSP_VERSION_MINOR >= 30)) || (R_BSP_VERSION_MAJOR >= 6) + bsp_int_ctrl_t int_ctrl; +#endif + +#if ADC_CFG_PARAM_CHECKING_ENABLE == 1 + if (unit > 0) + { + return ADC_ERR_INVALID_ARG; + } +#endif + + /* Stop triggers & conversions, and disable peripheral interrupts */ + R_BSP_InterruptRequestDisable(VECT(S12AD,S12ADI0)); // disable interrupts in ICU + IR(S12AD,S12ADI0) = 0; // clear interrupt flag + R_BSP_InterruptRequestDisable(VECT(S12AD,GBADI)); // disable interrupts in ICU + IR(S12AD,GBADI) = 0; // clear interrupt flag + + p_regs->ADGSPCR.BIT.PGS = 0; + if (ADC_ADCS_GROUP_SCAN == p_regs->ADCSR.BIT.ADCS) + { + p_regs->ADSTRGR.WORD = 0x3F3F; + } + else + { + p_regs->ADSTRGR.BIT.TRSA = 0x3F; + } + + p_regs->ADCSR.WORD = p_regs->ADCSR.WORD & 0x0400; + if (0x0000 == (p_regs->ADCSR.WORD & 0xFBFF)) // dummy read for waiting until set the value of ADCSR + { + R_BSP_NOP(); + } + + /* Wait for 3 ADCLK cycles (1 PCLKB + 2 ADCLK when ADCLK is faster than PCLKB */ + if (BSP_PCLKD_HZ > BSP_PCLKB_HZ) + { + /* 1PCLK + 2ADCLK Round up the decimal point */ + adc_wait_microsecs = (uint32_t)((1000000 + (BSP_PCLKB_HZ - 1)) / BSP_PCLKB_HZ) + + (uint32_t)((2000000 + (BSP_PCLKD_HZ - 1)) / BSP_PCLKD_HZ); + } + else + { + /* 3ADCLK Round up the decimal point */ + adc_wait_microsecs = (uint32_t)((3000000 + (BSP_PCLKD_HZ - 1)) / BSP_PCLKD_HZ); + } + R_BSP_SoftwareDelay (adc_wait_microsecs, BSP_DELAY_MICROSECS); + + /* Power down peripheral */ + R_BSP_RegisterProtectDisable(BSP_REG_PROTECT_LPC_CGC_SWR); + +#if ((R_BSP_VERSION_MAJOR == 5) && (R_BSP_VERSION_MINOR >= 30)) || (R_BSP_VERSION_MAJOR >= 6) + R_BSP_InterruptControl(BSP_INT_SRC_EMPTY, BSP_INT_CMD_FIT_INTERRUPT_DISABLE, &int_ctrl); +#endif + MSTP(S12AD) = 1; +#if ((R_BSP_VERSION_MAJOR == 5) && (R_BSP_VERSION_MINOR >= 30)) || (R_BSP_VERSION_MAJOR >= 6) + R_BSP_InterruptControl(BSP_INT_SRC_EMPTY, BSP_INT_CMD_FIT_INTERRUPT_ENABLE, &int_ctrl); +#endif + R_BSP_RegisterProtectEnable(BSP_REG_PROTECT_LPC_CGC_SWR); + + /* Show driver as closed */ + + g_dcb.opened = false; + + return ADC_SUCCESS; +} /* End of function adc_close() */ + + +/****************************************************************************** +* Function Name: adc_read_all +* Description : This is the RX130 implementation of R_ADC_ReadAll(). +* It reads conversion results from all potential sources, +* enabled or not. +* Arguments : p_all_data- +* Pointer to structure to load register values into. +* Return Value : ADC_SUCCESS- +* Successful +*******************************************************************************/ +adc_err_t adc_read_all(adc_data_t * const p_all_data) +{ + p_all_data->chan[ADC_REG_CH0] = S12AD.ADDR0; + p_all_data->chan[ADC_REG_CH1] = S12AD.ADDR1; + p_all_data->chan[ADC_REG_CH2] = S12AD.ADDR2; + p_all_data->chan[ADC_REG_CH3] = S12AD.ADDR3; + p_all_data->chan[ADC_REG_CH4] = S12AD.ADDR4; + p_all_data->chan[ADC_REG_CH5] = S12AD.ADDR5; + p_all_data->chan[ADC_REG_CH6] = S12AD.ADDR6; + p_all_data->chan[ADC_REG_CH7] = S12AD.ADDR7; + p_all_data->chan[ADC_REG_CH8] = S12AD.ADDR8; + + p_all_data->chan[ADC_REG_CH16] = S12AD.ADDR16; + p_all_data->chan[ADC_REG_CH17] = S12AD.ADDR17; + p_all_data->chan[ADC_REG_CH18] = S12AD.ADDR18; + p_all_data->chan[ADC_REG_CH19] = S12AD.ADDR19; + p_all_data->chan[ADC_REG_CH20] = S12AD.ADDR20; + p_all_data->chan[ADC_REG_CH21] = S12AD.ADDR21; + p_all_data->chan[ADC_REG_CH22] = S12AD.ADDR22; + p_all_data->chan[ADC_REG_CH23] = S12AD.ADDR23; + p_all_data->chan[ADC_REG_CH24] = S12AD.ADDR24; + p_all_data->chan[ADC_REG_CH25] = S12AD.ADDR25; + p_all_data->chan[ADC_REG_CH26] = S12AD.ADDR26; + p_all_data->chan[ADC_REG_CH27] = S12AD.ADDR27; + p_all_data->chan[ADC_REG_CH28] = S12AD.ADDR28; + p_all_data->chan[ADC_REG_CH29] = S12AD.ADDR29; + p_all_data->chan[ADC_REG_CH30] = S12AD.ADDR30; + p_all_data->chan[ADC_REG_CH31] = S12AD.ADDR31; + p_all_data->temp = S12AD.ADTSDR; + p_all_data->volt = S12AD.ADOCDR; + + p_all_data->dbltrig = S12AD.ADDBLDR; + p_all_data->self_diag = S12AD.ADRD.WORD; + + return ADC_SUCCESS; +} /* End of function adc_read_all() */ + + +#endif /* #if defined BSP_MCU_RX130 */ + diff --git a/drivers/rx/rdp/src/r_s12ad_rx/src/targets/rx261/r_s12ad_rx261_if.h b/drivers/rx/rdp/src/r_s12ad_rx/src/targets/rx261/r_s12ad_rx261_if.h new file mode 100644 index 00000000..353c84fb --- /dev/null +++ b/drivers/rx/rdp/src/r_s12ad_rx/src/targets/rx261/r_s12ad_rx261_if.h @@ -0,0 +1,361 @@ +/*********************************************************************************************************************** +* Copyright (c) 2021 Renesas Electronics Corporation and/or its affiliates +* +* SPDX-License-Identifier: BSD-3-Clause +***********************************************************************************************************************/ +/********************************************************************************************************************** +* File Name : r_s12ad_rx261_if.h +* Description : 12-bit A/D Converter driver interface file. +*********************************************************************************************************************** +* History : DD.MM.YYYY Version Description +* 30.07.2021 1.00 Initial Release. +* 19.11.2021 4.92 Fixed macro definition of ADC_SST_CNT_MIN. +* 20.03.2025 5.41 Changed the disclaimer in program sources. +***********************************************************************************************************************/ + +/****************************************************************************** +Includes , "Project Includes" +*******************************************************************************/ +#include "platform.h" + +#ifndef S12AD_PRV_RX261_IF_H +#define S12AD_PRV_RX261_IF_H + +/****************************************************************************** +Macro definitions +*******************************************************************************/ +#if (BSP_CFG_PCKB_DIV > BSP_CFG_PCKD_DIV) +#define ADC_SST_CNT_MIN (6) /* For PCLKB < ADCLK */ +#else +#define ADC_SST_CNT_MIN (5) /* For PCLKB >= ADCLK */ +#endif /* (BSP_CFG_PCKB_DIV > BSP_CFG_PCKD_DIV) */ +#define ADC_SST_CNT_MAX (255) +#define ADC_SST_CNT_DEFAULT (13) + +#define ADC_DDA_STATE_CNT_MIN (2) /* ADDISCR.ADNDIS[0..3] bits. */ +#define ADC_DDA_STATE_CNT_MAX (15) + + +/* for ADC_CMD_ENABLE_CHANS */ +/* Bitwise OR these masks together for desired channels and sensors + Used for all commands containing a "mask" or "flags" field */ +#define ADC_MASK_CH0 (1<<0) +#define ADC_MASK_CH1 (1<<1) +#define ADC_MASK_CH2 (1<<2) +#define ADC_MASK_CH3 (1<<3) +#define ADC_MASK_CH4 (1<<4) +#define ADC_MASK_CH5 (1<<5) +#define ADC_MASK_CH6 (1<<6) +#define ADC_MASK_CH7 (1<<7) +#define ADC_MASK_CH8 (1<<8) +#define ADC_MASK_CH16 (1<<16) +#define ADC_MASK_CH17 (1<<17) +#define ADC_MASK_CH18 (1<<18) +#define ADC_MASK_CH19 (1<<19) +#define ADC_MASK_CH20 (1<<20) +#define ADC_MASK_CH21 (1<<21) +#define ADC_MASK_CH22 (1<<22) +#define ADC_MASK_CH23 (1<<23) +#define ADC_MASK_CH24 (1<<24) +#define ADC_MASK_CH25 (1<<25) +#define ADC_MASK_CH26 (1<<26) +#define ADC_MASK_CH27 (1<<27) +#define ADC_MASK_CH28 (1<<28) +#define ADC_MASK_CH29 (1<<29) +#define ADC_MASK_CH30 (1<<30) +#define ADC_MASK_CH31 (1<<31) +#define ADC_MASK_TEMP (1<<9) /* temperature sensor */ +#define ADC_MASK_VOLT (1<<10) /* internal reference voltage sensor */ + +#define ADC_MASK_SENSORS (ADC_MASK_TEMP | ADC_MASK_VOLT) +#define ADC_MASK_GROUPB_OFF (0) +#define ADC_MASK_ADD_OFF (0) +#define ADC_MASK_SAMPLE_HOLD_OFF (0) + + +/***************************************************************************** +Typedef definitions +******************************************************************************/ + +/***** ADC_OPEN() ARGUMENT DEFINITIONS *****/ + +typedef enum e_adc_mode +{ + ADC_MODE_SS_TEMPERATURE, // single scan temperature sensor + ADC_MODE_SS_INT_REF_VOLT, // single scan internal ref voltage sensor + ADC_MODE_SS_ONE_CH, // single scan one channel + ADC_MODE_SS_MULTI_CH, // 1 trigger source, scan multiple channels + ADC_MODE_CONT_ONE_CH, // continuous scan one channel + ADC_MODE_CONT_MULTI_CH, // continuous scan multiple channels + ADC_MODE_SS_ONE_CH_DBLTRIG, // on even triggers save to ADDBLDR & interrupt + ADC_MODE_SS_MULTI_CH_GROUPED, // 2 trigger sources, scan multiple channels + ADC_MODE_SS_MULTI_CH_GROUPED_DBLTRIG_A, + ADC_MODE_MAX // This definition DO NOT USE for R_ADC_Open() argument +} adc_mode_t; + +typedef enum e_adc_align +{ + ADC_ALIGN_RIGHT = 0x0000, + ADC_ALIGN_LEFT = 0x8000 +} adc_align_t; + +typedef enum e_adc_add // Addition and averaging of sampled data. +{ + ADC_ADD_OFF = 0, // addition is turned off for chans/sensors + ADC_ADD_TWO_SAMPLES = 1, // Two samples are added,Register ADADC.ADC[1,0] + ADC_ADD_THREE_SAMPLES = 2, // Three samples are added + ADC_ADD_FOUR_SAMPLES = 3, // Four samples are added + ADC_ADD_SIXTEEN_SAMPLES = 5, // Sixteen samples are added + ADC_ADD_AVG_2_SAMPLES = 0x81, // average 2 samples + ADC_ADD_AVG_4_SAMPLES = 0x83, // average 4 samples +} adc_add_t; + +typedef enum e_adc_clear +{ + ADC_CLEAR_AFTER_READ_OFF = 0x0000, + ADC_CLEAR_AFTER_READ_ON = 0x0020 +} adc_clear_t; + + +typedef enum e_adc_trig // trigger sources (set to TRSA bit or TRSB bit) +{ + ADC_TRIG_ASYNC_ADTRG = 0, /* external asynchronous trigger; not for Group modes + nor double trigger modes */ + ADC_TRIG_SYNC_GTADTRA0N = 17, // GPTW0 GTADTRA + ADC_TRIG_SYNC_GTADTRB0N = 18, // GPTW0 GTADTRB + ADC_TRIG_SYNC_GTADTRA1N = 19, // GPTW1 GTADTRA + ADC_TRIG_SYNC_GTADTRB1N = 20, // GPTW1 GTADTRB + ADC_TRIG_SYNC_GTADTRA2N = 21, // GPTW2 GTADTRA + ADC_TRIG_SYNC_GTADTRB2N = 22, // GPTW2 GTADTRB + ADC_TRIG_SYNC_GTADTRA0N_OR_GTADTRB0N = 25, // GPTW0 GTADTRA or GPTW0 GTADTRB + ADC_TRIG_SYNC_GTADTRA1N_OR_GTADTRB1N = 26, // GPTW1 GTADTRA or GPTW1 GTADTRB + ADC_TRIG_SYNC_GTADTRA2N_OR_GTADTRB2N = 27, // GPTW2 GTADTRA or GPTW2 GTADTRB + ADC_TRIG_SYNC_ELCTRG00N = 9, // ELC.ELSR15 + ADC_TRIG_SYNC_ELCTRG01N = 10, // ELC.ELSR56 + ADC_TRIG_SYNC_ELCTRG00N_OR_ELCTRG01N = 11, // ELC.ELSR15 or ELC.ELSR56 + + ADC_TRIG_SOFTWARE = 32, /* software trigger; not for Group modes + nor double trigger modes + This is not set to TRSA or TRSB */ + ADC_TRIG_NONE = 0x3F +} adc_trig_t; + +/* -------------------------------------------------------------------------------------------------------------------- + adc_cycle_t | adc_speed_t | Formula Calculated | value +-------------------------------------------------|-------------------------------------------------------|------------- + ADC_CONVERT_3cycles | ADC_CONVERT_SPEED_HIGH | Number of cycles required to convert one bit * 12 – 4 | 32 cycles + ADC_CONVERT_3cycles | ADC_CONVERT_CURRENT_LOW | Number of cycles required to convert one bit * 12 + 5 | 41 cycles + ADC_CONVERT_2cycles | ADC_CONVERT_SPEED_HIGH | Number of cycles required to convert one bit * 12 – 2 | 22 cycles + ADC_CONVERT_2cycles | ADC_CONVERT_CURRENT_LOW | Number of cycles required to convert one bit * 12 + 4 | 28 cycles +---------------------------------------------------------------------------------------------------------------------*/ +typedef enum e_adc_speed +{ + ADC_CONVERT_SPEED_DEFAULT = 0, + ADC_CONVERT_SPEED_HIGH = 0, + ADC_CONVERT_CURRENT_LOW = 1 +} adc_speed_t; + +typedef enum e_adc_cycle +{ + ADC_CONVERT_3CYCLES = 0, // ADCCR.BIT.CCS = 0, + ADC_CONVERT_2CYCLES = 1 // ADCCR.BIT.CCS = 1, +} adc_cycle_t; + +typedef struct st_adc_cfg +{ + adc_speed_t conv_speed; // ADCSR.ADHSC, rx140 has two conversion speeds + adc_align_t alignment; // ADCER.ADRFMT, Left or Right alignment,ignored if addition used + adc_add_t add_cnt; // ADADC.ADC, Addition/average count select. + adc_clear_t clearing; // ADCER.ACE, Automatic clearing enable/disable after read + adc_trig_t trigger; // ADSTRGR.TRSA, default and Group A trigger source + adc_trig_t trigger_groupb; // valid only for group modes + uint8_t priority; // for S12ADIO int; 1=lo 15=hi 0=off/polled + uint8_t priority_groupb; // S12GBADI interrupt priority; 0-15 + adc_cycle_t conv_cycle; // ADCCR.CCS, Selects the number of cycles required to convert; 2cycles or 3cycles +} adc_cfg_t; + + +/***** ADC_CONTROL() ARGUMENT DEFINITIONS *****/ + +typedef enum e_adc_cmd +{ + /* Commands for special hardware configurations */ + ADC_CMD_USE_VREFL0, // Low reference. Default is to use AVSS0. + ADC_CMD_USE_VREFH0, // High reference. Default is to use AVCC0. + ADC_CMD_SET_DDA_STATE_CNT, // For Disconnect Detection Assist + ADC_CMD_SET_SAMPLE_STATE_CNT, // Set the conversion time + + /* Command to configure channels, sensors, and comparator */ + ADC_CMD_ENABLE_CHANS, // Configure channels to scan + ADC_CMD_ENABLE_TEMP_SENSOR, // "configure" temperature sensor + ADC_CMD_ENABLE_VOLT_SENSOR, // "configure" internal ref voltage sensor + ADC_CMD_EN_COMPARATOR_LEVEL, // Enable comparator for threshold compare + ADC_CMD_EN_COMPARATOR_WINDOW, // Enable comparator for range compare + + /* Commands to enable hardware triggers or cause software trigger */ + ADC_CMD_ENABLE_TRIG, // ADCSR.TRGE=1 for sync/asynchronous triggers + ADC_CMD_SCAN_NOW, // Software trigger start scan + + /* Commands to poll for scan completion and comparator results */ + ADC_CMD_CHECK_SCAN_DONE, // For Normal or GroupA scan + ADC_CMD_CHECK_SCAN_DONE_GROUPA, + ADC_CMD_CHECK_SCAN_DONE_GROUPB, + ADC_CMD_CHECK_CONDITION_MET, // comparator condition + + /* Advanced control commands */ + ADC_CMD_DISABLE_TRIG, // ADCSR.TRGE=0 for sync/async trigs + ADC_CMD_DISABLE_INT, // interrupt disable; ADCSR.ADIE=0 + ADC_CMD_ENABLE_INT, // interrupt enable; ADCSR.ADIE=1 + ADC_CMD_DISABLE_INT_GROUPB, // interrupt disable; ADCSR.GBADIE=0 + ADC_CMD_ENABLE_INT_GROUPB // interrupt enable; ADCSR.GBADIE=1 +} adc_cmd_t; + + +/* for ADC_CMD_SET_DDA_STATE_CNT */ + +typedef enum e_adc_charge // Disconnection Detection Assist (DDA) +{ + ADC_DDA_DISCHARGE = 0x00, + ADC_DDA_PRECHARGE = 0x01, + ADC_DDA_OFF = 0x02 +} adc_charge_t; + + +typedef struct st_adc_dda +{ + adc_charge_t method; // Discharge or Precharge + uint8_t num_states; // 2-15 (0 = DISABLED, 1 is invalid) +} adc_dda_t; + + +/* for ADC_CMD_SET_SAMPLE_STATE_CNT */ + +typedef enum e_adc_sst_reg // sample state registers +{ + ADC_SST_CH0 = 0, + ADC_SST_CH1, + ADC_SST_CH2, + ADC_SST_CH3, + ADC_SST_CH4, + ADC_SST_CH5, + ADC_SST_CH6, + ADC_SST_CH7, + ADC_SST_CH8, + ADC_SST_CH16_TO_31, // Use for ADSSTRL register + ADC_SST_TEMPERATURE, + ADC_SST_VOLTAGE, + ADC_SST_REG_MAX = ADC_SST_VOLTAGE +} adc_sst_reg_t; + + +typedef struct st_adc_sst +{ + adc_sst_reg_t reg_id; + uint8_t num_states; // ch16-31 use the same value +} adc_sst_t; + + +typedef enum e_adc_grpa // action when groupa interrupts groupb scan +{ + ADC_GRPA_PRIORITY_OFF = 0, // groupa ignored and does not interrupt groupb + ADC_GRPA_GRPB_WAIT_TRIG = 1, // groupb restarts at next trigger + ADC_GRPA_GRPB_RESTART_SCAN = 3, // groupb restarts immediately + ADC_GRPA_GRPB_CONT_SCAN= 0x8001, // groupb restarts immediately and scans continuously +} adc_grpa_t; + +typedef enum e_adc_diag // Self-Diagnosis Channel +{ + ADC_DIAG_OFF = 0x00, + ADC_DIAG_0_VOLT = 0x01, + ADC_DIAG_HALF_VREFH0 = 0x02, + ADC_DIAG_VREFH0 = 0x03, + ADC_DIAG_ROTATE_VOLTS = 0x04 +} adc_diag_t; + +typedef enum e_adc_elc +{ + ADC_ELC_SCAN_DONE = 0, // normal scan or Group A scan complete + ADC_ELC_GROUPB_SCAN_DONE, + ADC_ELC_ALL_SCANS_DONE +} adc_elc_t; + +typedef struct st_adc_ch_cfg +{ + uint32_t chan_mask; // channels/bits 0-8, 16-31 + uint32_t chan_mask_groupb; // valid for group modes + adc_grpa_t priority_groupa; // valid for group modes + uint32_t add_mask; // valid if add enabled in Open() + adc_diag_t diag_method; // self-diagnosis virtual channel + adc_elc_t signal_elc; // +} adc_ch_cfg_t; + + +/* for ADC_CMD_EN_COMPARATOR_LEVEL and ADC_CMD_EN_COMPARATOR_WINDOW */ + +typedef struct st_adc_cmpwin_cfg // bit-OR ADC_MASK_xxx to indicate channels/sensors +{ + uint32_t compare_mask; // channels/sensors to compare + uint32_t inside_window_mask; /* condition met when within range + default=0 met when outside range */ + uint16_t level_lo; // Low-value of window + uint16_t level_hi; // High-value of window + bool windowa_enable; // comparison window A enable +} adc_cmpwin_t; + + +/* for ADC_CMD_CHECK_CONDITION_MET use uint32_t */ + +/***** ADC_READ() ARGUMENT DEFINITIONS *****/ +typedef enum e_adc_reg +{ + ADC_REG_CH0 = 0, // Channel 0 + ADC_REG_CH1, + ADC_REG_CH2, + ADC_REG_CH3, + ADC_REG_CH4, + ADC_REG_CH5, + ADC_REG_CH6, + ADC_REG_CH7, + ADC_REG_CH8, // Channel 8 + ADC_REG_CH16, // Channel 16 + ADC_REG_CH17, + ADC_REG_CH18, + ADC_REG_CH19, + ADC_REG_CH20, + ADC_REG_CH21, + ADC_REG_CH22, + ADC_REG_CH23, + ADC_REG_CH24, + ADC_REG_CH25, + ADC_REG_CH26, + ADC_REG_CH27, + ADC_REG_CH28, + ADC_REG_CH29, + ADC_REG_CH30, + ADC_REG_CH31, + ADC_REG_TEMP, // A/D Temperature sensor output + ADC_REG_VOLT, // A/D Internal Voltage Reference + ADC_REG_DBLTRIG, // Data Duplication register + ADC_REG_SELF_DIAG, // self-diagnosis register + ADC_REG_MAX = ADC_REG_SELF_DIAG +} adc_reg_t; + +/* ADC_READALL() ARGUMENT DEFINITIONS */ + +typedef struct st_adc_data +{ + uint16_t chan[32]; + uint16_t temp; + uint16_t volt; + uint16_t dbltrig; + uint16_t self_diag; +} adc_data_t; + + + +/***************************************************************************** +Public Functions +******************************************************************************/ + +#endif /* S12AD_PRV_RX140_IF_H */ +