DT has been helping me to figure out how to bring my application into sleep mode and still be able to awaken it when a USB plug-in is detected. I have followed his instructions explicitly and the code does now operate the USB interface and the INT2_INT interrupt as intended, however I still have a problem in getting the unit to properly go into SLEEP mode and awaken when USB is plugged in. I have included a complete listing of my current code below in hopes someone can help me figure out why the SLEEP mode is not allowing the USB plug-in to wake it up.
As you see in my Note just before the @ SLEEP and @ NOP statements (see RED text), everything works as intended up to that point of the code, but as soon as I uncomment the @ SLEEP and @ NOP statements, although the unit does go into sleep mode, it won’t wake up on USB plug-in….. nor do the INT2_INT interrupts continue to work.

Would REALLY appreciate anyone's help on this. Solving this problem will basically complete my development of this PBPro application. The help of the forum members has been outstanding and greatly appreciated.

Code:
' -----------------------[ Program Description ]--------------------------
'  PICBASIC PRO program for Ultrasonic measurement & USB ops *
'    1)  Initializes 2x16 LCD display with EasyPic6.                     *
'    2)  Initializes DS1337 Real-time-clock.                             *
'    3)  Takes range measurement from SRF02 Ultrasonic sensor upon       *
'        programmed interrupt time from DS1337 RTC & displays results    *
'        on 2x16 display.                                                *
'    4)  Also displays time/date at time of measurment.                  *
'    5)  Also logs date-stamped measurement in EEPROM                    *
'    6)  When USB connection is detected, transfers log data to host PC  *
'        & receives time/date corrections when sent from PC host.        *
'                                                                        *
'*************************************************************************
' -----------------------[ Revision History ]-----------------------------
' Version 1.0   Started on 03/22/10
' Version 1.5   Fully functional TX mode completed (06/01/10)
' Version 1.5.1 Having difficulty with SLEEP mode operation

'-----------------18F2550/4550 Port/PIN Connections ]--------------------
'I/O pin connections to the 18F4550 MCU are as follows:
'PORTA.0 (02) connected to LCD D4.
'PORTA.1 (03) connected to LCD D5.
'PORTA.2 (04) connected to LCD D6.
'PORTA.3 (05) connected to LCD D7.
'PORTA.4 (06) connected to LCD RS.
'PORTA.5 (07) connected to LCD E.
'PORTB.0 (21) connected as I2C SDA output to DS1337. 
'PORTB.1 (22) connected as I2C SCL output to DS1337. 
'PORTB.2 (23) connected as INT2 interrupt from pin-3 (_INTA) of DS1337 RTC.
              ' Also senses pushbutton for manual range measurement. 
'PORTB.3 (24) connected as input from SQW/_INTB pin-7 of DS1337 RTC. 
'PORTB.4 (25) RB4 connected to Green LED to indicate USB connected & power on.
'PORTB.5 (26) RB5 not connected...used during test as mainloop heartbeat LED 
'PORTB.6 (27) connected as PGC for ICSP connection. 
'PORTB.7 (28) connected as PGD for ICSP connection. 
'PORTC.0 (11) RC0 connected to control external power to Ultrasonic sensors. 
'PORTC.1 (12) RC1 connected as an output to a Red LED for battery low.
'PORTC.2 (13) RC2 connected to LCD R/W. 
'PORTC.3 (14) RC3/Vbus connected to 470 pf capacitor for USB
'PORTC.4 (15) normally connected as USB D-.
'PORTC.5 (16) normally connected as USB D+.
'PORTC.6 (17) normally connected as RS232 TX. 
'PORTC.7 (18) normally connected as RS232 RX.

'INCLUDE "CodeSize.pbp"     'FOR TEST ONLY
DEFINE Measure 1
  
Pause 10     ' This statement is placed at beginning of code for ICD use

;-- if you un-comment these, you must comment the ones in the .inc file --
ASM  ; 18F2550/4550, 8mhz crystal
   __CONFIG    _CONFIG1L, _PLLDIV_2_1L & _CPUDIV_OSC4_PLL6_1L & _USBDIV_2_1L
   __CONFIG    _CONFIG1H, _FOSC_HSPLL_HS_1H
   __CONFIG    _CONFIG2L, _PWRT_ON_2L & _BOR_OFF_2L & _VREGEN_ON_2L
   __CONFIG    _CONFIG2H, _WDT_OFF_2H & _WDTPS_512_2H
   __CONFIG    _CONFIG3H, _PBADEN_OFF_3H
   __CONFIG    _CONFIG4L, _LVP_OFF_4L & _XINST_OFF_4L
ENDASM

