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