Ahmed HADDAD / EasyCAT_lib

Dependents:   MOTION_LCD

Files at this revision

API Documentation at this revision

Comitter:
EasyCAT
Date:
Tue Sep 12 17:09:43 2017 +0000
Child:
1:47eefd835111
Child:
4:66867fae2256
Commit message:
first release

Changed in this revision

EasyCAT.cpp Show annotated file Show diff for this revision Revisions of this file
EasyCAT.h Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/EasyCAT.cpp	Tue Sep 12 17:09:43 2017 +0000
@@ -0,0 +1,584 @@
+//********************************************************************************************
+//                                                                                           *
+// AB&T Tecnologie Informatiche - Ivrea Italy                                                *
+// http://www.bausano.net                                                                    *
+// https://www.ethercat.org/en/products/791FFAA126AD43859920EA64384AD4FD.htm                 *
+//                                                                                           *  
+//********************************************************************************************    
+//                                                                                           *
+// This software is distributed as an example, in the hope that it could be useful,          *
+// WITHOUT ANY WARRANTY, even the implied warranty of FITNESS FOR A PARTICULAR PURPOSE       *
+//                                                                                           *
+//******************************************************************************************** 
+
+
+//----- EasyCAT library for mbed boards -----------------------------------------------------
+//----- Derived from the AB&T EasyCAT Arduino shield library V 1.5 170912--------------------------
+
+//----- Tested with the STM32 NUCLEO-F767ZI board -------------------------------------------
+
+
+
+#include "mbed.h"
+#include "EasyCAT.h"                         
+
+
+DigitalOut * SpiCs;								 	
+SPI Spi(D11, D12, D13);                          // declare MOSI MISO SCK 
+
+
+#define SCS_Low_macro  (*SpiCs = 0);			// macro for set/reset SPI chip select
+#define SCS_High_macro (*SpiCs = 1);			//
+
+												// macro for the SPI transfer		
+inline static void SPI_TransferTx (unsigned char Data) 
+{                                               //
+	Spi.write(Data);                            //
+};                                              //
+                                                //
+inline static void SPI_TransferTxLast (unsigned char Data) 
+{                                               //
+	Spi.write(Data);                            // 
+};                                              //
+                                                //
+inline static unsigned char SPI_TransferRx (unsigned char Data) 
+{                                               //
+	return Spi.write(Data);                     //
+};	                                            //
+
+
+  
+//---- constructors --------------------------------------------------------------------------------
+
+EasyCAT::EasyCAT()                              //------- default constructor ---------------------- 
+{                                               // 
+  Sync_ = ASYNC;                                // if no synchronization mode is declared
+                                                // ASYNC is the default
+                                                //
+  SCS_ = (PinName)D9;                           // if no chip select is declared                 
+  SpiCs = new DigitalOut(SCS_, 1);              // pin D9 is the default  
+}                                               //
+
+
+EasyCAT::EasyCAT(PinName SCS) 					//------- SPI_CHIP_SELECT options -----------------
+                                                //
+                                                // for EasyCAT board REV_A we can choose between:
+                                                // D8, D9, D10
+                                                //  
+                                                // for EasyCAT board REV_B we have three additional options:
+                                                // A5, D6, D7 
+{                                       
+  SCS_ = SCS;                                   //  initialize chip select  
+  SpiCs = new DigitalOut(SCS_, 1);				//
+}                                               // 
+
+
+EasyCAT::EasyCAT(SyncMode Sync)                 //-------Synchronization options ---------------------- 
+                                                //   
+                                                // we can choose between:
+                                                // ASYNC   = free running i.e. no synchronization
+                                                //           between master and slave (default)   
+                                                //
+                                                // DC_SYNC = interrupt is generated from the
+                                                //           Distributed clock unit
+                                                //
+                                                // SM_SYNC = interrupt is generated from the
+                                                //           Syncronizatiom manager 2 
+{                                               //
+  Sync_ = Sync;                                 //                                           
+                                                //                                        
+  SCS_ = (PinName)D9;                           // default chip select is pin 9 
+  SpiCs = new DigitalOut(SCS_, 1);              //
+}                                               //  
+
+
+                                                //-- Synchronization and chip select options -----  
+EasyCAT::EasyCAT(PinName SCS, SyncMode Sync) 	//
+												//				
+{                                               //
+  Sync_ = Sync;                                 //  
+                                                //   
+  SCS_ = SCS;                                   //  initialize chip select                                                 
+  SpiCs = new DigitalOut(SCS_, 1);              // 
+}                                               //  
+
+
+  
+//---- EasyCAT board initialization ---------------------------------------------------------------
+
+
+bool EasyCAT::Init()
+{
+  #define Tout 1000
+  
+  ULONG TempLong;
+  unsigned short i;
+   
+  Spi.frequency(14000000);						          // SPI speed 14MHz  
+  Spi.format(8,0);	  							          // 8 bit mode 0
+  
+  wait_ms(100);
+ 
+  SPIWriteRegisterDirect (RESET_CTL, DIGITAL_RST);        // LAN9252 reset 
+   
+  i = 0;                                                  // reset timeout 
+  do                                                      // wait for reset to complete
+  {                                                       //
+    i++;                                                  //
+    TempLong.Long = SPIReadRegisterDirect (RESET_CTL, 4); //
+  }while (((TempLong.Byte[0] & 0x01) != 0x00) && (i != Tout));    
+                                                          //                                                       
+  if (i == Tout)                                          // time out expired      
+  {                                                       //   
+    return false;                                         // initialization failed  
+  }                                                         
+  
+  i = 0;                                                  // reset timeout  
+  do                                                      // check the Byte Order Test Register
+  {                                                       //
+    i++;                                                  //      
+    TempLong.Long = SPIReadRegisterDirect (BYTE_TEST, 4); //
+  }while ((TempLong.Long != 0x87654321) && (i != Tout));  //    
+                                                          //                                                            
+  if (i == Tout)                                          // time out expired      
+  {                                                       // 
+    return false;                                         // initialization failed  
+  }            
+  
+  i = 0;                                                  // reset timeout  
+  do                                                      // check the Ready flag
+  {                                                       //
+    i++;                                                  //    
+    TempLong.Long = SPIReadRegisterDirect (HW_CFG, 4);    //
+  }while (((TempLong.Byte[3] & READY) == 0) && (i != Tout));//
+                                                          //
+  if (i == Tout)                                          // time out expired      
+  {                                                       //
+    return false;                                         // initialization failed  
+  }            
+  
+
+  
+#ifdef BYTE_NUM
+  printf ("STANDARD MODE\n"); 
+#else
+  printf ("CUSTOM MODE\n"); 
+#endif
+
+  printf ("%u Byte Out\n",TOT_BYTE_NUM_OUT);  
+  printf ("%u Byte In\n",TOT_BYTE_NUM_IN);      
+
+  printf ("Sync = ");                                                              
+                                                            
+                                                          
+  if ((Sync_ == DC_SYNC) || (Sync_ == SM_SYNC))           //--- if requested, enable --------   
+  {                                                       //--- interrupt generation -------- 
+  
+    if (Sync_ == DC_SYNC)
+    {                                                     // enable interrupt from SYNC 0
+      SPIWriteRegisterIndirect (0x00000004, AL_EVENT_MASK, 4);  
+                                                          // in AL event mask register, and disable 
+                                                          // other interrupt sources    
+      printf("DC_SYNC\n");                                                      
+    }                                                       
+                                                                                                         
+    else
+    {                                                     // enable interrupt from SM 0 event
+      SPIWriteRegisterIndirect (0x00000100, AL_EVENT_MASK, 4);  
+                                                          // in AL event mask register, and disable 
+                                                          // other interrupt sources 
+      printf("SM_SYNC\n");    
+    }   
+                                                         
+    SPIWriteRegisterDirect (IRQ_CFG, 0x00000111);         // set LAN9252 interrupt pin driver  
+                                                          // as push-pull active high
+                                                          // (On the EasyCAT shield board the IRQ pin
+                                                          // is inverted by a mosfet, so Arduino                                                        
+                                                          // receives an active low signal)
+                                                                        
+    SPIWriteRegisterDirect (INT_EN, 0x00000001);          // enable LAN9252 interrupt      
+  } 
+
+  else
+  {
+    printf("ASYNC\n");
+  }
+  
+
+  TempLong.Long = SPIReadRegisterDirect (ID_REV, 4);      // read the chip identification 
+  printf ("Detected chip ");                     		  // and revision, and print it
+  printf ("%x ", TempLong.Word[1]);                       // out on the serial line
+  printf (" Rev ");                                       //    
+  printf ("%u \n", TempLong.Word[0]);                     //    
+  
+  
+ /* 
+  printf ("%u \n", TOT_BYTE_NUM_OUT); 
+  printf ("%u \n", BYTE_NUM_OUT);                   
+  printf ("%u \n", BYTE_NUM_ROUND_OUT);                
+  printf ("%u \n", LONG_NUM_OUT);                  
+     
+  printf ("%u \n", SEC_BYTE_NUM_OUT);                    
+  printf ("%u \n", SEC_BYTE_NUM_ROUND_OUT);                       
+  printf ("%u \n\n", SEC_LONG_NUM_OUT);                   
+
+  printf ("%u \n", TOT_BYTE_NUM_IN); 
+  printf ("%u \n", BYTE_NUM_IN);                       
+  printf ("%u \n", BYTE_NUM_ROUND_IN);                   
+  printf ("%u \n", LONG_NUM_IN);                    
+     
+  printf ("%u \n", SEC_BYTE_NUM_IN);                    
+  printf ("%u \n", SEC_BYTE_NUM_ROUND_IN);                         
+  printf ("%u \n", SEC_LONG_NUM_IN);                         
+*/
+  
+  
+//--------------------------------------------------------------------------------------------  
+  
+  
+  return true;                                            // initalization completed        
+};  
+
+
+
+
+//---- EtherCAT task ------------------------------------------------------------------------------
+
+unsigned char EasyCAT::MainTask()                           // must be called cyclically by the application
+
+{
+  bool WatchDog = true;
+  bool Operational = false; 
+  unsigned char i;
+  ULONG TempLong; 
+  unsigned char Status;  
+ 
+  
+  TempLong.Long = SPIReadRegisterIndirect (WDOG_STATUS, 1); // read watchdog status
+  if ((TempLong.Byte[0] & 0x01) == 0x01)                    //
+    WatchDog = false;                                       // set/reset the corrisponding flag
+  else                                                      //
+    WatchDog = true;                                        //
+
+    
+  TempLong.Long = SPIReadRegisterIndirect (AL_STATUS, 1);   // read the EtherCAT State Machine status
+  Status = TempLong.Byte[0] & 0x0F;                         //
+  if (Status == ESM_OP)                                     // to see if we are in operational state
+    Operational = true;                                     //
+  else                                                      // set/reset the corrisponding flag
+    Operational = false;                                    //    
+
+
+                                                            //--- process data transfert ----------
+                                                            //                                                        
+  if (WatchDog | !Operational)                              // if watchdog is active or we are 
+  {                                                         // not in operational state, reset 
+    for (i=0; i < TOT_BYTE_NUM_OUT ; i++)                   // the output buffer
+    BufferOut.Byte[i] = 0;                                  //
+
+/*                                                          // debug
+    if (!Operational)                                       //
+      printf("Not operational\n");                    		//
+    if (WatchDog)                                           //    
+      printf("WatchDog\n");                           		//  
+*/                                                          //
+  }
+  
+  else                                                      
+  {                                                         
+    SPIReadProcRamFifo();                                   // otherwise transfer process data from 
+  }                                                         // the EtherCAT core to the output buffer  
+                 
+  SPIWriteProcRamFifo();                                    // we always transfer process data from
+                                                            // the input buffer to the EtherCAT core  
+
+  if (WatchDog)                                             // return the status of the State Machine      
+  {                                                         // and of the watchdog
+    Status |= 0x80;                                         //
+  }                                                         //
+  return Status;                                            //   
+  
+}
+
+
+    
+//---- read a directly addressable registers  -----------------------------------------------------
+
+unsigned long EasyCAT::SPIReadRegisterDirect (unsigned short Address, unsigned char Len)
+
+                                                   // Address = register to read
+                                                   // Len = number of bytes to read (1,2,3,4)
+                                                   //
+                                                   // a long is returned but only the requested bytes
+                                                   // are meaningful, starting from LsByte                                                 
+{
+  ULONG Result; 
+  UWORD Addr;
+  Addr.Word = Address; 
+  unsigned char i; 
+
+  SCS_Low_macro                                             // SPI chip select enable
+
+  SPI_TransferTx(COMM_SPI_READ);                            // SPI read command
+  SPI_TransferTx(Addr.Byte[1]);                             // address of the register
+  SPI_TransferTxLast(Addr.Byte[0]);                         // to read, MsByte first
+ 
+  for (i=0; i<Len; i++)                                     // read the requested number of bytes
+  {                                                         // LsByte first 
+    Result.Byte[i] = SPI_TransferRx(DUMMY_BYTE);            //
+  }                                                         //    
+  
+  SCS_High_macro                                            // SPI chip select disable 
+ 
+  return Result.Long;                                       // return the result
+}
+
+
+
+
+//---- write a directly addressable registers  ----------------------------------------------------
+
+void EasyCAT::SPIWriteRegisterDirect (unsigned short Address, unsigned long DataOut)
+
+                                                   // Address = register to write
+                                                   // DataOut = data to write
+{ 
+  ULONG Data; 
+  UWORD Addr;
+  Addr.Word = Address;
+  Data.Long = DataOut;    
+
+  SCS_Low_macro                                             // SPI chip select enable  
+  
+  SPI_TransferTx(COMM_SPI_WRITE);                           // SPI write command
+  SPI_TransferTx(Addr.Byte[1]);                             // address of the register
+  SPI_TransferTx(Addr.Byte[0]);                             // to write MsByte first
+
+  SPI_TransferTx(Data.Byte[0]);                             // data to write 
+  SPI_TransferTx(Data.Byte[1]);                             // LsByte first
+  SPI_TransferTx(Data.Byte[2]);                             //
+  SPI_TransferTxLast(Data.Byte[3]);                         //
+ 
+  SCS_High_macro                                            // SPI chip select enable   
+}
+
+
+//---- read an undirectly addressable registers  --------------------------------------------------
+
+unsigned long EasyCAT::SPIReadRegisterIndirect (unsigned short Address, unsigned char Len)
+
+                                                   // Address = register to read
+                                                   // Len = number of bytes to read (1,2,3,4)
+                                                   //
+                                                   // a long is returned but only the requested bytes
+                                                   // are meaningful, starting from LsByte                                                  
+{
+  ULONG TempLong;
+  UWORD Addr;
+  Addr.Word = Address;
+                                                            // compose the command
+                                                            //
+  TempLong.Byte[0] = Addr.Byte[0];                          // address of the register
+  TempLong.Byte[1] = Addr.Byte[1];                          // to read, LsByte first
+  TempLong.Byte[2] = Len;                                   // number of bytes to read
+  TempLong.Byte[3] = ESC_READ;                              // ESC read 
+
+  SPIWriteRegisterDirect (ECAT_CSR_CMD, TempLong.Long);     // write the command
+
+  do
+  {                                                         // wait for command execution
+    TempLong.Long = SPIReadRegisterDirect(ECAT_CSR_CMD,4);  //
+  }                                                         //
+  while(TempLong.Byte[3] & ECAT_CSR_BUSY);                  //
+                                                             
+                                                              
+  TempLong.Long = SPIReadRegisterDirect(ECAT_CSR_DATA,Len); // read the requested register
+  return TempLong.Long;                                     //
+}
+
+
+//---- write an undirectly addressable registers  -------------------------------------------------
+
+void  EasyCAT::SPIWriteRegisterIndirect (unsigned long DataOut, unsigned short Address, unsigned char Len)
+
+                                                   // Address = register to write
+                                                   // DataOut = data to write                                                    
+{
+  ULONG TempLong;
+  UWORD Addr;
+  Addr.Word = Address;
+
+
+  SPIWriteRegisterDirect (ECAT_CSR_DATA, DataOut);            // write the data
+
+                                                              // compose the command
+                                                              //                                
+  TempLong.Byte[0] = Addr.Byte[0];                            // address of the register  
+  TempLong.Byte[1] = Addr.Byte[1];                            // to write, LsByte first
+  TempLong.Byte[2] = Len;                                     // number of bytes to write
+  TempLong.Byte[3] = ESC_WRITE;                               // ESC write
+
+  SPIWriteRegisterDirect (ECAT_CSR_CMD, TempLong.Long);       // write the command
+
+  do                                                          // wait for command execution
+  {                                                           //
+    TempLong.Long = SPIReadRegisterDirect (ECAT_CSR_CMD, 4);  //  
+  }                                                           //  
+  while (TempLong.Byte[3] & ECAT_CSR_BUSY);                   //
+}
+
+
+//---- read from process ram fifo ----------------------------------------------------------------
+
+
+void EasyCAT::SPIReadProcRamFifo()    // read BYTE_NUM bytes from the output process ram, through the fifo
+                                      //        
+                                      // these are the bytes received from the EtherCAT master and
+                                      // that will be use by our application to write the outputs
+{
+  ULONG TempLong;
+  unsigned char i;
+   
+  #if TOT_BYTE_NUM_OUT > 0
+
+    SPIWriteRegisterDirect (ECAT_PRAM_RD_CMD, PRAM_ABORT);        // abort any possible pending transfer
+
+  
+    SPIWriteRegisterDirect (ECAT_PRAM_RD_ADDR_LEN, (0x00001000 | (((uint32_t)TOT_BYTE_NUM_OUT) << 16)));   
+                                                                  // the high word is the num of bytes
+                                                                  // to read 0xTOT_BYTE_NUM_OUT----
+                                                                  // the low word is the output process        
+                                                                  // ram offset 0x----1000 
+
+    SPIWriteRegisterDirect (ECAT_PRAM_RD_CMD, 0x80000000);        // start command        
+ 
+ 
+                                                //------- one round is enough if we have ----
+                                                //------- to transfer up to 64 bytes --------
+   
+    do                                                            // wait for the data to be       
+    {                                                             // transferred from the output  
+      TempLong.Long = SPIReadRegisterDirect (ECAT_PRAM_RD_CMD,2); // process ram to the read fifo       
+    }                                                             //    
+    while (TempLong.Byte[1] != FST_LONG_NUM_OUT);                 // 
+  
+    SCS_Low_macro                                                 // enable SPI chip select 
+  
+    SPI_TransferTx(COMM_SPI_READ);                                // SPI read command
+    SPI_TransferTx(0x00);                                         // address of the read  
+    SPI_TransferTxLast(0x00);                                     // fifo MsByte first
+  
+    for (i=0; i< FST_BYTE_NUM_ROUND_OUT; i++)                     // transfer the data
+    {                                                             //
+      BufferOut.Byte[i] = SPI_TransferRx(DUMMY_BYTE);             //
+    }                                                             //
+    
+    SCS_High_macro                                                // disable SPI chip select    
+  #endif  
+
+  
+  #if SEC_BYTE_NUM_OUT > 0                    //-- if we have to transfer more then 64 bytes --
+                                              //-- we must do another round -------------------
+                                              //-- to transfer the remainig bytes -------------
+
+
+    do                                                          // wait for the data to be       
+    {                                                           // transferred from the output  
+      TempLong.Long = SPIReadRegisterDirect(ECAT_PRAM_RD_CMD,2);// process ram to the read fifo 
+    }                                                           //    
+    while (TempLong.Byte[1] != SEC_LONG_NUM_OUT);               //  
+
+    SCS_Low_macro                                               // enable SPI chip select   
+    
+    SPI_TransferTx(COMM_SPI_READ);                              // SPI read command
+    SPI_TransferTx(0x00);                                       // address of the read  
+    SPI_TransferTxLast(0x00);                                   // fifo MsByte first
+    
+    for (i=0; i< (SEC_BYTE_NUM_ROUND_OUT); i++)                 // transfer loop for the remaining 
+    {                                                           // bytes
+      BufferOut.Byte[i+64] = SPI_TransferRx(DUMMY_BYTE);        // we transfer the second part of
+    }                                                           // the buffer, so offset by 64
+      
+    SCS_High_macro                                              // SPI chip select disable  
+  #endif    
+}
+
+
+//---- write to the process ram fifo --------------------------------------------------------------
+
+void EasyCAT::SPIWriteProcRamFifo()    // write BYTE_NUM bytes to the input process ram, through the fifo
+                                       //    
+                                       // these are the bytes that we have read from the inputs of our                   
+                                       // application and that will be sent to the EtherCAT master
+{
+  ULONG TempLong;
+  unsigned char i;  
+  
+  
+  
+  #if TOT_BYTE_NUM_IN > 0  
+  
+    SPIWriteRegisterDirect (ECAT_PRAM_WR_CMD, PRAM_ABORT);        // abort any possible pending transfer
+  
+ 
+    SPIWriteRegisterDirect (ECAT_PRAM_WR_ADDR_LEN, (0x00001200 | (((uint32_t)TOT_BYTE_NUM_IN) << 16)));   
+                                                                  // the high word is the num of bytes
+                                                                  // to write 0xTOT_BYTE_NUM_IN----
+                                                                  // the low word is the input process        
+                                                                  // ram offset  0x----1200
+                                                                                               
+    SPIWriteRegisterDirect (ECAT_PRAM_WR_CMD, 0x80000000);        // start command  
+  
+  
+                                                //------- one round is enough if we have ----
+                                                //------- to transfer up to 64 bytes --------
+    
+    do                                                            // check that the fifo has      
+    {                                                             // enough free space 
+      TempLong.Long = SPIReadRegisterDirect (ECAT_PRAM_WR_CMD,2); //  
+    }                                                             //  
+    while (TempLong.Byte[1] < FST_LONG_NUM_IN);                   //
+  
+    SCS_Low_macro                                                 // enable SPI chip select
+  
+    SPI_TransferTx(COMM_SPI_WRITE);                               // SPI write command
+    SPI_TransferTx(0x00);                                         // address of the write fifo 
+    SPI_TransferTx(0x20);                                         // MsByte first 
+
+    for (i=0; i< (FST_BYTE_NUM_ROUND_IN - 1 ); i++)               // transfer the data
+    {                                                             //
+      SPI_TransferTx (BufferIn.Byte[i]);                          // 
+    }                                                             //
+                                                                  //  
+    SPI_TransferTxLast (BufferIn.Byte[i]);                        // one last byte
+  
+    SCS_High_macro                                                // disable SPI chip select           
+  #endif        
+
+  
+  #if SEC_BYTE_NUM_IN > 0                     //-- if we have to transfer more then 64 bytes --
+                                              //-- we must do another round -------------------
+                                              //-- to transfer the remainig bytes -------------
+
+    do                                                          // check that the fifo has     
+    {                                                           // enough free space       
+      TempLong.Long = SPIReadRegisterDirect(ECAT_PRAM_WR_CMD,2);// 
+    }                                                           //  
+    while (TempLong.Byte[1] < (SEC_LONG_NUM_IN));               //
+                             
+    SCS_Low_macro                                               // enable SPI chip select
+    
+    SPI_TransferTx(COMM_SPI_WRITE);                             // SPI write command
+    SPI_TransferTx(0x00);                                       // address of the write fifo 
+    SPI_TransferTx(0x20);                                       // MsByte first 
+
+    for (i=0; i< (SEC_BYTE_NUM_ROUND_IN - 1); i++)              // transfer loop for the remaining 
+    {                                                           // bytes
+      SPI_TransferTx (BufferIn.Byte[i+64]);                     // we transfer the second part of
+    }                                                           // the buffer, so offset by 64
+                                                                //  
+    SPI_TransferTxLast (BufferIn.Byte[i+64]);                   // one last byte  
+
+    SCS_High_macro                                              // disable SPI chip select    
+  #endif       
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/EasyCAT.h	Tue Sep 12 17:09:43 2017 +0000
@@ -0,0 +1,424 @@
+//********************************************************************************************
+//                                                                                           *
+// AB&T Tecnologie Informatiche - Ivrea Italy                                                *
+// http://www.bausano.net                                                                    *
+// https://www.ethercat.org/en/products/791FFAA126AD43859920EA64384AD4FD.htm                 *
+//                                                                                           *  
+//********************************************************************************************    
+//                                                                                           *
+// This software is distributed as an example, in the hope that it could be useful,          *
+// WITHOUT ANY WARRANTY, even the implied warranty of FITNESS FOR A PARTICULAR PURPOSE       *
+//                                                                                           *
+//******************************************************************************************** 
+
+
+//----- EasyCAT library for mbed boards 170912 ----------------------------------------------
+//----- Derived from the AB&T EasyCAT Arduino shield library V 1.5 --------------------------
+
+//----- Tested with the STM32 NUCLEO-F767ZI board -------------------------------------------
+
+
+
+
+#ifndef EasyCAT_H
+#define EasyCAT_H
+
+
+
+ 
+//****** PDO configuration parameters ******************************************************** 
+ 
+// Here we can define how many I/O bytes our EasyCAT can exchange
+
+// We can use STANDARD MODE or CUSTOM MODE
+// !!! Warning: CUSTOM MODE is recommended only for advanced users !!!
+
+// In STANDARD MODE the EasyCAT exchanges a fixed number of bytes 
+// in input and in output
+// The number of bytes in input are equal to the number of bytes in output
+// Valid values are 16, 32, 64, 128  
+//
+// The configuration EEPROM on board of the EasyCAT must be  
+// loaded with the corresponding bin file, provided by AB&T
+//
+// The EasyCAT is shipped configured for 32+32 bytes I.E. with
+// the "EasyCAT_32_32.bin" file loaded into the configuration EEPROM  
+
+
+//--   BYTE_NUM    -----------      Byte exchanged  ------    Config EEPROM file
+                          
+//#define BYTE_NUM   16         //      16 + 16               EasyCAT_16_16.bin 
+#define BYTE_NUM   32           //      32 + 32               EasyCAT_32_32.bin
+//#define BYTE_NUM   64         //      64 + 64               EasyCAT_64_64.bin
+//#define BYTE_NUM   128        //      128 + 128             EasyCAT_128_128.bin
+
+
+
+// In CUSTOM MODE, recommended only for advanced users, the EasyCAT exchanges 
+// a configurable number of bytes, between 0 and 128, in input and in output 
+// The number of bytes in input and in output can be different
+//
+// The configuration EEPROM on board of the EasyCAT must be  
+// loaded with a suitable bin file, provided by the user
+// or with the "EasyCAT_configurable.bin" file provided by AB&T
+ 
+// Comment all the above BYTE_NUM #define for the STANDARD MODE
+// and define here the custom number of exchanged bytes 
+ 
+                                           //----- CUSTOM_MODE example -------
+                                           //         
+//#define CUST_BYTE_NUM_OUT      49        // total number of bytes in output
+//#define CUST_BYTE_NUM_IN       17        // total number of bytes in input
+
+// We can also customize names and data types for the PDOs
+// see the example in this file (look for tag "Custom data types example")
+ 
+//*************************************************************************************
+ 
+ 
+ 
+//-- the preprocessor calculates the parameters necessary to transfer out data --- 
+
+                                                   // define TOT_BYTE_NUM_OUT as the total
+                                                   // number of byte you need to
+                                                   // transfer in output (between 0 and 128)
+                                                   // this must match your ESI XML
+                                                   
+#ifdef  BYTE_NUM
+  #define TOT_BYTE_NUM_OUT  BYTE_NUM                // bytes in output
+#else  
+  #define TOT_BYTE_NUM_OUT  CUST_BYTE_NUM_OUT       // any number between 0 and 128  
+#endif
+
+
+#if ((TOT_BYTE_NUM_OUT & 0x03) != 0x00)             // number of bytes in output
+  #define TOT_BYTE_NUM_ROUND_OUT  ((TOT_BYTE_NUM_OUT | 0x03) + 1)  
+#else                                               // rounded to 4 (long)
+  #define TOT_BYTE_NUM_ROUND_OUT  TOT_BYTE_NUM_OUT  //
+#endif                                              //
+
+#if TOT_BYTE_NUM_OUT > 64                           // if we have more then  64 bytes
+                                                    // we have to split the transfer in two
+                                                        
+  #define SEC_BYTE_NUM_OUT  (TOT_BYTE_NUM_OUT - 64) // number of bytes of the second transfer
+  
+  #if ((SEC_BYTE_NUM_OUT & 0x03) != 0x00)           // number of bytes of the second transfer
+    #define SEC_BYTE_NUM_ROUND_OUT  ((SEC_BYTE_NUM_OUT | 0x03) + 1)  
+  #else                                             // rounded to 4 (long)
+    #define SEC_BYTE_NUM_ROUND_OUT  SEC_BYTE_NUM_OUT//
+  #endif                                            //
+
+  #define SEC_LONG_NUM_OUT  SEC_BYTE_NUM_ROUND_OUT/4// number of long of the second transfer
+
+  #define FST_BYTE_NUM_OUT  64                      // number of bytes of the first transfer     
+  #define FST_BYTE_NUM_ROUND_OUT  64                // number of bytes of the first transfer
+                                                    // rounded to 4 (long)
+  #define FST_LONG_NUM_OUT  16                      // number of long of the second transfer
+
+  
+#else                                               // if we have 64 bytes max we tranfert
+                                                    // them in just one round
+                                                        
+  #define FST_BYTE_NUM_OUT  TOT_BYTE_NUM_OUT        // number of bytes of the first and only transfer  
+
+  #if ((FST_BYTE_NUM_OUT & 0x03) != 0x00)           // number of bytes of the first and only transfer
+    #define FST_BYTE_NUM_ROUND_OUT ((FST_BYTE_NUM_OUT | 0x03) + 1)
+  #else                                             // rounded to 4 (long)
+    #define FST_BYTE_NUM_ROUND_OUT  FST_BYTE_NUM_OUT   
+  #endif
+
+  #define FST_LONG_NUM_OUT  FST_BYTE_NUM_ROUND_OUT/4// number of long of the first and only transfer
+  
+  #define SEC_BYTE_NUM_OUT  0                       // we don't use the second round
+  #define SEC_BYTE_NUM_ROUND_OUT  0                 //
+  #define SEC_LONG_NUM_OUT  0                       //
+  
+#endif
+
+
+//-- the preprocessor calculates the parameters necessary to transfer in data --- 
+
+                                                   // define TOT_BYTE_NUM_IN the total
+                                                   // number of byte you need to
+                                                   // transfer in input (between 0 and 128)
+ 
+#ifdef  BYTE_NUM
+  #define TOT_BYTE_NUM_IN  BYTE_NUM                // bytes in input
+#else  
+  #define TOT_BYTE_NUM_IN  CUST_BYTE_NUM_IN       // any number between 0 and 128  
+#endif
+
+    
+#if ((TOT_BYTE_NUM_IN & 0x03) != 0x00)              // number of bytes in output
+  #define TOT_BYTE_NUM_ROUND_IN  ((TOT_BYTE_NUM_IN | 0x03) + 1)  
+#else                                               // rounded to 4 (long)
+  #define TOT_BYTE_NUM_ROUND_IN  TOT_BYTE_NUM_IN    //
+#endif                                              //
+
+#if TOT_BYTE_NUM_IN > 64                            // if we have more then  64 bytes
+                                                    // we have to split the transfer in two
+                                                        
+  #define SEC_BYTE_NUM_IN  (TOT_BYTE_NUM_IN - 64)   // number of bytes of the second transfer
+  
+  #if ((SEC_BYTE_NUM_IN & 0x03) != 0x00)            // number of bytes of the second transfer
+    #define SEC_BYTE_NUM_ROUND_IN  ((SEC_BYTE_NUM_IN | 0x03) + 1)  
+  #else                                             // rounded to 4 (long)
+    #define SEC_BYTE_NUM_ROUND_IN  SEC_BYTE_NUM_IN  //
+  #endif                                            //
+
+  #define SEC_LONG_NUM_IN  SEC_BYTE_NUM_ROUND_IN/4  // number of long of the second transfer
+
+  #define FST_BYTE_NUM_IN  64                       // number of bytes of the first transfer     
+  #define FST_BYTE_NUM_ROUND_IN  64                 // number of bytes of the first transfer
+                                                    // rounded to 4 (long)
+  #define FST_LONG_NUM_IN  16                       // number of long of the second transfer
+
+  
+#else                                               // if we have 64 bytes max we tranfert
+                                                    // them in just one round
+                                                        
+  #define FST_BYTE_NUM_IN  TOT_BYTE_NUM_IN          // number of bytes of the first and only transfer  
+
+  #if ((FST_BYTE_NUM_IN & 0x03) != 0x00)            // number of bytes of the first and only transfer
+    #define FST_BYTE_NUM_ROUND_IN ((FST_BYTE_NUM_IN | 0x03) + 1)
+  #else                                             // rounded to 4 (long)
+    #define FST_BYTE_NUM_ROUND_IN  FST_BYTE_NUM_IN   
+  #endif
+
+  #define FST_LONG_NUM_IN  FST_BYTE_NUM_ROUND_IN/4  // number of long of the first and only transfer
+  
+  #define SEC_BYTE_NUM_IN  0                        // we don't use the second round
+  #define SEC_BYTE_NUM_ROUND_IN  0                  //
+  #define SEC_LONG_NUM_IN  0                        //
+
+#endif
+ 
+ 
+//---------------------------------------------------------------------------------
+
+//----------------- sanity check -------------------------------------------------------                                 
+      
+
+#ifdef BYTE_NUM                     // STANDARD MODE and CUSTOM MODE
+                                    // cannot be defined at the same time
+  #ifdef CUST_BYTE_NUM_OUT 
+    #error "BYTE_NUM and CUST_BYTE_NUM_OUT cannot be defined at the same time !!!!"
+    #error "define them correctly in file EasyCAT.h"
+    #endif
+  
+  #ifdef CUST_BYTE_NUM_IN 
+    #error "BYTE_NUM and CUST_BYTE_NUM_IN cannot be defined at the same time !!!!"
+    #error "define them correctly in file EasyCAT.h"
+  #endif
+#endif 
+      
+#ifdef BYTE_NUM                     //--- for BYTE_NUM we accept only 16  32  64  128 --
+                                  
+  #if ((BYTE_NUM !=16) && (BYTE_NUM !=32) && (BYTE_NUM !=64)  && (BYTE_NUM !=128))
+    #error "BYTE_NUM must be 16, 32, 64 or 128 !!! define it correctly in file EasyCAT.h"
+  #endif 
+  
+#else
+                                   //--- CUST_BYTE_NUM_OUT and CUST_BYTE_NUM_IN --------
+                                   //    must be max 128
+  #if (CUST_BYTE_NUM_OUT > 128)
+    #error "CUST_BYTE_NUM_OUT must be max 128 !!! define it correctly in file EasyCAT.h"
+  #endif 
+  
+  #if (CUST_BYTE_NUM_IN > 128)
+    #error "CUST_BYTE_NUM_IN must be max 128 !!! define it correctly in file EasyCAT.h"
+  #endif 
+  
+#endif 
+
+  
+//*************************************************************************************************
+
+
+
+
+//---- LAN9252 registers --------------------------------------------------------------------------
+
+                                            //---- access to EtherCAT registers -------------------
+
+#define ECAT_CSR_DATA           0x0300      // EtherCAT CSR Interface Data Register
+#define ECAT_CSR_CMD            0x0304      // EtherCAT CSR Interface Command Register
+
+
+                                            //---- access to EtherCAT process RAM ----------------- 
+
+#define ECAT_PRAM_RD_ADDR_LEN   0x0308      // EtherCAT Process RAM Read Address and Length Register
+#define ECAT_PRAM_RD_CMD        0x030C      // EtherCAT Process RAM Read Command Register
+#define ECAT_PRAM_WR_ADDR_LEN   0x0310      // EtherCAT Process RAM Write Address and Length Register 
+#define ECAT_PRAM_WR_CMD        0x0314      // EtherCAT Process RAM Write Command Register
+
+#define ECAT_PRAM_RD_DATA       0x0000      // EtherCAT Process RAM Read Data FIFO
+#define ECAT_PRAM_WR_DATA       0x0020      // EtherCAT Process RAM Write Data FIFO
+
+                                            //---- EtherCAT registers -----------------------------
+                                            
+#define AL_STATUS               0x0130      // AL status
+#define WDOG_STATUS             0x0440      // watch dog status
+#define AL_EVENT_MASK           0x0204      // AL event interrupt mask
+
+                                            //---- LAN9252 registers ------------------------------    
+
+#define HW_CFG                  0x0074      // hardware configuration register
+#define BYTE_TEST               0x0064      // byte order test register
+#define RESET_CTL               0x01F8      // reset register       
+#define ID_REV                  0x0050      // chip ID and revision
+#define IRQ_CFG                 0x0054      // interrupt configuration
+#define INT_EN                  0x005C      // interrupt enable
+
+
+//---- LAN9252 flags ------------------------------------------------------------------------------
+
+#define ECAT_CSR_BUSY     0x80
+
+#define PRAM_ABORT        0x40000000
+
+#define PRAM_BUSY         0x80
+
+#define PRAM_AVAIL        0x01
+
+#define READY             0x08
+
+#define DIGITAL_RST       0x00000001
+
+
+//---- EtherCAT flags -----------------------------------------------------------------------------
+
+                                                      // EtherCAT state machine 
+                                                      
+#define ESM_INIT                0x01                  // init
+#define ESM_PREOP               0x02                  // pre-operational
+#define ESM_BOOT                0x03                  // bootstrap
+#define ESM_SAFEOP              0x04                  // safe-operational
+#define ESM_OP                  0x08                  // operational
+
+
+//--- ESC commands --------------------------------------------------------------------------------
+
+#define ESC_WRITE 		   0x80
+#define ESC_READ 		     0xC0
+
+
+//---- SPI ----------------------------------------------------------------------------------------
+
+#define COMM_SPI_READ    0x03
+#define COMM_SPI_WRITE   0x02
+
+#define DUMMY_BYTE       0xFF
+
+
+
+//---- typedef ------------------------------------------------------------------------------------
+
+typedef union
+{
+    unsigned short  Word;
+    unsigned char   Byte[2];
+} UWORD;
+
+typedef union
+{
+    unsigned long   Long;
+    unsigned short  Word[2];
+    unsigned char   Byte[4];
+} ULONG;
+
+                                       
+typedef union								//-- output buffer -----------------
+{											//			
+  uint8_t  Byte [TOT_BYTE_NUM_ROUND_OUT];   //
+  
+  #if CUST_BYTE_NUM_OUT > 0                 //----- Custom data types example -----  
+/*                                            // 
+    struct                                  // Here we can define our custom 
+    {                                       // data types and names for the outputs
+                                            //
+      uint8_t Control;                      // The total number of bytes declared 
+      float PreZone1;                       // in this structure must be equal   
+      float CommZone1;                      // to the value assigned to CUST_BYTE_NUM_OUT 
+      float RampZone1;                      //        
+      float PreZone2;                       // In this case 1+ 4+4+4+ 4+4+4+ 4+4+4+ 4+4+4 = 49 
+      float CommZone2;                      //
+      float RampZone2;                      //
+      float PreZone3;                       //
+      float CommZone3;                      //
+      float RampZone3;                      //
+      float PreZone4;                       //
+      float CommZone4;                      //  
+      float RampZone4;                      //
+    }Cust;                                  //   
+*/                                            //
+  #endif                                    //
+  
+} PROCBUFFER_OUT;							//
+
+                                            
+typedef union                               //-- input buffer ------------------
+{											//
+  uint8_t  Byte [TOT_BYTE_NUM_ROUND_IN];    //
+                                            
+  #if CUST_BYTE_NUM_IN > 0                  //----- Custom data types example ------   
+/*                                             //  
+    struct                                  // Here we can define our custom  
+    {                                       // data types and names for the inputs
+                                            //
+      uint8_t Status;                       // The total number of bytes declared 
+      float TempZone1;                      // in this structure must be equal
+      float TempZone2;                      // to the value assigned to CUST_BYTE_NUM_IN 
+      float TempZone3;                      //
+      float TempZone4;                      // In this case 1+ 4+4+4+4 = 17
+    }Cust;                                  //   
+*/                                            //
+  #endif                                    //
+  
+} PROCBUFFER_IN;                            //
+
+
+typedef enum  
+{
+  ASYNC,
+  DC_SYNC,
+  SM_SYNC
+}SyncMode;
+
+
+
+//-------------------------------------------------------------------------------------------------
+ 
+class EasyCAT 
+{
+  public:
+    EasyCAT();                              // default constructor
+    EasyCAT(PinName SCS); 
+    EasyCAT(SyncMode Sync);              
+    EasyCAT(PinName SCS, SyncMode Sync);    
+    
+    
+    unsigned char MainTask();               // EtherCAT main task
+                                            // must be called cyclically by the application 
+    
+    bool Init();                            // EasyCAT board initialization 
+    
+    PROCBUFFER_OUT BufferOut;               // output process data buffer 
+    PROCBUFFER_IN BufferIn;                 // input process data buffer
+    
+    
+  private:
+    void          SPIWriteRegisterDirect   (unsigned short Address, unsigned long DataOut);
+    unsigned long SPIReadRegisterDirect    (unsigned short Address, unsigned char Len);
+    
+    void          SPIWriteRegisterIndirect (unsigned long  DataOut, unsigned short Address, unsigned char Len);
+    unsigned long SPIReadRegisterIndirect  (unsigned short Address, unsigned char Len); 
+    
+    void          SPIReadProcRamFifo();    
+    void          SPIWriteProcRamFifo();  
+    
+    PinName SCS_;     
+    SyncMode Sync_;    
+};
+
+#endif