;******************************************************************************
;*                                                                            
;* TITLE: Rain Gauge
;*                                                                            
;* AUTHOR: Robert Farrer for PreMac/AgriGel         
;*
;* Ping:
;*    0x24 0x25 0xDB
;* Write external EEPROM:
;*    0x24 0x3F 0x04 0x00 0x00 0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0A 0x0B 0x0C 0x0D 0x0E 0x0F 0x45
;*    0x24 0x3F 0x04 0x00 0x60 0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0A 0x0B 0x0C 0x0D 0x0E 0x0F 0xE5
;* Read external EEPROM:
;*    0x24 0x7F 0x04 0x00 0x00 0x7D
;*    0x24 0x7F 0x04 0x00 0x10 0x6D
;*    0x24 0x7F 0x04 0x00 0x20 0x5D
;*    0x24 0x7F 0x04 0x00 0x30 0x4D
;*    0x24 0x7F 0x04 0x00 0x40 0x3D
;*    0x24 0x7F 0x04 0x00 0x50 0x2D
;*    0x24 0x7F 0x04 0x00 0x60 0x1D
;*    0x24 0x7F 0x04 0x00 0x70 0x0D
;*    0x24 0x7F 0x04 0x00 0x80 0xFD
;*    0x24 0x7F 0x04 0x00 0x90 0xED
;* Write internal EEPROM:
;*    0x24 0x1F 0x80 0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0A 0x0B 0x0C 0x0D 0x0E 0x0F 0xE9
;*    0x24 0x12 0x1A 0x00 0xFF 0xFF 0xD6 ;Reset Debug1, 2 & 3
;* Read internal EEPROM:
;*    0x24 0x5F 0x80 0x21
;*    0x24 0x5F 0x00 0xA1 ;Read first page of non-volatile variables
;*    0x24 0x5F 0x10 0x91 ;Read second page of non-volatile variables
;*    0x24 0x5F 0x1C 0x85 ;Read the 15 bytes of RAM following the last non-volatile variable, (currently Debug3_0 at 0x1C in EEPROM and 0x3C in RAM!!!)
;* Write DS1307:
;*    0x24 0x06 0x00 0x00 0x47 0x14 0x00 0x19 0x03 0x20 0x63 ;20/03/19 14H47
;* Read DS1307:
;*    0x24 0x47 0x00 0xB9
;*
;*
;*
;* Assumptions are based on:
;*
;* - 2mm bucket size
;* - Absolute insane rainfall rate of 800mm/hour then generates 1 pulse every 500msec
;* - To be safe, try keep states in the event state machine at around 250msec
;*   - In other words, try to pass through Forever_RainGauge every 250msec, in order to queue RainPulse and RTC events
;*
;* Resource allocation:
;*
;* INTF - RTC
;* IOCF - Rain pulse
;*
;* T1 - general purpose timer for us within events
;*      - Like waiting for the AHT10 to power up
;*      - Or an external EEPROM write to complete 
;*      - etc
;*
;* T2 - also used for waiting within events???
;*      - see why I can't use T1, unless they are running in parallel???
;*
;* T4 - RainPulse input lock out to filter debouncing
;*
;* I2C routines:
;*
;*    I2C_Delay:   7 @SlowSpeed =  0.896 msec
;*    I2C_Start:  45 @SlowSpeed =  5.760 msec 
;*    I2C_Stop.:  34 @SlowSpeed =  4.352 msec
;*    I2C_Rx...: 305 @SlowSpeed = 39.040 msec
;*    I2C_Tx...: 385 @SlowSpeed = 49.280 msec
;*
;* External EEPROM buffer routines:
;*
;*    EEPROM_WriteBuffer: 24 @SlowSpeed = 3.072 msec
;*
;* 
;*
;*
;* Event buffer routines:
;*
;*
;*
;*
;*
;*
;* Maths routines:
;*
;*    Mul40_2.......: 1623 @SlowSpeed = 207.744 msec
;*    BCD2BinaryTU_2:   82 @SlowSpeed =  10.496 msec 
;*
;*
;*
;*
;*
;* 20(20)/(07)/(08) - Jacques app seems to hang up the rain gauge
;*                    - He has subsequently confirmed that there is an extra byte in the clock set packet, which shouldn't be there!
;*                    - Use the app and the existing code and see how to make it more bullet proof
;*                      - Check address for critical bytes and mask accordingly
;*                        - Like address 0 bit 7 must be 0
;*                        - Like address 7 must be 0x10
;*                        - The rest need to be correct for it to work, but aren't critical
;*                    - Test with existing app 
;*                      - The rain gauge at least keeps running now, even if the date and time are being set incorrectly
;*
;*
;*
;*
;*
;*
;*
;*
;*
;*
;*
;*                  - Switch back to normal time
;*
;*
;*
;*
;*
;*
;*
;*                  - Add a guard timer to detect when the clock tick isn't being received
;*                    - Leave this one for some time in the future
;*
;*
;*
;*
;*     
;*     
;*     
;*     
;*     
;*     
;*     
;*     
;*     
;*     
;*     
;*     
;*     
;*     
;*     
;*     
;* 20(20)/(06)/(02) - I think there may be an anomaly in reading the non-volatile variables, which I can exploit
;*                    to read a portion of the RAM, so check if it actually exists?
;*                    - Yes it does, I can read 15 varaibles of RAM
;*                    - Put the current humidity and temperature into it and allocate some variables to watch over the USB port
;*                    - Test   
;*                  - Switch back to normal time
;*                  - Program the 2 test units
;*     
;* 20(20)/(05)/(27) - Resolve issues which have arisen from the back door test site
;*                    - The RainPulse input needs to be debounced
;*                      - So at the absoulutely crazy rate of 800mm/hour we receive a pulse once every 500msec
;*                        - So if I lock out the RainPulse input for 250msec we should prevent any false counts and also not lose any pulses
;*                        - Find a timer 
;*                          - T4 is good
;*                      - Still accumulates the rain pulses on the bench, but the debouncing will have to wait until it goes back into the test unit on the door
;*                    - Debug1 is not incrementing only once per failure
;*                      - Sorted
;*                    - Add Debug3 to track the power pin in each state
;*                      - Debug3 will initially be 0xFF and the bits will be cleared if the power pin is in the wrong state  
;*                        - Bit 0 = Event_X_DHL_PowerOn
;*                        - Bit 1 = Event_X_DHL_WaitPowerOn
;*                        - Bit 2 = Event_X_DHL_Initialise
;*                        - Bit 3 = Event_X_DHL_WaitInitialise
;*                        - Bit 4 = Event_X_DHL_StartConversion
;*                        - Bit 5 = Event_X_DHL_WaitConversion
;*                        - Bit 6 = Event_X_DHL_Read
;*                        - Bit 7 = Event_X_DHL_Temperature1
;*                  - Program the back door test unit and verify the rain pulse debouncing is working
;*                    - I am happy with it, let's see when we have plastic how it performs there
;*                  - Roll forward to K528 to carry on for the day
;*                  - Switch to accelerated time  
;*                    - x24, so the HiLo event gets run about every 10.6s to help trying to get it to fail
;*                      - It did fail a conversion time once and when I single stepped through it, it was correctly ignored and didn't corrupt anything  
;*                        - Yip, only once all afternoon
;*                    - Also set a breakpoint on when the HumidityLo_0 is cleared to 0
;*                      - Never, broke here all afternoon, but it does seem to be random, so I am not surprised!
;*                    - I leave partial calculations in the calculator between the HiLo event states and these states can be pre-empted, so if some
;*                      other event uses the calculator or even the variables that could be the cause of the corrupted HiLo readings
;*                      - I see the external EEPROM event uses the calculator variables, even though it doesn't use the calculator!!!
;*                      - And SampleBatteryVoltage and ...
;*                        - But in reality I only need one other routine to use these variables to cause a problem, so I don't have to find them all, I 
;*                          must rather just not leave the partial calculations in the calculator variables!!!
;*                    - It's too late to try reprogramming the back door test unit now, but leave the code in accelerated time and
;*                      program the unit on my desk and let's see what it looks like tomorrow
;*     
;* 20(20)/(05)/(20) - Resolve issues which have arisen from the back door test site
;*                    - The checksum for the DailyLog is computed incorrectly
;*                      - Remove the byte we skip from the calculation
;*                    - There is a problem with reading the AHT10 which results in the highs going to maximum
;*                      - I don't get it on the unit on my desk, so I think it is temperature related in the early hours of the morning
;*                        - Either the temperature is going negative and confusing the issue 
;*                          - Instead of doing the offset here, let the app do it, then I don't need to worry about
;*                            negative numbers when determining the Highs and Lows
;*                            - Update the spec accordingly
;*                        - Or, the conversion is taking longer than their vague 75msec in the datasheet
;*                          - Add EE_Debug1_0 and EE_Debug2_0 to the non-volatile variables to help with debugging in future
;*                            - Right now they will be used to verify if this conversion is taking longer than expected
;*                              - Debug1 counts how many times we need to extend the conversion time
;*                              - Debug2 tracks the longest extension we gave the conversion time
;*                              - Switch to accelerated time to debug this new code
;*                              - Sort out issues looping back to wait for the conversion to complete  
;*                  - Switch back to normal time
;*                  - Re-assemble the test site and see what tomorrow brings
;*                  - Update the workshop test unit
;*                  - Verify the DailyLog checksum is computed correctly
;*     
;* 20(20)/(05)/(15) - Make a real time version for the back door test site
;*                  - When the comms port is plugged in we don't process the rain pulses, as discussed
;*                    - So when I exit I need to clear the rain pulse interrupt flag, otherwise it gets recorded!
;*     
;* 20(20)/(05)/(13) - The battery life PCB we had running from K115 went from 3V11 to 2V92 to 2V88 to 2V83 to 2V77 to 2V72 to 2V68 to 2V65 to 2V63 to 2V58 to 2V52 to 2V42 to 2V32
;*                    to 2V269 to 2V178 to 2V042 
;*                    - The battery wire was broken off when I came to measure on Saturday 2 May
;*                    - Reconnected the battery this morning - K506- it has recovered a bit from being disconnected - 2V12 to 1V912
;*                    - It is still running
;*                  - Last time I worked out a battery voltage strategy, now implement it
;*                    - Once a day power up the USB chip to feed the battery voltage in on CheckUSBAlert
;*                      - Once I have a reading, divide it by 2, subtract 180 and initiate an event to store it in EEPROM for the app to read
;*                    - Verify operation
;*                    - Document
;*                  - Increment powerups counter
;*                    - Only for cold starts
;*                  - Increment device connect counter 
;*                    - Only when there is actual comms
;*                  - Add code to log a clock set event whenever we exit comms mode and the DS1307 has been written to  
;*                    - Also make sure the user left the DS1307 TICKing
;*                  - Test the last 3 additions
;*                  - Log all the garbage events to EEPROM            
;*                  - Log the number of lost RainPulse times to EEPROM
;*                  - Find and repair all ;??? 
;*                    - There are still 2
;*                      - I am happy with them but want to leave this markers in in case there are issues later on
;*                  - At 17H45 the batteries on the live test are 2V5
;*     
;* 20(20)/(05)/(06) - The battery life PCB we had running from K115 went from 3V11 to 2V92 to 2V88 to 2V83 to 2V77 to 2V72 to 2V68 to 2V65 to 2V63 to 2V58 to 2V52 to 2V42 to 2V32
;*                    to 2V269 to 2V178 to 2V042 
;*                    - The battery wire was broken off when I came to measure on Saturday 2 May
;*                    - Reconnected the battery this morning - K506- it has recovered a bit from being disconnected - 2V12
;*                    - It is still running
;*                  - Live test PCB went from 2V56 at 16H45 K429 to 2V47 
;*                  - Analyse the Hi/Lo data I downloaded on Saturday to make sure the humidity and temperature Hi/Lo readings are making sense  
;*                    - The lows are lower than the highs and they make a logical progression, so I am happy with this    
;*                  - Work through the notes I have been making at the top of the code and resolve these outstanding issues:
;*                    - Remember we may need to "eject" the memory before changing batteries
;*                      - The most reliable "battery change" alert I can think of is simply plugging in a device!
;*                      - Already taken care of - when a device is plugged in the external EEPROM buffer is flushed and the non-volatile variables are written to internal EEPROM 
;*                    - Backup and restore the logging pointer using internal EEPROM
;*                      - Already taken care of periodically and also when plugging in a device
;*                    - Manage the read and write pointers for external EEPROM log memory
;*                      - The write pointer does increment, but there is no wrap around code yet
;*                    - Use CheckUSBAlert to check for a device periodically instead of continually, to save power by not powering up the ADC continually
;*                    - Sample the battery periodically
;*                      - If I enable USB_Tx without a device connected I inadvertently power up the CH340G through the protection diode and then I get the battery
;*                        voltage appearing on USB_E through a 4K7/2K4 voltage divider
;*                        - New batteries are  3V2 * 2.4 / 7.1 = 1V081
;*                        - Flat batteries are 2V0 * 2.4 / 7.1 = 0V676
;*                        - With FVR set to 2V048 we get 539 and 337 respectively
;*                          - Converting to 8-bits we get 134 and 84 thats 50 steps over 1V2 = 24mV not bad
;*                          - OR if I subtract 300 as an offset I get 202 steps over 1V2 = 59mV which is much better
;*                          - See if I run into issues when the battery voltage is heading below 2V048 
;*                      - Don't do this very often, otherwise we use too much battery power - maybe once a day is good?
;*                  - Jacques reported an internal EEPROM write bug 
;*                    - As he suspected I was not incrementing the internal EEPROM address when writing
;*                    - Let's build and verify this fix
;*                    - Send to Jacques 
;*                  - Roll the version forward to K507
;*                    - Carry on with the battery voltage
;*                      - If I enable USB_Tx without a device connected I inadvertently power up the CH340G through the protection diode and then I get the battery
;*                        voltage appearing on USB_E through a 4K7/2K4 voltage divider
;*                        - New batteries are  3V2 * 2.4 / 7.1 = 1V081
;*                        - Flat batteries are 2V0 * 2.4 / 7.1 = 0V676
;*                        - With FVR set to 2V048 we get 539 and 337 respectively
;*                          - Converting to 8-bits we get 134 and 84 thats 50 steps over 1V2 = 24mV not bad
;*                          - OR if I subtract 300 as an offset I get 202 steps over 1V2 = 59mV which is much better
;*                          - See if I run into issues when the battery voltage is heading below 2V048 
;*                      - Don't do this very often, otherwise we use too much battery power - maybe once a day is good?
;*                        - But for now do it very second    
;*                        - Set up some code and use the PSU to change the voltage and see what we get in practice
;*     
;* 20(20)/(04)/(29) - The battery life PCB we had running from K115 went from 3V11 to 2V92 to 2V88 to 2V83 to 2V77 to 2V72 to 2V68 to 2V65 to 2V63 to 2V58 to 2V52 to 2V42 to 2V32
;*                    to 2V269 to 2V178 to 2V042
;*                    - It is still running
;*                  - Last time I put the QueueDailyLog event state machine structure in place and created a list of what needs to be done
;*                    - Create the code
;*                    - Get it running
;*                    - Debug the code
;*                  - Switch off the LiveDebug, so that I can try logging some real data and read it through the comms port
;*                  - Let's leave it to log some data tomorrow, while I do some other work  
;*                    - Batteries are 2V56 at 16H45
;*     
;* 20(20)/(04)/(28) - I need a mechanism for verifying the integrity of the EVENTs once the program is running
;*                    - I had the idea the other night that maybe the hardware UART can be used in the background, I know we won't be able to 
;*                      switch to comms mode then, but I can live with that for testing purposes
;*                      - See if I can achieve any meaningful standard baud rates from the 31.25KHz clock
;*                        - First accurate one is 600bps, but RealTerm doesn't seem to support that
;*                          - Let's see if there is a later version
;*                          - Also, let's see if there is a TERMINAL program that support non-standard baud rates
;*                            - Seems like RealTerm ill try to pass any baud setting you request to the PC, whether it works depends on many things!
;*                              - Let's try 3906bps
;*                                - It works, so do the donkey work to implement this LiveDebug
;*                  - See how to check for the daily log time and log a hi lo event to the external EEPROM
;*                    - Add a debug switch AcceleratedTime
;*                      - Use this switch to make everything happen faster, in oder to accumulate data quicker for debugging and verification
;*
;* 20(20)/(04)/(24) - Add code to increment the non-volatile sequence number and implement the actual ActiveBank switch
;*                    - But first I need to implement a proper program memory page switching strategy otherwise this issue is going to keep cropping up!
;*                      - Implemented a PagedCall macro which can be used to call subroutines in other program memory pages and it takes care of the
;*                        paging issues automatically
;*                        - It does increase the code size a bit and it cant' be used directly after a btfsc or btfss
;*                    - There we go, non-volatile variables are automatically, safely, saved away to EEPROM when various parts of the program update them 
;*
;* 20(20)/(04)/(22) - The battery life PCB we had running from K115 went from 3V11 to 2V92 to 2V88 to 2V83 to 2V77 to 2V72 to 2V68 to 2V65 to 2V63 to 2V58 to 2V52 to 2V42 to 2V32
;*                    to 2V269 to 2V178
;*                    - It is still running
;*                  - Figure out why I only seem to be able to read the AHT10 correctly the first time after power up
;*                    - It isn't just after power up, but if I reset the processor then I can read it again, but also only once  
;*                      - If I sit in a loop without going through the event state machine I can read it repeatedly! 
;*                        - Even if I cycle the power on the AHT10
;*                    - I was clearing TMR1IF instead of TMR2IF in the conversion delay routine
;*                    - The highs and lows for the humidity and temperature are making sense
;*                  - Add code to save the non-volatile variables to EEPROM whenever we switch in and out of comms mode
;*                    - Let's do this while we are running at high speed :-)
;*                  - Add code to check the EEPROM variables to see if they have changed and if so back them to memory
;*     
;* 20(20)/(04)/(15) - The battery life PCB we had running from K115 went from 3V11 to 2V92 to 2V88 to 2V83 to 2V77 to 2V72 to 2V68 to 2V65 to 2V63 to 2V58 to 2V52 to 2V42 to 2V32
;*                    to 2V269
;*                    - It is still running
;*                  - Add an LED to the power line of the peripherals and use it to debug the rain pulse code from last week, which wasn't working
;*                    - Copy the reed switch to the power line
;*                      - Works
;*                    - Use the comparator interrupt to toggle the power line
;*                      - Nothing!
;*                      - Ah, the reed switch is not one of the comparator inputs, so that strategy must be for something else and not the reed switch
;*                      - It is an IOC pin and that is all it really is, so let's set that up and test it
;*                        - Who new there was an INLNLA register - it allows you to set ST or TTL inputs! 
;*                        - Also not working 
;*                          - Check the voltage levels
;*                            - Looks good
;*                          - Add an LED to the reed switch, so I know the magnet is actually activating the reed switch
;*                            - When the LED on the reed switch activates, it works
;*                    - Put the rain pulse code back now
;*                      - By looking at the power LED I would say it is working
;*                      - Can I read the rain pulse data from the external EEPROM?
;*                        - Yes, but they aren't incrementing!
;*                        - It isn't the rain pulses we are reading, but the seconds between pulses
;*                          - Make the Seconds_Offset tick
;*                          - Yes it is working
;*                  - Start bringing up the temperature and humidity hi/lo code again 
;*                    - Fix up maths routine paging issues 
;*                    - It only seems to run once
;*                      - Sub-state not cleared on exit
;*                    - Do the Highs and Lows make sense?
;*                      - No 
;*                        - Try to determine whether this chip has ever been read or not!
;*                          - No, looks like the chip I was successfully reading was on the other PCB  
;*                            - Verify we are happy with the way the chip is mounted, connected, etc
;*                        - The other new PCB I have behaves the same, but I did notice that I do read it correctly the first time after power up  
;*     
;* 20(20)/(04)/(08) - The battery life PCB we had running from K115 went from 3V11 to 2V92 to 2V88 to 2V83 to 2V77 to 2V72 to 2V68 to 2V65 to 2V63 to 2V58 to 2V52 to 2V42 to 2V32
;*                    - It is still running
;*                  - Carry on with logging the power up event
;*                  - Now debug it, because it was quite a big change and now the rain gauge doesn't see the device being plugged in
;*                    - It looks like something keeps queuing events, so remove all the event triggers and see
;*                  - Program memory paging issues
;*                  - Pointer issues in LogHiLoEvent subroutine
;*                    - I can use the comms port and see that the event entry, event detail and date are correct 
;*                      - See what is wrong with the time!
;*                        - Nothing, hot start time is supposed to advance
;*                      - See what is wrong with the highs and lows on a hot start
;*                        - The initialisation values for programming needed to brought in line with the specs 
;*                  - Add code to FLUSHHH the external EEPROM buffer to the external EEPROM whenever a device is connected
;*                    - I will sequentially write the letters FLUSHHH to the buffer until I have a full page and then trigger an EEPROM event 
;*                      - Debug the FLUSHHH code
;*                        - I think it is sorted and I have another error elsewhere
;*                          - Yes, in the comm port code to read the external EEPROM
;*                  - Test the rain pulse code I have 
;*                    - Not working, will debug it next time 
;*     
;* 20(20)/(04)/(07) - Log a power up event
;*                    - Sort out what that event must look like
;*                    - The longest event is now much longer, so adjust the EEPROM buffer size and write page size accordingly  
;*                    - Log it to memory
;*     
;* 20(20)/(04)/(06) - Get the clock tick sorted out
;*                    - The alarm pin from the DS1307 is on A2 which is the external interrupt pin, so set it up and poll for it  
;*                      - Most of this is done, but the tick rate I was accumulating was wrong  
;*                    - See if I can distinguish between a cold start where the clock is not setup and a warm start where the clock is potentially correct
;*                      - It looks like when the DS1307 powers up the CH bit in the seconds register is set, inhibiting the oscillator
;*                        - So let's assume if it is clear we are good to go and if it is set we are not
;*                          - CH = 1 = setup DS1307
;*                            - Initialise the clock with a fake, but known time   
;*                          - CH = 0 = potentially we have good time here
;*                            - Verify that the control register is setup correctly
;*                            - Calculate how make seconds have elapsed from 07H00M00S in order for everything else to work properly
;*                        - Figure out why the code only wants to go to ColdStart
;*                          - Pointer and calculation issues
;*                    - Calculate the SecondsOffset from the log time of 07H00
;*     
;* 20(20)/(04)/(03) - Get the program to transition from rain gauge mode at 31.25KHz to comms mode at 11.0592MHz
;*                  - Power up at high speed, to get the initialisation done and then switch to low speed and go into the rain gauge code, which can look
;*                    for the device and then switch to comms mode when the event queue is empty
;*                    - The device is on RC2, refresh myself on what the detection strategy is for this pin
;*                      - This is an analogue pin and it is only polled when the event queue is empty, so there is no urgency here, so reserve the specialised hardware
;*                        for other inputs and just do an analogue conversion
;*                        - I expected to be reading close to 0 with the device unplugged, but I am reading 422
;*                          - See what voltage is on the actual pin 2V48
;*                            - It is the Tx from the PIC going through the diode on the Rx on the USB chip
;*                              - Made Tx low, now I read what I expected
;*                        - PC gives 738, my phone gives 718 and when I disconnect I get 1         
;*                          - I can work with these numbers
;*                      - I can detect the device and switch to comms mode and the device can talk to the PCB
;*                      - See if I can see the device being unplugged and go back to the rain gauge code
;*                        - Yes
;*     
;* 20(20)/(04)/(02) - Resolve paging issues, now that the program is bigger than 2K
;*                  - Finalise restoring non-volatile variables from internal EEPROM
;*                  - Finalise writing and reading non-volatile variables over the comms port
;*     
;* 20(20)/(04)/(01) - The battery life PCB we had running from K115 went from 3V11 to 2V92 to 2V88 to 2V83 to 2V77 to 2V72 to 2V68 to 2V65 to 2V63 to 2V58 to 2.52 to 2.42
;*                    - It is still running
;*                  - The internal EEPROM read command is already written, but it needs to be completed in respsct of the scratchpad we added
;*                    for Jacques to store info, which does not concern me
;*                    - 0x24 0x5F 0x80 0x21
;*                    - 0x24 0x5F 0xC0 0xE1
;*                  - Figure out what the internal EEPROM write command looks like
;*                    - Let's do the ScratchPad for the app first
;*                    - 0x24 0x10 0xC0 0xA5 0x8B
;*                    - Scratchpad is working
;*                    - Decide on non-volatile variables and how to manage them both here in the comms routines and in the rain gauge state machine
;*                      - Copy, paste and edit in the save routine
;*
;* 20(20)/(03)/(25) - The battery life PCB we had running from K115 went from 3V11 to 2V92 to 2V88 to 2V83 to 2V77 to 2V72 to 2V68 to 2V65 to 2V63 to 2V58 to 2.52
;*                    - It is still running
;*                  - Started 2 units 2020/01/22 16:45:00 OK, so the second one started 15s later   
;*                    - DailyPower 00s -------------------------- 3V24
;*                      - Reports 029 14:52:00 and it is 14:10:27 2V99
;*                      - Ignore the time, but the voltage is now 2V94
;*                      - Ignore the time, but the voltage is now 2V89
;*                      - Ignore the time, but the voltage is now 2V84
;*                      - Ignore the time, but the voltage is now 2V79
;*                      - Ignore the time, but the voltage is now 2V74
;*                      - Ignore the time, but the voltage is now 2V72
;*                      - This test is no longer running - Jacques is using the batteries for his board
;*                    - Duracell   15s -------------------------- 3V20
;*                      - Reports 029 14:46:00 and it is 14:14:12 3V08
;*                      - Ignore the time, but the voltage is now 3V03 
;*                      - Ignore the time, but the voltage is now 3V00
;*                      - Ignore the time, but the voltage is now 2V98
;*                      - Ignore the time, but the voltage is now 2V96
;*                      - Ignore the time, but the voltage is now 2V94
;*                      - Ignore the time, but the voltage is now 2V93
;*                      - Ignore the time, but the voltage is now 2V92
;*                      - Ignore the time, but the voltage is now 2V90
;*                  - What does an external EEPROM read command look like:
;*                    - 0x24 0x7F 0x00 0x00 0x00 0x81
;*                    - 0x24 0x7F 0x00 0x00 0x01 0x80
;*                    - 0x24 0x7F 0x04 0x00 0x07 0x76
;*                    - I would expect the data to move along, but it is always the same, so I am not actually reading the EEPROM!  
;*                      - Resolved quite a few issues and now I think it is reading 0xFFs which makes sense
;*                        - Put some data in the EEPROM first when I get there and then read it back
;*                          - Figure out why this isn't working
;*                            - The code is essentially correct, but I am addressing the EEPROMs in correctly, because they are 512s and not 1024s
;*                              - So they start at:
;*                                - 0x40000
;*                                - 0x50000 
;*                    - Instead of hard coding the chip selection bits derive them from the high byte of the address in the protocol
;*                  - What does an external EEPROM write command look like:
;*                    - 0x24 0x33 0x04 0x00 0x07 0x11 0x22 0x33 0x44 0x18 
;*                    - There we go, I can now write data to the EEPROM and read it back from the comms interface 
;*                  - Check if I can ESCape the start characters:
;*                    - If the line buffer contains 0x24 0x33 0x04 0x00 0x07 0x11 0x22 0x33 0x24 0x38 it must ESCape to
;*                                                  0x24 0x33 0x04 0x00 0x07 0x11 0x22 0x33 0x2F 0x53 0x38
;*                    - The receive ESCape mechanism is working  
;*                    - Add code to add ESCape sequences when transmitting
;*                      - A response of #23  9F  11 "22 333 $24  11  12  13  14  15  16  17  18  19  20 !21  FF  DA must ESCape to
;*                                      #23  9F  11 "22 333 /2F S53  11  12  13  14  15  16  17  18  19  20 !21  FF  DA
;*                  - What does a clock read command look like
;*                    - 0x24 0x47 0x00 0xB9
;*                      - After resolving a few issues with the write as well as the read the clock can now be written and read back
;*     
;* 20(20)/(03)/(19) - Add ESCaping to the receive routines 
;*                  - Test with details command
;*                    - 0x24 0x25 0xDB
;*                  - What does a DS1307 write command look like:
;*                    - 0x24 0x06 0x00 0x00 0x47 0x14 0x00 0x19 0x03 0x20 0x63
;*                    - I can see the data in the PIC and it is writing to the clock, but I can't verify that right now
;*                  - What does an internal EEPROM read command look like:
;*                    - 0x24 0x57 0x00 0xA9
;*                    - Just read RAM from address 0, until I sort out the EEPROM double buffering 
;*     
;* 20(20)/(03)/(18) - The battery life PCB we had running from K115 went from 3V11 to 2V92 to 2V88 to 2V83 to 2V77 to 2V72 to 2V68 to 2V65 to 2V63 to 2V58
;*                    - It is still running
;*                  - Started 2 units 2020/01/22 16:45:00 OK, so the second one started 15s later   
;*                    - DailyPower 00s -------------------------- 3V24
;*                      - Reports 029 14:52:00 and it is 14:10:27 2V99
;*                      - Ignore the time, but the voltage is now 2V94
;*                      - Ignore the time, but the voltage is now 2V89
;*                      - Ignore the time, but the voltage is now 2V84
;*                      - Ignore the time, but the voltage is now 2V79
;*                      - Ignore the time, but the voltage is now 2V74
;*                      - Ignore the time, but the voltage is now 2V72
;*                      - This test is no longer running - Jacques is using the batteries for his board
;*                    - Duracell   15s -------------------------- 3V20
;*                      - Reports 029 14:46:00 and it is 14:14:12 3V08
;*                      - Ignore the time, but the voltage is now 3V03 
;*                      - Ignore the time, but the voltage is now 3V00
;*                      - Ignore the time, but the voltage is now 2V98
;*                      - Ignore the time, but the voltage is now 2V96
;*                      - Ignore the time, but the voltage is now 2V94
;*                      - Ignore the time, but the voltage is now 2V93
;*                      - Ignore the time, but the voltage is now 2V92
;*                  - Carry on with sorting out the comms using RealTerm as the host for now
;*                    - Sort out some issues with the interpreter not flushing the queue properly  
;*     
;* 20(20)/(03)/(11) - The battery life PCB we had running from K115 went from 3V11 to 2V92 to 2V88 to 2V83 to 2V77 to 2V72 to 2V68 to 2V65 to 2V63
;*                    - It is still running
;*                  - Started 2 units 2020/01/22 16:45:00 OK, so the second one started 15s later   
;*                    - DailyPower 00s -------------------------- 3V24
;*                      - Reports 029 14:52:00 and it is 14:10:27 2V99
;*                      - Ignore the time, but the voltage is now 2V94
;*                      - Ignore the time, but the voltage is now 2V89
;*                      - Ignore the time, but the voltage is now 2V84
;*                      - Ignore the time, but the voltage is now 2V79
;*                      - Ignore the time, but the voltage is now 2V74
;*                      - Ignore the time, but the voltage is now 2V72
;*                    - Duracell   15s -------------------------- 3V20
;*                      - Reports 029 14:46:00 and it is 14:14:12 3V08
;*                      - Ignore the time, but the voltage is now 3V03 
;*                      - Ignore the time, but the voltage is now 3V00
;*                      - Ignore the time, but the voltage is now 2V98
;*                      - Ignore the time, but the voltage is now 2V96
;*                      - Ignore the time, but the voltage is now 2V94
;*                      - Ignore the time, but the voltage is now 2V93
;*                  - Bring in the communication protocol I have for the PIC18 devices
;*                    - Port it over to work on the PIC16F1825
;*                    - I can receive the connect packet from the app
;*                    - I can see my reponse going out on the scope, but the app isn't displaying it
;*                      - While Jacques looks at that, flesh out the comms routines
;*                        - Sorted, so in principle the comms works
;*                        - I will use RealTerm to debug my comms and finalise the specifications
;*                  - Make the I2C routines aware of the processor speed in order to time correctly
;*                  - Flesh out the documents a bit, to cover some of the things Jacques covered while chatting
;*     
;* 20(20)/(03)/(04) - The battery life PCB we had running from K115 went from 3V11 to 2V92 to 2V88 to 2V83 to 2V77 to 2V72 to 2V68 to 2V65
;*                    - It is still running
;*                  - Started 2 units 2020/01/22 16:45:00 OK, so the second one started 15s later   
;*                    - DailyPower 00s -------------------------- 3V24
;*                      - Reports 029 14:52:00 and it is 14:10:27 2V99
;*                      - Ignore the time, but the voltage is now 2V94
;*                      - Ignore the time, but the voltage is now 2V89
;*                      - Ignore the time, but the voltage is now 2V84
;*                      - Ignore the time, but the voltage is now 2V79
;*                      - Ignore the time, but the voltage is now 2V74
;*                    - Duracell   15s -------------------------- 3V20
;*                      - Reports 029 14:46:00 and it is 14:14:12 3V08
;*                      - Ignore the time, but the voltage is now 3V03 
;*                      - Ignore the time, but the voltage is now 3V00
;*                      - Ignore the time, but the voltage is now 2V98
;*                      - Ignore the time, but the voltage is now 2V96
;*                      - Ignore the time, but the voltage is now 2V94
;*                  - We have the new PCB, so let's bring it up and test it 
;*                    - I can see the PIC with the PICKit3
;*                    - Change the config, to use the alternative pins for the Rx and Tx
;*                      - They aren't config bits they are in SFR
;*                        - The way the hardware is now, the default values work
;*                    - Remap the ports and see if what we have is still working
;*                      - Because of the pin assignments the rain pulse cannot be debugged, which isn't an issue, but seen as currently
;*                        I use that as a trigger instead of the RTC, it means I can't really see anything right now
;*                    - Program the RTC to give me a 1 second tick
;*                      - Set up the external interrupt to flag the alarm to me for now, later I will use the interrupt to wake the PIC up        
;*                    - Plug the USB into my phone               
;*                      - The phone sees the CH340 IC
;*                    - Bring in the serial port routines
;*                      - Install CH340 driver on PC and try to type to the PIC to see what is workig and what isn't
;*                        - I can type characters in RealTerm and see them being received by the PIC
;*                      - When I connect with the APP I don't receive any characters
;*                        - I don't see any with the scope either
;*                          - I will have to debug this with Jacques next time.
;*     
;* 20(20)/(02)/(26) - The battery life PCB we had running from K115 went from 3V11 to 2V92 to 2V88 to 2V83 to 2V77 to 2V72 to 2V68
;*                    - It is still running
;*                  - Started 2 units 2020/01/22 16:45:00 OK, so the second one started 15s later   
;*                    - DailyPower 00s -------------------------- 3V24
;*                      - Reports 029 14:52:00 and it is 14:10:27 2V99
;*                      - Ignore the time, but the voltage is now 2V94
;*                      - Ignore the time, but the voltage is now 2V89
;*                      - Ignore the time, but the voltage is now 2V84
;*                      - Ignore the time, but the voltage is now 2V79
;*                    - Duracell   15s -------------------------- 3V20
;*                      - Reports 029 14:46:00 and it is 14:14:12 3V08
;*                      - Ignore the time, but the voltage is now 3V03 
;*                      - Ignore the time, but the voltage is now 3V00
;*                      - Ignore the time, but the voltage is now 2V98
;*                      - Ignore the time, but the voltage is now 2V96
;*                  - Debug the code to unqueue and requeue the same event to allow the HiLo event to be split to allow other events a chance
;*                  - Do the 1s event to update the seconds since midnight and queue events to check the time for the Daily Log
;*     
;* 20(20)/(02)/(19) - The battery life PCB we had running from K115 went from 3V11 to 2V92 to 2V88 to 2V83 to 2V77 to 2V72
;*                    - It is still running
;*                  - Started 2 units 2020/01/22 16:45:00 OK, so the second one started 15s later   
;*                    - DailyPower 00s -------------------------- 3V24
;*                      - Reports 029 14:52:00 and it is 14:10:27 2V99
;*                      - Ignore the time, but the voltage is now 2V94
;*                      - Ignore the time, but the voltage is now 2V89
;*                      - Ignore the time, but the voltage is now 2V84
;*                    - Duracell   15s -------------------------- 3V20
;*                      - Reports 029 14:46:00 and it is 14:14:12 3V08
;*                      - Ignore the time, but the voltage is now 3V03 
;*                      - Ignore the time, but the voltage is now 3V00
;*                      - Ignore the time, but the voltage is now 2V98
;*                  - Danny sorted out a reed switch on a bucket, so use it test whether the signal needs debouncing or not  
;*                    - It reliably reads 88 pulses in 30s = about 30msec per pulse = 586mm/hour which is huge
;*                  - See how the bucket tips under a stream of water and a drip of water
;*                    - Very cleanly
;*                  - Build the code for the rain event
;*                    - Instead of having seperate event queue and a rain buffer for rain events, allow events to be queued with data
;*                      - Use the high nibble to identify the event and the low nibble can then be used as part of the data if necessary  
;*                    - Because the data being written to the EEPROM is variable length, I cannot gaurantee that it won't cross an EEPROM page boundary
;*                      - I don't want to write 1 byte at a time, the 5msec write time takes too long
;*                      - I don't necessarily want to buffer a whole EEPROM page either, because of space 
;*                      - Let's meet half way and buffer a binary fraction
;*                    - See what chip Danny wants to use at the end of the day and replace the 24LC02 on the prototype with it  
;*                      - We are going with the 24LC512 - the addressing will be different at the end of the day, but that is a minor change
;*                      - The chips page size is 128 bytes and the page write time is 5msec
;*                        - That's almost all my memory! - let's settle on a buffer size of 20 bytes and we write to EEPROM as soon as we have 8 bytes  
;*                          - My logic is the longest event is 12 bytes and if we already have 7 buffered then we still need to be able to buffer these 12 
;*                          - Also allow the EEPROM to pre-empt any events in the queue by replacing the current event in the queue if there is a mini page
;*                            waiting to be written to the EEPROM
;*                  - We don't have a RTC chip, but it would be nice to queue RTC events, so implement a software RTC with a timer 
;*                    - Or to throw in HiLo events periodically just use a counter
;*                      - In reality we may only run a HiLo event once every 4 minutes, but if we go Danny's way it will only be once every hour!
;*                        - But even just running it once in heavy rain seems to cause rain pulse times to be lost  
;*                          - 2 times get lost
;*                      - Split the HiLo event over multiple events to allow other events to be processed in between                  
;*                        - This means I will have to take note of the Power line to the peripherals in other events and leave it in the correct state when I exit 
;*                          - Right now this only happens in the EEPROM event
;*
;* 20(20)/(02)/(12) - The battery life PCB we had running from K115 went from 3V11 to 2V92 to 2V88 to 2V83 to 2V77
;*                    - It is still running
;*                  - Started 2 units 2020/01/22 16:45:00 OK, so the second one started 15s later   
;*                    - DailyPower 00s -------------------------- 3V24
;*                      - Reports 029 14:52:00 and it is 14:10:27 2V99
;*                      - Ignore the time, but the voltage is now 2V94
;*                      - Ignore the time, but the voltage is now 2V89
;*                    - Duracell   15s -------------------------- 3V20
;*                      - Reports 029 14:46:00 and it is 14:14:12 3V08
;*                      - Ignore the time, but the voltage is now 3V03 
;*                      - Ignore the time, but the voltage is now 3V00
;*                  - See how to reliably do everything that needs doing at only 31.25KHz
;*                    - Right now I am thinking of an event queue and events which take long can segment themselves and add events to carry on to the queue
;*                      - Keep the event queue, but long events can segment themselves using a state machine
;*                    - Built the event queue and dispatcher 
;*                      - Debug it
;*                    - Use the rain input to trigger the HiLo event
;*                      - Build the code for the HiLo event
;*                        - Debug it
;*
;* 20(20)/(02)/(05) - The battery life PCB we had running from K115 went from 3V11 to 2V92 to 2V88 to 2V83
;*                    - It is still running
;*                  - Started 2 units 2020/01/22 16:45:00 OK, so the second one started 15s later   
;*                    - DailyPower 00s 3V24
;*                      - Reports 029 14:52:00 and it is 14:10:27 2V99
;*                      - Ignore the time, but the voltage is now 2V94
;*                    - Duracell   15s 3V20
;*                      - Reports 029 14:46:00 and it is 14:14:12 3V08
;*                      - Ignore the time, but the voltage is now 3V03 
;*                  - Verify the logging protocol to make sure I can re-synchronise in the event that the buffer wraps around and the pointers get corrupted
;*                    - The biggest issue is that the rain event is recorded as an offset from the last HiLo event
;*                      - Therefore, at power up we must log a HiLo event to give us a base to re-construct the time from, as there is no real HiLo data
;*                        we will simply record the current humidity and teperature as both the Hi and the Lo
;*                  - Bring in a maths package, so that we can process the 20-bit data from the AHT10
;*                    - See if I already ported one over when we worked on the active end of line check valve
;*                      - No, that wasn't so complicated, so port it over now
;*                  - Read the AHT10 and use the maths package to calculate the temperature and humidity   
;*                    - The readings seem to be correct
;*                  - Report the temperature and humidity over the scope pin at 1200bps 
;*                  - Run some tests, by holding it and breathing on it to see that the readings change
;*                    - Yes, they do
;*                  - Do the high/low code for the temperature and the humidity     
;*                  - Also report the rain pulses
;*                  - The temperature reading is interefering with the accumulation of the rain pulses
;*                  - Build a state machine to run the whole process, so that slow events like reading the AHT10 don't block other events from happening
;*     
;* 20(20)/(01)/(29) - The battery life PCB we had running from K115 went from 3V11 to 2V92 to 2V88
;*                    - It is still running
;*                  - Started 2 units 2020/01/22 16:45:00 OK, so the second one started 15s later   
;*                    - DailyPower 00s 3V24
;*                      - Reports 029 14:52:00 and it is 14:10:27 2V99
;*                    - Duracell   15s 3V20
;*                      - Reports 029 14:46:00 and it is 14:14:12 3V08
;*     
;* 20(20)/(01)/(22) - The battery life PCB we had running from last week went from 3V11 to 2V92 in 1 week
;*                  - Sort out 2 more PCBs  
;*                  - Start working on the real time clock, so that we can start determining the accuracy of the internal 31.25KHz oscillator
;*                    - Use last weeks code to make sure the board is running
;*                    - The time base we created last week wasn't running as expected, so see if I can figure out why
;*                      - I calculate it to be 33,4s, but it is only about 11,2s that is only a third!
;*                      - Use debugger to check registers
;*                        - Ah, the default radix is HEX instead of decimal
;*                      - There we go 10 ticks with a stop watch gives 33,4s average     
;*                    - Use this to implement the RTC now  
;*                      - Only go as far as the days for now, we just want to see if works, if it does we can do the months and years
;*                  - Stop switching the peripherals on and off every tick
;*                  - Set the clock and let it run over lunch
;*                    - 12:23:40 to 12:53:40 read as 12:54:35 which is 55s to much over 30 minutes - which means it is gaining 1.83s every minute
;*                      - I can trim it, but are all the micros going to run the same?                      
;*                  - Try the HF 31.25KHz clock and see if it is more accurate than the MF one
;*                    - 13:04:50 to 13:19:50 read as 13:19:52 which is 2s to much over 15 minutes - which means it is gaining 0.13s every minute
;*                      - 3 minutes a day isn't great, but it is workable compared to the MF oscillator!
;*                  - Decide which pin to use as the transmit pin
;*                    - Let's use the SCOPE pin for now and see
;*                  - Write the code to transmit the time at 110bps, so that we can see what the accuracy of the clock looks like 
;*                    - FTDI only works down to 300bps
;*                      - I am sending *, (2A), but receiving T,(54)
;*                        - 00101010
;*                        - 01010100
;*                      - I am transmitting the wrong bit first
;*                  - How long is a usec tick and how long does it take to transmit a byte?
;*                    - usec tick is 32,64msec
;*                    - 1 byte at 300bps is 33,3msec
;*                    - So I am going to mess with the timing!!! 
;*                  - Can I get this up to 1200bps reliably? 
;*                    - Looks like it with some inline code and some juggling to average out the half an instruction delay I can't execute!
;*                  - Now I can do the code to report the time once every minute
;*                  - Started 2 units 2020/01/22 16:45:00 OK, so the second one started 15s later   
;*                    - DailyPower 00s 3V24
;*                    - Duracell   15s 3V20
;*     
;* 20(20)/(01)/(15) - I can't see the PIC with the PICKit3
;*                    - There is a conflict with the MCP220
;*                      - Cut the lines for now
;*                        - We also need to swap them around
;*                  - Get the PIC running and see what the current looks like 
;*                    - About 200uA at 31.25KHz     
;*                    - About 1.1mA at 12MHz
;*                  - Test the comparator to see if we see the rain pulse
;*                    - No, so check my setup  
;*                      - Yes, so capture the pulse  
;*                  - Bring up the I2C routines and talk to the EEPROM
;*                    - I can write to and read back from the EEPROM      
;*                  - Now try talking to the AHT10
;*                    - I can read the data  
;*                      - The temperature looks good
;*                      - The humidity increases if I breathe on the sensor, so I assume it is good
;*                  - Figure out how to store the humidity and temperature
;*                    - Humidity 0 - 100% with 1% resolution needs 7 bits 
;*                    - Temperature needs at least 10 bits to record -50 to +50
;*                    - Which means we need 3 bytes
;*                  - Sort out a test to run on the batteries to see how they last 
;*     
;* 20(20)/(01)/(08) - Start from here                
;*                  - Strip out all the unwanted ActiveEndOfLineCheckValve code
;*                  - Start building the code we need 
;*                    - Try to figure out how the AHT10 works
;*     
;******************************************************************************
;
              INCLUDE   "P16F1825.INC"
