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

📄 csr_1hl.asm

📁 Button 一个国外大学生毕业设计,用的是AVR单片机
💻 ASM
📖 第 1 页 / 共 4 页
字号:
;  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 + -