static int ni_ns_to_timer(int *nanosec,int round_mode);
+static int gpct_setup(comedi_device *dev,comedi_subdevice *s);
+static int ni_gpct(comedi_device *dev,comedi_subdevice *s,comedi_trig *it);
+
#undef DEBUG
#define AIMODE_NONE 0
}
+/*
+ HACK!
+
+ general purpose timer counter (CLO)
+ This reads the value of the counter
+
+*/
+static int ni_gpct(comedi_device *dev,comedi_subdevice *s,comedi_trig *it)
+{
+ int data,mask;
+ int i;
+ int temp;
+
+ /* rt stuff */
+ temp=win_save();
+
+ if(it->flags & TRIG_CONFIG){
+ data=s->io_bits;
+ for(i=0;i<it->n_chan;i++){
+ mask=1<<CR_CHAN(it->chanlist[i]);
+ data&= ~mask;
+ if(it->data[i])
+ data|=mask;
+ }
+ s->io_bits=data;
+ win_out(s->io_bits,DIO_Control_Register);
+ }else{
+ if(it->flags & TRIG_WRITE){
+ do_pack(&s->state,it);
+ win_out(s->state,DIO_Output_Register);
+ }else{
+ data=win_in(DIO_Input_Register);
+ di_unpack(data,it);
+ }
+ }
+
+ win_restore(temp);
+
+ return it->n_chan;
+}
static int ni_E_init(comedi_device *dev,comedi_devconfig *it)
}
/* XXX */
- /* timer/counter device */
+ /* general purpose counter/timer device */
+ /* CLO */
s=dev->subdevices+4;
- s->type=COMEDI_SUBD_UNUSED;
- s->trig[0]=NULL;
+ if(boardtype.n_gpct){
+ gpct_setup(dev,s);
+ s->type=COMEDI_SUBD_COUNTER;
+ s->trig[0]=ni_gpct;
+ }else{
+ s->type=COMEDI_SUBD_UNUSED;
+ s->trig[0]=NULL;
+ }
/* XXX */
/* calibration subdevice -- ai and ao */
win_out(IO_Bidirection_Pin_Register,0);
}
+#endif
/*
/* event counting */
+/*
+ Initialize the general purpose counter timers. (CLO)
+
+ Everything after the word HACK is a HACK because I don't
+ properly understand how to work within the comedi
+ architecture!
+
+ */
+int gpct_setup(comedi_device *dev,comedi_subdevice *s)
+{
+ unsigned short tmpreg; /* For handling strobe writes */
+ unsigned short int msb, lsb;
+ unsigned short counter_init = 10000;
+
+ /* basic initialization of both counters, from section 4.6.1.3
+ of the DAQ-STC manul */
+
+ /* we track several write only register values in software */
+
+ /* G(i)_Reset = 1 (strobe) */
+ win_out(G0_Reset,Joint_Reset_Register);
+ win_out(G1_Reset,Joint_Reset_Register);
+
+ /* G(i)_Mode_Register = 0 */
+ devpriv->gpct_mode0 = 0x0000;
+ devpriv->gpct_mode1 = 0x0000;
+ win_out(devpriv->gpct_mode0,G_Mode_Register(0));
+ win_out(devpriv->gpct_mode1,G_Mode_Register(1));
+
+ /* G(i)_Command_Register = 0 */
+ devpriv->gpct_command0 = 0x0000;
+ devpriv->gpct_command1 = 0x0000;
+ win_out(devpriv->gpct_command0,G_Command_Register(0));
+ win_out(devpriv->gpct_command1,G_Command_Register(1));
+
+ /* G(i)_Input_Select_Register = 0 */
+ devpriv->gpct_input_select0 = 0x0000;
+ devpriv->gpct_input_select1 = 0x0000;
+ win_out(devpriv->gpct_input_select0,G_Input_Select_Register(0));
+ win_out(devpriv->gpct_input_select1,G_Input_Select_Register(1));
+
+ /* G(i)_Autoincrement = 0 (write) */
+ /* G(i)_Autoincrement_Register = 0 */
+ win_out(G_Autoincrement(0x00),G_Autoincrement_Register(0));
+ win_out(G_Autoincrement(0x00),G_Autoincrement_Register(1));
+
+ /* XXX - for now we ignore interrupts */
+ /* G(i)_TC_Interrupt_Enable = 0 (write)*/
+ /* G(i)_Gate_Interrupt_Enable = 0 (write) */
+ /* win_out(0x0000,Interrupt_A_Enable_Register); */
+ /* win_out(0x0000,Interrupt_B_Enable_Register); */
+
+ /* G(i)_Synchronized_Gate = 1 (write) */
+ devpriv->gpct_command0 |= G0_Synchronized_Gate;
+ devpriv->gpct_command1 |= G1_Synchronized_Gate;
+ win_out(devpriv->gpct_command0,G_Command_Register(0));
+ win_out(devpriv->gpct_command1,G_Command_Register(1));
+
+ /* XXX - for now we leave this in, but perhaps we could do without
+ if it causes problems elsewhere? */
+ /* G(i)_Gate_Error_Confirm = 1 (strobe) */
+ /* G(i)_TC_Error_Confirm = 1 (strobe) */
+ /* G(i)_TC_Interrupt_Ack = 1 (strobe) */
+ /* G(i)_Gate_Interrupt_Ack = 1 (strobe) */
+ win_out(G0_Gate_Error_Confirm|G0_TC_Error_Confirm|G0_TC_Interrupt_Ack|
+ G0_Gate_Interrupt_Ack,Interrupt_A_Ack_Register);
+ win_out(G1_Gate_Error_Confirm|G1_TC_Error_Confirm|G1_TC_Interrupt_Ack|
+ G1_Gate_Interrupt_Ack,Interrupt_B_Ack_Register);
+
+ /********************************************************************/
+
+ /* HACK - What follows is a hack. This puts counter #0 in
+ "relative position sensing" mode and then arms it */
+
+ /* G(i)_Load_Source_Select = 0 (write) */
+ devpriv->gpct_mode0 &= ~G0_Load_Source_Select;
+ win_out(devpriv->gpct_mode0,G_Mode_Register(0));
+
+ /* G(i)_Load_A = initial counter value (write) */
+ msb = counter_init>>16;
+ lsb = counter_init - msb;
+ win_out(msb,G_Load_A_Register_High(0));
+ win_out(lsb,G_Load_A_Register_Low(0));
+
+ /* FLUSH */
+
+ /* G(i)_Load = 1 (strobe) */
+ tmpreg = devpriv->gpct_command0 | G0_Load;
+ win_out(tmpreg,G_Command_Register(0));
+
+ /* FLUSH */
+
+ /* G(i)_Source_Select = PFI0 (write) */
+ devpriv->gpct_input_select0 &= (0xffff & G_Source_Select(0x00));
+ devpriv->gpct_input_select0 |= G_Source_Select(0x01);
+
+ /* G(i)_Source_Polarity = 0 (count rising edges) (write) */
+ devpriv->gpct_input_select0 &= ~G0_Source_Polarity;
+
+ /* G(i)_Gate_select = 0 (write) */
+ devpriv->gpct_input_select0 &= (0xffff & G_Gate_Select(0x00));
+ devpriv->gpct_input_select0 |= G_Gate_Select(0x00);
+
+ /* G(i)_OR_Gate = 0 (write) */
+ devpriv->gpct_input_select0 &= ~G0_OR_Gate;
+
+ /* G(i)_Output_Polarity = 0 (write) */
+ devpriv->gpct_input_select0 &= ~G0_Output_Polarity;
+
+ /* G(i)_Gate_Select_Load_Source = 0 (write) */
+ devpriv->gpct_input_select0 &= ~G0_Gate_Select_Load_Source;
+
+ /* G(i)_Gate_Polarity = 0 (write) */
+ devpriv->gpct_mode0 &= ~G0_Gate_Polarity;
+
+ /* G(i)_Output_Mode = 1 (one clock cycle output) (write) */
+ devpriv->gpct_mode0 &= (0xffff & G_Output_Mode(0x00));
+ devpriv->gpct_mode0 |= G_Output_Mode(0x01);
+
+ /* G(i)_Reload_Source_Switching = 1 (write) */
+ devpriv->gpct_mode0 |= G0_Reload_Source_Switching;
+
+ /* G(i)_Loading_On_Gate = 0 (write) */
+ devpriv->gpct_mode0 &= ~G0_Loading_On_Gate;
+
+ /* G(i)_Gating_Mode = 2 (write) */
+ devpriv->gpct_mode0 &= (0xffff & G_Gating_Mode(0x00));
+ devpriv->gpct_mode0 |= G_Gating_Mode(0x02);
+
+ /* G(i)_Gate_On_Both_Edges = 0 (write) */
+ devpriv->gpct_mode0 &= ~G0_Gate_On_Both_Edges;
+
+ /* G(i)_Trigger_Mode_For_Edge_Gate = 3 (write) */
+ devpriv->gpct_mode0 &= (0xffff & G_Trigger_Mode_For_Edge_Gate(0x00));
+ devpriv->gpct_mode0 |= G_Trigger_Mode_For_Edge_Gate(0x03);
+
+ /* G(i)_Stop_Mode = 0 */
+ devpriv->gpct_mode0 &= (0xffff & G0_Stop_Mode(0x00));
+ devpriv->gpct_mode0 |= G0_Stop_Mode(0x00);
+
+ /* G(i)_Counting_Once = 0 (write) */
+ devpriv->gpct_mode0 &= (0xffff & G0_Counting_Once(0x00));
+ devpriv->gpct_mode0 |= G0_Counting_Once(0x00);
+
+ /* G(i)_Up_Down = 2 (hardware controlled) (write) */
+ devpriv->gpct_command0 &= (0xffff & G_Up_Down(0x00));
+ devpriv->gpct_command0 |= G_Up_Down(0x02);
+
+ /* G(i)_Bank_Switch_Enable = 0 (write) */
+ devpriv->gpct_command0 &= ~G0_Bank_Switch_Enable;
+
+ /* G(i)_Bank_Switch_Mode = 0 (write) */
+ devpriv->gpct_command0 &= ~G0_Bank_Switch_Mode;
+
+ /* XXX - for now we ignore interrupts */
+ /* G(i)_TC_Interrupt_Enable = 0 (write) */
+ /* win_out(0x0000,Interrupt_A_Enable_Register); */
+
+ /* XXX - for now we ignore interrupts */
+ /* G(i)_Gate_Interrupt_Enable = 0 (write) */
+ /* win_out(0x0000,Interrupt_A_Enable_Register); */
+
+ /* actually write out the registers */
+ win_out(devpriv->gpct_input_select0,G_Input_Select_Register(0));
+ win_out(devpriv->gpct_mode0,G_Mode_Register(0));
+ win_out(devpriv->gpct_command0,G_Command_Register(0));
+
+ /********************************************************************/
+
+ /* HACK - What follows continues my hack of configuring the
+ counter in a specific mode. Arming the counter instructs
+ it to start running with our configuration */
+
+ /* Arm the counter 0 (stobe) */
+ tmpreg = devpriv->gpct_command0 | G0_Arm;
+ win_out(tmpreg,G_Command_Register(0));
+
+ return 0;
+}
+
+#if 0
int gpct_start(comedi_device *dev,int chan)
{
/* select load source */
}
return -EINVAL;
}
-
#endif
static int ni_8255_callback(int dir,int port,int data,void *arg)
return ni_readb(25+2*port);
}
}
-
#define G_Autoincrement_Register(a) (68+(a))
#define G_Command_Register(a) (6+(a))
-#define G_HW_Save_Register1(a) (8+(a)*2)
-#define G_HW_Save_Register2(a) (9+(a)*2)
+#define G_HW_Save_Register_High(a) (8+(a)*2)
+#define G_HW_Save_Register_Low(a) (9+(a)*2)
#define G_Input_Select_Register(a) (36+(a))
-#define G_Load_A_Register1(a) (28+(a)*4)
-#define G_Load_A_Register2(a) (29+(a)*4)
-#define G_Load_B_Register1(a) (30+(a)*4)
-#define G_Load_B_Register2(a) (31+(a)*4)
+#define G_Load_A_Register_High(a) (28+(a)*4)
+#define G_Load_A_Register_Low(a) (29+(a)*4)
+#define G_Load_B_Register_High(a) (30+(a)*4)
+#define G_Load_B_Register_Low(a) (31+(a)*4)
#define G_Mode_Register(a) (26+(a))
-#define G_Save_Register1(a) (12+(a)*2)
-#define G_Save_Register2(a) (13+(a)*2)
+#define G_Save_Register_High(a) (12+(a)*2)
+#define G_Save_Register_Low(a) (13+(a)*2)
#define G_Status_Register 4
/* command register */
#define G_Disarm_Copy _bit15 /* strobe */
#define G_Save_Trace_Copy _bit14
#define G_Arm_Copy _bit13 /* strobe */
-#define G_Bank_Switch_Enable _bit12
-#define G_Bank_Switch_Mode _bit11
+#define G0_Bank_Switch_Enable _bit12
+#define G1_Bank_Switch_Enable _bit12
+#define G0_Bank_Switch_Mode _bit11
+#define G1_Bank_Switch_Mode _bit11
#define G_Bank_Switch_Start _bit10 /* strobe */
#define G_Little_Big_Endian _bit9
#define G_Synchronized_Gate _bit8
#define G_Up_Down(a) (((a)&0x03)<<5)
#define G_Disarm _bit4 /* strobe */
#define G_Analog_Trigger_Reset _bit3 /* strobe */
-#define G_Load _bit2 /* strobe */
+#define G0_Load _bit2 /* strobe */
+#define G1_Load _bit2 /* strobe */
#define G_Save_Trace _bit1
#define G_Arm _bit0 /* strobe */
/* input select register */
-#define G_Source_Polarity _bit15
-#define G_Output_Polarity _bit14
-#define G_OR_Gate _bit13
-#define G_Gate_Select_Load_Source _bit12
+#define G0_Source_Polarity _bit15
+#define G1_Source_Polarity _bit15
+#define G0_Output_Polarity _bit14
+#define G1_Output_Polarity _bit14
+#define G0_OR_Gate _bit13
+#define G1_OR_Gate _bit13
+#define G0_Gate_Select_Load_Source _bit12
+#define G1_Gate_Select_Load_Source _bit12
#define G_Gate_Select(a) (((a)&0x1f)<<7)
#define G_Source_Select(a) (((a)&0x1f)<<2)
#define G_Write_Acknowledges_Irq _bit1
#define G_Read_Acknowledges_Irq _bit0
/* mode register */
-#define G_Reload_Source_Switching _bit15
-#define G_Loading_On_Gate _bit14
-#define G_Gate_Polarity _bit13
+#define G0_Load_Source_Select _bit7
+#define G1_Load_Source_Select _bit7
+
+#define G0_Reload_Source_Switching _bit15
+#define G1_Reload_Source_Switching _bit15
+#define G0_Loading_On_Gate _bit14
+#define G1_Loading_On_Gate _bit14
+#define G0_Gate_Polarity _bit13
+#define G1_Gate_Polarity _bit13
#define G_Loading_On_TC _bit12
-#define G_Counting_Once(a) (((a)&0x03)<<10)
+#define G0_Counting_Once(a) (((a)&0x03)<<10)
+#define G1_Counting_Once(a) (((a)&0x03)<<10)
#define G_Output_Mode(a) (((a)&0x03)<<8)
-#define G_Load_Source_Select _bit7
-#define G_Stop_Mode(a) (((a)&0x03)<<5)
+#define G0_Stop_Mode(a) (((a)&0x03)<<5)
+#define G1_Stop_Mode(a) (((a)&0x03)<<5)
#define G_Trigger_Mode_For_Edge_Gate(a) (((a)&0x03)<<3)
-#define G_Gate_On_Both_Edges _bit1
+#define G0_Gate_On_Both_Edges _bit1
+#define G1_Gate_On_Both_Edges _bit1
#define G_Gating_Mode(a) (((a)&0x03)<<0)
-
+/* CLO */
+/* general purpose counter timer */
+#define G0_Reset _bit2
+#define G1_Reset _bit3
+#define G0_TC_Interrupt_Enable _bit6
+#define G1_TC_Interrupt_Enable _bit9
+#define G0_Gate_Interrupt_Enable _bit8
+#define G1_Gate_Interrupt_Enable _bit10
+#define G0_Synchronized_Gate _bit8
+#define G1_Synchronized_Gate _bit8
+#define G0_Gate_Error_Confirm _bit5
+#define G1_Gate_Error_Confirm _bit1
+#define G0_TC_Error_Confirm _bit6
+#define G1_TC_Error_Confirm _bit2
+#define G0_TC_Interrupt_Ack _bit14
+#define G1_TC_Interrupt_Ack _bit14
+#define G0_Gate_Interrupt_Ack _bit15
+#define G1_Gate_Interrupt_Ack _bit15
+#define G_Autoincrement(a) ((a)<<0)
+#define G_Autoincrement(a) ((a)<<0)
+#define G0_Arm _bit0
+#define G1_Arm _bit0
/* Additional windowed registers unique to E series */
int has_8255;
+ int n_gpct; /* CLO */
+
struct caldac_struct **caldac;
}ni_board;