/*******************************************************************************
* FILE NAME: etpu_asac.c            COPYRIGHT (c) Freescale Semiconductor 2005
*                                               All Rights Reserved
* DESCRIPTION:
* This file contains the eTPU Analog Sensing for AC motors (ASAC) function API.
*===============================================================================
* REV      AUTHOR      DATE        DESCRIPTION OF CHANGE
* ---   -----------  ----------    ---------------------
* 2.0   M.Princ      02/Sep/05     Initial version derived from ASDC function.
* 2.1   M.Princ      01/Dec/05     eQADC command queue definition added,
*                                  DMA request and interrupt to CPU on the first
*                                  and the second edge option added.
* 2.2   M.Princ      25/Feb/09     Bug correction in fs_etpu_asac_get_outputX
* 2.3   M.Brejl      12/Jan/10     64 added to channel number for link usage.
* 2.4   M.Brejl      18/Jan/12     ASAC output is 50% duty-cycle PWM.
*                                  Option negate_phase_currents added. 
*******************************************************************************/
#include "etpu_util.h"          /* Utility routines for working with the eTPU */
#include "etpu_asac.h"          /* eTPU ASAC API */

extern uint32_t fs_etpu_data_ram_start;
extern uint32_t fs_etpu_data_ram_ext;

/*******************************************************************************
* NAME:        : fs_etpu_asac_init
* PURPOSE      : This routine is used to initialize the eTPU channel
*                for the ASAC function.
*
* INPUTS NOTES : This function has the following parameters:
*   channel               - This is the ASAC channel number.
*                           0-31 for ETPU_A and 64-95 for ETPU_B.
*   priority              - This is the priority to assign to the ASAC function.
*                           This parameter should be assigned a value of:
*                           FS_ETPU_PRIORITY_HIGH,
*                           FS_ETPU_PRIORITY_MIDDLE,
*                           FS_ETPU_PRIORITY_LOW or
*                           FS_ETPU_PRIORITY_DISABLED.
*   polarity              - This is the polarity of the ASAC output.
*                           This parameter should be assigned a value of:
*                           FS_ETPU_ASAC_PULSE_HIGH or
*                           FS_ETPU_ASAC_PULSE_LOW.
*   mode                  - Mode configuration parameter.
*                           This parameter should be assigned a values of:
*                           FS_ETPU_ASAC_MODE_PERIODIC or
*                           FS_ETPU_ASAC_MODE_SYNC.
*   measure_samples_mask  - This parameter defines which measured samples are
*                           processed by ASAC function.
*                           This parameter should be assigned a values of:
*                           FS_ETPU_ASAC_SAMPLE_A_B_C (phase currents) or
*                           FS_ETPU_ASAC_SAMPLE_D (DC_BUS voltage) or
*                           FS_ETPU_ASAC_SAMPLE_A_B_C_D.
*   DTC_option            - This parameter turns on/off the dead-time
*                           compensation. This parameter should be assigned 
*                           a value of:
*                           FS_ETPU_ASAC_DTC_OFF or
*                           FS_ETPU_ASAC_DTC_ON.
*   phase_current_option  - This parameter defines processing of phase currents.
*                           All 3 phase currents (smaples a, b, c) might be used,
*                           or 3rd current might be calculated from 2 measured currents.
*                           In this case, the calculated current can be a fixed one,
*                           or dependent on the actual rotor position in one of 6
*                           sectors. The PWMMAC function provides the sector value.
*                           This parameter should be assigned a value of:
*                           FS_ETPU_ASAC_PHASE_CURR_USE_ALL
*                           FS_ETPU_ASAC_PHASE_CURR_USE_AB_CALC_C
*                           FS_ETPU_ASAC_PHASE_CURR_USE_BC_CALC_A
*                           FS_ETPU_ASAC_PHASE_CURR_USE_CA_CALC_B
*                           FS_ETPU_ASAC_PHASE_CURR_USE_SECTOR
*   negate_phase_currents - This parameter turns on/off negation of measured phase 
*                           currents.
*                           This parameter should be assigned a value of:
*                           FS_ETPU_ASAC_PHASE_CURRENTS_POS or
*                           FS_ETPU_ASAC_PHASE_CURRENTS_NEG
*   cfifo_update          - This parameter enables the ASAC eTPU functions to modify order
*                           of ADC commands according to actual PWMMAC sector value.
*                           This parameter should be assigned a values of:
*                           FS_ETPU_ASAC_CFIFO_UPDATE_ON
*                           FS_ETPU_ASAC_CFIFO_UPDATE_OFF
*   DMA_interrupt_option  - This parameter defines whether the DMA request and
*                           the interrupt to CPU are generated on the first ASAC
*                           edge (DMA_interrupt_option=FS_ETPU_ASAC_DMA_INTR_ON_FIRST_EDGE)
*                           or on the second ASAC edge
*                           (DMA_interrupt_option=FS_ETPU_ASAC_DMA_INTR_ON_SECOND_EDGE).
*   period                - This is the ASAC period, as number of
*                           TCR1 clocks.
*   start_offset          - This parameter is used to synchronize various
*                           eTPU functions that generate a signal. For ASAC,
*                           the first pulse starts the start_offset TCR1 clocks
*                           after initialization.
*                           This parameter applies in the Periodic Mode only
*                           (mode=FS_ETPU_ASAC_MODE_PERIODIC).
*   egde_offset           - Offset, either positive or negative, between 
*                           PWM period edge_times and the ASAC pulse
*                           first edge as number of TCR1 clocks.
*                           This parameter applies in the Synchronized Mode only
*                           (mode = FS_ETPU_ASAC_MODE_SYNC).
*   PWMMAC_chan           - PWMMAC channel number from which the PWM edge_times
*                           are taken.
*                           This parameter applies in the Synchronized Mode
*                           only (mode=FS_ETPU_ASAC_MODE_SYNC).
*   measure_time          - Time from the first (triggering) edge to the second
*                           edge, at which the result queue is supposed to be
*                           ready in the DATA_RAM (in TCR1 clocks).
*   periods_per_outerloop - A link service request is generated to the
*                           outerloop_chan each periods_per_outerloop period.
*   SC_BC_outerloop_chan  - Number of a channel on which an outer-loop
*                           controller (in Slave Mode) runs. In order not to
*                           activate any inner-loop controller, set a number of
*                           a channel with priority disabled. This parameter
*                           should be assigned a value of
*                           0-31 for ETPU_A and of 64-95 for ETPU_B.
*   PMSMVC_ACIMVC_innerloop_chan - Number of a channel on which an inner-loop
*                           controller (in Slave Mode) runs. In order not to
*                           activate any inner-loop controller, set a number of
*                           a channel with priority disabled. This parameter
*                           should be assigned a value of
*                           0-31 for ETPU_A and of 64-95 for ETPU_B.
*   result_queue          - Pointer to the result queue. Result queue is an
*                           array of 16-bit words that contains the measured
*                           values.
*   queue_offset_a        - Sample A position in the result queue - offset in
*                           bytes.
*   queue_offset_b        - Sample B position in the result queue - offset in
*                           bytes.
*   queue_offset_c        - Sample C position in the result queue - offset in
*                           bytes.
*   queue_offset_d        - Sample D position in the result queue - offset in
*                           bytes.
*   forget_factor_a       - EWMA filter "Forgetting Factor" applied to sample A.
*                           This parameter must be a value between 0 and 1,
*                           usually close to 1,
*                           assigned in fract24 (Maximum 0x7FFFFF).
*   forget_factor_b       - EWMA filter "Forgetting Factor" applied to sample B.
*                           This parameter must be a value between 0 and 1,
*                           usually close to 1,
*                           assigned in fract24 (Maximum 0x7FFFFF).
*   forget_factor_c       - EWMA filter "Forgetting Factor" applied to sample C.
*                           This parameter must be a value between 0 and 1,
*                           usually close to 1,
*                           assigned in fract24 (Maximum 0x7FFFFF).
*   forget_factor_d       - EWMA filter "Forgetting Factor" applied to sample D.
*                           This parameter must be a value between 0 and 1,
*                           usually close to 1,
*                           assigned in fract24 (Maximum 0x7FFFFF).
*   bit_shift             - This parameter defines how to align data from the
*                           result queue into fract24 (or int24).
*                           This parameter should be assigned a values of:
*                           FS_ETPU_ASAC_SHIFT_LEFT_BY_8,
*                           FS_ETPU_ASAC_SHIFT_LEFT_BY_10,
*                           FS_ETPU_ASAC_SHIFT_LEFT_BY_12 or
*                           FS_ETPU_ASAC_SHIFT_LEFT_BY_16.
*   dtc_threshold         - This parameter defines the threshold of dead-time 
*                           compensation states. This parameter must be a value 
*                           between 0 and 1. This parameter applies only if 
*                           DTC_option is set to 
*                           FS_ETPU_ASAC_DTC_ON.
*   outputA_chan          - This is the number of the channel that requires
*                           processed sample_A. (ASAC output_a receiver.)
*   outputA_offset        - This parameter defines the processed sample_A offset
*                           in the scope of outputA_chan function parameters.
*   outputB_chan          - This is the number of the channel that requires
*                           processed sample_B. (ASAC output_b receiver.)
*   outputB_offset        - This parameter defines the processed sample_B offset
*                           in scope of outputB_chan function parameters.
*   outputC_chan          - This is the number of the channel that requires
*                           processed sample_C. (ASAC output_c receiver.)
*   outputC_offset        - This parameter defines the processed sample_C offset
*                           in the scope of outputC_chan function parameters.
*   outputD1_chan         - This is the number of the first channel that requires
*                           processed sample_D. (ASAC output_d receiver1.)
*   outputD1_offset       - This parameter defines the processed sample_D offset
*                           in the scope of outputD1_chan function parameters.
*   outputD2_chan         - This is the number of the second channel that requires
*                           processed sample_D. (ASAC output_d receiver2.)
*   outputD2_offset       - This parameter defines the processed sample_D offset
*                           in the scope of outputD2_chan function parameters.
*   eQADC_cmds_number     - The total number of eQADC conversion commands,
*                           which should be sent through eDMA to eQADC 
*                           when the first trigering ASAC edge occurs.
*  *eQADC_cmds_current_measurements - Pointer to the table of eQADC conversion 
*                           commands for current measurement.
*  *eQADC_cmds_other_measurements - Pointer to the table of eQADC conversion 
*                           commands for measurement of other quantities
*                           (DC_BUS voltage, BackEMF, temperature).
*
* RETURNS NOTES: Error codes which can be returned are: FS_ETPU_ERROR_VALUE,
*                FS_ETPU_ERROR_MALLOC
*                
* PROJECT NOTES: Analog Sensing for AC Motors (ASAC) function is configured
*                to process analog sample value(s) available at eTPU DATA RAM 
*                address %valueof(result_queue)% (value of the result_queue
*                parameter). An AD converter, optionally triggered by ASAC
*                output signal, must sample the analog signal(s), and the 
*                converted value(s) must be written, preferably by DMA, 
*                to address %valueof(result_queue)%. <br>
*                <font color=red>The configuration of DMA channels and other 
*                necessary peripherals must be performed separately from eTPU 
*                configuration!</font>
*******************************************************************************/
int32_t fs_etpu_asac_init( uint8_t    channel,
                           uint8_t    priority,
                           uint8_t    polarity,
                           uint8_t    mode,
                           uint8_t    measure_samples_mask,
                           uint8_t    DTC_option,
                           uint8_t    phase_current_option,
                           uint8_t    negate_phase_currents,
                           uint8_t    cfifo_update,
                           uint8_t    DMA_interrupt_option,
                           uint24_t   period,
                           uint24_t   start_offset,
                           int24_t    egde_offset,
                           uint8_t    PWMMAC_chan,
                           uint24_t   measure_time,
                           uint8_t    periods_per_outerloop,
                           uint8_t    SC_BC_outerloop_chan,
                           uint8_t    PMSMVC_ACIMVC_innerloop_chan,
                           uint32_t * result_queue,
                           uint8_t    queue_offset_a,
                           uint8_t    queue_offset_b,
                           uint8_t    queue_offset_c,
                           uint8_t    queue_offset_d,
                           fract24_t  forget_factor_a,
                           fract24_t  forget_factor_b,
                           fract24_t  forget_factor_c,
                           fract24_t  forget_factor_d,
                           uint8_t    bit_shift,
                           fract24_t  dtc_threshold,
                           uint8_t    outputA_chan,
                           uint16_t   outputA_offset,
                           uint8_t    outputB_chan,
                           uint16_t   outputB_offset,
                           uint8_t    outputC_chan,
                           uint16_t   outputC_offset,
                           uint8_t    outputD1_chan,
                           uint16_t   outputD1_offset,
                           uint8_t    outputD2_chan,
                           uint16_t   outputD2_offset,
                           uint8_t    eQADC_cmds_number,
             etpu_asac_eQADC_cmds_t * eQADC_cmds_current_measurements,
                           uint32_t * eQADC_cmds_other_measurements)
{

   uint32_t * pba;            /* Parameter base address for ASAC channel. */
   uint32_t * pba_eQADC_cmds; /* Parameter base address for eQADC commands. */

   /****************************************
    * Parameters bounds check.
    ***************************************/
   #ifdef FS_ETPU_MC_PARAM_CHECK
      if(((channel>31)&&(channel<64))||(channel>95)||
          (priority>FS_ETPU_PRIORITY_HIGH)||
          (polarity > FS_ETPU_ASAC_PULSE_LOW )||
          (mode>FS_ETPU_ASAC_MODE_SYNC)||
          (DTC_option>FS_ETPU_ASAC_DTC_ON)||
          (phase_current_option>FS_ETPU_ASAC_PHASE_CURR_USE_SECTOR)||
          (DMA_interrupt_option>FS_ETPU_ASAC_DMA_INTR_ON_SECOND_EDGE)||
          ((SC_BC_outerloop_chan>31)&&(SC_BC_outerloop_chan<64))||(SC_BC_outerloop_chan>95)||
          ((PMSMVC_ACIMVC_innerloop_chan>31)&&(PMSMVC_ACIMVC_innerloop_chan<64))||(PMSMVC_ACIMVC_innerloop_chan>95)||
          (measure_samples_mask>FS_ETPU_ASAC_SAMPLE_A_B_C_D)||
          (bit_shift>FS_ETPU_ASAC_SHIFT_LEFT_BY_16)||
          (cfifo_update>FS_ETPU_ASAC_CFIFO_UPDATE_ON)||
          ((PWMMAC_chan>31)&&(PWMMAC_chan<64))||(PWMMAC_chan>95)||
          ((outputA_chan>31)&&(outputA_chan<64))||(outputA_chan>95)||
          ((outputB_chan>31)&&(outputB_chan<64))||(outputB_chan>95)||
          ((outputC_chan>31)&&(outputC_chan<64))||(outputC_chan>95)||
          ((outputD1_chan>31)&&(outputD1_chan<64))||(outputD1_chan>95)||
          ((outputD2_chan>31)&&(outputD2_chan<64))||(outputD2_chan>95))
      {
          return(FS_ETPU_ERROR_VALUE);
      }
   #endif

   /****************************************
    * PRAM allocation.
    ***************************************/
   if (((pba=fs_etpu_malloc(FS_ETPU_ASAC_NUM_PARMS))== 0))
   {
       return(FS_ETPU_ERROR_MALLOC);
   }

   if (((pba_eQADC_cmds=fs_etpu_malloc(4*eQADC_cmds_number))== 0))
   {
       return(FS_ETPU_ERROR_MALLOC);
   }

   /****************************************
    * Write chan config register.
    ***************************************/
   eTPU->CHAN[channel].CR.R = (FS_ETPU_ASAC_TABLE_SELECT << 24) +
                              (FS_ETPU_ASAC_FUNCTION_NUMBER << 16) +
                              (((uint32_t)pba - fs_etpu_data_ram_start) >> 3);
   eTPU->CHAN[channel].SCR.R = DTC_option;
   if (phase_current_option != FS_ETPU_ASAC_PHASE_CURR_USE_ALL)
   {
      eTPU->CHAN[channel].SCR.R |= FS_ETPU_ASAC_FM_PHASE_CURRENTS_ON;
   }
      
   /****************************************
    * Write parameters.
    ***************************************/
   if (mode == FS_ETPU_ASAC_MODE_SYNC)
   {
      start_offset = (uint24_t)egde_offset;
      *(pba + ((FS_ETPU_ASAC_P_EDGE_TIME_OFFSET - 1)>>2)) =
                    (uint24_t)((eTPU->CHAN[PWMMAC_chan].CR.B.CPBA << 3) +
                    FS_ETPU_PWMMAC_EDGETIME_OFFSET);
   }

   *(pba + ((FS_ETPU_ASAC_PERIOD_OFFSET - 1)>>2)) = (uint24_t)period;
   *(pba + ((FS_ETPU_ASAC_START_OFFSET_OFFSET - 1)>>2)) = (uint24_t)start_offset;
   *(pba + ((FS_ETPU_ASAC_MEASURE_TIME_OFFSET - 1)>>2)) = (uint24_t)measure_time;
   *(pba + ((FS_ETPU_ASAC_PERIODS_PER_OUTERLOOP_OFFSET - 1)>>2)) = (uint24_t)periods_per_outerloop;
   *(pba + ((FS_ETPU_ASAC_RESULT_QUEUE_OFFSET - 1)>>2)) = ((uint32_t)result_queue) & 0x1FFF;
   *(pba + ((FS_ETPU_ASAC_BIT_SHIFT_OFFSET - 1)>>2)) = (uint24_t)bit_shift;
   *(pba + ((FS_ETPU_ASAC_DC_OFFSET_A_OFFSET - 1)>>2)) = 0;
   *(pba + ((FS_ETPU_ASAC_DC_OFFSET_B_OFFSET - 1)>>2)) = 0;
   *(pba + ((FS_ETPU_ASAC_DC_OFFSET_C_OFFSET - 1)>>2)) = 0;
   *(pba + ((FS_ETPU_ASAC_DC_OFFSET_D_OFFSET - 1)>>2)) = 0;
   *(pba + ((FS_ETPU_ASAC_OUTPUT_A_OFFSET - 1)>>2)) = 0;
   *(pba + ((FS_ETPU_ASAC_OUTPUT_B_OFFSET - 1)>>2)) = 0;
   *(pba + ((FS_ETPU_ASAC_OUTPUT_C_OFFSET - 1)>>2)) = 0;
   *(pba + ((FS_ETPU_ASAC_OUTPUT_D_OFFSET - 1)>>2)) = 0;
   *(pba + ((FS_ETPU_ASAC_P_OUTPUT_A_OFFSET - 1)>>2)) = 0;
   *(pba + ((FS_ETPU_ASAC_P_OUTPUT_B_OFFSET - 1)>>2)) = 0;
   *(pba + ((FS_ETPU_ASAC_P_OUTPUT_C_OFFSET - 1)>>2)) = 0;
   *(pba + ((FS_ETPU_ASAC_P_OUTPUT_D1_OFFSET - 1)>>2)) = 0;
   *(pba + ((FS_ETPU_ASAC_P_OUTPUT_D2_OFFSET - 1)>>2)) = 0;
   *(pba + ((FS_ETPU_ASAC_FORGET_FACTOR_A_OFFSET - 1)>>2)) = 0;
   *(pba + ((FS_ETPU_ASAC_FORGET_FACTOR_B_OFFSET - 1)>>2)) = 0;
   *(pba + ((FS_ETPU_ASAC_FORGET_FACTOR_C_OFFSET - 1)>>2)) = 0;
   *(pba + ((FS_ETPU_ASAC_FORGET_FACTOR_D_OFFSET - 1)>>2)) = 0;
   *(pba + ((FS_ETPU_ASAC_P_APPLIED_EQADC_CMDS_OFFSET - 1)>>2)) = (uint24_t) ((uint32_t)pba_eQADC_cmds - fs_etpu_data_ram_start);
   
   if (eQADC_cmds_current_measurements)
   {
      fs_memcpy32((uint32_t *)((uint8_t *)pba + FS_ETPU_ASAC_ADC0_I_A_CMD_OFFSET),
                  (uint32_t *)eQADC_cmds_current_measurements, 24);
      *(pba_eQADC_cmds + 0) = eQADC_cmds_current_measurements->ADC0_iA_cmd;
      *(pba_eQADC_cmds + 1) = eQADC_cmds_current_measurements->ADC1_iB_cmd;
      *(pba_eQADC_cmds + 2) = eQADC_cmds_current_measurements->ADC0_iC_cmd;
   }

   if (eQADC_cmds_other_measurements)
   {
      if (eQADC_cmds_current_measurements) 
      {
         fs_memcpy32((uint32_t *)((uint8_t *)pba_eQADC_cmds + 0xC),
                     (uint32_t *)eQADC_cmds_other_measurements, ((eQADC_cmds_number*4) - 0xC));
      } 
      else
      {
         fs_memcpy32((uint32_t *)((uint8_t *)pba_eQADC_cmds),
                     (uint32_t *)eQADC_cmds_other_measurements, (eQADC_cmds_number*4));
      }
   }

   if (measure_samples_mask & FS_ETPU_ASAC_SAMPLE_A_B_C)
   {
      *(pba + ((FS_ETPU_ASAC_P_OUTPUT_A_OFFSET - 1)>>2)) = (uint24_t) ((eTPU->CHAN[outputA_chan].CR.B.CPBA << 3) + outputA_offset);
      *(pba + ((FS_ETPU_ASAC_P_OUTPUT_B_OFFSET - 1)>>2)) = (uint24_t) ((eTPU->CHAN[outputB_chan].CR.B.CPBA << 3) + outputB_offset);
      *(pba + ((FS_ETPU_ASAC_P_OUTPUT_C_OFFSET - 1)>>2)) = (uint24_t) ((eTPU->CHAN[outputC_chan].CR.B.CPBA << 3) + outputC_offset);
      *(pba + ((FS_ETPU_ASAC_FORGET_FACTOR_A_OFFSET - 1)>>2)) = (uint24_t)forget_factor_a;
      *(pba + ((FS_ETPU_ASAC_FORGET_FACTOR_B_OFFSET - 1)>>2)) = (uint24_t)forget_factor_b;
      *(pba + ((FS_ETPU_ASAC_FORGET_FACTOR_C_OFFSET - 1)>>2)) = (uint24_t)forget_factor_c;
   }
   if (measure_samples_mask & FS_ETPU_ASAC_SAMPLE_D)
   {
      *(pba + ((FS_ETPU_ASAC_P_OUTPUT_D1_OFFSET - 1)>>2)) = (uint24_t) ((eTPU->CHAN[outputD1_chan].CR.B.CPBA << 3) + outputD1_offset);
      *(pba + ((FS_ETPU_ASAC_P_OUTPUT_D2_OFFSET - 1)>>2)) = (uint24_t) ((eTPU->CHAN[outputD2_chan].CR.B.CPBA << 3) + outputD2_offset);
      *(pba + ((FS_ETPU_ASAC_FORGET_FACTOR_D_OFFSET - 1)>>2)) = (uint24_t)forget_factor_d;
   }   
   
   /* if DTC is on */
   if ( (eTPU->CHAN[channel].SCR.R) & FS_ETPU_ASAC_FM_DTC_ON )
   {
      *(pba + ((FS_ETPU_ASAC_P_DTC_A_OFFSET - 1)>>2)) = (uint24_t) ((eTPU->CHAN[PWMMAC_chan].CR.B.CPBA << 3) + FS_ETPU_PWMMAC_PHASEA_OFFSET + FS_ETPU_PWMF_DTC_OFFSET);
      *(pba + ((FS_ETPU_ASAC_P_DTC_B_OFFSET - 1)>>2)) = (uint24_t) ((eTPU->CHAN[PWMMAC_chan].CR.B.CPBA << 3) + FS_ETPU_PWMMAC_PHASEB_OFFSET + FS_ETPU_PWMF_DTC_OFFSET);
      *(pba + ((FS_ETPU_ASAC_P_DTC_C_OFFSET - 1)>>2)) = (uint24_t) ((eTPU->CHAN[PWMMAC_chan].CR.B.CPBA << 3) + FS_ETPU_PWMMAC_PHASEC_OFFSET + FS_ETPU_PWMF_DTC_OFFSET);
      *(pba + ((FS_ETPU_ASAC_DTC_THRESHOLD_OFFSET - 1)>>2)) = (uint24_t)dtc_threshold;
   }															

   /* if 2 out of 3 phase currents are measured */
   if ( (eTPU->CHAN[channel].SCR.R) & FS_ETPU_ASAC_FM_PHASE_CURRENTS_ON )
   {
      if ( phase_current_option == FS_ETPU_ASAC_PHASE_CURR_USE_SECTOR )
      {
         *(pba + ((FS_ETPU_ASAC_P_PWMMAC_SECTOR_OFFSET - 1)>>2)) = (uint24_t) ((eTPU->CHAN[PWMMAC_chan].CR.B.CPBA << 3) + FS_ETPU_PWMMAC_SECTOR_OFFSET);
      }
      else
      {
         *((uint8_t*)pba + FS_ETPU_ASAC_SECTOR_PLACE_HOLDER_OFFSET) = phase_current_option;
         *(pba + ((FS_ETPU_ASAC_P_PWMMAC_SECTOR_OFFSET - 1)>>2)) = (uint24_t) ((eTPU->CHAN[channel].CR.B.CPBA << 3) + FS_ETPU_ASAC_SECTOR_PLACE_HOLDER_OFFSET);
      }
   }

   *((uint8_t*)pba + FS_ETPU_ASAC_OUTERLOOP_CHAN_OFFSET) = SC_BC_outerloop_chan + 64;
   *((uint8_t*)pba + FS_ETPU_ASAC_INNERLOOP_CHAN_OFFSET) = PMSMVC_ACIMVC_innerloop_chan + 64;
   *((uint8_t*)pba + FS_ETPU_ASAC_QUEUE_OFFSET_A_OFFSET) = queue_offset_a;
   *((uint8_t*)pba + FS_ETPU_ASAC_QUEUE_OFFSET_B_OFFSET) = queue_offset_b;
   *((uint8_t*)pba + FS_ETPU_ASAC_QUEUE_OFFSET_C_OFFSET) = queue_offset_c;
   *((uint8_t*)pba + FS_ETPU_ASAC_QUEUE_OFFSET_D_OFFSET) = queue_offset_d;
   *((uint8_t*)pba + FS_ETPU_ASAC_MEASURE_SAMPLES_MASK_OFFSET) = measure_samples_mask;
   *((uint8_t*)pba + FS_ETPU_ASAC_SECTOR_OFFSET) = 0;
   *((uint8_t*)pba + FS_ETPU_ASAC_OPTIONS_OFFSET) = DMA_interrupt_option;
   if (negate_phase_currents == FS_ETPU_ASAC_PHASE_CURRENTS_NEG)
   {
       *((uint8_t*)pba + FS_ETPU_ASAC_OPTIONS_OFFSET) |= FS_ETPU_ASAC_PHASE_CURRENTS_NEG;
   }
   if (cfifo_update == FS_ETPU_ASAC_CFIFO_UPDATE_ON)
   {
       *((uint8_t*)pba + FS_ETPU_ASAC_OPTIONS_OFFSET) |= FS_ETPU_ASAC_OPTION_UPDATE_COMMAND_QUEUE;
   }
   if (polarity == FS_ETPU_ASAC_PULSE_LOW) 
   {
       *((uint8_t*)pba + FS_ETPU_ASAC_OPTIONS_OFFSET) |= FS_ETPU_ASAC_OPTION_POLARITY_1ST_LOW_2ND_HIGH;
   }

   /****************************************
    * Write HSR.
    ***************************************/
   if ( mode == FS_ETPU_ASAC_MODE_PERIODIC )
      eTPU->CHAN[channel].HSRR.R = FS_ASAC_HSR_INIT_PERIOD_MODE;
   else
      eTPU->CHAN[channel].HSRR.R = FS_ASAC_HSR_INIT_SYNC_MODE;

   /****************************************
    * Set channel priority and enable.
    ***************************************/
   fs_etpu_enable(channel, priority);

   return(0);
}

/*******************************************************************************
* NAME:        : fs_etpu_asac_measure_dc_offsets
* PURPOSE      : This function enables to set the dc_offsets by measuring.
*
* INPUTS NOTES : This function has the following parameters:
*   channel                - This is the ASAC channel number.
*                            This parameter must be assigned the same value
*                            as the channel parameter of the initialization
*                             function was assigned.
*   measure_dc_offset_mask - This parameter determines which samples can be
*                            used as dc_offsets. This parameter should be
*                            assigned by a values of:
*                            FS_ETPU_ASAC_DC_OFFSET_SAMPLE_A_B_C,
*                            FS_ETPU_ASAC_DC_OFFSET_SAMPLE_D or
*                            FS_ETPU_ASAC_DC_OFFSET_SAMPLE_A_B_C_D.
*
*RETURNS NOTES: This function returns 0 if DC offset(s) was successfully
*               measured. In case ASAC channel has any pending HSRs DC offset(s)
*               are not set and this function should be called again later.
*               In this case a sum of pending HSR numbers is returned.
*               Error code that can be returned is: FS_ETPU_ERROR_VALUE.
*******************************************************************************/
int32_t fs_etpu_asac_measure_dc_offsets(uint8_t channel,
                                        int8_t  measure_dc_offsets_mask)
{
   uint32_t  hsrr;

   /****************************************
    * Parameters bounds check.
    ***************************************/
   #ifdef FS_ETPU_MC_PARAM_CHECK
      if(((channel>31)&&(channel<64))||(channel>95)||
         (measure_dc_offsets_mask>FS_ETPU_ASAC_DC_OFFSET_SAMPLE_A_B_C_D))
      {
          return(FS_ETPU_ERROR_VALUE);
      }
   #endif

  /****************************************
   * Write parameters.
   ***************************************/
  fs_etpu_set_chan_local_8(channel, FS_ETPU_ASAC_MEASURE_DC_OFFSET_MASK_OFFSET,
                           (uint8_t)measure_dc_offsets_mask);

  /****************************************
   * Write HSR.
   ***************************************/
  /* if ASAC channel has any pending HSRs do not write new HSRs but return
     sum of pending HSR numbers */
  hsrr = eTPU->CHAN[channel].HSRR.R;
  if (hsrr != 0) return ((int32_t)hsrr);
  
  eTPU->CHAN[channel].HSRR.R = FS_ASAC_HSR_MEASURE_DC_OFFSETS;

  return(0);
}

