1
+ /*
2
+ MIT License
3
+
4
+ Copyright (c) 2024 Maximilian Mönikes
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ of this software and associated documentation files (the "Software"), to deal
8
+ in the Software without restriction, including without limitation the rights
9
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ copies of the Software, and to permit persons to whom the Software is
11
+ furnished to do so, subject to the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be included in all
14
+ copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ SOFTWARE.
23
+ */
24
+
25
+
26
+ #include " TLE9012.h"
27
+
28
+ HardwareSerial* hisoUART;
29
+
30
+
31
+ TLE9012::TLE9012 () // Constructor
32
+ {
33
+
34
+ }
35
+
36
+
37
+ TLE9012::~TLE9012 () // Destructor
38
+ {
39
+
40
+ }
41
+
42
+
43
+
44
+
45
+ void TLE9012::init (HardwareSerial* serial, uint32_t baudrate=1000000 )// Driver init
46
+ {
47
+ hisoUART = serial;
48
+ hisoUART->begin (baudrate,SERIAL_8N1,16 ,17 );
49
+ }
50
+
51
+ void TLE9012::wakeUp ()
52
+ {
53
+
54
+ iso_uart_status_t status;
55
+ status = isoUART_TIMEOUT;
56
+
57
+ uint8_t wakeupbuffer[2 ];
58
+ wakeupbuffer[0 ] = 0xAA ;
59
+ wakeupbuffer[1 ] = 0xAA ;
60
+ wakeupbuffer[2 ] = 0xAA ;
61
+
62
+
63
+ isoUARTClearRXBUffer ();
64
+ hisoUART->write (wakeupbuffer,2 );
65
+
66
+ uint32_t starttime = millis ();
67
+ while ((millis ()-starttime) < ISOUART_TIMEOUT)
68
+ {
69
+ if (hisoUART->available () > 1 )
70
+ {
71
+ status = isoUART_OK;
72
+ break ;
73
+ }
74
+ }
75
+ }
76
+
77
+ // Low Level Routines for direct register Access
78
+ iso_uart_status_t TLE9012::readRegisterSingle (uint8_t nodeID, uint16_t regaddress, uint16_t * result)
79
+ {
80
+ iso_uart_status_t status;
81
+ uint8_t response_buffer[9 ];
82
+
83
+ status = isoUART_TIMEOUT;
84
+
85
+ isoUARTClearRXBUffer ();
86
+ isoUARTReadRequest (nodeID, regaddress);
87
+
88
+ uint32_t starttime = millis ();
89
+ while ((millis ()-starttime) < ISOUART_TIMEOUT)
90
+ {
91
+ if (hisoUART->available () > 8 )
92
+ {
93
+ hisoUART->readBytes (response_buffer,9 );
94
+ status = isoUART_OK;
95
+ break ;
96
+ }
97
+ }
98
+
99
+ // Check if Timeout occured
100
+ if (status != isoUART_OK)
101
+ {
102
+ status = isoUART_TIMEOUT;
103
+ return status;
104
+ }
105
+
106
+
107
+ msb_first_converter (&(response_buffer[4 ]),5 );
108
+ uint8_t crc = crc8 (&response_buffer[4 ],5 );
109
+
110
+ *result = (((uint16_t ) response_buffer[6 ])<<8 ) | ((uint16_t ) response_buffer[7 ]);
111
+
112
+ if (crc != response_buffer[8 ]);
113
+ // status = isoUART_CRC_ERROR;
114
+
115
+ return status;
116
+ }
117
+
118
+ iso_uart_status_t TLE9012::writeRegisterSingle (uint8_t nodeID, uint16_t regaddress, uint16_t databuffer) // Write data to a single register
119
+ {
120
+
121
+ iso_uart_status_t status;
122
+ uint8_t response_buffer[7 ];
123
+
124
+ status = isoUART_TIMEOUT;
125
+
126
+ isoUARTClearRXBUffer ();
127
+ isoUARTWriteRequest (nodeID, regaddress, databuffer);
128
+
129
+ uint32_t starttime = millis ();
130
+ while ((millis ()-starttime) < ISOUART_TIMEOUT)
131
+ {
132
+ if (hisoUART->available () > 6 )
133
+ {
134
+ hisoUART->readBytes (response_buffer,7 );
135
+ status = isoUART_OK;
136
+ break ;
137
+ }
138
+ }
139
+
140
+ // Check if Timeout occured
141
+ if (status != isoUART_OK)
142
+ {
143
+ status = isoUART_TIMEOUT;
144
+ return status;
145
+ }
146
+
147
+ return status;
148
+ }
149
+
150
+ iso_uart_status_t TLE9012::readRegisterBroadcast (uint16_t regaddress, uint16_t * result) // Write a broadcast to all devices in the daisy chain
151
+ {
152
+ iso_uart_status_t status;
153
+ uint8_t response_buffer[N_DEVICES*5 +4 ];
154
+
155
+ status = isoUART_TIMEOUT;
156
+
157
+ isoUARTClearRXBUffer ();
158
+ isoUARTReadRequest (BROADCAST_ID, regaddress);
159
+
160
+ uint32_t starttime = millis ();
161
+ while ((millis ()-starttime) < ISOUART_TIMEOUT)
162
+ {
163
+ if (hisoUART->available () > (3 +(5 *N_DEVICES)))
164
+ {
165
+ hisoUART->readBytes (response_buffer,4 +5 *N_DEVICES);
166
+ status = isoUART_OK;
167
+ break ;
168
+ }
169
+ }
170
+
171
+ // Check if Timeout occured
172
+ if (status != isoUART_OK)
173
+ {
174
+ status = isoUART_TIMEOUT;
175
+ return status;
176
+ }
177
+
178
+ msb_first_converter (&response_buffer[4 ],N_DEVICES*5 );
179
+
180
+ for (uint8_t n = 0 ; n < N_DEVICES; n++)
181
+ {
182
+ uint8_t crc = crc8 (&response_buffer[4 +(n*N_DEVICES)],5 );
183
+ result[n] = (((uint16_t ) response_buffer[6 +(n*N_DEVICES)])<<8 ) | ((uint16_t ) response_buffer[7 +(n*N_DEVICES)]);
184
+ if (crc != 0 )
185
+ status = isoUART_CRC_ERROR;
186
+ }
187
+
188
+
189
+ return status;
190
+ }
191
+
192
+ iso_uart_status_t TLE9012::writeRegisterBroadcast (uint16_t regaddress, uint16_t databuffer) // Read a register as broadcast from all devices in the chain
193
+ {
194
+
195
+ iso_uart_status_t status;
196
+ uint8_t response_buffer[7 ];
197
+
198
+ status = isoUART_TIMEOUT;
199
+
200
+ isoUARTClearRXBUffer ();
201
+ isoUARTWriteRequest (BROADCAST_ID, regaddress, databuffer);
202
+ uint32_t starttime = millis ();
203
+ while ((millis ()-starttime) < ISOUART_TIMEOUT)
204
+ {
205
+ if (hisoUART->available () > 6 )
206
+ {
207
+ hisoUART->readBytes (response_buffer,7 );
208
+ status = isoUART_OK;
209
+ break ;
210
+ }
211
+ }
212
+
213
+ // Check if Timeout occured
214
+ if (status != isoUART_OK)
215
+ {
216
+ status = isoUART_TIMEOUT;
217
+ return status;
218
+ }
219
+
220
+ return status;
221
+ }
222
+
223
+ iso_uart_status_t TLE9012::configureMultiread (multiread_cfg_t cfg) // Write a multiread configuration to all devices in the daisy chain
224
+ {
225
+
226
+ }
227
+
228
+ iso_uart_status_t TLE9012::multiRead (multread_result_t * databuffer) // Multiread command from all devices in the chain
229
+ {
230
+
231
+ }
232
+
233
+ // Private Functions start here
234
+ uint8_t TLE9012::crc8 (uint8_t * buffer, uint16_t len)
235
+ {
236
+ const uint8_t polynomial = 0x1D ;
237
+ uint8_t crc = 0xFF ;
238
+
239
+ for (uint16_t i = 0 ; i < len; i++)
240
+ {
241
+ crc ^= buffer[i];
242
+
243
+ for (uint8_t j = 0 ; j < 8 ; j++)
244
+ {
245
+ if ((crc & 0x80 ) != 0 )
246
+ {
247
+ crc = (crc<<1 )^polynomial;
248
+ }
249
+ else
250
+ crc = crc << 1 ;
251
+ }
252
+ }
253
+
254
+ return crc^0xFF ;
255
+ }
256
+
257
+ uint8_t TLE9012::msb_first_converter (uint8_t * data, uint16_t len)
258
+ {
259
+ for (uint16_t n = 0 ; n < len; n++)
260
+ {
261
+ data[n] = ((data[n] & 0xF0 ) >> 4 ) | ((data[n] & 0x0F ) << 4 );
262
+ data[n] = ((data[n] & 0xCC ) >> 2 ) | ((data[n] & 0x33 ) << 2 );
263
+ data[n] = ((data[n] & 0xAA ) >> 1 ) | ((data[n] & 0x55 ) << 1 );
264
+ }
265
+ return 0 ;
266
+ }
267
+
268
+ void TLE9012::isoUARTWriteRequest (uint8_t nodeID, uint8_t regaddress, uint16_t data)
269
+ {
270
+ uint8_t writebuffer[6 ];
271
+ writebuffer[0 ] = 0x1E ; // Syncframe
272
+ writebuffer[1 ] = nodeID | WRITECOMMAND;
273
+ writebuffer[2 ] = regaddress;
274
+ writebuffer[3 ] = (uint8_t )(data >> 8 );
275
+ writebuffer[4 ] = (uint8_t )(data & 0xFF );
276
+ writebuffer[5 ] = 0x00 ;
277
+
278
+ writebuffer[5 ] = crc8 (writebuffer,5 );
279
+ msb_first_converter (writebuffer, 6 );
280
+
281
+ hisoUART->write (writebuffer,6 );
282
+ }
283
+
284
+ void TLE9012::isoUARTReadRequest (uint8_t nodeID, uint8_t regaddress)
285
+ {
286
+ uint8_t writebuffer[4 ];
287
+ writebuffer[0 ] = 0x1E ;
288
+ writebuffer[1 ] = nodeID;
289
+ writebuffer[2 ] = regaddress;
290
+ writebuffer[3 ] = 0x00 ;
291
+
292
+ writebuffer[3 ] = crc8 (writebuffer,3 );
293
+ msb_first_converter (writebuffer, 4 );
294
+ hisoUART->write (writebuffer,4 );
295
+ }
296
+
297
+ void TLE9012::isoUARTClearRXBUffer ()
298
+ {
299
+ while (hisoUART->available ())
300
+ uint8_t null = hisoUART->read ();
301
+ }
0 commit comments