/*
 * File:   main.c
 * Author: boos
 *
 * Created on March 28, 2020, 10:13 PM
 */

// CONFIG
#pragma config FOSC = INTOSCIO  // Oscillator Selection bits (INTOSC oscillator: I/O function on RA6/OSC2/CLKOUT pin, I/O function on RA7/OSC1/CLKIN)
#pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = OFF      // Power-up Timer Enable bit (PWRT disabled)
#pragma config MCLRE = OFF      // RA5/MCLR/VPP Pin Function Select bit (RA5/MCLR/VPP pin function is digital input, MCLR internally tied to VDD)
#pragma config BOREN = OFF      // Brown-out Detect Enable bit (BOD disabled)
#pragma config LVP = OFF        // Low-Voltage Programming Enable bit (RB4/PGM pin has digital I/O function, HV on MCLR must be used for programming)
#pragma config CPD = OFF        // Data EE Memory Code Protection bit (Data memory code protection off)
#pragma config CP = OFF         // Flash Program Memory Code Protection bit (Code protection off)

#include <xc.h>

// global variable that stores the received 8-bit value
unsigned char value = 0;

// define LED locations for later convenience
#define LED1 RB4
#define LED2 RB5
#define LED3 RB6
#define LED4 RB7
#define LED5 RA6
#define LED6 RA7
#define LED7 RA0
#define LED8 RA1

// main function
void main (void) {
    
	// set tristate registers
    
    // tristate bits for RB1 (RX) and RB2 (TX)
    // must both be set to 1 in USART mode
    TRISB1 = 1;
	TRISB2 = 1;
	
    // LEDs are outputs
    TRISB4 = 0;
    TRISB5 = 0;
    TRISB6 = 0;
    TRISB7 = 0;
    TRISA0 = 0;
    TRISA1 = 0;
    TRISA6 = 0;
    TRISA7 = 0;
    
    // disable analog features on PORTA
    // (we don't need them here)
    CMCON = 0b111;
    
	// configure USART module
	
	// slow Baud rate
	BRGH = 0;

	// set Baud rate to 1200
	// f_osc = 4MHz
    // SBPRG = fosc/(64 x Baud rate) - 1
	SPBRG = 51;

	// set to asynchronous
	SYNC = 0;

	// enable serial port
	SPEN = 1;

	// enable interrupts for receiving data
	RCIE = 1;

	// enable receiving module
	CREN = 1;

	// interrupts
    
    // global interrupts enabled
	GIE = 1;
    
    // peripheral interrupts enabled
	PEIE = 1;

	// main loop
	while (1) {

        // update LEDs
        LED1 = value & 1;
        LED2 = (value >> 1) & 1;
        LED3 = (value >> 2) & 1;
        LED4 = (value >> 3) & 1;
        LED5 = (value >> 4) & 1;
        LED6 = (value >> 5) & 1;
        LED7 = (value >> 6) & 1;
        LED8 = (value >> 7) & 1;
        
	}
    
    return;
    
}

// interrupt service routine
void __interrupt () isr (void) {

  // received some data via USART?
  if (RCIF) {

    // retrieve value
    value = RCREG;
    
    // send value back
	TXREG = value;
	TXEN = 1;

    // react to possible errors (we skip that here)
    CREN = 0;
    CREN = 1;
    OERR = 0;
    FERR = 0;

  }

}