/*******************************************************************************
* NAME:        : fs_etpu_asac_set_dc_offsets_ABCD
* PURPOSE      : This function enables to set the dc_offsets of samples A,B,C,D 
*                by values.
*
* INPUTS NOTES : This function has the following parameters:
*   channel           - This is the ASAC channel number.
*                       This parameter must be assigned the same value
*                       as the channel parameter of the initialization
*                       function was assigned.
*   dc_offset_a       - This parameter is the DC offset to remove from sample A.
*                       The DC offset must be in the same format as the
*                       sample - after the bit allignment.
*   dc_offset_b       - This parameter is the DC offset to remove from sample B.
*                       The DC offset must be in the same format as the
*                       sample - after the bit allignment.
*   dc_offset_c       - This parameter is the DC offset to remove from sample C.
*                       The DC offset must be in the same format as the
*                       sample - after the bit allignment.
*   dc_offset_d       - This parameter is the DC offset to remove from sample D.
*                       The DC offset must be in the same format as the
*                       sample - after the bit allignment.
*
* RETURNS NOTES: Error code which can be returned is: FS_ETPU_ERROR_VALUE
*******************************************************************************/
int32_t fs_etpu_asac_set_dc_offsets_ABCD(uint8_t    channel,
                                         ufract24_t dc_offset_a,
                                         ufract24_t dc_offset_b,
                                         ufract24_t dc_offset_c,
                                         ufract24_t dc_offset_d)
{
   /****************************************
    * Parameters bounds check.
    ***************************************/
   #ifdef FS_ETPU_MC_PARAM_CHECK
      if(((channel>31)&&(channel<64))||(channel>95))
      {
          return(FS_ETPU_ERROR_VALUE);
      }
   #endif

  /****************************************
   * Write parameters.
   ***************************************/
   fs_etpu_set_chan_local_24(channel, FS_ETPU_ASAC_DC_OFFSET_A_OFFSET,
                             dc_offset_a);
   fs_etpu_set_chan_local_24(channel, FS_ETPU_ASAC_DC_OFFSET_B_OFFSET,
                             dc_offset_b);
   fs_etpu_set_chan_local_24(channel, FS_ETPU_ASAC_DC_OFFSET_C_OFFSET,
                             dc_offset_c);
   fs_etpu_set_chan_local_24(channel, FS_ETPU_ASAC_DC_OFFSET_D_OFFSET,
                             dc_offset_d);

  return(0);
}

