DSPRelated.com
Forums

Measuring PW using Quad Timer Captures

Started by dflieb20 November 26, 2002
Hello-

I am using the 56807 with the Motorola SDK. I am tryng to measure
the pulse-width of a ~50Hz squarewave using the capture registers on
two timers (one to save the rise time, one to save the fall time).
The rise and fall interrupts fire correctly, but the values returned
by the SDK function ioctl(...,QT_READ_CAPTURE_REG,...) are strange at
best (the rise and fall times are usually separated by only 1 clock
cycle, which is near impossible). I am connecting the signal
generator to timer D0 and using that pin as input to both timers.
Here is the code - thanks for any input.

dave

#include <stdio.h>
#include "port.h"
#include "arch.h"
#include "io.h"
#include "led.h"
#include "qtimerdrv.h"
#include "periph.h"

#include "fcntl.h"
#include "quadraturetimer.h" static void CallbackOnRisingEdge(qt_eCallbackType CallbackType,
void* pParam);
static void CallbackOnFallingEdge(qt_eCallbackType CallbackType,
void* pParam); const qt_sState quadParam1 = {

/* Mode = */ qtCount,
/* InputSource = */ qtCounter0Input,
/* InputPolarity = */ qtNormal,
/* SecondaryInputSource = */ 0,

/* CountFrequency = */ qtRepeatedly,
/* CountLength = */ qtPastCompare,
/* CountDirection = */ qtUp,

/* OutputMode = */ qtToggleOnCompare,
/* OutputPolarity = */ qtNormal,
/* OutputDisabled = */ 0,

/* Master = */ 0,
/* OutputOnMaster = */ 0,
/* CoChannelInitialize = */ 0,
/* AssertWhenForced = */ 0,

/* CaptureMode = */ qtRisingEdge,

/* CompareValue1 = */ 0xFFFF,
/* CompareValue2 = */ 0xFFFF,
/* InitialLoadValue = */ 0x0000,

/* CallbackOnCompare = */ { 0, 0 },
/* CallbackOnOverflow = */ { 0, 0 },
/* CallbackOnInputEdge = */ { CallbackOnRisingEdge, 0 }
};

const qt_sState quadParam2 = {

/* Mode = */ qtCount,
/* InputSource = */ qtCounter0Input,
/* InputPolarity = */ qtNormal,
/* SecondaryInputSource = */ 0,

/* CountFrequency = */ qtRepeatedly,
/* CountLength = */ qtPastCompare,
/* CountDirection = */ qtUp,

/* OutputMode = */ qtToggleOnCompare,
/* OutputPolarity = */ qtNormal,
/* OutputDisabled = */ 0,

/* Master = */ 0,
/* OutputOnMaster = */ 0,
/* CoChannelInitialize = */ 0,
/* AssertWhenForced = */ 0,

/* CaptureMode = */ qtFallingEdge,

/* CompareValue1 = */ 0xFFFF,
/* CompareValue2 = */ 0xFFFF,
/* InitialLoadValue = */ 0x0000,

/* CallbackOnCompare = */ { 0, 0 },
/* CallbackOnOverflow = */ { 0, 0 },
/* CallbackOnInputEdge = */ { CallbackOnFallingEdge, 0 }
}; Word16 RiseTime=0, FallTime=0, PW=0;
int PwUpdated =0, PrevPW=0;; UWord16 TimerD0; /* file handles */
UWord16 TimerD1;
static int LedFD;

/*********************************************************************
********/
main()
{
LedFD = open(BSP_DEVICE_NAME_LED_0, 0);
ioctl(LedFD, LED_OFF, LED_GREEN); TimerD0 = open(BSP_DEVICE_NAME_QUAD_TIMER_D_0, 0, &quadParam1 );
TimerD1 = open(BSP_DEVICE_NAME_QUAD_TIMER_D_1, 0, &quadParam2 ); ioctl(TimerD0, QT_DISABLE, (void*)&quadParam1 );
ioctl(TimerD1, QT_DISABLE, (void*)&quadParam2 );

ioctl(TimerD0, QT_ENABLE_CAPTURE_REG, (void*)&quadParam1 );
ioctl(TimerD1, QT_ENABLE_CAPTURE_REG, (void*)&quadParam2 );

ioctl(TimerD0, QT_ENABLE, (void*)&quadParam1 );
ioctl(TimerD1, QT_ENABLE, (void*)&quadParam2 ); while(1) /* executive loop */
{
if (PwUpdated)
{
PrevPW = PW;
PwUpdated = 0;
}
}
} /*********************************************************************
********/
void CallbackOnRisingEdge(qt_eCallbackType CallbackType, void*
pParam)
{
ioctl(LedFD, LED_ON, LED_GREEN);
ioctl(LedFD, LED_OFF, LED_RED);

RiseTime = ioctl(TimerD0, QT_READ_CAPTURE_REG, (void*)
&quadParam1 );
}

void CallbackOnFallingEdge(qt_eCallbackType CallbackType, void*
pParam)
{
ioctl(LedFD, LED_OFF, LED_GREEN);
ioctl(LedFD, LED_ON, LED_RED);

FallTime = ioctl(TimerD1, QT_READ_CAPTURE_REG, (void*)
&quadParam2 );
PW = FallTime-RiseTime;
PwUpdated = 1;
}



Hey Dave,
 
    I'm using the 56807 for pulse width measurement as well but I use the gated clock mode instead. This mode proved to be a bit more reliable than trying to capture the rise and fall times of a particular signal. I can remember getting screwy number until I switched to the gated clock mode. Remember that you have to consider the pulse width that you are measuring is within the limits of your prescale value settings so that your counter doesn't overflow before the end of your measurement. If it does then things can get messy and you will probably end up sacrificing the resolution or accuracy.  The following code was a simple test program I wrote to simulate the state of charge (SOC) output signal on an electric vehicle. The SOC signal is not always active and when the vehicle reaches 100% then a DC signal is present on the line. I have included a timeout timer so that it doesn't get stuck if nothing fires off the interrupts. If it does happen to timeout, then it will read the input source and take action accordingly.
 
here is the setup:
 
ThinkSOCTmrParm0     => fake signal generator.
PeridTmrParm1            => timeout timer
SocTmrParm0              => gated counter for measuring pulse width
 
 
things to note:
    /* Mode = */                    qtGatedCount,
    /* InputSource = */             qtPrescalerDiv128,  // sets up the granularity of the measurement
    /* InputPolarity = */           qtInverted,               // my signals are inverted coming in so you may need to change this
    /* SecondaryInputSource = */    qtCounter1Input, // you need to specify which pin you are reading
 
   
Lastly, read the section 14.6.4 in the dsp5680x users manual if you want to know how the gated count works.
 
Hope you find this helpful
 
Best Regards
 
Victor
 
 
Victor Miramontes
Principal Engineer
Advanced Mobility Systems, LLC
1960 Chicago Ave, Suite D-20
Riverside CA, 92507
tel. 909.276.9746
fax.909.276.9747
m...@admosys.com
m...@ieee.org
 
 
/* File: main.c
 
 Author: Victor Miramontes. m...@ieee.org.
 
 11-1-01
  -modified soc function to use less timers and better resolution
  -also modified safeguard against timer locking up if SOC on thinks
   reaches 100 % and signal is always high.
  -fixed when no signal is present
  -clean up code   
   
 11-2-01
  -make sure to check appconfig.h for Think SOC simulation
  -simulated Think SOC is output on TimerC0 I/O signal and read into TC1 I/O
 
 11-2-01 Updated code to correctly use the DSP frequency counter to measure the pulse
  width of the SOC signal.  IPBus clock rate is 36MHz thought the SDK claims it runs
  at 40MHz. The SOC signal from the Think is a PWM signal which is delivered at a
  frequency of 200Hz. The duty cycle indicates the SOC for the Think
   
   Scaling: 0 - 100 % Duty Cycle for 0 ~ 100 % State of Charge
   
  The signal is read from the % of positive portion of the signal
    
 11-3-01 
  Tested code on protoboard
 
*/
 
