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 should 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 |
38 +-----------------------------------------------------------------------+
39 | several changes done by S. Weber in 1998 and C. Guinot in 2000 |
40 +-----------------------------------------------------------------------+
43 #define APCI1710_30MHZ 30
44 #define APCI1710_33MHZ 33
45 #define APCI1710_40MHZ 40
47 #define APCI1710_BINARY_MODE 0x1
48 #define APCI1710_GRAY_MODE 0x0
50 #define APCI1710_SSI_READ1VALUE 1
51 #define APCI1710_SSI_READALLVALUE 2
53 #define APCI1710_SSI_SET_CHANNELON 0
54 #define APCI1710_SSI_SET_CHANNELOFF 1
55 #define APCI1710_SSI_READ_1CHANNEL 2
56 #define APCI1710_SSI_READ_ALLCHANNEL 3
59 +----------------------------------------------------------------------------+
60 | Function Name : _INT_ i_APCI1710_InitSSI |
61 | (unsigned char_ b_BoardHandle, |
62 | unsigned char_ b_ModulNbr, |
63 | unsigned char_ b_SSIProfile, |
64 | unsigned char_ b_PositionTurnLength, |
65 | unsigned char_ b_TurnCptLength, |
66 | unsigned char_ b_PCIInputClock, |
67 | ULONG_ ul_SSIOutputClock, |
68 | unsigned char_ b_SSICountingMode) |
69 +----------------------------------------------------------------------------+
70 | Task : Configure the SSI operating mode from selected module |
71 | (b_ModulNbr). You must calling this function be for you|
72 | call any other function witch access of SSI. |
73 +----------------------------------------------------------------------------+
74 | Input Parameters : unsigned char_ b_BoardHandle : Handle of board APCI-1710|
75 | unsigned char_ b_ModulNbr : Module number to |
76 | configure (0 to 3) |
77 | unsigned char_ b_SSIProfile : Selection from SSI |
78 | profile length (2 to 32).|
79 | unsigned char_ b_PositionTurnLength : Selection from SSI |
80 | position data length |
82 | unsigned char_ b_TurnCptLength : Selection from SSI turn |
83 | counter data length |
85 | unsigned char b_PCIInputClock : Selection from PCI bus |
87 | - APCI1710_30MHZ : |
88 | The PC have a PCI bus |
90 | - APCI1710_33MHZ : |
91 | The PC have a PCI bus |
93 | ULONG_ ul_SSIOutputClock : Selection from SSI output|
95 | From 229 to 5 000 000 Hz|
96 | for 30 MHz selection. |
97 | From 252 to 5 000 000 Hz|
98 | for 33 MHz selection. |
99 | unsigned char b_SSICountingMode : SSI counting mode |
101 | - APCI1710_BINARY_MODE : |
102 | Binary counting mode. |
103 | - APCI1710_GRAY_MODE : |
104 | Gray counting mode.
106 b_ModulNbr = CR_AREF(insn->chanspec);
107 b_SSIProfile = (unsigned char) data[0];
108 b_PositionTurnLength= (unsigned char) data[1];
109 b_TurnCptLength = (unsigned char) data[2];
110 b_PCIInputClock = (unsigned char) data[3];
111 ul_SSIOutputClock = (unsigned int) data[4];
112 b_SSICountingMode = (unsigned char) data[5]; |
113 +----------------------------------------------------------------------------+
114 | Output Parameters : - |
115 +----------------------------------------------------------------------------+
116 | Return Value : 0: No error |
117 | -1: The handle parameter of the board is wrong |
118 | -2: The module parameter is wrong |
119 | -3: The module is not a SSI module |
120 | -4: The selected SSI profile length is wrong |
121 | -5: The selected SSI position data length is wrong |
122 | -6: The selected SSI turn counter data length is wrong |
123 | -7: The selected PCI input clock is wrong |
124 | -8: The selected SSI output clock is wrong |
125 | -9: The selected SSI counting mode parameter is wrong |
126 +----------------------------------------------------------------------------+
129 static int i_APCI1710_InsnConfigInitSSI(struct comedi_device *dev,
130 struct comedi_subdevice *s,
131 struct comedi_insn *insn,
134 struct addi_private *devpriv = dev->private;
135 int i_ReturnValue = 0;
136 unsigned int ui_TimerValue;
137 unsigned char b_ModulNbr, b_SSIProfile, b_PositionTurnLength, b_TurnCptLength,
138 b_PCIInputClock, b_SSICountingMode;
139 unsigned int ul_SSIOutputClock;
141 b_ModulNbr = CR_AREF(insn->chanspec);
142 b_SSIProfile = (unsigned char) data[0];
143 b_PositionTurnLength = (unsigned char) data[1];
144 b_TurnCptLength = (unsigned char) data[2];
145 b_PCIInputClock = (unsigned char) data[3];
146 ul_SSIOutputClock = (unsigned int) data[4];
147 b_SSICountingMode = (unsigned char) data[5];
149 i_ReturnValue = insn->n;
150 /**************************/
151 /* Test the module number */
152 /**************************/
154 if (b_ModulNbr < 4) {
155 /***********************/
156 /* Test if SSI counter */
157 /***********************/
159 if ((devpriv->s_BoardInfos.
160 dw_MolduleConfiguration[b_ModulNbr] &
161 0xFFFF0000UL) == APCI1710_SSI_COUNTER) {
162 /*******************************/
163 /* Test the SSI profile length */
164 /*******************************/
166 /* CG 22/03/00 b_SSIProfile >= 2 anstatt b_SSIProfile > 2 */
167 if (b_SSIProfile >= 2 && b_SSIProfile < 33) {
168 /*************************************/
169 /* Test the SSI position data length */
170 /*************************************/
172 if (b_PositionTurnLength > 0
173 && b_PositionTurnLength < 32) {
174 /*****************************************/
175 /* Test the SSI turn counter data length */
176 /*****************************************/
178 if (b_TurnCptLength > 0
179 && b_TurnCptLength < 32) {
180 /***************************/
181 /* Test the profile length */
182 /***************************/
184 if ((b_TurnCptLength +
185 b_PositionTurnLength)
187 /****************************/
188 /* Test the PCI input clock */
189 /****************************/
191 if (b_PCIInputClock ==
198 /*************************/
199 /* Test the output clock */
200 /*************************/
202 if ((b_PCIInputClock == APCI1710_30MHZ && (ul_SSIOutputClock > 228 && ul_SSIOutputClock <= 5000000UL)) || (b_PCIInputClock == APCI1710_33MHZ && (ul_SSIOutputClock > 251 && ul_SSIOutputClock <= 5000000UL))) {
203 if (b_SSICountingMode == APCI1710_BINARY_MODE || b_SSICountingMode == APCI1710_GRAY_MODE) {
204 /**********************/
205 /* Save configuration */
206 /**********************/
221 b_PositionTurnLength;
231 /*********************************/
232 /* Initialise the profile length */
233 /*********************************/
235 if (b_SSICountingMode == APCI1710_BINARY_MODE) {
237 outl(b_SSIProfile + 1, devpriv->s_BoardInfos.ui_Address + 4 + (64 * b_ModulNbr));
240 outl(b_SSIProfile, devpriv->s_BoardInfos.ui_Address + 4 + (64 * b_ModulNbr));
243 /******************************/
244 /* Calculate the output clock */
245 /******************************/
251 ((unsigned int) (b_PCIInputClock) * 500000UL) / ul_SSIOutputClock);
253 /************************/
254 /* Initialise the timer */
255 /************************/
257 outl(ui_TimerValue, devpriv->s_BoardInfos.ui_Address + (64 * b_ModulNbr));
259 /********************************/
260 /* Initialise the counting mode */
261 /********************************/
263 outl(7 * b_SSICountingMode, devpriv->s_BoardInfos.ui_Address + 12 + (64 * b_ModulNbr));
273 /*****************************************************/
274 /* The selected SSI counting mode parameter is wrong */
275 /*****************************************************/
277 DPRINTK("The selected SSI counting mode parameter is wrong\n");
283 /******************************************/
284 /* The selected SSI output clock is wrong */
285 /******************************************/
287 DPRINTK("The selected SSI output clock is wrong\n");
293 /*****************************************/
294 /* The selected PCI input clock is wrong */
295 /*****************************************/
297 DPRINTK("The selected PCI input clock is wrong\n");
302 /********************************************/
303 /* The selected SSI profile length is wrong */
304 /********************************************/
306 DPRINTK("The selected SSI profile length is wrong\n");
310 /******************************************************/
311 /* The selected SSI turn counter data length is wrong */
312 /******************************************************/
314 DPRINTK("The selected SSI turn counter data length is wrong\n");
318 /**************************************************/
319 /* The selected SSI position data length is wrong */
320 /**************************************************/
322 DPRINTK("The selected SSI position data length is wrong\n");
326 /********************************************/
327 /* The selected SSI profile length is wrong */
328 /********************************************/
330 DPRINTK("The selected SSI profile length is wrong\n");
334 /**********************************/
335 /* The module is not a SSI module */
336 /**********************************/
338 DPRINTK("The module is not a SSI module\n");
342 /***********************/
343 /* Module number error */
344 /***********************/
346 DPRINTK("Module number error\n");
350 return i_ReturnValue;
354 +----------------------------------------------------------------------------+
355 | Function Name : _INT_ i_APCI1710_Read1SSIValue |
356 | (unsigned char_ b_BoardHandle, |
357 | unsigned char_ b_ModulNbr, |
358 | unsigned char_ b_SelectedSSI, |
359 | PULONG_ pul_Position, |
360 | PULONG_ pul_TurnCpt)
361 int i_APCI1710_ReadSSIValue(struct comedi_device *dev,struct comedi_subdevice *s,
362 struct comedi_insn *insn,unsigned int *data) |
363 +----------------------------------------------------------------------------+
367 Read the selected SSI counter (b_SelectedSSI) from |
368 | selected module (b_ModulNbr).
369 or Read all SSI counter (b_SelectedSSI) from |
370 | selected module (b_ModulNbr). |
371 +----------------------------------------------------------------------------+
372 | Input Parameters : unsigned char_ b_BoardHandle : Handle of board APCI-1710|
373 | unsigned char_ b_ModulNbr : Module number to |
374 | configure (0 to 3) |
375 | unsigned char_ b_SelectedSSI : Selection from SSI |
378 b_ModulNbr = (unsigned char) CR_AREF(insn->chanspec);
379 b_SelectedSSI = (unsigned char) CR_CHAN(insn->chanspec); (in case of single ssi)
380 b_ReadType = (unsigned char) CR_RANGE(insn->chanspec);
382 +----------------------------------------------------------------------------+
383 | Output Parameters : PULONG_ pul_Position : SSI position in the turn |
384 | PULONG_ pul_TurnCpt : Number of turns
386 pul_Position = (unsigned int *) &data[0];
387 pul_TurnCpt = (unsigned int *) &data[1]; |
388 +----------------------------------------------------------------------------+
389 | Return Value : 0: No error |
390 | -1: The handle parameter of the board is wrong |
391 | -2: The module parameter is wrong |
392 | -3: The module is not a SSI module |
393 | -4: SSI not initialised see function |
394 | "i_APCI1710_InitSSI" |
395 | -5: The selected SSI is wrong |
396 +----------------------------------------------------------------------------+
399 static int i_APCI1710_InsnReadSSIValue(struct comedi_device *dev,
400 struct comedi_subdevice *s,
401 struct comedi_insn *insn,
404 struct addi_private *devpriv = dev->private;
405 int i_ReturnValue = 0;
407 unsigned char b_Length;
408 unsigned char b_Schift;
409 unsigned char b_SSICpt;
411 unsigned int dw_And1;
412 unsigned int dw_And2;
413 unsigned int dw_StatusReg;
414 unsigned int dw_CounterValue;
415 unsigned char b_ModulNbr;
416 unsigned char b_SelectedSSI;
417 unsigned char b_ReadType;
418 unsigned int *pul_Position;
419 unsigned int *pul_TurnCpt;
420 unsigned int *pul_Position1;
421 unsigned int *pul_TurnCpt1;
423 i_ReturnValue = insn->n;
424 pul_Position1 = (unsigned int *) &data[0];
426 pul_TurnCpt1 = (unsigned int *) &data[1];
428 pul_Position = (unsigned int *) &data[0]; /* 0-2 */
429 pul_TurnCpt = (unsigned int *) &data[3]; /* 3-5 */
430 b_ModulNbr = (unsigned char) CR_AREF(insn->chanspec);
431 b_SelectedSSI = (unsigned char) CR_CHAN(insn->chanspec);
432 b_ReadType = (unsigned char) CR_RANGE(insn->chanspec);
434 /**************************/
435 /* Test the module number */
436 /**************************/
438 if (b_ModulNbr < 4) {
439 /***********************/
440 /* Test if SSI counter */
441 /***********************/
443 if ((devpriv->s_BoardInfos.
444 dw_MolduleConfiguration[b_ModulNbr] &
445 0xFFFF0000UL) == APCI1710_SSI_COUNTER) {
446 /***************************/
447 /* Test if SSI initialised */
448 /***************************/
450 if (devpriv->s_ModuleInfo[b_ModulNbr].
451 s_SSICounterInfo.b_SSIInit == 1) {
453 switch (b_ReadType) {
455 case APCI1710_SSI_READ1VALUE:
456 /****************************************/
457 /* Test the selected SSI counter number */
458 /****************************************/
460 if (b_SelectedSSI < 3) {
461 /************************/
462 /* Start the conversion */
463 /************************/
465 outl(0, devpriv->s_BoardInfos.
470 /*******************/
471 /* Read the status */
472 /*******************/
479 } while ((dw_StatusReg & 0x1)
482 /******************************/
483 /* Read the SSI counter value */
484 /******************************/
490 (b_SelectedSSI * 4) +
500 if ((b_Length * 2) !=
515 b_PositionTurnLength;
529 b_PositionTurnLength;
559 /*****************************/
560 /* The selected SSI is wrong */
561 /*****************************/
563 DPRINTK("The selected SSI is wrong\n");
568 case APCI1710_SSI_READALLVALUE:
574 s_ModuleInfo[b_ModulNbr].
576 b_PositionTurnLength; b_Cpt++) {
577 dw_And1 = dw_And1 * 2;
585 s_ModuleInfo[b_ModulNbr].
587 b_TurnCptLength; b_Cpt++) {
588 dw_And2 = dw_And2 * 2;
591 /************************/
592 /* Start the conversion */
593 /************************/
595 outl(0, devpriv->s_BoardInfos.
600 /*******************/
601 /* Read the status */
602 /*******************/
609 } while ((dw_StatusReg & 0x1) != 0);
611 for (b_SSICpt = 0; b_SSICpt < 3;
613 /******************************/
614 /* Read the SSI counter value */
615 /******************************/
631 if ((b_Length * 2) !=
646 b_PositionTurnLength;
648 pul_Position[b_SSICpt] =
651 pul_Position[b_SSICpt] =
652 pul_Position[b_SSICpt] &
655 pul_TurnCpt[b_SSICpt] =
658 pul_TurnCpt[b_SSICpt] =
659 pul_TurnCpt[b_SSICpt] &
665 printk("Read Type Inputs Wrong\n");
667 } /* switch ending */
670 /***********************/
671 /* SSI not initialised */
672 /***********************/
674 DPRINTK("SSI not initialised\n");
678 /**********************************/
679 /* The module is not a SSI module */
680 /**********************************/
682 DPRINTK("The module is not a SSI module\n");
687 /***********************/
688 /* Module number error */
689 /***********************/
691 DPRINTK("Module number error\n");
695 return i_ReturnValue;
699 +----------------------------------------------------------------------------+
700 | Function Name : _INT_ i_APCI1710_ReadSSI1DigitalInput |
701 | (unsigned char_ b_BoardHandle, |
702 | unsigned char_ b_ModulNbr, |
703 | unsigned char_ b_InputChannel, |
704 | unsigned char *_ pb_ChannelStatus) |
705 +----------------------------------------------------------------------------+
707 (0) Set the digital output from selected SSI module |
709 (1) Set the digital output from selected SSI module |
711 (2)Read the status from selected SSI digital input |
713 (3)Read the status from all SSI digital inputs from |
714 | selected SSI module (b_ModulNbr) |
715 +----------------------------------------------------------------------------+
716 | Input Parameters : unsigned char_ b_BoardHandle : Handle of board APCI-1710|
717 | unsigned char_ b_ModulNbr CR_AREF : Module number to |
718 | configure (0 to 3) |
719 | unsigned char_ b_InputChannel CR_CHAN : Selection from digital |
720 | data[0] which IOTYPE input ( 0 to 2) |
721 +----------------------------------------------------------------------------+
722 | Output Parameters : unsigned char *_ pb_ChannelStatus : Digital input channel |
724 | 0 : Channle is not active|
725 | 1 : Channle is active |
726 +----------------------------------------------------------------------------+
727 | Return Value : 0: No error |
728 | -1: The handle parameter of the board is wrong |
729 | -2: The module parameter is wrong |
730 | -3: The module is not a SSI module |
731 | -4: The selected SSI digital input is wrong |
732 +----------------------------------------------------------------------------+
735 static int i_APCI1710_InsnBitsSSIDigitalIO(struct comedi_device *dev,
736 struct comedi_subdevice *s,
737 struct comedi_insn *insn,
740 struct addi_private *devpriv = dev->private;
741 int i_ReturnValue = 0;
742 unsigned int dw_StatusReg;
743 unsigned char b_ModulNbr;
744 unsigned char b_InputChannel;
745 unsigned char *pb_ChannelStatus;
746 unsigned char *pb_InputStatus;
747 unsigned char b_IOType;
749 i_ReturnValue = insn->n;
750 b_ModulNbr = (unsigned char) CR_AREF(insn->chanspec);
751 b_IOType = (unsigned char) data[0];
753 /**************************/
754 /* Test the module number */
755 /**************************/
757 if (b_ModulNbr < 4) {
758 /***********************/
759 /* Test if SSI counter */
760 /***********************/
762 if ((devpriv->s_BoardInfos.
763 dw_MolduleConfiguration[b_ModulNbr] &
764 0xFFFF0000UL) == APCI1710_SSI_COUNTER) {
766 case APCI1710_SSI_SET_CHANNELON:
767 /*****************************/
768 /* Set the digital output ON */
769 /*****************************/
771 outl(1, devpriv->s_BoardInfos.ui_Address + 16 +
775 case APCI1710_SSI_SET_CHANNELOFF:
776 /******************************/
777 /* Set the digital output OFF */
778 /******************************/
780 outl(0, devpriv->s_BoardInfos.ui_Address + 16 +
784 case APCI1710_SSI_READ_1CHANNEL:
785 /******************************************/
786 /* Test the digital imnput channel number */
787 /******************************************/
789 b_InputChannel = (unsigned char) CR_CHAN(insn->chanspec);
790 pb_ChannelStatus = (unsigned char *) &data[0];
792 if (b_InputChannel <= 2) {
793 /**************************/
794 /* Read all digital input */
795 /**************************/
798 inl(devpriv->s_BoardInfos.
799 ui_Address + (64 * b_ModulNbr));
801 (unsigned char) (((~dw_StatusReg) >> (4 +
805 /********************************/
806 /* Selected digital input error */
807 /********************************/
809 DPRINTK("Selected digital input error\n");
814 case APCI1710_SSI_READ_ALLCHANNEL:
815 /**************************/
816 /* Read all digital input */
817 /**************************/
818 pb_InputStatus = (unsigned char *) &data[0];
821 inl(devpriv->s_BoardInfos.ui_Address +
824 (unsigned char) (((~dw_StatusReg) >> 4) & 7);
828 printk("IO type wrong\n");
832 /**********************************/
833 /* The module is not a SSI module */
834 /**********************************/
836 DPRINTK("The module is not a SSI module\n");
840 /***********************/
841 /* Module number error */
842 /***********************/
844 DPRINTK("Module number error\n");
848 return i_ReturnValue;