EasyCAT LAB - EtherCAT master legacy example

Dependencies:   SOEM SPI_STMPE610 SPI_TFT_ILI9341 TFT_fonts

The EasyCAT LAB is a complete educational and experimental EtherCAT® system, composed of one master and two slaves .

/media/uploads/EasyCAT/easycat_lab.jpg

/media/uploads/EasyCAT/components.jpg

main.cpp

Committer:
sulymarco
Date:
2021-05-28
Revision:
6:4b39b4dee215
Parent:
5:550a1222dcba
Child:
7:d71db73dcdd9

File content as of revision 6:4b39b4dee215:

//********************************************************************************************    
//                                                                                           *
// This software is distributed as an example, "AS IS", in the hope that it could            *
// be useful, WITHOUT ANY WARRANTY of any kind, express or implied, included, but            *
// not limited,  to the warranties of merchantability, fitness for a particular              *
// purpose, and non infringiment. In no event shall the authors be liable for any            *    
// claim, damages or other liability, arising from, or in connection with this software.     *
//                                                                                           *
//******************************************************************************************** 


// The AB&T EasyCAT LAB is a complete experimental EtherCAT® system, composed by
// one master and two slaves.
// The EasyCAT LAB software is provided free of charge and its pourpose is to allow
// makers and educational institutes to experiment with the EtherCAT® protocol.
//
// The EasyCAT LAB is developed by "AB&T Tecnologie Informatiche" Via dell'About 2A Ivrea Italy.
// www.bausano.net
// www.easycatshield.com
//
// The EasyCAT LAB uses the SOEM library by rt:labs
// https://rt-labs.com/products/soem-ethercat-master-stack/
// 
// EtherCAT® is a registered trademark and patented technology, licensed by Beckhoff Automation GmbH.
// www.beckhoff.com
// www.ethercat.org     


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

//#define ADA_TFT       // IMPORTANT!!! 

                        // If your EasyCAT LAB uses the Adafruit TFT
                        // you must uncomment this define
                        
                        // If your EasyCAT LAB uses the Seeed Studio TFT
                        // you must comment this define                                                  

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

#define ETH_TXBUFNB 16
#define ETH_RXBUFNB 16

#include "mbed.h"    

#ifndef __align
#define __align MBED_ALIGN
#endif

#include "config.h"  
#include "SPI_TFT_ILI9341.h"
#include "Arial12x12.h"
#include "Arial24x23.h"
#include "Arial28x28.h"
#include "font_big.h"
#include "soem_start.h"
#include "SPI_STMPE610.h"

#define CYCLE_TIME 1000                 // master cycle time in uS                    
                                        // 1000 = 1mS 

                                  
#define SysMilliS() (uint32_t)Kernel::get_ms_count()                                      

UnbufferedSerial pc(USBTX,USBRX,115200);          // set the debug serial line speed to 115200


//---- TFT with resistive touchscreen pins -------------------------------------

// the display used is the SeeedStudio 2.8 inch TFT v2.0
// http://wiki.seeedstudio.com/2.8inch_TFT_Touch_Shield_v2.0/ 
//
// or the Adafruit 2.8" with resistive touchscreen
// https://www.adafruit.com/product/1651


#define PIN_YP          A3                          // resistive touchscreen
#define PIN_YM          A1                          //
#define PIN_XM          A2                          //
#define PIN_XP          A0                          //

#define PIN_MOSI        D11                         // TFT display SPI
#define PIN_MISO        D12                         //
#define PIN_SCLK        D13                         //

#if defined ADA_TFT                                 // pins for the Adafruit TFT                      
    #define PIN_CS_TFT  D10                         //                 
    #define PIN_DC_TFT  D9                          //                     
    #define PIN_CS_TSC  D8                          // 
    
#else                                               // pins for the SeeedStudio TFT
    #define PIN_CS_TFT  D5                          //    
    #define PIN_DC_TFT  D6                          //
#endif                                              //


//---- touchscreen parameters --------------------------------------------------

#define TOUCH_SAMPLES 8                                                     
#define TOUCH_WINDOW 0.05
#define TOUCH_THRESHOLD 0.2
#define TOUCH_MAX_ROUNDS 16
#define TIME_TOUCH_RELEASED 300

#define TOUCH_X_OFFSET 0.118
#define TOUCH_X_GAIN 402

#define TOUCH_Y_OFFSET 0.090
#define TOUCH_Y_GAIN 302


//---- side menu parameters ----------------------------------------------------

#define MENU_Y 0                    
#define MENU_WIDTH 83               
#define MENU_HEIGHT 42                  
#define MENU_X (319-MENU_WIDTH)     


//---- slave parameters - LAB_1 EasyCAT with multifunction shield --------------

#define TERMO_X 55                
#define TERMO_Y 185                
                                  
#define ALARM_X 140                
#define ALARM_Y 0                  
#define ALARM_WIDTH 83              
#define ALARM_HEIGHT 42  

#define TIME_BLINK 1000
#define TIME_AUTO_REP_START 1000
#define TIME_AUTO_REP_REPEAT 200    


//---- slave parameters - LAB_2 EasyCAT with multifunction shield --------------

#define SEG_X 0                     
#define SEG_Y 0                     
#define SEG_WIDTH 42                
#define SEG_HEIGHT 16               
#define SEG_STEP 60                     

#define BUTTONS_X 38
#define BUTTONS_Y 80 
#define BUTTONS_WIDTH 26
#define BUTTONS_R 3
#define BUTTONS_STEP 60 

#define ANALOG_X 0
#define ANALOG_Y 120 
#define ANALOG_WIDTH 222
#define ANALOG_HEIGHT 80 

#define TIME_REP_SEG 300
#define TIME_POTENTIOMETER 100


//---- local functions ---------------------------------------------------------

void DrawBanner();
void DrawSlaveFixedParts();
void DrawSideMenu (uint8_t Slave);

void DrawTemperatureValue(float fValue);
void DrawAlarmSettings(float fThreshold, bool OnOff, bool MinMax);
void DrawOnlyThreshold(float fThreshold, bool OnOff, bool MinMax);
void DrawAlarmStatus(bool Alarm);
void DisplayInRect(int X, int Y, int X_off, int Y_off, char* Value, int BackColor, unsigned char* Font);

void DrawButtonsValue(uint8_t Value);
void DrawSegmentsValue(uint8_t Value);
void DrawPotentiometerValue(uint16_t PotValue);


float ReadAnalog(AnalogIn Ana);


void Application();   

