/*******************************************************************************
  MPLAB Harmony Application Source File
  
  Company:
    Microchip Technology Inc.
  
  File Name:
    weller.c

  Summary:
    This file contains the source code for the MPLAB Harmony application.

  Description:
 * Ver 20171008 
 *    - EEPROM running
 *    - ADC running
 *    - Start implementing state machine
 *    - Needs
 *        - state machine and all transitions (none in there yet)
 *        - user interface stuff other than pictures
 * 
 * Ver
 *******************************************************************************/

// DOM-IGNORE-BEGIN
/*******************************************************************************
Copyright (c) 2013-2014 released Microchip Technology Inc.  All rights reserved.

Microchip licenses to you the right to use, modify, copy and distribute
Software only when embedded on a Microchip microcontroller or digital signal
controller that is integrated into your product or third party product
(pursuant to the sublicense terms in the accompanying license agreement).

You should refer to the license agreement accompanying this Software for
additional information regarding your rights and obligations.

SOFTWARE AND DOCUMENTATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF
MERCHANTABILITY, TITLE, NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE.
IN NO EVENT SHALL MICROCHIP OR ITS LICENSORS BE LIABLE OR OBLIGATED UNDER
CONTRACT, NEGLIGENCE, STRICT LIABILITY, CONTRIBUTION, BREACH OF WARRANTY, OR
OTHER LEGAL EQUITABLE THEORY ANY DIRECT OR INDIRECT DAMAGES OR EXPENSES
INCLUDING BUT NOT LIMITED TO ANY INCIDENTAL, SPECIAL, INDIRECT, PUNITIVE OR
CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF PROCUREMENT OF
SUBSTITUTE GOODS, TECHNOLOGY, SERVICES, OR ANY CLAIMS BY THIRD PARTIES
(INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF), OR OTHER SIMILAR COSTS.
 *******************************************************************************/
// DOM-IGNORE-END


// *****************************************************************************
// *****************************************************************************
// Section: Included Files 
// *****************************************************************************
// *****************************************************************************

#include "Reflow.h"
#include "delay.h"
#include "KS0108-PIC16.h"
#include "KS0108.h"
#include "Solder.h"
#include "Zap_Off.h"
#include "Zap_On.h"
#include "TGM_Logo.h"
#include "EEPROM.h"
#include <stdio.h>
#include <xc.h>
#include <math.h>
#include "framework/driver/spi/static/drv_spi_static.h"



// *****************************************************************************
// *****************************************************************************
// Section: Global Data Definitions
// *****************************************************************************
// *****************************************************************************

// *****************************************************************************
/* Application Data

  Summary:
    Holds application data

  Description:
    This structure holds the application's data.

  Remarks:
    This structure should be initialized by the APP_Initialize function.
    
    Application strings and buffers are be defined outside this structure.
*/
WELLER_DATA wellerData;

static unsigned char Old_Rot_Status = 0;   /* Records state of rotary control */
int Fast_Loop_Counter = Fast_Counter_Init; /* Used to set Fast_Cnt */
int Slow_Loop_Counter = Slow_Counter_Init; /* Used to see if user turning control continuously */
static unsigned char Keypress_Read = 0;    /* this is the data on key / rotation changes */
static unsigned char Key_Just_Pressed = 0; 	/* use this to keep track of which keys have been pressed */
int Fast_Change = 1;			/* use this to indicate fast change of values */

/* This is where all the data is stored... */
data_val_struct Data_Values;                            
char loop, test_temp;
/* location at which input data is written into a cyclical buffer */
unsigned int Write_Pointer_Offset, Ch1_Rd_Offset, Ch2_Rd_Offset; 
/* used for output clipping to 24 bits */
int Out_Test_Temp;    

/* SPI Globals*/
uint8_t __attribute__ ((aligned (16))) txData[]  = "                ";
uint8_t __attribute__ ((aligned (16))) rxData[sizeof(txData)];
uint8_t txDataSize = sizeof(txData);




/*****************************************************************************/
// Graphics Buffers
//  Graphics Macros
/*****************************************************************************/
//unsigned char ScreenBuff[KS0108_SCREEN_HEIGHT/8][KS0108_SCREEN_WIDTH] , ScreenBuff1[KS0108_SCREEN_HEIGHT/8][KS0108_SCREEN_WIDTH]; 
unsigned char ScreenBuff[KS0108_SCREEN_WIDTH][KS0108_SCREEN_HEIGHT/8] , ScreenBuff1[KS0108_SCREEN_WIDTH][KS0108_SCREEN_HEIGHT/8]; 
/* You might want to move these into the display LCD function - though it is really not a gut buster for these two */
char line1[] =   Line1_Init;
char line2[] =   Line2_Init;
char *line1_ptr, *line2_ptr;				/* use these to point into the arrays */
/* These are ROM constants used in bnuilding the display */
const char Blank_Char = Blank_Char_Init;            /* ROM */
unsigned int display_temp;

/*****************************************************************************/
/*                    Measured Data for Weller function                      */
/*****************************************************************************/
//ADC buffers and data
unsigned int channel6;      // conversion result as read from result buffer
unsigned int channel7;      // conversion result as read from result buffer
unsigned int offset;        // buffer offset to point to the base of the idle buffer
int Measured_Temp;          // MEasured Temperature


// *****************************************************************************
// *****************************************************************************
// Section: Application Callback Functions
// *****************************************************************************
// *****************************************************************************
static void APP_TimerCallback ( uintptr_t context, uint32_t alarmCount )
{
    int Slice;              /* used in calc of heater time */
    int Heat_On_To_Slice;   /* will be Percentage of heat command (ut) times slices */
    
    wellerData.heartbeatCount++;
    if (wellerData.heartbeatCount >= APP_HEARTBEAT_COUNT_MAX)
    {
        /* increment process timer */
        wellerData.Process_Time +=1;

        /* then decrement the snooze timer */
        if (wellerData.Snooze_Counter > 0)
            wellerData.Snooze_Counter--;
        wellerData.heartbeatCount = 0;
        wellerData.heartbeatToggle = true;
        
        /* then decrement the Revert To Idle timer */
        if (wellerData.Revert_To_Idle_Counter > 0)
            wellerData.Revert_To_Idle_Counter--;
        /* add this to drive sreen updates in idle */
        wellerData.UI_Update_Display = true;
    }
    
    /*   This section of code:                  */
    /* - determines which slide of time we are in out of a set number of slices */
    /* - Clculates what percentage of process output is demanded of the maximum */
    /* - Scales this to the number of slices                                    */
    /* - turns the heater on up until that slice                                */

    Slice = wellerData.Process_Time % Number_Of_Slices;
    Heat_On_To_Slice = (int)(wellerData.ut * Number_Of_Slices)/ ut_Max;
//    if ((Slice < Heat_On_To_Slice) && (wellerData.Soak_Done) && (!wellerData.Reflow_Done))
    if ((Slice < Heat_On_To_Slice))
    {
        wellerData.Heater_On = true;
        SYS_PORTS_PinSet(PORTS_ID_0, APP_WELLER_HEATER_PORT, APP_WELLER_HEATER_PIN);
    }
    else
    {
        wellerData.Heater_On = false;
        SYS_PORTS_PinClear(PORTS_ID_0, APP_WELLER_HEATER_PORT, APP_WELLER_HEATER_PIN);
    }    
}


static void APP_UI_Callback ( uintptr_t context, uint32_t alarmCount )
{
    unsigned char Current_Rot_Status = 0;
    unsigned int ADC_Temp_In;
    int Old_Heater_State = 0;
    int ADC_To_Temp = 0;
    
    /* Save old heater state then turn heater off by default */
    Old_Heater_State = wellerData.Heater_On;
            
    /* it is convenient to update the temp measurement in the ISR */
    /* this way is is updated without blocking */
    if (DRV_ADC_SamplesAvailable(REFLOW_Temp_ADC))
        {
            ADC_Temp_In = DRV_ADC_SamplesRead(REFLOW_Temp_ADC);
            /* scale and add offset */
            ADC_To_Temp = ((ADC_Temp_In * wellerData.Temp_Coeff*Temp_Scale)/Tempco_Scale + wellerData.Temp_Sensor_Offset);
            wellerData.Temp_Meas =  (wellerData.Temp_Meas * (ADC_Filter_Scale-ADC_Filter_Coeff) + ADC_Filter_Coeff*ADC_To_Temp)/ADC_Filter_Scale;
        }

    /* update the pretty picture on he screen */
    if ((Old_Heater_State != wellerData.Heater_On) &&(wellerData.state == WELLER_STATE_IDLE))
    {
        wellerData.UI_Update_Display = true;
        if (wellerData.Heater_On)
            WriteBMP_Buf(ScreenBuff, Zap_On, Zap_X, Zap_Y, Zap_On_Width, Zap_On_Height);
        else
            WriteBMP_Buf(ScreenBuff, Zap_Off, Zap_X, Zap_Y, Zap_Off_Width, Zap_Off_Height);
        wellerData.UI_Update_Display = true;
        /* update old temp meas if we have updated the display*/
        wellerData.Temp_Last_Update = wellerData.Temp_Meas;
    }

    /* update the number on the screen if it's changed */
    if (((abs(wellerData.Temp_Last_Update - wellerData.Temp_Meas)) > UI_Temp_Meas_Update_Threshold) 
            && (wellerData.state == WELLER_STATE_IDLE) && (wellerData.UI_Display_Lockout == false))
    {
        Update_Temp_Meas(wellerData.Temp_Meas/Temp_Scale);
        wellerData.UI_Update_Display = true;
        wellerData.Temp_Last_Update = wellerData.Temp_Meas;
    }
        
    /*Read Rot Status and mask off bits of interest */
	Current_Rot_Status = HMI_Port & (Vals_0 + Vals_1 + Exit + Sel);
	Key_Just_Pressed = (Current_Rot_Status != Old_Rot_Status);
    /* set the flag */
       
    if(Key_Just_Pressed)
    {
        /* Only do this if something has changed - but neither of the select or exit buttons are pressed */
        if (Key_Just_Pressed  && !(Current_Rot_Status & (Sel + Exit)))
        {
            /* Old Type Encoder is biphase input on two ports with */
            /*      Each detent click of the resolver being one change in phase*/
            /*      Thus one gray code change of the inputs occurs per click*/
            if Encoder_Type_Is_Old
            {
                if (Old_Rot_Status == Phase_0)  /* From here need to work out if going up or down */
                {
                    if (Current_Rot_Status == Phase_1)
                        Keypress_Read = Rot_Up;
                    else
                        Keypress_Read = Rot_Down;
                }
                else if (Old_Rot_Status == Phase_1)  /* From here need to work out if going up or down */
                {
                    if (Current_Rot_Status == Phase_2)
                        Keypress_Read = Rot_Up;
                    else
                        Keypress_Read = Rot_Down;
                }
                else if (Old_Rot_Status == Phase_2)  /* From here need to work out if going up or down */
                {
                    if (Current_Rot_Status == Phase_3)
                        Keypress_Read = Rot_Up;
                    else
                        Keypress_Read = Rot_Down;
                }
                else if (Old_Rot_Status == Phase_3)  /* From here need to work out if going up or down */
                {
                    if (Current_Rot_Status == Phase_0)
                        Keypress_Read = Rot_Up;
                    else
                        Keypress_Read = Rot_Down;
                }
                wellerData.UI_Keypressed = true;
            }

            /* Type A - TYPE 2 on schematics - Encoder is biphase input on two ports with */
            /*      Each detent click of the resolver being four changes in phase*/
            /*      Thus one complete cycle of gray code occurs per click*/
            /*      Type A goes 11 -> 10 -> 00 -> 01 -> 11 and vice versa*/
            /*      This is the ALTRONICS device and my EBAY sourced devices */
            else if Encoder_Type_Is_TypeA 
            {
                /* Phase_0 = 00*/
                /* From here need to work out if going up or down or reading crap*/
                /* CW 00 -> 01 */
                /* CCW 00-> 10 */
                /* But we do not want to act on these as it is mid-click*/
                if (Old_Rot_Status == Phase_0)
                {
                    /* Have read crap*/
                    Keypress_Read = 0;
                }
                /* From here need to work out if going up or down or reading crap*/
                /* CW 01 -> 11 */
                /* CCW 01-> 00 */
                /* But we do not want to act on these as it is mid-click*/
                else if (Old_Rot_Status == Phase_1)
                {
                    /* Have read crap*/
                    Keypress_Read = 0;
                }
                /* From here need to work out if going up or down or reading crap*/
                /* CW 11 -> 10 */
                /* CCW 11-> 01 */
                /* This is it... do something*/
                else if (Old_Rot_Status == Phase_2)
                {
                    if (Current_Rot_Status == Phase_3)
                    {
                        Keypress_Read = Rot_Up;
                        wellerData.UI_Keypressed = true;
                    }
                    else if (Current_Rot_Status == Phase_1)
                    {
                        Keypress_Read = Rot_Down;
                        wellerData.UI_Keypressed = true;
                    }
                    else Keypress_Read = 0;
 //                   DelayUs(debounce_time_us);
                    
                }
                /* From here need to work out if going up or down or reading crap*/
                /* CW 10 -> 00 */
                /* CCW 10-> 11 */
                /* But we do not want to act on these as it is mid-click*/
                else if (Old_Rot_Status == Phase_3)
                {
                    /* Have read crap*/
                    Keypress_Read = 0;
                }
            }
            /* Type B  - TYPE 2 on schematics -  Encoder is biphase input on two ports with */
            /*  This is the JAYCAR encoder. */
            /*      Each detent click of the resolver being two changes in phase*/
            /*      Thus one complete cycle of pseudo gray code occurs every 2nd click*/
            /*      Type B goes 11 -> 10 -> 00 CW on the first click then...*/
            /*                  00 -> 10 -> 11 CW on the second click*/
            /*                  11 -> 01 -> 00 CW on the first click, then...*/
            /*                  00 -> 01 -> 11 CW on the second click*/
            else if Encoder_Type_Is_TypeB
            {
                /* Phase_0 = 00*/
                /* From here need to work out if going up or down or reading crap*/
                /* CW 00 -> 10 */
                /* CCW 00-> 01 */
                if (Old_Rot_Status == Phase_0)
                {
                    if (Current_Rot_Status == Phase_1)
                    {
                        Keypress_Read = Rot_Up;
                        wellerData.UI_Keypressed = true;
                    }
                    else if (Current_Rot_Status == Phase_3)
                    {
                        Keypress_Read = Rot_Down;
                        wellerData.UI_Keypressed = true;
                    }
                    else
                        Keypress_Read = 0;
                    
                    /* The Jaycar encoders have reversed pinouts to 
                       the baseline code!*/
                }
                /* Phase_1 = 01*/
                /* This is an intermediate state as the encoder is clicked...*/
                /* Do not want to act on these */
                else if (Old_Rot_Status == Phase_1)
                {
                    /* Have read crap*/
                    Keypress_Read = 0;
                }
                /* Phase_2 = 11*/
                /* From here need to work out if going up or down or reading crap*/
                /* CW 11 -> 10 */
                /* CCW 11-> 01 */
                /* OK This is it... */
                else if (Old_Rot_Status == Phase_2)
                {
                    if (Current_Rot_Status == Phase_1)
                    {
                        Keypress_Read = Rot_Down;
                        wellerData.UI_Keypressed = true;
                    }
                    else if (Current_Rot_Status == Phase_3)
                    {
                        Keypress_Read = Rot_Up;
                        wellerData.UI_Keypressed = true;
                    }
                    else
                        Keypress_Read = 0;
                }
                /* Phase_3 = 10*/
                /* again an intermediate state */
                /* We do not want to act on these */
                else if (Old_Rot_Status == Phase_3)  /* From here need to work out if going up or down */
                {
                    /* Have read crap*/
                    Keypress_Read = 0;
                }
                else
                {
                    Keypress_Read = 0;
                }
            }

            Slow_Loop_Counter = Slow_Counter_Init;	/* If key just pressed initialise slow counter */

            if (Fast_Loop_Counter > (unsigned int)0)
                Fast_Loop_Counter--;
        }
        /* else if key pressed is not a rotation, then...*/
        else if (Key_Just_Pressed && (Current_Rot_Status & (Sel + Exit)))
        {
            if (Current_Rot_Status & Sel)
                Keypress_Read = Sel;
            if (Current_Rot_Status & Exit)
                Keypress_Read = Exit;
            Fast_Change = 1;
            wellerData.UI_Keypressed = true;
        }
        else    /* else not Key_just_Pressed */
        {
            Keypress_Read = 0;
            if (Slow_Loop_Counter > (unsigned int)0)
                Slow_Loop_Counter--;
        }
    }
        
	if (Slow_Loop_Counter == (unsigned int)0)
	{
		Fast_Change = 1;
		Fast_Loop_Counter = Fast_Counter_Init;
	}

	if (Fast_Loop_Counter == (unsigned int)0)   /* move into fast change of value for user */
	{
        Fast_Change = 100;
	}

	Old_Rot_Status = Current_Rot_Status;   /*Record Rot Status to allow comparison next ISR loop */

    // Increment User Interface Update Counter
    // This cimply cycles and the UI is only updated at UI_DIV intervals of this
    wellerData.UI_Update_Counter++;
    
}


// *****************************************************************************
// *****************************************************************************
// Section: Application Local Functions
// *****************************************************************************
// *****************************************************************************
/************************************************************************/
/* 	Write Line 1 and Line 2 of LCD							   */
/************************************************************************/
void Update_LCD(void)
{
    /* Clear Screen */
    GLCD_ClearScreen();

    /* write line1 */
    GLCD_WriteString_12x7_buf(ScreenBuff,&(line1[0]),0, 0);
    GLCD_WriteString_12x7_buf(ScreenBuff,&(line2[0]),0, 16);
    Refresh_LCD;
}

void Write_Boot_Ver()
{
    /* write value to screen buffer */
    GLCD_ClearRegion_buff(ScreenBuff, UI_BootClr_X1, UI_BootClr_Y1, UI_BootClr_X2, UI_BootClr_Y2);
    sprintf(line1, Line1_Init);
    sprintf(line2, Line2_Init);
    GLCD_WriteString_12x7_buf(ScreenBuff,&(line1[0]),UI_BootVer_X, UI_BootVer_Y);
    GLCD_WriteString_12x7_buf(ScreenBuff,&(line2[0]),UI_BootMod_X, UI_BootMod_Y);
}

void Update_Temp_Set(unsigned int Set)
{
    /* write value to screen buffer */
    sprintf(line1, "%3d",Set);
    GLCD_WriteString_16x11_buf(ScreenBuff,&(line1[0]),UI_Set_X, UI_Set_Y);
}

void Update_Temp_Meas(int Meas)
{    
    /* write value to screen buffer */
    sprintf(line2, "%3d",Meas);
    GLCD_WriteString_16x11_buf(ScreenBuff,&(line2[0]),UI_Meas_X, UI_Meas_Y);
}

/*******************************************************************************
  Function:
    void Splash_Screen ( void )
  Remarks:
 * PResents strart up screen, initialises display for idle state
******************************************************************************/
void Splash_Screen()
{    
    /* write TGM splash to screen buffer */
    WriteBMP(ScreenBuff, SC_Logo_Full, 0, 0, 128, 64);
    Refresh_LCD;
    WELLER_EEPROM_Initialize();
    DelayMs(1500);
    /* write version to screen buffer*/
    WriteBMP(ScreenBuff, Solder, 0, 0, 128, 64);
    Write_Boot_Ver();
    Refresh_LCD;
    DelayMs(1000);
    Idle_Screen();
    Refresh_LCD;
}

/*******************************************************************************
  Function:
    void Idle_Screen ( void )
  Remarks:
 * PResents strart up screen, initialises display for idle state
******************************************************************************/
void Idle_Screen(void)
{    
    int Target_Temp, Process_Error; /* used to draw the bar */
    char Plot_line_1[20];
    char Plot_line_2[20];
    char Plot_line_3[20];
    char Plot_line_4[20];
   
    if (wellerData.Process_Time > wellerData.Process_Time_Previous)
    {
      /* Remember set temp is off the main screen...*/
            Target_Temp = wellerData.Temp_Set; /* this is aldeady scaled... */
            /***************************************************/
            /*          PID STUFF                              */
            /***************************************************/
            /* all scaled by Temp_Scale */
            Process_Error = Target_Temp - wellerData.Temp_Meas;  
            wellerData.Differential = Process_Error - wellerData.Error_Prev;    
            wellerData.Integral += Process_Error;
            if (wellerData.Integral > Integral_Max)
                wellerData.Integral = Integral_Max;
            else if (wellerData.Integral < Integral_Min)
                wellerData.Integral = Integral_Min;
                        
            /* remember this is scaled by Temp_Scale */
            /* for low temps the PID values have P much too large which cuses overshoot*/
            /* rather than use two sets of PID on the user interfce*/
            /* this code reduces the "P" for temperatures below a threshold */
            if(Target_Temp < Low_Temp_For_PID)
            {
                wellerData.ut = (wellerData.PID_P * Low_Temp_P_Scale) * Process_Error + wellerData.PID_I* wellerData.Integral + wellerData.PID_D* Low_Temp_D_Scale * wellerData.Differential;
            }
            else  /* the temperature is high, let things go....*/
            {
                wellerData.ut = wellerData.PID_P * Process_Error + wellerData.PID_I* wellerData.Integral + wellerData.PID_D* wellerData.Differential;
            }
            wellerData.ut = wellerData.ut/Temp_Scale;
            if (wellerData.ut < ut_Min)
                wellerData.ut = ut_Min;
            else if (wellerData.ut > ut_Max)
                wellerData.ut = ut_Max;
            
        wellerData.Process_Time_Previous = wellerData.Process_Time; 
         /* store away previous temp for differential next time we come around */     
        wellerData.Prev_Temp_Meas = wellerData.Temp_Meas;
        wellerData.Error_Prev = Process_Error;
 
   }
    
    /* write idle screed (Solder BMP) to screen buffer */
    /* use this lock to stop changing display strings half way through */

    wellerData.UI_Display_Lockout = true;
    WriteBMP(ScreenBuff, SC_Idle, 0, 0, 128, 64);
    Update_Temp_Meas(wellerData.Temp_Meas/Temp_Scale);
    Update_Temp_Set(wellerData.Temp_Set/Temp_Scale);
    if (wellerData.Snooze_Flag)
        WriteBMP_Buf(ScreenBuff, Zap_Snooze, Zap_X, Zap_Y, Zap_On_Width, Zap_On_Height);
    else if (wellerData.Heater_On)
        WriteBMP_Buf(ScreenBuff, Zap_On, Zap_X, Zap_Y, Zap_On_Width, Zap_On_Height);
    else
        WriteBMP_Buf(ScreenBuff, Zap_Off, Zap_X, Zap_Y, Zap_Off_Width, Zap_Off_Height);
    wellerData.UI_Update_Display = true;

    /* Clear the lock */
    Refresh_LCD;
    wellerData.UI_Display_Lockout = false;
}

/*******************************************************************************
  Function:
    void WELLER_Initialize ( void )

  Remarks:
    See prototype in weller.h.
******************************************************************************/
void REFLOW_Initialize ( void )
{
    /* Place the App state machine in its initial state. */
    wellerData.state = WELLER_STATE_INIT;
    wellerData.UI_Timer = DRV_HANDLE_INVALID;
    wellerData.UI_Count = 3;
    wellerData.UI_Update_Counter = 0;
    wellerData.UI_Update_Display = true;
    wellerData.UI_Display_Lockout = false;
    wellerData.UI_Keypressed = false;
    wellerData.UI_Action = WELLER_STATE_START;
    wellerData.heartbeatTimer = DRV_HANDLE_INVALID;
    wellerData.heartbeatCount = 0;
    wellerData.heartbeatToggle = false;
    wellerData.MemoryBankSelected = 0;
    wellerData.Temp_Set = 0;        /* update in WELLER_EEPROM_Initialise */
    wellerData.Temp_Meas = 0;       /* update in WELLER_EEPROM_Initialise */
    wellerData.Prev_Temp_Meas = 0;  /* prev temp for differential */
    wellerData.Temp_Sensor_Offset = Temp_Offset_Default;     /* update in WELLER_EEPROM_Initialise */
    wellerData.Temp_Coeff = Tempco_Default;    /* update in WELLER_EEPROM_Initialise */
    wellerData.Snooze = Snooze_Default;       /* update in WELLER_EEPROM_Initialise */
    wellerData.Snooze_Flag = false;       /* update in WELLER_EEPROM_Initialise */
    wellerData.Snooze_Counter = wellerData.Snooze; 
    wellerData.Temp_Set_Backup = Temp_Default;
    wellerData.Heater_On = 0;       /* Output to heater is on */
    wellerData.UI_Fast_Count = Fast_Counter_Init;
    wellerData.UI_Slow_Count = Slow_Counter_Init;
    wellerData.UI_Speed = Speed_Init;
    wellerData.Revert_To_Idle_Counter = Revert_To_Idle;
    wellerData.PID_P = P_Default;
    wellerData.PID_I = I_Default;
    wellerData.PID_D = D_Default;
    wellerData.Temp_Preheat = Temp_Preheat_Default;
    wellerData.Temp_Reflow = Temp_Reflow_Default;
    wellerData.Process_Time = 0;   /* start this at zero! */
    wellerData.Process_Time_Previous = 0;   /* start this at zero! */
    wellerData.Done = true; /* flag to track process done or not */
    wellerData.Start_Settle_Done = false; /* start false */
    wellerData.Preheat_Done = false; /* start false */
    wellerData.Soak_Done = false; /* start false */
    wellerData.Reflow_Done = false; /* start false */
    wellerData.Start_Time_End = 0; /* initialise this out of good form */
    wellerData.Preheat_Time_End = 0; /* initialise this out of good form */
    wellerData.Reflow_Time_End = 0; /* initialise this out of good form */
    wellerData.Soak_Time_End = 0; /* initialise this out of good form */
    wellerData.ut = 0; /* start the PID PRocess output at zero - good form!*/
    wellerData.Error_Prev = 0; /* start the PID PRocess error output at zero - good form!*/
    
    /* set port E to drive logic high for encoder / buttons*/
    Drive_PortE_Out;
    EEPROM_Disable_Hold;
}


/******************************************************************************/
//  Function:
//    void WELLER_EEPROM_Initialize ( void )
//    
// AIm
//      - Set up EEPROM for operation
//     - Read in Init values stored in EEPROM
/*******************************************************************************/
void WELLER_EEPROM_Initialize(void)
{
    int Read_Temp; /* coeffs stored in an integer */
    
     /* this function clears write protect and any other necessary housekeeping*/
    EEPROM_Init();
                
    /* Read in stored Temp Set for WELLER app */
    HDWordReadSPI(((wellerData.MemoryBankSelected*ParmSet_Array_Size) + Temp_Offset), &wellerData.Temp_Set, 4 );
    if (wellerData.Temp_Set > Temp_Max)
        wellerData.Temp_Set = Temp_Default;
    else if (wellerData.Temp_Set < Temp_Min)
        wellerData.Temp_Set = Temp_Default;

    /* Read in stored Temp Offset for WELLER app */
    HDWordReadSPI(((wellerData.MemoryBankSelected*ParmSet_Array_Size) + Offset_Offset), &wellerData.Temp_Sensor_Offset, 4 );
    if (wellerData.Temp_Sensor_Offset > Temp_Offset_Max)
        wellerData.Temp_Sensor_Offset = Temp_Offset_Default;
    else if (wellerData.Temp_Sensor_Offset < Temp_Offset_Min)
        wellerData.Temp_Sensor_Offset = Temp_Offset_Default;

    /* Read in stored Temp Coefficient for WELLER app */
    HDWordReadSPI(((wellerData.MemoryBankSelected*ParmSet_Array_Size) + Tempco_Offset), &wellerData.Temp_Coeff, 4 );
    if (wellerData.Temp_Coeff > Tempco_Max)
        wellerData.Temp_Coeff = Tempco_Default;
    else if (wellerData.Temp_Coeff < Tempco_Min)
        wellerData.Temp_Coeff = Tempco_Default;
    
    /* Read in stored Temp Coefficient for WELLER app */
    HDWordReadSPI(((wellerData.MemoryBankSelected*ParmSet_Array_Size) + Snooze_Time_Offset), &wellerData.Snooze, 4 );
    if (wellerData.Snooze > Snooze_Max)
        wellerData.Snooze = Snooze_Default;
    else if (wellerData.Snooze < Snooze_Min)
        wellerData.Snooze = Snooze_Default;

    /* Read in stored PID Coefficient for REFLOW app */
    HDWordReadSPI(((wellerData.MemoryBankSelected*ParmSet_Array_Size) + P_Offset), &Read_Temp, 4 );
    wellerData.PID_P = (float)Read_Temp/PID_SCALING;
    if (wellerData.PID_P > P_Max)
        wellerData.PID_P = P_Default;
    else if (wellerData.PID_P < P_Min)
        wellerData.PID_P = P_Default;
    
    /* Read in stored PID Coefficient for REFLOW app */
    HDWordReadSPI(((wellerData.MemoryBankSelected*ParmSet_Array_Size) + I_Offset), &Read_Temp, 4 );
    wellerData.PID_I = (float)Read_Temp/PID_SCALING;
    if (wellerData.PID_I > I_Max)
        wellerData.PID_I = I_Default;
    else if (wellerData.PID_I < I_Min)
        wellerData.PID_I = I_Default;
    
    /* Read in stored PID Coefficient for REFLOW app */
    HDWordReadSPI(((wellerData.MemoryBankSelected*ParmSet_Array_Size) + D_Offset), &Read_Temp, 4 );
    wellerData.PID_D = (float)Read_Temp/PID_SCALING;
    if (wellerData.PID_D > D_Max)
        wellerData.PID_D = D_Default;
    else if (wellerData.PID_D < D_Min)
        wellerData.PID_D = D_Default;

    /* Read in stored Preheat Temp */
    HDWordReadSPI(((wellerData.MemoryBankSelected*ParmSet_Array_Size) + Preheat_Offset), &wellerData.Temp_Preheat, 4 );
    if (wellerData.Temp_Preheat > Temp_Preheat_Max)
        wellerData.Temp_Preheat = Temp_Preheat_Default;
    else if (wellerData.Temp_Preheat < Temp_Preheat_Min)
        wellerData.Temp_Preheat = Temp_Preheat_Default;
    
    /* Read in stored Reflow Temp */
    HDWordReadSPI(((wellerData.MemoryBankSelected*ParmSet_Array_Size) + Reflow_Offset), &wellerData.Temp_Reflow, 4 );
    if (wellerData.Temp_Reflow > Temp_Reflow_Max)
        wellerData.Temp_Reflow = Temp_Reflow_Default;
    else if (wellerData.Temp_Reflow < Temp_Reflow_Min)
        wellerData.Temp_Reflow = Temp_Reflow_Default;
    
    wellerData.Snooze_Counter = wellerData.Snooze; 
    wellerData.Temp_Set_Backup = wellerData.Temp_Set;
}


/******************************************************************************/
//  Function:
//    void WELLER_Done ( void )
//    
// AIm
//     - Display DONE for a second - user feedback
/******************************************************************************/
void WELLER_Done( void )
{
    char line[16];
    
    WriteBMP(ScreenBuff, YES, 0, 0, 128, 64);
    sprintf(line, "DONE");
    GLCD_WriteString_16x11_buf(ScreenBuff,&(line[0]),Saved_X, Saved_Y);
    Refresh_LCD;
    HDWordWriteSPI(((wellerData.MemoryBankSelected*ParmSet_Array_Size) + Temp_Offset), wellerData.Temp_Set);
    HDWordWriteSPI(((wellerData.MemoryBankSelected*ParmSet_Array_Size) + Offset_Offset), wellerData.Temp_Sensor_Offset);
    HDWordWriteSPI(((wellerData.MemoryBankSelected*ParmSet_Array_Size) + Tempco_Offset), wellerData.Temp_Coeff);
    HDWordWriteSPI(((wellerData.MemoryBankSelected*ParmSet_Array_Size) + Snooze_Time_Offset), wellerData.Snooze);
    HDWordWriteSPI(((wellerData.MemoryBankSelected*ParmSet_Array_Size) + P_Offset), (int) (wellerData.PID_P * PID_SCALING));
    HDWordWriteSPI(((wellerData.MemoryBankSelected*ParmSet_Array_Size) + I_Offset), (int) (wellerData.PID_I * PID_SCALING));
    HDWordWriteSPI(((wellerData.MemoryBankSelected*ParmSet_Array_Size) + D_Offset), (int) (wellerData.PID_D * PID_SCALING));
    HDWordWriteSPI(((wellerData.MemoryBankSelected*ParmSet_Array_Size) + Preheat_Offset), wellerData.Temp_Preheat);
    HDWordWriteSPI(((wellerData.MemoryBankSelected*ParmSet_Array_Size) + Reflow_Offset), wellerData.Temp_Reflow);
    DelayMs(1000);
}

/******************************************************************************/
//  Function:
//    void WELLER_EEPROM_Plot ( void )
// AIm
//     - Called throughout the process to plot the temp profile and run reflow 
/*******************************************************************************/
void WELLER_Plot(void)
{
    int Delta_Time, t, y;
    int Target_Temp;
    float Process_Error;    /* as it says... */
    float Differential;     /* as it says... */
    float Integral;         /* as it says... */
    char Plot_line_1[20];
    char Plot_line_2[20];
    char Plot_line_3[20];
    char Plot_line_4[20];


    if (wellerData.Process_Time > wellerData.Process_Time_Previous)
    {
        if (wellerData.Process_Time < (wellerData.Start_Time_End + 3))
        {
            /* Draw the background screen */
            WriteBMP(ScreenBuff, TEMP_GRAPH_DISPLAY, 0, 0, 128, 64);
        }
        
        /* in this case we have settled, and need to preheat*/
        if ((wellerData.Start_Settle_Done == true) && (wellerData.Preheat_Done == false))
            {
            /* how long into */
            Delta_Time = wellerData.Process_Time - wellerData.Start_Time_End;
            Target_Temp = Ambient*Temp_Scale + (Delta_Time * (wellerData.Temp_Preheat*Temp_Scale - Ambient*Temp_Scale))/Preheat_Time;
            /* Capture the time - this will be updated last when we exit this state */
            wellerData.Preheat_Time_End = wellerData.Process_Time;
            /* we are done at the end of PReheat Time*/
            if (Delta_Time > Preheat_Time)
                {
                wellerData.Preheat_Done = true;
                /* Capture the temperature at the end of preheat in Temp_Preheat_Old*/
                wellerData.Temp_Preheat_Old = wellerData.Temp_Meas;
                }
            /***************************************************/
            /*          PID STUFF                              */
            /***************************************************/
            /* error times  Temp_Scale */
            Process_Error = Target_Temp - wellerData.Temp_Meas;
            wellerData.Differential = Process_Error - wellerData.Error_Prev;    
            wellerData.Integral += Process_Error;
            if (wellerData.Integral > Integral_Max)
                wellerData.Integral = Integral_Max;
            else if (wellerData.Integral < Integral_Min)
                wellerData.Integral = Integral_Min;
            
            /* remember this is scaled by Temp_Scale */
            wellerData.ut = wellerData.PID_P * Process_Error + wellerData.PID_I* wellerData.Integral + wellerData.PID_D* wellerData.Differential;
            wellerData.ut = wellerData.ut/Temp_Scale;
            if (wellerData.ut < ut_Min)
                wellerData.ut = ut_Min;
            else if (wellerData.ut > ut_Max)
                wellerData.ut = ut_Max;
            }
        /* in this case we have preheated, and need to soak*/
        else if ((wellerData.Start_Settle_Done == true) && (wellerData.Preheat_Done == true) && (wellerData.Soak_Done == false))
            {
            /* how long into */
            Delta_Time = wellerData.Process_Time - wellerData.Preheat_Time_End;
            /* Remember the soak temperature is EQUAL to the preheat temperature... This is a constant*/
            Target_Temp = wellerData.Temp_Preheat*Temp_Scale;
            /* Capture the time - this will be updated last when we exit this state */
            wellerData.Soak_Time_End = wellerData.Process_Time;
            if (Delta_Time > Soak_Time)
                {
                wellerData.Soak_Done = true;
                /* Capture the temperature at the end of Soak in Temp_Preheat_Old*/
                wellerData.Temp_Preheat_Old = wellerData.Temp_Meas;
                }
            /***************************************************/
            /*          PID STUFF                              */
            /***************************************************/
            if (Delta_Time <= 1)
            {
                wellerData.Error_Prev = 0;
                wellerData.Integral = 0;
            }
            /* error times  Temp_Scale */
            Process_Error = Target_Temp - wellerData.Temp_Meas;
            wellerData.Differential = Process_Error - wellerData.Error_Prev;    
            wellerData.Integral += Process_Error;
            if (wellerData.Integral > Integral_Max)
                wellerData.Integral = Integral_Max;
            else if (wellerData.Integral < Integral_Min)
                wellerData.Integral = Integral_Min;
                        
            /* remember this is scaled by Temp_Scale */
            wellerData.ut = wellerData.PID_P * Process_Error + wellerData.PID_I* wellerData.Integral + wellerData.PID_D* wellerData.Differential;
            wellerData.ut = wellerData.ut/Temp_Scale;
            if (wellerData.ut < ut_Min)
                wellerData.ut = ut_Min;
            else if (wellerData.ut > ut_Max)
                wellerData.ut = ut_Max;
            }
        /* in this case we have soaked, and need to reflow*/
        else if ((wellerData.Start_Settle_Done == true) && (wellerData.Preheat_Done == true) && (wellerData.Soak_Done == true) && (wellerData.Reflow_Done == false))
            {
            /* how long into reflow*/
            Delta_Time = wellerData.Process_Time - wellerData.Soak_Time_End;

            if (Delta_Time <= Reflow_Time)
            {
                /* Remember the reflow temperature is assumed to be different and higher than the preheat temperature... This is a constant*/
                Target_Temp = wellerData.Temp_Preheat*Temp_Scale + (Delta_Time * (wellerData.Temp_Reflow*Temp_Scale - wellerData.Temp_Preheat*Temp_Scale))/Reflow_Time;
            }
            else if (Delta_Time <= (Reflow_Time + Reflow_Hold))
            {
                /* sets reflow temp target */
                Target_Temp = (wellerData.Temp_Reflow)*Temp_Scale;
            }
                
            
            /* disable the temp ramp... aboove code is for reference only */
            /* drive hard to the reflow temp */
            Target_Temp = wellerData.Temp_Reflow*Temp_Scale;
            /* Capture the time - this will be updated last when we exit this state */
            wellerData.Reflow_Time_End = wellerData.Process_Time;
            if ((wellerData.Temp_Meas >= Target_Temp)|(Delta_Time >= (Reflow_Time + Reflow_Hold)))
                {
                wellerData.Reflow_Done = true;
                /* Capture the temperature at the end of Soak in Temp_Preheat_Old*/
                wellerData.Temp_Preheat_Old = wellerData.Temp_Meas;
                }
            /***************************************************/
            /*          PID STUFF                              */
            /***************************************************/
            if (Delta_Time <= 1)
            {
                wellerData.Error_Prev = 0;
                wellerData.Integral = 0;
            }
            /* error times  Temp_Scale */
//            Process_Error = Target_Temp - wellerData.Temp_Meas;
//            wellerData.Differential = Process_Error - wellerData.Error_Prev;    
//            wellerData.Integral += Process_Error;
//            if (wellerData.Integral > Integral_Max)
//                wellerData.Integral = Integral_Max;
//            else if (wellerData.Integral < Integral_Min)
//                wellerData.Integral = Integral_Min;
            
            /* remember this is scaled by Temp_Scale */
//            wellerData.ut = wellerData.PID_P * Process_Error + wellerData.PID_I* wellerData.Integral + wellerData.PID_D* wellerData.Differential;
//            wellerData.ut = wellerData.ut/Temp_Scale;
//            if (wellerData.ut < ut_Min)
//                wellerData.ut = ut_Min;
//            else if (wellerData.ut > ut_Max)
//                wellerData.ut = ut_Max;

            /****************************************************************************************/
            /* OK, we don't reallt want a PID for this part - we want the heater on flat out to get */
            /* reflow done ASAP                                                                     */
            /****************************************************************************************/
            wellerData.ut = ut_Max;
            }
        /* now let things cool */
        else if((wellerData.Start_Settle_Done == true) && (wellerData.Preheat_Done == true) && (wellerData.Soak_Done == true) && (wellerData.Reflow_Done == true) && (wellerData.Done == false))
        {
            /* how long into */
            Delta_Time = wellerData.Process_Time - wellerData.Reflow_Time_End;
            /* Remember the soak temperature is EQUAL to the preheat temperature... This is a constant*/
            Target_Temp = Temp_Snooze;
            /* Capture the time - this will be updated last when we exit this state */
            if (Delta_Time > Cool_Time)
            {
                wellerData.Done = true;
            }
            wellerData.Heater_On = 0;
            wellerData.ut = 0;
        }
        /* Now we are done*/
        else 
            {
            wellerData.Done = true;
            wellerData.Heater_On = 0;
            wellerData.ut = 0;
            }

        /* SET UP THE STRINGS */
        sprintf(Plot_line_1, "Temp:%3d", wellerData.Temp_Meas/Temp_Scale);
        sprintf(Plot_line_2, "Time:%3d", (wellerData.Process_Time - wellerData.Start_Time_End));
        sprintf(Plot_line_3, "Target:%3d", Target_Temp/Temp_Scale);
//        sprintf(Plot_line_4, "ut:%.1f", wellerData.ut);
        /* Write them first, then the graph over the top*/
        GLCD_WriteString_8x5_buf(ScreenBuff,&(Plot_line_1[0]),Plot_L1x, Plot_L1y);
        GLCD_WriteString_8x5_buf(ScreenBuff,&(Plot_line_2[0]),Plot_L2x, Plot_L2y);
        GLCD_WriteString_8x5_buf(ScreenBuff,&(Plot_line_3[0]),Plot_L3x, Plot_L3y);
//        GLCD_WriteString_8x5_buf(ScreenBuff,&(Plot_line_4[0]),Plot_L4x, Plot_L4y);

        /* PLOT HEATER SYMBOL*/
        if (wellerData.Snooze_Flag)
            WriteBMP_Buf(ScreenBuff, Zap_Snooze, Zap_X_Reflow, Zap_Y_Reflow, Zap_On_Width, Zap_On_Height);
        else if (wellerData.Heater_On)
            WriteBMP_Buf(ScreenBuff, Zap_On, Zap_X_Reflow, Zap_Y_Reflow, Zap_On_Width, Zap_On_Height);
        else
            WriteBMP_Buf(ScreenBuff, Zap_Off, Zap_X_Reflow, Zap_Y_Reflow, Zap_Off_Width, Zap_Off_Height);

        
        /* plot up the target */
        for (t=0; t< (Preheat_Time + Soak_Time + Reflow_Time + Cool_Time); t++)
        {
            if (t < Preheat_Time)
            {
                y = (Ambient*Temp_Scale + ((t * (wellerData.Temp_Preheat*Temp_Scale - Ambient*Temp_Scale))/Preheat_Time))/Temp_Scale;
                GLCD_SetPixelBuf(ScreenBuff, Display_Origin_X + (t/Display_Scale_X) , Display_Origin_Y - (y/Display_Scale_Y), 0);
            }
            else if (t < (Preheat_Time + Soak_Time))
            {
                y = (wellerData.Temp_Preheat);
                GLCD_SetPixelBuf(ScreenBuff, Display_Origin_X + (t/Display_Scale_X) , Display_Origin_Y - (y/Display_Scale_Y), 0);
            }
            else if (t < (Preheat_Time + Soak_Time + Reflow_Time))
            {
                y = (wellerData.Temp_Preheat*Temp_Scale + (((t - Preheat_Time - Soak_Time) * (wellerData.Temp_Reflow*Temp_Scale - wellerData.Temp_Preheat*Temp_Scale))/Reflow_Time))/Temp_Scale;
                GLCD_SetPixelBuf(ScreenBuff, Display_Origin_X + (t/Display_Scale_X) , Display_Origin_Y - (y/Display_Scale_Y), 0);
            }
            else if (t < (Preheat_Time + Soak_Time + Reflow_Time + Cool_Time))
            {
                y = (wellerData.Temp_Reflow*Temp_Scale + (((t - Preheat_Time - Soak_Time - Reflow_Time) * (wellerData.Temp_Preheat*Temp_Scale - wellerData.Temp_Reflow*Temp_Scale))/Cool_Time))/Temp_Scale;
                GLCD_SetPixelBuf(ScreenBuff, Display_Origin_X + (t/Display_Scale_X) , Display_Origin_Y - (y/Display_Scale_Y), 0);
            }
        }
        /* Plot Actual */
        GLCD_SetPixelBuf(ScreenBuff, Display_Origin_X + ((wellerData.Process_Time - wellerData.Start_Time_End)/Display_Scale_X) , Display_Origin_Y - (wellerData.Temp_Meas/Temp_Scale/Display_Scale_Y), 0);
        wellerData.UI_Update_Display = true;
        /* store away previous temp for differential next time we come around */     
        wellerData.Prev_Temp_Meas = wellerData.Temp_Meas;
        wellerData.Error_Prev = Process_Error;
        /* store away previous temp for differential next time we come around */     
        wellerData.Process_Time_Previous = wellerData.Process_Time; 
        Refresh_LCD;
    }
}

/******************************************************************************/
//  Function:
//    void WELLER_EEPROM_Start ( void )
// AIm
//     - run the process of setting up for reflow process
// Continues to wait until measured temp is less that the maximum start temp
// Temp_Max_Start defined in Reflow.h
// Notionally well below 100C, allowing for a reasonable ramp up
/*******************************************************************************/
void WELLER_Start(void)
{
    int temporary;
    char Start_line_1[20];
    char Start_line_2[20];
    char Start_line_3[20];
    char Start_line_4[20];

    /* clear the screen */
    GLCD_ClearScreen_buff(ScreenBuff);
    /* SET UP THE STRINGS */
//    sprintf(Start_line_4, " Cooldown Phase");
    sprintf(Start_line_4, " Time: %d", wellerData.Process_Time);
    sprintf(Start_line_1, " Please Wait...");
    sprintf(Start_line_2, "Max Temp:%d",Temp_Start_Max);
    sprintf(Start_line_3, "Curr Temp:%d", (wellerData.Temp_Meas/Temp_Scale));

    /* Wait until temperature is below a minimum to allow the process to start */
    /* check if things are ready to proceed */
    if ((wellerData.Temp_Meas/Temp_Scale) < Temp_Start_Max)
    {
        wellerData.Start_Settle_Done = true;
        /* Capture the time at end of cooldown */
        DelayMs(Display_Start_Screen_ms);
    }
    wellerData.Start_Time_End = wellerData.Process_Time;
    /* Store temperature at end of prep in Temp_Preheat_Old*/
    wellerData.Temp_Preheat_Old = wellerData.Temp_Meas;
 
    
    /* Start with capturing errors*/
    if ((wellerData.Start_Settle_Done == false) && (wellerData.Process_Time > (Start_Settle_Timeout)))
    {
        sprintf(Start_line_1, "ERROR TIMEOUT");
        wellerData.Start_Settle_Done = true;
        DelayMs(Display_Start_Screen_ms);
    }

    GLCD_WriteString_12x7_buf(ScreenBuff,&(Start_line_1[0]),Temoco_L1x, Start_L2y);
    GLCD_WriteString_12x7_buf(ScreenBuff,&(Start_line_2[0]),Temoco_L1x, Start_L3y);
    GLCD_WriteString_12x7_buf(ScreenBuff,&(Start_line_3[0]),Temoco_L1x, Start_L4y);
    GLCD_WriteString_12x7_buf(ScreenBuff,&(Start_line_4[0]),Temoco_L1x, Start_L1y);
    Refresh_LCD;

    if (wellerData.Start_Settle_Done == true)
    {
        /* Draw the background screen in prep for plotting in realtime*/
        WriteBMP(ScreenBuff, TEMP_GRAPH_DISPLAY, 0, 0, 128, 64);
//        wellerData.Process_Time = wellerData.Process_Time_Previous;
    }
    
}


/******************************************************************************/
//  Function:
//    void WELLER_EEPROM_Save ( void )
// AIm
//     - Save the data set to EEPROM
/*******************************************************************************/
void WELLER_EEPROM_Save( void )
{
    char line[16];
    
    WriteBMP(ScreenBuff, YES, 0, 0, 128, 64);
    sprintf(line, "Saved");
    GLCD_WriteString_16x11_buf(ScreenBuff,&(line[0]),Saved_X, Saved_Y);
    Refresh_LCD;
    HDWordWriteSPI(((wellerData.MemoryBankSelected*ParmSet_Array_Size) + Temp_Offset), wellerData.Temp_Set);
    HDWordWriteSPI(((wellerData.MemoryBankSelected*ParmSet_Array_Size) + Offset_Offset), wellerData.Temp_Sensor_Offset);
    HDWordWriteSPI(((wellerData.MemoryBankSelected*ParmSet_Array_Size) + Tempco_Offset), wellerData.Temp_Coeff);
    HDWordWriteSPI(((wellerData.MemoryBankSelected*ParmSet_Array_Size) + Snooze_Time_Offset), wellerData.Snooze);
    HDWordWriteSPI(((wellerData.MemoryBankSelected*ParmSet_Array_Size) + P_Offset), (int) (wellerData.PID_P * PID_SCALING));
    HDWordWriteSPI(((wellerData.MemoryBankSelected*ParmSet_Array_Size) + I_Offset), (int) (wellerData.PID_I * PID_SCALING));
    HDWordWriteSPI(((wellerData.MemoryBankSelected*ParmSet_Array_Size) + D_Offset), (int) (wellerData.PID_D * PID_SCALING));
    HDWordWriteSPI(((wellerData.MemoryBankSelected*ParmSet_Array_Size) + Preheat_Offset), wellerData.Temp_Preheat);
    HDWordWriteSPI(((wellerData.MemoryBankSelected*ParmSet_Array_Size) + Reflow_Offset), wellerData.Temp_Reflow);
    DelayMs(1000);
    WriteBMP(ScreenBuff, Solder, 0, 0, 128, 64);
    Update_Temp_Meas(wellerData.Temp_Meas/Temp_Scale);
    Update_Temp_Set(wellerData.Temp_Set/Temp_Scale);
    wellerData.UI_Update_Display = true;
    Refresh_LCD;
}

/******************************************************************************/
//  Function:
//    void WELLER_CHANGE_Setpoints ( void )
//    
// AIm
//     - Save the soak and reflow temperatures
/*******************************************************************************/
void WELLER_CHANGE_Preheat( void )
{
    char SP_line_1[20];
    char SP_line_2[20];
    char SP_line_3[20];
    char SP_line_4[20];

    /* clear the screen */
    GLCD_ClearScreen_buff(ScreenBuff);
    /* SET UP THE STRINGS */
    sprintf(SP_line_1, "Set Preheat Temp");
    sprintf(SP_line_2, "Old Value: %d C", (wellerData.Temp_Preheat_Old));
    sprintf(SP_line_3, "                ");
    sprintf(SP_line_4, "Preheat:   %d C", (wellerData.Temp_Preheat));
    GLCD_WriteString_12x7_buf(ScreenBuff,&(SP_line_1[0]),Temoco_L1x, Temoco_L1y);
    GLCD_WriteString_12x7_buf(ScreenBuff,&(SP_line_2[0]),Temoco_L1x, Temoco_L2y);
    GLCD_WriteString_12x7_buf(ScreenBuff,&(SP_line_3[0]),Temoco_L1x, Temoco_L3y);
    GLCD_WriteString_12x7_buf(ScreenBuff,&(SP_line_4[0]),Temoco_L1x, Temoco_L4y);
    Refresh_LCD;
}

