Bug fix release

Dependents:   AntiTheftGPS XbeeReceive XbeeSend Superball_Ball2 ... more

MODSERIAL is an easy to use library that extends Serial to add fully buffered input and output.

The features of MODSERIAL include:-

/media/uploads/mbedofficial/serial_interfaces.png

Connecting up the MODSERIAL module

The starting point for using MODSERIAL is the Mbed's own handbook for Serial library object. MODSERIAL inherits Serial and adds extensions for buffering. So getting started is easy. Follow the Mbed instructions for Serial to get setup. Here's a reproduction of Serial's simple code starter:-

1  #include "mbed.h"
2
3  Serial pc(USBTX, USBRX); // tx, rx
4 
5  int main() {
6      pc.printf("Hello World!");
7      while(1) {
8          pc.putc(pc.getc() + 1);
9      }
10 }

All we need to do to use MODSERIAL is to add a #include and alter one line thus:-

1  #include "mbed.h"
2  #include "MODSERIAL.h"
3  MODSERIAL pc(USBTX, USBRX); // tx, rx
4 
5  int main() {
6      pc.printf("Hello World!");
7      while(1) {
8          pc.putc(pc.getc() + 1);
9      }
10 }

As we can see, all we have done is add the header at line 2 and changed line 3 to specify the use of MODSERIAL in replacement for Serial. The default settings for MODSERIAL are that both the TX and RX buffers are assigned 256 bytes each of storage space. This storage space is acquired from the heap using malloc.

The default buffer assignment can be manipulated in three ways. First is the compile time setting which alters the default parameters used when creating a MODSERIAL object. This is done thus:-

1  #include "mbed.h"
2
3  #define MODSERIAL_DEFAULT_RX_BUFFER_SIZE 512
4  #define MODSERIAL_DEFAULT_TX_BUFFER_SIZE 1024 
5  #include "MODSERIAL.h"
6
7  MODSERIAL pc(USBTX, USBRX); // tx, rx
8  ...

By defining the two #defines before the #include "MODSERIAL.h" alters the defaults MODSERIAL uses to create it's buffers.

The second method is the run-time version. To get TX at 1024 and RX buffer at 512 as above during run-time initialisation, alter the constructor thus:-

1  #include "mbed.h"
2  #include "MODSERIAL.h"
3
4  // Make TX buffer 1024bytes and RX buffer use 512bytes.
5  MODSERIAL pc(USBTX, USBRX, 1024, 512); // tx, rx
6  ...

If you supply only one numeric value, as shown below, both TX and RX will have the same buffer sizes assigned to them:-

1  #include "mbed.h"
2  #include "MODSERIAL.h"
3
4  // Make both TX and RX use a 512byte buffer.
5  MODSERIAL pc(USBTX, USBRX, 512); // tx, rx
6  ...

The third method is reassigning a new buffer while the program is running. This allows the program to grow and shrink either buffer as required. However, there are caveats to do this as will be shown below.

First, expanding the buffer involves increasing the buffer size. This is fairly straight forward and is accomplished thus:-

1  #include "mbed.h"
2  #include "MODSERIAL.h"
3  MODSERIAL pc(USBTX, USBRX); // tx, rx
4 
5  int main() {
6
7      // Increase the TX buffer from the default 256bytes to 1024bytes.
8      if (pc.txBufferSetSize(1024) != MODSERIAL::Ok) {
9         error("Failed to allocate memory for new buffer");
10     }
11
12     pc.printf("Hello World!");
13     while(1) {
14         pc.putc(pc.getc() + 1);
15     }
16 }

As can be seen, growing the buffer is fairly straight forward. However, how it is done should be understood by the user. First, a new buffer allocation is made using malloc. Once acquired the current buffer is checked for contents. If the current buffer is not empty it is copied to the new buffer so the old buffer contents is maintained after resizing. The last step is then to free() the old memory buffer.

The buffer can also be contracted to a smaller length buffer. Here's the code:-

1  #include "mbed.h"
2  #include "MODSERIAL.h"
3  MODSERIAL pc(USBTX, USBRX); // tx, rx
4 
5  int main() {
6      int result;
7
8      // Decrease the TX buffer from the default 256bytes to 32bytes.
9      result = pc.txBufferSetSize(32);
10     if (result != MODSERIAL::Ok) {
11         switch(result) {
12             case MODSERIAL::BufferOversize: 
13                 error("Contents too big to fit into new allocation");
14                 break;
15             case MODSERIAL::NoMemory: 
16                 error("Not enough memory for new allocation");
17                 break;
18         }
19     }
11
12     pc.printf("Hello World!");
13     while(1) {
14         pc.putc(pc.getc() + 1);
15     }
16 }

Since buffer resizing involves the copying over of any existing old buffer contents the possibility exists that the current buffer contains more bytes than will fit into the new requested buffer. In these conditions the user must handle the return value of the resize functions. If the contents are of no concern then calling txBufferFlush() to empty of the contents before resizing.

MODSERIAL Interrupts

Users of Serial will be familar with the fact that you can attach functions or methods to TxIrq or RxIrq. This attachment of callbacks allows users to have Interrupt Service Routines (ISR) for both the TX and RX channel of the Uart. MODSERIAL uses both of these callbacks to maintain it's buffers and so are not available to users. However, MODSERIAL does contain five potential callbacks the user can use. These are:-

  • TxIrq - This callback is used to inform the user's program that a character was transferred from the TX buffer to the Uart's TX THR FIFO.
  • RxIrq - This callback is used to inform the user's program that a character was transferred from the Uart's RX FIFO RBR to the RX buffer.
  • RxOvIrq - This callback is used to inform the user's program that a character in the Uart's RX FIFO RBR failed to transfer to the RX buffer because the RX buffer was full. The failed byte is availble via xxGetLastChar() methods.
  • TxOvIrq - As RX overflow above
  • TxEmpty - This callback is made when the last byte in the TX buffer is transferred to the Uart's TX THR FIFO. It informs the user's program that the TX buffer has become empty. However, it does not mean transmission is complete. See the example1.cpp example for more information.

Delineating "packets"

Many devices send information on RS232 interfaces in distinct "packets". As an example of this is NMEA information sent by many GPS modules. Each NMEA sentence is delineated by a '\n' newline character. Each sentence can be of vary length depending upon the information being sent, however, all are seperated by a '\n' newline. Detecting this if very simple with MODSERIAL. Here's an example:-

#include "mbed.h"
#include "MODSERIAL.h"

// Connect the TX of the GPS module to p10 RX input
MODSERIAL gps(NC, p10);

bool newline_detected = false;

// Called everytime a new character goes into
// the RX buffer. Test that character for \n
// Note, rxGetLastChar() gets the last char that
// we received but it does NOT remove it from
// the RX buffer.
void rxCallback(MODSERIAL_IRQ_INFO *q) {
    MODSERIAL *serial = q->serial;
    if ( serial->rxGetLastChar() == '\n') {
    	newline_detected = true;
    }
}

int main() {
    gps.baud(9600);
    gps.attach(&rxCallback, MODSERIAL::RxIrq);

    // Wait here until we detect the \n going into the buffer.
    while (! newline_detected ) ;    
    
    // When we get here the RX buffer now contains a NMEA sentence.
    // ...

}

Note, the txGetLastChar() and rxGetLastChar() methods only return the last character but they do not remove that character from the associated buffer.

If this is your first time using MODSERIAL or would just like to test it out then see the example.cpp that comes with the library.



Committer:
AjK
Date:
Tue May 10 08:07:27 2011 +0000
Revision:
21:af2af4c61c2f
Parent:
20:59c74aaedda2
Child:
24:9c456e647a8f
V1.21 See ChangeLog.c

Who changed what in which revision?

UserRevisionLine numberNew contents of line
AjK 12:8c7394e2ae7f 1 /*
AjK 12:8c7394e2ae7f 2 Copyright (c) 2010 Andy Kirkham
AjK 12:8c7394e2ae7f 3
AjK 12:8c7394e2ae7f 4 Permission is hereby granted, free of charge, to any person obtaining a copy
AjK 12:8c7394e2ae7f 5 of this software and associated documentation files (the "Software"), to deal
AjK 12:8c7394e2ae7f 6 in the Software without restriction, including without limitation the rights
AjK 12:8c7394e2ae7f 7 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
AjK 12:8c7394e2ae7f 8 copies of the Software, and to permit persons to whom the Software is
AjK 12:8c7394e2ae7f 9 furnished to do so, subject to the following conditions:
AjK 12:8c7394e2ae7f 10
AjK 12:8c7394e2ae7f 11 The above copyright notice and this permission notice shall be included in
AjK 12:8c7394e2ae7f 12 all copies or substantial portions of the Software.
AjK 12:8c7394e2ae7f 13
AjK 12:8c7394e2ae7f 14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
AjK 12:8c7394e2ae7f 15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
AjK 12:8c7394e2ae7f 16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AjK 12:8c7394e2ae7f 17 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
AjK 12:8c7394e2ae7f 18 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
AjK 12:8c7394e2ae7f 19 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
AjK 12:8c7394e2ae7f 20 THE SOFTWARE.
AjK 12:8c7394e2ae7f 21
AjK 12:8c7394e2ae7f 22 @file MODSERIAL.h
AjK 12:8c7394e2ae7f 23 @purpose Extends Serial to provide fully buffered IO
AjK 12:8c7394e2ae7f 24 @version see ChangeLog.c
AjK 12:8c7394e2ae7f 25 @date Nov 2010
AjK 12:8c7394e2ae7f 26 @author Andy Kirkham
AjK 12:8c7394e2ae7f 27 */
AjK 12:8c7394e2ae7f 28
AjK 12:8c7394e2ae7f 29 #ifndef MODSERIAL_H
AjK 12:8c7394e2ae7f 30 #define MODSERIAL_H
AjK 12:8c7394e2ae7f 31
AjK 12:8c7394e2ae7f 32 /** @defgroup API The MODSERIAL API */
AjK 12:8c7394e2ae7f 33 /** @defgroup MISC Misc MODSERIAL functions */
AjK 12:8c7394e2ae7f 34 /** @defgroup INTERNALS MODSERIAL Internals */
AjK 12:8c7394e2ae7f 35
AjK 12:8c7394e2ae7f 36 #ifndef MODSERIAL_DEFAULT_RX_BUFFER_SIZE
AjK 12:8c7394e2ae7f 37 #define MODSERIAL_DEFAULT_RX_BUFFER_SIZE 256
AjK 12:8c7394e2ae7f 38 #endif
AjK 12:8c7394e2ae7f 39
AjK 12:8c7394e2ae7f 40 #ifndef MODSERIAL_DEFAULT_TX_BUFFER_SIZE
AjK 12:8c7394e2ae7f 41 #define MODSERIAL_DEFAULT_TX_BUFFER_SIZE 256
AjK 12:8c7394e2ae7f 42 #endif
AjK 12:8c7394e2ae7f 43
AjK 12:8c7394e2ae7f 44 #include "mbed.h"
AjK 12:8c7394e2ae7f 45
AjK 12:8c7394e2ae7f 46 namespace AjK {
AjK 12:8c7394e2ae7f 47
AjK 18:21ef26402365 48 // Forward reference.
AjK 18:21ef26402365 49 class MODSERIAL;
AjK 18:21ef26402365 50
AjK 18:21ef26402365 51 /**
AjK 18:21ef26402365 52 * @author Andy Kirkham
AjK 18:21ef26402365 53 * @see http://mbed.org/cookbook/MODSERIAL
AjK 18:21ef26402365 54 * @see example3a.cpp
AjK 18:21ef26402365 55 * @see example3b.cpp
AjK 18:21ef26402365 56 * @see API
AjK 18:21ef26402365 57 *
AjK 18:21ef26402365 58 * <b>MODSERIAL_IRQ_INFO</b> is a class used to pass information (and access to protected
AjK 19:a158936322cc 59 * MODSERIAL functions) to IRQ callbacks.
AjK 18:21ef26402365 60 */
AjK 18:21ef26402365 61 class MODSERIAL_IRQ_INFO
AjK 18:21ef26402365 62 {
AjK 18:21ef26402365 63 public:
AjK 18:21ef26402365 64 friend class MODSERIAL;
AjK 18:21ef26402365 65
AjK 18:21ef26402365 66 MODSERIAL *serial;
AjK 18:21ef26402365 67
AjK 18:21ef26402365 68 MODSERIAL_IRQ_INFO() { serial = 0; }
AjK 18:21ef26402365 69
AjK 18:21ef26402365 70 /** rxDiscardLastChar()
AjK 18:21ef26402365 71 *
AjK 18:21ef26402365 72 * Remove the last char placed into the rx buffer.
AjK 18:21ef26402365 73 * This is an operation that can only be performed
AjK 18:21ef26402365 74 * by an rxCallback function.
AjK 18:21ef26402365 75 * @ingroup API
AjK 18:21ef26402365 76 * @return The byte removed from the buffer.
AjK 18:21ef26402365 77 */
AjK 18:21ef26402365 78 int rxDiscardLastChar(void);
AjK 18:21ef26402365 79
AjK 18:21ef26402365 80 protected:
AjK 18:21ef26402365 81
AjK 18:21ef26402365 82 /** setSerial()
AjK 18:21ef26402365 83 *
AjK 18:21ef26402365 84 * Used internally by MODSERIAL to set the "this" pointer
AjK 18:21ef26402365 85 * of the MODSERIAL that created this object.
AjK 18:21ef26402365 86 * @ingroup INTERNAL
AjK 18:21ef26402365 87 * @param A pointer to a MODSERIAL object instance.
AjK 18:21ef26402365 88 */
AjK 18:21ef26402365 89 void setSerial(MODSERIAL *s) { serial = s; }
AjK 18:21ef26402365 90 };
AjK 18:21ef26402365 91
AjK 18:21ef26402365 92 // Forward reference dummy class.
AjK 18:21ef26402365 93 class MODSERIAL_callback_dummy;
AjK 18:21ef26402365 94
AjK 18:21ef26402365 95 /**
AjK 18:21ef26402365 96 * @author Andy Kirkham
AjK 18:21ef26402365 97 * @see http://mbed.org/cookbook/MODSERIAL
AjK 18:21ef26402365 98 * @see example3a.cpp
AjK 18:21ef26402365 99 * @see example3b.cpp
AjK 18:21ef26402365 100 * @see API
AjK 18:21ef26402365 101 *
AjK 18:21ef26402365 102 * <b>MODSERIAL_callback</b> is a class used to hold application callbacks that
AjK 18:21ef26402365 103 * MODSERIAL can invoke on certain events.
AjK 18:21ef26402365 104 */
AjK 18:21ef26402365 105 class MODSERIAL_callback
AjK 18:21ef26402365 106 {
AjK 18:21ef26402365 107 protected:
AjK 18:21ef26402365 108
AjK 18:21ef26402365 109 //! C callback function pointer.
AjK 18:21ef26402365 110 void (*c_callback)(MODSERIAL_IRQ_INFO *);
AjK 18:21ef26402365 111
AjK 18:21ef26402365 112 //! C++ callback object/method pointer (the object part).
AjK 18:21ef26402365 113 MODSERIAL_callback_dummy *obj_callback;
AjK 18:21ef26402365 114
AjK 18:21ef26402365 115 //! C++ callback object/method pointer (the method part).
AjK 18:21ef26402365 116 void (MODSERIAL_callback_dummy::*method_callback)(MODSERIAL_IRQ_INFO *);
AjK 18:21ef26402365 117
AjK 18:21ef26402365 118 public:
AjK 18:21ef26402365 119
AjK 18:21ef26402365 120 /** Constructor
AjK 18:21ef26402365 121 */
AjK 18:21ef26402365 122 MODSERIAL_callback() {
AjK 18:21ef26402365 123 c_callback = 0;
AjK 18:21ef26402365 124 obj_callback = 0;
AjK 18:21ef26402365 125 method_callback = 0;
AjK 18:21ef26402365 126 }
AjK 18:21ef26402365 127
AjK 18:21ef26402365 128 /** attach - Overloaded attachment function.
AjK 18:21ef26402365 129 *
AjK 18:21ef26402365 130 * Attach a C type function pointer as the callback.
AjK 18:21ef26402365 131 *
AjK 18:21ef26402365 132 * Note, the callback function prototype must be:-
AjK 18:21ef26402365 133 * @code
AjK 18:21ef26402365 134 * void myCallbackFunction(MODSERIAL_IRQ_INFO *);
AjK 18:21ef26402365 135 * @endcode
AjK 18:21ef26402365 136 * @param A C function pointer to call.
AjK 18:21ef26402365 137 */
AjK 18:21ef26402365 138 void attach(void (*function)(MODSERIAL_IRQ_INFO *) = 0) { c_callback = function; }
AjK 18:21ef26402365 139
AjK 18:21ef26402365 140 /** attach - Overloaded attachment function.
AjK 18:21ef26402365 141 *
AjK 18:21ef26402365 142 * Attach a C++ type object/method pointer as the callback.
AjK 18:21ef26402365 143 *
AjK 18:21ef26402365 144 * Note, the callback method prototype must be:-
AjK 18:21ef26402365 145 * @code
AjK 18:21ef26402365 146 * public:
AjK 18:21ef26402365 147 * void myCallbackFunction(MODSERIAL_IRQ_INFO *);
AjK 18:21ef26402365 148 * @endcode
AjK 18:21ef26402365 149 * @param A C++ object pointer.
AjK 18:21ef26402365 150 * @param A C++ method within the object to call.
AjK 18:21ef26402365 151 */
AjK 18:21ef26402365 152 template<class T>
AjK 18:21ef26402365 153 void attach(T* item, void (T::*method)(MODSERIAL_IRQ_INFO *)) {
AjK 18:21ef26402365 154 obj_callback = (MODSERIAL_callback_dummy *)item;
AjK 18:21ef26402365 155 method_callback = (void (MODSERIAL_callback_dummy::*)(MODSERIAL_IRQ_INFO *))method;
AjK 18:21ef26402365 156 }
AjK 18:21ef26402365 157
AjK 18:21ef26402365 158 /** call - Overloaded callback initiator.
AjK 18:21ef26402365 159 *
AjK 18:21ef26402365 160 * call the callback function.
AjK 18:21ef26402365 161 *
AjK 20:59c74aaedda2 162 * @param A pointer to a MODSERIAL_IRQ_INFO object.
AjK 18:21ef26402365 163 */
AjK 18:21ef26402365 164 void call(MODSERIAL_IRQ_INFO *arg) {
AjK 18:21ef26402365 165 if (c_callback != 0) {
AjK 18:21ef26402365 166 (*c_callback)(arg);
AjK 18:21ef26402365 167 }
AjK 18:21ef26402365 168 else {
AjK 18:21ef26402365 169 if (obj_callback != 0 && method_callback != 0) {
AjK 18:21ef26402365 170 (obj_callback->*method_callback)(arg);
AjK 18:21ef26402365 171 }
AjK 18:21ef26402365 172 }
AjK 18:21ef26402365 173 }
AjK 18:21ef26402365 174 };
AjK 18:21ef26402365 175
AjK 12:8c7394e2ae7f 176 /**
AjK 12:8c7394e2ae7f 177 * @author Andy Kirkham
AjK 12:8c7394e2ae7f 178 * @see http://mbed.org/cookbook/MODSERIAL
AjK 12:8c7394e2ae7f 179 * @see http://mbed.org/handbook/Serial
AjK 19:a158936322cc 180 * @see example1.cpp
AjK 19:a158936322cc 181 * @see example2.cpp
AjK 19:a158936322cc 182 * @see example3a.cpp
AjK 19:a158936322cc 183 * @see example3b.cpp
AjK 19:a158936322cc 184 * @see example_dma.cpp
AjK 12:8c7394e2ae7f 185 * @see API
AjK 12:8c7394e2ae7f 186 *
AjK 12:8c7394e2ae7f 187 * <b>MODSERIAL</b> extends the Mbed library <a href="/handbook/Serial">Serial</a> to provide fully buffered
AjK 12:8c7394e2ae7f 188 * TX and RX streams. Buffer length is fully customisable.
AjK 12:8c7394e2ae7f 189 *
AjK 12:8c7394e2ae7f 190 * Before using MODSERIAL users should be familar with Mbed's standard <a href="/handbook/Serial">Serial</a>
AjK 12:8c7394e2ae7f 191 * library object. MODSERIAL is a direct "drop in" replacement for <a href="/handbook/Serial">Serial</a>. Where
AjK 12:8c7394e2ae7f 192 * previously Serial was used, MODSERIAL can be used as adirect replacement instantly offering standard
AjK 12:8c7394e2ae7f 193 * TX and RX buffering. By default, both TX and RX buffers are 256 bytes in length.
AjK 12:8c7394e2ae7f 194 *
AjK 12:8c7394e2ae7f 195 * @image html /media/uploads/mbedofficial/serial_interfaces.png
AjK 12:8c7394e2ae7f 196 *
AjK 12:8c7394e2ae7f 197 * Standard example:
AjK 12:8c7394e2ae7f 198 * @code
AjK 12:8c7394e2ae7f 199 * #include "mbed.h"
AjK 12:8c7394e2ae7f 200 * #include "MODSERIAL.h"
AjK 12:8c7394e2ae7f 201 *
AjK 12:8c7394e2ae7f 202 * MODSERIAL pc(USBTX, USBRX); // tx, rx
AjK 12:8c7394e2ae7f 203 *
AjK 12:8c7394e2ae7f 204 * int main() {
AjK 12:8c7394e2ae7f 205 * pc.printf("Hello World!");
AjK 12:8c7394e2ae7f 206 * while(1) {
AjK 12:8c7394e2ae7f 207 * pc.putc(pc.getc() + 1);
AjK 12:8c7394e2ae7f 208 * }
AjK 12:8c7394e2ae7f 209 * }
AjK 12:8c7394e2ae7f 210 * @endcode
AjK 12:8c7394e2ae7f 211 *
AjK 12:8c7394e2ae7f 212 * Example with alternate buffer length:
AjK 12:8c7394e2ae7f 213 * @code
AjK 12:8c7394e2ae7f 214 * #include "mbed.h"
AjK 12:8c7394e2ae7f 215 * #include "MODSERIAL.h"
AjK 12:8c7394e2ae7f 216 *
AjK 12:8c7394e2ae7f 217 * // Make TX and RX buffers 512byes in length
AjK 12:8c7394e2ae7f 218 * MODSERIAL pc(USBTX, USBRX, 512); // tx, rx
AjK 12:8c7394e2ae7f 219 *
AjK 12:8c7394e2ae7f 220 * int main() {
AjK 12:8c7394e2ae7f 221 * pc.printf("Hello World!");
AjK 12:8c7394e2ae7f 222 * while(1) {
AjK 12:8c7394e2ae7f 223 * pc.putc(pc.getc() + 1);
AjK 12:8c7394e2ae7f 224 * }
AjK 12:8c7394e2ae7f 225 * }
AjK 12:8c7394e2ae7f 226 * @endcode
AjK 12:8c7394e2ae7f 227 *
AjK 12:8c7394e2ae7f 228 * Example with alternate buffer length:
AjK 12:8c7394e2ae7f 229 * @code
AjK 12:8c7394e2ae7f 230 * #include "mbed.h"
AjK 12:8c7394e2ae7f 231 * #include "MODSERIAL.h"
AjK 12:8c7394e2ae7f 232 *
AjK 12:8c7394e2ae7f 233 * // Make TX 1024bytes and RX 512byes in length
AjK 12:8c7394e2ae7f 234 * MODSERIAL pc(USBTX, USBRX, 1024, 512); // tx, rx
AjK 12:8c7394e2ae7f 235 *
AjK 12:8c7394e2ae7f 236 * int main() {
AjK 12:8c7394e2ae7f 237 * pc.printf("Hello World!");
AjK 12:8c7394e2ae7f 238 * while(1) {
AjK 12:8c7394e2ae7f 239 * pc.putc(pc.getc() + 1);
AjK 12:8c7394e2ae7f 240 * }
AjK 12:8c7394e2ae7f 241 * }
AjK 12:8c7394e2ae7f 242 * @endcode
AjK 12:8c7394e2ae7f 243 */
AjK 12:8c7394e2ae7f 244 class MODSERIAL : public Serial
AjK 12:8c7394e2ae7f 245 {
AjK 12:8c7394e2ae7f 246 public:
AjK 12:8c7394e2ae7f 247
AjK 18:21ef26402365 248 // Allow instances of MODSERIAL_IRQ_INFO to use protected properties and methods.
AjK 18:21ef26402365 249 friend class MODSERIAL_IRQ_INFO;
AjK 18:21ef26402365 250
AjK 12:8c7394e2ae7f 251 //! A copy of the Serial parity enum
AjK 12:8c7394e2ae7f 252 /** @see http://mbed.org/projects/libraries/api/mbed/trunk/Serial#Serial.format */
AjK 12:8c7394e2ae7f 253 enum Parity {
AjK 12:8c7394e2ae7f 254 None = 0
AjK 12:8c7394e2ae7f 255 , Odd
AjK 12:8c7394e2ae7f 256 , Even
AjK 12:8c7394e2ae7f 257 , Forced1
AjK 12:8c7394e2ae7f 258 , Forced0
AjK 12:8c7394e2ae7f 259 };
AjK 12:8c7394e2ae7f 260
AjK 12:8c7394e2ae7f 261 //! A copy of the Serial IrqType enum
AjK 12:8c7394e2ae7f 262 enum IrqType {
AjK 12:8c7394e2ae7f 263 RxIrq = 0
AjK 12:8c7394e2ae7f 264 , TxIrq
AjK 12:8c7394e2ae7f 265 , RxOvIrq
AjK 12:8c7394e2ae7f 266 , TxOvIrq
AjK 12:8c7394e2ae7f 267 , TxEmpty
AjK 12:8c7394e2ae7f 268 , RxAutoDetect
AjK 12:8c7394e2ae7f 269 , NumOfIrqTypes
AjK 12:8c7394e2ae7f 270 };
AjK 12:8c7394e2ae7f 271
AjK 12:8c7394e2ae7f 272 //! Non-blocking functions return code.
AjK 12:8c7394e2ae7f 273 enum Result {
AjK 12:8c7394e2ae7f 274 Ok = 0 /*!< Ok. */
AjK 12:8c7394e2ae7f 275 , NoMemory = -1 /*!< Memory allocation failed. */
AjK 12:8c7394e2ae7f 276 , NoChar = -1 /*!< No character in buffer. */
AjK 12:8c7394e2ae7f 277 , BufferOversize = -2 /*!< Oversized buffer. */
AjK 12:8c7394e2ae7f 278 };
AjK 12:8c7394e2ae7f 279
AjK 12:8c7394e2ae7f 280 /**
AjK 12:8c7394e2ae7f 281 * The MODSERIAL constructor is used to initialise the serial object.
AjK 12:8c7394e2ae7f 282 *
AjK 12:8c7394e2ae7f 283 * @param tx PinName of the TX pin.
AjK 12:8c7394e2ae7f 284 * @param rx PinName of the TX pin.
AjK 12:8c7394e2ae7f 285 * @param name An option name for RPC usage.
AjK 12:8c7394e2ae7f 286 */
AjK 12:8c7394e2ae7f 287 MODSERIAL(PinName tx, PinName rx, const char *name = NULL);
AjK 12:8c7394e2ae7f 288
AjK 12:8c7394e2ae7f 289 /**
AjK 12:8c7394e2ae7f 290 * The MODSERIAL constructor is used to initialise the serial object.
AjK 12:8c7394e2ae7f 291 *
AjK 12:8c7394e2ae7f 292 * @param tx PinName of the TX pin.
AjK 12:8c7394e2ae7f 293 * @param rx PinName of the TX pin.
AjK 12:8c7394e2ae7f 294 * @param bufferSize Integer of the TX and RX buffer sizes.
AjK 12:8c7394e2ae7f 295 * @param name An option name for RPC usage.
AjK 12:8c7394e2ae7f 296 */
AjK 12:8c7394e2ae7f 297 MODSERIAL(PinName tx, PinName rx, int bufferSize, const char *name = NULL);
AjK 12:8c7394e2ae7f 298
AjK 12:8c7394e2ae7f 299 /**
AjK 12:8c7394e2ae7f 300 * The MODSERIAL constructor is used to initialise the serial object.
AjK 12:8c7394e2ae7f 301 *
AjK 12:8c7394e2ae7f 302 * @param tx PinName of the TX pin.
AjK 12:8c7394e2ae7f 303 * @param rx PinName of the TX pin.
AjK 12:8c7394e2ae7f 304 * @param txBufferSize Integer of the TX buffer sizes.
AjK 12:8c7394e2ae7f 305 * @param rxBufferSize Integer of the RX buffer sizes.
AjK 12:8c7394e2ae7f 306 * @param name An option name for RPC usage.
AjK 12:8c7394e2ae7f 307 */
AjK 12:8c7394e2ae7f 308 MODSERIAL(PinName tx, PinName rx, int txBufferSize, int rxBufferSize, const char *name = NULL);
AjK 12:8c7394e2ae7f 309
AjK 12:8c7394e2ae7f 310 virtual ~MODSERIAL();
AjK 12:8c7394e2ae7f 311
AjK 12:8c7394e2ae7f 312 /**
AjK 12:8c7394e2ae7f 313 * Function: attach
AjK 12:8c7394e2ae7f 314 *
AjK 12:8c7394e2ae7f 315 * The Mbed standard <a href="/handbook/Serial">Serial</a> library object allows an interrupt callback
AjK 12:8c7394e2ae7f 316 * to be made when a byte is received by the TX or RX UART hardware. MODSERIAL traps these interrupts
AjK 12:8c7394e2ae7f 317 * to enable it's buffering system. However, after the byte has been received/sent under interrupt control,
AjK 12:8c7394e2ae7f 318 * MODSERIAL can callback a user function as a notification of the interrupt. Note, user code should not
AjK 12:8c7394e2ae7f 319 * directly interact with the Uart hardware, MODSERIAL does that, instead, MODSERIAL API functions should
AjK 12:8c7394e2ae7f 320 * be used.
AjK 12:8c7394e2ae7f 321 *
AjK 12:8c7394e2ae7f 322 * <b>Note</b>, a character is written out then, if there is room in the TX FIFO and the TX buffer is empty,
AjK 12:8c7394e2ae7f 323 * putc() will put the character directly into THR (the output holding register). If the TX FIFO is full and
AjK 12:8c7394e2ae7f 324 * cannot accept the character, it is placed into the TX output buffer. The TX interrupts are then enabled
AjK 12:8c7394e2ae7f 325 * so that when the TX FIFO empties, the TX buffer is then transferred to the THR FIFO. The TxIrq will ONLY
AjK 12:8c7394e2ae7f 326 * be activated when this transfer of a character from BUFFER to THR FIFO takes place. If your character
AjK 12:8c7394e2ae7f 327 * throughput is not high bandwidth, then the 16 byte TX FIFO may be enough and the TX output buffer may
AjK 12:8c7394e2ae7f 328 * never come into play.
AjK 12:8c7394e2ae7f 329 *
AjK 12:8c7394e2ae7f 330 * @code
AjK 12:8c7394e2ae7f 331 * #include "mbed.h"
AjK 12:8c7394e2ae7f 332 * #include "MODSERIAL.h"
AjK 12:8c7394e2ae7f 333 *
AjK 12:8c7394e2ae7f 334 * DigitalOut led1(LED1);
AjK 12:8c7394e2ae7f 335 * DigitalOut led2(LED2);
AjK 12:8c7394e2ae7f 336 * DigitalOut led3(LED3);
AjK 12:8c7394e2ae7f 337 *
AjK 12:8c7394e2ae7f 338 * // To test, connect p9 to p10 as a loopback.
AjK 12:8c7394e2ae7f 339 * MODSERIAL pc(p9, p10);
AjK 12:8c7394e2ae7f 340 *
AjK 12:8c7394e2ae7f 341 * // This function is called when a character goes into the TX buffer.
AjK 12:8c7394e2ae7f 342 * void txCallback(void) {
AjK 12:8c7394e2ae7f 343 * led2 = !led2;
AjK 12:8c7394e2ae7f 344 * }
AjK 12:8c7394e2ae7f 345 *
AjK 12:8c7394e2ae7f 346 * // This function is called when a character goes into the RX buffer.
AjK 12:8c7394e2ae7f 347 * void rxCallback(void) {
AjK 12:8c7394e2ae7f 348 * led3 = !led3;
AjK 12:8c7394e2ae7f 349 * }
AjK 12:8c7394e2ae7f 350 *
AjK 12:8c7394e2ae7f 351 * int main() {
AjK 12:8c7394e2ae7f 352 * pc.baud(115200);
AjK 12:8c7394e2ae7f 353 * pc.attach(&txCallback, MODSERIAL::TxIrq);
AjK 12:8c7394e2ae7f 354 * pc.attach(&rxCallback, MODSERIAL::RxIrq);
AjK 12:8c7394e2ae7f 355 *
AjK 12:8c7394e2ae7f 356 * while(1) {
AjK 12:8c7394e2ae7f 357 * led1 = !led1;
AjK 12:8c7394e2ae7f 358 * wait(0.5);
AjK 12:8c7394e2ae7f 359 * pc.putc('A');
AjK 12:8c7394e2ae7f 360 * wait(0.5);
AjK 12:8c7394e2ae7f 361 * }
AjK 12:8c7394e2ae7f 362 * ]
AjK 12:8c7394e2ae7f 363 * @endcode
AjK 12:8c7394e2ae7f 364 *
AjK 12:8c7394e2ae7f 365 * @ingroup API
AjK 12:8c7394e2ae7f 366 * @param fptr A pointer to a void function, or 0 to set as none
AjK 12:8c7394e2ae7f 367 * @param type Which serial interrupt to attach the member function to (Seriall::RxIrq for receive, TxIrq for transmit buffer empty)
AjK 12:8c7394e2ae7f 368 */
AjK 18:21ef26402365 369 void attach(void (*fptr)(MODSERIAL_IRQ_INFO *), IrqType type = RxIrq) { _isr[type].attach(fptr); }
AjK 12:8c7394e2ae7f 370
AjK 12:8c7394e2ae7f 371 /**
AjK 12:8c7394e2ae7f 372 * Function: attach
AjK 12:8c7394e2ae7f 373 *
AjK 12:8c7394e2ae7f 374 * The Mbed standard <a href="/handbook/Serial">Serial</a> library object allows an interrupt callback
AjK 12:8c7394e2ae7f 375 * to be made when a byte is received by the TX or RX UART hardware. MODSERIAL traps these interrupts
AjK 12:8c7394e2ae7f 376 * to enable it's buffering system. However, after the byte has been received/sent under interrupt control,
AjK 12:8c7394e2ae7f 377 * MODSERIAL can callback a user function as a notification of the interrupt. Note, user code should not
AjK 12:8c7394e2ae7f 378 * directly interact with the Uart hardware, MODSERIAL does that, instead, MODSERIAL API functions should
AjK 12:8c7394e2ae7f 379 * be used.
AjK 12:8c7394e2ae7f 380 *
AjK 12:8c7394e2ae7f 381 * <b>Note</b>, a character is written out then, if there is room in the TX FIFO and the TX buffer is empty,
AjK 12:8c7394e2ae7f 382 * putc() will put the character directly into THR (the output holding register). If the TX FIFO is full and
AjK 12:8c7394e2ae7f 383 * cannot accept the character, it is placed into the TX output buffer. The TX interrupts are then enabled
AjK 12:8c7394e2ae7f 384 * so that when the TX FIFO empties, the TX buffer is then transferred to the THR FIFO. The TxIrq will ONLY
AjK 12:8c7394e2ae7f 385 * be activated when this transfer of a character from BUFFER to THR FIFO takes place. If your character
AjK 12:8c7394e2ae7f 386 * throughput is not high bandwidth, then the 16 byte TX FIFO may be enough and the TX output buffer may
AjK 12:8c7394e2ae7f 387 * never come into play.
AjK 12:8c7394e2ae7f 388 *
AjK 12:8c7394e2ae7f 389 * @code
AjK 12:8c7394e2ae7f 390 * #include "mbed.h"
AjK 12:8c7394e2ae7f 391 * #include "MODSERIAL.h"
AjK 12:8c7394e2ae7f 392 *
AjK 12:8c7394e2ae7f 393 * DigitalOut led1(LED1);
AjK 12:8c7394e2ae7f 394 * DigitalOut led2(LED2);
AjK 12:8c7394e2ae7f 395 * DigitalOut led3(LED3);
AjK 12:8c7394e2ae7f 396 *
AjK 12:8c7394e2ae7f 397 * // To test, connect p9 to p10 as a loopback.
AjK 12:8c7394e2ae7f 398 * MODSERIAL pc(p9, p10);
AjK 12:8c7394e2ae7f 399 *
AjK 12:8c7394e2ae7f 400 * class Foo {
AjK 12:8c7394e2ae7f 401 * public:
AjK 12:8c7394e2ae7f 402 * // This method is called when a character goes into the TX buffer.
AjK 12:8c7394e2ae7f 403 * void txCallback(void) { led2 = !led2; }
AjK 12:8c7394e2ae7f 404 *
AjK 12:8c7394e2ae7f 405 * // This method is called when a character goes into the RX buffer.
AjK 12:8c7394e2ae7f 406 * void rxCallback(void) { led3 = !led3; }
AjK 12:8c7394e2ae7f 407 * };
AjK 12:8c7394e2ae7f 408 *
AjK 12:8c7394e2ae7f 409 * Foo foo;
AjK 12:8c7394e2ae7f 410 *
AjK 12:8c7394e2ae7f 411 * int main() {
AjK 12:8c7394e2ae7f 412 * pc.baud(115200);
AjK 12:8c7394e2ae7f 413 * pc.attach(&foo, &Foo::txCallback, MODSERIAL::TxIrq);
AjK 12:8c7394e2ae7f 414 * pc.attach(&foo, &Foo::rxCallback, MODSERIAL::RxIrq);
AjK 12:8c7394e2ae7f 415 *
AjK 12:8c7394e2ae7f 416 * while(1) {
AjK 12:8c7394e2ae7f 417 * led1 = !led1;
AjK 12:8c7394e2ae7f 418 * wait(0.5);
AjK 12:8c7394e2ae7f 419 * pc.putc('A');
AjK 12:8c7394e2ae7f 420 * wait(0.5);
AjK 12:8c7394e2ae7f 421 * }
AjK 12:8c7394e2ae7f 422 * ]
AjK 12:8c7394e2ae7f 423 * @endcode
AjK 12:8c7394e2ae7f 424 *
AjK 12:8c7394e2ae7f 425 * @ingroup API
AjK 12:8c7394e2ae7f 426 * @param tptr A pointer to the object to call the member function on
AjK 12:8c7394e2ae7f 427 * @param mptr A pointer to the member function to be called
AjK 12:8c7394e2ae7f 428 * @param type Which serial interrupt to attach the member function to (Seriall::RxIrq for receive, TxIrq for transmit buffer empty)
AjK 12:8c7394e2ae7f 429 */
AjK 12:8c7394e2ae7f 430 template<typename T>
AjK 21:af2af4c61c2f 431 void attach(T* tptr, void (T::*mptr)(MODSERIAL_IRQ_INFO *), IrqType type = RxIrq) {
AjK 18:21ef26402365 432 if((mptr != 0) && (tptr != 0)) {
AjK 12:8c7394e2ae7f 433 _isr[type].attach(tptr, mptr);
AjK 12:8c7394e2ae7f 434 }
AjK 12:8c7394e2ae7f 435 }
AjK 12:8c7394e2ae7f 436
AjK 12:8c7394e2ae7f 437 /**
AjK 12:8c7394e2ae7f 438 * @see attach
AjK 12:8c7394e2ae7f 439 * @ingroup API
AjK 12:8c7394e2ae7f 440 */
AjK 18:21ef26402365 441 void connect(void (*fptr)(MODSERIAL_IRQ_INFO *), IrqType type = RxIrq) { _isr[RxIrq].attach(fptr); }
AjK 12:8c7394e2ae7f 442
AjK 12:8c7394e2ae7f 443 /**
AjK 12:8c7394e2ae7f 444 * @see attach
AjK 12:8c7394e2ae7f 445 * @ingroup API
AjK 12:8c7394e2ae7f 446 */
AjK 12:8c7394e2ae7f 447 template<typename T>
AjK 18:21ef26402365 448 void connect(T* tptr, void (T::*mptr)(MODSERIAL_IRQ_INFO *), IrqType type = RxIrq) {
AjK 18:21ef26402365 449 if((mptr != 0) && (tptr != 0)) {
AjK 12:8c7394e2ae7f 450 _isr[type].attach(tptr, mptr);
AjK 12:8c7394e2ae7f 451 }
AjK 12:8c7394e2ae7f 452 }
AjK 12:8c7394e2ae7f 453
AjK 12:8c7394e2ae7f 454 /**
AjK 12:8c7394e2ae7f 455 * Function: writeable
AjK 12:8c7394e2ae7f 456 *
AjK 12:8c7394e2ae7f 457 * Determine if there is space available to write a byte
AjK 12:8c7394e2ae7f 458 *
AjK 12:8c7394e2ae7f 459 * @ingroup API
AjK 12:8c7394e2ae7f 460 * @return 1 if there is space to write a character, else 0
AjK 12:8c7394e2ae7f 461 */
AjK 12:8c7394e2ae7f 462 int writeable() { return txBufferFull() ? 0 : 1; }
AjK 12:8c7394e2ae7f 463
AjK 12:8c7394e2ae7f 464 /**
AjK 12:8c7394e2ae7f 465 * Function: readable
AjK 12:8c7394e2ae7f 466 *
AjK 12:8c7394e2ae7f 467 * Determine if there is a byte available to read
AjK 12:8c7394e2ae7f 468 *
AjK 12:8c7394e2ae7f 469 * @ingroup API
AjK 12:8c7394e2ae7f 470 * @return 1 if there is a character available to read, else 0
AjK 12:8c7394e2ae7f 471 */
AjK 12:8c7394e2ae7f 472 int readable() { return rxBufferEmpty() ? 0 : 1; }
AjK 12:8c7394e2ae7f 473
AjK 12:8c7394e2ae7f 474 /**
AjK 12:8c7394e2ae7f 475 * Function: txBufferSane
AjK 12:8c7394e2ae7f 476 *
AjK 12:8c7394e2ae7f 477 * Determine if the TX buffer has been initialized.
AjK 12:8c7394e2ae7f 478 *
AjK 12:8c7394e2ae7f 479 * @ingroup API
AjK 12:8c7394e2ae7f 480 * @return true if the buffer is initialized, else false
AjK 12:8c7394e2ae7f 481 */
AjK 12:8c7394e2ae7f 482 bool txBufferSane(void) { return buffer[TxIrq] != (char *)NULL ? true : false; }
AjK 12:8c7394e2ae7f 483
AjK 12:8c7394e2ae7f 484 /**
AjK 12:8c7394e2ae7f 485 * Function: rxBufferSane
AjK 12:8c7394e2ae7f 486 *
AjK 12:8c7394e2ae7f 487 * Determine if the RX buffer has been initialized.
AjK 12:8c7394e2ae7f 488 *
AjK 12:8c7394e2ae7f 489 * @ingroup API
AjK 12:8c7394e2ae7f 490 * @return true if the buffer is initialized, else false
AjK 12:8c7394e2ae7f 491 */
AjK 12:8c7394e2ae7f 492 bool rxBufferSane(void) { return buffer[TxIrq] != (char *)NULL ? true : false; }
AjK 12:8c7394e2ae7f 493
AjK 12:8c7394e2ae7f 494 /**
AjK 12:8c7394e2ae7f 495 * Function: txBufferGetCount
AjK 12:8c7394e2ae7f 496 *
AjK 12:8c7394e2ae7f 497 * Returns how many bytes are in the TX buffer
AjK 12:8c7394e2ae7f 498 *
AjK 12:8c7394e2ae7f 499 * @ingroup API
AjK 12:8c7394e2ae7f 500 * @return The number of bytes in the TX buffer
AjK 12:8c7394e2ae7f 501 */
AjK 12:8c7394e2ae7f 502 int txBufferGetCount(void) { return buffer_count[TxIrq]; }
AjK 12:8c7394e2ae7f 503
AjK 12:8c7394e2ae7f 504 /**
AjK 12:8c7394e2ae7f 505 * Function: rxBufferGetCount
AjK 12:8c7394e2ae7f 506 *
AjK 12:8c7394e2ae7f 507 * Returns how many bytes are in the RX buffer
AjK 12:8c7394e2ae7f 508 *
AjK 12:8c7394e2ae7f 509 * @ingroup API
AjK 12:8c7394e2ae7f 510 * @return The number of bytes in the RX buffer
AjK 12:8c7394e2ae7f 511 */
AjK 12:8c7394e2ae7f 512 int rxBufferGetCount(void) { return buffer_count[RxIrq]; }
AjK 12:8c7394e2ae7f 513
AjK 12:8c7394e2ae7f 514 /**
AjK 12:8c7394e2ae7f 515 * Function: txBufferGetSize
AjK 12:8c7394e2ae7f 516 *
AjK 12:8c7394e2ae7f 517 * Returns the current size of the TX buffer
AjK 12:8c7394e2ae7f 518 *
AjK 12:8c7394e2ae7f 519 * @ingroup API
AjK 12:8c7394e2ae7f 520 * @return The length iof the TX buffer in bytes
AjK 12:8c7394e2ae7f 521 */
AjK 12:8c7394e2ae7f 522 int txBufferGetSize(int size) { return buffer_size[TxIrq]; }
AjK 12:8c7394e2ae7f 523
AjK 12:8c7394e2ae7f 524 /**
AjK 12:8c7394e2ae7f 525 * Function: rxBufferGetSize
AjK 12:8c7394e2ae7f 526 *
AjK 12:8c7394e2ae7f 527 * Returns the current size of the RX buffer
AjK 12:8c7394e2ae7f 528 *
AjK 12:8c7394e2ae7f 529 * @ingroup API
AjK 12:8c7394e2ae7f 530 * @return The length iof the RX buffer in bytes
AjK 12:8c7394e2ae7f 531 */
AjK 12:8c7394e2ae7f 532 int rxBufferGetSize(int size) { return buffer_size[RxIrq]; }
AjK 12:8c7394e2ae7f 533
AjK 12:8c7394e2ae7f 534 /**
AjK 12:8c7394e2ae7f 535 * Function: txBufferFull
AjK 12:8c7394e2ae7f 536 *
AjK 12:8c7394e2ae7f 537 * Is the TX buffer full?
AjK 12:8c7394e2ae7f 538 *
AjK 12:8c7394e2ae7f 539 * @ingroup API
AjK 12:8c7394e2ae7f 540 * @return true if the TX buffer is full, otherwise false
AjK 12:8c7394e2ae7f 541 */
AjK 12:8c7394e2ae7f 542 bool txBufferFull(void);
AjK 12:8c7394e2ae7f 543
AjK 12:8c7394e2ae7f 544 /**
AjK 12:8c7394e2ae7f 545 * Function: rxBufferFull
AjK 12:8c7394e2ae7f 546 *
AjK 12:8c7394e2ae7f 547 * Is the RX buffer full?
AjK 12:8c7394e2ae7f 548 *
AjK 12:8c7394e2ae7f 549 * @ingroup API
AjK 12:8c7394e2ae7f 550 * @return true if the RX buffer is full, otherwise false
AjK 12:8c7394e2ae7f 551 */
AjK 12:8c7394e2ae7f 552 bool rxBufferFull(void);
AjK 12:8c7394e2ae7f 553
AjK 12:8c7394e2ae7f 554 /**
AjK 12:8c7394e2ae7f 555 * Function: txBufferEmpty
AjK 12:8c7394e2ae7f 556 *
AjK 12:8c7394e2ae7f 557 * Is the TX buffer empty?
AjK 12:8c7394e2ae7f 558 *
AjK 12:8c7394e2ae7f 559 * @ingroup API
AjK 12:8c7394e2ae7f 560 * @return true if the TX buffer is empty, otherwise false
AjK 12:8c7394e2ae7f 561 */
AjK 12:8c7394e2ae7f 562 bool txBufferEmpty(void);
AjK 12:8c7394e2ae7f 563
AjK 12:8c7394e2ae7f 564 /**
AjK 12:8c7394e2ae7f 565 * Function: rxBufferEmpty
AjK 12:8c7394e2ae7f 566 *
AjK 12:8c7394e2ae7f 567 * Is the RX buffer empty?
AjK 12:8c7394e2ae7f 568 *
AjK 12:8c7394e2ae7f 569 * @ingroup API
AjK 12:8c7394e2ae7f 570 * @return true if the RX buffer is empty, otherwise false
AjK 12:8c7394e2ae7f 571 */
AjK 12:8c7394e2ae7f 572 bool rxBufferEmpty(void);
AjK 12:8c7394e2ae7f 573
AjK 12:8c7394e2ae7f 574 /**
AjK 12:8c7394e2ae7f 575 * Function: txBufferSetSize
AjK 12:8c7394e2ae7f 576 *
AjK 12:8c7394e2ae7f 577 * Change the TX buffer size.
AjK 12:8c7394e2ae7f 578 *
AjK 12:8c7394e2ae7f 579 * @see Result
AjK 12:8c7394e2ae7f 580 * @ingroup API
AjK 12:8c7394e2ae7f 581 * @param size The new TX buffer size in bytes.
AjK 12:8c7394e2ae7f 582 * @param m Perform a memory sanity check. Errs the Mbed if memory alloc fails.
AjK 12:8c7394e2ae7f 583 * @return Result Ok on success.
AjK 12:8c7394e2ae7f 584 */
AjK 12:8c7394e2ae7f 585 int txBufferSetSize(int size, bool m) { return resizeBuffer(size, TxIrq, m); }
AjK 12:8c7394e2ae7f 586
AjK 12:8c7394e2ae7f 587 /**
AjK 12:8c7394e2ae7f 588 * Function: rxBufferSetSize
AjK 12:8c7394e2ae7f 589 *
AjK 12:8c7394e2ae7f 590 * Change the RX buffer size.
AjK 12:8c7394e2ae7f 591 *
AjK 12:8c7394e2ae7f 592 * @see Result
AjK 12:8c7394e2ae7f 593 * @ingroup API
AjK 12:8c7394e2ae7f 594 * @param size The new RX buffer size in bytes.
AjK 12:8c7394e2ae7f 595 * @param m Perform a memory sanity check. Errs the Mbed if memory alloc fails.
AjK 12:8c7394e2ae7f 596 * @return Result Ok on success.
AjK 12:8c7394e2ae7f 597 */
AjK 12:8c7394e2ae7f 598 int rxBufferSetSize(int size, bool m) { return resizeBuffer(size, RxIrq, m); }
AjK 12:8c7394e2ae7f 599
AjK 12:8c7394e2ae7f 600 /**
AjK 12:8c7394e2ae7f 601 * Function: txBufferSetSize
AjK 12:8c7394e2ae7f 602 *
AjK 12:8c7394e2ae7f 603 * Change the TX buffer size.
AjK 12:8c7394e2ae7f 604 * Always performs a memory sanity check, halting the Mbed on failure.
AjK 12:8c7394e2ae7f 605 *
AjK 12:8c7394e2ae7f 606 * @see Result
AjK 12:8c7394e2ae7f 607 * @ingroup API
AjK 12:8c7394e2ae7f 608 * @param size The new TX buffer size in bytes.
AjK 12:8c7394e2ae7f 609 * @return Result Ok on success.
AjK 12:8c7394e2ae7f 610 */
AjK 12:8c7394e2ae7f 611 int txBufferSetSize(int size) { return resizeBuffer(size, TxIrq, true); }
AjK 12:8c7394e2ae7f 612
AjK 12:8c7394e2ae7f 613 /**
AjK 12:8c7394e2ae7f 614 * Function: rxBufferSetSize
AjK 12:8c7394e2ae7f 615 *
AjK 12:8c7394e2ae7f 616 * Change the RX buffer size.
AjK 12:8c7394e2ae7f 617 * Always performs a memory sanity check, halting the Mbed on failure.
AjK 12:8c7394e2ae7f 618 *
AjK 12:8c7394e2ae7f 619 * @see Result
AjK 12:8c7394e2ae7f 620 * @ingroup API
AjK 12:8c7394e2ae7f 621 * @param size The new RX buffer size in bytes.
AjK 12:8c7394e2ae7f 622 * @return Result Ok on success.
AjK 12:8c7394e2ae7f 623 */
AjK 12:8c7394e2ae7f 624 int rxBufferSetSize(int size) { return resizeBuffer(size, RxIrq, true); }
AjK 12:8c7394e2ae7f 625
AjK 12:8c7394e2ae7f 626 /**
AjK 12:8c7394e2ae7f 627 * Function: txBufferFlush
AjK 12:8c7394e2ae7f 628 *
AjK 12:8c7394e2ae7f 629 * Remove all bytes from the TX buffer.
AjK 12:8c7394e2ae7f 630 * @ingroup API
AjK 12:8c7394e2ae7f 631 */
AjK 12:8c7394e2ae7f 632 void txBufferFlush(void) { flushBuffer(TxIrq); }
AjK 12:8c7394e2ae7f 633
AjK 12:8c7394e2ae7f 634 /**
AjK 12:8c7394e2ae7f 635 * Function: rxBufferFlush
AjK 12:8c7394e2ae7f 636 *
AjK 12:8c7394e2ae7f 637 * Remove all bytes from the RX buffer.
AjK 12:8c7394e2ae7f 638 * @ingroup API
AjK 12:8c7394e2ae7f 639 */
AjK 12:8c7394e2ae7f 640 void rxBufferFlush(void) { flushBuffer(RxIrq); }
AjK 12:8c7394e2ae7f 641
AjK 12:8c7394e2ae7f 642 /**
AjK 12:8c7394e2ae7f 643 * Function: getcNb
AjK 12:8c7394e2ae7f 644 *
AjK 12:8c7394e2ae7f 645 * Like getc() but is non-blocking. If no bytes are in the RX buffer this
AjK 12:8c7394e2ae7f 646 * function returns Result::NoChar (-1)
AjK 12:8c7394e2ae7f 647 *
AjK 12:8c7394e2ae7f 648 * @ingroup API
AjK 12:8c7394e2ae7f 649 * @return A byte from the RX buffer or Result::NoChar (-1) if bufer empty.
AjK 12:8c7394e2ae7f 650 */
AjK 12:8c7394e2ae7f 651 int getcNb() { return __getc(false); }
AjK 12:8c7394e2ae7f 652
AjK 12:8c7394e2ae7f 653 /**
AjK 12:8c7394e2ae7f 654 * Function: getc
AjK 12:8c7394e2ae7f 655 *
AjK 12:8c7394e2ae7f 656 * Overloaded version of Serial::getc()
AjK 12:8c7394e2ae7f 657 *
AjK 12:8c7394e2ae7f 658 * This function blocks (if the RX buffer is empty the function will wait for a
AjK 12:8c7394e2ae7f 659 * character to arrive and then return that character).
AjK 12:8c7394e2ae7f 660 *
AjK 12:8c7394e2ae7f 661 * @ingroup API
AjK 12:8c7394e2ae7f 662 * @return A byte from the RX buffer
AjK 12:8c7394e2ae7f 663 */
AjK 12:8c7394e2ae7f 664 int getc() { return __getc(true); }
AjK 12:8c7394e2ae7f 665
AjK 12:8c7394e2ae7f 666 /**
AjK 12:8c7394e2ae7f 667 * Function: txGetLastChar
AjK 12:8c7394e2ae7f 668 *
AjK 12:8c7394e2ae7f 669 * Rteurn the last byte to pass through the TX interrupt handler.
AjK 12:8c7394e2ae7f 670 *
AjK 12:8c7394e2ae7f 671 * @ingroup MISC
AjK 12:8c7394e2ae7f 672 * @return The byte
AjK 12:8c7394e2ae7f 673 */
AjK 12:8c7394e2ae7f 674 char txGetLastChar(void) { return txc; }
AjK 12:8c7394e2ae7f 675
AjK 12:8c7394e2ae7f 676 /**
AjK 12:8c7394e2ae7f 677 * Function: rxGetLastChar
AjK 12:8c7394e2ae7f 678 *
AjK 12:8c7394e2ae7f 679 * Return the last byte to pass through the RX interrupt handler.
AjK 12:8c7394e2ae7f 680 *
AjK 12:8c7394e2ae7f 681 * @ingroup MISC
AjK 12:8c7394e2ae7f 682 * @return The byte
AjK 12:8c7394e2ae7f 683 */
AjK 12:8c7394e2ae7f 684 char rxGetLastChar(void) { return rxc; }
AjK 12:8c7394e2ae7f 685
AjK 12:8c7394e2ae7f 686 /**
AjK 12:8c7394e2ae7f 687 * Function: txIsBusy
AjK 12:8c7394e2ae7f 688 *
AjK 12:8c7394e2ae7f 689 * If the Uart is still actively sending characters this
AjK 12:8c7394e2ae7f 690 * function will return true.
AjK 12:8c7394e2ae7f 691 *
AjK 12:8c7394e2ae7f 692 * @ingroup API
AjK 12:8c7394e2ae7f 693 * @return bool
AjK 12:8c7394e2ae7f 694 */
AjK 12:8c7394e2ae7f 695 bool txIsBusy(void);
AjK 12:8c7394e2ae7f 696
AjK 12:8c7394e2ae7f 697 /**
AjK 16:8b1dbf4cce4e 698 * Function: autoDetectChar
AjK 12:8c7394e2ae7f 699 *
AjK 12:8c7394e2ae7f 700 * Set the char that, if seen incoming, invokes the AutoDetectChar callback.
AjK 12:8c7394e2ae7f 701 *
AjK 12:8c7394e2ae7f 702 * @ingroup API
AjK 12:8c7394e2ae7f 703 * @param int c The character to detect.
AjK 12:8c7394e2ae7f 704 */
AjK 16:8b1dbf4cce4e 705 void autoDetectChar(char c) { auto_detect_char = c; }
AjK 12:8c7394e2ae7f 706
AjK 12:8c7394e2ae7f 707 /**
AjK 12:8c7394e2ae7f 708 * Function: move
AjK 12:8c7394e2ae7f 709 *
AjK 12:8c7394e2ae7f 710 * Move contents of RX buffer to external buffer. Stops if "end" detected.
AjK 12:8c7394e2ae7f 711 *
AjK 12:8c7394e2ae7f 712 * @ingroup API
AjK 12:8c7394e2ae7f 713 * @param char *s The destination buffer address
AjK 12:8c7394e2ae7f 714 * @param int max The maximum number of chars to move.
AjK 12:8c7394e2ae7f 715 * @param char end If this char is detected stop moving.
AjK 12:8c7394e2ae7f 716 */
AjK 12:8c7394e2ae7f 717 int move(char *s, int max, char end) {
AjK 12:8c7394e2ae7f 718 int counter = 0;
AjK 12:8c7394e2ae7f 719 char c;
AjK 12:8c7394e2ae7f 720 while(readable()) {
AjK 12:8c7394e2ae7f 721 c = getc();
AjK 12:8c7394e2ae7f 722 if (c == end) break;
AjK 12:8c7394e2ae7f 723 *(s++) = c;
AjK 12:8c7394e2ae7f 724 counter++;
AjK 12:8c7394e2ae7f 725 if (counter == max) break;
AjK 12:8c7394e2ae7f 726 }
AjK 12:8c7394e2ae7f 727 return counter;
AjK 12:8c7394e2ae7f 728 }
AjK 12:8c7394e2ae7f 729
AjK 12:8c7394e2ae7f 730 /**
AjK 12:8c7394e2ae7f 731 * Function: move (overloaded)
AjK 12:8c7394e2ae7f 732 *
AjK 12:8c7394e2ae7f 733 * Move contents of RX buffer to external buffer. Stops if auto_detect_char detected.
AjK 12:8c7394e2ae7f 734 *
AjK 12:8c7394e2ae7f 735 * @ingroup API
AjK 12:8c7394e2ae7f 736 * @param int max The maximum number of chars to move.
AjK 12:8c7394e2ae7f 737 * @param char *s The destination buffer address
AjK 12:8c7394e2ae7f 738 */
AjK 12:8c7394e2ae7f 739 int move(char *s, int max) {
AjK 12:8c7394e2ae7f 740 return move(s, max, auto_detect_char);
AjK 12:8c7394e2ae7f 741 }
AjK 12:8c7394e2ae7f 742
AjK 12:8c7394e2ae7f 743 #if 0 // Inhereted from Serial/Stream, for documentation only
AjK 12:8c7394e2ae7f 744 /**
AjK 12:8c7394e2ae7f 745 * Function: putc
AjK 12:8c7394e2ae7f 746 *
AjK 12:8c7394e2ae7f 747 * Write a character
AjK 12:8c7394e2ae7f 748 * Inhereted from Serial/Stream
AjK 12:8c7394e2ae7f 749 *
AjK 12:8c7394e2ae7f 750 * @see http://mbed.org/projects/libraries/api/mbed/trunk/Serial#Serial.putc
AjK 12:8c7394e2ae7f 751 * @ingroup API
AjK 12:8c7394e2ae7f 752 * @param c The character to write to the serial port
AjK 12:8c7394e2ae7f 753 */
AjK 12:8c7394e2ae7f 754 int putc(int c);
AjK 12:8c7394e2ae7f 755 #endif
AjK 12:8c7394e2ae7f 756
AjK 12:8c7394e2ae7f 757 #if 0 // Inhereted from Serial/Stream, for documentation only
AjK 12:8c7394e2ae7f 758 /**
AjK 12:8c7394e2ae7f 759 * Function: printf
AjK 12:8c7394e2ae7f 760 *
AjK 12:8c7394e2ae7f 761 * Write a formated string
AjK 12:8c7394e2ae7f 762 * Inhereted from Serial/Stream
AjK 12:8c7394e2ae7f 763 *
AjK 12:8c7394e2ae7f 764 * @see http://mbed.org/projects/libraries/api/mbed/trunk/Serial#Serial.printf
AjK 12:8c7394e2ae7f 765 * @ingroup API
AjK 12:8c7394e2ae7f 766 * @param format A printf-style format string, followed by the variables to use in formating the string.
AjK 12:8c7394e2ae7f 767 */
AjK 12:8c7394e2ae7f 768 int printf(const char* format, ...);
AjK 12:8c7394e2ae7f 769 #endif
AjK 12:8c7394e2ae7f 770
AjK 12:8c7394e2ae7f 771 #if 0 // Inhereted from Serial/Stream, for documentation only
AjK 12:8c7394e2ae7f 772 /**
AjK 12:8c7394e2ae7f 773 * Function: scanf
AjK 12:8c7394e2ae7f 774 *
AjK 12:8c7394e2ae7f 775 * Read a formated string
AjK 12:8c7394e2ae7f 776 * Inhereted from Serial/Stream
AjK 12:8c7394e2ae7f 777 *
AjK 12:8c7394e2ae7f 778 * @see http://mbed.org/projects/libraries/api/mbed/trunk/Serial#Serial.scanf
AjK 12:8c7394e2ae7f 779 * @ingroup API
AjK 12:8c7394e2ae7f 780 * @param format - A scanf-style format string, followed by the pointers to variables to store the results.
AjK 12:8c7394e2ae7f 781 */
AjK 12:8c7394e2ae7f 782 int scanf(const char* format, ...);
AjK 12:8c7394e2ae7f 783 #endif
AjK 18:21ef26402365 784
AjK 18:21ef26402365 785 protected:
AjK 18:21ef26402365 786 /**
AjK 18:21ef26402365 787 * Used to pass information to callbacks.
AjK 18:21ef26402365 788 * @ingroup INTERNALS
AjK 18:21ef26402365 789 */
AjK 18:21ef26402365 790 MODSERIAL_IRQ_INFO callbackInfo;
AjK 18:21ef26402365 791
AjK 18:21ef26402365 792 /**
AjK 18:21ef26402365 793 * Remove the last char placed into the rx buffer.
AjK 18:21ef26402365 794 * This is an operation that can only be performed
AjK 18:21ef26402365 795 * by an rxCallback function. To protect the buffers
AjK 18:21ef26402365 796 * this function is defined protected so that a
AjK 18:21ef26402365 797 * regular application cannot call it directly. It
AjK 18:21ef26402365 798 * can only be called by the public version within a
AjK 18:21ef26402365 799 * MODSERIAL_IRQ_INFO class.
AjK 18:21ef26402365 800 * @ingroup INTERNALS
AjK 18:21ef26402365 801 * @return The byte removed from the buffer.
AjK 18:21ef26402365 802 */
AjK 18:21ef26402365 803 int rxDiscardLastChar(void);
AjK 12:8c7394e2ae7f 804
AjK 18:21ef26402365 805 private:
AjK 12:8c7394e2ae7f 806
AjK 12:8c7394e2ae7f 807 /**
AjK 12:8c7394e2ae7f 808 * A pointer to the UART peripheral base address being used.
AjK 12:8c7394e2ae7f 809 * @ingroup INTERNALS
AjK 12:8c7394e2ae7f 810 */
AjK 12:8c7394e2ae7f 811 void *_base;
AjK 12:8c7394e2ae7f 812
AjK 12:8c7394e2ae7f 813 /**
AjK 12:8c7394e2ae7f 814 * The last byte to pass through the TX IRQ handler.
AjK 12:8c7394e2ae7f 815 * @ingroup INTERNALS
AjK 12:8c7394e2ae7f 816 */
AjK 12:8c7394e2ae7f 817 volatile char txc;
AjK 12:8c7394e2ae7f 818
AjK 12:8c7394e2ae7f 819 /**
AjK 12:8c7394e2ae7f 820 * The last byte to pass through the RX IRQ handler.
AjK 12:8c7394e2ae7f 821 * @ingroup INTERNALS
AjK 12:8c7394e2ae7f 822 */
AjK 12:8c7394e2ae7f 823 volatile char rxc;
AjK 12:8c7394e2ae7f 824
AjK 12:8c7394e2ae7f 825 /**
AjK 12:8c7394e2ae7f 826 * Pointers to the TX and RX buffers.
AjK 12:8c7394e2ae7f 827 * @ingroup INTERNALS
AjK 12:8c7394e2ae7f 828 */
AjK 12:8c7394e2ae7f 829 volatile char *buffer[2];
AjK 12:8c7394e2ae7f 830
AjK 12:8c7394e2ae7f 831 /**
AjK 12:8c7394e2ae7f 832 * Buffer in pointers.
AjK 12:8c7394e2ae7f 833 * @ingroup INTERNALS
AjK 12:8c7394e2ae7f 834 */
AjK 12:8c7394e2ae7f 835 volatile int buffer_in[2];
AjK 12:8c7394e2ae7f 836
AjK 12:8c7394e2ae7f 837 /**
AjK 12:8c7394e2ae7f 838 * Buffer out pointers.
AjK 12:8c7394e2ae7f 839 * @ingroup INTERNALS
AjK 12:8c7394e2ae7f 840 */
AjK 12:8c7394e2ae7f 841 volatile int buffer_out[2];
AjK 12:8c7394e2ae7f 842
AjK 12:8c7394e2ae7f 843 /**
AjK 12:8c7394e2ae7f 844 * Buffer lengths.
AjK 12:8c7394e2ae7f 845 * @ingroup INTERNALS
AjK 12:8c7394e2ae7f 846 */
AjK 12:8c7394e2ae7f 847 volatile int buffer_size[2];
AjK 12:8c7394e2ae7f 848
AjK 12:8c7394e2ae7f 849 /**
AjK 12:8c7394e2ae7f 850 * Buffer content counters.
AjK 12:8c7394e2ae7f 851 * @ingroup INTERNALS
AjK 12:8c7394e2ae7f 852 */
AjK 12:8c7394e2ae7f 853 volatile int buffer_count[2];
AjK 12:8c7394e2ae7f 854
AjK 12:8c7394e2ae7f 855 /**
AjK 12:8c7394e2ae7f 856 * Buffer overflow.
AjK 12:8c7394e2ae7f 857 * @ingroup INTERNALS
AjK 12:8c7394e2ae7f 858 */
AjK 12:8c7394e2ae7f 859 volatile int buffer_overflow[2];
AjK 12:8c7394e2ae7f 860
AjK 12:8c7394e2ae7f 861 /**
AjK 12:8c7394e2ae7f 862 * Auto-detect character.
AjK 12:8c7394e2ae7f 863 * @ingroup INTERNALS
AjK 12:8c7394e2ae7f 864 */
AjK 12:8c7394e2ae7f 865 volatile char auto_detect_char;
AjK 12:8c7394e2ae7f 866
AjK 12:8c7394e2ae7f 867 /**
AjK 12:8c7394e2ae7f 868 * Callback system.
AjK 12:8c7394e2ae7f 869 * @ingroup INTERNALS
AjK 12:8c7394e2ae7f 870 */
AjK 18:21ef26402365 871 MODSERIAL_callback _isr[NumOfIrqTypes];
AjK 12:8c7394e2ae7f 872
AjK 12:8c7394e2ae7f 873 /**
AjK 12:8c7394e2ae7f 874 * TX Interrupt Service Routine.
AjK 12:8c7394e2ae7f 875 * @ingroup INTERNALS
AjK 12:8c7394e2ae7f 876 */
AjK 12:8c7394e2ae7f 877 void isr_tx(bool doCallback);
AjK 12:8c7394e2ae7f 878
AjK 12:8c7394e2ae7f 879 /**
AjK 12:8c7394e2ae7f 880 * TX Interrupt Service Routine stub version.
AjK 12:8c7394e2ae7f 881 * @ingroup INTERNALS
AjK 12:8c7394e2ae7f 882 */
AjK 12:8c7394e2ae7f 883 void isr_tx(void) { isr_tx(true); }
AjK 12:8c7394e2ae7f 884
AjK 12:8c7394e2ae7f 885
AjK 12:8c7394e2ae7f 886 /**
AjK 12:8c7394e2ae7f 887 * RX Interrupt Service Routine.
AjK 12:8c7394e2ae7f 888 * @ingroup INTERNALS
AjK 12:8c7394e2ae7f 889 */
AjK 12:8c7394e2ae7f 890 void isr_rx(void);
AjK 12:8c7394e2ae7f 891
AjK 12:8c7394e2ae7f 892 /**
AjK 12:8c7394e2ae7f 893 * Disable the interrupts for this Uart.
AjK 12:8c7394e2ae7f 894 * @ingroup INTERNALS
AjK 12:8c7394e2ae7f 895 */
AjK 12:8c7394e2ae7f 896 void disableIrq(void);
AjK 12:8c7394e2ae7f 897
AjK 12:8c7394e2ae7f 898 /**
AjK 12:8c7394e2ae7f 899 * Enable the interrupts for this Uart.
AjK 12:8c7394e2ae7f 900 * @ingroup INTERNALS
AjK 12:8c7394e2ae7f 901 */
AjK 12:8c7394e2ae7f 902 void enableIrq(void);
AjK 18:21ef26402365 903
AjK 12:8c7394e2ae7f 904 /**
AjK 12:8c7394e2ae7f 905 * Get a character from the RX buffer
AjK 12:8c7394e2ae7f 906 * @ingroup INTERNALS
AjK 12:8c7394e2ae7f 907 * @param bool True to block (wait for input)
AjK 12:8c7394e2ae7f 908 * @return A byte from the buffer.
AjK 12:8c7394e2ae7f 909 */
AjK 12:8c7394e2ae7f 910 int __getc(bool);
AjK 12:8c7394e2ae7f 911
AjK 12:8c7394e2ae7f 912 /**
AjK 12:8c7394e2ae7f 913 * Put a character from the TX buffer
AjK 12:8c7394e2ae7f 914 * @ingroup INTERNALS
AjK 12:8c7394e2ae7f 915 * @param bool True to block (wait for space in the TX buffer if full)
AjK 12:8c7394e2ae7f 916 * @return 0 on success
AjK 12:8c7394e2ae7f 917 */
AjK 12:8c7394e2ae7f 918 int __putc(int c, bool);
AjK 12:8c7394e2ae7f 919
AjK 12:8c7394e2ae7f 920 /**
AjK 12:8c7394e2ae7f 921 * Function: _putc
AjK 12:8c7394e2ae7f 922 * Overloaded virtual function.
AjK 12:8c7394e2ae7f 923 */
AjK 12:8c7394e2ae7f 924 virtual int _putc(int c) { return __putc(c, true); }
AjK 12:8c7394e2ae7f 925
AjK 12:8c7394e2ae7f 926 /**
AjK 12:8c7394e2ae7f 927 * Function: _getc
AjK 12:8c7394e2ae7f 928 * Overloaded virtual function.
AjK 12:8c7394e2ae7f 929 */
AjK 12:8c7394e2ae7f 930 virtual int _getc() { return __getc(true); }
AjK 12:8c7394e2ae7f 931
AjK 12:8c7394e2ae7f 932 /**
AjK 12:8c7394e2ae7f 933 * Function: init
AjK 12:8c7394e2ae7f 934 * Initialize the MODSERIAL object
AjK 12:8c7394e2ae7f 935 * @ingroup INTERNALS
AjK 12:8c7394e2ae7f 936 */
AjK 12:8c7394e2ae7f 937 void init(int txSize, int rxSize);
AjK 12:8c7394e2ae7f 938
AjK 12:8c7394e2ae7f 939 /**
AjK 12:8c7394e2ae7f 940 * Function: flushBuffer
AjK 12:8c7394e2ae7f 941 * @ingroup INTERNALS
AjK 12:8c7394e2ae7f 942 */
AjK 12:8c7394e2ae7f 943 void flushBuffer(IrqType type);
AjK 12:8c7394e2ae7f 944
AjK 12:8c7394e2ae7f 945 /**
AjK 12:8c7394e2ae7f 946 * Function: resizeBuffer
AjK 12:8c7394e2ae7f 947 * @ingroup INTERNALS
AjK 12:8c7394e2ae7f 948 */
AjK 12:8c7394e2ae7f 949 int resizeBuffer(int size, IrqType type = RxIrq, bool memory_check = true);
AjK 12:8c7394e2ae7f 950
AjK 12:8c7394e2ae7f 951 /**
AjK 12:8c7394e2ae7f 952 * Function: downSizeBuffer
AjK 12:8c7394e2ae7f 953 * @ingroup INTERNALS
AjK 12:8c7394e2ae7f 954 */
AjK 12:8c7394e2ae7f 955 int downSizeBuffer(int size, IrqType type, bool memory_check);
AjK 12:8c7394e2ae7f 956
AjK 12:8c7394e2ae7f 957 /**
AjK 12:8c7394e2ae7f 958 * Function: upSizeBuffer
AjK 12:8c7394e2ae7f 959 * @ingroup INTERNALS
AjK 12:8c7394e2ae7f 960 */
AjK 12:8c7394e2ae7f 961 int upSizeBuffer(int size, IrqType type, bool memory_check);
AjK 12:8c7394e2ae7f 962
AjK 12:8c7394e2ae7f 963 /*
AjK 12:8c7394e2ae7f 964 * If MODDMA is available the compile in code to handle sending
AjK 12:8c7394e2ae7f 965 * an arbitary char buffer. Note, the parts before teh #ifdef
AjK 12:8c7394e2ae7f 966 * are declared so that MODSERIAL can access then even if MODDMA
AjK 12:8c7394e2ae7f 967 * isn't avaiable. Since MODDMA.h is only available at this point
AjK 12:8c7394e2ae7f 968 * all DMA functionality must be declared inline in the class
AjK 12:8c7394e2ae7f 969 * definition.
AjK 12:8c7394e2ae7f 970 */
AjK 12:8c7394e2ae7f 971 public:
AjK 12:8c7394e2ae7f 972
AjK 12:8c7394e2ae7f 973 int dmaSendChannel;
AjK 12:8c7394e2ae7f 974 void *moddma_p;
AjK 12:8c7394e2ae7f 975
AjK 12:8c7394e2ae7f 976 #ifdef MODDMA_H
AjK 12:8c7394e2ae7f 977
AjK 17:6c9b57c14868 978 MODDMA_Config *config;
AjK 17:6c9b57c14868 979
AjK 12:8c7394e2ae7f 980 /**
AjK 12:8c7394e2ae7f 981 * Set the "void pointer" moddma_p to be a pointer to a
AjK 12:8c7394e2ae7f 982 * MODDMA controller class instance. Used to manage the
AjK 12:8c7394e2ae7f 983 * data transfer of DMA configurations.
AjK 12:8c7394e2ae7f 984 *
AjK 12:8c7394e2ae7f 985 * @ingroup API
AjK 12:8c7394e2ae7f 986 * @param p A pointer to "the" instance of MODDMA.
AjK 12:8c7394e2ae7f 987 */
AjK 12:8c7394e2ae7f 988 void MODDMA(MODDMA *p) { moddma_p = p; }
AjK 12:8c7394e2ae7f 989
AjK 12:8c7394e2ae7f 990 /**
AjK 12:8c7394e2ae7f 991 * Send a char buffer to the Uarts TX system
AjK 12:8c7394e2ae7f 992 * using DMA. This blocks regular library
AjK 12:8c7394e2ae7f 993 * sending.
AjK 12:8c7394e2ae7f 994 *
AjK 12:8c7394e2ae7f 995 * @param buffer A char buffer of bytes to send.
AjK 12:8c7394e2ae7f 996 * @param len The length of the buffer to send.
AjK 12:8c7394e2ae7f 997 * @param dmaChannel The DMA channel to use, defaults to 7
AjK 12:8c7394e2ae7f 998 * @return MODDMA::Status MODDMA::ok if all went ok
AjK 12:8c7394e2ae7f 999 */
AjK 12:8c7394e2ae7f 1000 int dmaSend(char *buffer, int len, int dmaChannel = 7)
AjK 12:8c7394e2ae7f 1001 {
AjK 12:8c7394e2ae7f 1002 if (moddma_p == (void *)NULL) return -2;
AjK 12:8c7394e2ae7f 1003 class MODDMA *dma = (class MODDMA *)moddma_p;
AjK 12:8c7394e2ae7f 1004
AjK 12:8c7394e2ae7f 1005 dmaSendChannel = dmaChannel & 0x7;
AjK 12:8c7394e2ae7f 1006
AjK 12:8c7394e2ae7f 1007 uint32_t conn = MODDMA::UART0_Tx;
AjK 12:8c7394e2ae7f 1008 switch(_uidx) {
AjK 12:8c7394e2ae7f 1009 case 0: conn = MODDMA::UART0_Tx; break;
AjK 12:8c7394e2ae7f 1010 case 1: conn = MODDMA::UART1_Tx; break;
AjK 12:8c7394e2ae7f 1011 case 2: conn = MODDMA::UART2_Tx; break;
AjK 12:8c7394e2ae7f 1012 case 3: conn = MODDMA::UART3_Tx; break;
AjK 12:8c7394e2ae7f 1013 }
AjK 12:8c7394e2ae7f 1014
AjK 17:6c9b57c14868 1015 config = new MODDMA_Config;
AjK 12:8c7394e2ae7f 1016 config
AjK 12:8c7394e2ae7f 1017 ->channelNum ( (MODDMA::CHANNELS)(dmaSendChannel & 0x7) )
AjK 12:8c7394e2ae7f 1018 ->srcMemAddr ( (uint32_t) buffer )
AjK 12:8c7394e2ae7f 1019 ->transferSize ( len )
AjK 12:8c7394e2ae7f 1020 ->transferType ( MODDMA::m2p )
AjK 12:8c7394e2ae7f 1021 ->dstConn ( conn )
AjK 12:8c7394e2ae7f 1022 ->attach_tc ( this, &MODSERIAL::dmaSendCallback )
AjK 12:8c7394e2ae7f 1023 ->attach_err ( this, &MODSERIAL::dmaSendCallback )
AjK 12:8c7394e2ae7f 1024 ; // config end
AjK 12:8c7394e2ae7f 1025
AjK 12:8c7394e2ae7f 1026 // Setup the configuration.
AjK 17:6c9b57c14868 1027 if (dma->Setup(config) == 0) {
AjK 12:8c7394e2ae7f 1028 return -1;
AjK 12:8c7394e2ae7f 1029 }
AjK 12:8c7394e2ae7f 1030
AjK 12:8c7394e2ae7f 1031 //dma.Enable( MODDMA::Channel_0 );
AjK 12:8c7394e2ae7f 1032 dma->Enable( config->channelNum() );
AjK 12:8c7394e2ae7f 1033 return MODDMA::Ok;
AjK 12:8c7394e2ae7f 1034 }
AjK 12:8c7394e2ae7f 1035
AjK 12:8c7394e2ae7f 1036 /**
AjK 12:8c7394e2ae7f 1037 * Attach a callback to the DMA completion.
AjK 12:8c7394e2ae7f 1038 *
AjK 12:8c7394e2ae7f 1039 * @ingroup API
AjK 12:8c7394e2ae7f 1040 * @param fptr A function pointer to call
AjK 12:8c7394e2ae7f 1041 * @return this
AjK 12:8c7394e2ae7f 1042 */
AjK 18:21ef26402365 1043 void attach_dmaSendComplete(void (*fptr)(MODSERIAL_IRQ_INFO *)) {
AjK 12:8c7394e2ae7f 1044 _isrDmaSendComplete.attach(fptr);
AjK 12:8c7394e2ae7f 1045 }
AjK 12:8c7394e2ae7f 1046
AjK 12:8c7394e2ae7f 1047 /**
AjK 12:8c7394e2ae7f 1048 * Attach a callback to the DMA completion.
AjK 12:8c7394e2ae7f 1049 *
AjK 12:8c7394e2ae7f 1050 * @ingroup API
AjK 12:8c7394e2ae7f 1051 * @param tptr A template pointer to the calling object
AjK 12:8c7394e2ae7f 1052 * @param mptr A method pointer within the object to call.
AjK 12:8c7394e2ae7f 1053 * @return this
AjK 12:8c7394e2ae7f 1054 */
AjK 12:8c7394e2ae7f 1055 template<typename T>
AjK 18:21ef26402365 1056 void attach_dmaSendComplete(T* tptr, void (T::*mptr)(MODSERIAL_IRQ_INFO *)) {
AjK 12:8c7394e2ae7f 1057 if((mptr != NULL) && (tptr != NULL)) {
AjK 12:8c7394e2ae7f 1058 _isrDmaSendComplete.attach(tptr, mptr);
AjK 12:8c7394e2ae7f 1059 }
AjK 12:8c7394e2ae7f 1060 }
AjK 12:8c7394e2ae7f 1061
AjK 18:21ef26402365 1062 MODSERIAL_callback _isrDmaSendComplete;
AjK 12:8c7394e2ae7f 1063
AjK 12:8c7394e2ae7f 1064 protected:
AjK 12:8c7394e2ae7f 1065 /**
AjK 12:8c7394e2ae7f 1066 * Callback for dmaSend().
AjK 12:8c7394e2ae7f 1067 */
AjK 12:8c7394e2ae7f 1068 void dmaSendCallback(void)
AjK 12:8c7394e2ae7f 1069 {
AjK 12:8c7394e2ae7f 1070 if (moddma_p == (void *)NULL) return;
AjK 12:8c7394e2ae7f 1071 class MODDMA *dma = (class MODDMA *)moddma_p;
AjK 12:8c7394e2ae7f 1072
AjK 12:8c7394e2ae7f 1073 MODDMA_Config *config = dma->getConfig();
AjK 12:8c7394e2ae7f 1074 dma->haltAndWaitChannelComplete( (MODDMA::CHANNELS)config->channelNum());
AjK 12:8c7394e2ae7f 1075 dma->Disable( (MODDMA::CHANNELS)config->channelNum() );
AjK 12:8c7394e2ae7f 1076 if (dma->irqType() == MODDMA::TcIrq) dma->clearTcIrq();
AjK 12:8c7394e2ae7f 1077 if (dma->irqType() == MODDMA::ErrIrq) dma->clearErrIrq();
AjK 12:8c7394e2ae7f 1078 dmaSendChannel = -1;
AjK 18:21ef26402365 1079 _isrDmaSendComplete.call(&this->callbackInfo);
AjK 17:6c9b57c14868 1080 delete(config);
AjK 12:8c7394e2ae7f 1081 }
AjK 12:8c7394e2ae7f 1082
AjK 12:8c7394e2ae7f 1083 #endif // MODDMA_H
AjK 12:8c7394e2ae7f 1084
AjK 12:8c7394e2ae7f 1085 };
AjK 12:8c7394e2ae7f 1086
AjK 12:8c7394e2ae7f 1087 }; // namespace AjK ends
AjK 12:8c7394e2ae7f 1088
AjK 12:8c7394e2ae7f 1089 using namespace AjK;
AjK 12:8c7394e2ae7f 1090
AjK 12:8c7394e2ae7f 1091 #endif