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 | (unsigned char_ b_BoardHandle, |
69 | unsigned char_ b_ModulNbr, |
70 | unsigned char_ b_SSIProfile, |
71 | unsigned char_ b_PositionTurnLength, |
72 | unsigned char_ b_TurnCptLength, |
73 | unsigned char_ b_PCIInputClock, |
74 | ULONG_ ul_SSIOutputClock, |
75 | unsigned char_ 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 : unsigned char_ b_BoardHandle : Handle of board APCI-1710|
82 | unsigned char_ b_ModulNbr : Module number to |
83 | configure (0 to 3) |
84 | unsigned char_ b_SSIProfile : Selection from SSI |
85 | profile length (2 to 32).|
86 | unsigned char_ b_PositionTurnLength : Selection from SSI |
87 | position data length |
89 | unsigned char_ b_TurnCptLength : Selection from SSI turn |
90 | counter data length |
92 | unsigned char 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 | unsigned char 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 = (unsigned char) data[0];
115 b_PositionTurnLength= (unsigned char) data[1];
116 b_TurnCptLength = (unsigned char) data[2];
117 b_PCIInputClock = (unsigned char) data[3];
118 ul_SSIOutputClock = (unsigned int) data[4];
119 b_SSICountingMode = (unsigned char) 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(struct comedi_device *dev, struct comedi_subdevice *s,
137 struct comedi_insn *insn, unsigned int *data)
139 int i_ReturnValue = 0;
140 unsigned int ui_TimerValue;
141 unsigned char b_ModulNbr, b_SSIProfile, b_PositionTurnLength, b_TurnCptLength,
142 b_PCIInputClock, b_SSICountingMode;
143 unsigned int ul_SSIOutputClock;
145 b_ModulNbr = CR_AREF(insn->chanspec);
146 b_SSIProfile = (unsigned char) data[0];
147 b_PositionTurnLength = (unsigned char) data[1];
148 b_TurnCptLength = (unsigned char) data[2];
149 b_PCIInputClock = (unsigned char) data[3];
150 ul_SSIOutputClock = (unsigned int) data[4];
151 b_SSICountingMode = (unsigned char) 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 ((unsigned int) (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 | (unsigned char_ b_BoardHandle, |
361 | unsigned char_ b_ModulNbr, |
362 | unsigned char_ b_SelectedSSI, |
363 | PULONG_ pul_Position, |
364 | PULONG_ pul_TurnCpt)
365 int i_APCI1710_ReadSSIValue(struct comedi_device *dev,struct comedi_subdevice *s,
366 struct 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 : unsigned char_ b_BoardHandle : Handle of board APCI-1710|
377 | unsigned char_ b_ModulNbr : Module number to |
378 | configure (0 to 3) |
379 | unsigned char_ b_SelectedSSI : Selection from SSI |
382 b_ModulNbr = (unsigned char) CR_AREF(insn->chanspec);
383 b_SelectedSSI = (unsigned char) CR_CHAN(insn->chanspec); (in case of single ssi)
384 b_ReadType = (unsigned char) 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 = (unsigned int *) &data[0];
391 pul_TurnCpt = (unsigned int *) &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(struct comedi_device *dev, struct comedi_subdevice *s,
404 struct comedi_insn *insn, unsigned int *data)
406 int i_ReturnValue = 0;
408 unsigned char b_Length;
409 unsigned char b_Schift;
410 unsigned char b_SSICpt;
412 unsigned int dw_And1;
413 unsigned int dw_And2;
414 unsigned int dw_StatusReg;
415 unsigned int dw_CounterValue;
416 unsigned char b_ModulNbr;
417 unsigned char b_SelectedSSI;
418 unsigned char b_ReadType;
419 unsigned int *pul_Position;
420 unsigned int *pul_TurnCpt;
421 unsigned int *pul_Position1;
422 unsigned int *pul_TurnCpt1;
424 i_ReturnValue = insn->n;
425 pul_Position1 = (unsigned int *) &data[0];
427 pul_TurnCpt1 = (unsigned int *) &data[1];
429 pul_Position = (unsigned int *) &data[0]; /* 0-2 */
430 pul_TurnCpt = (unsigned int *) &data[3]; /* 3-5 */
431 b_ModulNbr = (unsigned char) CR_AREF(insn->chanspec);
432 b_SelectedSSI = (unsigned char) CR_CHAN(insn->chanspec);
433 b_ReadType = (unsigned char) 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 /*******************/
480 } while ((dw_StatusReg & 0x1)
483 /******************************/
484 /* Read the SSI counter value */
485 /******************************/
491 (b_SelectedSSI * 4) +
501 if ((b_Length * 2) !=
516 b_PositionTurnLength;
530 b_PositionTurnLength;
560 /*****************************/
561 /* The selected SSI is wrong */
562 /*****************************/
564 DPRINTK("The selected SSI is wrong\n");
569 case APCI1710_SSI_READALLVALUE:
575 s_ModuleInfo[b_ModulNbr].
577 b_PositionTurnLength; b_Cpt++) {
578 dw_And1 = dw_And1 * 2;
586 s_ModuleInfo[b_ModulNbr].
588 b_TurnCptLength; b_Cpt++) {
589 dw_And2 = dw_And2 * 2;
592 /************************/
593 /* Start the conversion */
594 /************************/
596 outl(0, devpriv->s_BoardInfos.
601 /*******************/
602 /* Read the status */
603 /*******************/
610 } while ((dw_StatusReg & 0x1) != 0);
612 for (b_SSICpt = 0; b_SSICpt < 3;
614 /******************************/
615 /* Read the SSI counter value */
616 /******************************/
632 if ((b_Length * 2) !=
647 b_PositionTurnLength;
649 pul_Position[b_SSICpt] =
652 pul_Position[b_SSICpt] =
653 pul_Position[b_SSICpt] &
656 pul_TurnCpt[b_SSICpt] =
659 pul_TurnCpt[b_SSICpt] =
660 pul_TurnCpt[b_SSICpt] &
666 printk("Read Type Inputs Wrong\n");
668 } /* switch ending */
671 /***********************/
672 /* SSI not initialised */
673 /***********************/
675 DPRINTK("SSI not initialised\n");
679 /**********************************/
680 /* The module is not a SSI module */
681 /**********************************/
683 DPRINTK("The module is not a SSI module\n");
688 /***********************/
689 /* Module number error */
690 /***********************/
692 DPRINTK("Module number error\n");
696 return i_ReturnValue;
700 +----------------------------------------------------------------------------+
701 | Function Name : _INT_ i_APCI1710_ReadSSI1DigitalInput |
702 | (unsigned char_ b_BoardHandle, |
703 | unsigned char_ b_ModulNbr, |
704 | unsigned char_ b_InputChannel, |
705 | unsigned char *_ pb_ChannelStatus) |
706 +----------------------------------------------------------------------------+
708 (0) Set the digital output from selected SSI moule |
710 (1) Set the digital output from selected SSI moule |
712 (2)Read the status from selected SSI digital input |
714 (3)Read the status from all SSI digital inputs from |
715 | selected SSI module (b_ModulNbr) |
716 +----------------------------------------------------------------------------+
717 | Input Parameters : unsigned char_ b_BoardHandle : Handle of board APCI-1710|
718 | unsigned char_ b_ModulNbr CR_AREF : Module number to |
719 | configure (0 to 3) |
720 | unsigned char_ b_InputChannel CR_CHAN : Selection from digital |
721 | data[0] which IOTYPE input ( 0 to 2) |
722 +----------------------------------------------------------------------------+
723 | Output Parameters : unsigned char *_ pb_ChannelStatus : Digital input channel |
725 | 0 : Channle is not active|
726 | 1 : Channle is active |
727 +----------------------------------------------------------------------------+
728 | Return Value : 0: No error |
729 | -1: The handle parameter of the board is wrong |
730 | -2: The module parameter is wrong |
731 | -3: The module is not a SSI module |
732 | -4: The selected SSI digital input is wrong |
733 +----------------------------------------------------------------------------+
736 int i_APCI1710_InsnBitsSSIDigitalIO(struct comedi_device *dev, struct comedi_subdevice *s,
737 struct comedi_insn *insn, unsigned int *data)
739 int i_ReturnValue = 0;
740 unsigned int dw_StatusReg;
741 unsigned char b_ModulNbr;
742 unsigned char b_InputChannel;
743 unsigned char *pb_ChannelStatus;
744 unsigned char *pb_InputStatus;
745 unsigned char b_IOType;
746 i_ReturnValue = insn->n;
747 b_ModulNbr = (unsigned char) CR_AREF(insn->chanspec);
748 b_IOType = (unsigned char) data[0];
750 /**************************/
751 /* Test the module number */
752 /**************************/
754 if (b_ModulNbr < 4) {
755 /***********************/
756 /* Test if SSI counter */
757 /***********************/
759 if ((devpriv->s_BoardInfos.
760 dw_MolduleConfiguration[b_ModulNbr] &
761 0xFFFF0000UL) == APCI1710_SSI_COUNTER) {
763 case APCI1710_SSI_SET_CHANNELON:
764 /*****************************/
765 /* Set the digital output ON */
766 /*****************************/
768 outl(1, devpriv->s_BoardInfos.ui_Address + 16 +
772 case APCI1710_SSI_SET_CHANNELOFF:
773 /******************************/
774 /* Set the digital output OFF */
775 /******************************/
777 outl(0, devpriv->s_BoardInfos.ui_Address + 16 +
781 case APCI1710_SSI_READ_1CHANNEL:
782 /******************************************/
783 /* Test the digital imnput channel number */
784 /******************************************/
786 b_InputChannel = (unsigned char) CR_CHAN(insn->chanspec);
787 pb_ChannelStatus = (unsigned char *) &data[0];
789 if (b_InputChannel <= 2) {
790 /**************************/
791 /* Read all digital input */
792 /**************************/
795 inl(devpriv->s_BoardInfos.
796 ui_Address + (64 * b_ModulNbr));
798 (unsigned char) (((~dw_StatusReg) >> (4 +
802 /********************************/
803 /* Selected digital input error */
804 /********************************/
806 DPRINTK("Selected digital input error\n");
811 case APCI1710_SSI_READ_ALLCHANNEL:
812 /**************************/
813 /* Read all digital input */
814 /**************************/
815 pb_InputStatus = (unsigned char *) &data[0];
818 inl(devpriv->s_BoardInfos.ui_Address +
821 (unsigned char) (((~dw_StatusReg) >> 4) & 7);
825 printk("IO type wrong\n");
829 /**********************************/
830 /* The module is not a SSI module */
831 /**********************************/
833 DPRINTK("The module is not a SSI module\n");
837 /***********************/
838 /* Module number error */
839 /***********************/
841 DPRINTK("Module number error\n");
845 return i_ReturnValue;