NI Home
Cart Cart | Help
Hello Events Academic NI Developer Zone Support Solutions Products & Services Contact NI MyNI
You are here: 
NI Home > NI Developer Zone > NI Discussion Forums


Reply
Member spg
Member
spg
Posts: 51
0 Kudos
Accepted Solution

x-series non-cumulative buffered event counting

 

hi --

 

i have buffered event counting mostly ported over to x-series from my m-series driver.  

 

For the counter sample clock, I am using AI_Start, so that the counter values coming  in are synchronized with analog input.

 

This works fine, and i get values like so (assuming we are getting a constant 100 counts between AI_Start signals):

 

100 200 300 400 500 etc...

 

Optionally, though, I would like to get non cumulative data, like so:

 

100 100 100 100 100 etc...

 

To accomplish this, I am also using AI_Start as the counter Gate, where the Gate function is to reload the counter (reset to zero) on each rising Gate edge.  This doesn't seem to work.  However if I drive the sample clock and Gate from a slower external signal (e.g. a 1MHz square wave via PFI) , the counter is reloaded correctly, and I get non-cumulative values.

 

M-series is a little different, but basically uses the same idea, with the Gate being AI_Start_Pulse via RTSI.

 

If anyone has a suggestion, or an alternate way to accomplish this (basically, a counter reload synchronous with the counter sample clock or AI_Start signal), I'd appreciate some input.

 

My initial setup code is below, based on gpctex5.cpp:

 

thanks,

 

--spg

 

 

static void counterSetup(tCounter *counter,
nNISTC3::counterResetHelper *counterResetHelper,
bool enabled,
int cumulative,
int pfi, // pfi, or -1 for internal clock
bool fallingPolarity,
UInt32 *buffer)
{
nMDBG::tStatus2 status;

counterResetHelper->reset( /*initialReset*/ kTrue, status);

if (!enabled)
return;

 

// -------------------
// Mode
// -------------------

counter->Gi_Mode_Register.setGi_Reload_Source_Switching(nCounter::kUseSameLoadRegister);
counter->Gi_Mode_Register.setGi_Loading_On_Gate(cumulative ?  nCounter::kNoCounterReloadOnGate : nCounter::kReloadOnStopGate );// cumulative?
counter->Gi_Mode_Register.setGi_ForceSourceEqualToTimebase(kFalse);
counter->Gi_Mode_Register.setGi_Loading_On_TC(nCounter::kRolloverOnTC);
counter->Gi_Mode_Register.setGi_Counting_Once(nCounter::kNoHardwareDisarm);
counter->Gi_Mode_Register.setGi_Load_Source_Select(nCounter::kLoad_From_Register_A);
counter->Gi_Mode_Register.setGi_Trigger_Mode_For_Edge_Gate(nCounter::kGateLoads);
counter->Gi_Mode_Register.setGi_Gate_On_Both_Edges(nCounter::kDisabled);
counter->Gi_Mode_Register.setGi_Gating_Mode(nCounter::kAssertingEdgeGating);
// Gi_Output_Mode doesn't matter
// Gi_Stop_Mode doesn't matter
// Gi_Gate_On_Both_Edges doesn't matter
counter->Gi_Mode_Register.flush();

 

// -------------------
// Mode2
// -------------------

counter->Gi_Mode2_Register.setGi_Up_Down(nCounter::kCountUp);
counter->Gi_Mode2_Register.setGi_Bank_Switch_Enable(nCounter::kDisabled_If_Armed_Else_Write_To_X);
counter->Gi_Mode2_Register.setGi_Bank_Switch_Mode(nCounter::kGate);
counter->Gi_Mode2_Register.setGi_StopOnError(kFalse);
// Gi_WriteOnSwitchRequest doesn't matter
// Gi_CtrOutFifoRegenerationEn doesn't matter
// Gi_HwArmSyncMode doesn't matter
counter->Gi_Mode2_Register.flush();

 

// -------------------
// Counting Mode
// -------------------

counter->Gi_Counting_Mode_Register.setGi_Prescale(kFalse);
counter->Gi_Counting_Mode_Register.setGi_HW_Arm_Enable(kFalse);
counter->Gi_Counting_Mode_Register.setGi_Counting_Mode(nCounter::kNormalCounting);
// Gi_Prescale_Div_2 doesn't matter
// Gi_HW_Arm_Select doesn't matter
// Gi_Index_Phase doesn't matter
// Gi_Index_Mode doesn't matter
// Gi_HW_Arm_Polarity doesn't matter
counter->Gi_Counting_Mode_Register.flush();

 

// -------------------
// Sample Clock
// -------------------

const nCounter::tGi_SampleClockSelect_t sampClkSource = nCounter::kSampleClk_AI_START;
const nCounter::tGi_Polarity_t sampClkPolarity = nCounter::kActiveHigh;

counter->Gi_SampleClockRegister.setGi_SampleClockGateIndependent(kTrue);
counter->Gi_SampleClockRegister.setGi_SampleClockSampleMode(nCounter::kSC_LastSaved);
counter->Gi_SampleClockRegister.setGi_SampleClockMode(nCounter::kSC_SingleSample);
counter->Gi_SampleClockRegister.setGi_SampleClockPolarity(sampClkPolarity);
counter->Gi_SampleClockRegister.setGi_SampleClockSelect(sampClkSource);
// Gi_SampleClockPulse doesn't matter
// Gi_SampleClockLevelMode doesn't matter
counter->Gi_SampleClockRegister.flush();

 

// -------------------
// Aux
// -------------------

 

counter->Gi_AuxCtrRegister.writeGi_AuxCtrMode(nCounter::kAux_Disabled);

 

// -------------------
// Don't Matter
// -------------------

 

// Gi_Autoincrement_Register doesn't matter
// Gi_ABZ_Select_Register doesn't matter

 

// -------------------
// Second Gate
// -------------------

 

counter->Gi_Second_Gate_Register.setGi_Second_Gate_Mode(nCounter::kDisabledSecondGate);
// Gi_Second_Gate_Polarity doesn't matter
// Gi_Second_Gate_Select doesn't matter
counter->Gi_Second_Gate_Register.flush();

 

// -------------------
// Input Select
// -------------------

 

const nCounter::tGi_Source_Select_t source = (pfi==-1) ?  nCounter::kSrc_TB1 :  (nCounter::tGi_Source_Select_t) (pfi + ((pfi<10) ? 1 : 11));

const nCounter::tGi_Polarity_t sourcePolarity = (fallingPolarity ?  nCounter::kActiveLow : nCounter::kActiveHigh);


counter->Gi_Input_Select_Register.setGi_Gate_Select(nCounter::kGate_AI_START1);
counter->Gi_Input_Select_Register.setGi_Source_Polarity(sourcePolarity);
counter->Gi_Input_Select_Register.setGi_Source_Select(source);
// Gi_Output_Polarity doesn't matter
// Gi_Gate_Select_Load_Source doesn't matter
// Gi_Gate_Polarity doesn't matter
counter->Gi_Input_Select_Register.flush();

 

// -------------------
// Fifo
// -------------------

 

counter->Gi_DMA_Config_Register.setGi_WrFifoEnable(kFalse);
counter->Gi_DMA_Config_Register.setGi_DMA_Write(kFalse);
counter->Gi_DMA_Config_Register.setGi_DMA_Enable(kTrue);
// Gi_DoneNotificationEnable doesn't matter
// Gi_WaitForFirstEventOnGate doesn't matter
// Gi_DMA_Reset doesn't matter
counter->Gi_DMA_Config_Register.flush();
}

 

 

 

 

------------------
scott gillespie
applied brain, inc.
------------------
Member spg
Member
spg
Posts: 51

Re: x-series non-cumulative buffered event counting

blurg!

 

i just realized what the problem is:

 

    counter->Gi_Input_Select_Register.setGi_Gate_Select(nCounter::kGate_AI_START1);// <------------------ using Start1 instead of Start

 

So, similar to M-series, I can't get the signal I want directly, so by exporting it to RTSI0:

 

   device.Triggers.RTSI_OutputSelectRegister_i[0].writeRTSI_i_Output_Select(nTriggers::kRTSI_AI_START);

   device.Triggers.RTSI_Trig_Direction_Register.writeRTSI0_Pin_Dir(nTriggers::kRTSI_Output);


i can then replace the erroneous line with:

 

    counter->Gi_Input_Select_Register.setGi_Gate_Select(nCounter::kGate_RTSI0); 

and it is working now.
cheers,
--spg
------------------
scott gillespie
applied brain, inc.
------------------
By using this web site, you accept the Terms of Use for this web site. Please read these Terms of Use carefully before using any part of this site. Please go here for information on ni.com's copyright infringement policy.
My Profile | Privacy | Legal | Contact NI © 2011 National Instruments Corporation. All rights reserved.    |    E-Mail this Page E-Mail this Page