#include "arch.h"
#include "bsp.h"
#include "port.h"
#include "quadraturetimer.h"
#include "led.h"
 

UWord16 GetSOCstatus(void);
 
static void  ThinkSocInt(qt_eCallbackType CallbackType, void* pParam);
static void  SocTimerInt(qt_eCallbackType CallbackType, void* pParam);
static void  SocTmrFail(qt_eCallbackType CallbackType, void* pParam);
 
const qt_sState ThinkSOCTmrParm0 = {    // fake sigal generator output is a 90% duty cycle 200Hz square wave.
 
    /* Mode = */                    qtCount,
    /* InputSource = */             qtPrescalerDiv128,
    /* InputPolarity = */           qtNormal,
    /* SecondaryInputSource = */    0,
 
    /* CountFrequency = */          qtRepeatedly,
    /* CountLength = */             qtUntilCompare,
    /* CountDirection = */          qtUp,
 
    /* OutputMode = */              qtToggleUsingAlternateCompare,
    /* OutputPolarity = */          qtNormal, // change to qtInverted for vehicle simulation
    /* OutputDisabled = */          false,
 
    /* Master = */                  0,
    /* OutputOnMaster = */          0,
    /* CoChannelInitialize = */     0,
    /* AssertWhenForced = */        0,
 
    /* CaptureMode = */             qtDisabled,
 
    /* CompareValue1 = */           0x008d,  // 200Hz 90% duty 0008d  , 057e
    /* CompareValue2 = */           0x04f1, // 04F1
    /* InitialLoadValue = */        0x0000,
 
    /* CallbackOnCompare = */       { 0, 0 },
    /* CallbackOnOverflow = */      { 0, 0 },
    /* CallbackOnInputEdge = */     { 0, 0 }
};
const qt_sState PeridTmrParm1 = {
 
    /* Mode = */                    qtCount,
    /* InputSource = */             qtPrescalerDiv128,
    /* InputPolarity = */           qtNormal,
    /* SecondaryInputSource = */    0,
 
    /* CountFrequency = */          qtRepeatedly,
    /* CountLength = */             qtUntilCompare,
    /* CountDirection = */          qtUp,
 
    /* OutputMode = */              qtAssertWhileActive,
    /* OutputPolarity = */          qtNormal,
    /* OutputDisabled = */          true,
 
    /* Master = */                  0,
    /* OutputOnMaster = */          0,
    /* CoChannelInitialize = */     0,
    /* AssertWhenForced = */        0,
 
    /* CaptureMode = */             qtDisabled,
 
    /* CompareValue1 = */           0x20F5,   // Check every 10 ms
    /* CompareValue2 = */           0x0000,
    /* InitialLoadValue = */        0x0000,
 
    /* CallbackOnCompare = */       { SocTmrFail, 0},
    /* CallbackOnOverflow = */      { 0, 0 },
    /* CallbackOnInputEdge = */     { 0, 0 }
};
const qt_sState SocTmrParm0 = {
 
    /* Mode = */                    qtGatedCount,
    /* InputSource = */             qtPrescalerDiv128,
    /* InputPolarity = */           qtInverted,
    /* SecondaryInputSource = */    qtCounter1Input,
 
    /* CountFrequency = */          qtRepeatedly,
    /* CountLength = */             qtPastCompare,
    /* CountDirection = */          qtUp,
 
    /* OutputMode = */              qtAssertWhileActive,
    /* OutputPolarity = */          qtNormal,
    /* OutputDisabled = */          true,
 
    /* Master = */                  0,
    /* OutputOnMaster = */          0,
    /* CoChannelInitialize = */     0,
    /* AssertWhenForced = */        0,
 
    /* CaptureMode = */             qtFallingEdge,
 
    /* CompareValue1 = */           0x0000, 
    /* CompareValue2 = */           0x0000,
    /* InitialLoadValue = */        0x0000,
 
    /* CallbackOnCompare = */       { 0, 0 },
    /* CallbackOnOverflow = */      { 0, 0 },
    /* CallbackOnInputEdge = */     { SocTimerInt, 0 }
};
 
int ThinkSocTmr,SOCFailTmr;
int SocTimer;
/// these need to be moved out of the GetSocStatus function to work
static UWord32 CapReg=0,CapReg1=0,Duty=0;
static UWord16 SocCounter=0;
static bool SocReady = false, SocFinished = false, SocFailse;
//  end
UWord32 temp2;
 

void main (void)
{
 
int LedFD;
 
  LedFD = open(BSP_DEVICE_NAME_LED_0, 0);   // init LED's
  ioctl(LedFD, LED_OFF, LED_GREEN);
 
  ThinkSocTmr = open(BSP_DEVICE_NAME_QUAD_TIMER_C_0, 0, NULL);   // Start think SOC sig gen.
  ioctl(ThinkSocTmr, QT_ENABLE, (void*)&ThinkSOCTmrParm0);
 
while(1)
 {
  temp2 =GetSOCstatus();
 
  while(1)
   {
    if(SocReady)
    ioctl(LedFD, LED_ON, LED_YELLOW); 
   } 
 } // end while loop
} /// end main
 

UWord16 GetSOCstatus(void)
{  UWord32 temp;
  SocTimer = open(BSP_DEVICE_NAME_QUAD_TIMER_C_1, 0, NULL);
  ioctl(SocTimer, QT_ENABLE, (void*)&SocTmrParm0);
 
  SOCFailTmr = open(BSP_DEVICE_NAME_QUAD_TIMER_C_2, 0, NULL);
  ioctl(SOCFailTmr, QT_ENABLE, (void*)&PeridTmrParm1); 
  while(!SocFinished)
  {
   if(SocReady)
   {
    SocReady= false;
    SocFinished = true;
    if(!SocFail)
    {    
     temp=(CapReg1*0x0064);
     Duty= (temp/0x057E);
    }
    else
    Duty = 0;
   }
  }
  ioctl(SOCFailTmr, QT_DISABLE, NULL);
 return Duty;
}
//static void  ThinkSocInt(qt_eCallbackType CallbackType, void* pParam)
//{
//  ioctl(LedFD, LED_TOGGLE, LED_GREEN);
//}
void SocTmrFail(qt_eCallbackType CallbackType, void* pParam)
{
 if ((periphMemRead(&ArchIO.TimerC.Channel1.StatusControlReg) & 0x0800)==0)
  {
   if((periphMemRead(&ArchIO.TimerC.Channel1.StatusControlReg) & 0x0100))
    {
     SocReady= true;
     SocFailse;
     CapReg1=0x057E;
 
    }
   else
    {
     SocReady= true;
     SocFail=true;
    ioctl(LedFD, LED_OFF, LED_GREEN);
    }
  }
}
void SocTimerInt(qt_eCallbackType CallbackType, void* pParam)
{
 CapReg1Reg;
 CapReg = ioctl(SocTimer, QT_READ_CAPTURE_REG, NULL);
 ioctl(SocTimer, QT_ENABLE, (void*)&SocTmrParm0);
 if(++SocCounter%4==0)
  {  
   ioctl(SocTimer, QT_DISABLE, NULL);
   SocReady = true;
  ioctl(LedFD, LED_ON, LED_RED);
  }
}
   
-----Original Message-----
From: dflieb20 [mailto:d...@aol.com]
Sent: Tuesday, November 26, 2002 12:53 PM
To: m...@yahoogroups.com
Subject: [motoroladsp] Measuring PW using Quad Timer Captures

Hello-

I am using the 56807 with the Motorola SDK.  I am tryng to measure
the pulse-width of a ~50Hz squarewave using the capture registers on
two timers (one to save the rise time, one to save the fall time). 
The rise and fall interrupts fire correctly, but the values returned
by the SDK function ioctl(...,QT_READ_CAPTURE_REG,...) are strange at
best (the rise and fall times are usually separated by only 1 clock
cycle, which is near impossible).  I am connecting the signal
generator to timer D0 and using that pin as input to both timers. 
Here is the code - thanks for any input.

dave

#include <stdio.h>
#include "port.h"
#include "arch.h"
#include "io.h"
#include "led.h"
#include "qtimerdrv.h"
#include "periph.h"

#include "fcntl.h"
#include "quadraturetimer.h"static void  CallbackOnRisingEdge(qt_eCallbackType CallbackType,
void* pParam);
static void  CallbackOnFallingEdge(qt_eCallbackType CallbackType,
void* pParam);const qt_sState quadParam1 = {

    /* Mode = */                    qtCount,
    /* InputSource = */             qtCounter0Input,
    /* InputPolarity = */           qtNormal,
    /* SecondaryInputSource = */    0,

    /* CountFrequency = */          qtRepeatedly,
    /* CountLength = */             qtPastCompare,
    /* CountDirection = */          qtUp,

    /* OutputMode = */              qtToggleOnCompare,
    /* OutputPolarity = */          qtNormal,
    /* OutputDisabled = */          0,

    /* Master = */                  0,
    /* OutputOnMaster = */          0,
    /* CoChannelInitialize = */     0,
    /* AssertWhenForced = */        0,

    /* CaptureMode = */             qtRisingEdge,

    /* CompareValue1 = */           0xFFFF,
    /* CompareValue2 = */           0xFFFF,
    /* InitialLoadValue = */        0x0000,

    /* CallbackOnCompare = */       { 0, 0 },
    /* CallbackOnOverflow = */      { 0, 0 },
    /* CallbackOnInputEdge = */     { CallbackOnRisingEdge, 0 }
};

const qt_sState quadParam2 = {

    /* Mode = */                    qtCount,
    /* InputSource = */             qtCounter0Input,
    /* InputPolarity = */           qtNormal,
    /* SecondaryInputSource = */    0,

    /* CountFrequency = */          qtRepeatedly,
    /* CountLength = */             qtPastCompare,
    /* CountDirection = */          qtUp,

    /* OutputMode = */              qtToggleOnCompare,
    /* OutputPolarity = */          qtNormal,
    /* OutputDisabled = */          0,

    /* Master = */                  0,
    /* OutputOnMaster = */          0,
    /* CoChannelInitialize = */     0,
    /* AssertWhenForced = */        0,

    /* CaptureMode = */             qtFallingEdge,

    /* CompareValue1 = */           0xFFFF,
    /* CompareValue2 = */           0xFFFF,
    /* InitialLoadValue = */        0x0000,

    /* CallbackOnCompare = */       { 0, 0 },
    /* CallbackOnOverflow = */      { 0, 0 },
    /* CallbackOnInputEdge = */     { CallbackOnFallingEdge, 0 }
};Word16  RiseTime=0, FallTime=0, PW=0;
int PwUpdated =0, PrevPW=0;;UWord16  TimerD0; /* file handles */
UWord16  TimerD1;
static int LedFD;

