/*******************************************************************************
* File Name: PWMQ.c  
* Version 1.10
*
* Description:
*  The PWM User Module consist of an 8 or 16-bit counter with two 8 or 16-bit
*  comparitors.  Each instance of this user module is capable of generating
*  two PWM outputs with the same period.  The pulse width is selectable
*  between 1 and 255/65535.  The period is selectable between 2 and 255/65536 clocks. 
*  The compare value output may be configured to be active when the present 
*  counter is less than or less than/equal to the compare value.
*  A terminal count output is also provided.  It generates a pulse one clock
*  width wide when the counter is equal to zero.
*
* Note:
*
*******************************************************************************
* Copyright 2008-2009, Cypress Semiconductor Corporation.  All rights reserved.
* You may use this file only in accordance with the license, terms, conditions, 
* disclaimers, and limitations in the end user license agreement accompanying 
* the software package with which this file was provided.
********************************************************************************/



#include "cytypes.h"
#include "PWMQ.h"

uint8 PWMQ_initvar = 0;


/*******************************************************************************
* Function Name: PWMQ_Start
********************************************************************************
* Summary:
*  The start function initializes the pwm with the default values, the 
*  enables the counter to begin counting.  It does not enable interrupts,
*  the EnableInt command should be called if interrupt generation is required.
*
* Parameters:  
*  void  
*
* Return: 
*  void
*
*******************************************************************************/
void PWMQ_Start(void) 
{
    if(PWMQ_initvar == 0)
    {
        #if (PWMQ_UsingFixedFunction || PWMQ_UseControl)
        uint8 ctrl;
        #endif
        PWMQ_initvar = 1;
        
        #if (PWMQ_UsingFixedFunction)
            /* Mode Bit of the Configuration Register must be 1 before */
            /* you are allowed to write the compare value (FF only) */
            PWMQ_CONTROL |= PWMQ_CFG0_MODE;
            #if PWMQ_DeadBand2_4
                PWMQ_CONTROL |= PWMQ_CFG0_DB;
            #endif
            ctrl = PWMQ_CONTROL2 & ~PWMQ_CTRL_CMPMODE1_MASK;
            PWMQ_CONTROL2 = ctrl | PWMQ_DEFAULT_COMPARE1_MODE;
        #elif (PWMQ_UseControl)
            /* Set the default compare mode defined in the parameter */
            ctrl = PWMQ_CONTROL & ~PWMQ_CTRL_CMPMODE2_MASK & ~PWMQ_CTRL_CMPMODE1_MASK;
            PWMQ_CONTROL = ctrl | PWMQ_DEFAULT_COMPARE2_MODE | PWMQ_DEFAULT_COMPARE1_MODE;
        #endif 
        
        #if (!PWMQ_UsingFixedFunction)
            #if (PWMQ_Resolution == 8)
                /* Set FIFO 0 to 1 byte register for period*/
               PWMQ_AUX_CONTROLDP0 |= (PWMQ_AUX_CTRL_FIFO0_CLR);
            #else /* (PWMQ_Resolution == 16)*/
               /* Set FIFO 0 to 1 byte register for period */
               PWMQ_AUX_CONTROLDP0 |= (PWMQ_AUX_CTRL_FIFO0_CLR);
               PWMQ_AUX_CONTROLDP1 |= (PWMQ_AUX_CTRL_FIFO0_CLR);
            #endif
        #endif
        
        PWMQ_WritePeriod(PWMQ_INIT_PERIOD_VALUE);
        //PWMQ_WriteCounter(PWMQ_INIT_PERIOD_VALUE);
        
        #if PWMQ_UseOneCompareMode
            PWMQ_WriteCompare(PWMQ_INIT_COMPARE_VALUE1);
        #else
            PWMQ_WriteCompare1(PWMQ_INIT_COMPARE_VALUE1);
            PWMQ_WriteCompare2(PWMQ_INIT_COMPARE_VALUE2);
        #endif
        
        #if PWMQ_KillModeMinTime
            PWMQ_WriteKillTime(PWMQ_MinimumKillTime);
        #endif
        
        #if PWMQ_DeadBandUsed
            PWMQ_WriteDeadTime( PWMQ_INIT_DEAD_TIME );
        #endif

        #if (PWMQ_UseStatus || PWMQ_UsingFixedFunction)
        PWMQ_SetInterruptMode(PWMQ_INIT_INTERRUPTS_MODE);
        #endif
        
        #if (PWMQ_UsingFixedFunction)
            /* Globally Enable the Fixed Function Block chosen */
            PWMQ_GLOBAL_ENABLE |= PWMQ_BLOCK_EN_MASK;
            /* Set the Interrupt source to come from the status register */
            PWMQ_CONTROL2 |= PWMQ_CTRL2_IRQ_SEL;
        #else
            #if(PWMQ_UseStatus)
                /* Use the interrupt output of the status register for IRQ output */
                PWMQ_STATUS_AUX_CTRL |= PWMQ_STATUS_ACTL_INT_EN_MASK;
            #endif
        #endif
    }
    #if (PWMQ_UseControl)
        PWMQ_CONTROL |= PWMQ_CTRL_ENABLE;
    #endif
}