/*******************************************************************************
* NAME:        : fs_etpu_asac_set_dc_offsets_ABC
* PURPOSE      : This function enables to set the dc_offsets of samples A,B,C 
*                by values.
*
* INPUTS NOTES : This function has the following parameters:
*   channel           - This is the ASAC channel number.
*                       This parameter must be assigned the same value
*                       as the channel parameter of the initialization
*                       function was assigned.
*   dc_offset_a       - This parameter is the DC offset to remove from sample A.
*                       The DC offset must be in the same format as the
*                       sample - after the bit allignment.
*   dc_offset_b       - This parameter is the DC offset to remove from sample B.
*                       The DC offset must be in the same format as the
*                       sample - after the bit allignment.
*   dc_offset_c       - This parameter is the DC offset to remove from sample C.
*                       The DC offset must be in the same format as the
*                       sample - after the bit allignment.
*
* RETURNS NOTES: Error code which can be returned is: FS_ETPU_ERROR_VALUE
*******************************************************************************/
int32_t fs_etpu_asac_set_dc_offsets_ABC(uint8_t    channel,
                                        ufract24_t dc_offset_a,
                                        ufract24_t dc_offset_b,
                                        ufract24_t dc_offset_c)
{
   /****************************************
    * Parameters bounds check.
    ***************************************/
   #ifdef FS_ETPU_MC_PARAM_CHECK
      if(((channel>31)&&(channel<64))||(channel>95))
      {
          return(FS_ETPU_ERROR_VALUE);
      }
   #endif

  /****************************************
   * Write parameters.
   ***************************************/
   fs_etpu_set_chan_local_24(channel, FS_ETPU_ASAC_DC_OFFSET_A_OFFSET,
                             dc_offset_a);
   fs_etpu_set_chan_local_24(channel, FS_ETPU_ASAC_DC_OFFSET_B_OFFSET,
                             dc_offset_b);
   fs_etpu_set_chan_local_24(channel, FS_ETPU_ASAC_DC_OFFSET_C_OFFSET,
                             dc_offset_c);

  return(0);
}

