;;*****************************************************************************
;;  FILENAME: CSDHL.asm
;;   Version: 1.2, Updated on 2008/02/28 at 09:57:56
;;  Generated by PSoC Designer ???
;;
;;  DESCRIPTION: CSD User Module high level software
;;                implementation file for the 24x94 PSoC family of devices.
;;-----------------------------------------------------------------------------
;;  Copyright (c) Cypress Semiconductor 2000-2007. All Rights Reserved.
;;*****************************************************************************
;;*****************************************************************************

include "m8c.inc"
include "memory.inc"
include "CSD.inc"

;-----------------------------------------------
; Global Symbols
;-----------------------------------------------

export _CSD_UpdateSensorBaseline
export  CSD_UpdateSensorBaseline
export _CSD_InitializeSensorBaseline
export  CSD_InitializeSensorBaseline
export _CSD_bIsSensorActive
export  CSD_bIsSensorActive
export _CSD_bIsAnySensorActive
export  CSD_bIsAnySensorActive
export _CSD_SetDefaultFingerThresholds
export  CSD_SetDefaultFingerThresholds
export _CSD_InitializeBaselines
export  CSD_InitializeBaselines
export _CSD_UpdateAllBaselines
export  CSD_UpdateAllBaselines
IF CSD_SLIDERS_EXIST
export _CSD_wGetCentroidPos
export  CSD_wGetCentroidPos
ENDIF
;-----------------------------------------------
; Variable Allocation
;-----------------------------------------------
AREA InterruptRAM (RAM, REL, CON)

_CSD_bNoiseThreshold:
 CSD_bNoiseThreshold:					 BLK  1
_CSD_bNegativeNoiseThreshold:
 CSD_bNegativeNoiseThreshold:           BLK  1
_CSD_bBaselineUpdateThreshold:
 CSD_bBaselineUpdateThreshold:          BLK  1
_CSD_bHysteresis:
 CSD_bHysteresis:                       BLK  1
_CSD_bDebounce:
 CSD_bDebounce:                         BLK  1
_CSD_bLowBaselineReset:
 CSD_bLowBaselineReset:                 BLK  1

export _CSD_bNoiseThreshold
export  CSD_bNoiseThreshold
export _CSD_bNegativeNoiseThreshold:
export  CSD_bNegativeNoiseThreshold:
export _CSD_bBaselineUpdateThreshold:
export  CSD_bBaselineUpdateThreshold:
export _CSD_bHysteresis:
export  CSD_bHysteresis:
export _CSD_bDebounce:
export  CSD_bDebounce:
export _CSD_bLowBaselineReset:
export  CSD_bLowBaselineReset:

; Local variables
_CSD_bEndOfArray:                               ; Temp pointer variable
 CSD_bEndOfArray:                       BLK  1
_CSD_fIsPressed:                                ; Temp variable for if any sensor is pressed
 CSD_fIsPressed:                        BLK  1
_CSD_bCurPos:                                   ; Temp position variable
 CSD_bCurPos:                           BLK  1
_CSD_bSnsMaskPtr:                               ; Temp sensor mask pointer used in centroid calculation
 CSD_bSnsMaskPtr:                       BLK  1
_CSD_bStartIndex:                               ; Temp Start index
 CSD_bStartIndex:						 BLK  1
_CSD_wTmpBtnFThreshold:                         ; Temp Difference
 CSD_wTmpBtnFThreshold:				 BLK  2

IF CSD_SLIDERS_EXIST
; Local slider variables
_CSD_wDenom:                                    ; Denominator is also the Ctrd Pos
 CSD_wDenom:                            BLK  2
_CSD_dNumer:                                    ; Numerator also contains the Ctrd Pos
 CSD_dNumer:                            BLK  2
_CSD_wCtrdPos:                                  ; Ctrd Pos is LMSB and LLSB of the numerator
 CSD_wCtrdPos:                          BLK  2
_CSD_dMultTempX:                                ; Temp multiplication register
 CSD_dMultTempX:                        BLK  4
_CSD_dMultTempY:                                ; Temp multiplication register
 CSD_dMultTempY:                        BLK  4
_CSD_bCurSlider:
 CSD_bCurSlider:                        BLK  1
_CSD_bCurCtrdStartPos:                          ; Temp current centroid start position
 CSD_bCurCtrdStartPos:                  BLK  1
_CSD_bCurCtrdSize:                              ; Temp current centroid size
 CSD_bCurCtrdSize:                      BLK  1
_CSD_bBiggestCtrdStartPos:                      ; Temp biggest centroid start position
 CSD_bBiggestCtrdStartPos:              BLK  1
_CSD_bBiggestCtrdSize:                          ; Temp biggest centroid size
 CSD_bBiggestCtrdSize:                  BLK  1
_CSD_wCurPkValue:                               ; Temp current peak
 CSD_wCurPkValue:                       BLK  2
_CSD_bCurPkPos:                                 ; Temp current slider pointer
 CSD_bCurPkPos:                         BLK  1
_CSD_bDiplexInfo:                               ; Temp flag for diplex of current group
 CSD_bDiplexInfo:						 BLK  1
_CSD_bDiplexMSB:                                ; Temp that contains the address of the rom diplex table
 CSD_bDiplexMSB:                        BLK  1
