#define main drill_entry
#include "firmware/固件/drill_target/src/main.c"
#undef main
#include "firmware/固件/drill_target/src/drill_clock.c"
#include "firmware/固件/drill_target/src/drill_pwm_stage.c"
#include "firmware/固件/drill_target/src/drill_spi_transport.c"
#include "firmware/固件/drill_target/src/drill_timebase.c"
#include "firmware/固件/drill_target/src/drill_safe_gpio.c"
#include "firmware/固件/drill_target/src/drill_config_binding.c"
#include "firmware/固件/drill_target/src/drill_config_async.c"
#include "firmware/固件/drill_driver/drv8316.c"
#include "firmware/固件/drill_target/src/drill_adc_capture.c"
#include "firmware/固件/drill_target/src/drill_dual_adc.c"
#include <assert.h>
#include <stdio.h>
#include <string.h>
#include "host_clock_fixture.h"
#include <setjmp.h>
DMA_TypeDef dma;DMA_Channel_TypeDef dma_channel;DMAMUX_Channel_TypeDef mux;DMAMUX_ChannelStatus_TypeDef mux_status;ADC_TypeDef adc1,adc2;ADC_Common_TypeDef adc_common;RCC_TypeDef rcc;GPIO_TypeDef ga,gb,gf;TIM_TypeDef timer,timer2;SPI_TypeDef spi;host_systick_type systick;unsigned host_systick_config_calls;
static jmp_buf returned;
static unsigned resets,wfi_calls;
void host_wait(void){if(++wfi_calls==1){timer2.CNT+=1000;SysTick_Handler();return;}longjmp(returned,1);}
static void pins(GPIO_TypeDef *p){p->ODR=(p->ODR|(p->BSRR&65535u))&~(p->BSRR>>16);p->IDR=p->ODR;p->BSRR=0;}
void host_dsb(void){if(timer.EGR&TIM_EGR_UG){timer.CNT=0;timer.EGR=0;}if(adc2.ISR==ADC_ISR_ADRDY || adc2.ISR==(ADC_ISR_EOC|ADC_ISR_EOS|ADC_ISR_EOSMP))adc2.ISR=0;if(adc1.ISR==ADC_ISR_ADRDY || adc1.ISR==(ADC_ISR_EOC|ADC_ISR_EOS|ADC_ISR_EOSMP))adc1.ISR=0;if(rcc.AHB2RSTR&RCC_AHB2RSTR_ADC12RST){memset(&adc1,0,sizeof adc1);memset(&adc2,0,sizeof adc2);memset(&adc_common,0,sizeof adc_common);adc1.CR=adc2.CR=ADC_CR_DEEPPWD;}if(rcc.APB1RSTR1&RCC_APB1RSTR1_TIM2RST)memset(&timer2,0,sizeof timer2);if(rcc.APB1RSTR1&RCC_APB1RSTR1_SPI2RST)memset(&spi,0,sizeof spi);pins(&ga);pins(&gb);pins(&gf);if(rcc.APB2RSTR&RCC_APB2RSTR_TIM1RST){memset(&timer,0,sizeof timer);++resets;}}
static void fixture(void){
 memset(&rcc,0,sizeof rcc);memset(&ga,0,sizeof ga);memset(&gb,0,sizeof gb);memset(&gf,0,sizeof gf);memset(&timer,0,sizeof timer);memset(&timer2,0,sizeof timer2);memset(&spi,0,sizeof spi);memset(&systick,0,sizeof systick);memset(&adc1,0,sizeof adc1);memset(&adc2,0,sizeof adc2);memset(&adc_common,0,sizeof adc_common);
 owned=sampling_owned=timebase_owned=false;state=UNINITIALIZED;drill_config=(dc_runtime){0};drill_adc_state=DA_IDLE;drill_dual_state=DU_IDLE;drill_dual_error=0;host_clock_profile();
 drill_safe_boot();assert(drill_pwm_stage_init());assert(drill_timebase_init());assert(drill_spi_init(0));ga.MODER&=~(3u<<12);ga.ODR|=1u<<6;ga.IDR|=1u<<6;gf.BSRR=2u;host_dsb();drill_config.state=DC_READY;spi.SR=SPI_SR_TXE;
}
static void poll(uint32_t now){timer2.CNT=now;drill_config_service(now);drill_dual_poll(now);}
static void ready(uint32_t n){
 drill_config.last=n;
 assert(drill_dual_bench_begin(n,true));assert(drill_dual_state==DU_REG&&adc1.CR==ADC_CR_ADVREGEN&&adc2.CR==ADC_CR_ADVREGEN);
 assert(adc_common.CCR==0x30006&&adc1.CFGR==0x540&&adc2.CFGR==0&&adc1.SQR1==0x40&&adc2.SQR1==0x80&&adc1.SMPR1==0x10&&adc2.SMPR1==0x80);
 assert(timer.CR2==0x700000&&timer.CCR4==200&&timer.CCER==0&&!(timer.BDTR&TIM_BDTR_MOE)&&!(timer.CR1&TIM_CR1_CEN));
 poll(n+39);assert(drill_dual_state==DU_REG);poll(n+40);assert(drill_dual_state==DU_CAL&&(adc1.CR&ADC_CR_ADCAL)&&(adc2.CR&ADC_CR_ADCAL));
 adc1.CR&=~ADC_CR_ADCAL;poll(n+49);assert(drill_dual_state==DU_CAL);adc2.CR&=~ADC_CR_ADCAL;poll(n+50);assert(drill_dual_state==DU_GAP);poll(n+51);assert(!(adc1.CR&ADC_CR_ADEN));poll(n+52);assert(drill_dual_state==DU_ENABLE);
 adc1.ISR=ADC_ISR_ADRDY;poll(n+53);assert(drill_dual_state==DU_ENABLE);adc2.ISR=ADC_ISR_ADRDY;poll(n+55);assert(drill_dual_state==DU_READY&&drill_spi_available());
}
static void off(void){assert(drill_dual_state==DU_FAILED&&drill_config.state==DC_FAILED&&!sampling_owned);assert(!(rcc.AHB2ENR&RCC_AHB2ENR_ADC12EN));assert(!(gf.ODR&2u));assert(!(ga.ODR&((1u<<5)|(1u<<7)|(7u<<8)))&&!(gb.ODR&3u)&&(ga.ODR&(1u<<12)));assert(timer.CCER==0&&!(timer.CR1&TIM_CR1_CEN)&&!(timer.BDTR&TIM_BDTR_MOE));assert(!drill_dual_bench_begin(10000,true));}
static void data(uint16_t a,uint16_t b,uint32_t start){
 timer.CNT=320;adc1.ISR=ADC_ISR_EOC|ADC_ISR_EOS;adc2.ISR=0;poll(start+20);assert(drill_dual_state==DU_WAIT);adc2.ISR=ADC_ISR_EOC|ADC_ISR_EOS;adc2.CR|=ADC_CR_ADSTART;adc_common.CDR=((uint32_t)b<<16)|a;poll(start+21);assert(drill_dual_state==DU_STOP&&!(timer.CR1&TIM_CR1_CEN)&&(adc1.CR&ADC_CR_ADSTP));
 adc1.CR&=~(ADC_CR_ADSTART|ADC_CR_ADSTP);poll(start+22);assert(drill_dual_state==DU_STOP);adc2.CR&=~ADC_CR_ADSTART;poll(start+23);assert(drill_dual_state==DU_DONE);
}
int main(void){unsigned cases=0;const uint16_t raw[]={0,1,2047,2048,4094,4095};
 for(unsigned wrap=0;wrap<2;++wrap)for(unsigned i=0;i<6;++i)for(unsigned j=0;j<6;++j){fixture();uint32_t n=wrap?UINT32_MAX-100:0;ready(n);
  for(unsigned run=0;run<2;++run){uint32_t start=n+60+100*run;timer2.CNT=start;assert(drill_dual_capture_start(start));assert(timer.CR1&TIM_CR1_CEN);assert(drill_dual_busy()&&drill_spi_available());assert(!drill_dual_capture_start(start));assert(!drill_adc_bench_begin(start,true));
   du_sample out;memset(&out,0xa5,sizeof out);du_sample old=out;assert(!drill_dual_take(&out,start)&&!memcmp(&out,&old,sizeof out));data(raw[i],raw[j],start);assert(!drill_dual_take(NULL,start+23));assert(drill_dual_take(&out,start+23)&&out.ia_raw==raw[i]&&out.ib_raw==raw[j]&&out.armed_us==start&&out.observed_us==start+21&&out.sequence==run+1&&!out.calibration_verified);old=out;assert(!drill_dual_take(&out,start+24)&&!memcmp(&out,&old,sizeof out));assert(timer.CCER==0&&!(timer.BDTR&TIM_BDTR_MOE)&&!(ga.ODR&((1u<<5)|(1u<<7)|(7u<<8)))&&!(gb.ODR&3));
  }++cases;
 }
 /* Configuration pollution of both ADCs and internal trigger timer. */
 for(unsigned which=0;which<2;++which)for(unsigned reg=0;reg<18;++reg)for(unsigned bit=0;bit<32;++bit){fixture();ready(0);ADC_TypeDef *a=which?&adc2:&adc1;volatile uint32_t *regs[]={&a->CR,&a->CFGR,&a->CFGR2,&a->IER,&a->DIFSEL,&a->JSQR,&a->SMPR1,&a->SMPR2,&a->SQR1,&a->SQR2,&a->SQR3,&a->SQR4,&a->OFR1,&a->OFR2,&a->OFR3,&a->OFR4,&a->GCOMP,&adc_common.CCR};*regs[reg]^=1u<<bit;poll(60);off();++cases;}
 for(unsigned reg=0;reg<12;++reg)for(unsigned bit=0;bit<32;++bit){fixture();ready(0);volatile uint32_t *regs[]={&timer.CR1,&timer.CR2,&timer.SMCR,&timer.DIER,&timer.CCER,&timer.BDTR,&timer.PSC,&timer.ARR,&timer.RCR,&timer.CCMR1,&timer.CCMR2,&timer.CCR4};*regs[reg]^=1u<<bit;poll(60);
  /* DIR is hardware direction state; unexpected CEN in READY must be rejected. */
  if(reg==0&&bit==4){assert(drill_dual_state==DU_READY);}else off();++cases;
 }
 for(unsigned which=0;which<2;++which)for(unsigned i=0;i<7;++i){fixture();ready(0);const uint32_t flags[]={ADC_ISR_OVR,ADC_ISR_JQOVF,ADC_ISR_AWD1,ADC_ISR_AWD2,ADC_ISR_AWD3,ADC_ISR_JEOC,ADC_ISR_JEOS};(which?&adc2:&adc1)->ISR|=flags[i];poll(60);off();assert(drill_dual_error==3);++cases;}
 for(unsigned i=0;i<8;++i){fixture();ready(0);assert(drill_dual_capture_start(60));timer.CNT=320;adc1.ISR=adc2.ISR=ADC_ISR_EOC|ADC_ISR_EOS;adc_common.CDR=1u<<(i<4?12+i:24+i);poll(81);off();assert(drill_dual_error==4);++cases;}
 for(unsigned mode=0;mode<10;++mode){fixture();ready(0);assert(drill_dual_capture_start(60));
  if(mode==0)poll(59);if(mode==1)poll(101);if(mode==2){adc1.ISR=ADC_ISR_EOC|ADC_ISR_EOS;poll(80);poll(101);}if(mode==3){adc1.ISR=adc2.ISR=ADC_ISR_EOC;poll(81);}if(mode==4){ga.IDR&=~(1u<<6);poll(61);}if(mode==5){gf.IDR&=~2u;poll(61);}if(mode==6){ga.IDR&=~(1u<<12);poll(61);}if(mode==7){data(1,2,60);du_sample out;assert(!drill_dual_take(&out,182));}if(mode==8){timer.CNT=320;adc1.ISR=adc2.ISR=ADC_ISR_EOC|ADC_ISR_EOS;adc_common.CDR=0x08000800;poll(81);assert(drill_dual_state==DU_STOP);poll(182);}if(mode==9){rcc.CFGR|=RCC_CFGR_HPRE_3;poll(61);}off();++cases;
 }
 for(unsigned mode=0;mode<5;++mode){fixture();TIM_TypeDef old=timer;if(mode==0)assert(!drill_dual_bench_begin(0,false));if(mode==1){rcc.AHB2ENR|=RCC_AHB2ENR_ADC12EN;assert(!drill_dual_bench_begin(0,true));}if(mode==2){drill_adc_state=DA_READY;assert(!drill_dual_bench_begin(0,true));}if(mode==3){drill_config.state=DC_IDLE;assert(!drill_dual_bench_begin(0,true));}if(mode==4){timer.CCR1=200;old=timer;assert(!drill_dual_bench_begin(0,true));}assert(drill_dual_state==DU_IDLE&&!memcmp(&old,&timer,sizeof timer));++cases;}
 printf("%u DUAL ADC / INTERNAL TIM1 SOURCE MODEL SCENARIOS PASS\n",cases);
}
