xref: /inferno-os/doc/lego.ms (revision 46439007cf417cbd9ac8049bb4122c890097a0fa)
1.TL
2Styx-on-a-Brick
3.AU
4Chris Locke
5.br
6chris@vitanuova.com
7.AI
8Vita Nuova
9.br
10June 2000
11.SH
12Background
13.LP
14The aim of the Vita-Nuova ``styx-on-a-brick'' project was
15to demonstrate the simplicity of the Styx protocol and the ease
16with which a Styx `stub' can be implemented on tiny devices.
17We also aimed to demonstrate the effectiveness of a protocol based approach
18to resource management and sharing, whether the resource be a physical device
19or a software service.
20.LP
21Adopting a protocol-centric view of resource and service management, as opposed to
22a language-centric approach (as emphasised for instance by Jini™ with Java)
23greatly eased the software burden on our tiny target device \-
24implementing a simple protocol in firmware required much less work than trying to
25implement a virtual machine.  We are confident that if we had adopted a language-centric
26approach, we would not have completed the project within our aggressive space and implementation time constraints.†
27.FS
28.FA
29†Indeed, we later discovered that in the application of Jini to load code into an RCX robot no part
30of Jini was actually on the brick.
31.FE
32.LP
33The project took 2 weeks from start to finish.
34In this time the firmware was developed and all client software
35was written: firmware download, IR-link protocol support,
36clockface application and worldclock application.
37Two people worked on the project, one full-time, the other (Nigel Roles) part-time.
38.LP
39The demo was then taken on a Press Conference tour of the US
40and later appeared at the Usenix2000 Plan 9/Inferno BOF at the request
41of Dennis Ritchie.
42.LP
43I should stress that the project was a demonstration of the ease of
44supporting Styx on small devices \- it was not a demo of robotics!
45(Indeed, the design of the IR-link protocol, Styx name space and the
46services provided by the firmware would be considerably different for
47serious robotics.)
48.LP
49The project used a standard Lego™ Mindstorms™ robotics kit \-
50the ``Robotics Invention System''.  This consists of the RCX brick,
512 motors, 2 button sensors, a light sensor and a whole load of
52lego pieces \- including wheels, gears and axles; which all adds up
53to a whole load of fun!
54.LP
55The RCX brick is an Hitachi H8 microcontroller with 32K of RAM and
56a 16K ROM BIOS.  The RCX provides 3 motor outputs and 3 sensor inputs.
57Communication with the RCX is via IR.  An IR tower is supplied with the
58``Robotics Invention System'' that connects to a PC via a serial port.
59.SH
60Acknowledgements
61.LP
62Before going any further I must acknowledge the work of Kekoa Proudfoot at
63Stanford and Russ Nelson at Crynwr Software.
64Without their valiant efforts we would not have been able to pursue this project.
65Our work relied on the documents and librcx suite provided by Kekoa:
66.P1
67http://graphics.stanford.edu/~kekoa/rcx/
68.P2
69and on information from Russ Nelson's web site
70.P1
71http://www.crynwr.com/lego-robotics/
72.P2
73.SH
74Files
75.LP
76The files in the
77.CW legostyx.tar
78file are shown in Table 1.
79.KF
80.TS
81center;
82lf(CW) lfR .
83llp.h	Link level protocol constants
84styx.c	The firmware implementation
85styx.srec	The firmware image (S-record format)
86styx_abp.srec	The firmware with the alternating bit part of the link protocol enabled
87send.b	Test app \- sends RCX op codes to the brick
88firmdl.b	Firmware download app
89rcxsend.m	Util module header
90rcxsend.b	Util module \- supports RCX ROM message format on serial link
91timers.m	Timer module header
92timers.b	Util module \- general purpose timers
93legolink.b	Implements the link protocol via a limbo file2chan()
94clockface.b	The controller app for our Clockface robot
95.TE
96.fi
97.ce 10
98.I "Table 1.\ "\c
99Files in the Styx-on-a-Brick package
100.ce 0
101.KE
102.SH
103Project details
104.NH 1
105Firmware Download
106.LP
107The RCX brick comes supplied with Lego firmware to be downloaded into the RAM via
108the IR link.  The ROM implements a monitor which provides for the firmware download,
109as well as other 'op-codes'.
110.LP
111We wrote our own firmware in C using the GNU H8 compiler suite on a FreeBSD machine.
112The code used Kekoa's
113.CW librcx
114library for interfacing to the RCX ROM routines.
115(We should have liked to have done an H8 code generator for our own compiler suite,
116but time did not permit this!)
117The
118.CW gnuh8
119list is accessible via:
120.P1
121http://www.pcserv.demon.co.uk/
122.P2
123First up we had to write a Limbo application to communicate with the ROM, via
124the IR tower in order that we could get our firmware downloaded onto the RCX.
125This is the firmdl application.  Source files:
126.CW firmdl.b ,
127.CW rcxsend.b
128and
129.CW timers.b
130.NH 1
131Styx Comms Link
132.LP
133Having got a means of installing our firmware we needed a means of delivering
134Styx messages to and from the Brick.
135.LP
136Styx makes certain demands of its transport media:
137.TS
138l l .
139Reliable	messages must not get 'lost'
140Ordered	messages must not get transposed
141.TE
142The RCX ROM provides a couple of functions for IR comms \- a routine to check
143for message reception and a routine for message delivery.
144The message reception routine receives the data of a RCX "Transfer Data"
145message (RCX op-code 0x45)
146.LP
147We chose to use this facility as a means of delivering Styx messages to our Firmware
148on the Brick.  But it did not provide the Transport properties that Styx requires.
149To meet the Styx requirements we implemented a simple 'alternating bit' protocol whose
150payload was the Styx messages themselves.  These Link protocol messages become the
151payload of the RCX "Transfer Data" messages.
152.LP
153The IR link is very slow, the baud rate of the IR tower serial link is 2400
154and the ROM message format requires that every byte of a message be doubled up with
155its complement. (e.g. the byte 0x7e is transmitted as 0x7e, 0x81)
156This is because of the simple way that the RCX ROM and hardware handle elimination
157of the ambient IR signal level \- all message have the same number of 1s and 0s so
158the ambient IR level can be negated by subtracting the average level.
159All RCX messages are also prefixed by a header and suffixed with a checksum:
160.P1
1610x55 0xff 0x00 \fID1 ~D1 D2 ~D2 ... Dn ~Dn C ~C\fP
162.P2
163where
164.I D1
165\&...
166.I Dn
167are the bytes in the message body and \fIC = D1+D2+ ... Dn\fP.
168.LP
169Therefore, the effective data rate is considerably less than 1200 baud.
170.LP
171We noted that many Styx messages, especially
172.CW Twstat
173and
174.CW Rstat ,
175contained a high
176proportion of 0 byte values.†
177.FS
178.FA
179The protocol has since been revised to reduce that.
180.FE
181Consequently, we decided to incorporate a 0-run-length
182compression scheme in our simple link protocol.
183.LP
184Within the payload of the link messages:
185.TS
186l l .
1870x88 0x00	represents 0x88
1880x88 n	represents n + 2 0's
189others	represent themselves
190.TE
191.LP
192An additional burden is that communication with the Brick via the IR tower has to be strictly
193synchronous.  The IR tower echoes back all data transmitted to it on the serial link
194as well as any data received on the IR link.  Therefore the brick must not send IR data
195while the PC is sending serial data to the tower.  In order to achieve this a 'ping-pong'
196communication scheme must be employed.  The PC is the master, the brick is the slave.
197The master sends a request and waits for the reply from the slave.
198Only the master is allowed to start an exchange.
199.LP
200The problem with the master/slave style of communication is that a Styx Server
201implements blocking requests, e.g. reads and writes, by simply not responding to the
202request until the operation is completed.  This does not fit with the link protocol
203requirement that the server (slave) always respond and the requirement that the brick
204cannot instigate a data exchange.
205The firmware could simply reply with an empty Link protocol message but it then has no
206way of giving timely notification of the completion of a pending Styx request as it is not
207allowed to start a link-protocol message exchange.
208.LP
209To get around the pending Styx reply problem, the link protocol header incorporates a flag
210that the slave (brick) can set to indicate that it is holding outstanding requests and that the
211master (PC) should continue to poll the slave in order to receive their replies in a timely
212fashion.
213.LP
214The link protocol message format is as follows.
215Request from Master (PC) to Slave (RCX):
216.LP
217.TS
218l l .
2190x45/4d	RCX Transfer Data op-code  (including RCX alternating bit)
2200	LSB of "Data" block number
2210	MSB of "Data" block number
222*	LSB of "Data" payload length (lost to ROM firmware)
223*	MSB of "Data" payload length (lost to ROM firmware) (n+2)
224*	LSB of Link protocol payload length
225*	MSB of Link protocol payload length (n+1)
226*	Link protocol header
227*[n-1]	Link protocol payload (0 or 1 Styx messages)
228*	"Transfer Data" cksum (Last byte of Link protocol payload)
229.TE
230.LP
231Note that the 0x45 ROM op-code ("Transfer Data") message incorporates a checksum byte at the
232end, but the ROM doesn't bother to check it so we moved the last byte of the Link protocol
233payload (or the link header if the payload is empty) into the checksum position of
234the ROM message.
235.LP
236Reply from Slave to Master:
237.LP
238.TS
239l l .
240?	Junk from ROM
241*	LSB of Link protocol payload length
242*	MSB of Link protocol payload length (n+1)
243*	Link protocol header
244*[n]	Link protocol payload
245.TE
246.LP
247The Link protocol header has the following flags:
248.LP
249.TS
250l l .
251bit 0	Alternating bit
252bit 1	Poll immediate (requested by slave)
253bit 2	Poll periodic (requested by slave)
254bit 3	compressed (payload is 0-run-length compressed)
255bits 4-7	reserved (should be 0)
256.TE
257.LP
258The master flips the
259.I Alternating
260.I bit
261for every message that it successfully delivers.
262If a slave reply is lost or corrupted the master will re-send the message using the same
263alternating bit value.  The slave should not act on a repeated message but should
264re-send it's last response.  The value of the alternating bit in the slave response
265is the same as in the request from the master.
266.LP
267The
268.I Poll
269.I immediate
270bit indicates that the slave has more data to send to the master.
271The master should immediately send another Link-protocol message, even if it has no
272data to send, so as the slave can reply with its pending data.
273.LP
274The
275.I Poll
276.I periodic
277bit indicates that the slave has pending (blocked) requests that
278it will reply to sometime in the future.  The master should periodically poll the
279slave, even if the master has no data to send.  The polling period should be small
280enough that reply latencies are acceptable.
281.NH 1
282The name space
283.LP
284We now have a means of getting Styx messages to and from the brick.
285But what does the name space provided by the firmware on the brick look like?
286.LP
287We wanted a generic name space; one that reflected the functions of the brick, not
288the model attached to it, so that the same firmware could be used with many
289different robots.
290.LP
291The brick has 3 motor outputs and 3 sensor inputs.
292The motors can be run forwards or reverse with 8 different power settings.
293They can be stalled, also with 8 power levels, and they can be left 'floating'
294[A stalled motor presents resistance to turning proportional to the stall power level]
295.LP
296There are 2 types of sensor \- buttons and light-sensors.
297[You can also get a 'rotation sensor', but we had not got one in our kit!]
298.LP
299We decided on a name space comprised of 2 directories,
300.CW motor
301and
302.CW sensor .
303We didn't need to use subdirectories for our name space but it was easy, so we did!
304.LP
305The motor directory contains 4 files \-
306.CW 0 ,
307.CW 1 ,
308.CW 2
309and
310.CW 012 .
311The files
312.CW 0 ,
313.CW 1
314and
315.CW 2
316represent the individual motor outputs and
317accept command messages of the form
318.I 'XP'
319where
320.I X
321is a direction and
322.I P
323is the power level.
324.LP
325.I X
326can be one of
327.TS
328l l .
329f	forward
330r	reverse
331s	stall
332F	float
333.TE
334.LP
335.I P
336is a digit in the range
337.CW '0..7'
338.LP
339The file
340.CW 012
341takes messages of the form
342.I 'XPXPXP'
343enabling the state of all the motors to be modified with a single message.
344The first
345.I XP
346pair affects motor 0, the middle pair affects motor 1 and the
347last pair affects motor 2.
348.I XP
349can be
350.CW '--'
351indicating that the state should remain the same as before.
352.LP
353.LP
354The sensor directory contains three files
355.CW 0 ,
356.CW 1
357and
358.CW 2 ,
359corresponding to the three sensor inputs on the brick.
360.LP
361Before a sensor file can be read it must be configured by writing a configuration
362message to the file.  These message take the form
363.I 'Tv*'
364where
365.I T
366is the sensor type and
367.I v*
368is a threshold value.
369The idea of the threshold value is that reads of the sensor file wil block until
370the threshold value has been achieved.
371.LP
372Reads of a sensor file return its current value.
373When a sensor file is configured any pending reads of the sensor are
374failed with the error message
375.CW 'reset' .
376.LP
377The available sensor types are:
378.LP
379.TS
380l l .
381b	button
382l	light sensor
383.TE
384.LP
385The threshold value for a button sensor is a click count.
386So the control message
387.CW 'b0'
388configures a sensor to be a button and subsequent reads
389of the file will yield the current click count.
390.br
391The message
392.CW 'b20'
393will cause subsequent reads to block until the click count reaches
39420 or more.
395.LP
396The threshold value for a light sensor is a raw sensor value qualified by
397.CW '<'
398or
399.CW '>' .
400.LP
401The control message
402.CW 'l>600'
403configures the input to be a light sensor and subsequent
404reads will block until the sensor value exceeds 600.
405If the
406.CW '<'
407qualifier is used, reads block until the value drops below the threshold.
408.SH
409Using the Styx firmware
410.NH 1
411Download the firmware
412.LP
413Use the
414.CW firmdl
415command to download the firmware to the brick
416.P1
417% firmdl 0 styx.srec
418%
419.P2
420.LP
421The first argument is the number of the inferno serial port (
422.CW /dev/eia0
423in this example).
424The second argument is the file containing the firmware image in s-record format.
425.LP
426The firmdl app prints the response code from the ROM.
427On successful download the ROM reports:
428.P1
429Just a bit off the block!
430.P2
431.LP
432Once the firmware is downloaded it is immediately run.
433The RCX display should be showing the 'running man' symbol.
434If at any time the Styx firmware encounters an error, the 'running man'
435is changed to a 'standing man' and the source code line number of the error
436is displayed on the LCD.
437The firmware doesn't stay resident: it monitors the on/off button and
438restarts the ROM monitor when it is pressed.
439.NH 1
440Start the link protocol
441.LP
442.P1
443% legolink 0
444%
445.P2
446.LP
447The legolink argument is the serial port over which to run the link protocol.
448This will be the same as the first argument to the firmdl command.
449.LP
450Once started the legolink command creates the file
451.CW /net/legolink
452in the Inferno
453name space.  Any reads/writes of this file are the payload data of the link protocol.
454.NH 1
455Mount the brick name space
456.LP
457.P1
458% mount -o -A /net/legolink /n/remote
459.P2
460.LP
461The
462.CW -A
463flag to mount prevents the command from trying to
464do authentication
465on the link before running the Styx protocol over it.
466The
467.CW -o
468option uses an older version of Styx.
469The second argument to mount is the the file over which the Styx protocol will be run.
470Raw Styx messages are written to and read from this file.
471The third argument is the directory on which to mount the name space presented by the
472Styx server on the other end of the link \- the firmware on the Brick.
473.NH 1
474Explore the name space
475.LP
476.P1
477% cd /n/remote
478% ls
479motor
480sensor
481% ls motor
482motor/0
483motor/1
484motor/2
485motor/012
486% ls sensor
487sensor/0
488sensor/1
489sensor/2
490%
491.P2
492.LP
493Attach a motor to the first output and a button sensor to the first input
494and then try the following...
495.LP
496Start motor...
497.P1
498% cd motor
499% echo -n f7 > 0
500%
501.P2
502.LP
503Reverse the motor...
504.P1
505% echo -n r7 > 0
506%
507.P2
508.LP
509Stop the motor (float)...
510.P1
511% echo -n F0 > 0
512%
513.P2
514.LP
515Notice the need for the
516.CW -n
517flag to echo.  The firmware is a bit touchy about
518the format of the motor control messages \- they have to be 2 bytes long.
519.LP
520Run the motor for (a little more than) 5 seconds...
521.P1
522% echo -n r7 > 0; sleep 5; echo -n F0 > 0
523%
524.P2
525.LP
526It takes time on the slow link to open the file for the control message to
527stop the motor.  It should be possible to reduce the delay by keeping the file open:
528.P1
529% {echo -n r7; sleep 5; echo -n F0} > 0
530%
531.P2
532but the firmware only accepts command messages written to file offset 0.
533.br
534[Fixing this is left as an exercise for the reader!]
535.LP
536Ok, lets play with a sensor...
537.P1
538% cd /n/remote/sensor
539% echo b0 > 0
540% cat 0
5410%
542.P2
543.LP
544Note that the sensor file isn't as fussy about its message format as the motor file.
545.LP
546Click the button a few times and then try reading the sensor file again
547.P1
548% cat 0
5494%
550.P2
551.LP
552Let's try a blocking read on the sensor
553.P1
554% echo b5 > 0
555% cat 0
556\fR[click the button 5 times]\fP
5575%
558.P2
559.LP
560Ok, we're done playing \- unmount the brick name space
561.P1
562% cd
563% ls /n/remote
564/n/remote/motor
565/n/remote/sensor
566% unmount /n/remote
567% ls /n/remote
568%
569.P2
570.SH
571The Clockface robot
572.LP
573So we have a means of controlling the brick via Styx.
574We now needed to design a robot suitable for demonstrating the software.
575.LP
576The robot needed to be static; the IR link needs to maintain line-of-sight contact
577between the IR tower and the brick.
578The operation of the robot needed to be clearly visible to a group of people in a
579conference room.
580We also wanted a robot that we could layer services on top of each other to demonstrate
581the versatility of Inferno name spaces.
582.LP
583We decided on a clock robot.  The robot is static; it doesn't move around the room!
584The clockface would be visible and its operation obvious
585to a group of people in a reasonably large room.
586.LP
587The clockface robot also allowed us to layer services:
588.LP
589Initially we just mount the Brick name space.
590This name space represents the services of the brick \- nothing is known of the
591robot model that is attached to the brick.
592.LP
593We then start the clockface service.  This knows how to use the name space of
594the brick to control the motors and sensors of the clockface model.
595The clockface service provides a
596.CW clockface
597file which accepts
598time values (e.g.
599.CW '14:35' ),
600the service then runs motors and reads sensors
601to set the hands of the robot to the specified time.
602.LP
603On top of the clockface service we can run a world-clock service.
604This periodically reads the system clock and writes time messages to the
605.CW clockface
606file resented by the clockface service.
607The world-clock service also provides a configuration file so that the user
608can set the time zone of the clock display.  Writing a time zone abbreviation into
609the control file causes the world-clock service to write new time messages into
610the
611.CW clockface
612file to reflect the new time zone setting.
613.LP
614By using Inferno's ability to export a name space, any of the clock  services
615could be running anywhere in the network.
616The Lego brick could be attached to machine A.
617Machine B could be running the legolink application using
618.CW /dev/eia0
619imported from machine A.
620Machine C could mount the
621.CW /net/legolink
622file imported from machine B's
623name space.
624Machine D could then run the clockface service over the brick's name space
625imported from machine C, etc. etc.
626.LP
627The source of the clockface service is
628.CW clockface.b .
629.br
630The source of the world-clock service is
631.CW worldclock.b .
632.SH
633Final Notes
634.LP
635The firmware could do with some more work on it, such as the overly strict
636length restriction on motor control messages, or the fact that control messages
637must be written at offset 0.
638.LP
639Please feel free to fix problems and make modifications.  I am more than happy
640to discuss the software and answer any questions you may have.
641.LP
642Have Fun!
643