;;******************************************************************************** ;; @file ;; @brief VIA W65C22 header ;; @ingroup system ;; @details ;; @device Western Design - W65C22N Versatile Interface Adapter ;;******************************************************************************** .ifndef INCLUDE_IOW65C22 INCLUDE_IOW65C22 = 1 ;;******************************************************************************** ;; @brief Versatile Interface Adapter (VIA) W65C22 ;; @ingroup system ;; @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. ;;******************************************************************************** .scope IO ; not using a struct for this since the syntax for access would be the same, ; ie label+IO::RA ;;******************************************************************************** ;; @brief VIA register offsets from the base address ;; @details ;; Use like this: `VIA_ADDRESS + IO::RB` ;;******************************************************************************** .enum 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 T1CH = $5 T1LL = $6 ;;< Timer 1 Latch Low/High T1LH = $7 T2CL = $8 ;;< Timer 2 Counter Low/High T2CH = $9 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 .endenum .enum ACR_MASK ; ACR Masks PA = %00000001 PB = %00000010 SR = %00011100 T2 = %00100000 T1 = %11000000 .endenum ;;******************************************************************************** ;; @brief Settings for Auxiliary Control Register ;; @details ;; `OR` the values with the appropriate IO::ACR_MASK to not target only specific settings ;;******************************************************************************** .enum ACR ; SR Modes 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 ; T1 Modes 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 ; T2 Modes T2_IRQ_LOAD = %00000000 ;;< Timed interrupt each time T2 is loaded T2_COUNT_PB6 = %00100000 ;;< Count down with pulsen on PB6 ; Latch 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 .endenum .enum PCR_MASK ; PCR Masks CA1 = %00000001 ; CA2 = %00001110 ; CB1 = %00010000 ; CB2 = %11100000 ; .endenum ;;******************************************************************************** ;; @brief Settings for Peripheral Control Register ;; @details ;; `OR` the values with the appropriate IO::PCR_MASK to not target only specific settings ;;******************************************************************************** .enum PCR ; CA1 Modes CA1_IN_AE = %00000000 ;;< Input-negative active edge CA1_IP_AE = %00000001 ;;< Input-positive active edge ; CA2 Modes 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 CA2_OUT_HANDSHAKE= %00001000 ;;< Handshake output CA2_OUT_PULSE = %00001010 ;;< Pulse output CA2_OUT_LOW = %00001100 ;;< Low output CA2_OUT_HIGH = %00001110 ;;< High output ; CB1 Modes CB1_IN_AE = %00000000 ;;< Input-negative active edge CB1_IP_AE = %00010000 ;;< Input-positive active edge ; CB2 Modes 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 CB2_OUT_HANDSHAKE= %10000000 ;;< Handshake output CB2_OUT_PULSE = %10100000 ;;< Pulse output CB2_OUT_LOW = %11000000 ;;< Low output CB2_OUT_HIGH = %11100000 ;;< High output .endenum ;;******************************************************************************** ;; @brief Interrupt Flag/Enable Register bits ;;******************************************************************************** .enum IRQ CA2 = %00000001 CA1 = %00000010 SR = %00000100 CB2 = %00001000 CB1 = %00010000 T2 = %00100000 T1 = %01000000 IRQ = %10000000 .endenum ;;******************************************************************************** ;; @macro Enable an interrupt source ;; @modifies A ;; @param flag: A flag of the interrupt flag register (IO::IRQ) ;;******************************************************************************** .macro IO_EnableIRQ ioaddr, flag lda #(IO::IRQ::IRQ | flag) sta ioaddr + IO::IER .endmacro ;;******************************************************************************** ;; @macro Disable an interrupt source ;; @modifies A ;; @param flag: A flag of the interrupt flag register (IO::IRQ) ;;******************************************************************************** .macro IO_DisableIRQ ioaddr, flag lda #flag sta ioaddr + IO::IER .endmacro .endscope ; IO .endif ; guard