Initial import of onewire-to-usb bridge
[onewire] / serial.c
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 */
13 char outbuff[100];
14 char * outp = 0;
15 uint8_t outlen = 0;
16
17 /* incoming text buffer */
18 char inbuff[10];
19 uint8_t inlen = 0;
20
21
22 void 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 */
58 bool msg_empty(void)
59 {
60     if (outp == 0) return 1;
61     return 0;
62 }
63
64 /* new message in the queue */
65 void 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
79 void 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
90 void putch(char data)
91 {
92     msg_writebyte(data);
93 }
94
95 /* called from interrupt routine to send next char */
96 void 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 */
110 void 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
127 bool msg_recvready(void)
128 {
129     if (inlen > 0) return 1;
130     return 0;
131 }
132
133 char 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