6502-OS/system/io_W65C22.h65

161 lines
6.5 KiB
Plaintext
Raw Normal View History

2023-12-23 14:18:32 +01:00
;;********************************************************************************
;; @module IO-W65C22
2024-08-08 20:39:25 +02:00
;; @ingroup system
2023-12-23 14:18:32 +01:00
;; @device Western Design - W65C22N Versatile Interface Adapter
;; @details
;;********************************************************************************
2023-10-26 19:51:20 +02:00
.ifndef INCLUDE_IOW65C22
INCLUDE_IOW65C22 = 1
2024-08-08 20:15:50 +02:00
;;********************************************************************************
;; @brief Versatile Interface Adapter (VIA) W65C22
;; @ingroup utility
;; @device Western Design - W65C22N Versatile Interface Adapter
;; @todo rename to VIA
;; @warning @anchor via_hardware_bug
;; The 6522 and 65C22 have a hardware bug, where a bit is not read in when the
;; external shift register clock transitions close to @f$ \phi_2 @f$.
;; To resolve this, you should use a @f$ \phi_2 @f$ controlled flip flop to ensure
;; the external clock transitions after the system clock.
;;********************************************************************************
2023-11-01 13:13:23 +01:00
.scope IO
2023-12-21 17:27:54 +01:00
; not using a struct for this since the syntax for access would be the same,
; ie label+IO::RA
2024-08-08 20:15:50 +02:00
;;********************************************************************************
;; @brief VIA register offsets from the base address
;; @details
;; Use like this: `VIA_ADDRESS + IO::RB`
;;********************************************************************************
2023-11-01 13:13:23 +01:00
.enum
2024-08-08 20:15:50 +02:00
RB = $0 ;; Register B (ORB/IRB)
RA = $1 ;; Register A (ORA/IRA)
DDRB = $2 ;; Data Direction Register B
DDRA = $3 ;; Data Direction Register A
T1CL = $4 ;; Timer 1 Counter Low/High
2023-11-01 13:13:23 +01:00
T1CH = $5
2024-08-08 20:15:50 +02:00
T1LL = $6 ;; Timer 1 Latch Low/High
2023-11-01 13:13:23 +01:00
T1LH = $7
2024-08-08 20:15:50 +02:00
T2CL = $8 ;; Timer 2 Counter Low/High
2023-11-01 13:13:23 +01:00
T2CH = $9
2024-08-08 20:15:50 +02:00
SR = $a ;; Shift Register
ACR = $b ;; Auxiliary Control Register
PCR = $c ;; Peripheral Control Register
IFR = $d ;; Interrupt Flag Register
IER = $e ;; Interrupt Enable Register
RANH = $f ;; RA without handshake
2023-11-01 13:13:23 +01:00
.endenum
.enum ACR_MASK ; ACR Masks
PA = %00000001
PB = %00000010
SR = %00011100
T2 = %00100000
T1 = %11000000
.endenum
2024-08-08 20:15:50 +02:00
;;********************************************************************************
;; @brief Settings for Auxiliary Control Register
;; @details
;; `OR` the values with the appropriate IO::ACR_MASK to not target only specific settings
;;********************************************************************************
.enum ACR
2023-10-27 16:50:58 +02:00
; SR Modes
2024-08-08 20:15:50 +02:00
SR_DISABLE = %00000000 ;; Disabled
SR_SIN_T2 = %00000100 ;; Shift in under control of T2
SR_SIN_PHI2 = %00001000 ;; Shift in under control of PHI2
SR_SIN_PHIE = %00001100 ;; Shift in under control of external clock
SR_SOUT_FREE_T2 = %00010000 ;; Shift out free running at T2 rate
SR_SOUT_T2 = %00010100 ;; Shift out under control of T2
SR_SOUT_PHI2 = %00011000 ;; Shift out under control of PHI2
SR_SOUT_PHIE = %00011100 ;; Shift out under control of external clock
2023-10-27 16:50:58 +02:00
; T1 Modes
2024-08-08 20:15:50 +02:00
T1_IRQ_LOAD = %00000000 ;; Timed interrupt each time T1 is loaded
T1_IRQ_CONT = %01000000 ;; Continuous interrupts
T1_IRQ_LOAD_PB7 = %10000000 ;; Timed interrupt each time T1 is loaded - PB7 One Shot output
T1_IRQ_CONT_PB7 = %11000000 ;; Continuous interrupts - PB7 Square wave output
2023-12-20 12:27:54 +01:00
; T2 Modes
2024-08-08 20:15:50 +02:00
T2_IRQ_LOAD = %00000000 ;; Timed interrupt each time T2 is loaded
T2_COUNT_PB6 = %00100000 ;; Count down with pulsen on PB6
2023-12-20 12:27:54 +01:00
; Latch
2024-08-08 20:15:50 +02:00
LATCH_DISABLE = %00000000 ;; `OR` this with IO::ACR_MASK::PA or IO::ACR_MASK::PB
LATCH_ENBLE = %00000011 ;; `OR` this with IO::ACR_MASK::PA or IO::ACR_MASK::PB
2023-11-01 13:13:23 +01:00
.endenum
.enum PCR_MASK ; PCR Masks
CA1 = %00000001 ;
CA2 = %00001110 ;
CB1 = %00010000 ;
CB2 = %11100000 ;
.endenum
2024-08-08 20:15:50 +02:00
;;********************************************************************************
;; @brief Settings for Peripheral Control Register
;; @details
;; `OR` the values with the appropriate IO::PCR_MASK to not target only specific settings
;;********************************************************************************
2023-11-01 13:13:23 +01:00
.enum PCR
2023-10-27 16:50:58 +02:00
; CA1 Modes
2023-11-01 13:13:23 +01:00
CA1_IN_AE = %00000000 ; Input-negative active edge
CA1_IP_AE = %00000001 ; Input-positive active edge
2023-10-27 16:50:58 +02:00
; CA2 Modes
2023-11-01 13:13:23 +01:00
CA2_IN_AE = %00000000 ; Input-negative active edge
CA2_IN_AE_IRQ_IND= %00000010 ; Independent interrupt input-negative edge
CA2_IP_AE = %00000100 ; Input-positive active edge
CA2_IP_AE_IRQ_IND= %00000110 ; Independent interrupt input-positive edge
2024-01-02 23:36:58 +01:00
CA2_OUT_HANDSHAKE= %00001000 ; Handshake output
CA2_OUT_PULSE = %00001010 ; Pulse output
CA2_OUT_LOW = %00001100 ; Low output
CA2_OUT_HIGH = %00001110 ; High output
2023-10-27 16:50:58 +02:00
; CB1 Modes
2023-11-01 13:13:23 +01:00
CB1_IN_AE = %00000000 ; Input-negative active edge
CB1_IP_AE = %00010000 ; Input-positive active edge
2023-10-27 16:50:58 +02:00
; CB2 Modes
2023-11-01 13:13:23 +01:00
CB2_IN_AE = %00000000 ; Input-negative active edge
CB2_IN_AE_IRQ_IND= %00100000 ; Independent interrupt input-negative edge
CB2_IP_AE = %01000000 ; Input-positive active edge
CB2_IP_AE_IRQ_IND= %01100000 ; Independent interrupt input-positive edge
2024-01-02 23:36:58 +01:00
CB2_OUT_HANDSHAKE= %10000000 ; Handshake output
CB2_OUT_PULSE = %10100000 ; Pulse output
CB2_OUT_LOW = %11000000 ; Low output
CB2_OUT_HIGH = %11100000 ; High output
2023-11-01 13:13:23 +01:00
.endenum
2023-10-27 16:50:58 +02:00
2024-08-08 20:15:50 +02:00
;;********************************************************************************
;; @brief Interrupt Flag/Enable Register bits
;;********************************************************************************
2023-11-01 13:13:23 +01:00
.enum IRQ
CA2 = %00000001
CA1 = %00000010
SR = %00000100
CB2 = %00001000
CB1 = %00010000
T2 = %00100000
T1 = %01000000
IRQ = %10000000
.endenum
2023-10-26 19:51:20 +02:00
2024-01-01 14:56:11 +01:00
;;********************************************************************************
;; @macro Enable an interrupt source
2024-08-08 20:39:25 +02:00
;; @modifies A
2024-08-08 20:15:50 +02:00
;; @param flag: A flag of the interrupt flag register (IO::IRQ)
2024-01-01 14:56:11 +01:00
;;********************************************************************************
.macro IO_EnableIRQ ioaddr, flag
lda #(IO::IRQ::IRQ | flag)
sta ioaddr + IO::IER
.endmacro
;;********************************************************************************
;; @macro Disable an interrupt source
2024-08-08 20:39:25 +02:00
;; @modifies A
2024-08-08 20:15:50 +02:00
;; @param flag: A flag of the interrupt flag register (IO::IRQ)
2024-01-01 14:56:11 +01:00
;;********************************************************************************
.macro IO_DisableIRQ ioaddr, flag
lda #flag
sta ioaddr + IO::IER
.endmacro
2023-12-08 00:02:52 +01:00
.endscope ; IO
.endif ; guard