/*******************************************************************************
* Function Name: PWMQ_Stop
********************************************************************************
* Summary:
*  The stop function halts the PWM, but does not change any modes or disable
*  interrupts.
*
* Parameters:  
*  void  
*
* Return: 
*  void
*
*******************************************************************************/
void PWMQ_Stop(void)
{
    #if (PWMQ_UseControl || PWMQ_UsingFixedFunction)
        PWMQ_CONTROL &= ~PWMQ_CTRL_ENABLE;
    #endif
}


#if (PWMQ_UseStatus || PWMQ_UsingFixedFunction)
/*******************************************************************************
* Function Name: PWMQ_SetInterruptMode
********************************************************************************
* Summary:
*  This function is used to set enable the individual interrupt sources.
*
* Parameters:  
*  irqMode:  Enables or disables the interrupt source, compare1, compare2, and 
*            terminal count.  Also, the Less Than or Less Than or equal To 
*            mode may be changed as well with this function. 
*
* Return: 
*  void
*
*******************************************************************************/
void PWMQ_SetInterruptMode(uint8 interruptMode)
{
    /* Set the status Registers Mask Register with the bit-field */
    PWMQ_STATUS_MASK = interruptMode; 
}


/*******************************************************************************
* Function Name: PWMQ_GetInterruptSource
********************************************************************************
* Summary:
*  This function is used to get the source of an interrupt by the ISR routine
*
* Parameters:  
*  void  
*
* Return: 
*  Status Register containing bit-field of interrupt source
*
* Side Effects:  The status register is clear on Read.  This will clear the 
*                interrupt.
*
*******************************************************************************/
uint8 PWMQ_GetInterruptSource(void)
{
    return PWMQ_STATUS;
}


/*******************************************************************************
* Function Name: PWMQ_ReadStatusRegister
********************************************************************************
* Summary:
*  Reads the status register and returns it's state. This function should use
*  defined types for the bit-field information as the bits in this register may
*  be permuteable.
*
* Parameters:  
*  void
*
* Return: 
*  The contents of the status register
*
* Side Effects:
*  Some status register bits are clear on read. 
*******************************************************************************/
uint8   PWMQ_ReadStatusRegister(void)
{
    return PWMQ_STATUS;
}
#endif /* (PWMQ_UseStatus || PWMQ_UsingFixedFunction) */


