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