from pathlib import Path
import shutil
R=Path(__file__).resolve().parent; B=R.parent
shutil.copytree(B/'lamp_pinmap_A36/firmware',R/'firmware',ignore=shutil.ignore_patterns('build','__pycache__'))
D=R/'firmware/固件'; C=D/'lamp_control';T=D/'lamp_target'
for n in ['lamp_guard.c','lamp_guard.h','test_lamp_guard.c','test_lamp_program.c','test_lamp_ir.c']:
 shutil.copy2(B/'lamp_ir_A35/lamp_control'/n,C/n)
# Explicitly provide simulated physical IR=true in existing positive fixtures.
# No target source is granted readiness by these host-only fixtures.
for p in C.glob('test_*.c'):
 s=p.read_text();s=s.replace('{true, true, true, true}', '{true, true, true, true, true}');p.write_text(s)
(T/'include/lamp_board_inputs.h').write_text('''#ifndef LAMP_BOARD_INPUTS_H
#define LAMP_BOARD_INPUTS_H
#include "lamp_guard.h"
typedef struct {
    bool thermal_contact_closed;
    bool hardware_interlock_closed;
    bool user_key_pressed;
    lg_inputs guard_inputs;
} lamp_board_input_snapshot;
/* Read physical PCA-branch pin17 PA12 and pin7 PA0. No ADC, LED-driver
 * health or IR interface is bound yet; those readiness flags remain false.
 * Raw thermal contact must not substitute for calibrated NTC temperature. */
lamp_board_input_snapshot lamp_board_inputs_read(void);
#endif
''')
(T/'src/lamp_board_inputs.c').write_text('''#include "lamp_board_inputs.h"
#include "stm32g0xx.h"
lamp_board_input_snapshot lamp_board_inputs_read(void) {
    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.guard_inputs.hardware_interlock_ok = s.hardware_interlock_closed;
    /* No temperature/rail calibration, driver readback or physical IR input.
     * Unmeasured conditions cannot authorize output or fresh vision tickets. */
    return s;
}
''')
p=T/'src/main.c';s=p.read_text().replace('#include "lamp_uart.h"','#include "lamp_uart.h"\n#include "lamp_board_inputs.h"')
s=s.replace('volatile uint32_t lamp_debug_ui_ack_failures;', '''volatile uint32_t lamp_debug_ui_ack_failures;
volatile uint32_t lamp_debug_raw_input_bits;

static void sample_and_poll_inputs(void) {
    const lamp_board_input_snapshot sample = lamp_board_inputs_read();
    lamp_debug_raw_input_bits = (sample.thermal_contact_closed ? 1u : 0u) |
                               (sample.hardware_interlock_closed ? 2u : 0u) |
                               (sample.user_key_pressed ? 4u : 0u);
    lg_poll(&rx_guard, system_tick_ms, sample.guard_inputs);
}''')
s=s.replace('    for (;;) {\n        lamp_uart_get_stats','    for (;;) {\n        sample_and_poll_inputs();\n        lamp_uart_get_stats')
s=s.replace('                ++lamp_debug_crc_valid_frames;', '                sample_and_poll_inputs(); /* Re-sample before accepting any command/result. */\n                ++lamp_debug_crc_valid_frames;')
p.write_text(s)
p=T/'build.sh';s=p.read_text().replace('$CC $FLAGS $INCLUDES -c "$TARGET/src/main.c" -o "$OUT/main.o"','$CC $FLAGS $INCLUDES -c "$TARGET/src/main.c" -o "$OUT/main.o"\n$CC $FLAGS $INCLUDES -c "$TARGET/src/lamp_board_inputs.c" -o "$OUT/lamp_board_inputs.o"').replace('"$OUT/runtime.o" "$OUT/main.o" \\', '"$OUT/runtime.o" "$OUT/main.o" "$OUT/lamp_board_inputs.o" \\');p.write_text(s)
p=T/'verify_image.py';s=p.read_text().replace('"SysTick_Handler", "main")','"SysTick_Handler", "lamp_board_inputs_read", "lg_poll", "main")');s=s.replace('for forbidden in (', '''# GPIO sampler and policy poll must be reachable from the actual entry loop,
# possibly through the compiler-kept sampling helper.
sample_path = main_body
if "sample_and_poll_inputs" in main_body:
    sample_path += function_body("sample_and_poll_inputs")
for call in ("lamp_board_inputs_read", "lg_poll"):
    if call not in sample_path:
        raise SystemExit("main has no bound physical sampler/poll call: " + call)
for forbidden in (''');s=s.replace('    "runtime_control_enabled": False,','    "runtime_control_enabled": False,\n    "physical_contact_GPIO_sampling_bound": True,\n    "A35_IR_policy_linked": True,\n    "IR_GPIO_bound": False,\n    "ADC_temperature_and_supply_sampling_bound": False,\n    "LED_driver_health_readback_bound": False,');p.write_text(s)
print('A37 target sources prepared')