/*******************************************************************************
* NAME:        : fs_etpu_asac_set_dc_offset_D
* PURPOSE      : This function enables to set the dc_offset of sample D by value
*
* INPUTS NOTES : This function has the following parameters:
*   channel           - This is the ASAC channel number.
*                       This parameter must be assigned the same value
*                       as the channel parameter of the initialization
*                       function was assigned.
*   dc_offset_d       - This parameter is the DC offset to remove from sample D.
*                       The DC offset must be in the same format as the
*                       sample - after the bit allignment.
*
* RETURNS NOTES: Error code which can be returned is: FS_ETPU_ERROR_VALUE
*******************************************************************************/
int32_t fs_etpu_asac_set_dc_offset_D(uint8_t    channel,
                                     ufract24_t dc_offset_d)
{
   /****************************************
    * Parameters bounds check.
    ***************************************/
   #ifdef FS_ETPU_MC_PARAM_CHECK
      if(((channel>31)&&(channel<64))||(channel>95))
      {
          return(FS_ETPU_ERROR_VALUE);
      }
   #endif

  /****************************************
   * Write parameters.
   ***************************************/
   fs_etpu_set_chan_local_24(channel, FS_ETPU_ASAC_DC_OFFSET_D_OFFSET,
                             dc_offset_d);

  return(0);
}

