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 .
- It is provided as a kit by AB&T Tecnologie Informatiche, to allow everybody to have an educational EtherCAT® system up and running in a matter of minutes.
- This repository contains a demo software for the EtherCAT® master, that runs on the Nucleo STM32F767ZI board.
- It uses the SOEM (Simple Open EtherCAT® Master) library by rt-labs, that has been ported in the ecosystem by AB&T Tecnologie Informatiche.
- The slaves are based on the EasyCAT SHIELD and the Arduino UNO.
Diff: main.cpp
- 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; +} + + +