423 lines
8.0 KiB
NASM
423 lines
8.0 KiB
NASM
|
|
; ***************************************************************************
|
|
; defines
|
|
|
|
.equ TWI_BIT_LENGTH = 10000 ; 100000 and 200000 works for display: 10000, 100000, 200000
|
|
|
|
|
|
|
|
; ***************************************************************************
|
|
; data
|
|
|
|
.dseg
|
|
|
|
twiMasterDataBegin:
|
|
twiMasterScanEnabled: .byte 1
|
|
twiMasterLastScanned: .byte 1
|
|
twiMasterDataEnd:
|
|
|
|
|
|
|
|
; ***************************************************************************
|
|
; code
|
|
|
|
.cseg
|
|
|
|
|
|
|
|
; ---------------------------------------------------------------------------
|
|
; macros
|
|
|
|
.macro twiClockHi
|
|
cbi TWI_DDR_SCL, TWI_PINNUM_SCL ; set to input
|
|
cbi TWI_PORT_SCL, TWI_PINNUM_SCL ; disable internal pullup
|
|
.endmacro
|
|
|
|
|
|
.macro twiClockLo
|
|
sbi TWI_DDR_SCL, TWI_PINNUM_SCL ; set to output
|
|
cbi TWI_PORT_SCL, TWI_PINNUM_SCL ; set to low
|
|
.endmacro
|
|
|
|
|
|
.macro twiDataHi
|
|
cbi TWI_DDR_SDA, TWI_PINNUM_SDA ; set to input
|
|
cbi TWI_PORT_SDA, TWI_PINNUM_SDA ; disable internal pullup
|
|
.endmacro
|
|
|
|
|
|
.macro twiDataLo
|
|
sbi TWI_DDR_SDA, TWI_PINNUM_SDA ; set to output
|
|
cbi TWI_PORT_SDA, TWI_PINNUM_SDA ; set to low
|
|
.endmacro
|
|
|
|
|
|
; ---------------------------------------------------------------------------
|
|
; TWI_Master_Init
|
|
;
|
|
; IN:
|
|
; OUT:
|
|
; - CFLAG: set if okay, clear on error
|
|
; USED:
|
|
|
|
TWI_Master_Init:
|
|
twiClockHi
|
|
twiDataHi
|
|
|
|
; preset SRAM data area
|
|
ldi xh, HIGH(twiMasterDataBegin)
|
|
ldi xl, LOW(twiMasterDataBegin)
|
|
clr r16
|
|
ldi r17, (twiMasterDataEnd-twiMasterDataBegin)
|
|
rcall Utils_FillSram
|
|
|
|
sec
|
|
ret
|
|
|
|
|
|
|
|
; ---------------------------------------------------------------------------
|
|
; TWI_Master_Fini
|
|
;
|
|
; IN:
|
|
; OUT:
|
|
; USED:
|
|
|
|
TWI_Master_Fini:
|
|
sec
|
|
ret
|
|
|
|
|
|
|
|
; ---------------------------------------------------------------------------
|
|
; TWI_Master_Run
|
|
;
|
|
; IN:
|
|
; OUT:
|
|
; USED:
|
|
|
|
TWI_Master_Run:
|
|
clc
|
|
ret
|
|
|
|
|
|
|
|
|
|
; ---------------------------------------------------------------------------
|
|
; twiStart
|
|
;
|
|
; Send START condition on the bus.
|
|
;
|
|
; IN:
|
|
; - nothing
|
|
; OUT:
|
|
; - nothing
|
|
; USED: R22
|
|
|
|
twiStart:
|
|
twiDataHi
|
|
Utils_WaitNanoSecs TWI_BIT_LENGTH, 0, r22
|
|
twiClockHi
|
|
Utils_WaitNanoSecs TWI_BIT_LENGTH, 0, r22
|
|
twiDataLo
|
|
Utils_WaitNanoSecs TWI_BIT_LENGTH, 0, r22
|
|
twiClockLo
|
|
Utils_WaitNanoSecs TWI_BIT_LENGTH, 0, r22
|
|
ret
|
|
|
|
|
|
|
|
; ---------------------------------------------------------------------------
|
|
; twiStop
|
|
;
|
|
; Send STOP condition on the bus.
|
|
;
|
|
; IN:
|
|
; - nothing
|
|
; OUT:
|
|
; - nothing
|
|
; USED: R22
|
|
|
|
twiStop:
|
|
twiDataLo
|
|
Utils_WaitNanoSecs TWI_BIT_LENGTH, 0, r22
|
|
twiClockHi
|
|
Utils_WaitNanoSecs TWI_BIT_LENGTH, 0, r22
|
|
twiDataHi
|
|
Utils_WaitNanoSecs TWI_BIT_LENGTH, 0, r22
|
|
ret
|
|
|
|
|
|
|
|
; ---------------------------------------------------------------------------
|
|
; twiRestart
|
|
;
|
|
; Send START condition again (needed for some chips to send address in write mode
|
|
; and receive data afterwards in read mode).
|
|
;
|
|
; IN:
|
|
; - nothing
|
|
; OUT:
|
|
; - nothing
|
|
; USED: R22
|
|
|
|
|
|
twiRestart:
|
|
twiDataHi
|
|
twiClockHi
|
|
rjmp twiStart
|
|
|
|
|
|
|
|
; ---------------------------------------------------------------------------
|
|
; twiReadBit
|
|
;
|
|
; Read a bit from the line (handling SCL line and possible clock stretching).
|
|
;
|
|
; IN:
|
|
; - nothing
|
|
; OUT:
|
|
; - CARRY flag set: okay, cleared on error
|
|
; - R16: bit read (if CARRY flag set), i.e. 0x00 or 0x01
|
|
; USED: R16, R22
|
|
|
|
twiReadBit:
|
|
twiDataHi
|
|
Utils_WaitNanoSecs TWI_BIT_LENGTH, 0, r22
|
|
twiClockHi
|
|
Utils_WaitNanoSecs TWI_BIT_LENGTH, 0, r22
|
|
ldi r16, 100
|
|
twiReadBit_loop:
|
|
sbic TWI_PIN_SCL, TWI_PINNUM_SCL
|
|
rjmp twiReadBit_clockReleased
|
|
Utils_WaitNanoSecs TWI_BIT_LENGTH/20, 0, r22
|
|
dec r16
|
|
brne twiReadBit_loop
|
|
; timeout
|
|
clc
|
|
ret
|
|
twiReadBit_clockReleased:
|
|
Utils_WaitNanoSecs TWI_BIT_LENGTH, 0, r22
|
|
ldi r16, 1
|
|
sbis TWI_PIN_SDA, TWI_PINNUM_SDA
|
|
clr r16
|
|
Utils_WaitNanoSecs TWI_BIT_LENGTH, 0, r22
|
|
twiClockLo
|
|
Utils_WaitNanoSecs TWI_BIT_LENGTH, 0, r22
|
|
sec
|
|
ret
|
|
|
|
|
|
|
|
; ---------------------------------------------------------------------------
|
|
; twiWriteBit
|
|
;
|
|
; Write a bit from the line (handling SCL and SDA line and possible clock stretching).
|
|
;
|
|
; IN:
|
|
; - R16: bit to send (either 0x00 or 0x01)
|
|
; OUT:
|
|
; - CARRY flag set: okay, cleared on error
|
|
; USED: R16, R22
|
|
|
|
twiWriteBit:
|
|
twiClockLo
|
|
Utils_WaitNanoSecs TWI_BIT_LENGTH, 0, r22
|
|
tst r16
|
|
breq twiWriteBit_write0
|
|
twiDataHi
|
|
rjmp twiWriteBit_written
|
|
twiWriteBit_write0:
|
|
twiDataLo
|
|
twiWriteBit_written:
|
|
Utils_WaitNanoSecs TWI_BIT_LENGTH, 0, r22
|
|
twiClockHi
|
|
Utils_WaitNanoSecs TWI_BIT_LENGTH, 0, r22
|
|
ldi r16, 100
|
|
twiWriteBit_loop:
|
|
sbic TWI_PIN_SCL, TWI_PINNUM_SCL
|
|
rjmp twiWriteBit_clockReleased
|
|
Utils_WaitNanoSecs TWI_BIT_LENGTH/20, 0, r22
|
|
dec r16
|
|
brne twiWriteBit_loop
|
|
; timeout
|
|
clc
|
|
ret
|
|
twiWriteBit_clockReleased:
|
|
Utils_WaitNanoSecs TWI_BIT_LENGTH, 0, r22
|
|
twiClockLo
|
|
Utils_WaitNanoSecs TWI_BIT_LENGTH, 0, r22
|
|
sec
|
|
ret
|
|
|
|
|
|
|
|
; ---------------------------------------------------------------------------
|
|
; twiSendByte
|
|
;
|
|
; Write a byte to the bus and reads the ACK bit back.
|
|
;
|
|
; IN:
|
|
; - R16: byte to send
|
|
; OUT:
|
|
; - CARRY flag set: okay, cleared on error
|
|
; - R16: ACK bit read (0x00 or 0x01)
|
|
; USED: R16, R17, R18, R22
|
|
|
|
twiSendByte:
|
|
mov r17, r16
|
|
ldi r18, 8
|
|
twiSendByte_loop:
|
|
clr r16
|
|
lsl r17 ; shift MSB out into carry flag
|
|
rol r16 ; shift carry flag into r16
|
|
rcall twiWriteBit ; (R16, R22)
|
|
brcc twiSendByte_error
|
|
dec r18
|
|
brne twiSendByte_loop
|
|
rcall twiReadBit ; r16: ACK bit received
|
|
brcc twiSendByte_error
|
|
sec
|
|
ret
|
|
twiSendByte_error:
|
|
clc
|
|
ret
|
|
|
|
|
|
|
|
; ---------------------------------------------------------------------------
|
|
; twiSendByteExpectAck
|
|
;
|
|
; Write a byte to the bus and expect ACK response.
|
|
;
|
|
; IN:
|
|
; - R16: byte to send
|
|
; OUT:
|
|
; - CARRY flag set: okay, cleared on error (including case of non-ACK response)
|
|
; USED: R16, R17, R18, R22
|
|
|
|
twiSendByteExpectAck:
|
|
rcall twiSendByte
|
|
brcc twiSendByteExpectAck_error
|
|
tst r16
|
|
brne twiSendByteExpectAck_error
|
|
sec
|
|
ret
|
|
twiSendByteExpectAck_error:
|
|
clc
|
|
ret
|
|
|
|
|
|
|
|
; ---------------------------------------------------------------------------
|
|
; twiReceiveByte
|
|
;
|
|
; Read a byte from the bus. Does not send an ACK bit, this must be done by the caller,
|
|
; if required.
|
|
;
|
|
; IN:
|
|
; OUT:
|
|
; - CARRY flag set: okay, cleared on error
|
|
; - R16: byte received
|
|
; USED: R16, R17, R18, R22
|
|
|
|
twiReceiveByte:
|
|
clr r17
|
|
ldi r18, 8
|
|
twiReceiveByte_loop:
|
|
rcall twiReadBit
|
|
brcc twiReceiveByte_error
|
|
lsr r16
|
|
rol r17
|
|
dec r18
|
|
brne twiReceiveByte_loop
|
|
mov r16, r17
|
|
sec
|
|
ret
|
|
twiReceiveByte_error:
|
|
clc
|
|
ret
|
|
|
|
|
|
|
|
; ---------------------------------------------------------------------------
|
|
; twiReceiveByteSendAck
|
|
;
|
|
; Read a byte from the bus. Sends ACK bit.
|
|
;
|
|
; IN:
|
|
; OUT:
|
|
; - CARRY flag set: okay, cleared on error
|
|
; - R16: byte received
|
|
; USED: R16, R17, R18, R22
|
|
|
|
twiReceiveByteSendAck:
|
|
rcall twiReceiveByte
|
|
brcc twiReceiveByteSendAck_error
|
|
push r16
|
|
clr r16
|
|
rcall twiWriteBit ; send ACK (R16, R22)
|
|
pop r16
|
|
sec
|
|
ret
|
|
twiReceiveByteSendAck_error:
|
|
clc
|
|
ret
|
|
|
|
|
|
|
|
TWI_Master_ScanNext:
|
|
in r15, SREG
|
|
cli
|
|
lds r16, twiMasterScanEnabled
|
|
tst r16
|
|
breq TWI_Master_ScanNext_end
|
|
lds r16, twiMasterLastScanned
|
|
tst r16
|
|
brne TWI_Master_ScanNext_inc
|
|
ldi r16, 7
|
|
TWI_Master_ScanNext_inc:
|
|
inc r16
|
|
cpi r16, 121
|
|
breq TWI_Master_ScanNext_finshed
|
|
; check current address
|
|
mov r21, r16
|
|
rcall twiStart
|
|
sec
|
|
rol r16 ; (ADDR<<1) + 1: read from address
|
|
rcall twiSendByte
|
|
brcc TWI_Master_ScanNext_abort ; clock stretching too long, bus error
|
|
sts twiMasterLastScanned, r21
|
|
rcall twiStop
|
|
tst r16
|
|
brne TWI_Master_ScanNext_noAnswer
|
|
; send message about available address
|
|
mov r1, r21
|
|
ldi r16, 1
|
|
mov r2, r16
|
|
ldi r16, 255 ; send to all
|
|
push r15
|
|
rcall COM_EnqueueI2cBusMember
|
|
pop r15
|
|
rjmp TWI_Master_ScanNext_end
|
|
TWI_Master_ScanNext_noAnswer:
|
|
; send message about available address
|
|
; mov r1, r21
|
|
; clr r2
|
|
; ldi r16, 255 ; send to all
|
|
; push r15
|
|
; rcall COM_EnqueueI2cBusMember
|
|
; pop r15
|
|
rjmp TWI_Master_ScanNext_end
|
|
TWI_Master_ScanNext_abort:
|
|
rcall twiStop
|
|
rjmp TWI_Master_ScanNext_end
|
|
TWI_Master_ScanNext_finshed:
|
|
clr r16
|
|
sts twiMasterScanEnabled, r16
|
|
TWI_Master_ScanNext_end:
|
|
out SREG, r15
|
|
ret
|
|
|
|
|