#if (PWMQ_UseControl || PWMQ_UsingFixedFunction)
/*******************************************************************************
* Function Name: PWMQ_ReadControlRegister
********************************************************************************
* Summary:
*  Reads the control register and returns it's state. This function should use
*  defined types for the bit-field information as the bits in this register may
*  be permuteable.
*
* Parameters:  
*  void
*
* Return: 
*  The contents of the control register
*
*******************************************************************************/
uint8   PWMQ_ReadControlRegister(void)
{
    return PWMQ_CONTROL;
}


/*******************************************************************************
* Function Name: PWMQ_WriteControlRegister
********************************************************************************
* Summary:
*  Sets the bit-field of the control register.  This function should use
*  defined types for the bit-field information as the bits in this
*  register may be permuteable.
*
* Parameters:  
*  void
*
* Return: 
*  The contents of the control register
*
*******************************************************************************/
void    PWMQ_WriteControlRegister(uint8 control)
{
    PWMQ_CONTROL = control;
}
#endif  /* (PWMQ_UseControl || PWMQ_UsingFixedFunction) */


#if PWMQ_UseOneCompareMode
#if PWMQ_CompareMode1SW
/*******************************************************************************
* Function Name: PWMQ_SetCompareMode
********************************************************************************
* Summary:
*  This function writes the Compare Mode for the pwm output when in Dither mode
*
* Parameters:
*  comparemode:  The new compare mode for the PWM output. Use the compare types
*                defined in the H file as input arguments.
*
* Return:
*  void
*
*******************************************************************************/
void PWMQ_SetCompareMode( uint8 comparemode )
{
    #if(PWMQ_UsingFixedFunction)
        uint8 comparemodemasked = (comparemode << PWMQ_CTRL_CMPMODE1_SHIFT);
        PWMQ_CONTROL2 &= ~PWMQ_CTRL_CMPMODE1_MASK; /*Clear Existing Data */
        PWMQ_CONTROL2 |= comparemodemasked;
        
    #elif (PWMQ_UseControl)
        uint8 comparemode1masked = (comparemode << PWMQ_CTRL_CMPMODE1_SHIFT) & PWMQ_CTRL_CMPMODE1_MASK;
        uint8 comparemode2masked = (comparemode << PWMQ_CTRL_CMPMODE2_SHIFT) & PWMQ_CTRL_CMPMODE2_MASK;
        PWMQ_CONTROL &= ~(PWMQ_CTRL_CMPMODE1_MASK | PWMQ_CTRL_CMPMODE2_MASK); /*Clear existing mode */
        PWMQ_CONTROL |= (comparemode1masked | comparemode2masked);
        
    #else
        uint8 temp = comparemode;
    #endif
}
#endif /* PWMQ_CompareMode1SW */

#else /* UseOneCompareMode */

#if PWMQ_CompareMode1SW
/*******************************************************************************
* Function Name: PWMQ_SetCompareMode1
********************************************************************************
* Summary:
*  This function writes the Compare Mode for the pwm or pwm1 output
*
* Parameters:  
*  comparemode:  The new compare mode for the PWM output. Use the compare types
*                defined in the H file as input arguments.
*
* Return: 
*  void
*
*******************************************************************************/
void PWMQ_SetCompareMode1( uint8 comparemode )
{
    uint8 comparemodemasked = (comparemode << PWMQ_CTRL_CMPMODE1_SHIFT) & PWMQ_CTRL_CMPMODE1_MASK;
    #if(PWMQ_UsingFixedFunction)
        PWMQ_CONTROL2 &= PWMQ_CTRL_CMPMODE1_MASK; /*Clear existing mode */
        PWMQ_CONTROL2 |= comparemodemasked; 
    #elif (PWMQ_UseControl)
        PWMQ_CONTROL &= PWMQ_CTRL_CMPMODE1_MASK; /*Clear existing mode */
        PWMQ_CONTROL |= comparemodemasked;
    #endif    
}
#endif /* PWMQ_CompareMode1SW */

#if PWMQ_CompareMode2SW
/*******************************************************************************
* Function Name: PWMQ_SetCompareMode2
********************************************************************************
* Summary:
*  This function writes the Compare Mode for the pwm or pwm2 output
*
* Parameters:  
*  comparemode:  The new compare mode for the PWM output. Use the compare types
*                defined in the H file as input arguments.
*
* Return: 
*  void
*
*******************************************************************************/
void PWMQ_SetCompareMode2( uint8 comparemode )
{
    #if(PWMQ_UsingFixedFunction)
        /* Do Nothing because there is no second Compare Mode Register in FF block*/ 
    #elif (PWMQ_UseControl)
    uint8 comparemodemasked = (comparemode << PWMQ_CTRL_CMPMODE2_SHIFT) & PWMQ_CTRL_CMPMODE2_MASK;
    PWMQ_CONTROL &= PWMQ_CTRL_CMPMODE2_MASK; /*Clear existing mode */
    PWMQ_CONTROL |= comparemodemasked;
    #endif    
}
#endif /*PWMQ_CompareMode2SW */
#endif /* UseOneCompareMode */

/*******************************************************************************
* Function Name: PWMQ_WriteCounter
********************************************************************************
* Summary:
*  This function is used to change the counter value.
*
* Parameters:  
*  counter:  This value may be between 1 and (2^Resolution)-1.   
*
* Return: 
*  void
*
*******************************************************************************/
void PWMQ_WriteCounter(uint8 counter)
{
    #if(PWMQ_UsingFixedFunction)
        uint16 counter_temp = (uint16)counter;
        CY_SET_REG16(PWMQ_COUNTER_LSB_PTR, counter_temp);
    #else
        CY_SET_REG8(PWMQ_COUNTER_LSB_PTR, counter);
    #endif
}


#if (!PWMQ_UsingFixedFunction)
/*******************************************************************************
* Function Name: PWMQ_ReadCounter
********************************************************************************
* Summary:
*  This function returns the current value of the counter.  It doesn't matter
*  if the counter is enabled or running.
*
* Parameters:  
*  void  
*
* Return: 
*  The current value of the counter.
*
*******************************************************************************/
uint8 PWMQ_ReadCounter(void)
{
    CY_GET_REG8(PWMQ_COUNTERCAP_LSB_PTR);
    return ( CY_GET_REG8(PWMQ_CAPTURE_LSB_PTR) );
}


/*******************************************************************************
* Function Name: PWMQ_ReadCapture
********************************************************************************
* Summary:
*  This function returns the last value captured.
*
* Parameters:  
*  void 
*
* Return: 
*  Present Capture value.
*
*******************************************************************************/
uint8 PWMQ_ReadCapture( void )
{
   return ( CY_GET_REG8(PWMQ_CAPTURE_LSB_PTR) );  
}


#if (PWMQ_UseStatus)
/*******************************************************************************
* Function Name: PWMQ_ClearFIFO
********************************************************************************
* Summary:
*  This function clears all capture data from the capture FIFO
*
* Parameters:  
*  void
*
* Return: 
*  void
*
*******************************************************************************/
void PWMQ_ClearFIFO(void)
{
    while(PWMQ_ReadStatusRegister() & PWMQ_STATUS_FIFONEMPTY)
        PWMQ_ReadCapture();
}
#endif /* PWMQ_UseStatus */
#endif /* !PWMQ_UsingFixedFunction */


/*******************************************************************************
* Function Name: PWMQ_WritePeriod
********************************************************************************
* Summary:
*  This function is used to change the period of the counter.  The new period 
*  will be loaded the next time terminal count is detected.
*
* Parameters:  
*  void  
*
* Return: 
*  Period value. May be between 1 and (2^Resolution)-1.  A value of 0 will result in
*  the counter remaining at zero.
*
*******************************************************************************/
void PWMQ_WritePeriod(uint8 period)
{
    #if(PWMQ_UsingFixedFunction)
        uint16 period_temp = (uint16)period;
        CY_SET_REG16(PWMQ_PERIOD_LSB_PTR, period_temp);
    #else
        CY_SET_REG8(PWMQ_PERIOD_LSB_PTR, period);
    #endif
}


