Initial import of onewire-to-usb bridge
[onewire] / serial.c
CommitLineData
bba33fe1
JM
1/***
2 *** Serial Port driver for 12f1840 and kin
3 ***/
4
5#include "user.h"
6#include "system.h"
7
8#include <stdint.h>
9#include <stdbool.h>
10
11
12/* outgoing text buffer */
13char outbuff[100];
14char * outp = 0;
15uint8_t outlen = 0;
16
17/* incoming text buffer */
18char inbuff[10];
19uint8_t inlen = 0;
20
21
22void serial_init(void)
23{
24 /* Enabling transmitter 26.1.1.1 page 259 - TX/CK I/O pin */
25 TXSTAbits.TXEN = 1;
26 TXSTAbits.SYNC = 0;
27 RCSTAbits.SPEN = 1;
28 /* Enabling receiver 26.1.2 page 262 - RX/DT I/O pin */
29 RCSTAbits.CREN = 1;
30
31 /* Select pins 4&5 as the uart - page 102 */
32 APFCONbits.RXDTSEL = 1; /* RX/DT on RA5 */
33 APFCONbits.TXCKSEL = 1; /* TX/CK on RA4 */
34 TRISAbits.TRISA5 = 1; /* RA5 as input */
35 TRISAbits.TRISA4 = 0; /* RA4 as output */
36
37 ANSELAbits.ANSA4 = 0; /* no analog */
38
39#if _XTAL_FREQ != 4000000L
40#error "Adjust serial port baudrate settings"
41#endif
42
43 /* assume 4MHz clock, 19k2 baud */
44 TXSTAbits.BRGH = 0;
45 BAUDCONbits.BRG16 = 1;
46 SPBRG = 12;
47
48 /* Enable interrupts */
49 INTCONbits.GIE = 1;
50 INTCONbits.PEIE = 1;
51
52 /* enable uart receiver interupt */
53 PIE1bits.RCIE = 1;
54}
55
56
57/* is the queue empty yet */
58bool msg_empty(void)
59{
60 if (outp == 0) return 1;
61 return 0;
62}
63
64/* new message in the queue */
65void msg_write(const char *msg)
66{
67 char * p = outbuff + outlen;
68 while (outlen < sizeof(outbuff) && *msg != 0) {
69 *(p++) = *(msg++);
70 outlen++;
71 }
72 *p = 0;
73 if (outp == 0) {
74 outp = outbuff;
75 PIE1bits.TXIE = 1;
76 }
77}
78
79void msg_writebyte(const char msg)
80{
81 if (outlen+1 >= (uint8_t)sizeof(outbuff)) return;
82 outbuff[outlen++] = msg;
83 outbuff[outlen] = 0;
84 if (outp == 0) {
85 outp = outbuff;
86 PIE1bits.TXIE = 1;
87 }
88}
89
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 bool err = RCSTAbits.FERR;
114 char new = RCREG;
115
116 /* bad char, skip it */
117 if (err) continue;
118
119 /* our input buffer has overflowed */
120 if (inlen > sizeof(inbuff)) return;
121
122 /* keep this one */
123 inbuff[inlen++] = new;
124 }
125}
126
127bool msg_recvready(void)
128{
129 if (inlen > 0) return 1;
130 return 0;
131}
132
133char msg_recv(void)
134{
135 if (inlen == 0) return 0;
136
137 /* record and disable the interupt */
138 bool in = PIE1bits.RCIE;
139 PIE1bits.RCIE = 0;
140
141 char new = inbuff[0];
142 inlen--;
143
144 /* shuffle them down one */
145 for (char i=0;i<inlen;i++)
146 inbuff[i] = inbuff[i+1];
147
148 /* restore the interupt */
149 PIE1bits.RCIE = in;
150 return new;
151}
152
153