#include "firmware/固件/drill_target/src/drill_pwm_stage.c"
#include "firmware/固件/drill_target/src/drill_timebase.c"
#include <assert.h>
#include <stdio.h>
#include <string.h>
#include "host_clock_fixture.h"
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 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){pins(&ga);pins(&gb);pins(&gf);if(rcc.APB2RSTR&RCC_APB2RSTR_TIM1RST)memset(&timer,0,sizeof timer);if(rcc.APB1RSTR1&RCC_APB1RSTR1_TIM2RST)memset(&timer2,0,sizeof timer2);}
void host_wait(void){assert(0);}
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,0xff,sizeof timer2);memset(&systick,0,sizeof systick);owned=timebase_owned=false;host_systick_config_calls=0;
 host_clock_profile();rcc.AHB2ENR=RCC_AHB2ENR_GPIOAEN|RCC_AHB2ENR_GPIOBEN|RCC_AHB2ENR_GPIOFEN;
 for(unsigned p=5;p<=10;++p)if(p!=6)ga.MODER|=1u<<(p*2);gb.MODER=5;gf.MODER=4;assert(drill_pwm_stage_init());
}
int main(void){unsigned cases=0;uint32_t out;
 fixture();assert(drill_timebase_init());assert(host_systick_config_calls==1);
 const uint32_t counts[]={0,1,32767,32768,65535,65536,0x7fffffffu,0x80000000u,UINT32_MAX};
 for(unsigned i=0;i<sizeof counts/sizeof counts[0];++i){timer2.CNT=counts[i];out=0;assert(drill_timebase_get(&out)&&out==counts[i]);++cases;}
 for(unsigned reg=0;reg<9;++reg)for(unsigned bit=0;bit<32;++bit){fixture();assert(drill_timebase_init());volatile uint32_t *rs[]={&timer2.CR1,&timer2.CR2,&timer2.SMCR,&timer2.DIER,&timer2.CCER,&timer2.CCMR1,&timer2.CCMR2,&timer2.PSC,&timer2.ARR};*rs[reg]^=1u<<bit;out=0xaabb55aa;assert(!drill_timebase_get(&out)&&out==0xaabb55aa);++cases;}
 for(unsigned bit=0;bit<32;++bit){fixture();assert(drill_timebase_init());systick.CTRL^=1u<<bit;out=0xaabb55aa;assert(drill_timebase_get(&out)==(bit==16));if(bit!=16)assert(out==0xaabb55aa);++cases;}
 for(unsigned bit=0;bit<24;++bit){fixture();assert(drill_timebase_init());systick.LOAD^=1u<<bit;out=123;assert(!drill_timebase_get(&out)&&out==123);++cases;}
 for(unsigned n=0;n<6;++n){fixture();TIM_TypeDef old=timer2;host_systick_type st=systick;
  if(n==0)rcc.APB1ENR1|=RCC_APB1ENR1_TIM2EN;if(n==1)rcc.APB1RSTR1|=RCC_APB1RSTR1_TIM2RST;
  if(n==2)systick.CTRL=1;if(n==3)rcc.CR&=~RCC_CR_HSIRDY;if(n==4)rcc.CFGR|=RCC_CFGR_PPRE1_DIV2;if(n==5)ga.IDR=ga.ODR=1u<<5;
  if(n==2)st=systick;assert(!drill_timebase_init());assert(memcmp(&timer2,&old,sizeof timer2)==0&&memcmp(&systick,&st,sizeof st)==0);++cases;
 }
 fixture();assert(drill_timebase_init());assert(drill_timebase_init()&&host_systick_config_calls==1);++cases;
 timer2.CNT=UINT32_MAX;assert(drill_timebase_get(&out)&&out==UINT32_MAX);timer2.CNT=0;assert(drill_timebase_get(&out)&&out==0);++cases;
 drill_debug_tick_wakeups=UINT32_MAX;SysTick_Handler();assert(drill_debug_tick_wakeups==0);++cases;
 assert(!drill_timebase_get(NULL));++cases;
 printf("%u TIM2/SYSTICK TIMEBASE CASES PASS\n",cases);
}
