dc32-retro-tech-addon/firmware/retro_tech_fw/user/src/adc.c

145 lines
3.0 KiB
C

/*
* Created on: Jul 27, 2024
*
* because the ambient light sensor is facing toward the bottom, and
* this badge has an "ADJUST" knob that is intended for brightness,
* the light sensor code is incomplete.
*
* if you want to use it, copy code from another badge, where it's also
* likely incomplete lol
*/
#include <ch32v00x.h>
// deadzone fudge factors for potentionmeter. test on actual badge
// and see if necessary, or if pot hardware + adc periph is good enough
#define POT_LO 40
#define POT_HI (1024-POT_LO)
uint16_t adc_val[16];
uint16_t adc_val_idx;
uint16_t adc_avg;
uint16_t lsens_val;
void adc_init()
{
ADC_InitTypeDef adc = {0};
GPIO_InitTypeDef gpio = {0};
RCC_ADCCLKConfig(RCC_PCLK2_Div4);
gpio.GPIO_Pin = GPIO_Pin_3;
gpio.GPIO_Mode = GPIO_Mode_AIN;
GPIO_Init(GPIOD, &gpio);
ADC_DeInit(ADC1);
adc.ADC_Mode = ADC_Mode_Independent;
adc.ADC_ScanConvMode = DISABLE;
adc.ADC_ContinuousConvMode = DISABLE;
adc.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
adc.ADC_DataAlign = ADC_DataAlign_Right;
adc.ADC_NbrOfChannel = 1;
ADC_Init(ADC1, &adc);
ADC_RegularChannelConfig(ADC1, ADC_Channel_4, 1, ADC_SampleTime_241Cycles);
ADC_InjectedChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_73Cycles);
ADC_Calibration_Vol(ADC1, ADC_CALVOL_50PERCENT);
ADC_Cmd(ADC1, ENABLE);
ADC_ResetCalibration(ADC1);
while(ADC_GetResetCalibrationStatus(ADC1));
ADC_StartCalibration(ADC1);
while(ADC_GetCalibrationStatus(ADC1));
}
void adc_calc_avg()
{
uint8_t i;
uint16_t sum = 0;
for (i = 0; i < 16; i++) {
sum += adc_val[i];
}
sum >>= 4;
adc_avg = sum;
}
void adc_convert()
{
ADC_SoftwareStartConvCmd(ADC1, ENABLE);
}
void adc_read()
{
if (ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC)) {
adc_val[adc_val_idx++] = ADC_GetConversionValue(ADC1);
adc_val_idx &= 0x0f;
if (!adc_val_idx) adc_calc_avg();
if (ADC1->CTLR1 & ADC_JAUTO) {
if (ADC_GetFlagStatus(ADC1, ADC_FLAG_JEOC)) {
lsens_val = ADC_GetInjectedConversionValue(ADC1, ADC_InjectedChannel_1);
// reset LSENS
ADC_AutoInjectedConvCmd(ADC1, DISABLE);
}
}
}
}
void adc_use_lsens()
{
GPIO_InitTypeDef gpio = {0};
// configure GPIO
gpio.GPIO_Pin = GPIO_Pin_2;
gpio.GPIO_Mode = GPIO_Mode_AIN;
GPIO_Init(GPIOA, &gpio);
// enable injected channel
ADC_AutoInjectedConvCmd(ADC1, ENABLE);
}
void adc_stop_lsens()
{
GPIO_InitTypeDef gpio = {0};
// configure GPIO
gpio.GPIO_Pin = GPIO_Pin_2;
gpio.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOA, &gpio);
}
uint8_t adc_get_pot()
{
uint32_t pot;
// set lower bound
pot = adc_avg;
if (pot < POT_LO) pot = 0; else pot -= POT_LO;
// scale to upper bound
pot <<= 10;
pot /= POT_HI;
// 8 bits is good enough for us
pot >>= 2;
return 255 - (pot & 0xff);
}
uint16_t adc_get_lsens()
{
return lsens_val;
}