it works spasmodically theses days. [one more nail in pbp coffin]

i find it will work with edge or chrome , sometimes incognito window works better


Code:
;****************************************************************
;*  Name    : I2C EEPROM                                        *
;*  Author  : Daniel T. Barber                                  *
;*  Notice  : Copyright (c) 2018                                *
;*          : No expressed or implied reliability               *
;*  Date    : 1/25/2018                                         *
;*  Version : 1.0                                               *
;*  Notes   : Written for PIC16F1877. If using a differnt PIC   *
;*          : adjust MSSP Module Variables consistent with      *
;*          : the specific PIC datasheet                        *
;*          : Written for use with LabX-1 development board     *
;*          : and 24LC64 EEPROM (WORD size memory addressing)   *
;*          : Adjust CTRL address value as necessary            *
;*          : Software I2C routines are for debugging           *
;*          : If necessary, uncommment routines in Main Code    *
;*                                                              *
;****************************************************************


@ ERRORLEVEL -306   ; turn off crossing page boundary message
 
#CONFIG
  CONFIG  FOSC = INTIO67
  CONFIG  PLLCFG = ON
  CONFIG  PRICLKEN = OFF
  CONFIG  FCMEN = OFF
  CONFIG  IESO = OFF
  CONFIG  PWRTEN = OFF
  CONFIG  BOREN = SBORDIS
  CONFIG  BORV = 190
  CONFIG  WDTEN = ON
  CONFIG  WDTPS = 32768
  CONFIG  CCP2MX = PORTC1
  CONFIG  PBADEN = OFF
  CONFIG  CCP3MX = PORTB5
  CONFIG  HFOFST = ON
  CONFIG  T3CMX = PORTC0
  CONFIG  P2BMX = PORTB5
  CONFIG  MCLRE = EXTMCLR
  CONFIG  STVREN = ON
  CONFIG  LVP = OFF
  CONFIG  XINST = OFF
  CONFIG  DEBUG = OFF
  CONFIG  CP0 = OFF
  CONFIG  CP1 = OFF
  CONFIG  CP2 = OFF
  CONFIG  CP3 = OFF
  CONFIG  CPB = OFF
  CONFIG  CPD = OFF
  CONFIG  WRT0 = OFF
  CONFIG  WRT1 = OFF
  CONFIG  WRT2 = OFF
  CONFIG  WRT3 = OFF
  CONFIG  WRTC = OFF
  CONFIG  WRTB = OFF
  CONFIG  WRTD = OFF
  CONFIG  EBTR0 = OFF
  CONFIG  EBTR1 = OFF
  CONFIG  EBTR2 = OFF
  CONFIG  EBTR3 = OFF
  CONFIG  EBTRB = OFF
#ENDCONFIG




  
define OSC 64
OSCCON = %11110000 
osctune.6=1           
ANSELb = 0
ANSELA = 0
ANSELC = 0
 
DEFINE LCD_DREG PORTB 
DEFINE LCD_DBIT 0 
DEFINE LCD_EREG PORTB 
DEFINE LCD_EBIT 5 
DEFINE LCD_RSREG PORTB 
DEFINE LCD_RSBIT 4 
Define LCD_Bits 4
DEFINE LCD_LINES 4 
Define LCD_Commandus 2000
Define LCD_DATAUS 50




;************ LCD Instruction Constants & Variables *************
Cmd                 Con     $FE     ;Used to send instructions to LCD
CLR                 Con     $01     ;Clears LCD & Homes Cursor
Cursor_Off          Con     $0C     ;Turns OFF Cursor
Cursor_Underline    Con     $0E     ;Turns on Underline cursor
Cursor_Block        Con     $0F     ;Turns on Blinking block cursor
Cursor_Right        Con     $14     ;Advance cursor 1 space to right
Cursor_Left         Con     $10     ;Advance cursor 1 space to left
Home                Con     $02     ;Sends Cursor to Home position
'LCD_PWR             VAR     PORTD.7 ;Connects LCD to VCC
Line_1              Con     $80     ;Position Cursor at beginning of line 1
Line_2              Con     $C0     ;Position Cursor at beginning of line 2
Scroll_Left         Con     $18     ;Scroll all lines 1 space to left
Scroll_Right        Con     $1C     ;Scroll all lines 1 space to right
Blank_Display       Con     $08     ;Blank display without clearing
Restore_Display     Con     $0C     ;Restores display with cursor hidden (same as Cursor_Off)
CG_RAM	            Con	    $40     ;Special-character RAM, address 0. 
DD_RAM	            Con	    $80     ;Display RAM, address 0


