/////////////////////////////////////////////////////////////////////
//                                                                 //
// file: aUSBCSwitchPro.h	 	  	                               //
//                                                                 //
/////////////////////////////////////////////////////////////////////
//                                                                 //
// description: USBCSwitchPro C++ Module object.                   //
//                                                                 //
// build number: source                                            //
//                                                                 //
/////////////////////////////////////////////////////////////////////
//                                                                 //
// Copyright (c) 2018 Acroname Inc. - All Rights Reserved          //
//                                                                 //
// This file is part of the BrainStem release. See the license.txt //
// file included with this package or go to                        //
// https://acroname.com/software/brainstem-development-kit         //
// for full license details.                                       //
/////////////////////////////////////////////////////////////////////

#ifndef __aUSBCSwitchPro_H__
#define __aUSBCSwitchPro_H__

#include "BrainStem-all.h"
#include "aProtocoldefs.h"

/**
 * \defgroup aUSBCSwitchPro_Constants USBCSwitchPro Module Constants
 * @{
 */
#define aUSBCSWITCHPRO_MODULE                                     16  /**< USBCSwitchPro module number */

#define aUSBCSWITCHPRO_NUM_APPS                                    4 /**< Number of App instances available */
#define aUSBCSWITCHPRO_NUM_POINTERS                                4 /**< Number of Pointer instances available */

#define aUSBCSWITCHPRO_NUM_STORES                                  3 /**< Number of Store instances available */
#define   aUSBCSWITCHPRO_NUM_INTERNAL_SLOTS                        12 /**< Store: Number of internal slots instances available */
#define   aUSBCSWITCHPRO_NUM_RAM_SLOTS                             1 /**< Store: Number of RAM slot instances available */
#define   aUSBCSWITCHPRO_NUM_EEPROM_SLOTS                          8 /**< Store: Number of EEPROM slot instances available */
#define aUSBCSWITCHPRO_STORE_INTERNAL_INDEX                        0 /**< Store: Array index for internal store */
#define aUSBCSWITCHPRO_STORE_RAM_INDEX                             1 /**< Store: Array index for RAM store */
#define aUSBCSWITCHPRO_STORE_EEPROM_INDEX                          2 /**< Store: Array index for EEPROM store */

#define aUSBCSWITCHPRO_NUM_TEMPERATURES                            1 /**< Number of Temperature instances available */
#define aUSBCSWITCHPRO_NUM_TIMERS                                  8 /**< Number of Timer instances available */
#define aUSBCSWITCHPRO_NUM_USB                                     1 /**< Number of USB instances available */
#define aUSBCSWITCHPRO_NUM_USB_PORTS                               6 /**< Number of USB ports available */
#define aUSBCSWITCHPRO_NUM_PORTS                                   6 /**< Number of Ports available */
#define aUSBCSWITCHPRO_NUM_PD_PORTS                                6 /**< Number of PD compatible ports available */
#define aUSBCSWITCHPRO_NUM_PD_RULES_PER_PORT                       7 /**< Number of PD Rules per port available */
#define aUSBCSWITCHPRO_NUM_RAILS                                   1 /**< Number of Rail instances available */
#define aUSBCSWITCHPRO_NUM_I2C                                     1 /**< Number of I2C instances available */
#define aUSBCSWITCHPRO_NUM_UART                                    1 /**< Number of UART instances available */
#define aUSBCSWITCHPRO_NUM_MUX                                     1 /**< Number of Mux instances available */  
#define   aUSBCSWITCHPRO_NUM_MUX_CHANNELS                          4 /**< Number of Mux channels available */ 
#define aUSBCSWITCHPRO_NUM_EQ                                      2 /**< Number of Equalizer instances available */
/** @} */

/**
 * \defgroup aUSBCSwitchPro_Port_State_Defines Port State Definitions
 * \brief Bit defines for port state UInt32
 * \brief (Tip: Use _BIT(X) from aDefs.h to retrieve bit value)
 * @{
 */
