;******************************************************************************
;*                                                                            
;* TITLE: Valve Controller for Liquid Fertilser Applicator for PreMac                          
;*                                                                            
;* AUTHOR: Robert Farrer for PreMac         
;*     
;*     ===================     
;*     
;*     How to build this package: 
;*     
;*        1. Assemble
;*        2. In the Program Memory window export CC.MCH from 0x0000 to 0x3FFC
;*        3. Run MCHG128-LB       
;*        4. Re-assemble
;*        5. Program chip
;*        6. Copy CCMain.INC to the MainUnit directory for inclusion in the MainUnit
;*     
;*     ===================     
;*                  
;*     ===================     
;*     
;*     Known issues - G602
;*                  
;*                  - G602 - Implement signed numbers in the median filter
;*                  
;*     ===================     
;*     
;*     Known issues - F417
;*                  
;*                  - F417 - Clarify how internal faults in the UFO2 are reported to us
;*                  
;*     ===================     
;*     
;*     Known issues - F319 
;*                  
;*                  - F319 - Averaging code can be improved by using all 10 samples instead of only 8 and
;*                           then eliminating the highest and lowest sample in the list - FLOW and ADC
;*                           - This may be redundant since G602 implemented the median filter, but it may
;*                             become relevant again if we switch back to the averaging filter again
;*     
;*     ===================     
;*     
;*     
;*     
;*          7   6        5       4  3  2       1      0
;*          O   O        A       I  A  A       I      O 
;*        Osc Osc Pressure GSM_Net M1 M0 GSM_Run GSM_On
;* TRISA    0   0        1       1  1  1       1      0
;* LATA     0   0        0       0  0  0       0      0
;* ANSELA   0   0        1       0  1  1       0      0 
;*
;*          7   6          5   4    3            2          1           0    
;*          I   O          O   O    O            I          I           O
;*         Rx  Tx Reset_5984 Dir Step Speed_Engage Flow_Meter Fault_Relay
;* TRISB    1   0          0   0    0            1          1           0
;* LATB     0   1          0   0    0            0          0           0
;* ANSELB   0   0          0   0    0            0          0           0
;*
;*             7      6      5   4   3       2         1       0
;*             I      O      I   I   I       O         O       O
;*        GSM_Rx GSM_Tx Limits SDA SCL GSM_DTR Green_LED Red_LED 
;* TRISC       1      0      1   1   1       0         0       0
;* LATC        0      1      0   0   0       0         0       0
;* ANSELC      0      0      0   0   0       0         0       0
;*     
;*     
;*     
;*     
;* 
;* 
;* 
;* 
;* 
;* 20(24)/(10)/(29) - OA29
;*                  - Bump up version number = 4 places
;*                  - The new SET key functionality seems to have broken the spinner in AUTOMATIC and MANUAL
;*                    - The problem is only in AUTOMATIC 
;*                    - This fix should also reolve the SMS issue
;*
;*
;*
;*
;*
;*
;*
;*
;*
;*                  - Release this version to Danny for the prototype field test
;*
;*
;*                     
;*                    - Menu function to enter alert SMS telephone number
;*                    - Send the following alerts:
;*                      - Power up
;*                      - No flow
;*                      - Flow error more than x%, (25%?)
;*
;*                  - Enable the fault relay by SMS for systems which have the unit powered separately from the pump
;* 
;*
;*  idle
;*  check for cell module
;*  echo off
;*  select text mode
;*  checkforsms
;*
;* 
;*
;* 
;* 20(24)/(10)/(22) - OA22
;*                  - Add AlertNumber to settings and also the code to restore and save it
;*                  - The flag for enabling alerts will be stored in the non-volatile file register, so it doesn't need any special attention
;*                  - Decide on how the menu to edit the alert setting and number is going to look
;*                    - What it looks like is decided, but there is no code for it yet in the menu structure
;*                  - Extend number of states possible in the menu structure
;*                  - Fix up the open and close keys translation from the keypad to the buttons on the PCB 
;*                  - Check the way the SMS pin is defined in the EEPROM to the EEPROM labels and the variabless taht they all tie up, because somewhere the SMS pin gets reversed
;*                  - Add key down functionality when editing
;*                  - Make sure the manual overide functionality can't mess editing around and the other way around
;*                  - Also add a menu time out, so that if keys stop being pressed then the menu will time out 
;*                    - If it does time out then perform a reset, so that the original settings get reloaded, in case they are partially edited               
;*                  - The network sometimes delays the delivery of the SMSes, to try and hurry it up, cycle the GSM power very 30 read attempts, (about 7 minutes) 
;*                  - ZIP file is to here
;*                  - Report mode and fault relay in SMS   
;*                  - If the closed limit is not made and there is zero flow then do not adjust the valve
;*                  - Change the error for high and low speed adjustement of the valve to 100
;*                  - Change the number of steps in high speed adjustment from 5 to 25
;*                  - Enable the fault relay from the SET button for systems which have the unit powered separately from the pump
;*
;* 20(24)/(10)/(21) - OA21
;*                  - Remove the fancy real time EEPROM refresh that this code inherrited from the rain gauge, which isn't currently working, and isn't necessary in this applicaation
;*                    - Add code at the end of the menu to save the settings to the EEPROM
;*                    - Verify that there is code in the beginning which restores the settings from the EEPROM
;*                    - Add defaults to the EEPROM for programming
;*                    - Package and send to Danny for testing
;*
;* 20(24)/(10)/(17) - OA17
;*                  - Work through the SMS state machine, I suspect that the IdleState may be causing the issue because it isn't powering down the modem and simply keeps retrying
;*                    - I don't need to re-invent the wheel here, I just need to understand how hte bus sign code works and then do the same thing 
;*                      - This code was a mix of server and SMS code and the linking in the state machine had been hacked to get the code going
;*                        - The biggest issue is that there was a state X_GSM)ModuleOffDone that was linked in and it had no code populated, so the GSM statemachine just ended up hanging here!!! 
;*                  - Add the alerts SMS functionality Danny and Leon want:
;*                    - Menu function to enter alert SMS telephone number
;*                      - Add this to the menu, but at the same time allow the user to skip over the SMS setup in order to keep the menu more user friendly no that the options are increasing
;*                      - This was an opportune time for Danny to give me the new PCB, because the menu switches work and I can incorporate them into the new code, instead of the membrance keypad
;*                        - MENU is the old calibrate open
;*                        - DOWN is the old manual?
;*                        - UP   is the old calibrate close 
;*                        - SET  is the old manual? 
;* 
;* 20(24)/(10)/(10) - OA10
;*                  - Pick up where I left off last week and carry on coding the interpretation of the received SMS   
;*                    - Interpret the received SMS
;*                    - Generate a fixed text reply
;*                      - This is working, but the code to delete the SMSes isn't working, so the unit just keeps reading the same SMS over and over again 
;*                        and sending me a reply
;*                      - Figure out where the deleting code is different between the Siemens and the SIM800  
;*                        - Now the SMS is deleted after interpretation
;*                    - Add in the flow to the reply SMS  
;*                  - Danny wants to send out a prototype for field testing 
;*                    - Check the flow calibration on the test bench
;*                      - Fine tune 
;*                    - The SMS code struggles to send a reply when the system is working on the test bench, but it manages to send replies
;*                      when I use the flowmeter simulator on my desk!
;* 
;* 20(24)/(10)/(03) - OA03
;*                  - The following SMS flow has been decided on for now: 
;*
;*                       Status SMS:
;* 
;*                        CurrentFlow RequiredFlow NORMAL RemaingSMSes ExpiryDate SoftwareVersion
;*                                                 FAULT
;* 
;*                        eg: 1000 of 1100 lph NORMAL 58 2024/10/16 OA03
;* 
;* 
;*                        When the unit receives an SMS with a valid pin it will reply with the unit status to that number
;* 
;*                           PPPP
;*                           PPPP RequiredFlow
;                       *    PPPP RequiredFlow RemainingSMSes 
;*                           PPPP RequiredFlow RemainingSMSes ExpiryDate
;* 
;*                        At power up the unit will send the unit status to the default number entered into the unit
;* 
;*                       If the flow stops, (no liquid?), then the unit will send the unit status to the default number entered into the unit
;*                    - Carry on coding the interpretation of the received SMS
;*                  - My day was interrupted, so in the end nothing happened 
;* 
;* 20(24)/(09)/(19) - O926
;*                  - Use the GSM comms sniffer to figure out how to read the SMSes with the SIM800C, because it is different to the Siemens GSM module the code is based on  
;*
;*                    +cmgr;*                                                                        
;*                    ERROR
;*                                                                                
;*                    +CMTI: "ME",30
;*
;*                    at+cnmi=0
;*   
;*                    at+cmgl="ALL"
;*                    at+cmgr=index number
;*                    at+cmgd=index number
;*
;*                    +cmgl="all";*                                                                  
;*                    +CMGL: 21,"REC READ","+27825105782","","24/09/19,16:01:20+08"
;*                 
;*                    1234: 1200 auto fault
;*                                                       
;*                    +CMGL: 30,"REC READ","+27825105782","","24/09/26,09:40:44+08"
;                 
;*                    1234: 1200 auto fault
;*                                                       
;*                    OK
;*
;*                  - Now that we know how to read the SMSes manually, bring up the SMS code
;*                  - Verify this format for the SMS with Danny before I  commit to writing the parser for it 
;*
;*                    REQUEST SMS:
;*                       PPPP?
;*                       PPPP 1200
;*     
;*                    RESPONSE SMS:
;*                       FFFFF SSSSS MODE VERSION
;*
;*                  - Add code to ProcessEEPROM to store the SMS password
;*     
;* 20(24)/(09)/(19) - O919
;*                  - Resolve the RS232 routine issues between the code this was based on and the code the GSM routines were copied from
;*                    - Find a project with more fleshed out GSM code for handling the SMSes and then use that codes RS232 engine
;*                      - Resolve variable paging issues
;*                      - I now make it all the way to the network registration
;*                  - Bring in the additional SMS routines that are needed in order to interpret and reply to the SMSes the unit receives
;*                    - That's too much code with too many errors     
;*                    - Roll back and do it bit by bit rather, otherwise I am going to become demoralised!
;*                  - Get a SIM from Danny
;*                    - The number is 076-866-6221
;*                  - See if the module registers on the network
;*     
;* 20(24)/(09)/(12) - O912
;*                  - Carry on with the 3 times per second screen refresh mod I started last week
;*                    - Hook up the pulse simulator and verify that it wants to work, even though any effect of the additional filtering will only be seen on the test bench
;*                    - Revise the NoFlowTimeOut to match the expected minimum flow rate better, so that the screen zeroes crisply
;*                    - Copy over the code from the Automatic state to the Manual state
;*                      - Test manual mod with the simulator                     
;*                  - See why manual mode time out takes soooo long, it isn't 2s as intended  
;*                    - The time constant was set in 1msec increments instead of 5msec increments
;*                  - Add a heartbeat to the display, so that the user gets the feeling that something is happening, even if the numbers are standing still by some chance
;*                  - Danny soldered up some new LCDs and the backlights flash at power up, but don't stay on    
;*                    - Identify the correct bit in the code and make sure the backlight gets switched on in future
;*                  - Save a restore point 0912a
;*                  - Swap resistor and cap on GSM board       
;*                  - Jumper missing relay to power the modem 
;*                  - See if we get past the power up code in the GSM state machine
;*                    - Stuck waiting for a time out
;*                      - The interrupt code to run the GSM timer wasn't brought in with the rest of the package
;*                    - It is powering up and getting to the point where is wants to communicate with the module
;*                      - Now I need to confirm baud rates, comms buffers, etc
;*                  - Test the filtering software on the test bench 
;*                    - The numbers still walk around, but not as alarmingly
;*                    - Capture some flows on automatic:
;*                      - Setpoint  300 22.43s for 2l =  320 lph - reverse out 23 571 988 / 320 = 71430 0001 0001 0011 0001 1110
;*                      - Setpoint  600 12.48s for 2l =  576 lph                                = 40923 0000 1001 1111 1101 1011
;*                      - Setpoint  778 10.49s for 2l =  686 lph                                = 34361 0000 1000 0110 0011 1001
;*                      - Setpoint 1300  6.57s for 2l = 1095 lph                                = 21256 0000 0101 0011 0000 1000
;*                      - Setpoint 1300  6.55s for 2l = 1099 lph
;*                    - Switch to manual and re-adjust 1300 and capture a bigger amount:
;*                      - Process variable about 1300, (from 1280 to 1320) 17.94s for 5l = 1003 = 23501
;*                        - I am surprised that this one is so much lower than the automatic
;*                          - And if I calculate the flow then backwards it works out to 7.17s which is around 0.6s longer which is a lot of time, so I don't think it is that     
;*                    - The errors are not linear, so we are going to have to figure out what to do!
;*                  - Carry on bringing up the GSM code                   
;*                    - REMEMBER to check out the SendSMS flag at the end of the day, because I am crippling it in a few places to get the module to power up
;*                    - The table reads from program memory are different on this device to the one the code was copied from
;*                      - That is not the problem! The problem is that the fertiliser comms uses 9-bit data, so it needs 2 bytes in the buffer, but the GSM code is only 8-bit data
;*                        and expecting to only use 1 byte
;*     
;* 20(24)/(09)/(05) - O905
;*                  - After giving the flow meter issues we saw last week some thought, I would like to try it with the occassional missed pulse,
;*                    because that should result in a low flow value, which should be filtered out by the median filter
;*                  - Danny has also skimmed the housing to give the ball a little bit more height clearance, to make sure it isn't sticking on the wave guide  
;*                  - For this test remove the call to ProcessEEPROM, just to make sure that everything flows as smoothly as possible
;*                  - Gathered this information from the test bench:      
;*                    17s 1 litre 300-335msec per pulse 211 l/H     315msec per pulse 
;*                    5.87 1 litre 468-492msec for 5 pulses 613 l/H  96msec per pulse
;*                    6.34 2 litre 525msec for 10 pulses 1135 l/H    52msec per pulse
;*                    4.4 2 litre 546msec for 15 pulses 1636 l/H     36msec per pulse
;*                  - By trial and error worked out that 37msec = 1818 l/h
;*                  - Use another PCB to generate pulses:
;*                    - When the pulse timer overflows the maths is incorrect because we are only using 18 out of 24 bits
;*                      - Resolved     
;*                  - Add code to zero the flow when the pulses stop 
;*                  - Test on the bench again 
;*                    - Very very happy with this result
;*                  - Can't seem to edit the setpoint
;*                    - Debug in the office 
;*                      - Now it doesn't do it
;*                      - It's related to the pulses    
;*                        - It's because of the DebugComms sending the flow and trashing the BCD registers the editing code is using 
;*                 - Put back the ProcessEEPROM call in the main program loop
;*                 - Other than filtering the display some more, this looks very good
;*                   - Save a restore point 0905A
;*                 - Decide on an additional filtering strategy for the display
;*                   - If it is based on the number of pulses received then it will be very slow at low flow rates and maybe too lively at high flow rates
;*                     - 37msec * 64 = 2.3s
;*                     - 300msec * 64 = 20s 
;*                   - I wonder if I can step it based on the setpoint     
;*                     -  200 l/h /25 =  8 x300msec = 2.4s
;*                     - 1800 l/h /25 = 72 x 37msec = 2.66s
;*                    - But dividing by 25 is slow, so let's try 32
;*                     -  200 l/h /32 =  6 x300msec = 1.8s
;*                     - 1800 l/h /32 = 56 x 37msec = 2.07s
;*                   - We currently refresh the LCD every 25 x5msec = 125msec with is 8 times a second
;*                     - Let's use a multimeter as a guidline and go with 3 times a second
;*                       - And then let's accumulate samples over that period
;*                         - And if the accumulated value is 0 then we will use the current value of the FlowProcessVariable
;*                         - Add an accumulator and a counter
;*     
;* 20(24)/(08)/(29) - O829
;*                  - Modify PCB to match new circuit to make the limit switches independent and identifiable
;*                  - Update the code to identify the individual limit switches 
;*                    - Change RC5 to analogue
;*                    - Measure the various limit switch voltages  
;*                    - Write the code to differentiate the lmit switches 
;*                    - Debounce them
;*                  - Change the motor routine to look at the individual limit switches instead of the single combined input 
;*                    - Remove all the unnecessary release code
;*                  - Test the assembly to see that the motor does stop when the limits are reached
;*                  - Modify a second PCB
;*                  - There is a new valve so let's test it with a pump to see if we can control the flow any better
;*                    - The range of control is much bigger, so that is good     
;*                    - The maximum flow through the valve is 13.8 litres in 30s = 1656 litres per hour
;*                    - The pulses I am capturing are not consistent
;*                      - Check that the code I have added recently hasn't interfered with the speed interrupts
;*                        - No it seems to be a flow meter issue if we look with the scope
;*                          - Changing the ball size made a difference, but it still skips the occassional pulse   
;*     
;* 20(24)/(08)/(22) - O823
;*                  - The GSM code is ready for testing, but the PCB is not ready yet, so I have rolled forward in case I have issues
;*                    with the code I continue with, then at least I can roll back to the point where I am just debugging the added
;*                    cell module code 
;*                  - Think about what the SMS request is going to look like and how I am going to interpret it 
;*
;*                    REQUEST SMS:
;*                       PPPP FFFFF MODE FAULT PPPP pppp pppp      
;*                                                               
;*                                                  pppp pppp = new password which must match for change to be accepted  
;*                                                              (This password may be any characters, unlike the password
;*                                                               set on the unit which can only be numerical) 
;*                                             PPPP = current password, only rquired to change to a new password 
;*                                       FAULT = ENABLE or DISABLE
;*                                  MODE = AUTOMATIC or MANUAL 
;*                            FFFFF = Flow setpoint in l/H
;*                       PPPP = current password
;*     
;*                    RESPONSE SMS:
;*                       Flow=FFFFFl/H MODE=MMMMM FAULT=FFFFF (new password is pppp) Version=YDMM
;*     
;*                  - Add SMS password to the menu, so that it can always be recovered by the person who has access to the physical unit
;*             
;* 20(24)/(08)/(22) - O822
;*                  - When we started the rain gauge it was going to be an SMS unit before it migrated to GPRS,
;*                    so import the SMS code we started there and get it to a point were it compiles, so I can
;*                    continue with it for the Center Pivot Flow Controller
;*     
;* 20(24)/(08)/(01) - O801
;*                  - Test new flow guides to see if we can measure the lower flows
;*                    - The flow guide seems to produce a good flash on the proxy but the numbers are all over the place
;*                      - Using the debugger I can confirm that the pulses are reasonable, unlike the numbers!
;*                        - Debug on desk
;*                          - Defining the GoldenNumber from the MSB first instead of the LSB
;*                    - The numbers are now much more stable and consistent
;*                      - 13s for 2 litres with a flow of 200 on the screen
;*                      - 60/13*2 = 9.375 l/m * 60 = 562 l/H
;*                        - So scale up the GoldenNumber = 0x800000*562/200 = 0x0167AE14
;*                      - Reprogram and check again
;*                        - 13.5s for 2 l with reading 520 is 533 l/H
;*                        - 6.48s for 2 l with reading 1230 is 1111 l/H
;*                        - 9.3s for 2 l with reading 750 is 774 l/H
;*                          - Consistently a little low, but for now I am happy with this
;*                    - Also check that we can achieve our maximum flow rate of 1000l/H
;*                      - Captured 1440 l/H, so yes the flow meter does allow 1000 l/H through 
;*                    - Enable automatic mode and see if the valve can control the flow
;*                      - Yes, it wants to work but the valve is a bit too big, so the control range is very small
;*                      - If I change the SetPoint the valve does however try to track it
;*                  - Store non-volatile variables in EEPROM
;*                    - SetPoint 
;*                    - ModeSelect
;*                    - FaultRelay
;*                      - Automatic Disable & 12345 - works across power cycles 
;*                      - Automatic Enable  & 53567 - works
;*                      -    Manual Enable  & 06789 - works
;*                      -    Manual Disable & 13691 - works
;*                    - There is no double buffering implemented yet, so if it gets powered down while writing to the EEPROM then the non-volatile memory can be corrupted
;*                    - Add code to flip the fault relay if there is no flow for 2s
;*                      - And display a message     
;*     
;* 20(24)/(07)/(25) - O725
;*                  - We have new flow meter plastic, so let's test to see if it wants to work     
;*                    - Very happy to say it does :-)
;*                  - Add a setting to switch to manual mode
;*                  - Now check the ManualMode flag to determine system operation     
;*                  - Add a setting too enable/disable the fault relay 
;*                  - Also tes the new plastics and try calibrating
;*                    - Only to find out that our idea of the required flow was way too high
;*                    - The precision planting flow meter is too small it limits the flow to 600l/H and we need to reach 1000l/H
;*                    - The flows don't really mean anything, because we are changing the core of the impeller for the 1 inch system, but derive a new golden number anyway for the next round
;*     
;* 20(24)/(07)/(11) - O6711
;*                  - It is now at the stage where it is meaningful to track the versions
;*                  - So far I have taken an old version of the precision planting flow controller, (GB24), and
;*                    converted it for this center pivot application
;*                    - Add in code for the I2C interface and start implementing a menu
;*                    - Add in code to manually adjust the valve open and closed
;*                    - Add code to display the flow rate whenever it isn't in the menu
;*                    - Add in code for the limit switches
;*                      - Resolve the issue that having a single input for 2 limits switches poses
;*                  - Today we have all the bits and pieces we need to start wet testing
;*                  - Initially let's keep the system in manual mode by preventing the OverRideTimer from decrementing:
;*                    - Firstly we can manually confirm that we can control the flow with the valve
;*                    - Secondly we can catch water 
;*     
;**************************************************************************************************     
;*     
;* 20(16)/(11)/(24) - GB24 - Bump up the version number
;*                           - But keep it at GB17 for debugging and only update it once we are running
;*                  - Enable the median filter and show Danny
;*                    - Increase the filter size from 7 to 9
;*                      - Remembered to change the position in the filter which we read from as well :-)
;*                  - Danny is happy with this and wants to release it      
;*                  - Bump up the version number and build a package
;*     
;* 20(16)/(11)/(17) - GB17 - Bump up the version number
;*                           - But keep it at GB16 for debugging and only update it once we are running
;*                  - Used my own context preservation for the high priority interrupts 
;*                    - Still there 
;*                  - Modernised Add40 and Sub40
;*                  - Verified Mul40 and Div40
;*                    - Removed Div40 and used shifting to divide 
;*                      - Still there, so I know it isn't the multiply
;*                  - Seems to be the FlowCompensation from the main unit which is fluctuating instead of being 100
;*                    - Send to the debug port
;*                      - Yes, whenever the flow is wrong this value is not 100 
;*                        - Chat to Danny about hard coding it
;*                          - He is happy, so lets finalise this package   
;*                  - Bump up the version number and build a package
;*     
;* 20(16)/(11)/(16) - GB16 - Bump up the version number
;*                           - But keep it at GB14 for debugging and only update it once we are running
;*                  - Danny has captured some interesting data from the slave debug port in the field, so use it
;*                    to try and simulate the problem here on my desk, to narrow down where the error could be
;*                    - Let's try with data from capture36.txt which Danny sent me
;*                      - First let's run it through Open Office Calc
;*                        - Pretty much it looks good, I can't match the figures 100% because when the
;*                          headings are printed then the data isn't, but they correspond
;*                      - OK, let's step through the maths
;*                        - It matches my spreadsheet
;*                        - Set a breakpoint and see if the lower value pops up on the debugger
;*                          - No such luck
;*                    - See if there are any overlaps in the memory pages and check bank selection  
;*                      - Also check interrupt context preservation code
;*                        - OK, so I found some interesting stuff here, but it has more to do with 
;*                          interference between the re-flashing code and the speed pick-up than with anything
;*                          to do with FlowProcessVariable     
;*                          - In the low priority interrupt when receiving the new slave image, the BSR gets loaded
;*                            with 0 when we want to program the block into the program flash, but the high priority
;*                            interrupts are still active and are expecting it to be 1!
;*                            - The high priority interrupts use the fast return stack for context preservation, which
;*                              saves W, STATUS and BSR - so I could make BSR 1 when I enter the high priority interrupt
;*                              and the RETFIE FAST will restore it appropriately from the fast return stack
;*                          - ProcessTimer3 is called from both the low and high priority interrupts
;*                            - Let's rather make TMR3 a high priority timer
;*                          - As far as I can see the TBLPTR and TABLAT shouldn't need to be preserved and PRODL
;*                            and PRDOH are not used by the program, but let's add them to the low priority
;*                            interrupt context preservation - also add in FSR0 just in case!
;*                    - Use the simulator to manual enter the flow meter readings with the sample aging code running
;*                      - The samples age correctly and the new samples are correctly inserted in the list and the
;*                        average is calculated and calibrated correctly
;*                    - Repair the way we report the new sample in the debug window
;*                      - Try displaying the heading as well as the debug data, so that we don't have any holes    
;*                    - Pin the low priority interrupt independently of the high priority interrupt
;*                  - Bump up the version number and build a package
;*     
;* 20(16)/(11)/(12) - GB14 - Bump up the version number
;*                  - I already report GB13 in GB02, because of the maths issues, so let's roll forward to Monday and use GB14
;*                    - But keep it at GB13 for debugging and only update it once we are running
;*                  - So the problem stems from a few things:  
;*                    - I am substituting 0 for negative readings, which is fine if we get a few every now and again, but
;*                      if we get a few in a row chucking away 1 low doesn't solve the problem, so rather just ignore
;*                      negative readings completely while we are controlling the flow
;*                    - The negative readings only seem to occur on our side and not on the UFO2 side
;*                      - They arise from some kind of I2C somms issue, but the I2C error flag is set 
;*                        - Add in a retry counter and then ignore
;*                          - If the error is long term it is already reported to the main unit and will be displayed
;*                            on the screen
;*                    - We settled on the averaging filter and are happy with the results
;*                  - Bump up the version number and build a package
;*     
;* 20(16)/(11)/(11) - GB11
;*                  - Danny has found problems on site and needs a quick fix, so keep the version number the same
;*                    -  Change FilterSize from 7 to 10, which I didn't do when swapping from the median filter to the averaging filter
;*                    - While checking the code I saw that Flow9 wasn't initialised
;*                  - That made no difference!
;*                  - GB12
;*                    - I can't see anything else, so switch filtering off
;*
;*     
;* 20(16)/(11)/(02) - GB02 - Bump up the version number
;*                  - The units in the field are sporadically hunting 
;*                    - When I monitor the packets at the slave, I notice that the flags sometimes change from 1 to 0
;*                      - I suspect that the valve is trying to open and close in response to these changes
;*                    - I think that the packets intended for the hub are confusing the slaves   
;*                      - Add code to ignore packets intended for the hub, (just like we ignore packets intended for the master)
;*                  - Let's put this code in the slave and then go to the main unit and make the necessary changes there  
;*                  - Make a PICkit3 image now that it is tested
;*                  - The Slaves don't want to upgrade from the Main Unit
;*                    - Turns out the high and low bytes of the minimum and current version are swapped around, so
;*                      0B02 ends up being less than 0713 => 020B < 1307!!!
;*                      - This has to do with how we build and read the MinimumVersionNumber and CurrentVersionNumber
;*                        and not how it is reported to the Main Unit, so to fix it I can leave it as GB02 for reporting to
;*                        the Main Unit and implement the following:
;*                        - In this upgrade:
;*                          - Swap the MinimumVersionNumber around in preparation for next time
;*                          - Force the CurrentVersionNumber so that the maths passes now
;*                        - In the next upgrade
;*                          - Swap the CurrentVersionNumber around so that the maths works, (the reason I couldn't
;*                            just swap the maths around is that it is in the bootloader which can only be changed 
;*                            by programming!!!)
;*                    - I will have to match the version numbers, because the main unit ties them together!!!
;*                      - So the file will be GB02, but the screen will report GB13
;*                    - The problem now is that the re-mapped interrupt routines have moved, which means the
;*                      Checksum is now failing, I am going to have to ORG these routines and shuffle code around 
;*                      them in the future
;*     
;* 20(16)/(07)/(13) - Bump up the version number
;*                  - Known issues:
;*                    - G428 - While working on the hub I noticed that sometimes the address is invalid, but later in the
;*                             packet a valid address arrives, but it gets thrown away because I don't re-synchronise the
;*                             packet - I suspect that I may be doing the same thing in this code, so it may be worth checking
;*                             - This code checks every byte received to see if it is an address, so it is already taken care of 
;*                  - Make sure we have a version which reliably updates from the Main Unit
;*                    - Take out the line which bypasses the re-flashing  
;*                  - Comment out the include, so that we can get a valid build  
;*                    - Check CC.INC  
;*                      - It has too many lines, so delete it and then generate it again 
;*                      - Now it has the correct number of lines
;*                  - I have old versions which aren't compatible with the new responses for the hub, so add in a check to see that 
;*                    the minimum version which can upgrade is G713
;*                  - Let's build and test these changes 
;*                    - I think there is a bug in the Liberty Basic code, because sometimes CC.INC contains too many lines, 
;*                      but CC.MCH is the correct length  
;*                      - Can't see anything, so let's leave this for now and keep an eye on it
;*                    - In the middle of the upgrading the micro seems to be reset, see how I can figure out where that 
;*                      is happening
;*                      - The recovery to the existing firmware was testing the Checksum bytes the wrong way around
;*                      - Figure out why the red LED is flashing - it doesn't make sense to me 
;*                        - It is being switched on in PokedInTheEye, but how is it getting there while the main unit is still busy 
;*                          sending over the firmware
;*                      - PacketCounter is BANKED, but with BSR=1, in the InternalFlash code BSR=0, so who knows what we are using
;*                        to count how many bytes there are in the packet we are busy copying to flash!!!
;*                        - Regenrate the include files and let's try that 
;*                          - On the debugger I just just get green flashing lights now :-)
;*                  - Let's put this code in the slave and then go to the main unit and make the necessary changes there  
;*                  - Make a PICkit3 image now that it is tested
;*     
;* 20(16)/(07)/(06) - Bump up the version number
;*                  - Figure out why I am not seeing the data going out of the slave to the hub? - it is in the buffer
;*     
;* 20(16)/(06)/(23) - Bump up the version number
;*                  - Implement latest changes to the communication specification to allow the hub to assign an address to the slave
;*                    - Add EE_AssignedValveNumber and AssignedValveNumber and the code to restore the variable and refresh
;*                      the EEPROM if the variable is manipulated
;*                    - Bring up the EEPROM section of the communication code
;*                      - This is sort of a clone of the RAM code because we will write to the non-volatile variable and the
;*                        rest of the code will ensure that the EEPROM gets updated in due course
;*                    - Decide if we are testing the existing command correctly
;*                      - Yes, I am
;*                    - Implement the other commands  
;*                    - I forgot to check UseAssignedAddress flag to decide which address to use for accepting packets
;*     
;* 20(16)/(06)/(09) - Bump up the version number
;*                  - Implement the changes to the packet responses as per "Serial Protocol for Agrigel - G609" 
;*                  - Build file for main unit and allow it to upgrade the slaves, (which may require accepting both
;*                    kinds of packet responses)
;*     
;* 20(16)/(06)/(08) - Carry on seeing why the main unit keeps wanting to upgrade the slave
;*                    - Because this code is so full of errors, I don't know how I passed it as functional!!!
;*                      - Address testing was wrong
;*                      - Data high and low bytes switched around
;*                      - Plus, I have to remember to build CC.INC on every iteration, otherwise that causes
;*                        its own set of crocodiles!
;*                      - So until next time, I am calling the slave re-flasher released!
;*     
;* 20(16)/(06)/(02) - Leave the version for reporting over the comms port, otherwise I need to update the main unit 
;*                  - Change the way I filter the flow:
;*                    - Play with various filtering options
;*                      - I had an idea for a fast median filter let's see if it actually is fast!!!
;*                        - Worst case it is roughly the same as my 10-Hi-Lo averaging code I had in here, so 
;*                          for a Median filter it is fast
;*                  - Make the version reporting on the debug port work automatically from the version constants
;*                  - Put back the bootloading section of the code
;*                  - This debugging was based of G217, so merge in G428 
;*                  - Build for release as G602
;*                  - The main unit keeps wanting to upgrade the slave, so try to figure out why that is  
;*     
;* 20(16)/(06)/(01) - Leave the version for reporting over the comms port, otherwise I need to update the main unit 
;*                  - Change the way I filter the flow:
;*                    - If we are controlling the flow we want to throw any negative values away
;*                    - If we are not controlling the flow we can zero the negative values  
;*                    - Report the flow from the UFO2 over the debug port
;*                    - Play with various filtering options
;*                      - Found one reference to CalculatorX2 as Banked, instead of as Access 
;*
;* 20(16)/(02)/(25) - Change version for reporting over the comms port 
;*                  - While modifying this code for the radar, I noticed:
;*                    - That not all the special function registers reside in the ACCESS bank, so check it out here
;*                      - CM1CON0, CM2CON0 and CM2CON1
;*                      - The comparators are both off by default and writing into the top of the ACCESS bank RAM shouldn't 
;*                        cause any problems, because it only happens at power up, so keep this mod over for future release 
;*                    - That RS485RxEnable gets set in the code for serial port 2, as well as for serial port 1
;*                      - It shouldn't have any ill effect, but if the buffer for serial port 1 runs dry, it may cause a problem,
;*                        so let's remove it and keep this mod over for future release as well 
;*     
;* 20(16)/(02)/(17) - Change version for reporting over the comms port (or not we are playing with different versions here)
;*                  - Does this code manage to reboot itslef from its' carbon coppy image
;*                    - No, so then it will never manage to reboot from the image we receive from the main unit
;*                    - Sorted, now it can reboot from the carbon copy 
;*                    - And it reboots from the image we receive from the main unit
;*                  - Finalise this version number as G217   
;*                    - So all slaves with later versions can be reflashed remotely
;*                  - Switch code protection back on    
;*     
;* 20(16)/(02)/(04) - Change version for reporting over the comms port
;*                  - Carry on with the code to receive the new firmware from the main unit and store it in the upper portion of memory
;*                    - The reason it isn't re-flashing is because there were some bugs in the main unit code    
;*                    - In this package I was also ORing the low byte of the Checksum with itself, instead of with the high byte    
;*                    - After a re-flash we go to PokedInTheEye which tells me the downloaded firmware checksum isn't
;*                      correct, but it looks good and KDiff3 tells me it is the executable version which is corrupt 
;*                      - Let's go and check the actual reflashing code carefully
;*                        - The extra byte is at address 0x200, which is in the bootloader portion, which shouldn't be changing!!!  
;*     
;* 20(16)/(02)/(03) - Change version for reporting over the comms port
;*                  - Carry on with the code to receive the new firmware from the main unit and store it in the upper portion of memory
;*     
;* 20(16)/(01)/(28) - Change version for reporting over the comms port
;*                  - Carry on with code to re-flash slave from main unit
;*                    - OK, so the re-flash code is up and running
;*                  - Now do the code to receive the new firmware from the main unit and store it in the upper portion of memory
;*     
;* 20(16)/(01)/(21) - Change version for reporting over the comms port
;*                  - There are issues with the operation and Danny wants to remove the FREEZE MOTOR code, so stop the ReFlashing
;*                    project and see what I can do
;*                    - It wants to work, but it isn't
;*                    - Add some more debugging code to show what state the valve is in
;*     
;* 20(16)/(01)/(20) - Fix up the version reporting code, so that I can define the version constants properly, instead
;*                    as offsets, like I am doing now
;*                    - It reports FC17 correctly now
;*                    - Make the version current = G120 
;*                      - It isn't reported correctly on the main unit, but that doesn't mean anything, let's go into
;*                        debug mode and see if it is being transmitted from the slave correctly
;*                        - OK, the data from the slave to the main unit is correct, so let's make this stand alone and then 
;*                          go see what we are doing wrong in the main unit
;*     ROLL FORWARD - G121
;*                  - Danny wants to re-flash the slaves from the main unit, so let's see how I can make that happen
;*                  - I have no EEPROM on this PCB, so I can't do the same as I did with the bus sign!!! 
;*                  - Throw out the bootloader, we haven't used it and are unlikely to do so
;*                  - I still need to trim down the code a bit, to under half, so that I can store the new version in the flash
;*                    as I receive it from the main unit and then copy it over when I know that I have the whole thing 
;*                    - For starters, lets store all the messages as strings, rather than individual movlw commands
;*                      - WOW, its amazing how much space that quick start cost us, anyway we have space to make a working solution now
;*     
;* 20(16)/(01)/(14) - Leave the version for reporting over the comms port, otherwise I have to mod the main unit
;*                  - Add code to display the speed related data for debugging
;*                  - Add code to verify that interrupts aren't corrupting the 16-bit and 24-bit transmitted data
;*                    - This made an astounding difference to the speed pickup stability
;*     
;* 20(15)/(12)/(18) - Leave the version for reporting over the comms port, otherwise I have to mod the main unit
;*                    - I will update the version number finally, when we get to the end of this round of mods
;*                  - See why the comms is not reporting at the moment
;*                    - At least the calibration and the flow data are still reporting, so it probably has to do with the triggering   
;*                    - I was double testing for the trigger and obviously the second time it was clear, so I never ran the code
;*                    - Very interesting - the control flow and freeze stepper motor flags are not constant but bounce around, I
;*                      wonder if it is like that on the tractor as well?
;*                  - See what other debug info we want to report over the serial port
;*                    - A Tick would be nice, so that we can place events relative to each other
;*                    - Add PacketCounter as well
;*                      - OK, so I shouldn't be getting multiple versions of the same packet, I think I may be triggering elsewhere as well
;*                        - Yes, the flow meter was triggering all the time
;*                        - Much better, the packet number increment sequentially and the ControlFlow and FreezeStepperMotor flags are consistent
;*                        - Maybe we can process these numbers further, if we need to in the future - either here or at the PC
;*                    - Try to display a graph to show what is going on with the control of the valve 
;*                         big CLOSING small     Stationery     small OPENING small
;*                                         small STEPS OPEN big             
;*                      - It looks like this happens too quickly for me to generate even crude text based graphics - the
;*                        serial buffer write subroutine simply dumps characters if the buffer is full, to keep the important
;*                        processes running - it would have been nice, but maybe in the future?
;*                  - While I was doing the above, I noticed that the steps open code looks odd, so check it out
;*                  - Change version for reporting over the comms port
;*     
;* 20(15)/(12)/(17) - Change version for reporting over the comms port
;*                  - This code is very convoluted and full of stuff which remains from when it was going 
;*                    to integrate into the original system, so let's tidy it up to make it simpler to work on,
;*                    because we aren't ever going to go back to the original system
;*                    - Check the Automatic states, especially now that we quickly added the FreezeStepperMotor
;*                      - WaitUntilClosed and Closed didn't really make sense, so maybe they worked, but more likely
;*                        they weren't doing exactly what we wanted
;*                        - Test on the tractor, with the new main unit code, (FC11)
;*                          - That is looking more like the specification to me
;*                    - At the moment I hap-hazardly display data from wherever I like in the program, rather than using the
;*                      DisplayDebugData subroutine, so try to find the ones that slipped through the cracks and tidy it up
;*                      so that it works the way it was originally intended to work     
;*                      - Periodically add headings to the flow meter data
;*                      - Understand how the display data timing is achieved
;*                        - Use the DisplayMode to allow it to be triggered in different places in the program
;*                        - Understand how the time is worked out?
;*                      - Now with this mechanism I can easily add other information which can help me debug the system :-)
;*                        - Like the calibration values from the EEPROM and Main Unit
;*                        - Like the discretes for example, I could, but let's rather make them part of the packet data where they belong
;*                          - There used to be an elaborate array for storing multiple packets, let's see what remains of thatccccccccccccccccccccf
;*     
;* 20(15)/(12)/(10) - Change version for reporting over the comms port
;*                  - Receive new data in packet from main unit
;*                    - Add in all the variables and populate them from the packet
;*                      - OpenKickInitial = ReceivedOpenKick
;*                      - OpenKick = ReceivedOpenKick / 4
;*                  - Double read FlowSetPoint and OpenKick to make sure the interrupt didn't corrupt any 16-bit variables
;*                    - No, let's rather disable the interrupts while reading the 16-bit variables and then enable the 
;*                      interrupts afterwards again
;*                      - Do this with all 16-bit variables, throughout the package     
;*                  - See how to debug the comms on the bus
;*     
;* 20(15)/(10)/(29) - Change version for reporting over the comms port
;*                  - Implement the FreezeStepperMotor flag from the main unit  
;*                  - Use the filtered flow as the process variable for controlling the flow
;*                    - Add customisation label FilterProcessVariable to easily switch back if we need to      
;*                    - Switch back to using the unfiltered ProcessVariable
;*     
;* 20(15)/(10)/(16) - Change version for reporting over the comms port
;*                  - Increase StepSizeInitial from 520 to 1000
;*                  - Decrease Delay500usec to Delay250usec for stepping the motor
;*     
;* 20(15)/(09)/(25) - Change version for reporting over the comms port
;*                  - With the new connectors the PCB gets mounted differently in the box, so now there is a 
;*                    twist in the keypad pigtail, so add a configuration option to flip the keypad
;*                    - Add line #define FlipKeypad then we can comment/uncomment it if we need to change this in the future
;*     
;* 20(15)/(05)/(08) - Change version for reporting over the comms port
;*                  - Danny now has a new molded cam and the valve is opening quite slowly, see how
;*                    I can speed that up
;*                    - Add a special version of KickStartFlow = KickStartFlowInitial, which controls
;*                      the inital number of steps we want to open the valve
;*                    - Add code in the flow control section to only update Steps if the new value is
;*                      bigger than the value already in Steps
;*                    - Fixed up some paging issues with Steps at a few places in the program 
;*                    - The unit now accepts all flow control packets for flow control purposes     
;*     
;* 20(15)/(04)/(23) - Change version for reporting over the comms port
;*                  - Add debouncing routine for speed pick up input, in case we want to collect
;*                    level data, rather than edge data with it
;*                  - Add a flag to report the level of the input to the main unit
;*                  - Saw some banking issues with I2C diagnostic flags, so I fixed that up and tested them
;*                  - Remove hard coded flag references and name them, to remove conflicts!!!
;*     
;* 20(15)/(04)/(17) - Change version for reporting over the comms port
;*                  - Known issue - F319 - Add in I2C error reporting     
;*                    - The bits are already defined in the serial protocol, I just need to implement them 
;*                      - 0x0112 -  Flags.7 - Flow error - I2C - UFO 
;*                      - 0x0112 -  Flags.6 - Flow error - I2C - EEPROM
;*                      - 0x0117 - Flags2.1 - MCP3021 - I2C
;*                    - Test them by unplugging PCBs
;*                      - Looks like they want to work
;*                  - Add a bit to Lock out the Calibration keys, which needs to be unlocked by the Main Unit    
;*                    - Rather just allocate a bit in the serial protocol as an UnlockCalibration bit
;*                      and get the Main Unit to send it with every packet
;*                    - Also looks like it wants to work
;*                  - Now let's go write some code for the Main Unit
;*                    - Won't be today, but next week
;*     
;* 20(15)/(03)/(26) - Change version for reporting over the comms port
;*                  - The parts have arrived
;*                    - Build up a PCB  
;*                    - Let's go into debug mode and see what we are reading from the MCP3021
;*                      - Something, but it isn't correct
;*                        - Fixed paging errors in the averaging code
;*                    - Check we are reporting the reading over the RS485 bus   
;*                      - Yes we are 
;*                    - Let's put this in stand alone mode and go work in the main unit
;*     
;* 20(15)/(03)/(19) - Change version for reporting over the comms port
;*                  - Add code to read the MCP3021
;*                  - Prepare the version number for transmission, in case it is requested by the MASTER 
;*                  - Repaired a bug in RestartMainState, it probably never showed up, but it could
;*                  - The parts haven't arrived, so we can't test this code today  
;*     
;* 20(15)/(03)/(03) - Change version for reporting over the comms port
;*                  - Report the speed value over the debug port                            
;*                    - We have 3 magnets on the pick-up and we get 3 different numbers which repeat
;*                    - Remove 2 magnets  
;*                      - Now we get 1 consistent number, (only the units are changing a bit)
;*                  - Reduce the time out from about 4 seconds to about 1 second for Danny  
;*                    - This limit gets set in the Main Unit     
;*                    - Yes, but the time out gets set here
;*                      - Clear TMR3 when bit 2 of TMR3HH is set, (instead of bit 4)
;*                        - Remember to change the mask for maths!!!  
;*     
;* 20(14)/(12)/(11) - Change version for reporting over the comms port
;*                  - Report interrupt count locally over the debug port                            
;*     
;* 20(14)/(12)/(04) - Change version for reporting over the comms port
;*                  - Add and report interrupt count for interrupt 2                                
;*                    - For odometer on main unit
;*     
;* 20(14)/(11)/(27) - Change version for reporting over the comms port
;*                  - Use DIP switch 6 to select between 0=Auto and 1=Manual as per Leon's request
;*                  - Allow the manual buttons to AutoRepeat  
;*     
;* 20(14)/(11)/(08) - After a while the calibration seems to cancel itself out
;*                    - Because I am using the CONTROL buttons instead of the BYPASS buttons
;*                      - So, it switches to manual mode and opens and closes the valve and then
;*                        times out and goes back to automatic mode!!!
;*                  - Version EB06 is still good to go, but it reports as EA30 
;*     
;* 20(14)/(11)/(06) - Danny changed the cam, it now has a dead spot to lock it in the off position
;*                    - But, the flow meter reads 0 before it gets to the dead spot, so it doesn't lock
;*                      - Add code to make sure it does lock
;*                  - Change the logic, so that it makes sure the valve shuts, even if the flow meter
;*                    is reading 0
;*                  - Sort out why the FlowCompensation doesn't get saved to the EEPROM
;*                    - It is BANKED not ACCESS!!!  
;*     
;* 20(14)/(10)/(30) - Build up a system using new moldings
;*                    - It's the biggest we've had - 6 systems   
;*                    - Let's see what the 6 slaves have to say for themselves
;*                      - They are all reporting the same flow electronically, but not on the visual flow meters
;*                      - We need a way to easily calibrate these flow meters 
;*                        - Let's use the bypass keys on the keypad
;*                          - Add code to debounce them
;*                          - Add code to use them to modify the calibration value in the EEPROM of the flow meter
;*                  - Check whether we are reporting the average flow value or the instantaneous flow value  
;*                    - I now report both
;*     
;* 20(14)/(10)/(27) - It doesn't look like the master is sending the low flow we are seeing on the debug port
;*                    - So, try to see if we are messing it up when we receive it?
;*                      - No, it is in the receive buffer and the checksum is good, so I must just figure
;*                        out how to break on that in the main unit
;*                      - The main unit is sending the value, because the speed is not being reported
;*                        correctly all the time by the slave  
;*                    - Figure out what is wrong with the speed calculation   
;*                      - When the timer rolls over the maths falls over because I limited the timer
;*                        to 20-bits instead of 24-bits, but didn't take care of the extra 4-bits
;*                        when calculating the actual time between pulses
;*                    - I think that problem is sorted :-)
;*                  - The one flow indicator always shows more flow even though the electronics are reporting
;*                    the correct flow, so put them in series and compare them
;*                    - The one reads 1600 and the other reads 1400, so we need to trim the calibration
;*                      constant to make them the same
;*                  - Apply a piece wise stepped scale to how aggressively we drive the stepper motor,   
;*                    based on how close or far away we are from the set point 
;*                    - This is definately the way to go!
;*                  - Swap stepper motor connections, because cam works the other way around on the molded valve 
;*                    -  |   |   |   |
;*                      [R] [G] [K] {U]
;*     
;* 20(14)/(10)/(23) - Integrate the speed pick up into the slave code      
;*                    - This way any slave can be a speed pick up and we don't need a separate slave just for this
;*     
;* 20(14)/(10)/(16) - Make Saturday's code stand alone, so that we can go work on the main unit
;*     
;* 20(14)/(10)/(11) - Finalise the code for the field trial
;*                    - Capture the times from the interrupt inputs
;*                      - They no longer get processed here, but are simply reported to the main unit 
;*                    - The flows are now directly in ml/min, so they can be compared
;*                      - However, the flow we read is compensated 
;*                        - Firstly by the EEPROM value
;*                        - And secondly by the compensation value received from the main unit
;*                    - Revise the comms document, so that we know where we are
;*                    - Integrate the ultrasonic flow meter and get the whole slave up and running again                    
;*     
;* 20(14)/(09)/(18) - Make the changes to the address which Jorgen suggested        
;*                  - Now I can talk to the UFO2 ASIC
;*                  - There are some 0 readings, but in principle it looks good
;*                  - Make a simple stand alone version which reports the flow I read from the
;*                    UFO2 ASIC to the serial port, so that we can have our web conference more easily
;*                  - Strip out the geared flow meter code
;*                    - Let's leave the interrupts for the inputs in place, but remove the other code
;*     
;* 20(14)/(09)/(11) - There is a "demo" version of the flow meter available, so let's 
;*                    see if we can talk to it 
;*                    - Flash the ultra sonic flow meter PCB with the demo firmware
;*                      - It is reporting data on the com port
;*                    - Hook it up to the flow controller PCB
;*                    - Now write some code and see if we get anything from it on the I2C line
;*                      - I am reading 0x7F0F or is it 0x0F7F from the UFO2 chip
;*                        - The numbers are different, so there is a chance that it is working
;*                        - Let's make sure we are failing
;*                          - Set a breakpoint in I2CBUS1Recovery
;*                            - No error :-)
;*                            - Unplug the flow meter PCB
;*                              - now i do get an error :-)
;*                      - Try programming the 24LC256 and reading it back  
;*                        - Reading back 0xFA instead 0x55
;*                        - Let's hook up some test leads and see if the hardware and software agree
;*                          - Especially before and after the level translator
;*                            - Matches up in single step, but maybe the caps are messing me around at full speed
;*                              - Animate 
;*                                - Can write and read 24LC256
;*                        - Remove the caps on the level converter lines
;*                          - Can write and read the 24LC256 at full spead
;*                      - But now I get errors when trying to talk to the UFO2 chip
;*                        - Let's email Jorgen and see what he has to say
;*     
;* 20(14)/(06)/(05) - Try to reduce the turn around time in order to speed up the communication
;*                    - Remember to roll back to E227 if I am not successful
;*                    - Reduce the turn around time from 4, (20msec), to 2, (10msec)
;*                    - Quadrupple the baud rate from 9600 to 38400
;*                      - 71 doesn't just divide nicely by 4, so figure out what else needs to change
;*                        in order to select 38400bps accurately! 
;*                      - Looks like I can just change BRGH from 0 to 1
;*                        - BRGH is bit 2 of TXSTA
;*                    - Can't easily get the main unit to read see the slaves at 38400, so let's toll back to 9600
;*                  - See if we can turn the steppers faster
;*                    - Step the motor in batches
;*                      - Let's try batches of 5 steps  
;*                        - Surprisingly, I can't see any difference between this one which is batched
;*                          and the other ones which aren't! 
;*                  - Let's go back to the main unit and see if we can make the comms still faster by trimming
;*                    the time outs and packet delays
;*     
;* 20(13)/(07)/(04) - Work on the analogue matrices    
;*                    - Not working when I toggle the switches
;*                      - Let's see what the voltages are doing 
;*                        - They are changing on the pin of the micro
;*                      - Check everything is setup correctly
;*                        - Not reading the ADC correctly
;*                      - Check the SELECT macro
;*                        - Not terminating when a match is found
;*                      - There we go, it works beautifully
;*                    - Now copy over for DIP switches 4, 5 & 6
;*                    - Figure out how to apply this to the membrane keypad 2x2 matrix
;*     
;* 20(13)/(06)/(28) - Test drive the new flow meter PCB    
;*                  - Sort out the new pin assignments  
;*                                +-----+-----+-----+-----+-----+-----+-----+-----+
;*                                |  7  |  6  |  5  |  4  |  3  |  2  |  1  |  0  |
;*                       +--------+-----+-----+-----+-----+-----+-----+-----+-----+
;*                       | TRIS A |  0  |  0  |  0  |  0  |  1  |  1  |  1  |  1  |
;*                       | LAT  A | Osc | Osc |  0  |  0  | ANA | ANA | ANA | ANA |
;*                       | PORT A |     |     | MS2 | MS1 |  M1 |  M0 | DP1 | DP0 |
;*                       +--------+-----+-----+-----+-----+-----+-----+-----+-----+
;*                       | TRIS B |  0  |  0  |  0  |  0  |  0  |  1  |  1  |  0  |
;*                       | LAT  B |  0  |  0  |  0  |  0  |  0  |  0  |  0  |  1  |
;*                       | PORT B | ICD | ICD | RST | Dir | STEP| SNS | FM  | SLP |
;*                       +--------+-----+-----+-----+-----+-----+-----+-----+-----+
;*                       | TRIS C |  1  |  0  |  0  |  1  |  1  |  0  |  0  |  0  |
;*                       | LAT  C |  0  |  1  |  0  |  0  |  0  |  0  |  0  |  0  |
;*                       | PORT C | Rx  | Tx  | TxE | SDA | SCL | RLY | GRN | RED |
;*                       +--------+-----+-----+-----+-----+-----+-----+-----+-----+
;*                  - Motors 
;*                    - Turning but low torque, will check settings later
;*                    - Flow meter PCB
;*                    - Analogue matrices
;*     
;* 20(13)/(06)/(27) - Sort out the flow meter EEPROM    
;*                    - My prototype used a24LC65 which I had lying around and the production units
;*                      are using a 24LC02B 
;*     
;*     
;* 20(12)/(10)/(18) - Quickly adapted from IntelligentFlowControllerC921
;*                  - This will need to be tidied up and re-visited, but it is just to keep going with the
;*                    Main Unit for now :-)
;* 
;******************************************************************************
;
              include   "P18F25K22.INC"
