10/8/23 Update

A project log for 1802 MemberChip Card

A retro-microcomputer in a micro-package. Learn from the ground up, just like the pioneers. Has monitor editor assembler BASIC FORTH LISP...

lee-hartLee Hart 10/10/2023 at 05:233 Comments

Here are some "Quickstart" instructions for the Menu, BASIC, VTL2, and Visual/02 programs in Mike Riley's alternate program ROM. They're not a full manual yet, but will get you started and give you a "taste" of vintage programs and languages.

A Quickstart Guide to the Diskless Elf/OS ROM

by Mike Riley and Lee Hart

Last update: 2 Nov 2023

Elf/OS is a disk operating system for 1802 microprocessor systems. Since disk drives on the 1802 are rare, Mike also made a "diskless" version, so users could add their own form of mass storage. The Diskless Elf/OS ROM is stored in a single 32K EPROM, which contains a "sampler" of vintage programming tools and languages, including BASIC, FORTH, LISP, and VTL-2. It also includes a Monitor, Visual debugger, mini Editor/Assembler, and XMODEM load/save programs.

Diskless Elf/OS can be used in any 1802 system with 32K ROM and 32K RAM. A 5V USB-serial adapter provides power and serial I/O using the 1802's Q output and EF3 input pins. The MemberChip Card has a header to match the Sparkfun FTDI 5v USB-TTL serial cable #9718 Use it with a serial terminal, or a PC running a Terminal program such as TeraTerm Here are the basic steps:

1. Connect the 1802ME MemberChip Card:

2. Start TeraTerm:
        If it asks, select Serial (not TCP/IP), and select your COMn: port

3. Select Setup... Serial port... and select:
        Port = COM5 (or whatever serial port number your computer has)
        Speed = 4800
        Data = 8 bit
        Parity = none
        Stop = 1 bit
        Flow control = none

4. Select Setup... Terminal... and select:
        Term size = 80 x 24
        New-line: Receive = CR, Transmit = CR
        Terminal ID = VT100
        Coding: Receive = UTF-8, Transmit = UTF-8

5. Press the <ENTER> key, and the 1802ME will figure out the baud rate
        and display its sign-on menu:

|    MemberCHIP                       |
|                                     |
|    1. Rc/Basic L2                   |
|    2. Rc/Forth                      |
|    3. Rc/Lisp                       |
|    4. EDTASM                        |
|    5. VTL2                          |
|    6. Visual/02                     |
|    7. Minimon                       |
|    8. Dump Memory                   |
|    9. Load Memory                   |
|                                     |
|       Option ?                      |
|                            v1.7.2   |

Select one of the options by typing its number (1-9) and the <ENTER> key. The selected program will then start. See the instructions for how to use each program. Each program has its own way to EXIT back to the Menu.

1. Rc/BASIC L2

This is a classic 16-bit integer BASIC. Type a command line, and end it with the <ENTER> key. BASIC will execute the command, and display the result. Commands can be typed in upper or lower case, but will be converted to uppercase.

Rc/BASIC has two types of variables: Numeric and String. There are 26 Numeric variables, named A-Z. Longer names can be used for readability, but the additional letters are ignored (so A is the same variable as APPLE). Numeric variables must be integers in the range -32768 to +32767. Numbers smaller or larger than this will wrap around (so 32767+1 = -32768).

There are 26 String variables A-Z. Longer names can be used, but the last character must be a $ (so A$ is the same string variable as APPLE$). Strings are placed in quotes, like this: ROSE$="are red". Strings can be any length up to the available memory size.

There are two modes of operation; Direct and Program. In Direct mode, BASIC executes each line you type immediately. For example:

A=5               type these 3 lines
PRINT "A times B is "; A*B
    A times B is 20        ...and BASIC types this line

In Program mode, start each line with a line number. Rather than being executed, the lines are stored in memory, sorted into ascending order. If a line already exists with that number, the new line replaces it. To erase a line, type a line with just its number. It is traditional to number the lines by 10's. This makes it easy to add a line later to make changes. For example:

10 PRINT "Hello ";         ...first line of your program
11 PR                      ...oops; I started with the wrong line number
11                delete line 11
20 PRINT "world!"          ...and type line 20 instead
LIST                       ...LIST the program
    10 PRINT "Hello ";
    20 PRINT "world!"
RUN               RUN it
    Hello world!           ...and here's the output from your first program!

The LIST command will list (display) your program.
The RUN command will run your program.
The BYE command exits BASIC and returns to the menu.

Here is another simple example. Try entering and running it, then experiment by making your own changes to see how it works:

20 FOR X=1 to 10
30 PRINT 11-X; "...";
50 PRINT "Blast off!"
60 END
    Countdown 10...9...8...7...6...5...4...3...2...1...Blast off!

Programs can be saved as a file on your PC with the XMODEM function of your Terminal program. If you are using TeraTerm, here are the steps to save your BASIC program:

1. Type the SAVE command, and press <ENTER>.

2. In TeraTerm, select File... Transfer... XMODEM... Receive.

3. TeraTerm will prompt you for the file name, and location where you want to save it.
        Use a file name ending in .BAS (so you can tell it's a BASIC program).

4. Click Save to start the transfer.

5. The transfer process should start automatically.
        You will see a progress window as it proceeds, which will close when the transfer is complete.

A similar process is used to load a saved program:

1. Type the LOAD command, and press <ENTER>.

2. In TeraTerm, select File... Transfer... XMODEM... Send.

3. TeraTerm will prompt you for the file name, and location of the file.

4. Click Send to start the transfer.

5. The transfer process should start automatically.
        You will see a progress window as it proceeds, which will close when the transfer is complete.

Rc/BASIC Expressions

Arithmetic expressions can be used in most places where a number is expected (even in GOTO or GOSUB statements). The arithmetic operators are:

          +       add
          -       subtract
          *       multiply
          /       divide
AND or &   bitwise AND
  OR or  |     bitwise OR

Relational operators return -1 if TRUE, or 0 if FALSE:

          =       equal
        <>       not equal
          <       less than
          >       greater than
        <=       less than or equal
        >=       greater than or equal

Rc/BASIC follows the standard convention for operator precedence. ( and ) are evaluated first, then * and /, then + and -, then AND OR & and |, then = > < <> <= => are evaluated last.

Rc/BASIC Statements

CLEAR                                clear all variables, variable names, strings, and arrays
DATA value,value,value...   set up values to be read into variables (see READ)
DIM variable(size)               dimension 'variable' as having 'size' elements
END                                    end the program and returns to Direct mode
FOR variable = start TO end STEP size   start a FOR..NEXT loop,
    or FOR variable = start TO end            which sets 'variable' to 'start',
                                                                  then executes lines until NEXT.
STEP expr                           set step size for NEXT (must be +, defaults to 1)
NEXT variable                     increment 'variable' by STEP. If 'variable' is less than
    or NEXT                           or equal to 'end', jump back to FOR; else continue.
GOTO expr                          jump to line number calculated by 'expr'
GOSUB expr                       call subroutine at line# calculated by 'expr' (see RETURN)
IF expr THEN statement     if 'expr' is true (non-zero), then do 'statement'
    or IF expr statement       else if 'expr' is false (zero), then skip to next line
INPUT "prompt"; var, var...   get input(s) from user, and assign to variable(s).
    or INPUT var, var...          "prompt" is optional and displays first if provided
LET var = expr                     set 'variable' to value of expression
    or var = expr                   'LET' is optional
LIST                                     list entire program
LIST line                              list only 'line' number
LIST start-end                     list lines from 'start' to 'end'
LOAD                                  load a BASIC program from a file on your PC (in XMODEM format)
NEW                                    clear the program and variables
ON expr GOTO line1, line2...     if expr=1, GOTO line1, if 2 GOTO line2, etc.
OUT port, value                 write 'value' to 1802 output port (1-7)
POKE addr, value               write 'value' into memory address
PLOT x, y                            move cursor to x (horizontal 1-80), y (vertical 1-24)
PRINT exprlist                     display numbers, strings, or values of variables. Separate
                                            items with ; for no spaces between them, or ; to put a <tab>
                                            between them. If , or ; ends the list, no <CR> will be output.
RANDOM                            prompt user for a number to set the RND( ) seed
RESTORE line                     reset the DATA pointer to 'line' number
RETURN                             return to line following the last GOSUB
READ var, var...                   read values from DATA statement and store them in 'var' list
REM anything                     mark the rest of the line as a comment that will be ignored
RUN                                    start running the program at the first line number
SAVE                                   save a BASIC program as a file on your PC (in XMODEM format)

Rc/BASIC Functions

ASC(string)                         return ASCII value of first character of the string
CHR$(expr)                        return value of expression as a 1-character ASCII string
FLG( )                                 return value of 1802's EF1-4 flags
FRE( )                                 return remaining amount of memory available
INP(port)                             return value of 1802 input port 1-7
LEFT$(string, expr)            return 'expr' characters from left side of string
LEN(string)                         return length of the string
MID$(string, start, length)  return 'length' characters of string,
                                           beginning at the 'start' position
PEEK(addr)                         return decimal value of the byte at the memory address
RIGHT$(string, expr)          return 'expr' characters from right side of string
RND(range)                        return a random number from 0 to 1 less than 'range'
STR$(expr)                         return the value of 'expr' converted into an ASCII string
USR(addr, expr)                 call machine language subroutine. If 'expr' is provided,
    or USR(addr)                  it is loaded into RF. USR returns the value left in RF
                                           by the machine language subroutine when it returns.
VAL(string)                         return value of 'string' expressed as a binary number
VARPTR(varname)             return address where a variable name is stored

5. VTL2

VTL (Very Tiny Language) was developed in 1976 for the 8080 CPU in the Altair 8800 microcomputer. Memory was expensive, so VTL only required 768 bytes! To put that in perspective, Microsoft's 4K Integer BASIC was five times bigger. Despite its size, VTL is a clever little language that is smaller, faster, more powerful, and almost as easy to use as BASIC.

VTL2 is an improved version, developed in 1977 for the 6800 microprocessor. It is also tiny, but has more commands and features. Mike Riley wrote this version for the 1802. Here are the "quickstart" instructions:

  1. Press 5 <ENTER> to start the VTL2 program. It displays its sign-on message:
    Rc/VTL2 V1.0.0
  2. Type < then the <ENTER> key. (This is the VTL2 "LOAD" command.)

  3. In the Teraterm menu, select File... Transfer... XMODEM... Send

  4. Select the MAZE.V program to send (you can download it from the files section of this project). You should see a progress box as Teraterm sends the program to the 1802ME.

  5. Type #=1 and the <ENTER> key. This is the VTL command to go RUN the program starting at line #1.

This program draws a maze, with the entry at the top and exit at the bottom. It will prompt you for the starting Seed, Width, and Height. Here is a sample run:

------------------------------- | Rc/VTL2 V1.0.0 | | >< | | >#=1 | | Enter seed: 2 | | Enter width: 5 | | Enter height: 5 | | | | + +--+--+--+--+ | | | | | | | + + + +--+ + | | | | | | | | +--+--+--+ + + | | | | | | | + +--+--+--+ + | | | | | | | | +--+--+ + + + | | | | | | | +--+--+ +--+--+ | | > | -------------------------------

VTL2 is an interpreter, like BASIC. You type in your command, and it is acted on immediately. It uses unsigned decimal numbers from 0-65535, and strings of ASCII characters, delimited by quotes "like this".

There are two types of commands:

  1. Direct statements, which have no line number. They are executed immediately after you hit the ENTER key. All Direct statements are of the form:

  2.         variable=expression

  3. Program statements, which start with a line number. They are saved in numerical order in memory, and executed later when the program is run. All program statements look like this:

  4.         line# variable=expression

VTL2 Operators

    +       add
    -       subtract
    *       multiply
    /       divide
    &      bitwise AND
    |        bitwise OR
    ^       bitwise XOR

Comparison Operators:
    <       less than
    =       equal to
    >       greater than

VTL2 is unusual in that it only has *ONE* statement; variable = expression ! The uppercase alphabet A-Z, plus most of the rest of the punctuation symbols are all variables. However, the punctuation symbols are "system variables" with special functions:

VTL2 System Variables

    !       return address
    "       pointer for literal print statements
    #       current line number
    $       single character input or output
    %       remainder after last division
    &       points to last byte of program
    '       random number
    (       starts a parenthesized expression
    )       ends a parenthesized expression
            or, starts a Remark if no matching ( before it on the line
            or, ends an array description
    *       end of memory
    >       save to disk (to PC in XMODEM format)
    <       load from disk (from PC in XMODEM format)
    ?       print if left of =, input if right of =
    :       start of array description
    ;       suppress <CR><LF> if at end of print statement
    {       start of an absolute memory address
    }       ends an absolute memory address

It takes some time to wrap your head around how this "system variable" concept works. For example, the system variable '#' is the current line number, so

      #=1                           jumps to the first line of the program (it's the same as RUN in BASIC)
      10 #=100                  jumps from the current line to line 100 (the same as GOTO 100 in BASIC)

You can also read system variables. Since '#' is the current line number,

      100 A=#                   sets A = 100 (the current line number)

If a statement tries to set #=0, it is ignored and # is not changed. This is how VTL2 implements the IF statement:

      10 X=25
      20 #=(X=25)*50       if X=25 is true (=1), then set line# = 50 (i.e. GOTO 50)
      30 ...                         do this if X is not 25
      40 #=20                   and GOTO 20
      50 ...                         do this if X=25

Every time a program statement writes to '#', the (old value of # + 1) is saved in the system variable '!'. VTL2 uses this to implement BASIC's GOSUB and RETURN commands. For example:

      10 X=1
      20 #=100                 CALL subroutine at 100 (and set !=21)...
      30 X=2            returns here, since '!' points to the next line after 20
      40 #=100                 CALL 100 again (and set !=41)...
      50 X=3                     ...returns here
      60 #=100                 etc.
      100 X=X*X               this is the subroutine; it squares X...
      110 #=!                       ...and returns to the next line after the CALL (like RETURN in BASIC)

'?' is the variable equivalent to BASIC's PRINT and INPUT statements. If '?' is to the right of the = sign, it is the PRINT statement.

      A=?                           this requests a user input, and sets A to it

If the '?' is to the left of the = sign, it is the INPUT statement

      ?="You typed ";A       prompts user with message "You typed ", inputs a number, and saves it in A

Special things:
    0            list program (like LIST in BASIC)
    #=1         run program, by setting line number to 1 (like RUN in BASIC)
    &=0       clear program, by setting last byte of program to 0 (like CLEAR in BASIC)
    *=0         exit VTL2, by setting the end of memory to 0 (like BYE in BASIC)

6. VISUAL/02

VISUAL/02 is an 1802 simulator. It creates a virtual 1802, with its own independent set of registers. Unlike a monitor program that must reserve some registers for itself, VISUAL/02 can examine, change, and display all the 1802 registers and memory contents, and visually display them as it executes instructions or runs programs. It includes a simple disassembler, and can set breakpoints and trap individual opcodes. VISUAL/02 is a great way to debug programs, and to learn what the 1802 opcodes actually do.

Here is a sample display:

  _______1802_registers_______     _____Disassembled_code______
 /                            \   /                            \
+----------+ +-------+ +-------+ +------------------------------+
| R0  7018 | | D  FF | | DF 1  | | 7018 LDI  FF                 | TRAPS
| R1  3E7D | +-------+ +-------+ | 701A PLO  2                  |  80
| R2  FDFF | +-------+ +-------+ | 701B LDI  FD                 |   ^
| R3  3FD1 | | X  0  | | P  0  | | 701D PHI  2                  |   |
| R4  EB1D | +-------+ +-------+ | 701E LDI  27                 |   |
| R5  63FF | +-------+           | 7020 PLO  6                  | Trapped opcodes
| R6  7027 | | T  7D |    BRK:   | 7021 LDI  70                 | displayed here
| R7  DC3E | +-------+    701E   +------------------------------+
| R8  7BEF | +-------+    7021   +------------------------------+
| R9  F2BE | | Q  0  |     ^     | 7018 F8 FF A2 F8 FD B2 F8 27 | \
| RA  E9BF | +-------+     |     | 7020 A6 F8 70 B6 C0 0F 3F D4 |  |
| RB  F97C | +-------+     |     | 7028 0F 2D C0 70 3D F8 FF A2 |  |
| RC  5FBF | | IE 1  |     |     | 7030 F8 FD B2 F8 3D A6 F8 70 |  | memory
| RD  FFCF | +-------+     |     | 7038 B6 E2 C0 0F 3F F8 0C D4 |  | contents
| RE  FF5A |         Breakpoints | 7040 0F 03 F8 17 AD F8 4B BD |  |
| RF  17DF |          displayed  | 7048 D4 73 10 D4 0F 66 76 31 | /
+----------+             here    +------------------------------+

 7000 LBR  7018  <-- the LAST instruction executed
>7018 LDI  FF    <-- the NEXT instruction that that will be executed

V02>_            <-- VISUAL's prompt when it is waiting for your command

VISUAL/02 Commands:

?P                    display memory from R[P]
?X                    display memory from R[X]
?Rn                  display memory from R[n]
?aaaa              display memory from address aaaa
$P                    disassemble from R[P]
$X                    disassemble from R[X]
$Rn                  disassemble from R[n]
$aaaa              disassemble from address aaaa
!P bb bb ...       store bytes bb into address R[P]
!X bb bb ...       store bytes bb into address R[X]
!Rn bb bb ...     store bytes bb into address R[n]
!aaaa bb bb ... store bytes bb into address aaaa
@aaaa             set R[P] to run at address aaaa
Rn=aaaa          set R[n] to aaaa
P=n                  set P to n
X=n                  set X to n
D=nn                set D to nn
DF=b                set DF to b
Q=b                  set Q  to b
IE=b                  set IE to b
T=bb                 set T to bb
I                        trigger interrupt action
B+aaaa            set breakpoint at aaaa
B-aaaa             remove breakpoint at aaaa
BC                  ; clear all breakpoints
T+nn                set trap for instruction opcode nn
T-nn                 remove trap for instruction nn
TC                    clear all traps
<ENTER>          step 1 instruction
G                      go (run) until next breakpoint or trap
E                      exit VISUAL/02
A                      go to EDTASM (Pico/Elf only)

Note: As of 2 Nov 2023, use the TC command (Clear all Traps) before setting a Trap.

6. Minimon

This is a Mini Monitor program that lets you read and write to memory, and run programs. The sign-on prompt is ">". Commands consist of a "?" (read), "!" (write), or "@" (run) followed by a hexadecimal address. All numbers are hexadecimal. You can use the <backspace> key to correct mistakes until the final <ENTER> key to execute the command. Here's an example:

>?8000                                                 <-- READ memory starting at 8000h.
8000: BE EA 9D 64 8E D0 F9 EF 2D 4C 75 EC B4 E4 92 F6  <-- Here are 128 bytes of memory
8010: 63 02 3A 81 66 EC B4 99 B8 96 C4 D4 CE DE 59 90      starting at 8000h.
8020: E1 68 AE E2 1B CC 7F C3 CE 8B E7 FF 5C 1D A2 3D
8030: 86 9D AC FD 61 F8 A9 2C 26 CE D8 51 3C 5C 1C 76
8040: D7 6B 5F 58 CF E6 D0 69 98 43 C7 EE 1F 95 AD 24
8050: 3F AE C9 C9 6E EF 56 D7 22 F4 02 A3 A7 4B 96 33
8060: E4 47 8E D5 43 39 30 2C FD AD E7 9F 88 2E E5 BA
8070: 71 76 1B 67 B1 D3 BE A3 3F 29 6F DA 58 DC A0 F9
>!8000 F8 FF BB 7A 2B 9B 3A 03 C0 00 00                <-- WRITE a little program into memory.
>?8000                                                 <-- Read memory again to see if it's correct.
8000: F8 FF BB 7A 2B 9B 3A 03 C0 00 00 EC B4 E4 92 F6  <-- Yep; it's correct!
8010: 63 02 3A 81 66 EC B4 99 B8 96 C4 D4 CE DE 59 90
8020: E1 68 AE E2 1B CC 7F C3 CE 8B E7 FF 5C 1D A2 3D
8030: 86 9D AC FD 61 F8 A9 2C 26 CE D8 51 3C 5C 1C 76
8040: D7 6B 5F 58 CF E6 D0 69 98 43 C7 EE 1F 95 AD 24
8050: 3F AE C9 C9 6E EF 56 D7 22 F4 02 A3 A7 4B 96 33
8060: E4 47 8E D5 43 39 30 2C FD AD E7 9F 88 2E E5 BA
8070: 71 76 1B 67 B1 D3 BE A3 3F 29 6F DA 58 DC A0 F9
>@8000                                                 <-- Now RUN the program. (It turns the red Q
                                                           LED on for a second, then waits for the
                                                           <ENTER> key to return to the main menu.)

Minimon has two more commands that will prove useful. "=" is the copy command, which copies "size" bytes from the "source" address to the "destination" address. Finally, the "/" command exits Minimon and returns to the Main Menu.

>=8000 8010 10                                         <-- COPY 10 bytes from 8000 to 8010
>?8000                                                 <-- Read to see if it worked.
8000: F8 FF BB 7A 2B 9B 3A 03 C0 00 00 EE F4 E7 9E FF
8010: F8 FF BB 7A 2B 9B 3A 03 C0 00 00 EE F4 E7 9E FF  <-- See? It did!
8020: E1 68 AE E2 1B CC 7F C3 CE 8B E7 FF 5C 1D A2 3D
8030: 86 9D AC FD 61 F8 A9 2C 26 CE D8 51 3C 5C 1C 76
8040: D7 6B 5F 58 CF E6 D0 69 98 43 C7 EE 1F 95 AD 24
8050: 3F AE C9 C9 6E EF 56 D7 22 F4 02 A3 A7 4B 96 33
8060: E4 47 8E D5 43 39 30 2C FD AD E7 9F 88 2E E5 BA
8070: 71 76 1B 67 B1 D3 BE A3 3F 29 6F DA 58 DC A0 F9
>/                                                      <-- EXIT Minimon


Lee Hart wrote 04/24/2024 at 22:10 point

updated on 24 Apr 2024

  Are you sure? yes | no

Lee Hart wrote 11/02/2023 at 20:43 point

updated on 12 Nov 2023

  Are you sure? yes | no

Lee Hart wrote 10/16/2023 at 07:44 point

updated on 16 Oct 2023

  Are you sure? yes | no