Bug fix release

Dependents:   AntiTheftGPS XbeeReceive XbeeSend Superball_Ball2 ... more

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

The features of MODSERIAL include:-

/media/uploads/mbedofficial/serial_interfaces.png

Connecting up the MODSERIAL module

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

MODSERIAL Interrupts

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

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

Delineating "packets"

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

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

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

bool newline_detected = false;

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

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

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

}

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

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



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