← Commit history
design/stm32-adc-host-tests.log+2−1
@@ -1,3 +1,4 @@+ADC adapter fake-HAL: channel isolation, every-operation failure, saturation and age/wrap passed. STM32 adapter fake-HAL: pins, endian/address encoding, zero-only DAC, age and sticky faults passed. load_core: safety policy tests passed (host C build; no MCU/HAL validation) fan_tach: qualification, RPM, stale input, noise, slow fan, timer wrap and stale-history expiry passed@@ -7,6 +8,6 @@ Measurement cache: conversion age, WAIT expiry, fault latch and clock wrap passe Instrument register, readback, signed conversion and transaction-failure tests passed. ......................... -----------------------------------------------------------------------Ran 25 tests in 0.071s+Ran 25 tests in 0.059s  OK
docs/completion-plan.md+1−1
@@ -25,7 +25,7 @@ Sunon MF40200V1-1000U-G99 version 0.2.3 is published in source and registry: fac  ## Firmware continuation -Fresh latch acknowledgement, instrument readback/fault injection, and null-sensor diagnostic host connections are implemented and host-tested (25 Python tests plus C suites). MCU output stays locked; no flash occurred. Diagnostic I2C integration, conversion-age cache and fake-HAL tests now pass; nominal ADC/temperature adaptation now compiles and its conversion math passes host tests. Continue with ADC adapter fault injection, board calibration and physical timing tests. Do not mistake these checks for physical qualification or use them to close thermal/finish gates. The reviewed fan-stall replay brings the raw inventory to 63 (the latest static fastener-page take is excluded from the action edit).+Fresh latch acknowledgement, instrument readback/fault injection, and null-sensor diagnostic host connections are implemented and host-tested (25 Python tests plus C suites). MCU output stays locked; no flash occurred. Diagnostic I2C integration, conversion-age cache and fake-HAL tests now pass; nominal ADC/temperature adaptation now compiles and its conversion math passes host tests. ADC adapter fault injection now passes for every HAL operation, channel isolation, saturation and stale/timer-wrap handling. Board calibration and physical timing tests remain. Do not mistake these checks for physical qualification or use them to close thermal/finish gates. The reviewed fan-stall replay brings the raw inventory to 63 (the latest static fastener-page take is excluded from the action edit).  ## Browser recovery and fastener review 
docs/status.md+13
@@ -121,3 +121,16 @@ The schematic capture attempt failed with an encoder initialization timeout. Oth A read-only Bridge inspection unexpectedly reported dismissing an unrelated Remote Desktop dialog. Reported to the owner as [adom/kicad-bridge#120](https://wiki.adom.inc/adom/kicad-bridge/issues/120). No fix or deployment is verified. Subsequent window inventories use `autoDismiss:false`.  Placement update: the native candidate now has zero DRC violations, with 218 unrouted connections. Its USB intra-footprint hole-clearance rule and unresolved U2 assembled label location are documented in the placement review.+++## 9 October, 20:54 UTC continuation++AIFlow 0.1.77 is source-published directly, registry-published and locally installed. The actual Native Browser visual/DOM disagreement now classifies as human verification. Its published release page was visually reviewed. This does not prove installation in Colby's session.++Board 18 remains unchanged; live revision rechecked. The dashboard is open at thermal-vias, step 9 of 19. Fields 0.6.2 remains installed, physical-stack/PTH PR #5 remains open, and package heat-path issue #8 remains open. No thermal/finish gate was waived.++The cooling fastener review now checks the actual TO-220 tab thickness and the PPS washer catalog, plus a clearly limited short-sleeve centering sensitivity. No exact toleranced clamp stack is qualified. The stock sink candidate remains provisional.++The output-locked firmware now cross-compiles I2C and ADC diagnostics. Host tests cover actual I2C/ADC adapter code through fake HALs, register faults, sample age, nominal thermistor conversion and existing safety/protocol behavior; 25 Python tests also pass. The current build uses 74,004 bytes flash and 24,192 bytes RAM including reservations. No flash, physical sensor measurement, calibration or enabled load test occurred. Sensor and assembly qualification remain false.++The video inventory is 63 raw takes, including rejected material. The newest static fastener-page recording is excluded from the action edit; its full decode passed and recorder timing warning is retained. This is not 63 finished highlights. The narrated final film remains incomplete.
firmware/stm32/README.md+1−1
@@ -69,4 +69,4 @@ PA1 reads DUT voltage through the nominal 100k/10k divider; PA0 reads the 10k pu  Temperature conversion uses the extended Steinhart–Hart coefficients for material A, Bn3977, in [Vishay NTCLE100E3 document 29049, revision 7 May 2025](https://www.vishay.com/docs/29049/ntcle100.pdf). The actual 5%-tolerance NTC and its case attachment are uncalibrated. Tests compare nominal table points at 0, 55 and 100 C, plus divider/reference scaling and saturation rejection. They do not certify temperature accuracy or shutdown temperature. -A failed conversion, implausible reference, saturated sensor or out-of-range nominal temperature invalidates ADC diagnostics until reset. Samples expire after 50 ms. The combined reply uses the older available ADC/INA timestamp. `sensors_valid` remains false even when numbers are available, and assembly qualification remains false. No production enable path was added. ADC peripheral behavior is cross-compiled but has not yet been exercised with a fake ADC HAL or on hardware.+A failed conversion, implausible reference, saturated sensor or out-of-range nominal temperature invalidates ADC diagnostics until reset. Samples expire after 50 ms. The combined reply uses the older available ADC/INA timestamp. `sensors_valid` remains false even when numbers are available, and assembly qualification remains false. No production enable path was added. The real ADC adapter is also exercised through a fake HAL: channel selection/removal, failure at every HAL operation, saturation and stale/timer-wrap handling. Physical ADC operation remains unverified.
tests/adc_hal_stub/stm32g0xx_hal.hadded+42
@@ -0,0 +1,42 @@+#include <stdint.h>+typedef int HAL_StatusTypeDef;+#define HAL_OK 0+#define HAL_ERROR 1+typedef struct {uint32_t Pin,Mode,Pull;} GPIO_InitTypeDef;+typedef struct {uint32_t ClockPrescaler,Resolution,DataAlign,ScanConvMode,EOCSelection,NbrOfConversion,ExternalTrigConv,ExternalTrigConvEdge,Overrun,SamplingTimeCommon1,SamplingTimeCommon2,TriggerFrequencyMode;} TestADCInit;+typedef struct {void *Instance;TestADCInit Init;} ADC_HandleTypeDef;+typedef struct {uint32_t Channel,Rank,SamplingTime;} ADC_ChannelConfTypeDef;+#define ADC1 ((void *)1)+#define GPIOA ((void *)2)+#define GPIO_PIN_0 1+#define GPIO_PIN_1 2+#define GPIO_MODE_ANALOG 3+#define GPIO_NOPULL 0+#define ADC_RANK_CHANNEL_NUMBER 1+#define ADC_RANK_NONE 2+#define ADC_SAMPLINGTIME_COMMON_1 1+#define ADC_CHANNEL_0 0+#define ADC_CHANNEL_1 1+#define ADC_CHANNEL_VREFINT 13+#define ADC_CLOCK_SYNC_PCLK_DIV4 4+#define ADC_RESOLUTION_12B 12+#define ADC_DATAALIGN_RIGHT 0+#define ADC_SCAN_SEQ_FIXED 1+#define ADC_EOC_SINGLE_CONV 1+#define ADC_SOFTWARE_START 1+#define ADC_EXTERNALTRIGCONVEDGE_NONE 0+#define ADC_OVR_DATA_PRESERVED 1+#define ADC_SAMPLETIME_160CYCLES_5 1605+#define ADC_TRIGGER_FREQ_LOW 0+#define __HAL_RCC_GPIOA_CLK_ENABLE() ((void)0)+#define __HAL_RCC_ADC_CLK_ENABLE() ((void)0)+uint32_t HAL_GetTick(void);+void HAL_Delay(uint32_t);+void HAL_GPIO_Init(void *,GPIO_InitTypeDef *);+HAL_StatusTypeDef HAL_ADC_Init(ADC_HandleTypeDef *);+HAL_StatusTypeDef HAL_ADCEx_Calibration_Start(ADC_HandleTypeDef *);+HAL_StatusTypeDef HAL_ADC_ConfigChannel(ADC_HandleTypeDef *,ADC_ChannelConfTypeDef *);+HAL_StatusTypeDef HAL_ADC_Start(ADC_HandleTypeDef *);+HAL_StatusTypeDef HAL_ADC_PollForConversion(ADC_HandleTypeDef *,uint32_t);+uint32_t HAL_ADC_GetValue(ADC_HandleTypeDef *);+HAL_StatusTypeDef HAL_ADC_Stop(ADC_HandleTypeDef *);
tests/adc_hal_stub/stm32g0xx_ll_adc.hadded+2
@@ -0,0 +1,2 @@+extern const unsigned short test_factory_cal;+#define VREFINT_CAL_ADDR (&test_factory_cal)
tests/test_adc_input.cadded+46
@@ -0,0 +1,46 @@+#include <assert.h>+#include <math.h>+#include <stdio.h>+#define ADOM_BRINGUP_OUTPUT_LOCK 1+#include "../firmware/stm32/adc_input.c"+const unsigned short test_factory_cal=1650;+static uint32_t tick;+static int selected=-1;+static unsigned calls,fail_at;+static uint16_t ntc_code=2048;+static bool started;+static HAL_StatusTypeDef step(void){return ++calls==fail_at?HAL_ERROR:HAL_OK;}+uint32_t HAL_GetTick(void){return tick;}+void HAL_Delay(uint32_t t){tick+=t;}+void HAL_GPIO_Init(void *p,GPIO_InitTypeDef *g){assert(p==GPIOA&&g->Pin==3&&g->Mode==GPIO_MODE_ANALOG&&g->Pull==GPIO_NOPULL);}+HAL_StatusTypeDef HAL_ADC_Init(ADC_HandleTypeDef *a){assert(a->Instance==ADC1&&a->Init.Resolution==12&&a->Init.ClockPrescaler==4);return step();}+HAL_StatusTypeDef HAL_ADCEx_Calibration_Start(ADC_HandleTypeDef *a){(void)a;return step();}+HAL_StatusTypeDef HAL_ADC_ConfigChannel(ADC_HandleTypeDef *a,ADC_ChannelConfTypeDef *c){+ (void)a;assert(!started);if(step()!=HAL_OK)return HAL_ERROR;+ if(c->Rank==ADC_RANK_NONE){assert(selected==(int)c->Channel);selected=-1;}+ else{assert(selected==-1);selected=(int)c->Channel;}return HAL_OK;+}+HAL_StatusTypeDef HAL_ADC_Start(ADC_HandleTypeDef *a){(void)a;assert(selected>=0&&!started);if(step()!=HAL_OK)return HAL_ERROR;started=true;return HAL_OK;}+HAL_StatusTypeDef HAL_ADC_PollForConversion(ADC_HandleTypeDef *a,uint32_t timeout){(void)a;assert(started&&timeout==2);return step();}+uint32_t HAL_ADC_GetValue(ADC_HandleTypeDef *a){(void)a;assert(started);return selected==13?1500:selected==1?564:ntc_code;}+HAL_StatusTypeDef HAL_ADC_Stop(ADC_HandleTypeDef *a){(void)a;started=false;return step();}+static void reset(void){tick=0;calls=fail_at=0;selected=-1;started=false;ntc_code=2048;}+int main(void){+ reset();assert(load_adc_input_init());float v=-1,t=-1;uint32_t s=99;+ assert(!load_adc_input_read(&v,&t,&s));tick=10;load_adc_input_poll();+ assert(load_adc_input_read(&v,&t,&s)&&s==10&&fabsf(v-5)<.005f&&fabsf(t-25)<.03f);+ unsigned sequence_calls=calls;assert(selected==-1);+ tick=61;assert(!load_adc_input_read(&v,&t,&s));+ /* Fail every HAL operation, both initialization and a complete scan. */+ for(unsigned i=1;i<=sequence_calls;i++){+  reset();fail_at=i;bool init_ok=load_adc_input_init();+  if(init_ok){tick=10;load_adc_input_poll();}+  assert(!load_adc_input_read(&v,&t,&s));+  unsigned n=calls;tick=100;load_adc_input_poll();assert(calls==n);+ }+ reset();assert(load_adc_input_init());ntc_code=4095;tick=10;load_adc_input_poll();+ assert(!load_adc_input_read(&v,&t,&s));+ reset();tick=UINT32_MAX-20;assert(load_adc_input_init());tick=UINT32_MAX-10;load_adc_input_poll();+ assert(load_adc_input_read(&v,&t,&s));tick=40;assert(!load_adc_input_read(&v,&t,&s));+ puts("ADC adapter fake-HAL: channel isolation, every-operation failure, saturation and age/wrap passed.");+}
tools/check_firmware.sh+2
@@ -4,6 +4,8 @@ cd "$(dirname "$0")/.." load_check_dir=$(mktemp -d) trap 'rm -rf "$load_check_dir"' EXIT cc_args=(-std=c11 -Wall -Wextra -Werror -fsanitize=address,undefined -g)+gcc "${cc_args[@]}" -Itests/adc_hal_stub -Ifirmware firmware/adc_conversion.c tests/test_adc_input.c -lm -o "$load_check_dir/adc-adapter"+"$load_check_dir/adc-adapter" gcc "${cc_args[@]}" -Itests/hal_stub -Ifirmware firmware/instruments.c firmware/measurement_cache.c tests/test_instrument_input.c -lm -o "$load_check_dir/adapter" "$load_check_dir/adapter" gcc "${cc_args[@]}" firmware/load_core.c tests/test_load_core.c -lm -o "$load_check_dir/core"