/****************************************************************************/
/* Copyright 2010 MBARI.                                                    */
/* MBARI Proprietary Information. All rights reserved.                      */
/****************************************************************************/
#include "dig_io.h"
#include "p24Fxxxx.h"
#include "sys_defs.h"

static int dummyBit;

#define TOTAL_OUT_BITS  16

#define OUT_BIT_0 LATCbits.LATC6 // SPI #2 CS Add A
#define OUT_BIT_1 LATCbits.LATC7 // SPI #2 CS Add B
#define OUT_BIT_2 LATCbits.LATC8 // SPI #2 CS Add C
#define OUT_BIT_3 LATCbits.LATC9 // SPI #2 CS Add D
#define OUT_BIT_4 LATCbits.LATC0 // Offset Digital Pot CS (SPI #2)
#define OUT_BIT_5 LATCbits.LATC3 // Main Bus Interrupt Output Enable
#define OUT_BIT_6 LATBbits.LATB15 // ADC #1 Shutdown
#define OUT_BIT_7 LATCbits.LATC5 // ADC #2 Shutdown 

#define OUT_BIT_8 LATBbits.LATB7 // UART Shutdown
#define OUT_BIT_9 LATCbits.LATC1 // Offset Digital Pot Reset
#define OUT_BIT_10 LATBbits.LATB5 // Mag Compass XY Offset LR
#define OUT_BIT_11 LATBbits.LATB6 // Mag Compass Z Offset LR
#define OUT_BIT_12 LATCbits.LATC2 // Mag Compass SR Strap
#define OUT_BIT_13 dummyBit 
#define OUT_BIT_14 dummyBit 
#define OUT_BIT_15 dummyBit 


#define TOTAL_IN_BITS  16

#define IN_BIT_0 PORTAbits.RA8 // Board Address 0 [LSB]
#define IN_BIT_1 PORTAbits.RA9 // Board Address 1
#define IN_BIT_2 PORTAbits.RA10 // Board Address 2 [MSB]
#define IN_BIT_3 PORTBbits.RB13 // Main Bus Chip Select (SPI #1)
#define IN_BIT_4 PORTAbits.RA0 // Water Sensor #1
#define IN_BIT_5 PORTAbits.RA1 // Water Sensor #2
#define IN_BIT_6 PORTAbits.RA4 // Water Sensor #3
#define IN_BIT_7 PORTAbits.RA7 // Water Sensor #4

#define IN_BIT_8 PORTBbits.RB14 // ADC #1 Busy
#define IN_BIT_9 PORTCbits.RC4 // ADC #2 Busy
#define IN_BIT_10 dummyBit 
#define IN_BIT_11 dummyBit 
#define IN_BIT_12 dummyBit 
#define IN_BIT_13 dummyBit 
#define IN_BIT_14 dummyBit 
#define IN_BIT_15 dummyBit 


/* init registers */
void digInit()
{
    /* Note: the AD1PCFGL and TRIS registers have to be set on 
    ADC pins if you want to use them as digital I/O pins */    
	
	/* Configure all analog/digital sharing pins to digital */
	// 1 = digital, 0 = analog (n=ADC#)

	AD1PCFGbits.PCFG0 = 1;
	AD1PCFGbits.PCFG1 = 1;
	AD1PCFGbits.PCFG2 = 1;
	AD1PCFGbits.PCFG3 = 1;
	AD1PCFGbits.PCFG4 = 1;
	AD1PCFGbits.PCFG5 = 1;
	AD1PCFGbits.PCFG6 = 1;
	AD1PCFGbits.PCFG7 = 1;
	AD1PCFGbits.PCFG8 = 1;
	AD1PCFGbits.PCFG9 = 1;
	AD1PCFGbits.PCFG10 = 1;
	AD1PCFGbits.PCFG11 = 1;
	AD1PCFGbits.PCFG12 = 1;

    /* set outputs here */
    
	TRISBbits.TRISB5 = 0;
	TRISBbits.TRISB6 = 0;
	TRISBbits.TRISB7 = 0;
	TRISBbits.TRISB15 = 0;

	TRISBbits.TRISB8 = 0; // For UART1 Tx

	TRISCbits.TRISC0 = 0;
	TRISCbits.TRISC1 = 0;
	TRISCbits.TRISC2 = 0;
	TRISCbits.TRISC3 = 0;
	TRISCbits.TRISC5 = 0;
	TRISCbits.TRISC6 = 0;
	TRISCbits.TRISC7 = 0;
	TRISCbits.TRISC8 = 0;
	TRISCbits.TRISC9 = 0;
       
    /* set inputs here */
	
	TRISAbits.TRISA0 = 1;
	TRISAbits.TRISA1 = 1;
	TRISAbits.TRISA4 = 1;
	TRISAbits.TRISA7 = 1;
	TRISAbits.TRISA8 = 1;
	TRISAbits.TRISA9 = 1;
	TRISAbits.TRISA10 = 1;

	TRISBbits.TRISB13 = 1;
	CNPU1bits.CN13PUE = 0;
	TRISBbits.TRISB14 = 1;    
	
	TRISBbits.TRISB9 = 1; // For UART1 Rx

	TRISCbits.TRISC4 = 1;

    /* put out bits in default state here */
    Nop();
    OUT_BIT_0 = 1;
    Nop();
    OUT_BIT_1 = 1;    
    Nop();
    OUT_BIT_2 = 1;
    Nop();
    OUT_BIT_3 = 1;
    Nop();
    OUT_BIT_4 = 1;
    Nop();
    OUT_BIT_5 = 1;
    Nop();
    OUT_BIT_6 = 1;
    Nop();
    OUT_BIT_7 = 1;
	Nop();
    OUT_BIT_8 = 1;
	Nop();
    OUT_BIT_9 = 1;
	Nop();
    OUT_BIT_10 = 0;
	Nop();
    OUT_BIT_11 = 0;
	Nop();
    OUT_BIT_12 = 0;
	Nop();
    OUT_BIT_13 = 0; // Dummy
	Nop();
    OUT_BIT_14 = 0; // Dummy
	Nop();
    OUT_BIT_15 = 0; // Dummy

}

/* power bit API */
void digSetOutBit(int bit, int state)
{
    /* state is non zero, set it to one */
    if ( state )
        state = 1;
    
    Nop();

    switch (bit)
    {
        case 0: OUT_BIT_0 = state; break;
        case 1: OUT_BIT_1 = state; break;
        case 2: OUT_BIT_2 = state; break;
        case 3: OUT_BIT_3 = state; break;
        case 4: OUT_BIT_4 = state; break;
        case 5: OUT_BIT_5 = state; break;
        case 6: OUT_BIT_6 = state; break;
        case 7: OUT_BIT_7 = state; break;
		case 8: OUT_BIT_8 = state; break;
        case 9: OUT_BIT_9 = state; break;
        case 10: OUT_BIT_10 = state; break;
        case 11: OUT_BIT_11 = state; break;
        case 12: OUT_BIT_12 = state; break;
        case 13: OUT_BIT_13 = state; break;
        case 14: OUT_BIT_14 = state; break;
        case 15: OUT_BIT_15 = state; break;
        default: return;
    }
}

int digGetOutBit(int bit)
{
    Nop();

    /* set dummyBit to 0 so undefined bits always read back as 0 */
    dummyBit = 0;
    
    switch (bit)
    {
        case 0: return (int)OUT_BIT_0;
        case 1: return (int)OUT_BIT_1;
        case 2: return (int)OUT_BIT_2;
        case 3: return (int)OUT_BIT_3;
        case 4: return (int)OUT_BIT_4;
        case 5: return (int)OUT_BIT_5;
        case 6: return (int)OUT_BIT_6;
        case 7: return (int)OUT_BIT_7;
		case 8: return (int)OUT_BIT_8;
        case 9: return (int)OUT_BIT_9;
        case 10: return (int)OUT_BIT_10;
        case 11: return (int)OUT_BIT_11;
        case 12: return (int)OUT_BIT_12;
        case 13: return (int)OUT_BIT_13;
        case 14: return (int)OUT_BIT_14;
        case 15: return (int)OUT_BIT_15;
        default: return 0;
    }
}

void digSetOutPort(unsigned int val)
{
    int i;
    unsigned int bit = 0x0001;
     
    for (i = 0; i < TOTAL_OUT_BITS; ++i)
    {
        digSetOutBit(i, (val & bit));
        bit <<= 1;
    }
}

unsigned int digGetOutPort(void)
{
    int i;
    unsigned int bit = 0x0001;
    unsigned int val = 0;

    for (i = 0; i < TOTAL_OUT_BITS; ++i)
    {
        if ( digGetOutBit(i) )
            val += bit;
        
        bit <<= 1;
    }

    return val;
}

/* digital input API */
int digGetInBit(int bit)
{
    Nop();

    /* set dummyBit to 0 so undefined bits always read back as 0 */
    dummyBit = 0;
    
    switch (bit)
    {
        case 0: return (int)IN_BIT_0;
        case 1: return (int)IN_BIT_1;
        case 2: return (int)IN_BIT_2;
        case 3: return (int)IN_BIT_3;
        case 4: return (int)IN_BIT_4;
        case 5: return (int)IN_BIT_5;
        case 6: return (int)IN_BIT_6;
        case 7: return (int)IN_BIT_7;
		case 8: return (int)IN_BIT_8;
        case 9: return (int)IN_BIT_9;
        case 10: return (int)IN_BIT_10;
        case 11: return (int)IN_BIT_11;
        case 12: return (int)IN_BIT_12;
        case 13: return (int)IN_BIT_13;
        case 14: return (int)IN_BIT_14;
        case 15: return (int)IN_BIT_15;
        default: return 0;
    }
}

unsigned int digGetInPort(void)
{
    int i;
    unsigned int bit = 0x0001;
    unsigned int val = 0;

    for (i = 0; i < TOTAL_IN_BITS; ++i)
    {
        if ( digGetInBit(i) )
            val += bit;
        
        bit <<= 1;
    }

    return val;
}