/*********************************************************************
********/
main()
{
    LedFD  = open(BSP_DEVICE_NAME_LED_0,  0);
    ioctl(LedFD,  LED_OFF, LED_GREEN);
 

    TimerD0 = open(BSP_DEVICE_NAME_QUAD_TIMER_D_0, 0, &quadParam1 );
    TimerD1 = open(BSP_DEVICE_NAME_QUAD_TIMER_D_1, 0, &quadParam2 );    ioctl(TimerD0, QT_DISABLE, (void*)&quadParam1 );
    ioctl(TimerD1, QT_DISABLE, (void*)&quadParam2 );
  
    ioctl(TimerD0, QT_ENABLE_CAPTURE_REG, (void*)&quadParam1 );
    ioctl(TimerD1, QT_ENABLE_CAPTURE_REG, (void*)&quadParam2 );
   
    ioctl(TimerD0, QT_ENABLE, (void*)&quadParam1 );
    ioctl(TimerD1, QT_ENABLE, (void*)&quadParam2 );
   
   
    while(1) /* executive loop */
    {
        if (PwUpdated)
        {
              PrevPW = PW;
              PwUpdated = 0;  
        }
    }
}/*********************************************************************
********/
void  CallbackOnRisingEdge(qt_eCallbackType CallbackType, void*
pParam)
{
    ioctl(LedFD,  LED_ON, LED_GREEN);
    ioctl(LedFD,  LED_OFF, LED_RED);
   
    RiseTime = ioctl(TimerD0, QT_READ_CAPTURE_REG, (void*)
&quadParam1 );
}

void  CallbackOnFallingEdge(qt_eCallbackType CallbackType, void*
pParam)
{
    ioctl(LedFD,  LED_OFF, LED_GREEN);
    ioctl(LedFD,  LED_ON, LED_RED);
   
    FallTime = ioctl(TimerD1, QT_READ_CAPTURE_REG, (void*)
&quadParam2 );
    PW = FallTime-RiseTime;
    PwUpdated = 1;
}


_____________________________________
Note: If you do a simple "reply" with your email client, only the author of this message will receive your answer.  You need to do a "reply all" if you want your answer to be distributed to the entire group.

_____________________________________
About this discussion group:

To Join:  m...@yahoogroups.com

To Post:  m...@yahoogroups.com

To Leave: m...@yahoogroups.com

Archives: http://www.yahoogroups.com/group/motoroladsp

More Groups: http://www.dsprelated.com/groups.php3


">Yahoo! Terms of Service.


We have developed our own low-level drivers for frequency and/or period
measurement, using any of the Quad Timers that have an I/O pin. Details on our
low-level drivers are in 2 messages I posted to this group:
- 10:09am, September 24, 2002:
"RE: [motoroladsp] Doubt regarding context saving for SCI callback routine."
- 6:43am, September 25, 2002:
"RE: [motoroladsp] Timer Pins, more I/O"

The first message describes the "Super Fast" interrupt for the Quad Timer
frequency and/or period measurement, and the second message has a ZIP file that
contains the complete source code for the interrupt and data processing
functions, in the file "io_func.c". These functions are:
static void init_frequency_inputs(void);
static void read_frequency_inputs( void );
void process_frequency_inputs( void );
void Freq_Period_Input_ISR(
WORD status, // Status read from the DSP Timer
DSP_TIMER_T *p_dsp_timer, // Pointer to the DSP Timer
DSPTMR_FP_DATA_T *p_dsp_fp_data // Pointer to the input data structure
);

The attached file "anaiodef.h" contains the following typedef for the
DSPTMR_FP_DATA_T structure:
// Frequency/period input data structure (one for each input).
typedef struct {
SWORD ad_idx; // Index into the ANA_DATA array
union { // Union for the raw data input
LWORD fp_count; // The whole frequency/period count
struct { // Structure for the parts of the count
WORD fp_lsw; // Freq./Period least significant word
WORD fp_msw; // Freq./Period most significant word
} parts;
} raw_data;
LWORD fp_start_val; // Count at the start point
LWORD fp_end_val; // Count at the end point
SWORD fp_meas_type; // 0 == count pulses, else from period
SWORD ignore_count; // Ignore next count when mode changed
SWORD count_index; // Index into the count_data[] array
WORD count_data[ FREQ_COUNTS_PER_SEC ];
SWORD raw_fp_meas_type; // 0 == count pulses, else from period
LWORD raw_fp_data; // Raw frequency data (period or count)
} DSPTMR_FP_DATA_T;

