int simlog_full;
const char *simulate;
-static SimEventFn se_timestamp, se_timerevent;
-static SimEventFn se_serial, se_samedet, se_command, se_eof;
+static SimEventFn se_timestamp, se_timerevent, se_command;
+static SimEventFn se_serial, se_serial_detcompr, se_samedet, se_eof;
static SimTimeout *simtimeouts;
+#define DETSAVESLN2 4
+#define DETSAVES (1<<DETSAVESLN2) /* encoded in letters so must be <=26 ! */
+
static FILE *simoutput;
static FILE *siminput;
static char *sevent_buf;
static size_t sevent_buflen;
static int sevent_lno;
-static Byte sevent_lastdet[2];
+static Byte sevent_lastdet[DETSAVES][2];
static SimEventFn *sevent_type;
static char *sevent_data;
/*---------- writing simulation log ----------*/
-static Byte simlog_lastdet[2];
+static Byte simlog_lastdet[DETSAVES][2];
+static uint32_t simlog_detcompr_lcongx;
void simlogv(const char *fmt, va_list al) {
if (simoutput==stdout) ovprintf(UPO,fmt,al);
else if (simoutput) vfprintf(simoutput,fmt,al);
- simlog_lastdet[0]= 0;
}
void simlog(const char *fmt, ...) {
va_list al;
if (ferror(simoutput) || fflush(simoutput))
diee("write simulation log");
}
+
void simlog_serial(const Byte *data, int length) {
static Byte db0, db1;
int is_det;
db0= data[0] & ~PICMSG_DETECT_01;
- /* optimise consecutive dithering detects into just 0 and 1 msgs */
is_det= PICMSG_DETECT0_P(db0) && length==2 && !((db1=data[1]) & 0x80);
if (is_det) {
- if (db0==simlog_lastdet[0] && data[1]==simlog_lastdet[1]) {
- simlog("%d\n",!!(data[0] & PICMSG_DETECT_01));
- goto set_lastdet;
- }
- simlog("picioh in suppressed-detect");
+ int i;
+ for (i=0; i<DETSAVES; i++)
+ if (simlog_lastdet[i][0]==db0 && simlog_lastdet[i][1]==db1) {
+ simlog("%c\n", ((data[0] & PICMSG_DETECT_01) ? 'A' : 'a') + i);
+ simlog_flush();
+ return;
+ }
+ /* not found, choose a slot to replace */
+ simlog_detcompr_lcongx += 5; /* WP Linear_congruential_generator */
+ simlog_detcompr_lcongx *= 69069; /* values are those also used by GCC */
+ i= (simlog_detcompr_lcongx >> (30 - DETSAVESLN2)) &
+ ((1UL << DETSAVESLN2)-1);
+ simlog_lastdet[i][0]= db0;
+ simlog_lastdet[i][1]= db1;
+ simlog("picioh in detcompr%c", 'A' + i);
} else {
simlog("picioh in suppressed");
}
-
while (length--) simlog(" %02x",*data++);
simlog("\n");
simlog_flush();
-
- set_lastdet:
- if (is_det) {
- simlog_lastdet[0]= db0;
- simlog_lastdet[1]= db1;
- }
}
void simlog_open(const char *fn) {
if (!fn) fn= "+realtime.log";
assert(sevent_buf[gr-1]=='\n');
sevent_buf[gr-1]= 0;
- if ((sevent_buf[0] & ~1)=='0' && !sevent_buf[1]) {
+ if (gr==2 && CTYPE(isalpha,sevent_buf[0])) {
sevent_type= se_samedet;
sevent_data= &sevent_buf[0];
return;
}
#define IF_ET(pfx, et) \
- if (!strncmp(pfx " ", sevent_buf, sizeof(pfx)) \
- && (sevent_type=(et), p=sevent_buf+(sizeof(pfx))))
+ if (!strncmp(pfx, sevent_buf, sizeof(pfx)-1) \
+ && (sevent_type=(et), p=sevent_buf+sizeof(pfx)-1))
- IF_ET("command-in", se_command) {
+ IF_ET("command-in ", se_command) {
sevent_data= p;
return;
}
- IF_ET("picioh in", se_serial) {
+ IF_ET("picioh in detcompr", se_serial_detcompr) {
+ sevent_data= p;
+ return;
+ }
+ IF_ET("picioh in ", se_serial) {
p= strchr(p,' ');
if (!p) simbad("missing space after `in'");
sevent_data= p+1;
return;
}
- IF_ET("timer-event", se_timerevent) {
+ IF_ET("timer-event ", se_timerevent) {
sevent_data= p;
return;
}
- IF_ET("timestamp", se_timestamp) {
+ IF_ET("timestamp ", se_timestamp) {
int n, r;
n=-1;
r= sscanf(p,"%ld.%ld%n", &sevent_abst.tv_sec, &sevent_abst.tv_usec, &n);
toev_callback(0, sevent_abst, toev);
}
-static void se_serial(void) {
- int buf_used;
+static int unhex(const char *str, Byte *buf, int buf_len) {
char c[3], *ep;
+ int buf_used;
const char *p;
c[2]= 0;
- for (p=sevent_data, buf_used=serial_buf.l;
+ for (p=str, buf_used=0;
;
) {
if (*p==' ') p++;
if (!(c[0]= *p++)) break;
if (!(c[1]= *p++)) simbad("odd number of hex digits");
- if (buf_used==sizeof(serial_buf.d)) simbad("serial_buf overrun");
+ if (buf_used==buf_len) simbad("serial_buf overrun");
- serial_buf.d[buf_used++]= strtoul(c,&ep,16);
+ buf[buf_used++]= strtoul(c,&ep,16);
if (*ep) simbad("bad hex");
}
- if (buf_used>=2) {
- Byte db0= serial_buf.d[buf_used-2] & ~PICMSG_DETECT_01;
- if (PICMSG_DETECT0_P(db0)) {
- sevent_lastdet[0]= db0;
- sevent_lastdet[1]= serial_buf.d[buf_used-1];
- }
- }
- serial_indata_process(buf_used);
+ return buf_used;
}
-
-static void se_samedet(void) {
+
+static void se_serial(void) {
int buf_used;
buf_used= serial_buf.l;
- if (buf_used >= sizeof(serial_buf.d)-1) simbad("samedet serial_buf overrun");
- if (!sevent_lastdet[0]) simbad("samedet but no previous det");
- if (sevent_lastdet[1] & 0x80) simbad("samedet but bad previous det");
- serial_buf.d[buf_used++]= sevent_lastdet[0] |
- (sevent_data[0]=='1' ? PICMSG_DETECT_01 : 0);
- serial_buf.d[buf_used++]= sevent_lastdet[1];
+ buf_used += unhex(sevent_data, serial_buf.d + buf_used,
+ sizeof(serial_buf.d) - buf_used);
+ serial_indata_process(buf_used);
+}
+
+static void serial_detevent(Byte m[2], Byte or_m0) {
+ int buf_used;
+ buf_used= serial_buf.l+2;
+ if (buf_used > sizeof(serial_buf.d)) simbad("serial_buf det overrun");
+ serial_buf.d[serial_buf.l]= m[0] | or_m0;
+ serial_buf.d[serial_buf.l+1]= m[1];
serial_indata_process(buf_used);
}
+static void se_serial_detcompr(void) {
+ int i, l;
+
+ i= *sevent_data++ - 'A';
+ if (i<0 || i>=DETSAVES) simbad("detcompr bad slot specifier");
+ l= unhex(sevent_data, sevent_lastdet[i], 2);
+ if (l!=2) simbad("detcompr wrong message length");
+ serial_detevent(sevent_lastdet[i],0);
+ sevent_lastdet[i][0] &= ~PICMSG_DETECT_01;
+}
+static void se_samedet(void) {
+ int i, d;
+ i= *sevent_data - 'a';
+ d= *sevent_data < 'a'; /* A is before a */
+ if (d) i -= 'A'-'a';
+ if (i<0 || i>=DETSAVES || !sevent_lastdet[i][0]) simbad("detsame bad slot");
+ serial_detevent(sevent_lastdet[i], d ? PICMSG_DETECT_01 : 0);
+}
+
static void se_command(void) {
ParseState ps;
ps.remain= sevent_data;