#include "stm32g0xx.h"
#include "lamp_i2c_read.h"
#include <assert.h>
#include <stdio.h>
#include <string.h>
GPIO_TypeDef b;RCC_TypeDef r;I2C_TypeDef i;static bool pins;
bool lamp_i2c_pins_available(void){return pins;}
static void seed(lamp_i2c_read *s){memset(&i,0,sizeof i);pins=true;i.CR1=I2C_CR1_PE;i.TIMINGR=1;lamp_i2c_read_reset(s);}
static void invisible(lamp_i2c_read *s,uint32_t now){uint8_t v=0xa5;assert(!lamp_i2c_read_get(s,now,&v));assert(v==0xa5);}
static void advance(lamp_i2c_read *s,unsigned stage,uint32_t now){
 if(stage==0){i.ISR=I2C_ISR_TXIS|I2C_ISR_BUSY;lamp_i2c_read_poll(s,now);assert(i.TXDR==s->reg);assert(s->state==LIR_WAIT_TC);}
 if(stage==1){i.ISR=I2C_ISR_TC|I2C_ISR_BUSY;lamp_i2c_read_poll(s,now);assert(s->state==LIR_RX_BYTE);
 assert(i.CR2==(((uint32_t)s->address<<1)|(1u<<16)|I2C_CR2_START|I2C_CR2_RD_WRN|I2C_CR2_AUTOEND));}
 if(stage==2){i.ISR=I2C_ISR_RXNE|I2C_ISR_BUSY;i.RXDR=0x6b;lamp_i2c_read_poll(s,now);assert(s->state==LIR_WAIT_STOP);}
 if(stage==3){i.ISR=I2C_ISR_STOPF;lamp_i2c_read_poll(s,now);assert(s->state==LIR_DONE);assert(i.ICR==I2C_ICR_STOPCF && i.CR2==0);}
}
int main(void){lamp_i2c_read s;unsigned cases=0;uint8_t v;uint8_t addr[]={0x15,0x19,0x65};uint8_t regs[]={1,0x41,0x42,0x43,0x44,0x45,0x46};uint32_t base[]={0,100,0xfffffffeu};
 for(unsigned a=0;a<3;a++)for(unsigned q=0;q<7;q++)for(unsigned k=0;k<3;k++){
 seed(&s);assert(lamp_i2c_read_start(&s,addr[a],regs[q],base[k]));
 assert(i.CR2==(((uint32_t)addr[a]<<1)|(1u<<16)|I2C_CR2_START));
 invisible(&s,base[k]);assert(!lamp_i2c_read_start(&s,addr[a],regs[q],base[k]));
 for(unsigned st=0;st<4;st++){advance(&s,st,base[k]+st+1);if(st<3)invisible(&s,base[k]+st+1);}
 assert(lamp_i2c_read_get(&s,base[k]+4,&v) && v==0x6b);
 assert(!lamp_i2c_read_get(&s,base[k]+10,&v));
 i.ISR=0;assert(lamp_i2c_read_start(&s,addr[a],regs[q],base[k]+5));invisible(&s,base[k]+5);cases++;
 }
 uint32_t errors[]={I2C_ISR_NACKF,I2C_ISR_BERR,I2C_ISR_ARLO,I2C_ISR_OVR,I2C_ISR_TIMEOUT};
 for(unsigned e=0;e<5;e++)for(unsigned st=0;st<4;st++){
 seed(&s);assert(lamp_i2c_read_start(&s,0x15,1,0));for(unsigned z=0;z<st;z++)advance(&s,z,z+1);
 i.ISR=errors[e]|I2C_ISR_BUSY;lamp_i2c_read_poll(&s,st+1);assert(s.state==LIR_FAILED);invisible(&s,st+1);assert((i.CR1&I2C_CR1_PE)==0);
 assert(((i.CR2&I2C_CR2_STOP)!=0)==(e!=2));assert(!lamp_i2c_read_start(&s,0x15,1,st+1));cases++;
 }
 for(unsigned st=0;st<4;st++){
 seed(&s);assert(lamp_i2c_read_start(&s,0x15,1,0));for(unsigned z=0;z<st;z++)advance(&s,z,z+1);
 i.ISR=I2C_ISR_BUSY;lamp_i2c_read_poll(&s,6);assert(s.state==LIR_FAILED);invisible(&s,6);cases++;
 }
 seed(&s);assert(lamp_i2c_read_start(&s,0x15,1,100));lamp_i2c_read_poll(&s,99);assert(s.state==LIR_FAILED);
 for(unsigned st=0;st<3;st++){
 seed(&s);assert(lamp_i2c_read_start(&s,0x15,1,0));for(unsigned z=0;z<st;z++)advance(&s,z,z+1);
 i.ISR=I2C_ISR_STOPF;lamp_i2c_read_poll(&s,st+1);assert(s.state==LIR_FAILED);invisible(&s,st+1);cases++;
 }
 seed(&s);assert(lamp_i2c_read_start(&s,0x15,1,0));advance(&s,0,1);advance(&s,1,2);
 i.ISR=I2C_ISR_RXNE|I2C_ISR_STOPF;i.RXDR=0x55;lamp_i2c_read_poll(&s,3);invisible(&s,3);
 i.ISR=I2C_ISR_STOPF;lamp_i2c_read_poll(&s,4);assert(lamp_i2c_read_get(&s,4,&v)&&v==0x55);
 seed(&s);assert(lamp_i2c_read_start(&s,0x15,1,0));advance(&s,0,1);advance(&s,1,2);advance(&s,2,3);
 i.ISR=I2C_ISR_STOPF|I2C_ISR_BUSY;lamp_i2c_read_poll(&s,4);invisible(&s,4);assert(s.state==LIR_WAIT_STOP);
 i.ISR=I2C_ISR_STOPF;lamp_i2c_read_poll(&s,5);assert(lamp_i2c_read_get(&s,5,&v));
 for(unsigned a=0;a<256;a++)for(unsigned reg=0;reg<256;reg++){
 seed(&s);bool expected=(a==0x15||a==0x19||a==0x65)&&(reg==1||(reg>=0x41&&reg<=0x46));
 assert(lamp_i2c_read_start(&s,a,reg,0)==expected);
 if(!expected)assert(i.CR2==0);cases++;
 }
 for(unsigned bad=0;bad<6;bad++){
 seed(&s);if(bad==0)pins=false;if(bad==1)i.CR1=0;if(bad==2)i.CR1|=I2C_CR1_TXDMAEN;
 if(bad==3)i.TIMINGR=0;if(bad==4)i.ISR=I2C_ISR_BUSY;if(bad==5)i.ISR=I2C_ISR_RXNE;
 assert(!lamp_i2c_read_start(&s,0x15,1,0));assert(i.CR2==0);cases++;
 }
 seed(&s);assert(lamp_i2c_read_start(&s,0x15,1,0));pins=false;lamp_i2c_read_poll(&s,1);assert(s.state==LIR_FAILED);
 seed(&s);assert(lamp_i2c_read_start(&s,0x15,1,0));
 i.ISR=I2C_ISR_ARLO|I2C_ISR_BUSY;lamp_i2c_read_poll(&s,1);
 i.ISR=I2C_ISR_BUSY; /* model hardware ICR clearing ARLO */
 uint32_t oldcr2=i.CR2;lamp_i2c_read_cancel(&s);
 assert(i.CR2==oldcr2 && (i.CR2&I2C_CR2_STOP)==0);invisible(&s,1);
 printf("PASS %u addressed cases plus wrap/backward, all stage errors, timeouts, partial/STOP/BUSY/ownership checks. Register model only.\n",cases);
}
