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

Revision:
0:7077d8f28b3e
Child:
2:7d4fd6354015
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Tue Jun 11 10:19:08 2019 +0000
@@ -0,0 +1,1525 @@
+//********************************************************************************************    
+//                                                                                           *
+// 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 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"
+
+#define CYCLE_TIME 1000                 // master cycle time in uS                    
+                                        // 1000 = 1mS 
+
+                                  
+#define SysMilliS() (uint32_t)Kernel::get_ms_count()                                      
+
+Serial 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/ 
+
+#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                         //
+#define PIN_CS_TFT      D5                          //
+#define PIN_DC_TFT      D6                          //
+
+
+//---- 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
+
+/*
+//---- slave 3 parameters - EL2004 ---------------------------------------------
+
+#define OUT_X 0                     
+#define OUT_Y 65                     
+#define OUT_WIDTH 42                
+#define OUT_HEIGHT 42               
+#define OUT_STEP 60                     
+
+
+//---- slave 4 parameters - EL1014 ---------------------------------------------
+
+#define INPUTS_X 12
+#define INPUTS_Y 84 
+#define INPUTS_WIDTH 26
+#define INPUTS_R 3
+#define INPUTS_STEP 60 
+*/
+
+
+//---- 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);
+
+void DrawOutputsValue(uint8_t Value);
+
+void DrawInputsValue(uint8_t Value);
+
+
+
+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);
+
+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();                                                      //
+    TFT.set_orientation(3);                                         // 
+
+    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 ------------------------                                                                        
+                                                                          
+    
+    /*
+                                                                    //----- slave 3 EL2004 data management -----  
+                                                                
+        if (Outputs != PrevOutputs)                                 // check if the outputs value has changed
+        {                                                           
+            PrevOutputs = Outputs;                                  // remember the current outputs value 
+            
+            if (VisuSlave == EL2004)                                // if the HMI is setted to slave 3
+            {                                                       //    
+                DrawOutputsValue(Outputs);                          // draw the current Outputs value                                                                                              
+            }                                                       //            
+        }
+               
+        if (VisuSlave == EL2004 && FirstRound)                      // if the HMI is set to slave 3                                                        
+        {                                                           // and it is the first time 
+            FirstRound = false;                                     //                
+                                                                    //       
+            DrawOutputsValue(Outputs);                              // draw the current Outputs value            
+        }    
+                    
+        if (Outputs & 0x01)                                         // send the Outputs status to the slave        
+            out_EL2004->Out_0 = 1;                                  //   
+        else                                                        //        
+            out_EL2004->Out_0 = 0;                                  //
+        if (Outputs & 0x02)                                         //
+            out_EL2004->Out_1 = 1;                                  //
+        else                                                        //
+            out_EL2004->Out_1 = 0;                                  //
+        if (Outputs & 0x04)                                         //
+            out_EL2004->Out_2 = 1;                                  //
+        else                                                        //
+            out_EL2004->Out_2 = 0;                                  //
+        if (Outputs & 0x08)                                         //
+            out_EL2004->Out_3 = 1;                                  //
+        else                                                        //
+            out_EL2004->Out_3 = 0;                                  //
+        
+                                                                    //----- end EL2004 -----------------------               
+              
+            
+                                                                    //----- slave 4 EL1014 data management -----              
+        Inputs = 0;
+        if (in_EL1014->In_0)                                        // read the inputs status from the slave 
+            Inputs |= 0x01;                                         //                
+        if (in_EL1014->In_1)                                        //      
+            Inputs |= 0x02;                                         //    
+        if (in_EL1014->In_2)                                        //
+            Inputs |= 0x04;                                         //
+        if (in_EL1014->In_3)                                        //
+            Inputs |= 0x08;                                         //     
+                   
+        if (Inputs != PrevInputs)                                   // check if the inputs value has changed
+        {
+            PrevInputs = Inputs;                                    // remember the current inputs value  
+            
+            if (VisuSlave == EL1014)                                // if the HMI is setted to slave 4
+            {                                                       //    
+                DrawInputsValue(Inputs);                            // draw the current inputs value                                                                                              
+            }                                                       //
+        }                                               
+                                                                    //----- end EL1014 -----------------------         
+    */               
+            
+        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 (TouchRead(&X, &Y))                                          // the touchscreen has been tapped
+    {    
+        TimeTouchReleased = SysMilliS();
+                                                                    // 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 ----------------                          
+
+      
+ /*       
+            case (EL2004):     //-------------- slave 3 EL2004 ----------------        
+        
+        
+                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 output is tapped
+                                                                    //
+                    for (i=0; i<4; i++)                             //
+                    {                                               //        
+                        if ((X>OUT_X+(i*OUT_STEP)) && (X<OUT_X+(i*OUT_STEP)+OUT_WIDTH) && (Y>OUT_Y) && (Y<OUT_Y+OUT_HEIGHT))                
+                        {                                           //
+                            Outputs ^= Mask >> i;                   //
+                        }                                           //  
+                    }                                               //
+                }  
+*/                                                                                                  
+        }             
+    }
+    
+    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;     
+
+/*
+        case (EK1100):     //-------------- slave 3 EK1100 --------------------
+
+            TFT.foreground(Red);   
+            TFT.set_font((unsigned char*) Arial12x12);
+            TFT.locate(0, MENU_Y+(MENU_HEIGHT*2)+12);
+
+            TFT.printf("This slave has no Input/Output:");
+
+        break;
+
+     
+        case (EL2004):     //-------------- slave 4 EL2004 --------------------
+                
+            TFT.foreground(Yellow);   
+
+            for (i=0; i<4; i++)                                     // draw the outputs fixed parts
+            {                                                       //
+                TFT.rect(OUT_X+(i*OUT_STEP), OUT_Y, OUT_X+OUT_WIDTH+(i*OUT_STEP), OUT_Y+OUT_HEIGHT, Yellow);                            
+                                                                    //
+                TFT.set_font((unsigned char*) Arial12x12);          // 
+                TFT.locate(OUT_X+45, OUT_Y+OUT_HEIGHT+40);          // 
+                TFT.printf("DIGITAL OUTPUTS");                      //
+            }                                                       //
+            
+            DrawOutputsValue(Outputs);                              // draw the outputs status           
+        break;           
+        
+        case (EL1014):     //-------------- slave 5 EL1014 --------------------
+                   
+            TFT.foreground(Yellow);   
+
+               
+            for (i=0; i<4; i++)                                     // draw the inputs fixed parts        
+            {                                                       //    
+                TFT.circle(INPUTS_X+(i*INPUTS_STEP), INPUTS_Y, INPUTS_R, Red);                
+                TFT.circle(INPUTS_X+INPUTS_WIDTH+(i*INPUTS_STEP), INPUTS_Y, INPUTS_R, Red); 
+                                                                    //
+                TFT.line(INPUTS_X+(i*INPUTS_STEP)-INPUTS_R, INPUTS_Y, INPUTS_X+(i*INPUTS_STEP)-INPUTS_R-4, INPUTS_Y, Red);  
+                TFT.line(INPUTS_X+INPUTS_WIDTH+(i*INPUTS_STEP)+INPUTS_R, INPUTS_Y, INPUTS_X+INPUTS_WIDTH+(i*INPUTS_STEP)+INPUTS_R+4 , INPUTS_Y, Red);                          
+            }                                                       //
+                                                                    //   
+            TFT.set_font((unsigned char*) Arial12x12);              // 
+            TFT.locate(INPUTS_X+45, INPUTS_Y+40);                   // 
+            TFT.printf("DIGITAL INPUTS");                           //               
+
+            DrawInputsValue (Inputs);                               // draw the inputs status               
+        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/");     
+}  
+
+
+
+//****** 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);                 
+    }                                                       
+}
+
+
+//****** slave 3 functions EL2004 **********************************************
+/*
+
+//------------------------------------------------------------------------------
+
+void DrawOutputsValue(uint8_t Value)
+{
+    int i;
+    int Color;
+   
+    for (i=0; i<4; i++)
+    {
+        if ((Value & 0x08) == 0x08)
+            Color = Green;
+        else
+            Color = Black;    
+        
+        TFT.fillrect(OUT_X+(i*OUT_STEP)+1, OUT_Y+1, OUT_X+OUT_WIDTH+(i*OUT_STEP)-1, OUT_Y+OUT_HEIGHT-1, Color);   
+    
+        Value = Value << 1;   
+    } 
+}    
+
+//****** slave 4 functions *****************************************************
+
+//------------------------------------------------------------------------------
+
+void DrawInputsValue (uint8_t Value)
+{
+    uint8_t Slope;
+    int i;
+  
+    for (i=0; i<4; i++)
+    {
+        if ((Value & 0x08) == 0x08)
+            Slope = INPUTS_R;
+        else
+            Slope = 16;          
+    
+        TFT.fillrect(INPUTS_X+(i*INPUTS_STEP), INPUTS_Y-16-1, INPUTS_X+INPUTS_WIDTH+(i*INPUTS_STEP), INPUTS_Y-INPUTS_R-1, Black);
+    
+        TFT.line(INPUTS_X+(i*INPUTS_STEP), INPUTS_Y-INPUTS_R-1, INPUTS_X+INPUTS_WIDTH+(i*INPUTS_STEP), INPUTS_Y-Slope-1, Red); 
+
+        Value = Value << 1;    
+    } 
+}    
+*/
+
+
+//****** 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;    
+}    
+
+
+