Commit | Line | Data |
---|---|---|
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 */ | |
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 |