TWIMASTER: Added two-wire-master code (bitbang).
This commit is contained in:
372
avr/twimaster.asm
Normal file
372
avr/twimaster.asm
Normal file
@@ -0,0 +1,372 @@
|
||||
|
||||
; ***************************************************************************
|
||||
; defines
|
||||
|
||||
.equ TWI_BIT_LENGTH = 100000 ; 100000 and 200000 works for display
|
||||
|
||||
|
||||
|
||||
; ***************************************************************************
|
||||
; 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
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; 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
|
||||
|
||||
|
||||
|
||||
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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user