/*** *** Serial Port driver for 12f1840 and kin ***/ #include "user.h" #include "system.h" #include #include /* outgoing text buffer */ char outbuff[100]; char * outp = 0; uint8_t outlen = 0; /* incoming text buffer */ char inbuff[10]; uint8_t inlen = 0; void serial_init(void) { /* Enabling transmitter 26.1.1.1 page 259 - TX/CK I/O pin */ TXSTAbits.TXEN = 1; TXSTAbits.SYNC = 0; RCSTAbits.SPEN = 1; /* Enabling receiver 26.1.2 page 262 - RX/DT I/O pin */ RCSTAbits.CREN = 1; /* Select pins 4&5 as the uart - page 102 */ APFCONbits.RXDTSEL = 1; /* RX/DT on RA5 */ APFCONbits.TXCKSEL = 1; /* TX/CK on RA4 */ TRISAbits.TRISA5 = 1; /* RA5 as input */ TRISAbits.TRISA4 = 0; /* RA4 as output */ ANSELAbits.ANSA4 = 0; /* no analog */ #if _XTAL_FREQ != 4000000L #error "Adjust serial port baudrate settings" #endif /* assume 4MHz clock, 19k2 baud */ TXSTAbits.BRGH = 0; BAUDCONbits.BRG16 = 1; SPBRG = 12; /* Enable interrupts */ INTCONbits.GIE = 1; INTCONbits.PEIE = 1; /* enable uart receiver interupt */ PIE1bits.RCIE = 1; } /* is the queue empty yet */ bool msg_empty(void) { if (outp == 0) return 1; return 0; } /* new message in the queue */ void msg_write(const char *msg) { char * p = outbuff + outlen; while (outlen < sizeof(outbuff) && *msg != 0) { *(p++) = *(msg++); outlen++; } *p = 0; if (outp == 0) { outp = outbuff; PIE1bits.TXIE = 1; } } void msg_writebyte(const char msg) { if (outlen+1 >= (uint8_t)sizeof(outbuff)) return; outbuff[outlen++] = msg; outbuff[outlen] = 0; if (outp == 0) { outp = outbuff; PIE1bits.TXIE = 1; } } void putch(char data) { msg_writebyte(data); } /* called from interrupt routine to send next char */ void msg_sendnext(void) { /* we have finished, turn off the iterrupt */ if (outp == 0 || *outp == 0) { PIE1bits.TXIE = 0; outp = 0; outlen = 0; return; } TXREG = *outp; outp++; } /* called from interrupt routine to receive next byte */ void msg_recvnext(void) { while (PIR1bits.RCIF) { bool err = RCSTAbits.FERR; char new = RCREG; /* bad char, skip it */ if (err) continue; /* our input buffer has overflowed */ if (inlen > sizeof(inbuff)) return; /* keep this one */ inbuff[inlen++] = new; } } bool msg_recvready(void) { if (inlen > 0) return 1; return 0; } char msg_recv(void) { if (inlen == 0) return 0; /* record and disable the interupt */ bool in = PIE1bits.RCIE; PIE1bits.RCIE = 0; char new = inbuff[0]; inlen--; /* shuffle them down one */ for (char i=0;i