;************ I2C Variables ************
SCL     VAR     PORTC.3    ; Clock pin
SDA     VAR     PORTC.4    ; Data pin


;**************** General Variables ****************
I       VAR    word    ;General purpose counter


;**************** I2C Controller Variables **************** 
CTRL        Con      $A0     ;Specific address for this I2C device
Address_B   Var      byte    ;Use with EEPROM using byte memory addresses 
Address_W   Var      Word    ;Use with EEPROM using word memory addresses 
Data_Out_B  VAR      byte    ;Byte Data to be shifted out
Data_Out_W  VAR      word    ;Word Data to be shifted out
Data_In_B   Var      byte    ;Byte Data to be shifted In
Data_In_W   Var      word    ;Word Data to be shifted In
I2C_DATA    var      byte    ;Hardare I2C variable
tries       var      byte
i2c_error    var      byte




;**************** Hardware I2C Variables ****************     
CTRL_W          con     $A0
CTRL_R          con     $A1


;************ MSSP Module Variables ************* 
WCOL        var     SSP1CON1.7   ;Write collision indicator
SSPOV       var     SSP1CON1.6   ;Receive overflow indicator
SSPEN       var     SSP1CON1.5   ; I2C Serial Port Enable
ACKSTAT     var     SSPCON2.6   ;Slave ACK Response: 1 = ACK received, 0 NACK received
ACKDT       var     SSPCON2.5   ;Master ACK Response: 1 = send ACK, 0 send NACK     
ACKEN       var     SSPCON2.4   ;Send the Master ACK Response
RCEN        var     SSPCON2.3   ;Set Master to Receive Mode - Auto clears at end of receive
PEN         var     SSPCON2.2   ;Send Stop Sequence
RSEN        var     SSPCON2.1   ;Send Repeated Start Sequence
SEN         var     SSPCON2.0   ;Send Start Sequence
TX_Stat     var     SSPSTAT.2   ;Status of TX Sequence: 1 = TX in progress, 0 = TX finished
BF          var     SSPSTAT.0   ;Buffer Full Status bit: 1 = Receive Complete, 0 = Receive not complete
SSPIF       var     PIR1.3      ;Serial Port Interrupt flag: 1 = operation complete


;************ Configure MSSP Module *************
SSP1CON1 = $28    ;Master Mode
SSPEN = 1       ; I2C enabled
SSPSTAT = $80   ;100 KHz bus
SSPADD = $26   ;Set Baud Rate


;************ Initialize *************
 PAUSE 1000
 Gosub Initialize_LCD
 PAUSE 100


;************ Main Code *************
Main:
do
;Software I2C routines
;Gosub Software_I2C_WB  ;Write byte sized data using PPB commands
;Gosub Software_I2C_RB  ;Read byte sized data using PPB commands
;Gosub Software_I2C_WW  ;Write Word sized data using PPB commands
;Gosub Software_I2C_RW  ;Read Word sized data using PPB commands


;Hardware I2C routines
gosub Hardware_I2C_WB   ;Write byte sized data using MSSP 
gosub Hardware_I2C_RB   ;Read byte sized data using MSSP
gosub Hardware_I2C_WW   ;Write word sized data using MSSP 
gosub Hardware_I2C_Rw   ;Read word sized data using MSSP
loop


