From 84403d07f68a77374e1fe0d4fce8fba14eb71403 Mon Sep 17 00:00:00 2001 From: Martin Preuss Date: Fri, 12 May 2023 21:41:39 +0200 Subject: [PATCH] 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). --- avr/att84_temp1.asm | 43 ++++- avr/defs.asm | 10 +- avr/main.asm | 8 + avr/modules/0BUILD | 1 + avr/modules/reed/0BUILD | 11 ++ avr/modules/reed/main.asm | 355 ++++++++++++++++++++++++++++++++++++++ 6 files changed, 424 insertions(+), 4 deletions(-) create mode 100644 avr/modules/reed/0BUILD create mode 100644 avr/modules/reed/main.asm diff --git a/avr/att84_temp1.asm b/avr/att84_temp1.asm index 62500fc..540eedd 100644 --- a/avr/att84_temp1.asm +++ b/avr/att84_temp1.asm @@ -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< + + + + + main.asm + + + + + diff --git a/avr/modules/reed/main.asm b/avr/modules/reed/main.asm new file mode 100644 index 0000000..3ed6d0c --- /dev/null +++ b/avr/modules/reed/main.asm @@ -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 + + +