analog/v2-analog-rev1/common/abus.pio
David Kuder d9be2ed9cd Firmware Release 23-01-16-119
New autodetect routines for Apple II+, IIe (Platinum), IIgs (ROM03).
Timing tweaks to improve compatibility on IIgs and IIe.
Corrected text rendering on all supported machines.
Initial Super HiRes support (not recommended to use at this time)
Monochrome DHGR and HGR support activated with IIgs MONOCOLOR or NEWVID registers.
80 Column mode on IIe and IIgs.
2023-01-16 20:36:00 -05:00

98 lines
4.2 KiB
Plaintext

.define public PHI0_GPIO 26
.define READ_DATA_TRIGGER_IRQ 4
.define DATA_BUSY_IRQ 5
; Apple II bus interface
; Ref: Understanding the Apple II, pages 4-7, 7-8
.program abus
; Prerequisites:
; * Bus clock used is PHI0, wired to GPIO 26
; * JMP pin is mapped to the R/W signal
; * IN pins are mapped to ~DEVSEL, R/W, and Data[7:0]
; * SET pins are mapped to the transceiver enable signals
; * input shift left & autopush @ 26 bits
; * run at about 125MHz (8ns/instruction)
;
; SET bits for tranceiver control:
; 0bxxx
; x - select AddrHi, active low
; x - select AddrLo, active low
; x - select Data, active low
.wrap_target
next_bus_cycle:
set PINS, 0b011 ; enable AddrHi tranceiver
wait 1 GPIO, PHI0_GPIO ; wait for PHI0 to rise. Data propagation through the transceiver should
; be complete by the time this happens.
in PINS, 8 ; read AddrHi[7:0]
set PINS, 0b101 [2] ; enable AddrLo tranceiver and delay for transceiver propagation delay
in PINS, 8 ; read AddrLo[7:0]
jmp PIN, read_cycle ; jump based on the state of the R/W pin
write_cycle:
; the current time is P0+88ns (P0 + 16ns + 2 clocks (input synchronizers) + 7 instructions)
set PINS, 0b110 [14] ; enable Data tranceiver & wait until both ~DEVSEL and the written data are valid (P0+200ns)
in PINS, 10 ; read R/W, ~DEVSEL, and Data[7:0], then autopush
wait 0 GPIO, PHI0_GPIO [6] ; wait for PHI0 to fall
jmp next_bus_cycle
read_cycle:
; the current time is P0+88ns (P0 + 16ns + 2 clocks (input synchronizers) + 7 instructions)
set PINS, 0b110 ; ensure AddrLo transceiver is disabled and delay for ~DEVSEL to become valid (P0+63ns+buffer delay)
in PINS, 10 ; read R/W, ~DEVSEL, and dontcare[7:0], then autopush
irq set READ_DATA_TRIGGER_IRQ ; trigger the data read state machine to put data on the data bus
wait 0 GPIO, PHI0_GPIO [6] ; wait for PHI0 to fall
wait 0 irq DATA_BUSY_IRQ ; wait for the data handling state machine to complete to avoid contention w/transceiver control
.wrap
.program abus_device_read
; Prerequisites:
; * Bus clock used is PHI0, wired to GPIO 26
; * JMP pin is the ~DEVSEL signal
; * OUT pins are the 8 data signals
; * SET pins are the Data transceiver control signals
;
; SET bits for tranceiver control:
; 0bxx
; x - select Data transceiver (active low)
; x - Data transceiver direction (0=input, 1=output)
.wrap_target
wait_loop:
wait 1 irq READ_DATA_TRIGGER_IRQ ; wait for the data portion of a read cycle (from the main SM)
jmp PIN, wait_loop ; skip if this device is not being addressed
; the current time is P0+136ns (P0 + 16ns + 2 clocks (input synchronizers) + 13 instructions) and
; this read cycle is addressed to this device.
;
; Phase 0 is typically 489 ns long.
; * Data from peripherals should be valid on the data bus by 45 nanoseconds before the end of phase 0
; * Data should be held for 40ns after phase 0 ends
; * Data bus should be tri-stated within 60ns after phase 0 ends
irq set DATA_BUSY_IRQ
pull noblock ; extra early pull to clear out any standing values from the FIFO
set PINS, 0b01 ; enable Data tranceiver with output direction
mov OSR, ~NULL
out PINDIRS, 8 [30] ; set data pins as outputs
pull noblock ; pull value from the FIFO as late as possible
out PINS, 8
; the current time is P0+440ns (P0 + 16ns + 2 clocks (input synchronizers) + 51 instructions)
wait 0 GPIO, PHI0_GPIO [2] ; wait for PHI0 to fall then hold for 40ns (2 clocks (input synchronizers) + 2-3 instructions)
set PINS, 0b10 ; disable Data tranceiver to tri-state the data bus
mov OSR, NULL
out PINDIRS, 8 ; reset data pins as inputs
irq clear DATA_BUSY_IRQ
.wrap