Serial Wombat Arduino Library
Loading...
Searching...
No Matches
SerialWombat.cpp
Go to the documentation of this file.
1#include "Arduino.h"
2#include "SerialWombat.h"
3/*
4Copyright 2020-2022 Broadwell Consulting Inc.
5
6Serial Wombat is a registered trademark in the US of Broadwell Consulting Inc.
7
8Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the "Software"),
10 * to deal in the Software without restriction, including without limitation
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 * and/or sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following conditions:
14
15The above copyright notice and this permission notice shall be included in
16 * all copies or substantial portions of the Software.
17
18THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
22 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
23 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
24 * OTHER DEALINGS IN THE SOFTWARE.
25*/
26
29
30
34
35
36
40
41
42
43
44
45int16_t SerialWombatChip::begin(uint8_t i2cAddress)
46{
47 //i2cInterface = &Wire;
48 //address = i2cAddress;
49 return begin(Wire, i2cAddress);
50}
51
52int SerialWombatChip::sendPacket(uint8_t tx[], bool retryIfEchoDoesntMatch)
53{
54 uint8_t rx[8];
55 return (sendPacket(tx,rx, retryIfEchoDoesntMatch));
56}
57
58int SerialWombatChip::sendPacket(uint8_t tx[], uint8_t rx[], bool retryIfEchoDoesntMatch, uint8_t startBytesToMatch, uint8_t endBytesToMatch)
59{
60 uint8_t retry = 4; //TODO communicationErrorRetries;
61
62
63 if (!retryIfEchoDoesntMatch)
64 {
65 retry = 1;
66 }
67
68 int result = 0;
69 for (int i = 0; i < 8; ++i)
70 {
71 rx[i] = 0;
72 }
73 while (retry)
74 {
75 result = sendPacket(tx, rx);
76
77 if (rx[0] == 'E')
78 {
79 return result;
80 }
81 uint8_t i;
82 bool success = true;
83 for (i = 0; i < startBytesToMatch; ++i)
84 {
85 if ( tx[i] != rx[i])
86 {
87 success = false;
88 }
89 }
90 for (i = 8- endBytesToMatch; i < 8; ++i)
91 {
92 if (tx[i] != rx[i])
93 {
94 success = false;
95 }
96 }
97 if (success)
98 {
99 return (result);
100 }
101 --retry;
102 delayMicroseconds(100);
103 {
104 //char echoTx[] = "!COM_ERR";
105 //sendPacket((uint8_t*)echoTx);
106 continue;
107 }
108 delayMicroseconds(100);
109
110 }
111
112 return(result);
113}
114
115int SerialWombatChip::sendPacket(uint8_t tx[], uint8_t rx[])
116{
117 if (sendReadyTime != 0 )
118 {
119 unsigned long currentTime = millis();
120 if (currentTime < sendReadyTime)
121 {
122 delay(sendReadyTime - currentTime);
123
124 }
125 sendReadyTime = 0;
126 initialize();
127 }
128
129 if (Serial != NULL)
130 {
131 if (_currentlyCommunicating)
132 {
133 //TODO return (-1 * SW_ERROR_REENTRANCY_NOT_SUPPORTED);
134 }
135 _currentlyCommunicating = true;
136 while (Serial->read() >= 0);
137 Serial->write(tx, 8); //TODO add addressing, CRC
138 uint32_t millisWrite = millis();
139 int bytesRx = 0;
140
141 uint32_t timenow = millis();
142 while (bytesRx < 8 && timenow <= (millisWrite + 50))
143 {
144 int32_t data = Serial->read();
145 if (data >= 0)
146 {
147 rx[bytesRx] = data;
148 ++bytesRx;
149 }
150 timenow = millis();
151 }
152 if (bytesRx < 8)
153 {
154 if (errorHandler != NULL)
155 {
156 errorHandler(SW_ERROR_LESS_THAN_8_BYTES_RETURNED,this);
157 }
158 ++errorCount;
159 _currentlyCommunicating = false;
161 }
162 if (rx[0] == 'E')
163 {
165 if (errorHandler != NULL)
166 {
167 errorHandler(lastErrorCode,this);
168 }
169 lastErrorCode *= -1;
170 ++errorCount;
171 _currentlyCommunicating = false;
172 return (lastErrorCode);
173 }
174 _currentlyCommunicating = false;
175 return (8);
176 }
177
178 if (i2cInterface != NULL)
179 {
180 int bytesWritten;
181 uint8_t retry = communicationErrorRetries;
182 int i2cResult;
183 int count = 8;
184 //while (tx[count - 1] == 0x55)
185 //{
186 // --count;
187 //}
188 if (_currentlyCommunicating)
189 {
190 //TODO return (-1 * SW_ERROR_REENTRANCY_NOT_SUPPORTED);
191 }
192 _currentlyCommunicating = true;
193 while (retry)
194 {
195 --retry;
196 i2cInterface->beginTransmission(address);
197 bytesWritten = i2cInterface->write(tx, 8);
198 i2cResult = i2cInterface->endTransmission();
199
200 if (bytesWritten == 8 && i2cResult == 0)
201 {
202 retry = 0;
203 }
204 else
205 {
206 delayMicroseconds(100);
207 continue;
208 }
209 }
210 //delay(3);
211 //Serial->setTimeout(10);
212 delayMicroseconds(100);
213 i2cInterface->requestFrom(address, (uint8_t)8);
214
215 count = 0;
216 int r = 0;
217 while (r >= 0 && count < 8)
218 {
219 r = i2cInterface->read();
220
221 if (r >= 0)
222 {
223 rx[count] = (uint8_t) r;
224 ++count;
225 }
226 else
227 {
228 break;
229 }
230 }
231
232 if (count < 8)
233 {
234 delayMicroseconds(100);
235 i2cInterface->requestFrom(address, (uint8_t)8);
236
237 count = 0;
238 while (i2cInterface->available() && count < 8)
239 {
240 int r = i2cInterface->read();
241
242 if (r >= 0)
243 {
244 rx[count] = (uint8_t)r;
245 ++count;
246 }
247 else
248 {
249 break;
250 }
251 }
252 if (count < 8)
253 {
254 if (errorHandler != NULL)
255 {
256 errorHandler(SW_ERROR_LESS_THAN_8_BYTES_RETURNED, this);
257 }
258 ++errorCount;
259 _currentlyCommunicating = false;
261 }
262 }
263 if (rx[0] == 'E')
264 {
266 if (errorHandler != NULL)
267 {
268 errorHandler(lastErrorCode,this);
269 }
270 lastErrorCode *= -1;
271 ++errorCount;
272 _currentlyCommunicating = false;
273 return (lastErrorCode);
274 }
275 }
276 _currentlyCommunicating = false;
277 return(0);
278
279}
281{
282
283 if (Serial != NULL)
284 {
285 Serial->write(tx, 8); //TODO add addressing, CRC
286 return (8);
287 }
288
289 if (i2cInterface != NULL)
290 {
291 i2cInterface->beginTransmission(address);
292 i2cInterface->write(tx, 8);
293 i2cInterface->endTransmission();
294 }
295 return(0);
296
297}
298
300{
301 uint8_t rx[8];
302
303 if (_asleep)
304 {
305 _asleep = false;
306 uint8_t txw[8] = { '!','!','!','!','!','!','!','!' }; //TODO adapt for UART
307 sendPacket(txw);
308 delayMicroseconds(200);
309 }
310
311 return(sendPacket(tx,rx));
312
313 if (sendReadyTime != 0)
314 {
315 unsigned long currentTime = millis();
316 if (currentTime < sendReadyTime)
317 {
318 delay(sendReadyTime - currentTime);
319
320 }
321 sendReadyTime = 0;
322 initialize();
323 }
324
325 if (Serial != NULL)
326 {
327 return Serial->write(tx, 8); //TODO add addressing, CRC
328 }
329
330 if (i2cInterface != NULL)
331 {
332 i2cInterface->beginTransmission(address);
333 i2cInterface->write(tx, 8);
334 i2cInterface->endTransmission();
335 }
336 return(0);
337
338}
339
341{
342 char s[10];
343 Serial.print("Comm Error on SW at addr ");
344 sprintf(s, "0x%02X ", sw->address);
345 Serial.print(s);
346 Serial.print(" Error code ");
347
348 Serial.print(error);
349
350 Serial.print(" Error count ");
351 Serial.print(sw->errorCount);
352
353 uint8_t errorCmd[8];
354 if (sw->readLastErrorCommand(errorCmd) >= 0)
355 {
356 Serial.print(" Command: ");
357 for (int i = 0; i < 8; ++i)
358 {
359 sprintf(s, "0x%02X ", errorCmd[i]);
360 Serial.print(s);
361 }
362 }
363
364 Serial.println();
365}
366
void SerialWombatSerialErrorHandlerBrief(uint16_t error, SerialWombatChip *sw)
a sample error handler that can be registered with registerErrorHandler to report protocol errors on ...
@ SW_ERROR_LESS_THAN_8_BYTES_RETURNED
(#48) The Serial Wombat Chip returned less than 8 bytes (Used at host level, not firmware)
Class for a Serial Wombat chip. Each Serial Wombat chip on a project should have its own instance.
uint8_t address
The I2C address of the SerialWombatChip instance.
uint32_t sendReadyTime
uint8_t communicationErrorRetries
How many times to retry a packet if communcation bus (such as I2C) error.
int sendPacketNoResponse(uint8_t tx[])
Send an 8 byte packet to the Serial Wombat chip, don't wait for a response.
int16_t lastErrorCode
The last error code returned as part of a protocol error message expressed as a positive integer.
int16_t begin(HardwareSerial &serial, bool reset=true)
initialize a Serial Wombat chip to use a Serial Interface.
int sendPacket(uint8_t tx[], uint8_t rx[])
Send an 8 byte packet to the Serial Wombat chip and wait for 8 bytes back.
uint16_t returnErrorCode(uint8_t *rx)
int16_t initialize()
uint16_t errorCount
Incremented every time a communication or command error is detected.
int16_t readLastErrorCommand(uint8_t *cmd)
Returns the last Serial Wombat command that produced a protocol error.