#include "stm32g0xx.h"
#include "lamp_i2c_clock.h"
#include "lamp_i2c_read.h"
#include <assert.h>
#include <string.h>
#include <stdio.h>
GPIO_TypeDef b; RCC_TypeDef r; I2C_TypeDef i; static bool pins;
bool lamp_i2c_pins_available(void){return pins;}
static void seed(void){memset(&b,0,sizeof b);memset(&r,0,sizeof r);memset(&i,0,sizeof i);pins=true;b.IDR=(1u<<6)|(1u<<7);r.CR=RCC_CR_HSION|RCC_CR_HSIRDY;r.APBENR1=RCC_APBENR1_I2C1EN;r.CCIPR=0xc0300001u;}
static void corrupt(unsigned n){
 switch(n){case 0:pins=false;break;case 1:r.APBENR1=0;break;case 2:r.CR&=~RCC_CR_HSION;break;case 3:r.CR&=~RCC_CR_HSIRDY;break;
 case 4:b.IDR&=~(1u<<6);break;case 5:b.IDR&=~(1u<<7);break;case 6:i.CR1=I2C_CR1_PE;break;case 7:i.CR1=I2C_CR1_ANFOFF;break;case 8:i.CR2=I2C_CR2_START;break;case 9:i.OAR1=1;break;case 10:i.OAR2=1;break;case 11:i.TIMEOUTR=1;break;
 case 12:i.ISR=I2C_ISR_BUSY;break;case 13:i.ISR=I2C_ISR_RXNE;break;case 14:i.ISR=I2C_ISR_TC;break;case 15:i.ISR=I2C_ISR_TCR;break;case 16:i.ISR=I2C_ISR_STOPF;break;case 17:i.ISR=I2C_ISR_NACKF;break;case 18:i.ISR=I2C_ISR_BERR;break;case 19:i.ISR=I2C_ISR_ARLO;break;case 20:i.ISR=I2C_ISR_OVR;break;case 21:i.ISR=I2C_ISR_TIMEOUT;break;}
}
int main(void){unsigned cases=0;
 for(unsigned n=0;n<22;n++){seed();corrupt(n);RCC_TypeDef rr=r;I2C_TypeDef ii=i;GPIO_TypeDef bb=b;assert(!lamp_i2c_clock_init());assert(!lamp_i2c_clock_available());assert(!memcmp(&rr,&r,sizeof r)&&!memcmp(&ii,&i,sizeof i)&&!memcmp(&bb,&b,sizeof b));cases++;}
 for(unsigned n=0;n<8;n++){seed();r.CR|=n<<RCC_CR_HSIDIV_Pos;uint32_t old=r.CCIPR;assert(lamp_i2c_clock_init());assert((r.CCIPR&~RCC_CCIPR_I2C1SEL)==(old&~RCC_CCIPR_I2C1SEL));assert(lamp_i2c_clock_available());assert(i.CR2==0&&i.TXDR==0&&i.CR1==I2C_CR1_PE);cases++;}
 for(unsigned n=0;n<15;n++){seed();assert(lamp_i2c_clock_init());
 switch(n){case 0:pins=false;break;case 1:r.APBENR1=0;break;case 2:r.CR&=~RCC_CR_HSION;break;case 3:r.CR&=~RCC_CR_HSIRDY;break;case 4:r.CCIPR&=~RCC_CCIPR_I2C1SEL;break;case 5:r.CCIPR=(r.CCIPR&~RCC_CCIPR_I2C1SEL)|(1u<<12);break;case 6:r.CCIPR|=RCC_CCIPR_I2C1SEL;break;case 7:i.TIMINGR^=1;break;case 8:i.CR1=0;break;case 9:i.CR1|=I2C_CR1_ANFOFF;break;case 10:i.CR1|=I2C_CR1_DNF;break;case 11:i.CR1|=I2C_CR1_TXDMAEN;break;case 12:i.OAR1=1;break;case 13:i.OAR2=1;break;case 14:i.TIMEOUTR=1;break;}
 assert(!lamp_i2c_clock_available());cases++;}
 for(unsigned n=0;n<5;n++){seed();assert(lamp_i2c_clock_init());lamp_i2c_read q;lamp_i2c_read_reset(&q);assert(lamp_i2c_read_start(&q,0x15,1,0));i.ISR=I2C_ISR_BUSY;
 if(n==0)r.CR&=~RCC_CR_HSIRDY;if(n==1)r.CCIPR&=~RCC_CCIPR_I2C1SEL;if(n==2)i.TIMINGR^=1;if(n==3)i.CR1|=I2C_CR1_ANFOFF;if(n==4)i.OAR1=1;
 lamp_i2c_read_poll(&q,1);uint8_t v=0xa5;assert(q.state==LIR_FAILED&&!(i.CR1&I2C_CR1_PE));assert(!lamp_i2c_read_get(&q,1,&v)&&v==0xa5);cases++;}
 printf("PASS %u owner initialization, nonmutation, mux preservation, runtime corruption and real-reader abort cases; register model only.\n",cases);
}
