/*************************************************************************
 * (c) Copyright 2009 Actel Corporation.  All rights reserved.
 *
 *  Application demo for Smartfusion
 *
 *
 * Author : Actel Application Team
 * Rev     : 1.0.0.3
 *
 **************************************************************************/

/**************************************************************************/
/* Standard Includes */
/**************************************************************************/

#include <stdio.h>
#include <stdlib.h>

/**************************************************************************/
/* Driver Includes */
/**************************************************************************/

#include "../drivers/mss_ace/mss_ace.h"
#include "mss_ace_configurator.h"
#include "../../CMSIS/a2fxxxm3.h"
#include "../../CMSIS/mss_assert.h"
#include "../../drivers_config/mss_ace/ace_handles.h"
#include "../../drivers_config/mss_ace/ace_config.h"

/**************************************************************************/
/* RTOS Includes */
/**************************************************************************/


extern ace_channel_desc_t g_ace_channel_desc_table[ACE_NB_OF_INPUT_CHANNELS];
extern ace_adc_config_t g_ace_adc_config[ACE_NB_OF_ADC];
extern const uint32_t g_ace_current_resistors[ACE_NB_OF_CURRENT_MONITORS];

#define VOLTAGE_CHANNEL     0u
#define CURRENT_CHANNEL     1u
#define TEMPERATURE_CHANNEL 2u
#define INVALID_CHANNEL     0xFFu

/**************************************************************************/
/* Global Declarations */
/**************************************************************************/

float                            real_voltage_value;
float                            real_current_value;
float                            real_temperature_value;
float                            real_temperature_value_tc;
float                            real_temperature_value_tk;
float                            real_temperature_value_tf;

static const uint8_t channel_type_lut[] =
{
    VOLTAGE_CHANNEL,        /* ADC0_1P5V = 0 */
    VOLTAGE_CHANNEL,        /* ABPS0 = 1 */
    VOLTAGE_CHANNEL,        /* ABPS1 = 2 */
    CURRENT_CHANNEL,        /* CM0 = 3 */
    TEMPERATURE_CHANNEL,    /* TM0 = 4 */
    VOLTAGE_CHANNEL,        /* ABPS2 = 5 */
    VOLTAGE_CHANNEL,        /* ABPS3 = 6 */
    CURRENT_CHANNEL,        /* CM1 = 7 */
    TEMPERATURE_CHANNEL,    /* TM1 = 8 */
    VOLTAGE_CHANNEL,        /* ADC0 = 9 */
    VOLTAGE_CHANNEL,        /* ADC1 = 10 */
    VOLTAGE_CHANNEL,        /* ADC2 = 11 */
    VOLTAGE_CHANNEL,        /* ADC3 = 12 */
    INVALID_CHANNEL,
    INVALID_CHANNEL,
    VOLTAGE_CHANNEL,        /* SDD0_IN = 15 */

    VOLTAGE_CHANNEL,        /* ADC1_1P5V = 16 */
    VOLTAGE_CHANNEL,        /* ABPS4 = 17 */
    VOLTAGE_CHANNEL,        /* ABPS5 = 18 */
    CURRENT_CHANNEL,        /* CM2 = 19 */
    TEMPERATURE_CHANNEL,    /* TM2 = 20 */
    VOLTAGE_CHANNEL,        /* ABPS6 = 21 */
    VOLTAGE_CHANNEL,        /* ABPS7 = 22 */
    CURRENT_CHANNEL,        /* CM3 = 23 */
    TEMPERATURE_CHANNEL,    /* TM3 = 24 */
    VOLTAGE_CHANNEL,        /* ADC4 = 25 */
    VOLTAGE_CHANNEL,        /* ADC5 = 26 */
    VOLTAGE_CHANNEL,        /* ADC6 = 27 */
    VOLTAGE_CHANNEL,        /* ADC7 = 28 */
    INVALID_CHANNEL,
    INVALID_CHANNEL,
    VOLTAGE_CHANNEL,        /* SDD1_IN = 31 */

    VOLTAGE_CHANNEL,        /* ADC2_1P5V = 32 */
    VOLTAGE_CHANNEL,        /* ABPS8 = 33 */
    VOLTAGE_CHANNEL,        /* ABPS9 = 34 */
    CURRENT_CHANNEL,        /* CM4 = 35 */
    TEMPERATURE_CHANNEL,    /* TM4 = 36 */
    VOLTAGE_CHANNEL,        /* ABPS10 = 37 */
    VOLTAGE_CHANNEL,        /* ABPS11 = 38 */
    CURRENT_CHANNEL,        /* CM5 = 39 */
    TEMPERATURE_CHANNEL,    /* TM5 = 40 */
    VOLTAGE_CHANNEL,        /* ADC8 = 41 */
    VOLTAGE_CHANNEL,        /* ADC9 = 42 */
    VOLTAGE_CHANNEL,        /* ADC10 = 43 */
    VOLTAGE_CHANNEL,        /* ADC11 = 44 */
    INVALID_CHANNEL,
    INVALID_CHANNEL,
    VOLTAGE_CHANNEL         /* SDD2_IN = 47 */
};

/****************************************************************/
/* Function converts a PPE sample value into micro-amps.
   The result of the conversion is only meaningful if the PPE sample value
   results from the conversion of a current monitor input.*/
/****************************************************************/

uint32_t ACE_convert_to_uA
(
    ace_channel_handle_t    channel_handle,
    uint16_t                sample_value
)
{
    uint32_t current = 0u;

    ASSERT(channel_handle < ACE_NB_OF_INPUT_CHANNELS);

    if((int32_t)channel_handle < ACE_NB_OF_INPUT_CHANNELS)
    {
        adc_channel_id_t channel_id;
        uint8_t current_monitor_idx;

        channel_id = g_ace_channel_desc_table[channel_handle].signal_id;
        ASSERT(channel_id < sizeof(channel_type_lut));
        if(CURRENT_CHANNEL == channel_type_lut[channel_id])
        {
            uint32_t resistor;
            uint32_t voltage;

            /* Compute index into g_ace_current_resistors[] from the current
             * channel number. This uses bit 2, 4 and 5 of the channel number
             * to derive the index as follows:
             *  channel name : channel number : index
             *       CM0     :       0x03     :   0
             *       CM1     :       0x07     :   1
             *       CM2     :       0x13     :   2
             *       CM3     :       0x17     :   3
             *       CM4     :       0x23     :   4
             *       CM5     :       0x27     :   5
             */
            current_monitor_idx
                = (((uint8_t)channel_id & 0x04u) >> 2u) + (((uint8_t)channel_id & 0x30u) >> 3u);

            if(current_monitor_idx < (uint8_t)ACE_NB_OF_CURRENT_MONITORS)
            {
                /* Retrieve the current sensing external resistor value from
                 * the ACE configuration data generated by the ACE configurator. */
                resistor = g_ace_current_resistors[current_monitor_idx];

                /* Compute mA current value taking into account the amplication
                 * factor of 50 used within the current monitor hardware. */
                voltage = ACE_convert_adc_input_to_mV(channel_handle, sample_value);
                current = (voltage * (1000000u / 50u)) / resistor;
;
            }
        }
    }

    return current;
}

/****************************************************************/
/* Analog test */
/* Function to update global variable related ACE values */
/****************************************************************/
void update_ace_values( ace_channel_handle_t channel_handle,
     uint16_t raw_value )
{
    channel_type_t channel_type;
    channel_type = ACE_get_channel_type( channel_handle );

    switch(channel_type)
    {
        case VOLTAGE:
            real_voltage_value =  (float)ACE_convert_to_mV( channel_handle,
                                                            raw_value )/(float)1000;
            break;

        case CURRENT:
            real_current_value = (float)ACE_convert_to_uA( channel_handle,
                                                           raw_value );
            break;

        case TEMPERATURE:
            real_temperature_value_tk = (float)ACE_convert_to_Kelvin( channel_handle,
                                                                      raw_value );
            real_temperature_value_tf = (float)ACE_convert_to_Fahrenheit( channel_handle,
                                                                          raw_value );
            real_temperature_value_tc = (float)ACE_convert_to_Celsius( channel_handle,
                                                                       raw_value )/(float)10;
            break;

        default:
            break;
    }

}

/****************************************************************/
/* Creating ACE task for free RTOS */
/****************************************************************/

void ace_task(void *para)
{
    uint16_t adc_result;
    for (;;)
    {
        ace_channel_handle_t first_channel;
        ace_channel_handle_t current_channel;
        /*
         * Display all configured channels current sampled value.
        */

        current_channel = ACE_get_first_channel();
        first_channel = current_channel;
        do
        {
            adc_result = ACE_get_ppe_sample( current_channel );
            update_ace_values( current_channel, adc_result );
            current_channel = ACE_get_next_channel( current_channel );
        } while ( current_channel != first_channel );
    }
}



