327 lines
8.3 KiB
NASM
327 lines
8.3 KiB
NASM
.include "extern_symbols.s" ;include monitor symbols.
|
||
org 0xB000
|
||
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_RTC equ 11010000b
|
||
|
||
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
|
||
|
||
NOP
|
||
NOP
|
||
NOP
|
||
|
||
LD A, 0x80 ;S1 -> Select S0, PIN disabled, ESO = 0, Interrupt disabled, STA, STA, ACK = 0
|
||
OUT (CS_I2C_S1),A
|
||
CALL SlowAccess
|
||
CALL SlowAccess
|
||
|
||
LD A,0x55 ;S0 -> Loads byte 55H into register S0'; effective own address becomes AAH
|
||
OUT (CS_I2C_SX),A
|
||
CALL SlowAccess
|
||
|
||
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 SlowAccess
|
||
|
||
|
||
LD A,0x00 ;Load 18H into S2 register (clock control - 8 MHz, 90 KHz)
|
||
OUT (CS_I2C_SX),A
|
||
CALL SlowAccess
|
||
|
||
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 SlowAccess
|
||
|
||
|
||
|
||
;CALL force_stop
|
||
JP PROMPT_BEGIN
|
||
|
||
LD BC,$0100
|
||
CALL PAUSE_LOOP
|
||
|
||
|
||
; Send test message to RTC
|
||
|
||
LD DE, 0xC000 ; Set I2C Buffer Location
|
||
LD A,0x00
|
||
LD (DE),A
|
||
;call regdump
|
||
|
||
LD B, IIC_RTC ; Set I2C Address
|
||
LD A, 1 ; Set I2C Buffer length
|
||
call i2c_send
|
||
|
||
LD DE, 0xC010
|
||
LD B, IIC_RTC
|
||
LD A, 7
|
||
call i2c_read
|
||
|
||
|
||
|
||
JP PROMPT_BEGIN
|
||
|
||
|
||
;CLK_ENABLE:
|
||
; LD DE, 0xC000 ; Set I2C Buffer Location
|
||
; LD A,0x00
|
||
; LD (0xC000),A
|
||
; LD (0xC001),A
|
||
; ;call regdump
|
||
;
|
||
; LD B, IIC_RTC ; Set I2C Address
|
||
; LD A, 2 ; Set I2C Buffer length
|
||
; call i2c_send
|
||
; JP PROMPT_BEGIN
|
||
|
||
;------------------------------------------------------------------------------
|
||
; i2c_send
|
||
;
|
||
; Sends data over the i2c bus
|
||
; A contains BYTE COUNTER
|
||
; B contains ADDRESS
|
||
; DE contains location of Data Buffer
|
||
;------------------------------------------------------------------------------
|
||
i2c_send:
|
||
; CALL PRINTINLINE;
|
||
; defb "SEND A",10,13,0
|
||
PUSH BC
|
||
PUSH AF
|
||
CALL i2c_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 SlowAccess
|
||
|
||
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
|
||
i2c_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,i2c_send_1 ; No - loop
|
||
BIT 4,A ; slave acknowledged? (LRB = 0?)
|
||
JR NZ, i2c_send_stop ; if not, cancel transmission
|
||
LD A,(DE) ; Load next byte from buffer
|
||
INC DE
|
||
DEC C
|
||
JR Z, i2c_send_stop ; if counter = 0, exit loop
|
||
OUT (CS_I2C_SX),A ; Send byte
|
||
JR i2c_send_1 ; if counter > 0, loop again
|
||
i2c_send_stop:
|
||
LD A, 0xC3 ;STOP
|
||
OUT (CS_I2C_S1),A
|
||
CALL SlowAccess
|
||
POP BC
|
||
RET
|
||
|
||
|
||
;------------------------------------------------------------------------------
|
||
; i2c_read
|
||
;
|
||
; Sends data over the i2c bus
|
||
; A contains BYTE COUNTER
|
||
; B contains ADDRESS
|
||
; DE contains location of Data Buffer
|
||
;------------------------------------------------------------------------------
|
||
i2c_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 SlowAccess
|
||
CALL i2c_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
|
||
i2c_read_1: ;Wait for PIN = 0
|
||
IN A,(CS_I2C_S1) ; Read byte from S1 register
|
||
BIT 7,A ; S1 PIN=1?
|
||
JR NZ,i2c_read_1 ; No - loop
|
||
BIT 3,A ; S1 LRB=0? slave ACK?
|
||
JR NZ, i2c_read_error ; No ACK -> an error has occured
|
||
DEC C
|
||
LD A, C
|
||
DEC A ;If n = m − 1?
|
||
JR Z, i2c_read_last
|
||
IN A,(CS_I2C_SX)
|
||
LD (DE),A
|
||
INC DE
|
||
JR i2c_read_1
|
||
i2c_read_last: ;read last byte
|
||
LD A, 0x40
|
||
OUT (CS_I2C_S1),A
|
||
CALL SlowAccess
|
||
IN A,(CS_I2C_SX) ;receives the final data byte. Neg. ACK is also sent.
|
||
LD (DE),A
|
||
INC DE
|
||
i2c_read_last_1:
|
||
IN A,(CS_I2C_S1) ; Read byte from S1 register
|
||
BIT 7,A ; S1 PIN=1?
|
||
JR NZ,i2c_read_last_1 ; No - loop
|
||
|
||
i2c_read_error:
|
||
NOP
|
||
i2c_read_stop:
|
||
LD A, 0xC3
|
||
OUT (CS_I2C_S1),A
|
||
CALL SlowAccess
|
||
IN A,(CS_I2C_SX) ;transfers the final data byte from the
|
||
;data buffer to accumulator.
|
||
CALL SlowAccess
|
||
LD (DE),A
|
||
POP BC
|
||
POP DE
|
||
RET
|
||
|
||
|
||
i2c_stop_force:
|
||
|
||
;------------------------------------------------------------------------------
|
||
; i2c_rdy
|
||
;
|
||
; Waits until the PCF8584 signals a byte transmission/reception is complete.
|
||
;------------------------------------------------------------------------------
|
||
i2c_rdy:
|
||
PUSH AF
|
||
i2c_rlp:
|
||
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,i2c_rlp ; No - loop
|
||
i2crlpex:
|
||
POP AF
|
||
RET
|
||
|
||
;------------------------------------------------------------------------------
|
||
; i2c_bus_rdy
|
||
;
|
||
; Waits until the I2C bus is free before RETurning
|
||
;------------------------------------------------------------------------------
|
||
i2c_bus_rdy:
|
||
PUSH AF
|
||
i2c_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,i2c_blp ; No - loop
|
||
i2cblpex:
|
||
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
|
||
pau_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,pau_lp ; 10 T-states
|
||
POP AF ; 10 T-states
|
||
RET ; Pause complete, RETurn
|
||
|
||
;------------------------------------------------------------------------------
|
||
; PRINTINLINE
|
||
;
|
||
; String output function
|
||
;
|
||
; Prints in-line data (bytes immediately following the PRINTINLINE call)
|
||
; until a string terminator is encountered (0 - null char).
|
||
;------------------------------------------------------------------------------
|
||
PRINTINLINE:
|
||
EX (SP),HL ; PUSH HL and put RET ADDress into HL
|
||
PUSH AF
|
||
PUSH BC
|
||
nxtILC:
|
||
LD A,(HL)
|
||
CP 0
|
||
JR Z,endPrint
|
||
CALL print_char
|
||
INC HL
|
||
JR nxtILC
|
||
endPrint:
|
||
INC HL ; Get past "null" terminator
|
||
POP BC
|
||
POP AF
|
||
EX (SP),HL ; PUSH new RET ADDress on stack and restore HL
|
||
RET
|
||
|
||
SlowAccess:
|
||
NOP
|
||
NOP
|
||
NOP
|
||
NOP
|
||
NOP
|
||
NOP
|
||
NOP
|
||
NOP
|
||
RET
|
||
|
||
|
||
;.include "regdump.s"
|
||
|
||
force_stop:
|
||
IN A,(CS_I2C_S1)
|
||
BIT 0, A
|
||
RET NZ
|
||
LD A, 11000011b
|
||
OUT (CS_I2C_S1),A
|
||
NOP
|
||
NOP
|
||
JR force_stop |