'--------------[ Define Hardware / Set Registers ]------------------------    
    DEFINE OSC 16       ' CPU oscillator set at 16 MHz for compiler read
    DEFINE I2C_SLOW 1   ' Set i2c to the standard speed
    DEFINE I2C_HOLD 1   ' Enable recieving i2c device to pause communication

    Include "Modedefs.Bas" ' Mode definitions for Debug,Serin/out,
                           ' Shiftin/out, Xin/out. 
    INCLUDE "ALLDIGITAL.pbp"  ' Sets all registers for digital ops.
    'DEFINE SHOWDIGITAL 1 ' When uncommented will show analog settings
                              ' in Assembler Results window.                        
    INCLUDE "DT_INTS-18.bas"    ' Base Interrupt System
    INCLUDE "ReEnterPBP-18.bas" ' Include if using PBP high priority interrupts
    TRISA = 0           ' PortA output connections are used for LCD interface
    TRISB = %00001100   ' RB2 & RB3 set as RTC Alarm1 & Alarm2 inputs 
                        ' PORTB.2 is also an input from switch grounding 
                        ' PortB.5 is used for a mainloop Heartbeat LED output
    TRISC.2 = 0         ' PortC.2 is used for the LCD R/W connection

CLEAR

;--- Setup Interrupts ----------------------------------------------------

ASM
INT_LIST  macro      ; IntSource,        Label,  Type, ResetFlag?
        INT_Handler   USB_ACTV_INT, _ACTVIFhandler,   ASM,  no  ; first in list
        INT_Handler   USB_Handler 
        INT_Handler   INT2_INT,         _Range,   PBP,  yes
        INT_Handler   HLVD_INT,       _LowVolt,   PBP,  yes
    endm
    INT_CREATE               ; Creates the interrupt processor
endasm

' Per DT, DT_INTS already takes care of setting INTCON and RCON registers
' but this doesn't work unles INTCON2 set per below:
    INTCON2 = %10000000  ' Set INT2 for falling edge (Bit4-low)
                         ' on RTC's interrupt.
                         ' Disable all PortB pull-ups (Bit7-high)
    RTC_INT_FLG  VAR INTCON3.1 'INT2 interrupt flag from RTC..DT_INTS handles 

;--- Setup USB -----------------------------------------------------------
INCLUDE "DT_HID260.pbp"

DEFINE USB_VENDORID    6017
DEFINE USB_PRODUCTID   2000
DEFINE USB_VERSION     1
DEFINE USB_VENDORNAME  "LodeStar Assoc. Inc."
DEFINE USB_PRODUCTNAME "FillMonitor"
DEFINE USB_SERIAL      "002"
DEFINE USB_INSIZE      16   ; IN report is PIC to PC (8,16,32,64)
DEFINE USB_OUTSIZE     16   ; OUT report is PC to PIC
DEFINE USB_POLLIN      10   ; Polling times in mS, MIN=1 MAX=10
DEFINE USB_POLLOUT     10

; --- Each USB status LED is optional, comment them if not used ----------
; -- They can be assigned to any pin, and no further action is required -- 
DEFINE USB_LEDPOLARITY 1       ; LED ON State [0 or 1]  (default = 1)
DEFINE USB_PLUGGEDLED  PORTB,4 ; LED indicates if USB is connected
;DEFINE USB_TXLED       PORTB,6 ;  "      "    data being sent to PC
;DEFINE USB_RXLED       PORTB,5 ;  "      "    data being received from PC

'--- Variables & Aliases -------------------------------------------------
BATTLOW     VAR BIT       ' Flag that is set when battery is low
corHr       VAR BYTE      ' Corrected Hr from PC
corMINs     VAR BYTE      ' Corrected MINs from PC
corSecs     VAR BYTE      ' Corrected Secs from PC
corMon      VAR BYTE      ' Corrected month (Mon) from PC
corDate     VAR Byte      ' Corrected Date in Month from PC
corYr       VAR BYTe      ' Corrected Yr from PC
corA1hr     VAR Byte      ' Corrected Alarm1 hour from PC
corA1MINs   VAR byte      ' Corrected Alarm1 minutes from PC
corA1sec    VAR byte      ' Corrected Alarm1 seconds from PC
day_cnt     VAR BYTE      ' Counter for day number during monthly epoch
deviceID1   VAR BYTE      ' Serial # of MCU (MSB)
deviceID2   VAR BYTE      ' Serial # of MCU (LSB)
empty       VAR BYTE      ' Used as variable when empty buffer needed
stamp       VAR Byte      ' Stored Date stamp of measurment
ext_pwr     VAR PORTC.0   ' Alias to control power to Ultrasonic sensors
I           VAR Byte      ' Index for loop counters
ID          VAR BYTE(8)   ' DeviceID array
J           VAR BYTE      ' EEPROM address index for storing measurements
LED_RED     VAr PortC.1   ' Red LED used to indicate battery is low
LED_GRN     VAR PortB.4   ' Green LED used to indicate Routine entries
LCD_Flag    VAR Bit       ' Flag when set indicates LCD is installed/used
ReportID    VAR Byte      ' Report ID for USB message
ResetClk    VAR BIT       ' Reset flag if set resets microcontroller clock
rng0        VAR w0.Byte0  ' LSB of range measurement when right justified
rng1        VAR w0.byte1  ' MSB of range measurement when right justified 
SCL         VAR PORTB.1   ' I2C clock pin 
SDA         VAR PORTB.0   ' I2C data pin
Spare_1     VAR PORTB.7   ' PGD for ICSP & Spare I/O for normal ops
Spare_2     VAR PORTB.6   ' PGC for ICSP & Spare I/O for normal op
X           VAR WORD      ' Used as a loop index during Main for USB
w0          var word      ' W0 is the word value of the range measurement

' Constants
'==========
  RTCdevice CON $D0  ' Device write address = %11010000 for DS1337 RTC
  srfdevice CON $E0  ' Device address for SRF02 ultrasonic RangeFinder                    

;--- Initialize ----------------------------------------------------------
' Set FLAGS for current configuration
  BATTLOW = 1         ' Test Low Battery Flag = 0
  LCD_Flag = 1        ' Set for LCD installed/used; cleared otherwise                                       

PR2     =   249             ' 0-1000 duty range
T2CON   =   %00000101       ' TMR2 on, prescaler 1:4

TRISB = 0

' Read MCU Serial Number from device ID Locations
    TBLPTRU=$20        ' Address $200000
    TBLPTRH=$00
    TBLPTRL=$00
For i = 0 To 7
@  TBLRD*+             ; Get value and increment the address
    ID(i) = TABLAT     ; Store the byte as ID(i)
Next
deviceID1 = ID(0)      ' MSB of MCU Device Serial Number
deviceID2 = ID(1)      ' LSB of MCU Device Serial Number
deviceID1 = 0
deviceID2 = 2    
WRITE 240, ID(0)       ' Write fixed values to EEPROM
WRITE 241, ID(1)

'Initialize epoch indexes at time of powerup/reset
    day_cnt = 0
    WRITE 9, day_cnt   ' Store new epoch initialized day_count
    Pause 10
    J = 16             ' Initialize EEPROM logging index @ start address 
    WRITE 10,J         ' Store new epoch initialized J index
    Pause 10
    
'Initialize LEDs to off
    LOW LED_GRN
    LOW LED_RED

'*******************SETUP FOR USING DS1337 Real Time Clock**************
    ' Setup Hardware for uart
        DEFINE HSER_BAUD 115200
        DEFINE HSER_RCSTA 90h
        DEFINE HSER_TXSTA 24h
        DEFINE HSER_CLROERR 1
    
    ' Aliased Variables for CLock 
        Alarm1     VAR PORTB.2    ' Alarm1 input from DS1337 INTA (pin-3)
        'Alarm2     VAR PORTB.3   ' Alarm2 input from DS1337 INTB (pin-7)
        'SCL        VAR PORTB.1   ' I2C clock pin..previously set 
        'SDA        VAR PORTB.0   ' I2C data pin..previously sset 
        'RTCdevice  CON %11010000 ' RTC device write address..already set

    ' RTC Address definitions
        SecReg      CON $00   ' seconds address (00 - 59) 
                              ' Must set MSB of SecReg to a 0 to enable RTC 
        MinReg      CON $01   ' minutes address (00 - 59) 
        HrReg       CON $02   ' hours address (01 - 12) or (00 - 23) 
        DayReg      CON $03   ' day address (1 - 7) 
        DateReg     CON $04   ' date address (01 - 28/29, 30, 31) 
        MonReg      CON $05   ' month address (01 - 12) 
        YearReg     CON $06   ' year address (00 - 99) 
    
    ' Alarm 1 Address definitions 
        Alm1sec     CON $07  ' Alarm 1 seconds address (00 - 59) 
        Alm1min     CON $08  ' Alarm 1 minutes address (00 - 59)
        Alm1hr      CON $09  ' Alarm 1 hours address (01 - 12) or (00 - 23) 
        Alm1Day     CON $0A  ' Alarm 1 day address (1 - 7)
    
    ' Alarm 2 Address definitions..not used in this application
        'Alm2min     CON $0B  ' Alarm 2 minutes address (00 - 59)
        'Alm2hr      CON $0C  ' Alarm 2 hours address (01 - 12) or (00 - 23) 
        'Alm2Day     CON $0D  ' Alarm 2 day address (1 - 7)
    
    ' Alias of Clock register addresses
       ContReg     CON $0E    ' CONTROL register address 
       StatusReg   CON $0F    ' STATUS register address
     
    ' Clock Variables
        sec         VAR BYTE  ' seconds 
        MINs        VAR BYTE  ' minutes 
        hr          VAR BYTE  ' hours 
        day         VAR BYTE  ' day of week (Sunday = 7) 
        date        VAR BYTE  ' date in month 
        mon         VAR BYTE  ' month 
        yr          VAR BYTE  ' year 
    
    ' ALARM1 VARIABLES
        A1sec       VAR BYTE  ' seconds 
        A1MINs      VAR BYTE  ' minutes 
        A1hr        VAR BYTE  ' hours 
        A1day       VAR BYTE  ' day 
        
    ' ALARM2 VARIABLES..not used in this application
        'A2MINs      VAR BYTE  ' minutes
        'A2hr        VAR BYTE  ' hours
        'A2day       VAR BYTE  ' day
      
GOTO JumpPoint ' Jump over all subroutines so they don't execute on powerup

' ----------------------[ START SUBROUTINES ]--------------------------

InitializeDisplay:  ' Subroutine to initialize 2X16 LCD display      
'=================
     ' Blink LED_GRN 3X to indicate entered IntializeDisplay
       For i = 0 to 2
           HIGH LED_GRN
           Pause 500
           LOW LED_GRN
           PAUSE 500
       Next
  
'-----SETUP FOR USING 2x16 LCD THAT IS INSTALLED IN EASYPIC6--------  
     ' LCD DEFINES FOR USING 2x16 LCD with PortA in EASYPIC6
           DEFINE LCD_DREG PORTA    ' Use PORTA for LCD Data
           DEFINE LCD_DBIT 0        ' Use lower(4) 4 bits of PORTA
                                      ' PORTA.0 thru PORTA.3 connect to
                                      ' LCD DB4 thru LCD DB-7 respectively
           DEFINE LCD_RSREG PORTA   ' PORTA for RegisterSelect (RS) bit
           DEFINE LCD_RSBIT 4       ' PORTA.4 pin for LCD's RS line
           DEFINE LCD_RWREG PORTC   ' LCD read/write port
           DEFINE LCD_RWBIT 2       ' LCD read/write bit
           DEFINE LCD_EREG PORTA    ' PORTA for Enable (E) bit
           DEFINE LCD_EBIT 5        ' PORTA.5 pin for LCD's E line
           DEFINE LCD_BITS 4        ' Using 4-bit bus
           DEFINE LCD_LINES 2       ' Using 2 line Display
           DEFINE LCD_COMMANDUS 1500' Command Delay (uS)
           DEFINE LCD_DATAUS 44     ' Data Delay (uS)
       
    ' DEFINE LCD Control Constants  
           Line1   CON 128          ' Point to beginning of line 1 ($80) 
           Line2   CON 192          ' Point to beginning of line 2 ($C0)
    
    ' Test the LCD during initialization
           LCDOut $fe,1:FLAGS=0:Pause 250  ' Clear Display
           LCDOut $fe,Line1,"LCD TEST "    ' Display on 1st line
           LCDOut $fe,Line2,"Power On!!"   ' Display on 2nd line
           PAUSE 2000
Return

