#include "lamp_board_inputs.h"
#include "lamp_ir_filter.h"
#include "stm32g0xx.h"
static lamp_ir_filter ir_filter;
static bool ir_initialized;
static bool clock_allows_ir(void) {
    return (RCC->BDCR & (RCC_BDCR_LSEON|RCC_BDCR_LSERDY|RCC_BDCR_LSEBYP))==0u;
}
static bool configuration_allows_ir(void) {
    return (RCC->IOPENR & RCC_IOPENR_GPIOCEN)!=0u && clock_allows_ir() &&
           (GPIOC->LCKR & ((1u<<16u)|(1u<<15u)))!=((1u<<16u)|(1u<<15u)) &&
           (GPIOC->MODER & (3u<<30u))==0u &&
           (GPIOC->PUPDR & (3u<<30u))==0u &&
           (GPIOC->AFR[1] & (15u<<28u))==0u;
}
bool lamp_board_ir_init(void) {
    ir_initialized=false;ir_filter=(lamp_ir_filter){0};
    if (!clock_allows_ir()) return false;
    RCC->IOPENR |= RCC_IOPENR_GPIOCEN;
    (void)RCC->IOPENR;
    if ((GPIOC->LCKR & ((1u<<16u)|(1u<<15u)))==((1u<<16u)|(1u<<15u))) return false;
    GPIOC->MODER &= ~(3u<<30u);
    GPIOC->PUPDR &= ~(3u<<30u); /* Use A39 external 47k pulldown. */
    GPIOC->AFR[1] &= ~(15u<<28u);
    __DSB();
    ir_initialized=configuration_allows_ir();
    return ir_initialized;
}
lamp_board_input_snapshot lamp_board_inputs_read(uint32_t now_ms) {
    lamp_board_input_snapshot s={0};
    const uint32_t pa=GPIOA->IDR;
    const uint32_t pb=GPIOB->IDR;
    s.thermal_contact_closed=(pa & (1u<<12u))!=0u;
    s.hardware_interlock_closed=(pa & (1u<<0u))!=0u;
    s.user_key_pressed=(pb & (1u<<0u))==0u;
    s.infrared_gpio_available=ir_initialized && configuration_allows_ir();
    s.infrared_raw_high=s.infrared_gpio_available && (GPIOC->IDR & (1u<<15u))!=0u;
    s.guard_inputs.hardware_interlock_ok=s.hardware_interlock_closed;
    s.guard_inputs.infrared_hand_present=lamp_ir_filter_update(&ir_filter,
        s.infrared_gpio_available,s.infrared_raw_high,now_ms);
    /* NTC/rail calibration and driver health are not bound yet; those fields
       deliberately remain false. A closed thermal contact is raw evidence. */
    return s;
}