/*******************************************************************************
* NAME:        : fs_etpu_asac_get_outputA
* PURPOSE      : This function returns outputA value - after filtration.
*
* INPUTS NOTES : This function has the following parameter:
*   channel      - This is the ASAC channel number.
*                  This parameter must be assigned the same value
*                  as the channel parameter of the initialization
*                  function was assigned.
*
* RETURNS NOTES: This function returns outputA value - after filtration.
*******************************************************************************/
fract24_t fs_etpu_asac_get_outputA(uint8_t channel)
{
  uint24_t  outputA_addr;

  outputA_addr = fs_etpu_get_chan_local_24(channel,
                                           FS_ETPU_ASAC_P_OUTPUT_A_OFFSET);
  outputA_addr |= 0x01;
  return(fs_etpu_get_global_24s(outputA_addr));
}

/*******************************************************************************
* NAME:        : fs_etpu_asac_get_outputB
* PURPOSE      : This function returns outputB value - after filtration.
*
* INPUTS NOTES : This function has the following parameter:
*   channel      - This is the ASAC channel number.
*                  This parameter must be assigned the same value
*                  as the channel parameter of the initialization
*                  function was assigned.
*
* RETURNS NOTES: This function returns outputB value - after filtration.
*******************************************************************************/
fract24_t fs_etpu_asac_get_outputB(uint8_t channel)
{
  uint24_t  outputB_addr;

  outputB_addr = fs_etpu_get_chan_local_24(channel,
                                           FS_ETPU_ASAC_P_OUTPUT_B_OFFSET);
  outputB_addr |= 0x01;
  return(fs_etpu_get_global_24s(outputB_addr));
}

/*******************************************************************************
* NAME:        : fs_etpu_asac_get_outputC
* PURPOSE      : This function returns outputC value - after filtration.
*
* INPUTS NOTES : This function has the following parameter:
*   channel      - This is the ASAC channel number.
*                  This parameter must be assigned the same value
*                  as the channel parameter of the initialization
*                  function was assigned.
*
* RETURNS NOTES: This function returns outputC value - after filtration.
*******************************************************************************/
fract24_t fs_etpu_asac_get_outputC(uint8_t channel)
{
  uint24_t  outputC_addr;

  outputC_addr = fs_etpu_get_chan_local_24(channel,
                                           FS_ETPU_ASAC_P_OUTPUT_C_OFFSET);
  outputC_addr |= 0x01;
  return(fs_etpu_get_global_24s(outputC_addr));
}

/*******************************************************************************
* NAME:        : fs_etpu_asac_get_outputD
* PURPOSE      : This function returns outputD value - after filtration.
*
* INPUTS NOTES : This function has the following parameter:
*   channel      - This is the ASAC channel number.
*                  This parameter must be assigned the same value
*                  as the channel parameter of the initialization
*                  function was assigned.
*
* RETURNS NOTES: This function returns outputD value - after filtration.
*******************************************************************************/
ufract24_t fs_etpu_asac_get_outputD(uint8_t channel)
{
  uint24_t  outputD_addr;

  outputD_addr = fs_etpu_get_chan_local_24(channel,
                                           FS_ETPU_ASAC_P_OUTPUT_D1_OFFSET);
  outputD_addr |= 0x01;
  return(fs_etpu_get_global_24(outputD_addr));
}

/*******************************************************************************
* NAME:        : fs_etpu_asac_get_phase_currents
* PURPOSE      : This function returns phase currents (outputs A,B,C 
*                after filtration).
*
* INPUTS NOTES : This function has the following parameters:
*   channel      - This is the ASAC channel number.
*                  This parameter must be assigned the same value
*                  as the channel parameter of the initialization
*                  function was assigned.
*   p_i_abc      - Pointer to return structure of phase currents.
*
* RETURNS NOTES: Error code that can be returned is: FS_ETPU_ERROR_VALUE.
*******************************************************************************/
int32_t fs_etpu_asac_get_phase_currents(uint8_t channel,
                                        asac_abc_t * p_i_abc)
{
   uint24_t  outputA_addr;
   uint24_t  outputB_addr;
   uint24_t  outputC_addr;

   /* Parameters bounds check */
   #ifdef FS_ETPU_MC_PARAM_CHECK
       if(((channel>31)&&(channel<64))||(channel>95))
       {
          return(FS_ETPU_ERROR_VALUE);
       }
   #endif
   
   outputA_addr = fs_etpu_get_chan_local_24(channel,
                                            FS_ETPU_ASAC_P_OUTPUT_A_OFFSET);
   outputB_addr = fs_etpu_get_chan_local_24(channel,
                                            FS_ETPU_ASAC_P_OUTPUT_B_OFFSET);
   outputC_addr = fs_etpu_get_chan_local_24(channel,
                                            FS_ETPU_ASAC_P_OUTPUT_C_OFFSET);

   p_i_abc->a = (fract24_t)(fs_etpu_get_global_24s(outputA_addr));
   p_i_abc->b = (fract24_t)(fs_etpu_get_global_24s(outputB_addr));
   p_i_abc->c = (fract24_t)(fs_etpu_get_global_24s(outputC_addr));

   return(0);
}