/*******************************************************************************
* Function Name: PWMQ_ReadPeriod
********************************************************************************
* Summary:
*  This function reads the period without affecting pwm operation.
*
* Parameters:  
*  uint8:  Current Period Value
*
* Return: 
*  (void)
*
*******************************************************************************/
uint8 PWMQ_ReadPeriod( void )
{
   return ( CY_GET_REG8(PWMQ_PERIOD_LSB_PTR) );
}


#if PWMQ_UseOneCompareMode
/*******************************************************************************
* Function Name: PWMQ_WriteCompare
********************************************************************************
* Summary:
*  This funtion is used to change the compare1 value when the PWM is in Dither
*  mode.  The compare output will 
*  reflect the new value on the next UDB clock.  The compare output will be 
*  driven high when the present counter value is compared to the compare value
*  based on the compare mode defined in Dither Mode.
*
* Parameters:  
*  compare:  New compare value.  
*
* Return: 
*  void
*
*******************************************************************************/
void PWMQ_WriteCompare(uint8 compare)
{
   CY_SET_REG8(PWMQ_COMPARE1_LSB_PTR, compare);
   #if (PWMQ_PWMMode == PWMQ__B_PWM__DITHER)
        CY_SET_REG8(PWMQ_COMPARE2_LSB_PTR, compare+1);
   #endif
}


/*******************************************************************************
* Function Name: PWMQ_ReadCompare
********************************************************************************
* Summary:
*  This function returns the compare value.
*
* Parameters:  
*  void  
*
* Return: 
*  Current compare value.
*
*******************************************************************************/
uint8 PWMQ_ReadCompare( void )
{
  return ( CY_GET_REG8(PWMQ_COMPARE1_LSB_PTR) );
}


#else


/*******************************************************************************
* Function Name: PWMQ_WriteCompare1
********************************************************************************
* Summary:
*  This funtion is used to change the compare1 value.  The compare output will 
*  reflect the new value on the next UDB clock.  The compare output will be 
*  driven high when the present counter value is less than or less than or 
*  equal to the compare register, depending on the mode.
*
* Parameters:  
*  compare:  New compare value.  
*
* Return: 
*  void
*
*******************************************************************************/
void PWMQ_WriteCompare1(uint8 compare)
{
    #if(PWMQ_UsingFixedFunction)
        uint16 compare_temp = (uint16)compare;
        CY_SET_REG16(PWMQ_COMPARE1_LSB_PTR, compare_temp);
    #else
        CY_SET_REG8(PWMQ_COMPARE1_LSB_PTR, compare);
    #endif
}


/*******************************************************************************
* Function Name: PWMQ_ReadCompare1
********************************************************************************
* Summary:
*  This function returns the compare1 value.
*
* Parameters:  
*  void  
*
* Return: 
*  Current compare value.
*
*******************************************************************************/
uint8 PWMQ_ReadCompare1( void )
{
  return ( CY_GET_REG8(PWMQ_COMPARE1_LSB_PTR) );
}


/*******************************************************************************
* Function Name: PWMQ_WriteCompare2
********************************************************************************
* Summary:
*  This funtion is used to change the compare value, for compare1 output.  
*  The compare output will reflect the new value on the next UDB clock.  
*  The compare output will be driven high when the present counter value is 
*  less than or less than or equal to the compare register, depending on the 
*  mode.
*
* Parameters:  
*  compare:  New compare value.  
*
* Return: 
*  void
*
*******************************************************************************/
void PWMQ_WriteCompare2(uint8 compare)
{
    #if(PWMQ_UsingFixedFunction)
       //TODO: This should generate an error because the fixed function block doesn't have a compare 2 register
       uint16 compare_temp = (uint16)compare;
       CY_SET_REG16(PWMQ_COMPARE2_LSB_PTR, compare_temp);
    #else
        CY_SET_REG8(PWMQ_COMPARE2_LSB_PTR, compare);
    #endif
}