SetTimeAndDate:  ' Subroutine to set current time, date and alarms
'==============
    ' Blink LED_GRN 2X times to indicate entered SetTimeAndDate
           For i = 0 to 1
               HIGH LED_GRN
               Pause 500
               LOW LED_GRN
               PAUSE 500
           Next
           
    HIGH ext_pwr ' Temporarily turn on power to SRF02 for I2C bus use
    PAUSE 70     ' Delay to let I2C bus stabilize after SRF02 turn on              
    ' Initialize the display & clock
        ' Initialize clock variables to 0 
            yr=0:date =0:mon =0:day=0:hr=0:MINs=0:sec=0 
            A1sec=0:A1MINs=0:A1hr=0:A1Day=0   
            'A2MINs=0:A2hr=0:A2day=0 
        ' The BCD constants below set the RTC to: 08:15:00 on 06-23-2010 
            hr=$08
            MINs=$15
            sec=$00
            day=$03
            mon=$06
            date=$23
            yr=$10
        ' Per MAXIM TechSupport, proper sequencing requires setting  
        ' INTCN = 1, & A2IE=A1IE=0 before setting alarms.
            I2CWrite SDA, SCL, RTCdevice, ContReg,[%00000101]
            PAUSE 10  
        'Define ALARM1 FOR 08:16:00 & to alarm when secs match (1/min).
            ' This requires A1M1=0 and A1M2=A1M3=A1M4=1
            ' ($80+$A1xxx or 128d+A1xxx sets bit 7 as A1Mx = 1)
            A1hr   = %10001000  '$80+$08 = $88 = %10001000 = 136d, for A1M3 = 1
                                'Bit6 must be 0 for 24 hour clock
            A1MINs = %10010110  '$80+$16 = $96 = %10010110 = 150d, for A1M2 = 1
            A1sec  = $00        '$00 = %00000000, for A1M1 = 0
            A1day  = %10000011  '$80+$03 = $83 = %10000011 = 131d, for A1M4 = 1
                                'DY/_DT Bit6 = 0 for using Day of month alarm
        'Define ALARM2 FOR 14:01:00 & to alarm once per minute (00 secs)
        'Disabled in this application
            ' This requires A2M2 = A2M3 = A2M4 = 1
            ' (A2xxx + $80 or A2xxx + 128d sets bit 7 as A2Mx = 1)
            'A2hr   = $14 + $80  '$14  + $80 = %10010100, for A2M3 = 1
                                'Bit6 must be 0 for 24 hour clock
            'A2MINs = $01 + $80  '$01 + $80 = %10000001, for A2M2 = 1
            'A2day  = $07 + $80  '$07 + $80 = $10000111, for A2M4 = 1
                                'DY/_DT Bit6 = 0 for using Day of month alarm
                                
        ' Per MAXIM TechSupport, reset control register for desired Alarm
        ' after setting alarms.
            I2CWrite SDA, SCL, RTCdevice, ContReg,[%00000101]
            PAUSE 10 
        'Set the main Time
            I2CWrite SDA, SCL, RTCdevice, SecReg,[sec,MINs,hr,day,date,mon,yr]
            PAUSE 10
        ' Write date/time setting to EEPROM
            WRITE 242, Mon
            WRITE 243, Date   
            WRITE 244, Yr
            WRITE 245, hr                
            WRITE 246, MINs
            Write 247, sec     
        'Set the Alarm1 Time
            I2CWrite SDA, SCL, RTCdevice, Alm1sec,[A1sec,A1MINs,A1hr,A1day]
            PAUSE 10
        'Set the Alarm2 Time  ' Alarm2 disabled for this application
            'I2CWrite SDA, SCL, RTCdevice, Alm2min,[A2MINs,A2hr,A2day] 
            'PAUSE 10

        IF LCD_Flag = 1 Then ' This code block FOR TESTING ONLY
           'Test to see if Time set correctly by displaying on LCD
                I2CREAD SDA, SCL, RTCdevice, SecReg,[sec,MINs,hr,day,date,mon,yr]
                LCDOut $fe,1 ' Clear Display                                       
                LCDOUT $fe,Line1,"SetTime"
                LCDOUT $FE,LINE2,hex2 hr,":",hex2 MINs,":",hex2 sec
                Pause 2000    ' Delay so user can view display
            'Test if Alarm1 set correctly by displaying stored Alarm1 time
                I2CREAD SDA,SCL,RTCdevice,Alm1sec,[A1sec,A1MINs,A1hr,A1day]
                LCDOut $fe,1 ' Clear Display                                       
                LCDOUT $fe,Line1,"SetAlm1"
                LCDOut $FE,line2,hex2 A1hr,":",hex2 A1MINs,":",hex2 A1sec 
                PAUSE 2000    ' Delay so user can view display 
        ENDIF
        
        ' Clear STATUS and set CONTROL registers 
            I2CWrite SDA, SCL, RTCdevice, StatusReg,[$00]
            PAUSE 10
            I2CWrite SDA, SCL, RTCdevice, ContReg,[%00000101]
                          ' Starts oscillator, no interrupts enabled.
                          ' WORKS as intended!!
            Pause 10
     LOW ext_pwr  ' Turn off power to the SRF02 at end of I2C use.
     ' This statement will distort the I2C bus & ext_pwr must be set
     ' HIGH again before any attempts are made to use the I2C bus.
Return

DisplayDateTime  ' Subroutine to display date/time on LCD
'==============
    LCDOut $fe,1 ' Clear Display
    HIGH ext_pwr ' Temporarily turn on SRF02 power for I2C bus use
    PAUSE 70     ' Delay to let I2C bus stabilize after SRF02 turn on
    I2CREAD SDA, SCL, RTCdevice, SecReg,[sec,MINs,hr,day,date,mon,yr]
    LCDOUT $fe,Line1,Hex2 mon,"/",hex2 date,"/", hex2 yr
    LCDOUT $fe,Line2,hex2 hr,":",hex2 MINs,":",hex2 sec
    LOW ext_pwr  ' Turn off power to SRF02 until I2C bus is needed
    Pause 2000
Return
' ----------------------[ END OF SUBROUTINES ]-------------------------- 

JumpPoint:
    ' This block FOR TEST ONLY...comment out for ops.
        rng0 = 8                 ' Initializes for data set
        date = 0
        For X = 16 To 220 Step 3 ' Write 45 ea 3 byte data sets to EEPROM
                                 ' Max EEPROM index is $DC or dec 220
            date = date +1
            rng0 = rng0+1
            rng1 = 0 
            WRITE x, date        ' Log Day of month date-stamp
            WRITE x+1, rng0      ' Log LSB of range for day's measurement
            WRITE X+2, rng1      ' Log MSB of range for day's measurement  
        NEXT
    
    'Setup for starting Main Program 
        ' Initialize LCD if installed before starting main loop?       
          IF LCD_Flag = 1 Then GOSUB InitializeDisplay  
    
         GOSUB SetTimeAndDate    ' Set RTC time/date before starting mainloop
                      ' Also turns SRF02 power off to save battery
                      ' until I2C bus is needed again.         
        
        IF LCD_Flag = 1 Then ' This code block FOR TESTING ONLY
                             ' Comment out for ops.        
            LCDOut $fe,1' Clear Display                                       
            LCDOUT $fe,Line1,"Entered"
            LCDOUT $fe,Line2,"JumpPoint"
        ' Display Date/Time on LCD
            GOSUB DisplayDateTime
        ENDIF
    ' Enable the interrupts that are to be active during main loop.