;************ Sub-Routines ************
;************ Initialize LCD ************
Initialize_LCD:
'    high LCD_PWR    ;Turn on LCD
        pause 1000 ;Wait for LCD to power up
            Lcdout Cmd, Clr
                lcdout CMD,Cursor_off 
                    lcdout CMD, Line_1 + 5,  "I2C Demo" 
                        Pause 3000   ;Display message for 3 seconds
                             lcdout CMD,clr  ;Clear display 
Return


;************ Software I2C Byte Write *************
Software_I2C_WB:  ;Write byte sized data using PPB commands


  SSPEN = 0 ;MSSP module off
   
  Lcdout Cmd, Clr
  lcdout CMD, Line_1 + 2,"Software I2C" 
  lcdout CMD, Line_2, "Write Byte Variables"
  pause 2000
 
   For I = 0 to 5 Step 1
       address_W = I  ;Address_W is a word size variable
            Data_Out_B = I * 10   ;Data_Out_B is byte size variable
               i2cwrite SDA, SCL, $A0, address_W,[Data_Out_B]
                    Pause 10
                        Lcdout Cmd, Clr
                            lcdout CMD, Line_1,  "Write Address = ", dec address_W
                                lcdout CMD, Line_2, "Byte Data = ", dec Data_Out_B 
                                    pause 1000
                                        next I
  return


;************ Software I2C Byte Read *************
Software_I2C_RB:  ;Read byte sized data using PPB commands


SSPEN = 0 ;MSSP module off
                                          
 Lcdout Cmd, Clr
 lcdout CMD, Line_1 + 2,"Software I2C" 
 lcdout CMD, Line_2,  "Read Byte Values" 
 pause 2000
                                         
    For I = 0 to 5 step 1
        address_W = I
           i2cread SDA, SCL, $A0, address_W,[Data_In_B] 
                Pause 10
                    Lcdout Cmd, Clr
                        lcdout CMD, Line_1,  "Read Address = ", dec address_W
                            lcdout CMD, Line_2, "Byte Data = ", dec Data_In_B
                                pause 1000
                                    next I  
Return                                    
                                    
;************ Hardware I2C Write Byte Sized Variables  *************                                                                      
Hardware_I2C_WB:


SSPEN = 1 ;MSSP module on
   
  Lcdout Cmd, Clr
  lcdout CMD, Line_1 + 2,"Hardware I2C" 
  lcdout CMD, Line_2 + 2, "Byte Variables"
  pause 2000
  
  ;************ Write to EEPROM *************
   For I = 0 to 5 Step 1
       address_W = I  ;Address_W is a word size variable
            Data_Out_B = (I * 10) + 1   ;Data_Out_B is byte size variable
               
Lcdout Cmd, Clr
    lcdout CMD, Line_1,  "Write Address = ", dec address_W
        lcdout CMD, Line_2, "Byte Data = ", dec Data_Out_B
 
gosub I2C_START   ;Begin I2C sequence


I2C_DATA = CTRL_W  ;Send Control + write command
gosub I2C_TX 


'I2C_DATA = address_W.byte1  ;Address high byte 
'gosub I2C_TX 
 
I2C_DATA = address_W.byte0  ;Address low byte 
gosub I2C_TX 


I2C_DATA = Data_Out_B   ;Data byte
gosub I2C_TX 


gosub  I2C_STOP   ;Stop Write sequence


pause 1000       ;Delay for LCD display of values


Next I


return


;************ Hardware I2C Read Byte Sized Variables *************
Hardware_I2C_RB:  ;Read byte sized data using hardware I2C


SSPEN = 1 ;MSSP module on
                                        
 Lcdout Cmd, Clr
  lcdout CMD, Line_1 + 2,"Hardware I2C" 
 lcdout CMD, Line_2 + 1,  "Read Byte Values" 
 pause 2000
                                         
 For I = 0 to 5 step 1
     address_W = I                      
         
gosub I2C_START   ;Begin I2C sequence


I2C_DATA = CTRL_W  ;Send Control + write command
gosub I2C_TX 