/******************************************************************************/
//  Function:
//  void WELLER_Seetpoint
//    
// AIm
//     - Check the user is serious...
/*******************************************************************************/
void WELLER_CHANGE_Setpoints( void )
{
    char SP_line_1[20];
    char SP_line_2[20];
    char SP_line_3[20];
    char SP_line_4[20];

    /* clear the screen */
    GLCD_ClearScreen_buff(ScreenBuff);
    /* SET UP THE STRINGS */
    sprintf(SP_line_1, " Are you sure?  ");
    if(wellerData.UI_Action == WELLER_ACTION_NO)
        sprintf(SP_line_2, "      No        ");
    else
        sprintf(SP_line_2, "     Yes        ");
    sprintf(SP_line_3, "                ");
    /* step 1 - intro and graphic */
    sprintf(SP_line_4, "CHANGE:         ");
    GLCD_WriteString_12x7_buf(ScreenBuff,&(SP_line_1[0]),Temoco_L1x, Temoco_L1y);
    GLCD_WriteString_12x7_buf(ScreenBuff,&(SP_line_4[0]),Temoco_L1x, Temoco_L4y);
    WriteBMP_Buf(ScreenBuff, Choose_Offset, Q4_Graphic_x, Q4_Graphic_y, 64, 32);
    Refresh_LCD;
    /* step 2 - make the user check themselves */
    GLCD_WriteString_12x7_buf(ScreenBuff,&(SP_line_2[0]),Temoco_L1x, Temoco_L2y);
    Refresh_LCD;
}


/******************************************************************************/
//  Function:
//    void WELLER_CHANGE_Reflow ( void )
//    
// AIm
//     - Save the soak and reflow temperatures
/*******************************************************************************/
void WELLER_CHANGE_Reflow( void )
{
    char SP_line_1[20];
    char SP_line_2[20];
    char SP_line_3[20];
    char SP_line_4[20];

    /* clear the screen */
    GLCD_ClearScreen_buff(ScreenBuff);
    /* SET UP THE STRINGS */
    sprintf(SP_line_1, "Set Reflow Temp");
    sprintf(SP_line_2, "Old Value: %d C", (wellerData.Temp_Reflow_Old));
    sprintf(SP_line_3, "                ");
    sprintf(SP_line_4, "Reflow:   %d C", (wellerData.Temp_Reflow));
    GLCD_WriteString_12x7_buf(ScreenBuff,&(SP_line_1[0]),Temoco_L1x, Temoco_L1y);
    GLCD_WriteString_12x7_buf(ScreenBuff,&(SP_line_2[0]),Temoco_L1x, Temoco_L2y);
    GLCD_WriteString_12x7_buf(ScreenBuff,&(SP_line_3[0]),Temoco_L1x, Temoco_L3y);
    GLCD_WriteString_12x7_buf(ScreenBuff,&(SP_line_4[0]),Temoco_L1x, Temoco_L4y);
    Refresh_LCD;
}


/******************************************************************************/
//  Function:
//    void WELLER_CHANGE_Sensoor_Tempco ( void )
//    
// AIm
//     - Save the data set to EEPROM
/*******************************************************************************/
void WELLER_CHANGE_Sensor_Tempco( void )
{
    char TC_line_1[20];
    char TC_line_2[20];
    char TC_line_3[20];
    char TC_line_4[20];
    int Old_Tempco;

    /* clear the screen */
    GLCD_ClearScreen_buff(ScreenBuff);
    /* SET UP THE STRINGS */
    sprintf(TC_line_1, " CHANGE TEMPCO  ");
    sprintf(TC_line_2, "Old Value: %2.3f", ((float)wellerData.Temp_Coeff_Old /Tempco_Scale));
    sprintf(TC_line_3, "                ");
    sprintf(TC_line_4, "Tempco: %2.3f   ", (float)(wellerData.Temp_Coeff)/Tempco_Scale);
    GLCD_WriteString_12x7_buf(ScreenBuff,&(TC_line_1[0]),Temoco_L1x, Temoco_L1y);
    GLCD_WriteString_12x7_buf(ScreenBuff,&(TC_line_2[0]),Temoco_L1x, Temoco_L2y);
    GLCD_WriteString_12x7_buf(ScreenBuff,&(TC_line_3[0]),Temoco_L1x, Temoco_L3y);
    GLCD_WriteString_12x7_buf(ScreenBuff,&(TC_line_4[0]),Temoco_L1x, Temoco_L4y);
    Refresh_LCD;
}


/******************************************************************************/
//  Function:
//    void WELLER_Sensoor_Offset ( void )
//    
// AIm
//     - Check the user is serious...
/*******************************************************************************/
void WELLER_Sensor_Offset( void )
{
    char TC_line_1[20];
    char TC_line_2[20];
    char TC_line_3[20];
    char TC_line_4[20];

    /* clear the screen */
    GLCD_ClearScreen_buff(ScreenBuff);
    /* SET UP THE STRINGS */
    sprintf(TC_line_1, " Are you sure?  ");
    if(wellerData.UI_Action == WELLER_ACTION_NO)
        sprintf(TC_line_2, "      No        ");
    else
        sprintf(TC_line_2, "     Yes        ");
    sprintf(TC_line_3, "                ");
    /* step 1 - intro and graphic */
    sprintf(TC_line_4, "CHANGE:         ");
    GLCD_WriteString_12x7_buf(ScreenBuff,&(TC_line_1[0]),Temoco_L1x, Temoco_L1y);
    GLCD_WriteString_12x7_buf(ScreenBuff,&(TC_line_4[0]),Temoco_L1x, Temoco_L4y);
    WriteBMP_Buf(ScreenBuff, Choose_Tempco, Q4_Graphic_x, Q4_Graphic_y, 63, 32);
    Refresh_LCD;
    /* step 2 - make the user check themselves */
    GLCD_WriteString_12x7_buf(ScreenBuff,&(TC_line_2[0]),Temoco_L1x, Temoco_L2y);
    Refresh_LCD;
}


/******************************************************************************/
//  Function:
//    void PID Coefficients ( void )
//    
// AIm
//     - Entry and update of PID Coefficients
/*******************************************************************************/
void WELLER_PID( void )
{
    char PID_line_1[20];
    char PID_line_2[20];
    char PID_line_3[20];
    char PID_line_4[20];

    /* clear the screen */
    GLCD_ClearScreen_buff(ScreenBuff);
    /* SET UP THE STRINGS */
    sprintf(PID_line_1, " Are you sure?  ");
    if(wellerData.UI_Action == WELLER_ACTION_NO)
        sprintf(PID_line_2, "      No        ");
    else
        sprintf(PID_line_2, "     Yes        ");
    sprintf(PID_line_3, "                ");
    /* step 1 - intro and graphic */
    sprintf(PID_line_4, "CHANGE: PID Values");
    GLCD_WriteString_12x7_buf(ScreenBuff,&(PID_line_1[0]),Temoco_L1x, Temoco_L1y);
    GLCD_WriteString_12x7_buf(ScreenBuff,&(PID_line_4[0]),Temoco_L1x, Temoco_L4y);
    WriteBMP_Buf(ScreenBuff, Choose_PID, Q4_Graphic_x, Q4_Graphic_y, 64, 32);
    Refresh_LCD;
    /* step 2 - make the user check themselves */
    GLCD_WriteString_12x7_buf(ScreenBuff,&(PID_line_2[0]),Temoco_L1x, Temoco_L2y);
    Refresh_LCD;
}

/******************************************************************************/
//  Function:
//    void PID Coefficients  >>> P <<< ( void )
//    
// AIm
//     - Entry and update of PID P Coefficient
/*******************************************************************************/
void WELLER_PID_P( void )
{
    char PID_line_1[20];
    char PID_line_2[20];
    char PID_line_3[20];
    char PID_line_4[20];

    /* clear the screen */
    GLCD_ClearScreen_buff(ScreenBuff);
    /* SET UP THE STRINGS */
    sprintf(PID_line_1, "Old P: %.0f", wellerData.PID_P_Old);
    sprintf(PID_line_2, "New P: %.0f", wellerData.PID_P);
    sprintf(PID_line_3, "                ");
    /* step 1 - intro and graphic */
    sprintf(PID_line_4, "CHANGE: PID Values");
    GLCD_WriteString_12x7_buf(ScreenBuff,&(PID_line_1[0]),Temoco_L1x, Temoco_L1y);
    GLCD_WriteString_12x7_buf(ScreenBuff,&(PID_line_2[0]),Temoco_L1x, Temoco_L2y);
    GLCD_WriteString_12x7_buf(ScreenBuff,&(PID_line_4[0]),Temoco_L1x, Temoco_L4y);
    WriteBMP_Buf(ScreenBuff, Choose_PID, Q4_Graphic_x, Q4_Graphic_y, 64, 32);
    Refresh_LCD;
    /* step 2 - make the user check themselves */
    GLCD_WriteString_12x7_buf(ScreenBuff,&(PID_line_2[0]),Temoco_L1x, Temoco_L2y);
    Refresh_LCD;
}

/******************************************************************************/
//  Function:
//    void PID Coefficients  >>> I <<< ( void )
//    
// AIm
//     - Entry and update of PID I Coefficient
/*******************************************************************************/
void WELLER_PID_I( void )
{
    char PID_line_1[20];
    char PID_line_2[20];
    char PID_line_3[20];
    char PID_line_4[20];

    /* clear the screen */
    GLCD_ClearScreen_buff(ScreenBuff);
    /* SET UP THE STRINGS */
    sprintf(PID_line_1, "Old I: %.1f", wellerData.PID_I_Old);
    sprintf(PID_line_2, "New I: %.1f", wellerData.PID_I);
    sprintf(PID_line_3, "                ");
    /* step 1 - intro and graphic */
    sprintf(PID_line_4, "CHANGE: PID Values");
    GLCD_WriteString_12x7_buf(ScreenBuff,&(PID_line_1[0]),Temoco_L1x, Temoco_L1y);
    GLCD_WriteString_12x7_buf(ScreenBuff,&(PID_line_2[0]),Temoco_L1x, Temoco_L2y);
    GLCD_WriteString_12x7_buf(ScreenBuff,&(PID_line_4[0]),Temoco_L1x, Temoco_L4y);
    WriteBMP_Buf(ScreenBuff, Choose_PID, Q4_Graphic_x, Q4_Graphic_y, 64, 32);
    Refresh_LCD;
    /* step 2 - make the user check themselves */
    GLCD_WriteString_12x7_buf(ScreenBuff,&(PID_line_2[0]),Temoco_L1x, Temoco_L2y);
    Refresh_LCD;
}

/******************************************************************************/
//  Function:
//    void PID Coefficients  >>> D <<< ( void )
//    
// AIm
//     - Entry and update of PID D Coefficient
/*******************************************************************************/
void WELLER_PID_D( void )
{
    char PID_line_1[20];
    char PID_line_2[20];
    char PID_line_3[20];
    char PID_line_4[20];

    /* clear the screen */
    GLCD_ClearScreen_buff(ScreenBuff);
    /* SET UP THE STRINGS */
    sprintf(PID_line_1, "Old D: %.0f", wellerData.PID_D_Old);
    sprintf(PID_line_2, "New D: %.0f", wellerData.PID_D);
    sprintf(PID_line_3, "                ");
    /* step 1 - intro and graphic */
    sprintf(PID_line_4, "CHANGE: PID Values");
    GLCD_WriteString_12x7_buf(ScreenBuff,&(PID_line_1[0]),Temoco_L1x, Temoco_L1y);
    GLCD_WriteString_12x7_buf(ScreenBuff,&(PID_line_2[0]),Temoco_L1x, Temoco_L2y);
    GLCD_WriteString_12x7_buf(ScreenBuff,&(PID_line_4[0]),Temoco_L1x, Temoco_L4y);
    WriteBMP_Buf(ScreenBuff, Choose_PID, Q4_Graphic_x, Q4_Graphic_y, 64, 32);
    Refresh_LCD;
    /* step 2 - make the user check themselves */
    GLCD_WriteString_12x7_buf(ScreenBuff,&(PID_line_2[0]),Temoco_L1x, Temoco_L2y);
    Refresh_LCD;
}

/******************************************************************************/
//  Function:
//    void WELLER_CHANGE_Sensoor_Offset ( void )
//    
// AIm
//     - Update Offset Data
/*******************************************************************************/
void WELLER_CHANGE_Sensor_Offset( void )
{
    char TC_line_1[20];
    char TC_line_2[20];
    char TC_line_3[20];
    char TC_line_4[20];

    /* clear the screen */
    GLCD_ClearScreen_buff(ScreenBuff);
    /* SET UP THE STRINGS */
    sprintf(TC_line_1, " CHANGE OFFSET  ");
    sprintf(TC_line_2, "Old Value: %d", (wellerData.Temp_Sensor_Offset_Old /Temp_Scale));
    sprintf(TC_line_3, "                ");
    sprintf(TC_line_4, "Offset: %d C", (wellerData.Temp_Sensor_Offset/Temp_Scale));
    GLCD_WriteString_12x7_buf(ScreenBuff,&(TC_line_1[0]),Temoco_L1x, Temoco_L1y);
    GLCD_WriteString_12x7_buf(ScreenBuff,&(TC_line_2[0]),Temoco_L1x, Temoco_L2y);
    GLCD_WriteString_12x7_buf(ScreenBuff,&(TC_line_3[0]),Temoco_L1x, Temoco_L3y);
    GLCD_WriteString_12x7_buf(ScreenBuff,&(TC_line_4[0]),Temoco_L1x, Temoco_L4y);
    Refresh_LCD;
}


