rt-thread/bsp/nuvoton/libraries/n9h30/Driver/Source/nu_pwm.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. ***/