/* * lightsense.c * * Created on: Oct 18, 2024 * Author: true */ #include #include #include "periph/adc.h" static GPIO_InitTypeDef lsens_gpio = { .GPIO_Mode = GPIO_Mode_Out_PP, .GPIO_Pin = LSENS_A_PIN, .GPIO_Speed = GPIO_Speed_2MHz }; uint16_t lsens_val; static uint8_t lsens_mode = LSENS_READING_IDLE; uint8_t lsens_wait; uint8_t lsens_coarse = 1; uint16_t lsens_timeout; void adc_init() { ADC_InitTypeDef adc = {0}; RCC_ADCCLKConfig(RCC_PCLK2_Div4); 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, LSENS_ADC_CH, 1, ADC_SampleTime_239Cycles5); ADC_Cmd(ADC1, ENABLE); } void adc_convert() { ADC_SoftwareStartConvCmd(ADC1, ENABLE); } void adc_read() { uint16_t timeout = 0xfff; while((!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC)) && timeout) timeout--; if (timeout) { lsens_val = ADC_GetConversionValue(ADC1); } } void adc_set_mode_lsens(uint8_t mode) { lsens_mode = mode; if (mode == LSENS_OUTPUT) { lsens_gpio.GPIO_Mode = GPIO_Mode_Out_PP; lsens_gpio.GPIO_Pin = LSENS_A_PIN; GPIO_Init(LSENS_A_PORT, &lsens_gpio); lsens_gpio.GPIO_Pin = LSENS_K_PIN; GPIO_Init(LSENS_K_PORT, &lsens_gpio); } } uint8_t adc_get_mode_lsens() { return lsens_mode; } static void lsens_start() { // set anode and cathode low LSENS_A_PORT->BCR = LSENS_A_PIN; LSENS_K_PORT->BCR = LSENS_K_PIN; adc_set_mode_lsens(LSENS_READING_START); // set cathode high, let it charge LSENS_K_PORT->BSHR = LSENS_K_PIN; // set anode low lsens_gpio.GPIO_Pin = LSENS_A_PIN; lsens_gpio.GPIO_Mode = GPIO_Mode_IPD; GPIO_Init(LSENS_A_PORT, &lsens_gpio); // set cathode as analog input lsens_gpio.GPIO_Pin = LSENS_K_PIN; lsens_gpio.GPIO_Mode = GPIO_Mode_AIN; GPIO_Init(LSENS_K_PORT, &lsens_gpio); } static void lsens_stop() { lsens_gpio.GPIO_Mode = GPIO_Mode_Out_PP; lsens_gpio.GPIO_Pin = LSENS_A_PIN; GPIO_Init(LSENS_A_PORT, &lsens_gpio); lsens_gpio.GPIO_Pin = LSENS_K_PIN; GPIO_Init(LSENS_K_PORT, &lsens_gpio); lsens_mode = LSENS_READING_IDLE; } void adc_process_lsens() { if (lsens_mode != LSENS_OUTPUT) { // do what needs to be done by me to defeat the light enemys switch (lsens_mode) { case LSENS_READING_IDLE: { // prepare LED, wait a little bit lsens_start(); adc_convert(); lsens_wait = lsens_coarse; lsens_mode = LSENS_READING_START; break; } case LSENS_READING_START: { if (!lsens_wait) { // convert the LED adc_convert(); lsens_mode = LSENS_READING_WAIT; } lsens_wait--; break; } case LSENS_READING_WAIT: { // read the light sensor value adc_read(); lsens_stop(); // calculate adjustments if (lsens_val > LSENS_COARSE_UP) { lsens_coarse++; if (lsens_coarse > 0x3f) lsens_coarse = 0x3f; } else if (lsens_val < LSENS_COARSE_DOWN) { if (lsens_coarse) lsens_coarse--; } lsens_wait = 255 - lsens_coarse; // wait a bit before doing it again lsens_mode = LSENS_READING_TIMEOUT; break; } case LSENS_READING_TIMEOUT: { if (!lsens_wait) { // do it all again lsens_mode = LSENS_READING_IDLE; } lsens_wait--; } } } } uint16_t adc_get_lsens() { return lsens_val; } uint8_t adc_get_lsens_coarse() { return lsens_coarse; }