_CSD_bDiplexLSB:
 CSD_bDiplexLSB:                        BLK  1
_CSD_wDivBtwSns:                                ; Temp divisions between sensors
 CSD_wDivBtwSns:                        BLK  2
ENDIF

AREA bss
; Global variables
_CSD_baSnsBucket:                                 ; Baseline difference accumulator, one entry for each sensor
 CSD_baSnsBucket:                       BLK  CSD_TotalSensorCount
_CSD_baSnsDebounce:
 CSD_baSnsDebounce:                     BLK  CSD_TotalSensorCount
_CSD_baLowBaselineReset:
 CSD_baLowBaselineReset:                BLK  CSD_TotalSensorCount

IF CSD_SLIDERS_EXIST
_CSD_waCtrdPkValue:                             ; Array containing peak value of centroid
 CSD_waCtrdPkValue:                     BLK  (2*CSD_SliderCount)
ENDIF

; Local variables
export _CSD_fIsPressed
export  CSD_fIsPressed
export _CSD_bEndOfArray
export  CSD_bEndOfArray
export _CSD_bCurPos
export  CSD_bCurPos
export _CSD_bSnsMaskPtr
export  CSD_bSnsMaskPtr

IF CSD_SLIDERS_EXIST
; Local slider variables
export _CSD_wDenom
export  CSD_wDenom
export _CSD_wCtrdPos
export  CSD_wCtrdPos
export _CSD_dNumer
export  CSD_dNumer
export _CSD_dMultTempX
export  CSD_dMultTempX
export _CSD_dMultTempY
export  CSD_dMultTempY
export _CSD_bCurCtrdStartPos
export  CSD_bCurCtrdStartPos
export _CSD_bCurCtrdSize
export  CSD_bCurCtrdSize
export _CSD_bBiggestCtrdStartPos
export  CSD_bBiggestCtrdStartPos
export _CSD_bBiggestCtrdSize
export  CSD_bBiggestCtrdSize
export _CSD_wCurPkValue
export  CSD_wCurPkValue
export _CSD_bCurPkPos
export  CSD_bCurPkPos
export _CSD_bDiplexMSB
export  CSD_bDiplexMSB
export _CSD_bDiplexLSB
export  CSD_bDiplexLSB
export _CSD_wDivBtwSns
export  CSD_wDivBtwSns
ENDIF

;@PSoC_UserCode_INIT@ (Do not change this line.)
;---------------------------------------------------
; Insert your custom declarations below this banner
;---------------------------------------------------

;------------------------
; User Includes
;------------------------


;------------------------
; User Constant Definitions
;------------------------


;------------------------
; User Variable Allocation
;------------------------


;---------------------------------------------------
; Insert your custom declarations above this banner
;---------------------------------------------------
;@PSoC_UserCode_END@ (Do not change this line.)

;------------------------
;  Constant Definitions
;------------------------
AREA UserModules (ROM, REL, CON)

; For using two byte variables
LSB:  equ  1
MSB:  equ  0

; For using four byte variables
MMSB: equ 0
MLSB: equ 1
LMSB: equ 2
LLSB: equ 3

.SECTION
;-----------------------------------------------------------------------------
;  FUNCTION NAME: CSD_UpdateSensorBaseline(BYTE bSensorNum)
;
;  DESCRIPTION:
;      Update baseline for one sensor. The algorithm is as follows:
;        If difference count is negative baseline become raw count
;        If difference count is above noise threshold do not update
;        Else difference count is positive and within noise threshold so
;        difference is halved and added to the bucket. When the bucket
;        reaches the threshold the baseline increments and the bucket resets
;-----------------------------------------------------------------------------
;  STACK USAGE: 0 BYTES
;
;  ARGUMENTS:
;      A => Sensor Number
;
;  RETURNS:
;      Nothing
;
;  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.
;
 CSD_UpdateSensorBaseline:
_CSD_UpdateSensorBaseline:
   RAM_PROLOGUE RAM_USE_CLASS_3
   RAM_SETPAGE_CUR 0 ; direct access ram will always be in interrupt ram area
   RAM_X_POINTS_TO_INDEXPAGE

   mov [CSD_bSensorNum], A                                                     ; Save sensor index
   asl A
   mov X,A

   ; Get the difference counts
   RAM_SETPAGE_IDX >CSD_waSnsResult
   mov A, [X+CSD_waSnsResult+LSB]
   RAM_SETPAGE_IDX >CSD_waSnsBaseline
   sub A, [X+CSD_waSnsBaseline+LSB]
   RAM_SETPAGE_IDX >CSD_waSnsDiff
   mov [X+CSD_waSnsDiff+LSB], A
   RAM_SETPAGE_IDX >CSD_waSnsResult
   mov A, [X+CSD_waSnsResult+MSB]
   RAM_SETPAGE_IDX >CSD_waSnsBaseline
   sbb A, [X+CSD_waSnsBaseline+MSB]
   RAM_SETPAGE_IDX >CSD_waSnsDiff
   mov [X+CSD_waSnsDiff+MSB], A

   tst [X+CSD_waSnsDiff+MSB], 80h						                                        ; Is difference negative?
   jnz .IsNegative

IF (CSD_AUTORESET)
   cmp [X+CSD_waSnsDiff+MSB], 0
   jz   .AddBucketLSB
   mov  A, 255
   jmp  .AddBucketConst