;
; FOSC_INTOSC or FOSC_HS
;
 __CONFIG _CONFIG1,_FOSC_HS & _WDTE_OFF & _PWRTE_ON & _MCLRE_OFF & _CP_ON & _CPD_OFF & _BOREN_ON & _CLKOUTEN_OFF & _IESO_OFF & _FCMEN_OFF
 __CONFIG _CONFIG2,_WRT_ALL & _PLLEN_OFF & _STVREN_OFF & _BORV_LO & _LVP_OFF
;
;***************************************
;
; Customisation constants
;
;***************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
;#define LiveDebugEnable
;#define AcceleratedTime
#define AcceleratedTime_Adjustment 24 ;Increment 24s every real second, so 1 day will take 1 hour
;
#define VersionYear     'K'
#define VersionMonth    '7'
#define VersionDayTens  '0'
#define VersionDayUnits '8'
;
#define LogEvent_HiLo              b'10100110' ;A6
#define LogEvent_RainPulse         b'11000110' ;C6 & C7
#define LogEvent_RainPulseTimeLost b'11010100' ;D4
#define LogEvent_GarbageFlags      b'11100100' ;E4
;
;***************************************
;
; MACRO: LiveDebug
;
;***************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;                1         2         3
;       12345678901234567890123456789012
#define LiveDebug_Forever_RainGauge      '\n'
#define LiveDebug_VerifySettings_Start   'V'
#define LiveDebug_VerifySettings_End     'v'
#define LiveDebug_RefreshNV_Start        'N'
#define LiveDebug_RefreshNV_End          'n'
#define LiveDebug_DetermineHiLo_Start    'D'
#define LiveDebug_DetermineHiLo_End      'd'
#define LiveDebug_WriteExtEEPROM_Start   'X'
#define LiveDebug_WriteExtEEPROM_End     'x'
#define LiveDebug_QueueDailyLog_Start    'Q'
#define LiveDebug_QueueDailyLog_End      'q' 
#define LiveDebug_RTC                    'T'
#define LiveDebug_CaptureRainPulse       'R'
#define LiveDebug_LogHiLoEvent_Start     'H'
#define LiveDebug_LogHiLoEvent_End       'h'
#define LiveDebug_SampleBattery_Start    'B'
#define LiveDebug_SampleBattery_End      'b'
#define LiveDebug_UnknownState           '?'
;
LiveDebug:    macro     Trace
;
              local     LiveDebug1,LiveDebugSkip
;
           IFDEF LiveDebugEnable
;
              btfss     LiveDebugInitialised
              goto      LiveDebugSkip
;
              movlb     PIR1>>7
;
LiveDebug1:
;
              btfss     _TXIF
              goto      LiveDebug1
;
              movlb     TXREG>>7
              movlw     Trace
              movwf     TXREG
;
LiveDebugSkip:
;
              movlb     0
;         
           ENDIF
;
              endm
;
;***************************************
;
; MACRO: PagedCall
;
;***************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
PagedCall:    macro     Subroutine
;
              movlp     HIGH(Subroutine)
              call      Subroutine
              movlp     HIGH($)               
;
              endm
;
;***************************************
;
; MACRO: SaveGIE
;
;***************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
SaveGIE:      macro     
;
              bcf       _SaveGIE
              btfsc     _GIE
              bsf       _SaveGIE
;
              bcf       _GIE
;
              endm
;
;***************************************
;
; MACRO: RestoreGIE
;
;***************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
RestoreGIE:   macro     
;
              btfss     _SaveGIE
              bcf       _GIE
              btfsc     _SaveGIE
              bsf       _GIE
;
              endm
;
;***************************************
;
; MACRO: CopyBit
;
;***************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
CopyBit:      macro     InFile,InBit,OutFile,OutBit
;
              btfss     InFile,InBit
              bcf       OutFile,OutBit
              btfsc     InFile,InBit
              bsf       OutFile,OutBit
;
              endm
;
;***************************************
;
; MACRO: InvertBit
;
;***************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
InvertBit:    macro     InFile,InBit,OutFile,OutBit
;
              btfss     InFile,InBit
              bsf       OutFile,OutBit
              btfsc     InFile,InBit
              bcf       OutFile,OutBit
;
              endm
;
;***************************************
;
; MACRO: Debounce
;
; This macro debounces the INPUT in the background and requires a maximum
; of 19 instruction cycles to operate
;
; The FLAG always uses POSITIVE LOGIC to make reading, understanding and
; maintaining the software simpler
;
;***************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
Debounce:     macro     PinLogic,PinFile,PinBit,FlagFile,FlagBit,HistoryFile,HistoryBit,TimerFile,TC
;
              LOCAL     WasLo,WasHi,Stable,Differs,ToggleHi,ToggleLo,Toggle,DebounceEnd
;
              btfss     HistoryFile,HistoryBit   ;IF !HISTORY
              goto      WasLo                    ;THEN check if still LO
              goto      WasHi                    ;ELSE check if still HI
;
WasLo         btfss     PinFile,PinBit           ;IF !PIN
              goto      Stable                   ;THEN STABLE
              goto      Differs                  ;ELSE DIFFERS
;
WasHi         btfsc     PinFile,PinBit           ;IF PIN
              goto      Stable                   ;THEN STABLE
              goto      Differs                  ;ELSE DIFFERS
;       
Stable        movf      TimerFile,W              ;IF TIMER=0
              btfsc     ZeroFlag
              goto      DebounceEnd              ;THEN go
;
              decfsz    TimerFile,Same           ;IF TIMER-1!=0
              goto      DebounceEnd              ;THEN go
;
              btfss     HistoryFile,HistoryBit   ;FLAG=HISTORY
           IF PinLogic==PositiveLogic
              bcf       FlagFile,FlagBit
           ELSE
              bsf       FlagFile,FlagBit 
           ENDIF
              btfsc     HistoryFile,HistoryBit
           IF PinLogic==PositiveLogic
              bsf       FlagFile,FlagBit
           ELSE
              bcf       FlagFile,FlagBit
           ENDIF
;
              goto      DebounceEnd
;
Differs       movlw     TC                       ;Reload debounce timer
              movwf     TimerFile
;                                                 _______
              btfss     HistoryFile,HistoryBit   ;HISTORY=HISTORY 
              goto      Toggle
;
              bcf       HistoryFile,HistoryBit
;
              goto      DebounceEnd
;
Toggle:
;
              bsf       HistoryFile,HistoryBit
;
              goto      DebounceEnd
;
DebounceEnd
;
              endm
;
;***************************************
;
; MACRO: DebounceAutoRepeat
;
; This macro debounces the INPUT in the background and requires a maximum
; of 19 instruction cycles to operate
;
; The FLAG always uses POSITIVE LOGIC to make reading, understanding and
; maintaining the software simpler
;
;***************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
DebounceAutoRepeat:     macro     PinLogic,PinFile,PinBit,FlagFile,FlagBit,HistoryFile,HistoryBit,TimerFile,TC,RepeatTC,RepeatDelayTC,RepeatRateTC
;
              LOCAL     WasLo,WasHi,Stable,Differs,ToggleHi,ToggleLo,Toggle,DebounceEnd
;
              btfss     HistoryFile,HistoryBit   ;IF !HISTORY
              goto      WasLo                    ;THEN check if still LO
              goto      WasHi                    ;ELSE check if still HI
;
WasLo         btfss     PinFile,PinBit           ;IF !PIN
              goto      Stable                   ;THEN STABLE
              goto      Differs                  ;ELSE DIFFERS
;
WasHi         btfsc     PinFile,PinBit           ;IF PIN
              goto      Stable                   ;THEN STABLE
              goto      Differs                  ;ELSE DIFFERS
;       
Stable        movf      TimerFile,W              ;IF TIMER=0
              btfsc     ZeroFlag
              goto      DebounceEnd              ;THEN go
;
              decfsz    TimerFile,Same           ;IF TIMER-1!=0
              goto      DebounceEnd              ;THEN go
;
              movf      RepeatTC,W               ;Reload for auto-repeat
              movwf     TimerFile
;
              movlw     RepeatRateTC
              movwf     RepeatTC
;
              btfss     HistoryFile,HistoryBit   ;FLAG=HISTORY
           IF PinLogic==PositiveLogic
              bcf       FlagFile,FlagBit
           ELSE
              bsf       FlagFile,FlagBit 
           ENDIF
              btfsc     HistoryFile,HistoryBit
           IF PinLogic==PositiveLogic
              bsf       FlagFile,FlagBit
           ELSE
              bcf       FlagFile,FlagBit
           ENDIF
;
              goto      DebounceEnd
;
Differs       movlw     TC                       ;Reload debounce timer
              movwf     TimerFile
;
              movlw     RepeatDelayTC            ;Reload auto-repeat timer
              movwf     RepeatTC
;                                                 _______
              btfss     HistoryFile,HistoryBit   ;HISTORY=HISTORY 
              goto      Toggle
;
              bcf       HistoryFile,HistoryBit
;
              goto      DebounceEnd
;
Toggle:
;
              bsf       HistoryFile,HistoryBit
;
              goto      DebounceEnd
;
DebounceEnd
;
              endm
;
;***************************************
;
; Constants
;
;***************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
#define Same 1
;
#define FALSE 0
#define TRUE ~FALSE
;
#define NegativeLogic 0
#define PositiveLogic ~NegativeLogic
;
;***************************************
;
; Constants - Complete BIT locations
;
;***************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
#define _GIE INTCON,GIE
;
#define _TMR0IF INTCON,TMR0IF
;
#define _IOCIE INTCON,IOCIE
#define _IOCIF INTCON,IOCIF
#define _INTE INTCON,INTE
#define _INTF INTCON,INTF
;
#define _RCIE PIE1,RCIE
#define _RCIF PIR1,RCIF
#define _OERR RCSTA,OERR
#define _CREN RCSTA,CREN
#define _FERR RCSTA,FERR
#define _RX9D RCSTA,RX9D
#define _TX9D TXSTA,TX9D
#define _TRMT TXSTA,TRMT
;
#define _TXIE PIE1,TXIE
#define _TXIF PIR1,TXIF
;
#define _TMR1IF PIR1,TMR1IF
;
#define _TMR2IF PIR1,TMR2IF
;
#define _TMR4IF PIR3,TMR4IF
;
#define _EEPGD  EECON1,EEPGD
#define _EECFGS EECON1,CFGS
#define _EERD   EECON1,RD
#define _EEWREN EECON1,WREN
#define _EEWR   EECON1,WR
;
#define _C1IF   PIR2,C1IF
;
#define _Go ADCON0,GO
;
#define CarryFlag STATUS,C
#define ZeroFlag  STATUS,Z
;
;***************************************
;
; Constants - Timing related
;
;***************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
#define usecTC 32768 ;1000000usec*4*256/31250
#define SecondTC 1000000 ;1s=1000000usec
;
;***************************************
;
; Constants - Flags
;
;***************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
#define StorePower           Flags0_A,0
#define Boolean_Interrupt    Flags0_A,1
#define HighSpeed            Flags0_A,2
#define ESCape               Flags0_A,3
#define FirstPass            Flags0_A,4
#define _SaveGIE             Flags0_A,5
#define CheckUSBAlert        Flags0_A,6
#define BankSwitchRequired   Flags0_A,7
;
#define AckTx                Flags1_A,0
#define AckRx                Flags1_A,1
#define PowerDown            Flags1_A,2
#define LiveDebugInitialised Flags1_A,3
#define DeviceCommunicated   Flags1_A,4
#define DeviceSetClock       Flags1_A,5
;
; Garbage flags
; - Keep them all in one byte to make a bulk test easy
;
#define GarbageFlags_A Flags2_A
;
#define EventQueueUnderFlow           GarbageFlags_A,0
#define EventQueueOverFlow            GarbageFlags_A,1
#define EEPROM_UnderFlow              GarbageFlags_A,2
#define EEPROM_OverFlow               GarbageFlags_A,3
#define ExtEE_PageAligned             GarbageFlags_A,4
#define ExtEE_WritePointerOutOfBounds GarbageFlags_A,5
#define ExtEE_ReadPointerOutOfBounds  GarbageFlags_A,6
#define ExtEE_MadeLoggingSpace        GarbageFlags_A,7 
;
;***************************************
;
; Memory Usage
;
;***************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
#define Rx1BufferSize 39
#define Tx1BufferSize 39
;
           CBLOCK    0x70
