⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sensehl.asm

📁 cypress的触摸按键模块介绍calibrating_capsense_with_the_csr_user_module___an2355_13.
💻 ASM
📖 第 1 页 / 共 4 页
字号:
.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 + -