Files
Z8C-Homebrew-Computer/OperatingSystem/iictest/include/kdrv_iic.s
2024-01-12 13:29:20 +01:00

271 lines
7.2 KiB
ArmAsm
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
CS_PIO_BD .EQU 0xF5
CS_PIO_BC .EQU 0xF7
CS_PIO_AD .EQU 0xF4
CS_PIO_AC .EQU 0xF6
CS_I2C_S1 .EQU 0xF3
CS_I2C_SX .EQU 0xF2
iic_init:
LD A,0xCF
OUT (CS_PIO_AC), A
LD A,11110101b
OUT (CS_PIO_AC), A
LD A,00000000b ; Reset PCF8584 minimum 30 clock cycles
OUT (CS_PIO_AD), A
LD BC,0x1000
CALL _pause_loop
LD A,0000010b
OUT (CS_PIO_AD), A
LD BC,0x2000
CALL _pause_loop
LD A, 0x80 ;S1 -> Select S0, PIN disabled, ESO = 0, Interrupt disabled, STA, STA, ACK = 0
OUT (CS_I2C_S1),A
CALL _slow_access
;CALL _slow_access
LD A,0x55 ;S0 -> Loads byte 55H into register S0'; effective own address becomes AAH
OUT (CS_I2C_SX),A
CALL _slow_access
LD A, 0xA0 ;S1 -> Loads byte A0H into register S1, i.e. next byte will be loaded into the clock control register S2.
OUT (CS_I2C_S1),A
CALL _slow_access
; 000100000
LD A,0x18 ;Load 18H into S2 register (clock control - 4.43 MHz, 90 KHz)
LD A,0x00 ;Load 18H into S2 register (clock control - 4.43 MHz, 90 KHz)
OUT (CS_I2C_SX),A
CALL _slow_access
;CALL _slow_access
;CALL _slow_access
;CALL _slow_access
LD A,0xC1 ;S1 -> loads byte C1H into register S1; register enable
;serial interface, set I 2C-bus into idle mode;
;SDA and SCL are HIGH. The next write or read
;operation will be to/from data transfer register
;S0 if A0 = LOW.;
OUT (CS_I2C_S1),A
CALL _slow_access
RET
;------------------------------------------------------------------------------
; iic_send
;
; Sends data over the i2c bus
; A contains BYTE COUNTER
; B contains ADDRESS
; DE contains location of Data Buffer
;------------------------------------------------------------------------------
iic_send:
;CALL PRINTINLINE;
;defb "SEND A",10,13,0
PUSH BC
PUSH AF
CALL iic_bus_rdy
;CALL PRINTINLINE
;defb "SEND START",10,13,0
LD A,B ;Load 'slave address' into S0 register:
OUT (CS_I2C_SX),A
CALL _slow_access
LD A, 0xC5 ;Load C5H into S1. 'C5H' = PCF8584 generates
;the 'START' condition and clocks out the slave
;address and the clock pulse for slave acknowledgement.
OUT (CS_I2C_S1),A
POP AF
LD C,A
INC C
_iic_send_1: ; LOOP 1 : Wait for bus ready
IN A,(CS_I2C_S1) ; Read byte from S1 register
BIT 7,A ; Is bus free? (S1 ~BB=1?)
JR NZ,_iic_send_1 ; No - loop
BIT 4,A ; slave acknowledged? (LRB = 0?)
JR NZ, _iic_send_stop ; if not, cancel transmission
LD A,(DE) ; Load next byte from buffer
INC DE
DEC C
JR Z, _iic_send_stop ; if counter = 0, exit loop
OUT (CS_I2C_SX),A ; Send byte
JR _iic_send_1 ; if counter > 0, loop again
_iic_send_stop:
LD A, 0xC3 ;STOP
OUT (CS_I2C_S1),A
CALL _slow_access
POP BC
RET
;------------------------------------------------------------------------------
; iic_read
;
; Sends data over the i2c bus
; A contains BYTE COUNTER
; B contains ADDRESS
; DE contains location of Data Buffer
;------------------------------------------------------------------------------
iic_read:
PUSH DE
PUSH BC
PUSH AF
LD A,B ;Load 'slave address' into S0 register:
OR 0x01 ;Set RW Bit for read operation
OUT (CS_I2C_SX),A
CALL _slow_access
CALL iic_bus_rdy ; Is bus ready
LD A, 0xC5 ;Load C5H into S1. 'C5H' = PCF8584 generates
;the 'START' condition and clocks out the slave
;address and the clock pulse for slave acknowledgement.
OUT (CS_I2C_S1),A
;Setup counter
POP AF
LD C,A ; Load BYTE COUNTER into C
INC C ; Offset C by 1
_iic_read_1: ;Wait for PIN = 0
IN A,(CS_I2C_S1) ; Read byte from S1 register
BIT 7,A ; S1 PIN=1?
JR NZ,_iic_read_1 ; No - loop
BIT 3,A ; S1 LRB=0? slave ACK?
JR NZ, _iic_read_error ; No ACK -> an error has occured
DEC C
LD A, C
DEC A ;If n = m 1?
JR Z, _iic_read_last
IN A,(CS_I2C_SX)
LD (DE),A
INC DE
JR _iic_read_1
_iic_read_last: ;read last byte
LD A, 0x40
OUT (CS_I2C_S1),A
CALL _slow_access
IN A,(CS_I2C_SX) ;receives the final data byte. Neg. ACK is also sent.
LD (DE),A
INC DE
_iic_read_last_1:
IN A,(CS_I2C_S1) ; Read byte from S1 register
BIT 7,A ; S1 PIN=1?
JR NZ,_iic_read_last_1 ; No - loop
_iic_read_error:
NOP
_iic_read_stop:
LD A, 0xC3
OUT (CS_I2C_S1),A
CALL _slow_access
IN A,(CS_I2C_SX) ;transfers the final data byte from the
;data buffer to accumulator.
CALL _slow_access
LD (DE),A
POP BC
POP DE
RET
;------------------------------------------------------------------------------
; iic_rdy
;
; Waits until the PCF8584 signals a byte transmission/reception is complete.
;------------------------------------------------------------------------------
iic_rdy:
PUSH AF
_iic_rdy_loop:
IN A,(CS_I2C_S1) ; Read byte from S1 register
BIT 7,A ; Is Tx/Rx complete? (S1 PIN=0?)
;call print_a_hex
JR NZ,_iic_rdy_loop ; No - loop
_iic_rdy_done:
POP AF
RET
;------------------------------------------------------------------------------
; i2c_bus_rdy
;
; Waits until the I2C bus is free before RETurning
;------------------------------------------------------------------------------
iic_bus_rdy:
PUSH AF
_iic_blp:
IN A,(CS_I2C_S1) ; Read byte from S1 register
PUSH AF
call print_a_hex
POP AF
BIT 0,A ; Is bus free? (S1 ~BB=1?)
JR Z,_iic_blp ; No - loop
POP AF
RET
;------------------------------------------------------------------------------
; _pause_loop
;
; Timer function
;
; 16-bit (BC) decrement counter, performing 4xNEG loop until BC
; reaches zero.
;
; 61 T-states in loop = 15.25uS per loop @ 4 MHz - near enough
; a second delay for 65,535 iterations.
;
; Set iteration count in BC before calling this function.
; Destroys: BC
;------------------------------------------------------------------------------
_pause_loop:
PUSH AF ; 11 T-states
_pause_loop_lp:
;NEG ; 8 T-states
;NEG ; 8 T-states
;NEG ; 8 T-states
;NEG ; 8 T-states
PUSH BC ; 11 T-states
POP BC ; 10 T-states
PUSH BC ; 11 T-states
POP BC ; 10 T-states
DEC BC ; 6 T-states
LD A,C ; 9 T-states
OR B ; 4 T-states
JP NZ,_pause_loop_lp ; 10 T-states
POP AF ; 10 T-states
RET ; Pause complete, RETurn
iic_force_stop:
IN A,(CS_I2C_S1)
BIT 0, A
RET NZ
LD A, 11000011b
OUT (CS_I2C_S1),A
NOP
NOP
JR iic_force_stop
_slow_access:
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
PUSH AF
POP AF
PUSH AF
POP AF
PUSH AF
POP AF
PUSH AF
POP AF
PUSH AF
POP AF
PUSH AF
POP AF
POP AF
RET