Neptune_170620

Dependencies:   mbed

Files at this revision

API Documentation at this revision

Comitter:
Picmon
Date:
Wed Jun 17 10:11:19 2020 +0000
Commit message:
Neptune;

Changed in this revision

.gitignore Show annotated file Show diff for this revision Revisions of this file
.mbed Show annotated file Show diff for this revision Revisions of this file
Boolean.h Show annotated file Show diff for this revision Revisions of this file
Controls.cpp Show annotated file Show diff for this revision Revisions of this file
Controls.h Show annotated file Show diff for this revision Revisions of this file
Definitions.h Show annotated file Show diff for this revision Revisions of this file
Functions.cpp Show annotated file Show diff for this revision Revisions of this file
Functions.h Show annotated file Show diff for this revision Revisions of this file
ISR.cpp Show annotated file Show diff for this revision Revisions of this file
ISR.h Show annotated file Show diff for this revision Revisions of this file
Languages.cpp Show annotated file Show diff for this revision Revisions of this file
Languages.h Show annotated file Show diff for this revision Revisions of this file
MotorControl.cpp Show annotated file Show diff for this revision Revisions of this file
MotorControl.h Show annotated file Show diff for this revision Revisions of this file
NVM.cpp Show annotated file Show diff for this revision Revisions of this file
NVM.h Show annotated file Show diff for this revision Revisions of this file
NextionLCD.cpp Show annotated file Show diff for this revision Revisions of this file
NextionLCD.h Show annotated file Show diff for this revision Revisions of this file
NextionPages.cpp Show annotated file Show diff for this revision Revisions of this file
NextionPages.h Show annotated file Show diff for this revision Revisions of this file
Ser25lcxxx.cpp Show annotated file Show diff for this revision Revisions of this file
Ser25lcxxx.h Show annotated file Show diff for this revision Revisions of this file
Threads.cpp Show annotated file Show diff for this revision Revisions of this file
Threads.h Show annotated file Show diff for this revision Revisions of this file
Watchdog.cpp Show annotated file Show diff for this revision Revisions of this file
Watchdog.h Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
main.h Show annotated file Show diff for this revision Revisions of this file
mbed-os.lib Show annotated file Show diff for this revision Revisions of this file
mbed.bld Show annotated file Show diff for this revision Revisions of this file
peripheral Pins.txt Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.gitignore	Wed Jun 17 10:11:19 2020 +0000
@@ -0,0 +1,7 @@
+.build
+.mbed
+projectfiles
+*.py*
+mbed-os
+BUILD
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.mbed	Wed Jun 17 10:11:19 2020 +0000
@@ -0,0 +1,5 @@
+ROOT=.
+TARGET=NUCLEO_F746ZG
+TARGET_CODE=0816
+TARGET_SERIAL=066FFF535548887767081944
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Boolean.h	Wed Jun 17 10:11:19 2020 +0000
@@ -0,0 +1,44 @@
+/* 
+ * File:   Boolean.h
+ * Author: LoweJ
+ *
+ * Created on 08 December 2015, 15:29
+ */
+
+#ifndef BOOLEAN_H
+#define BOOLEAN_H
+
+#include "mbed.h"
+
+// SYSTEM BOOLEANS
+#define ON                  1
+#define _ON                 0
+#define OFF                 0
+#define _OFF                1
+#define SET                 1
+#define CLEAR               0
+#define HI                  1
+#define LO                  0
+#define OPEN                1
+#define CLOSED              0
+#define DISCHARGE           1
+#define CHARGE              0
+#define OUTPUT              0 
+#define INPUT               1
+#define VALID               1
+#define INVALID             0
+#define ODD                 1
+#define EVEN                0
+#define ENABLE              1
+#define DISABLE             0
+#define PASS                1
+#define FAIL                0
+#define INC                 1
+#define DEC                 0   
+#define TICK                0
+#define UNTICK              1
+#define NONE                0
+
+
+
+#endif  /* BOOLEAN_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Controls.cpp	Wed Jun 17 10:11:19 2020 +0000
@@ -0,0 +1,600 @@
+#include <string> 
+#include "main.h"
+#include "Functions.h"
+#include "Definitions.h"
+#include "Boolean.h"
+#include "NextionLCD.h"
+#include "mbed_debug.h"
+#include "mbed.h"
+#include "Languages.h"
+#include "Ser25lcxxx.h"
+#include "NVM.h"
+#include "Watchdog.h"
+#include "NextionPages.h"
+#include "Controls.h"
+#include "ISR.h"
+#include "FastPWM.h"
+
+/*
+    CONTROLS
+
+    Start Button
+    Stop Button
+    Analogue Input
+    Analogue Output
+    Motor Control
+*/
+
+///////////////////////////////////////////////////////////////////////////////
+// MBED OBJECTS
+///////////////////////////////////////////////////////////////////////////////
+extern NextionLCD lcd;//Tx, Rx, Nextion Port
+
+//ADC/DAC
+AnalogIn ain(ANA_IN_A0);
+AnalogOut aout(ANA_OUT_DAC1);
+
+//Button Membrane 
+DigitalOut startLED(START_LED);
+DigitalOut stopLED(STOP_LED);
+DigitalIn startButton(START_BTN);
+DigitalIn stopButton(STOP_BTN);
+
+//4-20mA Control Inputs
+DigitalIn rmtRunStop(RUN_STOP);// Run / Stop Input
+DigitalIn rmtExtCont(EXT_CONT);//External Contact Input
+DigitalIn rmtFldRec(RMT_FLD_REC);//Remote Fluid Recovery Input
+
+//Leak detection
+DigitalIn leakIn(LEAK_DETECT_INPUT);//Pump head leak detection
+
+//4-20mA Control Outputs
+DigitalOut alarmOut1(ALARM_OUT1);
+DigitalOut alarmOut2(ALARM_OUT2);
+
+//Nucleo Debug LEDs
+DigitalOut led1(LED1);
+DigitalOut led2(LED2);
+DigitalOut led3(LED3); 
+
+//DVR8603 BLDC Motor Controller
+DigitalOut motEnable(MOT_EN);
+DigitalOut motDir(MOT_DIR);
+DigitalOut nBrake(N_BRK);
+DigitalIn nFault(N_FAULT);
+
+//Netxion Power Control
+DigitalOut nexPwrCont(NEX_PWR);
+
+//3V3 Power Good signal from power supply
+DigitalIn pwrGood(PWR_GOOD);
+
+FastPWM pwm(PWM, PWM_PRESCALER);//leave prescaler at 1 so that that the smallest speed inc/dec results in a measureable PWM change, resolution is ~20ns/bit
+
+float motorSpeed = ZERO;
+float motSpeedSetPoint = ZERO;
+float flowPercent = ZERO;
+float lastMaxScale = maxScale;
+
+bool leakDetect(bool leakInput){
+    bool leak = false;    
+
+    if(leakInput == true){
+        leak = true;
+    }   
+
+    return(leak);    
+}
+
+bool outputFluidLevMon(void){
+
+    return(0);
+}
+
+bool outputContactMode(void){
+
+    /*
+    
+     need debouce routine 
+     measure pulse time, 40 - 1000ms
+
+     if valid do stuff, if pulse not valid ignore
+
+     count the pulses also
+    
+     */
+    return(0);
+}
+
+bool startBtn(bool byPassPress){//Interrupt pin
+/*
+    byPassPress if true allows the fucntion to be used for LED indicators without pressing the start button
+*/
+    bool state = OFF;
+
+    if((startButton == _ON)||(byPassPress == true)){    
+        startLED = ON;//Keypad LEDs OFF ta power up
+        stopLED = OFF;          
+        state = ON;
+    }
+    return(state);
+}
+
+bool stopBtn(bool byPassPress){//Interrupt pin
+/*
+    byPassPress if true allows the fucntion to be used  for LED indicators without pressing the stop button
+*/
+    bool state = OFF;
+
+    if((stopButton == _ON)||(byPassPress  == true)){
+        startLED = OFF;//Keypad LEDs OFF ta power up
+        stopLED = ON;             
+        state = ON;
+    }
+    return(state);
+}
+
+void reset(void){
+    ml=ZERO;
+    arrowFlag = false;
+    motorSpeed = ZERO;
+    motSpeedSetPoint = ZERO;
+    ConfInputSw();
+    confBtn();
+    confMotor();//turn motor off    
+    confPWM();//Reset      
+}
+
+void confBtn(void){
+    startLED = OFF;//Keypad LEDs OFF ta power up
+    stopLED = OFF;
+    startButton.mode(PullUp);//Enable pull up resistors to 3V3
+    stopButton.mode(PullUp);
+}
+
+void ConfInputSw(void){
+    rmtFldRec.mode(PullDown);
+    rmtExtCont.mode(PullDown);
+    rmtRunStop.mode(PullDown);
+}
+
+void confMotor(void){
+    motEnable = OFF;
+    motDir = CCW;//Default motor direction
+    nBrake = _OFF;
+    tachoIn.mode(PullUp);//Speed feedback, OD Output from motor controller
+    nFault.mode(PullUp);
+}
+
+uint8_t fluidRecMode(void){
+    
+ return(0);     
+}
+
+uint8_t flowCalMode(void){
+
+ return(0); 
+}
+
+uint8_t contactMode(void){
+
+ return(0); 
+}
+
+void anaOutScale(float mA_FullScale, float mA_MatchScale){
+    
+    if(nvm._4_20mAoutPut == _4_20MA_OUT_FULL_SCALE)
+        anaOut_mA(mA_FullScale);    
+    else
+        if(nvm._4_20mAoutPut == _4_20MA_OUT_MATCH_INPUT_SCALE)
+            anaOut_mA(mA_MatchScale);
+}
+
+void anaOut_mA(float mA){
+/*
+    Current to DAC Voltage converter
+    aout.write() has range 0.0 - 1.0
+*/    
+
+    float rawDAC_V = ZERO;
+    float lpfDAC_V = ZERO;
+   
+    rawDAC_V = mapF(mA, I_3MA, I_20MA, DAC_V_LOW, DAC_V_HIGH);        
+    aout.write(rawDAC_V);         
+}
+
+float anaIn_mA(void){
+/*
+    Low Pass Filtered analogue signal
+*/
+    float rawADC_V = ZERO;//Raw ADC voltage
+    float lpfADC_V = ZERO;//Low Pass Filtered ADC Voltage    
+    float ana_mA = ZERO; //ADC Voltage convered to mA 
+
+    rawADC_V = (ain.read() * VDD);//Output in V  
+    lpfADC_V = low_pass_filterF(rawADC_V);
+    ana_mA = mapF(lpfADC_V, ADC_MIN_V, ADC_MAX_V, I_0MA, I_22_4MA);
+
+    return(ana_mA);    
+}
+ 
+uint8_t anaIn(void){
+/*
+    Convert analogue signal to mA output and control motor speed
+    Measured Hyteresis band is approx 50uA on QDOS 30
+*/
+
+    float lpfADC_V = ZERO;//ADC variable from Low Pass Filter 
+    float ana_mA = ZERO;
+    static float flowPercent;//flow rate percentage, used for map calculations
+    static float hyst_mA = ZERO;//
+    static bool pumpMotor =  OFF;//make sure the motor is off by default
+ 
+    uint8_t task = RUNNING;//next normal task
+
+    ana_mA = anaIn_mA();//get the analogue current from external equipment 
+
+    //lcd.nexSendFloat("p1left",ana_mA,2);//update
+         
+    if(ana_mA >= (nvm.mA_low - hyst_mA)){//hysteresis to stop noise triggering motor control    
+        hyst_mA = HYST_MA;
+        pumpMotor = ON;       
+        startBtn(ON);              
+    }          
+    else{
+        hyst_mA = ZERO;  
+        pumpMotor = OFF; 
+        stopBtn(ON);              
+    }
+                
+      if((runStopSignal(rmtRunStop, &nvm) == false)&&(pumpMotor == ON)){//Pump is ON
+        lcd.nexRotArrow(ON);
+        lcd.nexSetFontCol("p1mid",BLACK);       
+        lcd.nexSendTxt("p1mid","4-20mA Input Mode");//page 1 middle text box   
+ 
+        flowPercent = mapF(ana_mA, nvm.mA_low, nvm.mA_high, nvm.flow_low, nvm.flow_high);//this outputs flow rate % used in map calculations     
+
+        nvm.flowUnitVal = mapF(flowPercent, 0.0, 100.0, minScale, maxScale);
+
+        lcd.nexSendFloat("meter", nvm.flowUnitVal, precision);//display the flow units                                           
+
+        motor(flowPercent, CCW, BRAKE_OFF, MOTOR_ENABLE, 1);
+
+        anaOutScale((mapF(nvm.flowUnitVal, minScale, maxScale, I_4MA, I_20MA)), (mapF(nvm.flowUnitVal, minScale, nvm.flow_high, I_4MA, I_20MA)));
+ 
+    }
+    else
+    {//Pump is OFF     
+        //lcd.nexDispSymbol("stop", OFF);          
+        lcd.nexRotArrow(OFF);
+        lcd.nexSetFontCol("p1mid",RED);     
+        lcd.nexSendTxt("p1mid","4-20mA Input Mode");//page 1 middle text box    
+        lcd.nexSendFloat("meter", METER_ZERO, precision);//bug warning: writting 0.00 result in blank writted to meter, writing 0.00001 to the meter then displays 0.0        
+        motor(ZERO, CCW, BRAKE_OFF, MOTOR_DISABLE, 1);   
+        anaOut_mA(I_3MA);//analogue output forced to 3mA 
+    }      
+    return(task);           
+}
+
+uint8_t manual(void){
+
+    float ana_mA = 0;    
+    static float lastFlowUnitVal = nvm.flowUnitVal;
+    uint8_t task = RUNNING;
+
+    if(runStopSignal(rmtRunStop, &nvm) == false){//Run/Stop signal logic                   
+
+        flowPercent = incDecControl(&nvm.flowUnitVal, precision, minScale, maxScale, nvm.speedLimit);
+
+            if((tPop.read() > 1.0)&&(lastFlowUnitVal == nvm.flowUnitVal)){//x seconds has expired save the updated  flowUnitVal to NVM memory and reload NVM
+                tPop.stop();
+                tPop.reset();
+                stopLED = ON;
+                wait(0.01);
+                stopLED = OFF;  
+                writeNVMfloat(NVM_FLOWU_VAL,nvm.flowUnitVal);        
+            }
+
+            lcd.nexRotArrow(ON);
+            lcd.nexSetFontCol("p1mid",BLACK);                                                                                           
+            lcd.nexSendTxt("p1mid","Manual Mode");//page 1 middle text box       
+
+            nvm.flowUnitVal = ((flowPercent/100)*maxScale);
+            lcd.nexSendFloat("meter", nvm.flowUnitVal, precision);//display the flow units   
+                
+            motor(flowPercent, CCW, BRAKE_OFF, MOTOR_ENABLE, 1);    
+
+            anaOut_mA(mapF(nvm.flowUnitVal, minScale, maxScale, I_4MA, I_20MA));//convert flow rate % to analogue output current    
+
+            lastFlowUnitVal = nvm.flowUnitVal;//update
+        //}
+    }
+    else{   
+        //lcd.nexDispSymbol("stop", OFF);   
+        lcd.nexRotArrow(OFF); 
+        lcd.nexSetFontCol("p1mid",RED);                                                                                           
+        lcd.nexSendTxt("p1mid","Manual Mode");//page 1 middle text box           
+        motor(flowPercent, CCW, BRAKE_OFF, MOTOR_DISABLE, 1);    
+    }
+    
+    return(task); 
+}
+ 
+uint8_t motor(float rpmSetPoint, bool dir, bool brake, bool enable, float rampTime){
+
+    uint8_t task = RUNNING;//next normal task
+
+    static float rpmRamp = ZERO;
+    
+    motEnable = enable;
+    motDir = dir;
+    nBrake = brake;
+    
+    if((motEnable == MOTOR_DISABLE)||(nBrake == BRAKE_ON))    
+        rpmRamp = ZERO;
+    else{
+
+        if(rpmRamp > rpmSetPoint){    
+
+            pwm.pulsewidth_us(rpmRamp);            
+
+            if(rpmRamp > MOTOR_PWM_MIN)
+                rpmRamp-=0.1;
+            else
+                rpmRamp = MOTOR_RPM_MIN;                                       
+        }
+
+        if(rpmRamp < rpmSetPoint){
+        
+            pwm.pulsewidth_us(rpmRamp);        
+        
+            if(rpmRamp < MOTOR_PWM_MAX)
+                rpmRamp+=0.1;
+            else  
+                rpmRamp = MOTOR_PWM_MAX;                                 
+        }                      
+    }
+
+    lcd.nexSetPrgBar("progBar",rpmRamp);  
+
+    return(task);
+}
+
+void confPWM(void){    
+    pwm.period_us(PWM_PERIOD);
+    pwm.pulsewidth_us(ZERO);      
+}
+
+void ledClr(void){
+    led1=OFF; 
+    led2=OFF; 
+    led3=OFF; 
+}
+
+uint8_t startUpMode(uint8_t runMode){
+    uint8_t task = START;         
+    uint8_t setRunMode;    
+
+    setRunMode = runModeNVM(runMode);//retreive the run mode stored in NVM    
+
+    if(setRunMode == ANALOGUE_SET)//if set for analogue start 
+        task = ANALOGUE_SET;                                                  
+    else
+    {  
+        if((startBtn(BTN_AND_IND))&&(setRunMode == MANUAL_SET))//if set for manual bypass start button and start                                                                                                              
+            task = MANUAL_SET;                                                                                                                                                                                                                                                     
+    }                                                                                                                                                                            
+    return(task);
+}
+ 
+bool runStopSignal(bool runStopSig, struct settingsNVM *nvm){    
+
+    //#define DEBUG_LOCAL
+
+    #ifdef DEBUG_LOCAL
+        uint8_t selected=0;
+    #endif
+
+    bool pumpPause = false;
+
+
+    if((nvm->rmtStopPump == RMT_STOP_PUMP_HIGH)&&(runStopSig == HI)){  
+
+        #ifdef DEBUG_LOCAL
+            selected=1;    
+        #endif 
+
+        lcd.nexDispSymbol("pause", ON);         
+        nvm->pumpOnOff = PUMP_OFF;                  
+        writeNVMByte(PUMP_ON_OFF,nvm->pumpOnOff);          
+        pumpPause = true;        
+    }
+    else
+    if((nvm->rmtStopPump == RMT_STOP_PUMP_HIGH)&&(runStopSig == LO)){  
+
+        #ifdef DEBUG_LOCAL
+            selected=2;                
+        #endif
+
+        lcd.nexDispSymbol("pause", OFF);      
+        nvm->pumpOnOff = PUMP_ON;  
+        writeNVMByte(PUMP_ON_OFF,nvm->pumpOnOff);                           
+        pumpPause = false;                  
+    }    
+    else       
+    if((nvm->rmtStopPump == RMT_STOP_PUMP_LOW)&&(runStopSig == HI)){        
+
+        #ifdef DEBUG_LOCAL        
+            selected=3;          
+        #endif
+
+        lcd.nexDispSymbol("pause", OFF);  
+        nvm->pumpOnOff = PUMP_ON;                
+        writeNVMByte(PUMP_ON_OFF,nvm->pumpOnOff);                     
+        pumpPause = false;                
+    }
+    else
+    if((nvm->rmtStopPump == RMT_STOP_PUMP_LOW)&&(runStopSig == LO)){    
+
+        #ifdef DEBUG_LOCAL        
+            selected=4;          
+        #endif    
+
+        lcd.nexDispSymbol("pause", ON);   
+        nvm->pumpOnOff = PUMP_OFF;                     
+        writeNVMByte(PUMP_ON_OFF,nvm->pumpOnOff);                 
+        pumpPause = true;                         
+    }        
+ 
+    #ifdef DEBUG_LOCAL
+        pc.printf("\r\n\nPump On/Off = 0x%02X, Selected = %d",nvm->pumpOnOff, selected); 
+    #endif        
+    
+
+    return(pumpPause);
+}
+ 
+void outPuts(bool leakDetection, struct settingsNVM *nvm){
+
+        if((nvm->outPut1 ==  OUT1_RUN_STATUS)&&(nvm->outPut1Logic == OUT1_LOGIC_LO)&&(nvm->pumpOnOff == PUMP_ON)){
+        // Run status ok for manual and analogue            
+        
+            alarmOut1 = OFF;
+        }
+        else   
+        if((nvm->outPut1 ==  OUT1_RUN_STATUS)&&(nvm->outPut1Logic == OUT1_LOGIC_LO)&&(nvm->pumpOnOff == PUMP_OFF)){
+            alarmOut1 = ON;
+        }   
+        else
+        if((nvm->outPut1 ==  OUT1_RUN_STATUS)&&(nvm->outPut1Logic == OUT1_LOGIC_HI)&&(nvm->pumpOnOff == PUMP_ON)){
+            alarmOut1 = ON;
+        }
+        else   
+        if((nvm->outPut1 ==  OUT1_RUN_STATUS)&&(nvm->outPut1Logic == OUT1_LOGIC_HI)&&(nvm->pumpOnOff == PUMP_OFF)){
+            alarmOut1 = OFF;
+        }         
+        else
+        if((nvm->outPut1 ==  OUT1_MANUAL_MODE)&&(nvm->outPut1Logic == OUT1_LOGIC_HI)&&(nvm->runMode == MANUAL)){
+            alarmOut1 = ON;
+        }    
+        else
+        if((nvm->outPut1 ==  OUT1_MANUAL_MODE)&&(nvm->outPut1Logic == OUT1_LOGIC_LO)&&(nvm->runMode == MANUAL)){
+            alarmOut1 = OFF;
+        }  
+        else
+        if((nvm->outPut1 ==  OUT1_ANALOGUE_MODE)&&(nvm->outPut1Logic == OUT1_LOGIC_HI)&&(nvm->runMode == ANALOGUE)){
+            alarmOut1 = ON;
+        }    
+        else
+        if((nvm->outPut1 ==  OUT1_ANALOGUE_MODE)&&(nvm->outPut1Logic == OUT1_LOGIC_LO)&&(nvm->runMode == ANALOGUE)){
+            alarmOut1 = OFF;
+        }     
+        else
+        if((nvm->outPut1 ==  OUT1_CONTACT_MODE)&&(nvm->outPut1Logic == OUT1_LOGIC_HI)){
+            alarmOut1 = ON;
+        }    
+        else
+        if((nvm->outPut1 ==  OUT1_CONTACT_MODE)&&(nvm->outPut1Logic == OUT1_LOGIC_LO)){
+            alarmOut1 = OFF;
+        }     
+        else
+        if((nvm->outPut1 ==  OUT1_FLUID_LEVEL)&&(nvm->outPut1Logic == OUT1_LOGIC_HI)){
+            alarmOut1 = ON;
+        }    
+        else
+        if((nvm->outPut1 ==  OUT1_FLUID_LEVEL)&&(nvm->outPut1Logic == OUT1_LOGIC_LO)){
+            alarmOut1 = OFF;
+        }          
+        else
+        if((nvm->outPut1 ==  OUT1_LEAK_DETECT)&&(nvm->outPut1Logic == OUT1_LOGIC_HI)){            
+            alarmOut1 = ~leakDetect(leakDetection);
+        }    
+        else
+        if((nvm->outPut1 ==  OUT1_LEAK_DETECT)&&(nvm->outPut1Logic == OUT1_LOGIC_LO)){
+            alarmOut1 = leakDetect(leakDetection);
+        }                
+        else
+        if((nvm->outPut1 ==  OUT1_GENERAL_ALARM)&&(nvm->outPut1Logic == OUT1_LOGIC_HI)){
+        /*  Not defined in QDOS documents, I know leak detect triggers this there will be 
+            others faults tha trigger this but at this time they are not known.
+            
+        */
+            alarmOut1 = ~leakDetect(leakDetection);
+        }    
+        else
+        if((nvm->outPut1 ==  OUT1_GENERAL_ALARM)&&(nvm->outPut1Logic == OUT1_LOGIC_LO)){
+            alarmOut1 = leakDetect(leakDetection);
+        }                
+
+
+
+        if((nvm->outPut2 ==  OUT2_RUN_STATUS)&&(nvm->outPut2Logic == OUT2_LOGIC_LO)&&(nvm->pumpOnOff == PUMP_ON)){
+            alarmOut2 = OFF;
+        }
+        else   
+        if((nvm->outPut2 ==  OUT2_RUN_STATUS)&&(nvm->outPut2Logic == OUT2_LOGIC_LO)&&(nvm->pumpOnOff == PUMP_OFF)){
+            alarmOut2 = ON;
+        }   
+        else
+        if((nvm->outPut2 ==  OUT2_RUN_STATUS)&&(nvm->outPut2Logic == OUT2_LOGIC_HI)&&(nvm->pumpOnOff == PUMP_ON)){
+            alarmOut2 = ON;
+        }
+        else   
+        if((nvm->outPut2 ==  OUT2_RUN_STATUS)&&(nvm->outPut2Logic == OUT2_LOGIC_HI)&&(nvm->pumpOnOff == PUMP_OFF)){
+            alarmOut2 = OFF;
+        }     
+        else
+        if((nvm->outPut2 ==  OUT2_MANUAL_MODE)&&(nvm->outPut2Logic == OUT2_LOGIC_HI)&&(nvm->runMode == MANUAL)){
+            alarmOut2 = ON;
+        }    
+        else
+        if((nvm->outPut2 ==  OUT2_MANUAL_MODE)&&(nvm->outPut2Logic == OUT2_LOGIC_LO)&&(nvm->runMode == MANUAL)){
+            alarmOut2 = OFF;
+        }    
+        else
+        if((nvm->outPut2 ==  OUT2_ANALOGUE_MODE)&&(nvm->outPut2Logic == OUT2_LOGIC_HI)&&(nvm->runMode == ANALOGUE)){
+            alarmOut2 = ON;
+        }    
+        else
+        if((nvm->outPut2 ==  OUT2_ANALOGUE_MODE)&&(nvm->outPut2Logic == OUT2_LOGIC_LO)&&(nvm->runMode == ANALOGUE)){
+            alarmOut2 = OFF;
+        }             
+        else
+        if((nvm->outPut2 ==  OUT2_CONTACT_MODE)&&(nvm->outPut2Logic == OUT2_LOGIC_HI)){
+            alarmOut2 = ON;
+        }    
+        else
+        if((nvm->outPut2 ==  OUT2_CONTACT_MODE)&&(nvm->outPut2Logic == OUT2_LOGIC_LO)){
+            alarmOut2 = OFF;
+        }             
+        else
+        if((nvm->outPut1 ==  OUT1_FLUID_LEVEL)&&(nvm->outPut1Logic == OUT1_LOGIC_HI)){
+            alarmOut1 = ON;
+        }    
+        else
+        if((nvm->outPut2 ==  OUT2_FLUID_LEVEL)&&(nvm->outPut2Logic == OUT2_LOGIC_LO)){
+            alarmOut2 = OFF;
+        }          
+        else
+        if((nvm->outPut2 ==  OUT2_LEAK_DETECT)&&(nvm->outPut2Logic == OUT2_LOGIC_HI)){            
+            alarmOut2 = ~leakDetect(leakDetection);
+        }    
+        else
+        if((nvm->outPut2 ==  OUT2_LEAK_DETECT)&&(nvm->outPut2Logic == OUT2_LOGIC_LO)){
+            alarmOut2 = leakDetect(leakDetection);
+        }                
+        else
+        if((nvm->outPut2 ==  OUT2_GENERAL_ALARM)&&(nvm->outPut2Logic == OUT2_LOGIC_HI)){
+        /*  Not defined in QDOS documents, I know leak detect triggers this there will be 
+            others faults tha trigger this but at this time they are not known.
+            
+        */
+            alarmOut2 = ~leakDetect(leakDetection);
+        }    
+        else
+        if((nvm->outPut2 ==  OUT2_GENERAL_ALARM)&&(nvm->outPut2Logic == OUT2_LOGIC_LO)){
+            alarmOut2 = leakDetect(leakDetection);
+        }           
+}     
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Controls.h	Wed Jun 17 10:11:19 2020 +0000
@@ -0,0 +1,75 @@
+#ifndef CONTROLS_H 
+#define CONTROLS_H 
+
+#include "mbed.h"
+#include "FastPWM.h"
+
+//DVR8603 BLDC Motor Controller
+extern DigitalOut motEnable;
+extern DigitalOut motDir;
+extern DigitalOut nBrake;
+extern DigitalIn nFault;
+
+//ADC/DAC
+extern AnalogIn ain;
+extern AnalogOut aout;
+
+//Nucleo Debug LEDs
+extern DigitalOut led1;
+extern DigitalOut led2;
+extern DigitalOut led3;
+
+//Button Membrane  
+extern DigitalOut startLED;
+extern DigitalOut stopLED;
+extern DigitalIn startButton;
+extern DigitalIn stopButton;
+
+//4-20mA Control Inputs
+extern DigitalIn rmtRunStop;// Run / Stop Input
+extern DigitalIn rmtExtCont;//External Contact Input
+extern DigitalIn rmtFldRec;//Remote Fluid Recovery Inputs
+
+//Leak detection
+extern DigitalIn leakIn;
+
+//4-20mA Control Outputs
+extern DigitalOut alarmOut1;
+extern DigitalOut alarmOut2;
+
+//Netxion Power Control
+extern DigitalOut nexPwrCont;
+
+//extern PwmOut pwm;
+extern FastPWM pwm;
+
+extern float motorSpeed;
+extern float flowPercent;
+extern float lastMaxScale;
+
+
+
+bool startBtn(bool byPassPress);
+bool stopBtn(bool byPassPress);
+
+void confPWM(void);
+void confMotor(void);
+void confBtn(void);
+uint8_t anaIn(void);
+uint8_t manual(void);
+uint8_t contactMode(void);
+uint8_t flowCalMode(void);
+uint8_t fluidRecMode(void);
+void reset(void);
+void anaOut_mA(float mA);
+void anaOutScale(float mA_FullScale, float mA_MatchScale);
+float anaIn_mA(void);
+void ledClr(void);
+uint8_t motor(float rpmSetPoint, bool dir, bool brake, bool enable, float rampTime);
+void ConfInputSw(void);
+uint8_t startUpMode(uint8_t runMode);
+bool runStopSignal(bool runStopSig, struct settingsNVM *nvm);   
+void outPuts(bool leakDetection, struct settingsNVM *nvm);
+bool leakDetect(bool leakInput);
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Definitions.h	Wed Jun 17 10:11:19 2020 +0000
@@ -0,0 +1,639 @@
+#ifndef DEFINITIONS_H 
+#define DEFINITIONS_H 
+
+#include "mbed.h"
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// NEPTUNE DEFINITIONS
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+//#define BOOTLOADER
+//#define WDT_TEST
+//#define DEBUG_STATES
+//#define LOOP_TIME
+#define DEBUG_LCD
+#define DEBUG_NVM
+#define DEBUG_FUNCTIONS
+
+#define MV(x)   ((0xFFFF*X)/3300)
+
+enum STATES{INITIALISE,START,STOP,STOP_SCRN,RUNNING,ANALOGUE_SET,DOSE,MANUAL_SET,PROFIBUS,STALL,
+                DEBUG,DIAGS,ALARM,FAULT,READ_KEYS,MANUAL_MODE,ANALOGUE_MODE,PROFIBUS_MODE,
+                CONTACT_SET,FLUIDREC_SET,READ_NVM,RESET_VARS,ANA_CAL,MAX,REMOTE_IN,FLOW_CAL_SET};
+
+enum ANACAL{CAL1_SCRN, CAL2_SCRN, CAL3_SCRN, CAL4_SCRN, COMPLETE_SCRN, EXIT};
+
+///////////////////////////////////////////
+// DEBUG
+//////////////////////////////////////////
+#define HEX 0
+#define STR 1
+#define CHR 3
+
+///////////////////////////////////////////
+// NEPTUNE TYPE
+//////////////////////////////////////////
+#define QDOS_30                 0
+#define VDOS_20                 1
+#define VDOS_30                 2
+#define VDOS_60                 3
+#define VDOS_120                4
+
+///////////////////////////////////////////
+// WATCHDOG
+//////////////////////////////////////////
+#define WDT                     1.0//Seconds
+
+///////////////////////////////////////////
+// METER DISPLAY
+//////////////////////////////////////////
+#define METER_ZERO              0.00001
+
+///////////////////////////////////////////
+// PWM CONSTANTS
+//////////////////////////////////////////
+#define PWM_PERIOD              100.0//100us
+#define MOTOR_PWM_MIN           0.000
+#define MOTOR_PWM_MAX           100.0
+#define PWM_PRESCALER           1
+#define ZERO                    0
+
+///////////////////////////////////////////
+// MOTOR / GEARBOX CONSTANTS
+//////////////////////////////////////////
+#define MOTOR_RPM_MIN           3.2//Motor RPM based on QDOS 20, 32:1 gearbox ratio
+#define MOTOR_RPM_MAX           55//Motor RPM based on QDOS 20, 32:1 gearbox ratio
+
+///////////////////////////////////////////
+// INC/DEC BUTTON SPEED CONSTANTS
+//////////////////////////////////////////
+#define START_DELAY             0.5//Delay before INC/DEC starts to operate
+#define DELAY_SHORT             0.5//Delay before INC/DEC of SLOW_SPEED when < DELAY_LONG
+#define DELAY_LONG              4.0//After DELAY_LONG switch to FAST_SPEED
+#define SLOW_SPEED              0.25
+#define FAST_SPEED              0.02
+
+///////////////////////////////////////////
+// MOTOR CONSTANTS
+//////////////////////////////////////////
+#define ARROW_ROTATION_SPEED    150//Milliseconds
+#define CCW                     0
+#define CW                      1 
+#define MOTOR_ENABLE            1
+#define MOTOR_DISABLE           0
+#define BRAKE_ON                0
+#define BRAKE_OFF               1
+#define MOT_STALL               1
+#define MOT_FAULT               2
+#define INDICATORS_ONLY         1
+#define BTN_AND_IND             0
+#define BTN_BYPASS_TRUE         1
+#define BTN_BYPASS_FALSE        0
+
+///////////////////////////////////////////
+// MOTOR CONTROL CONSTANTS
+//////////////////////////////////////////
+#define MOT_RAMP_1_SEC          0.3
+
+///////////////////////////////////////////
+// ANALOGUE INPUT CONSTANTS
+//////////////////////////////////////////
+#define ADC_SAMPLES             500//Min sample size is 50, when on PCB I expect to be alble to lower this sample size due to less noise
+
+///////////////////////////////////////////
+// ANALOGUE INPUT/OUTPUT CONSTANTS
+//////////////////////////////////////////
+#define HYST_MA                 0.05
+#define I_0MA                   0.00
+#define I_3MA                   3.00
+#define I_4MA                   4.00
+#define I_4_1MA                 4.10
+#define I_19_8MA                19.80
+#define I_20MA                  20.00
+#define I_21MA                  21.00
+#define I_22_4MA                22.40
+
+///////////////////////////////////////////
+// ANALOGUE INPUT/OUTPUT CALIBRATION CONSTANTS
+//////////////////////////////////////////
+#define DAC_V_HIGH              (0.3030*3.0000)//factor * V
+#define DAC_V_LOW               (0.3030*0.4450)//factor * V
+
+#define ADC_MIN_V               0.01250//[05/11/19] 4.00, accurate on this day, 13:30
+#define ADC_MAX_V               3.31200//[05/11/19] 20.00, accurate on this day, 13:30
+#define VDD                     3.30
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// NEXTION
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////
+// NEXTION  CONSTANTS
+//////////////////////////////////////////
+#define FLOW_U_STRING_LIST      0
+#define OUTPUT_STRING_LIST      1
+
+#define OUTPUT1_LIST            1//uses the same list items indexer (1) for output 1 & 2   
+#define OUTPUT2_LIST            2//uses the same list items indexer (1) for output 1 & 2     
+#define MA_OUTPUT_LIST          3     
+
+#define ADJ_FLOW_UNITS          1
+#define ADJ_CONT_SET            2
+
+#define P8_MENU_ITEMS           9
+#define P36_MENU_ITEMS          6
+
+//NEXTION PAGES
+#define PAGE_0                  0
+#define PAGE_1_HOME             1
+#define PAGE_2_INFO             2
+#define PAGE_3_MAIN             3
+#define PAGE_5_FLUID_LEV_SET    5
+#define PAGE_7_FLUID_LEV_SET    7
+#define PAGE_8_FLOWU_ADJ        8
+#define PAGE_9_SETTINGS         9    
+#define PAGE_12_MODE            12  
+#define PAGE_11_RESET           11 
+#define PAGE_14_ANA_CAL         14
+#define PAGE_18_ANA_CAL_MODE    18
+#define PAGE_27_ABOUT           27
+#define PAGE_31_SPEED_LIMIT     31
+#define PAGE_33_MA_OUT          33
+#define PAGE_34_START_STOP      34
+#define PAGE_35_CONT_SET        35
+
+#define PAGE_36_CONT_ADJ        36
+
+#define CLEAR_INC_DEC           35
+//EVENTS 
+#define TOUCH_EVENT             0x65   
+
+//RX ARRAY
+#define PAGE                    1//element 1
+#define ID                      2//element 2  
+#define PUSHPOP                 3//element 3
+
+#define PUSH                    1
+#define POP                     0
+
+///////////////////////////////////////////////////////////////////////////////
+// NEXTION CONSTANTS
+///////////////////////////////////////////////////////////////////////////////
+
+//ANALOGUE CALIBRATION DRAWLINE COORDINATES
+#define X1                      70
+#define Y1                      182
+#define X2                      196
+#define Y2                      57
+
+#define DRAW_SPEED              50
+
+#define DRAW                    1
+#define ERASE                   0
+
+//DEFAULT FACTORY SETTINGS
+#define LOW_CAL_MIN             3.00
+#define LOW_CAL_DEF             4.10
+#define HIGH_CAL_DEF            19.80
+#define HIGH_CAL_MAX            21.00
+
+///////////////////////////////////////////////////////////////////////////////
+// NEXTION COMPONENT IDs
+///////////////////////////////////////////////////////////////////////////////
+
+//PAGE 1 HOME COMPONENT IDs
+#define P1_INC                  7//Inc key
+#define P1_DEC                  8//Dec key
+#define P1_MAX                  11
+#define P1_SET                  12
+#define P1_MENU                 13
+#define P1_MODE                 14
+
+//PAGE 3 MAIN MENU IDs
+#define P3_FLUID_LEV_MON        5
+#define P3_SECURITY             6
+#define P3_CONT_SETTINGS        4
+#define P3_INFO                 3
+#define P3_BACK                 1
+
+//PAGE 5 FLUID LEVEL SETTINGS MENU IDs
+#define P5_BACK                 1  
+#define P5_HOME                 2  
+
+//PAGE 5 FLUID LEVEL SETTINGS IDs
+#define P5_DISABLE              7
+#define P5_CON_LEV_MON          3
+#define P5_ADJ_LEV              4
+#define P5_US_GALS              5    
+#define P5_LITRES               6              
+
+//PAGE 7 FLUID LEVEL SETTINGS IDs
+#define P7_BACK                 1
+#define P7_HOME                 2
+#define P7_ENABLE               3
+
+//PAGE 8 IDs
+#define P8_INC                  4
+#define P8_DEC                  5
+#define P8_OK                   6
+#define P8_HOME                 9
+#define P8_BACK                 1  
+
+//PAGE 9 SETTINGS COMPONENT IDs
+#define P9_AUTO_RESTART         3
+#define P9_FLOW_UNITS           4
+#define P9_ASS_NUM              5
+#define P9_PUMP_LAB             6
+#define P9_RESTORE              7    
+#define P9_LANG                 8
+#define P9_BACK                 1  
+
+//PAGE 11 IDs
+#define P11_OK                  4
+
+//PAGE 12 MODE COMPONENT IDs
+#define P11_RESET               3
+#define P11_BACK                1
+
+//PAGE 12 MODE COMPONENT IDs
+#define P12_MANUAL              3
+#define P12_FLOW_CAL            4
+#define P12_ANALOGUE            5
+#define P12_CONTACT             6    
+#define P12_FLUID_REC           7
+#define P12_ANA_CAL             8
+#define P12_BACK                1  
+
+//PAGE 14 4-20mA CAL COMPONENT IDs
+#define P14_INC                 3
+#define P14_DEC                 4
+#define P14_OK                  5
+#define P14_BACK                1    
+
+//Page 18 4-20mA CAL COMPONENT IDs
+#define P18_MAN                 5
+#define P18_INPUT               6
+#define P18_BACK                8
+
+//Page 27 COMPONENT IDs
+#define P27_BACK                7    
+
+//Page 31 SPEED LIMIT COMPONENT IDs
+#define P31_INC                 2
+#define P31_DEC                 3
+#define P31_OK                  4
+#define P31_HOME                6 
+#define P31_BACK                5
+
+//Page 33 START/STOP INPUT COMPONENT IDs
+#define P33_MATCH               5
+#define P33_FULL_SCALE          4
+#define P33_HOME                7
+#define P33_BACK                6
+
+//Page 34 START/STOP INPUT COMPONENT IDs
+#define P34_HIGH                2
+#define P34_LOW                 3
+#define P34_HOME                4 
+#define P34_BACK                5
+
+//Page 35 CONTROL SETTINGS COMPONENT IDs
+#define P35_INPUT               3
+#define P35_OUTPUT1             4
+#define P35_OUTPUT2             5
+#define P35_MA_OUTPUT           6
+#define P35_SPEED_LIMIT         8
+#define P35_RUN_HOURS           9
+#define P35_VOLUME_CNTR         10
+#define P35_SCALE_FACTOR        11
+#define P35_HOME                7
+#define P35_BACK                2  
+
+//Page 36 CONTROL SETTINGS ADJ COMPONENT IDs
+#define P36_INC                 1
+#define P36_DEC                 2
+#define P36_OK                  3
+#define P36_LOW                 5
+#define P36_HIGH                6    
+#define P36_BACK                7
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// NVM
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+/*
+    NVM MEMORY MAP LOCATIONS
+
+    Flow Units                      : 0x00         : 1 byte
+    Run Mode                        : 0x01         : 1 byte
+    Auto Restart                    : 0x02         : 1 byte
+    Pump Head Failure               : 0x03         : 1 byte
+    Alarm                           : 0x04         : 1 byte
+         
+    4-20mA Low Val Calibration      : 0x0A - 0x0B  : two bytes 16 bits
+    4-20mA High Val Calibration     : 0x0C - 0x0F  : two bytes 16 bits    
+*/
+
+//NVM CONSTANTS
+#define NVM_INIT                0x00
+
+//Auto Restart
+#define DISABLED                0x20
+#define ENABLED                 0x21
+
+//Pump Head Failure
+#define HEAD_OK                 0x30
+#define HEAD_FAIL               0x31
+
+#define NVM_UN_USED             0xff
+
+//NVM CONSTANTS
+#define NVM_START               0
+#define NVM_INIT                0x00
+#define NVM_UN_USED             0xff
+
+///////////////////////////////////////////
+// EEPROM CONSTANTS
+//////////////////////////////////////////
+#define SPI_FREQ                10000000//SPI Frequency in Hz  
+#define BYTE_SIZE               128//Organised 128 x 8 = 1024
+#define PAGE_SIZE               16//64 pages
+
+#define NVM_SIZE                64//Initial size until further notice
+
+#define BLANK                   0xff
+#define INIT                    0x00
+
+//NVM BYTE MEMORY LOCATIONS 
+#define NVM_START_ADDR          0
+
+#define NVM_FLOW_UNITS          0//uint8_t 1 byte
+#define NVM_RUN_MODE            1//uint8_t 1 byte
+#define NVM_AUTO_RESTART        2//uint8_t 1 byte
+#define NVM_PUMP_HEAD_STATUS    3//uint8_t 1 byte
+#define NVM_ALARM_OUTPUT        4//uint8_t 1 byte
+#define NVM_HEAD_SIDE           5//uint8_t 1 byte
+#define PUMP_ON_OFF             6//uint8_t 1 byte
+#define SPARE                   7//uint8_t 1 byte 
+#define NVM_SPEED_LIMIT         8//float value 4 bytes
+#define NVM_FLOWU_VAL           12//float value 4 bytes
+#define NVM_ANA_MA_CAL_LOW      16//float value 4 bytes
+#define NVM_ANA_MA_CAL_HIGH     20//float value 4 bytes
+#define NVM_ANA_FLOW_CAL_LOW    24//float value 4 bytes
+#define NVM_ANA_FLOW_CAL_HIGH   28//float value 4 bytes
+#define NVM_ADC_V_MIN           32//float value 4 bytes
+#define NVM_ADC_V_MAX           36//float value 4 bytes
+#define NVM_DAC_V_LOW           40//float value 4 bytes   
+#define NVM_DAC_V_HIGH          44//float value 4 bytes
+#define NVM_RMT_STOP_PUMP       48//uint8_t 1 byte
+#define NVM_OUTPUT1             49//uint8_t 1 byte
+#define NVM_OUTPUT1_LOGIC       50//uint8_t 1 byte
+#define NVM_OUTPUT2             51//uint8_t 1 byte
+#define NVM_OUTPUT2_LOGIC       52//uint8_t 1 byte
+#define NVM_4_20MA_OUT          53//uint8_t 1 byte
+
+///////////////////////////////////////////
+// NVM FLOW UNIT CONSTANTS
+//////////////////////////////////////////
+#define FLOW_UNITS              0x01
+#define PERCENT                 0x10
+#define GPD                     0x11
+#define GPH                     0x12
+#define ML_HR                   0x13
+#define ML_MIN                  0x14
+#define L_DAY                   0x15
+#define L_HR                    0x16
+#define L_MIN                   0x17
+#define OZ_MIN                  0x18
+#define RPM                     0x19
+
+///////////////////////////////////////////
+// NVM RUN MODE CONSTANTS
+//////////////////////////////////////////
+#define MANUAL                  0x20
+#define ANALOGUE                0x21
+#define CONTACT                 0x22
+#define FLUID_REC               0x23
+#define FLOW_CAL                0x24
+
+///////////////////////////////////////////
+// NVM AUTO RESTART CONSTANTS
+//////////////////////////////////////////
+#define AUTO_RESTART_OFF        0x30
+#define AUTO_RESTART_ON         0x31
+
+///////////////////////////////////////////
+// NVM PUMP HEAD CONSTANTS
+//////////////////////////////////////////
+#define PUMP_HEAD_FAIL          0x40
+#define PUMP_HEAD_OK            0x41
+
+///////////////////////////////////////////
+// NVM ALARM CONSTANTS
+//////////////////////////////////////////
+#define ALARM_OFF               0x50
+#define ALARM_ON                0x51
+
+///////////////////////////////////////////
+// NVM HEAD SIDE CONSTANTS
+//////////////////////////////////////////
+#define HEAD_LEFT               0x60
+#define HEAD_RIGHT              0x61
+
+///////////////////////////////////////////
+// NVM PUMP ON/OFF CONSTANTS
+//////////////////////////////////////////
+#define PUMP_OFF                0x70
+#define PUMP_ON                 0x71
+
+///////////////////////////////////////////
+// NVM REMOTE START/STOP CONSTANTS
+//////////////////////////////////////////
+#define RMT_STOP_PUMP_LOW       0x80
+#define RMT_STOP_PUMP_HIGH      0x81
+
+///////////////////////////////////////////
+// NVM OUTPUT1 CONSTANTS
+//////////////////////////////////////////
+#define OUT1_GENERAL_ALARM      0x90
+#define OUT1_RUN_STATUS         0x91
+#define OUT1_MANUAL_MODE        0x92
+#define OUT1_ANALOGUE_MODE      0x93
+#define OUT1_CONTACT_MODE       0x94
+#define OUT1_FLUID_LEVEL        0x95
+#define OUT1_LEAK_DETECT        0x96
+
+///////////////////////////////////////////
+// NVM OUTPUT1 LOGIC CONSTANTS
+//////////////////////////////////////////
+#define OUT1_LOGIC_HI           0x97
+#define OUT1_LOGIC_LO           0x98
+
+///////////////////////////////////////////
+// NVM OUTPUT2 CONSTANTS
+//////////////////////////////////////////
+#define OUT2_GENERAL_ALARM      0xA0
+#define OUT2_RUN_STATUS         0xA1
+#define OUT2_MANUAL_MODE        0xA2
+#define OUT2_ANALOGUE_MODE      0xA3
+#define OUT2_CONTACT_MODE       0xA4
+#define OUT2_FLUID_LEVEL        0xA5
+#define OUT2_LEAK_DETECT        0xA6
+
+///////////////////////////////////////////
+// NVM OUTPUT2 LOGIC CONSTANTS
+//////////////////////////////////////////
+#define OUT2_LOGIC_HI           0xA7
+#define OUT2_LOGIC_LO           0xA8
+
+///////////////////////////////////////////
+// NVM 4-20mA CONSTANTS
+//////////////////////////////////////////
+#define _4_20MA_OUT_FULL_SCALE          0xB0
+#define _4_20MA_OUT_MATCH_INPUT_SCALE   0xB1
+
+///////////////////////////////////////////
+// NVM SPEED LIMIT CONSTANTS
+//////////////////////////////////////////
+#define MAX_SPEED_LIMIT                 125.0
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// NUCLEO-F746ZG PIN ASSIGNMENTS
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////
+// SHAFT ENCODER
+//////////////////////////////////////////
+#define USB_BOOTLOAD            PF_11//Output to set Bootload mode
+
+///////////////////////////////////////////
+// SHAFT ENCODER
+//////////////////////////////////////////
+#define A                       PG_10//Schematic Checked 051219  
+#define B                       PG_11//Schematic Checked 051219  
+#define I                       PG_12//Schematic Checked 051219  
+
+///////////////////////////////////////////
+// POWER GOOD SIGNAL
+//////////////////////////////////////////
+#define PWR_GOOD                PD_0
+
+///////////////////////////////////////////
+// LEAK DETEDCT INPUT
+//////////////////////////////////////////
+#define LEAK_DETECT_INPUT       PD_1//Schematic Checked 051219 
+
+///////////////////////////////////////////
+// REMOTE CONTROL INPUTS
+//////////////////////////////////////////
+#define RUN_STOP                PB_3//Schematic Checked 051219
+#define EXT_CONT                PB_4//Schematic Checked 051219 
+#define RMT_FLD_REC             PB_5//Schematic Checked 051219 
+
+///////////////////////////////////////////
+// 4-20mA CONTROL OUTPUTS
+//////////////////////////////////////////
+#define ALARM_OUT1              PC_7//Schematic Checked 051219 
+#define ALARM_OUT2              PA_15//Schematic Checked 051219 
+
+///////////////////////////////////////////
+// (ADC1/3) 4-20mA ANALOGUE INPUT
+//////////////////////////////////////////
+#define ANA_IN_A0               PA_3//Schematic Checked 051219 
+
+///////////////////////////////////////////
+// (DAC1/1) 4-20mA ANALOGUE OUTPUT
+//////////////////////////////////////////
+#define ANA_OUT_DAC1            PA_4//Schematic Checked 
+
+///////////////////////////////////////////
+// SPI (SPI4)
+//////////////////////////////////////////
+#define SCLK                    PE_2//Schematic Checked 051219 
+#define SSEL                    PE_4//Schematic Checked 051219 
+#define MISO                    PE_5//Schematic Checked 051219 
+#define MOSI                    PE_6//Schematic Checked 051219 
+
+///////////////////////////////////////////
+// BUTTON MEMBRANE INDICATOR 
+//////////////////////////////////////////
+#define START_LED               PC_6//Schematic Checked 051219 
+#define STOP_LED                PB_12//Schematic Checked 051219 
+
+#define STOP_BTN                PB_13//Schematic Checked, grey box build only 
+#define START_BTN               PB_15//Schematic Checked, grey box build only 
+
+
+///////////////////////////////////////////
+// MOTOR CONTROL / ALARMS 
+//////////////////////////////////////////
+#define MOT_EN                  PB_11//MOVED_280220 
+#define MOT_DIR                 PB_10//MOVED_280220 
+#define N_BRK                   PF_15
+#define FG_OUT                  PF_13
+#define N_FAULT                 PF_14
+#define PWM                     PD_15
+
+///////////////////////////////////////////
+// NETION POWER CONTROL 
+//////////////////////////////////////////
+#define NEX_PWR                 PF_12//Schematic Checked 051219 
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// NUCLEO-F746ZG RS232 COMMUNICATION
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+/*USART
+
+USART1 = VERDERBUS
+USART2 = NEXTION DISPLAY
+USART3 = BOOTLOADER
+USART6 = MOTOR CONTROL
+
+*/
+
+
+///////////////////////////////////////////
+// BAUS RATES
+///////////////////////////////////////////
+#define SLOW_BAUD               9600
+#define MED_BAUD                115200
+#define FAST_BAUD               921600
+
+///////////////////////////////////////////
+// USART2 NEXTION DISPLAY
+///////////////////////////////////////////
+#define USART2_TX               PD_5
+#define USART2_RX               PD_6
+
+///////////////////////////////////////////
+// USART6 ED MOTOR CONTROL
+///////////////////////////////////////////
+#define USART6_TX               PG_14
+#define USART6_RX               PG_9
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// VERDERBUS EXPANSION
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+#define USART1_TX               PA_9//Schematic Checked 051219
+#define USART1_RX               PA_10//Schematic Checked 051219 
+#define SPI5_SSEL               PF_6//Schematic Checked 051219  
+#define SPI5_SCK                PF_7//Schematic Checked 051219  
+#define SPI5_MISO               PF_8//Schematic Checked 051219  
+#define SPI5_MOSI               PF_9//Schematic Checked 051219  
+#define ADC1_1                  PA_1//Schematic Checked 051219  
+#define ADC1_2                  PA_2//Schematic Checked 051219  
+#define DAC1_2                  PA_5//Schematic Checked 051219  
+#define VBD0                    PG_0
+#define VBD1                    PG_1
+#define VBD2                    PG_2
+#define VBD3                    PG_3
+#define VBD4                    PG_4//Schematic Checked 051219 
+#define VBD5                    PG_5//Schematic Checked 051219 
+#define VBD6                    PG_6//Schematic Checked 051219 
+#define VBD7                    PG_7//Schematic Checked 051219 
+#define PWM3_3                  PC_8//Schematic Checked 051219    
+
+#endif  /* DEFINITIONS_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Functions.cpp	Wed Jun 17 10:11:19 2020 +0000
@@ -0,0 +1,1030 @@
+#include <string> 
+#include "main.h"
+#include "Functions.h"
+#include "Definitions.h"
+#include "Boolean.h"
+#include "NextionLCD.h"
+#include "mbed_debug.h"
+#include "mbed.h"
+#include "Languages.h"
+#include "Ser25lcxxx.h"
+#include "NVM.h"
+#include "Watchdog.h"
+#include "NextionPages.h"
+#include "Controls.h"
+#include "Threads.h"
+#include "ISR.h"
+#include "FastPWM.h"
+
+///////////////////////////////////////////////////////////////////////////////
+// MBED OBJECTS
+///////////////////////////////////////////////////////////////////////////////
+extern NextionLCD lcd;//Tx, Rx, Nextion Port
+
+Thread thread;
+volatile uint16_t loopTime = 0; 
+volatile bool loopTimeFlag = false;
+volatile bool readFlag = false;
+
+///////////////////////////////////////////////////////////////////////////////
+// VARIABLES
+///////////////////////////////////////////////////////////////////////////////
+bool incFlag = false;
+bool decFlag = false;
+bool okFlag =  false;
+bool manFlag = false;
+
+uint8_t pumpType = QDOS_30;
+uint8_t calState = ZERO;
+
+///////////////////////////////////////////////////////////////////////////////
+// THREADS
+///////////////////////////////////////////////////////////////////////////////
+void loopTime_thread(){
+
+    while(1){
+        #ifdef LOOP_TIME        
+            if(readFlag){
+                pc.printf("\r\n\r\n Loop Time \t=  %d us",loopTime);
+                readFlag = false;
+                loopTimeFlag = true;                
+            }
+        #endif
+    }
+}
+
+void loopTimeMeasure(void){
+
+    #ifdef LOOP_TIME                                          
+        if(!loopTimeFlag){
+            //wait_us(20);//add a known time to verify the accuracy of the loop timer
+            tSec.stop();    
+            loopTime  = tSec.read_us();
+            //run_stat_out_oc = 1;
+            readFlag = true;         
+        }
+        else{
+            tSec.reset();
+            tSec.start(); 
+            loopTimeFlag = false;   
+            //run_stat_out_oc = 0;          
+        }
+    #endif    
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// ARRAYS
+///////////////////////////////////////////////////////////////////////////////
+char buffer[20];
+
+const uint8_t uOutPut1_ID[7] = {
+    OUT1_GENERAL_ALARM,
+    OUT1_RUN_STATUS,         
+    OUT1_MANUAL_MODE,        
+    OUT1_ANALOGUE_MODE,      
+    OUT1_CONTACT_MODE,       
+    OUT1_FLUID_LEVEL,        
+    OUT1_LEAK_DETECT        
+};
+
+const uint8_t uOutPut2_ID[7] = {
+    OUT2_GENERAL_ALARM,
+    OUT2_RUN_STATUS,         
+    OUT2_MANUAL_MODE,        
+    OUT2_ANALOGUE_MODE,      
+    OUT2_CONTACT_MODE,       
+    OUT2_FLUID_LEVEL,        
+    OUT2_LEAK_DETECT        
+};
+
+const uint8_t uFlowUnitID[10] = {
+    PERCENT,
+    GPD,
+    GPH,
+    ML_HR,                 
+    ML_MIN,
+    L_DAY,                  
+    L_HR,                
+    L_MIN,
+    OZ_MIN,            
+    RPM 
+};
+
+const string menuStringArray[3][10] = {//[Group][Item], 2 groups, 10 items in each group i.e menuItems[1][6]= "Leak Detect"
+     "%\0",       //0x10
+     "gpd\0",     //0x11
+     "gph\0",     //0x12
+     "ml/hr\0",   //0x13
+     "ml/min\0",  //0x14
+     "l/day\0",   //0x15
+     "l/hr\0",    //0x16
+     "l/min\0",   //0x17   
+     "oz/min\0",  //0x18
+     "RPM\0",     //0x19 
+
+    "General Alarm\0",
+    "Run Status\0",
+    "Manual Mode\0",
+    "Analogue Mode\0",
+    "Contact Mode\0",
+    "Fluid Level\0",
+    "Leak Detect\0",
+    "A1\0",
+    "B1\0",
+    "C1\0",
+
+    "General Alarm\0",
+    "Run Status\0",
+    "Manual Mode\0",
+    "Analogue Mode\0",
+    "Contact Mode\0",
+    "Fluid Level\0",
+    "Leak Detect\0",
+    "A2\0",
+    "B2\0",
+    "C2\0"   
+};
+
+const float fMaxFlowUnits[5][10] = {
+
+      //QDOS 30          
+      100.0,//%
+      190.2,//gpd
+      7.925,//gph
+      30.00,//l/hr
+      500.0,//ml/min
+      720.0,//l/day
+      30.00,//l/hr
+      0.500,//l/min        
+      17.6,//oz
+      125.0,//rpm
+
+      //VDOS 20          
+      100.0,
+      131.06,
+      5.46,
+      20670.00,
+      344.50,
+      496.08,
+      20.67,
+      0.34,        
+      12.15,
+      65.0,
+
+      //VDOS 30  
+      100.0,
+      191.56,
+      7.98,
+      30210.00,
+      503.50,
+      725.04,
+      30.21,
+      0.50,        
+      17.76,
+      95.00,
+
+      //VDOS 60  
+      100.0,
+      380.83,
+      15.87,
+      60060.00,
+      1001.00,
+      1441.44,
+      60.06,
+      1.00,        
+      35.31,
+      110.00,    
+
+      //VDOS 120  
+      100.0,
+      765.62,
+      31.90,
+      120744.00,
+      2012.40,
+      2897.86,
+      120.74,
+      2.01,        
+      70.98,
+      129.00        
+};      
+
+const float fMinFlowUnits[5][10] = {
+
+      //QDOS 30          
+      0.1,//%
+      0.1,//gpd
+      0.001,//gph
+      1.0,//ml/hr
+      0.1,//ml/min
+      0.1,//l/day
+      0.01,//l/hr
+      0.001,//l/min        
+      0.1,//oz
+      0.1,//rpm
+
+      //VDOS 20          
+      0.2,
+      0.26,
+      0.01,
+      41.34,
+      0.87,
+      0.99,
+      0.04,
+      0.00,        
+      0.02,
+      5.0,
+
+      //VDOS 30  
+      0.2,
+      0.38,
+      0.02,
+      60.42,
+      1.01,
+      1.45,
+      0.06,
+      0.00,        
+      0.04,
+      5.0,
+
+      //VDOS 60  
+      0.2,
+      0.76,
+      0.03,
+      120.12,
+      2.0,
+      2.88,
+      0.16,
+      0.00,        
+      0.07,
+      5.0,    
+
+      //VDOS 120  
+      0.2,
+      1.53,
+      0.06,
+      241.49,
+      4.02,
+      5.80,
+      0.24,
+      0.00,        
+      0.14,
+      5.0        
+};  
+
+
+///////////////////////////////////////////////////////////////////////////////
+// FUNCTIONS
+///////////////////////////////////////////////////////////////////////////////
+void sysInit(void){
+
+    wait(0.250);//settle time
+
+    pc.baud(MED_BAUD);//Debug Port
+    usart6.baud(MED_BAUD);//Motor Controller Port
+
+    led1=ON; 
+    led2=ON; 
+    led3=ON; 
+    wait(2.00);
+    led1=OFF; 
+    led2=OFF; 
+    led3=OFF; 
+
+    nexInit(MED_BAUD);       
+    reset();
+
+    //4-20mA Control Outputs
+    alarmOut1 = OFF;
+    alarmOut2 = OFF;
+
+    initNVM();//Initialise the NVM memory       
+    loadNVM(&nvm,0);//loads EEPROM content to nvm data structure
+
+    nvm.pumpOnOff = PUMP_OFF;
+    writeNVMByte(PUMP_ON_OFF,nvm.pumpOnOff);
+
+    nvm.speedLimit = 125.0;
+    writeNVMfloat(NVM_SPEED_LIMIT,nvm.speedLimit); 
+
+    #ifdef DEBUG_NVM
+            
+        pc.printf("\r\n\r\n HARDWARE \t\t=  %s", HARDWARE.c_str());
+        pc.printf("\r\n\r\n SOFTWARE \t\t=  %s",SOFTWARE.c_str());
+        pc.printf("\r\n\r\n AUTHOR \t\t=  %s",AUTHOR.c_str());
+        pc.printf("\r\n\r\n DATE \t\t\t=  %s",__DATE__);        
+        pc.printf("\r\n\r\n TIME \t\t\t=  %s",__TIME__);   
+        pc.printf("\r\n\r\n ADC Samples \t\t=  %d", ADC_SAMPLES);   
+        pc.printf("\r\n\r\n SPI Freq \t\t=  %d(Hz)", SPI_FREQ);  
+        pc.printf("\r\n\r\n Watchdog  \t\t=  %.1f(Seconds)", WDT);                  
+        pc.printf("\r\n\r\n Flow Unit\t\t=  0x%X", nvm.flowUnits);
+        pc.printf("\r\n\r\n Run Mode\t\t=  0x%X", nvm.runMode);
+        pc.printf("\r\n\r\n Auto Restart\t\t=  0x%X", nvm.autoRestart);                                
+        pc.printf("\r\n\r\n Pump Head\t\t=  0x%X", nvm.pumpHeadStatus);
+        pc.printf("\r\n\r\n Alarm\t\t\t=  0x%X", nvm.alarm);
+        pc.printf("\r\n\r\n Head Side\t\t=  0x%X", nvm.headSide);
+        pc.printf("\r\n\r\n Pump On/Off\t\t=  0x%X", nvm.pumpOnOff);                                                              
+        pc.printf("\r\n\r\n Speed Limit Val\t=  %.2f", nvm.speedLimit);        
+        pc.printf("\r\n\r\n Flow Unit Val\t\t=  %.2f", nvm.flowUnitVal);
+        pc.printf("\r\n\r\n Analogue Cal mA Low\t=  %.2f(mA)", nvm.mA_low);                                
+        pc.printf("\r\n\r\n Analogue Cal mA High\t=  %.2f(mA)", nvm.mA_high);     
+        pc.printf("\r\n\r\n Analogue Cal Flow Low\t=  %.2f(%%)", nvm.flow_low);                                     
+        pc.printf("\r\n\r\n Analogue Cal Flow High\t=  %.2f(%%)", nvm.flow_high);    
+        pc.printf("\r\n\r\n ADC min V\t\t=  %.2f(V)", nvm.adc_min_v);   
+        pc.printf("\r\n\r\n ADC max V\t\t=  %.2f(V)", nvm.adc_max_v);  
+        pc.printf("\r\n\r\n DAC V low factor\t=  %f", nvm.dac_v_low);     
+        pc.printf("\r\n\r\n DAC V high factor\t=  %f", nvm.dac_v_high);      
+        pc.printf("\r\n\r\n DAC V low \t\t=  %.2f(V)", nvm.dac_v_low*VDD);     
+        pc.printf("\r\n\r\n DAC V high \t\t=  %.2f(V)", nvm.dac_v_high*VDD);        
+        pc.printf("\r\n\r\n Remote Stop Pump Input =  0x%X", nvm.rmtStopPump);           
+        pc.printf("\r\n\r\n Output 1\t\t=  0x%X", nvm.outPut1);   
+        pc.printf("\r\n\r\n Output 1 Logic \t=  0x%X", nvm.outPut1Logic);          
+        pc.printf("\r\n\r\n Output 2\t\t=  0x%X", nvm.outPut2);   
+        pc.printf("\r\n\r\n Output 2 Logic \t=  0x%X", nvm.outPut2Logic);                    
+        pc.printf("\r\n\r\n 4-20mA Output\t\t=  0x%X", nvm._4_20mAoutPut);     
+
+        usart6.printf("\r\n\r\n Motor Controller Active");
+                                                                                                                                                                             
+    #endif
+    
+    //pumpType = VDOS_120;
+    pumpType = QDOS_30;    
+
+    //tachoIn.rise(&isr1);
+
+    motor(MOTOR_RPM_MIN, CW, BRAKE_OFF, MOTOR_DISABLE, 100);     
+
+    anaOut_mA(I_3MA);//analogue output forced to 3mA   
+
+    wd.Configure(WDT);       // sets the timeout 
+    
+    thread.start(callback(loopTime_thread));
+}
+
+void nexInit(uint32_t baud){
+
+    /* Set the baudrate which is for debug and communicate with Nextion screen. */
+
+    nexPwrCont = ON;//Nextion power is on    
+    wait(0.25);     
+    lcd.nexSetBaud(baud);//Set Nextion baud        
+    lcd.nexSetBckLite(100);//program backlight to be off at power up      
+}
+
+float motorRPM(void){
+    static float rpm = 0.1;
+    //static float flowUnits = 0.1;
+
+    rpm = mapF(nvm.flowUnitVal, minScale, maxScale, 0, fMaxFlowUnits[pumpType][9]);
+          
+    //flowUnits = mapF(rpm,0.1,125.0,minScale,maxScale);
+
+    //return(flowUnits);      
+    return(rpm);          
+}
+
+float incDecControl(float *val, float precision, float min, float max, float speedLimit){
+
+    static bool incMode = false;
+    static bool decMode = false;
+    static float speed = SLOW_SPEED;
+
+    if(motorRPM() < speedLimit){
+
+        if(*val < max){
+            if((tPush.read() > START_DELAY)&&(incMode)){//INC button pressed > 0.5 seconds, speed set to fast update
+
+                if(tSpeed.read() > speed){//fast and then slow after 4 seconds
+                    tSpeed.reset();
+                
+                    if(tPush.read() > DELAY_LONG){//INC button pressed > 4 seconds, now set speed to slow update                        
+                        tPush.stop();
+                        speed = FAST_SPEED;                    
+                    }            
+                    *val+=flowUnitPrec(precision-1);                                                                                                                                 
+                }    
+            }
+            else//INC button released
+                if(incFlag){
+                    incFlag = false;
+                    incMode = true;
+                    decMode = false;
+                    speed = SLOW_SPEED;    
+                    *val+=flowUnitPrec(precision);//Inc 0.1            
+                }
+                if(*val > max)
+                    *val = max;                     
+        }
+    }
+    else
+        if(motorRPM() > speedLimit)
+            *val-=0.1;
+
+    if(*val > min){
+
+        if((tPush.read() > START_DELAY)&&(decMode)){
+
+            if(tSpeed.read() > speed){//fast and then slow after 4 seconds
+                tSpeed.reset();
+            
+                if(tPush.read() > DELAY_LONG){//INC button pressed > 4 seconds, now set speed to slow update                        
+                    tPush.stop();
+                    speed = FAST_SPEED;                    
+                }
+                *val-=flowUnitPrec(precision-1);                                                                                                                                 
+            }                                                                                     
+        }
+        else
+            if(decFlag){
+                decFlag = false;
+                decMode = true;
+                incMode = false;
+                speed = SLOW_SPEED;                         
+                *val-=flowUnitPrec(precision);//Dec 0.1    
+            }
+            if(*val < min)//catch fix
+                *val = min;   
+
+    }                
+    return(mapF(*val, 0.0, max, 0.0, 100.0));//return percentage multiplier
+}   
+
+long mapI(long x, long in_min, long in_max, long out_min, long out_max){
+  return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
+}
+
+float mapF(float in, float inMin, float inMax, float outMin, float outMax) {
+  // check it's within the range
+  if (inMin<inMax) { 
+    if (in <= inMin) 
+      return outMin;
+    if (in >= inMax)
+      return outMax;
+  } else {  // cope with input range being backwards.
+    if (in >= inMin) 
+      return outMin;
+    if (in <= inMax)
+      return outMax;
+  }
+  // calculate how far into the range we are
+  float scale = (in-inMin)/(inMax-inMin);
+  // calculate the output.
+  return outMin + scale*(outMax-outMin);
+}
+
+void diags(void){
+    pc.printf("////////////////////////////////////////////////////////////////////////////////\r\n");
+    pc.printf("//Neptune Diagnostics\r\n");
+    pc.printf("////////////////////////////////////////////////////////////////////////////////\r\n");
+}
+ 
+uint8_t decodeByteNVM(uint8_t nvmByte, uint8_t *prec){
+/*
+    Decode Byte from NVM
+
+    Function decodes nvm byte and displays and:-    
+    * Displays the approriate string for the passed nvm byte
+    * Sets the flow unit precision when nvm byte is a flow unit
+    * Sets the min and max scale when nvm bytes is a flow unit
+ */
+    uint8_t list = 0;
+    uint8_t i = ZERO;
+    bool error = false;
+
+    switch(nvmByte){     
+
+        case OUT1_GENERAL_ALARM:      
+        case OUT1_RUN_STATUS:        
+        case OUT1_MANUAL_MODE:        
+        case OUT1_ANALOGUE_MODE:     
+        case OUT1_CONTACT_MODE:       
+        case OUT1_FLUID_LEVEL:       
+        case OUT1_LEAK_DETECT:  list = OUTPUT1_LIST; break;     
+
+        case OUT2_GENERAL_ALARM:      
+        case OUT2_RUN_STATUS:         
+        case OUT2_MANUAL_MODE:        
+        case OUT2_ANALOGUE_MODE:      
+        case OUT2_CONTACT_MODE:       
+        case OUT2_FLUID_LEVEL:        
+        case OUT2_LEAK_DETECT:  list = OUTPUT2_LIST; break;         
+
+        case PERCENT:   
+        case GPD:          
+        case ML_MIN:                   
+        case L_DAY:                
+        case OZ_MIN:                
+        case RPM:       *prec = 1;  break;                                               
+                        
+        case ML_HR:                    
+        case L_HR:      *prec = 2;  break;     
+
+        case GPH:    
+        case L_MIN:     *prec = 3;  break;        
+
+        default:        pc.printf("Error flowUnitsNVM : Last case %d", nvmByte);  
+                        error = true;    
+    }  
+
+    if(!error){
+        i = ReadListIndexNVM(nvmByte);        
+
+        minScale = fMinFlowUnits[pumpType][i];    
+        maxScale = fMaxFlowUnits[pumpType][i];//float, max flow unit range
+
+        lcd.nexSendFloat("p1right",maxScale, 2);//page 1 right text box          
+        lcd.nexSendTxt("units", menuStringArray[list][i]);
+    }
+
+    return(i);
+}
+
+uint8_t ReadListIndexNVM(uint8_t nvm){
+/*
+    return the list item index
+*/
+    return(0x0f&nvm);
+}
+
+float flowUnitPrec(int8_t precision){
+/*
+precision = number of decimal places, 1, 2 & 3
+returns a float used to Inc/Dec flow units
+
+      100.0,
+      139.6,
+      5.815,
+      22.01,
+      366.9,
+      528.2,
+      22.01,
+      0.367,        
+      12.9,
+      55.0,
+*/
+
+    float precisionVal;
+
+    switch(precision){
+        case -1:    precisionVal = 10; break; 
+        case 0:     precisionVal = 1; break; 
+        case 1:     precisionVal = 0.1; break; 
+        case 2:     precisionVal = 0.01; break;       
+        case 3:     precisionVal = 0.001; break;                              
+        default:pc.printf("Error incDec : Last case %d",precision);  
+    }
+    return(precisionVal);
+}
+
+float low_pass_filterF(float x) {
+
+   //https://www.eevblog.com/forum/beginners/averaging-or-smoothing-adc-values/
+
+   static float samples[ADC_SAMPLES];
+   static int i = ZERO;
+   static float total = ZERO;
+
+   /* Update the moving average */  
+   total += x - samples[i];
+   samples[i] = x;
+
+   /* Update the index */
+   i = (i==(ADC_SAMPLES-1) ? 0 : i+1);
+
+   return total/ADC_SAMPLES;
+}
+
+uint8_t runModeNVM(uint8_t settingIndex){
+    uint8_t task;
+/*
+    Converts EEPROM setting to state machine case setting
+
+ */
+    switch(settingIndex)
+    {
+        case MANUAL:        task = MANUAL_SET; break;
+        case ANALOGUE:      task = ANALOGUE_SET; break;
+        case CONTACT:       task = CONTACT_SET; break;
+        case FLUID_REC:     task = FLUIDREC_SET; break;
+        case FLOW_CAL:      task = FLOW_CAL_SET;  break;
+        default:            pc.printf("Error runModeNVM : Last case %d",settingIndex);  
+    }    
+    return(task);
+}
+
+void dbgStates(uint8_t state){
+    
+    #ifdef DEBUG_STATES
+
+        static uint8_t lastState = INITIALISE;
+        
+        if(state != lastState){
+            switch(state){
+                case INITIALISE:    pc.printf("\r\nSTATE = INITIALISE");  break;
+                case START:         pc.printf("\r\nSTATE = START");  break;
+                case STOP:          pc.printf("\r\nSTATE = STOP");  break;
+                case STOP_SCRN:     pc.printf("\r\nSTATE = STOP_SCRN");  break;
+                case RUNNING:       pc.printf("\r\nSTATE = RUNNING");  break;
+                case ANALOGUE_SET:  pc.printf("\r\nSTATE = ANALOGUE_SET");  break;
+                case DOSE:          pc.printf("\r\nSTATE = DOSE");  break;
+                case MANUAL_SET:    pc.printf("\r\nSTATE = MANUAL_SET");  break;
+                case PROFIBUS:      pc.printf("\r\nSTATE = PROFIBUS");  break;
+                case STALL:         pc.printf("\r\nSTATE = STALL");  break;
+                case DEBUG:         pc.printf("\r\nSTATE = DEBUG");  break;
+                case DIAGS:         pc.printf("\r\nSTATE = DIAGS");  break;
+                case ALARM:         pc.printf("\r\nSTATE = ALARM");  break;
+                case FAULT:         pc.printf("\r\nSTATE = FAULT");  break;
+                case READ_KEYS:     pc.printf("\r\nSTATE = READ_KEYS");  break;
+                case MANUAL_MODE:   pc.printf("\r\nSTATE = MANUAL_MODE");  break;
+                case ANALOGUE_MODE: pc.printf("\r\nSTATE = ANALOGUE_MODE");  break;
+                case PROFIBUS_MODE: pc.printf("\r\nSTATE = PROFIBUS_MODE");  break;
+                case CONTACT_SET:   pc.printf("\r\nSTATE = CONTACT_SET");  break;
+                case FLUIDREC_SET:  pc.printf("\r\nSTATE = FLUIDREC_SET");  break;
+                case READ_NVM:      pc.printf("\r\nSTATE = READ_NVM");  break;
+                case RESET_VARS:    pc.printf("\r\nSTATE = RESET_VARS");  break;
+                case ANA_CAL:       pc.printf("\r\nSTATE = ANA_CAL");  break;
+                case REMOTE_IN:     pc.printf("\r\nSTATE = REMOTE_IN");  break;                
+
+                default:            pc.printf("\r\nSTATE = UNDEFINED");
+            }
+    
+            lastState = state;
+        }
+
+    #endif
+}
+ 
+uint8_t touchBtn(uint8_t nexPage, uint8_t nexBtn, uint8_t nexPushPop){
+    /*
+        Function returns true if the button matches input parameters
+    */
+ 
+    uint8_t state = false;
+    
+    if((page == nexPage)&&(id == nexBtn)&&(pushPop == nexPushPop))
+        state = true;
+
+    return(state);
+}
+
+uint8_t anaCal(void){
+
+    char* buffer;
+    float tmp;
+    bool drawCompleted = false;
+    uint8_t task = ANA_CAL;
+
+    switch(calState){
+    
+            case CAL1_SCRN:                                   
+                                if(scrnUpdate){
+                                    scrnUpdate = false;
+
+                                    lcd.nexSendTxt("title","4-20mA Calibration 1/4");   
+                                    lcd.nexSendTxt("info2","signal");                                              
+                                    lcd.nexSendTxt("sigName","Signal High");                                                                                               
+                                    lcd.nexSendTxt("t1","mA");                                
+
+                                    if(manFlag){                                                   
+                                        lcd.nexSendTxt("info1","Enter HIGH");       
+                                        lcd.nexSendTxt("info2","signal");      
+                                        lcd.nexSendTxt("info3","using +/- keys");                                                                                                                                                                                                                         
+                                    }                                        
+                                    else                     
+                                    {                                                                                   
+                                        lcd.nexSendTxt("info1","Apply HIGH");                                                 
+                                        lcd.nexSendTxt("info2","signal");    
+                                    }                                        
+                                
+                                    lcd.nexSendTxt("info4","then press OK");             
+                                    lcd.nexSendTxt("info5",""); 
+                                }
+
+                                if(manFlag)
+                                    incDecControl(&nvm.mA_high, 2, LOW_CAL_MIN, HIGH_CAL_MAX, nvm.speedLimit);//2 decimal places for mA                                                        
+                                else                                                           
+                                    nvm.mA_high = anaIn_mA();                                                                                                         
+                                        
+                                lcd.nexSendFloat("anaVal", nvm.mA_high, 2);                                                                                                                           
+                                tmp = nvm.mA_high;//make a copy of the data to be 
+
+                                drawCompleted = drawCalGraph(X1,Y1,mapF(nvm.mA_high, I_0MA, I_21MA,X1,X2),Y2,DRAW);//wait for graph to complete
+
+                                if(okFlag && drawCompleted){
+                                    drawCompleted = okFlag = false;                                    
+                                    scrnUpdate = true;  
+                                    calState++;
+                                    
+                                    if(writeNVMfloat(NVM_ANA_MA_CAL_HIGH, nvm.mA_high))
+                                        lcd.nexSendTxt("info5","Data Varified"); 
+                                    else
+                                    {
+                                            lcd.nexSendTxt("info5","Varify Failed");                                     
+                                            while(1);
+                                    }
+
+                                    wait(1.0);
+                                    lcd.nexSendTxt("info5",""); 
+                                }
+                                break;
+
+            case CAL2_SCRN:                 
+                                if(scrnUpdate){
+                                    scrnUpdate = false;
+
+                                    lcd.nexSendTxt("title","4-20mA Calibration 2/4");   
+                                    lcd.nexSendTxt("info1","Enter MAX");     
+                                    lcd.nexSendTxt("info2","flow signal");  
+                                    lcd.nexSendTxt("info3","using +/- keys");  
+                                    lcd.nexSendTxt("info4","then press OK");                                                                                                                               
+                                    lcd.nexSendTxt("flowName","Flow High");                                                                                            
+                                    lcd.nexSendTxt("t0","%");       
+                                    drawCalGraph(X1,Y1,mapF(nvm.mA_high, I_0MA, I_21MA,X1,X2),Y2,ERASE);//mA high, now erase the line read for next cal screen                                                                                                                                                                                                          
+                                }
+                                            
+                                incDecControl(&nvm.flow_high, 1, 0.0, 100.0, nvm.speedLimit);//2 decimal places for mA                                                                                              
+                                lcd.nexSendFloat("flowVal", nvm.flow_high, 1);   
+                                drawCompleted = drawCalGraph(X1,Y1,mapF(nvm.mA_high, I_0MA, I_21MA,X1,X2),mapF(nvm.flow_high, 0.0, 100.0,Y1,Y2),DRAW);//%, draw the line  
+
+                                if(okFlag && drawCompleted){
+                                    drawCompleted = okFlag = false;                                 
+                                    scrnUpdate = true;  
+                                    calState++;
+
+                                    if(writeNVMfloat(NVM_ANA_FLOW_CAL_HIGH, nvm.flow_high))                
+                                        lcd.nexSendTxt("info5","Data Varified"); 
+                                    else
+                                    {
+                                            lcd.nexSendTxt("info5","Varify Failed");                                     
+                                            while(1);
+                                    }                           
+                                    
+                                    wait(1.0);
+                                    lcd.nexSendTxt("info5","");                                   
+                                }                                                          
+                                break;
+
+            case CAL3_SCRN:                                                                                                                                                                                                                      
+                                if(scrnUpdate){
+                                    scrnUpdate = false;
+
+                                    lcd.nexSendTxt("title","4-20mA Calibration 3/4");              
+                                    lcd.nexSendTxt("info2","signal");                                  
+                                    lcd.nexSendTxt("sigName","Signal Low");        
+                    
+                                    lcd.nexSendTxt("flowName","");//Clear these displays                                                                                            
+                                    lcd.nexSendTxt("flowVal","");                                                   
+                                    lcd.nexSendTxt("t0","");                                                                                                                                                               
+
+                                    if(manFlag){                                                   
+                                        lcd.nexSendTxt("info1","Enter LOW");        
+                                        lcd.nexSendTxt("info2","signal");                                                                                         
+                                        lcd.nexSendTxt("info3","using +/- keys");                                                                                                 
+                                    }
+                                    else
+                                    {                                       
+                                        lcd.nexSendTxt("info1","Apply LOW");    
+                                        lcd.nexSendTxt("info2","signal");                                                                                 
+                                    }
+
+                                    lcd.nexSendTxt("info4","then press OK");                                         
+                                    
+                                    drawCalGraph(X1,Y1,mapF(nvm.mA_high, I_0MA, I_21MA,X1,X2),mapF(nvm.flow_high, 0.0, 100.0,Y1,Y2),ERASE);//%, now erase the line read for next cal screen  
+                                }
+                        
+                                if(manFlag)
+                                    incDecControl(&nvm.mA_low, 2, LOW_CAL_MIN, HIGH_CAL_MAX, nvm.speedLimit);//2 decimal places for mA                                                    
+                                else                                
+                                    nvm.mA_low = anaIn_mA();
+                            
+                                lcd.nexSendFloat("anaVal", nvm.mA_low, 2);                     
+                                drawCompleted = drawCalGraph(X1,Y1,mapF(nvm.mA_low, I_0MA, I_21MA,X1,X2),Y2,DRAW);//mA low, draw the line                                              
+
+                                if(okFlag && drawCompleted){
+                                    drawCompleted = okFlag = false;                                        
+                                    scrnUpdate = true;  
+                                    calState++;
+                                                    
+                                    if(writeNVMfloat(NVM_ANA_MA_CAL_LOW, nvm.mA_low))
+                                        lcd.nexSendTxt("info5","Data Varified"); 
+                                    else
+                                    {
+                                            lcd.nexSendTxt("info5","Varify Failed");                                     
+                                            while(1);
+                                    }                           
+                                    
+                                    wait(1.0);
+                                    lcd.nexSendTxt("info5","");                           
+                                }                              
+                                break;
+
+            case CAL4_SCRN:                                                                                                                                   
+                                if(scrnUpdate){
+                                    scrnUpdate = false;
+                                                                        
+                                    lcd.nexSendTxt("title","4-20mA Calibration 4/4");   
+                                    lcd.nexSendTxt("info1","Enter MIN");     
+                                    lcd.nexSendTxt("info2","flow signal");  
+                                    lcd.nexSendTxt("info3","using +/- keys");  
+                                    lcd.nexSendTxt("info4","then press OK");                                                                                                                                           
+                                    lcd.nexSendTxt("flowName","Flow Low");    
+                                    lcd.nexSendTxt("t0","%");   
+                                    drawCalGraph(X1,Y1,mapF(nvm.mA_low, I_0MA, I_21MA,X1,X2),Y2,ERASE);//mA low, now erase the line read for next cal screen                                                                                                                                                                                                                                                                                                                                                                             
+                                }
+                                        
+                                incDecControl(&nvm.flow_low, 1, 0.0, 100.0, nvm.speedLimit);//2 decimal places for mA                                                                                         
+                                lcd.nexSendFloat("flowVal", nvm.flow_low, 1);   
+                                drawCompleted = drawCalGraph(X1,Y1,mapF(nvm.mA_low, I_0MA, I_21MA,X1,X2),mapF(nvm.flow_low, 0.0, 100.0,Y1,Y2),DRAW);//%, draw the line                                              
+
+                                if(okFlag && drawCompleted){
+                                    drawCompleted = okFlag = false;                                                              
+                                    scrnUpdate = true;  
+                                    calState++;                  
+
+                                    if(writeNVMfloat(NVM_ANA_FLOW_CAL_LOW, nvm.flow_low))                                    
+                                        lcd.nexSendTxt("info5","Data Varified");                                         
+                                    else
+                                    {
+                                            lcd.nexSendTxt("info5","Varify Failed");                                     
+                                            while(1);
+                                    }
+  
+                                    wait(1.0);
+                                    lcd.nexSendTxt("info5",""); 
+                                }                                                              
+                                break;                                    
+
+            case COMPLETE_SCRN:                                                                                     
+                                if(scrnUpdate){
+                                    scrnUpdate = false;
+
+                                    calComplete = true;                                    
+
+                                    lcd.nexChgPage(PAGE_18_ANA_CAL_MODE);  
+                                    //lcd.nexSendTxt("title","4 - 20mA Calibration completed");   
+                                    //lcd.nexSendTxt("info2","Analogue = Starts in 4-20mA mode");   
+                                    //lcd.nexSendTxt("info4","Manual = Starts in Manual mode");                                                                                             
+                                    //lcd.nexSendTxt("btnRight","Manual");  
+                                    //lcd.nexSendTxt("btnLeft","Analogue");   
+
+                                    stopLED = 0;//turn off the stop LED                         
+                                    drawCalGraph(X1,Y1,mapF(nvm.mA_low, I_0MA, I_21MA,X1,X2),mapF(nvm.flow_low, 0.0, 100.0,Y1,Y2),ERASE);//%, now erase the line read for next cal screen                                 
+                                }                                
+                                break;
+                                                                                         
+    }
+
+    return(task);
+}
+
+bool drawCalGraph(float x1, float y1, float x2, float y2,bool draw){
+    
+    static uint16_t cntr = ZERO;    
+    static float lastX1 = X1;
+    static float lastY1 = Y1;
+    static float lastX2 = X2;
+    static float lastY2 = Y2;
+    bool updated = false;
+
+    if(draw){
+
+        if(cntr < DRAW_SPEED){
+            cntr++; 
+            updated = false;    
+        }
+        else   
+        {
+            cntr=ZERO;
+
+            stopLED = !stopLED;               
+
+            lcd.nexDrawLine (lastX1, lastY1, lastX2, lastY2, WHITE);//Erase the previous red line calibration posotion   
+            wait(0.001); 
+            lcd.nexDrawLine (x1, y1, x2, y2, RED);//draw the new red line calibration position   
+
+            lastX1 = x1; 
+            lastY1 = y1; 
+            lastX2 = x2; 
+            lastY2 = y2; 
+            updated = true;
+        }                
+    }
+    else    
+        lcd.nexDrawLine (x1, y1, x2, y2, WHITE);//erase the new red line calibration position   
+    
+    return(updated);                    
+}
+
+uint8_t retLastStoredTask(uint8_t storedTask){
+/*
+    Returns to the last stored task
+*/
+
+    uint8_t task;
+
+    switch(storedTask){
+        case STOP_SCRN:         task = STOP_SCRN;//refresh stop screen 
+                                break;
+
+        case ANALOGUE_SET:      task = ANALOGUE_SET;//refresh 
+                                break;
+
+        case MANUAL_SET:        task = MANUAL_SET;//refresh  
+                                break;
+        default:;
+    }
+    return(task);
+}
+ 
+void flowUnitInc(uint8_t *fUx, uint8_t *fUy, uint8_t *fUz){
+
+    if(*fUx > ZERO) 
+        *fUx-=1;
+    else
+        *fUx = P8_MENU_ITEMS;                                                                    
+
+    if(*fUy > ZERO) 
+        *fUy-=1;
+    else
+        *fUy = P8_MENU_ITEMS;    
+
+    if(*fUz > ZERO) 
+        *fUz-=1;
+    else
+        *fUz = P8_MENU_ITEMS;                                                                        
+
+    lcd.nexSendTxt("top", menuStringArray[0][*fUx]);                                                                                                                                                                                                        
+    lcd.nexSendTxt("data", menuStringArray[0][*fUy]);    
+    lcd.nexSendTxt("bot", menuStringArray[0][*fUz]);     
+
+    nvm.flowUnits = uFlowUnitID[*fUy];    
+}
+
+void flowUnitDec(uint8_t *fUx, uint8_t *fUy, uint8_t *fUz){
+
+    if(*fUx < P8_MENU_ITEMS)         
+        *fUx+=1;                        
+    else 
+        *fUx = ZERO;
+
+    if(*fUy < P8_MENU_ITEMS)           
+        *fUy+=1;                        
+    else 
+        *fUy = ZERO;
+
+    if(*fUz < P8_MENU_ITEMS)           
+        *fUz+=1;                        
+    else 
+        *fUz = ZERO;
+
+    lcd.nexSendTxt("top", menuStringArray[0][*fUx]);                                                                                                                                                                                                        
+    lcd.nexSendTxt("data", menuStringArray[0][*fUy]);    
+    lcd.nexSendTxt("bot", menuStringArray[0][*fUz]);     
+
+    nvm.flowUnits = uFlowUnitID[*fUy]; 
+} 
+
+void dispList(uint8_t i[3], uint8_t incDec, uint8_t stringList, const string sArray[2][10], uint8_t maxListStrings){    
+    
+    const uint8_t x=0,y=1,z=2;
+
+    if(incDec){
+        if(i[x] < maxListStrings)         
+            i[x]+=1;                        
+        else 
+            i[x] = ZERO;
+
+        if(i[y] < maxListStrings)           
+            i[y]+=1;                        
+        else 
+            i[y] = ZERO;
+
+        if(i[z] < maxListStrings)           
+            i[z]+=1;                        
+        else 
+            i[z] = ZERO;        
+    }else{
+        if(i[x] > ZERO)         
+            i[x]-=1;                        
+        else 
+            i[x] = maxListStrings;
+
+        if(i[y] > ZERO)           
+            i[y]-=1;                        
+        else 
+            i[y] = maxListStrings;
+
+        if(i[z] > ZERO)           
+            i[z]-=1;                        
+        else 
+            i[z] = maxListStrings;
+    }
+    
+    lcd.nexSetFontCol("data", RED);
+    lcd.nexSendTxt("top", sArray[stringList][i[x]]);                                                                                                                                                                                                        
+    lcd.nexSendTxt("data", sArray[stringList][i[y]]);    
+    lcd.nexSendTxt("bot", sArray[stringList][i[z]]);          
+}
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Functions.h	Wed Jun 17 10:11:19 2020 +0000
@@ -0,0 +1,59 @@
+
+#ifndef FUNCTIONS_H
+#define FUNCTIONS_H
+
+#include "mbed.h"
+#include "Definitions.h"
+
+extern Thread thread;
+extern volatile uint16_t loopTime; 
+extern volatile bool loopTimeFlag;
+extern volatile bool readFlag;
+
+extern uint8_t pumpType;
+extern const uint8_t uOutPut1_ID[7];
+extern const uint8_t uOutPut2_ID[7];
+extern const uint8_t uFlowUnitID[10];
+extern const string sFlowUnits[];
+extern const float fMaxFlowUnits[][10];
+extern const float fMinFlowUnits[][10];
+
+extern const string menuStringArray[][10];
+
+extern bool incFlag;
+extern bool decFlag;
+extern bool okFlag;
+extern bool manFlag;
+
+extern uint8_t calState;
+
+uint8_t decodeByteNVM(uint8_t nvmByte, uint8_t *prec);
+
+char* itoa(int num, char* str, int base);  
+long mapI(long x, long in_min, long in_max, long out_min, long out_max);
+float mapF(float in, float inMin, float inMax, float outMin, float outMax);
+void nexScrnUpdate(void);
+void dbgNextion(void);
+void eepromTesting(void);
+void infoScrn(void);
+void NVM_update_Thread(void);
+
+void nexInit(uint32_t baud);
+float low_pass_filterF(float x);
+void keyScan(void);
+float flowUnitPrec(int8_t precision);
+uint8_t runModeNVM(uint8_t settingIndex);
+void dbgStates(uint8_t state);
+uint8_t touchBtn(uint8_t nexPage, uint8_t nexBtn, uint8_t nexPushPop);
+uint8_t anaCal(void);
+float incDecControl(float *val, float precision, float min, float max, float speedLimit);
+bool drawCalGraph(float x1, float y1, float x2, float y2,bool draw);
+uint8_t retLastStoredTask(uint8_t storedTask);
+void flowUnitInc(uint8_t *flowUx, uint8_t *flowUy, uint8_t *flowUz);
+void flowUnitDec(uint8_t *flowUx, uint8_t *flowUy, uint8_t *flowUz);
+void dispList(uint8_t i[3], uint8_t incDec, uint8_t stringList, const string sArray[2][10], uint8_t maxListStrings);
+uint8_t ReadListIndexNVM(uint8_t nvm);
+void loopTimeMeasure(void);
+float motorRPM(void);
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ISR.cpp	Wed Jun 17 10:11:19 2020 +0000
@@ -0,0 +1,50 @@
+#include <string> 
+#include "main.h"
+#include "Functions.h"
+#include "Definitions.h"
+#include "Boolean.h"
+#include "NextionLCD.h"
+#include "mbed_debug.h"
+#include "mbed.h"
+#include "Languages.h"
+#include "Ser25lcxxx.h"
+#include "NVM.h"
+#include "Watchdog.h"
+#include "NextionPages.h"
+#include "Controls.h"
+#include "Threads.h"
+#include "FastPWM.h"
+
+
+InterruptIn tachoIn(FG_OUT);
+Timer t1Sec;
+volatile float rpm = 0;
+
+
+void isr1(){
+/*
+    Tacho feedback from BLDC drive controller
+*/
+    static uint16_t cntr =0;   
+    static bool pulse = HI;
+
+    if(cntr > 5){
+        ml+=0.1;
+        cntr = 0;
+    }
+    cntr++;
+    
+/* 
+    if(pulse){//tacho pulse rising edge 
+        t1Sec.reset();
+        t1Sec.start();
+        //startLED = ON;
+    }
+    else{
+        t1Sec.reset();//tacho pulse falling edge
+        t1Sec.start();
+        //startLED = OFF;
+    }
+    pulse^=1;
+*/    
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ISR.h	Wed Jun 17 10:11:19 2020 +0000
@@ -0,0 +1,10 @@
+#ifndef ISR_H 
+#define ISR_H 
+
+#include "mbed.h"
+extern Timer t1Sec,t2Sec;
+extern InterruptIn tachoIn;
+extern volatile float rpm;
+extern void isr1();
+
+#endif 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Languages.cpp	Wed Jun 17 10:11:19 2020 +0000
@@ -0,0 +1,40 @@
+#include <cstdlib>
+#include <string>
+#include "main.h"
+#include "Functions.h"
+#include "Definitions.h"
+#include "Boolean.h"
+#include "NextionLCD.h"
+#include "mbed.h"
+#include "platform/CircularBuffer.h"
+#include "rtos.h"
+#include "Threads.h"
+#include "Languages.h"
+#include "FastPWM.h"
+
+
+uint8_t menu = 0;
+
+//struct{
+//const string teststring[][] = {
+//                                "String1","String1","String1","String1","String1","String1","String1","String1","String1","String1",
+//                                "String2","String1","String1","String1","String1","String1","String1","String1","String1","String1",
+//                                };
+
+//}Language;
+
+const string english[][STRINGS_PER_MENU] = {
+                                            "Neptune Running\0","String1\0","String1\0","String1\0","String1\0","String1\0","String1\0","String1\0","String1\0","String1\0",
+                                            "String2","String1","String1","String1","String1","String1","String1","String1","String1","String1",
+                                            "String1","String1","String1","String1","String1","String1","String1","String1","String1","String1",
+                                            "String2","String1","String1","String1","String1","String1","String1","String1","String1","String1",
+                                            "String1","String1","String1","String1","String1","String1","String1","String1","String1","String1",
+                                            "String2","String1","String1","String1","String1","String1","String1","String1","String1","String1",                                                                
+                                            };
+
+const string espanol[][STRINGS_PER_MENU] = {};
+const string francias[][STRINGS_PER_MENU] = {};
+const string deutsch[][STRINGS_PER_MENU] = {};
+const string portugues[][STRINGS_PER_MENU] = {};
+const string italiano[][STRINGS_PER_MENU] = {};
+const string netherlands[][STRINGS_PER_MENU] = {};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Languages.h	Wed Jun 17 10:11:19 2020 +0000
@@ -0,0 +1,8 @@
+#ifndef LANGUAGES_H
+#define LANGUAGES_H
+
+#include "mbed.h"
+
+#define STRINGS_PER_MENU 10
+
+#endif 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MotorControl.cpp	Wed Jun 17 10:11:19 2020 +0000
@@ -0,0 +1,23 @@
+#include <string> 
+#include "main.h"
+#include "Functions.h"
+#include "Definitions.h"
+#include "Boolean.h"
+#include "NextionLCD.h"
+#include "mbed_debug.h"
+#include "mbed.h"
+#include "Languages.h"
+#include "Ser25lcxxx.h"
+#include "NVM.h"
+#include "Watchdog.h"
+#include "NextionPages.h"
+#include "Controls.h"
+#include "Threads.h"
+#include "ISR.h"
+#include "FastPWM.h"
+#include "MotorControl.h"
+/* 
+MotorControl::MotorControl(PinName Tx, PinName Rx) : ED(Tx, Rx){
+
+}
+*/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MotorControl.h	Wed Jun 17 10:11:19 2020 +0000
@@ -0,0 +1,14 @@
+#ifndef MOTORCONTROL_H
+#define MOTORCONTROL_H
+
+#include "mbed.h"
+/* *
+class MotorControl 
+{
+  public:
+
+    MotorControl(PinName Tx, PinName Rx);
+
+};
+*/
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/NVM.cpp	Wed Jun 17 10:11:19 2020 +0000
@@ -0,0 +1,248 @@
+#include <cstdlib>
+#include <string>
+#include "main.h"
+#include "Functions.h"
+#include "Definitions.h"
+#include "Boolean.h"
+#include "NextionLCD.h"
+#include "mbed.h"
+#include "platform/CircularBuffer.h"
+#include "rtos.h"
+#include "Threads.h"
+#include "Languages.h"
+#include "Ser25lcxxx.h"
+#include "NVM.h"
+#include "FastPWM.h"
+
+extern Ser25LCxxx eeprom;
+extern Serial pc;//Debug Port via USB
+extern SPI spi;//SPI
+
+const char romNVM[NVM_SIZE]=    {   //Deafault NVM Parameters written to empty EEPROM                    
+                                    RPM,//Flow Units
+                                    MANUAL,//Run Mode
+                                    AUTO_RESTART_OFF,
+                                    PUMP_HEAD_OK,
+                                    ALARM_OFF,
+                                    HEAD_LEFT,
+                                    PUMP_OFF,
+                                    0x00,
+                                    0x00,//8 MAX speed limit, 125.0
+                                    0x00,
+                                    0xFA,
+                                    0x42,
+                                    0xCD,//12 Flow Unit Value, 0.1                                                                                                                                                
+                                    0xCC,
+                                    0xCC,
+                                    0x3D,                                                                                                            
+                                    0x33,//16 Analogue low cal float value loc 0, 4.10
+                                    0x33,
+                                    0x84,
+                                    0x40,
+                                    0x0A,//20 Analogue high cal float loc 0, 19.80
+                                    0xD7,     
+                                    0x9F,
+                                    0x41,
+                                    0x00,//24 Flow % low cal float loc 0, 0.00
+                                    0x00,     
+                                    0x00,
+                                    0x00,
+                                    0x00,//28 Flow % high cal float loc 0, 100.00
+                                    0x00,     
+                                    0xC8,
+                                    0x42,  
+                                    0xCD,//32 ADC min V 0.1360V
+                                    0xCC,
+                                    0x4C,
+                                    0x3C,
+                                    0xCF,//36 ADC max V 3.31200V
+                                    0xF7,
+                                    0x53,
+                                    0x40,
+                                    0x03,//40 DAC V low 0.1348 = (0.3030*0.445)//445mV
+                                    0x09,
+                                    0x0A,
+                                    0x3E,
+                                    0xA6,//44 DAC V high 0.90597 = (0.3030*2.99)//2.99V     
+                                    0xED,
+                                    0x67,
+                                    0x3F,
+                                    RMT_STOP_PUMP_HIGH,//48
+                                    OUT1_GENERAL_ALARM,
+                                    OUT1_LOGIC_LO,                                                                          
+                                    OUT2_RUN_STATUS,                         
+                                    OUT2_LOGIC_LO,                                      
+                                    _4_20MA_OUT_FULL_SCALE//53
+                                };
+
+                                
+           
+void clearNVM(void){
+/*
+    Clears NVM EEPROM space to 0xFF
+*/
+    #ifdef DEBUG_NVM
+        pc.printf("\r\n\r\nClear All NMV settings (page 0 - 1)");//Display the buffer
+    #endif
+
+    eeprom.clearMem();
+}
+
+void wrtDefNVM(struct settingsNVM *data){
+
+    #ifdef DEBUG_NVM
+        pc.printf("\r\n\nWriting default NVM Settings from NVM ROM to NVM data structure and EEPROM");
+    #endif    
+    
+    memcpy(data,romNVM,NVM_SIZE);
+
+    writeNVM(NVM_START,NVM_SIZE,data);//Write NVM structure to EEPROM     
+}
+
+void loadNVM(struct settingsNVM *data, bool loadDefaults)
+{
+    char* tmp;
+
+    if((blkChkEEPROM() == true)||(loadDefaults == true))//Virgin EEPROM     
+    {
+        #ifdef DEBUG_NVM
+            pc.printf("\r\n\nVirgin EEPROM so load the default NVM ROM data");         
+        #endif
+
+        clearNVM();
+        wrtDefNVM(data);
+    }
+    else
+    {
+        tmp = eeprom.read(NVM_START,NVM_SIZE);
+
+        memcpy(data,tmp,NVM_SIZE);
+        
+        #ifdef DEBUG_NVM        
+            pc.printf("\r\n\nEEPROM Contents");                 
+            for(int i=0; i < NVM_SIZE; i++)      
+                pc.printf("\r\n|(%d) \t 0x%02X |",i,tmp[i]);
+    
+            pc.printf("\r\n");
+        #endif             
+
+        free(tmp);           
+    }
+}
+
+bool writeNVM(uint16_t start_addr,uint8_t len,struct settingsNVM *data){
+/*
+    Writes All contents of data structure to EEPROM
+*/
+    bool writeOK = true;
+ 
+    if(!eeprom.write(start_addr,len,(char*)data)){
+        #ifdef DEBUG_NVM
+            pc.printf("\r\n\nWritting All NMV Settings\r\n");//Display the buffer            
+        #endif
+        writeOK = false;          
+    }
+    else
+    {
+        #ifdef DEBUG_NVM
+            pc.printf("\r\n\nNMV Write FAILED\r\n");//Display the buffer     
+        #endif
+    }
+
+    return(writeOK);
+}
+ 
+bool writeNVMfloat(uint16_t addr,float val){
+
+    bool writeOK = true;
+
+    #ifdef DEBUG_NVM
+        pc.printf("\r\n\r\nWriting Float %f to EEPROM at base Addr %d", val, addr);//Display the buffer
+    #endif    
+        
+    if(!eeprom.write(addr, sizeof(val), (char*)&val)){
+            #ifdef DEBUG_NVM
+                pc.printf("\r\n\r\nEEPROM Write Fail");
+            #endif   
+            writeOK = false;     
+    }
+
+    return(writeOK);
+}
+
+bool writeNVMByte(uint16_t addr,uint8_t val){
+
+    static uint16_t lastAddr = 0;
+    static uint8_t lastVal = 0;
+    bool writeOK = true;
+
+    if((addr != lastAddr)||(val != lastVal)){
+        #ifdef DEBUG_NVM
+            pc.printf("\r\n\r\nWriting Byte to 0x%02X to EEPROM at Addr %d", val, addr);
+        #endif    
+        
+        if(!eeprom.write(addr, sizeof(val), (char*)&val)){
+            #ifdef DEBUG_NVM
+                pc.printf("\r\n\r\nEEPROM Write Fail");
+            #endif   
+            writeOK = false;     
+        }
+        else
+            #ifdef DEBUG_NVM
+                pc.printf("\tWrite OK");
+            #endif    
+
+        lastAddr = addr;
+        lastVal = val;
+    }
+
+    return(writeOK);
+}
+
+bool blkChkEEPROM(void)
+{
+    /*
+       Checks if ANY NVM location in the EEPROM is 0xFF, if so the EEPROM is deemed to be a virgin EEPROM
+    */
+
+    bool blank = true;
+    uint8_t i;
+
+    char* store = eeprom.read(NVM_START,NVM_SIZE);
+
+    for (i=0;i<NVM_SIZE;i++)
+    {
+        #ifdef DEBUG_NVM
+            pc.printf("\r\n\nBlank Check EEPROM = 0x%02X, Index = %d",store[i],i); 
+        #endif    
+
+        if(store[i] != BLANK)
+        {            
+            #ifdef DEBUG_NVM        
+                pc.printf("\r\n\nEEPROM has NVM settings so load up the NVM data into NVM RAM");                 
+                for(int i=0; i < NVM_SIZE; i++)      
+                    pc.printf("\r\n|(%d) \t 0x%02X |",i,store[i]);
+        
+                pc.printf("\r\n");
+            #endif
+
+            blank = false;
+            break;
+        }
+    }
+
+    if(i==NVM_SIZE)
+    {
+        #ifdef DEBUG_NVM
+            pc.printf("\r\n\nNVM EEPROM IS BLANK :-)"); 
+        #endif    
+    }
+
+    return(blank);    
+}
+
+void initNVM(void){
+    spi.format(8,3);
+    spi.frequency(SPI_FREQ);
+    Ser25LCxxx eeprom(&spi,SSEL,BYTE_SIZE,PAGE_SIZE);//CS SSEL
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/NVM.h	Wed Jun 17 10:11:19 2020 +0000
@@ -0,0 +1,19 @@
+
+#ifndef NVM_H
+#define NVM_H
+
+#include "mbed.h"
+
+extern const char romNVM[];
+
+bool writeNVM(uint16_t start_addr,uint8_t len,struct settingsNVM *data);
+void clearNVM(void);
+bool blkChkEEPROM(void);
+bool writeNVMByte(uint16_t addr,uint8_t val);
+bool writeNVMfloat(uint16_t addr,float val);
+void wrtDefNVM(struct settingsNVM *data);
+void initNVM(void);
+void loadNVM(struct settingsNVM *data, bool loadDefaults);
+
+
+#endif 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/NextionLCD.cpp	Wed Jun 17 10:11:19 2020 +0000
@@ -0,0 +1,416 @@
+#include <cstdlib>
+#include <string> 
+#include "main.h"
+#include "Functions.h"
+#include "Definitions.h"
+#include "Boolean.h"
+#include "NextionLCD.h"
+#include "mbed.h"
+#include "Languages.h"
+#include "NVM.h"
+#include "Controls.h"
+#include "FastPWM.h"
+#include <cstring>
+
+///////////////////////////////////////////////////////////////////////////////
+// MBED
+///////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////
+// VARIABLES
+///////////////////////////////////////////////////////////////////////////////
+bool scrnUpdate = true;//Update the Nexion screen
+
+volatile bool keyScanFlag;
+
+uint8_t nexDataLSB;
+uint8_t nexDataMSB;
+volatile uint8_t page = 0;
+volatile uint8_t id= 0;
+volatile bool pushPop = 0;
+
+///////////////////////////////////////////////////////////////////////////////
+// CONSTANTS
+///////////////////////////////////////////////////////////////////////////////
+bool push = 1;
+bool pop = 0;
+
+///////////////////////////////////////////////////////////////////////////////
+// DEBUG
+///////////////////////////////////////////////////////////////////////////////
+volatile char dbgNexMsg[20];
+volatile int dbgMRxIdx;
+volatile bool debugFlag;
+volatile bool tx_true;
+
+NextionLCD::NextionLCD(PinName Tx, PinName Rx) : lcd(Tx, Rx){
+    lcd.baud(9600);    
+    mTouch=false;
+    mRxIdx=0;
+    lcd.printf("rest%c%c%c", 0xff, 0xff, 0xff);    
+    lcd.printf("rest%c%c%c", 0xff, 0xff, 0xff);
+
+    #ifdef DEBUG_LCD
+        pc.printf("\r\n\r\nNextionLCD Rst\r\n");
+    #endif   
+
+    wait(1.0);
+    lcd.attach(callback(this,&NextionLCD::RxInterrupt),Serial::RxIrq);
+}
+
+void NextionLCD::nexRst(void){
+    lcd.printf("rest%c%c%c", 0xff, 0xff, 0xff);   
+    lcd.printf("rest%c%c%c", 0xff, 0xff, 0xff);
+
+    #ifdef DEBUG_LCD
+        pc.printf("\r\n\r\nnexRst\r\n");
+    #endif      
+}
+
+void NextionLCD::nexSetFont(string id, uint8_t val){
+    static string newId = 0;
+    static uint8_t newVal = 0;
+    
+    if((id != newId)||(val != newVal)){    
+        lcd.printf("%s.font=%d%c%c%c",id.c_str(),val, 0xff, 0xff, 0xff); 
+        newId = id;
+        newVal = val;
+
+        #ifdef DEBUG_LCD
+            pc.printf("\r\n\r\nnexSetFont %s %d\r\n",id.c_str(),val);
+        #endif            
+    }
+}
+
+void NextionLCD::nexSetBckLite(uint8_t val){//ok
+/*
+dim : use dim to instanteniously change backlight intensity, this is not saved in NVM and forgotten once power cycled
+dims: use dims to instanteniously change backlight intensity, this is saved in NVM and remembered after power cycle.
+*/
+    static uint8_t newVal = 0;
+
+    if(val != newVal){
+        lcd.printf("dims=%d%c%c%c",val, 0xff, 0xff, 0xff);
+        newVal = val;
+
+        #ifdef DEBUG_LCD
+            pc.printf("\r\n\r\nnexSetBcklite = %d\r\n",val);
+        #endif            
+    }
+}
+
+void NextionLCD::nexSetBaud(uint32_t baud){//ok
+    static uint32_t newBaud = 0;
+
+    if(baud != newBaud){
+        lcd.printf("baud=%d%c%c%c",baud, 0xff, 0xff, 0xff);//Set Nextion display to high baud    
+        wait(0.5);    
+        lcd.baud(baud);//Set Mbed target to high baud    
+        wait(0.5);    
+        newBaud = baud;
+
+        #ifdef DEBUG_LCD
+            pc.printf("\r\n\r\nnexSetBaud = %u\r\n",baud);
+        #endif            
+    }
+}
+
+void NextionLCD::nexChgPage(uint8_t nexPage){//ok
+    lcd.printf("page %d%c%c%c",nexPage,0xff, 0xff, 0xff);    
+
+    #ifdef DEBUG_LCD
+        pc.printf("\r\n\r\nnexChgPage = %d\r\n",nexPage);
+    #endif          
+}
+
+void NextionLCD::nexSetDSBtn(string id, uint8_t on_off){    
+    
+    if(on_off == ON)
+        lcd.printf("%s.val=1%c%c%c",id.c_str(),0xff, 0xff, 0xff);     
+    else
+        if(on_off == OFF)
+            lcd.printf("%s.val=0%c%c%c",id.c_str(),0xff, 0xff, 0xff);     
+                      
+    #ifdef DEBUG_LCD
+        pc.printf("\r\n\r\nnexSetDSBtn %s %d\r\n",id.c_str(),on_off);
+    #endif                    
+}
+
+void NextionLCD::nexRotArrow(bool on_off){//ok
+    static bool newOnOff = 0;
+ 
+    if(on_off != newOnOff){
+
+        if(on_off == ON){
+            lcd.printf("arrow.picc=19%c%c%c", 0xff, 0xff, 0xff);    
+            lcd.printf("arrowTimer.en=1%c%c%c", 0xff, 0xff, 0xff); 
+        }
+        else
+            if(on_off == OFF){
+                lcd.printf("arrowTimer.en=0%c%c%c", 0xff, 0xff, 0xff); 
+                lcd.printf("arrow.picc=18%c%c%c", 0xff, 0xff, 0xff);             
+            }
+
+        newOnOff = on_off;
+
+
+        #ifdef DEBUG_LCD
+            pc.printf("\r\n\r\nnexRotArrow = %d\r\n", on_off);
+        #endif             
+    }          
+}
+
+void NextionLCD::nexDispSymbol(string id, bool on_off){   
+    static string newId = 0;    
+    static bool newOnOff = 0;
+    
+    if((id != newId)||(on_off!= newOnOff)){        
+
+        if(on_off == ON)
+            nexSetCrop(id, 1);//display symbol      
+        else
+            if(on_off == OFF)        
+                nexSetCrop(id, 16);//white page                  
+
+        newId = id;    
+        newOnOff = on_off;       
+
+        #ifdef DEBUG_LCD
+            pc.printf("\r\n\r\nnexDispSymbol %s %d\r\n", id.c_str(),on_off );
+        #endif              
+    }
+}
+
+void NextionLCD::nexSetCrop(string id, uint16_t picc){//ok
+/*
+   q0 = arrow crop image
+   picc = 1//Turn rotation arrow off
+   picc = 2// pos1 displayed
+   picc = 3// pos2 displayed
+   picc = 4// pos3 displayed
+   picc = 5// pos4 displayed    
+
+*/ 
+    static string newId = 0;
+    static uint16_t newPicc = 0;
+
+    if((id != newId)||(picc!= newPicc)){
+        lcd.printf("%s.picc=%d%c%c%c",id.c_str(),picc,0xff, 0xff, 0xff);     
+        newId = id;     
+        newPicc = picc;
+
+        #ifdef DEBUG_LCD
+            pc.printf("\r\n\r\nnexSetCrop %s %d\r\n", id.c_str(),picc);
+        #endif             
+    }
+}
+
+void NextionLCD::nexSetTimer(string id,uint16_t tim, uint16_t on_off){//ok
+    lcd.printf("%s.tim=%d%c%c%c",id.c_str(),tim,0xff, 0xff, 0xff);      
+    lcd.printf("%s.en=%d%c%c%c",id.c_str(),on_off,0xff, 0xff, 0xff);    
+
+    #ifdef DEBUG_LCD
+        pc.printf("\r\n\r\nnexSetTimer %s %d %d \r\n", id.c_str(),tim,on_off);
+    #endif                    
+}
+
+void NextionLCD::nexSetSlider(string id, uint16_t sliderVal){//ok
+    static string newId = 0;
+    static uint16_t newSliderVal = 0;
+
+    if((id != newId)||(sliderVal!= newSliderVal)){
+        lcd.printf("%s.val=%d%c%c%c",id.c_str(),sliderVal,0xff, 0xff, 0xff);         
+        newId = id;
+        newSliderVal = sliderVal;
+
+        #ifdef DEBUG_LCD
+            pc.printf("\r\n\r\nnexSetSlider %s %d\r\n", id.c_str(),sliderVal);
+        #endif             
+    }
+}
+
+void NextionLCD::nexSetPrgBar(string id, uint16_t progBarVal){//ok
+    static string newId = 0;
+    static uint16_t newProgBarVal = 0;
+
+    if((id != newId)||(progBarVal!= newProgBarVal)){
+        lcd.printf("%s.val=%d%c%c%c",id.c_str(),progBarVal,0xff, 0xff, 0xff);         
+        newId = id;
+        newProgBarVal = progBarVal;
+
+        #ifdef DEBUG_LCD
+            pc.printf("\r\n\r\nnexSetPrgBar %s %d\r\n", id.c_str(),progBarVal);
+        #endif          
+    }      
+}
+
+void NextionLCD::nexSendTxt(string id,string txt){//ok
+    static string newId = 0;
+    static string newTxt = 0;
+    
+    if((id != newId)||(txt != newTxt)){
+        lcd.printf("%s.txt=\"%s\"%c%c%c",id.c_str(),txt.c_str(),0xff, 0xff, 0xff);           
+        newId = id;
+        newTxt = txt;
+
+        #ifdef DEBUG_LCD
+            pc.printf("\r\n\r\nnexSendTxt %s %s\r\n",id.c_str(),txt.c_str());
+        #endif           
+    }        
+}
+
+void NextionLCD::nexSendFloat(string id, float val ,uint8_t precision){
+/*
+    In C, the printf() statement allows the precision lengths to be supplied in the parameter list.
+
+    printf("%*.*f", 7, 3, floatValue);
+
+    where the asterisks are replaced with first and second values, respectively.    
+*/
+    static string newId = 0;
+    static float newVal = 0;
+    
+    if((id != newId)||(val != newVal)){        
+        lcd.printf("%s.txt=\"%.*f\"%c%c%c",id.c_str(), precision, val, 0xff, 0xff, 0xff);                
+        newId = id;
+        newVal = val;
+
+        #ifdef DEBUG_LCD
+            pc.printf("\r\n\r\nnexSendFloat string=%s, pre=%d, val=%f\r\n",id.c_str(), precision, val);        
+        #endif          
+    }
+}
+
+void NextionLCD::nexSetFontCol(string id, uint16_t color){    
+    static string newId = 0;    
+    static uint16_t newColor = 0;    
+
+    if((id != newId)||(color!= newColor)){
+        lcd.printf("%s.pco=%d%c%c%c",id.c_str(),color,0xff, 0xff, 0xff);   
+        newId = id;    
+        newColor = color;
+
+        #ifdef DEBUG_LCD
+            pc.printf("\r\n\r\nnexSetFontCol %s %d\r\n", id.c_str(),color);
+        #endif          
+    }
+}
+
+void NextionLCD::nexSendVal(string id,uint16_t val){
+    static string newId = 0;
+    static uint16_t newVal = 0;
+    
+    if((id != newId)||(val!= newVal)){    
+        lcd.printf("%s.txt=\"%d\"%c%c%c",id.c_str(), val, 0xff, 0xff, 0xff);         
+        newId = id;
+        newVal = val;
+
+        #ifdef DEBUG_LCD
+            pc.printf("\r\n\r\nnexSendVal %s %d\r\n", id.c_str(),val);
+        #endif          
+    }
+}
+
+void NextionLCD::nexSendGetVal(string id){
+    static string newId = 0;
+
+    if(id != newId){    
+        lcd.printf("get %s.val%c%c%c",id.c_str(),0xff, 0xff, 0xff);   
+        newId = id;
+
+        #ifdef DEBUG_LCD
+            pc.printf("\r\n\r\nnexSendGetVal %s\r\n",id.c_str());
+        #endif          
+    }             
+}
+
+void NextionLCD::ClrScr(uint16_t color){//ok 
+    lcd.printf("cls %d%c%c%c", color, 0xff, 0xff, 0xff);        
+
+    #ifdef DEBUG_LCD
+        pc.printf("\r\n\r\nClrScr %d\r\n",color);
+    #endif      
+}
+
+void NextionLCD::nexLoadSD(void){
+    nexPwrCont = ON;//Nextion power is on    
+    wait(0.50);            
+    nexSetBckLite(5);//program backlight to be off at power up
+    wait(5.0);      
+    nexPwrCont = OFF;
+    wait(5.0);    
+    nexPwrCont = ON;//Nextion power is on   
+    wait(0.25);        
+
+    #ifdef DEBUG_LCD
+        pc.printf("\r\n\r\nnexLoadSD\r\n");
+    #endif      
+}
+
+void NextionLCD::nexDrawLine(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color) {
+    static uint16_t newX1,newY1,newX2,newY2,newColor = 0;
+
+    if((x1 != newX1)||(y1 != newY1)||(x2 != newX2)||(y2 != newY2)||(color != newColor)){
+        lcd.printf("line %d,%d,%d,%d,%d%c%c%c", x1, y1, x2, y2, color, 0xff, 0xff, 0xff);
+        newX1 = x1;
+        newY1 = y1;
+        newX2 = x2;
+        newY2 = y2;
+        newColor = color;       
+
+        #ifdef DEBUG_LCD
+            pc.printf("\r\n\r\nnexDrawLine x1=%d y1=%d x2=%d y2=%d col=%d\r\n",x1, y1, x2, y2, color);
+        #endif                                   
+    }
+}
+
+void NextionLCD::RxInterrupt(void){
+/*
+    Decode Nextion messages
+*/    
+    char c;
+    
+    if(lcd.readable()){
+
+        debugFlag = true;//Debug all 
+
+        c = lcd.getc(); 
+        mRxMsg[mRxIdx] = c;  
+        dbgNexMsg[mRxIdx] = c;//make a copy of the message in dbgNexMsg[]     
+        dbgMRxIdx = mRxIdx++;//Save a copy of the index counter in dbgMRxIdx
+
+
+        /* 
+            These are touch screen evernt and by there nature slow so 
+            it should no be necessary to have to process these received touch event that quickly
+            so no need to just set a flag in the RX ISR and let a thread do the processing it can 
+            ALL be done with the RX ISR
+        */
+
+
+        if((mRxIdx >= 3) && (mRxMsg[mRxIdx-1] == 0xff) && (mRxMsg[mRxIdx-2] == 0xff) && (mRxMsg[mRxIdx-3] == 0xff)){//valid rx message           
+        
+            mRxIdx=0;
+            //////////////////////////////debugFlag = true;
+
+            //led1=1; 
+        
+            if(mRxMsg[0] == TOUCH_EVENT){//Nextion RX Touch Event
+
+                page = mRxMsg[PAGE];//get the page
+                id = mRxMsg[ID];//get the component ID
+                pushPop = mRxMsg[PUSHPOP];//get the push/pop state
+
+                keyScanFlag = true;//set key scn flag for main routine
+
+            }
+         
+            if(mRxMsg[0] == 0x71){//Nextion RX Numeric Data
+                //led1=1;                            
+                scrnUpdate = true;
+                nexDataLSB = mRxMsg[1];
+                nexDataMSB = mRxMsg[2];
+            }            
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/NextionLCD.h	Wed Jun 17 10:11:19 2020 +0000
@@ -0,0 +1,90 @@
+/* NextionLCD Library v1.0
+ * Copyright (c) 2018 Grant Phillips
+ * grant.phillips@mandela.ac.za
+ *
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+ 
+#ifndef NEXTIONLCD_H
+#define NEXTIONLCD_H
+ 
+#include "mbed.h"
+
+#define BLACK   0
+#define BLUE    31
+#define BROWN   48192
+#define GREEN   1024
+#define YELLOW  65504
+#define RED     63488
+#define GRAY    33840
+#define WHITE   65535
+ 
+//extern NextionLCD lcd;//Tx, Rx, Nextion Port
+
+extern bool push;
+extern bool pop;
+extern volatile bool keyScanFlag;
+extern bool scrnUpdate;//Update the Nexion screen
+
+extern uint8_t nexDataLSB;
+extern uint8_t nexDataMSB;
+extern volatile uint8_t page;
+extern volatile uint8_t id;
+extern volatile bool pushPop;
+
+class NextionLCD 
+{
+  public:
+
+    NextionLCD(PinName Tx, PinName Rx);
+    void nexRst(void);
+    void nexSendVal(string id,uint16_t val);
+    void nexSetBckLite(uint8_t val);//ok        
+    void nexCls(string colour);
+    void nexSetBaud(uint32_t baud);//ok                  
+    void nexChgPage(uint8_t page);//ok             
+    void nexSetDSBtn(string id, uint8_t on_off);    
+    void nexRotArrow(bool on_off);
+    void nexSetCrop(string id, uint16_t picc);//ok    
+    void nexSetTimer(string id,uint16_t tim, uint16_t on_off);//ok        
+    void nexSetSlider(string id, uint16_t sliderVal);//ok        
+    void nexSetPrgBar(string id, uint16_t progBarVal);//ok    
+    void nexSendTxt(string id,string txt);//ok
+    void ClrScr(uint16_t color);//ok
+    void nexSendGetVal(string id);    
+    void nexSetFont(string id, uint8_t val);
+    void nexSendFloat(string id,float val,uint8_t p);
+    void nexLoadSD(void);
+    void nexDrawLine(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color);
+    void nexSetFontCol(string id, uint16_t colour);
+    void nexDispSymbol(string id, bool on_off);
+        
+    
+  private:
+    RawSerial lcd;             //Serial object for connecting to Nextion LCD
+    //Serial pc;
+    bool mTouch;
+    int mTouchX, mTouchY;
+    char mRxMsg[40];
+    int mRxIdx;
+    void RxInterrupt(void); //Rx Interrupt
+};
+ 
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/NextionPages.cpp	Wed Jun 17 10:11:19 2020 +0000
@@ -0,0 +1,671 @@
+#include <cstdlib>
+#include <string> 
+#include "main.h"
+#include "Functions.h"
+#include "Definitions.h"
+#include "Boolean.h"
+#include "NextionLCD.h"
+#include "mbed_debug.h"
+#include "mbed.h"
+#include "Languages.h"
+#include "Ser25lcxxx.h"
+#include "NVM.h"
+#include "Watchdog.h"
+#include "Controls.h"
+#include "Threads.h"
+#include "FastPWM.h"
+
+///////////////////////////////////////////////////////////////////////////////
+// MBED OBJECTS
+///////////////////////////////////////////////////////////////////////////////
+extern NextionLCD lcd;//Tx, Rx, Nextion Port
+
+///////////////////////////////////////////////////////////////////////////////
+// VARIABLES
+///////////////////////////////////////////////////////////////////////////////
+bool calComplete = false;
+uint8_t precision = 0;
+uint8_t adjustItem = ADJ_FLOW_UNITS;
+uint8_t menuStringID = FLOW_U_STRING_LIST;//store the last displayed list
+
+///////////////////////////////////////////////////////////////////////////////
+// STRINGS
+///////////////////////////////////////////////////////////////////////////////
+extern string HARDWARE;
+extern string SOFTWARE;
+extern string BUILD;
+extern string DATE; 
+extern string AUTHOR;   
+
+///////////////////////////////////////////////////////////////////////////////
+// FUNCTIONS
+///////////////////////////////////////////////////////////////////////////////
+uint8_t nexPage(uint8_t presentTask, uint8_t savedTask){
+    
+    const uint8_t x=0,y=1,z=2;
+    static uint8_t i[3]={x,y,z};
+    uint8_t task = presentTask;//return the present task unless task in re-assigned by pages
+
+    switch(page){
+        case PAGE_0:                    break;
+
+        case PAGE_1_HOME:                     
+                                        ///////////////////////////////////////////////////////////////////////////////
+                                        // PAGE 1 HOME
+                                        ///////////////////////////////////////////////////////////////////////////////           
+                                        if(touchBtn(PAGE_1_HOME, P1_INC, PUSH)){
+                                            tPush.start();
+                                            tSpeed.start();                                    
+                                            tPop.stop();
+                                            tPop.reset();
+                                            incFlag = true; 
+                                            scrnUpdate = true;
+                                            led1=1;
+                                            led2=0;
+                                        }
+                                        else
+                                        if(touchBtn(PAGE_1_HOME, P1_DEC, PUSH)){
+                                            tPush.start(); 
+                                            tSpeed.start();                                
+                                            tPop.stop();
+                                            tPop.reset();        
+                                            decFlag = true; 
+                                            scrnUpdate = true;    
+                                            led3=1;
+                                            led1=0;     
+                                        }
+                                        else
+                                        if(touchBtn(PAGE_1_HOME, P1_INC, POP)){
+                                            tPush.stop(); 
+                                            tPush.reset();
+                                            tPop.start();
+                                            incFlag = false;     
+                                            led1=0;
+                                            led2=1;  
+                                        }
+
+                                        if(touchBtn(PAGE_1_HOME, P1_DEC, POP)){
+                                            tPush.stop(); 
+                                            tPush.reset();
+                                            tPop.start();
+                                            decFlag = false;     
+                                            led3=0;
+                                            led1=1;  
+                                        }
+                                        else
+                                        if(touchBtn(PAGE_1_HOME, P1_MAX, PUSH)){    
+                                            maxBtnPress = true;             
+                                            task = MAX;                                       
+                                        }
+                                        else                                                            
+                                        if(touchBtn(PAGE_1_HOME, P1_MAX, POP)){    
+                                            maxBtnPress = false;
+                                        }
+                                        else
+                                        if(touchBtn(PAGE_1_HOME, P1_SET, PUSH)){//load the auto restart button with its NVM setting
+
+                                            if(nvm.autoRestart == AUTO_RESTART_ON)
+                                                lcd.nexSetDSBtn("bt0",ON);
+                                            else    
+                                                if(nvm.autoRestart == AUTO_RESTART_OFF)
+                                                lcd.nexSetDSBtn("bt0",OFF);   
+                                        }            
+                                        break;
+
+        case PAGE_2_INFO:
+                                        break;
+        case PAGE_3_MAIN:
+                                        ///////////////////////////////////////////////////////////////////////////////
+                                        // PAGE 3 MAIN MENU
+                                        ///////////////////////////////////////////////////////////////////////////////            
+/*                                        
+                                        if(touchBtn(PAGE_3_MAIN, P3_FLUID_LEV_MON, PUSH)){                            
+
+                                        }
+                                        else
+                                        if(touchBtn(PAGE_3_MAIN, P3_SECURITY, PUSH)){                            
+                                            
+                                        }
+                                        else
+                                        if(touchBtn(PAGE_3_MAIN, P3_CONT_SETTINGS, PUSH)){   
+                        
+                                            
+                                        }  
+                                        else
+*/                                        
+                                        if(touchBtn(PAGE_3_MAIN, P3_INFO, PUSH)){    
+
+                                            //lcd.nexChgPage(BLANK_PAGE);
+
+
+                                            
+                                            lcd.nexChgPage(PAGE_27_ABOUT);
+                                            lcd.nexSendTxt("hardware",HARDWARE);                                                 
+                                            lcd.nexSendTxt("software",SOFTWARE);                                                                                                
+                                            lcd.nexSendTxt("date",__DATE__);  
+                                            lcd.nexSendTxt("time",__TIME__);                                               
+                                            lcd.nexSendTxt("author",AUTHOR);                                                                                                                                                                                                  
+                                            
+                                        }  
+                                        else
+                                        if(touchBtn(PAGE_3_MAIN, P3_BACK, PUSH))
+                                        task = retLastStoredTask(savedTask);                                             
+                                    
+                                        break;    
+                                        
+
+        case PAGE_7_FLUID_LEV_SET:
+                                        ///////////////////////////////////////////////////////////////////////////////
+                                        // PAGE 7 FLUID LEVEL SETTINGS
+                                        ///////////////////////////////////////////////////////////////////////////////    
+/*                                        
+                                        if(touchBtn(PAGE_7_FLUID_LEV_SET, P7_HOME, PUSH))
+                                            task = retLastStoredTask(savedTask); 
+*/                                                               
+                                        break;      
+
+        case PAGE_8_FLOWU_ADJ:
+
+                                        ///////////////////////////////////////////////////////////////////////////////
+                                        // PAGE 8 FLOW UNIT ADJUSTMENT
+                                        ///////////////////////////////////////////////////////////////////////////////                                                                                                                                                        
+                                        if(touchBtn(PAGE_8_FLOWU_ADJ, P8_DEC, PUSH))   
+                                            dispList(i, DEC, menuStringID, menuStringArray, P8_MENU_ITEMS);                                                                                
+                                        else
+                                        if(touchBtn(PAGE_8_FLOWU_ADJ, P8_INC, PUSH))   
+                                            dispList(i, INC, menuStringID, menuStringArray, P8_MENU_ITEMS);  
+                                        else
+                                        if(touchBtn(PAGE_8_FLOWU_ADJ, P8_OK, PUSH)){     
+                                            lcd.nexSetFontCol("data", GREEN);                          
+                                            nvm.flowUnits = uFlowUnitID[i[1]]; 
+                                            writeNVMByte(NVM_FLOW_UNITS,nvm.flowUnits);                                    
+                                            decodeByteNVM(nvm.flowUnits, &precision);
+                                            nvm.flowUnitVal = ((flowPercent/100)*maxScale);
+                                            writeNVMfloat(NVM_FLOWU_VAL,nvm.flowUnitVal);                                                                                                                                                                                                                                                                                      
+                                        }
+                                        else
+                                        if(touchBtn(PAGE_8_FLOWU_ADJ, P8_HOME, PUSH))   
+                                            task = retLastStoredTask(savedTask);                                         
+                                        else
+                                        if(touchBtn(PAGE_8_FLOWU_ADJ, P8_BACK, PUSH))                                           
+                                            lcd.nexChgPage(PAGE_9_SETTINGS);                                                                      
+                                        break;         
+
+        case PAGE_9_SETTINGS:
+                                        ///////////////////////////////////////////////////////////////////////////////
+                                        // PAGE 9 GENERAL SETTINGS
+                                        ///////////////////////////////////////////////////////////////////////////////    
+                                        if(touchBtn(PAGE_9_SETTINGS, P9_AUTO_RESTART, PUSH)){                                                  
+                                            if(nvm.autoRestart ==  AUTO_RESTART_ON){//read the present auto restart state and toggle to alternative state                                    
+                                                lcd.nexSetDSBtn("bt0",OFF);
+
+                                                nvm.autoRestart = AUTO_RESTART_OFF;
+                                                writeNVMByte(NVM_AUTO_RESTART, nvm.autoRestart);                    
+                                            }
+                                            else    
+                                                if(nvm.autoRestart ==  AUTO_RESTART_OFF){
+                                                    lcd.nexSetDSBtn("bt0",ON);
+
+                                                    nvm.autoRestart = AUTO_RESTART_ON;
+                                                    writeNVMByte(NVM_AUTO_RESTART, nvm.autoRestart);                                                                                 
+                                                }    
+                                            //DO NOT RETURN TO A TASK  
+                                        }
+                                        else
+                                        if(touchBtn(PAGE_9_SETTINGS, P9_FLOW_UNITS, PUSH)){                                                  
+                                            lcd.nexChgPage(PAGE_8_FLOWU_ADJ);
+                                            //lcd.nexSendTxt("title","Flow Units");    
+                                            //lcd.nexSendTxt("btnOK","OK");                    
+
+                                            menuStringID = FLOW_U_STRING_LIST;
+
+                                            i[y] = decodeByteNVM(nvm.flowUnits, &precision);
+
+                                            if(i[y] == 0){i[x] = 9; i[z] = 1;}                                            
+                                            else
+                                            if(i[y] == 9){i[x] = 8; i[z] = 0;}
+                                            else{i[x] = (i[1]-1); i[z] = (i[1]+1);}
+
+                                            lcd.nexSendTxt("top",menuStringArray[0][i[x]]); 
+                                            lcd.nexSendTxt("data",menuStringArray[0][i[y]]);   
+                                            lcd.nexSendTxt("bot",menuStringArray[0][i[z]]); 
+                                        }
+/*                                        
+                                        else
+                                        if(touchBtn(PAGE_9_SETTINGS, P9_ASS_NUM, PUSH)){                                                  
+
+                                        }
+                                        else
+                                        if(touchBtn(PAGE_9_SETTINGS, P9_PUMP_LAB, PUSH)){                                                  
+
+                                        }
+                                        else
+                                        if(touchBtn(PAGE_9_SETTINGS, P9_RESTORE, PUSH)){                                                  
+
+                                        }
+                                        else
+                                        if(touchBtn(PAGE_9_SETTINGS, P9_LANG, PUSH)){                                                  
+
+                                        }           
+                                        else
+*/                                        
+                                        if(touchBtn(PAGE_9_SETTINGS, P9_BACK, PUSH))
+                                            task = retLastStoredTask(savedTask); 
+                                        
+                                        break;            
+
+        case PAGE_11_RESET:           
+                                        ///////////////////////////////////////////////////////////////////////////////
+                                        // PAGE 11 RESET RUN HOURS / RESET VOLUME COUNTER
+                                        ///////////////////////////////////////////////////////////////////////////////
+                                        if(touchBtn(PAGE_11_RESET, P11_RESET, PUSH)){    
+
+                                            lcd.nexChgPage(PAGE_11_RESET);
+/*                                    
+                                            if(runHours)                          
+                                                lcd.nexSendFloat("info1",0.0);                                           
+                                            else
+                                            if(volCntr)                                    
+                                                lcd.nexSendFloat("info1",0.0);                 
+*/                                        
+                                        }  
+                                        break;
+
+        case PAGE_12_MODE:
+                                        ///////////////////////////////////////////////////////////////////////////////
+                                        // PAGE 12 CHANGE MODE
+                                        ///////////////////////////////////////////////////////////////////////////////     
+                                        if(touchBtn(PAGE_12_MODE, P12_MANUAL, PUSH)){                                            
+                                            nvm.runMode = MANUAL;//set manual mode
+                                            writeNVMByte(NVM_RUN_MODE, nvm.runMode);//update EEPROM with manual mode             
+                                            //lcd.nexChgPage(PAGE_1_HOME);                                                                                                                                                                                                                                                                                         
+                                            task = STOP_SCRN;                                     
+                                        }
+                                        else
+                                        if(touchBtn(PAGE_12_MODE, P12_ANALOGUE, PUSH)){     
+                                            nvm.runMode = ANALOGUE;//set analogue mode
+                                            writeNVMByte(NVM_RUN_MODE, nvm.runMode);//update EEPROM with analogue mode     
+                                            //lcd.nexChgPage(PAGE_1_HOME);                                                                                                                         
+                                            task = ANALOGUE_SET;                                    
+                                        }
+                                        else
+                                        if(touchBtn(PAGE_12_MODE, P12_ANA_CAL, PUSH)){  
+
+                                            calComplete = false;//for new calibration entry make sure this flag is cleared
+
+                                            lcd.nexChgPage(PAGE_18_ANA_CAL_MODE);    
+                                            //lcd.nexSendTxt("btnLeft","Analogue");    
+                                            //lcd.nexSendTxt("btnRight","Manual");                                    
+                                            //lcd.nexSendTxt("title","4-20mA Calibration");    
+                                            //lcd.nexSendTxt("info1","Select Analogue Signal");    
+                                            //lcd.nexSendTxt("info2","or");  
+                                            //lcd.nexSendTxt("info3","Manual Input");          
+                                            //lcd.nexSendTxt("info4","Calibration"); 
+                                        }                                                
+                                        else
+                                        if(touchBtn(PAGE_12_MODE, P12_CONTACT, PUSH)){  
+                                            //nvm.runMode = CONTACT; 
+                                            //writeNVMByte(NVM_RUN_MODE,nvm.runMode);                             
+                                            //task = runModeNVM(nvm.runMode);//reload page 1 titles   
+                                        }     
+                                        else
+                                        if(touchBtn(PAGE_12_MODE, P12_FLUID_REC, PUSH)){     
+                                            //nvm.runMode = FLUIDREC; 
+                                            //writeNVMByte(NVM_RUN_MODE,nvm.runMode);
+                                            //task = runModeNVM(nvm.runMode);//reload page 1 titles  
+                                        }                                         
+                                        else
+                                        if(touchBtn(PAGE_12_MODE, P12_FLOW_CAL, PUSH)){   
+
+                                        }
+                                        else
+                                        if(touchBtn(PAGE_12_MODE, P12_BACK, PUSH)){   
+                                            task = retLastStoredTask(savedTask);  
+                                        }                                           
+                                        break;
+
+        case PAGE_14_ANA_CAL:
+                                        ///////////////////////////////////////////////////////////////////////////////
+                                        // PAGE 14 ANALOGUE CALIBRATION CONTROLS
+                                        ///////////////////////////////////////////////////////////////////////////////                                                       
+                                        if(touchBtn(PAGE_14_ANA_CAL, P14_INC, PUSH)){
+                                            tPush.start(); 
+                                            tPop.stop();
+                                            tPop.reset();
+                                            incFlag = true; 
+                                            scrnUpdate = true;
+                                            led1=1;
+                                            led2=0;
+                                        }
+                                        else
+                                        if(touchBtn(PAGE_14_ANA_CAL, P14_DEC, PUSH)){ 
+                                            tPush.start(); 
+                                            tPop.stop();
+                                            tPop.reset();        
+                                            decFlag = true;         
+                                            scrnUpdate = true;    
+                                            led3=1;
+                                            led1=0;        
+                                        }
+                                        else
+                                        if(touchBtn(PAGE_14_ANA_CAL, P14_INC, POP)){
+                                            tPush.stop(); 
+                                            tPush.reset();
+                                            tPop.start();
+                                            incFlag = false;     
+                                            led1=0;
+                                            led2=1;
+                                        }  
+                                        else 
+                                        if(touchBtn(PAGE_14_ANA_CAL, P14_DEC, POP)){
+                                            tPush.stop(); 
+                                            tPush.reset();
+                                            tPop.start();
+                                            decFlag = false;            
+                                            led3=0;
+                                            led1=1;        
+                                        }  
+                                        else
+                                        if(touchBtn(PAGE_14_ANA_CAL, P14_OK, PUSH)){ 
+                                            okFlag = true; scrnUpdate = true;    
+                                        }
+                                        else
+                                        if(touchBtn(PAGE_14_ANA_CAL, P14_BACK, PUSH)){ 
+                                            stopLED = OFF; 
+                                            task = STOP_SCRN;
+                                            
+                                        }                                                     
+                                        break;   
+
+        case PAGE_18_ANA_CAL_MODE:
+                                        ///////////////////////////////////////////////////////////////////////////////
+                                        // PAGE 18 4-20mA CALIBRATION MODE
+                                        ///////////////////////////////////////////////////////////////////////////////     
+                                        if(touchBtn(PAGE_18_ANA_CAL_MODE, P18_MAN, PUSH)){   
+                                            if(calComplete){
+                                                nvm.runMode = MANUAL;
+                                                writeNVMByte(NVM_RUN_MODE, nvm.runMode);//update EEPROM with manual mode                                                               
+                                                task = STOP_SCRN;                                                                           
+                                            }   
+                                            else 
+                                            {                                   
+                                                reset();                                               
+                                                manFlag = true;//manual cal mode                                            
+                                                lcd.nexChgPage(PAGE_14_ANA_CAL);                                             
+                                                calState = CAL1_SCRN;   
+                                                scrnUpdate = true;                         
+                                                task = ANA_CAL;                            
+                                            }                                                
+                                        }
+                                        else                                                                                    
+                                        if(touchBtn(PAGE_18_ANA_CAL_MODE, P18_INPUT, PUSH)){   
+                                            if(calComplete){
+                                                nvm.runMode = ANALOGUE;
+                                                writeNVMByte(NVM_RUN_MODE,nvm.runMode);                                                                                 
+                                                task = STOP_SCRN;
+                                            }   
+                                            else{                                                                    
+                                                reset();                              
+                                                manFlag = false;//signal cal mode                    
+                                                lcd.nexChgPage(PAGE_14_ANA_CAL);     
+                                                calState = CAL1_SCRN;  
+                                                scrnUpdate = true;                
+                                                task = ANA_CAL;
+                                            }  
+                                        }                                                 
+                                        break;         
+
+        case PAGE_27_ABOUT:
+                                        ///////////////////////////////////////////////////////////////////////////////
+                                        // PAGE 27 INFOMATION
+                                        ///////////////////////////////////////////////////////////////////////////////                                                   
+                                        if(touchBtn(PAGE_27_ABOUT, P27_BACK, PUSH))                                                                   
+                                            task = retLastStoredTask(savedTask);                                                                                            
+                                        break;
+
+        case PAGE_33_MA_OUT:
+                                        ///////////////////////////////////////////////////////////////////////////////
+                                        // PAGE 33 mA OUTPUT
+                                        //////////////////////////////////////////////////////////////////////////////        
+                                        if(touchBtn(PAGE_33_MA_OUT, P33_FULL_SCALE, PUSH)){                                                  
+                                            lcd.nexSetDSBtn("bt1", UNTICK);//display no tick
+                                            lcd.nexSetDSBtn("bt0", TICK);//display output low tick
+                                            nvm._4_20mAoutPut = _4_20MA_OUT_FULL_SCALE;
+                                            writeNVMByte(NVM_4_20MA_OUT,nvm._4_20mAoutPut);                                                                                                                                                                
+                                        }       
+                                        else
+                                        if(touchBtn(PAGE_33_MA_OUT, P33_MATCH, PUSH)){                                                                                     
+                                            lcd.nexSetDSBtn("bt0", UNTICK);//display no tick 
+                                            lcd.nexSetDSBtn("bt1", TICK);//display output high tick
+                                            nvm._4_20mAoutPut = _4_20MA_OUT_MATCH_INPUT_SCALE;
+                                            writeNVMByte(NVM_4_20MA_OUT,nvm._4_20mAoutPut);                                                                                                                                                                                                                               
+                                        }    
+                                        break;                                                                                                                     
+
+        case PAGE_34_START_STOP:            
+                                        ///////////////////////////////////////////////////////////////////////////////
+                                        // PAGE 34 RUN/STOP INPUT
+                                        //////////////////////////////////////////////////////////////////////////////                        
+                                        if(touchBtn(PAGE_34_START_STOP, P34_LOW, PUSH)){                                                  
+                                            lcd.nexSetDSBtn("bt0", UNTICK);                                            
+                                            lcd.nexSetDSBtn("bt1", TICK);                     
+                                            nvm.rmtStopPump = RMT_STOP_PUMP_LOW;
+                                            writeNVMByte(NVM_RMT_STOP_PUMP,nvm.rmtStopPump);                                                                                                                                                                
+                                        }       
+                                        else
+                                        if(touchBtn(PAGE_34_START_STOP, P34_HIGH, PUSH)){                                                                                     
+                                            lcd.nexSetDSBtn("bt0", TICK);//display no tick 
+                                            lcd.nexSetDSBtn("bt1", UNTICK);//display output high tick
+                                            nvm.rmtStopPump = RMT_STOP_PUMP_HIGH; 
+                                            writeNVMByte(NVM_RMT_STOP_PUMP,nvm.rmtStopPump);                                                                                                                                                                                                                               
+                                        }       
+                                        else                                                                                                                                                                                                              
+                                        if(touchBtn(PAGE_34_START_STOP, P34_HOME, PUSH))  
+                                            lcd.nexChgPage(PAGE_1_HOME);   
+                                        else                                            
+                                        if(touchBtn(PAGE_34_START_STOP, P34_BACK, PUSH))  
+                                            lcd.nexChgPage(PAGE_3_MAIN);                                                                                                                                                  
+                                        break;
+
+        case PAGE_35_CONT_SET:
+                                        ///////////////////////////////////////////////////////////////////////////////
+                                        // PAGE 35 INPUT/OUTPUT CONTROL SETTINGS
+                                        ///////////////////////////////////////////////////////////////////////////////       
+                                        if(touchBtn(PAGE_35_CONT_SET, P35_INPUT, PUSH)){//input button pressed                                   
+                                            lcd.nexChgPage(PAGE_34_START_STOP);
+                                            lcd.nexSendTxt("title34","Run/Stop input");       
+
+                                            if(nvm.rmtStopPump == RMT_STOP_PUMP_LOW){//Read the settings
+                                                lcd.nexSetDSBtn("bt0", UNTICK);//display info                                                                                             
+                                                lcd.nexSetDSBtn("bt1", TICK);//display info                                                                                                                     
+                                            }
+                                            else
+                                            if(nvm.rmtStopPump == RMT_STOP_PUMP_HIGH){//Read the settings   
+                                                lcd.nexSetDSBtn("bt0", TICK);//display info                                                
+                                                lcd.nexSetDSBtn("bt1", UNTICK);//display info
+                                            }                                                                               
+                                        }
+                                        else
+                                        if(touchBtn(PAGE_35_CONT_SET, P35_OUTPUT1, PUSH)){//Output 1 button pressed   
+                                            lcd.nexChgPage(PAGE_36_CONT_ADJ);       
+
+                                            if(nvm.outPut1Logic == OUT1_LOGIC_HI){//Read the settings                                                
+                                                lcd.nexSetDSBtn("bt1", TICK);//display info
+                                                lcd.nexSetDSBtn("bt0", UNTICK);//display info                                                  
+                                            }
+                                            else
+                                            if(nvm.outPut1Logic == OUT1_LOGIC_LO){//Read the settings
+                                                lcd.nexSetDSBtn("bt1", UNTICK);//display info
+                                                lcd.nexSetDSBtn("bt0", TICK);//display info
+                                            }
+                                                                                          
+                                            lcd.nexSendTxt("title36","Output 1");    
+                                            lcd.nexSendTxt("t0","LOW");      
+                                            lcd.nexSendTxt("t1","HIGH");                                                                    
+                                            menuStringID = OUTPUT1_LIST;  
+                                            i[y] = ReadListIndexNVM(nvm.outPut1);                                                                                                           
+                                            lcd.nexSendTxt("data",menuStringArray[menuStringID][i[y]]);                                                
+                                        }                                          
+                                        else
+                                        if(touchBtn(PAGE_35_CONT_SET, P35_OUTPUT2, PUSH)){//Output 2 button pressed  
+                                            lcd.nexChgPage(PAGE_36_CONT_ADJ);//display        
+
+                                            if(nvm.outPut2Logic == OUT2_LOGIC_HI){                                                
+                                                lcd.nexSetDSBtn("bt1", TICK);//display info 
+                                                lcd.nexSetDSBtn("bt0", UNTICK);//display info
+                                            }
+                                            else
+                                            if(nvm.outPut2Logic == OUT2_LOGIC_LO){
+                                                lcd.nexSetDSBtn("bt1", UNTICK);//display info
+                                                lcd.nexSetDSBtn("bt0", TICK);//display info
+                                            }
+                                                                                                                                                                                                                                                           
+                                            lcd.nexSendTxt("title36","Output 2");//display   
+                                            lcd.nexSendTxt("t0","LOW");      
+                                            lcd.nexSendTxt("t1","HIGH");                                      
+                                            menuStringID = OUTPUT2_LIST;//set the menu string ID for list for output 2   
+                                            i[y] = ReadListIndexNVM(nvm.outPut2);//get the index of the present output 2 setting from nvm
+                                            lcd.nexSendTxt("data",menuStringArray[menuStringID][i[y]]);//display the current nvm setting                                            
+                                        }       
+                                        else
+                                        if(touchBtn(PAGE_35_CONT_SET, P35_MA_OUTPUT, PUSH)){//mA output button pressed                                                                            
+                                            lcd.nexChgPage(PAGE_33_MA_OUT);//display    
+                                            lcd.nexSendTxt("title33","4-20mA Output scale");     
+                                            lcd.nexSendTxt("info1","Pin 3: Full scale 0 to 125 RPM");                                                    
+                                            lcd.nexSendTxt("info2","Pin 3: Match input scale");  
+
+                                            if(nvm._4_20mAoutPut == _4_20MA_OUT_FULL_SCALE){                                                
+                                                lcd.nexSetDSBtn("bt1", UNTICK);//display 
+                                                lcd.nexSetDSBtn("bt0", TICK);//display                                                  
+                                            }
+                                            else
+                                            if(nvm._4_20mAoutPut == _4_20MA_OUT_MATCH_INPUT_SCALE){
+                                                lcd.nexSetDSBtn("bt1", TICK);//display 
+                                                lcd.nexSetDSBtn("bt0", UNTICK);//display 
+                                            }                                            
+                                        }                                                     
+                                        else
+                                        if(touchBtn(PAGE_35_CONT_SET, P35_SPEED_LIMIT, PUSH)){//Speed limit button pressed   
+                                            lcd.nexChgPage(PAGE_31_SPEED_LIMIT); 
+                                            //speedLimit = 
+
+                                        }
+                                        else
+                                        if(touchBtn(PAGE_35_CONT_SET, P35_RUN_HOURS, PUSH)){//Run hours button pressed   
+                                            lcd.nexChgPage(PAGE_11_RESET);
+                                            lcd.nexSendTxt("title11","Run Hours");  
+                                            lcd.nexSendTxt("btn","RESET");                                                  
+                                            lcd.nexSendTxt("info1","159");          
+                                            lcd.nexSendTxt("info5","Hours"); 
+                                            bool runHours = 1;
+                                            bool volCntr = 0;                                                                                                                    
+                                        }                                        
+                                        else
+                                        if(touchBtn(PAGE_35_CONT_SET, P35_VOLUME_CNTR, PUSH)){//Reset flow counter button pressed   
+                                            lcd.nexChgPage(PAGE_11_RESET);
+                                            lcd.nexSendTxt("title11","Volume Counter");  
+                                            lcd.nexSendTxt("btn","RESET");                                                  
+                                            lcd.nexSendTxt("info1","60");          
+                                            lcd.nexSendTxt("info5","Litres");     
+                                            bool runHours = 0;
+                                            bool volCntr = 1;                                                                                    
+                                        }                                        
+                                        else
+                                        if(touchBtn(PAGE_35_CONT_SET, P35_SCALE_FACTOR, PUSH)){   
+
+                                        }                                                                               
+                                        break;
+
+        case PAGE_36_CONT_ADJ:        
+                                        ///////////////////////////////////////////////////////////////////////////////
+                                        // PAGE 36 CONTROL SETTINGS ADJUSTMENT
+                                        ///////////////////////////////////////////////////////////////////////////////     
+                                        if(touchBtn(PAGE_36_CONT_ADJ, P36_DEC, PUSH)){   
+                                            dispList(i, INC, menuStringID, menuStringArray, P36_MENU_ITEMS);
+                                            //pc.printf("\r\n\r\nx = 0x%X, y = 0x%X, z = 0x%X, ",i[x],i[y],i[z]);   
+                                        }                                                                                                                         
+                                        else
+                                        if(touchBtn(PAGE_36_CONT_ADJ, P36_INC, PUSH)){   
+                                            dispList(i, DEC, menuStringID, menuStringArray, P36_MENU_ITEMS);                                                                                      
+                                            //pc.printf("\r\n\r\nx = 0x%X, y = 0x%X, z = 0x%X, ",i[x],i[y],i[z]); 
+                                        }
+                                        else      
+                                        if(touchBtn(PAGE_36_CONT_ADJ, P36_LOW, PUSH)){//Low button pressed
+                                            if(menuStringID == OUTPUT1_LIST){//Output 1 selected                             
+                                                lcd.nexSetDSBtn("bt1", UNTICK);//Untick High
+                                                lcd.nexSetDSBtn("bt0", TICK);//Tick Low
+                                                nvm.outPut1Logic = OUT1_LOGIC_LO;//Set Low for output 1 in global structure
+                                                writeNVMByte(NVM_OUTPUT1_LOGIC,nvm.outPut1Logic);//write Low for output 1 to NVM                                                                                          
+                                            }
+                                            else 
+                                            if(menuStringID == OUTPUT2_LIST){//Output 2 selected                                                                            
+                                                lcd.nexSetDSBtn("bt1", UNTICK);//Untick High
+                                                lcd.nexSetDSBtn("bt0", TICK);//Tick Low
+                                                nvm.outPut2Logic = OUT2_LOGIC_LO;//Set Low for output 2 in global structure 
+                                                writeNVMByte(NVM_OUTPUT2_LOGIC,nvm.outPut2Logic);//write Low for output 2 to NVM                                                     
+                                            }
+                                        }       
+                                        else
+                                        if(touchBtn(PAGE_36_CONT_ADJ, P36_HIGH, PUSH)){//High button pressed 
+                                           if(menuStringID == OUTPUT1_LIST){//Output 1 selected                                              
+                                                lcd.nexSetDSBtn("bt0", UNTICK);//Untick Low
+                                                lcd.nexSetDSBtn("bt1", TICK);//Tick High
+                                                nvm.outPut1Logic = OUT1_LOGIC_HI;//Set High for output 1 in global structure  
+                                                writeNVMByte(NVM_OUTPUT1_LOGIC,nvm.outPut1Logic);//write High for output 1 to NVM                                                                                           
+                                            }
+                                            else 
+                                            if(menuStringID == OUTPUT2_LIST){//Output 2 selected                                     
+                                                lcd.nexSetDSBtn("bt0", UNTICK);//Untick Low
+                                                lcd.nexSetDSBtn("bt1", TICK);//Tick High
+                                                nvm.outPut2Logic = OUT2_LOGIC_HI;//Set High for output 2 in global structure  
+                                                writeNVMByte(NVM_OUTPUT2_LOGIC,nvm.outPut2Logic);//write High for output  to NVM                                                    
+                                            }                                        
+                                        }
+                                        else
+                                        if(touchBtn(PAGE_36_CONT_ADJ, P36_OK, PUSH)){              
+
+                                            lcd.nexSetFontCol("data", GREEN);
+
+                                            switch(menuStringID){      
+                                                case OUTPUT1_LIST:                                                                  
+                                                                    nvm.outPut1 = uOutPut1_ID[i[y]]; 
+                                                                    writeNVMByte(NVM_OUTPUT1,nvm.outPut1);
+                                                                    break;
+
+                                                case OUTPUT2_LIST:  
+                                                                    nvm.outPut2 = uOutPut2_ID[i[y]]; 
+                                                                    writeNVMByte(NVM_OUTPUT2,nvm.outPut2);
+                                                                    break;                                                                                        
+                                            }                                                         
+                                            //task = retLastStoredTask(savedTask);                                      
+                                        }        
+                                        break;                                
+    }
+    return(task);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// SCAN NEXTION TOUCH KEYS
+///////////////////////////////////////////////////////////////////////////////
+uint8_t nexKeyScan(uint8_t presentTask, uint8_t savedTask){
+/*
+    Do not place any delays or function that take too much time as this is an ISR message service, use a flag in the main routing instead
+ */
+
+/*
+    Nextion RX interrupt sets the keyScanFlag
+    when a touch key command has been received
+    the switch below filters which Nextion page 
+    has sent the command
+*/
+    static uint8_t task = presentTask;
+
+    if(task != ANA_CAL)
+        task = presentTask;
+
+    if(keyScanFlag == true){//RX ISR sets this flag
+        keyScanFlag = false;
+        task = nexPage(presentTask, savedTask);      
+    } 
+    return(task);//return back to the present task or next task                                          
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/NextionPages.h	Wed Jun 17 10:11:19 2020 +0000
@@ -0,0 +1,15 @@
+
+#ifndef NEXTIONPAGES_H
+#define NEXTIONPAGES_H
+
+#include "mbed.h"
+
+extern uint8_t precision;
+extern uint8_t curPos;
+extern uint16_t x;
+extern bool calComplete;
+
+uint8_t nexKeyScan(uint8_t presentTask, uint8_t savedTask);
+
+uint8_t nexPage(uint8_t presentTask, uint8_t savedTask);
+#endif 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Ser25lcxxx.cpp	Wed Jun 17 10:11:19 2020 +0000
@@ -0,0 +1,234 @@
+/*
+* Ser25lcxxx library
+* Copyright (c) 2010 Hendrik Lipka
+* 
+* Permission is hereby granted, free of charge, to any person obtaining a copy
+* of this software and associated documentation files (the "Software"), to deal
+* in the Software without restriction, including without limitation the rights
+* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+* copies of the Software, and to permit persons to whom the Software is
+* furnished to do so, subject to the following conditions:
+* 
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+* 
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+* THE SOFTWARE.
+*/
+
+#include "mbed.h"
+#include "Definitions.h"
+#include "Ser25lcxxx.h"
+#include "wait_api.h"
+#include "NVM.h"
+
+#define HIGH(x) ((x&0xff00)>>8)
+#define LOW(x) (x&0xff)
+
+extern Serial pc;//Debug Port via USB
+extern char ramNVM[];//NVM value store
+
+Ser25LCxxx::Ser25LCxxx(SPI *spi, PinName enable, int bytes, int pagesize) {
+    _spi=spi;
+    _enable=new DigitalOut(enable);
+    _size=bytes;
+    _pageSize=pagesize;
+    _enable->write(1);
+}
+
+Ser25LCxxx::~Ser25LCxxx() {
+    delete _enable;
+}
+
+char* Ser25LCxxx::read(unsigned int startAdr, unsigned int len) {
+    // assertion
+    if (startAdr+len>_size)
+        return NULL;
+    char* ret=(char*)malloc(len);
+    _enable->write(0);
+    wait_us(1);
+    // send address
+    if (_size<512) { // 256 and 128 bytes
+        _spi->write(0x03);
+        _spi->write(LOW(startAdr));
+    } else if (512==_size) { // 4k variant adds 9th address bit to command
+        _spi->write(startAdr>255?0xb:0x3);
+        _spi->write(LOW(startAdr));
+    } else if (_size<131072) { // everything up to 512k
+        _spi->write(0x03);
+        _spi->write(HIGH(startAdr));
+        _spi->write(LOW(startAdr));
+    } else { // 25xx1024, needs 3 byte address
+        _spi->write(0x03);
+        _spi->write(startAdr>>16);
+        _spi->write(HIGH(startAdr));
+        _spi->write(LOW(startAdr));
+    }
+    // read data into buffer
+    for (int i=0;i<len;i++) {
+        ret[i]=_spi->write(0);
+    }
+    wait_us(1);
+    _enable->write(1);
+    return ret;
+}
+
+bool Ser25LCxxx::write(unsigned int startAdr, unsigned int len, const char* data) {
+    if (startAdr+len>_size)
+        return -1;
+
+    int ofs=0;
+    while (ofs<len) {
+        // calculate amount of data to write into current page
+        int pageLen=_pageSize-((startAdr+ofs)%_pageSize);
+        if (ofs+pageLen>len)
+            pageLen=len-ofs;
+        // write single page
+        bool b=writePage(startAdr+ofs,pageLen,data+ofs);
+        if (!b)
+            return false;
+        // and switch to next page
+        ofs+=pageLen;
+    }
+    return true;
+}
+
+bool Ser25LCxxx::writePage(unsigned int startAdr, unsigned int len, const char* data) {
+    enableWrite();
+
+    _enable->write(0);
+    wait_us(1);
+
+    if (_size<512) { // 256 and 128 bytes
+        _spi->write(0x02);
+        _spi->write(LOW(startAdr));
+    } else if (512==_size) { // 4k variant adds 9th address bit to command
+        _spi->write(startAdr>255?0xa:0x2);
+        _spi->write(LOW(startAdr));
+    } else if (_size<131072) { // everything up to 512k
+        _spi->write(0x02);
+        _spi->write(HIGH(startAdr));
+        _spi->write(LOW(startAdr));
+    } else { // 25xx1024, needs 3 byte address
+        _spi->write(0x02);
+        _spi->write(startAdr>>16);
+        _spi->write(HIGH(startAdr));
+        _spi->write(LOW(startAdr));
+    }
+
+    // do real write
+    for (int i=0;i<len;i++) {
+        _spi->write(data[i]);
+    }
+    wait_us(1);
+    // disable to start physical write
+    _enable->write(1);
+    
+    waitForWrite();
+
+    return true;
+}
+
+bool Ser25LCxxx::clearPage(unsigned int pageNum) {
+    enableWrite();
+    if (_size<65535) {
+        char* s=(char*)malloc(_pageSize);
+        for (int i=0;i<_pageSize;i++) {
+            s[i]=0xff;
+        }
+        bool b=writePage(_pageSize*pageNum,_pageSize,s);
+        delete s;
+        return b;
+    } else {
+        _enable->write(0);
+        wait_us(1);
+        _spi->write(0x42);
+        _spi->write(HIGH(_pageSize*pageNum));
+        _spi->write(LOW(_pageSize*pageNum));
+        wait_us(1);
+        _enable->write(1);
+
+        waitForWrite();
+    }
+    return true;
+}
+
+void Ser25LCxxx::clearMem() {
+    enableWrite();
+    if (_size<65535) {
+        for (int i=0;i<_size/_pageSize;i++) {
+            if (!clearPage(i))
+                break;
+        }
+    }
+    else
+    {
+        _enable->write(0);
+        wait_us(1);
+        _spi->write(0xc7);
+        wait_us(1);
+        _enable->write(1);
+
+        waitForWrite();
+    }
+}
+
+int Ser25LCxxx::readStatus() {
+    _enable->write(0);
+    wait_us(1);
+    _spi->write(0x5);
+    int status=_spi->write(0x00);
+    wait_us(1);
+    _enable->write(1);
+    return status;
+}
+
+void Ser25LCxxx::waitForWrite() {
+    while (true) {
+        if (0==readStatus()&1)
+            break;
+        wait_us(10);
+    }
+}
+
+void Ser25LCxxx::enableWrite()
+{
+    _enable->write(0);
+    wait_us(1);
+    _spi->write(0x06);
+    wait_us(1);
+    _enable->write(1);
+}
+
+void dumpLine(char* s, int len,int disp)
+{
+    for (int i=0;i<len;i++)
+    {
+        //ramNVM[i]=s[i];
+
+        switch(disp)
+        {
+            case HEX:    pc.printf("\r\n|(%d) \t 0x%02X |",i,s[i]); break;
+            //case STR:    pc.printf("%s ",s[i]); break;
+            case CHR:    pc.printf("%c ",s[i]); break;
+        }           
+    }
+}
+
+void dump(char *s, int len,int disp)
+{
+    int i=0;
+    while (i<len)
+    {
+        if (i+16<len)
+            dumpLine(s+i,16,disp);
+        else
+            dumpLine(s+i,len-i,disp);
+        i+=16;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Ser25lcxxx.h	Wed Jun 17 10:11:19 2020 +0000
@@ -0,0 +1,96 @@
+/*
+* Ser25lcxxx library
+* Copyright (c) 2010 Hendrik Lipka
+* 
+* Permission is hereby granted, free of charge, to any person obtaining a copy
+* of this software and associated documentation files (the "Software"), to deal
+* in the Software without restriction, including without limitation the rights
+* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+* copies of the Software, and to permit persons to whom the Software is
+* furnished to do so, subject to the following conditions:
+* 
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+* 
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+* THE SOFTWARE.
+*/
+
+#ifndef __SER25LCXXX_H__
+#define __SER25LCXXX_H__
+
+#include "mbed.h"
+
+/**
+A class to read and write all 25* serial SPI eeprom devices from Microchip (from 25xx010 to 25xx1024).
+
+One needs to provide total size and page size, since this cannot be read from the devices,
+and the page size differs even by constant size (look up the data sheet for your part!)
+*/
+class Ser25LCxxx
+{
+    public:
+        /**
+            create the handler class
+            @param spi the SPI port where the eeprom is connected. Must be set to format(8,3), and with a speed matching the one of your device (up to 5MHz should work)
+            @param enable the pin name for the port where /CS is connected
+            @param bytes the size of you eeprom in bytes (NOT bits, eg. a 25LC010 has 128 bytes)
+            @param pagesize the size of a single page, to provide overruns
+        */
+        Ser25LCxxx(SPI *spi, PinName enable, int bytes, int pagesize);
+        
+        /**
+            destroys the handler, and frees the /CS pin        
+        */
+        ~Ser25LCxxx();
+        
+        /**
+            read a part of the eeproms memory. The buffer will be allocated here, and must be freed by the user
+            @param startAdr the adress where to start reading. Doesn't need to match a page boundary
+            @param len the number of bytes to read (must not exceed the end of memory)
+            @return NULL if the adresses are out of range, the pointer to the data otherwise
+        */
+        char* read(unsigned int startAdr, unsigned int len);
+        
+        /**
+            writes the give buffer into the memory. This function handles dividing the write into 
+            pages, and waites until the phyiscal write has finished
+            @param startAdr the adress where to start writing. Doesn't need to match a page boundary
+            @param len the number of bytes to read (must not exceed the end of memory)
+            @return false if the adresses are out of range
+        */
+        bool write(unsigned int startAdr, unsigned int len, const char* data);
+        
+        /**
+            fills the given page with 0xFF
+            @param pageNum the page number to clear
+            @return if the pageNum is out of range        
+        */
+        bool clearPage(unsigned int pageNum);
+        
+        /**
+            fills the while eeprom with 0xFF
+        */
+        void clearMem();
+    private:
+        bool writePage(unsigned int startAdr, unsigned int len, const char* data);
+        int readStatus();
+        void waitForWrite();
+        void enableWrite();
+        
+
+        SPI* _spi;
+        DigitalOut* _enable;
+        int _size,_pageSize;
+        
+};
+
+void dumpLine(char* s, int len,int disp);
+void dump(char *s, int len,int disp);
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Threads.cpp	Wed Jun 17 10:11:19 2020 +0000
@@ -0,0 +1,50 @@
+#include <cstdlib>
+#include <string> 
+#include "main.h"
+#include "Functions.h"
+#include "Definitions.h"
+#include "Boolean.h"
+#include "NextionLCD.h"
+#include "mbed_debug.h"
+#include "mbed.h"
+#include "Languages.h"
+#include "Ser25lcxxx.h"
+#include "NVM.h"
+#include "Watchdog.h"
+#include "math.h"
+
+///////////////////////////////////////////////////////////////////////////////
+// MBED OBJECTS
+///////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////
+// VARIABLES
+///////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////
+// DEBUG
+///////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////
+// THREADS
+///////////////////////////////////////////////////////////////////////////////
+//Threads
+Thread thread1;
+Thread thread2;
+
+void dbgNextion(void){
+#ifdef DEBUG_RX
+    while(1){
+        if(debugFlag){   
+            debugFlag = false;
+
+            pc.printf("RX Msg : "); 
+
+            for(int i=0; i<= dbgMRxIdx;i++)
+                pc.printf("%.2X ",dbgNexMsg[i]); 
+            
+            pc.printf("\r\n"); 
+        }
+    }
+#endif    
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Threads.h	Wed Jun 17 10:11:19 2020 +0000
@@ -0,0 +1,12 @@
+
+#ifndef THREADS_H
+#define THREADS_H
+
+#include "mbed.h"
+
+extern Thread thread1;
+extern Thread thread2;
+
+void dbgNextion(void);
+
+#endif 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Watchdog.cpp	Wed Jun 17 10:11:19 2020 +0000
@@ -0,0 +1,111 @@
+///
+/// @author Bernaérd Remond
+///
+
+//#define LPC
+#define ST_NUCLEO
+
+
+#include "mbed.h"
+#include "Watchdog.h"
+
+
+/// Watchdog gets instantiated at the module level
+Watchdog::Watchdog() {
+#ifdef LPC    
+    wdreset = (LPC_WDT->WDMOD >> 2) & 1;    // capture the cause of the previous reset
+#endif
+#ifdef ST_NUCLEO
+    // capture the cause of the previous reset
+    /* Check if the system has resumed from IWDG reset */
+/*
+    if (__HAL_RCC_GET_FLAG(RCC_FLAG_IWDGRST)) {
+        wdreset = true;
+    }
+    else {
+        wdreset = false; 
+    }
+*/        
+        wdreset = false; 
+#endif
+
+}
+
+/// Load timeout value in watchdog timer and enable
+void Watchdog::Configure(float timeout) {
+#ifdef LPC    
+    LPC_WDT->WDCLKSEL = 0x1;                // Set CLK src to PCLK
+    uint32_t clk = SystemCoreClock / 16;    // WD has a fixed /4 prescaler, PCLK default is /4
+    LPC_WDT->WDTC = (uint32_t)(timeout * (float)clk);
+    LPC_WDT->WDMOD = 0x3;                   // Enabled and Reset
+#endif   
+#ifdef ST_NUCLEO
+    // see http://embedded-lab.com/blog/?p=9662    
+    #define LsiFreq (45000)
+    
+    uint16_t PrescalerCode;
+    uint16_t Prescaler;
+    uint16_t ReloadValue;
+    float Calculated_timeout;
+    
+    if ((timeout * (LsiFreq/4)) < 0x7FF) {
+        PrescalerCode = IWDG_PRESCALER_4;
+        Prescaler = 4;
+    }
+    else if ((timeout * (LsiFreq/8)) < 0xFF0) {
+        PrescalerCode = IWDG_PRESCALER_8;
+        Prescaler = 8;
+    }
+    else if ((timeout * (LsiFreq/16)) < 0xFF0) {
+        PrescalerCode = IWDG_PRESCALER_16;
+        Prescaler = 16;
+    }
+    else if ((timeout * (LsiFreq/32)) < 0xFF0) {
+        PrescalerCode = IWDG_PRESCALER_32;
+        Prescaler = 32;
+    }
+    else if ((timeout * (LsiFreq/64)) < 0xFF0) {
+        PrescalerCode = IWDG_PRESCALER_64;
+        Prescaler = 64;
+    }
+    else if ((timeout * (LsiFreq/128)) < 0xFF0) {
+        PrescalerCode = IWDG_PRESCALER_128;
+        Prescaler = 128;
+    }
+    else {
+        PrescalerCode = IWDG_PRESCALER_256;
+        Prescaler = 256;
+    }
+    
+    // specifies the IWDG Reload value. This parameter must be a number between 0 and 0x0FFF.
+    ReloadValue = (uint32_t)(timeout * (LsiFreq/Prescaler));
+    
+    Calculated_timeout = ((float)(Prescaler * ReloadValue)) / LsiFreq;
+    printf("\r\n\r\nWATCHDOG set with prescaler:%d reload value: 0x%X - timeout:%f",Prescaler, ReloadValue, Calculated_timeout);
+    
+    IWDG->KR = 0x5555; //Disable write protection of IWDG registers      
+    IWDG->PR = PrescalerCode;      //Set PR value      
+    IWDG->RLR = ReloadValue;      //Set RLR value      
+    IWDG->KR = 0xAAAA;    //Reload IWDG      
+    IWDG->KR = 0xCCCC;    //Start IWDG - See more at: http://embedded-lab.com/blog/?p=9662#sthash.6VNxVSn0.dpuf       
+#endif
+ 
+    Service();
+}
+
+/// "Service", "kick" or "feed" the dog - reset the watchdog timer
+/// by writing this required bit pattern
+void Watchdog::Service() {
+#ifdef LPC    
+    LPC_WDT->WDFEED = 0xAA;
+    LPC_WDT->WDFEED = 0x55;
+#endif    
+#ifdef ST_NUCLEO
+    IWDG->KR = 0xAAAA;         //Reload IWDG - See more at: http://embedded-lab.com/blog/?p=9662#sthash.6VNxVSn0.dpuf
+#endif
+}
+
+/// get the flag to indicate if the watchdog causes the reset
+bool Watchdog::WatchdogCausedReset() {
+    return wdreset;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Watchdog.h	Wed Jun 17 10:11:19 2020 +0000
@@ -0,0 +1,101 @@
+/// @file Watchdog.h provides the interface to the Watchdog module
+///
+/// This provides basic Watchdog service for the mbed. You can configure
+/// various timeout intervals that meet your system needs. Additionally,
+/// it is possible to identify if the Watchdog was the cause of any 
+/// system restart, permitting the application code to take appropriate
+/// behavior.
+/// 
+/// Adapted from Simon's Watchdog code from http://mbed.org/forum/mbed/topic/508/
+///
+/// @note Copyright &copy; 2011 by Smartware Computing, all rights reserved.
+///     This software may be used to derive new software, as long as
+///     this copyright statement remains in the source file.
+/// @author David Smart
+///
+/// History
+/// \li v1.00 - 20110616: initial release with some documentation improvements
+///
+#ifndef WATCHDOG_H
+#define WATCHDOG_H
+#include "mbed.h"
+
+/// The Watchdog class provides the interface to the Watchdog feature
+///
+/// Embedded programs, by their nature, are usually unattended. If things
+/// go wrong, it is usually important that the system attempts to recover.
+/// Aside from robust software, a hardware watchdog can monitor the
+/// system and initiate a system reset when appropriate.
+///
+/// This Watchdog is patterned after one found elsewhere on the mbed site,
+/// however this one also provides a method for the application software
+/// to determine the cause of the reset - watchdog or otherwise.
+///
+/// example:
+/// @code
+/// Watchdog wd;
+///
+/// ...
+/// main() {
+///    if (wd.WatchdogCausedReset())
+///        pc.printf("Watchdog caused reset.\r\n");
+///      
+///    wd.Configure(3.0);       // sets the timeout interval
+///    for (;;) {
+///         wd.Service();       // kick the dog before the timeout
+///         // do other work
+///    }
+/// }
+/// @endcode
+///
+class Watchdog {
+public:
+    /// Create a Watchdog object
+    ///
+    /// example:
+    /// @code
+    /// Watchdog wd;    // placed before main
+    /// @endcode
+    Watchdog();
+    
+    /// Configure the timeout for the Watchdog
+    ///
+    /// This configures the Watchdog service and starts it. It must
+    /// be serviced before the timeout, or the system will be restarted.
+    ///
+    /// example:
+    /// @code
+    ///     ...
+    ///     wd.Configure(1.4);  // configure for a 1.4 second timeout
+    ///     ...
+    /// @endcode
+    ///
+    /// @param[in] timeout in seconds, as a floating point number
+    /// @returns none
+    ///
+    void Configure(float timeout);
+    
+    /// Service the Watchdog so it does not cause a system reset
+    ///
+    /// example:
+    /// @code
+    ///    wd.Service();
+    /// @endcode
+    /// @returns none
+    void Service();
+    
+    /// WatchdogCausedReset identifies if the cause of the system
+    /// reset was the Watchdog
+    ///
+    /// example:
+    /// @code
+    ///    if (wd.WatchdogCausedReset())) {
+    /// @endcode
+    ///
+    /// @returns true if the Watchdog was the cause of the reset
+    bool WatchdogCausedReset();
+private:
+    bool wdreset;
+};
+
+#endif // WATCHDOG_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Wed Jun 17 10:11:19 2020 +0000
@@ -0,0 +1,535 @@
+#include <cstdlib>
+#include <string>
+#include "main.h"
+#include "Functions.h"
+#include "Definitions.h"
+#include "Boolean.h"
+#include "NextionLCD.h"
+#include "mbed.h"
+#include "platform/CircularBuffer.h"
+#include "rtos.h"
+#include "Threads.h"
+#include "Languages.h"
+#include "Ser25lcxxx.h"
+#include "NVM.h"
+#include "Watchdog.h"
+#include "NextionPages.h"
+#include "Controls.h"
+#include "FastPWM.h"
+#include "MotorControl.h"
+
+/*
+
+  _/      _/  _/_/_/_/  _/_/_/    _/_/_/    _/_/_/_/  _/_/_/        _/_/_/      _/_/      _/_/_/   
+ _/      _/  _/        _/    _/  _/    _/  _/        _/    _/      _/    _/  _/    _/  _/          
+_/      _/  _/_/_/    _/_/_/    _/    _/  _/_/_/    _/_/_/        _/    _/  _/    _/    _/_/       
+ _/  _/    _/        _/    _/  _/    _/  _/        _/    _/      _/    _/  _/    _/        _/      
+  _/      _/_/_/_/  _/    _/  _/_/_/    _/_/_/_/  _/    _/      _/_/_/      _/_/    _/_/_/    
+
+*/
+
+//================================================================================================================================
+// COMPANY                :  Verderflex
+//
+// PROJECT                :  Verder DOS Peristaltic Pump
+// DATE                   :  3rd March 2020   
+
+string HARDWARE =           "Hardware Version : HVDOS X1.00";                                                
+string SOFTWARE =           "Software Version : SVDOS X1.00";
+string AUTHOR   =           "Author : Jim Lowe";
+
+/*
+ *   Firmware Numbering Scheme, V Major.Minor.Bugfix
+ *
+ *   Major  : Major Changes to function
+ *   Minor  : Minor Changes to function
+ *   Bugfix : Firmware fixes to function
+ *
+ */
+
+// HARDWARE              :   NUCLEO-F746ZG + Nextion 4.3" Display
+//
+// COMPILER              :   Mbed Studio
+
+//================================================================================================================================
+//************************************************  Code Status / Changes ********************************************************
+//================================================================================================================================
+
+/*
+ *
+ *  NOTES on Nextion Displays:
+ *  Nextion Push event is generated when the touch screen is PRESSED
+ *  Nextion Pop event is generated when the touch screen is RELEASED
+
+ *  Firmware Log, Initial Software Development Phase
+
+    09/05/19    itoa() now working
+    09/05/19_E  Nextion now running at 115200 Baud
+    13/05/19_D  Ported over to Nucleo-F746ZG
+    15/05/19_A  First version working on Mbed Studio
+    15/05/19_F  Nextion RX Interrupt message decoder started
+    16/05/19_A  Increment / Decrement arrow work but project need to be cleaned up before going further
+    16/05/19_A  Push & Pop functions for touch buttons are working. 
+    17/05/19_A  Adding debugging functions
+    17/05/19_A  Created a debug thread seems to work ok  
+    17/05/19_B  Success Nextion slider is working   
+    17/05/19_B  Flow rate / RPM selection now working
+    17/05/19_C  PWM now working, needs scaling factors to represent 100% for 1250 RPM etc
+    17/05/19_C  Progress bar working
+    20/05/19_A  Peripheral Pin List added
+    20/05/19_D  PWM frequency changed to 24kHz, this was found to be the frequency used on the DRV8306EVM BLDC Demo board
+    20/05/19_D  BLDC Motor working under PWM control, now reaches the same build level as QAD with Mbed 
+    28/05/19_A  STM32 does not have any EEPROM, need EEPROM for NVM capability, adding EEPROM capabilities to project
+    28/05/19_A  Add digital motor control
+    28/05/19_A  Motor direction control working, other I/O need to be done when schematics arrive from TI
+    28/05/19_B  Nextion back light dim now working, it is fussy about where it is executed
+    29/05/19_B  EEPROM testing thread proves EEPROM can be accessed and read correctly, removing EEPROM result in all 00, with EEPROM pattern is repeatable.
+    29/05/19_E  Good demo code for NVM, needs tidying up
+    30/05/19_A  Can read full NVM, can write single bytes to NVM
+    30/05/19_B  This EEPROM library cannot write a single byte to a memory location, it does not work, you have to write the entire NVM which is not good
+    31/05/19_A  Other EEPROM library no good, will try this again
+    31/05/19_A now working in a way to develop the NVM feature properly, this will be pursued after my holiday   
+    10/06/19_A  Continue with NVM development  
+    10/06/19_B  NVM ready for Nextion menu to be taken to next level to feature NVM settings
+    12/06/19_A  Rotation arrow on menu was not controlling motor rotation, it had been broken by adding other menu buttons, and this is something I am aware of now and to watch out for
+    13/06/19_B  Culled the amount of project in Mbed Studio as this was too big for the resources for Mbed Studio causing it to not recognize the target as an Mbed enabled device
+    13/06/19_B  Though I could get away with doing the NVM update in the RX ISR but this causes a run time error crashing the processor, I will place the NVM update in a thread
+    14/06/19_A  This code is broken trying to transition to better way to implement metering units selection, use next code or previous code
+    14/06/19_C  Taken most of the day but now NVM RAM is being written to from EEPROM, due to char* pointer this mechanism not working as thought, I have a working method now.
+    17/06/18_A  First implementation of working NVM, needs some refinement
+    17/06/19_D  Good refinement achieved for Metering Units NVM
+    17/06/19_E  memcpy() replaces for loop, implemented free() to free up dynamically created pointer memory after use as eepro.read() uses malloc()
+    27/06/19_A  Pre work ONLY for 4-20mA, setup of button membrane, 4-20mA control inputs
+    01/07/19_A  Pre work ONLY for 4-20mA, Open Drain outputs setup and default to off at power up
+    02/07/19_A  Adding map function
+    12/07/19_A  Assigned new I/O for start/stop buttons and start/stop LEDS as I/O I has assigned might be required later on as they are part of USB and ST_LINK stuff.
+    15/07/19_A  Grey Box build all working correctly, phew
+    15/07/19_A  Need to implement start / stop button control, added state machine
+    15/07/19_A  Motor thread commented out, motor control part of state machine
+    15/07/19_B  Not sure how text box b2 is displaying RPM when stopped, I have overridden this for now
+    15/07/19_C  Stop/Start operational
+    16/07/19_A  Scaling for RPM, ml/min and % working perfectly
+    16/07/19_A_TEXT This is the first version that uses TEXT for displaying metering digits using printf
+    17/07/19_C  Issues with nextion, this version look ok    
+    18/07/19_A  Page component IDs definitions had changed on Nextion HMI code again when I created  16/07/19_A_TEXT version, its a really crappy and stops your working code from working
+    19/07/19_A  3 Second Watchdog implemented and working   
+    19/07/19_A  Nextion power control added and working 
+    19/07/19_A  1ms timer implemented and working, not uses at present
+    22/07/19_A  Fit 4-20mA Module and connect up to system
+    22/07/19_A  DAC pins already use I will have to re-assign pins to be able to use DAC
+    22/07/19_A  ADC is now measuring mV, ADC is 12bit so more noise than 10bit ADC
+    23/07/19_B  4-20mA is outputting to debug screen and is scaled using mapF, look fairly stable and no averaging has been applied yet.
+    24/07/19_A  Look at ways to make analogue reading  more stable 
+    24/07/19_A  Speed control using LoopMate achieved, although values from ain.read_u16() do not seem to make any sense at this time, was expecting 0 - 4095?
+    25/07/19_A  Good results displayed on debug screen without any software smoothing applied.
+    25/07/19_B  Working really well now I have add the moving average algorithm, this adds a nice ramp rate to the product
+    26/07/19_A  Full motor speed does not seem to be there, need to fix this and create a function for motor control via 4-20mA
+    26/07/19_A  Motor speed is ok now, used mapF() to make sure motor has stopped at 4.0mA, previously it would only stop at 0.0mA
+    26/07/19_A  Wow, showing excellent stability at 10uA resolution
+    26/07/19_A  Metering unit displayed against mA, cool
+    29/07/19_A  Rough ramp rate applied when change of motor direction, this code is only an experiment and is blocking and needs to be refined in to non-blocking code   
+    01/08/19_A  Create functions for manual and 4-20mA
+    01/08/19_A  Nextion definition need changing for updated display GUI featuring QDOS type menu system
+    02/08/19_A  Created Timers.cpp to hold all timer functions and structures
+    05/08/19_A  Trying to implement manual control with dual speed inc/dec functionality
+    05/08/19_A  I have inc/dec functionality working, tidy code up and move forward
+    05/08/19_C  meter val changed to int16_t data type from uint16_t so abs() can be used for zeroing negative numbers
+    05/08/19_C  Nextion screen initializes on page 33 wher no buttons are, page 1 is called when start button is press, stop button calls page 33
+    06/08/19_A  Threads remove until required, all processing done in main and nextion RX ISR, all working.
+    07/08/19_A  Can now display flow units retrieval from NVM
+    08/08/19_A  Implement flow unit selection and storage to EEPROM
+    08/08/19_A  flow unit can not be see using extern!
+    08/08/19_B  Flow unit can be written and read from EEPROM
+    08/08/19_C  Implement manual and analogue operating mode stored in EEPROM     
+    12/08/19_A  Analogue function need to support all flow units
+    12/08/19_C  This version can demo flow units change, analogue and manual mode selected from menu system
+    12/08/19_D  meterVal, minScale, maxScale are now floats to give resolution required, this version is not full working at this time
+    13/08/19_A  displayed info in p1left not correct, need to implement incDecSpeed variable so when the touch key is held the inc/dec speed increases
+    14/08/19_A  Beware EEPROM value had somehow been changed for run.mode stopping normal program from running, suspect power glitch, as a consequence 
+                it has taken all morning to figure out the problem.
+    14/08/19_B  System can now be re-booted by pressing and holding down the ON button for 3 seconds         
+    15/08/19_A  Add some diagnostics to check EEPROM contents    
+    16/08/19_A  Change state machine structure so meter screen is correctly updated on return from Nextion pages
+    27/08/19_B  Inc/Dec indexer needs improvement
+    28/08/19_B  Inc/Dec control has been improved, speed can be set manually some tweaking may still be required at later point, moving on to analogue out now.
+    28/08/19_C  Start of DAC implementation to provide analogue output
+    28/08/19_C  SPI moved from SPI1 on CN7 to SPI14 on CN9, this is required to allow connection to DACs required for analogue output
+    28/08/19_C  I have verified that the SPI NVM is working after moving to other microcontroller pins for SPI14
+    28/08/19_C  I am able to set analogue output currents for test purposes.
+    28/08/19_E  Analogue output development started
+    29/08/19_B  Manual speed adjustment improved further now.
+    29/08/19_B  Stop LED used to prompt user to number indexer when setting flow rates
+    02/09/19_A  Accurate analogue output when in manual mode  can be demonstrated
+    02/09/19_B  Two dimensional array created for ALL VDOS flow rate types   
+    02/09/19_B  Can store and retrieve floats to EEPROM as an experiment, need to implement this in analogue cal routine  
+    04/09/19_A  Able to switch in and out of ANA_CAL state read for analogue menus
+    05/09/19_A  WARNING page 1 component ID have changed
+    06/09/19_B  Almost finished improved flow unit manual inc/dec control
+    09/09/19_A  I need to be moving forward with analogue calibration so I have put on hold development o inc/dec control for now
+    12/09/19_A  Floats can be written to and read from EEPROM for mA high, flow high, mA low, flow low calibrations
+    12/09/19_B  % / mA graph working as initial demo
+    16/09/19_A  Calibration graph line generation now done on Nextion by timer so no resources are required for this micro.
+    17/09/19_A  IncDecControl function created that can be used for all inc/dec controls on all pages
+    17/09/19_A  Clear out functions that are not used general tidy up of code
+    18/09/19_A  Working on calibration graph, good progress made here
+    19/09/19_A  struct settingsNVM has been updated to include calibration variables
+    20/09/19_A  Hysteresis add to 4-20 pump motor start threshold
+    20/09/19_A  Re-declaration of constants to give accurate rage #define ADC_MIN_V 0.013, #define ADC_MAX_V 2.9012//V   
+    23/09/19_B  full NVM RAM loaded into NVM structure in READ_NVM
+    23/09/19_B  USB ISOLATOR TO BE USED FROM NOW ON TO STOP USB GND EFFECTING THE UNIT
+    23/09/19_B  Calibration is working, checking all aspects of calibration
+    24/09/19_A  anaOut_mA(mapF(ana_mA, I_3MA, I_20MA, nvm.mA_low, nvm.mA_high)); APPEARS TO BE WORKING NOW, TESTING REQUIRED
+    25/09/19_B  Calibarion, analogue output, displayed flow  units all appear to be match well to QDOS
+    26/09/19_B  Works like QDOS for calibration now and analogue  in/out, issue when leaving calibration normal running does not resume correctly
+    27/09/19_A  Calibration graph has refresh problem when adjusting flow rate %
+    30/09/19_A  I hope the issue above in now fixed, this was done by erasing the RED line before going to the next calibration screen
+    30/09/19_B  Start looking at speed feedback from tacho output on motor controller
+    30/09/19_B  Tacko from fGout processed by isr test working
+    01/10/19_A  General code tidy, removal of unused variables, add ISR module
+    03/10/19_A  Implement motor stall detection
+    07/10/19_A  Motor development put on hold as present motor controller cannot produce high torque at low speed as QDOS 20 does
+    07/10/19_A  Remote Start / Stop implemented
+    07/10/19_A  Remote Fluid Recover, reverses motor in analogue mode, will check more when we receive new QDOS with this feature
+    07/10/19_A  Open Collector outputs now function, they have to be allocated to status and alarm software functions yet
+    10/10/19_A  Remote run/stop operational, code tidy now required
+    10/10/19_A  Need to store and retrieve the speed setting
+    11/10/19_A  configure Neptune motor for shaft speed range of 100 - 2500 RPM
+    14/10/19_A  Motor controller is on hold for now, I will concentrate of delivering the features of QDOS 20
+    14/10/19_A  Implement Auto-restart feature    
+    14/10/19_A  Flow units in manual mode saved and retreived from NVM after power loss
+    16/10/19_B  State machine does not work as intended causing problem for auto-restart and flow unit change over, re-do state machine
+    18/10/19_A  flow rate can be switched from one to another matching the percentage as QDOS does
+    21/10/19_A  Auto-Restart, remote inputs and O/C outputs working, read for checking with QDOS 30
+    22/10/19_A  Motor rotation is CCW but QDOS arrow is CW, Neptune will be set the same
+    22/10/19_A  FastPWM library added, leave PWM prescaler at 1 so that that the smallest speed inc/dec results in a measureable PWM change,
+                resolution is 12 bit (4096), measured bit width is ~20ns/bit, pwm period is 1/10000 = 100us, so 100us / 20ns = 5000
+    22/10/19_B  Implement MAX prime function   
+    23/10/19_A  To allow the touch button to be active at the stop screen as with QDOS the nexKeyScan() need to be call in the main loop   
+    23/10/19_A  New motor ramp time added to motor function, need to connect up nBrake to motor controller         
+    24/10/19_A  New readNVM() created to hide complexity and improve readability, working on motor ramp time parameter
+    25/10/19_A  Nextion display has failed, as extra protection tristate TX & RX line until Nextion has powered up
+    30/10/19_A  New Nextion display fitted, 1K resistor mod added to RX line
+    30/10/19_B  QDOS 30 flow units added to replace QDOS 20 flow units
+    31/10/19_A  Removed ramNVM so epprom data is transferred to and from direct to NVM data structure
+    01/11/19_A  NVM memory working good and more easy to understand and use now
+    01/11/19_B  PWM is now incremented / decremented at 0.1 resolution, so a change of 0.1% alter the PWM    
+    01/11/19_B  Cannot find any problems with this version, best version so far       
+    05/11/19_A  Calibration Menu cannot be accessed after initial calibration.  
+    11/11/19_A  Work required for remote control inputs 
+    11/11/19_A  Adding output1&2 settings
+    12/11/19_A  Discovery that SPI frequency was set to 1000 Hz, I forgot about this    
+    18/11/19_A  Various icon indicators added to page 1 top line
+    20/11/19_A  Implementation of control settings
+    21/11/19_A  Provide a version of software to use USB USART1 (PA9 & PA10) on product ONLY as product will not have ST-LINK 
+    02/12/19_A  Method of programming via USB has been designed in hardware, trap software in while loop and it will re-boot via watchdog timer with boot0 connected to vdd
+    03/12/19_A  #ifdef BOOTLOADER setup for production bootloader without USB/ST-LINK
+    05/12/19_A  Microcontroller pin assignment checked with Kevin Moon's work, all ok.
+    06/12/19_A  Continue with control settings menu, EEPROM variables for control settings
+    11/12/19_A  Output 1 NVM working
+    02/01/20_A  Output 1 & 2 appears to be working, NVM setting is being saved and retrieved correctly for displayed string names
+    06/01/20_A  Trying to fix return from analogue cal routine, the nvm.flowUnitVal is being set to minium value
+    06/01/20_B  The above is fixed, reset() was clearing nvm.flowUnitVal, this has been commeted out for now.    
+    08/01/20_A  Code refactoring 
+    13/01/20_A  Control Setting output 1&2, tick boxes for High and Low logic under development
+    13/01/20_A  High & Low output logic setting now stored in nvm, develop function for remote inputs and O/C outputs
+    16/01/20_A  Start/Stop input Pump Stop logic NVM tick boxes working.
+    17/02/20_A  4-20mA Scale NVM tick boxes working.
+    03/02/20_A  Remote pump Ster/Stop working same as QDOS
+    04/02/20_A  Improve Nextion driver so that only updated data is sent to Nextion, if the data is the same nothing is done.
+    04/02/20_B  Demonstrated code working for alarm outputs, continue this tomorrow
+    10/02/20_A  Rotation arrow issues now resolved
+    12/02/20_A  Control setting, inputs, o/c outputs, mA output scale all working
+    13/02/20_A  DEBUG_LCD added to improve loop time further by being able to see if any LCD functions are being called continuoisly.
+    24/02/20_A  Problem with with inc/dec controls, this is related to the speedLimit variable introduced
+    24/02/20_A  SpeedLimit now operates from nvm.speedLimit, speed limit menu need to be implemented
+    28/02/20_A  Improvements made to pause/stop symbol fucntion and output1 & 2 logic, test concur operation same as QDOS
+    28/02/20_B  Staring investigatory work for ED motor controller controler support, setup an serial interface for rs232 motor control    
+    28/02/20_C  Communication established on usart6 for motor control
+    28/02/20_C  Speeded up tremendously the serial communiucations on all at usarts, they all work at 921600 Baud, Nextion seem not to 
+                have a problem with this unimate fast baud, if I start to see problems I will slow the baud down.
+
+*/
+
+/*
+
+    ***** TARGET CAN BE LOST FROM USB FOR NO REASON, ONLY WAY TO GET IT BACK IS TO RE-BOOT PC AND SELECT ACTIVE PROGRAM AGAIN *****
+
+    Nextion text for mA readings will have to be set txt_maxl = 4 to limit precision
+
+    Analogue read is ~15us
+        
+    Find relationship between RPM and PWM, make sure we have 4000 RPM, measure with tachometer
+    Ramping need to be implemented so there is no abrupt stop and start at high speed
+    Hide away complexity in functions
+    Review all function, trim out useless functions
+    
+    Measured 4426 RPM unloaded
+
+    Neptune requirement is 120 Litres/Hour = 2000ml/min
+
+    Meeting today 16/8/19
+
+    US Flow Units, DB
+    Screen RED for alarm
+    Screen saver
+    Cooling fan as standard
+    Digital Dosing Pump 
+    Heads Left & Right fitment, rotation direction fixed based on which head is selected
+    Sep 2020 exhibition
+
+    QDOS 20 & 30 are the initial target
+
+    PA_4 and PA_5 are DAC1 & DAC2 outputs, these are presently used for SPI, I am going to have to move the SPI in order to use the DACs
+
+*/
+
+//PERIPHERAL PINS
+//https://github.com/ARMmbed/mbed-os/blob/master/targets/TARGET_STM/TARGET_STM32F7/TARGET_STM32F746xG/TARGET_NUCLEO_F746ZG/PeripheralPins.capabilities
+
+/*
+    25LC010AT
+
+    1K SPI EEPROM (128 x 8)
+
+    EEPROM 3V3 ok
+         ---------                
+    SCK |1       6| VDD
+    VSS |2       5| /CS
+    SI  |3       4| SO
+         ---------
+
+    PA_7 MOSI// Connected to RMII_CRS_DV [LAN8742A-CZ-TR_CRS_DV]
+    PA_6 MISO  
+    PA_5 SCLK    
+    PA_4 SSEL  
+*/
+
+//Objects
+
+
+/*USART
+
+USART1 = VERDERBUS
+USART2 = NEXTION DISPLAY
+USART3 = BOOTLOADER
+USART6 = MOTOR CONTROL
+
+
+*/
+
+#ifdef BOOTLOADER//USB TO UART BOOTLOADER
+    /* 
+        Physical connections PB10, PB11 USART3 required for Bootloader
+        RXPC <- PB10 OUTPUT TXN        
+        TXPC -> PB11 INPUT RXN
+        These become Virtual Com Port PD_8, PD_9
+    */
+    Serial pc(SERIAL_TX, SERIAL_RX);//Bootloader port
+#else//MBED VIA ST-LINK
+    /* 
+        Physical connections PD_8, PD_9 {USART3} debug port
+        RXPC <- PD_8 OUTPUT TXN        
+        TXPC -> PD_9 INPUT RXN
+    */
+    Serial pc(USBTX, USBRX);//Virtual Com Port PD_8, PD_9 Debug port required for MBED
+#endif
+
+NextionLCD lcd(USART2_TX, USART2_RX);//Tx, Rx, Nextion Port {USART2}
+
+Serial usart6(USART6_TX, USART6_RX);//Tx, Rx Motor Controller {USART6}
+
+SPI spi(MOSI,MISO,SCLK);//MOSI, MISO, SCLK, SSEL
+Ser25LCxxx eeprom(&spi,SSEL,BYTE_SIZE,PAGE_SIZE);
+Watchdog wd;
+
+Timer tPop;//touch button release timer
+Timer tPush;//touch button press timer
+Timer tRst;//reset timer
+Timer tSpeed;//numerical update rate of flow units
+
+volatile float ml = 0;
+bool maxBtnPress = false;//Prime buttOn (MAX)
+uint8_t storedTask = false;//Remember the previous state machine state
+bool rmtFlag = false;//Remote input flag
+char *readbuf;
+bool maxFlag = true;
+bool arrowFlag = false;   
+
+///////////////////////////////////////////////////////////////////////////////
+//VARIABLES
+///////////////////////////////////////////////////////////////////////////////
+float minScale = 0;
+float maxScale = 0;//Max Scale variable to stop max RPM, max ml/min and max %
+
+///////////////////////////////////////////////////////////////////////////////
+// ARRAYS
+///////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////
+// CONSTANTS
+///////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////
+// STRUCTURE DEFINITIONS
+///////////////////////////////////////////////////////////////////////////////
+struct settingsNVM nvm;
+
+///////////////////////////////////////////////////////////////////////////////
+// DEBUG
+///////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////
+// MAIN
+///////////////////////////////////////////////////////////////////////////////
+int main(){
+
+    uint8_t task;
+
+    task = INITIALISE;
+ 
+    while(1){
+    
+        switch(task){
+        
+            case INITIALISE:    
+                                sysInit();                                                                         
+                                task = STOP_SCRN;
+                                //task = DIAGS;
+                                dbgStates(task); 
+                                break;
+
+            case STOP_SCRN:    
+                                ml=ZERO;            
+                                lcd.nexChgPage(PAGE_1_HOME);       
+/*                                                            
+                                lcd.nexDispSymbol("key", ON);
+                                lcd.nexDispSymbol("leak", ON);
+                                lcd.nexDispSymbol("update", ON);
+                                lcd.nexDispSymbol("error", ON);
+                                lcd.nexDispSymbol("wifi", ON);        
+                                lcd.nexDispSymbol("locked", ON);
+                                lcd.nexDispSymbol("unlocked", ON);
+                                lcd.nexDispSymbol("temp", ON);
+                                lcd.nexDispSymbol("stop", ON);
+                                lcd.nexDispSymbol("pause", ON);                                                                                                                                                            
+*/
+                                lcd.nexDispSymbol("stop", ON);
+                                lcd.nexDispSymbol("pause", OFF);                                  
+                                lcd.nexDispSymbol("unlocked", ON);
+                                decodeByteNVM(nvm.flowUnits, &precision);     
+                               
+                                lcd.nexSendTxt("p1left","VDOS");//page 1 middle text box    
+                                lcd.nexSetFontCol("p1mid",RED);                                                                                          
+                                lcd.nexSendTxt("p1mid","Manual Mode");//page 1 middle text box  
+
+                                lcd.nexSendFloat("meter", nvm.flowUnitVal, precision);//display the flow units                                                             
+                                stopBtn(BTN_BYPASS_TRUE);//button disasbled LEDs only      
+                                motor(ZERO, CCW, BRAKE_OFF, MOTOR_DISABLE, 1);                      
+
+                                storedTask = STOP_SCRN;//this state   
+                                task = START;
+                                dbgStates(task); 
+                                break;
+                                                                                                 
+            case START:         
+                                anaOut_mA(I_3MA);                                               
+                                task = startUpMode(nvm.runMode);                         
+                                storedTask = START;
+                                                             
+                                dbgStates(task); 
+                                break;      
+                                                            
+            case MANUAL_SET:    //Setup for Manual running mode             
+                                lcd.nexChgPage(PAGE_1_HOME);   
+                                lcd.nexDispSymbol("unlocked", ON);
+                                //lcd.nexSetFontCol("p1mid",BLACK);                                                                                           
+                                //lcd.nexSendTxt("p1mid","Manual Mode");//page 1 middle text box                                                                                                                                                                                                                                                                
+                        
+                                lcd.nexSetCrop("inc",PAGE_1_HOME);//restore inc button image required for manual mode    
+                                lcd.nexSetCrop("dec",PAGE_1_HOME);//restore dec button image required for manual mode                                                                                
+                                decodeByteNVM(nvm.flowUnits, &precision);//display the flow unit symbol                                  
+                                lcd.nexSendFloat("meter", nvm.flowUnitVal, precision);//display the flow unit value           
+                                
+                                storedTask = MANUAL_SET;//this state                                                                         
+                                task = RUNNING;//next state  
+                                dbgStates(task);                                
+                                break;
+
+            case ANALOGUE_SET:  //Setup for Analogue running mode                                    
+                                lcd.nexChgPage(PAGE_1_HOME); 
+                                lcd.nexDispSymbol("unlocked", ON);                                
+                                lcd.nexSetFontCol("p1mid",RED);   
+                                
+                                lcd.nexSendTxt("p1mid","4-20mA Input Mode");//page 1 middle text box                                                                                                                                                                                               
+                                lcd.nexSetCrop("inc",CLEAR_INC_DEC);//remove inc button image not required for analogue mode   
+                                lcd.nexSetCrop("dec",CLEAR_INC_DEC);//remove dec button image not required for analogue mode                                                                                                                                                                            
+                                decodeByteNVM(nvm.flowUnits, &precision); 
+ 
+                                storedTask = ANALOGUE_SET;
+                                task = RUNNING;  
+                                dbgStates(task);                                                                                      
+                                break;           
+     
+            case RUNNING:                   
+                                switch(runModeNVM(nvm.runMode)){                                                                                                                        
+                                    case MANUAL_SET:    task = manual();    break;
+                                    case ANALOGUE_SET:  task = anaIn();       break;                                    
+                                    //case FLOW_CAL:      task = flowCalMode();   break;                                    
+                                    //case CONTACT_SET:   task = contactMode();   break;
+                                    //case FLUIDREC_SET:  task = fluidRecMode();  break;  
+                                    
+                                    default:;
+                                }   
+                                  
+                                task = STOP;   
+                                dbgStates(task);                       
+                                break;
+
+            case STOP:                                       
+                                if(((rmtRunStop == LO)&&(rmtFlag == true))||stopBtn(BTN_BYPASS_FALSE)){
+                                                         
+                                    lcd.nexDispSymbol("stop", OFF);                                       
+                            
+                                    task = STOP_SCRN;                                                                                                          
+                                }
+                                else
+                                    task = RUNNING;
+                                                
+                                dbgStates(task); 
+                                break;
+
+            case ANA_CAL:            
+                                task = anaCal();     
+                                dbgStates(task);                                                         
+                                break;
+
+            case STALL:         while(1);
+            
+                                break;
+
+            case FAULT:
+                                break;     
+
+            case DIAGS:         
+             
+                                break;                                                       
+
+            default:            pc.printf("Error Main : Last task = %d",task);  
+                             
+                                //////////////////////////////////////while(1)
+                                    //////////////////////////////////////////////////////wd.Service();//Kick the dog
+        }
+
+        #ifdef LOOP_TIME  
+            loopTimeMeasure();
+        #endif    
+ 
+        #ifndef WDT_TEST
+            if(!startBtn(OFF))//holding the start button will re-boot the system
+                wd.Service();//Kick the dog    
+        #endif        
+
+        outPuts(leakIn, &nvm); 
+        task = nexKeyScan(task, storedTask);//read nextion touch keys  
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.h	Wed Jun 17 10:11:19 2020 +0000
@@ -0,0 +1,77 @@
+
+#ifndef MAIN_H
+#define MAIN_H
+
+#include "mbed.h"
+#include "Watchdog.h"
+#include "Ser25lcxxx.h"
+
+
+extern string HARDWARE;
+extern string SOFTWARE;
+extern string AUTHOR;
+
+extern Serial pc;//Debug Port via USB
+extern Serial usart6;
+extern SPI spi;//SPI
+extern Ser25LCxxx eeprom;
+extern Watchdog wd;
+
+extern Timer tPop;
+extern Timer tPush;
+extern Timer tRst;
+extern Timer tSpeed;
+
+extern float minScale;
+extern float maxScale;//Max Scale variable to stop max RPM, max ml/min and max %
+
+extern char *readbuf;
+extern bool maxFlag;
+extern bool arrowFlag;
+
+extern bool rmtFlag;
+extern bool maxBtnPress;
+extern uint8_t storedTask;//Remember the previous state machine state
+extern volatile float ml;
+
+///////////////////////////////////////////////////////////////////////////////
+// STRUCTURES
+///////////////////////////////////////////////////////////////////////////////
+struct settingsNVM{
+    uint8_t flowUnits;//0
+    uint8_t runMode;//1
+    uint8_t autoRestart;//2
+    uint8_t pumpHeadStatus;//3
+    uint8_t alarm;//4
+    uint8_t headSide;//5   
+    uint8_t pumpOnOff;//6 
+    uint8_t spare;//7 
+
+    float speedLimit;//8
+    float flowUnitVal;//12             
+    float mA_low;//16
+    float mA_high;//20;  
+    float flow_low;//24
+    float flow_high;//28
+    float adc_min_v;//32
+    float adc_max_v;//36
+    float dac_v_low;//40
+    float dac_v_high;//44    
+
+    uint8_t rmtStopPump;//48
+    uint8_t outPut1;//Stores the setting, analogue, manual, run status, general alarm, leak detect, fluid level, contact mode on page 36    
+    uint8_t outPut1Logic;//Output logic state can be HI or LO depend on tick box setting on page 36  
+    uint8_t outPut2;//Stores the setting, analogue, manual, run status, general alarm, leak detect, fluid level, contact mode on page 36    
+    uint8_t outPut2Logic;//Output logic state can be HI or LO depend on tick box setting on page 36       
+    uint8_t _4_20mAoutPut;    
+
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// STRUCTURE DEFINITIONS
+///////////////////////////////////////////////////////////////////////////////
+extern struct settingsNVM nvm;
+
+void sysInit(void);
+
+#endif 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed-os.lib	Wed Jun 17 10:11:19 2020 +0000
@@ -0,0 +1,1 @@
+https://github.com/ARMmbed/mbed-os/#7e7f4f561bcdf84e50c947ebd2d5a14437f36f1c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed.bld	Wed Jun 17 10:11:19 2020 +0000
@@ -0,0 +1,1 @@
+https://os.mbed.com/users/mbed_official/code/mbed/builds/65be27845400
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/peripheral Pins.txt	Wed Jun 17 10:11:19 2020 +0000
@@ -0,0 +1,368 @@
+
+MBED_WEAK const PinMap PinMap_ADC[] = {
+    {PA_0,       ADC_1, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 0, 0)}, // ADC1_IN0
+    {PA_0_ALT0,  ADC_2, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 0, 0)}, // ADC2_IN0
+    {PA_0_ALT1,  ADC_3, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 0, 0)}, // ADC3_IN0
+    {PA_1,       ADC_1, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 1, 0)}, // ADC1_IN1 // Connected to RMII_REF_CLK [LAN8742A-CZ-TR_REFCLK0]
+    {PA_1_ALT0,  ADC_2, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 1, 0)}, // ADC2_IN1 // Connected to RMII_REF_CLK [LAN8742A-CZ-TR_REFCLK0]
+    {PA_1_ALT1,  ADC_3, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 1, 0)}, // ADC3_IN1 // Connected to RMII_REF_CLK [LAN8742A-CZ-TR_REFCLK0]
+    {PA_2,       ADC_1, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 2, 0)}, // ADC1_IN2 // Connected to RMII_MDIO [LAN8742A-CZ-TR_MDIO]
+    {PA_2_ALT0,  ADC_2, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 2, 0)}, // ADC2_IN2 // Connected to RMII_MDIO [LAN8742A-CZ-TR_MDIO]
+    {PA_2_ALT1,  ADC_3, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 2, 0)}, // ADC3_IN2 // Connected to RMII_MDIO [LAN8742A-CZ-TR_MDIO]
+    {PA_3,       ADC_1, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 3, 0)}, // ADC1_IN3
+    {PA_3_ALT0,  ADC_2, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 3, 0)}, // ADC2_IN3
+    {PA_3_ALT1,  ADC_3, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 3, 0)}, // ADC3_IN3
+    {PA_4,       ADC_1, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 4, 0)}, // ADC1_IN4
+    {PA_4_ALT0,  ADC_2, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 4, 0)}, // ADC2_IN4
+    {PA_5,       ADC_1, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 5, 0)}, // ADC1_IN5
+    {PA_5_ALT0,  ADC_2, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 5, 0)}, // ADC2_IN5
+    {PA_6,       ADC_1, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 6, 0)}, // ADC1_IN6
+    {PA_6_ALT0,  ADC_2, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 6, 0)}, // ADC2_IN6
+    {PA_7,       ADC_1, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 7, 0)}, // ADC1_IN7 // Connected to RMII_CRS_DV [LAN8742A-CZ-TR_CRS_DV]
+    {PA_7_ALT0,  ADC_2, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 7, 0)}, // ADC2_IN7 // Connected to RMII_CRS_DV [LAN8742A-CZ-TR_CRS_DV]
+    {PB_0,       ADC_1, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 8, 0)}, // ADC1_IN8 // Connected to LD1 [Green]
+    {PB_0_ALT0,  ADC_2, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 8, 0)}, // ADC2_IN8 // Connected to LD1 [Green]
+    {PB_1,       ADC_1, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 9, 0)}, // ADC1_IN9
+    {PB_1_ALT0,  ADC_2, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 9, 0)}, // ADC2_IN9
+    {PC_0,       ADC_1, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 10, 0)}, // ADC1_IN10
+    {PC_0_ALT0,  ADC_2, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 10, 0)}, // ADC2_IN10
+    {PC_0_ALT1,  ADC_3, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 10, 0)}, // ADC3_IN10
+    {PC_1,       ADC_1, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 11, 0)}, // ADC1_IN11 // Connected to RMII_MDC [LAN8742A-CZ-TR_MDC]
+    {PC_1_ALT0,  ADC_2, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 11, 0)}, // ADC2_IN11 // Connected to RMII_MDC [LAN8742A-CZ-TR_MDC]
+    {PC_1_ALT1,  ADC_3, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 11, 0)}, // ADC3_IN11 // Connected to RMII_MDC [LAN8742A-CZ-TR_MDC]
+    {PC_2,       ADC_1, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 12, 0)}, // ADC1_IN12
+    {PC_2_ALT0,  ADC_2, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 12, 0)}, // ADC2_IN12
+    {PC_2_ALT1,  ADC_3, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 12, 0)}, // ADC3_IN12
+    {PC_3,       ADC_1, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 13, 0)}, // ADC1_IN13
+    {PC_3_ALT0,  ADC_2, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 13, 0)}, // ADC2_IN13
+    {PC_3_ALT1,  ADC_3, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 13, 0)}, // ADC3_IN13
+    {PC_4,       ADC_1, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 14, 0)}, // ADC1_IN14 // Connected to RMII_RXD0 [LAN8742A-CZ-TR_RXD0]
+    {PC_4_ALT0,  ADC_2, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 14, 0)}, // ADC2_IN14 // Connected to RMII_RXD0 [LAN8742A-CZ-TR_RXD0]
+    {PC_5,       ADC_1, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 15, 0)}, // ADC1_IN15 // Connected to RMII_RXD1 [LAN8742A-CZ-TR_RXD1]
+    {PC_5_ALT0,  ADC_2, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 15, 0)}, // ADC2_IN15 // Connected to RMII_RXD1 [LAN8742A-CZ-TR_RXD1]
+    {PF_3,       ADC_3, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 9, 0)}, // ADC3_IN9
+    {PF_4,       ADC_3, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 14, 0)}, // ADC3_IN14
+    {PF_5,       ADC_3, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 15, 0)}, // ADC3_IN15
+    {PF_6,       ADC_3, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 4, 0)}, // ADC3_IN4
+    {PF_7,       ADC_3, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 5, 0)}, // ADC3_IN5
+    {PF_8,       ADC_3, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 6, 0)}, // ADC3_IN6
+    {PF_9,       ADC_3, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 7, 0)}, // ADC3_IN7
+    {PF_10,      ADC_3, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 8, 0)}, // ADC3_IN8
+    {NC, NC, 0}
+};
+
+MBED_WEAK const PinMap PinMap_ADC_Internal[] = {
+    {ADC_TEMP,   ADC_1,    STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 16, 0)},
+    {ADC_VREF,   ADC_1,    STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 17, 0)},
+    {ADC_VBAT,   ADC_1,    STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 18, 0)},
+    {NC, NC, 0}
+};
+
+//*** DAC ***
+
+MBED_WEAK const PinMap PinMap_DAC[] = {
+    {PA_4,       DAC_1, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 1, 0)}, // DAC_OUT1
+    {PA_5,       DAC_1, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 2, 0)}, // DAC_OUT2
+    {NC, NC, 0}
+};
+
+//*** I2C ***
+
+MBED_WEAK const PinMap PinMap_I2C_SDA[] = {
+    {PB_7,       I2C_1, STM_PIN_DATA(STM_MODE_AF_OD, GPIO_NOPULL, GPIO_AF4_I2C1)}, // Connected to LD2 [Blue]
+    {PB_9,       I2C_1, STM_PIN_DATA(STM_MODE_AF_OD, GPIO_NOPULL, GPIO_AF4_I2C1)},
+    {PB_11,      I2C_2, STM_PIN_DATA(STM_MODE_AF_OD, GPIO_NOPULL, GPIO_AF4_I2C2)},
+    {PC_9,       I2C_3, STM_PIN_DATA(STM_MODE_AF_OD, GPIO_NOPULL, GPIO_AF4_I2C3)},
+    {PD_13,      I2C_4, STM_PIN_DATA(STM_MODE_AF_OD, GPIO_NOPULL, GPIO_AF4_I2C4)},
+    {PF_0,       I2C_2, STM_PIN_DATA(STM_MODE_AF_OD, GPIO_NOPULL, GPIO_AF4_I2C2)},
+    {PF_15,      I2C_4, STM_PIN_DATA(STM_MODE_AF_OD, GPIO_NOPULL, GPIO_AF4_I2C4)},
+    {NC, NC, 0}
+};
+
+MBED_WEAK const PinMap PinMap_I2C_SCL[] = {
+    {PA_8,       I2C_3, STM_PIN_DATA(STM_MODE_AF_OD, GPIO_NOPULL, GPIO_AF4_I2C3)}, // Connected to USB_SOF [TP1]
+    {PB_6,       I2C_1, STM_PIN_DATA(STM_MODE_AF_OD, GPIO_NOPULL, GPIO_AF4_I2C1)},
+    {PB_8,       I2C_1, STM_PIN_DATA(STM_MODE_AF_OD, GPIO_NOPULL, GPIO_AF4_I2C1)},
+    {PB_10,      I2C_2, STM_PIN_DATA(STM_MODE_AF_OD, GPIO_NOPULL, GPIO_AF4_I2C2)},
+    {PD_12,      I2C_4, STM_PIN_DATA(STM_MODE_AF_OD, GPIO_NOPULL, GPIO_AF4_I2C4)},
+    {PF_1,       I2C_2, STM_PIN_DATA(STM_MODE_AF_OD, GPIO_NOPULL, GPIO_AF4_I2C2)},
+    {PF_14,      I2C_4, STM_PIN_DATA(STM_MODE_AF_OD, GPIO_NOPULL, GPIO_AF4_I2C4)},
+    {NC, NC, 0}
+};
+
+//*** PWM ***
+
+// TIM5 cannot be used because already used by the us_ticker
+MBED_WEAK const PinMap PinMap_PWM[] = {
+    {PA_0,       PWM_2,  STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF1_TIM2, 1, 0)}, // TIM2_CH1
+//  {PA_0,       PWM_5,  STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF2_TIM5, 1, 0)}, // TIM5_CH1
+    {PA_1,       PWM_2,  STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF1_TIM2, 2, 0)}, // TIM2_CH2 // Connected to RMII_REF_CLK [LAN8742A-CZ-TR_REFCLK0]
+//  {PA_1,       PWM_5,  STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF2_TIM5, 2, 0)}, // TIM5_CH2 // Connected to RMII_REF_CLK [LAN8742A-CZ-TR_REFCLK0]
+    {PA_2,       PWM_2,  STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF1_TIM2, 3, 0)}, // TIM2_CH3 // Connected to RMII_MDIO [LAN8742A-CZ-TR_MDIO]
+//  {PA_2,       PWM_5,  STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF2_TIM5, 3, 0)}, // TIM5_CH3 // Connected to RMII_MDIO [LAN8742A-CZ-TR_MDIO]
+    {PA_2_ALT0,  PWM_9,  STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF3_TIM9, 1, 0)}, // TIM9_CH1 // Connected to RMII_MDIO [LAN8742A-CZ-TR_MDIO]
+    {PA_3,       PWM_2,  STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF1_TIM2, 4, 0)}, // TIM2_CH4
+//  {PA_3,       PWM_5,  STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF2_TIM5, 4, 0)}, // TIM5_CH4
+    {PA_3_ALT0,  PWM_9,  STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF3_TIM9, 2, 0)}, // TIM9_CH2
+    {PA_5,       PWM_2,  STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF1_TIM2, 1, 0)}, // TIM2_CH1
+    {PA_5_ALT0,  PWM_8,  STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF3_TIM8, 1, 1)}, // TIM8_CH1N
+    {PA_6,       PWM_3,  STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF2_TIM3, 1, 0)}, // TIM3_CH1
+    {PA_6_ALT0,  PWM_13, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_TIM13, 1, 0)}, // TIM13_CH1
+    {PA_7,       PWM_1,  STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF1_TIM1, 1, 1)}, // TIM1_CH1N // Connected to RMII_CRS_DV [LAN8742A-CZ-TR_CRS_DV] - JP6 ON
+    {PA_7_ALT0,  PWM_3,  STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF2_TIM3, 2, 0)}, // TIM3_CH2 // Connected to RMII_CRS_DV [LAN8742A-CZ-TR_CRS_DV] - JP6 ON
+    {PA_7_ALT1,  PWM_8,  STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF3_TIM8, 1, 1)}, // TIM8_CH1N // Connected to RMII_CRS_DV [LAN8742A-CZ-TR_CRS_DV] - JP6 ON
+    {PA_7_ALT2,  PWM_14, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_TIM14, 1, 0)}, // TIM14_CH1 // Connected to RMII_CRS_DV [LAN8742A-CZ-TR_CRS_DV] - JP6 ON
+    {PA_8,       PWM_1,  STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF1_TIM1, 1, 0)}, // TIM1_CH1 // Connected to USB_SOF [TP1]
+    {PA_9,       PWM_1,  STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF1_TIM1, 2, 0)}, // TIM1_CH2 // Connected to USB_VBUS
+    {PA_10,      PWM_1,  STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF1_TIM1, 3, 0)}, // TIM1_CH3 // Connected to USB_ID
+    {PA_11,      PWM_1,  STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF1_TIM1, 4, 0)}, // TIM1_CH4 // Connected to USB_DM
+    {PA_15,      PWM_2,  STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF1_TIM2, 1, 0)}, // TIM2_CH1
+    {PB_0,       PWM_1,  STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF1_TIM1, 2, 1)}, // TIM1_CH2N // Connected to LD1 [Green]
+    {PB_0_ALT0,  PWM_3,  STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF2_TIM3, 3, 0)}, // TIM3_CH3 // Connected to LD1 [Green]
+    {PB_0_ALT1,  PWM_8,  STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF3_TIM8, 2, 1)}, // TIM8_CH2N // Connected to LD1 [Green]
+    {PB_1,       PWM_1,  STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF1_TIM1, 3, 1)}, // TIM1_CH3N
+    {PB_1_ALT0,  PWM_3,  STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF2_TIM3, 4, 0)}, // TIM3_CH4
+    {PB_1_ALT1,  PWM_8,  STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF3_TIM8, 3, 1)}, // TIM8_CH3N
+    {PB_3,       PWM_2,  STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF1_TIM2, 2, 0)}, // TIM2_CH2 // Connected to SW0
+    {PB_4,       PWM_3,  STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF2_TIM3, 1, 0)}, // TIM3_CH1
+    {PB_5,       PWM_3,  STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF2_TIM3, 2, 0)}, // TIM3_CH2
+    {PB_6,       PWM_4,  STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF2_TIM4, 1, 0)}, // TIM4_CH1
+    {PB_7,       PWM_4,  STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF2_TIM4, 2, 0)}, // TIM4_CH2 // Connected to LD2 [Blue]
+    {PB_8,       PWM_4,  STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF2_TIM4, 3, 0)}, // TIM4_CH3
+    {PB_8_ALT0,  PWM_10, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF3_TIM10, 1, 0)}, // TIM10_CH1
+    {PB_9,       PWM_4,  STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF2_TIM4, 4, 0)}, // TIM4_CH4
+    {PB_9_ALT0,  PWM_11, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF3_TIM11, 1, 0)}, // TIM11_CH1
+    {PB_10,      PWM_2,  STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF1_TIM2, 3, 0)}, // TIM2_CH3
+    {PB_11,      PWM_2,  STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF1_TIM2, 4, 0)}, // TIM2_CH4
+    {PB_13,      PWM_1,  STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF1_TIM1, 1, 1)}, // TIM1_CH1N // Connected to RMII_TXD1 [LAN8742A-CZ-TR_TXD1] - JP7 OFF
+    {PB_14,      PWM_1,  STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF1_TIM1, 2, 1)}, // TIM1_CH2N // Connected to LD3 [Red]
+    {PB_14_ALT0, PWM_8,  STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF3_TIM8, 2, 1)}, // TIM8_CH2N // Connected to LD3 [Red]
+    {PB_14_ALT1, PWM_12, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_TIM12, 1, 0)}, // TIM12_CH1 // Connected to LD3 [Red]
+    {PB_15,      PWM_1,  STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF1_TIM1, 3, 1)}, // TIM1_CH3N
+    {PB_15_ALT0, PWM_8,  STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF3_TIM8, 3, 1)}, // TIM8_CH3N
+    {PB_15_ALT1, PWM_12, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_TIM12, 2, 0)}, // TIM12_CH2
+    {PC_6,       PWM_3,  STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF2_TIM3, 1, 0)}, // TIM3_CH1
+    {PC_6_ALT0,  PWM_8,  STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF3_TIM8, 1, 0)}, // TIM8_CH1
+    {PC_7,       PWM_3,  STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF2_TIM3, 2, 0)}, // TIM3_CH2
+    {PC_7_ALT0,  PWM_8,  STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF3_TIM8, 2, 0)}, // TIM8_CH2
+    {PC_8,       PWM_3,  STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF2_TIM3, 3, 0)}, // TIM3_CH3
+    {PC_8_ALT0,  PWM_8,  STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF3_TIM8, 3, 0)}, // TIM8_CH3
+    {PC_9,       PWM_3,  STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF2_TIM3, 4, 0)}, // TIM3_CH4
+    {PC_9_ALT0,  PWM_8,  STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF3_TIM8, 4, 0)}, // TIM8_CH4
+    {PD_12,      PWM_4,  STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF2_TIM4, 1, 0)}, // TIM4_CH1
+    {PD_13,      PWM_4,  STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF2_TIM4, 2, 0)}, // TIM4_CH2
+    {PD_14,      PWM_4,  STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF2_TIM4, 3, 0)}, // TIM4_CH3
+    {PD_15,      PWM_4,  STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF2_TIM4, 4, 0)}, // TIM4_CH4
+    {PE_5,       PWM_9,  STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF3_TIM9, 1, 0)}, // TIM9_CH1
+    {PE_6,       PWM_9,  STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF3_TIM9, 2, 0)}, // TIM9_CH2
+    {PE_8,       PWM_1,  STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF1_TIM1, 1, 1)}, // TIM1_CH1N
+    {PE_9,       PWM_1,  STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF1_TIM1, 1, 0)}, // TIM1_CH1
+    {PE_10,      PWM_1,  STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF1_TIM1, 2, 1)}, // TIM1_CH2N
+    {PE_11,      PWM_1,  STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF1_TIM1, 2, 0)}, // TIM1_CH2
+    {PE_12,      PWM_1,  STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF1_TIM1, 3, 1)}, // TIM1_CH3N
+    {PE_13,      PWM_1,  STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF1_TIM1, 3, 0)}, // TIM1_CH3
+    {PE_14,      PWM_1,  STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF1_TIM1, 4, 0)}, // TIM1_CH4
+    {PF_6,       PWM_10, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF3_TIM10, 1, 0)}, // TIM10_CH1
+    {PF_7,       PWM_11, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF3_TIM11, 1, 0)}, // TIM11_CH1
+    {PF_8,       PWM_13, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_TIM13, 1, 0)}, // TIM13_CH1
+    {PF_9,       PWM_14, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_TIM14, 1, 0)}, // TIM14_CH1
+    {NC, NC, 0}
+};
+
+//*** SERIAL ***
+
+MBED_WEAK const PinMap PinMap_UART_TX[] = {
+    {PA_0,       UART_4,  STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF8_UART4)},
+    {PA_2,       UART_2,  STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF7_USART2)}, // Connected to RMII_MDIO [LAN8742A-CZ-TR_MDIO]
+    {PA_9,       UART_1,  STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF7_USART1)}, // Connected to USB_VBUS
+    {PB_6,       UART_1,  STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF7_USART1)},
+//  {PB_10,      UART_3,  STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF7_USART3)}, // STDIO UART
+    {PC_6,       UART_6,  STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF8_USART6)},
+//  {PC_10,      UART_3,  STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF7_USART3)}, // STDIO UART
+    {PC_10,      UART_4,  STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF8_UART4)},
+    {PC_12,      UART_5,  STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF8_UART5)},
+    {PD_5,       UART_2,  STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF7_USART2)},
+    {PD_8,       UART_3,  STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF7_USART3)}, // Connected to STDIO_UART_TX
+    {PE_1,       UART_8,  STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF8_UART8)},
+    {PE_8,       UART_7,  STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF8_UART7)},
+    {PF_7,       UART_7,  STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF8_UART7)},
+    {PG_14,      UART_6,  STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF8_USART6)},
+    {NC, NC, 0}
+};
+
+MBED_WEAK const PinMap PinMap_UART_RX[] = {
+    {PA_1,       UART_4,  STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF8_UART4)}, // Connected to RMII_REF_CLK [LAN8742A-CZ-TR_REFCLK0]
+    {PA_3,       UART_2,  STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF7_USART2)},
+    {PA_10,      UART_1,  STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF7_USART1)}, // Connected to USB_ID
+    {PB_7,       UART_1,  STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF7_USART1)}, // Connected to LD2 [Blue]
+//  {PB_11,      UART_3,  STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF7_USART3)}, // STDIO UART
+    {PC_7,       UART_6,  STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF8_USART6)},
+//  {PC_11,      UART_3,  STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF7_USART3)}, // STDIO UART
+    {PC_11,      UART_4,  STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF8_UART4)},
+    {PD_2,       UART_5,  STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF8_UART5)},
+    {PD_6,       UART_2,  STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF7_USART2)},
+    {PD_9,       UART_3,  STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF7_USART3)}, // Connected to STDIO_UART_RX
+    {PE_0,       UART_8,  STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF8_UART8)},
+    {PE_7,       UART_7,  STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF8_UART7)},
+    {PF_6,       UART_7,  STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF8_UART7)},
+    {PG_9,       UART_6,  STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF8_USART6)},
+    {NC, NC, 0}
+};
+
+MBED_WEAK const PinMap PinMap_UART_RTS[] = {
+    {PA_1,       UART_2,  STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF7_USART2)}, // Connected to RMII_REF_CLK [LAN8742A-CZ-TR_REFCLK0]
+    {PA_12,      UART_1,  STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF7_USART1)}, // Connected to USB_DP
+    {PA_15,      UART_4,  STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF8_UART4)},
+    {PB_14,      UART_3,  STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF7_USART3)}, // Connected to LD3 [Red]
+    {PC_8,       UART_5,  STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF7_UART5)},
+    {PD_4,       UART_2,  STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF7_USART2)},
+    {PD_12,      UART_3,  STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF7_USART3)},
+    {PD_15,      UART_8,  STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF8_UART8)},
+    {PE_9,       UART_7,  STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF8_UART7)},
+    {PF_8,       UART_7,  STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF8_UART7)},
+    {PG_8,       UART_6,  STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF8_USART6)},
+    {PG_12,      UART_6,  STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF8_USART6)},
+    {NC, NC, 0}
+};
+
+MBED_WEAK const PinMap PinMap_UART_CTS[] = {
+    {PA_0,       UART_2,  STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF7_USART2)},
+    {PA_11,      UART_1,  STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF7_USART1)}, // Connected to USB_DM
+    {PB_0,       UART_4,  STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF8_UART4)}, // Connected to LD1 [Green]
+    {PB_13,      UART_3,  STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF7_USART3)}, // Connected to RMII_TXD1 [LAN8742A-CZ-TR_TXD1]
+    {PC_9,       UART_5,  STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF7_UART5)},
+    {PD_3,       UART_2,  STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF7_USART2)},
+    {PD_11,      UART_3,  STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF7_USART3)},
+    {PD_14,      UART_8,  STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF8_UART8)},
+    {PE_10,      UART_7,  STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF8_UART7)},
+    {PF_9,       UART_7,  STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF8_UART7)},
+    {PG_13,      UART_6,  STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF8_USART6)}, // Connected to RMII_TXD0 [LAN8742A-CZ-TR_TXD0]
+    {PG_15,      UART_6,  STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF8_USART6)},
+    {NC, NC, 0}
+};
+
+//*** SPI ***
+
+MBED_WEAK const PinMap PinMap_SPI_MOSI[] = {
+    {PA_7,       SPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF5_SPI1)}, // Connected to RMII_CRS_DV [LAN8742A-CZ-TR_CRS_DV]
+    {PB_2,       SPI_3, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF7_SPI3)},
+    {PB_5,       SPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF5_SPI1)},
+    {PB_5_ALT0,  SPI_3, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF6_SPI3)},
+    {PB_15,      SPI_2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF5_SPI2)},
+    {PC_1,       SPI_2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF5_SPI2)}, // Connected to RMII_MDC [LAN8742A-CZ-TR_MDC]
+    {PC_3,       SPI_2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF5_SPI2)},
+    {PC_12,      SPI_3, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF6_SPI3)},
+    {PD_6,       SPI_3, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF5_SPI3)},
+    {PE_6,       SPI_4, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF5_SPI4)},
+    {PE_14,      SPI_4, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF5_SPI4)},
+    {PF_9,       SPI_5, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF5_SPI5)},
+    {PF_11,      SPI_5, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF5_SPI5)},
+    {PG_14,      SPI_6, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF5_SPI6)},
+    {NC, NC, 0}
+};
+
+MBED_WEAK const PinMap PinMap_SPI_MISO[] = {
+    {PA_6,       SPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF5_SPI1)},
+    {PB_4,       SPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF5_SPI1)},
+    {PB_4_ALT0,  SPI_3, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF6_SPI3)},
+    {PB_14,      SPI_2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF5_SPI2)}, // Connected to LD3 [Red]
+    {PC_2,       SPI_2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF5_SPI2)},
+    {PC_11,      SPI_3, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF6_SPI3)},
+    {PE_5,       SPI_4, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF5_SPI4)},
+    {PE_13,      SPI_4, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF5_SPI4)},
+    {PF_8,       SPI_5, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF5_SPI5)},
+    {PG_12,      SPI_6, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF5_SPI6)},
+    {NC, NC, 0}
+};
+
+MBED_WEAK const PinMap PinMap_SPI_SCLK[] = {
+    {PA_5,       SPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF5_SPI1)},
+    {PA_9,       SPI_2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF5_SPI2)}, // Connected to USB_VBUS
+    {PB_3,       SPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF5_SPI1)}, // Connected to SW0
+    {PB_3_ALT0,  SPI_3, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF6_SPI3)}, // Connected to SW0
+    {PB_10,      SPI_2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF5_SPI2)},
+    {PB_13,      SPI_2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF5_SPI2)}, // Connected to RMII_TXD1 [LAN8742A-CZ-TR_TXD1]
+    {PC_10,      SPI_3, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF6_SPI3)},
+    {PD_3,       SPI_2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF5_SPI2)},
+    {PE_2,       SPI_4, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF5_SPI4)},
+    {PE_12,      SPI_4, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF5_SPI4)},
+    {PF_7,       SPI_5, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF5_SPI5)},
+    {PG_13,      SPI_6, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF5_SPI6)}, // Connected to RMII_TXD0 [LAN8742A-CZ-TR_TXD0]
+    {NC, NC, 0}
+};
+
+MBED_WEAK const PinMap PinMap_SPI_SSEL[] = {
+    {PA_4,       SPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF5_SPI1)},
+    {PA_4_ALT0,  SPI_3, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF6_SPI3)},
+    {PA_15,      SPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF5_SPI1)},
+    {PA_15_ALT0, SPI_3, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF6_SPI3)},
+    {PB_4,       SPI_2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF7_SPI2)},
+    {PB_9,       SPI_2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF5_SPI2)},
+    {PB_12,      SPI_2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF5_SPI2)},
+    {PE_4,       SPI_4, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF5_SPI4)},
+    {PE_11,      SPI_4, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF5_SPI4)},
+    {PF_6,       SPI_5, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF5_SPI5)},
+    {PG_8,       SPI_6, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF5_SPI6)},
+    {NC, NC, 0}
+};
+
+//*** CAN ***
+
+MBED_WEAK const PinMap PinMap_CAN_RD[] = {
+    {PA_11,      CAN_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF9_CAN1)}, // Connected to USB_DM
+    {PB_5,       CAN_2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF9_CAN2)},
+    {PB_8,       CAN_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF9_CAN1)},
+    {PB_12,      CAN_2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF9_CAN2)},
+    {PD_0,       CAN_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF9_CAN1)},
+    {NC, NC, 0}
+};
+
+MBED_WEAK const PinMap PinMap_CAN_TD[] = {
+    {PA_12,      CAN_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF9_CAN1)}, // Connected to USB_DP
+    {PB_6,       CAN_2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF9_CAN2)},
+    {PB_9,       CAN_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF9_CAN1)},
+    {PB_13,      CAN_2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF9_CAN2)}, // Connected to RMII_TXD1 [LAN8742A-CZ-TR_TXD1]
+    {PD_1,       CAN_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF9_CAN1)},
+    {NC, NC, 0}
+};
+
+//*** QUADSPI ***
+
+MBED_WEAK const PinMap PinMap_QSPI_DATA0[] = {
+    {PC_9,      QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QUADSPI)},  // QUADSPI_BK1_IO0
+    {PD_11,     QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QUADSPI)},  // QUADSPI_BK1_IO0
+    {PF_8,      QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)},  // QUADSPI_BK1_IO0
+    {NC, NC, 0}
+};
+
+MBED_WEAK const PinMap PinMap_QSPI_DATA1[] = {
+    {PC_10,     QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QUADSPI)},  // QUADSPI_BK1_IO1
+    {PD_12,     QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QUADSPI)},  // QUADSPI_BK1_IO1
+    {PF_9,      QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)},  // QUADSPI_BK1_IO1
+    {NC, NC, 0}
+};
+
+MBED_WEAK const PinMap PinMap_QSPI_DATA2[] = {
+    {PE_2,      QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QUADSPI)},  // QUADSPI_BK1_IO2
+    {PF_7,      QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QUADSPI)},  // QUADSPI_BK1_IO2
+    {NC, NC, 0}
+};
+
+MBED_WEAK const PinMap PinMap_QSPI_DATA3[] = {
+    {PA_1,      QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QUADSPI)},  // QUADSPI_BK1_IO3 // Connected to RMII_REF_CLK [LAN8742A-CZ-TR_REFCLK0]
+    {PD_13,     QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QUADSPI)},  // QUADSPI_BK1_IO3
+    {PF_6,      QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QUADSPI)},  // QUADSPI_BK1_IO3
+    {NC, NC, 0}
+};
+
+MBED_WEAK const PinMap PinMap_QSPI_SCLK[] = {
+    {PB_2,      QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF9_QUADSPI)},  // QUADSPI_CLK
+    {NC, NC, 0}
+};
+
+MBED_WEAK const PinMap PinMap_QSPI_SSEL[] = {
+    {PB_6,      QSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)},  // QUADSPI_BK1_NCS
+    {NC, NC, 0}
+};
+
+*/