Reaction Wheel Actuated Satellite Dynamics Test Platform

Dependencies:   mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers MODSERIAL.h Source File

MODSERIAL.h

00001 /*
00002     Copyright (c) 2010 Andy Kirkham
00003  
00004     Permission is hereby granted, free of charge, to any person obtaining a copy
00005     of this software and associated documentation files (the "Software"), to deal
00006     in the Software without restriction, including without limitation the rights
00007     to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
00008     copies of the Software, and to permit persons to whom the Software is
00009     furnished to do so, subject to the following conditions:
00010  
00011     The above copyright notice and this permission notice shall be included in
00012     all copies or substantial portions of the Software.
00013  
00014     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00015     IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00016     FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
00017     AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00018     LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00019     OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
00020     THE SOFTWARE.
00021     
00022     @file          MODSERIAL.h 
00023     @purpose       Extends Serial to provide fully buffered IO
00024     @version       see ChangeLog.c
00025     @date          Nov 2010
00026     @author        Andy Kirkham
00027 */
00028 
00029 #ifndef MODSERIAL_H
00030 #define MODSERIAL_H
00031 
00032 /** @defgroup API The MODSERIAL API */
00033 /** @defgroup MISC Misc MODSERIAL functions */
00034 /** @defgroup INTERNALS MODSERIAL Internals */
00035 
00036 #ifndef MODSERIAL_DEFAULT_RX_BUFFER_SIZE
00037 #define MODSERIAL_DEFAULT_RX_BUFFER_SIZE    256
00038 #endif
00039 
00040 #ifndef MODSERIAL_DEFAULT_TX_BUFFER_SIZE
00041 #define MODSERIAL_DEFAULT_TX_BUFFER_SIZE    256
00042 #endif
00043 
00044 #include "mbed.h"
00045 
00046 namespace AjK {
00047 
00048 // Forward reference.
00049 class MODSERIAL ;
00050 
00051 /**
00052  * @author Andy Kirkham
00053  * @see http://mbed.org/cookbook/MODSERIAL
00054  * @see example3a.cpp
00055  * @see example3b.cpp
00056  * @see API 
00057  *
00058  * <b>MODSERIAL_IRQ_INFO</b> is a class used to pass information (and access to protected
00059  * MODSERIAL functions) to IRQ callbacks. 
00060  */
00061 class MODSERIAL_IRQ_INFO 
00062 {
00063 public:
00064     friend class MODSERIAL ;
00065     
00066     MODSERIAL  *serial;
00067     
00068     MODSERIAL_IRQ_INFO () { serial = 0; }
00069     
00070     /** rxDiscardLastChar()
00071      *
00072      * Remove the last char placed into the rx buffer.
00073      * This is an operation that can only be performed
00074      * by an rxCallback function. 
00075      * @ingroup API
00076      * @return The byte removed from the buffer.
00077      */
00078     int rxDiscardLastChar(void);
00079 
00080 protected:
00081 
00082     /** setSerial()
00083      *
00084      * Used internally by MODSERIAL to set the "this" pointer
00085      * of the MODSERIAL that created this object.
00086      * @ingroup INTERNAL
00087      * @param A pointer to a MODSERIAL object instance.
00088      */
00089     void setSerial(MODSERIAL  *s) { serial = s; }    
00090 };
00091 
00092 // Forward reference dummy class.
00093 class MODSERIAL_callback_dummy;
00094 
00095 /**
00096  * @author Andy Kirkham
00097  * @see http://mbed.org/cookbook/MODSERIAL
00098  * @see example3a.cpp
00099  * @see example3b.cpp
00100  * @see API 
00101  *
00102  * <b>MODSERIAL_callback</b> is a class used to hold application callbacks that
00103  * MODSERIAL can invoke on certain events.
00104  */
00105 class MODSERIAL_callback  
00106 {
00107 protected:
00108 
00109     //! C callback function pointer.
00110     void (*c_callback)(MODSERIAL_IRQ_INFO  *); 
00111     
00112     //! C++ callback object/method pointer (the object part).
00113     MODSERIAL_callback_dummy *obj_callback;
00114     
00115     //! C++ callback object/method pointer (the method part).
00116     void (MODSERIAL_callback_dummy::*method_callback)(MODSERIAL_IRQ_INFO  *);
00117 
00118 public:
00119     
00120     /** Constructor
00121      */
00122     MODSERIAL_callback() {
00123         c_callback      = 0;
00124         obj_callback    = 0;
00125         method_callback = 0;
00126     }
00127     
00128     /** attach - Overloaded attachment function.
00129      *
00130      * Attach a C type function pointer as the callback.
00131      *
00132      * Note, the callback function prototype must be:-
00133      * @code
00134      * void myCallbackFunction(MODSERIAL_IRQ_INFO *);
00135      * @endcode
00136      * @param A C function pointer to call.
00137      */
00138     void attach(void (*function)(MODSERIAL_IRQ_INFO  *) = 0) { c_callback = function; }
00139     
00140     /** attach - Overloaded attachment function.
00141      *
00142      * Attach a C++ type object/method pointer as the callback.
00143      *
00144      * Note, the callback method prototype must be:-
00145      * @code
00146      *     public:
00147      *         void myCallbackFunction(MODSERIAL_IRQ_INFO *);
00148      * @endcode
00149      * @param A C++ object pointer.
00150      * @param A C++ method within the object to call.
00151      */
00152     template<class T> 
00153     void attach(T* item, void (T::*method)(MODSERIAL_IRQ_INFO  *)) { 
00154         obj_callback    = (MODSERIAL_callback_dummy *)item; 
00155         method_callback = (void (MODSERIAL_callback_dummy::*)(MODSERIAL_IRQ_INFO  *))method; 
00156     }
00157 
00158     /** call - Overloaded callback initiator.
00159      *
00160      * call the callback function.
00161      *
00162      * @param A pointer to a MODSERIAL_IRQ_INFO object.
00163      */
00164     void call(MODSERIAL_IRQ_INFO  *arg) {
00165         if (c_callback != 0) {
00166             (*c_callback)(arg);
00167         }
00168         else {
00169             if (obj_callback  != 0 && method_callback != 0) {
00170                 (obj_callback->*method_callback)(arg);
00171             }
00172         }       
00173     }    
00174 };
00175 
00176 /**
00177  * @author Andy Kirkham
00178  * @see http://mbed.org/cookbook/MODSERIAL
00179  * @see http://mbed.org/handbook/Serial
00180  * @see example1.cpp
00181  * @see example2.cpp
00182  * @see example3a.cpp
00183  * @see example3b.cpp
00184  * @see example_dma.cpp
00185  * @see API 
00186  *
00187  * <b>MODSERIAL</b> extends the Mbed library <a href="/handbook/Serial">Serial</a> to provide fully buffered
00188  * TX and RX streams. Buffer length is fully customisable. 
00189  *
00190  * Before using MODSERIAL users should be familar with Mbed's standard <a href="/handbook/Serial">Serial</a>
00191  * library object. MODSERIAL is a direct "drop in" replacement for <a href="/handbook/Serial">Serial</a>. Where
00192  * previously Serial was used, MODSERIAL can be used as adirect replacement instantly offering standard
00193  * TX and RX buffering. By default, both TX and RX buffers are 256 bytes in length.
00194  *
00195  * @image html /media/uploads/mbedofficial/serial_interfaces.png
00196  *
00197  * Standard example:
00198  * @code
00199  * #include "mbed.h"
00200  * #include "MODSERIAL.h"
00201  *
00202  * MODSERIAL pc(USBTX, USBRX); // tx, rx
00203  *
00204  * int main() {
00205  *     pc.printf("Hello World!");
00206  *     while(1) {
00207  *         pc.putc(pc.getc() + 1);
00208  *     }
00209  * }
00210  * @endcode
00211  *
00212  * Example with alternate buffer length:
00213  * @code
00214  * #include "mbed.h"
00215  * #include "MODSERIAL.h"
00216  *
00217  * // Make TX and RX buffers 512byes in length
00218  * MODSERIAL pc(USBTX, USBRX, 512); // tx, rx
00219  *
00220  * int main() {
00221  *     pc.printf("Hello World!");
00222  *     while(1) {
00223  *         pc.putc(pc.getc() + 1);
00224  *     }
00225  * }
00226  * @endcode
00227  *
00228  * Example with alternate buffer length:
00229  * @code
00230  * #include "mbed.h"
00231  * #include "MODSERIAL.h"
00232  *
00233  * // Make TX 1024bytes and RX 512byes in length
00234  * MODSERIAL pc(USBTX, USBRX, 1024, 512); // tx, rx
00235  *
00236  * int main() {
00237  *     pc.printf("Hello World!");
00238  *     while(1) {
00239  *         pc.putc(pc.getc() + 1);
00240  *     }
00241  * }
00242  * @endcode
00243  */
00244 class MODSERIAL  : public Serial 
00245 {
00246 public:
00247 
00248     // Allow instances of MODSERIAL_IRQ_INFO to use protected properties and methods.
00249     friend class MODSERIAL_IRQ_INFO ;
00250 
00251     //! A copy of the Serial parity enum
00252     /** @see http://mbed.org/projects/libraries/api/mbed/trunk/Serial#Serial.format */
00253     enum Parity {
00254           None = 0
00255         , Odd
00256         , Even
00257         , Forced1   
00258         , Forced0
00259     };
00260     
00261     //! A copy of the Serial IrqType enum
00262     enum IrqType {
00263           RxIrq = 0
00264         , TxIrq
00265         , RxOvIrq
00266         , TxOvIrq
00267         , TxEmpty
00268         , RxAutoDetect
00269         , NumOfIrqTypes
00270     };
00271     
00272     //! Non-blocking functions return code.
00273     enum Result {
00274           Ok  = 0                /*!< Ok. */
00275         , NoMemory        = -1   /*!< Memory allocation failed. */
00276         , NoChar          = -1   /*!< No character in buffer. */
00277         , BufferOversize  = -2   /*!< Oversized buffer. */
00278     };
00279     
00280     /**
00281      * The MODSERIAL constructor is used to initialise the serial object.
00282      *
00283      * @param tx PinName of the TX pin.
00284      * @param rx PinName of the TX pin.
00285      * @param name An option name for RPC usage.
00286      */    
00287     MODSERIAL(PinName tx, PinName rx, const char *name = NULL);
00288     
00289     /**
00290      * The MODSERIAL constructor is used to initialise the serial object.
00291      *
00292      * @param tx PinName of the TX pin.
00293      * @param rx PinName of the TX pin.
00294      * @param bufferSize Integer of the TX and RX buffer sizes.
00295      * @param name An option name for RPC usage.
00296      */    
00297     MODSERIAL(PinName tx, PinName rx, int bufferSize, const char *name = NULL);
00298     
00299     /**
00300      * The MODSERIAL constructor is used to initialise the serial object.
00301      *
00302      * @param tx PinName of the TX pin.
00303      * @param rx PinName of the TX pin.
00304      * @param txBufferSize Integer of the TX buffer sizes.
00305      * @param rxBufferSize Integer of the RX buffer sizes.
00306      * @param name An option name for RPC usage.
00307      */    
00308     MODSERIAL(PinName tx, PinName rx, int txBufferSize, int rxBufferSize, const char *name = NULL);
00309     
00310     virtual ~MODSERIAL ();
00311 
00312     /**
00313      * Function: attach
00314      *  
00315      * The Mbed standard <a href="/handbook/Serial">Serial</a> library object allows an interrupt callback
00316      * to be made when a byte is received by the TX or RX UART hardware. MODSERIAL traps these interrupts
00317      * to enable it's buffering system. However, after the byte has been received/sent under interrupt control, 
00318      * MODSERIAL can callback a user function as a notification of the interrupt. Note, user code should not
00319      * directly interact with the Uart hardware, MODSERIAL does that, instead, MODSERIAL API functions should
00320      * be used.
00321      *
00322      * <b>Note</b>, a character is written out then, if there is room in the TX FIFO and the TX buffer is empty,
00323      * putc() will put the character directly into THR (the output holding register). If the TX FIFO is full and 
00324      * cannot accept the character, it is placed into the TX output buffer. The TX interrupts are then enabled
00325      * so that when the TX FIFO empties, the TX buffer is then transferred to the THR FIFO. The TxIrq will ONLY 
00326      * be activated when this transfer of a character from BUFFER to THR FIFO takes place. If your character 
00327      * throughput is not high bandwidth, then the 16 byte TX FIFO may be enough and the TX output buffer may 
00328      * never come into play.
00329      *
00330      * @code
00331      * #include "mbed.h"
00332      * #include "MODSERIAL.h"
00333      *
00334      * DigitalOut led1(LED1);
00335      * DigitalOut led2(LED2);
00336      * DigitalOut led3(LED3);
00337      *
00338      * // To test, connect p9 to p10 as a loopback.
00339      * MODSERIAL pc(p9, p10);
00340      *
00341      * // This function is called when a character goes into the TX buffer.
00342      * void txCallback(void) {
00343      *     led2 = !led2;
00344      * }
00345      *
00346      * // This function is called when a character goes into the RX buffer.
00347      * void rxCallback(void) {
00348      *     led3 = !led3;
00349      * }
00350      *
00351      * int main() {
00352      *     pc.baud(115200);
00353      *     pc.attach(&txCallback, MODSERIAL::TxIrq);
00354      *     pc.attach(&rxCallback, MODSERIAL::RxIrq);
00355      *
00356      *     while(1) {
00357      *         led1 = !led1;
00358      *         wait(0.5);
00359      *         pc.putc('A');
00360      *         wait(0.5);
00361      *     }
00362      * ]
00363      * @endcode
00364      *
00365      * @ingroup API
00366      * @param fptr A pointer to a void function, or 0 to set as none
00367      * @param type Which serial interrupt to attach the member function to (Seriall::RxIrq for receive, TxIrq for transmit buffer empty)
00368      */  
00369     void attach(void (*fptr)(MODSERIAL_IRQ_INFO  *), IrqType type = RxIrq) { _isr[type].attach(fptr); }
00370     
00371     /**
00372      * Function: attach
00373      *  
00374      * The Mbed standard <a href="/handbook/Serial">Serial</a> library object allows an interrupt callback
00375      * to be made when a byte is received by the TX or RX UART hardware. MODSERIAL traps these interrupts
00376      * to enable it's buffering system. However, after the byte has been received/sent under interrupt control, 
00377      * MODSERIAL can callback a user function as a notification of the interrupt. Note, user code should not
00378      * directly interact with the Uart hardware, MODSERIAL does that, instead, MODSERIAL API functions should
00379      * be used.
00380      *
00381      * <b>Note</b>, a character is written out then, if there is room in the TX FIFO and the TX buffer is empty,
00382      * putc() will put the character directly into THR (the output holding register). If the TX FIFO is full and 
00383      * cannot accept the character, it is placed into the TX output buffer. The TX interrupts are then enabled
00384      * so that when the TX FIFO empties, the TX buffer is then transferred to the THR FIFO. The TxIrq will ONLY 
00385      * be activated when this transfer of a character from BUFFER to THR FIFO takes place. If your character 
00386      * throughput is not high bandwidth, then the 16 byte TX FIFO may be enough and the TX output buffer may 
00387      * never come into play.
00388      *
00389      * @code
00390      * #include "mbed.h"
00391      * #include "MODSERIAL.h"
00392      *
00393      * DigitalOut led1(LED1);
00394      * DigitalOut led2(LED2);
00395      * DigitalOut led3(LED3);
00396      *
00397      * // To test, connect p9 to p10 as a loopback.
00398      * MODSERIAL pc(p9, p10);
00399      *
00400      * class Foo {
00401      * public:
00402      *     // This method is called when a character goes into the TX buffer.
00403      *     void txCallback(void) { led2 = !led2; }
00404      *
00405      *     // This method is called when a character goes into the RX buffer.
00406      *     void rxCallback(void) { led3 = !led3; }
00407      * };
00408      *
00409      * Foo foo;
00410      *
00411      * int main() {
00412      *     pc.baud(115200);
00413      *     pc.attach(&foo, &Foo::txCallback, MODSERIAL::TxIrq);
00414      *     pc.attach(&foo, &Foo::rxCallback, MODSERIAL::RxIrq);
00415      *
00416      *     while(1) {
00417      *         led1 = !led1;
00418      *         wait(0.5);
00419      *         pc.putc('A');
00420      *         wait(0.5);
00421      *     }
00422      * ]
00423      * @endcode
00424      *     
00425      * @ingroup API
00426      * @param  tptr A pointer to the object to call the member function on
00427      * @param  mptr A pointer to the member function to be called
00428      * @param  type Which serial interrupt to attach the member function to (Seriall::RxIrq for receive, TxIrq for transmit buffer empty)
00429      */
00430     template<typename T>
00431     void attach(T* tptr, void (T::*mptr)(MODSERIAL_IRQ_INFO  *), IrqType type = RxIrq) {
00432         if((mptr != 0) && (tptr != 0)) {
00433             _isr[type].attach(tptr, mptr);            
00434         }
00435     }
00436 
00437     /**
00438      * @see attach
00439      * @ingroup API
00440      */
00441     void connect (void (*fptr)(MODSERIAL_IRQ_INFO  *), IrqType type = RxIrq) { _isr[RxIrq].attach(fptr); }
00442     
00443     /**
00444      * @see attach
00445      * @ingroup API
00446      */
00447     template<typename T>
00448     void connect (T* tptr, void (T::*mptr)(MODSERIAL_IRQ_INFO  *), IrqType type = RxIrq) {
00449         if((mptr != 0) && (tptr != 0)) {
00450             _isr[type].attach(tptr, mptr);            
00451         }
00452     }
00453     
00454     /**
00455      * Function: writeable
00456      *  
00457      * Determine if there is space available to write a byte
00458      *
00459      * @ingroup API
00460      * @return 1 if there is space to write a character, else 0
00461      */
00462     int writeable() { return txBufferFull() ? 0 : 1; }
00463     
00464     /**
00465      * Function: readable
00466      *  
00467      * Determine if there is a byte available to read
00468      *
00469      * @ingroup API
00470      * @return 1 if there is a character available to read, else 0
00471      */
00472     int readable() { return rxBufferEmpty() ? 0 : 1; } 
00473     
00474     /**
00475      * Function: txBufferSane
00476      *  
00477      * Determine if the TX buffer has been initialized.
00478      *
00479      * @ingroup API
00480      * @return true if the buffer is initialized, else false
00481      */
00482     bool txBufferSane(void) { return buffer[TxIrq] != (char *)NULL ? true : false; }
00483     
00484     /**
00485      * Function: rxBufferSane
00486      *  
00487      * Determine if the RX buffer has been initialized.
00488      *
00489      * @ingroup API
00490      * @return true if the buffer is initialized, else false
00491      */
00492     bool rxBufferSane(void) { return buffer[TxIrq] != (char *)NULL ? true : false; }
00493     
00494     /**
00495      * Function: txBufferGetCount
00496      *  
00497      * Returns how many bytes are in the TX buffer
00498      *
00499      * @ingroup API
00500      * @return The number of bytes in the TX buffer
00501      */
00502     int txBufferGetCount(void)    { return buffer_count[TxIrq]; }
00503     
00504     /**
00505      * Function: rxBufferGetCount
00506      *  
00507      * Returns how many bytes are in the RX buffer
00508      *
00509      * @ingroup API
00510      * @return The number of bytes in the RX buffer
00511      */
00512     int rxBufferGetCount(void)    { return buffer_count[RxIrq]; }
00513     
00514     /**
00515      * Function: txBufferGetSize
00516      *  
00517      * Returns the current size of the TX buffer
00518      *
00519      * @ingroup API
00520      * @return The length iof the TX buffer in bytes
00521      */
00522     int txBufferGetSize(int size) { return buffer_size[TxIrq]; } 
00523     
00524     /**
00525      * Function: rxBufferGetSize
00526      *  
00527      * Returns the current size of the RX buffer
00528      *
00529      * @ingroup API
00530      * @return The length iof the RX buffer in bytes
00531      */
00532     int rxBufferGetSize(int size) { return buffer_size[RxIrq]; } 
00533     
00534     /**
00535      * Function: txBufferFull
00536      *  
00537      * Is the TX buffer full?
00538      *
00539      * @ingroup API
00540      * @return true if the TX buffer is full, otherwise false
00541      */
00542     bool txBufferFull(void);
00543     
00544     /**
00545      * Function: rxBufferFull
00546      *  
00547      * Is the RX buffer full?
00548      *
00549      * @ingroup API
00550      * @return true if the RX buffer is full, otherwise false
00551      */
00552     bool rxBufferFull(void);
00553     
00554     /**
00555      * Function: txBufferEmpty
00556      *  
00557      * Is the TX buffer empty?
00558      *
00559      * @ingroup API
00560      * @return true if the TX buffer is empty, otherwise false
00561      */
00562     bool txBufferEmpty(void);
00563     
00564     /**
00565      * Function: rxBufferEmpty
00566      *  
00567      * Is the RX buffer empty?
00568      *
00569      * @ingroup API
00570      * @return true if the RX buffer is empty, otherwise false
00571      */
00572     bool rxBufferEmpty(void);
00573     
00574     /**
00575      * Function: txBufferSetSize
00576      *  
00577      * Change the TX buffer size.
00578      *
00579      * @see Result
00580      * @ingroup API
00581      * @param size The new TX buffer size in bytes.
00582      * @param m Perform a memory sanity check. Errs the Mbed if memory alloc fails.
00583      * @return Result Ok on success.
00584      */
00585     int txBufferSetSize(int size, bool m) { return resizeBuffer(size, TxIrq, m); } 
00586     
00587     /**
00588      * Function: rxBufferSetSize
00589      *  
00590      * Change the RX buffer size.
00591      *
00592      * @see Result
00593      * @ingroup API
00594      * @param size The new RX buffer size in bytes.
00595      * @param m Perform a memory sanity check. Errs the Mbed if memory alloc fails.
00596      * @return Result Ok on success.
00597      */
00598     int rxBufferSetSize(int size, bool m) { return resizeBuffer(size, RxIrq, m); } 
00599     
00600     /**
00601      * Function: txBufferSetSize
00602      *  
00603      * Change the TX buffer size.
00604      * Always performs a memory sanity check, halting the Mbed on failure.
00605      *
00606      * @see Result
00607      * @ingroup API
00608      * @param size The new TX buffer size in bytes.
00609      * @return Result Ok on success.
00610      */
00611     int txBufferSetSize(int size) { return resizeBuffer(size, TxIrq, true); } 
00612     
00613     /**
00614      * Function: rxBufferSetSize
00615      *  
00616      * Change the RX buffer size.
00617      * Always performs a memory sanity check, halting the Mbed on failure.
00618      *
00619      * @see Result
00620      * @ingroup API
00621      * @param size The new RX buffer size in bytes.
00622      * @return Result Ok on success.
00623      */
00624     int rxBufferSetSize(int size) { return resizeBuffer(size, RxIrq, true); } 
00625     
00626     /**
00627      * Function: txBufferFlush
00628      *  
00629      * Remove all bytes from the TX buffer.
00630      * @ingroup API
00631      */
00632     void txBufferFlush(void) { flushBuffer(TxIrq); }
00633     
00634     /**
00635      * Function: rxBufferFlush
00636      *  
00637      * Remove all bytes from the RX buffer.
00638      * @ingroup API
00639      */
00640     void rxBufferFlush(void) { flushBuffer(RxIrq); }
00641         
00642     /**
00643      * Function: getcNb
00644      *
00645      * Like getc() but is non-blocking. If no bytes are in the RX buffer this
00646      * function returns Result::NoChar (-1)
00647      *
00648      * @ingroup API
00649      * @return A byte from the RX buffer or Result::NoChar (-1) if bufer empty.
00650      */
00651     int getcNb() { return __getc(false); }
00652     
00653     /**
00654      * Function: getc
00655      *
00656      * Overloaded version of Serial::getc()
00657      * 
00658      * This function blocks (if the RX buffer is empty the function will wait for a
00659      * character to arrive and then return that character).
00660      *
00661      * @ingroup API
00662      * @return A byte from the RX buffer
00663      */
00664     int getc()   { return __getc(true);  }
00665     
00666     /**
00667      * Function: txGetLastChar
00668      *
00669      * Rteurn the last byte to pass through the TX interrupt handler.
00670      *
00671      * @ingroup MISC
00672      * @return The byte
00673      */
00674     char txGetLastChar(void) { return txc; }
00675     
00676     /**
00677      * Function: rxGetLastChar
00678      *
00679      * Return the last byte to pass through the RX interrupt handler.
00680      *
00681      * @ingroup MISC
00682      * @return The byte
00683      */
00684     char rxGetLastChar(void) { return rxc; }
00685     
00686     /**
00687      * Function: txIsBusy
00688      *
00689      * If the Uart is still actively sending characters this
00690      * function will return true.
00691      *
00692      * @ingroup API
00693      * @return bool
00694      */
00695     bool txIsBusy(void);
00696     
00697     /**
00698      * Function: autoDetectChar
00699      *
00700      * Set the char that, if seen incoming, invokes the AutoDetectChar callback.
00701      *
00702      * @ingroup API
00703      * @param int c The character to detect.
00704      */
00705     void autoDetectChar(char c) { auto_detect_char = c; }
00706     
00707     /**
00708      * Function: move
00709      *
00710      * Move contents of RX buffer to external buffer. Stops if "end" detected.
00711      *
00712      * @ingroup API
00713      * @param char *s The destination buffer address
00714      * @param int max The maximum number of chars to move.
00715      * @param char end If this char is detected stop moving.
00716      */
00717     int move(char *s, int max, char end) {
00718         int counter = 0;
00719         char c;
00720         while(readable()) {
00721             c = getc();
00722             if (c == end) break;
00723             *(s++) = c;
00724             counter++;
00725             if (counter == max) break;
00726         }
00727         return counter;
00728     }
00729     
00730     /**
00731      * Function: move (overloaded)
00732      *
00733      * Move contents of RX buffer to external buffer. Stops if auto_detect_char detected.
00734      *
00735      * @ingroup API
00736      * @param int max The maximum number of chars to move.
00737      * @param char *s The destination buffer address
00738      */
00739     int move(char *s, int max) {
00740         return move(s, max, auto_detect_char);
00741     }
00742     
00743     #if 0 // Inhereted from Serial/Stream, for documentation only
00744     /**
00745      * Function: putc
00746      * 
00747      * Write a character
00748      * Inhereted from Serial/Stream
00749      *
00750      * @see http://mbed.org/projects/libraries/api/mbed/trunk/Serial#Serial.putc
00751      * @ingroup API
00752      * @param c The character to write to the serial port
00753      */
00754     int putc(int c);
00755     #endif
00756     
00757     #if 0 // Inhereted from Serial/Stream, for documentation only
00758     /**
00759      * Function: printf
00760      *  
00761      * Write a formated string
00762      * Inhereted from Serial/Stream
00763      *
00764      * @see http://mbed.org/projects/libraries/api/mbed/trunk/Serial#Serial.printf
00765      * @ingroup API
00766      * @param format A printf-style format string, followed by the variables to use in formating the string.
00767      */
00768     int printf(const char* format, ...);
00769     #endif
00770     
00771     #if 0 // Inhereted from Serial/Stream, for documentation only
00772     /**
00773      * Function: scanf
00774      *  
00775      * Read a formated string
00776      * Inhereted from Serial/Stream
00777      *
00778      * @see http://mbed.org/projects/libraries/api/mbed/trunk/Serial#Serial.scanf
00779      * @ingroup API
00780      * @param format - A scanf-style format string, followed by the pointers to variables to store the results.
00781      */
00782     int scanf(const char* format, ...);
00783     #endif
00784 
00785 protected:    
00786     /**
00787      * Used to pass information to callbacks.
00788      * @ingroup INTERNALS
00789      */
00790     MODSERIAL_IRQ_INFO  callbackInfo;
00791 
00792     /**
00793      * Remove the last char placed into the rx buffer.
00794      * This is an operation that can only be performed
00795      * by an rxCallback function. To protect the buffers
00796      * this function is defined protected so that a 
00797      * regular application cannot call it directly. It 
00798      * can only be called by the public version within a
00799      * MODSERIAL_IRQ_INFO class.
00800      * @ingroup INTERNALS
00801      * @return The byte removed from the buffer.
00802      */
00803     int rxDiscardLastChar(void);    
00804             
00805 private:
00806 
00807     /**
00808      * A pointer to the UART peripheral base address being used.
00809      * @ingroup INTERNALS
00810      */
00811     void *_base;
00812     
00813     /**
00814      * The last byte to pass through the TX IRQ handler.
00815      * @ingroup INTERNALS
00816      */
00817     volatile char txc;
00818     
00819     /**
00820      * The last byte to pass through the RX IRQ handler.
00821      * @ingroup INTERNALS
00822      */
00823     volatile char rxc;
00824     
00825     /**
00826      * Pointers to the TX and RX buffers.
00827      * @ingroup INTERNALS
00828      */
00829     volatile char *buffer[2];
00830     
00831     /**
00832      * Buffer in pointers.
00833      * @ingroup INTERNALS
00834      */
00835     volatile int   buffer_in[2];
00836     
00837     /**
00838      * Buffer out pointers.
00839      * @ingroup INTERNALS
00840      */
00841     volatile int   buffer_out[2];
00842     
00843     /**
00844      * Buffer lengths.
00845      * @ingroup INTERNALS
00846      */
00847     volatile int   buffer_size[2];
00848     
00849     /**
00850      * Buffer content counters.
00851      * @ingroup INTERNALS
00852      */
00853     volatile int   buffer_count[2];
00854     
00855     /**
00856      * Buffer overflow.
00857      * @ingroup INTERNALS
00858      */
00859     volatile int   buffer_overflow[2];
00860     
00861     /**
00862      * Auto-detect character.
00863      * @ingroup INTERNALS
00864      */
00865     volatile char auto_detect_char;
00866     
00867     /**
00868      * Callback system.
00869      * @ingroup INTERNALS
00870      */
00871     MODSERIAL_callback  _isr[NumOfIrqTypes];
00872     
00873     /**
00874      * TX Interrupt Service Routine.
00875      * @ingroup INTERNALS
00876      */
00877     void isr_tx(bool doCallback);
00878     
00879     /**
00880      * TX Interrupt Service Routine stub version.
00881      * @ingroup INTERNALS
00882      */ 
00883     void isr_tx(void) { isr_tx(true); }
00884     
00885     
00886     /**
00887      * RX Interrupt Service Routine.
00888      * @ingroup INTERNALS
00889      */
00890     void isr_rx(void);
00891     
00892     /**
00893      * Disable the interrupts for this Uart.
00894      * @ingroup INTERNALS
00895      */
00896     void disableIrq(void);
00897     
00898     /**
00899      * Enable the interrupts for this Uart.
00900      * @ingroup INTERNALS
00901      */
00902     void enableIrq(void);
00903     
00904     /**
00905      * Get a character from the RX buffer
00906      * @ingroup INTERNALS
00907      * @param bool True to block (wait for input)
00908      * @return A byte from the buffer.
00909      */
00910     int __getc(bool);
00911     
00912     /**
00913      * Put a character from the TX buffer
00914      * @ingroup INTERNALS
00915      * @param bool True to block (wait for space in the TX buffer if full)
00916      * @return 0 on success
00917      */
00918     int __putc(int c, bool);
00919     
00920     /**
00921      * Function: _putc 
00922      * Overloaded virtual function.
00923      */
00924     virtual int _putc(int c) { return __putc(c, true); }
00925     
00926     /**
00927      * Function: _getc 
00928      * Overloaded virtual function.
00929      */
00930     virtual int _getc()      { return __getc(true); }
00931         
00932     /** 
00933      * Function: init
00934      * Initialize the MODSERIAL object
00935      * @ingroup INTERNALS
00936      */
00937     void init(int txSize, int rxSize);
00938     
00939     /** 
00940      * Function: flushBuffer
00941      * @ingroup INTERNALS
00942      */
00943     void flushBuffer(IrqType type);
00944 
00945     /** 
00946      * Function: resizeBuffer
00947      * @ingroup INTERNALS
00948      */
00949     int resizeBuffer(int size, IrqType type = RxIrq, bool memory_check = true);   
00950     
00951     /** 
00952      * Function: downSizeBuffer
00953      * @ingroup INTERNALS
00954      */
00955     int downSizeBuffer(int size, IrqType type, bool memory_check); 
00956     
00957     /** 
00958      * Function: upSizeBuffer
00959      * @ingroup INTERNALS
00960      */
00961     int upSizeBuffer(int size, IrqType type, bool memory_check); 
00962 
00963     /*
00964      * If MODDMA is available the compile in code to handle sending
00965      * an arbitary char buffer. Note, the parts before teh #ifdef
00966      * are declared so that MODSERIAL can access then even if MODDMA
00967      * isn't avaiable. Since MODDMA.h is only available at this point
00968      * all DMA functionality must be declared inline in the class
00969      * definition.
00970      */
00971 public:
00972 
00973     int dmaSendChannel;
00974     void *moddma_p;
00975     
00976 #ifdef MODDMA_H
00977 
00978     MODDMA_Config *config;
00979     
00980     /**
00981      * Set the "void pointer" moddma_p to be a pointer to a
00982      * MODDMA controller class instance. Used to manage the
00983      * data transfer of DMA configurations.
00984      *
00985      * @ingroup API
00986      * @param p A pointer to "the" instance of MODDMA.
00987      */
00988     void MODDMA(MODDMA *p) { moddma_p = p; }
00989     
00990     /**
00991      * Send a char buffer to the Uarts TX system
00992      * using DMA. This blocks regular library
00993      * sending.
00994      *
00995      * @param buffer A char buffer of bytes to send.
00996      * @param len The length of the buffer to send.
00997      * @param dmaChannel The DMA channel to use, defaults to 7
00998      * @return MODDMA::Status MODDMA::ok if all went ok
00999      */   
01000     int dmaSend(char *buffer, int len, int dmaChannel = 7) 
01001     {
01002         if (moddma_p == (void *)NULL) return -2;
01003         class MODDMA *dma = (class MODDMA *)moddma_p;
01004         
01005         dmaSendChannel = dmaChannel & 0x7;
01006         
01007         uint32_t conn = MODDMA::UART0_Tx;
01008         switch(_serial.index) {
01009             case 0: conn = MODDMA::UART0_Tx; break;
01010             case 1: conn = MODDMA::UART1_Tx; break;
01011             case 2: conn = MODDMA::UART2_Tx; break;
01012             case 3: conn = MODDMA::UART3_Tx; break;
01013         }
01014         
01015         config = new MODDMA_Config;
01016         config
01017          ->channelNum    ( (MODDMA::CHANNELS)(dmaSendChannel & 0x7) )
01018          ->srcMemAddr    ( (uint32_t) buffer )
01019          ->transferSize  ( len )
01020          ->transferType  ( MODDMA::m2p )
01021          ->dstConn       ( conn )
01022          ->attach_tc     ( this, &MODSERIAL::dmaSendCallback )
01023          ->attach_err    ( this, &MODSERIAL::dmaSendCallback )
01024         ; // config end
01025         
01026         // Setup the configuration.
01027         if (dma->Setup(config) == 0) { 
01028             return -1;
01029         }
01030         
01031         //dma.Enable( MODDMA::Channel_0 );
01032         dma->Enable( config->channelNum() );
01033         return MODDMA::Ok ;
01034     }
01035     
01036     /**
01037      * Attach a callback to the DMA completion.
01038      *
01039      * @ingroup API
01040      * @param fptr A function pointer to call
01041      * @return this
01042      */
01043     void attach_dmaSendComplete(void (*fptr)(MODSERIAL_IRQ_INFO  *)) {  
01044         _isrDmaSendComplete.attach(fptr);         
01045     }
01046     
01047     /**
01048      * Attach a callback to the DMA completion.
01049      *
01050      * @ingroup API
01051      * @param tptr A template pointer to the calling object
01052      * @param mptr A method pointer within the object to call.
01053      * @return this
01054      */
01055     template<typename T>
01056     void attach_dmaSendComplete(T* tptr, void (T::*mptr)(MODSERIAL_IRQ_INFO  *)) {  
01057         if((mptr != NULL) && (tptr != NULL)) {
01058             _isrDmaSendComplete.attach(tptr, mptr);         
01059         }
01060     }
01061     
01062     MODSERIAL_callback  _isrDmaSendComplete;
01063     
01064 protected:    
01065     /**
01066      * Callback for dmaSend(). 
01067      */
01068     void dmaSendCallback(void) 
01069     {
01070         if (moddma_p == (void *)NULL) return;
01071         class MODDMA *dma = (class MODDMA *)moddma_p;
01072         
01073         MODDMA_Config *config = dma->getConfig();
01074         dma->haltAndWaitChannelComplete( (MODDMA::CHANNELS)config->channelNum());
01075         dma->Disable( (MODDMA::CHANNELS)config->channelNum() );
01076         if (dma->irqType() == MODDMA::TcIrq)  dma->clearTcIrq();
01077         if (dma->irqType() == MODDMA::ErrIrq) dma->clearErrIrq();
01078         dmaSendChannel = -1;
01079         _isrDmaSendComplete.call(&this->callbackInfo);
01080         delete(config);
01081     }
01082     
01083 #endif // MODDMA_H
01084 
01085 };
01086 
01087 }; // namespace AjK ends
01088 
01089 using namespace AjK;
01090 
01091 #endif