avr: added initial module to handle reed contacts.
Detects and reports opening and closing of a window/door. Nexts step is to allow for external configuration (e.g. standard mode with one reed contact versus multi-contact mode to detect tilting of a window/door).
This commit is contained in:
@@ -68,6 +68,7 @@
|
||||
#define MODULES_SI7021
|
||||
#define MODULES_STATS
|
||||
;#define MODULES_CNY70
|
||||
#define MODULES_REED
|
||||
|
||||
|
||||
.set MODULES_MASK = 0
|
||||
@@ -95,6 +96,9 @@
|
||||
#ifdef MODULES_CNY70
|
||||
.set MODULES_MASK = MODULES_MASK | (1<<AQHOME_FW_MODULE_CNY70)
|
||||
#endif
|
||||
#ifdef MODULES_REED
|
||||
.set MODULES_MASK = MODULES_MASK | (1<<AQHOME_FW_MODULE_REED)
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
@@ -108,6 +112,8 @@
|
||||
.equ VALUE_ID_HUM1 = 0x02
|
||||
|
||||
.equ VALUE_ID_ADC = 0x03
|
||||
.equ VALUE_ID_REED1 = 0x04
|
||||
.equ VALUE_ID_REED2 = 0x05
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
@@ -185,6 +191,28 @@
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; Reed
|
||||
;
|
||||
|
||||
.equ REEDOUT_DDR = DDRA
|
||||
.equ REEDOUT_PORT = PORTA
|
||||
.equ REEDOUT_PIN = PINA
|
||||
.equ REEDOUT_PINNUM = PORTA0
|
||||
|
||||
.equ REED1_DDR = DDRA
|
||||
.equ REED1_PORT = PORTA
|
||||
.equ REED1_PIN = PINA
|
||||
.equ REED1_PINNUM = PORTA2
|
||||
|
||||
.equ REED2_DDR = DDRA
|
||||
.equ REED2_PORT = PORTA
|
||||
.equ REED2_PIN = PINA
|
||||
.equ REED2_PINNUM = PORTA5
|
||||
|
||||
|
||||
|
||||
|
||||
; ***************************************************************************
|
||||
; code segment
|
||||
|
||||
@@ -270,6 +298,9 @@ firmwareStart: rjmp main
|
||||
#ifdef MODULES_CNY70
|
||||
.include "modules/cny70/main.asm"
|
||||
#endif
|
||||
#ifdef MODULES_REED
|
||||
.include "modules/reed/main.asm"
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
@@ -292,7 +323,10 @@ sramTimerEnqueueValues: .byte 2
|
||||
sramTimerCny70SendAdc: .byte 2
|
||||
#endif
|
||||
#ifdef MODULES_LCD
|
||||
sramPeriodicalLcdMark: .byte 2
|
||||
sramPeriodicalLcdMark: .byte 2
|
||||
#endif
|
||||
#ifdef MODULES_REED
|
||||
sramTimerReedCheck: .byte 2
|
||||
#endif
|
||||
|
||||
|
||||
@@ -331,6 +365,9 @@ timerList:
|
||||
#endif
|
||||
#ifdef MODULES_CNY70
|
||||
.dw sramTimerCny70SendAdc, sendAdc, TIMER_FLAGS_IF_ADDR, 30 ; every 30s
|
||||
#endif
|
||||
#ifdef MODULES_REED
|
||||
.dw sramTimerReedCheck, REED_Timer, TIMER_FLAGS_IF_ADDR, 1 ; every 1s
|
||||
#endif
|
||||
.dw 0 ; end of list
|
||||
|
||||
@@ -419,6 +456,10 @@ onEvery100ms:
|
||||
rcall CNY70_Every100ms
|
||||
#endif
|
||||
|
||||
#ifdef MODULES_REED
|
||||
rcall REED_Every100ms
|
||||
#endif
|
||||
|
||||
ret
|
||||
|
||||
|
||||
|
||||
10
avr/defs.asm
10
avr/defs.asm
@@ -12,6 +12,7 @@
|
||||
.equ AQHOME_VALUETYPE_UNKNOWN = 0
|
||||
.equ AQHOME_VALUETYPE_TEMP = 1
|
||||
.equ AQHOME_VALUETYPE_HUMIDITY = 2
|
||||
.equ AQHOME_VALUETYPE_DOOR = 3
|
||||
|
||||
|
||||
; module type ids for firmware header
|
||||
@@ -23,6 +24,7 @@
|
||||
.equ AQHOME_FW_MODULE_SI7021 = 6
|
||||
.equ AQHOME_FW_MODULE_STATS = 7
|
||||
.equ AQHOME_FW_MODULE_CNY70 = 8
|
||||
.equ AQHOME_FW_MODULE_REED = 9
|
||||
|
||||
|
||||
.equ AQHOME_FW_TYPE_ATT84_BASE = 0
|
||||
@@ -37,8 +39,10 @@
|
||||
; EEPROM positions
|
||||
|
||||
|
||||
.equ EEPROM_OFFS_UUID = 0 ; 4 bytes (occupy total of 8 bytes for extensibility)
|
||||
.equ EEPROM_OFFS_COMADDR = 8 ; 1 byte
|
||||
.equ EEPROM_OFFS_SEED = 10 ; 2 bytes
|
||||
.equ EEPROM_OFFS_UUID = 0 ; 4 bytes (occupy total of 8 bytes for extensibility)
|
||||
.equ EEPROM_OFFS_COMADDR = 8 ; 1 byte (plus one byte reserved)
|
||||
.equ EEPROM_OFFS_SEED = 10 ; 2 bytes
|
||||
|
||||
.equ EEPROM_OFFS_REED_CONF = 12 ; 1 byte (plus one byte reserved)
|
||||
; next is 14
|
||||
|
||||
|
||||
@@ -140,6 +140,10 @@ initModules:
|
||||
rcall CNY70_Init
|
||||
#endif
|
||||
|
||||
#ifdef MODULES_REED
|
||||
rcall REED_Init
|
||||
#endif
|
||||
|
||||
; done
|
||||
ret
|
||||
|
||||
@@ -181,6 +185,10 @@ runModulesUntilIdle_ComEnd:
|
||||
rcall Stats_Run
|
||||
#endif
|
||||
|
||||
#ifdef MODULES_REED
|
||||
rcall REED_Run
|
||||
#endif
|
||||
|
||||
; add more modules here
|
||||
ret
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
flash
|
||||
lcd
|
||||
led
|
||||
reed
|
||||
si7021
|
||||
stats
|
||||
timer
|
||||
|
||||
11
avr/modules/reed/0BUILD
Normal file
11
avr/modules/reed/0BUILD
Normal file
@@ -0,0 +1,11 @@
|
||||
<?xml?>
|
||||
|
||||
<gwbuild>
|
||||
|
||||
<extradist>
|
||||
main.asm
|
||||
</extradist>
|
||||
|
||||
</gwbuild>
|
||||
|
||||
|
||||
355
avr/modules/reed/main.asm
Normal file
355
avr/modules/reed/main.asm
Normal file
@@ -0,0 +1,355 @@
|
||||
; ***************************************************************************
|
||||
; copyright : (C) 2023 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. *
|
||||
; ***************************************************************************
|
||||
|
||||
|
||||
|
||||
; The state byte contains the state for two reed contacts (one in each nibble).
|
||||
;
|
||||
; bit meaning
|
||||
; ------------------------------
|
||||
; 0 last measurement
|
||||
; 1 measurement before last
|
||||
; 2 change occurred
|
||||
; 3 current stable state
|
||||
|
||||
|
||||
|
||||
; ***************************************************************************
|
||||
; defs
|
||||
|
||||
.equ REED_STATE_MASK_CURRENT = 0x8
|
||||
.equ REED_STATE_MASK_CHANGED = 0x4
|
||||
.equ REED_STATE_MASK_BEFORELAST = 0x2
|
||||
.equ REED_STATE_MASK_LAST = 0x1
|
||||
|
||||
.equ REED_STATE_MASK_LASTVALUES = 0x3 ; bits 0 and 1
|
||||
.equ REED_STATE_BIT_CURRENT = 3
|
||||
.equ REED_STATE_BIT_CHANGED = 2
|
||||
|
||||
|
||||
.equ REED_CONFIG_MASK_SET = 0x80
|
||||
.equ REED_CONFIG_MASK_MULTI = 0x40
|
||||
.equ REED_CONFIG_MASK_NO = 0x20 ; if set: normally open (e.g. disconnected when magnet near)
|
||||
|
||||
.equ REED_INITIAL_CONFIG = REED_CONFIG_MASK_SET
|
||||
|
||||
|
||||
|
||||
|
||||
; ***************************************************************************
|
||||
; data
|
||||
|
||||
.dseg
|
||||
|
||||
reedDataBegin:
|
||||
reedConfigFromEeprom: .byte 1
|
||||
reedState: .byte 1
|
||||
reedDataEnd:
|
||||
|
||||
|
||||
|
||||
; ***************************************************************************
|
||||
; code
|
||||
|
||||
.cseg
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; @routine REED_Init
|
||||
;
|
||||
; Init module.
|
||||
;
|
||||
; @return CFLAG set if okay, cleared on error
|
||||
; @clobbers r16, r17, X
|
||||
|
||||
REED_Init:
|
||||
; preset SRAM data area
|
||||
ldi xh, HIGH(reedDataBegin)
|
||||
ldi xl, LOW(reedDataBegin)
|
||||
clr r16
|
||||
ldi r17, (reedDataEnd-reedDataBegin)
|
||||
rcall Utils_FillSram ; (r17, x)
|
||||
|
||||
cbi REEDOUT_PORT, REEDOUT_PINNUM ; set common reed port to low
|
||||
sbi REEDOUT_DDR, REEDOUT_PINNUM ; set common reed output port as output
|
||||
|
||||
cbi REED1_PORT, REED1_PINNUM ; disable internal pullup for DATA
|
||||
cbi REED1_DDR, REED1_PINNUM ; set reed1 port as input
|
||||
|
||||
cbi REED2_PORT, REED2_PINNUM ; disable internal pullup for DATA
|
||||
cbi REED2_DDR, REED2_PINNUM ; set reed2 port as input
|
||||
|
||||
rcall reedSetupConfig ; initial setup from EEPROM, if possible
|
||||
|
||||
ret
|
||||
|
||||
|
||||
|
||||
REED_Fini:
|
||||
sec
|
||||
ret
|
||||
|
||||
|
||||
|
||||
REED_Run:
|
||||
ret ; debug
|
||||
push r15
|
||||
in r15, SREG
|
||||
cli
|
||||
rcall reedHandleChanges
|
||||
out SREG, r15
|
||||
pop r15
|
||||
ret
|
||||
|
||||
|
||||
|
||||
REED_Every100ms:
|
||||
push r15
|
||||
in r15, SREG
|
||||
cli
|
||||
rcall reedUpdateState ; (r16, r17, r18, r19)
|
||||
out SREG, r15
|
||||
pop r15
|
||||
ret
|
||||
|
||||
|
||||
|
||||
REED_Timer:
|
||||
push r15
|
||||
in r15, SREG
|
||||
cli
|
||||
rcall reedHandleChanges
|
||||
out SREG, r15
|
||||
pop r15
|
||||
ret
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; @routine reedSetupConfig
|
||||
;
|
||||
; Read initial config from EEPROM or setup from new and write to EEPROM
|
||||
;
|
||||
; @clobbers r16, X
|
||||
|
||||
reedSetupConfig:
|
||||
ldi xh, HIGH(EEPROM_OFFS_REED_CONF) ; read initial config from EEPROM
|
||||
ldi xl, LOW(EEPROM_OFFS_REED_CONF) ;
|
||||
rcall Utils_ReadEepromIncr ; (r16)
|
||||
sbiw xh:xl, 1 ; called routine increments X, undo
|
||||
tst r16
|
||||
breq reedSetupConfig_noConfig
|
||||
cpi r16, 0xff
|
||||
brne reedSetupConfig_haveConfig
|
||||
reedSetupConfig_noConfig:
|
||||
ldi r16, REED_INITIAL_CONFIG
|
||||
rcall Utils_WriteEepromIncr
|
||||
reedSetupConfig_haveConfig:
|
||||
sts reedConfigFromEeprom, r16
|
||||
reedSetupConfig_end:
|
||||
ret
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; @routine reedHandleChanges
|
||||
;
|
||||
; @clobbers all
|
||||
|
||||
reedHandleChanges:
|
||||
lds r19, reedState
|
||||
|
||||
; reed 1
|
||||
mov r16, r19
|
||||
ldi r17, VALUE_ID_REED1
|
||||
push r19
|
||||
rcall reedSendValueIfChanged
|
||||
pop r19
|
||||
andi r16, 0x0f
|
||||
andi r19, 0xf0
|
||||
or r19, r16
|
||||
|
||||
; reed 2
|
||||
mov r16, r19
|
||||
swap r16
|
||||
ldi r17, VALUE_ID_REED2
|
||||
push r19
|
||||
rcall reedSendValueIfChanged
|
||||
pop r19
|
||||
andi r16, 0x0f
|
||||
swap r16
|
||||
andi r19, 0x0f
|
||||
or r19, r16
|
||||
|
||||
sts reedState, r19
|
||||
ret
|
||||
; @end
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; @routine reedSendValueIfChanged
|
||||
;
|
||||
; @return r16 updated state
|
||||
; @param r16: current state nibble
|
||||
; @param r17: value id
|
||||
; @clobbers r16, r19 (all others)
|
||||
|
||||
reedSendValueIfChanged:
|
||||
push r16
|
||||
mov r18, r16
|
||||
andi r16, REED_STATE_MASK_CHANGED
|
||||
breq reedSendValueIfChanged_l1 ; jmp if not changed
|
||||
; value changed
|
||||
clr r16
|
||||
sbrc r18, REED_STATE_BIT_CURRENT
|
||||
dec r16 ; if stable state=0 (meaning: closed)
|
||||
rcall reedSendChange
|
||||
brcc reedSendValueIfChanged_l1
|
||||
pop r16
|
||||
andi r16, ~REED_STATE_MASK_CHANGED ; clear change bit
|
||||
ret
|
||||
reedSendValueIfChanged_l1:
|
||||
pop r16
|
||||
ret
|
||||
; @end
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; @routine reedSendChange
|
||||
;
|
||||
; @param r16 value
|
||||
; @param r17 value id
|
||||
; @clobbers r16, r18, r19, r20, r21, r22, X (R3, R4, R6, R7, R8, R9, R10, R11, R12, R15, R16, R17, R18, R19, R20, R21, R22, X, Y)
|
||||
|
||||
reedSendChange:
|
||||
mov r18, r16 ; value to send in r19:r18
|
||||
clr r19
|
||||
ldi r16, 0xff ; dest addr: send to all
|
||||
ldi r20, 1 ; denominator in r21:r20
|
||||
clr r21
|
||||
ldi r22, AQHOME_VALUETYPE_DOOR
|
||||
ldi xl, LOW(com2SendBuffer)
|
||||
ldi xh, HIGH(com2SendBuffer)
|
||||
rcall CPRO_WriteValue ; (R3, R4, R6, R7, R8, R9, R10, R11, R12, R15, R16, R17, R18, R19, R20, R21, X, Y)
|
||||
rjmp COM2_SendPacket ; (r18, r19, r22, X)
|
||||
; @end
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; @routine reedUpdateState
|
||||
;
|
||||
; Updates SDRAM variable reedState according to current pin states.
|
||||
;
|
||||
; @clobbers r16, r17, r18, r19
|
||||
|
||||
reedUpdateState:
|
||||
lds r19, reedState ; current reed state
|
||||
; handle reed 1 (low nibble state)
|
||||
rcall reedReadValue1 ; (r16)
|
||||
mov r17, r16
|
||||
mov r16, r19
|
||||
rcall reedUpdateStateNibble ; (r18)
|
||||
; replace lower state nibble with new value
|
||||
andi r16, 0x0f ; only keep low nibble
|
||||
andi r19, 0xf0 ; clear out low nibble before or'ing new value in
|
||||
or r19, r16
|
||||
|
||||
; handle reed2 (high nibble state)
|
||||
rcall reedReadValue2 ; (r16)
|
||||
mov r17, r16
|
||||
mov r16, r19
|
||||
swap r16
|
||||
rcall reedUpdateStateNibble ; (r18)
|
||||
swap r16
|
||||
; replace higher state nibble with new value
|
||||
andi r16, 0xf0
|
||||
andi r19, 0x0f
|
||||
or r19, r16
|
||||
; write back reed state
|
||||
sts reedState, r19
|
||||
ret
|
||||
; @end
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; @routine reedUpdateStateNibble
|
||||
;
|
||||
; @return r16 updated current state nibble
|
||||
; @param r16 current state nibble
|
||||
; @param r17 current pin status (o if clear, 1 if set)
|
||||
; @clobbers r18
|
||||
|
||||
reedUpdateStateNibble:
|
||||
mov r18, r16
|
||||
andi r18, REED_STATE_MASK_LAST ; clear everything but last measurement
|
||||
lsl r18 ; shift previous measurement to left
|
||||
andi r17, 1
|
||||
or r18, r17 ; or current measurement into value
|
||||
; store new value in state nibble
|
||||
andi r16, ~REED_STATE_MASK_LASTVALUES ; clear pin states
|
||||
or r16, r18 ; put updated measurements back into state nibble
|
||||
; check for new stable state
|
||||
tst r18 ; last measurements all zero?
|
||||
breq reedUpdateStateNibble_stable0
|
||||
cpi r18, 0x03 ; last measurements all one?
|
||||
breq reedUpdateStateNibble_stable1
|
||||
; not a stable state right now
|
||||
ret
|
||||
reedUpdateStateNibble_stable0:
|
||||
sbrs r16, REED_STATE_BIT_CURRENT ; new stable is 0, changed?
|
||||
ret ; ret if no change
|
||||
ori r16, REED_STATE_MASK_CHANGED ; flag change
|
||||
andi r16, ~REED_STATE_MASK_CURRENT ; set new stable value to 0
|
||||
ret
|
||||
reedUpdateStateNibble_stable1:
|
||||
sbrc r16, REED_STATE_BIT_CURRENT ; new stable is 1, changed?
|
||||
ret ; ret if no change
|
||||
ori r16, (REED_STATE_MASK_CHANGED | REED_STATE_MASK_CURRENT) ; flag change, set new stable value to 1
|
||||
ret
|
||||
; @end
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; @routine reedReadValue1
|
||||
;
|
||||
; @return r16 current pin state
|
||||
|
||||
reedReadValue1:
|
||||
clr r16
|
||||
clc
|
||||
sbic REED1_PIN, REED1_PINNUM
|
||||
sec
|
||||
adc r16, r16
|
||||
ret
|
||||
; @end
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; @routine reedReadValue2
|
||||
;
|
||||
; @return r16 current pin state
|
||||
|
||||
reedReadValue2:
|
||||
clr r16
|
||||
clc
|
||||
sbic REED2_PIN, REED2_PINNUM
|
||||
sec
|
||||
adc r16, r16
|
||||
ret
|
||||
; @end
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user