;
              Flags0_A
              Flags1_A
              Flags2_A 
              BBTxData
              Delay100msA
              Delay100msB   
;
              I2C_DelayCounter_A
              I2C_Count_A
              I2C_Data_A
;
              Checksum_A
;
              ScratchPad0_A ;When using these ScratchPad variables and you call subroutines, make sure there is no conflict
;
              CheckCommonBankUsage
;
           endc
;
           IF CheckCommonBankUsage > h'80'
              ERROR "Too many file registers have been used in Common Bank"
           ENDIF
;
           CBLOCK    0x20
;
; START NON-VOLATILE variables
; - These variables must correspond with their order in the EEPROM memory map
;
              ActiveBank_0
              SequenceNumber_0
;
              FirmwareYear_0
              FirmwareMonth_0
              FirmwareDayTens_0
              FirmwareDayUnits_0
;
              PowerUps_0
              PowerUps_0H
              Connections_0
              Connections_0H
;
              BatteryVoltage_0
;
              LogReadPointer_0
              LogReadPointer_0H
              LogReadPointer_0HH
;
              LogWritePointer_0
              LogWritePointer_0H
              LogWritePointer_0HH 
;
              RainPulse_0
              RainPulse_0H
              RainPulse_0HH
;
              HumidityLo_0
              HumidityHi_0
;
              TemperatureLo_0
              TemperatureLo_0H 
              TemperatureHi_0
              TemperatureHi_0H 
;
              Debug1_0
              Debug2_0
              Debug3_0 ;Remember to update NV_BoundaryHi if this is no longer the last non-volatile variable
;
; END NON-VOLATILE variables
;
; The first 15 variables following the non-volatile variables can be read over the USB port - thanks to an anomaly in the code :-)
;
              Humidity_0                         ;1   
;
              Temperature_0                      ;2
              Temperature_0H                     ;3
;
              AHT10_S_0                          ;4
              AHT10_H1_0                         ;5
              AHT10_H2_0                         ;6
              AHT10_HT_0                         ;7
              AHT10_T1_0                         ;8
              AHT10_T2_0                         ;9
;
              EventQueueAvailable_0              ;10
              EEPROM_Buffered_0                  ;11
;
              Seconds_Offset_0                   ;12
              Seconds_Offset_0H                  ;13
              Seconds_Offset_0HH                 ;14 
;
              RainPulseTimeLost_0                ;15 
;
              Event_0
              EventQueueReadPointer_0
              EventQueueWritePointer_0
;
              EEPROM_0
              EEPROM_ReadPointer_0
              EEPROM_WritePointer_0
;
              CalculatorFlags
              CalculatorCount
              CalculatorX0
              CalculatorX1
              CalculatorX2
              CalculatorX3
              CalculatorX4
              CalculatorY0
              CalculatorY1
              CalculatorY2
              CalculatorY3
              CalculatorY4
              CalculatorTA0
              CalculatorTA1
              CalculatorTA2
              CalculatorTA3
              CalculatorTA4
;
              Binary
              BinaryH
;
              Thousands
              Hundreds
              Tens
              Units
;
              EEAdrs
              EEAdrsH
              EEAdrsHH
;
              EventState_0
;
              DetermineHiLo_State_0
              DetermineHiLo_Extend_0
;
              CheckBank0Usage
;
           endc
;
           IF CheckBank0Usage > h'70'
              ERROR "Too many file registers have been used in Bank 0"
           ENDIF
;
#define NV_BoundaryLo FirmwareYear_0
#define NV_BoundaryHi Debug3_0+1
;
#define EEPROM_BufferSize 60
#define EEPROM_WritePageSize 8 ;Don't be too tempted to make this bigger, (16, 32, 64 or 128), because it impacts the ability to service event triggers
;
           cblock 0xA0 ;This is data page 1 all variables have a suffix of _1
;
              EEPROM_Buffer_1:EEPROM_BufferSize
;
              CheckBank1Usage
;
           endc
;
           IF CheckBank1Usage > h'0F0'
              ERROR "Too many file registers have been used in Bank 1"
           ENDIF
;
#define EEPROM_FirstLocation EEPROM_Buffer_1
#define EEPROM_LastLocation  EEPROM_Buffer_1+EEPROM_BufferSize-1
;
           cblock 0x120   ;This is data page 2 all variables have a suffix of _2
;
              HiLoDetail1_2
              HiLoDetail2_2
;
              Seconds_2
              Minutes_2
              Hours_2
              DayOfWeek_2
              Date_2
              Month_2
              Year_2
              Control_2
;
              DetermineHiLo_Calculator0_2
              DetermineHiLo_Calculator1_2
              DetermineHiLo_Calculator2_2
              DetermineHiLo_Calculator3_2
              DetermineHiLo_Calculator4_2
;
              CheckBank2Usage
;
           endc
;
           IF CheckBank2Usage > h'170'
              ERROR "Too many file registers have been used in Bank 2"
           ENDIF
;
           cblock 0x1A0   ;This is data page 3 all variables have a suffix of _3
                          ;These file registers are in the same page as the UART special function regsiters, 
                          ;in order to minimise the amount of page switching we have to do - the actual buffers
                          ;can be in other pages, as they are accessed indirectly
                          ;The internal EEPROM variables are also here for the same reason
;
              Rx1BufferReadPointer_3        
              Rx1BufferWritePointer_3
              Tx1BufferReadPointer_3
              Tx1BufferWritePointer_3
              Tx1BufferWritePointerWork_3
;
              Rx1Character_3                     ;Character buffering in the receive routine
              Rx1BufferData_3                    ;Character buffering in the receive buffer routine
              Tx1BufferData_3
              RxByteSerialPort1_Work_3
;
              PacketCounter_3
              LineBufferPointer_3
              PacketCharacter_3
              PacketState_3
              PacketCommand_3
;
              LineBuffer_3:40
;
              EEPROMSaveBank_3
              EEPROMSequenceBank_3
              EEPROMSequence_3
              EEPROMNewBank_3
              EEPROMRestoreBank_3
              EEPROMBank0Sequence_3
              EEPROMBank1Sequence_3
;
              VerifySettings_State_3
;   
              DS1307_Address_3
              DS1307_Data_3 
;
              CheckBank3Usage
;
           endc
;
           IF CheckBank3Usage > h'1F0'
              ERROR "Too many file registers have been used in Bank 3"
           ENDIF
;
           cblock 0x220   ;This is data page 4 all variables have a suffix of _4
;
              Rx1Buffer_4:Rx1BufferSize
              Tx1Buffer_4:Tx1BufferSize
;
              CheckBank4Usage
;
           endc
;
           IF CheckBank4Usage > h'270'
              ERROR "Too many file registers have been used in Bank 4"
           ENDIF
;
#define EventQueueSize 60
;
           cblock 0x2A0   ;This is data page 5 all variables have a suffix of _5
;
              EventQueue_5:EventQueueSize
;
              CheckBank5Usage
;
           endc
;
           IF CheckBank5Usage > h'2F0'
              ERROR "Too many file registers have been used in Bank 5"
           ENDIF
;
#define EventQueueFirstLocation EventQueue_5
#define EventQueueLastLocation  EventQueue_5+EventQueueSize-1
;
           cblock 0x320   ;This is data page 6 all variables have a suffix of _6
;

;
              CheckBank6Usage
;
           endc
;
           IF CheckBank6Usage > h'370'
              ERROR "Too many file registers have been used in Bank 6"
           ENDIF
;
           cblock 0x3A0   ;This is data page 7 all variables have a suffix of _7
;

;
              CheckBank7Usage
;
           endc
;
           IF CheckBank7Usage > h'3F0'
              ERROR "Too many file registers have been used in Bank 7"
           ENDIF
;
           cblock 0x420   ;This is data page 8 all variables have a suffix of _8
;

;
              CheckBank8Usage
;
           endc
;
           IF CheckBank8Usage > h'470'
              ERROR "Too many file registers have been used in Bank 8"
           ENDIF
;
           cblock 0x4A0   ;This is data page 9 all variables have a suffix of _9
;

;
              CheckBank9Usage
;
           endc
;
           IF CheckBank9Usage > h'4F0'
              ERROR "Too many file registers have been used in Bank 9"
           ENDIF
;
           cblock 0x520   ;This is data page 10 all variables have a suffix of _10
;

;
              CheckBank10Usage
;
           endc
;
           IF CheckBank10Usage > h'570'
              ERROR "Too many file registers have been used in Bank 10"
           ENDIF
;
           cblock 0x5A0   ;This is data page 11 all variables have a suffix of _11
;

;
              CheckBank11Usage
;
           endc
;
           IF CheckBank11Usage > h'5F0'
              ERROR "Too many file registers have been used in Bank 11"
           ENDIF
;
           cblock 0x620   ;This is data page 12 all variables have a suffix of _12
;

;
              CheckBank12Usage
;
           endc
;
           IF CheckBank4Usage > h'650'
              ERROR "Too many file registers have been used in Bank 12"
           ENDIF
;
#define Rx1BufferFirstLocation (Rx1Buffer_4&b'11111111')
#define Rx1BufferLastLocation ((Rx1Buffer_4+Rx1BufferSize-1)&b'11111111')
;
#define Tx1BufferFirstLocation (Tx1Buffer_4&b'11111111')
#define Tx1BufferLastLocation ((Tx1Buffer_4+Tx1BufferSize-1)&b'11111111')



;
;***************************************
;
; Calculator flags
;
#define CalculatorOverflow CalculatorFlags,0       
#define CalculatorError    CalculatorFlags,1       
#define CalculatorBoolean  CalculatorFlags,2       
#define CalculatorMulOver  CalculatorFlags,3        
#define CalculatorDivStore CalculatorFlags,4         
;
;***************************************
;
; Internal EEPROM memory map
;
;***************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
           CBLOCK 0
;
; These are the non-volatile variables used in the system.
; The order of the variables in EEPROM and RAM must correspond with each other.
; When the app reads/writes to these variables, it is actually writing to the RAM and then the program will manage the write to the correct page
; The app is blocked from writing to the ActiveBank variable to maintain integerity of the non-volatile variables.
;
              EE_ActiveBank                      ;0x5A=0x00 / 0xA5=0x40
              EE_SequenceNumber
;
              EE_FirmwareYear
              EE_FirmwareMonth
              EE_FirmwareDayTens
              EE_FirmwareDayUnits
;
              EE_PowerUps
              EE_PowerUpsH
              EE_Connections
              EE_ConnectionsH
;
              EE_BatteryVoltage
;
              EE_LogReadPointer
              EE_LogReadPointerH
              EE_LogReadPointerHH
;
              EE_LogWritePointer
              EE_LogWritePointerH
              EE_LogWritePointerHH  
;
              EE_RainPulse
              EE_RainPulseH
              EE_RainPulseHH
;
              EE_HumidityLo
              EE_HumidityHi
;
              EE_TemperatureLo
              EE_TemperatureLoH 
              EE_TemperatureHi
              EE_TemperatureHiH 
;
              EE_Debug1
              EE_Debug2
              EE_Debug3
;
           ENDC
;
           CBLOCK 0x40                           ;0xA5
           ENDC
;
           CBLOCK 0x80
              EE_ScratchPad:128                  ;This is the scratchpad the app can use for storing "cookies"
           ENDC
;
;***************************************
;
; Internal EEPROM default data
;
;***************************************
; 
              org       0xF000
;                       Bank0,Sequence,
              de        0x5A ,0x63
              de        VersionYear,VersionMonth,VersionDayTens,VersionDayUnits
;                       PowerUps,PowerUpsH,Connections,ConnectionsH
              de        0       ,0        ,0          ,0
;                       BatteryVoltage
              de        0xAA                     ;We don't know, so let's just put the size of the battery here
;                       LogReadPointer,LogReadPointerH,LogReadPointerHH,LogWritePointer,LogWritePointerH,LogWritePointerHH  
              de        0             ,0              ,4               ,0              ,0               ,4
;                       Rain,RainH,RainHH
              de        0   ,0    ,0
;                       HumidityLo,HumidityHi
              de        0xFF      ,0
;                       TemperatureLo,TemperatureLoH,TemperatureHi,TemperatureHiH 
              de        0xFF         ,0xFF          ,0            ,0 
;                       Debug1,Debug2,Debug3
              de        0     ,0xFF  ,0xFF
; 
              org       0xF040
;                       Bank0,Sequence ... the rest is don't care because bank 0 is active
              de        0x5A ,0x62
; 
              org       0xF080
;                       128 bytes 
              de        'A','P','P',' ','S','C','R','A','T','C','H','P','A','D'
;
;***************************************
;
; Reset comes to here
;
;***************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
              org       0x0000
;
ResetComesToHere:
;
              nop
              clrf      INTCON
              goto      Begin
;
;***************************************
;
; Interrupts come to here
;
;***************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
              org       0x0004
;
; For now I am going to simply stick with the automatic context saving, but will add additional registers if they are needed
;
              movlp     HIGH($)                  ;Not sure where we came from, so select this program page now
;
              movlb     0                        ;Not sure where we came from, so select this data page now
;
ProcessInt_RC1:
;
              movlb     PIR1>>7
              btfss     _RCIF                   ;IF Rx
              goto      ProcessInt_RC1End
;
              movlb     0 
              PagedCall RxByteSerialPort1_2
;
ProcessInt_RC1End:
;
ProcessInt_TX1:
;
              movlb     PIE1>>7
              btfss     _TXIE
              goto      ProcessInt_TX1B
;
              movlb     Tx1BufferReadPointer_3>>7
              movf      Tx1BufferReadPointer_3,W
              xorwf     Tx1BufferWritePointer_3,W
              btfsc     ZeroFlag
              goto      ProcessInt_TX1A
;
              movlb     0
;
              btfss     _TXIF
              goto      ProcessInt_Tx1End
;             
              PagedCall TxByteSerialPort_2
;  
              goto      ProcessInt_Tx1End
;
ProcessInt_TX1A:
;
              movlb     0
;
              movlb     TXSTA>>7
              btfss     _TRMT
              goto      ProcessInt_Tx1End
;
              movlb     PIE1>>7
              bcf       _TXIE
;
 ;             movlb     Rx1BufferWritePointer_3>>7 ;Flush the receive buffer
 ;             movf      Rx1BufferWritePointer_3,W
 ;             movwf     Rx1BufferReadPointer_3
;
              goto      ProcessInt_Tx1End
;
ProcessInt_TX1B:
;
              movlb     Tx1BufferReadPointer_3>>7
              movf      Tx1BufferReadPointer_3,W
              xorwf     Tx1BufferWritePointer_3,W
              btfsc     ZeroFlag
              goto      ProcessInt_Tx1End
;
              movlb     PIE1>>7
              bsf       _TXIE
;
              goto      ProcessInt_Tx1End
;
ProcessInt_Tx1End:
;
              movlb     0                       ;This is actually pointless, it will be replaced by the shadow registers 
;
              retfie
;
;***************************************
;
; This is the beginning, so we need to initialise everything
;
;***************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
Begin:
;
              movlb     ANSELA>>7
              movlw     b'00000000'              ;All ports are digital 
              movwf     ANSELA
              movlw     b'00000100'              ;
              movwf     ANSELC
;
              movlb     LATA>>7         
              movlw     b'00000000'              ;All ports are low
              movwf     LATA
              movlw     b'00000000'              ;Tx line defaults to active to keep comms chip powered down without a device
              movwf     LATC
;
              movlb     TRISA>>7
              movlw     b'00001100'              ;Select inputs and outputs
              movwf     TRISA
              movlw     b'00100111'              ;Select inputs and outputs
              movwf     TRISC
;
;#define ICDDAT PORTA,0
;#define ICDDAT PORTA,1
#define Alarm PORTA,2
#define MCLR_Reed PORTA,3
;#define OSC1  PORTA,4
;#define OSC2  PORTA,5
;
#define SCL_Direction TRISC,0
#define SCL_In        PORTC,0 
#define SCL_Out       LATC,0
#define SDA_Direction TRISC,1
#define SDA_In        PORTC,1 
#define SDA_Out       LATC,1
#define USBAlert PORTC,2
#define Power LATC,3
#define ReadPower PORTC,3
#define TxPin LATC,4
#define RxPin PORTC,5
;
#define BBTx PORTA,0
;
#define Track_USBAlert b'00011001'
#define USBAlert_Threshold 950
;
              movlb     OSCCON>>7
              movlw     b'00011000'              ;Switch to high speed to get through the initialisation quickly
              movwf     OSCCON
;
              clrf      Flags0_A
              clrf      Flags1_A
              clrf      Flags2_A
;
              bsf       HighSpeed
;
              movlb     WPUA>>7
              movlw     b'00000111'              ;Select internal pull-ups
              movwf     WPUA
;
              movlb     INLVLA>>7
              movlw     b'00000100'
              movwf     INLVLA
;
              movlb     IOCAP>>7
              movlw     b'00001000'
              movwf     IOCAP
;
              movlb     IOCAF>>7
              movlw     0
              movwf     IOCAF
;
              movlb     APFCON0>>7
              movlw     b'00000000'
              movwf     APFCON0
;
              movlb     ADCON1>>7
              movlw     b'11110011'
              movwf     ADCON1
;
              movlb     TMR2>>7
              clrf      TMR2
;
              movlb     PR2>>7
              movlw     255
              movwf     PR2
;
              movlb     T2CON>>7
              movlw     b'01111111' ;Pre-scaler=64 Post-scaler=16 PR2=255 4*16*64*255/31250=33,42336
              movwf     T2CON
;
              movlb     OPTION_REG>>7
              movlw     b'10011111' ;No pre-scaler internal oscillator/4 as source=0,032768 - interrupt responds to falling edge
              movwf     OPTION_REG
;
              movlb     TMR0>>7
              clrf      TMR0
;
              movlb     0
;
              clrf      DetermineHiLo_State_0
;
              movlw     0
              movwf     RainPulseTimeLost_0
;
              movlb     EventQueueWritePointer_0>>7
              movlw     EventQueueFirstLocation
              movwf     EventQueueWritePointer_0
              movwf     EventQueueReadPointer_0
              movlw     EventQueueSize
              movwf     EventQueueAvailable_0
              movlw     0
              movwf     EventState_0
;
              movlb     EEPROM_WritePointer_0>>7
              movlw     EEPROM_FirstLocation
              movwf     EEPROM_WritePointer_0
              movwf     EEPROM_ReadPointer_0
              movlw     0
              movwf     EEPROM_Buffered_0   
;
              PagedCall RestoreSettings_Bulk_3
;
              movlb     LATC>>7                  ;The clock always has power, but we need to switch on the I2C pull-up resistors
              bsf       Power
;
              call      I2C_Delay
;
              movlw     HIGH(Seconds_2)
              movwf     FSR0H
              movlw     LOW(Seconds_2)
              movwf     FSR0L
;
              call      I2C_Start               
              movlw     b'11010000'
              call      I2C_Tx        
              movlw     b'00000000'              ;Read the Seconds register in order to check the CH bit
              call      I2C_Tx
              call      I2C_Start
              movlw     b'11010001'
              call      I2C_Tx
              bcf       AckTx
              call      I2C_Rx
              bsf       AckTx 
              movwf     INDF0
              call      I2C_Stop
;
              btfsc     INDF0,7
              goto      ColdStart
;
WarmStart:
;
              movlb     HiLoDetail1_2>>7
              movlw     0xBE
              movwf     HiLoDetail1_2
              movlw     0xEF
              movwf     HiLoDetail2_2
;
              call      I2C_Start                
              movlw     b'11010000'
              call      I2C_Tx        
              movlw     b'00000001'              ;The clock is good, so carry on reading from the minutes 
              call      I2C_Tx
              call      I2C_Start
              movlw     b'11010001'
              call      I2C_Tx
              bsf       AckTx 
              call      I2C_Rx                   ;Minutes
              movwi     ++FSR0
              call      I2C_Rx                   ;Hours
              movwi     ++FSR0
              call      I2C_Rx                   ;DayOfWeek
              movwi     ++FSR0
              call      I2C_Rx                   ;Date
              movwi     ++FSR0
              call      I2C_Rx                   ;Month
              movwi     ++FSR0
              call      I2C_Rx                   ;Year
              movwi     ++FSR0
              bcf       AckTx
              call      I2C_Rx                   ;Control
              bsf       AckTx
              movwi     ++FSR0
              call      I2C_Stop
;
              movlw     0x10                     ;Check control is setup correctly
              xorwf     INDF0,W
              btfss     ZeroFlag
              goto      ColdStart
;
              PagedCall CalculateSecondsOffset_2
;
              goto      ClockRunning
;
ColdStart:
;
              movlb     PowerUps_0>>7
              movlw     1
              addwf     PowerUps_0,Same
              movlw     0
              addwfc    PowerUps_0H,Same
;
              btfss     CarryFlag
              goto      ColdStart_1
;
              movlw     0xFF
              movwf     PowerUps_0
              movwf     PowerUps_0H
;
ColdStart_1:
;
              movlb     HiLoDetail1_2>>7
              movlw     0xDE
              movwf     HiLoDetail1_2
              movlw     0xAD
              movwf     HiLoDetail2_2
;
; Start the clock - we don't have any date or time, but we need the 1s tick, so we don't have a choice
;
              movlb     Seconds_Offset_0>>7
              clrf      Seconds_Offset_0
              clrf      Seconds_Offset_0H
              clrf      Seconds_Offset_0HH
;
              movlw     LOW(Seconds_2)
              movwf     FSR1L
              movlw     HIGH(Seconds_2)
              movwf     FSR1H  
;
              call      I2C_Start
              movlw     b'11010000'
              call      I2C_Tx        
              movlw     b'00000000'
              call      I2C_Tx
              movlw     0x00 ;0 = Seconds
              movwi     FSR0++
              call      I2C_Tx
              movlw     0x00 ;1 = Minutes
              movwi     FSR0++
              call      I2C_Tx
              movlw     0x07 ;2 = Hours
              movwi     FSR0++
              call      I2C_Tx
              movlw     0x00 ;3 = DayOfWeek
              movwi     FSR0++
              call      I2C_Tx
              movlw     0x07 ;4 = Date
              movwi     FSR0++
              call      I2C_Tx
              movlw     0x04 ;5 = Month
              movwi     FSR0++
              call      I2C_Tx
              movlw     0x20 ;6 = Year
              movwi     FSR0++
              call      I2C_Tx
              movlw     0x10 ;7 = Control
              movwi     FSR0++
              call      I2C_Tx
              call      I2C_Stop
;
; The highs and lows we loaded from EEPROM earlier are meaningless, so let's reset them like we would every day
;
              movlb     HumidityLo_0>>7
              movlw     0xFF
              movwf     HumidityLo_0
              movwf     TemperatureLo_0
              movwf     TemperatureLo_0H 
;
              movlw     0x00
              movwf     HumidityHi_0
              movwf     TemperatureHi_0
              movwf     TemperatureHi_0H 
;
ClockRunning:
;
              movlb     LATC>>7
              bcf       Power
;
              call      I2C_Delay
;
              PagedCall LogHiLoEvent_2           ;Log this power up event to external EEPROM
;
              movlb     PIR3>>7
              bsf       _TMR4IF                  ;Ensure we can read the first rain pulse
;
              movlb     OSCCON>>7
              movlw     b'00011010' ;Run at low speed to save battery power 
              movwf     OSCCON
;
              bcf       HighSpeed 
;
           IFDEF LiveDebugEnable
;
              movlb     LATC>>7
              bsf       TxPin
;
              movlb     SPBRG>>7
;
              movlw     LOW(1) ;3906bps @ 31250Hz
              movwf     SPBRG
              movlw     HIGH(1)
              movwf     SPBRGH
;
              movlw     b'00001000' ;16-bit baud rate
              movwf     BAUDCON
;
              movlw     b'00100110' ;High speed UART
              movwf     TXSTA
;
              movlw     b'10010000'
              movwf     RCSTA
;
              movlb     0
;
              bsf       LiveDebugInitialised
;
           ENDIF
;
Forever_RainGauge:
;
              LiveDebug LiveDebug_Forever_RainGauge
;
              btfsc     _INTF
              call      ProcessRTC
;
              btfsc     _IOCIF
              call      CaptureRainPulse
;
ProcessEvent:
;
              call      ReadEventQueue  
;
              movlp     HIGH(EventDispatchTable)
;
              swapf      Event_0,W
              andlw     b'00000111'
              addlw     LOW(EventDispatchTable)
              btfsc     CarryFlag
              incf      PCLATH,Same 
              movwf     PCL

EventDispatchTable:
;
#define Event_PowerDown 0*16
EDT00:        goto      Event_X_PowerDown
#define Event_DetermineHiLo      1*16
EDT01:        goto      Event_X_DetermineHiLo
#define Event_WriteEEPROM 2*16
EDT02:        goto      Event_X_WriteEEPROM               
#define Event_RefreshNV 3*16
EDT03:        goto      Event_X_RefreshNV
#define Event_QueueDailyLog 4*16
EDT04:        goto      Event_X_QueueDailyLog
#define Event_SampleBatteryVoltage 5*16
EDT05:        goto      Event_X_SampleBatteryVoltage
EDT06:        nop    
EDT07:        nop
;
              call      RemoveEventFromQueue
;
              LiveDebug LiveDebug_UnknownState
;
              goto      ProcessEvent_End
;
Event_X_PowerDown:
;
; The event queue is empty, so we may be able to power down
;
              bsf       PowerDown
;
; To speed up testing all the garbage flags are kept in a single byte which should normally be 0
;
              movf      GarbageFlags_A,W
              btfsc     ZeroFlag   
              goto      Event_X_PowerDown1 
;
              bcf       PowerDown
;
              movlw     LogEvent_GarbageFlags
              call      EEPROM_WriteBuffer
              movf      GarbageFlags_A,W
              call      EEPROM_WriteBuffer
;             
              movlw     Event_WriteEEPROM
              call      WriteEventToQueue
;
              clrf      GarbageFlags_A
;
Event_X_PowerDown1:
;
              movlb     RainPulseTimeLost_0>>7
              movf      RainPulseTimeLost_0,W
              btfsc     ZeroFlag
              goto      Event_X_PowerDown2 
;
              bcf       PowerDown
;
              movlw     LogEvent_RainPulseTimeLost
              call      EEPROM_WriteBuffer
              movlb     RainPulseTimeLost_0>>7
              movf      RainPulseTimeLost_0,W
              call      EEPROM_WriteBuffer
;             
              movlw     Event_WriteEEPROM
              call      WriteEventToQueue
;
              movlb     RainPulseTimeLost_0>>7
              clrf      RainPulseTimeLost_0
;
Event_X_PowerDown2:
;
              btfss     PowerDown
              goto      Event_X_PowerDown_Out