;
              CONFIG    FOSC=HSMP, PLLCFG=OFF, PRICLKEN=ON, FCMEN=OFF, IESO=OFF
              CONFIG    PWRTEN=ON
              CONFIG    BOREN=OFF, BORV=285
              CONFIG    WDTEN=OFF, WDTPS=32768
              CONFIG    CCP2MX=PORTC1, PBADEN=OFF, CCP3MX=PORTC6
              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, CP2=ON, CP3=ON, CPB=ON, CPD=ON
              CONFIG    WRT0=OFF, WRT1=OFF, WRT2=OFF, WRT3=OFF, WRTB=OFF, WRTC=OFF, WRTD=OFF
              CONFIG    EBTR0=OFF, EBTR1=OFF, EBTR2=OFF, EBTR3=OFF, EBTRB=OFF
;
;***************************************
;
; Customisation constants
;
;***************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
#define VersionYear     'O'
#define VersionMonth    'A'
#define VersionDayTens  '2'
#define VersionDayUnits '9'
;
#define MinimumVersionYear     'G'
#define MinimumVersionMonth    '7'
#define MinimumVersionDayTens  '2'
#define MinimumVersionDayUnits '9'
;
#define FilterProcessVariable
#define MedianFilter 
#define FilterSize 9 ;10 ;7 
;
#define Retries (3-1)
;
#define PollForSMSTC 5 ;*1s=5s
;
#define FlipKeypad
;
#define SkipFirstPulses1TC 2
#define SkipFirstPulses2TC 2
;
#define NewActuator ;Apply from CC20
;
#define OpenValve  bcf ValveDirection 
#define SkipIfValveOpen btfsc ValveDirection
#define CloseValve bsf ValveDirection
#define SkipIfValveClosed btfss ValveDirection
;
#define BuildForProgrammer
#define BuildForBootLoader
;
#define UsingICD
;#define Debugging
#define TracePinEnable
;
#define ClockSpeed 11059200
#define SerialSpeed1 19200
#define SerialSpeed2 9600
;

;*          7   6        5       4  3  2       1      0
;*          O   O        A       I  A  A       I      O 
;*        Osc Osc Pressure GSM_Net M1 M0 GSM_Run GSM_On
;* TRISA    0   0        1       1  1  1       1      0
;* LATA     0   0        0       0  0  0       0      0
;* ANSELA   0   0        1       0  1  1       0      0 
;*
;*          7   6          5   4    3            2          1           0    
;*          I   O          O   O    O            I          I           O
;*         Rx  Tx Reset_5984 Dir Step Speed_Engage Flow_Meter Fault_Relay
;* TRISB    1   0          0   0    0            1          1           0
;* LATB     0   1          0   0    0            0          0           0
;* ANSELB   0   0          0   0    0            0          0           0
;*
;*             7      6      5   4   3       2         1       0
;*             I      O      I   I   I       O         O       O
;*        GSM_Rx GSM_Tx Limits SDA SCL GSM_DTR Green_LED Red_LED 
;* TRISC       1      0      1   1   1       0         0       0
;* LATC        0      1      0   0   0       0         0       0
;* ANSELC      0      0      0   0   0       0         0       0






#define InitialisePORTA b'00000000'
#define InitialisePORTB b'01000000'
#define InitialisePORTC b'01000000'
;
#define ConfigurePORTA b'00111110'
              IFNDEF TracePinEnable
#define ConfigurePORTB b'10000110'
              ELSE  
#define ConfigurePORTB b'10000010'
              ENDIF 
#define ConfigurePORTC b'10100000'
;
#define _RA6 PORTA,6,Access
#define _RA7 PORTA,7,Access
;
#define FaultRelayPin PORTB,0,Access
#define Flow1Pin PORTB,1,Access
#define Flow2Pin PORTB,2,Access
#define TracePin LATB,2,Access
#define ValveStep LATB,3,Access
#define ValveDirection LATB,4,Access
#define A3977nReset LATB,5,Access 
#define _PGC PORTB,6,Access
#define _PGD PORTB,7,Access
;
           IFNDEF FlipKeypad
#define RedLED LATC,1,Access
#define GreenLED LATC,0,Access
           ELSE
#define RedLED LATC,0,Access
#define GreenLED LATC,1,Access
           ENDIF           
#define _RC2 PORTC,2,Access
#define _RC3 PORTC,3,Access
#define _RC4 PORTC,4,Access
#define RS485TxEnable LATC,5,Access
#define ValveLimits PORTC,5,Access
#define RS485Tx PORTC,6,Access
#define RS485Rx PORTC,7,Access



#define GSM_On      LATA,0,Access
#define GSM_Powered PORTA,1,Access




;
;                SystemClock,BusSpeed,ClockFile,ClockBit,DataFile,DataBit,ErrorHandler
#define I2C_BUS1 ClockSpeed,Slow,PORTC,3,PORTC,4,I2CBUS1Recovery
;
#DEFINE _RE3 PORTE,3,Access
;
#define TrackADC_Limits     b'01000101'
#define TrackADC_Matrix0    b'00001001'
#define TrackADC_Matrix1    b'00001101'
#define ConfigureADC1       b'00000000'
#define ConfigureADC2       b'00111110'
#define ConfigureComparator b'00000111'
;
#define LCD_Line1 b'10000000'
#define LCD_Line2 b'11000000'
;
#define LCD_Column1 0
#define LCD_Column2 1
#define LCD_Column3 2
#define LCD_Column4 3
#define LCD_Column5 4
#define LCD_Column6 5
#define LCD_Column7 6
#define LCD_Column8 7
#define LCD_Column9 8
#define LCD_Column10 9
#define LCD_Column11 10
#define LCD_Column12 11
#define LCD_Column13 12
#define LCD_Column14 13
#define LCD_Column15 14
#define LCD_Column16 15
;
;***************************************
;
; 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: CreateString
;
;        This macro creates a text message in program memory
;
;***************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
CreateString  macro     Reference,Text
Reference     DATA      Text
              DW        0
              endm
;
;***************************************
;
; MACRO: SendStringToDebugPort
;
;        This macro reads a text message from program memory and writes it to the LCD buffer
;
;***************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
SendStringToDebugPortFast: macro Reference
;
              PointToMessage Reference
              call      X_SendStringToDebugPortFast
;
              endm
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
SendStringToDebugPortSlow: macro Reference
;
              PointToMessage Reference
              call      X_SendStringToDebugPortSlow
;
              endm
;
;***************************************
;
; MACRO: SendStringToLCDLine1
;
;        This macro reads a text message from program memory and writes it to the LCD buffer
;
;***************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
SendStringToLCDLine1: macro Reference
;
              PointToMessage Reference
              call      X_SendStringToLCDLine1
;
              endm
;
;***************************************
;
; MACRO: SendStringToLCDLine2
;
;        This macro reads a text message from program memory and writes it to the LCD buffer
;
;***************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
SendStringToLCDLine2: macro Reference
;
              PointToMessage Reference
              call      X_SendStringToLCDLine2
;
              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
;
;***************************************
;
; MACRO: Debounce with long press and repeat
;
; 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
;
DebounceSet:     macro     PinLogic,PinFile,PinBit,PinBank,FlagFile,FlagBit,FlagBank,HistoryFile,HistoryBit,HistoryBank,TimerFile,TimerBank,TC,RepeatTC,TCBank
;
              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
;
              movf      RepeatTC,TCBank
              movwf     TimerFile,TimerBank
;
              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       movf      TC,TCBank                       ;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
;
;***************************************
;
; 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: 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
;
;***************************************
;
; 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
;
;***************************************
;
; Constants - Complete BIT locations
;
;***************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
#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 _TMR3IP IPR2,TMR3IP,Access
#define _TMR3IF PIR2,TMR3IF,Access
#define _TMR3IE PIE2,TMR3IE,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 _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 _EEFREE   EECON1,FREE,Access
#define _EEWREN   EECON1,WREN,Access
#define _EEWR     EECON1,WR,Access
;
#define _Go ADCON0,GO,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 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' ;1:8, ON, 1:16
#define TC5msec 108
#define ConfigureTMR3 b'00110011' ;Fosc/4, 1:8, 16-bit, ON
#define ConfigureTMR3Gate b'00000000'
;
#define SensePowerDebounceTC 100
;
#define TCFlasher 100
#define TC1Second 200
;
#define Splash_Time 250
#define Refresh_LCD_TC 66
;
#define Key_SetDebounceTC 10
#define Key_DownDebounceTC 10
#define Interrupt1DebounceTC 10
#define Interrupt2DebounceTC 10
;
#define AutoRepeatTC 15
#define Key_SetStart 25
#define Key_SetIncrement 20 
#define Key_DownStart 25
#define Key_DownIncrement 20
;
#define FlowTC 60 ;*5msec = 300msec
#define StepSizeInitial 1000
#define CommsTC 2000
#define ManualOverRideTC 400 ;*5msec = 2 seconds
;
#define MenuTimeOutTC 6000 ;*5msec = 30 seconds
;
#define CyclePowerAttempts 30
;
#define NoFlowTimeOutTC 200 ;5msec = 2 seconds
;
#define NewDataTC 10            ;*5msec = 50msec
#define NewDataDelayTC 200      ;*5msec = 1 second
#define CommandHelpDelayCount 5 ;*1 second = 5 seconds   
#define RefreshHeadingsTC 40    ;lines
;
#define TurnAroundTC 2        ;*5msec = 10msec
;
#define msec 1/5
#define Seconds 1000*msec
#define Minutes 60*Seconds
;
#define UltraTC 50  ;*5msec = 250msec
#define MCP3021TC 5 ;*5msec = 25msec
;
;***************************************
;
; Constants - Buffer related
;
;***************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
#define Rx1BufferSize 250
#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 250
;
#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 RS485RxEnable                  Flags1,0,Access
#define SensePower                     Flags1,1,Access
#define SensePowerHistory              Flags1,2,Access
#define SaveTMR2IE                     Flags1,3,Access
#define ShowFlow                       Flags1,4,Access
#define NewDataForSensor1              Flags1,5,Access
#define NewDataForSensor2              Flags1,6,Access
#define SyncSeen                       Flags1,7,Access
;
#define DisplayNewDataForInterrupt1    Flags2,0,Access
#define DisplayNewDataForInterrupt2    Flags2,1,Access
#define Sensor1WrappedAround           Flags2,2,Access
#define Sensor2WrappedAround           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 Broadcast                      Flags3,2,Access
#define RxAddress                      Flags3,3,Access
#define SerialBuffer1AddressByte       Flags3,4,Access
#define ReadUltraSonic                 Flags3,5,Access
#define ProcessNewFlowData             Flags3,6,Access
#define ReadMCP3021ADC                 Flags3,7,Access
;
#define Key_Down                    Flags4,0,Access
#define Key_Set                     Flags4,1,Access
#define Key_DownHistory             Flags4,2,Access
#define Key_SetHistory              Flags4,3,Access
#define Key_Up                    Flags4,4,Access
#define Key_Menu                     Flags4,5,Access
#define Key_UpHistory             Flags4,6,Access
#define Key_MenuHistory              Flags4,7,Access
;
#define I2CBUS_Error                   Flags5,0,Access
#define Interrupt1_LevelHistory        Flags5,1,Access
#define Interrupt2_LevelHistory        Flags5,2,Access
#define ReplyToPacket                  Flags5,3,Access
#define SkipQueue                      Flags5,4,Access
#define RefreshLCD                     Flags5,5,Access
;
#define SendSMS                        Flags6,0,Access
#define ReplyToSMS                     Flags6,1,Access
#define ModemFound                     Flags6,2,Access
#define PollForSMS                     Flags6,3,Access
;
; Flags7 will be made non-volatile in the final version of the code
;
#define ManualMode                     Flags7,0,Access 
#define FaultRelay                     Flags7,1,Access
;
; Flags 8
;
#define Limit_Open_Pin                 Flags8,2,Access
#define Limit_Open                     Flags8,3,Access
#define Limit_Open_History             Flags8,4,Access
#define Limit_Closed_Pin               Flags8,5,Access
#define Limit_Closed                   Flags8,6,Access
#define Limit_Closed_History           Flags8,7,Access
;
#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
;
#define LCD_RS                         LCD_Port,0,Access
#define LCD_RnW                        LCD_Port,1,Access
#define LCD_Enable                     LCD_Port,2,Access
#define B_LCD_Enable                   2
#define LCD_BackLight                  LCD_Port,3,Access
;
#define NoSwitch                       DIPSwitches,6,Banked,Off 
;
#define MembraneSWControlOpenPin       MembraneSwitches,0,Banked
#define MembraneSWControlClosePin      MembraneSwitches,1,Banked
#define MembraneSWKey_MenuPin        MembraneSwitches,2,Banked
#define MembraneSWKey_UpPin       MembraneSwitches,3,Banked
;
           CBLOCK    0
;
              Flags0
              Flags1
              Flags2
              Flags3
              Flags4
              Flags5
              Flags6
              Flags7
              Flags8
;
              ScratchPad0
              ScratchPad1
              ScratchPad2
              ScratchPad3
              ScratchPad4
              ScratchPad5
              ScratchPad6
;
              Timer_GP1
              Timer_GP1H
;
              Timer_RefreshLCD
;
              Timer_50u
              Timer_5m
              Timer_nx5m             
;
              CharacterBuffer1
              CharacterBuffer2
;
              LCD_Port
              LCD_Data
              HexPotIn
;
              EEAdrsLo
              EEAdrsHi
              EEAdrsUp
;
              I2C_Work
              I2C_BitCount
              I2C_Retries
;
              Test0
              ShiftOut
;
              Command
              StepsHundreds 
              StepsTens
              StepsUnits
              Steps
              StepsH
              StepsOpen
              StepsOpenH
; 
              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
;
              FlowTimer
              FlowTimerH
;
              CommsTimer
              CommsTimerH
;
              NewDataTimer
              NewDataDelayCounter
              RefreshHeadings
;
              TMR3HH
;
              ValveNumber
;
              MainState
              EEPROMState
              MenuState
              HeartBeatState
;
              LineBufferPointer
              LineBufferCounter
              CharacterBuffer
              CharactersInBuffer
              ParameterStart
              ParameterLength
	          PhraseNumber
	          PhraseLength
	          PhraseCounter
;
              MenuTimeOut
              MenuTimeOutH
;
              GSM_CyclePower
;
              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
;
           CBLOCK h'60'
;
              ReFlash_ByteCounter
              ReFlash_ByteCounterH
              ReFlash_Checksum
              ReFlash_ChecksumH
              ReFlash_TBLPTRL
              ReFlash_TBLPTRH
;
              ReFlash_MinimumVersionNumber
              ReFlash_MinimumVersionNumberH
              ReFlash_UpgradeVersionNumber
              ReFlash_UpgradeVersionNumberH
;
              ReFlash_PacketCounter
;
              ReFlash_BlockBuffer:64
;
              AlertNumber:10
;
              CheckBank0Usage
           ENDC
;
           IF CheckBank0Usage > h'100'
              ERROR "Too many file registers have been used in Bank 0"
           ENDIF
;
           CBLOCK h'100'
;
              SerialDataFromMasterToSlave:16
              SerialDataFromSlaveToMaster:16
;
              SaveWREG
              SaveSTATUS
              SaveFSR0L
              SaveFSR0H
              SaveFSR1L
              SaveFSR1H
              SaveFSR2L
              SaveFSR2H
              SavePCLATH
              SavePCLATU
              SaveTBLPTR
              SaveTBLPTRH
              SaveTBLPTRU
              SaveTABLAT
              SavePRODL
              SavePRODH
              SaveBSR
;
              HPI_SaveWREG
              HPI_SaveSTATUS
              HPI_SaveBSR
;
              GSM_Flags0
              GSM_Flags1
;
              FlasherTimer
              OneSecondTimer
;
              Rx1BufferReadPointer
              Rx1BufferWritePointer
              Tx1BufferReadPointer
              Tx1BufferWritePointer
;
              Rx2BufferReadPointer
              Rx2BufferWritePointer
              Tx2BufferReadPointer
              Tx2BufferWritePointer
;
              AddressSelector
;
              CRC
              CRCH
              CRC_BitCounter
              CRC_ByteCounter
              CRC_ByteCounterH
;
              Interrupt1Capture
              Interrupt1CaptureH
              Interrupt1CaptureHH
              Interrupt1Work
              Interrupt1WorkH
              Interrupt1WorkHH
              Interrupt1Old
              Interrupt1OldH
              Interrupt1OldHH
;
              Interrupt2Capture
              Interrupt2CaptureH
              Interrupt2CaptureHH
              Interrupt2Work
              Interrupt2WorkH
              Interrupt2WorkHH
              Interrupt2Old
              Interrupt2OldH
              Interrupt2OldHH

              PollForSMSTimer
;
              LinePointer
;
              FlowError
              FlowErrorH
;
              CommsCount
;
              SkipFirstPulses1
              SkipFirstPulses2
; 
              DisplayMode
;
              OverRideTimer
              OverRideTimerH
;
              PacketState
              PacketCharacter
              PacketCounter
              CheckSum
;
              TurnAroundTimer
;
              Dummy
;
              DIPSwitches 
              Limits     
              Matrix0
              Matrix1
              MembraneSwitches
;
              StepBatch
;
              Flow0Age
              Flow0
              Flow0H
              Flow1Age
              Flow1
              Flow1H
              Flow2Age
              Flow2
              Flow2H
              Flow3Age
              Flow3
              Flow3H
              Flow4Age
              Flow4
              Flow4H
              Flow5Age
              Flow5
              Flow5H
              Flow6Age
              Flow6
              Flow6H
              Flow7Age
              Flow7
              Flow7H
              Flow8Age
              Flow8
              Flow8H
              Flow9Age
              Flow9
              Flow9H
;
              MedianCounter
              MedianTempAge
              MedianTemp
              MedianTempH
              MedianNewSamplePointer
              MedianNewSamplePointerH
;
              Limit_Open_DebounceTimer
              Limit_Closed_DebounceTimer
;
              Key_SetDebounceTimer
              Key_DownDebounceTimer
;
              Key_MenuDebounceTimer
              Key_UpDebounceTimer
;
              Integral
;
              FlowSetPoint
              FlowSetPointH
              FlowFlags
              FlowCompensation
              OpenKickInitial
              OpenKickInitialH
              OpenKick
              OpenKickH
;
              FlowProcessVariable
              FlowProcessVariableH
;
              SensorFlags
;
              Interrupt1Count
              Interrupt1Time
              Interrupt1TimeH
              Interrupt1TimeHH
              Interrupt1DebounceTimer
;
              Interrupt2Count
              Interrupt2Time
              Interrupt2TimeH
              Interrupt2TimeHH
              Interrupt2DebounceTimer
;
              AutoRepeat
              Key_SetKick
              Key_DownKick
;
              TickCount
              PacketCount
;
              AssignedValveNumber
              NonVolatileFlags
;
              SetTimer
              SetRepeat
;
              LCD_Pointer
;
              NoFlowTimeOut
              NoFlowTimeOutH
;
              HexToASCIIScratch
              NibblesToASCIIScratch
;
              GSM_State  
              GSM_Dispatch
              GSM_DispatchH
;
	      CellModuleTimeOutTimer
	      CellModuleTimeOutTimerH
;
              NetworkRegistrationAttempts
;
              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
;
              GSM_ScratchPad0
              GSM_ScratchPad1
              GSM_ScratchPad2
;
              SMSNumber
              SMSScratchPad 
              ReplyNumberLength
              ReplyNumber:15
;
              MessageRetries
              InitialiseRetries
;
              PasswordThousands
              PasswordHundreds
              PasswordTens
              PasswordUnits
              PasswordThousands_Work
              PasswordHundreds_Work
              PasswordTens_Work
              PasswordUnits_Work
;
              DisplayFlow_Total
              DisplayFlow_TotalH
              DisplayFlow_Count
;
              FlowForDisplay
              FlowForDisplayH
;
              CheckBank1Usage
           ENDC
;
           CBLOCK SerialDataFromMasterToSlave
              ReceivedFlowSetPoint
              ReceivedFlowSetPointH
              ReceivedFlowFlags            
              ReceivedFlowCompensation
              ReceivedOpenKick
              ReceivedOpenKickH
              ReceivedSpare0
              ReceivedSpare1
              ReceivedSpare2
              ReceivedSpare3
              ReceivedSpare4
              ReceivedSpare5
              ReceivedSpare6
              ReceivedSpare7
              ReceivedSpare8
              ReceivedFlowMeterCalibration ;Command 1100 writes this value to the flow meter EEPROM
           ENDC
;
#define ControlFlow FlowFlags,0,Banked
#define CalibrationUnlock FlowFlags,1,Banked
#define FreezeStepperMotor FlowFlags,2,Banked
;
           CBLOCK SerialDataFromSlaveToMaster
              TransmitFlowProcessVariable
              TransmitFlowProcessVariableH
              TransmitFlags
              TransmitInterrupt2Time
              TransmitInterrupt2TimeH
              TransmitInterrupt2TimeHH
              TransmitInterrupt2Count
              TransmitFlags2
              TransmitMCP3021Reading
              TransmitFlowMeterCalibration
              TransmitInterrupt1Time
              TransmitInterrupt1TimeH
              TransmitInterrupt1TimeHH
              TransmitInterrupt1Count
              TransmitVersionYM
              TransmitVersionDD
           ENDC 
;
#define I2CBUS_Error_UFO2     TransmitFlags,7,Banked
#define I2CBUS_Error_EEPROM   TransmitFlags,6,Banked
#define UFO2_Error            TransmitFlags,5,Banked
#define UFO2_NewReading       TransmitFlags,4,Banked
#define Interrupt2_OverFlow   TransmitFlags,3,Banked
#define Interrupt2_NewReading TransmitFlags,2,Banked
#define Interrupt2_Level      TransmitFlags,1,Banked
;
#define Interrupt1_OverFlow   TransmitFlags2,5,Banked
#define Interrupt1_NewReading TransmitFlags2,4,Banked
#define Interrupt1_Level      TransmitFlags2,3,Banked
#define VersionY0             TransmitFlags2,2,Banked
#define I2CBUS_Error_MCP3021  TransmitFlags2,1,Banked
#define MCP3021_NewReading    TransmitFlags2,0,Banked
;
#define UseAssignedValveNumber NonVolatileFlags,0
;
           IF CheckBank1Usage > h'200'
              ERROR "Too many file registers have been used in Bank 1"
           ENDIF
;
           CBLOCK h'200'
              Tx1Buffer:Tx1BufferSize              ;Serial transmit buffer 1
              Rx2Buffer:Rx2BufferSize              ;Serial receive buffer 2
              CheckBank2Usage
           ENDC
;
           IF CheckBank2Usage > h'300'
              ERROR "Too many file registers have been used in Bank 2"
           ENDIF
;
           CBLOCK h'300'
;
              Rx1Buffer:Rx1BufferSize              ;Serial receive buffer 1
;
              CheckBank3Usage
           ENDC
;
           IF CheckBank3Usage > h'400'
              ERROR "Too many file registers have been used in Bank 3"
           ENDIF
;
           CBLOCK h'400'
              LineBuffer:LineBufferSize          ;Line buffer
              CheckBank4Usage
           ENDC
;
           IF CheckBank4Usage > h'500'
              ERROR "Too many file registers have been used in Bank 4"
           ENDIF
;
           CBLOCK h'500'
              Tx2Buffer:Tx2BufferSize              ;Serial transmit buffer 2
              CheckBank5Usage
           ENDC
;
           IF CheckBank5Usage > h'600'
              ERROR "Too many file registers have been used in Bank 5"
           ENDIF
;
           CBLOCK h'600'
              FlowCompensationTable:64
;
              CheckBank6Usage
           ENDC
;
           IF CheckBank6Usage > h'700'
              ERROR "Too many file registers have been used in Bank 6"
           ENDIF
;
           CBLOCK h'700'
              EEPROMWriteBufferInternal:EEPROMWriteBufferSizeInternal
              EEPROMReadBufferInternal:EEPROMReadBufferSizeInternal
              CheckBank7Usage
           ENDC
;
           IF CheckBank7Usage > h'800'
              ERROR "Too many file registers have been used in Bank 7"
           ENDIF
;
           CBLOCK h'800'
              EEPROMWriteBufferExtertnal:EEPROMWriteBufferSizeExternal
              EEPROMReadBufferExternal:EEPROMReadBufferSizeExternal
              CheckBank8Usage
           ENDC
;
           IF CheckBank8Usage > h'900'
              ERROR "Too many file registers have been used in Bank 8"
           ENDIF
;
           CBLOCK h'900'
              Image
              CheckBank9Usage
           ENDC
;
           IF CheckBank9Usage > h'A00'
              ERROR "Too many file registers have been used in Bank 9"
           ENDIF
;
           CBLOCK h'A00'
              CheckBank10Usage
           ENDC
;
           IF CheckBank10Usage > h'B00'
              ERROR "Too many file registers have been used in Bank 10"
           ENDIF
;
           CBLOCK h'B00'
              CheckBank11Usage
           ENDC
;
           IF CheckBank11Usage > h'C00'
              ERROR "Too many file registers have been used in Bank 11"
           ENDIF
;
           CBLOCK h'C00'
              CheckBank12Usage
           ENDC
;
           IF CheckBank12Usage > h'D00'
              ERROR "Too many file registers have been used in Bank 12"
           ENDIF
;
           CBLOCK h'D00'
              CheckBank13Usage
           ENDC
;
           IF CheckBank13Usage > h'E00'
              ERROR "Too many file registers have been used in Bank 13"
           ENDIF
;
           CBLOCK h'E00'
              CheckBank14Usage
           ENDC
;
           IF CheckBank14Usage > h'EF4'
              ERROR "Too many file registers have been used in Bank 14"
           ENDIF
;
;***************************************
;
; Internal EEPROM memory map
;
;***************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
           CBLOCK 0
              EE_FlowSetPoint
              EE_FlowSetPointH
              EE_NonVolatileFlags
              EE_PasswordThousands
              EE_PasswordHundreds
              EE_PasswordTens
              EE_PasswordUnits
              EE_SpacerForNow
              EE_AlertNumber:10  
;
; To make the code compile for now
;
              EE_ValveNumber
              EE_FlowCompensation
              EE_AssignedValveNumber
              EE_ProgramMemorySmudged
           ENDC
;
;***************************************
;
; Internal EEPROM default data
;
;***************************************
; 
              org       h'F00000'
;
              de        0xE8,0x03,0x00,0x31,0x32,0x33,0x34,0x00
              de        '0','8','3','5','3','1','5','5','3','0'
;
              org       h'F000C0'
;                                 2   3  p4   5   6  p7   8  p9      11      13    
              de        140,135,130,125,120,117,115,113,109,105,103,102,101,100,099,098
;                                   p19                      25
              de        097,096,095,094,094,093,093,092,092,091,091,090,090,089,089,089  
; 
              de        088,088,088,087,087,087,086,086,086,085,085,085,085,084,084,084 
;                                                            57
              de        084,083,083,083,083,083,082,082,082,082,081,081,081,081,081,081   

;*
;*                  - Setpoint  300 - reverse out 23 571 988 /  100 = 235719 0011 1001  1000 1100 0111
;*                  - Setpoint  300 - reverse out 23 571 988 /  200 = 117859 0001 1100  1100 0110 0011
;*                  - Setpoint  300 - reverse out 23 571 988 /  300 =  78573 0001 0011  0010 1110 1101
;*                  - Setpoint  300 - reverse out 23 571 988 /  400 =  58929 0000 1110  0110 0011 0001
;*                  - Setpoint  300 - reverse out 23 571 988 /  500 =  47143 0000 1011  1000 0010 0111
;*                  - Setpoint  300 - reverse out 23 571 988 /  600 =  39286 0000 1001  1001 0111 0110
;*                  - Setpoint  300 - reverse out 23 571 988 /  700 =  33674 0000 1000  0011 1000 1010
;*                  - Setpoint  300 - reverse out 23 571 988 /  800 =  29464 0000 0111  0011 0001 1000
;*                  - Setpoint  300 - reverse out 23 571 988 /  900 =  26191 0000 0110  0110 0100 1111
;*                  - Setpoint  300 - reverse out 23 571 988 / 1000 =  23571 0000 0101  1100 0001 0011
;*                  - Setpoint  300 - reverse out 23 571 988 / 1200 =  19643 0000 0100  1100 1011 1011
;*                  - Setpoint  300 - reverse out 23 571 988 / 1300 =  18132 0000 0100  0110 1101 0100
;*                  - Setpoint  300 - reverse out 23 571 988 / 1400 =  16837 0000 0100  0001 1100 0101
;*                  - Setpoint  300 - reverse out 23 571 988 / 1500 =  15714 0000 0011  1101 0110 0010
;*                  - Setpoint  300 - reverse out 23 571 988 / 1600 =  14732 0000 0011  1001 1000 1100
;*                  - Setpoint  300 - reverse out 23 571 988 / 1700 =  13865 0000 0011  0110 0010 1001
;*                  - Setpoint  300 - reverse out 23 571 988 / 1800 =  13095 0000 0011  0011 0010 0111
;*                  - Setpoint  300 - reverse out 23 571 988 / 1900 =  12406 0000 0011  0000 0111 0110
;*                  - Setpoint  300 - reverse out 23 571 988 / 2000 =  11785 0000 0010  1110 0000 1001
;
;***************************************
;
; Debug port modes
;
;***************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
           CBLOCK 0
;
              DisplayFlowMeterData
              DisplayPacketData
              DisplayValveData
              DisplayCalibrationData
              DisplaySpeedData
;
           ENDC
;
              include   "I2C.INC"
;
;***************************************
;
; Reset comes to here
;
;***************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
              org       0
;
ResetComesToHere:
;
              clrf      INTCON,Access
              goto      Begin
;
              org       h'8'
;
;***************************************
;
; High Priority Interrupts come to here
;
;***************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
              goto      ProcessHighPriorityInterrupts ;And then we go and process them
;
;***************************************
;
; Low Priority Interrupts come to here
;
;***************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
              org       h'18'
;
              goto      ProcessLowPriorityInterrupts ;And then we go and process them
; 
;***************************************
;
; Read data from internal EEPROM                
; - Address to be read in W  
; - Return with data in W
;
;***************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
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:
;
              movwf     EEDATA,Access
              bcf       _EEPGD
              bcf       _EECFGS
              bsf       _EEWREN
;
              DisableInterrupts
              movlw     0x55
              movwf     EECON2,Access
              movlw     0xAA
              movwf     EECON2,Access
              bsf       _EEWR
              RestoreInterrupts
;
              bcf       _EEWREN
;
              return
;
B_Delay10msec:
              movlw     b'11000111'
              movwf     T0CON,Access
              movlw     256-108
              movwf     TMR0L
              bcf       _TMR0IF
;
B_Delay10msec1:
;
              btfss     _TMR0IF
              goto      B_Delay10msec1
;
              return
;
B_Delay100msec:
;
              call      B_Delay10msec
              call      B_Delay10msec
              call      B_Delay10msec
              call      B_Delay10msec
              call      B_Delay10msec
;
B_Delay50msec:
;
              call      B_Delay10msec
              call      B_Delay10msec
              call      B_Delay10msec
              call      B_Delay10msec
              call      B_Delay10msec
;
              return
;
Delay1Second:
;
              call      B_Delay100msec
              call      B_Delay100msec
              call      B_Delay100msec
              call      B_Delay100msec
              call      B_Delay100msec
;
Delay500msec:
;
              call      B_Delay100msec
              call      B_Delay100msec
              call      B_Delay100msec
;
B_Delay200msec:
;
              call      B_Delay100msec
              call      B_Delay100msec
;
              return
;
B_Delay250msec:
;
              call      B_Delay200msec
              call      B_Delay50msec
;
              return
;
SmudgeProgramMemory:
;
              movlw     EE_ProgramMemorySmudged
              movwf     EEADR,Access
              movlw     0xFF
              call      WriteInternalEEPROM
;
              call      B_Delay10msec
;
              return
;
UnSmudgeProgramMemory:
;
              movlw     EE_ProgramMemorySmudged
              movwf     EEADR,Access
              movlw     0x5A
              call      WriteInternalEEPROM
;
              call      B_Delay10msec
;
              return
;
PokedInTheEye:
;
; Maybe the operating image is still good and we can still run?
;
              PointToMessage ResetComesToHere
;
              movlw     LOW(0x4000-2)
              movwf     ReFlash_ByteCounter,Banked
              movlw     HIGH(0x4000-2)
              movwf     ReFlash_ByteCounterH,Banked
;
              movlw     LOW(0xDEED)
              movwf     ReFlash_Checksum,Banked
              movlw     HIGH(0xDEED)
              movwf     ReFlash_ChecksumH,Banked
;
VerifyOperatingFirmwareA:
;
              tblrd*+
              movf      TABLAT,W,Access
              xorwf     ReFlash_ChecksumH,Same,Banked
              tblrd*+
              movf      TABLAT,W,Access
              xorwf     ReFlash_Checksum,Same,Banked
;
              movlw     2
              subwf     ReFlash_ByteCounter,Same,Banked
              movlw     0
              subwfb    ReFlash_ByteCounterH,Same,Banked
;
              movf      ReFlash_ByteCounter,W,Banked
              iorwf     ReFlash_ByteCounterH,W,Banked
              btfss     ZeroFlag
              goto      VerifyOperatingFirmwareA                      
;
              comf      ReFlash_Checksum,Same,Banked
              comf      ReFlash_ChecksumH,Same,Banked
;              
              tblrd*+    
              movf      TABLAT,W,Access
              subwf     ReFlash_ChecksumH,W,Banked
              btfss     ZeroFlag              
              goto      PokedInTheEyeForSure
              tblrd*+    
              movf      TABLAT,W,Access
              subwf     ReFlash_Checksum,W,Banked
              btfss     ZeroFlag              
              goto      PokedInTheEyeForSure
;
UnSmudge1A
              movlw     EE_ProgramMemorySmudged
              call      ReadInternalEEPROM
              xorlw     0x5A
              btfsc     ZeroFlag
              goto      ReadyForAction
;
              call      UnSmudgeProgramMemory 
;
              goto      UnSmudge1A
;
PokedInTheEyeForSure:
;
              bcf       GreenLED
              bcf       RedLED
;
              call      Delay1Second
;
              movlw     10
              movwf     ReFlash_ByteCounter,Banked
;
PokedInTheEye1:
;
              bsf       RedLED
;
              call      B_Delay250msec
;
              bcf       RedLED
;
              call      B_Delay250msec
;
              decfsz    ReFlash_ByteCounter,Same,Banked
              goto      PokedInTheEye1
;
              goto     PokedInTheEyeForSure
;
ReFlash:
;
              PointToMessage NewFirmware+2 ;Point to first word of new firmware
;
              movlw     LOW(0x4000)
              movwf     ReFlash_ByteCounter,Banked
              movlw     HIGH(0x4000)
              movwf     ReFlash_ByteCounterH,Banked
;
              movlw     LOW(0xDEED)
              movwf     ReFlash_Checksum,Banked
              movlw     HIGH(0xDEED)
              movwf     ReFlash_ChecksumH,Banked
;
ReFlash1:
;
              tblrd*+
              movf      TABLAT,W,Access
              xorwf     ReFlash_ChecksumH,Same,Banked
              tblrd*+
              movf      TABLAT,W,Access
              xorwf     ReFlash_Checksum,Same,Banked
;
              movlw     2
              subwf     ReFlash_ByteCounter,Same,Banked
              movlw     0
              subwfb    ReFlash_ByteCounterH,Same,Banked
;
              movf      ReFlash_ByteCounter,W,Banked
              iorwf     ReFlash_ByteCounterH,W,Banked
              btfss     ZeroFlag
              goto      ReFlash1                            
;
              comf      ReFlash_Checksum,Same,Banked
              comf      ReFlash_ChecksumH,Same,Banked
;              
              movf      ReFlash_Checksum,W,Banked
              iorwf     ReFlash_ChecksumH,W,Banked

              btfss     ZeroFlag              
              goto      PokedInTheEye
;
ReFlash_CheckMinimumVersion:
;
              PointToMessage MinimumVersionNumber 
;
              tblrd*+
              movf      TABLAT,W,Access
              movwf     ReFlash_MinimumVersionNumberH,Banked
              tblrd*+
              movf      TABLAT,W,Access
              movwf     ReFlash_MinimumVersionNumber,Banked
;
              PointToMessage NewFirmware+2+CurrentVersionNumber 
;
              tblrd*+
              movf      TABLAT,W,Access
              movwf     ReFlash_UpgradeVersionNumberH,Banked
              tblrd*+
              movf      TABLAT,W,Access
              movwf     ReFlash_UpgradeVersionNumber,Banked
;
              movf      ReFlash_MinimumVersionNumber,W,Banked
              subwf     ReFlash_UpgradeVersionNumber,W,Banked
              movf      ReFlash_MinimumVersionNumberH,W,Banked
              subwfb    ReFlash_UpgradeVersionNumberH,W,Banked
              btfss     CarryFlag
              goto      PokedInTheEye
;              
ReFlash_Erase:
;
              bsf       GreenLED
              bsf       RedLED
;
              movlw     LOW((0x4000-OperatingFirmware)/64)
              movwf     ReFlash_ByteCounter,Banked
              movlw     HIGH((0x4000-OperatingFirmware)/64)
              movwf     ReFlash_ByteCounterH,Banked
;
              clrf      TBLPTRU,Access
              movlw     HIGH(OperatingFirmware)
              movwf     TBLPTRH,Access
              movlw     LOW(OperatingFirmware)
              movwf     TBLPTRL,Access
;               
ReFlash_EraseLoop:
;
              bsf        _EEPGD
              bcf        _EECFGS
              bsf        _EEFREE
              bsf        _EEWREN             
              movlw      0x55
              movwf      EECON2,Access
              movlw      0xAA
              movwf      EECON2,Access
              bsf        _EEWR
;
              movlw      64
              addwf      TBLPTRL,Same,Access
              btfsc      CarryFlag
              incf       TBLPTRH,Same,Access
;
              movlw      1
              subwf      ReFlash_ByteCounter,Same,Banked
              movlw      0
              subwfb     ReFlash_ByteCounterH,Same,Banked
;
              movf       ReFlash_ByteCounter,W,Banked
              iorwf      ReFlash_ByteCounter,W,Banked
;
              btfss      ZeroFlag
              goto       ReFlash_EraseLoop             
;
              movlw     LOW(0x4000-OperatingFirmware)
              movwf     ReFlash_ByteCounter,Banked
              movlw     HIGH(0x4000-OperatingFirmware)
              movwf     ReFlash_ByteCounterH,Banked
;
              clrf      TBLPTRU,Access
              movlw     HIGH(OperatingFirmware)
              movwf     TBLPTRH,Access
              movlw     LOW(OperatingFirmware)
              movwf     TBLPTRL,Access
;               
ReFlash_EraseCheck:
;
              tblrd*+
              movlw     0xFF
              subwf     TABLAT,W,Access
              btfss     ZeroFlag
              goto      ReFlash_Erase              
;
              movlw      1
              subwf      ReFlash_ByteCounter,Same,Banked
              movlw      0
              subwfb     ReFlash_ByteCounterH,Same,Banked
;
              movf       ReFlash_ByteCounter,W,Banked
              iorwf      ReFlash_ByteCounterH,W,Banked
;
              btfss      ZeroFlag
              goto       ReFlash_EraseCheck
;
ReFlash_Program:
;
              movlw     LOW((0x4000-OperatingFirmware)/64)
              movwf     ReFlash_ByteCounterH,Banked
;
              clrf      TBLPTRU,Access
;
              movlw     HIGH(OperatingFirmware)
              movwf     ReFlash_TBLPTRH,Banked
              movlw     LOW(OperatingFirmware)
              movwf     ReFlash_TBLPTRL,Banked
;
ReFlash_ProgramLoop:
;
              CopyBit   ReFlash_ByteCounterH,4,Banked,RedLED
;
              movff     ReFlash_TBLPTRL,TBLPTRL
              movff     ReFlash_TBLPTRH,TBLPTRH
;
              movlw     LOW(0x4000)
              addwf     TBLPTRL,Same,Access
              movlw     HIGH(0x4000)
              addwfc    TBLPTRH,Same,Access              
;
              lfsr      0,ReFlash_BlockBuffer
;
              movlw     64
              movwf     ReFlash_ByteCounter,Banked
;
ReFlash_ProgramReadLoop:              
;
              tblrd*+
              movff     TABLAT,POSTINC0
;
              decfsz    ReFlash_ByteCounter,Same,Banked              
              goto      ReFlash_ProgramReadLoop
;
              movff     ReFlash_TBLPTRL,TBLPTRL
              movff     ReFlash_TBLPTRH,TBLPTRH
;
              lfsr      0,ReFlash_BlockBuffer
;
              movlw     64
              movwf     ReFlash_ByteCounter,Banked
;
ReFlash_ProgramWriteLoop:              
;
              movff     POSTINC0,TABLAT
              tblwt*+
;
              decfsz    ReFlash_ByteCounter,Same,Banked              
              goto      ReFlash_ProgramWriteLoop
;
              movff     ReFlash_TBLPTRL,TBLPTRL
              movff     ReFlash_TBLPTRH,TBLPTRH
;
              bsf        _EEPGD
              bcf        _EECFGS
              bcf        _EEFREE
              bsf        _EEWREN             
              movlw      0x55
              movwf      EECON2,Access
              movlw      0xAA
              movwf      EECON2,Access
              bsf        _EEWR
;
              movlw      64
              addwf      ReFlash_TBLPTRL,Same,Banked
              btfsc      CarryFlag
              incf       ReFlash_TBLPTRH,Same,Banked
;
              decfsz     ReFlash_ByteCounterH,Same,Banked
              goto       ReFlash_ProgramLoop             
;
              bcf        GreenLED
              bcf        RedLED
;
              call      UnSmudgeProgramMemory 
;
;***************************************
;
; This is the beginning, so we need to initialise everything
;
;***************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
Begin:
;
              movlw     InitialisePORTA          ;Define port latches
              movwf     PORTA,Access
              movlw     InitialisePORTB
              movwf     PORTB,Access
              movlw     InitialisePORTC
              movwf     PORTC,Access
;
              movlw     ConfigurePORTA
              movwf     TRISA,Access
              movlw     ConfigurePORTB
              movwf     TRISB,Access
              movlw     ConfigurePORTC
              movwf     TRISC,Access
;
              movlw     b'00101100'
              movff     WREG,ANSELA
              movlw     b'00000000'
              movff     WREG,ANSELB
              movlw     b'00100000'
              movff     WREG,ANSELC
;
              movlw     ConfigureADC1
              movff     WREG,ADCON1
;
              movlw     ConfigureADC2
              movff     WREG,ADCON2
;
   ;           movlw     ConfigureComparator      ;Define comparator usage
              movlw     0
              movff     WREG,CM1CON0
              movff     WREG,CM2CON0
              movff     WREG,CM2CON1
;
              bcf       _nRBPU                   ;Enable weak pull-ups on PORT B
;
              movlb     0                        ;Banked instructions default to bank 0 until we are happy with the operating firmware
;
 goto Execute ;Uncomment this line when working on the code, otherwise the bootloader messes around
;
              movlw     EE_ProgramMemorySmudged
              call      ReadInternalEEPROM
              xorlw     0x5A
              btfss     ZeroFlag
              goto      ReFlash
;
              PointToMessage ResetComesToHere
;
              movlw     LOW(0x4000-2)
              movwf     ReFlash_ByteCounter,Banked
              movlw     HIGH(0x4000-2)
              movwf     ReFlash_ByteCounterH,Banked
;
              movlw     LOW(0xDEED)
              movwf     ReFlash_Checksum,Banked
              movlw     HIGH(0xDEED)
              movwf     ReFlash_ChecksumH,Banked
;
VerifyOperatingFirmware:
;
              tblrd*+
              movf      TABLAT,W,Access
              xorwf     ReFlash_ChecksumH,Same,Banked
              tblrd*+
              movf      TABLAT,W,Access
              xorwf     ReFlash_Checksum,Same,Banked
;
              movlw     2
              subwf     ReFlash_ByteCounter,Same,Banked
              movlw     0
              subwfb    ReFlash_ByteCounterH,Same,Banked
;
              movf      ReFlash_ByteCounter,W,Banked
              iorwf     ReFlash_ByteCounterH,W,Banked
              btfss     ZeroFlag
              goto      VerifyOperatingFirmware                      
;
              comf      ReFlash_Checksum,Same,Banked
              comf      ReFlash_ChecksumH,Same,Banked
;              
              tblrd*+    
              movf      TABLAT,W,Access
              subwf     ReFlash_ChecksumH,W,Banked
              btfss     ZeroFlag              
              goto      ReFlash
              tblrd*+    
              movf      TABLAT,W,Access
              subwf     ReFlash_Checksum,W,Banked
              btfss     ZeroFlag              
              goto      ReFlash
;
UnSmudge1
              movlw     EE_ProgramMemorySmudged
              call      ReadInternalEEPROM
              xorlw     0x5A
              btfsc     ZeroFlag
              goto      ReadyForAction
;
              call      UnSmudgeProgramMemory 
;
              goto      UnSmudge1
;
ReadyForAction:
;
              goto      Execute
;
              org       0x0400
;
OperatingFirmware:
;
;***************************************
;
; 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             ,"Center Pivot OA29 "
	          CreateMessage Cell_Message_ContentAutomatic    ,", mode=AUTOMATIC"
	          CreateMessage Cell_Message_ContentManual       ,", mode=MANUAL"
	          CreateMessage Cell_Message_ContentFREnable     ,", fault relay=ENABLED"
	          CreateMessage Cell_Message_ContentFRDisable    ,", fault relay=DISABLED"
              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
;
Execute:      goto      Execute1 
;
              CreateString S_Splash1,"\n\n\n\n\n\n\n\n\n\n\rAgrigel Flow Control Valve "
              CreateString S_Splash2,"\n\n\r? = Command Help\n\n\r"
              CreateString S_Help_a,"a = Automatic\n\r"
              CreateString S_Help_c,"c = Close valve 1 step, (ONLY IN MANUAL)\n\r"
              CreateString S_Help_C,"C = Close valve 100 steps, (ONLY IN MANUAL)\n\r"
              CreateString S_Help_d,"d = Decrement valve number\n\r"
              CreateString S_Help_f,"f = Flow meter data\n\r"
              CreateString S_Help_i,"i = Increment valve number\n\r"
              CreateString S_Help_k,"k = Kalibration\n\r"
              CreateString S_Help_m,"m = Manual\n\r"
              CreateString S_Help_o,"o = Open valve 1 step, (ONLY IN MABUAL)\n\r"
              CreateString S_Help_O,"O = Open valve 100 steps, (ONLY IN MANUAL)\n\r"
              CreateString S_Help_p,"p = Packet data\n\r"
              CreateString S_Help_r,"r = Reset flow pulse counter\n\r"
              CreateString S_Help_v,"v = Valve data\n\r\n\r"
              CreateString S_CalibrationDataHeadings,"5ms   EEP   COM\n\r"
              CreateString S_FlowMeterDataHeadings,"5ms    PV      SP      NEW     UFO2\n\r"
              CreateString S_SpeedDataHeadings,"Count\n\r"
;
;                                                             1111111
;                                                    1234567890123456
              CreateString S_ClearLine             ,"                "
              CreateString S_Splash1_LCD           ,"CenterPivotFlow "
              CreateString S_Splash2_LCD           ,"Controller OA29 "
              CreateString S_Automatic1WithFR      ,"AUTO GUARDED    "
              CreateString S_Automatic1NoFR        ,"AUTO !!CAUTION!!"
              CreateString S_Automatic2            ,"                "
              CreateString S_Manual1WithFR         ,"MANUAL GUARDED  "
              CreateString S_Manual1NoFR           ,"MANUAL !CAUTION!"
              CreateString S_Manual2               ,"                "
              CreateString S_EditNo                ,"   Edit? No     "
              CreateString S_EditYes               ,"   Edit? Yes    "
              CreateString S_SettingsMenu          ,"Settings Menu:  "
              CreateString S_FlowSetPointIs        ,"Set point: "
              CreateString S_FlowSetPointEdit      ,"Flow set point: "
              CreateString S_FlowProcessVariable   ,"Flow rate is:   "
              CreateString S_ModeSelect            ,"Select MODE:    "
              CreateString S_ModeSelectManual      ,"     MANUAL     "
              CreateString S_ModeSelectAutomatic   ,"     AUTOMATIC  "
              CreateString S_FaultRelay            ,"FAULT relay:    "
              CreateString S_FaultRelayEnable      ,"     ENABLE     "
              CreateString S_FaultRelayDisable     ,"     DISABLE    "
              CreateString S_PasswordIs            ,"SMS pin...: "
              CreateString S_PasswordEdit          ,"SMS pin:        "
              CreateString S_SMSAlerts             ,"SMS alerts:     "
              CreateString S_SMSAlertsEnable       ,"     ENABLE     "
              CreateString S_SMSAlertsDisable      ,"     DISABLE    "
;
; Display number on top line and then check whether to edit or not on second line
;
              CreateString S_AlertNumber           ,"Alert mumber:   "
              CreateString S_FlowFault1            ,"!! FLOW FAULT !!"
              CreateString S_FlowFault2            ,"POWER DOWN / SET"
;
Execute1:
;
              movlb     1                        ;Banked instructions default to bank 1
;
              movlw     LOW(287) ;287=9600 71=38400 47=57600 23=115200
              movwf     SPBRG1,Access
              movlw     HIGH(287)
              movwf     SPBRGH1,Access
;
              movlw     b'00001000'
              movwf     BAUDCON1
;
              movlw     b'00100110' 
              movwf     TXSTA1,Access
;
              movlw     b'10010000'
              movwf     RCSTA1,Access
;
              movlw     LOW(35) ;SerialSpeed2TC  ;Define serial port 2
              movwf     SPBRG2,Access
              movlw     HIGH(35)
              movwf     SPBRGH2,Access
;
              movlw     b'00001000'
              movwf     BAUDCON2
;
              movlw     b'00100010' ;b'00100010'|SerialSpeed2Select
              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     TC5msec                  ;Set up timer 2
              movwf     PR2,Access
;
              clrf      TMR2,Access
;
              movlw     ConfigureTMR2 
              movwf     T2CON,Access
;
              movlw     ConfigureTMR3
              movwf     T3CON,Access
;
              movlw     ConfigureTMR3Gate
              movwf     T3GCON,Access
;
              clrf      TMR3HH,Access
              clrf      TMR3H,Access
              clrf      TMR3L,Access
;
              movlw     1
              movwf     Flow0Age,Banked
              clrf      Flow0,Banked
              clrf      Flow0H,Banked
;
              movlw     2
              movwf     Flow1Age,Banked
              clrf      Flow1,Banked
              clrf      Flow1H,Banked
;
              movlw     3
              movwf     Flow2Age,Banked
              clrf      Flow2,Banked
              clrf      Flow2H,Banked
;
              movlw     4
              movwf     Flow3Age,Banked
              clrf      Flow3,Banked
              clrf      Flow3H,Banked
;
              movlw     5
              movwf     Flow4Age,Banked
              clrf      Flow4,Banked
              clrf      Flow4H,Banked
;
              movlw     6
              movwf     Flow5Age,Banked
              clrf      Flow5,Banked
              clrf      Flow5H,Banked
;
              movlw     7
              movwf     Flow6Age,Banked
              clrf      Flow6,Banked
              clrf      Flow6H,Banked
;
              movlw     8
              movwf     Flow7Age,Banked
              clrf      Flow7,Banked
              clrf      Flow7H,Banked
;
              movlw     9
              movwf     Flow8Age,Banked
              clrf      Flow8,Banked
              clrf      Flow8H,Banked
;
              movlw     10
              movwf     Flow9Age,Banked
              clrf      Flow9,Banked
              clrf      Flow9H,Banked
;
              clrf      INTCON,Access            ;Interrupts are off for now
;
              clrf      IPR1,Access              ;All interrupts are low priority
              clrf      IPR2,Access
              clrf      IPR3,Access
              bsf       _INT1IP
              bsf       _INT2IP
;
              bsf       _TMR1IP                  ;Select high priority interrupts
              bsf       _TMR3IP               
;
              bcf       _INT1EDG                 ;Work on the falling edge
              bcf       _INT2EDG
;
              bsf       _RC1IE                   ;Select active interrupts
              bsf       _RC2IE
              bsf       _TMR1IE
              bsf       _TMR2IE
              bcf       _TMR3IF
              bsf       _TMR3IE
              bsf       _INT1IE
              bsf       _INT2IE
;
              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      Flags7,Access
              clrf      Flags8,Access
;
              clrf      GSM_Flags0,Banked
              clrf      GSM_Flags1,Banked
;
              movlw     b'00001000'
              movwf     LCD_Port,Access
;
              movlw     TCFlasher                ;Load flasher
              movwf     FlasherTimer,Banked
;
              movlw     TC1Second                ;Load 1 second timer
              movwf     OneSecondTimer,Banked
;
              clrf      AutoRepeat,Banked
;
              bsf       TransmitNewData
;
              movlw     NewDataTC
              movwf     NewDataTimer,Access
              clrf      NewDataDelayCounter,Access
              movlw     0
              movwf     RefreshHeadings,Access
; 
              movlw     DisplayFlowMeterData
              movwf     DisplayMode,Banked
;
              clrf      TickCount,Banked
              clrf      PacketCount,Banked
;
              movlw     Rx1BufferLastLocation    ;Initialise the receive buffer for serial port 1  
              movwf     Rx1BufferReadPointer,Banked
              movwf     Rx1BufferWritePointer,Banked
;
              movlw     Tx1BufferLastLocation-1  ;Initialise the transmit buffer for serial port 1
              movwf     Tx1BufferReadPointer,Banked
              movwf     Tx1BufferWritePointer,Banked
;
              movlw     Rx2BufferLastLocation    ;Initialise the receive buffer for serial port 1  
              movwf     Rx2BufferReadPointer,Banked
              movwf     Rx2BufferWritePointer,Banked
;
              movlw     Tx2BufferLastLocation    ;Initialise the transmit buffer for serial port 1
              movwf     Tx2BufferReadPointer,Banked
              movwf     Tx2BufferWritePointer,Banked
;
              movff     TMR3L,Interrupt1Old
              movff     TMR3H,Interrupt1OldH
              movff     TMR3HH,Interrupt1OldHH
              clrf      Interrupt1Time,Banked
              clrf      Interrupt1TimeH,Banked
              clrf      Interrupt1TimeHH,Banked
;
              movff     TMR3L,Interrupt2Old
              movff     TMR3H,Interrupt2OldH
              movff     TMR3HH,Interrupt2OldHH
              clrf      Interrupt2Time,Banked
              clrf      Interrupt2TimeH,Banked
              clrf      Interrupt2TimeHH,Banked
;
              movlw     SkipFirstPulses1TC
              movwf     SkipFirstPulses1,Banked
              movlw     SkipFirstPulses2TC
              movwf     SkipFirstPulses2,Banked
;
              movlw     LOW(FlowTC)
              movwf     FlowTimer,Access
              movlw     HIGH(FlowTC)
              movwf     FlowTimerH,Access
;
              movlw     LOW(CommsTC) 
              movwf     CommsTimer,Access
              movlw     HIGH(CommsTC)
              movwf     CommsTimerH,Access
;
              movlw     LOW(10000)
              movwf     FlowSetPoint,Banked
              movlw     HIGH(10000)
              movwf     FlowSetPointH,Banked
;
              movlw     0
              movwf     FlowFlags,Banked
              movwf     FlowProcessVariable,Banked
              movwf     FlowProcessVariableH,Banked
;
              movlw     0
              movwf     EEPROMState,Access
;
              movlw     0
              movwf     HeartBeatState,Access
;
              movlw     0
              movwf     MainState,Access
;
              movlw     0
              movwf     MenuState,Access
;
              movlw     0
              movwf     GSM_State,Banked
;
              movlw     255
              movwf     SetTimer,Banked
;
; Restore settings from internal EEPROM
;
              movlw     EE_FlowSetPoint
              call      ReadInternalEEPROM
              movwf     FlowSetPoint,Banked
;
              movlw     EE_FlowSetPointH
              call      ReadInternalEEPROM
              movwf     FlowSetPointH,Banked
;
              movlw     EE_NonVolatileFlags
              call      ReadInternalEEPROM
              movwf     Flags7,Access
;
              movlw     EE_PasswordThousands
              call      ReadInternalEEPROM
              movwf     PasswordThousands,Banked
;
              movlw     EE_PasswordHundreds
              call      ReadInternalEEPROM
              movwf     PasswordHundreds,Banked
;
              movlw     EE_PasswordTens
              call      ReadInternalEEPROM
              movwf     PasswordTens,Banked
;
              movlw     EE_PasswordUnits
              call      ReadInternalEEPROM
              movwf     PasswordUnits,Banked
;
              movlw     EE_AlertNumber+0
              call      ReadInternalEEPROM
              movff     WREG,AlertNumber+0
;
              movlw     EE_AlertNumber+1
              call      ReadInternalEEPROM
              movff     WREG,AlertNumber+1
;
              movlw     EE_AlertNumber+2
              call      ReadInternalEEPROM
              movff     WREG,AlertNumber+2
;
              movlw     EE_AlertNumber+3
              call      ReadInternalEEPROM
              movff     WREG,AlertNumber+3 
;
              movlw     EE_AlertNumber+4
              call      ReadInternalEEPROM
              movff     WREG,AlertNumber+4
;
              movlw     EE_AlertNumber+5
              call      ReadInternalEEPROM
              movff     WREG,AlertNumber+5
;
              movlw     EE_AlertNumber+6
              call      ReadInternalEEPROM
              movff     WREG,AlertNumber+6
;
              movlw     EE_AlertNumber+7
              call      ReadInternalEEPROM
              movff     WREG,AlertNumber+7
;
              movlw     EE_AlertNumber+8
              call      ReadInternalEEPROM
              movff     WREG,AlertNumber+8
;
              movlw     EE_AlertNumber+9
              call      ReadInternalEEPROM
              movff     WREG,AlertNumber+9
;
              call      PopulateFlowCompensationTable
;
              movlw     200
              subwf     FlowCompensation,W,Banked
              btfss     CarryFlag
              goto      CompensationValueInRange
;
              movlw     100
              movwf     FlowCompensation,Banked
;
CompensationValueInRange:
;
              movlw     LOW(StepSizeInitial)
              movwf     OpenKickInitial,Banked
              movwf     OpenKick,Banked
              movlw     HIGH(StepSizeInitial)
              movwf     OpenKickInitialH,Banked
              movwf     OpenKickH,Banked
;
              bcf       CarryFlag
              rrcf      OpenKickH,Same,Banked
              rrcf      OpenKick,Same,Banked
;
              bcf       CarryFlag
              rrcf      OpenKickH,Same,Banked
              rrcf      OpenKick,Same,Banked
;
              clrf      Dummy,Banked
;
              I2C_Initialise I2C_BUS1
;
; O530 - insert new LCD driver code here for now
;      - once it is working I can decide where it must live permanently
;
;                         DDDDB _R
;                         7654LEWS
              movlw     b'00001000'              ;Initialise LCD port
              movwf     LCD_Port,Access
;
              movlw     b'00000000'
              movwf     LCD_Data,Access          ;Initialise LCD data
;
              call      OpenWrite8574            ;Perform a dummy write to make sure the I2C pins are configured correctly 
              movf      LCD_Data,W,Access
              call      Write8574
;
              call      I2CBUS1Stop
;
              call      Delay500msec
;
              call      OpenWrite8574            
              movf      LCD_Data,W,Access
              call      Write8574
;
              movlw     b'00110000'
              movwf     LCD_Data,Access          
;
              call      WriteLCDNibbleHi
;
              call      Delay5msec
;
              call      WriteLCDNibbleHi
;
              call      Delay5msec
;
              call      WriteLCDNibbleHi
;
              call      Delay5msec
;
              movlw     b'00100000'
              movwf     LCD_Data,Access          ;Interface length is 4-bits
              call      WriteLCDNibbleHi
;
              call      Delay5msec
;
              movlw     b'00101000'              ;Interface length is 4-bits, 2 lines, 5x7 font
              call      WriteLCDInstruction
;
              call      Delay5msec
;
              movlw     b'00001000'              ;Display off, cursor off, blink off
              call      WriteLCDInstruction
;
              call      Delay5msec
;
              movlw     b'00000001'              ;Clear display
              call      WriteLCDInstruction
;
              call      Delay5msec
;
           ;   movlw     b'00100100'              ;Increment, shift
           ;   call      WriteLCDInstruction
;
              call      Delay5msec
;
              movlw     b'00001100'              ;Display on, cursor off, blink off
              call      WriteLCDInstruction
;
              call      Delay5msec
;
              movlw     b'10000000'
              call      WriteLCDInstruction
;
              call      Delay5msec
;
;                         DDDDB _R
;                         7654LEWS
              movlw     b'00001001'              ;Initialise LCD port
              movwf     LCD_Port,Access
;
              clrf      TransmitFlags,Banked
;
        IF ((VersionYear-'A'+10)/16) == 0 ;(2000-2015:0-F)
              movlw     b'00000000'
              movwf     TransmitFlags2,Banked
           IF (VersionMonth-'0') < 10
              movlw     ((VersionYear-'A'+10)<<4)+(VersionMonth-'0')
           ELSE
              movlw     ((VersionYear-'A'+10)<<4)+(VersionMonth-'A'+10)
           ENDIF
        ENDIF
        IF ((VersionYear-'A'+10)/16) == 1 ;(2016-2031:G-V)
              movlw     b'00000100'
              movwf     TransmitFlags2,Banked
           IF (VersionMonth-'0') < 10
              movlw     ((VersionYear-'A'+10-16)<<4)+(VersionMonth-'0')
           ELSE
              movlw     ((VersionYear-'A'+10-16)<<4)+(VersionMonth-'A'+10)
           ENDIF
        ENDIF
              movwf     TransmitVersionYM,Banked
;
              movlw     ((VersionDayTens-'0')<<4)+(VersionDayUnits-'0')
              movwf     TransmitVersionDD,Banked
;
              CopyBit   Flow1Pin,Interrupt1_Level
              clrf      Interrupt1DebounceTimer,Banked
              CopyBit   Flow2Pin,Interrupt2_Level
              clrf      Interrupt2DebounceTimer,Banked
;
              movlw     255
              movwf     SetRepeat,Banked
;
              movlw     Refresh_LCD_TC
              movwf     Timer_RefreshLCD,Access
;
              bsf       A3977nReset
;
              clrf      Steps,Access
              clrf      StepsH,Access
;
              movlw     LOW(NoFlowTimeOutTC)
              movwf     NoFlowTimeOut,Banked
              movlw     HIGH(NoFlowTimeOutTC)
              movwf     NoFlowTimeOutH,Banked
;
              clrf      OverRideTimer,Banked
              clrf      OverRideTimerH,Banked
;
              movlw     CyclePowerAttempts
              movwf     GSM_CyclePower,Access
;
              bsf       _IPEN                    ;Switch the interrupts on
              bsf       _GIEH
              bsf       _GIEL
;
              movlw     Retries
              movwf     MessageRetries,Banked
              movlw     Retries*2
              movwf     InitialiseRetries,Banked
;
              SendStringToDebugPortSlow S_Splash1
              call      DisplayOnDebug_Version 
              SendStringToDebugPortSlow S_Splash2
;
Forever:
;
              movf      MenuState,W,Access
              btfss     ZeroFlag
              goto      Forever_SkipToHereWhenEditing
;
              call      ProcessManualOverRide    ;Put this first, so that manual over rides reset state selection
              call      ProcessMainState
        ;      call      DisplayDebugData
        ;      call      ProcessDebugComms
;
Forever_SkipToHereWhenEditing:
;
              call      ProcessStepperMotor
              call      ProcessSensor1
 ;             call      ProcessSensor2
         ;     call      ProcessCalibrationValue
;
              call      ProcessMenu
;
 bsf SendSMS
              call      ProcessGSM
;
              goto      Forever
;
ProcessMenu:
;
              movf      MenuState,W,Access
              btfsc     ZeroFlag
              goto      ProcessMenu_3
;
              btfsc     Key_Menu
              goto      ProcessMenu_1
              btfsc     Key_Up
              goto      ProcessMenu_1
              btfsc     Key_Down
              goto      ProcessMenu_1
              btfsc     Key_Set
              goto      ProcessMenu_1
;
              goto      ProcessMenu_2
;
ProcessMenu_1:
;
              movlw     LOW(MenuTimeOutTC)
              movwf     MenuTimeOut,Access
              movlw     HIGH(MenuTimeOutTC)
              movwf     MenuTimeOutH,Access
;
ProcessMenu_2:
;
              movf      MenuTimeOut,W,Access
              iorwf     MenuTimeOutH,Access
              btfss     ZeroFlag
              goto      ProcessMenu_3
;
              reset                              ;Force a reset, so that we reload the existing settings
;
ProcessMenu_3:
;
MenuStateDispatcher:
;
#define S_Menu_Idle          0
#define S_Menu_Initialise    1
#define S_Menu_Set           2 
;
              clrf      PCLATU,Access
              movlw     HIGH(MenuStateDispatchTable) 
              movwf     PCLATH,Access
;
              movf      MenuState,W,Access
              rlcf      WREG,W,Access
              rlcf      WREG,W,Access
              andlw     b'11111100'
;
              addlw     LOW(MenuStateDispatchTable)
              btfsc     CarryFlag
              incf      PCLATH,Same,Access
              movwf     PCL,Access
;
MenuStateDispatchTable:
;
MenuSDT00:       goto      Menu_Idle
;
MenuSDT01:       goto      Menu_SettingsMenuInitialise
MenuSDT02:       goto      Menu_SettingsMenuYes
MenuSDT03:       goto      Menu_SettingsMenuNo 
;
MenuSDT04:       goto      Menu_FlowSetPointIs
                 goto      Menu_FlowSetPointIsNo
MenuSDT05:       goto      Menu_FlowSetPointIsYes
MenuSDT06:       goto      Menu_FlowSetPointEdit
MenuSDT07:       goto      Menu_FlowSetPointEditUnits
MenuSDT08:       goto      Menu_FlowSetPointEditTens
MenuSDT09:       goto      Menu_FlowSetPointEditHundreds
MenuSDT10:       goto      Menu_FlowSetPointEditThousands
;
MenuSDT11:       goto      Menu_ModeInitialise
MenuSDT12:       goto      Menu_ModeSelect
MenuSDT13:       goto      Menu_ModeFinalise
;
MenuSDT14:       goto      Menu_FaultRelayInitialise
MenuSDT15:       goto      Menu_FaultRelaySelect
MenuSDT16:       goto      Menu_FaultRelayFinalise
;
MenuSDT17:       goto      Menu_PasswordIs
MenuSDT18:       goto      Menu_PasswordIsNo
MenuSDT19:       goto      Menu_PasswordIsYes
MenuSDT20:       goto      Menu_PasswordEdit
MenuSDT21:       goto      Menu_PasswordEditUnits
MenuSDT22:       goto      Menu_PasswordEditTens
MenuSDT23:       goto      Menu_PasswordEditHundreds
MenuSDT24:       goto      Menu_PasswordEditThousands
;
MenuSDT25:       goto      Menu_Exit
MenuSDT26:       goto      RestartMenuState    
MenuSDT27:       goto      RestartMenuState
MenuSDT28:       goto      RestartMenuState
MenuSDT29:       goto      RestartMenuState
MenuSDT30:       goto      RestartMenuState
MenuSDT31:       goto      RestartMenuState
MenuSDT32:       goto      RestartMenuState
MenuSDT33:       goto      RestartMenuState
MenuSDT34:       goto      RestartMenuState
MenuSDT35:       goto      RestartMenuState
MenuSDT36:       goto      RestartMenuState
MenuSDT37:       goto      RestartMenuState
MenuSDT38:       goto      RestartMenuState
MenuSDT39:       goto      RestartMenuState
MenuSDT40:       goto      RestartMenuState
MenuSDT41:       goto      RestartMenuState
MenuSDT42:       goto      RestartMenuState
MenuSDT43:       goto      RestartMenuState
MenuSDT44:       goto      RestartMenuState
MenuSDT45:       goto      RestartMenuState
MenuSDT46:       goto      RestartMenuState
MenuSDT47:       goto      RestartMenuState
MenuSDT48:       goto      RestartMenuState
MenuSDT49:       goto      RestartMenuState
MenuSDT50:       goto      RestartMenuState
MenuSDT51:       goto      RestartMenuState
MenuSDT52:       goto      RestartMenuState
MenuSDT53:       goto      RestartMenuState
MenuSDT54:       goto      RestartMenuState
MenuSDT55:       goto      RestartMenuState
MenuSDT56:       goto      RestartMenuState
MenuSDT57:       goto      RestartMenuState
MenuSDT58:       goto      RestartMenuState
MenuSDT59:       goto      RestartMenuState
MenuSDT60:       goto      RestartMenuState
MenuSDT61:       goto      RestartMenuState
MenuSDT62:       goto      RestartMenuState
MenuSDT63:       goto      RestartMenuState
;
;************************************************
;
RestartMenuState:
;
              movlw     S_Menu_Idle
              movwf     MenuState,Access
;
              goto      MenuStateDispatcherEnd
;
;************************************************
;
Menu_Idle:
;
              btfss     Key_Set
              goto      Menu_Idle1
;
              bcf       Key_Set
              btg       FaultRelay
;
Menu_Idle1:
;
              btfss     Key_Menu
              goto      Menu_Idle_End
;
              bcf       Key_Menu
;
              incf      MenuState,Same,Access  
;
              movlw     LOW(MenuTimeOutTC)
              movwf     MenuTimeOut,Access
              movlw     HIGH(MenuTimeOutTC)
              movwf     MenuTimeOutH,Access
;
Menu_Idle_End:
;
              goto      MenuStateDispatcherEnd
;
;************************************************
;
Menu_SettingsMenuInitialise:
;
              SendStringToLCDLine1 S_SettingsMenu
              SendStringToLCDLine2 S_EditYes
;
              movlw     LCD_Line2+LCD_Column10
              call      WriteLCDInstruction
;
              call      Delay5msec
;
              movlw     b'00001111'
              call      WriteLCDInstruction
;
              call      Delay5msec
;
              bcf       Key_Set
              bcf       Key_Up
              bcf       Key_Down
              bcf       Key_Menu
;
              incf      MenuState,Same,Access
;
Menu_SettingsMenuInitialise_End:
;
              goto      MenuStateDispatcherEnd
;
Menu_SettingsMenuYes:
;
              btfss     Key_Set
              goto      Menu_SettingsMenuYes1
;
              bcf       Key_Set
; 
              incf      MenuState,Same,Access
              incf      MenuState,Same,Access
;
              goto      Menu_SettingsMenuYes_End
;
Menu_SettingsMenuYes1:
;
              btfsc     Key_Up
              goto      Menu_SettingsMenuYes2
;
              btfss     Key_Down
              goto      Menu_SettingsMenuYes3
;
Menu_SettingsMenuYes2:
;
              bcf       Key_Up
              bcf       Key_Down
;
              SendStringToLCDLine2 S_EditNo
;
              movlw     LCD_Line2+LCD_Column10
              call      WriteLCDInstruction
;
              call      Delay5msec
;
              incf      MenuState,Same,Access
;
              goto      Menu_FlowSetPointIsNo_End
;
Menu_SettingsMenuYes3:
;
Menu_SettingsMenuYes_End:
;
              goto      MenuStateDispatcherEnd
;
Menu_SettingsMenuNo:
;
              btfss     Key_Set
              goto      Menu_SettingsMenuNo1
;
              bcf       Key_Set
; 
              clrf      MenuState,Access
;
              goto      Menu_SettingsMenuNo_End
;
Menu_SettingsMenuNo1:
;
              btfsc     Key_Up
              goto      Menu_SettingsMenuNo2
;
              btfss     Key_Down
              goto      Menu_SettingsMenuNo3
;
Menu_SettingsMenuNo2:
;
              bcf       Key_Up
              bcf       Key_Down
;
              SendStringToLCDLine2 S_EditYes
;
              movlw     LCD_Line2+LCD_Column10
              call      WriteLCDInstruction
;
              call      Delay5msec
;
              decf      MenuState,Same,Access
;
              goto      Menu_FlowSetPointIsNo_End
;
Menu_SettingsMenuNo3:
;
Menu_SettingsMenuNo_End:
;
              goto      MenuStateDispatcherEnd
;
;************************************************
;
Menu_FlowSetPointIs:
;
              SendStringToLCDLine1 S_FlowSetPointIs
;
              movlw     LCD_Line1+LCD_Column12
              movwf     LCD_Pointer,Banked
;
              movf      FlowSetPoint,W,Banked
              movwf     Binary,Access
              movf      FlowSetPointH,W,Banked
              movwf     BinaryH,Access
;
              call      X_DisplayBinaryToLCDLine
;
              SendStringToLCDLine2 S_EditNo
;
              movlw     LCD_Line2+LCD_Column10
              call      WriteLCDInstruction
;
              call      Delay5msec
;
              movlw     b'00001111'
              call      WriteLCDInstruction
;
              call      Delay5msec
;
              bcf       Key_Set
              bcf       Key_Up
              bcf       Key_Down
              bcf       Key_Menu
;
              incf      MenuState,Same,Access
;
Menu_FlowSetPointIs_End:
;
              goto      MenuStateDispatcherEnd
;
Menu_FlowSetPointIsNo:
;
              btfss     Key_Set
              goto      Menu_FlowSetPointIsNo1
;
              bcf       Key_Set
; 
              movlw     7
              addwf     MenuState,Same,Access
;
              goto      Menu_FlowSetPointIsNo_End
;
Menu_FlowSetPointIsNo1:
;
              btfsc     Key_Up
              goto      Menu_FlowSetPointIsNo2
;
              btfss     Key_Down
              goto      Menu_FlowSetPointIsNo3  
;
Menu_FlowSetPointIsNo2:
;
              bcf       Key_Up
              bcf       Key_Down
;
              SendStringToLCDLine2 S_EditYes
;
              movlw     LCD_Line2+LCD_Column10
              call      WriteLCDInstruction
;
              call      Delay5msec
;
              incf      MenuState,Same,Access
;
              goto      Menu_FlowSetPointIsNo_End
;
Menu_FlowSetPointIsNo3:
;
Menu_FlowSetPointIsNo_End:
;
              goto      MenuStateDispatcherEnd
;
Menu_FlowSetPointIsYes:
;
              btfss     Key_Set
              goto      Menu_FlowSetPointIsYes1
;
              bcf       Key_Set
;
              incf      MenuState,Same,Access
;
              goto      Menu_FlowSetPointIsYes_End
;
Menu_FlowSetPointIsYes1:
;
              btfsc     Key_Up
              goto      Menu_FlowSetPointIsYes2
;
              btfss     Key_Down
              goto      Menu_FlowSetPointIsYes3
;
Menu_FlowSetPointIsYes2:
;
              bcf       Key_Up
              bcf       Key_Down
;
              SendStringToLCDLine2 S_EditNo
;
              movlw     LCD_Line2+LCD_Column10
              call      WriteLCDInstruction
;
              call      Delay5msec
;
              decf      MenuState,Same,Access
;
              goto      Menu_FlowSetPointIsYes_End
;
Menu_FlowSetPointIsYes3:
;
Menu_FlowSetPointIsYes_End:
;
              goto      MenuStateDispatcherEnd
;
Menu_FlowSetPointEdit:
;
              SendStringToLCDLine1 S_FlowSetPointEdit
              SendStringToLCDLine2 S_ClearLine 
;
              movlw     LCD_Line2+LCD_Column7
              movwf     LCD_Pointer,Banked
;
              movf      FlowSetPoint,W,Banked
              movwf     Binary,Access
              movf      FlowSetPointH,W,Banked
              movwf     BinaryH,Access
;
              call      X_DisplayBinaryToTHTULCDLine
;
              movlw     LCD_Line2+LCD_Column10
              call      WriteLCDInstruction
;
              call      Delay5msec
;
              movlw     b'00001111'
              call      WriteLCDInstruction
;
              call      Delay5msec
;
              bcf       Key_Set
              bcf       Key_Up
              bcf       Key_Down
              bcf       Key_Menu
;             
              incf      MenuState,Same,Access
;
              goto      MenuStateDispatcherEnd
;
Menu_FlowSetPointEditUnits:
;
              btfss     Key_Up
              goto      Menu_FSPEditUnits1
;
              bcf       Key_Up
;
              incf      Units,Same,Access
              movlw     10
              subwf     Units,W,Access
              movlw     0
              btfsc     CarryFlag
              movwf     Units,Access
;
              movlw     LCD_Line2+LCD_Column10
              call      WriteLCDInstruction
;
              call      Delay5msec
;
              movf      Units,W,Access
              addlw     BinaryToASCII
              call      WriteLCDByte
;
              movlw     LCD_Line2+LCD_Column10
              call      WriteLCDInstruction
;
              call      Delay5msec
;
Menu_FSPEditUnits1:
;
              btfss     Key_Down
              goto      Menu_FSPEditUnits2
;
              bcf       Key_Down
;
              decf      Units,Same,Access
              movlw     10
              subwf     Units,W,Access
              movlw     9
              btfsc     CarryFlag
              movwf     Units,Access
;
              movlw     LCD_Line2+LCD_Column10
              call      WriteLCDInstruction
;
              call      Delay5msec
;
              movf      Units,W,Access
              addlw     BinaryToASCII
              call      WriteLCDByte
;
              movlw     LCD_Line2+LCD_Column10
              call      WriteLCDInstruction
;
              call      Delay5msec
;
Menu_FSPEditUnits2:
;
              btfss     Key_Set
              goto      Menu_FSPEditUnitsEnd
;
              bcf       Key_Set
;
              movlw     LCD_Line2+LCD_Column9
              call      WriteLCDInstruction
;
              call      Delay5msec
;
              incf      MenuState,Same,Access
;
Menu_FSPEditUnitsEnd:
;
              goto      MenuStateDispatcherEnd
;
Menu_FlowSetPointEditTens:
;
              btfss     Key_Up
              goto      Menu_FSPEditTens1
;
              bcf       Key_Up
;
              incf      Tens,Same,Access
              movlw     10
              subwf     Tens,W,Access
              movlw     0
              btfsc     CarryFlag
              movwf     Tens,Access
;
              movlw     LCD_Line2+LCD_Column9
              call      WriteLCDInstruction
;
              call      Delay5msec
;
              movf      Tens,W,Access
              addlw     BinaryToASCII
              call      WriteLCDByte
;
              movlw     LCD_Line2+LCD_Column9
              call      WriteLCDInstruction
;
              call      Delay5msec
;
Menu_FSPEditTens1:
;
              btfss     Key_Down
              goto      Menu_FSPEditTens2
;
              bcf       Key_Down
;
              decf      Tens,Same,Access
              movlw     10
              subwf     Tens,W,Access
              movlw     9
              btfsc     CarryFlag
              movwf     Tens,Access
;
              movlw     LCD_Line2+LCD_Column9
              call      WriteLCDInstruction
;
              call      Delay5msec
;
              movf      Tens,W,Access
              addlw     BinaryToASCII
              call      WriteLCDByte
;
              movlw     LCD_Line2+LCD_Column9
              call      WriteLCDInstruction
;
              call      Delay5msec
;
Menu_FSPEditTens2:
;
              btfss     Key_Set
              goto      Menu_FSPEditTensEnd
;
              bcf       Key_Set
;
              movlw     LCD_Line2+LCD_Column8
              call      WriteLCDInstruction
;
              call      Delay5msec
;
              incf      MenuState,Same,Access
;
Menu_FSPEditTensEnd:
;
              goto      MenuStateDispatcherEnd
;
Menu_FlowSetPointEditHundreds:
;
              btfss     Key_Up
              goto      Menu_FSPEditHundreds1
;
              bcf       Key_Up
;
              incf      Hundreds,Same,Access
              movlw     10
              subwf     Hundreds,W,Access
              movlw     0
              btfsc     CarryFlag
              movwf     Hundreds,Access
;
              movlw     LCD_Line2+LCD_Column8
              call      WriteLCDInstruction
;
              call      Delay5msec
;
              movf      Hundreds,W,Access
              addlw     BinaryToASCII
              call      WriteLCDByte
;
              movlw     LCD_Line2+LCD_Column8
              call      WriteLCDInstruction
;
              call      Delay5msec
;
Menu_FSPEditHundreds1:
;
              btfss     Key_Down
              goto      Menu_FSPEditHundreds2
;
              bcf       Key_Down
;
              decf      Hundreds,Same,Access
              movlw     10
              subwf     Hundreds,W,Access
              movlw     9
              btfsc     CarryFlag
              movwf     Hundreds,Access
;
              movlw     LCD_Line2+LCD_Column8
              call      WriteLCDInstruction
;
              call      Delay5msec
;
              movf      Hundreds,W,Access
              addlw     BinaryToASCII
              call      WriteLCDByte
;
              movlw     LCD_Line2+LCD_Column8
              call      WriteLCDInstruction
;
              call      Delay5msec
;
Menu_FSPEditHundreds2:
;
              btfss     Key_Set
              goto      Menu_FSPEditHundredsEnd
;
              bcf       Key_Set
;
              movlw     LCD_Line2+LCD_Column7
              call      WriteLCDInstruction
;
              call      Delay5msec
;
              incf      MenuState,Same,Access
;
Menu_FSPEditHundredsEnd:
;
              goto      MenuStateDispatcherEnd
;
Menu_FlowSetPointEditThousands:
;
              btfss     Key_Up
              goto      Menu_FSPEditThousands1
;
              bcf       Key_Up
;
              incf      Thousands,Same,Access
              movlw     2
              subwf     Thousands,W,Access
              movlw     0
              btfsc     CarryFlag
              movwf     Thousands,Access
;
              movlw     LCD_Line2+LCD_Column7
              call      WriteLCDInstruction
;
              call      Delay5msec
;
              movf      Thousands,W,Access
              addlw     BinaryToASCII
              call      WriteLCDByte
;
              movlw     LCD_Line2+LCD_Column7
              call      WriteLCDInstruction
;
              call      Delay5msec
;
Menu_FSPEditThousands1:
;
              btfss     Key_Down
              goto      Menu_FSPEditThousands2
;
              bcf       Key_Down
;
              decf      Thousands,Same,Access
              movlw     2
              subwf     Thousands,W,Access
              movlw     1
              btfsc     CarryFlag
              movwf     Thousands,Access
;
              movlw     LCD_Line2+LCD_Column7
              call      WriteLCDInstruction
;
              call      Delay5msec
;
              movf      Thousands,W,Access
              addlw     BinaryToASCII
              call      WriteLCDByte
;
              movlw     LCD_Line2+LCD_Column7
              call      WriteLCDInstruction
;
              call      Delay5msec
;
Menu_FSPEditThousands2:
;
              btfss     Key_Set
              goto      Menu_FSPEditThousandsEnd
;
              bcf       Key_Set
;
              call      BCD2Binary
;
              movf      Binary,W,Access
              movwf     FlowSetPoint,Banked
              movf      BinaryH,W,Access
              movwf     FlowSetPointH,Banked
;
              movlw     7
              subwf     MenuState,Same,Access
;
Menu_FSPEditThousandsEnd:
;
              goto      MenuStateDispatcherEnd
;
;************************************************
;
Menu_ModeInitialise:
;
              SendStringToLCDLine1 S_ModeSelect
;
              btfss     ManualMode
              goto      Menu_ModeInitialiseAutomatic
;
Menu_ModeInitialiseManual:
;
              SendStringToLCDLine2 S_ModeSelectManual
;
              goto      Menu_ModeInitialiseEnd
;
Menu_ModeInitialiseAutomatic:
;
              SendStringToLCDLine2 S_ModeSelectAutomatic
;
Menu_ModeInitialiseEnd:
;
              movlw     LCD_Line2+LCD_Column6
              call      WriteLCDInstruction
;
              call      Delay5msec
;
              movlw     b'00001111'
              call      WriteLCDInstruction
;
              call      Delay5msec
;
              bcf       Key_Set
              bcf       Key_Up
              bcf       Key_Down
              bcf       Key_Menu
;
              incf      MenuState,Same,Access
;
              goto      MenuStateDispatcherEnd
;
Menu_ModeSelect:
;
              btfsc     Key_Up
              goto      Menu_ModeSelect1
;
              btfss     Key_Down
              goto      Menu_ModeSelect2
;
Menu_ModeSelect1:
;
              bcf       Key_Up
              bcf       Key_Down
;
              btg       ManualMode
;  
              decf      MenuState,Same,Access
;
              goto      Menu_ModeSelectEnd
;
Menu_ModeSelect2:
;
              btfss     Key_Set
              goto      Menu_ModeSelect3
;
              bcf       Key_Set
;
              incf      MenuState,Same,Access
;
              goto      Menu_ModeSelectEnd
;
Menu_ModeSelect3:
;
Menu_ModeSelectEnd:
;
              goto      MenuStateDispatcherEnd
;
Menu_ModeFinalise:
;
              incf      MenuState,Same,Access
;
Menu_ModeFinaliseEnd:
;
              goto      MenuStateDispatcherEnd
;
;************************************************
;
Menu_FaultRelayInitialise:
;
              SendStringToLCDLine1 S_FaultRelay
;
              btfss     FaultRelay
              goto      Menu_FaultRelayInitialiseDisable
;
Menu_FaultRelayInitaliseEnable:
;
              SendStringToLCDLine2 S_FaultRelayEnable
;
              goto      Menu_FaultRelayInitialiseEnd
;
Menu_FaultRelayInitialiseDisable:
;
              SendStringToLCDLine2 S_FaultRelayDisable
;
Menu_FaultRelayInitialiseEnd:
;
              movlw     LCD_Line2+LCD_Column6
              call      WriteLCDInstruction
;
              call      Delay5msec
;
              movlw     b'00001111'
              call      WriteLCDInstruction
;
              call      Delay5msec
;
              bcf       Key_Set
              bcf       Key_Up
              bcf       Key_Down
              bcf       Key_Menu
;
              incf      MenuState,Same,Access
;
              goto      MenuStateDispatcherEnd
;
Menu_FaultRelaySelect:
;
              btfsc     Key_Up
              goto      Menu_FaultRelaySelect1
;
              btfss     Key_Down
              goto      Menu_FaultRelaySelect2
;
Menu_FaultRelaySelect1:
;
              bcf       Key_Up
              bcf       Key_Down
;
              btg       FaultRelay
;  
              decf      MenuState,Same,Access
;
              goto      Menu_FaultRelaySelectEnd
;
Menu_FaultRelaySelect2:
;
              btfss     Key_Set
              goto      Menu_FaultRelaySelect3
;
              bcf       Key_Set
;
              incf      MenuState,Same,Access
;
              goto      Menu_FaultRelaySelectEnd
;
Menu_FaultRelaySelect3:
;
Menu_FaultRelaySelectEnd:
;
              goto      MenuStateDispatcherEnd
;
Menu_FaultRelayFinalise:
;
              incf      MenuState,Same,Access
;
Menu_FaultRelayFinaliseEnd:
;
              goto      MenuStateDispatcherEnd
;
;************************************************
;
Menu_PasswordIs:
;
              SendStringToLCDLine1 S_PasswordIs
              movf      PasswordThousands,W,Banked 
              call      WriteLCDByte
              movf      PasswordHundreds,W,Banked 
              call      WriteLCDByte 
              movf      PasswordTens,W,Banked 
              call      WriteLCDByte 
              movf      PasswordUnits,W,Banked 
              call      WriteLCDByte 
;
              SendStringToLCDLine2 S_EditNo
;
              movlw     LCD_Line2+LCD_Column10
              call      WriteLCDInstruction
;
              call      Delay5msec
;
              movlw     b'00001111'
              call      WriteLCDInstruction
;
              call      Delay5msec
;
              bcf       Key_Set
              bcf       Key_Up
              bcf       Key_Down
              bcf       Key_Menu
;
              incf      MenuState,Same,Access
;
Menu_PasswordIs_End:
;
              goto      MenuStateDispatcherEnd
;
Menu_PasswordIsNo:
;
              btfss     Key_Set
              goto      Menu_PasswordIsNo1
;
              bcf       Key_Set
; 
              movlw     7
              addwf     MenuState,Same,Access
;
              goto      Menu_PasswordIsNo_End
;
Menu_PasswordIsNo1:
;
              btfsc     Key_Up
              goto      Menu_PasswordIsNo2
;
              btfss     Key_Down
              goto      Menu_PasswordIsNo3  
;
Menu_PasswordIsNo2:
;
              bcf       Key_Up
              bcf       Key_Down
;
              SendStringToLCDLine2 S_EditYes
;
              movlw     LCD_Line2+LCD_Column10
              call      WriteLCDInstruction
;
              call      Delay5msec
;
              incf      MenuState,Same,Access
;
              goto      Menu_PasswordIsNo_End
;
Menu_PasswordIsNo3:
;
Menu_PasswordIsNo_End:
;
              goto      MenuStateDispatcherEnd
;
Menu_PasswordIsYes:
;
              btfss     Key_Set
              goto      Menu_PasswordIsYes1
;
              bcf       Key_Set
;
              incf      MenuState,Same,Access
;
              goto      Menu_PasswordIsYes_End
;
Menu_PasswordIsYes1:
;
              btfsc     Key_Up
              goto      Menu_PasswordIsYes2
;
              btfss     Key_Down
              goto      Menu_PasswordIsYes3
;
Menu_PasswordIsYes2:
;
              bcf       Key_Up
              bcf       Key_Down
;
              SendStringToLCDLine2 S_EditNo
;
              movlw     LCD_Line2+LCD_Column10
              call      WriteLCDInstruction
;
              call      Delay5msec
;
              decf      MenuState,Same,Access
;
              goto      Menu_PasswordIsYes_End
;
Menu_PasswordIsYes3:
;
Menu_PasswordIsYes_End:
;
              goto      MenuStateDispatcherEnd
;
Menu_PasswordEdit:
;
              SendStringToLCDLine1 S_PasswordEdit
              SendStringToLCDLine2 S_ClearLine 
;
              movlw     LCD_Line2+LCD_Column7
              call      WriteLCDInstruction
;
              call      Delay5msec
;
              movf      PasswordThousands,W,Banked
              call      WriteLCDByte
;
              movf      PasswordHundreds,W,Banked
              call      WriteLCDByte
;
              movf      PasswordTens,W,Banked
              call      WriteLCDByte
;
              movf      PasswordUnits,W,Banked
              call      WriteLCDByte
;
              movlw     LCD_Line2+LCD_Column10
              call      WriteLCDInstruction
;
              call      Delay5msec
;
              movlw     b'00001111'
              call      WriteLCDInstruction
;
              call      Delay5msec
;
              bcf       Key_Set
              bcf       Key_Up
              bcf       Key_Down
              bcf       Key_Menu
;             
              incf      MenuState,Same,Access
;
              goto      MenuStateDispatcherEnd
;
Menu_PasswordEditUnits:
;
              btfss     Key_Up
              goto      Menu_PasswordEditUnits1
;
              bcf       Key_Up
;
              incf      PasswordUnits,Same,Banked
              movlw     '9'+1
              subwf     PasswordUnits,W,Banked
              movlw     '0'
              btfsc     CarryFlag
              movwf     PasswordUnits,Banked
;
              movlw     LCD_Line2+LCD_Column10
              call      WriteLCDInstruction
;
              call      Delay5msec
;
              movf      PasswordUnits,W,Banked
              call      WriteLCDByte
;
              movlw     LCD_Line2+LCD_Column10
              call      WriteLCDInstruction
;
              call      Delay5msec
;
Menu_PasswordEditUnits1:
;
              btfss     Key_Down
              goto      Menu_PasswordEditUnits2
;
              bcf       Key_Down
;
              decf      PasswordUnits,Same,Banked
              movlw     '0'
              subwf     PasswordUnits,W,Banked
              movlw     '9'
              btfss     CarryFlag
              movwf     PasswordUnits,Banked
;
              movlw     LCD_Line2+LCD_Column10
              call      WriteLCDInstruction
;
              call      Delay5msec
;
              movf      PasswordUnits,W,Banked
              call      WriteLCDByte
;
              movlw     LCD_Line2+LCD_Column10
              call      WriteLCDInstruction
;
              call      Delay5msec
;
Menu_PasswordEditUnits2:
;
              btfss     Key_Set
              goto      Menu_PasswordEditUnitsEnd
;
              bcf       Key_Set
;
              movlw     LCD_Line2+LCD_Column9
              call      WriteLCDInstruction
;
              call      Delay5msec
;
              incf      MenuState,Same,Access
;
Menu_PasswordEditUnitsEnd:
;
              goto      MenuStateDispatcherEnd
;
Menu_PasswordEditTens:
;
              btfss     Key_Up
              goto      Menu_PasswordEditTens1
;
              bcf       Key_Up
;
              incf      PasswordTens,Same,Banked
              movlw     '9'+1
              subwf     PasswordTens,W,Banked
              movlw     '0'
              btfsc     CarryFlag
              movwf     PasswordTens,Banked
;
              movlw     LCD_Line2+LCD_Column9
              call      WriteLCDInstruction
;
              call      Delay5msec
;
              movf      PasswordTens,W,Banked
              call      WriteLCDByte
;
              movlw     LCD_Line2+LCD_Column9
              call      WriteLCDInstruction
;
              call      Delay5msec
;
Menu_PasswordEditTens1:
;
              btfss     Key_Down
              goto      Menu_PasswordEditTens2
;
              bcf       Key_Down
;
              decf      PasswordTens,Same,Banked
              movlw     '0'
              subwf     PasswordTens,W,Banked
              movlw     '9'
              btfss     CarryFlag
              movwf     PasswordTens,Banked
;
              movlw     LCD_Line2+LCD_Column9
              call      WriteLCDInstruction
;
              call      Delay5msec
;
              movf      PasswordTens,W,Banked
              call      WriteLCDByte
;
              movlw     LCD_Line2+LCD_Column9
              call      WriteLCDInstruction
;
              call      Delay5msec
;
Menu_PasswordEditTens2:
;
              btfss     Key_Set
              goto      Menu_PasswordEditTensEnd
;
              bcf       Key_Set
;
              movlw     LCD_Line2+LCD_Column8
              call      WriteLCDInstruction
;
              call      Delay5msec
;
              incf      MenuState,Same,Access
;
Menu_PasswordEditTensEnd:
;
              goto      MenuStateDispatcherEnd
;
Menu_PasswordEditHundreds:
;
              btfss     Key_Up
              goto      Menu_PasswordEditHundreds1
;
              bcf       Key_Up
;
              incf      PasswordHundreds,Same,Banked
              movlw     '9'+1
              subwf     PasswordHundreds,W,Banked
              movlw     '0'
              btfsc     CarryFlag
              movwf     PasswordHundreds,Banked
;
              movlw     LCD_Line2+LCD_Column8
              call      WriteLCDInstruction
;
              call      Delay5msec
;
              movf      PasswordHundreds,W,Banked
              call      WriteLCDByte
;
              movlw     LCD_Line2+LCD_Column8
              call      WriteLCDInstruction
;
              call      Delay5msec
;
Menu_PasswordEditHundreds1:
;
              btfss     Key_Down
              goto      Menu_PasswordEditHundreds2
;
              bcf       Key_Down
;
              decf      PasswordHundreds,Same,Banked
              movlw     '0'
              subwf     PasswordHundreds,W,Banked
              movlw     '9'
              btfss     CarryFlag
              movwf     PasswordHundreds,Banked
;
              movlw     LCD_Line2+LCD_Column8
              call      WriteLCDInstruction
;
              call      Delay5msec
;
              movf      PasswordHundreds,W,Banked
              call      WriteLCDByte
;
              movlw     LCD_Line2+LCD_Column8
              call      WriteLCDInstruction
;
              call      Delay5msec
;
Menu_PasswordEditHundreds2:
;
              btfss     Key_Set
              goto      Menu_PasswordEditHundredsEnd
;
              bcf       Key_Set
;
              movlw     LCD_Line2+LCD_Column7
              call      WriteLCDInstruction
;
              call      Delay5msec
;
              incf      MenuState,Same,Access
;
Menu_PasswordEditHundredsEnd:
;
              goto      MenuStateDispatcherEnd
;
Menu_PasswordEditThousands:
;
              btfss     Key_Up
              goto      Menu_PasswordEditThousands1
;
              bcf       Key_Up
;
              incf      PasswordThousands,Same,Banked
              movlw     '9'+1
              subwf     PasswordThousands,W,Banked
              movlw     '0'
              btfsc     CarryFlag
              movwf     PasswordThousands,Banked
;
              movlw     LCD_Line2+LCD_Column7
              call      WriteLCDInstruction
;
              call      Delay5msec
;
              movf      PasswordThousands,W,Banked
              call      WriteLCDByte
;
              movlw     LCD_Line2+LCD_Column7
              call      WriteLCDInstruction
;
              call      Delay5msec
;
Menu_PasswordEditThousands1:
;
              btfss     Key_Down
              goto      Menu_PasswordEditThousands2
;
              bcf       Key_Down
;
              decf      PasswordThousands,Same,Banked
              movlw     '0'
              subwf     PasswordThousands,W,Banked
              movlw     '9'
              btfss     CarryFlag
              movwf     PasswordThousands,Banked
;
              movlw     LCD_Line2+LCD_Column7
              call      WriteLCDInstruction
;
              call      Delay5msec
;
              movf      PasswordThousands,W,Banked
              call      WriteLCDByte
;
              movlw     LCD_Line2+LCD_Column7
              call      WriteLCDInstruction
;
              call      Delay5msec
;
Menu_PasswordEditThousands2:
;
              btfss     Key_Set
              goto      Menu_PasswordEditThousandsEnd
;
              bcf       Key_Set
;
              movlw     7
              subwf     MenuState,Same,Access
;
Menu_PasswordEditThousandsEnd:
;
              goto      MenuStateDispatcherEnd
;
Menu_Exit:
;
; Verify the settings in the EEPROM reflect the settings in memmory and refresh if necessary
;
Menu_Exit_FlowSetPoint:
;
              movlw     EE_FlowSetPoint
              call      ReadInternalEEPROM
              subwf     FlowSetPoint,W,Banked
;
              btfsc     ZeroFlag
              goto      Menu_Exit_FlowSetPoint_End
;
              movf      FlowSetPoint,W,Banked
              call      WriteInternalEEPROM
;
              call      Delay10msec
;
              goto      Menu_Exit_FlowSetPoint
;
Menu_Exit_FlowSetPoint_End:
;
Menu_Exit_FlowSetPointH:
;
              movlw     EE_FlowSetPointH
              call      ReadInternalEEPROM
              subwf     FlowSetPointH,W,Banked
;
              btfsc     ZeroFlag
              goto      Menu_Exit_FlowSetPointH_End
;
              movf      FlowSetPointH,W,Banked
              call      WriteInternalEEPROM
;
              call      Delay10msec
;
              goto      Menu_Exit_FlowSetPointH
;
Menu_Exit_FlowSetPointH_End:
;
Menu_Exit_NonVolatileFlags:
;
              movlw     EE_NonVolatileFlags
              call      ReadInternalEEPROM
              subwf     Flags7,W,Access
;
              btfsc     ZeroFlag
              goto      Menu_Exit_NonVolatileFlags_End
;
              movf      Flags7,W,Access
              call      WriteInternalEEPROM
;
              call      Delay10msec
;
              goto      Menu_Exit_NonVolatileFlags
;
Menu_Exit_NonVolatileFlags_End:
;
Menu_Exit_PasswordThousands:
;
              movlw     EE_PasswordThousands
              call      ReadInternalEEPROM
              subwf     PasswordThousands,W,Banked
;
              btfsc     ZeroFlag
              goto      Menu_Exit_PasswordThousands_End
;
              movf      PasswordThousands,W,Banked
              call      WriteInternalEEPROM
;
              call      Delay10msec
 ;
              goto       Menu_Exit_PasswordThousands
;
Menu_Exit_PasswordThousands_End: 
;
Menu_Exit_PasswordHundreds:
;
              movlw     EE_PasswordHundreds
              call      ReadInternalEEPROM
              subwf     PasswordHundreds,W,Banked
;
              btfsc     ZeroFlag
              goto      Menu_Exit_PasswordHundreds_End
;
              movf      PasswordHundreds,W,Banked
              call      WriteInternalEEPROM 
;
              call      Delay10msec
;
              goto      Menu_Exit_PasswordHundreds
;
Menu_Exit_PasswordHundreds_End:
;
Menu_Exit_PasswordTens:
;
              movlw     EE_PasswordTens
              call      ReadInternalEEPROM
              subwf     PasswordTens,W,Banked
;
              btfsc     ZeroFlag
              goto      Menu_Exit_PasswordTens_End
;
              movf      PasswordTens,W,Banked
              call      WriteInternalEEPROM
;
              call      Delay10msec
;
              goto      Menu_Exit_PasswordTens
;
Menu_Exit_PasswordTens_End:
;
Menu_Exit_PasswordUnits:
;
              movlw     EE_PasswordUnits
              call      ReadInternalEEPROM
              subwf     PasswordUnits,W,Banked
;
              btfsc     ZeroFlag
              goto      Menu_Exit_PasswordUnits_End
;
              movf      PasswordUnits,W,Banked
              call      WriteInternalEEPROM
;
              call      Delay10msec
;
              goto      Menu_Exit_PasswordUnits
;
Menu_Exit_PasswordUnits_End:
;
Menu_Exit_AlertNumber0:
;
              movlw     EE_AlertNumber+0
              call      ReadInternalEEPROM
              movff     AlertNumber+0,WREG
              subwf     EEDATA,W,Access
;
              btfsc     ZeroFlag
              goto      Menu_Exit_AlertNumber0_End
;
              movff     AlertNumber+0,WREG
              call      WriteInternalEEPROM
;
              call      Delay10msec
;
              goto      Menu_Exit_AlertNumber0
;
Menu_Exit_AlertNumber0_End:
;
Menu_Exit_AlertNumber1:
;
              movlw     EE_AlertNumber+1
              call      ReadInternalEEPROM
              movff     AlertNumber+1,WREG
              subwf     EEDATA,W,Access
;
              btfsc     ZeroFlag
              goto      Menu_Exit_AlertNumber1_End
;
              movff     AlertNumber+1,WREG
              call      WriteInternalEEPROM
;
              call      Delay10msec
;
              goto      Menu_Exit_AlertNumber1
;
Menu_Exit_AlertNumber1_End:
;
Menu_Exit_AlertNumber2:
;
              movlw     EE_AlertNumber+2
              call      ReadInternalEEPROM
              movff     AlertNumber+2,WREG
              subwf     EEDATA,W,Access
;
              btfsc     ZeroFlag
              goto      Menu_Exit_AlertNumber2_End
;
              movff     AlertNumber+2,WREG
              call      WriteInternalEEPROM
;
              call      Delay10msec
;
              goto      Menu_Exit_AlertNumber2
;
Menu_Exit_AlertNumber2_End:
;
Menu_Exit_AlertNumber3:
;
              movlw     EE_AlertNumber+3
              call      ReadInternalEEPROM
              movff     AlertNumber+3,WREG
              subwf     EEDATA,W,Access
;
              btfsc     ZeroFlag
              goto      Menu_Exit_AlertNumber3_End
;
              movff     AlertNumber+3,WREG
              call      WriteInternalEEPROM
;
              call      Delay10msec
;
              goto      Menu_Exit_AlertNumber3
;
Menu_Exit_AlertNumber3_End:
;
Menu_Exit_AlertNumber4:
;
              movlw     EE_AlertNumber+4
              call      ReadInternalEEPROM
              movff     AlertNumber+4,WREG
              subwf     EEDATA,W,Access
;
              btfsc     ZeroFlag
              goto      Menu_Exit_AlertNumber4_End
;
              movff     AlertNumber+4,WREG
              call      WriteInternalEEPROM
;
              call      Delay10msec
;
              goto      Menu_Exit_AlertNumber4
;
Menu_Exit_AlertNumber4_End:
;
Menu_Exit_AlertNumber5:
;
              movlw     EE_AlertNumber+5
              call      ReadInternalEEPROM
              movff     AlertNumber+5,WREG
              subwf     EEDATA,W,Access
;
              btfsc     ZeroFlag
              goto      Menu_Exit_AlertNumber5_End
;
              movff     AlertNumber+5,WREG
              call      WriteInternalEEPROM
;
              call      Delay10msec
;
              goto      Menu_Exit_AlertNumber5
;
Menu_Exit_AlertNumber5_End:
;
Menu_Exit_AlertNumber6:
;
              movlw     EE_AlertNumber+6
              call      ReadInternalEEPROM
              movff     AlertNumber+6,WREG
              subwf     EEDATA,W,Access
;
              btfsc     ZeroFlag
              goto      Menu_Exit_AlertNumber6_End
;
              movff     AlertNumber+6,WREG
              call      WriteInternalEEPROM
;
              call      Delay10msec
;
              goto      Menu_Exit_AlertNumber6
;
Menu_Exit_AlertNumber6_End:
;
Menu_Exit_AlertNumber7:
;
              movlw     EE_AlertNumber+7
              call      ReadInternalEEPROM
              movff     AlertNumber+7,WREG
              subwf     EEDATA,W,Access
;
              btfsc     ZeroFlag
              goto      Menu_Exit_AlertNumber7_End
;
              movff     AlertNumber+7,WREG
              call      WriteInternalEEPROM
;
              call      Delay10msec
;
              goto      Menu_Exit_AlertNumber7
;
Menu_Exit_AlertNumber7_End:
;
Menu_Exit_AlertNumber8:
;
              movlw     EE_AlertNumber+8
              call      ReadInternalEEPROM
              movff     AlertNumber+8,WREG
              subwf     EEDATA,W,Access
;
              btfsc     ZeroFlag
              goto      Menu_Exit_AlertNumber8_End
;
              movff     AlertNumber+8,WREG
              call      WriteInternalEEPROM
;
              call      Delay10msec
;
              goto      Menu_Exit_AlertNumber8
;
Menu_Exit_AlertNumber8_End:
;
Menu_Exit_AlertNumber9:
;
              movlw     EE_AlertNumber+9
              call      ReadInternalEEPROM
              movff     AlertNumber+9,WREG
              subwf     EEDATA,W,Access
;
              btfsc     ZeroFlag
              goto      Menu_Exit_AlertNumber9_End
;
              movff     AlertNumber+9,WREG
              call      WriteInternalEEPROM
;
              call      Delay10msec
;
              goto      Menu_Exit_AlertNumber9
;
Menu_Exit_AlertNumber9_End:
;
              movlw     4 ;S_AutomaticInitialise
              movwf     MainState,Access
;
              clrf      MenuState,Access
;
              goto      MenuStateDispatcherEnd
;
MenuStateDispatcherEnd:
;
ProcessMenuEnd:
;          
              return
;
ProcessCalibrationValue:
;
;              btfss     Key_Up
;              goto      ProcessCalibrationValue1
;;
;              bcf       Key_Up
;;
;              btfss     CalibrationUnlock
;              goto      ProcessCalibrationValue1
;;
;              movlw     1
;              addwf     FlowMeterCalibration,Same,Banked
;;
;              movlw     200
;              subwf     FlowMeterCalibration,W,Banked
;              movlw     199
;              btfsc     CarryFlag
;              movwf     FlowMeterCalibration,Banked
;;
;              bcf       I2CBUS_Error
;;
;              call      OpenWrite256
;              movf      FlowMeterCalibration,W,Banked
;              call      Write256
;              call      I2CBUS1Stop
;;
;              CopyBit   I2CBUS_Error,I2CBUS_Error_EEPROM
;;
;              call      Delay10msec
;;
;ProcessCalibrationValue1:
;;
;              btfss     Key_Menu
;              goto      ProcessCalibrationValue2
;;
;              bcf       Key_Menu
;;
;              btfss     CalibrationUnlock
;              goto      ProcessCalibrationValue2
;;
;              decfsz    FlowMeterCalibration,W,Banked
;              decf      FlowMeterCalibration,Same,Banked
;;
;              bcf       I2CBUS_Error
;;
;              call      OpenWrite256
;              movf      FlowMeterCalibration,W,Banked
;              call      Write256
;              call      I2CBUS1Stop
;;
;              CopyBit   I2CBUS_Error,I2CBUS_Error_EEPROM
;;
;              call      Delay10msec
;;
;ProcessCalibrationValue2:
;
              return
;
ProcessFlow:
;
; 0x000167AE14
; 0x0001A5A4A0
; 0x00022422D0
; 0x0001445740
; 0x0001280000
#define GoldenNumber0 h'00'
#define GoldenNumber1 h'00'
#define GoldenNumber2 h'28'
#define GoldenNumber3 h'01'
#define GoldenNumber4 h'00'
;
;*    21.63 6143     = 332 l/h   70999  
;*    10.53 3500ish  = 683 l/h   34512
;*    16.67 4009     = 431 l/h   54691
;*
;* 
;*
;* 977d d858
              movlw     GoldenNumber0 
              movwf     CalculatorX0,Access
              movlw     GoldenNumber1
              movwf     CalculatorX1,Access
              movlw     GoldenNumber2
              movwf     CalculatorX2,Access
              movlw     GoldenNumber3
              movwf     CalculatorX3,Access
              movlw     GoldenNumber4
              movwf     CalculatorX4,Access
;
              movff     Interrupt1Time,CalculatorY0
              movff     Interrupt1TimeH,CalculatorY1
              movff     Interrupt1TimeHH,CalculatorY2
              clrf      CalculatorY3,Access
              clrf      CalculatorY4,Access
;
              call      Div40
;
; Now average the reading from the flow meter
; - The newest FLOW must be in CalculatorX0 and CalculatorX1
;
              movlw     FilterSize
              movwf     MedianCounter,Banked
;
              lfsr      0,Flow0Age
;
Filter1:      decfsz    POSTINC0,Same,Access
              goto      Filter2
;
              movf      POSTDEC0,W,Access
;
              movff     FSR0L,MedianNewSamplePointer
              movff     FSR0H,MedianNewSamplePointerH
;
              movlw     FilterSize
              movwf     POSTINC0,Access
              movff     CalculatorX0,POSTINC0
              movff     CalculatorX1,POSTINC0
;
              goto      Filter3
;
Filter2:      movf      POSTINC0,W,Access        ;Dummy +1
              movf      POSTINC0,W,Access        ;Dummy +1 
;
Filter3:      decfsz    MedianCounter,Same,Banked
              goto      Filter1
;
           IFDEF FilterProcessVariable
;
           IFDEF MedianFilter   
;
              movff     MedianNewSamplePointer,FSR0L
              movff     MedianNewSamplePointerH,FSR0H 
;
; See if the new sample is right at the top or right at the bottom
;
              movlw     LOW(Flow0Age)
              subwf     FSR0L,W,Access
              btfss     ZeroFlag
              goto      Filter4
;
              movlw     HIGH(Flow0Age)
              subwfb    FSR0H,W,Access
              btfsc     ZeroFlag
              goto      MedianSink
;
Filter4:
;
              movlw     LOW(Flow0Age+((FilterSize-1)*3))
              subwf     FSR0L,W,Access
              btfss     ZeroFlag
              goto      Filter5
;
              movlw     HIGH(Flow0Age+((FilterSize-1)*3))
              subwfb    FSR0H,W,Access
              btfsc     ZeroFlag
              goto      MedianFloat
;
Filter5:
;      
; The new sample is somewhere in the middle, see if it must float up or sink down
;              
              movf      POSTINC0,W,Access        ;Point to next higher sample and check that it is higher than the new one
              movf      POSTINC0,W,Access 
              movf      POSTINC0,W,Access
;
              movf      POSTINC0,W,Access        ;Skip Age
;
              movf      CalculatorX0,W,Access
              subwf     POSTINC0,W,Access
              movf      CalculatorX1,W,Access
              subwfb    POSTINC0,W,Access
              btfss     CarryFlag
              goto      MedianSink 
;              
              movlw     8                        ;Point to next lower sample and check that it is lower than the new one
              subwf     FSR0L,Same,Access
              movlw     0
              subwfb    FSR0H,Same,Access
;
              movf      POSTINC0,W,Access
              subwf     CalculatorX0,W,Access
              movf      POSTINC0,W,Access
              subwfb    CalculatorX1,W,Access
              btfss     CarryFlag
              goto      MedianFloat
;
              goto      MedianEnd                ;It is in the right place
;
MedianSink:
;
              movff     MedianNewSamplePointer,FSR0L
              movff     MedianNewSamplePointerH,FSR0H 
              movff     MedianNewSamplePointer,FSR1L
              movff     MedianNewSamplePointerH,FSR1H 
;
MedianSink1:
;
; See if the new sample is right at the bottom
;
              movlw     LOW(Flow0Age+((FilterSize-1)*3))
              subwf     FSR0L,W,Access
              btfss     ZeroFlag
              goto      MedianSink2
;
              movlw     HIGH(Flow0Age+((FilterSize-1)*3))
              subwfb    FSR0H,W,Access
              btfsc     ZeroFlag
              goto      MedianSinkEnd
;
MedianSink2:
;
              movf      POSTINC0,W,Access        ;Point to the next higher sample and check that it is higher than the new one
              movf      POSTINC0,W,Access
              movf      POSTINC0,W,Access
              movf      POSTINC0,W,Access
;
              movf      CalculatorX0,W,Access
              subwf     POSTINC0,W,Access
              movf      CalculatorX1,W,Access
              subwfb    INDF0,W,Access
              btfsc     CarryFlag
              goto      MedianSinkEnd
;
              movff     POSTDEC0,MedianTempH
              movff     POSTDEC0,MedianTemp
              movff     INDF0,MedianTempAge
              movff     POSTINC1,POSTINC0
              movff     POSTINC1,POSTINC0
              movff     INDF1,INDF0
              movff     MedianTempH,POSTDEC1
              movff     MedianTemp,POSTDEC1
              movff     MedianTempAge,POSTINC1
              movf      POSTINC1,W,Access
              movf      POSTINC1,W,Access
              movf      POSTDEC0,W,Access
              movf      POSTDEC0,W,Access
;             
              goto      MedianSink1
;
MedianSinkEnd:
;
              goto      MedianEnd
;
MedianFloat:
;
              movff     MedianNewSamplePointer,FSR0L
              movff     MedianNewSamplePointerH,FSR0H 
              movff     MedianNewSamplePointer,FSR1L
              movff     MedianNewSamplePointerH,FSR1H 
;
MedianFloat1:
;
; See if the new sample is right at the top
;
              movlw     LOW(Flow0Age)
              subwf     FSR0L,W,Access
              btfss     ZeroFlag
              goto      MedianFloat2  
;
              movlw     HIGH(Flow0Age)
              subwfb    FSR0H,W,Access
              btfsc     ZeroFlag
              goto      MedianFloatEnd
;
MedianFloat2:
;
              movf      POSTDEC0,W,Access        ;Point to the next lower sample and check that it is lower than the new one
              movf      POSTDEC0,W,Access
;
              movf      POSTINC0,W,Access
              subwf     CalculatorX0,W,Access
              movf      INDF0,W,Access
              subwfb    CalculatorX1,W,Access
              btfsc     CarryFlag
              goto      MedianFloatEnd
;
              movff     POSTDEC0,MedianTempH
              movff     POSTDEC0,MedianTemp
              movff     INDF0,MedianTempAge
              movff     POSTINC1,POSTINC0
              movff     POSTINC1,POSTINC0
              movff     INDF1,INDF0
              movff     MedianTempH,POSTDEC1
              movff     MedianTemp,POSTDEC1
              movff     MedianTempAge,POSTDEC1
              movf      POSTDEC1,W,Access
              movf      POSTDEC1,W,Access
              movf      POSTDEC0,W,Access
              movf      POSTDEC0,W,Access
;             
              goto      MedianFloat1
;
MedianFloatEnd:
;
              goto      MedianEnd
;
MedianEnd:
;
              movff     Flow4,CalculatorX0
              movff     Flow4H,CalculatorX1
;
           ELSE 
;
              movff     Flow0,CalculatorX0
              movff     Flow0H,CalculatorX1
              clrf      CalculatorX2,Access
;
              movff     Flow1,WREG
              addwf     CalculatorX0,Same,Access
              movff     Flow1H,WREG
              addwfc    CalculatorX1,Same,Access
              movlw     0
              addwfc    CalculatorX2,Same,Access
;
              movff     Flow2,WREG
              addwf     CalculatorX0,Same,Access
              movff     Flow2H,WREG
              addwfc    CalculatorX1,Same,Access
              movlw     0
              addwfc    CalculatorX2,Same,Access
;
              movff     Flow3,WREG
              addwf     CalculatorX0,Same,Access
              movff     Flow3H,WREG
              addwfc    CalculatorX1,Same,Access
              movlw     0
              addwfc    CalculatorX2,Same,Access
;
              movff     Flow4,WREG
              addwf     CalculatorX0,Same,Access
              movff     Flow4H,WREG
              addwfc    CalculatorX1,Same,Access
              movlw     0
              addwfc    CalculatorX2,Same,Access
;
              movff     Flow5,WREG
              addwf     CalculatorX0,Same,Access
              movff     Flow5H,WREG
              addwfc    CalculatorX1,Same,Access
              movlw     0
              addwfc    CalculatorX2,Same,Access
;
              movff     Flow6,WREG
              addwf     CalculatorX0,Same,Access
              movff     Flow6H,WREG
              addwfc    CalculatorX1,Same,Access
              movlw     0
              addwfc    CalculatorX2,Same,Access
;
              movff     Flow7,WREG
              addwf     CalculatorX0,Same,Access
              movff     Flow7H,WREG
              addwfc    CalculatorX1,Same,Access
              movlw     0
              addwfc    CalculatorX2,Same,Access
;
              movff     Flow8,WREG
              addwf     CalculatorX0,Same,Access
              movff     Flow8H,WREG
              addwfc    CalculatorX1,Same,Access
              movlw     0
              addwfc    CalculatorX2,Same,Access
;
              movff     Flow9,WREG
              addwf     CalculatorX0,Same,Access
              movff     Flow9H,WREG
              addwfc    CalculatorX1,Same,Access
              movlw     0
              addwfc    CalculatorX2,Same,Access
;
; Find the high and subtract it
;
              clrf      CalculatorY0,Access
              clrf      CalculatorY1,Access
;
              movf      CalculatorY0,W,Access
              subwf     Flow0,W,Banked
              movf      CalculatorY1,W,Access
              subwfb    Flow0H,W,Banked
              btfsc     CarryFlag
              movff     Flow0,CalculatorY0
              btfsc     CarryFlag
              movff     Flow0H,CalculatorY1
;
              movf      CalculatorY0,W,Access
              subwf     Flow1,W,Banked
              movf      CalculatorY1,W,Access
              subwfb    Flow1H,W,Banked
              btfsc     CarryFlag
              movff     Flow1,CalculatorY0
              btfsc     CarryFlag
              movff     Flow1H,CalculatorY1
;
              movf      CalculatorY0,W,Access
              subwf     Flow2,W,Banked
              movf      CalculatorY1,W,Access
              subwfb    Flow2H,W,Banked
              btfsc     CarryFlag
              movff     Flow2,CalculatorY0
              btfsc     CarryFlag
              movff     Flow2H,CalculatorY1
;
              movf      CalculatorY0,W,Access
              subwf     Flow3,W,Banked
              movf      CalculatorY1,W,Access
              subwfb    Flow3H,W,Banked
              btfsc     CarryFlag
              movff     Flow3,CalculatorY0
              btfsc     CarryFlag
              movff     Flow3H,CalculatorY1
;
              movf      CalculatorY0,W,Access
              subwf     Flow4,W,Banked
              movf      CalculatorY1,W,Access
              subwfb    Flow4H,W,Banked
              btfsc     CarryFlag
              movff     Flow4,CalculatorY0
              btfsc     CarryFlag
              movff     Flow4H,CalculatorY1
;
              movf      CalculatorY0,W,Access
              subwf     Flow5,W,Banked
              movf      CalculatorY1,W,Access
              subwfb    Flow5H,W,Banked
              btfsc     CarryFlag
              movff     Flow5,CalculatorY0
              btfsc     CarryFlag
              movff     Flow5H,CalculatorY1
;
              movf      CalculatorY0,W,Access
              subwf     Flow6,W,Banked
              movf      CalculatorY1,W,Access
              subwfb    Flow6H,W,Banked
              btfsc     CarryFlag
              movff     Flow6,CalculatorY0
              btfsc     CarryFlag
              movff     Flow6H,CalculatorY1
;
              movf      CalculatorY0,W,Access
              subwf     Flow7,W,Banked
              movf      CalculatorY1,W,Access
              subwfb    Flow7H,W,Banked
              btfsc     CarryFlag
              movff     Flow7,CalculatorY0
              btfsc     CarryFlag
              movff     Flow7H,CalculatorY1
;
              movf      CalculatorY0,W,Access
              subwf     Flow8,W,Banked
              movf      CalculatorY1,W,Access
              subwfb    Flow8H,W,Banked
              btfsc     CarryFlag
              movff     Flow8,CalculatorY0
              btfsc     CarryFlag
              movff     Flow8H,CalculatorY1
;
              movf      CalculatorY0,W,Access
              subwf     Flow9,W,Banked
              movf      CalculatorY1,W,Access
              subwfb    Flow9H,W,Banked
              btfsc     CarryFlag
              movff     Flow9,CalculatorY0
              btfsc     CarryFlag
              movff     Flow9H,CalculatorY1
;
              movf      CalculatorY0,W,Access
              subwf     CalculatorX0,Same,Access
              movf      CalculatorY1,W,Access
              subwfb    CalculatorX1,Same,Access
              movlw     0                      
              subwfb    CalculatorX2,Same,Access
;
; Find the low and subtract it
;
              movlw     0xFF
              movwf     CalculatorY0,Access
              movwf     CalculatorY1,Access
;
              movf      CalculatorY0,W,Access
              subwf     Flow0,W,Banked
              movf      CalculatorY1,W,Access
              subwfb    Flow0H,W,Banked
              btfss     CarryFlag
              movff     Flow0,CalculatorY0
              btfss     CarryFlag
              movff     Flow0H,CalculatorY1
;
              movf      CalculatorY0,W,Access
              subwf     Flow1,W,Banked
              movf      CalculatorY1,W,Access
              subwfb    Flow1H,W,Banked
              btfss     CarryFlag
              movff     Flow1,CalculatorY0
              btfss     CarryFlag
              movff     Flow1H,CalculatorY1
;
              movf      CalculatorY0,W,Access
              subwf     Flow2,W,Banked
              movf      CalculatorY1,W,Access
              subwfb    Flow2H,W,Banked
              btfss     CarryFlag
              movff     Flow2,CalculatorY0
              btfss     CarryFlag
              movff     Flow2H,CalculatorY1
;
              movf      CalculatorY0,W,Access
              subwf     Flow3,W,Banked
              movf      CalculatorY1,W,Access
              subwfb    Flow3H,W,Banked
              btfss     CarryFlag
              movff     Flow3,CalculatorY0
              btfss     CarryFlag
              movff     Flow3H,CalculatorY1
;
              movf      CalculatorY0,W,Access
              subwf     Flow4,W,Banked
              movf      CalculatorY1,W,Access
              subwfb    Flow4H,W,Banked
              btfss     CarryFlag
              movff     Flow4,CalculatorY0
              btfss     CarryFlag
              movff     Flow4H,CalculatorY1
;
              movf      CalculatorY0,W,Access
              subwf     Flow5,W,Banked
              movf      CalculatorY1,W,Access
              subwfb    Flow5H,W,Banked
              btfss     CarryFlag
              movff     Flow5,CalculatorY0
              btfss     CarryFlag
              movff     Flow5H,CalculatorY1
;
              movf      CalculatorY0,W,Access
              subwf     Flow6,W,Banked
              movf      CalculatorY1,W,Access
              subwfb    Flow6H,W,Banked
              btfss     CarryFlag
              movff     Flow6,CalculatorY0
              btfss     CarryFlag
              movff     Flow6H,CalculatorY1
;
              movf      CalculatorY0,W,Access
              subwf     Flow7,W,Banked
              movf      CalculatorY1,W,Access
              subwfb    Flow7H,W,Banked
              btfss     CarryFlag
              movff     Flow7,CalculatorY0
              btfss     CarryFlag
              movff     Flow7H,CalculatorY1
;
              movf      CalculatorY0,W,Access
              subwf     Flow8,W,Banked
              movf      CalculatorY1,W,Access
              subwfb    Flow8H,W,Banked
              btfss     CarryFlag
              movff     Flow8,CalculatorY0
              btfss     CarryFlag
              movff     Flow8H,CalculatorY1
;
              movf      CalculatorY0,W,Access
              subwf     Flow9,W,Banked
              movf      CalculatorY1,W,Access
              subwfb    Flow9H,W,Banked
              btfss     CarryFlag
              movff     Flow9,CalculatorY0
              btfss     CarryFlag
              movff     Flow9H,CalculatorY1
;
              movf      CalculatorY0,W,Access
              subwf     CalculatorX0,Same,Access
              movf      CalculatorY1,W,Access
              subwfb    CalculatorX1,Same,Access
              movlw     0                      
              subwfb    CalculatorX2,Same,Access
;         
              rrcf      CalculatorX2,Same,Access
              rrcf      CalculatorX1,Same,Access
              rrcf      CalculatorX0,Same,Access
;         
              rrcf      CalculatorX2,Same,Access
              rrcf      CalculatorX1,Same,Access
              rrcf      CalculatorX0,Same,Access
;         
              rrcf      CalculatorX2,Same,Access
              rrcf      CalculatorX1,Same,Access
              rrcf      CalculatorX0,Same,Access
;
           ENDIF
;
        ELSE
;  
 ;             movff     Flow0,CalculatorX0
 ;             movff     Flow0H,CalculatorX1
;
        ENDIF
;
              clrf      CalculatorX2,Access
              clrf      CalculatorX3,Access
              clrf      CalculatorX4,Access
;
; Now I can use the flow to manipulate the stepp motor
; - But first apply the compensation
;








              movff     CalculatorX0,FlowProcessVariable
              movff     CalculatorX1,FlowProcessVariableH
;
              movf      FlowProcessVariable,W,Banked
              addwf     DisplayFlow_Total,Same,Banked
              movf      FlowProcessVariableH,W,Banked
              addwfc    DisplayFlow_TotalH,Same,Banked
;
              incf      DisplayFlow_Count,Same,Banked
;
ProcessFlowEnd:
;
              return

ProcessMainState:
;
MainStateDispatcher:
;
#define S_PowerUp             0
#define S_SplashInitialise    1
#define S_SplashTimeOut       2
#define S_SplashFinalise      3 
#define S_AutomaticInitialise 4
#define S_Automatic           5
#define S_AutomaticFinalise   6
#define S_ManualInitialise    7
#define S_Manual              8
#define S_ManualFinalise      9
#define S_FlowFault           10
;
              clrf      PCLATU,Access
              movlw     HIGH(MainStateDispatchTable) 
              movwf     PCLATH,Access
;
              movf      MainState,W,Access
              rlcf      WREG,W,Access
              rlcf      WREG,W,Access
              andlw     b'01111100'
;
              addlw     LOW(MainStateDispatchTable)
              btfsc     CarryFlag
              incf      PCLATH,Same,Access
              movwf     PCL,Access
;
MainStateDispatchTable:
;
MSDT00:       goto      PowerUp
MSDT01:       goto      SplashInitialise          
MSDT02:       goto      SplashTimeOut
MSDT03:       goto      SplashFinalise 
MSDT04:       goto      AutomaticInitialise
MSDT05:       goto      Automatic
MSDT06:       goto      AutomaticFinalise
MSDT07:       goto      ManualInitialise
MSDT08:       goto      Manual
MSDT09:       goto      ManualFinalise
MSDT10:       goto      FlowFault
MSDT11:       goto      RestartMainState
MSDT12:       goto      RestartMainState
MSDT13:       goto      RestartMainState
MSDT14:       goto      RestartMainState
MSDT15:       goto      RestartMainState
MSDT16:       goto      RestartMainState
MSDT17:       goto      RestartMainState
MSDT18:       goto      RestartMainState
MSDT19:       goto      RestartMainState
MSDT20:       goto      RestartMainState
MSDT21:       goto      RestartMainState
MSDT22:       goto      RestartMainState
MSDT23:       goto      RestartMainState
MSDT24:       goto      RestartMainState
MSDT25:       goto      RestartMainState
MSDT26:       goto      RestartMainState
MSDT27:       goto      RestartMainState
MSDT28:       goto      RestartMainState
MSDT29:       goto      RestartMainState
MSDT30:       goto      RestartMainState
MSDT31:       goto      RestartMainState
;
RestartMainState:
;
              movlw     S_PowerUp
              movwf     MainState,Access
;
              goto      ProcessMainState
;
PowerUp:
;
; This state implements everything that is required when the system powers up
; 



;
              movlw     S_SplashInitialise
              movwf     MainState,Access
;
PowerUp_End:
;
              goto      MainStateEnd
;
SplashInitialise:
;
; This state writes the SPLASH message to the displasy and sets the "Splash" timer
;
              SendStringToLCDLine1 S_Splash1_LCD 
              SendStringToLCDLine2 S_Splash2_LCD   
;
              movlw     LOW(Splash_Time)
              movwf     Timer_GP1,Access
              movlw     HIGH(Splash_Time)
              movwf     Timer_GP1H,Access
;
              movlw     S_SplashTimeOut
              movwf     MainState,Access
;
SplashInitialise_End:
;
              goto      MainStateEnd
;
SplashTimeOut:
;
; This state waits for the "SPLASH" timer to time out
;
              movf     Timer_GP1,W,Access
              iorwf    Timer_GP1H,W,Access
              btfss    ZeroFlag
              goto     SplashTimeOut_End
;
              movlw     S_SplashFinalise
              movwf     MainState,Access
;
SplashTimeOut_End:
;
              goto      MainStateEnd
;
SplashFinalise:
;
; This state clears the SPLASH message
;
              SendStringToLCDLine1 S_ClearLine
              SendStringToLCDLine2 S_ClearLine   
;
              movlw     S_AutomaticInitialise
              movwf     MainState,Access
;
SplashFinalise_End:
;
              goto      MainStateEnd
;
AutomaticInitialise:
;
; This state sets up the LCD for AUTOMATIC
;
              btfss     FaultRelay
              goto      AutomaticInitNoFR
              goto      AutomaticInitWithFR
;
AutomaticInitNoFR:
              SendStringToLCDLine1 S_Automatic1NoFR
              goto      AutomaticInitEnd
;
AutomaticInitWithFR:
              SendStringToLCDLine1 S_Automatic1WithFR
              goto      AutomaticInitEnd
;
AutomaticInitEnd:
;
              movlw     S_Automatic
              movwf     MainState,Access
;
AutomaticInitialiseEnd:
;
              goto      MainState
;
Automatic:
;
; This is where the Automatic control takes place
;
              btfsc     ManualMode
              goto      Automatic1
;
              movf      OverRideTimer,W,Banked
              iorwf     OverRideTimerH,W,Banked
              btfsc     ZeroFlag
              goto      Automatic2
;
Automatic1:
;
              movlw     S_AutomaticFinalise
              movwf     MainState,Access
;
              goto      AutomaticEnd
;
Automatic2:
;
              btfss     RefreshLCD
              goto      AutomaticEnd
;
              bcf       RefreshLCD
              btg       TracePin
;
              btfss     FaultRelay
              goto      Automatic2NoFR
              goto      Automatic2WithFR
;
Automatic2NoFR:
              SendStringToLCDLine1 S_Automatic1NoFR
              goto      Automatic3
;
Automatic2WithFR:
              SendStringToLCDLine1 S_Automatic1WithFR
              goto      Automatic3
;
Automatic3:
;
; Display the process variable
;
              movlw     LCD_Line2+LCD_Column3
              movwf     LCD_Pointer,Banked
;
              movf      DisplayFlow_Count,W,Banked
              btfss     ZeroFlag
              goto      Automatic2_Average
;
              movf      FlowProcessVariable,W,Banked
              movwf     Binary,Access
              movf      FlowProcessVariableH,W,Banked
              movwf     BinaryH,Access
;
              goto      Automatic2_Display
;
Automatic2_Average:
;
              movff     DisplayFlow_Total,CalculatorX0
              movff     DisplayFlow_TotalH,CalculatorX1
              clrf      CalculatorX2,Access
              clrf      CalculatorX3,Access
              clrf      CalculatorX4,Access
;
              movff     DisplayFlow_Count,CalculatorY0
              clrf      CalculatorY1,Access
              clrf      CalculatorY2,Access
              clrf      CalculatorY3,Access
              clrf      CalculatorY4,Access
;
              call      Div40
;
              movff     CalculatorX0,Binary
              movff     CalculatorX1,BinaryH
;
              movff     CalculatorX0,FlowForDisplay
              movff     CalculatorX1,FlowForDisplayH
;
Automatic2_Display:
;
              clrf      DisplayFlow_Total,Banked
              clrf      DisplayFlow_TotalH,Banked
              clrf      DisplayFlow_Count,Banked
;
              call      AdjustFlow
;
              call      X_DisplayBinaryToLCDLine
;
; In relation to the setpoint
;
              call      HeartBeatCharacter
              call      WriteLCDByte
;
              movlw     LCD_Line2+LCD_Column9
              movwf     LCD_Pointer,Banked
;
              movf      FlowSetPoint,W,Banked
              movwf     Binary,Access
              movf      FlowSetPointH,W,Banked
              movwf     BinaryH,Access
;
              call      X_DisplayBinaryToLCDLine
;
              goto      AutomaticEnd
;
              btfsc     ControlFlow
              goto      Automatic1
;
  ;G121            btfsc     FreezeStepperMotor
  ;            goto      Automatic1
;
              CloseValve
;
              movlw     LOW(3000)
              movwf     Steps,Access
              movlw     HIGH(3000)
              movwf     StepsH,Access
;
       ;       movlw     S_WaitUntilClosed
              movwf     MainState,Access
;
              goto      AutomaticEnd
;
Automatic1aaa:
;
   ;G121           btfsc     FreezeStepperMotor 
   ;           goto      AutomaticEnd
;
              bcf       _GIEH
              movf      FlowTimer,W,Access
              iorwf     FlowTimerH,W,Access
              bsf       _GIEH
              btfsc     ZeroFlag
              call      KickStartFlow
;
AutomaticProcessFlow:
;
              btfss     ProcessNewFlowData
              goto      AutomaticProcessFlowEnd
;
              bcf       ProcessNewFlowData
;
              bcf       _GIEH
              movf      FlowSetPoint,W,Banked
              subwf     FlowProcessVariable,W,Banked
              movwf     FlowError,Banked
              movf      FlowSetPointH,W,Banked
              subwfb    FlowProcessVariableH,W,Banked
              movwf     FlowErrorH,Banked
              bsf       _GIEH
              btfss     CarryFlag
              goto      AutomaticProcessFlowOpen
              goto      AutomaticProcessFlowClose
;
AutomaticProcessFlowOpen:
;
              SkipIfValveOpen
              clrf      Integral,Banked
              OpenValve
;
              goto      AutomaticProcessFlowError
;
AutomaticProcessFlowClose:
;
              SkipIfValveClosed
              clrf      Integral,Banked
              CloseValve
;
              goto      AutomaticProcessFlowError
;
AutomaticProcessFlowError:
;
              movf      FlowError,W,Banked
              iorwf     FlowErrorH,W,Banked
              btfsc     ZeroFlag
              goto      AutomaticProcessFlowReset
;
              btfsc     CarryFlag
              goto      AutomaticProcessFlowError1
;
              comf      FlowError,Same,Banked
              comf      FlowErrorH,Same,Banked
              movlw     1
              addwf     FlowError,Same,Banked
              movlw     0
              addwfc    FlowErrorH,Same,Banked
;
AutomaticProcessFlowError1:
;
              movlw     LOW(500)
              subwf     FlowError,W,Banked
              movlw     HIGH(500)
              subwfb    FlowErrorH,W,Banked
;
              btfss     CarryFlag
              goto      AutomaticProcessFlowError3
;
              incf      Integral,Same,Banked
              movlw     25
              subwf     Integral,W,Banked
              movlw     25
              btfsc     CarryFlag    
              movwf     Integral,Banked
;
              goto      AutomaticProcessFlowError3a
;
AutomaticProcessFlowError3:
;
              clrf      Integral,Banked

AutomaticProcessFlowError3a:
;
#define MotorFactor 2
;
              movlw     LOW(5000)
              subwf     FlowError,W,Banked
              movlw     HIGH(5000)
              subwfb    FlowErrorH,W,Banked
;
              btfss     CarryFlag
              goto      AutomaticProcessFlowError4
;
              movlw     LOW(64*MotorFactor) ;250
              movwf     FlowError,Banked
              movlw     HIGH(64*MotorFactor)
              movwf     FlowErrorH,Banked
;
              goto      AutomaticProcessFlowErrorApply
;
AutomaticProcessFlowError4:
;
              movlw     LOW(2400)
              subwf     FlowError,W,Banked
              movlw     HIGH(2400)
              subwfb    FlowErrorH,W,Banked
;
              btfss     CarryFlag
              goto      AutomaticProcessFlowError5
;
              movlw     LOW(32*MotorFactor) ;64
              movwf     FlowError,Banked
              movlw     HIGH(32*MotorFactor)
              movwf     FlowErrorH,Banked
;
              goto      AutomaticProcessFlowErrorApply
;
AutomaticProcessFlowError5:
;
              movlw     LOW(1600)
              subwf     FlowError,W,Banked
              movlw     HIGH(1600)
              subwfb    FlowErrorH,W,Banked
;
              btfss     CarryFlag
              goto      AutomaticProcessFlowError6
;
              movlw     LOW(16*MotorFactor) ;32
              movwf     FlowError,Banked
              movlw     HIGH(16*MotorFactor)
              movwf     FlowErrorH,Banked
;
              goto      AutomaticProcessFlowErrorApply
;
AutomaticProcessFlowError6:
;
              movlw     LOW(400)
              subwf     FlowError,W,Banked
              movlw     HIGH(400)
              subwfb    FlowErrorH,W,Banked
;
              btfss     CarryFlag
              goto      AutomaticProcessFlowError7
;
              movlw     LOW(8*MotorFactor) ;16
              movwf     FlowError,Banked
              movlw     HIGH(8*MotorFactor)
              movwf     FlowErrorH,Banked
;
              goto      AutomaticProcessFlowErrorApply
;
AutomaticProcessFlowError7:
;
              movlw     LOW(200)
              subwf     FlowError,W,Banked
              movlw     HIGH(200)
              subwfb    FlowErrorH,W,Banked
;
              btfss     CarryFlag
              goto      AutomaticProcessFlowError8
;
              movlw     LOW(4*MotorFactor)
              movwf     FlowError,Banked
              movlw     HIGH(4*MotorFactor)
              movwf     FlowErrorH,Banked
;
              goto      AutomaticProcessFlowErrorApply
;
AutomaticProcessFlowError8:
;
              movlw     LOW(100)
              subwf     FlowError,W,Banked
              movlw     HIGH(100)
              subwfb    FlowErrorH,W,Banked
;
              btfss     CarryFlag
              goto      AutomaticProcessFlowError9
;
              movlw     LOW(2*MotorFactor)
              movwf     FlowError,Banked
              movlw     HIGH(2*MotorFactor)
              movwf     FlowErrorH,Banked
;
              goto      AutomaticProcessFlowErrorApply
;
AutomaticProcessFlowError9:
;
              movlw     LOW(10)
              subwf     FlowError,W,Banked
              movlw     HIGH(10)
              subwfb    FlowErrorH,W,Banked
;
              btfss     CarryFlag
              goto      AutomaticProcessFlowError10
;
              movlw     LOW(1*MotorFactor)
              movwf     FlowError,Banked
              movlw     HIGH(1*MotorFactor)
              movwf     FlowErrorH,Banked
;
              goto      AutomaticProcessFlowErrorApply
;
AutomaticProcessFlowError10:
;
              movlw     LOW(0)
              movwf     FlowError,Banked
              movlw     HIGH(0)
              movwf     FlowErrorH,Banked
;
              goto      AutomaticProcessFlowErrorApply
;             
AutomaticProcessFlowErrorApply:
;
              movf      FlowError,W,Banked
              subwf     Steps,W,Access
              movf      FlowErrorH,W,Banked
              subwfb    StepsH,W,Access
;
              btfsc     CarryFlag
              goto      AutomaticProcessFlowErrorApply1     
;
              movff     FlowError,Steps
              movff     FlowErrorH,StepsH
;
;AutomaticProcessFlowErrorApply1:
;
              movf      Steps,W,Access
              iorwf     StepsH,W,Access
              btfsc     ZeroFlag
              incf      Steps,Same,Access
;
              movf      Integral,W,Banked
              addwf     Steps,Same,Access
              movlw     0
              addwfc    StepsH,Same,Access
;
              goto      AutomaticProcessFlowEnd
;
AutomaticProcessFlowReset:
;
              clrf      Integral,Banked
;    
AutomaticProcessFlowErrorApply1:
AutomaticProcessFlowEnd:
;
AutomaticEnd:
;
              goto      MainStateEnd
;
AutomaticFinalise:
;



; 
              movlw     S_ManualInitialise
              movwf     MainState,Access
;             
AutomaticFinaliseEnd:
;
              goto      MainStateEnd
;
ManualInitialise:
;
; This state sets up the LCD for MANUAL
;
              btfss     FaultRelay
              goto      ManualInitNoFR
              goto      ManualInitWithFR
;
ManualInitNoFR:
              SendStringToLCDLine1 S_Manual1NoFR
              goto      ManualInitEnd
;
ManualInitWithFR:
              SendStringToLCDLine1 S_Manual1WithFR
              goto      ManualInitEnd
;
ManualInitEnd:
;
              SendStringToLCDLine2 S_Manual2
;
              movlw     S_Manual
              movwf     MainState,Access
;
ManualInitialiseEnd:
;
              goto      MainState
;
Manual:
;
; We just have to display the flow, so that the user knows where they stand
;
              btfsc     ManualMode
              goto      Manual1
;
              movf      OverRideTimer,W,Banked
              iorwf     OverRideTimerH,W,Banked
              btfss     ZeroFlag
              goto      Manual1
;
              movlw     S_ManualFinalise
              movwf     MainState,Access
;
              goto      ManualEnd
;
Manual1:
;
              btfss     RefreshLCD
              goto      ManualEnd
;
              bcf       RefreshLCD
;
              btfsc     ManualMode
              goto      Manual2
;
;
; Display a count down
;
              movlw     LCD_Line1+LCD_Column8
              call      WriteLCDInstruction
;
              call      Delay5msec
;
              movlw     ' '
              call      WriteLCDByte
              movlw     ' '
              call      WriteLCDByte
              movlw     ' '
              call      WriteLCDByte
              movlw     ' '
              call      WriteLCDByte
;
              movlw     LCD_Line1+LCD_Column12
              movwf     LCD_Pointer,Banked
;
              movf      OverRideTimer,W,Banked
              movwf     Binary,Access
              movf      OverRideTimerH,W,Banked
              movwf     BinaryH,Access
;
              call      X_DisplayBinaryToLCDLine
;
              goto      Manual3
;
Manual2:
;
              btfss     FaultRelay
              goto      Manual2NoFR
              goto      Manual2WithFR
;
Manual2NoFR:
              SendStringToLCDLine1 S_Manual1NoFR
              goto      Manual2End
;
Manual2WithFR:
              SendStringToLCDLine1 S_Manual1WithFR
              goto      Manual2End
;
Manual2End:
;
              goto      Manual3
;
Manual3:
;
; Display the process variable
;
              movlw     LCD_Line2+LCD_Column3
              movwf     LCD_Pointer,Banked
;
              movf      DisplayFlow_Count,W,Banked
              btfss     ZeroFlag
              goto      Manual2_Average
;
              movf      FlowProcessVariable,W,Banked
              movwf     Binary,Access
              movf      FlowProcessVariableH,W,Banked
              movwf     BinaryH,Access
;
              goto      Manual2_Display
;
Manual2_Average:
;
              movff     DisplayFlow_Total,CalculatorX0
              movff     DisplayFlow_TotalH,CalculatorX1
              clrf      CalculatorX2,Access
              clrf      CalculatorX3,Access
              clrf      CalculatorX4,Access
;
              movff     DisplayFlow_Count,CalculatorY0
              clrf      CalculatorY1,Access
              clrf      CalculatorY2,Access
              clrf      CalculatorY3,Access
              clrf      CalculatorY4,Access
;
              call      Div40
;
              movff     CalculatorX0,Binary
              movff     CalculatorX1,BinaryH
;
              movff     CalculatorX0,FlowForDisplay
              movff     CalculatorX1,FlowForDisplayH
;
Manual2_Display:
;
              clrf      DisplayFlow_Total,Banked
              clrf      DisplayFlow_TotalH,Banked
              clrf      DisplayFlow_Count,Banked
;
              call      X_DisplayBinaryToLCDLine
;
; In relation to the setpoint
;
              call      HeartBeatCharacter
              call      WriteLCDByte
;
              movlw     LCD_Line2+LCD_Column9
              movwf     LCD_Pointer,Banked
;
              movf      FlowSetPoint,W,Banked
              movwf     Binary,Access
              movf      FlowSetPointH,W,Banked
              movwf     BinaryH,Access
;
              call      X_DisplayBinaryToLCDLine
;
              goto      ManualEnd
;
ManualEnd:
;
              goto      MainStateEnd
;
ManualFinalise:
; 
              movlw     S_AutomaticInitialise
              movwf     MainState,Access
;             
ManualFinaliseEnd:
;
              goto      MainStateEnd
;
FlowFault:
;
              SendStringToLCDLine1 S_FlowFault1
              SendStringToLCDLine2 S_FlowFault2
;
              bsf       FaultRelayPin
;
              btfsc     Key_Set
              reset
;
FlowFaultEnd:
;
              goto      MainStateEnd
;
MainStateEnd:
;
              return
;
HeartBeatCharacter:
;
              clrf      PCLATU,Access
              movlw     HIGH(HeartBeatDispatchTable) 
              movwf     PCLATH,Access
;
              movf      HeartBeatState,W,Access
              incf      HeartBeatState,Same,Access
              rlcf      WREG,W,Access
              andlw     b'00000110'
;
              addlw     LOW(HeartBeatDispatchTable)
              btfsc     CarryFlag
              incf      PCLATH,Same,Access
              movwf     PCL,Access
;
HeartBeatDispatchTable:
;
HBDT00:       retlw     '/'
HBDT01:       retlw     '-'
HBDT02:       retlw     0xCD
HBDT03:       retlw     '|'
;
ProcessManualOverRide:
;
              movlw     Key_SetStart
              btfss     Key_Up
              movwf     Key_SetKick,Banked
;
              btfss     Key_Up
              goto      ProcessManualOverRide1
;
              movlw     Key_DownStart
              movwf     Key_DownKick,Banked
;
              movf      AutoRepeat,W,Banked
;
              btfss     ZeroFlag
              goto      ProcessManualOverRide1
;
              movlw     AutoRepeatTC
              movwf     AutoRepeat,Banked
;
              movlw     LOW(ManualOverRideTC)
              movwf     OverRideTimer,Banked
              movlw     HIGH(ManualOverRideTC)
              movwf     OverRideTimerH,Banked  
;
              OpenValve
;
              movlw     Key_SetIncrement
              addwf     Key_SetKick,Same,Banked
              movlw     255
              btfsc     CarryFlag
              movwf     Key_SetKick,Banked
;
              movf      Key_SetKick,W,Banked
;
              movwf     Steps,Access
              clrf      StepsH,Access
;
ProcessManualOverRide1:
;
              movlw     Key_DownStart
              btfss     Key_Down
              movwf     Key_DownKick,Banked
;
              btfss     Key_Down
              goto      ProcessManualOverRide2
;
              movlw     Key_SetStart
              movwf     Key_SetKick,Banked
;
              movf      AutoRepeat,W,Banked
;
              btfss     ZeroFlag
              goto      ProcessManualOverRide2
;
              movlw     AutoRepeatTC
              movwf     AutoRepeat,Banked
;
              movlw     LOW(ManualOverRideTC)
              movwf     OverRideTimer,Banked
              movlw     HIGH(ManualOverRideTC)
              movwf     OverRideTimerH,Banked  
;
              CloseValve
;
              movlw     Key_DownIncrement
              addwf     Key_DownKick,Same,Banked
              movlw     255
              btfsc     CarryFlag
              movwf     Key_DownKick,Banked
;
              movf      Key_DownKick,W,Banked
;
              movwf     Steps,Access
              clrf      StepsH,Access
;
ProcessManualOverRide2:
;
ProcessManualOverRide_End:
;
              return
;
;********************************************************************************************
;********************************************************************************************
;********************************************************************************************
;
ProcessDebugComms:
;
              call      CheckByteSerialBuffer2
              btfss     CarryFlag
              goto      ProcessCommsEnd
;
 btg RedLED
;
              xorlw     '?'
              btfsc     ZeroFlag
              goto      ProcessCommsCommandHelp
;
              xorlw     'a'^'?'
              btfsc     ZeroFlag
              goto      ProcessCommsAutomatic
;
              xorlw     'A'^'a'
              btfsc     ZeroFlag
              goto      ProcessCommsAutomatic
;
              xorlw     'c'^'A'
              btfsc     ZeroFlag
              goto      ProcessCommsClose1Step
;
              xorlw     'C'^'c'
              btfsc     ZeroFlag
              goto      ProcessCommsClose100Steps
;
              xorlw     'f'^'C'
              btfsc     ZeroFlag
              goto      ProcessCommsFlowMeterData
;
              xorlw     'F'^'f'
              btfsc     ZeroFlag
              goto      ProcessCommsFlowMeterData
;
              xorlw     'k'^'F'
              btfsc     ZeroFlag
              goto      ProcessCommsCalibrationData
;
              xorlw     'K'^'k'
              btfsc     ZeroFlag
              goto      ProcessCommsCalibrationData
;
              xorlw     'm'^'K'
              btfsc     ZeroFlag
              goto      ProcessCommsManual
;
              xorlw     'M'^'m'
              btfsc     ZeroFlag
              goto      ProcessCommsManual
;
              xorlw     'o'^'M'
              btfsc     ZeroFlag
              goto      ProcessCommsOpen1Step
;
              xorlw     'O'^'o'
              btfsc     ZeroFlag
              goto      ProcessCommsOpen100Steps
;
              xorlw     'v'^'O'
              btfsc     ZeroFlag
              goto      ProcessCommsValveData  
;
              xorlw     'V'^'v'
              btfsc     ZeroFlag
              goto      ProcessCommsValveData  
;
              goto      ProcessCommsEnd
;
ProcessCommsCommandHelp:
;
; ? = Command help
; a = Automatic
; c = Close valve 1 step, (ONLY IN MANUAL)
; C = Close valve 100 steps, (ONLY IN MANUAL)
; d = Decrement valve number
; f = Flow meter data
; i = Increment valve number
; k = Kalibration data
; m = Manual
; o = Open valve 1 step, (ONLY IN MANUAL)
; O = Open valve 100 steps, (ONLY in MANUAL)
; p = Packet data
; r = Reset flow pulse counters
; s = Speed data
; v = Valve data
;
              SendStringToDebugPortSlow S_Splash1
              call      DisplayOnDebug_Version 
              SendStringToDebugPortSlow S_Splash2
              SendStringToDebugPortSlow S_Help_a 
              SendStringToDebugPortSlow S_Help_c 
              SendStringToDebugPortSlow S_Help_C 
              SendStringToDebugPortSlow S_Help_d 
              SendStringToDebugPortSlow S_Help_f 
              SendStringToDebugPortSlow S_Help_i 
              SendStringToDebugPortSlow S_Help_k 
              SendStringToDebugPortSlow S_Help_m 
              SendStringToDebugPortSlow S_Help_o 
              SendStringToDebugPortSlow S_Help_O 
              SendStringToDebugPortSlow S_Help_p 
              SendStringToDebugPortSlow S_Help_r 
              SendStringToDebugPortSlow S_Help_d 
              SendStringToDebugPortSlow S_Help_v 
;
              movlw     NewDataDelayTC
              movwf     NewDataTimer,Access
              movlw     CommandHelpDelayCount
              movwf     NewDataDelayCounter,Access
;
              bcf       TransmitNewData
;
              goto      ProcessCommsEnd
;
ProcessCommsAutomatic:
;
              movlw     S_Automatic
              movwf     MainState,Access
;
              goto      ProcessCommsEnd
;
ProcessCommsClose1Step:
;
  ;            movlw     S_Manual
  ;            subwf     MainState,W,Access
  ;            btfss     ZeroFlag
  ;            goto      ProcessCommsClose1StepEnd
;
              CloseValve
;
              movlw     1 
              movwf     Steps,Access
              clrf      StepsH,Access
;
ProcessCommsClose1StepEnd:
; 
              goto      ProcessCommsEnd
;
ProcessCommsClose100Steps:
;
 ;             movlw     S_Manual
 ;             subwf     MainState,W,Access
 ;             btfss     ZeroFlag
 ;             goto      ProcessCommsClose100StepsEnd
;
              CloseValve
;
              movlw     100
              movwf     Steps,Access
              clrf      StepsH,Access
;
ProcessCommsClose100StepsEnd:
; 
              goto      ProcessCommsEnd
;
ProcessCommsFlowMeterData:
;
              bcf       NewDataForSensor1
              bcf       NewDataForSensor2
;
              movlw     DisplayFlowMeterData
              movwf     DisplayMode,Banked
;
              goto      ProcessCommsEnd
;
ProcessCommsCalibrationData:
;
              movlw     DisplayCalibrationData
              movwf     DisplayMode,Banked
;
              goto      ProcessCommsEnd
;
ProcessCommsManual:
;
              movlw     S_Manual
              movwf     MainState,Access
; 
              goto      ProcessCommsEnd
;
ProcessCommsOpen1Step:
;
  ;            movlw     S_Manual
  ;            subwf     MainState,W,Access
  ;            btfss     ZeroFlag
  ;            goto      ProcessCommsOpen1StepEnd
;
              OpenValve
;
              movlw     1 
              movwf     Steps,Access
              clrf      StepsH,Access
;
ProcessCommsOpen1StepEnd:
; 
              goto      ProcessCommsEnd
;
ProcessCommsOpen100Steps:
;
   ;           movlw     S_Manual
   ;           subwf     MainState,W,Access
   ;           btfss     ZeroFlag
   ;           goto      ProcessCommsOpen100StepsEnd
;
              OpenValve
;
              movlw     100
              movwf     Steps,Access
              clrf      StepsH,Access
;
ProcessCommsOpen100StepsEnd:
; 
              goto      ProcessCommsEnd
;
ProcessCommsValveData:
;
              bcf       NewDataForSensor1
              bcf       NewDataForSensor2
;
              movlw     DisplayValveData
              movwf     DisplayMode,Banked
;
              goto      ProcessCommsEnd
;
ProcessCommsEnd:
; 
              return
;
ProcessFlowMeterCalibration:
;

;
ProcessFlowMeterCalibrationEnd:
;
              return
;
ProcessStepperMotor:
;
              movf      DisplayMode,W,Banked
              xorlw     DisplayValveData
              btfss     ZeroFlag
              goto      ProcessStepperMotorSkipDisplay
;
              movlw     40
              subwf     Steps,W,Access
              movlw     0
              subwfb    StepsH,W,Access
;              
              btfss     CarryFlag
              goto      PSM_1
;               
              movlw     40
;              
              goto      PSM_2
;
PSM_1:
;
              movf      Steps,W,Access
;
PSM_2:
;
              movwf     ScratchPad0,Access
;
              SkipIfValveClosed
              goto      PSM_DisplayOpen
;
PSM_DisplayClosed:
;
              movlw     40
              movwf     ScratchPad1,Access
;
              movf      ScratchPad0,W,Access
              subwf     ScratchPad1,W,Access
              movwf     ScratchPad2,Access
              btfsc     ZeroFlag
              goto      PSM_DC2
;
PSM_DC1:  
;                            
              movlw     ' '
              call      WriteByteSerialBuffer2
              decfsz    ScratchPad2,Same,Access
              goto      PSM_DC1
;
PSM_DC2:
;
              movlw     'c'
              call      WriteByteSerialBuffer2
;
              movf      ScratchPad0,W,Access
              btfsc     ZeroFlag
              goto      PSM_DC4
;
PSM_DC3:  
;                            
              movlw     ' '
              call      WriteByteSerialBuffer2
              decfsz    ScratchPad0,Same,Access
              goto      PSM_DC3
;
PSM_DC4:  
;
              movlw     '|'
              call      WriteByteSerialBuffer2
;
PSM_DC5:  
;                            
              movlw     ' '
              call      WriteByteSerialBuffer2
              decfsz    ScratchPad1,Same,Access
              goto      PSM_DC5
;
              movlw     ' '
              call      WriteByteSerialBuffer2
;
              call      TerminateLine
;
              goto      ProcessStepperMotorSkipDisplay
;
PSM_DisplayOpen:
;              

;
ProcessStepperMotorSkipDisplay:
;  
              movf      StepsH,W,Access
              movlw     5
              btfss     ZeroFlag
              movlw     200
              movwf     StepBatch,Banked
;
ProcessStepperMotor1 
;
              movf      Steps,W,Access
              iorwf     StepsH,W,Access
              btfsc     ZeroFlag
              goto      ProcessStepperMotorEnd
              movlw     1
              subwf     Steps,Same,Access
              movlw     0
              subwfb    StepsH,Same,Access
;
              SkipIfValveOpen
              goto      ProcessStepperMotorClose            
              goto      ProcessStepperMotorOpen
;
ProcessStepperMotorClose
;
              btfsc     Limit_Closed
              goto      ProcessStepperMotorEnd
;
              movf      StepsOpen,W,Access
              iorwf     StepsOpenH,W,Access
              btfsc     ZeroFlag
              goto      ProcessStepperMotorClose1
;
              movlw     1
              subwf     StepsOpen,Same,Access
              movlw     0
              subwfb    StepsOpenH,Same,Access
;
ProcessStepperMotorClose1:
;
              movlw     'c'
;
              goto      ProcessStepperMotorStep
;
ProcessStepperMotorOpen
;
              btfsc     Limit_Open
              goto      ProcessStepperMotorEnd
;
              btfsc     StepsOpenH,4,Access
              goto      ProcessStepperMotorOpen1
              movlw     1
              addwf     StepsOpen,Same,Access
              movlw     0
              addwfc    StepsOpenH,Same,Access 
;
ProcessStepperMotorOpen1:
;
              movlw     'o'
;
              goto      ProcessStepperMotorStep
;
ProcessStepperMotorStep:
;
              call      Delay250usec
              bsf       ValveStep
              call      Delay250usec
              bcf       ValveStep
;
              decfsz    StepBatch,Same,Banked
              goto      ProcessStepperMotor1
;
ProcessStepperMotorEnd:
;
              return
;
KickStartFlow:
;
 ;G121             bcf       _GIEH ;Switch interrupts off because of FlowSetPoint
 ;             movf      FlowSetPoint,W,Banked
 ;             iorwf     FlowSetPointH,W,Banked
 ;             bsf       _GIEH
 ;             btfsc     ZeroFlag
 ;             goto      KickStartFlowEnd
;
              OpenValve
              bcf       _GIEH ;Switch interrupts off because of OpenKick and FlowTimer
;              
              movf      OpenKick,W,Banked
              subwf     Steps,W,Access
              movf      OpenKickH,W,Banked
              subwfb    StepsH,W,Access
;
              btfsc     CarryFlag
              goto      KickStartFlow1
;
              movff     OpenKick,Steps
              movff     OpenKickH,StepsH
;
              movlw     LOW(FlowTC)
              movwf     FlowTimer,Access
              movlw     HIGH(FlowTC)
              movwf     FlowTimerH,Access
;
KickStartFlow1:              
;              
              bsf       _GIEH
;
KickStartFlowEnd:
;
              return
;
KickStartFlowInitial:
;
 ;G121             bcf       _GIEH ;Switch interrupts off because of SlowSetPoint
 ;             movf      FlowSetPoint,W,Banked
 ;             iorwf     FlowSetPointH,W,Banked
 ;             bsf       _GIEH
 ;             btfsc     ZeroFlag
 ;             goto      KickStartFlowInitialEnd
;
              OpenValve               
              bcf       _GIEH ;Switch the interrupts off because of OpenKick and FlowTimer        
              movff     OpenKickInitial,Steps
              movff     OpenKickInitialH,StepsH
              movlw     LOW(FlowTC)
              movwf     FlowTimer,Access
              movlw     HIGH(FlowTC)
              movwf     FlowTimerH,Access
              bsf       _GIEH
;
KickStartFlowInitialEnd:
;
              return
;
Delay1second
;
             call       Delay100msec
             call       Delay100msec
             call       Delay100msec
             call       Delay100msec
             call       Delay100msec
             call       Delay100msec
             call       Delay100msec
             call       Delay100msec
             call       Delay100msec
             call       Delay100msec
;
             return
;
Delay100msec 
;
             call       Delay10msec
             call       Delay10msec
             call       Delay10msec
             call       Delay10msec
             call       Delay10msec
             call       Delay10msec
             call       Delay10msec
             call       Delay10msec
             call       Delay10msec
             call       Delay10msec
;
             return
;
Delay15msec
              movlw     b'11000111'
              movwf     T0CON,Access
              movlw     256-162
              movwf     TMR0L
              bcf       _TMR0IF
;
Delay15msec1  btfss     _TMR0IF
              goto      Delay10msec1
;
              return

;
Delay10msec
              movlw     b'11000111'
              movwf     T0CON,Access
              movlw     256-108
              movwf     TMR0L
              bcf       _TMR0IF
;
Delay10msec1  btfss     _TMR0IF
              goto      Delay10msec1
;
              return
;
Delay5msec
              movlw     b'11000111'
              movwf     T0CON,Access
              movlw     256-154 ;54
              movwf     TMR0L
              bcf       _TMR0IF
;
Delay5msec1   btfss     _TMR0IF
              goto      Delay10msec1
;
              return
;
Delay1msec
              movlw     b'11000111'
              movwf     T0CON,Access
              movlw     256-11
              movwf     TMR0L
              bcf       _TMR0IF
;
Delay2msec1   btfss     _TMR0IF
              goto      Delay2msec1
;
              return
;
Delay250usec
              movlw     b'11000111'
              movwf     T0CON,Access
              movlw     256-3 ;6
              movwf     TMR0L
              bcf       _TMR0IF
;
Delay250usec1   btfss     _TMR0IF
                goto      Delay250usec1
;
              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      TxByteSerialPort1A       ;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
;
              goto      TxByteSerialPort1End     ;We are done
;
TxByteSerialPort1A
;
              bcf       _TX1IE                   ;Switch the Tx interrupt OFF
;
TxByteSerialPort1End
;
              return
;
;***************************************
;
; Unbuffer and transmit serial byte to Serial Port 2
;
;***************************************
;
TxByteSerialPort2
;
              lfsr      2,Tx2Buffer              ;Point to correct bank
;
              movf      Tx2BufferReadPointer,W,Banked ;IF READ = WRITE
              xorwf     Tx2BufferWritePointer,W,Banked
              btfsc     ZeroFlag
              goto      TxByteSerialPort2A       ;THEN EMPTY, so go
;
              incf      Tx2BufferReadPointer,W,Banked ;Point to next location
;
              xorlw     Tx2BufferLastLocation+1  ;IF > LAST
              btfsc     ZeroFlag                 ;THEN ROLL OVER to FIRST
              movlw     Tx2BufferFirstLocation^(Tx2BufferLastLocation+1) 
;
              xorlw     Tx2BufferLastLocation+1  ;Restore W from comparison
;
              movwf     FSR2L,Access
;
              movwf     Tx2BufferReadPointer,Banked ;Update the read pointer
;
              movf      INDF2,W,Access
              movwf     TXREG2,Access            ;Transmit byte
;
              goto      TxByteSerialPort2End     ;We are done
;
TxByteSerialPort2A
;
              bcf       _TX2IE                   ;Switch the Tx interrupt OFF
;
TxByteSerialPort2End
;
             return
;
;**************************************
;
; 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
;
;**************************************
;
; Receive and buffer serial byte from Serial Port 2
;
;**************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
RxByteSerialPort2
;
              bcf       Boolean_Interrupt        ;Assume no error
;
              btfss     _OERR2                   ;IF !OVER RUN
              goto      RxByteSerialPort2C       ;THEN check for FRAMING
              bsf       Boolean_Interrupt        ;ELSE flag error and
RxByteSerialPort2A                               ;     recover from OVER RUN
              bcf       _CREN2                   ;     - CREN OFF
              btfsc     _CREN2      
              goto      RxByteSerialPort2A
;
RxByteSerialPort2B
;
              bsf       _CREN2                   ;     - CREN back ON
              btfss     _CREN2      
              goto      RxByteSerialPort2B
;
RxByteSerialPort2C
;
              btfss     _FERR2                   ;IF !FRAMING
              goto      RxByteSerialPort2D       ;THEN check error flag
              bsf       Boolean_Interrupt        ;ELSE flag error and
              movf      RCREG2,W                 ;     recover from FRAMING
;
RxByteSerialPort2D
;
              btfsc     Boolean_Interrupt        ;IF ERROR
              goto      RxByteSerialPort2End      ;THEN go
                                                  ;ELSE buffer byte
;
              lfsr      2,Rx2Buffer              ;Point to correct bank
;
              incf      Rx2BufferWritePointer,W,Banked ;Point to next location
;
              xorlw     Rx2BufferLastLocation+1  ;IF > LAST
              btfsc     ZeroFlag                 ;THEN ROLL OVER to FIRST
              movlw     Rx2BufferFirstLocation^(Rx2BufferLastLocation+1) 
;
              xorlw     Rx2BufferLastLocation+1  ;Restore W from comparison
;
              movwf     FSR2L,Access             ;Point to next buffer location
;
              xorwf     Rx2BufferReadPointer,W,Banked ;IF WRITE = READ
              btfsc     ZeroFlag                 
              goto      RxByteSerialPort2BufferFull   ;THEN FULL, so go
;
              movf      RCREG2,W,Access          ;Read the byte received
              movwf     INDF2,Access             ;And buffer it for later
;
              movf      FSR2L,W,Access           ;Update the write pointer
              movwf     Rx2BufferWritePointer,Banked
;
              goto      RxByteSerialPort2End     ;We are done
;
RxByteSerialPort2BufferFull
;
              movf      RCREG2,W,Access          ;Dump this byte
              bsf       SerialBuffer2OverFlow    ;And flag it
;
RxByteSerialPort2End
;
              return
;
;***************************************
;
; 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
;
              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
;
              movf      CharacterBuffer1,W,Access ;Restore W to entry value
;
              return
;
;***************************************
;
; Write byte from W to serial transmit buffer 2
;
;**************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
WriteByteSerialBuffer2:
;
              movwf     CharacterBuffer2,Access  ;Buffer character for later
;
              lfsr      2,Tx2Buffer              ;Point to the correct page
;
              incf      Tx2BufferWritePointer,W,Banked ;Point to next location
;
              xorlw     Tx2BufferLastLocation+1  ;IF > LAST
              btfsc     ZeroFlag                 ;THEN ROLL OVER to FIRST
              movlw     Tx2BufferFirstLocation^(Tx2BufferLastLocation+1) 
;
              xorlw     Tx2BufferLastLocation+1  ;Restore W from comparison
;
              movwf     FSR2L,Access             ;Point to next buffer location
;
WriteByteSerialBuffer2A:
;
              movf      FSR2L,W,Access           ;IF WRITE <> READ
              xorwf     Tx2BufferReadPointer,W,Banked
              btfss     ZeroFlag                 
              goto      WriteByteSerialBuffer2B  ;THEN there is space in the queue
;
              btfss     SkipQueue              
              goto      WriteByteSerialBuffer2A 
              goto      WriteByteSerialBuffer2C
;
WriteByteSerialBuffer2B:
;
              movf      CharacterBuffer2,W,Access ;Read the byte received
;
              movwf     INDF2,Access             ;And buffer it for transmission
;
              movf      FSR2L,W,Access           ;Update the write pointer
              movwf     Tx2BufferWritePointer,Banked
;
WriteByteSerialBuffer2C:
;
              movf      CharacterBuffer2,W,Access ;Restore W to entry value
;
              return
;
;**************************************
;
; This is where we remap the high priority interrupts
;
;**************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
ProcessHighPriorityInterrupts:
;
              goto      ProcessHighPriorityInterrupts_Remapped
;
;**************************************
;
; This is where we remap the low priority interrupts
;
;**************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
ProcessLowPriorityInterrupts:

              goto      ProcessLowPriorityInterrupts_Remapped
;
;**************************************
;
; This is where we actually process the high priority interrupts
;
;**************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
ProcessHighPriorityInterrupts_Remapped:
;
              movff     WREG,HPI_SaveWREG
              movff     STATUS,HPI_SaveSTATUS
              movff     BSR,HPI_SaveBSR
;
              movlb     1                        ;Make sure we are pointing to the correct RAM bank
;
              btfsc     _TMR3IF                  ;IF Timer 
              call      ProcessTimer3            ;THEN process it
;
              btfsc     _INT1IF                  ;IF Interrupt1
              call      ProcessInterrupt1        ;THEN process it
;
              btfsc     _INT2IF                  ;IF Interrupt2
              call      ProcessInterrupt2        ;THEN process it
;
ProcessHighPriorityInterruptsEnd
;
              bcf       _TMR1IF
              movff     HPI_SaveWREG,WREG
              movff     HPI_SaveSTATUS,STATUS
              movff     HPI_SaveBSR,BSR
;
              retfie    NoShadow
;
;**************************************
;
; This is where we actually process the low priority interrupts
;
;**************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
ProcessLowPriorityInterrupts_Remapped:
; 
              movff     WREG,SaveWREG
              movff     STATUS,SaveSTATUS
              movff     FSR0H,SaveFSR0H
              movff     FSR0L,SaveFSR0L
              movff     FSR1H,SaveFSR1H
              movff     FSR1L,SaveFSR1L
              movff     FSR2H,SaveFSR2H
              movff     FSR2L,SaveFSR2L
              movff     PCLATH,SavePCLATH
              movff     PCLATU,SavePCLATU
              movff     TABLAT,SaveTABLAT
              movff     TBLPTRU,SaveTBLPTRU
              movff     TBLPTRH,SaveTBLPTRH
              movff     TBLPTR,SaveTBLPTR
              movff     PRODL,SavePRODL
              movff     PRODH,SavePRODH
              movff     BSR,SaveBSR 
;
ProcessLPI_RC1:
;
              btfsc     _RC1IF                  ;IF Rx
              call      RxByteSerialPort1       ;THEN process it
;
              btfss     _OERR1                  ;IF !OVER RUN
              goto      ProcessLPI_RC1End       ;THEN we are done
                                                ;ELSE we need to clear the error,
              nop                               ;     so that we can receive data again
ProcessLPI_RC1A:                                ;     - CREN OFF
              bcf       _CREN1  
              btfsc     _CREN1       
              goto      ProcessLPI_RC1A 
;
ProcessLPI_RC1B:                                ;     - CREN ON 
              bsf       _CREN1   
              btfss     _CREN1       
              goto      ProcessLPI_RC1B
;
ProcessLPI_RC1End:
;
              btfsc     _RC2IF                   ;IF Rx
              call      RxByteSerialPort2        ;THEN process it
;
              btfss     _TX1IE   
              goto      ProcessInterrupts1
;
              btfsc     _TX1IF                   ;IF Tx
              call      TxByteSerialPort1        ;THEN process it
;
ProcessInterrupts1
;
              btfss     _TX2IE   
              goto      ProcessInterrupts2
;
              btfsc     _TX2IF                   ;IF Tx
              call      TxByteSerialPort2        ;THEN process it
;
ProcessInterrupts2
;
              btfsc     _TMR2IF                  ;IF Timer
              call      ProcessTimer2            ;THEN process it
;
              movff     SaveWREG,WREG
              movff     SaveSTATUS,STATUS
              movff     SaveFSR0H,FSR0H
              movff     SaveFSR0L,FSR0L
              movff     SaveFSR1H,FSR1H
              movff     SaveFSR1L,FSR1L
              movff     SaveFSR2H,FSR2H
              movff     SaveFSR2L,FSR2L
              movff     SavePCLATH,PCLATH
              movff     SavePCLATU,PCLATU
              movff     SaveTABLAT,TABLAT
              movff     SaveTBLPTRU,TBLPTRU
              movff     SaveTBLPTRH,TBLPTRH
              movff     SaveTBLPTR,TBLPTR
              movff     SavePRODL,PRODL
              movff     SavePRODH,PRODH
              movff     SaveBSR,BSR
;
              retfie    NoShadow
;
;***************************************
;
ProcessTimer2
;
              bsf       Tick
              incf      TickCount,Same,Banked
;
              bsf       _Go
;
ProcessFlasher:
;
              decfsz    FlasherTimer,Same,Banked
              goto      ProcessFlasherEnd
;
              movlw     TCFlasher
              movwf     FlasherTimer,Banked
;
              btg       Flasher
;
ProcessFlasherEnd:
;
ProcessAutoRepeatTimer:
;
              movf      AutoRepeat,W,Banked
              btfss     ZeroFlag
              decf      AutoRepeat,Same,Banked
;
ProcessAutoRepeatTimerEnd:
;
ProcessTX1IE: ;*** Bypassed for now
;
              btfsc     _TX1IE
              goto      ProcessTX1IEEnd
;
              movf      Tx1BufferReadPointer,W,Banked
              xorwf     Tx1BufferWritePointer,W,Banked
              btfsc     ZeroFlag
              goto      ProcessTX1IEEnd
;
              bsf       _TX1IE
;
ProcessTX1IEEnd:
;
ProcessTX2IE:
;
              btfsc     _TX2IE
              goto      ProcessTX2IEEnd
;
              movf      Tx2BufferReadPointer,W,Banked
              xorwf     Tx2BufferWritePointer,W,Banked
              btfsc     ZeroFlag
              goto      ProcessTX2IEEnd
;
              bsf       _TX2IE
;
ProcessTX2IEEnd:
;
ProcessPacket:
;
ProcessPacketEnd:
;
ProcessTimer_GP1:
;
              movf      Timer_GP1,W,Access
              iorwf     Timer_GP1H,W,Access
              btfsc     ZeroFlag
              goto      ProcessTimer_GP1_Expired
;
              movlw     1
              subwf     Timer_GP1,Same,Access
              movlw     0
              subwfb    Timer_GP1H,Same,Access
;
              goto      ProcessCommsTimerEnd
;
ProcessTimer_GP1_Expired:
;
; There is nothing to do here for this timer, the main state will take care of it when it sees it has timed out
;
              goto      ProcessTimer_GP1_End
;
ProcessTimer_GP1_End:
;
ProcessCellModuleTimeOutTimer:
;
	      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:
;
ProcessCellModuleTimeOutTimerEnd:
;
ProcessTimer_RefreshLCD:
;
              decfsz    Timer_RefreshLCD,Same,Access
              goto      ProcessTimer_RefreshLCD_End
;
              bsf       RefreshLCD
;
              movlw     Refresh_LCD_TC
              movwf     Timer_RefreshLCD,Access
;
ProcessTimer_RefreshLCD_End:
;
ProcessOverRideTimer:
;
              btfsc     ManualMode
              goto      ProcessOverRideTimer1
;
              movf      OverRideTimer,W,Banked
              iorwf     OverRideTimerH,W,Banked
              btfsc     ZeroFlag
              goto      ProcessOverRideTimerLEDOff
;
              movlw     1
              subwf     OverRideTimer,Same,Banked
              movlw     0
              subwfb    OverRideTimerH,Same,Banked
;
              movf      OverRideTimer,W,Banked
              iorwf     OverRideTimerH,W,Banked
              btfsc     ZeroFlag
              goto      ProcessOverRideTimerLEDOff
;
ProcessOverRideTimer1:
;
              CopyBit   Flasher,RedLED
              bcf       GreenLED
;
              goto      ProcessOverRideTimerEnd
;
ProcessOverRideTimerLEDOff:
;
              bcf       RedLED
;
ProcessOverRideTimerEnd:
;
ProcessMenuTimeOut:
;
              movf      MenuTimeOut,W,Access
              iorwf     MenuTimeOutH,W,Access
              btfsc     ZeroFlag
              goto      ProcessMenuTimeOutEnd
;
              movlw     1
              subwf     MenuTimeOut,Same,Access
              movlw     0
              subwfb    MenuTimeOutH,Same,Access
;
ProcessMenuTimeOutEnd:
;
ProcessNoFlowTimeOut:
;
              movf      NoFlowTimeOut,W,Banked
              iorwf     NoFlowTimeOutH,W,Banked
              btfsc     ZeroFlag
              goto      ProcessNoFlowTimeOut1 
;
              movlw     1
              subwf     NoFlowTimeOut,Same,Banked
              movlw     0
              subwfb    NoFlowTimeOutH,Same,Banked
;
              goto      ProcessNoFlowTimeOut2
;
ProcessNoFlowTimeOut1:
;
              clrf      FlowProcessVariable,Banked
              clrf      FlowProcessVariableH,Banked
;
              btfss     FaultRelay    
              goto      ProcessNoFlowTimeOut2
;
              movlw     S_FlowFault
              movwf     MainState,Access
;
ProcessNoFlowTimeOut2:
;
ProcessNoFlowTimeOutEnd:
;
ProcessCommsTimer:
;
              movf      CommsTimer,W,Access
              iorwf     CommsTimerH,W,Access
              btfsc     ZeroFlag
              goto      ProcessCommsTimerExpired
;
              movlw     1
              subwf     CommsTimer,Same,Access
              movlw     0
              subwfb    CommsTimerH,Same,Access
;
              goto      ProcessCommsTimerEnd
;
ProcessCommsTimerExpired:
;
              movlw     0
              movwf     FlowFlags,Banked
      ;        movwf     FlowSetPoint,Banked
      ;        movwf     FlowSetPointH,Banked 
;
              goto      ProcessCommsTimerEnd
;
ProcessCommsTimerEnd:
;
ProcessFlowTimer:
;
              movf      FlowTimer,W,Access
              iorwf     FlowTimerH,W,Access
              btfsc     ZeroFlag
              goto      ProcessFlowTimerEnd
              movlw     1
              subwf     FlowTimer,Same,Access 
              movlw     0
              subwfb    FlowTimerH,Same,Access
;
ProcessFlowTimerEnd:
;
ProcessNewDataTimer:
;
              decfsz    NewDataTimer,Same,Access
              goto      ProcessNewDataTimerEnd
;
              movf      NewDataDelayCounter,W,Access
              btfss     ZeroFlag
              goto      ProcessNewDataTimerDelay
;
ProcessNewDataTimerNormal:
;
              movf      DisplayMode,W,Banked
;
              xorlw     DisplayFlowMeterData              
              btfsc     ZeroFlag
              goto      ProcessNewDataTimerSkip
;
              xorlw     DisplayPacketData^DisplayFlowMeterData              
              btfsc     ZeroFlag
              goto      ProcessNewDataTimerSkip
;
              xorlw     DisplaySpeedData^DisplayPacketData              
              btfsc     ZeroFlag
              goto      ProcessNewDataTimerSkip
;
              bsf       TransmitNewData
;
ProcessNewDataTimerSkip:
;
              movf      RefreshHeadings,W,Access
              btfss     ZeroFlag
              decf      RefreshHeadings,Same,Access
;
              movlw     NewDataTC
;
              goto      ProcessNewDataTimerSave
;
ProcessNewDataTimerDelay:
;
              decf      NewDataDelayCounter,Same,Access
;
              movlw     NewDataDelayTC
;
ProcessNewDataTimerSave:
;
              movwf     NewDataTimer,Access
;
ProcessNewDataTimerEnd:
;
ProcessMembrane2x2Matrix:
;
              movlw     TrackADC_Matrix0
              call      ReadADC
              movff     ADRESH,Matrix0
;
              movlw     TrackADC_Matrix1
              call      ReadADC
;
              movf      Matrix0,W,Banked
              subwf     ADRESH,W,Access
              btfsc     CarryFlag
              goto      ProcessMembrane2x2Matrix1
              movf      ADRESH,W,Access
              subwf     Matrix0,W,Banked
;
ProcessMembrane2x2Matrix1:
;
              movwf     Matrix1,Banked
              movlw     5
              subwf     Matrix1,W,Banked
              btfsc     CarryFlag
              goto      ProcessMembrane2x2Matrix2
;
              SelectSW 98,Matrix0,Banked,ProcessMembrane2x2MatrixEnd,NoSwitch,NoSwitch,NoSwitch,NoSwitch
              SelectSW 70,Matrix0,Banked,ProcessMembrane2x2MatrixEnd,MembraneSWControlOpenPin,Off,MembraneSWControlClosePin,On,MembraneSWKey_MenuPin,On,MembraneSWKey_UpPin,Off
              SelectSW 40,Matrix0,Banked,ProcessMembrane2x2MatrixEnd,MembraneSWControlOpenPin,On,MembraneSWControlClosePin,Off,MembraneSWKey_MenuPin,Off,MembraneSWKey_UpPin,On
;
              bcf       MembraneSWControlOpenPin
              bcf       MembraneSWControlClosePin
              bcf       MembraneSWKey_MenuPin
              bcf       MembraneSWKey_UpPin
;
              goto      ProcessMembrane2x2MatrixEnd
;
ProcessMembrane2x2Matrix2:
;
              SelectSW 141,Matrix0,Banked,ProcessMembrane2x2Matrix3,MembraneSWControlOpenPin,On,MembraneSWControlClosePin,On,NoSwitch,NoSwitch
              SelectSW 108,Matrix0,Banked,ProcessMembrane2x2Matrix3,MembraneSWControlOpenPin,Off,MembraneSWControlClosePin,On,NoSwitch,NoSwitch
              SelectSW 73,Matrix0,Banked,ProcessMembrane2x2Matrix3,MembraneSWControlOpenPin,On,MembraneSWControlClosePin,Off,NoSwitch,NoSwitch
              bcf       MembraneSWControlOpenPin
              bcf       MembraneSWControlClosePin
;
ProcessMembrane2x2Matrix3:
;
              SelectSW 141,ADRESH,Access,ProcessMembrane2x2Matrix4,MembraneSWKey_MenuPin,On,MembraneSWKey_UpPin,On,NoSwitch,NoSwitch
              SelectSW 108,ADRESH,Access,ProcessMembrane2x2Matrix4,MembraneSWKey_MenuPin,On,MembraneSWKey_UpPin,Off,NoSwitch,NoSwitch
              SelectSW 73,ADRESH,Access,ProcessMembrane2x2Matrix4,MembraneSWKey_MenuPin,Off,MembraneSWKey_UpPin,On,NoSwitch,NoSwitch
              bcf       MembraneSWKey_MenuPin
              bcf       MembraneSWKey_UpPin
;
ProcessMembrane2x2Matrix4:
;
ProcessMembrane2x2MatrixEnd:
;
           IFNDEF FlipKeypad 
              Debounce PositiveLogic,MembraneSWControlOpenPin,Key_Set,Key_SetHistory,Key_SetDebounceTimer,Banked,1
              Debounce PositiveLogic,MembraneSWControlClosePin,Key_Down,Key_DownHistory,Key_DownDebounceTimer,Banked,1
;
              Debounce PositiveLogic,MembraneSWKey_MenuPin,Key_Menu,Key_MenuHistory,Key_MenuDebounceTimer,Banked,1
              Debounce PositiveLogic,MembraneSWKey_UpPin,Key_Up,Key_UpHistory,Key_UpDebounceTimer,Banked,1
           ELSE
              Debounce PositiveLogic,MembraneSWKey_MenuPin,Key_Set,Key_SetHistory,Key_SetDebounceTimer,Banked,1
              Debounce PositiveLogic,MembraneSWKey_UpPin,Key_Down,Key_DownHistory,Key_DownDebounceTimer,Banked,1
;
              Debounce PositiveLogic,MembraneSWControlOpenPin,Key_Menu,Key_MenuHistory,Key_MenuDebounceTimer,Banked,1
              Debounce PositiveLogic,MembraneSWControlClosePin,Key_Up,Key_UpHistory,Key_UpDebounceTimer,Banked,1
           ENDIF
;
              Debounce PositiveLogic,Flow1Pin,Interrupt1_Level,Interrupt1_LevelHistory,Interrupt1DebounceTimer,Banked,Interrupt1DebounceTC 
              Debounce PositiveLogic,Flow2Pin,Interrupt2_Level,Interrupt2_LevelHistory,Interrupt2DebounceTimer,Banked,Interrupt2DebounceTC 
;
ProcessLimits:
;
; Limit switches are normally closed, (negative logic)
;
;                    o c
;                    0 0 3V03 0x9C 156
;                                      142    
;                    1 0 2V48 0x80 128
;                                      109
;                    0 1 1V78 0x5B 91
;                                       45
;                    1 1  0V  0x00
;
              movlw     TrackADC_Limits
              call      ReadADC
              movff     ADRESH,Limits
;
              movlw     142
              subwf     Limits,W,Banked
              btfss     CarryFlag
              goto      ProcessLimits1
;
              bcf       Limit_Open_Pin
              bcf       Limit_Closed_Pin
;
              goto      ProcessLimitsEnd
;
ProcessLimits1:
;
              movlw     109
              subwf     Limits,W,Banked
              btfss     CarryFlag
              goto      ProcessLimits2
;
              bsf       Limit_Open_Pin
              bcf       Limit_Closed_Pin
;
              goto      ProcessLimitsEnd
;
ProcessLimits2:
;
              movlw     45
              subwf     Limits,W,Banked
              btfss     CarryFlag
              goto      ProcessLimits3
;
              bcf       Limit_Open_Pin
              bsf       Limit_Closed_Pin
;
              goto      ProcessLimitsEnd
;
ProcessLimits3:
;
              bsf       Limit_Open_Pin
              bsf       Limit_Closed_Pin
;
              goto      ProcessLimitsEnd
;
ProcessLimitsEnd:
;
DebounceLimits:
;
              Debounce PositiveLogic,Limit_Open_Pin,Limit_Open,Limit_Open_History,Limit_Open_DebounceTimer,Banked,1
              Debounce PositiveLogic,Limit_Closed_Pin,Limit_Closed,Limit_Closed_History,Limit_Closed_DebounceTimer,Banked,1
;
DebounceLimitsEnd:
;
ProcessValveNumber:
;
              movf      DIPSwitches,W,Banked
              andlw     b'00111111'
              addlw     1
              movwf     ValveNumber,Access
;
ProcessValveNumberEnd:


;
ProcessMatrix0:

ProcessMatrix0End:
;
ProcessMatrix1:



ProcessMatrix1End:
;
ProcessTimer2_1SecondTimer
;
              decfsz    OneSecondTimer,Same,Banked
              goto      ProcessTimer2_1SecondTimerEnd
;
              movlw     TC1Second
              movwf     OneSecondTimer,Banked
;
              bsf       ShowFlow
;
ProcessTimer2_1ST_SMSTimer:

              decfsz    PollForSMSTimer,Same,Banked
              goto      ProcessTimer2_1ST_SMSTimerEnd
;
              movlw     PollForSMSTC
              movwf     PollForSMSTimer,Banked
              bsf       PollForSMS
;
ProcessTimer2_1ST_SMSTimerEnd:
;
ProcessTimer2_1SecondTimerEnd
;
ProcessTimer2Z
;
              btfsc     _Go
              goto      ProcessTimer2Z
;
ProcessTimer2End
;
              bcf       _TMR2IF
;
              return
;
;*******************************************************************************
;
ProcessTimer3:
;
              incf      TMR3HH,Same,Access
              btfss     TMR3HH,2,Access
              goto      ProcessTimer3End
;
              clrf      TMR3HH,Access    
;
              btfss     Sensor1WrappedAround
              goto      ProcessTimer3A
;
              movlw     SkipFirstPulses1TC
              movwf     SkipFirstPulses1,Banked
;
ProcessTimer3A:
;
              btfss     Sensor2WrappedAround
              goto      ProcessTimer3B
;
              movlw     SkipFirstPulses2TC
              movwf     SkipFirstPulses2,Banked
;
ProcessTimer3B:
;
              bsf       Sensor1WrappedAround
              bsf       Sensor2WrappedAround
;
ProcessTimer3End:
;
              bcf       _TMR3IF
;
              return
;
;*******************************************************************************
;
ProcessInterrupt1:
;
              incf      Interrupt1Count,Same,Banked
;
              btfsc     NewDataForSensor1
              bsf       Sensor1DataNotProcessed
;
              bsf       NewDataForSensor1
;
ProcessInterrupt1A:
;
              btfsc     _TMR3IF                  ;IF Timer 
              call      ProcessTimer3            ;THEN process it
;
              movff     TMR3L,Interrupt1Capture
              movff     TMR3H,Interrupt1CaptureH
              movff     TMR3HH,Interrupt1CaptureHH
;
              btfsc     _TMR3IF
              goto      ProcessInterrupt1A
;
ProcessInterrupt1End:
;
              bcf       _INT1IF
;
              return
;
;*******************************************************************************
;
ProcessInterrupt2:
;
              incf      Interrupt2Count,Same,Banked
;
              btfsc     NewDataForSensor2
              bsf       Sensor2DataNotProcessed
;
              bsf       NewDataForSensor2
;
ProcessInterrupt2A:
;
              btfsc     _TMR3IF                  ;IF Timer 
              call      ProcessTimer3            ;THEN process it
;
              movff     TMR3L,Interrupt2Capture
              movff     TMR3H,Interrupt2CaptureH
              movff     TMR3HH,Interrupt2CaptureHH
;
              btfsc     _TMR3IF
              goto      ProcessInterrupt2A
;
ProcessInterrupt2End:
;
              bcf       _INT2IF
;
              return
;
;***************************************
;
; This is subroutine twiddles the bits from the various address selector ports into a number in W
;
;***************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
AssembleAddressSelector:
;
              comf      PORTC,W,Access
              CopyBit   WREG,5,Access,WREG,3,Access
              andlw     b'00001111'
;
              return
;
;***************************************
;
; This subroutine initialises the 16-bit CRC
;
;***************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
CRC_Initialise:
;
              movlw     h'FF'
              movwf     CRC,Banked
              movwf     CRCH,Banked
;
              return
;
;***************************************
;
; This subroutine updates the 16-bit CRC with the byte in W
;
;***************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
CRC_Update:
              xorwf     CRCH,Same,Banked
;
              movlw     8
              movwf     CRC_BitCounter,Banked
;
CRC_Update1   bcf       CarryFlag
              rrcf      CRC,Same,Banked
              rrcf      CRCH,Same,Banked
              btfss     CarryFlag
              goto      CRC_Update2
;
              movlw     h'A0'
              xorwf     CRC,Same,Banked
              movlw     h'01'
              xorwf     CRCH,Same,Banked
;
CRC_Update2   decfsz    CRC_BitCounter,Same,Banked
              goto      CRC_Update1
;
              return
;
;***************************************
;
; Flush serial receive buffer 2
;
;**************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
FlushSerialReceiveBuffer2
;
              DisableInterrupts
              movff     Rx2BufferWritePointer,Rx2BufferReadPointer
              RestoreInterrupts
;
              bcf       SerialBuffer2OverFlow
;
              return
;
BinaryToBCDDisplay5:
;
              call      BinaryToBCD
;
              movf      TenThousands,W,Access
              addlw     '0' 
              call      WriteByteSerialBuffer2
;
              movf      Thousands,W,Access
              addlw     '0' 
              call      WriteByteSerialBuffer2
;
              movf      Hundreds,W,Access
              addlw     '0' 
              call      WriteByteSerialBuffer2
;
              movf      Tens,W,Access
              addlw     '0' 
              call      WriteByteSerialBuffer2
;
              movf      Units,W,Access
              addlw     '0' 
              call      WriteByteSerialBuffer2
;
              return
;
BinaryToBCDDisplay3:
;
              call      BinaryToBCD
;
              movf      Hundreds,W,Access
              addlw     '0' 
              call      WriteByteSerialBuffer2
;
              movf      Tens,W,Access
              addlw     '0' 
              call      WriteByteSerialBuffer2
;
              movf      Units,W,Access
              addlw     '0' 
              call      WriteByteSerialBuffer2
;
              return
;
DisplaySpaceSpaceSpace:
;
              movlw     ' '
              call      WriteByteSerialBuffer2
              movlw     ' '
              call      WriteByteSerialBuffer2
              movlw     ' '
              call      WriteByteSerialBuffer2
;              
              return
;
DisplaySpaceColonSpace:
;
              movlw     ' '
              call      WriteByteSerialBuffer2
              movlw     ':'
              call      WriteByteSerialBuffer2
              movlw     ' '
              call      WriteByteSerialBuffer2
;              
              return
;
BCD2Binary:
;
              movf      Units,W,Access
              movwf     Binary,Access
              clrf      BinaryH,Access
;
BCD2Binary_Tens:
;
              movf      Tens,W,Access
              movwf     CalculatorX0,Access
              clrf      CalculatorX1,Access
              clrf      CalculatorX2,Access
              clrf      CalculatorX3,Access
              clrf      CalculatorX4,Access
;
              movlw     10
              movwf     CalculatorY0,Access
              clrf      CalculatorY1,Access
              clrf      CalculatorY2,Access
              clrf      CalculatorY3,Access
              clrf      CalculatorY4,Access
;
              call      Mul40
;
              movf      CalculatorX0,W,Access
              addwf     Binary,Same,Access
              movf      CalculatorX1,W,Access
              addwfc    BinaryH,Same,Access
;
BCD2Binary_Hundreds:
;
              movf      Hundreds,W,Access
              movwf     CalculatorX0,Access
              clrf      CalculatorX1,Access
              clrf      CalculatorX2,Access
              clrf      CalculatorX3,Access
              clrf      CalculatorX4,Access
;
              movlw     LOW(100)
              movwf     CalculatorY0,Access
              movlw     HIGH(100)
              movwf     CalculatorY1,Access
              clrf      CalculatorY2,Access
              clrf      CalculatorY3,Access
              clrf      CalculatorY4,Access
;
              call      Mul40
;
              movf      CalculatorX0,W,Access
              addwf     Binary,Same,Access
              movf      CalculatorX1,W,Access
              addwfc    BinaryH,Same,Access
;
BCD2Binary_Thousands:
;
              movf      Thousands,W,Access
              movwf     CalculatorX0,Access
              clrf      CalculatorX1,Access
              clrf      CalculatorX2,Access
              clrf      CalculatorX3,Access
              clrf      CalculatorX4,Access
;
              movlw     LOW(1000)
              movwf     CalculatorY0,Access
              movlw     HIGH(1000)
              movwf     CalculatorY1,Access
              clrf      CalculatorY2,Access
              clrf      CalculatorY3,Access
              clrf      CalculatorY4,Access
;
              call      Mul40
;
              movf      CalculatorX0,W,Access
              addwf     Binary,Same,Access
              movf      CalculatorX1,W,Access
              addwfc    BinaryH,Same,Access
;
BCD2Binary_TenThousands:
;
              movf      TenThousands,W,Access
              movwf     CalculatorX0,Access
              clrf      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      CalculatorX0,W,Access
              addwf     Binary,Same,Access
              movf      CalculatorX1,W,Access
              addwfc    BinaryH,Same,Access
;
              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
;
              movf      CalculatorY1,W,Access
              addwfc    CalculatorX1,Same,Access  
;
              movf      CalculatorY2,W,Access
              addwfc    CalculatorX2,Same,Access  
;
              movf      CalculatorY3,W,Access
              addwfc    CalculatorX3,Same,Access  
;
              movf      CalculatorY4,W,Access
              addwfc    CalculatorX4,Same,Access  
;
              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
;
              movf      CalculatorY1,W,Access
              subwfb    CalculatorX1,Same,Access
;
              movf      CalculatorY2,W,Access
              subwfb    CalculatorX2,Same,Access
;
              movf      CalculatorY3,W,Access
              subwfb    CalculatorX3,Same,Access
;
              movf      CalculatorY4,W,Access
              subwfb    CalculatorX4,Same,Access
;
              return                             ;And back we go
;
;***************************************
;
; FUNCTION.....: 40-bit by 40-bit multiplication
;                CalculatorX = CalculatorX * CalculatorY
;
; INPUTS.......: CalculatorX4, CalculatorX3, CalculatorX2, CalculatorX1, CalculatorX0
;                CalculatorY4, CalculatorY3, CalculatorY2, CalculatorY1, CalculatorY0
;
; OUTPUTS......: CalculatorX4, CalculatorX3, CalculatorX2, CalculatorX1, CalculatorX0
;                CalculatorError
;
; SPECIAL NOTES: Uses CalculatorCount, CalculatorTA4, CalculatorTA3, CalculatorTA2,
;                CalculatorTA1, CalculatorTA0, Add32
;
;                Using 40-bit inputs for both X and Y means that the product
;                could be 40-bits in length! If the product exceeds 40-bits
;                the BError bit is set to indicate an overflow. The reason
;                for having 40-bit inputs with only a 40-bit output, is that
;                it allows you to do:
;
;                   1 * 5 000 000 000
;                   5 000 000 000 * 1
;
;***************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
Mul40         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 40-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
;
;***************************************
;
; That's all the 40-bit maths routines we need for here
;
;***************************************
;
;***************************************
;
; Open MCP3021 for reading
;
;***************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
OpenReadMCP3021:
;
              I2C_Start I2C_BUS1
;
              movlw     b'10011011'
              I2C_Write I2C_BUS1
;
              return

;
;***************************************
;
; Read a byte from the MCP3021
;
;***************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
ReadMCP3021:
;
              I2C_Read I2C_BUS1
;
              return
;
;***************************************
;
; Read last byte from the MCP3021
;
;***************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
ReadLastMCP3021:
;
              I2C_ReadLast I2C_BUS1
;
              return
;
;***************************************
;
; Open ultra sonic flow meter for reading
;
;***************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
OpenReadUltra:
;
              I2C_Start I2C_BUS1
;
              movlw     b'10000101'
              I2C_Write I2C_BUS1
;
        ;      I2C_Start I2C_BUS1
;
              return

;
;***************************************
;
; Read a byte from the ultra sonic flow meter
;
;***************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
ReadUltra:
;
              I2C_Read I2C_BUS1
;
              return
;
;***************************************
;
; Read last byte from the ultra sonic flow meter
;
;***************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
ReadLastUltra:
;
              I2C_ReadLast I2C_BUS1
;
              return
;
;***************************************
;
; Open 8574 for writing
;
;***************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
OpenWrite8574:
;
              movlw     b'01001110'
              I2C_Start I2C_BUS1
              I2C_Write I2C_BUS1
;
              return
;
;***************************************
;
; Open 8574 for writing
;
;***************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
Write8574:
;
              I2C_Write I2C_BUS1
;
              return
;
;***************************************
;
; Write high nibble to LCD
;
;***************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
WriteLCDNibbleHi:
;
              movlw     b'00001111'
              andwf     LCD_Port,Same,Access
;
              movf      LCD_Data,W,Access
              andlw     b'11110000'
              iorwf     LCD_Port,Same,Access
;
              movf      LCD_Port,W,Access
              I2C_Write I2C_BUS1
; 
              movf      LCD_Port,W,Access
              bsf       WREG,B_LCD_Enable,Access
              I2C_Write I2C_BUS1
; 
              movf      LCD_Port,W,Access
              I2C_Write I2C_BUS1
;
              return
;
;***************************************
;
; Write low nibble to LCD
;
;***************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
WriteLCDNibbleLo:
;
              movlw     b'00001111'
              andwf     LCD_Port,Same,Access
;
              swapf     LCD_Data,W,Access
              andlw     b'11110000'
              iorwf     LCD_Port,Same,Access
;
              movf      LCD_Port,W,Access
              I2C_Write I2C_BUS1
; 
              movf      LCD_Port,W,Access
              bsf       WREG,B_LCD_Enable,Access
              I2C_Write I2C_BUS1
; 
              movf      LCD_Port,W,Access
              I2C_Write I2C_BUS1
;
              return
























;
;***************************************
;
; Open on board 24LC256 for reading
;
;***************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
OpenRead256:
;
              I2C_OpenRead24256 I2C_BUS1
;
              return
;
;***************************************
;
; Open on board 24LC256 for writing
;
;***************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
OpenWrite256:
;
              I2C_OpenWrite24256 I2C_BUS1
;
              return
;
;***************************************
;
; Write a byte to the on board 24LC256
;
;***************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
Write256:
;
              I2C_Write I2C_BUS1
;
              return
;
;***************************************
;
; Read a byte from the on board 24LC256
;
;***************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
Read256:
;
              I2C_Read I2C_BUS1
;
              return
;
;***************************************
;
; Read the last byte from the on board 24LC256
;
;***************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
ReadLast256:
;
              I2C_ReadLast I2C_BUS1
;
              return

;
;***************************************
;
; Write instruction byte to LCD
;
;***************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
WriteLCDInstruction:
;
              movwf     LCD_Data,Access
              bcf       LCD_RS  
              call      WriteLCDNibbleHi
              call      WriteLCDNibbleLo
;
              return
;
;***************************************
;
; Write data byte to LCD
;
;***************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
WriteLCDByte:
;
              bsf       LCD_RS
              movwf     LCD_Data,Access
              call      WriteLCDNibbleHi
              call      WriteLCDNibbleLo
;
              return
;
;***************************************
;
; Open flow meter 24LC02 for reading
;
;***************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
OpenReadFlowMeter:
;
              I2C_Start I2C_BUS1
;
              movlw     b'10100000'
              I2C_Write I2C_BUS1
;
              movf      EEAdrsLo,W,Access
              I2C_Write I2C_BUS1
;
              I2C_Start I2C_BUS1
;
              movlw     b'10100001'
              I2C_Write I2C_BUS1
;
              return
;
;***************************************
;
; Open flow meter 24LC02 for writing
;
;***************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
OpenWriteFlowMeter:
;
              I2C_Start I2C_BUS1
;
              movlw     b'10100000'
              I2C_Write I2C_BUS1
;
              movf      EEAdrsLo,W,Access
              I2C_Write I2C_BUS1
;
              return
;
;***************************************
;
; Write a byte to the flow meter 24LC02
;
;***************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
WriteFlowMeter:
;
              I2C_Write I2C_BUS1
;
              return
;
;***************************************
;
; Read a byte from the flow meter 24LC02
;
;***************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
ReadFlowMeter:
;
              I2C_Read I2C_BUS1
;
              return
;
;***************************************
;
; Read the last byte from the flow meter 24LC02
;
;***************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
ReadLastFlowMeter:
;
              I2C_ReadLast I2C_BUS1
;
              return
;
;***************************************
;
; This is the recovery routine for I2C_BUS1
;
;***************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
I2CBUS1Recovery
;  
              bsf       I2CBUS_Error
;
              I2C_Stop I2C_BUS1            
;
              return
;
;***************************************
;
; This is the STOP routine for I2C_BUS1
;
;***************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
I2CBUS1Stop:
;  

 nop
 nop


              I2C_Stop I2C_BUS1            
;
              return
;
DisplayByte:
;
              movwf     ScratchPad0,Access      
              swapf     ScratchPad0,W,Access
              call      DisplayNibble
              movf      ScratchPad0,W,Access
              call      DisplayNibble
              movlw     ' '
              call      WriteByteSerialBuffer2
;
              return 
;
DisplayNibble:
;
              andlw     b'00001111'
              movwf     ScratchPad1,Access
              movlw     10
              subwf     ScratchPad1,W,Access
              movlw     '0'
              btfsc     CarryFlag
              movlw     'A'-10
              addwf     ScratchPad1,W,Access
              call      WriteByteSerialBuffer2
;
              return
;
ReadADC:
;
              movwf     ADCON0,Access
              bsf       _Go
;
ReadADC1:
;
              btfsc     _Go
              goto      ReadADC1
;
              return
;              
X_SendStringToDebugPortFast:              
;
              bsf       SkipQueue
;
              goto      X_SendStringToDebugPort
;                            
X_SendStringToDebugPortSlow:              
;
              bcf       SkipQueue
;
              goto      X_SendStringToDebugPort
;
X_SendStringToDebugPort:              
;
              tblrd*+
              movf      TABLAT,W,Access
              btfsc     ZeroFlag
              goto      X_SendStringToDebugPortOut
;
              call      WriteByteSerialBuffer2
;
              goto      X_SendStringToDebugPort
;
X_SendStringToDebugPortOut:
;
              bsf       SkipQueue
;
X_SendStringToDebugPortEnd:
;
              return
;              
X_SendStringToLCDLine1:
;
              movlw     b'10000000'
              call      WriteLCDInstruction
;
              call      Delay5msec
;
X_SendStringToLCDLine1A:
;
              tblrd*+
              movf      TABLAT,W,Access
              btfsc     ZeroFlag
              goto      X_SendStringToLCDLine1Out
;
              call      WriteLCDByte
;
              goto      X_SendStringToLCDLine1A
;
X_SendStringToLCDLine1Out:
;
X_SendStringToLCDLine1End:
;
              return
;              
X_SendStringToLCDLine2:
;
              movlw     b'11000000'
              call      WriteLCDInstruction
;
              call      Delay5msec
;
X_SendStringToLCDLine2A:
;
              tblrd*+
              movf      TABLAT,W,Access
              btfsc     ZeroFlag
              goto      X_SendStringToLCDLine2Out
;
              call      WriteLCDByte
;
              goto      X_SendStringToLCDLine2A
;
X_SendStringToLCDLine2Out:
;
X_SendStringToLCDLine2End:
;
              return
;              
X_DisplayBinaryToLCDLine:
;
              movf      LCD_Pointer,W,Banked
              call      WriteLCDInstruction
;
              call      Delay5msec
;
              call      BinaryToBCD  
;
              movf      TenThousands,W,Access
              addlw     BinaryToASCII
              call      WriteLCDByte
;
              movf      Thousands,W,Access
              addlw     BinaryToASCII
              call      WriteLCDByte
;
              movf      Hundreds,W,Access
              addlw     BinaryToASCII
              call      WriteLCDByte
;
              movf      Tens,W,Access
              addlw     BinaryToASCII
              call      WriteLCDByte
;
              movf      Units,W,Access
              addlw     BinaryToASCII
              call      WriteLCDByte
;
              return
;              
X_DisplayBinaryToTHTULCDLine:
;
              movf      LCD_Pointer,W,Banked
              call      WriteLCDInstruction
;
              call      Delay5msec
;
              call      BinaryToBCD  
;
              movf      Thousands,W,Access
              addlw     BinaryToASCII
              call      WriteLCDByte
;
              movf      Hundreds,W,Access
              addlw     BinaryToASCII
              call      WriteLCDByte
;
              movf      Tens,W,Access
              addlw     BinaryToASCII
              call      WriteLCDByte
;
              movf      Units,W,Access
              addlw     BinaryToASCII
              call      WriteLCDByte
;
              return
;              
DisplayOnDebug_Version:
;
              movlw     VersionYear
              call      WriteByteSerialBuffer2
;
              movlw     VersionMonth
              call      WriteByteSerialBuffer2
;
              movlw     VersionDayTens
              call      WriteByteSerialBuffer2
;
              movlw     VersionDayUnits
              call      WriteByteSerialBuffer2
;
              return
;
TerminateLine:
;
              movlw     '\r'
              call      WriteByteSerialBuffer2
              movlw     '\n'
              call      WriteByteSerialBuffer2
;
              return
;
ProcessSensor1:
;
              btfss     NewDataForSensor1
              goto      ProcessSensor1End
;
              bcf       _GIEH
;
              bcf       NewDataForSensor1
              movff     Interrupt1Capture,Interrupt1Work
              movff     Interrupt1CaptureH,Interrupt1WorkH
              movff     Interrupt1CaptureHH,Interrupt1WorkHH
;
              bcf       Sensor1WrappedAround
;
              bsf       DisplayNewDataForInterrupt1
   ;           bsf       TransmitNewData
;
              movf      Interrupt1Old,W,Banked
              subwf     Interrupt1Work,W,Banked
              movwf     Interrupt1Time,Banked
;
              movf      Interrupt1OldH,W,Banked
              subwfb    Interrupt1WorkH,W,Banked
              movwf     Interrupt1TimeH,Banked
;
              movf      Interrupt1OldHH,W,Banked
              subwfb    Interrupt1WorkHH,W,Banked
              movwf     Interrupt1TimeHH,Banked
;
              movff     Interrupt1Work,Interrupt1Old 
              movff     Interrupt1WorkH,Interrupt1OldH
              movff     Interrupt1WorkHH,Interrupt1OldHH
; 
ProcessSensor1CheckFirstPulses:
;
              movf      SkipFirstPulses1,W,Banked
              btfsc     ZeroFlag
              goto      ProcessSensor1CheckFirstPulsesEnd
;
              decf      SkipFirstPulses1,Same,Banked
;
              movlw     h'FF'
              clrf      Interrupt1Count,Banked
              movwf     Interrupt1Time,Banked
              movwf     Interrupt1TimeH,Banked
              movwf     Interrupt1TimeHH,Banked
;
ProcessSensor1CheckFirstPulsesEnd:
;
              movlw     b'00000011'
              btfsc     Interrupt1TimeHH,2,Banked
              andwf     Interrupt1TimeHH,Same,Banked
;
              bsf       _GIEH
;
              call      ProcessFlow
;
              movlw     LOW(NoFlowTimeOutTC)
              movwf     NoFlowTimeOut,Banked
              movlw     HIGH(NoFlowTimeOutTC)
              movwf     NoFlowTimeOutH,Banked
;
ProcessSensor1End:
;
              return
;
ProcessSensor2:
;
              btfss     NewDataForSensor2
              goto      ProcessSensor2End
;
              bcf       _GIEH
;
              bcf       NewDataForSensor2
              movff     Interrupt2Capture,Interrupt2Work
              movff     Interrupt2CaptureH,Interrupt2WorkH
              movff     Interrupt2CaptureHH,Interrupt2WorkHH
;
              bcf       Sensor2WrappedAround
;
              bsf       DisplayNewDataForInterrupt2
;
              movf      Interrupt2Old,W,Banked
              subwf     Interrupt2Work,W,Banked
              movwf     Interrupt2Time,Banked
;
              movf      Interrupt2OldH,W,Banked
              subwfb    Interrupt2WorkH,W,Banked
              movwf     Interrupt2TimeH,Banked
;
              movf      Interrupt2OldHH,W,Banked
              subwfb    Interrupt2WorkHH,W,Banked
              andlw     b'00000011'
              movwf     Interrupt2TimeHH,Banked
;
              movff     Interrupt2Work,Interrupt2Old 
              movff     Interrupt2WorkH,Interrupt2OldH
              movff     Interrupt2WorkHH,Interrupt2OldHH
; 
ProcessSensor2CheckFirstPulses:
;
              movf      SkipFirstPulses2,W,Banked
              btfsc     ZeroFlag
              goto      ProcessSensor2CheckFirstPulsesEnd
;
              decf      SkipFirstPulses2,Same,Banked
;
              movlw     h'FF'
              clrf      Interrupt2Count,Banked
              movwf     Interrupt2Time,Banked
              movwf     Interrupt2TimeH,Banked
              movwf     Interrupt2TimeHH,Banked
;
              goto      ProcessSensor2End
;
ProcessSensor2CheckFirstPulsesEnd:
;
ProcessSensor2End:
;
              bsf       _GIEH
;
              return
;
DisplayDebugData:
;
              btfss     TransmitNewData
              goto      DisplayDebugDataEnd
;
              bcf       TransmitNewData
; 
              movf      DisplayMode,W,Banked
;
              xorlw     DisplayFlowMeterData
              btfsc     ZeroFlag
              goto      DisplayNewFlowMeterData
;
              xorlw     DisplayPacketData^DisplayFlowMeterData
              btfsc     ZeroFlag
              goto      DisplayNewPacketData
;
              xorlw     DisplayValveData^DisplayPacketData
              btfsc     ZeroFlag
              goto      DisplayNewValveData
;
              xorlw     DisplayCalibrationData^DisplayValveData
              btfsc     ZeroFlag
              goto      DisplayNewCalibrationData
;
              goto      DisplayNewSpeedData
;
DisplayNewFlowMeterData:
;
              movf      RefreshHeadings,W,Access
              btfss     ZeroFlag
              goto      DisplayFlowMeterData1
;
              movlw     RefreshHeadingsTC
              movwf     RefreshHeadings,Access
;
              SendStringToDebugPortFast S_FlowMeterDataHeadings
;              
  ;            goto      DisplayFlowMeterDataEnd
;              
DisplayFlowMeterData1:
;
              movff     TickCount,Binary
              clrf      BinaryH,Access
;
              call      BinaryToBCDDisplay3
;
              call      DisplaySpaceColonSpace
;
              movff     FlowProcessVariable,Binary
              movff     FlowProcessVariableH,BinaryH
;
              call      BinaryToBCDDisplay5
;
              call      DisplaySpaceColonSpace
;
              bcf       _GIEH
              movff     FlowSetPoint,Binary
              movff     FlowSetPointH,BinaryH
              bsf       _GIEH
;
              call      BinaryToBCDDisplay5
;
              call      DisplaySpaceColonSpace
;
              bcf       _GIEH
              movff     MedianNewSamplePointer,FSR0L
              movff     MedianNewSamplePointerH,FSR0H
              movff     POSTINC0,WREG ;Skip over the AGE
              movff     POSTINC0,Binary
              movff     POSTINC0,BinaryH
              bsf       _GIEH
;
              call      BinaryToBCDDisplay5
;
              call      DisplaySpaceColonSpace
;
 ;             movff     UFO2Flow,Binary
 ;             movff     UFO2FlowH,BinaryH
;
              call      BinaryToBCDDisplay5
;
              bsf       SkipQueue
;
              call      DisplaySpaceColonSpace
;
              movlw     'E' 
              call      WriteByteSerialBuffer2
              movlw     '=' 
              call      WriteByteSerialBuffer2
              movlw     '0'
;              btfsc     UFO2Flags,7
              movlw     '1'
              call      WriteByteSerialBuffer2
;
              call      DisplaySpaceColonSpace
;
              movlw     'R' 
              call      WriteByteSerialBuffer2
              movlw     '=' 
              call      WriteByteSerialBuffer2
;
;              movf      UFO2Flags,W,Banked
              andlw     b'01111111'
              addlw     '0' 
              call      WriteByteSerialBuffer2
;
              bcf       SkipQueue
;
              call      TerminateLine
;
DisplayFlowMeterDataEnd:
;
              goto      DisplayDebugDataEnd
;
DisplayNewPacketData:
;
              movff     TickCount,Binary
              clrf      BinaryH,Access
;
              call      BinaryToBCDDisplay3
;
              call      DisplaySpaceColonSpace
;
              movff     PacketCount,Binary
              clrf      BinaryH,Access
;
              call      BinaryToBCDDisplay3
;
              call      DisplaySpaceColonSpace
;
              lfsr      0,SerialDataFromMasterToSlave
;
              movff     POSTINC0,WREG
              call      DisplayByte
              movff     POSTINC0,WREG
              call      DisplayByte
              movff     POSTINC0,WREG
              call      DisplayByte
;
              movlw     '('
              call      WriteByteSerialBuffer2
;              
              movlw     '0'
              btfsc     SerialDataFromMasterToSlave+2,2,Banked
              movlw     '1'
              call      WriteByteSerialBuffer2
;              
              movlw     '0'
              btfsc     SerialDataFromMasterToSlave+2,1,Banked
              movlw     '1'
              call      WriteByteSerialBuffer2
;              
              movlw     '0'
              btfsc     SerialDataFromMasterToSlave+2,0,Banked
              movlw     '1'
              call      WriteByteSerialBuffer2
;             
              movlw     ')'
              call      WriteByteSerialBuffer2
              movlw     ' '
              call      WriteByteSerialBuffer2
;             
              movff     POSTINC0,WREG
              call      DisplayByte
              movff     POSTINC0,WREG
              call      DisplayByte
              movff     POSTINC0,WREG
              call      DisplayByte
              movff     POSTINC0,WREG
              call      DisplayByte
              movff     POSTINC0,WREG
              call      DisplayByte
              movff     POSTINC0,WREG
              call      DisplayByte
              movff     POSTINC0,WREG
              call      DisplayByte
              movff     POSTINC0,WREG
              call      DisplayByte
              movff     POSTINC0,WREG
              call      DisplayByte
              movff     POSTINC0,WREG
              call      DisplayByte
              movff     POSTINC0,WREG
              call      DisplayByte
              movff     POSTINC0,WREG
              call      DisplayByte
              movff     POSTINC0,WREG
              call      DisplayByte
;
              movlw     ':'
              call      WriteByteSerialBuffer2
              movlw     ' '
              call      WriteByteSerialBuffer2
;
              movff     POSTINC0,WREG
              call      DisplayByte
              movff     POSTINC0,WREG
              call      DisplayByte
              movff     POSTINC0,WREG
              call      DisplayByte
              movff     POSTINC0,WREG
              call      DisplayByte
              movff     POSTINC0,WREG
              call      DisplayByte
              movff     POSTINC0,WREG
              call      DisplayByte
              movff     POSTINC0,WREG
              call      DisplayByte
              movff     POSTINC0,WREG
              call      DisplayByte
              movff     POSTINC0,WREG
              call      DisplayByte
              movff     POSTINC0,WREG
              call      DisplayByte
              movff     POSTINC0,WREG
              call      DisplayByte
              movff     POSTINC0,WREG
              call      DisplayByte
              movff     POSTINC0,WREG
              call      DisplayByte
              movff     POSTINC0,WREG
              call      DisplayByte
              movff     POSTINC0,WREG
              call      DisplayByte
              movff     POSTINC0,WREG
              call      DisplayByte
;
              call      TerminateLine
;
DisplayNewPacketDataEnd:

;
              goto      DisplayDebugDataEnd
;
DisplayNewValveData:
;
; Nothing to do here - it all happens in the stepper motor code
;
              goto      DisplayDebugDataEnd
;
DisplayNewCalibrationData:
;
              movf      RefreshHeadings,W,Access
              btfss     ZeroFlag
              goto      DisplayCalibrationData1
;
              movlw     RefreshHeadingsTC
              movwf     RefreshHeadings,Access
;
              SendStringToDebugPortFast S_CalibrationDataHeadings
;              
              goto      DisplayCalibrationDataEnd
;              
DisplayCalibrationData1:
;
              movff     TickCount,Binary
              clrf      BinaryH,Access
;
              call      BinaryToBCDDisplay3
;
              call      DisplaySpaceColonSpace
;
;              movff     FlowMeterCalibration,Binary
              clrf      BinaryH,Access
;
              call      BinaryToBCDDisplay3
;
              call      DisplaySpaceColonSpace
;
              movff     FlowCompensation,Binary
              clrf      BinaryH,Access
;
              call      BinaryToBCDDisplay3
;
              call      TerminateLine
;
DisplayCalibrationDataEnd:
;
              goto      DisplayDebugDataEnd
;
DisplayNewSpeedData:
;
              movf      RefreshHeadings,W,Access
              btfss     ZeroFlag
              goto      DisplayNewSpeedData1
;
              movlw     RefreshHeadingsTC
              movwf     RefreshHeadings,Access
;
              SendStringToDebugPortFast S_SpeedDataHeadings
;
              goto      DisplayNewSpeedDataEnd 
;
DisplayNewSpeedData1:
;
              btfss     DisplayNewDataForInterrupt1
              goto      DisplayNewSpeedDataEnd
              bcf       DisplayNewDataForInterrupt1
;
; Display the latest speed information for debugging purposes
;
              movff     Interrupt2Time,Binary
              movff     Interrupt2TimeH,Access
;
              call      BinaryToBCDLong
;
              movf      TenMillions,W,Access
              addlw     '0' 
              call      WriteByteSerialBuffer2
;
              movf      Millions,W,Access
              addlw     '0' 
              call      WriteByteSerialBuffer2
;
              movf      HundredThousands,W,Access
              addlw     '0' 
              call      WriteByteSerialBuffer2
;
              movf      TenThousands,W,Access
              addlw     '0' 
              call      WriteByteSerialBuffer2
;
              movf      Thousands,W,Access
              addlw     '0' 
              call      WriteByteSerialBuffer2
;
              movf      Hundreds,W,Access
              addlw     '0' 
              call      WriteByteSerialBuffer2
;
              movf      Tens,W,Access
              addlw     '0' 
              call      WriteByteSerialBuffer2
;
              movf      Units,W,Access
              addlw     '0' 
              call      WriteByteSerialBuffer2
;
              call      TerminateLine
;
DisplayNewSpeedDataEnd:
;
DisplayDebugDataEnd:
;
              return
;
AdjustFlow:
;
; The display routine has worked out the flow over the last 330msec
;
              btfsc      Limit_Closed
              goto       AdjustFlow1             ;IF the valve is closed then adjust it even if the flow is 0
;
              movf       Binary,W,Access         ;Otherwise check if we have flow before we adjust the valve
              iorwf      BinaryH,W,Access
              btfsc      ZeroFlag
              goto       AdjustFlowEnd
;
AdjustFlow1:
;
              movf      Binary,W,Access
              subwf     FlowSetPoint,W,Banked
              movwf     CalculatorX0,Access
              movf      BinaryH,W,Access
              subwfb    FlowSetPointH,W,Banked
              movwf     CalculatorX1,Access
;
              btfss     CarryFlag
              goto      AdjustFlowClosed
              goto      AdjustFlowOpen
;
AdjustFlowOpen:
;
              OpenValve
;
              movlw     100
              subwf     CalculatorX0,W,Access 
              movlw     0
              subwfb    CalculatorX1,W,Access
;
              movlw     1              
              btfsc     CarryFlag
              movlw     25
              movwf     Steps,Access
;
              goto      AdjustFlowEnd
;
AdjustFlowClosed:
;
              CloseValve 
;
              comf     CalculatorX0,Same,Access
              comf     CalculatorX1,Same,Access
;
              movlw    1
              addwf    CalculatorX0,Same,Access
              movlw    0
              addwfc   CalculatorX1,Same,Access
;
              movlw     100
              subwf     CalculatorX0,W,Access 
              movlw     0
              subwfb    CalculatorX1,W,Access
;
              movlw     1              
              btfsc     CarryFlag
              movlw     25
              movwf     Steps,Access
;
              goto      AdjustFlowEnd
;
AdjustFlowEnd:
;
              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:
;
              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             
;
;***************************************
;
; Check serial receive buffer 2 for byte:
; C = 1 then W = unbuffered serial byte
; C = 0 then serial buffer is empty
;
;**************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
CheckByteSerialBuffer2
;
              movf      Rx2BufferReadPointer,W,Banked
              xorwf     Rx2BufferWritePointer,W,Banked
              InvertBit ZeroFlag,CarryFlag
              btfsc     ZeroFlag
              goto      ReadByteSerialBuffer2End
              goto      ReadByteSerialBuffer2A
;
;***************************************
;
; Unbuffer byte from serial receive buffer 2 and return with it in W
;
;**************************************
;
; LABEL       OP-CODE   OPERAND                  ;COMMENTS
;
ReadByteSerialBuffer2
;
              movf      Rx2BufferReadPointer,W,Banked
              xorwf     Rx2BufferWritePointer,W,Banked
              btfsc     ZeroFlag
              goto      ReadByteSerialBuffer2
;
ReadByteSerialBuffer2A
;
              lfsr      2,Rx2Buffer              ;Point to the correct page
;
              incf      Rx2BufferReadPointer,W,Banked
;
              xorlw     Rx2BufferLastLocation+1  ;IF > LAST
              btfsc     ZeroFlag                 ;THEN ROLL OVER to FIRST
              movlw     Rx2BufferFirstLocation^(Rx2BufferLastLocation+1) 
;
              xorlw     Rx2BufferLastLocation+1  ;Restore W from comparison
;
              movwf     FSR2L,Access
;
;              DisableReceive2Interrupt
;
              movwf     Rx2BufferReadPointer,Banked
;
              movf      INDF2,W,Access
;
;              RestoreReceive2Interrupt
;
              bsf       CarryFlag
;
ReadByteSerialBuffer2End
;
              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



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_CheckForSMS,X_GSM_CheckForSMS
GSM_34        CreateStateTableEntry S_GSM_CheckForSMSWait,X_GSM_CheckForSMSWait
GSM_35        CreateStateTableEntry S_GSM_CheckForSMSHeaderPoll,X_GSM_CheckForSMSHeaderPoll
GSM_36        CreateStateTableEntry S_GSM_CheckForSMSHeaderAnalyse,X_GSM_CheckForSMSHeaderAnalyse
GSM_37        CreateStateTableEntry S_GSM_CheckForSMSBodyPoll,X_GSM_CheckForSMSBodyPoll
GSM_38        CreateStateTableEntry S_GSM_CheckForSMSBodyAnalyse,X_GSM_CheckForSMSBodyAnalyse
;
GSM_39        CreateStateTableEntry S_GSM_ReplySMS,X_GSM_ReplySMS
GSM_40        CreateStateTableEntry S_GSM_ReplySMSWait,X_GSM_ReplySMSWait
GSM_41        CreateStateTableEntry S_GSM_ReplySMSWaitForPromptA,X_GSM_ReplySMSWaitForPromptA
GSM_42        CreateStateTableEntry S_GSM_ReplySMSWaitForPromptB,X_GSM_ReplySMSWaitForPromptB
GSM_43        CreateStateTableEntry S_GSM_ReplySMSPoll,X_GSM_ReplySMSPoll
GSM_44        CreateStateTableEntry S_GSM_ReplySMSAnalyse,X_GSM_ReplySMSAnalyse
;
GSM_45        CreateStateTableEntry S_GSM_DeleteSMS,X_GSM_DeleteSMS
GSM_46        CreateStateTableEntry S_GSM_DeleteSMSWait,X_GSM_DeleteSMSWait
GSM_47        CreateStateTableEntry S_GSM_DeleteSMSPoll,X_GSM_DeleteSMSPoll
GSM_48        CreateStateTableEntry S_GSM_DeleteSMSAnalyse,X_GSM_DeleteSMSAnalyse





;
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










;
;*************************************************
;
; This is the STATE we should spend most of our time in!!!
;
;*************************************************
;
X_GSM_IdleInitialise:
;
              movlw     PollForSMSTC
              movwf     PollForSMSTimer,Banked
;
              movlw     S_GSM_Idle
              movff     WREG,GSM_State
;
              bcf       PollForSMS
;
              GSM_EndOfState Dispatch
;
X_GSM_Idle:
;
              btfss     PollForSMS
              goto      X_GSM_IdleEnd
;
              bcf       PollForSMS
;




              movlw     S_GSM_CheckForCellModule
              movff     WREG,GSM_State
;
X_GSM_IdleEnd
;
              GSM_EndOfState Release
;
;*************************************************
;
; These STATEs switch the cell module on
;
;*************************************************
;
;-----------------------
;
X_GSM_ModuleOn:
;
;-----------------------
;
              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
;
              movlw     CyclePowerAttempts
              movwf     GSM_CyclePower,Access
;
              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
              btfss     GSM_On
              movlw     S_GSM_ModuleOn
;
              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




;O926 add in a state here to switch SMS notifications off














;
;*************************************************
;
; 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
;
; But on the center pivot flow controller we don't have an external RTC, if we add one it will be internal!
;
              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:
;
; Here we wrote to the RTC chip, but we would just put new values in the RTC registers
;
X_GSM_ReadTimeStampAnalyse1_End:
;
              call      Delay1msec
;
              call      PollCellModuleWithTimeOutInitialise
;
              movlw     S_GSM_ReadTimeStampPoll
              movff     WREG,GSM_State
;
              GSM_EndOfState Dispatch
;
X_GSM_ReadTimeStampAnalyse2:
;
              movlw     S_GSM_NetworkRegistration ;NB13 S_GSM_SelectTextMode
              movff     WREG,GSM_State
;
X_GSM_ReadTimeStampAnalyse_End
;
              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 ;S_GSM_CheckForSMS ;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_CheckForSMS
              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_ReplySMS ;O822 also see other O822
              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 for a configuration SMS
;
;*************************************************
;
;-----------------------
;
X_GSM_CheckForSMS:
;
;-----------------------
;
              call      LoadCellModuleTimeOut_CommandCheckForSMS
;
              movlw     S_GSM_CheckForSMSWait
              movff     WREG,GSM_State
;
              GSM_EndOfState Release
;
;-----------------------
;
X_GSM_CheckForSMSWait:
;
;-----------------------
;
              btfss     CellModuleResponseTimeOut
              goto      X_GSM_CheckForSMSWaitEnd
;
              call      FlushSerialReceiveBuffer1
;
              bcf       NoCR
              SendCellMessage Cell_Message_ListAllSMSs
;
              call      LoadCellModuleTimeOut_ListAllSMSs
;
              call      PollCellModuleWithTimeOutInitialise
;
              movlw     S_GSM_CheckForSMSHeaderPoll
              movff     WREG,GSM_State
;
X_GSM_CheckForSMSWaitEnd
;
              GSM_EndOfState Release
;
;-----------------------
;
X_GSM_CheckForSMSHeaderPoll:
;
;-----------------------
;
              bcf       AcceptSpaces
              call      PollCellModuleWithTimeOut
;
              btfss     PollComplete
              goto      X_GSM_CheckForSMSHeader1Poll
;
              movlw     S_GSM_CheckForSMSHeaderAnalyse
              movff     WREG,GSM_State
;
              GSM_EndOfState Dispatch
;
X_GSM_CheckForSMSHeader1Poll
;
              btfss     CellModuleResponseTimeOut
              goto      X_GSM_CheckForSMSHeaderPollEnd
;
              movlw     S_GSM_ModuleOff ;S_GSM_ModuleOffDone    
              movff     WREG,GSM_State
;
X_GSM_CheckForSMSHeaderPollEnd
;
              GSM_EndOfState Release
;
;-----------------------
;
X_GSM_CheckForSMSHeaderAnalyse:
;
;-----------------------
;
 ;            bsf       ModemFound
 ;            bsf       CheckedForSMS
;
              movf      PhraseNumber,W,Access
              xorlw     CellResponse_OK
              btfss     ZeroFlag
              goto      X_GSM_CheckForSMSHeader1Analyse
;
              decf      GSM_CyclePower,Same,Access
;
              movlw     S_GSM_IdleInitialise
              btfsc     ZeroFlag
              movlw     S_GSM_ModuleOff  
              movff     WREG,GSM_State
;
              goto      X_GSM_CheckForSMSHeaderEndAnalyse
;
X_GSM_CheckForSMSHeader1Analyse
;
              movf      PhraseNumber,W,Access
              xorlw     CellResponse_pCMGL
              btfsc     ZeroFlag
              goto      X_GSM_CheckForSMSHeader2Analyse
;
              bcf       ModemFound ;O926 is this flag correct in this new context?
;
              movlw     S_GSM_ModuleOff ; S_GSM_CheckForSMSHeaderPoll ;S_GSM_IdleInitialise
              movff     WREG,GSM_State
;
              goto      X_GSM_CheckForSMSHeaderEndAnalyse
;
X_GSM_CheckForSMSHeader2Analyse
;
              movlw     CyclePowerAttempts
              movwf     GSM_CyclePower,Access
;
              call      Parse_IgnoreLeadingWhiteSpace
              call      Parse_ReadNumeric
;
              movff     FSR2L,FSR0L
              movff     FSR2H,FSR0H
;
              clrf      SMSNumber,Banked
;
              movf      POSTDEC2,W,Access
;
              movlw     1
              movwf     SMSScratchPad,Banked
;
X_GSM_CheckForSMSHeader2aAnalyse
;
              movf      POSTDEC2,W,Access
              addlw     -'0'
              mulwf     SMSScratchPad,Banked
              movf      PRODL,W,Access
              addwf     SMSNumber,Banked
              movlw     10
              mulwf     SMSScratchPad,Banked
              movff     PRODL,SMSScratchPad
;
              decfsz    ParameterLength,Same,Access
              goto      X_GSM_CheckForSMSHeader2aAnalyse
;
              movff     FSR0L,FSR2L
              movff     FSR0H,FSR2H
;
              clrf      ReplyNumberLength,Banked
;
X_GSM_CFSMSHeader1:
;
              btfsc     EOL
              goto      X_GSM_CFSMSHeader4
              call      Parse_ReadNextCharacter
              xorlw     ','
              btfss     ZeroFlag
              goto      X_GSM_CFSMSHeader1
;
              btfsc     EOL
              goto      X_GSM_CFSMSHeader4
              call      Parse_ReadNextCharacter
              xorlw     '\"'
              btfss     ZeroFlag
              goto      X_GSM_CFSMSHeader4
;
              lfsr      0,ReplyNumber
;
X_GSM_CFSMSHeader2:
;
              btfsc     EOL
              goto      X_GSM_CFSMSHeader3
              call      Parse_ReadNextCharacter
              xorlw     '\"'
              btfsc     ZeroFlag
              goto      X_GSM_CFSMSHeader4
;
              xorlw     '\"'
              movwf     POSTINC0,Access
;              
              incf      ReplyNumberLength,Same,Banked
;
              btfss     ReplyNumberLength,4,Banked
              goto      X_GSM_CFSMSHeader2
;
X_GSM_CFSMSHeader3:
;
              clrf      ReplyNumberLength,Banked
;
X_GSM_CFSMSHeader4:
;
              call      PollCellModuleWithTimeOutInitialise
;
              movlw     S_GSM_CheckForSMSBodyPoll
              movff     WREG,GSM_State
;
X_GSM_CheckForSMSHeaderEndAnalyse
;
              GSM_EndOfState Release
;
;-----------------------
;
X_GSM_CheckForSMSBodyPoll:
;
;-----------------------
;
              bsf       AcceptSpaces
              bcf       ForceToUpperCase
              call      PollCellModuleWithTimeOut
              bsf       ForceToUpperCase
;
              btfss     PollComplete
              goto      X_GSM_CheckForSMSBody1Poll
;
              movlw     S_GSM_CheckForSMSBodyAnalyse
              movff     WREG,GSM_State
;
              GSM_EndOfState Dispatch
;
X_GSM_CheckForSMSBody1Poll
;
              btfss     CellModuleResponseTimeOut
              goto      X_GSM_CheckForSMSBodyPollEnd
;
              movlw     S_GSM_IdleInitialise      
              movff     WREG,GSM_State
;
X_GSM_CheckForSMSBodyPollEnd
;
              GSM_EndOfState Release
;
;-----------------------
;
X_GSM_CheckForSMSBodyAnalyse:
;
;-----------------------
;
              bcf       ReplyToSMS  ;Assume that this isn't a configuration SMS and therefore we don't want to reply to it
;              
              lfsr      2,LineBuffer
;
              decf      FSR2L,Same,Access
;
              movlw     LineBufferSize-1
              movwf     CharactersInBuffer,Access
              movf      LineBufferCounter,W,Access
              subwf     CharactersInBuffer,Same,Access
;
              bcf       EOL
;
; Check the SMS code
;
              btfsc     EOL
              goto      X_GSM_CheckForSMSBodyAnalyseEnd
              call      Parse_ReadNextCharacter
              xorwf     PasswordThousands,W,Banked
              btfss     ZeroFlag
              goto      X_GSM_CheckForSMSBodyAnalyseEnd
;
              btfsc     EOL
              goto      X_GSM_CheckForSMSBodyAnalyseEnd
              call      Parse_ReadNextCharacter
              xorwf     PasswordHundreds,W,Banked
              btfss     ZeroFlag
              goto      X_GSM_CheckForSMSBodyAnalyseEnd
;
              btfsc     EOL
              goto      X_GSM_CheckForSMSBodyAnalyseEnd
              call      Parse_ReadNextCharacter
              xorwf     PasswordTens,W,Banked
              btfss     ZeroFlag
              goto      X_GSM_CheckForSMSBodyAnalyseEnd
;
              btfsc     EOL
              goto      X_GSM_CheckForSMSBodyAnalyseEnd
              call      Parse_ReadNextCharacter
              xorwf     PasswordUnits,W,Banked
              btfss     ZeroFlag
              goto      X_GSM_CheckForSMSBodyAnalyseEnd
;
              bsf       ReplyToSMS 
;
              btfsc     EOL
              goto      X_GSM_CheckForSMSBodyAnalyseEnd
              call      Parse_ReadNextCharacter
;

;O926 so when we get here we need to interpret the SMS we have received





;
              goto      X_GSM_CheckForSMSBodyAnalyseEnd
;
X_GSM_CheckForSMSBodyAnalyseEnd:
;
              movlw     S_GSM_ReplySMS ;S_GSM_ReadSignalStrength
              btfss     ReplyToSMS
              movlw     S_GSM_DeleteSMS
;
              movf      ReplyNumberLength,Same,Banked
              btfsc     ZeroFlag
              movlw     S_GSM_DeleteSMS
;
              movff     WREG,GSM_State
;
              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
;
              lfsr      0,ReplyNumber
              movff     ReplyNumberLength,GSM_ScratchPad0

X_GSM_ReplySMSWait3:
;
              movf      POSTINC0,W,Access              
              call      WriteByteSerialBuffer1
              decfsz    GSM_ScratchPad0,Same,Banked
              goto      X_GSM_ReplySMSWait3
;
              movlw     "\""
              call      WriteByteSerialBuffer1
              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_Content:
;
              bsf       NoCR
              SendCellMessage Cell_Message_Content
;
; The reply SMS content is built over here
; - The limit is 140 characters
;
              movff     FlowForDisplay,Binary
              movff     FlowForDisplayH,BinaryH
;
              call      BinaryToBCD  
;
              movf      TenThousands,W,Access
              addlw     BinaryToASCII
              call      WriteByteSerialBuffer1
;
              movf      Thousands,W,Access
              addlw     BinaryToASCII
              call      WriteByteSerialBuffer1
;
              movf      Hundreds,W,Access
              addlw     BinaryToASCII
              call      WriteByteSerialBuffer1
;
              movf      Tens,W,Access
              addlw     BinaryToASCII
              call      WriteByteSerialBuffer1
;
              movf      Units,W,Access
              addlw     BinaryToASCII
              call      WriteByteSerialBuffer1
;
              movlw     ' '
              call      WriteByteSerialBuffer1
              movlw     'o'
              call      WriteByteSerialBuffer1
              movlw     'f'
              call      WriteByteSerialBuffer1
              movlw     ' '
              call      WriteByteSerialBuffer1
;
              movff     FlowSetPoint,Binary
              movff     FlowSetPointH,BinaryH
;
              call      BinaryToBCD  
;
              movf      TenThousands,W,Access
              addlw     BinaryToASCII
              call      WriteByteSerialBuffer1
;
              movf      Thousands,W,Access
              addlw     BinaryToASCII
              call      WriteByteSerialBuffer1
;
              movf      Hundreds,W,Access
              addlw     BinaryToASCII
              call      WriteByteSerialBuffer1
;
              movf      Tens,W,Access
              addlw     BinaryToASCII
              call      WriteByteSerialBuffer1
;
              movf      Units,W,Access
              addlw     BinaryToASCII
              call      WriteByteSerialBuffer1
;
              movlw     ' '
              call      WriteByteSerialBuffer1
              movlw     'L'
              call      WriteByteSerialBuffer1
              movlw     '/'
              call      WriteByteSerialBuffer1
              movlw     'H'
              call      WriteByteSerialBuffer1
;
X_GSM_ReplySMS_ContentMode:
;
              btfss     ManualMode
              goto      X_GSM_ReplySMS_ContentAutomatic
              goto      X_GSM_ReplySMS_ContentManual
;
X_GSM_ReplySMS_ContentAutomatic:
              SendCellMessage Cell_Message_ContentAutomatic
              goto      X_GSM_ReplySMS_ContentModeEnd
;
X_GSM_ReplySMS_ContentManual:
              SendCellMessage Cell_Message_ContentManual
              goto      X_GSM_ReplySMS_ContentModeEnd
;
X_GSM_ReplySMS_ContentModeEnd
;
;************************************************
;
X_GSM_ReplySMS_ContentFaultRelay:

              btfss     FaultRelay
              goto      X_GSM_ReplySMS_ContentFRDisable
              goto      X_GSM_ReplySMS_ContentFREnable
;
X_GSM_ReplySMS_ContentFRDisable:
              SendCellMessage Cell_Message_ContentFRDisable
              goto      X_GSM_ReplySMS_ContentFREnd
;
X_GSM_ReplySMS_ContentFREnable:
              SendCellMessage Cell_Message_ContentFREnable
              goto      X_GSM_ReplySMS_ContentFREnd
;
X_GSM_ReplySMS_ContentFREnd:
;
              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_DeleteSMS
              movff     WREG,GSM_State
;
              goto      X_GSM_ReplySMSAnalyseEnd
;
X_GSM_ReplySMSAnalyse2
;
              movlw     S_GSM_DeleteSMS
              movff     WREG,GSM_State
;
X_GSM_ReplySMSAnalyseEnd
;
              GSM_EndOfState Release
;
;*************************************************
;
; These STATEs delete an SMS
;
;*************************************************
;
;-----------------------
;
X_GSM_DeleteSMS:
;
;-----------------------
;
              call      LoadCellModuleTimeOut_DeleteSMSCommandDelay
;
              movlw     S_GSM_DeleteSMSWait
              movff     WREG,GSM_State
;
              GSM_EndOfState Release
;
;-----------------------
;
X_GSM_DeleteSMSWait:
;
;-----------------------
;
              btfss     CellModuleResponseTimeOut
              goto      X_GSM_DeleteSMSWaitEnd
;
              clrf      SMSScratchPad,Banked
;
              movlw     10
;
X_GSM_DeleteSMSWait1
;
              subwf     SMSNumber,Same,Banked
              btfss     CarryFlag
              goto      X_GSM_DeleteSMSWait2
              incf      SMSScratchPad,Same,Banked
              goto      X_GSM_DeleteSMSWait1
;
X_GSM_DeleteSMSWait2
;
              addwf     SMSNumber,Same,Banked
;
              call      FlushSerialReceiveBuffer1
;
              bsf       NoCR
              SendCellMessage Cell_Message_DeleteSMS
              bcf       NoCR
;
              movf      SMSScratchPad,W,Banked
              btfsc     ZeroFlag
              goto      X_GSM_DeleteSMSWait3
              addlw     "0"
              call      WriteByteSerialBuffer1
;
X_GSM_DeleteSMSWait3
;
              movf      SMSNumber,W,Banked
              addlw     "0"
              call      WriteByteSerialBuffer1
;
              movlw     '\r'
              call      WriteByteSerialBuffer1
;
              call      LoadCellModuleTimeOut_DeleteSMS
;
              call      PollCellModuleWithTimeOutInitialise
;
              movlw     S_GSM_DeleteSMSPoll
              movff     WREG,GSM_State
;
X_GSM_DeleteSMSWaitEnd
;
              GSM_EndOfState Release
;
;-----------------------
;
X_GSM_DeleteSMSPoll:
;
;-----------------------
;
              bcf       AcceptSpaces
              call      PollCellModuleWithTimeOut
;
              btfss     PollComplete
              goto      X_GSM_DeleteSMSPoll1
;
              movlw     S_GSM_DeleteSMSAnalyse
              movff     WREG,GSM_State
;
              GSM_EndOfState Dispatch
;
X_GSM_DeleteSMSPoll1
;
              btfss     CellModuleResponseTimeOut
              goto      X_GSM_DeleteSMSPollEnd
;
              movlw     S_GSM_ModuleOff ;S_GSM_IdleInitialise
              movff     WREG,GSM_State
;
X_GSM_DeleteSMSPollEnd
;
              GSM_EndOfState Release
;
;-----------------------
;
X_GSM_DeleteSMSAnalyse:
;
;-----------------------
;
              movf      PhraseNumber,W,Access
              xorlw     CellResponse_OK
              btfss     ZeroFlag
              goto      X_GSM_DeleteSMSAnalyse1
;
              movlw     S_GSM_IdleInitialise
              movff     WREG,GSM_State
;
              goto      X_GSM_DeleteSMSAnalyseEnd
;
X_GSM_DeleteSMSAnalyse1
;
              movlw     S_GSM_ModuleOff ;S_GSM_IdleInitialise
              movff     WREG,GSM_State
;
              goto      X_GSM_DeleteSMSAnalyseEnd
;
X_GSM_DeleteSMSAnalyseEnd
;
              GSM_EndOfState Release
;
;*************************************************
;
; These STATEs switch the cell module off
;
;*************************************************
;
;-----------------------
;
X_GSM_ModuleOff:
;
;-----------------------
;
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:
;
;-----------------------
;

;
              movlw     S_GSM_IdleInitialise
              movff     WREG,GSM_State




              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_IdleInitialise
              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
;
PopulateFlowCompensationTable:
;
              lfsr      0,FlowCompensationTable
;
PopulateFCT1:
;
              movf      FSR0L,W,Access
              addlw     0xC0
              call      ReadInternalEEPROM
              movwf     POSTINC0,Access
;
              btfss     FSR0L,6,Access           ;Have we reached the end of the table? 
              goto      PopulateFCT1
;
              return
;
              org       0x1DBC ;I forgot to pin this in an intelligent place, so now it is pinned here
                               ;and I will just have to shuffle code around it in future



;
              org       h'3FFA'
;
MinimumVersionNumber:
;
 ;             dw        ((MinimumVersionYear-'G')*16)+((MinimumVersionMonth-'0')*1)+((MinimumVersionDayTens-'0')*4096)+((MinimumVersionDayUnits-'0')*256)
;
CurrentVersionNumber:
;
 ;             dw        ((VersionYear-'G')*16)+((0x0B)*1)+((VersionDayTens-'0')*4096)+((VersionDayUnits-'0')*256)
;              dw        ((VersionYear-'G')*16)+((VersionMonth-'0')*1)+((VersionDayTens-'0')*4096)+((VersionDayUnits-'0')*256)
;
NewFirmware:
;
;              include "CC.inc"                   ;First dw is for operating firmware checksum
                                                 ;   - Then the new firmware checksum will always be 0
                                                 ;The rest of the file is a duplicate of the first half of the file
;
              END
