Skip to content

Commit 002b0f6

Browse files
authored
Merge pull request #29 from embedded-creations/callbackptr
Allow for passing a custom pointer to callback function
2 parents 840272c + 858ab2d commit 002b0f6

File tree

2 files changed

+158
-6
lines changed

2 files changed

+158
-6
lines changed
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
//
2+
// Copyright (c) 2012 Christopher Baker <https://christopherbaker.net>
3+
//
4+
// SPDX-License-Identifier: MIT
5+
//
6+
7+
// This example is PacketSerialReverseEcho modified to use PacketSerial from within a class
8+
9+
#include <PacketSerial.h>
10+
11+
// This function takes a byte buffer and reverses it.
12+
void reverse(uint8_t* buffer, size_t size)
13+
{
14+
uint8_t tmp;
15+
16+
for (size_t i = 0; i < size / 2; i++)
17+
{
18+
tmp = buffer[i];
19+
buffer[i] = buffer[size - i - 1];
20+
buffer[size - i - 1] = tmp;
21+
}
22+
}
23+
24+
class EchoClass {
25+
public:
26+
void begin(unsigned long speed) {
27+
// If we want to receive packets, we must specify a packet handler function.
28+
// The packet handler is a custom function with a signature like the
29+
// onPacketReceived function below.
30+
myPacketSerial.setPacketHandler(&onPacketReceived, this);
31+
32+
myPacketSerial.begin(speed);
33+
}
34+
35+
void loop() {
36+
// The PacketSerial::update() method attempts to read in any incoming serial
37+
// data and emits received and decoded packets via the packet handler
38+
// function specified by the user in the void setup() function.
39+
//
40+
// The PacketSerial::update() method should be called once per loop(). Failure
41+
// to call the PacketSerial::update() frequently enough may result in buffer
42+
// serial overflows.
43+
myPacketSerial.update();
44+
45+
// Check for a receive buffer overflow (optional).
46+
if (myPacketSerial.overflow())
47+
{
48+
// Send an alert via a pin (e.g. make an overflow LED) or return a
49+
// user-defined packet to the sender.
50+
//
51+
// Ultimately you may need to just increase your recieve buffer via the
52+
// template parameters (see the README.md).
53+
}
54+
}
55+
56+
private:
57+
// C-style callbacks can't use non-static methods, so we use a static method that receives "this" as the sender argument: https://wiki.c2.com/?VirtualStaticIdiom
58+
static void onPacketReceived(const void* sender, const uint8_t* buffer, size_t size) {
59+
((EchoClass*)sender)->onPacketReceived(buffer, size);
60+
}
61+
62+
// This is our handler callback function.
63+
// When an encoded packet is received and decoded, it will be delivered here.
64+
// The `buffer` is a pointer to the decoded byte array. `size` is the number of
65+
// bytes in the `buffer`.
66+
void onPacketReceived(const uint8_t* buffer, size_t size) {
67+
// In this example, we will simply reverse the contents of the array and send
68+
// it back to the sender.
69+
70+
// Make a temporary buffer.
71+
uint8_t tempBuffer[size];
72+
73+
// Copy the packet into our temporary buffer.
74+
memcpy(tempBuffer, buffer, size);
75+
76+
// Reverse our temporaray buffer.
77+
reverse(tempBuffer, size);
78+
79+
// Send the reversed buffer back to the sender. The send() method will encode
80+
// the whole buffer as as single packet, set packet markers, etc.
81+
// The `tempBuffer` is a pointer to the `tempBuffer` array and `size` is the
82+
// number of bytes to send in the `tempBuffer`.
83+
myPacketSerial.send(tempBuffer, size);
84+
}
85+
86+
PacketSerial myPacketSerial;
87+
};
88+
89+
// By default, PacketSerial automatically wraps the built-in `Serial` object.
90+
// While it is still possible to use the Serial object directly, it is
91+
// recommended that the user let the PacketSerial object manage all serial
92+
// communication. Thus the user should not call Serial.write(), Serial.print(),
93+
// etc. Additionally the user should not use the serialEvent() framework.
94+
//
95+
// By default, PacketSerial uses COBS encoding and has a 256 byte receive
96+
// buffer. This can be adjusted by the user by replacing `PacketSerial` with
97+
// a variation of the `PacketSerial_<COBS, 0, BufferSize>` template found in
98+
// PacketSerial.h.
99+
100+
EchoClass myEchoClass;
101+
102+
void setup()
103+
{
104+
// We begin communication with our PacketSerial object by setting the
105+
// communication speed in bits / second (baud).
106+
myEchoClass.begin(115200);
107+
}
108+
109+
110+
void loop()
111+
{
112+
// Do your program-specific loop() work here as usual.
113+
114+
myEchoClass.loop();
115+
}

src/PacketSerial.h

Lines changed: 43 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,8 @@ class PacketSerial_
5454
_receiveBufferIndex(0),
5555
_stream(nullptr),
5656
_onPacketFunction(nullptr),
57-
_onPacketFunctionWithSender(nullptr)
57+
_onPacketFunctionWithSender(nullptr),
58+
_senderPtr(nullptr)
5859
{
5960
}
6061

@@ -224,18 +225,23 @@ class PacketSerial_
224225
_receiveBufferIndex,
225226
_decodeBuffer);
226227

228+
// clear the index here so that the callback function can call update() if needed and receive more data
229+
_receiveBufferIndex = 0;
230+
_recieveBufferOverflow = false;
231+
227232
if (_onPacketFunction)
228233
{
229234
_onPacketFunction(_decodeBuffer, numDecoded);
230235
}
231236
else if (_onPacketFunctionWithSender)
232237
{
233-
_onPacketFunctionWithSender(this, _decodeBuffer, numDecoded);
238+
_onPacketFunctionWithSender(_senderPtr, _decodeBuffer, numDecoded);
234239
}
235-
}
236240

237-
_receiveBufferIndex = 0;
238-
_recieveBufferOverflow = false;
241+
} else {
242+
_receiveBufferIndex = 0;
243+
_recieveBufferOverflow = false;
244+
}
239245
}
240246
else
241247
{
@@ -302,6 +308,7 @@ class PacketSerial_
302308
{
303309
_onPacketFunction = onPacketFunction;
304310
_onPacketFunctionWithSender = nullptr;
311+
_senderPtr = nullptr;
305312
}
306313

307314
/// \brief Set the function that will receive decoded packets.
@@ -333,13 +340,42 @@ class PacketSerial_
333340
///
334341
/// myPacketSerial.setPacketHandler(&onPacketReceived);
335342
///
343+
/// You can also register an arbitrary void* pointer to be passed to your packet handler method.
344+
/// This is most useful when PacketSerial is used inside a class, to pass a pointer to
345+
/// the containing class:
346+
///
347+
/// class EchoClass {
348+
/// public:
349+
/// void begin(unsigned long speed) {
350+
/// myPacketSerial.setPacketHandler(&onPacketReceived, this);
351+
/// myPacketSerial.begin(speed);
352+
/// }
353+
///
354+
/// // C-style callbacks can't use non-static methods,
355+
/// // so we use a static method that receives "this" as the sender argument:
356+
/// // https://wiki.c2.com/?VirtualStaticIdiom
357+
/// static void onPacketReceived(const void* sender, const uint8_t* buffer, size_t size) {
358+
/// ((EchoClass*)sender)->onPacketReceived(buffer, size);
359+
/// }
360+
///
361+
/// void onPacketReceived(const uint8_t* buffer, size_t size) {
362+
/// // we can now use myPacketSerial as needed here
363+
/// }
364+
///
365+
/// PacketSerial myPacketSerial;
366+
/// };
367+
///
336368
/// Setting a packet handler will remove all other packet handlers.
337369
///
338370
/// \param onPacketFunctionWithSender A pointer to the packet handler function.
339-
void setPacketHandler(PacketHandlerFunctionWithSender onPacketFunctionWithSender)
371+
/// \param senderPtr Optional pointer to a void* pointer, default argument will pass a pointer to the sending PacketSerial instance to the callback
372+
void setPacketHandler(PacketHandlerFunctionWithSender onPacketFunctionWithSender, void * senderPtr = nullptr)
340373
{
341374
_onPacketFunction = nullptr;
342375
_onPacketFunctionWithSender = onPacketFunctionWithSender;
376+
_senderPtr = senderPtr;
377+
// for backwards compatibility, the default _senderPtr is "this", but you can't use "this" as a default argument
378+
if(!senderPtr) _senderPtr = this;
343379
}
344380

345381
/// \brief Check to see if the receive buffer overflowed.
@@ -384,6 +420,7 @@ class PacketSerial_
384420

385421
PacketHandlerFunction _onPacketFunction = nullptr;
386422
PacketHandlerFunctionWithSender _onPacketFunctionWithSender = nullptr;
423+
void* _senderPtr = nullptr;
387424
};
388425

389426

0 commit comments

Comments
 (0)