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.
 
 
 
 

157 lines
2.8 KiB

  1. #include <pic.h>
  2. #include "config.h"
  3. #include "serial.h"
  4. volatile uint8_t stq[STQ_SIZE], stq_start, stq_len;
  5. volatile uint8_t bank1 srq[SRQ_SIZE], srq_start, srq_len;
  6. /*
  7. * Initialization
  8. */
  9. void serial_init(void)
  10. {
  11. /* Set up serial transmit queue and serial receive queue */
  12. stq_start = stq_len = 0;
  13. srq_start = srq_len = 0;
  14. /* Initialize serial port with baudrate specified in config.h */
  15. TRISRX = 1;
  16. TRISTX = 1;
  17. BRGH = 1;
  18. #define BRG (((FOSC + (8 * BAUDRATE - 1)) /(16 * BAUDRATE)) - 1)
  19. #if (BRG < 1) || (BRG > 255)
  20. #error Cannot achieve baudrate
  21. #endif
  22. #define ACT_BR (FOSC / (16 * (BRG + 1)))
  23. #if ((ACT_BR * 100 / BAUDRATE) > 105) || ((ACT_BR * 100 / BAUDRATE) < 94)
  24. #error Actual baudrate is too far from requested baudrate. Ratio is
  25. #error FOSC/(16*floor((FOSC+(8*BAUDRATE-1))/(16*BAUDRATE)))/BAUDRATE
  26. #endif
  27. SPBRG = BRG;
  28. SYNC = 0;
  29. SPEN = 1;
  30. CREN = 1;
  31. SREN = 0;
  32. TX9 = 0;
  33. RX9 = 0;
  34. TXEN = 1;
  35. /* Enable serial port interrupts. To avoid being interrupted
  36. all the time, TXIE is kept off until we have data to
  37. transmit. */
  38. TXIE = 0;
  39. RCIE = 1;
  40. PEIE = 1;
  41. }
  42. /*
  43. * Interrupt handling
  44. */
  45. /* Get a byte from the transmit queue and send it */
  46. void serial_interrupt_tx(void)
  47. {
  48. if(stq_len != 0) {
  49. TXREG = stq[stq_start];
  50. stq_start = (stq_start + 1) & STQ_MASK;
  51. stq_len--;
  52. }
  53. /* If queue is empty, disable interrupt */
  54. if(stq_len == 0)
  55. TXIE = 0;
  56. }
  57. /* Receive a byte and write it to the receive queue. */
  58. void serial_interrupt_rx(void)
  59. {
  60. if(FERR) {
  61. /* Framing error: discard byte */
  62. (void) RCREG;
  63. return;
  64. }
  65. if(OERR) {
  66. /* Overflow error, clear it */
  67. CREN = 0;
  68. CREN = 1;
  69. return;
  70. }
  71. if(!(srq_len & SRQ_SIZE)) {
  72. srq[(srq_start + srq_len) & SRQ_MASK] = RCREG;
  73. srq_len++;
  74. } else {
  75. /* Queue is full; discard data */
  76. (void) RCREG;
  77. }
  78. }
  79. /*
  80. * Userspace interface
  81. */
  82. /* Send byte to PC. Blocks iff transmit queue is full. */
  83. void serial_put(uint8_t x)
  84. {
  85. while(!serial_can_put())
  86. continue;
  87. GIE = 0;
  88. stq[(stq_start + stq_len) & STQ_MASK] = x;
  89. stq_len++;
  90. TXIE = 1;
  91. GIE = 1;
  92. }
  93. /* Get byte from PC. Blocks iff receive queue is empty. */
  94. uint8_t serial_get(void)
  95. {
  96. uint8_t x;
  97. while(!serial_can_get())
  98. continue;
  99. x = srq[srq_start];
  100. GIE = 0;
  101. srq_start = (srq_start + 1) & SRQ_MASK;
  102. srq_len--;
  103. GIE = 1;
  104. return x;
  105. }
  106. /*
  107. * I/O helpers
  108. */
  109. void serial_put_string(const uint8_t *s)
  110. {
  111. while(s && *s)
  112. serial_put(*s++);
  113. }
  114. const uint8_t hex[16]={'0','1','2','3','4','5','6','7',
  115. '8','9','a','b','c','d','e','f'};
  116. void serial_put_hex(uint8_t x)
  117. {
  118. serial_put(hex[x >> 4]);
  119. serial_put(hex[x & 15]);
  120. }
  121. void serial_put_hex32(uint32_t x)
  122. {
  123. serial_put_hex((x >> 24) & 0xFF);
  124. serial_put_hex((x >> 16) & 0xFF);
  125. serial_put_hex((x >> 8) & 0xFF);
  126. serial_put_hex((x) & 0xFF);
  127. }
  128. void serial_crlf(void)
  129. {
  130. serial_put('\r');
  131. serial_put('\n');
  132. }