Fork of EasyCAT
Diff: EasyCAT.h
- Revision:
- 0:7816b38c99cc
diff -r 000000000000 -r 7816b38c99cc EasyCAT.h --- /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