Bug fix release

Dependents:   AntiTheftGPS XbeeReceive XbeeSend Superball_Ball2 ... more

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