ELSE
   ; Compare to Noise Threshold
   cmp [X+CSD_waSnsDiff+MSB], 0
   jnz  .InitLowBaselineReset
   mov A, [CSD_bNoiseThreshold]
   cmp A, [X+CSD_waSnsDiff+LSB]
   jc	.InitLowBaselineReset
ENDIF

   ; Add to the Bucket
.AddBucketLSB:
   mov A, [X+CSD_waSnsDiff+LSB]
.AddBucketConst:
   mov X, [CSD_bSensorNum]
   add A, 0
   rrc A															                                                        ; For slower tracking
   RAM_SETPAGE_IDX >CSD_baSnsBucket
   add [X+CSD_baSnsBucket], A
   jc  .DoInc
   mov A, [CSD_bBaselineUpdateThreshold]
   cmp A, [X+CSD_baSnsBucket]
   jnc .EndBucket
   jz  .EndBucket
.DoInc:
   ; Increment Baseline
   mov [X+CSD_baSnsBucket], 0
   mov A, X
   asl A
   mov X, A
   RAM_SETPAGE_IDX >CSD_waSnsBaseline
   add [X+CSD_waSnsBaseline+LSB], 1
   adc [X+CSD_waSnsBaseline+MSB], 0

.EndBucket:
IF (CSD_AUTORESET)
   mov  A, [CSD_bSensorNum]
   asl  A
   mov  X, A
   ; Compare to Noise Threshold
   RAM_SETPAGE_IDX >CSD_waSnsDiff
   cmp [X+CSD_waSnsDiff+MSB], 0
   jnz  .InitLowBaselineReset
   mov A, [CSD_bNoiseThreshold]
   cmp A, [X+CSD_waSnsDiff+LSB]
   jc	.InitLowBaselineReset
ELSE
ENDIF
   jmp .SetDifferenceToZero

.IsNegative:
   ; Compare to Negative Noise Threshold
   cmp [X+CSD_waSnsDiff+MSB], FFh
   jnz  .CheckLowBaseline
   mov A, FFh
   sub A, [CSD_bNegativeNoiseThreshold]
   cmp A, [X+CSD_waSnsDiff+LSB]
   jc	.LowerBaseline
.CheckLowBaseline:
   ; Set difference to zero
   RAM_SETPAGE_IDX >CSD_waSnsDiff
   mov [X+CSD_waSnsDiff+LSB], 0
   mov [X+CSD_waSnsDiff+MSB], 0
   ; Check Low Baseline Reset
   mov A, X
   asr A
   mov X, A
   RAM_SETPAGE_IDX >CSD_baLowBaselineReset
   mov A, [X+CSD_baLowBaselineReset]
   dec A
   mov [X+CSD_baLowBaselineReset], A
   push A
   mov A, X
   asl A
   mov X, A
   pop A
   jnz .EndofUpdateSensorBaseline

.LowerBaseline:
   RAM_SETPAGE_IDX >CSD_waSnsResult
   mov A, [X+CSD_waSnsResult+LSB]
   RAM_SETPAGE_IDX >CSD_waSnsBaseline
   mov [X+CSD_waSnsBaseline+LSB], A
   RAM_SETPAGE_IDX >CSD_waSnsResult
   mov A, [X+CSD_waSnsResult+MSB]
   RAM_SETPAGE_IDX >CSD_waSnsBaseline
   mov [X+CSD_waSnsBaseline+MSB], A

.SetDifferenceToZero:
   ; Set difference to zero
   mov A, [CSD_bSensorNum]
   asl A
   mov X,A
   RAM_SETPAGE_IDX >CSD_waSnsDiff
   mov [X+CSD_waSnsDiff+LSB], 0
   mov [X+CSD_waSnsDiff+MSB], 0
.InitLowBaselineReset:
   mov A, X
   asr A
   mov X, A
   RAM_SETPAGE_IDX >CSD_baLowBaselineReset
   mov A, [CSD_bLowBaselineReset]
   mov [X+CSD_baLowBaselineReset], A

.EndofUpdateSensorBaseline:
   RAM_EPILOGUE RAM_USE_CLASS_3
   ret

.ENDSECTION

.SECTION
;-----------------------------------------------------------------------------
;  FUNCTION NAME: CSD_bIsSensorActive(BYTE bSensorNum)
;
;  DESCRIPTION:
;      Returns state of one sensor.	Updates the baSnsOnMask array.
;      Implements hysteresis based on the Hysteresis parameter.
;-----------------------------------------------------------------------------
;  STACK USAGE: 3 BYTES
;
;  ARGUMENTS:
;      A => sensor index
;
;  RETURNS:
;      A => 1 if sensor is active, 0 otherwise
;
;  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.
;
 CSD_bIsSensorActive:
_CSD_bIsSensorActive:
   RAM_PROLOGUE RAM_USE_CLASS_3
   RAM_SETPAGE_CUR 0 ; direct access ram will always be in interrupt ram area
   RAM_X_POINTS_TO_INDEXPAGE

   push A
   mov X,A
   RAM_SETPAGE_IDX >CSD_baBtnFThreshold
   mov A, [X+CSD_baBtnFThreshold]
   mov [CSD_wTmpBtnFThreshold+LSB], A
   mov [CSD_wTmpBtnFThreshold+MSB], 0

   pop A
   push A
   call CSD_GetOnMask
   RAM_SETPAGE_IDX >CSD_baSnsOnMask
   and A, [X+CSD_baSnsOnMask]
   jnz .WasOn

