MODSERIAL with support for more devices

Fork of MODSERIAL by Erik -

Revision:
18:21ef26402365
Parent:
17:6c9b57c14868
Child:
19:a158936322cc
diff -r 6c9b57c14868 -r 21ef26402365 MODSERIAL.h
--- 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);
     }