/****************************************************************************/
/* Copyright 2015 MBARI                                                     */
/****************************************************************************/
/* Summary  : Digital I/O Support for the OASIS5 5 Port expander (PIC25FJ128GA406)*/
/* Filename : dig_io.c                                                      */
/* Author   : Robert Herlien (rah)                                          */
/* Project  : OASIS Mooring Replacement (OASIS5)                            */
/* Revision: 1.0                                                            */
/* Created  : 10/27/2015                                                    */
/*                                                                          */
/* MBARI provides this documentation and code "as is", with no warranty,    */
/* express or implied, of its quality or consistency. It is provided without*/
/* support and without obligation on the part of the Monterey Bay Aquarium  */
/* Research Institute to assist in its use, correction, modification, or    */
/* enhancement. This information should not be published or distributed to  */
/* third parties without specific written permission from MBARI.            */
/*                                                                          */
/****************************************************************************/
/* Modification History:                                                    */
/* 27oct2015 rah - created                                                  */
/****************************************************************************/

#include "xc.h"
#include "dig_io.h"
#include "serial.h"


/********************************/
/*  Module Local Data           */
/********************************/

#ifdef O5_DB    /* Daughter Board  */

static WORD  pwrVec = 0;

const PortBits serEnblBits[] =
    { {&LATD, 0x10}, {&LATB, 0x8000},  {&LATG, 0x40},  {&LATD, 0x0100},
      {&LATB, 0x4000}, {&LATB, 0x0100} };

const RelayBits pwrBits[] =
    { {&LATD, 0x20, &LATF, 0x40},  {&LATF, 0x04, &LATF, 0x08},
      {&LATG, 0x04, &LATG, 0x08},  {&LATD, 0x01, &LATD, 0x0800},
      {&LATF, 0x01, &LATD, 0x080}, {&LATB, 0x0400, &LATB, 0x0200} };

#else   /* 5 Port Expander Board  */

const PortBits serEnblBits[] =
    { {&LATD, 0x10}, {&LATD, 0x0800}, {&LATG, 0x08}, {&LATB, 0x2000},
      {&LATB, 0x40}, {&LATE, 0x80} };

const PortBits pwrBits[] =
    { {&LATD, 0x20}, {&LATD, 0x01}, {&LATG, 0x04}, {&LATB, 0x8000}, {&LATD, 0x80} };

#endif


/************************************************************************/
/* Function    : digInit                                                */
/* Purpose     : Initialize digital I/O ports on PIC24                  */
/* Inputs      : None                                                   */
/* Outputs     : None                                                   */
/************************************************************************/
void digInit()
{
    /* Note: the ANSx and TRIS registers have to be set on 
       ADC pins if you want to use them as digital I/O pins */    

    ANSA = 0;
    ANSB = 0;
    ANSC = 0;
    ANSD = 0;
    ANSE = 0;
    ANSF = 0;
    ANSG = 0;
    ANSH = 0;
    ANSJ = 0;

    TRISA = 0;
    TRISC = 0x9000;
    TRISD = 0x0244;
    TRISE = 0;
    TRISF = 0x0010;
    TRISH = 0;
    TRISJ = 0;

#ifdef O5_DB            /* Daughter Board            */
#ifdef PROTO
    TRISB = 0x1070;     /* Proto Daughter Board      */
#else
    TRISB = 0x1030;     /* Production Daughter Board */
#endif
    TRISG = 0x0280;     /* Daughter Board            */
    LATB = 0x08;
#else                   /* 5 Port Expander Board     */
    TRISB = 0x1000;
    TRISG = 0x0080;
    LATB = 0;
#endif


    LATA = 0;
    LATC = 0x9000;
    LATD = 0;
    LATE = 0;
    LATF = 0;
    LATG = 0;
    LATH = 0;
    LATJ = 0;

}


/************************************************************************/
/* Function    : digSerEnable                                           */
/* Purpose     : Enable Tx on a serial port                             */
/* Inputs      : Serial port number                                     */
/* Outputs     : None                                                   */
/************************************************************************/
void digSerEnable(int port)
{
    if (port < NumberOf(serEnblBits))
        *serEnblBits[port].portP |= serEnblBits[port].bit;
}


/************************************************************************/
/* Function    : digSerDisable                                          */
/* Purpose     : Disable Tx on a serial port                            */
/* Inputs      : Serial port number                                     */
/* Outputs     : None                                                   */
/************************************************************************/
void digSerDisable(int port)
{
    if (port < NumberOf(serEnblBits))
        *serEnblBits[port].portP &= ~(serEnblBits[port].bit);
}


/************************************************************************/
/* Function    : digSetSerEnable                                        */
/* Purpose     : Set Tx Enable status on a serial port                  */
/* Inputs      : Serial port number, enable state                       */
/* Outputs     : None                                                   */
/************************************************************************/
void digSetSerEnable(int port, int state)
{
    if (port < NumberOf(serEnblBits))
    {
        if (state)
            *serEnblBits[port].portP |= serEnblBits[port].bit;
        else
            *serEnblBits[port].portP &= ~serEnblBits[port].bit;
    }
}


