Initial import of goggles v2
[goggles] / serial.c
CommitLineData
5fc23db2
JM
1/***
2 *** Serial Port driver for 16f1455 and kin
3 ***/
4
5#include "user.h"
6#include <stdint.h>
7#include <stdbool.h>
8
9/* outgoing text buffer */
10char outbuff[3];
11char * outp = 0;
12uint8_t outlen = 0;
13
14/* incoming text buffer */
15char inbuff[1];
16uint8_t inlen = 0;
17
18
19void serial_init(void)
20{
21 /* Enabling transmitter 26.1.1.1 page 259 - TX/CK I/O pin */
22 TXSTAbits.TXEN = 1;
23 TXSTAbits.SYNC = 0;
24 RCSTAbits.SPEN = 1;
25 /* Enabling receiver 26.1.2 page 262 - RX/DT I/O pin */
26 RCSTAbits.CREN = 1;
27
28 /* Switch serial port to alternate pins */
29 APFCON0bits.RXDTSEL = 1;
30 APFCON0bits.TXCKSEL = 1;
31
32 ANSELAbits.ANSA4 = 0;
33
34 /* Select pins 4&5 as the uart - page 102 */
35 TRISAbits.TRISA4 = 0; /* RA4 as TX output */
36 TRISAbits.TRISA5 = 1; /* RA5 as RX input */
37
38#if _XTAL_FREQ != 32000000L
39#error "Adjust serial port baudrate settings"
40#endif
41
42 /* assume 32MHz clock, 19k2 baud */
43 TXSTAbits.BRGH = 0;
44 BAUDCONbits.BRG16 = 1;
45 SPBRGL = 103;
46
47 /* Enable interrupts */
48 INTCONbits.GIE = 1;
49 INTCONbits.PEIE = 1;
50
51 /* enable uart receiver interupt */
52 PIE1bits.RCIE = 1;
53}
54
55
56/* is the queue empty yet */
57bool msg_empty(void)
58{
59 if (outp == 0) return 1;
60 return 0;
61}
62
63/* new message in the queue */
64void msg_write(const char *msg)
65{
66 char * p = outbuff + outlen;
67 while (outlen < sizeof(outbuff) && *msg != 0) {
68 *(p++) = *(msg++);
69 outlen++;
70 }
71 *p = 0;
72 if (outp == 0) {
73 outp = outbuff;
74 PIE1bits.TXIE = 1;
75 }
76}
77
78void msg_writebyte(const char msg)
79{
80 if (outlen+1 >= (uint8_t)sizeof(outbuff)) return;
81 outbuff[outlen++] = msg;
82 outbuff[outlen] = 0;
83 if (outp == 0) {
84 outp = outbuff;
85 PIE1bits.TXIE = 1;
86 }
87}
88
89/* some library functions will use this if defined, eg printf */
90void putch(char data)
91{
92 msg_writebyte(data);
93}
94
95/* called from interrupt routine to send next char */
96void msg_sendnext(void)
97{
98 /* we have finished, turn off the iterrupt */
99 if (outp == 0 || *outp == 0) {
100 PIE1bits.TXIE = 0;
101 outp = 0;
102 outlen = 0;
103 return;
104 }
105 TXREG = *outp;
106 outp++;
107}
108
109/* called from interrupt routine to receive next byte */
110void msg_recvnext(void)
111{
112 while (PIR1bits.RCIF) {
113 /* bad char, skip it */
114 if (RCSTAbits.FERR) {
115 RCREG==0?0:0; // discard by reading
116 continue;
117 }
118
119 /* our input buffer has overflowed */
120 if (inlen > sizeof(inbuff)) {
121 RCREG==0?0:0; // discard by reading
122 return;
123 }
124
125 /* keep this one */
126 inbuff[inlen++] = RCREG;
127 }
128}
129
130/* is there text waiting to be read */
131bool msg_recvready(void)
132{
133 if (inlen > 0) return 1;
134 return 0;
135}
136
137/* read next byte from inpout buffer */
138char msg_recv(void)
139{
140 if (inlen == 0) return 0;
141
142 /* record and disable the interupt */
143 bool in = PIE1bits.RCIE;
144 PIE1bits.RCIE = 0;
145
146 char new = inbuff[0];
147 inlen--;
148
149 /* shuffle them down one */
150 for (char i=0;i<inlen;i++)
151 inbuff[i] = inbuff[i+1];
152
153 /* restore the interupt */
154 PIE1bits.RCIE = in;
155 return new;
156}
157
158inline void msg_flush(void)
159{
160 while (!msg_empty());
161}