/****************************************************************************/
/* Copyright 2015 MBARI                                                     */
/****************************************************************************/
/* Summary  : Digital I/O Support for OASIS5 on PIC32MX470F512L             */
/* Filename : dig_io.c                                                      */
/* Author   : Robert Herlien (rah)                                          */
/* Project  : OASIS Mooring Replacement (OASIS5)                            */
/* Revision: 1.0                                                            */
/* Created  : 07/13/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:                                                    */
/* 13jul2015 rah - created                                                  */
/****************************************************************************/

#include <xc.h>
#include "dig_io.h"
#include "serial.h"

#define NumberOf(arr)       ((sizeof(arr) / sizeof(arr[0])))


/********************************/
/*  Module Local Data           */
/********************************/

unsigned int    pwrState;


/************************************************************************/
/* Function    : digInit                                                */
/* Purpose     : Initialize digital I/O ports on PIC32MX                */
/* Inputs      : None                                                   */
/* Outputs     : None                                                   */
/************************************************************************/
void digInit()
{
    /* Note: the ANSEL and TRIS registers have to be set on 
       ADC pins if you want to use them as digital I/O pins */    

    ANSELA = 0;
    ANSELB = 0x07c0;
    ANSELC = 0;
    ANSELD = 0;
    ANSELE = 0;
    ANSELF = 0;
    ANSELG = 0;

    TRISA = 0x0600;
    TRISB = 0x47dc;
    TRISC = 0x0014;
    TRISD = 0x980f;
    TRISE = 0x0200;
    TRISF = 0x001c;
    TRISG = 0x0100;

    LATA = 0xc038;
    LATB = 0;
    LATC = 0x0008;
    LATD = 0x2000;
    LATE = 0;
    LATF = 0;
    LATG = 0;

    CNPUD = 0x100f;

    clearRelayCoils();
    digPwrAllOff();
    pwrState = 0;
}


/************************************************************************/
/* Function    : digSerEnable                                           */
/* Purpose     : Enable Tx on a serial port                             */
/* Inputs      : Serial port number                                     */
/* Outputs     : None                                                   */
/************************************************************************/
void digSerEnable(int port)
{
    switch(port)
    {
      case 0: digTx0En();  return;
      case 1: digTx1En();  return;
      case 2: digTx2En();  return;
      case 3: digTx3En();  return;
      case 4: digTx4En();  return;
    }
}

/************************************************************************/
/* Function    : digSerDisable                                          */
/* Purpose     : Disable Tx on a serial port                            */
/* Inputs      : Serial port number                                     */
/* Outputs     : None                                                   */
/************************************************************************/
void digSerDisable(int port)
{
    switch(port)
    {
      case 0: digTx0Dis();  return;
      case 1: digTx1Dis();  return;
      case 2: digTx2Dis();  return;
      case 3: digTx3Dis();  return;
      case 4: digTx4Dis();  return;
    }
}

/************************************************************************/
/* Function    : digSnd485                                              */
/* Purpose     : Put Modbus port into 485 Send mode                     */
/* Inputs      : Serial port number                                     */
/* Outputs     : None                                                   */
/************************************************************************/
void digSnd485(int port)
{
    switch(port)
    {
      case 1: dig1Snd485();  return;
      case 2: dig2Snd485();  return;
      case 3: dig3Snd485();  return;
      case 4: dig4Snd485();  return;
    }
}

/************************************************************************/
/* Function    : digRcv485                                              */
/* Purpose     : Put Modbus port into 485 Receive mode                  */
/* Inputs      : Serial port number                                     */
/* Outputs     : None                                                   */
/************************************************************************/
void digRcv485(int port)
{
    switch(port)
    {
      case 1: dig1Rcv485();  return;
      case 2: dig2Rcv485();  return;
      case 3: dig3Rcv485();  return;
      case 4: dig4Rcv485();  return;
    }
}

/************************************************************************/
/* Function    : digSense485                                            */
/* Purpose     : Read 485/232 sense bit                                 */
/* Inputs      : Serial port number                                     */
/* Outputs     : Zero for RS-232, non-zero for RS-485                   */
/************************************************************************/
int  digSense485(int port)
{
    switch(port)
    {
      case 1: return(dig1Is485());
      case 2: return(dig2Is485());
      case 3: return(dig3Is485());
      case 4: return(dig4Is485());
    }

    return(0);
}


/************************************************************************/
/* Function    : digPwrOn                                               */
/* Purpose     : Turn on a power relay                                  */
/* Inputs      : Power port number                                      */
/* Outputs     : None                                                   */
/************************************************************************/
void digPwrOn(int port)
{
    dig12vEnable();

    switch(port)
    {
      case 1: relay1SetOn(); break;
      case 2: relay2SetOn(); break;
      case 3: relay3SetOn(); break;
      case 4: relay4SetOn(); break;
      default: dig12vDisable(); return;
    }

    tmrDelayMs(RELAY_DELAY_MS);

    clearRelayCoils();
    dig12vDisable();
    
    pwrState |= (1 << port);
}

/************************************************************************/
/* Function    : digPwrOff                                              */
/* Purpose     : Turn off a power relay                                 */
/* Inputs      : Power port number                                      */
/* Outputs     : None                                                   */
/************************************************************************/
void digPwrOff(int port)
{
    dig12vEnable();

    switch(port)
    {
      case 1: relay1ResetOn(); break;
      case 2: relay2ResetOn(); break;
      case 3: relay3ResetOn(); break;
      case 4: relay4ResetOn(); break;
      default: dig12vDisable(); return;
    }

    tmrDelayMs(RELAY_DELAY_MS);

    clearRelayCoils();
    dig12vDisable();

    pwrState &= ~(1 << port);
}


/************************************************************************/
/* Function    : digPwrSet                                              */
/* Purpose     : Turn on/off a power relay                              */
/* Inputs      : Power port number, state                               */
/* Outputs     : None                                                   */
/************************************************************************/
void digPwrSet(int port, int state)
{
    if (state)
        digPwrOn(port);
    else
        digPwrOff(port);
}


/************************************************************************/
/* Function    : digPwrGet                                              */
/* Purpose     : Return state of power bits                             */
/* Inputs      : None                                                   */
/* Outputs     : Power Vector                                           */
/************************************************************************/
int digPwrGet(void)
{
    return(pwrState);
}

/************************************************************************/
/* Function    : digPwrAllOff                                           */
/* Purpose     : Turn off all power/serial relays                       */
/* Inputs      : None                                                   */
/* Outputs     : None                                                   */
/************************************************************************/
void digPwrAllOff(void)
{
    dig12vEnable();
    relay1ResetOn();
    relay2ResetOn();
    relay3ResetOn();
    relay4ResetOn();
    
    tmrDelayMs(RELAY_DELAY_MS);

    clearRelayCoils();
    dig12vDisable();

    pwrState = 0;
}
