lego.ms 19 KB

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