css_cmake_test/f2833x/examples/eqep_freqcal/Example_freqcal.c

272 lines
9.0 KiB
C
Raw Normal View History

2024-01-19 12:18:27 +03:00
//###########################################################################
//
// FILE: Example_freqcal.c
//
// TITLE: EXAMPLE_FREQCAL_C Frequency Calculation
//
//! \addtogroup f2833x_example_list
//! \section EXAMPLE_FREQCAL_C Frequency Calculation (Example_freqal.c)
//!
//! This file includes the EQEP initialization and frequency calculation
//! functions called by \b Example_2833xEqep_freqcal.c.
//! The frequency calculation steps performed by FREQCAL_Calc()at
//! SYSCLKOUT = 150 MHz and 100 MHZ are described below:
//!
//! -# This program calculates: \b **freqhz_fr** for SYSCLKOUT = 150MHz \n
//! \f[ freqhz\_fr\ or\ v = \frac{x_{2}-x_{1}}{T} .......... 1 \f] \n
//! If \f[ \frac{max}{base}\ freq = 10kHz => 10kHz = \
\frac{x_{2}-x_{1}}{(2/100Hz)} .......... 2\f] \n
//! \f[ max (x_{2}-x_{1}) = 200 counts = freqScaler\_fr \f]
//!
//! \note \f$ T = \frac{2}{100Hz} \f$ . 2 is from \f$ \frac{x_{2}-x_{1}}{2}\f$
//! because QPOSCNT counts 2 edges per cycle (rising and falling)
//!
//! If both sides of Equation 2 are divided by 10 kHz, then: \n
//! \f[ 1 = \frac{x_{2}-x_{1}}{10kHz*(2/100Hz)}\f]\n where,
//! \f[ [10kHz*\frac{2}{100Hz}] = 200 \f]\n
//! Because \f[ x_{2}-x_{1} < 200 (max)\f]
//! \f[ \frac{x_{2}-x_{1}}{200} < 1 \f]\n for all frequencies less than max\n
//! \f[ freq\_fr = \frac{x_{2}-x_{1}}{200}\ or\ \
\frac{x_{2}-x_{1}}{10kHz*(2/100Hz)} .......... 3\f] \n
//!
//! To get back to original velocity equation, Equation 1, multiply
//! Equation 3 by 10 kHz\n
//! \f[ freqhz\_fr(or\ velocity) = \
10kHz*\frac{x_{2}-x_{1}}{10kHz*(2/100Hz)}\f]\n
//! \f[ = \frac{x_{2}-x_{1}}{(2/100Hz)} .......... final\ equation\f] \n
//!
//! -# \b **min \b freq** \f$ = \frac{1\ count}{(2/100Hz)} = 50 Hz\f$
//! -# \b **freqhz_pr** \n
//! \f[ freqhz\_pr\ or\ v = \frac{X}{t_{2}-t_{1}} .......... 4\f] \n
//! If \f[ \frac{max}{base}\ freq = 10kHz => 10kHz = \frac{(4/2)}{T} = \
\frac{4}{2T} \f] \n
//! where,
//! - 4 = QCAPCTL [UPPS] (Unit timeout - once every 4 edges)
//! - 2 = divide by 2 because QPOSCNT counts 2 edges per cycle
//! (rising and falling)
//! - T = time in seconds
//! = \f$ \frac{t_{2}-t_{1}}{(150MHz/128)}, t_{2}-t_{1} \f$ =
//! # of QCAPCLK cycles,
//! \n and \f$ 1\ QCAPCLK\ cycle = \frac{1}{(150MHz/128)} = QCPRDLAT \f$
//!
//! So: \f[ 10 kHz = 4*\frac{(150MHz/128)}{2*(t_{2}-t_{1})} \f] \n
//! \f[ t_{2}-t_{1} = 4*\frac{(150MHz/128)}{10kHz*2} = \
\frac{(150MHz/128)}{((2*10KHz)/4)} .......... 5\f] \n
//! \f[ = 234\ QCAPCLK\ cycles = maximum (t_{2}-t_{1}) = freqScaler\_pr \f]
//! Divide both sides by \f$ (t_{2}-t_{1}) \f$, and:\n
//! \f[ 1 = \frac{234}{t_{2}-t_{1}} = \
\frac{(150MHz/128)/((2*10KHz)/4)}{t_{2}-t_{1}} \f]\n
//! Because \f$ (t_{2}-t_{1}) < 234 (max) \f$,
//! \f$ \frac{234}{t_{2}-t_{1}} < 1 \f$ for all frequencies less than max \n
//! \f[ freq\_pr = \frac{234}{t_{2}-t_{1}}\ or\ \
\frac{(150MHz/128)/((2*10KHz)/4)}{t_{2}-t_{1}} .......... 6\f] \n
//! Now within velocity limits, to get back to original velocity equation,
//! Equation 1, multiply Equation 6 by 10 kHz: \n
//! \f[ freqhz\_fr(or\ velocity) = \
10kHz*\frac{(150MHz/128)/((2*10KHz)/4)}{t_{2}-t_{1}}\f]\n
//! \f[ = \frac{(150MHz/128)*4}{2*(t_{2}-t_{1})} \f]\n
//! or
//! \f[ \frac{4}{2*(t_{2}-t_{1})*(QCPRDLAT)} .......... final\ equation\f] \n
//!
//! For 100 MHz Operation:
//!
//! The same calculations as above are performed, but with 100 MHz
//! instead of 150MHz when calculating freqhz_pr, and at UPPS of 8
//! instead of 4. The value for freqScaler_pr becomes:
//! (100MHz/128)/(2*10kHz/8) = 313
//!
//! More detailed calculation results can be found in the Example_freqcal.xls
//! spreadsheet included in the example folder.
//
//###########################################################################
// $TI Release: $
// $Release Date: $
// $Copyright:
// Copyright (C) 2009-2023 Texas Instruments Incorporated - http://www.ti.com/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
// Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//
// Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the
// distribution.
//
// Neither the name of Texas Instruments Incorporated nor the names of
// its contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// $
//###########################################################################
//
// Included Files
//
#include "DSP28x_Project.h" // Device Headerfile and Examples Include File
#include "Example_freqcal.h" // Example specific include file
//
// FREQCAL_Init -
//
void
FREQCAL_Init(void)
{
#if (CPU_FRQ_150MHZ)
EQep1Regs.QUPRD=1500000; // Unit Timer for 100Hz at 150MHz SYSCLKOUT
#endif
#if (CPU_FRQ_100MHZ)
EQep1Regs.QUPRD=1000000; // Unit Timer for 100Hz at 100MHz SYSCLKOUT
#endif
EQep1Regs.QDECCTL.bit.QSRC=2; // Up count mode (freq. measurement)
EQep1Regs.QDECCTL.bit.XCR=0;
EQep1Regs.QEPCTL.bit.FREE_SOFT=2;
EQep1Regs.QEPCTL.bit.PCRM=00; // QPOSCNT reset on index evnt
EQep1Regs.QEPCTL.bit.UTE=1; // Unit Timer Enable
EQep1Regs.QEPCTL.bit.QCLM=1; // Latch on unit time out
EQep1Regs.QPOSMAX=0xffffffff;
EQep1Regs.QEPCTL.bit.QPEN=1; // QEP enable
#if (CPU_FRQ_150MHZ)
EQep1Regs.QCAPCTL.bit.UPPS=2; // 1/4 for unit position at 150MHz SYSCLKOUT
#endif
#if (CPU_FRQ_100MHZ)
EQep1Regs.QCAPCTL.bit.UPPS=3; // 1/8 for unit position at 100MHz SYSCLKOUT
#endif
EQep1Regs.QCAPCTL.bit.CCPS=7; // 1/128 for CAP clock
EQep1Regs.QCAPCTL.bit.CEN=1; // QEP Capture Enable
}
//
// FREQCAL_Calc -
//
void
FREQCAL_Calc(FREQCAL *p)
{
unsigned long tmp;
_iq newp,oldp;
//
// Freq Calculation using QEP position counter
// Check unit Time out-event for speed calculation
//
//
// Unit Timer is configured for 100Hz in INIT function
//
//
// For a more detailed explanation of the calculation, read
// the description at the top of this file
//
if(EQep1Regs.QFLG.bit.UTO==1) // Unit Timeout event
{
//
// Differentiator
//
newp=EQep1Regs.QPOSLAT; // Latched POSCNT value
oldp=p->oldpos;
if (newp>oldp)
{
tmp = newp - oldp; // x2-x1 in v=(x2-x1)/T equation
}
else
{
tmp = (0xFFFFFFFF-oldp)+newp;
}
//
// p->freq_fr = (x2-x1)/(T*10KHz)
//
p->freq_fr = _IQdiv(tmp,p->freqScaler_fr);
tmp=p->freq_fr;
if (tmp>=_IQ(1))
{
p->freq_fr = _IQ(1);
}
else
{
p->freq_fr = tmp;
}
//
// Q0 = Q0*GLOBAL_Q => _IQXmpy(), X = GLOBAL_Q
// p->freqhz_fr = (p->freq_fr)*10kHz = (x2-x1)/T
//
p->freqhz_fr = _IQmpy(p->BaseFreq,p->freq_fr);
//
// Update position counter
//
p->oldpos = newp;
EQep1Regs.QCLR.bit.UTO=1; // Clear interrupt flag
}
//
// Freq Calculation using QEP capture counter
//
if(EQep1Regs.QEPSTS.bit.UPEVNT==1) // Unit Position Event
{
if(EQep1Regs.QEPSTS.bit.COEF==0) // No Capture overflow
{
tmp=(unsigned long)EQep1Regs.QCPRDLAT;
}
else // Capture overflow, saturate the result
{
tmp=0xFFFF;
}
//
// p->freq_pr = X/[(t2-t1)*10KHz]
//
p->freq_pr = _IQdiv(p->freqScaler_pr,tmp);
tmp=p->freq_pr;
if (tmp>_IQ(1))
{
p->freq_pr = _IQ(1);
}
else
{
p->freq_pr = tmp;
}
//
// Q0 = Q0*GLOBAL_Q => _IQXmpy(), X = GLOBAL_Q
// p->freqhz_pr =( p->freq_pr)*10kHz = X/(t2-t1)
//
p->freqhz_pr = _IQmpy(p->BaseFreq,p->freq_pr);
//
// Clear Unit position event flag
// Clear overflow error flag
//
EQep1Regs.QEPSTS.all=0x88;
}
}
//
// End of File
//