/** \file
 *
 *  Contains the LPC3Reg class declaration.
 *
 *  Copyright (c) 2007,2008,2009 MBARI
 *  MBARI Proprietary Information.  All Rights Reserved
 *
 */

#ifndef LPC3REG_H_
#define LPC3REG_H_

#include "utils/Mutex.h"

/**
 *  Provides pointers for poking and peeking at LPC3XXX registers
 *
 *  \ingroup io
 *
 */
class LPC3Reg
{
public:

// Constructor
    LPC3Reg( unsigned long baseAddress, int bytesMapped );

// Destructor
    virtual ~LPC3Reg();

    // Clock Control - 0x40004000 base
    static volatile int& AdcClkCtrl1_;
    static volatile int& AdcClkCtrl_;
    static volatile int& TimClkCtrl_;
    static volatile int& U3ClkPhys_;
    static volatile int& U4ClkPhys_;
    static volatile int& U6ClkPhys_;
    static volatile int& UartClkCtrl_;

    // Main Interrupt Controller - 0x40008000 base

    // Sub Interrupt Controller 1 - 0x4000C000 base
    static volatile int& Sic1Er_;
    static volatile int& Sic1Rsr_;
    static volatile int& Sic1Sr_;
    static volatile int& Sic1Apr_;
    static volatile int& Sic1Atr_;
    static volatile int& Sic1Itr_;

    // Sub Interrupt Controller 2 - 0x40010000 base

    // High Speed Uart 1 - 40014000 base
    static volatile int& Hsu1Ctrl_;
    static volatile int& Hsu1RX_;

    // High Speed Uart 2 - 40018000 base
    static volatile int& Hsu2Level_;
    static volatile int& Hsu2RX_;

    // High Speed Uart 7 - 0x4001C000 base
    static volatile int& Hsu7RX_;

    // GPIO Registers
    static volatile int& P3InpStatePhys_;
    static volatile int& PioOutpSetPhys_;
    static volatile int& PioOutpClrPhys_;
    static volatile int& PioMuxSetPhys_;
    static volatile int& PioMuxClrPhys_;
    static volatile int& PioMuxStatePhys_;
    static volatile int& P0InpStatePhys_;
    static volatile int& P0OutpSetPhys_;
    static volatile int& P0OutpClrPhys_;
    static volatile int& P0OutpStatePhys_;
    static volatile int& P0DirSetPhys_;
    static volatile int& P0MuxSetPhys_;
    static volatile int& P0MuxClrPhys_;
    static volatile int& P3MuxSetPhys_;
    static volatile int& P3MuxClrPhys_;
    static volatile int& P3MuxStatePhys_;

    // ADC Control - 0x40048000 base
    static volatile int& AdcSelect_;
    static volatile int& AdcCtrl_;
    static volatile int& AdcValue_;

    // UART Control - 0x40054000 base
    static volatile int& UartCtrlPhys_;
    static volatile int& UartClkModePhys_;
    static volatile int& UartLoopPhys_;

    // Regular Uart 3 - 0x40080000 base
    static volatile int& U3LsrPhys_;
    static volatile int& U3DllPhys_;

    // Regular Uart 4 - 0x40088000 base
    static volatile int& U4DllPhys_;
    static volatile int& U4LsrPhys_;

    // Regular Uart 5 - 0x40090000 base
    static volatile int& U5LsrPhys_;

    // Regular Uart 6 - 0x40098000 base
    static volatile int& U6LsrPhys_;
    static volatile int& U6DllPhys_;
    static volatile int& U6IERPhys_;

    // Watchdog Timer - 0x4003C000 base
    static volatile int& WDTimCtrl_;
    static volatile int& WDTimCounter_;
    static volatile int& WDTimMCtrl_;
    static volatile int& WDTimMatch0_;
    static volatile int& WDTimEMR_;
    static volatile int& WDTimPulse_;
    static volatile int& WDTimRes_;

    /// Returns true if the drop weight is present, false if not
    static bool IsDropweightOK( void );

    /// Returns true if the burn wire is burning, false if not
    static bool IsBurnwireActive()
    {
        return BurnwireActive_;
    }

private:
    // Note that the copy constructor below is private and not given a body.
    // Any attempt to call it will return a compiler error.
    LPC3Reg( const LPC3Reg& old ); // disallow copy constructor

    int devFD_;
    int* map_;
    unsigned long targetAddress_;
    int bytesMapped_;

    static bool BurnwireActive_;

    // Clock Control - 0x40004000 base
    static LPC3Reg SysCtrlPhys_;

    // Main Interrupt Controller - 0x40008000 base

    // Sub Interrupt Controller 1 - 0x4000C000 base
    static LPC3Reg Sic1_;

    // Sub Interrupt Controller 2 - 0x40010000 base

    // High Speed Uart 1 - 40014000 base
    static LPC3Reg Hsu1RxPhys_;

