summaryrefslogtreecommitdiff
path: root/appl/demo/lego
diff options
context:
space:
mode:
authorCharles.Forsyth <devnull@localhost>2006-12-22 17:07:39 +0000
committerCharles.Forsyth <devnull@localhost>2006-12-22 17:07:39 +0000
commit37da2899f40661e3e9631e497da8dc59b971cbd0 (patch)
treecbc6d4680e347d906f5fa7fca73214418741df72 /appl/demo/lego
parent54bc8ff236ac10b3eaa928fd6bcfc0cdb2ba46ae (diff)
20060303a
Diffstat (limited to 'appl/demo/lego')
-rw-r--r--appl/demo/lego/clockface.b367
-rw-r--r--appl/demo/lego/clockface.disbin0 -> 4676 bytes
-rw-r--r--appl/demo/lego/clockface.sbl998
-rw-r--r--appl/demo/lego/clockreg.sh17
-rw-r--r--appl/demo/lego/firmdl.b294
-rw-r--r--appl/demo/lego/firmdl.disbin0 -> 4423 bytes
-rw-r--r--appl/demo/lego/firmdl.sbl819
-rw-r--r--appl/demo/lego/legolink.b601
-rw-r--r--appl/demo/lego/legolink.disbin0 -> 6591 bytes
-rw-r--r--appl/demo/lego/legolink.sbl1298
-rw-r--r--appl/demo/lego/mkfile36
-rw-r--r--appl/demo/lego/rcxsend.b240
-rw-r--r--appl/demo/lego/rcxsend.disbin0 -> 3000 bytes
-rw-r--r--appl/demo/lego/rcxsend.m4
-rw-r--r--appl/demo/lego/rcxsend.sbl552
-rwxr-xr-xappl/demo/lego/styx.srec329
-rw-r--r--appl/demo/lego/timers.b263
-rw-r--r--appl/demo/lego/timers.disbin0 -> 1645 bytes
-rw-r--r--appl/demo/lego/timers.m15
-rw-r--r--appl/demo/lego/timers.sbl441
20 files changed, 6274 insertions, 0 deletions
diff --git a/appl/demo/lego/clockface.b b/appl/demo/lego/clockface.b
new file mode 100644
index 00000000..1f2aa105
--- /dev/null
+++ b/appl/demo/lego/clockface.b
@@ -0,0 +1,367 @@
+# Model 1
+implement Clockface;
+
+include "sys.m";
+include "draw.m";
+
+Clockface : module {
+ init : fn (ctxt : ref Draw->Context, argv : list of string);
+};
+
+sys : Sys;
+
+hmpath : con "motor/0"; # hour-hand motor
+mmpath : con "motor/2"; # minute-hand motor
+allmpath : con "motor/012"; # all motors (for stopall msg)
+
+hbpath : con "sensor/0"; # hour-hand sensor
+mbpath : con "sensor/2"; # minute-hand sensor
+lspath: con "sensor/1"; # light sensor;
+
+ONTHRESH : con 780; # light sensor thresholds
+OFFTHRESH : con 740;
+NCLICKS : con 120;
+MINCLICKS : con 2; # min number of clicks required to stop a motor
+
+Hand : adt {
+ motor : ref Sys->FD;
+ sensor : ref Sys->FD;
+ fwd : array of byte;
+ rev : array of byte;
+ stop : array of byte;
+ pos : int;
+};
+
+lightsensor : ref Sys->FD;
+allmotors : ref Sys->FD;
+hourhand : ref Hand;
+minutehand : ref Hand;
+
+reqch: chan of (string, chan of int);
+
+init(nil : ref Draw->Context, argv : list of string)
+{
+ sys = load Sys Sys->PATH;
+ sys->pctl(Sys->NEWPGRP, nil);
+
+ argv = tl argv;
+ if (len argv != 1) {
+ sys->print("usage: lego_dir\n");
+ raise("fail:usage");
+ }
+
+ # set up our control file
+ if (sys->bind("#s", ".", Sys->MBEFORE) == -1) {
+ sys->print("failed to bind srv device: %r\n");
+ return;
+ }
+ f2c := sys->file2chan(".", "clockface");
+ if (f2c == nil) {
+ sys->print("cannot create legolink channel: %r\n");
+ return;
+ }
+
+ legodir := hd argv;
+ if (legodir[len legodir -1] != '/')
+ legodir[len legodir] = '/';
+
+ # get the motor files
+ sys->print("opening motor files\n");
+ hm := sys->open(legodir + hmpath, Sys->OWRITE);
+ mm := sys->open(legodir +mmpath, Sys->OWRITE);
+ allmotors = sys->open(legodir + allmpath, Sys->OWRITE);
+ if (hm == nil || mm == nil || allmotors == nil) {
+ sys->print("cannot open motor files\n");
+ raise("fail:error");
+ }
+
+ # get the sensor files
+ sys->print("opening sensor files\n");
+ hb := sys->open(legodir + hbpath, Sys->ORDWR);
+ mb := sys->open(legodir + mbpath, Sys->ORDWR);
+ lightsensor = sys->open(legodir + lspath, Sys->ORDWR);
+
+ if (hb == nil || mb == nil) {
+ sys->print("cannot open sensor files\n");
+ raise("fail:error");
+ }
+
+ hourhand = ref Hand(hm, hb, array of byte "f7", array of byte "r7", array of byte "s7", 0);
+ minutehand = ref Hand(mm, mb, array of byte "f7", array of byte "r7", array of byte "s7", 0);
+
+ sys->print("setting sensor types\n");
+ setsensortypes(hourhand, minutehand, lightsensor);
+
+ reqch = chan of (string, chan of int);
+ spawn sethands();
+# reqch <-= ("reset", nil);
+ spawn srvlink(f2c);
+}
+
+srvlink(f2c : ref Sys->FileIO)
+{
+ for (;;) alt {
+ (offset, count, fid, rc) := <- f2c.read =>
+ if (rc == nil)
+ continue;
+ if (offset != 0) {
+ rc <-= (nil, nil);
+ continue;
+ }
+ rc <- = (array of byte gettime(), nil);
+
+ (offset, data, fid, wc) := <- f2c.write =>
+ if (wc == nil)
+ continue;
+ if (offset != 0) {
+ wc <-= (0, "bad offset");
+ continue;
+ }
+ spawn settime(wc, string data, len data);
+ }
+}
+
+gettime(): string
+{
+ hpos := hourhand.pos;
+ mpos := minutehand.pos;
+
+ h := 12 * hpos / NCLICKS;
+ m := 60 * mpos / NCLICKS;
+
+ time := "??:??";
+ for (hadj := -1; hadj <= 1; hadj++) {
+ hpos2 := (((h+hadj) * NCLICKS) / 12) + ((m * NCLICKS) / (12 * 60));
+ dhpos := hpos - hpos2;
+ if (dhpos >= -2 && dhpos <= 2) {
+ # allow 2 clicks of imprecision either way
+ time = sys->sprint("%.2d:%.2d", h+hadj, m);
+ break;
+ }
+ }
+ return sys->sprint("%s %d %d", time, hpos*360/NCLICKS, mpos*360/NCLICKS);
+}
+
+settime(wc: Sys->Rwrite, time: string, wn: int)
+{
+ done := chan of int;
+ reqch <-= (time, done);
+ <- done;
+ wc <-= (wn, nil);
+}
+
+str2clicks(s : string) : (int, int)
+{
+ h, m : int = 0;
+ (n, toks) := sys->tokenize(s, ":");
+ if (n > 1) {
+ h = int hd toks;
+ toks = tl toks;
+ n--;
+ }
+ if (n > 0) {
+ m = int hd toks;
+ }
+ h = ((h * NCLICKS) / 12) + ((m * NCLICKS) / (12 * 60));
+ m = (m * NCLICKS)/60;
+ return (h, m);
+}
+
+sethands()
+{
+ for (;;) {
+ (time, rc) := <- reqch;
+ if (time == "reset" || time == "reset\n") {
+ reset();
+ time = "12:00";
+ }
+ (hclk, mclk) := str2clicks(time);
+ for (i := 0; i < 6; i++) {
+ hdelta := clickdistance(hourhand.pos, hclk, NCLICKS);
+ mdelta := clickdistance(minutehand.pos, mclk, NCLICKS);
+ if (hdelta == 0 && mdelta == 0)
+ break;
+ if (hdelta != 0)
+ sethand(hourhand, hdelta);
+ if (mdelta != 0)
+ sethand(minutehand, mdelta);
+ }
+ releaseall();
+ if (rc != nil)
+ rc <- = 1;
+ }
+}
+
+clickdistance(start, stop, mod : int) : int
+{
+ if (start > stop)
+ stop += mod;
+ d := (stop - start) % mod;
+ if (d > mod/2)
+ d -= mod;
+ return d;
+}
+
+setsensortypes(h1, h2 : ref Hand, ls : ref Sys->FD)
+{
+ button := array of byte "b0";
+ light := array of byte "l0";
+
+ sys->seek(h1.sensor, big 0, Sys->SEEKSTART);
+ sys->write(h1.sensor, button, len button);
+ sys->seek(h2.sensor, big 0, Sys->SEEKSTART);
+ sys->write(h2.sensor, button, len button);
+ sys->seek(ls, big 0, Sys->SEEKSTART);
+ sys->write(ls, light, len light);
+}
+
+HOUR_ADJUST : con 1;
+MINUTE_ADJUST : con 3;
+reset()
+{
+ # run the motors until hands are well away from 12 o'clock (below threshold)
+ setsensortypes(hourhand, minutehand, lightsensor);
+ val := readsensor(lightsensor);
+ if (val > OFFTHRESH) {
+ triggered := chan of int;
+ sys->print("wait for hands clear of light sensor\n");
+ spawn lightwait(triggered, lightsensor, 0);
+ forward(minutehand);
+ reverse(hourhand);
+ val = <- triggered;
+ stopall();
+ sys->print("sensor %d\n", val);
+ }
+
+ resethand(hourhand);
+ hourhand.pos += HOUR_ADJUST;
+ resethand(minutehand);
+ minutehand.pos += MINUTE_ADJUST;
+}
+
+sethand(hand : ref Hand, delta : int)
+{
+ triggered := chan of int;
+ dir := 1;
+ if (delta < 0) {
+ dir = -1;
+ delta = -delta;
+ }
+ if (delta > MINCLICKS) {
+ spawn handwait(triggered, hand, delta - MINCLICKS);
+ if (dir > 0)
+ forward(hand);
+ else
+ reverse(hand);
+ <- triggered;
+ stop(hand);
+ hand.pos += dir * readsensor(hand.sensor);
+ } else {
+ startval := readsensor(hand.sensor);
+ if (dir > 0)
+ forward(hand);
+ else
+ reverse(hand);
+ stop(hand);
+ hand.pos += dir * (readsensor(hand.sensor) - startval);
+ }
+ if (hand.pos < 0)
+ hand.pos += NCLICKS;
+ hand.pos %= NCLICKS;
+}
+
+resethand(hand : ref Hand)
+{
+ triggered := chan of int;
+ val : int;
+
+ # run the hand until the light sensor is above threshold
+ sys->print("running hand until light sensor activated\n");
+ spawn lightwait(triggered, lightsensor, 1);
+ forward(hand);
+ val = <- triggered;
+ stop(hand);
+ sys->print("sensor %d\n", val);
+
+ startclick := readsensor(hand.sensor);
+
+ # advance until light sensor drops below threshold
+ sys->print("running hand until light sensor clear\n");
+ spawn lightwait(triggered, lightsensor, 0);
+ forward(hand);
+ val = <- triggered;
+ stop(hand);
+ sys->print("sensor %d\n", val);
+
+ stopclick := readsensor(hand.sensor);
+ nclicks := stopclick - startclick;
+ sys->print("startpos %d, endpos %d (nclicks %d)\n", startclick, stopclick, nclicks);
+
+ hand.pos = nclicks/2;
+}
+
+stop(hand : ref Hand)
+{
+ sys->seek(hand.motor, big 0, Sys->SEEKSTART);
+ sys->write(hand.motor, hand.stop, len hand.stop);
+}
+
+stopall()
+{
+ msg := array of byte "s0s0s0";
+ sys->seek(allmotors, big 0, Sys->SEEKSTART);
+ sys->write(allmotors, msg, len msg);
+}
+
+releaseall()
+{
+ msg := array of byte "F0F0F0";
+ sys->seek(allmotors, big 0, Sys->SEEKSTART);
+ sys->write(allmotors, msg, len msg);
+}
+
+forward(hand : ref Hand)
+{
+ sys->seek(hand.motor, big 0, Sys->SEEKSTART);
+ sys->write(hand.motor, hand.fwd, len hand.fwd);
+}
+
+reverse(hand : ref Hand)
+{
+ sys->seek(hand.motor, big 0, Sys->SEEKSTART);
+ sys->write(hand.motor, hand.rev, len hand.rev);
+}
+
+readsensor(fd : ref Sys->FD) : int
+{
+ buf := array [4] of byte;
+ sys->seek(fd, big 0, Sys->SEEKSTART);
+ n := sys->read(fd, buf, len buf);
+ if (n <= 0)
+ return -1;
+ return int string buf[0:n];
+}
+
+handwait(reply : chan of int, hand : ref Hand, clicks : int)
+{
+ blk := array of byte ("b" + string clicks);
+ sys->seek(hand.sensor, big 0, Sys->SEEKSTART);
+ sys->print("handwait(%s)\n", string blk);
+ if (sys->write(hand.sensor, blk, len blk) != len blk)
+ sys->print("handwait write error: %r\n");
+ reply <- = readsensor(hand.sensor);
+}
+
+lightwait(reply : chan of int, fd : ref Sys->FD, on : int)
+{
+ thresh := "";
+ if (on)
+ thresh = "l>" + string ONTHRESH;
+ else
+ thresh = "l<" + string OFFTHRESH;
+ blk := array of byte (thresh);
+ sys->print("lightwait(%s)\n", string blk);
+ sys->seek(fd, big 0, Sys->SEEKSTART);
+ sys->write(fd, blk, len blk);
+ reply <- = readsensor(fd);
+} \ No newline at end of file
diff --git a/appl/demo/lego/clockface.dis b/appl/demo/lego/clockface.dis
new file mode 100644
index 00000000..27ef856a
--- /dev/null
+++ b/appl/demo/lego/clockface.dis
Binary files differ
diff --git a/appl/demo/lego/clockface.sbl b/appl/demo/lego/clockface.sbl
new file mode 100644
index 00000000..f8e4dfb9
--- /dev/null
+++ b/appl/demo/lego/clockface.sbl
@@ -0,0 +1,998 @@
+limbo .sbl 2.1
+Clockface
+3
+clockface.b
+sys.m
+draw.m
+678
+44.1,25 0
+45.1,29 1
+11,23 1
+25,28 1
+1,29 1
+1,29 1
+47.1,15 2
+48.5,13 3
+5,18 3
+49.2,33 4
+13,32 4
+2,33 4
+2,33 4
+50.2,21 5
+54.5,39 6
+15,19 6
+21,24 6
+26,38 6
+5,39 6
+5,39 6
+5,45 6
+55.2,47 7
+13,46 7
+2,47 7
+2,47 7
+56.2,8 8
+58.1,40 9
+23,26 9
+28,39 9
+1,40 9
+1,40 9
+59.5,15 10
+60.2,52 11
+13,51 11
+2,52 11
+2,52 11
+61.2,8 12
+64.1,19 13
+65.13,24 14
+13,27 14
+5,28 14
+5,35 14
+66.10,21 15
+2,28 15
+69.1,36 16
+12,35 16
+1,36 16
+1,36 16
+70.1,47 17
+17,33 17
+35,46 17
+1,47 17
+1,47 17
+71.1,46 18
+17,32 18
+34,45 18
+1,46 18
+1,46 18
+72.1,55 19
+23,41 19
+43,54 19
+1,55 19
+1,55 19
+73.5,14 20
+18,27 20
+31,47 20
+74.2,41 21
+13,40 21
+2,41 21
+2,41 21
+75.2,21 22
+79.1,37 23
+12,36 23
+1,37 23
+1,37 23
+80.1,46 24
+17,33 24
+35,45 24
+1,46 24
+1,46 24
+81.1,46 25
+17,33 25
+35,45 25
+1,46 25
+1,46 25
+82.1,54 26
+25,41 26
+43,53 26
+1,54 26
+1,54 26
+84.5,14 27
+18,27 27
+85.2,42 28
+13,41 28
+2,42 28
+2,42 28
+86.2,21 29
+89.1,91 30
+21,23 30
+25,27 30
+29,47 30
+49,67 30
+69,87 30
+89,90 30
+1,91 30
+1,91 31
+90.1,93 32
+23,25 32
+27,29 32
+31,49 32
+51,69 32
+71,89 32
+91,92 32
+1,93 32
+1,93 33
+92.1,37 34
+12,36 34
+1,37 34
+1,37 34
+93.1,50 35
+16,24 35
+26,36 35
+38,49 35
+1,50 35
+95.1,38 36
+96.1,17 37
+1,17 37
+98.1,19 38
+15,18 38
+1,19 38
+99.0,1 39
+104.32,40 40
+32,40 40
+113.31,40 40
+31,40 40
+103.10,16 40
+10,16 40
+10,16 40
+10,16 40
+104.29,40 40
+29,40 41
+105.6,15 42
+6,15 43
+6,15 44
+106.3,11 45
+107.6,17 46
+108.11,14 47
+16,19 47
+3,20 47
+3,20 48
+3,20 49
+3,20 50
+3,20 51
+109.3,11 52
+111.25,34 53
+25,34 53
+25,34 53
+11,34 53
+11,34 54
+36,39 53
+2,40 53
+2,40 55
+2,40 56
+2,40 57
+2,40 58
+2,40 40
+113.28,40 40
+28,40 59
+28,40 60
+114.6,15 61
+6,15 62
+6,15 63
+6,15 64
+6,15 65
+115.3,11 66
+116.6,17 67
+117.11,12 68
+14,26 68
+3,27 68
+3,27 69
+3,27 70
+3,27 71
+3,27 72
+3,27 73
+118.3,11 74
+120.2,42 75
+16,18 75
+20,31 75
+33,41 75
+2,42 75
+2,42 76
+2,42 77
+2,42 78
+2,42 79
+2,42 40
+126.1,21 80
+127.1,23 81
+129.6,15 82
+1,25 82
+130.6,15 83
+1,25 83
+132.1,16 84
+133.6,16 85
+18,27 86
+134.13,21 87
+12,32 87
+11,38 87
+42,55 87
+41,68 87
+2,68 87
+135.2,23 88
+136.6,17 89
+21,31 89
+138.3,45 90
+22,33 90
+35,41 90
+43,44 90
+3,45 90
+3,45 90
+139.3,8 91
+133.29,35 92
+29,35 92
+142.8,73 93
+20,30 93
+32,36 93
+38,46 93
+38,54 93
+56,64 93
+56,72 93
+8,73 93
+8,73 93
+1,73 93
+147.1,20 94
+148.12,16 95
+18,22 95
+1,23 95
+1,23 96
+1,23 97
+149.1,8 98
+150.9,11 99
+13,16 99
+1,17 99
+1,17 100
+151.0,1 101
+155.14,15 102
+14,15 102
+156.14,35 103
+28,29 103
+31,34 103
+14,35 103
+14,35 103
+157.5,10 104
+158.10,17 105
+2,17 105
+2,17 106
+159.2,16 107
+160.2,5 108
+162.5,10 109
+163.10,17 110
+2,17 110
+2,17 111
+165.6,19 112
+5,25 112
+29,42 112
+28,55 112
+1,55 112
+166.5,18 113
+1,21 113
+167.9,10 114
+12,13 114
+1,14 114
+173.16,24 115
+174.6,21 116
+25,42 116
+175.3,10 117
+3,10 117
+176.3,17 118
+178.18,34 119
+29,33 119
+18,34 119
+18,34 119
+179.7,13 120
+15,20 121
+180.3,55 122
+27,39 122
+41,45 122
+47,54 122
+3,55 122
+3,55 122
+181.3,57 123
+27,41 123
+43,47 123
+49,56 123
+3,57 123
+3,57 123
+182.7,18 124
+22,33 124
+183.4,9 125
+184.7,18 126
+185.4,29 127
+12,20 127
+22,28 127
+4,29 127
+186.7,18 128
+187.4,31 129
+12,22 129
+24,30 129
+4,31 129
+179.22,25 130
+22,25 130
+189.2,14 131
+2,14 131
+190.6,15 132
+191.3,12 133
+3,12 134
+3,12 135
+3,12 136
+3,12 136
+197.5,17 137
+198.2,13 138
+199.6,20 139
+1,26 139
+200.9,14 140
+5,14 140
+201.2,10 141
+202.8,9 142
+1,9 142
+207.1,29 143
+208.1,28 144
+210.1,44 145
+11,20 145
+22,27 145
+29,43 145
+1,44 145
+1,44 145
+211.1,42 146
+12,21 146
+23,29 146
+31,41 146
+1,42 146
+1,42 146
+212.1,44 147
+11,20 147
+22,27 147
+29,43 147
+1,44 147
+1,44 147
+213.1,42 148
+12,21 148
+23,29 148
+31,41 148
+1,42 148
+1,42 148
+214.1,37 149
+11,13 149
+15,20 149
+22,36 149
+1,37 149
+1,37 149
+215.1,33 150
+12,14 150
+16,21 150
+23,32 150
+1,33 150
+1,33 150
+216.0,1 151
+223.1,50 152
+16,24 152
+26,36 152
+38,49 152
+1,50 152
+224.1,31 153
+19,30 153
+1,31 153
+1,31 153
+225.5,20 154
+226.2,26 155
+227.2,54 156
+13,53 156
+2,54 156
+2,54 156
+228.2,44 157
+18,27 157
+29,40 157
+42,43 157
+2,44 157
+229.2,21 158
+10,20 158
+2,21 158
+230.2,19 159
+10,18 159
+2,19 159
+231.2,20 160
+232.2,11 161
+2,11 161
+233.2,32 162
+13,26 162
+28,31 162
+2,32 162
+2,32 162
+2,32 163
+236.1,20 164
+11,19 164
+1,20 164
+237.1,28 165
+238.1,22 166
+11,21 166
+1,22 166
+239.1,32 167
+240.0,1 168
+244.1,25 169
+245.1,9 170
+246.5,14 171
+247.2,10 172
+248.2,16 173
+250.5,22 174
+251.2,52 175
+17,26 175
+28,32 175
+34,51 175
+2,52 175
+252.6,13 176
+253.3,16 177
+11,15 177
+3,16 177
+3,16 178
+255.3,16 179
+11,15 179
+3,16 179
+256.2,14 180
+257.2,12 181
+7,11 181
+2,12 181
+258.19,42 182
+30,41 182
+19,42 182
+19,42 182
+13,42 182
+1,42 182
+1,42 183
+260.2,37 184
+25,36 184
+2,37 184
+2,37 184
+261.6,13 185
+262.3,16 186
+11,15 186
+3,16 186
+3,16 187
+264.3,16 188
+11,15 188
+3,16 188
+265.2,12 189
+7,11 189
+2,12 189
+266.21,44 190
+32,43 190
+21,44 190
+21,44 190
+20,56 190
+14,56 190
+2,56 190
+268.5,17 191
+269.2,21 192
+270.1,20 193
+271.0,1 194
+275.1,25 195
+279.1,58 196
+12,57 196
+1,58 196
+1,58 196
+280.1,43 197
+17,26 197
+28,39 197
+41,42 197
+1,43 197
+281.1,14 198
+9,13 198
+1,14 198
+282.1,19 199
+283.1,11 200
+6,10 200
+1,11 200
+284.1,31 201
+12,25 201
+27,30 201
+1,31 201
+1,31 201
+286.1,38 202
+26,37 202
+1,38 202
+1,38 202
+289.1,54 203
+12,53 203
+1,54 203
+1,54 203
+290.1,43 204
+17,26 204
+28,39 204
+41,42 204
+1,43 204
+291.1,14 205
+9,13 205
+1,14 205
+292.1,19 206
+293.1,11 207
+6,10 207
+1,11 207
+294.1,31 208
+12,25 208
+27,30 208
+1,31 208
+1,31 208
+296.1,37 209
+25,36 209
+1,37 209
+1,37 209
+297.1,34 210
+298.1,84 211
+12,51 211
+53,63 211
+65,74 211
+76,83 211
+1,84 211
+1,84 211
+300.1,21 212
+301.0,1 213
+305.1,45 214
+11,21 214
+23,28 214
+30,44 214
+1,45 214
+1,45 214
+306.1,49 215
+12,22 215
+24,33 215
+35,48 215
+1,49 215
+1,49 215
+307.0,1 216
+311.1,30 217
+312.1,44 218
+11,20 218
+22,27 218
+29,43 218
+1,44 218
+1,44 218
+313.1,36 219
+12,21 219
+23,26 219
+28,35 219
+1,36 219
+1,36 219
+314.0,1 220
+318.1,30 221
+319.1,44 222
+11,20 222
+22,27 222
+29,43 222
+1,44 222
+1,44 222
+320.1,36 223
+12,21 223
+23,26 223
+28,35 223
+1,36 223
+1,36 223
+321.0,1 224
+325.1,45 225
+11,21 225
+23,28 225
+30,44 225
+1,45 225
+1,45 225
+326.1,47 226
+12,22 226
+24,32 226
+34,46 226
+1,47 226
+1,47 226
+327.0,1 227
+331.1,45 228
+11,21 228
+23,28 228
+30,44 228
+1,45 228
+1,45 228
+332.1,47 229
+12,22 229
+24,32 229
+34,46 229
+1,47 229
+1,47 229
+333.0,1 230
+337.1,25 231
+338.1,37 232
+11,13 232
+15,20 232
+22,36 232
+1,37 232
+1,37 232
+339.1,33 233
+16,18 233
+20,23 233
+25,32 233
+1,33 233
+1,33 233
+340.5,11 234
+341.9,11 235
+2,11 235
+342.19,22 236
+19,27 236
+12,27 236
+8,27 236
+8,27 237
+1,27 236
+347.29,42 238
+22,43 238
+1,43 238
+1,43 239
+348.1,46 240
+11,22 240
+24,29 240
+31,45 240
+1,46 240
+1,46 240
+349.1,41 241
+12,28 241
+30,40 241
+1,41 241
+1,41 241
+350.5,42 242
+16,27 242
+29,32 242
+34,41 242
+5,42 242
+5,42 242
+46,53 242
+5,53 242
+351.1,41 243
+12,40 243
+1,41 243
+1,41 243
+352.12,35 244
+23,34 244
+12,35 244
+12,35 244
+1,35 244
+353.0,1 245
+357.1,13 246
+358.5,7 247
+359.2,33 248
+2,33 249
+361.2,34 250
+362.1,30 251
+363.1,42 252
+12,29 252
+31,41 252
+1,42 252
+1,42 252
+364.1,37 253
+11,13 253
+15,20 253
+22,36 253
+1,37 253
+1,37 253
+365.1,29 254
+12,14 254
+16,19 254
+21,28 254
+1,29 254
+1,29 254
+366.12,26 255
+23,25 255
+12,26 255
+12,26 255
+1,26 255
+367.0,1 256
+16
+aSys->Dir 1:26.1,39.2 64
+11
+0:name:28.2,6 s
+4:uid:29.2,5 s
+8:gid:30.2,5 s
+12:muid:31.2,6 s
+16:qid:32.2,5 @1
+
+32:mode:33.2,6 i
+36:atime:34.2,7 i
+40:mtime:35.2,7 i
+48:length:36.2,8 B
+56:dtype:37.2,7 i
+60:dev:38.2,5 i
+aSys->Qid 11.1,16.2 16
+3
+0:path:13.2,6 B
+8:vers:14.2,6 i
+12:qtype:15.2,7 i
+aDraw->Chans 2:70.1,82.2 4
+1
+0:desc:72.2,6 i
+aDraw->Context 274.1,279.2 12
+3
+0:display:276.2,9 R@4
+
+4:screen:277.2,8 R@8
+
+8:wm:278.2,4 Ct8.2
+0:t0:15,21 s
+4:t1:15,21 Ct8.2
+0:t0:32,38 s
+4:t1:32,38 R@9
+
+
+
+aDraw->Display 201.1,230.2 20
+5
+0:image:203.2,7 R@5
+
+4:white:204.2,7 R@5
+
+8:black:205.2,7 R@5
+
+12:opaque:206.2,8 R@5
+
+16:transparent:207.2,13 R@5
+
+aDraw->Image 142.1,198.2 56
+8
+0:r:146.2,3 @6
+
+16:clipr:147.2,7 @6
+
+32:depth:148.2,7 i
+36:chans:149.2,7 @2
+
+40:repl:150.2,6 i
+44:display:151.2,9 R@4
+
+48:screen:152.2,8 R@8
+
+52:iname:153.2,7 s
+aDraw->Rect 116.1,139.2 16
+2
+0:min:118.2,5 @7
+
+8:max:119.2,5 @7
+
+aDraw->Point 99.1,113.2 8
+2
+0:x:101.2,3 i
+4:y:102.2,3 i
+aDraw->Screen 249.1,263.2 16
+4
+0:id:251.2,4 i
+4:image:252.2,7 R@5
+
+8:fill:253.2,6 R@5
+
+12:display:254.2,9 R@4
+
+aDraw->Wmcontext 282.1,291.2 28
+7
+0:kbd:284.2,5 Ci
+4:ptr:285.2,5 CR@10
+
+8:ctl:286.2,5 Cs
+12:wctl:287.2,6 Cs
+16:images:288.2,8 CR@5
+
+20:connfd:289.2,8 R@11
+
+24:ctxt:290.2,6 R@3
+
+aDraw->Pointer 266.1,271.2 16
+3
+0:buttons:268.2,9 i
+4:xy:269.2,4 @7
+
+12:msec:270.2,6 i
+aSys->FD 1:45.1,48.2 4
+1
+0:fd:47.2,4 i
+aSys->FileIO 65.1,69.2 8
+2
+0:read:67.2,6 Ct16.4
+0:t0:17,20 i
+4:t1:17,20 i
+8:t2:17,20 i
+12:t3:17,20 @13
+
+
+4:write:68.2,7 Ct16.4
+0:t0:18,21 i
+4:t1:18,21 Ab
+8:t2:18,21 i
+12:t3:18,21 @14
+
+
+Ct8.2
+0:t0:63.22,35 Ab
+4:t1:22,35 s
+Ct8.2
+0:t0:64.23,26 i
+4:t1:23,26 s
+aHand 0:26.0,33.1 24
+6
+0:motor:27.1,6 R@11
+
+4:sensor:28.1,7 R@11
+
+8:fwd:29.1,4 Ab
+12:rev:30.1,4 Ab
+16:stop:31.1,5 Ab
+20:pos:32.1,4 i
+19
+0:init
+1
+36:argv:42.30,34 Ls
+6
+40:legodir:64.1,8 s
+44:f2c:58.1,4 R@12
+
+48:hb:80.1,3 R@11
+
+52:hm:70.1,3 R@11
+
+56:mb:81.1,3 R@11
+
+60:mm:71.1,3 R@11
+
+n131:srvlink
+1
+32:f2c:101.8,11 R@12
+
+8
+36:offset:104.2,8 i
+40:count:10,15 i
+44:fid:17,20 i
+48:rc:22,24 @13
+
+52:offset:113.2,8 i
+56:data:10,14 Ab
+60:fid:16,19 i
+64:wc:21,23 @14
+
+n195:gettime
+0
+8
+32:hadj:133.6,10 i
+36:hpos:126.1,5 i
+40:dhpos:135.2,7 i
+44:h:129.1,2 i
+48:m:130.1,2 i
+52:mpos:127.1,5 i
+56:time:132.1,5 s
+60:hpos2:134.2,7 i
+s232:settime
+3
+32:wc:145.8,10 @14
+
+36:time:25,29 s
+40:wn:39,41 i
+1
+44:done:147.1,5 Ci
+n244:str2clicks
+1
+32:s:153.11,12 s
+4
+36:m:155.4,5 i
+40:h:1,2 i
+44:n:156.2,3 i
+48:toks:5,9 Ls
+t8.2
+0:t0:153.26,29 i
+4:t1:26,29 i
+271:sethands
+0
+7
+32:time:173.3,7 s
+36:rc:9,11 Ci
+40:hdelta:180.3,9 i
+44:mdelta:181.3,9 i
+48:i:179.7,8 i
+52:hclk:178.3,7 i
+56:mclk:9,13 i
+n318:clickdistance
+3
+32:start:195.14,19 i
+36:stop:21,25 i
+40:mod:27,30 i
+1
+44:d:199.1,2 i
+i327:setsensortypes
+3
+32:h1:205.15,17 R@15
+
+36:h2:19,21 R@15
+
+40:ls:34,36 R@11
+
+2
+44:button:207.1,7 Ab
+48:light:208.1,6 Ab
+n366:reset
+0
+2
+32:val:224.1,4 i
+36:triggered:226.2,11 Ci
+n410:sethand
+2
+32:hand:242.8,12 R@15
+
+36:delta:25,30 i
+3
+40:dir:245.1,4 i
+44:triggered:244.1,10 Ci
+48:startval:260.2,10 i
+n466:resethand
+1
+32:hand:273.10,14 R@15
+
+5
+36:triggered:275.1,10 Ci
+40:val:276.1,4 i
+44:nclicks:297.1,8 i
+48:startclick:286.1,11 i
+52:stopclick:296.1,10 i
+n527:stop
+1
+32:hand:303.5,9 R@15
+
+0
+n540:stopall
+0
+1
+32:msg:311.1,4 Ab
+n554:releaseall
+0
+1
+32:msg:318.1,4 Ab
+n568:forward
+1
+32:hand:323.8,12 R@15
+
+0
+n581:reverse
+1
+32:hand:329.8,12 R@15
+
+0
+n594:readsensor
+1
+32:fd:335.11,13 R@11
+
+2
+36:buf:337.1,4 Ab
+40:n:339.1,2 i
+i616:handwait
+3
+32:reply:345.9,14 Ci
+36:hand:30,34 R@15
+
+40:clicks:47,53 i
+1
+44:blk:347.1,4 Ab
+n649:lightwait
+3
+32:reply:355.10,15 Ci
+36:fd:31,33 R@11
+
+40:on:49,51 i
+2
+44:blk:362.1,4 Ab
+48:thresh:357.1,7 s
+n6
+60:allmotors:36.0,9 R@11
+
+116:hourhand:37.0,8 R@15
+
+132:lightsensor:35.0,11 R@11
+
+140:minutehand:38.0,10 R@15
+
+172:reqch:40.0,5 Ct8.2
+0:t0:16,22 s
+4:t1:16,22 Ci
+
+224:sys:11.0,3 mSys
+1:4.0,160.1 0
+
diff --git a/appl/demo/lego/clockreg.sh b/appl/demo/lego/clockreg.sh
new file mode 100644
index 00000000..9c0c6447
--- /dev/null
+++ b/appl/demo/lego/clockreg.sh
@@ -0,0 +1,17 @@
+#!/dis/sh.dis
+load std
+
+port=$1
+DIR=/dis/demo/lego
+pctl forkns newpgrp
+
+cd $DIR
+if { firmdl $port /dis/demo/lego/styx.srec } {
+ legolink $port
+ memfs /tmp
+ cd /tmp
+ mount -o -A /net/legolink /n/remote
+ $DIR/clockface /n/remote
+ echo reset > clockface
+ grid/register -a resource Robot -a name 'Lego Clock' {export /tmp}
+}
diff --git a/appl/demo/lego/firmdl.b b/appl/demo/lego/firmdl.b
new file mode 100644
index 00000000..1cc94e7b
--- /dev/null
+++ b/appl/demo/lego/firmdl.b
@@ -0,0 +1,294 @@
+implement RcxFirmdl;
+
+include "sys.m";
+include "draw.m";
+include "bufio.m";
+include "rcxsend.m";
+
+RcxFirmdl : module {
+ init : fn (ctxt : ref Draw->Context, argv : list of string);
+};
+
+sys : Sys;
+bufio : Bufio;
+rcx : RcxSend;
+me : int;
+
+Iobuf : import bufio;
+
+Image : adt {
+ start : int;
+ offset : int;
+ length : int;
+ data : array of byte;
+};
+
+DL_HDR : con 5; # download packet hdr size
+DL_DATA : con 16rc8; # download packet payload size
+
+init(nil : ref Draw->Context, argv : list of string)
+{
+ sys = load Sys Sys->PATH;
+ me = sys->pctl(Sys->NEWPGRP, nil);
+
+ bufio = load Bufio Bufio->PATH;
+ if (bufio == nil)
+ error(sys->sprint("cannot load bufio module: %r"));
+ rcx = load RcxSend "rcxsend.dis";
+ if (rcx == nil)
+ error(sys->sprint("cannot load rcx module: %r"));
+
+ argv = tl argv;
+ if (len argv != 2)
+ error("usage: portnum file");
+
+ portnum := int hd argv;
+ file := hd tl argv;
+
+ img := getimage(file);
+ cksum := sum(img.data[0:img.length]);
+ sys->print("length %.4x start %.4x \n", img.length, img.start);
+
+ err := rcx->init(portnum, 1);
+ if (err != nil)
+ error(err);
+
+ # delete firmware
+ sys->print("delete firmware\n");
+ reply : array of byte;
+ rmfirm := array [] of {byte 16r65, byte 1, byte 3, byte 5, byte 7, byte 11};
+ reply = rcx->send(rmfirm, len rmfirm, 1);
+ if (reply == nil)
+ error("delete firmware failed");
+ chkreply(reply, array [] of {byte 16r92}, "delete firmware");
+
+ # start download
+ sys->print("start download\n");
+ dlstart := array [] of {byte 16r75,
+ byte (img.start & 16rff),
+ byte ((img.start>>8) & 16rff),
+ byte (cksum & 16rff),
+ byte ((cksum>>8) & 16rff),
+ byte 0,
+ };
+ reply = rcx->send(dlstart, len dlstart, 2);
+ chkreply(reply,array [] of {byte 16r82, byte 0}, "start download");
+
+ # send the image
+ data := array [DL_HDR+DL_DATA+1] of byte; # hdr + data + 1 byte cksum
+ seqnum := 1;
+ step := DL_DATA;
+ for (i := 0; i < img.length; i += step) {
+ data[0] = byte 16r45;
+ if (seqnum & 1)
+ # alternate ops have bit 4 set
+ data[0] |= byte 16r08;
+ if (i + step > img.length) {
+ step = img.length - i;
+ seqnum = 0;
+ }
+ sys->print(".");
+ data[1] = byte (seqnum & 16rff);
+ data[2] = byte ((seqnum >> 8) & 16rff);
+ data[3] = byte (step & 16rff);
+ data[4] = byte ((step >> 8) & 16rff);
+ data[5:] = img.data[i:i+step];
+ data[5+step] = byte (sum(img.data[i:i+step]) & 16rff);
+ reply = rcx->send(data, DL_HDR+step+1, 2);
+ chkreply(reply, array [] of {byte 16rb2, byte 0}, "tx data");
+ seqnum++;
+ }
+
+ # unlock firmware
+ sys->print("\nunlock firmware\n");
+ ulfirm := array [] of {byte 16ra5, byte 'L', byte 'E', byte 'G', byte 'O', byte 174};
+ reply = rcx->send(ulfirm, len ulfirm, 26);
+ chkreply(reply, array [] of {byte 16r52}, "unlock firmware");
+ sys->print("result: %s\n", string reply[1:]);
+
+ # all done, tidy up
+ killgrp(me);
+}
+
+chkreply(got, expect : array of byte, err : string)
+{
+ if (got == nil || len got < len expect)
+ error(err + ": short reply");
+ # RCX sometimes sets bit 3 of 'opcode' byte to prevent
+ # headers with same opcode having exactly same value - mask out
+ got[0] &= byte 16rf7;
+
+ for (i := 0; i < len expect; i++)
+ if (got[i] != expect[i]) {
+ hexdump(got);
+ error(sys->sprint("%s: reply mismatch at %d", err, i));
+ }
+}
+
+error(msg : string)
+{
+ sys->print("%s\n", msg);
+ killgrp(me);
+ raise "fail:error" ;
+}
+
+killgrp(pid : int)
+{
+ pctl := sys->open("/prog/" + string pid + "/ctl", Sys->OWRITE);
+ if (pctl != nil) {
+ poison := array of byte "killgrp";
+ sys->write(pctl, poison, len poison);
+ }
+}
+
+sum(data : array of byte) : int
+{
+ t := 0;
+ for (i := 0; i < len data; i++)
+ t += int data[i];
+ return t;
+}
+
+hexdump(data : array of byte)
+{
+ for (i := 0; i < len data; i++)
+ sys->print("%.2x ", int data[i]);
+ sys->print("\n");
+}
+
+IMGSTART : con 16r8000;
+IMGLEN : con 16r4c00;
+getimage(path : string) : ref Image
+{
+ img := ref Image (IMGSTART, IMGSTART, 0, array [IMGLEN] of {* => byte 0});
+ iob := bufio->open(path, Sys->OREAD);
+ if (iob == nil)
+ error(sys->sprint("cannot open %s: %r", path));
+
+ lnum := 0;
+ while ((s := iob.gets('\n')) != nil) {
+ lnum++;
+ slen := len s;
+ # trim trailing space
+ while (slen > 0) {
+ ch := s[slen -1];
+ if (ch == ' ' || ch == '\r' || ch == '\n') {
+ slen--;
+ continue;
+ }
+ break;
+ }
+ # ignore blank lines
+ if (slen == 0)
+ continue;
+
+ if (slen < 10)
+ # STNNAAAACC
+ error("short S-record: line " + string lnum);
+
+ s = s[0:slen];
+ t := s[1];
+ if (s[0] != 'S' || t < '0' || t > '9')
+ error("bad S-record format: line " + string lnum);
+
+ data := hex2bytes(s[2:]);
+ if (data == nil)
+ error("bad chars in S-record: line " + string lnum);
+
+ count := int data[0];
+ cksum := int data[len data - 1];
+ if (count != len data -1)
+ error("S-record length mis-match: line " + string lnum);
+
+ if (sum(data[0:len data -1]) & 16rff != 16rff)
+ error("bad S-record checksum: line " + string lnum);
+
+ alen : int;
+ case t {
+ '0' =>
+ # addr[2] mname[10] ver rev desc[18] cksum
+ continue;
+ '1' =>
+ # 16-bit address, data
+ alen = 2;
+ '2' =>
+ # 24-bit address, data
+ alen = 3;
+ '3' =>
+ # 32-bit address, data
+ alen = 4;
+ '4' =>
+ # extension record
+ error("bad S-record type: line " + string lnum);
+ '5' =>
+ # data record count - ignore
+ continue;
+ '6' =>
+ # unused - ignore
+ continue;
+ '7' =>
+ img.start = wordval(data, 1, 4);
+ continue;
+ '8' =>
+ img.start = wordval(data, 1, 3);
+ continue;
+ '9' =>
+ img.start = wordval(data, 1, 2);
+ continue;
+ }
+ addr := wordval(data, 1, alen) - img.offset;
+ if (addr < 0 || addr > len img.data)
+ error("S-record address out of range: line " + string lnum);
+ img.data[addr:] = data[1+alen:1+count];
+ img.length = max(img.length, addr + count -(alen +1));
+ }
+ iob.close();
+ return img;
+}
+
+wordval(src : array of byte, s, l : int) : int
+{
+ r := 0;
+ for (i := 0; i < l; i++) {
+ r <<= 8;
+ r += int src[s+i];
+ }
+ return r;
+}
+
+max(a, b : int) : int
+{
+ if (a > b)
+ return a;
+ return b;
+}
+
+hex2bytes(s : string) : array of byte
+{
+ slen := len s;
+ if (slen & 1)
+ # should be even
+ return nil;
+ data := array [slen/2] of byte;
+ six := 0;
+ dix := 0;
+ while (six < slen) {
+ d1 := hexdigit(s[six++]);
+ d2 := hexdigit(s[six++]);
+ if (d1 == -1 || d2 == -1)
+ return nil;
+ data[dix++] = byte ((d1 << 4) + d2);
+ }
+ return data;
+}
+
+hexdigit(h : int) : int
+{
+ if (h >= '0' && h <= '9')
+ return h - '0';
+ if (h >= 'A' && h <= 'F')
+ return 10 + h - 'A';
+ if (h >= 'a' && h <= 'f')
+ return 10 + h - 'a';
+ return -1;
+}
diff --git a/appl/demo/lego/firmdl.dis b/appl/demo/lego/firmdl.dis
new file mode 100644
index 00000000..de04fdbb
--- /dev/null
+++ b/appl/demo/lego/firmdl.dis
Binary files differ
diff --git a/appl/demo/lego/firmdl.sbl b/appl/demo/lego/firmdl.sbl
new file mode 100644
index 00000000..2fd58677
--- /dev/null
+++ b/appl/demo/lego/firmdl.sbl
@@ -0,0 +1,819 @@
+limbo .sbl 2.1
+RcxFirmdl
+5
+firmdl.b
+sys.m
+draw.m
+bufio.m
+rcxsend.m
+587
+31.1,25 0
+32.1,34 1
+16,28 1
+30,33 1
+1,34 1
+1,34 1
+34.1,31 2
+35.5,17 3
+36.8,51 4
+20,50 4
+8,51 4
+8,51 4
+2,52 4
+2,52 4
+2,52 5
+2,52 4
+37.1,33 6
+38.5,15 7
+39.8,49 8
+20,48 8
+8,49 8
+8,49 8
+2,50 8
+2,50 8
+2,50 9
+2,50 8
+41.1,15 10
+42.5,13 11
+5,18 11
+43.2,30 12
+8,29 12
+2,30 12
+45.16,23 13
+1,23 13
+1,23 14
+46.12,19 15
+1,19 15
+1,19 16
+48.1,22 17
+17,21 17
+1,22 17
+1,22 17
+49.1,37 18
+25,35 18
+14,22 18
+14,36 18
+1,37 18
+1,37 18
+50.1,63 19
+12,39 19
+41,51 19
+53,62 19
+1,63 19
+1,63 19
+52.1,29 20
+18,25 20
+27,28 20
+1,29 20
+1,29 20
+53.5,15 21
+54.2,12 22
+8,11 22
+2,12 22
+57.1,32 23
+12,31 23
+1,32 23
+1,32 23
+59.1,76 24
+24,34 24
+24,34 24
+36,42 24
+36,42 24
+44,50 24
+44,50 24
+52,58 24
+52,58 24
+60,66 24
+60,66 24
+68,75 24
+68,75 24
+60.1,41 25
+19,25 25
+27,37 25
+39,40 25
+1,41 25
+1,41 25
+61.5,17 26
+62.2,33 27
+8,32 27
+2,33 27
+63.1,61 28
+10,15 28
+17,41 28
+30,40 28
+30,40 28
+43,60 28
+1,61 28
+66.1,31 29
+12,30 29
+1,31 29
+1,31 29
+67.1,73.2 30
+67.25,35 30
+25,35 30
+68.5,29 30
+10,29 30
+5,29 30
+69.5,34 30
+12,21 30
+11,25 30
+10,34 30
+5,34 30
+70.5,25 30
+10,25 30
+5,25 30
+71.5,30 30
+11,21 30
+10,30 30
+5,30 30
+72.5,11 30
+5,11 30
+74.1,43 31
+19,26 31
+28,39 31
+41,42 31
+1,43 31
+1,43 31
+75.1,67 32
+10,15 32
+16,48 32
+29,39 32
+29,39 32
+41,47 32
+41,47 32
+50,66 32
+1,67 32
+78.1,41 33
+79.1,12 34
+80.1,16 35
+81.6,12 36
+14,28 37
+82.2,9 38
+2,22 38
+83.6,16 39
+6,16 39
+85.3,10 40
+3,24 40
+86.6,14 41
+17,27 41
+6,27 41
+87.10,20 42
+3,24 42
+88.3,13 43
+90.2,17 44
+13,16 44
+2,17 44
+2,17 44
+91.2,9 45
+17,33 45
+2,33 45
+92.2,9 46
+18,31 46
+17,40 46
+2,40 46
+93.2,9 47
+17,31 47
+2,31 47
+94.2,9 48
+18,29 48
+17,38 48
+2,38 48
+95.24,30 49
+13,21 49
+13,31 49
+2,31 49
+2,31 50
+96.7,13 51
+2,14 51
+23,46 51
+38,44 51
+27,35 51
+27,45 51
+23,46 51
+23,46 51
+22,55 51
+2,55 51
+97.2,43 52
+20,24 52
+26,39 52
+41,42 52
+2,43 52
+2,43 52
+98.2,62 53
+11,16 53
+18,50 53
+31,41 53
+31,41 53
+43,49 53
+43,49 53
+52,61 53
+2,62 53
+99.2,10 54
+81.30,39 55
+30,39 55
+103.1,34 56
+12,33 56
+1,34 56
+1,34 56
+104.1,85 57
+24,34 57
+24,34 57
+36,44 57
+36,44 57
+46,54 57
+46,54 57
+56,64 57
+56,64 57
+66,74 57
+66,74 57
+76,84 57
+76,84 57
+105.1,42 58
+19,25 58
+27,37 58
+39,41 58
+1,42 58
+1,42 58
+106.1,61 59
+10,15 59
+17,41 59
+30,40 59
+30,40 59
+43,60 59
+1,61 59
+107.1,45 60
+12,26 60
+35,44 60
+35,40 60
+35,44 60
+28,44 60
+28,44 61
+1,45 60
+1,45 60
+110.1,12 62
+9,11 62
+1,12 62
+111.0,1 63
+115.5,15 64
+29,39 64
+19,26 64
+19,39 64
+116.2,30 65
+8,29 65
+2,30 65
+119.1,7 66
+1,21 66
+121.6,12 67
+18,28 68
+14,28 68
+122.16,25 69
+16,25 69
+6,12 69
+6,25 69
+123.3,15 70
+11,14 70
+3,15 70
+124.9,56 71
+21,47 71
+49,52 71
+54,55 71
+9,56 71
+9,56 71
+3,57 71
+3,57 71
+3,57 72
+3,57 71
+121.30,33 73
+30,33 73
+126.0,1 74
+130.1,24 75
+12,18 75
+20,23 75
+1,24 75
+1,24 75
+131.1,12 76
+9,11 76
+1,12 76
+132.1,19 77
+137.1,63 78
+30,40 78
+19,40 78
+19,49 78
+19,49 79
+51,62 78
+1,63 78
+1,63 78
+138.5,16 80
+139.2,35 81
+140.2,38 82
+13,17 82
+19,25 82
+27,37 82
+2,38 82
+2,38 82
+2,38 83
+142.0,1 84
+146.1,7 85
+147.6,12 86
+18,26 87
+14,26 87
+148.11,18 88
+7,18 88
+2,18 88
+147.28,31 89
+28,31 89
+149.8,9 90
+1,9 90
+154.6,12 91
+18,26 92
+14,26 92
+155.2,34 93
+13,20 93
+26,33 93
+22,33 93
+2,34 93
+2,34 93
+154.28,31 94
+28,31 94
+156.1,17 95
+12,16 95
+1,17 95
+1,17 95
+157.0,1 96
+163.1,74 97
+19,27 97
+29,37 97
+39,40 97
+42,73 97
+66,72 97
+66,72 97
+66,72 97
+66,72 97
+66,72 97
+66,72 97
+1,74 97
+1,74 98
+164.1,37 99
+20,24 99
+26,36 99
+1,37 99
+1,37 99
+165.5,15 100
+166.8,47 101
+20,40 101
+42,46 101
+8,47 101
+8,47 101
+2,48 101
+2,48 101
+2,48 102
+2,48 101
+168.1,10 103
+169.8,29 104
+14,17 104
+23,27 104
+8,29 104
+8,29 104
+8,29 104
+8,36 104
+8,36 105
+170.2,8 106
+171.2,15 107
+173.9,17 108
+174.11,18 109
+9,19 109
+175.7,16 110
+20,30 110
+34,44 110
+176.4,10 111
+177.4,12 112
+182.6,15 113
+6,15 114
+183.3,11 115
+185.6,15 116
+187.3,47 117
+35,46 117
+9,46 117
+9,46 118
+3,47 117
+189.2,15 119
+190.7,11 120
+191.6,10 121
+6,17 121
+21,28 121
+32,39 121
+192.3,52 122
+40,51 122
+9,51 122
+9,51 123
+3,52 122
+194.2,26 124
+20,25 124
+20,21 124
+20,25 124
+2,26 124
+2,26 124
+195.6,17 125
+196.3,55 126
+43,54 126
+9,54 126
+9,54 127
+3,55 126
+198.15,22 128
+2,22 128
+199.20,28 129
+20,32 129
+15,33 129
+2,33 129
+200.15,23 130
+15,26 130
+6,26 130
+201.3,59 131
+47,58 131
+9,58 131
+9,58 132
+3,59 131
+203.6,30 133
+17,25 133
+17,28 133
+10,14 133
+10,29 133
+6,30 133
+6,30 133
+6,47 133
+6,47 133
+204.3,55 134
+43,54 134
+9,54 134
+9,54 135
+3,55 134
+207.7,8 136
+7,8 136
+7,8 136
+7,8 136
+7,8 137
+210.3,11 138
+213.3,11 139
+3,11 136
+216.3,11 140
+3,11 136
+219.3,11 141
+3,11 136
+222.3,50 142
+38,49 142
+9,49 142
+9,49 143
+3,50 142
+3,50 136
+3,50 144
+225.3,11 145
+3,11 146
+228.3,11 147
+230.3,34 148
+23,27 148
+29,30 148
+32,33 148
+3,34 148
+3,34 148
+3,34 149
+231.3,11 150
+233.3,34 151
+23,27 151
+29,30 151
+32,33 151
+3,34 151
+3,34 151
+3,34 152
+234.3,11 153
+236.3,34 154
+23,27 154
+29,30 154
+32,33 154
+3,34 154
+3,34 154
+3,34 155
+237.3,11 156
+239.10,32 157
+18,22 157
+24,25 157
+27,31 157
+10,32 157
+10,32 157
+2,45 157
+240.6,14 158
+25,37 158
+18,37 158
+241.3,62 159
+50,61 159
+9,61 159
+9,61 160
+3,62 159
+242.32,39 161
+25,31 161
+20,24 161
+20,40 161
+2,40 161
+2,40 162
+243.31,43 163
+45,54 163
+31,54 163
+19,29 163
+15,55 163
+19,29 163
+19,29 163
+31,43 163
+45,54 163
+31,54 163
+31,54 164
+31,54 164
+245.1,12 165
+1,4 165
+1,12 165
+246.8,11 166
+1,11 166
+251.1,7 167
+252.6,12 168
+14,19 169
+253.2,9 170
+254.15,18 171
+11,19 171
+7,19 171
+2,19 171
+252.21,24 172
+21,24 172
+256.8,9 173
+1,9 173
+268.1,14 174
+269.5,13 175
+5,13 175
+271.9,12 176
+2,12 176
+272.16,22 177
+1,31 177
+273.1,9 178
+274.1,9 179
+275.8,18 180
+276.2,26 181
+19,24 181
+19,24 181
+17,25 181
+2,26 181
+2,26 181
+277.2,26 182
+19,24 182
+19,24 182
+17,25 182
+2,26 182
+2,26 182
+278.6,14 183
+18,26 183
+279.10,13 184
+3,13 184
+280.7,12 185
+7,12 185
+2,13 185
+22,31 185
+21,37 185
+2,37 185
+2,37 185
+282.8,12 186
+1,12 186
+287.5,13 187
+17,25 187
+288.9,16 188
+2,16 188
+289.5,13 189
+17,25 189
+290.9,15 190
+9,21 190
+2,21 190
+291.5,13 191
+17,25 191
+292.9,15 192
+9,21 192
+2,21 192
+293.8,10 193
+1,10 193
+14
+aSys->Dir 1:26.1,39.2 64
+11
+0:name:28.2,6 s
+4:uid:29.2,5 s
+8:gid:30.2,5 s
+12:muid:31.2,6 s
+16:qid:32.2,5 @1
+
+32:mode:33.2,6 i
+36:atime:34.2,7 i
+40:mtime:35.2,7 i
+48:length:36.2,8 B
+56:dtype:37.2,7 i
+60:dev:38.2,5 i
+aSys->Qid 11.1,16.2 16
+3
+0:path:13.2,6 B
+8:vers:14.2,6 i
+12:qtype:15.2,7 i
+aDraw->Chans 2:70.1,82.2 4
+1
+0:desc:72.2,6 i
+aDraw->Context 274.1,279.2 12
+3
+0:display:276.2,9 R@4
+
+4:screen:277.2,8 R@8
+
+8:wm:278.2,4 Ct8.2
+0:t0:15,21 s
+4:t1:15,21 Ct8.2
+0:t0:32,38 s
+4:t1:32,38 R@9
+
+
+
+aDraw->Display 201.1,230.2 20
+5
+0:image:203.2,7 R@5
+
+4:white:204.2,7 R@5
+
+8:black:205.2,7 R@5
+
+12:opaque:206.2,8 R@5
+
+16:transparent:207.2,13 R@5
+
+aDraw->Image 142.1,198.2 56
+8
+0:r:146.2,3 @6
+
+16:clipr:147.2,7 @6
+
+32:depth:148.2,7 i
+36:chans:149.2,7 @2
+
+40:repl:150.2,6 i
+44:display:151.2,9 R@4
+
+48:screen:152.2,8 R@8
+
+52:iname:153.2,7 s
+aDraw->Rect 116.1,139.2 16
+2
+0:min:118.2,5 @7
+
+8:max:119.2,5 @7
+
+aDraw->Point 99.1,113.2 8
+2
+0:x:101.2,3 i
+4:y:102.2,3 i
+aDraw->Screen 249.1,263.2 16
+4
+0:id:251.2,4 i
+4:image:252.2,7 R@5
+
+8:fill:253.2,6 R@5
+
+12:display:254.2,9 R@4
+
+aDraw->Wmcontext 282.1,291.2 28
+7
+0:kbd:284.2,5 Ci
+4:ptr:285.2,5 CR@10
+
+8:ctl:286.2,5 Cs
+12:wctl:287.2,6 Cs
+16:images:288.2,8 CR@5
+
+20:connfd:289.2,8 R@11
+
+24:ctxt:290.2,6 R@3
+
+aDraw->Pointer 266.1,271.2 16
+3
+0:buttons:268.2,9 i
+4:xy:269.2,4 @7
+
+12:msec:270.2,6 i
+aSys->FD 1:45.1,48.2 4
+1
+0:fd:47.2,4 i
+aImage 0:19.0,24.1 16
+4
+0:start:20.1,6 i
+4:offset:21.1,7 i
+8:length:22.1,7 i
+12:data:23.1,5 Ab
+aBufio->Iobuf 3:16.1,50.2 48
+9
+0:fd:41.2,4 R@11
+
+4:buffer:42.2,8 Ab
+8:index:43.2,7 i
+12:size:44.2,6 i
+16:dirty:45.2,7 i
+24:bufpos:46.2,8 B
+32:filpos:47.2,8 B
+40:lastop:48.2,8 i
+44:mode:49.2,6 i
+10
+0:init
+1
+36:argv:0:29.30,34 Ls
+13
+40:img:48.1,4 R@12
+
+44:data:78.1,5 Ab
+48:reply:58.1,6 Ab
+52:step:80.1,5 i
+56:i:81.6,7 i
+60:seqnum:79.1,7 i
+64:cksum:49.1,6 i
+68:dlstart:67.1,8 Ab
+72:err:52.1,4 s
+76:rmfirm:59.1,7 Ab
+80:ulfirm:104.1,7 Ab
+84:file:46.1,5 s
+88:portnum:45.1,8 i
+n247:chkreply
+3
+32:got:113.9,12 Ab
+36:expect:14,20 Ab
+40:err:38,41 s
+1
+48:i:121.6,7 i
+n279:error
+1
+32:msg:128.6,9 s
+0
+n288:killgrp
+1
+32:pid:135.8,11 i
+2
+36:pctl:137.1,5 R@11
+
+40:poison:139.2,8 Ab
+n306:sum
+1
+32:data:144.4,8 Ab
+2
+36:i:147.6,7 i
+40:t:146.1,2 i
+i317:hexdump
+1
+32:data:152.8,12 Ab
+1
+36:i:154.6,7 i
+n333:getimage
+1
+32:path:161.9,13 s
+12
+36:data:194.2,6 Ab
+40:img:163.1,4 R@12
+
+44:lnum:168.1,5 i
+48:s:169.9,10 s
+52:slen:171.2,6 i
+56:alen:206.2,6 i
+60:addr:239.2,6 i
+64:ch:174.3,5 i
+68:count:198.2,7 i
+72:iob:164.1,4 R@13
+
+92:cksum:199.2,7 i
+64:t:190.2,3 i
+R@12
+524:wordval
+3
+32:src:249.8,11 Ab
+36:s:29,30 i
+40:l:32,33 i
+2
+44:i:252.6,7 i
+48:r:251.1,2 i
+i536:hex2bytes
+1
+32:s:266.10,11 s
+6
+36:six:273.1,4 i
+40:slen:268.1,5 i
+44:d1:276.2,4 i
+48:d2:277.2,4 i
+52:data:272.1,5 Ab
+56:dix:274.1,4 i
+Ab571:hexdigit
+1
+32:h:285.9,10 i
+0
+i4
+136:bufio:13.0,5 mBufio
+3:1.0,57.1 0
+
+176:me:0:15.0,2 i
+184:rcx:14.0,3 mRcxSend
+4:1.0,4.1 0
+
+208:sys:0:12.0,3 mSys
+1:4.0,160.1 0
+
diff --git a/appl/demo/lego/legolink.b b/appl/demo/lego/legolink.b
new file mode 100644
index 00000000..ea29efd6
--- /dev/null
+++ b/appl/demo/lego/legolink.b
@@ -0,0 +1,601 @@
+implement LegoLink;
+
+include "sys.m";
+include "draw.m";
+include "timers.m";
+include "rcxsend.m";
+
+LegoLink : module {
+ init : fn (ctxt : ref Draw->Context, argv : list of string);
+};
+
+POLLDONT : con 0;
+POLLNOW : con 16r02;
+POLLDO : con 16r04;
+
+sys : Sys;
+timers : Timers;
+Timer : import timers;
+datain : chan of array of byte;
+errormsg : string;
+
+error(msg: string)
+{
+ sys->fprint(sys->fildes(2), "%s\n", msg);
+ raise "fail:error";
+}
+
+init(nil : ref Draw->Context, argv : list of string)
+{
+ sys = load Sys Sys->PATH;
+ sys->pctl(Sys->NEWPGRP, nil);
+
+ argv = tl argv;
+ if (len argv != 1)
+ error("usage: legolink portnum");
+
+ timers = load Timers "timers.dis";
+ if (timers == nil)
+ error(sys->sprint("cannot load timers module: %r"));
+
+ portnum := int hd argv;
+ (rdfd, wrfd, err) := serialport(portnum);
+ if (err != nil)
+ error(err);
+
+ # set up our mount file
+ if (sys->bind("#s", "/net", Sys->MBEFORE) == -1)
+ error(sys->sprint("failed to bind srv device: %r"));
+
+ f2c := sys->file2chan("/net", "legolink");
+ if (f2c == nil)
+ error(sys->sprint("cannot create legolink channel: %r"));
+
+ datain = chan of array of byte;
+ send := chan of array of byte;
+ recv := chan of array of byte;
+ timers->init(50);
+ spawn reader(rdfd, datain);
+ consume();
+ spawn protocol(wrfd, send, recv);
+ spawn srvlink(f2c, send, recv);
+}
+
+srvlink(f2c : ref Sys->FileIO, send, recv : chan of array of byte)
+{
+ me := sys->pctl(0, nil);
+ rdfid := -1;
+ wrfid := -1;
+ buffer := array [256] of byte;
+ bix := 0;
+
+ rdblk := chan of (int, int, int, Sys->Rread);
+ readreq := rdblk;
+ wrblk := chan of (int, array of byte, int, Sys->Rwrite);
+ writereq := f2c.write;
+ wrreply : Sys->Rwrite;
+ sendblk := chan of array of byte;
+ sendchan := sendblk;
+ senddata : array of byte;
+
+ for (;;) alt {
+ data := <- recv =>
+ # got some data from brick, nil for error
+ if (data == nil) {
+ # some sort of error
+ if (wrreply != nil) {
+ wrreply <- = (0, errormsg);
+ }
+ killgrp(me);
+ }
+ if (bix + len data > len buffer) {
+ newb := array [bix + len data + 256] of byte;
+ newb[0:] = buffer;
+ buffer = newb;
+ }
+ buffer[bix:] = data;
+ bix += len data;
+ readreq = f2c.read;
+
+ (offset, count, fid, rc) := <- readreq =>
+ if (rdfid == -1)
+ rdfid = fid;
+ if (fid != rdfid) {
+ if (rc != nil)
+ rc <- = (nil, "file in use");
+ continue;
+ }
+ if (rc == nil) {
+ rdfid = -1;
+ continue;
+ }
+ if (errormsg != nil) {
+ rc <- = (nil, errormsg);
+ killgrp(me);
+ }
+ # reply with what we've got
+ if (count > bix)
+ count = bix;
+ rdata := array [count] of byte;
+ rdata[0:] = buffer[0:count];
+ buffer[0:] = buffer[count:bix];
+ bix -= count;
+ if (bix == 0)
+ readreq = rdblk;
+ alt {
+ rc <- = (rdata, nil)=>
+ ;
+ * =>
+ ;
+ }
+
+ (offset, data, fid, wc) := <- writereq =>
+ if (wrfid == -1)
+ wrfid = fid;
+ if (fid != wrfid) {
+ if (wc != nil)
+ wc <- = (0, "file in use");
+ continue;
+ }
+ if (wc == nil) {
+ wrfid = -1;
+ continue;
+ }
+ if (errormsg != nil) {
+ wc <- = (0, errormsg);
+ killgrp(me);
+ }
+ senddata = data;
+ sendchan = send;
+ wrreply = wc;
+ writereq = wrblk;
+
+ sendchan <- = senddata =>
+ alt {
+ wrreply <- = (len senddata, nil) =>
+ ;
+ * =>
+ ;
+ }
+ wrreply = nil;
+ sendchan = sendblk;
+ writereq = f2c.write;
+ }
+}
+
+killgrp(pid : int)
+{
+ pctl := sys->open("/prog/" + string pid + "/ctl", Sys->OWRITE);
+ if (pctl != nil) {
+ poison := array of byte "killgrp";
+ sys->write(pctl, poison, len poison);
+ }
+ exit;
+}
+
+serialport(port : int) : (ref Sys->FD, ref Sys->FD, string)
+{
+ serport := "/dev/eia" + string port;
+ serctl := serport + "ctl";
+
+ rfd := sys->open(serport, Sys->OREAD);
+ if (rfd == nil)
+ return (nil, nil, sys->sprint("cannot read %s: %r", serport));
+ wfd := sys->open(serport, Sys->OWRITE);
+ if (wfd == nil)
+ return (nil, nil, sys->sprint("cannot write %s: %r", serport));
+ ctlfd := sys->open(serctl, Sys->OWRITE);
+ if (ctlfd == nil)
+ return (nil, nil, sys->sprint("cannot open %s: %r", serctl));
+
+ config := array [] of {
+ "b2400",
+ "l8",
+ "po",
+ "m0",
+ "s1",
+ "d1",
+ "r1",
+ };
+
+ for (i := 0; i < len config; i++) {
+ cmd := array of byte config[i];
+ if (sys->write(ctlfd, cmd, len cmd) <= 0)
+ return (nil, nil, sys->sprint("serial config (%s): %r", config[i]));
+ }
+ return (rfd, wfd, nil);
+}
+
+# reader and nbread as in rcxsend.b
+reader(fd : ref Sys->FD, out : chan of array of byte)
+{
+ # with buf size of 1 there is no need
+ # for overrun code in nbread()
+
+ buf := array [1] of byte;
+ for (;;) {
+ n := sys->read(fd, buf, len buf);
+ if (n <= 0)
+ break;
+ data := array [n] of byte;
+ data[0:] = buf[0:n];
+ out <- = data;
+ }
+ out <- = nil;
+}
+
+overrun : array of byte;
+
+nbread(ms, n : int) : array of byte
+{
+ ret := array[n] of byte;
+ tot := 0;
+ if (overrun != nil) {
+ if (n < len overrun) {
+ ret[0:] = overrun[0:n];
+ overrun = overrun[n:];
+ return ret;
+ }
+ ret[0:] = overrun;
+ tot += len overrun;
+ overrun = nil;
+ }
+ tmr := timers->new(ms, 0);
+loop:
+ while (tot < n) {
+ tmr.reset();
+ alt {
+ data := <- datain =>
+ if (data == nil)
+ break loop;
+ dlen := len data;
+ if (dlen > n - tot) {
+ dlen = n - tot;
+ overrun = data[dlen:];
+ }
+ ret[tot:] = data[0:dlen];
+ tot += dlen;
+ <- tmr.tick =>
+ # reply timeout;
+ break loop;
+ }
+ }
+ tmr.destroy();
+ if (tot == 0)
+ return nil;
+ return ret[0:tot];
+}
+
+consume()
+{
+ while (nbread(300, 1024) != nil)
+ ;
+}
+
+# fd: connection to remote client
+# send: from local to remote
+# recv: from remote to local
+protocol(fd : ref Sys->FD, send, recv : chan of array of byte)
+{
+ seqnum := 0;
+ towerdown := timers->new(1500, 0);
+ starttower := 1;
+ tmr := timers->new(250, 0);
+
+ for (;;) {
+ data : array of byte = nil;
+ # get data to send
+ alt {
+ data = <- send =>
+ ;
+ <- tmr.tick =>
+ data = nil;
+ <- towerdown.tick =>
+ starttower = 1;
+ continue;
+ }
+
+ poll := POLLNOW;
+ while (poll == POLLNOW) {
+ reply : array of byte;
+ (reply, poll, errormsg) = datasend(fd, seqnum++, data, starttower);
+ starttower = 0;
+ towerdown.reset();
+ if (errormsg != nil) {
+sys->print("protocol: send error: %s\n", errormsg);
+ tmr.destroy();
+ recv <- = nil;
+ return;
+ }
+ if (reply != nil) {
+ recv <- = reply;
+ }
+ if (poll == POLLNOW) {
+ # quick check to see if we have any more data
+ alt {
+ data = <- send =>
+ ;
+ * =>
+ data = nil;
+ }
+ }
+ }
+ if (poll == POLLDO)
+ tmr.reset();
+ else
+ tmr.cancel();
+ }
+}
+
+TX_HDR : con 3;
+DL_HDR : con 5; # 16r45 seqLSB seqMSB lenLSB lenMSB
+DL_CKSM : con 1;
+LN_HDR : con 1;
+LN_JUNK : con 2;
+LN_LEN : con 2;
+LN_RXLEN : con 2;
+LN_POLLMASK : con 16r06;
+LN_COMPMASK : con 16r08;
+
+
+# send a message (may be empty)
+# wait for the reply
+# returns (data, poll request, error)
+
+datasend(wrfd : ref Sys->FD, seqnum : int, data : array of byte, startup : int) : (array of byte, int, string)
+{
+if (startup) {
+ dummy := array [] of { byte 255, byte 0, byte 255, byte 0};
+ sys->write(wrfd, dummy, len dummy);
+ nbread(100, 100);
+}
+ seqnum = seqnum & 1;
+ docomp := 0;
+ if (data != nil) {
+ comp := rlencode(data);
+ if (len comp < len data) {
+ docomp = 1;
+ data = comp;
+ }
+ }
+
+ # construct the link-level data packet
+ # DL_HDR LN_HDR data cksum
+ # last byte of data is stored in cksum byte
+ llen := LN_HDR + len data;
+ blklen := LN_LEN + llen - 1; # llen includes cksum
+ ldata := array [DL_HDR + blklen + 1] of byte;
+
+ # DL_HDR
+ if (seqnum == 0)
+ ldata[0] = byte 16r45;
+ else
+ ldata[0] = byte 16r4d;
+ ldata[1] = byte 0; # blk number LSB
+ ldata[2] = byte 0; # blk number MSB
+ ldata[3] = byte (blklen & 16rff); # blk length LSB
+ ldata[4] = byte ((blklen >> 8) & 16rff); # blk length MSB
+
+ # LN_LEN
+ ldata[5] = byte (llen & 16rff);
+ ldata[6] = byte ((llen>>8) & 16rff);
+ # LN_HDR
+ lhval := byte 0;
+ if (seqnum == 1)
+ lhval |= byte 16r01;
+ if (docomp)
+ lhval |= byte 16r08;
+
+ ldata[7] = lhval;
+
+ # data (+cksum)
+ ldata[8:] = data;
+
+ # construct the rcx data packet
+ # TX_HDR (dn ~dn) cksum ~cksum
+ rcxlen := TX_HDR + 2*(len ldata + 1);
+ rcxdata := array [rcxlen] of byte;
+
+ rcxdata[0] = byte 16r55;
+ rcxdata[1] = byte 16rff;
+ rcxdata[2] = byte 16r00;
+ rcix := TX_HDR;
+ cksum := 0;
+ for (i := 0; i < len ldata; i++) {
+ b := ldata[i];
+ rcxdata[rcix++] = b;
+ rcxdata[rcix++] = ~b;
+ cksum += int b;
+ }
+ rcxdata[rcix++] = byte (cksum & 16rff);
+ rcxdata[rcix++] = byte (~cksum & 16rff);
+
+ # send it
+ err : string;
+ reply : array of byte;
+ for (try := 0; try < 8; try++) {
+ if (err != nil)
+ sys->print("Try %d (lasterr %s)\n", try, err);
+ err = "";
+ step := 8;
+ for (i = 0; err == nil && i < rcxlen; i += step) {
+ if (i + step > rcxlen)
+ step = rcxlen -i;
+ if (sys->write(wrfd, rcxdata[i:i+step], step) != step) {
+ return (nil, 0, "hangup");
+ }
+
+ # get the echo
+ reply = nbread(300, step);
+ if (reply == nil || len reply != step)
+ # short echo
+ err = "tower not responding";
+
+ # check the echo
+ for (ei := 0; err == nil && ei < step; ei++) {
+ if (reply[ei] != rcxdata[i+ei])
+ # echo mis-match
+ err = "serial comms error";
+ }
+ }
+ if (err != nil) {
+ consume();
+ continue;
+ }
+
+ # wait for a reply
+ replen := TX_HDR + LN_JUNK + 2*LN_RXLEN;
+ reply = nbread(300, replen);
+ if (reply == nil || len reply != replen) {
+ err = "brick not responding";
+ consume();
+ continue;
+ }
+ if (reply[0] != byte 16r55 || reply[1] != byte 16rff || reply[2] != byte 0
+ || reply[5] != ~reply[6] || reply[7] != ~reply[8]) {
+ err = "bad reply from brick";
+ consume();
+ continue;
+ }
+ # reply[3] and reply [4] are junk, ~junk
+ # put on front of msg by rcx rom
+ replen = int reply[5] + ((int reply[7]) << 8) + 1;
+ cksum = int reply[3] + int reply[5] + int reply[7];
+ reply = nbread(200, replen * 2);
+ if (reply == nil || len reply != replen * 2) {
+ err = "short reply from brick";
+ consume();
+ continue;
+ }
+ cksum += int reply[0];
+ for (i = 1; i < replen; i++) {
+ reply[i] = reply[2*i];
+ cksum += int reply[i];
+ }
+ cksum -= int reply[replen-1];
+ if (reply[replen-1] != byte (cksum & 16rff)) {
+ err = "bad checksum from brick";
+ consume();
+ continue;
+ }
+ if ((reply[0] & byte 1) != byte (seqnum & 1)) {
+ # seqnum error
+ # we have read everything, don't bother with consume()
+ err = "bad seqnum from brick";
+ continue;
+ }
+
+ # TADA! we have a valid message
+ mdata : array of byte;
+ lnhdr := int reply[0];
+ poll := lnhdr & LN_POLLMASK;
+ if (replen > 2) {
+ # more than just hdr and cksum
+ if (lnhdr & LN_COMPMASK) {
+ mdata = rldecode(reply[1:replen-1]);
+ if (mdata == nil) {
+ err = "bad brick msg compression";
+ continue;
+ }
+ } else {
+ mdata = array [replen - 2] of byte;
+ mdata[0:] = reply[1:replen-1];
+ }
+ }
+ return (mdata, poll, nil);
+ }
+ return (nil, 0, err);
+}
+
+
+rlencode(data : array of byte) : array of byte
+{
+ srcix := 0;
+ outix := 0;
+ out := array [64] of byte;
+ val := 0;
+ nextval := -1;
+ n0 := 0;
+
+ while (srcix < len data || nextval != -1) {
+ if (nextval != -1) {
+ val = nextval;
+ nextval = -1;
+ } else {
+ val = int data[srcix];
+ if (val == 16r88)
+ nextval = 0;
+ if (val == 0) {
+ n0++;
+ srcix++;
+ if (srcix < len data && n0 < 16rff + 2)
+ continue;
+ }
+ case n0 {
+ 0 =>
+ srcix++;
+ 1 =>
+ val = 0;
+ nextval = -1;
+ n0 = 0;
+ 2 =>
+ val = 0;
+ nextval = 0;
+ n0 = 0;
+ * =>
+ val = 16r88;
+ nextval = (n0-2);
+ n0 = 0;
+ }
+ }
+ if (outix >= len out) {
+ newout := array [2 * len out] of byte;
+ newout[0:] = out;
+ out = newout;
+ }
+ out[outix++] = byte val;
+ }
+ return out[0:outix];
+}
+
+rldecode(data : array of byte) : array of byte
+{
+ srcix := 0;
+ outix := 0;
+ out := array [64] of byte;
+
+ n0 := 0;
+ val := 0;
+ while (srcix < len data || n0 > 0) {
+ if (n0 > 0)
+ n0--;
+ else {
+ val = int data[srcix++];
+ if (val == 16r88) {
+ if (srcix >= len data)
+ # bad encoding
+ return nil;
+ n0 = int data[srcix++];
+ if (n0 > 0) {
+ n0 += 2;
+ val = 0;
+ continue;
+ }
+ }
+ }
+ if (outix >= len out) {
+ newout := array [2 * len out] of byte;
+ newout[0:] = out;
+ out = newout;
+ }
+ out[outix++] = byte val;
+ }
+ return out[0:outix];
+}
+
+hexdump(data : array of byte)
+{
+ for (i := 0; i < len data; i++)
+ sys->print("%.2x ", int data[i]);
+ sys->print("\n");
+}
diff --git a/appl/demo/lego/legolink.dis b/appl/demo/lego/legolink.dis
new file mode 100644
index 00000000..77f5573f
--- /dev/null
+++ b/appl/demo/lego/legolink.dis
Binary files differ
diff --git a/appl/demo/lego/legolink.sbl b/appl/demo/lego/legolink.sbl
new file mode 100644
index 00000000..11de96e7
--- /dev/null
+++ b/appl/demo/lego/legolink.sbl
@@ -0,0 +1,1298 @@
+limbo .sbl 2.1
+LegoLink
+5
+legolink.b
+sys.m
+draw.m
+timers.m
+rcxsend.m
+949
+24.13,27 0
+25,26 0
+13,27 0
+13,27 0
+1,41 0
+1,41 0
+1,41 1
+29,35 0
+37,40 0
+1,41 0
+1,41 0
+25.1,19 2
+30.1,25 3
+31.1,29 4
+11,23 4
+25,28 4
+1,29 4
+1,29 4
+33.1,15 5
+34.5,13 6
+5,18 6
+35.2,34 7
+8,33 7
+2,34 7
+37.1,34 8
+38.5,18 9
+39.8,52 10
+20,51 10
+8,52 10
+8,52 10
+2,53 10
+2,53 10
+2,53 11
+2,53 10
+41.16,23 12
+1,23 12
+1,23 13
+42.22,41 14
+33,40 14
+22,41 14
+22,41 14
+43.5,15 15
+44.2,12 16
+8,11 16
+2,12 16
+47.5,42 17
+15,19 17
+21,27 17
+29,41 17
+5,42 17
+5,42 17
+5,48 17
+48.8,52 18
+20,51 18
+8,52 18
+8,52 18
+2,53 18
+2,53 18
+2,53 19
+2,53 18
+50.1,42 20
+23,29 20
+31,41 20
+1,42 20
+1,42 20
+51.5,15 21
+52.8,57 22
+20,56 22
+8,57 22
+8,57 22
+2,58 22
+2,58 22
+2,58 23
+2,58 22
+54.1,31 24
+55.1,30 25
+56.1,30 26
+57.1,17 27
+14,16 27
+1,17 27
+58.1,27 28
+14,18 28
+20,26 28
+1,27 28
+59.1,10 29
+1,10 29
+60.1,33 30
+16,20 30
+22,26 30
+28,32 30
+1,33 30
+61.1,31 31
+15,18 31
+20,24 31
+26,30 31
+1,31 31
+62.0,1 32
+66.1,24 33
+17,18 33
+20,23 33
+1,24 33
+1,24 33
+67.1,12 34
+68.1,12 35
+69.1,30 36
+70.1,9 37
+72.1,45 38
+73.1,17 39
+74.1,56 40
+75.1,22 41
+77.1,33 42
+78.1,20 43
+82.12,16 44
+12,16 44
+100.32,39 44
+32,39 44
+132.31,39 44
+31,39 44
+153.1,9 44
+1,9 44
+81.10,16 44
+10,16 44
+10,16 44
+10,16 44
+84.6,17 45
+86.7,21 46
+87.18,19 47
+21,29 47
+4,30 47
+4,30 48
+89.3,14 49
+11,13 49
+3,14 49
+91.23,33 50
+12,20 50
+6,20 50
+6,33 50
+92.24,32 51
+18,32 51
+18,38 51
+3,47 51
+93.3,20 52
+94.3,16 53
+3,16 54
+96.2,21 55
+97.9,17 56
+2,17 56
+98.2,20 57
+2,20 58
+2,20 44
+100.29,39 44
+29,39 59
+101.6,17 60
+102.3,14 61
+103.6,18 62
+104.7,16 63
+105.13,16 64
+18,31 64
+4,32 64
+4,32 65
+4,32 66
+4,32 67
+4,32 68
+4,32 69
+106.3,11 70
+108.6,15 71
+109.3,13 72
+3,13 73
+3,13 74
+3,13 75
+110.3,11 76
+112.6,21 77
+113.12,15 78
+17,25 78
+3,26 78
+3,26 79
+3,26 80
+114.3,14 81
+11,13 81
+3,14 81
+117.6,17 82
+118.3,14 83
+119.2,32 84
+120.14,20 85
+14,29 85
+2,29 85
+2,29 86
+121.15,21 87
+15,32 87
+2,32 87
+2,32 88
+122.2,14 89
+123.6,14 90
+124.3,18 91
+126.2,4 92
+11,16 92
+18,21 92
+2,4 92
+125.2,8 92
+2,8 92
+2,8 92
+2,8 92
+2,8 93
+2,8 94
+2,8 92
+2,8 92
+2,8 95
+2,8 96
+2,8 97
+2,8 44
+132.28,39 44
+28,39 98
+28,39 99
+133.6,17 100
+134.3,14 101
+135.6,18 102
+136.7,16 103
+137.13,14 104
+16,29 104
+4,30 104
+4,30 105
+4,30 106
+4,30 107
+4,30 108
+4,30 109
+138.3,11 110
+140.6,15 111
+141.3,13 112
+3,13 113
+3,13 114
+3,13 115
+3,13 116
+142.3,11 117
+144.6,21 118
+145.12,13 119
+15,23 119
+3,24 119
+3,24 120
+146.3,14 121
+11,13 121
+3,14 121
+148.2,17 122
+149.2,17 123
+150.2,14 124
+151.2,18 125
+2,18 126
+2,18 127
+2,18 128
+2,18 129
+2,18 44
+155.2,9 130
+16,28 130
+30,33 130
+2,9 130
+154.2,8 130
+2,8 130
+2,8 130
+2,8 130
+2,8 131
+2,8 130
+2,8 130
+160.2,15 132
+161.2,20 133
+162.2,22 134
+2,22 44
+168.1,63 135
+30,40 135
+19,40 135
+19,49 135
+19,49 136
+51,62 135
+1,63 135
+1,63 135
+169.5,16 137
+170.2,35 138
+171.2,38 139
+13,17 139
+19,25 139
+27,37 139
+2,38 139
+2,38 139
+2,38 140
+173.1,5 141
+178.25,36 142
+1,36 142
+1,36 143
+179.1,26 144
+181.1,38 145
+18,25 145
+27,37 145
+1,38 145
+1,38 145
+182.5,15 146
+183.10,13 147
+15,18 147
+20,62 147
+32,52 147
+54,61 147
+20,62 147
+20,62 147
+2,63 147
+184.1,39 148
+18,25 148
+27,38 148
+1,39 148
+1,39 148
+185.5,15 149
+186.10,13 150
+15,18 150
+20,63 150
+32,53 150
+55,62 150
+20,63 150
+20,63 150
+2,64 150
+187.1,40 151
+20,26 151
+28,39 151
+1,40 151
+1,40 151
+188.5,17 152
+189.10,13 153
+15,18 153
+20,61 153
+32,52 153
+54,60 153
+20,61 153
+20,61 153
+2,62 153
+191.1,199.2 154
+192.2,9 154
+2,9 154
+193.2,6 154
+2,6 154
+194.2,6 154
+2,6 154
+195.2,6 154
+2,6 154
+196.2,6 154
+2,6 154
+197.2,6 154
+2,6 154
+198.2,6 154
+2,6 154
+201.6,12 155
+18,28 156
+14,28 156
+202.23,32 157
+2,32 157
+203.6,37 158
+17,22 158
+24,27 158
+29,36 158
+6,37 158
+6,37 158
+6,42 158
+204.11,14 159
+16,19 159
+21,69 159
+33,57 159
+59,68 159
+59,68 159
+21,69 159
+21,69 159
+3,70 159
+3,70 160
+201.30,33 161
+30,33 161
+206.9,12 162
+14,17 162
+19,22 162
+1,23 162
+215.1,25 163
+217.2,34 164
+17,19 164
+21,24 164
+26,33 164
+2,34 164
+2,34 164
+218.6,12 165
+6,12 166
+219.3,8 167
+220.2,27 168
+221.13,16 169
+13,21 169
+2,21 169
+2,21 170
+222.2,15 171
+2,15 172
+2,15 172
+224.1,13 173
+225.0,1 174
+231.1,24 175
+232.1,9 176
+233.5,19 177
+234.10,21 178
+6,21 178
+235.13,20 179
+13,25 179
+3,25 179
+3,25 180
+236.3,24 181
+3,24 181
+237.10,13 182
+3,13 182
+239.2,19 183
+240.9,20 184
+2,20 184
+241.2,15 185
+243.1,26 186
+20,22 186
+24,25 186
+1,26 186
+1,26 186
+245.8,15 187
+246.2,13 188
+2,5 188
+2,13 188
+248.14,20 189
+14,20 189
+258.6,14 189
+6,14 189
+247.2,8 189
+2,8 189
+2,8 189
+2,8 189
+249.8,19 190
+8,19 191
+250.5,10 192
+251.4,20 193
+252.15,22 194
+8,22 194
+253.5,19 195
+254.5,26 196
+15,19 196
+5,26 196
+256.16,20 197
+16,28 197
+4,28 197
+4,28 198
+257.4,15 199
+4,15 200
+4,15 189
+260.4,9 201
+263.1,14 202
+1,4 202
+1,14 202
+264.5,13 203
+265.9,12 204
+2,12 204
+266.8,11 205
+8,18 205
+1,18 205
+271.8,25 206
+15,18 206
+20,24 206
+8,25 206
+8,25 206
+8,32 206
+8,32 207
+8,32 207
+273.0,1 208
+280.1,12 209
+281.1,34 210
+26,30 210
+32,33 210
+1,34 210
+1,34 210
+282.1,16 211
+283.1,27 212
+20,23 212
+25,26 212
+1,27 212
+1,27 212
+286.25,28 213
+289.12,16 214
+12,16 214
+291.5,13 214
+5,13 214
+293.5,19 214
+5,19 214
+288.2,8 214
+2,8 214
+2,8 214
+2,8 214
+2,8 214
+292.3,13 215
+3,13 214
+294.3,17 216
+3,17 217
+295.3,11 218
+298.2,17 219
+299.9,24 220
+301.29,69 221
+38,40 221
+42,50 221
+42,50 221
+52,56 221
+58,68 221
+29,69 221
+29,69 221
+4,9 221
+11,15 221
+17,25 221
+17,25 222
+17,25 223
+302.3,17 224
+303.3,20 225
+3,12 225
+3,20 225
+304.7,22 226
+305.0,50 227
+11,39 227
+41,49 227
+0,50 227
+0,50 227
+306.4,17 228
+4,7 228
+4,17 228
+307.4,17 229
+308.4,10 230
+310.7,19 231
+311.4,19 232
+313.7,22 233
+316.14,18 234
+14,18 234
+315.4,10 234
+4,10 234
+4,10 234
+4,10 234
+4,10 234
+319.6,16 235
+6,16 234
+6,16 236
+6,16 236
+323.6,20 237
+324.3,14 238
+3,6 238
+3,14 238
+3,14 239
+326.3,15 240
+3,6 240
+3,15 240
+3,15 241
+3,15 241
+347.4,11 242
+348.1,59 243
+24,32 243
+24,32 243
+34,40 243
+34,40 243
+42,50 243
+42,50 243
+52,58 243
+52,58 243
+349.1,35 244
+12,16 244
+18,23 244
+25,34 244
+1,35 244
+1,35 244
+350.1,17 245
+8,11 245
+13,16 245
+1,17 245
+1,17 245
+1,17 246
+1,17 247
+352.1,20 248
+353.1,12 249
+354.5,16 250
+355.2,24 251
+19,23 251
+2,24 251
+2,24 251
+356.17,25 252
+6,14 252
+6,25 252
+357.3,13 253
+358.3,14 254
+3,14 255
+365.18,26 256
+1,26 256
+366.11,24 257
+1,28 257
+367.17,36 258
+1,45 258
+370.5,16 259
+371.2,10 260
+2,23 260
+2,23 261
+373.2,10 262
+2,23 262
+374.1,9 263
+1,18 263
+375.1,9 264
+1,18 264
+376.1,9 265
+17,33 265
+1,33 265
+377.1,9 266
+18,31 266
+17,40 266
+1,40 266
+380.1,9 267
+17,31 267
+1,31 267
+381.1,9 268
+18,27 268
+17,36 268
+1,36 268
+383.1,16 269
+384.5,16 270
+385.2,21 271
+386.5,11 272
+387.2,21 273
+389.1,9 274
+1,17 274
+392.1,17 275
+396.23,32 276
+22,37 276
+20,37 276
+1,37 276
+397.1,34 277
+399.1,11 278
+1,24 278
+400.1,11 279
+1,24 279
+401.1,11 280
+1,24 280
+402.1,15 281
+403.1,11 282
+404.6,12 283
+18,27 284
+14,27 284
+405.7,15 285
+2,15 285
+406.10,16 286
+10,16 286
+2,17 286
+2,21 286
+407.10,16 287
+10,16 287
+2,17 287
+2,22 287
+408.11,16 288
+2,16 288
+404.29,32 289
+29,32 289
+410.9,15 290
+9,15 290
+1,16 290
+24,39 290
+1,39 290
+411.9,15 291
+9,15 291
+1,16 291
+25,31 291
+24,40 291
+1,40 291
+416.6,14 292
+16,23 293
+417.6,16 294
+418.3,48 295
+14,37 295
+39,42 295
+44,47 295
+3,48 295
+3,48 295
+419.2,10 296
+420.2,11 297
+421.7,12 298
+14,24 299
+28,38 299
+422.7,15 300
+7,24 300
+423.4,20 301
+424.7,48 302
+18,22 302
+34,40 302
+24,31 302
+24,41 302
+43,47 302
+7,48 302
+7,48 302
+7,56 302
+425.12,15 303
+17,18 303
+20,28 303
+4,29 303
+429.3,28 304
+18,21 304
+23,27 304
+3,28 304
+3,28 304
+430.7,19 305
+23,32 305
+23,40 305
+432.4,32 306
+435.8,15 307
+17,27 308
+31,40 308
+436.29,33 309
+21,34 309
+21,34 309
+8,17 309
+8,34 309
+438.5,31 310
+435.42,46 311
+42,46 311
+421.40,49 312
+40,49 312
+441.6,16 313
+442.3,12 314
+3,12 314
+3,12 315
+443.3,11 316
+447.2,41 317
+448.2,29 318
+17,20 318
+22,28 318
+2,29 318
+2,29 318
+449.6,18 319
+22,31 319
+22,41 319
+450.3,31 320
+451.3,12 321
+3,12 321
+3,12 322
+452.3,11 323
+454.6,14 324
+6,28 324
+32,40 324
+32,54 324
+58,66 324
+58,76 324
+455.18,26 324
+17,26 324
+5,13 324
+5,26 324
+43,51 324
+42,51 324
+30,38 324
+30,51 324
+456.3,31 325
+457.3,12 326
+3,12 326
+3,12 327
+458.3,11 328
+462.15,23 329
+11,23 329
+32,40 329
+27,41 329
+26,47 329
+11,47 329
+2,51 329
+463.14,22 330
+10,22 330
+29,37 330
+25,37 330
+10,37 330
+44,52 330
+40,52 330
+2,52 330
+464.2,33 331
+17,20 331
+22,32 331
+2,33 331
+2,33 331
+465.6,18 332
+35,45 332
+22,31 332
+22,45 332
+466.3,33 333
+467.3,12 334
+3,12 334
+3,12 335
+468.3,11 336
+470.15,23 337
+11,23 337
+2,23 337
+471.7,12 338
+14,24 339
+472.3,11 340
+20,23 340
+14,24 340
+3,24 340
+473.16,24 341
+12,24 341
+3,24 341
+471.26,29 342
+26,29 342
+475.21,29 343
+15,30 343
+11,30 343
+2,30 343
+476.30,45 344
+25,45 344
+12,20 344
+6,21 344
+6,45 344
+477.3,34 345
+478.3,12 346
+3,12 346
+3,12 347
+479.3,11 348
+481.34,46 349
+29,46 349
+7,15 349
+6,25 349
+6,46 349
+484.3,32 350
+3,32 351
+485.3,11 352
+490.15,23 353
+2,23 353
+491.2,29 354
+492.6,16 355
+494.7,26 356
+7,26 356
+495.4,39 357
+29,37 357
+21,26 357
+21,38 357
+4,39 357
+4,39 357
+496.8,20 358
+497.5,38 359
+5,38 360
+498.5,13 361
+501.19,29 362
+4,38 362
+502.24,32 363
+16,21 363
+16,33 363
+4,33 363
+4,33 364
+505.10,15 365
+17,21 365
+23,26 365
+2,27 365
+416.25,30 366
+25,30 366
+507.9,12 367
+14,15 367
+17,20 367
+1,21 367
+513.1,11 368
+514.1,11 369
+515.1,26 370
+516.1,9 371
+517.1,14 372
+518.1,8 373
+520.16,24 374
+8,24 374
+28,41 374
+521.6,19 375
+522.3,16 376
+523.3,15 377
+3,15 378
+525.13,24 379
+3,24 379
+526.7,19 380
+527.4,15 381
+528.7,15 382
+529.4,8 383
+530.4,11 384
+531.16,24 385
+8,24 385
+28,42 385
+532.5,13 386
+534.8,10 387
+8,10 387
+8,10 387
+536.4,11 388
+4,11 387
+538.4,11 389
+539.4,16 390
+540.4,10 391
+4,10 387
+542.4,11 392
+543.4,15 393
+544.4,10 394
+4,10 387
+546.4,15 395
+547.4,20 396
+548.4,10 397
+4,10 387
+551.15,22 398
+6,22 398
+552.24,31 399
+20,31 399
+3,40 399
+553.3,19 400
+554.3,15 401
+3,15 402
+556.6,13 403
+6,13 403
+2,14 403
+2,25 403
+2,25 403
+558.8,11 404
+8,20 404
+1,20 404
+563.1,11 405
+564.1,11 406
+565.1,26 407
+567.1,8 408
+568.1,9 409
+569.16,24 410
+8,24 410
+28,34 410
+570.6,12 411
+571.3,7 412
+3,7 413
+573.18,25 414
+18,25 414
+13,26 414
+3,26 414
+574.7,19 415
+575.17,25 416
+8,25 416
+577.12,15 417
+5,15 417
+578.18,25 418
+18,25 418
+13,26 418
+4,26 418
+579.8,14 419
+580.5,12 420
+581.5,12 421
+582.5,13 422
+586.15,22 423
+6,22 423
+587.24,31 424
+20,31 424
+3,40 424
+588.3,19 425
+589.3,15 426
+3,15 427
+591.6,13 428
+6,13 428
+2,14 428
+2,25 428
+2,25 428
+593.8,11 429
+8,20 429
+1,20 429
+16
+aSys->Dir 1:26.1,39.2 64
+11
+0:name:28.2,6 s
+4:uid:29.2,5 s
+8:gid:30.2,5 s
+12:muid:31.2,6 s
+16:qid:32.2,5 @1
+
+32:mode:33.2,6 i
+36:atime:34.2,7 i
+40:mtime:35.2,7 i
+48:length:36.2,8 B
+56:dtype:37.2,7 i
+60:dev:38.2,5 i
+aSys->Qid 11.1,16.2 16
+3
+0:path:13.2,6 B
+8:vers:14.2,6 i
+12:qtype:15.2,7 i
+aDraw->Chans 2:70.1,82.2 4
+1
+0:desc:72.2,6 i
+aDraw->Context 274.1,279.2 12
+3
+0:display:276.2,9 R@4
+
+4:screen:277.2,8 R@8
+
+8:wm:278.2,4 Ct8.2
+0:t0:15,21 s
+4:t1:15,21 Ct8.2
+0:t0:32,38 s
+4:t1:32,38 R@9
+
+
+
+aDraw->Display 201.1,230.2 20
+5
+0:image:203.2,7 R@5
+
+4:white:204.2,7 R@5
+
+8:black:205.2,7 R@5
+
+12:opaque:206.2,8 R@5
+
+16:transparent:207.2,13 R@5
+
+aDraw->Image 142.1,198.2 56
+8
+0:r:146.2,3 @6
+
+16:clipr:147.2,7 @6
+
+32:depth:148.2,7 i
+36:chans:149.2,7 @2
+
+40:repl:150.2,6 i
+44:display:151.2,9 R@4
+
+48:screen:152.2,8 R@8
+
+52:iname:153.2,7 s
+aDraw->Rect 116.1,139.2 16
+2
+0:min:118.2,5 @7
+
+8:max:119.2,5 @7
+
+aDraw->Point 99.1,113.2 8
+2
+0:x:101.2,3 i
+4:y:102.2,3 i
+aDraw->Screen 249.1,263.2 16
+4
+0:id:251.2,4 i
+4:image:252.2,7 R@5
+
+8:fill:253.2,6 R@5
+
+12:display:254.2,9 R@4
+
+aDraw->Wmcontext 282.1,291.2 28
+7
+0:kbd:284.2,5 Ci
+4:ptr:285.2,5 CR@10
+
+8:ctl:286.2,5 Cs
+12:wctl:287.2,6 Cs
+16:images:288.2,8 CR@5
+
+20:connfd:289.2,8 R@11
+
+24:ctxt:290.2,6 R@3
+
+aDraw->Pointer 266.1,271.2 16
+3
+0:buttons:268.2,9 i
+4:xy:269.2,4 @7
+
+12:msec:270.2,6 i
+aSys->FD 1:45.1,48.2 4
+1
+0:fd:47.2,4 i
+aSys->FileIO 65.1,69.2 8
+2
+0:read:67.2,6 Ct16.4
+0:t0:17,20 i
+4:t1:17,20 i
+8:t2:17,20 i
+12:t3:17,20 @13
+
+
+4:write:68.2,7 Ct16.4
+0:t0:18,21 i
+4:t1:18,21 Ab
+8:t2:18,21 i
+12:t3:18,21 @14
+
+
+Ct8.2
+0:t0:63.22,35 Ab
+4:t1:22,35 s
+Ct8.2
+0:t0:64.23,26 i
+4:t1:23,26 s
+aTimers->Timer 3:2.1,9.2 8
+2
+0:id:3.2,4 i
+4:tick:4.2,6 Ci
+12
+0:error
+1
+32:msg:0:22.6,9 s
+0
+n12:init
+1
+36:argv:28.30,34 Ls
+7
+40:f2c:50.1,4 R@12
+
+44:recv:56.1,5 CAb
+48:send:55.1,5 CAb
+52:portnum:41.1,8 i
+56:rdfd:42.2,6 R@11
+
+60:wrfd:8,12 R@11
+
+64:err:14,17 s
+n97:srvlink
+3
+32:f2c:64.8,11 R@12
+
+36:send:31,35 CAb
+40:recv:37,41 CAb
+24
+44:bix:70.1,4 i
+48:buffer:69.1,7 Ab
+52:data:82.1,5 Ab
+56:rdfid:67.1,6 i
+60:wrfid:68.1,6 i
+64:wrreply:76.1,8 @14
+
+68:me:66.1,3 i
+72:readreq:73.1,8 Ct16.4
+0:t0:72.19,22 i
+4:t1:19,22 i
+8:t2:19,22 i
+12:t3:19,22 @13
+
+
+76:sendchan:78.1,9 CAb
+80:writereq:75.1,9 Ct16.4
+0:t0:1:68.18,21 i
+4:t1:18,21 Ab
+8:t2:18,21 i
+12:t3:18,21 @14
+
+
+84:newb:0:92.3,7 Ab
+88:rdata:119.2,7 Ab
+92:rdblk:72.1,6 Ct16.4
+0:t0:19,22 i
+4:t1:19,22 i
+8:t2:19,22 i
+12:t3:19,22 @13
+
+
+96:sendblk:77.1,8 CAb
+100:senddata:79.1,9 Ab
+104:wrblk:74.1,6 Ct16.4
+0:t0:19,22 i
+4:t1:19,22 Ab
+8:t2:19,22 i
+12:t3:19,22 @14
+
+
+120:offset:100.2,8 i
+124:count:10,15 i
+128:fid:17,20 i
+132:rc:22,24 @13
+
+136:offset:132.2,8 i
+140:data:10,14 Ab
+144:fid:16,19 i
+148:wc:21,23 @14
+
+n265:killgrp
+1
+32:pid:166.8,11 i
+2
+36:pctl:168.1,5 R@11
+
+40:poison:170.2,8 Ab
+n283:serialport
+1
+32:port:176.11,15 i
+8
+36:serport:178.1,8 s
+40:i:201.6,7 i
+44:config:191.1,7 As
+48:cmd:202.2,5 Ab
+52:ctlfd:187.1,6 R@11
+
+56:rfd:181.1,4 R@11
+
+60:serctl:179.1,7 s
+64:wfd:184.1,4 R@11
+
+t12.3
+0:t0:176.26,37 R@11
+
+4:t1:26,37 R@11
+
+8:t2:26,37 s
+372:reader
+2
+32:fd:210.7,9 R@11
+
+36:out:25,28 CAb
+3
+40:buf:215.1,4 Ab
+44:n:217.2,3 i
+48:data:220.2,6 Ab
+n392:nbread
+2
+32:ms:229.7,9 i
+36:n:11,12 i
+5
+40:tot:232.1,4 i
+44:dlen:251.4,8 i
+48:ret:231.1,4 Ab
+52:data:248.3,7 Ab
+56:tmr:243.1,4 R@15
+
+Ab453:consume
+0
+0
+n462:protocol
+3
+32:fd:278.9,11 R@11
+
+36:send:27,31 CAb
+40:recv:33,37 CAb
+7
+44:data:286.2,6 Ab
+48:poll:298.2,6 i
+52:tmr:283.1,4 R@15
+
+56:starttower:282.1,11 i
+60:reply:300.3,8 Ab
+64:towerdown:281.1,10 R@15
+
+68:seqnum:280.1,7 i
+n545:datasend
+4
+32:wrfd:345.9,13 R@11
+
+36:seqnum:29,35 i
+40:data:43,47 Ab
+44:startup:65,72 i
+22
+48:b:405.2,3 b
+49:lhval:383.1,6 b
+52:reply:415.1,6 Ab
+56:i:404.6,7 i
+60:err:414.1,4 s
+64:ldata:367.1,6 Ab
+68:rcxdata:397.1,8 Ab
+72:step:420.2,6 i
+76:cksum:403.1,6 i
+80:ei:435.8,10 i
+84:mdata:489.2,7 Ab
+88:rcix:402.1,5 i
+92:rcxlen:396.1,7 i
+96:blklen:366.1,7 i
+100:llen:365.1,5 i
+104:try:416.6,9 i
+108:comp:355.2,6 Ab
+112:docomp:353.1,7 i
+116:dummy:348.1,6 Ab
+120:lnhdr:490.2,7 i
+124:poll:491.2,6 i
+80:replen:447.2,8 i
+t12.3
+0:t0:345.83,96 Ab
+4:t1:83,96 i
+8:t2:83,96 s
+848:rlencode
+1
+32:data:511.9,13 Ab
+7
+36:nextval:517.1,8 i
+40:val:516.1,4 i
+44:n0:518.1,3 i
+48:out:515.1,4 Ab
+52:srcix:513.1,6 i
+56:outix:514.1,6 i
+60:newout:552.3,9 Ab
+Ab905:rldecode
+1
+32:data:561.9,13 Ab
+6
+36:n0:567.1,3 i
+40:out:565.1,4 Ab
+44:srcix:563.1,6 i
+48:val:568.1,4 i
+52:outix:564.1,6 i
+56:newout:587.3,9 Ab
+Ab5
+196:datain:19.0,6 CAb
+200:errormsg:20.0,8 s
+240:overrun:227.0,7 Ab
+272:sys:16.0,3 mSys
+1:4.0,160.1 0
+
+276:timers:0:17.0,6 mTimers
+3:1.0,13.1 0
+
diff --git a/appl/demo/lego/mkfile b/appl/demo/lego/mkfile
new file mode 100644
index 00000000..3ae4e898
--- /dev/null
+++ b/appl/demo/lego/mkfile
@@ -0,0 +1,36 @@
+<../../../mkconfig
+
+TARG=\
+ clockface.dis\
+ firmdl.dis\
+ legolink.dis\
+ rcxsend.dis\
+ timers.dis\
+ styx.srec\
+
+SHTARG=\
+ clockreg.sh\
+
+MODULES=\
+ rcxsend.m\
+
+SYSMODULES= \
+ bufio.m\
+ draw.m\
+ sys.m\
+ timers.m\
+
+DISBIN=$ROOT/dis/demo/lego
+
+<$ROOT/mkfiles/mkdis
+
+$DISBIN/%.srec: %.srec
+ rm -f $target && cp $stem.srec $target
+
+SHFILES=${SHTARG:%.sh=$DISBIN/%}
+install:V: $SHFILES
+%.install:V: $DISBIN/%
+%.installall:V: $DISBIN/%
+
+$DISBIN/%: %.sh
+ cp $stem.sh $target && chmod a+rx $target
diff --git a/appl/demo/lego/rcxsend.b b/appl/demo/lego/rcxsend.b
new file mode 100644
index 00000000..5896f09b
--- /dev/null
+++ b/appl/demo/lego/rcxsend.b
@@ -0,0 +1,240 @@
+implement RcxSend;
+
+include "sys.m";
+include "timers.m";
+include "rcxsend.m";
+
+sys : Sys;
+timers : Timers;
+Timer : import timers;
+datain : chan of array of byte;
+debug : int;
+rpid : int;
+wrfd : ref Sys->FD;
+
+TX_HDR : con 3;
+TX_CKSM : con 2;
+
+init(portnum, dbg : int) : string
+{
+ debug = dbg;
+ sys = load Sys Sys->PATH;
+ timers = load Timers "timers.dis";
+ if (timers == nil)
+ return sys->sprint("cannot load timer module: %r");
+
+ rdfd : ref Sys->FD;
+ err : string;
+ (rdfd, wrfd, err) = serialport(portnum);
+ if (err != nil)
+ return err;
+
+ timers->init(50);
+ pidc := chan of int;
+ datain = chan of array of byte;
+ spawn reader(pidc, rdfd, datain);
+ rpid = <- pidc;
+ consume();
+ return nil;
+}
+
+reader(pidc : chan of int, fd : ref Sys->FD, out : chan of array of byte)
+{
+ pidc <- = sys->pctl(0, nil);
+
+ # with buf size of 1 there is no need
+ # for overrun code in nbread()
+
+ buf := array [1] of byte;
+ for (;;) {
+ n := sys->read(fd, buf, len buf);
+ if (n <= 0)
+ break;
+ data := array [n] of byte;
+ data[0:] = buf[0:n];
+ out <- = data;
+ }
+ if (debug)
+ sys->print("Reader error\n");
+}
+
+send(data : array of byte, n, rlen: int) : array of byte
+{
+ # 16r55 16rff 16r00 (d[i] ~d[i])*n cksum ~cksum
+ obuf := array [TX_HDR + (2*n ) + TX_CKSM] of byte;
+ olen := 0;
+ obuf[olen++] = byte 16r55;
+ obuf[olen++] = byte 16rff;
+ obuf[olen++] = byte 16r00;
+ cksum := 0;
+ for (i := 0; i < n; i++) {
+ obuf[olen++] = data[i];
+ obuf[olen++] = ~data[i];
+ cksum += int data[i];
+ }
+ obuf[olen++] = byte (cksum & 16rff);
+ obuf[olen++] = byte (~cksum & 16rff);
+
+ needr := rlen;
+ if (rlen > 0)
+ needr = TX_HDR + (2 * rlen) + TX_CKSM;
+ for (try := 0; try < 5; try++) {
+ ok := 1;
+ err := "";
+ reply : array of byte;
+
+ step := 8;
+ for (i = 0; ok && i < olen; i += step) {
+ if (i + step > olen)
+ step = olen -i;
+ if (sys->write(wrfd, obuf[i:i+step], step) != step) {
+ if (debug)
+ sys->print("serial tx error: %r\n");
+ return nil;
+ }
+
+ # get the echo
+ reply = nbread(200, step);
+ if (reply == nil || len reply != step) {
+ err = "short echo";
+ ok = 0;
+ }
+
+ # check the echo
+ for (ei := 0; ok && ei < step; ei++) {
+ if (reply[ei] != obuf[i+ei]) {
+ err = "bad echo";
+ ok = 0;
+ }
+ }
+ }
+
+ # get the reply
+ if (ok) {
+ if (needr == 0)
+ return nil;
+ if (needr == -1) {
+ # just get what we can
+ needr = TX_HDR + TX_CKSM;
+ reply = nbread(300, 1024);
+ } else {
+ reply = nbread(200, needr);
+ }
+ if (len reply < needr) {
+ err = "short reply";
+ ok = 0;
+ }
+ }
+ # check the reply
+ if (ok && reply[0] == byte 16r55 && reply[1] == byte 16rff && reply[2] == byte 0) {
+ cksum := int reply[len reply -TX_CKSM];
+ val := reply[TX_HDR:len reply -TX_CKSM];
+ r := array [len val / 2] of byte;
+ sum := 0;
+ for (i = 0; i < len r; i++) {
+ r[i] = val[i*2];
+ sum += int r[i];
+ }
+ if (cksum == (sum & 16rff)) {
+ return r;
+ }
+ ok = 0;
+ err = "bad cksum";
+ } else if (ok) {
+ ok = 0;
+ err = "reply header error";
+ }
+ if (debug && ok == 0 && err != nil) {
+ sys->print("try %d %s: ", try, err);
+ hexdump(reply);
+ }
+ consume();
+ }
+ return nil;
+}
+
+overrun : array of byte;
+
+nbread(ms, n : int) : array of byte
+{
+ ret := array[n] of byte;
+ tot := 0;
+ if (overrun != nil) {
+ if (n < len overrun) {
+ ret[0:] = overrun[0:n];
+ overrun = overrun[n:];
+ return ret;
+ }
+ ret[0:] = overrun;
+ tot += len overrun;
+ overrun = nil;
+ }
+ tmr := timers->new(ms, 0);
+loop:
+ while (tot < n) {
+ tmr.reset();
+ alt {
+ data := <- datain =>
+ dlen := len data;
+ if (dlen > n - tot) {
+ dlen = n - tot;
+ overrun = data[dlen:];
+ }
+ ret[tot:] = data[0:dlen];
+ tot += dlen;
+ <- tmr.tick =>
+ # reply timeout;
+ break loop;
+ }
+ }
+ tmr.destroy();
+ if (tot == 0)
+ return nil;
+ return ret[0:tot];
+}
+
+consume()
+{
+ while (nbread(300, 1024) != nil)
+ ;
+}
+
+serialport(port : int) : (ref Sys->FD, ref Sys->FD, string)
+{
+ serport := "/dev/eia" + string port;
+ serctl := serport + "ctl";
+
+ rfd := sys->open(serport, Sys->OREAD);
+ if (rfd == nil)
+ return (nil, nil, sys->sprint("cannot read %s: %r", serport));
+ wfd := sys->open(serport, Sys->OWRITE);
+ if (wfd == nil)
+ return (nil, nil, sys->sprint("cannot write %s: %r", serport));
+ ctlfd := sys->open(serctl, Sys->OWRITE);
+ if (ctlfd == nil)
+ return (nil, nil, sys->sprint("cannot open %s: %r", serctl));
+
+ config := array [] of {
+ "b2400",
+ "l8",
+ "po",
+ "m0",
+ "s1",
+ "d1",
+ "r1",
+ };
+
+ for (i := 0; i < len config; i++) {
+ cmd := array of byte config[i];
+ if (sys->write(ctlfd, cmd, len cmd) <= 0)
+ return (nil, nil, sys->sprint("serial config (%s): %r", config[i]));
+ }
+ return (rfd, wfd, nil);
+}
+hexdump(data : array of byte)
+{
+ for (i := 0; i < len data; i++)
+ sys->print("%.2x ", int data[i]);
+ sys->print("\n");
+}
+
diff --git a/appl/demo/lego/rcxsend.dis b/appl/demo/lego/rcxsend.dis
new file mode 100644
index 00000000..cf718cce
--- /dev/null
+++ b/appl/demo/lego/rcxsend.dis
Binary files differ
diff --git a/appl/demo/lego/rcxsend.m b/appl/demo/lego/rcxsend.m
new file mode 100644
index 00000000..f597ea1f
--- /dev/null
+++ b/appl/demo/lego/rcxsend.m
@@ -0,0 +1,4 @@
+RcxSend : module {
+ init: fn (pnum, dbg : int) : string;
+ send : fn (data : array of byte, slen, rlen : int) : array of byte;
+}; \ No newline at end of file
diff --git a/appl/demo/lego/rcxsend.sbl b/appl/demo/lego/rcxsend.sbl
new file mode 100644
index 00000000..34d1dc97
--- /dev/null
+++ b/appl/demo/lego/rcxsend.sbl
@@ -0,0 +1,552 @@
+limbo .sbl 2.1
+RcxSend
+4
+rcxsend.b
+sys.m
+timers.m
+rcxsend.m
+423
+20.1,12 0
+21.1,25 1
+22.1,34 2
+23.5,18 3
+24.10,53 4
+22,52 4
+10,53 4
+10,53 4
+3,53 4
+28.21,40 5
+32,39 5
+21,40 5
+21,40 5
+2,6 5
+8,12 5
+14,17 5
+14,17 6
+14,17 7
+14,17 8
+29.5,15 9
+30.9,12 10
+2,12 10
+32.1,17 11
+14,16 11
+1,17 11
+33.1,20 12
+34.1,31 13
+35.1,33 14
+14,18 14
+20,24 14
+26,32 14
+1,33 14
+36.1,15 15
+37.1,10 16
+1,10 16
+38.8,11 17
+1,11 17
+43.11,28 18
+21,22 18
+24,27 18
+11,28 18
+11,28 18
+1,28 18
+48.1,25 19
+50.2,34 20
+17,19 20
+21,24 20
+26,33 20
+2,34 20
+2,34 20
+51.6,12 21
+6,12 22
+52.3,8 23
+53.2,27 24
+54.13,16 25
+13,21 25
+2,21 25
+2,21 26
+55.2,15 27
+2,15 28
+2,15 28
+57.5,10 29
+58.2,30 30
+13,29 30
+2,30 30
+2,30 30
+59.0,1 31
+64.25,31 32
+16,41 32
+1,50 32
+65.1,10 33
+66.6,12 34
+6,12 34
+1,13 34
+1,26 34
+67.6,12 35
+6,12 35
+1,13 35
+1,26 35
+68.6,12 36
+6,12 36
+1,13 36
+1,26 36
+69.1,11 37
+70.6,12 38
+14,19 39
+71.7,13 40
+7,13 40
+2,14 40
+17,24 40
+2,24 40
+72.7,13 41
+7,13 41
+2,14 41
+18,25 41
+2,25 41
+73.15,22 42
+11,22 42
+2,22 42
+70.21,24 43
+21,24 43
+75.6,12 44
+6,12 44
+1,13 44
+21,36 44
+1,36 44
+76.6,12 45
+6,12 45
+1,13 45
+22,28 45
+21,37 45
+1,37 45
+78.1,14 46
+79.5,13 47
+80.19,29 48
+2,39 48
+81.6,14 49
+16,23 50
+82.2,9 51
+83.2,11 52
+86.2,11 53
+87.7,12 54
+14,16 55
+20,28 55
+88.7,15 56
+7,22 56
+89.4,18 57
+90.7,45 58
+18,22 58
+31,37 58
+24,28 58
+24,38 58
+40,44 58
+7,45 58
+7,45 58
+7,53 58
+91.8,13 59
+92.5,40 60
+16,39 60
+5,40 60
+5,40 60
+93.11,14 61
+4,14 61
+97.3,28 62
+18,21 62
+23,27 62
+3,28 62
+3,28 62
+98.7,19 63
+23,32 63
+23,40 63
+99.4,22 64
+100.4,10 65
+104.8,15 66
+17,19 67
+23,32 67
+105.26,30 68
+21,31 68
+21,31 68
+8,17 68
+8,31 68
+106.5,21 69
+107.5,11 70
+104.34,38 71
+34,38 71
+87.30,39 72
+30,39 72
+113.6,8 73
+114.7,17 74
+115.11,14 75
+4,14 75
+116.7,18 76
+118.4,28 77
+119.4,29 78
+19,22 78
+24,28 78
+4,29 78
+4,29 78
+4,29 79
+121.4,30 80
+19,22 80
+24,29 80
+4,30 80
+4,30 80
+123.7,16 81
+7,24 81
+124.4,23 82
+125.4,10 83
+129.6,8 84
+12,20 84
+12,34 84
+38,46 84
+38,60 84
+64,72 84
+64,82 84
+130.22,31 85
+22,40 85
+16,41 85
+3,41 85
+131.23,32 86
+23,41 86
+10,15 86
+3,42 86
+132.15,22 87
+15,26 87
+3,35 87
+133.3,11 88
+134.8,13 89
+19,24 90
+15,24 90
+135.4,8 91
+15,18 91
+11,19 91
+4,19 91
+136.15,19 92
+11,19 92
+4,19 92
+134.26,29 93
+26,29 93
+138.16,29 94
+7,29 94
+139.11,12 95
+4,12 95
+141.3,9 96
+142.3,20 97
+3,20 98
+3,20 99
+3,20 100
+143.13,15 101
+144.3,9 102
+145.3,29 103
+147.6,11 104
+15,22 104
+26,36 104
+148.3,38 105
+14,27 105
+29,32 105
+34,37 105
+3,38 105
+3,38 105
+149.3,17 106
+11,16 106
+3,17 106
+151.2,11 107
+2,11 107
+2,11 108
+2,11 109
+81.25,30 110
+25,30 110
+153.8,11 111
+1,11 111
+160.1,24 112
+161.1,9 113
+162.5,19 114
+163.10,21 115
+6,21 115
+164.13,20 116
+13,25 116
+3,25 116
+3,25 117
+165.3,24 118
+3,24 118
+166.10,13 119
+3,13 119
+168.2,19 120
+169.9,20 121
+2,20 121
+170.2,15 122
+172.1,26 123
+20,22 123
+24,25 123
+1,26 123
+1,26 123
+174.8,15 124
+175.2,13 125
+2,5 125
+2,13 125
+177.14,20 126
+14,20 126
+185.6,14 126
+6,14 126
+176.2,8 126
+2,8 126
+2,8 126
+2,8 126
+178.4,20 127
+179.15,22 128
+8,22 128
+180.5,19 129
+181.5,26 130
+15,19 130
+5,26 130
+183.16,20 131
+16,28 131
+4,28 131
+4,28 132
+184.4,15 133
+4,15 134
+4,15 126
+187.4,9 135
+190.1,14 136
+1,4 136
+1,14 136
+191.5,13 137
+192.9,12 138
+2,12 138
+193.8,11 139
+8,18 139
+1,18 139
+198.8,25 140
+15,18 140
+20,24 140
+8,25 140
+8,25 140
+8,32 140
+8,32 141
+8,32 141
+200.0,1 142
+204.25,36 143
+1,36 143
+1,36 144
+205.1,26 145
+207.1,38 146
+18,25 146
+27,37 146
+1,38 146
+1,38 146
+208.5,15 147
+209.10,13 148
+15,18 148
+20,62 148
+32,52 148
+54,61 148
+20,62 148
+20,62 148
+2,63 148
+210.1,39 149
+18,25 149
+27,38 149
+1,39 149
+1,39 149
+211.5,15 150
+212.10,13 151
+15,18 151
+20,63 151
+32,53 151
+55,62 151
+20,63 151
+20,63 151
+2,64 151
+213.1,40 152
+20,26 152
+28,39 152
+1,40 152
+1,40 152
+214.5,17 153
+215.10,13 154
+15,18 154
+20,61 154
+32,52 154
+54,60 154
+20,61 154
+20,61 154
+2,62 154
+217.1,225.2 155
+218.2,9 155
+2,9 155
+219.2,6 155
+2,6 155
+220.2,6 155
+2,6 155
+221.2,6 155
+2,6 155
+222.2,6 155
+2,6 155
+223.2,6 155
+2,6 155
+224.2,6 155
+2,6 155
+227.6,12 156
+18,28 157
+14,28 157
+228.23,32 158
+2,32 158
+229.6,37 159
+17,22 159
+24,27 159
+29,36 159
+6,37 159
+6,37 159
+6,42 159
+230.11,14 160
+16,19 160
+21,69 160
+33,57 160
+59,68 160
+59,68 160
+21,69 160
+21,69 160
+3,70 160
+3,70 161
+227.30,33 162
+30,33 162
+232.9,12 163
+14,17 163
+19,22 163
+1,23 163
+236.6,12 164
+18,26 165
+14,26 165
+237.2,34 166
+13,20 166
+26,33 166
+22,33 166
+2,34 166
+2,34 166
+236.28,31 167
+28,31 167
+238.1,17 168
+12,16 168
+1,17 168
+1,17 168
+239.0,1 169
+4
+aSys->Dir 1:26.1,39.2 64
+11
+0:name:28.2,6 s
+4:uid:29.2,5 s
+8:gid:30.2,5 s
+12:muid:31.2,6 s
+16:qid:32.2,5 @1
+
+32:mode:33.2,6 i
+36:atime:34.2,7 i
+40:mtime:35.2,7 i
+48:length:36.2,8 B
+56:dtype:37.2,7 i
+60:dev:38.2,5 i
+aSys->Qid 11.1,16.2 16
+3
+0:path:13.2,6 B
+8:vers:14.2,6 i
+12:qtype:15.2,7 i
+aSys->FD 45.1,48.2 4
+1
+0:fd:47.2,4 i
+aTimers->Timer 2:2.1,9.2 8
+2
+0:id:3.2,4 i
+4:tick:4.2,6 Ci
+7
+0:init
+2
+32:portnum:0:18.5,12 i
+36:dbg:14,17 i
+3
+40:err:27.1,4 s
+44:pidc:33.1,5 Ci
+48:rdfd:26.1,5 R@2
+
+s37:reader
+3
+32:pidc:41.7,11 Ci
+36:fd:27,29 R@2
+
+40:out:45,48 CAb
+3
+44:buf:48.1,4 Ab
+48:n:50.2,3 i
+52:data:53.2,6 Ab
+n67:send
+3
+32:data:61.5,9 Ab
+36:n:27,28 i
+40:rlen:30,34 i
+15
+48:i:70.6,7 i
+52:reply:84.2,7 Ab
+56:ok:82.2,4 i
+60:olen:65.1,5 i
+64:obuf:64.1,5 Ab
+68:step:86.2,6 i
+72:err:83.2,5 s
+76:needr:78.1,6 i
+80:ei:104.8,10 i
+84:r:132.3,4 Ab
+88:cksum:69.1,6 i
+92:try:81.6,9 i
+96:sum:133.3,6 i
+100:val:131.3,6 Ab
+80:cksum:130.3,8 i
+Ab251:nbread
+2
+32:ms:158.7,9 i
+36:n:11,12 i
+5
+40:tot:161.1,4 i
+44:dlen:178.4,8 i
+48:ret:160.1,4 Ab
+52:data:177.3,7 Ab
+56:tmr:172.1,4 R@3
+
+Ab309:consume
+0
+0
+n318:serialport
+1
+32:port:202.11,15 i
+8
+36:serport:204.1,8 s
+40:i:227.6,7 i
+44:config:217.1,7 As
+48:cmd:228.2,5 Ab
+52:ctlfd:213.1,6 R@2
+
+56:rfd:207.1,4 R@2
+
+60:serctl:205.1,7 s
+64:wfd:210.1,4 R@2
+
+t12.3
+0:t0:202.26,37 R@2
+
+4:t1:26,37 R@2
+
+8:t2:26,37 s
+407:hexdump
+1
+32:data:234.8,12 Ab
+1
+36:i:236.6,7 i
+n7
+72:datain:10.0,6 CAb
+76:debug:11.0,5 i
+92:overrun:156.0,7 Ab
+108:rpid:12.0,4 i
+132:sys:7.0,3 mSys
+1:4.0,160.1 0
+
+136:timers:0:8.0,6 mTimers
+2:1.0,13.1 0
+
+148:wrfd:0:0,4 R@2
+
diff --git a/appl/demo/lego/styx.srec b/appl/demo/lego/styx.srec
new file mode 100755
index 00000000..687a50aa
--- /dev/null
+++ b/appl/demo/lego/styx.srec
@@ -0,0 +1,329 @@
+S00C0000737479782E7372656340
+S11880006DF06DF16DF26DF35E00967E6D736D726D716D7054AD
+S118801570446F20796F7520627974652C207768656E20492057
+S10B802A6B6E6F636B3F0000F5
+S11880326DF60D761B870D621B8279014000790029F25E00965F
+S1188047AC6B039A0A6F62FFFE1D23470819226B829A084012E9
+S118805C6B039A08790200091D234E060B036B839A086F61FF76
+S1188071FE6B819A0A6B039A08790200097900FFFF1D234F02CC
+S11880860D100B876D7654706DF60D760D02790330026DF3790F
+S118809B01301F79001FF25E0096BC0B87790027C85E0096D480
+S11880B06D7654706DF60D766DF40D047901300679001B625EB4
+S11880C50096DE0D405E00808E5E0080320D0046F86D746D7656
+S11880DA54706DF60D766DF40D041900684B473C0D1147380B7A
+S11880EF040CBA8AD0AA09422E0CB8F00088D090FF1B01684BC7
+S118810447200D11471C0B040CBA8AD0AA0942120D0209220901
+S118811922092009000CBAF200092040D66D746D7654706DF617
+S118812E0D761B871B876DF46DF56FE0FFFE0D146FE0FFFC0DEA
+S1188143444C16FA2D688A6F62FFFE0D230B036FE3FFFC170CE8
+S118815817040B040D444610FA306F63FFFC68BA0B036FE3FFC5
+S118816DFC404C790527101D454F407901000A0D505E0096EA0C
+S11881820D051D454EF0402E0D510D405E0096EA0C8A8A306F7C
+S118819763FFFC68BA0B036FE3FFFC0D510D405E0096FC0D0448
+S11881AC7901000A0D505E0096EA0D050D5546CE6F62FFFC6F38
+S11881C163FFFE19326FE2FFFC6F60FFFC6D756D740B870B87FD
+S11881D66D7654706DF60D761B876DF46DF50D040D156FE2FF1B
+S11881EBFE7900000A5E00972269846F8500026F62FFFE6F8241
+S118820000046F6200046F82000619226F8200086A0AA40A8AB5
+S1188215016A8AA40A6D756D740B876D7654706DF60D765E006D
+S118822A979C6A0AA40A8AFF6A8AA40A6D7654706DF60D7669C5
+S118823F00790198885E008FD6790000016D7654706DF60D76C2
+S11882541B871B876DF46DF50D056FE1FFFE6FE2FFFC40266990
+S1188269546F61FFFC0D406F62FFFE5D200D00470E6F4200082A
+S118827E69D20D405E0082244006790500080945695246D66DFD
+S1188293756D740B870B876D7654706DF60D761B871B876DF426
+S11882A86DF56FE0FFFE6FE1FFFC19557904A3DC6F62FFFC6F1F
+S11882BD61FFFE0D405E0082508C0E94000B05790200021D25D0
+S11882D24FE46D756D740B870B876D7654706DF60D7679030070
+S11882E70C19376DF46DF56FE2FFFE6F6400040D1147045A0077
+S11882FC83FE6E080002F00088F990FF6FE0FFFC6F65FFFC094E
+S11883115509550955190509557902A3D009520D256F62FFFE7D
+S118832646045A0083FE684BF300790200621D23470C79020088
+S118833B6C1D23470A5A0083FE79020060400219226FE2FFF8B1
+S11883500B046F63FFFE1B030D3346045A0083FE684AAA3E46D3
+S118836504FA014006AA3C460C18AA6EEAFFFB0B041B034006FB
+S118837AFA016EEAFFFB0D3346045A0083FE7901823A0D50881D
+S118838F0C900019226FE3FFF45E0082506F62FFFC8A00921091
+S11883A46FE2FFF66F61FFF6790019C45E0096DEFA0168DA6EE2
+S11883B96AFFF96EDA00016F63FFF40D310D405E0080DC6FD0B7
+S11883CE000A19226FD200026FD200046EDA0006FA016EDA0038
+S11883E3086E6AFFFB6EDA00096F61FFF6790019465E0096DEE7
+S11883F86F60FFFE40047900FFFF6D756D747903000C09376DED
+S118840D7654706DF60D767903000619376DF46DF56FE0FFFE55
+S11884226FE1FFFC0D256F6400085E0090340D031D45443219C6
+S1188437546F6000041D0443046F6400046F62000609526FE243
+S118844C00060D300B800B000D426F6100066FE3FFFA5E0097D9
+S1188461AE6F63FFFA4002194468BC0D420C2A18226EBA0001DE
+S118847618AA6EBA00020B840B046DF419226DF26F62FFFC6F2D
+S118848B61FFFEF80F5E0090480B870B876D756D7479030006D4
+S11884A009376D7654706DF60D767903000C19376DF46DF56FEC
+S11884B5E0FFF66FE1FFF40D257904FFF809646F6100060D4060
+S11884CA5E00812C6DF06DF46F6200046DF20D526F61FFF46F0B
+S11884DF60FFF65E0084108F0697006D756D747903000C093786
+S11884F46D7654706DF60D766E0A0009471019116F0300046FFB
+S118850902000A1D234514400E19116F0300046F02000A1D230B
+S118851E4404790100010D106D7654706DF60D761B876DF46D67
+S1188533F56FE1FFFE0D256E0A0002F2008AF992FF0D240944BD
+S118854809440944192409447902A3D009420D246E4A00084686
+S118855D067900FFFF404E0D405E0084F80D0047206F420004AA
+S11885726DF26F6200066DF26F6200040D516F60FFFE5E00847A
+S1188587A60B870B8740226F6200066DF26F6200040D516F6077
+S118859CFFFE5E0081DA6F42000C6F8200086FC0000C0B871974
+S11885B1006D756D740B876D7654706DF60D761B876DF46DF56A
+S11885C67903A400683A4D045A008686EA7F68BA19440D4509E0
+S11885DB5509550955194509557902A3D009520D256E5A00086F
+S11885F00D430B036FE3FFFE0CAA46045A0086768C0094100D32
+S1188605520D41790014C05E0096AC0D520D41790014C05E0077
+S118861A96AC0D520D41790014C05E0096AC0D520D4179001431
+S118862FC05E0096AC0D505E0084F80D00473840306F54000CD0
+S11886446F4200086FD2000C6F41000269406F5200046DF26F29
+S11886594200066DF26F4200045E0084A60D405E0082240B8741
+S118866E0B876F52000C46CA6F64FFFE790200021D244E045A4A
+S11886830085D86D756D740B876D7654706DF60D766DF46DF5DC
+S11886980D050D246F600004680BF300790200661D2347244E73
+S11886AD127902002D1D234750790200461D23472440327902CA
+S11886C200721D23470E0B021D23470E4022790200014010794F
+S11886D7020002400A7902000340047902000469926E0A000187
+S11886EC8AD0AA074304190040146E0A0001F2008AD092FF69F7
+S1188701C2FA0168DA790000016D756D746D7654706DF60D7696
+S11887167903001A19376DF46DF56FE2FFEE0D1147045A008818
+S118872B1A6EE9FFF26EE9FFF16EE9FFF06E0A0002AA054704D2
+S11887405A0087CC790200066F60FFEE1D2047045A00881A7939
+S118875504FFF409647905FFFA09657902FFF009626FE2FFECB1
+S118876A6F6300046DF30D420D516F60FFEC5E0086900B870D46
+S118877F0046045A00881A0D611B811B817900FFF109606F6252
+S118879400040B826DF21B826FE200047902FFF609625E00862B
+S11887A9900B870D00476A0D611B817900FFF209606F63000424
+S11887BE0B830B836DF37902FFF809624044790200026F63FF77
+S11887D3EE1D2346426E0B0002F3001B837900FFF409606FE0A7
+S11887E8FFEA0D3209227905FFFA09650D5109217904FFF00943
+S11887FD640D4009306F6300046DF36F63FFEA09230D325E00BF
+S118881286900B870D0046067900FFFF405019337904FFF40980
+S1188827647900FFF009606FE0FFE86F60FFE86C0A6FE0FFE86B
+S118883C0CAA471E0D318900912069426DF2695279001A4E6F7B
+S1188851E3FFE65E0096BC0B876F63FFE60B840B850B037902A5
+S118886600021D234FC66F60FFEE6D756D747903001A09376DE0
+S118887B7654706DF60D760D036B00A408400269000D00470896
+S11888906F0200021D3246F26D7654706DF60D761B876DF46DD8
+S11888A5F50D056FE1FFFE7900000E5E0097220D0446087900F0
+S11888BA02135E0080B418AA6ECA00046FC500026B02A4086948
+S11888CFC20D4088059000790200086F61FFFE5E0097AE6B8482
+S11888E4A4080D406D756D740B876D7654706DF60D766F03002E
+S11888F9026F1200021D23470419004004790000016D765470D8
+S118890E6DF60D766DF40D04790088F20D415E00829E7903A419
+S118892308401269301D40460A690269B25E00979C400E0D0326
+S1188938693246EA790002325E0080B46D746D7654706DF60D24
+S118894D766DF46DF50D040D156F4200044608790002395E0090
+S118896280B46F440004401C6940790198DC5E0097D20D004703
+S11889770A0D5546040D40400C1B058C0A9400694246E0190064
+S118898C6D756D746D7654706DF60D761B876DF46DF50D056F9C
+S11889A1E1FFFE6E5A000446226E5A0005AA0943087900024B1A
+S11889B65E0080B46E5A0005F20009226F229A0C6F220004461A
+S11889CB067900FFFF403E0D20690247360D0469406F61FFFEFC
+S11889E05E0097D20D00461E6E4A00026EDA00056F4200041872
+S11889F5BB0D224702FB806EDB000879000001400A8C0A94007C
+S1188A0A694246CC19006D756D740B876D7654706DF60D761B80
+S1188A1F876DF46DF56FE0FFFE0D157902007419110D505E00B2
+S1188A3498086F62FFFE69210D505E00981E0D50881C900079B6
+S1188A490400050D427901995E5E0097AE0D50883890000D42AC
+S1188A5E7901995E5E0097AE6F63FFFE6E3A00026EDA00546F67
+S1188A73320004FBB60D224702FB6D6EDB005CFA016EDA005DDE
+S1188A886F63FFFE6F32000418BB0D224702FB806EDB005F6D86
+S1188A9D756D740B876D7654706DF60D766DF46DF50D040D1555
+S1188AB26E4A000447067900FFFF40266E4A0005AA0943087991
+S1188AC700026B5E0080B46E4A0005F20009226F209A0C0D512A
+S1188ADC5E008A1A790000016D756D746D7654706DF60D766E47
+S1188AF10A000446107369460C6E0A0008470A89FFA901420491
+S1188B061900400AFA016E8A0004790000016D7654706DF60D6B
+S1188B1B767903000A19376DF46DF56FE0FFFE6FE1FFFC6FE24A
+S1188B30FFFA6E0A0005AA094308790002875E0080B46F60FF56
+S1188B45FE6E0A0005F20009226F229A0C6FE2FFF86E0A000880
+S1188B5AEA8046045A008C3A6E0A00044720790100746F60008E
+S1188B6F045E0098320D004610790100746F60FFFA5E00983280
+S1188B840D0047087900FFFF5A008C6C790100746F6000045E94
+S1188B990098446FE00004790100746F60FFFA5E0098446FE055
+S1188BAEFFFA5E0090346FE0FFF66F64FFF60B840B041955403B
+S1188BC30C0D415E008A1A8C7494000B056F6200041D2544122C
+S1188BD86F61FFFA09516F60FFF85E00894A0D0046DA0D5209D5
+S1188BED22092209221952092209220925095509556F63FFF685
+S1188C0268BD0D520C2A10021E226EBA000118AA6EBA00020B2D
+S1188C17850B056DF519226DF26F63FFFE6F3200026F61FFFC76
+S1188C2CF80F5E00904819000B870B8740326F60FFF86F03000B
+S1188C410647246F6200046DF26F60FFFA6DF06F60FFFE6F0213
+S1188C5600026F61FFFC6F60FFF85D300B870B8740047900FF05
+S1188C6BFF6D756D747903000A09376D7654706DF60D761B8739
+S1188C806DF46DF50D046FE1FFFE0D256E4A0008EA8046066EA4
+S1188C954A000446067900FFFF403C6E4A0005AA094308790005
+S1188CAA02B35E0080B46E4A0005F20009226F209A0C6F0200EA
+S1188CBF0847166F6200046DF26F0300080D526F61FFFE5D30D0
+S1188CD40B8740047900FFFF6D756D740B876D7654706DF60DCE
+S1188CE9761B876DF46DF56F63000446087900FFFF5A008DD243
+S1188CFE0D25194419116F6300040D5209326FE2FFFE40386806
+S1188D135BAB8846186F6200041B821D214CD4688B0B0018AACB
+S1188D28688A0B000B8140180CBB46040B0440106F6200041BF1
+S1188D3D021D214CB4688B0B000B010B0519336F62FFFE1D2567
+S1188D52450479030001685A46040D3347B2790200011D2447F9
+S1188D67124E060D4447584038790200021D24471A402E6F62C7
+S1188D7C00041B021D214D045A008CF618AA688A0B000B014047
+S1188D91346F6200041B821D214D045A008CF618AA688A0B00F9
+S1188DA640186F6200041B821D214D045A008CF6FA88688A0B00
+S1188DBB000CCA8AFE688A0B000B8119440D3346045A008D12D8
+S1188DD00D106D756D740B876D7654706DF60D761B876DF46D1B
+S1188DE5F50D040D2519226FE2FFFE0D55475E681AAA8847149E
+S1188DFA68CA0B010B046F62FFFE0B026FE2FFFE1B0540E20B9D
+S1188E0F016818F0000D00461468CA0B046F62FFFE0B026FE205
+S1188E24FFFE0B011B8540C40D030B836F62FFFE09326FE2FF91
+S1188E39FE0D321B030B011B854FAC188868C80B040D321B03E2
+S1188E4E4EF6409E6F60FFFE6D756D740B876D7654706DF60DB1
+S1188E63766DF46DF56A0CA40E47045A008F0079059F586B027F
+S1188E78A4106DF20D527901009379009EC35E008CE66B80A429
+S1188E8D060B870D004C206B02A4100D5179009EC35E0097AEBF
+S1188EA26B02A4106B82A40679029EC268AC0D23400879039E7E
+S1188EB7C2FA0868BA6A0AA40A47047D3070206838F0006A0A0E
+S1188ECCA40F4602C80168B86B00A4060D020B026B82A4066A77
+S1188EE10BA4076A8B9EC00C2A10021E226A8A9EC10B800B00FE
+S1188EF66B80A406FA016A8AA40E6D756D746D7654706DF60D53
+S1188F0B766DF46DF55E008E606B02A4106B82A40C79059EC02E
+S1188F206B04A406471A6DF46DF51922790117767900343E5E70
+S1188F350098560B870B870C8846E66D756D746D7654706DF684
+S1188F4A0D766B02A4106B03A40C1D32430E79009F580D3109F5
+S1188F5F0119325E0097AE6B02A40C6B03A41019230D326B8263
+S1188F74A41018AA6A8AA40E6D7654706DF60D766DF46DF50D6B
+S1188F89246F6500046B03A41079029F5809320D2368B86EB98D
+S1188F9E00010C1918116EB900020D44470E0B830B030D520D94
+S1188FB3410D305E0097AE6B02A4100B820B0209526B82A410CD
+S1188FC818AA6A8AA40E6D756D746D7654706DF60D766DF46D0A
+S1188FDDF50D156B04A41079029F5809420D24FA0368CA6EC8EE
+S1188FF200010C0818006EC800020D505E009874790200401D62
+S1189007204F020D200B840B040D020D510D405E0097AE6B024A
+S118901CA4108A4392006B82A41018AA6A8AA40E6D756D746DEF
+S11890317654706DF60D766B00A41079029F5D09020D206D7655
+S118904654706DF60D766DF46DF56F6400046B03A41079059F8E
+S118905B5809350D5368B86EB900010C1918116EB900026EBA1F
+S118907000030C2A18226EBA00040D4447108B0593006F6200AC
+S1189085060D410D305E0097AE6B02A4108A0592006F60000687
+S118909A09026B82A41018AA6A8AA40E6D756D746D7654706DD2
+S11890AFF60D7669021D12470419004004790000016D765470CC
+S11890C46DF60D760D01790090AE5E00829E6D7654706DF60D53
+S11890D9767903000E19376DF46DF50D050D14790000021D049C
+S11890EE4E08790003935E0080B46C5A6EEAFFFD6E5B00010C82
+S1189103B318BB685AF20014AB14236FE3FFFA1B841B040B858A
+S11891186E6BFFFDF3000D33470A790200041D23470E40446DE0
+S118912DF319226F61FFFAF801402E790200021D244708790045
+S1189142039D5E0080B46E5800010C801888685AF20014A8146B
+S1189157205E0090C419226DF26F61FFFAF8055E008F800B87CE
+S118916C5A009496790200011D244E08790003A45E0080B46E33
+S11891815800010C801888685AF20014A814206FE0FFF81B84C7
+S11891960B855E00887E6FE0FFF46E6BFFFDF3008BFA93FF7932
+S11891AB0200161D2343045A00948E09336F3299DA592079024C
+S11891C000381D244708790003AA5E0080B46F63FFF447087989
+S11891D50199635A0094567901988E6F60FFF85E00889C6FE009
+S11891EAFFF4790200086DF2880590006DF06F62FFF86F61FF86
+S11891FFFAF81D5A0094840D444708790003B65E0080B46F62A1
+S1189214FFF446087901996E5A0094566F60FFF45E00890E6E16
+S11892296BFFFDAB1446087901997A5A00945619226DF26DF2EE
+S118923E6F62FFF86F61FFFAF8135A009484790200021D244704
+S118925308790003C45E0080B46E5C00010CC418CC685AF200F5
+S118926814AC14240D405E00887E6F62FFF446045A0092186EC4
+S118927D2A00044708790199875A0094560D0047045A0091D466
+S11892926F61FFF4890591000D405E00889C19226DF26DF26FAA
+S11892A762FFF86F61FFFAF8075A0094847902001C1D244708F4
+S11892BC790003D35E0080B40D516F60FFF45E0089940D0046CA
+S11892D108790199935A009456790200086DF26F63FFF48B055B
+S11892E693006DF36F62FFF86F61FFFAF8095A0094840D4447E0
+S11892FB08790003DA5E0080B47904A3580D416F60FFF45E0084
+S11893108AA60D004608790199A05A009456790200746DF26D07
+S1189325F46F62FFF86F61FFFAF8175A009484790200211D244C
+S118933A4708790003E25E0080B4790199AB5A0094567902005E
+S118934F011D244708790003E65E0080B468596F60FFF45E009F
+S11893648AEC0D004608790199B85A009456790200086DF26FBF
+S118937960FFF4880590006DF06F62FFF86F61FFFAF80B5A0020
+S118938E94847902000A1D244708790003ED5E0080B46E5A00D6
+S11893A3010CA218AA6859F1006E5B00090CB318BB6E5800085C
+S11893B8F000148B14036DF3149A14126F61FFFA6F60FFF45ED9
+S11893CD008B180B870D004D045A009496790199C35A00945656
+S11893E27902000A1D244E08790003F45E0080B46E5A00010C7F
+S11893F7A218AA6FE2FFF6685AF2006F60FFF614A814206FE0FC
+S118940CFFF66E5B00090CB318BB6E5A0008F20014AB14238DA9
+S11894210B95008CF594FF1D434710790003F96FE3FFF25E00B1
+S118943680B46F63FFF26DF50D326F61FFF66F60FFF45E008C14
+S118944B7A0B870D004C0E790199CE6F60FFFA5E008FD64036B3
+S11894606EE8FFFE0C0810001E006EE8FFFF790200026DF20D21
+S1189475621B826DF26F62FFF86F61FFFAF8115E0090480B871E
+S118948A0B874008790004045E0080B46D756D747903000E0986
+S118949F376D7654706DF60D766DF46DF50D04684BF3007902FB
+S11894B400451D23470C7902004D1D2347045A009548790200C2
+S11894C9051D214708790004125E0080B479039A28683DF500FF
+S11894DE6A0A9A290CA218AA14AD14250D5209326E4B00036E10
+S11894F3AB000118BB6A0AA40F4602FB016A8BA40F5E008F4899
+S1189508790200011D254F326A0A9A2AEA08471E79019A2B79C4
+S118951D049AC00D521B020D405E008DDC0D050D510D405E002C
+S118953290D6400C79009A2B0D511B015E0090D65E008F0840BD
+S1189547087900042C5E0080B46D756D746D7654706DF60D7678
+S118955C7903005219376DF45E00970E7900FFB0096079020068
+S11895714019115E0098087902A4007901FFB6096179003B9A73
+S11895865E0096AC790029645E0096D4790014985E0096D479F8
+S118959B0200016DF26DF27902FFB609627901FFB4096179004B
+S11895B030D05E0098560B870B87790230026DF2192279013041
+S11895C51F79001FF25E0096BC0B877901300779001B625E009D
+S11895DA96DE790027C85E0096D419446DF479029A2879011748
+S11895EF717900327C5E0096BC0B876A8CA40F6B84A4066B8458
+S1189604A4106A8CA40E405C19227901FFAF0961790034265E57
+S11896190096AC6E6AFFAFF2000CAA473E18AA6EEAFFAE790201
+S118962EFFAE09626DF2790200107901FFF00961790033B05E94
+S11896430096BC0B876E69FFAEF1006B029A200B026B829A20DA
+S11896581B017900FFF009605E0094A45E0085BC5E0080320DBA
+S114966D00469C19006D747903005209376D76547057
+S118967E6DF60D7679029A207903A4121D32470A188868A80B2B
+S1189693021D3246F85E009558FA016A8AFFCC6B0200005D2040
+S10796A86D76547013
+S11396AC6DF66DF20D165D000D600B876D765470C2
+S11896BC6DF66F7300046DF36DF20D165D000D600B870B876D0F
+S10696D176547058
+S10D96D46DF65D000D606D765470B4
+S10F96DE6DF60D165D000D606D76547085
+S11596EA6DF56DF60D060D155F520D606D766D755470C9
+S11596FC6DF56DF60D060D155F500D606D766D755470B9
+S118970E6DF60D767903A4127902EF00193269B26D7654706D46
+S1189723F60D766DF46DF50D040B04ECFE0B841D04455C79001D
+S1189738A4120D01404C69024D4209217902EEFF1D2142144068
+S118974D0E690209326982691209211D51420469134CEE6903E9
+S11897621D4345220D428A0692001D23450A0D02094219436908
+S1189777A369846902C28069820B804010E27F09210D107905B0
+S118978CEEFF1D5043AC19006D756D746D7654706DF60D766FA3
+S11097A102FFFEE27F6F82FFFE6D765470C2
+S11897AE6DF60D766DF40D140D010D0309231D31470A6C4A6833
+S11297C38A0B001D3046F60D106D746D765470D0
+S11897D26DF60D76401C680B681A1CAB430679000001401E1C43
+S11897E7AB44067900FFFF40140B000B01680A46E0681A19005F
+S10F97FC0CAA47047900FFFF6D7654703E
+S11898086DF60D760D0309231D3047066CB91D3046FA6D7654A2
+S104981D70D6
+S117981E6DF60D760D036C1A68BA0B030CAA46F66D765470ED
+S11598326DF56DF60D060D155F4C0D606D766D75547085
+S11598446DF56DF60D060D155F4E0D606D766D75547071
+S11898566DF66F7300066DF36F7300066DF36DF20D165D000D1A
+S10C986B608F0697006D765470BD
+S11798746DF60D76193340020B036C0A46FA0D306D765470C0
+S1189888726573657400000000800000000098DC000099120005
+S118989D00000098DA020000000000871298D803000000000032
+S11898B2871298D6040000000000871298D20500000000008703
+S11898C712000000000000000000003031320032003100300050
+S11898DC2E2E000098DC000099120000000098DA0700000085FA
+S11898F12A82E098D808000000852A82E098D609000000852A23
+S118990682E00000000000000000000098DC0000994800000091
+S118991B0099410100989600000000993A060098E000000000D9
+S11899300000000000000000000073656E736F72006D6F746FC5
+S1189945720000995C00009912000000000000000000000000F7
+S118995A00002F006C65676F0066696420696E20757365006E19
+S118996F6F2073756368206669640063616E27742072656D6FAA
+S118998476650063616E277420636C6F6E65006E6F20737563A9
+S118999968206E616D650063616E277420737461740063616EB1
+S11899AE2774206372656174650063616E2774206F70656E00D2
+S11899C363616E277420726561640063616E277420777269744F
+S11899D86500924C948E92B4948E934C948E9334948E93909408
+S11899ED8E93E2948E9206948E9206948E92F8948E948E948ED8
+S1099A02948E948E91BEC7
+S1189A080000FFFF9948991C98A098AA98B498BE992698EA98BC
+S1069A1DF498FEB8
+S90380007C
diff --git a/appl/demo/lego/timers.b b/appl/demo/lego/timers.b
new file mode 100644
index 00000000..67e08dec
--- /dev/null
+++ b/appl/demo/lego/timers.b
@@ -0,0 +1,263 @@
+# Chris Locke. June 2000
+
+# TODO: for auto-repeat timers don't set up a new sender
+# if there is already a pending sender for that timer.
+
+implement Timers;
+
+include "sys.m";
+include "timers.m";
+
+RealTimer : adt {
+ t : ref Timer;
+ nticks : int;
+ rep : int;
+ nexttick: big;
+ tick : chan of int;
+ sender : int;
+};
+
+Sender : adt {
+ tid : int;
+ idle : int; # set by sender() when done, reset by main when about to assign work
+ ctl : chan of chan of int;
+};
+
+sys : Sys;
+acquire : chan of int;
+timers := array [4] of ref RealTimer;
+senders := array [4] of ref Sender;
+curtick := big 0;
+tickres : int;
+
+init(res : int)
+{
+ sys = load Sys Sys->PATH;
+ acquire = chan of int;
+ tickres = res;
+ spawn main();
+}
+
+new(ms, rep : int) : ref Timer
+{
+ acquire <- = 1;
+ t := do_new(ms, rep);
+ <- acquire;
+ return t;
+}
+
+Timer.destroy(t : self ref Timer)
+{
+ acquire <- = 1;
+ do_destroy(t);
+ <- acquire;
+}
+
+Timer.reset(t : self ref Timer)
+{
+ acquire <- = 1;
+ do_reset(t);
+ <- acquire;
+}
+
+Timer.cancel(t : self ref Timer)
+{
+ acquire <- = 1;
+ do_cancel(t);
+ <- acquire;
+}
+
+# only call under lock
+#
+realtimer(t : ref Timer) : ref RealTimer
+{
+ if (t.id < 0 || t.id >= len timers)
+ return nil;
+ if (timers[t.id] == nil)
+ return nil;
+ if (timers[t.id].t != t)
+ return nil;
+ return timers[t.id];
+}
+
+
+# called under lock
+#
+do_destroy(t : ref Timer)
+{
+ rt := realtimer(t);
+ if (rt == nil)
+ return;
+ clearsender(rt, t.id);
+ timers[t.id] = nil;
+}
+
+# called under lock
+#
+do_reset(t : ref Timer)
+{
+ rt := realtimer(t);
+ if (rt == nil)
+ return;
+ clearsender(rt, t.id);
+ rt.nexttick = curtick + big (rt.nticks);
+ startclk = 1;
+}
+
+# called under lock
+#
+do_cancel(t : ref Timer)
+{
+ rt := realtimer(t);
+ if (rt == nil)
+ return;
+ clearsender(rt, t.id);
+ rt.nexttick = big 0;
+}
+
+# only call under lock
+#
+clearsender(rt : ref RealTimer, tid : int)
+{
+ # check to see if there is a sender trying to deliver tick
+ if (rt.sender != -1) {
+ sender := senders[rt.sender];
+ rt.sender = -1;
+ if (sender.tid == tid && !sender.idle) {
+ # receive the tick to clear the busy state
+ alt {
+ <- rt.tick =>
+ ;
+ * =>
+ ;
+ }
+ }
+ }
+}
+
+# called under lock
+do_new(ms, rep : int) : ref Timer
+{
+ # find free slot
+ for (i := 0; i < len timers; i++)
+ if (timers[i] == nil)
+ break;
+ if (i == len timers) {
+ # grow the array
+ newtimers := array [len timers * 2] of ref RealTimer;
+ newtimers[0:] = timers;
+ timers = newtimers;
+ }
+ tick := chan of int;
+ t := ref Timer(i, tick);
+ nticks := ms / tickres;
+ if (nticks == 0)
+ nticks = 1;
+ rt := ref RealTimer(t, nticks, rep, big 0, tick, -1);
+ timers[i] = rt;
+ return t;
+}
+
+startclk : int;
+stopclk : int;
+
+main()
+{
+ clktick := chan of int;
+ clkctl := chan of int;
+ clkstopped := 1;
+ spawn ticker(tickres, clkctl, clktick);
+
+ for (;;) alt {
+ <- acquire =>
+ # Locking
+ acquire <- = 1;
+
+ if (clkstopped && startclk) {
+ clkstopped = 0;
+ startclk = 0;
+ clkctl <- = 1;
+ }
+
+ t := <- clktick =>
+ if (t == 0) {
+ stopclk = 0;
+ if (startclk) {
+ startclk = 0;
+ clkctl <- = 1;
+ } else {
+ clkstopped = 1;
+ continue;
+ }
+ }
+ curtick++;
+ npend := 0;
+ for (i := 0; i < len timers; i++) {
+ rt := timers[i];
+ if (rt == nil)
+ continue;
+ if (rt.nexttick == big 0)
+ continue;
+ if (rt.nexttick > curtick) {
+ npend++;
+ continue;
+ }
+ # Timeout - arrange to send the tick
+ if (rt.rep) {
+ rt.nexttick = curtick + big rt.nticks;
+ npend++;
+ } else
+ rt.nexttick = big 0;
+ si := getsender();
+ s := senders[si];
+ s.tid = i;
+ s.idle = 0;
+ rt.sender = si;
+ s.ctl <- = rt.tick;
+
+ }
+ if (!npend)
+ stopclk = 1;
+ }
+}
+
+getsender() : int
+{
+ for (i := 0; i < len senders; i++) {
+ s := senders[i];
+ if (s == nil || s.idle == 1)
+ break;
+ }
+ if (i == len senders) {
+ newsenders := array [len senders * 2] of ref Sender;
+ newsenders[0:] = senders;
+ senders = newsenders;
+ }
+ if (senders[i] == nil) {
+ s := ref Sender (-1, 1, chan of chan of int);
+ spawn sender(s);
+ senders[i] = s;
+ }
+ return i;
+}
+
+sender(me : ref Sender)
+{
+ for (;;) {
+ tickch := <- me.ctl;
+ tickch <- = 1;
+ me.idle = 1;
+ }
+}
+
+ticker(ms : int, start, tick : chan of int)
+{
+ for (;;) {
+ <- start;
+ while (!stopclk) {
+ sys->sleep(ms);
+ tick <- = 1;
+ }
+ tick <- = 0;
+ }
+}
diff --git a/appl/demo/lego/timers.dis b/appl/demo/lego/timers.dis
new file mode 100644
index 00000000..f5b2613e
--- /dev/null
+++ b/appl/demo/lego/timers.dis
Binary files differ
diff --git a/appl/demo/lego/timers.m b/appl/demo/lego/timers.m
new file mode 100644
index 00000000..55c97b5f
--- /dev/null
+++ b/appl/demo/lego/timers.m
@@ -0,0 +1,15 @@
+Timers : module{
+ Timer : adt {
+ id : int;
+ tick : chan of int;
+
+ reset : fn (t : self ref Timer);
+ cancel : fn (t : self ref Timer);
+ destroy : fn (t : self ref Timer);
+ };
+
+ init : fn (res : int);
+ new : fn(ms, rep : int) : ref Timer;
+};
+
+
diff --git a/appl/demo/lego/timers.sbl b/appl/demo/lego/timers.sbl
new file mode 100644
index 00000000..59751a86
--- /dev/null
+++ b/appl/demo/lego/timers.sbl
@@ -0,0 +1,441 @@
+limbo .sbl 2.1
+Timers
+3
+timers.b
+sys.m
+timers.m
+269
+35.1,25 0
+36.1,22 1
+37.1,14 2
+38.1,13 3
+1,13 3
+39.0,1 4
+43.1,15 5
+44.1,21 6
+13,15 6
+17,20 6
+1,21 6
+1,21 6
+45.1,11 7
+46.8,9 8
+1,9 8
+51.1,15 9
+52.1,14 10
+12,13 10
+1,14 10
+53.1,11 11
+54.0,1 12
+58.1,15 13
+59.1,12 14
+10,11 14
+1,12 14
+60.1,11 15
+61.0,1 16
+65.1,15 17
+66.1,13 18
+11,12 18
+1,13 18
+67.1,11 19
+68.0,1 20
+74.5,13 21
+25,35 21
+17,21 21
+17,35 21
+75.9,12 22
+2,12 22
+76.5,17 23
+5,24 23
+77.9,12 24
+2,12 24
+78.5,17 25
+5,17 25
+5,24 25
+5,24 26
+79.9,12 27
+2,12 27
+80.8,20 28
+8,20 28
+1,20 28
+88.1,19 29
+17,18 29
+1,19 29
+1,19 29
+89.5,14 30
+90.2,8 31
+91.1,22 32
+13,15 32
+17,21 32
+1,22 32
+92.1,13 33
+1,19 33
+93.0,1 34
+99.1,19 35
+17,18 35
+1,19 35
+1,19 35
+100.5,14 36
+101.2,8 37
+102.1,22 38
+13,15 38
+17,21 38
+1,22 38
+103.25,40 39
+1,40 39
+104.1,13 40
+105.0,1 41
+111.1,19 42
+17,18 42
+1,19 42
+1,19 42
+112.5,14 43
+113.2,8 44
+114.1,22 45
+13,15 45
+17,21 45
+1,22 45
+115.1,20 46
+116.0,1 47
+123.5,20 48
+124.12,30 49
+2,30 49
+125.2,16 50
+126.6,23 51
+28,39 51
+129.7,14 52
+7,14 52
+128.3,9 52
+3,9 52
+3,9 52
+3,9 52
+3,9 52
+3,9 52
+3,9 53
+136.0,1 54
+142.6,12 55
+18,28 56
+14,28 56
+143.6,15 57
+6,22 57
+144.3,8 58
+142.30,33 59
+30,33 59
+145.10,20 60
+5,20 60
+147.22,32 61
+22,36 61
+2,54 61
+148.2,24 62
+149.2,20 63
+2,20 64
+151.1,20 65
+152.1,24 66
+16,17 66
+19,23 66
+1,24 66
+1,24 67
+153.1,23 68
+154.5,16 69
+155.2,12 70
+156.1,53 71
+21,22 71
+24,30 71
+32,35 71
+37,42 71
+44,48 71
+50,52 71
+1,53 71
+1,53 72
+157.1,10 73
+1,15 73
+158.8,9 74
+1,9 74
+166.1,23 75
+167.1,22 76
+168.1,16 77
+169.1,39 78
+14,21 78
+23,29 78
+31,38 78
+1,39 78
+172.4,11 79
+4,11 79
+182.9,16 79
+9,16 79
+171.10,16 79
+10,16 79
+10,16 79
+10,16 79
+174.2,16 80
+176.6,16 81
+20,28 81
+177.3,17 82
+178.3,15 83
+179.3,16 84
+3,16 79
+183.6,12 85
+184.3,14 86
+185.7,15 87
+186.4,16 88
+187.4,17 89
+4,17 90
+189.4,18 91
+190.4,12 92
+193.2,11 93
+194.2,12 94
+195.7,13 95
+19,29 96
+15,29 96
+196.9,18 97
+3,18 97
+197.7,16 98
+7,16 99
+7,16 100
+198.4,12 101
+199.7,27 102
+7,27 103
+7,27 104
+200.4,12 105
+201.7,28 106
+202.4,11 107
+4,11 108
+4,11 109
+203.4,12 110
+206.7,13 111
+207.28,41 112
+4,41 112
+208.4,11 113
+4,11 114
+210.4,23 115
+211.3,20 116
+3,20 116
+3,20 116
+212.8,19 117
+3,19 117
+213.3,12 118
+214.3,13 119
+215.3,17 120
+216.3,21 121
+3,21 122
+3,21 123
+195.31,34 124
+31,34 124
+219.7,12 125
+220.3,14 126
+3,14 79
+226.6,12 127
+18,29 128
+14,29 128
+227.7,17 129
+2,17 129
+228.6,14 130
+18,29 130
+18,29 131
+229.3,8 132
+3,8 133
+226.31,34 134
+31,34 134
+231.10,21 135
+5,21 135
+232.23,34 136
+23,38 136
+2,53 136
+233.2,26 137
+234.2,22 138
+2,22 139
+236.5,15 140
+5,22 140
+237.2,46 141
+19,21 141
+23,24 141
+26,45 141
+2,46 141
+2,46 142
+238.2,17 143
+15,16 143
+2,17 143
+239.2,12 144
+2,16 144
+2,16 145
+241.8,9 146
+1,9 146
+247.2,21 147
+248.2,15 148
+249.2,13 149
+2,13 150
+2,13 150
+256.2,10 151
+257.10,17 152
+258.3,17 153
+14,16 153
+3,17 153
+3,17 153
+259.3,14 154
+3,14 154
+261.2,13 155
+2,13 155
+5
+aSys->Dir 1:26.1,39.2 64
+11
+0:name:28.2,6 s
+4:uid:29.2,5 s
+8:gid:30.2,5 s
+12:muid:31.2,6 s
+16:qid:32.2,5 @1
+
+32:mode:33.2,6 i
+36:atime:34.2,7 i
+40:mtime:35.2,7 i
+48:length:36.2,8 B
+56:dtype:37.2,7 i
+60:dev:38.2,5 i
+aSys->Qid 11.1,16.2 16
+3
+0:path:13.2,6 B
+8:vers:14.2,6 i
+12:qtype:15.2,7 i
+aRealTimer 0:11.0,18.1 32
+6
+0:t:12.1,2 R@3
+
+4:nticks:13.1,7 i
+8:rep:14.1,4 i
+16:nexttick:15.1,9 B
+24:tick:16.1,5 Ci
+28:sender:17.1,7 i
+aTimer 2:2.1,9.2 8
+2
+0:id:3.2,4 i
+4:tick:4.2,6 Ci
+aSender 0:20.0,24.1 12
+3
+0:tid:21.1,4 i
+4:idle:22.1,5 i
+8:ctl:23.1,4 CCi
+15
+0:init
+1
+32:res:33.5,8 i
+0
+n6:new
+2
+32:ms:41.4,6 i
+36:rep:8,11 i
+1
+40:t:44.1,2 R@3
+
+R@3
+15:Timer.destroy
+1
+32:t:49.14,15 R@3
+
+0
+n21:Timer.reset
+1
+32:t:56.12,13 R@3
+
+0
+n27:Timer.cancel
+1
+32:t:63.13,14 R@3
+
+0
+n33:realtimer
+1
+32:t:72.10,11 R@3
+
+0
+R@2
+52:do_destroy
+1
+32:t:86.11,12 R@3
+
+1
+36:rt:88.1,3 R@2
+
+n65:do_reset
+1
+32:t:97.9,10 R@3
+
+1
+36:rt:99.1,3 R@2
+
+n79:do_cancel
+1
+32:t:109.10,11 R@3
+
+1
+36:rt:111.1,3 R@2
+
+n91:clearsender
+2
+32:rt:120.12,14 R@2
+
+36:tid:32,35 i
+1
+40:sender:124.2,8 R@4
+
+n107:do_new
+2
+32:ms:139.7,9 i
+36:rep:11,14 i
+6
+40:i:142.6,7 i
+44:nticks:153.1,7 i
+48:newtimers:147.2,11 AR@2
+
+52:t:152.1,2 R@3
+
+56:tick:151.1,5 Ci
+60:rt:156.1,3 R@2
+
+R@3
+145:main
+0
+9
+32:rt:196.3,5 R@2
+
+36:i:195.7,8 i
+40:clkctl:167.1,7 Ci
+44:clkstopped:168.1,11 i
+48:npend:194.2,7 i
+52:s:212.3,4 R@4
+
+56:clktick:166.1,8 Ci
+60:si:211.3,5 i
+64:t:182.1,2 i
+n218:getsender
+0
+4
+32:i:226.6,7 i
+36:newsenders:232.2,12 AR@4
+
+40:s:227.2,3 R@4
+
+44:s:237.2,3 R@4
+
+i254:sender
+1
+32:me:244.7,9 R@4
+
+1
+36:tickch:247.2,8 Ci
+n259:ticker
+3
+32:ms:253.7,9 i
+36:start:17,22 Ci
+40:tick:24,28 Ci
+0
+n8
+48:acquire:27.0,7 Ci
+56:curtick:30.0,7 B
+68:senders:29.0,7 AR@4
+
+72:startclk:161.0,8 i
+76:stopclk:162.0,7 i
+80:sys:26.0,3 mSys
+1:4.0,160.1 0
+
+84:tickres:0:31.0,7 i
+88:timers:28.0,6 AR@2
+