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.

serial.c 13KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505
  1. /*
  2. * serial.c
  3. *
  4. * Copyright (c) 2012, 2013, Thomas Buck <xythobuz@me.com>
  5. * All rights reserved.
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following conditions
  9. * are met:
  10. *
  11. * - Redistributions of source code must retain the above copyright notice,
  12. * this list of conditions and the following disclaimer.
  13. *
  14. * - Redistributions in binary form must reproduce the above copyright
  15. * notice, this list of conditions and the following disclaimer in the
  16. * documentation and/or other materials provided with the distribution.
  17. *
  18. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  19. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
  20. * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  21. * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
  22. * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  23. * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  24. * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  25. * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  26. * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  27. * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  28. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  29. */
  30. #include <avr/io.h>
  31. #include <avr/interrupt.h>
  32. #include <stdint.h>
  33. #include "serial.h"
  34. #include "serial_device.h"
  35. /** \addtogroup uart UART Library
  36. * UART Library enabling you to control all available
  37. * UART Modules. With XON/XOFF Flow Control and buffered
  38. * Receiving and Transmitting.
  39. * @{
  40. */
  41. /** \file serial.c
  42. * UART Library Implementation
  43. */
  44. /** If you define this, a '\\r' (CR) will be put in front of a '\\n' (LF) when sending a byte.
  45. * Binary Communication will then be impossible!
  46. */
  47. // #define SERIALINJECTCR
  48. #ifndef RX_BUFFER_SIZE
  49. #define RX_BUFFER_SIZE 16 /**< RX Buffer Size in Bytes (Power of 2) */
  50. #endif
  51. #ifndef TX_BUFFER_SIZE
  52. #define TX_BUFFER_SIZE 128 /**< TX Buffer Size in Bytes (Power of 2) */
  53. #endif
  54. /** Defining this enables incoming XON XOFF (sends XOFF if rx buff is full) */
  55. //#define FLOWCONTROL
  56. #define FLOWMARK 5 /**< Space remaining to trigger xoff/xon */
  57. #define XON 0x11 /**< XON Value */
  58. #define XOFF 0x13 /**< XOFF Value */
  59. #if (RX_BUFFER_SIZE < 2) || (TX_BUFFER_SIZE < 2)
  60. #error SERIAL BUFFER TOO SMALL!
  61. #endif
  62. #ifdef FLOWCONTROL
  63. #if (RX_BUFFER_SIZE < 8) || (TX_BUFFER_SIZE < 8)
  64. #error SERIAL BUFFER TOO SMALL!
  65. #endif
  66. #endif
  67. #if ((RX_BUFFER_SIZE + TX_BUFFER_SIZE) * UART_COUNT) >= (RAMEND - 0x60)
  68. #error SERIAL BUFFER TOO LARGE!
  69. #endif
  70. // serialRegisters
  71. #define SERIALDATA 0
  72. #define SERIALB 1
  73. #define SERIALC 2
  74. #define SERIALA 3
  75. #define SERIALUBRRH 4
  76. #define SERIALUBRRL 5
  77. // serialBits
  78. #define SERIALUCSZ0 0
  79. #define SERIALUCSZ1 1
  80. #define SERIALRXCIE 2
  81. #define SERIALRXEN 3
  82. #define SERIALTXEN 4
  83. #define SERIALUDRIE 5
  84. #define SERIALUDRE 6
  85. uint8_t volatile rxBuffer[UART_COUNT][RX_BUFFER_SIZE];
  86. uint8_t volatile txBuffer[UART_COUNT][TX_BUFFER_SIZE];
  87. uint16_t volatile rxRead[UART_COUNT];
  88. uint16_t volatile rxWrite[UART_COUNT];
  89. uint16_t volatile txRead[UART_COUNT];
  90. uint16_t volatile txWrite[UART_COUNT];
  91. uint8_t volatile shouldStartTransmission[UART_COUNT];
  92. #ifdef FLOWCONTROL
  93. uint8_t volatile sendThisNext[UART_COUNT];
  94. uint8_t volatile flow[UART_COUNT];
  95. uint8_t volatile rxBufferElements[UART_COUNT];
  96. #endif
  97. uint8_t serialAvailable(void) {
  98. return UART_COUNT;
  99. }
  100. void serialInit(uint8_t uart, uint16_t baud) {
  101. if (uart >= UART_COUNT)
  102. return;
  103. // Initialize state variables
  104. rxRead[uart] = 0;
  105. rxWrite[uart] = 0;
  106. txRead[uart] = 0;
  107. txWrite[uart] = 0;
  108. shouldStartTransmission[uart] = 1;
  109. #ifdef FLOWCONTROL
  110. sendThisNext[uart] = 0;
  111. flow[uart] = 1;
  112. rxBufferElements[uart] = 0;
  113. #endif
  114. // Default Configuration: 8N1
  115. *serialRegisters[uart][SERIALC] = (1 << serialBits[uart][SERIALUCSZ0]) | (1 << serialBits[uart][SERIALUCSZ1]);
  116. // Set baudrate
  117. #if SERIALBAUDBIT == 8
  118. *serialRegisters[uart][SERIALUBRRH] = (baud >> 8);
  119. *serialRegisters[uart][SERIALUBRRL] = baud;
  120. #else
  121. *serialBaudRegisters[uart] = baud;
  122. #endif
  123. *serialRegisters[uart][SERIALB] = (1 << serialBits[uart][SERIALRXCIE]); // Enable Interrupts
  124. *serialRegisters[uart][SERIALB] |= (1 << serialBits[uart][SERIALRXEN]) | (1 << serialBits[uart][SERIALTXEN]); // Enable Receiver/Transmitter
  125. }
  126. void serialClose(uint8_t uart) {
  127. if (uart >= UART_COUNT)
  128. return;
  129. uint8_t sreg = SREG;
  130. sei();
  131. while (!serialTxBufferEmpty(uart));
  132. while (*serialRegisters[uart][SERIALB] & (1 << serialBits[uart][SERIALUDRIE])); // Wait while Transmit Interrupt is on
  133. cli();
  134. *serialRegisters[uart][SERIALB] = 0;
  135. *serialRegisters[uart][SERIALC] = 0;
  136. SREG = sreg;
  137. }
  138. #ifdef FLOWCONTROL
  139. void setFlow(uint8_t uart, uint8_t on) {
  140. if (uart >= UART_COUNT)
  141. return;
  142. if (flow[uart] != on) {
  143. if (on == 1) {
  144. // Send XON
  145. while (sendThisNext[uart] != 0);
  146. sendThisNext[uart] = XON;
  147. flow[uart] = 1;
  148. if (shouldStartTransmission[uart]) {
  149. shouldStartTransmission[uart] = 0;
  150. *serialRegisters[uart][SERIALB] |= (1 << serialBits[uart][SERIALUDRIE]);
  151. *serialRegisters[uart][SERIALA] |= (1 << serialBits[uart][SERIALUDRE]); // Trigger Interrupt
  152. }
  153. } else {
  154. // Send XOFF
  155. sendThisNext[uart] = XOFF;
  156. flow[uart] = 0;
  157. if (shouldStartTransmission[uart]) {
  158. shouldStartTransmission[uart] = 0;
  159. *serialRegisters[uart][SERIALB] |= (1 << serialBits[uart][SERIALUDRIE]);
  160. *serialRegisters[uart][SERIALA] |= (1 << serialBits[uart][SERIALUDRE]); // Trigger Interrupt
  161. }
  162. }
  163. // Wait till it's transmitted
  164. while (*serialRegisters[uart][SERIALB] & (1 << serialBits[uart][SERIALUDRIE]));
  165. }
  166. }
  167. #endif
  168. // ---------------------
  169. // | Reception |
  170. // ---------------------
  171. uint8_t serialHasChar(uint8_t uart) {
  172. if (uart >= UART_COUNT)
  173. return 0;
  174. if (rxRead[uart] != rxWrite[uart]) { // True if char available
  175. return 1;
  176. } else {
  177. return 0;
  178. }
  179. }
  180. uint8_t serialGetBlocking(uint8_t uart) {
  181. if (uart >= UART_COUNT)
  182. return 0;
  183. while(!serialHasChar(uart));
  184. return serialGet(uart);
  185. }
  186. uint8_t serialGet(uint8_t uart) {
  187. if (uart >= UART_COUNT)
  188. return 0;
  189. uint8_t c;
  190. #ifdef FLOWCONTROL
  191. rxBufferElements[uart]--;
  192. if ((flow[uart] == 0) && (rxBufferElements[uart] <= FLOWMARK)) {
  193. while (sendThisNext[uart] != 0);
  194. sendThisNext[uart] = XON;
  195. flow[uart] = 1;
  196. if (shouldStartTransmission[uart]) {
  197. shouldStartTransmission[uart] = 0;
  198. *serialRegisters[uart][SERIALB] |= (1 << serialBits[uart][SERIALUDRIE]); // Enable Interrupt
  199. *serialRegisters[uart][SERIALA] |= (1 << serialBits[uart][SERIALUDRE]); // Trigger Interrupt
  200. }
  201. }
  202. #endif
  203. if (rxRead[uart] != rxWrite[uart]) {
  204. c = rxBuffer[uart][rxRead[uart]];
  205. rxBuffer[uart][rxRead[uart]] = 0;
  206. if (rxRead[uart] < (RX_BUFFER_SIZE - 1)) {
  207. rxRead[uart]++;
  208. } else {
  209. rxRead[uart] = 0;
  210. }
  211. return c;
  212. } else {
  213. return 0;
  214. }
  215. }
  216. uint8_t serialRxBufferFull(uint8_t uart) {
  217. if (uart >= UART_COUNT)
  218. return 0;
  219. return (((rxWrite[uart] + 1) == rxRead[uart]) || ((rxRead[uart] == 0) && ((rxWrite[uart] + 1) == RX_BUFFER_SIZE)));
  220. }
  221. uint8_t serialRxBufferEmpty(uint8_t uart) {
  222. if (uart >= UART_COUNT)
  223. return 0;
  224. if (rxRead[uart] != rxWrite[uart]) {
  225. return 0;
  226. } else {
  227. return 1;
  228. }
  229. }
  230. // ----------------------
  231. // | Transmission |
  232. // ----------------------
  233. void serialWrite(uint8_t uart, uint8_t data) {
  234. if (uart >= UART_COUNT)
  235. return;
  236. #ifdef SERIALINJECTCR
  237. if (data == '\n') {
  238. serialWrite(uart, '\r');
  239. }
  240. #endif
  241. while (serialTxBufferFull(uart));
  242. txBuffer[uart][txWrite[uart]] = data;
  243. if (txWrite[uart] < (TX_BUFFER_SIZE - 1)) {
  244. txWrite[uart]++;
  245. } else {
  246. txWrite[uart] = 0;
  247. }
  248. if (shouldStartTransmission[uart]) {
  249. shouldStartTransmission[uart] = 0;
  250. *serialRegisters[uart][SERIALB] |= (1 << serialBits[uart][SERIALUDRIE]); // Enable Interrupt
  251. *serialRegisters[uart][SERIALA] |= (1 << serialBits[uart][SERIALUDRE]); // Trigger Interrupt
  252. }
  253. }
  254. void serialWriteString(uint8_t uart, const char *data) {
  255. if (uart >= UART_COUNT)
  256. return;
  257. if (data == 0) {
  258. serialWriteString(uart, "NULL");
  259. } else {
  260. while (*data != '\0') {
  261. serialWrite(uart, *data++);
  262. }
  263. }
  264. }
  265. void serialWriteHex(uint8_t uart, uint8_t value) {
  266. char buff[3] = { 0, 0, '\0' };
  267. if (value >= 16) {
  268. buff[0] = value / 16;
  269. value = value % 16;
  270. }
  271. buff[1] = value;
  272. if ((buff[0] >= 0) && (buff[0] <= 9)) {
  273. buff[0] += '0';
  274. } else {
  275. buff[0] -= 10;
  276. buff[0] += 'A';
  277. }
  278. if ((buff[1] >= 0) && (buff[1] <= 9)) {
  279. buff[1] += '0';
  280. } else {
  281. buff[1] -= 10;
  282. buff[1] += 'A';
  283. }
  284. serialWriteString(uart, buff);
  285. }
  286. void serialWriteUnsigned8(uint8_t uart, uint8_t value) {
  287. char buff[4] = { '0', '0', '0', '\0' };
  288. uint8_t pos = sizeof(buff) - 2;
  289. while (value > 0) {
  290. buff[pos--] = '0' + (value % 10);
  291. value /= 10;
  292. }
  293. uint8_t start = 0;
  294. while ((start < (sizeof(buff) - 2)) && (buff[start] == '0')) {
  295. start++;
  296. }
  297. serialWriteString(uart, buff + start);
  298. }
  299. void serialWriteUnsigned16(uint8_t uart, uint16_t value) {
  300. char buff[6] = { '0', '0', '0', '0', '0', '\0' };
  301. uint8_t pos = sizeof(buff) - 2;
  302. while (value > 0) {
  303. buff[pos--] = '0' + (value % 10);
  304. value /= 10;
  305. }
  306. uint8_t start = 0;
  307. while ((start < (sizeof(buff) - 2)) && (buff[start] == '0')) {
  308. start++;
  309. }
  310. serialWriteString(uart, buff + start);
  311. }
  312. void serialWriteUnsigned32(uint8_t uart, uint32_t value) {
  313. char buff[11] = { '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '\0' };
  314. uint8_t pos = sizeof(buff) - 2;
  315. while (value > 0) {
  316. buff[pos--] = '0' + (value % 10);
  317. value /= 10;
  318. }
  319. uint8_t start = 0;
  320. while ((start < (sizeof(buff) - 2)) && (buff[start] == '0')) {
  321. start++;
  322. }
  323. serialWriteString(uart, buff + start);
  324. }
  325. void serialWriteUnsigned64(uint8_t uart, uint64_t value) {
  326. char buff[21] = { '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
  327. '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '\0' };
  328. uint8_t pos = sizeof(buff) - 2;
  329. while (value > 0) {
  330. buff[pos--] = '0' + (value % 10);
  331. value /= 10;
  332. }
  333. uint8_t start = 0;
  334. while ((start < (sizeof(buff) - 2)) && (buff[start] == '0')) {
  335. start++;
  336. }
  337. serialWriteString(uart, buff + start);
  338. }
  339. uint8_t serialTxBufferFull(uint8_t uart) {
  340. if (uart >= UART_COUNT)
  341. return 0;
  342. return (((txWrite[uart] + 1) == txRead[uart]) || ((txRead[uart] == 0) && ((txWrite[uart] + 1) == TX_BUFFER_SIZE)));
  343. }
  344. uint8_t serialTxBufferEmpty(uint8_t uart) {
  345. if (uart >= UART_COUNT)
  346. return 0;
  347. if (txRead[uart] != txWrite[uart]) {
  348. return 0;
  349. } else {
  350. return 1;
  351. }
  352. }
  353. void serialReceiveInterrupt(uint8_t uart) {
  354. rxBuffer[uart][rxWrite[uart]] = *serialRegisters[uart][SERIALDATA];
  355. if (rxWrite[uart] < (RX_BUFFER_SIZE - 1)) {
  356. rxWrite[uart]++;
  357. } else {
  358. rxWrite[uart] = 0;
  359. }
  360. #ifdef FLOWCONTROL
  361. rxBufferElements[uart]++;
  362. if ((flow[uart] == 1) && (rxBufferElements[uart] >= (RX_BUFFER_SIZE - FLOWMARK))) {
  363. sendThisNext[uart] = XOFF;
  364. flow[uart] = 0;
  365. if (shouldStartTransmission[uart]) {
  366. shouldStartTransmission[uart] = 0;
  367. *serialRegisters[uart][SERIALB] |= (1 << serialBits[uart][SERIALUDRIE]); // Enable Interrupt
  368. *serialRegisters[uart][SERIALA] |= (1 << serialBits[uart][SERIALUDRE]); // Trigger Interrupt
  369. }
  370. }
  371. #endif
  372. }
  373. void serialTransmitInterrupt(uint8_t uart) {
  374. #ifdef FLOWCONTROL
  375. if (sendThisNext[uart]) {
  376. *serialRegisters[uart][SERIALDATA] = sendThisNext[uart];
  377. sendThisNext[uart] = 0;
  378. } else {
  379. #endif
  380. if (txRead[uart] != txWrite[uart]) {
  381. *serialRegisters[uart][SERIALDATA] = txBuffer[uart][txRead[uart]];
  382. if (txRead[uart] < (TX_BUFFER_SIZE -1)) {
  383. txRead[uart]++;
  384. } else {
  385. txRead[uart] = 0;
  386. }
  387. } else {
  388. shouldStartTransmission[uart] = 1;
  389. *serialRegisters[uart][SERIALB] &= ~(1 << serialBits[uart][SERIALUDRIE]); // Disable Interrupt
  390. }
  391. #ifdef FLOWCONTROL
  392. }
  393. #endif
  394. }
  395. ISR(SERIALRECIEVEINTERRUPT) { // Receive complete
  396. serialReceiveInterrupt(0);
  397. }
  398. ISR(SERIALTRANSMITINTERRUPT) { // Data register empty
  399. serialTransmitInterrupt(0);
  400. }
  401. #if UART_COUNT > 1
  402. ISR(SERIALRECIEVEINTERRUPT1) { // Receive complete
  403. serialReceiveInterrupt(1);
  404. }
  405. ISR(SERIALTRANSMITINTERRUPT1) { // Data register empty
  406. serialTransmitInterrupt(1);
  407. }
  408. #endif
  409. #if UART_COUNT > 2
  410. ISR(SERIALRECIEVEINTERRUPT2) { // Receive complete
  411. serialReceiveInterrupt(2);
  412. }
  413. ISR(SERIALTRANSMITINTERRUPT2) { // Data register empty
  414. serialTransmitInterrupt(2);
  415. }
  416. #endif
  417. #if UART_COUNT > 3
  418. ISR(SERIALRECIEVEINTERRUPT3) { // Receive complete
  419. serialReceiveInterrupt(3);
  420. }
  421. ISR(SERIALTRANSMITINTERRUPT3) { // Data register empty
  422. serialTransmitInterrupt(3);
  423. }
  424. #endif
  425. /** @} */