RunCPM provides access to Arduino I/O capabilities through CP/M's BDOS (Basic Disk Operating System) interface. By loading the C register with a function number and a call to address 5, additional functionality that has been added to the system can be accessed.
For these functions, the number of the pin being used is placed in the D register and the value to write (when appropriate) is placed in E. For read functions, the result is returned as noted.
LD C, 220 LD D, pin_number LD E, mode ;(0 = INPUT, 1 = OUTPUT, 2 = INPUT_PULLUP) CALL 5
LD C, 221 LD D, pin_number CALL 5Returns result in A (0 = LOW, 1 = HIGH).
LD C, 222 LD D, pin_number LD E, value ;(0 = LOW, 1 = HIGH) CALL 5
LD C, 223 LD D, pin_number CALL 5
Returns result in HL (0 - 1023).
AnalogWrite (i.e. PWM)
LD C, 224 LD D, pin_number LD E, value (0-255) CALL 5
Using the above
DigitalWrite calls, it's easy to write some code to turn on a LED connected to, for example, pin D8. Use ED (the editor) to enter the following into the file LED.ASM. You could do this on your workstation directly on the SD card since ED is a beast from another time and, quite possibly, another dimension.
; Turn on a LED wired to pin 8
org 100h ;start address
mvi c, 220 ;pinmode
mvi d, 8 ;digital pin number
mvi e, 1 ;value (0 = low, 1 = high)
push d ;save arguments
call 5 ;call BDOS
pop d ;restore arguments
mvi c, 222 ;digital write
call 5 ;call BDOS
ret ;exit to CP/M
Then use the ASM command to assemble it:
CP/M ASSEMBLER - VER 2.0
000H USE FACTOR
END OF ASSEMBLY
RunCPM Version 3.7 (CP/M 2.2 60K)
This produces several files. LED.PRN is a text file containing your assembly language program along with the machine code it assembles to. Each line has 3 columns: address, machine code, and assembly language.
0100 org 100h
0100 0EDC mvi c,220
0102 1608 mvi d,8
0104 1E01 mvi e, 1
0106 D5 push d
0107 CD0500 call 5
010A D1 pop d
010B 0EDE mvi c, 222
010D CD0500 call 5
0110 C9 ret
There is also now a LED.HEX file. We can use the LOAD command/program to convert it into LED.COM which can be executed.
A> load led
FIRST ADDRESS 0100
LAST ADDRESS 0110
BYTES READ 0011
RECORDS WRITTEN 01
Now it can executed:
which will turn on the LED connected to pin D8.
So now we can read and write digital and analog I/O from Z80 assembly language code that's running on a Z80 emulated on the Grand Central. That seems pretty round-about.
While that's true, the point is to be able to play around with Z80 assembly language (and CP/M in this case) without having to find or build an actual Z80 system (although that can be its own kind of fun).