A talking braille-input text message device!!

Dependencies:   Braille_In PinDetect mbed

Committer:
aganger3
Date:
Fri Oct 12 18:05:42 2012 +0000
Revision:
1:4e1b66d0799f
Parent:
0:c79379695e18
Changed title in comment;

Who changed what in which revision?

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