Modified
Roland PG1000
John Talbert, 1994
1
The Roland PG1000
The PG-1000 is a dedicated programmer for the Roland D-50 keyboard synthesizer and
the D-550 rack mounted version. It works with MIDI system exclusive, and requires an
external 9V power supply. It has an impressive 56 faders used to set the four partials,
two tones and one common parameter block for each D-50 patch. Programming was
made easier by displaying parameter values on a backlit LCD screen along with dedicated
partial/tone select buttons.
Its impressive number of faders and MIDI output immediately suggest a possible use as
a generic MIDI controller device. When it came out in the late 1980’s Midi Controller
devices were rare. However, the MIDI output of the PG1000 is in System Exclusive
form and each fader is tied to a specific D-50 function with a specific range of values; all
of which does not easily translate to any use as a generic MIDI controller.
Upon opening up the PG1000, the internal circuitry turned out to be very simple and
straightforward. It consists mainly of a NEC 78C10 Processor running code from a 32K
PROM memory chip. The Processor includes eight 8-bit Analog to Digital Converters
which are used to convert the 0 to 5 volt output from each slider. Each of the 8 ADCs
handles 8 sliders routed through a 4051 CMOS Data Selector chip. Note that this scheme
allows for a total of 64 sliders and the unit has only 56. One of the processor’s ADC is
not being used – a point that will turn out to be useful later.
The NEC 78C10 Processor, better described as a single chip microcomputer, has a
number of other useful features put to good use in the PG1000: an internal serial I/O
engine used for the MIDI I/O, internal clocks and counters used to set the MIDI and
serial data rates, a small amount of RAM memory for storing setup data, and extra I/O
lines dedicated to the LCD controller and several pushbuttons.
The Task
Seeing how simple and traceable the internal circuitry was, the task of reprogramming the
PROM memory to turn the PG1000 into a MIDI slide controller became a viable
possibility. To avoid as much assembly language programming as possible, I chose to set
up a Forth Language operating system on the memory chip. This route was made
possible by the development of the eForth system by C. H. Ting. The eForth system is
a complete Forth system, designed to be small enough to fit on a memory chip. It
requires that only 31 simple code words be built from assembly code for any particular
processor. The remaining higher level eForth code words are then built from these 31
base words. With eForth, after programming the base words, I then had a complete
higher-level programming language to facilitate building the main code that will turn the
PG1000 into a MIDI Controller.
2
The rest of this paper will document how this was done. First, here is a description of
the end product.
Modified Roland PG1000
This Roland PG1000 has been reprogrammed to put out conventional Midi command
instead of System Exclusive.
The unit has 56 sliders numbered from 0 to 55. (There is also the capability for 8 external,
zero to five volt, control voltage inputs numbered as sliders 56 to 63.) It also has 10
pushbuttons, 8 of which have taken on new functions as Cursor Left, Cursor Right, Field
increment, Field Decrement, Slide increment, Slide Decrement, ENTER, and MIDI.
The unit has four modes of operation:
(1) Edit Mode.
Each Slider has an Edit Window on the LCD display with the following fields: Slider
number, slider on/off, Midi channel number, Midi operation, Midi operation data, and
Slider value.
An LCD cursor can be moved to any of the above fields using the Left/Right buttons. The
selected field can then be edited using the Field Increment/Decrement buttons. The edited
Slider Window is only loaded into memory when the Enter button is pressed. The Slide
Increment/Decrement buttons enable you to step through the Slider Windows without
moving the cursor.
No Midi data is sent while in the Edit Mode. The Slider value field provides a running
display of the slider value.
The unit supports the following Midi Operations:
Key#
Midi Key On is sent when a slider movement up from zero
peaks out. The key value sent is programmed in the Midi data
field and the key velocity sent is the peak value of the slider
movement. A note off is sent when the slider returns to zero.
Key# AT
Midi Key On with After-touch. Midi Key On/Off values are
sent as described above in Key#. In addition, a continuous Midi
3
After-touch value is sent with any slider movement until it is
returned to zero.
Control#
Midi Controller. A continuous controller value is sent with any
slider movement. The Controller number is set in the Midi data
field.
Program#
Midi Program Change. When the slider goes above a certain
threshold value, the program change number as set in the midi
data field is sent once. The data is not sent again unless the
slider is returned below the threshold value.
Ch Press
Midi Channel Pressure. A continuous channel pressure value is
sent with any slider movement. The midi data field is not used.
Ptch Whl
Pitch Wheel. A continuous pitch wheel value is sent with any
slider movement. The midi data field is not used so that only a
7 bit value is sent.
(2) Midi Run Mode.
When the Midi button is pressed, the display will change to "Midi Running" and the
enabled Sliders will start sending Midi data. To get back to Edit Mode press Enter,
Increment, or Decrement.
(3) Setup Mode.
One problem with the unit is that when powered off, all the slider setting you set in the
Edit Mode are lost. To help alleviate this inconvenience, a “Setup Mode” was
programmed to allow you to easily setup the sliders with a number of fixed settings
stored away in some available EPROM space.
To enter the Setup Mode move the cursor under the Edit field labeled "Slider#" and then
press Up or Down. The display will change to read "Setup# nn". There are a total of 64
possible slider setups stored in ROM memory. To load a particular setup use the
Up/Down buttons to select the setup number and then press the Enter Button. The
display will then go back to Edit Mode.
4
Setup# 00 disables all 64 sliders. Setup# 01 was designed for a class. Most of the
remaining setups act like Setup#00 but are empty, available for future customizing.
(4) Forth Mode.
The unit can have a serial input/output port which connects to any computer's serial I/O.
With a terminal emulation program set for 9600 baud, 8-bits, 1 stop bit, you can access
the Forth language operating system used in the unit. There is a small amount of Ram
memory available on the processor chip for implementing your own programs.
The unit will exit its Edit program loop and enter the "Forth Mode" with any key action
on the computer terminal when the serial port is connected. To re-enter the Edit program
just type EDIT and return.
Availability
If you would like one of these units for your own, your first problem is finding an original
Roland PG1000. They are a pretty scarce item. Once you manage to find one, you will
then need to burn a 27C128 EPROM memory chip with the available code and then
install it in place of the unit’s original PROM memory.
5
6
Setups
0
All off except slider 0 with pitch wheel,
and slider 1 with channel pressure.
1
Combination of Note On with aftertouch, and midi control.
2
Midi Control 0 through 63, Midi channel 15.
3
4
Midi Program changes 0 through 63, Midi channel 0
Midi Program changes 64 through 127, Midi channel 0
5
6
Key On 0 through 63, Midi channel 15
Key On 64 through 127, Midi channel 15
7
8
Key On with Aftertouch 0 through 63, Midi channel 15
Key On with Aftertouch 64 through 127, Midi channel 15
7
Modified
Roland PG1000
Assembly Instructions
8
Modified PG1000 Disassembly
Once you have an EPROM chip burned with the new code, you will have to install it in
place of the original PROM. The following instructions detail how this is done.
1. Remove power connector. Pull off all the slider knobs.
2. Remove 6 screws on the bottom.
3. Open up the back.
4. Remove all the screws holding the main circuit board,
including the bar across the middle.
5. Gently lift up the circuit board and flip it over.
Be careful not to pull any of the connections to the other smaller boards.
6. Look for the socketed PROM chip (28-pin chip).
One end of the chip will have a small half-circle indentation.
Make a note of how the indentation is oriented.
7. Using a small flat screw driver, work the chip out of its socket
by prying up each end. Take your time, pry up a little at a time.
8. Replace the original PROM with the new one.
IMPORTANT!
 The chips can be destroyed with static electricity. Touch something metal
before handling.
 Make sure the chip orientation (indentation) is the same as the original.
 Make sure all the pins are set in the socket before pushing.
 After pushing, make sure all pins have gone in straight.
9. Reassemble. It may take some gentle jiggling around to get the main board
back in place. Don't start screwing until it is in place. Remember
that the bottom two screws to the circuit board go in from the back panel.
10. Plug in and power on.
9
PG1000 Circuit Revisions
Beyond changing the operation of the PG1000 by replacing its EPROM instructions, a
couple circuit changes can also be made to the PG1000.
First of all, the new EPROM contains a complete FORTH language operating system
which can be accessed through a standard RS232 serial connection (which was how the
new code was built). There is a small amount of RAM memory available on the
processor chip to allow some additional programming.
Secondly, the 78C10 processor has available 8 Analog to Digital Converters. One of them
is not being used. This unused ADC can be revived to provide an additional eight external
control voltages. These 0 to 5 volt control voltages can be generated by any number of
devices, several of which will be shown here.
What follows are instructions for making these changes.
General
These changes require a small circuit board mounted to the inside of the PG1000 with
connections to the main computer chip on the large circuit board and to the smaller
MIDI/Power board. You will need the following:






MAX 232 chip by Dallas Semiconductors (RS232 Serial Interface)
4051 CMOS chip (8 in to 1 out multiplexer)
a small circuit board and two 16-pin chip sockets
9 pin D plug ( male and female)
47K Resistor
4 Capacitors - 10 µF
A circuit diagram is shown on the following page. I have mounted the board onto
the back end of the PG1000 using a 9-pin D plug. Solder 2-inch lengths of solid wire
(heavy gauge, about 20) to the 9 pins on the plug. Insert the other wire ends into the edge
holes of the board and then solder to the 4051 chip socket. Bend the 9 wires until the Dplug is at a right angle to the board. Drill holes for the D-plug on the back of the PG1000
where the Roland name appears. The board will sit under the LCD panel.
Ribbon cable makes the connections to the main board a little easier. Most of the
connections are to the Main processor chip. This chip has 64 pins. A figure shows its
orientation and pin numbering scheme.
10
Too much heat to any chip's pins can destroy the internal connection; therefore,
use a low wattage soldering iron, clean the tip on a wet sponge till it is shiny, and don't
contact the pin for more than 2 or 3 seconds. In most cases you won't need to solder
directly to the processor's pins. I suggest that whenever possible, you trace the
connection to another pad and solder it there.
Serial Input/Output
This RS232 Serial I/O will allow you to explore the Forth Language operating
system on the new EPROM memory chip. A small amount of RAM memory is available
for creating your own programs. I used this interface to reprogram the box.
The serial interface requires only three lines - send, receive and ground). They
connect to another computer running a terminal emulation program. I have used the 5-pin
DIN plug labeled "parameter in" on the PG1000 to get these three lines plus a Reset line
out of the box. You will then need to make a cable to go from the 5-pin DIN to your own
computer’s RS232 connector.
See the "Modified PG1000" description sheet for more information on this "Forth
Mode" of operation. If you are not interested in this mode, ignore the MAX232 part of
the circuit diagram.
External Control Voltages
The internal processor has 8 Analog to Digital Converters each of which takes care
of 8 sliders. The PG1000 uses only 7 of these ADC's for a total of 56 sliders. The eighth
one (AN7) is grounded. So by disconnecting the ground to AN7 and adding another 4051
chip you can get 8 more zero to 5 volt control inputs numbered 55 through 63.
The 8 control voltage inputs and circuit ground are brought out of the box using a
9-pin D plug. Each of the 8 inputs can then be connected to any 0 to 5 volt source. Zero
volts will read as a 0, and 5 volts will read as 127. Be careful to limit the voltage on these
inputs to the range 0 to +5 volts.
11
Simple Controllers
The external inputs can come from a wide variety of devices - switches, pedals,
pots, light sensors, motion sensors, pressure sensors. A few simple devices are shown in
the accompanying sheets.
For a light sensor use Cadmium Cells ( source - Radio Shack), also known as
Photoresistors. A simple pressure sensitive resistance is skin resistance accomplished by
bridging across two metal poles with your finger. The harder you press the smaller the
skin resistance. Another simple pressure sensitive substance is the black foam that
distributors sometime use to protect chips from static electricity. This foam changes its
resistance when pressed. Just sandwich it between two metal plates for a variable
resistance when pressed. Piezoelectric disks can be directly connected to the inputs with
some success. You can get better response, though, by electrically buffering them.
Piezo's, often used in drum pads, put out a voltage which varies with changing pressure
applied to it.
One useful way of distributing your 8 voltage inputs is by connecting the 9-pin D
connector to a small box with 8 stereo phone jacks. Also inside the box is a simple 5 volt
power supply using a 9 volt DC power wart and a 5 volt regulator, shown on an
accompanying sheet. The 5 volt power source is connected to the ring of each stereo jack
which is a convenient way to send power to each of your eight controller devices. I
prefer this method to taking 5 volts from inside the PG1000. Each of the simple circuits
shown on the sheets assumes you are using stereo plugs for the connections with a 5 volt
power source on the ring.
12
13
32
30
31
34
29
36
PG 1000
Circuit Board
Solder Side
33
35
78C10
Solder Side
6
4
2
14
7
5
3
1
59
61
63
60
62
64
15
16
Modified
Roland PG1000
NEC78C10 Microcomputer
17
NEC 78C10 Microcomputer
At the heart of the Roland PG1000 is a NEC 78C10 single-chip microcomputer. It
integrates on-chip functions that are normally provided by external components. These
functions include a 16-bit ALU, a 256-byte RAM memory (used for program variables),
an eight channel Analog to Digital converter (used to convert 56 slider voltages), a 16-bit
timer/event counter, two 8-bit timers, a USART serial interface (used to send MIDI) and
a total 44 input/output lines (used for the LCD screen, pushbuttons, LEDs, serial I/O, and
other uses).
What follows is the pin configuration for the 64-pin chip, and a table of its instruction
set. More detailed info can be found in the NEC Single-Chip Microcontroller Data Book
(1990, NEC Electronics Inc).
18
00
01
04
05
07
08
09
0A
0B
0C
0D
0E
0F
10
11
12
13
14
15
16
17
18
19
1A
1B
1C
1D
1E
1F
20
21
22
23
24
25
NOP
LDAW wa
LXI rp2,word
ANIW wa,byte
ANI A,byte
MOV A, r1
MOV A, r1
MOV A, r1
MOV A, r1
MOV A, r1
MOV A, r1
MOV A, r1
MOV A, r1
EXA
EXX
INX rp
DCX rp
LXI rp2,word
ORIW wa,byte
XRI A,byte
ORI A,byte
MOV r1,A
MOV r1,A
MOV r1,A
MOV r1,A
MOV r1,A
MOV r1,A
MOV r1,A
MOV r1,A
INRW wa
JB
INX rp
DCX rp
LXI rp2,word
GTIW wa,byte
1
2
3
3
2
1
1
1
1
1
1
1
1
1
1
1
1
3
3
2
2
1
1
1
1
1
1
1
1
2
1
1
1
3
3
26
27
29
2A
2B
2C
2D
2E
2F
30
31
32
33
34
35
36
37
39
ADINC A,byte
GTI A,byte
LDAX rpa2
LDAX rpa2
LDAX rpa2
LDAX rpa2
LDAX rpa2
LDAX rpa2
LDAX rpa2
DCRW wa
BLOCK
INX rp
DCX rp
LXI rp2,word
LTIW wa,byte
SUINB A,byte
LTI A,byte
STAX rpa2
2
2
1
1
1
1
1
1
1
2
1
1
1
3
3
2
2
1
No operation
A < ( V / offset )
SP < word
(V / offset) < (V / offset) AND byte
A < A AND byte
A < EAH
A < EAL
A<B
A<C
A<D
A<E
A<H
A<L
Alternate V, A, EA register sets
Alternate B, C, D, E, H, L register sets
BC < BC +1
BC < BC - 1
BC < word
(V / offset) < (V / offset) OR byte
A < A EX-OR byte
A < A OR byte
EAH < A
EAL < A
B<A
C<A
D<A
E<A
H<A
L<A
(V / offset) < (V / offset) + 1, Skip if carry
PC(hi) < B, PC(lo) < C
DE < DE +1
DE < DE - 1
DE < word
(V / offset) < (V / offset) - byte - 1,
Skip if no borrow
A < A + byte, Skip if no carry
A < A - byte - 1, Skip if no borrow
A < (BC)
A < (DE)
A < (HL)
A < (DE)+
A < (HL)+
A < (DE)A < (HL)(V / offset) < (V / offset) - 1, Skip if borrow
Block transfer (HL)+ to (DE)+ for C counts
HL < HL + 1
HL < HL - 1
HL < word
(V / offset) - byte, Skip if borrow
A < A - byte, Skip if no borrow
A - byte, Skip if borrow
(BC) < A
19
3A
3B
3C
3D
3E
3F
40
41
42
43
44
45
46
47
48 01
48 02
48 03
48 05
48 06
48 07
48 0A
48 0B
48 0C
48 0A
48 0B
48 0C
48 21
48 22
48 23
48 25
48 26
48 27
48 28
48 29
48 2A
48 2B
48 2D
48 2E
48 2F
48 31
48 32
48 33
48 35
48 36
48 37
48 38
48 39
48 3A
48 3B
48 3D
48 3E
48 3F
48 40
STAX rpa2
STAX rpa2
STAX rpa2
STAX rpa2
STAX rpa2
STAX rpa2
CALL word
INR r2
INR r2
INR r2
LXI rp2,word
ONIW wa,byte
ADI A,byte
ONI A,byte
SLRC r2
SLRC r2
SLRC r2
SLLC r2
SLLC r2
SLLC r2
SK f
SK f
SK f
SK f
SK f
SK f
SLR r2
SLR r2
SLR r2
SLL r2
SLL r2
SLL r2
JEA
CALB
CLC
STC
MUL r2
MUL r2
MUL r2
RLR r2
RLR r2
RLR r2
RLL r2
RLL r2
RLL r2
RLD
RRD
NEGA
HLT
DIV r2
DIV r2
DIV r2
SKIT irf
1
1
1
1
1
1
3
1
1
1
3
3
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
1
2
2
2
2
(DE) < A
(HL) < A
(DE)+ < A
(HL)+ < A
(DE)- < A
(HL)- < A
Subroutine call, PC < word
A < A + 1, Skip if carry
B < B + 1, Skip if carry
C < C + 1, Skip if carry
EA < word
(V / offset) AND byte, Skip if no zero
A < A + byte
A AND byte, Skip if no zero
A shift logical right, Skip if carry
B shift logical right, Skip if carry
C shift logical right, Skip if carry
A shift logical left, Skip if carry
B shift logical left, Skip if carry
C shift logical left, Skip if carry
Skip if CY = 1,
Skip if HC = 1,
Skip if Z = 1,
Skip if CY = 1,
Skip if HC = 1,
Skip if Z = 1,
A shift logical right
B shift logical right
C shift logical right
A shift logical left
B shift logical left
C shift logical left
PC < EA
Subroutine call, PC < BC
CY < 0
CY < 1
EA < EA x A,
EA < EA x B,
EA < EA x C,
A rotate logical right
B rotate logical right
C rotate logical right
A rotate logical left
B rotate logical left
C rotate logical left
A, (HL) rotate left digit
A, (HL) rotate right digit
Negate A, add 1 (two's complement)
Set Halt mode
EA < EA div A, A < remainder
EA < EA div B, B < remainder
EA < EA div C, C < remainder
Skip if NMI = 1,
20
48 41
48 42
48 43
48 44
48 45
48 46
48 47
48 48
48 49
48 4A
48 4B
48 4C
48 50
48 51
48 52
48 53
48 54
48 60
48 61
48 62
48 63
48 64
48 65
48 66
48 67
48 68
48 69
48 6A
48 6B
48 6C
48 70
48 71
48 72
48 73
48 74
48 82
48 83
48 84
48 85
48 8B
48 8C
48 8D
48 8E
48 8F
48 92
48 93
48 94
48 95
48 9B
48 9C
48 9D
48 9E
48 9F
SKIT irf
SKIT irf
SKIT irf
SKIT irf
SKIT irf
SKIT irf
SKIT irf
SKIT irf
SKIT irf
SKIT irf
SKIT irf
SKIT irf
SKIT irf
SKIT irf
SKIT irf
SKIT irf
SKIT irf
SKNIT irf
SKNIT irf
SKNIT irf
SKNIT irf
SKNIT irf
SKNIT irf
SKNIT irf
SKNIT irf
SKNIT irf
SKNIT irf
SKNIT irf
SKNIT irf
SKNIT irf
SKNIT irf
SKNIT irf
SKNIT irf
SKNIT irf
SKNIT irf
LDEAX rpa3
LDEAX rpa3
LDEAX rpa3
LDEAX rpa3
LDEAX rpa3
LDEAX rpa3
LDEAX rpa3
LDEAX rpa3
LDEAX rpa3
STEAX rpa3
STEAX rpa3
STEAX rpa3
STEAX rpa3
STEAX rpa3
STEAX rpa3
STEAX rpa3
STEAX rpa3
STEAX rpa3
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
3
2
2
2
3
2
2
2
2
3
2
2
2
3
Skip if FT0 = 1,
Skip if FT1 = 1,
Skip if F1 = 1,
Skip if F2 = 1,
Skip if FE0 = 1,
Skip if FE1 = 1,
Skip if FEIN = 1,
Skip if FAD = 1,
Skip if FSR = 1,
Skip if FST = 1,
Skip if ER = 1,
Skip if OV = 1,
Skip if AN4 = 1,
Skip if AN5 = 1,
Skip if AN6 = 1,
Skip if AN7 = 1,
Skip if SB = 1,
Skip if NMI = 0,
Skip if FT0 = 0,
Skip if FT1 = 0,
Skip if F1 = 0,
Skip if F2 = 0,
Skip if FE0 = 0,
Skip if FE1 = 0,
Skip if FEIN = 0,
Skip if FAD = 0,
Skip if FSR = 0,
Skip if FST = 0,
Skip if ER = 0,
Skip if OV = 0,
Skip if AN4 = 0,
Skip if AN5 = 0,
Skip if AN6 = 0,
Skip if AN7 = 0,
Skip if SB = 0,
EAL<(DE), EAH<(DE+1)
EAL<(HL), EAH<(HL+1)
EAL<(DE++), EAH<(DE++ +1)
EAL<(HL++), EAH<(HL++ +1)
EAL<(DE+byte), EAH<(DE+byte+1)
EAL<(HL+A), EAH<(HL+A+1)
EAL<(HL+B), EAH<(HL+B+1)
EAL<(HL+EA), EAH<(HL+EA+1)
EAL<(HL+byte), EAH<(HL+byte+1)
(DE)<EAL, (DE+1)<EAH
(HL)<EAL, (HL+1)<EAH
(DE++)<EAL, (DE++ +1)<EAH
(HL++)<EAL, (HL++ +1)<EAH
(DE+byte)<EAL, (DE+byte+1)<EAH
(HL+A)<EAL, (HL+A+1)<EAH
(HL+B)<EAL, (HL+B+1)<EAH
(HL+EA)<EAL, (HL+EA+1)<EAH
(HL+byte)<EAL, (HL+byte+1)<EAH
21
48 A0
48 A4
48 A8
48 B0
48 B4
48 BB
48 C0
48 C1
48 D2
48 D3
49
4A
4B
4C
4D
4E
4F
50
51
52
53
54
55
56
57
5H
60 0H
60 1L
60 1H
60 2L
60 2H
60 3L
60 3H
60 4L
60 5L
60 6L
60 6H
60 7L
60 7H
60 8H
60 9L
60 9H
60 AL
60 AH
60 BL
60 BH
60 CL
60 CH
60 DL
60 DH
60 EL
60 EH
60 FL
DSLR EA
DSLL EA
TABLE
DRLR EA
DRLL EA
STOP
DMOV EA,sr4
DMOV EA,sr4
DMOV sr3,EA
DMOV sr3,EA
MVIX rpa1, byte
MVIX rpa1, byte
MVIX rpa1, byte
MOV A,sr1
MOV sr,A
JRE
JRE
EXH
DCR r2
DCR r2
DCR r2
JMP word
OFFIW wa,byte
ACI A,byte
OFFI A,byte
BIT bit,wa
ANA r,A
XRA r,A
ORA r,A
ADDNC r,A
GTA r,A
SUBNB r,A
LTA r,A
ADD r,A
ADC r,A
SUB r,A
NEA r,A
SBB r,A
EQA r,A
ANA A,r
XRA A,r
ORA A,r
ADDNC A,r
GTA A,r
SUBNB A,r
LTA A,r
ADD A,r
ONA A,r
ADC A,r
OFFA A,r
SUB A,r
NEA A,r
SBB A,r
2
2
2
2
2
1
2
2
2
2
2
2
2
2
2
2
2
1
1
1
1
3
3
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
EA shift logical right
EA shift logical left
C < (PC+3+A), B < (PC+3+A+1)
EA rotate logical right
EA rotate logical left
Set software Stop mode
EA < ECNT
EA < ECPT
ETM0 < EA
ETM1 < EA
(BC) < byte
(DE) < byte
(HL) < byte
A < sr1
(1 1 s5 s4 s3 s2 s1)
sr < A
(1 1 s5 s4 s3 s2 s1)
PC < PC + 2 + disp forward
PC < PC + 2 - disp backward
Alternate H, L register sets
A < A - 1, Skip if borrow
B < B - 1, Skip if borrow
C < C - 1, Skip if borrow
PC < word
(V / offset) AND byte, Skip if zero
A < A + byte + CY
A AND byte, Skip if zero
Skip if (V / offset) bit (b2,b1,b0) is 1
r < r AND A
(r = V, A, B, C, D, E, H, L)
r < r EX-OR A
(r = V, A, B, C, D, E, H, L)
r < r OR A
(r = V, A, B, C, D, E, H, L)
r < r + A, Skip if no carry
r - A - 1, Skip if no borrow
r < r - A, Skip if no carry
r - A, Skip if borrow
r<r+A
(r = V, A, B, C, D, E, H, L)
r < r + A + CY
(r = V, A, B, C, D, E, H, L)
r<r-A
(r = V, A, B, C, D, E, H, L)
r - A, Skip if no zero
r < r - A - CY
(r = V, A, B, C, D, E, H, L)
r - A, Skip if zero
A < A AND r
(r = V, A, B, C, D, E, H, L)
A < A EX-OR r
(r = V, A, B, C, D, E, H, L)
A < A OR r
(r = V, A, B, C, D, E, H, L)
A < A + r, Skip if no carry
A - r - 1, Skip if no borrow
A < A - r, Skip if no carry
A - r, Skip if borrow
A<A+r
(r = V, A, B, C, D, E, H, L)
A AND r, Skip if no zero
A < A + r + CY (r = V, A, B, C, D, E, H, L)
A AND r, Skip if zero
A<A-r
(r = V, A, B, C, D, E, H, L)
A - r, Skip if no zero
A < a - r - CY
(r = V, A, B, C, D, E, H, L)
22
60 FH
61
62
63
64 0L
64 8L
64 0H
EQA A,r
DAA
RETI
STAW wa
MVI sr2,byte
MVI sr2,byte
ANI sr2,byte
2
1
1
2
3
3
3
64 8H
ANI sr2,byte
3
64 1L
XRI sr2,byte
3
64 9L
XRI sr2,byte
3
64 1H
ORI sr2,byte
3
64 9H
ORI sr2,byte
3
64 2L
ADINC sr2,byte
3
64 AL
ADINC sr2,byte
3
64 2H
GTI sr2,byte
3
64 AH
GTI sr2,byte
3
64 3L
SUINB sr2,byte
3
64 BL
SUINB sr2,byte
3
64 3H
LTI sr2,byte
3
64 BH
LTI sr2,byte
3
64 4L
ADI sr2,byte
3
64 CL
64 4H
ADI sr2,byte
ONI sr2,byte
3
3
64 CH
ONI sr2,byte
3
64 5L
ACI sr2,byte
3
64 DL
ACI sr2,byte
3
64 5H
OFFI sr2,byte
3
64 DH
OFFI sr2,byte
3
64 6L
SUI sr2,byte
3
64 EL
64 6H
SUI sr2,byte
NEI sr2,byte
3
3
A - r, Skip if zero
Decimal adjust A
Return from Interrupt
(V / offset ) < A
sr2 < byte (PA,PB,PC,PD, -,PF,MKH,MKL)
sr2 < byte (ANM,SMH,-,EOM, -,TMM,-,-)
sr2 < sr2 AND byte, (PA,PB,PC,PD, ,PF,MKH,MKL)
sr2 < sr2 AND byte, (ANM,SMH,-,EOM, ,TMM,-,-)
sr2 < sr2 EX-OR byte (PA,PB,PC,PD, ,PF,MKH,MKL)
sr2 < sr2 EX-OR byte (ANM,SMH,-,EOM, ,TMM,-,-)
sr2 < sr2 OR byte, (PA,PB,PC,PD, ,PF,MKH,MKL)
sr2 < sr2 OR byte, (ANM,SMH,-,EOM, ,TMM,-,-)
sr2 < sr2 + byte, Skip if no carry
(PA,PB,PC,PD, -,PF,MKH,MKL)
sr2 < sr2 + byte, Skip if no carry (ANM,SMH,,EOM, -,TMM,-,-)
sr2 - byte-1, Skip if no borrow (PA,PB,PC,PD, ,PF,MKH,MKL)
sr2 - byte-1, Skip if no borrow (ANM,SMH,,EOM, -,TMM,-,-)
sr2 < sr2 - byte, Skip if no borrow
(PA,PB,PC,PD, -,PF,MKH,MKL)
sr2 < sr2 - byte, Skip if no borrow
(ANM,SMH,-,EOM, -,TMM,-,-)
sr2 - byte, Skip if borrow (PA,PB,PC,PD, ,PF,MKH,MKL)
sr2 - byte, Skip if borrow (ANM,SMH,-,EOM,
-,TMM,-,-)
sr2 < sr2 + byte (PA,PB,PC,PD, ,PF,MKH,MKL)
sr2 < sr2 + byte (ANM,SMH,-,EOM, -,TMM,-,-)
sr2 AND byte, Skip if no zero (PA,PB,PC,PD, ,PF,MKH,MKL)
sr2 AND byte, Skip if no zero (ANM,SMH,,EOM, -,TMM,-,-)
sr2 < sr2 + byte + CY (PA,PB,PC,PD, ,PF,MKH,MKL)
sr2 < sr2 + byte + CY (ANM,SMH,-,EOM, ,TMM,-,-)
sr2 AND byte, Skip if zero (PA,PB,PC,PD, ,PF,MKH,MKL)
sr2 AND byte, Skip if zero (ANM,SMH,,EOM, -,TMM,-,-)
sr2 < sr2 - byte (PA,PB,PC,PD, ,PF,MKH,MKL)
sr2 < sr2 - byte (ANM,SMH,-,EOM, -,TMM,-,-)
sr2 - byte, Skip if no zero (PA,PB,PC,PD, ,PF,MKH,MKL)
23
64 EH
NEI sr2,byte
3
64 7L
SBI sr2,byte
3
64 FL
SBI sr2,byte
3
64 7H
EQI sr2,byte
3
64 FH
EQI sr2,byte
3
65
66
67
68
69
6A
6B
6C
6D
6E
6F
70 0E
70 0F
70 1E
70 1F
70 2E
70 2F
70 3E
70 3F
70 41
70 42
70 43
70 61
70 62
70 63
70 6H
70 7H
70 8H
NEIW wa,byte
SUI A,byte
NEI A,byte
MVI r,byte
MVI r,byte
MVI r,byte
MVI r,byte
MVI r,byte
MVI r,byte
MVI r,byte
MVI r,byte
SSPD word
LSPD word
SBCD word
LBCD word
SDED word
LDED word
SHLD word
LHLD word
EADD EA,r2
EADD EA,r2
EADD EA,r2
ESUB EA,rp3
ESUB EA,rp3
ESUB EA,rp3
MOV r,word
MOV word,r
ANAX rpa
3
2
2
2
2
2
2
2
2
2
2
4
4
4
4
4
4
4
4
2
2
2
2
2
2
4
4
2
70 9L
XRAX rpa
2
70 9H
ORAX rpa
2
70 AL
70 AH
70 BL
70 BH
70 CL
ADDNCX rpa
GTAX rpa
SUBNBX rpa
LTAX rpa
ADDX rpa
2
2
2
2
2
70 CH
70 DL
ONAX rpa
ADCX rpa
2
2
70 DH
70 EL
OFFAX rpa
SUBX rpa
2
2
sr2 - byte, Skip if no zero (ANM,SMH,-,EOM,
-,TMM,-,-)
sr2 < sr2 - byte - CY, (PA,PB,PC,PD, ,PF,MKH,MKL)
sr2 < sr2 - byte - CY, (ANM,SMH,-,EOM, ,TMM,-,-)
sr2 - byte, Skip if zero (PA,PB,PC,PD, ,PF,MKH,MKL)
sr2 - byte, Skip if zero (ANM,SMH,-,EOM, ,TMM,-,-)
(V / offset) - byte, Skip if no zero
A < A - byte
A - byte, Skip if no zero
V < byte
A < byte
B < byte
C < byte
D < byte
E < byte
H < byte
L < byte
(word) < SP(low), (word + 1) < SP(hi)
SP(lo) < (word), SP(hi) < (word + 1)
(word) < C, (word + 1) < B
C < (word), B < (word + 1)
(word) < E, (word + 1) < D
E < (word), D < (word + 1)
(word) < L, (word + 1) < H
L < (word), H < (word + 1)
EA < EA + A
EA < EA + B
EA < EA + C
EA < EA - A
EA < EA - B
EA < EA - C
r < (word)
(r = V, A, B, C, D, E, H, L)
(word) < r
(r = V, A, B, C, D, E, H, L)
A<A AND (rpa),
(-,BC,DE,HL, DE+,HL+,DE-,HL-)
A<A EX-OR (rpa),
(-,BC,DE,HL, DE+,HL+,DE-,HL-)
A<A OR (rpa),
(-,BC,DE,HL, DE+,HL+,DE-,HL-)
A < A + (rpa),
Skip if no carry
A - (rpa) - 1,
Skip if no borrow
A < A - (rpa) - CY,
Skip if no borrow
A _ (rpa),
Skip if borrow
A<A+(rpa),
(-,BC,DE,HL, DE+,HL+,DE-,HL-)
A AND (rpa),
Skip if no zero
A<A+(rpa)+CY,
(-,BC,DE,HL, DE+,HL+,DE-,HL-)
A AND (rpa),
Skip if zero
A<A-(rpa), (-,BC,DE,HL, DE+,HL+,DE-,HL-)
24
70 EH
70 FL
NEAX rpa
SBBX rpa
2
2
70 FH
71
72
74 0L
74 1L
74 1H
74 2L
74 2H
74 3L
74 3H
74 4L
74 4H
74 5L
74 5H
74 6L
74 6H
74 7L
74 7H
74 88
74 8D
74 8E
74 8F
74 90
74 95
74 96
74 97
74 98
74 9D
74 9E
74 9F
74 A0
74 A5
74 A6
74 A7
74 A8
74 AD
74 AE
74 AF
74 B0
74 B5
74 B6
74 B7
74 B8
74 BD
74 BE
74 BF
74 C0
74 C5
74 C6
74 C7
74 C8
EQAX rpa
MVIW wa,byte
SOFTI
ANI r,byte
XRI r,byte
ORI r,byte
ADINC r,byte
GTI r,byte
SUINB r,byte
LTI r,byte
ADI r,byte
ONI r,byte
ACI r,byte
OFFI r,byte
SUI r,byte
NEI r,byte
SBI r,byte
EQI r,byte
ANAW wa
DAN EA,rp3
DAN EA,rp3
DAN EA,rp3
XRAW wa
DXR EA,rp3
DXR EA,rp3
DXR EA,rp3
ORAW wa
DOR EA,rp3
DOR EA,rp3
DOR EA,rp3
ADDNCW wa
DADDNC EA,rp3
DADDNC EA,rp3
DADDNC EA,rp3
GTAW wa
DGT EA,rp3
DGT EA,rp3
DGT EA,rp3
SUBNBW wa
DSUBNB EA,rp3
DSUBNB EA,rp3
DSUBNB EA,rp3
LTAW wa
DLT EA,rp3
DLT EA,rp3
DLT EA,rp3
ADDW wa
DADD EA,rp3
DADD EA,rp3
DADD EA,rp3
ONAW wa
2
3
1
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
2
2
2
3
2
2
2
3
2
2
2
3
2
2
2
3
2
2
2
3
2
2
2
3
2
2
2
3
2
2
2
3
A - (rpa),
Skip if no zero
A<A-(rpa)-CY,
(-,BC,DE,HL, DE+,HL+,DE-,HL-)
A - (rpa),
Skip if zero
( V / offset ) < byte
Software Interrupt
r < r AND byte, (r = V,A,B,C, D,E,H,L)
r < r EX-OR byte, (r = V,A,B,C, D,E,H,L)
r < r OR byte, (r = V,A,B,C, D,E,H,L)
r < r + byte, Skip if no carry
r - byte - 1, Skip if no borrow
r < r - byte, Skip if no borrow
r - byte, Skip if borrow
r < r + byte, (r = V,A,B,C, D,E,H,L)
r AND byte, Skip if no zero
r < r + byte + CY, (r = V,A,B,C, D,E,H,L)
r AND byte, Skip if zero
r < r - byte, (r = V,A,B,C, D,E,H,L)
r - byte, Skip if no zero
r < r - byte - CY, (r = V,A,B,C, D,E,H,L)
r - byte, Skip if zero
A < A AND ( V / offset )
EA < EA AND BC,
EA < EA AND DE
EA < EA AND HL,
A < A EX-OR ( V / offset )
EA , EA EX-OR BC,
EA , EA EX-OR DE,
EA , EA EX-OR HL,
A < A OR ( V / offset )
EA < EA OR BC, (BC, DE, HL)
EA < EA OR DE, (BC, DE, HL)
EA < EA OR HL, (BC, DE, HL)
A < A + ( V / offset ), Skip if no carry
EA < EA + BC, Skip if no carry,
EA < EA + DE, Skip if no carry,
EA < EA + HL, Skip if no carry,
A - ( V / offset ) - 1, Skip if no borrow
EA-BC-1, Skip if no borrow,
EA-DE-1, Skip if no borrow,
EA-HL-1, Skip if no borrow,
A < A - ( V / offset ), Skip if no borrow
EA < EA - BC, Skip if no borrow,
EA < EA - DE, Skip if no borrow,
EA < EA - HL, Skip if no borrow,
A - ( V / offset ), Skip if borrow
EA - BC Skip if borrow,
EA - DE, Skip if borrow,
EA - HL, Skip if borrow,
A < A + ( V / offset )
EA < EA + BC,
EA < EA + DE,
EA < EA +HL,
A AND ( V / offset ), Skip if no Zero
25
74 CD
74 CE
74 CF
74 D0
74 D5
74 D6
74 D7
74 D8
74 DD
74 DE
74 DF
74 E0
74 E5
74 E6
74 E7
74 E8
74 ED
74 EE
74 EF
74 F0
74 F5
74 F6
74 F7
74 F8
74 FD
74 FE
74 FF
75
76
77
78
79
7A
7B
7C
7D
7E
7F
80
81
82
83
84
85
86
87
88
89
8A
8B
8C
8D
8E
DON EA,rp3
DON EA,rp3
DON EA,rp3
ADCW wa
DADC EA,rp3
DADC EA,rp3
DADC EA,rp3
OFFAW wa
DOFF EA,rp3
DOFF EA,rp3
DOFF EA,rp3
SUBW wa
DSUB EA,rp3
DSUB EA,rp3
DSUB EA,rp3
NEAW wa
DNE EA,rp3
DNE EA,rp3
DNE EA,rp3
SBBW wa
DSBB EA,rp3
DSBB EA,rp3
DSBB EA,rp3
EQAW wa
DEQ EA,rp3
DEQ EA,rp3
DEQ EA,rp3
EQIW wa,byte
SBI A,byte
EQI A,byte
CALF word
CALF word
CALF word
CALF word
CALF word
CALF word
CALF word
CALF word
CALT
CALT
CALT
CALT
CALT
CALT
CALT
CALT
CALT
CALT
CALT
CALT
CALT
CALT
CALT
2
2
2
3
2
2
2
3
2
2
2
3
2
2
2
3
2
2
2
3
2
2
2
3
2
2
2
3
2
2
2
2
2
2
2
2
2
2
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
EA AND BC, Skip if no zero,
EA AND DE, Skip if no zero,
EA AND HL, Skip if no zero,
A < A + ( V / offset ) + CY
EA < EA + BC + CY,
EA < EA + DE + CY,
EA < EA + HL + CY,
A AND ( V / offset ), Skip if zero
EA AND BC, Skip if zero,
EA AND DE, Skip if zero,
EA AND HL, Skip if zero,
A < A - ( V / offset )
EA < EA -BC,
EA < EA - DE,
EA < EA - HL,
A - ( V / offset ), Skip if no zero
EA - BC, Skip if no zero,
EA - DE, Skip if no zero,
EA - HL, Skip if no zero,
A < A - ( V / offset ) - CY
EA < EA - BC - CY,
EA < EA - DE - CY,
EA < EA - HL - CY,
A - ( V / offset ), Skip if zero
EA - BC, Skip if zero,
EA - DE, Skip if zero,
EA - HL, Skip if zero,
(V / offset) - byte, Skip if zero
A < A - byte - CY
A - byte, Skip if zero
Subroutine call to 8xx
Subroutine call to 9xx
Subroutine call to Axx
Subroutine call to Bxx
Subroutine call to Cxx
Subroutine call to Dxx
Subroutine call to Exx
Subroutine call to Fxx
Subroutine call to Jump Table 80
Subroutine call to Jump Table 82
Subroutine call to Jump Table 84
Subroutine call to Jump Table 86
Subroutine call to Jump Table 88
Subroutine call to Jump Table 8A
Subroutine call to Jump Table 8C
Subroutine call to Jump Table 8E
Subroutine call to Jump Table 90
Subroutine call to Jump Table 92
Subroutine call to Jump Table 94
Subroutine call to Jump Table 96
Subroutine call to Jump Table 98
Subroutine call to Jump Table 9A
Subroutine call to Jump Table 9C
26
8F
90
91
92
93
94
95
96
97
98
99
9A
9B
9C
9D
9E
9F
A0
A1
A2
A3
A4
A5
A6
A7
A8
A9
AA
AB
AC
AD
AE
AF
B0
B1
B2
B3
B4
B5
B6
B7
B8
B9
BA
BB
BC
BD
BE
BF
C0
C1
C2
C3
CALT
CALT
CALT
CALT
CALT
CALT
CALT
CALT
CALT
CALT
CALT
CALT
CALT
CALT
CALT
CALT
CALT
POP rp1
POP rp1
POP rp1
POP rp1
POP rp1
DMOV EA,rp3
DMOV EA,rp3
DMOV EA,rp3
INX EA
DCX EA
EI
LDAX rpa2
LDAX rpa2
LDAX rpa2
LDAX rpa2
LDAX rpa2
PUSH rp1
PUSH rp1
PUSH rp1
PUSH rp1
PUSH rp1
DMOV rp3,EA
DMOV rp3,EA
DMOV rp3,EA
RET
RETS
DI
STAX rpa2
STAX rpa2
STAX rpa2
STAX rpa2
STAX rpa2
JR
JR
JR
JR
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
2
1
1
1
2
1
1
1
1
1
1
1
1
1
1
1
2
1
1
1
2
1
1
1
1
Subroutine call to Jump Table 9E
Subroutine call to Jump Table A0
Subroutine call to Jump Table A2
Subroutine call to Jump Table A4
Subroutine call to Jump Table A6
Subroutine call to Jump Table A8
Subroutine call to Jump Table AA
Subroutine call to Jump Table AC
Subroutine call to Jump Table AE
Subroutine call to Jump Table B0
Subroutine call to Jump Table B2
Subroutine call to Jump Table B4
Subroutine call to Jump Table B6
Subroutine call to Jump Table B8
Subroutine call to Jump Table BA
Subroutine call to Jump Table BC
Subroutine call to Jump Table BE
A<(SP), V<(SP+1), SP<SP+2
C<(SP), B<(SP+1), SP<SP+2
E<(SP), D<(SP+1), SP<SP+2
L<(SP), H<(SP+1), SP<SP+2
EA(lo)<(SP), EA(hi)<(SP+1), SP<SP+2
EA < BC
EA < DE
EA < HL
EA < EA + 1
EA < EA - 1
Enable Interrupt
A < (DE + byte)
A < (HL + A)
A < (HL + B)
A < (HL + EA)
A < (HL + byte)
(SP-1)<V, (SP-2)<A, SP<SP-2
(SP-1)<B, (SP-2)<C, SP<SP-2
(SP-1)<D, (SP-2)<E, SP<SP-2
(SP-1)<H, (SP-2)<L, SP<SP-2
(SP-1)<EA(hi), (SP-2)<EA(lo), SP<SP-2
BC < EA
DE < EA
HL < EA
Return from subroutine
Return from subroutine then Skip
Disable Interrupt
(DE + byte) < A
(HL + A) < A
(HL + B) < A
(HL + EA) < A
(HL + byte) < A
Jump 1
Jump 2
Jump 3
Jump 4
27
C4
C5
C6
C7
C8
C9
CA
CB
CC
CD
CE
CF
D0
D1
D2
D3
D4
D5
D6
D7
D8
D9
DA
DB
DC
DD
DE
DF
E0
E1
E2
E3
E4
E5
E6
E7
E8
E9
EA
EB
EC
ED
EE
EF
F0
F1
F2
F3
F4
F5
F6
F7
F8
JR
JR
JR
JR
JR
JR
JR
JR
JR
JR
JR
JR
JR
JR
JR
JR
JR
JR
JR
JR
JR
JR
JR
JR
JR
JR
JR
JR
JR
JR
JR
JR
JR
JR
JR
JR
JR
JR
JR
JR
JR
JR
JR
JR
JR
JR
JR
JR
JR
JR
JR
JR
JR
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
Jump 5
Jump 6
Jump 7
Jump 8
Jump 9
Jump 10
Jump 11
Jump 12
Jump 13
Jump 14
Jump 15
Jump 16
Jump 17
Jump 18
Jump 19
Jump 20
Jump 21
Jump 22
Jump 23
Jump 24
Jump 25
Jump 26
Jump 27
Jump 28
Jump 29
Jump 30
Jump 31
Jump 32
Jump -31
Jump -30
Jump -29
Jump -28
Jump -27
Jump -26
Jump -25
Jump -24
Jump -23
Jump -22
Jump -21
Jump -20
Jump -19
Jump -18
Jump -17
Jump -16
Jump -15
Jump -14
Jump -13
Jump -12
Jump -11
Jump -10
Jump -9
Jump -8
Jump -7
28
F9
FA
FB
FC
FD
FE
FF
JR
JR
JR
JR
JR
JR
JR
1
1
1
1
1
1
1
Jump -6
Jump -5
Jump -4
Jump -3
Jump -3
Jump -2
Jump -0
29
Modified
Roland PG1000
eForth Programming Tool
30
;===============================================================
;
;
eForth 1.0 by Bill Muench and C. H. Ting, 1990
;
Much of the code is derived from the following sources:
;
8086 figForth by Thomas Newman, 1981 and Joe smith, 1983
;
aFORTH by John Rible
;
bFORTH by Bill Muench
;
;
eForth is a small portable Forth design for a wide range of
;
microprocessors.
;
;
The goal of this implementation is to provide a simple eForth Model
;
which can be ported easily to many 8, 16, 24 and 32 bit CPU's.
;
The following attributes make it suitable for CPU's of the '90:
;
;
small machine dependent kernel and portable high level code
;
source code in the MASM format
;
direct threaded code
;
separated code and name dictionaries
;
simple vectored terminal and file interface to host computer
;
aligned with the proposed ANS Forth Standard
;
easy upgrade path to optimize for specific CPU
;
;
You are invited to implement this Model on your favorite CPU and
;
contribute it to the eForth Library for public use. You may use
;
a portable implementation to advertise more sophisticated and
;
optimized version for commercial purposes. However, you are
;
expected to implement the Model faithfully. The eForth Working
;
Group reserves the right to reject implementation which deviates
;
significantly from this Model.
;
;
As the ANS Forth Standard is still evolving, this Model will
;
change accordingly. Implementations must state clearly the
;
version number of the Model being tracked.
;
;
Representing the eForth Working Group in the Silicon Valley FIG Chapter.
;
Send contributions to:
;
;
Dr. C. H. Ting
;
156 14th Avenue
;
San Mateo, CA 94402
;
(415) 571-7639
;
This disk and the companion manual 'eForth Implementation Guide'
are available from Offete enterprises, Inc., 1306 South B Street,
San Mateo, CA 94402, (415)574-8250 for $25. The other implementation
8051 eForth and its manual are also distributed by Offete for $25.
31
eForth Glossary
Derived from bFORTH by Bill Muench, 1990.
WARNING: Advanced information -- subject to change.
Attributes
C
D
I
U
Capitalized symbols.
the word may only be used during compilation of a colon definition.
the word is a defining word.
the word is IMMEDIATE and will execute during compilation, unless special action is taken.
a user value.
================================================================
Stack notes
( compile \ run \ child ;Return ;Float ; <input stream> )
( before -- after ;R before -- after ;F before -- after ; <string> )
================================================================
Glossary
!( w a -- )"store"
Store a 16-bit number at aligned address.
!CSP( -- )"set c s p"
Save the values of the current stack pointers.
!IO( -- )"store i o"
Initialize the serial I/O device.
#( d -- d )"number sign"
Convert one digit of a number using the current base. Must be used within <# and #> .
#>( d -- b u )"number sign greater"
Terminate a numeric conversion.
#S( ud -- 0 0 )"number sign s"
Convert all digits of a number using the current base.
#TIB( -- a )"number t i b"
The system double variable which holds the size and aligned address of the terminal input buffer.
$"( -- ; <string> \ -- $ )I,C"string quote"
Used only within a definition to compile an inline packed string terminated by the " double quote character.
At run-time the address of the packed string is pushed on the data stack.
$"|( -- $ )C"string quote primitive"
Return the address of a compiled inline packed string. The run-time primitive compiled by " .
$,"( -- ; <string> )"string comma quote"
Compile an inline packed character string into the code area, terminated by the " double quote character.
$,n( $ -- )"string comma n"
Create a name for a definition using string.
code is compiled.
The name is not linked into the dictionary.
$COMPILE( $ -- )
Convert a string to a word address.
Set the code pointer to the next free cell in the code area, no
Execute the word in interpreting mode or compile it if in compiling mode.
$INTERPRET( $ -- )"string interpret"
At the interactive level, if a word is defined perform its action. If not, try to convert it to a number, if
32
that fails, issue an error message.
'( -- ca ; <string> )"tick"
Return the code address of the word following.
'?KEY( -- a )U"tick question key"
The system input device status vector.
'BOOT( -- a )
Return the address of a system boot-up routine.
'ECHO( -- a )U"tick echo"
The system echo device vector.
'EMIT( -- a )U"tick emit"
The system output device vector.
'EVAL( -- a )"tick eval"
The system interpret/compile vector.
'EXPECT( -- a )U"tick expect"
The system line input vector.
'NUMBER( -- a )"tick number"
The system number conversion vector.
'PROMPT( -- a )U"tick prompt"
The system prompt vector.
'TAP( -- a )U"tick tap"
The input case function vector.
(( -- ; <string> )I"paren"
Begin a comment. The comment is terminated by the )character. May be used inside or outside a definition.
*( n n -- n )"star"
Multiply two signed numbers. Return a 16-bit signed number.
*/( n1 n2 n3 -- q )"star slash"
Multiply n1 by n2 producing the 32-bit intermediate product d. Divide d by n3 producing a 16-bit quotient.
*/MOD( n1 n2 n3 -- r q )"star slash mod"
Multiply n1 by n2 producing the 32-bit intermediate product d. Divide d by n3 producing a 16-bit remainder and
a 16-bit quotient.
+( w w -- w )"plus"
Addition.
+!( n a -- )"plus store"
Increment the 16-bit value at address by n.
,( w -- )"comma"
Compile a 16-bit value into the code area.
-( w w -- w )"minus"
Subtract the top from the second element on the data stack.
-TRAILING( b u -- b u )"dash trailing"
Adjust the count to eliminate any trailing white-space in the string.
.( n -- )"dot"
Display the single value, use the current base. If BASE is DECIMAL , display as a signed number.
."( -- ; <string> )I,C"dot quote"
Used only within a definition to compile an inline packed string terminated by the " double quote character.
At run-time the string is displayed on the current output device.
33
."|( -- )C"dot quote primitive"
Display a compiled inline packed string to the current output device. This run-time primitive is compiled by
." .
.(( -- ; <string> )I"dot paren"
Begin a comment that is displayed to the current output device. May be used inside or outside a definition.
.ID( na -- )"dot i d"
Display the packed string at address.
.OK( -- )"dot o k"
Display the standard system prompt.
.R( n +n -- )"dot r"
Display the single value right-justified in a field of width +n, use the current base.
.S( ? -- ? )"dot s"
Display the contents of the data stack.
/( n n -- q )"slash"
Floored division for 16-bit numbers. Returns only the 16-bit quotient.
/MOD( n n -- r q )"slash mod"
Floored division for 16-bit numbers. 16-bit remainder and 16-bit quotient.
0<( n -- t )"zero less"
Return true if n is less than 0, negative. Comparison is signed. Also used for sign extension.
0=( w -- t )"zero equals"
Return true if w is equal to 0.
2!( d a -- )"two store"
Store a 32-bit value at aligned address.
2@( a -- d )"two fetch"
Return the 32-bit value stored at aligned address.
2DROP( d -- )"two drop"
Pop the 32-bit number, or the top two 16-bit numbers, from the data stack.
2DUP( d -- d d )"two dupe"
Duplicate the 32-bit number, or the top two 16-bit numbers, on the data stack.
:( -- ; <string> )D"colon"
Begin a colon definition to be added to the current vocabulary.
;( -- )I,C"semicolon"
Terminate a colon definition begun with : .
<( n1 n2 -- t )"less than"
Return true if n1 is less than n2. Comparison is signed.
<#( -- )"start number""less number sign"
Begin a numeric conversion.
=( w w -- t )"equals"
Return true if w1 is equal to w2.
>CHAR( u -- c )"to character"
Convert a value to a printable character. Replace an unprintable character with the _ underscore character.
>IN( -- a )"to in"
The pointer into the input stream.
>NAME( ca -- na, F )"to name"
34
If possible, convert a code address to a name address. If not possible, return a false flag.
>R( w -- ;R -- w )C"to r"
Pop the top element of the data stack and Push it on the return stack.
?( a -- )"question"
Display the single value stored at address, use the current base. If BASE is DECIMAL , display as a signed
number.
?branch( f -- )"question branch"
Run time rouitne to redirect execution to the address in the next cell if flag is false.
?CSP( -- )"question c s p"
Compare the current value of the stack pointers with the saved values. ABORT with an error message if
different.
?DUP( w -- w w, 0 )"question dupe"
Duplicate the number on top of the data stack only if it is non-zero.
?KEY( -- t )"question key"
Return the status of the current input device.
?RX( -- c T, F )"question r x"
Return a character from the input device and true.
Return false only if no character is pending.
?STACK( -- )"question stack"
Display an error message if the stack limits have been exceeded.
?UNIQUE( $ -- $ )"question unique"
Display a warning massage for a duplicate definition.
@( a -- w )"fetch"
Return the 16-bit value stored at aligned address.
@EXECUTE( a -- )"fetch execute"
Fetch the execution token stored at address and execute it, ie indirect execution. If the value contained in
address is zero, do nothing.
ABORT( -- )
Reset the data stack and perform the function of QUIT . Note, no message is displayed.
ABORT"( -- ; <string> \ f -- )I,C"abort quote"
Used only within a definition to compile an inline packed string terminated the " double quote character. At
run-time, if the flag
is false, execute the sequence of words following the string. Otherwise, the string is displayed on the
current output ce,
execution is then passed to an error handling routine.
abort"( f -- )C"abort quote primitive"
The run-time primitive compiled by ABORT" .
ABS( n -- +n )
Return the absolute value of n.
accept( b u -- b u )
Receive a line of u characters maximum to the an input buffer at byte address. Terminate input if a carriage
return is received. Return the actual count of received characters. Perform any currently defined keyboard
macros. Use the current input device.
AFT( a -- a a \ -- )I,C
Used within a loop structure to unconditional skip a portion of code the first time thru the loop. AFT
compiles the machine unconditional branch instruction and leaves an address to be resolved by THEN .
AGAIN( a -- \ -- )I,C
Terminate an infinite loop structure. AGAIN compiles an unconditional branch instruction, and uses the address
left by BEGIN to resolve this backward branch.
35
AHEAD( -- a \ -- )I,C
Mark the beginning of a forward branching, unconditional branch structure. AHEAD compiles the machine
unconditional branch instruction and leaves an address to be resolved by THEN .
ALIGNED( b -- a )
Convert a byte address to a word aligned address.
ALLOT( n -- )
Adjust the code area pointer by n.
AND( w w -- w )
A bitwise logical AND.
BASE( -- a )U
The system variable which holds the current numeric conversion radix.
BEGIN( -- a \ -- )I,C
Mark the beginning of an indefinite loop structure. Leave an address to be resolved by UNTIL, or WHILE and
REPEAT .
BL( -- c )"b l"
Push the value of a space, the blank character, on the data stack.
branch( -- )C
Run time routine to redirect execution to the address in the next cell.
BYE( -- )
Exit Forth and return to the underlying environment or DOS.
C!( v b -- )"c store"
Store an byte value at byte address.
C@( b -- v )"c fetch"
Return the byte value stored at byte address.
CALL,( a -- )C"call comma"
Assemble a 4 byte subroutine call to the designated address.
CATCH( ca -- err#/0 )
Setup a local error frame and execute the word referenced by the execution token ca. Return a non-zero error
number or zero for no error.
CELL+( a1 -- a2 )"cell plus"
Add cell size in bytes to address a1.
CELL-( a1 -- a2 )"cell minus"
Subtract cell size in bytes to address a1.
CELLS( n1 -- n2 )
Multiply n1 by the cell size in byte.
CHAR( -- c ; <string> )
Return the value of the first character in <string>. If used within a defintion, use the phrase [ CHAR
<string> ] LITERAL.
CHARS( +n c -- )
Display +n of character to the current output device.
CMOVE( b1 b2 u -- )"c move"
Move u byte values from byte address b1 to b2, proceeding from lower to higher memory. Overwrite occurs if
b1<b2<b1+u .
COLD( -- )
Completely re-initialize the system, but does not re-load the system from ROM.
COMPILE( -- )C
36
Used only within a definition. At run-time the word following COMPILE is not executed, but its code address is
copied into the code area.
CONSOLE( -- )
Initialize the vectored input and output devices to a terminal.
CONTEXT( -- a )
The variable used to specify the dictionary search order.
COUNT( $ -- b +n )
Return the byte address and byte count of a packed string.
CP( -- a )"c p"
The pointer to the next available dictionary location in code space. Since code and names are seperated, the
traditional DP, dictionary pointer, had to be split into CP, code pointer, and NP, name pointer.
CR( -- )"carriage return"
Position the cursor at the beginning of the next line of the current output device.
CREATE( -- ; <string> \ -- a )D
Build a named definition. At run-time the address pointing to next availabe code space is pushed on the data
stack.
CSP( -- a )"c s p"
The system variable which holds the current stack pointer. Used for error checking.
CURRENT( -- a )
The variable used to specify the vocabulary in which new definitions are compiled.
DECIMAL( -- )
Set decimal as the current BASE . Base 10.
DEPTH( -- n )
The number of elements on the data stack, does not include n .
DIGIT( u -- c )
Convert a single digit number to its character value.
DIGIT?( c base -- v t )"digit question"
Try to convert a character to binary digit. Return true if the digit is valid for the current base.
dm+( a u -- p a+ )"d m plus"
Display the 16-bit values starting at the aligned address a.
DNEGATE( d -- -d )"d negate"
Return the two's complement a double number. Change the sign of a double number.
do$( -- $ )C"do string"
Return the address of a compiled inline packed string.
doLIST( a -- )C"do list"
The run-time routine which executes the list in a colon definition pointed to by a.
doLIT( -- n )C"do literal"
Return the in-line literal compiled by LITERAL.
doUSER( -- )C"do user variable"
The run-time action of user variables.
doVAR( -- a )C"do variable"
The run-time action of variable.
DROP( w -- )
Remove the top element on the data stack.
DUMP( a u -- )
37
Display the HEX and character values starting at aligned address a, for count u.
DUP( w -- w w )"dupe"
Duplicate the top element on the data stack.
ELSE( -- \ a -- a )I,C
Used within a conditional branch structure. ELSE resolves a forward conditional branch compiled by IF . ELSE
then compiles an unconditional branch instruction, leaving an address to be resolve by THEN .
EMIT( w -- )
Output a character to the current output device.
EVAL( -- )
Interpret or compile the tokens from the input stream.
EXECUTE( w -- ;R -- w )
Execute the word definition indicated by the execution token w.
EXIT( -- ;R w -- )
Compile a subroutine return.
EXPECT( b u -- )
Receive a line of u characters maximum to the an input buffer at byte address. Terminate input if a carriage
return is received. The count of received characters is saved in the variable SPAN. Use the current input
device. This word is vectored.
EXTRACT( d base -- d' c )
Used incrementally to convert each digit in a number to its character value.
FILE( -- )
Specify system input from a file using pace handshake. File input is not echoed, all output messages are
displayed.
FILL( b u v -- )
Fill an area at byte address of length u using the byte value v.
find( $ va -- ca f, $ F )"find primitive"
Given a string and a dictionary entry thread, search for a name match. If found, return the code address and a
true flag. If not
found, the string address and a false flag.
FOR( u -- )I,C
Begin a down-counting loop.
Repeat the loop till NEXT u+1 times from u to 0.
FORTH( -- )
Make the default system vocabulary FORTH the context vocabulary.
HAND( -- )
Specify system input from keyboard, no handshake. All input is echoed.
HANDLER( -- a )
The current error handler frame pointer.
HERE( -- a )
Push the address of the next free cell in the code area on the data stack.
HEX( -- )
Set hexadecimal as the current BASE . Base 16.
hi( -- )
Display the sign-on message.
HLD( -- a )"h l d"
The pointer to a formatted numeric output string.
HOLD( c -- )
38
Insert the character in the formatted numeric output string.
I/O( -- a )"i slash o"
An array used by CONSOLE to initialize the system input and output vectors. The vector order is 'KEY? 'KEY and
'EMIT.
IF( -- a \ f -- )I,C
Mark the beginning of a forward branching, conditional branch structure. IF compiles the machine conditional
branch instruction and leaves an address to be resolved by THEN or ELSE .
IMMEDIATE( -- )
Mark the most recently created dictionary entry as a word which will execute during compilation.
INVERT( w -- w )
Bitwise logical invert. Equivalent to -1 XOR. The one's complement.
KEY( -- c )
Return a character from the current input device. If no key is ready, wait until one is available.
kTAP( b b b c -- b b b )"k tap"
The 'tap routine used for file input.
LAST( -- a )
The pointer to the name of the most recently created dictionary entry.
LITERAL( w -- \ -- w )I
Compile a number as an inline value.
M*( n n -- d )"m star"
Multiply two signed numbers. Return a 32-bit signed number.
M/MOD( d n -- r q )"m slash mod"
Floored division of a 32-bit number divided by a 16-bit number. Return a 16-bit quotient and a 16-bit
remainder.
MAX( n n -- n )
Leave the greater of the two signed values.
MIN( n n -- n )
Leave the smaller of the two signed values.
MOD( n n -- r )
Floored division for 16-bit numbers. Returns only the 16-bit remainder.
NAME>( na -- ca )"name to code"
Convert a name address to a code address.
NAME?( $ -- ca f, $ F )"name question"
Given a string, search for a name match. If found, return the code address and a true flag. If not found, the
string address and a
false flag.
NEGATE( n -- -n )
Equivalent to 0 SWAP-. The two's complement of a number. Change the sign of a number.
NEXT( a -- \ -- ;R u -- [u-1] )I,C
Terminate a down-counting loop structure. NEXT compiles the machine loop instruction, pointing to the address
left by FOR . The
loop count is held on the return stack. Looping continues until the count is equal to zero.
next( -- )C
Run-time routine to terminate a down-counting FOR-NEXT loop.
See NEXT.
NP( -- a )"n p"
The pointer to the next available dictionary location in name space.
39
NUF?( -- t )"nuf question"
Continue until paused or terminated by user. Any key will pause, while paused any key except 'enter' will
restart and return
false, enter will return true.
NULL$( -- $ )"null string"
The address of a string with a zero count.
NUMBER?( $ -- d T, $ F )"number question"
Try to convert a packed string to binary number. If possible return the number and a true. Otherwise, return
the string address
and false. A leading '$' for hexidecimal, a leading '-' for negative, and/or the decimal point for a double
number.
OR( w w -- w )
A bitwise logical OR.
OVER( w1 w2 -- w1 w2 w1 )
Copy the second element to the top of the data stack.
OVERT( -- )
Used by ; to link a successfully defined word into the search order.
PACE( -- )
Send the file transfer handshake character.
PACK$( b u $ -- $ )"pack string"
Move and convert the string at byte address with byte count to a packed string at address $ .
PAD( -- a )
Short for scratch pad. Address of a temporary buffer.
PARSE( c -- b u ; <string> )
Scan the current input stream for the given character as a delimiter. Return the beginning byte address and
count of the delimited string.
parse( b u c -- b u delta ; <string> )
Scan string for the given character as a delimiter. Return the beginning byte address and count of the
delimited string. Delta is the beginning to current offset.
PICK( +n -- w )
Copy the +nth data stack value to the top of the data stack.
PRESET( -- )C
Clear the data stack, the return stack and initialize system.
QUERY( -- )
Receive a line to the current input buffer from current input device.
QUIT( -- )
Clear the return stack, set interpret state, and return control to the current command line interpreter.
R>( -- w ;R w -- )C"r from"
Pop the top element of the return stack and Push it on the data stack.
R@( -- w ;R w -- w )"r fetch"
Copy the top element of the return stack and Push it on the data stack.
RECURSE( -- \ -- ;R -- a )I,C
Used only within the word currently being defined to allow self reference. Recursion.
REPEAT( a a -- \ -- )I,C
Terminate an indefinite loop structure. REPEAT compiles an unconditional branch instruction, and uses the
address left by WHILE to resolve this backward branch.
ROT( w1 w2 w3 -- w2 w3 w1 )"rote"
40
Rotate the top three elements on the data stack. Third element to top and all other shifted down.
RP!( a -- )C"r p store"
Set the return stack pointer to address.
RP0( -- a )"r p zero"
Return the bottom address of the return stack pointer.
RP@( -- a )"r p fetch"
Return the address of the return stack pointer.
SAME?( a1 a2 u -- a1' f \ -0+ )"same question"
Compare the two strings, return the beginning address of the first string and a truth flag.
SIGN( n -- )
Display a minus sign if n is negative. Must be used within <# and #> .
SP!( a -- )"s p store"
Set the data stack pointer to address.
SP0( -- a )"s p zero"
Return the bottom address of the data stack pointer.
SP@( -- a )"s p fetch"
Return the address of the data stack pointer.
SPACE( -- )
Display one space, blank character, to the current output device.
SPACES( +n -- )
Display +n spaces, blank characters, to the current output device.
SPAN( -- a )
The system variable which holds the count of characters input by EXPECT.
str( d -- b u )"s t r"???
Convert number to a string in current BASE . Signed if DECIMAL .
SWAP( w1 w2 -- w2 w1 )
Exchange the top two elements on the data stack.
TAP( b b b c -- b b b' )
Echo and store the keystroke, and update the cursor position.
temp( -- a )U
Return address of a user variable for temporary storage.
THEN( a -- \ -- )I,C
Terminate a conditional branch structure. Resolves a forward branch compiled by IF, ELSE, AHEAD, or AFT.
THROW( err# -- err# )
Reset the state of the system to the current local error frame, and update the error flag.
TIB( -- a )"t i b"
Address of the terminal input buffer.
TOKEN( -- $ ; <string> )
Scan the current input stream for a blank delimited word. Move the word to the end of the names area as a
packed string. Return the address of the packed string.
TX!( c -- )"t x store"
Send a character to the output device.
Primitive of EMIT.
TYPE( b u -- )
Output u characters of the string at b address to the current output device.
41
U.( u -- )"u dot"
Display the unsigned single value, use the current base.
U.R( u +n -- )"u dot r"
Display the unsigned single value right-justified in a field of width +n, use the current base.
U<( u1 u2 -- t )"u less"
Return true if u1 is less than u2. Comparison is unsigned.
UM*( u u -- ud )"u m star"
Multiply two unsigned 16-bit numbers. Return an unsigned 32-bit number.
UM+( u u -- ud )"u m plus"
Add two unsigned numbers and return a 32-bit sum.
UM/MOD( ud u -- ur uq )"u m slash mod"
Unsigned division of a 32-bit number divided by a 16-bit number. Return an unsigned 16-bit quotient and an
unsigned 16-bit remainder.
UNTIL( a -- \ f -- )I,C
Terminate an indefinite loop structure. Condition testing is done after executing the code within the loop.
UNTIL compiles the machine conditional branch instruction, and uses the address left by BEGIN to resolve this
backward branch.
UP( -- a )"u p"
Return the address of the current user area.
USER( u -- ; <string> \ -- a )D
Build a named user variable with an offset from the current user base. At run-time the address of the variable
is pushed on the
data stack.
VARIABLE( -- ; <string> \ -- a )D
Build a named variable. At run-time the address of the variable is pushed on the data stack.
VER( -- n )
Return the version code.
Major revision is in the high byte and minor release in the low byte.
VOCABS( -- a )
Return the address of the first vocabulary FORTH in the vocabulary area.
WHILE( a -- a a \ f -- )I,C
Used within an indefinite loop structure. Condition testing is done before executing the code within the loop.
WHILE compiles the machine conditional branch instruction and leaves an address to be resolved by REPEAT .
WITHIN( u lo hi -- t )
Return true if lo <= u < hi. Comparison is unsigned and circular.
WORD( c -- $ ; <string> )
Scan the current input stream for the string delimited by 'c'. Return the address of the packed string.
WORDS( -- )
Display the words in the CONTEXT vocabulary. Display continues until paused or terminated by user.
XIO( a1 a2 a3 -- )"x i o"
Revector 'prompt, 'echo and 'tap to the code addresses on the stack.
XOR( w w -- w )
Bitwise logical Exclusive OR.
[( -- )I"left bracket"
Begin interpreting text from the input stream. Change from compiling to interpreting.
[COMPILE]( -- ; <string> \ -- )I"bracket compile"
Used only within a definition to force the compilation of the following IMMEDIATE word.
42
\( -- ; <string> )I"backslash"
Begin a comment. The comment is terminated by the system end-of-line character. May be used inside or outside
a definition.
]( -- )"right bracket"
Change from interpreting to compiling.
^H( b b b -- b b b' ; <backspace> )"control h"
A keyboard macro to delete characters from the current input stream. No action is taken if the beginning of
the input stream is reached.
_TYPE( b u -- )"printable type"
Display the the string starting at the byte address b, for count u. Substitute _ the underscore character, for
unprintable charact!_TY
43
1
September 12, 2004
78C10 EFORTH
Base Machine Coded Words
Interpreter Pointer
Data Stack Pointer
Return Stack Pntr
DE
SP
HL
Free to use: BC, EA, VA, Alternate Registers
$NEXT
48 84
48 28
EA < (DE)++
JMP EA
doLIT
48 84
B4
$NEXT
EA < (DE)++
PUSH EA
doLIST
33
33
A6
48 93
A2
$NEXT
HL < HL -1
HL < HL -1
EA < DE
(HL) < EA
POP DE
COLD
BYE
54 0000 JMP Reset Vector
54 0000 JMP Reset Vector
EXECUTE
A1
21
POP BC
JMP BC
EXIT
48 85
B6
$NEXT
EA < (HL)++
DE < EA
next
6A 00
6B 01
48 83
74 B5
C9
48 93
48 82
B6
$NEXT
22 22
32 32
$NEXT
B < 00
C < 01
EA < (HL)
EA < EA - BC Skip if no borrow
JMP NEXT1
(HL) < EA
EA < (DE)
DE < EA
NEXT1
DE < DE + 2
HL < HL + 2
44
2
September 12, 2004
?branch
BRAN1
6A FF
6B FF
A4
74 CD
C6
22 22
$NEXT
48 82
B6
$NEXT
branch 48 82
B6
$NEXT
B < FF
C < FF
POP EA
EA AND BC Skip if no zero
JMP BRAN1
DE < DE + 2
EA < (DE)
DE < EA
EA < (DE)
DE < EA
! (w a --)
A6
B5
A2
A4
48 92
A5
B6
$NEXT
EA < DE
BC < EA
POP DE (address)
POP EA (data)
(DE) < EA
EA < BC
DE < EA
@ (a -- w)
A6
B5
A2
48 82
B4
A5
B6
$NEXT
EA < DE
BC < EA
POP DE
EA < (DE)
PUSH EA
EA < BC
DE < EA
C! (w b --)
A1
A4
09
39
$NEXT
POP BC (address)
POP AE (data)
A < EAL
(BC) < A
C@ (b -- c)
A1
29
6A 00
1B
B1
$NEXT
POP BC
A < (BC)
B < 00
C < A
PUSH BC
RP@ (--a)
B3
$NEXT
PUSH HL
RP! (a--)
A3
$NEXT
POP HL
R> (--w)
48 85
B4
$NEXT
EA < (HL)++
PUSH EA
R@ (--w)
48 83
EA < (HL)
45
3
September 12, 2004
B4
$NEXT
PUSH EA
>R (w--)
33 33
A4
48 93
$NEXT
HL < HL - 2
POP EA
(HL) < EA
SP@ (--a)
70 0E FEFF
70 1F FEFF
B1
$NEXT
(FFFE) < SP
BC < (FFFE)
PUSH BC
SP! (a--)
A1
70 1E FEFF
70 0F FEFF
$NEXT
POP BC
(FFFE) < BC
PC < (FFFE)
DROP
A4
$NEXT
POP EA
DUP
A4
B4
B4
$NEXT
POP EA
PUSH EA
PUSH EA
SWAP
A4
A1
B4
B1
$NEXT
POP EA
POP BC
PUSH EA
PUSH BC
OVER
A4
A1
B1
B4
B1
$NEXT
POP AE
POP BC
PUSH BC
PUSH AE
PUSH BC
46
4
September 12, 2004
0< (n--t)
A1
69 FF
48 06
69 00
1A
1B
B1
$NEXT
POP BC
A < FF
B Shift Left, Skip if carry
A < 00
B <A
C < A
PUSH BC
AND
A1
A4
74 8D
B4
$NEXT
POP BC
POP AE
EA < EA AND BC
PUSH EA
OR
A1
A4
74 9D
B4
$NEXT
POP BC
POP EA
EA < EA OR BC
PUSH EA
XOR
A1
A4
74 95
B4
$NEXT
POP BC
POP EA
EA < EA EX-OR BC
PUSH EA
INVERT
A1
69 FF
60 12
60 13
B1
$NEXT
POP BC
A < FF
B < B EX-OR A
C < C EX-OR A
PUSH BC
UM+
A1
A4
69 00
74 A5
69 01
1B
6A 00
B4
B1
$NEXT
POP BC
POP EA
A < 00
EA < EA + BC Skip if no carry
A < 01
C < A
B < 00
PUSH EA
PUSH BC
47
5
September 12, 2004
+
A1
A4
74A5
00
B4
$NEXT
POP BC
POP EA
EA < EA + BC Skip
NOP
PUSH EA
NEGATE
A1
69 FF
60 12
60 13
12
B1
$NEXT
POP BC
A < FF
B < B EX-OR A
C < C EX-OR A
BC < BC + 1
PUSH BC
-
A1
69 FF
60 12
60 13
12
A4
74 A5
00
B4
$NEXT
POP BC
A < FF
B < B EX-OR A
C < C EX-OR A
BC < BC +1
POP EA
EA < EA + BC Skip
NOP
PUSH EA
0=
A4
A9 FF
1A
1B
74 CD
C4
A9 FF
1A
1B
B1
$NEXT
POP EA
A < FF
B < A
C < A
EA AND BC Skip if not zero
JMP BRAN2
A < 00
B < A
C < A
PUSH BC
=
A4
A1
69 FF
74 FD
69 00
1A
1B
B1
$NEXT
POP EA
POP BC
A < FF
EA - BC Skip if zero
A < 00
B < A
C < A
PUSH BC
doUSER
48 83
70 1F up
74 A5
00
B4
$NEXT
EA < (HL)
BC < (up)
EA < EA +BC SKIP
NOP
PUSH EA
BRAN2
48
Modified
Roland PG1000
Programming
49
Machine Code
50
PUSHBUTTONS AND LED's
8(4)
MIDI
4(3)
LOAD
X
XX
40(7)
LEFT
80(8)
RIGHT
10(5)
DOWN
X
XX
20(6)
UP
2(2)
SLD UP
1(1)
SLD DWN
Each button is associated with a bit in the PA port. The number above the button is the hex
value of the PA input port for that button. Note that two of the switches have no numbers
associated with them.
There are 6 LED's located in the 6 non-xx buttons. These are turned on and off through the
PB output port. The same port numbers as for the buttons apply to port B outputs for the
LED's.
Bit zero of port B is used for serial transmission. Any serial transmission will
automatically turn off all 6 LEDs. Bit one of port B is used to select between the bank of 8
numbered switches shown above and the bank of two currently unused ones in the upper
right corner. PB1 must remain low to enable the 8 buttons above that are numbered.
CODE
SW@
( --- n, Read the 8 switch values in a byte. Switches are
normally high.)
4C C0
A < PA
6A 0
B < 0
1B
C < A
B1
PUSH BC
ENDCODE
CODE
LOOP:
OUT:
S@
4C
6B
74
74
C4
43
48
FC
6A
B1
(--- n, Return # of lowest switch on. n = 0,1,2,3,...,8)
C0
A < PA
0
C < 0
11 FF
A < A EXOR FF
49 FF
A AND FF, Skip if NO ZERO
JMP OUT
C < C+1
01
A Shift Right, Skip if Carry
JMP LOOP
0
B<0
PUSH BC
ENDCODE
:
TST
( --- ) CR BEGIN
SW@ FF XOR
200 DELAY D EMIT NUF? UNTIL ;
51
<# # # #>
TYPE
ORG 0200H
;
Interrupt routine for Analog to Digital Converters
;
;
;
DB 10H
;EXA, use alternate registers
DB 11H
;EXX
Load ADC Address and Counter into HL. Uses FFF3.
DB 68H,0FFH
;V'<FF
DB 69H,0C6H
;A<C6
DB 1EH
;H<A, H<C6, C6xx is ADC RAM buffer area
DB 01H,0F3H
;A<(V/F3)
DB 1FH
;L<A, L<(FFF3) the slider interrupt count
Store ADC values.
DB 4CH,0E0H
;A<CR0
DB 3DH
;(HL)+<A, store new value, increment count
DB 4CH,0E1H
;A<CR1
DB 3DH
;(HL)+<A, store new value, increment count
DB 4CH,0E2H
;A<CR2
DB 3DH
;(HL)+<A, store new value, increment count
DB 4CH,0E3H
;A<CR3
DB 3DH
;(HL)+<A, store new value, increment count
Update Counters
DB 0FH
;A<L
DB 63H,0F3H
;(V/F3)<A, update counter.
DB 48H,25H
;A shift logical left
DB 48H,05H
;A shift left, skip if carry, if count = 40H
DB 0C7H
;JMP AHEAD if all 64 values are not converted yet.
DB 64H,1EH,01
DB 10H,11H,0AAH,62H
AHEAD:
;
DB 1AH
DB 74H,0AH,0E0H
DB 4CH,0C2H
DB 07H,1FH
DB 60H,9AH
DB 4DH,0C2H
DB 64H,90H,08H
Return from Interrupt.
DB 10H
DB 11H
DB 0AAH
DB 62H
;MKH<MKH OR 1, disable INTAD
;EXA,EXX,EI,RETI return from interrupt
;B<A
;B<B AND E0
;A<Pc
;A<A AND 1F
;A<A OR B
;Pc<A, Load 4051s' address select bits (3 bits).
;Invert ANM bit and start next ADC convert cycle.
;EXA
;EXX
;EI
;RETI
SERIAL INTERFACES
A 9600 Baud, software driven serial I/O is provided. PortB/bit0 is used for serial output and
PortC/bit3 (INT2) is used for the serial input. The serial input is interrupt driven with a vectored
interrupt routine located at 0A0H. The code words ?RX, TX!, and !IO make up the rest of the
serial I/O code. Three USER variables have been set up for use by these serial I/O routines:
SERIN, which holds the received character and a flag; HAFBIT, which adjusts the software
timing of the receiver to read in the middle of each bit frame (set it for 1/2 the BITIME minus
52
5); and BITIME, which adjusts the software for a specific baud rate (17H for 9600 baud
assuming a 12Mhz processor clock).
;
;
SERIN
( -- a )
Point to host serial input. Flag in high, char in low byte.
$USER
5,'SERIN',SERIN
;
;
HAFBIT
( -- a )
Point to half bit time used by serial i/0 routines. (Equals 06H).
$USER
6,'HAFBIT',HAFBIT
;
;
BITIME
( -- a )
Point to bit time used to set serial i/o baud rate. (Equals 16H).
$USER
6,'BITIME',BITIME
ORG
00A0H
; Vectored INT2 routine for Serial Input from Host Computer.
; Uses address FFF0 as a counter location - do not use elsewhere!
LOOP1:
LOOP2:
DB
DB
DB
DB
DB
DB
DB
DB
DB
DB
DB
DB
DB
DB
DB
DB
DB
DB
DB
DB
DB
DB
DB
DB
DB
DB
DB
DB
DB
DB
0B1H
0B2H
0B0H
68H,0FFH
71H,0F0H,07H
70H,1FH,04CH,0FFH
53H
0FEH
52H
0FCH
70H,1FH,4EH,0FFH
53H
0FEH
52H
0FCH
04CH,0C2H
48H,31H,48H,31H
48H,31H,48H,31H
0CH
48H,31H
1CH
30H,0F0H
0E7H
70H,1FH,4EH,0FFH
53H,0FEH,52H,0FCH
71H,04BH,0FFH
0CH,63H,04AH
0A0H,0A2H,0A1H
48H,44H,0
0AAH,062H
;PUSH BC
;PUSH DE
;PUSH VA
;MVI, V<FF
;MVIW, (V/F0)<07, number of bits to receive.
;LBCD, BC<(FF4C), wait for a half bit.
;DCR, C<C-1 skip if borrow
;JR, Jump to loop1
;DCR, B<B-1 skip if borrow
;JR, Jump to loop1
;LBCD, BC<(FF4E),wait 1 bit time
;DCR, C<C-1 skip if borrow
;JR, Jump to loop2
;DCR, B<B-1 skip if borrow
;JR, Jump to loop2
;MOV, A<PC, read serial input on pc3
;Rotate PC3 bit into Cy
;RLR, A rotate right 4xs
;MOV, A<D, D collects the bits
;RLR, shift in next bit, CY to top of D
;MOV, D<A
;DCRW, (V/F0)<(V/F0)-1 skip if borrow
;JR, Jump to loop2 for next bit.
;LBCD, BC<(FF4E)
;DCR JR DCR JR, stop bit loop time.
;MVIW, (V/4B)<FF, load flag
;MOV STAW, A<D (V/4A)<A, load data
;POP, restore AV DE and BC
;SKIT,NOP
;EI RETI, enable interrupts and return
;
;
'?KEY
( -- a )
Execution vector of ?KEY.
$USER
5,"'?KEY",TQKEY
;
;
'EMIT
( -- a )
Execution vector of EMIT. Points to TX! Code Word.
$USER
5,"'EMIT",TEMIT
53
;
;
?RX
AHEAD:
;
;
$CODE
3,'?RX',QRX
DB 68H,0FFH
;MVI, V<FF
DB 01H,4BH
;LDAW, A<(V/4B) read serial-in flag
DB 47H,0FFH
;ONI, A AND FF skip if flag not zero
DB 0CAH
;JR, jump ahead
DB 71H,04BH,0
;MVIW, (V/4B)<0, reset flag to zero
DB 70H,1FH,4AH,0FFH
;LBCD, BC<(FF4A), read serin data
DB 0B1H
;PUSH BC, push serial input data to stack
DB 69H,0FFH
;A<FF
DB 1BH
;C<A,
DB 6AH,0
;B<0
DB 0B1H
;PUSH BC, push serial input flag to stack
$NEXT
TX!
LOOP1:
LOOP2:
;
;
( -- c T | F )
Return input character and true, or a false if no input.
Points to ?RX Code word.
!IO
( c -- )
Send character c to the output device.
$CODE
3,'TX!',TXSTO
DB 0BAH
;Disable Interrupts
DB 0A1H
;POP BC, pop char into C
DB 0B2H
;PUSH DE, store interpreter pointer
DB 0BH,1CH
;A<C, D<A, char in A and D
DB 68H,0FFH
;V<FF
DB 71H,0F0H,07H
;(V/F0)<7
DB 60H,91H
;A<A EXOR A
DB 6DH,01H
;E<01
DB 4DH,0C1H
;PB<A
DB 70H,1FH,04EH,0FFH
;BC<(FF4E) set baud
DB 53H,0FEH,52H,0FCH
;C<C-1, JR, B<B-1, JR, jr to loop1
DB 0CH
;A<D
DB 07H,01H
;A<A AND 01
DB 4DH,0C1H
;PB<A, send a bit
DB 0CH
;A<D
DB 48H,31H
;A rotate logical right
DB 1CH
;D<A
DB 0,0,0,0
;NOPs to make rec loop = transmit loop.
DB 30H,0F0H
;(V/F0)<(V/F0)-1 skip if borrow
DB 0E8H
;JR, jump to loop1
DB 0DH
;A<E
DB 51H
;A<A-1 skip if borrow
DB 0C6H
;JR, jump to loop2
DB 0A2H
;POP DE, restore interpreter pointer
DB 0AAH
;Enable Interrupts
$NEXT
;End of routine
DB
DB
DB
DB
6CH,03H
1DH
71H,0F0H,01
4FH,0D7H
;D<03
;E<A
;(V/F0)<01
;JRE, jump to loop1
( -- )
Initialize the serial I/O devices.
54
$CODE
3,'!IO',STOIO
DB 69H,0EFH,4DH,0C7H
;MKL<EF, enable int2 interrupt and
DB 69H,0FFH,4DH,0C6H
;MKH<FF, disable all others with mask
DB 0AAH
;EI, enable interrupt
$NEXT
MIDI INTERFACE
PC0 is the MIDI serial output. PC1 is the MIDI serial input. Both use the 78C10 microprocessor's
internal serial I/O device. The following is set in the Cold Start Routine:
69
69
64
69
0B
0A
81
4E
4D D1
4D D4
06
4D CA
MCC < 0B
MC < 0A
SMH < 6
SML < 4E
PC0,PC1,PC3 set for I/O (4-8)
PC1 and PC3 set as inputs (4-9)
Receive disabled, Transmit enb (7-7)
Clk x16,8 bits,no parity,1 stop (7-9)
To transmit midi data xx, code it as follows: 69 xx 4D D8 (A < xx, TXB < A). When
transmission is done, an INTST interrupt is generated. This software does not use an interrupt. Instead,
it checks the INTFST flag using SKIT FST to wait until the flag goes high before transmitting the data.
Because of this wait period, when coding, it will save processor time to put operations between
TM commands - i.e. the following code
90 TM 40 TM 40 TM
OP1 OP2 OP3
is optimized by placing it in following order:
OP1 90 TM
;
;
:
TM
OP2 40 TM
( n -- )
Wait for last transmit,
$CODE 2,'TM',TM
DB 0A1H
DB 0BH
DB 48H,4AH
DB 0FDH
DB 4DH,0D8H
$NEXT
then send midi byte n.
;POP BC
;A<C
;SKIT FST, skip if interrupt
;JMP TO SKIT
;MOV TXB,A
ENBREC ( ---, Enable Midi Receive)
$CODE
DB 64H,81H,0EH
$NEXT
:
OP3 40 TM
RM
;SMH<E
( --- Midi Receive: If received leave - char, FF;
If nothing there leave - 00 .)
$CODE
6A,0
;B<0
6B,0
;C<0
48,49
;SKIT FSR, Skip if Interrupt flag
C6
;JMP AHEAD
4C,D9
;A<RXB
55
1B
B1
6B FF
B1
$NEXT
AHEAD:
:
TST
;C<A
;PUSH BC, push received data
;C<FF
;PUSH BC, push flag
ENBREC BEGIN
RM IF . THEN NUF? UNTIL ;
MEMORY BUFFERS AND REGISTERS:
C600 - C800
SLIDER RAM for the ADC/EDIT/MIDI routines.
C600-C63F
C640-C67F
ADC data, 8-bits.
SLAST. Last ADC value read.
C680-C6B7
C6C0-C6FF
Midi Byte 2 (Key#, Controller#, Program#, etc.)
Midi Byte 1 (Status and Channel number). Disabled if bit7=0.
C700-C73F
FLAG to keep track of current state of Midi operation.
Used only in some operations.
Each of the 64 Sliders has a 5-byte buffer. For example, Slider #1 uses C600, C640, C680,
C6C0 and C700. This buffer is serviced by the ADC interrupt routine and the main
program's EDIT routines. The MIDI routineS read from it to transmit Midi data.
Serial Input Registers
FFF0
Timing counter.
FF4A
USER value SERIN
FF4C
USER value HAFBIT
FF4E
USER value BITIME
ADC Interrupt routine registers:
FFF3
ADC interrupt slider counter
EDIT Routine registers:
FF00
eSLD#
FF01
eFLD
FF02
eBYTE1
FF03
eBYTE2
FF04
eBYTE3
FF05
eSET
FF06
eSET#
:
:
:
:
:
:
:
eSLD#
eFLD
eBYTE1
eBYTE2
eBYTE3
eSET
eSET#
FF00
FF01
FF02
FF03
FF04
FF05
FF06
MIDI Routine registers:
FFE0
LCNT
FFE1
LST
;
;
;
;
;
;
;
Slider number being edited.
LCD field being edited.
Midi Byte with Status/Channel data. ENB flag.
Midi Byte with Key#, Controller#, or Program#.
8-bit Slider value.
MODE: 0 = Slider Edit, FF = Setup mode.
Holds Setup number. Used to address Rom setups.
Edit
Edit
Edit
Edit
Edit
Buffer
Buffer
Buffer
Buffer
Buffer
Slider Number.
LCD field.
Midi status byte.
Midi data byte.
Slider value.
Midi Loop count.
Last Midi Status sent.
Microprocessor Ram:
56
RPP
TIBB
SPP
UPP
CTOP
NTOP
PADD
NAMEE
CODEE
COLD
FF08 - FF80
EQU
EQU
EQU
EQU
EQU
EQU
EQU
EQU
EQU
EQU
USER Variables
0C2F0H
0C200H
0C1F0H
0FF00H
0C390H
0C7FFH
0C300H
01FF0H
00300H
00100H
;start of return stack (RP0)
;terminal input buffer (TIB)
;start of data stack (SP0)
;start of user area (UP0)
;RAM code dict. expansion
;RAM name dict. expansion
;PAD area
;start of Name dictionary
;start of Code dictionary
;Cold Start code
Tables:
The sliders are not converted in the same order in which they are physically laid out in the box.
A table of 64 has been created in ROM at address 00200H to translate the slider numbers to
physical position numbers:
48
51
54
24
44
06
04
07
56
59
62
21
27
34
28
15
40
43
46
13
17
50
18
23
37
33
30
05
09
60
10
31
53
49
32
29
01
52
02
39
61
57
16
19
25
36
26
47
45
41
08
11
22
20
42
55
35
38
00
03
14
12
58
63
(numbers in decimal)
The following chart shows the physical layout of the sliders on the Roland PG1000 box:
07 15 23 31 39 47 55 63
56 57 58 59 60 61 62 63
(External)
(External)
60 52 36 20 12 04|28 18 10 02 26 42 58
43 44 45 46 47 48|49 50 51 52 53 54 55
32 16 08 00 24 21 13 05 29 19 11|03 44 27 17 09 01|25 22 14 06 34 50
20 21 22 23 24 25 26 27 28 29 30|31 32 33 34 35 36|37 38 39 40 41 42
48 56 40 37 53 61 45 35|51 59 43 33 49 57|41 38 54 62 46 30
00 01 02 03 04 05 06 07|08 09 10 11 12 13|14 15 16 17 18 19
57
Utility Words
58
UTILITY WORDS
:
CASE
( n --- , Use 'n' as a pointer to following list of words, execute
the pointed word, then leave the current word )
R>
( Remove return stack pointer to next token, put on data stack )
SWAP
( pointer 'n' to the top )
2* +
( pointer + 2n )
@EXECUTE
( execute token at pointer + 2n, leave current word )
;
The CASE word is used as follows:
: XXX
( n --- )
ANYWORDS
CASE
PG0
PG1
PG2
;
If n=0, PG0 is executed after CASE. If n=1, PG1 is executed after CASE. If n=2, PG2 is executed after
CASE. Only the one PG is executed after which XXX terminates.
Warning!! If n is greater than the number of words between CASE and ';' minus one, the program will
bomb.
********************************************
:
INCR
OVER
:
DECR
OVER
( n, nmax
1+
<
--- n+1,
Increment n but set to zero if greater than nmax )
IF
DROP 0
ELSE
1+
THEN ;
( n, nmax --- n-1,
10<
IF
Decrement n but set to nmax if less than zero )
SWAP DROP
ELSE
DROP 1THEN ;
**********************************************
CODE
DELAY
A1
53
FE
52
FC
ENDCODE
(
POP
C <
JMP
B <
JMP
n --- )
BC
C-1, Skip if borrow
back 1
B-1, Skip if borrow
back 3
*********************************************
59
CODE
TM
A1
0B
48,4A
FD
4D,D8
ENDCODE
( n -- , Transmit Midi, Wait for last transmit, then send n )
POP BC
A<C
SKIT FST, Skip if interrupt
JMP TO SKIT
MOV TXB,A
**********************************************
:
SEE
( -- word --, Decompiles word )
' CR 1+ BEGIN
( Code address of word plus one )
DUP DUP SPACE . 7C EMIT @ DUP
IF >NAME THEN ?DUP
IF .ID
ELSE DUP @ U.
THEN 2+
NUF? UNTIL DROP
;
:
DUMMY ; ( -- , Do nothing word for filling in CASE definitions )
REMOTE FILE LOADING:
Build a TEXT-ONLY file in Word (or other) of the words you want to load. When using White
Knight, go under Custom / Otions / Text Transfer and set the "Wait after each line sent for the ^K
character (the Pacing character used in Eforth). Type in the Eforth word FILE. Character echoes are
now turned off. Go under File to Send a Text File. Make sure there is the HAND command at the end
of your text file to return control back to the console. Type WORDS to see if your text was loaded.
60
LCD Screen
61
The HD44780 LCD Controller
Display is 2 Lines of 16 Characters. Position addresses are 0 to F for the top line, and 40 to 4F
for the bottom line. Cursor automatically increments to the next position after a character write,
except for the jump between the end of the top line and beginning of the bottom line.
Characters can be taken from internal ROM which holds all the ASCII characters plus other
special characters (see the chart) or from an internal RAM which must be loaded at power on by
the user. This project uses only the ROM.
There are two Write modes controlled by the RS input line:
RS = 0, LCD setup commands such as Cursor on/off/ position, Clear, etc.
RS = 1, write character to cursor position.
Core LCD Words:
CODE
LLI
64 0A EF
ENDCODE
( --, Sets RS=0 for LCD setup commands )
Pc < Pc AND EF
CODE LLC
64 1A 10
ENDCODE
( --- , Sets RS=1 for character displaying )
Pc < Pc OR 10
CODE LCD
A1
0B
14 00 A0
39
ENDCODE
(n--- , Loads
POP BC
A < C
BC < A000
(BC) < A
:
LI
LLI
LCD command 'n')
(n --, Load LCD setup command 'n'.
Exit with RS=1 for char writes.)
LCD LLC 1FF DELAY ;
Example LCD Display Commands:
1 LI
F LI
C0 LI
41 LCD
Clear LCD Screen.
Turn on the Cursor
C LI
80 LI
Turn off the Cursor
Position cursor at start
Position cursor at start of 2nd line.
Display ASCII 'A' at current cursor position,
increment cursor.
62
Power Up Reset Routine
:
LCDINIT
( Initialize LCD display )
D7A
DELAY
38 LI ( Function Set-8 bit input, 2 lines, 5x7 char )
47E
DELAY
38 LI
017
DELAY
38 LI
017
DELAY
38 LI
017
DELAY
08 LI ( Display off, cursor off, blink off )
017
DELAY
01 LI ( Clear display, home the cursor )
1CC
DELAY
02 LI ( Cursor at home - top left position )
1CC
DELAY
017
DELAY
06 LI ( Entry Mode Set - cursor auto
increment,shift off )
0F LI ( Display on, cursor on, blink on )
017
DELAY
;
Display Routines
:
#DISP
( n,p --- , Display 'n' as a 3-digit number in current base at LCD
position 'p' and reset cursor to start of number )
DUP LI SWAP
<# # # # #>
DROP DUP C@ LCD
C@ LCD 1+ C@
1+ DUP
LCD LI
( Move cursor to 'p', and save )
( Convert 'n' to 3 ascii digits.
Leave address and 3 on stack )
( Locations of the 3 digits in TIB)
( Display 3 digits and reset cursor )
;
:
#2DISP
DUP LI SWAP <# # # #> DROP DUP C@ LCD 1+ C@ LCD LI ;
:
DISP
(a,p ---,
Display string from address 'a' in LCD position 'p' )
LI DUP C@ 1- >R (Set cursor. First byte at string address is a count.)
FOR 1+ DUP C@ LCD NEXT DROP
(Display 'count' string characters )
;
MASM Macro to Compile a Stored String
SD$
MACRO
STRNG
DW DOLIT
_LEN
= $ + 4
DW
_LEN,EXIT
;;save address of count byte
;;save cnt address on stack
63
DB
_CODE
_LEN
DB
_CODE
ENDM
ORG
ORG
0,STRNG
= $
;;count byte and string
;;save code pointer
;;point to count byte
;;set count
;;restore code pointer
_CODE-_LEN-1
;
EXAMPLE Stored String
( --- a )
;
Packed string. 'a' is addr of count byte.
$COLON 2,'Example',Example
SD$ 'Slider'
String Data for DISP
Can be built with the SD$ Macro in MASM, or from FORTH in the following manner:
:
STRING1
$" Slider "
;
The word above is loaded into code space as follows:
DoList$"| Count
80
84 A
7
S
53
l
6C
i
69
d
64
e
65
r
72
Space
20
EXIT
94 3
This needs some explanation: The word $" is an immediate word which acts in
compilation mode to set up the word's code area as shown. When STRING1 is executed
the word $"| found in the code area is first to execute. This word puts the address of
'Count' on the data stack and rearranges the return stack so that the next word to execute
is EXIT.
The word $" cannot be used when forming the ROM code with MASM. The string
creating macro 'SD$' is used instead. It leaves the code area looking like this:
doLit
80
addr-of-count
xxxx
EXIT Count
94 3 7
64
S
53
l
6C
i
69
d
64
e
65
r
72
Space
20
LCD DISPLAY FIELDS
( **** Labels, ---- Numbers )
0 1 2 3 4 5 6 7 8 9 A B C D E F
_______________________________
* * * * * * - - * * * - - FLD0
FLD1
FLD2 FLD3
_______________________________
* * * * * * * *
- - - - FLD4
FLD5
FLD6
_______________________________
:
:
:
:
FLD0
FLD1
FLD2
FLD3
80
86
88
8D
;
;
;
;
: FLD4 C0 ;
: FLD5 C9 ;
: FLD6 CD ;
: FLDCASE
(Slider, Setup#, * MIDI Running *)
(Slider number 0 to 55 )
(Ch(Midi Channel), Off(Slider disabled))
(Midi Channel number 0 to 15)
(Midi Status - KEY#, KEY# AT, CONTROL#, PROGRAM#, CH PRESS,
PTCH WHL, ********)
(Midi byte value 0 to 127)
(Slider value 0 to 127)
(n---f, Choose an LCD field position )
7 AND CASE
FLD0 FLD1 FLD2 FLD3 FLD4 FLD5 FLD6 FLD0
;
LCD Displayed Strings
;
;
L0
( --- a )
Packed string. 'a' is addr of count byte.
$COLON 2,'L0',L0
SD$ 'Slider'
;
;
L1
( --- a )
Packed string. 'a' is addr of count byte.
$COLON 2,'L1',L1
SD$ 'Setup#'
;
;
L2
( --- a )
Packed string. 'a' is addr of count byte.
$COLON 2,'L2',L2
SD$ '* MIDI Running *'
;
;
L20
( --- a )
Packed string. 'a' is addr of count byte.
$COLON 3,'L20',L20
SD$ ' chl'
;
;
L21
( --- a )
Packed string. 'a' is addr of count byte.
65
$COLON 3,'L21',L21
SD$ ' off'
;
;
L40
( --- a )
Packed string. 'a' is addr of count byte.
$COLON 3,'L40',L40
SD$ 'Key#
'
;
;
L41
( --- a )
Packed string. 'a' is addr of count byte.
$COLON 3,'L41',L41
SD$ 'Key# A-T'
;
;
L42
( --- a )
Packed string. 'a' is addr of count byte.
$COLON 3,'L42',L42
SD$ 'Control#'
;
;
L43
( --- a )
Packed string. 'a' is addr of count byte.
$COLON 3,'L43',L43
SD$ 'Program#'
;
;
L44
( --- a )
Packed string. 'a' is addr of count byte.
$COLON 3,'L44',L44
SD$ 'Ch Press'
;
;
L45
( --- a )
Packed string. 'a' is addr of count byte.
$COLON 3,'L45',L45
SD$ 'Ptch Whl'
;
;
L4X
( --- a )
Packed string. 'a' is addr of count byte.
$COLON 3,'L4X',L4X
SD$ '********'
;
;
L50
( --- a )
Packed string. 'a' is addr of count byte.
$COLON 3,'L50',L50
SD$ '***'
:
LSTAT
CASE
(n---, Choose a Midi Status Label)
L4X L40 L41 L42 L43 L44 L45 L4X
;
LCD Hardware Interface
14 pin ribbon cable:
1.
GND
2.
+5 v
3.
Resistor to Gnd, Sets LCD back light contrast
66
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
RS = Pc4, 78C10/21
R/W = Gnd, Writes only, no reads used.
E, Write pulse derived from address decoder - Axxx / Bxxx, ***
Data 0 = Pd0, 78C10/55
Data 1 = Pd1, 78C10/56
Data 2 = Pd2, 78C10/57
Data 3 = Pd3, 78C10/58
Data 4 = Pd4, 78C10/59
Data 5 = Pd5, 78C10/60
Data 6 = Pd6, 78C10/61
Data 7 = Pd7, 78C10/62
67
EDIT Words
68
EDIT BUFFER UTILITY ROUTINES
;
;
;
;
eUPDAT
eLOAD
( --- )
Move data from Slider Ram to Edit Buffer.
$CODE
6,'eUPDAT',EUPDAT
DB
68H,0FFH
;;V<FF
DB
6AH,2
;;B<2
DB
1,0
;;A<(V/00) Read eSLD#
DB
1BH
;;C<A
DB
29H
;;A<(BC) Read Translation Table
DB
6AH,0C6H
;;B<C6
DB
DB
DB
DB
1BH
29H
48H,21H
63H,4
;;C<A
;;A<(BC)
;;A SHIFT RIGHT
;;(V/04)<A, eBYTE3 (7bits) to FF04
DB
DB
DB
DB
69H,80H
60H,43H
29H
63H,3H
;;A<80
;;C<C+A
;;A<(BC)
;;(V/03)<A, eBYTE2 to FF03
DB
DB
DB
DB
$NEXT
69H,40H
60H,43H
29H
63H,2H
;;A<40
;;C<C+A
;;A<(BC)
;;(V/02)<A, eBYTE1 to FF02
( --- )
Load Edit Buffer data into Slider Memory.
$CODE
5,'eLOAD',ELOAD
DB
68H,0FFH
;;V<FF
DB
6AH,2
;;B<2
DB
1,0
;;A<(V/00) Read eSLD#
DB
1BH
;;C<A
DB
29H
;;A<(BC) Read Translation Table
DB
6AH,0C6H
;;B<C6
DB
1BH
;;C<A
DB
DB
DB
69H,40H
60H,43H
49H,0
;;A<40
;;C<C+A
;;(BC)<0, Zero to SLAST
DB
DB
DB
DB
69H,40H
60H,43H
1,3
39H
;;A<40
;;C<C+A
;;A<(V/03)
;;(BC)<A, (FF03) to Midi byte 2
DB
DB
DB
DB
$NEXT
69H,40H
60H,43H
1,2
39H
;;A<40
;;C<C+A
;;A<(V/02)
;;(BC)<A, (FF02) to Midi byte 1
69
;
;
esUPDAT
( --- )
Update only the Slider data of the Edit Buffer.
$CODE
7,'esUPDAT',ESUPDAT
DB
68H,0FFH
;;V<FF
DB
6AH,2
;;B<2
DB
1,0
;;A<(V/00) Read eSLD#
DB
1BH
;;C<A
DB
29H
;;A<(BC) Read Translation Table
DB
6AH,0C6H
;;B<C6
DB
1BH
;;C<A
DB
DB
DB
$NEXT
29H
48H,21H
63H,4
;;A<(BC)
;;A SHIFT RIGHT
;;(V/04)<A, 7-bit Slider value to FF04
LCD DISPLAY ROUTINES
:
FLDAT
( --- , Return LCD cursor to current edit field )
eFLD C@ FLDCASE LI
;
:
SDISP
( ---, Display the Setup operation on the LCD)
1 LI BDEL
L1 FLD0 DISP
eSET# C@ FLD1 #2DISP
FLDAT
;
:
SLDISP ( --- , Update and display Slider data )
esUPDATE
eFLD C@ FLDCASE
eBYTE3 C@ 7F AND
<# # # # #> DROP LLI FLD6 LCD LLC
DUP C@ LCD 1+ DUP C@ LCD 1+ C@ LCD LI
(Get latest slide value)
(Get current field position)
(Display Slide value)
;
:
eDISP
( --- ,
Display Edit Buffer data on the LCD )
L0 FLD0 DISP
eSLD#
C@ FLD1 #2DISP
eBYTE3 C@ 80 AND
IF
L20 FLD2 DISP
ELSE L21 FLD2 DISP
THEN
eBYTE1 C@ DUP F AND FLD3 #DISP
2/ 2/ 2/ 2/
7 AND LSTAT FLD4 DISP
CF eBYTE1 C@ F0 AND <
IF
L50 FLD5 DISP
ELSE eBYTE2 C@ FLD5 #DISP
70
(
(
(
(
SLIDER )
Slider # )
OFF )
CHL )
( Midi Channel # )
( Midi Status )
( *** in Fld 5 )
( Number in Fld 5 )
THEN
SLDISP FLDAT
( Slider Data # )
;
:
MNDISP
eSET C@
( ---, MAIN DISPLAY UPDATE used in EDIT word )
IF SDISP
ELSE eDISP
THEN
;
LCD CURSOR CONTROL
:
BDEL
( --- , Long delay for poky LCD )
8000 DELAY
;
:
BL/R
( fld---pos, Translates LCD field number to LCD position)
DUP eFLD C! FLDCASE
;
:
SL/R
:
BLEFT
( --- , If in setup mode, toggle between fields 0 and 1 )
eFLD C@ 01 AND 01 XOR DUP eFLD C!
BL/R LI BDEL ;
( --- , Move cursor left & update eFLD)
40 LED!
eSET C@ IF SL/R ELSE
eFLD C@ 5 DECR BL/R LI BDEL THEN
;
:
BRIGHT ( --- , Move cursor right & update eFLD)
80 LED!
eSET C@ IF SL/R ELSE
eFLD C@ 5 INCR BL/R LI BDEL THEN
;
LCD FIELD INCREMENT/DECREMENT
;
UDCASE ( n---, Choose field dependent up/down routine)
eFLD C@ 7 AND
CASE U/D0 U/D1 U/D2 U/D3 U/D4 U/D5 U/D6 U/D7
;
:
BUP
( --- , Increment value at cursor field )
10 LED!
1 UDCASE BDEL
;
71
:
BDOWN
( --- , Decrement value at cursor field )
20 LED!
0 UDCASE BDEL
;
:
U/D0
(flg---, inc/dec field 0, SLIDER#/SETUP)
DROP eSET C@
IF
0 eSET C! eDISP
ELSE FF eSET C! SDISP THEN
;
:
U/D1
(flg---, Inc/Dec fLd 1 which shows the Slider OR SETUP #)
eSET C@ IF eSET# ELSE eSLD# THEN
C@ 3F ROT
(slider#, max value, up/dwn flag)
IF INCR ELSE DECR THEN
( slider# + 1 or -1)
CFLD1
;
:
CFLD1
(slider# --- , Change Slider/SETUP# in Fld1. Update Edit Buffer & LCD)
eSET C@ IF
eSET# C! SDISP
ELSE eSLD# C! eUPDAT eDISP
THEN
FLDAT
;
:
U/D2
IF
ELSE
THEN
(flg ---, Change Chnl or Off label in Field 2)
eBYTE1 C@ 80 OR
eBYTE1 C! L20 FLD2 DISP
eBYTE1 C@ 7F AND
eBYTE1 C! L21 FLD2 DISP
FLDAT
( display 'ch ' )
( display 'off' )
;
:
U/D3
(flg ---, Change midi channel in Field 3 )
eBYTE1 C@ F AND F ROT
( chnl#, F, u/d flg )
IF INCR ELSE DECR THEN
( chnl# +1 or -1 )
CFLD3
;
:
CFLD3
(channel # ---, Change midi channel in Field 3 )
DUP eBYTE1 C@ F0 AND OR
(Construct eByte1 with new Chnl # )
eBYTE1 C!
FLD3 #DISP
(Load into Edit buffer, Display it )
;
:
U/D4
(flg ---,
Change Midi operation in the status byte1 )
eBYTE1 C@
70 AND 2/ 2/ 2/ 2/ 7 ROT
( stat, 7, u/d flg )
IF INCR ELSE DECR THEN
( stat +1 or -1 )
DUP 0 = OVER 7 = OR
IF DROP 1 THEN
( avoid status bytes 0x and Fx )
CFLD4
;
:
CFLD4
( status# ---, Change Midi operation label in field 4 )
DUP
2* 2* 2* 2*
80 OR
eBYTE1 C@
F AND OR
(Construct eByte1 with new Stat#)
eBYTE1 C!
LSTAT FLD4
DISP
(Load into Edit buffer, Display it )
FLDAT
;
:
U/D5
(flg---, Change Midi data byte2 )
eBYTE2 C@ 7F ROT
( data, 7F, u/d flg )
IF INCR ELSE DECR THEN
( data +1 or -1 )
CFLD5
;
72
:
CFLD5
(midi data ---, Change Midi Data Byte2 in field 5 )
CF eBYTE1 C@
F0 AND <
(If chnl press or ptch whl, no data here)
IF
L50 FLD5 DISP
FLD5 LI DROP
( display '***' in field 5 )
ELSE DUP eBYTE2 C! FLD5 #DISP
(Load into Edit buffer, Display it )
THEN
;
:
U/D6
(flg---, Do nothing with Slider value field)
DROP
;
:
U/D7
(flg---, bogus field. Does not exist)
DROP
;
:
TST
BEGIN KEY DUP
( 1 = UP, 0 = DWN,
31 = IF 1 U/D3 DROP 0 ELSE
30 = IF 0 U/D3 0
ELSE
1 THEN THEN UNTIL ;
any other key = quit )
EDIT BUTTON ROUTINES
8(4)
MIDI
4(3)
LOAD
X
XX
40(7)
LEFT
80(8)
RIGHT
10(5)
UP
X
XX
20(6)
DOWN
2(2)
SLD UP
1(1)
SLIDE DWN
:
MNCASE ( --- , Main Case statement for button routines)
S@
CASE
DUMMY BSDWN BSUP BLOAD BMIDI BUP BDOWN BLEFT BRIGHT
;
:
BSDWN
( ---, Button 1 decrements the slider number)
0 UD1 BDEL
;
:
BSUP
( ---, Button 2 increments slider number)
1 UD1 BDEL
;
73
:
SETUP
( ---, Setup Slider Ram Buffer from ROM locations 2000H)
eSET# C@ 2000 +
C680
80 CMOVE
;
:
BLOAD
( ---, Button 3 loads data shown on LCD into Slider Memory)
4 LED!
eSET C@
IF
SETUP 0 eSET C!eUPDAT eDISP BDEL
ELSE eLOAD eDISP BDEL
THEN
;
:
BMIDI
( ---, Button 4 starts the Midi program)
1 LI BDEL
L2 FLD0 DISP
MIDI
;
:
EDIT
(MAIN EDIT PROGRAM)
CR DECIMAL 1 LI BDEL
eUPDATE eDISP
BEGIN
NUF?
ADCINIT SLDISP
0 LED! MNCASE
UNTIL HEX
;
74
MIDI Words
75
PG1000 MIDI
The main MIDI loop rotates through the 64 ADC Slider values until an enabled one is
found. The loop count is stored in register FFE0. Then the Midi status is checked for the
following operations:
1
2
3
4
5
6
KEYN
KEYAT
CNTRL
PRG
CHAT
PWHL
Key On or Key Off
Key On or Key Off with After Touch
Control Change
Program Change
Channel After Touch
Pitch Wheel
MIDI UTILITY ROUTINES
;
;
MLOOP
LOOPBACK:
( --- stat)
Loop thru ADC values until an enabled one is found.
$CODE
5,'MLOOP',MLOOP
DB 68H,0FFH
;V<FF
DB 6AH,0C6H
;B<C6
DB 1,0E0H
;A<(V/E0)
DB 41H
;A<A+1 skip if carry (never carries)
DB 07H,3FH
;A<A AND 3F
DB 63H,0E0H
;(V/E0)<A, incremented count to FFE0
DB
DB
DB
DB
DB
46H,0C0H
1BH
29H
47H,80H
0F2H
;A<A+C0
;C<A
;A<(BC), get midi byte1
;A AND 80, skip if no zero
;JMP LOOPBACK, if disabled
DB 7H,7FH
DB 48H,21H
DB 48H,21H
DB 48H,21H
DB 48H,21H
DB 1BH
DB 6AH,0
DB 0B1H
$NEXT
;
;
ADCV
;A<A AND 7F
;A shift right
;A shift right
;A shift right
;A shift right
;C<A, Midi status number
;B<0
;PUSH BC, push status# on stack
( --- adc value)
Push stack with current
$CODE
4,'ADCV',ADCV
DB 1,0E0H
DB 1BH
DB 6AH,0C6H
DB 29H
DB 1BH
DB 6AH,0
DB 0B1H
$NEXT
76
adc value for MIDI operation.
;A<(V/E0), Midi loop count.
;C<A
;B<C6
;A<(BC)
;C<A
;B<0
;PUSH BC
;
;
SLAST
( --- slast value)
Push stack with last adc value for MIDI operation.
$CODE
4,'DIFF',DIFF
DB 1,0E0H
;A<(V/E0), Midi loop count.
DB 46H,40H
;A<A+40
DB 1BH
;C<A
DB 6AH,0C6H
;B<C6
DB 29H
;A<(BC)
DB 1BH
;C<A
DB 6AH,0
;B<0
DB 0B1H
;PUSH BC
$NEXT
;
;
BYT2
( --- byt2 value)
Push stack with current
$CODE
4,'BYT2',BYT2
DB 1,0E0H
DB 46H,80H
DB 1BH
DB 6AH,0C6H
DB 29H
DB 1BH
DB 6AH,0
DB 0B1H
$NEXT
;
;
;
;
BYT1
FLAG
( --- byt1 value)
Push stack with current
$CODE
4,'BYT1',BYT1
DB 1,0E0H
DB 46H,0C0H
DB 1BH
DB 6AH,0C6H
DB 29H
DB 1BH
DB 6AH,0
DB 0B1H
$NEXT
( --- flag value)
Push stack with current
$CODE
4,'FLAG',FLAG
DB 1,0E0H
DB 1BH
DB 6AH,0C7H
DB 29H
DB 1BH
DB 6AH,0
DB 0B1H
$NEXT
77
BYTE2 value for MIDI operation.
;A<(V/E0), Midi loop count.
;A<A+80
;C<A
;B<C6
;A<(BC)
;C<A
;B<0
;PUSH BC
BYTE1 value for MIDI operation.
;A<(V/E0), Midi loop count.
;A<A+C0
;C<A
;B<C6
;A<(BC)
;C<A
;B<0
;PUSH BC
FLAG value for MIDI operation.
;A<(V/E0), Midi loop count.
;C<A
;B<C7
;A<(BC)
;C<A
;B<0
;PUSH BC
;
;
FLGON
( --- )
Store FF in FLAG of current slider.
$CODE
5,'FLGON',FLGON
DB 1,0E0H
;A<(V/E0)
DB 1BH
;C<A
DB 6AH,0C7H
;B<C7
DB 69H,0FFH
;A<FF
DB 39H
;(BC)<A
$NEXT
;
;
FLGOFF
( --- )
Store 0 in FLAG of current slider.
$CODE
6,'FLGOFF',FLGOFF
DB 1,0E0H
;A<(V/E0)
DB 1BH
;C<A
DB 6AH,0C7H
;B<C7
DB 69H,0
;A<0
DB 39H
;(BC)<A
$NEXT
;
;
;
?DIFF
AHEAD:
;
;
LDLAST
(old,new --- |shifted new,FF| or |00|)
If |old-new| > 1, then push 7-bit new and a flag of FFH.
Else push flag of zero.
$CODE
5,'?DIFF',QDIFF
DB 0A4H
DB 0A1H
DB 09H
DB 60H,0E3H
;POP EA, new
;POP BC, old
;A<EAL
;A<A-C
DB
DB
DB
DB
DB
DB
DB
DB
DB
DB
DB
;C<FF
;A-C, skip if no zero, check diff=0.
;A<0
;C<0, flag = 00
;A AND FE, skip if no zero
;JMP AHEAD if |old-new| < 1.
;A<EAL
;A SHIFT RIGHT, change 8bit to 7bit.
;EAL<A
;PUSH EA, Push 7-bit "new" value
;C<FF, flag = FF
6BH,0FFH
60H,0EBH
69H,0
6BH,0
47H,0FEH
0C7H
9H
48H,21H
19H
0B4H
6BH,0FFH
DB 6AH,0
DB 0B1H
$NEXT
;B<0
;PUSH BC, Push flag.
( --- )
Moves ADC value to SLAST value
of the slider specified in MLOOP counter FFE0.
$CODE
6,'LDLAST',LDLAST
DB 1,0E0H
;A<(V/E0)
DB 1BH
;C<A
DB 6AH,0C6H
;B<C6
DB 29H
;A<(BC)
DB 19H
;EAL<A
DB 0BH
;A<C
78
DB 46H,40H
DB 1BH
DB 09H
DB 39H
$NEXT
:
;A<A+40
;C<A
;A<EAL
;(BC)<A
LDSTAT ( --- )
(Load current Byte1 to FFE1, last Midi status sent)
BYT1 FFE1 C!
;
:
TSTAT
( --- )
(Check last Midi status sent & send new one if not =)
BYT1 DUP FFE1 C@ =
IF DROP
ELSE TM LDSTAT
THEN
;
MIDI OPERATIONS
:
MCASE
CASE
( --- , Midi routines Case statement)
DUMMY KEYN KEYAT CNTRL PRG CHAT PWHL DUMMY
;
:
KEYN
(Midi routine for Key On and Key Off.
If the slider goes below the top of its travel and the
note is off (as indicated by FLAG=0) then send a MIDI Note
On message.
If ADC=0 and the note is on (indicated by FLAG=FF)
then send a Midi Note Off.)
ADCV 0 =
IF LDLAST FLAG
IF BYT1 TM LDSTAT BYT2 TM FLGOFF 0 TM
ELSE EXIT
THEN
ELSE
FLAG
IF
ELSE
(Midi Note Off)
EXIT
ADCV SLAST - 0<
IF BYT1 TM LDSTAT BYT2 TM FLGON
ADCV 2/ TM
THEN LDLAST
THEN
THEN
;
79
(Midi Note on)
:
KEYAT
(Midi routine for Key On and Key Off with Polyphonic After
Touch.
Turn on Note when the slider drops below the top of
its rise.
Continue sending polyphonic After Touch.
Turn the Note off when the slider is brought back
down to zero.)
ADCV 0 =
IF LDLAST FLAG
IF BYT1 0F AND 90 OR TM
90 FFE1 C! (Load LST, last status)
BYT2 TM FLGOFF 0 TM EXIT
ELSE EXIT
THEN
ELSE
FLAG
IF
(Midi Note Off)
SLAST ADCV ?DIFF
IF TSTAT BYTE2 TM LDLAST TM EXIT (Midi After Touch)
ELSE EXIT
THEN
ELSE
ADCV SLAST - 0<
IF BYT1 F0 AND 90 OR TM
(Midi Note On)
90 FFE1 C! (Load LST, last status)
BYT2 TM FLGON ADCV 2/ TM
THEN LDLAST
THEN
THEN
;
:
CNTRL
(Midi routine for Controller Data.
changed, then send the new value)
SLAST ADCV ?DIFF
IF TSTAT BYT2 TM LDLAST TM
THEN
If the slider value has
(Do nothing if no change)
(Send Controller data)
;
:
PRG
(Midi routine for Program Changes. When the slider goes
above a set threshold then send a Midi Program Change once.)
40 ADCV <
IF FLAG
IF EXIT
ELSE BYT1 TM LDSTAT FLGON BYT2 TM (Send Midi Program)
THEN
ELSE FLGOFF
(If ADCV goes below threshold turn off FLAG)
THEN
;
80
:
CHAT
(Midi routine for Channel After Touch.
has changed, send the new value.)
SLAST ADCV ?DIFF
IF TSTAT LDLAST TM
THEN
If the slider value
(Do nothing if no change)
(Send Midi Channel Pressure)
;
:
PWHL
(Midi routine for Pitch Wheel data.
changed, send the new value.)
SLAST ADCV ?DIFF
IF TSTAT 0 TM LDLAST TM
THEN
If the slider value has
(Do nothing if no change)
(Send Midi Pitch Wheel)
;
***********************************************
:
MIDI
( --- , Main Midi loop)
C700 40 0 FILL
C640 40 0 FILL
BEGIN
UNTIL
(Reset FLAGs)
(Reset SLASTs)
ADCINIT MLOOP MCASE
SW@ NOT 7 AND (Leave loop by pushing buttons 1,2 or 3)
(Returns to originating EDIT program)
;
Main Program
HEX
: BDOWN 20 LED! 0 eFLD C@ 7 AND CASE U/D0 U/D1 U/D2 U/D3
U/D3 U/D4 U/D5 U/D6 U/D7 ;
: DUMMY ;
: MCASE CASE DUMMY DUMMY DUMMY BLOAD BMIDI BUP BDOWN
BLEFT BRIGHT ;
: MAIN CR 1 LI DECIMAL 1 LI eUPDAT eDISP
BEGIN
0 LED!
S@ MCASE
FFFF DELAY
NUF? UNTIL ." END MAIN " CR ;
HAND
81
Modified
Roland PG1000
Final Assembly Code
82
Page 60,100
;===============================================================
;
;
eForth 1.0 by Bill Muench and C. H. Ting, 1990
;
;
This is an implementation for the NEC 78C10 microcomputer by
;
John Talbert, 1994, Oberlin Conservatory.
;
;
Register Use:
Interpreter Pointer = DE
;
Data Stack Pointer = SP
;
Return Stack Pointer = HL
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
Free to use: BC, EA, VA, Alternate Registers.
'doList'
is accessed as a subroutine through a CALT instruction
(Call to Jump Table). This shows up as a 'DB 80H' line
in the $COLON and $USER Macros. When executed the
processor jumps to an address vector located at 80H. The
vectored 'doList' code is then located at 0F0H. The word
'call,' was changed to load 80H into the code area for a
doLST assembly.
A 9600 Baud serial I/O is provided. PortB/bit0 is used for serial
output and PortC/bit3 (INT2) is used for the serial input. The
serial input is interrupt driven with a vectored interrupt routine
located at 0A0H. The code words ?RX, TX!, and !IO make up the
rest of the serial I/O code. Three USER variables have been set
up for use by these serial I/O routines: SERIN, which holds the
received character and a flag; HAFBIT, which adjusts the software
timing of the receiver to read in the middle of each bit frame
(set it for 1/2 the BITIME minus 5); and BITIME, which adjusts the
software for a specific baud rate (17H for 9600 baud assuming a 12Mhz
processor clock).
The 78C10 is an 8-bit micro, therefore cell aligning to even addresses
is unnecessary. The $ALIGN Macro was taken out along with the NOP's
used for cell alignment in the other Macros. All occurrences of the
word ALGND were erased also. The word SEE no longer works because it
relies on cell alignment.
All of the system FORTH code is to be stored in ROM (up to 32K) starting
at address 0000H. Then there is 2K of RAM starting at address COOOH.
This memory setup required the following changes:
1) Return and Data stacks and TIB moved to RAM.
(See the Memory allocation EQU assignments.)
2) The USER variables were moved to the micro's
internal RAM at FF00H to FFFFH.
3) PAD word was changed to move the temporary buffer
area to RAM space.
4) The vocabulary pointers found in the word FORTH were
moved to RAM space by creating two new USER variables,
FHEAD and FLINK and changing DOVOC to read:
DW FHEAD,CNTXT,STORE,EXIT.
5) NTOP and CTOP were moved to RAM space to allow dictionary
expansion into RAM space.
Several words were added to the ROM Dictionary. The simple operators
1+,1-,2+,2-,2*,2/, were defined in machine code. The words C, ,
83
;
CCOMPILE, CODE, and ENDCODE were created to enable the creation
;
of code definition.
;
;
The NEC78C10 offers the following advantages:
;
1) Ten 16-bit internal registers and a 16-bit ALU.
;
Many 16-bit instructions for those FORTH stack operations.
;
2) Three 8-bit I/O ports.
;
3) Eight 8-bit Analog to Digital Converters.
;
4) Internal counters and programmable clock generators.
;
5) Internal hardware serial I/O. (can be used for MIDI I/O).
;
6) 64K address space including 256 bytes of internal RAM.
;
;
;==================================================================
;; Version control
VER
EQU
01H
;major release version
EXT
EQU
01H
;minor extension
;; Constants
COMPO
IMEDD
MASKK
EQU
EQU
EQU
040H
080H
07F1FH
;lexicon compile only bit
;lexicon immediate bit
;lexicon bit mask
CELLL
BASEE
VOCSS
EQU
EQU
EQU
2
10
6
;size of a cell
;default radix
;depth of vocabulary stack
BKSPP
LF
CRR
ERR
TIC
EQU
EQU
EQU
EQU
EQU
8
10
13
27
39
;backspace
;line feed
;carriage return
;error escape
;tick
CALLL
EQU
80H
;CALT opcodes
;; Memory allocation
0//code>--//--<name//up>--<sp//tib>--rp//em
COLDD
RPP
TIBB
SPP
UPP
NAMEE
CODEE
CTOP
NTOP
PADD
SLDTR
ADCINT
00100H
0C2F0H
0C200H
0C1F0H
0FF00H
03FFDH
00300H
0C390H
0C7FFH
0C300H
00200H
00280H
EQU
EQU
EQU
EQU
EQU
EQU
EQU
EQU
EQU
EQU
EQU
EQU
;cold start
;start of return stack (RP0)
;terminal input buffer (TIB)
;start of data stack (SP0)
;start of user area (UP0)
;name dictionary
;code dictionary
;RAM code dict. expansion
;RAM name dict. expansion
;PAD area
;Table for Slider# translate
;ADC Interrupt routine
;; Initialize assembly variables
_LINK
_NAME
_CODE
_USER
=
=
=
=
0
NAMEE
CODEE
4*CELLL
;force a null link
;initialize name pointer
;initialize code pointer
;first user variable offset
;; Define assembly macros
84
;
Compile a code definition header.
$CODE
LABEL:
MACRO
LEX,NAME,LABEL
_CODE
_LEN
_NAME
_NAME
DW
_LINK
DB
_CODE
ENDM
= $
= (LEX AND 01FH)/CELLL
= _NAME-((_LEN+3)*CELLL)
ORG
ORG
_CODE,_LINK
= $
LEX,NAME
;
Compile a colon definition header.
$COLON
MACRO
$CODE
DB 80H
ENDM
LEX,NAME,LABEL
LEX,NAME,LABEL
;;include CALT doLIST
;
Compile a user variable header.
$USER
MACRO
$CODE
DB 80H
DW
_USER
ENDM
LEX,NAME,LABEL
LEX,NAME,LABEL
Compile an inline string.
D$
MACRO
DW
_LEN
DB
_CODE
_LEN
DB
_CODE
ENDM
ORG
FUNCT,STRNG
FUNCT
= $
0,STRNG
= $
Compile a stored string.
SD$
MACRO
STRNG
DW DOLIT
_LEN
= $ + 4
DW
_LEN,EXIT
DB
0,STRNG
_CODE
= $
_LEN
DB
_CODE-_LEN-1
_CODE
ENDM
ORG
;
;;function
;;save address of count byte
;;count byte and string
;;save code pointer
;;point to count byte
;;set count
;;restore code pointer
_CODE-_LEN-1
;
ORG
;;include CALT doLIST
;;followed by doUSER and offset
;;update user area offset
DOUSE,_USER
= _USER+CELLL
;
ORG
;;assembly label
;;save code pointer
;;string cell count, round down
;;new header on cell boundary
;;set name pointer
;;token pointer and link
;;link points to a name string
;;name string
;;restore code pointer
;;save address of count byte
;;save cnt address on stack
;;count byte and string
;;save code pointer
;;point to count byte
;;set count
;;restore code pointer
Assemble inline direct threaded code ending.
85
$NEXT
MACRO
DB 48H,84H
;;EA<(DE)++,next code address
DB 48H,28H
;;JMP EA,jump directly to code
into AX
address
ENDM
;; Main entry points and COLD start data
MAIN
ASSUME
SEGMENT
CS:MAIN,DS:MAIN,ES:MAIN,SS:MAIN
ORG
0000H
ORIG:
DB
DB
DB
DB
DB
DB
DB
DB
DB
ORG
00A0H
54H,00,01,00
0AAH,62H,0,0
8 DUP(0)
54H,0A0H,00H, 5 DUP(0)
8 DUP(0)
54H,80H,02, 5 DUP(0)
8 DUP(0)
48 DUP(0)
32 DUP(0)
;RESET vector, JMP 0100H
;NMI vector, EI RETI
;INT T0/T1 vector
;INT1/2 vector, JMP 00A0H
;INT E1/E0 vector
;INT EIN/AD vector, JMP 0280H
;INT SR/ST vector
;FREE
;SOFTI vector at 0060H
; Vectored INT2 routine for Serial Input from Host Computer.
; Uses address FFF0 as a counter location - do not use elsewhere!
DB 0B1H
;PUSH BC
DB 0B2H
;PUSH DE
DB 0B0H
;PUSH VA
DB 68H,0FFH
;MVI, V<FF
DB 71H,0F0H,07H
;MVIW, (V/F0)<07, number of bits to receive.
DB 70H,1FH,04CH,0FFH
;LBCD, BC<(FF4C), wait for a half bit.
DB 53H
;DCR, C<C-1 skip, LOOP1
DB 0FEH
;JR, Jump to loop1
DB 52H
;DCR, B<B-1 skip
DB 0FCH
;JR, Jump to loop1
DB 70H,1FH,4EH,0FFH
;LBCD, BC<(FF4E),wait 1 bit time, LOOP2
DB 53H
;DCR, C<C-1 skip
DB 0FEH
;JR, Jump to loop2
DB 52H
;DCR, B<B-1 skip
DB 0FCH
;JR, Jump to loop2
DB 04CH,0C2H
;MOV, A<PC, read serial input on pc3
DB 48H,31H,48H,31H
;Rotate PC3 bit into Cy
DB 48H,31H,48H,31H
;RLR, A rotate right 4xs
DB 0CH
;MOV, A<D, D collects the bits
DB 48H,31H
;RLR, shift in next bit, CY to top of D
DB 1CH
;MOV, D<A
DB 30H,0F0H
;DCRW, (V/F0)<(V/F0)-1 skip
DB 0E7H
;JR, Jump to loop2 for next bit.
DB 70H,1FH,4EH,0FFH
;LBCD, BC<(FF4E)
DB 53H,0FEH,52H,0FCH
;DCR JR DCR JR, stop bit loop time.
DB 71H,04BH,0FFH
;MVIW, (V/4B)<FF, load flag
DB 0CH,63H,04AH
;MOV STAW, A<D (V/4A)<A, load data
DB 0A0H,0A2H,0A1H
;POP, restore AV DE and BC
DB 48H,44H,0
;SKIT,NOP
DB 0AAH,062H
;EI RETI, enable interrupts and return
86
;; Kernel doLST routine. Always accessed by the CALT instruction: 80H
;; which is a Call Subroutine to jump to address vector located at 0080H.
ORG
ORG
00F0H
DB 33H,33H
DB 0A6H
DB 48H,93H
DB 0A2H
DB 48H,84H
DB 48H,28H
0080H
DB 0F0H,0
;HL<HL-2
;EA<DE
;(HL)<EA
;POP DE previously pushed by CALT
;EA<(DE)++, $NEXT
;JMP EA
; set up vector to doLST
;; Table for translating Slider numbers into an orderly sequence as
;; physically set up on the Roland PG1000 board.
ORG
SLDTR
DB 48,56,40,37,53,61,45,35
DB 51,59,43,33,49,57,41,38
DB 54,62,46,30,32,16,08,00
DB 24,21,13,05,29,19,11,03
DB 44,27,17,09,01,25,22,14
DB 06,34,50,60,52,36,20,12
DB 04,28,18,10,02,26,42,58
DB 07,15,23,31,39,47,55,63
ORG
COLDD
DB 69H,0FH,4DH,0D0H
DB 69H,0FFH,4DH,0D2H
DB 69H,00H,4DH,0D3H
DB 64H,01H,05H
DB 4DH,0D7H
DB 69H,0AH,4DH,0D4H
DB 69H,0BH,4DH,0D1H
DB 64H,02H,04H
DB 64H,81H,06H
DB 69H,4EH,4DH,0CAH
DB 04H
DB LOW SPP
DB HIGH SPP
DB 34H
DB LOW RPP
DB HIGH RPP
DB 69H,00H,4DH,0E8H
DB 68H,0FFH
DB 10H,68H,0FFH,69H,0
;Beginning of Cold Boot
;MM<0F, memory map (11-8)
;MA<FF, pa inputs (4-2)
;MB<00, pb outputs (4-6)
;PB<5
;MF<00, pf outputs (4-15)
;MC<0A, pc1/3 inputs (4-9)
;MCC<0B, pc mode (4-8)
;PC<04
;SMH<06, serial mode (7-7)
;SML<4E, serial mode (7-9)
;SP<SPP, stack pointer=data stack
;HL<RPP, HL=return stack pointer
;ZCM<0, zero cross disabled (3-26)
;V<FF
;V'<FF, A"<0, V<FF, A<0
;; timer setups for Midi and LCD use
DB 69H,64H,4DH,0DAH
;TM0<64, timer0 (5-1)
DB 69H,0FFH,4DH,0DBH
;TM1<FF, timer1 (5-1)
DB 64H,85H,0B3H
;TMM<B3, timer mode (5-6)
DB 44H,60H,0EAH,48H,0D3H
;ETM1<EA = EA60 (6-2)
DB 64H,83H,0CCH
;EOM<CC, timer event mode (6-14)
DB 69H,5CH,4DH,0CCH
;ETMM<5C, timer event mode (6-11)
DB 54H,00,03H
;JMP to 0300, high level cold start
87
;COLD WORD MOVED TO THE START OF CODE AREA.
;ATTEMPTED TO AUTOMATE-JMP COLD-WITH $JUMP
;BUT MACRO PRODUCES ERROR CODES.
; COLD start moves the following to USER variables.
; MUST BE IN SAME ORDER AS USER VARIABLES.
UZERO:
DW
DW
DW
DW
DW
DW
DW
DW
DW
DW
DW
DW
DW
DW
DW
DW
DW
DW
DW
DW
DW
DW
DW
DW
DW
DW
DW
DW
DW
DW
DW
4 DUP (0)
SPP
RPP
QRX
TXSTO
ACCEP
KTAP
TXSTO
DOTOK
BASEE
0
0
0
0
TIBB
0
INTER
NUMBQ
0
0
0
VOCSS DUP (0)
0
0
0
0
CTOP
NTOP
LASTN
0
06H
DW
16H
;reserved
;SP0
;RP0
;'?KEY
;'EMIT
;'EXPECT
;'TAP
;'ECHO
;'PROMPT
;BASE
;tmp
;SPAN
;>IN
;#TIB
;TIB
;CSP
;'EVAL
;'NUMBER
;HLD
;HANDLER
;CONTEXT pointer
;vocabulary stack
;CURRENT pointer
;vocabulary link pointer
;FORTH HEAD
;FORTH LINK
;CP
;NP
;LAST
;SERIN host receive char & flag
;HAFBIT time for serial host,
; (1/2 BITIME - 5)
;BITIME baud for serial host
ULAST:
ORG ADCINT
;
;
;
;
Interrupt routine for Analog to Digital Converters
DB 10H
;EXA
DB 11H
;EXX
Load ADC Address and Counter into HL. Uses FFF2 and FFF3.
DB 68H,0FFH
;V'<FF
DB 69H,0C6H
;A<C6
DB 1EH
;H<A
DB 01H,0F3H
;A<(V/F3)
DB 1FH
;L<A
Store ADC 0.
DB 4CH,0E0H
;A<CR0
DB 3DH
;(HL)+<A, store new value
Store ADC 1.
88
;
;
;
DB 4CH,0E1H
DB 3DH
Store ADC 2.
DB 4CH,0E2H
DB 3DH
Store ADC 3.
DB 4CH,0E3H
DB 3DH
Update Counters
DB 0FH
DB 63H,0F3H
DB 48H,25H
DB 48H,05H
DB 0C7H
DB 64H,1EH,01
DB 10H,11H,0AAH,62H
DB
DB
DB
DB
DB
DB
DB
;
Return from Interrupt.
DB 10H
DB 11H
DB 0AAH
DB 62H
ORG
;
;
1AH
74H,0AH,0E0H
4CH,0C2H
07H,1FH
60H,9AH
4DH,0C2H
64H,90H,08H
;A<CR1
;(HL)+<A, store new value
;A<CR2
;(HL)+<A, store new value
;A<CR3
;(HL)+<A, store new value
;A<L
;(V/F3)<A, Load counter.
;A shift logical left
;A shift left, skip if carry (if end count)
;JMP AHEAD
;MKH<MKH OR 1, disable interrupts
;Return from interrupts
;B<A, "AHEAD"
;B<B AND E0
;A<Pc
;A<A AND 1F
;A<A OR B
;Pc<A, Load high 3 bits of slider select.
;Invert ANM bit and restart conversion.
;EXA
;EXX
;EI
;RETI
CODEE
COLD
COLD1:
;start code dictionary
( -- )
The hilevel cold start sequence.
CCOLD = $
$COLON 4,'COLD',COLD
DW
DOLIT,UZERO,DOLIT,UPP
DW
DOLIT,ULAST-UZERO,CMOVE ;initialize user area
DW
PRESE
;initialize stack and TIB
DW
TBOOT,ATEXE
;application boot
DW
FORTH,CNTXT,AT,DUPP
;initialize search order
DW
CRRNT,DSTOR,OVERT
DW
LCDIN
;initialize LCD
DW
EDIT
;Autostart EDIT
DW
QUIT
;start interpretation
DW
BRAN,COLD1
;just in case
;; Device dependent I/O
;
;
;
;
BYE
?RX
( -- )
Exit eForth.
$CODE
3,'BYE',BYE
DB 54H,0,0
;JMP Reset Vector
( -- c T | F )
Return input character and true, or a false if no input.
89
$CODE
3,'?RX',QRX
DB 68H,0FFH
;MVI, V<FF
DB 01H,4BH
;LDAW, A<(V/4B) read serial-in flag
DB 47H,0FFH
;ONI, A AND FF skip if flag not zero
DB 0CAH
;JR, jump ahead1
DB 71H,04BH,0
;MVIW, (V/4B)<0, reset flag to zero
DB 70H,1FH,4AH,0FFH
;LBCD, BC<(FF4A), read serin data
DB 0B1H
;PUSH BC, push serial input data to stack
DB 69H,0FFH
;A<FF
DB 1BH
;C<A, AHEAD1
DB 6AH,0
;B<0
DB 0B1H
;PUSH BC, push serial input flag to stack
$NEXT
;
;
TX!
( c -- )
Send character c to the output device.
$CODE
3,'TX!',TXSTO
DB 0BAH
;Disable Interrupts
DB 0A1H
;POP BC, pop char into C
DB 0B2H
;PUSH DE, store interpreter pointer
DB 0BH,1CH
;A<C, D<A, char in A and D
DB 68H,0FFH
;V<FF
DB 71H,0F0H,07H
;(V/F0)<7
DB 60H,91H
;A<A EXOR A
DB 6DH,01H
;E<01
DB 4DH,0C1H
;PB<A
DB 70H,1FH,04EH,0FFH
;BC<(FF4E) set baud, LOOP1
DB 53H,0FEH,52H,0FCH
;C<C-1, JR, B<B-1, JR, jr to loop1
DB 0CH
;A<D
DB 07H,01H
;A<A AND 01
DB 4DH,0C1H
;PB<A, send a bit
DB 0CH
;A<D
DB 48H,31H
;A rotate logical right
DB 1CH
;D<A
DB 0,0,0,0
;NOPs to make rec loop = transmit loop.
DB 30H,0F0H
;(V/F0)<(V/F0)-1 skip
DB 0E8H
;JR, jump to loop1
DB 0DH
;A<E
DB 51H
;A<A-1 skip
DB 0C6H
;JR, jump to loop2
DB 0A2H
;POP DE, restore interpreter pointer
DB 0AAH
;Enable Interrupts
$NEXT
;End of routine
DB
DB
DB
DB
;
;
!IO
6CH,03H
1DH
71H,0F0H,01
4FH,0D7H
;D<03, LOOP2
;E<A
;(V/F0)<01
;JRE, jump to loop1
( -- )
Initialize the serial I/O devices.
$CODE
3,'!IO',STOIO
DB 69H,0EFH,4DH,0C7H
;MKL<EF, enable int2 interrupt and
DB 69H,0FFH,4DH,0C6H
;MKH<FF, disable all others with mask
90
DB 0AAH
$NEXT
;EI, enable interrupt
;; The kernel
;
;
doLIT
( -- w )
Push an inline literal.
$CODE
COMPO+5,'doLIT',DOLIT
DB 48H,84H
DB 0B4H
$NEXT
;
;
EXIT
( -- )
Terminate a colon definition.
$CODE
4,'EXIT',EXIT
DB 48H,85H
DB 0B6H
$NEXT
;
;
EXECUTE
next
NEXT1:
;
;
?branch
;EA<(HL)++
;DE<EA
( ca -- )
Execute the word at ca.
$CODE
7,'EXECUTE',EXECU
DB 0A1H
DB 21H
;
;
;
;
;EA<(DE)++
;PUSH EA
;POP BC
;JMP BC
( -- )
Run time code for the single index loop.
: next ( -- ) \ hilevel model
r> r> dup if 1 - >r @ >r exit then drop cell+ >r ;
$CODE
COMPO+4,'next',DONXT
DB 6AH,0
DB 6BH,1
DB 48H,83H
DB 74H,0B5H
DB 0C9H
DB 48H,93H
DB 48H,82H
DB 0B6H
$NEXT
DB 22H,22H
DB 32H,32H
$NEXT
;B<00
;C<01
;EA<(HL)
;EA<EA-BC Skip if no borrow
;JMP NEXT1
;(HL)<EA
;EA<(DE)
;DE<EA
;DE<DE+2
;HL<HL+2
( f -- )
Branch if flag is zero.
$CODE
COMPO+7,'?branch',QBRAN
DB 6AH,0FFH
DB 6BH,0FFH
DB 0A4H
DB 74H,0CDH
DB 0C6H
DB 22H,22H
91
;B<FF
;C<FF
;POP EA
;EA AND BC Skip if not zero
;JMP BRAN1
;DE<DE+2
BRAN1:
;
;
branch
$NEXT
DB 48H,82H
DB 0B6H
$NEXT
;EA<(DE)
;DE<EA
( -- )
Branch to an inline address.
$CODE
COMPO+6,'branch',BRAN
DB 48H,82H
DB 0B6H
$NEXT
;
;
!
( w a -- )
Pop the data stack to memory.
$CODE
1,'!',STORE
DB 0A1H
DB 0A4H
DB 09H
DB 39H
DB 12H
DB 08H
DB 39H
$NEXT
;
;
@
C!
;POP BC
;A<(BC)
;EAL<A
;BC<BC+1
;A<(BC)
;EAH<A
;PUSH EA
( c b -- )
Pop the data stack to byte memory.
$CODE
2,'C!',CSTOR
DB 0A1H
DB 0A4H
DB 09H
DB 39H
$NEXT
;
;
C@
;POP BC, address
;POP EA, data
;A<EAL
;(BC)<A
;BC<BC+1
;A<EAH
;(BC)<A
( a -- w )
Push data at memory location to the data stack.
$CODE
1,'@',AT
DB 0A1H
DB 29H
DB 19H
DB 12H
DB 29H
DB 18H
DB 0B4H
$NEXT
;
;
;EA<(DE)
;DE<EA
;POP BC address
;POP AE data
;A<EAL
;(BC)<A
( b -- c )
Push byte memory location to the data stack.
$CODE
2,'C@',CAT
DB 0A1H
DB 29H
DB 6AH,0
DB 1BH
DB 0B1H
;POP BC
;A<(BC)
;B<00
;C<A
;PUSH BC
92
$NEXT
;
;
RP@
( -- a )
Push the current RP to the data stack.
$CODE
3,'RP@',RPAT
DB 0B3H
$NEXT
;
;
RP!
( a -- )
Set the return stack pointer.
$CODE
COMPO+3,'RP!',RPSTO
DB 0A3H
$NEXT
;
;
R>
R@
>R
;EA<(HL)
;PUSH EA
( w -- )
Push the data stack to the return stack.
$CODE
COMPO+2,'>R',TOR
DB 33H,33H
DB 0A4H
DB 48H,93H
$NEXT
;
;
SP@
SP!
;HL<HL-2
;POP EA
;(HL)<EA
( -- a )
Push the current data stack pointer.
$CODE
3,'SP@',SPAT
DB 70H,0EH,0FEH,0FFH
DB 70H,1FH,0FEH,0FFH
DB 0B1H
$NEXT
;
;
;EA<(HL)++
;PUSH EA
( -- w )
Copy top of return stack to the data stack.
$CODE
2,'R@',RAT
DB 48H,83H
DB 0B4H
$NEXT
;
;
;POP HL
( -- w )
Pop the return stack to the data stack.
$CODE
2,'R>',RFROM
DB 48H,85H
DB 0B4H
$NEXT
;
;
;PUSH HL
;(FFFE)<SP
;BC<(FFFE)
;PUSH BC
( a -- )
Set the data stack pointer.
$CODE
3,'SP!',SPSTO
DB 0A1H
DB 70H,1EH,0FEH,0FFH
DB 70H,0FH,0FEH,0FFH
$NEXT
93
;POP BC
;(FFFE)<BC
;PC<(FFFE)
;
;
DROP
( w -- )
Discard top stack item.
$CODE
4,'DROP',DROP
DB 0A4H
$NEXT
;
;
DUP
( w -- w w )
Duplicate the top stack item.
$CODE
3,'DUP',DUPP
DB 0A4H
DB 0B4H
DB 0B4H
$NEXT
;
;
SWAP
OVER
0<
AND
;POP AE
;POP BC
;PUSH BC
;PUSH AE
;PUSH BC
( n -- t )
Return true if n is negative.
$CODE
2,'0<',ZLESS
DB 0A1H
DB 69H,0FFH
DB 48H,06H
DB 69H,0
DB 1AH
DB 1BH
DB 0B1H
$NEXT
;
;
;POP EA
;POP BC
;PUSH EA
;PUSH BC
( w1 w2 -- w1 w2 w1 )
Copy second stack item to top.
$CODE
4,'OVER',OVER
DB 0A4H
DB 0A1H
DB 0B1H
DB 0B4H
DB 0B1H
$NEXT
;
;
;POP EA
;PUSH EA
;PUSH EA
( w1 w2 -- w2 w1 )
Exchange top two stack items.
$CODE
4,'SWAP',SWAP
DB 0A4H
DB 0A1H
DB 0B4H
DB 0B1H
$NEXT
;
;
;POP EA
;POP BC
;A<FF
;B Shift Left, Skip if carry
;A<00
;B<A
;C<A
;PUSH BC
( w w -- w )
Bitwise AND.
$CODE
3,'AND',ANDD
DB 0A1H
DB 0A4H
DB 74H,8DH
94
;POP BC
;POP AE
;EA<EA AND BC
DB 0B4H
$NEXT
;
;
OR
;PUSH EA
( w w -- w )
Bitwise inclusive OR.
$CODE
2,'OR',ORR
DB 0A1H
DB 0A4H
DB 74H,9DH
DB 0B4H
$NEXT
;
;
XOR
;POP BC
;POP EA
;EA<EA OR BC
;PUSH EA
( w w -- w )
Bitwise exclusive OR.
$CODE
3,'XOR',XORR
DB 0A1H
DB 0A4H
DB 74H,95H
DB 0B4H
$NEXT
;
;
UM+
;POP BC
;POP EA
;EA<EA EX-OR BC
;PUSH EA
( w w -- w cy )
Add two numbers, return the sum and carry flag.
$CODE
3,'UM+',UPLUS
DB 0A1H
DB 0A4H
DB 69H,0
DB 74H,0A5H
DB 41H
DB 1BH
DB 6AH,0
DB 0B4H
DB 0B1H
$NEXT
;POP BC
;POP EA
;A<00
;EA<EA+BC Skip if no carry
;A<A+1
;C<A
;B<00
;PUSH EA
;PUSH BC
;; System and user variables
;
;
doVAR
( -- a )
Run time routine for VARIABLE and CREATE.
$COLON
DW
;
;
UP
( -- a )
Pointer to the user area.
$COLON
DW
DW
;
;
doUSER
COMPO+5,'doVAR',DOVAR
RFROM,EXIT
2,'UP',UP
DOVAR
UPP
( -- a )
Run time routine for user variables.
$COLON
DW
COMPO+6,'doUSER',DOUSE
RFROM,AT,UP,AT,PLUS,EXIT
95
;
;
SP0
( -- a )
Pointer to bottom of the data stack.
$USER
;
;
RP0
( -- a )
Pointer to bottom of the return stack.
$USER
;
;
'?KEY
'EMIT
'EXPECT
'TAP
'ECHO
'PROMPT
BASE
tmp
SPAN
>IN
COMPO+3,'tmp',TEMP
( -- a )
Hold character count received by EXPECT.
$USER
;
;
4,'BASE',BASE
( -- a )
A temporary storage location used in parse and find.
$USER
;
;
7,"'PROMPT",TPROM
( -- a )
Storage of the radix base for numeric I/O.
$USER
;
;
5,"'ECHO",TECHO
( -- a )
Execution vector of PROMPT.
$USER
;
;
4,"'TAP",TTAP
( -- a )
Execution vector of ECHO.
$USER
;
;
7,"'EXPECT",TEXPE
( -- a )
Execution vector of TAP.
$USER
;
;
5,"'EMIT",TEMIT
( -- a )
Execution vector of EXPECT.
$USER
;
;
5,"'?KEY",TQKEY
( -- a )
Execution vector of EMIT.
$USER
;
;
3,'RP0',RZERO
( -- a )
Execution vector of ?KEY.
$USER
;
;
3,'SP0',SZERO
4,'SPAN',SPAN
( -- a )
Hold the character pointer while parsing input stream.
96
$USER
;
;
#TIB
3,'>IN',INN
( -- a )
Hold the current count and address of the terminal input buffer.
$USER
4,'#TIB',NTIB
_USER = _USER+CELLL
;
;
CSP
( -- a )
Hold the stack pointer for error checking.
$USER
;
;
'EVAL
( -- a )
Execution vector of EVAL.
$USER
;
;
'NUMBER
HLD
HANDLER
CONTEXT
3,'HLD',HLD
( -- a )
Hold the return stack pointer for error handling.
$USER
;
;
7,"'NUMBER",TNUMB
( -- a )
Hold a pointer in building a numeric output string.
$USER
;
;
5,"'EVAL",TEVAL
( -- a )
Execution vector of NUMBER?.
$USER
;
;
3,'CSP',CSP
7,'HANDLER',HANDL
( -- a )
A area to specify vocabulary search order.
$USER
7,'CONTEXT',CNTXT
_USER = _USER+VOCSS*CELLL
;
;
CURRENT
;vocabulary stack
( -- a )
Point to the vocabulary to be extended.
$USER
7,'CURRENT',CRRNT
_USER = _USER+CELLL
;vocabulary link pointer
;
;
FHEAD
( -- a )
Point to the FORTH vocab head pointer.
$USER
5,'FHEAD',FHEAD
;
;
FLINK
( -- a )
Point to the FORTH vocab link pointer.
$USER
5,'FLINK',FLINK
;
;
CP
( -- a )
Point to the top of the code dictionary.
$USER
2,'CP',CP
97
;
;
NP
( -- a )
Point to the bottom of the name dictionary.
$USER
;
;
LAST
( -- a )
Point to the last name in the name dictionary.
$USER
;
;
SERIN
HAFBIT
BITIME
5,'SERIN',SERIN
( -- a )
Point to half bit time used by serial i/0 routines.
$USER
;
;
4,'LAST',LAST
( -- a )
Point to host serial input. Flag in high, char in low byte.
$USER
;
;
2,'NP',NP
6,'HAFBIT',HAFBIT
( -- a )
Point to bit time used to set serial i/o baud rate.
$USER
6,'BITIME',BITIME
;; Common functions
;
;
doVOC
( -- )
Run time action of VOCABULARY's.
$COLON
DW
;
;
FORTH
COMPO+5,'doVOC',DOVOC
FHEAD,CNTXT,STORE,EXIT
( -- )
Make FORTH the context vocabulary.
$COLON 5,'FORTH',FORTH
DW
DOVOC,EXIT
; Head and Link pointers normally here were moved to User Ram.
;
;
?DUP
( w -- w w | 0 )
Dup tos if its is not zero.
$CODE 4,'?DUP',QDUP
DB 6AH,0FFH
DB 6BH,0FFH
DB 0A4H
DB 74H,0DDH
DB 0B4H
DB 0B4H
$NEXT
;
;
ROT
;B<FF
;C<FF
;POP EA
;EA AND BC, Skip if zero
;PUSH EA
;PUSH EA
( w1 w2 w3 -- w2 w3 w1 )
Rot 3rd item to top.
$COLON
DW
3,'ROT',ROT
TOR,SWAP,RFROM,SWAP,EXIT
98
;
;
2DROP
( w w -- )
Discard two items on stack.
$CODE 5,'2DROP',DDROP
DB 0A4H,0A4H
$NEXT
;
;
2DUP
( w1 w2 -- w1 w2 w1 w2 )
Duplicate top two items.
$CODE 4,'2DUP',DDUP
DB 0A4H,0A1H
DB 0B1H,0B4H
DB 0B1H,0B4H
$NEXT
;
;
+
D+
;
;
NOT
;POP BC, POP EA
;EA<EA+BC, Skip
;NOP
;PUSH EA
( d d -- d )
Double addition, as an example using UM+.
$COLON
DW
DW
2,'D+',DPLUS
TOR,SWAP,TOR,UPLUS
RFROM,RFROM,PLUS,PLUS,EXIT
( w -- w )
One's complement of tos.
$CODE 3,'NOT',INVER
DB 0A1H
DB 69H,0FFH
DB 60H,12H
DB 60H,13H
DB 0B1H
$NEXT
;
;
NEGATE
;POP EA, POP BC
;PUSH BC, PUSH EA
;PUSH BC, PUSH EA
( w w -- sum )
Add top two items.
$CODE 1,'+',PLUS
DB 0A1H,0A4H
DB 74H,0A5H
DB 0
DB 0B4H
$NEXT
;
;
;
;
;
;
;POP EA, POP EA
;POP BC
;A<FF
;B<B EX-OR A
;C<C EX-OR A
;PUSH BC
( n -- -n )
Two's complement of tos.
$CODE 6,'NEGATE',NEGAT
DB 0A1H
DB 69H,0FFH
DB 60H,12H
DB 60H,13H
DB 12H
DB 0B1H
$NEXT
99
;POP BC
;A<FF
;B<B EX-OR A
;C<C EX-OR A
;BC<BC+1
;PUSH BC
;
;
DNEGATE
( d -- -d )
Two's complement of top double.
$COLON
DW
DW
DW
;
;
-
7,'DNEGATE',DNEGA
INVER,TOR,INVER
DOLIT,1,UPLUS
RFROM,PLUS,EXIT
( n1 n2 -- n1-n2 )
Subtraction.
$CODE 1,'-',SUBB
DB 0A1H
DB 069H,0FFH
DB 060H,12H
DB 060H,13H
DB 12H
DB 0A4H
DB 74H,0A5H
DB 0
DB 0B4H
$NEXT
;
;
ABS
;POP BC
;A<FF
;B<B EX-OR A
;C<C EX-OR A
;BC<BC+1
;POP EA
;EA<EA+BC Skip
;NOP
;PUSH EA
( n -- n )
Return the absolute value of n.
ABS1:
$COLON
DW
DW
DW
DW
;
;
( w w -- t )
Return true if top two are equal.
=
3,'ABS',ABSS
DUPP,ZLESS
QBRAN,ABS1
NEGAT
EXIT
$CODE 1,'=',EQUAL
DB 0A4H,0A1H
DB 69H,0FFH
DB 74H,0FDH
DB 69H,00H
DB 1AH,1BH
DB 0B1H
$NEXT
;
;
U<
;POP EA, POP BC
;A<FF
;EA-BC, Skip if zero
;A<00
;B<A, C<A
;PUSH BC
( u u -- t )
Unsigned compare of top two items.
ULES1:
$COLON
DW
DW
DW
DW
;
;
( n1 n2 -- t )
Signed compare of top two items.
<
$COLON
DW
2,'U<',ULESS
DDUP,XORR,ZLESS
QBRAN,ULES1
SWAP,DROP,ZLESS,EXIT
SUBB,ZLESS,EXIT
1,'<',LESS
DDUP,XORR,ZLESS
100
LESS1:
DW
DW
DW
;
;
( n n -- n )
Return the greater of two top stack items.
MAX
QBRAN,LESS1
DROP,ZLESS,EXIT
SUBB,ZLESS,EXIT
$CODE 3,'MAX',MAX
DB 0A4H,0A1H
DB 74H,0BDH
DB 0C2H
DB 0B1H
DB 0C1H
DB 0B4H
$NEXT
;
;
MIN
;POP EA, POP BC
;EA-BC, Skip if borrow
;Jump to Push EA
;PUSH BC
;Jump to next
;PUSH EA
( n n -- n )
Return the smaller of top two stack items.
$CODE 3,'MIN',MIN
DB 0A4H,0A1H
DB 74H,0BDH
DB 0C2H
DB 0B4H
DB 0C1H
DB 0B1H
$NEXT
;
;
WITHIN
;POP EA, POP BC
;EA-BC, Skip if borrow
;Jump to Push EA
;PUSH EA
;Jump to next
;PUSH BC
( u ul uh -- t )
Return true if u is within the range of ul and uh.
$COLON
DW
DW
6,'WITHIN',WITHI
OVER,SUBB,TOR
SUBB,RFROM,ULESS,EXIT
;; Quick Operators
;
;
;
;
1+
1-
2+
( n -- n+1 )
$CODE 2,'1+',ONEP
DB 0A1H
DB 12H
DB 0B1H
$NEXT
;POP BC
;BC<BC+1
;PUSH BC
( n -- n-1 )
$CODE 2,'1-',ONEM
DB 0A1H
DB 013H
DB 0B1H
$NEXT
;POP BC
;BC<BC-1
;PUSH BC
( n -- n+2 )
$CODE 2,'2+',TWOP
101
;ul <= u < uh
DB 0A1H
DB 12H,12H
DB 0B1H
$NEXT
;
;
;
2-
2*
2/
;POP BC
;BC<BC+2
;PUSH BC
( n -- n-2 )
$CODE 2,'2-',TWOM
DB 0A1H
DB 13H,13H
DB 0B1H
$NEXT
;POP BC
;BC<BC-2
;PUSH BC
( n -- n*2 )
$CODE 2,'2*',TWOSL
DB 0A4H
DB 48H,0A4H
DB 0B4H
$NEXT
;POP EA
;EA Logical Shift Left
;PUSH EA
( n -- n/2 )
$CODE 2,'2/',TWOSR
DB 0A4H
DB 48H,0A0H
DB 0B4H
$NEXT
;POP EA
;EA Logical Shift Right
;PUSH EA
;; Divide
;
;
UM/MOD
UMM1:
UMM2:
UMM3:
UMM4:
;
M/MOD
;
quotient.
( udl udh u -- ur uq )
Unsigned divide of a double by a single. Return mod and quotient.
$COLON
DW
DW
DW
DW
DW
DW
DW
DW
DW
DW
DW
DW
DW
DW
DW
DW
DW
6,'UM/MOD',UMMOD
DDUP,ULESS
QBRAN,UMM4
NEGAT,DOLIT,15,TOR
TOR,DUPP,UPLUS
TOR,TOR,DUPP,UPLUS
RFROM,PLUS,DUPP
RFROM,RAT,SWAP,TOR
UPLUS,RFROM,ORR
QBRAN,UMM2
TOR,DROP,ONEP,RFROM
BRAN,UMM3
DROP
RFROM
DONXT,UMM1
DROP,SWAP,EXIT
DROP,DDROP
DOLIT,-1,DUPP,EXIT
;overflow, return max
( d n -- r q )
Signed floored divide of double by single. Return mod and
$COLON
DW
DW
DW
5,'M/MOD',MSMOD
DUPP,ZLESS,DUPP,TOR
QBRAN,MMOD1
NEGAT,TOR,DNEGA,RFROM
102
MMOD1:
MMOD3:
DW
DW
DW
DW
DW
DW
DW
;
;
( n n -- r q )
Signed divide. Return mod and quotient.
MMOD2:
/MOD
$COLON
DW
;
;
MOD
/
4,'/MOD',SLMOD
OVER,ZLESS,SWAP,MSMOD,EXIT
( n n -- r )
Signed divide. Return mod only.
$COLON
DW
;
;
TOR,DUPP,ZLESS
QBRAN,MMOD2
RAT,PLUS
RFROM,UMMOD,RFROM
QBRAN,MMOD3
SWAP,NEGAT,SWAP
EXIT
3,'MOD',MODD
SLMOD,DROP,EXIT
( n n -- q )
Signed divide. Return quotient only.
$COLON
DW
1,'/',SLASH
SLMOD,SWAP,DROP,EXIT
;; Multiply
;
;
UM*
UMST1:
UMST2:
;
;
*
( u u -- ud )
Unsigned multiply. Return double product.
$COLON
DW
DW
DW
DW
DW
DW
DW
( n n -- n )
Signed multiply. Return single product.
$COLON
DW
;
;
M*
3,'UM*',UMSTA
DOLIT,0,SWAP,DOLIT,15,TOR
DUPP,UPLUS,TOR,TOR
DUPP,UPLUS,RFROM,PLUS,RFROM
QBRAN,UMST2
TOR,OVER,UPLUS,RFROM,PLUS
DONXT,UMST1
ROT,DROP,EXIT
1,'*',STAR
UMSTA,DROP,EXIT
( n n -- d )
Signed multiply. Return double product.
MSTA1:
$COLON
DW
DW
DW
DW
DW
DW
;
( n1 n2 n3 -- r q )
*/MOD
2,'M*',MSTAR
DDUP,XORR,ZLESS,TOR
ABSS,SWAP,ABSS,UMSTA
RFROM
QBRAN,MSTA1
DNEGA
EXIT
103
;
Multiply n1 and n2, then divide by n3. Return mod and quotient.
$COLON
DW
;
;
*/
5,'*/MOD',SSMOD
TOR,MSTAR,RFROM,MSMOD,EXIT
( n1 n2 n3 -- q )
Multiply n1 by n2, then divide by n3. Return quotient only.
$COLON
DW
2,'*/',STASL
SSMOD,SWAP,DROP,EXIT
;; Miscellaneous
;
;
BL
( -- 32 )
Return 32, the blank character.
$COLON
DW
;
;
>CHAR
2,'BL',BLANK
DOLIT,' ',EXIT
( c -- c )
Filter non-printing characters.
TCHA1:
$COLON
DW
DW
DW
DW
DW
;
;
( -- n )
Return the depth of the data stack.
DEPTH
$COLON
DW
DW
;
;
PICK
5,'>CHAR',TCHAR
DOLIT,07FH,ANDD,DUPP
DOLIT,127,BLANK,WITHI
QBRAN,TCHA1
DROP,DOLIT,'_'
EXIT
;mask msb
;check for printable
;replace non-printables
5,'DEPTH',DEPTH
SPAT,SZERO,AT,SWAP,SUBB
DOLIT,CELLL,SLASH,EXIT
( ... +n -- ... w )
Copy the nth stack item to tos.
$COLON
DW
DW
4,'PICK',PICK
ONEP,TWOSL
SPAT,PLUS,AT,EXIT
;; Memory access
;
;
+!
( n a -- )
Add n to the contents at address a.
$COLON
DW
DW
;
;
2!
2,'+!',PSTOR
SWAP,OVER,AT,PLUS
SWAP,STORE,EXIT
( d a -- )
Store the double integer to address a.
$COLON
DW
DW
2,'2!',DSTOR
SWAP,OVER,STORE
TWOP,STORE,EXIT
104
;
;
2@
( a -- d )
Fetch double integer from address a.
$COLON
DW
DW
;
;
COUNT
( b -- b +n )
Return count byte of a string and add 1 to byte address.
$COLON
DW
DW
;
;
HERE
PAD
TIB
@EXECUTE
3,'PAD',PAD
DOLIT,PADD,EXIT
( -- a )
Return the address of the terminal input buffer.
$COLON
DW
;
;
4,'HERE',HERE
CP,AT,EXIT
( -- a )
Return the address of a temporary buffer.
$COLON
DW
;
;
5,'COUNT',COUNT
DUPP,ONEP
SWAP,CAT,EXIT
( -- a )
Return the top of the code dictionary.
$COLON
DW
;
;
2,'2@',DAT
DUPP,TWOP,AT
SWAP,AT,EXIT
3,'TIB',TIB
NTIB,TWOP,AT,EXIT
( a -- )
Execute vector stored in address a.
EXE1:
$COLON
DW
DW
DW
DW
;
;
( b1 b2 u -- )
Copy u bytes from b1 to b2.
CMOVE
CMOV1:
CMOV2:
;
;
FILL
$COLON
DW
DW
DW
DW
DW
DW
DW
DW
8,'@EXECUTE',ATEXE
AT,QDUP
QBRAN,EXE1
EXECU
EXIT
;?address or zero
;execute if non-zero
;do nothing if zero
5,'CMOVE',CMOVE
TOR
BRAN,CMOV2
TOR,DUPP,CAT
RAT,CSTOR
ONEP
RFROM,ONEP
DONXT,CMOV1
DDROP,EXIT
( b u c -- )
Fill u bytes of character c to area beginning at b.
105
FILL1:
FILL2:
;
;
-TRAILING
DTRA1:
DTRA2:
;
;
PACK$
$COLON
DW
DW
DW
DW
DW
4,'FILL',FILL
SWAP,TOR,SWAP
BRAN,FILL2
DDUP,CSTOR,ONEP
DONXT,FILL1
DDROP,EXIT
( b u -- b u )
Adjust the count to eliminate trailing white space.
$COLON
DW
DW
DW
DW
DW
DW
DW
9,'-TRAILING',DTRAI
TOR
BRAN,DTRA2
BLANK,OVER,RAT,PLUS,CAT,LESS
QBRAN,DTRA2
RFROM,ONEP,EXIT
;adjusted count
DONXT,DTRA1
DOLIT,0,EXIT
;count=0
( b u a -- a )
Build a counted string with u characters from b. Null fill.
$COLON
DW
DW
DW
DW
DW
DW
DW
5,'PACK$',PACKS
DUPP,TOR
;strings only on cell boundary
OVER,DUPP,DOLIT,0
DOLIT,CELLL,UMMOD,DROP ;count mod cell
SUBB,OVER,PLUS
DOLIT,0,SWAP,STORE
;null fill cell
DDUP,CSTOR,ONEP
;save count
SWAP,CMOVE,RFROM,EXIT
;move string
;; Numeric output, single precision
;
;
DIGIT
( u -- c )
Convert digit u to a character.
$COLON
DW
DW
DW
;
;
EXTRACT
( n base -- n c )
Extract the least significant digit from n.
$COLON
DW
DW
;
;
<#
HOLD
7,'EXTRACT',EXTRC
DOLIT,0,SWAP,UMMOD
SWAP,DIGIT,EXIT
( -- )
Initiate the numeric output process.
$COLON
DW
;
;
5,'DIGIT',DIGIT
DOLIT,9,OVER,LESS
DOLIT,7,ANDD,PLUS
DOLIT,'0',PLUS,EXIT
2,'<#',BDIGS
PAD,HLD,STORE,EXIT
( c -- )
Insert a character into the numeric output string.
$COLON
4,'HOLD',HOLD
106
DW
DW
;
;
#
( u -- u )
Extract one digit from u and append the digit to output string.
$COLON
DW
;
;
#S
HLD,AT,ONEM
DUPP,HLD,STORE,CSTOR,EXIT
1,'#',DIG
BASE,AT,EXTRC,HOLD,EXIT
( u -- 0 )
Convert u until all digits are added to the output string.
DIGS2:
$COLON
DW
DW
DW
DW
;
;
( n -- )
Add a minus sign to the numeric output string.
DIGS1:
SIGN
2,'#S',DIGS
DIG,DUPP
QBRAN,DIGS2
BRAN,DIGS1
EXIT
SIGN1:
$COLON
DW
DW
DW
DW
;
;
( w -- b u )
Prepare the output string to be TYPE'd.
#>
$COLON
DW
DW
;
;
str
HEX
DECIMAL
3,'str',STR
DUPP,TOR,ABSS
BDIGS,DIGS,RFROM
SIGN,EDIGS,EXIT
( -- )
Use radix 16 as base for numeric conversions.
$COLON
DW
;
;
2,'#>',EDIGS
DROP,HLD,AT
PAD,OVER,SUBB,EXIT
( n -- b u )
Convert a signed integer to a numeric string.
$COLON
DW
DW
DW
;
;
4,'SIGN',SIGN
ZLESS
QBRAN,SIGN1
DOLIT,'-',HOLD
EXIT
3,'HEX',HEX
DOLIT,16,BASE,STORE,EXIT
( -- )
Use radix 10 as base for numeric conversions.
$COLON
DW
7,'DECIMAL',DECIM
DOLIT,10,BASE,STORE,EXIT
;; Numeric input, single precision
;
DIGIT?
( c base -- u t )
107
;
success.
Convert a character to its numeric value. A flag indicates
DGTQ1:
$COLON
DW
DW
DW
DW
DW
DW
;
;
( a -- n T | a F )
Convert a number string to integer. Push a flag on tos.
NUMBER?
NUMQ1:
NUMQ2:
NUMQ3:
NUMQ4:
NUMQ5:
NUMQ6:
$COLON
DW
DW
DW
DW
DW
DW
DW
DW
DW
DW
DW
DW
DW
DW
DW
DW
DW
DW
DW
DW
DW
DW
DW
6,'DIGIT?',DIGTQ
TOR,DOLIT,'0',SUBB
DOLIT,9,OVER,LESS
QBRAN,DGTQ1
DOLIT,7,SUBB
DUPP,DOLIT,10,LESS,ORR
DUPP,RFROM,ULESS,EXIT
7,'NUMBER?',NUMBQ
BASE,AT,TOR,DOLIT,0,OVER,COUNT
OVER,CAT,DOLIT,'$',EQUAL
QBRAN,NUMQ1
HEX,SWAP,ONEP
SWAP,ONEM
OVER,CAT,DOLIT,'-',EQUAL,TOR
SWAP,RAT,SUBB,SWAP,RAT,PLUS,QDUP
QBRAN,NUMQ6
ONEM,TOR
DUPP,TOR,CAT,BASE,AT,DIGTQ
QBRAN,NUMQ4
SWAP,BASE,AT,STAR,PLUS,RFROM
ONEP
DONXT,NUMQ2
RAT,SWAP,DROP
QBRAN,NUMQ3
NEGAT
SWAP
BRAN,NUMQ5
RFROM,RFROM,DDROP,DDROP,DOLIT,0
DUPP
RFROM,DDROP
RFROM,BASE,STORE,EXIT
;; Basic I/O
;
;
?KEY
( -- c T | F )
Return input character and true, or a false if no input.
$COLON
DW
;
;
KEY
KEY1:
;
;
EMIT
4,'?KEY',QKEY
TQKEY,ATEXE,EXIT
( -- c )
Wait for and return an input character.
$COLON
DW
DW
DW
3,'KEY',KEY
QKEY
QBRAN,KEY1
EXIT
( c -- )
Send a character to the output device.
108
$COLON
DW
;
;
NUF?
4,'EMIT',EMIT
TEMIT,ATEXE,EXIT
( -- t )
Return false if no input, else pause and if CR return true.
NUFQ1:
$COLON
DW
DW
DW
DW
;
;
( -- )
Send a pace character for the file downloading process.
PACE
$COLON
DW
;
;
SPACE
SPACES
CHAR1:
CHAR2:
;
;
TYPE
TYPE1:
TYPE2:
;
;
CR
do$
5,'SPACE',SPACE
BLANK,EMIT,EXIT
( +n -- )
Send n spaces to the output device.
$COLON
DW
DW
DW
DW
DW
6,'SPACES',SPACS
DOLIT,0,MAX,TOR
BRAN,CHAR2
SPACE
DONXT,CHAR1
EXIT
( b u -- )
Output u characters from b.
$COLON
DW
DW
DW
DW
DW
DW
4,'TYPE',TYPEE
TOR
BRAN,TYPE2
DUPP,CAT,EMIT
ONEP
DONXT,TYPE1
DROP,EXIT
( -- )
Output a carriage return and a line feed.
$COLON
DW
DW
;
;
4,'PACE',PACE
DOLIT,11,EMIT,EXIT
( -- )
Send the blank character to the output device.
$COLON
DW
;
;
4,'NUF?',NUFQ
QKEY,DUPP
QBRAN,NUFQ1
DDROP,KEY,DOLIT,CRR,EQUAL
EXIT
2,'CR',CR
DOLIT,CRR,EMIT
DOLIT,LF,EMIT,EXIT
( -- a )
Return the address of a compiled string.
$COLON
DW
DW
COMPO+3,'do$',DOSTR
RFROM,RAT,RFROM,COUNT,PLUS
TOR,SWAP,TOR,EXIT
109
;
$"|
;
string.
( -- a )
Run time routine compiled by $". Return address of a compiled
$COLON
DW
;
;
."|
.R
U.R
U.
.
3,'U.R',UDOTR
TOR,BDIGS,DIGS,EDIGS
RFROM,OVER,SUBB
SPACS,TYPEE,EXIT
( u -- )
Display an unsigned integer in free format.
$COLON
DW
DW
;
;
2,'.R',DOTR
TOR,STR,RFROM,OVER,SUBB
SPACS,TYPEE,EXIT
( u +n -- )
Display an unsigned integer in n column, right justified.
$COLON
DW
DW
DW
;
;
COMPO+3,'."|',DOTQP
DOSTR,COUNT,TYPEE,EXIT
( n +n -- )
Display an integer in a field of n columns, right justified.
$COLON
DW
DW
;
;
;force a call to do$
( -- )
Run time routine of ." . Output a compiled string.
$COLON
DW
;
;
COMPO+3,'$"|',STRQP
DOSTR,EXIT
2,'U.',UDOT
BDIGS,DIGS,EDIGS
SPACE,TYPEE,EXIT
( w -- )
Display an integer in free format, preceeded by a space.
DOT1:
$COLON
DW
DW
DW
DW
;
;
( a -- )
Display the contents in a memory cell.
?
$COLON
DW
1,'.',DOT
BASE,AT,DOLIT,10,XORR
QBRAN,DOT1
UDOT,EXIT
STR,SPACE,TYPEE,EXIT
;?decimal
;no, display unsigned
;yes, display signed
1,'?',QUEST
AT,DOT,EXIT
;; Parsing
;
;
parse
( b u c -- b u delta ; <string> )
Scan string delimited by c. Return found string and its offset.
$COLON
DW
5,'parse',PARS
TEMP,STORE,OVER,TOR,DUPP
110
PARS8:
DW
DW
DW
DW
DW
DW
DW
DW
DW
DW
DW
DW
DW
DW
DW
DW
DW
DW
DW
DW
DW
DW
DW
DW
DW
DW
DW
;
;
( c -- b u ; <string> )
Scan input stream and return counted string delimited by c.
PARS1:
PARS2:
PARS3:
PARS4:
PARS5:
PARS6:
PARS7:
PARSE
$COLON
DW
DW
DW
;
;
.(
(
\
CHAR
IMEDD+1,'(',PAREN
DOLIT,')',PARSE,DDROP,EXIT
( -- )
Ignore following text till the end of line.
$COLON
DW
;
;
IMEDD+2,'.(',DOTPR
DOLIT,')',PARSE,TYPEE,EXIT
( -- )
Ignore following string up to next ) . A comment.
$COLON
DW
;
;
5,'PARSE',PARSE
TOR,TIB,INN,AT,PLUS
;current input buffer pointer
NTIB,AT,INN,AT,SUBB
;remaining count
RFROM,PARS,INN,PSTOR,EXIT
( -- )
Output following string up to next ) .
$COLON
DW
;
;
QBRAN,PARS8
ONEM,TEMP,AT,BLANK,EQUAL
QBRAN,PARS3
TOR
BLANK,OVER,CAT
;skip leading blanks ONLY
SUBB,ZLESS,INVER
QBRAN,PARS2
ONEP
DONXT,PARS1
RFROM,DROP,DOLIT,0,DUPP,EXIT
RFROM
OVER,SWAP
TOR
TEMP,AT,OVER,CAT,SUBB
;scan for delimiter
TEMP,AT,BLANK,EQUAL
QBRAN,PARS5
ZLESS
QBRAN,PARS6
ONEP
DONXT,PARS4
DUPP,TOR
BRAN,PARS7
RFROM,DROP,DUPP
ONEP,TOR
OVER,SUBB
RFROM,RFROM,SUBB,EXIT
OVER,RFROM,SUBB,EXIT
IMEDD+1,'\',BKSLA
NTIB,AT,INN,STORE,EXIT
( -- c )
Parse next word and return its first character.
$COLON
4,'CHAR',CHAR
111
DW
;
;
TOKEN
( -- a ; <string> )
Parse a word from input stream and copy it to name dictionary.
$COLON
DW
DW
DW
;
;
WORD
BLANK,PARSE,DROP,CAT,EXIT
5,'TOKEN',TOKEN
BLANK,PARSE,DOLIT,31,MIN
NP,AT,OVER,SUBB,TWOM
PACKS,EXIT
( c -- a ; <string> )
Parse a word from input stream and copy it to code dictionary.
$COLON
DW
4,'WORD',WORDD
PARSE,HERE,PACKS,EXIT
;; Dictionary search
;
;
NAME>
( na -- ca )
Return a code address given a name address.
$COLON
DW
;
;
SAME?
SAME1:
SAME2:
;
;
find
FIND1:
FIND2:
FIND3:
FIND6:
FIND4:
5,'NAME>',NAMET
TWOM,TWOM,AT,EXIT
( a a u -- a a f \ -0+ )
Compare u cells in two strings. Return 0 if identical.
$COLON
DW
DW
DW
DW
DW
DW
DW
DW
DW
5,'SAME?',SAMEQ
TOR
BRAN,SAME2
OVER,RAT,TWOSL,PLUS,AT
OVER,RAT,TWOSL,PLUS,AT
SUBB,QDUP
QBRAN,SAME2
RFROM,DROP,EXIT
DONXT,SAME1
DOLIT,0,EXIT
;strings not equal
;strings equal
( a va -- ca na | a F )
Search a vocabulary for a string. Return ca and na if succeeded.
$COLON
DW
DW
DW
DW
DW
DW
DW
DW
DW
DW
DW
DW
DW
DW
DW
DW
4,'find',FIND
SWAP,DUPP,CAT
DOLIT,CELLL,SLASH,TEMP,STORE
DUPP,AT,TOR,TWOP,SWAP
AT,DUPP
QBRAN,FIND6
DUPP,AT,DOLIT,MASKK,ANDD,RAT,XORR
QBRAN,FIND2
TWOP,DOLIT,-1
;true flag
BRAN,FIND3
TWOP,TEMP,AT,SAMEQ
BRAN,FIND4
RFROM,DROP
SWAP,TWOM,SWAP,EXIT
QBRAN,FIND5
TWOM,TWOM
BRAN,FIND1
112
FIND5:
DW
DW
DW
;
;
( a -- ca na | a F )
Search all context vocabularies for a string.
NAME?
NAMQ1:
NAMQ2:
NAMQ3:
$COLON
DW
DW
DW
DW
DW
DW
DW
DW
DW
DW
DW
DW
RFROM,DROP,SWAP,DROP
TWOM
DUPP,NAMET,SWAP,EXIT
5,'NAME?',NAMEQ
CNTXT,DUPP,DAT,XORR
QBRAN,NAMQ1
TWOM
TOR
RFROM,TWOP,DUPP,TOR
AT,QDUP
QBRAN,NAMQ3
FIND,QDUP
QBRAN,NAMQ2
RFROM,DROP,EXIT
RFROM,DROP
DOLIT,0,EXIT
;?context=also
;no, start with context
;next in search order
;search vocabulary
;found name
;name not found
;false flag
;; Terminal response
;
;
^H
( bot eot cur -- bot eot cur )
Backup the cursor by one character.
BACK1:
$COLON
DW
DW
DW
DW
DW
DW
;
;
( bot eot cur c -- bot eot cur )
Accept and echo the key stroke and bump the cursor.
TAP
$COLON
DW
DW
;
;
kTAP
2,'^H',BKSP
TOR,OVER,RFROM,SWAP,OVER,XORR
QBRAN,BACK1
DOLIT,BKSPP,TECHO,ATEXE,ONEM
BLANK,TECHO,ATEXE
DOLIT,BKSPP,TECHO,ATEXE
EXIT
3,'TAP',TAP
DUPP,TECHO,ATEXE
OVER,CSTOR,ONEP,EXIT
( bot eot cur c -- bot eot cur )
Process a key stroke, CR or backspace.
KTAP1:
KTAP2:
$COLON
DW
DW
DW
DW
DW
DW
DW
;
;
( b u -- b u )
Accept characters to input buffer. Return with actual count.
accept
$COLON
DW
4,'kTAP',KTAP
DUPP,DOLIT,CRR,XORR
QBRAN,KTAP2
DOLIT,BKSPP,XORR
QBRAN,KTAP1
BLANK,TAP,EXIT
BKSP,EXIT
DROP,SWAP,DROP,DUPP,EXIT
6,'accept',ACCEP
OVER,PLUS,OVER
113
ACCP1:
ACCP2:
ACCP3:
ACCP4:
DW
DW
DW
DW
DW
DW
DW
DW
DW
DW
DW
;
;
( b u -- )
Accept input stream and store count in SPAN.
;
EXPECT
$COLON
DW
;
;
QUERY
DDUP,XORR
QBRAN,ACCP4
KEY,DUPP
BLANK,SUBB,DOLIT,95,ULESS
BLANK,DOLIT,127,WITHI
QBRAN,ACCP2
TAP
BRAN,ACCP3
TTAP,ATEXE
BRAN,ACCP1
DROP,OVER,SUBB,EXIT
6,'EXPECT',EXPEC
TEXPE,ATEXE,SPAN,STORE,DROP,EXIT
( -- )
Accept input stream to terminal input buffer.
$COLON
DW
DW
5,'QUERY',QUERY
TIB,DOLIT,80,TEXPE,ATEXE,NTIB,STORE
DROP,DOLIT,0,INN,STORE,EXIT
;; Error handling
;
;
CATCH
( ca -- 0 | err# )
Execute word at ca and set up an error frame for it.
$COLON
DW
DW
DW
DW
;
;
THROW
NULL$
ABORT
5,'THROW',THROW
HANDL,AT,RPSTO
RFROM,HANDL,STORE
RFROM,SWAP,TOR,SPSTO
DROP,RFROM,EXIT
;restore return stack
;restore handler frame
;restore data stack
( -- a )
Return address of a null string with zero count.
$COLON
DW
DW
DB
;
;
;save error frame
;execute
;restore error frame
;no error
( err# -- err# )
Reset system to current local error frame an update error flag.
$COLON
DW
DW
DW
DW
;
;
5,'CATCH',CATCH
SPAT,TOR,HANDL,AT,TOR
RPAT,HANDL,STORE,EXECU
RFROM,HANDL,STORE
RFROM,DROP,DOLIT,0,EXIT
5,'NULL$',NULLS
DOVAR
0
99,111,121,111,116,101
;emulate CREATE
( -- )
Reset data stack and jump to QUIT.
$COLON
DW
5,'ABORT',ABORT
NULLS,THROW
114
;
;
abort"
ABOR1:
( f -- )
Run time routine of ABORT" . Abort with a message.
$COLON
DW
DW
DW
COMPO+6,'abort"',ABORQ
QBRAN,ABOR1
DOSTR,THROW
DOSTR,DROP,EXIT
;text flag
;pass error string
;drop error
;; The text interpreter
;
;
$INTERPRET
( a -- )
Interpret a word. If failed, try to convert it to an integer.
INTE2:
$COLON
DW
DW
DW
D$
DW
DW
DW
DW
DW
;
;
( -- )
Start the text interpreter.
INTE1:
[
$COLON
DW
;
;
.OK
10,'$INTERPRET',INTER
NAMEQ,QDUP
QBRAN,INTE1
AT,DOLIT,COMPO,ANDD
ABORQ,' compile only'
EXECU,EXIT
TNUMB,ATEXE
QBRAN,INTE2
EXIT
THROW
;?defined
;?compile only lexicon bits
;execute defined word
;convert a number
;error
IMEDD+1,'[',LBRAC
DOLIT,INTER,TEVAL,STORE,EXIT
( -- )
Display 'ok' only while interpreting.
DOTO1:
$COLON
DW
DW
D$
DW
;
;
( -- )
Abort if the data stack underflows.
?STACK
$COLON
DW
D$
DW
;
;
EVAL
EVAL1:
EVAL2:
3,'.OK',DOTOK
DOLIT,INTER,TEVAL,AT,EQUAL
QBRAN,DOTO1
DOTQP,' ok'
CR,EXIT
6,'?STACK',QSTAC
DEPTH,ZLESS
ABORQ,' underflow'
EXIT
;check only for underflow
( -- )
Interpret the input stream.
$COLON
DW
DW
DW
DW
DW
4,'EVAL',EVAL
TOKEN,DUPP,CAT
QBRAN,EVAL2
TEVAL,ATEXE,QSTAC
BRAN,EVAL1
DROP,TPROM,ATEXE,EXIT
115
;?input stream empty
;evaluate input, check stack
;prompt
;; Shell
;
;
PRESET
( -- )
Reset data stack pointer and the terminal input buffer.
$COLON
DW
DW
;
;
xio
( a a a -- )
Reset the I/O vectors 'EXPECT, 'TAP, 'ECHO and 'PROMPT.
$COLON
DW
DW
;
;
FILE
HAND
I/O
CONSOLE
QUIT
QUIT1:
QUIT2:
3,'I/O',ISLO
DOVAR
QRX,TXSTO
;emulate CREATE
;default I/O vectors
( -- )
Initiate terminal interface.
$COLON
DW
DW
;
;
4,'HAND',HAND
DOLIT,DOTOK,DOLIT,EMIT
DOLIT,KTAP,XIO,EXIT
( -- a )
Array to store default I/O vectors.
$COLON
DW
DW
;
;
4,'FILE',FILE
DOLIT,PACE,DOLIT,DROP
DOLIT,KTAP,XIO,EXIT
( -- )
Select I/O vectors for terminal interface.
$COLON
DW
DW
;
;
COMPO+3,'xio',XIO
DOLIT,ACCEP,TEXPE,DSTOR
TECHO,DSTOR,EXIT
( -- )
Select I/O vectors for file download.
$COLON
DW
DW
;
;
6,'PRESET',PRESE
SZERO,AT,SPSTO
DOLIT,TIBB,NTIB,TWOP,STORE,EXIT
7,'CONSOLE',CONSO
ISLO,DAT,TQKEY,DSTOR
HAND,EXIT
;restore default I/O device
;keyboard input
( -- )
Reset return stack pointer and start text interpreter.
$COLON
DW
DW
DW
DW
DW
DW
DW
DW
DW
D$
4,'QUIT',QUIT
RZERO,AT,RPSTO
LBRAC
QUERY
DOLIT,EVAL,CATCH,QDUP
QBRAN,QUIT2
TPROM,AT,SWAP
CONSO,NULLS,OVER,XORR
QBRAN,QUIT3
SPACE,COUNT,TYPEE
DOTQP,' ? '
116
;reset return stack pointer
;start interpretation
;get input
;evaluate input
;continue till error
;save input device
;?display error message
;error message
;error prompt
QUIT3:
QUIT4:
DW
DW
DW
DW
DW
DOLIT,DOTOK,XORR
QBRAN,QUIT4
DOLIT,ERR,EMIT
PRESE
BRAN,QUIT1
;?file input
;file error, tell host
;some cleanup
;; The compiler
;
;
'
( -- ca )
Search context vocabularies for the next word in input stream.
TICK1:
$COLON
DW
DW
DW
DW
;
;
( n -- )
Allocate n bytes to the code dictionary.
ALLOT
$COLON
DW
;
;
,
C,
[COMPILE]
COMPILE
LITERAL
$,"
1,',',COMMA
HERE,DUPP,TWOP
CP,STORE,STORE,EXIT
;cell boundary
;adjust code pointer, compile
2,'C,',CCOMMA
HERE,DUPP,ONEP
CP,STORE,CSTOR,EXIT
IMEDD+9,'[COMPILE]',BCOMP
TICK,COMMA,EXIT
COMPO+7,'COMPILE',COMPI
RFROM,DUPP,AT,COMMA
;compile address
TWOP,TOR,EXIT
;adjust return address
( w -- )
Compile tos to code dictionary as an integer literal.
$COLON
DW
;
;
;adjust code pointer
( -- )
Compile the next address in colon list to code dictionary.
$COLON
DW
DW
;
;
5,'ALLOT',ALLOT
CP,PSTOR,EXIT
( -- ; <string> )
Compile the next immediate word into code dictionary.
$COLON
DW
;
;
;yes, push code address
;no, error
( b -- )
Compile a byte into the code dictionary
$COLON
DW
DW
;
;
;?defined
( w -- )
Compile an integer into the code dictionary.
$COLON
DW
DW
;
;
1,"'",TICK
TOKEN,NAMEQ
QBRAN,TICK1
EXIT
THROW
IMEDD+7,'LITERAL',LITER
COMPI,DOLIT,COMMA,EXIT
( -- )
Compile a literal string up to next " .
117
$COLON
DW
DW
DW
;
;
RECURSE
3,'$,"',STRCQ
DOLIT,'"',WORDD
COUNT,PLUS
CP,STORE,EXIT
;move string to code dictionary
;calculate aligned end of string
;adjust the code pointer
( -- )
Make the current word available for compilation.
$COLON
DW
IMEDD+7,'RECURSE',RECUR
LAST,AT,NAMET,COMMA,EXIT
;; Structures
;
;
FOR
( -- a )
Start a FOR-NEXT loop structure in a colon definition.
$COLON
DW
;
;
BEGIN
( -- a )
Start an infinite or indefinite loop structure.
$COLON
DW
;
;
NEXT
UNTIL
AGAIN
IF
AHEAD
REPEAT
IMEDD+2,'IF',IFF
COMPI,QBRAN,HERE
DOLIT,0,COMMA,EXIT
( -- A )
Compile a forward branch instruction.
$COLON
DW
;
IMEDD+5,'AGAIN',AGAIN
COMPI,BRAN,COMMA,EXIT
( -- A )
Begin a conditional branch structure.
$COLON
DW
DW
;
;
IMEDD+5,'UNTIL',UNTIL
COMPI,QBRAN,COMMA,EXIT
( a -- )
Terminate a BEGIN-AGAIN infinite loop structure.
$COLON
DW
;
;
IMEDD+4,'NEXT',NEXT
COMPI,DONXT,COMMA,EXIT
( a -- )
Terminate a BEGIN-UNTIL indefinite loop structure.
$COLON
DW
;
;
IMEDD+5,'BEGIN',BEGIN
HERE,EXIT
( a -- )
Terminate a FOR-NEXT loop structure.
$COLON
DW
;
;
IMEDD+3,'FOR',FOR
COMPI,TOR,HERE,EXIT
IMEDD+5,'AHEAD',AHEAD
COMPI,BRAN,HERE,DOLIT,0,COMMA,EXIT
( A a -- )
118
;
Terminate a BEGIN-WHILE-REPEAT indefinite loop.
$COLON
DW
;
;
THEN
( A -- )
Terminate a conditional branch structure.
$COLON
DW
;
;
AFT
ELSE
WHILE
ABORT"
$"
."
IMEDD+6,'ABORT"',ABRTQ
COMPI,ABORQ,STRCQ,EXIT
( -- ; <string> )
Compile an inline string literal.
$COLON
DW
;
;
IMEDD+5,'WHILE',WHILE
IFF,SWAP,EXIT
( -- ; <string> )
Conditional abort with an error message.
$COLON
DW
;
;
IMEDD+4,'ELSE',ELSEE
AHEAD,SWAP,THENN,EXIT
( a -- A a )
Conditional branch out of a BEGIN-WHILE-REPEAT loop.
$COLON
DW
;
;
IMEDD+3,'AFT',AFT
DROP,AHEAD,BEGIN,SWAP,EXIT
( A -- A )
Start the false clause in an IF-ELSE-THEN structure.
$COLON
DW
;
;
IMEDD+4,'THEN',THENN
HERE,SWAP,STORE,EXIT
( a -- a A )
Jump to THEN in a FOR-AFT-THEN-NEXT loop the first time through.
$COLON
DW
;
;
IMEDD+6,'REPEAT',REPEA
AGAIN,HERE,SWAP,STORE,EXIT
IMEDD+2,'$"',STRQ
COMPI,STRQP,STRCQ,EXIT
( -- ; <string> )
Compile an inline string literal to be typed out at run time.
$COLON
DW
IMEDD+2,'."',DOTQ
COMPI,DOTQP,STRCQ,EXIT
;; Name compiler
;
;
?UNIQUE
UNIQ1:
( a -- a )
Display a warning message if the word already exists.
$COLON
DW
DW
D$
DW
DW
7,'?UNIQUE',UNIQU
DUPP,NAMEQ
QBRAN,UNIQ1
DOTQP,' reDef '
OVER,COUNT,TYPEE
DROP,EXIT
119
;?name exists
;redefinitions are OK
;but warn the user
;just in case its not planned
;
;
$,n
PNAM1:
( na -- )
Build a new dictionary name using the string at na.
$COLON
DW
DW
DW
DW
DW
DW
DW
DW
DW
D$
DW
3,'$,n',SNAME
DUPP,CAT
;?null input
QBRAN,PNAM1
UNIQU
;?redefinition
DUPP,LAST,STORE
;save na for vocabulary link
HERE,SWAP
;align code address
TWOM
;link address
CRRNT,AT,AT,OVER,STORE
TWOM,DUPP,NP,STORE
;adjust name pointer
STORE,EXIT
;save code pointer
STRQP,' name'
;null input
THROW
;; FORTH compiler
;
;
$COMPILE
( a -- )
Compile next word to code dictionary as a token or literal.
SCOM3:
$COLON
DW
DW
DW
DW
DW
DW
DW
DW
DW
DW
;
;
( a -- )
Compile next byte to code dictionary as machine code.
SCOM1:
SCOM2:
CCOMPILE
8,'$COMPILE',SCOMP
NAMEQ,QDUP
QBRAN,SCOM2
AT,DOLIT,IMEDD,ANDD
QBRAN,SCOM1
EXECU,EXIT
COMMA,EXIT
TNUMB,ATEXE
QBRAN,SCOM3
LITER,EXIT
THROW
;?immediate
;its immediate, execute
;its not immediate, compile
;try to convert to number
;compile number as integer
;error
CCOM3:
$COLON
DW
DW
DW
DW
DW
DW
DW
DW
DW
DW
;
;
( -- )
Link a new word into the current vocabulary.
CCOM1:
CCOM2:
OVERT
$COLON
DW
;
;
;
8,'CCOMPILE',CCOMP
NAMEQ,QDUP
QBRAN,CCOM2
AT,DOLIT,IMEDD,ANDD
QBRAN,CCOM1
EXECU,EXIT
DROP,EXIT
TNUMB,ATEXE
QBRAN,CCOM3
CCOMMA,EXIT
THROW
;?defined
;?defined
;?immediate
;its immediate, execute
;its not immediate,drop
;try to convert to number
;compile as code byte
;error
5,'OVERT',OVERT
LAST,AT,CRRNT,AT,STORE,EXIT
( -- )
Terminate a colon definition.
120
$COLON
DW
;
;
]
( -- )
Start compiling the words in the input stream.
$COLON
DW
;
;
call,
:
IMMEDIATE
5,'call,',CALLC
DOLIT,CALLL,CCOMMA,EXIT
;Direct Threaded Code
( -- ; <string> )
Start a new colon definition using next word as its name.
$COLON
DW
DW
;
;
1,']',RBRAC
DOLIT,SCOMP,TEVAL,STORE,EXIT
( ca -- )
Assemble a call instruction to doLST.
$COLON
DW
;
;
IMEDD+COMPO+1,';',SEMIS
COMPI,EXIT,LBRAC,OVERT,EXIT
1,':',COLON
TOKEN,SNAME
CALLC,RBRAC,EXIT
( -- )
Make the last compiled word an immediate word.
$COLON
DW
DW
9,'IMMEDIATE',IMMED
DOLIT,IMEDD,LAST,AT,AT,ORR
LAST,AT,STORE,EXIT
;; Defining words
;
;
USER
( u -- ; <string> )
Compile a new user variable.
$COLON
DW
DW
;
;
CREATE
( -- ; <string> )
Compile a new array entry without allocating code space.
$COLON
DW
DW
;
;
VARIABLE
CODE
6,'CREATE',CREAT
TOKEN,SNAME,OVERT,CALLC
COMPI,DOVAR,EXIT
( -- ; <string> )
Compile a new variable initialized to 0.
$COLON
DW
;
;
4,'USER',USER
TOKEN,SNAME,OVERT,CALLC
COMPI,DOUSE,COMMA,EXIT
8,'VARIABLE',VARIA
CREAT,DOLIT,0,COMMA,EXIT
( -- )
Start a new code definition using next word as its name.
$COLON
DW
DW
4,'CODE',CODE
TOKEN,SNAME
DOLIT,CCOMP,TEVAL,STORE,EXIT
121
;
;
ENDCODE
( -- )
Terminate a code definition
$COLON
DW
DW
DW
IMEDD+COMPO+7,'ENDCODE',ENDCD
DOLIT,48H,CCOMMA,DOLIT,84H,CCOMMA
DOLIT,48H,CCOMMA,DOLIT,28H,CCOMMA
LBRAC,OVERT,EXIT
;$NEXT
;; Tools
;
;
_TYPE
UTYP1:
UTYP2:
;
;
dm+
PDUM1:
PDUM2:
;
;
DUMP
DUMP1:
DUMP2:
DUMP3:
;
;
.S
( b u -- )
Display a string. Filter non-printing characters.
$COLON
DW
DW
DW
DW
DW
DW
5,'_TYPE',UTYPE
TOR
BRAN,UTYP2
DUPP,CAT,TCHAR,EMIT
ONEP
DONXT,UTYP1
DROP,EXIT
;start count down loop
;skip first pass
;display only printable
;increment address
;loop till done
( a u -- a )
Dump u bytes from , leaving a+u on the stack.
$COLON
DW
DW
DW
DW
DW
DW
DW
3,'dm+',DMP
OVER,DOLIT,4,UDOTR
SPACE,TOR
BRAN,PDUM2
DUPP,CAT,DOLIT,3,UDOTR
ONEP
DONXT,PDUM1
EXIT
;display address
;start count down loop
;skip first pass
;display numeric data
;increment address
;loop till done
( a u -- )
Dump u bytes from a, in a formatted manner.
$COLON
DW
DW
DW
DW
DW
DW
DW
DW
DW
DW
DW
DW
DW
4,'DUMP',DUMP
BASE,AT,TOR,HEX
DOLIT,16,SLASH
TOR
CR,DOLIT,16,DDUP,DMP
ROT,ROT
SPACE,SPACE,UTYPE
NUFQ,INVER
QBRAN,DUMP2
DONXT,DUMP1
BRAN,DUMP3
RFROM,DROP
DROP,RFROM,BASE,STORE
EXIT
;save radix, set hex
;change count to lines
;start count down loop
;display numeric
;display printable characters
;user control
;loop till done
;cleanup loop stack, early exit
;restore radix
( ... -- ... )
Display the contents of the data stack.
$COLON
DW
DW
DW
2,'.S',DOTS
CR,DEPTH
TOR
BRAN,DOTS2
122
;stack depth
;start count down loop
;skip first pass
DOTS1:
DOTS2:
DW
DW
D$
DW
;
;
( -- )
Save stack pointer in CSP for error checking.
!CSP
$COLON
DW
;
;
?CSP
>NAME
4,'!CSP',STCSP
SPAT,CSP,STORE,EXIT
4,'?CSP',QCSP
SPAT,CSP,AT,XORR
ABORQ,'stacks'
EXIT
TNAM4:
;
;
( na -- )
Display the name at address.
TNAM2:
TNAM3:
.ID
DOTI1:
;
;
WORDS
WORS1:
;save pointer
;compare pointers
;abort if different
( ca -- na | F )
Convert code address to a name address.
$COLON
DW
DW
DW
DW
DW
DW
DW
DW
DW
DW
DW
DW
DW
DW
TNAM1:
;index stack, display contents
;loop till done
( -- )
Abort if stack pointer differs from that saved in CSP.
$COLON
DW
D$
DW
;
;
RAT,PICK,DOT
DONXT,DOTS1
DOTQP,' <sp'
EXIT
$COLON
DW
DW
DW
DW
D$
DW
5,'>NAME',TNAME
CRRNT
;vocabulary link
TWOP,AT,QDUP
;check all vocabularies
QBRAN,TNAM4
DDUP
AT,DUPP
;?last word in a vocabulary
QBRAN,TNAM3
DDUP,NAMET,XORR
;compare
QBRAN,TNAM3
TWOM
;continue with next word
BRAN,TNAM2
SWAP,DROP,QDUP
QBRAN,TNAM1
SWAP,DROP,SWAP,DROP,EXIT
DROP,DOLIT,0,EXIT
;false flag
3,'.ID',DOTID
QDUP
QBRAN,DOTI1
COUNT,DOLIT,01FH,ANDD
UTYPE,EXIT
DOTQP,' {noName}'
EXIT
;if zero no name
;mask lexicon bits
;display name string
( -- )
Display the names in the context vocabulary.
$COLON
DW
DW
DW
DW
DW
5,'WORDS',WORDS
CR,CNTXT,AT
AT,QDUP
QBRAN,WORS2
DUPP,SPACE,DOTID
TWOM,NUFQ
123
;only in context
;?at end of list
;display a name
;user control
WORS2:
DW
DW
DW
QBRAN,WORS1
DROP
EXIT
;; Hardware reset
;
;
VER
( -- n )
Return the version number of this implementation.
$COLON
DW
;
;
hi
( -- )
Display the sign-on message of eForth.
$COLON
DW
D$
DW
DW
DW
DW
DW
;
;
'BOOT
SEE
SEE1:
SEE2:
SEE3:
SEE4:
;
;
ADCINIT
2,'hi',HI
STOIO,CR
DOTQP,'eForth v'
BASE,AT,HEX
VERSN,BDIGS,DIG,DIG
DOLIT,'.',HOLD
DIGS,EDIGS,TYPEE
BASE,STORE,CR,EXIT
;initialize I/O
( -- a )
The application startup vector.
$COLON
DW
DW
;
;
3,'VER',VERSN
DOLIT,VER*256+EXT,EXIT
5,"'BOOT",TBOOT
DOVAR
HI
;application to boot
( --word-- )
Decompiles word.
$COLON 3,'SEE',SEE
DW
TICK
DW
CR,ONEP
DW
DUPP,DUPP,SPACE,DOT,DOLIT,07CH,EMIT,AT,DUPP
DW
QBRAN,SEE2
DW
TNAME
DW
QDUP
DW
QBRAN,SEE3
DW
DOTID
DW
BRAN,SEE4
DW
DUPP,AT,UDOT
DW
TWOP,NUFQ
DW
QBRAN,SEE1
DW
DROP,EXIT
( -- )
Init routine for starting ADC Interrupts
$CODE 7,'ADCINIT',ADCIN
DB 64H,4EH,1
;MKH AND 1, skip if not zero
DB 0D1H
;JUMP TO $NEXT
DB 64H,0AH,1FH
;PC<PC AND 1F
DB 68H,0FFH
;V<FF
DB 69H,0
;A<0
DB 63H,0F3H
;(V/F3)<A
124
DB 4DH,0C8H
DB 48H,48H
DB 00
DB 64H,0EH,0FEH
$NEXT
;
;
;
;
;
;
;
;
ADCOFF
TM
DELAY
LCD
;ANM <A
;SKIT FAD, reset INTFAD
;NOP
;ENABLE INTAD
( --- )
Disable ADC Interrupts.
$CODE
6,'ADCOFF',ADCOF
DB 64H,1EH,1
;;MKH < MKH OR 1
$NEXT
( n -- )
Wait for last transmit,
$CODE 2,'TM',TM
DB 0A1H
DB 0BH
DB 48H,4AH
DB 0FDH
DB 4DH,0D8H
$NEXT
( n -- )
Wait for n loops.
$CODE 5,'DELAY',DELAY
DB 0A1H
DB 53H
DB 0FEH
DB 52H
DB 0FCH
$NEXT
then send midi byte n.
;POP BC
;A<C
;SKIT FST, skip if interrupt
;JMP TO SKIT
;MOV TXB,A
;POP BC
;C<C-1, Skip if borrow
;JMP
;B<B-1, Skip if borrow
;JMP
( n -- )
Load control n to LCD display.
$CODE 3,'LCD',LCD
DB 0A1H
;POP BC
DB 0BH
;A<C
DB 14H,0,0A0H
;BC<A000
DB 39H
;(BC)<A
$NEXT
;
;
LLI
( --- )
Sets RS=0 for LCD setup commands.
$CODE 3,'LLI',LLI
DB 64H,0AH,0EFH
;Pc<Pc AND EF
$NEXT
;
;
LLC
( --- )
Sets RS=1 for LCD character loading
$CODE 3,'LLC',LLC
DB 64H,1AH,10H
;Pc<Pc OR 10
$NEXT
;
;
LI
( n --- )
load LCD setup instruction n, exit ready for char loads
$COLON 2,'LI',LI
DW
LLI,LCD,LLC,DOLIT,01FFH,DELAY,EXIT
125
;
;
LCDINIT
( -- )
Initialize LCD display.
$COLON 7,'LCDINIT',LCDIN
DW
DOLIT,0D7AH,DELAY
DW
DOLIT,038H,LI
DW
DOLIT,047EH,DELAY
DW
DOLIT,038H,LI
DW
DOLIT,017H,DELAY
DW
DOLIT,038H,LI
DW
DOLIT,017H,DELAY
DW
DOLIT,038H,LI
DW
DOLIT,017H,DELAY
DW
DOLIT,08H,LI
DW
DOLIT,017H,DELAY
DW
DOLIT,01H,LI
DW
DOLIT,01CCH,DELAY
DW
DOLIT,02H,LI
DW
DOLIT,01CCH,DELAY
DW
DOLIT,06H,LI
DW
DOLIT,17H,DELAY
DW
DOLIT,0EH,LI
DW
DOLIT,17H,DELAY
DW
EXIT
;
;
#DISP
( n,p --- )
Display n as a 3-digit number at LCD position p.
$COLON 5,'#DISP',NDISP
DW
DUPP,LI,SWAP
DW
BDIGS,DIG,DIG,DIG,EDIGS
DW
DROP,DUPP,CAT,LCD,ONEP
DW
DUPP,CAT,LCD,ONEP,CAT,LCD,LI,EXIT
;
;
#2DISP
( n,p --- )
Display n as a 3-digit number at LCD position p.
$COLON 6,'#2DISP',N2DISP
DW
DUPP,LI,SWAP
DW
BDIGS,DIG,DIG,EDIGS
DW
DROP,DUPP,CAT,LCD,ONEP
DW
CAT,LCD,LI,EXIT
;
;
DISP
( a,p --- )
Display packed string at a to LCD position p.
$COLON 4,'DISP',DISP
DW
LI,DUPP,CAT,ONEM,TOR
DW
ONEP
DW
DUPP,CAT,LCD
DW
DONXT,DISP1
DW
DROP,EXIT
DISP1:
;
;
CASE
( n --Execute
$COLON
DW
DW
)
one of a list of words pointed to by n.
4,'CASE',CASE
RFROM,SWAP,TWOSL,PLUS
ATEXE,EXIT
126
;
;
INCR
INCR1:
INCR2:
;
;
DECR
DECR1:
DECR2:
( n,nmax --- n+1 )
Increment n mod nmax.
$COLON 4,'INCR',INCR
DW
OVER,ONEP,LESS
DW
QBRAN,INCR1
DW
DROP,DOLIT,0
DW
BRAN,INCR2
DW
ONEP
DW
EXIT
( n,nmax --- n-1 )
Decrement n mod nmax.
$COLON 4,'DECR',DECR
DW
OVER,ONEM,ZLESS
DW
QBRAN,DECR1
DW
SWAP,DROP
DW
BRAN,DECR2
DW
DROP
DW
ONEM
DW
EXIT
;
;
SW@
( --- n )
Read Roland switches as a byte.
$CODE
3,'SW@',SWAT
DB
4CH,0C0H
;;A<PA
DB
6AH,0
;;B<0
DB
1BH
;;C<A
DB
0B1H
;;PUSH BC
$NEXT
;
;
S@
( --- n )
Return number of the lowest Roland switch on.
$CODE
2,'S@',SAT
DB
4CH,0C0H
;;A<PA
DB
6BH,0
;;C<0
DB
74H,11H,0FFH
;;A<A EXOR FF
DB
74H,49H,0FFH
;;A AND FF, SKIP IF NO ZERO
DB
0C4H
;; JMP OUT
DB
43H
;; C<C+1, LOOP1
DB
48H,1
;; A SHIFT RIGHT, SKIP IF CARRY
DB
0FCH
;; JMP LOOP1
DB
6AH,0
;;B<0, OUT
DB
0B1H
;;PUSH BC
$NEXT
;
;
LED!
( n --- )
Turn on/off Roland LED's.
$CODE
4,'LED!',LEDB
DB
0A1H
;;POP BC
DB
0BH
;;A<C
DB
74H,9H,0FCH
;;A<A AND FC
DB
74H,19H,1
;;A<A OR 1
DB
4DH,0C1H
;;PB<A
$NEXT
;
;
eUPDAT
( --- )
Move data from Slider Ram to Edit Buffer.
$CODE
6,'eUPDAT',EUPDAT
127
;
;
;
;
eLOAD
esUPDAT
DB
DB
DB
DB
DB
DB
68H,0FFH
6AH,2
1,0
1BH
29H
6AH,0C6H
;;V<FF
;;B<2
;;A<(V/00) Read eSLD#
;;C<A
;;A<(BC) Read Translation Table
;;B<C6
DB
DB
DB
DB
1BH
29H
48H,21H
63H,4
;;C<A
;;A<(BC)
;;A SHIFT RIGHT
;;(V/04)<A, eBYTE3
DB
DB
DB
DB
69H,80H
60H,43H
29H
63H,3H
;;A<80
;;C<C+A
;;A<(BC)
;;(V/03)<A, eBYTE2
DB
DB
DB
DB
$NEXT
69H,40H
60H,43H
29H
63H,2H
;;A<40
;;C<C+A
;;A<(BC)
;;(V/02)<A, eBYTE1
( --- )
Load Edit Buffer data into Slider Memory.
$CODE
5,'eLOAD',ELOAD
DB
68H,0FFH
;;V<FF
DB
6AH,2
;;B<2
DB
1,0
;;A<(V/00) Read eSLD#
DB
1BH
;;C<A
DB
29H
;;A<(BC) Read Translation Table
DB
6AH,0C6H
;;B<C6
DB
1BH
;;C<A
DB
DB
DB
69H,40H
60H,43H
49H,0
;;A<40
;;C<C+A
;;(BC)<0, LAST
DB
DB
DB
DB
69H,40H
60H,43H
1,3
39H
;;A<40
;;C<C+A
;;A<(V/03)
;;(BC)<A, eBYTE2
DB
DB
DB
DB
$NEXT
69H,40H
60H,43H
1,2
39H
;;A<40
;;C<C+A
;;A<(V/02)
;;(BC)<A, eBYTE1
( --- )
Update only the Slider data of the Edit Buffer.
$CODE
7,'esUPDAT',ESUPDAT
DB
68H,0FFH
;;V<FF
DB
6AH,2
;;B<2
DB
1,0
;;A<(V/00) Read eSLD#
DB
1BH
;;C<A
DB
29H
;;A<(BC) Read Translation Table
DB
6AH,0C6H
;;B<C6
128
DB
1BH
;;C<A
DB
DB
DB
$NEXT
29H
48H,21H
63H,4
;;A<(BC)
;;A SHIFT RIGHT
;;(V/04)<A
;
;
eSLD#
( --- FF00 )
Edit Buffer Slider number.
$COLON 5,'eSLD#',ESLDN
DW
DOLIT,0FF00H,EXIT
;
;
eFLD
( --- FF01 )
Edit Buffer LCD Field.
$COLON 4,'eFLD',EFLD
DW
DOLIT,0FF01H,EXIT
;
;
eBYTE1
( --- FF07 )
Edit Buffer Midi Status/Chnl byte.
$COLON 6,'eBYTE1',EBYT1
DW
DOLIT,0FF02H,EXIT
;
;
eBYTE2
( --- FF06 )
Edit Buffer Midi Key#, Controller#, or Program# byte.
$COLON 6,'eBYTE2',EBYT2
DW
DOLIT,0FF03H,EXIT
;
;
eBYTE3
( --- FF04 )
Edit Buffer Slider value.
$COLON 6,'eBYTE3',EBYT3
DW
DOLIT,0FF04H,EXIT
; eSET
;
( --- FF05 )
Flag indicating Slider or Setup operation.
$COLON 4,'eSET',ESET
DW
DOLIT,0FF05H,EXIT
; eSET#
;
( --- FF06 )
Holds Setup number.
$COLON 5,'eSET#',ESETN
DW
DOLIT,0FF06H,EXIT
;
;
FLD0
( --- 80 )
LCD Field start.
$COLON 4,'FLD0',FLD0
DW
DOLIT,080H,EXIT
;
;
FLD1
( --- 86 )
LCD Field start.
$COLON 4,'FLD1',FLD01
DW
DOLIT,086H,EXIT
;
;
FLD2
( --- 8A )
LCD Field start.
$COLON 4,'FLD2',FLD2
DW
DOLIT,088H,EXIT
;
FLD3
( --- 8D )
129
;
LCD Field start.
$COLON 4,'FLD3',FLD3
DW
DOLIT,08DH,EXIT
;
;
FLD4
( --- C0 )
LCD Field start.
$COLON 4,'FLD4',FLD4
DW
DOLIT,0C0H,EXIT
;
;
FLD5
( --- C9 )
LCD Field start.
$COLON 4,'FLD5',FLD5
DW
DOLIT,0C9H,EXIT
;
;
FLD6
( --- CD )
LCD Field start.
$COLON 4,'FLD6',FLD6
DW
DOLIT,0CDH,EXIT
;
;
L0
( --- a )
Packed string. 'a' is addr of count byte.
$COLON 2,'L0',L0
SD$ 'Slider'
;
;
L1
( --- a )
Packed string. 'a' is addr of count byte.
$COLON 2,'L1',L1
SD$ 'Setup#'
;
;
L2
( --- a )
Packed string. 'a' is addr of count byte.
$COLON 2,'L2',L2
SD$ '* MIDI Running *'
;
;
L20
( --- a )
Packed string. 'a' is addr of count byte.
$COLON 3,'L20',L20
SD$ ' chl '
;
;
L21
( --- a )
Packed string. 'a' is addr of count byte.
$COLON 3,'L21',L21
SD$ ' off '
;
;
L40
( --- a )
Packed string. 'a' is addr of count byte.
$COLON 3,'L40',L40
SD$ 'Key#
'
;
;
L41
( --- a )
Packed string. 'a' is addr of count byte.
$COLON 3,'L41',L41
SD$ 'Key# A-T'
;
;
L42
( --- a )
Packed string. 'a' is addr of count byte.
$COLON 3,'L42',L42
SD$ 'Control#'
130
;
;
L43
( --- a )
Packed string. 'a' is addr of count byte.
$COLON 3,'L43',L43
SD$ 'Program#'
;
;
L44
( --- a )
Packed string. 'a' is addr of count byte.
$COLON 3,'L44',L44
SD$ 'Ch Press'
;
;
L45
( --- a )
Packed string. 'a' is addr of count byte.
$COLON 3,'L45',L45
SD$ 'Ptch Whl'
;
;
L4X
( --- a )
Packed string. 'a' is addr of count byte.
$COLON 3,'L4X',L4X
SD$ '********'
;
;
L50
( --- a )
Packed string. 'a' is addr of count byte.
$COLON 3,'L50',L50
SD$ '***'
;
;
FLDCASE
( n -- f )
Choose an LCD field position.
$COLON 7,'FLDCASE',FLDCS
DW
DOLIT,7H,ANDD,CASE
DW
FLD0,FLD01,FLD2,FLD3,FLD4,FLD5,FLD6,FLD0
DW
EXIT
;
;
FLDAT
( --- )
Return LCD cursor to current field.
$COLON 5,'FLDAT',FLDAT
DW
EFLD,CAT,FLDCS,LI,EXIT
;
;
LSTAT
( n --- )
Choose a midi status label.
$COLON 5,'LSTAT',LSTAT
DW
CASE,L4X,L40,L41,L42,L43,L44,L45,L4X,EXIT
;
;
SLDISP
( --- )
Slider data update and display.
$COLON 6,'SLDISP',SLDISP
DW
ESUPDAT,EFLD,CAT,FLDCS
DW
EBYT3,CAT,DOLIT,07FH,ANDD
DW
BDIGS,DIG,DIG,DIG,EDIGS
DW
DROP,LLI,FLD6,LCD,LLC
DW
DUPP,CAT,LCD,ONEP,DUPP,CAT,LCD
DW
ONEP,CAT,LCD,LI,EXIT
;
;
eDISP
( --- )
Display the Edit buffer on the LCD
$COLON 5,'eDISP',EDISP
;
131
DW
DW
DW
DW
DW
DW
DW
DW
DW
DW
DW
DW
DW
DW
DW
DW
L0,FLD0,DISP,ESLDN,CAT,FLD01,N2DISP
EBYT1,CAT,DOLIT,80H,ANDD
QBRAN,EDISA
L20,FLD2,DISP
BRAN,EDISB
L21,FLD2,DISP
EBYT1,CAT,DUPP,DOLIT,0FH,ANDD,FLD3,NDISP
TWOSR,TWOSR,TWOSR,TWOSR,DOLIT,7H,ANDD
LSTAT,FLD4,DISP
DOLIT,0CFH,EBYT1,CAT,DOLIT,0F0H,ANDD,LESS
QBRAN,EDISC
L50,FLD5,DISP
BRAN,EDISD
EBYT2,CAT,FLD5,NDISP
SLDISP
FLDAT,EXIT
; SDISP
;
( --- )
Display
$COLON
DW
DW
DW
the Setup operation on the LCD.
5,'SDISP',SDISP
DOLIT,01,LI,BDEL
L1,FLD0,DISP
ESETN,CAT,FLD01,N2DISP,FLDAT,EXIT
; MNDISP
;
( --- )
Main display routine for updating LCD display.
$COLON 6,'MNDISP',MNDISP
DW
ESET,CAT
DW
QBRAN,MNDIS1
DW
SDISP,EXIT
DW
EDISP,EXIT
EDISA:
EDISB:
EDISC:
EDISD:
MNDIS1:
;
;
BDEL
;
;
UDCASE
;
;
BL/R
( --- )
Long delay at end of button routines.
$COLON 4,'BDEL',BDEL
DW
DOLIT,08000H,DELAY,EXIT
( n --- )
Choose an up/down routine from list.
$COLON 6,'UDCASE',UDCS
DW
EFLD,CAT,DOLIT,7H,ANDD,CASE
DW
UD0,UD1,UD2,UD3,UD4,UD5,UD6,UD7
DW
EXIT
( fld --- pos )
Translates LCD field number to a position number.
$COLON 4,'BL/R',BLR
DW
DUPP,EFLD,CSTOR,FLDCS
DW
EXIT
; SL/R
;
( --- )
Limit cursor movement only between fields 0 and 1.
$COLON 4,'SL/R',SLR
DW
EFLD,CAT,DOLIT,01,ANDD,DOLIT,01,XORR,DUPP
DW
EFLD,CSTOR,BLR,LI,BDEL,EXIT
;
;
( --- )
Moves the LCD cursor to next field. Loads eFLD.
BLEFT
132
BLEFT1:
;
;
BRIGHT
BRIGH1:
$COLON
DW
DW
DW
DW
DW
5,'BLEFT',BLEFT
DOLIT,40H,LEDB
ESET,CAT
QBRAN,BLEFT1
SLR,EXIT
EFLD,CAT,DOLIT,5,DECR,BLR,LI,BDEL,EXIT
( --- )
Moves the LCD cursor to next field. Loads eFLD.
$COLON 6,'BRIGHT',BRIGH
DW
DOLIT,80H,LEDB
DW
ESET,CAT
DW
QBRAN,BRIGH1
DW
SLR,EXIT
DW
EFLD,CAT,DOLIT,5,INCR,BLR,LI,BDEL,EXIT
; SETUP
;
( --- )
Setup Slider full Ram buffer from ROM, or MIDI in.
$COLON 5,'SETUP',SETUP
DW
ESETN,CAT,DOLIT,2000H,PLUS
DW
DOLIT,0C680H,DOLIT,80H,CMOVE
DW
EXIT
;
;
( --- )
Load Buffer data shown on LCD into Slider Memory.
$COLON 5,'BLOAD',BLOAD
DW
DOLIT,4,LEDB
DW
ESET,CAT
DW
QBRAN,BLOAD1
DW
SETUP,DOLIT,0,ESET,CSTOR,EUPDAT,EDISP,BDEL,EXIT
DW
ELOAD,EDISP,BDEL,EXIT
BLOAD
BLOAD1:
;
;
BMIDI
( --- )
Start the Midi program.
$COLON 5,'BMIDI',BMIDI
DW
DOLIT,1,LI,BDEL
DW
L2,FLD0,DISP
DW
MIDI,EXIT
;
;
BUP
( --- )
Increment value in LCD cursor field.
$COLON 3,'BUP',BUP
DW
DOLIT,10H,LEDB
DW
DOLIT,1,UDCS,BDEL,EXIT
;
;
BDOWN
( --- )
Decrement value in LCD cursor field.
$COLON 5,'BDOWN',BDOWN
DW
DOLIT,20H,LEDB
DW
DOLIT,0,UDCS,BDEL,EXIT
;
;
U/D0
( i/d --- )
Field increment/decrement routine.
$COLON 4,'U/D0',UD0
DW
DROP,ESET,CAT
DW
QBRAN,UD0A
133
UD0A:
DW
DW
DOLIT,0,ESET,CSTOR,EDISP,EXIT
DOLIT,0FFH,ESET,CSTOR,SDISP,EXIT
; U/D7
;
( i/d --- )
Field increment/decrement routine. (bogus field)
$COLON 4,'U/D7',UD7
DW
DROP,EXIT
;
;
U/D6
( i/d --- )
Field increment/decrement routine.
$COLON 4,'U/D6',UD6
DW
DROP,EXIT
;
;
U/D1
( i/d --- )
Field increment/decrement routine.
$COLON 4,'U/D1',UD1
DW
ESET,CAT
DW
QBRAN,UD1C
DW
ESETN
DW
BRAN,UD1D
DW
ESLDN
DW
CAT,DOLIT,3FH,ROT
DW
QBRAN,UD1A
DW
INCR
DW
BRAN,UD1B
DW
DECR
DW
CFLD1,EXIT
UD1C:
UD1D:
UD1A:
UD1B:
;
;
CFLD1
CFLA:
CFLB:
;
;
U/D2
UD2A:
UD2B:
;
;
U/D3
UD3A:
UD3B:
( sld# --- )
Change Slider# in field 1. Update Edit buffer & LCD.
$COLON 5,'CFLD1',CFLD1
DW
ESET,CAT
DW
QBRAN,CFLA
DW
ESETN,CSTOR,SDISP
DW
BRAN,CFLB
DW
ESLDN,CSTOR,EUPDAT,EDISP,FLDAT
DW
FLDAT,EXIT
( i/d --- )
Ch/Off Field increment/decrement routine.
$COLON 4,'U/D2',UD2
DW
QBRAN,UD2A
DW
EBYT1,CAT,DOLIT,80H,ORR
DW
EBYT1,CSTOR,L20,FLD2,DISP
DW
BRAN,UD2B
DW
EBYT1,CAT,DOLIT,7FH,ANDD
DW
EBYT1,CSTOR,L21,FLD2,DISP
DW
FLDAT,EXIT
( i/d --- )
Field increment/decrement routine.
$COLON 4,'U/D3',UD3
DW
EBYT1,CAT,DOLIT,0FH,ANDD,DOLIT,0FH,ROT
DW
QBRAN,UD3A
DW
INCR
DW
BRAN,UD3B
DW
DECR
DW
CFLD3,EXIT
134
;
;
CFLD3
( chnl --- )
Change midi channel in field 3.
$COLON 5,'CFLD3',CFLD3
DW
DUPP,EBYT1,CAT,DOLIT,0F0H
DW
ANDD,ORR,EBYT1,CSTOR,FLD3,NDISP,EXIT
;
;
U/D4
( i/d --- )
Field increment/decrement routine.
$COLON 4,'U/D4',UD4
DW
EBYT1,CAT,DOLIT,70H,ANDD
DW
TWOSR,TWOSR,TWOSR,TWOSR,DOLIT,7,ROT
DW
QBRAN,UD4A
DW
INCR
DW
BRAN,UD4B
DW
DECR
DW
DUPP,DOLIT,0,EQUAL,OVER,DOLIT,7H,EQUAL,ORR
DW
QBRAN,UD4C
DW
DROP,DOLIT,1
DW
CFLD4,EXIT
UD4A:
UD4B:
UD4C:
;
;
CFLD4
( status --- )
Change Midi operation label in field 4.
$COLON 5,'CFLD4',CFLD4
DW
DUPP,TWOSL,TWOSL,TWOSL,TWOSL
DW
DOLIT,80H,ORR,EBYT1,CAT
DW
DOLIT,0FH,ANDD,ORR,EBYT1,CSTOR
DW
LSTAT,FLD4,DISP,FLDAT,EXIT
;
;
U/D5
( i/d --- )
Field increment/decrement routine.
$COLON 4,'U/D5',UD5
DW
EBYT2,CAT,DOLIT,07FH,ROT
DW
QBRAN,UD5A
DW
INCR
DW
BRAN,UD5B
DW
DECR
DW
CFLD5,EXIT
UD5A:
UD5B:
;
;
CFLD5
UD5AA:
UD5BB:
( data --- )
Change Midi data byte in field 5.
$COLON 5,'CFLD5',CFLD5
DW
DOLIT,0CFH,EBYT1,CAT,DOLIT,0F0H,ANDD,LESS
DW
QBRAN,UD5AA
DW
L50,FLD5,DISP,FLD5,LI,DROP
DW
BRAN,UD5BB
DW
DUPP,EBYT2,CSTOR,FLD5,NDISP
DW
EXIT
;
;
BSUP
( --- )
Button 1. Increments Slider number.
$COLON 4,'BSUP',BSUP
DW
DOLIT,1,UD1,BDEL,EXIT
;
;
BSDWN
( --- )
Button 2. Decrements Slider Number.
$COLON 5,'BSDWN',BSDWN
DW
DOLIT,0,UD1,BDEL,EXIT
135
;
;
MNCASE
( --- )
Button case for Main.
$COLON 6,'MNCASE',MNCASE
DW
SAT,CASE
DW
DUMMY,BSDWN,BSUP,BLOAD,BMIDI,BUP,BDOWN,BLEFT,BRIGH
DW
EXIT
;
;
MLOOP
( --- stat)
Loop thru ADC values until an enabled one is found.
$CODE
5,'MLOOP',MLOOP
DB 68H,0FFH
;V<FF
DB 6AH,0C6H
;B<C6
DB 1,0E0H
;A<(V/E0), LOOPBACK
DB 41H
;A<A+1 skip if carry
DB 07H,3FH
;A<A AND 3F
DB 63H,0E0H
;(V/E0)<A
DB
DB
DB
DB
DB
46H,0C0H
1BH
29H
47H,80H
0F2H
;A<A+C0
;C<A
;A<(BC), midi byte1
;A AND 80, skip if no zero
;JMP LOOPBACK, if disabled
DB 7H,7FH
DB 48H,21H
DB 48H,21H
DB 48H,21H
DB 48H,21H
DB 1BH
DB 6AH,0
DB 0B1H
$NEXT
;
;
;
;
ADCV
SLAST
;A<A AND 7F
;A shift right
;A shift right
;A shift right
;A shift right
;C<A
;B<0
;PUSH BC, push status# on stack
( --- adc value)
Push stack with current
$CODE
4,'ADCV',ADCV
DB 1,0E0H
DB 1BH
DB 6AH,0C6H
DB 29H
DB 1BH
DB 6AH,0
DB 0B1H
$NEXT
( --- diff value)
Push stack with current
$CODE
5,'SLAST',SLAST
DB 1,0E0H
DB 46H,40H
DB 1BH
DB 6AH,0C6H
DB 29H
DB 1BH
DB 6AH,0
DB 0B1H
136
adc value for MIDI operation.
;A<(V/E0), Midi loop count.
;C<A
;B<C6
;A<(BC)
;C<A
;B<0
;PUSH BC
diff value for MIDI operation.
;A<(V/E0), Midi loop count.
;A<A+40
;C<A
;B<C6
;A<(BC)
;C<A
;B<0
;PUSH BC
$NEXT
;
;
;
;
;
;
BYT2
BYT1
FLAG
( --- byt2 value)
Push stack with current
$CODE
4,'BYT2',BYT2
DB 1,0E0H
DB 46H,80H
DB 1BH
DB 6AH,0C6H
DB 29H
DB 1BH
DB 6AH,0
DB 0B1H
$NEXT
( --- byt1 value)
Push stack with current
$CODE
4,'BYT1',BYT1
DB 1,0E0H
DB 46H,0C0H
DB 1BH
DB 6AH,0C6H
DB 29H
DB 1BH
DB 6AH,0
DB 0B1H
$NEXT
( --- flag value)
Push stack with current
$CODE
4,'FLAG',FLAG
DB 1,0E0H
DB 1BH
DB 6AH,0C7H
DB 29H
DB 1BH
DB 6AH,0
DB 0B1H
$NEXT
BYTE2 value for MIDI operation.
;A<(V/E0), Midi loop count.
;A<A+80
;C<A
;B<C6
;A<(BC)
;C<A
;B<0
;PUSH BC
BYTE1 value for MIDI operation.
;A<(V/E0), Midi loop count.
;A<A+C0
;C<A
;B<C6
;A<(BC)
;C<A
;B<0
;PUSH BC
FLAG value for MIDI operation.
;A<(V/E0), Midi loop count.
;C<A
;B<C7
;A<(BC)
;C<A
;B<0
;PUSH BC
; FLGON
;
( --- )
Store FF in FLAG of current slider.
$CODE
5,'FLGON',FLGON
DB 1,0E0H
;A<(V/E0)
DB 1BH
;C<A
DB 6AH,0C7H
;B<C7
DB 69H,0FFH
;A<FF
DB 39H
;(BC)<A
$NEXT
; FLGOFF
;
( --- )
Store 0 in FLAG of current slider.
$CODE
6,'FLGOFF',FLGOFF
DB 1,0E0H
;A<(V/E0)
DB 1BH
;C<A
DB 6AH,0C7H
;B<C7
DB 69H,0
;A<0
DB 39H
;(BC)<A
137
$NEXT
; ?DIFF
;
(old,new --- /shifted new,0F/ OR /00/)
Flag=0F if /old-new/>1, else Flag=0.
$CODE
5,'?DIFF',QDIFF
DB 0A4H
;POP EA, new
DB 0A1H
;POP BC, old
DB 09H
;A<EAL
DB 60H,0E3H
;A<A-C
DB
DB
DB
DB
DB
DB
DB
DB
DB
DB
DB
6BH,0FFH
60H,0EBH
69H,0
6BH,0
47H,0FEH
0C7H
9H
48H,21H
19H
0B4H
6BH,0FFH
;C<FF
;A-C, skip if no zero
;A<0
;C<0
;A AND FE, skip if no zero
;JMP AHEAD
;A<EAL
;A SHIFT RIGHT
;EAL<A
;PUSH EA
;C<FF
DB 6AH,0
DB 0B1H
$NEXT
;B<0, AHEAD
;PUSH BC
; LDLAST
;
( --- )
Moves ADC value to SLAST value in current MLOOP slider buffer.
$CODE
6,'LDLAST',LDLAST
DB 1,0E0H
;A<(V/E0)
DB 1BH
;C<A
DB 6AH,0C6H
;B<C6
DB 29H
;A<(BC)
DB 19H
;EAL<A
DB 0BH
;A<C
DB 46H,40H
;A<A+40
DB 1BH
;C<A
DB 09H
;A<EAL
DB 39H
;(BC)<A
$NEXT
;
;
DUMMY
( --- )
Do nothing dummy.
$COLON 5,'DUMMY',DUMMY
DW
EXIT
;
;
LDSTAT
( --- )
Load current Byte1 to FFE1, last Midi status sent.
$COLON 6,'LDSTAT',LDSTAT
DW
BYT1,DOLIT,0FFE1H,CSTOR,EXIT
;
;
KEYN
( --- )
Midi routine for Key On and Key Off.
$COLON 4,'KEYN',KEYN
DW
ADCV,DOLIT,0,EQUAL
DW
QBRAN,KEYN1
DW
LDLAST,FLAG
DW
QBRAN,KEYN4
138
KEYN1:
KEYN2:
KEYN3:
KEYN4:
;
;
TSTAT
TSTAT1:
TSTAT2:
;
;
KEYAT
KEYAT1:
KEYAT2:
KEYAT3:
KEYAT4:
;
;
CNTRL
CNTRL1
;
;
PRG
DW
DW
DW
DW
DW
DW
DW
DW
DW
BYT1,TM,LDSTAT,BYT2,TM,FLGOFF,DOLIT,0,TM,EXIT
FLAG
QBRAN,KEYN2
EXIT
ADCV,SLAST,SUBB,ZLESS
QBRAN,KEYN3
BYT1,TM,LDSTAT,BYT2,TM,FLGON,ADCV,TWOSR,TM
LDLAST
EXIT
( --- )
Test status byte, send midi status if not last sent.
$COLON 5,'TSTAT',TSTAT
DW
BYT1,DUPP,DOLIT,0FFE1H,CAT,EQUAL
DW
QBRAN,TSTAT1
DW
DROP,BRAN,TSTAT2
DW
TM,LDSTAT
DW
EXIT
( --- )
Midi routine for Key On and Key Off with Poly After Touch.
$COLON 5,'KEYAT',KEYAT
DW
ADCV,DOLIT,0,EQUAL
DW
QBRAN,KEYAT1
DW
LDLAST,FLAG
DW
QBRAN,KEYAT4
DW
BYT1,DOLIT,0FH,ANDD,DOLIT,90H,ORR,TM
DW
DOLIT,90H,DOLIT,0FFE1H,CSTOR
DW
BYT2,TM,FLGOFF,DOLIT,0,TM,EXIT
DW
FLAG
DW
QBRAN,KEYAT2
DW
SLAST,ADCV
DW
QDIFF
DW
QBRAN,KEYAT4
DW
TSTAT,BYT2,TM,LDLAST,TM,EXIT
DW
ADCV,SLAST,SUBB,ZLESS
DW
QBRAN,KEYAT3
DW
BYT1,DOLIT,0FH,ANDD,DOLIT,90H,ORR,TM
DW
DOLIT,90H,DOLIT,0FFE1H,CSTOR
DW
BYT2,TM,FLGON,ADCV,TWOSR,TM
DW
LDLAST
DW
EXIT
( --- )
Midi Routine for controller data.
$COLON 5,'CNTRL',CNTRL
DW
SLAST,ADCV
DW
QDIFF
DW
QBRAN,CNTRL1
DW
TSTAT,BYT2,TM,LDLAST,TM,EXIT
DW
EXIT
( --- )
Midi Routine for program changes.
$COLON 3,'PRG',PRG
DW
DOLIT,40H,ADCV,LESS
DW
QBRAN,PRG2
DW
FLAG
139
PRG1:
PRG2:
;
;
CHAT
CHAT1:
;
;
PWHL
PWHL1:
DW
DW
DW
DW
QBRAN,PRG1
EXIT
BYT1,TM,LDSTAT,FLGON,BYT2,TM,EXIT
FLGOFF,EXIT
( --- )
Midi Routine for Channel Pressure.
$COLON 4,'CHAT',CHAT
DW
SLAST,ADCV
DW
QDIFF
DW
QBRAN,CHAT1
DW
TSTAT,LDLAST,TM,EXIT
DW
EXIT
( --- )
Midi Routine for Pitch Wheel.
$COLON 4,'PWHL',PWHL
DW
SLAST,ADCV
DW
QDIFF
DW
QBRAN,PWHL1
DW
TSTAT,DOLIT,0,TM,LDLAST,TM,EXIT
DW
EXIT
;
;
MCASE
( --- )
Midi Routines Case Statement.
$COLON 5,'MCASE',MCASE
DW
CASE,DUMMY
DW
KEYN,KEYAT,CNTRL,PRG,CHAT,PWHL,DUMMY
DW
EXIT
;
;
MIDI
( --- )
Main Midi Loop.
$COLON 4,'MIDI',MIDI
DW
DOLIT,0C700H,DOLIT,40H,DOLIT,0,FILL
DW
DOLIT,0C640H,DOLIT,40H,DOLIT,0,FILL
DW
ADCIN,MLOOP,MCASE,SWAT,INVER,DOLIT,07H,ANDD
DW
QBRAN,MIDI1
DW
EXIT
MIDI1:
;
;
;
EDIT
EDIT1:
( --- )
MAIN SLIDER EDIT PROGRAM.
$COLON 4,'EDIT',EDIT
DW
DW
DW
DW
DW
CR,DECIM,DOLIT,1,LI,BDEL
EUPDAT,EDISP
ADCIN,SLDISP,DOLIT,0,LEDB,MNCASE,NUFQ
QBRAN,EDIT1
HEX,EXIT
; ENBRM
;
( --- )
Enable Midi Receive.
$CODE
5,'ENBRM',ENBRM
DB
64H,81H,0EH
;SMH<E
$NEXT
; RM
;
( --- b,f)
Receive Midi.
If midi received, returns the data plus true,
140
;
else returns false flag.
$CODE
2,'RM',RM
DB
6AH,0
;B<0
DB
6BH,0
;C<0
DB
48H,49H
;SKIT FSR, skip if interrupt flg
DB
0C6H
;JMP AHEAD
DB
4CH,0D9H
;A<RXB
DB
1BH
;C<A
DB
0B1H
;PUSH BC, received byte
DB
6BH,0FFH
;C<FF
DB
0B1H
;PUSH BC, the flag, AHEAD
$NEXT
;===============================================================
LASTN
EQU
_NAME+4
NTOPP
dictionary
CTOPP
dictionary
EQU
_NAME-0
;next available memory in ROM name
EQU
$+0
;next available memory in ROM code
MAIN
END
;last name address
ENDS
ORIG
;===============================================================
141