/*******************************************************************************
* Function Name: PWMQ_ReadCompare2
********************************************************************************
* Summary:
*  This function returns the compare value, for the second compare output.
*
* Parameters:  
*  void
*
* Return: 
*  Present compare2 value.
*
*******************************************************************************/
uint8 PWMQ_ReadCompare2( void )
{
    return ( CY_GET_REG8(PWMQ_COMPARE2_LSB_PTR) );
}
#endif /* UseOneCompareMode */


#if (PWMQ_DeadBandUsed)
/*******************************************************************************
* Function Name: PWMQ_WriteDeadTime
********************************************************************************
* Summary:
*  This function writes the dead-band counts to the corresponding register
*
* Parameters:  
*  deadtime:  Number of counts for dead time 
*
* Return: 
*  void
*
*******************************************************************************/
void PWMQ_WriteDeadTime( uint8 deadtime )
{
    /* If using the Dead Band 1-255 mode then just write the register */
    #if(!PWMQ_DeadBand2_4)
        CY_SET_REG8(PWMQ_DEADBAND_COUNT_PTR, deadtime);
    #else
        /* Otherwise the data has to be masked and offset */
        uint8 deadtimemasked = (deadtime << PWMQ_DEADBAND_COUNT_SHIFT) & PWMQ_DEADBAND_COUNT_MASK;
        PWMQ_DEADBAND_COUNT &= ~PWMQ_DEADBAND_COUNT_MASK; /* Clear existing data */
        PWMQ_DEADBAND_COUNT |= deadtimemasked; /* Set new dead time */
    #endif
}


/*******************************************************************************
* Function Name: PWMQ_ReadDeadTime
********************************************************************************
* Summary:
*  This function reads the dead-band counts from the corresponding register
*
* Parameters:  
*  void
*
* Return: 
*  Dead Band Counts
*
*******************************************************************************/
uint8 PWMQ_ReadDeadTime(void)
{
    /* If using the Dead Band 1-255 mode then just read the register */
    #if(!PWMQ_DeadBand2_4)
        return ( CY_GET_REG8(PWMQ_DEADBAND_COUNT_PTR) );
    #else
        /* Otherwise the data has to be masked and offset */
        return ((PWMQ_DEADBAND_COUNT & PWMQ_DEADBAND_COUNT_MASK) >> PWMQ_DEADBAND_COUNT_SHIFT);
    #endif
}
#endif /* DeadBandUsed */


#if ( PWMQ_KillModeMinTime)
/*******************************************************************************
* Function Name: PWMQ_WriteKillTime
********************************************************************************
* Summary:
*  This function writes the kill-time counts to the corresponding register
*
* Parameters:
*  killtime:  Number of counts for killtime 
*
* Return: 
*  void
*
*******************************************************************************/
void PWMQ_WriteKillTime( uint8 killtime )
{
    /* Not available in Fixed Function mode.  This is taken care of by the 
     * customizer to not allow the user to set Fixed Function and set 
     * the Kill Mode*/
    CY_SET_REG8(PWMQ_KILLMODEMINTIME_PTR, killtime);
}


/*******************************************************************************
* Function Name: PWMQ_ReadKillTime
********************************************************************************
* Summary:
*  This function reads the Kill-time counts from the corresponding register
*
* Parameters:  
*  void
*
* Return: 
*  Kill Time Counts
*
*******************************************************************************/
uint8 PWMQ_ReadKillTime(void)
{
    return ( CY_GET_REG8(PWMQ_KILLMODEMINTIME_PTR) );
}
#endif /* KillModeMinTime */


/* [] END OF FILE */