@    INT_ENABLE   INT2_INT     ; enable external (INT) interrupts

'--------------------[ Begin Main Program Loop ]-------------------------
Main:
       GOSUB DisplayDateTime
     ' Store current date/time in EEPROM  
        WRITE 242, Mon
        WRITE 243, Date
        WRITE 244, Yr
        WRITE 245, hr                
        WRITE 246, MINs
        Write 247, sec            
     
    ' BufferOut (PIC to PC) Data Structure
        ' BufferOut(0) = 0, must always be zero as valid Report ID
        ' BufferOut(1) = DeviceID1 or MSB of Device Serial Number
        ' BufferOut(2) = DeviceID2 or LSB of Device Serial Number      
        ' BufferOut(3) = mon
        ' BufferOut(4) = date
        ' BufferOut(5) = yr
        ' BufferOut(6) = hr (Pic hours time)
        ' BufferOut(7) = MINs (Pic minutes time)
        ' BufferOut(8) = sec (Pic seconds time)
        ' BufferOut(9) = stamp
        ' BufferOut(10) = rng0
        ' BufferOut(11) = rng1  
        ' BufferOut(12) = BATTLOW (Low Battery Flag)
        ' BufferOut(13) = n/a ..0
        ' BufferOut(14) = n/a ..0
        ' BufferOut(15) = n/a ..0
        ' BufferOut(15) must be zero for sending data buffers (1) thru (14)
        '        ...else must send a text string with Buffer(15) = 1
        
@       ON_USBRX_GOSUB  _HandleRX
         
    IF J > 222 THEN     ' If reached maximum EEPROM usage location...
        J = 16            ' ..reset pointer to start of range data
    Endif
    READ j, stamp       ' Read date stamp of measurment
    READ J+1, rng0      ' Read range measurement from EEPROM
    READ J+2, rng1
    Pause 10
    J = J + 3
    
    ' Send Data to PC
        ' Send device ID to PC
        ' Send current Date/Time to PC
        ' Send each EEPROM stored range measurement to PC
        ' Send current BATTLOW indicator to PC                     
        ARRAYWRITE USBTXBuffer,[0,deviceID1,deviceID2,mon,date,yr, _
                           hr,MINs,sec,A1hr,A1mins,A1sec,BATTLOW,stamp,0,0]
    GOSUB SendIfReady
    
        ' Place code here to put MCU and Ultrasonic Ranger in SLEEP mode.
    ' while waiting for clock or USB interrupt to wakeup from SLEEP mode.    
        ' If USB is un-plugged, put MCU in deep sleep to save power.    
        ' If the USB is still Plugged, no sense putting PIC to sleep because it 
        ' will just wake up again in 1ms or less.
        ' The ACTVIE enable bit is already enabled by DT_HID.
        ' You don't need to do anything with it before going to sleep.
        IF !Plugged THEN   ' Go into deep sleep
            UCON.1 = 1     ' Set  the SUSPEND bit on the USB module
        ENDIF
' NOTE:  All of above code works fine and the USB_Handler and INT2_INT interrupts
'        work as intended.   However, as soon as the below @ SLEEP & @ NOP 
'        statements are un-commented, the unit does go into sleep mode, but 
'        then plugging in the USB will not wake it up.  
'        Nor does the INT2_INT interrupt continue to work....so MCU just stays
'        in SLEEP mode until powerup/reset.
;@ SLEEP
;@ NOP
     ' Microcontroller is in Sleep State awaiting next interrupt from RTC or USB
    
GOTO Main
;@ EndSize(MainLoop)    ; FOR TEST ONLY

;--- Send Data if Plugged and ready, otherwise discard -------------------
SendIfReady:                                    
    IF Plugged AND TX_READY THEN DoUSBOut
RETURN

;--- Wait till Ready to send or until unplugged --------------------------
WaitToSend:
    WHILE Plugged and !TX_READY : WEND
    IF TX_READY THEN GOSUB DoUSBOut
RETURN