void TouchScreenManagement();
bool TouchRead(uint16_t* X, uint16_t* Y);
uint16_t TouchRead_X();
uint16_t TouchRead_Y();
bool TouchRead_Z();



//---- global variables --------------------------------------------------------


bool TouchWasReleased;

bool FirstRound;

//------------------------------------------------------------------------------

SPI_TFT_ILI9341 TFT(PIN_MOSI, PIN_MISO, PIN_SCLK, PIN_CS_TFT, NC, PIN_DC_TFT);

#if defined ADA_TFT             // touchscreen controller for the Adafruit TFT       
    SPI_STMPE610 TSC(PIN_MOSI, PIN_MISO, PIN_SCLK, PIN_CS_TSC);             
#endif

Ticker SampleTicker;
Thread thread;

DigitalOut Test_1(D1);          // debug test points
DigitalOut Test_2(D2);          //
DigitalOut Test_3(D3);          //
DigitalOut Test_4(D4);          //


//------------------------------------------------------------------------------

float fAlarmThreshold;
bool AlarmOnOff;
bool AlarmMinMax;


uint16_t PotValue;
uint16_t PrevPotValue;
uint8_t Buttons; 
uint8_t PrevButtons;
uint8_t Segments;
uint8_t PrevSegments;
int16_t Graph_x;

uint8_t Outputs;
uint8_t PrevOutputs;

uint8_t Inputs;
uint8_t PrevInputs;

    
int8_t VisuSlave;
    
   
//------------------------------------------------------------------------------   
    
uint32_t Time;    
uint32_t TimeBlink; 
uint32_t TimeAutoRepeat;
uint32_t TimeAutoRepRepeat;
uint32_t TimePotentiometer;
uint32_t TimeTouchReleased;

bool Blink;

uint8_t TouchAxes = 0;
uint8_t Action = 0;

uint16_t X;
uint16_t Y;

float fTemperature;   
float static fPrevTemperature;  

int ExpectWorkCounter;
int WorkCounter; 
int WorkCounterSafe; 
bool NetworkError;  
bool NetworkErrorSafe; 

#define DATA_EXCHANGE_FLAG      (1UL << 0)
#define APPLICATION_FLAG        (1UL << 1)

EventFlags event_flags;

Mutex IO_data;


//---- data exchange thread ----------------------------------------------------

void ExchangeMaster()
{
    while (true)
    {
                
        
        event_flags.wait_any(DATA_EXCHANGE_FLAG);   // the thread waits for the synchronization flag
    
        //Test_1 = 1;
    
        IO_data.lock();                             // Ethercat data exchange
        ec_send_processdata();                      // 
        WorkCounter = ec_receive_processdata(EC_TIMEOUTRET);  
        
                            if (WorkCounter != ExpectWorkCounter)
                                NetworkError = true;
                            else
                                NetworkError = false;    
                            
        IO_data.unlock();                           //
        event_flags.set(APPLICATION_FLAG);          // synchronize the application    
        
        //Test_1 = 0;                    
    }
}


//----- thicker generated sample time ------------------------------------------

void SampleIsr()                                    // set the event that starts
{                                                   // the data exchange
    event_flags.set(DATA_EXCHANGE_FLAG);            //
}                                                   //
    
    
//****** initialization ********************************************************

int main()
{      
    int i;
    
    printf("Start \n");
    
    Test_1 = 0; 
    Test_2 = 0;
    Test_3 = 0;
    Test_4 = 0;      
  
    TFT.background(Black);                                          // init TFT  
    TFT.cls();                                                      //
    
    #if defined ADA_TFT
        TFT.set_orientation(1);     
    #else
        TFT.set_orientation(3);                                        
    #endif    
    
    DrawBanner();     
        
    NetworkError = false;  
    VisuSlave = LAB_1; 
    
    AlarmOnOff = true;
    AlarmMinMax = false;
    fAlarmThreshold = 28.8;
    fTemperature = 0;
    TouchWasReleased = true;
    

    if (ec_init(NULL))                                              // init SOEM
    {
        printf("ec_init succeeded.\n");     
        printf("Scanning the network\n");

        TFT.cls();  
                                                            
        TFT.set_font((unsigned char*) Arial12x12);
        TFT.foreground(Green);
        TFT.locate(0, 0);
        
        TFT.printf("Scanning the network\n");           
          
        if (network_scanning())
        {   
            if (network_configuration())                            // check network configuration
            {
                ec_config_map(&IOmap);                              // map the I/O
                MapLocalStructures();                 

                printf("\nSlaves mapped, state to SAFE_OP.\n");     
                                                                    // wait for all slaves to reach SAFE_OP state         
                ec_statecheck(0, EC_STATE_SAFE_OP,  EC_TIMEOUTSTATE);
    
                printf("Request operational state for all slaves\n");
                ec_slave[0].state = EC_STATE_OPERATIONAL;           
           
                ec_send_processdata();                              // send one valid process data to make outputs in slaves happy
                ExpectWorkCounter = ec_receive_processdata(EC_TIMEOUTRET);          
               
                ec_writestate(0);                                   // request OP state for all slaves 
                
                                                                    // wait for all slaves to reach OP state 
                ec_statecheck(0, EC_STATE_OPERATIONAL,  EC_TIMEOUTSTATE);
                if (ec_slave[0].state == EC_STATE_OPERATIONAL )
                {
                    printf("Operational state reached for all slaves.\n");
                }
                else
                {
                    printf("Not all slaves reached operational state.\n");
                    ec_readstate();
                    for(i = 1; i<=ec_slavecount ; i++)
                    {
                        if(ec_slave[i].state != EC_STATE_OPERATIONAL)
                        {
                            printf("Slave %d State=0x%04x StatusCode=0x%04x\n",
                                    i, ec_slave[i].state, ec_slave[i].ALstatuscode);
                        }
                    }
                    
                    TFT.foreground(Red);                                                     
                    TFT.locate(0, 0);      
                    TFT.printf("Not all slaves reached operational state!");                           
                    while(1){}  
                }   
                
                DrawSlaveFixedParts(); 
                                
                thread.start(ExchangeMaster);
                thread.set_priority(osPriorityRealtime); 

                SampleTicker.attach_us(&SampleIsr, CYCLE_TIME);  
              
                Application();
            }
            
            else
            {
                printf("Mismatch of network units!\n");            
                TFT.foreground(Red);                                                     
                TFT.locate(0, 0);      
                TFT.printf("Mismatch of network units!");
    
                while(1){}  
            }                       
        }       
        
        else
        {
            printf("No slaves found!\n");
            TFT.foreground(Red);                                                          
            TFT.printf("No slaves found!");             
        
            while(1){}  
        }           
    }
    else
    {
        printf("Ethernet interface init failed!");
        TFT.foreground(Red);                                                     
        TFT.locate(0, 0);      
        TFT.printf("Ethernet interface init failed!");                
        while(1){}
    }    
}             
                                 
              
//****** user master application  **********************************************
      
