Code:
	'****************************************************************'*  Name    : MAX30102  FOR PIC 18 DEMO                         *
'*  Author  :  Richard                                          *
'*  Notice  :                                                   *
'*          :                                                   *
'*  Date    : 9/1/2022                                          *
'*  Version : 1.0                                               *
'*  Notes   : MAX30102                                          *        
'*          :18f26k22 @64Mhz                                    *
'****************************************************************
 
  #CONFIG   ;  The PBP configuration for the PIC18F26K22 is:
    CONFIG FOSC     = INTIO67	       
    CONFIG PLLCFG   = OFF	        ;Oscillator multiplied by 4                       
    CONFIG PRICLKEN  = ON	        ;Primary clock enabled
    CONFIG FCMEN     = OFF	        ;Fail-Safe Clock Monitor disabled
    CONFIG IESO      = OFF	        ;Oscillator Switchover mode disabled
    CONFIG  BOREN    = SBORDIS      ; Brown-out Reset enabled in hardware only (SBOREN is disabled)
    CONFIG  WDTEN    = ON           ; WDT is always enabled. SWDTEN bit has no effect                     ;|
    CONFIG  WDTPS    = 32768        ; 1:32768 ---> HERE enable the watchdog timer with a 1:32768 postscale;|
    CONFIG  PWRTEN   = ON
    CONFIG  HFOFST   = ON           ; HFINTOSC output and ready status are not delayed by the oscillator stable status
    CONFIG  MCLRE    = EXTMCLR      ; MCLR pin enabled, RE3 input pin disabled
    CONFIG  LVP      = OFF          ; Single-Supply ICSP disabled
    CONFIG  XINST    = OFF          ; Instruction set extension and Indexed Addressing mode disabled (Legacy mode)
    CONFIG  DEBUG    = OFF          ; Disabled
    CONFIG  CP0 = OFF             ; Block 0 (000800-003FFFh) not code-protected
    CONFIG  CP1 = OFF             ; Block 1 (004000-007FFFh) not code-protected
    CONFIG  CP2 = OFF             ; Block 2 (008000-00BFFFh) not code-protected
    CONFIG  CP3 = OFF             ; Block 3 (00C000-00FFFFh) not code-protected
    CONFIG  CPB = OFF             ; Boot block (000000-0007FFh) not code-protected
    CONFIG  CPD = OFF             ; Data EEPROM not code-protected
    CONFIG  WRT0 = OFF            ; Block 0 (000800-003FFFh) not write-protected
    CONFIG  WRT1 = OFF            ; Block 1 (004000-007FFFh) not write-protected
    CONFIG  WRT2 = OFF            ; Block 2 (008000-00BFFFh) not write-protected
    CONFIG  WRT3 = OFF            ; Block 3 (00C000-00FFFFh) not write-protected
    CONFIG  WRTC = OFF            ; Configuration registers (300000-3000FFh) not write-protected
    CONFIG  WRTB = OFF            ; Boot Block (000000-0007FFh) not write-protected
    CONFIG  WRTD = OFF            ; Data EEPROM not write-protected
    CONFIG  EBTR0 = OFF           ; Block 0 (000800-003FFFh) not protected from table reads executed in other blocks
    CONFIG  EBTR1 = OFF           ; Block 1 (004000-007FFFh) not protected from table reads executed in other blocks
    CONFIG  EBTR2 = OFF           ; Block 2 (008000-00BFFFh) not protected from table reads executed in other blocks
    CONFIG  EBTR3 = OFF           ; Block 3 (00C000-00FFFFh) not protected from table reads executed in other blocks
    CONFIG  EBTRB = OFF           ; Boot Block (000000-0007FFh) not protected from table reads executed in other blocks
 #ENDCONFIG  
 goto overasm  
 asm
PutMulResult?D macro Din
    MOVE?BB   Din, R2
    MOVE?BB   Din + 1, R2 + 1
    MOVE?BB   Din + 2, R0
    MOVE?BB   Din + 3, R0 + 1
    RST?RP
  endm
 endasm
 overasm:
define  OSC 64
OSCCON    = %01110000   ; 16Mhz
OSCTUNE.6 = 1           ; Enable 4x PLL
while ! osccon2.7 :WEND ; to make sure the pll has stabilised before you run any other code
   
TRISC = %11011000                  
ANSELC=0
ANSELB=0
#DEFINE    DEBUGING 1
DEFINE DEBUG_REG PORTB
DEFINE DEBUG_BIT 7
DEFINE DEBUG_BAUD 9600
DEFINE DEBUG_MODE 0
SDA     var portc.4  
SCL     VAR portc.3  
reg        var BYTE
fifo       var byte[6] bank0
addr       var byte 
REVISION   var byte
PARTID     var byte
buffer     var word[384] 
ptr        var byte
btr        var byte
index      var word
average    var byte[4] bank0
ave        var word
peaks      var byte[5]
lastpeak   var word 
lpfdata    var word[192]
result     var word ext
result1    var word ext
@result  =  _fifo 
@result1 =  _fifo + 3
;-----------------------  REGISTER -------------------------
REG_TEMP_INT         con $1F
REG_TEMP_FRAC        con $20
REG_TEMP_CONFIG      con $21
REG_PART_REVISION    con $FE
REG_MODE             con $09
REG_SPO2_CONFIG      con $0A        ;SPO2_ADC_RGE[6:5]SPO2_SR[4:2]LED_PW[1:0]
REG_LED1_PA          con $0C
REG_LED2_PA          con $0D
FIFO_WR_PTR          con $04        ;FIFO_WR_PTR[4:0]
FIFO_RD_PTR          con $06
FIFO_DATA            con $07
FIFO_CONFIG          con $08        ;FIFO_A_FULL[3:0]   SMP_AVE[7:5]
OVF_COUNTER          con $05
STATUS1              con 0          ;A_FULL[7]
INTERRUPT_EN         con 2
' -----------------------------------------------------------------------------|  
#IFDEF  DEBUGING
    LATB.7=1
    PAUSE 2000
    DEBUG 13,10,  "READY"
#ENDIF
    ADDR = $ae     ; addr is  0x57 << 1
    reg = REG_PART_REVISION
    i2cread  SDA,scl,ADDR,reg,[REVISION,PARTID]
    reg = REG_MODE 
    i2cwrite  SDA,scl,ADDR,reg,[3] 
    reg = REG_SPO2_CONFIG
    i2cwrite  SDA,scl,ADDR,reg,[$20]
    reg = REG_LED2_PA 
    i2cwrite  SDA,scl,ADDR,reg,[10]
    reg = REG_LED1_PA 
    i2cwrite  SDA,scl,ADDR,reg,[10]
    reg = FIFO_CONFIG  
    i2cwrite  SDA,scl,ADDR,reg,[16]        
    reg = INTERRUPT_EN  
    i2cwrite  SDA,scl,ADDR,reg,[$E0]
    DEBUG 13,10,  "PART ID: 0X",hex PARTID,"/0X",hex REVISION
start:
    reg= REG_TEMP_CONFIG
    i2cwrite  SDA,scl,ADDR,reg,[1] 
    reg= REG_TEMP_INT        
    i2cread  sda,scl,ADDR,reg,[fifo[0],fifo[1]]
    DEBUG 13,10, "TEMP: ",DEC fifo[0],".",DEC2( fifo[1]<<6)
    GOSUB AQUIRE
    pause 2000
goto start
aquire:
    reg= FIFO_WR_PTR
    i2cwrite  SDA,scl,ADDR,reg,[0]
    reg= FIFO_RD_PTR
    i2cwrite  SDA,scl,ADDR,reg,[0]
    reg = OVF_COUNTER
    i2cwrite sda,scl,ADDR,reg,[0]
    asm
    banksel 0 
    clrf _average
    clrf _average+1
    clrf _average+2
    clrf _average+3
    endasm
 FOR index = 0 TO 255 STEP 0
    btr = 0
    reg = STATUS1
    WHILE (btr & 192) = 0
        i2cread  sda,scl,ADDR,reg,[btr]
    WEND
    reg = FIFO_WR_PTR
    i2cread  SDA,scl,ADDR,reg,[Ptr]
    reg = FIFO_RD_PTR
    i2cread  SDA,scl,ADDR,reg,[btr]
    btr = (ptr - btr) &  31
    WHILE btr
        reg = FIFO_DATA           ;---------ir----------;===========red===========
        i2cread  sda,scl,ADDR,reg,[FIFO[5],FIFO[4],FIFO[3],FIFO[2],FIFO[1],FIFO[0]]
        asm         ;ROTATE READING TO GET SUFFICIENT RESOLOUTION INTO lower WORD
    banksel 0
    bcf STATUS,C
    RRCF  _fifo + 2 ,f
    RRCF  _fifo + 1 ,f
    RRCF  _fifo     ,f
    bcf STATUS,C
    RRCF  _fifo + 2 ,f
    RRCF  _fifo + 1 ,f
    RRCF  _fifo     ,f
    bcf STATUS,C
    RRCF  _fifo + 5 ,f
    RRCF  _fifo + 4 ,f
    RRCF  _fifo + 3 ,f
    bcf STATUS,C
    RRCF  _fifo + 5 ,f
    RRCF  _fifo + 4 ,f
    RRCF  _fifo + 3 ,f
    
    movf  _fifo  ,w         ;RED AVERAGE
    addwf  _average,f
    movf  _fifo + 1 ,w
    bnc s1   
    incf   _average + 1,f
s1    
    addwf  _average + 1,f
    movf  _fifo + 2 ,w
    bnc    s2
    incf   _average + 2,f
s2    
    bnc     s3
    incf   _average + 3 ,f
s3  
endasm
        buffer[index] = result  ;red
        index = index + 1
        buffer[index] = result1 ;ir
        index = index + 1
        btr = btr - 1
    WEND
NEXT  
    DEBUG 13,10,hex2 average[3],hex2 average[2],hex2 average[1],hex2 average  
    @ PutMulResult?D _average   ;RED AVERAGE
    ave  = DIV32 128            ;RED AVERAGE
    reg = OVF_COUNTER
    i2cread sda,scl,ADDR,reg,[reg ] 
    DEBUG 13,10,"OverFlows ",DEC reg,9,dec ave,9,hex ave
    FOR index = 0 TO 255 STEP 0
        ave = (ave ** 62259) + (buffer[index] ** 3276 )
        lpfdata[index>>1]=ave 
              ;.....lpf..;;;;----red-----;;;;======-ir-========
        DEBUG 13,10,dec ave,9,dec buffer[index],9,dec buffer[index+1]
        index = index + 2
    NEXT 
 RETURN
 
				
Bookmarks