SYNOPSIS barebone [ -v | -h | -s | -e | t start ] -v : version -h : help -s : stop CD -e : eject CD -t start : play CD, beginning at trackType barebone to play the whole CD.
Do you like FORTH because you can solve tasks rather fast and easy? Are you annoyed by all the SWAP, DUP, FLUP, OVER, UNDER, PICK, PUCK, SICK, SUCK? If you answered yes to both of the questions you can get a good deal of relief by using REORDER. It does exactly what you tell it to do with your parameters on the stack. Download REORDER.SEQ and load it into F-PC ( a Forth for the PC by Tom Zimmer ) and you can use it (together with the old words, if you want). Or download REORDER.F for Win32Forth.
The usage of REORDER is straightforward:
REORDER ( fred bob joe bill gates -- bob joe fred )This example drops the top 2 items ( bill gates ), and effectively picks the ( then ) 3.rd and puts it on TOS, just like the stack comment shows. Of course you can use an item more than once on the right side (but all items on the left must have unique names). So
REORDER ( a b c d -- a b c d d c b a a a a b b b c c d )is totally ok. But don't be afraid that REORDER will compile a lot of stack operations for this. The example above are only 71 bytes! And pure assembly code - fast! And try to do this fiddling with the parameters with your "normal" stack operations. You will end up (after 1001 crashes and hours later) with much more space consumed and with a much slower solution. The "secret" of REORDER is a simple optimizing algorithm:
-3 -2 -1 0 0 -1 -2 -3 -3 -3 -3 -2 -2 -2 -1 -1 0because we wrote:
"-- a b c d d c b a a a a b b b c c don the right side.)
Now with "a" in the second register we find that it's destination is currently occupied by "b". So we compile a load to the first register for "b" and a store of the second to the location where we got the "b" from (this places "a" where it has to go to and frees the second register, as no more copies of "a" are needed. Next we load "c" and store "b" and finally we store "c". We do not have to load "d" as we made the copy in the first of our load-store sequences.
This procedure works whether the stack grows, shrinks or stays the same. The only thing to care here is that we first make all copies (or moves) to items that are on the stack afterwards in the additional locations.
(If that procedure reminds you of something but you do not know right now of what - think of a sort procedure: bubble sort. Our procedure is a derivate of it with the only difference that bubble sort always takes adjacent items and we choose the item to exchange according to the byte-string.)
variable MOTOR .... MOTOR @ \ this reports the current state .... MOTOR OFF \ set the variable to off .... MOTOR ON \ and this sets it onThis seems to be a good way to do the job, but when the two different states have dissimilar functions, like that famous STATE in Forth, it becomes difficult to remember what is done in which state. A way to elivate this could be a colon definition like:
: compiling state on ; \ give it a meaningful nameThis is OK for small projects, but becomes cumbersome for bigger ones as people tend to "forget" these redefinitions - they use ON and OFF in their code.
SWITCH: < switch name > < word to set it off > < word to set it on > Example: SWITCH direction? counter-clockwise clockwiseThis declares three words: DIRECTION?, COUNTER-CLOCKWISE and CLOCKWISE. When you want to get the current state of the switch you use
DIRECTION? ( -- state )that leaves the current state on the stack ( 0 or -1 ). To set it on (clockwise) in our example you use
CLOCKWISE ( -- )and
COUNTER-CLOCKWISE ( -- )to set it off.
The main advantage is the decoupling of the function from the implementation. On a processor with good bit operators you can implement it easily to use only one bit in a storage cell. This saves space in embedded applications.
The following guideline assumes that the processor is an 8-bit type (like the Z80). But the extension to any width is simply a redefinition of one constant (BUS_WIDTH). Following is the symbolic code to implement the SWITCH: in any Forth.
8 constant bus_width \ how many bits our system is wide variable (next_bit) \ what is the next free bit in the \ currently used memory cell (of width \ BUS_WIDTH) variable (current_cell) \ holds the address of the current cell : get_next_bit ( -- adr bit# ) \ find the next free bit in the current \ cell, allocate the next if current is \ full next_bit @ \ what is the next free location? bus_width > \ is it beyond the cell? IF \ yes, we must allocate a new cell 1 next_bit ! \ we start with the 1.st bit here \ where we want to put the new cell (current_cell) ! \ remember the adr THEN \ here we come with enough space in the cell (current_cell) @ \ leave the adr on the stack (next_bit) @ \ and the bit# to use (next_bit) incr \ increment the bit# to use ; : SWITCH: \ becomes a compiler extension add-name-to-dictionary \ name of the switch to the dictionary \ cfa is set to HERE get_next_bit ( -- adr bit# ) \ get the next free bit and the adr over over \ we need both values again compile-"Test bit bit# at adr adr" \ LD A,adr BIT A,bit# (on a Z80) extend-to-word \ JZ unnest LD A, -1 unnest: compile-unnest \ end the execution here \ is JUMP NEXT or RTS, depending on system add-name-to-dictionary \ name of the off state word, cfa=here over over \ we need them a last time for the on state compile-"Clear bit bit# at adr adr" \ LD A,adr RES bit# LD adr,A compile-unnest \ end the execution here add-name-to-dictionary \ name of the on state word, cfa=here compile-"set bit bit# at adr adr" \ LD A,adr SET bit# LD adr,A compile-unnest \ end the execution here ;That is all to use just one bit for it (if the processor has a good bit manipulation instruction set)!
The file SWITCH.SEQ does not use this technique because the x86 processors are very slow with bit operations and FPC is running on a PC. But it gives you the convenience of the SWITCH construct instantly.
If you have downloaded V2.0 please get the new version 2.02 above. There
was a small bug in version 2.0. Or you fix it yourself: Put this line as the
last line in function cleanup_module
(file spi.c):
if (spi_buf != NULL) kfree (spi_buf);
The driver should work under 2.4.x kernels, but this is still untested.
The version 2.1 introduces an optional feature: It can catch the INT (IRQ)
from the port and remember it. The process having the spi-device open can
check that via an ioctl call. See the documentation for details. If you do
not need that feature V2.0 will do it. (Note:
only one process can have /dev/spi open at any given time. This is a limitation of
the SPI-Bus
The SPI-bus (from Motorola) and it's companion, the MicroWire-bus (from National Semiconductor), are 3-wire serial busses with TTL-level that are designed for communication with a lot of devices, like ADCs, DACs, ports, EEROMs. Devices for these busses are available from, among others, Motorola, National Semiconductor, Maxim, Harris, Siemens.
Both busses differ only in simple terms, so one driver can talk to chips of both families, even when they are mixed on the same bus. The driver is called spi-driver simply because it is short (and the author knows that one driver can handle both ;-) ).
To have the spi-driver in your kernel you need the following files:
spi.c spi.h spi-driver-ifc.txt spi-driver-install.txtThe first two are the ones which are REALLY necessary; the others are simply instructions on usage and installation of the driver. You can put them wherever you want, but the first 2 must be copied to certain locations, as instructed in spi-driver-install.txt
As the driver is a module you have two choices where to put the files, but read spi-driver-install.txt for that. The usage afterwards is identical in both cases. NOTE: The spi driver uses a parallel port and the lp driver snatches all ports when it is loaded. So you MUST make the lp driver a module, too. (More in the installation instructions.)
First unpack the .tgz file at some convenient location. It does not create any directories. You have to do it manually if you want the files to go to a specific one. Then run make.
Thanks a lot to Alessandro Rubini who proposed to make the driver a module and helped me to get it done.
Unfortunately we do no longer have this board here, so we cannot improve the driver. You are free to make changes to the software at will, but notify us, please. Contact the webmaster and mail your modified code so that we can keep this site as current as possible and give you the credits you deserve.
As soon as some modifications are made by someone to the software we will start to give it version numbers and in the future you will then find files with version numbers. Consider this to be version 0.1.
Note: With the package comes a file with the ending .dll . This contains the firmware for the board. Agilent allowed us to supply it with the driver, but explictly forbids any modifications to, or reverse engineering of, that file. Honour the support of Agilent, please.