Skip to content

Instantly share code, notes, and snippets.

@tln
Created April 10, 2012 01:13
Show Gist options
  • Save tln/2347744 to your computer and use it in GitHub Desktop.
Save tln/2347744 to your computer and use it in GitHub Desktop.
DCPU16 proposal: Probes, devices and ROM.
Probes, devices and ROM.
Imagine that there are several devices on a bus of some kind. CPUs
can probe devices and devices can probe back via a controller chip.
A probe consists of a device ID (1 byte, low bit unset, 127 possible devices)
and a command (1 byte). The CPU can be probed too. Each device has a
DWORD in memory as well, to send/receive extra information with the probe.
Probes sent back to the CPU don't interrupt the CPU, the CPU must
be HALTed waiting for the probe.
New extended instructions:
HALT, a -- halts the CPU. CPU reawakens upon probe, with probe value in "a".
PRB, 0xddcc -- Probes device dd with command cc. Probes take 8 cycles.
CPUID, a -- puts device ID of this CPU in location/register. 2 cycles.
TIMER, n -- sets a probe (of 0) to come in n cycles. 2 cycles.
Additions to memory map:
0x0000 -- 0x006f -- ROM boot.
0x0070 -- 0x007f -- Serial #s
---- end of ROM ----
0x0080-ff -- Reserved for ROM. OS and apps can read device info.
0x0100-0x1ff -- Probe command buffer
0x200-0x0a00 -- Bootloader/OS
DCPU Devices
0x00 Controller -- always present (emulators should support)
0x10 Keyboard -- almost always present (emulators SHOULD support)
0x20 Monitor -- almost always present (emulators SHOULD support)
0xb0 BEEP -- almost always present (emulators SHOULD support)
0x30 CLOCK -- always present
0xc0 CPU0 -- always present
0xc2 CPU1 -- often present (emulators should try to support)
0xc4 CPU2 -- often present (emulators should try to support)
0xc6 CPU3 -- maybe present.
0xc8 CPU4 -- maybe present.
0xca CPU5 -- maybe present.
0xcc CPU6 -- maybe present.
0xce CPU7 -- maybe present. Max 8 cpus in current system.
0xd0 Disk 0 -- almost always present (emulators SHOULD support)
0xd2 Disk 1 -- often present (emulators should try to support)
Device details.
CPU.
Probes sent to CPU:
0x0 PROBE_TIMER
0x1 PROBE_ACK
0x2 PROBE_NAK
0x3 PROBE_BUSY
Controller.
Probe with a device in the command, and the controller will return either PROBE_ACK or PROBE_NAK depending on whether the given device can be probed. Probing the controller
and getting an answer is pretty fast, 10s of cycles.
Clock.
This is the real-time clock that retains the time after the computer is off. Probes take ~50 cycles.
Clock fits in DWORD, format TBD.
0x02 PROBE_GET_CLOCK. Current clock updated in DWORD.
0x03 PROBE_SET_CLOCK. Current clock updated to DWORD.
Beep.
This either beeps or flashes a light. One short beep occurs on boot before CPU0 starts
running ROM.
0x02 PROBE_START_BEEP
0x03 PROBE_STOP_BEEP
0x04 PROBE_BEEP_CHIRP
0x05 PROBE_BEEP_SHORT
Keyboard.
This device will treat its DWORD as a 4 byte buffer. If the high byte is set (buffer full), then
a chirp will be sent and the keypress will be dropped.
0x0 PROBE_KEY_WAIT Wait for key. ACK sent when key pressed. If there is something
in the buffer, ACK is sent immediately.
Screen.
The screen can have many modes. Modes < 8 are text modes. Modes > 8 are graphical modes.
Only modes 1 and 2 are currently defined. Mode 1 does not need to have a relocatable buffer range -- implementations can refuse to map range. Implementations can likewise leave off mode 2 and can refuse to map range on mode 2.
Mode definitions as stored in the DWORD:
Mode, 5 bits. Width: 11 bits. Height: 12 bits, Reserved: 4 bits.
0x00 PROBE_SCREEN_GET_MODE -- gets current mode.
0x01 PROBE_SCREEN_SET_MODE1 -- switch mode to 1 (text 32x12 b/w. 1 word per char.)
set text buffer range for screen from low word of DWORD to high word of DWORD.
ACK sent when mode is active and screen is displaying the selected memory.
NAK sent on invalid mode or range. NB mode 1 may only work at 0x8000 - 0x817f
0x02 PROBE_SCREEN_SET_MODE2 -- switch mode to 1 (text 32x12 color. 1 word per char, high byte is color).
Disk.
One disk is mandatory, two disks is pretty common. Typical disks are floppies with sector size of 256 2 words. Maximum sector size of 2048 words. A disk has a maximum of 65536 sectors. Maximum size is 256MB.
0x0 PROBE_DISK_INFO -- pack info in command buffer DWORD. ACK sent when info ready.
Low word:
1 bit: disk not present. FLAG_DISK_NOT_PRESENT
1 bit: disk busy. FLAG_DISK_BUSY
1 bit: disk error. set if either of above is set, or if there is some other error. FLAG_DISK_ERROR
1 bit: command finished. FLAG_DISK_COMMAND_FINISHED
2 bits: sector size (256 << sector size gives range of 256 to 2048).
MASK_DISK_SECTOR_SIZE, SHIFT_DISK_SECTOR_SIZE
2 bits: last command 0=info 1=read 2=write 3=eject
MASK_DISK_LAST_COMMAND, DISK_COMMAND_READ,_INFO,_WRITE,_EJECT
6 bits: # of sectors read/written. MASK_DISK_SECTORS_WRITTEN
High word:
16 bits: # of sectors on disk.
0x1-0x3f PROBE_DISK_READ1-63
reads 1-63 sectors starting at low word of dword into buffer given by high word of dword.
No guarantee on # of cycles. Hard disk: 2,000 - 50,000. Floppy: 20,000 - 500,000. ACK
sent when done.
0x41-7f PROBE_DISK_WRITE1-63
Writes 1-63 sectors starting at DWORD into buffer.
0x81-af PROBE_DISK_ERASE1-63
Erases 1-63 sectors starting at DWORD into buffer.
0xff PROBE_DISK_EJECT -- eject disk
ROM.
The ROM has 128 words to print a boot message to screen and load the bootloader from the disk.
0x80 Disk0 sector size
0x82 Disk0 # sectors
0x84 Disk1 flags
0x86 Disk1 size
0x90 screen mode
0x91 screen width
0x92 screen height
0x93 current offset
0x94 current color
ROM.
CPUID, z
IFE z, 0c0
ADD PC, 3 ; jump ahead to keyboard buffer
; not cpu0 -- wait for address from cpu0
HALT y
SET PC, [z+0x100]
; look for screen / clear screen
SET [0x120], 0x8000
SET [0x121], 0x817f
PRB 0x2001
JSR cls
TIMER, 10000
HALT y
IFE y, 0
SET PC, :noscreen
; look for keyboard or print message
PRB, 0x0010
HALT y
IFE y, 0xc001
ADD PC, 3 ; skip message
SET PC, msgnokbd
JSR pr
; look for disk0.
SET A, msgdisk
JSR pr
TIMER, 1000
PRB, 0xd000
HALT y
IFE y, 0
JMP :nodisk
IF y & FLAG_DISK_ERROR
JMP :nodisk
AND y, MASK_DISK_SECTOR_SIZE
SHR y, SHIFT_DISK_SECTOR_SIZE
SET [0x80], 256 ; # of sectors
SHL [0x80], y
SET [0x81], [0x1d1]
; determine # of sectors + corresponding read command
SET 0x800, x
DIV x, [0x80]
BOR x, 0xd000
SET [0xd0], 0 ; read sector 0
SET [0xd1], 0x200 ; into 0x200
PRB x
HALT y
;!!! handle errors
SET PC, 0x200
; booted!
:nodisk
SET A, :nodiskmsg
:nokbdmsg
DAT "No keyboard", 0x0
:nodiskmsg
DAT "No disk", 0x0
:msgdisk
DAT "Loading", 0x0
:cls
SET A, 0x817f
:clsloop
SET [A], 0
SUB A, 1
IFN A, 0x8000
SET PC, clsloop
SET [0x83], 0
SET PC, POP
:pr
; set A to point to data to print.
; I will be clobbered
SET I, [0x83]
:loop
SET [I+0x8000], [A]
ADD I, 1
ADD A, 1
IFN [A], 0
SET PC, loop
SET [0x83], I
SET PC, POP
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment