1 /**
2  * CANopen trace interface.
3  *
4  * @file        CO_trace.h
5  * @ingroup     CO_trace
6  * @author      Janez Paternoster
7  * @copyright   2016 - 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_TRACE_H
28 #define CO_TRACE_H
29 
30 #ifdef __cplusplus
31 extern "C" {
32 #endif
33 
34 #include "CO_driver.h"
35 #include "CO_SDO.h"
36 
37 
38 /**
39  * @defgroup CO_trace Trace
40  * @ingroup CO_CANopen
41  * @{
42  *
43  * CANopen trace for recording variables over time.
44  *
45  * In embedded systems there is often a need to monitor some variables over time.
46  * Results are then displayed on graph, similar as in oscilloscope.
47  *
48  * CANopen trace is a configurable object, accessible via CANopen Object
49  * Dictionary, which records chosen variable over time. It generates a curve,
50  * which can be read via SDO and can then be displayed in a graph.
51  *
52  * CO_trace_process() runs in 1 ms intervals and monitors one variable. If it
53  * changes, it makes a record with timestamp into circular buffer. When trace is
54  * accessed by CANopen SDO object, it reads latest points from the the circular
55  * buffer, prints a SVG curve into string and sends it as a SDO response. If a
56  * SDO request was received from the same device, then no traffic occupies CAN
57  * network.
58  */
59 
60 
61 /**
62  * Start index of traceConfig and Trace objects in Object Dictionary.
63  */
64 #ifndef OD_INDEX_TRACE_CONFIG
65 #define OD_INDEX_TRACE_CONFIG   0x2301
66 #define OD_INDEX_TRACE          0x2401
67 #endif
68 
69 
70 /**
71  *  structure for reading variables and printing points for specific data type.
72  */
73 typedef struct {
74     /** Function pointer for getting the value from OD variable. **/
75     int32_t (*pGetValue) (void *OD_variable);
76     /** Function pointer for printing the start point to trace.plot */
77     uint32_t (*printPointStart)(char *s, uint32_t size, uint32_t timeStamp, int32_t value);
78     /** Function pointer for printing the point to trace.plot */
79     uint32_t (*printPoint)(char *s, uint32_t size, uint32_t timeStamp, int32_t value);
80     /** Function pointer for printing the end point to trace.plot */
81     uint32_t (*printPointEnd)(char *s, uint32_t size, uint32_t timeStamp, int32_t value);
82 } CO_trace_dataType_t;
83 
84 
85 /**
86  * Trace object.
87  */
88 typedef struct {
89     bool_t              enabled;        /**< True, if trace is enabled. */
90     CO_SDO_t           *SDO;            /**< From CO_trace_init(). */
91     uint32_t           *timeBuffer;     /**< From CO_trace_init(). */
92     int32_t            *valueBuffer;    /**< From CO_trace_init(). */
93     uint32_t            bufferSize;     /**< From CO_trace_init(). */
94     volatile uint32_t   writePtr;       /**< Location in buffer, which will be next written. */
95     volatile uint32_t   readPtr;        /**< Location in buffer, which will be next read. */
96     uint32_t            lastTimeStamp;  /**< Last time stamp. If zero, then last point contains last timestamp. */
97     void               *OD_variable;    /**< Pointer to variable, which is monitored */
98     const CO_trace_dataType_t *dt;      /**< Data type specific function pointers. **/
99     int32_t             valuePrev;      /**< Previous value of value. */
100     uint32_t           *map;            /**< From CO_trace_init(). */
101     uint8_t            *format;         /**< From CO_trace_init(). */
102     int32_t            *value;          /**< From CO_trace_init(). */
103     int32_t            *minValue;       /**< From CO_trace_init(). */
104     int32_t            *maxValue;       /**< From CO_trace_init(). */
105     uint32_t           *triggerTime;    /**< From CO_trace_init(). */
106     uint8_t            *trigger;        /**< From CO_trace_init(). */
107     int32_t            *threshold;      /**< From CO_trace_init(). */
108 } CO_trace_t;
109 
110 
111 /**
112  * Initialize trace object.
113  *
114  * Function must be called in the communication reset section.
115  *
116  * @param trace This object will be initialized.
117  * @param SDO SDO server object.
118  * @param enabled Is trace enabled.
119  * @param timeBuffer Memory block for storing time records.
120  * @param valueBuffer Memory block for storing value records.
121  * @param bufferSize Size of the above buffers.
122  * @param map Map to variable in Object Dictionary, which will be monitored. Same structure as in PDO.
123  * @param Format Format of the plot. If first bit is 1, above variable is unsigned. For more info see Object Dictionary.
124  * @param trigger If different than zero, trigger time is recorded, when variable goes through threshold.
125  * @param threshold Used with trigger.
126  * @param value Pointer to variable, which will show last value of the variable.
127  * @param minValue Pointer to variable, which will show minimum value of the variable.
128  * @param maxValue Pointer to variable, which will show maximum value of the variable.
129  * @param triggerTime Pointer to variable, which will show last trigger time of the variable.
130  * @param idx_OD_traceConfig Index in Object Dictionary.
131  * @param idx_OD_trace Index in Object Dictionary.
132  *
133  * @return 0 on success, -1 on error.
134  */
135 void CO_trace_init(
136         CO_trace_t             *trace,
137         CO_SDO_t               *SDO,
138         uint8_t                 enabled,
139         uint32_t               *timeBuffer,
140         int32_t                *valueBuffer,
141         uint32_t                bufferSize,
142         uint32_t               *map,
143         uint8_t                *format,
144         uint8_t                *trigger,
145         int32_t                *threshold,
146         int32_t                *value,
147         int32_t                *minValue,
148         int32_t                *maxValue,
149         uint32_t               *triggerTime,
150         uint16_t                idx_OD_traceConfig,
151         uint16_t                idx_OD_trace);
152 
153 
154 /**
155  * Process trace object.
156  *
157  * Function must be called cyclically in 1ms intervals.
158  *
159  * @param trace This object.
160  * @param timestamp Timestamp (usually in millisecond resolution).
161  *
162  * @return 0 on success, -1 on error.
163  */
164 void CO_trace_process(CO_trace_t *trace, uint32_t timestamp);
165 
166 #ifdef __cplusplus
167 }
168 #endif /*__cplusplus*/
169 
170 /** @} */
171 #endif
172