/*************************************************************************\ * Copyright (c) 2019 European Spallation Source ERIC * ecmc is distributed subject to a Software License Agreement found * in file LICENSE that is included with this distribution. * * ecmcSocketCAN.h * * Created on: Mar 22, 2020 * Author: anderssandstrom * \*************************************************************************/ #ifndef ECMC_SOCKETCAN_H_ #define ECMC_SOCKETCAN_H_ #include #include "ecmcDataItem.h" #include "ecmcAsynPortDriver.h" #include "ecmcSocketCANDefs.h" #include "ecmcSocketCANWriteBuffer.h" #include "ecmcCANOpenDevice.h" #include "ecmcCANOpenMaster.h" #include "inttypes.h" #include #include #include #include #include #include #include #include #include #include #include #define ECMC_CAN_MAX_WRITE_CMDS 128 #define ECMC_CAN_MAX_DEVICES 128 #define ECMC_CAN_ERROR_WRITE_FULL 10 #define ECMC_CAN_ERROR_WRITE_BUSY 11 #define ECMC_CAN_ERROR_WRITE_NO_DATA 12 #define ECMC_CAN_ERROR_WRITE_INCOMPLETE 13 #define ECMC_CAN_ERROR_WRITE_BUFFER_NULL 14 #define ECMC_CAN_ERROR_READ_INCOMPLETE 15 class ecmcSocketCAN { public: /** ecmc ecmcSocketCAN class * This object can throw: * - bad_alloc * - invalid_argument * - runtime_error * - out_of_range */ ecmcSocketCAN(char* configStr, char* portName, int exeSampelTimeMs); ~ecmcSocketCAN(); void doReadWorker(); void doWriteWorker(); void doConnectWorker(); //virtual asynStatus writeInt32(asynUser *pasynUser, epicsInt32 value); //virtual asynStatus readInt32(asynUser *pasynUser, epicsInt32 *value); //virtual asynStatus readInt8Array(asynUser *pasynUser, epicsInt8 *value, // size_t nElements, size_t *nIn); //virtual asynStatus readFloat64(asynUser *pasynUser, epicsFloat64 *value); void connectExternal(); int getConnected(); int addWriteCAN(uint32_t canId, uint8_t len, uint8_t data0, uint8_t data1, uint8_t data2, uint8_t data3, uint8_t data4, uint8_t data5, uint8_t data6, uint8_t data7); int getlastWritesError(); void execute(); // ecmc rt loop void addMaster(uint32_t nodeId, const char* name, int lssSampleTimeMs, int syncSampleTimeMs, int heartSampleTimeMs); void addDevice(uint32_t nodeId, const char* name, int heartTimeoutMs); void addPDO(uint32_t nodeId, uint32_t cobId, ecmc_can_direction rw, uint32_t ODSize, int readTimeoutMs, int writeCycleMs, //if <0 then write on demand. const char* name); void addSDO(uint32_t nodeId, uint32_t cobIdTx, // 0x580 + CobId uint32_t cobIdRx, // 0x600 + Cobid ecmc_can_direction rw, uint16_t ODIndex, // Object dictionary index uint8_t ODSubIndex, // Object dictionary subindex uint32_t ODSize, int readSampleTimeMs, const char* name); int findDeviceWithNodeId(uint32_t nodeId); private: void parseConfigStr(char *configStr); static std::string to_string(int value); void connectPrivate(); int writeCAN(can_frame *frame); char* cfgCanIFStr_; // Config: can interface can0, vcan0.. int cfgDbgMode_; int cfgAutoConnect_; int destructs_; int connected_; epicsEvent doConnectEvent_; epicsEvent doWriteEvent_; struct can_frame rxmsg_; struct ifreq ifr_; int socketId_; struct sockaddr_can addr_; struct can_frame txmsgBuffer_[ECMC_CAN_MAX_WRITE_CMDS]; int exeSampleTimeMs_; ecmcSocketCANWriteBuffer *writeBuffer_; int deviceCounter_; ecmcCANOpenDevice *devices_[ECMC_CAN_MAX_DEVICES]; ecmcCANOpenMaster *masterDev_; int errorCode_; int refreshNeeded_; //ASYN void initAsyn(); void refreshAsynParams(); ecmcAsynDataItem *errorParam_; ecmcAsynDataItem *connectedParam_; }; #endif /* ECMC_SOCKETCAN_H_ */