'I2C_DATA = address_W.byte1  ;Address high byte 
'gosub I2C_TX 
 
I2C_DATA = address_W.byte0  ;Address low byte 
gosub I2C_TX 


gosub I2C_Restart ;Reset bus before sending Read control byte 


I2C_DATA = CTRL_R  ;Send Control + read command
gosub I2C_TX 


gosub I2C_RX   ;Clock data into MSSP buffer


gosub I2C_NACK ;Terminate EPPROM sending data


gosub  I2C_STOP   ;Stop Read sequence


Data_IN_B = SSPBUF  ;Read data from MSSP buffer


Lcdout Cmd, Clr
    lcdout CMD, Line_1,  "Read Address = ", dec address_W
        lcdout CMD, Line_2, "Byte Data = ", dec Data_In_B
            pause 1000  
Next I


return


;************ Software I2C Word Write *************
Software_I2C_WW:  ;Write word sized data using PPB commands


  SSPEN = 0 ;MSSP module off
   
  Lcdout Cmd, Clr
  lcdout CMD, Line_1 + 2,"Software I2C" 
  lcdout CMD, Line_2, "Write Word Variables"
  pause 2000
 
   For I = 0 to 10 Step 2
       address_W = I  ;Address_W is a word size variable
            Data_Out_W = I * 1000   ;Data_Out_W is word size variable
               i2cwrite SDA, SCL, $A0, address_W,[Data_Out_W.byte1,Data_Out_W.byte0]
                    Pause 10
                        Lcdout Cmd, Clr
                            lcdout CMD, Line_1,  "Write Address = ", dec address_W
                                lcdout CMD, Line_2, "Word Data = ", dec Data_Out_W 
                                    pause 1000
                                        next I
return


;************ Software I2C Read Word *************
Software_I2C_RW:  ;Read byte sized data using PPB commands
SSPEN = 0 ;MSSP module off
                                          
 Lcdout Cmd, Clr
   lcdout CMD, Line_1 + 2,"Software I2C" 
 lcdout CMD, Line_2,  "Read Word Values" 
 pause 2000
                                         
    For I = 0 to 10 step 2
        address_W = I
           i2cread SDA, SCL, $A0, address_W,[Data_In_W.byte1,Data_In_W.byte0]
                Pause 10
                    Lcdout Cmd, Clr
                        lcdout CMD, Line_1,  "Read Address = ", dec address_W
                            lcdout CMD, Line_2, "Word Data = ", dec Data_In_W
                                pause 1000
                                    next I  
Return                                    
                                    
;************ Hardware I2C Write Word Sized Variables  *************                                                                      
Hardware_I2C_WW:


SSPEN = 1 ;MSSP module on
   
  Lcdout Cmd, Clr
  lcdout CMD, Line_1 + 2,"Hardware I2C" 
  lcdout CMD, Line_2 + 2, "Word Variables"
  pause 2000
  
  ;************ Write to EEPROM *************
   For I = 0 to 10 Step 2  ;Word values require 2 bytes
       address_W = I  ;Address_W is a word size variable
            Data_Out_W = I * 1000  ;Data_Out_W is word size variable
               
Lcdout Cmd, Clr
    lcdout CMD, Line_1,  "Write Address = ", dec address_W
        lcdout CMD, Line_2, "Word Data = ", dec Data_Out_W
            pause 1000      
        
gosub I2C_START   ;Begin I2C sequence


I2C_DATA = CTRL_W  ;Send Control + write command
gosub I2C_TX 


'I2C_DATA = address_W.byte1  ;Address high byte 
'gosub I2C_TX 
 
I2C_DATA = address_W.byte0  ;Address low byte 
gosub I2C_TX 


I2C_DATA = Data_Out_W.byte1  ;Word value high byte
gosub I2C_TX 


I2C_DATA = Data_Out_W.byte0  ;Word value low byte
gosub I2C_TX 


gosub  I2C_STOP   ;Stop Write sequence


Next I


return


