- From: Anders Blomdell <anders.blomdell_at_control.lth.se>
- Date: Mon, 25 Jun 2007 18:15:41 +0200
Anders Blomdell wrote:
> Frank Mori Hess wrote:
>> On Thursday 21 June 2007 13:36, you wrote:
>>> I know (I'll get to it as soon as I have figured out how to use the NI
>>> pci-6221 with quadrature encoders).
>> See the enums in comedi.h, in particular enum ni_gpct_mode_bits. You'll
>> need to use one of the NI_GPCT_COUNTING_MODE_QUADRATURE_XN_BITS bitfields,
>> instead of the NI_GPCT_COUNTING_MODE_NORMAL_BITS that the simple counting
>> demo uses. And maybe some of the NI_GPCT_INDEX_* bits. It might actually
>> be useful to look at the ni 6601/6602 register level programming manual.
> That only partially works, what happens is that whatever
> NI_GPCT_COUNTING_MODE_QUADRATURE_XN_BITS is selected, the counter starts to
> count down on each edge on CTR{0/1}A (PFI 8/PFI 3) but remains stationary
> regardless of activity on CTR{0/1}B (PFI 10/PFI 11). To me this indicates that
> the counter is not in encoder mode, because a failure in the routing of the B
> signal should result in the counter changing one value only (X0 -> X1 -> X0
> transitions should gige one up and one down event). Direction is changed if
> NI_GPCT_COUNTING_DIRECTION_UP_BITS is set.
>
> Where can I find the documentation where M_Offset_G0_Counting_Mode, etc are
> found (the only document I have found on NI's site is "NI M Series Register Map
> (Preliminay)"
The following hack (gleaned after getting a working example in the NI
nimhddk_linux26/nimseries register level programming), makes it work:
case NITIO_G0_Counting_Mode_Reg:
ni_writew(bits, M_Offset_G0_Counting_Mode);
bits = 0x26a0;
ni_writew(bits, M_Offset_G0_MSeries_ABZ);
break;
Seems like we (I?) need to add functionality to do the equivalent of (see
attached NI/RLP example for context):
board->G0_MSeries_ABZ.setG0_A_Select(9);
board->G0_MSeries_ABZ.setG0_B_Select(21);
board->G0_MSeries_ABZ.flush();
any comments on what it should look like (or is it already there, but hidden by
my ignorance)?
Regards
Anders Blomdell
--
Anders Blomdell Email: anders.blomdell_at_control.lth.se
Department of Automatic Control
Lund University Phone: +46 46 222 4625
P.O. Box 118 Fax: +46 46 138118
SE-221 00 Lund, Sweden
//
// gpctex2.cpp --
//
// Simple Event Counting -- hardware controlled up/down
//
// $DateTime: 2006/07/27 23:51:45 $
//
// Count pulses from an external source using an external signal to control
// the count direction.
//
// Connect an external source to pin 37 (PFI 8), and connect an external up/down
// signal to pin 38 (PFI 9)
//
////////////////////////////////////////////////////////////////////////////////
// Possible Gi_Source_Select values:
// 0: TB1(20 MHz)
// 1-10: PFI<0..9>
// 11-17: RTSI<0..6>
// 18: TB2(100 kHz)
// 19: The G_TC signal from the other general-purpose counter
// 20: The G_GATE signal from the other counter, when G0_Src_SubSelect = 0;
// Star_Trig when G0_Src_SubSelect = 1
// 21-26: PFI<10..15>
// 27: RTSI7
// 28: TB1(20 MHz)
// 29: PXIClk10
// 30: The internal signal TB3(80 MHz), when G0_Src_SubSelect = 0;
// The output of the Analog Trigger module when G0_Src_SubSelect = 1
// 31: Logic low
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// Possible Gi_Gate_Select values
// 0: The output of the TimeStamping Mux.
// This signal is selected with the G0_TimeStamp_Select bitfield
// 1-10: PFI<0..9>
// 11-17: RTSI<0..6>
// 18: The internal analog input signal AI_START2
// 19: Star_Trig
// 20: The G_OUT signal from the other general-purpose counter
// 21-26: PFI<10..15>
// 27: RTSI7
// 28: The internal analog input signal AI_START1
// 29: The G_SOURCE signal from the other general-purpose counter
// 30: The output of the Analog Trigger Module
// 31: Logic low
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
//
// Possible up/down signal values (Gi_B_Select)
//
// 0: P0(6) (DIO line on port 0 line 6)
// 1-10: PFI<0..9>
// 11-17: RTSI<0..6>
// 18: Reserved
// 19: Reserved
// 20: Star_Trig
// 21-26: PFI<10..15>
// 27: RTSI7
// 28: Reserved
// 29: Reserved
// 30: ANALOG_TRIGGER_OUT, the analog trigger circuitry output signal
// 31: Logic low
////////////////////////////////////////////////////////////////////////////////
#include <stdio.h>
#include <unistd.h>
#ifndef ___tMSeries_h___
#include "tMSeries.h"
#endif
#ifndef ___tTIO_h___
#include "tTIO.h"
#endif
#ifndef ___common_h___
#include "common.h"
#endif
#define GPCT0_INITIAL_COUNT 0x0100
void resetGPCT0(tTIO *board);
void armGPCT0(tTIO *board);
void disarmGPCT0(tTIO *board);
void simpleEventCountConfigGPCT0(tTIO *board, tMSeries *boardM);
u32 readSaveRegGPCT0(tTIO *board);
void test(iBus *bus)
{
// create register map
tAddressSpace bar1;
tMSeries *boardM;
tTIO *board;
bar1 = bus->createAddressSpace(kPCI_BAR1);
boardM = new tMSeries(bar1);
board = new tTIO(bar1);
//TIO chip on MSeries boards is at offset 0x100
board->setAddressOffset(0x100);
configureTimebase(boardM);
resetGPCT0(board);
simpleEventCountConfigGPCT0(board, boardM);
//Set PFI pins to be input
boardM->IO_Bidirection_Pin.writeRegister (0x00);
armGPCT0(board);
{
int i;
for (i = 0 ; i < 10 ; i++) {
sleep(1);
printf("GPCT0 value is now 0x%08lx\n",readSaveRegGPCT0(board));
}
}
disarmGPCT0(board);
printf("GPCT0 value is now 0x%08lx\n",readSaveRegGPCT0(board));
//cleanup
delete boardM;
delete board;
bus->destroyAddressSpace(bar1);
}
void resetGPCT0(tTIO *board)
{
// Reset GPCT0
board->G01_Joint_Reset.writeG0_Reset(1);
board->G0_Mode.writeRegister(0);
board->G0_Command.writeRegister(0);
board->G0_Input_Select.writeRegister(0);
board->G0_AutoIncrement.writeRegister(0);
board->Interrupt_G0_Enable.setG0_TC_Interrupt_Enable(0);
board->Interrupt_G0_Enable.setG0_Gate_Interrupt_Enable(0);
board->Interrupt_G0_Enable.flush();
board->G0_Command.writeG0_Synchronized_Gate(tTIO::tG0_Command::kG0_Synchronized_GateEnabled);
board->Interrupt_G0_Ack.setG0_Gate_Error_Confirm(1);
board->Interrupt_G0_Ack.setG0_TC_Error_Confirm(1);
board->Interrupt_G0_Ack.setG0_TC_Interrupt_Ack(1);
board->Interrupt_G0_Ack.setG0_Gate_Interrupt_Ack(1);
board->Interrupt_G0_Ack.flush();
board->G0_AutoIncrement.write(0);
board->G0_MSeries_Counting_Mode.setG0_MSeries_Alternate_Synchronization(0);
board->G0_MSeries_Counting_Mode.setG0_MSeries_Index_Enable(0);
board->G0_MSeries_Counting_Mode.flush();
board->G0_Second_Gate.setG0_Second_Gate_Select(0);
board->G0_Second_Gate.setG0_Second_Gate_Polarity(0);
board->G0_Second_Gate.flush();
}
void armGPCT0(tTIO *board)
{
//Arm CPCT0
board->G0_Command.writeG0_Arm(1);
}
void disarmGPCT0(tTIO *board)
{
//Disarm CPCT0
board->G0_Command.writeG0_Disarm(1);
}
#define DD(x) printf("# %s\n", #x); x
void simpleEventCountConfigGPCT0(tTIO *board, tMSeries *boardM)
{
//Set up GPCT0 for Simple Event Counting
DD(board->G0_Mode.writeG0_Load_Source_Select(tTIO::tG0_Mode::kG0_Load_Source_SelectLoad_A););
DD(board->G0_Load_A.writeRegister(GPCT0_INITIAL_COUNT););
DD(board->G0_Command.writeG0_Load(1););
DD(board->G0_Load_B.writeRegister(0););
DD(board->G0_Load_A.writeRegister(0););
DD(board->G0_Input_Select.setG0_Source_Select(9);); //see above for choices, PFI8=9, 100 kHZ=18
DD(board->G0_Input_Select.setG0_Source_Polarity(0);); //rising=0
DD(board->G0_MSeries_Counting_Mode.setG0_MSeries_Alternate_Synchronization(1););
DD(board->G0_MSeries_Counting_Mode.setG0_MSeries_Encoder_Counting_Mode(3););
DD(board->G0_MSeries_Counting_Mode.flush(););
//Enable Input Pins
DD(board->G0_MSeries_ABZ.setG0_A_Select(9);); //PFI8=9,
DD(board->G0_MSeries_ABZ.setG0_B_Select(21);); //PFI10=21
DD(board->G0_MSeries_ABZ.flush(););
// Set counter to use HW signal for up/down selection
DD(board->G0_Command.writeG0_Up_Down(tTIO::tG0_Command::kG0_Up_DownHardware);); // Software_Down=0, Software_Up=1, Hardware=2, Hardware_Gate= 3
DD(board->G0_Input_Select.setG0_Source_Select(20);); //PFI8=9, 0=20 MHz
DD(return;);
}
u32 readSaveRegGPCT0(tTIO *board)
{
//Read save register twice and compare.
//If not equal, then read third time and return.
u32 value1, value2;
board->G0_Command.writeG0_Save_Trace(0);
board->G0_Command.writeG0_Save_Trace(1);
value1 = board->G0_Save.readG0_Save_Value();
value2 = board->G0_Save.readG0_Save_Value();
if(value1 != value2)
{
value1 = board->G0_Save.readG0_Save_Value();
}
return value1;
}
Received on 2007-06-25Z15:15:41