/****************************************************************************/
/* Copyright 1991, 1992, 1993 MBARI                                         */
/****************************************************************************/
/* Summary  : IBC Monitor '196 microntroller - Main C Source file           */
/* Filename : monitor.c                                                     */
/* Author   : Andrew Pearce                                                 */
/* Project  : ROV 1.5 IBC Based Data Concentrator                           */
/* Version  : 1.0                                                           */
/* Created  : 01/13/93                                                      */
/* Modified : 01/14/93                                                      */
/* Archived :                                                               */
/****************************************************************************/
/* Modification History:                                                    */
/* $Header: /usr/tiburon/.cvsroot/micro/ibc/monitor/monitor.c,v 1.1.1.1 1997/05/02 18:51:25 pean Exp $
 * $Log: monitor.c,v $
 * Revision 1.1.1.1  1997/05/02 18:51:25  pean
 * Initial check in of IBC microcontroller software
 *
*/
/****************************************************************************/

#pragma model(196)
#pragma nosignedchar

#include "C:/C96/include/80C196.h"      /* 80196 Register mapping           */
#include "C:/C96/INCLUDE/string.h"      /* string function library          */
#include "const.h"                      /* Misc. constants - TRUE/FALSE etc */
#include "types.h"                      /* MBARI style guide declarations   */
#include "microasm.h"                   /* Assembly language functions      */
#include "applic.h"                     /* Microcontroller applications     */
#include "malloc.h"                     /* Malloc support routines          */

#include "timer.h"                      /* Timer library definitions        */
#include "microlib.h"                   /* Microcontroller Library decls.   */
#include "applay.h"                     /* Application layer funcitions     */
#include "microCmd.h"                   /* microcontroller commands         */
#include "syslib.h"                     /* Board Support library decls.     */
#include "../ibc/ibc_card.h"            /* IBC Board Types and Addresses    */
#include "../ibc/ibc_cmd.h"             /* Core IBC application definitions */
#include "../cpu196/cpu196.h"           /* IBC 80C196 CPU Board functions   */
#include "../cpu196/pic.h"              /* Intel 82C59 Interrupt Controller */
#include "../cpu196/eeprom.h"           /* Atmel 28C256 EEPROM Definitions  */

#include "../filter/filter.h"           /* IBC General IIR Filter Routines  */

#include "../gf_5v/gf_board.h"          /* Ground Fault Board Definitions   */
#include "../low_pwr/low_pwr.h"         /* Low Power Switch Board Defs      */
#include "../high_pwr/high_pwr.h"       /* High Power Switch Board Defs     */
#include "../vicor/vicor.h"             /* Dual Vicor Board Definitions     */
#include "../nav_if/nav_if.h"           /* Navigation Interface Board Defs  */
#include "../atod/atod.h"               /* IBC A to D Board Definitions     */
#include "../pio/pio.h"                 /* Parallel IO Board Definitions    */

#include "monitor.h"                    /* Application specific definitions */

/****************************************************************************/

const Char micro_id[] = "87C196KC IBC Monitor";
const Char softwareRev[] = "$Revision: 1.1.1.1 $";
const Char microSerialNo[] = "Monitor";

MLocal Boolean microEnabled;            /* Enables serial command processing*/

                                        /* Array of IBC boards in backplane */
MLocal IBC_BoardEntry *(IBC_CardTable[IBC_MAX_CARDS]);
MLocal Int16   IBC_CardCount;           /* IBC cards found in backplane     */


/****************************************************************************/
/* Function    : microReadPICStatusCmd                                      */
/* Purpose     : Send 82C59 PIC status register to serial port              */
/* Inputs      : None                                                       */
/* Outputs     : None                                                       */
/****************************************************************************/
    Void
microReadPICStatusCmd( Void )
{                                        /* send PIC status to serial port  */
    replyToCommand(2, CMD_OK, PIC_intStatus());
} /* microReadPICStatusCmd() */

/****************************************************************************/
/* Function    : microEEPROMTestCmd                                         */
/* Purpose     : Performs Read Write Test of EEPROM                         */
/* Inputs      : None                                                       */
/* Outputs     : None                                                       */
/****************************************************************************/
    Void
microEEPROMTestCmd( Void )
{
    Int16 addr, page;
    Boolean bad = FALSE;

    Byte buffer[EEPROM_PAGE_SIZE];
    Byte preserve[EEPROM_PAGE_SIZE];
    Byte pattern1[EEPROM_PAGE_SIZE];
    Byte pattern2[EEPROM_PAGE_SIZE];

    memset(pattern1, 0x55, EEPROM_PAGE_SIZE);
    memset(pattern2, 0xaa, EEPROM_PAGE_SIZE);

    for (page = 0; bad == FALSE, page < EEPROM_SIZE/EEPROM_PAGE_SIZE; page++)
    {
        EEPROM_Read(preserve, EEPROM_PAGE_SIZE, page * EEPROM_PAGE_SIZE);

        EEPROM_Write(pattern1, EEPROM_PAGE_SIZE, page * EEPROM_PAGE_SIZE);
        EEPROM_Read(buffer,    EEPROM_PAGE_SIZE, page * EEPROM_PAGE_SIZE);

        for (addr = 0; bad == FALSE, addr < EEPROM_PAGE_SIZE; addr++)
           if (buffer[addr] != pattern1[0]) bad = TRUE;

       if (bad == FALSE)
       {
           EEPROM_Write(pattern2, EEPROM_PAGE_SIZE, page * EEPROM_PAGE_SIZE);
           EEPROM_Read(buffer,    EEPROM_PAGE_SIZE, page * EEPROM_PAGE_SIZE);

           for (addr = 0; bad == FALSE, addr < EEPROM_PAGE_SIZE; addr++)
               if (buffer[addr] != pattern2[0]) bad = TRUE;

       } /* if */

       EEPROM_Write(preserve, EEPROM_PAGE_SIZE, page * EEPROM_PAGE_SIZE);
    } /* for */

    if (bad)
        replyToCommand(2, ECOMMAND, page * EEPROM_PAGE_SIZE + addr);
    else
        replyToCommand(2, CMD_OK, 0);
} /* microEEPROMTestCmd() */

/****************************************************************************/
/* Function    : microGetHumidity                                           */
/* Purpose     : Send humidity sensor value to serial port                  */
/* Inputs      : None                                                       */
/* Outputs     : None                                                       */
/****************************************************************************/
    Void
microGetHumidityCmd( Void )
{                                       /* send humidity to serial port    */
    replyToCommand(2, CMD_OK, readHumidity());
} /* microGetHumidityCmd() */

/****************************************************************************/
/* Function    : processCommand                                             */
/* Purpose     : Decode serial port command and dispatch handler            */
/* Inputs      : Command buffer and command buffer length                   */
/* Outputs     : None                                                       */
/****************************************************************************/
    Void
processCommand( Char * commandBuf, Int16 commandLen )
{
                                /* try to recognize the command and call    */
                                /* the appropriate handler                  */
    switch (wordFromBuf(commandBuf, 0))
    {
        default:
                                    /* Command received but not valid so    */
                                    /* Send pack an Invalid Command message */
            replyToCommand(1, ECOMMAND);
            break;

    } /* switch */
} /* processCommand() */

/****************************************************************************/
/* Function    : executeCommand                                             */
/* Purpose     : Check commands received from serial port and call handler  */
/* Inputs      : None                                                       */
/* Outputs     : None                                                       */
/****************************************************************************/
    Void
