| 1 | #ifndef COSY_CanOpen | 
|---|
| 2 | #define COSY_CanOpen | 
|---|
| 3 |  | 
|---|
| 4 | #ifndef ROOT_TCondition | 
|---|
| 5 | #include <TCondition.h> | 
|---|
| 6 | #endif | 
|---|
| 7 |  | 
|---|
| 8 | #ifdef __CINT__ | 
|---|
| 9 | typedef Byte_t   BYTE_t; | 
|---|
| 10 | typedef UShort_t WORD_t; | 
|---|
| 11 | typedef Short_t  WORDS_t; | 
|---|
| 12 | typedef UInt_t   LWORD_t; | 
|---|
| 13 | typedef Int_t    LWORDS_t; | 
|---|
| 14 | struct Message; | 
|---|
| 15 | struct FastMessage; | 
|---|
| 16 | #else | 
|---|
| 17 | #include "gendef.h" | 
|---|
| 18 | #include "dpm.h" | 
|---|
| 19 | #endif | 
|---|
| 20 |  | 
|---|
| 21 | #ifndef COSY_SdoList | 
|---|
| 22 | #include "sdolist.h" | 
|---|
| 23 | #endif | 
|---|
| 24 |  | 
|---|
| 25 | #ifndef COSY_MTimeout | 
|---|
| 26 | #include "MTimeout.h" | 
|---|
| 27 | #endif | 
|---|
| 28 |  | 
|---|
| 29 | //#define FALSE       0 | 
|---|
| 30 | //#define TRUE        1 | 
|---|
| 31 |  | 
|---|
| 32 | // CAL Function Codes | 
|---|
| 33 | // COB-ID = function code | node-id (5bits) | 
|---|
| 34 | #define kNMT           0x0 // only with COB-ID 0 | 
|---|
| 35 | #define kSYNC          0x1 // only with COB-ID 0 | 
|---|
| 36 | #define kTIMESTAMP     0x2 // only with COB-ID 0 | 
|---|
| 37 |  | 
|---|
| 38 | #define kEMERGENCY     0x1 | 
|---|
| 39 | #define kPDO1_TX       0x3 | 
|---|
| 40 | #define kPDO2_TX       0x5 | 
|---|
| 41 | #define kPDO3_TX       0x7 | 
|---|
| 42 | #define kPDO4_TX       0x9 | 
|---|
| 43 | #define kSDO_RX        0xb  // this is used to set data of the shaft encoder | 
|---|
| 44 | #define kSDO_TX        0xc  // this is used to request data from the shaft encoder | 
|---|
| 45 | #define kNodeguard     0xe | 
|---|
| 46 |  | 
|---|
| 47 | // NMT: no answer to NMT command | 
|---|
| 48 | // cob-id=0, command (byte), id (byte) | 
|---|
| 49 | #define kNMT_START     0x01 // change to operational state (start) | 
|---|
| 50 | #define kNMT_STOP      0x02 // change to prepared    state (stop) | 
|---|
| 51 | #define kNMT_PREOP     0x80 // enter pre operational state | 
|---|
| 52 | #define kNMT_RESET     0x81 // reset node (set parameter to power on values) | 
|---|
| 53 | #define kNMT_REINIT    0x82 // reset communication of node (set communication parameters to power on values) | 
|---|
| 54 |  | 
|---|
| 55 | // command for SDOs | 
|---|
| 56 | #define kSDO_LEN4      0x3 | 
|---|
| 57 | #define kSDO_LEN2      0xb | 
|---|
| 58 | #define kSDO_LEN1      0xf | 
|---|
| 59 |  | 
|---|
| 60 | #define kSDO_RXm4      0x22  // this is used with SDO_TX to send a maximum of 4 bytes | 
|---|
| 61 | #define kSDO_RX4       0x20|kSDO_LEN4  // this is used with SDO_TX to send 4 bytes | 
|---|
| 62 | #define kSDO_RX2       0x20|kSDO_LEN2  // this is used with SDO_TX to send 2 bytes | 
|---|
| 63 | #define kSDO_RX1       0x20|kSDO_LEN1  // this is used with SDO_TX to send 1 byte | 
|---|
| 64 | #define kSDO_RX_DATA   0x40            // this is used to request parameters from the encoder | 
|---|
| 65 | #define kSDO_TX4       0x40|kSDO_LEN4  // answer to 0x40 with 4 bytes of data | 
|---|
| 66 | #define kSDO_TX3       0x40|kSDO_LEN2  // answer to 0x40 with 2 bytes of data | 
|---|
| 67 | #define kSDO_TX1       0x40|kSDO_LEN1  // answer to 0x40 with 1 byte  of data | 
|---|
| 68 | #define kSDO_TX_OK     0x60            // answer to a SDO_TX message | 
|---|
| 69 | #define kSDO_TX_ERROR  0x80            // error message (instead of 0x60) | 
|---|
| 70 |  | 
|---|
| 71 | #define kWaitUnlimited 0 | 
|---|
| 72 | #define kDontWait      (-1) | 
|---|
| 73 |  | 
|---|
| 74 | class Interface; | 
|---|
| 75 |  | 
|---|
| 76 | typedef struct timeval timeval_t; | 
|---|
| 77 |  | 
|---|
| 78 | class CanOpen | 
|---|
| 79 | { | 
|---|
| 80 | private: | 
|---|
| 81 | Interface     *fInterface;      // Handle to the I/O interface | 
|---|
| 82 | PendingSDOList fSdoList;        // List for pending SDOs | 
|---|
| 83 | TCondition     fPdoCond[32][4]; // one for every PDO of every node | 
|---|
| 84 |  | 
|---|
| 85 | protected: | 
|---|
| 86 | virtual void Start();           // Start CanOpen communication | 
|---|
| 87 | virtual void Stop();            // Stop  CanOpen communcation | 
|---|
| 88 |  | 
|---|
| 89 | virtual bool HasError() const; | 
|---|
| 90 |  | 
|---|
| 91 | private: | 
|---|
| 92 | // | 
|---|
| 93 | // Handle can objects arrived at the CanOpen interface | 
|---|
| 94 | // | 
|---|
| 95 | virtual void HandleSDO(BYTE_t node, BYTE_t cmd, WORD_t idx, BYTE_t subidx, LWORD_t data, const timeval_t &tv)=0; | 
|---|
| 96 | virtual void HandlePDO1(BYTE_t node, const BYTE_t *data, const timeval_t &tv)=0; | 
|---|
| 97 | virtual void HandlePDO2(BYTE_t node, const BYTE_t *data, const timeval_t &tv)=0; | 
|---|
| 98 | virtual void HandlePDO3(BYTE_t node, const BYTE_t *data, const timeval_t &tv)=0; | 
|---|
| 99 | virtual void HandlePDO4(BYTE_t node, const BYTE_t *data, const timeval_t &tv)=0; | 
|---|
| 100 | virtual void HandleNodeguard(BYTE_t node, const timeval_t &tv)=0; | 
|---|
| 101 | virtual void HandleEmergency(BYTE_t node, const timeval_t &tv)=0; | 
|---|
| 102 |  | 
|---|
| 103 | // Handle message arrived at the CanOpen interface and split into can objects | 
|---|
| 104 | virtual void HandleCanMessage(WORD_t cobid, const BYTE_t *data, const timeval_t &tv); | 
|---|
| 105 |  | 
|---|
| 106 | public: | 
|---|
| 107 | CanOpen(); | 
|---|
| 108 | virtual ~CanOpen(); | 
|---|
| 109 |  | 
|---|
| 110 | void SetInterface(Interface *f) { fInterface=f; } // Set Handle to the interface | 
|---|
| 111 | Bool_t HasConnection() const; | 
|---|
| 112 |  | 
|---|
| 113 | // Send a Process Data Object (PDO) to the CanOpen bus | 
|---|
| 114 | void SendPDO1(BYTE_t node, BYTE_t data[8]); | 
|---|
| 115 | void SendPDO2(BYTE_t node, BYTE_t data[8]); | 
|---|
| 116 | void SendPDO3(BYTE_t node, BYTE_t data[8]); | 
|---|
| 117 | void SendPDO4(BYTE_t node, BYTE_t data[8]); | 
|---|
| 118 | void SendPDO1(BYTE_t node, | 
|---|
| 119 | BYTE_t m0=0, BYTE_t m1=0, BYTE_t m2=0, BYTE_t m3=0, | 
|---|
| 120 | BYTE_t m4=0, BYTE_t m5=0, BYTE_t m6=0, BYTE_t m7=0); | 
|---|
| 121 | void SendPDO2(BYTE_t node, | 
|---|
| 122 | BYTE_t m0=0, BYTE_t m1=0, BYTE_t m2=0, BYTE_t m3=0, | 
|---|
| 123 | BYTE_t m4=0, BYTE_t m5=0, BYTE_t m6=0, BYTE_t m7=0); | 
|---|
| 124 | void SendPDO3(BYTE_t node, | 
|---|
| 125 | BYTE_t m0=0, BYTE_t m1=0, BYTE_t m2=0, BYTE_t m3=0, | 
|---|
| 126 | BYTE_t m4=0, BYTE_t m5=0, BYTE_t m6=0, BYTE_t m7=0); | 
|---|
| 127 | void SendPDO4(BYTE_t node, | 
|---|
| 128 | BYTE_t m0=0, BYTE_t m1=0, BYTE_t m2=0, BYTE_t m3=0, | 
|---|
| 129 | BYTE_t m4=0, BYTE_t m5=0, BYTE_t m6=0, BYTE_t m7=0); | 
|---|
| 130 |  | 
|---|
| 131 | // Send a Service Data Object (SDO) to a CanOpen device (aka. write parameter) | 
|---|
| 132 | void SendSDO(BYTE_t node, WORD_t idx, BYTE_t subidx, BYTE_t val, bool store); | 
|---|
| 133 | void SendSDO(BYTE_t node, WORD_t idx, BYTE_t subidx, WORD_t val, bool store); | 
|---|
| 134 | void SendSDO(BYTE_t node, WORD_t idx, BYTE_t subidx, LWORD_t val, bool store); | 
|---|
| 135 |  | 
|---|
| 136 | void SendSDO(BYTE_t node, WORD_t idx, BYTE_t val, bool store)   { SendSDO(node, idx, 0, val, store); } | 
|---|
| 137 | void SendSDO(BYTE_t node, WORD_t idx, WORD_t val, bool store)   { SendSDO(node, idx, 0, val, store); } | 
|---|
| 138 | void SendSDO(BYTE_t node, WORD_t idx, LWORD_t val, bool store)  { SendSDO(node, idx, 0, val, store); } | 
|---|
| 139 |  | 
|---|
| 140 | // Send other objects | 
|---|
| 141 | void SendNMT(BYTE_t node, BYTE_t cmd); | 
|---|
| 142 | void SendNodeguard(BYTE_t node); | 
|---|
| 143 |  | 
|---|
| 144 | // Request a Service Data Object (SDO) from a CanOpen device (aka. read parameter) | 
|---|
| 145 | void RequestSDO(BYTE_t node, WORD_t idx, BYTE_t subidx=0); | 
|---|
| 146 |  | 
|---|
| 147 | // Enable interface for pass-through of a kind of can-object | 
|---|
| 148 | void EnableSdoRx(BYTE_t node); | 
|---|
| 149 | void EnablePdo1Rx(BYTE_t node); | 
|---|
| 150 | void EnablePdo2Rx(BYTE_t node); | 
|---|
| 151 | void EnablePdo3Rx(BYTE_t node); | 
|---|
| 152 | void EnablePdo4Rx(BYTE_t node); | 
|---|
| 153 | void EnableEmcy(BYTE_t node); | 
|---|
| 154 | void EnableNodeguard(BYTE_t node); | 
|---|
| 155 |  | 
|---|
| 156 | // Enable interface for pass-through of a can-object | 
|---|
| 157 | void EnableCanMsg(BYTE_t node, BYTE_t fcode, int flag=TRUE); | 
|---|
| 158 |  | 
|---|
| 159 | // Wait until the next Pdo object has arrived | 
|---|
| 160 | void WaitForNextPdo1(BYTE_t node) { node -= 1; fPdoCond[node][0].Wait(); } | 
|---|
| 161 | void WaitForNextPdo2(BYTE_t node) { node -= 1; fPdoCond[node][1].Wait(); } | 
|---|
| 162 | void WaitForNextPdo3(BYTE_t node) { node -= 1; fPdoCond[node][2].Wait(); } | 
|---|
| 163 | void WaitForNextPdo4(BYTE_t node) { node -= 1; fPdoCond[node][3].Wait(); } | 
|---|
| 164 |  | 
|---|
| 165 | // Wait for arrival of a return to a given Sdo (or all axpected Sdos) | 
|---|
| 166 | bool WaitForSdos(WORDS_t ms=500); | 
|---|
| 167 | bool WaitForSdo(BYTE_t node, WORD_t idx, BYTE_t subidx, WORDS_t ms=500); | 
|---|
| 168 |  | 
|---|
| 169 | virtual int StopWaitingForSDO() const { return FALSE; } | 
|---|
| 170 |  | 
|---|
| 171 | // Low level function to send rawcan frames | 
|---|
| 172 | void SendCanFrame(WORD_t cobid, BYTE_t m[8], BYTE_t rtr=0); | 
|---|
| 173 | void SendCanFrame(WORD_t cobid, | 
|---|
| 174 | BYTE_t m0=0, BYTE_t m1=0, BYTE_t m2=0, BYTE_t m3=0, | 
|---|
| 175 | BYTE_t m4=0, BYTE_t m5=0, BYTE_t m6=0, BYTE_t m7=0); | 
|---|
| 176 |  | 
|---|
| 177 | // Extract the CanOpen message from the message delivered by the interface | 
|---|
| 178 | void HandleMessage(const Message &msg, const timeval_t &tv); | 
|---|
| 179 |  | 
|---|
| 180 | // Compile CobId from node and function code | 
|---|
| 181 | WORD_t CobId(BYTE_t node, BYTE_t fcode) const; | 
|---|
| 182 |  | 
|---|
| 183 | ClassDef(CanOpen, 0) // implementation of the can open layer | 
|---|
| 184 | }; | 
|---|
| 185 |  | 
|---|
| 186 | #endif | 
|---|