#ifndef COSY_CanOpen #define COSY_CanOpen #ifndef ROOT_TCondition #include #endif #ifndef COSY_SdoList #include "sdolist.h" #endif #ifndef COSY_MTimeout #include "MTimeout.h" #endif #ifdef __CINT__ typedef UInt_t LWORD_t; typedef Short_t WORDS_t; #endif //#define FALSE 0 //#define TRUE 1 // CAL Function Codes // COB-ID = function code | node-id (5bits) #define kNMT 0x0 // only with COB-ID 0 #define kSYNC 0x1 // only with COB-ID 0 #define kTIMESTAMP 0x2 // only with COB-ID 0 #define kEMERGENCY 0x1 #define kPDO1_TX 0x3 #define kPDO2_TX 0x5 #define kPDO3_TX 0x7 #define kPDO4_TX 0x9 #define kSDO_RX 0xb // this is used to set data of the shaft encoder #define kSDO_TX 0xc // this is used to request data from the shaft encoder #define kNodeguard 0xe // NMT: no answer to NMT command // cob-id=0, command (byte), id (byte) #define kNMT_START 0x01 // change to operational state (start) #define kNMT_STOP 0x02 // change to prepared state (stop) #define kNMT_PREOP 0x80 // enter pre operational state #define kNMT_RESET 0x81 // reset node (set parameter to power on values) #define kNMT_REINIT 0x82 // reset communication of node (set communication parameters to power on values) // command for SDOs #define kSDO_LEN4 0x3 #define kSDO_LEN2 0xb #define kSDO_LEN1 0xf #define kSDO_RXm4 0x22 // this is used with SDO_TX to send a maximum of 4 bytes #define kSDO_RX4 0x20|kSDO_LEN4 // this is used with SDO_TX to send 4 bytes #define kSDO_RX2 0x20|kSDO_LEN2 // this is used with SDO_TX to send 2 bytes #define kSDO_RX1 0x20|kSDO_LEN1 // this is used with SDO_TX to send 1 byte #define kSDO_RX_DATA 0x40 // this is used to request parameters from the encoder #define kSDO_TX4 0x40|kSDO_LEN4 // answer to 0x40 with 4 bytes of data #define kSDO_TX3 0x40|kSDO_LEN2 // answer to 0x40 with 2 bytes of data #define kSDO_TX1 0x40|kSDO_LEN1 // answer to 0x40 with 1 byte of data #define kSDO_TX_OK 0x60 // answer to a SDO_TX message #define kSDO_TX_ERROR 0x80 // error message (instead of 0x60) #define kWaitUnlimited 0 #define kDontWait (-1) class Interface; typedef struct timeval timeval_t; class CanOpen { private: Interface *fInterface; // Handle to the I/O interface PendingSDOList fSdoList; // List for pending SDOs TCondition fPdoCond[32][4]; // one for every PDO of every node protected: virtual void Start(); // Start CanOpen communication virtual void Stop(); // Stop CanOpen communcation virtual bool HasError() const; private: // // Handle can objects arrived at the CanOpen interface // virtual void HandleSDO(BYTE_t node, BYTE_t cmd, WORD_t idx, BYTE_t subidx, LWORD_t data, const timeval_t &tv)=0; virtual void HandlePDO1(BYTE_t node, const BYTE_t *data, const timeval_t &tv)=0; virtual void HandlePDO2(BYTE_t node, const BYTE_t *data, const timeval_t &tv)=0; virtual void HandlePDO3(BYTE_t node, const BYTE_t *data, const timeval_t &tv)=0; virtual void HandlePDO4(BYTE_t node, const BYTE_t *data, const timeval_t &tv)=0; virtual void HandleNodeguard(BYTE_t node, const timeval_t &tv)=0; virtual void HandleEmergency(BYTE_t node, const timeval_t &tv)=0; // Handle message arrived at the CanOpen interface and split into can objects virtual void HandleCanMessage(WORD_t cobid, const BYTE_t *data, const timeval_t &tv); public: CanOpen(); virtual ~CanOpen(); void SetInterface(Interface *f) { fInterface=f; } // Set Handle to the interface Bool_t HasConnection() const; // Send a Process Data Object (PDO) to the CanOpen bus void SendPDO1(BYTE_t node, BYTE_t data[8]); void SendPDO2(BYTE_t node, BYTE_t data[8]); void SendPDO3(BYTE_t node, BYTE_t data[8]); void SendPDO4(BYTE_t node, BYTE_t data[8]); void SendPDO1(BYTE_t node, BYTE_t m0=0, BYTE_t m1=0, BYTE_t m2=0, BYTE_t m3=0, BYTE_t m4=0, BYTE_t m5=0, BYTE_t m6=0, BYTE_t m7=0); void SendPDO2(BYTE_t node, BYTE_t m0=0, BYTE_t m1=0, BYTE_t m2=0, BYTE_t m3=0, BYTE_t m4=0, BYTE_t m5=0, BYTE_t m6=0, BYTE_t m7=0); void SendPDO3(BYTE_t node, BYTE_t m0=0, BYTE_t m1=0, BYTE_t m2=0, BYTE_t m3=0, BYTE_t m4=0, BYTE_t m5=0, BYTE_t m6=0, BYTE_t m7=0); void SendPDO4(BYTE_t node, BYTE_t m0=0, BYTE_t m1=0, BYTE_t m2=0, BYTE_t m3=0, BYTE_t m4=0, BYTE_t m5=0, BYTE_t m6=0, BYTE_t m7=0); // Send a Service Data Object (SDO) to a CanOpen device (aka. write parameter) void SendSDO(BYTE_t node, WORD_t idx, BYTE_t subidx, BYTE_t val, bool store); void SendSDO(BYTE_t node, WORD_t idx, BYTE_t subidx, WORD_t val, bool store); void SendSDO(BYTE_t node, WORD_t idx, BYTE_t subidx, LWORD_t val, bool store); void SendSDO(BYTE_t node, WORD_t idx, BYTE_t val, bool store) { SendSDO(node, idx, 0, val, store); } void SendSDO(BYTE_t node, WORD_t idx, WORD_t val, bool store) { SendSDO(node, idx, 0, val, store); } void SendSDO(BYTE_t node, WORD_t idx, LWORD_t val, bool store) { SendSDO(node, idx, 0, val, store); } // Send other objects void SendNMT(BYTE_t node, BYTE_t cmd); void SendNodeguard(BYTE_t node); // Request a Service Data Object (SDO) from a CanOpen device (aka. read parameter) void RequestSDO(BYTE_t node, WORD_t idx, BYTE_t subidx=0); // Enable interface for pass-through of a kind of can-object void EnableSdoRx(BYTE_t node); void EnablePdo1Rx(BYTE_t node); void EnablePdo2Rx(BYTE_t node); void EnablePdo3Rx(BYTE_t node); void EnablePdo4Rx(BYTE_t node); void EnableEmcy(BYTE_t node); void EnableNodeguard(BYTE_t node); // Enable interface for pass-through of a can-object void EnableCanMsg(BYTE_t node, BYTE_t fcode, int flag=TRUE); // Wait until the next Pdo object has arrived void WaitForNextPdo1(BYTE_t node) { node -= 1; fPdoCond[node][0].Wait(); } void WaitForNextPdo2(BYTE_t node) { node -= 1; fPdoCond[node][1].Wait(); } void WaitForNextPdo3(BYTE_t node) { node -= 1; fPdoCond[node][2].Wait(); } void WaitForNextPdo4(BYTE_t node) { node -= 1; fPdoCond[node][3].Wait(); } // Wait for arrival of a return to a given Sdo (or all axpected Sdos) bool WaitForSdos(WORDS_t ms=500); bool WaitForSdo(BYTE_t node, WORD_t idx, BYTE_t subidx, WORDS_t ms=500); virtual int StopWaitingForSDO() const { return FALSE; } // Low level function to send rawcan frames void SendCanFrame(WORD_t cobid, BYTE_t m[8], BYTE_t rtr=0); void SendCanFrame(WORD_t cobid, BYTE_t m0=0, BYTE_t m1=0, BYTE_t m2=0, BYTE_t m3=0, BYTE_t m4=0, BYTE_t m5=0, BYTE_t m6=0, BYTE_t m7=0); // Extract the CanOpen message from the message delivered by the interface void HandleMessage(const Message &msg, const timeval_t &tv); // Compile CobId from node and function code WORD_t CobId(BYTE_t node, BYTE_t fcode) const; ClassDef(CanOpen, 0) // implementation of the can open layer }; #endif