;
; When we get here, we know that there are no events in the queue, so it could be safe to switch to comms mode if a device has connected
;
              btfss     CheckUSBAlert
              goto      Event_X_PowerDown_Now
;
              bcf       CheckUSBAlert
;
; - So seen as we have nothing to do and we are potentially waiting for device to connect, let's verify the firmware version hasn't been trashed before we connect to a device
;
              movlb     FirmwareYear_0>>7
;
              movlw     VersionYear
              subwf     FirmwareYear_0,W
              btfss     ZeroFlag
              goto      ReloadFirmwareVersion
;
              movlw     VersionMonth
              subwf     FirmwareMonth_0,W
              btfss     ZeroFlag
              goto      ReloadFirmwareVersion
;
              movlw     VersionDayTens
              subwf     FirmwareDayTens_0,W
              btfss     ZeroFlag
              goto      ReloadFirmwareVersion
;
              movlw     VersionDayUnits
              subwf     FirmwareDayUnits_0,W
              btfsc     ZeroFlag
              goto      Event_X_PowerDown3
;
ReloadFirmwareVersion:
;
              bcf       PowerDown
;
              movlw     VersionYear
              movwf     FirmwareYear_0
              movlw     VersionMonth
              movwf     FirmwareMonth_0
              movlw     VersionDayTens
              movwf     FirmwareDayTens_0
              movlw     VersionDayUnits
              movwf     FirmwareDayUnits_0
;
              goto      Event_X_PowerDown_Now
;
Event_X_PowerDown3:
;
              movlw     Track_USBAlert
              PagedCall ReadADC_2
              movlw     LOW(USBAlert_Threshold)
              subwf     ADRESL,W
              movlw     HIGH(USBAlert_Threshold)
              subwfb    ADRESH,W
           IFNDEF LiveDebugEnable
              btfss     CarryFlag    
           ENDIF
              goto      Event_X_PowerDown_Now
;
; OK, so we have a device connected, but first check that the external EEPROM buffer is empty, otherwise FLUSHHH it first and then try again
;
              movlb     EEPROM_Buffered_0>>7
              movf      EEPROM_Buffered_0,W
              btfsc     ZeroFlag 
              goto      SwitchToComms
;
              movlw     'F'
              call      EEPROM_WriteBuffer
              movlw     EEPROM_WritePageSize
              subwf     EEPROM_Buffered_0,W
              btfsc     ZeroFlag
              goto      Event_X_PowerDown_Flush
;
              movlw     'L'
              call      EEPROM_WriteBuffer
              movlw     EEPROM_WritePageSize
              subwf     EEPROM_Buffered_0,W
              btfsc     ZeroFlag
              goto      Event_X_PowerDown_Flush
;
              movlw     'U'
              call      EEPROM_WriteBuffer
              movlw     EEPROM_WritePageSize
              subwf     EEPROM_Buffered_0,W
              btfsc     ZeroFlag
              goto      Event_X_PowerDown_Flush
;
              movlw     'S'
              call      EEPROM_WriteBuffer
              movlw     EEPROM_WritePageSize
              subwf     EEPROM_Buffered_0,W
              btfsc     ZeroFlag
              goto      Event_X_PowerDown_Flush
;
Event_X_PowerDown_Flushing:
;
              movlw     'H'
              call      EEPROM_WriteBuffer
              movlw     EEPROM_WritePageSize
              subwf     EEPROM_Buffered_0,W
              btfss     ZeroFlag
              goto      Event_X_PowerDown_Flushing
;        
Event_X_PowerDown_Flush:
;
              movlw     Event_WriteEEPROM
              call      WriteEventToQueue
;
              goto      Event_X_PowerDown_Out
;
Event_X_PowerDown_Now:
;
              PagedCall VerifySettings_3
;
              btfss     PowerDown
              goto      Event_X_PowerDown_Out
;
; At the moment we don't actually power down, so just keep waiting for events
;
Event_X_PowerDown_Out:
;
              goto      ProcessEvent_End  
;
;*************************************************
;
Event_X_DetermineHiLo:
;
              LiveDebug LiveDebug_DetermineHiLo_Start
;
              movlp     HIGH(DetermineHiLoDispatchTable)
;
              movf      EventState_0,W
              addwf     DetermineHiLo_State_0,W
              andlw     b'00001111'
              addlw     LOW(DetermineHiLoDispatchTable)
              btfsc     CarryFlag
              incf      PCLATH,Same 
              movwf     PCL

DetermineHiLoDispatchTable:
;
DHLDT00:       goto      Event_X_DHL_PowerOn
DHLDT01:       goto      Event_X_DHL_WaitPowerOn
DHLDT02:       goto      Event_X_DHL_Initialise
DHLDT03:       goto      Event_X_DHL_WaitInitialise
DHLDT04:       goto      Event_X_DHL_StartConversion
DHLDT05:       goto      Event_X_DHL_WaitConversion
DHLDT06:       goto      Event_X_DHL_Read
DHLDT07:       goto      Event_X_DHL_Temperature1
DHLDT08:       goto      Event_X_DHL_Temperature2
DHLDT09:       goto      Event_X_DHL_Temperature3
DHLDT10:       goto      Event_X_DHL_Temperature4
DHLDT11:       goto      Event_X_DHL_Humidity1
DHLDT12:       goto      Event_X_DHL_Humidity2
DHLDT13:       goto      Event_X_DHL_Humidity3
DHLDT14:       nop
DHLDT15:       nop      
;
              call     RemoveEventFromQueue
;
              LiveDebug LiveDebug_UnknownState
;
              goto      Event_X_DetermineHiLo_End
;
;*************************************************
;
DetermineHiLo_Push:
;
               movlw    LOW(DetermineHiLo_Calculator0_2)
               movwf    FSR0L
               movlw    HIGH(DetermineHiLo_Calculator0_2)
               movwf    FSR0H
;  
               movf     CalculatorX0,W
               movwi    FSR0++
               movf     CalculatorX1,W
               movwi    FSR0++
               movf     CalculatorX2,W
               movwi    FSR0++
               movf     CalculatorX3,W
               movwi    FSR0++
               movf     CalculatorX4,W
               movwi    FSR0++
;
               return
;
;*************************************************
;
DetermineHiLo_Pop:
;
               movlw    LOW(DetermineHiLo_Calculator0_2)
               movwf    FSR0L
               movlw    HIGH(DetermineHiLo_Calculator0_2)
               movwf    FSR0H
;
               moviw    FSR0++
               movwf    CalculatorX0
               moviw    FSR0++
               movwf    CalculatorX1
               moviw    FSR0++
               movwf    CalculatorX2
               moviw    FSR0++
               movwf    CalculatorX3
               moviw    FSR0++
               movwf    CalculatorX4
;
               return
;
;*************************************************
;
CheckPeripheralPowerIsOff: macro Bit ;Checks the power to the peripherals is off
;
              local     CheckPeripheralPowerIsOff1
;
              movlb     PORTC>>7                 ;Check the power pin is low, otherwise log a problem
              btfss     ReadPower 
              goto      CheckPeripheralPowerIsOff1
;
              movlb     Debug3_0>>7
              bcf       Debug3_0,Bit
;
CheckPeripheralPowerIsOff1:
;
              endm
;
;*************************************************
;
CheckPeripheralPowerIsOn: macro Bit ;Checks the power to the peripherals is on
;
              local     CheckPeripheralPowerIsOn1
;
              movlb     PORTC>>7                 ;Check the power pin is high, otherwise log a problem
              btfsc     ReadPower 
              goto      CheckPeripheralPowerIsOn1
;
              movlb     Debug3_0>>7
              bcf       Debug3_0,Bit
;
CheckPeripheralPowerIsOn1:
;
              endm
;
;*************************************************
;
Event_X_DHL_PowerOn:
;
              CheckPeripheralPowerIsOff 0 
;
              movlb     LATC>>7
              bsf       Power
;
              movlb     T1CON>>7
              clrf      T1CON
              movlw     HIGH(65536-625)
              movwf     TMR1H
              movlw     LOW(65536-625)
              movwf     TMR1L
              bcf       _TMR1IF
              movlw     b'00000000'
              movwf     T1GCON
              movlw     b'01000001'
              movwf     T1CON
;
              movlb     EventState_0>>7
              incf      EventState_0,Same
;
              goto      Event_X_DetermineHiLo_End
;
Event_X_DHL_WaitPowerOn:
;
              movlb     PIR1>>7
              btfss     _TMR1IF
              goto      Event_X_DHL_WaitPowerOn_End
;
              CheckPeripheralPowerIsOn 1   
;
              movlb     EventState_0>>7
              incf      EventState_0,Same
;
Event_X_DHL_WaitPowerOn_End:
;
              goto      Event_X_DetermineHiLo_End
;
Event_X_DHL_Initialise:
;
              CheckPeripheralPowerIsOn 2
;
              call      I2C_Start
              movlw     b'01110000'
              call      I2C_Tx        
              movlw     b'11100001'
              call      I2C_Tx
              movlw     b'00001000'
              call      I2C_Tx
              movlw     b'00000000'
              call      I2C_Tx
              call      I2C_Stop
;
              movlb     T1CON>>7
              clrf      T1CON
              movlw     HIGH(65536-625)
              movwf     TMR1H
              movlw     LOW(65536-625)
              movwf     TMR1L
              bcf       _TMR1IF
              movlw     b'00000000'
              movwf     T1GCON
              movlw     b'01000001'
              movwf     T1CON
;
              movlb     EventState_0>>7
              incf      EventState_0,Same
;
              goto      Event_X_DetermineHiLo_End
;
Event_X_DHL_WaitInitialise:
;
              CheckPeripheralPowerIsOn 3
;
              movlb     PIR1>>7
              btfss     _TMR1IF
              goto      Event_X_DHL_WaitInitialise_End
;
              movlb     EventState_0>>7
              incf      EventState_0,Same
;
Event_X_DHL_WaitInitialise_End:
;
              goto      Event_X_DetermineHiLo_End
;
Event_X_DHL_StartConversion:
;
              CheckPeripheralPowerIsOn 4
;
              call      I2C_Start
              movlw     b'01110000'
              call      I2C_Tx
              movlw     b'10101100'
              call      I2C_Tx
              movlw     b'00110011'
              call      I2C_Tx
              movlw     b'00000000'
              call      I2C_Tx
              call      I2C_Stop
;
              movlb     DetermineHiLo_Extend_0>>7 
              movlw     16                       ;For now let's allow another 16 * 5msec slots for the conversion to complete, before aborting it
              movwf     DetermineHiLo_Extend_0
;
              movlb     T2CON>>7
              clrf      T2CON
              movlw     157
              movwf     PR2
              clrf      TMR2 
              bcf       _TMR2IF
              movlw     b'00000101'
              movwf     T2CON
;
              movlb     EventState_0>>7
              incf      EventState_0,Same
;
              goto      Event_X_DetermineHiLo_End
;
Event_X_DHL_WaitConversion:
;
              CheckPeripheralPowerIsOn 5
;
              movlb     PIR1>>7
              btfsc     _TMR2IF
              goto      Event_X_DHL_WaitConversion1
;
              movlb     EventState_0>>7
              movf      EventState_0,W
              btfss     ZeroFlag                 ;??? K520 is this test even relevant - yes it is - because we may have had to wait and then it will be 0! 
              movwf     DetermineHiLo_State_0
;
              call      RemoveEventFromQueue
;
              movlw     Event_DetermineHiLo
              call      WriteEventToQueue
;
              goto      Event_X_DHL_WaitConversion_End
;
Event_X_DHL_WaitConversion1:
;
              movlb     EventState_0>>7
;
              movf      EventState_0,W
              btfss     ZeroFlag
              goto      Event_X_DHL_WaitConversion2 
;
              movf      DetermineHiLo_State_0,W
              movwf     EventState_0
              clrf      DetermineHiLo_State_0
;
Event_X_DHL_WaitConversion2:
;
              incf      EventState_0,Same
;
Event_X_DHL_WaitConversion_End:
;
              goto      Event_X_DetermineHiLo_End
;
Event_X_DHL_Read:
;
              CheckPeripheralPowerIsOn 6
;
              movlb     EventState_0>>7
              movf      EventState_0,W
              movwf     DetermineHiLo_State_0
;          
              call      I2C_Start
              movlw     b'01110001'
              call      I2C_Tx
;
              bsf       AckTx
              call      I2C_Rx
              movlb     0
              movwf     AHT10_S_0
;
              btfss     AHT10_S_0,7
              goto      Event_X_DHL_Read_On
;
; If we get here we need to give the AHT10 more time to complete the conversion
;
              bcf       AckTx
              call      I2C_Rx
              bsf       AckTx
;
              call      I2C_Stop
;
; Debug1 counts how many times we need to extend the conversion time
;
              btfss     DetermineHiLo_Extend_0,4
              goto      Event_X_DHL_SkipDebug1
;
              incf      Debug1_0,W
              btfss     ZeroFlag
              incf      Debug1_0,Same
;
Event_X_DHL_SkipDebug1:
;
              decf      DetermineHiLo_Extend_0,Same
;
; Debug2 tracks the longest extension we gave the conversion time
;
              movf      Debug2_0,W
              subwf     DetermineHiLo_Extend_0,W
              movf      DetermineHiLo_Extend_0,W
              btfss     CarryFlag
              movwf     Debug2_0
;
              movf      DetermineHiLo_Extend_0,W
              btfsc     ZeroFlag
              goto      Event_X_DHL_Read_Cancel
;
              movlb     T1CON>>7
              clrf      T1CON
              movlw     HIGH(65536-39) ;Extend the conversion time by about 5msec
              movwf     TMR1H
              movlw     LOW(65536-39)
              movwf     TMR1L
              bcf       _TMR1IF
              movlw     b'00000000'
              movwf     T1GCON
              movlw     b'01000001'
              movwf     T1CON
;
              call      RemoveEventFromQueue
;
              movlb     DetermineHiLo_State_0>>7
              clrf      DetermineHiLo_State_0  
;
              movlw     5 ;Go back to WaitConversion
              movwf     EventState_0
;  
              movlw     Event_DetermineHiLo
              call      WriteEventToQueue

              goto      Event_X_DHL_Read_End
;
Event_X_DHL_Read_Cancel:
;
              movlb     LATC>>7
              bcf       Power ;??? what if we are writing to ext ee or can't that happen?
;
              call      I2C_Delay
;
              call      RemoveEventFromQueue
;
              movlb     DetermineHiLo_State_0>>7
              clrf      DetermineHiLo_State_0  
;
              goto      Event_X_DHL_Read_End
;
Event_X_DHL_Read_On:
;
              call      I2C_Rx
              movlb     0
              movwf     AHT10_H1_0
;
              call      I2C_Rx
              movlb     0
              movwf     AHT10_H2_0
;
              call      I2C_Rx
              movlb     0
              movwf     AHT10_HT_0
;
              call      I2C_Rx              
              movlb     0
              movwf     AHT10_T1_0
;
              bcf       AckTx
              call      I2C_Rx
              bsf       AckTx
              movlb     0
              movwf     AHT10_T2_0
;
              call      I2C_Stop
;
              movlb     LATC>>7
              bcf       Power ;??? what if we are writing to ext ee or can't that happen?
;
              call      I2C_Delay
;
              movlb     DetermineHiLo_State_0>>7
              incf      DetermineHiLo_State_0,Same
;
              call      RemoveEventFromQueue
;
              movlw     Event_DetermineHiLo
              call      WriteEventToQueue
;
Event_X_DHL_Read_End:
;
              goto      Event_X_DetermineHiLo_End
;
Event_X_DHL_Temperature1:
;
              CheckPeripheralPowerIsOff 7
;
              movlb     AHT10_T2_0>>7
;
              movf      AHT10_T2_0,W
              movwf     CalculatorX0         
              movf      AHT10_T1_0,W
              movwf     CalculatorX1         
              movf      AHT10_HT_0,W
              andlw     b'00001111' 
              movwf     CalculatorX2
              clrf      CalculatorX3
              clrf      CalculatorX4
;
              movlw     LOW(20000)
              movwf     CalculatorY0
              movlw     HIGH(20000)
              movwf     CalculatorY1
              clrf      CalculatorY2         
              clrf      CalculatorY3         
              clrf      CalculatorY4         
;
              PagedCall Mul40_2
;
              call      DetermineHiLo_Push
;
              movlb     DetermineHiLo_State_0>>7
              incf      DetermineHiLo_State_0,Same
;
              call      RemoveEventFromQueue
;
              movlw     Event_DetermineHiLo
              call      WriteEventToQueue
;
              goto      Event_X_DetermineHiLo_End
;
Event_X_DHL_Temperature2:
;
              call      DetermineHiLo_Pop
;
              movlb     CalculatorY0>>7
;
              movlw     0x00
              movwf     CalculatorY0
              movlw     0x00
              movwf     CalculatorY1
              movlw     0x10
              movwf     CalculatorY2
              clrf      CalculatorY3         
              clrf      CalculatorY4         
;
              PagedCall Div40_2
;
              call      DetermineHiLo_Push
;
              movlb     DetermineHiLo_State_0>>7
              incf      DetermineHiLo_State_0,Same
;
              call      RemoveEventFromQueue
;
              movlw     Event_DetermineHiLo
              call      WriteEventToQueue
;
              goto      Event_X_DetermineHiLo_End
;
Event_X_DHL_Temperature3:
;
              call      DetermineHiLo_Pop
;
              movlb     CalculatorY0>>7
;
              movlw     LOW(5000)
              movwf     CalculatorY0
              movlw     HIGH(5000)
              movwf     CalculatorY1
              clrf      CalculatorY2         
              clrf      CalculatorY3         
              clrf      CalculatorY4         
;
 ;K520 moved the negative offset from the PIC to the APP, so we don't have to handle negative numbers when determining the Highs and Lows             PagedCall Sub40_2
;
              call      DetermineHiLo_Push
;
              movlb     DetermineHiLo_State_0>>7
              incf      DetermineHiLo_State_0,Same
;
              call      RemoveEventFromQueue
;
              movlw     Event_DetermineHiLo
              call      WriteEventToQueue
;
              goto      Event_X_DetermineHiLo_End
;
Event_X_DHL_Temperature4:
;
              call      DetermineHiLo_Pop
;
              movlb     CalculatorX0>>7
;
              movf      CalculatorX0,W
              movwf     Temperature_0
              subwf     TemperatureLo_0,W
              movf      CalculatorX1,W
              movwf     Temperature_0H
              subwfb    TemperatureLo_0H,W
;
              btfss     CarryFlag
              goto      SkipTLo
;
              movf      CalculatorX0,W
              movwf     TemperatureLo_0
              movf      CalculatorX1,W
              movwf     TemperatureLo_0H
;
SkipTLo:
;
              movf      CalculatorX0,W
              subwf     TemperatureHi_0,W
              movf      CalculatorX1,W
              subwfb    TemperatureHi_0H,W
;
              btfsc     CarryFlag
              goto      SkipTHi
;
              movf      CalculatorX0,W
              movwf     TemperatureHi_0
              movf      CalculatorX1,W
              movwf     TemperatureHi_0H
;
SkipTHi:
;
              movlb     DetermineHiLo_State_0>>7
              incf      DetermineHiLo_State_0,Same
;
              call      RemoveEventFromQueue
;
              movlw     Event_DetermineHiLo
              call      WriteEventToQueue
;
              goto      Event_X_DetermineHiLo_End
;
Event_X_DHL_Humidity1:
;
              movlb     AHT10_HT_0>>7
;
              movf      AHT10_HT_0,W
              movwf     CalculatorX0         
              movf      AHT10_H2_0,W
              movwf     CalculatorX1         
              movf      AHT10_H1_0,W
              movwf     CalculatorX2
;
              rrf       CalculatorX2,Same            
              rrf       CalculatorX1,Same            
              rrf       CalculatorX0,Same            
;
              rrf       CalculatorX2,Same            
              rrf       CalculatorX1,Same            
              rrf       CalculatorX0,Same            
;
              rrf       CalculatorX2,Same            
              rrf       CalculatorX1,Same            
              rrf       CalculatorX0,Same            
;
              rrf       CalculatorX2,Same            
              rrf       CalculatorX1,Same            
              rrf       CalculatorX0,Same            
;
              movlw     b'00001111'
              andwf     CalculatorX2,Same 
;
              clrf      CalculatorX3
              clrf      CalculatorX4
;
              movlw     LOW(100)                 ;*100 = 0 to 100% with no decimal places or 1000 = 1 decimal place or 10000 = 2 decimal places
              movwf     CalculatorY0
              movlw     HIGH(100)
              movwf     CalculatorY1
              clrf      CalculatorY2         
              clrf      CalculatorY3         
              clrf      CalculatorY4         
;
              PagedCall Mul40_2
;
              call      DetermineHiLo_Push
;
              movlb     DetermineHiLo_State_0>>7
              incf      DetermineHiLo_State_0,Same
;
              call      RemoveEventFromQueue
;
              movlw     Event_DetermineHiLo
              call      WriteEventToQueue
;
              goto      Event_X_DetermineHiLo_End
;
Event_X_DHL_Humidity2:
;
              call     DetermineHiLo_Pop
;
              movlb    CalculatorY0>>7
;
              movlw     0x00
              movwf     CalculatorY0
              movlw     0x00
              movwf     CalculatorY1
              movlw     0x10
              movwf     CalculatorY2
              clrf      CalculatorY3         
              clrf      CalculatorY4         
;
              PagedCall Div40_2
;
              call      DetermineHiLo_Push
;
              movlb     DetermineHiLo_State_0>>7
              incf      DetermineHiLo_State_0,Same
;
              call      RemoveEventFromQueue
;
              movlw     Event_DetermineHiLo
              call      WriteEventToQueue
;
              goto      Event_X_DetermineHiLo_End
;
Event_X_DHL_Humidity3:
;
              call     DetermineHiLo_Pop
;
              movlb    CalculatorX0>>7
;
              movf      CalculatorX0,W
              movwf     Humidity_0
              subwf     HumidityLo_0,W
;
              btfss     CarryFlag
              goto      SkipHLo
;
              movf      CalculatorX0,W
              movwf     HumidityLo_0
;
SkipHLo:
;
              movf      CalculatorX0,W
              subwf     HumidityHi_0,W
;
              btfsc     CarryFlag
              goto      SkipHHi
;
              movf      CalculatorX0,W
              movwf     HumidityHi_0
;
SkipHHi:
;
              call      RemoveEventFromQueue
;
              movlb     DetermineHiLo_State_0>>7
              clrf      DetermineHiLo_State_0  
;
              goto      Event_X_DetermineHiLo_End
;
Event_X_DetermineHiLo_End:
;
              LiveDebug LiveDebug_DetermineHiLo_End
;
              goto      ProcessEvent_End
;
;*************************************************
;
Event_X_WriteEEPROM:
;
              LiveDebug LiveDebug_WriteExtEEPROM_Start
;
              PagedCall Event_X_WriteEEPROM_1
;
              LiveDebug LiveDebug_WriteExtEEPROM_End
;
              goto      ProcessEvent_End
;
;*************************************************
;
Event_X_RefreshNV:
;
              LiveDebug LiveDebug_RefreshNV_Start
;
              PagedCall Event_X_RefreshNV_1 
;
              LiveDebug LiveDebug_RefreshNV_End
;
              goto      ProcessEvent_End
;
;*************************************************
;
Event_X_QueueDailyLog:
;
              LiveDebug LiveDebug_QueueDailyLog_Start
;
              PagedCall Event_X_QueueDailyLog_1
;
              LiveDebug LiveDebug_QueueDailyLog_End
;
              goto      ProcessEvent_End
;
;*************************************************
;
Event_X_SampleBatteryVoltage:
;
              LiveDebug LiveDebug_SampleBattery_Start
;
              PagedCall Event_X_SampleBatteryVoltage_1
;
              LiveDebug LiveDebug_SampleBattery_End
;
              goto      ProcessEvent_End
;
;*************************************************
;
ProcessEvent_End:
;
;*************************************************
;
              goto      Forever_RainGauge
;
SwitchToComms:
;
              movlb     OSCCON>>7
              movlw     b'00011000'              ;Switch to high speed to communicate at 38400bps
              movwf     OSCCON
;
              bsf       HighSpeed
;
              movlb     LATC>>7
              bsf       TxPin
;
              movlb     Tx1BufferReadPointer_3>>7
              movlw     Tx1BufferLastLocation  ;Initialise the transmit buffer pointers
              movwf     Tx1BufferReadPointer_3
              movwf     Tx1BufferWritePointer_3
;
              movlb     Rx1BufferReadPointer_3>>7
              movlw     Rx1BufferLastLocation  ;Initialise the receive buffer pointers
              movwf     Rx1BufferReadPointer_3
              movwf     Rx1BufferWritePointer_3
;
              movlb     SPBRG>>7
;
              movlw     LOW(71) ;38400bps
              movwf     SPBRG
              movlw     HIGH(71)
              movwf     SPBRGH
;
              movlw     b'00001000' ;16-bit baud rate
              movwf     BAUDCON
;
              movlw     b'00100110' ;High speed UART
              movwf     TXSTA
;
              movlw     b'10010000'
              movwf     RCSTA
              movlb     PIE1>>7
;
              bcf       DeviceCommunicated
              bcf       DeviceSetClock
;
              bsf       _RCIE
;
              movlw     b'11000000'
              movwf     INTCON
;
              PagedCall SaveSettings_Bulk_3
;
              goto      Forever_Comms
;
Forever_Comms:
;
              call      CheckByteSerialBuffer1
              btfsc     CarryFlag
              call      ProcessSerialInput 
;
              btfss     _INTF
              goto      Forever_Comms1
;     
              bcf       _INTF
;
              bsf       CheckUSBAlert
;
              goto      Forever_Comms
;
Forever_Comms1:
;
              btfss     CheckUSBAlert
              goto      Forever_Comms2 
;
              bcf       CheckUSBAlert
;            
              movlw     Track_USBAlert
              PagedCall ReadADC_2
              movlw     LOW(USBAlert_Threshold)
              subwf     ADRESL,W
              movlw     HIGH(USBAlert_Threshold)
              subwfb    ADRESH,W
              btfss     CarryFlag            
              goto      SwitchToRainGauge
;
Forever_Comms2:
;
              goto      Forever_Comms
;
SwitchToRainGauge:
;
              movlb     RCSTA>>7
              movlw     b'00000000'
              movwf     RCSTA
;
              movlb     LATC>>7
              bcf       TxPin
;
              clrf      INTCON
;
              btfss     DeviceCommunicated
              goto      SwitchToRainGauge_1
;
              bcf       DeviceCommunicated
;
              movlb     Connections_0>>7
              movlw     1
              addwf     Connections_0,Same
              movlw     0
              addwfc    Connections_0H,Same
;
              btfss     CarryFlag
              goto      SwitchToRainGauge_1
;
              movlw     0xFF
              movwf     Connections_0
              movwf     Connections_0H
;
SwitchToRainGauge_1:
;
              PagedCall SaveSettings_Bulk_3
;
              movlb     LATC>>7
              bsf       Power
;
              call      I2C_Delay
;
              movlw     HIGH(Seconds_2)
              movwf     FSR0H
              movlw     LOW(Seconds_2)
              movwf     FSR0L
;
              call      I2C_Start                
              movlw     b'11010000'
              call      I2C_Tx        
              movlw     b'00000000'              ;Read the clock 
              call      I2C_Tx
              call      I2C_Start
              movlw     b'11010001'
              call      I2C_Tx
              bsf       AckTx 
              call      I2C_Rx                   ;Seconds
              movwi     FSR0++
              call      I2C_Rx                   ;Minutes
              movwi     FSR0++
              call      I2C_Rx                   ;Hours
              movwi     FSR0++
              call      I2C_Rx                   ;DayOfWeek
              movwi     FSR0++
              call      I2C_Rx                   ;Date
              movwi     FSR0++
              call      I2C_Rx                   ;Month
              movwi     FSR0++
              call      I2C_Rx                   ;Year
              movwi     FSR0++
              bcf       AckTx
              call      I2C_Rx                   ;Control
              bsf       AckTx
              movwf     INDF0
              call      I2C_Stop
;
              movlw     0x10                     ;Check control is setup correctly
              xorwf     INDF0,W
              btfsc     ZeroFlag
              goto      SwitchToRainGauge_2
;
; Make the clock TICK again - never mind the date and time that the app set or that was in the RTC
;
              call      I2C_Start
              movlw     b'11010000'
              call      I2C_Tx        
              movlw     b'00000111'
              call      I2C_Tx
              movlw     0x10 ;7 = Control
              call      I2C_Tx
              call      I2C_Stop
;
SwitchToRainGauge_2:
;
              movlb     LATC>>7
              bcf       Power 
;
              PagedCall CalculateSecondsOffset_2
;
              btfss     DeviceSetClock
              goto      SwitchToRainGauge_3
;
              bcf       DeviceSetClock 
;
              movlb     HiLoDetail1_2>>7
              movlw     0xFE
              movwf     HiLoDetail1_2
              movlw     0xED
              movwf     HiLoDetail2_2
;
              PagedCall LogHiLoEvent_2
;
SwitchToRainGauge_3:
;
              movlb     OSCCON>>7
              movlw     b'00011010'              ;Switch to low speed to save power
              movwf     OSCCON
;
              bcf       HighSpeed
;
              movlb     IOCAF>>7                 ;Make sure we clear away any rain pulses which came in while a device was plugged in
              movlw     0
              movwf     IOCAF
;
              goto      Forever_RainGauge
;
;*************************************************
;
; EventQueue
;
; The event queue has a write pointer and a read pointer
; This queue works by writing to the write pointer and then incrementing it
;
;*************************************************
;
WriteEventToQueue:
;
              movlb     EventQueueWritePointer_0>>7
;
              movwf     Event_0
;
              movf      EventQueueAvailable_0,W
              btfss     ZeroFlag
              goto      WriteEventToQueue1 
;
              bsf       EventQueueOverFlow
;
              goto      WriteEventToQueueEnd
;
WriteEventToQueue1:
;
              movlw     HIGH(EventQueue_5)
              movwf     FSR0H
;
              movf      EventQueueWritePointer_0,W
              movwf     FSR0L
;
              movf      Event_0,W
              movwi     FSR0++
;
              movf      FSR0L,W
              xorlw     EventQueueLastLocation+1
              btfsc     ZeroFlag
              movlw     EventQueueFirstLocation^(EventQueueLastLocation+1) 
              xorlw     EventQueueLastLocation+1
              movwf     EventQueueWritePointer_0
;
              decf      EventQueueAvailable_0,Same ;There is one less space available in the event queue
;
WriteEventToQueueEnd:
;
              return
;
ReadEventQueue:
;
              movlb     EventQueueReadPointer_0>>7
;
              movlw     EventQueueSize           ;IF all the bytes are available 
              subwf     EventQueueAvailable_0,W
              btfsc     ZeroFlag
              goto      ReadEventQueue1          ;THEN the queue is empty and we return with 0
;
              movlw     HIGH(EventQueue_5)
              movwf     FSR0H
;
              movf      EventQueueReadPointer_0,W
              movwf     FSR0L
;
              movf      INDF0,W
;
ReadEventQueue1:
;
              movwf     Event_0
;
ReadEventQueueEnd:
;
              return
;
RemoveEventFromQueue:
;
              movlb     EventQueueReadPointer_0>>7
;
              movlw     EventQueueSize           ;IF all the bytes are available 
              subwf     EventQueueAvailable_0,W
              btfss     ZeroFlag
              goto      RemoveEventFromQueue1    
;
              bsf       EventQueueUnderFlow      ;THEN the event queue is empty and has UnderFlowed
;
              goto      RemoveEventFromQueueEnd
;
RemoveEventFromQueue1:
;
              movlw     HIGH(EventQueue_5)
              movwf     FSR0H
;
              movf      EventQueueReadPointer_0,W
              movwf     FSR0L
;
              incf      EventQueueReadPointer_0,W
              xorlw     EventQueueLastLocation+1
              btfsc     ZeroFlag
              movlw     EventQueueFirstLocation^(EventQueueLastLocation+1)
              xorlw     EventQueueLastLocation+1
              movwf     EventQueueReadPointer_0
;
              incf      EventQueueAvailable_0,Same ;There is one more space available in the queue
;
              clrf      EventState_0
;
              movf      INDF0,W
              movwf     Event_0
;
RemoveEventFromQueueEnd:
;
              return   
;
PreemptEventsInQueue: ;Not really, but for multi-byte events this allows the event to be write back into the last byte of data once it has been processed
;
              movwf     Event_0
;
              movlw     HIGH(EventQueue_5)
              movwf     FSR0H
;
              movf      EventQueueReadPointer_0,W
              movwf     FSR0L
;
              movf      Event_0,W
              movwf     INDF0
;
PreemptEventsInQueue_End:
;
              return
;
;*************************************************
;
; EEPROMBuffer
;
; The EEPROM buffer has a write pointer and a read pointer
; This buffer works by writing to the write pointer and then incrementing it
;
;*************************************************
;
EEPROM_WriteBuffer:
;
              movlb     EEPROM_WritePointer_0>>7
;
              movwf     EEPROM_0
;
              movlw     EEPROM_BufferSize 
              subwf     EEPROM_Buffered_0,W
              btfss     CarryFlag
              goto      EEPROM_WriteBuffer1 
;
              bsf       EEPROM_OverFlow
;
              goto      EEPROM_WriteBufferEnd
;
EEPROM_WriteBuffer1:
;
              movlw     HIGH(EEPROM_Buffer_1)
              movwf     FSR0H
;
              movf      EEPROM_WritePointer_0,W
              movwf     FSR0L
;
              movf      EEPROM_0,W
              movwi     FSR0++
;
              movf      FSR0L,W
              xorlw     EEPROM_LastLocation+1
              btfsc     ZeroFlag
              movlw     EEPROM_FirstLocation^(EEPROM_LastLocation+1) 
              xorlw     EEPROM_LastLocation+1
              movwf     EEPROM_WritePointer_0
;
              incf      EEPROM_Buffered_0,Same ;There is one less space available in the event queue
;
EEPROM_WriteBufferEnd:
;
              return
;
EEPROM_ReadBuffer:
;
              movlb     EEPROM_ReadPointer_0>>7
;
              movf      EEPROM_Buffered_0,W
              btfss     ZeroFlag
              goto      EEPROM_ReadBuffer1       
;
              bsf       EEPROM_UnderFlow
;
              goto      EEPROM_ReadBufferEnd
;
EEPROM_ReadBuffer1:
;
              movlw     HIGH(EEPROM_Buffer_1)
              movwf     FSR0H
;
              movf      EEPROM_ReadPointer_0,W
              movwf     FSR0L
;
              moviw     FSR0++
              movwf     EEPROM_0
;
              movf      FSR0L,W
              xorlw     EEPROM_LastLocation+1
              btfsc     ZeroFlag
              movlw     EEPROM_FirstLocation^(EEPROM_LastLocation+1)
              xorlw     EEPROM_LastLocation+1
              movwf     EEPROM_ReadPointer_0
;
              decf      EEPROM_Buffered_0,Same ;There is one more space available in the queue
;
              movf      EEPROM_0,W
;
EEPROM_ReadBufferEnd:
;
              return   
;
ProcessRTC:
;
              bcf       _INTF
;
              LiveDebug LiveDebug_RTC
;
              bsf       CheckUSBAlert
;
              movlb     Seconds_Offset_0>>7
;
           IFNDEF AcceleratedTime
              movlw     1 
           ELSE
              movlw     AcceleratedTime_Adjustment
           ENDIF
;
              addwf     Seconds_Offset_0,Same
;
              btfss     CarryFlag
              goto      ProcessRTC1
;
              movlw     Event_DetermineHiLo      ;Determine the temperature and humidity Highs and Lows every 256s = 4M16S
              call      WriteEventToQueue
;
              movlw     0
              addwfc    Seconds_Offset_0H,Same
              movlw     0
              addwfc    Seconds_Offset_0HH,Same
;
ProcessRTC1:
;
              movlw     LOW(86400)
              subwf     Seconds_Offset_0,W
              movlw     HIGH(86400)
              subwfb    Seconds_Offset_0H,W
              movlw     UPPER(86400)
              subwfb    Seconds_Offset_0HH,W
;
              btfss     CarryFlag
              goto      ProcessRTC2
;
              movlw     Event_QueueDailyLog
              call      WriteEventToQueue
;
ProcessRTC2:           
;
ProcessRTC_End:
;
              return
;
CaptureRainPulse:
;
; So theoretically we only have one IOC event enabled, so theoretically there is only 1 reason we can get here, but stranger things have happened, so if
; the bouncing issue on the rain pulse input crops up again then maybe we must check to see if the bit we are interested in is actually set in IOCAF
;
              movlb     IOCAF>>7                 ;Clear the interrupt flag
              movlw     0
              movwf     IOCAF
; 
              movlb     PIR3>>7                  ;Check if the lock out timer has expired
              btfss     _TMR4IF
              goto      CaptureRainPulseEnd  
;
              LiveDebug LiveDebug_CaptureRainPulse
;
              movlb     T4CON>>7                 ;Lock out rain pulses for 250msec to filter out any bouncing
              clrf      T4CON
              movlw     217
              movwf     PR4
              clrf      TMR4 
              bcf       _TMR4IF
              movlw     b'01000100'
              movwf     T4CON
;
              movlb     RainPulse_0>>7           ;Accumulate the rain pulse
              movlw     1
              addwf     RainPulse_0,Same
              movlw     0
              addwfc    RainPulse_0H,Same
              movlw     0
              addwfc    RainPulse_0HH,Same
;
              btfss     CarryFlag                ;Limit to maximum
              goto      CaptureRainPulse1
;
              movlw     0xFF
              movwf     RainPulse_0
              movwf     RainPulse_0H
              movwf     RainPulse_0HH
;
CaptureRainPulse1:
;
              movlw     EEPROM_BufferSize+2      ;(I need space for 3 bytes)
              subwf     EEPROM_Buffered_0,W
              addlw     3
              btfss     CarryFlag
              goto      CaptureRainPulse2
;
              incfsz    RainPulseTimeLost_0,W
              incf      RainPulseTimeLost_0,Same
;
              goto      CaptureRainPulseEnd
;
CaptureRainPulse2:
;
              movf      Seconds_Offset_0HH,W     ;Queue it for logging to EEPROM
              movlw     LogEvent_RainPulse+0
              btfss     ZeroFlag
              movlw     LogEvent_RainPulse+1
              call      EEPROM_WriteBuffer
              movf      Seconds_Offset_0H,W
              call      EEPROM_WriteBuffer
              movf      Seconds_Offset_0,W
              call      EEPROM_WriteBuffer
;             
              movlw     Event_WriteEEPROM
              call      WriteEventToQueue
;
CaptureRainPulseEnd:
;
              movlb     0
;
              return
;
;***************************************
;
; Read data from internal EEPROM                
; - Address to be read in W  
; - Return with data in W
;
;***************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
ReadInternalEEPROM:
;
              movlb     EEADRL>>7
;
              movwf     EEADRL
              bcf       _EEPGD
              bcf       _EECFGS
              bsf       _EERD
              movf      EEDATL,W
;
              movlb     0
;
              return
;
;***************************************
;
; Write data into internal EEPROM                
; - EEADR loaded with address
; - Data to be written in W
; - Assumes interrupts are disabled
;
;***************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
WriteInternalEEPROM:
;
              movlb     EEDATL>>7
;
              movwf     EEDATL
              bcf       _EEPGD
              bcf       _EECFGS
              bsf       _EEWREN
;
              movlw     0x55
              movwf     EECON2
              movlw     0xAA
              movwf     EECON2
              bsf       _EEWR
;
              bcf       _EEWREN
;
              movlb     0
;
 ;             movlw     EE_LockOutTC
 ;             movwf     EE_LockOutTimer
;
              return
;
; I2C routines
;
I2C_Delay:
;
              btfss     HighSpeed
              goto      I2C_Delay_End  
;
              movlw     14
              movwf     I2C_DelayCounter_A
;
I2C_Delay_1:
;
              decfsz    I2C_DelayCounter_A,Same
              goto      I2C_Delay_1
;
I2C_Delay_End:
;
              return
;
I2C_Start:
;
              movlb     TRISC>>7
              bsf       SDA_Direction ;SDA pulled high
              call      I2C_Delay
              movlb     LATC>>7
              bsf       SCL_Direction ;SCL pulled high
              call      I2C_Delay
              movlb     LATC>>7
              bcf       SDA_Out       ;SDA active low
              movlb     TRISC>>7
              bcf       SDA_Direction
              call      I2C_Delay
              movlb     LATC>>7
              bcf       SCL_Out       ;SCL active low
              movlb     TRISC>>7
              bcf       SCL_Direction
              call      I2C_Delay
              movlb     0
;
              return
;
I2C_Stop:
;
              movlb     LATC>>7
              bcf       SDA_Out       ;SDA active low
              movlb     TRISC>>7
              bcf       SDA_Direction
              call      I2C_Delay
              movlb     TRISC>>7
              bsf       SCL_Direction ;Clock pulled high
              call      I2C_Delay
              movlb     TRISC>>7
              bsf       SDA_Direction ;SDA pulled high
              call      I2C_Delay
              movlb     0
;
              return
;
I2C_Rx:
;
              movlb     TRISC>>7
              bsf       SDA_Direction ;SDA pulled high
              movlw     8
              movwf     I2C_Count_A
;
I2C_RxLoop:
;
              bcf       CarryFlag
              rlf       I2C_Data_A,Same
;
              movlb     LATC>>7
              bsf       SCL_Direction ;SCL is pullsed high
;
ClockStretching:
;
              movlb     PORTC>>7
              btfss     SCL_In
              goto      ClockStretching
;
              call      I2C_Delay
;
              movlb     PORTC>>7
              btfsc     SDA_In
              bsf       I2C_Data_A,0
;
              movlb     LATC>>7
              bcf       SCL_Out    ;SCL active low
              movlb     TRISC>>7
              bcf       SCL_Direction
;
              call      I2C_Delay
;
              decfsz    I2C_Count_A,Same
              goto      I2C_RxLoop
;
              movlb     LATC>>7  
              bcf       SDA_Out
              movlb     TRISC>>7 
              btfsc     AckTx
              bcf       SDA_Direction
              btfss     AckTx
              bsf       SDA_Direction
;
              movlb     TRISC>>7
              bsf       SCL_Direction ;SCL pulled high
              call      I2C_Delay
              movlb     LATC>>7
              bcf       SCL_Out       ;SCL active low
              movlb     TRISC>>7
              bcf       SCL_Direction
              call      I2C_Delay
              movlb     TRISC>7      ;SDA pulled high
              bsf       SDA_Direction
;
              movf      I2C_Data_A,W
;
              movlb     0
;
              return
;
I2C_Tx:
;
              movwf     I2C_Data_A
              movlw     8
              movwf     I2C_Count_A
;
I2C_TxLoop:
;
              movlw     LATC>>7
              bcf       SDA_Out
              btfsc     I2C_Data_A,7
              goto      I2C_TxLoopHi
              goto      I2C_TxLoopLo
;
I2C_TxLoopHi:
;
              movlb     TRISC>>7
              bsf       SDA_Direction
;
              goto      I2C_TxLoop1
;
I2C_TxLoopLo:
;
              movlb     TRISC>>7
              bcf       SDA_Direction
;
              goto      I2C_TxLoop1
;
I2C_TxLoop1:
;
              call      I2C_Delay
;
              movlb     TRISC>7
              bsf       SCL_Direction ;SCL pulled high 
;
              call      I2C_Delay
;
              rlf       I2C_Data_A,Same
;
              movlb     LATC>>7
              bcf       SCL_Out
              movlb     TRISC>7
              bcf       SCL_Direction
;
              call      I2C_Delay ;???
;
              decfsz    I2C_Count_A,Same
              goto      I2C_TxLoop
;
              movlb     TRISC>>7
              bsf       SDA_Direction ;SDA pulled high
              call      I2C_Delay
              bsf       SCL_Direction ;SCL pulled high
              call I2C_Delay
              bsf       AckRx
              btfss     SDA_In
              bcf       AckRx
;
              movlb     LATC>>7
              bcf       SCL_Out
              movlb     TRISC>>7
              bcf       SCL_Direction
;
              call      I2C_Delay
;
              movlb     0
;
              return
;
;***************************************
;
; Check serial receive buffer 1 for byte:
; C = 1 then W = unbuffered serial byte
; C = 0 then serial buffer is empty
;
;**************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
CheckByteSerialBuffer1:
;
              movlb     Rx1BufferReadPointer_3>>7
              movf      Rx1BufferReadPointer_3,W
              xorwf     Rx1BufferWritePointer_3,W
              InvertBit ZeroFlag,CarryFlag
              btfsc     ZeroFlag
              goto      ReadByteSerialBuffer1End
              goto      ReadByteSerialBuffer1A
;
;***************************************
;
; Unbuffer byte from serial receive buffer 1 and return with it in W
;
;**************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
ReadByteSerialBuffer1
;
              movf      Rx1BufferReadPointer_3,W
              xorwf     Rx1BufferWritePointer_3,W
              btfsc     ZeroFlag
              goto      ReadByteSerialBuffer1
;
ReadByteSerialBuffer1A
;
              movlw     HIGH(Rx1Buffer_4)           ;Point to the correct page
              movwf     FSR0H
; 
              movf      Rx1BufferReadPointer_3,W
              movwf     FSR0L
;
              movf      INDF0,W
              movwf     Rx1BufferData_3 
;
              incf      Rx1BufferReadPointer_3,W
;
              xorlw     Rx1BufferLastLocation+1  ;IF > LAST
              btfsc     ZeroFlag                 ;THEN ROLL OVER to FIRST
              movlw     Rx1BufferFirstLocation^(Rx1BufferLastLocation+1) 
;
              xorlw     Rx1BufferLastLocation+1  ;Restore W from comparison
;
              movwf     Rx1BufferReadPointer_3
;    
              movf      Rx1BufferData_3,W         
;
              bsf       CarryFlag
;
ReadByteSerialBuffer1End
;
              movlb     0
;
              return             








FlushSerialReceiveBuffer1:
;
              movf      Rx1BufferWritePointer_3,W
              movwf     Rx1BufferReadPointer_3
;
              return



;
;***************************************
;
; Write byte from W to serial transmit buffer 1 
;
;**************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
WriteByteSerialBuffer1:
;
              movlb     Tx1BufferData_3>>7
;
              movwf     Tx1BufferData_3          ;Buffer character for later
;
              movlw     HIGH(Tx1Buffer_4)        ;Point to the correct page 
              movwf     FSR0H 
;
              movf      Tx1BufferWritePointer_3,W
              movwf     FSR0L
;
              addlw     1                        ;Point to next location 
;
              xorlw     Tx1BufferLastLocation+1  ;IF > LAST
              btfsc     ZeroFlag                 ;THEN ROLL OVER to FIRST
              movlw     Tx1BufferFirstLocation^(Tx1BufferLastLocation+1) 
;
              xorlw     Tx1BufferLastLocation+1  ;Restore W from comparison
              movwf     Tx1BufferWritePointerWork_3
;
              xorwf     Tx1BufferReadPointer_3,W ;IF WRITE = READ
              btfsc     ZeroFlag                 
              goto      WriteByteSerialBuffer1A  ;THEN FULL, so go
;
              movf      Tx1BufferData_3,W        ;Read the byte received
              movwf     INDF0                    ;And buffer it for transmission
;
              movf      Tx1BufferWritePointerWork_3,W ;Update the write pointer 
              movwf     Tx1BufferWritePointer_3
;
              movlb     PIE1>>7
              bsf       _TXIE
;
WriteByteSerialBuffer1A:
;
              movf      Tx1BufferData_3,W        ;Restore W to entry value
;
              movlb     0
;
              return
;
;
ProcessSerialInput:
;
              movlb     PacketCharacter_3>>7
              movwf     PacketCharacter_3
;
PSI_Interpret:
;
              movlw     '$'
              xorwf     PacketCharacter_3,W
              btfsc     ZeroFlag
              clrf      PacketState_3
;
PacketStateDispatcher:
;
              movlp     HIGH(PacketStateDispatchTable) 
;
              movf      PacketState_3,W
              andlw     b'00001111'
;
              addlw     LOW(PacketStateDispatchTable)
              btfsc     CarryFlag
              incf      PCLATH,Same
              movwf     PCL
;
PacketStateDispatchTable:
;
#define               S_PS_ReceiveStart             0
PSI_PSDT00:   goto      PS_ReceiveStart
#define               S_PS_ReceiveCommand           1
PSI_PSDT01:   goto      PS_ReceiveCommand 
#define               S_PS_ReceivePayLoad           2
PSI_PSDT02:   goto      PS_ReceivePayLoad
#define               S_PS_ReceiveCheckSum          3
PSI_PSDT03:   goto      PS_ReceiveCheckSum
#define               S_PS_ExecuteCommand           4
PSI_PSDT04:   goto      PS_ExecuteCommand
PSI_PSDT05:   goto      RestartPacketState
PSI_PSDT06:   goto      RestartPacketState
PSI_PSDT07:   goto      RestartPacketState
PSI_PSDT08:   goto      RestartPacketState
PSI_PSDT09:   goto      RestartPacketState
PSI_PSDT10:   goto      RestartPacketState
PSI_PSDT11:   goto      RestartPacketState
PSI_PSDT12:   goto      RestartPacketState
PSI_PSDT13:   goto      RestartPacketState
PSI_PSDT14:   goto      RestartPacketState
PSI_PSDT15:   goto      RestartPacketState
;
PS_ReceiveStart:
;
              movlw     HIGH(LineBuffer_3)
              movwf     FSR0H 
              movlw     LOW(LineBuffer_3)
              movwf     FSR0L
;
              movf      PacketCharacter_3,W
              movwf     INDF0
;
              bcf       ESCape                   ;Make sure the ESCape flag is clear
;
              movlw     S_PS_ReceiveCommand
              movwf     PacketState_3
;
              goto      PacketStateDispatcherEnd
;
PS_ReceiveCommand:
;
              movlw     HIGH(LineBuffer_3+1)
              movwf     FSR0H 
              movlw     LOW(LineBuffer_3+1)
              movwf     FSR0L
;
              movf      PacketCharacter_3,W
              movwf     INDF0
              movwf     PacketCommand_3
;
              btfss     PacketCommand_3,7
              goto      PS_ReceiveCommandFast
;
PS_ReceiveCommandNormal:
;
; There are no normal commands at the moment, so ignore this packet and wait for the next one
;
              goto      RestartPacketState
;
PS_ReceiveCommandFast:
;
              movlw     LOW(LineBuffer_3+2)
              movwf     LineBufferPointer_3
;
PS_RCF_Dispatcher:
;
              movlp     HIGH(PS_RCF_DispatchTable) 
;
              swapf     PacketCommand_3,W
              andlw     b'00000011'
;
              addlw     LOW(PS_RCF_DispatchTable)
              btfsc     CarryFlag
              incf      PCLATH,Same
              movwf     PCL
;
PS_RCF_DispatchTable:
;
PS_RCF_DT00:  goto      PS_RCF_DS1307
PS_RCF_DT01:  goto      PS_RCF_InternalEE
PS_RCF_DT02:  goto      PS_RCF_Command
PS_RCF_DT03:  goto      PS_RCF_ExternalEE
;
PS_RCF_Command:
;
              movlw     0                        ;There is no payload to receive in this packet
              movwf     PacketCounter_3
;
              goto      PS_ReceiveCommandFastEnd
;
PS_RCF_DS1307:
PS_RCF_InternalEE:
;              
              movlw     1                        ;There is 1 address byte included in these packets
              movwf     PacketCounter_3
;
              goto      PS_RCF_ReadnWrite
;
PS_RCF_ExternalEE:
;              
              movlw     3                        ;There are 3 address bytes included in this packet
              movwf     PacketCounter_3
;
              goto      PS_RCF_ReadnWrite
;
PS_RCF_ReadnWrite:
;
              btfsc     PacketCommand_3,6        ;IF READing
              goto      PS_RCF_ReadnWrite1       ;THEN go because there are no extra bytes to take in account
;
              movf      PacketCommand_3,W
              andlw     b'00001111'
              addlw     1
              addwf     PacketCounter_3,Same
;
PS_RCF_ReadnWrite1:
;
              goto      PS_ReceiveCommandFastEnd
;
PS_ReceiveCommandFastEnd:
;
              movlw     S_PS_ReceivePayLoad
              movwf     PacketState_3
;
              goto      PacketStateDispatcherEnd
;
PS_ReceivePayLoad:
;
              movf      PacketCounter_3,W
              btfss     ZeroFlag
              goto      PS_ReceivePayLoad1
;
              movlw     S_PS_ReceiveCheckSum
              movwf     PacketState_3
;
              goto      PacketStateDispatcher    ;Execute next state immediately
;
PS_ReceivePayLoad1:
;
              btfss     ESCape
              goto      PS_ReceivePayLoad2
;
              bcf       ESCape 
              movlw     '/'
              subwf     PacketCharacter_3,Same
;
              goto      PS_ReceivePayLoad3
;
PS_ReceivePayLoad2:
;
              movlw     '/'
              subwf     PacketCharacter_3,W
              btfss     ZeroFlag
              goto      PS_ReceivePayLoad3
;
              bsf       ESCape 
;
              goto      PS_ReceivePayLoadEnd
;
PS_ReceivePayLoad3:
;
              movlw     HIGH(LineBuffer_3)
              movwf     FSR0H
;
              movf      LineBufferPointer_3,W
              movwf     FSR0L
;
              movf      PacketCharacter_3,W
              movwi     FSR0++
;
              movf      FSR0L,W
              movwf     LineBufferPointer_3
;
              decfsz    PacketCounter_3,Same
              goto      PS_ReceivePayLoadEnd              
;
              movlw     S_PS_ReceiveCheckSum
              movwf     PacketState_3
;
PS_ReceivePayLoadEnd:
;
              goto      PacketStateDispatcherEnd
;
PS_ReceiveCheckSum:
;
              btfss     ESCape
              goto      PS_ReceiveCheckSum1
;
              bcf       ESCape 
              movlw     '/'
              subwf     PacketCharacter_3,Same
;
              goto      PS_ReceiveCheckSum2
;
PS_ReceiveCheckSum1:
;
              movlw     '/'
              subwf     PacketCharacter_3,W
              btfss     ZeroFlag
              goto      PS_ReceiveCheckSum2
;
              bsf       ESCape 
;
              goto      PS_ReceiveCheckSumEnd
;
PS_ReceiveCheckSum2:
;
              movlw     HIGH(LineBuffer_3)
              movwf     FSR0H
;
              movf      LineBufferPointer_3,W
              movwf     FSR0L
;
              movf      PacketCharacter_3,W
              movwf     INDF0
;
              movlw     0
              movwf     Checksum_A
;
              movlw     LOW(LineBuffer_3)
              subwf     LineBufferPointer_3,W
              movwf     PacketCounter_3
              decf      PacketCounter_3,Same
;
              movlw     HIGH(LineBuffer_3+1)
              movwf     FSR0H
              movlw     LOW(LineBuffer_3+1)
              movwf     FSR0L
;
PS_ReceiveAndVerifyCheckSum1:
;
              moviw     FSR0++
              addwf     Checksum_A,Same
;
              decfsz    PacketCounter_3,Same
              goto      PS_ReceiveAndVerifyCheckSum1
;
              comf      Checksum_A,W
              addlw     1
              subwf     INDF0,W
              btfss     ZeroFlag
              goto      RestartPacketState
;
              movlw     S_PS_ExecuteCommand 
              movwf     PacketState_3
;
              goto      PacketStateDispatcher    ;Execute next state immediately
;
PS_ReceiveCheckSumEnd:
;
              goto      PacketStateDispatcherEnd
;
PS_ExecuteCommand:
;
              bsf       DeviceCommunicated       
;
              movlw     HIGH(LineBuffer_3+1)     ;Point to the command
              movwf     FSR0H
              movlw     LOW(LineBuffer_3+1)
              movwf     FSR0L
;
              movf      INDF0,W                  ;Work out how many bytes there are 
              andlw     b'00001111'
              addlw     1
              movwf     PacketCounter_3
;
; Determine which command interpreter to use
;
PS_EC_Dispatcher:
;
              movlp     HIGH(PS_EC_DispatchTable) 
;
              swapf     INDF0,W
              andlw     b'00000011'
;
              addlw     LOW(PS_EC_DispatchTable)
              btfsc     CarryFlag
              incf      PCLATH,Same
              movwf     PCL
;
PS_EC_DispatchTable:
;
PS_EC_DT00:   goto      PS_EC_DS1307
PS_EC_DT01:   goto      PS_EC_InternalEE
PS_EC_DT02:   goto      PS_EC_Command
PS_EC_DT03:   goto      PS_EC_ExternalEE
;
PS_EC_DS1307:
;
              movlb     LATC>>7
              bsf       Power
;
              movlb     PacketCommand_3>>7
              movf      INDF0,W
              movwf     PacketCommand_3
;
  call I2C_Delay
;
              movlw     HIGH(LineBuffer_3+2)
              movwf     FSR0H
              movlw     LOW(LineBuffer_3+2)
              movwf     FSR0L
;
              call      I2C_Start  
              movlw     b'11010000'
              call      I2C_Tx            
              moviw     FSR0++
              movwf     DS1307_Address_3
              call      I2C_Tx             
;
              movlb     PacketCommand_3>>7
              btfsc     PacketCommand_3,6
              goto      PS_EC_DS1307_Read
;
PS_EC_DS1307_Write:
;
; Filter and mask problematic addresses in the clock chip
;
              moviw     FSR0++
              movwf     DS1307_Data_3
;
              movf      DS1307_Address_3,W
;
              xorlw     0
              btfss     ZeroFlag
              goto      PS_EC_DS1307_Write1
;
              movlw     b'01111111'
              andwf     DS1307_Data_3,Same       
;
              goto      PS_EC_DS1307_WriteX
;
PS_EC_DS1307_Write1:
;
              xorlw     7^0
              btfss     ZeroFlag
              goto      PS_EC_DS1307_Write2
;
              movlw     b'00010000'
              movwf     DS1307_Data_3
;
              goto      PS_EC_DS1307_WriteX
;
PS_EC_DS1307_Write2:
;
              goto      PS_EC_DS1307_WriteX
;
PS_EC_DS1307_WriteX:
;
              incf      DS1307_Address_3,Same
;
; Now we can safely write to the DS1307 without crashing the rain gauge
;
              movf      DS1307_Data_3,W 
              call      I2C_Tx
;
              movlb     PacketCommand_3>>7 
              decfsz    PacketCounter_3,Same
              goto      PS_EC_DS1307_Write
;
              call      I2C_Stop               
;
              call      Response_CommandExecuted
;
              bsf       DeviceSetClock
;
              goto      PS_ExecuteCommandEnd
;
PS_EC_DS1307_Read:
;
; Build response in the line buffer
;
              movlw      '#'
              movwf      LineBuffer_3+0
;
              decf       PacketCounter_3,W       ;RESPONSE low nibble
              iorlw      b'10010000'             ;RESPONSE high nibble
              movwf      LineBuffer_3+1
; 
              movlw      HIGH(LineBuffer_3+2)
              movwf      FSR0H
              movlw      LOW(LineBuffer_3+2)
              movwf      FSR0L
;
              call      I2C_Start  
              movlw     b'11010001'
              call      I2C_Tx
;
PS_EC_DS1307_Read1:
;
              bsf        AckTx
              call       I2C_Rx
              movwi      FSR0++
; 
              movlb      PacketCommand_3>>7
              decfsz     PacketCounter_3,Same
              goto       PS_EC_DS1307_Read1
;
              bcf        AckTx
              call       I2C_Rx
;
              call       I2C_Stop
;
              movlb      LATC>>7
              bcf        Power              
;
              call      I2C_Delay
;
              call       Response_AppendChecksum
;
              goto       PS_ExecuteCommandEnd
;
PS_EC_InternalEE:
;
              movlw     HIGH(LineBuffer_3+2)
              movwf     FSR0H
              movlw     LOW(LineBuffer_3+2)
              movwf     FSR0L
;
              btfss     INDF0,7
              goto      PS_EC_InternalEE_Variables
              goto      PS_EC_InternalEE_ScratchPad
;
PS_EC_InternalEE_Variables: 
;
              movlw     HIGH(ActiveBank_0)
              movwf     FSR1H
              movlw     LOW(ActiveBank_0)
              movwf     FSR1L
;
              moviw     FSR0++                  ;Fetch address of required variable
              addwf     FSR1L,Same              ;And offset to it  
              btfsc     CarryFlag
              incf      FSR1H,Same
;
              btfsc     LineBuffer_3+1,6
              goto      PS_EC_InternalEE_Var_Read
;
PS_EC_InternalEE_Var_Write:
;
              movlb     PacketCounter_3>>7
;
PS_EC_InternalEE_Var_Write1:
;
              movlw     NV_BoundaryLo
              subwf     FSR1L,W
              btfss     CarryFlag
              goto      PS_EC_InternalEE_Var_Write2
;
              movlw     NV_BoundaryHi
              subwf     FSR1L,W
              btfss     CarryFlag
              goto      PS_EC_InternalEE_Var_Write3
;
PS_EC_InternalEE_Var_Write2:
;
              moviw     FSR0++
              moviw     FSR1++
;
              goto      PS_EC_InternalEE_Var_Write4
;           
PS_EC_InternalEE_Var_Write3
;
              moviw     FSR0++
              movwi     FSR1++
;
PS_EC_InternalEE_Var_Write4:
;
              decfsz    PacketCounter_3,Same
              goto      PS_EC_InternalEE_Var_Write1
;
              PagedCall SaveSettings_Bulk_3
;
              call      Response_CommandExecuted
;
              goto       PS_ExecuteCommandEnd
;
PS_EC_InternalEE_Var_Read:
;
; Build response in the line buffer
;
              movlw      '#'
              movwf      LineBuffer_3+0
;
              decf       PacketCounter_3,W       ;RESPONSE low nibble
              iorlw      b'10010000'             ;RESPONSE high nibble
              movwf      LineBuffer_3+1
; 
              movlw      HIGH(LineBuffer_3+2)
              movwf      FSR0H
              movlw      LOW(LineBuffer_3+2)
              movwf      FSR0L
;
PS_EC_InternalEE_Var_Read1:
;
              moviw      FSR1++
              movwi      FSR0++
;
              decfsz     PacketCounter_3,Same
              goto       PS_EC_InternalEE_Var_Read1
;
              call       Response_AppendChecksum
;
              goto       PS_ExecuteCommandEnd
;
PS_EC_InternalEE_ScratchPad: 
;
              moviw     FSR0++                  ;Fetch scratchpad address
              movlb     EEADR>>7
              movwf     EEADR
;
              btfsc     LineBuffer_3+1,6
              goto      PS_EC_InternalEE_SP_Read
;
PS_EC_InternalEE_SP_Write:
;
              bcf       _EEPGD
              bcf       _EECFGS
              bsf       _EEWREN
;
PS_EC_InternalEE_SP_Write1:
;
; No paging required EEDATL and PacketCounter_3 are both in data page 3
;
              moviw     FSR0++
;
              movwf     EEDATL
;
              bcf       _GIE
              movlw     0x55
              movwf     EECON2
              movlw     0xAA
              movwf     EECON2
              bsf       _EEWR
              bsf       _GIE
;
PS_EC_InternalEE_SP_Write2:
;
              btfsc     _EEWR
              goto      PS_EC_InternalEE_SP_Write2
;
              incf      EEADR,Same
;
              decfsz    PacketCounter_3,Same
              goto      PS_EC_InternalEE_SP_Write1
;
              bcf       _EEWREN
;
              call      Response_CommandExecuted
;
              goto      PS_ExecuteCommandEnd
;
PS_EC_InternalEE_SP_Read:
;
; Build response in the line buffer
;
              movlw     '#'
              movwf     LineBuffer_3+0
;
              decf      PacketCounter_3,W        ;RESPONSE low nibble
              iorlw     b'10010000'              ;RESPONSE high nibble
              movwf     LineBuffer_3+1
; 
              movlw     HIGH(LineBuffer_3+2)
              movwf     FSR0H
              movlw     LOW(LineBuffer_3+2)
              movwf     FSR0L
;
              bcf       _EEPGD
              bcf       _EECFGS
;
PS_EC_InternalEE_SP_Read1:
;
; No paging required EEDATL and PacketCounter_3 are both in data page 3
;
              bsf       _EERD
              movf      EEDATL,W
;
              movwi     FSR0++
;
              incf      EEADRL,Same
;
              decfsz    PacketCounter_3,Same
              goto      PS_EC_InternalEE_SP_Read1
;
              call      Response_AppendChecksum
;
              goto      PS_ExecuteCommandEnd
;
PS_EC_Command:
;
; Currently the ReadnWrite is ignored, it could be concatenated with the lower 4 bits to provide 32 commands instead of 16
;
PS_EC_CommandDispatcher:
;
              movlp     HIGH(PS_EC_CommandDispatchTable) 
              movf      INDF0,W
              andlw     b'00001111'
;
              addlw     LOW(PS_EC_CommandDispatchTable)
              btfsc     CarryFlag
              incf      PCLATH,Same
              movwf     PCL
;
PS_EC_CommandDispatchTable:
;
PS_EC_CDT00:  goto      PS_EC_NotImplemented
PS_EC_CDT01:  goto      PS_EC_NotImplemented
PS_EC_CDT02:  goto      PS_EC_Reserved           ;Reserved START (# or $)
PS_EC_CDT03:  goto      PS_EC_NotImplemented
PS_EC_CDT04:  goto      PS_EC_NotImplemented
PS_EC_CDT05:  goto      PS_EC_Details
PS_EC_CDT06:  goto      PS_EC_NotImplemented
PS_EC_CDT07:  goto      PS_EC_NotImplemented
PS_EC_CDT08:  goto      PS_EC_DownloadFirstBlock ;ResetDownloadPointer
PS_EC_CDT09:  goto      PS_EC_DownloadNextBlock 
PS_EC_CDT10:  goto      PS_EC_ResetLoggingPointer
PS_EC_CDT11:  goto      PS_EC_NotImplemented
PS_EC_CDT12:  goto      PS_EC_NotImplemented
PS_EC_CDT13:  goto      PS_EC_NotImplemented
PS_EC_CDT14:  goto      PS_EC_NotImplemented
PS_EC_CDT15:  goto      PS_EC_NotImplemented
;
PS_EC_Reserved:
;
; Place for reserved commands to go to
;
              goto       PS_ExecuteCommandEnd
;
PS_EC_NotImplemented:
;
; Place for unimplemented commands to go to
;
              goto       PS_ExecuteCommandEnd
;
PS_EC_DownloadFirstBlock:
;
 ;             movlw      0
 ;             movwf      DownloadPointerLo,Banked
 ;             movwf      DownloadPointerHi,Banked
 ;             movwf      DownloadPointerUp,Banked
;
 ;             bsf        SendBlockToApp
;
              goto       PS_ExecuteCommandEnd
;
PS_EC_DownloadNextBlock:
;
  ;            movlw      32
  ;            addwf      DownloadPointerLo,Same,Banked
  ;            movlw      0 
   ;           addwfc     DownloadPointerHi,Same,Banked
  ;            movlw      0
  ;            addwfc     DownloadPointerUp,Same,Banked
;
  ;            bsf        SendBlockToApp
;
              goto       PS_ExecuteCommandEnd
;
PS_EC_ResetLoggingPointer:
;
  ;            bsf        ResetLoggingPointer
;
              goto       PS_ExecuteCommandEnd

PS_EC_Details:
;
              call       Response_CommandExecuted
;
              goto       PS_ExecuteCommandEnd
;
PS_EC_ExternalEE:
;
              movlb      PacketCommand_3>>7
              moviw      FSR0++
              movwf      PacketCommand_3
; 
              movlb      EEAdrs>>7
              moviw      FSR0++
              movwf      EEAdrsHH 
              moviw      FSR0++
              movwf      EEAdrsH 
              moviw      FSR0++
              movwf      EEAdrs 
;
              movlb     PacketCommand_3>>7
              btfsc     PacketCommand_3,6
              goto      PS_EC_ExternalEE_Read
;
PS_EC_ExternalEE_Write:
;
              movlb     LATC>>7
              bsf       Power
;
 call I2C_Delay
;
              call      I2C_Start
              movlb     EEAdrs>>7
              rlf       EEAdrsHH,W
              andlw     b'00001110'
              iorlw     b'10100000'
              call      I2C_Tx        
              movf      EEAdrsH,W
              call      I2C_Tx
              movf      EEAdrs,W
              call      I2C_Tx
;
PS_EC_ExternalEE_Write1:
;
              moviw      FSR0++ 
              call      I2C_Tx
;
              movlb      PacketCounter_3>>7
              decfsz     PacketCounter_3,Same
              goto       PS_EC_ExternalEE_Write1
;      
              call       I2C_Stop
;    
              PagedCall Delay5msec_2
;
              movlb     LATC>>7
              bcf       Power
;
              call      I2C_Delay
;
              call       Response_CommandExecuted 
;
              goto       PS_ExecuteCommandEnd
;
PS_EC_ExternalEE_Read:
;
; Build response in the line buffer
;
              movlb      LineBuffer_3>>7
              movlw      '#'
              movwf      LineBuffer_3+0
;
              decf       PacketCounter_3,W       ;RESPONSE low nibble
              iorlw      b'10010000'             ;RESPONSE high nibble
              movwf      LineBuffer_3+1
; 
              movlw      HIGH(LineBuffer_3+2)
              movwf      FSR0H
              movlw      LOW(LineBuffer_3+2)
              movwf      FSR0L
;
              call       OpenExternalEEPROMforReading
;
PS_EC_ExternalEE_Read1:
;
              call       ReadExternalEEPROM
              movwi      FSR0++ 
;
              movlb      PacketCounter_3>>7
              decfsz     PacketCounter_3,Same
              goto       PS_EC_ExternalEE_Read1
;
              call       CloseExternalEEPROMforReading
;
              call       Response_AppendChecksum
;
              goto       PS_ExecuteCommandEnd
;
PS_ExecuteCommandEnd:
;
              goto      RestartPacketState
;
RestartPacketState:
;
              movlb     PacketState_3>>7
              clrf      PacketState_3
;
              call      FlushSerialReceiveBuffer1
;
              goto      PacketStateDispatcherEnd
;
PacketStateDispatcherEnd:
;
              call      CheckByteSerialBuffer1
              btfsc     CarryFlag
              goto      ProcessSerialInput
;
              return


;
Response_CommandExecuted:
;
              movlw     '#'
              call      WriteByteSerialBuffer1
              movlw     b'10001010'
              call      WriteByteSerialBuffer1
              movlw     0x76
              call      WriteByteSerialBuffer1
;
              return
;
Response_AppendChecksum:
;
              movlw     HIGH(LineBuffer_3+1)
              movwf     FSR0H
              movlw     LOW(LineBuffer_3+1) 
              movwf     FSR0L
;
              movlb     PacketCounter_3>>7
              clrf      PacketCounter_3   ;Start with 0 bytes
;
              swapf     LineBuffer_3+1,W  ;See what the multiplier is 
              andlw     b'00000111'
              btfsc     ZeroFlag
              goto      Response_AC_1          ;It is 0, so go 
;
              movwf     LineBufferPointer_3
; 
              movf      LineBuffer_3+1,W
              andlw     b'00001111'
              addlw     1
;
Response_AC_Multiply:
;
              addwf     PacketCounter_3,Same
;
              decfsz    LineBufferPointer_3,Same              
              goto      Response_AC_Multiply  
;
Response_AC_1:
;
              addlw     1                      ;Add the RESPONSE byte
              movwf     PacketCounter_3
;
              movlw     0
              movwf     Checksum_A
;
Response_AC_CalculateChecksum:
;
              moviw     FSR0++
              addwf     Checksum_A,Same
;
              decfsz    PacketCounter_3,Same
              goto      Response_AC_CalculateChecksum
;
              comf      Checksum_A,W
              addlw     1
              movwi     FSR0++
;
              movf      FSR0L,W
              movwf     LineBufferPointer_3
              movlw     HIGH(LineBuffer_3)
              movwf     FSR1H
              movlw     LOW(LineBuffer_3)
              movwf     FSR1L
;
              bsf       FirstPass
              bcf       ESCape
;
Response_AC_Transmit:
;
              btfss     ESCape
              goto      Response_AC_Transmit1
;
              bcf       ESCape
              moviw     FSR1++
              addlw     '/'              
;
              goto      Response_AC_TransmitCheck
;
Response_AC_Transmit1:
;
              btfsc     FirstPass
              goto      Response_AC_Transmit3
;
              movlw     '#'
              subwf     INDF1,W
              btfsc     ZeroFlag
              goto      Response_AC_Transmit2
              movlw     '$'
              subwf     INDF1,W
              btfsc     ZeroFlag
              goto      Response_AC_Transmit2
              movlw     '/'
              subwf     INDF1,W
              btfss     ZeroFlag
              goto      Response_AC_Transmit3
 ;
Response_AC_Transmit2:
;
              bsf       ESCape
              movlw     '/'
              call      WriteByteSerialBuffer1
;
              goto      Response_AC_Transmit
;
Response_AC_Transmit3:
;
              bcf       FirstPass
              moviw     FSR1++
;
Response_AC_TransmitCheck:
;
              call      WriteByteSerialBuffer1
;
              movf      FSR1L,W
              movlb     LineBufferPointer_3>>7
              subwf     LineBufferPointer_3,W
              btfss     ZeroFlag
              goto      Response_AC_Transmit
;
Response_AC_Transmit_End:
;
              return
;
OpenExternalEEPROMforReading:
;
              movlb     LATC>>7
              bsf       Power
;
 call I2C_Delay
;
              call      I2C_Start
              movlb     EEAdrs>>7
              rlf       EEAdrsHH,W
              andlw     b'00001110'
              iorlw     b'10100000'
              call      I2C_Tx        
              movf      EEAdrsH,W
              call      I2C_Tx
              movf      EEAdrs,W
              call      I2C_Tx
              call      I2C_Start
              movlw     b'10101001'
              call      I2C_Tx        
;
              return
;
ReadExternalEEPROM:
;
              bsf       AckTx
              call      I2C_Rx
;
              return
;
CloseExternalEEPROMforReading:
;
              bcf       AckTx
              call      I2C_Rx
              bsf       AckTx
;
              call      I2C_Stop 
;
              movlb     LATC>>7
              bcf       Power
;
              call      I2C_Delay
;
              return
;
              org       0x0800 ;Program memory page 1
;
Event_X_WriteEEPROM_1:
;
              movlp     HIGH(WriteEEPROMDispatchTable)
;
              movf      EventState_0,W
              andlw     b'00000111'
              addlw     LOW(WriteEEPROMDispatchTable)
              btfsc     CarryFlag
              incf      PCLATH,Same 
              movwf     PCL

WriteEEPROMDispatchTable:
;
WEDT00:       goto      Event_X_WriteEEPROM_CheckForData
WEDT01:       goto      Event_X_WriteEEPROM_PowerOn
WEDT02:       goto      Event_X_WriteEEPROM_WaitPowerOn
WEDT03:       goto      Event_X_WriteEEPROM_WritePage
WEDT04:       goto      Event_X_WriteEEPROM_WaitWrite
WEDT05:       nop
WEDT06:       nop
WEDT07:       nop
;
              PagedCall RemoveEventFromQueue
;
              LiveDebug LiveDebug_UnknownState
;
              goto      Event_X_WriteEEPROM_End
;
;*************************************************
;
Event_X_WriteEEPROM_CheckForData:
;
              movlb     EventState_0>>7          ;Assume this event hasn't been pre-empted
              incf      EventState_0,Same
;
              movlb     EEPROM_Buffered_0>>7
              movlw     EEPROM_WritePageSize
              subwf     EEPROM_Buffered_0,W
              btfsc     CarryFlag
              goto      Event_X_WriteEEPROM_CFD_End

              PagedCall RemoveEventFromQueue              
;
Event_X_WriteEEPROM_CFD_End:
;
              goto      Event_X_WriteEEPROM_End
;
Event_X_WriteEEPROM_PowerOn:
;
              movlb     LATC>>7
              bcf       StorePower
              btfsc     Power
              bsf       StorePower
              bsf       Power
;
              movlb     T1CON>>7
              clrf      T1CON
              movlw     HIGH(65536-32) ;Give the EEPROM 1msec to wake up
              movwf     TMR1H
              movlw     LOW(65536-32)
              movwf     TMR1L
              bcf       _TMR1IF
              movlw     b'00000000'
              movwf     T1GCON
              movlw     b'01000001'
              movwf     T1CON
;
              movlb     EventState_0>>7
              incf      EventState_0,Same
;
              goto      Event_X_WriteEEPROM_End
;
Event_X_WriteEEPROM_WaitPowerOn:
;
              movlb     PIR1>>7
              btfss     _TMR1IF
              goto      Event_X_WriteEEPROM_WaitPowerOn_End
;
              movlb     EventState_0>>7
              incf      EventState_0,Same
;
Event_X_WriteEEPROM_WaitPowerOn_End:
;
              goto      Event_X_WriteEEPROM_End
;
Event_X_WriteEEPROM_WritePage:
;
; Validate the write pointer, in case the app has not left it on a page boundary or it has been set out of bounds or it just got stupid!
;
              movlw     EEPROM_WritePageSize-1
              andwf     LogWritePointer_0,W
              btfsc     ZeroFlag
              goto      Event_X_WriteEEPROM_SkipAlignment
;
; Move forward to the next page boundary
; - There are risks involved in relation to the read pointer, but it is already broken anyway!
;
              movlw     EEPROM_WritePageSize
              addwf     LogWritePointer_0,Same
              movlw     0
              addwfc    LogWritePointer_0H,Same
              movlw     0
              addwfc    LogWritePointer_0HH,Same
              movlw     EEPROM_WritePageSize-1
              xorlw     b'11111111'
              andwf     LogWritePointer_0,Same
;
              bsf       ExtEE_PageAligned
;
Event_X_WriteEEPROM_SkipAlignment:
;
              movlw     4
              subwf     LogWritePointer_0HH,W
              btfss     CarryFlag
              goto      Event_X_WriteEEPROM_WriteOutOfBounds
;
              movlw     6
              subwf     LogWritePointer_0HH,W
              btfss     CarryFlag
              goto      Event_X_WriteEEPROM_WriteInBounds
;
Event_X_WriteEEPROM_WriteOutOfBounds:
;
              movlw     0x00
              movwf     LogWritePointer_0
              movwf     LogReadPointer_0
;
              movlw     0x00
              movwf     LogWritePointer_0H
              movwf     LogReadPointer_0H
;
              movlw     0x04
              movwf     LogWritePointer_0HH
              movwf     LogReadPointer_0HH
;
              bsf       ExtEE_WritePointerOutOfBounds
;
Event_X_WriteEEPROM_WriteInBounds:
;
; Validate the read pointer, in case the app has left it out of bounds
; - It is not a requirement that it must be page aligned
;
              movlw     4
              subwf     LogReadPointer_0HH,W
              btfss     CarryFlag
              goto      Event_X_WriteEEPROM_ReadOutOfBounds
;
              movlw     6
              subwf     LogReadPointer_0HH,W
              btfss     CarryFlag
              goto      Event_X_WriteEEPROM_ReadInBounds
;
Event_X_WriteEEPROM_ReadOutOfBounds:
;
              movf      LogWritePointer_0,W
              movwf     LogReadPointer_0
              movf      LogWritePointer_0H,W
              movwf     LogReadPointer_0H
              movf      LogWritePointer_0HH,W
              movwf     LogReadPointer_0HH
;
              bsf       ExtEE_ReadPointerOutOfBounds
;
Event_X_WriteEEPROM_ReadInBounds:
;
; Check that the WritePointer won't overtake the ReadPointer
; - If the write pointer >= read pointer we are good
;
              movf      LogWritePointer_0,W
              subwf     LogReadPointer_0,W
              movwf     CalculatorX0
              movf      LogWritePointer_0H,W
              subwfb    LogReadPointer_0H,W
              movwf     CalculatorX1      
              movf      LogWritePointer_0HH,W
              subwfb    LogReadPointer_0HH,W
              movwf     CalculatorX2
              btfss     CarryFlag
              goto      Event_X_WriteEEPROM_PointersVerified 
              btfsc     ZeroFlag
              goto      Event_X_WriteEEPROM_PointersVerified 
;
              comf      CalculatorX0,Same
              comf      CalculatorX1,Same
              comf      CalculatorX2,Same
              movlw     1
              addwf     CalculatorX0,Same
              movlw     0
              addwfc    CalculatorX1,Same
              movlw     0
              addwfc    CalculatorX2,Same
;
              movlw     EEPROM_WritePageSize
              subwf     CalculatorX0,W
              btfsc     CarryFlag
              goto      Event_X_WriteEEPROM_PointersVerified 
              movf      CalculatorX1,W
              btfss     ZeroFlag
              goto      Event_X_WriteEEPROM_PointersVerified 
              movf      CalculatorX2,W
              btfss     ZeroFlag
              goto      Event_X_WriteEEPROM_PointersVerified 
;
; Advance the read pointer to make space
; - We don't have the computing power here, to do this intelligently, so the app is going to have figure things out!
; - Let's make 256 bytes of space for now, we can always make more later on
;
              bsf       ExtEE_MadeLoggingSpace
;               
              movlw     1
              addwf     LogReadPointer_0H,Same
              movlw     0
              addwfc    LogReadPointer_0HH,Same
;
              movlw     6
              subwf     LogReadPointer_0HH,W
              btfss     CarryFlag
              goto      Event_X_WriteEEPROM_PointersVerified 
;
              movlw     0x00
              movwf     LogReadPointer_0
;
              movlw     0x01
              movwf     LogReadPointer_0H
;
              movlw     0x04
              movwf     LogReadPointer_0HH
;             
Event_X_WriteEEPROM_PointersVerified:
;
              PagedCall I2C_Start
              rlf       LogWritePointer_0HH,w
              andlw     b'00001110'
              iorlw     b'10100000'
              PagedCall I2C_Tx        
              movf      LogWritePointer_0H,W
              PagedCall I2C_Tx
              movf      LogWritePointer_0,W
              PagedCall I2C_Tx
;
              movlw     EEPROM_WritePageSize
              movwf     ScratchPad0_A
;
Event_X_WriteEEPROM_WritePage1:
;
              PagedCall EEPROM_ReadBuffer
              PagedCall I2C_Tx
;
              decfsz    ScratchPad0_A
              goto      Event_X_WriteEEPROM_WritePage1
;
              PagedCall I2C_Stop
;
              movlb     T1CON>>7
              clrf      T1CON
              movlw     HIGH(65536-200) ;Give the EEPROM 6.4msec to write the data away
              movwf     TMR1H
              movlw     LOW(65536-200)
              movwf     TMR1L
              bcf       _TMR1IF
              movlw     b'00000000'
              movwf     T1GCON
              movlw     b'01000001'
              movwf     T1CON
;
              movlb     EventState_0>>7
              incf      EventState_0,Same
;
              goto      Event_X_WriteEEPROM_End
;
Event_X_WriteEEPROM_WaitWrite:
;
              movlb     PIR1>>7
              btfss     _TMR1IF
              goto      Event_X_WriteEEPROM_WaitWrite_End
;
              movlw     EEPROM_WritePageSize
              addwf     LogWritePointer_0,Same
              movlw     0
              addwfc    LogWritePointer_0H,Same
              movlw     0
              addwfc    LogWritePointer_0HH,Same
;
              movlw     6
              subwf     LogWritePointer_0HH,W
              btfss     CarryFlag
              goto      Event_X_WriteEEPROM_SkipWrapAround
;
              movlw     0x00
              movwf     LogWritePointer_0
              movlw     0x00
              movwf     LogWritePointer_0H
              movlw     0x04
              movwf     LogWritePointer_0HH
;
              movf      LogWritePointer_0,W
              subwf     LogReadPointer_0,W
              movf      LogWritePointer_0H,W
              subwfb    LogReadPointer_0H,W
              movf      LogWritePointer_0HH,W
              subwfb    LogReadPointer_0HH,W
              btfss     ZeroFlag
              goto      Event_X_WriteEEPROM_SkipMakeLoggingSpace
;
              movlw     0x00
              movwf     LogReadPointer_0
;
              movlw     0x01
              movwf     LogReadPointer_0H
;
              movlw     0x04
              movwf     LogReadPointer_0HH
;
              bsf       ExtEE_MadeLoggingSpace
;             
Event_X_WriteEEPROM_SkipMakeLoggingSpace:
;
Event_X_WriteEEPROM_SkipWrapAround:
;
              movlb     EEPROM_Buffered_0>>7
              movlw     EEPROM_WritePageSize
              subwf     EEPROM_Buffered_0,W
              btfsc     CarryFlag
              goto      Event_X_WriteEEPROM_WaitWrite1
;
              movlb     LATC>>7
              btfss     StorePower
              bcf       Power
;
              PagedCall I2C_Delay
;
              PagedCall RemoveEventFromQueue              
;
              goto      Event_X_WriteEEPROM_WaitWrite_End 
;
Event_X_WriteEEPROM_WaitWrite1:
;
              movlb     EventState_0>>7
              movlw     3                        ;To save time keep the EEPROM powered up and write the next page
              movwf     EventState_0     
;
Event_X_WriteEEPROM_WaitWrite_End:
;
              goto      Event_X_WriteEEPROM_End
;
Event_X_WriteEEPROM_End:
;
              return
;
Event_X_RefreshNV_1:
;
              movlp     HIGH(RefreshNVDispatchTable)
;
              movf      EventState_0,W
              andlw     b'00000011'
              addlw     LOW(RefreshNVDispatchTable)
              btfsc     CarryFlag
              incf      PCLATH,Same 
              movwf     PCL

RefreshNVDispatchTable:
;
RNVDT00:      goto      Event_X_RefreshNV_IdleCheck
RNVDT01:      goto      Event_X_RefreshNV_Write
RNVDT02:      goto      Event_X_RefreshNV_Complete
RNVDT03:      nop
;
              PagedCall RemoveEventFromQueue
;
              LiveDebug LiveDebug_UnknownState
;
              goto      Event_X_RefreshNV_End
;
;*************************************************
;
Event_X_RefreshNV_IdleCheck:
;
              movlb     EEADRL>>7
              btfsc     _EEWR
              goto      Event_X_RefreshNV_IdleCheck_End
;
              movlb     EventState_0>>7          
              incf      EventState_0,Same
;
Event_X_RefreshNV_IdleCheck_End:
;
              goto      Event_X_RefreshNV_End
;
Event_X_RefreshNV_Write:
;
              PagedCall RemoveEventFromQueue     ;We need to get to the address and the data
              PagedCall RemoveEventFromQueue     ;This is the address
              movlb     EEADRL>>7
              movwf     EEADRL
              PagedCall ReadEventQueue           ;This is the data
              PagedCall WriteInternalEEPROM
;
              movlb     EventState_0>>7
              movlw     2                        ;RemoveEventFromQueue clears EventState_0, but we want to go to the next state, so load it with 2
              movwf     EventState_0
;
              movlw     Event_RefreshNV          ;Now write the event in place of the data. 
                                                 ;If we remove the event and re-write it other events may already be queued and cause problems
              PagedCall PreemptEventsInQueue
;
              goto      Event_X_RefreshNV_End
;
Event_X_RefreshNV_Complete:
;
              movlb     EEADRL>>7
              btfsc     _EEWR
              goto      Event_X_RefreshNV_Complete_End
;
              PagedCall RemoveEventFromQueue
; 
              bsf       BankSwitchRequired
;
Event_X_RefreshNV_Complete_End:
;
              goto      Event_X_RefreshNV_End

Event_X_RefreshNV_End:
;
              return
;
Event_X_QueueDailyLog_1:
;
              movlp     HIGH(QueueDailyLogDispatchTable)
;
              movf      EventState_0,W
              andlw     b'00001111'
              addlw     LOW(QueueDailyLogDispatchTable)
              btfsc     CarryFlag
              incf      PCLATH,Same 
              movwf     PCL
;
QueueDailyLogDispatchTable:
;
QDLDT00:      goto      Event_X_QueueDailyLog_PowerOn
QDLDT01:      goto      Event_X_QueueDailyLog_WaitPowerOn
QDLDT02:      goto      Event_X_QueueDailyLog_ReadTimeAndDate1   
QDLDT03:      goto      Event_X_QueueDailyLog_ReadTAndD2
QDLDT04:      goto      Event_X_QueueDailyLog_LogHiLoEvent
QDLDT05:      goto      Event_X_QueueDailyLog_SecondsH
QDLDT06:      goto      Event_X_QueueDailyLog_SecondsM
QDLDT07:      goto      Event_X_QueueDailyLog_SecondsS
QDLDT08:      goto      Event_X_QueueDailyLog_ResetHiLo
QDLDT09:      nop
QDLDT10:      nop
QDLDT11:      nop
QDLDT12:      nop
QDLDT13:      nop
QDLDT14:      nop
QDLDT15:      nop
;
              PagedCall RemoveEventFromQueue
;
              LiveDebug LiveDebug_UnknownState
;
              goto      Event_X_QueueDailyLog_End
;
Event_X_QueueDailyLog_PowerOn:
;
              movlb     LATC>>7
              bcf       StorePower
              btfsc     Power
              bsf       StorePower
              bsf       Power
;
              movlb     T1CON>>7
              clrf      T1CON
              movlw     HIGH(65536-32) ;Give the EEPROM 1msec to wake up
              movwf     TMR1H
              movlw     LOW(65536-32)
              movwf     TMR1L
              bcf       _TMR1IF
              movlw     b'00000000'
              movwf     T1GCON
              movlw     b'01000001'
              movwf     T1CON
;
              movlb     EventState_0>>7
              incf      EventState_0,Same
;
              goto      Event_X_QueueDailyLog_End
;
Event_X_QueueDailyLog_WaitPowerOn:
;
              movlb     PIR1>>7
              btfss     _TMR1IF
              goto      Event_X_QueueDailyLog_WPO_End
;
              movlb     EventState_0>>7
              incf      EventState_0,Same
;
Event_X_QueueDailyLog_WPO_End:
;
              goto      Event_X_QueueDailyLog_End
;
Event_X_QueueDailyLog_ReadTimeAndDate1:
;
              PagedCall I2C_Start               
              movlw     b'11010000'
              PagedCall I2C_Tx        
              movlw     b'00000000'              ;Read from the Seconds register
              PagedCall I2C_Tx
              PagedCall I2C_Start
              movlw     b'11010001'
              PagedCall I2C_Tx
;
              bsf       AckTx
              PagedCall I2C_Rx                   ;Seconds
              movlb     Seconds_2>>7
              movwf     Seconds_2
;
; Allow other events to queue   
;
              movlb     EventState_0>>7
              incf      EventState_0,Same
;
              goto      Event_X_QueueDailyLog_End
;
Event_X_QueueDailyLog_ReadTAndD2:
;
; Carry on reading from the Minutes
;
              movlw     HIGH(Minutes_2)
              movwf     FSR0H
              movlw     LOW(Minutes_2)
              movwf     FSR0L
;
              PagedCall I2C_Rx                   ;Minutes
              movwi     FSR0++
              PagedCall I2C_Rx                   ;Hours
              movwi     FSR0++
              PagedCall I2C_Rx                   ;DayOfWeek
              movwi     FSR0++
              PagedCall I2C_Rx                   ;Date
              movwi     FSR0++
              PagedCall I2C_Rx                   ;Month
              movwi     FSR0++
              bcf       AckTx
              PagedCall I2C_Rx                   ;Year
              bsf       AckTx
              movwi     FSR0++
              PagedCall I2C_Stop
;
              movlb     EventState_0>>7
              incf      EventState_0,Same
;
              goto      Event_X_QueueDailyLog_End
;
Event_X_QueueDailyLog_LogHiLoEvent:
;
              movlb     HiLoDetail1_2>>7
              movlw     0xFA
              movwf     HiLoDetail1_2
              movlw     0xCE
              movwf     HiLoDetail2_2
;
              PagedCall LogHiLoEvent_2
;
              movlb     EventState_0>>7
              incf      EventState_0,Same
;
              goto      Event_X_QueueDailyLog_End
;
Event_X_QueueDailyLog_SecondsH:
;
              PagedCall CalculateSecondsOffset_Hours_2
;
              movlb     EventState_0>>7
              incf      EventState_0,Same
;
              goto      Event_X_QueueDailyLog_End
;
Event_X_QueueDailyLog_SecondsM:
;
              PagedCall CalculateSecondsOffset_Minutes_2
;
              movlb     EventState_0>>7
              incf      EventState_0,Same
;
              goto      Event_X_QueueDailyLog_End
;
Event_X_QueueDailyLog_SecondsS:
;
              PagedCall CalculateSecondsOffset_Seconds_2
;
              movlb     EventState_0>>7
              incf      EventState_0,Same
;
              goto      Event_X_QueueDailyLog_End
;
Event_X_QueueDailyLog_ResetHiLo
;
; Reset the Highs and Lows
;
              movlb     HumidityLo_0>>7
              movlw     0xFF
              movwf     HumidityLo_0
              movwf     TemperatureLo_0
              movwf     TemperatureLo_0H 
;
              movlw     0x00
              movwf     HumidityHi_0
              movwf     TemperatureHi_0
              movwf     TemperatureHi_0H 
;
; And then populate them with the current temperature and humidity
;
              movlw     Event_DetermineHiLo
              PagedCall WriteEventToQueue
;
              movlb     LATC>>7   
              btfss     StorePower
              bcf       Power
;
              PagedCall I2C_Delay
;
              PagedCall RemoveEventFromQueue              
;
              movlw     Event_SampleBatteryVoltage
              PagedCall WriteEventToQueue
;
              goto      Event_X_QueueDailyLog_End
;
Event_X_QueueDailyLog_End:
;
              return 
;
Event_X_SampleBatteryVoltage_1:
;
              movlp     HIGH(SampleBatteryVoltageDispatchTable)
;
              movf      EventState_0,W
              andlw     b'00000011'
              addlw     LOW(SampleBatteryVoltageDispatchTable)
              btfsc     CarryFlag
              incf      PCLATH,Same 
              movwf     PCL
;
SampleBatteryVoltageDispatchTable:
;
SBVDT00:      goto      Event_X_SampleBatteryVoltage_PowerOn
SBVDT01:      goto      Event_X_SampleBatteryVoltage_Charge
SBVDT02:      goto      Event_X_SampleBatteryVoltage_Sample
SBVDT03:      goto      Event_X_SampleBatteryVoltage_Discharge
;
              PagedCall RemoveEventFromQueue
;
              LiveDebug LiveDebug_UnknownState
;
              goto      Event_X_SampleBatteryVoltage_End
;
Event_X_SampleBatteryVoltage_PowerOn
;
; When we get here we are assuming there is no device connected, because the rain gauge side of the program is still running and not the comms side!
; - But a device could be waiting for attention, but the chances are very low              
;   - If it is and we abort this sample, then we try again tomorrow :-)
;
              movlw     LATC>>7
              bsf       TxPin                    ;Power up the CH340 to put the battery voltage onto CheckUSBAlert
;
              movlb     T1CON>>7
              clrf      T1CON
              movlw     HIGH(65536-3125) ;Give the big USB power caps a chance to charge up - looks like 100msec is enough
              movwf     TMR1H
              movlw     LOW(65536-3125)
              movwf     TMR1L
              bcf       _TMR1IF
              movlw     b'00000000'
              movwf     T1GCON
              movlw     b'01000001'
              movwf     T1CON
;
              movlb     EventState_0>>7
              incf      EventState_0,Same
;
              goto      Event_X_SampleBatteryVoltage_End
;
Event_X_SampleBatteryVoltage_Charge:
;
              movlb     PIR1>>7
              btfss     _TMR1IF
              goto      Event_X_SBV_Charge_End
;
              movlb     ADCON0>>7
              movlw     Track_USBAlert
              movwf     ADCON0
;
              movlb     FVRCON>>7
              movlw     b'10000001'
              movwf     FVRCON
;
Event_X_SBV_Charge_FVROn:
;
              btfss     FVRCON,6
              goto      Event_X_SBV_Charge_FVROn
;
              movlb     EventState_0>>7
              incf      EventState_0,Same
;
Event_X_SBV_Charge_End:
;
              goto      Event_X_SampleBatteryVoltage_End
;
Event_X_SampleBatteryVoltage_Sample:
;
              movlb     ADCON0>>7
              bsf       _Go
;
Event_X_SBV_Sample_1:
;
              btfsc     _Go
              goto      Event_X_SBV_Sample_1
;
              clrf      ADCON0
;
              movlb     FVRCON>>7
              movlw     b'00000000'
              movwf     FVRCON
;
              movlw     LATC>>7
              bcf       TxPin                    ;Power down the CH340 to save battery power
;
; See if a device managed to sneak into the picture
;
              movlb     ADCON0>>7
              movlw     LOW(USBAlert_Threshold)
              subwf     ADRESL,W
              movlw     HIGH(USBAlert_Threshold)
              subwfb    ADRESH,W
;
              btfsc     CarryFlag
              goto      Event_X_SBV_Sample_SkipCalculation
;
              movf      ADRESL,W
              movlb     0
              movwf     CalculatorX0
              movlb     ADCON0>>7
              movf      ADRESH,W
              movlb     0
              movwf     CalculatorX1
;
              movlb     0
;
              bcf       CarryFlag
              rrf       CalculatorX1,Same
              rrf       CalculatorX0,Same
;
              movlw     LOW(180)
              subwf     CalculatorX0,Same
              movlw     HIGH(180)
              subwfb    CalculatorX1,Same
;
              btfss     CarryFlag
              goto      Event_X_SBV_Sample_SkipCalculation
;
              movf      CalculatorX1,W
              movlw     0xFF
              btfss     ZeroFlag
              movwf     CalculatorX0
;
              movf      CalculatorX0,W
              movwf     BatteryVoltage_0         ;This is a non-volatile variable if it changes it will automatically be written to EEPROM
;            
Event_X_SBV_Sample_SkipCalculation:
;
              movlb     T1CON>>7
              clrf      T1CON
              movlw     HIGH(65536-3125) ;Give the big USB power caps a chance to discharge - looks like 100msec is enough
              movwf     TMR1H
              movlw     LOW(65536-3125)
              movwf     TMR1L
              bcf       _TMR1IF
              movlw     b'00000000'
              movwf     T1GCON
              movlw     b'01000001'
              movwf     T1CON
;
              movlb     EventState_0>>7
              incf      EventState_0,Same
;
              goto      Event_X_SampleBatteryVoltage_End
;
Event_X_SampleBatteryVoltage_Discharge:
;
              movlb     PIR1>>7
              btfss     _TMR1IF
              goto      Event_X_SBV_Discharge_End
;
              PagedCall RemoveEventFromQueue              
;
              goto      Event_X_SBV_Discharge_End
;
Event_X_SBV_Discharge_End:
;
              goto      Event_X_SampleBatteryVoltage_End
;
Event_X_SampleBatteryVoltage_End:
;
              return
;
              org       0x1000 ;Program memory page 2
;
Delay5msec_2:
;
              btfss     HighSpeed
              goto      Delay5msecEnd ;No code yet for a 5msec delay when running slowly
;
              movlw      20
              movwf      Delay100msA
;
              movlw      0 
              movwf      Delay100msB
;
D5msA:
;
              decfsz     Delay100msB,Same
              goto       D5msA
;
              decfsz     Delay100msA,Same
              goto       D5msA             
;
Delay5msecEnd:
;
              return
;
;*************************************************
;
ReadADC_2: ;Switch ADC and FVR on
           ;Do conversion
           ;Switch ADC and FVR off
           ;Point to memory page with result
;
;*************************************************
;
              movlb     ADCON0>>7
              movwf     ADCON0
;
              movlb     FVRCON>>7
              movlw     b'10000001'
              movwf     FVRCON
;
ReadADC_2A:
;
              btfss     FVRCON,6
              goto      ReadADC_2A
;
              PagedCall I2C_Delay
;
              movlb     ADCON0>>7
              bsf       _Go
;
ReadADC_2B:
;
              btfsc     _Go
              goto      ReadADC_2B
;
              clrf      ADCON0
;
              movlb     FVRCON>>7
              movlw     b'00000000'
              movwf     FVRCON
;
              movlb     ADCON0>>7
;
              return
;
;**************************************
;
; Receive and buffer serial byte from Serial Port 1  
;
;**************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
RxByteSerialPort1_2:
;
              bcf       Boolean_Interrupt        ;Assume no error
;
              movlb     RCREG>>7                 ;Point to the page with the serial port registers 
;
              btfss     _OERR                    ;IF !OVER RUN
              goto      RxByteSerialPort1C       ;THEN check for FRAMING
              bsf       Boolean_Interrupt        ;ELSE flag error and
RxByteSerialPort1A:                              ;     recover from OVER RUN
              bcf       _CREN                    ;     - CREN OFF
              btfsc     _CREN       
              goto      RxByteSerialPort1A 
;
RxByteSerialPort1B:
;
              bsf       _CREN                   ;     - CREN back ON
              btfss     _CREN       
              goto      RxByteSerialPort1B       
;
RxByteSerialPort1C:
;
              btfss     _FERR                    ;IF !FRAMING
              goto      RxByteSerialPort1D       ;THEN check error flag
              bsf       Boolean_Interrupt        ;ELSE flag error and
              movf      RCREG,W                  ;     recover from FRAMING
;
RxByteSerialPort1D:
;
              btfsc     Boolean_Interrupt        ;IF ERROR
              goto      RxByteSerialPort1End     ;THEN go
                                                 ;ELSE buffer byte
;
              movf      RCREG,W                  ;Read the byte received
              movwf     Rx1Character_3
;
              incf      Rx1BufferWritePointer_3,W
;
              xorlw     Rx1BufferLastLocation+1  ;IF > LAST
              btfsc     ZeroFlag                 ;THEN ROLL OVER to FIRST
              movlw     Rx1BufferFirstLocation^(Rx1BufferLastLocation+1) 
;
              xorlw     Rx1BufferLastLocation+1  ;Restore W from comparison
;
              movwf     RxByteSerialPort1_Work_3
;
              subwf     Rx1BufferReadPointer_3,W
              btfsc     ZeroFlag
              goto      RxByteSerialPort1End     ;The buffer is full, so drop this character 
; 
              movf      Rx1BufferWritePointer_3,W
              movwf     FSR0L
;
              movlw     HIGH(Rx1Buffer_4)
              movwf     FSR0H
;
              movf      Rx1Character_3,W
              movwf     INDF0  
;
              movf      RxByteSerialPort1_Work_3,W
              movwf     Rx1BufferWritePointer_3
;
RxByteSerialPort1End:
;
              movlb     0              ;Point to page 0
;
              btfsc     _RCIF
              goto      RxByteSerialPort1_2
;
              return
; 
;***************************************
;
; Unbuffer and transmit serial byte to Serial Port 1
;
;***************************************
;
TxByteSerialPort_2:
;
              movlb     Tx1BufferReadPointer_3>>7 
;
              movlw     HIGH(Tx1Buffer_4)        ;Point to the correct bank
              movwf     FSR0H
;
              movf      Tx1BufferReadPointer_3,W
              movwf     FSR0L
;
              moviw     FSR0++
              movwf     TXREG                    ;Transmit byte
;
              movf      FSR0L,W
              xorlw     Tx1BufferLastLocation+1  ;IF > LAST
              btfsc     ZeroFlag                 ;THEN ROLL OVER to FIRST
              movlw     Tx1BufferFirstLocation^(Tx1BufferLastLocation+1) 
;
              xorlw     Tx1BufferLastLocation+1  ;Restore W from comparison
;
              movwf     Tx1BufferReadPointer_3
;
TxByteSerialPortEnd
;
             return
;

;
;***************************************
;*
;* TITLE..: PICMATHS - 40-bit maths routines
;* AUTHOR.: Robert Farrer
;*
;* V02R00 - 21/01/2004 - Let's start here and see what happens !!!
;*                     - For PICO PLC                                  
;* V02R01 - 17/01/2005 - Converted to PIC18Fxxx
;* V02R02 - 14/02/2006 - Converted from 32-bit to 40-bit for DALLAS date and time conversions
;* V03R00 - 2020/02/05 - Adapted for the PIC16F18xx series of devices with multiple small memory pages
;*
;***************************************
;
;***************************************
;
; FUNCTION.....: 40-bit addition
;                CalculatorX = CalculatorX + CalculatorY
;
; INPUTS.......: CalculatorX4, CalculatorX3, CalculatorX2, CalculatorX1, CalculaotrX0
;                CalculatorY4, CalculatorY3, CalculatorY2, CalculatorY1, CalculatorY0
;
; OUTPUTS......: CalculatorX4, CalculatorX3, CalculatorX2, CalculatorX1, CalculatorX0
;                CarryFlag
;
; SPECIAL NOTES: None
;
;***************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
Add40_2:      movf      CalculatorY0,W           ;Fetch Y low byte
              addwf     CalculatorX0,Same        ;And add to X low byte
;
              movf      CalculatorY1,W       
              addwfc    CalculatorX1,Same         
;
              movf      CalculatorY2,W       
              addwfc    CalculatorX2,Same         
;
              movf      CalculatorY3,W       
              addwfc    CalculatorX3,Same         
;
              movf      CalculatorY4,W        
              addwfc    CalculatorX4,Same         
;
              return                             ;And back we go
;
;***************************************
;
; FUNCTION.....: 40-bit subtraction
;                CalculatorX = CalculatorX - CalculatorY
;
; INPUTS.......: CalculatorX4, CalculatorX3, CalculatorX2, CalculatorX1, CalculatorX0,
;                CalculatorY4, CalculatorY3, CalculatorY2, CalculatorY1, CalculatorY0
;
; OUTPUTS......: CalculatorX4, CalculatorX3, CalculatorX2, CalculatorX1, CalculatorX0
;
; SPECIAL NOTES: None
;
;***************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
Sub40_2:      movf      CalculatorY0,W           ;Fetch Y low byte
              subwf     CalculatorX0,Same        ;And subtract from X low byte
;
              movf      CalculatorY1,W        
              subwfb    CalculatorX1,Same       
;
              movf      CalculatorY2,W       
              subwfb    CalculatorX2,Same       
;
              movf      CalculatorY3,W       
              subwfb    CalculatorX3,Same       
;
              movf      CalculatorY4,W       
              subwfb    CalculatorX4,Same       
;
              return                             ;And back we go
;
;***************************************
;
; FUNCTION.....: 40-bit by 40-bit multiplication
;                CalculatorX = CalculatorX * CalculatorY
;
; INPUTS.......: CalculatorX4, CalculatorX3, CalculatorX2, CalculatorX1, CalculatorX0
;                CalculatorY4, CalculatorY3, CalculatorY2, CalculatorY1, CalculatorY0
;
; OUTPUTS......: CalculatorX4, CalculatorX3, CalculatorX2, CalculatorX1, CalculatorX0
;                CalculatorError
;
; SPECIAL NOTES: Uses CalculatorCount, CalculatorTA4, CalculatorTA3, CalculatorTA2,
;                CalculatorTA1, CalculatorTA0, Add32
;
;                Using 40-bit inputs for both X and Y means that the product
;                could be 40-bits in length! If the product exceeds 40-bits
;                the BError bit is set to indicate an overflow. The reason
;                for having 40-bit inputs with only a 40-bit output, is that
;                it allows you to do:
;
;                   1 * 5 000 000 000
;                   5 000 000 000 * 1
;
;***************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;    
Mul40_2:      bcf       CalculatorError          ;Assume no ERROR
              bcf       CalculatorMulOver        ;RESET muliplier overflow flag
;
              movf      CalculatorX0,W
              movwf     CalculatorTA0 ;Save X to Temp
              movf      CalculatorX1,W
              movwf     CalculatorTA1
              movf      CalculatorX2,W
              movwf     CalculatorTA2
              movf      CalculatorX3,W
              movwf     CalculatorTA3
              movf      CalculatorX4,W
              movwf     CalculatorTA4
;
              clrf      CalculatorX0             ;Zero product
              clrf      CalculatorX1       
              clrf      CalculatorX2       
              clrf      CalculatorX3       
              clrf      CalculatorX4        
;
              movlw     40                       ;There are 40-bits to process
              movwf     CalculatorCount       
;
Mul40A        rrf       CalculatorTA4,Same        ;IF LSB = 1
              rrf       CalculatorTA3,Same       
              rrf       CalculatorTA2,Same       
              rrf       CalculatorTA1,Same       
              rrf       CalculatorTA0,Same       
;
              bsf       CalculatorBoolean        ;IF MulOver .AND. LSB
              btfss     CalculatorMulOver
              bcf       CalculatorBoolean
              btfss     CarryFlag
              bcf       CalculatorBoolean
;
              btfsc     CalculatorBoolean
              bsf       CalculatorError          ;THEN indicate an ERROR
;
              btfsc     CarryFlag    
              call      Add40_2                  ;THEN update product
;
              btfsc     CarryFlag                ;IF CARRY, (from Add40)
              bsf       CalculatorError          ;THEN indicate an ERROR
;
              bcf       CarryFlag                ;CalcY * 2
              rlf       CalculatorY0,Same        
              rlf       CalculatorY1,Same       
              rlf       CalculatorY2,Same        
              rlf       CalculatorY3,Same       
              rlf       CalculatorY4,Same       
;
              btfsc     CarryFlag                ;IF CalcY overflowed
              bsf       CalculatorMulOver        ;THEN flag for next addition
;
              decfsz    CalculatorCount,Same     ;IF more bits
              goto      Mul40A                   ;THEN process them
;
              return                             ;Back we go
;
;***************************************
;
; FUNCTION.....: 40-bit division
;                CalculatorX = INTEGER (CalculatorX / CalculatorY)
;
; INPUTS.......: CalculatorX4, CalculatorX3, CalculatorX2, CalculatorX1, CalculatorX0, 
;                CalculatorY4, CalculatorY3, CalculatorY2, CalculatorY1, CalculatorY0
;
; OUTPUTS......: CalculatorX4, CalculatorX3, CalculatorX2, CalculatorX1, CalculatorX0
;
; SPECIAL NOTES: Uses CalcCount, CalculatorTA4, CalculatorTA3, CalculatorTA2,  
;                CalculatorTA1, CalculatorTA0, Sub32, Add32
;
;                We need a 40-bit result as 5 000 000 000 / 1 is still 40-bits!
;
;                If you try dividing by 0 then BError will be set.
;
;***************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
Div40_2:      bcf       CalculatorError          ;Assume no ERROR
              movf      CalculatorY0,W           ;Fetch Y0        
              iorwf     CalculatorY1,W           ;OR with Y1
              iorwf     CalculatorY2,W           ;OR with Y2
              iorwf     CalculatorY3,W           ;OR with Y3
              iorwf     CalculatorY4,W           ;OR with Y4
              btfsc     ZeroFlag                 ;IF ZERO
              bsf       CalculatorError          ;THEN indicate an error
;
              movf      CalculatorX0,W
              movwf     CalculatorTA0 ;Save X to Temp
              movf      CalculatorX1,W
              movwf     CalculatorTA1
              movf      CalculatorX2,W
              movwf     CalculatorTA2
              movf      CalculatorX3,W
              movwf     CalculatorTA3
              movf      CalculatorX4,W
              movwf     CalculatorTA4
;
              clrf      CalculatorX0             ;Zero CalcX as temp work space
              clrf      CalculatorX1       
              clrf      CalculatorX2       
              clrf      CalculatorX3       
              clrf      CalculatorX4       
;
              movlw     40                       ;There are 40-bits to process
              movwf     CalculatorCount       
;
Div40A        rlf       CalculatorTA0,Same        ;Quotient goes to temp LSB
              rlf       CalculatorTA1,Same              
              rlf       CalculatorTA2,Same        
              rlf       CalculatorTA3,Same        
              rlf       CalculatorTA4,Same         
              rlf       CalculatorX0,Same         ;Temp MSB goes to CalcX LSB
              rlf       CalculatorX1,Same        
              rlf       CalculatorX2,Same         
              rlf       CalculatorX3,Same        
              rlf       CalculatorX4,Same          
;
              call      Sub40_2                  ;IF CalcX < CalcY
;
              bsf       CalculatorDivStore       ;Assume no BORROW
              btfss     CarryFlag                ;IF BORROW
              bcf       CalculatorDivStore       ;THEN correct assumption
;
              btfss     CarryFlag    
              call      Add40_2                  ;THEN restore CalcX