    // High Speed Uart 2 - 0x40018000 base
    static LPC3Reg Hsu2RxPhys_;

    // High Speed Uart 7 - 0x4001C000 base
    static LPC3Reg Hsu7RxPhys_;

    // GPIO Registers - 0x40028000 base
    static LPC3Reg PioPhys_;

    // ADC Control - 0x40048000 base
    static LPC3Reg Adc_;

    // UART Control - 0x40054000 base
    static LPC3Reg UartGenCtrlPhys_;

    // Regular Uart 3 - 0x40080000 base
    static LPC3Reg Uart3Phys_;

    // Regular Uart 4 - 0x40088000 base
    static LPC3Reg Uart4Phys_;

    // Regular Uart 5 - 0x40090000 base
    static LPC3Reg Uart5Phys_;

    // Regular Uart 6 - 0x40098000 base
    static LPC3Reg Uart6Phys_;

    // Watchdog Timer - 0x4003C000 base
    static LPC3Reg WDTPhys_;


private:

    friend class CBIT;
    friend class SBIT;
    friend class IBIT;
    friend class Supervisor;
    friend class CommandExec;
    friend class LoadControl;
    friend class VerticalControl;
    friend class DropWeight;
    friend class BPC1;
    friend class Onboard;

    // Activates backup radio power
    static void ActivateBackupRadioPwr( void );

    // Activate the burnwire to drop the weight
    static void ActivateBurnwire( void );

    // Activates power to monitor state of the dropweight
    static void ActivateDropweightSense( void );

    // Activates power for the GF monitoring circuit
    static void ActivateGFPwr( void );

    // Monitors the batteries
    static void CheckBatt( void );

    // Deactivate the burnwire to NOT drop the weight
    static void DeactivateBurnwire( void );

    // Deactivate the power for dropweight state monitoring
    static void DeactivateDropweightSense( void );

    // Deactivate the radio(s) so they are not powered in emergency mode
    static void DeactivateEmergMode( void );

    // Deactivates power for the GF monitoring circuit
    static void DeactivateGFPwr( void );

    // Deactivates backup radio power
    static void DeactivateBackupRadioPwr( void );

    // Get ready to heartbeat
    static void InitializeHBC( void );

    // Handles initialization of multipurpose pins
    static bool InitializeMuxPins( void );

    // Strobe the heartbeat counter
    static void StrobeHBC( void );

    // Kick the dog
    static void StrobeWDT( void );

    // Asserts reset signal
    static void SWReset( void );

    // Shut down the watchdog timer
    static void UninitializeWDT( void );


    // Returns true if CF card is missing (NOT detected)
    static bool CFMissing( void );

    // Fire up the watchdog timer
    static bool InitializeWDT( void );

    // Turns the battery pack controller mux on or off
    static void PowerOffBatteryMux( void );
    static void PowerOnBatteryMux( void );

    // Removes power from the load control backplane
    static bool PowerOffLoads( void );

    // Applies power to the load control backplane
    static bool PowerOnLoads( void );

    // Returns true if LOAD_CONT_STATE is asserted (note signal is active low)
    static bool QueryBackplanePower( void );

    // Returns true if battery power is being distributed to the backplane
    static bool QueryBackplaneOvercurrent( void );

    // Returns true if battery power is on, false if not.
    static bool QueryBattPower( void );

    // Returns true if shore power is on, false if not.
    static bool QueryShorepower( void );

    // Returns true if water is detected in the pressure hull
    static bool WaterDetected( void );

    // Keeps track of flipping the state of the heartbeat signal
    static bool HeartbeatHi_;


    // Ground fault channel definitions
    // 2 bit encoding with an enable for chan A/B
    // Addr 0: GPO_02, Bit 2 (0x4)
    // Addr 1: GPO_01, Bit 1 (0x2)
    // Enable A: GPO_00, Bit 0 (0x1)
    // Enable B: GPO_18, Bit 18 (0x40000)
    typedef enum { CHAN_A0 = 0x1, // VBAT
                   CHAN_A1 = 0x5, // +24V_LC
                   CHAN_A2 = 0x3, // +12.0V_LC
                   CHAN_A3 = 0x7, // +5V LC
                   CHAN_B0 = 0x40000, // +3.3V_LC
                   CHAN_B1 = 0x40004, // CPU-A_3.15V
                   CHAN_B2 = 0x40002, // CPU-B_3.15V
                   CHAN_B3 = 0x40006, // GND
                 } GFChan;

    // Ground fault circuit handling
    static void ActivateGF( GFChan channel );
//    void LPC3Reg::DeactivateGF( GFChan channel )
    static void DeactivateGF( void );

    // Mutex for thread-safing an instance of LPC3Reg.
    static Mutex Mutex_;

};

#endif /*LPC3REG_H_*/