.WasOff:
   ; Check the difference counts against the threshold
   mov A, [CSD_bHysteresis]
   add [CSD_wTmpBtnFThreshold+LSB], A
   adc [CSD_wTmpBtnFThreshold+MSB], 0
   pop A
   asl A
   mov X, A
   RAM_SETPAGE_IDX >CSD_waSnsDiff
   mov A, [X+CSD_waSnsDiff+LSB]
   sub A, [CSD_wTmpBtnFThreshold+LSB]
   mov A, [X+CSD_waSnsDiff+MSB]
   sbb A, [CSD_wTmpBtnFThreshold+MSB]
   jc .NotActive
   mov A, X
   asr A
   mov X, A
   RAM_SETPAGE_IDX >CSD_baSnsDebounce
   mov A, [X+CSD_baSnsDebounce]
   dec A
   mov [X+CSD_baSnsDebounce], A
   push A
   mov A, X
   asl A
   mov X, A
   pop A
   jnz .NotActiveDebouncing
   jmp .Active

.WasOn:
   ; Check the difference counts against the threshold
   mov A, [CSD_bHysteresis]
   sub [CSD_wTmpBtnFThreshold+LSB], A
   sbb [CSD_wTmpBtnFThreshold+MSB], 0
   pop A
   asl A
   mov X, A
   RAM_SETPAGE_IDX >CSD_waSnsDiff
   mov A, [X+CSD_waSnsDiff+LSB]
   sub A, [CSD_wTmpBtnFThreshold+LSB]
   mov A, [X+CSD_waSnsDiff+MSB]
   sbb A, [CSD_wTmpBtnFThreshold+MSB]
   jc .NotActive

.Active:
   mov A, X
   asr A
   call CSD_GetOnMask
   RAM_SETPAGE_IDX >CSD_baSnsOnMask
   or [X+CSD_baSnsOnMask], A
   mov A, 1
   jmp .EndIsSensorActive
.NotActive:
   mov A, X
   asr A
   push A
   call CSD_GetOnMask
   cpl A
   RAM_SETPAGE_IDX >CSD_baSnsOnMask
   and [X+CSD_baSnsOnMask], A
   RAM_SETPAGE_IDX >CSD_baSnsDebounce
   pop X
   mov A, [CSD_bDebounce]
   mov [X+CSD_baSnsDebounce], A
   mov A, 0
   jmp .EndIsSensorActive
.NotActiveDebouncing:
   mov A, X
   asr A
   call CSD_GetOnMask
   cpl A
   RAM_SETPAGE_IDX >CSD_baSnsOnMask
   and [X+CSD_baSnsOnMask], A
   mov A, 0
.EndIsSensorActive:
   RAM_EPILOGUE RAM_USE_CLASS_3
   ret

.ENDSECTION

 CSD_GetOnMask:
_CSD_GetOnMask:
   push A
   asr A
   asr A
   asr A
   mov X, A
   pop A
   and A, 7h
   index CSD_bitlookup
   ret

.LITERAL
CSD_bitlookup:
	db 01h, 02h, 04h, 08h, 10h, 20h, 40h, 80h
.ENDLITERAL


.SECTION
;-----------------------------------------------------------------------------
;  FUNCTION NAME: CSD_SetDefaultFingerThresholds(void)
;
;  DESCRIPTION:
;    Sets the FingerThreshold RAM array to the user module parameter value
;
;-----------------------------------------------------------------------------
;
;  ARGUMENTS:    None.
;  RETURNS:      None
;  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.
;
 CSD_SetDefaultFingerThresholds:
_CSD_SetDefaultFingerThresholds:
   RAM_PROLOGUE RAM_USE_CLASS_3
   RAM_X_POINTS_TO_INDEXPAGE
   RAM_SETPAGE_IDX >CSD_baBtnFThreshold

   mov   A,CSD_TotalSensorCount                       ; Check if key value in range.
   dec   A
.ThresholdLoop:                                       ; Loop through all sensors and scan
   push  A
   mov   X, A
   mov   [X+CSD_baBtnFThreshold], CSD_FINGER_THRESHOLD
   pop   A
   dec   A
   jnc   .ThresholdLoop
   RAM_EPILOGUE RAM_USE_CLASS_3
   ret
.ENDSECTION

.SECTION
;-----------------------------------------------------------------------------
;  FUNCTION NAME: CSD_InitializeBaselines(void)
;
;  DESCRIPTION:
;    Scans all sensors to find their initial raw count values and loads these
;    into the baseline
;
;-----------------------------------------------------------------------------
;
;  ARGUMENTS:    None.
;  RETURNS:      None
;  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.
;
 CSD_InitializeBaselines:
_CSD_InitializeBaselines:
   RAM_PROLOGUE RAM_USE_CLASS_3

   mov   A,CSD_TotalSensorCount                       ; Get sensor num
   dec   A
.BaselineLoop:                                        ; Loop through all sensors and scan
   push  A
   call  CSD_ScanSensor
   RAM_X_POINTS_TO_INDEXPAGE
   pop   A
   push  A
   asl   A
   mov   X, A
   RAM_SETPAGE_IDX >CSD_waSnsResult
   mov A, [X+CSD_waSnsResult+LSB]
   RAM_SETPAGE_IDX >CSD_waSnsBaseline
   mov [X+CSD_waSnsBaseline+LSB], A
   RAM_SETPAGE_IDX >CSD_waSnsResult
   mov A, [X+CSD_waSnsResult+MSB]
   RAM_SETPAGE_IDX >CSD_waSnsBaseline
   mov [X+CSD_waSnsBaseline+MSB], A
   pop   A
   dec   A
   jnc   .BaselineLoop
   RAM_EPILOGUE RAM_USE_CLASS_3
   ret
.ENDSECTION

.SECTION
;-----------------------------------------------------------------------------
;  FUNCTION NAME: CSD_InitializeSensorBaseline(BYTE bSensorNum)
;
;  DESCRIPTION:
;    Scans all sensors to find their initial raw count values and loads these
;    into the baseline
;
;-----------------------------------------------------------------------------
;
;  ARGUMENTS:    None.
;  RETURNS:      None
;  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.
;
 CSD_InitializeSensorBaseline:
_CSD_InitializeSensorBaseline:
   RAM_PROLOGUE RAM_USE_CLASS_3
   push  A
   call  CSD_ScanSensor
   RAM_X_POINTS_TO_INDEXPAGE
   pop A
   asl   A
   mov   X, A
   RAM_SETPAGE_IDX >CSD_waSnsResult
   mov A, [X+CSD_waSnsResult+LSB]
   RAM_SETPAGE_IDX >CSD_waSnsBaseline
   mov [X+CSD_waSnsBaseline+LSB], A
   RAM_SETPAGE_IDX >CSD_waSnsResult
   mov A, [X+CSD_waSnsResult+MSB]
   RAM_SETPAGE_IDX >CSD_waSnsBaseline
   mov [X+CSD_waSnsBaseline+MSB], A
   RAM_EPILOGUE RAM_USE_CLASS_3
   ret
.ENDSECTION

.SECTION
;-----------------------------------------------------------------------------
;  FUNCTION NAME: CSD_bIsAnySensorActive(void)
;
;  DESCRIPTION:
;    Checks to see if any sensor is currently active
;
;-----------------------------------------------------------------------------
;
;  ARGUMENTS:    None.
;  RETURNS:      1 if any active, 0 if none active
;  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.
;
 CSD_bIsAnySensorActive:
_CSD_bIsAnySensorActive:
   RAM_PROLOGUE RAM_USE_CLASS_4
   RAM_SETPAGE_CUR 0 ; direct access ram will always be in interrupt ram area

   mov [CSD_fIsPressed], 0
   mov   A,CSD_TotalSensorCount
   dec   A
.ThresholdLoop:                                       ; Loop through all sensors
   push  A
   call  CSD_bIsSensorActive
   cmp   A, 1
   jnz    .NotActive
   mov [CSD_fIsPressed], 1
.NotActive:
   pop   A
   dec   A
   jnc   .ThresholdLoop
   mov   A, [CSD_fIsPressed]

.NoneActive:
   RAM_EPILOGUE RAM_USE_CLASS_4
   ret
.ENDSECTION

.SECTION
;-----------------------------------------------------------------------------
;  FUNCTION NAME: CSD_UpdateAllBaselines(void)
;
;  DESCRIPTION:
;    Scans all sensors to find their raw count values
;
;-----------------------------------------------------------------------------
;
;  ARGUMENTS:    None.
;  RETURNS:      None
;  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.
;
 CSD_UpdateAllBaselines:
_CSD_UpdateAllBaselines:
   RAM_PROLOGUE RAM_USE_CLASS_4

   mov   A,CSD_TotalSensorCount
   dec   A
.ThresholdLoop:                                       ; Loop through all sensors
   push  A
   call  CSD_UpdateSensorBaseline
   pop   A
   dec   A
   jnc   .ThresholdLoop

   RAM_EPILOGUE RAM_USE_CLASS_4
   ret
.ENDSECTION

IF CSD_SLIDERS_EXIST
.SECTION
;-----------------------------------------------------------------------------
;  FUNCTION NAME: CSD_wGetCentroidPos(BYTE bSnsGroup)
;
;  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 => Sensor Group
;       Sensor Group = 0 for the independent sensors group
;       Sensor Group = 1 for the first slider group
;       Sensor Group = 2 for the second slider group
;
;  RETURNS:
;      iCtrdPos -> 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.
;
 CSD_wGetCentroidPos:
_CSD_wGetCentroidPos:
; Legacy function name labels below, do not use for new designs
 CSD_bGetCentroidPos:
_CSD_bGetCentroidPos:
 CSD_iGetCentroidPos:
_CSD_iGetCentroidPos:
; End legacy function names
   RAM_PROLOGUE RAM_USE_CLASS_3
   RAM_SETPAGE_CUR 0 ; direct access ram will always be in interrupt ram area
   RAM_X_POINTS_TO_INDEXPAGE

; First get the starting location and size of this sensor group
   asl A ; multiply by two to get diplex
   mov X, A
   index CSD_Diplex_Table ; get the diplex table MSB and LSB
   mov [CSD_bDiplexMSB], A
   mov A, X
   inc A
   index CSD_Diplex_Table
   mov [CSD_bDiplexLSB], A
   mov A, X
   mov [CSD_bStartIndex], A ; Use bStartIndex as a temp storage byte
   asl A
   add [CSD_bStartIndex], A
   mov A, [CSD_bStartIndex] ; A now has slider offset multiplied by six
   mov X, A
   index CSD_Group_Table ; get first sensor index
   mov [CSD_bEndOfArray], A
   mov [CSD_bCurPos], A
   mov [CSD_bStartIndex], A
   mov A, X
   inc A
   index CSD_Group_Table ; get size of group
   add [CSD_bEndOfArray], A ; Store for later
   mov A, X
   add A, 2
   index CSD_Group_Table ; get if diplexed or not and max size of centroid (data = 0 if not diplexed)
   mov [CSD_bDiplexInfo], A ; Store for later
   mov A, X
   add A, 3
   mov [CSD_bSnsMaskPtr], A ; Store starting position in an unused temp CSD_bSnsMaskPtr

; First find the starting location and size of the largest centroid
   mov [CSD_bBiggestCtrdStartPos], 0
   mov [CSD_bBiggestCtrdSize], 0
   mov [CSD_bCurCtrdStartPos], 0
   mov [CSD_bCurCtrdSize], 0

   mov A, [CSD_bStartIndex]
   asl A ; multiply by two because we are using ints
   mov X, A

.LocateCtrd:
   RAM_SETPAGE_IDX >CSD_waSnsDiff
   mov A, [X+CSD_waSnsDiff]
   jnz .DiffIsNotZero
   mov A, [X+CSD_waSnsDiff+1]
   jnz .DiffIsNotZero
; The difference is zero, we either just ended a centroid or are between centroids
; First check the Current Size, if zero, we are in the middle of zeros, else, we just ended
.DifferenceIsZero:
   mov A, [CSD_bCurCtrdSize]
   jz .LocateCtrdNextSensor
; A centroid just ended.  Is it the largest centroid?
   cmp A, [CSD_bBiggestCtrdSize]
   jc .ClearCurCtrdSize
; It is the biggest so far, store as biggest
   mov [CSD_bBiggestCtrdSize], [CSD_bCurCtrdSize]
   mov [CSD_bBiggestCtrdStartPos], [CSD_bCurCtrdStartPos]
.ClearCurCtrdSize:
   mov [CSD_bCurCtrdSize], 0
   jmp .LocateCtrdNextSensor

;The difference is not zero, we either just started, or are in the middle of a centroid
.DiffIsNotZero:
   mov A, [CSD_bCurCtrdSize]
   jnz .IncCtrdSize
; Centroid just began, store the start pos
   mov A, [CSD_bCurPos]
   mov [CSD_bCurCtrdStartPos], A
.IncCtrdSize:
   inc [CSD_bCurCtrdSize]
; Find out the next position
.LocateCtrdNextSensor:
   inc X
   inc X
   inc [CSD_bCurPos]
   mov A, [CSD_bCurPos]
   cmp A, [CSD_bEndOfArray] ; Check for the end of the array
   jc .LocateCtrd
; Either at end of array, or diplexed
   tst [CSD_bDiplexInfo], 0xff ; check if diplexed
   jz .EndOfLocateCtrd
; Diplexed, so now find out if at end
   sub A, [CSD_bEndOfArray] ; subtract the size of the array
   add A, [CSD_bStartIndex] ; for comparison
   cmp A, [CSD_bEndOfArray] ; Check for the end of the array
   jnc .EndOfLocateCtrd
; Not the end of the diplexed array, find out offset of next position
   mov A, [CSD_bCurPos]
   sub A, [CSD_bStartIndex]
   add A, [CSD_bDiplexLSB]
   mov X, A
   mov A, [CSD_bDiplexMSB]
   adc A, 0 ; check if carry
   romx ; get the offset from the start
   add A, [CSD_bStartIndex]
   asl A ; because using ints
   mov X, A
   jmp .LocateCtrd
.EndOfLocateCtrd:
; Need to check if the current centroid is biggest
   mov A, [CSD_bCurCtrdSize]
   jz .CalculateCtrd
; There was a centroid at the end, is it biggest?
   cmp A, [CSD_bBiggestCtrdSize]
   jc .CalculateCtrd ; if two are the same size, last one wins
; It is the biggest so far, store as biggest
   mov [CSD_bBiggestCtrdSize], [CSD_bCurCtrdSize]
   mov [CSD_bBiggestCtrdStartPos], [CSD_bCurCtrdStartPos]

.CalculateCtrd:
   mov A, [CSD_bBiggestCtrdSize]
   jz .COM_Error
   mov A, [CSD_bDiplexInfo] ; check if diplexed
   jz .COM_Init
   cmp [CSD_bBiggestCtrdSize], 2
   jc .COM_Error ; for diplexing, one or less is too small
   cmp A, [CSD_bBiggestCtrdSize]
   jc .COM_Error ; for diplexing, check if centroid is too large

.COM_Init:
   mov A, [CSD_bBiggestCtrdStartPos] ; Use for current position, may be diplexed
   mov [CSD_bCurPos], A
   mov [CSD_wDenom+MSB], 0 ; Clear the numerator and denominator
   mov [CSD_wDenom+LSB], 0
   mov [CSD_dNumer+MMSB], 0
   mov [CSD_dNumer+MLSB], 0
   mov [CSD_dNumer+LMSB], 0
   mov [CSD_dNumer+LLSB], 0

