Serial Wombat Arduino Library
Loading...
Searching...
No Matches
SerialWombatSPI.h
Go to the documentation of this file.
1#pragma once
2#include "SerialWombat.h"
5
6/*
7Copyright 2026 Broadwell Consulting Inc.
8
9"Serial Wombat" is a registered trademark of Broadwell Consulting Inc. in
10the United States. See SerialWombat.com for usage guidance.
11
12Permission is hereby granted, free of charge, to any person obtaining a
13 * copy of this software and associated documentation files (the "Software"),
14 * to deal in the Software without restriction, including without limitation
15 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
16 * and/or sell copies of the Software, and to permit persons to whom the
17 * Software is furnished to do so, subject to the following conditions:
18
19The above copyright notice and this permission notice shall be included in
20 * all copies or substantial portions of the Software.
21
22THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
25 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
26 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
27 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
28 * OTHER DEALINGS IN THE SOFTWARE.
29*/
30
31// Define values the same as in Arduino SPI.
32
33#ifndef MSBFIRST
34#define MSBFIRST 1
35#endif
36// Don't define LSB first because it's not supported.
37
38
39#ifndef SPI_MODE0
40#define SPI_MODE0 0x00
41#define SPI_MODE1 0x04
42#define SPI_MODE3 0x0C
43#endif
44
45
48public:
49 SerialWombatSPISettings(uint32_t clock = 0, uint8_t bitOrder = MSBFIRST, uint8_t dataMode = SPI_MODE0) {
50 (void)clock; // Clock is not configurable, so ignore this parameter.
51 (void)bitOrder; // Bit order is not configurable, so ignore this parameter.
52 (void)dataMode;
53 }
54};
55
96
98{
99public:
104 SerialWombatSPI(SerialWombatChip& serialWombat):SerialWombatPin(serialWombat){}
105
106
116 int16_t begin( uint8_t pin,uint8_t SPIMode, uint8_t MOSIpin = 255, uint8_t MISOpin = 255, uint8_t CSpin = 255)
117 {
118
119 _pin = pin;
121 if (SPIMode == SPI_MODE1)
122 {
123 SPIMode = 1;
124 }
125 else if (SPIMode == SPI_MODE3)
126 {
127 SPIMode = 3;
128 }
129
130 if (SPIMode != 0 && SPIMode != 1 && SPIMode != 3)
131 {
133 }
134 uint8_t tx[8] = { 200, _pin,_pinMode, SPIMode,MOSIpin,MISOpin, CSpin, 0x55 };
135 uint8_t rx[8];
136 return _sw.sendPacket(tx, rx);
137
138 }
139
140 /* @brief Not needed for this class, included for congruency with Arduino SPIClass. Does nothing.
141
142 */
144 (void)settings; // Settings are not used because clock speed and bit order are fixed.
145 }
146
147 /* @brief Not needed for this class, included for congruency with Arduino SPIClass. Does nothing.
148
149 */
150 static void end(){}
151 /*
152 @brief Write to the SPI bus (MOSI pin) and also receive (MISO pin)
153 @param data The byte to send out the MOSI pin if configured. The byte received on the MISO pin during the transaction is returned.
154 @param csSaysStayLow If true, the chip select pin (if configured) will remain low after the transaction.
155 @return The byte received on the MISO pin during the transaction if configured.
156 */
157
158 uint8_t transfer(uint8_t data, bool csSaysStayLow = false)
159 {
160 uint8_t tx[8] = { 201, _pin, _pinMode, 8, data,0x55, 0x55, 0x55 };
161 uint8_t rx[8];
162
163 if (csSaysStayLow)
164 {
165 tx[0] = 202; // Use a different command to indicate that CS should stay low after the transaction.
166 }
167 int16_t result = _sw.sendPacket(tx, rx);
168 if (result < 0) {
169 // Handle error if needed. For now, just return 0 on error.
170 return 0;
171 }
172 return rx[4]; // The received byte is expected to be in rx[2].
173 }
174
175 /*
176 @brief Write to the SPI bus (MOSI pin) and also receive (MISO pin)
177 @param data The word to send out the MOSI pin if configured. The word will be send Least Significant Byte, most signficant bit first.
178 @param csSaysStayLow If true, the chip select pin (if configured) will remain low after the transaction.
179 @return The byte received on the MISO pin during the transaction if configured.
180 */
181
182 uint16_t transfer(uint16_t data, bool csSaysStayLow = false) {
183 uint8_t tx[8] = { 201, _pin, _pinMode, 16, SW_LE16(data), 0x55 };
184 uint8_t rx[8];
185
186 if (csSaysStayLow)
187 {
188 tx[0] = 202; // Use a different command to indicate that CS should stay low after the transaction.
189 }
190 int16_t result = _sw.sendPacket(tx, rx);
191 if (result < 0) {
192 // Handle error if needed. For now, just return 0 on error.
193 return 0;
194 }
195 return ((((uint16_t)rx[5]) << 8) + (uint16_t)rx[4]); // The received word is expected to be in rx[4] and rx[5].
196 }
197
198 /*
199 @brief Write to the SPI bus (MOSI pin) and also receive (MISO pin)
200 @param buf The array to send and receive data. The length of the array is determined by the count parameter.
201 @param csSaysStayLow If true, the chip select pin (if configured) will remain low after the transaction.
202 @return The byte received on the MISO pin during the transaction if configured.
203 */
204
205 void transfer(void* buf, size_t count, bool csSaysStayLow = false) {
206
207 if (_sw.isSW08())
208 {
209 while (count >= 5)
210 {
211 uint8_t tx[8] = { 204, _pin, _pinMode, ((uint8_t*)buf)[0], ((uint8_t*)buf)[1], ((uint8_t*)buf)[2], ((uint8_t*)buf)[3], ((uint8_t*)buf)[4] };
212 uint8_t rx[8];
213
214
215 count -= 5;
216 if (count == 0 && !csSaysStayLow)
217 {
218 --tx[0]; // Send a zero byte to indicate the end of the transaction and allow the chip select to go high again.
219 }
220 _sw.sendPacket(tx, rx);
221 ((uint8_t*)buf)[0] = rx[3];
222 ((uint8_t*)buf)[1] = rx[4];
223 ((uint8_t*)buf)[2] = rx[5];
224 ((uint8_t*)buf)[3] = rx[6];
225 ((uint8_t*)buf)[4] = rx[7];
226 buf = (void*)((uint8_t*)buf + 5);
227 }
228 if (count > 0)
229 {
230 uint8_t tx[8] = { 201, _pin, _pinMode,(uint8_t)(count * 8), 0x55, 0x55, 0x55, 0x55 };
231 for (size_t i = 0; i < count; ++i)
232 {
233 tx[4 + i] = ((uint8_t*)buf)[i];
234 }
235 uint8_t rx[8];
236
237 if (csSaysStayLow)
238 {
239 tx[0] = 202; // Use a different command to indicate that CS should stay low after the transaction.
240 }
241 int16_t result = _sw.sendPacket(tx, rx);
242 if (result < 0) {
243 // Handle error if needed. For now, just return 0 on error.
244 return;
245 }
246 for (size_t i = 0; i < count; ++i)
247 {
248 ((uint8_t*)buf)[i] = rx[4 + i];
249 }
250 }
251
252 }
253 else // SW18AB can only transfer 1 byte at a time to minimize the chance of frame overflows.
254 {
255 while (count > 0)
256 {
257 uint8_t tx[8] = { 202, _pin, _pinMode, 8, ((uint8_t*)buf)[0],0x55, 0x55, 0x55 };
258 uint8_t rx[8];
259
260 -- count;
261 if(count == 0 && !csSaysStayLow)
262 {
263 tx[0] = 201;
264 }
265 int16_t result = _sw.sendPacket(tx, rx);
266 if (result < 0) {
267 // Handle error if needed. For now, just return 0 on error.
268 return;
269 }
270 *(uint8_t*)buf = rx[4]; // The received byte is expected to be in rx[4].
271 buf = (void*)((uint8_t*)buf + 1);
272 }
273 }
274
275};
276
277 int16_t transferPacketUpTo32Bits(uint8_t* outBuf,uint8_t* inBuf, size_t bitCount, bool csSaysStayLow = false) {
278 if (bitCount > 32) {
279 // Handle error: bitCount exceeds maximum packet size.
280 return -1; // Return an error code or handle as appropriate.
281 }
282 uint8_t tx[8] = { 201, _pin, _pinMode, (uint8_t)(bitCount), 0x55, 0x55, 0x55, 0x55 };
283 if (csSaysStayLow) {
284 tx[0] = 202; // Use a different command to indicate that CS should stay low after the transaction.
285 }
286 uint8_t byteCount = (bitCount + 7) / 8; // Calculate the number of bytes needed to represent the bits.
287 if (outBuf != nullptr) {
288 for (size_t i = 0; i < byteCount; ++i) {
289 tx[4 + i] = outBuf[i];
290 }
291 }
292 uint8_t rx[8];
293
294 if (csSaysStayLow) {
295 tx[0] = 202; // Use a different command to indicate that CS should stay low after the transaction.
296 }
297 int16_t result = _sw.sendPacket(tx, rx);
298 if (result < 0) {
299 // Handle error if needed. For now, just return on error.
300 return result;
301 }
302 if (inBuf != nullptr) {
303 for (size_t i = 0; i < byteCount; ++i) {
304 inBuf[i] = rx[4 + i];
305 }
306 }
307 return bitCount;
308
309 };
310
311 int16_t transferPacket40Bits(uint8_t* outBuf,uint8_t* inBuf, bool csSaysStayLow = false) {
312
313 uint8_t tx[8] = { 203, _pin, _pinMode, 0x55, 0x55, 0x55, 0x55, 0x55 };
314 if (outBuf != nullptr) {
315 for (size_t i = 0; i < 5; ++i) {
316 tx[3 + i] = outBuf[i];
317 }
318 }
319 uint8_t rx[8];
320
321 if (csSaysStayLow) {
322 tx[0] = 204; // Use a different command to indicate that CS should stay low after the transaction.
323 }
324 int16_t result = _sw.sendPacket(tx, rx);
325 if (result < 0) {
326 // Handle error if needed. For now, just return on error.
327 return result;
328 }
329 if (inBuf != nullptr) {
330 for (size_t i = 0; i < 5; ++i) {
331 inBuf[i] = rx[3 + i];
332 }
333 }
334 return 40;
335};
336
337 int16_t setCSHigh() { // this will not be supported until 2.2.4
338
339 uint8_t tx[8] = { 205, _pin, _pinMode, 0x55, 0x55, 0x55, 0x55, 0x55 };
340 int16_t result = _sw.sendPacket(tx);
341 return result;
342};
343};
344
345
#define SW_LE16(_a)
Convert a uint16_t to two bytes in little endian format for array initialization.
@ PIN_MODE_SPI
(41)
@ SW_ERROR_INVALID_PARAMETER_3
(#17) The pin configuration parameter in Byte 3 was invalid
Class for a Serial Wombat chip. Each Serial Wombat chip on a project should have its own instance.
SerialWombatChip & _sw
SerialWombatPin(SerialWombatChip &serialWombatChip)
Instantiates a Serial Wombat Pin.
uint8_t pin()
Returns the current SW pin number. Used primarily for virtual calls by derived classes.
int16_t begin(uint8_t pin, uint8_t SPIMode, uint8_t MOSIpin=255, uint8_t MISOpin=255, uint8_t CSpin=255)
uint16_t transfer(uint16_t data, bool csSaysStayLow=false)
uint8_t transfer(uint8_t data, bool csSaysStayLow=false)
int16_t transferPacketUpTo32Bits(uint8_t *outBuf, uint8_t *inBuf, size_t bitCount, bool csSaysStayLow=false)
static void end()
SerialWombatSPI(SerialWombatChip &serialWombat)
Constructor for the SerialWombatSPI class.
int16_t transferPacket40Bits(uint8_t *outBuf, uint8_t *inBuf, bool csSaysStayLow=false)
static void beginTransaction(SerialWombatSPISettings settings)
void transfer(void *buf, size_t count, bool csSaysStayLow=false)
A class for storing SPI settings. This isn't actually used, but included for congruency with Arduino.
SerialWombatSPISettings(uint32_t clock=0, uint8_t bitOrder=MSBFIRST, uint8_t dataMode=SPI_MODE0)