/******************************************************************************/
//  Function:
//    void WELLER_Sensoor_Tempco ( void )
//    
// AIm
//     - Save the data set to EEPROM
/*******************************************************************************/
void WELLER_Sensor_Tempco( void )
{
    char TC_line_1[20];
    char TC_line_2[20];
    char TC_line_3[20];
    char TC_line_4[20];
    int Old_Tempco;

    /* clear the screen */
    GLCD_ClearScreen_buff(ScreenBuff);
    /* SET UP THE STRINGS */
    sprintf(TC_line_1, " Are you sure?  ");
    if(wellerData.UI_Action == WELLER_ACTION_NO)
        sprintf(TC_line_2, "      No        ");
    else
        sprintf(TC_line_2, "     Yes        ");
    sprintf(TC_line_3, "                ");
    /* step 1 - intro and graphic */
    sprintf(TC_line_4, "CHANGE:         ");
    GLCD_WriteString_12x7_buf(ScreenBuff,&(TC_line_1[0]),Temoco_L1x, Temoco_L1y);
    GLCD_WriteString_12x7_buf(ScreenBuff,&(TC_line_4[0]),Temoco_L1x, Temoco_L4y);
    WriteBMP_Buf(ScreenBuff, Choose_Tempco, Q4_Graphic_x, Q4_Graphic_y, 63, 32);
    Refresh_LCD;
    /* step 2 - make the user check themselves */
    GLCD_WriteString_12x7_buf(ScreenBuff,&(TC_line_2[0]),Temoco_L1x, Temoco_L2y);
    Refresh_LCD;
}


/******************************************************************************/
//  Function:
//    void WELLER_Choose_Fucntion ( void )
//    
// AIm
//     - PResent options to user for choice of other functions
/*******************************************************************************/
void WELLER_Choose_Function( void )
{
    switch (wellerData.UI_Action)
    {
        case WELLER_ACTION_START:
        {
            WriteBMP(ScreenBuff, Choose_Function, 0, 0, 128, 64);
            WriteBMP_Buf(ScreenBuff, Choose_Start, 0, 0, 63, 32);
            Refresh_LCD;
        }
        break;
        
        case WELLER_ACTION_TEMPCO:
        {
            WriteBMP(ScreenBuff, Choose_Function, 0, 0, 128, 64);
            WriteBMP_Buf(ScreenBuff, Choose_Tempco, 0, 32, 63, 32);
            Refresh_LCD;
        }
        break;
        
        case WELLER_ACTION_PID:
        {
            WriteBMP(ScreenBuff, Choose_Function, 0, 0, 128, 64);
            WriteBMP_Buf(ScreenBuff, Choose_PID, 64, 0, 64, 32);
            Refresh_LCD;
        }
        break;
        
        case WELLER_ACTION_SETPOINTS:
        {
            WriteBMP(ScreenBuff, Choose_Function, 0, 0, 128, 64);
            WriteBMP_Buf(ScreenBuff, Choose_Offset, Q4_Graphic_x, Q4_Graphic_y, 64, 32);
            Refresh_LCD;
        }
        break;
    }
}

/******************************************************************************/
//  Function:
//    void WELLER_UI_Fast_Slow( int Fast, int Slow )
//    
// AIm
//     - Update Fast Count in a couple of places
/*******************************************************************************/
WELLER_UI_Fast_Slow(int Fast, int Slow)
{
    /* check Slow Counter - if this is non zero then decrement fast counter */
    if (wellerData.UI_Slow_Count)
        {
        if (wellerData.UI_Fast_Count)
            {
            wellerData.UI_Fast_Count--;
            }
        }
    else /* slow counter expired, go back to normal speed */ 
        {
            wellerData.UI_Fast_Count = Fast_Counter_Init;
        }
    
    /* if fast counter is expired, then go max speed*/
    if (wellerData.UI_Fast_Count == 0)
        wellerData.UI_Speed = Fast;
    else
        wellerData.UI_Speed = Slow;
    /* reset slow counter to init value */
    wellerData.UI_Slow_Count = Slow_Counter_Init;
}


