Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: Autoflight2018_22_MODSERIAL
Fork of MODSERIAL by
Revision 18:21ef26402365, committed 2011-04-21
- Comitter:
- AjK
- Date:
- Thu Apr 21 09:20:41 2011 +0000
- Parent:
- 17:6c9b57c14868
- Child:
- 19:a158936322cc
- Commit message:
- 1.18 See ChangeLog.c
Changed in this revision
--- a/ChangeLog.c Tue Mar 08 01:42:25 2011 +0000
+++ b/ChangeLog.c Thu Apr 21 09:20:41 2011 +0000
@@ -1,5 +1,21 @@
/* $Id:$
+1.18 20 April 2011
+
+ * All callbacks now use MODSERIAL_callback (rather than Mbed's FunctionPointer[1] type)
+ to store and invoke it's callbacks. This allows MODSERIAL to pass a parameter
+ to callbacks. The function prototype is now void func(MODSERIAL_IRQ_INFO *q).
+ * Callbacks now pass a pointer to a MODSERIAL_IRQ_INFO class type.
+ This class holds a pointer to the MODSERIAL object that invoked the callback
+ thus freeing callbacks need to use the global variable of the original
+ MODSERIAL instance.
+ * MODSERIAL_IRQ_INFO also declares public functions that are protected within MODSERIAL
+ thus allowing certain functions to be restricted to callback context only.
+ * New function MODSERIAL_IRQ_INFO::rxDiscardLastChar() allows an rxCallback function
+ to remove the character that was just placed into the RX buffer.
+
+ [1] http://mbed.org/users/AjK/libraries/FPointer/latest/docs/
+
1.17 08/Mar/2011
Fixed a memory leak in the DMA code.
@@ -38,7 +54,7 @@
1.10 - 23/11/2010
- * Reanme the DMA callback from attach_dma_complete() to attach_dmaSendComplete()
+ * Rename the DMA callback from attach_dma_complete() to attach_dmaSendComplete()
1.9 - 23/11/2010
--- a/INIT.cpp Tue Mar 08 01:42:25 2011 +0000
+++ b/INIT.cpp Thu Apr 21 09:20:41 2011 +0000
@@ -30,6 +30,8 @@
{
disableIrq();
+ callbackInfo.setSerial(this);
+
switch(_uidx) {
case 0: _base = LPC_UART0; break;
case 1: _base = LPC_UART1; break;
--- a/ISR_RX.cpp Tue Mar 08 01:42:25 2011 +0000
+++ b/ISR_RX.cpp Thu Apr 21 09:20:41 2011 +0000
@@ -29,7 +29,7 @@
MODSERIAL::isr_rx(void)
{
if (! _base || buffer_size[RxIrq] == 0 || buffer[RxIrq] == (char *)NULL) {
- _isr[RxIrq].call();
+ _isr[RxIrq].call(&this->callbackInfo);
return;
}
@@ -37,9 +37,9 @@
rxc = (char)(_RBR & 0xFF);
if ( MODSERIAL_RX_BUFFER_FULL ) {
buffer_overflow[RxIrq] = rxc; // Oh dear, no room in buffer.
- _isr[RxOvIrq].call();
- }
- else {
+ _isr[RxOvIrq].call(&this->callbackInfo);
+ }
+ else {
if (buffer[RxIrq] != (char *)NULL) {
buffer[RxIrq][buffer_in[RxIrq]] = rxc;
buffer_count[RxIrq]++;
@@ -48,10 +48,10 @@
buffer_in[RxIrq] = 0;
}
}
- _isr[RxIrq].call();
+ _isr[RxIrq].call(&this->callbackInfo);
}
if (auto_detect_char == rxc) {
- _isr[RxAutoDetect].call();
+ _isr[RxAutoDetect].call(&this->callbackInfo);
}
}
}
--- a/ISR_TX.cpp Tue Mar 08 01:42:25 2011 +0000
+++ b/ISR_TX.cpp Thu Apr 21 09:20:41 2011 +0000
@@ -29,7 +29,7 @@
MODSERIAL::isr_tx(bool doCallback)
{
if (! _base || buffer_size[TxIrq] == 0 || buffer[TxIrq] == (char *)NULL) {
- _isr[TxIrq].call();
+ _isr[TxIrq].call(&this->callbackInfo);
return;
}
@@ -40,12 +40,12 @@
if (buffer_out[TxIrq] >= buffer_size[TxIrq]) {
buffer_out[TxIrq] = 0;
}
- if (doCallback) _isr[TxIrq].call();
+ if (doCallback) _isr[TxIrq].call(&this->callbackInfo);
}
if ( MODSERIAL_TX_BUFFER_EMPTY ) {
_IER = 1;
- _isr[TxEmpty].call();
+ _isr[TxEmpty].call(&this->callbackInfo);
}
}
--- a/MODSERIAL.cpp Tue Mar 08 01:42:25 2011 +0000
+++ b/MODSERIAL.cpp Thu Apr 21 09:20:41 2011 +0000
@@ -105,5 +105,24 @@
}
}
+int
+MODSERIAL::rxDiscardLastChar(void)
+{
+ // This function can only be called indirectly from
+ // an rxCallback function. Therefore, we know we
+ // just placed a char into the buffer.
+ char c = buffer[RxIrq][buffer_in[RxIrq]];
+
+ if (buffer_count[RxIrq]) {
+ buffer_count[RxIrq]--;
+ buffer_in[RxIrq]--;
+ if (buffer_in[RxIrq] < 0) {
+ buffer_in[RxIrq] = buffer_size[RxIrq] - 1;
+ }
+ }
+
+ return (int)c;
+}
+
}; // namespace AjK ends
--- a/MODSERIAL.h Tue Mar 08 01:42:25 2011 +0000
+++ b/MODSERIAL.h Thu Apr 21 09:20:41 2011 +0000
@@ -45,6 +45,135 @@
namespace AjK {
+// Forward reference.
+class MODSERIAL;
+
+/**
+ * @author Andy Kirkham
+ * @see http://mbed.org/cookbook/MODSERIAL
+ * @see example3a.cpp
+ * @see example3b.cpp
+ * @see API
+ *
+ * <b>MODSERIAL_IRQ_INFO</b> is a class used to pass information (and access to protected
+ * MODSERIAL functions) to IRQ callbacks.
+ */
+class MODSERIAL_IRQ_INFO
+{
+public:
+ friend class MODSERIAL;
+
+ MODSERIAL *serial;
+
+ MODSERIAL_IRQ_INFO() { serial = 0; }
+
+ /** rxDiscardLastChar()
+ *
+ * Remove the last char placed into the rx buffer.
+ * This is an operation that can only be performed
+ * by an rxCallback function.
+ * @ingroup API
+ * @return The byte removed from the buffer.
+ */
+ int rxDiscardLastChar(void);
+
+protected:
+
+ /** setSerial()
+ *
+ * Used internally by MODSERIAL to set the "this" pointer
+ * of the MODSERIAL that created this object.
+ * @ingroup INTERNAL
+ * @param A pointer to a MODSERIAL object instance.
+ */
+ void setSerial(MODSERIAL *s) { serial = s; }
+};
+
+// Forward reference dummy class.
+class MODSERIAL_callback_dummy;
+
+/**
+ * @author Andy Kirkham
+ * @see http://mbed.org/cookbook/MODSERIAL
+ * @see example3a.cpp
+ * @see example3b.cpp
+ * @see API
+ *
+ * <b>MODSERIAL_callback</b> is a class used to hold application callbacks that
+ * MODSERIAL can invoke on certain events.
+ */
+class MODSERIAL_callback
+{
+protected:
+
+ //! C callback function pointer.
+ void (*c_callback)(MODSERIAL_IRQ_INFO *);
+
+ //! C++ callback object/method pointer (the object part).
+ MODSERIAL_callback_dummy *obj_callback;
+
+ //! C++ callback object/method pointer (the method part).
+ void (MODSERIAL_callback_dummy::*method_callback)(MODSERIAL_IRQ_INFO *);
+
+public:
+
+ /** Constructor
+ */
+ MODSERIAL_callback() {
+ c_callback = 0;
+ obj_callback = 0;
+ method_callback = 0;
+ }
+
+ /** attach - Overloaded attachment function.
+ *
+ * Attach a C type function pointer as the callback.
+ *
+ * Note, the callback function prototype must be:-
+ * @code
+ * void myCallbackFunction(MODSERIAL_IRQ_INFO *);
+ * @endcode
+ * @param A C function pointer to call.
+ */
+ void attach(void (*function)(MODSERIAL_IRQ_INFO *) = 0) { c_callback = function; }
+
+ /** attach - Overloaded attachment function.
+ *
+ * Attach a C++ type object/method pointer as the callback.
+ *
+ * Note, the callback method prototype must be:-
+ * @code
+ * public:
+ * void myCallbackFunction(MODSERIAL_IRQ_INFO *);
+ * @endcode
+ * @param A C++ object pointer.
+ * @param A C++ method within the object to call.
+ */
+ template<class T>
+ void attach(T* item, void (T::*method)(MODSERIAL_IRQ_INFO *)) {
+ obj_callback = (MODSERIAL_callback_dummy *)item;
+ method_callback = (void (MODSERIAL_callback_dummy::*)(MODSERIAL_IRQ_INFO *))method;
+ }
+
+ /** call - Overloaded callback initiator.
+ *
+ * call the callback function.
+ *
+ * @param uint32_t The value to pass to the callback.
+ * @return uint32_t The value the callback returns.
+ */
+ void call(MODSERIAL_IRQ_INFO *arg) {
+ if (c_callback != 0) {
+ (*c_callback)(arg);
+ }
+ else {
+ if (obj_callback != 0 && method_callback != 0) {
+ (obj_callback->*method_callback)(arg);
+ }
+ }
+ }
+};
+
/**
* @author Andy Kirkham
* @see http://mbed.org/cookbook/MODSERIAL
@@ -113,6 +242,9 @@
{
public:
+ // Allow instances of MODSERIAL_IRQ_INFO to use protected properties and methods.
+ friend class MODSERIAL_IRQ_INFO;
+
//! A copy of the Serial parity enum
/** @see http://mbed.org/projects/libraries/api/mbed/trunk/Serial#Serial.format */
enum Parity {
@@ -231,7 +363,7 @@
* @param fptr A pointer to a void function, or 0 to set as none
* @param type Which serial interrupt to attach the member function to (Seriall::RxIrq for receive, TxIrq for transmit buffer empty)
*/
- void attach(void (*fptr)(void), IrqType type = RxIrq) { _isr[type].attach(fptr); }
+ void attach(void (*fptr)(MODSERIAL_IRQ_INFO *), IrqType type = RxIrq) { _isr[type].attach(fptr); }
/**
* Function: attach
@@ -293,8 +425,8 @@
* @param type Which serial interrupt to attach the member function to (Seriall::RxIrq for receive, TxIrq for transmit buffer empty)
*/
template<typename T>
- void attach(T* tptr, void (T::*mptr)(void), IrqType type = RxIrq) {
- if((mptr != NULL) && (tptr != NULL)) {
+ void attach(T* tptr, uint32_t (T::*mptr)(uint32_t), IrqType type = RxIrq) {
+ if((mptr != 0) && (tptr != 0)) {
_isr[type].attach(tptr, mptr);
}
}
@@ -303,15 +435,15 @@
* @see attach
* @ingroup API
*/
- void connect(void (*fptr)(void), IrqType type = RxIrq) { _isr[RxIrq].attach(fptr); }
+ void connect(void (*fptr)(MODSERIAL_IRQ_INFO *), IrqType type = RxIrq) { _isr[RxIrq].attach(fptr); }
/**
* @see attach
* @ingroup API
*/
template<typename T>
- void connect(T* tptr, void (T::*mptr)(void), IrqType type = RxIrq) {
- if((mptr != NULL) && (tptr != NULL)) {
+ void connect(T* tptr, void (T::*mptr)(MODSERIAL_IRQ_INFO *), IrqType type = RxIrq) {
+ if((mptr != 0) && (tptr != 0)) {
_isr[type].attach(tptr, mptr);
}
}
@@ -646,8 +778,28 @@
*/
int scanf(const char* format, ...);
#endif
+
+protected:
+ /**
+ * Used to pass information to callbacks.
+ * @ingroup INTERNALS
+ */
+ MODSERIAL_IRQ_INFO callbackInfo;
+
+ /**
+ * Remove the last char placed into the rx buffer.
+ * This is an operation that can only be performed
+ * by an rxCallback function. To protect the buffers
+ * this function is defined protected so that a
+ * regular application cannot call it directly. It
+ * can only be called by the public version within a
+ * MODSERIAL_IRQ_INFO class.
+ * @ingroup INTERNALS
+ * @return The byte removed from the buffer.
+ */
+ int rxDiscardLastChar(void);
-protected:
+private:
/**
* A pointer to the UART peripheral base address being used.
@@ -713,7 +865,7 @@
* Callback system.
* @ingroup INTERNALS
*/
- FunctionPointer _isr[NumOfIrqTypes];
+ MODSERIAL_callback _isr[NumOfIrqTypes];
/**
* TX Interrupt Service Routine.
@@ -745,7 +897,7 @@
* @ingroup INTERNALS
*/
void enableIrq(void);
-
+
/**
* Get a character from the RX buffer
* @ingroup INTERNALS
@@ -885,7 +1037,7 @@
* @param fptr A function pointer to call
* @return this
*/
- void attach_dmaSendComplete(void (*fptr)(void)) {
+ void attach_dmaSendComplete(void (*fptr)(MODSERIAL_IRQ_INFO *)) {
_isrDmaSendComplete.attach(fptr);
}
@@ -898,13 +1050,13 @@
* @return this
*/
template<typename T>
- void attach_dmaSendComplete(T* tptr, void (T::*mptr)(void)) {
+ void attach_dmaSendComplete(T* tptr, void (T::*mptr)(MODSERIAL_IRQ_INFO *)) {
if((mptr != NULL) && (tptr != NULL)) {
_isrDmaSendComplete.attach(tptr, mptr);
}
}
- FunctionPointer _isrDmaSendComplete;
+ MODSERIAL_callback _isrDmaSendComplete;
protected:
/**
@@ -921,7 +1073,7 @@
if (dma->irqType() == MODDMA::TcIrq) dma->clearTcIrq();
if (dma->irqType() == MODDMA::ErrIrq) dma->clearErrIrq();
dmaSendChannel = -1;
- _isrDmaSendComplete.call();
+ _isrDmaSendComplete.call(&this->callbackInfo);
delete(config);
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/MODSERIAL_IRQ_INFO.cpp Thu Apr 21 09:20:41 2011 +0000
@@ -0,0 +1,38 @@
+/*
+ Copyright (c) 2010 Andy Kirkham
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+
+ @file MODSERIAL_CB.h
+ @author Andy Kirkham
+*/
+
+#include "MODSERIAL.h"
+
+namespace AjK {
+
+int
+MODSERIAL_IRQ_INFO::rxDiscardLastChar(void)
+{
+ if (!serial) return -1;
+
+ return serial->rxDiscardLastChar();
+}
+
+}; // namespace AjK ends
--- a/PUTC.cpp Tue Mar 08 01:42:25 2011 +0000
+++ b/PUTC.cpp Thu Apr 21 09:20:41 2011 +0000
@@ -60,7 +60,7 @@
}
else if( MODSERIAL_TX_BUFFER_FULL ) {
buffer_overflow[TxIrq] = c; // Oh dear, no room in buffer.
- _isr[TxOvIrq].call();
+ _isr[TxOvIrq].call(&this->callbackInfo);
return -1;
}
_IER &= ~2;
--- a/example1.cpp Tue Mar 08 01:42:25 2011 +0000
+++ b/example1.cpp Thu Apr 21 09:20:41 2011 +0000
@@ -33,18 +33,18 @@
// This function is called when a character goes from the TX buffer
// to the Uart THR FIFO register.
-void txCallback(void) {
+void txCallback(MODSERIAL_IRQ_INFO *q) {
led2 = !led2;
}
// This function is called when TX buffer goes empty
-void txEmpty(void) {
+void txEmpty(MODSERIAL_IRQ_INFO *q) {
led2 = 0;
pc.puts(" Done. ");
}
// This function is called when a character goes into the RX buffer.
-void rxCallback(void) {
+void rxCallback(MODSERIAL_IRQ_INFO *q) {
led3 = !led3;
pc.putc(uart.getc());
}
--- a/example2.cpp Tue Mar 08 01:42:25 2011 +0000
+++ b/example2.cpp Thu Apr 21 09:20:41 2011 +0000
@@ -99,9 +99,11 @@
char messageBufferOutgoing[MESSAGE_BUFFER_SIZE];
bool messageReceived;
-void messageReceive(void) {
- messageSystem.move(messageBufferIncoming, MESSAGE_BUFFER_SIZE);
+void messageReceive(MODSERIAL_IRQ_INFO *q) {
+ MODSERIAL *sys = q->serial;
+ sys->move(messageBufferIncoming, MESSAGE_BUFFER_SIZE);
messageReceived = true;
+ return 0;
}
void messageProcess(void) {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/example3a.cpp Thu Apr 21 09:20:41 2011 +0000
@@ -0,0 +1,83 @@
+/*
+ Copyright (c) 2011 Andy Kirkham
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+
+ @file example3.cpp
+ @purpose Demos a simple filter.
+ @version see ChangeLog.c
+ @author Andy Kirkham
+*/
+
+/*
+ This example shows how to use the new callback system. In the old system
+ Mbed's FunctionPointer[1] type was used to store abd make calls to callbacks.
+ However, that limits the callback function prototype to void func(void);
+ which means we cannot pass parameters.
+
+ This latest version of MODSERIAL now uses its own callback object. This allows
+ the passing of a pointer to a class that holds information about the MODSERIAL
+ object making the callback. As of version 1.18 one critcal piece of information
+ is passed, a pointer to the MODSERIAL object. This allows callbacks to use the
+ MODSERIAL functions and data.
+
+ Additionally, since MODSERIAL and the callback parameter class MODSERIAL_IRQ_INFO
+ are friends, MODSERIAL_IRQ_INFO can access the protected functions of MODSERIAL.
+ This is used to ensure functions that can only be called during a callback
+ can be invoked from a callback.
+
+ [1] http://mbed.org/projects/libraries/svn/mbed/trunk/FunctionPointer.h
+*/
+
+#ifdef COMPILE_EXAMPLE3_CODE_MODSERIAL
+
+#include "mbed.h"
+#include "MODSERIAL.h"
+
+DigitalOut led1(LED1);
+
+MODSERIAL pc(USBTX, USBRX);
+
+// The following callback is defined in example3b.cpp
+//! @see example3b.cpp
+void rxCallback(MODSERIAL_IRQ_INFO *info);
+
+int main() {
+
+ int life_counter = 0;
+
+ pc.baud(115200);
+
+ pc.attach(&rxCallback, MODSERIAL::RxIrq);
+
+ while(1) {
+ // Echo back any chars we get except 'A' which is filtered by the rxCallback.
+ if (pc.readable()) {
+ pc.putc(pc.getc());
+ }
+
+ // Toggle LED1 every so often to show we are alive.
+ if (life_counter++ == 1000000) {
+ life_counter = 0;
+ led1 = !led1;
+ }
+ }
+}
+
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/example3b.cpp Thu Apr 21 09:20:41 2011 +0000
@@ -0,0 +1,78 @@
+/*
+ Copyright (c) 2011 Andy Kirkham
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+
+ @file example3b.cpp
+ @purpose Demos a simple filter.
+ @version see ChangeLog.c
+ @author Andy Kirkham
+*/
+
+/*
+ This example shows how to use the new callback system. In the old system
+ Mbed's FunctionPointer[1] type was used to store abd make calls to callbacks.
+ However, that limits the callback function prototype to void func(void);
+ which means we cannot pass parameters.
+
+ This latest version of MODSERIAL now uses its own callback object. This allows
+ the passing of a pointer to a class that holds information about the MODSERIAL
+ object making the callback. As of version 1.18 one critcal piece of information
+ is passed, a pointer to the MODSERIAL object. This allows callbacks to use the
+ MODSERIAL functions and data.
+
+ Additionally, since MODSERIAL and the callback parameter class MODSERIAL_IRQ_INFO
+ are friends, MODSERIAL_IRQ_INFO can access the protected functions of MODSERIAL.
+ This is used to ensure functions that can only be called during a callback
+ can be invoked from a callback.
+
+ [1] http://mbed.org/projects/libraries/svn/mbed/trunk/FunctionPointer.h
+*/
+
+
+#ifdef COMPILE_EXAMPLE3_CODE_MODSERIAL
+
+#include "mbed.h"
+#include "MODSERIAL.h"
+
+void rxCallback(MODSERIAL_IRQ_INFO *info) {
+
+ // Get the pointer to our MODSERIAL object that invoked this callback.
+ MODSERIAL *pc = info->serial;
+
+ // info->serial points at the MODSERIAL instance so we can use it to call
+ // any of the public MODSERIAL functions that are normally available. So
+ // there's now no need to use the global version (pc in our case) inside
+ // callback functions.
+ char c = pc->rxGetLastChar(); // Where local pc variable is a pointer to the global MODSERIAL pc object.
+
+ // The following is rather daft but demos the point.
+ // Don't allow the letter "A" go into the RX buffer.
+ // Basically acts as a filter to remove the letter "A"
+ // if it goes into the RX buffer.
+ if (c == 'A') {
+ // Note, we call the MODSERIAL_IRQ_INFO::rxDiscardLastChar() public function which
+ // is permitted access to the protected version of MODSERIAL::rxDiscardLastChar()
+ // within MODSERIAL (because they are friends). This ensures rxDiscardLastChar()
+ // can only be called within an rxCallback function.
+ info->rxDiscardLastChar();
+ }
+}
+
+#endif