;************ Hardware I2C Read Word Sized Variables *************
Hardware_I2C_RW:  ;Read word sized data using hardware I2C
;Word is the result of seqentially reading two consecutive memory addresses
SSPEN = 1 ;MSSP module on
                                        
 Lcdout Cmd, Clr
 lcdout CMD, Line_1 + 2,"Hardware I2C" 
 lcdout CMD, Line_2 + 1,"Read Word Values" 
 pause 2000
                                         
 For I = 0 to 10 step 2 ;Word values occupy two bytes
     address_W = I                      
         
gosub I2C_START   ;Begin I2C sequence


I2C_DATA = CTRL_W  ;Send Control + write command
gosub I2C_TX 


'I2C_DATA = address_W.byte1  ;Address high byte 
'gosub I2C_TX 
 
I2C_DATA = address_W.byte0  ;Address low byte 
gosub I2C_TX 


gosub I2C_Restart ;Reset I2C bus before sending read command


I2C_DATA = CTRL_R  ;Send Control + read command
gosub I2C_TX 


gosub I2C_RX    ;receive byte
Data_IN_w.byte1 = SSPBUF   ;High byte of word variable


gosub I2C_ACK   ;Signal EEPROM to send next byte 


gosub I2C_RX  ;receive byte
Data_IN_w.byte0 = SSPBUF  ;Low byte of word variable
gosub I2C_nACK
gosub  I2C_STOP   ;Stop Read sequence


Lcdout Cmd, Clr
    lcdout CMD, Line_1,  "Read Address = ", dec address_W
        lcdout CMD, Line_2, "Word Data = ", dec Data_In_W
            pause 1000  
Next I


return


;**************** I2C Hardware Subroutines ****************


I2C_Restart:  ;Send Restart Sequence
RSEN = 1 ; RSEN - Repeat Start Condition Enable Bit
SSPIF = 0; Reset Interrupt  flag 
WHILE SSPIF = 0 : WEND ; Wait for SSPIF to be set to 1 by Re-start sequence 
RETURN


;=====================================
I2C_START:  ;Send Start Sequence 
SEN = 1 ; SEN - Start Condition Enable Bit 
SSPIF = 0;  Must reset flag
WHILE SSPIF = 0 : WEND ; Wait for SSPIF to be set to 1 by Start sequence 
RETURN


;=====================================
I2C_RX:
RCEN = 1 ; RCEN - Enable receive mode
SSPIF = 0;  Must reset flag
WHILE SSPIF = 0 : WEND ; Wait for SSPIF to be set to 1 by Receive sequence 
;pause 1
Return


;=====================================
I2C_TX:
;tries=5   ;see below
SSPBUF = I2C_DATA ; Move data to SSPBUF
WHILE TX_Stat  : WEND
WHILE ACKSTAT : WEND  ;or use something like this for a timeout
 ;timeout if no ack
'WHILE (ACKSTAT&&tries)   ;wait for slave to respond
'tries=tries-1
'pauseus 15
'WEND
'if !tries then i2c_error=1
Return






;=====================================
I2C_STOP: ;Send Sotp Sequence
PEN = 1 ; PEN - send stop bit
SSPIF = 0;  Must reset flag
WHILE SSPIF = 0 : WEND ; Wait for SSPIF to be set to 1 by Stop sequence 
;pause 1
Return


;=====================================
I2C_NACK:  ;Send NACK 
ACKDT = 1 ; ACKDT - Set Ack bit to NotAck
ACKEN = 1 ; ACKEN - send ACKDT bit
SSPIF = 0;  Must reset flag
WHILE SSPIF = 0 : WEND ; Wait for SSPIF to be set to 1 by NACK sequence 
Return


;=====================================
I2C_ACK:  ;Send ACK
ACKDT = 0 ; ACKDT - Set Ack bit to Ack
ACKEN = 1 ; ACKEN - send ACKDT bit
SSPIF = 0;  Must reset flag
WHILE SSPIF = 0 : WEND ; Wait for SSPIF to be set to 1 by ACK sequence 
'pause 1
Return