390 lines
8.5 KiB
NASM
390 lines
8.5 KiB
NASM
; ***************************************************************************
|
|
; copyright : (C) 2025 by Martin Preuss
|
|
; email : martin@libchipcard.de
|
|
;
|
|
; ***************************************************************************
|
|
; * This file is part of the project "AqHome". *
|
|
; * Please see toplevel file COPYING of that project for license details. *
|
|
; ***************************************************************************
|
|
|
|
|
|
|
|
; ***************************************************************************
|
|
; defines
|
|
|
|
.equ SI7021_FLAGS_PRESENT_BIT = 7
|
|
|
|
.equ SI7021_FLAGS_PRESENT = 0x80
|
|
.equ SI7021_FLAGS_TEMP_VALID = 0x40
|
|
.equ SI7021_FLAGS_HUM_VALID = 0x20
|
|
.equ SI7021_FLAGS_LASTWASTEMP = 0x10
|
|
.equ SI7021_FLAGS_ERROR_MASK = 0x07
|
|
|
|
|
|
.equ SI7021_VALUE_TEMP = 0x01
|
|
.equ SI7021_VALUE_HUMIDITY = 0x02
|
|
|
|
|
|
; ***************************************************************************
|
|
; data
|
|
|
|
.dseg
|
|
|
|
si7021DataBegin:
|
|
si7021Flags: .byte 1
|
|
si7021FirmwareRevision: .byte 1
|
|
si7021LastTemp: .byte 2
|
|
si7021LastHumidity: .byte 2
|
|
si7021DataEnd:
|
|
|
|
|
|
|
|
; ***************************************************************************
|
|
; code
|
|
|
|
.cseg
|
|
|
|
|
|
SI7021_BEGIN:
|
|
|
|
|
|
|
|
; ---------------------------------------------------------------------------
|
|
; SI7021_Init
|
|
;
|
|
; IN:
|
|
; - nothing
|
|
; OUT:
|
|
; - CFLAG: set if okay, clear on error
|
|
; USED:
|
|
|
|
SI7021_Init:
|
|
ldi xh, HIGH(si7021DataBegin)
|
|
ldi xl, LOW(si7021DataBegin)
|
|
clr r16
|
|
ldi r17, (si7021DataEnd-si7021DataBegin)
|
|
rcall Utils_FillSram
|
|
; check presence
|
|
rcall si7021CheckPresence
|
|
brcc SI7021_Init_error
|
|
lds r16, si7021Flags
|
|
ori r16, SI7021_FLAGS_PRESENT
|
|
sts si7021Flags, r16
|
|
; get firmware revision
|
|
; rcall si7021ReadFirmwareRevision
|
|
; brcc SI7021_Init_error
|
|
; sts si7021FirmwareRevision, r16
|
|
sec
|
|
ret
|
|
SI7021_Init_error:
|
|
clc
|
|
ret
|
|
|
|
|
|
; ---------------------------------------------------------------------------
|
|
; SI7021_Fini
|
|
;
|
|
; IN:
|
|
; - nothing
|
|
; OUT:
|
|
; - CFLAG: set if okay, clear on error
|
|
; USED:
|
|
|
|
SI7021_Fini:
|
|
sec
|
|
ret
|
|
|
|
|
|
|
|
SI7021_MeasureTemp:
|
|
in r15, SREG
|
|
push r15
|
|
cli
|
|
lds r17, si7021Flags
|
|
sbrs r17, SI7021_FLAGS_PRESENT_BIT ; investigate PRESENT BIT
|
|
rjmp SI7021_MeasureTemp_error ; jmp if PRESENT bit clear
|
|
push r17
|
|
rcall si7021MeasureTemp
|
|
pop r17
|
|
brcc SI7021_MeasureTemp_error
|
|
ori r17, SI7021_FLAGS_TEMP_VALID
|
|
sts si7021Flags, r17
|
|
rcall si7021CalcTemp
|
|
sts si7021LastTemp, r18
|
|
sts si7021LastTemp+1, r19
|
|
SI7021_MeasureTemp_done:
|
|
pop r15
|
|
out SREG, r15
|
|
sec
|
|
ret
|
|
SI7021_MeasureTemp_error:
|
|
pop r15
|
|
out SREG, r15
|
|
clc
|
|
ret
|
|
; @end
|
|
|
|
|
|
|
|
SI7021_MeasureHumidity:
|
|
in r15, SREG
|
|
push r15
|
|
cli
|
|
lds r17, si7021Flags
|
|
sbrs r17, SI7021_FLAGS_PRESENT_BIT ; investigate PRESENT BIT
|
|
rjmp SI7021_MeasureHumidity_error ; jmp if PRESENT bit clear
|
|
push r17
|
|
rcall si7021MeasureHumidity
|
|
pop r17
|
|
brcc SI7021_MeasureHumidity_error
|
|
ori r17, SI7021_FLAGS_HUM_VALID
|
|
sts si7021Flags, r17
|
|
rcall si7021CalcHumidity ;
|
|
sts si7021LastHumidity, r18
|
|
sts si7021LastHumidity+1, r19
|
|
SI7021_MeasureHumidity_done:
|
|
pop r15
|
|
out SREG, r15
|
|
sec
|
|
ret
|
|
SI7021_MeasureHumidity_error:
|
|
pop r15
|
|
out SREG, r15
|
|
clc
|
|
ret
|
|
; @end
|
|
|
|
|
|
|
|
; ---------------------------------------------------------------------------
|
|
; si7021CheckPresence
|
|
;
|
|
; Expects interrupts being disabled!
|
|
;
|
|
; IN:
|
|
; - nothing
|
|
; OUT:
|
|
; - CFLAG: set if okay, clear on error
|
|
; USED:
|
|
|
|
si7021CheckPresence:
|
|
rcall twiStart
|
|
ldi r16, (SI7021_ADDR*2)+1
|
|
rcall twiSendByte
|
|
brcc si7021CheckPresence_notfound
|
|
rcall twiStop
|
|
sec
|
|
ret
|
|
|
|
si7021CheckPresence_notfound:
|
|
rcall twiStop
|
|
clc
|
|
ret
|
|
|
|
|
|
|
|
; ---------------------------------------------------------------------------
|
|
; si7021MeasureTemp
|
|
;
|
|
; IN:
|
|
; - nothing
|
|
; OUT:
|
|
; - CFLAG: set if okay, clear on error
|
|
; USED:
|
|
|
|
si7021MeasureTemp:
|
|
ldi r16, 0xf3
|
|
rjmp si7021MeasureAny
|
|
|
|
|
|
|
|
; ---------------------------------------------------------------------------
|
|
; si7021MeasureHumidity
|
|
;
|
|
; IN:
|
|
; - nothing
|
|
; OUT:
|
|
; - CFLAG: set if okay, clear on error
|
|
; USED:
|
|
|
|
si7021MeasureHumidity:
|
|
ldi r16, 0xf5
|
|
rjmp si7021MeasureAny
|
|
|
|
|
|
|
|
; ---------------------------------------------------------------------------
|
|
; si7021MeasureAny
|
|
;
|
|
; Sends the given command to the sensor and reads the result.
|
|
; Synchronization is done by sending re-start sequences until the sensor answers with
|
|
; the value.
|
|
; IN:
|
|
; - R16: command to send
|
|
; OUT:
|
|
; - CFLAG: set if okay, clear on error
|
|
; USED: R14, R16, R18, R19
|
|
|
|
si7021MeasureAny:
|
|
rcall twiStart ; (R22)
|
|
push r16
|
|
ldi r16, (SI7021_ADDR*2) ; write access
|
|
rcall twiSendByteExpectAck ; (R16, R17, R18, R22)
|
|
pop r16
|
|
brcc si7021MeasureAny_error
|
|
rcall twiSendByteExpectAck ; (R16, R17, R18, R22)
|
|
brcc si7021MeasureAny_error ; no ACK or other error
|
|
|
|
ldi r16, 200
|
|
mov r14, r16
|
|
si7021MeasureAny_loop: ; (R22)
|
|
rcall twiRestart
|
|
ldi r16, (SI7021_ADDR*2)+1 ; read access
|
|
rcall twiSendByteExpectAck ; (R16, R17, R18, R22)
|
|
brcs si7021MeasureAny_gotValue ; chip responds, receive values
|
|
dec r14
|
|
breq si7021MeasureAny_error ; timeout
|
|
rcall Utils_WaitFor50MicroSecs ; wait for 100usecs total
|
|
rcall Utils_WaitFor50MicroSecs
|
|
rjmp si7021MeasureAny_loop
|
|
|
|
si7021MeasureAny_gotValue:
|
|
rcall twiReceiveByteSendAck ; (R16, R17, R18, R22)
|
|
brcc si7021MeasureAny_error
|
|
mov r19, r16 ; MSByte
|
|
rcall twiReceiveByte ; no ACK (R16, R17, R18, R22)
|
|
brcc si7021MeasureAny_error
|
|
mov r18, r16
|
|
rcall twiStop ; (R22)
|
|
ldi r16, 0
|
|
rcall si7021SetError ; (none)
|
|
sec
|
|
ret
|
|
si7021MeasureAny_error:
|
|
rcall twiStop ; (R22)
|
|
clc
|
|
ret
|
|
|
|
|
|
|
|
; ---------------------------------------------------------------------------
|
|
; si7021SetError
|
|
;
|
|
; Set error code in flags.
|
|
; IN:
|
|
; - R16: error code to set (0-7)
|
|
; OUT:
|
|
; - CFLAG: set if okay, clear on error
|
|
; USED: none
|
|
|
|
|
|
si7021SetError:
|
|
push r17
|
|
lds r17, si7021Flags
|
|
andi r17, ~SI7021_FLAGS_ERROR_MASK
|
|
or r17, r16
|
|
sts si7021Flags, r17
|
|
pop r17
|
|
ret
|
|
|
|
|
|
|
|
; ---------------------------------------------------------------------------
|
|
; si7021CalcTemp
|
|
;
|
|
; Calculates temperatur * 100.
|
|
; Uses formula from specs: temp=(175.72*TEMP_CODE/65536)-46.85.
|
|
;
|
|
; IN:
|
|
; - R19:R18: Temperature value read from sensor
|
|
; OUT:
|
|
; - R19:R18: calculated temperature(Celsius) * 100
|
|
; USED: R16, R17, R18, R19, R20, R21, R22, R23, R24, R25, R26
|
|
|
|
si7021CalcTemp:
|
|
mov r20, r18
|
|
mov r21, r19
|
|
ldi r23, HIGH(17572)
|
|
ldi r22, LOW(17572)
|
|
rcall Utils_Mulu16x16_32 ; result is in R19:R18:R17:R16, we only use R19-R18 -> /65536
|
|
ldi r16, LOW(4685)
|
|
ldi r17, HIGH(4685)
|
|
sub r18, r16
|
|
sbc r19, r17
|
|
ret
|
|
|
|
|
|
|
|
; ---------------------------------------------------------------------------
|
|
; si7021CalcHumidity
|
|
;
|
|
; Calculates humidity in percent.
|
|
; Uses formula from specs: rel humidity=(125*HUMIDITY_CODE/65536)-6.
|
|
;
|
|
; IN:
|
|
; - R19:R18: Humidity value read from sensor
|
|
; OUT:
|
|
; - R19:R18: calculated relative humidity
|
|
; USED: R16, R17, R18, R19, R20, R21, R22, R23, R24, R25, R26
|
|
|
|
si7021CalcHumidity:
|
|
mov r20, r18
|
|
mov r21, r19
|
|
clr r23
|
|
ldi r22, 125
|
|
rcall Utils_Mulu16x16_32 ; result is in R19:R18:R17:R16, we only use R19-R18 -> /65536
|
|
ldi r16, 6
|
|
clr r17
|
|
sub r18, r16
|
|
sbc r19, r17
|
|
ret
|
|
|
|
|
|
|
|
; ---------------------------------------------------------------------------
|
|
; @routine SI7021_GetValue @global
|
|
;
|
|
; @param R16 value to get (SI7021_VALUE_TEMP, SI7021_VALUE_HUMIDITY)
|
|
; @return CFLAG set if value available, cleared otherwise
|
|
; @return R19:R18 value
|
|
; @return R21:R20 denom (e.g. 100, meaning value must be divided by 100)
|
|
; @clobbers R16
|
|
|
|
SI7021_GetValue:
|
|
cpi r16, SI7021_VALUE_TEMP
|
|
breq SI7021_GetValue_temp
|
|
cpi r16, SI7021_VALUE_HUMIDITY
|
|
breq SI7021_GetValue_hum
|
|
SI7021_GetValue_clcRet:
|
|
clc
|
|
ret
|
|
SI7021_GetValue_temp:
|
|
lds r16, si7021Flags
|
|
andi r16, SI7021_FLAGS_TEMP_VALID
|
|
breq SI7021_GetValue_clcRet
|
|
lds r18, si7021LastTemp ; value
|
|
lds r19, si7021LastTemp+1
|
|
ldi r20, 100 ; denominator
|
|
rjmp SI7021_GetValue_finishValue
|
|
SI7021_GetValue_hum:
|
|
lds r16, si7021Flags
|
|
andi r16, SI7021_FLAGS_HUM_VALID
|
|
breq SI7021_GetValue_clcRet
|
|
lds r18, si7021LastHumidity ; value
|
|
lds r19, si7021LastHumidity+1
|
|
ldi r20, 1 ; denominator
|
|
SI7021_GetValue_finishValue:
|
|
clr r21
|
|
sec
|
|
ret
|
|
; @end
|
|
|
|
|
|
|
|
|
|
|
|
SI7021_END:
|
|
.equ MODULE_SIZE_SI7021 = SI7021_END-SI7021_BEGIN
|
|
|
|
|