source: trunk/MagicSoft/Cosy/candrv/canopen.cc@ 1266

Last change on this file since 1266 was 1266, checked in by tbretz, 22 years ago
*** empty log message ***
File size: 11.5 KB
Line 
1/* ======================================================================== *\
2!
3! *
4! * This file is part of Stesy, the MAGIC Steering System
5! * Software. It is distributed to you in the hope that it can be a useful
6! * and timesaving tool in analysing Data of imaging Cerenkov telescopes.
7! * It is distributed WITHOUT ANY WARRANTY.
8! *
9! * Permission to use, copy, modify and distribute this software and its
10! * documentation for any purpose is hereby granted without fee,
11! * provided that the above copyright notice appear in all copies and
12! * that both that copyright notice and this permission notice appear
13! * in supporting documentation. It is provided "as is" without express
14! * or implied warranty.
15! *
16!
17!
18! Author(s): Thomas Bretz <mailto:tbretz@uni-sw.gwdg.de>, 2001
19!
20! Copyright: MAGIC Software Development, 2000-2001
21!
22!
23\* ======================================================================== */
24
25///////////////////////////////////////////////////////////////////////
26//
27// CanOpen
28//
29// implements the canopen layer over the raw device driver
30//
31///////////////////////////////////////////////////////////////////////
32#include "canopen.h"
33
34#include <iostream.h> // cout
35#include <iomanip.h> // setw, setfill
36
37ClassImp(CanOpen);
38
39// --------------------------------------------------------------------------
40//
41// Initializes a conditional and a mutex semaphore for all possible
42// PDO combinations
43//
44CanOpen::CanOpen(const char *dev, const int baud, MLog &out) : VmodIcan(dev, baud, out)
45{
46 for (int i=0; i<32; i++)
47 for (int j=0; j<4; j++)
48 {
49 pthread_cond_init(&fPdoCond[i][j], NULL);
50 pthread_mutex_init(&fPdoMux[i][j], NULL);
51 pthread_mutex_lock(&fPdoMux[i][j]);
52 }
53
54 lout << "- CanOpen initialized." << endl;
55}
56
57// --------------------------------------------------------------------------
58//
59// Destroys all conditional and mutex semaphores
60//
61CanOpen::~CanOpen()
62{
63 for (int i=0; i<32; i++)
64 for (int j=0; j<4; j++)
65 {
66 pthread_cond_destroy(&fPdoCond[i][j]);
67 pthread_mutex_destroy(&fPdoMux[i][j]);
68 }
69}
70
71// --------------------------------------------------------------------------
72//
73// This overloads VmodIcan::HandleCanMessage. It is called if a can
74// message was received with all message relevant data (COBId, data, time)
75// It distributes the data depending on its function code to several
76// functions (to be obverloaded)
77// In case of a PDO the conditional semaphore corresponding to this PDO
78// is raised (WaitForNextPDO)
79// HandleSDO: handles a SDO message
80// HandlePDO1/2/3/4:handles received PDOs
81//
82void CanOpen::HandleCanMessage(WORD_t cobid, BYTE_t *data, timeval_t *tv)
83{
84 const WORD_t fcode = cobid >> 7;
85
86 switch (fcode)
87 {
88 case kNMT:
89 cout << "NMT: " << hex ;
90 cout << "CobId: 0x" << cobid << " ";
91 cout << "cmd=0x" << (int)data[0] << " ";
92 cout << "node=" << dec << (int)data[1] << endl;
93 return;
94
95 case kSYNC:
96 cout << "Sync" << endl;
97 return;
98
99 case kSDO_RX:
100 {
101 const BYTE_t node = cobid & 0x1f;
102 const BYTE_t cmd = data[0];
103 const LWORD_t dat = data[4] | (data[5]<<8) | (data[6]<<16) | (data[7]<<24);
104 const WORD_t idx = data[1] | (data[2]<<8);
105 const WORD_t subidx = data[3];
106
107 HandleSDO(node, cmd, idx, subidx, dat, tv);
108
109 fSdoList.Del(node, idx, subidx);
110 }
111 return;
112
113 case kPDO1_TX:
114 {
115 const BYTE_t node = cobid & 0x1f;
116 HandlePDO1(node, data, tv);
117 pthread_cond_broadcast(&fPdoCond[node-1][0]);
118 }
119 return;
120
121 case kPDO2_TX:
122 {
123 const BYTE_t node = cobid & 0x1f;
124 HandlePDO2(node, data, tv);
125 pthread_cond_broadcast(&fPdoCond[node-1][1]);
126 }
127 return;
128
129 case kPDO3_TX:
130 {
131 const BYTE_t node = cobid & 0x1f;
132 HandlePDO3(node, data, tv);
133 pthread_cond_broadcast(&fPdoCond[node-1][2]);
134 }
135 return;
136
137 case kPDO4_TX:
138 {
139 const BYTE_t node = cobid & 0x1f;
140 HandlePDO4(node, data, tv);
141 pthread_cond_broadcast(&fPdoCond[node-1][3]);
142 }
143 return;
144 }
145
146 const BYTE_t node = cobid & 0x1f;
147 cout << "Function Code: 0x" << hex << fcode << " Node: " << dec << (int)node << endl;
148}
149
150// --------------------------------------------------------------------------
151//
152// Enables can messaged for a given node ID and function code.
153//
154void CanOpen::EnableCanMsg(BYTE_t node, BYTE_t fcode, int flag)
155{
156 if (node>=0x20)
157 return;
158
159 EnableCobId(CobId(node, fcode), flag);
160}
161
162// --------------------------------------------------------------------------
163//
164// Enables Emergency messages for a given node
165//
166void CanOpen::EnableEmcy(BYTE_t node)
167{
168 EnableCanMsg(node, kEMERGENCY);
169}
170
171
172// --------------------------------------------------------------------------
173//
174// Enables SDO rx messages for a given node
175//
176void CanOpen::EnableSdoRx(BYTE_t node)
177{
178 EnableCanMsg(node, kSDO_RX);
179}
180
181// --------------------------------------------------------------------------
182//
183// Enables PDO1 tx messages for a given node
184//
185void CanOpen::EnablePdo1Rx(BYTE_t node)
186{
187 EnableCanMsg(node, kPDO1_TX);
188}
189
190// --------------------------------------------------------------------------
191//
192// Enables PDO2 tx messages for a given node
193//
194void CanOpen::EnablePdo2Rx(BYTE_t node)
195{
196 EnableCanMsg(node, kPDO2_TX);
197}
198
199// --------------------------------------------------------------------------
200//
201// Enables PDO3 rx messages for a given node
202//
203void CanOpen::EnablePdo3Rx(BYTE_t node)
204{
205 EnableCanMsg(node, kPDO1_TX);
206}
207
208// --------------------------------------------------------------------------
209//
210// Enables PDO4 rx messages for a given node
211//
212void CanOpen::EnablePdo4Rx(BYTE_t node)
213{
214 EnableCanMsg(node, kPDO2_TX);
215}
216
217// --------------------------------------------------------------------------
218//
219// Sends a PDO1 message with the given data to the given node
220//
221void CanOpen::SendPDO1(BYTE_t node, BYTE_t data[8])
222{
223 SendCanFrame(CobId(node, kPDO1_TX), data);
224}
225
226// --------------------------------------------------------------------------
227//
228// Sends a PDO2 message with the given data to the given node
229//
230void CanOpen::SendPDO2(BYTE_t node, BYTE_t data[8])
231{
232 SendCanFrame(CobId(node, kPDO2_TX), data);
233}
234
235// --------------------------------------------------------------------------
236//
237// Sends a PDO3 message with the given data to the given node
238//
239void CanOpen::SendPDO3(BYTE_t node, BYTE_t data[8])
240{
241 SendCanFrame(CobId(node, kPDO3_TX), data);
242}
243
244// --------------------------------------------------------------------------
245//
246// Sends a PDO4 message with the given data to the given node
247//
248void CanOpen::SendPDO4(BYTE_t node, BYTE_t data[8])
249{
250 SendCanFrame(CobId(node, kPDO4_TX), data);
251}
252
253// --------------------------------------------------------------------------
254//
255// Sends a PDO1 message with the given data to the given node
256//
257void CanOpen::SendPDO1(BYTE_t node,
258 BYTE_t m0=0, BYTE_t m1=0, BYTE_t m2=0, BYTE_t m3=0,
259 BYTE_t m4=0, BYTE_t m5=0, BYTE_t m6=0, BYTE_t m7=0)
260{
261 BYTE_t msg[8] = { m0, m1, m2, m3, m4, m5, m6, m7 };
262 SendCanFrame(CobId(node, kPDO2_TX), msg);
263}
264
265// --------------------------------------------------------------------------
266//
267// Sends a PDO2 message with the given data to the given node
268//
269void CanOpen::SendPDO2(BYTE_t node,
270 BYTE_t m0=0, BYTE_t m1=0, BYTE_t m2=0, BYTE_t m3=0,
271 BYTE_t m4=0, BYTE_t m5=0, BYTE_t m6=0, BYTE_t m7=0)
272{
273 BYTE_t msg[8] = { m0, m1, m2, m3, m4, m5, m6, m7 };
274 SendCanFrame(CobId(node, kPDO2_TX), msg);
275}
276
277// --------------------------------------------------------------------------
278//
279// Sends a PDO3 message with the given data to the given node
280//
281void CanOpen::SendPDO3(BYTE_t node,
282 BYTE_t m0=0, BYTE_t m1=0, BYTE_t m2=0, BYTE_t m3=0,
283 BYTE_t m4=0, BYTE_t m5=0, BYTE_t m6=0, BYTE_t m7=0)
284{
285 BYTE_t msg[8] = { m0, m1, m2, m3, m4, m5, m6, m7 };
286 SendCanFrame(CobId(node, kPDO3_TX), msg);
287}
288
289// --------------------------------------------------------------------------
290//
291// Sends a PDO4 message with the given data to the given node
292//
293void CanOpen::SendPDO4(BYTE_t node,
294 BYTE_t m0=0, BYTE_t m1=0, BYTE_t m2=0, BYTE_t m3=0,
295 BYTE_t m4=0, BYTE_t m5=0, BYTE_t m6=0, BYTE_t m7=0)
296{
297 BYTE_t msg[8] = { m0, m1, m2, m3, m4, m5, m6, m7 };
298 SendCanFrame(CobId(node, kPDO4_TX), msg);
299}
300
301// --------------------------------------------------------------------------
302//
303// Sends a SDO message with the given data to the given node:
304// - index describing the dictionary index to set
305// - subindex describing the dictionary subindex of theindex to set
306// - val describing the value to set.
307// - store describes whether the sdo should be stored in a list to
308// be able to wait for an answer
309//
310void CanOpen::SendSDO(BYTE_t node, WORD_t idx, BYTE_t subidx, BYTE_t val, bool store)
311{
312 if (store)
313 fSdoList.Add(node, idx, subidx);
314
315 SendCanFrame(CobId(node, kSDO_TX), kSDO_RX1,
316 word_to_lsb(idx), word_to_msb(idx), subidx, val);
317}
318
319// --------------------------------------------------------------------------
320//
321// Sends a SDO message with the given data to the given node:
322// - index describing the dictionary index to set
323// - subindex describing the dictionary subindex of theindex to set
324// - val describing the value to set.
325// - store describes whether the sdo should be stored in a list to
326// be able to wait for an answer
327//
328void CanOpen::SendSDO(BYTE_t node, WORD_t idx, BYTE_t subidx, WORD_t val, bool store)
329{
330 if (store)
331 fSdoList.Add(node, idx, subidx);
332
333 SendCanFrame(CobId(node, kSDO_TX), kSDO_RX2,
334 word_to_lsb(idx), word_to_msb(idx), subidx,
335 word_to_lsb(val), word_to_msb(val));
336}
337
338// --------------------------------------------------------------------------
339//
340// Sends a SDO message with the given data to the given node:
341// - index describing the dictionary index to set
342// - subindex describing the dictionary subindex of theindex to set
343// - val describing the value to set.
344// - store describes whether the sdo should be stored in a list to
345// be able to wait for an answer
346//
347void CanOpen::SendSDO(BYTE_t node, WORD_t idx, BYTE_t subidx, LWORD_t val, bool store)
348{
349 if (store)
350 fSdoList.Add(node, idx, subidx);
351
352 SendCanFrame(CobId(node, kSDO_TX), kSDO_RX4,
353 word_to_lsb(idx), word_to_msb(idx), subidx,
354 word_to_lsb(val&0xffff), word_to_msb(val&0xffff),
355 word_to_lsb(val>>16), word_to_msb(val>>16));
356}
357
358// --------------------------------------------------------------------------
359//
360// Request a SDO message from the given node:
361// - index describing the dictionary index to request
362// - subindex describing the dictionary subindex of the index to request
363//
364void CanOpen::RequestSDO(BYTE_t node, WORD_t idx, BYTE_t subidx)
365{
366 fSdoList.Add(node, idx, subidx);
367
368 SendCanFrame(CobId(node, kSDO_TX), kSDO_RX_DATA, word_to_lsb(idx), word_to_msb(idx), subidx);
369}
370
371// --------------------------------------------------------------------------
372//
373// Send an NMT Message to the given node with command cmd
374//
375void CanOpen::SendNMT(BYTE_t node, BYTE_t cmd)
376{
377 SendCanFrame(CobId(0, kNMT), cmd, node);
378}
379
380// --------------------------------------------------------------------------
381//
382// Decodes node and function code into a CobId
383//
384WORD_t CanOpen::CobId(BYTE_t node, BYTE_t fcode) const
385{
386 return (fcode<<7) | node&0x1f;
387}
Note: See TracBrowser for help on using the repository browser.