1 /**
2  * CANopen Process Data Object protocol.
3  *
4  * @file        CO_PDO.h
5  * @ingroup     CO_PDO
6  * @author      Janez Paternoster
7  * @copyright   2004 - 2020 Janez Paternoster
8  *
9  * This file is part of CANopenNode, an opensource CANopen Stack.
10  * Project home page is <https://github.com/CANopenNode/CANopenNode>.
11  * For more information on CANopen see <http://www.can-cia.org/>.
12  *
13  * Licensed under the Apache License, Version 2.0 (the "License");
14  * you may not use this file except in compliance with the License.
15  * You may obtain a copy of the License at
16  *
17  *     http://www.apache.org/licenses/LICENSE-2.0
18  *
19  * Unless required by applicable law or agreed to in writing, software
20  * distributed under the License is distributed on an "AS IS" BASIS,
21  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22  * See the License for the specific language governing permissions and
23  * limitations under the License.
24  */
25 
26 
27 #ifndef CO_PDO_H
28 #define CO_PDO_H
29 
30 #ifdef __cplusplus
31 extern "C" {
32 #endif
33 
34 /**
35  * @defgroup CO_PDO PDO
36  * @ingroup CO_CANopen
37  * @{
38  *
39  * CANopen Process Data Object protocol.
40  *
41  * Process data objects are used for real-time data transfer with no protocol
42  * overhead.
43  *
44  * TPDO with specific identifier is transmitted by one device and recieved by
45  * zero or more devices as RPDO. PDO communication parameters(COB-ID,
46  * transmission type, etc.) are in Object Dictionary at index 0x1400+ and
47  * 0x1800+. PDO mapping parameters (size and contents of the PDO) are in Object
48  * Dictionary at index 0x1600+ and 0x1A00+.
49  *
50  * Features of the PDO as implemented here, in CANopenNode:
51  *  - Dynamic PDO mapping.
52  *  - Map granularity of one byte.
53  *  - After RPDO is received from CAN bus, its data are copied to buffer.
54  *    Function CO_RPDO_process() (called by application) copies data to
55  *    mapped objects in Object Dictionary. Synchronous RPDOs are processed AFTER
56  *    reception of the next SYNC message.
57  *  - Function CO_TPDO_process() (called by application) sends TPDO if
58  *    necessary. There are possible different transmission types, including
59  *    automatic detection of Change of State of specific variable.
60  */
61 
62 
63 /**
64  * RPDO communication parameter. The same as record from Object dictionary (index 0x1400+).
65  */
66 typedef struct{
67     uint8_t             maxSubIndex;    /**< Equal to 2 */
68     /** Communication object identifier for message received. Meaning of the specific bits:
69         - Bit  0-10: COB-ID for PDO, to change it bit 31 must be set.
70         - Bit 11-29: set to 0 for 11 bit COB-ID.
71         - Bit 30:    If true, rtr are NOT allowed for PDO.
72         - Bit 31:    If true, node does NOT use the PDO. */
73     uint32_t            COB_IDUsedByRPDO;
74     /** Transmission type. Values:
75         - 0-240:   Reciving is synchronous, process after next reception of the SYNC object.
76         - 241-253: Not used.
77         - 254:     Manufacturer specific.
78         - 255:     Asynchronous. */
79     uint8_t             transmissionType;
80 }CO_RPDOCommPar_t;
81 
82 
83 /**
84  * RPDO mapping parameter. The same as record from Object dictionary (index 0x1600+).
85  */
86 typedef struct{
87     /** Actual number of mapped objects from 0 to 8. To change mapped object,
88     this value must be 0. */
89     uint8_t             numberOfMappedObjects;
90     /** Location and size of the mapped object. Bit meanings `0xIIIISSLL`:
91         - Bit  0-7:  Data Length in bits.
92         - Bit 8-15:  Subindex from object distionary.
93         - Bit 16-31: Index from object distionary. */
94     uint32_t            mappedObject1;
95     uint32_t            mappedObject2;  /**< Same */
96     uint32_t            mappedObject3;  /**< Same */
97     uint32_t            mappedObject4;  /**< Same */
98     uint32_t            mappedObject5;  /**< Same */
99     uint32_t            mappedObject6;  /**< Same */
100     uint32_t            mappedObject7;  /**< Same */
101     uint32_t            mappedObject8;  /**< Same */
102 }CO_RPDOMapPar_t;
103 
104 
105 /**
106  * TPDO communication parameter. The same as record from Object dictionary (index 0x1800+).
107  */
108 typedef struct{
109     uint8_t             maxSubIndex;    /**< Equal to 6 */
110     /** Communication object identifier for transmitting message. Meaning of the specific bits:
111         - Bit  0-10: COB-ID for PDO, to change it bit 31 must be set.
112         - Bit 11-29: set to 0 for 11 bit COB-ID.
113         - Bit 30:    If true, rtr are NOT allowed for PDO.
114         - Bit 31:    If true, node does NOT use the PDO. */
115     uint32_t            COB_IDUsedByTPDO;
116     /** Transmission type. Values:
117         - 0:       Transmiting is synchronous, specification in device profile.
118         - 1-240:   Transmiting is synchronous after every N-th SYNC object.
119         - 241-251: Not used.
120         - 252-253: Transmited only on reception of Remote Transmission Request.
121         - 254:     Manufacturer specific.
122         - 255:     Asinchronous, specification in device profile. */
123     uint8_t             transmissionType;
124     /** Minimum time between transmissions of the PDO in 100micro seconds.
125     Zero disables functionality. */
126     uint16_t            inhibitTime;
127     /** Not used */
128     uint8_t             compatibilityEntry;
129     /** Time between periodic transmissions of the PDO in milliseconds.
130     Zero disables functionality. */
131     uint16_t            eventTimer;
132     /** Used with numbered SYNC messages. Values:
133         - 0:       Counter of the SYNC message shall not be processed.
134         - 1-240:   The SYNC message with the counter value equal to this value
135                    shall be regarded as the first received SYNC message. */
136     uint8_t             SYNCStartValue;
137 }CO_TPDOCommPar_t;
138 
139 
140 /**
141  * TPDO mapping parameter. The same as record from Object dictionary (index 0x1A00+).
142  */
143 typedef struct{
144     /** Actual number of mapped objects from 0 to 8. To change mapped object,
145     this value must be 0. */
146     uint8_t             numberOfMappedObjects;
147     /** Location and size of the mapped object. Bit meanings `0xIIIISSLL`:
148         - Bit  0-7:  Data Length in bits.
149         - Bit 8-15:  Subindex from object distionary.
150         - Bit 16-31: Index from object distionary. */
151     uint32_t            mappedObject1;
152     uint32_t            mappedObject2;  /**< Same */
153     uint32_t            mappedObject3;  /**< Same */
154     uint32_t            mappedObject4;  /**< Same */
155     uint32_t            mappedObject5;  /**< Same */
156     uint32_t            mappedObject6;  /**< Same */
157     uint32_t            mappedObject7;  /**< Same */
158     uint32_t            mappedObject8;  /**< Same */
159 }CO_TPDOMapPar_t;
160 
161 
162 /**
163  * RPDO object.
164  */
165 typedef struct{
166     CO_EM_t            *em;             /**< From CO_RPDO_init() */
167     CO_SDO_t           *SDO;            /**< From CO_RPDO_init() */
168     CO_SYNC_t          *SYNC;           /**< From CO_RPDO_init() */
169     const CO_RPDOCommPar_t *RPDOCommPar;/**< From CO_RPDO_init() */
170     const CO_RPDOMapPar_t  *RPDOMapPar; /**< From CO_RPDO_init() */
171     uint8_t            *operatingState; /**< From CO_RPDO_init() */
172     uint8_t             nodeId;         /**< From CO_RPDO_init() */
173     uint16_t            defaultCOB_ID;  /**< From CO_RPDO_init() */
174     uint8_t             restrictionFlags;/**< From CO_RPDO_init() */
175     /** True, if PDO is enabled and valid */
176     bool_t              valid;
177     /** True, if PDO synchronous (transmissionType <= 240) */
178     bool_t              synchronous;
179     /** Data length of the received PDO message. Calculated from mapping */
180     uint8_t             dataLength;
181     /** Pointers to 8 data objects, where PDO will be copied */
182     uint8_t            *mapPointer[8];
183     /** Variable indicates, if new PDO message received from CAN bus. */
184     volatile void      *CANrxNew[2];
185     /** 8 data bytes of the received message. */
186     uint8_t             CANrxData[2][8];
187     CO_CANmodule_t     *CANdevRx;       /**< From CO_RPDO_init() */
188     uint16_t            CANdevRxIdx;    /**< From CO_RPDO_init() */
189 }CO_RPDO_t;
190 
191 
192 /**
193  * TPDO object.
194  */
195 typedef struct{
196     CO_EM_t            *em;             /**< From CO_TPDO_init() */
197     CO_SDO_t           *SDO;            /**< From CO_TPDO_init() */
198     CO_SYNC_t          *SYNC;           /**< From CO_TPDO_init() */
199     const CO_TPDOCommPar_t *TPDOCommPar;/**< From CO_TPDO_init() */
200     const CO_TPDOMapPar_t  *TPDOMapPar; /**< From CO_TPDO_init() */
201     uint8_t            *operatingState; /**< From CO_TPDO_init() */
202     uint8_t             nodeId;         /**< From CO_TPDO_init() */
203     uint16_t            defaultCOB_ID;  /**< From CO_TPDO_init() */
204     uint8_t             restrictionFlags;/**< From CO_TPDO_init() */
205     bool_t              valid;          /**< True, if PDO is enabled and valid */
206     /** Data length of the transmitting PDO message. Calculated from mapping */
207     uint8_t             dataLength;
208     /** If application set this flag, PDO will be later sent by
209     function CO_TPDO_process(). Depends on transmission type. */
210     uint8_t             sendRequest;
211     /** Pointers to 8 data objects, where PDO will be copied */
212     uint8_t            *mapPointer[8];
213     /** Each flag bit is connected with one mapPointer. If flag bit
214     is true, CO_TPDO_process() functiuon will send PDO if
215     Change of State is detected on value pointed by that mapPointer */
216     uint8_t             sendIfCOSFlags;
217     /** SYNC counter used for PDO sending */
218     uint8_t             syncCounter;
219     /** Inhibit timer used for inhibit PDO sending translated to microseconds */
220     uint32_t            inhibitTimer;
221     /** Event timer used for PDO sending translated to microseconds */
222     uint32_t            eventTimer;
223     CO_CANmodule_t     *CANdevTx;       /**< From CO_TPDO_init() */
224     CO_CANtx_t         *CANtxBuff;      /**< CAN transmit buffer inside CANdev */
225     uint16_t            CANdevTxIdx;    /**< From CO_TPDO_init() */
226 }CO_TPDO_t;
227 
228 
229 /**
230  * Initialize RPDO object.
231  *
232  * Function must be called in the communication reset section.
233  *
234  * @param RPDO This object will be initialized.
235  * @param em Emergency object.
236  * @param SDO SDO server object.
237  * @param operatingState Pointer to variable indicating CANopen device NMT internal state.
238  * @param nodeId CANopen Node ID of this device. If default COB_ID is used, value will be added.
239  * @param defaultCOB_ID Default COB ID for this PDO (without NodeId).
240  * See #CO_Default_CAN_ID_t
241  * @param restrictionFlags Flag bits indicates, how PDO communication
242  * and mapping parameters are handled:
243  *  - Bit1: If true, communication parameters are writeable only in pre-operational NMT state.
244  *  - Bit2: If true, mapping parameters are writeable only in pre-operational NMT state.
245  *  - Bit3: If true, communication parameters are read-only.
246  *  - Bit4: If true, mapping parameters are read-only.
247  * @param RPDOCommPar Pointer to _RPDO communication parameter_ record from Object
248  * dictionary (index 0x1400+).
249  * @param RPDOMapPar Pointer to _RPDO mapping parameter_ record from Object
250  * dictionary (index 0x1600+).
251  * @param idx_RPDOCommPar Index in Object Dictionary.
252  * @param idx_RPDOMapPar Index in Object Dictionary.
253  * @param CANdevRx CAN device for PDO reception.
254  * @param CANdevRxIdx Index of receive buffer in the above CAN device.
255  *
256  * @return #CO_ReturnError_t: CO_ERROR_NO or CO_ERROR_ILLEGAL_ARGUMENT.
257  */
258 CO_ReturnError_t CO_RPDO_init(
259         CO_RPDO_t              *RPDO,
260         CO_EM_t                *em,
261         CO_SDO_t               *SDO,
262         CO_SYNC_t              *SYNC,
263         uint8_t                *operatingState,
264         uint8_t                 nodeId,
265         uint16_t                defaultCOB_ID,
266         uint8_t                 restrictionFlags,
267         const CO_RPDOCommPar_t *RPDOCommPar,
268         const CO_RPDOMapPar_t  *RPDOMapPar,
269         uint16_t                idx_RPDOCommPar,
270         uint16_t                idx_RPDOMapPar,
271         CO_CANmodule_t         *CANdevRx,
272         uint16_t                CANdevRxIdx);
273 
274 
275 /**
276  * Initialize TPDO object.
277  *
278  * Function must be called in the communication reset section.
279  *
280  * @param TPDO This object will be initialized.
281  * @param em Emergency object.
282  * @param SDO SDO object.
283  * @param operatingState Pointer to variable indicating CANopen device NMT internal state.
284  * @param nodeId CANopen Node ID of this device. If default COB_ID is used, value will be added.
285  * @param defaultCOB_ID Default COB ID for this PDO (without NodeId).
286  * See #CO_Default_CAN_ID_t
287  * @param restrictionFlags Flag bits indicates, how PDO communication
288  * and mapping parameters are handled:
289  *  - Bit1: If true, communication parameters are writeable only in pre-operational NMT state.
290  *  - Bit2: If true, mapping parameters are writeable only in pre-operational NMT state.
291  *  - Bit3: If true, communication parameters are read-only.
292  *  - Bit4: If true, mapping parameters are read-only.
293  * @param TPDOCommPar Pointer to _TPDO communication parameter_ record from Object
294  * dictionary (index 0x1400+).
295  * @param TPDOMapPar Pointer to _TPDO mapping parameter_ record from Object
296  * dictionary (index 0x1600+).
297  * @param idx_TPDOCommPar Index in Object Dictionary.
298  * @param idx_TPDOMapPar Index in Object Dictionary.
299  * @param CANdevTx CAN device used for PDO transmission.
300  * @param CANdevTxIdx Index of transmit buffer in the above CAN device.
301  *
302  * @return #CO_ReturnError_t: CO_ERROR_NO or CO_ERROR_ILLEGAL_ARGUMENT.
303  */
304 CO_ReturnError_t CO_TPDO_init(
305         CO_TPDO_t              *TPDO,
306         CO_EM_t                *em,
307         CO_SDO_t               *SDO,
308         CO_SYNC_t              *SYNC,
309         uint8_t                *operatingState,
310         uint8_t                 nodeId,
311         uint16_t                defaultCOB_ID,
312         uint8_t                 restrictionFlags,
313         const CO_TPDOCommPar_t *TPDOCommPar,
314         const CO_TPDOMapPar_t  *TPDOMapPar,
315         uint16_t                idx_TPDOCommPar,
316         uint16_t                idx_TPDOMapPar,
317         CO_CANmodule_t         *CANdevTx,
318         uint16_t                CANdevTxIdx);
319 
320 
321 /**
322  * Verify Change of State of the PDO.
323  *
324  * Function verifies if variable mapped to TPDO has changed its value. Verified
325  * are only variables, which has set attribute _CO_ODA_TPDO_DETECT_COS_ in
326  * #CO_SDO_OD_attributes_t.
327  *
328  * Function may be called by application just before CO_TPDO_process() function,
329  * for example: `TPDOx->sendRequest = CO_TPDOisCOS(TPDOx); CO_TPDO_process(TPDOx, ....`
330  *
331  * @param TPDO TPDO object.
332  *
333  * @return True if COS was detected.
334  */
335 uint8_t CO_TPDOisCOS(CO_TPDO_t *TPDO);
336 
337 
338 /**
339  * Send TPDO message.
340  *
341  * Function prepares TPDO data from Object Dictionary variables. It should not
342  * be called by application, it is called from CO_TPDO_process().
343  *
344  *
345  * @param TPDO TPDO object.
346  *
347  * @return Same as CO_CANsend().
348  */
349 int16_t CO_TPDOsend(CO_TPDO_t *TPDO);
350 
351 
352 /**
353  * Process received PDO messages.
354  *
355  * Function must be called cyclically in any NMT state. It copies data from RPDO
356  * to Object Dictionary variables if: new PDO receives and PDO is valid and NMT
357  * operating state is operational. It does not verify _transmission type_.
358  *
359  * @param RPDO This object.
360  * @param syncWas True, if CANopen SYNC message was just received or transmitted.
361  */
362 void CO_RPDO_process(CO_RPDO_t *RPDO, bool_t syncWas);
363 
364 
365 /**
366  * Process transmitting PDO messages.
367  *
368  * Function must be called cyclically in any NMT state. It prepares and sends
369  * TPDO if necessary. If Change of State needs to be detected, function
370  * CO_TPDOisCOS() must be called before.
371  *
372  * @param TPDO This object.
373  * @param SYNC SYNC object. Ignored if NULL.
374  * @param syncWas True, if CANopen SYNC message was just received or transmitted.
375  * @param timeDifference_us Time difference from previous function call in [microseconds].
376  */
377 void CO_TPDO_process(
378         CO_TPDO_t              *TPDO,
379         bool_t                  syncWas,
380         uint32_t                timeDifference_us);
381 
382 #ifdef __cplusplus
383 }
384 #endif /*__cplusplus*/
385 
386 /** @} */
387 #endif
388