;*******************************************************************************
;*                                                                            
;*  TITLE: Valve Controller for Liquid Fertilser Applicator for PreMac
;*                                                                            
;*  AUTHOR: Robert Ferrer and Jacques Duvenage for Agrigel        
;*     
;*******************************************************************************    
;*     
;*  INSTRUCTIONS: 
;*     
;*      1. Assemble
;*  
;*  NOTES:
;*
;*      -
;*
;*  KNOWN ISSUES:  
;*                  
;*      I222 - Not all branches of code have been tested
;*
;*******************************************************************************
;*  OP-CODE OPERAND				;COMMENTS			
;*******************************************************************************
;*		
;*  Config
;*
;*******************************************************************************
;
    CONFIG  RETEN=OFF, INTOSCSEL=LOW, SOSCSEL=DIG, XINST=OFF
    CONFIG  FOSC=HS1, PLLCFG=OFF, FCMEN=OFF, IESO=OFF
    CONFIG  PWRTEN=ON
    CONFIG  BOREN=OFF, BORV=0, BORPWR=LOW
    CONFIG  WDTEN=OFF, WDTPS=32768
    CONFIG  CANMX=PORTC, MSSPMSK=MSK7
    CONFIG  STVREN=ON, BBSIZ=BB1K
    CONFIG  MCLRE=ON
    CONFIG  CP0=OFF, CP1=OFF, CP2=OFF, CP3=OFF, CPB=OFF, CPD=OFF	;Turn code protection when it's time
    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   
; 
;*******************************************************************************
;*		
;*  Include:
;*
;*******************************************************************************
;*  Definitions used in external libraries
;*******************************************************************************
;
#define DefaultMemoryStart		0x100	;Default Bank is Bank 1
#define CANBusMemoryStart		0x100	;CANBus memory uses Bank 1
;
;*******************************************************************************
;*  Devices
;*******************************************************************************
;
;Primary device
#define FLOWCONTROLDEVICE			;This unit is used as a flow control pcb
;#define HYDDRIVEDEVICE				;This unit is used as a HYD drive pcb
;#define GRANCONTROLDEVICE			;This unit is used as a granular fertiliser control board
;
;*******************************************************************************
;*  Systems
;*******************************************************************************
;
#ifdef	FLOWCONTROLDEVICE
#define STEPPER_MOTOR				;This device uses the stepper motor
#define FLOW_SENSOR				;This device uses the pulse sensor
#define SPEED_SENSOR				;This device uses the speed sensor
#define PRESSURE_SENSOR				;This device uses the pressure sensor
#define ENGAGE_SENSOR				;This device uses the bit sensor
#define CANBUS					;This device uses the CANBus
#define COMMS					;This device uses serial communication
#define STORAGE					;This device uses memory to save variables (EEPROM)
#define DIP_SWITCH				;This device uses the dipswitch
#define VOLTAGE_METER				;This device uses the voltage meter
#define AMPERE_METER				;This device uses the ampere meter
#define HAUL_SENSOR				;This deivce uses the haul sensor
#define LED_SEQUENCE				;This device uses the red and green LEDs
#define KEYPAD					;This device uses the keypad

#endif
;
#ifdef	HYDDRIVEDEVICE
#define SPEED_SENSOR				;This device uses the stepper motor
#define PULSEWIDTH_MOD				;This device uses the pulse wisth modulator
#define CANBUS					;This device uses the CANBus
#define COMMS					;This device uses serial communication
#define STORAGE					;This device uses memory to save variables (EEPROM)
#define VOLTAGE_METER				;This device uses the voltage meter
#define HAUL_SENSOR				;This deivce uses the haul sensor
#define LED_SEQUENCE				;This device uses the red and green LEDs
#define KEYPAD					;This device uses the keypad
#endif
;
#ifdef  GRANCONTROLDEVICE
#define DIP_SWITCH				;This device uses the dipswitch
#define SPEED_SENSOR				;This device uses the speed sensor
#define ENGAGE_SENSOR				;This device uses the bit sensor
#define CANBUS					;This device uses the CANBus
#define COMMS					;This device uses serial communication
#define STORAGE					;This device uses memory to save variables (EEPROM)
#define VOLTAGE_METER				;This device uses the voltage meter
#define HAUL_SENSOR				;This deivce uses the haul sensor
#define LED_SEQUENCE				;This device uses the red and green LEDs
#define KEYPAD					;This device uses the keypad
#endif
;
;*******************************************************************************
;*  Sub-systems
;*******************************************************************************
;
#ifdef  FLOW_SENSOR
#define PULSE_SENSOR				;Flow sensor uses 
#endif
;
#ifdef  SPEED_SENSOR
#ifndef PULSE_SENSOR
#define PULSE_SENSOR				;The speed pickup works with an external interrupt
#endif
#endif
;
#ifdef  PRESSURE_SENSOR
#define ANALOGUE_SENSOR				;The pressure sensor is an analogue sensor (ADC)
#endif
;
#ifdef  ENGAGE_SENSOR
#define BIT_SENSOR				;The pressure sensor is an analogue sensor (ADC)
#endif
;
#ifdef  EXTERNALRATE_INPUT
#ifndef ANALOGUE_SENSOR
#define ANALOGUE_SENSOR				;The pressure sensor is an analogue sensor (ADC)
#endif
#endif
;
#ifdef  CANBUS

#endif
;
#ifdef  COMMS
#define UART_2
#endif
;
#ifdef  STORAGE
#define EEPROM_S
#endif
;
#ifdef  VOLTAGE_METER
#ifndef ANALOGUE_SENSOR
#define ANALOGUE_SENSOR				;The pressure sensor is an analogue sensor (ADC)
#endif
#endif
;
#ifdef  AMPERE_METER
#ifndef ANALOGUE_SENSOR
#define ANALOGUE_SENSOR				;The pressure sensor is an analogue sensor (ADC)
#endif
#endif
;
;*******************************************************************************
;*  Components
;*******************************************************************************
;
#ifdef  STEPPER_MOTOR
#define TIMER_4					;The stepper motor uses timer 4
#endif
;
#ifdef  PULSE_SENSOR
#define TIMER_2
#define TIMER_3
#define EXTERNAL_1
#define	CALCULATOR
#define STATISTICS
#endif
;
#ifdef ANALOGUE_SENSOR
#define ADC_CONVERTER
#endif
    
#ifdef PULSEWIDTH_MOD
#ifndef TIMER_4
#define TIMER_4
#endif
#endif
;
#ifdef LED_SEQUENCE
#define TIMER_1
#endif
;
#define TIMER_0
;
;*******************************************************************************
;*
;*  Definitions
;*
;*******************************************************************************
;*  Basic
;*******************************************************************************
;
;Version of Current Softare (J: 2019)
#define VersionYear			'J'
#define VersionMonth			'3'
#define VersionDayTens			'1'
#define VersionDayUnits			'2'
;
;Software short version
#define SOFTWARE_VERSION		d'11'	 ;1.1
;  
;Hardware version
#ifdef FLOWCONTROLDEVICE
#define HARDWARE_VERSION		d'50'	 ;5.0
#endif
;
#ifdef HYDDRIVEDEVICE
#define HARDWARE_VERSION		d'20'	 ;2.0
#endif
;
#ifdef GRANCONTROLDEVICE
#define HARDWARE_VERSION		d'10'	 ;1.0
#endif
;
;Commonly Used Registeres
#define CarryFlag			STATUS,C,Access;Carry
#define ZeroFlag			STATUS,Z,Access;ZeroFlag
;
;Instruction definitions
#define Same				1	;Return register
#define Access				0	;Access Bank
#define Banked				1	;BSR Selected Bank
#define Shadow				1			
#define NoShadow			0
;
;Boolean Defninitions
#define FALSE				0	;False
#define TRUE				~FALSE	;True
;
Fast equ				TRUE	;Fast
Slow equ				~Fast	;Slow
;
#define Off				0	;Off
#define On				~Off	;On
;
#define NegativeLogic			0	;Negative Logic
#define PositiveLogic			~NegativeLogic;Positive Logic
;
;*******************************************************************************
;*  Bootloader
;*******************************************************************************
;
#define SIZE_OF_BLOCK			0x40
#define CODE_ADD_UPPER_DEF		0x00
#define CODE_ADD_HIGH_DEF		0x00
#define CODE_ADD_LOW_DEF		0x00
#define BUFFER_ADDR_HIGH		0x02
#define BUFFER_ADDR_LOW			0x00
#define EEPROM_ORIGIN			0x3000
#define CANBUS_ORIGIN			0x4400
#define BOOTLOADER_ORIGIN		0x6000
;
;*******************************************************************************
;*  Libraries
;*******************************************************************************
;
#include "P18F26K80.INC"			;PIC defninitions
;
;*******************************************************************************
;*  Keypad
;*******************************************************************************
;
#DEFINE FlipKeypad				;Flip the Keypad Direction
;
#IFNDEF FlipKeypad
;
#define RedLED				LATC,1,Access;Keypad Red led toggle bit
#define GreenLED			LATC,0,Access;Keypad Green led toggle bit
#define ManualClose			KeyFlags,0,Access;Manual Close Button has been pressed
#define ManualOpen			KeyFlags,1,Access;Manual Open Button has been pressed
#define ManualCloseHistory		KeyFlags,2,Access;Manual Close Button hisotry
#define ManualOpenHistory		KeyFlags,3,Access;Manual Open Button hisotry
#define BypassClose			KeyFlags,4,Access;Bypass Close Button has been pressed
#define BypassOpen			KeyFlags,5,Access;Bypass Open Button has been pressed
#define BypassCloseHistory		KeyFlags,6,Access;Bypass Close Button hisotry
#define BypassOpenHistory		KeyFlags,7,Access;Bypass Open Button hisotry
;
#ELSE
;
#define RedLED				LATC,0,Access;Keypad Red led toggle bit
#define GreenLED			LATC,1,Access;Keypad Green led toggle bit
#define BypassClose			KeyFlags,0,Access;Bypass Close Button has been pressed
#define BypassOpen			KeyFlags,1,Access;Bypass Open Button has been pressed
#define BypassCloseHistory		KeyFlags,2,Access;Bypass Close Button hisotry
#define BypassOpenHistory		KeyFlags,3,Access;Bypass Open Button hisotry
#define ManualClose			KeyFlags,4,Access;Manual Close Button has been pressed
#define ManualOpen			KeyFlags,5,Access;Manual Open Button has been pressed
#define ManualCloseHistory		KeyFlags,6,Access;Manual Close Button hisotry
#define ManualOpenHistory		KeyFlags,7,Access;Manual Open Button hisotry
;
#ENDIF
;
#define MembraneSWControlOpenPin	MembraneSwitches,0,Banked
#define MembraneSWControlClosePin	MembraneSwitches,1,Banked
#define MembraneSWBypassOpenPin		MembraneSwitches,2,Banked
#define MembraneSWBypassClosePin	MembraneSwitches,3,Banked
#define NoSwitch			MembraneSwitches,4,Banked,Off 
 
#define LEDGreenL			LEDFlags,0,Access
#define LEDGreenH			LEDFlags,1,Access
#define LEDRedL				LEDFlags,2,Access
#define LEDRedH				LEDFlags,3,Access
#define LEDSetBoth			LEDFlags,4,Access
#define LEDFlashGreen			LEDFlags,5,Access
#define LEDFlashRed			LEDFlags,6,Access
;
;*******************************************************************************
;*  Pin Setup
;*******************************************************************************
;
#ifdef	FLOWCONTROLDEVICE
;
;*          +-----+-----+-----+-----+-----+-----+-----+-----+
;*          |  7  |  6  |  5  |  4  |  3  |  2  |  1  |  0  |
;* +--------+-----+-----+-----+-----+-----+-----+-----+-----+
;* | TRIS A |  0  |  0  |  1  |  0  |  1  |  1  |  1  |  1  |
;* | LAT  A | OSC | OSC |  -  |  -  |  -  |  -  |  -  |  -  |
;* | PORT A |  -  |  -  | DIP |  -  |  M1 |  M0 |  VI | PRES|
;* +--------+-----+-----+-----+-----+-----+-----+-----+-----+
;* | TRIS B |  1  |  1  |  1  |  1  |  0  |  1  |  1  |  1  |
;* | LAT  B |  -  |  -  |  0  |  -  | STEP|  0  |  0  |  0  |
;* | PORT B | PGD | PGC | RST |ISTEP|  -  | ENG | PM  | WAT |
;* +--------+-----+-----+-----+-----+-----+-----+-----+-----+
;* | TRIS C |  1  |  0  |  0  |  0  |  0  |  0  |  0  |  0  |
;* | LAT  C |  0  | TX  | RSTS| DIR | DLED| PLED| GRN | RED |
;* | PORT C | RX  |  -  |  -  |  -  |  -  |  -  |  -  |  -  |
;* +--------+-----+-----+-----+-----+-----+-----+-----+-----+
;*
;LAT bits
#define InitialisePORTA			b'00000000'
#define InitialisePORTB			b'00000000'
#define InitialisePORTC			b'00000000'
;
;TRIS bits
#define ConfigurePORTA			b'00101111'
#define ConfigurePORTB			b'11110111'
#define ConfigurePORTC			b'10000000'
;
;Pins
;Pins A2 and A3 is defined in the keypad section
;
#define Pressure			PORTA,0,Access;Pressure
#define VoltIn				PORTA,1,Access;VoltIn
#define M0				PORTA,2,Access;Keypad M0
#define M1				PORTA,3,Access;Keypad M1
#define _RA4				PORTA,4,Access;
#define DIPSwitch			PORTA,5,Access;DIP Switch
#define _RA6				PORTA,6,Access;
#define _RA7				PORTA,7,Access;
;
#define _LA0				LATA,0,Access;
#define _LA1				LATA,1,Access;
#define _LA2				LATA,2,Access;
#define _LA3				LATA,3,Access;
#define _LA4				LATA,4,Access;
#define _LA5				LATA,5,Access;
#define _LA6				LATA,6,Access;
#define _LA7				LATA,7,Access;
;
#define WaterSensor			PORTB,0,Access;Water Sensor
#define PulseMeter			PORTB,1,Access;Flow meter pulse pickup
#define EngageBit			PORTB,2,Access;Engage Bit
#define _RB3				PORTB,3,Access;
#define _RB4				PORTB,4,Access;
#define ProgReset			PORTB,5,Access;Program Reset
#define _RB6				PORTB,6,Access;
#define _RB7				PORTB,7,Access;
;
#define _LB0				LATB,0,Access;
#define _LB1				LATB,1,Access;
#define _LB2				LATB,2,Access;
#define ValveStep			LATB,3,Access;Valve step pin
#define ValveCurrent			LATB,4,Access;Valve current sensor
#define _LB5				LATB,5,Access;
#define _LB6				LATB,6,Access;
#define _LB7				LATB,7,Access;
;
;Pins C0 and C1 is defined in the keypad section
#define _RC2				PORTC,2,Access;
#define _RC3				PORTC,3,Access;I2C SCL Pin Input
#define _RC4				PORTC,4,Access;Valve step Direction (See Stepper Motor section)
#define _RC5				PORTC,5,Access;
#define _RC6				PORTC,6,Access;
#define RX				PORTC,7,Access;Serial RX
;
#define AnalogueLED			LATC,2,Access;Pressure LED
#define DIPLED				LATC,3,Access;DIP switch LED
#define ValveDirection			LATC,4,Access;Valve step Direction (See Stepper Motor section)
#define ValveReset			LATC,5,Access;Reset
#define TX				LATC,6,Access;Serial TX
#define _LC7				LATC,7,Access;
;
#define MCLR				PORTE,3,Access;MCLR Pin
;
#endif
;
#ifdef	HYDDRIVEDEVICE
;
;*          +-----+-----+-----+-----+-----+-----+-----+-----+
;*          |  7  |  6  |  5  |  4  |  3  |  2  |  1  |  0  |
;* +--------+-----+-----+-----+-----+-----+-----+-----+-----+
;* | TRIS A |  0  |  0  |  0  |  0  |  1  |  1  |  1  |  1  |
;* | LAT  A |  -  |  -  |  -  |  -  |  -  |  -  |  -  |  -  |
;* | PORT A | OSC | OSC |  -  |  -  |  M1 |  M0 |  VI |  A  |
;* +--------+-----+-----+-----+-----+-----+-----+-----+-----+
;* | TRIS B |  0  |  0  |  0  |  0  |  0  |  0  |  1  |  1  |
;* | LAT  B |  -  |  -  |  0  |  -  |  -  |  -  |  0  |  0  |
;* | PORT B | PGD | PGC | RST |  -  |  -  |  -  | PM  | WAT |
;* +--------+-----+-----+-----+-----+-----+-----+-----+-----+
;* | TRIS C |  1  |  0  |  0  |  0  |  0  |  0  |  0  |  0  |
;* | LAT  C |  0  | TX  |  -  |  -  |  -  | PWM | GRN | RED |
;* | PORT C | RX  |  -  |  -  |  -  |  -  |  -  |  -  |  -  |
;* +--------+-----+-----+-----+-----+-----+-----+-----+-----+
;*
;LAT bits
#define InitialisePORTA			b'00000000'
#define InitialisePORTB			b'00000000'
#define InitialisePORTC			b'00000000'
;
;TRIS bits
#define ConfigurePORTA			b'00001111'
#define ConfigurePORTB			b'00000011'
#define ConfigurePORTC			b'10000000'
;
;Pins
;Pins A2 and A3 is defined in the keypad section
;
#define _A				PORTA,0,Access;
#define VoltIn				PORTA,1,Access;
#define M0				PORTA,2,Access;Keypad M0
#define M1				PORTA,3,Access;Keypad M1
#define _RA4				PORTA,4,Access;
#define _RA5				PORTA,5,Access;
#define _RA6				PORTA,6,Access;
#define _RA7				PORTA,7,Access;
;
#define SCOPE0				LATA,0,Access;
#define SCOPE1				LATA,1,Access;
#define _LA2				LATA,2,Access;
#define _LA3				LATA,3,Access;
#define _LA4				LATA,4,Access;
#define SCOPE2				LATA,5,Access;
#define _LA6				LATA,6,Access;
#define _LA7				LATA,7,Access;
;
#define WaterSensor			PORTB,0,Access;Water Sensor
#define PulseMotor			PORTB,1,Access;Flow meter pulse pickup
#define _RB2				PORTB,2,Access;
#define _RB3				PORTB,3,Access;
#define _RB4				PORTB,4,Access;
#define ProgReset			PORTB,5,Access;Program Reset
#define _RB6				PORTB,6,Access;
#define _RB7				PORTB,7,Access;
;
#define _LB0				LATB,0,Access;
#define _LB1				LATB,1,Access;
#define _LB2				LATB,2,Access;
#define _LB3				LATB,3,Access;
#define _LB4				LATB,4,Access;
#define _LB5				LATB,5,Access;
#define _LB6				LATB,6,Access;
#define _LB7				LATB,7,Access;
;
;Pins C0 and C1 is defined in the keypad section
#define _RC2				PORTC,2,Access;
#define _RC3				PORTC,3,Access;
#define _RC4				PORTC,4,Access;
#define _RC5				PORTC,5,Access;
#define _RC6				PORTC,6,Access;
#define RX				PORTC,7,Access;Serial RX
;
#define PWM_Pin				LATC,2,Access;
#define _LC3				LATC,3,Access;
#define _LC4				LATC,4,Access;
#define _LC5				LATC,5,Access;
#define TX				LATC,6,Access;Serial TX
#define _LC7				LATC,7,Access;
;
#define MCLR				PORTE,3,Access;MCLR Pin
;
#endif
;
#ifdef	GRANCONTROLDEVICE
;
;*          +-----+-----+-----+-----+-----+-----+-----+-----+
;*          |  7  |  6  |  5  |  4  |  3  |  2  |  1  |  0  |
;* +--------+-----+-----+-----+-----+-----+-----+-----+-----+
;* | TRIS A |  0  |  0  |  1  |  0  |  1  |  1  |  1  |  0  |
;* | LAT  A | OSC | OSC |  -  |  -  |  -  |  -  |  -  | MCLR|
;* | PORT A |  -  |  -  | DIP |  -  |  M1 |  M0 |  VI |  -  |
;* +--------+-----+-----+-----+-----+-----+-----+-----+-----+
;* | TRIS B |  1  |  0  |  0  |  1  |  1  |  1  |  1  |  1  |
;* | LAT  B |  -  |  -  |  0  |  -  |  -  |  0  |  0  |  0  |
;* | PORT B | PGD | PGC | RST |DOUT2|DOUT1| ENG | PIC | WAT |
;* +--------+-----+-----+-----+-----+-----+-----+-----+-----+
;* | TRIS C |  1  |  0  |  1  |  0  |  0  |  0  |  0  |  0  |
;* | LAT  C |  0  | TX  |  -  | SDA | SCL |  -  | GRN | RED |
;* | PORT C | RX  |  -  | DIP | SDA | SCL |  -  |  -  |  -  |
;* +--------+-----+-----+-----+-----+-----+-----+-----+-----+
;*
;
;LAT bits
#define InitialisePORTA			b'00110000'
#define InitialisePORTB			b'01000001'
#define InitialisePORTC			b'01000100'
;
;TRIS bits
#define ConfigurePORTA			b'00101110'
#define ConfigurePORTB			b'10011111'
#define ConfigurePORTC			b'10110000'
;
;Pins
;Pins A2 and A3 is defined in the keypad section
;
#define _RA0				PORTA,0,Access;Pressure
#define VoltIn				PORTA,1,Access;VoltIn
#define M0				PORTA,2,Access;Keypad M0
#define M1				PORTA,3,Access;Keypad M1
#define _RA4				PORTA,4,Access;
#define DIPSwitch			PORTA,5,Access;DIP Switch
#define _RA6				PORTA,6,Access;
#define _RA7				PORTA,7,Access;
;
#define HX711_Clock			LATA,0,Access;
#define _LA1				LATA,1,Access;
#define _LA2				LATA,2,Access;
#define _LA3				LATA,3,Access;
#define _LA4				LATA,4,Access;
#define _LA5				LATA,5,Access;
#define _LA6				LATA,6,Access;
#define _LA7				LATA,7,Access;
;
#define WaterSensor			PORTB,0,Access;Water Sensor
#define Flow1Pin			PORTB,1,Access;Flow meter pulse pickup
#define Flow2Pin			PORTB,2,Access;Engage Bit
#define HX711_Data			PORTB,3,Access;Cell1
#define HX711_Data2			PORTB,4,Access;Cell2
#define ProgReset			PORTB,5,Access;Program Reset
#define _PGC				PORTB,6,Access;
#define _PGD				PORTB,7,Access;
;
#define _LB0				LATB,0,Access;
#define _LB1				LATB,1,Access;
#define _LB2				LATB,2,Access;
#define _LB3				LATB,3,Access;Valve step pin
#define _LB4				LATB,4,Access;Valve current sensor
#define _LB5				LATB,5,Access;
#define _LB6				LATB,6,Access;
#define _LB7				LATB,7,Access;
;
;Pins C0 and C1 is defined in the keypad section
#define BoardID_PORT			PORTC,2,Access;
#define PWM_Pin				PORTC,2,Access;
#define _RC3				PORTC,3,Access;I2C SCL Pin Input
#define _RC4				PORTC,4,Access;Valve step Direction (See Stepper Motor section)
#define _RC5				PORTC,5,Access;
#define _RC6				PORTC,6,Access;
#define RX				PORTC,7,Access;Serial RX
;
#define BoardID_LAT			LATC,2,Access;Pressure LED
#define _LC3				LATC,3,Access;DIP switch LED
#define _LC4				LATC,4,Access;Valve step Direction (See Stepper Motor section)
#define DIPLED				LATC,5,Access;DIPLED
#define TX				LATC,6,Access;Serial TX
#define _LC7				LATC,7,Access;
;
#define BoardID_TRIS			TRISC,2,Access
;
#define MCLR				PORTE,3,Access;MCLR Pin
;
#endif
;
;*******************************************************************************
;*  Analogue and Digital
;*******************************************************************************
;
#ifdef	ADC_CONVERTER
;
;* +--------+-----+-----+-----+-----+-----+-----+-----+-----+
;* | ANCON0 | AN7 | AN6 | AN5 | AN4 | AN3 | AN2 | AN1 | AN0 |
;* |        |  0  |  0  |  0  |  1  |  0  |  0  |  1  |  1  |
;* +--------+-----+-----+-----+-----+-----+-----+-----+-----+
;* | ANCON1 |  -  | AN14| AN13| AN12| AN11| AN10| AN9 | AN8 |
;* |        |  -  |  0  |  0  |  0  |  0  |  0  |  1  |  0  |
;* +--------+-----+-----+-----+-----+-----+-----+-----+-----+
;
#ifdef GRANCONTROLDEVICE
;
#define TrackADC_DIPSW123		b'00000001';ADCON0 setup for Pressure Pin (AN0)
#define TrackADC_DIPSW456		b'00000101';ADCON0 setup for Voltage meter Pin (AN1)
#define TrackADC_Volt			b'00000101';ADCON0 setup for Voltage meter Pin (AN1)
#define TrackADC_Matrix0		b'00001001';ADCON0 setup for Keypad matrix 1 (AN2)
#define TrackADC_Matrix1		b'00001101';ADCON0 setup for Keypad matrix 2 (AN3)
#define TrackADC_DIP			b'00010001';ADCON0 setup for DIP switch Pin (AN4)
#define TrackADC_Current		b'00111101';ADCON0 setup for Current measurement (AN15)
;
#define ConfigureADC1			b'00000000';ADC1 Config
#define ConfigureADC2			b'00111110';ADC2 Config
;
#endif
;
#ifdef FLOWCONTROLDEVICE
;
#define TrackADC_Pressure		b'00000001';ADCON0 setup for Pressure Pin (AN0)
#define TrackADC_Volt			b'00000101';ADCON0 setup for Voltage meter Pin (AN1)
#define TrackADC_Matrix0		b'00001001';ADCON0 setup for Keypad matrix 1 (AN2)
#define TrackADC_Matrix1		b'00001101';ADCON0 setup for Keypad matrix 2 (AN3)
#define TrackADC_DIP			b'00010001';ADCON0 setup for DIP switch Pin (AN4)
#define TrackADC_Amp			b'00100101';ADCON0 setup for Ampere meter Pin (AN9)
;
#define ConfigureADC1			b'00000000';ADC1 Config
#define ConfigureADC2			b'00111110';ADC2 Config
;
#endif
;
#ifdef HYDDRIVEDEVICE
;
#define TrackADC_Volt			b'00000101';ADCON0 setup for Voltage meter Pin (AN1)
#define TrackADC_Matrix0		b'00001001';ADCON0 setup for Keypad matrix 1 (AN2)
#define TrackADC_Matrix1		b'00001101';ADCON0 setup for Keypad matrix 2 (AN3)
;#define TrackADC_Amp			b'00100101';ADCON0 setup for Ampere meter Pin (AN9)
;
#define ConfigureADC1			b'00000000';ADC1 Config
#define ConfigureADC2			b'00111110';ADC2 Config
;
#endif
;
;ANSEL bits
#ifdef FLOWCONTROLDEVICE
#define ConfigureANCON0			b'00010011'
#define ConfigureANCON1			b'00000010'
#else
#define ConfigureANCON0			b'00000011'
#define ConfigureANCON1			b'00000000'
#endif
;
#define _Go				ADCON0,GO,Access;ADCON0 Go bit
;
#endif
;
;*******************************************************************************
;*  Flags
;*******************************************************************************
;
#define ControlFlow			PulseFlags,0,Banked;
;
#ifdef	FLOWCONTROLDEVICE
;
#define FlowDevice			PulseFlags,1,Banked;
#define FCDevice			PulseFlags,2,Banked;
#define PressureDevice			PulseFlags,3,Banked;
#define FirstTracking			PulseFlags,4,Access;
;
#endif
;
#ifdef	GRANCONTROLDEVICE
;
#define FlowDevice			PulseFlags,1,Banked;
#define FCDevice			PulseFlags,2,Banked;
#define PressureDevice			PulseFlags,3,Banked;
;
#endif
;
#ifdef	HYDDRIVEDEVICE
;
#define KickStartFlag			SystemFlags0,6,Banked;
;
#endif
;
#ifdef	PULSE_SENSOR
;
#define ProcessNewPulseData		PulseFlags,4,Banked;
#define HydraulicRefresh		PulseFlags,5,Banked;Set when we need too transmit a packet to the hydraulic PCB
#define _ProcessPWM			PulseFlags,6,Banked;
#define Tick				PulseFlags,7,Banked;
;
#define Flasher				PulseSensorFlags,0,Access;
#define NewDataForSensor1		PulseSensorFlags,1,Access
#define Sensor1WrappedAround		PulseSensorFlags,2,Access
#define DisplayNewDataForInterrupt1	PulseSensorFlags,3,Access
#define Sensor1DataNotProcessed		PulseSensorFlags,4,Access
#define ReadPulseSensor			PulseSensorFlags,6,Access
#define ExtraBit			PulseSensorFlags,7,Access
;
#endif
;    
#ifdef CALCULATOR
;
#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;
;
#endif
;
#ifdef	CANBUS
 
#define Overflow0_bit			COMSTAT,7,Access;Overflow flag RX1
#define Overflow1_bit			COMSTAT,6,Access;Overflow flag RX0
#define CANBusError_bit			PIR5,5,Access;CANBus error flag
#define InvalidMessage_bit		PIR5,7,Access;Invalid message flag
#define TX2BufferIF			PIR5,4,Access;TX2 buffer interrupt flag
#define TX1BufferIF			PIR5,3,Access;TX1 buffer interrupt flag
#define TX0BufferIF			PIR5,2,Access;TX0 buffer interrupt flag
#define WAKEIF_				PIR5,6,Access;Wake up interrupt flag

#define BootModeBit			BootFlags,1,Banked ;Device currently updateing firmware
#define BootNewData			BootFlags,2,Banked ;Device has changes to program memory that are waiting to be saved

#define SentEngagedBit			DeviceFlags,0,Banked ;Engage status message sent
;
#ifdef FLOWCONTROLDEVICE
#define ManualCalibration		DeviceFlags,1,Banked ;Is manual calibration alllowed?
#define CalibrationMode			DeviceFlags,2,Banked ;Is the device in calibration mode
#define IncCalibBit			DeviceFlags,3,Banked ;Send an increase calibration message to main unit
#define DecCalibBit			DeviceFlags,4,Banked ;Send a decrease calibration message to main unit
#define IncCalibBitHis			DeviceFlags,5,Banked ;Has the increase calibration message been sent to main unit?
#define DecCalibBitHis			DeviceFlags,6,Banked ;Has the decrease calibration message been sent to main unit?
#endif
;
#define ActionType			DeviceFlags,5,Banked ;CANKingdom action type (Run:0, Freeze:1)
#define CommType			DeviceFlags,6,Banked ;CANKingdom communication type (Communicate:0, Listen only:1)
;
#define ConfigModeBit			ConfigFlags,0,Banked ;Is the device in config mode?
#define ConfigInitBit			ConfigFlags,1,Banked ;Has the device been initialised?
#define ConfigReplySent			ConfigFlags,2,Banked ;Has reply been sent to the main unit after button press?
#define ConfigBaseNum			ConfigFlags,3,Banked ;The base number has been registerd
#define ConfigDeviceNum			ConfigFlags,4,Banked ;A device number is also registered
;
#define DeviceIDDefault			0x88	;Device ID default symbol
;
#endif
;
#ifdef DIP_SWITCH
;
#define DIP_Switch_0			SystemFlags0,0,Banked
#define DIP_Switch_1			SystemFlags0,1,Banked
#define DIP_Switch_2			SystemFlags0,2,Banked
;
#endif
;
#ifdef VOLTAGE_METER
;
#define VoltFlag			SystemFlags0,3,Banked
;
#endif
;
#ifdef AMPERE_METER
;
#define AmpFlag				SystemFlags0,4,Banked
;
#endif 
;
#ifdef HAUL_SENSOR
;
#define HaulFlag			SystemFlags0,5,Banked
;
#endif 
;
#ifdef GRANCONTROLDEVICE
#define Switched			LoadCellFlags,0,Access
#define FirstTracking			LoadCellFlags,1,Access
#define ZeroPointReset			LoadCellFlags,2,Access
#endif
;
;*******************************************************************************
;*  CANBus Clock Speed
;*******************************************************************************
;
#ifdef CANBUS    
;#define BRP_Setup			0x43	;125khz SJW = 1 BRP = 3
;#define BRP_Setup			0x42	;?khz   SJW = 1 BRP = 2
#define BRP_Setup			0x41	;250khz SJW = 1 BRP = 1
;#define BRP_Setup			0x40	;500khz SJW = 1 BRP = 0
;#define SEG1_Setup			0x83	;SEG2PHTS = 1 SEG1PH = 1 PRSEG = 4 SAM = 0
#define SEG1_Setup			0x45	;SEG2PHTS = 1 SEG1PH = 5 PRSEG = 6 SAM = 0
#define SEG2_Setup			0x02	;SEG2PH = 2
#endif
;
;*******************************************************************************
;*  Timers
;*******************************************************************************
;
;Timer for delay functions
#ifdef	TIMER_0
#define _TMR0IF				INTCON, TMR0IF, Access;Timer0 Interrupt
#define _TMR0IE				INTCON, TMR0IE, Access;Timer0 Interrupt Enable
#define _TMR0IP				INTCON2,TMR0IP, Access;Timer0 Interrupt Priority
;Timer 0 is configured inline before use
#endif
;
;Timer Pulse Width Modulation
#ifdef	TIMER_1
#define _TMR1IP				IPR1,TMR1IP,Access;Timer1 Interrupt Priority
#define _TMR1IF				PIR1,TMR1IF,Access;Timer1 Interrupt 
#define _TMR1IE				PIE1,TMR1IE,Access;Timer1 Interrupt Enable
#define TMR1_OFFSET_MAX			8	;Timer1 double timer limit
#define ConfigureTMR1			b'00010001';Timer 1 Configuration
#endif
;
;Pulse timers
#ifdef	TIMER_2
#define _TMR2IP				IPR1,TMR2IP,Access;Timer2 Interrupt Priority
#define _TMR2IF				PIR1,TMR2IF,Access;Timer2 Interrupt 
#define _TMR2IE				PIE1,TMR2IE,Access;Timer2 Interrupt Enable
#define TC5msec				d'108'	;
#ifdef HYDDRIVEDEVICE
#define ConfigureTMR2			b'00010111';Timer 2 Configuration
#else
#define ConfigureTMR2			b'00111110';Timer 2 Configuration
#endif
#endif
;
;Timer 3 HH byte
#ifdef	TIMER_3
#define _TMR3IP				IPR2,TMR3IP,Access;Timer3 Interrupt Priority
#define _TMR3IF				PIR2,TMR3IF,Access;Timer3 Interrupt
#define _TMR3IE				PIE2,TMR3IE,Access;Timer3 Interrupt Enable
#define ConfigureTMR3			b'00110011';Timer 3 Configuration
#define ConfigureTMR3Gate		b'00000000';Timer 3 Gate Configuration
#define SkipFirstPulses1TC		2	;
#endif
;
;
#ifdef	TIMER_4
#define _TMR4IP				IPR4,TMR4IP,Access
#define _TMR4IF				PIR4,TMR4IF,Access;Timer4 Interrupt
#define _TMR4IE				PIE4,TMR4IE,Access
#ifdef HYDDRIVEDEVICE
#define ConfigureTMR4			b'00010111';Timer 4 Configuration
#else
#define ConfigureTMR4			b'00000101';Timer 4 Configuration
#endif
#endif
;
#ifdef	EXTERNAL_1
#define _INT1IP				INTCON3,INT1IP,Access;External Interrupt Priority
#define _INT1IE				INTCON3,INT1IE,Access;External Interrupt Enable
#define _INT1IF				INTCON3,INT1IF,Access;External Interrupt
#define _INT1EDG			INTCON2,INTEDG1,Access;External Interrupt Edge Select bit
#define _nRBPU				INTCON2,RBPU,Access;PORTB Pull-up Enable bit
#endif
;
;*******************************************************************************
;*  Interrupt Definitions
;*******************************************************************************
;
#define _GIEH				INTCON,GIEH,Access;Global Interrupt enable high
#define _GIEL				INTCON,GIEL,Access;Global Interrupt enable low
#define _IPEN				RCON,IPEN,Access;Interrupt Priority Enable bit
;
;*******************************************************************************
;*  EEPROM Definitions
;*******************************************************************************
;
#ifdef EEPROM_S
;
#define _EEPGD				EECON1,EEPGD,Access;Flash Program or Data EEPROM Memory Select bit
#define _EECFGS				EECON1,CFGS,Access;Flash Program/Data EEPROM or Configuration Select bit
#define _EERD				EECON1,RD,Access;Read Control bit
#define _EEFREE				EECON1,FREE,Access;Flash Row Erase Enable bit
#define _EEWREN				EECON1,WREN,Access;Flash Program/Data EEPROM Write Enable bit
#define _EEWR				EECON1,WR,Access;Write Control bit
;
#endif
;
;*******************************************************************************
;*  UART Definitions
;*******************************************************************************
;
#ifdef  UART_2
;
#define _SPEN2				RCSTA2,SPEN,Access;EUSART2 enable
#define _UART2MD			PMD0,UART2MD,Access;EUSART2 module enable
    
#define configureSPBRGH2		b'00000000';EUSART2 baud rate generator high byte
#define configureSPBRG2			b'00010001';EUSART2 baud rate generator low byte
;#define configureSPBRG2		b'00000000';EUSART2 baud rate generator low byte
#define configureTXSTA2			b'10100000';EUSART2 TXSTA2 bitset
    
#define _TX2IF				PIR3,TX2IF,Access;EUSART2 TX Interrupt
#define _TX2IE				PIE3,TX2IE,Access;EUSART2 TX Interrupt enable
#define _TX2IP				IPR3,TX2IP,Access;EUSART2 TX Interrupt priority
#define _RX2IF				PIR3,RC2IF,Access;EUSART2 RX Interrupt
#define _RX2IE				PIE3,RC2IE,Access;EUSART2 RX Interrupt enable
#define _RX2IP				IPR3,RC2IP,Access;EUSART2 RX Interrupt priority
    
#define _RCIDL				BAUDCON2,RCIDL,Access;EUSART2 Receive Operation Idle status bit
#define _CREN2				RCSTA2,CREN,Access;EUSART2 Receive enable bit
    
#define _TXEN2				TXSTA2,TXEN,Access;EUSART2 TX enable
#define _TRMT2				TXSTA2,TRMT,Access;EUSART2 TRMT pin
#define _TXREG2				TXREG2	;EUSART2 TX Buffer
#define _RCREG2				RCREG2	;EUSART2 RX Buffer
;
#endif
;
;*******************************************************************************
;*  Stepper Motor 
;*******************************************************************************
;
#ifdef STEPPER_MOTOR
;
#define OpenValve			CALL Call_openValve;Valve clear for open direction 
#define SkipIfValveOpen			BTFSC ValveDirection;Skip if valve open
#define CloseValve			CALL Call_closeValve;Valve set for close direction 
#define SkipIfValveClosed		BTFSS ValveDirection;Skip if valve closed
;
#endif
;
;*******************************************************************************
;*  Device specific definitions
;*******************************************************************************
;
#define FilterSize			9
#define PulseTC				d'60'	;*5msec = 300msec
#define ProcessPulsemeterTC		d'50'	;*5msec
#define TCFlasher			d'100'
;
#define TICKS_PER_REVOLUTION_SECOND	d'86398'
;
;*******************************************************************************
;*
;*  Memory Organization
;*
;*******************************************************************************
;*  Internal EEPROM memory map
;*******************************************************************************
;
#ifdef EEPROM_S
;
    CBLOCK  0 ;Map the persistent variables into the EEPROM
    EE_BootFlags
    EE_CANKing_MODE
    EE_BaseNumber
    EE_Folder_1L
    EE_Folder_1H
    EE_Folder_2L
    EE_Folder_2H
    EE_Folder_3L
    EE_Folder_3H
    EE_Folder_4L
    EE_Folder_4H
    EE_Folder_5L
    EE_Folder_5H
    EE_Folder_6L
    EE_Folder_6H
    EE_Folder_7L
    EE_Folder_7H
    EE_DeviceFlags
    EE_ConfigFlags
    EE_DeviceID
    EE_FlowRateL
    EE_FlowRateH
    EE_GoldenNumber
    EE_GoldenNumberH
    EE_GoldenNumberHH
    EE_GoldenNumberHHH
    EE_GoldenNumberHHHH
    EE_ZeroA
    EE_ZeroAH
    EE_ZeroAHH
    EE_ZeroB
    EE_ZeroBH
    EE_ZeroBHH
    ENDC
;
#endif
;
;*******************************************************************************
;* Access Memory
;*******************************************************************************
;
    CBLOCK  0x000
;
    STKPTR_Ltemp				;Stack pointer high and low bytes
    STKPTR_Lmax
    STKPTR_Htemp
    STKPTR_Hmax
;
    DeviceID_0
    DeviceID_1
    DeviceID_2
    DeviceID_3
    DeviceID_4
;
    LEDFlags					;Indicates what state the LED flags are in
;
    KeyFlags
;
    TMR3HH					;Additional counting byte for Timer 3
;
    PulseSensorFlags
;
    CheckAccess_0BankUsage
;
    ENDC
;
#IF CheckAccess_0BankUsage > h'10'
    ERROR "Too many file registers have been used in the Access Bank (0x00:0x0F)"
#ENDIF
;
    CBLOCK  0x010
;
    Steps					;Motor steps to be executed
    StepsH
    StepsOpen					;Motor steps from closed
    StepsOpenH
    StepBatch
;
    GoldenNumber				;Number used to fine tune flow meter accuracy
    GoldenNumberH
    GoldenNumberHH
    GoldenNumberHHH
    GoldenNumberHHHH
;
    MotorState					;State of valve function
    MotorCurrentReference			;Amp meter voltage reference for 0 urrent
    PulseTimer					;Used to see if there is a flow meter timeout
;
    CurrentReading
    CurrentDebounce
    CurrentShutDown
    CurrentShutDownH 
;
    LoadCellMul
    LoadCellMulH
    LoadCellDiv
    LoadCellDivH
;
    LoadCellA
    LoadCellAH
    LoadCellAHH
;
    LoadCellB
    LoadCellBH
    LoadCellBHH
;
    AgeA0
    AgeA1
    AgeA2
    AgeB0
    AgeB1
    AgeB2
;
    LoadCellFlags
;
    TrackingTimer
    TrackingTimerH
;
;
    CheckAccess_1BankUsage
;
    ENDC
;
#IF CheckAccess_1BankUsage > h'40'
    ERROR "Too many file registers have been used in the Access Bank (0x10:0x3F)"
#ENDIF
;
#ifdef	CALCULATOR
;
    CBLOCK  0x040
    CalculatorFlags				;Calculator Memory
    CalculatorCount
    CalculatorX0
    CalculatorX1
    CalculatorX2
    CalculatorX3
    CalculatorX4
    CalculatorY0
    CalculatorY1
    CalculatorY2
    CalculatorY3
    CalculatorY4
    CalculatorTA0
    CalculatorTA1
    CalculatorTA2
    CalculatorTA3
    CalculatorTA4
    CalculatorP0
    CalculatorP1
    CalculatorP2
    CalculatorP3
    CalculatorP4
;
    CheckAccess_4BankUsage
    ENDC
;
#IF CheckAccess_4BankUsage >= h'60'
    ERROR "Too many file registers have been used in the Access Bank (0x40:0x5F)"
#ENDIF
    
#endif
;
;*******************************************************************************
;*  Bank 0 Memory (Without Access)
;*******************************************************************************
;
    CBLOCK h'60'
;
    MassA
    MassAH
    MassAHH
;
    MassB
    MassBH
    MassBHH
;
    LoadCellAAverage
    LoadCellAAverageH
    LoadCellAAverageHH
    LoadCellBAverage
    LoadCellBAverageH
    LoadCellBAverageHH
    LoadCellCAverage
    LoadCellCAverageH
    LoadCellCAverageHH
;
    LoadCellA0
    LoadCellA0H
    LoadCellA0HH
    LoadCellA1
    LoadCellA1H
    LoadCellA1HH
    LoadCellA2
    LoadCellA2H
    LoadCellA2HH
    LoadCellB0
    LoadCellB0H
    LoadCellB0HH
    LoadCellB1
    LoadCellB1H
    LoadCellB1HH
    LoadCellB2
    LoadCellB2H
    LoadCellB2HH
;
    LoadCellAZero
    LoadCellAZeroH
    LoadCellAZeroHH
    LoadCellBZero
    LoadCellBZeroH
    LoadCellBZeroHH
    LoadCellCZero
    LoadCellCZeroH
    LoadCellCZeroHH
;
    gpm
    gpmH
    gpmHH
;
    CheckBank0Usage
    ENDC
;
#IF CheckBank0Usage >= h'100'
    ERROR "Too many file registers have been used in Bank 0"
#ENDIF
;
;*******************************************************************************
;*  Bank 1 Memory
;*******************************************************************************
;
    CBLOCK h'100'
    
    BootFlags					;Is the device engaged or disingaged
    
    ;Interrupts
    SaveWREG					;PUSH Storage for Low Priority Interrupts
    SaveSTATUS
    SaveFSR0L
    SaveFSR0H
    SaveFSR1L
    SaveFSR1H
    SaveFSR2L
    SaveFSR2H
    SavePCLATH
    SavePCLATU
    SaveTBLPTR
    SaveTBLPTRH
    SaveTBLPTRU
    SaveTABLAT
    SavePRODL
    SavePRODH
    SaveBSR	    ;0x110
;
    ;Timers
    Timer1_offset				;Timers
;
    Interrupt1Count
;
    Interrupt1Time
    Interrupt1TimeH
    Interrupt1TimeHH
;
    Interrupt1Capture
    Interrupt1CaptureH
    Interrupt1CaptureHH
    Interrupt1CaptureCount			;0x120
    Interrupt1Work
    Interrupt1WorkH
    Interrupt1WorkHH
    Interrupt1WorkCount
    Interrupt1Old
    Interrupt1OldH
    Interrupt1OldHH
    Interrupt1OldCount
;
    Main_DoubleBuffer
    Main_DoubleBufferH
    SkipFirstPulses1
;
    ;EEPROM
    EEPROM_State
    EEPROM_Work
;
    UART2Write_State
    UART2Read_State
;
    Counter					;Bootloader counter
    DataAddressHigh				;Word to modify (at address) 
    DataAddressLow				;0x130
    NewDataHigh					;Word to replace with
    NewDataLow
    CodeAddressUpper
    CodeAddressHigh
    CodeAddressLow
    EraseAddressUpper
    EraseAddressHigh
    EraseAddressLow
;
    SystemFlags0
;
    DIPReading
;
    VoltReading
;
    AmpReading
;
    CheckBank1_0Usage
    ENDC
;   
;*******************************************************************************
;* CANBus Memory
;*******************************************************************************
;
#IF CheckBank1_0Usage > h'140'
    ERROR "Too many file registers have been used in Bank 1 (0x00:0x3F)"
#ENDIF
;
#ifdef	CANBUS
;
    CBLOCK h'140'
;
    CANKing_MODE				;CANKingdom Action, Comm and City Mode bits 
;
    BaseNumber					;Last received base number from capital
;
    DeviceID					;Current Deive ID
    DeviceFlags					;Is the device engaged or disingaged
    ConfigFlags					;Device config flags
    FlowRateH					;Current Flow rate 2bytes
    FlowRateL
;    
    Folder_1H					;Mayor's Message Folder Envelope
    Folder_1L
    Folder_2H					;Configuration Message Receive Folder Envelope
    Folder_2L
    Folder_3H					;Configuration Message Send Folder Envelope
    Folder_3L
    Folder_4H					;Bootloader Message Receive Folder Envelope
    Folder_4L
    Folder_5H					;Bootloader Message Send Folder Envelope
    Folder_5L
    Folder_6H					;Flow Control Message Receive Folder Envelope
    Folder_6L
    Folder_7H					;Flow Control Message Send Folder Envelope
    Folder_7L
;
    TXMessBuff_D0				;Message buffer used to send messages
    TXMessBuff_D1
    TXMessBuff_D2
    TXMessBuff_D3
    TXMessBuff_D4
    TXMessBuff_D5
    TXMessBuff_D6
    TXMessBuff_D7
    TXMessBuff_DL
    TXMessBuff_SH
    TXMessBuff_SL
    TXMessBuff_EH
    TXMessBuff_EL
;
    RXMessBuff_D0				;Message buffer used to proccess received messages
    RXMessBuff_D1
    RXMessBuff_D2
    RXMessBuff_D3
    RXMessBuff_D4
    RXMessBuff_D5
    RXMessBuff_D6
    RXMessBuff_D7
    RXMessBuff_DL
    RXMessBuff_SH
    RXMessBuff_SL
    RXMessBuff_EH
    RXMessBuff_EL
;
    TempCANSTAT
    TempCANCON
;
    CheckBank1_4Usage
    ENDC
;
#IF CheckBank1_4Usage > h'180'
    ERROR "Too many file registers have been used in Bank 1 (0x40:0x7F)"
#ENDIF   
;
#endif
;
#ifdef	STATISTICS
;
    CBLOCK h'180'
;
    StatsEntry0Age
    StatsEntry0
    StatsEntry0H
    StatsEntry1Age
    StatsEntry1
    StatsEntry1H
    StatsEntry2Age
    StatsEntry2
    StatsEntry2H
    StatsEntry3Age
    StatsEntry3
    StatsEntry3H
    StatsEntry4Age
    StatsEntry4
    StatsEntry4H
    StatsEntry5Age
    StatsEntry5
    StatsEntry5H
    StatsEntry6Age
    StatsEntry6
    StatsEntry6H
    StatsEntry7Age
    StatsEntry7
    StatsEntry7H
    StatsEntry8Age
    StatsEntry8
    StatsEntry8H
    StatsEntry9Age
    StatsEntry9
    StatsEntry9H
;
    StatsEntryA0
    StatsEntryA0H
    StatsEntryA1
    StatsEntryA1H
    StatsEntryA2
    StatsEntryA2H
    StatsEntryA3
    StatsEntryA3H
    StatsEntryA4
    StatsEntryA4H
    StatsEntryA5
    StatsEntryA5H
    StatsEntryA6
    StatsEntryA6H
    StatsEntryA7
    StatsEntryA7H
    StatsEntryA8
    StatsEntryA8H
    StatsEntryA9
    StatsEntryA9H
;
    MedianCounter
    MedianNewSamplePointer
    MedianNewSamplePointerH
    NewSample
    NewSampleH
;
    MedianTemp
    MedianTempH
    MedianTempAge
    SetError
    SetErrorH
;
    PWM_OutR
    PWM_OutRH
    PWM_Out
    PWM_SP
;
    PumpVolumeL				    ;Volume of one revolution on the hydraulic pump
    PumpVolumeH
;
    TargetVolumeL				    ;Target flow rate
    TargetVolumeH
    TargetVolumeU
;
    Matrix0					;Keypad Flags
    Matrix1
;
    ManualOpenDebounceTimer			;Keypad debounce timers
    ManualCloseDebounceTimer
;
    BypassOpenDebounceTimer
    BypassCloseDebounceTimer
;
    MembraneSwitches				;Keypad Flags
;
    CheckBank1_2Usage
    ENDC
;
#IF CheckBank1_2Usage > h'1D0'
    ERROR "Too many file registers have been used in Bank 1 (0x80:0xCF)"
#ENDIF
;
#endif
;
    CBLOCK h'1D0'
;
    OpenKickInitial
    OpenKickInitialH
    OpenKick
    OpenKickH
;
    PulseRange
    PulseRangeH
    PulseFlags
    PulseCalibration
    PulseProcessVariable
    PulseProcessVariableH
    ProcessPulsemeterTimer
    SetPoint
    SetPointH
    PulseAdjusted
    PulseAdjustedH
;
    Integral
    SetErrorOut
    SetErrorOutH
    DisplayMode
    DisplaySetErrorData
;
    AnalogueT					;Variables to store pressure
    AnalogueH
    AnalogueL
;
    PressureTargetH
    PressureTargetL
;
    PumpRPMH
;
    HydraulicSafetyTimer
    HydraulicSafetyTimerH
    HydraulicRefreshTimer
    HydraulicRefreshTimerH
;
    ControlOutput
    ControlSetPoint
    TickCount
    ProcessPWMTimer
    FlasherTimer
    AutoRepeat
;
    RPM_SP
    RPMH_SP
    RPMHH_SP
    RPM_SP_Old
    RPMH_SP_Old
    RPMHH_SP_Old
    RPM_PV
    RPMH_PV
    RPMHH_PV
    RPM_Error
    RPMH_Error
    RPMHH_Error
;
    CheckBank1_9Usage
    ENDC
;
#IF CheckBank1_9Usage > h'200'
    ERROR "Too many file registers have been used in Bank 1 (0xD0:0xFF)"
#ENDIF
;
;*******************************************************************************
;*  Bank 2 Memory
;*******************************************************************************
;
    CBLOCK h'200'
    CheckBank2Usage
    ENDC
;
#IF CheckBank2Usage > h'300'
    ERROR "Too many file registers have been used in Bank 2"
#ENDIF
;
;*******************************************************************************
;*  Bank 3 Memory
;*******************************************************************************
;
    CBLOCK h'300'
    CheckBank3Usage
    ENDC
;
#IF CheckBank3Usage > h'400'
    ERROR "Too many file registers have been used in Bank 3"
#ENDIF
;
;*******************************************************************************
;*  Bank 4 Memory
;*******************************************************************************
;
    CBLOCK h'400'
    CheckBank4Usage
    ENDC
;
#IF CheckBank4Usage > h'500'
    ERROR "Too many file registers have been used in Bank 4"
#ENDIF
;
;*******************************************************************************
;*
;*  Origins
;*
;*******************************************************************************
;*  Start
;*******************************************************************************
;
    ORG     0x00
;
ResetComesToHere:
;
    BANKSEL DefaultMemoryStart
    GOTO    Startup				;Start at Bootloader
;
;*******************************************************************************
;*  High Priority Interrupts
;*******************************************************************************
;
    ORG     0x08
    CALL    ProcessHighPriorityInterrupts
    RETFIE  FAST
;
;*******************************************************************************
;*  Low Priority Interrupts
;*******************************************************************************
;
    ORG     0x18
    CALL    ProcessLowPriorityInterrupts
    RETFIE
;
;Internal EEPROM ORG at end of code
;
;*******************************************************************************
;*****									   *****
;*****									   *****
;*****				Main Code				   *****
;*****									   *****
;*****									   *****
;*******************************************************************************
;
;*******************************************************************************
;*  Device ID
;*******************************************************************************
;
#ifdef	FLOWCONTROLDEVICE
;
;Flow Control Device ID
DeviceIDInitFlow:
;
    MOVLW   LOW(SOFTWARE_VERSION)
    MOVFF   WREG,DeviceID_0
    MOVLW   HIGH(SOFTWARE_VERSION)
    MOVFF   WREG,DeviceID_1
    MOVLW   LOW(HARDWARE_VERSION)
    MOVFF   WREG,DeviceID_2
    MOVLW   HIGH(HARDWARE_VERSION)
    MOVFF   WREG,DeviceID_3
    MOVLW   0xA5
    MOVFF   WREG,DeviceID_4
;
    RETURN
;
;FC Device ID
DeviceIDInitFC:
;
    MOVLW   LOW(SOFTWARE_VERSION)
    MOVFF   WREG,DeviceID_0
    MOVLW   HIGH(SOFTWARE_VERSION)
    MOVFF   WREG,DeviceID_1
    MOVLW   LOW(HARDWARE_VERSION)
    MOVFF   WREG,DeviceID_2
    MOVLW   HIGH(HARDWARE_VERSION)
    MOVFF   WREG,DeviceID_3
    MOVLW   0xFC
    MOVFF   WREG,DeviceID_4
;
    RETURN
;
;Pressure Control Device ID
DeviceIDInitPressure:
;
    MOVLW   LOW(SOFTWARE_VERSION)
    MOVFF   WREG,DeviceID_0
    MOVLW   HIGH(SOFTWARE_VERSION)
    MOVFF   WREG,DeviceID_1
    MOVLW   LOW(HARDWARE_VERSION)
    MOVFF   WREG,DeviceID_2
    MOVLW   HIGH(HARDWARE_VERSION)
    MOVFF   WREG,DeviceID_3
    MOVLW   0xB6
    MOVFF   WREG,DeviceID_4
;
    RETURN
;
#endif
;
#ifdef	HYDDRIVEDEVICE
;Hyd Drive Device ID
DeviceIDInitHyd:
;
    MOVLW   LOW(SOFTWARE_VERSION)
    MOVFF   WREG,DeviceID_0
    MOVLW   HIGH(SOFTWARE_VERSION)
    MOVFF   WREG,DeviceID_1
    MOVLW   LOW(HARDWARE_VERSION)
    MOVFF   WREG,DeviceID_2
    MOVLW   HIGH(HARDWARE_VERSION)
    MOVFF   WREG,DeviceID_3
    MOVLW   0xC7
    MOVFF   WREG,DeviceID_4
;
    RETURN
;
#endif
;
#ifdef	GRANCONTROLDEVICE
;Granular control Device ID
DeviceIDInitGran:
;
    MOVLW   LOW(SOFTWARE_VERSION)
    MOVFF   WREG,DeviceID_0
    MOVLW   HIGH(SOFTWARE_VERSION)
    MOVFF   WREG,DeviceID_1
    MOVLW   LOW(HARDWARE_VERSION)
    MOVFF   WREG,DeviceID_2
    MOVLW   HIGH(HARDWARE_VERSION)
    MOVFF   WREG,DeviceID_3
    MOVLW   0x3A
    MOVFF   WREG,DeviceID_4
;
    RETURN
;
#endif
;
Begin: 
;
;*******************************************************************************
;*  Initialisation
;*******************************************************************************
;
    CLRF    STKPTR_Lmax,Access			;Clear stack pointers
    CLRF    STKPTR_Hmax,Access
;   
    CALL    Boot_init				;Initialise Bootloader
    CALL    Pins_init				;Initialise pins
;
#ifdef STEPPER_MOTOR
    BCF	    ValveReset				;Reset the stepper motor
#endif
;
#ifdef ANALOGUE_SENSOR
    CALL    ADC_init				;Initialise ADC
#endif
;
#ifdef UART_2
    CALL    UART_init				;Initialise UART
#endif
;
#ifdef	FLOWCONTROLDEVICE
    CALL    Check_Device			;Find out what devvice is currently in use
;
FlowSectionInit:
;
    BTFSS   FlowDevice				;If this is a flow device
    GOTO    FCSectionInit			;Else goto next section
;
    CALL    DeviceIDInitFlow			;Init device ID
    CALL    PulseSensorInit			;Initialise flow-meter
    CALL    StepperMotorInit			;Initialise valve motor
;
    GOTO    ExitSectionInit			;After init exit
;
FCSectionInit:
;
    BTFSS   FCDevice				;If this is a fc peripheral device
    GOTO    PressureSectionInit
;
    CALL    DeviceIDInitFC			;Init device ID
    CALL    PulseSensorInit			;Initialise speed-pickup
    CALL    StepperMotorInit			;Initialise valve motor
;
    MOVLW   d'100'				;Init target pressure
    MOVWF   PressureTargetL,Banked
    MOVLW   d'0'				;
    MOVWF   PressureTargetH,Banked	    
;
    GOTO    ExitSectionInit			;After init exit
;
PressureSectionInit:
;
    BTFSS   PressureDevice			;If this is a pressure control device
    GOTO    ExitSectionInit
;
    CALL    DeviceIDInitPressure		;Init device ID
    CALL    StepperMotorInit			;Initialise valve motor
;
    MOVLW   d'100'				;Init target pressure
    MOVWF   PressureTargetL,Banked
    MOVLW   d'0'				;
    MOVWF   PressureTargetH,Banked	    
;
ExitSectionInit:
;
#endif
;
#ifdef	HYDDRIVEDEVICE
    CALL    DeviceIDInitHyd			;Init device ID
;
HydSectionInit:
;
    MOVLW   LOW(70)
    MOVWF   OpenKick,Banked
    MOVLW   HIGH(70)
    MOVWF   OpenKickH,Banked
;
    CALL    PulseSensorInit			;Initialise speed-pickup
;
    MOVLW   LOW(70)
    MOVWF   RPM_SP,Banked
    MOVLW   HIGH(70)
    MOVWF   RPMH_SP,Banked
;
#endif
;
#ifdef GRANCONTROLDEVICE
    CALL    DeviceIDInitGran
    CLRF    LoadCellFlags,Access
    BSF     FirstTracking
    MOVLW   LOW(2000)
    MOVWF   TrackingTimer,Access
    MOVLW   HIGH(2000)
    MOVWF   TrackingTimerH,Access
#endif
;
#ifdef	EXTERNAL_1
    CALL    External_1_init			;Initialise External Flow meter interrupt
#endif
;
#ifdef CANBUS
    CALL    CANBus_init				;Initialise CANBus
#endif
;
#ifdef	TIMER_1
    CALL    Timer_1_init			;Initialise timer 1
#endif
;
#ifdef	TIMER_2
    CALL    Timer_2_init			;Initialise timer 1
#endif
;
#ifdef	TIMER_3
    CALL    Timer_3_init			;Initialise timer 1
#endif
;
#ifdef	TIMER_4
    CALL    Timer_4_init			;Initialise timer 1
#endif
;
#ifdef	STATISTICS
    CALL    Stats_Init
#endif
;
#ifdef HAUL_SENSOR
    CALL    HaulSensorInit
#endif
;
#ifdef KEYPAD
    CALL    Keypad_init
#endif
;
    CALL    Interrupts_init			;Initialise interrupts
;
;*******************************************************************************
;*  Forever Loop
;*******************************************************************************
;
Forever:
;
    BTFSC   BootModeBit
    BCF	    _GIEH
    BTFSC   BootModeBit				;If in boot mode then just go into forever loop
    GOTO    Closed_Loop
;
#ifdef  PULSE_SENSOR
    ;Pulse sensor
    CALL    ProcessPulseSensor			;Get Flow rate
#endif    
;
#ifdef	FLOWCONTROLDEVICE
FlowSectionForever:
;
    BTFSS   FlowDevice				;If this is a flow device
    GOTO    FCSectionForever			;Else goto next section
    ;Flow device
    ;Flowmeter
    CALL    ProcessBSFMeter
    ;Stepper motor
    CALL    ProcessMotorState			;Process state of motor by using pressure difference
    CALL    ProcessStepperMotor			;Process motor
;
    GOTO    ExitSectionForever			;After init exit
;
FCSectionForever:
;
    BTFSS   FCDevice				;If this is a fc peripheral device
    GOTO    ExitSectionForever
    ;FC Device
    ;Speed Picup
    CALL    ProcessSpeedPickup
    ;Engage
    CALL    ProcessEngage
    ;Pressure
    CALL    ProcessPressure
    ;Stepper motor
    CALL    ProcessPressureMove			;Process state of motor by using pressure difference
    CALL    ProcessStepperMotor			;Process motor steps
;
    GOTO    ExitSectionForever			;After init exit
;
ExitSectionForever:
;
#endif        

    ;Flowmeter
#ifdef	HYDDRIVEDEVICE
    CALL    ProcessPWM
#endif
;
    ;Haul Sensor
#ifdef HAUL_SENSOR
    CALL    ProcessHaulSensor
    CALL    ProcessHaulFlag
#endif
    ;Comms
#ifdef UART_2
    CALL    UART2Write_Process
#endif
    ;EEPROM
#ifdef EEPROM_S
    CALL    ProcessEEPROM
#endif
;
#ifdef VOLTAGE_METER
    CALL    VoltageMeter_Process
#endif
;
#ifdef AMPERE_METER
    CALL    AmpereMeter_Process
#endif
;
#ifdef	DIP_SWITCH
    CALL    Check_Device
#endif
;
#ifdef  LED_SEQUENCE
    CALL    ProcessLEDState
#endif
;
#ifdef  KEYPAD
    CALL    ProcessMembrane2x2Matrix
    CALL    ProcessKeypad
#endif
;
#ifdef GRANCONTROLDEVICE
    CALL    GranControl
#endif
;
    GOTO    Forever				;Repeat
;
;*******************************************************************************
;*
;*  This is where we actually process the high priority interrupts
;*
;*******************************************************************************
;
ProcessHighPriorityInterrupts:
;
    ;MOVF    BSR,W,Access
    ;XORLW   1
    ;BTFSS   ZeroFlag
    ;NOP
;
    MOVF    STKPTR,W,Access
    ANDLW   b'00011111'
    MOVWF   STKPTR_Htemp,Access
;
    SUBWF   STKPTR_Hmax,W,Access
    BTFSS   CarryFlag
    MOVFF   STKPTR_Htemp,STKPTR_Hmax
;
    ;Interrupts go here
;
#ifdef	TIMER_3
    BTFSC   _TMR3IF				;Timer 3 interrupt
    CALL    Timer_3_interrupt
#endif
;
#ifdef CANBUS
    BCF	    PIR5,7,Access
    CALL    CANInterrupts
#endif
;
#ifdef	EXTERNAL_1
    BTFSC   _INT1IF				;External 1 interrupt
    CALL    External_1_interrupt
#endif
;
    ;MOVF    BSR,W,Access
    ;XORLW   1
    ;BTFSS   ZeroFlag
    ;NOP
;
    RETURN					;Exit
;
;*******************************************************************************
;*
;*  This is where we actually process the low priority interrupts
;*
;*******************************************************************************
;
ProcessLowPriorityInterrupts:
;
    ;Save registers
    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
;
    MOVF    STKPTR,W,Access
    ANDLW   b'00011111'
    MOVWF   STKPTR_Ltemp,Access
;
    SUBWF   STKPTR_Lmax,W,Access
    BTFSS   CarryFlag
    MOVFF   STKPTR_Ltemp,STKPTR_Lmax
;
    MOVF    BSR,W,Access
    XORLW   1
    BTFSS   ZeroFlag
    NOP
;
ProcessInterrupts2:
;
    ;Interrupts go here
#ifdef	TIMER_1
    BTFSC   _TMR1IF				;Timer 1 interrupt
    CALL    Timer_1_interrupt	
#endif
;
#ifdef	TIMER_2
    BTFSC   _TMR2IF				;Timer 2 interrupt
    CALL    Timer_2_interrupt	
#endif
    
#ifdef	UART_2    
    BTFSC   _RX2IF
    CALL    UART2_RX_interrupt
#endif
    
#ifdef PULSEWIDTH_MOD
    BTFSC   _TMR4IF
    CALL    Timer_4_interrupt
#endif
;
    ;Restore registers
    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
;
    RETURN					;Exit
;
;*******************************************************************************
;*
;*  Basic opperations
;*
;*******************************************************************************
;
;*******************************************************************************
;*
;*  DIP switch
;*
;*******************************************************************************
;*  Initialisation
;*******************************************************************************
;
#ifdef	DIP_SWITCH
;
Check_Device:
;
    CALL    DIPSample				;First get the current DIP value
;
Check_FlowDevice:
;
    BTFSC   DIP_Switch_0
    GOTO    Check_FlowDevice_Cle
    BTFSC   DIP_Switch_1
    GOTO    Check_FlowDevice_Cle
    BTFSC   DIP_Switch_2
    GOTO    Check_FlowDevice_Cle
;
Check_FlowDevice_Set:
;
    BSF	    FlowDevice
    GOTO    Check_FCDevice
;
Check_FlowDevice_Cle:
;
    BCF	    FlowDevice
;
Check_FCDevice:
;
    BTFSS   DIP_Switch_0
    GOTO    Check_FCDevice_Cle
    BTFSC   DIP_Switch_1
    GOTO    Check_FCDevice_Cle
    BTFSC   DIP_Switch_2
    GOTO    Check_FCDevice_Cle
;
Check_FCDevice_Set:
;
    BSF	    FCDevice
    GOTO    Check_PressureDevice
;
Check_FCDevice_Cle:
;
    BCF	    FCDevice
;
Check_PressureDevice:
;
    BTFSC   DIP_Switch_0
    GOTO    Check_PressureDevice_Cle
    BTFSS   DIP_Switch_1
    GOTO    Check_PressureDevice_Cle
    BTFSC   DIP_Switch_2
    GOTO    Check_PressureDevice_Cle
;
Check_PressureDevice_Set:
;
    BSF	    PressureDevice
    GOTO    Check_Device_Exit
;
Check_PressureDevice_Cle:
;
    BCF	    PressureDevice
;
Check_Device_Exit:
;
    RETURN
;
DIPSample:
;
    ;Get the latest reading
    MOVLW   TrackADC_DIP			;Set ADCON0 register with correct values			
    CALL    ReadADC				;Wait until read complete
;
    MOVFF   ADRESH,DIPReading			;Read digital value from
;
SelectSWD      MACRO     LowerLimit,UpperLimit,Target,OfBank,SW0State,SW1State,SW2State
;
    LOCAL   SelectSWDEnd, SelectSWDStart
;
    MOVLW   LowerLimit				;Test if Target is bigger than lower limit
    SUBWF   Target,W,OfBank
;
    BTFSS   CarryFlag				;If true then continue
    GOTO    SelectSWDEnd				;Exit
;
    MOVLW   UpperLimit				;Test if Target is bigger than lower limit
    SUBWF   Target,W,OfBank
;
    BTFSS   CarryFlag				;If true then continue
    GOTO    SelectSWDStart			;Start
    BTFSS   ZeroFlag				;Else check if equal
    GOTO    SelectSWDEnd
;
SelectSWDStart:
;
    IF SW0State == On				;if state0 is On
    BSF	    DIP_Switch_0			;Then set bit
    ELSE
    BCF	    DIP_Switch_0			;Else clear bit
    ENDIF
;
    IF SW1State == On				;if state1 is On
    BSF	    DIP_Switch_1			;Then set bit
    ELSE
    BCF	    DIP_Switch_1			;Else clear bit
    ENDIF
;
    IF SW2State == On				;if state2 is On
    BSF	    DIP_Switch_2			;Then set bit
    ELSE
    BCF	    DIP_Switch_2			;Else clear bit
    ENDIF
;
SelectSWDEnd:
;
    ENDM
    ;Get correct reading
    SelectSWD 0x6A,0x76,DIPReading,Banked,Off,Off,Off
    SelectSWD 0x76,0x82,DIPReading,Banked,Off,Off,On
    SelectSWD 0x82,0x92,DIPReading,Banked,Off,On,Off
    SelectSWD 0x92,0x9C,DIPReading,Banked,Off,On,On
    SelectSWD 0x9C,0xAE,DIPReading,Banked,On,Off,Off
    SelectSWD 0xAE,0xC9,DIPReading,Banked,On,Off,On
    SelectSWD 0xC9,0xEC,DIPReading,Banked,On,On,Off
    SelectSWD 0xEC,0xFF,DIPReading,Banked,On,On,On
;
    RETURN
;
#endif
;
;*******************************************************************************
;*
;*  Voltage meter
;*
;*******************************************************************************
;*  Initialisation
;*******************************************************************************
;
#ifdef	VOLTAGE_METER
;
VoltageMeter_Process:
;
    ;Get the latest reading
    MOVLW   TrackADC_Volt			;Set ADCON0 register with correct values
    CALL    ReadADC				;Wait until read complete
;
    MOVFF   ADRESH,VoltReading			;Read digital value from
;
    MOVLW   0x40				;Test if Target is bigger than lower limit
    SUBWF   VoltReading,W,Banked
;
    BTFSS   CarryFlag				;If true then continue
    BSF	    VoltFlag
    BTFSC   CarryFlag
    BCF	    VoltFlag
;
    RETURN
;
#endif
;
;*******************************************************************************
;*
;*  Voltage meter
;*
;*******************************************************************************
;*  Initialisation
;*******************************************************************************
;
#ifdef	AMPERE_METER
;
AmpereMeter_Read:
;
    ;Get the latest reading
    MOVLW   TrackADC_Amp			;Set ADCON0 register with correct values
    CALL    ReadADC				;Wait until read complete
;
    MOVFF   ADRESH,AmpReading			;Read digital value from
;
    RETURN
;
AmpereMeter_Process:
;
    CALL    AmpereMeter_Read			;Get the current reading
    ;MOVLW   0x82				;Test if Target is bigger than lower limit
    MOVF    MotorCurrentReference,W,Access	;Get the reference value
    SUBWF   AmpReading,W,Banked
;
    BTFSS   CarryFlag				;If true then continue
    BSF	    AmpFlag
    BTFSC   CarryFlag
    BCF	    AmpFlag
;
    RETURN
;
#endif
;
;*******************************************************************************
;*
;*  Pins
;*
;*******************************************************************************
;*  Initialisation
;*******************************************************************************
;
Pins_init:
;
    MOVLW   InitialisePORTA			;Define port latches for old PCB for now
    MOVWF   LATA,Access
    MOVLW   InitialisePORTB
    MOVWF   LATB,Access
    MOVLW   InitialisePORTC
    MOVWF   LATC,Access
;
    MOVLW   ConfigurePORTA			;Configure port directions for old PCB for now
    MOVWF   TRISA,Access
    MOVLW   ConfigurePORTB
    MOVWF   TRISB,Access
    MOVLW   ConfigurePORTC
    MOVWF   TRISC,Access
;
#ifdef	EXTERNAL_1
    BCF	    _nRBPU				;Enable weak pull-ups on PORT B
#endif
;
    RETURN
;
;*******************************************************************************
;*
;*  Analogue/Digital
;*
;*******************************************************************************
;*  Initialisation
;*******************************************************************************
;
#ifdef ANALOGUE_SENSOR
ADC_init:
;
    MOVLW   ConfigureANCON0			;Define the analogue and digital mix for the PCB
    MOVFF   WREG,ANCON0
    MOVLW   ConfigureANCON1
    MOVFF   WREG,ANCON1
;
    MOVLW   ConfigureADC1			;Analog to Digital Converter config
    MOVFF   WREG,ADCON1
;
    MOVLW   ConfigureADC2
    MOVFF   WREG,ADCON2
;
    MOVLW   0
    MOVFF   WREG,CM1CON				;Comparator config
    MOVFF   WREG,CM2CON
;
    RETURN
;
;*******************************************************************************
;*  Read/Write Basic
;*******************************************************************************
;
ReadADC:
;
    MOVWF   ADCON0,Access			;Set Converter up with WREG
    BSF	    _Go					;Start conversion
;
ReadADC1:
;
    BTFSC   _Go					;Wait until conversion complete
    GOTO    ReadADC1
;
    RETURN					;Exit
#endif
;
;*******************************************************************************
;*
;*  EUSART
;*
;*******************************************************************************
;*  Initialisation
;*******************************************************************************
;
#ifdef UART_2
UART_init:
;
    BCF	    _UART2MD				;Enable EUSART2 module
    BSF	    _SPEN2				;Enable EUSART2
    BSF	    _CREN2				;Enable EUSART2 receive enable
;
    MOVLW   configureSPBRGH2			;Configure EUSART2 Baud Rate Generator high byte
    MOVFF   WREG,SPBRGH2
    MOVLW   configureSPBRG2			;Configure EUSART2 Baud Rate Generator low byte
    MOVFF   WREG,SPBRG2
    MOVLW   configureTXSTA2			;Configure EUSART2 Stat TX register
    MOVFF   WREG,TXSTA2
;
    CLRF    UART2Write_State,Banked
    CLRF    UART2Read_State,Banked
;
    RETURN
;
;*******************************************************************************
;*  Read/Write Basic
;*******************************************************************************
;
WriteUART2:
;
    MOVWF   _TXREG2,Access			;Copy data to transmit buffer
;
    RETURN					;Exit
;
ReadUART2:
;
    MOVF   _RCREG2,W,Access			;Copy from receive buffer
;
    RETURN					;Exit
;
;*******************************************************************************
;*  UART Advanced
;*******************************************************************************
;
UART2Write_Process:
;
    BTFSS   _TRMT2
    GOTO    UART2_End
;
;Macros    
UART2Write_Var MACRO     VariableName  
;				    
    MOVFF     VariableName,_TXREG2	    ;1,2  
;
    INCF      UART2Write_State,Same,Banked	;3   
;    
    GOTO    UART2_End				;4,5
    NOP						;6
    NOP						;7
    NOP						;8 
;
    ENDM
;
UART2Read_Var MACRO     VariableName  
;				    
    MOVFF     _RCREG2,VariableName	    
;
    INCF      UART2Read_State,Same,Banked	    
;    
    GOTO    UART2_End		
    NOP						;6
    NOP						;7
    NOP						;8 
;
    ENDM
;

UART2Write_Lit MACRO     LiteralName  
;
    MOVLW   LiteralName			   
    MOVWF   _TXREG2,Access
;
    INCF    UART2Write_State,Same,Banked 	    
;    
    GOTO    UART2_End	
    NOP						;6
    NOP						;7
    NOP						;8	
;
    ENDM
;
UART2Write_Res MACRO
;
    CLRF    UART2Write_State,Banked	
;
    GOTO    UART2_End
    NOP
    NOP
    NOP						;6
    NOP						;7
    NOP						;8 
;
    ENDM
;
UART2Read_Res MACRO
;
    CLRF    UART2Read_State,Banked	
;    
    CALL    Send_Simulated	;Send the received message over the CANBus
;
    GOTO    UART2_End
    NOP
    NOP
    NOP						;6
    NOP						;7
    NOP						;8 
;
    ENDM
;
UART2Write_Dispatcher:
;
    CLRF    PCLATU,Access
;
    MOVF    UART2Write_State,W,Banked
    SWAPF   WREG,W,Access
    ANDLW   b'00000011'
    ADDLW   HIGH(UART2Write_DispatchTable)
    MOVWF   PCLATH,Access
;
    MOVF    UART2Write_State,W,Banked
    SWAPF   WREG,W,Access
    ANDLW   b'11110000'
;
    ADDLW   LOW(UART2Write_DispatchTable)
    BTFSC   CarryFlag
    INCF    PCLATH,Same,Access
    MOVWF   PCL,Access
;
#ifdef FLOWCONTROLDEVICE
;
UART2Write_DispatchTable:
;
SysDat_00   UART2Write_Lit 0x3A
SysDat_01   UART2Write_Lit 0xA3
SysDat_02   UART2Write_Lit 0xA5
SysDat_03   UART2Write_Lit d'55'
SysDat_04   UART2Write_Var DeviceID
SysDat_05   UART2Write_Lit 0x00
SysDat_06   UART2Write_Var Interrupt1Time
SysDat_07   UART2Write_Var Interrupt1TimeH
SysDat_08   UART2Write_Var Interrupt1TimeHH
SysDat_09   UART2Write_Var StatsEntry0
SysDat_10   UART2Write_Var StatsEntry0H
SysDat_11   UART2Write_Var StatsEntry1
SysDat_12   UART2Write_Var StatsEntry1H
SysDat_13   UART2Write_Var StatsEntry2
    
SysDat_14   UART2Write_Var StatsEntry2H
SysDat_15   UART2Write_Var StatsEntry3
SysDat_16   UART2Write_Var StatsEntry3H
SysDat_17   UART2Write_Var StatsEntry4
SysDat_18   UART2Write_Var StatsEntry4H
SysDat_19   UART2Write_Var StatsEntry5
SysDat_20   UART2Write_Var StatsEntry5H
SysDat_21   UART2Write_Var StatsEntry6
SysDat_22   UART2Write_Var StatsEntry6H
SysDat_23   UART2Write_Var StatsEntry7
SysDat_24   UART2Write_Var StatsEntry7H
SysDat_25   UART2Write_Var StatsEntry8
SysDat_26   UART2Write_Var StatsEntry8H
SysDat_27   UART2Write_Var StatsEntry9
SysDat_28   UART2Write_Var StatsEntry9H
SysDat_29   UART2Write_Var StatsEntryA0
SysDat_30   UART2Write_Var StatsEntryA0H
    
SysDat_31   UART2Write_Var StatsEntryA1
SysDat_32   UART2Write_Var StatsEntryA1H
SysDat_33   UART2Write_Var StatsEntryA2
SysDat_34   UART2Write_Var StatsEntryA2H
SysDat_35   UART2Write_Var StatsEntryA3
SysDat_36   UART2Write_Var StatsEntryA3H
SysDat_37   UART2Write_Var StatsEntryA4
SysDat_38   UART2Write_Var StatsEntryA4H
SysDat_39   UART2Write_Var StatsEntryA5
SysDat_40   UART2Write_Var StatsEntryA5H
SysDat_41   UART2Write_Var StatsEntryA6
SysDat_42   UART2Write_Var StatsEntryA6H
SysDat_43   UART2Write_Var StatsEntryA7
SysDat_44   UART2Write_Var StatsEntryA7H
SysDat_45   UART2Write_Var StatsEntryA8
SysDat_46   UART2Write_Var StatsEntryA8H
    
#ifdef PULSE_SENSOR
SysDat_47   UART2Write_Var PulseRange
SysDat_48   UART2Write_Var PulseRangeH
SysDat_49   UART2Write_Var PulseProcessVariable
SysDat_50   UART2Write_Var PulseProcessVariableH
#else
SysDat_47   UART2Write_Lit 0x00
SysDat_48   UART2Write_Lit 0x00
SysDat_49   UART2Write_Lit 0x00
SysDat_50   UART2Write_Lit 0x00
#endif
    
SysDat_51   UART2Write_Var SetPoint
SysDat_52   UART2Write_Var SetPointH
SysDat_53   UART2Write_Var PulseAdjusted
SysDat_54   UART2Write_Var PulseAdjustedH
SysDat_55   UART2Write_Var PulseFlags
SysDat_56   UART2Write_Var MotorState
SysDat_57   UART2Write_Var DeviceID_4
SysDat_58   UART2Write_Lit 0x0A
SysDat_59   UART2Write_Lit 0x0D
SysDat_60   UART2Write_Res
SysDat_61   UART2Write_Res
    
#endif
    
#ifdef HYDDRIVEDEVICE
;
UART2Write_DispatchTable:
;
SysDat_00   UART2Write_Lit 0x3A
SysDat_01   UART2Write_Lit 0xA3
SysDat_02   UART2Write_Lit 0xC7
SysDat_03   UART2Write_Lit d'48'
SysDat_04   UART2Write_Var DeviceID
SysDat_05   UART2Write_Var Interrupt1Time
SysDat_06   UART2Write_Var Interrupt1TimeH
SysDat_07   UART2Write_Var Interrupt1TimeHH
SysDat_08   UART2Write_Var Interrupt1Work
SysDat_09   UART2Write_Var Interrupt1WorkH
SysDat_10   UART2Write_Var Interrupt1WorkHH
SysDat_11   UART2Write_Var CalculatorP0
SysDat_12   UART2Write_Var CalculatorP1
SysDat_13   UART2Write_Var CalculatorP2
SysDat_14   UART2Write_Var PulseRangeH
SysDat_15   UART2Write_Var RPM_SP
SysDat_16   UART2Write_Var RPMH_SP
SysDat_17   UART2Write_Var RPMHH_SP
SysDat_18   UART2Write_Var RPM_SP_Old
SysDat_19   UART2Write_Var RPMH_SP_Old
SysDat_20   UART2Write_Var RPM_PV
;
SysDat_21   UART2Write_Var RPMH_PV
SysDat_22   UART2Write_Var RPM_Error
SysDat_23   UART2Write_Var RPMH_Error
SysDat_24   UART2Write_Var RPMHH_Error
SysDat_25   UART2Write_Var PWM_OutR
SysDat_26   UART2Write_Var PWM_OutRH
SysDat_27   UART2Write_Var PWM_Out
SysDat_28   UART2Write_Var PWM_SP
SysDat_29   UART2Write_Var PulseRange
SysDat_30   UART2Write_Var PulseRangeH
SysDat_31   UART2Write_Var PumpVolumeL
SysDat_32   UART2Write_Var PumpVolumeL
SysDat_33   UART2Write_Var PumpVolumeH
SysDat_34   UART2Write_Var StatsEntry9H
SysDat_35   UART2Write_Var GoldenNumber
SysDat_36   UART2Write_Var GoldenNumberH
    
SysDat_37   UART2Write_Var GoldenNumberHH
SysDat_38   UART2Write_Var GoldenNumberHHH
SysDat_39   UART2Write_Var GoldenNumberHHHH
SysDat_40   UART2Write_Var NewSample
SysDat_41   UART2Write_Var NewSampleH
SysDat_42   UART2Write_Var RPM_PV
SysDat_43   UART2Write_Var RPMH_PV
SysDat_44   UART2Write_Var RPM_SP
SysDat_45   UART2Write_Var RPMH_SP
SysDat_46   UART2Write_Var TargetVolumeL
SysDat_47   UART2Write_Var TargetVolumeH
SysDat_48   UART2Write_Var TargetVolumeU
SysDat_49   UART2Write_Var PulseFlags
SysDat_50   UART2Write_Var MotorState
SysDat_51   UART2Write_Lit 0x0A
SysDat_52   UART2Write_Lit 0x0D
SysDat_53   UART2Write_Res
;
#endif
;
#ifdef GRANCONTROLDEVICE
;
UART2Write_DispatchTable:
;
SysDat_00   UART2Write_Lit ':'
SysDat_01   UART2Write_Var LoadCellA
SysDat_02   UART2Write_Var LoadCellAH
SysDat_03   UART2Write_Var LoadCellAHH
SysDat_04   UART2Write_Var LoadCellCAverage
SysDat_05   UART2Write_Var LoadCellCAverageH
SysDat_06   UART2Write_Var LoadCellCAverageHH
SysDat_07   UART2Write_Var LoadCellCZero
SysDat_08   UART2Write_Var LoadCellCZeroH
SysDat_09   UART2Write_Var LoadCellCZeroHH
SysDat_10   UART2Write_Var LoadCellB
SysDat_11   UART2Write_Var LoadCellBH
SysDat_12   UART2Write_Var LoadCellBHH
SysDat_13   UART2Write_Var CalculatorP0
SysDat_14   UART2Write_Var CalculatorP1
SysDat_15   UART2Write_Var StatsEntry2
    
SysDat_16   UART2Write_Var StatsEntry2H
SysDat_17   UART2Write_Var StatsEntry3
SysDat_18   UART2Write_Var StatsEntry3H
SysDat_19   UART2Write_Var StatsEntry4
SysDat_20   UART2Write_Var StatsEntry4H
SysDat_21   UART2Write_Var StatsEntry5
SysDat_22   UART2Write_Var StatsEntry5H
SysDat_23   UART2Write_Var StatsEntry6
SysDat_24   UART2Write_Var StatsEntry6H
SysDat_25   UART2Write_Var StatsEntry7
SysDat_26   UART2Write_Var StatsEntry7H
SysDat_27   UART2Write_Var StatsEntry8
SysDat_28   UART2Write_Var StatsEntry8H
SysDat_29   UART2Write_Var StatsEntry9
SysDat_30   UART2Write_Var StatsEntry9H
SysDat_31   UART2Write_Var LoadCellMul
SysDat_32   UART2Write_Var LoadCellMulH
    
SysDat_33   UART2Write_Var LoadCellDiv
SysDat_34   UART2Write_Var LoadCellDivH
SysDat_35   UART2Write_Var StatsEntryA2
SysDat_36   UART2Write_Var StatsEntryA2H
SysDat_37   UART2Write_Var StatsEntryA3
SysDat_38   UART2Write_Var StatsEntryA3H
SysDat_39   UART2Write_Var StatsEntryA4
SysDat_40   UART2Write_Var StatsEntryA4H
SysDat_41   UART2Write_Var StatsEntryA5
SysDat_42   UART2Write_Var StatsEntryA5H
SysDat_43   UART2Write_Var StatsEntryA6
SysDat_44   UART2Write_Var StatsEntryA6H
SysDat_45   UART2Write_Var StatsEntryA7
SysDat_46   UART2Write_Var SetPoint
SysDat_47   UART2Write_Var SetPointH
SysDat_48   UART2Write_Lit 0
    
#ifdef PULSE_SENSOR
SysDat_49   UART2Write_Var gpm
SysDat_50   UART2Write_Var gpmH
SysDat_51   UART2Write_Var gpmHH
SysDat_52   UART2Write_Var LoadCellBAverage
#else
SysDat_49   UART2Write_Lit 0x00
SysDat_50   UART2Write_Lit 0x00
SysDat_51   UART2Write_Lit 0x00
SysDat_52   UART2Write_Lit 0x00
#endif
    
SysDat_53   UART2Write_Var LoadCellBAverageH
SysDat_54   UART2Write_Var LoadCellBAverageHH
SysDat_55   UART2Write_Var PulseFlags
SysDat_56   UART2Write_Var MotorState
SysDat_57   UART2Write_Lit 0x0A
SysDat_58   UART2Write_Lit 0x0D
SysDat_59   UART2Write_Res
SysDat_60   UART2Write_Res
SysDat_61   UART2Write_Res
SysDat_62   UART2Write_Res
SysDat_63   UART2Write_Res
;
#endif
;
UART2_End:
;
    RETURN
;
;*******************************************************************************
;*  UART Interrupts
;******************************************************************************* 
;
UART2_RX_interrupt:
;
    BCF	    _RX2IF
;
#ifdef	SIMULATIONDEVICE
;
    TSTFSZ  UART2Read_State,Banked		;Check progress of reading data
    GOTO    UART2Read_Process			;If zero then goto read databyte
;
    MOVFF   _RCREG2,WREG			;Else check if data start marker
    SUBLW   ':'
    BTFSC   ZeroFlag
    INCF    UART2Read_State,Same,Banked
    GOTO    UART2Read_Interrupt_exit		;Waiting for start symbol  
;
UART2Read_Process:
;
    CLRF    PCLATU,Access			;Read correct data byte
;
    RLNCF   UART2Read_State,W,Banked
    SWAPF   WREG,W,Access
    ANDLW   b'00000011'
    ADDLW   HIGH(UART2Read_DispatchTable)
    MOVWF   PCLATH,Access
;
    RLNCF   UART2Read_State,W,Banked
    SWAPF   WREG,W,Access
    ANDLW   b'11100000'
;
    ADDLW   LOW(UART2Read_DispatchTable)
    BTFSC   CarryFlag
    INCF    PCLATH,Same,Access
    MOVWF   PCL,Access	  
;
UART2Read_DispatchTable:
;
SysData_Copy00 UART2Read_Var simulBuffer0
SysData_Copy01 UART2Read_Var simulBuffer1
SysData_Copy02 UART2Read_Var simulBuffer2
SysData_Copy03 UART2Read_Var simulBuffer3
SysData_Copy04 UART2Read_Var simulBuffer4
SysData_Copy05 UART2Read_Var simulBuffer5
SysData_Copy06 UART2Read_Var simulBuffer6
SysData_Copy07 UART2Read_Var simulBuffer7
SysData_Copy08 UART2Read_Var simulBuffer8
SysData_Copy09 UART2Read_Var simulBuffer9
SysData_Copy10 UART2Read_Var simulBuffer10
SysData_Copy11 UART2Read_Var simulBuffer11
SysData_Copy12 UART2Read_Var simulBuffer12
SysData_Copy13 UART2Read_Res
SysData_Copy14 UART2Read_Res
SysData_Copy15 UART2Read_Res
;
#endif  
;
UART2Read_Interrupt_exit:
;
    RETURN
#endif
;
;*******************************************************************************
;*
;*  Keypad
;*
;*******************************************************************************
;*  Macros
;*******************************************************************************
;*  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
;*******************************************************************************
;
#ifdef KEYPAD
;
Keypad_init:
;
#ifdef FLOWCONTROLDEVICE
    BCF	    CalibrationMode
#endif
;
    RETURN
;
Debounce     MACRO     PinLogic,PinFile,PinBit,PinBank,FlagFile,FlagBit,FlagBank,HistoryFile,HistoryBit,HistoryBank,TimerFile,TimerBank,TC
;
    LOCAL   WasLo,WasHi,Stable,Differs,ToggleHi,ToggleLo,DebounceEnd
;
    ;Check if bit was high or low
    BTFSS   HistoryFile,HistoryBit,HistoryBank  ;IF !HISTORY
    GOTO    WasLo				;THEN check if still LO
    GOTO    WasHi				;ELSE check if still HI
;
    ;Check if bit still low
WasLo:         
;
    BTFSS   PinFile,PinBit,PinBank		;IF !PIN
    GOTO    Stable				;THEN STABLE
    GOTO    Differs				;ELSE DIFFERS
;
    ;Check if bit still high
WasHi:         
;
    BTFSC   PinFile,PinBit,PinBank		;IF PIN
    GOTO    Stable				;THEN STABLE
    GOTO    Differs				;ELSE DIFFERS
;
    ;The bit is still stable so do a debounce
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
;
    ;Depending on the PinLogic either set or clear specific bits
    IF PinLogic==PositiveLogic
    BCF	    FlagFile,FlagBit,FlagBank
    ELSE
    BSF	    FlagFile,FlagBit,FlagBank 
    ENDIF
;
    BTFSC   HistoryFile,HistoryBit,HistoryBank	;FLAG!=HISTORY
;
    ;Depending on the PinLogic either set or clear specific bits
    IF PinLogic==PositiveLogic
    BSF	    FlagFile,FlagBit,FlagBank
    ELSE
    BCF	    FlagFile,FlagBit,FlagBank
    ENDIF
;
    GOTO    DebounceEnd
;
    ;The bit is different so do a reset
Differs:      
;
    MOVLW   TC					;Reload debounce timer
    MOVWF   TimerFile,TimerBank			;
;                                                        _______
    BTG	    HistoryFile,HistoryBit,HistoryBank	;HISTORY=HISTORY 
    GOTO    DebounceEnd				;Exit
;
DebounceEnd:
;
    ENDM
;
SelectSW      MACRO     Case,Of,OfBank,SelectEnd,SWAFile,SWABit,SWABank,SWAState,SWBFile,SWBBit,SWBBank,SWBState
;
    LOCAL   SelectSWEnd
;
    MOVLW   Case				;Test if Case is smaller than Of
    SUBWF   Of,W,OfBank
;
    BTFSS   CarryFlag				;If true then continue
    GOTO    SelectSWEnd				;Else exit
;
    ;Set states according to inputs
    IF SWAState == On				;if stateA is On
    BSF	    SWAFile,SWABit,SWABank		;Then set bit
    ELSE
    BCF	    SWAFile,SWABit,SWABank		;Else clear bit
    ENDIF
;
    IF SWBState == On 
    BSF	    SWBFile,SWBBit,SWBBank 
    ELSE
    BCF	    SWBFile,SWBBit,SWBBank 
    ENDIF
;
    GOTO    SelectEnd				;Exit	
;
SelectSWEnd:
;
    ENDM
;
;*******************************************************************************
;*  Keypad Matrix Test
;*******************************************************************************
;
ProcessMembrane2x2Matrix:
;
    MOVLW   TrackADC_Matrix0			;Set ADCON0 register with correct values
    CALL    ReadADC				;Wait until read complete
;
    MOVFF   ADRESH,Matrix0			;Read digital value from
;
    MOVLW   TrackADC_Matrix1			;Repeat for next set of values
    CALL    ReadADC
;
    MOVFF   ADRESH,Matrix1			;Read digital value from
;
ProcessMembrane2x2Matrix1:
;
    MOVLW   d'5'
    SUBWF   Matrix0,W,Banked
    BTFSS   CarryFlag
    GOTO    ProcessMembrane2x2Matrix1C		;If matrix 1 smaller than 5 then GOTO Process Matrix 2
;
    ;Else set flags according to button pushed
    SelectSW 0x98,Matrix0,Banked,ProcessMembrane2x2Matrix2,NoSwitch,NoSwitch
    SelectSW 0x88,Matrix0,Banked,ProcessMembrane2x2Matrix2,MembraneSWControlOpenPin,On,MembraneSWControlClosePin,On
    SelectSW 0x60,Matrix0,Banked,ProcessMembrane2x2Matrix2,MembraneSWControlOpenPin,Off,MembraneSWControlClosePin,On
    SelectSW 0x40,Matrix0,Banked,ProcessMembrane2x2Matrix2,MembraneSWControlOpenPin,On,MembraneSWControlClosePin,Off
;
ProcessMembrane2x2Matrix1C:
;
    ;If none of the above then clear flags
    BCF	    MembraneSWControlOpenPin
    BCF	    MembraneSWControlClosePin
;
ProcessMembrane2x2Matrix2:
;
    MOVLW   d'5'
    SUBWF   Matrix1,W,Banked
    BTFSS   CarryFlag
    GOTO    ProcessMembrane2x2Matrix2C		;If matrix 1 smaller than 5 then GOTO Process Matrix 2
;
    SelectSW 0x98,Matrix1,Banked,ProcessMembrane2x2MatrixEnd,NoSwitch,NoSwitch
    SelectSW 0x88,Matrix1,Banked,ProcessMembrane2x2MatrixEnd,MembraneSWBypassOpenPin,On,MembraneSWBypassClosePin,On
    SelectSW 0x60,Matrix1,Banked,ProcessMembrane2x2MatrixEnd,MembraneSWBypassOpenPin,On,MembraneSWBypassClosePin,Off
    SelectSW 0x40,Matrix1,Banked,ProcessMembrane2x2MatrixEnd,MembraneSWBypassOpenPin,Off,MembraneSWBypassClosePin,On
;
ProcessMembrane2x2Matrix2C:
;
    ;If none of the above then clear flags
    BCF	    MembraneSWBypassOpenPin
    BCF	    MembraneSWBypassClosePin
;
    GOTO    ProcessMembrane2x2MatrixEnd	;Else exit
;
ProcessMembrane2x2MatrixEnd:
;
    IFNDEF FlipKeypad 
        Debounce PositiveLogic,MembraneSWControlOpenPin,ManualOpen,ManualOpenHistory,ManualOpenDebounceTimer,Banked,1
        Debounce PositiveLogic,MembraneSWControlClosePin,ManualClose,ManualCloseHistory,ManualCloseDebounceTimer,Banked,1
;
        Debounce PositiveLogic,MembraneSWBypassOpenPin,BypassOpen,BypassOpenHistory,BypassOpenDebounceTimer,Banked,1
        Debounce PositiveLogic,MembraneSWBypassClosePin,BypassClose,BypassCloseHistory,BypassCloseDebounceTimer,Banked,1
    ELSE
        Debounce PositiveLogic,MembraneSWBypassOpenPin,ManualOpen,ManualOpenHistory,ManualOpenDebounceTimer,Banked,1
        Debounce PositiveLogic,MembraneSWBypassClosePin,ManualClose,ManualCloseHistory,ManualCloseDebounceTimer,Banked,1
;
        Debounce PositiveLogic,MembraneSWControlOpenPin,BypassOpen,BypassOpenHistory,BypassOpenDebounceTimer,Banked,1
        Debounce PositiveLogic,MembraneSWControlClosePin,BypassClose,BypassCloseHistory,BypassCloseDebounceTimer,Banked,1
    ENDIF
;
    RETURN
;
;*******************************************************************************
;*  Process Keypad Flags
;*******************************************************************************
;
ProcessKeypad:
;
ProcessKeypadTopLeft:
;
    BTFSS   ManualOpen				;If top-left button was pressed and pointing to diagnostic page 3 then show that button was pressed
    GOTO    ProcessKeypadBottomLeft
;
    BTFSC   ConfigModeBit
    GOTO    ConfigButtonPressPre
;
#ifdef FLOWCONTROLDEVICE
    BTFSS   FlowDevice
    GOTO    ProcessKeypadBottomLeft
;
    BSF	    CalibrationMode
#endif
;
    GOTO    ProcessKeypadBottomLeft
;
ProcessKeypadBottomLeft:
;
    BTFSS   ManualClose				;If bottom-left button was pressed and pointing to diagnostic page 4 then show that button was pressed
    GOTO    ProcessKeypadTopRight
;
    BTFSC   ConfigModeBit
    GOTO    ConfigButtonPressPre
;
#ifdef FLOWCONTROLDEVICE
    BTFSS   FlowDevice
    GOTO    ProcessKeypadTopRight
;
    BCF	    CalibrationMode
#endif
;
    GOTO    ProcessKeypadTopRight
;
ProcessKeypadTopRight:
;
    BTFSS   BypassOpen				;If top-right button was pressed and pointing to diagnostic page 5 then show that button was pressed
    GOTO    ProcessKeypadTopRight_O
;
    BTFSC   ConfigModeBit
    GOTO    ConfigButtonPressPre
;
#ifdef FLOWCONTROLDEVICE
    BTFSS   FlowDevice
    GOTO    ProcessKeypadBottomRight
;
    BTFSS   CalibrationMode
    GOTO    ProcessKeypadBottomRight
    BTFSC   IncCalibBitHis
    GOTO    ProcessKeypadBottomRight
;
    BSF	    IncCalibBit
    BSF	    IncCalibBitHis
    BSF	    LEDFlashRed
;
    CALL    Send_Flow_rate
#endif
;
    GOTO    ProcessKeypadBottomRight
;
ProcessKeypadTopRight_O:
;
#ifdef FLOWCONTROLDEVICE
    BCF	    IncCalibBit
    BCF	    IncCalibBitHis
#endif
;
    GOTO    ProcessKeypadBottomRight
;
ProcessKeypadBottomRight:
;
    BTFSS   BypassClose				;If bottom-right button was pressed and pointing to diagnostic page 6 then show that button was pressed
    GOTO    ProcessKeypadBottomRight_O
;
    BTFSC   ConfigModeBit
    GOTO    ConfigButtonPressPre
;
#ifdef FLOWCONTROLDEVICE
    BTFSS   FlowDevice
    GOTO    ProcessKeypadEnd
;
    BTFSS   CalibrationMode
    GOTO    ProcessKeypadEnd
    BTFSC   DecCalibBitHis
    GOTO    ProcessKeypadEnd
;
    BSF	    DecCalibBit
    BSF	    DecCalibBitHis
    BSF	    LEDFlashRed
;
    CALL    Send_Flow_rate
#endif
;
    GOTO    ProcessKeypadEnd
;
ProcessKeypadBottomRight_O:
;
#ifdef FLOWCONTROLDEVICE
    BCF	    DecCalibBit
    BCF	    DecCalibBitHis
#endif
;
    GOTO    ProcessKeypadEnd
;
ConfigButtonPressPre:
;
    CALL    ConfigButtonPress
;
ProcessKeypadEnd:
;
    RETURN
;
ConfigButtonPress:
;
    BTFSS   ConfigModeBit			;Only when in config state should this code execute. Thus test it first
    GOTO    ConfigButtonPress_Exit
    BTFSC   ConfigInitBit
    GOTO    ConfigButtonPress_Exit
    BTFSC   ConfigReplySent
    GOTO    ConfigButtonPress_Exit
;
    ;We are in config state so execute
    BSF	    ConfigReplySent			;Indicate that a message has been sent
;
    CALL    Send_Config_Button
;
ConfigButtonPress_Exit:
;
    RETURN
;
#endif
;
;*******************************************************************************
;*  Process LED Global State
;*******************************************************************************
;
#ifdef LED_SEQUENCE
;
ProcessLEDState:
;
    ;If not in init mode then green LED
    BTFSC   BootModeBit
    GOTO    ProcessLEDState_Boot
    BTFSS   ConfigModeBit				;If not in config mode
    GOTO    ProcessLEDState_NoConfig		;Then GOTO no config leg of code, else continue
;
    BTFSS   ConfigReplySent
    GOTO    ProcessLEDState_NoReply
    GOTO    ProcessLEDState_ReplySent
;
ProcessLEDState_Boot:
;
    CALL    ProcessGreen_LVL1			;Long Flash Green LED
    CALL    ProcessRed_LVL1			;Long Flash Red LED
    GOTO    ProcessLEDState_Exit		;Exit 
;
ProcessLEDState_NoConfig:
;
    BTFSC   ConfigInitBit
#ifdef FLOWCONTROLDEVICE
    GOTO    ProcessLEDState_Calibration
#else
    GOTO    ProcessLEDState_Init
#endif
;
    CALL    ProcessGreen_LVL2			;Short Flash Green LED
    CALL    ProcessRed_LVL0			;Clear Red LED
    GOTO    ProcessLEDState_Exit		;Exit
;
#ifdef FLOWCONTROLDEVICE
ProcessLEDState_Calibration:
;
    BTFSS   CalibrationMode
    GOTO    ProcessLEDState_Init
;
    CALL    ProcessGreen_LVL3			;Set Green LED
    CALL    ProcessRed_LVL0			;Clear Red LED
    GOTO    ProcessLEDState_Exit		;Exit
#endif
;    
ProcessLEDState_Init:
;
    CALL    ProcessGreen_LVL0			;Clear Green LED
    CALL    ProcessRed_LVL0			;Clear Red LED
    GOTO    ProcessLEDState_Exit		;Exit
;
ProcessLEDState_NoReply:
;
    CALL    ProcessGreen_LVL0			;Clear Green LED
    CALL    ProcessRed_LVL1			;Long Flash Red LED
    GOTO    ProcessLEDState_Exit		;Exit
;
ProcessLEDState_ReplySent:
;
    CALL    ProcessGreen_LVL0			;Clear Green LED
    CALL    ProcessRed_LVL3			;Set Flash Red LED
    GOTO    ProcessLEDState_Exit		;Exit
;
ProcessLEDState_Exit:
;
    RETURN
;
ProcessGreen_LVL0:
;
    BCF	    LEDGreenH
    BCF	    LEDGreenL
    RETURN
;
ProcessGreen_LVL1:
;
    BCF	    LEDGreenH
    BSF	    LEDGreenL
    RETURN
;
ProcessGreen_LVL2:
;
    BSF	    LEDGreenH
    BCF	    LEDGreenL
    RETURN
;
ProcessGreen_LVL3:
;
    BSF	    LEDGreenH
    BSF	    LEDGreenL
    RETURN
;
ProcessRed_LVL0:
;
    BCF	    LEDRedH
    BCF	    LEDRedL
    RETURN
;
ProcessRed_LVL1:
;
    BCF	    LEDRedH
    BSF	    LEDRedL
    RETURN
;
ProcessRed_LVL2:
;
    BSF	    LEDRedH
    BCF	    LEDRedL
    RETURN
;
ProcessRed_LVL3:
;
    BSF	    LEDRedH
    BSF	    LEDRedL
    RETURN
;
#endif
;
;*******************************************************************************
;*
;*  Haul Sensor
;*
;*******************************************************************************
;*  Haul Sensor  Init
;*******************************************************************************
;
#ifdef HAUL_SENSOR
HaulSensorInit:
;
    ;Init Haul sensor here
;
    RETURN
;
;*******************************************************************************
;*  Haul Sensor Test
;*******************************************************************************
;
ProcessHaulSensor:
;
    ;Test sensor here
    BTFSS   M1					;If haul sensor signal low
    BCF	    HaulFlag				;Then clear haul signal
    BTFSC   M1					;If haul sensor signal high
    BSF	    HaulFlag				;Then set haul signal
;
    RETURN
;
;*******************************************************************************
;*  Process Haul Sensor Flags
;*******************************************************************************
;
ProcessHaulFlag:
;
    BTFSC   HaulFlag				;If haul sensor received a signal
    CALL    ConfigSignal
;
    RETURN
;
ConfigSignal:
;
    BTFSS   ConfigModeBit			;Only when in config state should this code execute. Thus test it first
    GOTO    ConfigSignal_Exit
    BTFSC   ConfigInitBit
    GOTO    ConfigSignal_Exit
    BTFSC   ConfigReplySent
    GOTO    ConfigSignal_Exit
;
    ;We are in config state so execute
    BSF	    ConfigReplySent			;Indicate that a message has been sent
;
    CALL    Send_Config_Button
;
ConfigSignal_Exit:
;
    BCF	    HaulFlag				;Clear Haul sensor signal bit
    RETURN
#endif
;
;*******************************************************************************
;*
;*  External Interrupts
;*
;*******************************************************************************
;
#ifdef	EXTERNAL_1
;
;*******************************************************************************
;*  External 1 Init
;*******************************************************************************
;
External_1_init:
;
    BCF	    _INT1IE				;Clear external 1 interrupt enable
    BCF	    _INT1IF				;Clear external 1 interrupt
;
    CLRF    Interrupt1Count,Banked		;Clear interrupt1Count
    BSF	    _INT1IP				;Set as high priority interrupt
    BSF	    _INT1IE				;Set interrupt enable
;
    RETURN					;Exit
;
;*******************************************************************************
;*  External 1 interrupt handler
;*******************************************************************************
;
;Everytime the flow sensor signal goes high there is an interrupt which coppies the current time in Timer 3.
;The result is then processed in the ProcessPulseSensor line of code
External_1_interrupt:
;
    INCF    Interrupt1Count,Same,Banked		;Increase the number of interrupts that occurd
;
    BTFSC   NewDataForSensor1			;Check if Sensor data hase been processed before trying to add new data
    BSF	    Sensor1DataNotProcessed		;Indicate that data has not been processed
;
    BSF	    NewDataForSensor1			;Set the New data flag
;
    MOVFF   TMR3L,Interrupt1Capture		;Capture the current time and save to Interrupt1Capture
    MOVFF   TMR3H,Interrupt1CaptureH
    MOVFF   TMR3HH,Interrupt1CaptureHH
;
    INCFSZ  Interrupt1CaptureCount,W,Banked	;Increase to maximum of 0xFF
    INCF    Interrupt1CaptureCount,Same,Banked
;
    BCF	    _INT1IF
;
    RETURN
;
#endif
;
;*******************************************************************************
;*
;*  Interrupts
;*
;*******************************************************************************
;
Interrupts_init:
;
    BSF	    _IPEN				;Active low priority interrupts
    BSF	    _GIEL				;SET PEIE register
    BSF	    _GIEH				;SET GIE register
;
    RETURN					;Exit
;
;*******************************************************************************
;*
;*  Timers
;*
;*******************************************************************************
;
;Timer 0 is used by the delay functions
;
#ifdef	TIMER_1
;
;*******************************************************************************
;*  Timer 1 Init
;*******************************************************************************
;
Timer_1_init:
;
    CLRF    Timer1_offset,Banked
;
    BCF	    PMD1,TMR1MD,Access			;Clear TMR1MD register to anable Timer 1
    SETF    TMR1H,Access			;Set up timer 1 
    SETF    TMR1L
    BCF	    _TMR1IE				;Clear TMR1IE register
    BCF	    _TMR1IF				;Clear TMR1 Interrupt
    MOVLW   ConfigureTMR1
    MOVWF   T1CON,Access
    BCF	    _TMR1IP				;Clear high priority
    BSF	    _TMR1IE				;SET TMR1IE register
;
    RETURN
;
;*******************************************************************************
;*  Timer 1 interrupt handler
;*******************************************************************************
;
Timer_1_interrupt:
;
#ifdef LED_SEQUENCE
;This section controls the LEDs
    BCF	    _TMR1IF				;Clear TMR1 Interrupt
    INCF    Timer1_offset,Same,Banked
    MOVLW   TMR1_OFFSET_MAX
;
    CPFSEQ  Timer1_offset,Banked
    GOTO    Timer1_Short
    CLRF    Timer1_offset
;
Timer1_Long:
;
    BTFSC   LEDGreenH
    GOTO    LED_Red_long
    BTFSS   LEDGreenL
    GOTO    LED_Red_long
    BTG	    GreenLED
;
LED_Red_long:
;
    BTFSC   LEDRedH
    GOTO    Timer1_Short
    BTFSS   LEDRedL
    GOTO    Timer1_Short
    BTG	    RedLED
;
Timer1_Short:   
;
    BTFSC   LEDGreenH
    GOTO    LED_Green_Set
;
LED_Green_Clear:
;
    BTFSS   LEDGreenL
    BCF	    GreenLED
    GOTO    LED_Red
;
LED_Green_Set:
;
    BTFSS   LEDGreenL
    BTG	    GreenLED
    BTFSC   LEDGreenL
    BSF	    GreenLED
;
LED_Red:
;
    BTFSC   LEDRedH
    GOTO    LED_Red_Set
;
LED_Red_Clear:
;
    BTFSS   LEDRedL
    BCF	    RedLED
    GOTO    LED_Flash
;
LED_Red_Set:
;
    BTFSS   LEDRedL
    BTG	    RedLED
    BTFSC   LEDRedL
    BSF	    RedLED
;
LED_Flash:
;
    BTFSC   LEDFlashGreen
    BSF	    GreenLED
    BCF	    LEDFlashGreen
;
    BTFSC   LEDFlashRed
    BSF	    RedLED
    BCF	    LEDFlashRed
;
    RETURN
;
#endif
;
#endif
;
#ifdef	TIMER_2
;
;*******************************************************************************
;*  Timer 2 Init
;*******************************************************************************
;
Timer_2_init:
;
    BCF	    PMD1,TMR2MD,Access			;Clear TMR2MD register to anable Timer 2
    BCF	    _TMR2IE				;Clear TMR2IE register
    BCF	    _TMR2IF				;Clear TMR2 Interrupt
    MOVLW   ConfigureTMR2
    MOVWF   T2CON,Access
    BCF	    _TMR2IP				;Clear LOW priority
    BSF	    _TMR2IE				;SET TMR2IE register
;
    MOVLW   TC5msec				;Set up timer 2 timeout
    MOVWF   PR2,Access				;
;
    CLRF    TMR2,Access				;Reset Timer 2
;
    RETURN
;
;*******************************************************************************
;*  Timer 2 interrupt handler
;*******************************************************************************
;
Timer_2_interrupt:
;	
ProcessProcessPulsemeterTimer:
;
#ifdef HYDDRIVEDEVICE
    BCF	    _TMR2IE
    BCF	    PWM_Pin    
#else
;
    BCF	    _TMR2IF
;
    MOVF    ProcessPulsemeterTimer,W,Banked
    BTFSS   ZeroFlag
    DECF    ProcessPulsemeterTimer,Same,Banked
;
ProcessPulseTimer:
;
    MOVF    PulseTimer,W,Access
    BTFSS   ZeroFlag
    DECF    PulseTimer,Same,Access 
;
ProcessPulseTimerEnd:
#endif
;
#ifdef GRANCONTROLDEVICE
;
    MOVF    TrackingTimer,W,Access
    iorwf   TrackingTimerH,W,Access
    btfsc   ZeroFlag
    bcf     FirstTracking
    movlw   1
    subwf   TrackingTimer,Same,Access
    movlw   0 
    subwfb   TrackingTimerH,Same,Access
;
#endif
;
    RETURN
;
#endif
;
#ifdef	TIMER_3
;
;*******************************************************************************
;*  Timer 3 Init
;*******************************************************************************
;
Timer_3_init:
;
    BCF	    PMD1,TMR3MD,Access			;Clear TMR2MD register to anable Timer 2
    SETF    TMR3H
    SETF    TMR3L
    BCF	    _TMR3IE				;Clear TMR2IE register
    BCF	    _TMR3IF				;Clear TMR2 Interrupt
    MOVLW   ConfigureTMR3
    MOVWF   T3CON,Access
    MOVLW   ConfigureTMR3Gate
    MOVWF   T3GCON,Access
    BSF	    _TMR3IP				;Set high priority
    BSF	    _TMR3IE
;
    RETURN
;
;*******************************************************************************
;*  Timer 3 interrupt handler
;*******************************************************************************
;
Timer_3_interrupt:
;	    
    INCF    TMR3HH,Same,Access
    BTFSS   TMR3HH,2,Access
    GOTO    ProcessTimer3End
;
    CLRF    TMR3HH,Access    
;
    BTFSS   Sensor1WrappedAround
    GOTO    ProcessTimer3A
;
    MOVLW   SkipFirstPulses1TC
    MOVWF   SkipFirstPulses1,Banked
;
    BSF	    NewDataForSensor1
;
ProcessTimer3A:
;
    BSF	    Sensor1WrappedAround
;
ProcessTimer3End:
;
    BCF	    _TMR3IF
;
    RETURN
;
#endif
;
#ifdef	TIMER_4
;
;*******************************************************************************
;*  Timer 4 Init
;*******************************************************************************    
;
Timer_4_init: ;250usec at 11.0592MHz
;
    BCF	    _TMR4IP				;Set high priority
    BCF	    _TMR4IE
;
    MOVLW   d'172'
    MOVWF   PR4,Access
    MOVLW   ConfigureTMR4
    MOVWF   T4CON,Access
;
#ifdef PULSEWIDTH_MOD
    BSF	    _TMR4IE
#endif
;
    RETURN
;
#ifdef PULSEWIDTH_MOD
;
;This is where the PWM signal is generated
Timer_4_interrupt:
;
    BCF	    _TMR4IF
;
    MOVF      PWM_OutR,W,Banked			;If there is an error
    SUBWF     PWM_Out,W,Banked
;
    BTFSC     ZeroFlag				;Then slowly change the PWM_Out
    GOTO      ProcessTimer4_1A
;
    BTFSS     CarryFlag
    INCF      PWM_Out,Same,Banked 
    BTFSC     CarryFlag
    DECF      PWM_Out,Same,Banked
;
ProcessTimer4_1A:
;
    MOVF    PWM_Out,W,Banked			;If PWM_Out is zero
    BTFSS   ZeroFlag
    GOTO    ProcessTimer4_1			;Else goto next section
;
    BCF       PWM_Pin				;Then Clear the PWM pin
    BCF       _TMR2IE				;Clear and exit timer
;
    GOTO      ProcessTimer4_End
;
ProcessTimer4_1:
;
    BSF       PWM_Pin				;Set the PWM Pin
;
    MOVFF     PWM_Out,PR2			;Update the new Timer 1 tick limit
;
    MOVLW     0
    MOVFF     WREG,TMR2				;Reset TMR 2
;
    BCF       _TMR2IF
    BSF       _TMR2IE
;
ProcessTimer4_End:
;   
    decfsz    ProcessPWMTimer,Same,Banked	;Decrease the PWMTimer and check if zero
    goto      Skip1				;Else goto next section
    movlw     d'60'				;Then reset timer
    movwf     ProcessPWMTimer,Banked
    bsf       _ProcessPWM			;Indicate that the PWM should be processed
;
Skip1:
;
    RETURN
    
#endif
#endif
;
;*******************************************************************************
;*  Timer 6 interrupt handler
;*******************************************************************************
;
Timer_6_interrupt:
;
    ;bsf       Tick				;Indicate that a tick has occurded
    ;incf      TickCount,Same,Banked		;Increase tick count
;
    ;bsf       _Go				;Enable the ADC go bit
;
;Skip1:
;
    RETURN
;
;*******************************************************************************
;*
;*  Stepper Motor
;*
;*******************************************************************************
;*  Initialisation
;*******************************************************************************
;
#ifdef STEPPER_MOTOR
;
StepperMotorInit:
;
    MOVLW   LOW(0x200)				;Set enough steps to make sure valve is closed
    MOVWF   Steps,Access
    MOVLW   HIGH(0x200)
    MOVWF   StepsH,Access
;
    CALL    AmpereMeter_Read			;Get the latest reference current reading
    MOVFF   AmpReading,WREG			;Move the amp reading
    ADDLW   0x02				;Add 2 as offset to reading
    MOVWF   MotorCurrentReference,Access	;Set value as new reference
;
    BSF	    ValveReset				;Exit reset state
;
    RETURN
;
;*******************************************************************************
;*  Process stepper motor
;*******************************************************************************
;

ProcessStepperMotor:
;  
    BTFSS   _TMR4IF				;Skip this routine if the timer hasn't timed out yet
    GOTO    ProcessStepperMotorEnd
;
    CLRF    TMR4,Access				;Not sure where the timer may be, so ensure that this pulse is at least as long as it needs to be
    BCF	    _TMR4IF
;
    BTFSS   ValveStep
    GOTO    NextStep

    BCF	    ValveStep
;
    GOTO    ProcessStepperMotorEnd
;
NextStep:
;  
    MOVF    Steps,W,Access			;Check if any steps left
    IORWF   StepsH,W,Access
    BTFSC   ZeroFlag		
    GOTO    ProcessStepperMotorEnd		;If no steps then exit
    MOVLW   1					;Else continue
    SUBWF   Steps,Same,Access			;Decrease steps by 1
    MOVLW   0			
    SUBWFB  StepsH,Same,Access			;If borrow then subtract StepsH by 1
;
    SkipIfValveOpen			        ;Continue to function based on direction
    GOTO    ProcessStepperMotorClose            
    GOTO    ProcessStepperMotorOpen
;
ProcessStepperMotorClose:
;
    MOVF    StepsOpen,W,Access			;Check if stepsOpen not zero
    IORWF   StepsOpenH,W,Access	
    BTFSC   ZeroFlag				;then GOTO next section
    GOTO    ProcessStepperMotorClose1
;
    MOVLW   1					;Else subtract 1 from StepsOpen first
    SUBWF   StepsOpen,Same,Access
    MOVLW   0
    SUBWFB  StepsOpenH,Same,Access
;
ProcessStepperMotorClose1:
;
    GOTO    ProcessStepperMotorStep
;
ProcessStepperMotorOpen:
;
    BTFSC   StepsOpenH,4,Access			;Check if StepsOpen at max
    GOTO    ProcessStepperMotorOpen1		;Then GOTO next section
    MOVLW   1					;Else add 1
    ADDWF   StepsOpen,Same,Access
    MOVLW   0
    ADDWFC  StepsOpenH,Same,Access 
;
ProcessStepperMotorOpen1:
;
    GOTO    ProcessStepperMotorStep
;
ProcessStepperMotorStep:
;
    BSF	    ValveStep				;Set Step bit
;
ProcessStepperMotorEnd:
;
    RETURN					;Else exit
;
Call_openValve:
;
    BCF	    ValveDirection
    RETURN
;
Call_closeValve:
;
    BSF	    ValveDirection
    RETURN
;
;*******************************************************************************
;*  Process flow               
;*******************************************************************************
;
KickStartMotor:
;
    OpenValve
;              
KickStartStatsEntry1:
;
    MOVF    OpenKick,W,Banked
    MOVWF   Main_DoubleBuffer,Banked
    MOVF    OpenKickH,W,Banked
    MOVWF   Main_DoubleBufferH,Banked
;
    MOVF    OpenKick,W,Banked
    SUBWF   Main_DoubleBuffer,W,Banked
    BTFSS   ZeroFlag
    GOTO    KickStartStatsEntry1
;
    MOVF    OpenKickH,W,Banked
    SUBWF   Main_DoubleBufferH,W,Banked
    BTFSS   ZeroFlag
    GOTO    KickStartStatsEntry1
;
    MOVF    Main_DoubleBuffer,W,Banked
    SUBWF   Steps,W,Access
    MOVF    Main_DoubleBufferH,W,Banked
    SUBWFB  StepsH,W,Access
;
    BTFSC   CarryFlag
    GOTO    KickStartStatsEntry2
;
    MOVF    Main_DoubleBuffer,W,Banked
    MOVWF   Steps,Access
    MOVF    Main_DoubleBufferH,W,Banked
    MOVWF   StepsH,Access
;
    CALL    ReloadPulseTimer
;
KickStartStatsEntry2:
;
KickStartMotorEnd:
;
    RETURN
;
KickStartMotorInitial:
;
    OpenValve               
;
KickStartMotorInitial1:
;
    MOVF    OpenKickInitial,W,Banked
    MOVWF   Steps,Access
    MOVF    OpenKickInitialH,W,Banked
    MOVWF   StepsH,Access
;
    MOVF    OpenKickInitial,W,Banked
    SUBWF   Steps,W,Access
    BTFSS   ZeroFlag	
    GOTO    KickStartMotorInitial1
;
    MOVF    OpenKickInitialH,W,Banked
    SUBWF   StepsH,W,Access
    BTFSS   ZeroFlag	
    GOTO    KickStartMotorInitial1
;
    CALL    ReloadPulseTimer
;
KickStartMotorInitialEnd:
;
    RETURN
;
#endif
;
ResetFlow:
;
    ;Clear values stored
    CLRF    StatsEntry0
    CLRF    StatsEntry0H
    CLRF    StatsEntry1
    CLRF    StatsEntry1H
    CLRF    StatsEntry2
    CLRF    StatsEntry2H
    CLRF    StatsEntry3
    CLRF    StatsEntry3H
    CLRF    StatsEntry4
    CLRF    StatsEntry4H
    CLRF    StatsEntry5
    CLRF    StatsEntry5H
    CLRF    StatsEntry6
    CLRF    StatsEntry6H
    CLRF    StatsEntry7
    CLRF    StatsEntry7H
    CLRF    StatsEntry8
    CLRF    StatsEntry8H
    CLRF    StatsEntry9
    CLRF    StatsEntry9H
    CLRF    StatsEntryA0
    CLRF    StatsEntryA0H
    CLRF    StatsEntryA1
    CLRF    StatsEntryA1H
    CLRF    StatsEntryA2
    CLRF    StatsEntryA2H
    CLRF    StatsEntryA3
    CLRF    StatsEntryA3H
    CLRF    StatsEntryA4
    CLRF    StatsEntryA4H
    CLRF    StatsEntryA5
    CLRF    StatsEntryA5H
    CLRF    StatsEntryA6
    CLRF    StatsEntryA6H
    CLRF    StatsEntryA7
    CLRF    StatsEntryA7H
    CLRF    StatsEntryA8
    CLRF    StatsEntryA8H
    CLRF    StatsEntryA9
    CLRF    StatsEntryA9H
;
    RETURN
;
;*******************************************************************************
;*
;*  Pulse Meter
;*
;*******************************************************************************
;*  Init
;*******************************************************************************
;
#ifdef PULSE_SENSOR
;
PulseSensorInit:
    NOP
;
#ifdef FLOWCONTROLDEVICE
;
    BTFSS   FlowDevice				;If this is a flow device
    GOTO    PulseSensorInitFC
    MOVLW   0x14                    ;Load up the GoldenNumber with a hard coded value for now
    MOVWF   GoldenNumber,Access	    ;0005220814
    MOVLW   0x08             
    MOVWF   GoldenNumberH,Access
    MOVLW   0x22
    MOVWF   GoldenNumberHH,Access
    MOVLW   0x05
    MOVWF   GoldenNumberHHH,Access
    MOVLW   0x00
    MOVWF   GoldenNumberHHHH,Access
;
    GOTO    PulseSensorInitO
;
PulseSensorInitFC:
;
    MOVLW   0x59				;2765 ticks should give 1ms at 11.0952 MHz
    MOVWF   GoldenNumber,Access
    MOVLW   0x01             
    MOVWF   GoldenNumberH,Access
    MOVLW   0x00
    MOVWF   GoldenNumberHH,Access
    MOVLW   0x00
    MOVWF   GoldenNumberHHH,Access
    MOVLW   0x00
    MOVWF   GoldenNumberHHHH,Access
;
#endif
;
#ifdef HYDDRIVEDEVICE
;
    MOVLW   0x00                     ;Load up the GoldenNumber with a hard coded value for now
    MOVWF   GoldenNumber,Access
    MOVLW   0xBA       
    MOVWF   GoldenNumberH,Access
    MOVLW   0x6F
    MOVWF   GoldenNumberHH,Access
    MOVLW   0x12
    MOVWF   GoldenNumberHHH,Access
    MOVLW   0x00
    MOVWF   GoldenNumberHHHH,Access
;
#endif
;
HydrCalcNewGoldenNumber:
;
;   This section calulates the golden number based on the PumpVolume. The golden number is used to calculate the targeted ticks per pulse
;
    MOVFF   PumpVolumeL,CalculatorY0	    ;Get Pump Volume
    MOVFF   PumpVolumeH,CalculatorY1
;
    MOVLW   0
    MOVFF   WREG,CalculatorY2
    MOVFF   WREG,CalculatorY3
    MOVFF   WREG,CalculatorY4
;
    MOVLW   LOW(TICKS_PER_REVOLUTION_SECOND);The number of ticks per pulse at 60RPM (Using 4 magnets)
    MOVFF   WREG,CalculatorX0
    MOVLW   HIGH(TICKS_PER_REVOLUTION_SECOND);The number of ticks per pulse at 60RPM (Using 4 magnets)
    MOVFF   WREG,CalculatorX1
    MOVLW   UPPER(TICKS_PER_REVOLUTION_SECOND);The number of ticks per pulse at 60RPM (Using 4 magnets)
    MOVFF   WREG,CalculatorX2
    MOVLW   0
    MOVFF   WREG,CalculatorX3
    MOVFF   WREG,CalculatorX4
;
    CALL    Mul40			    ;Divide to get the new golden number
;
    ;MOVFF   CalculatorX0,GoldenNumber
    ;MOVFF   CalculatorX1,GoldenNumberH
    ;MOVFF   CalculatorX2,GoldenNumberHH
    ;MOVFF   CalculatorX3,GoldenNumberHHH
    ;MOVFF   CalculatorX4,GoldenNumberHHHH
;
;   This number must still be divided by 60 but that results in a golden number too small
;   so we''ll do it later somewhere else
;
    RETURN
;
PulseSensorInitO:
;
    BCF	    ControlFlow		    ;System start in disengaged mode
;
    MOVLW   0
    MOVWF   MotorState,Access
;
    MOVLW   d'100'
    MOVWF   PulseCalibration,Banked
;
    RETURN

;Works by sending a pulse at varying speeds depending on the rate of flow
ProcessPulseSensor:
;
    BTFSS   NewDataForSensor1			;If there is new data then start process
    GOTO    ProcessPulseSensorEnd		;Else exit
;
ProcessPulseSensorA:
;
    MOVF    Interrupt1Capture,W,Banked		;Move the data that was captured to Interrupt1Work register
    MOVWF   Interrupt1Work,Banked 
    MOVF    Interrupt1CaptureH,W,Banked
    MOVWF   Interrupt1WorkH,Banked
    MOVF    Interrupt1CaptureHH,W,Banked
    MOVWF   Interrupt1WorkHH,Banked
    MOVF    Interrupt1CaptureCount,W,Banked
    MOVWF   Interrupt1WorkCount,Banked
;
    MOVF    Interrupt1Capture,W,Banked		;Verify the data that was captured to Interrupt1Work register
    SUBWF   Interrupt1Work,W,Banked
    BTFSS   ZeroFlag
    GOTO    ProcessPulseSensorA
;
    MOVF    Interrupt1CaptureH,W,Banked		;Verify the data that was captured to Interrupt1Work register
    SUBWF   Interrupt1WorkH,W,Banked
    BTFSS   ZeroFlag
    GOTO    ProcessPulseSensorA
;
    MOVF    Interrupt1CaptureHH,W,Banked	;Verify the data that was captured to Interrupt1Work register
    SUBWF   Interrupt1WorkHH,W,Banked
    BTFSS   ZeroFlag
    GOTO    ProcessPulseSensorA
;
    MOVF    Interrupt1CaptureCount,W,Banked	;Verify the data that was captured to Interrupt1Work register
    SUBWF   Interrupt1WorkCount,W,Banked
    BTFSS   ZeroFlag
    GOTO    ProcessPulseSensorA
;
    CLRF    Interrupt1CaptureCount,Banked
;
    BCF     NewDataForSensor1			;Clear new data flag
;
    BCF     Sensor1WrappedAround		;
;
    BSF     DisplayNewDataForInterrupt1		;
;
    MOVF    Interrupt1Old,W,Banked		;Get difference between old interrupt value and new
    SUBWF   Interrupt1Work,W,Banked
    MOVWF   Interrupt1Time,Banked		;Put result in Interrupt1Time
;
    MOVF    Interrupt1OldH,W,Banked
    SUBWFB  Interrupt1WorkH,W,Banked
    MOVWF   Interrupt1TimeH,Banked
;
    MOVF    Interrupt1OldHH,W,Banked
    SUBWFB  Interrupt1WorkHH,W,Banked
    ANDLW   b'00000011'				;Tie up 1 - Only two bits in the upper byte are used
    MOVWF   Interrupt1TimeHH,Banked
;
    MOVFF   Interrupt1Work,Interrupt1Old	;The New interrupt value becomes the old
    MOVFF   Interrupt1WorkH,Interrupt1OldH
    MOVFF   Interrupt1WorkHH,Interrupt1OldHH
;
ProcessPulseSensorCFP:				;Check First Pulses
;
    MOVF    SkipFirstPulses1,W,Banked		;If SkipFirstPulses1 not empty
    BTFSC   ZeroFlag				;Then skip
    GOTO    ProcessPulseSensorCFPEnd		;Else process next bit of code
;
    DECF    SkipFirstPulses1,Same,Banked	;Decrease number of skips to still do
;
    MOVLW   0xFF
    CLRF    Interrupt1Count,Banked		;Set the current time difference to max because we are not going to use it
    MOVWF   Interrupt1Time,Banked
    MOVWF   Interrupt1TimeH,Banked
    MOVWF   Interrupt1TimeHH,Banked
    CLRF    Interrupt1CaptureCount,Banked            
;
    MOVLW   0					;Current flow rate should be 0 because we are still skipping the first few pulses
    MOVFF   WREG,PulseRange
    MOVFF   WREG,PulseRangeH
;
    BSF     ReadPulseSensor			;
;
#ifdef	HYDDRIVEDEVICE
    GOTO    HYDInterruptProcess
#endif
;
    GOTO    ProcessPulseSensorEnd		;Exit
;
ProcessPulseSensorCFPEnd:
;
;   Since we are not skipping we can continue with the calculations
;
#ifdef FLOWCONTROLDEVICE
;
;Divide the time difference by the number of pulses (This gets the time per pulse)
    MOVFF   Interrupt1Time,CalculatorX0	;Move The calculated time to CalculatorX
    MOVFF   Interrupt1TimeH,CalculatorX1
    MOVFF   Interrupt1TimeHH,CalculatorX2
    MOVLW   0
    MOVFF   WREG,CalculatorX3			;Upper bytes of CalcuatorX are made 0;
    MOVFF   WREG,CalculatorX4
;
    MOVFF   Interrupt1WorkCount,CalculatorY0	;Move counter to CalculatorY
    MOVLW   0
    MOVFF   WREG,CalculatorY1
    MOVFF   WREG,CalculatorY2
    MOVFF   WREG,CalculatorY3
    MOVFF   WREG,CalculatorY4	
; 
    CALL    Div40
;
;After the division sava a copy of result
;
;    MOVFF   CalculatorX0,CalculatorP0
;    MOVFF   CalculatorX1,CalculatorP1
;    MOVFF   CalculatorX2,CalculatorP2
;    MOVFF   CalculatorX3,CalculatorP3
;    MOVFF   CalculatorX4,CalculatorP4
;
ProcessFlowDeviceP:
;
    BTFSS   FlowDevice				;If this is a flow device
    GOTO    ProcessFCDeviceP
;
    MOVFF   CalculatorX0,CalculatorY0		;Move answer to Y
    MOVFF   CalculatorX1,CalculatorY1
    MOVFF   CalculatorX2,CalculatorY2
    MOVFF   CalculatorX3,CalculatorY3
    MOVFF   CalculatorX4,CalculatorY4
;
    MOVFF   GoldenNumber,CalculatorX0		;Move Golden Number to X
    MOVFF   GoldenNumberH,CalculatorX1
    MOVFF   GoldenNumberHH,CalculatorX2
    MOVFF   GoldenNumberHHH,CalculatorX3
    MOVFF   GoldenNumberHHHH,CalculatorX4
; 
    CALL    Div40				;Divide X by Y
;
    MOVF    CalculatorX2,W,Access		;Check if answer bigger than 0x7FFF
    BTFSS   ZeroFlag
    GOTO    ProcessPulseSensorMaxOut		;If bigger then max out CalculatorX
;
    MOVF    CalculatorX3,W,Access
    BTFSS   ZeroFlag
    GOTO    ProcessPulseSensorMaxOut
;
    MOVF    CalculatorX4,W,Access
    BTFSS   ZeroFlag
    GOTO    ProcessPulseSensorMaxOut
;
    BTFSC   CalculatorX1,7,Access
    GOTO    ProcessPulseSensorMaxOut
;            
    GOTO    ProcessPulseSensorSaveFlow		;Else just save flow
;
ProcessFCDeviceP:
;
    BTFSS   FCDevice				;If this is a flow device
    GOTO    ProcessPulseSensorSaveFlow
;
    MOVFF   GoldenNumber,CalculatorY0		;Move Golden Number to X
    MOVFF   GoldenNumberH,CalculatorY1
    MOVFF   GoldenNumberHH,CalculatorY2
    MOVFF   GoldenNumberHHH,CalculatorY3
    MOVFF   GoldenNumberHHHH,CalculatorY4
; 
    CALL    Div40				;Divide X by Y
;
    MOVF    CalculatorX2,W,Access		;Check if answer bigger than 0x7FFF
    BTFSS   ZeroFlag
    GOTO    ProcessPulseSensorMaxOut		;If bigger then max out CalculatorX
;
    MOVF    CalculatorX3,W,Access
    BTFSS   ZeroFlag
    GOTO    ProcessPulseSensorMaxOut
;
    MOVF    CalculatorX4,W,Access
    BTFSS   ZeroFlag
    GOTO    ProcessPulseSensorMaxOut
;
    BTFSC   CalculatorX1,7,Access
    GOTO    ProcessPulseSensorMaxOut
;            
    GOTO    ProcessPulseSensorSaveFlow		;Else just save flow
;
ProcessPulseSensorMaxOut:
;
    MOVLW   0xFF				;Max out by placing 0x7FFF in CalcuatorX
    MOVWF   CalculatorX0,Access
    MOVLW   0x7F
    MOVWF   CalculatorX1,Access
    CALL    ResetFlow				;Max out and set statistical memory to zero
;
#endif
;
#ifdef	HYDDRIVEDEVICE
;
HYDInterruptProcess:
;Divide the time difference by the number of pulses (This gets the time per pulse)
;
    MOVFF   Interrupt1Time,CalculatorX0	;Move The calculated time to CalculatorX
    MOVFF   Interrupt1TimeH,CalculatorX1
    MOVFF   Interrupt1TimeHH,CalculatorX2
    MOVLW   0
    MOVFF   WREG,CalculatorX3			;Upper bytes of CalcuatorX are made 0;
    MOVFF   WREG,CalculatorX4
;
;    MOVFF   Interrupt1WorkCount,CalculatorY0	;Move counter to CalculatorY
;    MOVLW   0
;    MOVFF   WREG,CalculatorY1
;    MOVFF   WREG,CalculatorY2
;    MOVFF   WREG,CalculatorY3
;    MOVFF   WREG,CalculatorY4	
; 
;    CALL    Div40
;
    MOVLW   d'60'
    MOVFF   WREG,CalculatorY0
    MOVLW   0
    MOVFF   WREG,CalculatorY1
    MOVFF   WREG,CalculatorY2
    MOVFF   WREG,CalculatorY3
    MOVFF   WREG,CalculatorY4
; 
    CALL    Mul40
;
    MOVFF   CalculatorX0,CalculatorY0
    MOVFF   CalculatorX1,CalculatorY1
    MOVFF   CalculatorX2,CalculatorY2
    MOVFF   CalculatorX3,CalculatorY3
    MOVFF   CalculatorX4,CalculatorY4
;
;   Next take the interrupt time (ticks) and devide by goldenNumber to get flow rate
;
    MOVFF   GoldenNumber,CalculatorX0		;Move Golden Number to X
    MOVFF   GoldenNumberH,CalculatorX1
    MOVFF   GoldenNumberHH,CalculatorX2
    MOVFF   GoldenNumberHHH,CalculatorX3
    MOVFF   GoldenNumberHHHH,CalculatorX4
; 
    CALL    Div40				;Divide X by Y
;
    MOVFF   CalculatorX0,NewSample		;Move the CalculatorX value to NewSample
    MOVFF   CalculatorX1,NewSampleH
    MOVFF   CalculatorX0,RPM_PV		;Move the CalculatorX value to NewSample
    MOVFF   CalculatorX1,RPMH_PV
;
; Now average the reading from the flow meter using the filers
;
    ;CALL    AverageFilter
;
    ;MOVFF   CalculatorX0,RPM_PV			;Copy the result to target variable
    ;MOVFF   CalculatorX1,RPMH_PV
    ;MOVFF   CalculatorX2,RPMHH_PV
;
#endif
    
#endif
;
ProcessPulseSensorSaveFlow:	
;
    MOVFF   CalculatorX0,PulseRange		;Save current Pulse Flow
    MOVFF   CalculatorX1,PulseRangeH
;
    BSF     ReadPulseSensor
;
ProcessPulseSensorEnd:
;
    RETURN
;
;*******************************************************************************
;*  Flow meter - Ball Sensor
;*******************************************************************************
;
#ifdef	FLOWCONTROLDEVICE
;
ProcessBSFMeter:
;
ProcessBSFMeter_Normal:
;
    BTFSS   ReadPulseSensor			;Check if it is neccesary to read sensor
    GOTO    ProcessBSFMeterEnd			;If not then exit
;
    BCF     ReadPulseSensor			;Else start by clearing ReadPulseSensor bit
;
ProcessBSFMeterTry:
;
    MOVFF   PulseRange,CalculatorX0		;Move PulseRange to CalculatorX
    MOVFF   PulseRangeH,CalculatorX1
;
    CALL    ReloadPulseTimer
;
    BTFSS   CalculatorX1,7,Access		;Check if Pulse Flow bigger than 0x7FFF
    GOTO    ProcessBSFMeter1			;Else GOTO next section of code
;Then set to zero
ProcessBSFMeterZero:
;
    MOVLW   0					;Clear CalculatorX
    MOVWF   CalculatorX0,Access
    MOVWF   CalculatorX1,Access
;
ProcessBSFMeter1:
;
    BTFSC   ControlFlow				;If ControlFlow set GOTO processPulseMotor2
    GOTO    ProcessBSFMeter2
;
    MOVLW   d'100'				;Subtract 100 from calculatorX
    SUBWF   CalculatorX0,W,Access
    MOVLW   0
    SUBWFB  CalculatorX1,W,Access
;
    BTFSC   CarryFlag				;If CalculatorX bigger, then reset CalculatorX
    GOTO    ProcessBSFMeter2			;Else continue
;
    MOVLW   0
    MOVWF   CalculatorX0,Access 
    MOVWF   CalculatorX1,Access 
;
ProcessBSFMeter2:
;
    MOVFF   CalculatorX0,NewSample		;Move the CalculatorX value to NewSample
    MOVFF   CalculatorX1,NewSampleH
;
; Now average the reading from the flow meter using the filers
;
    CALL    MedianFilterOrder
    CALL    AverageFilter
;
; Now apply the flow meter calibration from the flow meter EEPROM
;
    MOVFF   PulseCalibration,CalculatorY0 
    CLRF    CalculatorY1,Access
    CLRF    CalculatorY2,Access
    CLRF    CalculatorY3,Access
    CLRF    CalculatorY4,Access
;
    CALL    Mul40
;
    ; Skip the /100 for now
;
; Now apply the flow compensation from the main unit
;
    MOVLW   d'100'				;GB17 hard code this for now because it fluctuates and messes the process variable around
    MOVFF   WREG,CalculatorY0 ;MOVFF     FlowCompensation,CalculatorY0
    CLRF    CalculatorY1,Access
    CLRF    CalculatorY2,Access
    CLRF    CalculatorY3,Access
    CLRF    CalculatorY4,Access
;
    CALL    Mul40
;
    ; Skip the /100 for now
;
; Instead of /100 and /100 just do a single /10000
; 
    MOVLW   LOW(d'10000')
    MOVWF   CalculatorY0,Access
    MOVLW   HIGH(d'10000')
    MOVWF   CalculatorY1,Access
    CLRF    CalculatorY2,Access
    CLRF    CalculatorY3,Access
    CLRF    CalculatorY4,Access
;
    CALL    Div40
;
    MOVFF   CalculatorX0,PulseProcessVariable
    MOVFF   CalculatorX1,PulseProcessVariableH
;
    BSF	    ProcessNewPulseData
;
    ;BTFSS   ControlFlow
    GOTO    NormalAdjusting
    GOTO    StartAdjusting
;
NormalAdjusting:
;
    MOVFF   PulseProcessVariable,PulseAdjusted
    MOVFF   PulseProcessVariableH,PulseAdjustedH
    GOTO    ProcessBSFMeterEnd
;
StartAdjusting:
;Check if right size
;
    BSF	    ExtraBit
    CLRF    CalculatorP2,Access
    CLRF    CalculatorP3,Access
    CLRF    CalculatorP4,Access
    BCF	    CarryFlag
    MOVF    SetPoint,W,Banked			;Get the flow process target value
    SUBWF   PulseProcessVariable,W,Banked	;subtract the real flow rate
    MOVWF   CalculatorP0,Access			;to get the error
    MOVF    SetPointH,W,Banked
    SUBWFB  PulseProcessVariableH,W,Banked
    MOVWF   CalculatorP1,Access
;
    BTFSC   CarryFlag				;If the error is positive
    GOTO    CheckSize				;Then just do calculation else 
;
InvertFirst:
;
    BCF	    ExtraBit
    MOVF    PulseProcessVariable,W,Banked	;Get the flow process target value
    SUBWF   SetPoint,W,Banked			;subtract the real flow rate
    MOVWF   CalculatorP0,Access			;to get the error
    MOVF    PulseProcessVariableH,W,Banked
    SUBWFB  SetPointH,W,Banked
    MOVWF   CalculatorP1,Access
;
CheckSize:
;
    BCF	    CarryFlag
    MOVLW   LOW(1000)
    SUBWF   CalculatorP0,W,Access		;subtract the real flow rate
    MOVLW   HIGH(1000)
    SUBWFB  CalculatorP1,W,Access
;
    BTFSS   CarryFlag
    GOTO    ExtraAdjustment_In
;
CheckSize_2:
;
    BCF	    CarryFlag
    MOVLW   LOW(1250)
    SUBWF   CalculatorP0,W,Access		;subtract the real flow rate
    MOVLW   HIGH(1250)
    SUBWFB  CalculatorP1,W,Access
;
    BTFSC   CarryFlag
    GOTO    NormalAdjusting
    GOTO    ExtraAdjustment_Out
;
ExtraAdjustment_In:
;
    MOVFF   CalculatorP0,CalculatorX0
    MOVFF   CalculatorP1,CalculatorX1
    BCF	    CarryFlag			    ;Divide by 4
    RRCF    CalculatorX1, Same, Access
    RRCF    CalculatorX0, Same, Access
    BCF	    CarryFlag
    RRCF    CalculatorX1, Same, Access
    RRCF    CalculatorX0, Same, Access
;
    MOVFF   SetPoint,PulseAdjusted
    MOVFF   SetPointH,PulseAdjustedH
    BTFSS   ExtraBit
    GOTO    ExtraAdjustment_In_M
;
ExtraAdjustment_In_P:
;
    BCF	    CarryFlag
    MOVF    CalculatorX0,W,Access
    ADDWF   PulseAdjusted,Same,Banked
    MOVF    CalculatorX1,W,Access
    ADDWFC  PulseAdjustedH,Same,Banked
    GOTO    ProcessBSFMeterEnd
;
ExtraAdjustment_In_M:
;
    BCF	    CarryFlag
    MOVF    CalculatorX0,W,Access
    SUBWF   PulseAdjusted,Same,Banked
    MOVF    CalculatorX1,W,Access
    SUBWFB  PulseAdjustedH,Same,Banked
    GOTO    ProcessBSFMeterEnd
;
ExtraAdjustment_Out:
;
    BCF	    CarryFlag
    MOVLW   LOW(1000)
    SUBWF   CalculatorP0,Same,Access
    MOVLW   HIGH(1000)
    SUBWFB  CalculatorP1,Same,Access
;
    BCF	    CarryFlag			    ;Multiply by 4
    RLCF    CalculatorP0, Same, Access
    RLCF    CalculatorP1, Same, Access
    BCF	    CarryFlag
    RLCF    CalculatorP0, Same, Access
    RLCF    CalculatorP1, Same, Access
;
    MOVFF   SetPoint,PulseAdjusted
    MOVFF   SetPointH,PulseAdjustedH
;
    BCF	    CarryFlag
    MOVLW   LOW(250)
    ADDWF   CalculatorP0, Same, Access
    MOVLW   HIGH(250)
    ADDWFC  CalculatorP1, Same, Access
;
    BTFSS   ExtraBit
    GOTO    ExtraAdjustment_Out_M
;
ExtraAdjustment_Out_P:
;
    BCF	    CarryFlag
    MOVF    CalculatorP0,W,Access
    ADDWF   PulseAdjusted,Same,Banked
    MOVF    CalculatorP1,W,Access
    ADDWFC  PulseAdjustedH,Same,Banked
    GOTO    ProcessBSFMeterEnd
;
ExtraAdjustment_Out_M:
;
    BCF	    CarryFlag
    MOVF    CalculatorP0,W,Access
    SUBWF   PulseAdjusted,Same,Banked
    MOVF    CalculatorP1,W,Access
    SUBWFB  PulseAdjustedH,Same,Banked
    GOTO    ProcessBSFMeterEnd
;
ProcessBSFMeterEnd:
;
    RETURN
;
#endif
;
;*******************************************************************************
;*  Process state of flow rate system          
;*******************************************************************************
;
#ifdef	FLOWCONTROLDEVICE
;
ProcessMotorState:
;
MotorStateDispatcher:
;
#define S_PowerUp            0
#define S_WaitUntilClosed    1
#define S_Closed             2
#define S_Automatic          3
#define S_Manual             4
;
    CLRF    PCLATU,Access
    MOVLW   HIGH(MotorStateDispatchTable) 
    MOVWF   PCLATH,Access
;
    MOVF    MotorState,W,Access
    RLCF    WREG,W,Access
    RLCF    WREG,W,Access
    ANDLW   b'00011100'
;
    ADDLW   LOW(MotorStateDispatchTable)
    BTFSC   CarryFlag
    INCF    PCLATH,Same,Access
    MOVWF   PCL,Access
;
MotorStateDispatchTable:
;
MSDT00:       
    GOTO    PowerUp
MSDT01:       
    GOTO    WaitUntilClosed
MSDT02:       
    GOTO    Closed
MSDT03:       
    GOTO    Automatic
MSDT04:       
    GOTO    Manual
MSDT05:       
    GOTO    RestartMotorState
MSDT06:       
    GOTO    RestartMotorState
MSDT07:       
    GOTO    RestartMotorState
;
RestartMotorState:
;
    MOVLW   S_PowerUp
    MOVWF   MotorState,Access
;
    GOTO    ProcessMotorState
;
PowerUp:
;
    ;When the system start the valve must be closed first
    ;We give it 300 steps to make sure it closed
    CloseValve					;Change direction to close direction
;
    MOVLW   LOW(3000)				;Add 3000 steps
    MOVWF   Steps,Access
    MOVLW   HIGH(3000)
    MOVWF   StepsH,Access
;
    MOVLW   S_WaitUntilClosed			;Go into WaitUntilClosed mode
    MOVWF   MotorState,Access
;
    GOTO    MotorStateEnd			;Exit
;
WaitUntilClosed:
;
    BTFSS   ControlFlow
    GOTO    WaitUntilClosedSteps
;
    CALL    KickStartMotorInitial		;Start the initial flow
;
    MOVLW   S_Automatic				;Go into automatic mode
    MOVWF   MotorState,Access
;
    GOTO    ClosedEnd
;
WaitUntilClosedSteps:
;
    MOVF    Steps,W,Access			;Check if steps equals zero
    IORWF   StepsH,W,Access
    BTFSS   ZeroFlag				;If not zero
    GOTO    WaitUntilClosedEnd			;Then exit
;
    ;Else
    MOVLW   0					;Clear StepsOpen
    MOVWF   StepsOpen,Access
    MOVWF   StepsOpenH,Access
;
    MOVLW   S_Closed				;Go into closed mode
    MOVWF   MotorState,Access 
;
    GOTO    WaitUntilClosedEnd			;Exit
;
WaitUntilClosedEnd:
;
    GOTO    MotorStateEnd
;
Closed:
;
    BTFSS   ControlFlow
    GOTO    Closed1
;
    CALL    KickStartMotorInitial		;Start the initial flow
;
    MOVLW   S_Automatic				;Go into automatic mode
    MOVWF   MotorState,Access
;
    GOTO    ClosedEnd
;
Closed1:
;
    BTFSS   ProcessNewPulseData
    GOTO    ClosedEnd
;
    BCF     ProcessNewPulseData
;
    MOVF    PulseProcessVariable,W,Banked
    IORWF   PulseProcessVariableH,W,Banked
;
    BTFSC   ZeroFlag
    GOTO    ClosedEnd
;
    CloseValve
;
Closed1A:
;
    MOVF    OpenKick,W,Banked			;Kick the motor open
    MOVWF   Steps,Access
    MOVF    OpenKickH,W,Banked
    MOVWF   StepsH,Access
;
    MOVF    OpenKick,W,Banked			;Verify the 2 values, in case OpenKick is currently being updated in the interrupt routine
    SUBWF   Steps,W,Access
    BTFSS   ZeroFlag
    GOTO    Closed1A
;
    MOVF    OpenKickH,W,Banked
    SUBWF   StepsH,W,Access
    BTFSS   ZeroFlag
    GOTO    Closed1A
;
ClosedEnd:
;
    GOTO    MotorStateEnd
;
Automatic:
;
    BTFSS   ControlFlow
    GOTO    Automatic_Close
;
    BTFSS   ActionType
    GOTO    Automatic1
;
Automatic_Close:
;
    CloseValve
;
    MOVLW   LOW(3000)
    MOVWF   Steps,Access
    MOVLW   HIGH(3000)
    MOVWF   StepsH,Access
;
    MOVLW   S_WaitUntilClosed
    MOVWF   MotorState,Access
;
    GOTO    AutomaticEnd
;
Automatic1:
;
    ;PulseTimer is used to check for periods of inactivity
    ;When there is no activity the device is kickstarted with a small flow
    MOVF    PulseTimer,W,Access			
    BTFSC   ZeroFlag				;If PulseTimer is not zero then continue
    ;CALL    ResetFlow				;Set the flow rate memory to zero
    CALL    KickStartMotor			;Else kickstart flow
;
AutomaticProcessFlow:
;
    ;Before we process the current state of the valve we must wait for ProcessPulsemeterTimer to clock out
    ;and we have to wait until new data is available to be processed
    MOVF    ProcessPulsemeterTimer,W,Banked	
    BTFSS   ZeroFlag				;If ProcessPulsemeterTimer is not zero
    GOTO    AutomaticProcessFlowEnd		;Then exit
;
    BTFSS   ProcessNewPulseData			;Else wait until new data to process
    GOTO    AutomaticProcessFlowEnd
;
    BCF     ProcessNewPulseData			;If new data to process then clear bit first and continue
;
    MOVLW   ProcessPulsemeterTC			;Reset ProcessPulsemeterTimer
    MOVWF   ProcessPulsemeterTimer,Banked
;
AutomaticProcessStatsEntry1:
;
    MOVF    SetPoint,W,Banked			;Get the flow process target value
    MOVWF   Main_DoubleBuffer,Banked
    MOVF    SetPointH,W,Banked
    MOVWF   Main_DoubleBufferH,Banked
;
    MOVF    SetPoint,W,Banked
    SUBWF   Main_DoubleBuffer,W,Banked
    BTFSS   ZeroFlag
    GOTO    AutomaticProcessStatsEntry1
;
    MOVF    SetPointH,W,Banked
    SUBWF   Main_DoubleBufferH,W,Banked
    BTFSS   ZeroFlag
    GOTO    AutomaticProcessStatsEntry1
;
    MOVF    Main_DoubleBuffer,W,Banked		;Get the flow process target value
    SUBWF   PulseProcessVariable,W,Banked	;subtract the real flow rate
    MOVWF   SetError,Banked			;to get the error
    MOVF    Main_DoubleBufferH,W,Banked
    SUBWFB  PulseProcessVariableH,W,Banked
    MOVWF   SetErrorH,Banked
;
    BTFSS   CarryFlag				;If the error is positive
    GOTO    AutomaticProcessFlowOpen		;Then open the valve up more
    GOTO    AutomaticProcessFlowClose		;Else close the valve more
;
AutomaticProcessFlowOpen:
;
    SkipIfValveOpen				;Set the direction and clear Integral if direction changed
    CLRF    Integral,Banked
    OpenValve
;
    GOTO    AutomaticProcessSetError
;
AutomaticProcessFlowClose:
;
    SkipIfValveClosed				;Set the direction and clear Integral if direction changed
    CLRF    Integral,Banked
    CloseValve
;
    GOTO    AutomaticProcessSetError
;
AutomaticProcessSetError:
;
    MOVFF   SetError,SetErrorOut		;Move SetError to SetErrorOut
    MOVFF   SetErrorH,SetErrorOutH
;
    MOVF    SetErrorOut,W,Banked
    IORWF   SetErrorOutH,W,Banked
    BTFSC   ZeroFlag				;If error is zero
    GOTO    AutomaticProcessFlowReset		;Then GOTO AutomaticProcessFlowReset
;
    BTFSC   CarryFlag				;If the error is negative
    GOTO    AutomaticProcessSetError1		;Then GOTO AutomaticProcessSetError1
;
    COMF    SetErrorOut,Same,Banked		;Else do ones complement on value to get positive number
    COMF    SetErrorOutH,Same,Banked
    MOVLW   1
    ADDWF   SetErrorOut,Same,Banked
    MOVLW   0
    ADDWFC  SetErrorOutH,Same,Banked
;
AutomaticProcessSetError1:
;
    MOVLW   LOW(d'400') ;100			;We will use a max of 400 for now
    SUBWF   SetErrorOut,W,Banked		;Subtract the SetErrorOut value
    MOVLW   HIGH(d'400')
    SUBWFB  SetErrorOutH,W,Banked
;
    BTFSS   CarryFlag				;If 400 bigger than SetErrorOut then skip
    GOTO    AutomaticProcessSetError3		;Else GOTO AutomaticProcessSetError3
;
    INCF    Integral,Same,Banked		;Increase Integral by 1
    MOVLW   d'50'				;If Integral bigger than 50
    SUBWF   Integral,W,Banked
    MOVLW   d'50'
    BTFSC   CarryFlag    
    MOVWF   Integral,Banked			;Set Integral to maximum of 50
;
    GOTO    AutomaticProcessSetError3a		;Else just continue
;
AutomaticProcessSetError3:
;
    CLRF    Integral,Banked			;Set integral to 0

AutomaticProcessSetError3a:
;
    ;Here the Error is translated to steps
#define MotorFactor 2
#define IncludeIntegral
;
    MOVLW   LOW(d'2400')
    SUBWF   SetErrorOut,W,Banked
    MOVLW   HIGH(d'2400')
    SUBWFB  SetErrorOutH,W,Banked
;
    BTFSS   CarryFlag				;If SetErrorOut bigger than 2400
    GOTO    AutomaticProcessSetError4		;Then continue
;
    MOVLW   LOW(d'64'*MotorFactor) ;250		;Else set SetErrorOut to 250
    MOVWF   SetErrorOut,Banked
    MOVLW   HIGH(d'64'*MotorFactor)
    MOVWF   SetErrorOutH,Banked
;
    GOTO    AutomaticProcessSetErrorApply	;Goto AutomaticProcessSetErrorApply
;
AutomaticProcessSetError4:
;
    MOVLW   LOW(d'1600')
    SUBWF   SetErrorOut,W,Banked
    MOVLW   HIGH(d'1600')
    SUBWFB  SetErrorOutH,W,Banked
;
    BTFSS   CarryFlag				;If SetErrorOut bigger than 1600
    GOTO    AutomaticProcessSetError5		;Then continue
;
    MOVLW   LOW(d'32'*MotorFactor) ;125		;Else set SetErrorOut to 125
    MOVWF   SetErrorOut,Banked
    MOVLW   HIGH(d'32'*MotorFactor)
    MOVWF   SetErrorOutH,Banked
;
    GOTO    AutomaticProcessSetErrorApply	;Goto AutomaticProcessSetErrorApply
;
AutomaticProcessSetError5:
;
    MOVLW   LOW(d'800') ;800
    SUBWF   SetErrorOut,W,Banked
    MOVLW   HIGH(d'800')
    SUBWFB  SetErrorOutH,W,Banked
;
    BTFSS   CarryFlag				;If SetErrorOut bigger than 800
    GOTO    AutomaticProcessSetError6		;Then continue
;
    MOVLW   LOW(d'16'*MotorFactor) ;64		;Else set SetErrorOut to 64
    MOVWF   SetErrorOut,Banked
    MOVLW   HIGH(d'16'*MotorFactor)
    MOVWF   SetErrorOutH,Banked
;
    GOTO    AutomaticProcessSetErrorApply	;Goto AutomaticProcessSetErrorApply
;
AutomaticProcessSetError6:
;
    MOVLW   LOW(d'400') ;400
    SUBWF   SetErrorOut,W,Banked
    MOVLW   HIGH(d'400')
    SUBWFB  SetErrorOutH,W,Banked
;
    BTFSS   CarryFlag
    GOTO    AutomaticProcessSetError7
;
    MOVLW   LOW(d'8'*MotorFactor) ;16
    MOVWF   SetErrorOut,Banked
    MOVLW   HIGH(d'8'*MotorFactor)
    MOVWF   SetErrorOutH,Banked
;
    GOTO    AutomaticProcessSetErrorApply
;
AutomaticProcessSetError7:
;
    MOVLW   LOW(d'200') ;100
    SUBWF   SetErrorOut,W,Banked
    MOVLW   HIGH(d'200')
    SUBWFB  SetErrorOutH,W,Banked
;
    BTFSS   CarryFlag
    GOTO    AutomaticProcessSetError8
;
    MOVLW   LOW(4*MotorFactor)			;Was 4
    MOVWF   SetErrorOut,Banked
    MOVLW   HIGH(4*MotorFactor)
    MOVWF   SetErrorOutH,Banked
;
    GOTO    AutomaticProcessSetErrorApply
;
AutomaticProcessSetError8:
;
    MOVLW   LOW(d'100') ;50
    SUBWF   SetErrorOut,W,Banked
    MOVLW   HIGH(d'100')
    SUBWFB  SetErrorOutH,W,Banked
;
    BTFSS   CarryFlag
    GOTO    AutomaticProcessSetError9
;
    MOVLW   LOW(2*MotorFactor)			;Was 2
    MOVWF   SetErrorOut,Banked
    MOVLW   HIGH(2*MotorFactor)
    MOVWF   SetErrorOutH,Banked
;
    GOTO    AutomaticProcessSetErrorApply
;
AutomaticProcessSetError9:
;
    MOVLW   LOW(d'10') ;50
    SUBWF   SetErrorOut,W,Banked
    MOVLW   HIGH(d'10')
    SUBWFB  SetErrorOutH,W,Banked
;
    BTFSS   CarryFlag
    GOTO    AutomaticProcessSetError10
;
    MOVLW   LOW(1*MotorFactor)			;Was 2
    MOVWF   SetErrorOut,Banked
    MOVLW   HIGH(1*MotorFactor)
    MOVWF   SetErrorOutH,Banked
;
    GOTO    AutomaticProcessSetErrorApply
;
AutomaticProcessSetError10:
;
    MOVLW   LOW(1)
    MOVWF   SetErrorOut,Banked
    MOVLW   HIGH(1)
    MOVWF   SetErrorOutH,Banked
;
    GOTO    AutomaticProcessSetErrorApply
;             
AutomaticProcessSetErrorApply:
;
    IFDEF	IncludeIntegral    
;
    MOVF    Integral,W,Banked
    ADDWF   SetErrorOut,Same,Banked
    MOVLW   0
    ADDWFC  SetErrorOutH,Same,Banked
;
    ENDIF
;
    SkipIfValveClosed
    GOTO    AutomaticProcessSetErrorApplyA
;
    BCF	    CarryFlag
;
    MOVFF   SetErrorOut,Steps			;Move SetErrorOut to Steps
    MOVFF   SetErrorOutH,StepsH
;
    GOTO    AutomaticProcessSetErrorApply1     
;
AutomaticProcessSetErrorApplyA:
;
    MOVF    SetErrorOut,W,Banked		;If still steps to process then subtract those steps
    SUBWF   Steps,W,Access
    MOVF    SetErrorOutH,W,Banked
    SUBWFB  StepsH,W,Access   
;
    MOVFF   SetErrorOut,Steps			;Move SetErrorOut to Steps
    MOVFF   SetErrorOutH,StepsH
;
AutomaticProcessSetErrorApply1:
;
    GOTO    AutomaticProcessFlowEnd
;
AutomaticProcessFlowReset:
;
    CLRF    Integral,Banked
;    
AutomaticProcessFlowEnd:
;
AutomaticEnd:
;
    GOTO    MotorStateEnd
;
    MOVLW   d'12'
    ADDWF   DisplayMode,W,Banked
    BTFSC   CarryFlag
    MOVWF   DisplayMode,Banked
;
Manual:
;
; There is nothing to do here :-)
;
    GOTO    MotorStateEnd
;
MotorStateEnd:
;
    RETURN
;
ProcessPressureMove:
;
    MOVFF   AnalogueL,WREG			;Subtract Current Pressure from Target Pressure
    SUBWF   PressureTargetL,W,Banked		;
    BTFSS   CarryFlag				;Check if Positive
    GOTO    PressureOpen			;Pressure open
;
PressureClose:
;
    COMF    WREG,W,Access			;Get two's complement (Change to positive number)
    INCF    WREG,W,Access
;
    MOVWF   Steps,Access			;Move to steps
    CALL    Call_closeValve			;Direction to open
    GOTO    PressureMoveExit			;Exit
;
PressureOpen:
;
    SUBLW   0x03				;Subtract 3 from current value
    BTFSC   CarryFlag				;If value smaller than 3
    GOTO    PressureMoveExit			;Then exit
;
    MOVWF   Steps,Access			;Else move to steps
    CALL    Call_openValve			;Direction to open
;
PressureMoveExit:
;
    RETURN
;
#endif
;
;*******************************************************************************
;*
;*  RPM
;*
;*******************************************************************************
;
#ifdef	PULSEWIDTH_MOD
;
ProcessPWM:
;
    BTFSS   _ProcessPWM				;Check for new data
    GOTO    ProcessPWMEnd			;If no new data then exit
;
    BCF	    _ProcessPWM				;Else start by clearing new data bit
;
    CLRF    CalculatorP2,Access
;
    MOVF    RPM_SP,W,Banked			;RPM target
    SUBWF   RPM_PV,W,Banked			;current rpm
    MOVWF   RPM_Error,Banked			;error
;
    MOVF    RPMH_SP,W,Banked			;DO the same for high bytes
    SUBWFB  RPMH_PV,W,Banked
    MOVWF   RPMH_Error,Banked
;
    BTFSS   CarryFlag				;depending if the error is bigger than zero or smaller than zero
    GOTO    ProcessPWMIncrement			;Increase RPM
    GOTO    ProcessPWMDecrement			;Decrease RPM
;
ProcessPWMIncrement:
;
; We used to manipulate the voltage here, but now we need to manipulate the RPM directly
;
    COMF    RPM_Error,Same,Banked		;Get the complement of the error (go from negative to positive)
    COMF    RPMH_Error,Same,Banked
    MOVLW   1
    ADDWF   RPM_Error,Same,Banked
    MOVLW   0
    ADDWFC  RPMH_Error,Same,Banked
;
    MOVFF   RPM_Error,CalculatorP0
    MOVFF   RPMH_Error,CalculatorP1
;
    CALL    ScaleError				;Scale the error from RPM
;
; Manipulate the PWM here directly
;
    MOVF    RPM_Error,W,Banked			;Add the error to the PWM_OutR variable
    ADDWF   PWM_OutR,Same,Banked		;This will adjust the the RPM to its new output
    MOVF    RPMH_Error,W,Banked
    ADDWFC  PWM_OutRH,Same,Banked
;
    MOVLW   LOW(d'180')				;If PWM_Out bigger than 180 then set at maximum of 180
    SUBWF   PWM_OutR,W,Banked
    MOVLW   HIGH(d'180')
    SUBWFB  PWM_OutRH,W,Banked
;
    BTFSS   CarryFlag				;If bigger
    GOTO    ProcessPWMUpdate1
;
    MOVLW   LOW(d'180')				;Then set to limit
    MOVWF   PWM_OutR,Banked
    MOVLW   HIGH(d'180')
    MOVWF   PWM_OutRH,Banked
;
ProcessPWMUpdate1:
;
ProcessPWMIncrementEnd:
;
    GOTO    ProcessPWMUpdate			;End the increment
;
ProcessPWMDecrement:
;
    MOVFF   RPM_Error,CalculatorP0
    MOVFF   RPMH_Error,CalculatorP1
;
    CALL    ScaleError				;Scale the error again
;
; Manipulate the PWM directly instead of the voltage
;
    MOVF    RPM_Error,W,Banked			;Update PWM_Out variable by subtracting error
    SUBWF   PWM_OutR,Same,Banked
    MOVF    RPMH_Error,W,Banked
    SUBWFB  PWM_OutRH,Same,Banked
    BTFSC   CarryFlag				;If overflow then make PWM_OutR zero
    GOTO    ProcessPWMDecrement1
;
    CLRF    PWM_OutR,Banked
    CLRF    PWM_OutRH,Banked
;
ProcessPWMDecrement1:
;
    MOVLW   LOW(d'60')				;Check if varibale bigger than 1250
    SUBWF   PWM_OutR,W,Banked
    MOVLW   HIGH(d'60')
    SUBWFB  PWM_OutRH,W,Banked
;
    BTFSC   CarryFlag				;If it is bigger then max out at 1250
    GOTO    ProcessPWMUpdate2
;
    MOVLW   LOW(d'60')
    MOVWF   PWM_OutR,Banked
    MOVLW   HIGH(d'60')
    MOVWF   PWM_OutRH,Banked
;
ProcessPWMUpdate2:
;
ProcessPWMDecrementEnd:
;
    GOTO    ProcessPWMUpdate
;
ProcessPWMUpdate:
;
    BTFSS   ControlFlow				;Check if system engaged
    GOTO    ProcessPWMUpdate_QuickStop
;
    BTFSS   KickStartFlag
    GOTO    ProcessPWMUpdate_WriteDAC
    GOTO    ProcessPWMUpdate_KickStart		;Then kick start
;
ProcessPWMUpdate_QuickStop:
;
    MOVLW   0

    MOVWF   PWM_OutR,Banked			;Else Switch the PM off
    MOVWF   PWM_OutRH,Banked
;
    BSF	    KickStartFlag
;
ProcessPWMUpdate_QuickStopEnd:
;
    GOTO    ProcessPWMUpdate_WriteDAC		
;
ProcessPWMUpdate_KickStart:
;
; RPM_SP_Old is zero
;
    BCF	    KickStartFlag
   ; MOVF    RPM_SP,W,Banked			;If new RPM still zero
   ; IORWF   RPMH_SP,W,Banked
   ; BTFSC   ZeroFlag
   ; GOTO    ProcessPWMUpdate_KickStartEnd	;Then exit
;	
; RPM_SP is non-zero
; - So make sure RPMVolltage >= 2000 rather than counting it up from 0, so that the motor starts quickly
;
 ;            MOVF      RPM_Kick,W
 ;            SUBWF     ControlVoltage,W
 ;            MOVF      RPMH_Kick,W
 ;            SUBWFB    ControlVoltageH,W   
;
 ;            BTFSC     CarryFlag
 ;            GOTO      ProcessPWMUpdate_KickStartEnd
;             
 ;            MOVF      RPM_Kick,W
 ;            MOVWF     ControlVoltage
 ;            MOVF      RPMH_Kick,W
 ;            MOVWF     ControlVoltageH
;
    MOVFF   OpenKick,CalculatorX0		;Else do a kickstart
    MOVFF   OpenKickH,CalculatorX1
    CLRF    CalculatorX2,Access
    CLRF    CalculatorX3,Access
    CLRF    CalculatorX4,Access
;
   ; MOVLW   41
   ; MOVWF   CalculatorY0,Access
   ; CLRF    CalculatorY1,Access
   ; CLRF    CalculatorY2,Access
   ; CLRF    CalculatorY3,Access
   ; CLRF    CalculatorY4,Access
;
    ;CALL    Mul40Fast 
;
    MOVFF   CalculatorX0,PWM_OutR		;New PWM_Out value
    MOVFF   CalculatorX1,PWM_OutRH
;
ProcessPWMUpdate_KickStartEnd:
;
    GOTO    ProcessPWMUpdate_WriteDAC
;
ProcessPWMUpdate_WriteDAC:
    
;
    GOTO    ProcessPWMEnd
;
    MOVF    RPM_SP, W, Banked			;Move New to Old
    MOVWF   RPM_SP_Old, Banked
    MOVF    RPMH_SP, W, Banked
    MOVWF   RPMH_SP_Old, Banked
;
    SWAPF   PWM_OutR, W, Banked			;Divide by 16	    
    ANDLW   b'00001111'
    MOVWF   CalculatorX0, Access
    SWAPF   PWM_OutRH, W, Banked
    ANDLW   b'11110000'
    IORWF   CalculatorX0, Same, Access
;
    BCF	    _TMR2IE
    MOVF    CurrentShutDown, W, Access
    IORWF   CurrentShutDownH, W, Access
;           BTFSC     ZeroFlag
    GOTO    CurrentSkip				;Goto current skip
;
    CLRF    CalculatorX0, Access
    CLRF    PWM_OutR, Banked
    CLRF    PWM_OutRH, Banked
    CLRF    PWM_Out, Banked
;
CurrentSkip:
;
    BSF	    _TMR2IE
;
; 25 = 0.25A gives a current value of             18
; 50 = 0.75A gives a current value of round about 60
; 60 = 1A                                         80
; 70 = 1.15A
; 80 = 1.35A
; 90 = 1.5A                                       120
; 120 = 2A                                        160
; 150 = 2.6A                                      190
;
    MOVFF   CalculatorX0, PWM_SP		;Update PWM_SP
; MOVLW 65
; MOVWF PWM_SP,Banked
;
ProcessPWMEnd:
;
    RETURN
;
ScaleError:
;
    MOVLW   1
    MOVWF   RPM_Error,Banked
    CLRF   RPMH_Error,Banked
    RETURN
    ;RRCF    RPMH_Error,Same,Banked		;Divide by 2
    ;RRCF    RPM_Error,Same,Banked
    ;RRCF    RPMH_Error,Same,Banked		;Divide by 2
    ;RRCF    RPM_Error,Same,Banked
    ;RRCF    RPMH_Error,Same,Banked		;Divide by 2
    ;RRCF    RPM_Error,Same,Banked
;
ScaleErrorEnd:
;
    MOVF    RPM_Error,W,Banked			;If error zero then make 1
    IORWF   RPMH_Error,W,Banked
    BTFSC   ZeroFlag
    INCF    RPM_Error,Same,Banked
;
    RETURN					;Exit
;
CalculateSP:
;
    MOVFF   TargetVolumeL,CalculatorX0
    MOVFF   TargetVolumeH,CalculatorX1
    MOVFF   TargetVolumeU,CalculatorX2
    MOVLW   0
    MOVWF   CalculatorX3,Access
    MOVWF   CalculatorX4,Access
;
    MOVWF   CalculatorY2,Access
    MOVWF   CalculatorY3,Access
    MOVWF   CalculatorY4,Access
    
    MOVFF   PumpVolumeL,CalculatorY0
    MOVFF   PumpVolumeH,CalculatorY1
;
    CALL    Div40
;
    MOVFF   CalculatorX0,RPM_SP
    MOVFF   CalculatorX1,RPMH_SP
;
    RETURN
;
#endif
;
;*******************************************************************************
;*
;*  Pulse Sensor functions
;*
;*******************************************************************************
;*  Speed Pickup
;*******************************************************************************
;
#IFDEF	PULSE_SENSOR
;
ProcessSpeedPickup:
;
ProcessSpeedPickup_Normal:
;
    BTFSS   ReadPulseSensor			;Check if it is neccesary to read sensor
    GOTO    ProcessSpeedPickupEnd		;If not then exit
;
    BCF     ReadPulseSensor			;Else start by cearing ReadPulseSensor bit
;
ProcessSpeedPickupTry:
;
    MOVFF   PulseRange,CalculatorX0		;Move PulseRange to CalculatorX
    MOVFF   PulseRangeH,CalculatorX1
;
    CALL    ReloadPulseTimer
;
    BTFSS   CalculatorX1,7,Access		;Check if Pulse Flow bigger than 0x7FFF
    GOTO    ProcessSpeedPickup1			;Else GOTO next section of code
;Then set to zero
ProcessSpeedPickupZero:
;
    MOVLW   0					;Clear CalculatorX
    MOVWF   CalculatorX0,Access
    MOVWF   CalculatorX1,Access
    CALL    ResetFlow				;Reset the stat variables also
;
ProcessSpeedPickup1:
;
    MOVFF   CalculatorX0,NewSample		;Move the CalculatorX value to NewSample
    MOVFF   CalculatorX1,NewSampleH
;
; Now average the reading from the flow meter using the filers
;
    MOVLW   FilterSize				;Filter Size we use for the median filter (number of entries)
    MOVWF   MedianCounter,Banked		
;
    LFSR    0,StatsEntry0Age			;Point FSR to StatsEntry0Age
;
    CALL    MedianFilterOrder
    CALL    AverageFilter
;
    MOVFF   CalculatorX0,PulseProcessVariable
    MOVFF   CalculatorX1,PulseProcessVariableH
;
ProcessSpeedPickupEnd:
;
    RETURN
;
ReloadPulseTimer:
;
    MOVLW   PulseTC
    MOVWF   PulseTimer,Access
;
    RETURN
;
#ENDIF
;
;
;*******************************************************************************
;*
;*  Engage Pickup
;*
;*******************************************************************************
;
#ifdef FLOWCONTROLDEVICE
;
ProcessEngage:
;
    BTFSS   ControlFlow
    GOTO    ProcessEngage_Dis
    
ProcessEngage_En:
;
    BTFSS   EngageBit
    GOTO    ProcessEngage_End
;
    BCF	    ControlFlow
    BTFSC   FCDevice
    CALL    Send_Engaged_Status
    GOTO    ProcessEngage_End
    
ProcessEngage_Dis:
;
    BTFSC   EngageBit
    GOTO    ProcessEngage_End
;
    BSF	    ControlFlow
    BTFSC   FCDevice
    CALL    Send_Engaged_Status
    GOTO    ProcessEngage_End
;
ProcessEngage_End:
;
    RETURN
;
;*******************************************************************************
;*
;*  Pressure Pickup
;*
;*******************************************************************************
;    
ProcessPressure:
;
    MOVLW   TrackADC_Pressure			;Set ADCON0 register with correct values
    CALL    ReadADC				;Wait until read complete
;
    MOVFF   ADRESH,AnalogueT			;Read digital value from
;
ProcessPressure_Top:
;
    MOVLW   d'227'				;Check if reading bigger than 205
    SUBWF   AnalogueT,W,Banked
    BTFSS   CarryFlag
    GOTO    ProcessPressure_Bottom		;If not then continue
;
    MOVLW   LOW(d'500')
    MOVWF   AnalogueL,Banked
    MOVLW   HIGH(d'500')
    MOVWF   AnalogueH,Banked
;
    GOTO    ProcessPressure_End
;
ProcessPressure_Bottom:
;
    MOVLW   d'25'				;Check if reading smaller than 25
    SUBWF   AnalogueT,W,Banked
    BTFSC   CarryFlag
    GOTO    ProcessPressure_Mid			;If not then continue
;
    MOVLW   LOW(d'20')
    MOVWF   AnalogueL,Banked
    MOVLW   HIGH(d'20')
    MOVWF   AnalogueH,Banked
;
    GOTO    ProcessPressure_End
;
ProcessPressure_Mid:
;
    MOVLW   d'25'				;Subtract 25 from Value
    SUBWF   AnalogueT,W,Banked			
    CLRF    AnalogueH,Banked			;AnalogueH to Zero
    MOVWF   AnalogueL,Banked			;Get current pressure
    RLCF    AnalogueL,Same,Banked		;Pressure times 2
    BTFSC   CarryFlag
    INCF    AnalogueH,Same,Banked		;If carry then inc AnalogueH
;
    MOVFF   AnalogueT,WREG			;Move AnalogueT to working register
    RRCF    WREG,Same,Access			;Pressure devide by 2
    ADDWF   AnalogueL,Same,Banked		;Add this pressure to rest of pressure
    BTFSC   CarryFlag
    INCF    AnalogueH,Same,Banked		;If carry then inc AnalogueH
    ;Now the Pressure is a value between 0 and 510 (0.0 Bar - 5.0 Bar)
;
ProcessPressure_End:
;
    RETURN
;
#endif
;
;*******************************************************************************
;*
;*  Granular Control
;*
;*******************************************************************************
;
#ifdef	GRANCONTROLDEVICE
;
;*******************************************************************************
;*  Granular Control Init
;*******************************************************************************
;
GranControl_init:
;
    RETURN					;Exit
;
;*******************************************************************************
;*  Granular Control Main
;*******************************************************************************
;
;Everytime the flow sensor signal goes high there is an interrupt which coppies the current time in Timer 3.
;The result is then processed in the ProcessPulseSensor line of code
GranControl:
;
; Read the loadcell
;
    btfsc     HX711_Data
    goto      GranControl_Exit
;
    btfsc     HX711_Data2
    goto      GranControl_Exit
;
    movlw     24
    movwf     CalculatorCount,Access
;
ReadLoadCell:
;
; Interrupts off, so the HX711 doesn't go to sleep because of a long clock pulse 
;
    bcf       _GIEH
;
    bsf       HX711_Clock
;
; Make space for next bit
;
    rlcf      LoadCellA,Same,Access
    rlcf      LoadCellAH,Same,Access
    rlcf      LoadCellAHH,Same,Access
;
    rlcf      LoadCellB,Same,Access
    rlcf      LoadCellBH,Same,Access
    rlcf      LoadCellBHH,Same,Access
;
    bcf       HX711_Clock
;
; Put the interrupts back on now that we have taken our reading
;
    bsf       _GIEH
;
; Copy bit into the space we made for it
;
    bcf       LoadCellA,0,Access
    btfsc     HX711_Data
    bsf       LoadCellA,0,Access
;
    bcf       LoadCellB,0,Access
    btfsc     HX711_Data2
    bsf       LoadCellB,0,Access
;
    decfsz    CalculatorCount,Same,Access
    goto      ReadLoadCell
;
; Select the channel and the gain for the next sample - Channel A 128
;
; Interrupts off, so the HX711 doesn't go to sleep because of a long clock pulse 
;
    bcf       _GIEH
;
    bsf       HX711_Clock
;
    nop
    nop
    nop
    nop
;
    bcf       HX711_Clock
;
    nop
    nop
    nop
    nop
;
; Put the interrupts back on now that we have taken our reading
;
    bsf       _GIEH
;
    call      ZeroTracking ;Treat small changes in the loadcell and electronics as drift and keep the weight zeroed
;

; Compare the new reading to the average and limit how much it can actually change by
; Let's make it not more than double or less than half, except if the average is 0
;
LimitLoadCellA:
;
    bcf       CarryFlag
;
    movff     LoadCellAAverage,CalculatorX0
    movff     LoadCellAAverageH,CalculatorX1
    movff     LoadCellAAverageHH,CalculatorX2

    rlcf      CalculatorX0,Same,Access ;Multiply the average by 2 to get the higher range
    rlcf      CalculatorX1,Same,Access
    rlcf      CalculatorX2,Same,Access
;
    btfss     CarryFlag
    goto      LimitLoadCellA0 
;
    movlw     0xFF
    movwf     CalculatorX0,Access
    movwf     CalculatorX1,Access
    movwf     CalculatorX2,Access
;
LimitLoadCellA0:
;
    bcf       CarryFlag
;
    movff     LoadCellAAverage,CalculatorY0
    movff     LoadCellAAverageH,CalculatorY1
    movff     LoadCellAAverageHH,CalculatorY2
;
    rrcf      CalculatorY2,Same,Access ;Divide the average by 2 to get the lower range
    movwf     CalculatorY1,Access
    movwf     CalculatorY0,Access
;
    movf      CalculatorY0,W,Access
    subwf     CalculatorX0,W,Access
    movwf     CalculatorTA0,Access
;
    movf      CalculatorY1,W,Access
    subwfb    CalculatorX1,W,Access
    movwf     CalculatorTA1,Access
;
    movf      CalculatorY2,W,Access
    subwfb    CalculatorX2,W,Access
    movwf     CalculatorTA2,Access
;
; Double cannot be more than what we can fit in 24-bits
;
    movlw     LOW(0x1000000)
    subwf     CalculatorTA0,W,Access
    movlw     HIGH(0x1000000)
    subwfb    CalculatorTA1,W,Access
    movlw     UPPER(0x1000000)
    subwfb    CalculatorTA2,W,Access
;
    btfsc     CarryFlag
    goto      LimitLoadCellA1
;
    movlw     LOW(0x1000000)
    addwf     CalculatorX0,Same,Access
    movlw     HIGH(0x1000000)
    addwfc    CalculatorX1,Same,Access
    movlw     UPPER(0x1000000)
    addwfc    CalculatorX2,Same,Access
;
LimitLoadCellA1:
;
    movf      LoadCellA,W,Access
    subwf     CalculatorX0,W,Access
    movf      LoadCellAH,W,Access
    subwfb    CalculatorX1,W,Access
    movf      LoadCellAHH,W,Access
    subwfb    CalculatorX2,W,Access
;
    btfsc     CarryFlag
    goto      LimitLoadCellA2
;
    movff     CalculatorX0,LoadCellA
    movff     CalculatorX1,LoadCellAH
    movff     CalculatorX2,LoadCellAHH            
;
LimitLoadCellA2:
;
    movf      CalculatorY0,W,Access
    subwf     LoadCellA,W,Access
    movf      CalculatorY1,W,Access
    subwfb    LoadCellAH,W,Access
    movf      CalculatorY2,W,Access
    subwfb    LoadCellAHH,W,Access
;
    btfsc     CarryFlag
    goto      LimitLoadCellA3
;
    movff     CalculatorY0,LoadCellA
    movff     CalculatorY1,LoadCellAH
    movff     CalculatorY2,LoadCellAHH
;
LimitLoadCellA3:
;
LimitLoadCellB:
    bcf       CarryFlag
;
    movff     LoadCellBAverage,CalculatorX0
    movff     LoadCellBAverageH,CalculatorX1
    movff     LoadCellBAverageHH,CalculatorX2

    rlcf      CalculatorX0,Same,Access ;Multiply the average by 2 to get the higher range
    rlcf      CalculatorX1,Same,Access
    rlcf      CalculatorX2,Same,Access
;
    btfss     CarryFlag
    goto      LimitLoadCellB0 
;
    movlw     0xFF
    movwf     CalculatorX0,Access
    movwf     CalculatorX1,Access
    movwf     CalculatorX2,Access
;
LimitLoadCellB0:
;
    bcf       CarryFlag
;
    movff     LoadCellBAverage,CalculatorY0
    movff     LoadCellBAverageH,CalculatorY1
    movff     LoadCellBAverageHH,CalculatorY2
;
    rrcf      CalculatorY2,Same,Access ;Divide the average by 2 to get the lower range
    movwf     CalculatorY1,Access
    movwf     CalculatorY0,Access
;
    movf      CalculatorY0,W,Access
    subwf     CalculatorX0,W,Access
    movwf     CalculatorTA0,Access
;
    movf      CalculatorY1,W,Access
    subwfb    CalculatorX1,W,Access
    movwf     CalculatorTA1,Access
;
    movf      CalculatorY2,W,Access
    subwfb    CalculatorX2,W,Access
    movwf     CalculatorTA2,Access
;
; Double cannot be more than what we can fit in 24-bits
;
    movlw     LOW(0x1000000)
    subwf     CalculatorTA0,W,Access
    movlw     HIGH(0x1000000)
    subwfb    CalculatorTA1,W,Access
    movlw     UPPER(0x1000000)
    subwfb    CalculatorTA2,W,Access
;
    btfsc     CarryFlag
    goto      LimitLoadCellB1
;
    movlw     LOW(0x1000000)
    addwf     CalculatorX0,Same,Access
    movlw     HIGH(0x1000000)
    addwfc    CalculatorX1,Same,Access
    movlw     UPPER(0x1000000)
    addwfc    CalculatorX2,Same,Access
;
LimitLoadCellB1:
;
    movf      LoadCellB,W,Access
    subwf     CalculatorX0,W,Access
    movf      LoadCellBH,W,Access
    subwfb    CalculatorX1,W,Access
    movf      LoadCellBHH,W,Access
    subwfb    CalculatorX2,W,Access
;
    btfsc     CarryFlag
    goto      LimitLoadCellB2
;
    movff     CalculatorX0,LoadCellB
    movff     CalculatorX1,LoadCellBH
    movff     CalculatorX2,LoadCellBHH            
;
LimitLoadCellB2:
;
    movf      CalculatorY0,W,Access
    subwf     LoadCellB,W,Access
    movf      CalculatorY1,W,Access
    subwfb    LoadCellBH,W,Access
    movf      CalculatorY2,W,Access
    subwfb    LoadCellBHH,W,Access
;
    btfsc     CarryFlag
    goto      LimitLoadCellB3
;
    movff     CalculatorY0,LoadCellB
    movff     CalculatorY1,LoadCellBH
    movff     CalculatorY2,LoadCellBHH
;
LimitLoadCellB3:
;
SkipLimit: 
;
;Perform median and average filtering on the new loadcell value
; - This a simple 3 sample median filter, intended to get rid of outlyers
;
MedianA:
;
    dcfsnz AgeA0,Same,Access
    goto UpdateA0
    dcfsnz AgeA1,Same,Access
    goto UpdateA1
;
    movlw 3
    movwf AgeA2,Access
    movff LoadCellA,LoadCellA2
    movff LoadCellAH,LoadCellA2H
    movff LoadCellAHH,LoadCellA2HH
    goto  NotOrderedA
;
UpdateA0:
    movlw 3
    movwf AgeA0,Access
    decf  AgeA1,Same,Access
    decf  AgeA2,Same,Access
    movff LoadCellA,LoadCellA0
    movff LoadCellAH,LoadCellA0H
    movff LoadCellAHH,LoadCellA0HH
    goto  NotOrderedA
;
UpdateA1:
    movlw 3
    movwf AgeA1,Access
    decf  AgeA2,Same,Access
    movff LoadCellA,LoadCellA1
    movff LoadCellAH,LoadCellA1H
    movff LoadCellAHH,LoadCellA1HH
    goto  NotOrderedA
;
NotOrderedA:
;
    bcf    Switched
;
    movff  LoadCellA1,CalculatorX0
    movff  LoadCellA1H,CalculatorX1
    movff  LoadCellA1HH,CalculatorX2
;
    movff  LoadCellA2,CalculatorY0
    movff  LoadCellA2H,CalculatorY1
    movff  LoadCellA2HH,CalculatorY2
;
    clrf   CalculatorX3,Access
    clrf   CalculatorX4,Access
    clrf   CalculatorY3,Access
    clrf   CalculatorY4,Access
;
    call   Sub40
;
    btfsc  CarryFlag
    goto   CheckA1
;
    movff  LoadCellA2,LoadCellA ;Move the values in the buffers around to sort them properly
    movff  LoadCellA2H,LoadCellAH
    movff  LoadCellA2HH,LoadCellAHH
;
    movff  LoadCellA1,LoadCellA2
    movff  LoadCellA1H,LoadCellA2H
    movff  LoadCellA1HH,LoadCellA2HH
;
    movff  LoadCellA,LoadCellA1
    movff  LoadCellAH,LoadCellA1H
    movff  LoadCellAHH,LoadCellA1HH
;
    movff  AgeA2,LoadCellA  ;???
    movff  AgeA1,AgeA2
    movff  LoadCellA,AgeA1
;
    bsf    Switched
;
CheckA1:
;
    movff  LoadCellA0,CalculatorX0
    movff  LoadCellA0H,CalculatorX1
    movff  LoadCellA0HH,CalculatorX2
;
    movff  LoadCellA1,CalculatorY0
    movff  LoadCellA1H,CalculatorY1
    movff  LoadCellA1HH,CalculatorY2
;
    clrf   CalculatorX3,Access
    clrf   CalculatorX4,Access
    clrf   CalculatorY3,Access
    clrf   CalculatorY4,Access
;
    call   Sub40
;
    btfsc  CarryFlag
    goto   CheckA2
;
    movff  LoadCellA1,LoadCellA ;Move the values in the buffers around to sort them properly
    movff  LoadCellA1H,LoadCellAH
    movff  LoadCellA1HH,LoadCellAHH
;
    movff  LoadCellA0,LoadCellA1
    movff  LoadCellA0H,LoadCellA1H
    movff  LoadCellA0HH,LoadCellA1HH
;
    movff  LoadCellA,LoadCellA0
    movff  LoadCellAH,LoadCellA0H
    movff  LoadCellAHH,LoadCellA0HH
;
    movff  AgeA1,LoadCellA
    movff  AgeA0,AgeA1
    movff  LoadCellA,AgeA0
;
    bsf    Switched
;
CheckA2:
;
    btfsc   Switched
    goto    NotOrderedA
;
    movff LoadCellA1,LoadCellA        ;Replace the loadcell reading with the median filter output 
    movff LoadCellA1H,LoadCellAH
    movff LoadCellA1HH,LoadCellAHH
;
    movff LoadCellAAverage,CalculatorX0
    movff LoadCellAAverageH,CalculatorX1
    movff LoadCellAAverageHH,CalculatorX2
    clrf  CalculatorX3,Access
    clrf  CalculatorX4,Access
;
    movlw LOW(7)
    movwf CalculatorY0,Access
    movlw HIGH(7)
    movwf CalculatorY1,Access
    movlw UPPER(7)
    movwf CalculatorY2,Access
    clrf  CalculatorY3,Access
    clrf  CalculatorY4,Access
;
    call  Mul40
;
    movff LoadCellA1,CalculatorY0
    movff LoadCellA1H,CalculatorY1
    movff LoadCellA1HH,CalculatorY2
    clrf  CalculatorY3,Access
    clrf  CalculatorY4,Access
;
    call  Add40
;
    movlw LOW(8)
    movwf CalculatorY0,Access
    movlw HIGH(8)
    movwf CalculatorY1,Access
    movlw UPPER(8)
    movwf CalculatorY2,Access
    clrf  CalculatorY3,Access
    clrf  CalculatorY4,Access
;
    call  Div40              
;
    movff CalculatorX0,LoadCellAAverage
    movff CalculatorX1,LoadCellAAverageH
    movff CalculatorX2,LoadCellAAverageHH
;
;Perform median and average filtering on the new loadcell value
; - This a simple 3 sample median filter, intended to get rid of outlyers
;
MedianB:
;
    dcfsnz AgeB0,Same,Access
    goto UpdateB0
    dcfsnz AgeB1,Same,Access
    goto UpdateB1
;
    movlw 3
    movwf AgeB2,Access
    movff LoadCellB,LoadCellB2
    movff LoadCellBH,LoadCellB2H
    movff LoadCellBHH,LoadCellB2HH
    goto  NotOrderedB
;
UpdateB0:
    movlw 3
    movwf AgeB0,Access
    decf  AgeB1,Same,Access
    decf  AgeB2,Same,Access
    movff LoadCellB,LoadCellB0
    movff LoadCellBH,LoadCellB0H
    movff LoadCellBHH,LoadCellB0HH
    goto  NotOrderedB
;
UpdateB1:
    movlw 3
    movwf AgeB1,Access
    decf  AgeB2,Same,Access
    movff LoadCellB,LoadCellB1
    movff LoadCellBH,LoadCellB1H
    movff LoadCellBHH,LoadCellB1HH
    goto  NotOrderedB
;
NotOrderedB:
;
    bcf    Switched
;
    movff  LoadCellB1,CalculatorX0
    movff  LoadCellB1H,CalculatorX1
    movff  LoadCellB1HH,CalculatorX2
;
    movff  LoadCellB2,CalculatorY0
    movff  LoadCellB2H,CalculatorY1
    movff  LoadCellB2HH,CalculatorY2
;
    clrf   CalculatorX3,Access
    clrf   CalculatorX4,Access
    clrf   CalculatorY3,Access
    clrf   CalculatorY4,Access
;
    call   Sub40
;
    btfsc  CarryFlag
    goto   CheckB1
;
    movff  LoadCellB2,LoadCellB ;Move the values in the buffers around to sort them properly
    movff  LoadCellB2H,LoadCellBH
    movff  LoadCellB2HH,LoadCellBHH
;
    movff  LoadCellB1,LoadCellB2
    movff  LoadCellB1H,LoadCellB2H
    movff  LoadCellB1HH,LoadCellB2HH
;
    movff  LoadCellB,LoadCellB1
    movff  LoadCellBH,LoadCellB1H
    movff  LoadCellBHH,LoadCellB1HH
;
    movff  AgeB2,LoadCellB  ;???
    movff  AgeB1,AgeB2
    movff  LoadCellB,AgeB1
;
    bsf    Switched
;
CheckB1:
;
    movff  LoadCellB0,CalculatorX0
    movff  LoadCellB0H,CalculatorX1
    movff  LoadCellB0HH,CalculatorX2
;
    movff  LoadCellB1,CalculatorY0
    movff  LoadCellB1H,CalculatorY1
    movff  LoadCellB1HH,CalculatorY2
;
    clrf   CalculatorX3,Access
    clrf   CalculatorX4,Access
    clrf   CalculatorY3,Access
    clrf   CalculatorY4,Access
;
    call   Sub40
;
    btfsc  CarryFlag
    goto   CheckB2
;
    movff  LoadCellB1,LoadCellB ;Move the values in the buffers around to sort them properly
    movff  LoadCellB1H,LoadCellBH
    movff  LoadCellB1HH,LoadCellBHH
;
    movff  LoadCellB0,LoadCellB1
    movff  LoadCellB0H,LoadCellB1H
    movff  LoadCellB0HH,LoadCellB1HH
;
    movff  LoadCellB,LoadCellB0
    movff  LoadCellBH,LoadCellB0H
    movff  LoadCellBHH,LoadCellB0HH
;
    movff  AgeB1,LoadCellB
    movff  AgeB0,AgeB1
    movff  LoadCellB,AgeB0
;
    bsf    Switched
;
CheckB2:
;
    btfsc   Switched
    goto    NotOrderedB
;
    movff LoadCellB1,LoadCellB        ;Replace the loadcell reading with the median filter output 
    movff LoadCellB1H,LoadCellBH
    movff LoadCellB1HH,LoadCellBHH
;
    movff LoadCellBAverage,CalculatorX0
    movff LoadCellBAverageH,CalculatorX1
    movff LoadCellBAverageHH,CalculatorX2
    clrf  CalculatorX3,Access
    clrf  CalculatorX4,Access
;
    movlw LOW(7)
    movwf CalculatorY0,Access
    movlw HIGH(7)
    movwf CalculatorY1,Access
    movlw UPPER(7)
    movwf CalculatorY2,Access
    clrf  CalculatorY3,Access
    clrf  CalculatorY4,Access
;
    call  Mul40
;
    movff LoadCellB1,CalculatorY0
    movff LoadCellB1H,CalculatorY1
    movff LoadCellB1HH,CalculatorY2
    clrf  CalculatorY3,Access
    clrf  CalculatorY4,Access
;
    call  Add40
;
    movlw LOW(8)
    movwf CalculatorY0,Access
    movlw HIGH(8)
    movwf CalculatorY1,Access
    movlw UPPER(8)
    movwf CalculatorY2,Access
    clrf  CalculatorY3,Access
    clrf  CalculatorY4,Access
;
    call  Div40              
;
    movff CalculatorX0,LoadCellBAverage
    movff CalculatorX1,LoadCellBAverageH
    movff CalculatorX2,LoadCellBAverageHH
;
Differentiate:
;
;   Differentiate between load cells
;
  movff     LoadCellAAverage,CalculatorX0
    movff     LoadCellAAverageH,CalculatorX1
    movff     LoadCellAAverageHH,CalculatorX2
    clrf  CalculatorX3
    clrf  CalculatorX4

    movff     LoadCellBAverage,CalculatorY0
    movff     LoadCellBAverageH,CalculatorY1
    movff     LoadCellBAverageHH,CalculatorY2
    clrf  CalculatorY3
    clrf  CalculatorY4
;
    CALL Sub40

    MOVFF CalculatorX0,LoadCellCAverage
    MOVFF CalculatorX1,LoadCellCAverageH
    MOVFF CalculatorX2,LoadCellCAverageHH
;
; See if we need to refresh the load cells zero?
; - In the system the command to zero the load cells could come from the main unit instead of locally
;
UpdateZeroTrack:
;
    btfss     ZeroPointReset
    goto      SkipZero
;
    bcf       ZeroPointReset
;
    movff     LoadCellAAverage,LoadCellAZero
    movff     LoadCellAAverageH,LoadCellAZeroH
    movff     LoadCellAAverageHH,LoadCellAZeroHH
;
    movff     LoadCellBAverage,LoadCellBZero
    movff     LoadCellBAverageH,LoadCellBZeroH
    movff     LoadCellBAverageHH,LoadCellBZeroHH
;
    movff     LoadCellCAverage,LoadCellCZero
    movff     LoadCellCAverageH,LoadCellCZeroH
    movff     LoadCellCAverageHH,LoadCellCZeroHH
;
SkipZero:
;
; Perform zeroing
;
ZeroA:
; 
    movff     LoadCellAAverage,CalculatorX0
    movff     LoadCellAAverageH,CalculatorX1
    movff     LoadCellAAverageHH,CalculatorX2
;
    movff     LoadCellAZero,CalculatorY0
    movff     LoadCellAZeroH,CalculatorY1
    movff     LoadCellAZeroHH,CalculatorY2
;
    clrf      CalculatorX3,Access
    clrf      CalculatorX4,Access
    clrf      CalculatorY3,Access 
    clrf      CalculatorY4,Access
;
    call      Sub40
;
    btfsc     CarryFlag
    goto      SkipNegativeA
;
    clrf      CalculatorX0,Access
    clrf      CalculatorX1,Access
    clrf      CalculatorX2,Access
    clrf      CalculatorX3,Access
    clrf      CalculatorX4,Access
;
SkipNegativeA:
;
    MOVFF	CalculatorX0,CalculatorP0
    MOVFF	CalculatorX1,CalculatorP1
    MOVFF	CalculatorX2,CalculatorP2
;
    movff     LoadCellMul,CalculatorY0
    movff     LoadCellMulH,CalculatorY1
    clrf      CalculatorY2,Access
    clrf      CalculatorY3,Access
    clrf      CalculatorY4,Access
;
    call      Mul40Fast 
;
    movff     LoadCellDiv,CalculatorY0
    movff     LoadCellDivH,CalculatorY1
    clrf      CalculatorY2,Access
    clrf      CalculatorY3,Access
    clrf      CalculatorY4,Access
;
    call      Div40
;
    bcf       _GIEH
    ;movff     CalculatorX0,gpm
    ;movff     CalculatorX1,gpmH
    ;movff     CalculatorX2,gpmHH
    bsf       _GIEH
;
ZeroB:
; 
    movff     LoadCellB,CalculatorX0
    movff     LoadCellBH,CalculatorX1
    movff     LoadCellBHH,CalculatorX2
;
    movff     LoadCellBAverage,CalculatorY0
    movff     LoadCellBAverageH,CalculatorY1
    movff     LoadCellBAverageHH,CalculatorY2
;
    clrf      CalculatorX3,Access
    clrf      CalculatorX4,Access
    clrf      CalculatorY3,Access 
    clrf      CalculatorY4,Access
;
    call      Sub40
;
    btfsc     CarryFlag
    goto      SkipNegativeB
;
    clrf      CalculatorX0,Access
    clrf      CalculatorX1,Access
    clrf      CalculatorX2,Access
    clrf      CalculatorX3,Access
    clrf      CalculatorX4,Access
;
SkipNegativeB:
;
    movff     LoadCellMul,CalculatorY0
    movff     LoadCellMulH,CalculatorY1
    clrf      CalculatorY2,Access
    clrf      CalculatorY3,Access
    clrf      CalculatorY4,Access
;
    call      Mul40Fast 
;
    movff     LoadCellDiv,CalculatorY0
    movff     LoadCellDivH,CalculatorY1
    clrf      CalculatorY2,Access
    clrf      CalculatorY3,Access
    clrf      CalculatorY4,Access
;
    call      Div40
;
   ; movff     CalculatorX0,gpm
   ; movff     CalculatorX1,gpmH
   ; movff     CalculatorX2,gpmHH
;
ZeroC:
; 
    movff     LoadCellCAverage,CalculatorX0
    movff     LoadCellCAverageH,CalculatorX1
    movff     LoadCellCAverageHH,CalculatorX2
;
    movff     LoadCellCZero,CalculatorY0
    movff     LoadCellCZeroH,CalculatorY1
    movff     LoadCellCZeroHH,CalculatorY2
;
    clrf      CalculatorX3,Access
    clrf      CalculatorX4,Access
    clrf      CalculatorY3,Access 
    clrf      CalculatorY4,Access
;
    call      Sub40
;
    btfsc     CarryFlag
    goto      SkipNegativeC
;
    clrf      CalculatorX0,Access
    clrf      CalculatorX1,Access
    clrf      CalculatorX2,Access
    clrf      CalculatorX3,Access
    clrf      CalculatorX4,Access
;
SkipNegativeC:
;
    MOVFF	CalculatorX0,CalculatorP0
    MOVFF	CalculatorX1,CalculatorP1
    MOVFF	CalculatorX2,CalculatorP2
;
    movff     LoadCellMul,CalculatorY0
    movff     LoadCellMulH,CalculatorY1
    clrf      CalculatorY2,Access
    clrf      CalculatorY3,Access
    clrf      CalculatorY4,Access
;
    call      Mul40Fast 
;
    movff     LoadCellDiv,CalculatorY0
    movff     LoadCellDivH,CalculatorY1
    clrf      CalculatorY2,Access
    clrf      CalculatorY3,Access
    clrf      CalculatorY4,Access
;
    call      Div40
;
    bcf       _GIEH
    movff     CalculatorX0,gpm
    movff     CalculatorX1,gpmH
    movff     CalculatorX2,gpmHH
    bsf       _GIEH
;
goto      GranControl_Exit
;
; All the subroutines for the granular control main loop go here
;
ZeroTracking:
;
; See how big the difference is between the reading and the zero
; - Rather than trying to do a 2's complement calculation, if the answer is negative, just do the calculation again with the numbers the other way around
; 
    movff     LoadCellAAverage,CalculatorX0
    movff     LoadCellAAverageH,CalculatorX1
    movff     LoadCellAAverageHH,CalculatorX2
;
    movff     LoadCellAZero,CalculatorY0
    movff     LoadCellAZeroH,CalculatorY1
    movff     LoadCellAZeroHH,CalculatorY2
;
    clrf      CalculatorX3,Access
    clrf      CalculatorX4,Access
    clrf      CalculatorY3,Access
    clrf      CalculatorY4,Access
;
    call      Sub40
;
    btfsc     CarryFlag
    goto      ZeroTrackingA
;
    movff     LoadCellAZero,CalculatorX0
    movff     LoadCellAZeroH,CalculatorX1
    movff     LoadCellAZeroHH,CalculatorX2
;
    movff     LoadCellAAverage,CalculatorY0
    movff     LoadCellAAverageH,CalculatorY1
    movff     LoadCellAAverageHH,CalculatorY2
;
    clrf      CalculatorX3,Access
    clrf      CalculatorX4,Access
    clrf      CalculatorY3,Access
    clrf      CalculatorY4,Access
;
    call      Sub40
;
ZeroTrackingA:
;
; At power up, if it is within 5000 counts then make the value from the load cell the new zero
; During normal operation, if it is within 100 counts then make the value from the load cell the new zero
;
    movlw     LOW(40)
    btfsc     FirstTracking
    movlw     LOW(5000)
    subwf     CalculatorX0,W,Access
    movlw     HIGH(40)
    btfsc     FirstTracking
    movlw     HIGH(5000)
    subwfb    CalculatorX1,W,Access
    movlw     0
    subwfb    CalculatorX2,W,Access
;
    btfsc     CarryFlag
    goto      ZeroTrackingAout
;
    movff     LoadCellAAverage,LoadCellAZero
    movff     LoadCellAAverageH,LoadCellAZeroH
    movff     LoadCellAAverageHH,LoadCellAZeroHH
;
ZeroTrackingAout:
;
    movff     LoadCellBAverage,CalculatorX0
    movff     LoadCellBAverageH,CalculatorX1
    movff     LoadCellBAverageHH,CalculatorX2
;
    movff     LoadCellBZero,CalculatorY0
    movff     LoadCellBZeroH,CalculatorY1
    movff     LoadCellBZeroHH,CalculatorY2
;
    clrf      CalculatorX3,Access
    clrf      CalculatorX4,Access
    clrf      CalculatorY3,Access
    clrf      CalculatorY4,Access
;
    call      Sub40
;
    btfsc     CarryFlag
    goto      ZeroTrackingB
;
    movff     LoadCellBZero,CalculatorX0
    movff     LoadCellBZeroH,CalculatorX1
    movff     LoadCellBZeroHH,CalculatorX2
;
    movff     LoadCellBAverage,CalculatorY0
    movff     LoadCellBAverageH,CalculatorY1
    movff     LoadCellBAverageHH,CalculatorY2
;
    clrf      CalculatorX3,Access
    clrf      CalculatorX4,Access
    clrf      CalculatorY3,Access
    clrf      CalculatorY4,Access
;
    call      Sub40
;
ZeroTrackingB:
;
; At power up, if it is within 5000 counts then make the value from the load cell the new zero
; During normal operation, if it is within 100 counts then make the value from the load cell the new zero
;
    movlw     LOW(100)
    btfsc     FirstTracking
    movlw     LOW(5000)
    subwf     CalculatorX0,W,Access
    movlw     HIGH(100)
    btfsc     FirstTracking
    movlw     HIGH(5000)
    subwfb    CalculatorX1,W,Access
    movlw     0
    subwfb    CalculatorX2,W,Access
;
    btfsc     CarryFlag
    goto      ZeroTrackingBout
;
    movff     LoadCellBAverage,LoadCellBZero
    movff     LoadCellBAverageH,LoadCellBZeroH
    movff     LoadCellBAverageHH,LoadCellBZeroHH
;
ZeroTrackingBout:
;
    movff     LoadCellCAverage,CalculatorX0
    movff     LoadCellCAverageH,CalculatorX1
    movff     LoadCellCAverageHH,CalculatorX2
;
    movff     LoadCellCZero,CalculatorY0
    movff     LoadCellCZeroH,CalculatorY1
    movff     LoadCellCZeroHH,CalculatorY2
;
    clrf      CalculatorX3,Access
    clrf      CalculatorX4,Access
    clrf      CalculatorY3,Access
    clrf      CalculatorY4,Access
;
    call      Sub40
;
    btfsc     CarryFlag
    goto      ZeroTrackingC
;
    movff     LoadCellCZero,CalculatorX0
    movff     LoadCellCZeroH,CalculatorX1
    movff     LoadCellCZeroHH,CalculatorX2
;
    movff     LoadCellCAverage,CalculatorY0
    movff     LoadCellCAverageH,CalculatorY1
    movff     LoadCellCAverageHH,CalculatorY2
;
    clrf      CalculatorX3,Access
    clrf      CalculatorX4,Access
    clrf      CalculatorY3,Access
    clrf      CalculatorY4,Access
;
    call      Sub40
;
ZeroTrackingC:
;
; At power up, if it is within 5000 counts then make the value from the load cell the new zero
; During normal operation, if it is within 100 counts then make the value from the load cell the new zero
;
    movlw     LOW(20)
    btfsc     FirstTracking
    movlw     LOW(5000)
    subwf     CalculatorX0,W,Access
    movlw     HIGH(20)
    btfsc     FirstTracking
    movlw     HIGH(5000)
    subwfb    CalculatorX1,W,Access
    movlw     0
    subwfb    CalculatorX2,W,Access
;
    btfsc     CarryFlag
    goto      ZeroTrackingCout
;
    movff     LoadCellCAverage,LoadCellCZero
    movff     LoadCellCAverageH,LoadCellCZeroH
    movff     LoadCellCAverageHH,LoadCellCZeroHH
;
ZeroTrackingCout:
;
    return
;
GranControl_Exit:
;
    RETURN
;
#endif
;
;**************************************************************
;*
;*  Delay functions
;*
;**************************************************************
;
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
;
Delay10msec:
;
    MOVLW   b'11000111'
    MOVWF   T0CON,Access
    MOVLW   d'256'-d'108'
    MOVWF   TMR0L
    BCF	    _TMR0IF
;
Delay10msec1:
;
    BTFSS   _TMR0IF
    GOTO    Delay10msec1
;
    RETURN
;
Delay1msec:
;
    MOVLW   b'11000111'
    MOVWF   T0CON,Access
    MOVLW   d'256'-d'11'
    MOVWF   TMR0L
    BCF	    _TMR0IF
;
Delay2msec1:
;
    BTFSS   _TMR0IF
    GOTO    Delay2msec1
;
    RETURN
;
Delay250usec:
;
    MOVLW   b'11000001'
    MOVWF   T0CON,Access
    MOVLW   d'256'-d'3' ;6
    MOVWF   TMR0L
    BCF	    _TMR0IF
;
Delay250usec1: 
;
    BTFSS   _TMR0IF
    GOTO    Delay250usec1
;
    RETURN
;
#ifdef CALCULATOR
;*******************************************************************************
;*
;* 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
;*
;*******************************************************************************
;
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
;
;*******************************************************************************
;
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
;
;*******************************************************************************
;
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   d'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 fast multiply
;                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.
;
;*******************************************************************************
;
Mul40Fast:
;
    MOVF      CalculatorY0,W,Access ; 1
    MULWF     CalculatorX0,Access ; 2
    MOVFF     PRODL,CalculatorTA0 ; 3 4
    MOVFF     PRODH,CalculatorTA1 ; 5 6
    CLRF      CalculatorTA2,Access ;7          
    CLRF      CalculatorTA3,Access ;8          
    CLRF      CalculatorTA4,Access ;9 - 17 = -8         
;
    MOVF      CalculatorY0,W,Access ;18
    MULWF     CalculatorX1,Access ;19
    MOVF      PRODL,W,Access ;20
    ADDWF     CalculatorTA1,Same,Access ;21
    MOVF      PRODH,W,Access ;22
    ADDWFC    CalculatorTA2,Same,Access ;23
    MOVLW     0 ;24
    ADDWFC    CalculatorTA3,Same,Access ;25 trimmed 26 & 27
;
    MOVF      CalculatorY0,W,Access ;28
    MULWF     CalculatorX2,Access ;29
    MOVF      PRODL,W,Access ;30
    ADDWF     CalculatorTA2,Same,Access ;31
    MOVF      PRODH,W,Access ;32
    ADDWFC    CalculatorTA3,Same,Access ;33
    MOVLW     0 ;34
    ADDWFC    CalculatorTA4,Same,Access ;35
;
    MOVF      CalculatorY0,W,Access ;36
    MULWF     CalculatorX3,Access ;37
    MOVF      PRODL,W,Access ;38
    ADDWF     CalculatorTA3,Same,Access ;39
    MOVF      PRODH,W,Access ;40
    ADDWFC    CalculatorTA4,Same,Access ;41
;
    MOVF      CalculatorY0,W,Access ;42
    MULWF     CalculatorX4,Access ;43
    MOVF      PRODL,W,Access ;44
    ADDWF     CalculatorTA4,Same,Access ;45
;
    MOVF      CalculatorY1,W,Access ;46
    MULWF     CalculatorX0,Access ;47
    MOVF      PRODL,W,Access ;48
    ADDWF     CalculatorTA1,Same,Access ;49
    MOVF      PRODH,W,Access ;50
    ADDWFC    CalculatorTA2,Same,Access ;51
    MOVLW     0 ;52
    ADDWFC    CalculatorTA3,Same,Access ;53
    MOVLW     0 ;54
    ADDWFC    CalculatorTA4,Same,Access ;55
;
    MOVF      CalculatorY1,W,Access ;56
    MULWF     CalculatorX1,Access ;57
    MOVF      PRODL,W,Access ;58 
    ADDWF     CalculatorTA2,Same,Access ;59
    MOVF      PRODH,W,Access ;60
    ADDWFC    CalculatorTA3,Same,Access ;61
    MOVLW     0 ;62
    ADDWFC    CalculatorTA4,Same,Access ;63
;
    MOVF      CalculatorY1,W,Access ;64
    MULWF     CalculatorX2,Access ;65
    MOVF      PRODL,W,Access ;66
    ADDWF     CalculatorTA3,Same,Access ;67
    MOVF      PRODH,W,Access ;68
    ADDWFC    CalculatorTA4,Same,Access ;69
;
    MOVF      CalculatorY1,W,Access ;70
    MULWF     CalculatorX3,Access ;71
    MOVF      PRODL,W,Access ;72
    ADDWF     CalculatorTA4,Same,Access ;73
;
    MOVF      CalculatorY2,W,Access ;74
    MULWF     CalculatorX0,Access ;75
    MOVF      PRODL,W,Access ;76
    ADDWF     CalculatorTA2,Same,Access ;77
    MOVF      PRODH,W,Access ;78
    ADDWFC    CalculatorTA3,Same,Access ;79
    MOVLW     0 ;80
    ADDWFC    CalculatorTA4,Same,Access ;81
;
    MOVF      CalculatorY2,W,Access ;82
    MULWF     CalculatorX1,Access ;83
    MOVF      PRODL,W,Access ;84
    ADDWF     CalculatorTA3,Same,Access ;85
    MOVF      PRODH,W,Access ;86
    ADDWFC    CalculatorTA4,Same,Access ;87
;
    MOVF      CalculatorY2,W,Access ;88
    MULWF     CalculatorX2,Access ;89
    MOVF      PRODL,W,Access ;90
    ADDWF     CalculatorTA4,Same,Access ;91
;
    MOVF      CalculatorY3,W,Access ;92
    MULWF     CalculatorX0,Access ;93
    MOVF      PRODL,W,Access ;94
    ADDWF     CalculatorTA3,Same,Access ;95
    MOVF      PRODH,W,Access ;96
    ADDWFC    CalculatorTA4,Same,Access ;97
;
    MOVF      CalculatorY3,W,Access ;98
    MULWF     CalculatorX1,Access ;99
    MOVF      PRODL,W,Access ;100
    ADDWF     CalculatorTA4,Same,Access ;101
;             MOVF      PRODH,W,Access ;102 this instruction serves no purpose -1
;
    MOVF      CalculatorY4,W,Access ;103
    MULWF     CalculatorX0,Access ;104
    MOVF      PRODL,W,Access ;105
    ADDWF     CalculatorTA4,Same,Access ;106
;
    MOVFF     CalculatorTA0,CalculatorX0 ;107 108
    MOVFF     CalculatorTA1,CalculatorX1 ;109 110
    MOVFF     CalculatorTA2,CalculatorX2 ;111 112
    MOVFF     CalculatorTA3,CalculatorX3 ;113 114
    MOVFF     CalculatorTA4,CalculatorX4 ;115 116
;
    RETURN ;117 118 119 120 * 4 / 11059200 = 43,1usec => trimmed 120 - 10 - 1 = 109 * 4 / 11059200 = 39.5usec => saves 3.6usec which means 1 free very 11 calls
	   ;                             399/39.5 = 10.11 times faster than minimum
	   ;                             587/39.5 = 14.87 times faster than maxiumum
	   ;This routine is at least 10 times faster, but the compromise here is that the error flag is not set if it overflows, if this is a requirement,
	   ; it could be added in and still be faster than shift and rotate
;
;*******************************************************************************
;
; 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.
;
;*******************************************************************************
;
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   d'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
;
#endif
;
#ifdef	    STATISTICS
;*******************************************************************************
;*
;* TITLE..: PICSTATS - 16-bit statistics routines
;* AUTHOR.: Robert Farrer
;*
;*******************************************************************************
;
Stats_Init:
;
    MOVLW     d'1'
    MOVWF     StatsEntry0Age,Banked
    CLRF      StatsEntry0,Banked
    CLRF      StatsEntry0H,Banked
;
    MOVLW     d'2'
    MOVWF     StatsEntry1Age,Banked
    CLRF      StatsEntry1,Banked
    CLRF      StatsEntry1H,Banked
;
    MOVLW     d'3'
    MOVWF     StatsEntry2Age,Banked
    CLRF      StatsEntry2,Banked
    CLRF      StatsEntry2H,Banked
;
    MOVLW     d'4'
    MOVWF     StatsEntry3Age,Banked
    CLRF      StatsEntry3,Banked
    CLRF      StatsEntry3H,Banked
;
    MOVLW     d'5'
    MOVWF     StatsEntry4Age,Banked
    CLRF      StatsEntry4,Banked
    CLRF      StatsEntry4H,Banked
;
    MOVLW     d'6'
    MOVWF     StatsEntry5Age,Banked
    CLRF      StatsEntry5,Banked
    CLRF      StatsEntry5H,Banked
;
    MOVLW     d'7'
    MOVWF     StatsEntry6Age,Banked
    CLRF      StatsEntry6,Banked
    CLRF      StatsEntry6H,Banked
;
    MOVLW     d'8'
    MOVWF     StatsEntry7Age,Banked
    CLRF      StatsEntry7,Banked
    CLRF      StatsEntry7H,Banked
;
    MOVLW     d'9'
    MOVWF     StatsEntry8Age,Banked
    CLRF      StatsEntry8,Banked
    CLRF      StatsEntry8H,Banked
;
    MOVLW     d'10'
    MOVWF     StatsEntry9Age,Banked
    CLRF      StatsEntry9,Banked
    CLRF      StatsEntry9H,Banked    
;
    RETURN
;
;*******************************************************************************
;
; FUNCTION.....: Insert new value and order values
;
;*******************************************************************************
;
MedianFilterOrder:
;
    MOVLW   FilterSize				;Filter Size we use for the median filter (number of entries)
    MOVWF   MedianCounter,Banked		
;
    LFSR    0,StatsEntry0Age			;Point FSR to StatsEntry0Age
;
StartOrder_DecreaseAge:    
;
    ;Decrease all ages and check for oldest entry
    DECFSZ  POSTINC0,Same,Access		;Decrease FlowxAge. If 0 then continue
    GOTO    StartOrder_SkipStatEntry		;Else GOTO next filter
;
    MOVF    POSTDEC0,W,Access			;Move StatsEntry0 to WREG and point back to StatsEntry0Age
;
    MOVFF   FSR0L,MedianNewSamplePointer	;Copy current address to MedianNewSamplePointer
    MOVFF   FSR0H,MedianNewSamplePointerH
;
    ;Reset FlowxAge and then assign new value to Flowx and FlowxH
    MOVLW   FilterSize				;Move FilterSize to FlowxAge
    MOVWF   POSTINC0,Access
    MOVFF   CalculatorX0,POSTINC0		;Move CalculatorX0 to Flowx
    MOVFF   CalculatorX1,POSTINC0		;Move CalculatorX1 to FlowxH
;
    GOTO    StartOrder_NextStatEntry		;Skip next filter
;
StartOrder_SkipStatEntry:      
;
    ;Goto next FlowAge byte
    MOVF    POSTINC0,W,Access			;Dummy +1
    MOVF    POSTINC0,W,Access			;Dummy +1
;
StartOrder_NextStatEntry:      
;
    ;Do this for all items inside MedianCounter then continue with code (One should always be eliminated and replaced)
    DECFSZ  MedianCounter,Same,Banked		;If last    continue with code
    GOTO    StartOrder_DecreaseAge		;Else continue for next index  
;
    MOVFF   MedianNewSamplePointer,FSR0L	;First move the MedianNewSample Pointer back into FSR0L and FSR0H
    MOVFF   MedianNewSamplePointerH,FSR0H 
;
; This documentation was added afterwards, so hopefully there are no discrepancies:
; - Smaller, (lighter?), values float to the top
; - Larger, (heavier?), values sink to the bottom
; - A new value added right at the top can only potentially sink
; - A new value added right at the bottom can only potentially float
; - Values added elsewhere in the list must be tested to see whether they must sink or float
; - Because the list is ordered only 1 pass is required in order to correctly insert the new value into the list
;
; See if the new sample is right at the top or right at the bottom
;
    MOVLW   LOW(StatsEntry0Age)			;Put StatsEntry0Age low address into W
    SUBWF   FSR0L,W,Access			;Subtract current FSR addres
    BTFSS   ZeroFlag				;If match 
    GOTO    StartOrder_CheckMedianFloat		;Then test high byte, else GOTO next test
    ;Else test for highest register
;
    MOVLW   HIGH(StatsEntry0Age)		;Put StatsEntry0Age high address into W
    SUBWFB  FSR0H,W,Access			;Subtract current FSR addres
    BTFSC   ZeroFlag				;If match
    GOTO    MedianSink				;Then continue to median sink procedure, else GOTO next test
;
StartOrder_CheckMedianFloat:
;
    MOVLW   LOW(StatsEntry0Age+((FilterSize-1)*3))	;Put last FlowxAge low address into W
    SUBWF   FSR0L,W,Access			;Subtract current FSR addres
    BTFSS   ZeroFlag				;If match 
    GOTO    StartOrder_SampleMiddle		;Then test high byte, else GOTO next test
;
    MOVLW   HIGH(StatsEntry0Age+((FilterSize-1)*3))	;Put last FlowxAge high address into W
    SUBWFB  FSR0H,W,Access			;Subtract current FSR addres
    BTFSC   ZeroFlag				;If match 
    GOTO    MedianFloat				;Then continue to median float procedure, else GOTO next test
;
StartOrder_SampleMiddle:
;      
; 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		;Test to see if it is bigger or smaller
    SUBWF   POSTINC0,W,Access
    MOVF    CalculatorX1,W,Access
    SUBWFB  POSTINC0,W,Access
    BTFSS   CarryFlag				;If new value is bigger than next value
    GOTO    MedianSink				;Then the value needs to go down
;              
    MOVLW   8					;Point to next lower sample (8 registers back)
    SUBWF   FSR0L,Same,Access
    MOVLW   0
    SUBWFB  FSR0H,Same,Access
;
    MOVF    POSTINC0,W,Access			;Check that it is lower than the new one
    SUBWF   CalculatorX0,W,Access
    MOVF    POSTINC0,W,Access
    SUBWFB  CalculatorX1,W,Access
    BTFSS   CarryFlag				;If new value is smaller than previous value
    GOTO    MedianFloat				;Then the value needs to go up
;
    GOTO    MedianEnd				;It is in the right place, so we don't need to do anything!
						;- I wonder how often we get this lucky in reality?
;
MedianSink:
;
    MOVFF   MedianNewSamplePointer,FSR0L	;Move pointer of new value to FSR0 and FSR1
    MOVFF   MedianNewSamplePointerH,FSR0H 
    MOVFF   MedianNewSamplePointer,FSR1L
    MOVFF   MedianNewSamplePointerH,FSR1H 
;
MedianSink1:
;
    MOVLW   LOW(StatsEntry0Age+((FilterSize-1)*3)); See if the new sample is right at the bottom
    SUBWF   FSR0L,W,Access
    BTFSS   ZeroFlag
    GOTO    MedianSink2
;
    MOVLW   HIGH(StatsEntry0Age+((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			;If the next higher sample is higher than this one, then we have sunk as far as we can sink
;
    MOVFF   POSTDEC0,MedianTempH		;Otherwise swap these 2 samples and test again  
    MOVFF   POSTDEC0,MedianTemp			;Move to temp
    MOVFF   INDF0,MedianTempAge
    MOVFF   POSTINC1,POSTINC0			;Replace
    MOVFF   POSTINC1,POSTINC0
    MOVFF   INDF1,INDF0
    MOVFF   MedianTempH,POSTDEC1		;Move from temp
    MOVFF   MedianTemp,POSTDEC1
    MOVFF   MedianTempAge,POSTINC1
    MOVF    POSTINC1,W,Access			;Move pointers to correct addresses
    MOVF    POSTINC1,W,Access
    MOVF    POSTDEC0,W,Access
    MOVF    POSTDEC0,W,Access
;             
    GOTO    MedianSink1
;
MedianSinkEnd:
;
    GOTO    MedianEnd
;
MedianFloat:
;
    MOVFF   MedianNewSamplePointer,FSR0L	;Move pointer of new value to FSR0 and FSR1
    MOVFF   MedianNewSamplePointerH,FSR0H 
    MOVFF   MedianNewSamplePointer,FSR1L
    MOVFF   MedianNewSamplePointerH,FSR1H 
;
MedianFloat1:
;
    MOVLW   LOW(StatsEntry0Age)			;See if the new sample is right at the bottom
    SUBWF   FSR0L,W,Access
    BTFSS   ZeroFlag
    GOTO    MedianFloat2  
;
    MOVLW   HIGH(StatsEntry0Age)
    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			;If the next lower sample is lower than this one, then we have floated as far as we can float
;
    MOVFF   POSTDEC0,MedianTempH		;Otherwise swap these 2 samples and test again
    MOVFF   POSTDEC0,MedianTemp			;Move to temp
    MOVFF   INDF0,MedianTempAge
    MOVFF   POSTINC1,POSTINC0			;Replace
    MOVFF   POSTINC1,POSTINC0
    MOVFF   INDF1,INDF0
    MOVFF   MedianTempH,POSTDEC1		;Move from temp
    MOVFF   MedianTemp,POSTDEC1
    MOVFF   MedianTempAge,POSTDEC1
    MOVF    POSTDEC1,W,Access			;Move pointers to correct addresses
    MOVF    POSTDEC1,W,Access
    MOVF    POSTDEC0,W,Access
    MOVF    POSTDEC0,W,Access
;             
    GOTO    MedianFloat1
;
MedianFloatEnd:
;
MedianEnd:
;
    RETURN
;
AverageFilter:
;
#ifdef  FLOWCONTROLDEVICE       
    MOVLW   S_WaitUntilClosed			;Move WaitUntilClosed constant to WREG
    XORWF   MotorState,W,Access			;Check if mainstate in closed mode
    BTFSC   ZeroFlag				;If system closed
    GOTO    AverageFilter_clear
;
AverageFilter_tryClosed:
;
    MOVLW   S_Closed				;Move Closed constant to WREG
    XORWF   MotorState,W,Access			;Check if mainstate in closed mode
    BTFSS   ZeroFlag				;If system closed
    GOTO    AverageFilter_moveup
;   
AverageFilter_clear:
;
    CLRF    StatsEntryA9,Banked			;Clear all Entries to cause a fast reset
    CLRF    StatsEntryA9H,Banked			 
    CLRF    StatsEntryA8,Banked				
    CLRF    StatsEntryA8H,Banked			 
    CLRF    StatsEntryA7,Banked				
    CLRF    StatsEntryA7H,Banked			 
    CLRF    StatsEntryA6,Banked				
    CLRF    StatsEntryA6H,Banked			 
    CLRF    StatsEntryA5,Banked				
    CLRF    StatsEntryA5H,Banked			 
    CLRF    StatsEntryA4,Banked				
    CLRF    StatsEntryA4H,Banked			 
    CLRF    StatsEntryA3,Banked				
    CLRF    StatsEntryA3H,Banked			 
    CLRF    StatsEntryA2,Banked				
    CLRF    StatsEntryA2H,Banked			 
    CLRF    StatsEntryA1,Banked				
    CLRF    StatsEntryA1H,Banked
;
    GOTO    AverageFilter_processEntry
#endif
;
AverageFilter_moveup:
;
    MOVFF   StatsEntryA8,StatsEntryA9		;Move all of the flow values up one register
    MOVFF   StatsEntryA8H,StatsEntryA9H
    MOVFF   StatsEntryA7,StatsEntryA8
    MOVFF   StatsEntryA7H,StatsEntryA8H
    MOVFF   StatsEntryA6,StatsEntryA7
    MOVFF   StatsEntryA6H,StatsEntryA7H
    MOVFF   StatsEntryA5,StatsEntryA6
    MOVFF   StatsEntryA5H,StatsEntryA6H
    MOVFF   StatsEntryA4,StatsEntryA5
    MOVFF   StatsEntryA4H,StatsEntryA5H
    MOVFF   StatsEntryA3,StatsEntryA4
    MOVFF   StatsEntryA3H,StatsEntryA4H
    MOVFF   StatsEntryA2,StatsEntryA3
    MOVFF   StatsEntryA2H,StatsEntryA3H
    MOVFF   StatsEntryA1,StatsEntryA2
    MOVFF   StatsEntryA1H,StatsEntryA2H
    MOVFF   StatsEntryA0,StatsEntryA1
    MOVFF   StatsEntryA0H,StatsEntryA1H
;
    MOVFF   StatsEntry4,StatsEntryA0		;Insert the new median flow rate at the bottom of the list
    MOVFF   StatsEntry4H,StatsEntryA0H
;   
AverageFilter_processEntry:
;
    MOVFF   StatsEntryA0,CalculatorX0		;Add all the rates together
    MOVFF   StatsEntryA0H,CalculatorX1
    CLRF    CalculatorX2,Access
;
    MOVFF   StatsEntryA1,WREG
    ADDWF   CalculatorX0,Same,Access
    MOVFF   StatsEntryA1H,WREG
    ADDWFC  CalculatorX1,Same,Access
    MOVLW   0
    ADDWFC  CalculatorX2,Same,Access
;
    MOVFF   StatsEntryA2,WREG
    ADDWF   CalculatorX0,Same,Access
    MOVFF   StatsEntryA2H,WREG
    ADDWFC  CalculatorX1,Same,Access
    MOVLW   0
    ADDWFC  CalculatorX2,Same,Access
;
    MOVFF   StatsEntryA3,WREG
    ADDWF   CalculatorX0,Same,Access
    MOVFF   StatsEntryA3H,WREG
    ADDWFC  CalculatorX1,Same,Access
    MOVLW   0
    ADDWFC  CalculatorX2,Same,Access
;
    MOVFF   StatsEntryA4,WREG
    ADDWF   CalculatorX0,Same,Access
    MOVFF   StatsEntryA4H,WREG
    ADDWFC  CalculatorX1,Same,Access
    MOVLW   0
    ADDWFC  CalculatorX2,Same,Access
;
    MOVFF   StatsEntryA5,WREG
    ADDWF   CalculatorX0,Same,Access
    MOVFF   StatsEntryA5H,WREG
    ADDWFC  CalculatorX1,Same,Access
    MOVLW   0
    ADDWFC  CalculatorX2,Same,Access
;
    MOVFF   StatsEntryA6,WREG
    ADDWF   CalculatorX0,Same,Access
    MOVFF   StatsEntryA6H,WREG
    ADDWFC  CalculatorX1,Same,Access
    MOVLW   0
    ADDWFC  CalculatorX2,Same,Access
;
    MOVFF   StatsEntryA7,WREG
    ADDWF   CalculatorX0,Same,Access
    MOVFF   StatsEntryA7H,WREG
    ADDWFC  CalculatorX1,Same,Access
    MOVLW   0
    ADDWFC  CalculatorX2,Same,Access
;
    MOVFF   StatsEntryA8,WREG
    ADDWF   CalculatorX0,Same,Access
    MOVFF   StatsEntryA8H,WREG
    ADDWFC  CalculatorX1,Same,Access
    MOVLW   0
    ADDWFC  CalculatorX2,Same,Access
;
    MOVFF   StatsEntryA9,WREG
    ADDWF   CalculatorX0,Same,Access
    MOVFF   StatsEntryA9H,WREG
    ADDWFC  CalculatorX1,Same,Access
    MOVLW   0
    ADDWFC  CalculatorX2,Same,Access
;
; Find the high and subtract it
;
    CLRF    CalculatorY0,Access			;Clear CalculatorY
    CLRF    CalculatorY1,Access
;
    MOVF    CalculatorY0,W,Access		;Subtract CalculatorY from FlowAx
    SUBWF   StatsEntryA0,W,Banked
    MOVF    CalculatorY1,W,Access
    SUBWFB  StatsEntryA0H,W,Banked
    BTFSC   CarryFlag				;If CalculatorY bigger than FlowAx
    MOVFF   StatsEntryA0,CalculatorY0			;Then move FlowAx to CalculatorY
    BTFSC   CarryFlag
    MOVFF   StatsEntryA0H,CalculatorY1		;Else just continue
;
    MOVF    CalculatorY0,W,Access
    SUBWF   StatsEntryA1,W,Banked
    MOVF    CalculatorY1,W,Access
    SUBWFB  StatsEntryA1H,W,Banked
    BTFSC   CarryFlag
    MOVFF   StatsEntryA1,CalculatorY0
    BTFSC   CarryFlag
    MOVFF   StatsEntryA1H,CalculatorY1
;
    MOVF    CalculatorY0,W,Access
    SUBWF   StatsEntryA2,W,Banked
    MOVF    CalculatorY1,W,Access
    SUBWFB  StatsEntryA2H,W,Banked
    BTFSC   CarryFlag
    MOVFF   StatsEntryA2,CalculatorY0
    BTFSC   CarryFlag
    MOVFF   StatsEntryA2H,CalculatorY1
;
    MOVF    CalculatorY0,W,Access
    SUBWF   StatsEntryA3,W,Banked
    MOVF    CalculatorY1,W,Access
    SUBWFB  StatsEntryA3H,W,Banked
    BTFSC   CarryFlag
    MOVFF   StatsEntryA3,CalculatorY0
    BTFSC   CarryFlag
    MOVFF   StatsEntryA3H,CalculatorY1
;
    MOVF    CalculatorY0,W,Access
    SUBWF   StatsEntryA4,W,Banked
    MOVF    CalculatorY1,W,Access
    SUBWFB  StatsEntryA4H,W,Banked
    BTFSC   CarryFlag
    MOVFF   StatsEntryA4,CalculatorY0
    BTFSC   CarryFlag
    MOVFF   StatsEntryA4H,CalculatorY1
;
    MOVF    CalculatorY0,W,Access
    SUBWF   StatsEntryA5,W,Banked
    MOVF    CalculatorY1,W,Access
    SUBWFB  StatsEntryA5H,W,Banked
    BTFSC   CarryFlag
    MOVFF   StatsEntryA5,CalculatorY0
    BTFSC   CarryFlag
    MOVFF   StatsEntryA5H,CalculatorY1
;
    MOVF    CalculatorY0,W,Access
    SUBWF   StatsEntryA6,W,Banked
    MOVF    CalculatorY1,W,Access
    SUBWFB  StatsEntryA6H,W,Banked
    BTFSC   CarryFlag
    MOVFF   StatsEntryA6,CalculatorY0
    BTFSC   CarryFlag
    MOVFF   StatsEntryA6H,CalculatorY1
;
    MOVF    CalculatorY0,W,Access
    SUBWF   StatsEntryA7,W,Banked
    MOVF    CalculatorY1,W,Access
    SUBWFB  StatsEntryA7H,W,Banked
    BTFSC   CarryFlag
    MOVFF   StatsEntryA7,CalculatorY0
    BTFSC   CarryFlag
    MOVFF   StatsEntryA7H,CalculatorY1
;
    MOVF    CalculatorY0,W,Access
    SUBWF   StatsEntryA8,W,Banked
    MOVF    CalculatorY1,W,Access
    SUBWFB  StatsEntryA8H,W,Banked
    BTFSC   CarryFlag
    MOVFF   StatsEntryA8,CalculatorY0
    BTFSC   CarryFlag
    MOVFF   StatsEntryA8H,CalculatorY1
;
    MOVF    CalculatorY0,W,Access
    SUBWF   StatsEntryA9,W,Banked
    MOVF    CalculatorY1,W,Access
    SUBWFB  StatsEntryA9H,W,Banked
    BTFSC   CarryFlag
    MOVFF   StatsEntryA9,CalculatorY0
    BTFSC   CarryFlag
    MOVFF   StatsEntryA9H,CalculatorY1
;
    MOVF    CalculatorY0,W,Access		;Subtract the highest value from CalculatorX
    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				;Set CalculatorY to 0xFFFF
    MOVWF   CalculatorY0,Access
    MOVWF   CalculatorY1,Access
;
    MOVF    CalculatorY0,W,Access		;Subtract CalculatorY from FlowAx
    SUBWF   StatsEntryA0,W,Banked
    MOVF    CalculatorY1,W,Access
    SUBWFB  StatsEntryA0H,W,Banked
    BTFSS   CarryFlag				;If CalculatorY smaller than FlowAx
    MOVFF   StatsEntryA0,CalculatorY0		;Then move FlowAx to CalculatorY
    BTFSS   CarryFlag
    MOVFF   StatsEntryA0H,CalculatorY1		;Else just continue
;
    MOVF    CalculatorY0,W,Access
    SUBWF   StatsEntryA1,W,Banked
    MOVF    CalculatorY1,W,Access
    SUBWFB  StatsEntryA1H,W,Banked
    BTFSS   CarryFlag
    MOVFF   StatsEntryA1,CalculatorY0
    BTFSS   CarryFlag
    MOVFF   StatsEntryA1H,CalculatorY1
;
    MOVF    CalculatorY0,W,Access
    SUBWF   StatsEntryA2,W,Banked
    MOVF    CalculatorY1,W,Access
    SUBWFB  StatsEntryA2H,W,Banked
    BTFSS   CarryFlag
    MOVFF   StatsEntryA2,CalculatorY0
    BTFSS   CarryFlag
    MOVFF   StatsEntryA2H,CalculatorY1
;
    MOVF    CalculatorY0,W,Access
    SUBWF   StatsEntryA3,W,Banked
    MOVF    CalculatorY1,W,Access
    SUBWFB  StatsEntryA3H,W,Banked
    BTFSS   CarryFlag
    MOVFF   StatsEntryA3,CalculatorY0
    BTFSS   CarryFlag
    MOVFF   StatsEntryA3H,CalculatorY1
;
    MOVF    CalculatorY0,W,Access
    SUBWF   StatsEntryA4,W,Banked
    MOVF    CalculatorY1,W,Access
    SUBWFB  StatsEntryA4H,W,Banked
    BTFSS   CarryFlag
    MOVFF   StatsEntryA4,CalculatorY0
    BTFSS   CarryFlag
    MOVFF   StatsEntryA4H,CalculatorY1
;
    MOVF    CalculatorY0,W,Access
    SUBWF   StatsEntryA5,W,Banked
    MOVF    CalculatorY1,W,Access
    SUBWFB  StatsEntryA5H,W,Banked
    BTFSS   CarryFlag
    MOVFF   StatsEntryA5,CalculatorY0
    BTFSS   CarryFlag
    MOVFF   StatsEntryA5H,CalculatorY1
;
    MOVF    CalculatorY0,W,Access
    SUBWF   StatsEntryA6,W,Banked
    MOVF    CalculatorY1,W,Access
    SUBWFB  StatsEntryA6H,W,Banked
    BTFSS   CarryFlag
    MOVFF   StatsEntryA6,CalculatorY0
    BTFSS   CarryFlag
    MOVFF   StatsEntryA6H,CalculatorY1
;
    MOVF    CalculatorY0,W,Access
    SUBWF   StatsEntryA7,W,Banked
    MOVF    CalculatorY1,W,Access
    SUBWFB  StatsEntryA7H,W,Banked
    BTFSS   CarryFlag
    MOVFF   StatsEntryA7,CalculatorY0
    BTFSS   CarryFlag
    MOVFF   StatsEntryA7H,CalculatorY1
;
    MOVF    CalculatorY0,W,Access
    SUBWF   StatsEntryA8,W,Banked
    MOVF    CalculatorY1,W,Access
    SUBWFB  StatsEntryA8H,W,Banked
    BTFSS   CarryFlag
    MOVFF   StatsEntryA8,CalculatorY0
    BTFSS   CarryFlag
    MOVFF   StatsEntryA8H,CalculatorY1
;
    MOVF    CalculatorY0,W,Access
    SUBWF   StatsEntryA9,W,Banked
    MOVF    CalculatorY1,W,Access
    SUBWFB  StatsEntryA9H,W,Banked
    BTFSS   CarryFlag
    MOVFF   StatsEntryA9,CalculatorY0
    BTFSS   CarryFlag
    MOVFF   StatsEntryA9H,CalculatorY1
;
    MOVF    CalculatorY0,W,Access		;Subtract the lowest value from CalculatorX
    SUBWF   CalculatorX0,Same,Access
    MOVF    CalculatorY1,W,Access
    SUBWFB  CalculatorX1,Same,Access
    MOVLW   0                      
    SUBWFB  CalculatorX2,Same,Access
;         
    RRCF    CalculatorX2,Same,Access		;Divide by 8 (Diveide by 2 three times)
    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
;
    CLRF    CalculatorX2,Access			;Clear upper bytes of CalculatorX
    CLRF    CalculatorX3,Access
    CLRF    CalculatorX4,Access
;
    RETURN
;
#endif
;
;*******************************************************************************
;*
;*  EEPROM
;*
;*******************************************************************************
;*  Read data from internal EEPROM                
;*  - W loaded with address
;*******************************************************************************
;
    ORG     EEPROM_ORIGIN   
;
#ifdef EEPROM_S
;
;*******************************************************************************
;*  Load variables specific to system from internal EEPROM                
;*******************************************************************************
;
LoadVariablesFromEEPROM:
;
    MOVLW   0x00
    MOVWF   EEADRH,Access
    MOVLW   0x00
    MOVWF   EEADR,Access
;

    MOVLW   EE_ConfigFlags			;Device config flags
    CALL    ReadInternalEEPROM
    MOVWF   ConfigFlags, Banked
;
    BTFSS   ConfigInitBit
    GOTO    LoadVariablesToEEPROM_Exit
;
    MOVLW   EE_CANKing_MODE
    CALL    ReadInternalEEPROM
    MOVWF   CANKing_MODE, Banked
    MOVLW   EE_BaseNumber
    CALL    ReadInternalEEPROM
    MOVWF   BaseNumber, Banked
;
    MOVLW   EE_DeviceID				;Current Deive ID
    CALL    ReadInternalEEPROM
    MOVWF   DeviceID, Banked
    MOVLW   EE_DeviceFlags			;Is the device engaged or disingaged
    CALL    ReadInternalEEPROM
    MOVWF   DeviceFlags, Banked
    MOVLW   EE_FlowRateH			;Current Flow rate 2bytes
    CALL    ReadInternalEEPROM
    MOVWF   FlowRateH, Banked
    MOVLW   EE_FlowRateL
    CALL    ReadInternalEEPROM
    MOVWF   FlowRateL, Banked
;    
    MOVLW   EE_Folder_1H			;Mayor's Message Folder Envelope
    CALL    ReadInternalEEPROM
    MOVWF   Folder_1H, Banked
    MOVLW   EE_Folder_1L
    CALL    ReadInternalEEPROM
    MOVWF   Folder_1L, Banked
    ;Folder 2 variable is not saved to memory
    ;Folder 3 variable is not saved to memory
    ;Folder 4 variable is not saved to memory
    ;Folder 5 variable is not saved to memory
    MOVLW   EE_Folder_6H			;Flow Control Message Receive Folder Envelope
    CALL    ReadInternalEEPROM
    MOVWF   Folder_6H, Banked
    MOVLW   EE_Folder_6L
    CALL    ReadInternalEEPROM
    MOVWF   Folder_6L, Banked
    MOVLW   EE_Folder_7H			;Flow Control Message Send Folder Envelope
    CALL    ReadInternalEEPROM
    MOVWF   Folder_7H, Banked
    MOVLW   EE_Folder_7L
    CALL    ReadInternalEEPROM
    MOVWF   Folder_7L, Banked
    MOVLW   EE_GoldenNumber
    CALL    ReadInternalEEPROM
    MOVWF   GoldenNumber, Access
    MOVLW   EE_GoldenNumberH
    CALL    ReadInternalEEPROM
    MOVWF   GoldenNumberH, Access
    MOVLW   EE_GoldenNumberHH
    CALL    ReadInternalEEPROM
    MOVWF   GoldenNumberHH, Access
    MOVLW   EE_GoldenNumberHHH
    CALL    ReadInternalEEPROM
    MOVWF   GoldenNumberHHH, Access
    MOVLW   EE_GoldenNumberHHHH
    CALL    ReadInternalEEPROM
    MOVWF   GoldenNumberHHHH, Access
;
LoadVariablesToEEPROM_Exit:
;
    RETURN
;
ReadInternalEEPROM:
;
    MOVWF   EEADR,Access
;  
    BCF	    _EEPGD
    BCF	    _EECFGS
;
    BSF	    _EERD
    NOP
    MOVF    EEDATA,W,Access
;
    RETURN
;
;*******************************************************************************
;* Write data into internal EEPROM                
;* - EEADR loaded with address
;* - Data to be written in W
;* - Interrupts are disabled
;*******************************************************************************
;
WriteInternalEEPROM:
;
    MOVWF   EEDATA,Access

    BCF	    _EEPGD
    BCF     _EECFGS
    BSF     _EEWREN
;
WriteInternalEEPROM1:
;
    BTFSS   BootModeBit
;
    BCF	    _GIEH
    BTFSC   _GIEH
    GOTO    WriteInternalEEPROM1
;
    MOVLW   0x55
    MOVWF   EECON2,Access
    MOVLW   0xAA
    MOVWF   EECON2,Access
    BSF	    _EEWR
    BTFSC   _EEWR
    BRA	    $-2
;
    BTFSS   BootModeBit
    BSF	    _GIEH
;
    BCF	    _EEWREN
    BTFSS   BootModeBit
;
    RETURN
;
ProcessEEPROM:
;
    BTFSC     _EEWR
    GOTO      ProcessEEPROMEnd
;
;The size of the code in this macro affects the calculation in the EEPROM state dispatcher
EEPROM_Check: MACRO     EEPROM,RAM
;
    LOCAL     EEPROM_CheckEnd
;
    MOVFF     RAM,WREG				;1 2
    MOVWF     EEPROM_Work,Banked		;3
    MOVLW     EEPROM				;4
    CALL      ReadInternalEEPROM		;5 6
    SUBWF     EEPROM_Work,W,Banked		;7      
    BTFSC     ZeroFlag				;8
    GOTO      EEPROM_CheckEnd			;9 10
    ;
    MOVF      EEPROM_Work,W,Banked		;11
    CALL      WriteInternalEEPROM		;12 13
;
EEPROM_CheckEnd:
;
    INCF      EEPROM_State,Same,Banked		;14
;
    GOTO      ProcessEEPROMEnd			;15 16
;
    ENDM
;
EEPROM_Save: MACRO     EEPROM,RAM
;
    MOVFF     RAM,WREG				
    MOVWF     EEPROM_Work,Banked			
    MOVLW     EEPROM					
    CALL      ReadInternalEEPROM
;
    SUBWF     EEPROM_Work,W,Banked			     				
;
    MOVF      EEPROM_Work,W,Banked			
    CALL      WriteInternalEEPROM	
;
    ENDM
;
EEPROM_Slot:  macro
;
    CLRF      EEPROM_State,Banked		;1
    GOTO      ProcessEEPROMEnd			;2 3
    NOP						;4
    NOP						;5
    NOP						;6
    NOP						;7
    NOP						;8
    NOP						;9
    NOP						;10
    NOP						;11
    NOP						;12
    NOP						;13
    NOP						;14
    NOP						;15
    NOP						;16
;
    ENDM
;
    CLRF    PCLATU,Access
;
    RLNCF   EEPROM_State,W,Banked
    SWAPF   WREG,W,Access
    ANDLW   b'00000011'
    ADDLW   HIGH(Process_EEPROM_DispatchTable)
    MOVWF   PCLATH,Access
;
    RLNCF   EEPROM_State,W,Banked
    SWAPF   WREG,W,Access
    ANDLW   b'11100000'
;
    ADDLW   LOW(Process_EEPROM_DispatchTable)
    BTFSC   CarryFlag
    INCF    PCLATH,Same,Access
    MOVWF   PCL,Access
;
Process_EEPROM_DispatchTable:
;
P_E_ST_00   EEPROM_Check EE_BootFlags,BootFlags
P_E_ST_01   EEPROM_Check EE_CANKing_MODE,CANKing_MODE
P_E_ST_02   EEPROM_Check EE_BaseNumber,BaseNumber
P_E_ST_03   EEPROM_Check EE_Folder_1H,Folder_1H
P_E_ST_04   EEPROM_Check EE_Folder_1L,Folder_1L
P_E_ST_05   EEPROM_Check EE_Folder_2H,Folder_2H
P_E_ST_06   EEPROM_Check EE_Folder_2L,Folder_2L
P_E_ST_07   EEPROM_Check EE_Folder_3H,Folder_3H
P_E_ST_08   EEPROM_Check EE_Folder_3L,Folder_3L
P_E_ST_09   EEPROM_Check EE_Folder_4H,Folder_4H
P_E_ST_10   EEPROM_Check EE_Folder_4L,Folder_4L
P_E_ST_11   EEPROM_Check EE_Folder_5H,Folder_5H
P_E_ST_12   EEPROM_Check EE_Folder_5L,Folder_5L
P_E_ST_13   EEPROM_Check EE_Folder_6H,Folder_6H
P_E_ST_14   EEPROM_Check EE_Folder_6L,Folder_6L
P_E_ST_15   EEPROM_Check EE_Folder_7H,Folder_7H
;
P_E_ST_16   EEPROM_Check EE_Folder_7L,Folder_7L
P_E_ST_17   EEPROM_Check EE_DeviceFlags,DeviceFlags
P_E_ST_18   EEPROM_Check EE_ConfigFlags,ConfigFlags
P_E_ST_19   EEPROM_Check EE_DeviceID,DeviceID
P_E_ST_20   EEPROM_Check EE_FlowRateH,FlowRateH
P_E_ST_21   EEPROM_Check EE_FlowRateL,FlowRateL
P_E_ST_22   EEPROM_Check EE_GoldenNumber,GoldenNumber
P_E_ST_23   EEPROM_Check EE_GoldenNumberH,GoldenNumberH
P_E_ST_24   EEPROM_Check EE_GoldenNumberHH,GoldenNumberHH
P_E_ST_25   EEPROM_Check EE_GoldenNumberHHH,GoldenNumberHHH
P_E_ST_26   EEPROM_Check EE_GoldenNumberHHHH,GoldenNumberHHHH
P_E_ST_27   EEPROM_Slot
P_E_ST_28   EEPROM_Slot
P_E_ST_29   EEPROM_Slot
P_E_ST_30   EEPROM_Slot
P_E_ST_31   EEPROM_Slot
;
ProcessEEPROMEnd:
;
    RETURN
;
#endif
;
;*******************************************************************************
;*
;*  CANBusCode
;*
;*******************************************************************************
;
    ORG     CANBUS_ORIGIN
;
CANKingdomRX_extern:
;
KingsMessTest:
;
    MOVFF   RXMessBuff_EL,WREG			;Compare EIDL with King's ID
    XORLW   0x00				;King's Identifier is 0x00000000
    BTFSS   ZeroFlag				;Test if Zero
    GOTO    ConfMessTest			;Else goto next test
;
    MOVFF   RXMessBuff_EH,WREG			;Compare EIDH with King's ID
    XORLW   0x00				;King's Identifier is 0x00000000
    BTFSS   ZeroFlag				;Test if Zero
    GOTO    ConfMessTest			;Else goto next test
;
    GOTO    KingsMess				;If match then goto King's message handler
;
ConfMessTest:
;
    MOVFF   RXMessBuff_EL,WREG			;Compare EIDL with Configuration ID
    XORWF   Folder_2L,W,Banked			;Configuration message identifier
    BTFSS   ZeroFlag				;Test if Zero
    GOTO    MessTestBasicExit			;Else goto exit
;
    MOVFF   RXMessBuff_EH,WREG			;Compare EIDH with Configuration ID
    XORWF   Folder_2H,W,Banked			;Configuration message identifier
    BTFSS   ZeroFlag				;Test if Zero
    GOTO    MessTestBasicExit			;Else goto exit
;
    GOTO    ConfMess				;If match then goto Configuration message handler
;
MessTestBasicExit:
;
#IFDEF  FLOWCONTROLDEVICE
;
    BTFSC   FlowDevice
    GOTO    FlowBroadTest
    BTFSC   FCDevice
    GOTO    FCBroadTest
    GOTO    MessExit
;
FlowBroadTest:
;
    MOVFF   RXMessBuff_EL,WREG		;Compare EIDL with Flow Control ID
    XORLW   0x2C				;Flow message identifier
    BTFSS   ZeroFlag				;Test if Zero
    GOTO    FlowMessTest			;Else goto exit
;
    MOVFF   RXMessBuff_EH,WREG		;Compare EIDH with Flow Control ID
    XORLW   0x01				;Flow message identifier
    BTFSS   ZeroFlag				;Test if Zero
    GOTO    FlowMessTest			;Else goto exit
;
    GOTO    FlowMess				;If match then goto Flow control message handler
;
FlowMessTest:
;
    MOVFF   RXMessBuff_EL,WREG		;Compare EIDL with Flow Control ID
    XORWF   Folder_6L,W,Banked			;Flow message identifier
    BTFSS   ZeroFlag				;Test if Zero
    GOTO    MessExit				;Else goto exit
;
    MOVFF   RXMessBuff_EH,WREG		;Compare EIDH with Flow Control ID
    XORWF   Folder_6H,W,Banked			;Flow message identifier
    BTFSS   ZeroFlag				;Test if Zero
    GOTO    MessExit				;Else goto exit
    GOTO    FlowMess				;If match then goto Flow control message handler
;
FCBroadTest:
;
    MOVFF   RXMessBuff_EL,WREG			;Compare EIDL with Flow Control ID
    XORLW   0x2C				;Flow message identifier
    BTFSS   ZeroFlag				;Test if Zero
    GOTO    FCMessTest				;Else goto exit
;
    MOVFF   RXMessBuff_EH,WREG			;Compare EIDH with Flow Control ID
    XORLW   0x01				;Flow message identifier
    BTFSS   ZeroFlag				;Test if Zero
    GOTO    FCMessTest				;Else goto exit
;
    GOTO    FCMessReplyOnly			;If match then goto Flow control message handler
;
FCMessTest:
;
    MOVFF   RXMessBuff_EL,WREG			;Compare EIDL with Flow Control ID
    XORWF   Folder_6L,W,Banked			;Flow message identifier
    BTFSS   ZeroFlag				;Test if Zero
    GOTO    MessExit				;Else goto exit
;
    MOVFF   RXMessBuff_EH,WREG			;Compare EIDH with Flow Control ID
    XORWF   Folder_6H,W,Banked			;Flow message identifier
    BTFSS   ZeroFlag				;Test if Zero
    GOTO    MessExit				;Else goto exit
    GOTO    FCMess				;If match then goto Flow control message handler
;
#ENDIF
;
#IFDEF  HYDDRIVEDEVICE
HydraulicBroadTest:
;
    MOVFF   RXMessBuff_EL,WREG		;Compare EIDL with Flow Control ID
    XORLW   0x2C				;Flow message identifier
    BTFSS   ZeroFlag				;Test if Zero
    GOTO    HydraulicMessTest			;Else goto exit
;
    MOVFF   RXMessBuff_EH,WREG		;Compare EIDH with Flow Control ID
    XORLW   0x01				;Flow message identifier
    BTFSS   ZeroFlag				;Test if Zero
    GOTO    HydraulicMessTest			;Else goto exit
;
    GOTO    HydraulicMessReplyOnly		;If match then goto Flow control message handler
;
HydraulicMessTest:
;
    MOVFF   RXMessBuff_EL,WREG		;Compare EIDL with Flow Control ID
    XORWF   Folder_6L,W,Banked			;Flow message identifier
    BTFSS   ZeroFlag				;Test if Zero
    GOTO    MessExit				;Else goto exit
;
    MOVFF   RXMessBuff_EH,WREG		;Compare EIDH with Flow Control ID
    XORWF   Folder_6H,W,Banked			;Flow message identifier
    BTFSS   ZeroFlag				;Test if Zero
    GOTO    MessExit				;Else goto exit
    GOTO    HydraulicMess			;If match then goto Flow control message handler
;
#ENDIF
;
#IFDEF  GRANCONTROLDEVICE
;
GranBroadTest:
;
    MOVFF   RXMessBuff_EL,WREG		;Compare EIDL with Flow Control ID
    XORLW   0x2C				;Flow message identifier
    BTFSS   ZeroFlag				;Test if Zero
    GOTO    GranMessTest			;Else goto exit
;
    MOVFF   RXMessBuff_EH,WREG		;Compare EIDH with Flow Control ID
    XORLW   0x01				;Flow message identifier
    BTFSS   ZeroFlag				;Test if Zero
    GOTO    GranMessTest			;Else goto exit
;
    GOTO    GranMess				;If match then goto Flow control message handler
;
GranMessTest:
;
    MOVFF   RXMessBuff_EL,WREG		;Compare EIDL with Flow Control ID
    XORWF   Folder_6L,W,Banked			;Flow message identifier
    BTFSS   ZeroFlag				;Test if Zero
    GOTO    MessExit				;Else goto exit
;
    MOVFF   RXMessBuff_EH,WREG		;Compare EIDH with Flow Control ID
    XORWF   Folder_6H,W,Banked			;Flow message identifier
    BTFSS   ZeroFlag				;Test if Zero
    GOTO    MessExit				;Else goto exit
    GOTO    GranMess				;If match then goto Flow control message handler
;
#ENDIF
;
CANKingdomRX_handler_exit:
;
    GOTO    MessExit
;
;*******************************************************************************
;   Page lookup
;*******************************************************************************
;
KingsMess:
;
    MOVF    RXMessBuff_D1, W, Banked		;Check Message Page byte
    BTFSC   ZeroFlag				;Test if Zero
    GOTO    KingsMess_0_A			;If true then goto page 0
;
    DCFSNZ  WREG,W,Access			;Decrease and test if Zero
    GOTO    KingsMess_1				;If true then goto page 1
;
    DCFSNZ  WREG,W,Access			;Decrease and test if Zero
    GOTO    KingsMess_2				;If true then goto page 2
;
    GOTO    Undefined_Page			;Else goto unidentified page handler
;
KingsMess_0_A:
;	    
    MOVF    RXMessBuff_D2,W,Banked		;Get Action mode byte
    BTFSC   ZeroFlag				;If keep current mode then
    GOTO    KingsMess_0_C			;Go to next section
    ANDLW   b'00000011'				;Get only relevant bits
;
    DCFSNZ  WREG,W,Access			;Decrease and test if Zero
    GOTO    KingsMess_0_A_Run			;If true then goto section
;
    DCFSNZ  WREG,W,Access			;Decrease and test if Zero
    GOTO    KingsMess_0_A_Freeze		;If true then goto section
;
    DCFSNZ  WREG,W,Access			;Decrease and test if Zero
    GOTO    KingsMess_0_A_Reset			;If true then goto section
    GOTO    KingsMess_0_C			;Go to next section
;	    
KingsMess_0_A_Run:
;
    BCF	    ActionType				;Set action to run
    GOTO    KingsMess_0_C			;Go to next section
;	    
KingsMess_0_A_Freeze:
;
    BSF	    ActionType				;Set action to run
    GOTO    KingsMess_0_C			;Go to next section
;	    
KingsMess_0_A_Reset:
;
    RESET
    GOTO    KingsMess_0_C			;Go to next section
;
KingsMess_0_C:
;
    MOVF    RXMessBuff_D3,W,Banked		;Get Comm mode byte
    BTFSC   ZeroFlag				;If keep current mode then
    GOTO    KingsMess_0_M			;Go to next section
    ANDLW   b'00000011'				;Get only relevant bits
;	    
    DCFSNZ  WREG,W,Access			;Decrease and test if Zero
    GOTO    KingsMess_0_C_Silent			;If true then goto section
;
    DCFSNZ  WREG,W,Access			;Decrease and test if Zero
    GOTO    KingsMess_0_C_Listen		;If true then goto section
;
    DCFSNZ  WREG,W,Access			;Decrease and test if Zero
    GOTO    KingsMess_0_C_Comm			;If true then goto section
    GOTO    KingsMess_0_M			;Go to next section
;	    
KingsMess_0_C_Silent:
;
    GOTO    KingsMess_0_M			;Go to next section
;	    
KingsMess_0_C_Listen:
;
    BSF	    CommType				;Set comm to listen only
    GOTO    KingsMess_0_M			;Go to next section
;	    
KingsMess_0_C_Comm:
;
    BCF	    CommType				;Set comm to communicate
    GOTO    KingsMess_0_M			;Go to next section
;
KingsMess_0_M:
;	    
    MOVF    RXMessBuff_D4,W,Banked		;Get City mode byte
    ANDLW   b'00001111'				;Get only relevant bits
    IORWF   CANKing_MODE,Same,Banked		;Add result to CANKing_MODE register
;
    GOTO    MessExit
;	    
KingsMess_1:
;	    
    MOVFF   RXMessBuff_D4,BaseNumber		;Get base number LCB from buffer
    BSF	    ConfigBaseNum			;Base number registered
;
    BTFSC   ConfigInitBit				;Is system initialized?
    GOTO    MessExit				;Then exit
    BTFSS   ConfigDeviceNum			;Else check if dvice id set
    GOTO    MessExit				;Else exit
;
    MOVFF   RXMessBuff_D2,WREG		;Move Mayor's response Page to working register
    XORLW   0xFF				;Mayor's document page 1
    BTFSS   ZeroFlag				;If no match
    GOTO    MessExit				;Exit
;
KingsMess_2:
;
    MOVF    RXMessBuff_D0,W,Banked		;Move target number to working register
    XORWF   Folder_1L,W,Banked			;Match Mayor's Evelope		
    BTFSS   ZeroFlag				;If match then continue
    GOTO    MessExit				;Else not for this device and Exit
;
    MOVF    RXMessBuff_D6,W,Banked		;Get folder number
    DECF    WREG,W,Access			;Decrease by three
    DECF    WREG,W,Access
    DECF    WREG,W,Access
    DECF    WREG,W,Access
    DECF    WREG,W,Access
;
KingsMess2_Env6:
;
    DECFSZ  WREG,W,Access			;If not for folder 4
    GOTO    KingsMess2_Env7			;Then move on
    MOVFF   RXMessBuff_D3,Folder_6H		;Else save folder envelope
    MOVFF   RXMessBuff_D2,Folder_6L
;	    
    GOTO    KingsMess2_Env6_2
;    
KingsMess2_Env6_2:
;    
    GOTO    MessExit		    
;
KingsMess2_Env7:

    DECFSZ  WREG,W,Access			;If not for folder 5
    GOTO    Undefined_Fold			;Then unidentified
;
    MOVFF   RXMessBuff_D3,Folder_7H		;Else save folder envelope
    MOVFF   RXMessBuff_D2,Folder_7L
    BCF	    ConfigModeBit				;Set device to config mode  
    BSF	    ConfigInitBit				;Set device to config mode
;
    CALL    Send_Config_Status			;Reply with the status of device
;
#ifdef FLOWCONTRLDEVICE
    BTFSC   FCDevice
    CALL    Send_Engaged_Status
#endif
;
    GOTO    MessExit
;
ConfMess:
;
    MOVF    RXMessBuff_D1,W,Banked		;Check Message Page byte
    BTFSC   ZeroFlag				;Test if Zero
    GOTO    ConfMess_0				;If true then goto ConfMess_0
;
    DCFSNZ  WREG,W,Access			;Decrease and test if Zero
    GOTO    Undefined_Page			;Else goto unidentified page handler
;
    DCFSNZ  WREG,W,Access			;Decrease and test if Zero
    GOTO    ConfMess_2				;If true then goto page 1
;
    GOTO    Undefined_Page			;Else goto unidentified page handler
;
ConfMess_0:					;Configure Flow Rate Unit
;
    MOVF    RXMessBuff_D0,W,Banked		;Move target number to working register
    XORWF   Folder_1L,W,Banked			;Match Mayor's Evelope		
    BTFSS   ZeroFlag				;If match then continue
    GOTO    ConfMess_C				;Else not for this device and Exit
;
    MOVFF   RXMessBuff_D2,WREG			;Compare Config bit flags
    ANDLW   b'00111000'				;Reset device?
    XORLW   b'00101000'
    BTFSS   ZeroFlag				;Test if true
    GOTO    ConfMess_C				;Go to next section
;
ConfMess_Reset:
;
    CLRF    DeviceID				;Clear the device ID
    CALL    Reset_Counters			;Reset all CANBus counters
    CALL    Reset_Default_values		;Reset all CANBus default values
;
    GOTO    MessExit				;Go to exit
;
ConfMess_C:					;Configure Flow Rate Unit
;
    MOVFF   RXMessBuff_D2,WREG			;Compare Config bit flags
    ANDLW   b'10000000'				;Go into init mode?
    BTFSC   ZeroFlag				;Test if true
    GOTO    ConfMess_0_2			;Go to exit
    BTFSC   ConfigInitBit
    GOTO    ConfMess_0_2			;Go to exit
;
Enter_config_mode:
;
    BSF	    ConfigModeBit			;Set device to config mode  
    BCF	    ConfigInitBit			;Device not initialised   
    BCF	    ConfigReplySent			;Button not yet pressed
    BCF	    ConfigDeviceNum			;Device ID is descarded
    BCF	    SentEngagedBit			;Reset sent engage flag
    CLRF    DeviceID				;Clear the device ID
    CLRF    Folder_1L				;Clear the Mayor's Folder
    CLRF    Folder_1H
    GOTO    ConfMess_Respond			;Continue to next section
;
ConfMess_0_2:
;
    MOVFF   RXMessBuff_D2,WREG			;Compare Config bit flags
    ANDLW   b'11000000'				;Go into init mode?
    XORLW   b'11000000'				;Make sure all bits are set
    BTFSC   ZeroFlag				;Test if true
    GOTO    Enter_config_mode			;Enter config mode
;
ConfMess_Respond:
;
    MOVFF   RXMessBuff_D2,WREG			;Compare Config bit flags
    ANDLW   b'00000001'				;Reply if not init
    BTFSC   ZeroFlag				;Test if true
    GOTO    MessExit				;Else goto exit
;
ConfMess_0_respond:
;
    BTFSS   ConfigInitBit				;Check if device initialised
    CALL    Send_Config_Status			;Reply with Device init status
;
    GOTO    MessExit				;Go to exit
;
ConfMess_2:					;Save new device ID message
;
    BTFSS   ConfigReplySent			;Make sure message is meant for this unit
    GOTO    MessExit
    BTFSC   ConfigInitBit
    GOTO    MessExit
    BTFSS   ConfigModeBit
    GOTO    MessExit
;
    MOVFF   RXMessBuff_D2,DeviceID		;Compare Config bit flags
    BSF	    ConfigDeviceNum
;
    BTFSS   ConfigBaseNum
    GOTO    MessExit
    CALL    MayorMess				;Send mayor's message for registration of deivce at main unit
    GOTO    MessExit				;Go to exit
;
MayorMess:
;
    MOVF    BaseNumber,W,Banked		;Move base number to working register
;
    ADDWF   DeviceID,W,Banked			;Add device id value to base number
    BTFSC   CarryFlag				;If there was a carry
    INCF    Folder_1H, Banked			;Then add 1 to Folder_1H
    MOVWF   Folder_1L, Banked			;Move new address to Folder_1L
;
    CALL    Send_Mayors				;Then send mayor's document page 1
    GOTO    MessExit				;Exit
;
#IFDEF  FLOWCONTROLDEVICE
FlowMess:
;
    TSTFSZ  Folder_1L
    GOTO    FlowMess_Content
    TSTFSZ  Folder_1H
    GOTO    FlowMess_Content
    RETURN
; 
FlowMess_Content:
;
    MOVF    RXMessBuff_D1,W,Banked
    BTFSC   ZeroFlag				;Test if Zero
    GOTO    Undefined_Page			;If true then goto unidentified page handler
;
    DCFSNZ  WREG,W,Access			;Decrease and test if Zero
    GOTO    FlowMess_1				;If true then goto page 1
;
    DCFSNZ  WREG,W,Access			;Decrease and test if Zero
    GOTO    FlowMess_2				;If true then goto page 1
;
    GOTO    Undefined_Page			;Else goto unidentified page handler
;
FlowMess_1:					;Save flow rate message
;
    MOVFF   RXMessBuff_D4,WREG			;Compare Config bit flags
    ANDLW   b'00001000'				;Update Engage?
    BTFSC   ZeroFlag				;Test if true
    GOTO    FlowMess_FlowRate			;Else goto exit
;
FlowMess_Engage:
;
    MOVFF   RXMessBuff_D4,WREG			;Compare Config bit flags
    ANDLW   b'00000010'				;Update Engage?
    BTFSS   ZeroFlag				;Test if true
    GOTO    FlowMess_Engage_On			;Set Engage bit
;
FlowMess_Engage_Off:
;
    BCF     EngageBit				;Engage system
    BCF	    ControlFlow
    GOTO    FlowMess_FlowRate			;Continue to next section
;
FlowMess_Engage_On:
;
    BSF     EngageBit				;Else goto exit
    BSF	    ControlFlow
;
FlowMess_FlowRate:
;
    MOVFF   RXMessBuff_D4,WREG		;Compare Config bit flags
    ANDLW   b'00000100'				;Update Flow rate?
    BTFSC   ZeroFlag				;Test if true
    GOTO    FlowMess_ManualCalib		;Else continue
;
    MOVFF   RXMessBuff_D2,SetPoint	;Save new flow rate
    MOVFF   RXMessBuff_D3,SetPointH	
;
FlowMess_ManualCalib:
;
    MOVFF   RXMessBuff_D5,WREG			;Compare Config bit flags
    ANDLW   b'00000001'				;Update ManualCalibration?
    BTFSS   ZeroFlag				;Test if true
    GOTO    FlowMess_ManualCalib_On		;Set ManualCalibration
;
FlowMess_ManualCalib_Off:
;
    BCF     ManualCalibration			;Manual calibration is not allowed
    GOTO    FlowMess_FlowRateReply		;Continue to next section
;
FlowMess_ManualCalib_On:
;
    BSF     ManualCalibration			;Manual calibration is allowed
;
FlowMess_FlowRateReply:
;
    MOVFF   RXMessBuff_D4,WREG		;Compare Config bit flags
    ANDLW   b'00010000'				;Reply with device details?
    BTFSC   ZeroFlag				;Test if true
    GOTO    MessExit				;Else exit
;
    CALL    Send_Flow_rate			;Call flow rate send message
;
    GOTO    MessExit
;
FlowMess_2:					;Save flow rate message
;
    MOVFF   RXMessBuff_D2,GoldenNumber		;Move new golden number
    MOVFF   RXMessBuff_D3,GoldenNumberH		;Move new golden number
    MOVFF   RXMessBuff_D4,GoldenNumberHH	;Move new golden number
    MOVFF   RXMessBuff_D5,GoldenNumberHHH	;Move new golden number
    MOVFF   RXMessBuff_D6,GoldenNumberHHHH	;Move new golden number
;
    GOTO    MessExit
;
FCMessReplyOnly:
; 
    TSTFSZ  Folder_1L
    GOTO    FCMess_Content_Reply
    TSTFSZ  Folder_1H
    GOTO    FCMess_Content_Reply
    RETURN
;
FCMess_Content_Reply:
;
    MOVF    RXMessBuff_D1,W,Banked
    BTFSC   ZeroFlag				;Test if Zero
    GOTO    Undefined_Page			;If true then goto unidentified page handler
;
    DCFSNZ  WREG,W,Access			;Decrease and test if Zero
    GOTO    FCMess_1_1				;If true then goto page 1
;
    GOTO    Undefined_Page			;Else goto unidentified page handler
;

FCMess:
; 
    TSTFSZ  Folder_1L
    GOTO    FCMess_Content
    TSTFSZ  Folder_1H
    GOTO    FCMess_Content
    RETURN
; 
FCMess_Content:
;
    MOVF    RXMessBuff_D1,W,Banked
    BTFSC   ZeroFlag				;Test if Zero
    GOTO    Undefined_Page			;If true then goto unidentified page handler
;
    DCFSNZ  WREG,W,Access			;Decrease and test if Zero
    GOTO    FCMess_1				;If true then goto page 1
;
    GOTO    Undefined_Page			;Else goto unidentified page handler
;
FCMess_1:
;
    MOVFF   RXMessBuff_D4,WREG			;Compare Config bit flags
    ANDLW   b'00001000'				;Reply with device details?
    BTFSC   ZeroFlag				;Test if true
    GOTO    FCMess_1_1				;Else goto next section
;
    MOVFF   RXMessBuff_D3,PressureTargetH	;Set new pressure target
    MOVFF   RXMessBuff_D2,PressureTargetL	;Set new pressure target
;
FCMess_1_1:
;
    MOVFF   RXMessBuff_D4,WREG			;Compare Config bit flags
    ANDLW   b'00010000'				;Reply with device details?
    BTFSC   ZeroFlag				;Test if true
    GOTO    MessExit				;Else exit
;
    CALL    Send_Engaged_Status			;Call engage status send message
;
    GOTO    MessExit
;
#ENDIF
;
#IFDEF  HYDDRIVEDEVICE
;
HydraulicMessReplyOnly:
;
    TSTFSZ  Folder_1L
    GOTO    HydraulicMess_Content
    TSTFSZ  Folder_1H
    GOTO    HydraulicMess_Content
    RETURN
;
HydraulicMess_ContentReply:
;
    MOVF    RXMessBuff_D1,W,Banked
    BTFSC   ZeroFlag				;Test if Zero
    GOTO    Undefined_Page			;If true then goto unidentified page handler
;
    DCFSNZ  WREG,W,Access			;Decrease and test if Zero
    GOTO    HydraulicMess_1Reply		;If true then goto page 1
;
    GOTO    Undefined_Page			;Else goto unidentified page handler
;
HydraulicMess_1Reply:
;
    MOVFF   RXMessBuff_D4,WREG			;Compare Config bit flags
    ANDLW   b'00010000'				;Reply with device details?
    BTFSC   ZeroFlag				;Test if true
    GOTO    MessExit				;Else exit
;
    CALL    Send_Flow_rate			;Call engage status send message
;
    GOTO    MessExit
;
HydraulicMess:
;
    TSTFSZ  Folder_1L
    GOTO    HydraulicMess_Content
    TSTFSZ  Folder_1H
    GOTO    HydraulicMess_Content
    RETURN
; 
HydraulicMess_Content:
;
    MOVF    RXMessBuff_D1,W,Banked
    BTFSC   ZeroFlag				;Test if Zero
    GOTO    Undefined_Page			;If true then goto unidentified page handler
;
    DCFSNZ  WREG,W,Access			;Decrease and test if Zero
    GOTO    HydraulicMess_1			;If true then goto page 1
;
    GOTO    Undefined_Page			;Else goto unidentified page handler
;
HydraulicMess_1:
;
    MOVFF   RXMessBuff_D4,WREG			;Compare Config bit flags
    ANDLW   b'00000100'				;Update flow rate?
    BTFSC   ZeroFlag				;Test if true
    GOTO    HydraulicMess_Eng			;Else exit
;
    MOVFF   RXMessBuff_D2,TargetVolumeL		;New target volume mL/min
    MOVFF   RXMessBuff_D3,TargetVolumeH
    MOVFF   RXMessBuff_D5,TargetVolumeU		
    CALL    CalculateSP
;
HydraulicMess_Eng:
;
    MOVFF   RXMessBuff_D4,WREG			;Compare Config bit flags
    ANDLW   b'00001000'				;Update flow rate?
    BTFSC   ZeroFlag				;Test if true
    GOTO    HydraulicMess_Vol			;Else exit
;
    MOVFF   RXMessBuff_D4,WREG			;Compare Config bit flags
    ANDLW   b'00000010'				;Update Engage?
    BTFSS   ZeroFlag				;Test if true
    GOTO    HydraulicMess_Eng_On		;Set Engage bit
;
HydraulicMess_Eng_Off:
;
    BCF	    ControlFlow
    GOTO    HydraulicMess_Vol			;Continue to next section
;
HydraulicMess_Eng_On:
;
    BSF	    ControlFlow
;
;
HydraulicMess_Vol:
;
    MOVFF   RXMessBuff_D4,WREG			;Compare Config bit flags
    ANDLW   b'00100000'				;Update volume?
    BTFSC   ZeroFlag				;Test if true
    GOTO    HydraulicMess_Rep			;Else exit
;
    MOVFF   RXMessBuff_D6,PumpVolumeL		;New set point
    MOVFF   RXMessBuff_D7,PumpVolumeH		;New set point H
;
    CALL    HydrCalcNewGoldenNumber
;
HydraulicMess_Rep:
;
    MOVFF   RXMessBuff_D4,WREG			;Compare Config bit flags
    ANDLW   b'00010000'				;Reply with device details?
    BTFSC   ZeroFlag				;Test if true
    GOTO    MessExit				;Else exit
;
    CALL    Send_Flow_rate			;Call engage status send message
;
    GOTO    MessExit
;
#ENDIF
;
;*******************************************************************************
;   Error Handlers
;*******************************************************************************
;
Undefined_Ident:
;
    GOTO    MessExit				;The identifier was not recognized
;
Undefined_Page:
;
    GOTO    MessExit				;The page was not recognized
;
Undefined_Fold:
;
    GOTO    MessExit				;The folder was not recognized
;    
MessExit:
;
    RETURN
;
;*******************************************************************************
;   Messages for sending
;*******************************************************************************
;
Send_Config_Status:
;
    BTFSC   ConfigInitBit
    GOTO    Send_Config_Button_ID		;Send Device ID if device configured
;
Send_Config_Button_None:
;
    MOVLW   0x00				;Byte 0
    GOTO    Send_Config_Button_Byte
;
Send_Config_Button_ID:
;
    MOVFF   Folder_1L,WREG			;Byte 0 - Device ID
;
Send_Config_Button_Byte:
;
    MOVWF   TXMessBuff_D0,Banked		
    MOVLW   0x01				;Byte 1	- Page 1
    MOVWF   TXMessBuff_D1,Banked	
    BTFSC   ConfigInitBit
    GOTO    Send_Config_Status_1
;
Send_Config_Status_0:
;
    MOVLW   0x00				;Byte 2			    
    MOVWF   TXMessBuff_D2,Banked
    GOTO    Send_Config_Status_O
;   
Send_Config_Status_1:
;
    MOVLW   0x01				;Byte 2			    
    MOVWF   TXMessBuff_D2,Banked
;
Send_Config_Status_O:
;
    MOVFF   DeviceID_4,TXMessBuff_D3		;Byte 3 - Device type
    MOVLW   0x00				;Byte 4		    
    MOVWF   TXMessBuff_D4,Banked
    MOVLW   0x00				;Byte 5			    
    MOVWF   TXMessBuff_D5,Banked
    MOVLW   0x00				;Byte 6			
    MOVWF   TXMessBuff_D6,Banked
    MOVLW   0x00				;Byte 7			    
    MOVWF   TXMessBuff_D7,Banked
    MOVLW   0x08				;DLC - 8 bytes			  
    MOVWF   TXMessBuff_DL,Banked
;
    MOVLW   08H					;Load SID2:SID0, EXIDE = 1
    MOVWF   TXMessBuff_SL,Banked
    MOVLW   00H					;Load SID10:SID3, EID17:EID16
    MOVWF   TXMessBuff_SH,Banked		;Load EID15:EID8
    MOVFF   Folder_3H,TXMessBuff_EH		;Load EID7:EID0
    MOVFF   Folder_3L,TXMessBuff_EL		;Load EID7:EID0
;    
    CALL    Send_Message
;
    RETURN 
;
Send_Config_Button:
;
    MOVLW   0x00				;Byte 0
    MOVWF   TXMessBuff_D0,Banked		
    MOVLW   0x01				;Byte 1	- Page 1
    MOVWF   TXMessBuff_D1,Banked	
    MOVLW   0x02				;Byte 2
    BTFSC   ConfigInitBit
    INCF    WREG,Same,Access
    MOVWF   TXMessBuff_D2,Banked
    MOVLW   0x00				;Byte 3			    
    MOVWF   TXMessBuff_D3,Banked
    MOVLW   0x00				;Byte 4		    
    MOVWF   TXMessBuff_D4,Banked
    MOVLW   0x00				;Byte 5			    
    MOVWF   TXMessBuff_D5,Banked
    MOVLW   0x00				;Byte 6			
    MOVWF   TXMessBuff_D6,Banked
    MOVLW   0x00				;Byte 7			    
    MOVWF   TXMessBuff_D7,Banked
    MOVLW   0x08				;DLC - 8 bytes			  
    MOVWF   TXMessBuff_DL,Banked
;
    MOVLW   08H					;Load SID2:SID0, EXIDE = 1
    MOVWF   TXMessBuff_SL,Banked
    MOVLW   00H					;Load SID10:SID3, EID17:EID16
    MOVWF   TXMessBuff_SH,Banked		;Load EID15:EID8
    MOVFF   Folder_3H,TXMessBuff_EH		;Load EID7:EID0
    MOVFF   Folder_3L,TXMessBuff_EL		;Load EID7:EID0
;    
    CALL    Send_Message
    RETURN
;
#IFDEF  FLOWCONTROLDEVICE
Send_Flow_rate:
;
    MOVFF   Folder_1L,TXMessBuff_D0		;Byte 0 - Device ID
    MOVLW   0x00				;Byte 1	- Page 0
    MOVWF   TXMessBuff_D1,Banked
;
    ;MOVFF   PulseProcessVariable,TXMessBuff_D2  ;Byte 2 - Flow rate low byte
    ;MOVFF   PulseProcessVariableH,TXMessBuff_D3 ;Byte 3 - Flow rate high byte
    MOVFF   PulseAdjusted,TXMessBuff_D2  ;Byte 2 - Flow rate low byte
    MOVFF   PulseAdjustedH,TXMessBuff_D3 ;Byte 3 - Flow rate high byte
;
    MOVLW   0x00				;Byte 4	- Device flags
    MOVWF   TXMessBuff_D4,Banked		;Clear byte	
;
SendFlowError_:
;
;    BTFSC   ErrorBit
;    GOTO    SendFlowEngage_
;
;    MOVLW   0x01
;    IORWF   TXMessBuff_D4,Same,Banked
;
SendFlowEngage_:
;
    BTFSC   ControlFlow
    GOTO    SendFlowWaterSensor
;
    MOVLW   0x02
    IORWF   TXMessBuff_D4,Same,Banked
;
SendFlowWaterSensor:
;
    BTFSC   WaterSensor
    GOTO    SendAmpMeter
;
    MOVLW   0x80
    IORWF   TXMessBuff_D4,Same,Banked
;
SendAmpMeter:
;
    BTFSS   AmpFlag
    GOTO    SendFlowVoltage
;
    MOVLW   0x40
    IORWF   TXMessBuff_D4,Same,Banked
;
SendFlowVoltage:
;
    MOVFF   SetError,TXMessBuff_D5
    MOVFF   VoltReading,TXMessBuff_D7		;Byte 7 - Volt reading
;
SendFlowCalib:
;
    CLRF   TXMessBuff_D5,Banked			;Byte 5	- Calibration flags - Clear byte
;
SendFlowCalib_I:
;
    BTFSS   IncCalibBit
    GOTO    SendFlowCalib_D
    MOVLW   0x02
    IORWF   TXMessBuff_D5,Same,Banked
;
SendFlowCalib_D:
;
    BTFSS   DecCalibBit
    GOTO    SendFlowDLCBytes
    MOVLW   0x01
    IORWF   TXMessBuff_D5,Same,Banked
;
SendFlowDLCBytes:
;
    MOVLW   0x08				;DLC - 8 bytes			  
    MOVWF   TXMessBuff_DL,Banked
;
    MOVLW   08H					;Load SID2:SID0, EXIDE = 1
    MOVWF   TXMessBuff_SL,Banked
    MOVLW   00H					;Load SID10:SID3, EID17:EID16
    MOVWF   TXMessBuff_SH,Banked		;Load EID15:EID8
    MOVFF   Folder_7H,TXMessBuff_EH		;Load EID7:EID0
    MOVFF   Folder_7L,TXMessBuff_EL		;Load EID7:EID0
;    
    CALL    Send_Message
;    
    RETURN
;
#endif
;
#IFDEF  GRANCONTROLDEVICE
Send_Flow_rate:
;
    MOVFF   Folder_1L,TXMessBuff_D0		;Byte 0 - Device ID
    MOVLW   0x00				;Byte 1	- Page 0
    MOVWF   TXMessBuff_D1,Banked
;
    MOVFF   gpm,TXMessBuff_D2  ;Byte 2 - Flow rate low byte
    MOVFF   gpmH,TXMessBuff_D3 ;Byte 3 - Flow rate high byte
;
    MOVLW   0x00				;Byte 4	- Device flags
    MOVWF   TXMessBuff_D4,Banked		;Clear byte	
;
SendFlowError_:
;
;    BTFSC   ErrorBit
;    GOTO    SendFlowEngage_
;
;    MOVLW   0x01
;    IORWF   TXMessBuff_D4,Same,Banked
;
SendFlowEngage_:
;
    BTFSC   ControlFlow
    GOTO    SendFlowWaterSensor
;
    MOVLW   0x02
    IORWF   TXMessBuff_D4,Same,Banked
;
SendFlowWaterSensor:
;
    BTFSC   WaterSensor
    GOTO    SendFlowVoltage
;
    MOVLW   0x80
    IORWF   TXMessBuff_D4,Same,Banked
;
SendFlowVoltage:
;
    MOVFF   SetError,TXMessBuff_D5
    MOVFF   VoltReading,TXMessBuff_D7		;Byte 7 - Volt reading
    
    MOVLW   0x08				;DLC - 8 bytes			  
    MOVWF   TXMessBuff_DL,Banked
;
    MOVLW   08H					;Load SID2:SID0, EXIDE = 1
    MOVWF   TXMessBuff_SL,Banked
    MOVLW   00H					;Load SID10:SID3, EID17:EID16
    MOVWF   TXMessBuff_SH,Banked		;Load EID15:EID8
    MOVFF   Folder_7H,TXMessBuff_EH		;Load EID7:EID0
    MOVFF   Folder_7L,TXMessBuff_EL		;Load EID7:EID0
;    
    CALL    Send_Message
;    
    RETURN
;
#endif
;
Send_Engaged_Status:
;
    TSTFSZ  Folder_7L
    GOTO    Send_Engaged_Status_Content
    TSTFSZ  Folder_7H
    GOTO    Send_Engaged_Status_Content
    RETURN
;
Send_Engaged_Status_Content:
;
    MOVFF   Folder_1L,TXMessBuff_D0		;Byte 0 - Device ID		
    MOVLW   0x00				;Byte 1	- Page 0
    MOVWF   TXMessBuff_D1,Banked	
    MOVFF   AnalogueL,TXMessBuff_D2		;Byte 2	- AnalogueL
    ;MOVFF   AnalogueT,TXMessBuff_D2		;Byte 2	- AnalogueT
    
    MOVFF   AnalogueH,TXMessBuff_D3		;Byte 3	- AnalogueH
#IFDEF  FLOWCONTROLDEVICE
    BTFSS   EngageBit
    MOVLW   0x0E				;Byte 4 - System is engaged
    BTFSC   EngageBit
    MOVLW   0x0C				;Byte 4 - System is not engaged
#else
;
#IFDEF  GRANCONTROLDEVICE
    BTFSS   ControlFlow
    MOVLW   0x0E				;Byte 4 - System is engaged
    BTFSC   ControlFlow
    MOVLW   0x0C				;Byte 4 - System is not engaged
#else
    MOVLW   0x0C				;Byte 4 - System is not engaged
#endif
#endif
;
    BTFSS   WaterSensor
    IORLW   b'10000000'
;
#IFDEF  FLOWCONTROLDEVICE
    BTFSC   AmpFlag
    IORLW   b'01000000'
#endif
;
    MOVWF   TXMessBuff_D4,Banked	 
    MOVFF   PulseProcessVariable,TXMessBuff_D5	;Byte 5	- Pulse Interval		   
    MOVFF   PulseProcessVariableH,TXMessBuff_D6	;Byte 6 - Pulse Interval High
;
#ifdef VOLTAGE_METER
    MOVFF   VoltReading,TXMessBuff_D7		;Byte 7 - Volt reading
#else
    MOVLW   0x00				;
    MOVWF   TXMessBuff_D7			;Byte 7
#endif
;
    MOVLW   0x08				;DLC - 8 bytes			  
    MOVWF   TXMessBuff_DL,Banked
;
    MOVLW   08H					;Load SID2:SID0, EXIDE = 1
    MOVWF   TXMessBuff_SL,Banked
    MOVLW   00H					;Load SID10:SID3, EID17:EID16
    MOVWF   TXMessBuff_SH,Banked		;Load EID15:EID8
    MOVFF   Folder_7H,TXMessBuff_EH		;Load EID7:EID0
    MOVFF   Folder_7L,TXMessBuff_EL		;Load EID7:EID0
;    
    CALL    Send_Message
;
    RETURN 
;
#IFDEF  HYDDRIVEDEVICE
Send_Flow_rate:
;
    MOVFF   Folder_1L,TXMessBuff_D0		;Byte 0 - Device ID
    MOVLW   0x00				;Byte 1	- Page 0
    MOVWF   TXMessBuff_D1,Banked
;
    MOVFF   PulseProcessVariable,TXMessBuff_D2	;Byte 2 - Flow rate low byte
    MOVFF   PulseProcessVariableH,TXMessBuff_D3	;Byte 3 - Flow rate high byte	
;
    MOVLW   0x00				;Byte 4	- Device flags
    MOVWF   TXMessBuff_D4,Banked		;Clear byte
;
SendFlowWaterSensor:
;
    BTFSC   WaterSensor
    GOTO    SendVoltMeter
;
    MOVLW   0x80
    IORWF   TXMessBuff_D4,Same,Banked
;
SendVoltMeter:
;
#ifdef VOLTAGE_METER
    MOVFF   VoltReading,TXMessBuff_D7
#endif
;
SendAmpMeter:
;
#ifdef AMPERE_METER
    BTFSS   AmpFlag
    GOTO    SendFlowError
;
    MOVLW   0x40
    IORWF   TXMessBuff_D4,Same,Banked
#endif
;
SendFlowError:
;
    MOVLW   0x08				;DLC - 8 bytes			  
    MOVWF   TXMessBuff_DL,Banked
;
    MOVLW   08H					;Load SID2:SID0, EXIDE = 1
    MOVWF   TXMessBuff_SL,Banked
    MOVLW   00H					;Load SID10:SID3, EID17:EID16
    MOVWF   TXMessBuff_SH,Banked		;Load EID15:EID8
    MOVFF   Folder_7H,TXMessBuff_EH		;Load EID7:EID0
    MOVFF   Folder_7L,TXMessBuff_EL		;Load EID7:EID0
;    
    CALL    Send_Message
;    
    RETURN 
#ENDIF
;		
Send_Mayors:
;
    MOVLW   0x00				;Byte 0
    MOVWF   TXMessBuff_D0,Banked
    MOVLW   0x01				;Byte 1	- Page 1
    MOVWF   TXMessBuff_D1,Banked
    MOVFF   DeviceID_0,TXMessBuff_D2		;Byte 2 - Device ID byte 0
    MOVFF   DeviceID_1,TXMessBuff_D3		;Byte 3 - Device ID byte 1
    MOVFF   DeviceID_2,TXMessBuff_D4		;Byte 4 - Device ID byte 2
    MOVFF   DeviceID_3,TXMessBuff_D5		;Byte 5 - Device ID byte 3
    MOVFF   DeviceID_4,TXMessBuff_D6		;Byte 6 - Device ID byte 4
    MOVLW   0x00				;Byte 7
    MOVWF   TXMessBuff_D7,Banked		
    MOVLW   0x08				;DLC - 8 bytes
    MOVWF   TXMessBuff_DL,Banked
;
    MOVLW   08H					;Load SID2:SID0, EXIDE = 1
    MOVWF   TXMessBuff_SL,Banked
    MOVLW   00H					;Load SID10:SID3, EID17:EID16
    MOVWF   TXMessBuff_SH,Banked
    MOVFF   Folder_1L,TXMessBuff_EL		;Load EID7:EID0
    MOVFF   Folder_1H,TXMessBuff_EH		;Load EID15:EID8
;
    CALL    Send_Message
;
    RETURN
;
Send_ADRH:
;
    MOVFF   Folder_6L,TXMessBuff_D0
    MOVFF   Folder_6H,TXMessBuff_D1
    MOVFF   Folder_7L,TXMessBuff_D2
    MOVFF   Folder_7H,TXMessBuff_D3
    MOVFF   RXMessBuff_D6,TXMessBuff_D4
    MOVLW   0xBB
    MOVFF   WREG,TXMessBuff_D5
    MOVFF   WREG,TXMessBuff_D6
    MOVFF   WREG,TXMessBuff_D7

    MOVLW   0x08				;DLC - 8 bytes
    MOVWF   TXMessBuff_DL,Banked
;
    MOVLW   08H					;Load SID2:SID0, EXIDE = 1
    MOVWF   TXMessBuff_SL,Banked
    MOVLW   00H					;Load SID10:SID3, EID17:EID16
    MOVWF   TXMessBuff_SH,Banked
    MOVLW   0x64
    MOVWF   TXMessBuff_EL			;Load EID7:EID0
    MOVLW   0x00
    MOVWF   TXMessBuff_EH			;Load EID7:EID0
;
    CALL    Send_Message
;
    RETURN
;
;*******************************************************************************
;*
;*  Boot-loader
;*
;*******************************************************************************
;
;   Read in the block of data from FLASH
;
    ORG     BOOTLOADER_ORIGIN
;
;*******************************************************************************
;*  Initialisation
;*******************************************************************************
;
Boot_init:
;
    BCF	    BootModeBit
;
    RETURN
;
;*******************************************************************************
;*  Bootloader
;*******************************************************************************
;
Startup:
;
    MOVLW   EE_BootFlags			;Device config flags
    CALL    BootReadInternalEEPROM
    MOVWF   BootFlags, Banked
    BTFSS   BootModeBit
    GOTO    Begin
    BSF	    RedLED
;
;There is an issue with the bootloader the system has reset without
Closed_Loop:
;
    CALL    CANInterrupts
    GOTO    Closed_Loop
;
;*******************************************************************************
;*  Start bootloader update session
;*******************************************************************************
;
Start_Bootload:
;
    MOVLW   SIZE_OF_BLOCK			;number of bytes in erase block
    MOVWF   Counter
;
    MOVLW   CODE_ADD_UPPER_DEF
    MOVWF   TBLPTRU, Access
    MOVWF   CodeAddressUpper,Banked
    MOVWF   EraseAddressUpper,Banked
;
    MOVLW   CODE_ADD_HIGH_DEF
    MOVWF   TBLPTRH, Access
    MOVWF   CodeAddressHigh,Banked
    MOVWF   EraseAddressHigh,Banked
;
    MOVLW   CODE_ADD_LOW_DEF
    MOVWF   TBLPTRL, Access
    MOVWF   CodeAddressLow,Banked
    MOVWF   EraseAddressLow,Banked
;
    MOVLW   0x02				;Data memory is in second bank
    MOVWF   DataAddressHigh,Banked
;
    CALL    SETUP_READ_BLOCK
;
    RETURN
;
;*******************************************************************************
;*  Update next line of code
;*******************************************************************************
;
CheckNextBootCodeLine:
;
    MOVF    TBLPTRU, W, Access
    XORWF   CodeAddressUpper, W, Banked
    BTFSS   ZeroFlag
    CALL    ChangeBootBlock
;
    MOVF    TBLPTRH, W, Access
    XORWF   CodeAddressHigh, W, Banked
    BTFSS   ZeroFlag
    CALL    ChangeBootBlock
;
    MOVF    TBLPTRL, W, Access
    XORWF   CodeAddressLow, W, Banked
    ANDLW   b'11000000'
    BTFSS   ZeroFlag
    CALL    ChangeBootBlock
;
    CALL    ModifyWord
;
    RETURN
;
;*******************************************************************************
;*  Change program block
;*******************************************************************************
;
ChangeBootBlock:
;
    CALL    ERASE_BLOCK
    CALL    SETUP_READ_BLOCK
;
    RETURN
;
SETUP_READ_BLOCK:
;
    MOVLW   SIZE_OF_BLOCK			;number of bytes in erase block
    MOVWF   Counter,Banked
;
    MOVLW   BUFFER_ADDR_HIGH			;point to buffer with address counter register
    MOVWF   FSR0H,Access
    MOVLW   BUFFER_ADDR_LOW
    MOVWF   FSR0L,Access
;
    MOVF    CodeAddressUpper, W, Banked		;Load TBLPTR with the base
    MOVWF   TBLPTRU, Access			;address of the memory block
    MOVF    CodeAddressHigh, W, Banked
    MOVWF   TBLPTRH, Access
    MOVF    CodeAddressLow, W, Banked
    MOVWF   TBLPTRL, Access
;
READ_BLOCK:
;
    TBLRD*+					;read into TABLAT, and inc
    MOVF    TABLAT, W, Access			;get data
    MOVWF   POSTINC0, Access			;store data
    DECFSZ  Counter, Same, Banked		;done?
    BRA	    READ_BLOCK				;repeat
;
RESET_READ_ADDRESS:
;
    MOVF    CodeAddressUpper, W, Banked		;Load TBLPTR with the base
    MOVFF   CodeAddressUpper, EraseAddressUpper
    MOVWF   TBLPTRU, Access			;address of the memory block
    MOVF    CodeAddressHigh, W, Banked
    MOVFF   CodeAddressHigh, EraseAddressHigh
    MOVWF   TBLPTRH, Access
    MOVF    CodeAddressLow, W, Banked
    MOVFF   CodeAddressLow, EraseAddressLow
    MOVWF   TBLPTRL, Access
;
    RETURN
;
ModifyWord:
;
    MOVF    DataAddressHigh, W, Banked		;point to buffer
    MOVWF   FSR0H, Access
    MOVF    DataAddressLow, W, Banked
    MOVWF   FSR0L, Access
    MOVF    NewDataLow, W, Banked		;update buffer word
    MOVWF   POSTINC0, Access
    MOVF    NewDataHigh, W, Banked
    MOVWF   INDF0, Access
    BSF	    BootNewData			;Indicate new data
;
    RETURN
;
ERASE_BLOCK:
;
    MOVF    EraseAddressUpper, W, Banked		;load TBLPTR with the base
    MOVWF   TBLPTRU, Access			;address of the memory block
    MOVF    EraseAddressHigh, W, Banked
    MOVWF   TBLPTRH, Access
    MOVF    EraseAddressLow, W, Banked
    MOVWF   TBLPTRL, Access
    BSF	    EECON1, EEPGD			;point to Flash program memory
    BCF	    EECON1, CFGS			;access Flash program memory
    BSF	    EECON1, WREN			;enable write to memory
    BSF	    EECON1, FREE			;enable Row Erase operation
    MOVLW   55h
    MOVWF   EECON2, Access			;write 55h
    MOVLW   0AAh
    MOVWF   EECON2, Access			;write 0AAh
    BSF	    EECON1, WR				;start erase (CPU stall)
    TBLRD*-					;dummy read decrement
    
    MOVLW   BUFFER_ADDR_HIGH			;point to buffer
    MOVWF   FSR0H, Access
    MOVLW   BUFFER_ADDR_LOW
    MOVWF   FSR0L, Access
;
WRITE_BUFFER_BACK:
;
    ;MOVF    EraseAddressUpper, W, Banked	;load TBLPTR with the base
    ;MOVWF   TBLPTRU, Access			;address of the memory block
    ;MOVF    EraseAddressHigh, W, Banked
    ;MOVWF   TBLPTRH, Access
    ;MOVF    EraseAddressLow, W, Banked
    ;MOVWF   TBLPTRL, Access
    
    MOVLW   SIZE_OF_BLOCK			;number of bytes in holding register
    MOVWF   Counter, Banked
;
WRITE_BYTE_TO_HREGS:
;
    MOVFF   POSTINC0, WREG			;get low byte of buffer data
    MOVWF   TABLAT, Access			;present data to table latch
    TBLWT+*					;write data, perform a short write
						;to internal TBLWT holding register.
    DECFSZ  Counter, Same, Banked		;loop until buffers are full
    BRA	    WRITE_BYTE_TO_HREGS
;	      
PROGRAM_MEMORY:
;
    MOVF    EraseAddressUpper, W, Banked		;load TBLPTR with the base
    MOVWF   TBLPTRU, Access			;address of the memory block
    MOVF    EraseAddressHigh, W, Banked
    MOVWF   TBLPTRH, Access
    MOVF    EraseAddressLow, W, Banked
    MOVWF   TBLPTRL, Access
;
    BSF	    EECON1, EEPGD			;point to Flash program memory
    BCF	    EECON1, CFGS			;access Flash program memory
    BSF	    EECON1, WREN			;enable write to memory
    MOVLW   55h
    MOVWF   EECON2, Access			;write 55h
    MOVLW   0AAh
    MOVWF   EECON2, Access			;write 0AAh
    BSF	    EECON1, WR				;start program (CPU stall)
    BCF	    EECON1, WREN			;disable write to memory
;
    BCF	    BootNewData			;Indicate no new data
;
    RETURN
;
SETUP_READ_BLOCK_A:
;
    MOVLW   SIZE_OF_BLOCK			;number of bytes in erase block
    MOVWF   Counter,Banked
;
    MOVLW   BUFFER_ADDR_HIGH			;point to buffer with address counter register
    MOVWF   FSR0H,Access
    MOVLW   BUFFER_ADDR_LOW
    MOVWF   FSR0L,Access
;
    MOVLW   0x00				;Load TBLPTR with the base
    MOVWF   TBLPTRU, Access			;address of the memory block
    MOVLW   0x00				;Load TBLPTR with the base
    MOVWF   TBLPTRH, Access
    MOVLW   0x00				;Load TBLPTR with the base
    MOVWF   TBLPTRL, Access
;
READ_BLOCK_A:
;
    TBLRD*+					;read into TABLAT, and inc
    MOVF    TABLAT, W, Access			;get data
    MOVWF   POSTINC0, Access			;store data
    DECFSZ  Counter, Same, Banked		;done?
    BRA	    READ_BLOCK_A			;repeat
;
    NOP
    RETURN
;
    
Check_if_Boot_Done:
    
    MOVF    CodeAddressUpper, W, Banked
    SUBLW   0x7F
    BTFSS   ZeroFlag
    GOTO    Boot_Exit
;
    MOVF    CodeAddressHigh, W, Banked
    SUBLW   0x3F
    BTFSS   ZeroFlag
    GOTO    Boot_Exit
;
Boot_Exit:
;
    RETURN
;
;*******************************************************************************
;*  CANBus bootloader code
;*******************************************************************************
;
#ifdef CANBUS
;
CANBus_init:
CANBus_Init_Basic:    
;
    BANKSEL PMD2				;Select proper bank
    BCF	    PMD2, 2, Banked			;Enable ECAN module
    MOVLW   0x00				;CAN Legacy Mode (Mode 0)
    MOVWF   ECANCON,Access
    MOVLW   0x80				;Request CONFIG Mode
    MOVWF   CANCON,Access
;	
CANBus_Init_Ports:    
;
CANBus_Init_Wait_for_config:
;
    MOVF    CANSTAT,W,Access			;Wait until module in Config mode
    ANDLW   b'11100000'				;Use only upper 3 bits
    XORLW   B'10000000'				;XOR with config mode bits
    TSTFSZ  WREG				;Is it Config mode yet?
    GOTO    CANBus_Init_Wait_for_config		;If not then repeat else continue
;
CANBus_Init_TXBnCON:
;
    MOVLW   0x21				;OUTPUT CANTX, drive Vdd, Oscilator as clock source
    MOVWF   CIOCON,Access
;
CANBus_Init_Filters:
;   
    BANKSEL RXFCON0
    CLRF    RXFCON0,Banked			;No Filters Enabled
    CLRF    RXFCON1,Banked			;No Filters Enabled
    CLRF    MSEL0,Banked			;Acceptance Mask 0
    CLRF    MSEL1,Banked			;Acceptance Mask 1
    CLRF    MSEL2,Banked			;Acceptance Mask 2
    CLRF    MSEL3,Banked			;Acceptance Mask 3
;
    ;RX Buffer 0
    BANKSEL RXF0SIDH				;Select proper bank
    MOVLW   0x00
    MOVWF   RXF0SIDH,Banked			;Filter SID = 0
    MOVLW   0x08			    
    MOVWF   RXF0SIDL,Banked			;Extended message and SID = 0
;
    CLRF    RXF0EIDH,Banked			;Filter EID = 0
    CLRF    RXF0EIDL,Banked			;Filter EID = 0
;		
    CLRF    RXM0SIDH,Banked			;MASK SID = 0
    MOVLW   0x08			    
    MOVWF   RXM0SIDL,Banked			;Extended message and SID = 0
;
    CLRF    RXM0EIDH,Banked			;Mask EID = 0
    CLRF    RXM0EIDL,Banked			;Mask EID = 0
;
    BCF	    RXB0CON,6,Access			;Do not filter any messages
    BCF	    RXB0CON,5,Access			;Do not filter any messages
    BSF	    RXB0CON,2,Access			;Overflow goes to Receive buffer 1
;
    ;RX Buffer 1
    MOVLW   0x00
    MOVWF   RXF1SIDH,Banked			;Filter SID = 0
    MOVLW   0x08			    
    MOVWF   RXF1SIDL,Banked			;Extended message and SID = 0
;
    CLRF    RXF1EIDH,Banked			;Filter EID = 0
    CLRF    RXF1EIDL,Banked			;Filter EID = 0
;		
    CLRF    RXM1SIDH,Banked			;MASK SID = 0
    MOVLW   0x08			    
    MOVWF   RXM1SIDL,Banked			;Extended message and SID = 0
;
    CLRF    RXM1EIDH,Banked			;Mask EID = 0
    CLRF    RXM1EIDL,Banked			;Mask EID = 0
;
    BCF	    RXB1CON,6,Access			;Do not filter any messages
    BCF	    RXB1CON,5,Access			;Do not filter any messages
;
CANBus_Init_Clock:
;
    BANKSEL BRGCON1				;Select proper bank
    MOVLW   BRP_Setup				;Set SJW and BRP bits    
    MOVWF   BRGCON1	    
    MOVLW   SEG1_Setup				;Set Segment sizes
    MOVWF   BRGCON2
    MOVLW   SEG2_Setup		
    MOVWF   BRGCON3
;
CANBus_Init_Buffer:
;
    BANKSEL TXBIE				;Select proper bank
    MOVLW   0xFF				;TXI0-2 Enabled (RX already enabled)
    MOVWF   TXBIE,Banked
;
CANBus_Init_Interrupts: 
;
    MOVLW   0xFF				;Enable all CANBus interrupts 
    MOVWF   PIE5,Access
    BSF	    IPR5,0,Access			;RXB0IF is high priority
    BSF	    IPR5,1,Access			;RXB1IF is high priority
    BSF	    IPR5,2,Access			;TXB0IF is high priority
    BSF	    IPR5,3,Access			;TXB1IF is high priority
    BSF	    IPR5,4,Access			;TXB2IF is high priority
    BSF	    IPR5,5,Access			;ERRIF is high priority
    BSF	    IPR5,6,Access			;WAKIF is high priority
    BSF	    IPR5,7,Access			;IRXIF is high priority
;
CANBus_Init_Normal_Mode:
;
    MOVLW   0x00				;Request NORMAL Mode
    MOVWF   CANCON,Access
;
CANBus_Init_Wait_for_normal:
;
    MOVF    CANSTAT, W, Access			;Read current mode state.
    ANDLW   B'11100000'				;Interested in OPMODE bits only.
    XORLW   B'00000000'				;Use 0 to match
    TSTFSZ  WREG				;Is it Normal mode yet?    
    GOTO    CANBus_Init_Wait_for_normal		;No. Continue to wait...
;
CANBus_Init_Reset_Variables:
;
    CALL    Reset_Variables			;Reset all CANBus variables
    CALL    Reset_Counters			;Reset all CANBus counters
    CALL    Reset_Default_values		;Reset all CANBus default values
;
    BANKSEL DefaultMemoryStart
    CALL    LoadVariablesFromEEPROM		;Load variables from EEPROM
;
    ;Other Init
CANBus_Init_Other:
;
    GOTO    CANBus_Init_Reset_Variables_Exit
;
    ;Other functions
;
CANBus_Init_Reset_Variables_Exit:
;
    BANKSEL DefaultMemoryStart
    RETURN
;
Reset_Counters:
;
    BANKSEL TXERRCNT				;Select proper bank
    CLRF    TXERRCNT,Banked			;Reset TX Error Counter	
    CLRF    RXERRCNT,Banked			;Reset RX Error Counter
    RETURN
;
Reset_Variables:
;
    BANKSEL DefaultMemoryStart
    CLRF    Folder_1L,Banked			;Reset Mayor's Folder Envelope
    CLRF    Folder_1H,Banked
    MOVLW   0x03
    MOVWF   Folder_2L,Banked			;Reset Configuration RX Envelope
    CLRF    Folder_2H,Banked
    MOVLW   0x03
    MOVWF   Folder_3L,Banked			;Reset Configuration TX Envelope
    CLRF    Folder_3H,Banked
    MOVLW   0x04
    MOVWF   Folder_4L,Banked			;Reset Boot-loader RX Envelope
    CLRF    Folder_4H,Banked
    MOVLW   0x04
    MOVWF   Folder_5L,Banked			;Reset Boot-loader TX Envelope
    CLRF    Folder_5H,Banked
    CLRF    Folder_6L,Banked			;Reset Flow Control RX Envelope
    CLRF    Folder_6H,Banked
    CLRF    Folder_7L,Banked			;Reset Flow Control TX Envelope
    CLRF    Folder_7H,Banked
    RETURN
;		
Reset_Default_values:
;
    BANKSEL DefaultMemoryStart
    MOVLW   0x00				;Default flow rate value
    MOVWF   FlowRateH,Banked
    MOVLW   d'250'			    
    MOVWF   FlowRateL,Banked
    MOVLW   DeviceIDDefault			;Index according to the Device ID
    MOVWF   DeviceID,Banked
    MOVLW   0x00				;Reset Config flags
    MOVWF   ConfigFlags
    BCF	    SentEngagedBit
    BCF	    ConfigModeBit
;
    RETURN
;
;*******************************************************************************
;*		
;*  CANBus Message Handler
;*
;*******************************************************************************
;
Send_Message:
Send_Message_Buf0:
;
    BANKSEL TXB0CON				;Select proper bank
    BTFSC   TXB0CON,3,Banked			;Check if TX Buffer 0 available
    GOTO    Send_Message_Buf1			;Else goto next buffer
;
    MOVFF   TXMessBuff_D0,TXB0D0		;Load data byte 0 into buffer
    MOVFF   TXMessBuff_D1,TXB0D1		;Load data byte 1 into buffer
    MOVFF   TXMessBuff_D2,TXB0D2		;Load data byte 2 into buffer
    MOVFF   TXMessBuff_D3,TXB0D3		;Load data byte 3 into buffer
    MOVFF   TXMessBuff_D4,TXB0D4		;Load data byte 4 into buffer
    MOVFF   TXMessBuff_D5,TXB0D5		;Load data byte 5 into buffer
    MOVFF   TXMessBuff_D6,TXB0D6		;Load data byte 6 into buffer
    MOVFF   TXMessBuff_D7,TXB0D7		;Load data byte 7 into buffer
    MOVFF   TXMessBuff_DL,TXB0DLC		;Load data DLC byte into buffer
    MOVFF   TXMessBuff_SL,TXB0SIDL		;Load data SIDL byte into buffer
    MOVFF   TXMessBuff_SH,TXB0SIDH		;Load data SIDH byte into buffer
    MOVFF   TXMessBuff_EL,TXB0EIDL		;Load data EIDL byte into buffer
    MOVFF   TXMessBuff_EH,TXB0EIDH		;Load data EIDH byte into buffer

    MOVLW   B'00001000'				;Normal priority; Request transmission
    MOVWF   TXB0CON,Banked
    GOTO    Send_Message_Exit			;Exit
;		
Send_Message_Buf1:
;
    BANKSEL TXB1CON				;Select proper bank
    BTFSC   TXB1CON,3,Banked			;Check if TX Buffer 0 available
    GOTO    Send_Message_Buf2			;Else goto next buffer
;
    MOVFF   TXMessBuff_D0,TXB1D0		;Load data byte 0 into buffer
    MOVFF   TXMessBuff_D1,TXB1D1		;Load data byte 1 into buffer
    MOVFF   TXMessBuff_D2,TXB1D2		;Load data byte 2 into buffer
    MOVFF   TXMessBuff_D3,TXB1D3		;Load data byte 3 into buffer
    MOVFF   TXMessBuff_D4,TXB1D4		;Load data byte 4 into buffer
    MOVFF   TXMessBuff_D5,TXB1D5		;Load data byte 5 into buffer
    MOVFF   TXMessBuff_D6,TXB1D6		;Load data byte 6 into buffer
    MOVFF   TXMessBuff_D7,TXB1D7		;Load data byte 7 into buffer
    MOVFF   TXMessBuff_DL,TXB1DLC		;Load data DLC byte into buffer
    MOVFF   TXMessBuff_SL,TXB1SIDL		;Load data SIDL byte into buffer
    MOVFF   TXMessBuff_SH,TXB1SIDH		;Load data SIDH byte into buffer
    MOVFF   TXMessBuff_EL,TXB1EIDL		;Load data EIDL byte into buffer
    MOVFF   TXMessBuff_EH,TXB1EIDH		;Load data EIDH byte into buffer

    MOVLW   B'00001000'				;Normal priority; Request transmission
    MOVWF   TXB1CON,Banked
    GOTO    Send_Message_Exit			;Exit
;
Send_Message_Buf2:
;
    BANKSEL TXB2CON				;Select proper bank
    BTFSC   TXB2CON,3,Banked			;Check if TX Buffer 0 available
    GOTO    Send_Message_Full			;Else goto next buffer
;
    MOVFF   TXMessBuff_D0,TXB2D0		;Load data byte 0 into buffer
    MOVFF   TXMessBuff_D1,TXB2D1		;Load data byte 1 into buffer
    MOVFF   TXMessBuff_D2,TXB2D2		;Load data byte 2 into buffer
    MOVFF   TXMessBuff_D3,TXB2D3		;Load data byte 3 into buffer
    MOVFF   TXMessBuff_D4,TXB2D4		;Load data byte 4 into buffer
    MOVFF   TXMessBuff_D5,TXB2D5		;Load data byte 5 into buffer
    MOVFF   TXMessBuff_D6,TXB2D6		;Load data byte 6 into buffer
    MOVFF   TXMessBuff_D7,TXB2D7		;Load data byte 7 into buffer
    MOVFF   TXMessBuff_DL,TXB2DLC		;Load data DLC byte into buffer
    MOVFF   TXMessBuff_SL,TXB2SIDL		;Load data SIDL byte into buffer
    MOVFF   TXMessBuff_SH,TXB2SIDH		;Load data SIDH byte into buffer
    MOVFF   TXMessBuff_EL,TXB2EIDL		;Load data EIDL byte into buffer
    MOVFF   TXMessBuff_EH,TXB2EIDH		;Load data EIDH byte into buffer
;
    MOVLW   B'00001000'				;Normal priority; Request transmission
    MOVWF   TXB2CON,Banked
    GOTO    Send_Message_Exit			;Exit
;
Send_Message_Full:
;
						;Put an error handler here
;
Send_Message_Exit:
;
    BANKSEL DefaultMemoryStart
    RETURN
;
CANInterrupts:
;
    MOVFF   CANCON, TempCANCON			; Save CANCON.WIN bits
						; This is required to prevent CANCON
						; from corrupting CAN buffer access
						; in-progress while this interrupt
						; occurred
    MOVFF   CANSTAT, TempCANSTAT		; Save CANSTAT register
						; This is required to make sure that
						; we use same CANSTAT value rather
						; than one changed by another CAN
						; interrupt.    
    MOVF    TempCANSTAT, W, Banked		;Retrieve ICODE bits
    ANDLW   B'00001110'
    RRNCF   WREG,W,Access			;Rotate 1 bit to the right
    
    BTFSC   ZeroFlag
    GOTO    NoInterrupt				;000 = No interrupt
    DCFSNZ  WREG,W,Access
    GOTO    ErrorInterrupt			;001 = Error interrupt
    DCFSNZ  WREG,W,Access
    GOTO    TXB2Interrupt			;010 = TXB2 interrupt
    DCFSNZ  WREG,W,Access
    GOTO    TXB1Interrupt			;011 = TXB1 interrupt
    DCFSNZ  WREG,W,Access
    GOTO    TXB0Interrupt			;100 = TXB0 interrupt
    DCFSNZ  WREG,W,Access
    GOTO    RXB1Interrupt			;101 = RXB1 interrupt
    DCFSNZ  WREG,W,Access
    GOTO    RXB0Interrupt			;110 = RXB0 interrupt
    DCFSNZ  WREG,W,Access
    GOTO    WakeupInterrupt			;111 = Wake-up on interrupt
;  
    GOTO    IntExit				;If error the goto exit
;
NoInterrupt:
;		
    GOTO    IntExit				;Do nothing
;
ErrorInterrupt:
;
    BTFSC   Overflow1_bit			;If overflow occurd
    CALL    OverflowHandler			;Then handle overflow error
    BCF	    Overflow1_bit			;Clear overflow interrupt 1
;
    BTFSC   Overflow0_bit			;If overflow occurd
    CALL    OverflowHandler			;Then handle overflow error
    BCF	    Overflow0_bit			;Clear overflow interrupt 0
;
    BTFSC   CANBusError_bit			;If error occurd
    CALL    GeneralErrorHandler			;Then handle error
    BCF	    CANBusError_bit			;Clear error interrupt
;
    BTFSC   InvalidMessage_bit			;If invalid message occurd
    CALL    InvalidMessageHandler		;Then handle invalid message
    BCF	    InvalidMessage_bit			;Clear invalid interrupt
;
    GOTO    IntExit
;
TXB2Interrupt:
;   
    BCF	    TX2BufferIF				;Clear TX sent interrupt
    
    GOTO    IntExit
; 
TXB1Interrupt:
;
    BCF	    TX1BufferIF				;Clear TX sent interrupt
;
    GOTO    IntExit
; 
TXB0Interrupt:
;  
    BCF	    TX0BufferIF				;Clear TX sent interrupt
;
    GOTO    IntExit
; 
RXB1Interrupt:
;
    BANKSEL RXB1D0				;Select proper bank
    BCF	    RXB1CON,7,Banked			;Clear1 RXFUL bit
    BCF	    PIR5,1,Access			;Clear RX1 interrupt
;	    
    MOVFF   RXB1EIDH,RXMessBuff_EH		;Move RX buffer data to memory
    MOVFF   RXB1EIDL,RXMessBuff_EL
    MOVFF   RXB1SIDH,RXMessBuff_SH
    MOVFF   RXB1SIDL,RXMessBuff_SL
    MOVFF   RXB1D0,RXMessBuff_D0
    MOVFF   RXB1D1,RXMessBuff_D1
    MOVFF   RXB1D2,RXMessBuff_D2
    MOVFF   RXB1D3,RXMessBuff_D3
    MOVFF   RXB1D4,RXMessBuff_D4
    MOVFF   RXB1D5,RXMessBuff_D5
    MOVFF   RXB1D6,RXMessBuff_D6
    MOVFF   RXB1D7,RXMessBuff_D7
    MOVFF   RXB1DLC,RXMessBuff_DL
    BANKSEL DefaultMemoryStart
;
    CALL    CANKingdomRX_handler		;Call the CANKingdom protocol
;
    GOTO    IntExit
;	    
RXB0Interrupt:
;
    BCF	    RXB0CON,7,Access			;Clear1 RXFUL bit
    BCF	    PIR5,0,Access			;Clear RX0 interrupt
;	    
    MOVFF   RXB0EIDH,RXMessBuff_EH		;Move RX buffer data to memory
    MOVFF   RXB0EIDL,RXMessBuff_EL
    MOVFF   RXB0SIDH,RXMessBuff_SH
    MOVFF   RXB0SIDL,RXMessBuff_SL
    MOVFF   RXB0D0,RXMessBuff_D0
    MOVFF   RXB0D1,RXMessBuff_D1
    MOVFF   RXB0D2,RXMessBuff_D2
    MOVFF   RXB0D3,RXMessBuff_D3
    MOVFF   RXB0D4,RXMessBuff_D4
    MOVFF   RXB0D5,RXMessBuff_D5
    MOVFF   RXB0D6,RXMessBuff_D6
    MOVFF   RXB0D7,RXMessBuff_D7
    MOVFF   RXB0DLC,RXMessBuff_DL
;
    CALL    CANKingdomRX_handler		;Call the CANKingdom protocol
;
    GOTO    IntExit
;
WakeupInterrupt:
;	
    BCF	    WAKEIF_				;Clear wakeup interrupt flag
    GOTO    IntExit
;
IntExit:
;
    RETURN
;
OverflowHandler:
;
						;Handle overflow error here
    RETURN
;
GeneralErrorHandler:
;
						;Handle general error here
    RETURN
;
InvalidMessageHandler:
;
						;Handle invalid error here
    RETURN
;
;*******************************************************************************
;*		
;*  CANKingdom Implementation
;*
;*******************************************************************************
;*  Identifier lookup
;*******************************************************************************
;
CANKingdomRX_handler:
;
    BTFSC   BootModeBit				;Check if system in boot update mode
    GOTO    BootMessTest			;If so then go straight to bootloader
;
BootMessTest:
;
    MOVFF   RXMessBuff_EL,WREG			;Compare EIDL with Boot-loader ID
    XORWF   Folder_4L,W,Banked			;Boot-loader message identifier
    BTFSS   ZeroFlag				;Test if Zero
    GOTO    CANKingdomRX_extern_		;Else goto exit
;
    MOVFF   RXMessBuff_EH,WREG			;Compare EIDH with Boot-loader ID
    XORWF   Folder_4H,W,Banked			;Boot-loader message identifier
    BTFSS   ZeroFlag				;Test if Zero
    GOTO    CANKingdomRX_extern_		;Else goto exit
;
BootMess:
;
    MOVF    RXMessBuff_D1,W,Banked		;Check Message Page byte
    BTFSC   ZeroFlag				;Test if Zero
    GOTO    BootMess_0				;If true then goto BootMess_0
;
    DCFSNZ  WREG,W,Access			;Decrease and test if Zero
    GOTO    BootMess_1				;If true then goto BootMess_1
;
    GOTO    Undefined_Page_			;Else goto unidentified page handler
;
BootMess_0:					;Configure Flow Rate Unit
;
    MOVFF   RXMessBuff_D2,WREG			;Compare Device ID to received ID
    XORWF   DeviceID_4,W,Access			;
    BTFSS   ZeroFlag				;Test if true
    GOTO    MessExit_				;Go to exit
;
BootMess_Mode:					;Configure Flow Rate Unit
;
    MOVFF   RXMessBuff_D7,WREG			;Compare Boot bit flags
    ANDLW   b'00000001'				;Go into boot mode?
    BTFSC   ZeroFlag				;Test if true
    GOTO    BootMess_Reset			;Go to exit
;
    BSF	    BootModeBit				;Set device to boot mode
    EEPROM_Save EE_BootFlags,BootFlags
    BCF	    _GIEH				;disable interrupts
    CALL    Start_Bootload
;
BootMess_Reset:
;
    MOVFF   RXMessBuff_D7,WREG		;Compare Boot bit flags
    ANDLW   b'00000010'				;Reset device?
    BTFSC   ZeroFlag				;Test if true
;
    GOTO    MessExit_				;Else goto exit
;
    BTFSC   BootNewData
    CALL    ERASE_BLOCK				;Erase and save last block
    BCF	    BootModeBit				;Set device to boot mode
    EEPROM_Save EE_BootFlags,BootFlags
    RESET					;Reset device
;
    GOTO    MessExit_				;Else goto exit
;
BootMess_1:					;Save new program code
;
    BTFSS   BootModeBit				;If system is not in boot mode then exit
    GOTO    MessExit_
;
    MOVFF   RXMessBuff_D2,WREG			;Point to correct data memory address
    ANDLW   b'11000000'
    MOVWF   CodeAddressLow,Banked
    MOVFF   RXMessBuff_D3,CodeAddressHigh	;Move high address byte
    MOVFF   RXMessBuff_D4,CodeAddressUpper	;Move upper address byte
;
    MOVF    CodeAddressUpper, W, Banked		;Check if upper address byte is zero
    BTFSS   ZeroFlag
    GOTO    MessExit_
;
    MOVFF   CodeAddressHigh,WREG		;Check if high address byte over bootloader address limit
    SUBLW   HIGH(BOOTLOADER_ORIGIN)
    BTFSS   CarryFlag
    GOTO    MessExit_		
    BTFSS   ZeroFlag
    GOTO    BootMess_1_GetData
;
    MOVFF   CodeAddressLow,WREG			;Check if low address byte over bootloader address limit
    SUBLW   LOW(BOOTLOADER_ORIGIN)
    BTFSS   CarryFlag
    GOTO    MessExit_		
    BTFSC   ZeroFlag
    GOTO    MessExit_	
;
BootMess_1_GetData:
;
    MOVFF   RXMessBuff_D2,WREG		;Point to correct data memory address
    ANDLW   b'00111111'
    MOVWF   DataAddressLow,Banked
;
    MOVFF   RXMessBuff_D5,NewDataLow	;Move low address byte
    MOVFF   RXMessBuff_D6,NewDataHigh	;Move high address byte
;
    CALL    CheckNextBootCodeLine		;
;
    GOTO    MessExit_				;Go to exit
;    
Undefined_Page_:
;
    GOTO    MessExit_				;The page was not recognized
;  
UpdateTable:
;
    CALL    ERASE_BLOCK
;
    GOTO    MessExit_
;
CANKingdomRX_extern_:
;
    BTFSS   BootModeBit
    GOTO    CANKingdomRX_extern
    GOTO    MessExit_				;The page was not recognized
;
MessExit_:
;
    RETURN
;
#endif
;
#ifdef EEPROM_S
;
BootReadInternalEEPROM:
;
    MOVWF   EEADR,Access
;  
    BCF	    _EEPGD
    BCF	    _EECFGS
;
    BSF	    _EERD
    NOP
    MOVF    EEDATA,W,Access
;
    RETURN
;
;*******************************************************************************
;* Write data into internal EEPROM                
;* - EEADR loaded with address
;* - Data to be written in W
;* - Interrupts are disabled
;*******************************************************************************
;
BootWriteInternalEEPROM:
;
    MOVWF   EEDATA,Access

    BCF	    _EEPGD
    BCF     _EECFGS
    BSF     _EEWREN
;
BootWriteInternalEEPROM1:
;
    BTFSS   BootModeBit
;
    BCF	    _GIEH
    BTFSC   _GIEH
    GOTO    WriteInternalEEPROM1
;
    MOVLW   0x55
    MOVWF   EECON2,Access
    MOVLW   0xAA
    MOVWF   EECON2,Access
    BSF	    _EEWR
    BTFSC   _EEWR
    BRA	    $-2
;
    BTFSS   BootModeBit
    BSF	    _GIEH
;
    BCF	    _EEWREN
    BTFSS   BootModeBit
;
    RETURN
;
BootEEPROM_Save: MACRO     EEPROM,RAM
;
    MOVFF     RAM,WREG				
    MOVWF     EEPROM_Work,Banked			
    MOVLW     EEPROM					
    CALL      BootReadInternalEEPROM
;
    SUBWF     EEPROM_Work,W,Banked			     				
;
    MOVF      EEPROM_Work,W,Banked			
    CALL      BootWriteInternalEEPROM	
;
    ENDM
;
#endif
;
;*******************************************************************************
;*  Internal EEPROM default data
;*******************************************************************************
;
    ORG	    0xF00000
;	
    DE	    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
;
    END