4 Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module.
10 Fax: +49(0)7223/9493-92
11 http://www.addi-data.com
14 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
16 This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
22 +-----------------------------------------------------------------------+
23 | (C) ADDI-DATA GmbH Dieselstraße 3 D-77833 Ottersweier |
24 +-----------------------------------------------------------------------+
25 | Tel : +49 (0) 7223/9493-0 | email : info@addi-data.com |
26 | Fax : +49 (0) 7223/9493-92 | Internet : http://www.addi-data.com |
27 +-----------------------------------------------------------------------+
28 | Project : API APCI1710 | Compiler : gcc |
29 | Module name : SSI.C | Version : 2.96 |
30 +-------------------------------+---------------------------------------+
31 | Project manager: Eric Stolz | Date : 02/12/2002 |
32 +-----------------------------------------------------------------------+
33 | Description : APCI-1710 SSI counter module |
34 +-----------------------------------------------------------------------+
35 | several changes done by S. Weber in 1998 and C. Guinot in 2000 |
36 +-----------------------------------------------------------------------+
39 #define APCI1710_30MHZ 30
40 #define APCI1710_33MHZ 33
41 #define APCI1710_40MHZ 40
43 #define APCI1710_BINARY_MODE 0x1
44 #define APCI1710_GRAY_MODE 0x0
46 #define APCI1710_SSI_READ1VALUE 1
47 #define APCI1710_SSI_READALLVALUE 2
49 #define APCI1710_SSI_SET_CHANNELON 0
50 #define APCI1710_SSI_SET_CHANNELOFF 1
51 #define APCI1710_SSI_READ_1CHANNEL 2
52 #define APCI1710_SSI_READ_ALLCHANNEL 3
55 +----------------------------------------------------------------------------+
56 | Function Name : _INT_ i_APCI1710_InitSSI |
57 | (unsigned char_ b_BoardHandle, |
58 | unsigned char_ b_ModulNbr, |
59 | unsigned char_ b_SSIProfile, |
60 | unsigned char_ b_PositionTurnLength, |
61 | unsigned char_ b_TurnCptLength, |
62 | unsigned char_ b_PCIInputClock, |
63 | ULONG_ ul_SSIOutputClock, |
64 | unsigned char_ b_SSICountingMode) |
65 +----------------------------------------------------------------------------+
66 | Task : Configure the SSI operating mode from selected module |
67 | (b_ModulNbr). You must calling this function be for you|
68 | call any other function witch access of SSI. |
69 +----------------------------------------------------------------------------+
70 | Input Parameters : unsigned char_ b_BoardHandle : Handle of board APCI-1710|
71 | unsigned char_ b_ModulNbr : Module number to |
72 | configure (0 to 3) |
73 | unsigned char_ b_SSIProfile : Selection from SSI |
74 | profile length (2 to 32).|
75 | unsigned char_ b_PositionTurnLength : Selection from SSI |
76 | position data length |
78 | unsigned char_ b_TurnCptLength : Selection from SSI turn |
79 | counter data length |
81 | unsigned char b_PCIInputClock : Selection from PCI bus |
83 | - APCI1710_30MHZ : |
84 | The PC have a PCI bus |
86 | - APCI1710_33MHZ : |
87 | The PC have a PCI bus |
89 | ULONG_ ul_SSIOutputClock : Selection from SSI output|
91 | From 229 to 5 000 000 Hz|
92 | for 30 MHz selection. |
93 | From 252 to 5 000 000 Hz|
94 | for 33 MHz selection. |
95 | unsigned char b_SSICountingMode : SSI counting mode |
97 | - APCI1710_BINARY_MODE : |
98 | Binary counting mode. |
99 | - APCI1710_GRAY_MODE : |
100 | Gray counting mode.
102 b_ModulNbr = CR_AREF(insn->chanspec);
103 b_SSIProfile = (unsigned char) data[0];
104 b_PositionTurnLength= (unsigned char) data[1];
105 b_TurnCptLength = (unsigned char) data[2];
106 b_PCIInputClock = (unsigned char) data[3];
107 ul_SSIOutputClock = (unsigned int) data[4];
108 b_SSICountingMode = (unsigned char) data[5]; |
109 +----------------------------------------------------------------------------+
110 | Output Parameters : - |
111 +----------------------------------------------------------------------------+
112 | Return Value : 0: No error |
113 | -1: The handle parameter of the board is wrong |
114 | -2: The module parameter is wrong |
115 | -3: The module is not a SSI module |
116 | -4: The selected SSI profile length is wrong |
117 | -5: The selected SSI position data length is wrong |
118 | -6: The selected SSI turn counter data length is wrong |
119 | -7: The selected PCI input clock is wrong |
120 | -8: The selected SSI output clock is wrong |
121 | -9: The selected SSI counting mode parameter is wrong |
122 +----------------------------------------------------------------------------+
125 static int i_APCI1710_InsnConfigInitSSI(struct comedi_device
*dev
,
126 struct comedi_subdevice
*s
,
127 struct comedi_insn
*insn
,
130 struct addi_private
*devpriv
= dev
->private;
131 int i_ReturnValue
= 0;
132 unsigned int ui_TimerValue
;
133 unsigned char b_ModulNbr
, b_SSIProfile
, b_PositionTurnLength
, b_TurnCptLength
,
134 b_PCIInputClock
, b_SSICountingMode
;
135 unsigned int ul_SSIOutputClock
;
137 b_ModulNbr
= CR_AREF(insn
->chanspec
);
138 b_SSIProfile
= (unsigned char) data
[0];
139 b_PositionTurnLength
= (unsigned char) data
[1];
140 b_TurnCptLength
= (unsigned char) data
[2];
141 b_PCIInputClock
= (unsigned char) data
[3];
142 ul_SSIOutputClock
= (unsigned int) data
[4];
143 b_SSICountingMode
= (unsigned char) data
[5];
145 i_ReturnValue
= insn
->n
;
146 /**************************/
147 /* Test the module number */
148 /**************************/
150 if (b_ModulNbr
< 4) {
151 /***********************/
152 /* Test if SSI counter */
153 /***********************/
155 if ((devpriv
->s_BoardInfos
.
156 dw_MolduleConfiguration
[b_ModulNbr
] &
157 0xFFFF0000UL
) == APCI1710_SSI_COUNTER
) {
158 /*******************************/
159 /* Test the SSI profile length */
160 /*******************************/
162 /* CG 22/03/00 b_SSIProfile >= 2 anstatt b_SSIProfile > 2 */
163 if (b_SSIProfile
>= 2 && b_SSIProfile
< 33) {
164 /*************************************/
165 /* Test the SSI position data length */
166 /*************************************/
168 if (b_PositionTurnLength
> 0
169 && b_PositionTurnLength
< 32) {
170 /*****************************************/
171 /* Test the SSI turn counter data length */
172 /*****************************************/
174 if (b_TurnCptLength
> 0
175 && b_TurnCptLength
< 32) {
176 /***************************/
177 /* Test the profile length */
178 /***************************/
180 if ((b_TurnCptLength
+
181 b_PositionTurnLength
)
183 /****************************/
184 /* Test the PCI input clock */
185 /****************************/
187 if (b_PCIInputClock
==
194 /*************************/
195 /* Test the output clock */
196 /*************************/
198 if ((b_PCIInputClock
== APCI1710_30MHZ
&& (ul_SSIOutputClock
> 228 && ul_SSIOutputClock
<= 5000000UL)) || (b_PCIInputClock
== APCI1710_33MHZ
&& (ul_SSIOutputClock
> 251 && ul_SSIOutputClock
<= 5000000UL))) {
199 if (b_SSICountingMode
== APCI1710_BINARY_MODE
|| b_SSICountingMode
== APCI1710_GRAY_MODE
) {
200 /**********************/
201 /* Save configuration */
202 /**********************/
217 b_PositionTurnLength
;
227 /*********************************/
228 /* Initialise the profile length */
229 /*********************************/
231 if (b_SSICountingMode
== APCI1710_BINARY_MODE
) {
233 outl(b_SSIProfile
+ 1, devpriv
->s_BoardInfos
.ui_Address
+ 4 + (64 * b_ModulNbr
));
236 outl(b_SSIProfile
, devpriv
->s_BoardInfos
.ui_Address
+ 4 + (64 * b_ModulNbr
));
239 /******************************/
240 /* Calculate the output clock */
241 /******************************/
247 ((unsigned int) (b_PCIInputClock
) * 500000UL) / ul_SSIOutputClock
);
249 /************************/
250 /* Initialise the timer */
251 /************************/
253 outl(ui_TimerValue
, devpriv
->s_BoardInfos
.ui_Address
+ (64 * b_ModulNbr
));
255 /********************************/
256 /* Initialise the counting mode */
257 /********************************/
259 outl(7 * b_SSICountingMode
, devpriv
->s_BoardInfos
.ui_Address
+ 12 + (64 * b_ModulNbr
));
269 /*****************************************************/
270 /* The selected SSI counting mode parameter is wrong */
271 /*****************************************************/
273 DPRINTK("The selected SSI counting mode parameter is wrong\n");
279 /******************************************/
280 /* The selected SSI output clock is wrong */
281 /******************************************/
283 DPRINTK("The selected SSI output clock is wrong\n");
289 /*****************************************/
290 /* The selected PCI input clock is wrong */
291 /*****************************************/
293 DPRINTK("The selected PCI input clock is wrong\n");
298 /********************************************/
299 /* The selected SSI profile length is wrong */
300 /********************************************/
302 DPRINTK("The selected SSI profile length is wrong\n");
306 /******************************************************/
307 /* The selected SSI turn counter data length is wrong */
308 /******************************************************/
310 DPRINTK("The selected SSI turn counter data length is wrong\n");
314 /**************************************************/
315 /* The selected SSI position data length is wrong */
316 /**************************************************/
318 DPRINTK("The selected SSI position data length is wrong\n");
322 /********************************************/
323 /* The selected SSI profile length is wrong */
324 /********************************************/
326 DPRINTK("The selected SSI profile length is wrong\n");
330 /**********************************/
331 /* The module is not a SSI module */
332 /**********************************/
334 DPRINTK("The module is not a SSI module\n");
338 /***********************/
339 /* Module number error */
340 /***********************/
342 DPRINTK("Module number error\n");
346 return i_ReturnValue
;
350 +----------------------------------------------------------------------------+
351 | Function Name : _INT_ i_APCI1710_Read1SSIValue |
352 | (unsigned char_ b_BoardHandle, |
353 | unsigned char_ b_ModulNbr, |
354 | unsigned char_ b_SelectedSSI, |
355 | PULONG_ pul_Position, |
356 | PULONG_ pul_TurnCpt)
357 int i_APCI1710_ReadSSIValue(struct comedi_device *dev,struct comedi_subdevice *s,
358 struct comedi_insn *insn,unsigned int *data) |
359 +----------------------------------------------------------------------------+
363 Read the selected SSI counter (b_SelectedSSI) from |
364 | selected module (b_ModulNbr).
365 or Read all SSI counter (b_SelectedSSI) from |
366 | selected module (b_ModulNbr). |
367 +----------------------------------------------------------------------------+
368 | Input Parameters : unsigned char_ b_BoardHandle : Handle of board APCI-1710|
369 | unsigned char_ b_ModulNbr : Module number to |
370 | configure (0 to 3) |
371 | unsigned char_ b_SelectedSSI : Selection from SSI |
374 b_ModulNbr = (unsigned char) CR_AREF(insn->chanspec);
375 b_SelectedSSI = (unsigned char) CR_CHAN(insn->chanspec); (in case of single ssi)
376 b_ReadType = (unsigned char) CR_RANGE(insn->chanspec);
378 +----------------------------------------------------------------------------+
379 | Output Parameters : PULONG_ pul_Position : SSI position in the turn |
380 | PULONG_ pul_TurnCpt : Number of turns
382 pul_Position = (unsigned int *) &data[0];
383 pul_TurnCpt = (unsigned int *) &data[1]; |
384 +----------------------------------------------------------------------------+
385 | Return Value : 0: No error |
386 | -1: The handle parameter of the board is wrong |
387 | -2: The module parameter is wrong |
388 | -3: The module is not a SSI module |
389 | -4: SSI not initialised see function |
390 | "i_APCI1710_InitSSI" |
391 | -5: The selected SSI is wrong |
392 +----------------------------------------------------------------------------+
395 static int i_APCI1710_InsnReadSSIValue(struct comedi_device
*dev
,
396 struct comedi_subdevice
*s
,
397 struct comedi_insn
*insn
,
400 struct addi_private
*devpriv
= dev
->private;
401 int i_ReturnValue
= 0;
403 unsigned char b_Length
;
404 unsigned char b_Schift
;
405 unsigned char b_SSICpt
;
407 unsigned int dw_And1
;
408 unsigned int dw_And2
;
409 unsigned int dw_StatusReg
;
410 unsigned int dw_CounterValue
;
411 unsigned char b_ModulNbr
;
412 unsigned char b_SelectedSSI
;
413 unsigned char b_ReadType
;
414 unsigned int *pul_Position
;
415 unsigned int *pul_TurnCpt
;
416 unsigned int *pul_Position1
;
417 unsigned int *pul_TurnCpt1
;
419 i_ReturnValue
= insn
->n
;
420 pul_Position1
= (unsigned int *) &data
[0];
422 pul_TurnCpt1
= (unsigned int *) &data
[1];
424 pul_Position
= (unsigned int *) &data
[0]; /* 0-2 */
425 pul_TurnCpt
= (unsigned int *) &data
[3]; /* 3-5 */
426 b_ModulNbr
= (unsigned char) CR_AREF(insn
->chanspec
);
427 b_SelectedSSI
= (unsigned char) CR_CHAN(insn
->chanspec
);
428 b_ReadType
= (unsigned char) CR_RANGE(insn
->chanspec
);
430 /**************************/
431 /* Test the module number */
432 /**************************/
434 if (b_ModulNbr
< 4) {
435 /***********************/
436 /* Test if SSI counter */
437 /***********************/
439 if ((devpriv
->s_BoardInfos
.
440 dw_MolduleConfiguration
[b_ModulNbr
] &
441 0xFFFF0000UL
) == APCI1710_SSI_COUNTER
) {
442 /***************************/
443 /* Test if SSI initialised */
444 /***************************/
446 if (devpriv
->s_ModuleInfo
[b_ModulNbr
].
447 s_SSICounterInfo
.b_SSIInit
== 1) {
449 switch (b_ReadType
) {
451 case APCI1710_SSI_READ1VALUE
:
452 /****************************************/
453 /* Test the selected SSI counter number */
454 /****************************************/
456 if (b_SelectedSSI
< 3) {
457 /************************/
458 /* Start the conversion */
459 /************************/
461 outl(0, devpriv
->s_BoardInfos
.
466 /*******************/
467 /* Read the status */
468 /*******************/
475 } while ((dw_StatusReg
& 0x1)
478 /******************************/
479 /* Read the SSI counter value */
480 /******************************/
486 (b_SelectedSSI
* 4) +
496 if ((b_Length
* 2) !=
511 b_PositionTurnLength
;
525 b_PositionTurnLength
;
555 /*****************************/
556 /* The selected SSI is wrong */
557 /*****************************/
559 DPRINTK("The selected SSI is wrong\n");
564 case APCI1710_SSI_READALLVALUE
:
570 s_ModuleInfo
[b_ModulNbr
].
572 b_PositionTurnLength
; b_Cpt
++) {
573 dw_And1
= dw_And1
* 2;
581 s_ModuleInfo
[b_ModulNbr
].
583 b_TurnCptLength
; b_Cpt
++) {
584 dw_And2
= dw_And2
* 2;
587 /************************/
588 /* Start the conversion */
589 /************************/
591 outl(0, devpriv
->s_BoardInfos
.
596 /*******************/
597 /* Read the status */
598 /*******************/
605 } while ((dw_StatusReg
& 0x1) != 0);
607 for (b_SSICpt
= 0; b_SSICpt
< 3;
609 /******************************/
610 /* Read the SSI counter value */
611 /******************************/
627 if ((b_Length
* 2) !=
642 b_PositionTurnLength
;
644 pul_Position
[b_SSICpt
] =
647 pul_Position
[b_SSICpt
] =
648 pul_Position
[b_SSICpt
] &
651 pul_TurnCpt
[b_SSICpt
] =
654 pul_TurnCpt
[b_SSICpt
] =
655 pul_TurnCpt
[b_SSICpt
] &
661 printk("Read Type Inputs Wrong\n");
663 } /* switch ending */
666 /***********************/
667 /* SSI not initialised */
668 /***********************/
670 DPRINTK("SSI not initialised\n");
674 /**********************************/
675 /* The module is not a SSI module */
676 /**********************************/
678 DPRINTK("The module is not a SSI module\n");
683 /***********************/
684 /* Module number error */
685 /***********************/
687 DPRINTK("Module number error\n");
691 return i_ReturnValue
;
695 +----------------------------------------------------------------------------+
696 | Function Name : _INT_ i_APCI1710_ReadSSI1DigitalInput |
697 | (unsigned char_ b_BoardHandle, |
698 | unsigned char_ b_ModulNbr, |
699 | unsigned char_ b_InputChannel, |
700 | unsigned char *_ pb_ChannelStatus) |
701 +----------------------------------------------------------------------------+
703 (0) Set the digital output from selected SSI module |
705 (1) Set the digital output from selected SSI module |
707 (2)Read the status from selected SSI digital input |
709 (3)Read the status from all SSI digital inputs from |
710 | selected SSI module (b_ModulNbr) |
711 +----------------------------------------------------------------------------+
712 | Input Parameters : unsigned char_ b_BoardHandle : Handle of board APCI-1710|
713 | unsigned char_ b_ModulNbr CR_AREF : Module number to |
714 | configure (0 to 3) |
715 | unsigned char_ b_InputChannel CR_CHAN : Selection from digital |
716 | data[0] which IOTYPE input ( 0 to 2) |
717 +----------------------------------------------------------------------------+
718 | Output Parameters : unsigned char *_ pb_ChannelStatus : Digital input channel |
720 | 0 : Channle is not active|
721 | 1 : Channle is active |
722 +----------------------------------------------------------------------------+
723 | Return Value : 0: No error |
724 | -1: The handle parameter of the board is wrong |
725 | -2: The module parameter is wrong |
726 | -3: The module is not a SSI module |
727 | -4: The selected SSI digital input is wrong |
728 +----------------------------------------------------------------------------+
731 static int i_APCI1710_InsnBitsSSIDigitalIO(struct comedi_device
*dev
,
732 struct comedi_subdevice
*s
,
733 struct comedi_insn
*insn
,
736 struct addi_private
*devpriv
= dev
->private;
737 int i_ReturnValue
= 0;
738 unsigned int dw_StatusReg
;
739 unsigned char b_ModulNbr
;
740 unsigned char b_InputChannel
;
741 unsigned char *pb_ChannelStatus
;
742 unsigned char *pb_InputStatus
;
743 unsigned char b_IOType
;
745 i_ReturnValue
= insn
->n
;
746 b_ModulNbr
= (unsigned char) CR_AREF(insn
->chanspec
);
747 b_IOType
= (unsigned char) data
[0];
749 /**************************/
750 /* Test the module number */
751 /**************************/
753 if (b_ModulNbr
< 4) {
754 /***********************/
755 /* Test if SSI counter */
756 /***********************/
758 if ((devpriv
->s_BoardInfos
.
759 dw_MolduleConfiguration
[b_ModulNbr
] &
760 0xFFFF0000UL
) == APCI1710_SSI_COUNTER
) {
762 case APCI1710_SSI_SET_CHANNELON
:
763 /*****************************/
764 /* Set the digital output ON */
765 /*****************************/
767 outl(1, devpriv
->s_BoardInfos
.ui_Address
+ 16 +
771 case APCI1710_SSI_SET_CHANNELOFF
:
772 /******************************/
773 /* Set the digital output OFF */
774 /******************************/
776 outl(0, devpriv
->s_BoardInfos
.ui_Address
+ 16 +
780 case APCI1710_SSI_READ_1CHANNEL
:
781 /******************************************/
782 /* Test the digital imnput channel number */
783 /******************************************/
785 b_InputChannel
= (unsigned char) CR_CHAN(insn
->chanspec
);
786 pb_ChannelStatus
= (unsigned char *) &data
[0];
788 if (b_InputChannel
<= 2) {
789 /**************************/
790 /* Read all digital input */
791 /**************************/
794 inl(devpriv
->s_BoardInfos
.
795 ui_Address
+ (64 * b_ModulNbr
));
797 (unsigned char) (((~dw_StatusReg
) >> (4 +
801 /********************************/
802 /* Selected digital input error */
803 /********************************/
805 DPRINTK("Selected digital input error\n");
810 case APCI1710_SSI_READ_ALLCHANNEL
:
811 /**************************/
812 /* Read all digital input */
813 /**************************/
814 pb_InputStatus
= (unsigned char *) &data
[0];
817 inl(devpriv
->s_BoardInfos
.ui_Address
+
820 (unsigned char) (((~dw_StatusReg
) >> 4) & 7);
824 printk("IO type wrong\n");
828 /**********************************/
829 /* The module is not a SSI module */
830 /**********************************/
832 DPRINTK("The module is not a SSI module\n");
836 /***********************/
837 /* Module number error */
838 /***********************/
840 DPRINTK("Module number error\n");
844 return i_ReturnValue
;