Naze32 clone with Frysky receiver
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

MODSERIAL.h 32KB

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