This low-level driver software uses the Overflow Interrupt to extend the counter
to 32 bits, by counting overflows in the "raw_data.parts.fp_msw" variable. The
32-bit value of the counter is read from the "raw_data.fp_count" variable. By
reading from the Capture Register (CAP), we are able to read the number of IPBus
clock cycles with zero error, please see Section 14.7.5 "Capture Register (CAP)"
in the DSP56F80x User's Manual.

Our software only captures one edge of the input signal, but you can put a
different value in the Status and Control Register (SCR) Input Capture Mode
value, please see Section 14.7.2.9 "Input Capture Mode (Capture Mode) - Bits
7-6" in the DSP56F80x User's Manual.

The period of one cycle is the difference between the "end" and "start" values
in the structure, for example:
LWORD period_value;
DSPTMR_FP_DATA_T *p_fp_data = &g_dsp_tmrb0_data;
period_value = p_fp_data->fp_end_val - p_fp_data->fp_start_val;

This is, of course, the count of Primary Count Source clock pulses (ie
IP_Bus_Clock/1) in one complete cycle. This is converted to the frequency value
in the function process_frequency_inputs(). You can use a similar calculation
to convert the count to the true period value.

We don't use the SDK low-level I/O drivers at all, so if you want to use the
method shown above, you will have to figure out how to do it on your own.

I hope this information is helpful to you.

Regards,

Art Johnson
Senior Systems Analyst
PMC Prime Mover Controls Inc.
3600 Gilmore Way
Burnaby, B.C., Canada
V5G 4R8
Phone: 604 433-4644
FAX: 604 433-5570
Email:
http://www.pmc-controls.com

-----Original Message-----
From: dflieb20 [mailto:]
Sent: Tuesday, November 26, 2002 12:53 PM
To:
Subject: [motoroladsp] Measuring PW using Quad Timer Captures Hello-

I am using the 56807 with the Motorola SDK. I am tryng to measure
the pulse-width of a ~50Hz squarewave using the capture registers on
two timers (one to save the rise time, one to save the fall time).
The rise and fall interrupts fire correctly, but the values returned
by the SDK function ioctl(...,QT_READ_CAPTURE_REG,...) are strange at
best (the rise and fall times are usually separated by only 1 clock
cycle, which is near impossible). I am connecting the signal
generator to timer D0 and using that pin as input to both timers.
Here is the code - thanks for any input.

dave

#include <stdio.h>
#include "port.h"
#include "arch.h"
#include "io.h"
#include "led.h"
#include "qtimerdrv.h"
#include "periph.h"

#include "fcntl.h"
#include "quadraturetimer.h" static void CallbackOnRisingEdge(qt_eCallbackType CallbackType,
void* pParam);
static void CallbackOnFallingEdge(qt_eCallbackType CallbackType,
void* pParam); const qt_sState quadParam1 = {

/* Mode = */ qtCount,
/* InputSource = */ qtCounter0Input,
/* InputPolarity = */ qtNormal,
/* SecondaryInputSource = */ 0,

/* CountFrequency = */ qtRepeatedly,
/* CountLength = */ qtPastCompare,
/* CountDirection = */ qtUp,

/* OutputMode = */ qtToggleOnCompare,
/* OutputPolarity = */ qtNormal,
/* OutputDisabled = */ 0,

/* Master = */ 0,
/* OutputOnMaster = */ 0,
/* CoChannelInitialize = */ 0,
/* AssertWhenForced = */ 0,

/* CaptureMode = */ qtRisingEdge,

/* CompareValue1 = */ 0xFFFF,
/* CompareValue2 = */ 0xFFFF,
/* InitialLoadValue = */ 0x0000,

/* CallbackOnCompare = */ { 0, 0 },
/* CallbackOnOverflow = */ { 0, 0 },
/* CallbackOnInputEdge = */ { CallbackOnRisingEdge, 0 }
};

