#include "stm32g0xx.h"
#include "lamp_i2c_clock.h"
#include "lamp_dark_init.h"
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
GPIO_TypeDef b;RCC_TypeDef r;I2C_TypeDef i;
bool lamp_i2c_pins_available(void){return true;}
static uint32_t base;static unsigned tick;static bool slow;
static uint32_t now(void){return base+tick/20;}
static void poll(uint32_t flags){i.ISR=flags;lamp_dark_init_poll(now());
 if(slow && lamp_dark_init_failed()){assert(now()-base>500u);puts("PASS total 500ms initialization deadline with timely individual transactions");exit(0);}
 tick+=slow?20u:1u;}
int main(int argc,char **argv){
 unsigned scenario=argc>1?(unsigned)atoi(argv[1]):0;int pos=argc>2?atoi(argv[2]):-1;
 slow=scenario==8;
 base=scenario==1?UINT32_MAX-10u:0;
 r.CR=RCC_CR_HSION|RCC_CR_HSIRDY;r.APBENR1=RCC_APBENR1_I2C1EN;b.IDR=(1u<<6)|(1u<<7);assert(lamp_i2c_clock_init());
 assert(lamp_dark_init_begin(base));poll(0);
 for(unsigned n=0;n<174;n++){
  unsigned reg=n%58;uint8_t addresses[]={0x15,0x19,0x65};
  assert((i.CR2&I2C_CR2_SADD)==((unsigned)addresses[n/58]<<1));
  assert((i.CR2&I2C_CR2_NBYTES)==2u<<I2C_CR2_NBYTES_Pos);
  if(scenario==2 && n==(unsigned)pos){poll(I2C_ISR_NACKF|I2C_ISR_BUSY);goto failed;}
  poll(I2C_ISR_TXIS|I2C_ISR_BUSY);assert(i.TXDR==reg);
  poll(I2C_ISR_TXIS|I2C_ISR_BUSY);assert(i.TXDR==0);assert(!lamp_dark_init_done());
  poll(I2C_ISR_STOPF);assert(!lamp_dark_init_done());poll(0);
  assert((i.CR2&I2C_CR2_NBYTES)==1u<<I2C_CR2_NBYTES_Pos);
  if(scenario==3 && n==(unsigned)pos){poll(I2C_ISR_NACKF|I2C_ISR_BUSY);goto failed;}
  poll(I2C_ISR_TXIS|I2C_ISR_BUSY);assert(i.TXDR==reg);poll(I2C_ISR_TC|I2C_ISR_BUSY);
  i.RXDR=reg==1?5:0;
  if(scenario==4 && n==(unsigned)pos)i.RXDR^=1;
  if(scenario==6 && n==1)i.RXDR=0; /* reserved MODE2 bits cannot be compared to zero */
  poll(I2C_ISR_RXNE|I2C_ISR_BUSY);poll(I2C_ISR_STOPF);
  if((scenario==4 && n==(unsigned)pos) || (scenario==6 && n==1))goto failed;
  if(n<173){
   if(reg==0){
    uint32_t old=i.CR2;poll(0);assert(i.CR2==old);tick+=40;poll(0);
   }
   if(scenario==5){lamp_dark_init_poll(now()+6);goto failed;}
   poll(0);
  }
 }
 assert(lamp_dark_init_done() && !lamp_dark_init_failed());assert(!lamp_dark_init_begin(now()));
 if(scenario==7){lamp_dark_init_abort();assert(!lamp_dark_init_done() && lamp_dark_init_failed());}
 puts("PASS 174 explicit write/read matches with MODE2 fixed bits and wake waits; model only");return 0;
failed:
 assert(lamp_dark_init_failed() && !lamp_dark_init_done());uint32_t cr2=i.CR2;lamp_dark_init_poll(now()+1);assert(i.CR2==cr2);assert(!lamp_dark_init_begin(now()));return 0;
}
