📄 csr_1hl.asm
字号:
; ARGUMENTS:
; None
;
; RETURNS:
; None, baseline is now updated with IIR for all switches
;
; 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.
;
CSR_1_UpdateBaselineIIR:
RAM_X_POINTS_TO_INDEXPAGE
RAM_SETPAGE_IDX 0 ; ram will always be in interrupt ram area
mov X, 0
.UpdateNextSwitchBaselineIIR:
; Update baseline using IIR filter
mov A, [X+CSR_1_iaSwBaseline+LSB]
mov [X+CSR_1_iaSwDiff+LSB], A ; Use for data manipulation
mov A, [X+CSR_1_iaSwBaseline+MSB]
mov [X+CSR_1_iaSwDiff+MSB], A
mov A, [X+CSR_1_iaSwResult+MSB] ; Add the actual data (1/8 weight of Baseline)
mov [X+CSR_1_iaSwBaseline+MSB], A
IF CSR_1_ESD_DETECTION
mov [X+CSR_1_iaSwPrevResult+MSB], A
ENDIF
mov A, [X+CSR_1_iaSwResult+LSB]
mov [X+CSR_1_iaSwBaseline+LSB], A
IF CSR_1_ESD_DETECTION
mov [X+CSR_1_iaSwPrevResult+LSB], A
ENDIF
and F, ~0x04 ; so no carry is brought in
rrc [X+CSR_1_iaSwDiff+MSB] ; Integer divide by two (now 1/2)
rrc [X+CSR_1_iaSwDiff+LSB]
mov A, [X+CSR_1_iaSwDiff+LSB]
add [X+CSR_1_iaSwBaseline+LSB], A
mov A, [X+CSR_1_iaSwDiff+MSB]
adc [X+CSR_1_iaSwBaseline+MSB], A ; X+CSR_1_iaSwBaseline contains 1/2 old Baseline + 1/8 result
asr [X+CSR_1_iaSwDiff+MSB] ; Integer divide by two (now 1/4)
rrc [X+CSR_1_iaSwDiff+LSB]
mov A, [X+CSR_1_iaSwDiff+LSB]
add [X+CSR_1_iaSwBaseline+LSB], A
mov A, [X+CSR_1_iaSwDiff+MSB]
adc [X+CSR_1_iaSwBaseline+MSB], A ; X+CSR_1_iaSwBaseline contains 3/4 old Baseline + 1/8 result
mov [X+CSR_1_iaSwDiff+MSB], 0
mov [X+CSR_1_iaSwDiff+LSB], 0
inc X
inc X
mov A, X
cmp A, CSR_1_TotalSwitchCount*2
jc .UpdateNextSwitchBaselineIIR
mov [CSR_1_bBaselineUpdateTimer], BASELINE_UPDATE_RATE ; reset the baseline counter
RAM_X_POINTS_TO_STACKPAGE
ret
.ENDSECTION
.SECTION
;-----------------------------------------------------------------------------
; FUNCTION NAME: CSR_1_bUpdateBaseline(BYTE bSwGroup)
;
; DESCRIPTION:
; Initially, for two calls of this function, the baseline for all valid
; switches in all groups is set equal to the current raw count. This
; reinitialization can also occur by externally setting the
; CSR_1_bBaselineUpdateTimer to 0.
;
; All later calls calculate the difference between the current signal
; and baseline, determines if the baseline needs updating, and sets
; switches on or off in the baSwOnMask bit-mask array. If the function
; is called for a slider group, it also calculates a peak value and
; position and stores this value in baCtrdPkValue and baCtrdPkPos
; respectively.
;
; The baseline is then updated as follows:
; 1. Every x scans, if the current difference is within the positive and
; negative noise threshold, the baseline is updated with a 1/4 new + 3/4
; old IIR filter.
; 2. If the difference is abnormal (> maximum finger limit or <
; negative noise threshold) for more than the abnormal count limit, the
; baseline is updated with the current raw count.
;
; The function also determines whether a switch is on or not. If a
; switches difference is above the finger high threshold, it is turned
; on. If the switch is below the finger low threshold, it is turned off.
;
; The function returns a flag indicating (1) if any switch in the group
; was pressed or (0) if all switches were not pressed.
;-----------------------------------------------------------------------------
; STACK USAGE: 3 BYTES
;
; 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:
; fIsFingerPresent => 0 if all switches in group below finger threshold
; 1 if any switch in group is above finger threshold
;
; 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.
;
CSR_1_bUpdateBaseline:
_CSR_1_bUpdateBaseline:
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
IF CSR_1_SLIDERS_EXIST
mov [CSR_1_bCurSlider], A
ENDIF
; First get the starting location and size of this switch group
asl A ; multiply by four to get group offset
asl A
mov X, A
index CSR_1_Group_Table
swap A, X
inc A
index CSR_1_Group_Table
; mov [CSR_1_bCurGroupSize], A
swap A, X ; A now has starting switch number, x has size of group
; This code finds the SwMaskPtr (which byte of the SwOnMask array the first sw is in)
; and also finds the CurSwMask (the mask bit of the first sw)
mov [CSR_1_bSwMaskPtr], A
mov [CSR_1_bCurPosMask], 0x01 ; contains mask, we will move based on remainder
.MaskOnes:
tst [CSR_1_bSwMaskPtr], 0x01
jz .MaskTwos
asl [CSR_1_bCurPosMask]
.MaskTwos:
asr [CSR_1_bSwMaskPtr]
tst [CSR_1_bSwMaskPtr], 0x01
jz .MaskFours
asl [CSR_1_bCurPosMask]
asl [CSR_1_bCurPosMask]
.MaskFours:
asr [CSR_1_bSwMaskPtr]
tst [CSR_1_bSwMaskPtr], 0x01
jz .MaskEights
asl [CSR_1_bCurPosMask]
asl [CSR_1_bCurPosMask]
asl [CSR_1_bCurPosMask]
asl [CSR_1_bCurPosMask]
.MaskEights:
asr [CSR_1_bSwMaskPtr]
asl A ; because we are dealing with ints
mov [CSR_1_bStartIndex], A ; A contains the first switch index
mov [CSR_1_bEndOfArray], A ; Store for end count
mov A, X ; X contains the switch count
asl A ; Using INTs so multiply by two
add [CSR_1_bEndOfArray], A ; Store for later
; Initialize variables
mov [CSR_1_fIsPressed], 0
IF CSR_1_SLIDERS_EXIST
mov A, [CSR_1_bCurSlider] ; only execute if looking at sliders (saves 26 cycles)
IF CSR_1_BUTTONS_EXIST
jz .AreBtnThresholdsDefined
ELSE
IF CSR_1_ESD_DETECTION
jz .CheckAbnormalEventStatus
ELSE
jz .IsBaselineDefined
ENDIF
ENDIF
mov X, A
;user
mov [X+CSR_1_baCtrdPkPos-1], 0
;temp
mov [CSR_1_bCurPkPos], 0
asl A
mov X, A
;user
mov [X+CSR_1_iaCtrdPkValue-1], 0
mov [X+CSR_1_iaCtrdPkValue-2], 0
;temp
mov [CSR_1_iCurPkValue], 0
mov [CSR_1_iCurPkValue+1], 0
IF CSR_1_ESD_DETECTION
jmp .CheckAbnormalEventStatus
ELSE
jmp .IsBaselineDefined
ENDIF
ENDIF
IF CSR_1_BUTTONS_EXIST
.AreBtnThresholdsDefined:
mov A, [CSR_1_baBtnFThreshold] ; Have the thresholds been defined?
IF CSR_1_ESD_DETECTION
jnz .CheckAbnormalEventStatus
ELSE
jnz .IsBaselineDefined
ENDIF
push X
mov A, CSR_1_ButtonCount
IF CSR_1_ESD_DETECTION
jz .CheckAbnormalEventStatus
ELSE
jz .IsBaselineDefined
ENDIF
dec A
mov X, A
.StoreButtonThresholds:
mov [X+CSR_1_baBtnFThreshold], FINGER_THRESHOLD
dec X
jnc .StoreButtonThresholds
pop X
ENDIF
IF CSR_1_ESD_DETECTION
.CheckAbnormalEventStatus:
; Check to see if we've had an abnormal event PRESS SUSPEND ONLY
tst [CSR_1_bAbnormalTimer], 0xff
jz .IsBaselineDefined
; We had an abnormal event and are pending
cmp [CSR_1_bAbnormalTimer], 0x01
jz .AbnormalEventBaselineUpdate
; We are still pending decrement and continue on
dec [CSR_1_bAbnormalTimer]
jmp .IsBaselineDefined
.AbnormalEventBaselineUpdate:
mov [CSR_1_bAbnormalTimer], 0x00
ENDIF
.IsBaselineDefined:
cmp [CSR_1_fIsBLValid], 0x01 ; Has baseline been defined?
jz .UpdateBaselineWithIIR ; After initially set, update filter on very next call
jnc .BaselineIsDefined
inc [CSR_1_fIsBLValid]
call CSR_1_GetBaseline
RAM_X_POINTS_TO_INDEXPAGE
jmp .BaselineIsDefined
.UpdateBaselineWithIIR:
inc [CSR_1_fIsBLValid]
call CSR_1_UpdateBaselineIIR
RAM_X_POINTS_TO_INDEXPAGE
.BaselineIsDefined:
; Now get the difference between the current signal and the baseline
mov X, [CSR_1_bStartIndex] ; X gets the first switch index
IF CSR_1_ESD_DETECTION
mov A, [CSR_1_bAbnormalTimer] ; only subtract for baseline update if abnormal timer is zero
jnz .GetSignalDiff ; if abnormal, do not subtract
ENDIF
dec [CSR_1_bBaselineUpdateTimer]
.GetSignalDiff:
; Flag whether or not current switch was pressed
push X
mov X, [CSR_1_bSwMaskPtr]
mov A, [CSR_1_bCurPosMask]
and A, [X+CSR_1_baSwOnMask]
jnz .SetToSwitchWasPressed
.SetToSwitchWasNotPressed:
and [CSR_1_fIsPressed], ~0x80 ; clear MSb indicating switch was off
jmp .RestoreBaseline
.SetToSwitchWasPressed:
or [CSR_1_fIsPressed], 0x80 ; set MSb to flag that switch was pressed
.RestoreBaseline:
pop X
; Integer divide by four (for IIR filter)
mov A, [X+CSR_1_iaSwBaseline+MSB]
push A ; MSB store to recover later
and F, ~0x04 ; so no carry is brought in
rrc [X+CSR_1_iaSwBaseline+MSB]
mov A, [X+CSR_1_iaSwBaseline+LSB]
push A ; LSB to recover bottom bits
rrc [X+CSR_1_iaSwBaseline+LSB]
asr [X+CSR_1_iaSwBaseline+MSB]
rrc [X+CSR_1_iaSwBaseline+LSB]
IF (CSR_1_Method)
; Period Method
; Find the difference by subtracting the current signal from the baseline
mov A, [X+CSR_1_iaSwResult+LSB]
mov [X+CSR_1_iaSwDiff+LSB], A ; Store in CSR_1_iASwDiff temporarily
mov A, [X+CSR_1_iaSwBaseline+LSB]
sub [X+CSR_1_iaSwDiff+LSB], A
mov A, [X+CSR_1_iaSwResult+MSB]
mov [X+CSR_1_iaSwDiff+MSB], A
mov A, [X+CSR_1_iaSwBaseline+MSB]
sbb [X+CSR_1_iaSwDiff+MSB], A
IF CSR_1_ESD_DETECTION
; Find derivative using previous and current raw switch result
mov A, [X+CSR_1_iaSwResult+LSB]
sub A, [X+CSR_1_iaSwPrevResult+LSB]
mov [X+CSR_1_iaSwDeriv+LSB], A
mov A, [X+CSR_1_iaSwResult+MSB]
sbb A, [X+CSR_1_iaSwPrevResult+MSB]
mov [X+CSR_1_iaSwDeriv+MSB], A
ENDIF
ELSE
; Frequency Method
; Subtract the baseline from the current signal
mov A, [X+CSR_1_iaSwBaseline+LSB]
mov [X+CSR_1_iaSwDiff+LSB], A ; Store in CSR_1_iASwDiff temporarily
mov A, [X+CSR_1_iaSwResult+LSB]
sub [X+CSR_1_iaSwDiff+LSB], A
mov A, [X+CSR_1_iaSwBaseline+MSB]
mov [X+CSR_1_iaSwDiff+MSB], A
mov A, [X+CSR_1_iaSwResult+MSB]
sbb [X+CSR_1_iaSwDiff+MSB], A
IF CSR_1_ESD_DETECTION
; Find derivative using previous and current raw switch result
mov A, [X+CSR_1_iaSwPrevResult+LSB]
sub A, [X+CSR_1_iaSwResult+LSB]
mov [X+CSR_1_iaSwDeriv+LSB], A
mov A, [X+CSR_1_iaSwPrevResult+MSB]
sbb A, [X+CSR_1_iaSwResult+MSB]
mov [X+CSR_1_iaSwDeriv+MSB], A
ENDIF
ENDIF
IF CSR_1_ESD_DETECTION
; Store the switch raw result for next deriv calculation
mov A, [X+CSR_1_iaSwResult+LSB]
mov [X+CSR_1_iaSwPrevResult+LSB], A
mov A, [X+CSR_1_iaSwResult+MSB]
mov [X+CSR_1_iaSwPrevResult+MSB], A
; Check for finger release on startup
.BranchOnDerivative:
; We are using the derivative to find a finger event
tst [X+CSR_1_iaSwDeriv+MSB], 0x80 ; Check to see if signal is negative (16-bit)
jz .IsPosDerivInRange ; If positive check if signal is in range, else find out how negative signal is
.IsNegDerivInRange:
cmp [X+CSR_1_iaSwDeriv+MSB], 0xff ; Check if < -255, if so, it is in range
jnz .SetNegDerivState ; If < -255, it is in range for first state
cmp [X+CSR_1_iaSwDeriv+LSB], 0x00-NOISE_THRESHOLD ; Is signal below negative finger threshold
jc .SetNegDerivState ; switch is below negative threshold--it is in range for first state
jmp .ResetDerivState ; Signal does not qualify for first state
.IsPosDerivInRange:
tst [X+CSR_1_iaSwDeriv+MSB], 0xff ; Check to see if signal is above 255
jnz .SetPosDerivState
cmp [X+CSR_1_iaSwDeriv+LSB], NOISE_THRESHOLD ; Check to see if signal is above threshold
jnc .SetPosDerivState
jmp .ResetDerivState
; Derivative is not large enough to qualify for a possible ESD event
.ResetDerivState:
push X
mov A, X
and F, ~0x04
rrc A
mov X, A
and [X+CSR_1_baESDDebounce], 0x3f
pop X
jmp .BranchOnDifference
; Derivative is negative enough to qualify for a possible ESD event
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -