Bug fix release
Dependents: AntiTheftGPS XbeeReceive XbeeSend Superball_Ball2 ... more
MODSERIAL.h
00001 /* 00002 Copyright (c) 2010 Andy Kirkham 00003 00004 Permission is hereby granted, free of charge, to any person obtaining a copy 00005 of this software and associated documentation files (the "Software"), to deal 00006 in the Software without restriction, including without limitation the rights 00007 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 00008 copies of the Software, and to permit persons to whom the Software is 00009 furnished to do so, subject to the following conditions: 00010 00011 The above copyright notice and this permission notice shall be included in 00012 all copies or substantial portions of the Software. 00013 00014 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 00015 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 00016 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 00017 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 00018 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 00019 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 00020 THE SOFTWARE. 00021 00022 @file MODSERIAL.h 00023 @purpose Extends Serial to provide fully buffered IO 00024 @version see ChangeLog.c 00025 @date Nov 2010 00026 @author Andy Kirkham 00027 */ 00028 00029 #ifndef MODSERIAL_H 00030 #define MODSERIAL_H 00031 00032 /** @defgroup API The MODSERIAL API */ 00033 /** @defgroup MISC Misc MODSERIAL functions */ 00034 /** @defgroup INTERNALS MODSERIAL Internals */ 00035 00036 #ifndef MODSERIAL_DEFAULT_RX_BUFFER_SIZE 00037 #define MODSERIAL_DEFAULT_RX_BUFFER_SIZE 256 00038 #endif 00039 00040 #ifndef MODSERIAL_DEFAULT_TX_BUFFER_SIZE 00041 #define MODSERIAL_DEFAULT_TX_BUFFER_SIZE 256 00042 #endif 00043 00044 #include "mbed.h" 00045 #include "serial_api.h" 00046 00047 namespace AjK { 00048 00049 // Forward reference. 00050 class MODSERIAL ; 00051 00052 /** 00053 * @author Andy Kirkham 00054 * @see http://mbed.org/cookbook/MODSERIAL 00055 * @see example3a.cpp 00056 * @see example3b.cpp 00057 * @see API 00058 * 00059 * <b>MODSERIAL_IRQ_INFO</b> is a class used to pass information (and access to protected 00060 * MODSERIAL functions) to IRQ callbacks. 00061 */ 00062 class MODSERIAL_IRQ_INFO 00063 { 00064 public: 00065 friend class MODSERIAL ; 00066 00067 MODSERIAL *serial; 00068 00069 MODSERIAL_IRQ_INFO () { serial = 0; } 00070 00071 /** rxDiscardLastChar() 00072 * 00073 * Remove the last char placed into the rx buffer. 00074 * This is an operation that can only be performed 00075 * by an rxCallback function. 00076 * @ingroup API 00077 * @return The byte removed from the buffer. 00078 */ 00079 int rxDiscardLastChar(void); 00080 00081 protected: 00082 00083 /** setSerial() 00084 * 00085 * Used internally by MODSERIAL to set the "this" pointer 00086 * of the MODSERIAL that created this object. 00087 * @ingroup INTERNAL 00088 * @param A pointer to a MODSERIAL object instance. 00089 */ 00090 void setSerial(MODSERIAL *s) { serial = s; } 00091 }; 00092 00093 // Forward reference dummy class. 00094 class MODSERIAL_callback_dummy; 00095 00096 /** 00097 * @author Andy Kirkham 00098 * @see http://mbed.org/cookbook/MODSERIAL 00099 * @see example3a.cpp 00100 * @see example3b.cpp 00101 * @see API 00102 * 00103 * <b>MODSERIAL_callback</b> is a class used to hold application callbacks that 00104 * MODSERIAL can invoke on certain events. 00105 */ 00106 class MODSERIAL_callback 00107 { 00108 protected: 00109 00110 //! C callback function pointer. 00111 void (*c_callback)(MODSERIAL_IRQ_INFO *); 00112 00113 //! C++ callback object/method pointer (the object part). 00114 MODSERIAL_callback_dummy *obj_callback; 00115 00116 //! C++ callback object/method pointer (the method part). 00117 void (MODSERIAL_callback_dummy::*method_callback)(MODSERIAL_IRQ_INFO *); 00118 00119 public: 00120 00121 /** Constructor 00122 */ 00123 MODSERIAL_callback() { 00124 c_callback = 0; 00125 obj_callback = 0; 00126 method_callback = 0; 00127 } 00128 00129 /** attach - Overloaded attachment function. 00130 * 00131 * Attach a C type function pointer as the callback. 00132 * 00133 * Note, the callback function prototype must be:- 00134 * @code 00135 * void myCallbackFunction(MODSERIAL_IRQ_INFO *); 00136 * @endcode 00137 * @param A C function pointer to call. 00138 */ 00139 void attach(void (*function)(MODSERIAL_IRQ_INFO *) = 0) { c_callback = function; } 00140 00141 /** attach - Overloaded attachment function. 00142 * 00143 * Attach a C++ type object/method pointer as the callback. 00144 * 00145 * Note, the callback method prototype must be:- 00146 * @code 00147 * public: 00148 * void myCallbackFunction(MODSERIAL_IRQ_INFO *); 00149 * @endcode 00150 * @param A C++ object pointer. 00151 * @param A C++ method within the object to call. 00152 */ 00153 template<class T> 00154 void attach(T* item, void (T::*method)(MODSERIAL_IRQ_INFO *)) { 00155 obj_callback = (MODSERIAL_callback_dummy *)item; 00156 method_callback = (void (MODSERIAL_callback_dummy::*)(MODSERIAL_IRQ_INFO *))method; 00157 } 00158 00159 /** call - Overloaded callback initiator. 00160 * 00161 * call the callback function. 00162 * 00163 * @param A pointer to a MODSERIAL_IRQ_INFO object. 00164 */ 00165 void call(MODSERIAL_IRQ_INFO *arg) { 00166 if (c_callback != 0) { 00167 (*c_callback)(arg); 00168 } 00169 else { 00170 if (obj_callback != 0 && method_callback != 0) { 00171 (obj_callback->*method_callback)(arg); 00172 } 00173 } 00174 } 00175 }; 00176 00177 /** 00178 * @author Andy Kirkham 00179 * @see http://mbed.org/cookbook/MODSERIAL 00180 * @see http://mbed.org/handbook/Serial 00181 * @see example1.cpp 00182 * @see example2.cpp 00183 * @see example3a.cpp 00184 * @see example3b.cpp 00185 * @see example_dma.cpp 00186 * @see API 00187 * 00188 * <b>MODSERIAL</b> extends the Mbed library <a href="/handbook/Serial">Serial</a> to provide fully buffered 00189 * TX and RX streams. Buffer length is fully customisable. 00190 * 00191 * Before using MODSERIAL users should be familar with Mbed's standard <a href="/handbook/Serial">Serial</a> 00192 * library object. MODSERIAL is a direct "drop in" replacement for <a href="/handbook/Serial">Serial</a>. Where 00193 * previously Serial was used, MODSERIAL can be used as adirect replacement instantly offering standard 00194 * TX and RX buffering. By default, both TX and RX buffers are 256 bytes in length. 00195 * 00196 * @image html /media/uploads/mbedofficial/serial_interfaces.png 00197 * 00198 * Standard example: 00199 * @code 00200 * #include "mbed.h" 00201 * #include "MODSERIAL.h" 00202 * 00203 * MODSERIAL pc(USBTX, USBRX); // tx, rx 00204 * 00205 * int main() { 00206 * pc.printf("Hello World!"); 00207 * while(1) { 00208 * pc.putc(pc.getc() + 1); 00209 * } 00210 * } 00211 * @endcode 00212 * 00213 * Example with alternate buffer length: 00214 * @code 00215 * #include "mbed.h" 00216 * #include "MODSERIAL.h" 00217 * 00218 * // Make TX and RX buffers 512byes in length 00219 * MODSERIAL pc(USBTX, USBRX, 512); // tx, rx 00220 * 00221 * int main() { 00222 * pc.printf("Hello World!"); 00223 * while(1) { 00224 * pc.putc(pc.getc() + 1); 00225 * } 00226 * } 00227 * @endcode 00228 * 00229 * Example with alternate buffer length: 00230 * @code 00231 * #include "mbed.h" 00232 * #include "MODSERIAL.h" 00233 * 00234 * // Make TX 1024bytes and RX 512byes in length 00235 * MODSERIAL pc(USBTX, USBRX, 1024, 512); // tx, rx 00236 * 00237 * int main() { 00238 * pc.printf("Hello World!"); 00239 * while(1) { 00240 * pc.putc(pc.getc() + 1); 00241 * } 00242 * } 00243 * @endcode 00244 */ 00245 class MODSERIAL : public Serial 00246 { 00247 public: 00248 00249 // Allow instances of MODSERIAL_IRQ_INFO to use protected properties and methods. 00250 friend class MODSERIAL_IRQ_INFO ; 00251 00252 //! A copy of the Serial parity enum 00253 /** @see http://mbed.org/projects/libraries/api/mbed/trunk/Serial#Serial.format */ 00254 enum Parity { 00255 None = 0 00256 , Odd 00257 , Even 00258 , Forced1 00259 , Forced0 00260 }; 00261 00262 //! A copy of the Serial IrqType enum 00263 enum IrqType { 00264 RxIrq = 0 00265 , TxIrq 00266 , RxOvIrq 00267 , TxOvIrq 00268 , TxEmpty 00269 , RxAutoDetect 00270 , NumOfIrqTypes 00271 }; 00272 00273 //! Non-blocking functions return code. 00274 enum Result { 00275 Ok = 0 /*!< Ok. */ 00276 , NoMemory = -1 /*!< Memory allocation failed. */ 00277 , NoChar = -1 /*!< No character in buffer. */ 00278 , BufferOversize = -2 /*!< Oversized buffer. */ 00279 }; 00280 00281 /** 00282 * The MODSERIAL constructor is used to initialise the serial object. 00283 * 00284 * @param tx PinName of the TX pin. 00285 * @param rx PinName of the TX pin. 00286 */ 00287 MODSERIAL(PinName tx, PinName rx, const char* name = NULL); 00288 00289 /** 00290 * The MODSERIAL constructor is used to initialise the serial object. 00291 * 00292 * @param tx PinName of the TX pin. 00293 * @param rx PinName of the TX pin. 00294 * @param bufferSize Integer of the TX and RX buffer sizes. 00295 */ 00296 MODSERIAL(PinName tx, PinName rx, int bufferSize, const char* name = NULL); 00297 00298 /** 00299 * The MODSERIAL constructor is used to initialise the serial object. 00300 * 00301 * @param tx PinName of the TX pin. 00302 * @param rx PinName of the TX pin. 00303 * @param txBufferSize Integer of the TX buffer sizes. 00304 * @param rxBufferSize Integer of the RX buffer sizes. 00305 */ 00306 MODSERIAL(PinName tx, PinName rx, int txBufferSize, int rxBufferSize, const char* name = NULL); 00307 00308 virtual ~MODSERIAL (); 00309 00310 /** 00311 * Function: attach 00312 * 00313 * The Mbed standard <a href="/handbook/Serial">Serial</a> library object allows an interrupt callback 00314 * to be made when a byte is received by the TX or RX UART hardware. MODSERIAL traps these interrupts 00315 * to enable it's buffering system. However, after the byte has been received/sent under interrupt control, 00316 * MODSERIAL can callback a user function as a notification of the interrupt. Note, user code should not 00317 * directly interact with the Uart hardware, MODSERIAL does that, instead, MODSERIAL API functions should 00318 * be used. 00319 * 00320 * <b>Note</b>, a character is written out then, if there is room in the TX FIFO and the TX buffer is empty, 00321 * putc() will put the character directly into THR (the output holding register). If the TX FIFO is full and 00322 * cannot accept the character, it is placed into the TX output buffer. The TX interrupts are then enabled 00323 * so that when the TX FIFO empties, the TX buffer is then transferred to the THR FIFO. The TxIrq will ONLY 00324 * be activated when this transfer of a character from BUFFER to THR FIFO takes place. If your character 00325 * throughput is not high bandwidth, then the 16 byte TX FIFO may be enough and the TX output buffer may 00326 * never come into play. 00327 * 00328 * @code 00329 * #include "mbed.h" 00330 * #include "MODSERIAL.h" 00331 * 00332 * DigitalOut led1(LED1); 00333 * DigitalOut led2(LED2); 00334 * DigitalOut led3(LED3); 00335 * 00336 * // To test, connect p9 to p10 as a loopback. 00337 * MODSERIAL pc(p9, p10); 00338 * 00339 * // This function is called when a character goes into the TX buffer. 00340 * void txCallback(void) { 00341 * led2 = !led2; 00342 * } 00343 * 00344 * // This function is called when a character goes into the RX buffer. 00345 * void rxCallback(void) { 00346 * led3 = !led3; 00347 * } 00348 * 00349 * int main() { 00350 * pc.baud(115200); 00351 * pc.attach(&txCallback, MODSERIAL::TxIrq); 00352 * pc.attach(&rxCallback, MODSERIAL::RxIrq); 00353 * 00354 * while(1) { 00355 * led1 = !led1; 00356 * wait(0.5); 00357 * pc.putc('A'); 00358 * wait(0.5); 00359 * } 00360 * ] 00361 * @endcode 00362 * 00363 * @ingroup API 00364 * @param fptr A pointer to a void function, or 0 to set as none 00365 * @param type Which serial interrupt to attach the member function to (Seriall::RxIrq for receive, TxIrq for transmit buffer empty) 00366 */ 00367 void attach(void (*fptr)(MODSERIAL_IRQ_INFO *), IrqType type = RxIrq) { _isr[type].attach(fptr); } 00368 00369 /** 00370 * Function: attach 00371 * 00372 * The Mbed standard <a href="/handbook/Serial">Serial</a> library object allows an interrupt callback 00373 * to be made when a byte is received by the TX or RX UART hardware. MODSERIAL traps these interrupts 00374 * to enable it's buffering system. However, after the byte has been received/sent under interrupt control, 00375 * MODSERIAL can callback a user function as a notification of the interrupt. Note, user code should not 00376 * directly interact with the Uart hardware, MODSERIAL does that, instead, MODSERIAL API functions should 00377 * be used. 00378 * 00379 * <b>Note</b>, a character is written out then, if there is room in the TX FIFO and the TX buffer is empty, 00380 * putc() will put the character directly into THR (the output holding register). If the TX FIFO is full and 00381 * cannot accept the character, it is placed into the TX output buffer. The TX interrupts are then enabled 00382 * so that when the TX FIFO empties, the TX buffer is then transferred to the THR FIFO. The TxIrq will ONLY 00383 * be activated when this transfer of a character from BUFFER to THR FIFO takes place. If your character 00384 * throughput is not high bandwidth, then the 16 byte TX FIFO may be enough and the TX output buffer may 00385 * never come into play. 00386 * 00387 * @code 00388 * #include "mbed.h" 00389 * #include "MODSERIAL.h" 00390 * 00391 * DigitalOut led1(LED1); 00392 * DigitalOut led2(LED2); 00393 * DigitalOut led3(LED3); 00394 * 00395 * // To test, connect p9 to p10 as a loopback. 00396 * MODSERIAL pc(p9, p10); 00397 * 00398 * class Foo { 00399 * public: 00400 * // This method is called when a character goes into the TX buffer. 00401 * void txCallback(void) { led2 = !led2; } 00402 * 00403 * // This method is called when a character goes into the RX buffer. 00404 * void rxCallback(void) { led3 = !led3; } 00405 * }; 00406 * 00407 * Foo foo; 00408 * 00409 * int main() { 00410 * pc.baud(115200); 00411 * pc.attach(&foo, &Foo::txCallback, MODSERIAL::TxIrq); 00412 * pc.attach(&foo, &Foo::rxCallback, MODSERIAL::RxIrq); 00413 * 00414 * while(1) { 00415 * led1 = !led1; 00416 * wait(0.5); 00417 * pc.putc('A'); 00418 * wait(0.5); 00419 * } 00420 * ] 00421 * @endcode 00422 * 00423 * @ingroup API 00424 * @param tptr A pointer to the object to call the member function on 00425 * @param mptr A pointer to the member function to be called 00426 * @param type Which serial interrupt to attach the member function to (Seriall::RxIrq for receive, TxIrq for transmit buffer empty) 00427 */ 00428 template<typename T> 00429 void attach(T* tptr, void (T::*mptr)(MODSERIAL_IRQ_INFO *), IrqType type = RxIrq) { 00430 if((mptr != 0) && (tptr != 0)) { 00431 _isr[type].attach(tptr, mptr); 00432 } 00433 } 00434 00435 /** 00436 * @see attach 00437 * @ingroup API 00438 */ 00439 void connect (void (*fptr)(MODSERIAL_IRQ_INFO *), IrqType type = RxIrq) { _isr[RxIrq].attach(fptr); } 00440 00441 /** 00442 * @see attach 00443 * @ingroup API 00444 */ 00445 template<typename T> 00446 void connect (T* tptr, void (T::*mptr)(MODSERIAL_IRQ_INFO *), IrqType type = RxIrq) { 00447 if((mptr != 0) && (tptr != 0)) { 00448 _isr[type].attach(tptr, mptr); 00449 } 00450 } 00451 00452 /** 00453 * Function: writeable 00454 * 00455 * Determine if there is space available to write a byte 00456 * 00457 * @ingroup API 00458 * @return 1 if there is space to write a character, else 0 00459 */ 00460 int writeable() { return txBufferFull() ? 0 : 1; } 00461 00462 /** 00463 * Function: readable 00464 * 00465 * Determine if there is a byte available to read 00466 * 00467 * @ingroup API 00468 * @return 1 if there is a character available to read, else 0 00469 */ 00470 int readable() { return rxBufferEmpty() ? 0 : 1; } 00471 00472 /** 00473 * Function: txBufferSane 00474 * 00475 * Determine if the TX buffer has been initialized. 00476 * 00477 * @ingroup API 00478 * @return true if the buffer is initialized, else false 00479 */ 00480 bool txBufferSane(void) { return buffer[TxIrq] != (char *)NULL ? true : false; } 00481 00482 /** 00483 * Function: rxBufferSane 00484 * 00485 * Determine if the RX buffer has been initialized. 00486 * 00487 * @ingroup API 00488 * @return true if the buffer is initialized, else false 00489 */ 00490 bool rxBufferSane(void) { return buffer[TxIrq] != (char *)NULL ? true : false; } 00491 00492 /** 00493 * Function: txBufferGetCount 00494 * 00495 * Returns how many bytes are in the TX buffer 00496 * 00497 * @ingroup API 00498 * @return The number of bytes in the TX buffer 00499 */ 00500 int txBufferGetCount(void) { return buffer_count[TxIrq]; } 00501 00502 /** 00503 * Function: rxBufferGetCount 00504 * 00505 * Returns how many bytes are in the RX buffer 00506 * 00507 * @ingroup API 00508 * @return The number of bytes in the RX buffer 00509 */ 00510 int rxBufferGetCount(void) { return buffer_count[RxIrq]; } 00511 00512 /** 00513 * Function: txBufferGetSize 00514 * 00515 * Returns the current size of the TX buffer 00516 * 00517 * @ingroup API 00518 * @return The length iof the TX buffer in bytes 00519 */ 00520 int txBufferGetSize(int size) { return buffer_size[TxIrq]; } 00521 00522 /** 00523 * Function: rxBufferGetSize 00524 * 00525 * Returns the current size of the RX buffer 00526 * 00527 * @ingroup API 00528 * @return The length iof the RX buffer in bytes 00529 */ 00530 int rxBufferGetSize(int size) { return buffer_size[RxIrq]; } 00531 00532 /** 00533 * Function: txBufferFull 00534 * 00535 * Is the TX buffer full? 00536 * 00537 * @ingroup API 00538 * @return true if the TX buffer is full, otherwise false 00539 */ 00540 bool txBufferFull(void); 00541 00542 /** 00543 * Function: rxBufferFull 00544 * 00545 * Is the RX buffer full? 00546 * 00547 * @ingroup API 00548 * @return true if the RX buffer is full, otherwise false 00549 */ 00550 bool rxBufferFull(void); 00551 00552 /** 00553 * Function: txBufferEmpty 00554 * 00555 * Is the TX buffer empty? 00556 * 00557 * @ingroup API 00558 * @return true if the TX buffer is empty, otherwise false 00559 */ 00560 bool txBufferEmpty(void); 00561 00562 /** 00563 * Function: rxBufferEmpty 00564 * 00565 * Is the RX buffer empty? 00566 * 00567 * @ingroup API 00568 * @return true if the RX buffer is empty, otherwise false 00569 */ 00570 bool rxBufferEmpty(void); 00571 00572 /** 00573 * Function: txBufferSetSize 00574 * 00575 * Change the TX buffer size. 00576 * 00577 * @see Result 00578 * @ingroup API 00579 * @param size The new TX buffer size in bytes. 00580 * @param m Perform a memory sanity check. Errs the Mbed if memory alloc fails. 00581 * @return Result Ok on success. 00582 */ 00583 int txBufferSetSize(int size, bool m) { return resizeBuffer(size, TxIrq, m); } 00584 00585 /** 00586 * Function: rxBufferSetSize 00587 * 00588 * Change the RX buffer size. 00589 * 00590 * @see Result 00591 * @ingroup API 00592 * @param size The new RX buffer size in bytes. 00593 * @param m Perform a memory sanity check. Errs the Mbed if memory alloc fails. 00594 * @return Result Ok on success. 00595 */ 00596 int rxBufferSetSize(int size, bool m) { return resizeBuffer(size, RxIrq, m); } 00597 00598 /** 00599 * Function: txBufferSetSize 00600 * 00601 * Change the TX buffer size. 00602 * Always performs a memory sanity check, halting the Mbed on failure. 00603 * 00604 * @see Result 00605 * @ingroup API 00606 * @param size The new TX buffer size in bytes. 00607 * @return Result Ok on success. 00608 */ 00609 int txBufferSetSize(int size) { return resizeBuffer(size, TxIrq, true); } 00610 00611 /** 00612 * Function: rxBufferSetSize 00613 * 00614 * Change the RX buffer size. 00615 * Always performs a memory sanity check, halting the Mbed on failure. 00616 * 00617 * @see Result 00618 * @ingroup API 00619 * @param size The new RX buffer size in bytes. 00620 * @return Result Ok on success. 00621 */ 00622 int rxBufferSetSize(int size) { return resizeBuffer(size, RxIrq, true); } 00623 00624 /** 00625 * Function: txBufferFlush 00626 * 00627 * Remove all bytes from the TX buffer. 00628 * @ingroup API 00629 */ 00630 void txBufferFlush(void) { flushBuffer(TxIrq); } 00631 00632 /** 00633 * Function: rxBufferFlush 00634 * 00635 * Remove all bytes from the RX buffer. 00636 * @ingroup API 00637 */ 00638 void rxBufferFlush(void) { flushBuffer(RxIrq); } 00639 00640 /** 00641 * Function: getcNb 00642 * 00643 * Like getc() but is non-blocking. If no bytes are in the RX buffer this 00644 * function returns Result::NoChar (-1) 00645 * 00646 * @ingroup API 00647 * @return A byte from the RX buffer or Result::NoChar (-1) if bufer empty. 00648 */ 00649 int getcNb() { return __getc(false); } 00650 00651 /** 00652 * Function: getc 00653 * 00654 * Overloaded version of Serial::getc() 00655 * 00656 * This function blocks (if the RX buffer is empty the function will wait for a 00657 * character to arrive and then return that character). 00658 * 00659 * @ingroup API 00660 * @return A byte from the RX buffer 00661 */ 00662 int getc() { return __getc(true); } 00663 00664 /** 00665 * Function: txGetLastChar 00666 * 00667 * Rteurn the last byte to pass through the TX interrupt handler. 00668 * 00669 * @ingroup MISC 00670 * @return The byte 00671 */ 00672 char txGetLastChar(void) { return txc; } 00673 00674 /** 00675 * Function: rxGetLastChar 00676 * 00677 * Return the last byte to pass through the RX interrupt handler. 00678 * 00679 * @ingroup MISC 00680 * @return The byte 00681 */ 00682 char rxGetLastChar(void) { return rxc; } 00683 00684 /** 00685 * Function: txIsBusy 00686 * 00687 * If the Uart is still actively sending characters this 00688 * function will return true. 00689 * 00690 * @ingroup API 00691 * @return bool 00692 */ 00693 bool txIsBusy(void); 00694 00695 /** 00696 * Function: autoDetectChar 00697 * 00698 * Set the char that, if seen incoming, invokes the AutoDetectChar callback. 00699 * 00700 * @ingroup API 00701 * @param int c The character to detect. 00702 */ 00703 void autoDetectChar(char c) { auto_detect_char = c; } 00704 00705 /** 00706 * Function: move 00707 * 00708 * Move contents of RX buffer to external buffer. Stops if "end" detected. 00709 * 00710 * @ingroup API 00711 * @param char *s The destination buffer address 00712 * @param int max The maximum number of chars to move. 00713 * @param char end If this char is detected stop moving. 00714 */ 00715 int move(char *s, int max, char end) { 00716 int counter = 0; 00717 char c; 00718 while(readable()) { 00719 c = getc(); 00720 if (c == end) break; 00721 *(s++) = c; 00722 counter++; 00723 if (counter == max) break; 00724 } 00725 return counter; 00726 } 00727 00728 /** 00729 * Function: move (overloaded) 00730 * 00731 * Move contents of RX buffer to external buffer. Stops if auto_detect_char detected. 00732 * 00733 * @ingroup API 00734 * @param int max The maximum number of chars to move. 00735 * @param char *s The destination buffer address 00736 */ 00737 int move(char *s, int max) { 00738 return move(s, max, auto_detect_char); 00739 } 00740 00741 #if 0 // Inhereted from Serial/Stream, for documentation only 00742 /** 00743 * Function: putc 00744 * 00745 * Write a character 00746 * Inhereted from Serial/Stream 00747 * 00748 * @see http://mbed.org/projects/libraries/api/mbed/trunk/Serial#Serial.putc 00749 * @ingroup API 00750 * @param c The character to write to the serial port 00751 */ 00752 int putc(int c); 00753 #endif 00754 00755 #if 0 // Inhereted from Serial/Stream, for documentation only 00756 /** 00757 * Function: printf 00758 * 00759 * Write a formated string 00760 * Inhereted from Serial/Stream 00761 * 00762 * @see http://mbed.org/projects/libraries/api/mbed/trunk/Serial#Serial.printf 00763 * @ingroup API 00764 * @param format A printf-style format string, followed by the variables to use in formating the string. 00765 */ 00766 int printf(const char* format, ...); 00767 #endif 00768 00769 #if 0 // Inhereted from Serial/Stream, for documentation only 00770 /** 00771 * Function: scanf 00772 * 00773 * Read a formated string 00774 * Inhereted from Serial/Stream 00775 * 00776 * @see http://mbed.org/projects/libraries/api/mbed/trunk/Serial#Serial.scanf 00777 * @ingroup API 00778 * @param format - A scanf-style format string, followed by the pointers to variables to store the results. 00779 */ 00780 int scanf(const char* format, ...); 00781 #endif 00782 00783 protected: 00784 /** 00785 * Used to pass information to callbacks. 00786 * @ingroup INTERNALS 00787 */ 00788 MODSERIAL_IRQ_INFO callbackInfo; 00789 00790 /** 00791 * Remove the last char placed into the rx buffer. 00792 * This is an operation that can only be performed 00793 * by an rxCallback function. To protect the buffers 00794 * this function is defined protected so that a 00795 * regular application cannot call it directly. It 00796 * can only be called by the public version within a 00797 * MODSERIAL_IRQ_INFO class. 00798 * @ingroup INTERNALS 00799 * @return The byte removed from the buffer. 00800 */ 00801 int rxDiscardLastChar(void); 00802 00803 private: 00804 00805 /** 00806 * A pointer to the UART peripheral base address being used. 00807 * @ingroup INTERNALS 00808 */ 00809 void *_base; 00810 00811 /** 00812 * The last byte to pass through the TX IRQ handler. 00813 * @ingroup INTERNALS 00814 */ 00815 volatile char txc; 00816 00817 /** 00818 * The last byte to pass through the RX IRQ handler. 00819 * @ingroup INTERNALS 00820 */ 00821 volatile char rxc; 00822 00823 /** 00824 * Pointers to the TX and RX buffers. 00825 * @ingroup INTERNALS 00826 */ 00827 volatile char *buffer[2]; 00828 00829 /** 00830 * Buffer in pointers. 00831 * @ingroup INTERNALS 00832 */ 00833 volatile int buffer_in[2]; 00834 00835 /** 00836 * Buffer out pointers. 00837 * @ingroup INTERNALS 00838 */ 00839 volatile int buffer_out[2]; 00840 00841 /** 00842 * Buffer lengths. 00843 * @ingroup INTERNALS 00844 */ 00845 volatile int buffer_size[2]; 00846 00847 /** 00848 * Buffer content counters. 00849 * @ingroup INTERNALS 00850 */ 00851 volatile int buffer_count[2]; 00852 00853 /** 00854 * Buffer overflow. 00855 * @ingroup INTERNALS 00856 */ 00857 volatile int buffer_overflow[2]; 00858 00859 /** 00860 * Auto-detect character. 00861 * @ingroup INTERNALS 00862 */ 00863 volatile char auto_detect_char; 00864 00865 /** 00866 * Callback system. 00867 * @ingroup INTERNALS 00868 */ 00869 MODSERIAL_callback _isr[NumOfIrqTypes]; 00870 00871 /** 00872 * TX Interrupt Service Routine. 00873 * @ingroup INTERNALS 00874 */ 00875 void isr_tx(bool doCallback); 00876 00877 /** 00878 * TX Interrupt Service Routine stub version. 00879 * @ingroup INTERNALS 00880 */ 00881 void isr_tx(void) { isr_tx(true); } 00882 00883 00884 /** 00885 * RX Interrupt Service Routine. 00886 * @ingroup INTERNALS 00887 */ 00888 void isr_rx(void); 00889 00890 /** 00891 * Disable the interrupts for this Uart. 00892 * @ingroup INTERNALS 00893 */ 00894 void disableIrq(void); 00895 00896 /** 00897 * Enable the interrupts for this Uart. 00898 * @ingroup INTERNALS 00899 */ 00900 void enableIrq(void); 00901 00902 /** 00903 * Get a character from the RX buffer 00904 * @ingroup INTERNALS 00905 * @param bool True to block (wait for input) 00906 * @return A byte from the buffer. 00907 */ 00908 int __getc(bool); 00909 00910 /** 00911 * Put a character from the TX buffer 00912 * @ingroup INTERNALS 00913 * @param bool True to block (wait for space in the TX buffer if full) 00914 * @return 0 on success 00915 */ 00916 int __putc(int c, bool); 00917 00918 /** 00919 * Function: _putc 00920 * Overloaded virtual function. 00921 */ 00922 virtual int _putc(int c) { return __putc(c, true); } 00923 00924 /** 00925 * Function: _getc 00926 * Overloaded virtual function. 00927 */ 00928 virtual int _getc() { return __getc(true); } 00929 00930 /** 00931 * Function: init 00932 * Initialize the MODSERIAL object 00933 * @ingroup INTERNALS 00934 */ 00935 void init(int txSize, int rxSize, PinName rx); 00936 00937 /** 00938 * Function: flushBuffer 00939 * @ingroup INTERNALS 00940 */ 00941 void flushBuffer(IrqType type); 00942 00943 /** 00944 * Function: resizeBuffer 00945 * @ingroup INTERNALS 00946 */ 00947 int resizeBuffer(int size, IrqType type = RxIrq, bool memory_check = true); 00948 00949 /** 00950 * Function: downSizeBuffer 00951 * @ingroup INTERNALS 00952 */ 00953 int downSizeBuffer(int size, IrqType type, bool memory_check); 00954 00955 /** 00956 * Function: upSizeBuffer 00957 * @ingroup INTERNALS 00958 */ 00959 int upSizeBuffer(int size, IrqType type, bool memory_check); 00960 00961 /* 00962 * If MODDMA is available the compile in code to handle sending 00963 * an arbitary char buffer. Note, the parts before teh #ifdef 00964 * are declared so that MODSERIAL can access then even if MODDMA 00965 * isn't avaiable. Since MODDMA.h is only available at this point 00966 * all DMA functionality must be declared inline in the class 00967 * definition. 00968 */ 00969 public: 00970 00971 int dmaSendChannel; 00972 void *moddma_p; 00973 00974 #ifdef MODDMA_H 00975 00976 MODDMA_Config *config; 00977 00978 /** 00979 * Set the "void pointer" moddma_p to be a pointer to a 00980 * MODDMA controller class instance. Used to manage the 00981 * data transfer of DMA configurations. 00982 * 00983 * @ingroup API 00984 * @param p A pointer to "the" instance of MODDMA. 00985 */ 00986 void MODDMA(MODDMA *p) { moddma_p = p; } 00987 00988 /** 00989 * Send a char buffer to the Uarts TX system 00990 * using DMA. This blocks regular library 00991 * sending. 00992 * 00993 * @param buffer A char buffer of bytes to send. 00994 * @param len The length of the buffer to send. 00995 * @param dmaChannel The DMA channel to use, defaults to 7 00996 * @return MODDMA::Status MODDMA::ok if all went ok 00997 */ 00998 int dmaSend(char *buffer, int len, int dmaChannel = 7) 00999 { 01000 if (moddma_p == (void *)NULL) return -2; 01001 class MODDMA *dma = (class MODDMA *)moddma_p; 01002 01003 dmaSendChannel = dmaChannel & 0x7; 01004 01005 uint32_t conn = MODDMA::UART0_Tx; 01006 switch(_uidx) { 01007 case 0: conn = MODDMA::UART0_Tx; break; 01008 case 1: conn = MODDMA::UART1_Tx; break; 01009 case 2: conn = MODDMA::UART2_Tx; break; 01010 case 3: conn = MODDMA::UART3_Tx; break; 01011 } 01012 01013 config = new MODDMA_Config; 01014 config 01015 ->channelNum ( (MODDMA::CHANNELS)(dmaSendChannel & 0x7) ) 01016 ->srcMemAddr ( (uint32_t) buffer ) 01017 ->transferSize ( len ) 01018 ->transferType ( MODDMA::m2p ) 01019 ->dstConn ( conn ) 01020 ->attach_tc ( this, &MODSERIAL::dmaSendCallback ) 01021 ->attach_err ( this, &MODSERIAL::dmaSendCallback ) 01022 ; // config end 01023 01024 // Setup the configuration. 01025 if (dma->Setup(config) == 0) { 01026 return -1; 01027 } 01028 01029 //dma.Enable( MODDMA::Channel_0 ); 01030 dma->Enable( config->channelNum() ); 01031 return MODDMA::Ok ; 01032 } 01033 01034 /** 01035 * Attach a callback to the DMA completion. 01036 * 01037 * @ingroup API 01038 * @param fptr A function pointer to call 01039 * @return this 01040 */ 01041 void attach_dmaSendComplete(void (*fptr)(MODSERIAL_IRQ_INFO *)) { 01042 _isrDmaSendComplete.attach(fptr); 01043 } 01044 01045 /** 01046 * Attach a callback to the DMA completion. 01047 * 01048 * @ingroup API 01049 * @param tptr A template pointer to the calling object 01050 * @param mptr A method pointer within the object to call. 01051 * @return this 01052 */ 01053 template<typename T> 01054 void attach_dmaSendComplete(T* tptr, void (T::*mptr)(MODSERIAL_IRQ_INFO *)) { 01055 if((mptr != NULL) && (tptr != NULL)) { 01056 _isrDmaSendComplete.attach(tptr, mptr); 01057 } 01058 } 01059 01060 MODSERIAL_callback _isrDmaSendComplete; 01061 01062 protected: 01063 /** 01064 * Callback for dmaSend(). 01065 */ 01066 void dmaSendCallback(void) 01067 { 01068 if (moddma_p == (void *)NULL) return; 01069 class MODDMA *dma = (class MODDMA *)moddma_p; 01070 01071 MODDMA_Config *config = dma->getConfig(); 01072 dma->haltAndWaitChannelComplete( (MODDMA::CHANNELS)config->channelNum()); 01073 dma->Disable( (MODDMA::CHANNELS)config->channelNum() ); 01074 if (dma->irqType() == MODDMA::TcIrq) dma->clearTcIrq(); 01075 if (dma->irqType() == MODDMA::ErrIrq) dma->clearErrIrq(); 01076 dmaSendChannel = -1; 01077 _isrDmaSendComplete.call(&this->callbackInfo); 01078 delete(config); 01079 } 01080 01081 #endif // MODDMA_H 01082 01083 }; 01084 01085 }; // namespace AjK ends 01086 01087 using namespace AjK; 01088 01089 #endif
Generated on Tue Jul 12 2022 12:20:34 by 1.7.2