/******************************************************************************
  Function:
    void WELLER_Tasks ( void )

  Remarks:
    See prototype in weller.h.
****************************************************************************/
void REFLOW_Tasks ( void )
{
    int il, jl;
    char DisplayLine[20];
    char DisplayLine1[20];
    char DisplayLine2[20];
 
    /* keep track of how often we run through the loop */
    wellerData.UI_Update_Counter++;
    
    /* Signal the application's heartbeat. */
    if (wellerData.heartbeatToggle == true)
    {
       // SYS_PORTS_PinToggle(PORTS_ID_0, APP_HEARTBEAT_PORT,
        //                    APP_HEARTBEAT_PIN);
        wellerData.heartbeatToggle = false;
    }

    
    /* Check the application's current state. */
    switch ( wellerData.state )
    {
        /* Application's initial state. */
        case WELLER_STATE_INIT:
        {
            
            /* open the ADC */
            DRV_ADC0_Open();
            DRV_ADC_Start();

            // Heartbeat ISR Timer
            wellerData.heartbeatTimer = DRV_TMR_Open( APP_HEARTBEAT_TMR,
                DRV_IO_INTENT_EXCLUSIVE);
            if ( DRV_HANDLE_INVALID != wellerData.heartbeatTimer )
            {
                DRV_TMR_AlarmRegister(wellerData.heartbeatTimer,
                                    APP_HEARTBEAT_TMR_PERIOD,
                                    APP_HEARTBEAT_TMR_IS_PERIODIC,
                                    (uintptr_t)&wellerData,
                                    APP_TimerCallback);
                DRV_TMR_Start(wellerData.heartbeatTimer);
                //wellerData.state = WELLER_STATE_LCDINIT;
            }
            // User Interface ISR Timer
            wellerData.UI_Timer = DRV_TMR_Open( APP_UI_TMR,
                DRV_IO_INTENT_EXCLUSIVE);
            if ( DRV_HANDLE_INVALID != wellerData.UI_Timer )
            {
                DRV_TMR_AlarmRegister(wellerData.UI_Timer,
                                    APP_UI_TMR_PERIOD,
                                    APP_UI_TMR_IS_PERIODIC,
                                    (uintptr_t)&wellerData,
                                    APP_UI_Callback);
                DRV_TMR_Start(wellerData.UI_Timer);
                wellerData.state = WELLER_STATE_LCDINIT;
            }

        }
         break;

        /* Application's initial state. */
        case WELLER_STATE_LCDINIT:
        {
            for(jl = 0; jl < KS0108_SCREEN_HEIGHT/8; jl++)
            {
                for(il = 0; (il < (int)(KS0108_SCREEN_WIDTH)); il++)
                {
                    ScreenBuff[il][jl] = 0;
                    ScreenBuff1[il][jl] = 0;
                }
            }
            /* Function Select */  /* Display On */
            GLCD_Initalize();
            /* Display Clear */
            GLCD_ClearScreen();
            GLCD_WriteCommand(DISPLAY_ON_CMD | DISPLAY_ON, 0);
            GLCD_WriteCommand(DISPLAY_ON_CMD | DISPLAY_ON, 1);
            // Splash Start Up Screen
            Splash_Screen();
            wellerData.state = WELLER_STATE_IDLE;

            /* get the EEPROM up and running and loaded into data structure */
            WELLER_EEPROM_Initialize();

        }        
        break;

        /* we are just sitting there at the "normal" screen */        
        case WELLER_STATE_IDLE:
        {
            /* reset the countdown timer */
            wellerData.Revert_To_Idle_Counter = Revert_To_Idle;
            
            /* see if Snooze counter has expired and if so take action */
            /* but only do this if we have not gone into Snooze yet */
            if ((wellerData.Snooze_Counter == 0) && (!wellerData.Snooze_Flag))
            {
                wellerData.UI_Update_Display = true;
                /* back up the temperature */
                wellerData.Temp_Set_Backup = wellerData.Temp_Set;
                /* set to the defined snooze value */
                wellerData.Temp_Set = Temp_Snooze;
                /* set the flag */
                wellerData.Snooze_Flag = true;
            }        

            if(wellerData.UI_Keypressed)
            {
            /* run update to counters to see if rapid value change needed */
            WELLER_UI_Fast_Slow(Temp_Speed, Temp_Normal_Speed);
            /* reset counter to default - else things will go into snooze */
            wellerData.Snooze_Counter = wellerData.Snooze; 
            wellerData.Snooze_Flag = false;
            /* reset the set temperature */
            wellerData.Temp_Set = wellerData.Temp_Set_Backup;

                if (Keypress_Read == Rot_Up)
                {
                    wellerData.Temp_Set += Temp_Step * wellerData.UI_Speed;
                    if (wellerData.Temp_Set > Temp_Max)
                        wellerData.Temp_Set = Temp_Max;
                    wellerData.UI_Update_Display = true;
                    wellerData.Temp_Set_Backup = wellerData.Temp_Set;
                }
                else if  (Keypress_Read == Rot_Down)
                {
                    wellerData.Temp_Set -= Temp_Step  * wellerData.UI_Speed;
                    if (wellerData.Temp_Set < Temp_Min)
                        wellerData.Temp_Set = Temp_Min;
                    wellerData.UI_Update_Display = true;
                    wellerData.Temp_Set_Backup = wellerData.Temp_Set;
                }
                else if (Keypress_Read == Sel)
                {
                    /* This function displays the save logo and writes the data to EEPROM */
                    WELLER_EEPROM_Save();
                    /* GO BACK TO IDLE STATE */        
                    wellerData.state = WELLER_STATE_IDLE;
                }
                else if (Keypress_Read == Exit)
                {
                    wellerData.UI_Action = WELLER_ACTION_START;
                    wellerData.state = WELLER_STATE_CHOOSING;
                    /* put the right display up */
                    WELLER_Choose_Function();
                }
                wellerData.UI_Keypressed = false;
            }    

            if (Update_UI_Timer && wellerData.UI_Update_Display) 
            {
                Idle_Screen();
                Reset_UI_Timer;
                wellerData.UI_Update_Display = false;
            }
        }
        break;
        
        case WELLER_STATE_START:
        {
            if (Keypress_Read == Exit)
            {
                wellerData.Heater_On = false;  /* turn heater off */
                wellerData.Done = true;  
                wellerData.state = WELLER_STATE_IDLE;
            }

            /* This function displays the start logo */
            WELLER_Start();
            /* The process is started so done = false */ 
            wellerData.Done = false;  
            wellerData.Preheat_Done = false; /* start false */
            wellerData.Soak_Done = false; /* start false */
            wellerData.Reflow_Done = false; /* start false */
            wellerData.Prev_Temp_Meas = wellerData.Temp_Meas;   /* start clear to be sure */
            wellerData.ut = 0;
            wellerData.Error_Prev = 0;
            wellerData.Integral = 0;
            wellerData.Differential = 0;
            /* turn heater off */
            wellerData.Heater_On = false;   
            /* Stay in ghe start state until the temperature is OK */        
            if (wellerData.Start_Settle_Done == true) 
                wellerData.state = WELLER_STATE_PLOT;
        }
        break;

        /*****************************************************************************************/
        
        
        case WELLER_STATE_PLOT:
        {
            /* This function displays the start logo */
            WELLER_Plot();

            if (Keypress_Read == Exit)
            {
                wellerData.Heater_On = 0;  /* turn heater off */
                wellerData.Done = true;  
                wellerData.state = WELLER_STATE_IDLE;
            }
            else if(wellerData.Done == true)
            {
                wellerData.Heater_On = 0;  /* turn heater off */
                if (wellerData.Process_Time > (wellerData.Reflow_Time_End + Cool_Time))
                {
                wellerData.state = WELLER_STATE_IDLE;
                Idle_Screen();
                }
                else
                {
                /* plot cooldown temps for a while*/
                wellerData.state = WELLER_STATE_PLOT;
                }
            }
        }
        break;

        
        /*****************************************************************************************/

        
        case WELLER_STATE_CHOOSING:
        {
            if(wellerData.UI_Keypressed)
            {
                /* reset the countdown timer */
                wellerData.Revert_To_Idle_Counter = Revert_To_Idle;

                /* reset this just to be clear */
                wellerData.UI_Speed = Temp_Normal_Speed;

                if (Keypress_Read == Rot_Up)
                {
                    if (wellerData.UI_Action == WELLER_ACTION_START)
                        wellerData.UI_Action = WELLER_ACTION_PID;
                    else if (wellerData.UI_Action == WELLER_ACTION_PID)
                        wellerData.UI_Action = WELLER_ACTION_SETPOINTS;
                    else if (wellerData.UI_Action == WELLER_ACTION_SETPOINTS)
                        wellerData.UI_Action = WELLER_ACTION_TEMPCO;
                    else if (wellerData.UI_Action == WELLER_ACTION_TEMPCO)
                        wellerData.UI_Action = WELLER_ACTION_START;
                    else   /* catch all */
                        wellerData.UI_Action = WELLER_ACTION_START;
                    /* This function displays the choose function screen  */
                    WELLER_Choose_Function();
                }
                else if  (Keypress_Read == Rot_Down)
                {
                    if (wellerData.UI_Action == WELLER_ACTION_START)
                        wellerData.UI_Action = WELLER_ACTION_TEMPCO;
                    else if (wellerData.UI_Action == WELLER_ACTION_TEMPCO)
                        wellerData.UI_Action = WELLER_ACTION_SETPOINTS;
                    else if (wellerData.UI_Action == WELLER_ACTION_SETPOINTS)
                        wellerData.UI_Action = WELLER_ACTION_PID;
                    else if (wellerData.UI_Action == WELLER_ACTION_PID)
                        wellerData.UI_Action = WELLER_ACTION_START;
                    else   /* catch all */
                        wellerData.UI_Action = WELLER_ACTION_START;
                    /* This function displays the choose function screen  */
                    WELLER_Choose_Function();
                }
                else if (Keypress_Read == Sel)
                {
                    if (wellerData.UI_Action == WELLER_ACTION_START)
                    {
                        /* Jump into the process setup state, "start" */        
                        wellerData.Start_Settle_Done = false; /* start false */
                        /* Make sure the process timer is reset to zero */
                        wellerData.Process_Time = 0;
                        wellerData.Process_Time_Previous = wellerData.Process_Time;
                        wellerData.state = WELLER_STATE_START;
                        WELLER_Start();
                    }
                    else if (wellerData.UI_Action == WELLER_ACTION_TEMPCO)
                    {
                        /* start with no */
                        wellerData.UI_Action = WELLER_ACTION_NO;
                        WELLER_Sensor_Offset();
                        wellerData.state = WELLER_STATE_SENSOR_OFFSET;
                    }
                    else if (wellerData.UI_Action == WELLER_ACTION_SETPOINTS)
                    {
                        /* start with no */
                        wellerData.UI_Action = WELLER_ACTION_NO;
                        WELLER_CHANGE_Setpoints();
                        wellerData.state = WELLER_STATE_SETPOINTS;
                    }
                    else if (wellerData.UI_Action == WELLER_ACTION_PID)
                    {
                        /* start with no */
                        wellerData.UI_Action = WELLER_ACTION_NO;
                        WELLER_PID();
                        wellerData.state = WELLER_STATE_PID;
                    }
                    /* This function displays the choose function screen  */
                }
                else if (Keypress_Read == Exit)
                {
                    /* GO BACK TO IDLE STATE */        
                    wellerData.state = WELLER_STATE_IDLE;
                    Idle_Screen();
                }
                wellerData.UI_Keypressed = false;
                // no need to update the display
            }
            /* if revert timer is out, then quit back to idle screen */
            if (wellerData.Revert_To_Idle_Counter == 0)
            {
                /* GO BACK TO IDLE STATE */        
                wellerData.state = WELLER_STATE_IDLE;
                Idle_Screen();
            }
        }
        break;

        case WELLER_STATE_SETPOINTS:
        {
            if(wellerData.UI_Keypressed)
            {
                /* reset the countdown timer */
                wellerData.Revert_To_Idle_Counter = Revert_To_Idle;
        
                /* reset this just to be clear */
                wellerData.UI_Speed = Temp_Normal_Speed;

                if (Keypress_Read == Rot_Up)
                {
                    if (wellerData.UI_Action == WELLER_ACTION_NO)
                        wellerData.UI_Action = WELLER_ACTION_YES;
                    else if (wellerData.UI_Action == WELLER_ACTION_YES)
                        wellerData.UI_Action = WELLER_ACTION_NO;
                    /* This function displays the choose function screen  */
                    WELLER_CHANGE_Setpoints();
                }
                else if  (Keypress_Read == Rot_Down)
                {
                    if (wellerData.UI_Action == WELLER_ACTION_NO)
                        wellerData.UI_Action = WELLER_ACTION_YES;
                    else if (wellerData.UI_Action == WELLER_ACTION_YES)
                        wellerData.UI_Action = WELLER_ACTION_NO;
                    /* This function displays the choose function screen  */
                    WELLER_CHANGE_Setpoints();
                }
                else if (Keypress_Read == Sel)
                {
                    if (wellerData.UI_Action == WELLER_ACTION_NO)
                    {
                        /* GO BACK TO IDLE STATE */        
                        wellerData.state = WELLER_STATE_IDLE;
                        Idle_Screen();
                    }
                    else if (wellerData.UI_Action == WELLER_ACTION_YES)
                    {
                        /* grab a copy of this as it will be used...*/
                        wellerData.Temp_Preheat_Old = wellerData.Temp_Preheat;
                        WELLER_CHANGE_Preheat();
                        wellerData.state = WELLER_STATE_PREHEAT;
                    }
                }
                else if (Keypress_Read == Exit)
                {
                    /* GO BACK TO IDLE STATE */        
                    wellerData.state = WELLER_STATE_IDLE;
                    Idle_Screen();
                }
                wellerData.UI_Keypressed = false;
                // no need to update the display
            }    
            /* if revert timer is out, then quit back to idle screen */
            if (wellerData.Revert_To_Idle_Counter == 0)
            {
                /* GO BACK TO IDLE STATE */        
                wellerData.state = WELLER_STATE_IDLE;
                Idle_Screen();
            }
        }
        break;


        case WELLER_STATE_PREHEAT:
        {
            if(wellerData.UI_Keypressed)
            {
                /* reset the countdown timer */
                wellerData.Revert_To_Idle_Counter = Revert_To_Idle;

                /* run update to counters to see if rapid value change needed */
                WELLER_UI_Fast_Slow(Temp_Speed, Temp_Normal_Speed);

                if (Keypress_Read == Rot_Up)
                {
                    wellerData.Temp_Preheat +=  wellerData.UI_Speed;
                    if (wellerData.Temp_Preheat >= Temp_Preheat_Max)
                    {
                        wellerData.Temp_Preheat = Temp_Preheat_Max;
                    }
                    /* This function displays the preheat data screen  */
                    WELLER_CHANGE_Preheat();
                }    
                else if  (Keypress_Read == Rot_Down)
                {
                    wellerData.Temp_Preheat -=  wellerData.UI_Speed;
                    if (wellerData.Temp_Preheat <= Temp_Preheat_Min)
                    {
                        wellerData.Temp_Preheat = Temp_Preheat_Min;
                    }
                    /* This function displays the preheat data screen  */
                    WELLER_CHANGE_Preheat();
                }
                else if (Keypress_Read == Sel)
                {
                    /* GO TO THE REFLOW SCREEN */        
                    wellerData.Temp_Reflow_Old = wellerData.Temp_Reflow;
                    wellerData.state = WELLER_STATE_REFLOW;
                    WELLER_CHANGE_Reflow();
                }
                else if (Keypress_Read == Exit)
                {
                    /* GO BACK TO IDLE STATE */        
                    /* with the old offset */
                    wellerData.Temp_Reflow = wellerData.Temp_Reflow_Old;
                    wellerData.state = WELLER_STATE_IDLE;
                    Idle_Screen();
                }
                wellerData.UI_Keypressed = false;
                // no need to update the display
            }    
            /* if revert timer is out, then quit back to idle screen */
            if (wellerData.Revert_To_Idle_Counter == 0)
            {
                /* GO BACK TO IDLE STATE */        
                wellerData.state = WELLER_STATE_IDLE;
                wellerData.Temp_Reflow = wellerData.Temp_Reflow_Old;
                Idle_Screen();
            }
        }
        break;


        case WELLER_STATE_REFLOW:
        {
            if(wellerData.UI_Keypressed)
            {
                /* reset the countdown timer */
                wellerData.Revert_To_Idle_Counter = Revert_To_Idle;

                /* run update to counters to see if rapid value change needed */
                WELLER_UI_Fast_Slow(Temp_Speed, Temp_Normal_Speed);

                if (Keypress_Read == Rot_Up)
                {
                    wellerData.Temp_Reflow += wellerData.UI_Speed;
                    if (wellerData.Temp_Reflow >= Temp_Reflow_Max)
                    {
                        wellerData.Temp_Reflow = Temp_Reflow_Max;
                    }
                    /* This function displays the choose function screen  */
                    WELLER_CHANGE_Reflow();
                }    
                else if  (Keypress_Read == Rot_Down)
                {
                    wellerData.Temp_Reflow -= wellerData.UI_Speed;
                    if (wellerData.Temp_Reflow <= Temp_Reflow_Min)
                    {
                        wellerData.Temp_Reflow = Temp_Reflow_Min;
                    }
                    /* This function displays the choose function screen  */
                    WELLER_CHANGE_Reflow();
                }
                else if (Keypress_Read == Sel)
                {
                    WELLER_Done();
                    /* GO BACK TO IDLE STATE */        
                    wellerData.state = WELLER_STATE_IDLE;
                    Idle_Screen();
                }
                else if (Keypress_Read == Exit)
                {
                    /* GO BACK TO IDLE STATE */        
                    wellerData.state = WELLER_STATE_IDLE;
                    /* With the old coeff value */
                    wellerData.Temp_Preheat = wellerData.Temp_Preheat_Old;
                    wellerData.Temp_Reflow = wellerData.Temp_Reflow_Old;
                    Idle_Screen();
                }
                wellerData.UI_Keypressed = false;
                // no need to update the display
            }    
            /* if revert timer is out, then quit back to idle screen */
            if (wellerData.Revert_To_Idle_Counter == 0)
            {
                /* GO BACK TO IDLE STATE */        
                wellerData.state = WELLER_STATE_IDLE;
                wellerData.Temp_Preheat = wellerData.Temp_Preheat_Old;
                wellerData.Temp_Reflow = wellerData.Temp_Reflow_Old;
                Idle_Screen();
            }
        }
        break;
       
        case WELLER_STATE_SENSOR_OFFSET:
        {
            if(wellerData.UI_Keypressed)
            {
                /* reset the countdown timer */
                wellerData.Revert_To_Idle_Counter = Revert_To_Idle;
        
                /* reset this just to be clear */
                wellerData.UI_Speed = Temp_Normal_Speed;

                if (Keypress_Read == Rot_Up)
                {
                    if (wellerData.UI_Action == WELLER_ACTION_NO)
                        wellerData.UI_Action = WELLER_ACTION_YES;
                    else if (wellerData.UI_Action == WELLER_ACTION_YES)
                        wellerData.UI_Action = WELLER_ACTION_NO;
                    /* This function displays the choose function screen  */
                    WELLER_Sensor_Offset();
                }
                else if  (Keypress_Read == Rot_Down)
                {
                    if (wellerData.UI_Action == WELLER_ACTION_NO)
                        wellerData.UI_Action = WELLER_ACTION_YES;
                    else if (wellerData.UI_Action == WELLER_ACTION_YES)
                        wellerData.UI_Action = WELLER_ACTION_NO;
                    /* This function displays the choose function screen  */
                    WELLER_Sensor_Offset();
                }
                else if (Keypress_Read == Sel)
                {
                    if (wellerData.UI_Action == WELLER_ACTION_NO)
                    {
                        /* GO BACK TO IDLE STATE */        
                        wellerData.state = WELLER_STATE_IDLE;
                        Idle_Screen();
                    }
                    else if (wellerData.UI_Action == WELLER_ACTION_YES)
                    {
                        /* grab a copy of this as it will be used...*/
                        wellerData.Temp_Sensor_Offset_Old = wellerData.Temp_Sensor_Offset;
                        WELLER_CHANGE_Sensor_Offset();
                        wellerData.state = WELLER_STATE_SENSOR_OFFSET_CHANGE;
                    }
                }
                else if (Keypress_Read == Exit)
                {
                    /* GO BACK TO IDLE STATE */        
                    wellerData.state = WELLER_STATE_IDLE;
                    Idle_Screen();
                }
                wellerData.UI_Keypressed = false;
                // no need to update the display
            }    
            /* if revert timer is out, then quit back to idle screen */
            if (wellerData.Revert_To_Idle_Counter == 0)
            {
                /* GO BACK TO IDLE STATE */        
                wellerData.state = WELLER_STATE_IDLE;
                Idle_Screen();
            }
        }
        break;


        case WELLER_STATE_SENSOR_OFFSET_CHANGE:
        {
            if(wellerData.UI_Keypressed)
            {
                /* reset the countdown timer */
                wellerData.Revert_To_Idle_Counter = Revert_To_Idle;

                /* run update to counters to see if rapid value change needed */
                WELLER_UI_Fast_Slow(TempOffset_Speed, TempOffset_Normal_Speed);

                if (Keypress_Read == Rot_Up)
                {
                    wellerData.Temp_Sensor_Offset +=  Temp_Step * wellerData.UI_Speed;
                    if (wellerData.Temp_Sensor_Offset >= Temp_Offset_Max)
                    {
                        wellerData.Temp_Sensor_Offset = Temp_Offset_Max;
                    }
                    /* This function displays the choose function screen  */
                    WELLER_CHANGE_Sensor_Offset();
                }    
                else if  (Keypress_Read == Rot_Down)
                {
                    wellerData.Temp_Sensor_Offset -=  Temp_Step * wellerData.UI_Speed;
                    if (wellerData.Temp_Sensor_Offset <= Temp_Offset_Min)
                    {
                        wellerData.Temp_Sensor_Offset = Temp_Offset_Min;
                    }
                    /* This function displays the choose function screen  */
                    WELLER_CHANGE_Sensor_Offset();
                }
                else if (Keypress_Read == Sel)
                {
                    /* GO BACK TO IDLE STATE */        
                    wellerData.Temp_Coeff_Old = wellerData.Temp_Coeff;
                    wellerData.state = WELLER_STATE_SENSOR_COEFF_CHANGE;
                    WELLER_CHANGE_Sensor_Tempco();
                }
                else if (Keypress_Read == Exit)
                {
                    /* GO BACK TO IDLE STATE */        
                    /* with the old offset */
                    wellerData.Temp_Sensor_Offset = wellerData.Temp_Sensor_Offset_Old;
                    wellerData.state = WELLER_STATE_IDLE;
                    Idle_Screen();
                }
                wellerData.UI_Keypressed = false;
                // no need to update the display
            }    
            /* if revert timer is out, then quit back to idle screen */
            if (wellerData.Revert_To_Idle_Counter == 0)
            {
                /* GO BACK TO IDLE STATE */        
                wellerData.state = WELLER_STATE_IDLE;
                wellerData.Temp_Sensor_Offset = wellerData.Temp_Sensor_Offset_Old;
                Idle_Screen();
            }
        }
        break;


        case WELLER_STATE_SENSOR_COEFF_CHANGE:
        {
            if(wellerData.UI_Keypressed)
            {
                /* reset the countdown timer */
                wellerData.Revert_To_Idle_Counter = Revert_To_Idle;

                /* run update to counters to see if rapid value change needed */
                WELLER_UI_Fast_Slow(Tempco_Speed, Tempco_Normal_Speed);
                
                if (Keypress_Read == Rot_Up)
                {
                    wellerData.Temp_Coeff += wellerData.UI_Speed;
                    if (wellerData.Temp_Coeff >= Tempco_Max)
                    {
                        wellerData.Temp_Coeff = Tempco_Max;
                    }
                    /* This function displays the choose function screen  */
                    WELLER_CHANGE_Sensor_Tempco();
                }    
                else if  (Keypress_Read == Rot_Down)
                {
                    wellerData.Temp_Coeff -= wellerData.UI_Speed;
                    if (wellerData.Temp_Coeff <= Tempco_Min)
                    {
                        wellerData.Temp_Coeff = Tempco_Min;
                    }
                    /* This function displays the choose function screen  */
                    WELLER_CHANGE_Sensor_Tempco();
                }
                else if (Keypress_Read == Sel)
                {
                    WELLER_Done();
                    /* GO BACK TO IDLE STATE */        
                    wellerData.state = WELLER_STATE_IDLE;
                    Idle_Screen();
                }
                else if (Keypress_Read == Exit)
                {
                    /* GO BACK TO IDLE STATE */        
                    wellerData.state = WELLER_STATE_IDLE;
                    /* With the old coeff value */
                    wellerData.Temp_Sensor_Offset = wellerData.Temp_Sensor_Offset_Old;
                    wellerData.Temp_Coeff = wellerData.Temp_Coeff_Old;
                    Idle_Screen();
                }
                wellerData.UI_Keypressed = false;
                // no need to update the display
            }    
            /* if revert timer is out, then quit back to idle screen */
            if (wellerData.Revert_To_Idle_Counter == 0)
            {
                /* GO BACK TO IDLE STATE */        
                wellerData.state = WELLER_STATE_IDLE;
                wellerData.Temp_Sensor_Offset = wellerData.Temp_Sensor_Offset_Old;
                wellerData.Temp_Coeff = wellerData.Temp_Coeff_Old;
                Idle_Screen();
            }
        }
        break;

        case WELLER_STATE_PID:
        {
            if(wellerData.UI_Keypressed)
            {
                /* reset the countdown timer */
                wellerData.Revert_To_Idle_Counter = Revert_To_Idle;

                /* run update to counters to see if rapid value change needed */
                WELLER_UI_Fast_Slow(Snooze_Speed, Snooze_Normal_Speed);

                if (Keypress_Read == Rot_Up)
                {
                    if (wellerData.UI_Action == WELLER_ACTION_NO)
                        wellerData.UI_Action = WELLER_ACTION_YES;
                    else 
                        wellerData.UI_Action = WELLER_ACTION_NO;
                    /* This function displays the check screen for chaning PID values  */
                    WELLER_PID( );
                }    
                else if  (Keypress_Read == Rot_Down)
                {
                    if (wellerData.UI_Action == WELLER_ACTION_NO)
                        wellerData.UI_Action = WELLER_ACTION_YES;
                    else 
                        wellerData.UI_Action = WELLER_ACTION_NO;
                    /* This function displays the check screen for chaning PID values  */
                    WELLER_PID( );
                }
                else if (Keypress_Read == Sel)
                {
                   if (wellerData.UI_Action == WELLER_ACTION_NO)
                    {
                        /* GO BACK TO IDLE STATE */        
                        wellerData.state = WELLER_STATE_IDLE;
                        Idle_Screen();
                    }
                    else if (wellerData.UI_Action == WELLER_ACTION_YES)
                    {
                        /* grab a copy of this as it will be used...*/
                        wellerData.PID_P_Old = wellerData.PID_P;
                        wellerData.state = WELLER_STATE_PID_P;
                        WELLER_PID_P();
                    }
                }
                else if (Keypress_Read == Exit)
                {
                    /* GO BACK TO IDLE STATE */        
                    wellerData.state = WELLER_STATE_IDLE;
                    Idle_Screen();
                }
                wellerData.UI_Keypressed = false;
                // no need to update the display
            }    
            /* if revert timer is out, then quit back to idle screen */
            if (wellerData.Revert_To_Idle_Counter == 0)
            {
                /* GO BACK TO IDLE STATE */        
                wellerData.state = WELLER_STATE_IDLE;
                Idle_Screen();
            }
        }
        break;

        case WELLER_STATE_PID_P:
        {
            if(wellerData.UI_Keypressed)
            {
                /* reset the countdown timer */
                wellerData.Revert_To_Idle_Counter = Revert_To_Idle;

                /* run update to counters to see if rapid value change needed */
                WELLER_UI_Fast_Slow(P_Speed, P_Normal_Speed);

                if (Keypress_Read == Rot_Up)
                {
                    wellerData.PID_P += ((float) (wellerData.UI_Speed)) / PID_SCALING ;
                    if (wellerData.PID_P >= P_Max)
                    {
                        wellerData.PID_P = P_Max;
                    }
                    /* This function displays the choose PID >>> P <<< screen  */
                    WELLER_PID_P();
                }    
                else if  (Keypress_Read == Rot_Down)
                {
                    wellerData.PID_P -=  ((float) (wellerData.UI_Speed)) / PID_SCALING;
                    if (wellerData.PID_P <= P_Min)
                    {
                        wellerData.PID_P = P_Min;
                    }
                    /* This function displays the choose PID >>> P <<< screen  */
                    WELLER_PID_P();
                }
                else if (Keypress_Read == Sel)
                {
                    /* grab a copy of this as it will be used...*/
                    wellerData.PID_I_Old = wellerData.PID_I;
                    wellerData.state = WELLER_STATE_PID_I;
                    WELLER_PID_I();
                }
                else if (Keypress_Read == Exit)
                {
                    /* GO BACK TO IDLE STATE */        
                    wellerData.state = WELLER_STATE_IDLE;
                    wellerData.PID_P = wellerData.PID_P_Old;
                    Idle_Screen();
                }
                wellerData.UI_Keypressed = false;
                // no need to update the display
            }    
            /* if revert timer is out, then quit back to idle screen */
            if (wellerData.Revert_To_Idle_Counter == 0)
            {
                /* GO BACK TO IDLE STATE */        
                wellerData.PID_P = wellerData.PID_P_Old;
                wellerData.state = WELLER_STATE_IDLE;
                Idle_Screen();
            }
        }
        break;

        case WELLER_STATE_PID_I:
        {
            if(wellerData.UI_Keypressed)
            {
                /* reset the countdown timer */
                wellerData.Revert_To_Idle_Counter = Revert_To_Idle;

                /* run update to counters to see if rapid value change needed */
                WELLER_UI_Fast_Slow(I_Speed, I_Normal_Speed);

                if (Keypress_Read == Rot_Up)
                {
                    wellerData.PID_I +=  ((float) (wellerData.UI_Speed)) / PID_SCALING;
                    if (wellerData.PID_I >= I_Max)
                    {
                        wellerData.PID_I = I_Max;
                    }
                    /* This function displays the choose PID >>> P <<< screen  */
                    WELLER_PID_I();
                }    
                else if  (Keypress_Read == Rot_Down)
                {
                    wellerData.PID_I -=  ((float) (wellerData.UI_Speed)) / PID_SCALING;
                    if (wellerData.PID_I <= I_Min)
                    {
                        wellerData.PID_I = I_Min;
                    }
                    /* This function displays the choose PID >>> P <<< screen  */
                    WELLER_PID_I();
                }
                else if (Keypress_Read == Sel)
                {
                    /* grab a copy of this as it will be used...*/
                    wellerData.PID_D_Old = wellerData.PID_D;
                    wellerData.state = WELLER_STATE_PID_D;
                    WELLER_PID_D();
                }
                else if (Keypress_Read == Exit)
                {
                    /* GO BACK TO IDLE STATE */        
                    wellerData.state = WELLER_STATE_IDLE;
                    wellerData.PID_P = wellerData.PID_P_Old;
                    wellerData.PID_I = wellerData.PID_I_Old;
                    Idle_Screen();
                }
                wellerData.UI_Keypressed = false;
                // no need to update the display
            }    
            /* if revert timer is out, then quit back to idle screen */
            if (wellerData.Revert_To_Idle_Counter == 0)
            {
                /* GO BACK TO IDLE STATE */        
                wellerData.PID_P = wellerData.PID_P_Old;
                wellerData.PID_I = wellerData.PID_I_Old;
                wellerData.state = WELLER_STATE_IDLE;
                Idle_Screen();
            }
        }
        break;

        case WELLER_STATE_PID_D:
        {
            if(wellerData.UI_Keypressed)
            {
                /* reset the countdown timer */
                wellerData.Revert_To_Idle_Counter = Revert_To_Idle;

                /* run update to counters to see if rapid value change needed */
                WELLER_UI_Fast_Slow(D_Speed, D_Normal_Speed);

                if (Keypress_Read == Rot_Up)
                {
                    wellerData.PID_D +=  ((float) (wellerData.UI_Speed)) / PID_SCALING;
                    if (wellerData.PID_D >= D_Max)
                    {
                        wellerData.PID_D = D_Max;
                    }
                    /* This function displays the choose PID >>> P <<< screen  */
                    WELLER_PID_D();
                }    
                else if  (Keypress_Read == Rot_Down)
                {
                    wellerData.PID_D -=  ((float) (wellerData.UI_Speed)) / PID_SCALING;
                    if (wellerData.PID_D <= D_Min)
                    {
                        wellerData.PID_D = D_Min;
                    }
                    /* This function displays the choose PID >>> P <<< screen  */
                    WELLER_PID_D();
                }
                else if (Keypress_Read == Sel)
                {
                    WELLER_Done();
                    wellerData.state = WELLER_STATE_IDLE;
                    Idle_Screen();
                }
                else if (Keypress_Read == Exit)
                {
                    /* GO BACK TO IDLE STATE */        
                    wellerData.state = WELLER_STATE_IDLE;
                    wellerData.PID_P = wellerData.PID_P_Old;
                    wellerData.PID_I = wellerData.PID_I_Old;
                    wellerData.PID_D = wellerData.PID_D_Old;
                    Idle_Screen();
                }
                wellerData.UI_Keypressed = false;
                // no need to update the display
            }    
            /* if revert timer is out, then quit back to idle screen */
            if (wellerData.Revert_To_Idle_Counter == 0)
            {
                /* GO BACK TO IDLE STATE */        
                wellerData.PID_P = wellerData.PID_P_Old;
                wellerData.PID_I = wellerData.PID_I_Old;
                wellerData.PID_D = wellerData.PID_D_Old;
                wellerData.state = WELLER_STATE_IDLE;
                Idle_Screen();
            }
        }
        break;

                
        
        case WELLER_STATE_SERVICE_TASKS:
        {
        
        }
        break;


        /* The default state should never be executed. */
        default:
        {
            /* TODO: Handle error in application's state machine. */
            break;
        }
    }
 
            
    /* decrement this outside the UI loop, if it gets to zero then */
    /* the UI will reset the fast counter and not got to fast change */
    if(wellerData.UI_Slow_Count > 0)
        wellerData.UI_Slow_Count--;
}

 

/*******************************************************************************
 End of File
 */