void Application()      
{        
     
    while(1)
    {          
        event_flags.wait_any(APPLICATION_FLAG);                     // the application waits for the synchronization flag
        
        //Test_2 = 1;     
     
        IO_data.lock();                                             // copy the Ethercat data to a safe buffer
        memcpy(&IOmapSafe[0], &IOmap[0], IO_MAP_SIZE);              //
                                                                    //                
        if (NetworkError)                                           //    
        {                                                           //
            NetworkErrorSafe = NetworkError;                        //    
            WorkCounterSafe = WorkCounter;                          //
        }                                                           //
        IO_data.unlock();                                           // 
              
        if (NetworkErrorSafe)
        {           
            TFT.rect(35,50, 285, 182, Red);    
            TFT.fillrect(36,51, 284, 181, Black);
            TFT.foreground(Red);
            TFT.set_font((unsigned char*) Arial28x28);        
            TFT.locate(58, 65); 
            TFT.printf("Network error!");
            printf("Network error!\n");                  
            TFT.foreground(Magenta);
            TFT.set_font((unsigned char*) Arial12x12);        
            TFT.locate(58, 106);
            
            if(WorkCounterSafe >= 0)
            {
                TFT.printf("Expected working counter %d", ExpectWorkCounter);                                         
                TFT.locate(58, 118);                                                   
                TFT.printf("Actual working counter %d", WorkCounterSafe); 
                printf("Expected working counter %d\n", ExpectWorkCounter);                                                    
                printf("Actual working counter %d\n", WorkCounterSafe); 
            } 
            else
            {
                TFT.printf("Timeout");                 
                printf("Timeout\n");   
            }                        
                
            TFT.foreground(Green);    
            TFT.locate(58, 142);                                                   
            TFT.printf("Please fix the error and");
            TFT.locate(58, 154);                      
            TFT.printf("press the reset button");                              
            printf("Please fix the error and press the reset button \n"); 
            
            SampleTicker.detach();                                  // stop the sample interrupt 
            while(1){}                                              // and loop for ever                           
        }     
        
                                                                    //----- slave 1 data management ------------            
          
        fTemperature = in_LAB_1->Temperature;                       // read the temperature 
     
        if (fTemperature != fPrevTemperature)                       // check if the temperature has changed
        {
            fPrevTemperature = fTemperature;                        // remember the current temperature value
                        
            if (VisuSlave == LAB_1)                                 // if the HMI is setted to slave 1
            {                                                       // visualize it            
                DrawTemperatureValue (fTemperature);                //                               
            }                                                        
        }                                                                           
    
        bool AlarmStatus;                                
        if (AlarmOnOff)                                             // check if we are in alarm 
        {                                                           //
            if ((AlarmMinMax && (fTemperature < fAlarmThreshold)) || (!AlarmMinMax && (fTemperature > fAlarmThreshold)))
            {
                out_LAB_1->Alarm = 0x01;                            // signal the alarm condition to the slave                                                                        
                AlarmStatus = true;                                 // and to remember it                     
            }
            else
            {     
                out_LAB_1->Alarm = 0x00;                            // signal the no alarm condition to the slave
                AlarmStatus = false;                                // and remember it              
            }            
        } 
        else 
        {
            out_LAB_1->Alarm = 0x00;                                // signal the no alarm condition to the slave      
            AlarmStatus = false;                                    // and remember it                       
        }   
                                                                
        if (VisuSlave == LAB_1)                                     // if the HMI is set to slave 1                       
        {                                                           // 
            DrawAlarmStatus(AlarmStatus);                           // update the alarm status on the TFT
        }  
    
        if (VisuSlave == LAB_1 && FirstRound)                       // if the HMI is set to slave 1                                                        
        {                                                           // and it is the first time 
            FirstRound = false;                                     //    
            DrawTemperatureValue (fTemperature);                    // draw the current temperature value 
            DrawAlarmSettings(fAlarmThreshold, AlarmOnOff, AlarmMinMax); // draw the alarm settings                                   
        }                                                                        
    
                                                                    //----- end LAB_1 ------------------------     
                                                                                           
                                                                                                                                  
                                                                    //----- slave 2 data management ------------  
                                                                
        PotValue = in_LAB_2->Potentiometer;                         // read the potentiometer value   
    
        if (VisuSlave == LAB_2)                                     // if the HMI is setted to slave 2
        {                                                           // 
            Time = SysMilliS();                                     // and the visualization timer is elapsed             
            if (Time-TimePotentiometer > TIME_POTENTIOMETER)        //    
            {                                                       // draw the potentiometer value
                TimePotentiometer = Time;                           //            
                DrawPotentiometerValue(PotValue);                   //                                                                                               
            }                                                       //
        }      
        
        Buttons = in_LAB_2->Buttons;                                // read the buttons status from the slave  
                   
        if (Buttons != PrevButtons)                                 // check if the buttons value has changed
        {
            PrevButtons = Buttons;                                  // remember the current buttons value  
            
            if (VisuSlave == LAB_2)                                 // if the HMI is setted to slave 2
            {                                                       //    
                DrawButtonsValue(Buttons);                          // draw the current buttons value                                                                                              
            }                                                       //
        }
        
        if (Segments != PrevSegments)                               // check if the segments value has changed
        {                                                           
            PrevSegments = Segments;                                // remember the current segments value 
            
            if (VisuSlave == LAB_2)                                 // if the HMI is setted to slave 2
            {                                                       //    
                DrawSegmentsValue(Segments);                        // draw the current segments value                                                                                              
            }                                                       //            
        }
               
        if (VisuSlave == LAB_2 && FirstRound)                       // if the HMI is set to slave 2                                                        
        {                                                           // and it is the first time 
            FirstRound = false;                                     //                
                                                                    //
            DrawButtonsValue(Buttons);                              // draw the current buttons value         
            DrawSegmentsValue(Segments);                            // draw the current segments value            
        }    
         
           out_LAB_2->Segments = Segments;                          // send the segments status to the slave 
    
                                                            
                                                                    //----- end LAB_2 ------------------------                                                                        
                                                                          
                
        TouchScreenManagement();                                    // check if the touchscreen is tapped 
                                                                    // and handle it       
        
        Time = SysMilliS();                                         // toggle the variable Blink every
        if ((Time-TimeBlink) > TIME_BLINK)                          // TIME_BLINK mS
        {                                                           //
          TimeBlink = Time;                                         // we use it to blink a field on the TFT
          Blink = !Blink;                                           //              
        }                        
                                
        IO_data.lock();                                             // copy the IO data from the safe area
        memcpy(&IOmap[0], &IOmapSafe[0], IO_MAP_SIZE);              // to the EtherCAT buffer
        IO_data.unlock();                                           //    
        
        //Test_2 = 0;                             
    }       
}      
  

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



