📄 sensehl.asm
字号:
.SetNegDerivState:
push X
mov A, X
and F, ~0x04
rrc A
mov X, A
or [X+SENSE_baESDDebounce], 0x40 ; set the neg bit to '1'
pop X
jmp .BranchOnDifference ; neg derivative bit is now set to '1'
; Derivative is positive enough to qualify for a possible ESD event
.SetPosDerivState:
push X
mov A, X
and F, ~0x04
rrc A
mov X, A
or [X+SENSE_baESDDebounce], 0x80 ; set the pos bit to '1'
pop X
jmp .BranchOnDifference ; pos derivative bit is now set to '1'
ENDIF
.BranchOnDifference:
; Signal difference is now calculated, branch based on what it is
tst [X+SENSE_iaSwDiff+MSB], 0x80 ; Check to see if signal is negative (16-bit)
jz .IsAboveNoiseThreshold ; If positive check if signal is in range, else find out how negative signal is
IF SENSE_ESD_DETECTION
.IsBelowNegNThreshold:
cmp [X+SENSE_iaSwDiff+MSB], 0xff ; Check if signal is negative and < -255 (16-bit)
jnz .AbnormalDiff ; switch is below negative threshold--it is abnormal and out of the update range
cmp [X+SENSE_iaSwDiff+LSB], 0x00-NOISE_THRESHOLD ; Is signal below negative fh threshold
jc .AbnormalDiff ; switch is below negative threshold--it is abnormal and out of the update range
jmp .CheckForUpdateBaseline ; Signal is in the noise, update baseline normally (every BL update rate scans)
ELSE
jmp .CheckForUpdateBaseline
ENDIF
.IsAboveNoiseThreshold:
tst [X+SENSE_iaSwDiff+MSB], 0x7f ; Is difference > 255, then it is above the noise threshold
jnz .SigAboveNThrs
cmp [X+SENSE_iaSwDiff+LSB], NOISE_THRESHOLD ; Check to see if signal is above threshold
jz .CheckForUpdateBaseline
jnc .SigAboveNThrs
; Signal is within noise range
.CheckForUpdateBaseline:
IF SENSE_ESD_DETECTION
push X
mov A, X
and F, ~0x04
rrc A
mov X, A
mov [X+SENSE_baBaselineResetCounter], 0 ; reset counter for finger on startup
pop X
ENDIF
; Check for update baseline (based on update baseline rate)
mov A, [SENSE_bBaselineUpdateTimer]
jnz .SetDiffToZeroNoUpdate ; if not zero, do not update baseline
.UpdateSwitchBaselineIIR:
; Update baseline using IIR filter
pop A ; contains Baseline LSB
mov [X+SENSE_iaSwDiff+LSB], A ; Use for data manipulation
pop A ; contains Baseline MSB
mov [X+SENSE_iaSwDiff+MSB], A
and F, ~0x04 ; so no carry is brought in
rrc [X+SENSE_iaSwDiff+MSB] ; Integer divide by two
rrc [X+SENSE_iaSwDiff+LSB]
mov A, [X+SENSE_iaSwDiff+MSB]
mov [X+SENSE_iaSwBaseline+MSB], A
mov A, [X+SENSE_iaSwDiff+LSB]
mov [X+SENSE_iaSwBaseline+LSB], A ; X+SENSE_iaSwBaseline contains 1/2 old Baseline
asr [X+SENSE_iaSwDiff+MSB] ; Integer divide by two
rrc [X+SENSE_iaSwDiff+LSB]
mov A, [X+SENSE_iaSwDiff+LSB]
add [X+SENSE_iaSwBaseline+LSB], A
mov A, [X+SENSE_iaSwDiff+MSB]
adc [X+SENSE_iaSwBaseline+MSB], A ; X+SENSE_iaSwBaseline contains 3/4 old Baseline
mov A, [X+SENSE_iaSwResult+LSB] ; Now add the actual data (1/4 weight of Baseline)
add [X+SENSE_iaSwBaseline+LSB], A
mov A, [X+SENSE_iaSwResult+MSB]
adc [X+SENSE_iaSwBaseline+MSB], A ; X+SENSE_iaSwBaseline contains 3/4 old Baseline + 1/4 current
jmp .SetDiffToZero
IF SENSE_ESD_DETECTION
; switch is behaving abnormally, if finger present on startup, reset baseline
; Possible causes:
; 1. Temperature is increasing or decreasing faster than baseline can keep up with
; 2. Finger was present on startup and then lifted off
; 3. ESD activity/external charge increase/decrease
.AbnormalDiff:
mov [SENSE_bBaselineUpdateTimer], BASELINE_UPDATE_RATE ; reset the baseline counter
push X
mov A, [SENSE_bAbnormalTimer] ; only check for update if abnormal timer is zero
jnz .CheckForESD ; if abnormal, still look for ESD, check if currently a spike
; Increment finger on counter, check if we should adjust baseline
mov A, X
and F, ~0x04
rrc A
mov X, A
inc [X+SENSE_baBaselineResetCounter]
; If switch has been low for three times the debounce, reset
cmp [X+SENSE_baBaselineResetCounter], ESD_DEBOUNCE*3
jz .FingerOnStartupUpdate
jmp .CheckForESD ; may be ESD, check if currently a spike
.FingerOnStartupUpdate:
mov [X+SENSE_baBaselineResetCounter], 0 ; reset counter
pop X ; restore pointer
pop A ; restore stack pointer (old baseline was stored)
pop A ; ..
mov A, [X+SENSE_iaSwResult+MSB]
mov [X+SENSE_iaSwBaseline+MSB], A
mov A, [X+SENSE_iaSwResult+LSB]
mov [X+SENSE_iaSwBaseline+LSB], A
asl [X+SENSE_iaSwBaseline+LSB] ; Multiply by four for IIR filter resolution
rlc [X+SENSE_iaSwBaseline+MSB]
asl [X+SENSE_iaSwBaseline+LSB]
rlc [X+SENSE_iaSwBaseline+MSB]
jmp .SetDiffToZero ; actual baseline is outside of current noise range, update using filter
.CheckForESD:
mov A, [X+SENSE_baESDDebounce]
pop X ; restore the index pointer
and A, 0xC0
cmp A, 0xC0 ; check if there was an ESD event (a negative and positive transition in two consecutive scans or vice versa)
jnz .SetDiffToZeroNoUpdate
; An ESD event has occured, repress switches being on for eight times the debounce time
mov [SENSE_bAbnormalTimer], ESD_DEBOUNCE*8
jmp .SetDiffToZeroNoUpdate
ENDIF
.SetDiffToZeroNoUpdate:
; Restore the baseline
pop A
mov [X+SENSE_iaSwBaseline+LSB], A
pop A
mov [X+SENSE_iaSwBaseline+MSB], A
.SetDiffToZero:
; Set switch state and signal difference to zero
mov [X+SENSE_iaSwDiff+MSB], 0 ; Set the difference to zero, it is below the low finger and/or noise threshold
mov [X+SENSE_iaSwDiff+LSB], 0
jmp .SetSwitchOff
.SigAboveNThrs:
; Signal is above FINGER_THRESHOLD
IF SENSE_ESD_DETECTION
push X
mov A, X
and F, ~0x04
rrc A
mov X, A
mov [X+SENSE_baBaselineResetCounter], 0 ; reset counter for finger on startup
pop X
; Check to see if we've had an abnormal event
tst [SENSE_bAbnormalTimer], 0xff
jnz .SetDiffToZeroNoUpdate ; If abnormal, ignore and set to diff to zero
ENDIF
; Recover baseline
pop A
mov [X+SENSE_iaSwBaseline+LSB], A
pop A
mov [X+SENSE_iaSwBaseline+MSB], A
IF SENSE_SLIDERS_EXIST
mov A, [SENSE_bCurSlider] ; only execute if looking at sliders
IF SENSE_BUTTONS_EXIST
jz .IsButtonSwitchOn
ELSE
jz .SetSwitchOff ; This will only happen if there are sliders and no buttons and UpdateBaseline(0) is called
ENDIF
mov A, [SENSE_iCurPkValue]
jz .DefineNewPeak
; There is an existing peak, is this one bigger?
cmp A, [X+SENSE_iaSwDiff+MSB]
jnc .IsSliderSwitchOn
cmp A, [X+SENSE_iaSwDiff+LSB]
jc .DefineNewPeak
jmp .IsSliderSwitchOn ; not a peak
.DefineNewPeak:
mov A, [X+SENSE_iaSwDiff+LSB]
mov [SENSE_iCurPkValue+LSB], A
mov A, [X+SENSE_iaSwDiff+MSB]
mov [SENSE_iCurPkValue+MSB], A
mov A, X
mov [SENSE_bCurPkPos], A
.IsSliderSwitchOn:
; Set switch to one in SENSE_baSwOnMask if above fixed high finger threshold and below
; max finger threshold, switch to off if below fixed low finger threshold
tst [X+SENSE_iaSwDiff+MSB], 0x7f ; check if difference is > 255, switch must be on
jnz .SetSwitchOn
cmp [X+SENSE_iaSwDiff+LSB], FINGER_THRESHOLD+1
jnc .SetSwitchOn
jmp .InBetweenThresholds
ENDIF
IF SENSE_BUTTONS_EXIST
.IsButtonSwitchOn:
; Set switch to one in SENSE_baSwOnMask if above variable high finger threshold, switch
; to off if below variable low finger threshold
tst [X+SENSE_iaSwDiff+MSB], 0x7f ; check if difference is > 255 and is less than the max finger threshold, switch must be on
jnz .SetSwitchOn
push X
mov A, X
and F, ~0x04
rrc A
mov X, A
mov A, [X+SENSE_baBtnFThreshold]
pop X
cmp A, [X+SENSE_iaSwDiff+LSB]
jc .SetSwitchOn ; If switch diff is above the high threshold, check if debounced
jmp .InBetweenThresholds ; check if switch is in between noise and finger threshold
ENDIF
.SetSwitchOff:
push X
IF SENSE_ESD_DETECTION
mov A, X
and F, ~0x04
rrc A
mov X, A
and [X+SENSE_baESDDebounce], 0xC0 ; clear all switch ESD debounce
ENDIF
mov X, [SENSE_bSwMaskPtr]
mov A, [SENSE_bCurPosMask]
cpl A
and [X+SENSE_baSwOnMask], A
pop X
jmp .NextBLSwitch ; switch is debounced off
.InBetweenThresholds:
; If in between, clear both press and release debounce
IF SENSE_ESD_DETECTION
push X
mov A, X
and F, ~0x04
rrc A
mov X, A
and [X+SENSE_baESDDebounce], 0xC0 ; clear all switch ESD debounce
pop X
ENDIF
tst [SENSE_fIsPressed], 0x80 ; check previous switch state
jz .NextBLSwitch ; if wasn't on, don't update flag
mov [SENSE_fIsPressed], 0x01
jmp .NextBLSwitch ; if in between, leave as it was before (hysteresis)
.SetSwitchOn:
mov [SENSE_bBaselineUpdateTimer], 0x02 ; set the baseline counter so we update immediately
IF SENSE_ESD_DETECTION
; Check if we are suspending a press due to an abnormal scan (ESD)
tst [SENSE_bAbnormalTimer], 0xff
jnz .NextBLSwitch
push X
mov A, X
and F, ~0x04
rrc A
mov X, A
; First check if switch was on, then it should stay on
tst [SENSE_fIsPressed], 0x80
jnz .TurnOnSwitchAndResetDebounce
; It was off, now check if it's debounced
mov A, [X+SENSE_baESDDebounce]
and A, 0x3f ; switch debounce is in the lower six bits
cmp A, ESD_DEBOUNCE
jnc .TurnOnSwitchAndResetDebounce
inc [X+SENSE_baESDDebounce]
pop X
jmp .NextBLSwitch ; switch is on but not debounced
.TurnOnSwitchAndResetDebounce:
and [X+SENSE_baESDDebounce], 0xC0 ; clear all debounce
pop X
ENDIF
push X
mov A, [SENSE_bCurPosMask]
mov X, [SENSE_bSwMaskPtr] ; x location already stored
or [X+SENSE_baSwOnMask], A
mov [SENSE_fIsPressed], 1
pop X
.NextBLSwitch:
; shift the mask over, if carry than increment to next byte in array
and [SENSE_fIsPressed], 0x01 ; clear previous bit setting
asl [SENSE_bCurPosMask]
jnc .IncrementToNextPos
inc [SENSE_bSwMaskPtr]
mov [SENSE_bCurPosMask], 0x01
.IncrementToNextPos:
inc X
inc X ; Increment to next position in array
mov A, X
cmp A, [SENSE_bEndOfArray] ; Check for the end of the array
jc .GetSignalDiff
; All switches have been updated, if baseline update is zero, reset
mov A, [SENSE_bBaselineUpdateTimer]
IF SENSE_SLIDERS_EXIST
jnz .UpdateGroupsStatus
ELSE
jnz .EndofUpdateBaseline
ENDIF
mov [SENSE_bBaselineUpdateTimer], BASELINE_UPDATE_RATE ; reset the timer
IF SENSE_SLIDERS_EXIST
.UpdateGroupsStatus:
; Update this groups characterictics
mov A, [SENSE_bCurSlider]
jz .EndofUpdateBaseline
mov X, A
mov A, [SENSE_bCurPkPos]
mov [X+SENSE_baCtrdPkPos-1], A
asl [SENSE_bCurSlider] ; for INT
mov X, [SENSE_bCurSlider]
mov A, [SENSE_iCurPkValue+1]
mov [X+SENSE_iaCtrdPkValue-1], A
mov A, [SENSE_iCurPkValue]
mov [X+SENSE_iaCtrdPkValue-2], A
ENDIF
.EndofUpdateBaseline:
mov A, [SENSE_fIsPressed]
RAM_RESTORE_NATIVE_PAGING
RAM_EPILOGUE RAM_USE_CLASS_4
ret
.ENDSECTION
IF SENSE_SLIDERS_EXIST
.SECTION
;-----------------------------------------------------------------------------
; FUNCTION NAME: SENSE_bGetCentroidPos(BYTE bSwGroup)
;
; DESCRIPTION:
; Checks the difference array for a centroid. If one exists, the offset
; (within the whole difference arrary) and length are placed in the
; bCentroidLength and bCentroidStart variables.
;
; Then the function finds and returns the position of the centroid in the
; difference array.
;
;-----------------------------------------------------------------------------
;
; ARGUMENTS:
; A => Switch Group
; Switch Group = 0 for the independent switches group
; Switch Group = 1 for the first slider group
; Switch Group = 2 for the second slider group
;
; RETURNS:
; A-> position of the centroid
;
; SIDE EFFECTS:
; The A and X registers may be modified by this or future implementations
; of this function. The same is true for all RAM page pointer registers in
; the Large Memory Model. When necessary, it is the calling function's
; responsibility to perserve their values across calls to fastcall16
; functions.
;
SENSE_bGetCentroidPos:
_SENSE_bGetCentroidPos:
RAM_PROLOGUE RAM_USE_CLASS_4
RAM_SETPAGE_CUR 0 ; ram will always be in interrupt ram area
RAM_X_POINTS_TO_INDEXPAGE
RAM_SETPAGE_IDX 0 ; ram will always be in interrupt ram area
; First get the starting location and size of this switch group
asl A ; multiply by two to get diplex
mov X, A
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -