;******************************************************************************
;*                                                                            
;* TITLE: GSM Rain Gauge
;*                                                                            
;* AUTHOR: Robert Farrer for AgriGel
;*     
;* 
;* 
;* SIM = R&D1 = 076-514-6859 voda 50MB expires 9 Dec - "C8G2"
;* SIM = R&D2 = 076-146-6576 voda
;* SIM = R&D3 = 082-664-6036 voda 
;* SIM = R&D4 = 073-927-4906 mtn 150MB expires 19 or 20 Nov
;*
;* MTN USSD codes: 
;* - *131*4# = check RICA
;* - *135# = check balance
;* - *136*VoucherNumber# to load
;* 
;* *************************************
;* *************************************
;* *************************************
;* ***                               ***
;* ***   THINGS TO CHECK / RESOLVE   ***
;* ***                               ***
;* *************************************
;* *************************************
;* *************************************
;* 
;* 
;* 
;* 
;* 
;* 
;* 
;* 
;*     Verify how T1 works and that the code to configure it is correct for this micro!!! - see L728 for some work I did on this
;*
;*     Verify how T2 works and that the code to configure it is correct for this micro!!! - see L728 for some work I did on this
;*
;*     Not all the dispatches have had their maths changed for this processor yet!!!
;*
;*     Verify that I don't have a problem with pclath in the dispatchers in the stand alone rain gauge
;* 
;* 
;* 
;* *************************************
;* *************************************
;* *************************************
;* ***                               ***
;* ***   THINGS TO CHECK / RESOLVE   ***
;* ***                               ***
;* *************************************
;* *************************************
;* *************************************
;* 
;* *************************************
;* *************************************
;* *************************************
;* ***                               ***
;* ***   THINGS CHECKED / RESOLVED   ***
;* ***                               ***
;* *************************************
;* *************************************
;* *************************************
;* 
;* 
;* 
;* 
;* 
;* 
;* 
;* - LB03 
;*   - L930 - Use AT+CIMI to extract number
;*     - No longer required
;*   - L915 - Consider changing FEED to a different identifier when the network sets the time and not a device 
;*     - No longer required
;*   - L804 - SIM balances?
;*     - No longer required
;*   - L804 - Signal strength?
;*     - No longer required 
;* 
;* - LA21 
;*   - Figure out why the MTN SIM doesn't work in the unit 
;*     - Maybe I go buy 1 and see?
;*       - I did and it worked straight out of the box  
;*   - L930 - Extract the time zone from the GSM module when reading the time and send it to the server
;*            - Add this to the second snapshot?
;* 
;* - L929
;*   - I am switching this to resolved because there is no way to do it remotely on this hardware platform
;*   - L804 - How do we reset the unit if it hangs up
;*            - We really need to make sure it doesn't, because the only real way to reset it is to go to it
;* 
;* - L929
;*   - I am switching this to resolved because it isn't really viable! The easiest way to debug the
;*     GSM is by sniffing the comms between the GSM module and the PIC  
;*   - Figure out if we can use the USB for live debug while we are communicating with the modem 
;*     - Yes and no, in this version of the hardware the Tx line is shared between the GSM and the USB,
;*       so if we aren't talking to the GSM then we could switch the Tx to the USB and use it to output
;*       live debug information, but as soon as we switch over to GSM, then we can't
;*     - Maybe I can use an I/O pin and a USB converter to live debug the GSM state machine
;*       - Maybe we can use one of the old GSM boards that didn't work?
;*         - Yes, it is possible to mod these boards into USB adapters!  
;* 
;* - L915 
;*   - Set the clock from the network time 
;* 
;* - L908 
;*   - L825 - See how we make sure the seconds_offset doesn't get cleared while timing the wind speed sample
;* 
;* - L901
;*   - L825 - See why the code gets stuck at I2C clock stretching sometimes
;*            - None of the chips implement clock stretching, so remove the clock stretching code because it is a rudimentary implementation anyway
;*   - L824 - POST retries counter to abort POSTing if there is a server issue  
;*            - The unit now stops trying to POST if the network or server fail to respond 
;* 
;* - L825
;*   - L824 - Block SnapShots from being queued for 10 minutes before the daily log gets queued, to minimise the DailyLog from failing
;*   - L811 - Verify that the rain pulses are debounced, (locked out)
;*   - L702 - Logging on every 15 minutes means we need to keep track of the rain pulses while POSTing 
;*            - Without access to the external EE we aren't going to be able to log individual ticks, so it is going to have to be a bulk log = new function
;*            - Expand the existing RainPulseTimeLost packet   
;*
;* - L820 
;*   - L818 - Sometimes the network terminates the connection before I can read the response from the server and then it is lost, so I keep trying to POST 
;*            the data over and over
;*            - I can see it has been successful because of the 1,200,2 I receive but I just don't have time to read the response before the network terminates the connection
;*            - This to be done about this: 
;*              - 1. Add a retry counter and stop trying after 3 unsuccesful attempts and then retry when we have more data  
;*              - 2. Accept the 1,200,2 as sufficient evidence that the server has the data
;*              - 3. See if Jacques has control over closing the connection from his side and see if he can keep it open, so that I have time to read the response
;*                 and then I will close it from my side
;*          - In the end it turns out that the server takes 3.5s to 7s to analyse the incoming data before responding and it looks like the network timesout the connection
;*            - Change the server side code so that it responds immediately
;*              - Danny's unit just started working without any intervention, so this looks promising
;*            - The downside is that we don't know the unit ID, so we cannot decide if it should be in power saving mode or not, so the server just replies with 0x80 
;* 
;* - L811
;*   - L805 - Vbat
;*   - There is no problem on the PIC side - I was looking at the low byte of the SecondsOffset in the SnapShot instead of the BatteryVoltage
;*     and that is why it was changing with every SnapShot POSTed!!!
;*   - Jacques resolved a server issue
;*     - The server is now displaying the battery status as a percentage
;* 
;* *************************************
;* *************************************
;* *************************************
;* ***                               ***
;* ***   THINGS CHECKED / RESOLVED   ***
;* ***                               ***
;* *************************************
;* *************************************
;* *************************************
;* 
;* 
;* 
;* 
;* 
;* TRISC F94 RTC_Seconds 194 
;* 
;* 
;* 
;* 20(23)/(11)/(10) - NB10
;*                  - Bump up version to server
;*                  - Reduce POST interval to 4 minutes for testing 
;* 
;* 
;* 
;* 
;* 
;* 
;* 
;* 20(23)/(11)/(01) - NB01
;*                  - Bump up version to server
;*                  - Instead of just waiting for 60s and then trying once rather try multiple times, like it was, but add a limit rather than just keeping on trying
;* 
;* 20(23)/(10)/(31) - NA31
;*                  - Bump up version to server
;*                  - Once the cell module has powered up, then wait 60s before telling it to do stuff on the network
;* 
;* 20(23)/(10)/(23) - NA23
;*                  - Bump up version to server
;*                  - Increase the HTTPaction time out from 5s to 90s
;* 
;* 20(23)/(09)/(15) - N915
;*                  - Bump up version to server
;*                  - See if it is possible to perform some averaging on the wind speed samples, instead of just looking for the peak in the sampling window
;*                    - If I look at the code for the case where the timer overflows the FirstPass flag must be set again, otherwise the next pulse will generate an invalid wind speed
;*                      which could be exceptionally high!
;* 
;* 20(23)/(06)/(07) - N607
;*                  - Bump up version to server
;*                  - Refresh my memory on how the wind speed sampling works
;*                  - For starters include Gust1 in the report to the server
;*                    - It was omitted because it is where the current Gust high is being accumulated, but by double reading it I can prevent high byte low byte mismatch errors
;*                  - Make the same change for WindSpeed1
;*                  - See how often we sample the wind speed
;*                    - I think it's about once every 4 minutes
;*                      - Yes, more or less, it is for 30s every 256s which is 4 minutes 16 seconds
;*                  - Program FLTA for testing
;*                    - I am happy for now
;*                  - Remember to comment out the debugging label for shipping to Danny
;* 
;* 20(23)/(03)/(14) - N314
;*                  - Bump up version to server
;*                  - NEWB has batteries which measure 3V6, which is below 3V* and yet it is reporting 0xE1 to the server 
;*                    - I vaguely remember a USBAlert resistor mod, but can't find any record of that and my PCB matches the values in the circuit diagram,
;*                      so I am going with it is something I considered and never did - maybe I just revised thresholds and ADC references
;*                  - I see there are some lines starting the ADC in the timer interrupt, but the interrupt never actually reads the ADC result!
;*                    - These could be causing problems in the in line code to read the ADC, so I have removed them, but seriously wonder if they
;*                      are the real reason that NEWB is reporting or is it just tolerances in the sensing path?
;* 
;* 20(23)/(02)/(23) - N223
;*                  - Bump up version to server
;*                  - The testing is complete, but Danny wants to change the kick in threshoild from 0xE5 to 0xE3
;*                  - Build a package and send it to Danny
;*                  - Oops nearly forgot to set it back to default unit name!
;*                  - Build again
;* 
;* 20(23)/(02)/(14) - N214
;*                  - Bump up version to server
;*                  - I expected the packets overnight to be twice the size because we report half as often, but they are not
;*                    - That's because the transmission timer also controls how often SnapShots get logged to EEPROM!
;*                  - The reporting only returned to normal at 07H00 instead of 05H00 as expected 
;*                    - The NightMode code looks good to me, so I am going with the extension was due to a NAKDelay, but will keep monitoring this        
;*                  - Change the transmission delay logic, so that we keep logging data every 12 minutes and only the transmission is delayed
;*                  - Add hysteresis to the battery voltage, so that we cut out at 3V8ish and only come back on at 3V9ish
;*                  - Change NightMode_Start to 11H00 for testing and program the rain gauge 
;*                    - Monitor the POSTing on the server 
;*                  - Set NightMode_Start back to 19H00
;*                  - Check the NightMode_End code again
;*                    - Found the mistake = copied and pasted and forgot to edit NightMode_Start to Nightmode_End
;*                  - Program the rain gauge
;*                  - Cover the solar panel to test the low voltage cut out and recovery hysteresis
;*                    - This may take a day or 2 to test
;* 
;* 20(23)/(02)/(13) - N213
;*                  - Bump up version to server
;*                  - Check that the voltage is above 3V8 before POSTing to the server
;*                    - Add build switch DoNotPostBelow3V8
;*                      - If it exists then:
;*                        - Queue Event_SampleBatteryVoltage when requesting a POST
;*                        - Check the battery voltage before switching to the GSM state machine 
;*                          - 4V04 = 0xE8
;*                          - 3V76 = 0xDF
;*                  - POST to the server half as often at night
;*                    - For starters let's call night between 19H00 and 05H00 
;*                    - Add build switch NightMode
;*                      - If it exists then:
;*                        - Check SecondsOffset against NightMode_Start and NightMode_End and extend delay if it is night
;*                  - If a POST is unsuccessful, then delay longer than usual before attempting to POST to the server again
;*                    - Add build switch NAKDelay
;*                      - If it exists the:
;*                        - Extend delay before attempting to POST again
;*                  - Program for FLTA and let me test it
;* 
;* 20(23)/(02)/(07) - N207
;*                  - Bump up version to server
;*                  - Enable BOR and set it to 2V85
;* 
;* 20(22)/(11)/(01) - MB01
;*                  - Bump up version to server
;*                  - Change power up so that if the USB is plugged in it goes to the Comms state machine first, rather than the GSM state machine 
;* 
;*                  - M326
;*                  - M325 
;* 
;* 20(22)/(03)/(24) - M324
;*                  - Bump up version to server
;*                  - Adjust the RainTickCompensationTime in the code for the GSM state machine
;*                  - See how I can verify the operation of the code   
;* 
;* 20(22)/(03)/(23) - M323 
;*                  - Bump up version to server
;*                  - Add rain tick compensation 
;*                    - This is going to impact the rain tick lockout in that now I will need to look for a value rather a flag being set
;*                    - The rain tick lockout time while the RainGuage state machine is running in low power mode is 250msec
;*                    - The rain tick lockout time while the GSM state machine is running is high speed mode is only 189msec
;*                      - I cannot expend real computing time doing proper maths to compensate, so the approximation I am using is /16*12, it sounds wrong if
;*                        you look at initially but because 189msec is quicker than 250msec we accumulate more counts in any given time period, which must be
;*                        reduced to arrive at a similar number to the 250msec number!
;*                    - See if I have space to create the compensation table in EEPROM and then copy it to RAM for speed reasons
;*                      - Yes, so create the table and copy it over to RAM
;*                    - Change the code for the RainGuage state machine to include this rain tick compensation now
;*                    - Change the code for the GSM state machine to include this rain tick compensation
;* 
;* 20(22)/(03)/(16) - M316 
;*                  - Bump up version to server
;*                  - Buffer the humidity and temperature and then report the latest good reading 
;*                    - Do we have space for 4 buffers
;*                      - Yes and 6 buffers 
;*                        - Yes, OK let's see what time frame 6 buffers gives us 
;*                          - (6+1)*256s = 1792s = 29m52s which is about 30 minutes, so that seems like a reasonable time
;*                    - Shuffle the buffers down and then populate with the new value when reading the sensor 
;*                    - Intervene if necessary
;*                    - Start testing
;*                      - I need to initialise the buffers
;* 
;* 20(22)/(01)/(07) - M107 
;*                  - Bump up version to server
;*                  - The old wind speed reading, sort of correlates with the new wind speed reading, but sometimes seems very low 
;*                    - I am not taking the highest of the samples but just reporting the current sample, which could lead to errors as the 
;*                      wind speed sample event can be interleaved with other events, so the snapshot could run in between!
;*                      - Follow the same strategy as for the new wind speed reading, but in this case take the highest instead of the lowest
;* 
;* 20(22)/(01)/(03) - M103 
;*                  - Bump up version to server
;*                  - Swap SnapShot order, so that SanpShot with the time and date stamp arrives at the server first
;*                    - This is so that the time and date stamp is available when the other SnapShot arrives at the server
;*                  - Remove the max cap from the RainPulse
;*                    - Of no real significance but this question keeps coming up and I am tired of answering it
;* 
;* 20(21)/(12)/(07) - LC07
;*                  - Danny is going with the Indian team to manage the APP and the server and wants some changes to the way data is POSTed 
;*                    - In the big picture:
;*                      - See what the 10 in the last byte of the second SnapShot is all about
;*                        - It is just a hard coded 10, I suspect it is a remnant from a very early version where we possibly
;*                          had 10 bytes free in this second SnapShot
;*                          - Renumber it appropriately for the number of bytes we have free
;*                      - Remove the individual rain ticks and only accumulate and report the total 
;*                      - Remove the daily log POSTs, which means I will need to add a full time and date stamp to the SnapShot
;*                    - Now do the nitty gritty to get the big picture implemented
;*                      - Remove the individual rain tick
;*                      - It is no longer necessary to report the RainPuleTimeLost, so remove that as well
;*                      - No longer report the garbage flags 
;*                      - Remove the code which writes the daily HiLo log event to the EEPROM, but leave all the support code in place to keep the system running
;*                      - Add a proper date and time stamp to the second SnapShot packet
;*                        - As the only events running now are the SnapShots and there are no rain ticks being recorded the timing is much more relaxed
;*                          and I can simply read the RTC without splitting the read over multiple state
;* 
;* 20(21)/(11)/(10) - LB10
;*                  - I didn't finish verifying the roaming code last time, because of tweaking the 
;*                    wind speed calibration, so carry on with that
;* 
;* 20(21)/(11)/(03) - LB03
;*                  - Verify the roaming code from LA22
;*                  - Tidy up all WIP code for things that are no longer required
;* 
;* 20(21)/(10)/(21) - LA22 roll forward and carry on
;*                  - Add roaming to network registration code
;*                    - I added this because Danny was messing around with enabling the roaming on the SIMs,
;*                      but if the unit won't recognise a roaming connection it doesn't help!
;*                  - Carry on figuring out how to extract the bundle value from the SIM card
;* 
;* 20(21)/(10)/(21) - LA21
;*                  - Bought an MTN SIM in Edenvale and RICAed it 
;*                    - Put some data in it and see if it works in the rain gauge
;*                      - Yes, it does
;*                  - Look through the list of things Jacques send last week and see what I can resolve from my side
;*                    - Parse the time zone from the network time and add it to the second snapshot 
;*                      - Test
;*                        - I can see the 8 I expected in the right place
;*                  - Jacques wants the cellphone number      
;*                    - I can extract it with AT+CIMI, but it is a waste to include it in every snapshot
;*                      - So I need to find a way to periodically extract it and a way to send it to the server
;*                        - Maybe a third snapshot that doesn't get sent to the server every time, like the other snapshots 
;*                  - Carry on figuring out how to extract the bundle value from the SIM card
;* 
;* 20(21)/(10)/(13) - LA14 (rolled forward)
;*                  - Carry on with extracting bundle value and MTN SIM issues  
;* 
;* 20(21)/(10)/(13) - LA13
;*                  - So we have a unit where the clock stops ticking and the unit freezes and we have units
;*                    in the field which freeze
;*                    - Add a flag to re-direct the execution when it fails, so that I can read out the clock
;*                      registers to try seeing what has happended 
;*                      - The CH, (Clock Halt), bit in register 0 is set 
;*                      - If I halt the debugger it still happens, so I can rule out a code issue!
;*                        - Which unfortunately makes it a hardware issue! 
;*                          - Try removing the filter capacitor on the rain pulse input, maybe it is making the  
;*                            voltage swing negative?
;*                            - Now I am unable to make it fail
;*                            - Program with L915 and see if Danny can get the clock to stop
;*                    - Add a gaurd timer to recover, just in case there is something else
;*                      - Use the WDT which varies from 3.5msec to 4.7msec 
;*                      - Making the postscaler 512 means 1.792s to 2.4064msec
;*                        - So I need to issue a CLRWDT timer command at least once every 1.7s to keep it alive
;*                      - Test this code thoroughly because there 3 loops that the code lives in: 
;*                        - The rain gauge state machine
;*                        - The comms state machine
;*                        - The GSM state machine
;* 
;* 20(21)/(09)/(29) - L930
;*                  - See if I can figure out why the MTN SIMs aren't working in the system
;*                    - Check to see if we need different settings?
;*                    - Keep in mind we need a mechanism for extracting the remaining data bundle from the SIM   
;* 
;* 20(21)/(09)/(29) - L929
;*                  - Verify the rain tick reporting code I did last week, so that we can confirm the number of rain pulses 
;*                  - It works, but it gets confusing when the unit switches to the GSM state machine and stops reporting ticks,
;*                    so add a character to announce the fact
;*                  - Release this to Danny for testing only (*** NOT FOR RELEASE ***)
;* 
;* 20(21)/(09)/(22) - L922
;*                  - I need a way of verifying the rain pulses against the server
;*                    - I am considering using the LiveDebug feature and recording the output in RealTerm and then 
;*                      searching for the RainPulseEvents 
;*                    - It looks like I won't even let the GSM state machine run, so I am going to have to check/resolve that 
;*                      - Yes, because otherwise it thinks the PC wants to talk to it and every second it will want to FLUSH
;*                        the EEPROM, so I am going to have to add code to the FLUSH routine to only FLUSH for an SMS if the
;*                        LiveDebug is enabled
;*                        - Ah, I see it is actually already implemented like this :-)
;*                      - Maybe I have to make a special switch that only reports the rain pulses to keep the "noise" down
;*                        - Problem is it was designed to be noisy and it isn't easy to quickly change that behaviour 
;*                          - But, there has to be a simple way!  
;*                            - There always is :-)
;*                      - Test to see that I get debug data for the rain pulses and that the unit reports to the server
;*                      - The debug port cannot report data while the GSM state machine is running, so I will have to
;*                        report all those pulses when I return to the main event state machine
;*                        - Check to see that I am recording rain pulses while in the GSM state machine 
;* 
;* 20(21)/(09)/(15) - L915
;*                  - Once again I am back trying to set the RTC from the network time  
;*                    - We are no longer needing to receive SMSes, so we no longer need the slow clock to put the unit to sleep, we simply switch it off
;*                      - So use that infrastructure for at+clts=1
;*                        - And add the code to save that setting to the start up profile, because it doesn't happen automatically!
;*                    - Add the command to read the time, but don't parse it for now, just look for the OK at the end and once
;*                      I can see the response I want on RealTerm then I will worry about parsing it
;*                      - Figure out how to parse responses again
;*                  - Add a tolerance to the minutes so we don't set the clock all the time
;*                  - Run some tests
;* 
;* 20(21)/(09)/(08) - L908
;*                  - LEON and JACQ are both hanging up and they are on different sites, so that rules out the GSM network       
;*                    - Set the clock to around 06:51 and force the SprayingIntervalTimer to 2 and see if I can make my unit hang up in order to debug it
;*                      - No it POSTED at 07:03 - the DEAD and the FACE packets as it is supposed to
;*                    - Set the clock to 06:49 and force the SprayingIntervalTimer to 2 and see if it fails then 
;*                      - Nope
;*                    - Set the clock to 06:42 and reduce the SprayingIntervalTime from 12 to 3 minutes 
;*                      - So now it hung up      
;*                      - It is 11H00 in the morning, so it shouldn't be server related to 07H00 in the morning
;*                      - Let's see if I can debug this without it going away!
;*                        - The clock rolled over 808s ago = 13m46s which seems about right, but there was no daily log to the server
;*                        - The SprayingIntervalTimer is set to 4446s, but it should never be more than 180 in this build
;*                          - If it rolled over to 0xFFFF it would take 16.96 hours to get to 4446, so that didn't happen, but something set it incorrectly
;*                        - Analyse the event queue to see if that helps me at all
;*                          - Nope, the DetermineWindDirection event is running and it re-queues itself to allow other events to be processed, so the
;*                            event queue is just full of these events
;*                        - The WindSpeedTimer is set to 86421 but the clock rolls over to 0 at 86400, so the DetermineWindDirection event will never terminate
;*                          - Let's see if the SendSMS flag is set, which would indicate that the daily log did queue and process, but because the event queue  
;*                            never empties out the GSM state machine cannot start up
;*                            - Yes, I am excited because it is set, so fixing this problem with the WindSpeedTimer should prevent this hang up from happening
;*                    - So now it POSTed the daily log and then stopped posting SnapShots
;*                      - This is the issue with the SprayingIntervalTimer being set incorrectly
;*                        - In this case it is 21703    
;*                          - See if I can figure out how this is happening    
;*                            - I have already checked paging     
;*                            - It seems to be good with the SnapShot events
;*                            - It seems to be corrupted by the DailyLog event
;*                              - Let's break at various points in the DailyLog to try narrowing it down
;*                                - When I read the RTC I save the seconds in Seconds, (a constant), instead of RTC_Seconds, (a variable)
;*                    
;* 20(21)/(09)/(02) - L902
;*                  - Resolve issues with the retry counters
;*                    - Found 2 semi-tombstones on my PCB
;*                  - Run some tests with Jacques on the server 
;*                  - Build releases for Danny
;* 
;* 20(21)/(09)/(01) - L901
;*                  - The SnapShot lockout seems to be making the unit hang up
;*                    - It seems like if the last SnapShot is POSTed to the server prior to 07H50 it keeps working, but if it happens
;*                      after 07H50 then the unit hangs up and needs to be reset
;*                    - Remove all the clock stretching code as none of the devices use clock stretching  
;*                    - Run some tests
;*                  - Roll forward to L902 and bring in the retry code from L826  
;* 
;* 20(21)/(08)/(25) - L825
;*                  - Make sure I am synchronised with the version Danny is running
;*                  - During the week the unit failed to POST a DailyLog and so all todays data ended up in yesterday 
;*                    - It is imperitive that the DailyLog gets queued
;*                      - The failure mechanism is:
;*                        - The SecondsOffset is sitting at let's say 86123 and a SnapShot gets queued 
;*                        - The unit goes and POSTs the Sanpshot to the server but while it is doing this the time rolls past 07H00, so now
;*                          when we return to the Event State Machine the SecondsOffset gets calculated from the real time clock and is sitting
;*                          at a very low value let's say 345
;*                        - So the SecondsOffset never rolled over in the Event State Machine and therefore the DailyLog was never queued
;*                      - The solution is to block SnapShots for a time period before the roll over for the DailyLog, so that there is a better chance
;*                        of the unit not being busy POSTing when the time rolls past 07H00 
;*                        - Let's try 10 minutes for starters and see if that mostly works, but if it doesn't there are bigger issue
;*                        - Test 
;*                  - Verify that the rain pulses are debounced, (locked out)
;*                    - TMR4 seesm to be used for some kind of PWM, but I think these are legacy instructions because RC2 is CCP1 and it is connected to the EE_WP
;*                  - Capture rain pulses which occur while we are in the GSMStateMachine and report them to the server
;*                    - Manage what happens if we require more than 1 LostRainPulseTime event when exiting the GSM state machine
;*                  - Add the RainPulse to the second SnapShot 
;* 
;* 20(21)/(08)/(18) - L818
;*                  - We are back to setting the clock from the network
;*                    - Been here a few times, but always get diverted, hopefully I get it done now
;*                      - See if I can just mod a few commands to test this without actually having to write code, but that may still be the easiest!
;*                        - SlowClock and SelectTextMode can be pressed into use for this test
;*                    - Interrupted again, because of Danny's unit repeatedly POSTing the same packet over and over 
;*                      - See items resolved L820 for details of the solution
;* 
;* 20(21)/(08)/(10) - L810
;*                  - Averaging the wind over 30s is giving very low readings, because even in reasonable winds, it 
;*                    does not blow consistently over the 30s sample!
;*                    - See if I can use TMR3 to measure the fastest revolution in that 30s sample and send it to the server as well
;*                      - The range we would need to measure is from 10msec to 100msec per revolution
;*                        - Times longer than 100msec will be treated as 0=no wind
;*                      - Let's see what we can do with the settings for TMR3 
;* 
;* 20(21)/(08)/(07) - L807
;*                  - Plug the example result for the humidity conversion in the datasheet into my code and see that my conversion routine calculates it correctly:
;*                    - 0x6352 should give me 42.49% so I must get either 42 or 43 
;*                      - Yes it gives me 42
;*                    - Build myself a stand alone version and see if the 42 makes it way to the server
;*                      - It does
;*                  - So I guess that means I must recheck the code to read the humidity from the chip again 
;*                    - The start conversion for the humiditz is not correctlz linked in
;*                  - Test 
;*                  - Package and send to Danny
;* 
;* 20(21)/(08)/(05) - L805
;*                  - Danny keeps wanting features so add them to the issue list, so that I don't loose them
;* 
;* 20(21)/(08)/(04) - L804
;*                  - Check out the humidity code for Danny
;*                    - Yes he is correct there is a problem, I am starting a temperature conversion instead of a humidity conversion
;*                      and then using that result in the humidity calculation
;*                  - Let's run some tests and see
;*                  - Build and send to Danny for field testing
;* 
;* 20(21)/(07)/(29) - L730
;*                  - Allow other events to queue inbetween while running the 30s WindSpeed sample 
;*                  - Find the high from the last 4 readings to send to the server
;*                  - Let's run some tests and see
;*                  - Build and send to Danny for field testing
;* 
;* 20(21)/(07)/(28) - L728
;*                  - I want to swap the pins for the wind speed and wind direction around in order to use TMR0 as a counter to count the anemometer rotations in a fixed time   
;*                    - See what TMR0 is currently used for and if this apprach will even be feasible
;*                      - In X_GSM_SendDataWait it generates a 1msec delay after the external EEPROM is powered up
;*                      - And the same again in OpenExternalEEPROMforReading
;*                      - In PS_EC_ExternalEE_Write1 it is called 5 times to generate a 5msec delay for the external EEPROM write to execute
;*                    - See how many timers this device has and how they are utilised:  
;*                      - It seems to have 3 * 8-bit and 4 * 16-bit timers available
;*                        - T0 - currently allocated to generating 1msec in line delays
;*                        - T1/T3/T5
;*                          - T1 - delays in the EVENT state machine
;*                          - T3
;*                            - In the EventStateMachine it determines the PWM for the wind direction sensor, (as of L810 it also measures the wind speed revolution time)
;*                            - In the GSMStateMachine it does rain pulse filtering, (lock out), in the EventStateMachine = 11059200Hz - (only 190msec)
;*                          - T5 - 1msec delay for HighSpeed routines
;*                        - T2/T4/T6
;*                          - T2 - delays in the EVENT state machine
;*                          - T4 - rain pulse filtering, (lock out), in the EventStateMachine = 31250Hz - 250msec
;*                          - T6 - regulates the transmission of data from the transmit buffer to the UART
;*                      - So let's move the 1msec time delay from T0 to T5 and send Danny code for parallel testing
;*                        - It doesn't seem to be aware of the oscillator speed and I suspect it appears to be used in both HighSpeed and LowSpeed
;*                          - Verify this 
;*                            -           X_GSM_SendDataWait - HighSpeed this is part of the GSM state machine
;*                            - OpenExternalEEPROMforReading - HighSpeed this is used in both the GSM state machine and the USB comms state machine
;*                            -      PS_EC_ExternalEE_Write1 - HighSpeed this is part of the USB comms state machine
;*                          - FALSE, it is only used in HighSpeed, so it doesn't need to be aware of the oscillator speed
;*                  - L729    
;*                  - Implement the new code for the WindSpeed measurement
;*                    - Great plan except it seems like I use the CCP5 functionality on RA4 for the wind direction, so swapping it over to RB2 might not be
;*                      as feasible as I thought it would be!
;*                      - If I am very careful, I could enable the high priority interrupt and count these events there in pretty much the same way, but
;*                        I would need to ensure that this is the only interrupt I am servicing here and none of the GSM or other interrupts!!!
;*                        - See what HighPriority interrupts we have running: 
;*                          - It is the transmit and receive interrupts
;*                            - _RC1IE gets enabled in SwitchToGSM and SwitchToComms
;*                            - _TMR6IE gets enabled in 
;*                          - INTCON gets configured in SwitchToGSM and SwitchToComms and gets cleared in SwitchToRainGauge   
;*                          - So add code to ProcessHighPriorityInterrupts to check if the interrupt is enabled before checking the flag 
;*                          - This all looks like it wants to work well, but needs refining    
;*                            - Allow other events to queue inbetween while running the 30s WindSpeed sample 
;*                              - Change the way I time the 30s in order to allow other events which require Timer 1
;*
;* 20(21)/(07)/(23) - L723
;*                  - Fix up the linking in the SHT20 code where the WindDirection is skipped if the SHT20 fails
;*
;* 20(21)/(07)/(22) - L722
;*                  - See why the battery voltage isn't sampling properly  
;*                    - The range was only changed where the device was detected not the battery samples
;*
;* 20(21)/(07)/(01) - L701
;*                  - Resolve POSTING issues with Danny and Jacques 
;*                  - Put the SHT20 code back in the build and finalise it, so that we can get live data going to the server again 
;*
;* 20(21)/(06)/(30) - L630
;*                  - Build for the AHT10 while I add the code for the 15 minute POST interval and test it  
;*
;* 20(21)/(06)/(23) - L623
;*                  - Bring over the POST2Server code I added to a version for Jacques for testing
;*                  - Test the new SHT21 Danny sent yesterday
;*                    - No SHT21, but there is an SHT20 and the comms protocol and commands are identical
;*                    - Put on a connector and let's run the debugger and see what we get with this chip
;*
;* 20(21)/(06)/(17) - L618 rolled forward
;*                  - Write code for the SHT21 sensor Danny wants to compare to the AHT10
;*                    - Let's just write simple linear code to get the chip talking and then I 
;*                      can split it up into the state machine to give everything a chance to work
;*
;* 20(21)/(06)/(17) - L617
;*                  - We have V0202 PCBs now, so let's bring up a PCB and test it                      
;*                    - The wind speed is not functional in this code yet, so bypass it for now
;*                    - Check the port assignments
;*                    - Build the code and program
;*                    - Assign it an ID and set the time
;*                    - Verify the pins on the external temperature sensor 
;*                      - Ah ha, new sensor - let's ask Danny for an old one for the initial test
;*                    - Let's see if it logs on to the server
;*                      - It isn't seeing the GSM module
;*                        - Power transistor not properly soldered 
;*                  - Test the other V0202 PCB 
;*                    - Make this a replacement for LEON
;*
;* 20(21)/(06)/(09) - L609
;*                  - Hook up the wind speed pickup PCB
;*                  - See if the GSM modem will work with the battery protection chip
;*                    - Doesn't look like it, so short it with the jumper
;*                      - Nope still not working
;*                        - Roll back, yes it works, so debug
;*                          - LineBufferPointer was in the Banked page instead of the Access page!
;*                    - It works now, but what amazes me is that it has been working so far with this bug in it! 
;*                  - Now let's code up and test the wind speed 
;*                    - But first let's spin some numbers and see what sort of times we get
;*
;* 20(21)/(06)/(02) - L602
;*                  - We have wind direction and speed hardware, so let's write code for these
;*                  - Also get Danny to build up solar PCBs, so we can start testing them
;*
;* 20(21)/(05)/(26) - L526
;*                  - Check how long Event_X_WriteEEPROM_WritePage takes now that we have to verify a second read pointer
;*                    - The verification of the extra pointer seems fine, but the pause at the end seems very long 
;*                      - Not sure if it is the waiting for the write to complete or looping back for the next block
;*                        - Add in some additional LiveDebug info and narrow it down
;*                          - Also understand where the timestamps happen and how they relate to the states, because
;*                            maybe that long time actually relates to the actual writing the 8 bytes to EEPROM and not 
;*                            the waiting!
;*                          - Split the write into individual bytes instead of a block
;*                            - Not worth the risk because sub 500msec still means we can read insane rain at 800mm/hour
;*                              - So leave it the way it is
;*                  - Add the firmware version and the battery voltage to the snapshot
;*                  - Repair issue with unused table entries beeing too short!
;*                    - Was: NOP
;*                    - Should be: NOP
;*                                 NOP
;*                  - Add code to set the clock from the network
;*                    - Started, but not compleeted yet!
;* 
;* 20(21)/(05)/(19) - L520 rolled forward because of a huge change to the code
;*                  - Implement a third memroy pointer
;*                    - GSMReadPointer
;*                    - This is specifically for managing data sent to the server 
;*                    - Change all instances of the LogReadPointer to GSMReadPointer
;*                    - Add code to validate the LogReadPointer and move it forward if the LogWritePointer collides with it 
;*                    - Remember to update the non-volatile code
;*                    - Check how long Event_X_WriteEEPROM_WritePage takes now that we have to verify a second read pointer
;* 
;* 20(21)/(05)/(19) - L519
;*                  - Add a SnapShot to the logged data
;*                    - Initially I wanted to simply make it part of the QueueDailyLog event, but let's rather make a separate
;*                      SnapShot event because in planting season there are going to be SnapShots every 15 minutes,
;*                      and I definitely don't want to reset the HiLos every 15 minutes, that must only happen
;*                      once a day at 07H00
;*                      - Make a hook for a new event 
;*                        - Build the event
;*                      - For now it will simply be concatenated with the QueueDailyLog event
;* 
;* 20(21)/(05)/(12) - L512
;*                  - Changed the USBAlert_Threshold - to extend the range - to more reliably detect when a device is disconnected
;* 
;* 20(21)/(04)/(21) - L421
;*                  - The POST is happening very reliably now, but there is still no FEED event when the clock gets set!
;*                    - Let me verify that on the bench in stand alone, before I start debugging spooks!
;* 
;* 20(21)/(04)/(14) - L414
;*                  - The first 8 bytes of the FEED aren't being written into the log EEPROM reliably:
;*                    - Switch the power to the EEPROM off sooner, so that when the EEPROM event switches
;*                      it back on a longer period of time has elapsed
;*                  - Bring up the LiveDebug code, although this won't help me debug the FEED issue, because
;*                    with live debug enabled I can't use the USB to set the clock, which then triggers the
;*                    FEED log, but it will help me ensure the integrity of the rest of the code
;*                  - Start bringing in the SMS code, first of all let's detect the fact that we have an SMS 
;*                    pending in the GSM module
;*                  - In the temperature routine, if I bring the subtraction back here, from the PC, then how do we
;*                    change the maths routines to manage the negative numbers
;* 
;* 20(20)/(12)/(02) - KC02
;*                  - Carry on bringing up the code to queue the daily log
;*                    - Load the event into the queue when 86400 seconds are reached
;*                      - Trace it through to see where it vanishes too 
;*                        - There are issues with the FVR, so resolve them 
;* 
;* 20(20)/(11)/(25) - KB25
;*                  - Last week I was struggling to get readings from the AHT10
;*                    - Let's reflow the AHT10 first
;*                      - Still the same
;*                    - Try reading the AHT with some stand alone code, to make sure the I2C routines and the hardware
;*                      are all good, then once we have this we can see what the problem with event state machine is
;*                      - I can read it successfully with this stand alone code
;*                    - Check OSCCON    
;*                      - Frequency is set to 250kHz because OSCCON is different on this device!
;*                        - So the times are all wrong for the AHT10 conversion delays
;*                        - Set the frequency to 31.25kHz 
;*                    - Check TMR1 and TMR2 config for this device
;*                      - All good
;*                    - Resolve porting issue with TemperatureHi
;*                    - Test 
;*                    - The determine HiLo event code is now working
;*                  - Bring up the WriteEEPROM event next
;*                    - But first I need to bring up the reed switch input, so that I can generate data to write away
;*                    - The port toggles between 2V97 and 4V instead of 0V and 4V
;*                      - Check internal pull-ups
;*                        - Switch the one on INT1 off
;*                    - Resolve issue with the WriteEEPROM event dispatcher porting    
;*                    - It seems to be working, but until I can read the EEPROM I won't know for sure
;*                  - Bring up the RefreshNV event
;*                    - Figure out where it gets triggered from
;*                      - In VerifySettings, so let's bring that up first
;*                        - Not here yet, so port it over
;*                        - Initialise VerifySettings_State to 0
;*                    - Resolve multiple instances of dispatcher porting issues where PCLATH was not loaded   
;*                    - Verify that the RefreshNV event and VerifySettings subroutine are working
;*                      - Yes
;*                  - Bring up the code to queue the daily log
;*                    - Load the event into the queue when 86400 seconds are reached
;* 
;* 20(20)/(11)/(18) - KB18
;*                  - Carry on porting over the working code from the stand alone rain gauge
;* 
;* 20(20)/(11)/(11) - KB12
;*                  - Most of the modem commands for talking to ther server have been implemented, but now I need some real
;*                    data to send to the server, so let's port over the working code for the rain gauge now 
;* 
;* 20(20)/(11)/(11) - KB11
;*                  - This is the start of the version which will communicate with the server
;*                    - Start implementing the GSM states required to do the POST
;* 
;* 20(20)/(11)/(04) - KB04
;*                  - This version sends an SMS at 07H00, 13H00, 19H00 and 01H00 and goes to sleep instead of powering the
;*                    modem down to get an idea of the battery life we can expect when the unit is in spraying mode
;*                  - Polish up the code
;*                  - Do an accellerated test at x360
;*                    - It took more than 4 minutes to SMS me
;*                      - 360 is greater than 255!
;*                        - Effective value is 104, so it is correct
;*                    - Set 4, so that it sends an SMS every 6 hours for the test 
;* 
;* 20(20)/(10)/(07) - KA07
;*                  - This version sends an SMS at 07H00 every morning to get an idea of the battery life we can expect 
;* 
;* 20(20)/(07)/(08) - K708
;*                  - Create a skeleton in order to get the GSM module sending SMSes
;* 
;******************************************************************************
;
#define VersionYear     'N'
#define VersionMonth    'B'
#define VersionDayTens  '5'
#define VersionDayUnits '1'
;
#define LogEvent_HiLo              b'10100110' ;A6
#define LogEvent_RainPulse         b'11000110' ;C6 & C7
#define LogEvent_RainPulseTimeLost b'11010100' ;D4 & D5
#define LogEvent_GarbageFlags      b'11100100' ;E4
#define LogEvent_SnapShot          b'11110110' ;F6 
;
; To be implemented:
;
#define LogEvent_SIMinfo             xxxxxxxx  ;?? 
; - The intention is to simply log the cell phone number, the bundle value and any other information that may periodically
;   need to be reported to the server in the EEPROM and then simply let the existing code sent it to the server with the
;   rest of the log information. But it will have to be recorded somewhere in memory because the GSM state machine doesn't
;   have the functionality to add to the log.
;
;#define BuildForProgrammer
#define BuildForBootLoader
;
#define UsingICD
;#define Debugging
;#define ForceColdStart
;
;#define AcceleratedTime
#define AcceleratedTime_Adjustment 1 ;255 max
;
#define RainTickVolume 1189
;
#define Retries (3-1)
;
; N213 build switches
;
#define DoNotPostBelow3V8
#define BatteryThreshold_KickOut 0xE1
#define BatteryThreshold_KickIn  0xE3 ;0xE5
;
#define NightMode
#define NightMode_Start 19
#define NightMode_End   5
#define NightMode_POSTingDelayTC 2
;
#define NAKDelay
;
#define WindSpeedFactor      0x78
#define WindSpeedFactorH     0xED
#define WindSpeedFactorHH    0xDE
#define WindSpeedFactorHHH   0x01
#define WindSpeedFactorHHHH  0x00
;
              include   "P18F25K22.INC"
;
              CONFIG    FOSC=HSMP, PLLCFG=OFF, PRICLKEN=ON, FCMEN=OFF, IESO=OFF
              CONFIG    PWRTEN=ON
              CONFIG    BOREN=SBORDIS, BORV=285
              CONFIG    WDTEN=ON, WDTPS=512
              CONFIG    CCP2MX=PORTC1, PBADEN=OFF ;, CCP3MX=PORTE0
              CONFIG    HFOFST=ON
              CONFIG    T3CMX=PORTC0
              CONFIG    P2BMX=PORTC0
              CONFIG    MCLRE=EXTMCLR
              CONFIG    STVREN=OFF
              CONFIG    LVP=OFF
              CONFIG    XINST=OFF
              CONFIG    DEBUG=OFF
              CONFIG    CP0=ON, CP1=ON, CPB=ON, CPD=OFF
              CONFIG    WRT0=OFF, WRT1=OFF, WRTB=OFF, WRTC=OFF, WRTD=OFF
              CONFIG    EBTR0=OFF, EBTR1=OFF, EBTRB=OFF
;
;***************************************
;
; Customisation constants
;
;***************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
;#define AHT10
#define SHT20
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
#define ClockSpeed 11059200
#define SerialSpeed1 19200
#define SerialSpeed2 9600
;
#define InitialisePORTA b'00000000'
#define InitialisePORTB b'00000000'
#define InitialisePORTC b'01000010'
#define InitialisePORTE b'00000000'
;
#define ConfigurePORTA b'00010111'
#define ConfigurePORTB b'00110111'
#define ConfigurePORTC b'10000000'
#define ConfigurePORTE b'00000000'
;
#define _PGC PORTB,6,Access
#define _PGD PORTB,7,Access
;
#define GSM_On      LATA,5,Access
#define GSM_Powered PORTA,2
#define RS232Tx PORTC,6,Access
#define RS232Rx PORTC,7,Access
;
#define ConfigureADC1       b'00001000'
#define ConfigureADC2       b'10000111'          ;0 acquisition time in hardware, it is taken care of in the software
#define ConfigureComparator b'00000111'
;
;***************************************
;
; Constants
;
;***************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
#define Same 1
#define Access 0
#define Banked 1
#define Shadow 1
#define NoShadow 0
;
#define FALSE 0
#define TRUE ~FALSE
;
Fast equ TRUE
Slow equ ~Fast
;
;***************************************
;
; MACRO: LiveDebug
;        - 4100bps for the GSM PCB
;
;***************************************
;
;#define LiveDebug_Enable
;#define LiveDebug_RainPulsesOnly
;
; 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_LostRainPulse          'r' ;This is the mechanism for reporting rain pulses recorded during GSM activity
#define LiveDebug_GSM                    'G'
#define LiveDebug_LogHiLoEvent_Start     'H'
#define LiveDebug_LogHiLoEvent_End       'h'
#define LiveDebug_SampleBattery_Start    'B'
#define LiveDebug_SampleBattery_End      'b'
#define LiveDebug_SnapShot_Start         'S'
#define LiveDebug_SnapShot_End           's'
#define LiveDebug_DWD_Start              'W'
#define LiveDebug_DWD_End                'w'
#define LiveDebug_UnknownState           '?'
#define LiveDebug_LookHere               'L'
;
LiveDebug:    macro     Trace
;
              local     LiveDebug1,LiveDebugSkip
;
        IFDEF LiveDebug_Enable
;
           IFNDEF LiveDebug_RainPulsesOnly
              LiveDebug_Build = TRUE
           ELSE  
              IF LiveDebug_RainPulse == TRUE
                 LiveDebug_Build = TRUE
              ELSE
                 LiveDebug_Build = FALSE
              ENDIF     
           ENDIF
;
           IF LiveDebug_Build == TRUE
;
              btfss     LiveDebugInitialised
              goto      LiveDebugSkip
;
LiveDebug1:
;
              btfss     _TRMT1 ;_TX1IF
              goto      LiveDebug1
              bcf       SelectGSM
              bsf       SelectUSB
              movlw     Trace
              movwf     TXREG,Access
              bsf       LiveDebug_Activity
;
LiveDebugSkip:
;
           ENDIF
;
        ENDIF   
;
              endm
;
LiveDebugEventState: macro
;
              local     LiveDebug1,LiveDebugSkip
;
        IFDEF LiveDebug_Enable
;
           IFNDEF LiveDebug_RainPulsesOnly
              LiveDebug_Build = TRUE
           ELSE  
              IF LiveDebug_RainPulse == TRUE
                 LiveDebug_Build = TRUE
              ELSE
                 LiveDebug_Build = FALSE
              ENDIF     
           ENDIF
;
           IF LiveDebug_Build == TRUE
;
              btfss     LiveDebugInitialised
              goto      LiveDebugSkip
;
LiveDebug1:
;
              btfss     _TRMT1 ;_TX1IF
              goto      LiveDebug1
              bcf       SelectGSM
              bsf       SelectUSB
              movf      EventState,W,Banked
              addlw     '0'
              movwf     TXREG,Access
              bsf       LiveDebug_Activity
;
LiveDebugSkip:
;
           ENDIF
;
        ENDIF
;
              endm
;
LiveDebugReportWord: macro
;
              local     LiveDebug1,LiveDebug2,LiveDebug3,LiveDebug4,LiveDebug5,LiveDebugSkip
;
        IFDEF LiveDebug_Enable
;
           IFNDEF LiveDebug_RainPulsesOnly
              LiveDebug_Build = TRUE
           ELSE  
              IF LiveDebug_RainPulse == TRUE
                 LiveDebug_Build = TRUE
              ELSE
                 LiveDebug_Build = FALSE
              ENDIF     
           ENDIF
;
           IF LiveDebug_Build == TRUE
;
              btfss     LiveDebugInitialised
              goto      LiveDebugSkip
;
              call      BinaryToBCD
;
              bcf       SelectGSM
              bsf       SelectUSB
;
LiveDebug1:
;
              btfss     _TRMT1 ;_TX1IF
              goto      LiveDebug1
              movf      TenThousands,W,Access
              addlw     '0'
              movwf     TXREG,Access
;
LiveDebug2:
;
              btfss     _TRMT1 ;_TX1IF
              goto      LiveDebug2
              movf      Thousands,W,Access
              addlw     '0'
              movwf     TXREG,Access
;
LiveDebug3:
;
              btfss     _TRMT1 ;_TX1IF
              goto      LiveDebug3
              movf      Hundreds,W,Access
              addlw     '0'
              movwf     TXREG,Access
;
LiveDebug4:
;
              btfss     _TRMT1 ;_TX1IF
              goto      LiveDebug4
              movf      Tens,W,Access
              addlw     '0'
              movwf     TXREG,Access
;
LiveDebug5:
;
              btfss     _TRMT1 ;_TX1IF
              goto      LiveDebug5
              movf      Units,W,Access
              addlw     '0'
              movwf     TXREG,Access
;
              bsf       LiveDebug_Activity
;
LiveDebugSkip:
;
           ENDIF
;
        ENDIF
;
              endm
;
;***************************************
;
; MACRO: SendCellMessage
;
;        This macro reads a text message from program memory and sends it to the cell serial buffer
;
;***************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
SendCellMessage macro Reference
;
              PointToMessage Reference
              call      X_SendCellMessage
;
              endm
;
;***************************************
;
; MACRO: CreateCellResponse
;
;        This macro creates a text message in program memory
;
;***************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
CreateCellResponse macro Reference,Text
;
Reference = CellResponse
CellResponse = CellResponse+1
;
              DATA      Text
              DW        0
              endm
;
;***************************************
;
; MACRO: CopyBit
;
;        This macro copies the InBit to the OutBit
;        If either Bit is Banked this macro assumes BSR is valid
;
;***************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
Wait2Ticks:   macro
;
              local     Wait2Ticks1, Wait2Ticks2
;
              bcf       Tick
;
Wait2Ticks1:
;
              btfss     Tick
              goto      Wait2Ticks1
;
              bcf       Tick
;
Wait2Ticks2:
;
              btfss     Tick
              goto      Wait2Ticks2
;
              endm
;
;***************************************
;
; MACRO: CopyBit
;
;        This macro copies the InBit to the OutBit
;        If either Bit is Banked this macro assumes BSR is valid
;
;***************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
CopyBit       macro     InFile,InBit,InPage,OutFile,OutBit,OutPage
;
              btfss     InFile,InBit,InPage
              bcf       OutFile,OutBit,OutPage
              btfsc     InFile,InBit,InPage
              bsf       OutFile,OutBit,OutPage
;
              endm
;
;***************************************
;
; MACRO: InvertBit
;
;        This macro inverts the InBit to the OutBit
;        If either Bit is Banked this macro assumes BSR is valid
;
;***************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
InvertBit     macro     InFile,InBit,InPage,OutFile,OutBit,OutPage
;
              btfss     InFile,InBit,InPage
              bsf       OutFile,OutBit,OutPage
              btfsc     InFile,InBit,InPage
              bcf       OutFile,OutBit,OutPage
;
              endm
;
;***************************************
;
; MACRO: ShortInvertBit
;
;        This macro inverts the InBit to the OutBit with the possibility of a glitch
;        If either Bit is Banked this macro assumes BSR is valid
;
;***************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
ShortInvertBit macro    InFile,InBit,InPage,OutFile,OutBit,OutPage
;
              bcf       OutFile,OutBit,OutPage
              btfss     InFile,InBit,InPage
              bsf       OutFile,OutBit,OutPage
;
              endm
;
;***************************************
;
; MACRO: DisableReceive1Interrupt
;
;        This macro saves the current state of the Receive 1 Interrupt and then disables it
;
;***************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
DisableReceive1Interrupt macro
;
              local     DisableReceive1Interrupt1
;
              CopyBit   _RC1IE,SaveRC1IE
;
DisableReceive1Interrupt1
;
              bcf       _RC1IE
              btfsc     _RC1IE
              goto      DisableReceive1Interrupt1
;
              endm
;
;***************************************
;
; MACRO: RestoreReceive1Interrupt
;
;        This macro restores the original state of the Receive 1 Interrupt
;
;***************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
RestoreReceive1Interrupt macro
;
              CopyBit   SaveRC1IE,_RC1IE
;
              endm
;
;***************************************
;
; MACRO: DisableReceive2Interrupt
;
;        This macro saves the current state of the Receive 2 Interrupt and then disables it
;
;***************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
DisableReceive2Interrupt macro
;
              local     DisableReceive2Interrupt1
;
              CopyBit   _RC2IE,SaveRC2IE
;
DisableReceive2Interrupt1
;
              bcf       _RC2IE
              btfsc     _RC2IE
              goto      DisableReceive2Interrupt1
;
              endm
;
;***************************************
;
; MACRO: RestoreReceive2Interrupt
;
;        This macro restores the original state of the Receive 2 Interrupt
;
;***************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
RestoreReceive2Interrupt macro
;
              CopyBit   SaveRC2IE,_RC2IE
;
              endm
;
;***************************************
;
; MACRO: DisableTimer2Interrupt
;
;        This macro saves the current state of the Timer 2 Interrupt and then disables it
;
;***************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
DisableTimer2Interrupt macro
;
              local     DisableTimer2Interrupt1
;
              CopyBit   _TMR2IE,SaveTMR2IE
;
DisableTimer2Interrupt1
;
              bcf       _TMR2IE
              btfsc     _TMR2IE
              goto      DisableTimer2Interrupt1
;
              endm
;
;***************************************
;
; MACRO: RestoreTimer2Interrupt
;
;        This macro restores the original state of the Timer 2 Interrupt
;
;***************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
RestoreTimer2Interrupt macro
;
              CopyBit   SaveTMR2IE,_TMR2IE
;
              endm
;
;***************************************
;
; MACRO: DisableInterrupts
;
;        This macro disables the High Priority Interrupt
;
;***************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
;
DisableInterrupts macro
;
              local     DisableInterrupts1
;
DisableInterrupts1
;
              bcf       _GIEH
              btfsc     _GIEH
              goto      DisableInterrupts1
;
              endm
;
;***************************************
;
; MACRO: RestoreInterrupts
;
;        This macro restores the High Priority Interrupt
;
;***************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
RestoreInterrupts macro
;
              bsf       _GIEH
;
              endm
;
;***************************************
;
; MACRO: CreateMessage
;
;        This macro creates a text message in program memory
;
;***************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
CreateMessage macro     Reference,Text
Reference     DATA      Text
              DW        0
              endm
;
;***************************************
;
; MACRO: DisplayLCDMessage
;
;        This macro reads a text message from program memory and writes it to the LCD buffer
;
;***************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
DisplayLCDMessage macro Reference
;
              PointToMessage Reference
              call      X_DisplayLCDMessage
;
              endm
;
;***************************************
;
; MACRO: PointToMessage
;
;        This macro points to a text message in program memory
;
;***************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
PointToMessage macro Reference
;
              bsf       _EEPGD
              clrf      TBLPTRU
              movlw     HIGH(Reference)
              movwf     TBLPTRH           
              movlw     LOW(Reference)
              movwf     TBLPTRL         
;
              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,PinBank,FlagFile,FlagBit,FlagBank,HistoryFile,HistoryBit,HistoryBank,TimerFile,TimerBank,TC
;
              LOCAL     WasLo,WasHi,Stable,Differs,ToggleHi,ToggleLo,DebounceEnd
;
              btfss     HistoryFile,HistoryBit,HistoryBank   ;IF !HISTORY
              goto      WasLo                    ;THEN check if still LO
              goto      WasHi                    ;ELSE check if still HI
;
WasLo         btfss     PinFile,PinBit,PinBank           ;IF !PIN
              goto      Stable                   ;THEN STABLE
              goto      Differs                  ;ELSE DIFFERS
;
WasHi         btfsc     PinFile,PinBit,PinBank           ;IF PIN
              goto      Stable                   ;THEN STABLE
              goto      Differs                  ;ELSE DIFFERS
;       
Stable        movf      TimerFile,W,TimerBank              ;IF TIMER=0
              btfsc     ZeroFlag
              goto      DebounceEnd              ;THEN go
;
              decfsz    TimerFile,Same,TimerBank           ;IF TIMER-1!=0
              goto      DebounceEnd              ;THEN go
;
              btfss     HistoryFile,HistoryBit,HistoryBank   ;FLAG=HISTORY
           IF PinLogic==PositiveLogic
              bcf       FlagFile,FlagBit,FlagBank
           ELSE
              bsf       FlagFile,FlagBit,FlagBank 
           ENDIF
              btfsc     HistoryFile,HistoryBit,HistoryBank
           IF PinLogic==PositiveLogic
              bsf       FlagFile,FlagBit,FlagBank
           ELSE
              bcf       FlagFile,FlagBit,FlagBank
           ENDIF
;
              goto      DebounceEnd
;
Differs       movlw     TC                       ;Reload debounce timer
              movwf     TimerFile,TimerBank
;                                                                     _______
              btg       HistoryFile,HistoryBit,HistoryBank   ;HISTORY=HISTORY 
              goto      DebounceEnd
;
DebounceEnd
;
              endm
;
SelectSW      macro     Case,Of,OfBank,SelectEnd,SWAFile,SWABit,SWABank,SWAState,SWBFile,SWBBit,SWBBank,SWBState,SWCFile,SWCBit,SWCBank,SWCState,SWDFile,SWDBit,SWDBank,SWDState
;
              local     SelectSWEnd
;
              movlw     Case
              subwf     Of,W,OfBank
;
              btfss     CarryFlag
              goto      SelectSWEnd
;
           IF SWAState == On 
              bsf       SWAFile,SWABit,SWABank 
           ELSE
              bcf       SWAFile,SWABit,SWABank 
           ENDIF
;
           IF SWBState == On 
              bsf       SWBFile,SWBBit,SWBBank 
           ELSE
              bcf       SWBFile,SWBBit,SWBBank 
           ENDIF
;
           IF SWCState == On 
              bsf       SWCFile,SWCBit,SWCBank 
           ELSE
              bcf       SWCFile,SWCBit,SWCBank 
           ENDIF
;
           IF SWDState == On 
              bsf       SWDFile,SWDBit,SWDBank 
           ELSE
              bcf       SWDFile,SWDBit,SWDBank 
           ENDIF
;
              goto      SelectEnd
;
SelectSWEnd
;
              endm
;
;***************************************
;
; Constants - Complete BIT locations
;
;***************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
#define _GIE INTCON,7,Access
;
#define _TMR0IF INTCON,TMR0IF,Access
;
#define _GIEH INTCON,GIEH,Access
#define _GIEL INTCON,GIEL,Access
#define _IPEN RCON,IPEN,Access
;
#define _nRBPU INTCON2,RBPU,Access
;
#define _TMR1IP IPR1,TMR1IP,Access
#define _TMR1IF PIR1,TMR1IF,Access
#define _TMR1IE PIE1,TMR1IE,Access
;
#define _TMR2IF PIR1,TMR2IF,Access
#define _TMR2IE PIE1,TMR2IE,Access
;
#define _TMR3IF PIR2,TMR3IF,Access
#define _TMR3IE PIE2,TMR3IE,Access
;
#define _TMR4IF PIR5,TMR4IF,Access
;
#define _TMR5IF PIR5,TMR5IF,Access
;
#define _TMR6IF PIR5,TMR6IF,Access
#define _TMR6IE PIE5,TMR6IE,Access
#define _TMR6IP IPR5,TMR6IP,Access
;
#define _SPEN1 RCSTA1,SPEN,Access
;
#define _TRMT1 TXSTA1,TRMT,Access
#define _TX9D1 TXSTA1,TX9D,Access
#define SerialPort1AddressByte WREG,0,Access
;
#define _ADDEN1 RCSTA1,ADDEN,Access
#define _RX9D1  RCSTA1,RX9D,Access
;
#define _RC1IF PIR1,RCIF,Access
#define _RC1IE PIE1,RCIE,Access
#define _TX1IF PIR1,TXIF,Access
#define _TX1IE PIE1,TXIE,Access
#define _RCIP  IPR1,RCIP,Access

;
#define _SPEN2 RCSTA2,SPEN,Access
;
#define _TRMT2 TXSTA2,TRMT,Access
;
#define _RC2IF PIR3,RCIF,Access
#define _RC2IE PIE3,RCIE,Access
#define _TX2IF PIR3,TXIF,Access
#define _TX2IE PIE3,TXIE,Access
;
#define _OERR1 RCSTA1,OERR,Access
#define _FERR1 RCSTA1,FERR,Access
#define _CREN1 RCSTA1,CREN,Access
;
#define _RC1MT BAUDCON1,RCIDL,Access
;
#define _OERR2 RCSTA2,OERR,Access
#define _FERR2 RCSTA2,FERR,Access
#define _CREN2 RCSTA2,CREN,Access
;
#define _RC2MT BAUDCON2,RCIDL,Access
;
#define _EEPGD  EECON1,EEPGD,Access
#define _EECFGS EECON1,CFGS,Access
#define _EERD   EECON1,RD,Access
#define _EEWREN EECON1,WREN,Access
#define _EEWR   EECON1,WR,Access
#define _FREE   EECON1,FREE,Access
;
#define _Go ADCON0,GO,Access
;
#define _INT0IF  INTCON,INT0IF,Access
#define _INT0EDG INTCON2,INTEDG0,Access
;
#define _INT1IP  INTCON3,INT1IP,Access
#define _INT1IE  INTCON3,INT1IE,Access
#define _INT1IF  INTCON3,INT1IF,Access
#define _INT1EDG INTCON2,INTEDG1,Access
;
#define _INT2IP  INTCON3,INT2IP,Access
#define _INT2IE  INTCON3,INT2IE,Access
#define _INT2IF  INTCON3,INT2IF,Access
#define _INT2EDG INTCON2,INTEDG2,Access
;
#define _CCP5IF PIR4,CCP5IF,Access
;
#define NegativeLogic 0
#define PositiveLogic ~NegativeLogic
;
#define Off 0
#define On ~Off
;
#define CarryFlag STATUS,C,Access
#define ZeroFlag  STATUS,Z,Access
;
;***************************************
;
; Constants - Timing related
;
;***************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
#define ConfigureTMR1 b'10000001'
#define ConfigureTMR2 b'00111110'
#define TC1msec 22 ;1.0185msec (22*4*8*16/11059200) ;This is the rate the interrupt fires at, but it is divided down
#define ConfigureTMR3 b'00110011'
#define ConfigureTMR3Gate b'00000000'
#define ConfigureTMR6 b'00111110'
#define TC275usec 6 ;277.7usec (6*4*8*16/11059200)
#define TC185usec 4 ;185.2usec (4*4*8*16/11059200)
#define TC92usec  2 ;92.59usec (2*4*8*16/11059200)
;
#define TC5msec 5     ;*1msec = 5msec
#define SerialOutTC 5 ;*1msec = 5msec
#define Scroll_TC 200 ;*5msec = 1s
#define Scroll_Blanking_TC 40 ;*5msec = 200msec
#define IgnitionInTC 50 ;*5msec
#define IsolatorInTC 50 ;*5msec
;
#define KeypadDebounceTC 10 ;*5msec = 50msec
#define TCFlasher 100
#define TC1Second 196 ;*5.0926msec = 1s
;
#define SerialInTC 20 ;*1s = 20s
;
#define msec 1/5
#define Seconds 1000*msec
#define Minutes 60*Seconds
;
#define BuzzerPWM 128

#define VersionBuzzerOnTC 40
#define VersionBuzzerOffTC 100
#define VersionBuzzerCount 2

#define KeypadBuzzerOnTC 20
#define KeypadBuzzerOffTC 20
#define KeypadBuzzerCount 1

#define CommsBuzzerOnTC 60
#define CommsBuzzerOffTC 20
#define CommsInitialBuzzerCount 10
#define CommsReminderBuzzerCount 3
;
;***************************************
;
; Constants - Buffer related
;
;***************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
#define Rx1BufferSize 64
#define Rx1BufferFirstLocation (Rx1Buffer&b'11111111')
#define Rx1BufferLastLocation ((Rx1Buffer+Rx1BufferSize-1)&b'11111111')
;
#define Tx1BufferSize 64
#define Tx1BufferFirstLocation (Tx1Buffer&b'11111111')
#define Tx1BufferLastLocation ((Tx1Buffer+Tx1BufferSize-1)&b'11111111')
;
#define Rx2BufferSize 64
#define Rx2BufferFirstLocation (Rx2Buffer&b'11111111')
#define Rx2BufferLastLocation ((Rx2Buffer+Rx2BufferSize-1)&b'11111111')
;
#define Tx2BufferSize 256
#define Tx2BufferFirstLocation (Tx2Buffer&b'11111111')
#define Tx2BufferLastLocation ((Tx2Buffer+Tx2BufferSize-1)&b'11111111')
;
#define LineBufferSize 128
;
#define PacketArraySize 8*16
;
#define EEPROMWriteBufferSizeInternal 128
#define EEPROMReadBufferSizeInternal 128
;
#define EEPROMWriteBufferSizeExternal 128
#define EEPROMReadBufferSizeExternal 128
;
;***************************************
;
; Derive the actual serial port 1 setup values from the customisation constants
;
;***************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
           IF SerialSpeed1 < ClockSpeed/(64*(255+1))
              ERROR "Requested serial speed 1 is too slow."
           ELSE
              IF SerialSpeed1 < ClockSpeed/(64*(1+1))  
SerialSpeed1LowTC = (ClockSpeed/(64*SerialSpeed1))-1
SerialSpeed1LowActual = ClockSpeed/(64*(SerialSpeed1LowTC+1))
                 IF SerialSpeed1LowActual > SerialSpeed1
SerialSpeed1LowError = ((SerialSpeed1LowActual-SerialSpeed1)*1000)/SerialSpeed1
                 ELSE
SerialSpeed1LowError = ((SerialSpeed1-SerialSpeed1LowActual)*1000)/SerialSpeed1
                 ENDIF
              ENDIF
           ENDIF
;
           IF SerialSpeed1 > ClockSpeed/(16*(1+1))
              ERROR "Requested serial speed 1 is too fast."
           ELSE
              IF SerialSpeed1 > ClockSpeed/(16*(255+1))  
SerialSpeed1HighTC = (ClockSpeed/(16*SerialSpeed1))-1
SerialSpeed1HighActual = ClockSpeed/(16*(SerialSpeed1HighTC+1))
                 IF SerialSpeed1HighActual > SerialSpeed1
SerialSpeed1HighError = ((SerialSpeed1HighActual-SerialSpeed1)*1000)/SerialSpeed1
                 ELSE
SerialSpeed1HighError = ((SerialSpeed1-SerialSpeed1HighActual)*1000)/SerialSpeed1
                 ENDIF
              ENDIF
           ENDIF
;
           IFDEF SerialSpeed1LowTC
              IFDEF SerialSpeed1HighTC 
                 IF SerialSpeed1LowError <= SerialSpeed1HighError
                    IF SerialSpeed1LowError < 20+1
SerialSpeed1TC = SerialSpeed1LowTC
SerialSpeed1Select = b'00000000'
                    ELSE
                       ERROR "Serial speed 1 error is greater than 2%"
                    ENDIF
                 ELSE
                    IF SerialSpeed1HighError < 20+1
SerialSpeed1TC equ SerialSpeed1HighTC
SerialSpeed1Select = b'00000100'
                    ELSE
                       ERROR "Serial speed 1 error is greater than 2%"
                    ENDIF
                 ENDIF
              ELSE
                 IF SerialSpeed1LowError < 20+1
SerialSpeed1TC equ SerialSpeed1LowTC
SerialSpeed1Select = b'00000000'
                 ELSE
                    ERROR "Serial speed 1 error is greater than 2%"
                 ENDIF
              ENDIF
           ELSE
              IFDEF SerialSpeed1HighTC
                 IF SerialSpeed1HighError < 20+1
SerialSpeed1TC = SerialSpeed1HighTC
SerialSpeed1Select = b'00000100'
                 ELSE
                    ERROR "Serial speed 1 error is greater than 2%"
                 ENDIF
              ENDIF
           ENDIF
;
;***************************************
;
; Derive the actual serial port 2 setup values from the customisation constants
;
;***************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
           IF SerialSpeed2 < ClockSpeed/(64*(255+1))
              ERROR "Requested serial speed 1 is too slow."
           ELSE
              IF SerialSpeed2 < ClockSpeed/(64*(1+1))  
SerialSpeed2LowTC = (ClockSpeed/(64*SerialSpeed2))-1
SerialSpeed2LowActual = ClockSpeed/(64*(SerialSpeed2LowTC+1))
                 IF SerialSpeed2LowActual > SerialSpeed2
SerialSpeed2LowError = ((SerialSpeed2LowActual-SerialSpeed2)*1000)/SerialSpeed2
                 ELSE
SerialSpeed2LowError = ((SerialSpeed2-SerialSpeed2LowActual)*1000)/SerialSpeed2
                 ENDIF
              ENDIF
           ENDIF
;
           IF SerialSpeed2 > ClockSpeed/(16*(1+1))
              ERROR "Requested serial speed 1 is too fast."
           ELSE
              IF SerialSpeed2 > ClockSpeed/(16*(255+1))  
SerialSpeed2HighTC = (ClockSpeed/(16*SerialSpeed2))-1
SerialSpeed2HighActual = ClockSpeed/(16*(SerialSpeed2HighTC+1))
                 IF SerialSpeed2HighActual > SerialSpeed2
SerialSpeed2HighError = ((SerialSpeed2HighActual-SerialSpeed2)*1000)/SerialSpeed2
                 ELSE
SerialSpeed2HighError = ((SerialSpeed2-SerialSpeed2HighActual)*1000)/SerialSpeed2
                 ENDIF
              ENDIF
           ENDIF
;
           IFDEF SerialSpeed2LowTC
              IFDEF SerialSpeed2HighTC 
                 IF SerialSpeed2LowError <= SerialSpeed2HighError
                    IF SerialSpeed2LowError < 20+1
SerialSpeed2TC = SerialSpeed2LowTC
SerialSpeed2Select = b'00000000'
                    ELSE
                       ERROR "Serial speed 1 error is greater than 2%"
                    ENDIF
                 ELSE
                    IF SerialSpeed2HighError < 20+1
SerialSpeed2TC equ SerialSpeed2HighTC
SerialSpeed2Select = b'00000100'
                    ELSE
                       ERROR "Serial speed 1 error is greater than 2%"
                    ENDIF
                 ENDIF
              ELSE
                 IF SerialSpeed2LowError < 20+1
SerialSpeed2TC equ SerialSpeed2LowTC
SerialSpeed2Select = b'00000000'
                 ELSE
                    ERROR "Serial speed 1 error is greater than 2%"
                 ENDIF
              ENDIF
           ELSE
              IFDEF SerialSpeed2HighTC
                 IF SerialSpeed2HighError < 20+1
SerialSpeed2TC = SerialSpeed2HighTC
SerialSpeed2Select = b'00000100'
                 ELSE
                    ERROR "Serial speed 1 error is greater than 2%"
                 ENDIF
              ENDIF
           ENDIF
;
;***************************************
;
; Constants - Serial port related
;
;***************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
#define ASCIItoBinary h'30'
#define BinaryToASCII h'30'
#define CR h'D'
#define LF h'A'
#define Tab h'9'
#define CtrlZ 26
#define QuotationMark 34
;
;***************************************
;
; Constants - LCD related
;
;***************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
;***************************************
;
; Constants - Flags
;
;***************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
#define Boolean_Interrupt              Flags0,0,Access
#define SerialBuffer1OverFlow          Flags0,1,Access
#define SaveRC1IE                      Flags0,2,Access
#define SerialBuffer2OverFlow          Flags0,3,Access
#define SaveRC2IE                      Flags0,4,Access
#define SaveGIEH                       Flags0,5,Access
#define GeneralPurposeTimer1           Flags0,6,Access
#define Flasher                        Flags0,7,Access
;
#define VNC1L_TimedOut                 Flags1,0,Access
#define SensePower                     Flags1,1,Access
#define SensePowerHistory              Flags1,2,Access
#define SaveTMR2IE                     Flags1,3,Access
#define LogData                        Flags1,4,Access
#define NewDataForSensor1              Flags1,5,Access
#define NewDataForSensor2              Flags1,6,Access
#define SyncSeen                       Flags1,7,Access
;
#define SignPresent                    Flags2,0,Access
#define SerialInTimedOut               Flags2,1,Access
#define SerialOutTimedOut              Flags2,2,Access
#define PollSign                       Flags2,3,Access
#define Sensor1DataNotProcessed        Flags2,4,Access
#define Sensor2DataNotProcessed        Flags2,5,Access
#define TransmitNewData                Flags2,6,Access
#define Tick                           Flags2,7,Access
;
#define ProcessNewDataForSensor1       Flags3,0,Access
#define ProcessNewDataForSensor2       Flags3,1,Access
#define ReflashFile                    Flags3,2,Access
#define RxAddress                      Flags3,3,Access
#define SerialBuffer1AddressByte       Flags3,4,Access
#define ReadUltraSonic                 Flags3,5,Access
#define ProcessNewFlowData             Flags3,6,Access
#define EndOfFile                      Flags3,7,Access
;
#define ESCape                         Flags4,0,Access
#define FirstPass                      Flags4,1,Access
#define DeviceCommunicated             Flags4,2,Access
#define DeviceSetClock                 Flags4,3,Access
#define LiveDebug_Activity             Flags4,4,Access
#define _ReadRTC                       Flags4,5,Access
#define DevicePresentAtPowerUp         Flags4,6,Access
#define CaptureWindSpeedAverage        Flags4,7,Access
;
#define SkipToEndOfLineNextPass        Flags5,0,Access
#define SkipToEndOfLine                Flags5,1,Access
#define RefreshSettings                Flags5,2,Access
#define ResetLoggingPointer            Flags5,3,Access
#define SendBlockToApp                 Flags5,4,Access
#define ScrollDisplay                  Flags5,5,Access
#define BreakEnable                    Flags5,6,Access
#define QueueLostRainPulses            Flags5,7,Access
;
#define PowerDown                      Flags6,0,Access
#define StorePower                     Flags6,1,Access
#define BankSwitchRequired             Flags6,2,Access
#define BatteryLow                     Flags6,3,Access
#define NewWindSampleFlag              Flags6,4,Access
#define CheckUSBAlert                  Flags6,5,Access
#define LiveDebugInitialised           Flags6,6,Access
#define Gust_FirstPass                 Flags6,7,Access
;
#define DIPSW1Pin                      DIPSwitches,0,Banked
#define DIPSW2Pin                      DIPSwitches,1,Banked
#define DIPSW3Pin                      DIPSwitches,2,Banked
#define DIPSW4Pin                      DIPSwitches,3,Banked
#define DIPSW5Pin                      DIPSwitches,4,Banked
#define DIPSW6Pin                      DIPSwitches,5,Banked
#define NoSwitch                       DIPSwitches,6,Banked,Off 
;
#define MembraneSWControlOpenPin       MembraneSwitches,0,Banked
#define MembraneSWControlClosePin      MembraneSwitches,1,Banked
#define MembraneSWBypassOpenPin        MembraneSwitches,2,Banked
#define MembraneSWBypassClosePin       MembraneSwitches,3,Banked
;
#define PollComplete                   GSM_Flags0,0,Banked
#define ConcatenatedCommands           GSM_Flags0,1,Banked
#define EOL                            GSM_Flags0,2,Banked
#define ForceToUpperCase               GSM_Flags0,3,Banked
#define AcceptQuotationMarks           GSM_Flags0,4,Banked
#define AcceptSpaces                   GSM_Flags0,5,Banked
#define CellModuleResponseTimeOut      GSM_Flags0,6,Banked
#define NoCR                           GSM_Flags0,7,Banked	   
;
#define GSM_CellModulePresent          GSM_Flags1,0,Banked	   
#define GSM_EchoOffRequired            GSM_Flags1,1,Banked
;
; Garbage flags
; - Keep them all in one byte to make a bulk test easy
;
#define EventQueueUnderFlow           GarbageFlags,0,Banked
#define EventQueueOverFlow            GarbageFlags,1,Banked
#define EEPROM_UnderFlow              GarbageFlags,2,Banked
#define EEPROM_OverFlow               GarbageFlags,3,Banked
#define ExtEE_PageAligned             GarbageFlags,4,Banked
#define ExtEE_WritePointerOutOfBounds GarbageFlags,5,Banked
#define ExtEE_ReadPointerOutOfBounds  GarbageFlags,6,Banked
#define ExtEE_MadeLoggingSpace        GarbageFlags,7,Banked 
;
           CBLOCK    0
;
              crc
              i
              cnt1
              cnt2
              cnt3
              counter_hi
              counter_lo
              flag
;
              Flags0
              Flags1
              Flags2
              Flags3
              Flags4
              Flags5
              Flags6
;
              Flags0A
              Flags1A
              Flags2A
;
              ScratchPad0
              ScratchPad1
              ScratchPad2
              ScratchPad3
              ScratchPad4
              ScratchPad5
              ScratchPad6
;
              Timer_50u
              Timer_5m
              Timer_nx5m             
;
              CharacterBuffer1
              CharacterBuffer2
;
              EEAdrs
              EEAdrsH
              EEAdrsHH
;
              I2C_Work
              I2C_BitCount
;
              RxData
              TxData
;
              DS1307_Seconds
              DS1307_Minutes
              DS1307_Hours
              DS1307_DayOfWeek
              DS1307_Days
              DS1307_Months
              DS1307_Years
              DS1307_Control
;
              AnalogueState
; 
              Binary
              BinaryH
              BinaryHH
;
              Units
              Tens
              Hundreds
              Thousands
              TenThousands
              HundredThousands
              Millions
              TenMillions
;
              CalculatorFlags
              CalculatorCount
              CalculatorX0
              CalculatorX1
              CalculatorX2
              CalculatorX3
              CalculatorX4
              CalculatorY0
              CalculatorY1
              CalculatorY2
              CalculatorY3
              CalculatorY4
              CalculatorTA0
              CalculatorTA1
              CalculatorTA2
              CalculatorTA3
              CalculatorTA4
;
              MultiByteZero
;
              Toggle ;For alternating good and bad responses  
;
              LineBufferPointer
              LineBufferCounter
              CharacterBuffer
              CharactersInBuffer
              ParameterStart
	      ParameterLength
	      PhraseNumber
	      PhraseLength
	      PhraseCounter
;
              DirectionStart
              DirectionStartH
              DirectionOn
              DirectionOnH
              DirectionStop
              DirectionStopH
;
              CheckAccessBankUsage
;
           endc
;
           IF CheckAccessBankUsage > h'60'
              ERROR "Too many file registers have been used in the Access Bank"
           ENDIF
;
;***************************************
;
; Calculator flags
;
#define CalculatorOverflow CalculatorFlags,0,Access
#define CalculatorError    CalculatorFlags,1,Access
#define CalculatorBoolean  CalculatorFlags,2,Access
#define CalculatorMulOver  CalculatorFlags,3,Access
#define CalculatorDivStore CalculatorFlags,4,Access
;
;***************************************
;
; Low power flags - separated for now
;
#define HighSpeed Flags0A,0,Access
#define AckTx     Flags0A,1,Access
#define AckRx     Flags0A,2,Access
#define SendSMS   Flags0A,3,Access
;
           CBLOCK h'60'
;
              ReFlash_BlockCounter
              ReFlash_BlockCounterH
              ReFlash_ByteCounter
              ReFlash_MemoryPointer
              ReFlash_MemoryPointerH
              ReFlash_Checksum
              ReFlash_ChecksumH
;
              DetermineHiLo_Calculator0_0
              DetermineHiLo_Calculator1_0
              DetermineHiLo_Calculator2_0
              DetermineHiLo_Calculator3_0
              DetermineHiLo_Calculator4_0
;
              RainPulseGSM_0
              RainPulseGSMH_0
              RainPulseGSMHH_0
;
              CheckBank0Usage
           ENDC
;
           IF CheckBank0Usage > h'100'
              ERROR "Too many file registers have been used in Bank 0"
           ENDIF
;
           CBLOCK h'100'
;
; START NON-VOLATILE variables
; - These variables must be in the same order as the EE_VariableName memory map
;
              ActiveBank 
              SequenceNumber
;
              FirmwareYear
              FirmwareMonth
              FirmwareDayTens
              FirmwareDayUnits
;
              PowerUps
              PowerUpsH
              Connections
              ConnectionsH
;
              BatteryVoltage
;
              LogReadPointer
              LogReadPointerH
              LogReadPointerHH
;
              LogWritePointer
              LogWritePointerH
              LogWritePointerHH 
;
              RainPulse
              RainPulseH
              RainPulseHH
;
              HumidityLo
              HumidityHi
;
              TemperatureLo
              TemperatureLoH 
              TemperatureHi
              TemperatureHiH 
;
              GSMReadPointer
              GSMReadPointerH
              GSMReadPointerHH
;
              Debug1
              Debug2
              Debug3 ;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                           ;1   
;
              Temperature                        ;2
              TemperatureH                       ;3
;
              AHT10_S                            ;4
              AHT10_H1                           ;5
              AHT10_H2                           ;6
              AHT10_HT                           ;7
              AHT10_T1                           ;8
              AHT10_T2                           ;9
;
              EventQueueAvailable                ;10
              EEPROM_Buffered                    ;11
;
              Seconds_Offset                     ;12
              Seconds_OffsetH                    ;13
              Seconds_OffsetHH                   ;14 
;
              RainPulseTimeLost                  ;15 
;
              Event
              EventQueueReadPointer
              EventQueueWritePointer
;
              EEPROM
              EEPROM_ReadPointer
              EEPROM_WritePointer
;
              EventState
;
              SaveWREG
              SaveSTATUS
              SaveFSR1L
              SaveFSR1H
              SaveFSR2L
              SaveFSR2H
              SavePCLATH
              SavePCLATU
;
              SaveHPI_FSR2L
              SaveHPI_FSR2H
;
              GSM_Flags0
              GSM_Flags1
;
              GarbageFlags
;
              DownloadPointerLo
              DownloadPointerHi
              DownloadPointerUp
;
              FlasherTimer
              OneSecondTimer
;
              _5msecTimer
;
              MultiplexingState
              MultiplexingBrightnessTC
              MultiplexingBrightnessTimer
;
              Digit1BufferA
              Digit2BufferA
              Digit3BufferA
              Digit4BufferA
;
              Digit1BufferB
              Digit2BufferB
              Digit3BufferB
              Digit4BufferB
;
              B27S_ScratchPad
;
              BuzzerOn
              BuzzerOnTC
              BuzzerOff
              BuzzerOffTC
              BuzzerCounter
;
              MessageRetries
              InitialiseRetries
;
              MessageNumber
              MessageNumberH
;
              SerialInTimer
              SerialOutTimer
;
              MessageCounter
;
              ProgramBlockUnits
              ProgramBlockTens
              ProgramBlockHundreds
;
              Rx1BufferReadPointer
              Rx1BufferWritePointer
              Tx1BufferReadPointer
              Tx1BufferWritePointer
;
              LoggingTimer
              LoggingTimerH
;
              DisplayCounter
;
              BatteryCutOutTimer
              BatteryCutOutTimerH 
;
              BCD2ASCII_Work
;
              ActiveThreshold
              ActiveThresholdH
;
              AnalogueCounter
              AnalogueTotal
              AnalogueTotalH
              AnalogueMinimum
              AnalogueMinimumH
              AnalogueMaximum
              AnalogueMaximumH
;
              PacketState
              PacketCharacter
              PacketCommand
              PacketCounter
;
              CheckSum
;
              EEPROMSaveBank
              EEPROMSequenceBank
              EEPROMSequence
              EEPROMNewBank
              EEPROMRestoreBank
              EEPROMBank0Sequence
              EEPROMBank1Sequence
;
              SBTA_Counter
              SBTA_Checksum
;
              Scroll_Digit
              Scroll_Timer
              Scroll_Passes
;
              IgnitionInTimer
              IsolatorInTimer
;
              App_Timer
              App_TimerH
;
              DisplayDisable_Timer
              DisplayDisable_TimerH
;
              ResponseTimeOut
              ResponseTimeOutH
;
              HexToASCIIScratch
              NibblesToASCIIScratch
;
              GSM_State  
              GSM_Dispatch
              GSM_DispatchH
;
	      CellModuleTimeOutTimer
	      CellModuleTimeOutTimerH
;
              RTC_Seconds
              RTC_Minutes
              RTC_Hours
              RTC_DayOfWeek
              RTC_Date
              RTC_Month
              RTC_Year
              RTC_Control
;
              GSM_Seconds
              GSM_Minutes
              GSM_Hours
              GSM_Date
              GSM_Month
              GSM_Year
              GSM_TimeZone_Sign
              GSM_TimeZone_Tens
              GSM_TimeZone_Units
;
              I2C_DelayCounter
              I2C_Count
              I2C_Data
;
              HiLoDetail1
              HiLoDetail2
;
              DetermineHiLo_Extend
              DetermineHiLo_State
;
              VerifySettings_State
;
              Checksum
;
              LogDataLength
              ServerDataLength
              ServerChecksum
;
              I2C_Tracker
;
              Checksum_A
;
              DS1307_Address
              DS1307_Data
;
              WindDirection
              WindDirectionH
;
              WindSpeedTimer
              WindSpeedTimerH
              WindSpeedTimerHH
;
              WindSpeed1
              WindSpeed1H
              WindSpeed2
              WindSpeed2H
              WindSpeed3
              WindSpeed3H
              WindSpeed4
              WindSpeed4H
;
              WindSpeed_State
;
              Gust1
              Gust1H
              Gust2
              Gust2H
              Gust3
              Gust3H
              Gust4
              Gust4H
;
              SprayingInterval
              SprayingIntervalH
              SprayingIntervalTimer
              SprayingIntervalTimerH
;
              RainPulseOld
              RainPulseOldH
              RainPulseOldHH
;
              Humidity1
              Humidity2
              Humidity3
              Humidity4
              Humidity5
              Humidity6
;
              Temperature1
              Temperature1H
              Temperature2
              Temperature2H
              Temperature3
              Temperature3H
              Temperature4
              Temperature4H
              Temperature5
              Temperature5H
              Temperature6
              Temperature6H
;
              RainTickCompensationTime
              RainTickCompensation
              RainTickCompensationH
;
              POSTingDelayMultiplier
              NAKDelayMultiplier
;
              NewWindSample
              NewWindSampleH
;
              WindSpeedTotal
              WindSpeedTotalH
              WindSpeedTotalHH
              WindSpeedTotalHHH
              WindSpeedTotalHHHH
;
              WindSpeedTotalCount
              WindSpeedTotalCountH
;
              WindSpeedAverage
              WindSpeedAverageH
;
              NetworkRegistrationAttempts
;	      
              CheckBank1Usage
           ENDC
;
#define ControlFlow FlowFlags,0,Banked
#define NV_BoundaryLo FirmwareYear
#define NV_BoundaryHi Debug3+1
;
           IF CheckBank1Usage > h'200'
              ERROR "Too many file registers have been used in Bank 1"
           ENDIF
;
           CBLOCK 0x200
              Rx1Buffer:Rx1BufferSize              ;Serial receive buffer 1
              Tx1Buffer:Tx1BufferSize              ;Serial transmit buffer 1
           ENDC 
;
#define EventQueueSize 60
;
#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 0x300
;
              EventQueue_3:EventQueueSize
              EEPROM_Buffer_3:EEPROM_BufferSize
;
           ENDC
;
#define EventQueueFirstLocation EventQueue_3
#define EventQueueLastLocation  EventQueue_3+EventQueueSize-1
;
#define EEPROM_FirstLocation EEPROM_Buffer_3
#define EEPROM_LastLocation  EEPROM_Buffer_3+EEPROM_BufferSize-1

;
           CBLOCK 0x400
;
              LineBuffer:LineBufferSize
;
           ENDC
;
           CBLOCK 0x500
;
              RainTickCompensationTable:64
;
           ENDC  
;
;***************************************
;
; 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_GSMReadPointer
              EE_GSMReadPointerH
              EE_GSMReadPointerHH
;
              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
;
           CBLOCK 0x80                           ;DeviceID is a "cookie" we need to send back to the server
              EE_DeviceIDHHH
              EE_DeviceIDHH
              EE_DeviceIDH
              EE_DeviceID
           ENDC
;
;***************************************
;
; Non-volatile flags
;
;***************************************
;
#define LoggingBufferFull NonVolatileFlags,0,Banked
;
;***************************************
;
; Internal EEPROM default data
;
;***************************************
; 
; The EEPROM is byte orientated, but somehow if you declare an EEPROM location on its own the assembler builds a seconds blank byte,
; instead of only 1 byte and that then messes up the alignment of the NV variables!!!
;
              org       h'F00000'
;                       Bank0,Sequence,
              de        0x5A ,0x63
              de        VersionYear,VersionMonth,VersionDayTens,VersionDayUnits
;                       PowerUps,PowerUpsH,Connections,ConnectionsH
              de        0       ,0        ,0          ,0
;                       BatteryVoltage,LogReadPointer,LogReadPointerH,LogReadPointerHH,LogWritePointer,LogWritePointerH,LogWritePointerHH,Rain,RainH,RainHH
              de        0xAA          ,0             ,0              ,4               ,0              ,0               ,4                ,0   ,0    ,0
;                       HumidityLo,HumidityHi
              de        0xFF      ,0
;                       TemperatureLo,TemperatureLoH,TemperatureHi,TemperatureHiH 
              de        0xFF         ,0xFF          ,0            ,0 
;                       GSMReadPointer,GSMReadPointerH,GSMReadPointerHH,Debug1,Debug2,Debug3  ; it is currently even so I dont' need the rest of this line ;? if I don't put this 0 here the assembler will and then I will forget it is there!!!
              de        0             ,0              ,4               ,0     ,0xFF  ,0xFF    ;0 
; 
              org       h'F00040'
;                       Bank0,Sequence ... the rest is don't care because bank 0 is active
              de        0x5A ,0x62
; 
              org       h'F00080'
;                       reduced to 64 bytes from 128 bytes M323 for rain tick compensation table
           IFNDEF Debugging    
 ;             de        'L','E','O','N','S','C','R','A','T','C','H','P','A','D'
 ;             de        'A','G','R','I','S','C','R','A','T','C','H','P','A','D'
             de        'A','P','P',' ','S','C','R','A','T','C','H','P','A','D'
           ELSE
;              de        'C','8','G','2','S','C','R','A','T','C','H','P','A','D'
;              de        'F','L','T','A','S','C','R','A','T','C','H','P','A','D'
              de        'N','E','W','A','S','C','R','A','T','C','H','P','A','D'
           ENDIF
;
              org       h'F000C0'
; RainTickVolume 1189
              de        000,234,212,190,168,147,125,103,081,045,006,000,000,000,000,000
              de        000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000   
              de        000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000   
              de        000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000   
; RainTickVolume 1189
;              de        000,234,212,190,168,147,125,103,081,060,038,016,000,000,000,000
;              de        000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000   
;              de        000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000   
;              de        000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000   
;M406              de        000,241,241,241,241,206,170,159,149,138,128,117,106,095,084,073
;              de        062,050,039,037,034,032,030,027,025,022,020,017,015,012,010,007
;              de        005,002,000,000,000,000,000,000,000,000,000,000,000,000,000,000
;              de        000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000   
;M324              de        235,235,235,235,235,208,182,156,130,121,112,104,095,087,078,070
;              de        055,040,025,024,023,022,021,020,020,019,018,017,016,015,015,014
;              de        013,013,012,012,011,010,010,009,009,008,007,007,006,006,005,004
;              de        004,003,003,002,001,001,000,000,000,000,000,000,000,000,000,000   
;
;***************************************
;
; Debug port modes
;
;***************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
           CBLOCK 0
;
              DisplayFlowMeterData
              DisplayPacketData
              DisplayValveData
;
           ENDC
;
;***************************************
;
; Reset comes to here
;
;***************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
              org       0
;
              clrf      INTCON,Access
              clrwdt
;
              goto      Begin
;
;***************************************
;
; High Priority Interrupts come to here
;
;***************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
              org       h'8'
;
              goto      RemapHighPriorityInterrupts ;And then we go and process them
;
;***************************************
;
; Low Priority Interrupts come to here
;
;***************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
              org       h'18'
;
              goto      RemapLowPriorityInterrupts ;And then we go and process them
;
;***************************************
;
; This is the beginning, so we need to initialise everything
;
;***************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
Begin:
;
              clrf      INTCON,Access            ;Interrupts are off for now
;
              movlw     InitialisePORTA          ;Define port latches
              movwf     PORTA,Access
              movwf     LATA,Access
              movlw     InitialisePORTB
              movwf     PORTB,Access
              movwf     LATB,Access
              movlw     InitialisePORTC
              movwf     PORTC,Access
              movwf     LATC,Access
              movlw     InitialisePORTE
              movwf     PORTE,Access
;
              movlw     ConfigurePORTA
              movwf     TRISA,Access
              movlw     ConfigurePORTB
              movwf     TRISB,Access
              movlw     ConfigurePORTC
              movwf     TRISC,Access
              movlw     ConfigurePORTE
              movwf     TRISE,Access
;
              movlw     b'00000011'
              movff     WREG,ANSELA
              movlw     b'00000000'
              movff     WREG,ANSELB
              movlw     b'00000000'
              movff     WREG,ANSELC
;
              movlw     ConfigureADC1
              movff     WREG,ADCON1
;
              movlw     ConfigureADC2
              movff     WREG,ADCON2
;
              movlw     0
              movwf     CM1CON0,Access
              movwf     CM2CON0,Access
              movwf     CM2CON1,Access
;
              movlw     b'11111101'
              movwf     WPUB,Access
              bcf       _nRBPU                   ;Enable weak pull-ups on PORT B
;
              movlw     1                        ;All banked addressing points to register bank 1 
              movwf     BSR
;
;#define ICDDAT PORTA,0
;#define ICDDAT PORTA,1
#define Alarm PORTA,2,Access
#define GSM_DTR_out LATA,3,Access
#define GSM_DTR_in PORTA,3,Access
;#define OSC1  PORTA,4
;#define OSC2  PORTA,5
;
#define RTC_PU            LATB,3,Access
#define SCL_RTC_Direction TRISB,5,Access
#define SCL_RTC_In        PORTB,5,Access
#define SCL_RTC_Out       LATB,5,Access
#define SDA_RTC_Direction TRISB,4,Access
#define SDA_RTC_In        PORTB,4,Access
#define SDA_RTC_Out       LATB,4,Access
;
#define SelectUSB LATC,0,Access
#define SelectGSM LATC,1,Access
;
#define SCL_Direction TRISC,3,Access
#define SCL_In        PORTC,3,Access
#define SCL_Out       LATC,3,Access
#define SDA_Direction TRISC,4,Access
#define SDA_In        PORTC,4,Access 
#define SDA_Out       LATC,4,Access
#define USBAlert PORTA,0,Access
#define Power     LATC,5,Access
#define ReadPower PORTC,5,Access
#define TxPin LATC,6,Access
#define RxPin PORTC,7,Access
;
#define BBTx PORTA,0,Access
;
#define Track_USBAlert b'00000001'
#define USBAlert_Threshold 650
;
              movlw     b'00000000'              ;Switch to high speed to get through initialisation quickly 
              movwf     OSCTUNE,Access
              movlw     b'00000100'
              movwf     OSCCON2,Access
              movlw     b'00001000'          
              movwf     OSCCON,Access
;
              clrf      Flags0,Access            ;Initialise system flags
              clrf      Flags1,Access
              clrf      Flags2,Access
              clrf      Flags3,Access
              clrf      Flags4,Access
              clrf      Flags5,Access
              clrf      Flags6,Access
;
              clrf      Flags0A,Access
              clrf      Flags1A,Access
              clrf      Flags2A,Access
;
              bsf       SendSMS                  ;Force a POST to the server to get the network time, in case this ends up being a cold start
;
              bsf       HighSpeed
;
              clrf      I2C_Tracker,Banked
;;
;              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,Banked
;
              movlw     0
              movwf     GarbageFlags,Banked
;
              movlw     EventQueueFirstLocation
              movwf     EventQueueWritePointer,Banked
              movwf     EventQueueReadPointer,Banked
              movlw     EventQueueSize
              movwf     EventQueueAvailable,Banked
              movlw     0
              movwf     EventState,Banked
              movwf     DetermineHiLo_State,Banked
              movwf     VerifySettings_State,Banked
              movwf     WindSpeed_State,Banked
;
              movlw     EEPROM_FirstLocation
              movwf     EEPROM_WritePointer
              movwf     EEPROM_ReadPointer
              movlw     0
              movwf     EEPROM_Buffered  
;
              call      RestoreSettings_Bulk
;
              call      PopulateRainTickCompensationTable
;
              clrf      RainTickCompensation,Banked
              clrf      RainTickCompensationH,Banked
;
; N213 include this code to prevent POSTing below 3V8
;
           IFDEF DoNotPostBelow3V8   
;
              movlw     5*16 ;Event_SampleBatteryVoltage
              call      WriteEventToQueue
;
           ENDIF
;
; N213 include this code to prevent POSTing below 3V8
;
;
           IFNDEF Debugging
#define SprayingIntervalTC 240 ;720 ;For Danny
           ELSE
#define SprayingIntervalTC 720 ;180 ;For me
           ENDIF
;
              movlw     LOW(SprayingIntervalTC)
              movwf     SprayingInterval,Banked
              movwf     SprayingIntervalTimer,Banked
              movlw     HIGH(SprayingIntervalTC)
              movwf     SprayingIntervalH,Banked
              movwf     SprayingIntervalTimerH,Banked
              movlw     1
              movwf     POSTingDelayMultiplier,Banked
;
              clrf      NAKDelayMultiplier,Banked
;
              bsf       RTC_PU
;
              call      Delay1msec
;
              call      I2C_Delay
;
              lfsr      0,RTC_Seconds
;
              call      I2C_RTC_Start               
              movlw     b'11010000'
              call      I2C_RTC_Tx        
              movlw     b'00000000'              ;Read the Seconds register in order to check the CH bit
              call      I2C_RTC_Tx
              call      I2C_RTC_Start
              movlw     b'11010001'
              call      I2C_RTC_Tx
              bcf       AckTx
              call      I2C_RTC_Rx
              bsf       AckTx 
              movwf     INDF0
              call      I2C_RTC_Stop
;
        IFNDEF Debugging
              btfsc     INDF0,7
              goto      ColdStart
        ELSE
           IFNDEF ForceColdStart
              btfsc     INDF0,7
              goto      ColdStart
           ELSE
              goto      ColdStart
           ENDIF
        ENDIF
;
WarmStart:
;
              movlw     0xBE
              movwf     HiLoDetail1,Banked
              movlw     0xEF
              movwf     HiLoDetail2,Banked
;
              call      I2C_RTC_Start                
              movlw     b'11010000'
              call      I2C_RTC_Tx        
              movlw     b'00000001'              ;The clock is good, so carry on reading from the minutes 
              call      I2C_RTC_Tx
              call      I2C_RTC_Start
              movlw     b'11010001'
              call      I2C_RTC_Tx
              bsf       AckTx 
              call      I2C_RTC_Rx               ;Minutes
              movwf     PREINC0,Access
              call      I2C_RTC_Rx               ;Hours
              movwf     PREINC0,Access
              call      I2C_RTC_Rx               ;DayOfWeek
              movwf     PREINC0,Access
              call      I2C_RTC_Rx               ;Date
              movwf     PREINC0,Access
              call      I2C_RTC_Rx               ;Month
              movwf     PREINC0,Access
              call      I2C_RTC_Rx               ;Year
              movwf     PREINC0,Access
              bcf       AckTx
              call      I2C_RTC_Rx               ;Control
              bsf       AckTx
              movwf     PREINC0,Access
              call      I2C_RTC_Stop
;
              movlw     0x10                     ;Check control is setup correctly
              xorwf     INDF0,W,Access
              btfss     ZeroFlag
              goto      ColdStart
;
              call      CalculateSecondsOffset
;
              goto      ClockRunning
;
ColdStart:
;
              movlw     1
              addwf     PowerUps,Same,Banked
              movlw     0
              addwfc    PowerUpsH,Same,Banked
;
              btfss     CarryFlag
              goto      ColdStart_1
;
              movlw     0xFF
              movwf     PowerUps,Banked
              movwf     PowerUpsH,Banked
;
ColdStart_1:
              movlw     0xDE
              movwf     HiLoDetail1,Banked
              movlw     0xAD
              movwf     HiLoDetail2,Banked
;
; Start the clock - we don't have any date or time, but we need the 1s tick, so we don't have a choice
;
              clrf      Seconds_Offset,Banked
              clrf      Seconds_OffsetH,Banked
              clrf      Seconds_OffsetHH,Banked
;
              lfsr      0,RTC_Seconds
;
              call      I2C_RTC_Start
              movlw     b'11010000'
              call      I2C_RTC_Tx        
              movlw     b'00000000'
              call      I2C_RTC_Tx
              movlw     0x00 ;0 = Seconds
              movwf     POSTINC0,Access
              call      I2C_RTC_Tx
              movlw     0x00 ;1 = Minutes
              movwf     POSTINC0,Access
              call      I2C_RTC_Tx
              movlw     0x07 ;2 = Hours
              movwf     POSTINC0,Access
              call      I2C_RTC_Tx
              movlw     0x00 ;3 = DayOfWeek
              movwf     POSTINC0,Access
              call      I2C_RTC_Tx
              movlw     0x07 ;4 = Date
              movwf     POSTINC0,Access 
              call      I2C_RTC_Tx
              movlw     0x04 ;5 = Month
              movwf     POSTINC0,Access
              call      I2C_RTC_Tx
              movlw     0x21 ;6 = Year
              movwf     POSTINC0,Access
              call      I2C_RTC_Tx
              movlw     0x10 ;7 = Control
              movwf     POSTINC0,Access
              call      I2C_RTC_Tx
              call      I2C_RTC_Stop
;
; The highs and lows we loaded from EEPROM earlier are meaningless, so let's reset them like we would every day
;
              movlw     0xFF
              movwf     HumidityLo,Banked
              movwf     TemperatureLo,Banked
              movwf     TemperatureLoH,Banked
;
              movlw     0x00
              movwf     HumidityHi,Banked
              movwf     TemperatureHi,Banked
              movwf     TemperatureHiH,Banked 
;
        IFDEF Debugging
           IFDEF ForceColdStart
              call      CalculateSecondsOffset
           ENDIF
        ENDIF
;
ClockRunning:
;
              bcf       RTC_PU
;
              call      Delay1msec
;
              call      LogHiLoEvent             ;Log this power up event to external EEPROM
;
              bsf       _TMR4IF                  ;Ensure we can read the first rain pulse
              clrf      RainTickCompensationTime,Banked
;
              movlw     0
              movwf     WindSpeed1,Banked
              movwf     WindSpeed1H,Banked
              movwf     WindSpeed2,Banked
              movwf     WindSpeed2H,Banked
              movwf     WindSpeed3,Banked
              movwf     WindSpeed3H,Banked
              movwf     WindSpeed4,Banked
              movwf     WindSpeed4H,Banked
;
              movlw     0xFF
              movwf     Gust1,Banked
              movwf     Gust1H,Banked
              movwf     Gust2,Banked
              movwf     Gust2H,Banked
              movwf     Gust3,Banked
              movwf     Gust3H,Banked
              movwf     Gust4,Banked
              movwf     Gust4H,Banked
;
              movlw    0xAD
              movwf    Humidity1,Banked
              movwf    Humidity2,Banked
              movwf    Humidity3,Banked
              movwf    Humidity4,Banked
              movwf    Humidity5,Banked
              movwf    Humidity6,Banked
;
              movwf    Temperature1,Banked
              movwf    Temperature2,Banked
              movwf    Temperature3,Banked
              movwf    Temperature4,Banked
              movwf    Temperature5,Banked
              movwf    Temperature6,Banked
;
              movlw    0xDE
              movwf    Temperature1H,Banked
              movwf    Temperature2H,Banked
              movwf    Temperature3H,Banked
              movwf    Temperature4H,Banked
              movwf    Temperature5H,Banked
              movwf    Temperature6H,Banked
;
              movlw     '+'
              movwf     GSM_TimeZone_Sign,Banked
              movlw     '9'
              movwf     GSM_TimeZone_Tens,Banked
              movlw     '9'
              movwf     GSM_TimeZone_Units,Banked
;
              movlw     b'00001010' ;Run at low speed to save battery power 
              movwf     OSCCON,Access
;
              bcf       HighSpeed 
;
              bcf       _INT0EDG
              bsf       _INT1EDG
;
              clrf      VerifySettings_State,Banked
;
              movlw     Track_USBAlert
              call      ReadADC
              movlw     LOW(USBAlert_Threshold)
              subwf     ADRESL,W,Access
              movlw     HIGH(USBAlert_Threshold)
              subwfb    ADRESH,W,Access
;
              btfsc     CarryFlag    
              bsf       DevicePresentAtPowerUp
;
           IFDEF LiveDebug_Enable
;
              movlw     LOW(1) ;3906bps @ 31250Hz
              movwf     SPBRG,Access
              movlw     HIGH(1)
              movwf     SPBRGH,Access
;
              movlw     b'00001000' ;16-bit baud rate
              movwf     BAUDCON,Access
;
              movlw     b'00100110' ;High speed UART
              movwf     TXSTA1,Access
;
              movlw     b'10010000'
              movwf     RCSTA1,Access
;
              bsf       LiveDebugInitialised
;
           ENDIF
;
Forever_RainGauge_Delay:
;
              clrf      T1CON,Access
              movlw     HIGH(65536-2500) ;This is 50msec
              movwf     TMR1H,Access
              movlw     LOW(65536-2500)
              movwf     TMR1L,Access
              bcf       _TMR1IF
              movlw     b'00000000'
              movwf     T1GCON,Access
              movlw     b'01000001'
              movwf     T1CON,Access
;
Forever_RainGauge_Delay1:
;
              btfss     _TMR1IF
              goto      Forever_RainGauge_Delay1
;
Forever_RainGauge:
;
              btfss     LiveDebug_Activity
              goto      Forever_RainGauge1
;
              LiveDebug_RainPulse = TRUE         ;We need this marker for all exceptions
              LiveDebug LiveDebug_Forever_RainGauge
              LiveDebug_RainPulse =FALSE
;
              bcf       LiveDebug_Activity
;
Forever_RainGauge1:
;
              btfsc     _INT0IF
              call      ProcessRTC
;
              btfsc     _ReadRTC
              goto      ReadRTC
;
              btfsc     _TMR4IF
              call      TimeTicks
;              
              btfsc     _INT1IF
              call      CaptureRainPulse
;
              btfss     NewWindSampleFlag
              goto      Forever_RainGauge2
;
              movff     NewWindSample,CalculatorY0
              movff     NewWindSampleH,CalculatorY1
;
              movf      NewWindSample,W,Banked
              subwf     CalculatorY0,W,Access
              btfss     ZeroFlag
              goto      Forever_RainGauge1
;
              movf      NewWindSampleH,W,Banked
              subwf     CalculatorY1,W,Access
              btfss     ZeroFlag
              goto      Forever_RainGauge1
;
              bcf       NewWindSampleFlag
;
              clrf      CalculatorY2,Access
              clrf      CalculatorY3,Access
              clrf      CalculatorY4,Access
;
              movlw     WindSpeedFactor
              movwf     CalculatorX0,Access
              movlw     WindSpeedFactorH
              movwf     CalculatorX1,Access
              movlw     WindSpeedFactorHH
              movwf     CalculatorX2,Access
              movlw     WindSpeedFactorHHH
              movwf     CalculatorX3,Access
              movlw     WindSpeedFactorHHHH
              movwf     CalculatorX4,Access
;
              call      Div40
;
              movf      CalculatorX0,W,Access
              addwf     WindSpeedTotal,Same,Banked 
              movf      CalculatorX1,W,Access
              addwfc    WindSpeedTotalH,Same,Banked 
              movf      CalculatorX2,W,Access
              addwfc    WindSpeedTotalHH,Same,Banked 
              movf      CalculatorX3,W,Access
              addwfc    WindSpeedTotalHHH,Same,Banked 
              movf      CalculatorX4,W,Access
              addwfc    WindSpeedTotalHHHH,Same,Banked 
;
              movlw     1
              addwf     WindSpeedTotalCount,Same,Banked
              movlw     0
              addwfc    WindSpeedTotalCountH,Same,Banked
;
              goto      Forever_RainGauge1
;
Forever_RainGauge2:
;
              btfss     CaptureWindSpeedAverage
              goto      Forever_RainGauge5
;
              movff     WindSpeedTotal,CalculatorX0
              movff     WindSpeedTotalH,CalculatorX1
              movff     WindSpeedTotalHH,CalculatorX2
              movff     WindSpeedTotalHHH,CalculatorX3
              movff     WindSpeedTotalHHHH,CalculatorX4
;
              movff     WindSpeedTotalCount,CalculatorY0
              movff     WindSpeedTotalCountH,CalculatorY1
;
              clrf      CalculatorY2,Access
              clrf      CalculatorY3,Access
              clrf      CalculatorY4,Access
;
              movf      CalculatorY0,W,Access
              iorwf     CalculatorY1,W,Access
              btfsc     ZeroFlag
              goto      Forever_RainGauge3
;
              call      Div40
;
              movff     CalculatorX0,CalculatorY0
              movff     CalculatorX1,CalculatorY1
              movff     CalculatorX2,CalculatorY2
              movff     CalculatorX3,CalculatorY3
              movff     CalculatorX4,CalculatorY4
;
              movlw     WindSpeedFactor
              movwf     CalculatorX0,Access
              movlw     WindSpeedFactorH
              movwf     CalculatorX1,Access
              movlw     WindSpeedFactorHH
              movwf     CalculatorX2,Access
              movlw     WindSpeedFactorHHH
              movwf     CalculatorX3,Access
              movlw     WindSpeedFactorHHHH
              movwf     CalculatorX4,Access
;
              movf      CalculatorY0,W,Access
              iorwf     CalculatorY1,W,Access
              iorwf     CalculatorY2,W,Access
              iorwf     CalculatorY3,W,Access
              iorwf     CalculatorY4,W,Access
              btfsc     ZeroFlag
              goto      Forever_RainGauge3
;
              call      Div40
;
              movff     CalculatorX0,WindSpeedAverage
              movff     CalculatorX1,WindSpeedAverageH
;
              goto      Forever_RainGauge4
;
Forever_RainGauge3:
;
              movlw     0xFF
              movwf     WindSpeedAverage,Banked
              movwf     WindSpeedAverageH,Banked
;
              goto      Forever_RainGauge4
;
Forever_RainGauge4:
;
              bcf       CaptureWindSpeedAverage
;
              goto      Forever_RainGauge1
;
Forever_RainGauge5:
;
ProcessEvent:
;
              call      ReadEventQueue  
;
              clrf      PCLATU,Access
              movlw     HIGH(EventDispatchTable)
              movwf     PCLATH,Access
              rrcf      Event,W,Banked
              rrcf      WREG,W,Access
              andlw     b'00111100'
              addlw     LOW(EventDispatchTable)
              btfsc     CarryFlag
              incf      PCLATH,Same,Access
              movwf     PCL,Access

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 ;Look for the fudge up in the initialisation that with poke you in the eye!
EDT05:        goto      Event_X_SampleBatteryVoltage
#define Event_SnapShot 6*16
EDT06:        goto      Event_X_SnapShot
#define Event_SnapShot2 7*16
EDT07:        goto      Event_X_SnapShot2
#define Event_DetermineWindDirection 8*16
EDT08:        goto      Event_X_DetermineWindDirection
#define Event_RainPulseGSM 9*16
EDT09:        goto      Event_X_RainPulseGSM
;
              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,W,Banked
              btfsc     ZeroFlag   
              goto      Event_X_PowerDown1 
;
              goto      Event_X_PowerDown1 ;LC07
;
              bcf       PowerDown
;
              movlw     LogEvent_GarbageFlags
              call      EEPROM_WriteBuffer
              movf      GarbageFlags,W,Banked
              call      EEPROM_WriteBuffer
;             
              movlw     Event_WriteEEPROM
              call      WriteEventToQueue
;
              clrf      GarbageFlags,Banked
;
Event_X_PowerDown1:
;
              movf      RainPulseTimeLost,W,Banked
              btfsc     ZeroFlag
              goto      Event_X_PowerDown2 
;
              bcf       PowerDown
;
; No need to check the EEPROM buffer it is empty, that is why we were powering down
;
              movf      Seconds_OffsetHH,W,Banked ;Queue it for logging to EEPROM
              movlw     LogEvent_RainPulseTimeLost+0
              btfss     ZeroFlag
              movlw     LogEvent_RainPulseTimeLost+1
              movwf     Checksum,Banked
              call      EEPROM_WriteBuffer
              movf      Seconds_OffsetH,W,Banked
              addwf     Checksum,Same,Banked
              call      EEPROM_WriteBuffer
              movf      Seconds_Offset,W,Banked
              addwf     Checksum,Same,Banked
              call      EEPROM_WriteBuffer
;
              movf      RainPulseTimeLost,W,Banked
              addwf     Checksum,Same,Banked
              call      EEPROM_WriteBuffer
;
              movf      RainPulse,W,Banked
              addwf     Checksum,Same,Banked
              call      EEPROM_WriteBuffer
              movf      RainPulseH,W,Banked
              addwf     Checksum,Same,Banked
              call      EEPROM_WriteBuffer
              movf      RainPulseHH,W,Banked
              addwf     Checksum,Same,Banked
              call      EEPROM_WriteBuffer
;
              comf      Checksum,W,Banked
              addlw     1
              call      EEPROM_WriteBuffer
;             
              movlw     Event_WriteEEPROM
              call      WriteEventToQueue
;
              clrf      RainPulseTimeLost,Banked
;
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
;
              movlw     VersionYear
              subwf     FirmwareYear,W,Banked
              btfss     ZeroFlag
              goto      ReloadFirmwareVersion
;
              movlw     VersionMonth
              subwf     FirmwareMonth,W,Banked
              btfss     ZeroFlag
              goto      ReloadFirmwareVersion
;
              movlw     VersionDayTens
              subwf     FirmwareDayTens,W,Banked
              btfss     ZeroFlag
              goto      ReloadFirmwareVersion
;
              movlw     VersionDayUnits
              subwf     FirmwareDayUnits,W,Banked
              btfsc     ZeroFlag
              goto      Event_X_PowerDown3
;
ReloadFirmwareVersion:
;
              bcf       PowerDown
;
              movlw     VersionYear
              movwf     FirmwareYear,Banked
              movlw     VersionMonth
              movwf     FirmwareMonth,Banked
              movlw     VersionDayTens
              movwf     FirmwareDayTens,Banked
              movlw     VersionDayUnits
              movwf     FirmwareDayUnits,Banked
;
              goto      Event_X_PowerDown_Now
;
Event_X_PowerDown3:
;
              btfsc     SendSMS
              goto      Event_X_FlushEEPROM
;
              movlw     Track_USBAlert
              call      ReadADC
              movlw     LOW(USBAlert_Threshold)
              subwf     ADRESL,W,Access
              movlw     HIGH(USBAlert_Threshold)
              subwfb    ADRESH,W,Access
;
           IFNDEF LiveDebug_Enable
              btfss     CarryFlag    
           ENDIF
              goto      Event_X_PowerDown_Now
;
Event_X_FlushEEPROM:
;
; OK, so we either have a device connected or need to send an SMS, but first check that the external EEPROM buffer is empty, otherwise FLUSHHH it first and then try again
;
              movf      EEPROM_Buffered,W,Banked
              btfsc     ZeroFlag 
              goto      FreeToCommunicate
;
              movlw     'F'
              call      EEPROM_WriteBuffer
              movlw     EEPROM_WritePageSize
              subwf     EEPROM_Buffered,W,Banked
              btfsc     ZeroFlag
              goto      Event_X_PowerDown_Flush
;
              movlw     'L'
              call      EEPROM_WriteBuffer
              movlw     EEPROM_WritePageSize
              subwf     EEPROM_Buffered,W,Banked
              btfsc     ZeroFlag
              goto      Event_X_PowerDown_Flush
;
              movlw     'U'
              call      EEPROM_WriteBuffer
              movlw     EEPROM_WritePageSize
              subwf     EEPROM_Buffered,W,Banked
              btfsc     ZeroFlag
              goto      Event_X_PowerDown_Flush
;
              movlw     'S'
              call      EEPROM_WriteBuffer
              movlw     EEPROM_WritePageSize
              subwf     EEPROM_Buffered,W,Banked
              btfsc     ZeroFlag
              goto      Event_X_PowerDown_Flush
;
Event_X_PowerDown_Flushing:
;
              movlw     'H'
              call      EEPROM_WriteBuffer
              movlw     EEPROM_WritePageSize
              subwf     EEPROM_Buffered,W,Banked
              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:
;
              call      VerifySettings
;
              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
;
;
           IFDEF SHT20

    ;          movlw     b'10000000'              ;Switch to high speed to get through initialisation quickly 
    ;          movwf     OSCCON,Access
;
    ;          bsf       HighSpeed

;;
;AnotherOne:
;;
;              bsf       Power
; nop
;;
;              call      I2C_Start
;              movlw     b'10000000' ;Address SHT20
;              call      I2C_Tx
;;
;              movlw     b'11110101' ;Start a temperature conversion
;              call      I2C_Tx
;;
; nop
;              call      I2C_Delay
;              call      I2C_Delay
;;
;              call      I2C_Stop
;;
;CheckAgain:
;;
; nop
;              call      I2C_Start
;              movlw     b'10000001' ;Address SHT20
;              call      I2C_Tx
;;
;              btfsc     AckRx
;              goto      CheckAgain
;;
; nop
;              bsf       AckTx
;              call      I2C_Rx
;              movwf     AHT10_T1,Banked
;;
;              bcf       AckTx
;              call      I2C_Rx
;              movwf     AHT10_T2,Banked
;              bsf       AckTx
;;
;              call      I2C_Stop
;
;;
; goto AnotherOne
;
              clrf      PCLATU,Access
              movlw     HIGH(DetermineHiLoDispatchTable)
              movwf     PCLATH,Access
;
              movf      EventState,W,Banked
              addwf     DetermineHiLo_State,W,Banked
              rlcf      WREG,W,Access
              rlcf      WREG,W,Access
              andlw     b'00111100'
              addlw     LOW(DetermineHiLoDispatchTable)
              btfsc     CarryFlag
              incf      PCLATH,Same,Access 
              movwf     PCL,Access
;
DetermineHiLoDispatchTable:
;

DHLDT00:      goto      Event_X_DHL_PowerOn
DHLDT01:      goto      Event_X_DHL_WaitPowerOn
DHLDT02:      goto      Event_X_DHL_StartConversionT 
DHLDT03:      goto      Event_X_DHL_WaitConversionT
DHLDT04:      goto      Event_X_DHL_ReadT
DHLDT05:      goto      Event_X_DHL_StartConversionH 
DHLDT06:      goto      Event_X_DHL_WaitConversionH
DHLDT07:      goto      Event_X_DHL_ReadH
DHLDT08:      goto      Event_X_DHL_Temperature1
DHLDT09:      goto      Event_X_DHL_Temperature2
DHLDT10:      goto      Event_X_DHL_Humidity1
DHLDT11:      goto      Event_X_DHL_Humidity1
DHLDT12:      goto      Event_X_DHL_Humidity1
DHLDT13:      goto      Event_X_DHL_Humidity2
DHLDT14:      goto      Event_X_DHL_Humidity3
DHLDT15:      nop
              nop
;
              call     RemoveEventFromQueue
;
              LiveDebug LiveDebug_UnknownState
;
              goto      Event_X_DetermineHiLo_End
;
;*************************************************
;
DetermineHiLo_Push:
;
               movlw    LOW(DetermineHiLo_Calculator0_0)
               movwf    FSR0L,Access
               movlw    HIGH(DetermineHiLo_Calculator0_0)
               movwf    FSR0H,Access
;  
               movf     CalculatorX0,W,Access
               movwf    POSTINC0,Access
               movf     CalculatorX1,W,Access
               movwf    POSTINC0,Access
               movf     CalculatorX2,W,Access
               movwf    POSTINC0,Access
               movf     CalculatorX3,W,Access
               movwf    POSTINC0,Access
               movf     CalculatorX4,W,Access
               movwf    POSTINC0,Access
;
               return
;
;*************************************************
;
DetermineHiLo_Pop:
;
               movlw    LOW(DetermineHiLo_Calculator0_0)
               movwf    FSR0L,Access
               movlw    HIGH(DetermineHiLo_Calculator0_0)
               movwf    FSR0H,Access
;
               movf     POSTINC0,Access
               movwf    CalculatorX0,Access
               movf     POSTINC0,Access
               movwf    CalculatorX1,Access
               movf     POSTINC0,Access
               movwf    CalculatorX2,Access
               movf     POSTINC0,Access
               movwf    CalculatorX3,Access
               movf     POSTINC0,Access
               movwf    CalculatorX4,Access
;
               return
;
;*************************************************
;
Event_X_DHL_PowerOn:
;
              bsf       Power
;
              clrf      T1CON,Access
              movlw     HIGH(65536-625) ;This is 20msec
              movwf     TMR1H,Access
              movlw     LOW(65536-625)
              movwf     TMR1L,Access
              bcf       _TMR1IF
              movlw     b'00000000'
              movwf     T1GCON,Access
              movlw     b'01000001'
              movwf     T1CON,Access
;
              incf      EventState,Same,Banked
;
              goto      Event_X_DetermineHiLo_End
;
Event_X_DHL_WaitPowerOn:
;
              btfss     _TMR1IF
              goto      Event_X_DHL_WaitPowerOn_End
;
              incf      EventState,Same,Banked
;
; Move the current readings to the buffers to make space for the new readings
;
              movff     Humidity5,Humidity6
              movff     Humidity4,Humidity5
              movff     Humidity3,Humidity4
              movff     Humidity2,Humidity3
              movff     Humidity1,Humidity2
              movff     Humidity,Humidity1
;
              movff     Temperature5,Temperature6
              movff     Temperature5H,Temperature6H
              movff     Temperature4,Temperature5
              movff     Temperature4H,Temperature5H
              movff     Temperature3,Temperature4
              movff     Temperature3H,Temperature4H
              movff     Temperature2,Temperature3
              movff     Temperature2H,Temperature3H
              movff     Temperature1,Temperature2
              movff     Temperature1H,Temperature2H
              movff     Temperature,Temperature1
              movff     TemperatureH,Temperature1H
;
Event_X_DHL_WaitPowerOn_End:
;
              goto      Event_X_DetermineHiLo_End
;
Event_X_DHL_StartConversionT:
;
              call      I2C_Start
              movlw     b'10000000' ;Adress SHT20
              call      I2C_Tx
              movlw     b'11110011' ;Start temperature conversion
              call      I2C_Tx
;
              call      I2C_Delay
              call      I2C_Delay
;
              call      I2C_Stop
;
              movlw     16          ;For now let's allow another 16 * 5msec slots for the conversion to complete, before aborting it
              movwf     DetermineHiLo_Extend,Banked
;
              clrf      T2CON,Access
              movlw     157 ;This is 80msec
              movwf     PR2,Access
              clrf      TMR2,Access 
              bcf       _TMR2IF
              movlw     b'00000101'
              movwf     T2CON,Access
;
              incf      EventState,Same,Banked
;
              goto      Event_X_DetermineHiLo_End
;
Event_X_DHL_WaitConversionT:
;
              btfsc     _TMR2IF
              goto      Event_X_DHL_WaitConversionT1
;
              movf      EventState,W,Banked
              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,Banked
;
              call      RemoveEventFromQueue
;
              movlw     Event_DetermineHiLo
              call      WriteEventToQueue
;
              goto      Event_X_DHL_WaitConversionT_End
;
Event_X_DHL_WaitConversionT1:
;
              movf      EventState,W,Banked
              btfss     ZeroFlag
              goto      Event_X_DHL_WaitConversionT2 
;
              movf      DetermineHiLo_State,W,Banked
              movwf     EventState,Banked
              clrf      DetermineHiLo_State,Banked
;
Event_X_DHL_WaitConversionT2:
;
              incf      EventState,Same,Banked
;
Event_X_DHL_WaitConversionT_End:
;
              goto      Event_X_DetermineHiLo_End
;
Event_X_DHL_ReadT:
;
              movf      EventState,W,Banked
              movwf     DetermineHiLo_State,Banked
;          
              call      I2C_Start
              movlw     b'10000001' ;Address SHT20
              call      I2C_Tx
;
              btfss     AckRx
              goto      Event_X_DHL_ReadT_On
;
; If we get here we need to give the AHT10 more time to complete the conversion
;
 ;             call      I2C_Stop
;
; Debug1 counts how many times we need to extend the conversion time
;
              btfss     DetermineHiLo_Extend,4,Banked
              goto      Event_X_DHL_SkipDebugT1
;
              incf      Debug1,W,Banked
              btfss     ZeroFlag
              incf      Debug1,Same,Banked
;
Event_X_DHL_SkipDebugT1:
;
              decf      DetermineHiLo_Extend,Same,Banked
;
; Debug2 tracks the longest extension we gave the conversion time
;
              movf      Debug2,W,Banked
              subwf     DetermineHiLo_Extend,W,Banked
              movf      DetermineHiLo_Extend,W,Banked
              btfss     CarryFlag
              movwf     Debug2,Banked
;
              movf      DetermineHiLo_Extend,W,Banked
              btfsc     ZeroFlag
              goto      Event_X_DHL_ReadT_Cancel
;
              clrf      T1CON,Access
              movlw     HIGH(65536-156) ;Extend the conversion time by about 5msec
              movwf     TMR1H,Access
              movlw     LOW(65536-156)
              movwf     TMR1L,Access
              bcf       _TMR1IF
              movlw     b'00000000'
              movwf     T1GCON,Access
              movlw     b'01000001'
              movwf     T1CON,Access
;
              call      RemoveEventFromQueue
;
              clrf      DetermineHiLo_State,Banked 
;
              movlw     3 ;Go back to WaitConversion
              movwf     EventState,Banked
;  
              movlw     Event_DetermineHiLo
              call      WriteEventToQueue

              goto      Event_X_DHL_ReadT_End
;
Event_X_DHL_ReadT_Cancel:
;
              bcf       Power ;??? what if we are writing to ext ee or can't that happen?
;
              call      I2C_Delay
;
              call      RemoveEventFromQueue
;
              clrf      DetermineHiLo_State,Banked
;
              movlw     0xAD
              movwf     Humidity,Banked
              movwf     Temperature,Banked
              movlw     0xDE
              movwf     TemperatureH,Banked
;
              goto      DHL_LinkForward ;Event_X_DHL_ReadT_End
;
Event_X_DHL_ReadT_On:
;
              bsf       AckTx
              call      I2C_Rx
              movwf     AHT10_T2,Banked ;TH
;
              bcf       AckTx
              call      I2C_Rx
              movwf     AHT10_T1,Banked ;TL
              bsf       AckTx
;
              call      I2C_Stop
;
;
 ;             bcf       Power ;??? what if we are writing to ext ee or can't that happen? I don't think it can happen, because
                              ;we can only get here if the EEPROM event has been removed from the queue
;
  ;            call      I2C_Delay
;
              incf      DetermineHiLo_State,Same,Banked
;
              call      RemoveEventFromQueue
;
              movlw     Event_DetermineHiLo
              call      WriteEventToQueue
;
Event_X_DHL_ReadT_End:
;
              goto      Event_X_DetermineHiLo_End
;
Event_X_DHL_StartConversionH:
;
              call      I2C_Start
              movlw     b'10000000' ;Adress SHT20
              call      I2C_Tx
              movlw     b'11110101' ;Start humididy conversion
              call      I2C_Tx
;
              call      I2C_Delay
              call      I2C_Delay
;
              call      I2C_Stop
;
              movlw     16          ;For now let's allow another 16 * 5msec slots for the conversion to complete, before aborting it
              movwf     DetermineHiLo_Extend,Banked
;
              clrf      T2CON,Access
              movlw     157 ;This is 80msec
              movwf     PR2,Access
              clrf      TMR2,Access 
              bcf       _TMR2IF
              movlw     b'00000101'
              movwf     T2CON,Access
;
              movff     DetermineHiLo_State,EventState
              clrf      DetermineHiLo_State,Banked
              incf      EventState,Same,Banked
;
              goto      Event_X_DetermineHiLo_End
;
Event_X_DHL_WaitConversionH:
;
              btfsc     _TMR2IF
              goto      Event_X_DHL_WaitConversionH1
;
              movf      EventState,W,Banked
              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,Banked
;
              call      RemoveEventFromQueue
;
              movlw     Event_DetermineHiLo
              call      WriteEventToQueue
;
              goto      Event_X_DHL_WaitConversionH_End
;
Event_X_DHL_WaitConversionH1:
;
              movf      EventState,W,Banked
              btfss     ZeroFlag
              goto      Event_X_DHL_WaitConversionH2 
;
              movf      DetermineHiLo_State,W,Banked
              movwf     EventState,Banked
              clrf      DetermineHiLo_State,Banked
;
Event_X_DHL_WaitConversionH2:
;
              incf      EventState,Same,Banked
;
Event_X_DHL_WaitConversionH_End:
;
              goto      Event_X_DetermineHiLo_End
;
Event_X_DHL_ReadH:
;
              movf      EventState,W,Banked
              movwf     DetermineHiLo_State,Banked
;          
              call      I2C_Start
              movlw     b'10000001' ;Address SHT20
              call      I2C_Tx
;
              btfss     AckRx
              goto      Event_X_DHL_ReadH_On
;
; If we get here we need to give the AHT10 more time to complete the conversion
;
              call      I2C_Stop
;
; Debug1 counts how many times we need to extend the conversion time
;
              btfss     DetermineHiLo_Extend,4,Banked
              goto      Event_X_DHL_SkipDebugH1
;
              incf      Debug1,W,Banked
              btfss     ZeroFlag
              incf      Debug1,Same,Banked
;
Event_X_DHL_SkipDebugH1:
;
              decf      DetermineHiLo_Extend,Same,Banked
;
; Debug2 tracks the longest extension we gave the conversion time
;
              movf      Debug2,W,Banked
              subwf     DetermineHiLo_Extend,W,Banked
              movf      DetermineHiLo_Extend,W,Banked
              btfss     CarryFlag
              movwf     Debug2,Banked
;
              movf      DetermineHiLo_Extend,W,Banked
              btfsc     ZeroFlag
              goto      Event_X_DHL_ReadH_Cancel
;
              clrf      T1CON,Access
              movlw     HIGH(65536-156) ;Extend the conversion time by about 5msec
              movwf     TMR1H,Access
              movlw     LOW(65536-156)
              movwf     TMR1L,Access
              bcf       _TMR1IF
              movlw     b'00000000'
              movwf     T1GCON,Access
              movlw     b'01000001'
              movwf     T1CON,Access
;
              call      RemoveEventFromQueue
;
              clrf      DetermineHiLo_State,Banked 
;
              movlw     6 ;Go back to WaitConversion
              movwf     EventState,Banked
;  
              movlw     Event_DetermineHiLo
              call      WriteEventToQueue

              goto      Event_X_DHL_ReadH_End
;
Event_X_DHL_ReadH_Cancel:
;
              bcf       Power ;??? what if we are writing to ext ee or can't that happen?
;
              call      I2C_Delay
;
              call      RemoveEventFromQueue
;
              clrf      DetermineHiLo_State,Banked
;
              movlw     0xAD
              movwf     Humidity,Banked
              movwf     Temperature,Banked
              movlw     0xDE
              movwf     TemperatureH,Banked
;
              goto      DHL_LinkForward ;Event_X_DHL_ReadH_End
;
Event_X_DHL_ReadH_On:
;
              bsf       AckTx
              call      I2C_Rx
; movlw 0x63 ;This is the example SHT20 result for the conversion example in the datasheet
              movwf     AHT10_H2,Banked ;HH
;
              bcf       AckTx
              call      I2C_Rx
; movlw 0x52 ;This is the example SHT20 result for the conversion example in the datasheet
              movwf     AHT10_H1,Banked ;HL
              bsf       AckTx
;
              call      I2C_Stop
;
;
 ;             bcf       Power ;??? what if we are writing to ext ee or can't that happen? I don't think it can happen, because
                              ;we can only get here if the EEPROM event has been removed from the queue
;
  ;            call      I2C_Delay
;
              incf      DetermineHiLo_State,Same,Banked
;
              call      RemoveEventFromQueue
;
              movlw     Event_DetermineHiLo
              call      WriteEventToQueue
;
Event_X_DHL_ReadH_End:
;
              goto      Event_X_DetermineHiLo_End
;
Event_X_DHL_Temperature1:
;
              movf      AHT10_T1,W,Banked
              movwf     CalculatorX0,Access         
              movf      AHT10_T2,W,Banked
              movwf     CalculatorX1,Access         
              clrf      CalculatorX2,Access
              clrf      CalculatorX3,Access
              clrf      CalculatorX4,Access
;
              movlw     LOW(17572)
              movwf     CalculatorY0,Access
              movlw     HIGH(17572)
              movwf     CalculatorY1,Access
              clrf      CalculatorY2,Access         
              clrf      CalculatorY3,Access         
              clrf      CalculatorY4,Access         
;
              call      Mul40
;
              movlw     LOW(315)
              addwf     CalculatorX2,W,Access
              movwf     Temperature,Banked
;
              movlw     HIGH(315)
              addwfc    CalculatorX3,W,Access
              movwf     TemperatureH,Banked
;
              incf      DetermineHiLo_State,Same,Banked
;
              call      RemoveEventFromQueue
;
              movlw     Event_DetermineHiLo
              call      WriteEventToQueue
;
              goto      Event_X_DetermineHiLo_End
;
Event_X_DHL_Temperature2:
;
              movf      Temperature,W,Banked
              subwf     TemperatureLo,W,Banked
              movf      TemperatureH,W,Banked
              subwfb    TemperatureLoH,W,Banked
;
              btfss     CarryFlag
              goto      SkipTLo
;
              movf      Temperature,W,Banked
              movwf     TemperatureLo,Banked
              movf      TemperatureH,W,Banked
              movwf     TemperatureLoH,Banked
;
SkipTLo:
;
              movf      Temperature,W,Banked
              subwf     TemperatureHi,W,Banked
              movf      TemperatureH,W,Banked
              subwfb    TemperatureHiH,W,Banked
;
              btfsc     CarryFlag
              goto      SkipTHi
;
              movf      Temperature,W,Banked
              movwf     TemperatureHi,Banked
              movf      TemperatureH,W,Banked
              movwf     TemperatureHiH,Banked
;
SkipTHi:
;
              incf      DetermineHiLo_State,Same,Banked
;
              call      RemoveEventFromQueue
;
              movlw     Event_DetermineHiLo
              call      WriteEventToQueue
;
              goto      Event_X_DetermineHiLo_End
;
Event_X_DHL_Humidity1:
;
              movf      AHT10_H1,W,Banked
              movwf     CalculatorX0,Access         
              movf      AHT10_H2,W,Banked
              movwf     CalculatorX1,Access         
              clrf      CalculatorX2,Access
              clrf      CalculatorX3,Access
              clrf      CalculatorX4,Access
;
              movlw     LOW(1250)
              movwf     CalculatorY0,Access
              movlw     HIGH(1250)
              movwf     CalculatorY1,Access
              clrf      CalculatorY2,Access         
              clrf      CalculatorY3,Access         
              clrf      CalculatorY4,Access         
;
              call      Mul40
;
              movlw     LOW(55)                  ;So where does this 55 come from: I need to subtract 60 for the conversion and add 5 for rounding, so I just subtract 55 instead
              subwf     CalculatorX2,W,Access
              movwf     CalculatorX0,Access
;
              movlw     HIGH(55)
              subwfb    CalculatorX3,W,Access
              movwf     CalculatorX1,Access
              clrf      CalculatorX2,Access
              clrf      CalculatorX3,Access
              clrf      CalculatorX4,Access
;
              call      DetermineHiLo_Push
;
              incf      DetermineHiLo_State,Same,Banked
;
              call      RemoveEventFromQueue
;
              movlw     Event_DetermineHiLo
              call      WriteEventToQueue
;
              goto      Event_X_DetermineHiLo_End
;
Event_X_DHL_Humidity2:
;
              call      DetermineHiLo_Pop
;
              movlw     10
              movwf     CalculatorY0,Access
              clrf      CalculatorY1,Access         
              clrf      CalculatorY2,Access         
              clrf      CalculatorY3,Access         
              clrf      CalculatorY4,Access         
;
              call      Div40
;
              movf      CalculatorX0,W,Access
              movwf     Humidity,Banked
;
              incf      DetermineHiLo_State,Same,Banked
;
              call      RemoveEventFromQueue
;
              movlw     Event_DetermineHiLo
              call      WriteEventToQueue
;
              goto      Event_X_DetermineHiLo_End
;
Event_X_DHL_Humidity3:
;
              movf      Humidity,W,Banked
              subwf     HumidityLo,W,Banked
;
              btfss     CarryFlag
              goto      SkipHLo
;
              movf      Humidity,W,Banked
              movwf     HumidityLo,Banked
;
SkipHLo:
;
              movf      Humidity,W,Banked
              subwf     HumidityHi,W,Banked
;
              btfsc     CarryFlag
              goto      SkipHHi
;
              movf      Humidity,W,Banked
              movwf     HumidityHi,Banked
;
SkipHHi:
;
              call      RemoveEventFromQueue
;
              clrf      DetermineHiLo_State,Banked
;
DHL_LinkForward:
;
              movlw     Event_DetermineWindDirection ;Now determine the wind direction
              call      WriteEventToQueue
;
              goto      Event_X_DetermineHiLo_End
;
Event_X_DetermineHiLo_End:
;
           ENDIF
; 
              LiveDebug LiveDebug_DetermineHiLo_End
;
              goto      ProcessEvent_End
;
Event_X_WriteEEPROM:
;
;*************************************************
;
Event_X_WriteEEPROM:
;
              LiveDebug LiveDebug_WriteExtEEPROM_Start
;
              clrf      PCLATU,Access
              movlw     HIGH(WriteEEPROMDispatchTable)
              movwf     PCLATH,Access
;
              LiveDebugEventState
;
              rlcf      EventState,W,Banked
              rlcf      WREG,W,Access
              andlw     b'00011100'
              addlw     LOW(WriteEEPROMDispatchTable)
              btfsc     CarryFlag
              incf      PCLATH,Same,Access
              movwf     PCL,Access

WriteEEPROMDispatchTable:
;
WEDT00:       goto      Event_X_WriteEEPROM_CheckForData
WEDT01:       goto      Event_X_WriteEEPROM_PowerOn
WEDT02:       goto      Event_X_WriteEEPROM_WaitPowerOn
WEDT03:       goto      Event_X_WriteEEPROM_VerifyPointers
WEDT04:       goto      Event_X_WriteEEPROM_WritePage
WEDT05:       goto      Event_X_WriteEEPROM_WaitWrite
WEDT06:       nop
              nop
WEDT07:       nop
              nop
;
              call      RemoveEventFromQueue
;
              LiveDebug LiveDebug_UnknownState
;
              goto      Event_X_WriteEEPROM_End
;
;*************************************************
;
Event_X_WriteEEPROM_CheckForData:
;
              incf      EventState,Same,Banked             ;Assume this event hasn't been pre-empted
;
              movlw     EEPROM_WritePageSize
              subwf     EEPROM_Buffered,W,Banked
              btfsc     CarryFlag
              goto      Event_X_WriteEEPROM_CFD_End

              call RemoveEventFromQueue              
;
Event_X_WriteEEPROM_CFD_End:
;
              goto      Event_X_WriteEEPROM_End
;
Event_X_WriteEEPROM_PowerOn:
;
              bcf       StorePower               ;Check to see if the I2C devices are on, because an AHT10 measurement is in progress
              btfsc     Power
              bsf       StorePower               ;If yes, then don't switch off when we are done with the EEPROM
              bsf       Power
;
              clrf      T1CON,Access
;
; If the I2C devices are already on, then we could speed things up, by not having to want here
;
              movlw     HIGH(65536-625) ;Give the EEPROM time to wake up properly
              movwf     TMR1H,Access
              movlw     LOW(65536-625)
              movwf     TMR1L,Access
              bcf       _TMR1IF
              movlw     b'00000000'
              movwf     T1GCON,Access
              movlw     b'01000001'
              movwf     T1CON,Access
;
              incf      EventState,Same,Banked
;
              goto      Event_X_WriteEEPROM_End
;
Event_X_WriteEEPROM_WaitPowerOn:
;
              btfss     _TMR1IF
              goto      Event_X_WriteEEPROM_WaitPowerOn_End
;
              incf      EventState,Same,Banked
;
Event_X_WriteEEPROM_WaitPowerOn_End:
;
              goto      Event_X_WriteEEPROM_End
;
Event_X_WriteEEPROM_VerifyPointers:
;
; 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,W,Banked
              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,Same,Banked
              movlw     0
              addwfc    LogWritePointerH,Same,Banked
              movlw     0
              addwfc    LogWritePointerHH,Same,Banked
              movlw     EEPROM_WritePageSize-1
              xorlw     b'11111111'
              andwf     LogWritePointer,Same,Banked
;
              bsf       ExtEE_PageAligned
;
Event_X_WriteEEPROM_SkipAlignment:
;
              movlw     4
              subwf     LogWritePointerHH,W,Banked
              btfss     CarryFlag
              goto      Event_X_WriteEEPROM_WriteOutOfBounds
;
              movlw     6
              subwf     LogWritePointerHH,W,Banked
              btfss     CarryFlag
              goto      Event_X_WriteEEPROM_WriteInBounds
;
Event_X_WriteEEPROM_WriteOutOfBounds:
;
              movlw     0x00
              movwf     LogWritePointer,Banked
              movwf     GSMReadPointer,Banked
;
              movlw     0x00
              movwf     LogWritePointerH,Banked
              movwf     GSMReadPointerH,Banked
;
              movlw     0x04
              movwf     LogWritePointerHH,Banked
              movwf     GSMReadPointerHH,Banked
;
              bsf       ExtEE_WritePointerOutOfBounds
;
Event_X_WriteEEPROM_WriteInBounds:
;
; Validate the GSM 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     GSMReadPointerHH,W,Banked
              btfss     CarryFlag
              goto      Event_X_WriteEEPROM_GSMReadOutOfBounds
;
              movlw     6
              subwf     GSMReadPointerHH,W,Banked
              btfss     CarryFlag
              goto      Event_X_WriteEEPROM_GSMReadInBounds
;
Event_X_WriteEEPROM_GSMReadOutOfBounds:
;
              movf      LogWritePointer,W,Banked
              movwf     GSMReadPointer,Banked
              movf      LogWritePointerH,W,Banked
              movwf     GSMReadPointerH,Banked
              movf      LogWritePointerHH,W,Banked
              movwf     GSMReadPointerHH,Banked
;
              bsf       ExtEE_ReadPointerOutOfBounds ;Garbage flags are fully utilised, otherwise I would have differentiated here
;
Event_X_WriteEEPROM_GSMReadInBounds:
;
; Check that the WritePointer won't overtake the GSMReadPointer
; - If the write pointer >= read pointer we are good
;
              movf      LogWritePointer,W,Banked
              subwf     GSMReadPointer,W,Banked
              movwf     CalculatorX0
              movf      LogWritePointerH,W,Banked
              subwfb    GSMReadPointerH,W,Banked
              movwf     CalculatorX1      
              movf      LogWritePointerHH,W,Banked
              subwfb    GSMReadPointerHH,W,Banked
              movwf     CalculatorX2
              btfss     CarryFlag
              goto      Event_X_WriteEEPROM_GSMReadPointerVerified 
              btfsc     ZeroFlag
              goto      Event_X_WriteEEPROM_GSMReadPointerVerified 
;
              comf      CalculatorX0,Same,Access
              comf      CalculatorX1,Same,Access
              comf      CalculatorX2,Same,Access
              movlw     1
              addwf     CalculatorX0,Same,Access
              movlw     0
              addwfc    CalculatorX1,Same,Access
              movlw     0
              addwfc    CalculatorX2,Same,Access
;
              movlw     EEPROM_WritePageSize
              subwf     CalculatorX0,W,Access
              btfsc     CarryFlag
              goto      Event_X_WriteEEPROM_GSMReadPointerVerified 
              movf      CalculatorX1,W,Access
              btfss     ZeroFlag
              goto      Event_X_WriteEEPROM_GSMReadPointerVerified 
              movf      CalculatorX2,W,Access
              btfss     ZeroFlag
              goto      Event_X_WriteEEPROM_GSMReadPointerVerified 
;
; Advance the GSM 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     GSMReadPointerH,Same,Banked
              movlw     0
              addwfc    GSMReadPointerHH,Same,Banked
;
              movlw     6
              subwf     GSMReadPointerHH,W,Banked
              btfss     CarryFlag
              goto      Event_X_WriteEEPROM_GSMReadPointerVerified 
;
              movlw     0x00
              movwf     GSMReadPointer,Banked
;
              movlw     0x01
              movwf     GSMReadPointerH,Banked
;
              movlw     0x04
              movwf     GSMReadPointerHH,Banked
;             
Event_X_WriteEEPROM_GSMReadPointerVerified:
;
; Validate the LOG 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     LogReadPointerHH,W,Banked
              btfss     CarryFlag
              goto      Event_X_WriteEEPROM_LogReadOutOfBounds
;
              movlw     6
              subwf     LogReadPointerHH,W,Banked
              btfss     CarryFlag
              goto      Event_X_WriteEEPROM_LogReadInBounds
;
Event_X_WriteEEPROM_LogReadOutOfBounds:
;
              movf      LogWritePointer,W,Banked
              movwf     LogReadPointer,Banked
              movf      LogWritePointerH,W,Banked
              movwf     LogReadPointerH,Banked
              movf      LogWritePointerHH,W,Banked
              movwf     LogReadPointerHH,Banked
;
              bsf       ExtEE_ReadPointerOutOfBounds ;Garbage flags are fully utilised, otherwise I would have differentiated here
;
Event_X_WriteEEPROM_LogReadInBounds:
;
; Check that the WritePointer won't overtake the LogReadPointer
; - If the write pointer >= read pointer we are good
;
              movf      LogWritePointer,W,Banked
              subwf     LogReadPointer,W,Banked
              movwf     CalculatorX0
              movf      LogWritePointerH,W,Banked
              subwfb    LogReadPointerH,W,Banked
              movwf     CalculatorX1      
              movf      LogWritePointerHH,W,Banked
              subwfb    LogReadPointerHH,W,Banked
              movwf     CalculatorX2
              btfss     CarryFlag
              goto      Event_X_WriteEEPROM_LogReadPointerVerified 
              btfsc     ZeroFlag
              goto      Event_X_WriteEEPROM_LogReadPointerVerified 
;
              comf      CalculatorX0,Same,Access
              comf      CalculatorX1,Same,Access
              comf      CalculatorX2,Same,Access
              movlw     1
              addwf     CalculatorX0,Same,Access
              movlw     0
              addwfc    CalculatorX1,Same,Access
              movlw     0
              addwfc    CalculatorX2,Same,Access
;
              movlw     EEPROM_WritePageSize
              subwf     CalculatorX0,W,Access
              btfsc     CarryFlag
              goto      Event_X_WriteEEPROM_LogReadPointerVerified 
              movf      CalculatorX1,W,Access
              btfss     ZeroFlag
              goto      Event_X_WriteEEPROM_LogReadPointerVerified 
              movf      CalculatorX2,W,Access
              btfss     ZeroFlag
              goto      Event_X_WriteEEPROM_LogReadPointerVerified 
;
; 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     LogReadPointerH,Same,Banked
              movlw     0
              addwfc    LogReadPointerHH,Same,Banked
;
              movlw     6
              subwf     LogReadPointerHH,W,Banked
              btfss     CarryFlag
              goto      Event_X_WriteEEPROM_GSMReadPointerVerified 
;
              movlw     0x00
              movwf     LogReadPointer,Banked
;
              movlw     0x01
              movwf     LogReadPointerH,Banked
;
              movlw     0x04
              movwf     LogReadPointerHH,Banked
;             
Event_X_WriteEEPROM_LogReadPointerVerified:
;
              incf      EventState,Same,Banked
;
              goto      Event_X_WriteEEPROM_End
;
Event_X_WriteEEPROM_WritePage:
;
              call      I2C_Start
              rlcf      LogWritePointerHH,W,Banked
              andlw     b'00001110'
              iorlw     b'10100000'
              call      I2C_Tx        
              movf      LogWritePointerH,W,Banked
              call      I2C_Tx
              movf      LogWritePointer,W,Banked
              call      I2C_Tx
;
              movlw     EEPROM_WritePageSize
              movwf     ScratchPad0,Access
;
Event_X_WriteEEPROM_WritePage1:
;
              call      EEPROM_ReadBuffer
              call      I2C_Tx
;
              decfsz    ScratchPad0,Same,Access
              goto      Event_X_WriteEEPROM_WritePage1
;
              call      I2C_Stop
;
              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,Access
              movlw     b'01000001'
              movwf     T1CON,Access
;
              incf      EventState,Same,Banked
;
              goto      Event_X_WriteEEPROM_End
;
Event_X_WriteEEPROM_WaitWrite:
;
              btfss     _TMR1IF
              goto      Event_X_WriteEEPROM_WaitWrite_End
;
              movlw     EEPROM_WritePageSize
              addwf     LogWritePointer,Same,Banked
              movlw     0
              addwfc    LogWritePointerH,Same,Banked
              movlw     0
              addwfc    LogWritePointerHH,Same,Banked
;
              movlw     6
              subwf     LogWritePointerHH,W,Banked
              btfss     CarryFlag
              goto      Event_X_WriteEEPROM_SkipWrapAround
;
              movlw     0x00
              movwf     LogWritePointer,Banked
              movlw     0x00
              movwf     LogWritePointerH,Banked
              movlw     0x04
              movwf     LogWritePointerHH,Banked
;
              movf      LogWritePointer,W,Banked
              subwf     GSMReadPointer,W,Banked
              movf      LogWritePointerH,W,Banked
              subwfb    GSMReadPointerH,W,Banked
              movf      LogWritePointerHH,W,Banked
              subwfb    GSMReadPointerHH,W,Banked
              btfss     ZeroFlag
              goto      Event_X_WriteEEPROM_SkipMakeLoggingSpace
;
              movlw     0x00
              movwf     GSMReadPointer,Banked
;
              movlw     0x01
              movwf     GSMReadPointerH,Banked
;
              movlw     0x04
              movwf     GSMReadPointerHH,Banked
;
              bsf       ExtEE_MadeLoggingSpace
;             
Event_X_WriteEEPROM_SkipMakeLoggingSpace:
;
Event_X_WriteEEPROM_SkipWrapAround:
;
              movlw     EEPROM_WritePageSize
              subwf     EEPROM_Buffered,W,Banked
              btfsc     CarryFlag
              goto      Event_X_WriteEEPROM_WaitWrite1
;
              btfss     StorePower
              bcf       Power
;
              call      I2C_Delay
;
              call      RemoveEventFromQueue              
;
              goto      Event_X_WriteEEPROM_WaitWrite_End 
;
Event_X_WriteEEPROM_WaitWrite1:
;
              movlw     3                        ;To save time keep the EEPROM powered up and write the next page
              movwf     EventState,Banked 
;
Event_X_WriteEEPROM_WaitWrite_End:
;
              goto      Event_X_WriteEEPROM_End
;
Event_X_WriteEEPROM_End:
;
              LiveDebug LiveDebug_WriteExtEEPROM_End
;
              goto      ProcessEvent_End
;
;*************************************************
;
Event_X_RefreshNV:
;
              LiveDebug LiveDebug_RefreshNV_Start
;
              clrf      PCLATU,Access
              movlw     HIGH(RefreshNVDispatchTable)
              movwf     PCLATH,Access
              rlcf      EventState,W,Banked
              rlcf      WREG,W,Access
              andlw     b'00001100'
              addlw     LOW(RefreshNVDispatchTable)
              btfsc     CarryFlag
              incf      PCLATH,Same,Access 
              movwf     PCL,Access
;
RefreshNVDispatchTable:
;
RNVDT00:      goto      Event_X_RefreshNV_IdleCheck
RNVDT01:      goto      Event_X_RefreshNV_Write
RNVDT02:      goto      Event_X_RefreshNV_Complete
RNVDT03:      nop
              nop
;
              call      RemoveEventFromQueue
;
              LiveDebug LiveDebug_UnknownState
;
              goto      Event_X_RefreshNV_End
;
;*************************************************
;
Event_X_RefreshNV_IdleCheck:
;
              btfsc     _EEWR
              goto      Event_X_RefreshNV_IdleCheck_End
;
              incf      EventState,Same,Banked
;
Event_X_RefreshNV_IdleCheck_End:
;
              goto      Event_X_RefreshNV_End
;
Event_X_RefreshNV_Write:
;
              call      RemoveEventFromQueue     ;We need to get to the address and the data
              call      RemoveEventFromQueue     ;This is the address
              movwf     EEADR,Access
              call      ReadEventQueue           ;This is the data
              call      WriteInternalEEPROM
;
              movlw     2                        ;RemoveEventFromQueue clears EventState_0, but we want to go to the next state, so load it with 2
              movwf     EventState,Banked
;
              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
              call      PreemptEventsInQueue
;
              goto      Event_X_RefreshNV_End
;
Event_X_RefreshNV_Complete:
;
              btfsc     _EEWR
              goto      Event_X_RefreshNV_Complete_End
;
              call      RemoveEventFromQueue
; 
              bsf       BankSwitchRequired
;
Event_X_RefreshNV_Complete_End:
;
              goto      Event_X_RefreshNV_End
;
Event_X_RefreshNV_End:
;
              LiveDebug LiveDebug_RefreshNV_End
;
              goto      ProcessEvent_End
;
;*************************************************
;
Event_X_QueueDailyLog:
;
              LiveDebug LiveDebug_QueueDailyLog_Start
;
              clrf      PCLATU,Access
              movlw     HIGH(QueueDailyLogDispatchTable)
              movwf     PCLATH,Access
              rlcf      EventState,W,Banked
              rlcf      WREG,W,Access
              andlw     b'00111100'
              addlw     LOW(QueueDailyLogDispatchTable)
              btfsc     CarryFlag
              incf      PCLATH,Same,Access 
              movwf     PCL,Access
;
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
              nop
QDLDT10:      nop
              nop
QDLDT11:      nop
              nop
QDLDT12:      nop
              nop
QDLDT13:      nop
              nop
QDLDT14:      nop
              nop
QDLDT15:      nop
              nop
;
              call      RemoveEventFromQueue
;
              LiveDebug LiveDebug_UnknownState
;
              goto      Event_X_QueueDailyLog_End
;
Event_X_QueueDailyLog_PowerOn:
;
 ;             bcf       StorePower      It is not necessary to switch the I2C devices on, because this is queued in RAM
 ;             btfsc     Power           for another part of the program to write it to EEPROM
 ;             bsf       StorePower      - If this code does get put back then remeber to put back the code to switch it off again
 ;             bsf       Power             - See below
;
              clrf      T1CON,Access
              movlw     HIGH(65536-32) ;Give the EEPROM 1msec to wake up - is this necessary - the log is written to the EEPROM queue which then writes it to EEPROM???
              movwf     TMR1H,Access
              movlw     LOW(65536-32)
              movwf     TMR1L,Access
              bcf       _TMR1IF
              movlw     b'00000000'
              movwf     T1GCON,Access
              movlw     b'01000001'
              movwf     T1CON,Access
;
              incf      EventState,Same,Banked
;
              goto      Event_X_QueueDailyLog_End
;
Event_X_QueueDailyLog_WaitPowerOn:
;
              btfss     _TMR1IF
              goto      Event_X_QueueDailyLog_WPO_End
;
              incf      EventState,Same,Banked
;
Event_X_QueueDailyLog_WPO_End:
;
              goto      Event_X_QueueDailyLog_End
;
Event_X_QueueDailyLog_ReadTimeAndDate1:
;
              bsf       RTC_PU
;
              call      I2C_Delay
;
              call      I2C_RTC_Start               
              movlw     b'11010000'
              call      I2C_RTC_Tx        
              movlw     b'00000000'              ;Read from the Seconds register
              call      I2C_RTC_Tx
              call      I2C_RTC_Start
              movlw     b'11010001'
              call      I2C_RTC_Tx
;
              bsf       AckTx
              call      I2C_RTC_Rx                   ;Seconds
              movwf     RTC_Seconds,Banked
;
; Allow other events to queue   
;
              incf      EventState,Same,Banked
;
              goto      Event_X_QueueDailyLog_End
;
Event_X_QueueDailyLog_ReadTAndD2:
;
; Carry on reading from the Minutes
;
              movlw     HIGH(RTC_Minutes)
              movwf     FSR0H,Access
              movlw     LOW(RTC_Minutes)
              movwf     FSR0L,Access
;
              bsf       AckTx
              call      I2C_RTC_Rx                   ;Minutes
              movwf     POSTINC0
              call      I2C_RTC_Rx                   ;Hours
              movwf     POSTINC0
              call      I2C_RTC_Rx                   ;DayOfWeek
              movwf     POSTINC0
              call      I2C_RTC_Rx                   ;Date
              movwf     POSTINC0
              call      I2C_RTC_Rx                   ;Month
              movwf     POSTINC0
              bcf       AckTx
              call      I2C_RTC_Rx                   ;Year
              bsf       AckTx
              movwf     POSTINC0
              call      I2C_RTC_Stop
;
              bcf       RTC_PU
;
  ;            btfss     StorePower        See explanation above
  ;            bcf       Power
;
              call      I2C_Delay
;
              incf      EventState,Same,Banked
;
              goto      Event_X_QueueDailyLog_End
;
Event_X_QueueDailyLog_LogHiLoEvent:
;
              movlw     0xFA
              movwf     HiLoDetail1,Banked
              movlw     0xCE
              movwf     HiLoDetail2,Banked
;
              call      LogHiLoEvent
;
              incf      EventState,Same,Banked
;
              goto      Event_X_QueueDailyLog_End
;
Event_X_QueueDailyLog_SecondsH:
;
              call      CalculateSecondsOffset_Hours
;
              incf      EventState,Same,Banked
;
              goto      Event_X_QueueDailyLog_End
;
Event_X_QueueDailyLog_SecondsM:
;
              call      CalculateSecondsOffset_Minutes
;
              incf      EventState,Same,Banked
;
              goto      Event_X_QueueDailyLog_End
;
Event_X_QueueDailyLog_SecondsS:
;
              call      CalculateSecondsOffset_Seconds
;
              incf      EventState,Same,Banked
;
              goto      Event_X_QueueDailyLog_End
;
Event_X_QueueDailyLog_ResetHiLo
;
; Reset the Highs and Lows
;
              movlw     0xFF
              movwf     HumidityLo,Banked
              movwf     TemperatureLo,Banked
              movwf     TemperatureLoH,Banked 
;
              movlw     0x00
              movwf     HumidityHi,Banked
              movwf     TemperatureHi,Banked
              movwf     TemperatureHiH,Banked
;
; And then populate them with the current temperature and humidity
;
              movlw     Event_DetermineHiLo
              call      WriteEventToQueue
;
              call      RemoveEventFromQueue              
;
              movlw     Event_SampleBatteryVoltage
              call      WriteEventToQueue
;
              movlw     Event_SnapShot
              call      WriteEventToQueue
;
              goto      Event_X_QueueDailyLog_End
;
Event_X_QueueDailyLog_End:
;
              LiveDebug LiveDebug_QueueDailyLog_End
;
              goto      ProcessEvent_End
;
;*************************************************
;
Event_X_SampleBatteryVoltage:
;
              LiveDebug LiveDebug_SampleBattery_Start
;
              clrf      PCLATU,Access
              movlw     HIGH(SampleBatteryVoltageDispatchTable)
              movwf     PCLATH,Access
              rlcf      EventState,W,Banked
              rlcf      WREG,W,Access
              andlw     b'00001100'
              addlw     LOW(SampleBatteryVoltageDispatchTable)
              btfsc     CarryFlag
              incf      PCLATH,Same,Access 
              movwf     PCL,Access
;
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
;
              call      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 :-)
;
              bcf       SelectGSM
              bsf       SelectUSB
;
              clrf      T1CON,Access
              movlw     HIGH(65536-3125) ;Give the big USB power caps a chance to charge up - looks like 100msec is enough
              movwf     TMR1H,Access
              movlw     LOW(65536-3125)
              movwf     TMR1L,Access
              bcf       _TMR1IF
              movlw     b'00000000'
              movwf     T1GCON,Access
              movlw     b'01000001'
              movwf     T1CON,Access
;
              incf      EventState,Same,Banked
;
              goto      Event_X_SampleBatteryVoltage_End
;
Event_X_SampleBatteryVoltage_Charge:
;
              btfss     _TMR1IF
              goto      Event_X_SBV_Charge_End
;
              movlw     Track_USBAlert
              movwf     ADCON0,Access
;
              movlw     b'10100000'
              movff     WREG,VREFCON0
;
Event_X_SBV_Charge_FVROn:
;
              movff     VREFCON0,WREG
              btfss     WREG,6,Access
              goto      Event_X_SBV_Charge_FVROn
;
              incf      EventState,Same,Banked
;
Event_X_SBV_Charge_End:
;
              goto      Event_X_SampleBatteryVoltage_End
;
Event_X_SampleBatteryVoltage_Sample:
;
              bsf       _Go
;
Event_X_SBV_Sample_1:
;
              btfsc     _Go
              goto      Event_X_SBV_Sample_1
;
              clrf      ADCON0,Access
;
              movlw     b'00000000'
              movff     WREG,FVRCON
;
              bcf       SelectUSB
              bsf       SelectGSM
;
; See if a device managed to sneak into the picture
;
              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
              movwf     CalculatorX0
              movf      ADRESH,W
              movwf     CalculatorX1
;
              bcf       CarryFlag
              rrcf      CalculatorX1,Same,Access
              rrcf      CalculatorX0,Same,Access
;
 ;             movlw     LOW(225)
 ;             subwf     CalculatorX0,Same,Access
 ;             movlw     HIGH(225)
 ;             subwfb    CalculatorX1,Same,Access
;
 ;             btfss     CarryFlag
 ;             goto      Event_X_SBV_Sample_SkipCalculation
;
              movf      CalculatorX1,W,Access
              movlw     0xFF
              btfss     ZeroFlag
              movwf     CalculatorX0,Access
;
              movf      CalculatorX0,W,Access
              movwf     BatteryVoltage,Banked ;This is a non-volatile variable if it changes it will automatically be written to EEPROM
;            
Event_X_SBV_Sample_SkipCalculation:
;
              clrf      T1CON,Access
              movlw     HIGH(65536-3125) ;Give the big USB power caps a chance to discharge - looks like 100msec is enough
              movwf     TMR1H,Access
              movlw     LOW(65536-3125)
              movwf     TMR1L,Access
              bcf       _TMR1IF
              movlw     b'00000000'
              movwf     T1GCON,Access
              movlw     b'01000001'
              movwf     T1CON,Access
;
              incf      EventState,Same,Banked
;
              goto      Event_X_SampleBatteryVoltage_End
;
Event_X_SampleBatteryVoltage_Discharge:
;
              btfss     _TMR1IF
              goto      Event_X_SBV_Discharge_End
;
              call      RemoveEventFromQueue      
;
              bsf       SendSMS        
;
              goto      Event_X_SBV_Discharge_End
;
Event_X_SBV_Discharge_End:
;
              goto      Event_X_SampleBatteryVoltage_End
;
Event_X_SampleBatteryVoltage_End:
;
              LiveDebug LiveDebug_SampleBattery_End
;
              goto      ProcessEvent_End
;
;*************************************************
;
Event_X_SnapShot:
;
              LiveDebug LiveDebug_SnapShot_Start
;
; As of M103 the code for SnapShot2 was moved to here, so that the time and date stamp arrives at the server first
;
; As of LC07 the SnapShots are the only events, so there is no longer any need to worry about how long this event
; runs for, in other words I can simply read the RTC here without splitting it over multiple states
;
              bsf       RTC_PU
;
              call      I2C_Delay
;
              call      I2C_RTC_Start               
              movlw     b'11010000'
              call      I2C_RTC_Tx        
              movlw     b'00000000'              ;Read from the Seconds register
              call      I2C_RTC_Tx
              call      I2C_RTC_Start
              movlw     b'11010001'
              call      I2C_RTC_Tx
;
              bsf       AckTx
              call      I2C_RTC_Rx                   ;Seconds
              movwf     RTC_Seconds,Banked
              call      I2C_RTC_Rx                   ;Minutes
              movwf     RTC_Minutes,Banked
              call      I2C_RTC_Rx                   ;Hours
              movwf     RTC_Hours,Banked
              call      I2C_RTC_Rx                   ;DayOfWeek
              movwf     RTC_DayOfWeek,Banked
              call      I2C_RTC_Rx                   ;Date
              movwf     RTC_Date,Banked
              call      I2C_RTC_Rx                   ;Month
              movwf     RTC_Month,Banked
              bcf       AckTx
              call      I2C_RTC_Rx                   ;Year
              bsf       AckTx
              movwf     RTC_Year,Banked
              call      I2C_RTC_Stop
;
              bcf       RTC_PU
;
              call      I2C_Delay
;
              movlw     LogEvent_SnapShot
              movwf     Checksum,Banked
              call      EEPROM_WriteBuffer
;
              movlw     'S'
              addwf     Checksum,Same,Banked
              call      EEPROM_WriteBuffer
;
              movlw     's'
              addwf     Checksum,Same,Banked
              call      EEPROM_WriteBuffer
;
Event_X_SnapShot_FetchGust1: ;N607
;
              movff     Gust1,CalculatorX0
              movff     Gust1H,CalculatorX1
;
              movf      Gust1,W,Banked
              subwf     CalculatorX0,W,Access
              btfss     ZeroFlag
              goto      Event_X_SnapShot_FetchGust1
;
              movf      Gust1H,W,Banked
              subwf     CalculatorX1,W,Access
              btfss     ZeroFlag
              goto      Event_X_SnapShot_FetchGust1
;
              movf      Gust2,W,Banked
              subwf     CalculatorX0,W,Access
              movf      Gust2H,W,Banked
              subwfb    CalculatorX1,W,Access
;
              btfss     CarryFlag
              goto      Event_X_SnapShot2A
;
              movff     Gust2,CalculatorX0
              movff     Gust2H,CalculatorX1
;
Event_X_SnapShot2A:
;
              movf      Gust3,W,Banked
              subwf     CalculatorX0,W,Access
              movf      Gust3H,W,Banked
              subwfb    CalculatorX1,W,Access
;
              btfss     CarryFlag
              goto      Event_X_SnapShot2B
;
              movff     Gust3,CalculatorX0
              movff     Gust3H,CalculatorX1
;
Event_X_SnapShot2B:
;
              movf      Gust4,W,Banked
              subwf     CalculatorX0,W,Access
              movf      Gust4H,W,Banked
              subwfb    CalculatorX1,W,Access
;
              btfss     CarryFlag
              goto      Event_X_SnapShot2C
;
              movff     Gust4,CalculatorX0
              movff     Gust4H,CalculatorX1
;
Event_X_SnapShot2C:
;
              movf      WindSpeedAverage,W,Banked ;N915 CalculatorX0,W,Access
              addwf     Checksum,Same,Banked
              call      EEPROM_WriteBuffer       
              movf      WindSpeedAverageH,W,Banked ;N915 CalculatorX1,W,Access
              addwf     Checksum,Same,Banked
              call      EEPROM_WriteBuffer
;
              movf      RainPulse,W,Banked
              addwf     Checksum,Same,Banked
              call      EEPROM_WriteBuffer
              movf      RainPulseH,W,Banked
              addwf     Checksum,Same,Banked
              call      EEPROM_WriteBuffer
              movf      RainPulseHH,W,Banked
              addwf     Checksum,Same,Banked
              call      EEPROM_WriteBuffer
;
              rlncf     GSM_TimeZone_Tens,W,Banked
              addwf     GSM_TimeZone_Units,Same,Banked
              rlncf     WREG,W,Access
              rlncf     WREG,W,Access
              addwf     GSM_TimeZone_Units,Same,Banked
;             
              movf      GSM_TimeZone_Sign,W,Banked
              xorlw     '-'
              btfsc     ZeroFlag
              negf      GSM_TimeZone_Units,Banked
;
              movf      GSM_TimeZone_Units,W,Banked
              addwf     Checksum,Same,Banked 
              call      EEPROM_WriteBuffer
;
              movf      RTC_Year,W,Banked
              addwf     Checksum,Same,Banked
              call      EEPROM_WriteBuffer
;
              movf      RTC_Month,W,Banked
              addwf     Checksum,Same,Banked
              call      EEPROM_WriteBuffer
;
              movf      RTC_Date,W,Banked 
              addwf     Checksum,Same,Banked
              call      EEPROM_WriteBuffer
;
              movf      RTC_Hours,W,Banked
              addwf     Checksum,Same,Banked
              call      EEPROM_WriteBuffer
;
              movf      RTC_Minutes,W,Banked
              addwf     Checksum,Same,Banked
              call      EEPROM_WriteBuffer
;
              movf      RTC_Seconds,W,Banked
              addwf     Checksum,Same,Banked
              call      EEPROM_WriteBuffer
;
              movlw     3 ;Spare  
              addwf     Checksum,Same,Banked
              call      EEPROM_WriteBuffer
;
              movlw     2 ;Spare
              addwf     Checksum,Same,Banked
              call      EEPROM_WriteBuffer
;
              movlw     1 ;Spare
              addwf     Checksum,Same,Banked
              call      EEPROM_WriteBuffer
;
              comf      Checksum,W,Banked
              addlw     1
              call      EEPROM_WriteBuffer
;
              call      RemoveEventFromQueue      
;             
              movlw     Event_WriteEEPROM        ;Write this SnapShot to EEPROM
              call      WriteEventToQueue
;             
              movlw     Event_SnapShot2          ;And then buffer the second SnapShot 
                                                 ; - as of M103 this is now actually the first SnapShot to arrive at the server
              call      WriteEventToQueue
;
              LiveDebug LiveDebug_SnapShot_End
;
              goto      ProcessEvent_End
;
;*************************************************
;
Event_X_SnapShot2:
;
              LiveDebug LiveDebug_SnapShot_Start
;
Event_X_SnapShot2_FetchWindSpeed1: ;N607
;
              movff     WindSpeed1,CalculatorX0
              movff     WindSpeed1H,CalculatorX1
;
              movf      WindSpeed1,W,Banked
              subwf     CalculatorX0,W,Access
              btfss     ZeroFlag
              goto      Event_X_SnapShot2_FetchWindSpeed1
;
              movf      WindSpeed1H,W,Banked
              subwf     CalculatorX1,W,Access
              btfss     ZeroFlag
              goto      Event_X_SnapShot2_FetchWindSpeed1
;
              movf      WindSpeed2,W,Banked
              subwf     CalculatorX0,W,Access
              movf      WindSpeed2H,W,Banked
              subwfb    CalculatorX1,W,Access
;
              btfsc     CarryFlag
              goto      Event_X_SnapShotA
;
              movff     WindSpeed2,CalculatorX0
              movff     WindSpeed2H,CalculatorX1
;
Event_X_SnapShotA:
;
              movf      WindSpeed3,W,Banked
              subwf     CalculatorX0,W,Access
              movf      WindSpeed3H,W,Banked
              subwfb    CalculatorX1,W,Access
;
              btfsc     CarryFlag
              goto      Event_X_SnapShotB
;
              movff     WindSpeed3,CalculatorX0
              movff     WindSpeed3H,CalculatorX1
;
Event_X_SnapShotB:
;
              movf      WindSpeed4,W,Banked
              subwf     CalculatorX0,W,Access
              movf      WindSpeed4H,W,Banked
              subwfb    CalculatorX1,W,Access
;
              btfsc     CarryFlag
              goto      Event_X_SnapShotC
;
              movff     WindSpeed4,CalculatorX0
              movff     WindSpeed4H,CalculatorX1
;
Event_X_SnapShotC:
;
              movlw     LogEvent_SnapShot
              movwf     Checksum,Banked
              call      EEPROM_WriteBuffer
;
              movlw     'S'
              addwf     Checksum,Same,Banked
              call      EEPROM_WriteBuffer
;
              movlw     'S'
              addwf     Checksum,Same,Banked
              call      EEPROM_WriteBuffer
;
              movlw     LOW(Humidity)
              movwf     FSR1L,Access             ;Remember EEPROM_WriteBuffer uses FSR0
              movlw     HIGH(Humidity)
              movwf     FSR1H,Access  
;
; Check to see if the current reading is DEAD or NOT!
; - if NOT then continue as normal
; - otherwise try to intervene
;
              movlw     0xDE                     ;Check if the high byte of the temperature is 0xDE from 0xDEAD
              subwf     TemperatureH,W,Banked
              btfss     ZeroFlag
              goto      NoInterventionRequired
;
              movf      POSTINC1,W,Access ;Maintain the pointer, which won't be used for the intervention
;
; Try to find a good reading in the past 30 minutes from the buffers
;
              movlw     0xDE                     ;Check if the high byte of the temperature buffer is 0xDE from 0xDEAD
              subwf     Temperature1H,W,Banked
              btfss     ZeroFlag
              goto      UseBuffer1 
;
              movlw     0xDE                     ;Check if the high byte of the temperature buffer is 0xDE from 0xDEAD
              subwf     Temperature2H,W,Banked
              btfss     ZeroFlag
              goto      UseBuffer2
;
              movlw     0xDE                     ;Check if the high byte of the temperature buffer is 0xDE from 0xDEAD
              subwf     Temperature3H,W,Banked
              btfss     ZeroFlag
              goto      UseBuffer3
;
              movlw     0xDE                     ;Check if the high byte of the temperature buffer is 0xDE from 0xDEAD
              subwf     Temperature4H,W,Banked
              btfss     ZeroFlag
              goto      UseBuffer4
; 
              movlw     0xDE                     ;Check if the high byte of the temperature buffer is 0xDE from 0xDEAD
              subwf     Temperature5H,W,Banked
              btfss     ZeroFlag
              goto      UseBuffer5
              goto      UseBuffer6
;
UseBuffer1:
;
              movf      Humidity1,W,Banked
              addwf     Checksum,Same,Banked
              call      EEPROM_WriteBuffer       
              movf      Temperature1,W,Banked
              addwf     Checksum,Same,Banked
              call      EEPROM_WriteBuffer
              movf      Temperature1H,W,Banked
              addwf     Checksum,Same,Banked
              call      EEPROM_WriteBuffer
;
              goto      InterventionEnd
;
UseBuffer2:
;
              movf      Humidity2,W,Banked
              addwf     Checksum,Same,Banked
              call      EEPROM_WriteBuffer       
              movf      Temperature2,W,Banked
              addwf     Checksum,Same,Banked
              call      EEPROM_WriteBuffer
              movf      Temperature2H,W,Banked
              addwf     Checksum,Same,Banked
              call      EEPROM_WriteBuffer
;
              goto      InterventionEnd
;
UseBuffer3:
;
              movf      Humidity3,W,Banked
              addwf     Checksum,Same,Banked
              call      EEPROM_WriteBuffer       
              movf      Temperature3,W,Banked
              addwf     Checksum,Same,Banked
              call      EEPROM_WriteBuffer
              movf      Temperature3H,W,Banked
              addwf     Checksum,Same,Banked
              call      EEPROM_WriteBuffer
;
              goto      InterventionEnd
;
UseBuffer4:
;
              movf      Humidity4,W,Banked
              addwf     Checksum,Same,Banked
              call      EEPROM_WriteBuffer       
              movf      Temperature4,W,Banked
              addwf     Checksum,Same,Banked
              call      EEPROM_WriteBuffer
              movf      Temperature4H,W,Banked
              addwf     Checksum,Same,Banked
              call      EEPROM_WriteBuffer
;
              goto      InterventionEnd
;
UseBuffer5:
;
              movf      Humidity5,W,Banked
              addwf     Checksum,Same,Banked
              call      EEPROM_WriteBuffer       
              movf      Temperature5,W,Banked
              addwf     Checksum,Same,Banked
              call      EEPROM_WriteBuffer
              movf      Temperature5H,W,Banked
              addwf     Checksum,Same,Banked
              call      EEPROM_WriteBuffer
;
              goto      InterventionEnd
;
UseBuffer6:
;
              movf      Humidity6,W,Banked
              addwf     Checksum,Same,Banked
              call      EEPROM_WriteBuffer       
              movf      Temperature6,W,Banked
              addwf     Checksum,Same,Banked
              call      EEPROM_WriteBuffer
              movf      Temperature6H,W,Banked
              addwf     Checksum,Same,Banked
              call      EEPROM_WriteBuffer
;
              goto      InterventionEnd
;
NoInterventionRequired:
;
              movf      POSTINC1,W,Access ;Humidity
              addwf     Checksum,Same,Banked
              call      EEPROM_WriteBuffer       
              movf      POSTINC1,W,Access ;Temperature
              addwf     Checksum,Same,Banked
              call      EEPROM_WriteBuffer
              movf      POSTINC1,W,Access ;TemperatureH
              addwf     Checksum,Same,Banked
              call      EEPROM_WriteBuffer
;
InterventionEnd:
;
              movf      POSTINC1,W,Access      ;Maintain the pointer, but ignore the data
              movf      WindDirection,W,Banked ;WindDirection
              addwf     Checksum,Same,Banked
              call      EEPROM_WriteBuffer
              movf      POSTINC1,W,Access       ;Maintain the pointer, but ignore the data
              movf      WindDirectionH,W,Banked ;WindDirectionH
              addwf     Checksum,Same,Banked
              call      EEPROM_WriteBuffer
              movf      POSTINC1,W,Access    ;Maintain the pointer, but ignore the data
              movf      CalculatorX0,W,Access  ;WindSpeed
              addwf     Checksum,Same,Banked 
              call      EEPROM_WriteBuffer
              movf      POSTINC1,W,Access    ;Maintain the pointer, but ignore the data
              movf      CalculatorX1,W,Access ;WindSpeed1H
              addwf     Checksum,Same,Banked
              call      EEPROM_WriteBuffer
              movf      POSTINC1,W,Access ;Maintain the pointer, but ignore the data
              movlw     VersionYear       ;VersionYear
              addwf     Checksum,Same,Banked
              call      EEPROM_WriteBuffer
              movf      POSTINC1,W,Access ;Maintain the pointer, but ignore the data
              movlw     VersionMonth      ;VersionMonth
              addwf     Checksum,Same,Banked
              call      EEPROM_WriteBuffer
              movf      POSTINC1,W,Access ;Maintain the pointer, but ignore the data
              movlw     VersionDayTens    ;VersionDayTens
              addwf     Checksum,Same,Banked
              call      EEPROM_WriteBuffer
              movf      POSTINC1,W,Access ;Maintain the pointer, but ignore the data
              movlw     VersionDayUnits   ;VersionDayUnits
              addwf     Checksum,Same,Banked
              call      EEPROM_WriteBuffer
;
              movf      POSTINC1,W,Access ;Seconds_Offset
              addwf     Checksum,Same,Banked
              call      EEPROM_WriteBuffer
              movf      POSTINC1,W,Access ;Seconds_OffsetH
              addwf     Checksum,Same,Banked
              call      EEPROM_WriteBuffer
              movf      POSTINC1,W,Access ;Seconds_OffsetHH
              addwf     Checksum,Same,Banked
              call      EEPROM_WriteBuffer
              movf      POSTINC1,W,Access ;Maintain the pointer, but ignore the data
              movf      BatteryVoltage,W,Banked ;BatteryVoltage
              addwf     Checksum,Same,Banked
              call      EEPROM_WriteBuffer
;
              comf      Checksum,W,Banked
              addlw     1
              call      EEPROM_WriteBuffer
;
              call      RemoveEventFromQueue      
;             
              movlw     Event_WriteEEPROM        ;Write this SnapShot to EEPROM
              call      WriteEventToQueue
;
              LiveDebug LiveDebug_SnapShot_End
;
              goto      ProcessEvent_End
;
ProcessEvent_End:
;
;*************************************************
;
              goto      Forever_RainGauge
;
ProcessRTC:
;
              bcf       _INT0IF
; 
              clrwdt
;
              LiveDebug LiveDebug_RTC
;
              bsf       CheckUSBAlert
;
           IFNDEF AcceleratedTime
              movlw     1 
           ELSE
              movlw     AcceleratedTime_Adjustment
           ENDIF
;
              addwf     Seconds_Offset,Same,Banked
;
              btfss     CarryFlag
              goto      ProcessRTC1
;
              movlw     Event_DetermineHiLo      ;Determine the temperature and humidity Highs and Lows every 256s = 4M16S
              call      WriteEventToQueue
;
              movlw     0
              addwfc    Seconds_OffsetH,Same,Banked
              movlw     0
              addwfc    Seconds_OffsetHH,Same,Banked
;
ProcessRTC1:
;
              movlw     LOW(86400)
              subwf     Seconds_Offset,W,Banked
              movlw     HIGH(86400)
              subwfb    Seconds_OffsetH,W,Banked
              movlw     UPPER(86400)
              subwfb    Seconds_OffsetHH,W,Banked
;
              btfss     CarryFlag
              goto      ProcessRTC2
;
              clrf      Seconds_Offset,Banked
              clrf      Seconds_OffsetH,Banked
              clrf      Seconds_OffsetHH,Banked
;
              movlw     Event_QueueDailyLog
              call      WriteEventToQueue
;
              goto      ProcessRTC_End
;
ProcessRTC2:           
;
              movf      SprayingIntervalTimer,W,Banked
              iorwf     SprayingIntervalTimerH,W,Banked
              btfsc     ZeroFlag
              goto      ProcessRTC3
;
              movlw     1
              subwf     SprayingIntervalTimer,Same,Banked
              movlw     0
              subwfb    SprayingIntervalTimerH,Same,Banked
;
              movf      SprayingIntervalTimer,W,Banked
              iorwf     SprayingIntervalTimerH,W,Banked
              btfss     ZeroFlag
              goto      ProcessRTC4
;
ProcessRTC3:
;
              movff     SprayingInterval,SprayingIntervalTimer
              movff     SprayingIntervalH,SprayingIntervalTimerH
;
; N214 when we get here 12 minutes have elapsed and we must log a SnapShot
;
              movlw     Event_SnapShot
              call      WriteEventToQueue
;
; N214 when we get here 12 minutes have elapsed and we must log a SnapShot
;
              decfsz    POSTingDelayMultiplier,Same,Banked
              goto      ProcessRTC4
;
              movlw     1 ; N214 assume we want to transmit every 12 minutes
              movwf     POSTingDelayMultiplier,Banked
;
;
; N213 include this code to post less often at night
;
           IFDEF NightMode
;
              movlw     LOW((NightMode_Start-7)*60*60)
              subwf     Seconds_Offset,W,Banked
              movlw     HIGH((NightMode_Start-7)*60*60)
              subwfb    Seconds_OffsetH,W,Banked
              movlw     UPPER((NightMode_Start-7)*60*60)
              subwfb    Seconds_OffsetHH,W,Banked
;
              btfss     CarryFlag
              goto      NM_AAA
;
              movlw     LOW((NightMode_End+17)*60*60)
              subwf     Seconds_Offset,W,Banked
              movlw     HIGH((NightMode_End+17)*60*60)
              subwfb    Seconds_OffsetH,W,Banked
              movlw     UPPER((NightMode_End+17)*60*60)
              subwfb    Seconds_OffsetHH,W,Banked
;
              btfsc     CarryFlag
              goto      NM_AAA
;
              movlw     NightMode_POSTingDelayTC
              movwf     POSTingDelayMultiplier,Banked
;
NM_AAA:
;
           ENDIF
;
; N213 include this code to post half as often at night
;
;
; N213 include this code to delay longer when POSTs are not acknowledged by the server
;
           IFDEF NAKDelay
;
              movf      NAKDelayMultiplier,W,Banked
              btfsc     ZeroFlag
              goto      ND_AAA
;
              movlw     4
              subwf     NAKDelayMultiplier,W,Banked
              movlw     3
              btfsc     CarryFlag
              movwf     NAKDelayMultiplier,Banked
;
              movf      NAKDelayMultiplier,W,Banked
              addwf     POSTingDelayMultiplier,Same,Banked
;
ND_AAA:
;
           ENDIF
;
; N213 include this code to delay longer when POSTs are not acknowledged by the server
;
#define BlockSnapShotSeconds 86400-(10*60) ;Block SnapShots from being queued for this long before the DailyLog to minimise failure of the DailyLog
;
              movlw     LOW(BlockSnapShotSeconds)
              subwf     Seconds_Offset,W,Banked
              movlw     HIGH(BlockSnapShotSeconds)
              subwfb    Seconds_OffsetH,W,Banked
              movlw     UPPER(BlockSnapShotSeconds)
              subwfb    Seconds_OffsetHH,W,Banked
;
              btfsc     CarryFlag
              goto      ProcessRTC4
;
              bsf       SendSMS
;
; N213 include this code to prevent POSTing below 3V8
;
           IFDEF DoNotPostBelow3V8   
;
              movlw     Event_SampleBatteryVoltage
              call      WriteEventToQueue
;
           ENDIF
;
; N213 include this code to prevent POSTing below 3V8
;
ProcessRTC4:
;
ProcessRTC_End:
;
              return
;
TimeTicks:
;
              movlw     0                        ;Lock out rain pulses for 250msec to filter out any bouncing
              movff     WREG,T4CON
              movlw     217
              movff     WREG,PR4
              movlw     0
              movff     WREG,TMR4 
              bcf       _TMR4IF
              movlw     b'01000100'
              movff     WREG,T4CON
;
              incfsz    RainTickCompensationTime,W,Banked
              incf      RainTickCompensationTime,Same,Banked
;
              return
;
CaptureRainPulse:
;
              LiveDebug_RainPulse = TRUE
              LiveDebug LiveDebug_CaptureRainPulse
              LiveDebug_RainPulse = FALSE
;
              bcf       _INT1IF
;  
              movf      RainTickCompensationTime,W,Banked
              btfsc     ZeroFlag                 ;Check if the lock out timer has expired
              goto      CaptureRainPulseEnd  
;
              movlw     0                        ;Lock out rain pulses for 250msec to filter out any bouncing
              movff     WREG,T4CON
              movlw     217
              movff     WREG,PR4
              movlw     0
              movff     WREG,TMR4 
              bcf       _TMR4IF
              movlw     b'01000100'
              movff     WREG,T4CON
;
              lfsr      0,RainTickCompensationTable
              movf      RainTickCompensationTime,W,Banked
              andlw     b'00111111'
              movwf     FSR0L,Access
              movf      INDF0,W,Access
              addwf     RainTickCompensation,Same,Banked
              movlw     0
              addwfc    RainTickCompensationH,Same,Banked
;
              clrf      RainTickCompensationTime,Banked
;
              movlw     LOW(RainTickVolume)
              subwf     RainTickCompensation,W,Banked
              movlw     HIGH(RainTickVolume)
              subwfb    RainTickCompensationH,W,Banked
;
              btfss     CarryFlag
              goto      NoExtraRainTick  
;
              movlw     LOW(RainTickVolume)
              subwf     RainTickCompensation,Same,Banked
              movlw     HIGH(RainTickVolume)
              subwfb    RainTickCompensationH,Same,Banked
;
              movlw     2
;
              goto      AccumulateRainTick
;
NoExtraRainTick:
              movlw     1
;
AccumulateRainTick:
;
              addwf     RainPulse,Same,Banked
              movlw     0
              addwfc    RainPulseH,Same,Banked
              movlw     0
              addwfc    RainPulseHH,Same,Banked
;
 ;M103             btfss     CarryFlag                ;Limit to maximum
              goto      CaptureRainPulse1
;
              movlw     0xFF
              movwf     RainPulse,Banked
              movwf     RainPulseH,Banked
              movwf     RainPulseHH,Banked
;
CaptureRainPulse1:
;
   goto CaptureRainPulseEnd ;LC07
;
              movlw     EEPROM_BufferSize+2      ;(I need space for 3 bytes)
              subwf     EEPROM_Buffered,W,Banked
              addlw     3
              btfss     CarryFlag
              goto      CaptureRainPulse2
;
              incfsz    RainPulseTimeLost,W,Banked
              incf      RainPulseTimeLost,Same,Banked
;
              goto      CaptureRainPulseEnd
;
CaptureRainPulse2:
;
              movf      Seconds_OffsetHH,W,Banked ;Queue it for logging to EEPROM
              movlw     LogEvent_RainPulse+0
              btfss     ZeroFlag
              movlw     LogEvent_RainPulse+1
              call      EEPROM_WriteBuffer
              movf      Seconds_OffsetH,W,Banked
              call      EEPROM_WriteBuffer
              movf      Seconds_Offset,W,Banked
              call      EEPROM_WriteBuffer
;             
              movlw     Event_WriteEEPROM
              call      WriteEventToQueue
;
CaptureRainPulseEnd:
;
              return
;
TimeTicks_GSM:
;
;
              clrf      T3CON,Access             ;Lock out rain pulses for 189msec, (supposed to be 250msec, but I can't easily get there!), to filter out any bouncing
;
              clrf      TMR3H,Access             ;Start from 0
              clrf      TMR3L,Access
;
              bcf       _TMR3IF                  ;If we overflow then the anemometer is going way too slow
;
              clrf      T3GCON,Access            ;No gating  
;
              movlw     b'00110011'              ;Start TMR3 - 16-bit - Fosc - Pre=8
              movwf     T3CON,Access  
;
              incfsz    RainTickCompensationTime,W,Banked
              incf      RainTickCompensationTime,Same,Banked
;
              return
;
CaptureRainPulse_GSM:
;
 ;No live debug while talking to the GSM             LiveDebug LiveDebug_CaptureRainPulse
;
              bcf       _INT1IF
;  
              movf      RainTickCompensationTime,W,Banked
              btfsc     ZeroFlag                 ;Check if the lock out timer has expired
              goto      CaptureRainPulseEnd  
;
              clrf      T3CON,Access             ;Lock out rain pulses for 189msec, (supposed to be 250msec, but I can't easily get there!), to filter out any bouncing
;
              clrf      TMR3H,Access             ;Start from 0
              clrf      TMR3L,Access
;
              bcf       _TMR3IF                  ;If we overflow then the anemometer is going way too slow
;
              clrf      T3GCON,Access            ;No gating  
;
              movlw     b'00110011'              ;Start TMR3 - 16-bit - Fosc - Pre=8
              movwf     T3CON,Access  
;
              lfsr      0,RainTickCompensationTable
              movf      RainTickCompensationTime,W,Banked
;
              movwf     CalculatorX0,Access
              clrf      CalculatorX1,Access
;
              bcf       CarryFlag
              rlcf      CalculatorX0,Same,Access ;x2
              rlcf      CalculatorX1,Same,Access 
              rlcf      CalculatorX0,Same,Access ;x4
              rlcf      CalculatorX1,Same,Access
              rlcf      CalculatorX0,W,Access    ;*8
              movwf     CalculatorY0,Access
              rlcf      CalculatorX1,W,Access
              movwf     CalculatorY1,Access
;
              movf      CalculatorY0,W,Access
              addwf     CalculatorX0,Same,Access
              movf      CalculatorY1,W,Access
              addwfc    CalculatorX1,Same,Access
;
              rrcf      CalculatorX1,Same,Access ;/2
              rrcf      CalculatorX0,Same,Access
              rrcf      CalculatorX1,Same,Access ;/4
              rrcf      CalculatorX0,Same,Access
              rrcf      CalculatorX1,Same,Access ;/8
              rrcf      CalculatorX0,Same,Access
              rrcf      CalculatorX1,Same,Access ;/16
              rrcf      CalculatorX0,Same,Access
;
              movf      CalculatorX0,W,Access

              andlw     b'00111111'
              movwf     FSR0L,Access
              movf      INDF0,W,Access
              addwf     RainTickCompensation,Same,Banked
              movlw     0
              addwfc    RainTickCompensationH,Same,Banked
;
              clrf      RainTickCompensationTime,Banked
;
              movlw     LOW(RainTickVolume)
              subwf     RainTickCompensation,W,Banked
              movlw     HIGH(RainTickVolume)
              subwfb    RainTickCompensationH,W,Banked
;
              btfss     CarryFlag
              goto      NoExtraRainTick_GSM
;
              movlw     LOW(RainTickVolume)
              subwf     RainTickCompensation,Same,Banked
              movlw     HIGH(RainTickVolume)
              subwfb    RainTickCompensationH,Same,Banked
;
              movlw     2
;
              goto      AccumulateRainTick_GSM
;
NoExtraRainTick_GSM:
;
              movlw     1
;
AccumulateRainTick_GSM:
;
              addwf     RainPulse,Same,Banked
              movlw     0
              addwfc    RainPulseH,Same,Banked
              movlw     0
              addwfc    RainPulseHH,Same,Banked
;
 ;M103             btfss     CarryFlag                ;Limit to maximum
              goto      CaptureRainPulse_GSM_1
;
              movlw     0xFF
              movwf     RainPulse,Banked
              movwf     RainPulseH,Banked
              movwf     RainPulseHH,Banked
;
CaptureRainPulse_GSM_1:
;
CaptureRainPulse_GSM_End:
;
              return
;
;***************************************
;
; This subroutine verifies the non-volatiles in EEPROM against RAM
;
;***************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
VerifySettings:
;
              LiveDebug LiveDebug_VerifySettings_Start
;               
              lfsr      0,FirmwareYear           ;Point to first non-volatile variable in RAM
;
              movlw     NV_BoundaryHi-NV_BoundaryLo
              movwf     ScratchPad0,Access
;
              movlw     EE_ActiveBank            ;Find the active EEPROM bank, so we can check the other one
              call      ReadInternalEEPROM
              xorlw     0x5A
              btfsc     ZeroFlag
              goto      VerifySettings_Offset5A
              xorlw     0xA5^0x5A
              btfsc     ZeroFlag 
              goto      VerifySettings_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_Offset5A:
;
              movlw     0x40
              goto      VerifySettings_1
; 
VerifySettings_OffsetA5:
;
              movlw     0x00
              goto      VerifySettings_1
;
VerifySettings_1:
;
              movwf     EEADR,Access
;
              clrf      PCLATU,Access
              movlw     HIGH(VerifySettings_DispatchTable)
              movwf     PCLATH,Access
              rlcf      VerifySettings_State,W,Banked
              rlcf      WREG,W,Access
              andlw     b'00001100'
              addlw     LOW(VerifySettings_DispatchTable)
              btfsc     CarryFlag
              incf      PCLATH,Same,Access
              movwf     PCL,Access

VerifySettings_DispatchTable:
;
VS_DT00:      goto      VS_Check
VS_DT01:      goto      VS_IncrementSequence
VS_DT02:      goto      VS_SwitchBank  
VS_DT03:      goto      VS_Finalise 
;
VS_Check:
;
              movlw     FirmwareYear-ActiveBank ;Point to first non-volatile variable in EEPROM
              addwf     EEADR,Same,Access
              bcf       _EEPGD
              bcf       _EECFGS
;
VS_Check_1:
;
              bsf       _EERD 
              movf      POSTINC0,W,Access
              subwf     EEDATA,W,Access 
              btfsc     ZeroFlag
              goto      VS_Check_2
;
              movf      POSTDEC0,W,Access        ;There is no PREDEC0!!!
              movf      INDF0,W,Access
              movwf     FSR1L,Access
              movlw     Event_RefreshNV
              call      WriteEventToQueue
              movf      EEADR,W,Access
              call      WriteEventToQueue
              movf      FSR1L,W
              call      WriteEventToQueue
;
              bcf       PowerDown                ;We have just queued an event, so cancel the PowerDown for now
;
              goto      VerifySettings_Out
;
VS_Check_2:
;
              incf      EEADR,Same,Access 
              decfsz    ScratchPad0,Same,Access
              goto      VS_Check_1
;
              btfss     BankSwitchRequired
              goto      VS_Check_3
;      
              incf      VerifySettings_State,Same,Banked
;
              bcf       PowerDown                ;We are about to queue an event, so cancel the PowerDown for now
;
VS_Check_3:
;
              goto      VerifySettings_Out
;
VS_IncrementSequence:
;
              movlw     SequenceNumber-ActiveBank ;Point to the sequence number
              addwf     EEADR,W,Access
              xorlw     0x40                     ;In the ACTIVE bank
              movwf     EEADR,Access      
              bcf       _EEPGD
              bcf       _EECFGS
;
              bsf       _EERD
              movf      EEDATA,W,Access
              addlw     1 
              movwf     EEDATA,Access
              movlw     0xFF                     ;0xFF is not a valid sequence number, because it is the value of erased EEPROM memory
              xorwf     EEDATA,W,Access
              btfsc     ZeroFlag
              incf      EEDATA,Same,Access       ;So increment 0xFF to become 0x00
; 
              movlw     Event_RefreshNV
              call      WriteEventToQueue
              movf      EEADR,W,Access
              xorlw     0x40                     ;Point back to the REFRESH bank
              call      WriteEventToQueue
              movf      EEDATA,W,Access
              call      WriteEventToQueue
;
              incf      VerifySettings_State,Same,Banked
;
              bcf       PowerDown                ;We have just queued an event, so cancel the PowerDown for now
;
              goto      VerifySettings_Out
;
VS_SwitchBank:
;
              movf      EEADR,W,Access
              movlw     0xA5
              btfsc     ZeroFlag
              movlw     0x5A
              movwf     EEDATA,Access
; 
              movlw     Event_RefreshNV
              call      WriteEventToQueue
              movlw     EE_ActiveBank
              call      WriteEventToQueue
              movf      EEDATA,W,Access
              call      WriteEventToQueue
;
              incf      VerifySettings_State,Same,Banked
;
              bcf       PowerDown                ;We have just queued an event, so cancel the PowerDown for now
;
              goto      VerifySettings_Out
;
VS_Finalise:
;
              bcf       BankSwitchRequired
              clrf      VerifySettings_State,Banked
;
              goto      VerifySettings_Out
;           
VerifySettings_Out:
;
              LiveDebug LiveDebug_VerifySettings_End
;
              return
;
Event_X_DetermineWindDirection:
;
              LiveDebug LiveDebug_DWD_Start
;
              clrf      PCLATU,Access
              movlw     HIGH(DWD_DispatchTable)
              movwf     PCLATH,Access
;
              movf      EventState,W,Banked
              addwf     WindSpeed_State,W,Banked
              rlcf      WREG,W,Access
              rlcf      WREG,W,Access
              andlw     b'00111100'
              addlw     LOW(DWD_DispatchTable)
              btfsc     CarryFlag
              incf      PCLATH,Same,Access 
              movwf     PCL,Access
;
DWD_DispatchTable:
;
DWDDT00:      goto      Event_X_DWD_PowerOn
DWDDT01:      goto      Event_X_DWD_WaitPowerOn
DWDDT02:      goto      Event_X_DWD_Sample
DWDDT03:      nop
              nop
DWDDT04:      nop
              nop
DWDDT05:      nop
              nop
DWDDT06:      nop
              nop
DHDDT07:      nop
              nop
DWDDT08:      nop
              nop
DWDDT09:      nop
              nop
DWDDT10:      nop
              nop
DWDDT15:      nop
              nop      
;
              call     RemoveEventFromQueue
;
              LiveDebug LiveDebug_UnknownState
;
              goto      Event_X_DWD_End
;
;*************************************************
;
Event_X_DWD_PowerOn:
;
#define BlockDWDSeconds 86400-(5*60) ;Block DetermineWindDirection from being executed for this long before the DailyLog to minimise failure of the DailyLog
;
              movlw     LOW(BlockDWDSeconds)
              subwf     Seconds_Offset,W,Banked
              movlw     HIGH(BlockDWDSeconds)
              subwfb    Seconds_OffsetH,W,Banked
              movlw     UPPER(BlockDWDSeconds)
              subwfb    Seconds_OffsetHH,W,Banked
;
              btfsc     CarryFlag
              goto      Event_X_DWD_Sample_DeleteEvent
;
              bsf       Power
;
              movff     WindSpeed3,WindSpeed4
              movff     WindSpeed3H,WindSpeed4H
;
              movff     WindSpeed2,WindSpeed3
              movff     WindSpeed2H,WindSpeed3H
;
              movff     WindSpeed1,WindSpeed2
              movff     WindSpeed1H,WindSpeed2H 
;
              clrf      WindSpeed1,Banked
              clrf      WindSpeed1H,Banked
;
              movff     Gust3,Gust4
              movff     Gust3H,Gust4H
;
              movff     Gust2,Gust3
              movff     Gust2H,Gust3H
;
              movff     Gust1,Gust2
              movff     Gust1H,Gust2H
;
              clrf      WindSpeedTotal,Banked
              clrf      WindSpeedTotalH,Banked
              clrf      WindSpeedTotalHH,Banked
              clrf      WindSpeedTotalHHH,Banked
              clrf      WindSpeedTotalHHHH,Banked
;
              clrf      WindSpeedTotalCount,Banked
              clrf      WindSpeedTotalCountH,Banked
;
              movlw     0xFF
              movwf     Gust1,Banked
              movwf     Gust1H,Banked
;
              bsf       Gust_FirstPass
;
              clrf      T3CON,Access             ;T3 is off
;
              clrf      TMR3H,Access             ;Start from 0
              clrf      TMR3L,Access
;
              bcf       _TMR3IF                  ;If we overflow then the anemometer is going way too slow
;
              clrf      T3GCON,Access            ;No gating  
;
              movlw     b'01000011'              ;Start TMR3 - 16-bit - Fosc - Pre=1
              movwf     T3CON,Access  
;
              bcf       _INT2EDG
              bsf       _INT2IP
              bcf       _INT2IF
              bsf       _INT2IE
              bsf       _IPEN                    ;Switch the high priority interrupts on
              bsf       _GIEH
;
              movlw     240
              addwf     Seconds_Offset,W,Banked
              movwf     WindSpeedTimer,Banked
              movlw     0
              addwfc    Seconds_OffsetH,W,Banked
              movwf     WindSpeedTimerH,Banked
              movlw     0
              addwfc    Seconds_OffsetHH,W,Banked
              movwf     WindSpeedTimerHH,Banked             
;
              incf      EventState,Same,Banked
;
              goto      Event_X_DWD_End
;
Event_X_DWD_WaitPowerOn:
;
              movf      WindSpeedTimer,W,Banked
              subwf     Seconds_Offset,W,Banked
;
              movf      WindSpeedTimerH,W,Banked
              subwfb    Seconds_OffsetH,W,Banked
;
              movf      WindSpeedTimerHH,W,Banked
              subwfb    Seconds_OffsetHH,W,Banked
;
              btfsc     CarryFlag
              goto      Event_X_DWD_WaitPowerOn_TimeUp
;
; Keep sampling the wind, but allow other events to queue inbetween for processing
;
              movlw     1
              movwf     WindSpeed_State,Banked
;
              call      RemoveEventFromQueue
;
              movlw     Event_DetermineWindDirection
              call      WriteEventToQueue
;
              goto      Event_X_DWD_WaitPowerOn_End
;
Event_X_DWD_WaitPowerOn_TimeUp:
;
              clrf      INTCON,Access
              bcf       _INT2IE
;
              movff     WindSpeed_State,EventState
              clrf      WindSpeed_State,Banked
              incf      EventState,Same,Banked
;
              bsf       CaptureWindSpeedAverage
;
              goto      Event_X_DWD_WaitPowerOn_End
;
Event_X_DWD_WaitPowerOn_End:
;
              goto      Event_X_DWD_End
;
Event_X_DWD_Sample:
;
              movlw     b'10000000'              ;Switch to high speed to get through initialisation quickly 
              movwf     OSCCON,Access
;
              movlw     0                        ;Halt the rain pulse lockout timer while we go into highspeed
              movff     WREG,T4CON 
;
              bsf       HighSpeed
;
              clrf      T3CON,Access             ;T3 is off
;
              clrf      TMR3H,Access             ;Start from 0
              clrf      TMR3L,Access
;
              bcf       _TMR3IF                  ;If we overflow then there is sensor fault
;
              clrf      T3GCON,Access            ;No gating  
;
              movlw     b'00000100'              ;Set T3 for CCP5
              movff     WREG,CCPTMRS1
;
; look for rising - this is start time
; look for falling - this is on time
; look for rising - this is stop time
; do the maths
;  (falling-start)*100/(end-start)
; range check >625 n <9375 - we can do these last 2 steps on the app/server
; extract angle (n-625)*360/8750
;
              movlw     b'00000011'              ;Start TMR3 - 16-bit - Fosc/4 - Pre=1
              movwf     T3CON,Access  
;
              movlw     0
              movff     WREG,CCP5CON
;
              bcf       _CCP5IF
;
              movlw     b'00000101'
              movff     WREG,CCP5CON
;
Event_X_DWD_Sample_Start:
;
              btfsc     _CCP5IF
              goto      Event_X_DWD_Sample_Start1
              btfsc     _TMR3IF
              goto      Event_X_DWD_Sample_Sensor
              goto      Event_X_DWD_Sample_Start
;
Event_X_DWD_Sample_Start1:
;
              bcf       _CCP5IF
;
              movff     CCPR5L,DirectionStart
              movff     CCPR5H,DirectionStartH
;
              movlw     b'00000100'
              movff     WREG,CCP5CON
;
Event_X_DWD_Sample_On:
;
              btfsc     _CCP5IF
              goto      Event_X_DWD_Sample_On1
              btfsc     _TMR3IF
              goto      Event_X_DWD_Sample_Sensor
              goto      Event_X_DWD_Sample_On
;
Event_X_DWD_Sample_On1:
;
              bcf       _CCP5IF
;
              movff     CCPR5L,DirectionOn
              movff     CCPR5H,DirectionOnH
;
              movlw     b'00000101'
              movff     WREG,CCP5CON
;
Event_X_DWD_Sample_Stop:
;
              btfsc     _CCP5IF
              goto      Event_X_DWD_Sample_Stop1
              btfsc     _TMR3IF
              goto      Event_X_DWD_Sample_Sensor
              goto      Event_X_DWD_Sample_Stop
;
Event_X_DWD_Sample_Stop1:
;
              bcf       _CCP5IF
              movff     CCPR5L,DirectionStop
              movff     CCPR5H,DirectionStopH
;
              movlw     b'00000000'
              movff     WREG,CCP5CON
;
 ;             bcf       Power ;moved to the wind speed event
;
              movf      DirectionStart,W,Access
              subwf     DirectionOn,W,Access
              movwf     CalculatorX0,Access
              movf      DirectionStartH,W,Access
              subwfb    DirectionOnH,W,Access
              movwf     CalculatorX1,Access
              clrf      CalculatorX2,Access
              clrf      CalculatorX3,Access
              clrf      CalculatorX4,Access
;
              movlw     LOW(10000)
              movwf     CalculatorY0,Access
              movlw     HIGH(10000)
              movwf     CalculatorY1,Access         
              clrf      CalculatorY2,Access         
              clrf      CalculatorY3,Access         
              clrf      CalculatorY4,Access         

              call      Mul40
;
              movf      DirectionStart,W,Access
              subwf     DirectionStop,W,Access
              movwf     CalculatorY0,Access
              movf      DirectionStartH,W,Access
              subwfb    DirectionStopH,W,Access
              movwf     CalculatorY1,Access
              clrf      CalculatorY2,Access         
              clrf      CalculatorY3,Access         
              clrf      CalculatorY4,Access         
;
              call      Div40
;
              movff     CalculatorX0,WindDirection
              movff     CalculatorX1,WindDirectionH        
;
              goto      Event_X_DWD_Sample_End
;
Event_X_DWD_Sample_Sensor:
;
              clrf      T3CON,Access
;
              movlw     b'00000000'
              movff     WREG,CCP5CON
;
              movlw     0xFF
              movwf     WindDirection,Banked
              movwf     WindDirectionH,Banked 
;
Event_X_DWD_Sample_End:
;
              movlw     b'00001010' ;Run at low speed to save battery power 
              movwf     OSCCON,Access
;
              bcf       HighSpeed 
;
              movlw     b'01000100'              ;Put the rain pulse lockout timer on again
              movff     WREG,T4CON 
;
Event_X_DWD_Sample_DeleteEvent:
;
; !!! Nothing beyond here because ...DWD_PowerOn... exits through here !!!
;
              call      RemoveEventFromQueue
;
              goto      Event_X_DWD_End
;
Event_X_DWD_End:
;
              LiveDebug LiveDebug_DWD_End
;
              goto      ProcessEvent_End
;
Event_X_RainPulseGSM:
;
              LiveDebug_RainPulse = TRUE
              LiveDebug LiveDebug_LostRainPulse
;
              movff     RainPulseGSM_0,Binary
              movff     RainPulseGSMH_0,BinaryH
;
              LiveDebugReportWord 
;
              LiveDebug_RainPulse = FALSE
;
              call      RemoveEventFromQueue
;
              goto      ProcessEvent_End
;
FreeToCommunicate:
;
              IFNDEF LiveDebug_Enable
                 btfsc     DevicePresentAtPowerUp
                 goto      SwitchToComms
              ENDIF
;
              btfsc     SendSMS
              goto      SwitchToGSM
              goto      SwitchToComms
;
SwitchToComms:
;
              clrf      INTCON,Access            ;Interrupts are off for now
;
              movlw     b'10000000'              ;Switch to high speed to get through initialisation quickly 
              movwf     OSCCON,Access
;
              bsf       HighSpeed
;
              bcf       SelectGSM
              bsf       SelectUSB
;
              movlw     LOW(71) ;287=9600 71=38400 47=57600 23=115200
              movwf     SPBRG1,Access
              movlw     HIGH(71)
              movwf     SPBRGH1,Access
;
              movlw     b'00001000'
              movwf     BAUDCON1
;
              movlw     b'00100110' 
              movwf     TXSTA1,Access
;
              movlw     b'10010000'
              movwf     RCSTA1,Access
;
              movlw     LOW(35) ;115200bps
              movwf     SPBRG2,Access
              movlw     HIGH(35)
              movwf     SPBRGH2,Access
;
              movlw     b'00001000'
              movwf     BAUDCON2
;
              movlw     b'00100110' 
              movwf     TXSTA2,Access
;
              movlw     b'10011000'
           ;   movwf     RCSTA2,Access
;
              setf      TMR1H,Access             ;Set up timer 1 
              setf      TMR1L,Access
;
              movlw     ConfigureTMR1
              movwf     T1CON,Access
;
              movlw     TC1msec                  ;Set up timer 2
              movwf     PR2,Access
;
              clrf      TMR2,Access
;
              movlw     ConfigureTMR2 
              movwf     T2CON,Access
;
              movlw     TC92usec                 ;Set up timer 6 275=38400 185=57600 92=115200
              movff     WREG,PR6
;
              movlw     0
              movff     WREG,TMR6
;
              movlw     ConfigureTMR6 
              movff     WREG,T6CON
;
              movlw     Rx1BufferLastLocation    ;Initialise the receive buffer for serial port 1  
              movwf     Rx1BufferReadPointer,Banked
              movwf     Rx1BufferWritePointer,Banked
;
              movlw     Tx1BufferLastLocation    ;Initialise the transmit buffer for serial port 1
              movwf     Tx1BufferReadPointer,Banked
              movwf     Tx1BufferWritePointer,Banked
;
              clrf      PacketState,Banked
;
              clrf      IPR1,Access              ;All interrupts are low priority
              clrf      IPR2,Access
              clrf      IPR3,Access
              clrf      IPR4,Access
              clrf      IPR5,Access
;
; Select active interrupts
;
              bsf       _TMR2IE
;
              bsf       _RCIP
              bsf       _RC1IE
              bsf       _TMR6IP
              bsf       _TMR6IE
;
              clrf      GSM_Flags0,Banked
              clrf      GSM_Flags1,Banked
              clrf      GarbageFlags,Banked
;
; Configure the non-zero flags
;
              movlw     TC5msec
              movwf     _5msecTimer,Banked
;
              movlw     TCFlasher                ;Load flasher
              movwf     FlasherTimer,Banked
;
              movlw     TC1Second                ;Load 1 second timer
              movwf     OneSecondTimer,Banked
;
              clrf      CellModuleTimeOutTimer,Banked
	          clrf      CellModuleTimeOutTimerH,Banked
;
              bsf       _IPEN                    ;Switch the interrupts on
              bsf       _GIEL
              bsf       _GIEH
;
              bcf       DeviceCommunicated
              bcf       DeviceSetClock
;
              call      SaveSettings_Bulk
;
              bcf       DevicePresentAtPowerUp
;
              goto      Forever_Comms
;
Forever_Comms:
;
              clrwdt
;
              call      CheckByteSerialBuffer1
              btfsc     CarryFlag
              call      ProcessSerialInput 
;
              btfss     _INT0IF
              goto      Forever_Comms1
;     
              bcf       _INT0IF
;
              bsf       CheckUSBAlert
;
              goto      Forever_Comms
;
Forever_Comms1:
;
              btfss     CheckUSBAlert
              goto      Forever_Comms2 
;
              bcf       CheckUSBAlert
;            
              movlw     Track_USBAlert
              call      ReadADC
              movlw     LOW(USBAlert_Threshold)
              subwf     ADRESL,W
              movlw     HIGH(USBAlert_Threshold)
              subwfb    ADRESH,W
              btfss     CarryFlag            
              goto      SwitchToRainGauge
;
Forever_Comms2:
;
              goto      Forever_Comms
;
;***************************************
;
; This where the interruptrs are re-mapped for the BootLoader
;
;***************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
RemapHighPriorityInterrupts goto ProcessHighPriorityInterrupts ;And then we go and process them
RemapLowPriorityInterrupts  goto ProcessLowPriorityInterrupts  ;And then we go and process them
;
;***************************************
;
; These are the message strings associated with the GSM modem
;
;***************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
              CreateMessage Cell_Message_QueryModule         ,"AT"
              CreateMessage Cell_Message_CommandEchoOff      ,"ATE0"
              CreateMessage Cell_Message_TimeStampEnable     ,"AT+CLTS=1"
              CreateMessage Cell_Message_SaveProfile         ,"AT&W"
              CreateMessage Cell_Message_ReadTimeStamp       ,"AT+CCLK?"
              CreateMessage Cell_Message_SelectTextMode      ,"AT+CMGF=1"
	          CreateMessage Cell_Message_NetworkRegistration ,"AT+CREG?"
	          CreateMessage Cell_Message_SendSMS             ,"AT+CMGS=\""
;	           CreateMessage Cell_Message_Number              ,"+27835315530\""
	          CreateMessage Cell_Message_Number              ,"+27825105782\""
	          CreateMessage Cell_Message_Content             ,"Clean switch L126"
              CreateMessage Cell_Message_ListAllSMSs         ,"AT+CMGL=\"ALL\""
              CreateMessage Cell_Message_SendMessage         ,"AT+CMGS="
              CreateMessage Cell_Message_DeleteSMS           ,"AT+CMGD="
              CreateMessage Cell_Message_ReadSignalStrength  ,"AT+CSQ"
              CreateMessage Cell_Message_ExtractIMSI         ,"AT+CIMI
              CreateMessage Cell_Message_GPRSattachment      ,"AT+CGATT?"
              CreateMessage Cell_Message_ConnectionType      ,"AT+SAPBR=3,1,\"CONTYPE\",\"GPRS\""
              CreateMessage Cell_Message_SetAPN              ,"AT+SAPBR=3,1,\"APN\",\"INTERNET\""
              CreateMessage Cell_Message_OpenBearer          ,"AT+SAPBR=1,1"
              CreateMessage Cell_Message_QueryBearer         ,"AT+SAPBR=2,1"
              CreateMessage Cell_Message_HTTPinit            ,"AT+HTTPINIT"
              CreateMessage Cell_Message_BearerID            ,"AT+HTTPPARA=\"CID\",1"
              CreateMessage Cell_Message_SetURL              ,"AT+HTTPPARA=\"URL\",\"http://farming.agrigel.co.za/index/api/api_data.php\""
              CreateMessage Cell_Message_ContentType         ,"AT+HTTPPARA=\"CONTENT\",\"application/x-www-form-urlencoded\""
              CreateMessage Cell_Message_DataSizeHead        ,"AT+HTTPDATA=" ;37,10000"
              CreateMessage Cell_Message_DataSizeTail        ,",10000"
              CreateMessage Cell_Message_Ping                ,"name=ajax_ping"
              CreateMessage Cell_Message_DataHead            ,"name=rd&data=3A81"  ;07 43384732000008 41 0D"  
              CreateMessage Cell_Message_DataTail            ,"0D"
              CreateMessage Cell_Message_HTTPaction          ,"AT+HTTPACTION=1"
              CreateMessage Cell_Message_HTTPread            ,"AT+HTTPREAD"
              CreateMessage Cell_Message_HTTPterminate       ,"AT+HTTPTERM"
              CreateMessage Cell_Message_CloseBearer         ,"AT+SAPBR=0,1"
;
CellResponse=0
;
CellResponses
;
              CreateCellResponse CellResponse_OK,                  "OK"
              CreateCellResponse CellResponse_AT,                  "AT"
;
              CreateCellResponse CellResponse_CommandEchoOff,      "ATE0"
;
              CreateCellResponse CellResponse_ERROR,               "ERROR"
;
              CreateCellResponse CellResponse_HomeNetwork,         "+CREG: 0,1"
              CreateCellResponse CellResponse_RoamingNetwork,      "+CREG: 0,5" ;Added this in because Danny is enabling roaming in the SIM cards
;
              CreateCellResponse CellResponse_ATpCPINQuestion,     "AT+CPIN?"
              CreateCellResponse CellResponse_pCPIN_READY,         "+CPIN: READY"
              CreateCellResponse CellResponse_pCPIN_SIM_PIN,       "+CPIN: SIM PIN"
;
              CreateCellResponse CellResponse_QuerySMSServiceCentre, "+CSCA:"
;
              CreateCellResponse CellResponse_SMSSent,               "+CMGS:"
;
              CreateCellResponse CellResponse_pCMGL,                 "+CMGL:"
;
              CreateCellResponse CellResponse_GPRSattachment        ,"+CGATT: 1" 
;
              CreateCellResponse CellResponse_QueryBearer           ,"+SAPBR:" 
;
              CreateCellResponse CellResponse_DataSize              ,"DOWNLOAD"
;
              CreateCellResponse CellResponse_HTTPaction            ,"+HTTPACTION:"
;
              CreateCellResponse CellResponse_HTTPread              ,"+HTTPREAD:"
;
              CreateCellResponse CellRespone_HTTPterminate          ,"+HTTPTERM"
;
              CreateCellResponse CellResponse_ReadTimeStamp         ,"+CCLK:"
;
              CreateCellResponse CellResponse_SignalStrength,        "+CSQ:" ;Keep this as the last entry in CellResponses
                                                                             ; - I can't tell you why :-) but on one version
                                                                             ;   of the code, it wouldn't work if you didn't
;
;***************************************
;
; This is the beginning, so we need to initialise everything
;
;***************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
SwitchToGSM:
;
; N213 include this code to prevent POSTing below 3V8
;
           IFDEF DoNotPostBelow3V8
;
              btfss     BatteryLow
              goto      DNPB3V8_BBB
;
              movlw     BatteryThreshold_KickIn
              subwf     BatteryVoltage,W,Banked
              btfss     CarryFlag
              goto      DNPB3V8_AAA
;
              bcf       BatteryLow
;
              goto      DNPB3V8_CCC
;
DNPB3V8_AAA:
;
              bcf       SendSMS
;
              goto      SwitchToRainGauge
;
DNPB3V8_BBB:
;
              movlw     BatteryThreshold_KickOut
              subwf     BatteryVoltage,W,Banked
              btfsc     CarryFlag
              goto      DNPB3V8_CCC
;
              bsf       BatteryLow
              bcf       SendSMS
;
              goto      SwitchToRainGauge
;
DNPB3V8_CCC:
;
           ENDIF
;
; N213 include this code to prevent POSTing below 3V8
;
              clrf      INTCON,Access            ;Interrupts are off for now
;
              LiveDebug_RainPulse = TRUE
              LiveDebug LiveDebug_GSM
              LiveDebug_RainPulse = FALSE
;
SwitchToGSM1:
;
              btfss     _TRMT1
              goto      SwitchToGSM1
;
              movlw     b'10000000'              ;Switch to high speed to get through initialisation quickly 
              movwf     OSCCON,Access
;
              bsf       HighSpeed
;
              bcf       SelectUSB
              bsf       SelectGSM
;
              bcf       LiveDebugInitialised
;
              movlw     LOW(23) ;287=9600 71=38400 47=57600 23=115200
              movwf     SPBRG1,Access
              movlw     HIGH(23)
              movwf     SPBRGH1,Access
;
              movlw     b'00001000'
              movwf     BAUDCON1
;
              movlw     b'00100110' 
              movwf     TXSTA1,Access
;
              movlw     b'10010000'
              movwf     RCSTA1,Access
;
              movlw     LOW(35) ;115200bps
              movwf     SPBRG2,Access
              movlw     HIGH(35)
              movwf     SPBRGH2,Access
;
              movlw     b'00001000'
              movwf     BAUDCON2
;
              movlw     b'00100110' 
              movwf     TXSTA2,Access
;
              movlw     b'10011000'
           ;   movwf     RCSTA2,Access
;
              setf      TMR1H,Access             ;Set up timer 1 
              setf      TMR1L,Access
;
              movlw     ConfigureTMR1
              movwf     T1CON,Access
;
              movlw     TC1msec                  ;Set up timer 2
              movwf     PR2,Access
;
              clrf      TMR2,Access
;
              movlw     ConfigureTMR2 
              movwf     T2CON,Access
;
              movlw     TC92usec                 ;Set up timer 6 275=38400 185=57600 92=115200
              movff     WREG,PR6
;
              movlw     0
              movff     WREG,TMR6
;
              movlw     ConfigureTMR6 
              movff     WREG,T6CON
;
              movlw     Rx1BufferLastLocation    ;Initialise the receive buffer for serial port 1  
              movwf     Rx1BufferReadPointer,Banked
              movwf     Rx1BufferWritePointer,Banked
;
              movlw     Tx1BufferLastLocation    ;Initialise the transmit buffer for serial port 1
              movwf     Tx1BufferReadPointer,Banked
              movwf     Tx1BufferWritePointer,Banked
;
              clrf      PacketState,Banked
;
              clrf      IPR1,Access              ;All interrupts are low priority
              clrf      IPR2,Access
              clrf      IPR3,Access
              clrf      IPR4,Access
              clrf      IPR5,Access
;
; Select active interrupts
;
              bsf       _TMR2IE
;
              bsf       _RCIP
              bsf       _RC1IE
              bsf       _TMR6IP
              bsf       _TMR6IE
;
              clrf      GSM_Flags0,Banked
              clrf      GSM_Flags1,Banked
              clrf      GarbageFlags,Banked
;
; Configure the non-zero flags
;
              movlw     TC5msec
              movwf     _5msecTimer,Banked
;
              movlw     TCFlasher                ;Load flasher
              movwf     FlasherTimer,Banked
;
              movlw     TC1Second                ;Load 1 second timer
              movwf     OneSecondTimer,Banked
;
              clrf      CellModuleTimeOutTimer,Banked
	          clrf      CellModuleTimeOutTimerH,Banked
;
              bsf       _IPEN                    ;Switch the interrupts on
              bsf       _GIEL
              bsf       _GIEH
;
              bsf       _TMR3IF                  ;Make sure we capture the first rain pulse
              clrf      RainTickCompensationTime,Banked
              movff     RainPulse,RainPulseOld
              movff     RainPulseH,RainPulseOldH
              movff     RainPulseHH,RainPulseOldHH
;
              movlw     Retries
              movwf     MessageRetries,Banked
              movlw     Retries*2
              movwf     InitialiseRetries,Banked
;
              movlw     0
              movwf     GSM_State,Banked
;
Forever:
;
              clrwdt
;
              btfsc     _TMR3IF
              call      TimeTicks_GSM

              btfsc     _INT1IF
              call      CaptureRainPulse_GSM
;
              call      ProcessGSM
;
              movff     GSM_State,WREG
              xorlw     S_GSM_ModuleOffDone
              btfss     ZeroFlag
              goto      Forever 
;
              clrf      T3CON,Access             ;We don't need T3 running anymore 
              bsf       _TMR4IF                  ;Ensure we can read the first rain pulse in the EventStaeMachine
              clrf      RainTickCompensationTime,Banked
   ;LC07              bsf       QueueLostRainPulses 
;
SwitchToRainGauge:

              clrf      INTCON,Access
              bcf       _RC1IE                   ;Switch these interrupts off here, so that they don't get processed with the WindSpeed
              bcf       _TMR6IE
;
; For now leave the UART switched to the GSM module           
; - This has now become the re-entry point from both the GSM and the USB, so now make sure it is switched 
;
              bcf       SelectUSB
              bsf       SelectGSM
;
           IFDEF LiveDebug_Enable
;
              movlw     LOW(1) ;3906bps @ 31250Hz
              movwf     SPBRG,Access
              movlw     HIGH(1)
              movwf     SPBRGH,Access
;
              movlw     b'00001000' ;16-bit baud rate
              movwf     BAUDCON,Access
;
              movlw     b'00100110' ;High speed UART
              movwf     TXSTA1,Access
;
              movlw     b'10010000'
              movwf     RCSTA1,Access
;
              bsf       LiveDebugInitialised
;
           ENDIF
;
              btfss     DeviceCommunicated
              goto      SwitchToRainGauge_1
;
              bcf       DeviceCommunicated
;
              movlw     1
              addwf     Connections,Same,Banked
              movlw     0
              addwfc    ConnectionsH,Same,Banked
;
              btfss     CarryFlag
              goto      SwitchToRainGauge_1
;
              movlw     0xFF
              movwf     Connections,Banked
              movwf     ConnectionsH,Banked
;
SwitchToRainGauge_1:
;
              call      SaveSettings_Bulk
;
; Read the date and time from the RTC
;
              bsf       RTC_PU
;
              call      Delay1msec
;
              lfsr      0,RTC_Seconds
;
              call      I2C_RTC_Start               
              movlw     b'11010000'
              call      I2C_RTC_Tx        
              movlw     b'00000000'              ;Read the Seconds register in order to check the CH bit
              call      I2C_RTC_Tx
              call      I2C_RTC_Start
              movlw     b'11010001'
              call      I2C_RTC_Tx
              bsf       AckTx
              call      I2C_RTC_Rx               ;Seconds
              movwf     POSTINC0,Access  
              call      I2C_RTC_Rx               ;Minutes
              movwf     POSTINC0,Access
              call      I2C_RTC_Rx               ;Hours
              movwf     POSTINC0,Access
              call      I2C_RTC_Rx               ;DayOfWeek
              movwf     POSTINC0,Access
              call      I2C_RTC_Rx               ;Date
              movwf     POSTINC0,Access
              call      I2C_RTC_Rx               ;Month
              movwf     POSTINC0,Access
              call      I2C_RTC_Rx               ;Year
              movwf     POSTINC0,Access
              bcf       AckTx
              call      I2C_RTC_Rx               ;Control
              bsf       AckTx
              movwf     INDF0,Access
              call      I2C_RTC_Stop
;
              btfss     RTC_Seconds,7,Banked
              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_RTC_Start
              movlw     b'11010000'
              call      I2C_RTC_Tx        
              movlw     b'00000000'
              call      I2C_RTC_Tx
              movf      RTC_Seconds,W,Banked
              andlw     b'01111111' ;Bit 7 of register 0 is Clock Halt and must be 0
              call      I2C_RTC_Tx
              call      I2C_RTC_Stop
;
SwitchToRainGauge_2:
;
              movlw     0x10                     ;Check control is setup correctly
              xorwf     INDF0,W
              btfsc     ZeroFlag
              goto      SwitchToRainGauge_3
;
; Make the clock TICK again - never mind the date and time that the app set or that was in the RTC
;
              call      I2C_RTC_Start
              movlw     b'11010000'
              call      I2C_RTC_Tx        
              movlw     b'00000111'
              call      I2C_RTC_Tx
              movlw     0x10 ;7 = Control
              call      I2C_RTC_Tx
              call      I2C_RTC_Stop
;
SwitchToRainGauge_3:
;
              bcf       RTC_PU
;
              call      Delay1msec
;
              call      CalculateSecondsOffset
;
              btfss     DeviceSetClock
              goto      SwitchToRainGauge_4
;
              bcf       DeviceSetClock 
;
              movlw     0xFE
              movwf     HiLoDetail1,Banked
              movlw     0xED
              movwf     HiLoDetail2,Banked
;
              call      LogHiLoEvent
;
SwitchToRainGauge_4:
;
              btfss     QueueLostRainPulses
              goto      SwitchToRainGauge_6
;
              bcf       QueueLostRainPulses
;             
              movlw     Event_RainPulseGSM
              call      WriteEventToQueue
;
              movf      RainPulseOld,W,Banked
              subwf     RainPulse,W,Banked              
              movwf     RainPulseOld,Banked
              movff     WREG,RainPulseGSM_0
              movf      RainPulseOldH,W,Banked
              subwfb    RainPulseH,W,Banked              
              movwf     RainPulseOldH,Banked
              movff     WREG,RainPulseGSMH_0
              movf      RainPulseOldHH,W,Banked
              subwfb    RainPulseHH,W,Banked              
              movwf     RainPulseOldHH,Banked
              movff     WREG,RainPulseGSMHH_0
;
SwitchToRainGauge_5:
;
              movf      RainPulseOld,W,Banked
              iorwf     RainPulseOldH,W,Banked
              iorwf     RainPulseOldHH,W,Banked
              btfsc     ZeroFlag
              goto      SwitchToRainGauge_6  
;
              movlw     EEPROM_BufferSize+7      ;(I need space for 8 bytes)
              subwf     EEPROM_Buffered,W,Banked
              addlw     8
              btfsc     CarryFlag
              goto      SwitchToRainGauge_6      ;EEPROM buffer is full, too bad the rest get lost!!! 
;
              movf      Seconds_OffsetHH,W,Banked ;Queue it for logging to EEPROM
              movlw     LogEvent_RainPulseTimeLost+0
              btfss     ZeroFlag
              movlw     LogEvent_RainPulseTimeLost+1
              movwf     Checksum,Banked
              call      EEPROM_WriteBuffer
              movf      Seconds_OffsetH,W,Banked
              addwf     Checksum,Same,Banked
              call      EEPROM_WriteBuffer
              movf      Seconds_Offset,W,Banked
              addwf     Checksum,Same,Banked
              call      EEPROM_WriteBuffer
;
              movf      RainPulseOldH,W,Banked
              iorwf     RainPulseOldHH,W,Banked
              movlw     255
              btfsc     ZeroFlag
              movf      RainPulseOld,W,Banked
;
              movwf     RainPulseTimeLost,Banked
;
              addwf     Checksum,Same,Banked
              call      EEPROM_WriteBuffer
;
              movf      RainPulse,W,Banked
              addwf     Checksum,Same,Banked
              call      EEPROM_WriteBuffer
              movf      RainPulseH,W,Banked
              addwf     Checksum,Same,Banked
              call      EEPROM_WriteBuffer
              movf      RainPulseHH,W,Banked
              addwf     Checksum,Same,Banked
              call      EEPROM_WriteBuffer
;
              comf      Checksum,W,Banked
              addlw     1
              call      EEPROM_WriteBuffer
;             
              movlw     Event_WriteEEPROM
              call      WriteEventToQueue
;
              movf      RainPulseTimeLost,W,Banked
              subwf     RainPulseOld,Same,Banked
              movlw     0
              subwfb    RainPulseOldH,Same,Banked
              movlw     0
              subwfb    RainPulseOldHH,Same,Banked
;
              goto      SwitchToRainGauge_5
;
SwitchToRainGauge_6:
;
              movlw     b'00001010' ;Run at low speed to save battery power 
              movwf     OSCCON,Access
;
              bcf       HighSpeed 
;
              goto      Forever_RainGauge_Delay
;
BCD2ASCII:
;
              movwf      BCD2ASCII_Work,Banked
              swapf      BCD2ASCII_Work,W,Banked
              andlw      b'00001111'
              addlw      '0'
              addwf     SBTA_Checksum,Same,Banked
              call       WriteByteSerialBuffer1 
;
              movf       BCD2ASCII_Work,W,Banked
              andlw      b'00001111'
              addlw      '0'
              addwf     SBTA_Checksum,Same,Banked
              call       WriteByteSerialBuffer1 
;
              return
;
BinaryToBCD2ASCII:
;
              call      BinaryToBCD
;
              movf      TenThousands,W,Access
              addlw     '0'
              addwf     SBTA_Checksum,Same,Banked
              call      WriteByteSerialBuffer1 
;
              movf      Thousands,W,Access
              addlw     '0'
              addwf     SBTA_Checksum,Same,Banked
              call      WriteByteSerialBuffer1 
;
              movf      Hundreds,W,Access
              addlw     '0'
              addwf     SBTA_Checksum,Same,Banked
              call      WriteByteSerialBuffer1 
;
              movf      Tens,W,Access
              addlw     '0'
              addwf     SBTA_Checksum,Same,Banked
              call      WriteByteSerialBuffer1 
;
              movf      Units,W,Access
              addlw     '0'
              addwf     SBTA_Checksum,Same,Banked
              call      WriteByteSerialBuffer1 
;
              return
;
CSV_Separator:
;
              movlw     ','
              addwf     SBTA_Checksum,Same,Banked
              call      WriteByteSerialBuffer1
;
              return
;
CSV_Terminator:
;
              movlw     '\n'
              addwf     SBTA_Checksum,Same,Banked
              call      WriteByteSerialBuffer1
              movlw     '\r'
              addwf     SBTA_Checksum,Same,Banked
              call      WriteByteSerialBuffer1
;
              return
;
;


;
              goto       Forever


;
;***************************************
;
; Write byte from W to serial transmit buffer 1 
;
;**************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
WriteByteSerialBuffer1:
;
              movwf     CharacterBuffer1,Access  ;Buffer character for later
;
              lfsr      2,Tx1Buffer              ;Point to the correct page
;
              incf      Tx1BufferWritePointer,W,Banked ;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     FSR2L,Access             ;Point to next buffer location
;
WriteByteSerialBuffer1A
;
              movf      FSR2L,W,Access           ;IF WRITE = READ
              xorwf     Tx1BufferReadPointer,W,Banked
              btfsc     ZeroFlag                 
              goto      WriteByteSerialBuffer1A  ;THEN FULL, so wait
;              goto      WriteByteSerialBuffer1B  ;THEN FULL, so go
;
              movf      CharacterBuffer1,W,Access ;Read the byte received
;
              movwf     INDF2,Access             ;And buffer it for transmission
;
              movf      FSR2L,W,Access           ;Update the write pointer
              movwf     Tx1BufferWritePointer,Banked

WriteByteSerialBuffer1B

;
              movf      CharacterBuffer1,W,Access ;Restore W to entry value
;
              return
;
;***************************************
;
; Flush serial receive buffer 1
;
;**************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
FlushSerialReceiveBuffer1:
;
              DisableInterrupts
              movff     Rx1BufferWritePointer,Rx1BufferReadPointer
              RestoreInterrupts
;
              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:
CheckByteCell: ;Alias for imported code to use
;
              movf      Rx1BufferReadPointer,W,Banked
              xorwf     Rx1BufferWritePointer,W,Banked
              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,W,Banked
              xorwf     Rx1BufferWritePointer,W,Banked
              btfsc     ZeroFlag
              goto      ReadByteSerialBuffer1
;
ReadByteSerialBuffer1A
;
              lfsr      2,Rx1Buffer              ;Point to the correct page
;
              incf      Rx1BufferReadPointer,W,Banked
;
              xorlw     Rx1BufferLastLocation+1  ;IF > LAST
              btfsc     ZeroFlag                 ;THEN ROLL OVER to FIRST
              movlw     Rx1BufferFirstLocation^(Rx1BufferLastLocation+1) 
;
              xorlw     Rx1BufferLastLocation+1   ;Restore W from comparison
;
              movwf     FSR2L,Access
;
 ;             DisableReceive1Interrupt
;
              movwf     Rx1BufferReadPointer,Banked
;
              movf      INDF2,W,Access
;
 ;             RestoreReceive1Interrupt
;
              bsf       CarryFlag
;
ReadByteSerialBuffer1End
;
              return             
;
;***************************************
;
; Unbuffer and transmit serial byte to Serial Port 1
;
;***************************************
;
TxByteSerialPort1:
;
              lfsr      2,Tx1Buffer              ;Point to correct bank
;
              movf      Tx1BufferReadPointer,W,Banked ;IF READ = WRITE
              xorwf     Tx1BufferWritePointer,W,Banked
              btfsc     ZeroFlag
              goto      TxByteSerialPort1End      ;THEN EMPTY, so go
;
              incf      Tx1BufferReadPointer,W,Banked ;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     FSR2L,Access
;
              movwf     Tx1BufferReadPointer,Banked ;Update the read pointer
;
              movf      INDF2,W,Access
              movwf     TXREG1,Access            ;Transmit byte
;
TxByteSerialPort1End
;
              return
;
;**************************************
;
; Receive and buffer serial byte from Serial Port 1  
;
;**************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
;
;**************************************
;
; Receive and buffer serial byte from Serial Port 1  
;
;**************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
RxByteSerialPort1:
;
              bcf       Boolean_Interrupt        ;Assume no error
;
              btfss     _OERR1                   ;IF !OVER RUN
              goto      RxByteSerialPort1C       ;THEN check for FRAMING
              bsf       Boolean_Interrupt        ;ELSE flag error and
RxByteSerialPort1A                               ;     recover from OVER RUN
              bcf       _CREN1                   ;     - CREN OFF
              btfsc     _CREN1       
              goto      RxByteSerialPort1A 
;
RxByteSerialPort1B
;
              bsf       _CREN1                   ;     - CREN back ON
              btfss     _CREN1       
              goto      RxByteSerialPort1B       
;
RxByteSerialPort1C
;
              btfss     _FERR1                   ;IF !FRAMING
              goto      RxByteSerialPort1D       ;THEN check error flag
              bsf       Boolean_Interrupt        ;ELSE flag error and
              movf      RCREG1,W                 ;     recover from FRAMING
;
RxByteSerialPort1D
;
              btfsc     Boolean_Interrupt        ;IF ERROR
              goto      RxByteSerialPort1End     ;THEN go
                                                 ;ELSE buffer byte
;
              lfsr      2,Rx1Buffer              ;Point to correct bank
;
              incf      Rx1BufferWritePointer,W,Banked ;Point to next location
;
              xorlw     Rx1BufferLastLocation+1  ;IF > LAST
              btfsc     ZeroFlag                 ;THEN ROLL OVER to FIRST
              movlw     Rx1BufferFirstLocation^(Rx1BufferLastLocation+1) 
;
              xorlw     Rx1BufferLastLocation+1  ;Restore W from comparison
;
              movwf     FSR2L,Access             ;Point to next buffer location
;
              xorwf     Rx1BufferReadPointer,W,Banked ;IF WRITE = READ
              btfsc     ZeroFlag                 
              goto      RxByteSerialPort1BufferFull   ;THEN FULL, so go
;
              movf      RCREG1,W,Access          ;Read the byte received
              movwf     INDF2,Access             ;And buffer it for later
;
              movf      FSR2L,W,Access           ;Update the write pointer
              movwf     Rx1BufferWritePointer,Banked
;
              goto      RxByteSerialPort1End     ;We are done
;
RxByteSerialPort1BufferFull
;
              movf      RCREG1,W,Access          ;Dump this byte
              bsf       SerialBuffer1OverFlow    ;And flag it
;
RxByteSerialPort1End
;
              return
;
DS1307_Write:
;
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
;Beware the subroutines called by this subroutine are still stubs!!!!
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
;
              ;I2C_Start  I2C_BUS1
              movlw      b'11010000'
              call       WriteDS1307             
              movlw      0x00
              call       WriteDS1307             
              movf       DS1307_Seconds,W,Access
              call       WriteDS1307             
              movf       DS1307_Minutes,W,Access
              call       WriteDS1307             
              movf       DS1307_Hours,W,Access
              call       WriteDS1307             
              movf       DS1307_DayOfWeek,W,Access
              call       WriteDS1307             
              movf       DS1307_Days,W,Access
              call       WriteDS1307             
              movf       DS1307_Months,W,Access
              call       WriteDS1307             
              movf       DS1307_Years,W,Access
              call       WriteDS1307             
              movf       DS1307_Control,W,Access
              call       WriteDS1307             
              ;call       I2CBUS1Stop               
;
              return
;
DS1307_Read:
;
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
;Beware the subroutines called by this subroutine are still stubs!!!!
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
;
              ;I2C_Start  I2C_BUS1
              movlw      b'11010000'
              call       WriteDS1307             
              movlw      0x00
              call       WriteDS1307             
              ;I2C_Start  I2C_BUS1
              movlw      b'11010001'
              call       WriteDS1307             
              call       ReadDS1307             
              movwf      DS1307_Seconds,Access
              call       ReadDS1307             
              movwf      DS1307_Minutes,Access
              call       ReadDS1307             
              movwf      DS1307_Hours,Access
              call       ReadDS1307             
              movwf      DS1307_DayOfWeek,Access
              call       ReadDS1307             
              movwf      DS1307_Days,Access
              call       ReadDS1307             
              movwf      DS1307_Months,Access
              call       ReadDS1307             
              movwf      DS1307_Years,Access
              call       ReadLastDS1307             
              movwf      DS1307_Control,Access
              ;call       I2CBUS1Stop               
;
              return
;
Delay1msec: ;Only call from routines running at HighSpeed
;
#define TC1msecInLine (65536-2765)
;
              movlw     LOW(TC1msecInLine)
              movff     WREG,TMR5L
              movlw     HIGH(TC1msecInLine)
              movff     WREG,TMR5H
;
              movlw     b'00000000'
              movff     WREG,T5GCON
              movlw     b'00000001'
              movff     WREG,T5CON
;
              bcf       _TMR5IF
;
Delay1msec_1  btfss     _TMR5IF
              goto      Delay1msec_1
;
              return
;
;**************************************
;
; This is where we actually process the high priority interrupts
;
;**************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
ProcessHighPriorityInterrupts
;
              movff     FSR2L,SaveHPI_FSR2L
              movff     FSR2H,SaveHPI_FSR2H
;
ProcessSerialReceiveInterrupt:
;
              btfss     _RC1IE
              goto      ProcessSerialReceiveInterrupt_End
;
              btfsc     _RC1IF
              call      RxByteSerialPort1
;
ProcessSerialReceiveInterrupt_End:
;
ProcessSerialTransmit:
;
              btfss     _TMR6IE
              goto      ProcessSerialTransmit_End
;
              btfss     _TMR6IF
              goto      ProcessSerialTransmit_End
;
              bcf       _TMR6IF
;
              btfsc     _TRMT1
              call      TxByteSerialPort1
;
ProcessSerialTransmit_End:
;
ProcessExternalInterrupt2:
;
              btfss     _INT2IE
              goto      ProcessExternalInterrupt2_End
;
              btfsc     _INT2IF
              call      AccumulateWindSpeed
;
ProcessExternalInterrupt2_End:
;
ProcessHighPriorityInterruptsEnd
;
              movff     SaveHPI_FSR2H,FSR2H
              movff     SaveHPI_FSR2L,FSR2L
;
              retfie    Shadow
;
;**************************************
;
; This is where we actually process the low priority interrupts
;
;**************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
ProcessLowPriorityInterrupts:
; 
              movff     WREG,SaveWREG
              movff     STATUS,SaveSTATUS
              movff     FSR1H,SaveFSR1H
              movff     FSR1L,SaveFSR1L
              movff     FSR2H,SaveFSR2H
              movff     FSR2L,SaveFSR2L
              movff     PCLATH,SavePCLATH
              movff     PCLATU,SavePCLATU
;
              btfsc     _TMR2IF                  ;IF Timer
              call      ProcessTimer2            ;THEN process it
;
              movff     SaveWREG,WREG
              movff     SaveSTATUS,STATUS
              movff     SaveFSR1H,FSR1H
              movff     SaveFSR1L,FSR1L
              movff     SaveFSR2H,FSR2H
              movff     SaveFSR2L,FSR2L
              movff     SavePCLATH,PCLATH
              movff     SavePCLATU,PCLATU
;
              retfie    NoShadow
;
;***************************************
;
ProcessTimer2: ;1msec but it get divided down to 5msec without use of the 1msec in this application
;
; All the 1msec events go here
;
              decfsz    _5msecTimer,Same,Banked
              goto      ProcessTimer2End
;
              movlw     TC5msec
              movwf     _5msecTimer,Banked
;
; All the 5msec events go here
;
              bsf       Tick
;
	      movf      CellModuleTimeOutTimer,W,Banked
	      iorwf     CellModuleTimeOutTimerH,W,Banked
	      btfsc     ZeroFlag
	      goto      SkipTO
;	      
              movlw     1
              subwf     CellModuleTimeOutTimer,Same,Banked
              movlw     0
              subwfb    CellModuleTimeOutTimerH,Same,Banked
;
              movf      CellModuleTimeOutTimer,W,Banked
              iorwf     CellModuleTimeOutTimerH,W,Banked
              btfsc     ZeroFlag
              bsf       CellModuleResponseTimeOut
;
SkipTO:
;	      
ProcessFlasher:
;
              decfsz    FlasherTimer,Same,Banked
              goto      ProcessFlasherEnd
;
              movlw     TCFlasher
              movwf     FlasherTimer,Banked
;
              btg       Flasher
;
ProcessFlasherEnd:
;
;
ProcessTimer2_1SecondTimer
;
              decfsz    OneSecondTimer,Same,Banked
              goto      ProcessTimer2_1SecondTimerEnd
;
              movlw     TC1Second
              movwf     OneSecondTimer,Banked
;
; All the 1s events go here
;
ProcessSerialIntTimer:
;
              movf      SerialInTimer,W,Banked   ;K706 - Also redundant???
              btfss     ZeroFlag
              goto      ProcessSerialInTimerUpdate
;
              bsf       SerialInTimedOut
;
              goto      ProcessSerialInTimerEnd
;
ProcessSerialInTimerUpdate:
;
              decf      SerialInTimer,Same,Banked
;
ProcessSerialInTimerEnd
;
ProcessTimer2_1SecondTimerEnd
;










;
ProcessAnalogueInputsEnd:
;
ProcessTimer2End
;
              bcf       _TMR2IF
;
              return
; 
;***************************************
;
; Read data from internal EEPROM                
; - Address to be read in W  
; - Return with data in W
;
;***************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
ReadInternalEEPROM:
;
              btfsc     _EEWR
              goto      ReadInternalEEPROM
;
              movwf     EEADR,Access
              bcf       _EEPGD
              bcf       _EECFGS
              bsf       _EERD
              movf      EEDATA,W,Access
;
              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:
;
              btfsc     _EEWR
              goto      WriteInternalEEPROM
;
              movwf     EEDATA,Access
              bcf       _EEPGD
              bcf       _EECFGS
              bsf       _EEWREN
;
              DisableInterrupts
              movlw     h'55'
              movwf     EECON2,Access
              movlw     h'AA'
              movwf     EECON2,Access
              bsf       _EEWR
              RestoreInterrupts
;
              bcf       _EEWREN
;
              return

ReadADC:
;
              movwf     ADCON0,Access
;
              movlw     b'10100000'
              movff     WREG,VREFCON0
;
ReadADC_FVROn:
;
              movff     VREFCON0,WREG
              btfss     WREG,6,Access
              goto      ReadADC_FVROn
;
              bsf       _Go
;
ReadADC1:
;
              btfsc    _Go
              goto     ReadADC1
;
              return
;
BinaryToBCD:
;
ConvertBinary2BCDWordA:
;
              clrf      Units,Access
              clrf      Tens,Access
              clrf      Hundreds,Access
              clrf      Thousands,Access
              clrf      TenThousands,Access
;
ConvertBinary2BCDWordTenThousands:
;
              movlw     LOW(10000)
              subwf     Binary,Same,Access
              movlw     High(10000)
              subwfb    BinaryH,Same,Access
              btfss     CarryFlag
              goto      ConvertBinary2BCDWordTenThouEnd
;
              incf      TenThousands,Same,Access
              goto      ConvertBinary2BCDWordTenThousands
;
ConvertBinary2BCDWordTenThouEnd:
;
               movlw    LOW(10000)
               addwf    Binary,Same,Access
               movlw    HIGH(10000)
               addwfc   BinaryH,Same,Access
;
ConvertBinary2BCDWordThousands:
;
              movlw     LOW(1000)
              subwf     Binary,Same,Access
              movlw     High(1000)
              subwfb    BinaryH,Same,Access
              btfss     CarryFlag
              goto      ConvertBinary2BCDWordThouEnd
;
              incf      Thousands,Same,Access
              goto      ConvertBinary2BCDWordThousands
;
ConvertBinary2BCDWordThouEnd:
;
               movlw    LOW(1000)
               addwf    Binary,Same,Access
               movlw    HIGH(1000)
               addwfc   BinaryH,Same,Access
;
ConvertBinary2BCDWordHundreds:
;
              movlw     LOW(100)
              subwf     Binary,Same,Access
              movlw     High(100)
              subwfb    BinaryH,Same,Access
              btfss     CarryFlag
              goto      ConvertBinary2BCDWordHunEnd
;
              incf      Hundreds,Same,Access
              goto      ConvertBinary2BCDWordHundreds
;
ConvertBinary2BCDWordHunEnd:
;
               movlw    LOW(100)
               addwf    Binary,Same,Access
               movlw    HIGH(100)
               addwfc   BinaryH,Same,Access
;
ConvertBinary2BCDWordTens:
;
              movlw     10
              subwf     Binary,Same,Access
              btfss     CarryFlag
              goto      ConvertBinary2BCDWordTensEnd
;
              incf      Tens,Same,Access
              goto      ConvertBinary2BCDWordTens
;
ConvertBinary2BCDWordTensEnd:
;
               movlw    10
               addwf    Binary,W,Access
               movwf    Units,Access
;
ConvertBinary2BCDWordEnd:
;
              return
;
BinaryToBCDLong:
;
              clrf      Units,Access
              clrf      Tens,Access
              clrf      Hundreds,Access
              clrf      Thousands,Access
              clrf      TenThousands,Access
              clrf      HundredThousands,Access
              clrf      Millions,Access
              clrf      TenMillions,Access
;
ConvertBinary2BCDWordTenMillions:
;
              movlw     LOW(10000000)
              subwf     Binary,Same,Access
              movlw     HIGH(10000000)
              subwfb    BinaryH,Same,Access
              movlw     UPPER(10000000)
              subwfb    BinaryHH,Same,Access
              btfss     CarryFlag
              goto      ConvertBinary2BCDWordTenMilEnd
;
              incf      TenMillions,Same,Access
              goto      ConvertBinary2BCDWordTenMillions
;
ConvertBinary2BCDWordTenMilEnd:
;
               movlw    LOW(10000000)
               addwf    Binary,Same,Access
               movlw    HIGH(10000000)
               addwfc   BinaryH,Same,Access
               movlw    UPPER(10000000)
               addwfc   BinaryHH,Same,Access
;
ConvertBinary2BCDWordMillions:
;
              movlw     LOW(1000000)
              subwf     Binary,Same,Access
              movlw     HIGH(1000000)
              subwfb    BinaryH,Same,Access
              movlw     UPPER(1000000)
              subwfb    BinaryHH,Same,Access
              btfss     CarryFlag
              goto      ConvertBinary2BCDWordMilEnd
;
              incf      Millions,Same,Access
              goto      ConvertBinary2BCDWordMillions
;
ConvertBinary2BCDWordMilEnd:
;
               movlw    LOW(1000000)
               addwf    Binary,Same,Access
               movlw    HIGH(1000000)
               addwfc   BinaryH,Same,Access
               movlw    UPPER(1000000)
               addwfc   BinaryHH,Same,Access
;
ConvertBinary2BCDWordHundredThousands:
;
              movlw     LOW(100000)
              subwf     Binary,Same,Access
              movlw     HIGH(100000)
              subwfb    BinaryH,Same,Access
              movlw     UPPER(100000)
              subwfb    BinaryHH,Same,Access
              btfss     CarryFlag
              goto      ConvertBinary2BCDWordHunThouEnd
;
              incf      HundredThousands,Same,Access
              goto      ConvertBinary2BCDWordHundredThousands
;
ConvertBinary2BCDWordHunThouEnd:
;
               movlw    LOW(100000)
               addwf    Binary,Same,Access
               movlw    HIGH(100000)
               addwfc   BinaryH,Same,Access
               movlw    UPPER(100000)
               addwfc   BinaryHH,Same,Access
;
ConvertBin2BCDWordTenThousands:
;
              movlw     LOW(10000)
              subwf     Binary,Same,Access
              movlw     HIGH(10000)
              subwfb    BinaryH,Same,Access
              movlw     UPPER(10000)
              subwfb    BinaryHH,Same,Access
              btfss     CarryFlag
              goto      ConvertBin2BCDWordTenThouEnd
;
              incf      TenThousands,Same,Access
              goto      ConvertBin2BCDWordTenThousands
;
ConvertBin2BCDWordTenThouEnd:
;
               movlw    LOW(10000)
               addwf    Binary,Same,Access
               movlw    HIGH(10000)
               addwfc   BinaryH,Same,Access
;
ConvertBin2BCDWordThousands:
;
              movlw     LOW(1000)
              subwf     Binary,Same,Access
              movlw     High(1000)
              subwfb    BinaryH,Same,Access
              btfss     CarryFlag
              goto      ConvertBin2BCDWordThouEnd
;
              incf      Thousands,Same,Access
              goto      ConvertBin2BCDWordThousands
;
ConvertBin2BCDWordThouEnd:
;
               movlw    LOW(1000)
               addwf    Binary,Same,Access
               movlw    HIGH(1000)
               addwfc   BinaryH,Same,Access
;
ConvertBin2BCDWordHundreds:
;
              movlw     LOW(100)
              subwf     Binary,Same,Access
              movlw     High(100)
              subwfb    BinaryH,Same,Access
              btfss     CarryFlag
              goto      ConvertBin2BCDWordHunEnd
;
              incf      Hundreds,Same,Access
              goto      ConvertBin2BCDWordHundreds
;
ConvertBin2BCDWordHunEnd:
;
               movlw    LOW(100)
               addwf    Binary,Same,Access
               movlw    HIGH(100)
               addwfc   BinaryH,Same,Access
;
ConvertBin2BCDWordTens:
;
              movlw     10
              subwf     Binary,Same,Access
              btfss     CarryFlag
              goto      ConvertBin2BCDWordTensEnd
;
              incf      Tens,Same,Access
              goto      ConvertBin2BCDWordTens
;
ConvertBin2BCDWordTensEnd:
;
               movlw    10
               addwf    Binary,W,Access
               movwf    Units,Access
;
ConvertBin2BCDWordEnd:
;
              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
;*
;***************************************
;
;***************************************
;
; 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         movf      CalculatorY0,W,Access    ;Fetch Y low byte
              addwf     CalculatorX0,Same,Access ;And add to X low byte
;
              movlw     0                        ;Assume no CARRY
              btfsc     CarryFlag                ;IF CARRY
              movlw     1                        ;THEN correct assumption
              addwf     CalculatorX1,Same,Access ;Update middle byte with CARRY
              bcf       CalculatorBoolean        ;Assume no CARRY
              btfsc     CarryFlag                ;IF CARRY
              bsf       CalculatorBoolean        ;THEN correct assumption
              movf      CalculatorY1,W,Access    ;Fetch Y middle byte
              addwf     CalculatorX1,Same,Access ;And add to X middle byte
              btfsc     CarryFlag                ;IF CARRY
              bsf       CalculatorBoolean        ;THEN .OR. it
;
              movlw     0                        ;Assume no CARRY
              btfsc     CalculatorBoolean        ;IF CARRY
              movlw     1                        ;THEN correct assumption
              addwf     CalculatorX2,Same,Access ;Update high byte with CARRY
              bcf       CalculatorBoolean        ;Assume no CARRY
              btfsc     CarryFlag                ;IF CARRY
              bsf       CalculatorBoolean        ;THEN correct assumption
              movf      CalculatorY2,W,Access    ;Fetch Y high byte
              addwf     CalculatorX2,Same,Access ;And add to X high byte
              btfsc     CarryFlag                ;IF CARRY
              bsf       CalculatorBoolean        ;THEN .OR. it
;
              movlw     0                        ;Assume no CARRY
              btfsc     CalculatorBoolean        ;IF CARRY
              movlw     1                        ;THEN correct assumption
              addwf     CalculatorX3,Same,Access ;Update high byte with CARRY
              bcf       CalculatorBoolean        ;Assume no CARRY
              btfsc     CarryFlag                ;IF CARRY
              bsf       CalculatorBoolean        ;THEN correct assumption
              movf      CalculatorY3,W,Access    ;Fetch Y high byte
              addwf     CalculatorX3,Same,Access ;And add to X high byte
              btfsc     CarryFlag                ;IF CARRY
              bsf       CalculatorBoolean        ;THEN .OR. it
;
              movlw     0                        ;Assume no CARRY
              btfsc     CalculatorBoolean        ;IF CARRY
              movlw     1                        ;THEN correct assumption
              addwf     CalculatorX4,Same,Access ;Update high byte with CARRY
              bcf       CalculatorBoolean        ;Assume no CARRY
              btfsc     CarryFlag                ;IF CARRY
              bsf       CalculatorBoolean        ;THEN correct assumption
              movf      CalculatorY4,W,Access    ;Fetch Y high byte
              addwf     CalculatorX4,Same,Access ;And add to X high byte
              btfsc     CalculatorBoolean        ;IF CARRY
              bsf       CarryFlag                ;THEN .OR. it
;
              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         movf      CalculatorY0,W,Access    ;Fetch Y low byte
              subwf     CalculatorX0,Same,Access ;And subtract from X low byte
;
              movlw     0                        ;Assume no BORROW
              btfss     CarryFlag                ;IF BORROW
              movlw     1                        ;THEN correct assumption
              subwf     CalculatorX1,Same,Access ;Update high byte with BORROW
              bsf       CalculatorBoolean        ;Assume no BORROW
              btfss     CarryFlag                ;IF BORROW
              bcf       CalculatorBoolean        ;THEN correct assumption
              movf      CalculatorY1,W,Access    ;Fetch Y middle byte
              subwf     CalculatorX1,Same,Access ;And subtract from X middle byte
              btfss     CarryFlag                ;IF BORROW
              bcf       CalculatorBoolean        ;THEN .OR. it
;
              movlw     0                        ;Assume no BORROW
              btfss     CalculatorBoolean        ;IF BORROW
              movlw     1                        ;THEN correct assumption
              subwf     CalculatorX2,Same,Access ;Update high byte with BORROW
              bsf       CalculatorBoolean        ;Assume no BORROW
              btfss     CarryFlag                ;IF BORROW
              bcf       CalculatorBoolean        ;THEN correct assumption
              movf      CalculatorY2,W,Access    ;Fetch Y middle byte
              subwf     CalculatorX2,Same,Access ;And subtract from X middle byte
              btfss     CarryFlag                ;IF BORROW
              bcf       CalculatorBoolean        ;THEN .OR. it
;
              movlw     0                        ;Assume no BORROW
              btfss     CalculatorBoolean        ;IF BORROW
              movlw     1                        ;THEN correct assumption
              subwf     CalculatorX3,Same,Access ;Update high byte with BORROW
              bsf       CalculatorBoolean        ;Assume no BORROW
              btfss     CarryFlag                ;IF BORROW
              bcf       CalculatorBoolean        ;THEN correct assumption
              movf      CalculatorY3,W,Access    ;Fetch Y high byte
              subwf     CalculatorX3,Same,Access ;And subtract from X high byte
              btfss     CarryFlag                ;IF BORROW
              bcf       CalculatorBoolean        ;THEN .OR. it
;
              movlw     0                        ;Assume no BORROW
              btfss     CalculatorBoolean        ;IF BORROW
              movlw     1                        ;THEN correct assumption
              subwf     CalculatorX4,Same,Access ;Update high byte with BORROW
              bsf       CalculatorBoolean        ;Assume no BORROW
              btfss     CarryFlag                ;IF BORROW
              bcf       CalculatorBoolean        ;THEN correct assumption
              movf      CalculatorY4,W,Access    ;Fetch Y high byte
              subwf     CalculatorX4,Same,Access ;And subtract from X high byte
              btfss     CalculatorBoolean        ;IF BORROW
              bcf       CarryFlag                ;THEN .OR. it
;
              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 80-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         bcf       CalculatorError          ;Assume no ERROR
              bcf       CalculatorMulOver        ;RESET muliplier overflow flag
;
              movff     CalculatorX0,CalculatorTA0 ;Save X to Temp
              movff     CalculatorX1,CalculatorTA1
              movff     CalculatorX2,CalculatorTA2
              movff     CalculatorX3,CalculatorTA3
              movff     CalculatorX4,CalculatorTA4
;
              clrf      CalculatorX0,Access      ;Zero product
              clrf      CalculatorX1,Access
              clrf      CalculatorX2,Access
              clrf      CalculatorX3,Access
              clrf      CalculatorX4,Access
;
              movlw     40                       ;There are 40-bits to process
              movwf     CalculatorCount,Access
;
Mul40A        rrcf      CalculatorTA4,Same,Access ;IF LSB = 1
              rrcf      CalculatorTA3,Same,Access
              rrcf      CalculatorTA2,Same,Access
              rrcf      CalculatorTA1,Same,Access
              rrcf      CalculatorTA0,Same,Access
;
              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                    ;THEN update product
;
              btfsc     CarryFlag                ;IF CARRY, (from Add40)
              bsf       CalculatorError          ;THEN indicate an ERROR
;
              bcf       CarryFlag                ;CalcY * 2
              rlcf      CalculatorY0,Same,Access 
              rlcf      CalculatorY1,Same,Access
              rlcf      CalculatorY2,Same,Access 
              rlcf      CalculatorY3,Same,Access
              rlcf      CalculatorY4,Same,Access
;
              btfsc     CarryFlag                ;IF CalcY overflowed
              bsf       CalculatorMulOver        ;THEN flag for next addition
;
              decfsz    CalculatorCount,Same,Access ;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         bcf       CalculatorError          ;Assume no ERROR
              movf      CalculatorY0,W,Access    ;Fetch Y0        
              iorwf     CalculatorY1,W,Access    ;OR with Y1
              iorwf     CalculatorY2,W,Access    ;OR with Y2
              iorwf     CalculatorY3,W,Access    ;OR with Y3
              iorwf     CalculatorY4,W,Access    ;OR with Y4
              btfsc     ZeroFlag                 ;IF ZERO
              bsf       CalculatorError          ;THEN indicate an error
;
              movff     CalculatorX0,CalculatorTA0 ;Save X to Temp
              movff     CalculatorX1,CalculatorTA1
              movff     CalculatorX2,CalculatorTA2
              movff     CalculatorX3,CalculatorTA3
              movff     CalculatorX4,CalculatorTA4
;
              clrf      CalculatorX0,Access      ;Zero CalcX as temp work space
              clrf      CalculatorX1,Access
              clrf      CalculatorX2,Access
              clrf      CalculatorX3,Access
              clrf      CalculatorX4,Access
;
              movlw     40                       ;There are 32-bits to process
              movwf     CalculatorCount,Access
;
Div40A        rlcf      CalculatorTA0,Same,Access ;Quotient goes to temp LSB
              rlcf      CalculatorTA1,Same,Access       
              rlcf      CalculatorTA2,Same,Access
              rlcf      CalculatorTA3,Same,Access
              rlcf      CalculatorTA4,Same,Access
              rlcf      CalculatorX0,Same,Access  ;Temp MSB goes to CalcX LSB
              rlcf      CalculatorX1,Same,Access
              rlcf      CalculatorX2,Same,Access
              rlcf      CalculatorX3,Same,Access
              rlcf      CalculatorX4,Same,Access
;
              call      Sub40                    ;IF CalcX < CalcY
;
              bsf       CalculatorDivStore       ;Assume no BORROW
              btfss     CarryFlag                ;IF BORROW
              bcf       CalculatorDivStore       ;THEN correct assumption
;
              btfss     CarryFlag    
              call      Add40                    ;THEN restore CalcX
;
              bsf       CarryFlag                ;Assume no BORROW
              btfss     CalculatorDivStore       ;IF BORROW
              bcf       CarryFlag                ;THEN correct assumption
;
              decfsz    CalculatorCount,Same,Access ;IF more bits
              goto      Div40A                   ;THEN process them
;
              rlcf       CalculatorTA0,Same,Access ;Quotient goes to temp LSB
              rlcf       CalculatorTA1,Same,Access
              rlcf       CalculatorTA2,Same,Access
              rlcf       CalculatorTA3,Same,Access
              rlcf       CalculatorTA4,Same,Access
              movff      CalculatorTA0,CalculatorX0
              movff      CalculatorTA1,CalculatorX1
              movff      CalculatorTA2,CalculatorX2
              movff      CalculatorTA3,CalculatorX3
              movff      CalculatorTA4,CalculatorX4
;
              return                             ;Back we go
;
;***************************************
;
BCD2BinaryTU:
;
;***************************************
;
              swapf       CalculatorX0,W,Access
              andlw       b'00001111'
              movwf       CalculatorX1,Access
              movlw       b'00001111'
              andwf       CalculatorX0,Same,Access
;
BCD2BinaryTUA:
;
              movf        CalculatorX1,W,Access
              btfsc       ZeroFlag
              goto        BCD2BinaryTUB
;
              movlw       10
              addwf       CalculatorX0,Same,Access
;
              decf        CalculatorX1,Same,Access
;
              goto        BCD2BinaryTUA
;
BCD2BinaryTUB:
;
              return
;
;***************************************
;
; That's all the 40-bit maths routines we need for here
;
;***************************************
; 

;
WriteDS1307:
ReadDS1307:
ReadLastDS1307:
OpenWrite512:
Write512:
OpenRead512:
Read512:
ReadLast512:
;
              return

;
PollCellModuleWithTimeOutInitialise:
;
              bcf       PollComplete
;
              movlw     LineBufferSize
              movwf     LineBufferCounter,Access
;
              movlw     LOW(LineBuffer)
              movwf     LineBufferPointer,Access
;
              return
;
PollCellModuleWithTimeOut:
;
PollCellModuleWithTimeOut1
;
              call      CheckByteCell
              btfss     CarryFlag
              goto      PollCellModuleWithTimeOutEnd
;
PollCellModuleWithTimeOut2
;
              movwf     CharacterBuffer,Access
              movf      LineBufferCounter,W,Access
              btfsc     ZeroFlag
              goto      PollCellModuleWithTimeOut4
;
              lfsr      2,LineBuffer
              movf      LineBufferPointer,W,Access
              movwf     FSR2L,Access
;
              incf      LineBufferPointer,Same,Access
              movf      CharacterBuffer,W,Access
              movwf     INDF2,Access
              decf      LineBufferCounter,Same,Access
;
              xorlw     CR
              btfsc     ZeroFlag
              goto      PollCellModuleWithTimeOut4
;
              xorlw     LF^CR
              btfsc     ZeroFlag
              goto      PollCellModuleWithTimeOut4
;
 ;            xorlw     ';'^LF
 ;            btfss     ZeroFlag
              goto      PollCellModuleWithTimeOut1
;
              bsf       ConcatenatedCommands
;
PollCellModuleWithTimeOut4
;
              lfsr      2,LineBuffer
;
              movlw     LineBufferSize
              movwf     CharactersInBuffer,Access
              movf      LineBufferCounter,W,Access
              subwf     CharactersInBuffer,Same,Access
              decfsz    CharactersInBuffer,Same,Access
              goto      PollCellModuleWithTimeOut5
;
              call      PollCellModuleWithTimeOutInitialise
              goto      PollCellModuleWithTimeOut
;
PollCellModuleWithTimeOut5
;
              movf      INDF2,W,Access
;
              bcf       EOL
              call      Parse_IgnoreLeadingWhiteSpace
;
              btfss     EOL
              goto      PollCellModuleWithTimeOut5A
;
              call      PollCellModuleWithTimeOutInitialise
              goto      PollCellModuleWithTimeOut
;
PollCellModuleWithTimeOut5A
;
              call      Parse_ReadAlphaNumericSpecial
;
              PointToMessage CellResponses
;
              movlw     CellResponse
              movwf     PhraseCounter,Access
;
              call      Parse_SearchForPhrase
;
              btfsc     CarryFlag
              goto      PollCellModuleWithTimeOut6
;
; ### so we didn't find the cell module response, what do we do now?
;     lets load an unknown phrase number to indicate an error
;
              movlw     h'FF'                
              movwf     PhraseNumber,Access
;
PollCellModuleWithTimeOut6
;
              movf      PhraseNumber,W,Access    ;Return with the phrase number in W, so that the
                                                 ;calling routine can compare to see if it is the
                                                 ;response it requires!
;
              bsf       PollComplete
;
PollCellModuleWithTimeOutEnd
;
              return
;
Parse_IgnoreLeadingWhiteSpace:
;
              btfsc     EOL                            ;IF End Of Line
              goto      Parse_IgnoreLeadingWhiteSpace2 ;THEN go
;
              movf      INDF2,W,Access                 ;ELSE fetch next character
;
              xorlw     " "                            ;     IF SPACE
              btfsc     ZeroFlag
              goto      Parse_IgnoreLeadingWhiteSpace1 ;     THEN keep looking
;
              xorlw     Tab^" "                        ;     IF SPACE 
              btfsc     ZeroFlag
              goto      Parse_IgnoreLeadingWhiteSpace1 ;     THEN keep looking
;
              goto      Parse_IgnoreLeadingWhiteSpace2 ;     ELSE go
;
Parse_IgnoreLeadingWhiteSpace1
;
              incf      FSR2L,Same,Access              ;Point to next character
              decfsz    CharactersInBuffer,Same,Access ;Update number of characters left to go
              goto      Parse_IgnoreLeadingWhiteSpace  ;And check again
;
              bsf       EOL                            ;No more characters to be checked
;
Parse_IgnoreLeadingWhiteSpace2
;
              movf      FSR2L,W,Access                 ;Save pointer as start of parameter
              movwf     ParameterStart,Access
              clrf      ParameterLength,Access         ;Clear parameter length
;
              movf      INDF2,W,Access                 ;Fetch character, so we are ready!
;
              return
;
; EOL - 0 = FALSE, W = non AlphaNumericSpecial which terminated read
;     - 1 = TRUE
; ZeroFlag  - 0 = ParameterLength > 0
;           - 1 = ParameterLength = 0
;
Parse_ReadAlphaNumericSpecial:
;
              btfsc     EOL
              goto      Parse_ReadAlphaNumericSpecial1
;
              call      IsAlphaNumericSpecial
;
              btfss     CarryFlag
              goto      Parse_ReadAlphaNumericSpecial1
;
              incf      FSR2L,Same,Access
              incf      ParameterLength,Same,Access
              decfsz    CharactersInBuffer,Same,Access  ;IF more characters
              goto      Parse_ReadAlphaNumericSpecial   ;THEN keep checking
;
              bsf       EOL
;
Parse_ReadAlphaNumericSpecial1
;
              movf      INDF2,W,Access
              movf      ParameterLength,Same
;
              return
;
; EOL - 0 = FALSE, W = non AlphaNumeric which terminated read
;     - 1 = TRUE
; ZeroFlag  - 0 = ParameterLength > 0
;           - 1 = ParameterLength = 0
;
Parse_ReadAlphaNumeric:
;
              btfsc     EOL
              goto      Parse_ReadAlphaNumeric1
;
              call      IsAlphaNumeric
;
              btfss     CarryFlag
              goto      Parse_ReadAlphaNumeric1
;
              incf      FSR2L,Same,Access
              incf      ParameterLength,Same,Access
              decfsz    CharactersInBuffer,Same,Access  ;IF more characters
              goto      Parse_ReadAlphaNumeric   ;THEN keep checking
;
              bsf       EOL
;
Parse_ReadAlphaNumeric1
;
              movf      INDF2,W,Access
              movf      ParameterLength,Same
;
              return
;
; EOL - 0 = FALSE, W = non Numeric which terminated read
;     - 1 = TRUE
; ZeroFlag  - 0 = ParameterLength > 0
;           - 1 = ParameterLength = 0
;
Parse_ReadNumeric:
;
              btfsc     EOL
              goto      Parse_ReadNumeric1
;
              call      IsNumeric
;
              btfss     CarryFlag
              goto      Parse_ReadNumeric1
;
              incf      FSR2L,Same,Access
              incf      ParameterLength,Same,Access
              decfsz    CharactersInBuffer,Same,Access  ;IF more characters
              goto      Parse_ReadNumeric        ;THEN keep checking
;
              bsf       EOL
;
Parse_ReadNumeric1
;
              movf      INDF2,W,Access
              movf      ParameterLength,Same,Access
;
              return
;
Parse_ReadNextCharacter:
;
              btfsc     EOL
              goto      Parse_ReadNextCharacter1
;
              incf      FSR2L,Same,Access
              decfsz    CharactersInBuffer,Same,Access  ;IF more characters
              goto      Parse_ReadNextCharacter1 ;THEN keep checking
;
              bsf       EOL
;
Parse_ReadNextCharacter1
;
              movf      INDF2,W,Access
;
              return
;
Parse_SearchForPhrase:
;
              movf      ParameterLength,W,Access
              btfsc     ZeroFlag
              goto      Parse_SFP_PhraseNotFound
;
              clrf      PhraseNumber,Access
;
Parse_SFP_Next         
;
              movf      ParameterStart,W,Access
              movwf     FSR2L,Access
              movf      ParameterLength,W,Access
              movwf     PhraseLength,Access
;
Parse_SFP_Same         
;
              tblrd     *+
              movf      TABLAT,W,Access
              andlw     b'11111111'
              btfsc     ZeroFlag
              goto      Parse_SFP_FindNextCommand
              subwf     INDF2,W,Access
              btfss     ZeroFlag
              goto      Parse_SFP_SkipToEnd
;
              incf      FSR2L,Same,Access
              decfsz    PhraseLength,Same,Access
              goto      Parse_SFP_Same
;
Parse_SFP_CheckEnd
;
              tblrd     *+
              movf      TABLAT,W,Access
              andlw     b'11111111'
              btfsc     ZeroFlag
;
              goto      Parse_SFP_PhraseFound
;
Parse_SFP_SkipToEnd
;
              tblrd     *+                       ;Skip to end of message
              movf      TABLAT,W,Access
              andlw     b'11111111'
              btfss     ZeroFlag
              goto      Parse_SFP_SkipToEnd
;
Parse_SFP_FindNextCommand
;
              tblrd     *+                       ;Now find the beginning of the next message
              movf      TABLAT,W,Access
              andlw     b'11111111'
              btfsc     ZeroFlag
              goto      Parse_SFP_FindNextCommand
;
              tblrd     *-                       ;We went too far, so go back
              incf      PhraseNumber,Same,Access
              decfsz    PhraseCounter,Same,Access ;Do we have more phrases
              goto      Parse_SFP_Next            ;Yes, so check them
;
Parse_SFP_PhraseNotFound
;
              bcf       CarryFlag                ;Phrase not found
              goto      Parse_SFP_End            ;And go
;
Parse_SFP_PhraseFound
;
              bsf       CarryFlag                ;Phrase found
;
Parse_SFP_End
;
              return                             ;And back we go
;
IsAlpha:      movlw     "A"
              subwf     INDF2,W,Access
              btfss     CarryFlag
              goto      NotAlpha
;
              movlw     "Z"+1
              subwf     INDF2,W,Access
              btfss     CarryFlag
              goto      IsAlpha1
;
              movlw     "a"
              subwf     INDF2,W,Access
              btfss     CarryFlag
              goto      NotAlpha
;
              movlw     "z"+1
              subwf     INDF2,W,Access
              btfsc     CarryFlag
              goto      NotAlpha
;
; This is where we force all letters to be upper case, which may not always be ideal
;
              movlw     "a"-"A"
              subwf     INDF2,Same,Access
;
IsAlpha1      bsf       CarryFlag
              goto      IsAlphaEnd
NotAlpha      bcf       CarryFlag
IsAlphaEnd    movf      INDF2,W,Access
              return
;
IsAlphaNumericSpecial:
;
              movlw     " "
              subwf     INDF2,W,Access
              btfss     AcceptSpaces
              bcf       ZeroFlag              
              btfsc     ZeroFlag
              goto      IsAlphaNumericSpecial1
;
              movlw     "!"
              subwf     INDF2,W,Access
              btfsc     ZeroFlag
              goto      IsAlphaNumericSpecial1
;
              movlw     QuotationMark
              btfss     AcceptQuotationMarks
              movlw     "#"
;
              subwf     INDF2,W,Access
              btfss     CarryFlag
              goto      NotAlphaNumericSpecial
;
              movlw     "+"+1
              subwf     INDF2,W,Access
              btfss     CarryFlag
              goto      IsAlphaNumericSpecial1
;
              movlw     ","
              btfss     AcceptSpaces
              movlw     "-"
;
              subwf     INDF2,W,Access
              btfss     CarryFlag
              goto      NotAlphaNumericSpecial
;
              movlw     "/"+1
              subwf     INDF2,W,Access
              btfss     CarryFlag
              goto      IsAlphaNumericSpecial1
;
              movlw     "0"
              subwf     INDF2,W,Access
              btfss     CarryFlag
              goto      NotAlphaNumericSpecial
;
              movlw     "9"+1
              subwf     INDF2,W,Access
              btfss     CarryFlag
              goto      IsAlphaNumericSpecial1
;
              movlw     ":"
              subwf     INDF2,W,Access
              btfss     CarryFlag
              goto      NotAlphaNumericSpecial
;
              movlw     "@"+1
              subwf     INDF2,W,Access
              btfss     CarryFlag
              goto      IsAlphaNumericSpecial1
;
              movlw     "A"
              subwf     INDF2,W,Access
              btfss     CarryFlag
              goto      NotAlphaNumericSpecial
;
              movlw     "Z"+1
              subwf     INDF2,W,Access
              btfss     CarryFlag
              goto      IsAlphaNumericSpecial1
;
              movlw     "a"
              subwf     INDF2,W,Access
              btfss     CarryFlag
              goto      NotAlphaNumericSpecial
;
              movlw     "z"+1
              subwf     INDF2,W,Access
              btfsc     CarryFlag
              goto      NotAlphaNumericSpecial
;
; This is where we force letters to be upper case if necessary
;
              btfss     ForceToUpperCase
              goto      IsAlphaNumericSpecial1
;
              movlw     "a"-"A"
              subwf     INDF2,Same,Access
;
IsAlphaNumericSpecial1
;
              bsf       CarryFlag
              goto      IsAlphaNumericSpecialEnd
;
NotAlphaNumericSpecial
;
              bcf       CarryFlag
;
IsAlphaNumericSpecialEnd
;
              movf      INDF2,W,Access
              return
;
IsAlphaNumeric:
;
              movlw     "0"
              subwf     INDF2,W,Access
              btfss     CarryFlag
              goto      NotAlphaNumeric
;
              movlw     "9"+1
              subwf     INDF2,W,Access
              btfss     CarryFlag
              goto      IsAlphaNumeric1
;
              movlw     "A"
              subwf     INDF2,W,Access
              btfss     CarryFlag
              goto      NotAlphaNumeric
;
              movlw     "Z"+1
              subwf     INDF2,W,Access
              btfss     CarryFlag
              goto      IsAlphaNumeric1
;
              movlw     "a"
              subwf     INDF2,W,Access
              btfss     CarryFlag
              goto      NotAlphaNumeric
;
              movlw     "z"+1
              subwf     INDF2,W,Access
              btfsc     CarryFlag
              goto      NotAlphaNumeric
;
; This is where we force all letters to be upper case, which may not always be ideal
;
              movlw     "a"-"A"
              subwf     INDF2,Same,Access
;
IsAlphaNumeric1
;
              bsf       CarryFlag
              goto      IsAlphaNumericEnd
;
NotAlphaNumeric
;
              bcf       CarryFlag
;
IsAlphaNumericEnd
;
              movf      INDF2,W,Access
              return
;
IsNumeric:
;
              movlw     "0"
              subwf     INDF2,W,Access
              btfss     CarryFlag
              goto      NotNumeric
;
              movlw     "9"+1
              subwf     INDF2,W,Access
              btfsc     CarryFlag
              goto      NotNumeric
;
IsNumeric1
;
              bsf       CarryFlag
              goto      IsNumericEnd
;
NotNumeric
;
              bcf       CarryFlag
;
IsNumericEnd
;
              movf      INDF2,W,Access
              return
;
GSM_NibblesToASCII:
; 
              movwf     NibblesToASCIIScratch,Banked
              swapf     NibblesToASCIIScratch,W,Banked
              call      HexToASCII
              call      WriteByteSerialBuffer1
              movf      NibblesToASCIIScratch,W,Banked
              call      HexToASCII
              call      WriteByteSerialBuffer1
; 
              return
;
HexToASCII:
;
              andlw     b'00001111'
              addlw     BinaryToASCII
              movwf     HexToASCIIScratch,Banked
              movlw     '9'+1
              subwf     HexToASCIIScratch,W,Banked
              movlw     'A'-'9'-1
              btfss     CarryFlag
              movlw     0
              addwf     HexToASCIIScratch,W,Banked
;
              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:
;
              call      CalculateSecondsOffset_Hours 
              call      CalculateSecondsOffset_Minutes
              call      CalculateSecondsOffset_Seconds
;
              return
;
CalculateSecondsOffset_Hours:
;
              movf      RTC_Hours,W,Banked
              movwf     CalculatorX0,Access
;
              call      BCD2BinaryTU
;
              movlw     7
              subwf     CalculatorX0,W,Access
              movlw     -7
              btfss     CarryFlag
              movlw     17
              addwf     CalculatorX0,Same,Access         
              clrf      CalculatorX1,Access
              clrf      CalculatorX2,Access
              clrf      CalculatorX3,Access
              clrf      CalculatorX4,Access
;
              movlw     LOW(60*60)
              movwf     CalculatorY0,Access
              movlw     HIGH(60*60)
              movwf     CalculatorY1,Access
              clrf      CalculatorY2,Access
              clrf      CalculatorY3,Access
              clrf      CalculatorY4,Access
;
              call      Mul40
;
              movf      CalculatorX0,W,Access
              movwf     Seconds_Offset,Banked
              movf      CalculatorX1,W,Access
              movwf     Seconds_OffsetH,Banked
              movf      CalculatorX2,W,Access
              movwf     Seconds_OffsetHH,Banked
;
              return
;
CalculateSecondsOffset_Minutes:
;
              movf      RTC_Minutes,W,Banked
              movwf     CalculatorX0,Access
;
              call      BCD2BinaryTU
;
              clrf      CalculatorX1,Access
              clrf      CalculatorX2,Access
              clrf      CalculatorX3,Access
              clrf      CalculatorX4,Access
;
              movlw     LOW(60)
              movwf     CalculatorY0,Access
              movlw     HIGH(60)
              movwf     CalculatorY1,Access 
              clrf      CalculatorY2,Access
              clrf      CalculatorY3,Access
              clrf      CalculatorY4,Access
;
              call      Mul40
;
              movf      CalculatorX0,W,Access
              addwf     Seconds_Offset,Same,Banked
              movf      CalculatorX1,W,Access
              addwfc    Seconds_OffsetH,Same,Banked
              movf      CalculatorX2,W,Access
              addwfc    Seconds_OffsetHH,Same,Banked
;
              return
;
CalculateSecondsOffset_Seconds:
;
              movf      RTC_Seconds,W,Banked
              movwf     CalculatorX0,Access
;
              call      BCD2BinaryTU
;
              clrf      CalculatorX1,Access
              clrf      CalculatorX2,Access
;
              movf      CalculatorX0,W,Access
              addwf     Seconds_Offset,Same,Banked
              movf      CalculatorX1,W,Access
              addwfc    Seconds_OffsetH,Same,Banked
              movf      CalculatorX2,W,Access
              addwfc    Seconds_OffsetHH,Same,Banked
;
              return
;
ProcessGSM:	      
;
;***************************************
;
; This is the GSM state machine
;
;***************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
GSM_StateMachine:
;
GSMStateNumber set 0
;
CreateStateTableEntry macro Reference,Executes
Reference        equ   GSMStateNumber 
GSMStateNumber set GSMStateNumber + 1 
                 goto  Executes
                 endm
;
Dispatch = 0
Release = ~Dispatch
;
GSM_EndOfState macro Destination
;
           IF Destination == Dispatch
              goto      ProcessGSM
           ELSE
              IF Destination == Release
                 goto   ProcessGSM_End
              ELSE
                 ERROR "Inavlid operand for GSM_EndOfState >>> GSM_EndOfState Dispatch OR GSM_EndOfState Release"
              ENDIF
           ENDIF
;
              endm
;
ProcessGSM:
;
              clrf      PCLATU,Access
;
              movff     GSM_State,GSM_Dispatch
              clrf      GSM_DispatchH,Banked
;
              bcf       CarryFlag
              rlcf      GSM_Dispatch,Same,Banked
              rlcf      GSM_DispatchH,Same,Banked
;
              rlcf      GSM_Dispatch,Same,Banked
              rlcf      GSM_DispatchH,Same,Banked
;
              movlw     LOW(GSMStateTable)
              addwf     GSM_Dispatch,Same,Banked
              movlw     HIGH(GSMStateTable)
              addwfc    GSM_DispatchH,W,Banked
              movwf     PCLATH,Access
              movf      GSM_Dispatch,W,Banked
              movwf     PCL,Access
;
; States that need to be added to this table
; - States to extract the data bundle value for the various networks
;   - See if we can simply have a generic set of code with settings or if we have to code up parsers for each network
; - States to make the MTN SIM card work with the rain gauge 
;   - Verify the APN, username and password required by MTN
;
GSMStateTable:
;
GSM_00        CreateStateTableEntry S_GSM_IdleInitialise,X_GSM_IdleInitialise
GSM_01        CreateStateTableEntry S_GSM_Idle,X_GSM_Idle
;
GSM_02        CreateStateTableEntry S_GSM_ModuleOn,X_GSM_ModuleOn
GSM_03        CreateStateTableEntry S_GSM_ModuleOnWait,X_GSM_ModuleOnWait
GSM_04        CreateStateTableEntry S_GSM_ModuleOnInitialising,X_GSM_ModuleOnInitialising
;
GSM_05        CreateStateTableEntry S_GSM_CheckForCellModule,X_GSM_CheckForCellModule
GSM_06        CreateStateTableEntry S_GSM_CheckForCellModuleWait,X_GSM_CheckForCellModuleWait
GSM_07        CreateStateTableEntry S_GSM_CheckForCellModulePoll,X_GSM_CheckForCellModulePoll
GSM_08        CreateStateTableEntry S_GSM_CheckForCellModuleAnalyse,X_GSM_CheckForCellModuleAnalyse
;
GSM_09        CreateStateTableEntry S_GSM_EchoOff,X_GSM_EchoOff
GSM_10        CreateStateTableEntry S_GSM_EchoOffWait,X_GSM_EchoOffWait
GSM_11        CreateStateTableEntry S_GSM_EchoOffPoll,X_GSM_EchoOffPoll
GSM_12        CreateStateTableEntry S_GSM_EchoOffAnalyse,X_GSM_EchoOffAnalyse
;
GSM_13        CreateStateTableEntry S_GSM_TimeStampEnable,X_GSM_TimeStampEnable
GSM_14        CreateStateTableEntry S_GSM_TimeStampEnableWait,X_GSM_TimeStampEnableWait
GSM_15        CreateStateTableEntry S_GSM_TimeStampEnablePoll,X_GSM_TimeStampEnablePoll
GSM_16        CreateStateTableEntry S_GSM_TimeStampEnableAnalyse,X_GSM_TimeStampEnableAnalyse
;
GSM_17        CreateStateTableEntry S_GSM_SaveProfile,X_GSM_SaveProfile
GSM_18        CreateStateTableEntry S_GSM_SaveProfileWait,X_GSM_SaveProfileWait
GSM_19        CreateStateTableEntry S_GSM_SaveProfilePoll,X_GSM_SaveProfilePoll
GSM_20        CreateStateTableEntry S_GSM_SaveProfileAnalyse,X_GSM_SaveProfileAnalyse
;
GSM_21        CreateStateTableEntry S_GSM_ReadTimeStamp,X_GSM_ReadTimeStamp
GSM_22        CreateStateTableEntry S_GSM_ReadTimeStampWait,X_GSM_ReadTimeStampWait
GSM_23        CreateStateTableEntry S_GSM_ReadTimeStampPoll,X_GSM_ReadTimeStampPoll
GSM_24        CreateStateTableEntry S_GSM_ReadTimeStampAnalyse,X_GSM_ReadTimeStampAnalyse
; 
GSM_25        CreateStateTableEntry S_GSM_SelectTextMode,X_GSM_SelectTextMode
GSM_26        CreateStateTableEntry S_GSM_SelectTextModeWait,X_GSM_SelectTextModeWait
GSM_27        CreateStateTableEntry S_GSM_SelectTextModePoll,X_GSM_SelectTextModePoll
GSM_28        CreateStateTableEntry S_GSM_SelectTextModeAnalyse,X_GSM_SelectTextModeAnalyse
;
GSM_29        CreateStateTableEntry S_GSM_NetworkRegistration,X_GSM_NetworkRegistration
GSM_30        CreateStateTableEntry S_GSM_NetworkRegistrationWait,X_GSM_NetworkRegistrationWait
GSM_31        CreateStateTableEntry S_GSM_NetworkRegistrationPoll,X_GSM_NetworkRegistrationPoll
GSM_32        CreateStateTableEntry S_GSM_NetworkRegistrationAnalyse,X_GSM_NetworkRegistrationAnalyse
;
GSM_33        CreateStateTableEntry S_GSM_GPRSattachment,X_GSM_GPRSattachment
GSM_34        CreateStateTableEntry S_GSM_GPRSattachmentWait,X_GSM_GPRSattachmentWait
GSM_35        CreateStateTableEntry S_GSM_GPRSattachmentPoll,X_GSM_GPRSattachmentPoll
GSM_36        CreateStateTableEntry S_GSM_GPRSattachmentAnalyse,X_GSM_GPRSattachmentAnalyse
;
GSM_37        CreateStateTableEntry S_GSM_ConnectionType,X_GSM_ConnectionType
GSM_38        CreateStateTableEntry S_GSM_ConnectionTypeWait,X_GSM_ConnectionTypeWait
GSM_39        CreateStateTableEntry S_GSM_ConnectionTypePoll,X_GSM_ConnectionTypePoll
GSM_40        CreateStateTableEntry S_GSM_ConnectionTypeAnalyse,X_GSM_ConnectionTypeAnalyse
;
GSM_41        CreateStateTableEntry S_GSM_SetAPN,X_GSM_SetAPN
GSM_42        CreateStateTableEntry S_GSM_SetAPNWait,X_GSM_SetAPNWait
GSM_43        CreateStateTableEntry S_GSM_SetAPNPoll,X_GSM_SetAPNPoll
GSM_44        CreateStateTableEntry S_GSM_SetAPNAnalyse,X_GSM_SetAPNAnalyse
;
GSM_45        CreateStateTableEntry S_GSM_OpenBearer,X_GSM_OpenBearer
GSM_46        CreateStateTableEntry S_GSM_OpenBearerWait,X_GSM_OpenBearerWait
GSM_47        CreateStateTableEntry S_GSM_OpenBearerPoll,X_GSM_OpenBearerPoll
GSM_48        CreateStateTableEntry S_GSM_OpenBearerAnalyse,X_GSM_OpenBearerAnalyse
;
GSM_49        CreateStateTableEntry S_GSM_QueryBearer,X_GSM_QueryBearer
GSM_50        CreateStateTableEntry S_GSM_QueryBearerWait,X_GSM_QueryBearerWait
GSM_51        CreateStateTableEntry S_GSM_QueryBearerPoll,X_GSM_QueryBearerPoll
GSM_52        CreateStateTableEntry S_GSM_QueryBearerAnalyse,X_GSM_QueryBearerAnalyse
;
GSM_53        CreateStateTableEntry S_GSM_HTTPinit,X_GSM_HTTPinit
GSM_54        CreateStateTableEntry S_GSM_HTTPinitWait,X_GSM_HTTPinitWait
GSM_55        CreateStateTableEntry S_GSM_HTTPinitPoll,X_GSM_HTTPinitPoll
GSM_56        CreateStateTableEntry S_GSM_HTTPinitAnalyse,X_GSM_HTTPinitAnalyse
;
GSM_57        CreateStateTableEntry S_GSM_BearerID,X_GSM_BearerID
GSM_58        CreateStateTableEntry S_GSM_BearerIDWait,X_GSM_BearerIDWait
GSM_59        CreateStateTableEntry S_GSM_BearerIDPoll,X_GSM_BearerIDPoll
GSM_60        CreateStateTableEntry S_GSM_BearerIDAnalyse,X_GSM_BearerIDAnalyse
;
GSM_61        CreateStateTableEntry S_GSM_SetURL,X_GSM_SetURL
GSM_62        CreateStateTableEntry S_GSM_SetURLWait,X_GSM_SetURLWait
GSM_63        CreateStateTableEntry S_GSM_SetURLPoll,X_GSM_SetURLPoll
GSM_64        CreateStateTableEntry S_GSM_SetURLAnalyse,X_GSM_SetURLAnalyse
;
GSM_65        CreateStateTableEntry S_GSM_ContentType,X_GSM_ContentType
GSM_66        CreateStateTableEntry S_GSM_ContentTypeWait,X_GSM_ContentTypeWait
GSM_67        CreateStateTableEntry S_GSM_ContentTypePoll,X_GSM_ContentTypePoll
GSM_68        CreateStateTableEntry S_GSM_ContentTypeAnalyse,X_GSM_ContentTypeAnalyse
;
GSM_69        CreateStateTableEntry S_GSM_DataSize,X_GSM_DataSize
GSM_70        CreateStateTableEntry S_GSM_DataSizeWait,X_GSM_DataSizeWait
GSM_71        CreateStateTableEntry S_GSM_DataSizePoll,X_GSM_DataSizePoll
GSM_72        CreateStateTableEntry S_GSM_DataSizeAnalyse,X_GSM_DataSizeAnalyse
;
GSM_73        CreateStateTableEntry S_GSM_SendData,X_GSM_SendData
GSM_74        CreateStateTableEntry S_GSM_SendDataWait,X_GSM_SendDataWait
GSM_75        CreateStateTableEntry S_GSM_SendDataPoll,X_GSM_SendDataPoll
GSM_76        CreateStateTableEntry S_GSM_SendDataAnalyse,X_GSM_SendDataAnalyse
;
GSM_77        CreateStateTableEntry S_GSM_HTTPaction,X_GSM_HTTPaction
GSM_78        CreateStateTableEntry S_GSM_HTTPactionWait,X_GSM_HTTPactionWait
GSM_79        CreateStateTableEntry S_GSM_HTTPactionPoll,X_GSM_HTTPactionPoll
GSM_80        CreateStateTableEntry S_GSM_HTTPactionAnalyse,X_GSM_HTTPactionAnalyse
;
GSM_81        CreateStateTableEntry S_GSM_HTTPread,X_GSM_HTTPread
GSM_82        CreateStateTableEntry S_GSM_HTTPreadWait,X_GSM_HTTPreadWait
GSM_83        CreateStateTableEntry S_GSM_HTTPreadPoll,X_GSM_HTTPreadPoll
GSM_84        CreateStateTableEntry S_GSM_HTTPreadAnalyse,X_GSM_HTTPreadAnalyse
;
GSM_85        CreateStateTableEntry S_GSM_HTTPterminate,X_GSM_HTTPterminate
GSM_86        CreateStateTableEntry S_GSM_HTTPterminateWait,X_GSM_HTTPterminateWait
GSM_87        CreateStateTableEntry S_GSM_HTTPterminatePoll,X_GSM_HTTPterminatePoll
GSM_88        CreateStateTableEntry S_GSM_HTTPterminateAnalyse,X_GSM_HTTPterminateAnalyse
;
GSM_89        CreateStateTableEntry S_GSM_CloseBearer,X_GSM_CloseBearer
GSM_90        CreateStateTableEntry S_GSM_CloseBearerWait,X_GSM_CloseBearerWait
GSM_91        CreateStateTableEntry S_GSM_CloseBearerPoll,X_GSM_CloseBearerPoll
GSM_92        CreateStateTableEntry S_GSM_CloseBearerAnalyse,X_GSM_CloseBearerAnalyse
;
GSM_93        CreateStateTableEntry S_GSM_ModuleOff,X_GSM_ModuleOff
GSM_94        CreateStateTableEntry S_GSM_ModuleOffWait,X_GSM_ModuleOffWait
GSM_95        CreateStateTableEntry S_GSM_ModuleOffCheck,X_GSM_ModuleOffCheck
GSM_96        CreateStateTableEntry S_GSM_ModuleOffDone,X_GSM_ModuleOffDone
GSM_97        CreateStateTableEntry S_GSM_ModuleOffPause,X_GSM_ModuleOffPause
;
; Legacy SMS states - not currently used
;
GSM_25y       CreateStateTableEntry S_GSM_ReplySMS,X_GSM_ReplySMS
GSM_26y       CreateStateTableEntry S_GSM_ReplySMSWait,X_GSM_ReplySMSWait
GSM_27y       CreateStateTableEntry S_GSM_ReplySMSWaitForPromptA,X_GSM_ReplySMSWaitForPromptA
GSM_28y       CreateStateTableEntry S_GSM_ReplySMSWaitForPromptB,X_GSM_ReplySMSWaitForPromptB
GSM_29y       CreateStateTableEntry S_GSM_ReplySMSPoll,X_GSM_ReplySMSPoll
GSM_30y       CreateStateTableEntry S_GSM_ReplySMSAnalyse,X_GSM_ReplySMSAnalyse
;
;*************************************************
;
; This is the STATE we should spend most of our time in!!!
;
;*************************************************
;
X_GSM_IdleInitialise:
;
              movf      InitialiseRetries,W,Banked
              btfsc     ZeroFlag
              goto      X_GSM_IdleInitialise_KillForNow
;
              decf      InitialiseRetries,Same,Banked
;
              movlw     S_GSM_Idle
              movff     WREG,GSM_State
;
              goto      X_GSM_IdleInitialise_End
;
X_GSM_IdleInitialise_KillForNow:
;
              bcf       SendSMS
;
; N213 include this code to delay longer when POSTs are not acknowledged by the server
;
           IFDEF NAKDelay
;
              incfsz    NAKDelayMultiplier,W,Banked
              incf      NAKDelayMultiplier,Same,Banked
;
           ENDIF
;
; N213 include this code to delay longer when POSTs are not acknowledged by the server
;
              movlw     S_GSM_ModuleOffDone
              movff     WREG,GSM_State
;
              goto      X_GSM_IdleInitialise_End
;
X_GSM_IdleInitialise_End:
;
              GSM_EndOfState Dispatch
;
X_GSM_Idle:
;
              movlw     S_GSM_ModuleOn
              movff     WREG,GSM_State
;
X_GSM_IdleEnd
;
              GSM_EndOfState Release
;
;*************************************************
;
; These STATEs switch the cell module on
;
;*************************************************
;
;-----------------------
;
X_GSM_ModuleOn:
;
;-----------------------
;
              bcf       GSM_DTR_out              ;Wake up from sleep
;
              btfsc     GSM_Powered
              goto      X_GSM_ModuleOn_1
;      
              bsf       GSM_On
;
              call      LoadCellModuleTimeOut_ModuleOn
;
              movlw     S_GSM_ModuleOnWait
              movff     WREG,GSM_State
;
              GSM_EndOfState Release
;
X_GSM_ModuleOn_1:
;
              bcf       GSM_On
;
              call      LoadCellModuleTimeOut_GSMInitialising
;
              movlw     S_GSM_ModuleOnInitialising
              movff     WREG,GSM_State
;
              GSM_EndOfState Release
;    
;-----------------------
;
X_GSM_ModuleOnWait:
;
;-----------------------
;
              btfss     CellModuleResponseTimeOut
              goto      X_GSM_ModuleOnWait_End
;
              bcf       GSM_On
;
              call      LoadCellModuleTimeOut_GSMInitialising
;
              movlw     S_GSM_ModuleOnInitialising
              movff     WREG,GSM_State
;
X_GSM_ModuleOnWait_End
;
              GSM_EndOfState Release
;
;-----------------------
;
X_GSM_ModuleOnInitialising:
;
;-----------------------
;
              btfss     CellModuleResponseTimeOut
              goto      X_GSM_ModuleOnInitialising_End
;
              movlw     S_GSM_CheckForCellModule
              movff     WREG,GSM_State
;
X_GSM_ModuleOnInitialising_End
;
              GSM_EndOfState Release
;
;*************************************************
;
; These STATEs check to see if the cell module is connected to the system and that it responds with OK
;
;*************************************************
;
;-----------------------
;
X_GSM_CheckForCellModule:
;
;-----------------------
;
              call      LoadCellModuleTimeOut_CommandDelay
;
              movlw     S_GSM_CheckForCellModuleWait
              movff     WREG,GSM_State
;
              GSM_EndOfState Release
;
;-----------------------
;
X_GSM_CheckForCellModuleWait:
;
;-----------------------
;
              btfss     CellModuleResponseTimeOut
              goto      X_GSM_CheckForCellModuleWaitEnd
;
              call      FlushSerialReceiveBuffer1 ;Dump the receive buffer so that we can't get confused
;
              bcf       NoCR
              SendCellMessage Cell_Message_QueryModule
;
              call      LoadCellModuleTimeOut_QueryModule
;
              call      PollCellModuleWithTimeOutInitialise
;
              movlw    S_GSM_CheckForCellModulePoll
              movff    WREG,GSM_State
;
X_GSM_CheckForCellModuleWaitEnd:
;
              GSM_EndOfState Release
;
;-----------------------
;
X_GSM_CheckForCellModulePoll:
;
;-----------------------
;
              bsf       AcceptSpaces
              call      PollCellModuleWithTimeOut
;
              btfss     PollComplete
              goto      X_GSM_CheckForCellModulePoll1
;
              movlw     S_GSM_CheckForCellModuleAnalyse
              movff     WREG,GSM_State
;
              GSM_EndOfState Dispatch
;
X_GSM_CheckForCellModulePoll1:
;
              btfss     CellModuleResponseTimeOut
              goto      X_GSM_CheckForCellModulePollEnd
;
              bcf       GSM_CellModulePresent
;
              movlw     S_GSM_ModuleOff
              movff     WREG,GSM_State
;
X_GSM_CheckForCellModulePollEnd:
;
              GSM_EndOfState Release
;
;-----------------------
;
X_GSM_CheckForCellModuleAnalyse:
;
;-----------------------
;
              movf      PhraseNumber,W,Access
              xorlw     CellResponse_AT
              btfss     ZeroFlag
              goto      X_GSM_Check4CellModuleAnalyse1
;
              bsf       GSM_EchoOffRequired
;
              call      PollCellModuleWithTimeOutInitialise
;
              movlw     S_GSM_CheckForCellModulePoll
              movff     WREG,GSM_State
;
              GSM_EndOfState Dispatch
;
X_GSM_Check4CellModuleAnalyse1:
;
              xorlw     CellResponse_OK^CellResponse_AT
              btfss     ZeroFlag
              goto      X_GSM_Check4CellModuleAnalyse2
;
              bsf       GSM_CellModulePresent
;
              movlw     S_GSM_EchoOff
              movff     WREG,GSM_State
;
              goto      X_GSM_Check4CellModuleAnalyseEnd
;
X_GSM_Check4CellModuleAnalyse2:
;
              bcf       GSM_CellModulePresent
;
              movlw     S_GSM_ModuleOff
              movff     WREG,GSM_State
;
X_GSM_Check4CellModuleAnalyseEnd:
;
              GSM_EndOfState Release
;
;*************************************************
;
; These STATEs check to see if command echo must be switched off
;
;*************************************************
;
;-----------------------
;
X_GSM_EchoOff:
;
;-----------------------
;
              btfsc     GSM_EchoOffRequired
              goto      X_GSM_EchoOff1
;
              movlw     S_GSM_TimeStampEnable ;S_GSM_SelectTextMode
              movff     WREG,GSM_State
;
              goto      X_GSM_EchoOffEnd
;
X_GSM_EchoOff1
;
              call      LoadCellModuleTimeOut_CommandDelay
;
              movlw     S_GSM_EchoOffWait
              movff     WREG,GSM_State
;
X_GSM_EchoOffEnd
;
              GSM_EndOfState Release
;
;-----------------------
;
X_GSM_EchoOffWait:
;
;-----------------------
;
              btfss     CellModuleResponseTimeOut
              goto      X_GSM_EchoOffWaitEnd
;
              call      FlushSerialReceiveBuffer1
;
              bcf       NoCR
              SendCellMessage Cell_Message_CommandEchoOff
;
              call      LoadCellModuleTimeOut_CommandEchoOff
;
              call      PollCellModuleWithTimeOutInitialise
;
              movlw     S_GSM_EchoOffPoll
              movff     WREG,GSM_State
;
              GSM_EndOfState Dispatch              ;Process on this pass
;             
X_GSM_EchoOffWaitEnd
;
              GSM_EndOfState Release
;
;-----------------------
;
X_GSM_EchoOffPoll:
;
;-----------------------
;
              bsf       AcceptSpaces
              call      PollCellModuleWithTimeOut
;
              btfss     PollComplete
              goto      X_GSM_EchoOffPoll1
;
              movlw     S_GSM_EchoOffAnalyse
              movff     WREG,GSM_State
;
              GSM_EndOfState Dispatch
;
X_GSM_EchoOffPoll1
;
              btfss     CellModuleResponseTimeOut
              goto      X_GSM_EchoOffPollEnd
;
              movlw     S_GSM_ModuleOff
              movff     WREG,GSM_State
;
X_GSM_EchoOffPollEnd
;
              GSM_EndOfState Release
;
;-----------------------
;
X_GSM_EchoOffAnalyse:
;
;-----------------------
;
              movf      PhraseNumber,W,Access
              xorlw     CellResponse_CommandEchoOff
              btfss     ZeroFlag
              goto      X_GSM_EchoOffAnalyse1
;
              call      PollCellModuleWithTimeOutInitialise
;
              movlw     S_GSM_EchoOffPoll
              movff     WREG,GSM_State
;
              GSM_EndOfState Dispatch
;
X_GSM_EchoOffAnalyse1
;
              xorlw     CellResponse_OK^CellResponse_CommandEchoOff
              btfss     ZeroFlag
              goto      X_GSM_EchoOffAnalyse2
;
              bcf       GSM_EchoOffRequired
;
              movlw     S_GSM_TimeStampEnable ;S_GSM_SelectTextMode
              movff     WREG,GSM_State
;
              goto      X_GSM_EchoOffAnalyseEnd
;
X_GSM_EchoOffAnalyse2
;
              movlw     S_GSM_ModuleOff
              movff     WREG,GSM_State
;
X_GSM_EchoOffAnalyseEnd
;
              GSM_EndOfState Release
;
;*************************************************
;
; These STATEs enable time reporting at power up
;
;*************************************************
;
;-----------------------
;
X_GSM_TimeStampEnable: 
;
;-----------------------
;
              call      LoadCellModuleTimeOut_CommandDelay
;
              movlw     S_GSM_TimeStampEnableWait
              movff     WREG,GSM_State
;
X_GSM_TimeStampEnableEnd
;
              GSM_EndOfState Release
;
;-----------------------
;
X_GSM_TimeStampEnableWait:
;
;-----------------------
;
              btfss     CellModuleResponseTimeOut
              goto      X_GSM_TimeStampEnableWaitEnd
;
              call      FlushSerialReceiveBuffer1
;
              bcf       NoCR
              SendCellMessage Cell_Message_TimeStampEnable
;
              call      LoadCellModuleTimeOut_TimeStampEnable
;
              call      PollCellModuleWithTimeOutInitialise
;
              movlw     S_GSM_TimeStampEnablePoll
              movff     WREG,GSM_State
;
              GSM_EndOfState Dispatch              ;Process on this pass
;             
X_GSM_TimeStampEnableWaitEnd
;
              GSM_EndOfState Release
;
;-----------------------
;
X_GSM_TimeStampEnablePoll:
;
;-----------------------
;
              bsf       AcceptSpaces
              call      PollCellModuleWithTimeOut
;
              btfss     PollComplete
              goto      X_GSM_TimeStampEnablePoll1
;
              movlw     S_GSM_TimeStampEnableAnalyse
              movff     WREG,GSM_State
;
              GSM_EndOfState Dispatch
;
X_GSM_TimeStampEnablePoll1
;
              btfss     CellModuleResponseTimeOut
              goto      X_GSM_TimeStampEnablePollEnd
;
              movlw     S_GSM_ModuleOff
              movff     WREG,GSM_State
;
X_GSM_TimeStampEnablePollEnd
;
              GSM_EndOfState Release
;
;-----------------------
;
X_GSM_TimeStampEnableAnalyse:
;
;-----------------------
;
; This command can have 2 responses:
; - OK 
; - ERROR
; In either case we carry on because we don't want a case where the network doesn't support this and then the rest of the unit doesn't work!
; - If it isn't supported the network won't report the time at power up and the user will have to use a device to set the time in the unit
;
              movf      PhraseNumber,W,Access
              xorlw     CellResponse_OK
              btfss     ZeroFlag
              goto      X_GSM_TimeStampEnableAnalyse1
;
              movlw     S_GSM_SaveProfile ;S_GSM_SelectTextMode
              movff     WREG,GSM_State
;
              GSM_EndOfState Dispatch
;
X_GSM_TimeStampEnableAnalyse1
;
              movlw     S_GSM_SaveProfile ;S_GSM_SelectTextMode
              movff     WREG,GSM_State
;
X_GSM_TimeStampEnableAnalyseEnd
;
              GSM_EndOfState Release
;
;*************************************************
;
; These STATEs save the TimeTampStampEnable to the power up profile
;
;*************************************************
;
;-----------------------
;
X_GSM_SaveProfile: 
;
;-----------------------
;
              call      LoadCellModuleTimeOut_CommandDelay
;
              movlw     S_GSM_SaveProfileWait
              movff     WREG,GSM_State
;
X_GSM_SaveProfileEnd
;
              GSM_EndOfState Release
;
;-----------------------
;
X_GSM_SaveProfileWait:
;
;-----------------------
;
              btfss     CellModuleResponseTimeOut
              goto      X_GSM_SaveProfileWaitEnd
;
              call      FlushSerialReceiveBuffer1
;
              bcf       NoCR
              SendCellMessage Cell_Message_SaveProfile
;
              call      LoadCellModuleTimeOut_SaveProfile
;
              call      PollCellModuleWithTimeOutInitialise
;
              movlw     S_GSM_SaveProfilePoll
              movff     WREG,GSM_State
;
              GSM_EndOfState Dispatch              ;Process on this pass
;             
X_GSM_SaveProfileWaitEnd
;
              GSM_EndOfState Release
;
;-----------------------
;
X_GSM_SaveProfilePoll:
;
;-----------------------
;
              bsf       AcceptSpaces
              call      PollCellModuleWithTimeOut
;
              btfss     PollComplete
              goto      X_GSM_SaveProfilePoll1
;
              movlw     S_GSM_SaveProfileAnalyse
              movff     WREG,GSM_State
;
              GSM_EndOfState Dispatch
;
X_GSM_SaveProfilePoll1
;
              btfss     CellModuleResponseTimeOut
              goto      X_GSM_SaveProfilePollEnd
;
              movlw     S_GSM_ModuleOff
              movff     WREG,GSM_State
;
X_GSM_SaveProfilePollEnd
;
              GSM_EndOfState Release
;
;-----------------------
;
X_GSM_SaveProfileAnalyse:
;
;-----------------------
;
; This command can have 2 responses:
; - OK 
; - ERROR
; In either case we carry on because we don't want a case where the profile won't save and then the rest of the unit doesn't work!
; - If it doesn't save the network won't report the time at power up and the user will have to use a device to set the time in the unit
;
              movf      PhraseNumber,W,Access
              xorlw     CellResponse_OK
              btfss     ZeroFlag
              goto      X_GSM_SaveProfileAnalyse1
;
              movlw     S_GSM_ReadTimeStamp ;S_GSM_SelectTextMode
              movff     WREG,GSM_State
;
              GSM_EndOfState Dispatch
;
X_GSM_SaveProfileAnalyse1
;
              movlw     S_GSM_ReadTimeStamp ;S_GSM_SelectTextMode
              movff     WREG,GSM_State
;
X_GSM_SaveProfileAnalyseEnd
;
              GSM_EndOfState Release
;
;*************************************************
;
; These STATEs read the time stamp
;
;*************************************************
;
;-----------------------
;
X_GSM_ReadTimeStamp: 
;
;-----------------------
;
              call      LoadCellModuleTimeOut_CommandDelay
;
              movlw     S_GSM_ReadTimeStampWait
              movff     WREG,GSM_State
;
X_GSM_ReadTimeStampEnd
;
              GSM_EndOfState Release
;
;-----------------------
;
X_GSM_ReadTimeStampWait:
;
;-----------------------
;
              btfss     CellModuleResponseTimeOut
              goto      X_GSM_ReadTimeStampWaitEnd
;
              call      FlushSerialReceiveBuffer1
;
              bcf       NoCR
              SendCellMessage Cell_Message_ReadTimeStamp
;
              call      LoadCellModuleTimeOut_ReadTimeStamp
;
              call      PollCellModuleWithTimeOutInitialise
;
              movlw     S_GSM_ReadTimeStampPoll
              movff     WREG,GSM_State
;
              GSM_EndOfState Dispatch              ;Process on this pass
;             
X_GSM_ReadTimeStampWaitEnd
;
              GSM_EndOfState Release
;
;-----------------------
;
X_GSM_ReadTimeStampPoll:
;
;-----------------------
;
              bcf       AcceptSpaces
              call      PollCellModuleWithTimeOut
;
              btfss     PollComplete
              goto      X_GSM_ReadTimeStampPoll1
;
              movlw     S_GSM_ReadTimeStampAnalyse
              movff     WREG,GSM_State
;
              GSM_EndOfState Dispatch
;
X_GSM_ReadTimeStampPoll1
;
              btfss     CellModuleResponseTimeOut
              goto      X_GSM_ReadTimeStampPollEnd
;
              movlw     S_GSM_ModuleOff
              movff     WREG,GSM_State
;
X_GSM_ReadTimeStampPollEnd
;
              GSM_EndOfState Release
;
;-----------------------
;
X_GSM_ReadTimeStampAnalyse:
;
;-----------------------
;
              movf      PhraseNumber,W,Access
              xorlw     CellResponse_OK
              btfss     ZeroFlag
              goto      X_GSM_ReadTimeStampAnalyse1
;
              movlw     S_GSM_SelectTextMode
              movff     WREG,GSM_State
;
              GSM_EndOfState Dispatch
;
X_GSM_ReadTimeStampAnalyse1:
;
              movf      PhraseNumber,W,Access
              xorlw     CellResponse_ReadTimeStamp
              btfss     ZeroFlag
              goto      X_GSM_ReadTimeStampAnalyse2
;
              movlw     S_GSM_SelectTextMode
              movff     WREG,GSM_State
;
; Format the time from the GSM for the RTC
; 
; Year
;
              call      Parse_IgnoreLeadingWhiteSpace
;
              movlw     "\""
              subwf     INDF2,W,Access
              btfss     ZeroFlag
              goto      X_GSM_ReadTimeStampAnalyse1_End
;
              call      Parse_ReadNextCharacter
              call      IsNumeric
              btfss     CarryFlag
              goto      X_GSM_ReadTimeStampAnalyse1_End
;
              movlw     "0"
              subwf     INDF2,W,Access
              swapf     WREG,W,Access
              movwf     GSM_Year,Banked
;
              call      Parse_ReadNextCharacter
              call      IsNumeric
              btfss     CarryFlag
              goto      X_GSM_ReadTimeStampAnalyse1_End
;
              movlw     "0"
              subwf     INDF2,W,Access
              iorwf     GSM_Year,Banked,Same
;
; Month
;
              call      Parse_ReadNextCharacter
;
              movlw     "/"
              subwf     INDF2,W,Access
              btfss     ZeroFlag
              goto      X_GSM_ReadTimeStampAnalyse1_End
;
              call      Parse_ReadNextCharacter
              call      IsNumeric
              btfss     CarryFlag
              goto      X_GSM_ReadTimeStampAnalyse1_End
;
              movlw     "0"
              subwf     INDF2,W,Access
              swapf     WREG,W,Access
              movwf     GSM_Month,Banked
;
              call      Parse_ReadNextCharacter
              call      IsNumeric
              btfss     CarryFlag
              goto      X_GSM_ReadTimeStampAnalyse1_End
;
              movlw     "0"
              subwf     INDF2,W,Access
              iorwf     GSM_Month,Banked,Same
;
; Date
;
              call      Parse_ReadNextCharacter
;
              movlw     "/"
              subwf     INDF2,W,Access
              btfss     ZeroFlag
              goto      X_GSM_ReadTimeStampAnalyse1_End
;
              call      Parse_ReadNextCharacter
              call      IsNumeric
              btfss     CarryFlag
              goto      X_GSM_ReadTimeStampAnalyse1_End
;
              movlw     "0"
              subwf     INDF2,W,Access
              swapf     WREG,W,Access
              movwf     GSM_Date,Banked
;
              call      Parse_ReadNextCharacter
              call      IsNumeric
              btfss     CarryFlag
              goto      X_GSM_ReadTimeStampAnalyse1_End
;
              movlw     "0"
              subwf     INDF2,W,Access
              iorwf     GSM_Date,Banked,Same
;
; Hours
;
              call      Parse_ReadNextCharacter
;
              movlw     ","
              subwf     INDF2,W,Access
              btfss     ZeroFlag
              goto      X_GSM_ReadTimeStampAnalyse1_End
;
              call      Parse_ReadNextCharacter
              call      IsNumeric
              btfss     CarryFlag
              goto      X_GSM_ReadTimeStampAnalyse1_End
;
              movlw     "0"
              subwf     INDF2,W,Access
              swapf     WREG,W,Access
              movwf     GSM_Hours,Banked
;
              call      Parse_ReadNextCharacter
              call      IsNumeric
              btfss     CarryFlag
              goto      X_GSM_ReadTimeStampAnalyse1_End
;
              movlw     "0"
              subwf     INDF2,W,Access
              iorwf     GSM_Hours,Banked,Same
;
; Minutes
;
              call      Parse_ReadNextCharacter
;
              movlw     ":"
              subwf     INDF2,W,Access
              btfss     ZeroFlag
              goto      X_GSM_ReadTimeStampAnalyse1_End
;
              call      Parse_ReadNextCharacter
              call      IsNumeric
              btfss     CarryFlag
              goto      X_GSM_ReadTimeStampAnalyse1_End
;
              movlw     "0"
              subwf     INDF2,W,Access
              swapf     WREG,W,Access
              movwf     GSM_Minutes,Banked
;
              call      Parse_ReadNextCharacter
              call      IsNumeric
              btfss     CarryFlag
              goto      X_GSM_ReadTimeStampAnalyse1_End
;
              movlw     "0"
              subwf     INDF2,W,Access
              iorwf     GSM_Minutes,Banked,Same
;
; Seconds
;
              call      Parse_ReadNextCharacter
;
              movlw     ":"
              subwf     INDF2,W,Access
              btfss     ZeroFlag
              goto      X_GSM_ReadTimeStampAnalyse1_End
;
              call      Parse_ReadNextCharacter
              call      IsNumeric
              btfss     CarryFlag
              goto      X_GSM_ReadTimeStampAnalyse1_End
;
              movlw     "0"
              subwf     INDF2,W,Access
              swapf     WREG,W,Access
              movwf     GSM_Seconds,Banked
;
              call      Parse_ReadNextCharacter
              call      IsNumeric
              btfss     CarryFlag
              goto      X_GSM_ReadTimeStampAnalyse1_End
;
              movlw     "0"
              subwf     INDF2,W,Access
              iorwf     GSM_Seconds,Banked,Same
;
              call      Parse_ReadNextCharacter
              movwf     GSM_TimeZone_Sign,Banked
;
              call      Parse_ReadNextCharacter
              call      IsNumeric
              btfss     CarryFlag
              goto      X_GSM_ReadTimeStampAnalyse1_End
;
              movlw     "0"
              subwf     INDF2,W,Access
              movwf     GSM_TimeZone_Tens,Banked
;
              call      Parse_ReadNextCharacter
              call      IsNumeric
              btfss     CarryFlag
              goto      X_GSM_ReadTimeStampAnalyse1_End
;
              movlw     "0"
              subwf     INDF2,W,Access
              movwf     GSM_TimeZone_Units,Banked
;
; Now read the RTC
;
              bsf       RTC_PU
;
              call      Delay1msec
;
              call      I2C_RTC_Start                
              movlw     b'11010000'
              call      I2C_RTC_Tx        
              movlw     b'00000000'              ;Start at the seconds 
              call      I2C_RTC_Tx
              call      I2C_RTC_Start
              movlw     b'11010001'
              call      I2C_RTC_Tx
              bsf       AckTx 
              call      I2C_RTC_Rx               ;Seconds
              movwf     RTC_Seconds,Banked
              call      I2C_RTC_Rx               ;Minutes
              movwf     RTC_Minutes,Banked
              call      I2C_RTC_Rx               ;Hours
              movwf     RTC_Hours,Banked
              call      I2C_RTC_Rx               ;DayOfWeek
              movwf     RTC_DayOfWeek,Banked
              call      I2C_RTC_Rx               ;Date
              movwf     RTC_Date,Banked
              call      I2C_RTC_Rx               ;Month
              movwf     RTC_Month,Banked
              call      I2C_RTC_Rx               ;Year
              movwf     RTC_Year,Banked
              bcf       AckTx
              call      I2C_RTC_Rx               ;Control
              bsf       AckTx
              movwf     RTC_Control,Banked
              call      I2C_RTC_Stop
;
              movlw     0x10                     ;Check control is setup correctly
              xorwf     RTC_Control,W,Banked
              btfss     ZeroFlag
              goto      X_GSM_ReadTimeStampAnalyse1_SetClock
;
              movf      GSM_Year,W,Banked
              xorwf     RTC_Year,W,Banked
              btfss     ZeroFlag
              goto      X_GSM_ReadTimeStampAnalyse1_SetClock
;
              movf      GSM_Month,W,Banked
              xorwf     RTC_Month,W,Banked
              btfss     ZeroFlag
              goto      X_GSM_ReadTimeStampAnalyse1_SetClock
;
              movf      GSM_Date,W,Banked
              xorwf     RTC_Date,W,Banked
              btfss     ZeroFlag
              goto      X_GSM_ReadTimeStampAnalyse1_SetClock
;
              movf      GSM_Hours,W,Banked
              xorwf     RTC_Hours,W,Banked
              btfss     ZeroFlag
              goto      X_GSM_ReadTimeStampAnalyse1_SetClock
;
              movf      GSM_Minutes,W,Banked
              subwf     RTC_Minutes,W,Banked
              btfsc     CarryFlag
              goto      X_GSM_ReadTimeStampAnalyse1_A
              movf      RTC_Minutes,W,Banked
              subwf     GSM_Minutes,W,Banked
;
X_GSM_ReadTimeStampAnalyse1_A:
;
              xorlw     0
              btfsc     ZeroFlag
              goto      X_GSM_ReadTimeStampAnalyse1_End
;
              xorlw     1^0
              btfsc     ZeroFlag
              goto      X_GSM_ReadTimeStampAnalyse1_End
;
              xorlw     2^1
              btfsc     ZeroFlag
              goto      X_GSM_ReadTimeStampAnalyse1_End
;
X_GSM_ReadTimeStampAnalyse1_SetClock:
;
              call      I2C_RTC_Start  
              movlw     b'11010000'
              call      I2C_RTC_Tx            
              movlw     b'00000000'              ;Write from the seconds
              call      I2C_RTC_Tx             
              movf      GSM_Seconds,W,Banked     ;Seconds
              call      I2C_RTC_Tx             
              movf      GSM_Minutes,W,Banked     ;Minutes
              call      I2C_RTC_Tx             
              movf      GSM_Hours,W,Banked       ;Hours
              call      I2C_RTC_Tx             
              movf      RTC_DayOfWeek,W,Banked   ;DayOfWeek
              call      I2C_RTC_Tx             
              movf      GSM_Date,W,Banked        ;Date
              call      I2C_RTC_Tx             
              movf      GSM_Month,W,Banked       ;Month
              call      I2C_RTC_Tx             
              movf      GSM_Year,W,Banked        ;Year
              call      I2C_RTC_Tx  
              movlw     0x10                     ;Control
              call      I2C_RTC_Tx  
;           
              call      I2C_RTC_Stop
;
              bsf       DeviceSetClock
;
X_GSM_ReadTimeStampAnalyse1_End:
;
              call      Delay1msec
;  
              bcf       RTC_PU
;
              call      PollCellModuleWithTimeOutInitialise
;
              movlw     S_GSM_ReadTimeStampPoll
              movff     WREG,GSM_State
;
              GSM_EndOfState Dispatch
;
X_GSM_ReadTimeStampAnalyse2:
;
              movlw     S_GSM_SelectTextMode
              movff     WREG,GSM_State
;
X_GSM_ReadTimeStampAnalyseEnd
;
              GSM_EndOfState Release
;
;*************************************************
;
; These STATEs tell the cell module that we want to SMS in text mode
;
;*************************************************
;
;-----------------------
;
X_GSM_SelectTextMode:
;
;-----------------------
;
              call      LoadCellModuleTimeOut_CommandDelay
;
              movlw     S_GSM_SelectTextModeWait
              movff     WREG,GSM_State
;
              GSM_EndOfState Release
;
;-----------------------
;
X_GSM_SelectTextModeWait:
;
;-----------------------
;
              btfss     CellModuleResponseTimeOut
              goto      X_GSM_SelectTextModeWaitEnd
;
              call      FlushSerialReceiveBuffer1
;
              bcf       NoCR
              SendCellMessage Cell_Message_SelectTextMode
;
              call      LoadCellModuleTimeOut_SelectTextMode
;
              call      PollCellModuleWithTimeOutInitialise
;
              movlw     S_GSM_SelectTextModePoll
              movff     WREG,GSM_State
;
X_GSM_SelectTextModeWaitEnd
;
              GSM_EndOfState Release
;
;-----------------------
;
X_GSM_SelectTextModePoll:
;
;-----------------------
;
              bsf       AcceptSpaces
              call      PollCellModuleWithTimeOut
;
              btfss     PollComplete
              goto      X_GSM_SelectTextModePoll1
;
              movlw     S_GSM_SelectTextModeAnalyse
              movff     WREG,GSM_State
;
              GSM_EndOfState Dispatch
;
X_GSM_SelectTextModePoll1
;
              btfss     CellModuleResponseTimeOut
              goto      X_GSM_SelectTextModePollEnd
;
              movlw     S_GSM_ModuleOff 
              movff     WREG,GSM_State
;
X_GSM_SelectTextModePollEnd
;
              GSM_EndOfState Release
;
;-----------------------
;
X_GSM_SelectTextModeAnalyse:
;
;-----------------------
;
              movf      PhraseNumber,W,Access
              xorlw     CellResponse_OK
              btfss     ZeroFlag
              goto      X_GSM_SelectTextModeAnalyse1
;
              clrf      NetworkRegistrationAttempts,Banked
;
              movlw     S_GSM_NetworkRegistration
              movff     WREG,GSM_State
;
              goto      X_GSM_SelectTextModeAnalyseEnd
;
X_GSM_SelectTextModeAnalyse1
;
              movlw     S_GSM_ModuleOff
              movff     WREG,GSM_State
;
X_GSM_SelectTextModeAnalyseEnd
;
              GSM_EndOfState Release
;
;*************************************************
;
; These STATEs check the cell module is registered on the home network
;
;*************************************************
;
;-----------------------
;
X_GSM_NetworkRegistration:
;
;-----------------------
;
              call      LoadCellModuleTimeOut_NetRegLPause ;NA31
              movf      NetworkRegistrationAttempts,W,Banked ;NB01
              btfss     ZeroFlag ;NB01
              call      LoadCellModuleTimeOut_NetRegSPause ;NB01
;
              movlw     S_GSM_NetworkRegistrationWait
              movff     WREG,GSM_State
;
              GSM_EndOfState Release
;
;-----------------------
;
X_GSM_NetworkRegistrationWait:
;
;-----------------------
;
              btfss     CellModuleResponseTimeOut
              goto      X_GSM_NetworkRegistrationWaitEnd
;
              call      FlushSerialReceiveBuffer1
;
              bcf       NoCR
              SendCellMessage Cell_Message_NetworkRegistration
;
              call      LoadCellModuleTimeOut_NetworkRegistration
;
              call      PollCellModuleWithTimeOutInitialise
;
              movlw     S_GSM_NetworkRegistrationPoll
              movff     WREG,GSM_State
;
X_GSM_NetworkRegistrationWaitEnd:
;
              GSM_EndOfState Release
;
;-----------------------
;
X_GSM_NetworkRegistrationPoll:
;
;-----------------------
;
              bsf       AcceptSpaces
              call      PollCellModuleWithTimeOut
;
              btfss     PollComplete
              goto      X_GSM_NetworkRegistrationPoll1
;
              movlw     S_GSM_NetworkRegistrationAnalyse
              movff     WREG,GSM_State
;
              GSM_EndOfState Dispatch
;
X_GSM_NetworkRegistrationPoll1
;
              btfss     CellModuleResponseTimeOut
              goto      X_GSM_NetworkRegistrationPollEnd
;
              movlw     S_GSM_ModuleOff
              movff     WREG,GSM_State
;
X_GSM_NetworkRegistrationPollEnd:
;
              GSM_EndOfState Release
;
;-----------------------
;
X_GSM_NetworkRegistrationAnalyse:
;
;-----------------------
;
              movf      PhraseNumber,W,Access
              xorlw     CellResponse_HomeNetwork
              btfss     ZeroFlag
              goto      X_GSM_NetworkRegistrationA1
;
              movlw     S_GSM_ConnectionType ;S_GSM_ReplySMS
              movff     WREG,GSM_State
;
              goto      X_GSM_NetworkRegistrationAEnd
;
X_GSM_NetworkRegistrationA1:
;
; Danny has been messing around with enabling the roaming on the SIMs, but it doesn't help if this code
; doesn't allow the unit to work on a roaming connection, so ass it in here
;
              movf      PhraseNumber,W,Access
              xorlw     CellResponse_RoamingNetwork 
              btfss     ZeroFlag
              goto      X_GSM_NetworkRegistrationA2
;
              movlw     S_GSM_ConnectionType ;S_GSM_ReplySMS
              movff     WREG,GSM_State
;
              goto      X_GSM_NetworkRegistrationAEnd
;
X_GSM_NetworkRegistrationA2:
;
              movlw     S_GSM_NetworkRegistration ;Assume we want to check the network registration again
              movff     WREG,GSM_State
;
              incf      NetworkRegistrationAttempts,Same,Banked ;We have had another attempt
;
              movf      NetworkRegistrationAttempts,W,Banked ;Check if there are more attempts left
              xorlw     13
              btfss     ZeroFlag
              goto      X_GSM_NetworkRegistrationAEnd ;Yes, so go try again
;
              movlw     S_GSM_ModuleOff ;No, so shut down module and try again
              movff     WREG,GSM_State
;
X_GSM_NetworkRegistrationAEnd:
;
              GSM_EndOfState Release
;
;*************************************************
;
; These STATEs check the cell module is registered on the GPRS network
;
;*************************************************
;
;-----------------------
;
X_GSM_GPRSattachment:
;
;-----------------------
;
              call      LoadCellModuleTimeOut_CommandDelay
;
              movlw     S_GSM_GPRSattachmentWait
              movff     WREG,GSM_State
;
              GSM_EndOfState Release
;
;-----------------------
;
X_GSM_GPRSattachmentWait:
;
;-----------------------
;
              btfss     CellModuleResponseTimeOut
              goto      X_GSM_GPRSattachmentWaitEnd
;
              call      FlushSerialReceiveBuffer1
;
              bcf       NoCR
              SendCellMessage Cell_Message_GPRSattachment
;
              call      LoadCellModuleTimeOut_GPRSattachment
;
              call      PollCellModuleWithTimeOutInitialise
;
              movlw     S_GSM_GPRSattachmentPoll
              movff     WREG,GSM_State
;
X_GSM_GPRSattachmentWaitEnd:
;
              GSM_EndOfState Release
;
;-----------------------
;
X_GSM_GPRSattachmentPoll:
;
;-----------------------
;
              bsf       AcceptSpaces
              call      PollCellModuleWithTimeOut
;
              btfss     PollComplete
              goto      X_GSM_GPRSattachmentPoll1
;
              movlw     S_GSM_GPRSattachmentAnalyse
              movff     WREG,GSM_State
;
              GSM_EndOfState Dispatch
;
X_GSM_GPRSattachmentPoll1
;
              btfss     CellModuleResponseTimeOut
              goto      X_GSM_GPRSattachmentPollEnd
;
              movlw     S_GSM_ModuleOff
              movff     WREG,GSM_State
;
X_GSM_GPRSattachmentPollEnd:
;
              GSM_EndOfState Release
;
;-----------------------
;
X_GSM_GPRSattachmentAnalyse:
;
;-----------------------
;
              movf      PhraseNumber,W,Access
              xorlw     CellResponse_GPRSattachment
              btfss     ZeroFlag
              goto      X_GSM_NetworkRegistrationA1
;
              call      PollCellModuleWithTimeOutInitialise
;
              movlw     S_GSM_GPRSattachmentPoll
              movff     WREG,GSM_State
;
              goto      X_GSM_GPRSattachmentAEnd
;
X_GSM_GPRSattachmentA1:
;
              xorlw     CellResponse_OK^CellResponse_GPRSattachment
              btfss     ZeroFlag
              goto      X_GSM_GPRSattachmentA2
;
              movlw     S_GSM_ConnectionType
              movff     WREG,GSM_State
;
              goto      X_GSM_GPRSattachmentAEnd
;
X_GSM_GPRSattachmentA2:
;
              movlw     S_GSM_ModuleOff
              movff     WREG,GSM_State
;
              goto      X_GSM_GPRSattachmentAEnd
;
X_GSM_GPRSattachmentAEnd:
;
              GSM_EndOfState Release
;
;*************************************************
;
; These STATEs set the connection type to GPRS
;
;*************************************************
;
;-----------------------
;
X_GSM_ConnectionType:
;
;-----------------------
;
              call      LoadCellModuleTimeOut_CommandDelay
;
              movlw     S_GSM_ConnectionTypeWait
              movff     WREG,GSM_State
;
              GSM_EndOfState Release
;
;-----------------------
;
X_GSM_ConnectionTypeWait:
;
;-----------------------
;
              btfss     CellModuleResponseTimeOut
              goto      X_GSM_ConnectionTypeWaitEnd
;
              call      FlushSerialReceiveBuffer1
;
              bcf       NoCR
              SendCellMessage Cell_Message_ConnectionType
;
              call      LoadCellModuleTimeOut_ConnectionType
;
              call      PollCellModuleWithTimeOutInitialise
;
              movlw     S_GSM_ConnectionTypePoll
              movff     WREG,GSM_State
;
X_GSM_ConnectionTypeWaitEnd:
;
              GSM_EndOfState Release
;
;-----------------------
;
X_GSM_ConnectionTypePoll:
;
;-----------------------
;
              bsf       AcceptSpaces
              call      PollCellModuleWithTimeOut
;
              btfss     PollComplete
              goto      X_GSM_ConnectionTypePoll1
;
              movlw     S_GSM_ConnectionTypeAnalyse
              movff     WREG,GSM_State
;
              GSM_EndOfState Dispatch
;
X_GSM_ConnectionTypePoll1
;
              btfss     CellModuleResponseTimeOut
              goto      X_GSM_ConnectionTypePollEnd
;
              movlw     S_GSM_ModuleOff
              movff     WREG,GSM_State
;
X_GSM_ConnectionTypePollEnd:
;
              GSM_EndOfState Release
;
;-----------------------
;
X_GSM_ConnectionTypeAnalyse:
;
;-----------------------
;
              movf      PhraseNumber,W,Access
              xorlw     CellResponse_OK
              btfss     ZeroFlag
              goto      X_GSM_ConnectionTypeA1
;
              movlw     S_GSM_SetAPN
              movff     WREG,GSM_State
;
              goto      X_GSM_GPRSattachmentAEnd
;
X_GSM_ConnectionTypeA1:
;
              movlw     S_GSM_ModuleOff
              movff     WREG,GSM_State
;
              goto      X_GSM_ConnectionTypeAEnd
;
X_GSM_ConnectionTypeAEnd:
;
              GSM_EndOfState Release
;
;*************************************************
;
; These STATEs set the APN
;
;*************************************************
;
;-----------------------
;
X_GSM_SetAPN:
;
;-----------------------
;
              call      LoadCellModuleTimeOut_ModuleOff ;CommandDelay
;
              movlw     S_GSM_SetAPNWait
              movff     WREG,GSM_State
;
              GSM_EndOfState Release
;
;-----------------------
;
X_GSM_SetAPNWait:
;
;-----------------------
;
              btfss     CellModuleResponseTimeOut
              goto      X_GSM_SetAPNWaitEnd
;
              call      FlushSerialReceiveBuffer1
;
              bcf       NoCR
              SendCellMessage Cell_Message_SetAPN
;
              call      LoadCellModuleTimeOut_SetAPN
;
              call      PollCellModuleWithTimeOutInitialise
;
              movlw     S_GSM_SetAPNPoll
              movff     WREG,GSM_State
;
X_GSM_SetAPNWaitEnd:
;
              GSM_EndOfState Release
;
;-----------------------
;
X_GSM_SetAPNPoll:
;
;-----------------------
;
              bsf       AcceptSpaces
              call      PollCellModuleWithTimeOut
;
              btfss     PollComplete
              goto      X_GSM_SetAPNPoll1
;
              movlw     S_GSM_SetAPNAnalyse
              movff     WREG,GSM_State
;
              GSM_EndOfState Dispatch
;
X_GSM_SetAPNPoll1
;
              btfss     CellModuleResponseTimeOut
              goto      X_GSM_SetAPNPollEnd
;
              movlw     S_GSM_ModuleOff
              movff     WREG,GSM_State
;
X_GSM_SetAPNPollEnd:
;
              GSM_EndOfState Release
;
;-----------------------
;
X_GSM_SetAPNAnalyse:
;
;-----------------------
;
              movf      PhraseNumber,W,Access
              xorlw     CellResponse_OK
              btfss     ZeroFlag
              goto      X_GSM_SetAPNA1
;
              movlw     S_GSM_OpenBearer
              movff     WREG,GSM_State
;
              goto      X_GSM_SetAPNAEnd
;
X_GSM_SetAPNA1:
;
              movlw     S_GSM_ModuleOff
              movff     WREG,GSM_State
;
              goto      X_GSM_SetAPNAEnd
;
X_GSM_SetAPNAEnd:
;
              GSM_EndOfState Release
;
;*************************************************
;
; These STATEs open the bearer
;
;*************************************************
;
;-----------------------
;
X_GSM_OpenBearer:
;
;-----------------------
;
              call      LoadCellModuleTimeOut_ModuleOff ;CommandDelay
;
              movlw     S_GSM_OpenBearerWait
              movff     WREG,GSM_State
;
              GSM_EndOfState Release
;
;-----------------------
;
X_GSM_OpenBearerWait:
;
;-----------------------
;
              btfss     CellModuleResponseTimeOut
              goto      X_GSM_OpenBearerWaitEnd
;
              call      FlushSerialReceiveBuffer1
;
              bcf       NoCR
              SendCellMessage Cell_Message_OpenBearer
;
              call      LoadCellModuleTimeOut_OpenBearer
;
              call      PollCellModuleWithTimeOutInitialise
;
              movlw     S_GSM_OpenBearerPoll
              movff     WREG,GSM_State
;
X_GSM_OpenBearerWaitEnd:
;
              GSM_EndOfState Release
;
;-----------------------
;
X_GSM_OpenBearerPoll:
;
;-----------------------
;
              bsf       AcceptSpaces
              call      PollCellModuleWithTimeOut
;
              btfss     PollComplete
              goto      X_GSM_OpenBearerPoll1
;
              movlw     S_GSM_OpenBearerAnalyse
              movff     WREG,GSM_State
;
              GSM_EndOfState Dispatch
;
X_GSM_OpenBearerPoll1
;
              btfss     CellModuleResponseTimeOut
              goto      X_GSM_OpenBearerPollEnd
;
              movlw     S_GSM_ModuleOff
              movff     WREG,GSM_State
;
X_GSM_OpenBearerPollEnd:
;
              GSM_EndOfState Release
;
;-----------------------
;
X_GSM_OpenBearerAnalyse:
;
;-----------------------
;
              movf      PhraseNumber,W,Access
              xorlw     CellResponse_OK
              btfss     ZeroFlag
              goto      X_GSM_OpenBearerA1
;
              movlw     S_GSM_QueryBearer
              movff     WREG,GSM_State
;
              goto      X_GSM_OpenBearerAEnd
;
X_GSM_OpenBearerA1:
;
              movlw     S_GSM_ModuleOff
              movff     WREG,GSM_State
;
              goto      X_GSM_OpenBearerAEnd
;
X_GSM_OpenBearerAEnd:
;
              GSM_EndOfState Release
;
;*************************************************
;
; These STATEs query the bearer - I don't really want the IP, but I do want to know we have a connection to the internet
;
;*************************************************
;
;-----------------------
;
X_GSM_QueryBearer:
;
;-----------------------
;
              call      LoadCellModuleTimeOut_ModuleOff ;CommandDelay
;
              movlw     S_GSM_QueryBearerWait
              movff     WREG,GSM_State
;
              GSM_EndOfState Release
;
;-----------------------
;
X_GSM_QueryBearerWait:
;
;-----------------------
;
              btfss     CellModuleResponseTimeOut
              goto      X_GSM_QueryBearerWaitEnd
;
              call      FlushSerialReceiveBuffer1
;
              bcf       NoCR
              SendCellMessage Cell_Message_QueryBearer
;
              call      LoadCellModuleTimeOut_QueryBearer
;
              call      PollCellModuleWithTimeOutInitialise
;
              movlw     S_GSM_QueryBearerPoll
              movff     WREG,GSM_State
;
X_GSM_QueryBearerWaitEnd:
;
              GSM_EndOfState Release
;
;-----------------------
;
X_GSM_QueryBearerPoll:
;
;-----------------------
;
              bcf       AcceptSpaces
              call      PollCellModuleWithTimeOut
;
              btfss     PollComplete
              goto      X_GSM_QueryBearerPoll1
;
              movlw     S_GSM_QueryBearerAnalyse
              movff     WREG,GSM_State
;
              GSM_EndOfState Dispatch
;
X_GSM_QueryBearerPoll1
;
              btfss     CellModuleResponseTimeOut
              goto      X_GSM_QueryBearerPollEnd
;
              movlw     S_GSM_ModuleOff
              movff     WREG,GSM_State
;
X_GSM_QueryBearerPollEnd:
;
              GSM_EndOfState Release
;
;-----------------------
;
X_GSM_QueryBearerAnalyse:
;
;-----------------------
;
              movf      PhraseNumber,W,Access
              xorlw     CellResponse_QueryBearer
              btfss     ZeroFlag
              goto      X_GSM_QueryBearerA1
;
              call      PollCellModuleWithTimeOutInitialise
;
              movlw     S_GSM_QueryBearerPoll
              movff     WREG,GSM_State
;
              goto      X_GSM_GPRSattachmentAEnd
;
X_GSM_QueryBearerA1:
;
              xorlw     CellResponse_OK^CellResponse_QueryBearer
              btfss     ZeroFlag
              goto      X_GSM_QueryBearerA2
;
              movlw     S_GSM_HTTPinit
              movff     WREG,GSM_State
;
              goto      X_GSM_QueryBearerAEnd
;
X_GSM_QueryBearerA2:
;
              movlw     S_GSM_ModuleOff
              movff     WREG,GSM_State
;
              goto      X_GSM_QueryBearerAEnd
;
X_GSM_QueryBearerAEnd:
;
              GSM_EndOfState Release
;
;*************************************************
;
; These STATEs initialise the HTTP 
;
;*************************************************
;
;-----------------------
;
X_GSM_HTTPinit:
;
;-----------------------
;
              call      LoadCellModuleTimeOut_ModuleOff ;CommandDelay
;
              movlw     S_GSM_HTTPinitWait
              movff     WREG,GSM_State
;
              GSM_EndOfState Release
;
;-----------------------
;
X_GSM_HTTPinitWait:
;
;-----------------------
;
              btfss     CellModuleResponseTimeOut
              goto      X_GSM_HTTPinitWaitEnd
;
              call      FlushSerialReceiveBuffer1
;
              bcf       NoCR
              SendCellMessage Cell_Message_HTTPinit
;
              call      LoadCellModuleTimeOut_HTTPinit
;
              call      PollCellModuleWithTimeOutInitialise
;
              movlw     S_GSM_HTTPinitPoll
              movff     WREG,GSM_State
;
X_GSM_HTTPinitWaitEnd:
;
              GSM_EndOfState Release
;
;-----------------------
;
X_GSM_HTTPinitPoll:
;
;-----------------------
;
              bsf       AcceptSpaces
              call      PollCellModuleWithTimeOut
;
              btfss     PollComplete
              goto      X_GSM_HTTPinitPoll1
;
              movlw     S_GSM_HTTPinitAnalyse
              movff     WREG,GSM_State
;
              GSM_EndOfState Dispatch
;
X_GSM_HTTPinitPoll1
;
              btfss     CellModuleResponseTimeOut
              goto      X_GSM_HTTPinitPollEnd
;
              movlw     S_GSM_ModuleOff
              movff     WREG,GSM_State
;
X_GSM_HTTPinitPollEnd:
;
              GSM_EndOfState Release
;
;-----------------------
;
X_GSM_HTTPinitAnalyse:
;
;-----------------------
;
              movf      PhraseNumber,W,Access
              xorlw     CellResponse_OK
              btfss     ZeroFlag
              goto      X_GSM_HTTPinitA1
;
              movlw     S_GSM_BearerID
              movff     WREG,GSM_State
;
              goto      X_GSM_HTTPinitAEnd
;
X_GSM_HTTPinitA1:
;
              movlw     S_GSM_ModuleOff
              movff     WREG,GSM_State
;
              goto      X_GSM_HTTPinitAEnd
;
X_GSM_HTTPinitAEnd:
;
              GSM_EndOfState Release
;
;*************************************************
;
; These STATEs set the bearer ID
;
;*************************************************
;
;-----------------------
;
X_GSM_BearerID:
;
;-----------------------
;
              call      LoadCellModuleTimeOut_ModuleOff ;CommandDelay
;
              movlw     S_GSM_BearerIDWait
              movff     WREG,GSM_State
;
              GSM_EndOfState Release
;
;-----------------------
;
X_GSM_BearerIDWait:
;
;-----------------------
;
              btfss     CellModuleResponseTimeOut
              goto      X_GSM_BearerIDWaitEnd
;
              call      FlushSerialReceiveBuffer1
;
              bcf       NoCR
              SendCellMessage Cell_Message_BearerID
;
              call      LoadCellModuleTimeOut_BearerID
;
              call      PollCellModuleWithTimeOutInitialise
;
              movlw     S_GSM_BearerIDPoll
              movff     WREG,GSM_State
;
X_GSM_BearerIDWaitEnd:
;
              GSM_EndOfState Release
;
;-----------------------
;
X_GSM_BearerIDPoll:
;
;-----------------------
;
              bsf       AcceptSpaces
              call      PollCellModuleWithTimeOut
;
              btfss     PollComplete
              goto      X_GSM_BearerIDPoll1
;
              movlw     S_GSM_BearerIDAnalyse
              movff     WREG,GSM_State
;
              GSM_EndOfState Dispatch
;
X_GSM_BearerIDPoll1
;
              btfss     CellModuleResponseTimeOut
              goto      X_GSM_BearerIDPollEnd
;
              movlw     S_GSM_ModuleOff
              movff     WREG,GSM_State
;
X_GSM_BearerIDPollEnd:
;
              GSM_EndOfState Release
;
;-----------------------
;
X_GSM_BearerIDAnalyse:
;
;-----------------------
;
              movf      PhraseNumber,W,Access
              xorlw     CellResponse_OK
              btfss     ZeroFlag
              goto      X_GSM_BearerIDA1
;
              movlw     S_GSM_SetURL
              movff     WREG,GSM_State
;
              goto      X_GSM_BearerIDAEnd
;
X_GSM_BearerIDA1:
;
              movlw     S_GSM_ModuleOff
              movff     WREG,GSM_State
;
              goto      X_GSM_BearerIDAEnd
;
X_GSM_BearerIDAEnd:
;
              GSM_EndOfState Release
;
;*************************************************
;
; These STATEs set the URL
;
;*************************************************
;
;-----------------------
;
X_GSM_SetURL:
;
;-----------------------
;
              call      LoadCellModuleTimeOut_ModuleOff ;CommandDelay
;
              movlw     S_GSM_SetURLWait
              movff     WREG,GSM_State
;
              GSM_EndOfState Release
;
;-----------------------
;
X_GSM_SetURLWait:
;
;-----------------------
;
              btfss     CellModuleResponseTimeOut
              goto      X_GSM_SetURLWaitEnd
;
              call      FlushSerialReceiveBuffer1
;
              bcf       NoCR
              SendCellMessage Cell_Message_SetURL
;
              call      LoadCellModuleTimeOut_SetURL
;
              call      PollCellModuleWithTimeOutInitialise
;
              movlw     S_GSM_SetURLPoll
              movff     WREG,GSM_State
;
X_GSM_SetURLWaitEnd:
;
              GSM_EndOfState Release
;
;-----------------------
;
X_GSM_SetURLPoll:
;
;-----------------------
;
              bsf       AcceptSpaces
              call      PollCellModuleWithTimeOut
;
              btfss     PollComplete
              goto      X_GSM_SetURLPoll1
;
              movlw     S_GSM_SetURLAnalyse
              movff     WREG,GSM_State
;
              GSM_EndOfState Dispatch
;
X_GSM_SetURLPoll1
;
              btfss     CellModuleResponseTimeOut
              goto      X_GSM_SetURLPollEnd
;
              movlw     S_GSM_ModuleOff
              movff     WREG,GSM_State
;
X_GSM_SetURLPollEnd:
;
              GSM_EndOfState Release
;
;-----------------------
;
X_GSM_SetURLAnalyse:
;
;-----------------------
;
              movf      PhraseNumber,W,Access
              xorlw     CellResponse_OK
              btfss     ZeroFlag
              goto      X_GSM_SetURLA1
;
              movlw     S_GSM_ContentType
              movff     WREG,GSM_State
;
              goto      X_GSM_SetAPNAEnd
;
X_GSM_SetURLA1:
;
              movlw     S_GSM_ModuleOff
              movff     WREG,GSM_State
;
              goto      X_GSM_SetURLAEnd
;
X_GSM_SetURLAEnd:
;
              GSM_EndOfState Release
;
;*************************************************
;
; These STATEs specify the content type
;
;*************************************************
;
;-----------------------
;
X_GSM_ContentType:
;
;-----------------------
;
              call      LoadCellModuleTimeOut_ModuleOff ;CommandDelay
;
              movlw     S_GSM_ContentTypeWait
              movff     WREG,GSM_State
;
              GSM_EndOfState Release
;
;-----------------------
;
X_GSM_ContentTypeWait:
;
;-----------------------
;
              btfss     CellModuleResponseTimeOut
              goto      X_GSM_ContentTypeWaitEnd
;
              call      FlushSerialReceiveBuffer1
;
              bcf       NoCR
              SendCellMessage Cell_Message_ContentType
;
              call      LoadCellModuleTimeOut_ContentType
;
              call      PollCellModuleWithTimeOutInitialise
;
              movlw     S_GSM_ContentTypePoll
              movff     WREG,GSM_State
;
X_GSM_ContentTypeWaitEnd:
;
              GSM_EndOfState Release
;
;-----------------------
;
X_GSM_ContentTypePoll:
;
;-----------------------
;
              bsf       AcceptSpaces
              call      PollCellModuleWithTimeOut
;
              btfss     PollComplete
              goto      X_GSM_ContentTypePoll1
;
              movlw     S_GSM_ContentTypeAnalyse
              movff     WREG,GSM_State
;
              GSM_EndOfState Dispatch
;
X_GSM_ContentTypePoll1
;
              btfss     CellModuleResponseTimeOut
              goto      X_GSM_ContentTypePollEnd
;
              movlw     S_GSM_ModuleOff
              movff     WREG,GSM_State
;
X_GSM_ContentTypePollEnd:
;
              GSM_EndOfState Release
;
;-----------------------
;
X_GSM_ContentTypeAnalyse:
;
;-----------------------
;
              movf      PhraseNumber,W,Access
              xorlw     CellResponse_OK
              btfss     ZeroFlag
              goto      X_GSM_ContentTypeA1
;
              movlw     S_GSM_DataSize
              movff     WREG,GSM_State
;
              goto      X_GSM_ContentTypeAEnd
;
X_GSM_ContentTypeA1:
;
              movlw     S_GSM_ModuleOff
              movff     WREG,GSM_State
;
              goto      X_GSM_ContentTypeAEnd
;
X_GSM_ContentTypeAEnd:
;
              GSM_EndOfState Release
;
;*************************************************
;
; These STATEs specify the data size
;
;*************************************************
; Start Command Length D1 D2 D3 D4 D5 D6 D7 !CS End
; 3A    81      07     43 38 47 32 00 00 08 41  0D
;
; CS = 3A + 81 + 7 + 43 + 38 + 47 + 32+ 00 + 00 + 08 = 1BE
; !CS = 41
;
; The length of this for the GSM module is 24
;
; but it must be concatenated with name=rd&data= which adds another 13 characters, so the length for the GSM module is 37
;
; I get back 4 bytes: 1000 which means all good
;
; So finally I have (([LogWritePointer-GSMReadPointer;max251])*2)+10+13
;
;-----------------------
;
X_GSM_DataSize:
;
;-----------------------
;
              call      LoadCellModuleTimeOut_ModuleOff ;CommandDelay
;
              movlw     S_GSM_DataSizeWait
              movff     WREG,GSM_State
;
              GSM_EndOfState Release
;
;-----------------------
;
X_GSM_DataSizeWait:
;
;-----------------------
;
              btfss     CellModuleResponseTimeOut
              goto      X_GSM_DataSizeWaitEnd
;
              call      FlushSerialReceiveBuffer1
;
              movf      GSMReadPointer,W,Banked
              subwf     LogWritePointer,W,Banked
              movwf     CalculatorX0,Access
              movf      GSMReadPointerH,W,Banked
              subwfb    LogWritePointerH,W,Banked
              movwf     CalculatorX1,Access
              movf      GSMReadPointerHH,W,Banked
              subwfb    LogWritePointerHH,W,Banked
              movwf     CalculatorX2,Access
;
              btfsc     CarryFlag
              goto      X_GSM_DataSizeWait_1
;
; The write pointer is behind the read pointer
; - So let's just read up to the boundary this time
;              
              movlw     LOW(0x60000)
              movwf     CalculatorX0,Access
              movlw     HIGH(0x60000)
              movwf     CalculatorX1,Access
              movlw     UPPER(0x60000)
              movwf     CalculatorX2,Access
;
              movf      GSMReadPointer,W,Banked
              subwf     CalculatorX0,Same,Access
              movf      GSMReadPointerH,W,Banked
              subwfb    CalculatorX1,Same,Access
              movf      GSMReadPointerHH,W,Banked
              subwfb    CalculatorX2,Same,Access
;
X_GSM_DataSizeWait_1:
;
              movlw     251+1                    ;251 is the maximum number of bytes that Jacques protocol on the srever allows
              subwf     CalculatorX0,W,Access
              movlw     0
              subwfb    CalculatorX1,W,Access
              movlw     0
              subwfb    CalculatorX2,W,Access
;
              movlw     251
              btfsc     CarryFlag
              movwf     CalculatorX0,Access
;
              movf      CalculatorX0,W,Access
              movwf     LogDataLength,Banked
;
              movlw     4
              addwf     CalculatorX0,Same,Access
;
              movf      CalculatorX0,W,Access
              movwf     ServerDataLength,Banked
;
              movlw     0x3A+0x81
              movwf     ServerChecksum,Banked
;
              clrf      CalculatorX1,Access
;
              bcf       CarryFlag
;
              rlcf      CalculatorX0,Same,Access
              rlcf      CalculatorX1,Same,Access
;
              movlw     10+13
              addwf     CalculatorX0,Same,Access
              movlw     0
              addwfc    CalculatorX1,Same,Access
;
              movff     CalculatorX0,Binary
              movff     CalculatorX1,BinaryH
              call      BinaryToBCD
;
              bsf       NoCR
              SendCellMessage Cell_Message_DataSizeHead
;
              movlw     '0'
              addwf     TenThousands,W,Access
              call      WriteByteSerialBuffer1
;
              movlw     '0'
              addwf     Thousands,W,Access
              call      WriteByteSerialBuffer1
;
              movlw     '0'
              addwf     Hundreds,W,Access
              call      WriteByteSerialBuffer1
;
              movlw     '0'
              addwf     Tens,W,Access
              call      WriteByteSerialBuffer1
;
              movlw     '0'
              addwf     Units,W,Access
              call      WriteByteSerialBuffer1
;
              bcf       NoCR
              SendCellMessage Cell_Message_DataSizeTail
;
              call      LoadCellModuleTimeOut_DataSize
;
              call      PollCellModuleWithTimeOutInitialise
;
              movlw     S_GSM_DataSizePoll
              movff     WREG,GSM_State
;
X_GSM_DataSizeWaitEnd:
;
              GSM_EndOfState Release
;
;-----------------------
;
X_GSM_DataSizePoll:
;
;-----------------------
;
              bsf       AcceptSpaces
              call      PollCellModuleWithTimeOut
;
              btfss     PollComplete
              goto      X_GSM_DataSizePoll1
;
              movlw     S_GSM_DataSizeAnalyse
              movff     WREG,GSM_State
;
              GSM_EndOfState Dispatch
;
X_GSM_DataSizePoll1
;
              btfss     CellModuleResponseTimeOut
              goto      X_GSM_DataSizePollEnd
;
              movlw     S_GSM_ModuleOff
              movff     WREG,GSM_State
;
X_GSM_DataSizePollEnd:
;
              GSM_EndOfState Release
;
;-----------------------
;
X_GSM_DataSizeAnalyse:
;
;-----------------------
;
              movf      PhraseNumber,W,Access
              xorlw     CellResponse_DataSize
              btfss     ZeroFlag
              goto      X_GSM_DataSizeAnalyse1
;
              movlw     S_GSM_SendData
              movff     WREG,GSM_State
;
              goto      X_GSM_DataSizeAnalyseEnd
;
X_GSM_DataSizeAnalyse1:
;
              movlw     S_GSM_ModuleOff
              movff     WREG,GSM_State
;
              goto      X_GSM_DataSizeAnalyseEnd
;
X_GSM_DataSizeAnalyseEnd:
;
              GSM_EndOfState Release
;
;*************************************************
;
; These STATEs specify the send the data to the GSM module
;
;*************************************************
;
;-----------------------
;
X_GSM_SendData:
;
;-----------------------
;
              call      LoadCellModuleTimeOut_ModuleOff ;CommandDelay
;
              movlw     S_GSM_SendDataWait
              movff     WREG,GSM_State
;
              GSM_EndOfState Release
;
;-----------------------
;
X_GSM_SendDataWait:
;
;-----------------------
;
              btfss     CellModuleResponseTimeOut
              goto      X_GSM_SendDataWaitEnd
;
              call      FlushSerialReceiveBuffer1
;
              bsf       NoCR
              SendCellMessage Cell_Message_DataHead
;
              movf      ServerDataLength,W,Banked
              addwf     ServerChecksum,Same,Banked
              call      GSM_NibblesToASCII
;
              movlw     EE_DeviceIDHHH
              call      ReadInternalEEPROM
              addwf     ServerChecksum,Same,Banked
              call      GSM_NibblesToASCII
              movlw     EE_DeviceIDHH
              call      ReadInternalEEPROM
              addwf     ServerChecksum,Same,Banked
              call      GSM_NibblesToASCII
              movlw     EE_DeviceIDH
              call      ReadInternalEEPROM
              addwf     ServerChecksum,Same,Banked
              call      GSM_NibblesToASCII
              movlw     EE_DeviceID
              call      ReadInternalEEPROM
              addwf     ServerChecksum,Same,Banked
              call      GSM_NibblesToASCII
;
              movlw     4
              subwf     ServerDataLength,Same,Banked
;
              btfsc     ZeroFlag
              goto      X_GSM_SendDataWait_Finalise
;
              movff     GSMReadPointer,EEAdrs
              movff     GSMReadPointerH,EEAdrsH
              movff     GSMReadPointerHH,EEAdrsHH
;
              bsf       Power
;
              call      Delay1msec
;
              call      I2C_Start
              rlcf      EEAdrsHH,W,Access
              andlw     b'00001110'
              iorlw     b'10100000'
              call      I2C_Tx        
              movf      EEAdrsH,W,Access
              call      I2C_Tx
              movf      EEAdrs,W,Access
              call      I2C_Tx
              call      OpenExternalEEPROMforReading
;
X_GSM_SendDataWait_ShipData:
;
              call      ReadExternalEEPROM
              addwf     ServerChecksum,Same,Banked
              call      GSM_NibblesToASCII
;
              decfsz    ServerDataLength,Same,Banked 
              goto      X_GSM_SendDataWait_ShipData
;
              call      CloseExternalEEPROMforReading
;
X_GSM_SendDataWait_Finalise:
;
              comf      ServerChecksum,W,Banked
              call      GSM_NibblesToASCII
;
              bcf       NoCR
              SendCellMessage Cell_Message_DataTail
;
              call      LoadCellModuleTimeOut_SendData
;
              call      PollCellModuleWithTimeOutInitialise
;
              movlw     S_GSM_SendDataPoll
              movff     WREG,GSM_State
;
X_GSM_SendDataWaitEnd:
;
              GSM_EndOfState Release
;
;-----------------------
;
X_GSM_SendDataPoll:
;
;-----------------------
;
              bsf       AcceptSpaces
              call      PollCellModuleWithTimeOut
;
              btfss     PollComplete
              goto      X_GSM_SendDataPoll1
;
              movlw     S_GSM_SendDataAnalyse
              movff     WREG,GSM_State
;
              GSM_EndOfState Dispatch
;
X_GSM_SendDataPoll1
;
              btfss     CellModuleResponseTimeOut
              goto      X_GSM_SendDataPollEnd
;
              movlw     S_GSM_ModuleOff
              movff     WREG,GSM_State
;
X_GSM_SendDataPollEnd:
;
              GSM_EndOfState Release
;
;-----------------------
;
X_GSM_SendDataAnalyse:
;
;-----------------------
;
              bcf       Power
;
              movf      PhraseNumber,W,Access
              xorlw     CellResponse_OK
              btfss     ZeroFlag
              goto      X_GSM_SendDataAnalyse1
;
              movlw     S_GSM_HTTPaction
              movff     WREG,GSM_State
;
              goto      X_GSM_DataSizeAnalyseEnd
;
X_GSM_SendDataAnalyse1:
;
              movlw     S_GSM_ModuleOff
              movff     WREG,GSM_State
;
              goto      X_GSM_SendDataAnalyseEnd
;
X_GSM_SendDataAnalyseEnd:
;
              GSM_EndOfState Release
;
;*************************************************
;
; These STATEs POST the data to the server
;
;*************************************************
;
;-----------------------
;
X_GSM_HTTPaction:
;
;-----------------------
;
              call      LoadCellModuleTimeOut_ModuleOff ;CommandDelay
;
              movlw     S_GSM_HTTPactionWait
              movff     WREG,GSM_State
;
              GSM_EndOfState Release
;
;-----------------------
;
X_GSM_HTTPactionWait:
;
;-----------------------
;
              btfss     CellModuleResponseTimeOut
              goto      X_GSM_HTTPactionWaitEnd
;
              call      FlushSerialReceiveBuffer1
;
              bcf       NoCR
              SendCellMessage Cell_Message_HTTPaction
;
              call      LoadCellModuleTimeOut_HTTPaction
;
              call      PollCellModuleWithTimeOutInitialise
;
              movlw     S_GSM_HTTPactionPoll
              movff     WREG,GSM_State
;
X_GSM_HTTPactionWaitEnd:
;
              GSM_EndOfState Release
;
;-----------------------
;
X_GSM_HTTPactionPoll:
;
;-----------------------
;
              bcf       AcceptSpaces
              call      PollCellModuleWithTimeOut
;
              btfss     PollComplete
              goto      X_GSM_HTTPactionPoll1
;
              movlw     S_GSM_HTTPactionAnalyse
              movff     WREG,GSM_State
;
              GSM_EndOfState Dispatch
;
X_GSM_HTTPactionPoll1
;
              btfss     CellModuleResponseTimeOut
              goto      X_GSM_HTTPactionPollEnd
;
              movlw     S_GSM_ModuleOff
              movff     WREG,GSM_State
;
X_GSM_HTTPactionPollEnd:
;
              GSM_EndOfState Release
;
;-----------------------
;
X_GSM_HTTPactionAnalyse:
;
;-----------------------
;
              movf      PhraseNumber,W,Access
              xorlw     CellResponse_HTTPaction
              btfss     ZeroFlag
              goto      X_GSM_HTTPactionAnalyse1
;
              movlw     S_GSM_HTTPread
              movff     WREG,GSM_State
;
              goto      X_GSM_HTTPactionAnalyseEnd
;
X_GSM_HTTPactionAnalyse1:
;
              movf      PhraseNumber,W,Access
              xorlw     CellResponse_OK
              btfss     ZeroFlag
              goto      X_GSM_HTTPactionAnalyse2
;
              call      LoadCellModuleTimeOut_HTTPaction
;
              call      PollCellModuleWithTimeOutInitialise
;
              movlw     S_GSM_HTTPactionPoll
              movff     WREG,GSM_State
;
              goto      X_GSM_HTTPactionAnalyseEnd
;
X_GSM_HTTPactionAnalyse2:
;
              movlw     S_GSM_ModuleOff
              movff     WREG,GSM_State
;
              goto      X_GSM_HTTPactionAnalyseEnd
;
X_GSM_HTTPactionAnalyseEnd:
;
              GSM_EndOfState Release
;
;*************************************************
;
; These STATEs READ the response from the server
;
;*************************************************
;
;-----------------------
;
X_GSM_HTTPread:
;
;-----------------------
;
              call      LoadCellModuleTimeOut_CommandDelay
;
              movlw     S_GSM_HTTPreadWait
              movff     WREG,GSM_State
;
              GSM_EndOfState Release
;
;-----------------------
;
X_GSM_HTTPreadWait:
;
;-----------------------
;
              btfss     CellModuleResponseTimeOut
              goto      X_GSM_HTTPreadWaitEnd
;
              call      FlushSerialReceiveBuffer1
;
              bcf       NoCR
              SendCellMessage Cell_Message_HTTPread
;
              call      LoadCellModuleTimeOut_HTTPread
;
              call      PollCellModuleWithTimeOutInitialise
;
              movlw     S_GSM_HTTPreadPoll
              movff     WREG,GSM_State
;
X_GSM_HTTPreadWaitEnd:
;
              GSM_EndOfState Release
;
;-----------------------
;
X_GSM_HTTPreadPoll:
;
;-----------------------
;
              bcf       AcceptSpaces
              call      PollCellModuleWithTimeOut
;
              btfss     PollComplete
              goto      X_GSM_HTTPreadPoll1
;
              movlw     S_GSM_HTTPreadAnalyse
              movff     WREG,GSM_State
;
              GSM_EndOfState Dispatch
;
X_GSM_HTTPreadPoll1
;
              btfss     CellModuleResponseTimeOut
              goto      X_GSM_HTTPreadPollEnd
;
              movlw     S_GSM_ModuleOff
              movff     WREG,GSM_State
;
X_GSM_HTTPreadPollEnd:
;
              GSM_EndOfState Release
;
;-----------------------
;
X_GSM_HTTPreadAnalyse:
;
;-----------------------
;
              movf      PhraseNumber,W,Access
              xorlw     CellResponse_HTTPread
              btfss     ZeroFlag
              goto      X_GSM_HTTPreadAnalyse4
;
; Parse out the response from the server here eventually, but for now just assume it is good and update the log pointer
; - Also, if it is bad then I need to decide how many retries before calling it quits for today and then trying tomorrow again
;
              movf      LogDataLength,W,Banked
              addwf     GSMReadPointer,Same,Banked
              movlw     0
              addwfc    GSMReadPointerH,Same,Banked
              movlw     0
              addwfc    GSMReadPointerHH,Same,Banked
;
              movlw     0x06
              subwf     GSMReadPointerHH,W,Banked
              btfss     CarryFlag
              goto      X_GSM_HTTPreadAnalyse1
;
              movlw     LOW(0x40000)
              movwf     GSMReadPointer,Banked
              movlw     HIGH(0x40000)
              movwf     GSMReadPointerH,Banked
              movlw     UPPER(0x40000)
              movwf     GSMReadPointerHH,Banked
;
X_GSM_HTTPreadAnalyse1:
;
              movf      GSMReadPointer,W,Banked
              xorwf     LogWritePointer,W,Banked
              btfss     ZeroFlag
              goto      X_GSM_HTTPreadAnalyse2
;
              movf      GSMReadPointerH,W,Banked
              xorwf     LogWritePointerH,W,Banked
              btfss     ZeroFlag
              goto      X_GSM_HTTPreadAnalyse2
;
              movf      GSMReadPointerHH,W,Banked
              xorwf     LogWritePointerHH,W,Banked
              btfss     ZeroFlag
              goto      X_GSM_HTTPreadAnalyse1
;
              movlw     S_GSM_HTTPterminate
              movff     WREG,GSM_State
;
              goto      X_GSM_HTTPreadAnalyse3
;
X_GSM_HTTPreadAnalyse2:
;
              movlw     S_GSM_DataSize
              movff     WREG,GSM_State
;
              goto      X_GSM_HTTPreadAnalyse3
;              
X_GSM_HTTPreadAnalyse3:
;
              goto      X_GSM_HTTPreadAnalyseEnd
;
X_GSM_HTTPreadAnalyse4:
;
              movlw     S_GSM_ModuleOff
              movff     WREG,GSM_State
;
              goto      X_GSM_HTTPreadAnalyseEnd
;
X_GSM_HTTPreadAnalyseEnd:
;
              GSM_EndOfState Release
;
;*************************************************
;
; These STATEs terminate the HTTP
;
;*************************************************
;
;-----------------------
;
X_GSM_HTTPterminate:
;
;-----------------------
;
              call      LoadCellModuleTimeOut_CommandDelay
;
              movlw     S_GSM_HTTPterminateWait
              movff     WREG,GSM_State
;
              GSM_EndOfState Release
;
;-----------------------
;
X_GSM_HTTPterminateWait:
;
;-----------------------
;
              btfss     CellModuleResponseTimeOut
              goto      X_GSM_HTTPterminateWaitEnd
;
              call      FlushSerialReceiveBuffer1
;
              bcf       NoCR
              SendCellMessage Cell_Message_HTTPterminate
;
              call      LoadCellModuleTimeOut_HTTPterminate
;
              call      PollCellModuleWithTimeOutInitialise
;
              movlw     S_GSM_HTTPterminatePoll
              movff     WREG,GSM_State
;
X_GSM_HTTPterminateWaitEnd:
;
              GSM_EndOfState Release
;
;-----------------------
;
X_GSM_HTTPterminatePoll:
;
;-----------------------
;
              bcf       AcceptSpaces
              call      PollCellModuleWithTimeOut
;
              btfss     PollComplete
              goto      X_GSM_HTTPterminatePoll1
;
              movlw     S_GSM_HTTPterminateAnalyse
              movff     WREG,GSM_State
;
              GSM_EndOfState Dispatch
;
X_GSM_HTTPterminatePoll1
;
              btfss     CellModuleResponseTimeOut
              goto      X_GSM_HTTPterminatePollEnd
;
              movlw     S_GSM_ModuleOff
              movff     WREG,GSM_State
;
X_GSM_HTTPterminatePollEnd:
;
              GSM_EndOfState Release
;
;-----------------------
;
X_GSM_HTTPterminateAnalyse:
;
;-----------------------
;
              movf      PhraseNumber,W,Access
              xorlw     CellResponse_OK
              btfss     ZeroFlag
              goto      X_GSM_HTTPterminateAnalyse1
;
              movlw     S_GSM_CloseBearer
              movff     WREG,GSM_State
;
              goto      X_GSM_HTTPterminateAnalyseEnd
;
X_GSM_HTTPterminateAnalyse1:
;
              movlw     S_GSM_ModuleOff
              movff     WREG,GSM_State
;
              goto      X_GSM_HTTPterminateAnalyseEnd
;
X_GSM_HTTPterminateAnalyseEnd:
;
              GSM_EndOfState Release
;
;*************************************************
;
; These STATEs close the bearer
;
;*************************************************
;
;-----------------------
;
X_GSM_CloseBearer:
;
;-----------------------
;
              call      LoadCellModuleTimeOut_CommandDelay
;
              movlw     S_GSM_CloseBearerWait
              movff     WREG,GSM_State
;
              GSM_EndOfState Release
;
;-----------------------
;
X_GSM_CloseBearerWait:
;
;-----------------------
;
              btfss     CellModuleResponseTimeOut
              goto      X_GSM_CloseBearerWaitEnd
;
              call      FlushSerialReceiveBuffer1
;
              bcf       NoCR
              SendCellMessage Cell_Message_CloseBearer
;
              call      LoadCellModuleTimeOut_CloseBearer
;
              call      PollCellModuleWithTimeOutInitialise
;
              movlw     S_GSM_CloseBearerPoll
              movff     WREG,GSM_State
;
X_GSM_CloseBearerWaitEnd:
;
              GSM_EndOfState Release
;
;-----------------------
;
X_GSM_CloseBearerPoll:
;
;-----------------------
;
              bsf       AcceptSpaces
              call      PollCellModuleWithTimeOut
;
              btfss     PollComplete
              goto      X_GSM_CloseBearerPoll1
;
              movlw     S_GSM_CloseBearerAnalyse
              movff     WREG,GSM_State
;
              GSM_EndOfState Dispatch
;
X_GSM_CloseBearerPoll1
;
              btfss     CellModuleResponseTimeOut
              goto      X_GSM_CloseBearerPollEnd
;
              movlw     S_GSM_ModuleOff
              movff     WREG,GSM_State
;
X_GSM_CloseBearerPollEnd:
;
              GSM_EndOfState Release
;
;-----------------------
;
X_GSM_CloseBearerAnalyse:
;
;-----------------------
;
              movf      PhraseNumber,W,Access
              xorlw     CellResponse_OK
              btfss     ZeroFlag
              goto      X_GSM_CloseBearerA1
;
              movlw     S_GSM_ModuleOff
              movff     WREG,GSM_State
;
              bcf       SendSMS
;
; N213 include this code to delay longer when POSTs are not acknowledged by the server
;
           IFDEF NAKDelay
;
              clrf      NAKDelayMultiplier,Banked
;
           ENDIF
;
; N213 include this code to delay longer when POSTs are not acknowledged by the server
;
              goto      X_GSM_CloseBearerAEnd
;
X_GSM_CloseBearerA1:
;
              movlw     S_GSM_ModuleOff
              movff     WREG,GSM_State
;
              goto      X_GSM_CloseBearerAEnd
;
X_GSM_CloseBearerAEnd:
;
              GSM_EndOfState Release
;
; Legacy states below
;
;-----------------------
;
X_GSM_ReplySMS:
;
;-----------------------
;
              call      LoadCellModuleTimeOut_CommandDelay ;ReplyToSMS
;
              movlw     S_GSM_ReplySMSWait
              movff     WREG,GSM_State
;
              GSM_EndOfState Release
;
;-----------------------
;
X_GSM_ReplySMSWait:
;
;-----------------------
;
              call      CheckByteSerialBuffer1
              btfss     CarryFlag
              goto      X_GSM_ReplySMSWait1
;
              call      LoadCellModuleTimeOut_CommandDelay
;
X_GSM_ReplySMSWait1:
;
              btfss     CellModuleResponseTimeOut
              goto      X_GSM_ReplySMSWaitEnd
;
              call      FlushSerialReceiveBuffer1
;
              bsf       NoCR
              SendCellMessage Cell_Message_SendSMS
	      SendCellMessage Cell_Message_Number
;
;             lfsr      0,ReplyNumber
;             movff     ReplyNumberLength,GSM_ScratchPad0
;
;_GSM_ReplySMSWait3:
;
;             movf      POSTINC0,W,Access              
;             call      WriteByteSerialBuffer1
;             decfsz    GSM_ScratchPad0,Same,Banked
;             goto      X_GSM_ReplySMSWait3
;
              movlw     CR
              call      WriteByteSerialBuffer1
;
              call      LoadCellModuleTimeOut_SendSMS
;
              movlw     S_GSM_ReplySMSWaitForPromptA
              movff     WREG,GSM_State
;
X_GSM_ReplySMSWaitEnd:
;
              GSM_EndOfState Release
;
;-----------------------
;
X_GSM_ReplySMSWaitForPromptA:
;
;-----------------------
;
              call      CheckByteSerialBuffer1
              btfss     CarryFlag
              goto      X_GSM_ReplySMSWaitForPromptA1
;
              xorlw     CR
              btfsc     ZeroFlag
              goto      X_GSM_ReplySMSWaitForPromptA
;
              xorlw     LF^CR
              btfsc     ZeroFlag
              goto      X_GSM_ReplySMSWaitForPromptA
;
              xorlw     '>'^LF
              btfss     ZeroFlag
              goto      X_GSM_ReplySMSWaitForPromptA2
;
              movlw     S_GSM_ReplySMSWaitForPromptB
              movff     WREG,GSM_State
;
              goto      X_GSM_ReplySMSWaitForPromptAEnd
;
X_GSM_ReplySMSWaitForPromptA1
;
              btfss     CellModuleResponseTimeOut
              goto      X_GSM_ReplySMSWaitForPromptAEnd
;
X_GSM_ReplySMSWaitForPromptA2
;
              movlw     S_GSM_ModuleOff
              movff     WREG,GSM_State
;
X_GSM_ReplySMSWaitForPromptAEnd
;
              GSM_EndOfState Release
;
;-----------------------
;
X_GSM_ReplySMSWaitForPromptB:
;
;-----------------------
;
              call      CheckByteSerialBuffer1
              btfss     CarryFlag
              goto      X_GSM_ReplySMSWaitForPromptBOut
;
              xorlw     ' '
              btfss     ZeroFlag
              goto      X_GSM_ReplySMSWaitForPromptBError
;
; Generate the TEXT for FULL!
;
X_GSM_ReplySMS_Full:
;
              bsf       NoCR
              SendCellMessage Cell_Message_Content
;
              movlw     CtrlZ
              call      WriteByteSerialBuffer1
;
              call      LoadCellModuleTimeOut_ConfirmReplySMS
;
              call      PollCellModuleWithTimeOutInitialise
;
              movlw     S_GSM_ReplySMSPoll
              movff     WREG,GSM_State
;
              goto      X_GSM_ReplySMSWaitForPromptBEnd
;
X_GSM_ReplySMSWaitForPromptBOut:
;
              btfss     CellModuleResponseTimeOut
              goto      X_GSM_ReplySMSWaitForPromptBEnd
;
X_GSM_ReplySMSWaitForPromptBError
X_GSM_ReplySMSDelete:
;
              movlw     S_GSM_ModuleOff
              movff     WREG,GSM_State
;
X_GSM_ReplySMSWaitForPromptBEnd
;
              GSM_EndOfState Release
;
;-----------------------
;
; This STATE polls for the response from the module
;
;-----------------------
;
X_GSM_ReplySMSPoll:
;
              bcf       AcceptSpaces
              call      PollCellModuleWithTimeOut
;
              btfss     PollComplete
              goto      X_GSM_ReplySMSPoll1
;
              movlw     S_GSM_ReplySMSAnalyse
              movff     WREG,GSM_State
;
              GSM_EndOfState Dispatch
;
X_GSM_ReplySMSPoll1
;
              btfss     CellModuleResponseTimeOut
              goto      X_GSM_ReplySMSPollEnd
;
              movlw     S_GSM_ModuleOff
              movff     WREG,GSM_State
;
X_GSM_ReplySMSPollEnd
;
              GSM_EndOfState Release
;
;-----------------------
;
; This STATE analyses the cell modems response to the set socket
;
;-----------------------
;
X_GSM_ReplySMSAnalyse:
;
              movf      PhraseNumber,W,Access
              xorlw     CellResponse_SMSSent
              btfss     ZeroFlag
              goto      X_GSM_ReplySMSAnalyse1
;
              call      PollCellModuleWithTimeOutInitialise
;
              movlw     S_GSM_ReplySMSPoll
              movff     WREG,GSM_State
;
              goto      X_GSM_ReplySMSAnalyseEnd
;
X_GSM_ReplySMSAnalyse1
;
              xorlw     CellResponse_OK^CellResponse_SMSSent
              btfss     ZeroFlag
              goto      X_GSM_ReplySMSAnalyse2
;
              movlw     S_GSM_ModuleOff
              movff     WREG,GSM_State
;
              bcf       SendSMS
;
              goto      X_GSM_ReplySMSAnalyseEnd
;
X_GSM_ReplySMSAnalyse2
;
              movlw     S_GSM_ModuleOff
              movff     WREG,GSM_State
;
X_GSM_ReplySMSAnalyseEnd
;
              GSM_EndOfState Release
;
;*************************************************
;
; These STATEs switch the cell module off
;
;*************************************************
;
;-----------------------
;
X_GSM_ModuleOff:
;
;-----------------------
;
      ;        btfsc     SendSMS
      ;        goto      X_GSM_ModuleOff_AAA
;
      ;        bsf       GSM_DTR_out              ;Put the module into sleep mode so that we can still receive SMSes
;
      ;        movlw     S_GSM_ModuleOffDone
      ;        movff     WREG,GSM_State
;
      ;        GSM_EndOfState Release
;
X_GSM_ModuleOff_AAA:
;              
              btfss     GSM_Powered
              goto      X_GSM_ModuleOff_1
;      
              bsf       GSM_On
;
              call      LoadCellModuleTimeOut_ModuleOff
;
              movlw     S_GSM_ModuleOffWait
              movff     WREG,GSM_State
;
              GSM_EndOfState Release
;
X_GSM_ModuleOff_1:
;
              bcf       GSM_On
;
              call      LoadCellModuleTimeOut_ModuleOffPause
;
              movlw     S_GSM_ModuleOffPause
              movff     WREG,GSM_State
;
              GSM_EndOfState Release
;    
;-----------------------
;
X_GSM_ModuleOffWait:
;
;-----------------------
;
              btfss     CellModuleResponseTimeOut
              goto      X_GSM_ModuleOnWait_End
;
              bcf       GSM_On
;
              call      LoadCellModuleTimeOut_ModuleOffCheck
;
              movlw     S_GSM_ModuleOffCheck
              movff     WREG,GSM_State
;
X_GSM_ModuleOffWait_End
;
              GSM_EndOfState Release
;    
;-----------------------
;
X_GSM_ModuleOffCheck:
;
;-----------------------
;
              btfss     CellModuleResponseTimeOut
              goto      X_GSM_ModuleOffCheck_1
;
              movlw     S_GSM_ModuleOff
              movff     WREG,GSM_State
;
              goto      X_GSM_ModuleOffCheck_End
;
X_GSM_ModuleOffCheck_1:
;
              btfsc     GSM_Powered
              goto      X_GSM_ModuleOffCheck_End 
;
              movlw     S_GSM_ModuleOffPause
              btfss     SendSMS
              movlw     S_GSM_ModuleOffDone
              movff     WREG,GSM_State
;
X_GSM_ModuleOffCheck_End
;
              GSM_EndOfState Release
;    
;-----------------------
;
X_GSM_ModuleOffDone:
;
;-----------------------
;
              GSM_EndOfState Release
;    
;-----------------------
;
X_GSM_ModuleOffPause:
;
;-----------------------
;
              btfss     CellModuleResponseTimeOut
              goto      X_GSM_ModuleOffPause_End
;
              movf      MessageRetries,W,Banked               
              btfsc     ZeroFlag
              goto      X_GSM_ModuleOffPause_KillForNow
;
              decf      MessageRetries,Same,Banked
;
              movlw     S_GSM_ModuleOn
              movff     WREG,GSM_State
;
              goto      X_GSM_ModuleOffPause_End
;
X_GSM_ModuleOffPause_KillForNow:           
;
              bcf       SendSMS
;
; N213 include this code to delay longer when POSTs are not acknowledged by the server
;
           IFDEF NAKDelay
;
              incfsz    NAKDelayMultiplier,W,Banked
              incf      NAKDelayMultiplier,Same,Banked
;
           ENDIF
;
; N213 include this code to delay longer when POSTs are not acknowledged by the server
;
              movlw     S_GSM_ModuleOffDone
              movff     WREG,GSM_State
;
              goto      X_GSM_ModuleOffPause_End
;
X_GSM_ModuleOffPause_End
;
              GSM_EndOfState Release
;
ProcessGSM_End:
;
              return
;
;***************************************
;
; Load cell module time out: 
;
;***************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
LoadCellModuleTimeOut_ModuleOn:
;
              movlw     LOW(1000*msec)           
              movwf     CellModuleTimeOutTimer,Banked
              movlw     HIGH(1000*msec)
              movwf     CellModuleTimeOutTimerH,Banked
              bcf       CellModuleResponseTimeOut
              return
;
;***************************************
;
; Load cell module time out: 
;
;***************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
LoadCellModuleTimeOut_ModuleOff:
;
              movlw     LOW(2100*msec)           
              movwf     CellModuleTimeOutTimer,Banked
              movlw     HIGH(2100*msec)
              movwf     CellModuleTimeOutTimerH,Banked
              bcf       CellModuleResponseTimeOut
              return
;
;***************************************
;
; Load cell module time out: 
;
;***************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
LoadCellModuleTimeOut_ModuleOffCheck:
;
              movlw     LOW(200*msec)           
              movwf     CellModuleTimeOutTimer,Banked
              movlw     HIGH(200*msec)
              movwf     CellModuleTimeOutTimerH,Banked
              bcf       CellModuleResponseTimeOut
              return
;
;***************************************
;
; Load cell module time out: 
;
;***************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
LoadCellModuleTimeOut_CommandDelay:
;
              movlw     LOW(100*msec)           
              movwf     CellModuleTimeOutTimer,Banked
              movlw     HIGH(100*msec)
              movwf     CellModuleTimeOutTimerH,Banked
              bcf       CellModuleResponseTimeOut
              return
;
;***************************************
;
; Load cell module time out:
;
;***************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
LoadCellModuleTimeOut_QueryModule:
LoadCellModuleTimeOut_QuerySIM:
LoadCellModuleTimeOut_TimeStampEnable:
LoadCellModuleTimeOut_SaveProfile:
LoadCellModuleTimeOut_ReadTimeStamp:
LoadCellModuleTimeOut_CommandEchoOff:
LoadCellModuleTimeOut_NetworkRegistration:
LoadCellModuleTimeOut_NoFlowControl:
LoadCellModuleTimeOut_FixBaudRate:
LoadCellModuleTimeOut_SelectTextMode:
LoadCellModuleTimeOut_SetTextModeParameters:
LoadCellModuleTimeOut_ReadSignalStrength:
LoadCellModuleTimeOut_SendSMS:
LoadCellModuleTimeOut_DeleteSMS:
LoadCellModuleTimeOut_CommandCheckForSMS:
LoadCellModuleTimeOut_ModuleOffPause:
LoadCellModuleTimeOut_ConnectionType:
LoadCellModuleTimeOut_SetAPN:
LoadCellModuleTimeOut_HTTPinit:
LoadCellModuleTimeOut_BearerID:
LoadCellModuleTimeOut_SetURL:
LoadCellModuleTimeOut_ContentType:
LoadCellModuleTimeOut_DataSize:
LoadCellModuleTimeOut_SendData:
LoadCellModuleTimeOut_HTTPread:
LoadCellModuleTimeOut_HTTPterminate:
;
              movlw     LOW(5*Seconds)           ;Includes 150msec for parsing
              movwf     CellModuleTimeOutTimer,Banked
              movlw     HIGH(5*Seconds)
              movwf     CellModuleTimeOutTimerH,Banked
              bcf       CellModuleResponseTimeOut
              return
;
;***************************************
;
; Load cell module time out: 
;
;***************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
LoadCellModuleTimeOut_DeleteSMSCommandDelay:
LoadCellModuleTimeOut_ListAllSMSs:
;
              movlw     LOW(10*Seconds)           
              movwf     CellModuleTimeOutTimer,Banked
              movlw     HIGH(10*Seconds)
              movwf     CellModuleTimeOutTimerH,Banked
              bcf       CellModuleResponseTimeOut
              return
;
;***************************************
;
; Load cell module time out: 
;
;***************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
LoadCellModuleTimeOut_GSMInitialising:
LoadCellModuleTimeOut_QuerySMSServiceCentre:
LoadCellModuleTimeOut_PhoneBookFind
;
              DisableInterrupts
              movlw     LOW(20*Seconds)           
              movwf     CellModuleTimeOutTimer,Banked
              movlw     HIGH(20*Seconds)
              movwf     CellModuleTimeOutTimerH,Banked
              bcf       CellModuleResponseTimeOut
              RestoreInterrupts
              return
;
;***************************************
;
; Load cell module time out: 
;
;***************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
LoadCellModuleTimeOut_HTTPaction: 
;
              DisableInterrupts
              movlw     LOW(90*Seconds)           
              movwf     CellModuleTimeOutTimer,Banked
              movlw     HIGH(90*Seconds)
              movwf     CellModuleTimeOutTimerH,Banked
              bcf       CellModuleResponseTimeOut
              RestoreInterrupts
              return
;
;***************************************
;
; Load cell module time out: 
;
;***************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
LoadCellModuleTimeOut_NetRegSPause:
;
              DisableInterrupts
              movlw     LOW(5*Seconds)           
              movwf     CellModuleTimeOutTimer,Banked
              movlw     HIGH(5*Seconds)
              movwf     CellModuleTimeOutTimerH,Banked
              bcf       CellModuleResponseTimeOut
              RestoreInterrupts
              return
;
;***************************************
;
; Load cell module time out: 
;
;***************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
LoadCellModuleTimeOut_NetRegLPause:
;
              DisableInterrupts
              movlw     LOW(60*Seconds)           
              movwf     CellModuleTimeOutTimer,Banked
              movlw     HIGH(60*Seconds)
              movwf     CellModuleTimeOutTimerH,Banked
              bcf       CellModuleResponseTimeOut
              RestoreInterrupts
              return
;
;***************************************
;
; Load cell module time out: 
;
;***************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
LoadCellModuleTimeOut_GPRSattachment:
;
              DisableInterrupts
              movlw     LOW(75*Seconds)           
              movwf     CellModuleTimeOutTimer,Banked
              movlw     HIGH(75*Seconds)
              movwf     CellModuleTimeOutTimerH,Banked
              bcf       CellModuleResponseTimeOut
              RestoreInterrupts
              return
;
;***************************************
;
; Load cell module time out: 
;
;***************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
LoadCellModuleTimeOut_OpenBearer:
LoadCellModuleTimeOut_QueryBearer:
LoadCellModuleTimeOut_CloseBearer:
;
              DisableInterrupts
              movlw     LOW(85*Seconds)           
              movwf     CellModuleTimeOutTimer,Banked
              movlw     HIGH(85*Seconds)
              movwf     CellModuleTimeOutTimerH,Banked
              bcf       CellModuleResponseTimeOut
              RestoreInterrupts
              return
;
;***************************************
;
; X_SendCellMessage
;
; This is the working code which reads a text message from program memory and sends it to the cell serial buffer
;
;***************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
X_SendCellMessage: 
;
X_SendCellMessage1
;
              TBLRD     *+                       ;Fetch character
              movf      TABLAT,W,Access
              andlw     b'11111111'              ;Is it 0?
              btfsc     ZeroFlag                 
              goto      X_SendCellMessage2       ;Yes, so we are done
;
              call      WriteByteSerialBuffer1   ;No, so send it to the cellphone
              goto      X_SendCellMessage1
;
X_SendCellMessage2
;
              btfsc     NoCR                     ;Do we want a CR
              goto      X_SendCellMessageEnd     ;No, so go
;
              movlw     CR                       ;Yes, so send one to the cellphone
              call      WriteByteSerialBuffer1
;
X_SendCellMessageEnd
;
              return
;
;***************************************
;
; Load cell module time out: 
;
;***************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
LoadCellModuleTimeOut_ConfirmSMS:
LoadCellModuleTimeOut_ConfirmReplySMS:
;
              movlw     LOW(180*Seconds)           ;Includes 150msec for parsing
              movwf     CellModuleTimeOutTimer,Banked
              movlw     HIGH(180*Seconds)
              movwf     CellModuleTimeOutTimerH,Banked
              bcf       CellModuleResponseTimeOut
              return
;
;*************************************************
;
; 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:
;
              movwf     Event,Banked
;
              movf      EventQueueAvailable,W,Banked
              btfss     ZeroFlag
              goto      WriteEventToQueue1 
;
              bsf       EventQueueOverFlow
;
              goto      WriteEventToQueueEnd
;
WriteEventToQueue1:
;
              movlw     HIGH(EventQueue_3)
              movwf     FSR0H,Access
;
              movf      EventQueueWritePointer,W,Banked
              movwf     FSR0L,Access
;
              movf      Event,W,Banked
              movwf     POSTINC0,Access
;
              movf      FSR0L,W,Access
              xorlw     EventQueueLastLocation+1
              btfsc     ZeroFlag
              movlw     EventQueueFirstLocation^(EventQueueLastLocation+1) 
              xorlw     EventQueueLastLocation+1
              movwf     EventQueueWritePointer,Banked
;
              decf      EventQueueAvailable,Same,Banked ;There is one less space available in the event queue
;
WriteEventToQueueEnd:
;
              return
;
ReadEventQueue:
;
              movlw     EventQueueSize           ;IF all the bytes are available 
              subwf     EventQueueAvailable,W,Banked
              btfsc     ZeroFlag
              goto      ReadEventQueue1          ;THEN the queue is empty and we return with 0
;
              movlw     HIGH(EventQueue_3)
              movwf     FSR0H,Access
;
              movf      EventQueueReadPointer,W,Banked
              movwf     FSR0L,Access
;
              movf      INDF0,W,Access
;
ReadEventQueue1:
;
              movwf     Event,Banked
;
ReadEventQueueEnd:
;
              return
;
RemoveEventFromQueue:
;
              movlw     EventQueueSize           ;IF all the bytes are available 
              subwf     EventQueueAvailable,W,Banked
              btfss     ZeroFlag
              goto      RemoveEventFromQueue1    
;
              bsf       EventQueueUnderFlow      ;THEN the event queue is empty and has UnderFlowed
;
              goto      RemoveEventFromQueueEnd
;
RemoveEventFromQueue1:
;
              movlw     HIGH(EventQueue_3)
              movwf     FSR0H,Access
;
              movf      EventQueueReadPointer,W,Banked
              movwf     FSR0L,Access
;
              incf      EventQueueReadPointer,W,Banked
              xorlw     EventQueueLastLocation+1
              btfsc     ZeroFlag
              movlw     EventQueueFirstLocation^(EventQueueLastLocation+1)
              xorlw     EventQueueLastLocation+1
              movwf     EventQueueReadPointer,Banked
;
              incf      EventQueueAvailable,Same,Banked ;There is one more space available in the queue
;
              clrf      EventState,Banked
;
              movf      INDF0,W,Access
              movwf     Event,Banked
;
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,Banked
;
              movlw     HIGH(EventQueue_3)
              movwf     FSR0H,Access
;
              movf      EventQueueReadPointer,W,Banked
              movwf     FSR0L,Access
;
              movf      Event,W,Banked
              movwf     INDF0,Access
;
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:
;
              movwf     EEPROM,Banked
;
              movlw     EEPROM_BufferSize 
              subwf     EEPROM_Buffered,W,Banked
              btfss     CarryFlag
              goto      EEPROM_WriteBuffer1 
;
              bsf       EEPROM_OverFlow
;
              goto      EEPROM_WriteBufferEnd
;
EEPROM_WriteBuffer1:
;
              movlw     HIGH(EEPROM_Buffer_3)
              movwf     FSR0H,Access
;
              movf      EEPROM_WritePointer,W,Banked
              movwf     FSR0L,Access
;
              movf      EEPROM,W,Banked
              movwf     POSTINC0,Access
;
              movf      FSR0L,W,Access
              xorlw     EEPROM_LastLocation+1
              btfsc     ZeroFlag
              movlw     EEPROM_FirstLocation^(EEPROM_LastLocation+1) 
              xorlw     EEPROM_LastLocation+1
              movwf     EEPROM_WritePointer,Banked
;
              incf      EEPROM_Buffered,Same,Banked ;There is one less space available in the event queue
;
EEPROM_WriteBufferEnd:
;
              return
;
EEPROM_ReadBuffer:
;
              movf      EEPROM_Buffered,W,Banked
              btfss     ZeroFlag
              goto      EEPROM_ReadBuffer1       
;
              bsf       EEPROM_UnderFlow
;
              goto      EEPROM_ReadBufferEnd
;
EEPROM_ReadBuffer1:
;
              movlw     HIGH(EEPROM_Buffer_3)
              movwf     FSR0H,Access
;
              movf      EEPROM_ReadPointer,W,Banked
              movwf     FSR0L,Access
;
              movf      POSTINC0,W,Access
              movwf     EEPROM,Banked
;
              movf      FSR0L,W,Access
              xorlw     EEPROM_LastLocation+1
              btfsc     ZeroFlag
              movlw     EEPROM_FirstLocation^(EEPROM_LastLocation+1)
              xorlw     EEPROM_LastLocation+1
              movwf     EEPROM_ReadPointer,Banked
;
              decf      EEPROM_Buffered,Same,Banked ;There is one more space available in the queue
;
              movf      EEPROM,W,Banked
;
EEPROM_ReadBufferEnd:
;
              return   




;
; I2C routines
;




;
; I2C routines
;
I2C_Delay:
;
              btfss     HighSpeed
              goto      I2C_Delay_End  
;
              movlw     14
              movwf     I2C_DelayCounter,Banked
;
I2C_Delay_1:
;
              decfsz    I2C_DelayCounter,Same,Banked
              goto      I2C_Delay_1
;
I2C_Delay_End:
;
              return
;
I2C_RTC_Start:
;
              bsf       SDA_RTC_Direction ;SDA pulled high
              call      I2C_Delay
              bsf       SCL_RTC_Direction ;SCL pulled high
              call      I2C_Delay
              bcf       SDA_RTC_Out       ;SDA active low
              bcf       SDA_RTC_Direction
              call      I2C_Delay
              bcf       SCL_RTC_Out       ;SCL active low
              bcf       SCL_RTC_Direction
              call      I2C_Delay
;
              return
;
I2C_RTC_Stop:
;
              bcf       SDA_RTC_Out       ;SDA active low
              bcf       SDA_RTC_Direction
              call      I2C_Delay
              bsf       SCL_RTC_Direction ;Clock pulled high
              call      I2C_Delay
              bsf       SDA_RTC_Direction ;SDA pulled high
              call      I2C_Delay
;
              return
;
I2C_RTC_Rx:
;
              bsf       SDA_RTC_Direction ;SDA pulled high
              movlw     8
              movwf     I2C_Count,Banked
;
I2C_RTC_RxLoop:
;
              bcf       CarryFlag
              rlcf      I2C_Data,Same,Banked
;
              bsf       SCL_RTC_Direction ;SCL is pulled high
;
              call      I2C_Delay
;
              btfsc     SDA_RTC_In
              bsf       I2C_Data,0,Banked
;
              bcf       SCL_RTC_Out    ;SCL active low
              bcf       SCL_RTC_Direction
;
              call      I2C_Delay
;
              decfsz    I2C_Count,Same,Banked
              goto      I2C_RTC_RxLoop
;
              bcf       SDA_RTC_Out
              btfsc     AckTx
              bcf       SDA_RTC_Direction
              btfss     AckTx
              bsf       SDA_RTC_Direction
;
              bsf       SCL_RTC_Direction ;SCL pulled high
              call      I2C_Delay
              bcf       SCL_RTC_Out       ;SCL active low
              bcf       SCL_RTC_Direction
              call      I2C_Delay
              bsf       SDA_RTC_Direction
;
              movf      I2C_Data,W,Banked
;
              return
;
I2C_RTC_Tx:
;
              movwf     I2C_Data,Banked
              movlw     8
              movwf     I2C_Count,Banked
;
I2C_RTC_TxLoop:
;
              bcf       SDA_RTC_Out
              btfsc     I2C_Data,7,Banked
              goto      I2C_RTC_TxLoopHi
              goto      I2C_RTC_TxLoopLo
;
I2C_RTC_TxLoopHi:
;
              bsf       SDA_RTC_Direction
;
              goto      I2C_RTC_TxLoop1
;
I2C_RTC_TxLoopLo:
;
              bcf       SDA_RTC_Direction
;
              goto      I2C_RTC_TxLoop1
;
I2C_RTC_TxLoop1:
;
              call      I2C_Delay
;
              bsf       SCL_RTC_Direction ;SCL pulled high 
;
              call      I2C_Delay
;
              rlcf      I2C_Data,Same,Banked
;
              bcf       SCL_RTC_Out
              bcf       SCL_RTC_Direction
;
              call      I2C_Delay ;???
;
              decfsz    I2C_Count,Same,Banked
              goto      I2C_RTC_TxLoop
;
              bsf       SDA_RTC_Direction ;SDA pulled high
              call      I2C_Delay
              bsf       SCL_RTC_Direction ;SCL pulled high
              call      I2C_Delay
              bsf       AckRx
              btfss     SDA_In
              bcf       AckRx
;
              bcf       SCL_RTC_Out
              bcf       SCL_RTC_Direction
;
              call      I2C_Delay
;
              return
;
I2C_Start:
;
              bsf       SDA_Direction ;SDA pulled high
              bsf       SCL_Direction ;SCL pulled high
              call      I2C_Delay
              bcf       SDA_Out       ;SDA active low
              bcf       SDA_Direction
              call      I2C_Delay
              bcf       SCL_Out       ;SCL active low
              bcf       SCL_Direction
              call      I2C_Delay
;
              return
;
I2C_Stop:
;
              bcf       SCL_Out       ;SCL should be low, but make sure
              bcf       SCL_Direction
              bcf       SDA_Out       ;SDA active low
              bcf       SDA_Direction
              call      I2C_Delay
              bsf       SCL_Direction ;Clock pulled high
              call      I2C_Delay
              bsf       SDA_Direction ;SDA pulled high
              call      I2C_Delay
;
              return
;
I2C_Rx:
;
              bsf       SDA_Direction ;SDA pulled high
              movlw     8
              movwf     I2C_Count,Banked
;
I2C_RxLoop:
;
              bcf       CarryFlag
              rlcf      I2C_Data,Same,Banked
;
              bsf       SCL_Direction ;SCL is pulled high
;
              call      I2C_Delay
;
              btfsc     SDA_In
              bsf       I2C_Data,0,Banked
;
              bcf       SCL_Out    ;SCL active low
              bcf       SCL_Direction
;
              call      I2C_Delay
;
              decfsz    I2C_Count,Same,Banked
              goto      I2C_RxLoop
;
              bcf       SDA_Out
              btfsc     AckTx
              bcf       SDA_Direction
              btfss     AckTx
              bsf       SDA_Direction
; 
              nop
              bsf       SCL_Direction ;SCL pulled high
              call      I2C_Delay
              nop
              bcf       SCL_Out       ;SCL active low
              nop
              bcf       SCL_Direction
              call      I2C_Delay
              bcf       SDA_Out
              bcf       SDA_Direction
;
              call      I2C_Delay
;
              movf      I2C_Data,W,Banked
;
              clrf      I2C_Tracker,Banked
;
              return
;
I2C_Tx:
;
              movwf     I2C_Data,Banked
              movlw     8
              movwf     I2C_Count,Banked
;
I2C_TxLoop:
;
              bcf       SDA_Out
              btfsc     I2C_Data,7,Banked
              goto      I2C_TxLoopHi
              goto      I2C_TxLoopLo
;
I2C_TxLoopHi:
;
              bsf       SDA_Direction
;
              goto      I2C_TxLoop1
;
I2C_TxLoopLo:
;
              bcf       SDA_Direction
;
              goto      I2C_TxLoop1
;
I2C_TxLoop1:
;
              call      I2C_Delay
;
              bsf       SCL_Direction ;SCL pulled high 
;
              call      I2C_Delay
;
              rlcf       I2C_Data,Same,Banked
;
              bcf       SCL_Out
              bcf       SCL_Direction
;
              call      I2C_Delay 
;
              decfsz    I2C_Count,Same,Banked
              goto      I2C_TxLoop
;
              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
;
              bcf       SCL_Out
              bcf       SCL_Direction
              bcf       SDA_Out
              bcf       SDA_Direction
;
              call      I2C_Delay
;
              return
;
OpenExternalEEPROMforReading:
;
              bsf       Power
;
              call      Delay1msec
;
              call      I2C_Start
              rlcf      EEAdrsHH,W,Access
              andlw     b'00001110'
              iorlw     b'10100000'
              call      I2C_Tx        
              movf      EEAdrsH,W,Access
              call      I2C_Tx
              movf      EEAdrs,W,Access
              call      I2C_Tx
              call      I2C_Start
              rlcf      EEAdrsHH,W,Access
              andlw     b'00001110'
              iorlw     b'10100001'
              call      I2C_Tx        
;
              return
;
ReadExternalEEPROM:
;
              movlw     10
              movwf     I2C_Tracker,Banked
;
              bsf       AckTx
              call      I2C_Rx
;
              return
;
CloseExternalEEPROMforReading:
;
              movlw     11
              movwf     I2C_Tracker,Banked
;
              bcf       AckTx
              call      I2C_Rx
              bsf       AckTx
;
              call      I2C_Stop 
;
              bcf       Power
;
              call      I2C_Delay
              call I2C_Delay
              call I2C_Delay
              call I2C_Delay
;
              return
;
ReadRTC:
;
              bsf       RTC_PU
;
              call      Delay1msec
;
              call      I2C_Delay
;
              lfsr      0,RTC_Seconds
;
              call      I2C_RTC_Start               
              movlw     b'11010000'
              call      I2C_RTC_Tx        
              movlw     b'00000000'              ;Read from the Seconds
              call      I2C_RTC_Tx
              call      I2C_RTC_Start
              movlw     b'11010001'
              call      I2C_RTC_Tx
              bsf       AckTx
              call      I2C_RTC_Rx
              movwf     INDF0
;
              call      I2C_RTC_Rx               ;Minutes
              movwf     PREINC0,Access
              call      I2C_RTC_Rx               ;Hours
              movwf     PREINC0,Access
              call      I2C_RTC_Rx               ;DayOfWeek
              movwf     PREINC0,Access
              call      I2C_RTC_Rx               ;Date
              movwf     PREINC0,Access
              call      I2C_RTC_Rx               ;Month
              movwf     PREINC0,Access
              call      I2C_RTC_Rx               ;Year
              movwf     PREINC0,Access
              bcf       AckTx
              call      I2C_RTC_Rx               ;Control
              bsf       AckTx
              movwf     PREINC0,Access
              call      I2C_RTC_Stop
;
              goto      ReadRTC
;
LogHiLoEvent:
;
 goto LogHiLoEvent_End
;
; 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,Banked
              call      EEPROM_WriteBuffer
;
              movf      HiLoDetail1,W,Banked
              addwf     Checksum,Same,Banked
              call      EEPROM_WriteBuffer
;
              movf      HiLoDetail2,W,Banked
              addwf     Checksum,Same,Banked
              call      EEPROM_WriteBuffer
;
              movlw     LOW(RTC_Year)
              movwf     FSR1L,Access             ;Remember EEPROM_WriteBuffer uses FSR0
              movlw     HIGH(RTC_Year)
              movwf     FSR1H,Access  
;
              movf      POSTDEC1,W,Access ;Year_2
              addwf     Checksum,Same,Banked
              call      EEPROM_WriteBuffer       
              movf      POSTDEC1,W,Access ;Month_2
              addwf     Checksum,Same,Banked
              call      EEPROM_WriteBuffer
              movf      POSTDEC1,W,Access ;Date_2
              addwf     Checksum,Same,Banked
              call      EEPROM_WriteBuffer
;
              movf      POSTDEC1,W,Access ;Skip DayOfWeek_2 ;K520 so it mustn't affect the checksum!
;
              movf      POSTDEC1,W,Access ;Hours_2
              addwf     Checksum,Same,Banked
              call      EEPROM_WriteBuffer
              movf      POSTDEC1,W,Access ;Minutes_2
              addwf     Checksum,Same,Banked
              call      EEPROM_WriteBuffer
              movf      POSTDEC1,W,Access ;Seconds_2
              addwf     Checksum,Same,Banked
              call      EEPROM_WriteBuffer
;
              lfsr      1,RainPulse ;Remember EEPROM_WriteBuffer uses FSR0
;
              movf      POSTINC1,W,Access ;Rain_0
              addwf     Checksum,Same,Banked
              call      EEPROM_WriteBuffer
              movf      POSTINC1,W,Access ;Rain_0H
              addwf     Checksum,Same,Banked
              call      EEPROM_WriteBuffer
              movf      POSTINC1,W,Access ;Rain_0HH
              addwf     Checksum,Same,Banked
              call      EEPROM_WriteBuffer
              movf      POSTINC1,W,Access ;HumidityLo_0
              addwf     Checksum,Same,Banked
              call      EEPROM_WriteBuffer
              movf      POSTINC1,W,Access ;HumidityHi_0
              addwf     Checksum,Same,Banked
              call      EEPROM_WriteBuffer
              movf      POSTINC1,W,Access ;TemperatureLo_0
              addwf     Checksum,Same,Banked
              call      EEPROM_WriteBuffer
              movf      POSTINC1,W,Access ;TemperattureLo_0H
              addwf     Checksum,Same,Banked
              call      EEPROM_WriteBuffer
              movf      POSTINC1,W,Access ;TemperatureHi_0
              addwf     Checksum,Same,Banked
              call      EEPROM_WriteBuffer
              movf      POSTINC1,W,Access ;TemperatureHi_0H
              addwf     Checksum,Same,Banked
              call      EEPROM_WriteBuffer
;
              comf      Checksum,W,Banked
              addlw     1
              call      EEPROM_WriteBuffer
;             
              movlw     Event_WriteEEPROM
              call      WriteEventToQueue
;
              LiveDebug LiveDebug_LogHiLoEvent_End
;
LogHiLoEvent_End:
;
              return
;
; These are the routines for communicating with a device over the USB port
;
ProcessSerialInput:
;
              movwf     PacketCharacter,Banked
;
PSI_Interpret:
;
              movlw     '$'
              xorwf     PacketCharacter,W,Banked
              btfsc     ZeroFlag
              clrf      PacketState,Banked
;
PacketStateDispatcher:
;
              clrf      PCLATU,Access
              movlw     HIGH(PacketStateDispatchTable)
              movwf     PCLATH,Access
              rlcf      PacketState,W,Banked
              rlcf      WREG,W,Access
              andlw     b'00111100'
              addlw     LOW(PacketStateDispatchTable)
              btfsc     CarryFlag
              incf      PCLATH,Same,Access
              movwf     PCL,Access
;
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:
;
              lfsr      0,LineBuffer
;
              movf      PacketCharacter,W,Banked
              movwf     INDF0,Access
;
              bcf       ESCape                   ;Make sure the ESCape flag is clear
;
              movlw     S_PS_ReceiveCommand
              movwf     PacketState,Banked
;
              goto      PacketStateDispatcherEnd
;
PS_ReceiveCommand:
;
              lfsr      0,LineBuffer+1
;
              movf      PacketCharacter,W,Banked
              movwf     INDF0,Access
              movwf     PacketCommand,Banked
;
              btfss     PacketCommand,7,Banked
              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+2)
              movwf     LineBufferPointer,Banked
;
PS_RCF_Dispatcher:
;
              clrf      PCLATU,Access
              movlw     HIGH(PS_RCF_DispatchTable)
              movwf     PCLATH,Access
              swapf     PacketCommand,W,Banked
              rlcf      WREG,W,Access
              rlcf      WREG,W,Access
              andlw     b'00001100'
              addlw     LOW(PS_RCF_DispatchTable)
              btfsc     CarryFlag
              incf      PCLATH,Same,Access
              movwf     PCL,Access
;
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,Banked
;
              goto      PS_ReceiveCommandFastEnd
;
PS_RCF_DS1307:
PS_RCF_InternalEE:
;              
              movlw     1                        ;There is 1 address byte included in these packets
              movwf     PacketCounter,Banked
;
              goto      PS_RCF_ReadnWrite
;
PS_RCF_ExternalEE:
;              
              movlw     3                        ;There are 3 address bytes included in this packet
              movwf     PacketCounter,Banked
;
              goto      PS_RCF_ReadnWrite
;
PS_RCF_ReadnWrite:
;
              btfsc     PacketCommand,6,Banked   ;IF READing
              goto      PS_RCF_ReadnWrite1       ;THEN go because there are no extra bytes to take in account
;
              movf      PacketCommand,W,Banked
              andlw     b'00001111'
              addlw     1
              addwf     PacketCounter,Same,Banked
;
PS_RCF_ReadnWrite1:
;
              goto      PS_ReceiveCommandFastEnd
;
PS_ReceiveCommandFastEnd:
;
              movlw     S_PS_ReceivePayLoad
              movwf     PacketState,Banked
;
              goto      PacketStateDispatcherEnd
;
PS_ReceivePayLoad:
;
              movf      PacketCounter,W,Banked
              btfss     ZeroFlag
              goto      PS_ReceivePayLoad1
;
              movlw     S_PS_ReceiveCheckSum
              movwf     PacketState,Banked
;
              goto      PacketStateDispatcher    ;Execute next state immediately
;
PS_ReceivePayLoad1:
;
              btfss     ESCape
              goto      PS_ReceivePayLoad2
;
              bcf       ESCape 
              movlw     '/'
              subwf     PacketCharacter,Same,Banked
;
              goto      PS_ReceivePayLoad3
;
PS_ReceivePayLoad2:
;
              movlw     '/'
              subwf     PacketCharacter,W,Banked
              btfss     ZeroFlag
              goto      PS_ReceivePayLoad3
;
              bsf       ESCape 
;
              goto      PS_ReceivePayLoadEnd
;
PS_ReceivePayLoad3:
;
              lfsr      0,LineBuffer
;
              movf      LineBufferPointer,W,Banked
              movwf     FSR0L,Access
;
              movf      PacketCharacter,W,Banked
              movwf     POSTINC0,Access
;
              movf      FSR0L,W,Access
              movwf     LineBufferPointer,Banked
;
              decfsz    PacketCounter,Same,Banked
              goto      PS_ReceivePayLoadEnd              
;
              movlw     S_PS_ReceiveCheckSum
              movwf     PacketState,Banked
;
PS_ReceivePayLoadEnd:
;
              goto      PacketStateDispatcherEnd
;
PS_ReceiveCheckSum:
;
              btfss     ESCape
              goto      PS_ReceiveCheckSum1
;
              bcf       ESCape 
              movlw     '/'
              subwf     PacketCharacter,Same,Banked
;
              goto      PS_ReceiveCheckSum2
;
PS_ReceiveCheckSum1:
;
              movlw     '/'
              subwf     PacketCharacter,W,Banked
              btfss     ZeroFlag
              goto      PS_ReceiveCheckSum2
;
              bsf       ESCape 
;
              goto      PS_ReceiveCheckSumEnd
;
PS_ReceiveCheckSum2:
;
              lfsr      0,LineBuffer
;
              movf      LineBufferPointer,W,Banked
              movwf     FSR0L,Access
;
              movf      PacketCharacter,W,Banked
              movwf     INDF0,Access
;
              movlw     0
              movwf     Checksum_A,Banked
;
              movlw     LOW(LineBuffer)
              subwf     LineBufferPointer,W,Banked
              movwf     PacketCounter,Banked
              decf      PacketCounter,Same,Banked
;
              lfsr      0,LineBuffer+1
;
PS_ReceiveAndVerifyCheckSum1:
;
              movf      POSTINC0,W,Access
              addwf     Checksum_A,Same,Banked
;
              decfsz    PacketCounter,Same,Banked
              goto      PS_ReceiveAndVerifyCheckSum1
;
              comf      Checksum_A,W,Banked
              addlw     1
              subwf     INDF0,W,Access
              btfss     ZeroFlag
              goto      RestartPacketState
;
              movlw     S_PS_ExecuteCommand 
              movwf     PacketState,Banked
;
              goto      PacketStateDispatcher    ;Execute next state immediately
;
PS_ReceiveCheckSumEnd:
;
              goto      PacketStateDispatcherEnd
;
PS_ExecuteCommand:
;
              bsf       DeviceCommunicated       
;
              lfsr      0,LineBuffer+1           ;Point to the command
;
              movf      INDF0,W,Access           ;Work out how many bytes there are 
              andlw     b'00001111'
              addlw     1
              movwf     PacketCounter,Banked
;
; Determine which command interpreter to use
;
PS_EC_Dispatcher:
;
              clrf      PCLATU,Access
              movlw     HIGH(PS_EC_DispatchTable)
              movwf     PCLATH,Access
              swapf     INDF0,W,Access
              rlcf      WREG,W,Access
              rlcf      WREG,W,Access
              andlw     b'00001100'
              addlw     LOW(PS_EC_DispatchTable)
              btfsc     CarryFlag
              incf      PCLATH,Same,Access
              movwf     PCL,Access
;
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:
;
              bsf       RTC_PU
; 
              call      Delay1msec
;
              movf      INDF0,W,Access
              movwf     PacketCommand,Banked
;
              call I2C_Delay
;
              lfsr      0,LineBuffer+2
;
              call      I2C_RTC_Start  
              movlw     b'11010000'
              call      I2C_RTC_Tx            
              movf      POSTINC0,W,Access
              movwf     DS1307_Address,Banked
              call      I2C_RTC_Tx             
;
              btfsc     PacketCommand,6,Banked
              goto      PS_EC_DS1307_Read
;
PS_EC_DS1307_Write:
;
; Filter and mask problematic addresses in the clock chip
;
              movf      POSTINC0,W,Access
              movwf     DS1307_Data,Banked
;
              movf      DS1307_Address,W,Banked
;
              xorlw     0
              btfss     ZeroFlag
              goto      PS_EC_DS1307_Write1
;
              movlw     b'01111111'
              andwf     DS1307_Data,Same,Banked
;
              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,Banked
;
              goto      PS_EC_DS1307_WriteX
;
PS_EC_DS1307_Write2:
;
              goto      PS_EC_DS1307_WriteX
;
PS_EC_DS1307_WriteX:
;
              incf      DS1307_Address,Same,Banked
;
; Now we can safely write to the DS1307 without crashing the rain gauge
;
              movf      DS1307_Data,W,Banked 
              call      I2C_RTC_Tx
;
              decfsz    PacketCounter,Same,Banked
              goto      PS_EC_DS1307_Write
;
              call      I2C_RTC_Stop               
;
              bcf       RTC_PU
;
              call      I2C_Delay
;
              call      Response_CommandExecuted
;
              bsf       DeviceSetClock
;
              goto      PS_ExecuteCommandEnd
;
PS_EC_DS1307_Read:
;
; Build response in the line buffer
;
              movlw      '#'
              movff      WREG,LineBuffer+0
;
              decf       PacketCounter,W,Banked  ;RESPONSE low nibble
              iorlw      b'10010000'             ;RESPONSE high nibble
              movff      WREG,LineBuffer+1
; 
              lfsr       0,LineBuffer+2
;
              call      I2C_RTC_Start  
              movlw     b'11010001'
              call      I2C_RTC_Tx
;
PS_EC_DS1307_Read1:
;
              bsf        AckTx
              call       I2C_RTC_Rx
              movwf      POSTINC0,Access
; 
              decfsz     PacketCounter,Same,Banked
              goto       PS_EC_DS1307_Read1
;
              bcf        AckTx
              call       I2C_RTC_Rx
;
              call       I2C_RTC_Stop
;
              bcf        RTC_PU              
;
              call      I2C_Delay
;
              call       Response_AppendChecksum
;
              goto       PS_ExecuteCommandEnd
;
PS_EC_InternalEE:
;
              lfsr      0,LineBuffer+2
;
              btfss     INDF0,7,Access
              goto      PS_EC_InternalEE_Variables
              goto      PS_EC_InternalEE_ScratchPad
;
PS_EC_InternalEE_Variables: 
;
              lfsr      1,ActiveBank
;
              movf      POSTINC0,W,Access       ;Fetch the address of the required variable
              addwf     FSR1L,Same,Access       ;And offset to it  
              btfsc     CarryFlag
              incf      FSR1H,Same,Access
;
              movff     LineBuffer+1,WREG
              btfsc     WREG,6,Access
              goto      PS_EC_InternalEE_Var_Read
;
PS_EC_InternalEE_Var_Write:
;
PS_EC_InternalEE_Var_Write1:
;
              movlw     NV_BoundaryLo
              subwf     FSR1L,W,Access
              btfss     CarryFlag
              goto      PS_EC_InternalEE_Var_Write2
;
              movlw     NV_BoundaryHi
              subwf     FSR1L,W,Access
              btfss     CarryFlag
              goto      PS_EC_InternalEE_Var_Write3
;
PS_EC_InternalEE_Var_Write2:
;
              movf      POSTINC0,W,Access        ;Out of bounds, so no writing!!! Just 2 reads to increment the pointers!!!
              movf      POSTINC1,W,Access
;
              goto      PS_EC_InternalEE_Var_Write4
;           
PS_EC_InternalEE_Var_Write3
;
              movf      POSTINC0,W,Access
              movwf     POSTINC1,Access
;
PS_EC_InternalEE_Var_Write4:
;
              decfsz    PacketCounter,Same,Banked
              goto      PS_EC_InternalEE_Var_Write1
;
              call      SaveSettings_Bulk
;
              call      Response_CommandExecuted
;
              goto       PS_ExecuteCommandEnd
;
PS_EC_InternalEE_Var_Read:
;
; Build response in the line buffer
;
              movlw      '#'
              movff      WREG,LineBuffer+0
;
              decf       PacketCounter,W,Banked  ;RESPONSE low nibble
              iorlw      b'10010000'             ;RESPONSE high nibble
              movff      WREG,LineBuffer+1
; 
              lfsr       0,LineBuffer+2
;
PS_EC_InternalEE_Var_Read1:
;
              movf       POSTINC1,W,Access
              movwf      POSTINC0,Access
;
              decfsz     PacketCounter,Same,Banked
              goto       PS_EC_InternalEE_Var_Read1
;
              call       Response_AppendChecksum
;
              goto       PS_ExecuteCommandEnd
;
PS_EC_InternalEE_ScratchPad: 
;
              movf      POSTINC0,W,Access        ;Fetch scratchpad address
              movwf     EEADR,Access
;
              btfsc     PacketCommand,6,Banked
              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
;
              movf      POSTINC0,W,Access
;
              movwf     EEDATA,Access
;
              bcf       _GIE
              movlw     0x55
              movwf     EECON2,Access
              movlw     0xAA
              movwf     EECON2,Access
              bsf       _EEWR
              bsf       _GIE
;
PS_EC_InternalEE_SP_Write2:
;
              btfsc     _EEWR
              goto      PS_EC_InternalEE_SP_Write2
;
              incf      EEADR,Same,Access
;
              decfsz    PacketCounter,Same,Banked
              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     '#'
              movff     WREG,LineBuffer+0
;
              decf      PacketCounter,W,Banked    ;RESPONSE low nibble
              iorlw     b'10010000'              ;RESPONSE high nibble
              movff     WREG,LineBuffer+1
; 
              lfsr      0,LineBuffer+2
;
              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      EEDATA,W,Access
;
              movwf     POSTINC0,Access
;
              incf      EEADR,Same,Access
;
              decfsz    PacketCounter,Same,Banked
              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:
;
              clrf      PCLATU,Access
              movlw     HIGH(PS_EC_CommandDispatchTable)
              movwf     PCLATH,Access
              movf      INDF0,W,Access
              rlcf      WREG,W,Access
              rlcf      WREG,W,Access
              andlw     b'00111100'
              addlw     LOW(PS_EC_CommandDispatchTable)
              btfsc     CarryFlag
              incf      PCLATH,Same,Access
              movwf     PCL,Access
;
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_POST2Server
PS_EC_CDT11:  goto      PS_EC_NotImplemented
PS_EC_CDT12:  goto      PS_EC_NotImplemented
PS_EC_CDT13:  goto      PS_EC_OnlyGSM2Respond
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_Details:
;
              call       Response_CommandExecuted
;
              goto       PS_ExecuteCommandEnd
;
PS_EC_POST2Server:
;
              bsf        SendSMS
;
              call       Response_CommandExecuted
;
              goto       PS_ExecuteCommandEnd
;
PS_EC_OnlyGSM2Respond:
;
              call       Response_CommandExecuted ;This line must be commented out on the stand alone rain gauges
                                                  ;- the app uses this to determine if the unit is GSM or stand alone
;
              goto       PS_ExecuteCommandEnd
;
PS_EC_ExternalEE:
;
              movf       POSTINC0,W,Access
              movwf      PacketCommand,Banked
; 
              movf       POSTINC0,W,Access
              movwf      EEAdrsHH,Access
              movf       POSTINC0,W,Access
              movwf      EEAdrsH,Access
              movf       POSTINC0,W,Access
              movwf      EEAdrs,Access
;
              btfsc     PacketCommand,6,Banked
              goto      PS_EC_ExternalEE_Read
;
PS_EC_ExternalEE_Write:
;
              bsf       Power
;
              call      I2C_Delay
;
              call      I2C_Start
              rlcf      EEAdrsHH,W,Access
              andlw     b'00001110'
              iorlw     b'10100000'
              call      I2C_Tx        
              movf      EEAdrsH,W,Access
              call      I2C_Tx
              movf      EEAdrs,W,Access
              call      I2C_Tx
;
PS_EC_ExternalEE_Write1:
;
              movf       POSTINC0,W,Access
              call      I2C_Tx
;
              decfsz     PacketCounter,Same,Banked
              goto       PS_EC_ExternalEE_Write1
;      
              call       I2C_Stop
;    
              call       Delay1msec
              call       Delay1msec
              call       Delay1msec
              call       Delay1msec
              call       Delay1msec
;
              bcf       Power
;
              call      I2C_Delay
;
              call       Response_CommandExecuted 
;
              goto       PS_ExecuteCommandEnd
;
PS_EC_ExternalEE_Read:
;
; Build response in the line buffer
;
              movlw      '#'
              movff      WREG,LineBuffer+0
;
              decf       PacketCounter,W,Banked  ;RESPONSE low nibble
              iorlw      b'10010000'             ;RESPONSE high nibble
              movff      WREG,LineBuffer+1
; 
              lfsr       0,LineBuffer+2
;
              call       OpenExternalEEPROMforReading
;
PS_EC_ExternalEE_Read1:
;
              call       ReadExternalEEPROM
              movwf      POSTINC0,Access
;
              decfsz     PacketCounter,Same,Banked
              goto       PS_EC_ExternalEE_Read1
;
              call       CloseExternalEEPROMforReading
;
              call       Response_AppendChecksum
;
              goto       PS_ExecuteCommandEnd
;
PS_ExecuteCommandEnd:
;
              goto      RestartPacketState
;
RestartPacketState:
;
              clrf      PacketState,Banked
;
              call      FlushSerialReceiveBuffer1
;
              goto      PacketStateDispatcherEnd
;
PacketStateDispatcherEnd:
;
              call      CheckByteSerialBuffer1
              btfsc     CarryFlag
              call      ProcessSerialInput
;
              return
;
Response_CommandExecuted:
;
              movlw     '#'
              call      WriteByteSerialBuffer1
              movlw     b'10001010'
              call      WriteByteSerialBuffer1
              movlw     0x76
              call      WriteByteSerialBuffer1
;
              return
;
Response_AppendChecksum:
;
              lfsr      0,LineBuffer+1
;
              clrf      PacketCounter,Banked     ;Start with 0 bytes
;
              movff     LineBuffer+1,WREG
              swapf     WREG,W,Access            ;See what the multiplier is 
              andlw     b'00000111'
              btfsc     ZeroFlag
              goto      Response_AC_1            ;It is 0, so go 
;
              movwf     LineBufferPointer,Banked
; 
              movff     LineBuffer+1,WREG
              andlw     b'00001111'
              addlw     1
;
Response_AC_Multiply:
;
              addwf     PacketCounter,Same,Banked
;
              decfsz    LineBufferPointer,Same,Banked
              goto      Response_AC_Multiply  
;
Response_AC_1:
;
              addlw     1                      ;Add the RESPONSE byte
              movwf     PacketCounter,Banked
;
              movlw     0
              movwf     Checksum_A,Banked
;
Response_AC_CalculateChecksum:
;
              movf      POSTINC0,W,Access
              addwf     Checksum_A,Same,Banked
;
              decfsz    PacketCounter,Same,Banked
              goto      Response_AC_CalculateChecksum
;
              comf      Checksum_A,W,Banked
              addlw     1
              movwf     POSTINC0,Access
;
              movf      FSR0L,W,Access
              movwf     LineBufferPointer,Banked
              lfsr      1,LineBuffer
;
              bsf       FirstPass
              bcf       ESCape
;
Response_AC_Transmit:
;
              btfss     ESCape
              goto      Response_AC_Transmit1
;
              bcf       ESCape
              movf      POSTINC1,W,Access
              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
              movf      POSTINC1,W,Access
;
Response_AC_TransmitCheck:
;
              call      WriteByteSerialBuffer1
;
              movf      FSR1L,W,Access
              subwf     LineBufferPointer,W,Banked
              btfss     ZeroFlag
              goto      Response_AC_Transmit
;
Response_AC_Transmit_End:
;
              return
;
AccumulateWindSpeed:
;
              bcf       _INT2IF
;
              clrf      T3CON,Access             ;T3 is off
;
              btfsc     Gust_FirstPass
              goto      AccumulateWindSpeed1     ;This is the first pulse, so the result is meaningless, so don't use it!
;
              btfss     _TMR3IF                  
              goto      AccumulateWindSpeed0
              bsf       Gust_FirstPass           ;The timer overflowed, so the result is also meaningless, so don't use it either
              goto      AccumulateWindSpeed2
;
AccumulateWindSpeed0:
;
              movf      TMR3L,W,Access
              subwf     Gust1,W,Banked
              movf      TMR3H,W,Access
              subwfb    Gust1H,W,Banked
;
              btfss     CarryFlag
              goto      AccumulateWindSpeed2
;
              movff     TMR3L,Gust1
              movff     TMR3H,Gust1H
;
              goto      AccumulateWindSpeed2
;
AccumulateWindSpeed1:
;
              bcf       Gust_FirstPass
              goto      AccumulateWindSpeed2
;
AccumulateWindSpeed2:
;
              movff     TMR3L,NewWindSample
              movff     TMR3H,NewWindSampleH
;
              bsf       NewWindSampleFlag
;
              clrf      TMR3H,Access             ;Start from 0
              clrf      TMR3L,Access
;
              bcf       _TMR3IF                  ;If we overflow then the anemometer is going way too slow
;
              movlw     b'01000011'              ;Start TMR3 - 16-bit - Fosc - Pre=1
              movwf     T3CON,Access  
;
              movlw     1
              addwf     WindSpeed1,Same,Banked
              movlw     0
              addwfc    WindSpeed1H,Same,Banked
;
              btfss     CarryFlag
              goto      AccumulateWindSpeed_End
;
              movlw     0xFF
              movwf     WindSpeed1,Banked
              movwf     WindSpeed1H,Banked
;
AccumulateWindSpeed_End:
;
              return
;
SaveSettings_Bulk:
;
              clrf      VerifySettings_State,Banked ;We may have been busy verifying the settings, so make sure we start from the beginning
;
              movlw     EE_ActiveBank
              call      ReadInternalEEPROM
              xorlw     0x5A
              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,Banked
              movlw     0x00
              movwf     EEPROMSequenceBank,Banked
              movlw     0xA5
              movwf     EEPROMNewBank,Banked
; 
              goto      SaveSettings1
; 
SaveSettingsOffsetA5:
;
              movlw     0x00
              movwf     EEPROMSaveBank,Banked
              movlw     0x40
              movwf     EEPROMSequenceBank,Banked
              movlw     0x5A
              movwf     EEPROMNewBank,Banked
;
              goto      SaveSettings1
;
SaveSettings_Donkey: macro EE_Location,NV_Variable
;
              local     SaveSettings_DonkeyOut
;
              movlw     EE_Location
              addwf     EEPROMSaveBank,W,Banked
              call      ReadInternalEEPROM
              subwf     NV_Variable,W,Banked
              btfsc     ZeroFlag
              goto      SaveSettings_DonkeyOut
              movf      NV_Variable,W,Banked
              call      WriteInternalEEPROM
;
SaveSettings_DonkeyOut:
;
              endm
;
SaveSettings1: SaveSettings_Donkey EE_FirmwareYear,FirmwareYear
               SaveSettings_Donkey EE_FirmwareMonth,FirmwareMonth
               SaveSettings_Donkey EE_FirmwareDayTens,FirmwareDayTens
               SaveSettings_Donkey EE_FirmwareDayUnits,FirmwareDayUnits
;
               SaveSettings_Donkey EE_PowerUps,PowerUps
               SaveSettings_Donkey EE_PowerUpsH,PowerUpsH
               SaveSettings_Donkey EE_Connections,Connections
               SaveSettings_Donkey EE_ConnectionsH,ConnectionsH
;
               SaveSettings_Donkey EE_BatteryVoltage,BatteryVoltage
;
               SaveSettings_Donkey EE_LogReadPointer,LogReadPointer
               SaveSettings_Donkey EE_LogReadPointerH,LogReadPointerH
               SaveSettings_Donkey EE_LogReadPointerHH,LogReadPointerHH
;
               SaveSettings_Donkey EE_LogWritePointer,LogWritePointer
               SaveSettings_Donkey EE_LogWritePointerH,LogWritePointerH
               SaveSettings_Donkey EE_LogWritePointerHH,LogWritePointerHH 
;
               SaveSettings_Donkey EE_RainPulse,RainPulse
               SaveSettings_Donkey EE_RainPulseH,RainPulseH
               SaveSettings_Donkey EE_RainPulseHH,RainPulseHH
;
               SaveSettings_Donkey EE_HumidityLo,HumidityLo
               SaveSettings_Donkey EE_HumidityHi,HumidityHi
;
               SaveSettings_Donkey EE_TemperatureLo,TemperatureLo
               SaveSettings_Donkey EE_TemperatureLoH,TemperatureLoH 
               SaveSettings_Donkey EE_TemperatureHi,TemperatureHi
               SaveSettings_Donkey EE_TemperatureHiH,TemperatureHiH 
;
               SaveSettings_Donkey EE_GSMReadPointer,GSMReadPointer
               SaveSettings_Donkey EE_GSMReadPointerH,GSMReadPointerH
               SaveSettings_Donkey EE_GSMReadPointerHH,GSMReadPointerHH
;
               SaveSettings_Donkey EE_Debug1,Debug1
               SaveSettings_Donkey EE_Debug2,Debug2 
               SaveSettings_Donkey EE_Debug3,Debug3 
;
SaveSettingsChangeSequenceNumber:
;
              movlw     EE_SequenceNumber
              addwf     EEPROMSequenceBank,W,Banked
              call      ReadInternalEEPROM
              movwf     EEPROMSequence,Banked
              movlw     EE_SequenceNumber
              addwf     EEPROMSaveBank,W,Banked
              call      ReadInternalEEPROM         ;Dummy read to set address
              incf      EEPROMSequence,Same,Banked
              movlw     0xFF                       ;0xFF is not a valid sequence number, because it is the value of erased EEPROM memory
              xorwf     EEPROMSequence,W,Banked
              btfsc     ZeroFlag
              incf      EEPROMSequence,Same,Banked ;So increment 0xFF to become 0x00
              movf      EEPROMSequence,W,Banked
              call      WriteInternalEEPROM
;
SaveSettingsSwitchActiveBank:
;
              movlw     EE_ActiveBank
              call      ReadInternalEEPROM         ;Dummy read to set address
              movf      EEPROMNewBank,W,Banked
              call      WriteInternalEEPROM
;
SaveSettingsOut:
;
              return
;
PopulateRainTickCompensationTable:
;
              lfsr      0,RainTickCompensationTable
;
PopulateRTCT1:
;
              movf      FSR0L,W,Access
              addlw     0xC0
              call      ReadInternalEEPROM
              movwf     POSTINC0,Access
;
              btfss     FSR0L,6,Access           ;Have we reached the end of the table? 
              goto      PopulateRTCT1
;
              return
;
RestoreSettings_Bulk:
;
; Restore settings from non-volatile memory
;
              movlw     EE_ActiveBank
              call      ReadInternalEEPROM
              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
              movwf     EEPROMBank0Sequence,Banked
;               
              movlw     EE_SequenceNumber
              addlw     0x40
              call      ReadInternalEEPROM
              movwf     EEPROMBank1Sequence,Banked
;
              movlw     0xFF
              xorwf     EEPROMBank0Sequence,W,Banked
              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,W,Banked
              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,W,Banked
              btfsc     ZeroFlag
              goto      RestoreSettingsIsBank1GreaterOrSmaller
;
              movlw     0xFE
              xorwf     EEPROMBank1Sequence,W,Banked
              btfsc     ZeroFlag
              goto      RestoreSettingsIsBank0GreaterOrSmaller
; 
              movf      EEPROMBank0Sequence,W,Banked
              subwf     EEPROMBank1Sequence,W,Banked
              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,W,Banked
              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,W,Banked
              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
              addwf     EEPROMRestoreBank,W,Banked
              call      ReadInternalEEPROM
              movwf     NV_Variable
;            
              endm
;
RestoreSettings1:
;
              movwf     EEPROMRestoreBank,Banked
;
              RestoreSettings_Donkey EE_FirmwareYear,FirmwareYear
              RestoreSettings_Donkey EE_FirmwareMonth,FirmwareMonth
              RestoreSettings_Donkey EE_FirmwareDayTens,FirmwareDayTens
              RestoreSettings_Donkey EE_FirmwareDayUnits,FirmwareDayUnits
;
              RestoreSettings_Donkey EE_PowerUps,PowerUps
              RestoreSettings_Donkey EE_PowerUpsH,PowerUpsH
              RestoreSettings_Donkey EE_Connections,Connections
              RestoreSettings_Donkey EE_ConnectionsH,ConnectionsH
;
              RestoreSettings_Donkey EE_BatteryVoltage,BatteryVoltage
;
              RestoreSettings_Donkey EE_LogReadPointer,LogReadPointer
              RestoreSettings_Donkey EE_LogReadPointerH,LogReadPointerH
              RestoreSettings_Donkey EE_LogReadPointerHH,LogReadPointerHH
;
              RestoreSettings_Donkey EE_LogWritePointer,LogWritePointer
              RestoreSettings_Donkey EE_LogWritePointerH,LogWritePointerH
              RestoreSettings_Donkey EE_LogWritePointerHH,LogWritePointerHH 
;
              RestoreSettings_Donkey EE_RainPulse,RainPulse
              RestoreSettings_Donkey EE_RainPulseH,RainPulseH
              RestoreSettings_Donkey EE_RainPulseHH,RainPulseHH
;
              RestoreSettings_Donkey EE_HumidityLo,HumidityLo
              RestoreSettings_Donkey EE_HumidityHi,HumidityHi
;
              RestoreSettings_Donkey EE_TemperatureLo,TemperatureLo
              RestoreSettings_Donkey EE_TemperatureLoH,TemperatureLoH 
              RestoreSettings_Donkey EE_TemperatureHi,TemperatureHi
              RestoreSettings_Donkey EE_TemperatureHiH,TemperatureHiH 
;
              RestoreSettings_Donkey EE_GSMReadPointer,GSMReadPointer
              RestoreSettings_Donkey EE_GSMReadPointerH,GSMReadPointerH
              RestoreSettings_Donkey EE_GSMReadPointerHH,GSMReadPointerHH
;
              RestoreSettings_Donkey EE_Debug1,Debug1
              RestoreSettings_Donkey EE_Debug2,Debug2
              RestoreSettings_Donkey EE_Debug3,Debug3
;
              return
;
	      MESSG "<<<<<<<<<<<<<<<   C U S T O M I S A T I O N   R E P O R T   >>>>>>>>>>>>>>>"
;
        IFDEF BuildForProgrammer
              MESSG "*** To program the flow controller use this hex file with a programmer ***" 
        ELSE
           IFDEF BuildForBootLoader
              MESSG "*** To program the flow controller use this hex file with the boot loader ***"
           ELSE 
              ERROR "*** Select either BuildForProgrammer or BuildForBootLoader ***"
           ENDIF
        ENDIF
;
          ;    org       0xFD00-2
          ;    dw        0xFACE ;Sounds like SPACE for the image checksum
;
              END
