custom-uv-k5-firmware/driver/adc.c
2023-08-10 20:37:33 +01:00

167 lines
5.5 KiB
C

/* Copyright 2023 Dual Tachyon
* https://github.com/DualTachyon
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "ARMCM0.h"
#include "adc.h"
#include "bsp/dp32g030/irq.h"
#include "bsp/dp32g030/saradc.h"
#include "bsp/dp32g030/syscon.h"
uint8_t ADC_GetChannelNumber(ADC_CH_MASK Mask)
{
if (Mask & ADC_CH15) return 15U;
if (Mask & ADC_CH14) return 14U;
if (Mask & ADC_CH13) return 13U;
if (Mask & ADC_CH12) return 12U;
if (Mask & ADC_CH11) return 11U;
if (Mask & ADC_CH10) return 10U;
if (Mask & ADC_CH9) return 9U;
if (Mask & ADC_CH8) return 8U;
if (Mask & ADC_CH7) return 7U;
if (Mask & ADC_CH6) return 6U;
if (Mask & ADC_CH5) return 5U;
if (Mask & ADC_CH4) return 4U;
if (Mask & ADC_CH3) return 3U;
if (Mask & ADC_CH2) return 2U;
if (Mask & ADC_CH1) return 1U;
if (Mask & ADC_CH0) return 0U;
return 0U;
}
void ADC_Disable(void)
{
SARADC_CFG = (SARADC_CFG & ~SARADC_CFG_ADC_EN_MASK) | SARADC_CFG_ADC_EN_BITS_DISABLE;
}
void ADC_Enable(void)
{
SARADC_CFG = (SARADC_CFG & ~SARADC_CFG_ADC_EN_MASK) | SARADC_CFG_ADC_EN_BITS_ENABLE;
}
void ADC_SoftReset(void)
{
SARADC_START = (SARADC_START & ~SARADC_START_SOFT_RESET_MASK) | SARADC_START_SOFT_RESET_BITS_ASSERT;
SARADC_START = (SARADC_START & ~SARADC_START_SOFT_RESET_MASK) | SARADC_START_SOFT_RESET_BITS_DEASSERT;
}
// The firmware thinks W_SARADC_SMPL_CLK_SEL is at [8:7] but the TRM says it's at [10:9]
#define FW_R_SARADC_SMPL_SHIFT 7
#define FW_R_SARADC_SMPL_MASK (3U << FW_R_SARADC_SMPL_SHIFT)
uint32_t ADC_GetClockConfig(void)
{
uint32_t Value;
Value = SYSCON_CLK_SEL;
Value = 0
| (Value & ~(SYSCON_CLK_SEL_R_PLL_MASK | FW_R_SARADC_SMPL_MASK))
| (((Value & SYSCON_CLK_SEL_R_PLL_MASK) >> SYSCON_CLK_SEL_R_PLL_SHIFT) << SYSCON_CLK_SEL_W_PLL_SHIFT)
| (((Value & FW_R_SARADC_SMPL_MASK) >> FW_R_SARADC_SMPL_SHIFT) << SYSCON_CLK_SEL_W_SARADC_SMPL_SHIFT)
;
return Value;
}
void ADC_Configure(ADC_Config_t *pAdc)
{
SYSCON_DEV_CLK_GATE = (SYSCON_DEV_CLK_GATE & ~SYSCON_DEV_CLK_GATE_SARADC_MASK) | SYSCON_DEV_CLK_GATE_SARADC_BITS_ENABLE;
ADC_Disable();
SYSCON_CLK_SEL = (ADC_GetClockConfig() & ~SYSCON_CLK_SEL_W_SARADC_SMPL_MASK) | ((pAdc->CLK_SEL << SYSCON_CLK_SEL_W_SARADC_SMPL_SHIFT) & SYSCON_CLK_SEL_W_SARADC_SMPL_MASK);
SARADC_CFG = 0
| (SARADC_CFG & ~(0
| SARADC_CFG_CH_SEL_MASK
| SARADC_CFG_AVG_MASK
| SARADC_CFG_CONT_MASK
| SARADC_CFG_SMPL_SETUP_MASK
| SARADC_CFG_MEM_MODE_MASK
| SARADC_CFG_SMPL_CLK_MASK
| SARADC_CFG_SMPL_WIN_MASK
| SARADC_CFG_ADC_TRIG_MASK
| SARADC_CFG_DMA_EN_MASK
))
| ((pAdc->CH_SEL << SARADC_CFG_CH_SEL_SHIFT) & SARADC_CFG_CH_SEL_MASK)
| ((pAdc->AVG << SARADC_CFG_AVG_SHIFT) & SARADC_CFG_AVG_MASK)
| ((pAdc->CONT << SARADC_CFG_CONT_SHIFT) & SARADC_CFG_CONT_MASK)
| ((pAdc->SMPL_SETUP << SARADC_CFG_SMPL_SETUP_SHIFT) & SARADC_CFG_SMPL_SETUP_MASK)
| ((pAdc->MEM_MODE << SARADC_CFG_MEM_MODE_SHIFT) & SARADC_CFG_MEM_MODE_MASK)
| ((pAdc->SMPL_CLK << SARADC_CFG_SMPL_CLK_SHIFT) & SARADC_CFG_SMPL_CLK_MASK)
| ((pAdc->SMPL_WIN << SARADC_CFG_SMPL_WIN_SHIFT) & SARADC_CFG_SMPL_WIN_MASK)
| ((pAdc->ADC_TRIG << SARADC_CFG_ADC_TRIG_SHIFT) & SARADC_CFG_ADC_TRIG_MASK)
| ((pAdc->DMA_EN << SARADC_CFG_DMA_EN_SHIFT) & SARADC_CFG_DMA_EN_MASK)
;
SARADC_EXTTRIG_SEL = pAdc->EXTTRIG_SEL;
if (pAdc->CALIB_OFFSET_VALID) {
SARADC_CALIB_OFFSET = (SARADC_CALIB_OFFSET & ~SARADC_CALIB_OFFSET_VALID_MASK) | SARADC_CALIB_OFFSET_VALID_BITS_YES;
} else {
SARADC_CALIB_OFFSET = (SARADC_CALIB_OFFSET & ~SARADC_CALIB_OFFSET_VALID_MASK) | SARADC_CALIB_OFFSET_VALID_BITS_NO;
}
if (pAdc->CALIB_KD_VALID) {
SARADC_CALIB_KD = (SARADC_CALIB_KD & ~SARADC_CALIB_KD_VALID_MASK) | SARADC_CALIB_KD_VALID_BITS_YES;
} else {
SARADC_CALIB_KD = (SARADC_CALIB_KD & ~SARADC_CALIB_KD_VALID_MASK) | SARADC_CALIB_KD_VALID_BITS_NO;
}
SARADC_IF = 0xFFFFFFFF;
SARADC_IE = 0
| (SARADC_IE & ~(0
| SARADC_IE_CHx_EOC_MASK
| SARADC_IE_FIFO_FULL_MASK
| SARADC_IE_FIFO_HFULL_MASK
))
| ((pAdc->IE_CHx_EOC << SARADC_IE_CHx_EOC_SHIFT) & SARADC_IE_CHx_EOC_MASK)
| ((pAdc->IE_FIFO_FULL << SARADC_IE_FIFO_FULL_SHIFT) & SARADC_IE_FIFO_FULL_MASK)
| ((pAdc->IE_FIFO_HFULL << SARADC_IE_FIFO_HFULL_SHIFT) & SARADC_IE_FIFO_HFULL_MASK)
;
if (SARADC_IE == 0) {
NVIC_DisableIRQ(DP32_SARADC_IRQn);
} else {
NVIC_EnableIRQ(DP32_SARADC_IRQn);
}
}
void ADC_Start(void)
{
SARADC_START = (SARADC_START & ~SARADC_START_START_MASK) | SARADC_START_START_BITS_ENABLE;
}
bool ADC_CheckEndOfConversion(ADC_CH_MASK Mask)
{
volatile ADC_Channel_t *pChannels = (volatile ADC_Channel_t *)&SARADC_CH0;
uint8_t Channel = ADC_GetChannelNumber(Mask);
return (pChannels[Channel].STAT & ADC_CHx_STAT_EOC_MASK) >> ADC_CHx_STAT_EOC_SHIFT;
}
uint16_t ADC_GetValue(ADC_CH_MASK Mask)
{
volatile ADC_Channel_t *pChannels = (volatile ADC_Channel_t *)&SARADC_CH0;
uint8_t Channel = ADC_GetChannelNumber(Mask);
SARADC_IF = 1 << Channel; // TODO: Or just use 'Mask'
return (pChannels[Channel].DATA & ADC_CHx_DATA_DATA_MASK) >> ADC_CHx_DATA_DATA_SHIFT;
}