#include "io.h"

unsigned int adcref,dacref;

void ioInit(void){
    unsigned char iflag;        //store INTCON
    adcref=readNVM(DIA_FVRA2X);
    dacref=readNVM(DIA_FVRC2X);
    //switches
    anselbits.S1=0; //digital inputs with pullups
    anselbits.S2=0;
    anselbits.S3=0;
    anselbits.S4=0;
    anselbits.S5=0;
    anselbits.S6=0;
    anselbits.S7=0;
    trisbits.S1=1;
    trisbits.S2=1;
    trisbits.S3=1;
    trisbits.S4=1;
    trisbits.S5=1;
    trisbits.S6=1;
    trisbits.S7=1;
    wpubits.S1=1;
    wpubits.S2=1;
    wpubits.S3=1;
    wpubits.S4=1;
    wpubits.S5=1;
    wpubits.S6=1;
    wpubits.S7=1;
    //analog input pulled up, not floating
    wpubits.UNUSED_A0=1;
    wpubits.UNUSED_A1=1;    
    anselbits.UNUSED_A0=1;
    anselbits.UNUSED_A1=1;    
}

void sendBBstring(char* c){
    while(*c){
        sendBBbyte(*c++);
    }    
}

void sendBBbyte(char d){
    anselbits.BB_UART_PIN=0;
    latbits.BB_UART_PIN=1;  //idle hi
    trisbits.BB_UART_PIN=0; //output
    latbits.BB_UART_PIN=0;  //start
    __delay_us(1000000/BB_BAUD);
    if(d&1){latbits.BB_UART_PIN=1;}else{latbits.BB_UART_PIN=0;}
    __delay_us(1000000/BB_BAUD);
    if(d&2){latbits.BB_UART_PIN=1;}else{latbits.BB_UART_PIN=0;}
    __delay_us(1000000/BB_BAUD);
    if(d&4){latbits.BB_UART_PIN=1;}else{latbits.BB_UART_PIN=0;}
    __delay_us(1000000/BB_BAUD);
    if(d&8){latbits.BB_UART_PIN=1;}else{latbits.BB_UART_PIN=0;}
    __delay_us(1000000/BB_BAUD);
    if(d&16){latbits.BB_UART_PIN=1;}else{latbits.BB_UART_PIN=0;}
    __delay_us(1000000/BB_BAUD);
    if(d&32){latbits.BB_UART_PIN=1;}else{latbits.BB_UART_PIN=0;}
    __delay_us(1000000/BB_BAUD);
    if(d&64){latbits.BB_UART_PIN=1;}else{latbits.BB_UART_PIN=0;}
    __delay_us(1000000/BB_BAUD);
    if(d&128){latbits.BB_UART_PIN=1;}else{latbits.BB_UART_PIN=0;}
    __delay_us(1000000/BB_BAUD);
    latbits.BB_UART_PIN=1;  //stop
    __delay_us(1000000/BB_BAUD);
}

void t0init(void){
    //16bit
    T0CON0=0;               //reset, 8-bit, 1:1    
    T0CON0bits.MD16=1;      //16-bit, period is 65536
    T0CON1bits.CS=2;        //FOSC/4=4MHz
    T0CON1bits.ASYNC=1;     //ASYNC
    T0CON1bits.T0CKPS=0;    //1:1
    T0CON0bits.OUTPS=14;    //1:15   1:15*65536 => 4Hz
    T0CON0bits.EN=1;        //on
    PIR0bits.TMR0IF=0;      //clear
    PIE0bits.TMR0IE=1;      //enable
/*
    //8bit
    T0CON0=0;               //reset, 8-bit, 1:1    
    T0CON1bits.CS=2;        //FOSC/4=8MHz
    T0CON1bits.ASYNC=1;     //ASYNC
    T0CON1bits.T0CKPS=7;    //1:128
    T0CON0bits.OUTPS=15;    //1:16
    TMR0H=255;              //full period
    T0CON0bits.EN=1;        //on
    PIR0bits.TMR0IF=0;      //clear
    PIE0bits.TMR0IE=1;      //enable
*/
}

void initADC(void){
    ADCON0=0;           //reset ADC, single ended
    ADCON1=0;
    ADCON2=0;           //legacy mode
    ADCON3=0;
    ADPRE=0;
    ADACQ=0;
    ADCAP=0;            //extra capacitance
    ADCON0bits.CS=1;    //ADCRC
    ADCON0bits.ADFM0=1; //right justify
    ADCON2=0;           //legacy mode
    ADREF=0;            //VDD    
    ADCON0bits.ADON=1;  //turn on, ready
    //FVR
    FVRCONbits.ADFVR=2;    //2.048V nominal
    FVRCONbits.EN=1;        //on    
}

void deInitADC(void){
    ADCON0=0;
    FVRCON=0;
}

unsigned int getADC(char c){
    ADPCH=c;
    ADCON0bits.GO=1;
    while(ADCON0bits.GO){}    
    return ADRES;
}

unsigned int getVCC(void){  //in mV
    unsigned long r;
    r=getADC(FVRBUF1);
    if(r<(adcref/2)){return 8192;}    //possible overflow/error
    return (unsigned int)(((unsigned long)adcref)*(4096UL)/r);
}

unsigned int readNVM(unsigned int add){ //maps top bit to NVMREGS
    NVMREGS=0;
    if(add&0x8000){NVMREGS=1;}
    NVMADR=add;
    NVMCON1bits.RD=1;   //start read
    return NVMDAT;    
}

unsigned int adjust(unsigned int v,unsigned int m){
    unsigned long t;
    t=((unsigned long)v) * ((unsigned long)m);
    t=t/(4096UL);
    return (unsigned int)t;
}