;
              bsf       CarryFlag                ;Assume no BORROW
              btfss     CalculatorDivStore       ;IF BORROW
              bcf       CarryFlag                ;THEN correct assumption
;
              decfsz    CalculatorCount,Same     ;IF more bits
              goto      Div40A                   ;THEN process them
;
              rlf        CalculatorTA0,Same        ;Quotient goes to temp LSB
              rlf        CalculatorTA1,Same       
              rlf        CalculatorTA2,Same        
              rlf        CalculatorTA3,Same        
              rlf        CalculatorTA4,Same       
              movf       CalculatorTA0,W
              movwf      CalculatorX0
              movf       CalculatorTA1,W
              movwf      CalculatorX1
              movf       CalculatorTA2,W
              movwf      CalculatorX2
              movf       CalculatorTA3,W
              movwf      CalculatorX3
              movf       CalculatorTA4,W
              movwf      CalculatorX4
;
              return                             ;Back we go
;
;***************************************
;
BCD2BinaryTU_2:
;
;***************************************
;
              swapf       CalculatorX0,W
              andlw       b'00001111'
              movwf       CalculatorX1
              movlw       b'00001111'
              andwf       CalculatorX0,Same
;
BCD2BinaryTU_2A:
;
              movf        CalculatorX1,W
              btfsc       ZeroFlag
              goto        BCD2BinaryTU_2B
;
              movlw       10
              addwf       CalculatorX0,Same
;
              decf        CalculatorX1,Same
;
              goto        BCD2BinaryTU_2A
;
BCD2BinaryTU_2B:
;
              return
;
;***************************************
;
; That's all the 40-bit maths routines we need for here
; - Work out what our offset is from our 07H00M00 log time in the morning
; - This is split up because the parts are called from the QueueDailyLog state machine
;
;***************************************
;
CalculateSecondsOffset_2:
;
              call      CalculateSecondsOffset_Hours_2 
              call      CalculateSecondsOffset_Minutes_2
              call      CalculateSecondsOffset_Seconds_2
;
              return
;
CalculateSecondsOffset_Hours_2:
;
              movlb     Hours_2>>7
              movf      Hours_2,W
              movlb     CalculatorX0>>7
              movwf     CalculatorX0
;
              call      BCD2BinaryTU_2
;
              movlw     7
              subwf     CalculatorX0,W
              movlw     -7
              btfss     CarryFlag
              movlw     17
              addwf     CalculatorX0,Same         
              clrf      CalculatorX1
              clrf      CalculatorX2
              clrf      CalculatorX3
              clrf      CalculatorX4
;
              movlw     LOW(60*60)
              movwf     CalculatorY0
              movlw     HIGH(60*60)
              movwf     CalculatorY1 
              clrf      CalculatorY2
              clrf      CalculatorY3
              clrf      CalculatorY4
;
              call      Mul40_2
;
              movlb     CalculatorX0>>7
              movf      CalculatorX0,W
              movwf     Seconds_Offset_0
              movf      CalculatorX1,W
              movwf     Seconds_Offset_0H
              movf      CalculatorX2,W
              movwf     Seconds_Offset_0HH
;
              return
;
CalculateSecondsOffset_Minutes_2:
;
              movlb     Minutes_2>>7
              movf      Minutes_2,W
              movlb     CalculatorX0>>7
              movwf     CalculatorX0
;
              call      BCD2BinaryTU_2
;
              clrf      CalculatorX1
              clrf      CalculatorX2
              clrf      CalculatorX3
              clrf      CalculatorX4
;
              movlw     LOW(60)
              movwf     CalculatorY0
              movlw     HIGH(60)
              movwf     CalculatorY1 
              clrf      CalculatorY2
              clrf      CalculatorY3
              clrf      CalculatorY4
;
              call      Mul40_2
;
              movlb     CalculatorX0>>7
              movf      CalculatorX0,W
              addwf     Seconds_Offset_0,Same
              movf      CalculatorX1,W
              addwfc    Seconds_Offset_0H,Same
              movf      CalculatorX2,W
              addwfc    Seconds_Offset_0HH,Same
;
              return
;
CalculateSecondsOffset_Seconds_2:
;
              movlb     Seconds_2>>7
              movf      Seconds_2,W
              movlb     CalculatorX0>>7
              movwf     CalculatorX0
;
              call      BCD2BinaryTU_2
;
              clrf      CalculatorX1
              clrf      CalculatorX2
;
              movlb     CalculatorX0>>7
              movf      CalculatorX0,W
              addwf     Seconds_Offset_0,Same
              movf      CalculatorX1,W
              addwfc    Seconds_Offset_0H,Same
              movf      CalculatorX2,W
              addwfc    Seconds_Offset_0HH,Same
;
              return
;
LogHiLoEvent_2:
;
; When we get here:
; - We expect HiLoDetail1_2 and HiLoDetail2_2 to contain valid data
; - The clock starting at Seconds_0 to contain valid time and date
; - Humidity and temperature highs and lows will be collected and written away as part of this log entry
;
              LiveDebug LiveDebug_LogHiLoEvent_Start
;
              movlw     LogEvent_HiLo
              movwf     Checksum_A
              PagedCall EEPROM_WriteBuffer
;
              movlb     HiLoDetail1_2>>7
              movf      HiLoDetail1_2,W
              addwf     Checksum_A,Same
              PagedCall EEPROM_WriteBuffer
;
              movlb     HiLoDetail1_2>>7
              movf      HiLoDetail2_2,W
              addwf     Checksum_A,Same
              PagedCall EEPROM_WriteBuffer
;
              movlw     LOW(Year_2)
              movwf     FSR1L                    ;Remember EEPROM_WriteBuffer uses FSR0
              movlw     HIGH(Year_2)
              movwf     FSR1H  
;
              moviw     FSR1-- ;Year_2
              addwf     Checksum_A,Same
              PagedCall EEPROM_WriteBuffer       
              moviw     FSR1-- ;Month_2
              addwf     Checksum_A,Same
              PagedCall EEPROM_WriteBuffer
              moviw     FSR1-- ;Date_2
              addwf     Checksum_A,Same
              PagedCall EEPROM_WriteBuffer
;
              moviw     FSR1-- ;Skip DayOfWeek_2 ;K520 so it mustn't affect the checksum!
;
              moviw     FSR1-- ;Hours_2
              addwf     Checksum_A,Same
              PagedCall EEPROM_WriteBuffer
              moviw     FSR1-- ;Minutes_2
              addwf     Checksum_A,Same
              PagedCall EEPROM_WriteBuffer
              moviw     FSR1-- ;Seconds_2
              addwf     Checksum_A,Same
              PagedCall EEPROM_WriteBuffer
;
              movlw     LOW(RainPulse_0)
              movwf     FSR1L                    ;Remember EEPROM_WriteBuffer uses FSR0
              movlw     HIGH(RainPulse_0)
              movwf     FSR1H  
;
              moviw     FSR1++ ;Rain_0
              addwf     Checksum_A,Same
              PagedCall EEPROM_WriteBuffer
              moviw     FSR1++ ;Rain_0H
              addwf     Checksum_A,Same
              PagedCall EEPROM_WriteBuffer
              moviw     FSR1++ ;Rain_0HH
              addwf     Checksum_A,Same
              PagedCall EEPROM_WriteBuffer
              moviw     FSR1++ ;HumidityLo_0
              addwf     Checksum_A,Same
              PagedCall EEPROM_WriteBuffer
              moviw     FSR1++ ;HumidityHi_0
              addwf     Checksum_A,Same
              PagedCall EEPROM_WriteBuffer
              moviw     FSR1++ ;TemperatureLo_0
              addwf     Checksum_A,Same
              PagedCall EEPROM_WriteBuffer
              moviw     FSR1++ ;TemperattureLo0H
              addwf     Checksum_A,Same
              PagedCall EEPROM_WriteBuffer
              moviw     FSR1++ ;TemperatureHi_0
              addwf     Checksum_A,Same
              PagedCall EEPROM_WriteBuffer
              moviw     FSR1++ ;TemperatureHi_0H
              addwf     Checksum_A,Same
              PagedCall EEPROM_WriteBuffer
;
              comf      Checksum_A,W
              addlw     1
              PagedCall EEPROM_WriteBuffer
;             
              movlw     Event_WriteEEPROM
              PagedCall WriteEventToQueue
;
              LiveDebug LiveDebug_LogHiLoEvent_End
;
              return
;
              org       0x1800 ;Program memory page 3
;
SaveSettings_Bulk_3:
;
              movlb     VerifySettings_State_3>>7 ;We may have been busy verifying the settings, so make sure we start from the beginning
              clrf      VerifySettings_State_3
;
              movlw     EE_ActiveBank
              call      ReadInternalEEPROM_3
              xorlw     0x5A
              movlb     EEPROMSaveBank_3>>7
              btfsc     ZeroFlag
              goto      SaveSettingsOffset5A
              xorlw     0xA5^0x5A
              btfsc     ZeroFlag 
              goto      SaveSettingsOffsetA5
;
; We should never get here, because any smudging issues should have been taken care of at power up!
;
              reset     ;This will potentially cause some data loss, but there isn't too much we can do about that now!!!
;
SaveSettingsOffset5A:
;
              movlw     0x40
              movwf     EEPROMSaveBank_3
              movlw     0x00
              movwf     EEPROMSequenceBank_3
              movlw     0xA5
              movwf     EEPROMNewBank_3
; 
              goto      SaveSettings1
; 
SaveSettingsOffsetA5:
;
              movlw     0x00
              movwf     EEPROMSaveBank_3
              movlw     0x40
              movwf     EEPROMSequenceBank_3
              movlw     0x5A
              movwf     EEPROMNewBank_3
;
              goto      SaveSettings1
;
SaveSettings_Donkey: macro EE_Location,NV_Variable
;
              local     SaveSettings_DonkeyOut
;
              movlb     EEPROMSaveBank_3>>7
              movlw     EE_Location
              addwf     EEPROMSaveBank_3,W
              call      ReadInternalEEPROM_3 ;This returns with BSR=0 and all NV_Variables are in page 0, so no banking necessary
              subwf     NV_Variable,W
              btfsc     ZeroFlag
              goto      SaveSettings_DonkeyOut
              movf      NV_Variable,W
              call      WriteInternalEEPROM_3
;
SaveSettings_DonkeyOut:
;
              endm
;
SaveSettings1: SaveSettings_Donkey EE_FirmwareYear,FirmwareYear_0
               SaveSettings_Donkey EE_FirmwareMonth,FirmwareMonth_0
               SaveSettings_Donkey EE_FirmwareDayTens,FirmwareDayTens_0
               SaveSettings_Donkey EE_FirmwareDayUnits,FirmwareDayUnits_0
;
               SaveSettings_Donkey EE_PowerUps,PowerUps_0
               SaveSettings_Donkey EE_PowerUpsH,PowerUps_0H
               SaveSettings_Donkey EE_Connections,Connections_0
               SaveSettings_Donkey EE_ConnectionsH,Connections_0H
;
               SaveSettings_Donkey EE_BatteryVoltage,BatteryVoltage_0
;
               SaveSettings_Donkey EE_LogReadPointer,LogReadPointer_0
               SaveSettings_Donkey EE_LogReadPointerH,LogReadPointer_0H
               SaveSettings_Donkey EE_LogReadPointerHH,LogReadPointer_0HH
;
               SaveSettings_Donkey EE_LogWritePointer,LogWritePointer_0
               SaveSettings_Donkey EE_LogWritePointerH,LogWritePointer_0H
               SaveSettings_Donkey EE_LogWritePointerHH,LogWritePointer_0HH 
;
               SaveSettings_Donkey EE_RainPulse,RainPulse_0
               SaveSettings_Donkey EE_RainPulseH,RainPulse_0H
               SaveSettings_Donkey EE_RainPulseHH,RainPulse_0HH
;
               SaveSettings_Donkey EE_HumidityLo,HumidityLo_0
               SaveSettings_Donkey EE_HumidityHi,HumidityHi_0
;
               SaveSettings_Donkey EE_TemperatureLo,TemperatureLo_0
               SaveSettings_Donkey EE_TemperatureLoH,TemperatureLo_0H 
               SaveSettings_Donkey EE_TemperatureHi,TemperatureHi_0
               SaveSettings_Donkey EE_TemperatureHiH,TemperatureHi_0H 
;
               SaveSettings_Donkey EE_Debug1,Debug1_0
               SaveSettings_Donkey EE_Debug2,Debug2_0 
               SaveSettings_Donkey EE_Debug3,Debug3_0 
;
SaveSettingsChangeSequenceNumber:
;
              movlw     EE_SequenceNumber
              movlb     EEPROMSequenceBank_3>>7 
              addwf     EEPROMSequenceBank_3,W
              call      ReadInternalEEPROM_3 
              movlb     EEPROMSequence_3>>7
              movwf     EEPROMSequence_3 
              movlw     EE_SequenceNumber
              addwf     EEPROMSaveBank_3,W
              call      ReadInternalEEPROM_3     ;Dummy read to set address
              movlb     EEPROMSequence_3>>7
              incf      EEPROMSequence_3,Same
              movlw     0xFF                     ;0xFF is not a valid sequence number, because it is the value of erased EEPROM memory
              xorwf     EEPROMSequence_3,W
              btfsc     ZeroFlag
              incf      EEPROMSequence_3,Same      ;So increment 0xFF to become 0x00
              movf      EEPROMSequence_3,W
              call      WriteInternalEEPROM_3
;
SaveSettingsSwitchActiveBank:
;
              movlw     EE_ActiveBank
              call      ReadInternalEEPROM_3     ;Dummy read to set address
              movlb     EEPROMNewBank_3>>7
              movf      EEPROMNewBank_3,W
              call      WriteInternalEEPROM_3
;
SaveSettingsOut:
;
              return
;
; Restore settings from non-volatile memory
;
RestoreSettings_Bulk_3:
;
              movlb     VerifySettings_State_3>>7 ;We may have been busy verifying the settings, so make sure we start from the beginning
              clrf      VerifySettings_State_3
;
              movlw     EE_ActiveBank
              call      ReadInternalEEPROM_3
              movlb     EEPROMRestoreBank_3>>7
              xorlw     0x5A
              btfsc     ZeroFlag
              goto      RestoreSettingsOffset5A
              xorlw     0xA5^0x5A
              btfsc     ZeroFlag 
              goto      RestoreSettingsOffsetA5
;
; Hopefully we never get here, but we may occassionally!
; - The EEPROM is smudged, see if I can recover from it
;               
              movlw     EE_SequenceNumber
              call      ReadInternalEEPROM_3
              movlb     EEPROMBank0Sequence_3>>7
              movwf     EEPROMBank0Sequence_3
;               
              movlw     EE_SequenceNumber
              addlw     0x40
              call      ReadInternalEEPROM_3
              movlb     EEPROMBank1Sequence_3>>7
              movwf     EEPROMBank1Sequence_3
;
              movlw     0xFF
              xorwf     EEPROMBank0Sequence_3,W
              btfsc     ZeroFlag
              goto      RestoreSettingsOffsetA5 ;Bank0 sequence is smudged, so take a chance on Bank1 - there isn't much else to do!
;
              movlw     0xFF
              xorwf     EEPROMBank1Sequence_3,W
              btfsc     ZeroFlag
              goto      RestoreSettingsOffset5A ;Bank1 sequence is smudged, so take a chance on Bank0 - there isn't much else to do!
;
; Both sequences are valid, so choose the bank with the highest sequence number
; - Remember 0xFE rolls over to 0x00 when it increments
;
              movlw     0xFE
              xorwf     EEPROMBank0Sequence_3,W
              btfsc     ZeroFlag
              goto      RestoreSettingsIsBank1GreaterOrSmaller
;
              movlw     0xFE
              xorwf     EEPROMBank1Sequence_3,W
              btfsc     ZeroFlag
              goto      RestoreSettingsIsBank0GreaterOrSmaller
; 
              movf      EEPROMBank0Sequence_3,W
              subwf     EEPROMBank1Sequence_3,W
              btfss     CarryFlag ;I don't even test the ZeroFlag, because what can we do if the sequences are equal???
              goto      RestoreSettingsOffset5A
              goto      RestoreSettingsOffsetA5
;
RestoreSettingsIsBank0GreaterOrSmaller:
;
              movf      EEPROMBank0Sequence_3,W
              btfss     ZeroFlag
              goto      RestoreSettingsOffsetA5 ;B1=0xFE B0!=0x00 so B1 is greater
              goto      RestoreSettingsOffset5A ;B1=0xFE B0=0x00 so B0 is greater
;
RestoreSettingsIsBank1GreaterOrSmaller:
;
              movf      EEPROMBank1Sequence_3,W
              btfss     ZeroFlag
              goto      RestoreSettingsOffset5A ;B0=0xFE B1!=0x00 so B0 is greater
              goto      RestoreSettingsOffsetA5 ;B0=0xFE B1=0x00 so B1 is greater
;
RestoreSettingsOffset5A:
;
              movlw     0x00
; 
              goto      RestoreSettings1
; 
RestoreSettingsOffsetA5:
;
              movlw     0x40
; 
              goto      RestoreSettings1
;
RestoreSettings_Donkey: macro EE_Location,NV_Variable
;
              movlw     EE_Location
              movlb     EEPROMRestoreBank_3>>7
              addwf     EEPROMRestoreBank_3,W
              call      ReadInternalEEPROM_3
              movwf     NV_Variable
;            
              endm
;
RestoreSettings1:
;
              movwf     EEPROMRestoreBank_3
;

              movlw     EE_FirmwareYear
              movlb     EEPROMRestoreBank_3>>7
              addwf     EEPROMRestoreBank_3,W
              call      ReadInternalEEPROM_3
              movwf     FirmwareYear_0



              RestoreSettings_Donkey EE_FirmwareYear,FirmwareYear_0
              RestoreSettings_Donkey EE_FirmwareMonth,FirmwareMonth_0
              RestoreSettings_Donkey EE_FirmwareDayTens,FirmwareDayTens_0
              RestoreSettings_Donkey EE_FirmwareDayUnits,FirmwareDayUnits_0
;
              RestoreSettings_Donkey EE_PowerUps,PowerUps_0
              RestoreSettings_Donkey EE_PowerUpsH,PowerUps_0H
              RestoreSettings_Donkey EE_Connections,Connections_0
              RestoreSettings_Donkey EE_ConnectionsH,Connections_0H
;
              RestoreSettings_Donkey EE_BatteryVoltage,BatteryVoltage_0
;
              RestoreSettings_Donkey EE_LogReadPointer,LogReadPointer_0
              RestoreSettings_Donkey EE_LogReadPointerH,LogReadPointer_0H
              RestoreSettings_Donkey EE_LogReadPointerHH,LogReadPointer_0HH
;
              RestoreSettings_Donkey EE_LogWritePointer,LogWritePointer_0
              RestoreSettings_Donkey EE_LogWritePointerH,LogWritePointer_0H
              RestoreSettings_Donkey EE_LogWritePointerHH,LogWritePointer_0HH 
;
              RestoreSettings_Donkey EE_RainPulse,RainPulse_0
              RestoreSettings_Donkey EE_RainPulseH,RainPulse_0H
              RestoreSettings_Donkey EE_RainPulseHH,RainPulse_0HH
;
              RestoreSettings_Donkey EE_HumidityLo,HumidityLo_0
              RestoreSettings_Donkey EE_HumidityHi,HumidityHi_0
;
              RestoreSettings_Donkey EE_TemperatureLo,TemperatureLo_0
              RestoreSettings_Donkey EE_TemperatureLoH,TemperatureLo_0H 
              RestoreSettings_Donkey EE_TemperatureHi,TemperatureHi_0
              RestoreSettings_Donkey EE_TemperatureHiH,TemperatureHi_0H 
;
              RestoreSettings_Donkey EE_Debug1,Debug1_0
              RestoreSettings_Donkey EE_Debug2,Debug2_0
              RestoreSettings_Donkey EE_Debug3,Debug3_0
;
              return
;
;***************************************
;
; Read data from internal EEPROM                
; - Address to be read in W  
; - Return with data in W
;
;***************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
ReadInternalEEPROM_3:
;
              movlb     EEADRL>>7
;
ReadInternalEEPROM_3A:
;
              btfsc     _EEWR
              goto      ReadInternalEEPROM_3A
;
              movwf     EEADRL
              bcf       _EEPGD
              bcf       _EECFGS
              bsf       _EERD
              movf      EEDATL,W
;
              movlb     0
;
              return
;
;***************************************
;
; Write data into internal EEPROM                
; - EEADR loaded with address
; - Data to be written in W
; - Disables and restores interrupts
;
;***************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
WriteInternalEEPROM_3:
;
              movlb     EEDATL>>7
;
WriteInternalEEPROM_3A:
;
              btfsc     _EEWR
              goto      WriteInternalEEPROM_3A      
;
              movwf     EEDATL
              bcf       _EEPGD
              bcf       _EECFGS
              bsf       _EEWREN
;
              SaveGIE 
              movlw     0x55
              movwf     EECON2
              movlw     0xAA
              movwf     EECON2
              bsf       _EEWR
              RestoreGIE
;
              bcf       _EEWREN
;
              movlb     0
;
              return
;
;***************************************
;
; This subroutine verifies the non-volatiles in EEPROM against RAM
;
;***************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
VerifySettings_3:
;
              LiveDebug LiveDebug_VerifySettings_Start
;               
              movlw     FirmwareYear_0           ;Point to first non-volatile variable in RAM
              movwf     FSR0L
              clrf      FSR0H
;
              movlw     NV_BoundaryHi-NV_BoundaryLo
              movwf     ScratchPad0_A
;
              movlw     EE_ActiveBank            ;Find the active EEPROM bank, so we can check the other one
              PagedCall ReadInternalEEPROM
              xorlw     0x5A
              btfsc     ZeroFlag
              goto      VerifySettings_3_Offset5A
              xorlw     0xA5^0x5A
              btfsc     ZeroFlag 
              goto      VerifySettings_3_OffsetA5
;
; We should never get here, because any smudging issues should have been taken care of at power up!
;
              reset     ;This will potentially cause some data loss, but there isn't too much we can do about that now!!!
;
VerifySettings_3_Offset5A:
;
              movlw     0x40
              goto      VerifySettings_3_1
; 
VerifySettings_3_OffsetA5:
;
              movlw     0x00
              goto      VerifySettings_3_1
;
VerifySettings_3_1:
;
              movlb     EEADRL>>7
              movwf     EEADRL
;
              movlp     HIGH(VerifySettings_3_DispatchTable)
              movf      VerifySettings_State_3,W
              andlw     b'00000011'
              addlw     LOW(VerifySettings_3_DispatchTable)
              btfsc     CarryFlag
              incf      PCLATH,Same 
              movwf     PCL

VerifySettings_3_DispatchTable
;
VS_3_DT00:    goto      VS_3_Check
VS_3_DT01:    goto      VS_3_IncrementSequence
VS_3_DT02:    goto      VS_3_SwitchBank  
VS_3_DT03:    goto      VS_3_Finalise 
;
VS_3_Check:
;
              movlb     EEADRL>>7
              movlw     FirmwareYear_0-ActiveBank_0 ;Point to first non-volatile variable in EEPROM
              addwf     EEADRL,Same
              bcf       _EEPGD
              bcf       _EECFGS
;
VS_3_Check_1:
;
              bsf       _EERD 
              moviw     FSR0++
              subwf     EEDATL,W 
              btfsc     ZeroFlag
              goto      VS_3_Check_2
;
              moviw     --FSR0
              movwf     FSR1L
              movlw     Event_RefreshNV
              PagedCall WriteEventToQueue
              movlb     EEADRL>>7
              movf      EEADRL,W
              PagedCall WriteEventToQueue
              movf      FSR1L,W
              PagedCall WriteEventToQueue
;
              bcf       PowerDown                ;We have just queued an event, so cancel the PowerDown for now
;
              goto      VerifySettings_3_Out
;
VS_3_Check_2:
;
              incf      EEADRL,Same 
              decfsz    ScratchPad0_A,Same  
              goto      VS_3_Check_1
;
              btfss     BankSwitchRequired
              goto      VS_3_Check_3
;      
              incf      VerifySettings_State_3,Same
;
              bcf       PowerDown                ;We are about to queue an event, so cancel the PowerDown for now
;
VS_3_Check_3:
;
              goto      VerifySettings_3_Out
;
VS_3_IncrementSequence:
;
              movlw     SequenceNumber_0-ActiveBank_0 ;Point to the sequence number
              addwf     EEADRL,W
              xorlw     0x40                     ;In the ACTIVE bank
              movwf     EEADRL      
              bcf       _EEPGD
              bcf       _EECFGS
;
              bsf       _EERD
              movf      EEDATL,W
              addlw     1 
              movwf     EEDATL
              movlw     0xFF                     ;0xFF is not a valid sequence number, because it is the value of erased EEPROM memory
              xorwf     EEDATL,W
              btfsc     ZeroFlag
              incf      EEDATL,Same              ;So increment 0xFF to become 0x00
; 
              movlw     Event_RefreshNV
              PagedCall WriteEventToQueue
              movlb     EEADRL>>7
              movf      EEADRL,W
              xorlw     0x40                     ;Point back to the REFRESH bank
              PagedCall WriteEventToQueue
              movlb     EEDATL>>7
              movf      EEDATL,W
              PagedCall WriteEventToQueue
;
              movlb     VerifySettings_State_3>>7
              incf      VerifySettings_State_3,Same
;
              bcf       PowerDown                ;We have just queued an event, so cancel the PowerDown for now
;
              goto      VerifySettings_3_Out
;
VS_3_SwitchBank:
;
              movf      EEADRL,W
              movlw     0xA5
              btfsc     ZeroFlag
              movlw     0x5A
              movwf     EEDATL
; 
              movlw     Event_RefreshNV
              PagedCall WriteEventToQueue
              movlw     EE_ActiveBank
              PagedCall WriteEventToQueue
              movlb     EEDATL>>7
              movf      EEDATL,W
              PagedCall WriteEventToQueue
;
              movlb     VerifySettings_State_3>>7
              incf      VerifySettings_State_3,Same
;
              bcf       PowerDown                ;We have just queued an event, so cancel the PowerDown for now
;
              goto      VerifySettings_3_Out
;
VS_3_Finalise:
;
              bcf       BankSwitchRequired
              clrf      VerifySettings_State_3
;
              goto      VerifySettings_3_Out
;           
VerifySettings_3_Out:
;
              LiveDebug LiveDebug_VerifySettings_End
;
              movlb     0
;
              return
;
DebugOnPower:
;
              movlb     IOCAF>>7
              movlw     0
              movwf     IOCAF
;
              movlw     HIGH(LATC)
              movwf     FSR1H
              movlw     LOW(LATC)
              movwf     FSR1L
;
              btfsc     INDF1,3
              goto      MakeLo
              goto      MakeHi
;
MakeLo:
;
              bcf       INDF1,3
; 
              goto      Forever_RainGauge
;
MakeHi:
; 
              bsf       INDF1,3
;
              goto Forever_RainGauge



;
BinaryToBCD:
;
              clrf      Thousands
              clrf      Hundreds
              clrf      Tens
              movwf     Units
;
BTBCDThou:
;
              movlw     LOW(1000)
              subwf     Binary,Same
              movlw     HIGH(1000)
              subwfb    BinaryH,Same
;
              btfss     CarryFlag
              goto      BTBCDThouOut
;
              incf      Thousands,Same
;
              goto      BTBCDThou
;
BTBCDThouOut:
;
              movlw     LOW(1000)
              addwf     Binary,Same
              movlw     HIGH(1000)
              addwfc    BinaryH,Same
;
BTBCDHun:
;
              movlw     LOW(100)
              subwf     Binary,Same
              movlw     HIGH(100)
              subwfb    BinaryH,Same
;
              btfss     CarryFlag
              goto      BTBCDHunOut
;
              incf      Hundreds,Same
;
              goto      BTBCDHun
;
BTBCDHunOut:
;
              movlw     LOW(100)
              addwf     Binary,Same
              movlw     HIGH(100)
              addwfc    BinaryH,Same
;
              movlw     10
;
BTBCDTen:
;
              incf      Tens,Same 
              subwf     Binary,Same
              btfsc     CarryFlag
              goto      BTBCDTen
;  
              decf      Tens,Same
              addwf     Binary,W
;
              movwf     Units
;
              return  


;
              END