.COM_NextPosition:
   mov A, [CSD_bCurPos]
   cmp A, [CSD_bEndOfArray]
   jnc .COM_CheckDiplex
   asl A
   mov X, A
   jmp .COM_AddElement
; Must be diplexed, check for safe measure
.COM_CheckDiplex:
   tst [CSD_bDiplexInfo], 0xff ; check if diplexed
   jz .COM_Compute
; Find out offset of next position
   mov A, [CSD_bCurPos]
   sub A, [CSD_bStartIndex]
   add A, [CSD_bDiplexLSB]
   mov X, A
   mov A, [CSD_bDiplexMSB]
   adc A, 0 ; check if carry
   romx ; get the offset from the start
   add A, [CSD_bStartIndex]
   asl A ; because using ints
   mov X, A
.COM_AddElement:
; Subtract the noise from the difference, this will yield a more accurate result
   RAM_SETPAGE_IDX >CSD_waSnsDiff
   mov A, [CSD_bNoiseThreshold]
   sub [X+CSD_waSnsDiff+LSB], A
   sbb [X+CSD_waSnsDiff+MSB], 0
; Store a copy of the sensor difference in CSD_dMultTempX
   mov A, [X+CSD_waSnsDiff+LSB]
   mov [CSD_dMultTempX+LLSB], A
; Add LSB to denominator
   add [CSD_wDenom+LSB], A
   mov A, [X+CSD_waSnsDiff]
   mov [CSD_dMultTempX+LMSB], A
   mov [CSD_dMultTempX+MLSB], 0
   mov [CSD_dMultTempX+MMSB], 0
; Add MSB to denominator
   adc [CSD_wDenom], A
   mov A, [CSD_bCurPos]
   sub A, [CSD_bStartIndex] ; we need offset from beginning of group
   mov [CSD_wDivBtwSns+MSB], 0
   mov [CSD_wDivBtwSns+LSB], A

   call .MultiplyNumeratorWhole

   inc [CSD_bCurPos]
   dec [CSD_bBiggestCtrdSize]
   jz .COM_Compute
   jmp .COM_NextPosition

.COM_Compute:
   mov A, [CSD_dNumer+LLSB] ; Move numerator to temp
   mov [CSD_dMultTempX+LLSB], A
   mov [CSD_dMultTempY+LLSB], A
   mov A, [CSD_dNumer+LMSB]
   mov [CSD_dMultTempX+LMSB], A
   mov [CSD_dMultTempY+LMSB], A
   mov A, [CSD_dNumer+MLSB]
   mov [CSD_dMultTempX+MLSB], A
   mov [CSD_dMultTempY+MLSB], A
   mov A, [CSD_dNumer+MMSB]
   mov [CSD_dMultTempX+MMSB], A
   mov [CSD_dMultTempY+MMSB], A

   mov [CSD_dNumer+MMSB], 0 ; Clear numerator
   mov [CSD_dNumer+MLSB], 0
   mov [CSD_dNumer+LMSB], 0
   mov [CSD_dNumer+LLSB], 0

   mov A, [CSD_bSnsMaskPtr] ; Retrieve starting position in index of the DivBtwSns
   push A
   index CSD_Group_Table ; get MSB of whole multiplier
   mov [CSD_wDivBtwSns+MSB], A
   pop A
   inc A
   push A
   index CSD_Group_Table ; get LSB of whole multiplier
   mov [CSD_wDivBtwSns+LSB], A
   call .MultiplyNumeratorWhole ; Multiplies by whole part
   pop A
   inc A
   index CSD_Group_Table ; get byte of fractional multiplier
   mov [CSD_wDivBtwSns+LSB], A
   call .MultiplyNumeratorFraction ; Multiplies by fractional part

; Now do the division of the numerator and denominator

; Round up the temp by half of the denominator (0.5 gets 1)
   mov A, [CSD_wDenom+MSB]
   mov [CSD_dMultTempX+MSB], A
   mov A, [CSD_wDenom+LSB]
   mov [CSD_dMultTempX+LSB], A
   and F, ~0x04 ; Clear carry bit if set
   rrc [CSD_dMultTempX+MSB] ; divide denominator by 2
   rrc [CSD_dMultTempX+LSB]
   mov A, [CSD_dMultTempX+LSB]
   add [CSD_dNumer+LLSB], A ; add 1/2 denominator
   mov A, [CSD_dMultTempX+MSB]
   adc [CSD_dNumer+LMSB], A
   adc [CSD_dNumer+MLSB], 0
   adc [CSD_dNumer+MMSB], 0

; Compute the division of numerator divided by denominator
   asl [CSD_dNumer+LLSB]
   rlc [CSD_dNumer+LMSB]
   rlc [CSD_dNumer+MLSB]
   rlc [CSD_dNumer+MMSB]
   mov X, 16
.DivideLoop:
; Subtract the divisor or denominator from the MMSB MLSB dividend or numerator
   mov A, [CSD_wDenom+LSB]
   sub [CSD_dNumer+MLSB], A
   mov A, [CSD_wDenom+MSB]
   sbb [CSD_dNumer+MMSB], A