/************************************************************************/
/* Function    : digGetSerEnable                                        */
/* Purpose     : Get Tx Enable status on a serial port                  */
/* Inputs      : Serial port number                                     */
/* Outputs     : 0 for disabled, 1 for enabled                          */
/************************************************************************/
int digGetSerEnable(int port)
{
    if (port < NumberOf(serEnblBits))
        return((*serEnblBits[port].portP & serEnblBits[port].bit) ? 1 : 0);
    else
        return(0);
}


#ifdef O5_DB    /**************** Daughter Board  ********************/

/************************************************************************/
/* Function    : digPwrSet                                              */
/* Purpose     : Turn on/off a power bit                                */
/* Inputs      : Power port number, state                               */
/* Outputs     : None                                                   */
/************************************************************************/
void digPwrSet(int port, int state)
{
    if (port < NumberOf(pwrBits))
    {
        digRelayEn();

        if (state)
        {
            *pwrBits[port].setP |= pwrBits[port].setBit;
            tmrDelayTicks(RELAY_TICKS);
            *pwrBits[port].setP &= ~(pwrBits[port].setBit);
            pwrVec |= (1<<port);
        }
        else
        {
            *pwrBits[port].resetP |= pwrBits[port].resetBit;
            tmrDelayTicks(RELAY_TICKS);
            *pwrBits[port].resetP &= ~(pwrBits[port].resetBit);
            pwrVec &= ~(1<<port);
        }

        digRelayDis();
    }
}


/************************************************************************/
/* Function    : digPwrVecSet                                           */
/* Purpose     : Turn on/off a power bit                                */
/* Inputs      : Power port number, state                               */
/* Outputs     : None                                                   */
/************************************************************************/
void digPwrVecSet(int vec)
{
    int         i;

    digRelayEn();

    for (i = 0; i < NumberOf(pwrBits); i++)
    {
        if (vec & (1<<i))
            *pwrBits[i].setP |= pwrBits[i].setBit;
        else
            *pwrBits[i].resetP |= pwrBits[i].resetBit;
    }

    tmrDelayTicks(RELAY_TICKS);

    for (i = 0; i < NumberOf(pwrBits); i++)
    {
        *pwrBits[i].setP &= ~(pwrBits[i].setBit);
        *pwrBits[i].resetP &= ~(pwrBits[i].resetBit);
    }

    digRelayDis();
    pwrVec = vec;
}


/************************************************************************/
/* Function    : digPwrIsOn                                             */
/* Purpose     : Return state of one power relay                        */
/* Inputs      : Bit Number                                             */
/* Outputs     : 1 if on, 0 if off                                      */
/************************************************************************/
int digPwrIsOn(int bitnum)
{
    if (bitnum >= NumberOf(pwrBits))
        return(0);

    return((pwrVec & (1<<bitnum)) ? 1 : 0);
}


/************************************************************************/
/* Function    : digPwrGet                                              */
/* Purpose     : Return state of power bits                             */
/* Inputs      : None                                                   */
/* Outputs     : Power Vector                                           */
/************************************************************************/
int digPwrGet(void)
{
    return(pwrVec);
}


#else   /*************** 5 Port Expander Board  *******************/


/************************************************************************/
/* Function    : digPwrSet                                              */
/* Purpose     : Turn on/off a power bit                                */
/* Inputs      : Power port number, state                               */
/* Outputs     : None                                                   */
/************************************************************************/
void digPwrSet(int port, int state)
{
    if (port < NumberOf(pwrBits))
    {
        if (state)
            *pwrBits[port].portP |= pwrBits[port].bit;
        else
            *pwrBits[port].portP &= ~(pwrBits[port].bit);
    }
}


/************************************************************************/
/* Function    : digPwrVecSet                                           */
/* Purpose     : Turn on/off a power bit                                */
/* Inputs      : Power port number, state                               */
/* Outputs     : None                                                   */
/************************************************************************/
void digPwrVecSet(int vec)
{
    int         i;

    for (i = 0; i < NumberOf(pwrBits); i++)
        digPwrSet(i, 1<<i);
}


/************************************************************************/
/* Function    : digPwrIsOn                                             */
/* Purpose     : Return state of one power relay                        */
/* Inputs      : Bit Number                                             */
/* Outputs     : 1 if on, 0 if off                                      */
/************************************************************************/
int digPwrIsOn(int bitnum)
{
    if (bitnum >= NumberOf(pwrBits))
        return(0);

    return((*pwrBits[bitnum].portP & pwrBits[bitnum].bit) ? 1 : 0);
}


/************************************************************************/
/* Function    : digPwrGet                                              */
/* Purpose     : Return state of power bits                             */
/* Inputs      : None                                                   */
/* Outputs     : Power Vector                                           */
/************************************************************************/
int digPwrGet(void)
{
    int         i, state;

    for (i = state = 0; i < NumberOf(pwrBits); i++)
        if (*pwrBits[i].portP & pwrBits[i].bit)
            state |= (1<<i);

    return(state);
}

#endif /* else O5_DB */
