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.
18 You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 You shoud also find the complete GPL in the COPYING file accompanying this source code.
26 +-----------------------------------------------------------------------+
27 | (C) ADDI-DATA GmbH Dieselstraße 3 D-77833 Ottersweier |
28 +-----------------------------------------------------------------------+
29 | Tel : +49 (0) 7223/9493-0 | email : info@addi-data.com |
30 | Fax : +49 (0) 7223/9493-92 | Internet : http://www.addi-data.com |
31 +-----------------------------------------------------------------------+
32 | Project : API APCI1710 | Compiler : gcc |
33 | Module name : SSI.C | Version : 2.96 |
34 +-------------------------------+---------------------------------------+
35 | Project manager: Eric Stolz | Date : 02/12/2002 |
36 +-----------------------------------------------------------------------+
37 | Description : APCI-1710 SSI counter module |
40 +-----------------------------------------------------------------------+
42 +-----------------------------------------------------------------------+
43 | Date | Author | Description of updates |
44 +----------+-----------+------------------------------------------------+
45 | 13/05/98 | S. Weber | SSI digital input / output implementation |
46 |----------|-----------|------------------------------------------------|
47 | 22/03/00 | C.Guinot | 0100/0226 -> 0200/0227 |
48 | | | Änderung in InitSSI Funktion |
49 | | | b_SSIProfile >= 2 anstatt b_SSIProfile > 2 |
51 +-----------------------------------------------------------------------+
52 | 08/05/00 | Guinot C | - 0400/0228 All Function in RING 0 |
54 +-----------------------------------------------------------------------+
58 +----------------------------------------------------------------------------+
60 +----------------------------------------------------------------------------+
63 #include "APCI1710_Ssi.h"
66 +----------------------------------------------------------------------------+
67 | Function Name : _INT_ i_APCI1710_InitSSI |
68 | (BYTE_ b_BoardHandle, |
70 | BYTE_ b_SSIProfile, |
71 | BYTE_ b_PositionTurnLength, |
72 | BYTE_ b_TurnCptLength, |
73 | BYTE_ b_PCIInputClock, |
74 | ULONG_ ul_SSIOutputClock, |
75 | BYTE_ b_SSICountingMode) |
76 +----------------------------------------------------------------------------+
77 | Task : Configure the SSI operating mode from selected module |
78 | (b_ModulNbr). You must calling this function be for you|
79 | call any other function witch access of SSI. |
80 +----------------------------------------------------------------------------+
81 | Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710|
82 | BYTE_ b_ModulNbr : Module number to |
83 | configure (0 to 3) |
84 | BYTE_ b_SSIProfile : Selection from SSI |
85 | profile length (2 to 32).|
86 | BYTE_ b_PositionTurnLength : Selection from SSI |
87 | position data length |
89 | BYTE_ b_TurnCptLength : Selection from SSI turn |
90 | counter data length |
92 | BYTE b_PCIInputClock : Selection from PCI bus |
94 | - APCI1710_30MHZ : |
95 | The PC have a PCI bus |
97 | - APCI1710_33MHZ : |
98 | The PC have a PCI bus |
100 | ULONG_ ul_SSIOutputClock : Selection from SSI output|
102 | From 229 to 5 000 000 Hz|
103 | for 30 MHz selection. |
104 | From 252 to 5 000 000 Hz|
105 | for 33 MHz selection. |
106 | BYTE b_SSICountingMode : SSI counting mode |
108 | - APCI1710_BINARY_MODE : |
109 | Binary counting mode. |
110 | - APCI1710_GRAY_MODE : |
111 | Gray counting mode.
113 b_ModulNbr = CR_AREF(insn->chanspec);
114 b_SSIProfile = (BYTE) data[0];
115 b_PositionTurnLength= (BYTE) data[1];
116 b_TurnCptLength = (BYTE) data[2];
117 b_PCIInputClock = (BYTE) data[3];
118 ul_SSIOutputClock = (ULONG) data[4];
119 b_SSICountingMode = (BYTE) data[5]; |
120 +----------------------------------------------------------------------------+
121 | Output Parameters : - |
122 +----------------------------------------------------------------------------+
123 | Return Value : 0: No error |
124 | -1: The handle parameter of the board is wrong |
125 | -2: The module parameter is wrong |
126 | -3: The module is not a SSI module |
127 | -4: The selected SSI profile length is wrong |
128 | -5: The selected SSI position data length is wrong |
129 | -6: The selected SSI turn counter data length is wrong |
130 | -7: The selected PCI input clock is wrong |
131 | -8: The selected SSI output clock is wrong |
132 | -9: The selected SSI counting mode parameter is wrong |
133 +----------------------------------------------------------------------------+
136 INT
i_APCI1710_InsnConfigInitSSI(comedi_device
* dev
, comedi_subdevice
* s
,
137 comedi_insn
* insn
, unsigned int * data
)
139 INT i_ReturnValue
= 0;
141 BYTE b_ModulNbr
, b_SSIProfile
, b_PositionTurnLength
, b_TurnCptLength
,
142 b_PCIInputClock
, b_SSICountingMode
;
143 ULONG ul_SSIOutputClock
;
145 b_ModulNbr
= CR_AREF(insn
->chanspec
);
146 b_SSIProfile
= (BYTE
) data
[0];
147 b_PositionTurnLength
= (BYTE
) data
[1];
148 b_TurnCptLength
= (BYTE
) data
[2];
149 b_PCIInputClock
= (BYTE
) data
[3];
150 ul_SSIOutputClock
= (ULONG
) data
[4];
151 b_SSICountingMode
= (BYTE
) data
[5];
153 i_ReturnValue
= insn
->n
;
154 /**************************/
155 /* Test the module number */
156 /**************************/
158 if (b_ModulNbr
< 4) {
159 /***********************/
160 /* Test if SSI counter */
161 /***********************/
163 if ((devpriv
->s_BoardInfos
.
164 dw_MolduleConfiguration
[b_ModulNbr
] &
165 0xFFFF0000UL
) == APCI1710_SSI_COUNTER
) {
166 /*******************************/
167 /* Test the SSI profile length */
168 /*******************************/
170 // CG 22/03/00 b_SSIProfile >= 2 anstatt b_SSIProfile > 2
171 if (b_SSIProfile
>= 2 && b_SSIProfile
< 33) {
172 /*************************************/
173 /* Test the SSI position data length */
174 /*************************************/
176 if (b_PositionTurnLength
> 0
177 && b_PositionTurnLength
< 32) {
178 /*****************************************/
179 /* Test the SSI turn counter data length */
180 /*****************************************/
182 if (b_TurnCptLength
> 0
183 && b_TurnCptLength
< 32) {
184 /***************************/
185 /* Test the profile length */
186 /***************************/
188 if ((b_TurnCptLength
+
189 b_PositionTurnLength
)
191 /****************************/
192 /* Test the PCI input clock */
193 /****************************/
195 if (b_PCIInputClock
==
202 /*************************/
203 /* Test the output clock */
204 /*************************/
206 if ((b_PCIInputClock
== APCI1710_30MHZ
&& (ul_SSIOutputClock
> 228 && ul_SSIOutputClock
<= 5000000UL)) || (b_PCIInputClock
== APCI1710_33MHZ
&& (ul_SSIOutputClock
> 251 && ul_SSIOutputClock
<= 5000000UL))) {
207 if (b_SSICountingMode
== APCI1710_BINARY_MODE
|| b_SSICountingMode
== APCI1710_GRAY_MODE
) {
208 /**********************/
209 /* Save configuration */
210 /**********************/
225 b_PositionTurnLength
;
235 /*********************************/
236 /* Initialise the profile length */
237 /*********************************/
239 if (b_SSICountingMode
== APCI1710_BINARY_MODE
) {
241 outl(b_SSIProfile
+ 1, devpriv
->s_BoardInfos
.ui_Address
+ 4 + (64 * b_ModulNbr
));
244 outl(b_SSIProfile
, devpriv
->s_BoardInfos
.ui_Address
+ 4 + (64 * b_ModulNbr
));
247 /******************************/
248 /* Calculate the output clock */
249 /******************************/
255 ((ULONG
) (b_PCIInputClock
) * 500000UL) / ul_SSIOutputClock
);
257 /************************/
258 /* Initialise the timer */
259 /************************/
261 outl(ui_TimerValue
, devpriv
->s_BoardInfos
.ui_Address
+ (64 * b_ModulNbr
));
263 /********************************/
264 /* Initialise the counting mode */
265 /********************************/
267 outl(7 * b_SSICountingMode
, devpriv
->s_BoardInfos
.ui_Address
+ 12 + (64 * b_ModulNbr
));
277 /*****************************************************/
278 /* The selected SSI counting mode parameter is wrong */
279 /*****************************************************/
281 DPRINTK("The selected SSI counting mode parameter is wrong\n");
287 /******************************************/
288 /* The selected SSI output clock is wrong */
289 /******************************************/
291 DPRINTK("The selected SSI output clock is wrong\n");
297 /*****************************************/
298 /* The selected PCI input clock is wrong */
299 /*****************************************/
301 DPRINTK("The selected PCI input clock is wrong\n");
306 /********************************************/
307 /* The selected SSI profile length is wrong */
308 /********************************************/
310 DPRINTK("The selected SSI profile length is wrong\n");
314 /******************************************************/
315 /* The selected SSI turn counter data length is wrong */
316 /******************************************************/
318 DPRINTK("The selected SSI turn counter data length is wrong\n");
322 /**************************************************/
323 /* The selected SSI position data length is wrong */
324 /**************************************************/
326 DPRINTK("The selected SSI position data length is wrong\n");
330 /********************************************/
331 /* The selected SSI profile length is wrong */
332 /********************************************/
334 DPRINTK("The selected SSI profile length is wrong\n");
338 /**********************************/
339 /* The module is not a SSI module */
340 /**********************************/
342 DPRINTK("The module is not a SSI module\n");
346 /***********************/
347 /* Module number error */
348 /***********************/
350 DPRINTK("Module number error\n");
354 return (i_ReturnValue
);
358 +----------------------------------------------------------------------------+
359 | Function Name : _INT_ i_APCI1710_Read1SSIValue |
360 | (BYTE_ b_BoardHandle, |
361 | BYTE_ b_ModulNbr, |
362 | BYTE_ b_SelectedSSI, |
363 | PULONG_ pul_Position, |
364 | PULONG_ pul_TurnCpt)
365 INT i_APCI1710_ReadSSIValue(comedi_device *dev,comedi_subdevice *s,
366 comedi_insn *insn,unsigned int *data) |
367 +----------------------------------------------------------------------------+
371 Read the selected SSI counter (b_SelectedSSI) from |
372 | selected module (b_ModulNbr).
373 or Read all SSI counter (b_SelectedSSI) from |
374 | selected module (b_ModulNbr). |
375 +----------------------------------------------------------------------------+
376 | Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710|
377 | BYTE_ b_ModulNbr : Module number to |
378 | configure (0 to 3) |
379 | BYTE_ b_SelectedSSI : Selection from SSI |
382 b_ModulNbr = (BYTE) CR_AREF(insn->chanspec);
383 b_SelectedSSI = (BYTE) CR_CHAN(insn->chanspec); (in case of single ssi)
384 b_ReadType = (BYTE) CR_RANGE(insn->chanspec);
386 +----------------------------------------------------------------------------+
387 | Output Parameters : PULONG_ pul_Position : SSI position in the turn |
388 | PULONG_ pul_TurnCpt : Number of turns
390 pul_Position = (PULONG) &data[0];
391 pul_TurnCpt = (PULONG) &data[1]; |
392 +----------------------------------------------------------------------------+
393 | Return Value : 0: No error |
394 | -1: The handle parameter of the board is wrong |
395 | -2: The module parameter is wrong |
396 | -3: The module is not a SSI module |
397 | -4: SSI not initialised see function |
398 | "i_APCI1710_InitSSI" |
399 | -5: The selected SSI is wrong |
400 +----------------------------------------------------------------------------+
403 INT
i_APCI1710_InsnReadSSIValue(comedi_device
* dev
, comedi_subdevice
* s
,
404 comedi_insn
* insn
, unsigned int * data
)
406 INT i_ReturnValue
= 0;
415 DWORD dw_CounterValue
;
421 PULONG pul_Position1
;
424 i_ReturnValue
= insn
->n
;
425 pul_Position1
= (PULONG
) & data
[0];
427 pul_TurnCpt1
= (PULONG
) & data
[1];
429 pul_Position
= (PULONG
) & data
[0]; //0-2
430 pul_TurnCpt
= (PULONG
) & data
[3]; //3-5
431 b_ModulNbr
= (BYTE
) CR_AREF(insn
->chanspec
);
432 b_SelectedSSI
= (BYTE
) CR_CHAN(insn
->chanspec
);
433 b_ReadType
= (BYTE
) CR_RANGE(insn
->chanspec
);
435 /**************************/
436 /* Test the module number */
437 /**************************/
439 if (b_ModulNbr
< 4) {
440 /***********************/
441 /* Test if SSI counter */
442 /***********************/
444 if ((devpriv
->s_BoardInfos
.
445 dw_MolduleConfiguration
[b_ModulNbr
] &
446 0xFFFF0000UL
) == APCI1710_SSI_COUNTER
) {
447 /***************************/
448 /* Test if SSI initialised */
449 /***************************/
451 if (devpriv
->s_ModuleInfo
[b_ModulNbr
].
452 s_SSICounterInfo
.b_SSIInit
== 1) {
454 switch (b_ReadType
) {
456 case APCI1710_SSI_READ1VALUE
:
457 /****************************************/
458 /* Test the selected SSI counter number */
459 /****************************************/
461 if (b_SelectedSSI
< 3) {
462 /************************/
463 /* Start the conversion */
464 /************************/
466 outl(0, devpriv
->s_BoardInfos
.
471 /*******************/
472 /* Read the status */
473 /*******************/
481 while ((dw_StatusReg
& 0x1) !=
484 /******************************/
485 /* Read the SSI counter value */
486 /******************************/
492 (b_SelectedSSI
* 4) +
502 if ((b_Length
* 2) !=
517 b_PositionTurnLength
;
531 b_PositionTurnLength
;
561 /*****************************/
562 /* The selected SSI is wrong */
563 /*****************************/
565 DPRINTK("The selected SSI is wrong\n");
570 case APCI1710_SSI_READALLVALUE
:
576 s_ModuleInfo
[b_ModulNbr
].
578 b_PositionTurnLength
; b_Cpt
++) {
579 dw_And1
= dw_And1
* 2;
587 s_ModuleInfo
[b_ModulNbr
].
589 b_TurnCptLength
; b_Cpt
++) {
590 dw_And2
= dw_And2
* 2;
593 /************************/
594 /* Start the conversion */
595 /************************/
597 outl(0, devpriv
->s_BoardInfos
.
602 /*******************/
603 /* Read the status */
604 /*******************/
612 while ((dw_StatusReg
& 0x1) != 0);
614 for (b_SSICpt
= 0; b_SSICpt
< 3;
616 /******************************/
617 /* Read the SSI counter value */
618 /******************************/
634 if ((b_Length
* 2) !=
649 b_PositionTurnLength
;
651 pul_Position
[b_SSICpt
] =
654 pul_Position
[b_SSICpt
] =
655 pul_Position
[b_SSICpt
] &
658 pul_TurnCpt
[b_SSICpt
] =
661 pul_TurnCpt
[b_SSICpt
] =
662 pul_TurnCpt
[b_SSICpt
] &
668 printk("Read Type Inputs Wrong\n");
673 /***********************/
674 /* SSI not initialised */
675 /***********************/
677 DPRINTK("SSI not initialised\n");
681 /**********************************/
682 /* The module is not a SSI module */
683 /**********************************/
685 DPRINTK("The module is not a SSI module\n");
690 /***********************/
691 /* Module number error */
692 /***********************/
694 DPRINTK("Module number error\n");
698 return (i_ReturnValue
);
702 +----------------------------------------------------------------------------+
703 | Function Name : _INT_ i_APCI1710_ReadSSI1DigitalInput |
704 | (BYTE_ b_BoardHandle, |
705 | BYTE_ b_ModulNbr, |
706 | BYTE_ b_InputChannel, |
707 | PBYTE_ pb_ChannelStatus) |
708 +----------------------------------------------------------------------------+
710 (0) Set the digital output from selected SSI moule |
712 (1) Set the digital output from selected SSI moule |
714 (2)Read the status from selected SSI digital input |
716 (3)Read the status from all SSI digital inputs from |
717 | selected SSI module (b_ModulNbr) |
718 +----------------------------------------------------------------------------+
719 | Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710|
720 | BYTE_ b_ModulNbr CR_AREF : Module number to |
721 | configure (0 to 3) |
722 | BYTE_ b_InputChannel CR_CHAN : Selection from digital |
723 | data[0] which IOTYPE input ( 0 to 2) |
724 +----------------------------------------------------------------------------+
725 | Output Parameters : PBYTE_ pb_ChannelStatus : Digital input channel |
727 | 0 : Channle is not active|
728 | 1 : Channle is active |
729 +----------------------------------------------------------------------------+
730 | Return Value : 0: No error |
731 | -1: The handle parameter of the board is wrong |
732 | -2: The module parameter is wrong |
733 | -3: The module is not a SSI module |
734 | -4: The selected SSI digital input is wrong |
735 +----------------------------------------------------------------------------+
738 INT
i_APCI1710_InsnBitsSSIDigitalIO(comedi_device
* dev
, comedi_subdevice
* s
,
739 comedi_insn
* insn
, unsigned int * data
)
741 INT i_ReturnValue
= 0;
745 PBYTE pb_ChannelStatus
;
746 PBYTE pb_InputStatus
;
748 i_ReturnValue
= insn
->n
;
749 b_ModulNbr
= (BYTE
) CR_AREF(insn
->chanspec
);
750 b_IOType
= (BYTE
) data
[0];
752 /**************************/
753 /* Test the module number */
754 /**************************/
756 if (b_ModulNbr
< 4) {
757 /***********************/
758 /* Test if SSI counter */
759 /***********************/
761 if ((devpriv
->s_BoardInfos
.
762 dw_MolduleConfiguration
[b_ModulNbr
] &
763 0xFFFF0000UL
) == APCI1710_SSI_COUNTER
) {
765 case APCI1710_SSI_SET_CHANNELON
:
766 /*****************************/
767 /* Set the digital output ON */
768 /*****************************/
770 outl(1, devpriv
->s_BoardInfos
.ui_Address
+ 16 +
774 case APCI1710_SSI_SET_CHANNELOFF
:
775 /******************************/
776 /* Set the digital output OFF */
777 /******************************/
779 outl(0, devpriv
->s_BoardInfos
.ui_Address
+ 16 +
783 case APCI1710_SSI_READ_1CHANNEL
:
784 /******************************************/
785 /* Test the digital imnput channel number */
786 /******************************************/
788 b_InputChannel
= (BYTE
) CR_CHAN(insn
->chanspec
);
789 pb_ChannelStatus
= (PBYTE
) & data
[0];
791 if (b_InputChannel
<= 2) {
792 /**************************/
793 /* Read all digital input */
794 /**************************/
797 inl(devpriv
->s_BoardInfos
.
798 ui_Address
+ (64 * b_ModulNbr
));
800 (BYTE
) (((~dw_StatusReg
) >> (4 +
804 /********************************/
805 /* Selected digital input error */
806 /********************************/
808 DPRINTK("Selected digital input error\n");
813 case APCI1710_SSI_READ_ALLCHANNEL
:
814 /**************************/
815 /* Read all digital input */
816 /**************************/
817 pb_InputStatus
= (PBYTE
) & data
[0];
820 inl(devpriv
->s_BoardInfos
.ui_Address
+
823 (BYTE
) (((~dw_StatusReg
) >> 4) & 7);
827 printk("IO type wrong\n");
831 /**********************************/
832 /* The module is not a SSI module */
833 /**********************************/
835 DPRINTK("The module is not a SSI module\n");
839 /***********************/
840 /* Module number error */
841 /***********************/
843 DPRINTK("Module number error\n");
847 return (i_ReturnValue
);