NI Home > Community > NI Discussion Forums

Driver Development Kit (DDK)

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.
------------------