/*******************************************************************************
 * (c) Copyright 2010-2012 Actel Corporation.  All rights reserved.
 *
 *  SmartFusion MPM reference design driver API providing the firmware
 *  interface to the MPM engine. 
 *
 *  SVN $Revision: 13756 $
 *  SVN $Date: 2010-07-15 14:47:11 +0100 (Thu, 15 Jul 2010) $
 *
 */

/* Start include guard */
#ifndef MPM_H_
#define MPM_H_

/* Start C++ support */
#ifdef __cplusplus
extern "C"
{
#endif

/* Includes */
#include <stdint.h>     /* sized int typedefs (e.g. uint8_t etc.) */
#include <stdbool.h>    /* for bool */

/* #defines */
	
/* Allow for up to 32 MPM channels 
 * Redefine MPM_MAX_NUMBER_OF_CHANNELS in client code using #define or
 * project properties using -D to tune MPM to cater for between 1 and 32
 * MPM channels if required.
 */
#ifndef MPM_MAX_NUMBER_OF_CHANNELS
#define MPM_MAX_NUMBER_OF_CHANNELS 32
#endif
	
#if ((MPM_MAX_NUMBER_OF_CHANNELS < 1) || (MPM_MAX_NUMBER_OF_CHANNELS > 32))
#error MPM_MAX_NUMBER_OF_CHANNELS must be between 1 and 32
#endif

/* By default MPM will assume that the number of ACE channels supported by 
 * A2F500 is possible and size internal data structures accordingly. To tune/
 * optimize for space based on a specific target device #define the relevant
 * target device symbol below. 
 */
#if 0
#define MPM_USING_A2F060
#define MPM_USING_A2F200
#define MPM_USING_A2F500
#endif

/* Sentinel invalid channel number
 * In the GUI, ACE configuration and here in the MPM "driver" channels are
 * identified by channel number n where 1 <= n <= min(32,
 * MPM_MAX_NUMBER_OF_CHANNELS). Anything else is an invalid channel number
 * and 0 is used in various places as a sentinel value.
 */
#define MPM_INVALID_CHANNEL_NUMBER (0)
	
/* Typedefs */

/* MPM engine states */ 
typedef enum mpm_state
{
    mpm_is_stopped,		/* Idle */
    mpm_is_starting,    /* Power up sequence running */
    mpm_is_started,     /* Monitoring/trimming/etc. */
    mpm_is_stopping		/* Power down sequence running */
} mpm_state_t;

/* Channels are identified by a number between 1 and 
 * min(32, MPM_MAX_NUMBER_OF_CHANNELS)
 */
typedef uint8_t mpm_channel_number_t;

/* Current state of a channel with respect to the 5 defined thresholds
 * OFF, UV2, UV1, OV1, OV2. Note that the relative ordering of the 
 * thresholds depends on channel polarity:
 * 
 * Positive: 0V < OFF < UV2 < UV1 [ < NOM ] < OV1 < OV2
 * Negative: 0V > OFF > OV2 > OV1 [ > NOM ] > UV1 > UV2
 */
typedef enum mpm_channel_state
{
    mpm_channel_is_off,
    mpm_channel_is_uv2,
    mpm_channel_is_uv1,
    mpm_channel_is_nominal,
    mpm_channel_is_ov1,
    mpm_channel_is_ov2
} mpm_channel_state_t;

/* Methods */

/* void mpm_init()
 * 
 * Initializes the MPM engine "driver" and must be called before any other 
 * the other MPM driver methods below.
 */
void mpm_init();

/* void mpm_start()
 * 
 * Starts the MPM engine.
 * 
 * If MPM is not in state mpm_is_stopped then this method does nothing and 
 * just returns immediately otherwise if MPM is in state mpm_is_stopped 
 * then this method:
 * 
 * - puts MPM into state mpm_is_starting
 * - starts channel threshold monitoring
 * - starts channel open loop trimming where applicable
 * - initiates power on sequencing
 * - waits until power on sequencing has successfully completed
 * - starts channel closed loop trimming where applicable
 * - puts MPM into state mpm_is_running
 * - channel threshold monitoring remains active
 */ 
void mpm_start();

/* void mpm_stop()
 * 
 * Stops the MPM engine 
 * 
 * If MPM is not in state mpm_is_running then this method does nothing and 
 * just returns immediately otherwise if MPM is in state mpm_is_running 
 * then this method:
 * 
 * - puts MPM into state mpm_is_stoping
 * - stops closed loop trimming where applicable
 * - initiates power down sequencing
 * - waits until power down sequencing has successfully completed
 * - stops open loop trimming where applicable
 * - stops channel threshold monitoring
 * - puts MPM into state mpm_is_stopped
 */
void mpm_stop();

/* mpm_state_t mpm_get_state()
 * 
 * Returns the state that the MPM engine is currently operating in.
 */
mpm_state_t mpm_get_state();

/* mpm_channel_state_t mpm_get_channel_state(mpm_channel_number_t)
 * 
 * Returns the current threshold relative state for the channel
 * identified by the channel number passed in. If the channel number
 * passed in does not refer to a valid channel then 
 * mpm_channel_is_off is returned.
 */
mpm_channel_state_t mpm_get_channel_state(mpm_channel_number_t);

/* int32_t mpm_get_channel_voltage_mv(mpm_channel_number_t)
 * 
 * Returns the current channel voltage in mV for the channel identified
 * by the channel number passed in. If the channel number passed in does
 * not refer to a valid channel then 0mV is returned.
 * 
 * If MPM is in state mpm_is_stopped then mpm_channel_is_off is returned 
 * for all channels.
 */ 
int32_t mpm_get_channel_voltage_mv(mpm_channel_number_t);

/* bool mpm_is_valid_channel(mpm_channel_number_t)
 * 
 * Returns true if the channel identified by the channel number passed in is
 * a valid channel recognized by the MPM engine and false otherwise. 
 * 
 * For a channel to be valid it must meet the following criteria:
 * 
 * - Signal name in ACE configuration must be "MPM_Channel_<n>..." where
 *   <n> is a unique identification number between 1 and min(32,
 *   MPM_MAX_NUMBER_OF_CHANNELS) and "..." can be any other text.
 * - ACE configuration for this channel must include one "UNDER" threshold
 *   flag named "DOWN" and one "OVER" threshold flag named "UP" with any
 *   valid voltage level (the threshold voltage levels are dynamically 
 *   adjusted at runtime by the MPM engine)
 * - None of the threshold/hysteresis/nominal voltage values configured
 *   through the MPM GUI is out of range of the underlying ACE (ABPS or 
 *   direct analog input) voltage channel.   
 */
bool mpm_is_valid_channel(mpm_channel_number_t);

/* uint32_t mpm_get_digital_inputs()
 * uint32_t mpm_get_digital_outputs()
 * uint32_t mpm_get_regulator_enable_outputs()
 * 
 * Returns a 32 bit bitmask [31:0] representing the current state of the 
 * relevant digital I/Os.  
 */
uint32_t mpm_get_digital_inputs();
uint32_t mpm_get_digital_outputs();
uint32_t mpm_get_regulator_enable_outputs();

/* End C++ support */
#ifdef __cplusplus
}
#endif

/* End include guard */
#endif  /* MPM_H_ */