//******* general functions ****************************************************


//------ touchscreen management ------------------------------------------------

void TouchScreenManagement()
{                   
    uint16_t X;
    uint16_t Y;  
    int i;
    
    #if defined ADA_TFT                                             // if the touchscreen has been tapped
        if (TSC.GetPoint(&X, &Y))                                   //
    #else                                                           //
        if (TouchRead(&X, &Y))                                      //   
    #endif       
    {    
        TimeTouchReleased = SysMilliS();
        
        if(TouchWasReleased)
        {                                                           // check if it is the side menu
                                                                    // decrement slave button
            if ((X>MENU_X) && (X>MENU_X+MENU_WIDTH/2) && (Y>MENU_HEIGHT) && (Y<MENU_HEIGHT*2))
            {                                                       //
                VisuSlave--;
                
                if (VisuSlave == 0)                                 //
                    VisuSlave = SLAVE_NUM;                          //      
                                                                    // the visualized slave has changed 
                DrawSlaveFixedParts();                              // draw the new slave fixed parts   
            }                                                       //
                   
                                                                    // check if it is the side menu
                                                                    // increment slave button                                                                        
            if ((X>MENU_X) && (X<MENU_X+MENU_WIDTH/2) && (Y>MENU_HEIGHT) && (Y<MENU_HEIGHT*2))
            {                                                       //
                VisuSlave++;
                
                if (VisuSlave > SLAVE_NUM)                          //    
                    VisuSlave = LAB_1;                              //                
                                                                    // the visualized slave has changed 
                DrawSlaveFixedParts();                              // draw the new slave fixed parts     
            }                                                       //
        }        
        
        switch (VisuSlave)                                          // check which slave is visualized on the TFT
        {                      
            case (LAB_1):     //-------------- slave 1 -----------------------
            
            
                if(TouchWasReleased)                                // first check if the touch was
                {                                                   // not tapped in the previous rounds  
                    TouchWasReleased = false;                       // because for the following fields 
                    TimeTouchReleased = SysMilliS();                // we don't want autorepeat         
                    
                    TimeAutoRepeat = SysMilliS();                   // reload the autorepeat time      
            
                                                                    // handle taps on the ">" and "<" buttons
                    if ((X>ALARM_X) && (X<ALARM_X+(ALARM_WIDTH/2)) && (Y>ALARM_Y+ALARM_HEIGHT) && (Y<ALARM_Y+ALARM_HEIGHT*2))       
                    {                                               //                      
                        AlarmMinMax = true;                         //
                        DrawAlarmSettings(fAlarmThreshold, AlarmOnOff, AlarmMinMax);  
                    }                                               //    
                    if ((X>ALARM_X+(ALARM_WIDTH/2)) && (X<ALARM_X+(ALARM_WIDTH)) && (Y>ALARM_Y+ALARM_HEIGHT) && (Y<ALARM_Y+ALARM_HEIGHT*2))                                                               //
                    {                                               // 
                        AlarmMinMax = false;                        //
                        DrawAlarmSettings(fAlarmThreshold, AlarmOnOff, AlarmMinMax);  
                    }                                               
                    
                                                                    // handle taps on the "ON" and "OFF" buttons
                    if ((X>ALARM_X) && (X<ALARM_X+(ALARM_WIDTH/2)) && (Y>ALARM_Y) && (Y<ALARM_Y+ALARM_HEIGHT))       
                    {                                               //                      
                        AlarmOnOff = true;                          //
                        DrawAlarmSettings(fAlarmThreshold, AlarmOnOff, AlarmMinMax);  
                    }                                               //    
                    if ((X>ALARM_X+(ALARM_WIDTH/2)) && (X<ALARM_X+(ALARM_WIDTH)) && (Y>ALARM_Y) && (Y<ALARM_Y+ALARM_HEIGHT))                                                              
                    {                                               // 
                        AlarmOnOff = false;                         //
                        DrawAlarmSettings(fAlarmThreshold, AlarmOnOff, AlarmMinMax);  
                    }            
                                
                                                                    // handle taps on the "+" and "-" buttons
                                                                    // here we don't use the autorepeat to increment
                                                                    // or decrement the threshold by 0.1    
                    if ((X>ALARM_X) && (X<ALARM_X+(ALARM_WIDTH/2)) && (Y>ALARM_Y+(ALARM_HEIGHT*3)) && (Y<ALARM_Y+(ALARM_HEIGHT*4)))       
                    {                                               //                      
                        fAlarmThreshold += 0.1;                     //
                        DrawOnlyThreshold(fAlarmThreshold, AlarmOnOff, AlarmMinMax);  
                    }                                               //    
                    if ((X>ALARM_X+(ALARM_WIDTH/2)) && (X<ALARM_X+(ALARM_WIDTH)) && (Y>ALARM_Y+(ALARM_HEIGHT*3)) && (Y<ALARM_Y+(ALARM_HEIGHT*4)))                                                         
                    {                                               // 
                        fAlarmThreshold -= 0.1;                     //
                        DrawOnlyThreshold(fAlarmThreshold, AlarmOnOff, AlarmMinMax);  
                    }                                               //
                }
                
                else                                                // autorepeat management
                {                                                   //
                    Time = SysMilliS();                             //            
                    if (Time-TimeAutoRepeat > TIME_AUTO_REP_START)  //    
                    {                                               //
                        if (Time-TimeAutoRepRepeat > TIME_AUTO_REP_REPEAT)
                        {                                           //
                            TimeAutoRepRepeat = Time;               //
                                                                    
                                                                    // handle taps on the "+" and "-" buttons
                                                                    // here we use the autorepeat to increment
                                                                    // or decrement the threshold by 1                                                                       
                            if ((X>ALARM_X) && (X<ALARM_X+(ALARM_WIDTH/2)) && (Y>ALARM_Y+(ALARM_HEIGHT*3)) && (Y<ALARM_Y+(ALARM_HEIGHT*4)))       
                            {                                       //                      
                                fAlarmThreshold += 1;               //
                                DrawOnlyThreshold(fAlarmThreshold, AlarmOnOff, AlarmMinMax);  
                            }                                       //    
                            if ((X>ALARM_X+(ALARM_WIDTH/2)) && (X<ALARM_X+(ALARM_WIDTH)) && (Y>ALARM_Y+(ALARM_HEIGHT*3)) && (Y<ALARM_Y+(ALARM_HEIGHT*4)))                                                         
                            {                                       // 
                                fAlarmThreshold -= 1;               //
                                DrawOnlyThreshold(fAlarmThreshold, AlarmOnOff, AlarmMinMax);  
                            }   
                        }       
                    }
                }     
                 
            break;              //-------------- end slave 1 -------------------
                
         
                
            case (LAB_2):     //-------------- slave 2 -----------------------
            
                if(TouchWasReleased)                                // first check if the touch was
                {                                                   // not tapped in the previous rounds  
                    TouchWasReleased = false;                       // because for the following fields
                    TimeTouchReleased = SysMilliS();                // we don't want autorepeat
                    
                    uint8_t Mask = 0x08;                            // check if one of the segment is tapped
                                                                    //
                    for (i=0; i<4; i++)                             //
                    {                                               //        
                        if ((X>SEG_X+(i*SEG_STEP)) && (X<SEG_X+(i*SEG_STEP)+SEG_WIDTH) && (Y>SEG_Y) && (Y<SEG_Y+SEG_HEIGHT*3))                
                        {                                           //
                            Segments ^= Mask >> i;                  //
                        }                                           //  
                    }                                               //
                }                                                       
            break;              //----------------- end slave 2 ----------------                          
        }             
    }
    
    else                                                               
    {       
        if ( SysMilliS()-TimeTouchReleased > TIME_TOUCH_RELEASED)   // if the touchscreen was not
        {                                                           // tapped for enought time            
            TouchWasReleased = true;                                // remember it
            
        }      
    }          
}    

 
//----- draw the fixed part of the visualized slave ----------------------------

void DrawSlaveFixedParts()
{
    int i;
    int Offset;
    
    TFT.cls();                                                      // clear screen
    DrawSideMenu(VisuSlave);                                        // draw the side menu
                   
    switch (VisuSlave)                                              // check which slave is visualized on the TFT                                 
    {                      
        case (LAB_1):     //-------------- slave 1 ---------------------------
                                                       
            TFT.foreground(Yellow);                                 // draw the thermometer
        
            TFT.circle(TERMO_X, TERMO_Y, 18, Yellow);               // bowl
            TFT.fillcircle(TERMO_X, TERMO_Y, 17, Red);              //
                            
                                                                    // tube
            TFT.rect(TERMO_X-8, TERMO_Y-185, TERMO_X+8, TERMO_Y-18, Yellow);    
            TFT.fillrect(TERMO_X-7, TERMO_Y-18, TERMO_X+7, TERMO_Y-16, Red);   
                       
            for (i=0; i<8; i++)                                     // scale      
            {                                                       //  
                if (i <1)                                           //            
                    Offset = 5;                                     //
                else                                                //
                    Offset = 0;                                     //    
                                                                    //        
                TFT.line(TERMO_X-8, (TERMO_Y-28)-(i *20), TERMO_X-18,(TERMO_Y-28)-(i*20), Yellow);
                TFT.locate(TERMO_X-48+Offset, TERMO_Y-(i*20)-32);   //
                TFT.set_font((unsigned char*) Arial12x12);          //
                TFT.printf("%3d",(i*10)-10);                        //
            }                                                         
   
            TFT.foreground(Green);                                  //
            TFT.set_font((unsigned char*) Arial28x28);              //            
            TFT.locate(TERMO_X+25, TERMO_Y+28);                     //  
            TFT.printf("C");                                        //
                             
                                                                    // draw the alarm control panel
                                                                    
                                                                    // frame
            TFT.rect(ALARM_X, ALARM_Y, ALARM_X+ALARM_WIDTH, ALARM_Y+(ALARM_HEIGHT*4), Magenta); 
                                                                    //
            for (i=0; i<3; i++)                                     //    
            {                                                       //
                TFT.line(ALARM_X, ALARM_Y+((i+1)*ALARM_HEIGHT) , ALARM_X+ALARM_WIDTH, ALARM_Y+((i+1)*ALARM_HEIGHT), Magenta);
            }                                                       //    
                                                                    //
            TFT.line(ALARM_X+(ALARM_WIDTH/2), ALARM_Y, ALARM_X+(ALARM_WIDTH/2), ALARM_Y+(ALARM_HEIGHT*2), Magenta);
            TFT.line(ALARM_X+(ALARM_WIDTH/2), ALARM_Y+(ALARM_HEIGHT*3), ALARM_X+(ALARM_WIDTH/2), ALARM_Y+(ALARM_HEIGHT*4), Magenta);           
   
            TFT.set_font((unsigned char*) Arial28x28);              // "+" and "-"
            TFT.foreground(Green);                                  //                   
            TFT.locate(ALARM_X+11, ALARM_Y+(ALARM_HEIGHT*3)+9);     //
            TFT.printf("+");                                        //    
            TFT.locate(ALARM_X+(ALARM_WIDTH/2)+14, ALARM_Y+(ALARM_HEIGHT*3)+9);    
            TFT.printf("-");                                        //
  
                                                                    // alarm bar  
            TFT.rect(ALARM_X-30, ALARM_Y, ALARM_X-25, ALARM_Y+168, Yellow);                                 
                       
            TFT.set_font((unsigned char*) Arial12x12);              // draw "ALARM SETTINGS"   
            TFT.foreground(Yellow);                                 //                          
            TFT.locate(ALARM_X-35, ALARM_Y+14+(ALARM_HEIGHT*4));    //
            TFT.printf("ALARM SETTINGS");                           //                  
            
        break;        
           
   
           
        
        case (LAB_2):     //-------------- slave 2 ---------------------------
                
            TFT.foreground(Yellow);   

            for (i=0; i<4; i++)                                     // draw the segments fixed parts
            {                                                       //
                TFT.rect(SEG_X+(i*SEG_STEP), SEG_Y, SEG_X+SEG_WIDTH+(i*SEG_STEP), SEG_Y+SEG_HEIGHT, Yellow);                            
                                                                    //
                TFT.set_font((unsigned char*) Arial12x12);          // 
                TFT.locate(SEG_X+44, SEG_Y+SEG_HEIGHT+12);          // 
                TFT.printf("MIDDLE SEGMENTS");                      //
            }                                                       //
               
            for (i=0; i<3; i++)                                     // draw the buttons fixed parts        
            {                                                       //    
                TFT.circle(BUTTONS_X+(i*BUTTONS_STEP), BUTTONS_Y, BUTTONS_R, Red);                
                TFT.circle(BUTTONS_X+BUTTONS_WIDTH+(i*BUTTONS_STEP), BUTTONS_Y, BUTTONS_R, Red); 
                                                                    //
                TFT.line(BUTTONS_X+(i*BUTTONS_STEP)-BUTTONS_R, BUTTONS_Y, BUTTONS_X+(i*BUTTONS_STEP)-BUTTONS_R-4, BUTTONS_Y, Red);  
                TFT.line(BUTTONS_X+BUTTONS_WIDTH+(i*BUTTONS_STEP)+BUTTONS_R, BUTTONS_Y, BUTTONS_X+BUTTONS_WIDTH+(i*BUTTONS_STEP)+BUTTONS_R+4 , BUTTONS_Y, Red);                          
            }                                                       //
                                                                    //   
            TFT.set_font((unsigned char*) Arial12x12);              // 
            TFT.locate(BUTTONS_X+38, BUTTONS_Y+12);                 // 
            TFT.printf("BUTTONS");                                  //               
      
                                                                    // draw the potentiometer window fixed parts
            TFT.rect(ANALOG_X, ANALOG_Y, ANALOG_X+ANALOG_WIDTH, ANALOG_Y+ANALOG_HEIGHT, Magenta); 
                                                                    //
            TFT.set_font((unsigned char*) Arial12x12);              // 
            TFT.locate(ANALOG_X+35, ANALOG_Y+ANALOG_HEIGHT+12);     // 
            TFT.printf("POTENTIOMETER");                            // 
            
            Graph_x = 0;                    
            
            DrawSegmentsValue(Segments);                            // draw the segments status 
            DrawButtonsValue (Buttons);                             // draw the buttons status  
            DrawPotentiometerValue(PotValue);                       // draw the potentiometer value                  
        break;                               
    }    
    
    FirstRound = true;                
}    


