Advertisement
Guest User

Untitled

a guest
Apr 25th, 2015
194
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.10 KB | None | 0 0
  1. //
  2. // LPC1114FN28+MBED software UART test
  3. //
  4. // This is a pure-mbed software UART implementation.
  5. // I tested this with 9600-8n1 configuration on LPC1114FN28/102.
  6. //
  7.  
  8. #include "mbed.h"
  9.  
  10. //
  11. // Timing control parameters
  12. //
  13. // As it is hard to be clock-precise on mbed, timing control parameter
  14. // for bit sampling (for RX) and bit toggling (for TX) is obtained
  15. // experimentally. So it probably needs tweaking with other CPU.
  16. //
  17. // With 9600baud, bitclock is ~104[us/bit].
  18. // However, due to mbed API overhead (overhead by attach_us and interrupt
  19. // routing), I ended up attaching RX/TX function with ~85us delay.
  20. //
  21. // Here, TX bitspace != RX bitspace just to make my logic analyzer happy.
  22. // It samples bits with different timing, and this change was needed to make
  23. // every device (RX/TX on both sides + LA) recognize data as same value. YMMV.
  24. //
  25. #define TX_BITSPACE 86 /* make this + overhead == ~104us */
  26. #define TX_BITSPACE_ONSTART 10 /* big enough to finish attach_us */
  27. #define RX_BITSPACE 82 /* make this + overhead == ~104us */
  28. #define RX_BITSPACE_ONRESET 1000 /* big enough to skip whole transfer */
  29. #define RX_BITSPACE_ONSTART 110 /* big enough to skip START bit */
  30.  
  31. enum { LED_ON = 0, LED_OFF };
  32. enum { IDLE = 1, STOP = 1, START = 0 };
  33.  
  34. DigitalOut led(P1_5);
  35.  
  36. // TX/RX bitclock must be separate as call to attach_us may compete.
  37. Timeout rxclock, txclock;
  38.  
  39. InterruptIn rxint(P1_6);
  40. DigitalOut tx(P1_7);
  41. DigitalIn rx(P1_6);
  42.  
  43. static struct uart_buffer {
  44. uint8_t buffer[16];
  45. uint8_t ri, wi;
  46. uint8_t cc;
  47.  
  48. struct {
  49. bool in_process:1;
  50.  
  51. unsigned int data_len:4;
  52. unsigned int stop_len:2;
  53. unsigned int parity_len:1;
  54.  
  55. bool parity_even:1;
  56. unsigned int parity:1;
  57.  
  58. bool frame_error:1;
  59. bool parity_error:1;
  60. bool overflow_error:1;
  61. } state;
  62. } rb, sb;
  63.  
  64. void send_bit() {
  65. int bit;
  66.  
  67. if (sb.state.data_len) {
  68. sb.state.data_len--;
  69. bit = sb.cc & 0x01;
  70. sb.cc >>= 1;
  71.  
  72. if (sb.state.parity_len) {
  73. sb.state.parity ^= bit;
  74. }
  75. }
  76. else if (sb.state.parity_len) {
  77. sb.state.parity_len--;
  78. bit = sb.state.parity ^ sb.state.parity_even;
  79. }
  80. else if (sb.state.stop_len) {
  81. sb.state.stop_len--;
  82. bit = STOP;
  83. }
  84. else {
  85. if (sb.ri == sb.wi) {
  86. sb.state.in_process = 0;
  87. return;
  88. }
  89. sb.cc = sb.buffer[sb.ri++];
  90. sb.ri = sb.ri < sizeof(sb.buffer) ? sb.ri : 0;
  91. sb.state.data_len = 8;
  92. sb.state.parity_len = 0;
  93. sb.state.stop_len = 1;
  94.  
  95. bit = START;
  96. }
  97.  
  98. tx = bit;
  99. txclock.attach_us(&send_bit, TX_BITSPACE);
  100. }
  101.  
  102. int uart_putc(uint8_t c) {
  103. uint8_t wi = sb.wi++;
  104.  
  105. sb.wi = sb.wi < sizeof(sb.buffer) ? sb.wi : 0;
  106. if (sb.wi == sb.ri) {
  107. sb.wi = wi;
  108. goto buffer_overflow;
  109. }
  110. sb.buffer[wi] = c;
  111.  
  112. if (sb.state.in_process == 0) {
  113. sb.state.in_process = 1;
  114. txclock.attach_us(&send_bit, TX_BITSPACE_ONSTART);
  115. }
  116.  
  117. return 0;
  118. buffer_overflow:
  119. return -1;
  120. }
  121.  
  122. int uart_getc() {
  123. if (rb.ri == rb.wi) {
  124. return -1;
  125. }
  126.  
  127. int c = rb.buffer[rb.ri++];
  128. rb.ri = rb.ri < sizeof(rb.buffer) ? rb.ri : 0;
  129.  
  130. return c;
  131. }
  132.  
  133. void recv_reset() {
  134. rb.state.in_process = 0;
  135. //rxint.enable_irq();
  136. }
  137.  
  138. void recv_bit() {
  139. led = LED_ON;
  140. int bit = rx;
  141. led = LED_OFF;
  142.  
  143. if (rb.state.data_len) {
  144. rb.state.data_len--;
  145. rb.cc >>= 1;
  146. rb.cc |= bit ? 0x80 : 0x00;
  147.  
  148. if (rb.state.parity_len) {
  149. rb.state.parity ^= bit;
  150. }
  151. }
  152. else if (rb.state.parity_len) {
  153. rb.state.parity_len--;
  154. if (bit != (rb.state.parity ^ rb.state.parity_even)) {
  155. goto parity_error;
  156. }
  157. }
  158. else if (rb.state.stop_len) {
  159. rb.state.stop_len--;
  160.  
  161. if (bit != STOP) {
  162. goto frame_error;
  163. }
  164.  
  165. // receive completed
  166. if (rb.state.stop_len == 0) {
  167. uint8_t wi = rb.wi++;
  168.  
  169. // save to buffer
  170. rb.wi = rb.wi < sizeof(rb.buffer) ? rb.wi : 0;
  171. if (rb.wi == rb.ri) {
  172. rb.wi = wi;
  173. goto buffer_overflow;
  174. }
  175. rb.buffer[wi] = rb.cc;
  176.  
  177. // prepare for next event
  178. recv_reset();
  179. return;
  180. }
  181. }
  182.  
  183. rxclock.attach_us(&recv_bit, RX_BITSPACE);
  184. return;
  185.  
  186. buffer_overflow:
  187. rb.state.overflow_error = 1;
  188. rxclock.attach_us(&recv_reset, RX_BITSPACE_ONRESET);
  189. return;
  190.  
  191. parity_error:
  192. rb.state.parity_error = 1;
  193. frame_error:
  194. rb.state.frame_error = 1;
  195. rxclock.attach_us(&recv_reset, RX_BITSPACE_ONRESET);
  196. }
  197.  
  198. void recv_start() {
  199. //rxint.disable_irq();
  200.  
  201. if (rb.state.in_process == 0) {
  202. rb.state.in_process = 1;
  203. rb.state.data_len = 8;
  204. rb.state.parity_len = 0;
  205. rb.state.stop_len = 1;
  206. rxclock.attach_us(&recv_bit, RX_BITSPACE_ONSTART);
  207. }
  208. }
  209.  
  210. void uart_init() {
  211. led = LED_OFF;
  212. tx = IDLE;
  213. rxint.fall(&recv_start);
  214. }
  215.  
  216. int main(void) {
  217. uart_init();
  218.  
  219. for (;;) {
  220. int c = uart_getc();
  221. if (c > 0) {
  222. while (uart_putc(c) < 0);
  223. }
  224. }
  225. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement