Hi --
I am implementing DMA-based buffered event counting on a PCIe-6259 board. I use G0_Out as the gate for G1, which counts events on a PFI pin. So by setting the speed of G0, I get an event count (either cumulative or non-cumulative) on a periodic basis, which is directly DMA'd to my buffer, and synchronized with other i/o operations.
This is working well right now, except for one problem, which is that the I only get data if there is at least one source edge between gates. i.e. if there are no edges, nothing gets pumped to the dma buffer.
I am guessing that a stale data error is somehow choking off the DMA transfer from the counter. Is that possible?
Is there some magic that I need to do to avoid this, because for this application, especially if I am counting cumulatively, I don't care about a missing edge, but I do care if the dma transfers get out of phase with the rest of my timing.
Thanks in advance for any help!
--spg
Here is a snippet of the code that sets up the event counting on G1, partly based on gpctex6.cpp:
// ----------------------------------------------------
const int sDMASelect[] = {1,2,4,8,3,5};
// source: pfi, or -1 for 20Khz clock
void eventTimerSetup(tMSeries *board, tTIO *tio, int dmaChannel, bool cumulative, int source)
{
int sourceSelect = (source==-1) ? 0 : (source+1);
//MSeries.CTR.Source
tio->G1_Input_Select.setG1_Source_Select(sourceSelect); // (pfi+1) or 20Khz=0
tio->G1_Input_Select.setG1_Source_Polarity(0); //rising=0
tio->G1_Input_Select.setG1_OR_Gate(0);
tio->G1_Input_Select.flush();
//MSeries.CTR.Gate
tio->G1_Input_Select.setG1_Gate_Select(20); //the G_OUT signal from other clock=20
tio->G1_Input_Select.setG1_Output_Polarity(0); //active high=0
tio->G1_Input_Select.flush();
//MSeries.CTR.IncrementRegisters
tio->G1_AutoIncrement.writeRegister(0);
//MSeries.CTR.InitialCountRegisters
tio->G1_Mode.writeG1_Load_Source_Select(tTIO::tG1_Mode::kG1_Load_Source_SelectLoad_A);
tio->G1_Load_A.writeRegister(0);
tio->G1_Command.writeG1_Load(1);
tio->G1_Load_B.writeRegister(0);
tio->G1_Load_A.writeRegister(0);
tio->G1_Command.setG1_Bank_Switch_Enable(tTIO::tG1_Command::kG1_Bank_Switch_EnableBank_X);
tio->G1_Command.setG1_Bank_Switch_Mode(tTIO::tG1_Command::kG1_Bank_Switch_ModeGate);
tio->G1_Command.flush();
//MSeries.CTR.ApplicationRegisters
tio->G1_Input_Select.setG1_Gate_Select_Load_Source(0);
tio->G1_Mode.setG1_Reload_Source_Switching(tTIO::tG1_Mode::kG1_Reload_Source_SwitchingAlternate);
tio->G1_Mode.setG1_Loading_On_Gate(cumulative ? tTIO::tG1_Mode::kG1_Loading_On_GateNo_Reload : tTIO::tG1_Mode::kG1_Loading_On_GateReload_On_Stop_Gate);
tio->G1_Mode.setG1_Loading_On_TC(tTIO::tG1_Mode::kG1_Loading_On_TCRollover_On_TC);
tio->G1_Mode.setG1_Gating_Mode (tTIO::tG1_Mode::kG1_Gating_ModeEdge_Gating_Active_High);
tio->G1_Mode.setG1_Gate_On_Both_Edges (tTIO::tG1_Mode::kG1_Gate_On_Both_EdgesBoth_Edges_Disabled);
tio->G1_Mode.setG1_Trigger_Mode_For_Edge_Gate(tTIO::tG1_Mode::kG1_Trigger_Mode_For_Edge_GateGate_Does_Not_Stop);
tio->G1_Mode.setG1_Stop_Mode(tTIO::tG1_Mode::kG1_Stop_ModeStop_On_Gate);
tio->G1_Mode.setG1_Counting_Once(tTIO::tG1_Mode::kG1_Counting_OnceNo_HW_Disarm);
tio->G1_Second_Gate.setG1_Second_Gate_Gating_Mode(0);
tio->G1_Input_Select.flush();
tio->G1_Mode.flush();
tio->G1_Second_Gate.flush();
//MSeries.CTR.UpDown.Registers
tio->G1_Command.writeG1_Up_Down(tTIO::tG1_Command::kG1_Up_DownSoftware_Up); //kG1_Up_DownSoftware_Down
//MSeries.CTR.OutputRegisters
tio->G1_Mode.writeG1_Output_Mode(tTIO::tG1_Mode::kG1_Output_ModePulse);
tio->G1_Input_Select.writeG1_Output_Polarity(0);
//MSeries.CTR.BufferEnable
board->G1_DMA_Config.writeG1_DMA_Reset(1);
board->G1_DMA_Config.setG1_DMA_Write(0);
board->G1_DMA_Config.setG1_DMA_Int_Enable(0);
board->G1_DMA_Config.setG1_DMA_Enable(1);
board->G1_DMA_Config.flush();
tio->G1_Counting_Mode.setG1_Encoder_Counting_Mode(0);
tio->G1_Counting_Mode.setG1_Alternate_Synchronization(0);
tio->G1_Counting_Mode.flush();
//MSeries.CTR.EnableOutput
//board->Analog_Trigger_Etc.setGPFO_1_Output_Enable(tMSeries::tAnalog_Trigger_Etc::kGPFO_1_Output_EnableOutput);
//board->Analog_Trigger_Etc.setGPFO_1_Output_Select(tMSeries::tAnalog_Trigger_Etc::kGPFO_1_Output_SelectG_OUT);
//board->Analog_Trigger_Etc.flush();
//MSeries.CTR.StartTriggerRegisters
tio->G1_MSeries_Counting_Mode.writeG1_MSeries_HW_Arm_Enable(0);
board->G0_G1_Select.writeG1_DMA_Select(sDMASelect[dmaChannel]);
tio->G1_Command.writeG1_Arm(1); // arm it
}
--------------------------------------------------
Scott Gillespie
http://www.appliedbrain.com
--------------------------------------------------