/*******************************************************************************
* NAME:        : fs_etpu_asac_get_sampleA
* PURPOSE      : This function returns sampleA value - prior to filtration.
*
* INPUTS NOTES : This function has the following parameter:
*   channel      - This is the ASAC channel number.
*                  This parameter must be assigned the same value
*                  as the channel parameter of the initialization
*                  function was assigned.
*
* RETURNS NOTES: This function returns sampleA value - prior to filtration.
*******************************************************************************/
fract24_t fs_etpu_asac_get_sampleA(uint8_t channel)
{
   uint32_t  sampleA_addr;
   uint24_t  bit_shift;
   fract24_t sampleA;

  sampleA_addr = fs_etpu_data_ram_start +
         fs_etpu_get_chan_local_24(channel, FS_ETPU_ASAC_RESULT_QUEUE_OFFSET) +
         fs_etpu_get_chan_local_8(channel, FS_ETPU_ASAC_QUEUE_OFFSET_A_OFFSET);
  sampleA = (fract24_t)(*(uint16_t *)(sampleA_addr));
  bit_shift = fs_etpu_get_chan_local_24(channel, FS_ETPU_ASAC_BIT_SHIFT_OFFSET);
  switch (bit_shift)
  {
      case 3: sampleA <<= 4;
      case 2: sampleA <<= 2;
      case 1: sampleA <<= 2;
      default:
      case 0: sampleA <<= 8;
  }
  sampleA &= 0x00FFFFFF;
  sampleA -= (fract24_t)fs_etpu_asac_get_dc_offsetA(channel);
  return(sampleA);
}

/*******************************************************************************
* NAME:        : fs_etpu_asac_get_sampleB
* PURPOSE      : This function returns sampleB value - prior to filtration.
*
* INPUTS NOTES : This function has the following parameter:
*   channel      - This is the ASAC channel number.
*                  This parameter must be assigned the same value
*                  as the channel parameter of the initialization
*                  function was assigned.
*
* RETURNS NOTES: This function returns sampleB value - prior to filtration.
*******************************************************************************/
fract24_t fs_etpu_asac_get_sampleB(uint8_t channel)
{
   uint32_t  sampleB_addr;
   uint24_t  bit_shift;
   fract24_t sampleB;

  sampleB_addr = fs_etpu_data_ram_start +
         fs_etpu_get_chan_local_24(channel, FS_ETPU_ASAC_RESULT_QUEUE_OFFSET) +
         fs_etpu_get_chan_local_8(channel, FS_ETPU_ASAC_QUEUE_OFFSET_B_OFFSET);
  sampleB = (fract24_t)(*(uint16_t *)(sampleB_addr));
  bit_shift = fs_etpu_get_chan_local_24(channel, FS_ETPU_ASAC_BIT_SHIFT_OFFSET);
  switch (bit_shift)
  {
      case 3: sampleB <<= 4;
      case 2: sampleB <<= 2;
      case 1: sampleB <<= 2;
      default:
      case 0: sampleB <<= 8;
  }
  sampleB &= 0x00FFFFFF;
  sampleB -= (fract24_t)fs_etpu_asac_get_dc_offsetB(channel);
  return(sampleB);
}

/*******************************************************************************
* NAME:        : fs_etpu_asac_get_sampleC
* PURPOSE      : This function returns sampleC value - prior to filtration.
*
* INPUTS NOTES : This function has the following parameter:
*   channel      - This is the ASAC channel number.
*                  This parameter must be assigned the same value
*                  as the channel parameter of the initialization
*                  function was assigned.
*
* RETURNS NOTES: This function returns sampleC value - prior to filtration.
*******************************************************************************/
fract24_t fs_etpu_asac_get_sampleC(uint8_t channel)
{
   uint32_t  sampleC_addr;
   uint24_t  bit_shift;
   fract24_t sampleC;

  sampleC_addr = fs_etpu_data_ram_start +
         fs_etpu_get_chan_local_24(channel, FS_ETPU_ASAC_RESULT_QUEUE_OFFSET) +
         fs_etpu_get_chan_local_8(channel, FS_ETPU_ASAC_QUEUE_OFFSET_C_OFFSET);
  sampleC = (fract24_t)(*(uint16_t *)(sampleC_addr));
  bit_shift = fs_etpu_get_chan_local_24(channel, FS_ETPU_ASAC_BIT_SHIFT_OFFSET);
  switch (bit_shift)
  {
      case 3: sampleC <<= 4;
      case 2: sampleC <<= 2;
      case 1: sampleC <<= 2;
      default:
      case 0: sampleC <<= 8;
  }
  sampleC &= 0x00FFFFFF;
  sampleC -= (fract24_t)fs_etpu_asac_get_dc_offsetC(channel);
  return(sampleC);
}

/*******************************************************************************
* NAME:        : fs_etpu_asac_get_sampleD
* PURPOSE      : This function returns sampleD value - prior to filtration.
*
* INPUTS NOTES : This function has the following parameter:
*   channel      - This is the ASAC channel number.
*                  This parameter must be assigned the same value
*                  as the channel parameter of the initialization
*                  function was assigned.
*
* RETURNS NOTES: This function returns sampleD value - prior to filtration.
*******************************************************************************/
fract24_t fs_etpu_asac_get_sampleD(uint8_t channel)
{
   uint32_t  sampleD_addr;
   uint24_t  bit_shift;
   fract24_t sampleD;

  sampleD_addr = fs_etpu_data_ram_start +
         fs_etpu_get_chan_local_24(channel, FS_ETPU_ASAC_RESULT_QUEUE_OFFSET) +
         fs_etpu_get_chan_local_8(channel, FS_ETPU_ASAC_QUEUE_OFFSET_D_OFFSET);
  sampleD = (fract24_t)(*(uint16_t *)(sampleD_addr));
  bit_shift = fs_etpu_get_chan_local_24(channel, FS_ETPU_ASAC_BIT_SHIFT_OFFSET);
  switch (bit_shift)
  {
      case 3: sampleD <<= 4;
      case 2: sampleD <<= 2;
      case 1: sampleD <<= 2;
      default:
      case 0: sampleD <<= 8;
  }
  sampleD &= 0x00FFFFFF;
  sampleD -= (fract24_t)fs_etpu_asac_get_dc_offsetD(channel);
  return(sampleD);
}

