/*
 * File:   pantografo.c
 * Author: Corrado
 *
 * Created on 19 dicembre 2016, 9.29
 */


#include <xc.h>
#include <stdio.h>

#define TIME_5MS   -625

int current_x, current_y;
int target_x, target_y;
char on;

void interrupt isr(void)
{
    if (INTCONbits.T0IF == 1) {
        INTCONbits.T0IF = 0;
        TMR0 = TIME_5MS;
        if (on) {
            // gestione asse X
            if (target_x > current_x) {
                // spostamento X positivo
                LATBbits.LATB0 = 1;
                LATBbits.LATB1 = 0;
                LATBbits.LATB4 = 1;
                ++current_x;
            }
            else if (target_x < current_x) {
                // spostamento X negativo
                LATBbits.LATB0 = 0;
                LATBbits.LATB1 = 1;
                LATBbits.LATB4 = 1;
                --current_x;                
            }
            else {
                // posizione X raggiunta
                LATBbits.LATB0 = 1;
                LATBbits.LATB1 = 1;
                LATBbits.LATB4 = 0;
            }
            // gestione asse Y
            if (target_y > current_y) {
                // spostamento Y positivo
                LATBbits.LATB2 = 1;
                LATBbits.LATB3 = 0;
                LATBbits.LATB5 = 1;
                ++current_y;
            }
            else if (target_y < current_y) {
                // spostamento Y negativo
                LATBbits.LATB2 = 0;
                LATBbits.LATB3 = 1;
                LATBbits.LATB5 = 1;
                --current_y;                
            }
            else {
                // posizione Y raggiunta
                LATBbits.LATB2 = 1;
                LATBbits.LATB3 = 1;
                LATBbits.LATB5 = 0;
            }
        }
        else {
            // spegniamo i motori
            LATBbits.LATB0 = 1;
            LATBbits.LATB1 = 1;
            LATBbits.LATB2 = 1;
            LATBbits.LATB3 = 1;
        }
    }
}

void setup_digital(void)
{
    // led ports as outputs
    TRISBbits.TRISB0 = 0;
    TRISBbits.TRISB1 = 0;
    TRISBbits.TRISB2 = 0;
    TRISBbits.TRISB3 = 0;
    TRISBbits.TRISB4 = 0;
    TRISBbits.TRISB5 = 0;
    
    // pushbutton pin as input
    TRISAbits.TRISA3 = 1;
    TRISAbits.TRISA2 = 1;
    TRISCbits.TRISC2 = 1;
}

void setup_timer(void)
{
    T0CONbits.TMR0ON = 0; // stop the timer
    T0CONbits.T08BIT = 0; // timer configured as 16-bit
    T0CONbits.T0CS = 0; // use system clock
    T0CONbits.PSA = 0; // use prescaler
    T0CONbits.T0PS = 0b110; // prescaler 1:128 ('0b' is a prefix for binary)    

    INTCONbits.T0IF = 0;
    INTCONbits.T0IE = 1;  // enable TMR0 interrupt generation
    
    TMR0 = TIME_5MS;
    
    T0CONbits.TMR0ON = 1; // start the timer    
}

void setup_uart(void)
{
    // setup UART
    TRISCbits.TRISC6 = 0; // TX as output
    TRISCbits.TRISC7 = 1; // RX as input
    TXSTA1bits.SYNC = 0; // Async operation
    TXSTA1bits.TX9 = 0; // No tx of 9th bit
    TXSTA1bits.TXEN = 1; // Enable transmitter
    RCSTA1bits.RX9 = 0; // No rx of 9th bit
    RCSTA1bits.CREN = 1; // Enable receiver
    RCSTA1bits.SPEN = 1; // Enable serial port
    // Setting for 19200 BPS
    BAUDCON1bits.BRG16 = 0; // Divisor at 8 bit
    TXSTA1bits.BRGH = 0; // No high-speed baudrate
    SPBRG1 = 51; // divisor value for 19200
}

void putch(char c)
{
    while (TXSTA1bits.TRMT == 0) {}
    TXREG1 = c;
}

void setup_adc(void)
{
    ANSELAbits.ANSA0 = 1; // RA0 = analog input --> AN0
    ANSELAbits.ANSA1 = 1; // RA1 = analog input --> AN1
    ADCON1bits.PVCFG = 0b00; // Positive reference = +VDD
    ADCON1bits.NVCFG = 0b00; // Negative reference = GND
    ADCON2bits.ADFM = 1; // format = right justified
    ADCON2bits.ACQT = 0b111; // acquisition time = 20*TAD
    ADCON2bits.ADCS = 0b110; // conversion clock = FOSC/64
    ADCON0bits.ADON = 1; // turn on ADC    
}


void main(void) {
    int temp_x, temp_y;
    setup_digital();
    setup_timer();
    setup_uart();
    setup_adc();

    RCONbits.IPEN = 0;  // no priorities
    INTCONbits.GIE = 1; // global interrupt enable
    INTCONbits.PEIE = 1; // interrupt enable from peripherals

    current_x = 0;
    current_y = 0;
    on = 0;

    ADCON0bits.CHS = 0;
    ADCON0bits.GODONE = 1;
    
    for (;;) {
        
        if (ADCON0bits.GODONE == 0) {
            if (ADCON0bits.CHS == 0) {
                temp_x = ADRES;
                ADCON0bits.CHS = 1;
                ADCON0bits.GODONE = 1;
            }
            else {
                // canale campionato = 1
                temp_y = ADRES;
                ADCON0bits.CHS = 0;
                ADCON0bits.GODONE = 1;                
            }
        }
        
        printf("Posizione corrente (%4d, %4d), posizione target (%4d,%4d)\r", 
                current_x, current_y,
                temp_x, temp_y);
        if (PORTAbits.RA3 == 0) {
            on = 1;
            target_x = temp_x;
            target_y = temp_y;
            while (PORTAbits.RA3 == 0) {}
        }
        else if (PORTAbits.RA2 == 0) {
            on = 0;
            while (PORTAbits.RA2 == 0) {}
        }
        else if (PORTCbits.RC2 == 0) {
            current_x = 0;
            current_y = 0;
            while (PORTCbits.RC2 == 0) {}
        }
    }
    
    return;
}
