/* * lightsense.c * * Created on: Oct 18, 2024 * Author: true */ #include #include #include "adc.h" static const uint8_t led_brightness_map[] = { 47, 44, 42, 41, 40, 38, 36, 34, 32, 31, 30, 29, 27, 25, 21, 19, 17, 16, 15, 15, // indoors normal brightness 14, 14, 13, 13, 12, 12, 12, 11, 11, 11, 10, 10, 10, 9, 9, 9, 8, 8, 8, 8, 7, 7, 7, 7, 7, 6, 6, 6 }; static GPIO_InitTypeDef lsens_gpio = { .GPIO_Mode = GPIO_Mode_Out_PP, .GPIO_Pin = LSENS_A_PIN | LSENS_K_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; 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_Pin = LSENS_A_PIN | LSENS_K_PIN; lsens_gpio.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_Init(LSENS_PORT, &lsens_gpio); } } uint8_t adc_get_mode_lsens() { return lsens_mode; } static void lsens_start() { // set anode and cathode low LSENS_PORT->BCR = LSENS_A_PIN | LSENS_K_PIN; adc_set_mode_lsens(LSENS_READING_START); // set cathode high, let it charge LSENS_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_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_PORT, &lsens_gpio); } static void lsens_stop() { lsens_gpio.GPIO_Pin = LSENS_A_PIN | LSENS_K_PIN; lsens_gpio.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_Init(LSENS_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; } uint8_t adc_get_brightness(uint8_t level) { if (!level) { // are you outside? why? it's too fucking hot // we'll shut down when in the presence of big nuclear fire if (adc_get_lsens() < 400) { // yup, outside or in a spotlight at 3ft away or something return 0; } } if (level >= sizeof(led_brightness_map)) { return led_brightness_map[sizeof(led_brightness_map) - 1]; } return led_brightness_map[level]; }