/* Portable contract tests. Assertions stay enabled even in Release builds. */ #include "set_emu_server.h" #include "set_crc.h" #include #include #include static set_emu_server a,b; static uint16_t banks[4][32*SET_UMP_WORDS],samples[2][16]; static set_wave_state wave[2]; static unsigned starts[2],stops[2]; static int start(void *ctx,const uint16_t *p,size_t n,uint32_t rate) { unsigned *calls=(unsigned *)ctx; assert(p&&n>=2&&rate);++*calls;return 0; } static void stop(void *ctx) { unsigned *calls=(unsigned *)ctx; ++stops[calls==&starts[1]]; } static void init(void) { set_wave_port p; memset(starts,0,sizeof(starts));memset(stops,0,sizeof(stops)); p.context=&starts[0];p.start=start;p.stop=stop;set_wave_init(&wave[0],samples[0],16,&p); p.context=&starts[1];set_wave_init(&wave[1],samples[1],16,&p); assert(!set_emu_server_init(&a,banks[0],banks[1],32,&wave[0],16,1,4,5,1)); assert(!set_emu_server_init(&b,banks[2],banks[3],32,&wave[1],23,2,0,6,0)); } static void write(set_emu_server *s,uint16_t address,uint16_t value) { uint16_t out[2];size_t n=99; assert(!set_regmap_request(&s->map,6,address,value,out,2,&n)); assert(n==2&&out[0]==address&&out[1]==value); } static void select_mode(set_emu_server *s,unsigned mode) { unsigned i;write(s,0x1219,(uint16_t)mode);write(s,0x1218,0xa55a); for(i=0;i<500;++i)set_emu_server_tick(s,0); assert(s->config[3]==mode); } static uint16_t read1(set_emu_server *s,uint16_t address) { uint16_t out;size_t n=99; assert(!set_regmap_request(&s->map,3,address,1,&out,1,&n)); assert(n==1);return out; } static void seal(uint8_t *p,size_t n) { uint16_t crc=set_crc16_modbus(p,n);p[n]=(uint8_t)crc;p[n+1]=(uint8_t)(crc>>8); } static void rtu(uint8_t *p,uint8_t device,uint8_t fn,uint16_t address,uint16_t value) { p[0]=device;p[1]=fn;p[2]=(uint8_t)(address>>8);p[3]=(uint8_t)address; p[4]=(uint8_t)(value>>8);p[5]=(uint8_t)value;seal(p,6); } static void directory_and_relocation(void) { uint16_t out[124];size_t n;set_igbt_emu other; set_regmap map;set_reg_region r[2]={ {0x300,16,SET_EMU_KIND_IGBT,2,0,3,&a.igbt,set_igbt_read,set_igbt_write}, {0x400,16,SET_EMU_KIND_IGBT,2,1,3,&other,set_igbt_read,set_igbt_write}}; init();set_igbt_init(&other); assert(!set_regmap_request(&a.map,3,0,64,out,124,&n)); assert(n==64&&out[0]==0x5345&&out[1]==1&&out[2]==7&&out[5]==124); assert(out[8]==SET_EMU_KIND_UMP&&out[11]==0x1000); assert(!set_regmap_init(&map,r,2)); assert(!set_regmap_request(&map,6,0x307,777,out,2,&n)); assert(a.igbt.delay_ms==777&&other.delay_ms==1); assert(!set_regmap_request(&map,6,0x407,9,out,2,&n)); assert(other.delay_ms==9); assert(set_regmap_request(&map,3,0x30f,2,out,124,&n)==2&&n==0); assert(set_regmap_request(&map,3,0xffff,2,out,124,&n)==2); assert(set_regmap_request(&map,6,0,1,out,124,&n)==2); r[1].base=0x30f;assert(set_regmap_init(&map,r,2)==2&&map.count==0); r[1].base=0xffff;assert(set_regmap_init(&map,r,2)==3); r[1].base=8;assert(set_regmap_init(&map,r,2)==3); r[1].base=0x400;r[1].write=0;assert(set_regmap_init(&map,r,2)==3); } static void capacity_and_frames(void) { uint8_t req[8],reply[256],can[8]={0x14,7,0,9,0x1f,0,7,6}; uint16_t out[124];size_t n;unsigned token,error; init();select_mode(&a,2);rtu(req,16,6,0x1407,123); assert(set_regmap_request(&a.map,6,0x1407,123,out,1,&n)==3&&n==0); assert(set_regmap_request(&a.map,3,0x1400,0,out,124,&n)==3); assert(set_regmap_request(&a.map,3,0x1400,125,out,124,&n)==3); assert(set_regmap_request(&a.map,4,0x1400,1,out,124,&n)==1); assert(!set_emu_server_rtu(&a,req,8,reply,8)); assert(a.igbt.delay_ms==1); assert(!set_emu_server_can(&a,can,8,out,2,&token,&error)); assert(a.igbt.delay_ms==1); req[7]^=1;assert(!set_emu_server_rtu(&a,req,8,reply,256));req[7]^=1; req[0]=17;seal(req,6);assert(!set_emu_server_rtu(&a,req,8,reply,256)); rtu(req,16,6,0x1407,123); assert(set_emu_server_rtu(&a,req,8,reply,256)==8&&!memcmp(reply,req,8)); assert(read1(&a,0x1407)==123&&b.igbt.delay_ms==1); rtu(req,16,6,0x1407,1001); assert(set_emu_server_rtu(&a,req,8,reply,256)==5); assert(reply[1]==0x86&&reply[2]==3&&!set_crc16_modbus(reply,5)); assert(a.igbt.delay_ms==123); assert(set_emu_server_can(&a,can,8,out,124,&token,&error)==2); assert(token==7&&!error&&a.igbt.delay_ms==9&&out[0]==0x1407&&out[1]==9); can[7]=3;can[2]=0;can[3]=1; assert(set_emu_server_can(&a,can,8,out,124,&token,&error)==2&&out[0]==9&&out[1]==0); assert(set_regmap_can_fragment(out,2,0,token,error,reply,8)==8); assert(!memcmp(reply,(const uint8_t[]){0,9,0,0,0x1f,0,7,0},8)); assert(!set_regmap_can_fragment(out,2,1,token,error,reply,8)); can[4]=0;assert(!set_emu_server_can(&a,can,8,out,124,&token,&error)); assert(token==0&&error==0); } static void independent_wave_and_igbt(void) { uint8_t r[8],reply[256],can[8]={0xa0,0,0,42,0x1f,0,9,6}; uint16_t w[124];unsigned token,error; init(); /* Identical addresses on different transports now select the same module. */ rtu(r,16,3,SET_WAVE_BASE,8); assert(set_emu_server_rtu(&a,r,8,reply,256)==21); assert(reply[3]==0x57&&reply[4]==0x47); rtu(r,16,3,SET_EMU_IGBT_BASE,16); assert(set_emu_server_rtu(&a,r,8,reply,256)==37); assert(reply[3]==0x49&&reply[4]==0x47); select_mode(&a,3); write(&a,0x1304,2); assert(set_emu_server_can(&a,can,8,w,124,&token,&error)==2&&!error); write(&a,0xa001,4095);write(&a,0x1306,0xa55a); rtu(r,16,6,0x1302,1);assert(set_emu_server_rtu(&a,r,8,reply,256)==8); assert(starts[0]==1&&starts[1]==0&&wave[0].running&&!wave[1].running); assert(read1(&a,0xa000)==42); rtu(r,16,6,0xa000,1);assert(set_emu_server_rtu(&a,r,8,reply,256)==5&&reply[2]==6); rtu(r,16,6,0x1402,1); assert(set_emu_server_rtu(&a,r,8,reply,256)==5&&reply[2]==6); assert(wave[0].running&&!a.igbt.enabled); select_mode(&a,2); assert(stops[0]==2&&!wave[0].running&&!wave[0].ready&&!a.igbt.enabled); write(&a,0x1407,500);assert(a.igbt.delay_ms==500); write(&a,0x1402,1);write(&a,0x1411,2); assert(a.igbt.rx==1); select_mode(&a,3); assert(!a.igbt.rx&&!a.igbt.enabled&&!wave[0].running); rtu(r,16,6,0x1302,1); assert(set_emu_server_rtu(&a,r,8,reply,256)==5&&reply[2]==3); /* needs fresh upload */ } static void igbt_timing(void) { unsigned i; init();select_mode(&a,2);write(&a,0x1402,1); write(&a,0x1407,300);write(&a,0x1408,3); set_igbt_tick(&a.igbt,255);assert(!a.igbt.rx&&a.igbt.event_count==8); for(i=0;i<299;++i)set_igbt_tick(&a.igbt,255); assert(!a.igbt.rx); set_igbt_tick(&a.igbt,255);assert(a.igbt.rx==255); set_igbt_tick(&a.igbt,255);set_igbt_tick(&a.igbt,255);assert(a.igbt.rx==255); set_igbt_tick(&a.igbt,255);assert(!a.igbt.rx); write(&a,0x1407,1);write(&a,0x1406,5); set_igbt_tick(&a.igbt,0);set_igbt_tick(&a.igbt,0);assert(a.igbt.rx==255); write(&a,0x1406,0);assert(a.igbt.rx==250); /* Preserve normal ACKs. */ set_igbt_tick(&a.igbt,0);set_igbt_tick(&a.igbt,0);set_igbt_tick(&a.igbt,0); assert(!a.igbt.rx); write(&a,0x1403,128);write(&a,0x140c,1); set_igbt_tick(&a.igbt,0);set_igbt_tick(&a.igbt,0);assert(a.igbt.rx==128); assert(read1(&a,0x1403)==128); write(&a,0x1402,0);assert(!a.igbt.rx); for(i=0;i<1000;++i)set_igbt_tick(&a.igbt,255); assert(!a.igbt.rx&&!b.igbt.rx); } static void tms_shared_state(void) { unsigned i;uint8_t req[18]={1,65},reply[256];uint16_t words[124];size_t n; init(); assert(set_regmap_request(&a.map,6,0x1512,1,words,124,&n)==6); write(&a,0x1219,1);write(&a,0x1218,0xa55a); for(i=0;i<500;++i)set_emu_server_tick(&a,0); write(&a,0x1508,5000);write(&a,0x150c,0x41);write(&a,0x150e,4);write(&a,0x1512,1); for(i=0;i<1000;++i)set_emu_server_tick(&a,0); assert(read1(&a,0x152e)==1000&&b.tms.frequency==0); req[10]=0x41;seal(req,16); /* Leave target latched, no Setspeed. */ assert(set_emu_server_rtu(&a,req,18,reply,256)==101); assert(reply[30]==0xe8&&reply[31]==3&&!set_crc16_modbus(reply,100)); req[10]=0x40;seal(req,16); assert(set_emu_server_rtu(&a,req,18,reply,256)==101&&!read1(&a,0x1502)); assert(!set_regmap_request(&a.map,3,0x1400,16,words,124,&n)); /* Both register and CAN writes reject inactive executors. */ assert(set_regmap_request(&a.map,6,0x1402,1,words,124,&n)==6); assert(set_regmap_request(&a.map,6,0x1302,1,words,124,&n)==6); set_emu_server_tick(&a,255);assert(!a.igbt.rx); select_mode(&a,2);assert(!a.tms.frequency&&!a.igbt.enabled); } static void stream_and_custom_composition(void) { set_emu_stream stream={0};uint8_t req[8],reply[256];size_t n=0;unsigned i; set_emu_server no_wave;uint16_t out[124];size_t count; init();select_mode(&a,2);rtu(req,16,6,0x1407,19); for(i=0;i<8;++i)n=set_emu_stream_feed(&stream,&a,req[i],i*20,reply,256); assert(n==8&&a.igbt.delay_ms==19&&b.igbt.delay_ms==1); assert(!set_emu_server_init(&no_wave,banks[2],banks[3],32,0,16,1,4,5,1)); assert(no_wave.map.count==5); assert(set_regmap_request(&no_wave.map,3,0x1300,8,out,124,&count)==2); assert(!set_regmap_request(&no_wave.map,3,0x1400,16,out,124,&count)); assert(set_emu_server_init(&no_wave,banks[2],banks[3],820,0,16,1,4,5,1)==3); } static void all_mode_pairs(void) { unsigned from,to,i,error,token;uint16_t out[124];size_t n; uint8_t can[8]={0x14,2,0,1,0x1f,0,7,6}; for(from=0;from<4;++from)for(to=0;to<4;++to) { init();select_mode(&a,from); if(from==3) { write(&a,0x1304,2);write(&a,0xa000,1);write(&a,0xa001,4095); write(&a,0x1306,0xa55a);write(&a,0x1302,1); } else if(from==2) { write(&a,0x1402,1);write(&a,0x1411,2);assert(a.igbt.rx==1); } else if(from==0)write(&a,0x1000,1); write(&a,0x1219,(uint16_t)to);write(&a,0x1218,0xa55a); for(i=0;i<499;++i)set_emu_server_tick(&a,255); assert(a.config[3]==from); set_emu_server_tick(&a,255);assert(a.config[3]==to); if(from!=to) { assert(!wave[0].running&&!wave[0].ready&&!a.igbt.rx&&!a.igbt.enabled); assert(!a.tms.frequency&&a.ump.state==3); } else if(from==3)assert(wave[0].running); /* a read/apply must not restart output */ if(to!=3)assert(set_regmap_request(&a.map,6,0x1302,1,out,124,&n)==6); if(to!=1)assert(set_regmap_request(&a.map,6,0x1512,1,out,124,&n)==6); if(to!=2) { (void)set_emu_server_can(&a,can,8,out,124,&token,&error); assert(error==6&&!a.igbt.enabled); } } } int main(void) { all_mode_pairs();directory_and_relocation();capacity_and_frames();independent_wave_and_igbt(); igbt_timing();tms_shared_state();stream_and_custom_composition(); puts("emulator services: directory, bounds, relocation, instances, RTU/CAN/stream, wave/TMS/IGBT OK"); return 0; }