1118 lines
30 KiB
C
1118 lines
30 KiB
C
/**************************************************************************//**
|
|
* @file pwm.c
|
|
* @brief N9H30 series PWM driver source file
|
|
*
|
|
* @note
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
* Copyright (C) 2018 Nuvoton Technology Corp. All rights reserved.
|
|
*****************************************************************************/
|
|
#include "N9H30.h"
|
|
#include "nu_sys.h"
|
|
#include "nu_pwm.h"
|
|
/** @addtogroup N9H30_Device_Driver N9H30 Device Driver
|
|
@{
|
|
*/
|
|
|
|
/** @addtogroup N9H30_PWM_Driver PWM Driver
|
|
@{
|
|
*/
|
|
|
|
|
|
/** @addtogroup N9H30_PWM_EXPORTED_FUNCTIONS PWM Exported Functions
|
|
@{
|
|
*/
|
|
|
|
//Internal function definition
|
|
/// @cond HIDDEN_SYMBOLS
|
|
|
|
void pwmISR(PVOID pvParam);
|
|
|
|
|
|
static INT pwmInitGPIO(const INT nTimerIdentity, const INT nValue);
|
|
static INT pwmInitTimer(const INT nTimerIdentity);
|
|
static INT pwmStartTimer(const INT nTimerIdentity);
|
|
static INT pwmStopTimer(const INT nTimerIdentity, const INT nMethod);
|
|
// Register operation
|
|
static INT pwmSetCP(const INT nTimerIdentity, const INT nValue);
|
|
static INT pwmSetDZI(const INT nTimerIdentity, const INT nValue);
|
|
static INT pwmSetCSR(const INT nTimerIdentity, const INT nValue);
|
|
static INT pwmSetDZGenerator(const INT nTimerIdentity, const INT nStatus);
|
|
static INT pwmSetTimerState(const INT nTimerIdentity, const INT nStatus);
|
|
static INT pwmSetInverter(const INT nTimerIdentity, const INT nStatus);
|
|
static INT pwmSetMode(const INT nTimerIdentity, const INT nStatus);
|
|
static INT pwmSetCNR(const INT nTimerIdentity, const INT nValue);
|
|
static INT pwmSetCMR(const INT nTimerIdentity, const INT nValue);
|
|
static UINT pwmGetPDR(const INT nTimerIdentity);
|
|
static INT pwmSetPIER(const INT nTimerIdentity, const INT value);
|
|
static INT pwmCleanPIIR(const INT nTimerIdentity);
|
|
|
|
//Global variable
|
|
static BOOL bPWMIRQFlag = FALSE; //IRQ enable flag, set after PWM IRQ enable
|
|
static BOOL bPWMTimerOpenStatus[PWM_TIMER_NUM]; //timer flag which set after open(for disable IRQ decision)
|
|
static BOOL bPWMTimerStartStatus[PWM_TIMER_NUM]; //timer flag which set after Start count(to avoid incorrectly stop procedure)
|
|
static BOOL bPWMTimerMode[PWM_TIMER_NUM]; //PWM timer toggle/one shot mode
|
|
static BOOL volatile bPWMIntFlag[PWM_TIMER_NUM]; //interrupt flag which set by ISR
|
|
/// @endcond /* HIDDEN_SYMBOLS */
|
|
|
|
|
|
/**
|
|
* @brief The init function of PWM device driver
|
|
*/
|
|
INT pwmInit(void)
|
|
{
|
|
UINT temp;
|
|
// Enable PWM clock
|
|
temp = inpw(REG_CLK_PCLKEN1);
|
|
temp = temp | 0x8000000;
|
|
outpw(REG_CLK_PCLKEN1, temp);
|
|
|
|
sysInstallISR(IRQ_LEVEL_1, PWM_IRQn, (PVOID)pwmISR);
|
|
sysSetLocalInterrupt(ENABLE_IRQ); // Enable CPSR I bit
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* @brief The exit function of PWM device driver
|
|
*/
|
|
INT pwmExit(void)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* @brief The open function of PWM device driver
|
|
* @param[in] nTimerIdentity PWM Timer channel identity
|
|
* @retval Successful PWM successfully opened
|
|
* @retval pwmTimerBusy PWM timer already open
|
|
* @retval pwmInvalidTimerChannel PWM Timer channel number error
|
|
*/
|
|
INT pwmOpen(const INT nTimerIdentity)
|
|
{
|
|
if (nTimerIdentity < PWM_TIMER_MIN || nTimerIdentity > PWM_TIMER_MAX)
|
|
{
|
|
return pwmInvalidTimerChannel;// nTimerIdentity value error
|
|
}
|
|
if (bPWMTimerOpenStatus[nTimerIdentity] == TRUE)
|
|
{
|
|
return pwmTimerBusy;
|
|
}
|
|
if (bPWMIRQFlag == FALSE)
|
|
{
|
|
|
|
sysEnableInterrupt(PWM_IRQn);
|
|
|
|
bPWMIRQFlag = TRUE;
|
|
}
|
|
bPWMTimerOpenStatus[nTimerIdentity] = TRUE;
|
|
|
|
// Set PWM timer default value(CSR->PPR->PCR->CMR->CNR)
|
|
pwmInitTimer(nTimerIdentity);
|
|
|
|
//Enable PIER
|
|
pwmSetPIER(nTimerIdentity, PWM_ENABLE);
|
|
|
|
//Reset PIIR
|
|
pwmCleanPIIR(nTimerIdentity);
|
|
|
|
//Reset PWM timer start count flag
|
|
bPWMTimerStartStatus[nTimerIdentity] = FALSE;
|
|
|
|
return Successful;
|
|
|
|
}
|
|
|
|
/**
|
|
* @brief The close function of PWM device driver
|
|
* @param[in] nTimerIdentity PWM Timer channel identity
|
|
* @retval Successful PWM successfully closed
|
|
* @retval pwmTimerNotOpen PWM timer not open
|
|
* @retval pwmInvalidTimerChannel PWM Timer channel number error
|
|
*/
|
|
INT pwmClose(const INT nTimerIdentity)
|
|
{
|
|
INT nLoop;
|
|
BOOL uAllTimerClose = TRUE;
|
|
if (nTimerIdentity < PWM_TIMER_MIN || nTimerIdentity > PWM_TIMER_MAX)
|
|
{
|
|
return pwmInvalidTimerChannel;// nTimerIdentity value error
|
|
}
|
|
if (bPWMTimerOpenStatus[nTimerIdentity] == FALSE)
|
|
{
|
|
return pwmTimerNotOpen;
|
|
}
|
|
bPWMTimerOpenStatus[nTimerIdentity] = FALSE;
|
|
//Check if all timer stop, IRQ can be disable
|
|
for (nLoop = PWM_TIMER_MIN; nLoop < PWM_TIMER_NUM; nLoop++)
|
|
{
|
|
if (bPWMTimerOpenStatus[nLoop] == TRUE)
|
|
{
|
|
uAllTimerClose = FALSE;
|
|
}
|
|
}
|
|
//All timer stop, disable IRQs
|
|
if (uAllTimerClose == TRUE)
|
|
{
|
|
|
|
sysDisableInterrupt(PWM_IRQn);
|
|
bPWMIRQFlag = FALSE;
|
|
}
|
|
|
|
pwmSetPIER(nTimerIdentity, PWM_DISABLE);
|
|
pwmCleanPIIR(nTimerIdentity);
|
|
|
|
|
|
return Successful;
|
|
|
|
}
|
|
|
|
/**
|
|
* @brief The read function of PWM device driver
|
|
* @param[in] nTimerIdentity PWM Timer channel identity
|
|
* @param[out] pucStatusValue The point of typePWMSTATUS
|
|
* @param[in] uLength The length of typePWMSTATUS
|
|
* @retval Successful Read PWM value successfully
|
|
* @retval pwmTimerNotOpen PWM timer not open
|
|
* @retval pwmInvalidTimerChannel PWM Timer channel number error
|
|
* @retval pwmInvalidStructLength Struct length error(struct type error)
|
|
*/
|
|
INT pwmRead(const INT nTimerIdentity, PUCHAR pucStatusValue, const UINT uLength)
|
|
{
|
|
if (nTimerIdentity < PWM_TIMER_MIN || nTimerIdentity > PWM_TIMER_MAX)
|
|
{
|
|
return pwmInvalidTimerChannel;// nTimerIdentity value error
|
|
}
|
|
if (bPWMTimerOpenStatus[nTimerIdentity] == FALSE)
|
|
{
|
|
return pwmTimerNotOpen;
|
|
}
|
|
if (uLength != sizeof(typePWMSTATUS))
|
|
{
|
|
return pwmInvalidStructLength;// Struct length error(struct type error)
|
|
}
|
|
if (sizeof(*((typePWMSTATUS *)pucStatusValue)) != sizeof(typePWMSTATUS))
|
|
{
|
|
return pwmInvalidStructLength;// Struct length error(struct type error)
|
|
}
|
|
((typePWMSTATUS *)pucStatusValue)->PDR = pwmGetPDR(nTimerIdentity);
|
|
if (bPWMIntFlag[nTimerIdentity] == TRUE)
|
|
{
|
|
bPWMIntFlag[nTimerIdentity] = FALSE;
|
|
((typePWMSTATUS *)pucStatusValue)->InterruptFlag = TRUE;
|
|
}
|
|
else
|
|
{
|
|
((typePWMSTATUS *)pucStatusValue)->InterruptFlag = FALSE;
|
|
}
|
|
|
|
return Successful;
|
|
|
|
}
|
|
|
|
/**
|
|
* @brief The write function of PWM device driver
|
|
* @param[in] nTimerIdentity PWM Timer channel identity
|
|
* @param[in] pucCNRCMRValue The value of CNR and CMR
|
|
* @param[in] uLength For future usage
|
|
* @retval Successful Write PWM setting successfully
|
|
* @retval pwmTimerNotOpen PWM timer not open
|
|
* @retval pwmInvalidTimerChannel PWM Timer channel number error
|
|
*/
|
|
INT pwmWrite(const INT nTimerIdentity, PUCHAR pucCNRCMRValue, const UINT uLength)
|
|
{
|
|
typePWMVALUE pwmvalue;
|
|
INT nStatus;
|
|
if (nTimerIdentity < PWM_TIMER_MIN || nTimerIdentity > PWM_TIMER_MAX)
|
|
{
|
|
return pwmInvalidTimerChannel;// nTimerIdentity value error
|
|
}
|
|
if (bPWMTimerOpenStatus[nTimerIdentity] == FALSE)
|
|
{
|
|
return pwmTimerNotOpen;
|
|
}
|
|
if (uLength != sizeof(typePWMVALUE))
|
|
{
|
|
return pwmInvalidStructLength;// Struct length error(struct type error)
|
|
}
|
|
pwmvalue.value = ((typePWMVALUE *)pucCNRCMRValue)->value;
|
|
nStatus = pwmSetCNR(nTimerIdentity, pwmvalue.field.cnr);
|
|
|
|
if (nStatus != Successful)
|
|
{
|
|
return nStatus;
|
|
}
|
|
nStatus = pwmSetCMR(nTimerIdentity, pwmvalue.field.cmr);
|
|
|
|
if (nStatus != Successful)
|
|
{
|
|
return nStatus;
|
|
}
|
|
return Successful;
|
|
|
|
}
|
|
|
|
/**
|
|
* @brief The ioctl function of PWM device driver
|
|
* @param[in] nTimerIdentity PWM Timer channel identity
|
|
* @param[in] uCommand Ioctl command which indicates different operation
|
|
* @param[in] uIndication Not use in PWM
|
|
* @param[in] uValue The value which use with uCommand
|
|
* @retval Successful PWM ioctl execute successfully
|
|
* @retval pwmTimerNotOpen PWM timer not open
|
|
* @retval pwmInvalidTimerChannel PWM Timer channel number error
|
|
* @retval pwmInvalidIoctlCommand Ioctl command error
|
|
* @retval Others Error according to different uCommand
|
|
*/
|
|
INT pwmIoctl(const INT nTimerIdentity, const UINT uCommand, const UINT uIndication, UINT uValue)
|
|
{
|
|
INT nStatus;
|
|
if (nTimerIdentity < PWM_TIMER_MIN || nTimerIdentity > PWM_TIMER_MAX)
|
|
{
|
|
return pwmInvalidTimerChannel;// nTimerIdentity value error
|
|
}
|
|
if (bPWMTimerOpenStatus[nTimerIdentity] == FALSE)
|
|
{
|
|
return pwmTimerNotOpen;
|
|
}
|
|
switch (uCommand)
|
|
{
|
|
case START_PWMTIMER:
|
|
{
|
|
nStatus = pwmStartTimer(nTimerIdentity);
|
|
break;
|
|
}
|
|
case STOP_PWMTIMER:
|
|
{
|
|
// default stop method is 2
|
|
nStatus = pwmStopTimer(nTimerIdentity, PWM_STOP_METHOD2);
|
|
break;
|
|
}
|
|
case SET_CSR:
|
|
{
|
|
nStatus = pwmSetCSR(nTimerIdentity, uValue);
|
|
break;
|
|
}
|
|
case SET_CP:
|
|
{
|
|
nStatus = pwmSetCP(nTimerIdentity, uValue);
|
|
break;
|
|
}
|
|
case SET_DZI:
|
|
{
|
|
nStatus = pwmSetDZI(nTimerIdentity, uValue);
|
|
break;
|
|
}
|
|
case SET_INVERTER:
|
|
{
|
|
nStatus = pwmSetInverter(nTimerIdentity, uValue);
|
|
break;
|
|
}
|
|
case SET_MODE:
|
|
{
|
|
nStatus = pwmSetMode(nTimerIdentity, uValue);
|
|
break;
|
|
}
|
|
case ENABLE_DZ_GENERATOR:
|
|
{
|
|
nStatus = pwmSetDZGenerator(nTimerIdentity, PWM_ENABLE);
|
|
break;
|
|
}
|
|
case DISABLE_DZ_GENERATOR:
|
|
{
|
|
nStatus = pwmSetDZGenerator(nTimerIdentity, PWM_DISABLE);
|
|
break;
|
|
}
|
|
case ENABLE_PWMGPIOOUTPUT:
|
|
{
|
|
nStatus = pwmInitGPIO(nTimerIdentity, uValue);
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
return pwmInvalidIoctlCommand;
|
|
}
|
|
}
|
|
return nStatus;
|
|
}
|
|
|
|
|
|
/// @cond HIDDEN_SYMBOLS
|
|
|
|
/**
|
|
* @brief The interrupt service routines of PWM
|
|
* @param[in] pvParam IRQ Parameter(not use in PWM)
|
|
*/
|
|
VOID pwmISR(PVOID pvParam)
|
|
{
|
|
INT i;
|
|
|
|
UINT32 uRegisterValue = 0;
|
|
uRegisterValue = inpw(REG_PWM_PIIR);// Get PIIR value
|
|
for (i = 0; i < PWM_TIMER_NUM ; i++)
|
|
{
|
|
if (uRegisterValue & (1 << i))
|
|
{
|
|
bPWMIntFlag[i] = 1;
|
|
outpw(REG_PWM_PIIR, (1 << i));
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief This function set corresponding GPIO as PWM function according to the
|
|
* parameter nTimerIdentity
|
|
* @param[in] nTimerIdentity Timer channel number
|
|
* @retval Successful PWM init GPIO successfully
|
|
* @retval pwmInvalidTimerChannel PWM Timer channel number error
|
|
* @retval pwmInvalidPin PWM output pin setting error
|
|
*/
|
|
static INT pwmInitGPIO(const INT nTimerIdentity, const INT nValue)
|
|
{
|
|
UINT temp = 0;
|
|
|
|
if (nTimerIdentity < PWM_TIMER_MIN || nTimerIdentity > PWM_TIMER_MAX)
|
|
{
|
|
return pwmInvalidTimerChannel;// Timer_num value error
|
|
}
|
|
|
|
if (nTimerIdentity == PWM_TIMER0)
|
|
{
|
|
if (nValue == PWM0_GPA12)
|
|
{
|
|
temp = inpw(REG_SYS_GPA_MFPH);
|
|
temp = (temp & ~0x000F0000) | 0xD0000;
|
|
outpw(REG_SYS_GPA_MFPH, temp);
|
|
}
|
|
else if (nValue == PWM0_GPB2)
|
|
{
|
|
temp = inpw(REG_SYS_GPB_MFPL);
|
|
temp = (temp & ~0xF00) | 0xD00;
|
|
outpw(REG_SYS_GPB_MFPL, temp);
|
|
}
|
|
else
|
|
return pwmInvalidPin;
|
|
}
|
|
else if (nTimerIdentity == PWM_TIMER1)
|
|
{
|
|
if (nValue == PWM1_GPA13)
|
|
{
|
|
temp = inpw(REG_SYS_GPA_MFPH);
|
|
temp = (temp & ~0x00F00000) | 0xD00000;
|
|
outpw(REG_SYS_GPA_MFPH, temp);
|
|
}
|
|
else if (nValue == PWM1_GPB3)
|
|
{
|
|
temp = inpw(REG_SYS_GPB_MFPL);
|
|
temp = (temp & ~0xF000) | 0xD000;
|
|
outpw(REG_SYS_GPB_MFPL, temp);
|
|
}
|
|
else
|
|
return pwmInvalidPin;
|
|
}
|
|
else if (nTimerIdentity == PWM_TIMER2)
|
|
{
|
|
if (nValue == PWM2_GPA14)
|
|
{
|
|
temp = inpw(REG_SYS_GPA_MFPH);
|
|
temp = (temp & ~0x0F000000) | 0xD000000;
|
|
outpw(REG_SYS_GPA_MFPH, temp);
|
|
}
|
|
else if (nValue == PWM2_GPH2)
|
|
{
|
|
temp = inpw(REG_SYS_GPH_MFPL);
|
|
temp = (temp & ~0xF00) | 0xD00;
|
|
outpw(REG_SYS_GPH_MFPL, temp);
|
|
}
|
|
else
|
|
return pwmInvalidPin;
|
|
}
|
|
else
|
|
{
|
|
if (nValue == PWM3_GPA15)
|
|
{
|
|
temp = inpw(REG_SYS_GPA_MFPH);
|
|
temp = (temp & ~0xF0000000) | 0xD0000000;
|
|
outpw(REG_SYS_GPA_MFPH, temp);
|
|
}
|
|
else if (nValue == PWM3_GPH3)
|
|
{
|
|
temp = inpw(REG_SYS_GPH_MFPL);
|
|
temp = (temp & ~0xF000) | 0xD000;
|
|
outpw(REG_SYS_GPH_MFPL, temp);
|
|
}
|
|
else
|
|
return pwmInvalidPin;
|
|
}
|
|
|
|
return Successful;
|
|
}
|
|
|
|
|
|
/**
|
|
* @brief This function initiates PWM timer n and set the default setting to CSR,
|
|
* PPR, PCR, CNR, CMR
|
|
* @param[in] nTimerIdentity Timer channel number
|
|
* @retval Successful PWM init timer successfully
|
|
* @retval pwmInvalidTimerChannel PWM Timer channel number error
|
|
*/
|
|
static INT pwmInitTimer(const INT nTimerIdentity)
|
|
{
|
|
typePPR PWMPPR;
|
|
INT nStatus;
|
|
if (nTimerIdentity < PWM_TIMER_MIN || nTimerIdentity > PWM_TIMER_MAX)
|
|
{
|
|
return pwmInvalidTimerChannel;// nTimerIdentity value error
|
|
}
|
|
|
|
//Set CSR
|
|
nStatus = pwmSetCSR(nTimerIdentity, DEFAULT_CSR);
|
|
|
|
if (nStatus != Successful)
|
|
{
|
|
return nStatus;
|
|
}
|
|
|
|
//Set PPR
|
|
PWMPPR.value = (UINT)inpw(REG_PWM_PPR);
|
|
switch (nTimerIdentity)
|
|
{
|
|
case PWM_TIMER0:
|
|
{
|
|
if (PWMPPR.field.cp0 == 0)
|
|
{
|
|
pwmSetCP(nTimerIdentity, DEFAULT_CP);
|
|
}
|
|
break;
|
|
}
|
|
case PWM_TIMER1:
|
|
{
|
|
if (PWMPPR.field.cp0 == 0)
|
|
{
|
|
pwmSetCP(nTimerIdentity, DEFAULT_CP);
|
|
}
|
|
break;
|
|
}
|
|
case PWM_TIMER2:
|
|
{
|
|
if (PWMPPR.field.cp1 == 0)
|
|
{
|
|
pwmSetCP(nTimerIdentity, DEFAULT_CP);
|
|
}
|
|
break;
|
|
}
|
|
case PWM_TIMER3:
|
|
{
|
|
if (PWMPPR.field.cp1 == 0)
|
|
{
|
|
pwmSetCP(nTimerIdentity, DEFAULT_CP);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
//Set PCR
|
|
nStatus = pwmSetMode(nTimerIdentity, DEFAULT_MODE);
|
|
|
|
if (nStatus != Successful)
|
|
{
|
|
return nStatus;
|
|
}
|
|
bPWMTimerMode[nTimerIdentity] = DEFAULT_MODE;
|
|
|
|
//Set CMR
|
|
nStatus = pwmSetCMR(nTimerIdentity, DEFAULT_CMR);
|
|
|
|
if (nStatus != Successful)
|
|
{
|
|
return nStatus;
|
|
}
|
|
|
|
//Set CNR
|
|
nStatus = pwmSetCNR(nTimerIdentity, DEFAULT_CNR);
|
|
|
|
if (nStatus != Successful)
|
|
{
|
|
return nStatus;
|
|
}
|
|
|
|
return Successful;
|
|
|
|
}
|
|
|
|
|
|
/**
|
|
* @brief This function starts PWM timer according to the parameter
|
|
* @param[in] nTimerIdentity Timer channel number
|
|
* @retval Successful PWM start timer successfully
|
|
* @retval pwmInvalidTimerChannel PWM Timer channel number error
|
|
*/
|
|
static INT pwmStartTimer(const INT nTimerIdentity)
|
|
{
|
|
if (nTimerIdentity < PWM_TIMER_MIN || nTimerIdentity > PWM_TIMER_MAX)
|
|
{
|
|
return pwmInvalidTimerChannel;// Timer_num value error
|
|
}
|
|
pwmSetTimerState(nTimerIdentity, PWM_ENABLE);
|
|
if (bPWMTimerMode[nTimerIdentity] == PWM_TOGGLE)
|
|
{
|
|
bPWMTimerStartStatus[nTimerIdentity] = TRUE;
|
|
}
|
|
|
|
return Successful;
|
|
}
|
|
|
|
/**
|
|
* @brief This function stops PWM timer n using method 1, 2, or 3 according to the
|
|
* parameter nTimerIdentity and nStatus
|
|
* @param[in] nTimerIdentity Timer channel number
|
|
* @param[in] nMethod Stop PWM timer method
|
|
* @retval Successful PWM stop timer successfully
|
|
* @retval pwmInvalidTimerChannel PWM Timer channel number error
|
|
* @retval pwmInvalidStopMethod Stop method error
|
|
*/
|
|
static INT pwmStopTimer(const INT nTimerIdentity, INT nMethod)
|
|
{
|
|
typeCNR PWMCNR;
|
|
if (nTimerIdentity < PWM_TIMER_MIN || nTimerIdentity > PWM_TIMER_MAX)
|
|
{
|
|
// Timer_num value error
|
|
return pwmInvalidTimerChannel;
|
|
}
|
|
//Can't stop before open PWM timer
|
|
if (bPWMTimerOpenStatus[nTimerIdentity] == FALSE)
|
|
{
|
|
return Successful;
|
|
}
|
|
// one shot mode didn't need stop procedure
|
|
if (bPWMTimerMode[nTimerIdentity] == PWM_ONESHOT)
|
|
{
|
|
return Successful;
|
|
}
|
|
// Timer stop already, no need to stop again
|
|
if (bPWMTimerStartStatus[nTimerIdentity] == FALSE)
|
|
{
|
|
return Successful;
|
|
}
|
|
|
|
// Set CNR as 0
|
|
PWMCNR.field.cnr = 0;
|
|
outpw(REG_PWM_CNR0 + (PWM_OFFSET * nTimerIdentity), PWMCNR.value);
|
|
|
|
switch (nMethod)
|
|
{
|
|
case PWM_STOP_METHOD1:
|
|
{
|
|
while (1)
|
|
{
|
|
if (pwmGetPDR(nTimerIdentity) == 0) // Wait PDR reach to 0
|
|
{
|
|
pwmSetTimerState(nTimerIdentity, PWM_DISABLE);// Disable pwm timer
|
|
bPWMIntFlag[nTimerIdentity] = FALSE;
|
|
bPWMTimerStartStatus[nTimerIdentity] = FALSE;
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case PWM_STOP_METHOD2:
|
|
{
|
|
while (1)
|
|
{
|
|
if (bPWMIntFlag[nTimerIdentity] == TRUE) // Wait interrupt happen
|
|
{
|
|
pwmSetTimerState(nTimerIdentity, PWM_DISABLE);// Disable pwm timer
|
|
bPWMIntFlag[nTimerIdentity] = FALSE;
|
|
bPWMTimerStartStatus[nTimerIdentity] = FALSE;
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
/*case PWM_STOP_METHOD3:
|
|
{
|
|
pwmSetPCRState(nTimerIdentity, PWM_DISABLE);// Disable pwm timer
|
|
bPWMIntFlag[nTimerIdentity] = FALSE;
|
|
bPWMTimerStartStatus[nTimerIdentity] = FALSE;
|
|
break;
|
|
}*/
|
|
default:
|
|
{
|
|
return pwmInvalidStopMethod;// Stop method value error
|
|
}
|
|
}
|
|
|
|
return Successful;
|
|
}
|
|
|
|
/**
|
|
* @brief This function set CPn value according to the parameter nTimerIdentity and nValue
|
|
* @param[in] nTimerIdentity Timer channel number
|
|
* @param[in] nValue The value which want to set in CSRn
|
|
* @retval Successful Set CPn successfully
|
|
* @retval pwmInvalidTimerChannel PWM Timer channel number error
|
|
* @retval pwmInvalidCPValue PWM_PPR CPn value out of range
|
|
*/
|
|
static INT pwmSetCP(const INT nTimerIdentity, const INT nValue)
|
|
{
|
|
typePPR PWMPPR;
|
|
if (nTimerIdentity < PWM_TIMER_MIN || nTimerIdentity > PWM_TIMER_MAX)
|
|
{
|
|
return pwmInvalidTimerChannel;// Timer_num value error
|
|
}
|
|
if (nValue < CP_MIN || nValue > CP_MAX)
|
|
{
|
|
return pwmInvalidCPValue;// CP value error
|
|
}
|
|
PWMPPR.value = (UINT)inpw(REG_PWM_PPR);
|
|
switch (nTimerIdentity)
|
|
{
|
|
case PWM_TIMER0:
|
|
{
|
|
PWMPPR.field.cp0 = nValue;
|
|
break;
|
|
}
|
|
case PWM_TIMER1:
|
|
{
|
|
PWMPPR.field.cp0 = nValue;
|
|
break;
|
|
}
|
|
case PWM_TIMER2:
|
|
{
|
|
PWMPPR.field.cp1 = nValue;
|
|
break;
|
|
}
|
|
case PWM_TIMER3:
|
|
{
|
|
PWMPPR.field.cp1 = nValue;
|
|
break;
|
|
}
|
|
}
|
|
outpw(REG_PWM_PPR, PWMPPR.value);
|
|
|
|
return Successful;
|
|
}
|
|
|
|
/**
|
|
* @brief This function set DZIn value according to the parameter nTimerIdentity and nValue
|
|
* @param[in] nTimerIdentity Timer channel number
|
|
* @param[in] nValue The value which want to set in DZIn
|
|
* @retval Successful Set DZIn successfully
|
|
* @retval pwmInvalidTimerChannel PWM Timer channel number error
|
|
* @retval pwmInvalidDZIValue PWM_PPR DZIn value out of range
|
|
*/
|
|
static INT pwmSetDZI(const INT nTimerIdentity, const INT nValue)
|
|
{
|
|
typePPR PWMPPR;
|
|
if (nTimerIdentity < PWM_TIMER_MIN || nTimerIdentity > PWM_TIMER_MAX)
|
|
{
|
|
return pwmInvalidTimerChannel;// Timer_num value error
|
|
}
|
|
if (nValue < DZI_MIN || nValue > DZI_MAX)
|
|
{
|
|
return pwmInvalidDZIValue;// CSR value error
|
|
}
|
|
PWMPPR.value = (UINT)inpw(REG_PWM_PPR);
|
|
switch (nTimerIdentity)
|
|
{
|
|
case PWM_TIMER0:
|
|
{
|
|
PWMPPR.field.dzi0 = nValue;
|
|
break;
|
|
}
|
|
case PWM_TIMER1:
|
|
{
|
|
PWMPPR.field.dzi0 = nValue;
|
|
break;
|
|
}
|
|
case PWM_TIMER2:
|
|
{
|
|
PWMPPR.field.dzi1 = nValue;
|
|
break;
|
|
}
|
|
case PWM_TIMER3:
|
|
{
|
|
PWMPPR.field.dzi1 = nValue;
|
|
break;
|
|
}
|
|
}
|
|
outpw(REG_PWM_PPR, PWMPPR.value);
|
|
|
|
return Successful;
|
|
}
|
|
|
|
/**
|
|
* @brief This function set CSRn value according to the parameter nTimerIdentity and nValue
|
|
* @param[in] nTimerIdentity Timer channel number
|
|
* @param[in] nValue The value which want to set in CSRn
|
|
* @retval Successful Set CSRn successfully
|
|
* @retval pwmInvalidTimerChannel PWM Timer channel number error
|
|
*/
|
|
static INT pwmSetCSR(const INT nTimerIdentity, const INT nValue)
|
|
{
|
|
typeCSR PWMCSR;
|
|
if (nTimerIdentity < PWM_TIMER_MIN || nTimerIdentity > PWM_TIMER_MAX)
|
|
{
|
|
return pwmInvalidTimerChannel;// Timer_num value error
|
|
}
|
|
if (nValue < CSR_MIN || nValue > CSR_MAX)
|
|
{
|
|
return pwmInvalidCSRValue;// CSR value error
|
|
}
|
|
PWMCSR.value = (UINT)inpw(REG_PWM_CSR);
|
|
switch (nTimerIdentity)
|
|
{
|
|
case PWM_TIMER0:
|
|
{
|
|
PWMCSR.field.csr0 = nValue;
|
|
break;
|
|
}
|
|
case PWM_TIMER1:
|
|
{
|
|
PWMCSR.field.csr1 = nValue;
|
|
break;
|
|
}
|
|
case PWM_TIMER2:
|
|
{
|
|
PWMCSR.field.csr2 = nValue;
|
|
break;
|
|
}
|
|
case PWM_TIMER3:
|
|
{
|
|
PWMCSR.field.csr3 = nValue;
|
|
break;
|
|
}
|
|
}
|
|
outpw(REG_PWM_CSR, PWMCSR.value);
|
|
|
|
return Successful;
|
|
}
|
|
|
|
/**
|
|
* @brief This function enable/disable PWM channel n dead zone function according to the
|
|
* parameter nTimerIdentity and nStatus
|
|
* @param[in] nTimerIdentity Timer channel number
|
|
* @param[in] nStatus PWMDZG_ENABLE/PWMDZG_DISABLE
|
|
* @retval Successful Set dead zone successfully
|
|
* @retval pwmInvalidTimerChannel PWM Timer channel number error
|
|
* @retval pwmInvalidDZGStatus PWM Dead-Zone Generator enable/disable status error
|
|
*/
|
|
static INT pwmSetDZGenerator(const INT nTimerIdentity, INT nStatus)
|
|
{
|
|
typePCR PWMPCR;
|
|
if (nTimerIdentity < PWM_TIMER_MIN || nTimerIdentity > PWM_TIMER_MAX)
|
|
{
|
|
return pwmInvalidTimerChannel;// Timer_num value error
|
|
}
|
|
if (nStatus != PWMDZG_ENABLE && nStatus != PWMDZG_DISABLE)
|
|
{
|
|
return pwmInvalidDZGStatus;// PCR inverter value error
|
|
}
|
|
PWMPCR.value = (UINT)inpw(REG_PWM_PCR);
|
|
switch (nTimerIdentity)
|
|
{
|
|
case PWM_TIMER0:
|
|
{
|
|
PWMPCR.field.grpup0_dzen = nStatus;
|
|
break;
|
|
}
|
|
case PWM_TIMER1:
|
|
{
|
|
PWMPCR.field.grpup0_dzen = nStatus;
|
|
break;
|
|
}
|
|
case PWM_TIMER2:
|
|
{
|
|
PWMPCR.field.grpup1_dzen = nStatus;
|
|
break;
|
|
}
|
|
case PWM_TIMER3:
|
|
{
|
|
PWMPCR.field.grpup1_dzen = nStatus;
|
|
break;
|
|
}
|
|
}
|
|
outpw(REG_PWM_PCR, PWMPCR.value);
|
|
|
|
return Successful;
|
|
}
|
|
|
|
/**
|
|
* @brief This function set PWM channel n enable/disable according to the
|
|
* parameter nTimerIdentity and nStatus
|
|
* @param[in] nTimerIdentity Timer channel number
|
|
* @param[in] nStatus PWM_ENABLE/PWMDISABLE
|
|
* @retval Successful Set channel enable/disable successfully
|
|
* @retval pwmInvalidTimerChannel PWM Timer channel number error
|
|
*/
|
|
static INT pwmSetTimerState(const INT nTimerIdentity, INT nStatus)
|
|
{
|
|
typePCR PWMPCR;
|
|
if (nTimerIdentity < PWM_TIMER_MIN || nTimerIdentity > PWM_TIMER_MAX)
|
|
{
|
|
return pwmInvalidTimerChannel;// Timer_num value error
|
|
}
|
|
if (nStatus != PWM_ENABLE && nStatus != PWM_DISABLE)
|
|
{
|
|
return pwmInvalidTimerStatus;
|
|
}
|
|
PWMPCR.value = (UINT)inpw(REG_PWM_PCR);
|
|
switch (nTimerIdentity)
|
|
{
|
|
case PWM_TIMER0:
|
|
{
|
|
PWMPCR.field.ch0_en = nStatus;
|
|
break;
|
|
}
|
|
case PWM_TIMER1:
|
|
{
|
|
PWMPCR.field.ch1_en = nStatus;
|
|
break;
|
|
}
|
|
case PWM_TIMER2:
|
|
{
|
|
PWMPCR.field.ch2_en = nStatus;
|
|
break;
|
|
}
|
|
case PWM_TIMER3:
|
|
{
|
|
PWMPCR.field.ch3_en = nStatus;
|
|
break;
|
|
}
|
|
}
|
|
outpw(REG_PWM_PCR, PWMPCR.value);
|
|
|
|
return Successful;
|
|
}
|
|
|
|
|
|
/**
|
|
* @brief This function set PWM channel n inverter on/off according to the
|
|
* parameter nTimerIdentity and nStatus
|
|
* @param[in] nTimerIdentity Timer channel number
|
|
* @param[in] nStatus PWM_ENABLE/PWM_DISABLE
|
|
* @retval Successful Set inverter successfully
|
|
* @retval pwmInvalidTimerChannel PWM Timer channel number error
|
|
* @retval pwmInvalidInverterValue Inverter value error
|
|
*/
|
|
static INT pwmSetInverter(const INT nTimerIdentity, INT nStatus)
|
|
{
|
|
typePCR PWMPCR;
|
|
if (nTimerIdentity < PWM_TIMER_MIN || nTimerIdentity > PWM_TIMER_MAX)
|
|
{
|
|
return pwmInvalidTimerChannel;// Timer_num value error
|
|
}
|
|
if (nStatus != PWM_INVON && nStatus != PWM_INVOFF)
|
|
{
|
|
return pwmInvalidInverterValue;// PCR inverter value error
|
|
}
|
|
PWMPCR.value = (UINT)inpw(REG_PWM_PCR);
|
|
switch (nTimerIdentity)
|
|
{
|
|
case PWM_TIMER0:
|
|
{
|
|
PWMPCR.field.ch0_inverter = nStatus;
|
|
break;
|
|
}
|
|
case PWM_TIMER1:
|
|
{
|
|
PWMPCR.field.ch1_inverter = nStatus;
|
|
break;
|
|
}
|
|
case PWM_TIMER2:
|
|
{
|
|
PWMPCR.field.ch2_inverter = nStatus;
|
|
break;
|
|
}
|
|
case PWM_TIMER3:
|
|
{
|
|
PWMPCR.field.ch3_inverter = nStatus;
|
|
break;
|
|
}
|
|
}
|
|
outpw(REG_PWM_PCR, PWMPCR.value);
|
|
|
|
return Successful;
|
|
}
|
|
|
|
/**
|
|
* @brief This function set PWM channel n toggle/one shot mode according to the
|
|
* parameter nTimerIdentity and nStatus
|
|
* @param[in] nTimerIdentity Timer channel number
|
|
* @param[in] nStatus PWM_TOGGLE/PWM_ONESHOT
|
|
* @retval Successful Set operation mode successfully
|
|
* @retval pwmInvalidTimerChannel PWM Timer channel number error
|
|
* @retval pwmInvalidModeStatus Operating mode error
|
|
*/
|
|
static INT pwmSetMode(const INT nTimerIdentity, INT nStatus)
|
|
{
|
|
typePCR PWMPCR;
|
|
if (nTimerIdentity < PWM_TIMER_MIN || nTimerIdentity > PWM_TIMER_MAX)
|
|
{
|
|
return pwmInvalidTimerChannel;// Timer_num value error
|
|
}
|
|
if (nStatus != PWM_TOGGLE && nStatus != PWM_ONESHOT)
|
|
{
|
|
return pwmInvalidModeStatus;// PCR inverter value error
|
|
}
|
|
PWMPCR.value = (UINT)inpw(REG_PWM_PCR);
|
|
switch (nTimerIdentity)
|
|
{
|
|
case PWM_TIMER0:
|
|
{
|
|
PWMPCR.field.ch0_mode = nStatus;
|
|
break;
|
|
}
|
|
case PWM_TIMER1:
|
|
{
|
|
PWMPCR.field.ch1_mode = nStatus;
|
|
break;
|
|
}
|
|
case PWM_TIMER2:
|
|
{
|
|
PWMPCR.field.ch2_mode = nStatus;
|
|
break;
|
|
}
|
|
case PWM_TIMER3:
|
|
{
|
|
PWMPCR.field.ch3_mode = nStatus;
|
|
break;
|
|
}
|
|
}
|
|
outpw(REG_PWM_PCR, PWMPCR.value);
|
|
bPWMTimerMode[nTimerIdentity] = nStatus;
|
|
|
|
return Successful;
|
|
}
|
|
|
|
|
|
/**
|
|
* @brief This function set PWM_CNRn value according to the parameter nTimerIdentity and nValue
|
|
* @param[in] nTimerIdentity Timer channel number
|
|
* @param[in] nValue CNR value
|
|
* @retval Successful Set CNR successfully
|
|
* @retval pwmInvalidTimerChannel PWM Timer channel number error
|
|
* @retval pwmInvalidCNRValue Invalid CNR value
|
|
*/
|
|
static INT pwmSetCNR(const INT nTimerIdentity, INT nValue)
|
|
{
|
|
typeCNR PWMCNR;
|
|
if (nTimerIdentity < PWM_TIMER_MIN || nTimerIdentity > PWM_TIMER_MAX)
|
|
{
|
|
return pwmInvalidTimerChannel;// Timer_num value error
|
|
}
|
|
if (nValue < CNR_MIN || nValue > CNR_MAX)
|
|
{
|
|
return pwmInvalidCNRValue;// PCR inverter value error
|
|
}
|
|
PWMCNR.field.cnr = nValue;
|
|
outpw(REG_PWM_CNR0 + (PWM_OFFSET * nTimerIdentity), PWMCNR.value);
|
|
|
|
return Successful;
|
|
}
|
|
|
|
/**
|
|
* @brief This function set PWM_CMRn value according to the parameter nTimerIdentity and nValue
|
|
* @param[in] nTimerIdentity Timer channel number
|
|
* @param[in] nValue CMR value
|
|
* @retval Successful Set CMR successfully
|
|
* @retval pwmInvalidTimerChannel PWM Timer channel number error
|
|
* @retval pwmInvalidCMRValue Invalid CMR value
|
|
*/
|
|
static INT pwmSetCMR(const INT nTimerIdentity, INT nValue)
|
|
{
|
|
typeCMR PWMCMR;
|
|
if (nTimerIdentity < PWM_TIMER_MIN || nTimerIdentity > PWM_TIMER_MAX)
|
|
{
|
|
return pwmInvalidTimerChannel;// Timer_num value error
|
|
}
|
|
if (nValue < CMR_MIN || nValue > CMR_MAX)
|
|
{
|
|
return pwmInvalidCMRValue;// CMR value error
|
|
}
|
|
PWMCMR.field.cmr = nValue;
|
|
outpw(REG_PWM_CMR0 + (PWM_OFFSET * nTimerIdentity), PWMCMR.value);
|
|
|
|
return Successful;
|
|
}
|
|
|
|
/**
|
|
* @brief This function return the PDR value of PWM timer n
|
|
* @param[in] nTimerIdentity Timer channel number
|
|
* @retval pwmInvalidTimerChannel PWM Timer channel number error
|
|
* @retval Others Current PDR value
|
|
*/
|
|
static UINT pwmGetPDR(const INT nTimerIdentity)
|
|
{
|
|
if (nTimerIdentity < PWM_TIMER_MIN || nTimerIdentity > PWM_TIMER_MAX)
|
|
{
|
|
return pwmInvalidTimerChannel;// Timer_num value error
|
|
}
|
|
else
|
|
{
|
|
return (UINT)inpw(REG_PWM_PDR0 + (PWM_OFFSET * nTimerIdentity)); // Return PDR value
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief This function set the PIERn bit of PWM timer n as 1 or 0 according to the
|
|
* parameter nTimerIdentity and nValue
|
|
* @param[in] nTimerIdentity Timer channel number
|
|
* @param[in] nValue PWM_ENABLE/PWM_DISABLE
|
|
* @retval Successful Set PIER successfully
|
|
* @retval pwmInvalidTimerChannel PWM Timer channel number error
|
|
*/
|
|
static INT pwmSetPIER(const INT nTimerIdentity, INT nValue)
|
|
{
|
|
UINT uRegisterValue = 0;;
|
|
if (nTimerIdentity < PWM_TIMER_MIN || nTimerIdentity > PWM_TIMER_MAX)
|
|
{
|
|
return pwmInvalidTimerChannel;// Timer_num value error
|
|
}
|
|
else
|
|
{
|
|
uRegisterValue = (UINT)inpw(REG_PWM_PIER);
|
|
if (nValue == PWM_ENABLE)
|
|
{
|
|
uRegisterValue = uRegisterValue | (1 << nTimerIdentity); // Set PIER
|
|
}
|
|
else
|
|
{
|
|
uRegisterValue = uRegisterValue & (0 << nTimerIdentity); // Clear PIER
|
|
}
|
|
outpw(REG_PWM_PIER, uRegisterValue);// Write value to PIER
|
|
|
|
return Successful;
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* @brief This function clear PIIRn bit according to the parameter nTimerIdentity
|
|
* @param[in] nTimerIdentity Timer channel number
|
|
* @retval Successful Clear PIIR successfully
|
|
* @retval pwmInvalidTimerChannel PWM Timer channel number error
|
|
*/
|
|
static INT pwmCleanPIIR(const INT nTimerIdentity)
|
|
{
|
|
UINT uRegisterValue = 0;
|
|
if (nTimerIdentity < PWM_TIMER_MIN || nTimerIdentity > PWM_TIMER_MAX)
|
|
{
|
|
return pwmInvalidTimerChannel;// nTimerIdentity value error
|
|
}
|
|
uRegisterValue = (UINT)inpw(REG_PWM_PIIR);
|
|
uRegisterValue = uRegisterValue & ~(1 << nTimerIdentity);
|
|
outpw(REG_PWM_PIIR, uRegisterValue);
|
|
|
|
return Successful;
|
|
}
|
|
|
|
/// @endcond /* HIDDEN_SYMBOLS */
|
|
|
|
/*@}*/ /* end of group N9H30_PWM_EXPORTED_FUNCTIONS */
|
|
|
|
/*@}*/ /* end of group N9H30_PWM_Driver */
|
|
|
|
/*@}*/ /* end of group N9H30_Device_Driver */
|
|
|
|
/*** (C) COPYRIGHT 2018 Nuvoton Technology Corp. ***/
|