executeCommand( Void )
{
    Char    *commandBuf;            /* Pointer to the command packet data.  */
    Int16   commandLen;             /* Length of the command packet data    */

                                    /* read a command from serial port      */
    while (readRecvdPacket(&commandBuf, &commandLen) == OK)
    {
        if (microEnabled)
        {                           /* try to recognize the command and call*/
                                    /* the appropriate handler              */
            processCommand( commandBuf, commandLen );
        } /* if */

        else if ( wordFromBuf(commandBuf, 0) == (MICRO_APP | CMD_ENABLE) )
        {
            microEnabled = TRUE;
            replyToCommand(1, CMD_OK);
        } /* else */

        freeRecvdPacket(commandBuf);/* Free up the memory allocated for the */
                                    /* packet by readSerialPacket()         */
    } /* while */
} /* executeCommand() */

/****************************************************************************/
/* Function    : processSRQPacket                                           */
/* Purpose     : proceses Service Request Packets                           */
/* Inputs      : received packet buffer                                     */
/* Outputs     : None                                                       */
/****************************************************************************/
    Void
processSRQPacket(Byte *command_buf)
{
} /* processSRQPacket() */

/****************************************************************************/
/* Function    : IBC_initializeCards                                        */
/* Purpose     : Performs IBC bus related hardware & software initialization*/
/* Inputs      : Pointer to IBC Card Table, size of Card Table              */
/* Outputs     : Returns number of IBC cards                                */
/****************************************************************************/
    MLocal Int16
IBC_initializeCards( IBC_BoardEntry *IBC_CardTable[], Int16 maxCards )
{
    Int16 cardCount;        /* Number of IBC boards in chassis          */

    ibcBusInitialize();         /* Initialize IBC Bus Timeout Functions     */
    ibcBusReset();              /* Bring IBC Bus out of power up reset state*/

                                /* Search for installed IBC Cards           */
    cardCount = IBC_CardSearch( IBC_CardTable, maxCards );

    initializePIC();            /* Initialize CPU board Interrupt Controller*/
    PIC_enable();               /* Enable Interrupt from PIC to processor   */

                                /* Wait for the AtoD boards to power up     */
    taskDelay(IBC_POWERUP_DELAY);

    IBC_InitInterrupts( IBC_CardTable, cardCount );

    return(cardCount);
} /* initializeCards() */

/****************************************************************************/
/* Function    : mainLoop                                                   */
/* Purpose     : C main program called from assembler startup routine       */
/* Inputs      : None                                                       */
/* Outputs     : None                                                       */
/****************************************************************************/
    Void
mainLoop( Void )
{
    initIoport1();              /* Initialize Input/Output Port 1           */
    initIoport2();              /* Initialize Input/Output Port 2           */

    initMalloc();               /* Initialize Memory allocator              */
    initBoardStatus();          /* Initialize board status word             */

                                /* Initialize installed IBC Cards           */
    IBC_CardCount = IBC_initializeCards(&IBC_CardTable, IBC_MAX_CARDS);

                                /* Add entry for one Dual Vicor Card        */
    IBC_CardCount += dualVicorBoardInit( &IBC_CardTable[IBC_CardCount],
	IBC_MAX_CARDS - IBC_CardCount, 	(Byte *) DUAL_VICOR_0_ADDR,
        DUAL_VICOR_TWO_MINI_MODS );
                                /* Add entry for one Dual Vicor Card        */
    IBC_CardCount += dualVicorBoardAdd( &IBC_CardTable, IBC_MAX_CARDS,
         IBC_CardCount, DUAL_VICOR_0_ADDR, DUAL_VICOR_TWO_MINI_MODS );

    microEnabled = FALSE;       /* Disabled processing of serial commands   */
                                /* Initialize serial protocol               */
    initSerialProtocol(NULL);

                                /* Send Micro Reset SRQ                     */
    writeServiceRequest(1, MICRO_RESET_SRQ);

    FOREVER
    {                           /* Repeat forever                           */
        executeCommand();       /* Process any commands from the VME        */

    } /* forever */

} /* mainLoop() */
