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

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