;---- Receive incoming data...PORTB LEDS & corrected time/date -----------
HandleRX:
;@    INT_DISABLE   INT2_INT     ; disable external (INT) interrupts
     IF LCD_Flag = 1 Then ' This code block for testing only 
        LCDOut $fe,1' Clear Display                                       
        LCDOUT $fe,Line1,"Entered"
        LCDOUT $fe,Line2,"HandleRX"  
        Pause 1000      ' Delay for user to view LCD
     ENDIF
 ' BufferIn (PC to PIC) Structure
       'BufferIn(0) = ReportID => always 0
       'BufferIn(1) is sent by PC as PORTB settings but used as a Flag
       'ResetClk = BufferIn(1) ' PORTB is Reset flag..if set restarts MCU clock
       'corHr = BufferIn(2)    ' Corrected Hr setting from PC
       'corMINs = BufferIn(3)  ' Corrected MINs setting from PC
       'corSecs = BufferIn(4)  ' Corrected Secs setting from PC
       'corMon = BufferIn(5)   ' Corrected Mon setting from PC
       'corDate = BufferIn(6)  ' Corrected Date from PC
       'corYr = BufferIn(7)    ' Corrected Yr from PC
       'corA1hr = BufferIn(8)  ' Corrected Alarm1 hour from PC
       'corA1MINs = BufferIn(9)' Corrected Alarm1 minutes from PC
       'corA1sec = BufferIn(10)' Corrected Alarm1 seconds from PC
 ' Receive ResetClk and corrected FMReset flag/time/date from PC 
       ARRAYREAD  USBRXBuffer,[ReportID,ResetClk,corHr,corMINs,corSecs,corMon, _
         corDate,corYr,corA1hr,corA1MINs,corA1sec,empty,empty,empty,empty,empty]
        IF ReportID = 0 Then   ' Check for valid RX report
          IF ResetClk = 1 Then ' Check if time correction sent
             ' Convert Decimal -> Hex coded time data
              mon = (corMon DIG 1) * $10 + (corMon DIG 0)
              date = (corDate DIG 1) * $10 + (corDate DIG 0)
              yr = (corYr DIG 1) * $10 + (corYr DIG 0) 
              hr = (corHR DIG 1) * $10 + (corHR DIG 0)
              MINs = (corMINs DIG 1) * $10 + (corMINs DIG 0)
              sec = (corSecs DIG 1) * $10 + (corSecs DIG 0)
              A1hr = A1hr +  $80  ' Set Alarm1 to interrupt every 24 hours
              A1hr = (corA1hr DIG 1) * $10 + (corA1hr DIG 0)
              A1MINs = (corA1MINs DIG 1) * $10 + (corA1MINs DIG 0)
              A1sec = (corA1sec DIG 1) * $10 + (corA1sec DIG 0)                                                               
              Write 224,ResetClk ' Record Reset flag state in EEPROM 
              WRITE 225,mon      ' Update PIC date/time from PC corrections
              WRITE 226,date
              WRITE 227,yr  
              WRITE 228,hr        
              Write 229,MINs
              Write 230,sec
              WRITE 231,empty
              'Set the corrected time/date
                   I2CWrite SDA, SCL, RTCdevice, SecReg,[sec,MINs,hr,day, _
                                                         date,mon,yr]
                   PAUSE 10
              'Set the Alarm1 Time (1 x every 24 hours)
                   I2CWrite SDA, SCL, RTCdevice, Alm1sec,[A1sec,A1MINs,A1hr]
                   PAUSE 10
                   LCDOut $fe,1' Clear Display                                       
                   LCDOUT $fe,Line1,"SetAlm1"
                   LCDOut $FE,line2,hex2 A1hr,":",hex2 A1MINs,":",hex2 A1sec 
                   PAUSE 2000    ' Delay so user can view display 
           ENDIF
       Endif
    
     ' Read back time setting for verification
        I2CREAD SDA, SCL, RTCdevice, SecReg,[sec,MINs,hr,day,date,mon,yr]
        LOW ext_pwr  ' Turn off power to the SRF02 at end of display.
            ' This statement will distort the I2C bus and ext_pwr
            ' must be set HIGH again before any attempts are made to
            ' use the I2C bus.
     ' Send RTC corrected time to PC as verification of corrections
        ARRAYWRITE USBTXBuffer,[0,deviceID1,deviceID2,mon,date,yr, _
                           hr,MINs,sec,A1hr,A1Mins,A1sec,BATTLOW,stamp,0,0]
                           'hr,MINs,sec,A1hr,A1MIns,A1sec,BATTLOW,stamp,rng0,0]
    GOSUB SendIfReady

    ' If ResetClk = 1, put code here to reset EEPROM memory index to J=16 
    ' and POR of MCU for new logging epoch .

;@    INT_ENABLE   INT2_INT     ;re-enable external (INT) interrupts                
return

'---------------------[ACTVIF - interrupt handler]------------------------
ACTVIFhandler:
    IF UCON.1 THEN UCON.1 = 0 ' Clear the SUSPEND bit to wakeup USB module
@ INT_RETURN

'--------------------[ Range - interrupt handler ]------------------------ 
Range:
Enable Debug
    IF LCD_Flag = 1 Then ' This code block FOR TESTING ONLY 
        LCDOut $fe,1' Clear Display                                       
        LCDOUT $fe,Line1,"Entered"
        LCDOUT $fe,Line2,"Range:"
    ENDIF
    
    ' Reset registers from SLEEP power save state to operational state
    TRISA = 0           ' PortA output connections are used for LCD interface
    TRISB = %00001100   ' RB2 & RB3 set as RTC Alarm1 (Alm1) & Alarm2 inputs 
                        ' PORTB.2 is an Alm1 interrupt or SW1 grounding input
                        ' PORTB.4 is used during test as a Green LED heartbeat
                        ' and as a USB connected indicator during ops 
    TRISC.1 = 0         ' PORTC.1 used during test as a RED LED output
    TRISC.2 = 0         ' PortC.2 is used for the LCD R/W connection
    ADCON1= %11111111 ' Set PortA to Digital I/O after SLEEP mode. 
     
    ' Blink LED_GRN 1X to indicate entered Range ISR
       HIGH LED_GRN
       Pause 500
       LOW LED_GRN
       PAUSE 500
       
    ' Test for low battery condition that causes Vdd to go below 3.3 vdc
      ' Setup registers for HLVD module to support low voltage interrupt
          ' Step 1-Disable the module by clearing HLVDCON.4
                  HLVDCON.4 = 0                 ' Implement Step 1           
          ' Step2 HLVD3:HLVDL0=1000   'Set the trip point at Vdd=3.39 vdc
          ' Step3 HLVDCON.7=0 'Set VDIRMAG=0 to detect low voltage transition
          ' Step4 HLVDCON.4=1         'Enable the HLVD module
                      HLVDCON = %00011000 'Implements Steps 2-4
          ' Clear the HLVDIF interrupt flag (PIR2<2>)
                  PIR2.2 = 0
          ' Setup the interrupt and an ISR in your code and enable the interrupt 
          ' where you want to test for low voltage
@  INT_ENABLE   HLVD_INT ; enable HLVD interrupt                               
    ' If low voltage exists a HLVD interrupt will take place here and
    ' the ISR will blink the low voltage warning LED 5x.
       
    HIGH ext_pwr ' Temporarily turn on power to SRF02 for I2C bus use
    PAUSE 70     ' Delay to let I2C bus stabilize after SRF02 turn on 
    'DEFINE WRITE_USED 1 'Required if only writing WORD variables in v2.6
    ' Update day counter and address offset for day's measurements
        READ 9,day_cnt     ' Test if EEPROM data has been captured
                           ' & cleared by PC & new monthly epoch
                           ' started.
        day_cnt = day_cnt + 1  ' Increment day counter
        Write 9,day_cnt 'Update contents of day_count memory address       
        Pause 10
        If J >= $DF Then  ' Max logging EEPROM memory address is 223
           J = 16      ' If allocated EEPROM already used, start over
        ENDIF
    ' Make SRF02 Range Measurement           
        I2CWRITE SDA,SCL,$E0,0,[80]' Request start of ranging in inches
        pause 100                  ' Wait for ranging to finish
        I2CREAD SDA,SCL,$E0,2,[rng1,rng0] ' Get ranging results                         
        WRITE 240,Word w0            ' Write range to EEPROM       
    ' Display time & range measurement on LCD display in inches
      IF LCD_Flag = 1 Then ' This code block for testing only   
        LCDOut $FE,1:FLAGS=0:Pause 250 ' Clear Display
        I2CREAD SDA, SCL, RTCdevice, SecReg,[sec,MINs,hr,day,date,mon,yr]       
        LCDOUT $fe,1
        LCDOUT $fe,Line1,Hex2 mon,"/",hex2 date,"/",hex2 yr
        LCDOUT $fe,Line2,hex2 hr,":",hex2 MINs,":",hex2 sec
        Pause 200                    ' Allow Time for user to view
        LCDOUT $FE,1
        LCDOut $FE,Line1,"Range:"    ' Display on 1st line
        LCDOut $FE,Line2,#w0," in."  ' Display on 2nd line
      ENDIF
      PAUSE 3000                     ' Allow Time for user to view
    ' Clear STATUS register & Alarm flags..ready for next interrupt             
        I2CWrite SDA, SCL, rtcdevice, StatusReg,[$00]           
    LOW ext_pwr  ' Turn off power to the SRF02 at end of display.
                 ' This statement will distort the I2C bus and ext_pwr
                 ' must be set HIGH again before any attempts are made to
                 ' use the I2C bus.
    ' Store range as date-stamped value in EEPROM
        WRITE J+1,WORD w0        'Store day's range in EEPROM
        PAUSE 10
        Write J,date             ' with day of month date-stamp
        PAUSE 10
    ' Step pointer to next logging address in EEPROM
        J = J + 3
        WRITE 10,J   'Update contents of J index EEPROM memory address
        Pause 10                             
    PAUSE 470        ' Delay to permit I2C bus to stabilize after SRF02 off
@ INT_DISABLE HLVD_INT 
    Disable debug   
    ' Resume Main Program 
@ INT_RETURN           

LowVolt:
        BATTLOW = 1     ' Set low battery warning flag       
        ' Blink LED_RED 5X to indicate Low Battery voltage detected
        For i = 0 to 4
           HIGH LED_RED
           Pause 500
           LOW LED_RED
           PAUSE 500
        Next

     ' Resume Main Program
@ INT_RETURN

End     ' Safety measure to insure program stops if reaches here