Files
systemvalidation-neupfc/mode1.cpp
T
2022-08-24 15:08:08 +08:00

351 lines
10 KiB
C++

/****************************************************************************
* @file main.c
* @version V3.0err
* $Revision: 4 $
* $Date: 17/05/04 12:57p $
* @brief Perform A/D Conversion with ADC continuous scan mode.
* @note
* Copyright (C) 2016 Nuvoton Technology Corp. All rights reserved.
*
******************************************************************************/
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include "M0564.h"
#include "define.h"
#define INTERRUPT
// dead time unit = 1/72us
// ex. dead time 72 = 1us, 36 = 0.5us, 18=0.25us
// ex. dead time 2 = 2/72 us, 3 = 3/72us, 4=4/72us
#define DEAD_ZONE_01 2 // unit=1/72us, PWM0.0 PWM0.1 Dead time
#define DEAD_ZONE_23 3 // unit=1/72us, PWM0.2 PWM0.3 Dead time
#define DEAD_ZONE_45 4 // unit=1/72us, PWM0.4 PWM0.5 Dead time
int Sync = 0;
volatile int Positve = -1, DetectPeriodP, DetectPeriodN;
int StableCnt;
volatile int err;
// phase angle, pwm freq in KHZ
const unsigned int FREQ_TBL[][2] = {
{30, 60},
{50, 80},
{70, 100},
{90, 150},
{110, 150},
{130, 100},
{150, 80},
{180, 60},
{210, 60},
{230, 80},
{250, 100},
{270, 150},
{290, 150},
{310, 100},
{330, 80},
{360, 60}};
unsigned int Period_tbl[361];
/**
* @brief ACMP01 IRQ
*
* @param None
*
* @return None
*
* @details The ACMP01 default IRQ, declared in startup_M0564.s.
*/
extern "C" {
void ACMP01_IRQHandler(void) {
if(ACMP_GET_INT_FLAG(ACMP01, 1)) {
ACMP_CLR_INT_FLAG(ACMP01, 1); // clear interrupt flag
int T = TIMER_GetCounter(TIMER0); // get timer0 counter
if(TIMER0->CTL & TIMER_CTL_CNTEN_Msk) {
if(T < NOISE) return; // noise. skip
} else {
//StableCnt = 0;
//Positve = -1;
}
TIMER_Stop(TIMER0); // stop timer0
TIMER_ClearIntFlag(TIMER0); // clear timer0 flag
TIMER0->CNT = 0; // set timer0 cnt to 0
TIMER_Start(TIMER0); // start timer0
if(HZ_50U < T || T < HZ_60L) { // not in range
Positve = -1;
StableCnt = 0;
err = 1;
} else {
if(StableCnt < STABLE_CNT) { // wait until stable
StableCnt++;
} else {
if(ACMP_GET_OUTPUT(ACMP01, 1)) { // N > L
Positve = 1; // positve
DetectPeriodN = T; // yes, Save period
} else { // L <= N
Positve = 0; // positve
DetectPeriodP = T; // yes, Save period
}
}
}
}
}
void TMR2_IRQHandler(void) {
TIMER_ClearIntFlag(TIMER2); // clear interrupt flag
PWM_Func();
}
}
/*---------------------------------------------------------------------------------------------------------*/
/* Init TABLE */
/*---------------------------------------------------------------------------------------------------------*/
void TABLE_Init() {
for(int i = 0, j = 0 ; i < 361 ; i++) {
if(i > FREQ_TBL[j][0]) {
j++;
}
Period_tbl[i] = (BASE_CLOCK/1000 + (FREQ_TBL[j][1]/2))/FREQ_TBL[j][1] - 1;
}
}
/*---------------------------------------------------------------------------------------------------------*/
/* WM callback */
/*---------------------------------------------------------------------------------------------------------*/
void PWM_Func() {
int currState, T, PeriodN, PeriodP;
do { // Get Curr State, Period and time
currState = Positve;
T = TIMER_GetCounter(TIMER0);
PeriodN = DetectPeriodN;
PeriodP = DetectPeriodP;
} while(currState != Positve); // ACMP interrupt occurs ?
if(currState < 0) { // Unrecognized signal?
ComplementaryPWM0(0, 0); // Turn off PWM
ComplementaryPWM0(2, 0); // Turn off PWM
ComplementaryPWM0(4, 0); // Turn off PWM
} else if(TIMER_GetIntFlag(TIMER0)) { // Unrecognized signal?
Positve = -1;
StableCnt = 0;
ComplementaryPWM0(0, 0); // Turn off PWM
ComplementaryPWM0(2, 0); // Turn off PWM
ComplementaryPWM0(4, 0); // Turn off PWM
} else {
Sync = SYNC_LOST_TIME;
int Angle;
if(currState == 0) { // negative wave
if(T >= PeriodN) { // over 360?
Angle = 359;
} else {
Angle = 180 + 180*T/PeriodN; // calculate angle
}
} else {
if(T >= PeriodP) { // over 180?
Angle = 179;
} else {
Angle = 180*T/PeriodP; // calculate angle
}
}
#ifdef DEBUG_IO
const int N = 13;
if(Angle >= FREQ_TBL[N][0] && Angle <= FREQ_TBL[N+1][0]) {
PC0 = 1;
} else {
PC0 = 0;
} // set output pwm
#else
int T = Period_tbl[Angle]; // get output freq
ComplementaryPWM0(0, T); // output pwm
ComplementaryPWM0(2, T); // output pwm
ComplementaryPWM0(4, T); // output pwm
#endif
}
}
/*---------------------------------------------------------------------------------------------------------*/
/* UART function */
/*---------------------------------------------------------------------------------------------------------*/
void UART_Func() {
int P1, P2;
int Func = UART_Command(P1, P2);
if(Func) {// command is received?
switch(Func) {
case 'v': // read v
print("%d\r\n", ADC_GET_CONVERSION_DATA(ADC, P1));
break;
case 'f': // read f
case 't': // read t
break;
case 'F': // write F
PWM(P1, P2>>1, P2);
break;
case 'T': // write T
case 'V': // write V
case 'a': // left
case 'w': // up
case 'd': // right
case 'x': // down
case ' ': // space
print("NA\r\n");
break;
}
}
}
/*---------------------------------------------------------------------------------------------------------*/
/* BUTTON function */
/*---------------------------------------------------------------------------------------------------------*/
void BUTTON_Func() {
if(Sync) {
Sync--;
}
static int t;
if(++t >= BLINK_TIME) {
t = 0;
if(Sync) SEG_DP = 0; // if signal is valid, blink DP
LED = 0;
if(err) {// if signal is unrecognized, display number counting
err = 0;
static unsigned char disp_num;
if(++disp_num < '0' || disp_num > '9') disp_num = '0';
Display(disp_num);
}
} else {
SEG_DP = 1;
LED = 1;
}
static unsigned int pressed = 0, deboounce_cnt;
if(pressed) {
if(!UP || !DOWN || !LEFT || !RIGHT) { // key is not released
deboounce_cnt = DEBOUNCE_TIME;
} else if(--deboounce_cnt == 0) {
pressed = 0;
}
} else if(!UP) {// UP is pressed
pressed = 1;
deboounce_cnt = DEBOUNCE_TIME;
} else if(!DOWN) {// DOWN is pressed
pressed = 1;
deboounce_cnt = DEBOUNCE_TIME;
} else if(!LEFT) {// LEFT is pressed
pressed = 1;
deboounce_cnt = DEBOUNCE_TIME;
} else if(!RIGHT) {// RIGHT is pressed
pressed = 1;
deboounce_cnt = DEBOUNCE_TIME;
}
}
/*---------------------------------------------------------------------------------------------------------*/
/* MAIN function */
/*---------------------------------------------------------------------------------------------------------*/
int main(void)
{
/* Unlock protected registers */
SYS_UnlockReg();
/* Init System, IP clock and multi-function I/O */
SYS_Init();
/* Lock protected registers */
SYS_LockReg();
/* Init TABLE */
TABLE_Init();
// Display 8
Display('8');
/* Init TIMER0 */
TIMER0_Init();
/* Init TIMER1 */
TIMER1_Init();
/* Set Pwm mode as complementary mode */
PWM_ENABLE_COMPLEMENTARY_MODE(PWM0);
// Initial PWM
PWM_Init();
// Set PWM0.0 PWM0.1 Dead time
SetPWM0DeadZone(0, DEAD_ZONE_01);
// Set PWM0.2 PWM0.3 Dead time
SetPWM0DeadZone(2, DEAD_ZONE_23);
// Set PWM0.4 PWM0.5 Dead time
SetPWM0DeadZone(4, DEAD_ZONE_45);
// Initial ADC
ADC_Init();
/* Init UART1 */
UART1_Init();
// Delay 0.5 sec
TIMER1_Delay(500000);
// Display 0
Display('0');
/* Init ACMP */
ACMP_Init();
/* Enable ACMP01 interrupt */
NVIC_EnableIRQ(ACMP01_IRQn);
#ifdef INTERRUPT
/* Init TIMER2 */
TIMER2_Init();
#endif
while(1) {
#ifndef INTERRUPT
PWM_Func();
#endif
UART_Func();
if(TIMER_GetIntFlag(TIMER1)) { // timer1 elapsed?
TIMER_ClearIntFlag(TIMER1); // clear timer1 flags
if(Shutdown == 0) {
BUTTON_Func();
}
if(SHUTDOWN_MODE_CHANGED() != 0) {
if(Shutdown) {
/* Enable TIMER2 interrupt */
NVIC_DisableIRQ(TMR2_IRQn);
TIMER_ClearIntFlag(TIMER2);
NVIC_DisableIRQ(ACMP01_IRQn);
TIMER_Stop(TIMER0); // stop timer0
TIMER_ClearIntFlag(TIMER0); // clear timer0 flag
Positve = -1;
StableCnt = 0;
ComplementaryPWM0(0, 0); // Turn off PWM
ComplementaryPWM0(2, 0); // Turn off PWM
ComplementaryPWM0(4, 0); // Turn off PWM
Display('E');
} else {
Display('0');
TIMER_Stop(TIMER0); // stop timer0
TIMER_ClearIntFlag(TIMER0); // clear timer0 flag
NVIC_EnableIRQ(ACMP01_IRQn);
TIMER_ClearIntFlag(TIMER2);
/* Enable TIMER2 interrupt */
NVIC_EnableIRQ(TMR2_IRQn);
}
}
}
}
}
/*** (C) COPYRIGHT 2016 Nuvoton Technology Corp. ***/