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