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