; Check if less than zero
   jnc .SetLSbToOneAndShift
.AddBackSetLSbToZeroAndShift:
; Less than zero so add back to dividend and shift a zero into the dividend
   mov A, [CSD_wDenom+LSB]
   add [CSD_dNumer+MLSB], A
   mov A, [CSD_wDenom+MSB]
   adc [CSD_dNumer+MMSB], A
   asl [CSD_dNumer+LLSB]
   rlc [CSD_dNumer+LMSB]
   rlc [CSD_dNumer+MLSB]
   rlc [CSD_dNumer+MMSB]
   dec X
   jnz .DivideLoop
   jmp .EndOfDivide
.SetLSbToOneAndShift:
   asl [CSD_dNumer+LLSB]
   or [CSD_dNumer+LLSB], 0x01
   rlc [CSD_dNumer+LMSB]
   rlc [CSD_dNumer+MLSB]
   rlc [CSD_dNumer+MMSB]
   dec X
   jnz .DivideLoop
.EndOfDivide:
; MMSB and MLSB have carry after shifted right once
   rrc [CSD_dNumer+MMSB]
   rrc [CSD_dNumer+MLSB]
; Load return value
   mov X, [CSD_wCtrdPos+MSB]
   mov A, [CSD_wCtrdPos+LSB]
   jmp .EndGetCtrdPos
.COM_Error:
; Load error return value
   mov A, 0xff
   mov X, 0xff
.EndGetCtrdPos:
; Algorithm is finished, position is in [CSD_wCtrdPos]
   RAM_EPILOGUE RAM_USE_CLASS_3
   ret

; Multiplication algorithm (for whole numbers)
.MultiplyNumeratorWhole:
   mov A, 0x01
.CheckToAddNext2xLSB:
   push A
   and A, [CSD_wDivBtwSns+LSB] ; See if current 2^x needs added
   jz .SkipAddAndShiftLeftLSB
   mov A, [CSD_dMultTempX+LLSB]
   add [CSD_dNumer+LLSB], A
   mov A, [CSD_dMultTempX+LMSB]
   adc [CSD_dNumer+LMSB], A
   mov A, [CSD_dMultTempX+MLSB]
   adc [CSD_dNumer+MLSB], A
   mov A, [CSD_dMultTempX+MMSB]
   adc [CSD_dNumer+MMSB], A
.SkipAddAndShiftLeftLSB:
   asl [CSD_dMultTempX+LLSB]
   rlc [CSD_dMultTempX+LMSB]
   rlc [CSD_dMultTempX+MLSB]
   rlc [CSD_dMultTempX+MMSB]
   pop A
   asl A
   jnc .CheckToAddNext2xLSB
   mov A, [CSD_wDivBtwSns+MSB]
   jz .EndMultiplyNumeratorWhole ; only multiply by MSB if needed
   mov A, 0x01
.CheckToAddNext2xMSB:
   push A
   and A, [CSD_wDivBtwSns+MSB] ; See if current 2^x needs added
   jz .SkipAddAndShiftLeftMSB
   mov A, [CSD_dMultTempX+LLSB]
   add [CSD_dNumer+LLSB], A
   mov A, [CSD_dMultTempX+LMSB]
   adc [CSD_dNumer+LMSB], A
   mov A, [CSD_dMultTempX+MLSB]
   adc [CSD_dNumer+MLSB], A
   mov A, [CSD_dMultTempX+MMSB]
   adc [CSD_dNumer+MMSB], A
.SkipAddAndShiftLeftMSB:
   asl [CSD_dMultTempX+LLSB]
   rlc [CSD_dMultTempX+LMSB]
   rlc [CSD_dMultTempX+MLSB]
   rlc [CSD_dMultTempX+MMSB]
   pop A
   asl A
   jnc .CheckToAddNext2xMSB
.EndMultiplyNumeratorWhole:
   ret

; Multiplication algorithm (for fractional numbers)
.MultiplyNumeratorFraction:
   and F, ~0x04 ; clear carry bit if set
   rrc [CSD_dMultTempY+MMSB]
   rrc [CSD_dMultTempY+MLSB]
   rrc [CSD_dMultTempY+LMSB]
   rrc [CSD_dMultTempY+LLSB]
   mov A, 0x80
.CheckToAddNextHalf:
   push A
   and A, [CSD_wDivBtwSns+LSB]
   jz .SkipAddAndShiftRight
   mov A, [CSD_dMultTempY+LLSB]
   add [CSD_dNumer+LLSB], A
   mov A, [CSD_dMultTempY+LMSB]
   adc [CSD_dNumer+LMSB], A
   mov A, [CSD_dMultTempY+MLSB]
   adc [CSD_dNumer+MLSB], A
   mov A, [CSD_dMultTempY+MMSB]
   adc [CSD_dNumer+MMSB], A
.SkipAddAndShiftRight:
   asr [CSD_dMultTempY+MMSB]
   rrc [CSD_dMultTempY+MLSB]
   rrc [CSD_dMultTempY+LMSB]
   rrc [CSD_dMultTempY+LLSB]
   pop A
   and F, ~0x04 ; clear carry bit if set
   rrc A
   jnc .CheckToAddNextHalf
   ret

.ENDSECTION
ENDIF
