flipflop
A lightweight serial bootloader for PIC16F1 devices.
/**
* Simple blocking, auto-baud capable, 1/2-wire UART driver for PIC16(L)F1919x.
*/
#include <xc.h>
#include "uart.h"
void uart_init(void)
{
// Configure PPS module. This will set the associated TRIS bits for us.
UART_RX_PPS_REG = UART_RX_PPS_VAL;
UART_TX_PPS_REG = UART_TX_PPS_VAL;
// Configure EUSART1 module.
#ifdef UART_BAUDRATE // Setup static baudrate if defined.
SP1BRG = (unsigned int)((32000000UL / UART_BAUDRATE) / 4) - 1;
#endif
RC1STAbits.SPEN = 1; // Enable serial port
RC1STAbits.CREN = 1; // Enable Continuos Receive (RX)
#ifndef UART_ONE_WIRE // Only enable transmit in 2-wire mode
TX1STAbits.TXEN = 1; // Enable Transmit (TX)
#endif
BAUD1CONbits.BRG16 = 1; // Set BRG to use 16 bits
TX1STAbits.BRGH = 1; // Select high speed baudrate
}
void
uart_sync (void)
{
unsigned char sync_trash;
// Start auto-baud calibration sequence
BAUD1CONbits.ABDEN = 1;
while(BAUD1CONbits.ABDEN)
{
// Wait for sync character
CLRWDT();
}
// Read our trash value to clear interrupt flag
sync_trash = RC1REG;
#if 0
// Make sure we didn't overflow
if (BAUD1CONbits.ABDOVF)
{
while (BAUD1CONbits.RCIDL == 0)
{
// Wait for the fifth rising edge of the sync character.
sync_trash = RC1REG;
}
// Clear overflow bit
BAUD1CONbits.ABDOVF = 0;
// Hang
while (1)
{
CLRWDT();
}
}
#endif
// Subtract one from SP1BRGH:SP1BRGL register pair
if (SP1BRGL)
{
// We dont have to worry about rolling over in the high byte
sync_trash = SP1BRGL - 1;
SP1BRGL = sync_trash;
}
else
{
// Subtract 1 from the high byte and roll over the low byte.
sync_trash = SP1BRGH - 1;
SP1BRGH = sync_trash;
SP1BRGL = 0xFF;
}
}
void
uart_deinit (void)
{
// Reset all registers to POR value
BAUD1CON = 0;
RC1STA = 0;
TX1STA = 0;
SP1BRGL = 0;
SP1BRGH = 0;
// TODO: PPS registers
}
void uart_write(unsigned char data)
{
#ifdef UART_ONE_WIRE
TX1STAbits.TXEN = 1; // Enable Transmit (TX)
#else
while (!TX1STAbits.TRMT)
{
// Wait for transmit register to be empty
}
#endif
// Write byte to transmit register
TX1REG = data;
#ifdef UART_ONE_WIRE
// These two empty while loops wait for the packet to be sent by waiting
// for it to be received. The RCIDL bit is cleared while receiving.
while (BAUD1CONbits.RCIDL)
{
// wait for start bit
CLRWDT();
}
while (!BAUD1CONbits.RCIDL)
{
// wait to finish receiving byte sent
CLRWDT();
}
data = RC1REG; // Read back sent byte
TX1STAbits.TXEN = 0; // Disable Transmit (TX)
#endif
}
unsigned char
uart_read (void)
{
while (!PIR3bits.RC1IF)
{
// Wait for interrupt flag to signify a byte has been received.
CLRWDT();
}
return RC1REG;
}
int
uart_read_bytes (int len, unsigned char * buff)
{
for (int data = 0; data < len; data++)
{
while (!PIR3bits.RC1IF)
{
CLRWDT();
}
buff[data] = RC1REG;
}
return len;
}
// EOF //