const qt_sState quadParam2 = {

/* Mode = */ qtCount,
/* InputSource = */ qtCounter0Input,
/* InputPolarity = */ qtNormal,
/* SecondaryInputSource = */ 0,

/* CountFrequency = */ qtRepeatedly,
/* CountLength = */ qtPastCompare,
/* CountDirection = */ qtUp,

/* OutputMode = */ qtToggleOnCompare,
/* OutputPolarity = */ qtNormal,
/* OutputDisabled = */ 0,

/* Master = */ 0,
/* OutputOnMaster = */ 0,
/* CoChannelInitialize = */ 0,
/* AssertWhenForced = */ 0,

/* CaptureMode = */ qtFallingEdge,

/* CompareValue1 = */ 0xFFFF,
/* CompareValue2 = */ 0xFFFF,
/* InitialLoadValue = */ 0x0000,

/* CallbackOnCompare = */ { 0, 0 },
/* CallbackOnOverflow = */ { 0, 0 },
/* CallbackOnInputEdge = */ { CallbackOnFallingEdge, 0 }
}; Word16 RiseTime=0, FallTime=0, PW=0;
int PwUpdated =0, PrevPW=0;; UWord16 TimerD0; /* file handles */
UWord16 TimerD1;
static int LedFD;

/*********************************************************************
********/
main()
{
LedFD = open(BSP_DEVICE_NAME_LED_0, 0);
ioctl(LedFD, LED_OFF, LED_GREEN); TimerD0 = open(BSP_DEVICE_NAME_QUAD_TIMER_D_0, 0, &quadParam1 );
TimerD1 = open(BSP_DEVICE_NAME_QUAD_TIMER_D_1, 0, &quadParam2 ); ioctl(TimerD0, QT_DISABLE, (void*)&quadParam1 );
ioctl(TimerD1, QT_DISABLE, (void*)&quadParam2 );

ioctl(TimerD0, QT_ENABLE_CAPTURE_REG, (void*)&quadParam1 );
ioctl(TimerD1, QT_ENABLE_CAPTURE_REG, (void*)&quadParam2 );

ioctl(TimerD0, QT_ENABLE, (void*)&quadParam1 );
ioctl(TimerD1, QT_ENABLE, (void*)&quadParam2 ); while(1) /* executive loop */
{
if (PwUpdated)
{
PrevPW = PW;
PwUpdated = 0;
}
}
} /*********************************************************************
********/
void CallbackOnRisingEdge(qt_eCallbackType CallbackType, void*
pParam)
{
ioctl(LedFD, LED_ON, LED_GREEN);
ioctl(LedFD, LED_OFF, LED_RED);

RiseTime = ioctl(TimerD0, QT_READ_CAPTURE_REG, (void*)
&quadParam1 );
}

void CallbackOnFallingEdge(qt_eCallbackType CallbackType, void*
pParam)
{
ioctl(LedFD, LED_OFF, LED_GREEN);
ioctl(LedFD, LED_ON, LED_RED);

FallTime = ioctl(TimerD1, QT_READ_CAPTURE_REG, (void*)
&quadParam2 );
PW = FallTime-RiseTime;
PwUpdated = 1;
}
_____________________________________
Note: If you do a simple "reply" with your email client, only the author of this
message will receive your answer. You need to do a "reply all" if you want your
answer to be distributed to the entire group.

_____________________________________
About this discussion group:

To Join:

To Post:

To Leave:

Archives: http://www.yahoogroups.com/group/motoroladsp

More Groups: http://www.dsprelated.com/groups.php3 ">http://docs.yahoo.com/info/terms/



Attachment (not stored)
anaiodef.h
Type: application/octet-stream