#include "stm32g0xx.h"
#include "lamp_output_pins.h"
#include <assert.h>
#include <stdio.h>
#include <string.h>
GPIO_TypeDef a,b,c;SYSCFG_TypeDef s;RCC_TypeDef r;
static void seed(void){
 memset(&a,0,sizeof a);memset(&b,0,sizeof b);memset(&c,0,sizeof c);memset(&s,0,sizeof s);memset(&r,0,sizeof r);
 a.MODER=(1u<<8)|(1u<<14)|(1u<<18)|(1u<<22);b.MODER=1u<<18;c.MODER=3u<<28;
 a.ODR=0xa000;b.ODR=0x3000;r.IOPENR=0x20;r.APBENR2=0x200;r.BDCR=0;
}
static void effect(void){
 uint32_t v=a.BSRR;a.ODR=(a.ODR|(v&0xffffu))&~(v>>16);a.IDR=a.ODR;a.BSRR=0;
 v=b.BSRR;b.ODR=(b.ODR|(v&0xffffu))&~(v>>16);b.IDR=b.ODR;b.BSRR=0;
}
static void off(void){
 uint32_t am=a.MODER,bm=b.MODER,cm=c.MODER,ot=a.OTYPER,bo=b.OTYPER,pu=a.PUPDR,cp=c.PUPDR,lock=a.LCKR,map=s.CFGR1,bdcr=r.BDCR;
 uint32_t aother=a.ODR&~((1u<<4)|(1u<<7)|(1u<<9)|(1u<<11)),bother=b.ODR&~(1u<<9);
 lamp_output_pins_request_off();
 assert(a.BSRR==((1u<<7)|(1u<<20)|(1u<<25)|(1u<<27)));assert(b.BSRR==1u<<25);
 assert(a.MODER==am && b.MODER==bm && c.MODER==cm && a.OTYPER==ot && b.OTYPER==bo);
 assert(a.PUPDR==pu && c.PUPDR==cp && a.LCKR==lock && s.CFGR1==map && r.BDCR==bdcr);
 effect();assert((a.ODR&~((1u<<4)|(1u<<7)|(1u<<9)|(1u<<11)))==aother);assert((b.ODR&~(1u<<9))==bother);
}
int main(void){
 unsigned cases=0;
 for(unsigned clocks=0;clocks<8;clocks++)for(unsigned remap=0;remap<2;remap++)for(unsigned latches=0;latches<32;latches++){
  seed();r.IOPENR|=clocks;s.CFGR1=remap?SYSCFG_CFGR1_PA11_RMP:0;
  unsigned pins[4]={4,7,9,11};for(unsigned j=0;j<4;j++)if(latches&(1u<<j))a.ODR|=1u<<pins[j];
  if(latches&16)b.ODR|=1u<<9;off();assert(lamp_output_pins_read_off()==LAMP_OFF_ALL);cases++;
 }
 for(unsigned pin_index=0;pin_index<4;pin_index++)for(unsigned mode=0;mode<4;mode++){
  seed();unsigned pins[4]={4,7,11,9};unsigned n=pins[pin_index];GPIO_TypeDef *port=pin_index==3?&b:&a;
  port->MODER=(port->MODER&~(3u<<(n*2u)))|(mode<<(n*2u));off();
  unsigned flag=1u<<pin_index;assert((lamp_output_pins_read_off()&flag)==(mode==1?flag:0));cases++;
 }
 for(unsigned pin_index=0;pin_index<4;pin_index++){
  seed();unsigned pins[4]={4,7,11,9};unsigned n=pins[pin_index];GPIO_TypeDef *port=pin_index==3?&b:&a;
  port->OTYPER|=1u<<n;off();assert(!(lamp_output_pins_read_off()&(1u<<pin_index)));cases++;
  seed();off();port->IDR^=1u<<n;assert(!(lamp_output_pins_read_off()&(1u<<pin_index)));cases++;
 }
 uint32_t osc[3]={RCC_BDCR_LSEON,RCC_BDCR_LSERDY,RCC_BDCR_LSEBYP};
 for(unsigned j=0;j<3;j++){seed();r.BDCR=osc[j];off();assert(lamp_output_pins_read_off()==7u);cases++;}
 seed();c.MODER=1u<<28;off();assert(lamp_output_pins_read_off()==7u);cases++;
 seed();c.PUPDR=1u<<28;off();assert(lamp_output_pins_read_off()==7u);cases++;
 seed();s.CFGR1=SYSCFG_CFGR1_PA11_RMP;a.MODER&=~(3u<<18);off();assert(lamp_output_pins_read_off()==11u);cases++;
 seed();off();r.IOPENR&=~RCC_IOPENR_GPIOAEN;assert(lamp_output_pins_read_off()==8u);cases++;
 seed();off();r.IOPENR&=~RCC_IOPENR_GPIOBEN;assert(lamp_output_pins_read_off()==7u);cases++;
 seed();off();r.APBENR2&=~RCC_APBENR2_SYSCFGEN;assert(lamp_output_pins_read_off()==11u);cases++;
 seed();off();a.LCKR=0x10090;off();assert(a.LCKR==0x10090 && lamp_output_pins_read_off()==15u);cases++;
 printf("PASS %u off-only GPIO cases: latch/clock/remap combinations, mode, open-drain, pad mismatch, oscillator conflict, unrelated-field preservation; model only\n",cases);
}
