234 lines
11 KiB
C
234 lines
11 KiB
C
/* Portable contract tests. Assertions stay enabled even in Release builds. */
|
|
#include "set_emu_server.h"
|
|
#include "set_crc.h"
|
|
#include <assert.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
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;
|
|
}
|