mirror of
https://github.com/V2RetroComputing/analog-firmware.git
synced 2024-11-18 11:06:06 +00:00
98 lines
4.2 KiB
Plaintext
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 [15] ; 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 [7] ; 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 [7] ; 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 [3]
|
|
out PINDIRS, 8 [31] ; 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
|