/*******************************************************************************
* NAME:        : fs_etpu_asac_get_phase_currents_samples
* PURPOSE      : This function returns phase currents - prior to filtration.
*
* INPUTS NOTES : This function has the following parameter:
*   channel      - This is the ASAC channel number.
*                  This parameter must be assigned the same value
*                  as the channel parameter of the initialization
*                  function was assigned.
*   p_i_abc      - Pointer to return structure of phase currents.
*
* RETURNS NOTES: Error code that can be returned is: FS_ETPU_ERROR_VALUE.
*******************************************************************************/
int32_t fs_etpu_asac_get_phase_currents_samples(uint8_t channel,
                                                asac_abc_t * p_i_abc)
{
   uint32_t  sampleA_addr;
   uint32_t  sampleB_addr;
   uint32_t  sampleC_addr;
   uint24_t  bit_shift;
   fract24_t sampleA;
   fract24_t sampleB;
   fract24_t sampleC;

   bit_shift = fs_etpu_get_chan_local_24(channel, FS_ETPU_ASAC_BIT_SHIFT_OFFSET);
 
   sampleA_addr = fs_etpu_data_ram_start +
          fs_etpu_get_chan_local_24(channel, FS_ETPU_ASAC_RESULT_QUEUE_OFFSET) +
          fs_etpu_get_chan_local_8(channel, FS_ETPU_ASAC_QUEUE_OFFSET_A_OFFSET);
   sampleA = (fract24_t)(*(uint16_t *)(sampleA_addr));
 
   sampleB_addr = fs_etpu_data_ram_start +
          fs_etpu_get_chan_local_24(channel, FS_ETPU_ASAC_RESULT_QUEUE_OFFSET) +
          fs_etpu_get_chan_local_8(channel, FS_ETPU_ASAC_QUEUE_OFFSET_B_OFFSET);
   sampleB = (fract24_t)(*(uint16_t *)(sampleB_addr));
 
   sampleC_addr = fs_etpu_data_ram_start +
          fs_etpu_get_chan_local_24(channel, FS_ETPU_ASAC_RESULT_QUEUE_OFFSET) +
          fs_etpu_get_chan_local_8(channel, FS_ETPU_ASAC_QUEUE_OFFSET_C_OFFSET);
   sampleC = (fract24_t)(*(uint16_t *)(sampleC_addr));
 
   switch (bit_shift)
   {
       case 3: sampleA <<= 4;
               sampleB <<= 4;
               sampleC <<= 4;
       case 2: sampleA <<= 2;
               sampleB <<= 2;
               sampleC <<= 2;
       case 1: sampleA <<= 2;
               sampleB <<= 2;
               sampleC <<= 2;
       default:
       case 0: sampleA <<= 8;
               sampleB <<= 8;
               sampleC <<= 8;
   }
   sampleA &= 0x00FFFFFF;
   sampleB &= 0x00FFFFFF;
   sampleC &= 0x00FFFFFF;
   sampleA -= (fract24_t)fs_etpu_asac_get_dc_offsetA(channel);
   sampleB -= (fract24_t)fs_etpu_asac_get_dc_offsetB(channel);
   sampleC -= (fract24_t)fs_etpu_asac_get_dc_offsetC(channel);
 
   p_i_abc->a = sampleA;
   p_i_abc->b = sampleB;
   p_i_abc->c = sampleC;
 
   return(0);
}

/*******************************************************************************
* NAME:        : fs_etpu_asac_get_dc_offsetA
* PURPOSE      : This function returns sampleA DC offset.
*
* INPUTS NOTES : This function has the following parameter:
*   channel      - This is the ASAC channel number.
*                  This parameter must be assigned the same value
*                  as the channel parameter of the initialization
*                  function was assigned.
*
* RETURNS NOTES: This function returns sampleA DC offset.
*******************************************************************************/
ufract24_t fs_etpu_asac_get_dc_offsetA(uint8_t channel)
{
    return(fs_etpu_get_chan_local_24(channel, FS_ETPU_ASAC_DC_OFFSET_A_OFFSET));
}

/*******************************************************************************
* NAME:        : fs_etpu_asac_get_dc_offsetB
* PURPOSE      : This function returns sampleB DC offset.
*
* INPUTS NOTES : This function has the following parameter:
*   channel      - This is the ASAC channel number.
*                  This parameter must be assigned the same value
*                  as the channel parameter of the initialization
*                  function was assigned.
*
* RETURNS NOTES: This function returns sampleB DC offset.
*******************************************************************************/
ufract24_t fs_etpu_asac_get_dc_offsetB(uint8_t channel)
{
    return(fs_etpu_get_chan_local_24(channel, FS_ETPU_ASAC_DC_OFFSET_B_OFFSET));
}

/*******************************************************************************
* NAME:        : fs_etpu_asac_get_dc_offsetC
* PURPOSE      : This function returns sampleC DC offset.
*
* INPUTS NOTES : This function has the following parameter:
*   channel      - This is the ASAC channel number.
*                  This parameter must be assigned the same value
*                  as the channel parameter of the initialization
*                  function was assigned.
*
* RETURNS NOTES: This function returns sampleC DC offset.
*******************************************************************************/
ufract24_t fs_etpu_asac_get_dc_offsetC(uint8_t channel)
{
    return(fs_etpu_get_chan_local_24(channel, FS_ETPU_ASAC_DC_OFFSET_C_OFFSET));
}

/*******************************************************************************
* NAME:        : fs_etpu_asac_get_dc_offsetD
* PURPOSE      : This function returns sampleD DC offset.
*
* INPUTS NOTES : This function has the following parameter:
*   channel      - This is the ASAC channel number.
*                  This parameter must be assigned the same value
*                  as the channel parameter of the initialization
*                  function was assigned.
*
* RETURNS NOTES: This function returns sampleD DC offset.
*******************************************************************************/
ufract24_t fs_etpu_asac_get_dc_offsetD(uint8_t channel)
{
    return(fs_etpu_get_chan_local_24(channel, FS_ETPU_ASAC_DC_OFFSET_D_OFFSET));
}

/*******************************************************************************
* FUNCTION     : fs_etpu_asac_get_eQADC_cmds_addr
* PURPOSE      : To get address of the eQADC command queue beginning.
* 
* INPUTS NOTES : This function has 1 parameter:
*   channel      - This is the ASAC channel number.
*                  This parameter must be assigned the same value
*                  as the channel parameter of the initialization
*                  function was assigned.
*
* RETURNS NOTES: This function returns the address
*                of the eQADC command queue beginning.
*******************************************************************************/
uint32_t fs_etpu_asac_get_eQADC_cmds_addr( uint8_t channel)
{
   uint32_t eQADC_cmds_addr;

   eQADC_cmds_addr = fs_etpu_data_ram_start + 
     fs_etpu_get_chan_local_24(channel, FS_ETPU_ASAC_P_APPLIED_EQADC_CMDS_OFFSET);

   return(eQADC_cmds_addr);
}

/*********************************************************************
 *
 * Copyright:
 *	Freescale Semiconductor, INC. All Rights Reserved.
 *  You are hereby granted a copyright license to use, modify, and
 *  distribute the SOFTWARE so long as this entire notice is
 *  retained without alteration in any modified and/or redistributed
 *  versions, and that such modified versions are clearly identified
 *  as such. No licenses are granted by implication, estoppel or
 *  otherwise under any patents or trademarks of Freescale
 *  Semiconductor, Inc. This software is provided on an "AS IS"
 *  basis and without warranty.
 *
 *  To the maximum extent permitted by applicable law, Freescale
 *  Semiconductor DISCLAIMS ALL WARRANTIES WHETHER EXPRESS OR IMPLIED,
 *  INCLUDING IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A
 *  PARTICULAR PURPOSE AND ANY WARRANTY AGAINST INFRINGEMENT WITH
 *  REGARD TO THE SOFTWARE (INCLUDING ANY MODIFIED VERSIONS THEREOF)
 *  AND ANY ACCOMPANYING WRITTEN MATERIALS.
 *
 *  To the maximum extent permitted by applicable law, IN NO EVENT
 *  SHALL Freescale Semiconductor BE LIABLE FOR ANY DAMAGES WHATSOEVER
 *  (INCLUDING WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS PROFITS,
 *  BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR OTHER
 *  PECUNIARY LOSS) ARISING OF THE USE OR INABILITY TO USE THE SOFTWARE.
 *
 *  Freescale Semiconductor assumes no responsibility for the
 *  maintenance and support of this software
 ********************************************************************/