// Example:  if (state & _BIT(aUSBCSwitchPro_USB_VBUS_ENABLED))
#define usbPortStateVBUS                               0 /**< USB VBUS current state */
#define usbPortStateUSB2A                              1 /**< USB2 side A current state */
#define usbPortStateUSB2B                              2 /**< USB2 side B current state */
#define usbPortStateSBU                                3 /**< SBU current state */
#define usbPortStateSS1                                4 /**< SS1 current state */
#define usbPortStateSS2                                5 /**< SS2 A current state */
#define usbPortStateCC1                                6 /**< CC1 current state */
#define usbPortStateCC2                                7 /**< CC2 A current state */
#define set_usbPortStateCOM_ORIENT_STATUS(var, state)  ((var & ~(3 << 8 )) | (state << 8)) /**< Common side orientation status */
#define get_usbPortStateCOM_ORIENT_STATUS(var)         ((var &  (3 << 8 )) >> 8) /**< Common side orientation status */
#define set_usbPortStateMUX_ORIENT_STATUS(var, state)  ((var & ~(3 << 10 )) | (state << 10)) /**< Mux side orientation status */
#define get_usbPortStateMUX_ORIENT_STATUS(var)         ((var &  (3 << 10 )) >> 10) /**< Mux side orientation status */
#define set_usbPortStateSPEED_STATUS(var, state)       ((var & ~(3 << 12)) | (state << 12)) /**< USB speed status */
#define get_usbPortStateSPEED_STATUS(var)              ((var &  (3 << 12)) >> 12) /**< USB speed status */
#define usbPortStateCCFlip                             14 /**< CC flip status */
#define usbPortStateSSFlip                             15 /**< SS flip status */
#define usbPortStateSBUFlip                            16 /**< SBU flip status */
#define usbPortStateUSB2Flip                           17 /**< USB2 flip status */
#define get_usbPortStateDaughterCard(var)              ((var & (3 << 18)) >> 18) /**< Daughter card status */
#define usbPortStateErrorFlag                          20 /**< Error indicator for this port */
#define usbPortStateUSB2Boost                          21 /**< USB2 boost current state */
#define usbPortStateUSB3Boost                          22 /**< USB3 boost current state */
#define usbPortStateConnectionEstablished              23 /**< Connection established state */
#define usbPortStateCC1Inject                          26 /**< CC1 inject current state */
#define usbPortStateCC2Inject                          27 /**< CC2 inject current state */
#define usbPortStateCC1Detect                          28 /**< CC1 detect current state */
#define usbPortStateCC2Detect                          29 /**< CC2 detect current state */
#define usbPortStateCC1LogicState                      30 /**< CC1 logic current state */
#define usbPortStateCC2LogicState                      31 /**< CC2 logic current state */
/** @} */

/**
 * \defgroup aUSBCSwitchPro_Port_Orientation_Defines Port Orientation Definitions
 * \brief State defines for 2 bit orientation elements.
 * @{
 */
#define usbPortStateOff                                0 /**< Indicator for port state off */
#define usbPortStateSideA                              1 /**< Indicator for port side A */
#define usbPortStateSideB                              2 /**< Indicator for port side B */
#define usbPortStateSideUndefined                      3 /**< Indicator for port side undefined */
/** @} */


///  \brief Concrete Module implementation of a USBCSwitchPro
///         Allows a user to connect to and control an attached switch
class aUSBCSwitchPro : public Acroname::BrainStem::Module
{
public:
    
    aUSBCSwitchPro(const uint8_t module = aUSBCSWITCHPRO_MODULE,
                bool bAutoNetworking = true,
                const uint8_t model = aMODULE_TYPE_USBC_Switch_Pro) :
    Acroname::BrainStem::Module(module, bAutoNetworking, model)
    {
        for(int x = 0; x < aUSBCSWITCHPRO_NUM_APPS; x++) {
            app[x].init(this, x);
        }

        // for(int x = 0; x < aUSBCSWITCHPRO_NUM_PD_PORTS; x++) {
        //     pd[x].init(this, x);
        // }

        for(int x = 0; x < aUSBCSWITCHPRO_NUM_POINTERS; x++) {
            pointer[x].init(this, x);
        }
        
        store[aUSBCSWITCHPRO_STORE_INTERNAL_INDEX].init(this, storeInternalStore);
        store[aUSBCSWITCHPRO_STORE_RAM_INDEX].init(this, storeRAMStore);
        store[aUSBCSWITCHPRO_STORE_EEPROM_INDEX].init(this, storeEEPROMStore);
        
        system.init(this, 0);
        
        for(int x = 0; x < aUSBCSWITCHPRO_NUM_TEMPERATURES; x++) {
            temperature[x].init(this, x);
        }
        
        for(int x = 0; x < aUSBCSWITCHPRO_NUM_TIMERS; x++) {
            timer[x].init(this, x);
        }

        for (int x = 0; x < aUSBCSWITCHPRO_NUM_PORTS; x++) {
            port[x].init(this, x);
        }

        mux.init(this, 0);
        
        for(int x = 0; x < aUSBCSWITCHPRO_NUM_RAILS; x++) {
            rail[x].init(this, x);
        }
        
        i2c[0].init(this, 0);
        uart.init(this, 0);
        
        usb.init(this, 0);
        
        equalizer[equalizer2p0].init(this, equalizer2p0);
        equalizer[equalizer3p0].init(this, equalizer3p0);
    }
    
    Acroname::BrainStem::AppClass app[aUSBCSWITCHPRO_NUM_APPS]; /**< App Class */
    Acroname::BrainStem::PointerClass pointer[aUSBCSWITCHPRO_NUM_POINTERS]; /**< Pointer Class */
    //Acroname::BrainStem::PowerDeliveryClass pd[aUSBCSWITCHPRO_NUM_PD_PORTS]; /**< Power Delivery Class */
    Acroname::BrainStem::RailClass rail[aUSBCSWITCHPRO_NUM_RAILS]; /**< Rail Class */
    Acroname::BrainStem::StoreClass store[aUSBCSWITCHPRO_NUM_STORES]; /**< Store Class */
    Acroname::BrainStem::SystemClass system; /**< System Class */
    Acroname::BrainStem::TemperatureClass temperature[aUSBCSWITCHPRO_NUM_TEMPERATURES]; /**< Temperature Class */
    Acroname::BrainStem::TimerClass timer[aUSBCSWITCHPRO_NUM_TIMERS]; /**< Timer Class */
    Acroname::BrainStem::I2CClass i2c[aUSBCSWITCHPRO_NUM_I2C]; /**< I2C Class */
    Acroname::BrainStem::USBClass usb; /**< USB Class */
    Acroname::BrainStem::UARTClass uart; /**< UART Class */ 
    Acroname::BrainStem::PortClass port[aUSBCSWITCHPRO_NUM_PORTS];
    Acroname::BrainStem::MuxClass mux; /**< Mux Class */
    Acroname::BrainStem::EqualizerClass equalizer[aUSBCSWITCHPRO_NUM_EQ]; /**< Equalizer Class */
    
    /** Port ID */
    typedef enum PORT_ID {
        kPORT_ID_0 = 0,
        kPORT_ID_1,
        kPORT_ID_2,
        kPORT_ID_3,
        kPORT_ID_COMMON,
        kPORT_ID_CONTROL
    } PORT_ID_t;

    // TODO: Should we change the equalizer enums to match the new switch, or try to keep backwards compatibility?

    /** Equalizer 3P0 transmitter configs */
    enum EQUALIZER_3P0_TRANSMITTER_CONFIGS {
        MUX_1db_COM_0db_900mV = 0,
        MUX_0db_COM_1db_900mV,
        MUX_1db_COM_1db_900mV,
        MUX_0db_COM_0db_900mV,
        MUX_0db_COM_0db_1100mV,
        MUX_1db_COM_0db_1100mV,
        MUX_0db_COM_1db_1100mV,
        MUX_2db_COM_2db_1100mV,
        MUX_0db_COM_0db_1300mV,
    };
    
    /** Equalizer 3P0 receiver configs */
    enum EQUALIZER_3P0_RECEIVER_CONFIGS {
        LEVEL_1_3P0 = 0,
        LEVEL_2_3P0,
        LEVEL_3_3P0,
        LEVEL_4_3P0,
        LEVEL_5_3P0,
        LEVEL_6_3P0,
        LEVEL_7_3P0,
        LEVEL_8_3P0,
        LEVEL_9_3P0,
        LEVEL_10_3P0,
        LEVEL_11_3P0,
        LEVEL_12_3P0,
        LEVEL_13_3P0,
        LEVEL_14_3P0,
        LEVEL_15_3P0,
        LEVEL_16_3P0,
    };
    
    /** Equalizer 2P0 transmitter configs */
    enum EQUALIZER_2P0_TRANSMITTER_CONFIGS {
        TRANSMITTER_2P0_40mV = 0,
        TRANSMITTER_2P0_60mV,
        TRANSMITTER_2P0_80mV,
        TRANSMITTER_2P0_0mV,
    };
    
    /** Equalizer 3P0 receiver configs */
    enum EQUALIZER_2P0_RECEIVER_CONFIGS {
        LEVEL_1_2P0 = 0,
        LEVEL_2_2P0,
    };
    
    /** Equalizer channels */
    enum EQUALIZER_CHANNELS {
        BOTH = 0,
        MUX,
        COMMON
    };
    
    /** Daughter Cards */
    enum daughtercard_type {
        NO_DAUGHTERCARD = 0,
        PASSIVE_DAUGHTERCARD,
        REDRIVER_DAUGHTERCARD,
        UNKNOWN_DAUGHTERCARD
    };
};



#endif /* aUSBCSwitchPro_h */