//---- draw the menu on the upper right part of the TFT ------------------------

void DrawSideMenu(uint8_t Slave)
{                                                                   // draw the side menu frame
    TFT.rect(MENU_X, MENU_Y, MENU_X+MENU_WIDTH, MENU_Y+MENU_HEIGHT*2, Green);  
    TFT.line(MENU_X, MENU_HEIGHT, MENU_X+MENU_WIDTH, MENU_HEIGHT, Green);    
    TFT.line(MENU_X+(MENU_WIDTH/2), MENU_Y+MENU_HEIGHT, MENU_X+(MENU_WIDTH/2), MENU_Y+(MENU_HEIGHT*2), Green);
                                                                                
                                                                    // draw the slave number
    TFT.fillrect(MENU_X+1, MENU_Y+1, MENU_X+MENU_WIDTH-1, MENU_Y+MENU_HEIGHT-1, Red);    
    TFT.set_font((unsigned char*) Arial12x12);                      //
    TFT.foreground(Yellow);                                         //        
    TFT.locate(MENU_X+8 , MENU_Y+18);                               //
    TFT.background(Red);                                            //
    TFT.printf("SLAVE %d", Slave);                                  //
    TFT.background(Black);                                          //
                                                                              
    TFT.set_font((unsigned char*) Arial28x28);                      // draw "+" and "-"   
    TFT.foreground(Green);                                          //                                                                                   
    TFT.locate (MENU_X+11, MENU_Y+MENU_HEIGHT+9);                   //      
    TFT.printf("+");                                                //                                                                                
    TFT.locate (MENU_X+(MENU_WIDTH/2)+14, MENU_Y+MENU_HEIGHT+9);    //
    TFT.printf("-");                                                //
 
    TFT.set_font((unsigned char*) Arial12x12);                      // draw the slave name
    TFT.foreground(Red);                                            //
                                                                    //
    TFT.locate(MENU_X, MENU_Y+(MENU_HEIGHT*2)+12);                  //
    TFT.printf("%.9s", ec_slave[Slave].name);                       //
}  


//---- draw the starting banner ------------------------------------------------

void DrawBanner()
{
    TFT.set_font((unsigned char*) Arial24x23);
    TFT.foreground(Red);
    TFT.locate(30, 50);
    TFT.printf("EasyCAT");
    TFT.locate(30, 80);
    TFT.printf("SOEM MASTER");    
    
    TFT.set_font((unsigned char*) Arial12x12);
    TFT.foreground(Green);
    TFT.locate(30, 140);
    TFT.printf("www.bausano.net");

    TFT.foreground(Green);
    TFT.locate(30, 160);
    TFT.printf("www.easycatshield.com"); 
    
    TFT.locate(30, 180);
    TFT.printf("https://openethercatsociety.github.io/"); 
    
    TFT.foreground(Red);    
    TFT.locate(30, 220);    
    #if defined ADA_TFT                                 
        TFT.printf("Adafruit TFT");   
    #else
        TFT.printf("Seeed Studio TFT");
    #endif          
}  



//****** slave 1 functions *****************************************************

//---- draw the temperature value both in analog and in digital form ------------

void DrawTemperatureValue(float fValue)
{                 
    TFT.set_font((unsigned char*) Arial28x28);                      // digital visualization       
    TFT.foreground(Green);                                          //
    TFT.locate(TERMO_X-45, TERMO_Y+28);                             //
    TFT.printf("%4.1f", fValue);                                    //
        
    if (fValue > 68)                                                // limit the value for the
        fValue = 68;                                                // analog visualization    
                                                                    //
    if (fValue < -15)                                               //
        fValue = -15;                                               //
            
    int LenColonnina = fValue * 2;                                  // analog visualization   
    TFT.fillrect(TERMO_X-7, TERMO_Y-184, TERMO_X+7, TERMO_Y-18-LenColonnina-30-1, Black);                             
    TFT.fillrect(TERMO_X-7, TERMO_Y-18-LenColonnina-30, TERMO_X+7, TERMO_Y-18, Red);
}   


//---- draw the current parameter of the temperature alarm ---------------------

void DrawAlarmSettings(float fThreshold, bool OnOff, bool MinMax)
{ 
   
    if (OnOff)                                                      // alarm on    
    {                                                               // draw "ON" on red background
                                                                    // and "OFF"" on black background
        DisplayInRect (ALARM_X, ALARM_Y, 10, 14, "ON", Red, (unsigned char*)Arial12x12);       
        DisplayInRect (ALARM_X+(ALARM_WIDTH/2), ALARM_Y, 10, 14, "OFF", Black, (unsigned char*)Arial12x12);
    }                                                                   
    else                                                            // alarm off             
    {                                                               // and "ON"" on black background 
                                                                    // draw "OFF" on red background
        DisplayInRect (ALARM_X, ALARM_Y, 10, 14, "ON", Black, (unsigned char*)Arial12x12);       
        DisplayInRect (ALARM_X+(ALARM_WIDTH/2), ALARM_Y, 10, 14, "OFF", Red, (unsigned char*)Arial12x12);                    
    }      
    
    
    if (MinMax)                                                     // alarm when temperature < threshold
    {                                                               // draw ">" on red background
                                                                    // and ">"" on black background 
        DisplayInRect (ALARM_X, ALARM_Y+ALARM_HEIGHT, 10, 9, ">", Red, (unsigned char*)Arial28x28);       
        DisplayInRect (ALARM_X+(ALARM_WIDTH/2), ALARM_Y+ALARM_HEIGHT, 10, 9, "<", Black, (unsigned char*)Arial28x28);
    }                                                               
    else                                                            // alarm when temperature > threshold
    {                                                               // draw ">" on black background
                                                                    // and ">"" on red background
        DisplayInRect (ALARM_X, ALARM_Y+ALARM_HEIGHT, 10, 9, ">", Black, (unsigned char*)Arial28x28);       
        DisplayInRect (ALARM_X+(ALARM_WIDTH/2), ALARM_Y+ALARM_HEIGHT, 10, 9, "<", Red, (unsigned char*)Arial28x28);
    }        

    DrawOnlyThreshold(fThreshold, OnOff, MinMax);
}    


//---- draw only the threshold setting -----------------------------------------

void DrawOnlyThreshold(float fThreshold, bool OnOff, bool MinMax)   // this function is used to update
{                                                                   // only the threshold value not to
                                                                    // flicker the TFT, when "+" or
                                                                    // "-" are tapped   
                                                                    
    TFT.foreground(Yellow);                                         // draw the alarm threshold    
    TFT.set_font((unsigned char*) Arial12x12);                      // in digital form
    TFT.locate(ALARM_X+26, ALARM_Y+14+(ALARM_HEIGHT*2));            // 
    TFT.printf("     ");                                            //    
    TFT.locate(ALARM_X+26, ALARM_Y+14+(ALARM_HEIGHT*2));            // 
    TFT.printf("%+3.1f", fThreshold);                               //                                                                        
                                                                    
    if (fThreshold > 68)                                            // limit the value for the
        fThreshold = 68;                                            // analog visualization
                                                                    //
    if (fThreshold < -15)                                           //
        fThreshold = -15;                                           //                        
                                                                                                                                        
    int LenAlarmBar = fThreshold * 2;    
  
    if (OnOff)                                                      // alarm on    
    {                                                               //    
        if (MinMax)                                                 // fill the threshold bar
        {                                                           // in accordance with the MinMax setting
            TFT.fillrect(ALARM_X-29, ALARM_Y+1, ALARM_X-26, ALARM_Y+167-LenAlarmBar-30, Green);          
            TFT.fillrect(ALARM_X-29, ALARM_Y+167-LenAlarmBar-30, ALARM_X-26, ALARM_Y+167, Red);               
        }                                                           //                                                           
        else                                                        //    
        {                                                           //
            TFT.fillrect(ALARM_X-29, ALARM_Y+1, ALARM_X-26, ALARM_Y+167-LenAlarmBar-30, Red);          
            TFT.fillrect(ALARM_X-29, ALARM_Y+167-LenAlarmBar-30, ALARM_X-26, ALARM_Y+167, Green);              
        }                                                           //                                                      
    }                                                                   
                                                                     
    else                                                            // alarm off             
    {                                                               //
                                                                    // clear the threshold bar
        TFT.fillrect(ALARM_X-29, ALARM_Y+1, ALARM_X-26, ALARM_Y+167, Black);                      
    }                                                               //                        
}    


//---- draw the blinking alarm signal ------------------------------------------

void DrawAlarmStatus(bool Alarm)
{              
    bool static PrevAlarmVisu;
                                            
    TFT.set_font((unsigned char*) Arial28x28);  
    TFT.foreground(Red);                        
    TFT.locate(TERMO_X+90, TERMO_Y+28); 
             
    if (Alarm && Blink && !PrevAlarmVisu)
    {
        TFT.printf("ALARM !");                         
        PrevAlarmVisu = true;               
    }
    else if ((!Alarm && PrevAlarmVisu) || (Alarm && !Blink && PrevAlarmVisu))
    {
        TFT.printf("       ");
        PrevAlarmVisu = false;         
    }             
}    


//----- draw a rectangle with text and colored background ----------------------
   
void DisplayInRect (int X, int Y, int X_off, int Y_off, char* Value, int BackColor, unsigned char* Font)
{
    TFT.set_font(Font);
    TFT.foreground(Green);     
 
    TFT.fillrect(X+1, Y+1, X+(MENU_WIDTH/2)-1, Y+MENU_HEIGHT-1, BackColor);
    
    TFT.locate(X+X_off , Y+Y_off); 
    TFT.background(BackColor); 
    TFT.printf("%s", Value );  
    TFT.background(Black);     
}    




//****** slave 2 functions *****************************************************

//------------------------------------------------------------------------------

void DrawButtonsValue (uint8_t Value)
{
    uint8_t Slope;
    int i;
  
    for (i=0; i<3; i++)
    {
        if ((Value & 0x04) == 0x04)
            Slope = BUTTONS_R;
        else
            Slope = 16;          
    
        TFT.fillrect(BUTTONS_X+(i*BUTTONS_STEP), BUTTONS_Y-16-1, BUTTONS_X+BUTTONS_WIDTH+(i*BUTTONS_STEP), BUTTONS_Y-BUTTONS_R-1, Black);
    
        TFT.line(BUTTONS_X+(i*BUTTONS_STEP), BUTTONS_Y-BUTTONS_R-1, BUTTONS_X+BUTTONS_WIDTH+(i*BUTTONS_STEP), BUTTONS_Y-Slope-1, Red); 

        Value = Value << 1;    
    } 
}    


//------------------------------------------------------------------------------

void DrawSegmentsValue(uint8_t Value)
{
    int i;
    int Color;
   
    for (i=0; i<4; i++)
    {
        if ((Value & 0x08) == 0x08)
            Color = Red;
        else
            Color = Black;    
        
        TFT.fillrect(SEG_X+(i*SEG_STEP)+1, SEG_Y+1, SEG_X+SEG_WIDTH+(i*SEG_STEP)-1, SEG_Y+SEG_HEIGHT-1, Color);   
    
        Value = Value << 1;   
    } 
}    


//---- draw the potentiometer value --------------------------------------------

void DrawPotentiometerValue (uint16_t PotValue)
{
    
    if (PotValue != PrevPotValue)
    {
        PrevPotValue = PotValue;
 
        TFT.set_font((unsigned char*) Arial12x12);              // 
        TFT.foreground(Green);                                  //            
        TFT.locate(ANALOG_X+170, ANALOG_Y+ANALOG_HEIGHT+12);    // 
        TFT.printf("%4d", (int)PotValue);                  //  
    }             
    
    
    if (++Graph_x > ANALOG_WIDTH-3)
    {
        Graph_x = 0;     
    }
    
    PotValue = PotValue / (1023/(ANALOG_HEIGHT-2)); 
                  
    TFT.pixel(ANALOG_X+Graph_x+1, ANALOG_Y+ANALOG_HEIGHT-PotValue-1, Green);       
    
    int Overflow = (ANALOG_WIDTH-2) - (Graph_x+16);
    if (Overflow < 0)
    {
        TFT.fillrect(ANALOG_X+Graph_x+2, ANALOG_Y+1, ANALOG_X+Graph_x+16+Overflow, ANALOG_Y+ANALOG_HEIGHT-1, Black);              
        TFT.fillrect(ANALOG_X+1, ANALOG_Y+1, ANALOG_X+1-Overflow, ANALOG_Y+ANALOG_HEIGHT-1, Black);                    
    } 
    else
    {
        TFT.fillrect(ANALOG_X+Graph_x+2, ANALOG_Y+1, ANALOG_X+Graph_x+16, ANALOG_Y+ANALOG_HEIGHT-1, Black);                 
    }                                                       
}


//****** touchscreen functions *************************************************

//----- read touchscreen status ------------------------------------------------

bool TouchRead(uint16_t* X, uint16_t* Y)                        
{
    bool Result = false;
      
    {                                       
        if (TouchRead_Z())                      // if the touchscreen is tapped
        {                                       //
            *X = TouchRead_X();                 // read also the X and Y axis
            *Y = TouchRead_Y();                 //
            
            wait_us (1000);
                                            
            if (TouchRead_Z())                  // if the touchscreen is still tapped
            {                                   // we assume that the result is good        
                Result = true;                  //
                
              //  TFT.pixel (*X, *Y, White);      //debug - draw the touched point on the TFT
            }
        }                          
    }              

   return Result;                         
}   


//----- read touchscreen X axis ------------------------------------------------

uint16_t TouchRead_X()
{ 
    float fValue;
      
    DigitalIn  Ym(PIN_YM);                      // set the I/O
    Ym.mode(PullDown);                          //
                                                //
    DigitalOut Xp(PIN_XP);                      //
    Xp = 1;                                     //
                                                //        
    DigitalOut Xm(PIN_XM);                      //
    Xm = 0;                                     //
                                                //
    AnalogIn Yp(PIN_YP);                        //
            
    fValue = ReadAnalog(Yp);                    // read the axis
    
    fValue -= TOUCH_X_OFFSET;                   // rectify offsett and gain
    if (fValue <0 )                             //
        fValue = 0;                             //
                                                //
    fValue *= TOUCH_X_GAIN;                     //
                                         
    return (uint16_t)fValue;
}


//----- read touchscreen Y axis ------------------------------------------------

uint16_t TouchRead_Y()
{ 
    float fValue;
      
    DigitalIn Xm(PIN_XM);                       // set the I/O
    Xm.mode(PullDown);                          //
                                                //            
    DigitalOut Yp(PIN_YP);                      //
    Yp = 1;                                     //
                                                //
    DigitalOut Ym(PIN_YM);                      //
    Ym = 0;                                     //
                                                //
    AnalogIn Xp(PIN_XP);                        //
                
    fValue = ReadAnalog(Xp);                    // read the axis
                      
    fValue -= TOUCH_Y_OFFSET;                   // rectify offset and gain 
    if (fValue <0 )                             // 
        fValue = 0;                             //
                                                //
    fValue *= TOUCH_Y_GAIN;                     //    
                                 
    return (uint16_t)fValue;
}


//----- read touchscreen Z axis ------------------------------------------------

bool TouchRead_Z()                              // read the Z axis to see if the 
{                                               // touchscreen has been tapped            
    float fValue = 0;    
    bool Result;
                                                  
    DigitalIn  Yp(PIN_YP);                      // set the I/O
    Yp.mode(PullUp);                            //
                                                //
    AnalogIn Ym(PIN_YM);                        //
                                                //
    DigitalOut Xm(PIN_XM);                      //    
    Xm = 0;                                     //
                                                //    
    DigitalOut Xp(PIN_XP);                      //
    Xp = 0;                                     //
                                                   
    for (int i = 0; i<TOUCH_SAMPLES; i++)       // read the axis several times    
    {                                           // and average the result
        wait_us(10);                            //
                                                //
        fValue += Ym.read();                    //
    }                                           //
    fValue /= TOUCH_SAMPLES;                    //
    
    if (fValue < TOUCH_THRESHOLD)               // compare the result with
        Result = true;                          // the threshold
    else                                        //
        Result = false;                         //

    return Result;                              //
}


//----- read touchscreen X or Y axis with a window filter ----------------------

float ReadAnalog (AnalogIn AnaCh)               // check that consecutive readings
{                                               // fall in the acceptance window
    float fArray[TOUCH_SAMPLES];                // 
    float fResult;
    float fDiff;
    
    int Rounds = TOUCH_MAX_ROUNDS;              // maximum number of attempts
        
    for (int i=0; i<TOUCH_SAMPLES; i++)         
    {        
        wait_us(10);
    
        fResult = AnaCh.read(); 
       
        if (i>0)
        {
            fDiff = abs(fResult - fArray[i-1]);
                    
            if (fDiff > TOUCH_WINDOW)
                i= -1;
            else
                fArray[i] = fResult; 
                                
            if (Rounds-- < 0) 
            { 
                fResult = 0;
                return fResult;       
            }    
        }                   
        
        else
        {
            fArray[i] = fResult;          
        }         
    }             
         
    fResult =0;
    
    for (int i=0; i<TOUCH_SAMPLES; i++)
    {        
        fResult += fArray[i];       
    }            

    return fResult /= TOUCH_SAMPLES;    
}