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 +-----------------------------------------------------------------------+
44 +----------------------------------------------------------------------------+
46 +----------------------------------------------------------------------------+
49 #include "APCI1710_Ssi.h"
52 +----------------------------------------------------------------------------+
53 | Function Name : _INT_ i_APCI1710_InitSSI |
54 | (unsigned char_ b_BoardHandle, |
55 | unsigned char_ b_ModulNbr, |
56 | unsigned char_ b_SSIProfile, |
57 | unsigned char_ b_PositionTurnLength, |
58 | unsigned char_ b_TurnCptLength, |
59 | unsigned char_ b_PCIInputClock, |
60 | ULONG_ ul_SSIOutputClock, |
61 | unsigned char_ b_SSICountingMode) |
62 +----------------------------------------------------------------------------+
63 | Task : Configure the SSI operating mode from selected module |
64 | (b_ModulNbr). You must calling this function be for you|
65 | call any other function witch access of SSI. |
66 +----------------------------------------------------------------------------+
67 | Input Parameters : unsigned char_ b_BoardHandle : Handle of board APCI-1710|
68 | unsigned char_ b_ModulNbr : Module number to |
69 | configure (0 to 3) |
70 | unsigned char_ b_SSIProfile : Selection from SSI |
71 | profile length (2 to 32).|
72 | unsigned char_ b_PositionTurnLength : Selection from SSI |
73 | position data length |
75 | unsigned char_ b_TurnCptLength : Selection from SSI turn |
76 | counter data length |
78 | unsigned char b_PCIInputClock : Selection from PCI bus |
80 | - APCI1710_30MHZ : |
81 | The PC have a PCI bus |
83 | - APCI1710_33MHZ : |
84 | The PC have a PCI bus |
86 | ULONG_ ul_SSIOutputClock : Selection from SSI output|
88 | From 229 to 5 000 000 Hz|
89 | for 30 MHz selection. |
90 | From 252 to 5 000 000 Hz|
91 | for 33 MHz selection. |
92 | unsigned char b_SSICountingMode : SSI counting mode |
94 | - APCI1710_BINARY_MODE : |
95 | Binary counting mode. |
96 | - APCI1710_GRAY_MODE : |
99 b_ModulNbr = CR_AREF(insn->chanspec);
100 b_SSIProfile = (unsigned char) data[0];
101 b_PositionTurnLength= (unsigned char) data[1];
102 b_TurnCptLength = (unsigned char) data[2];
103 b_PCIInputClock = (unsigned char) data[3];
104 ul_SSIOutputClock = (unsigned int) data[4];
105 b_SSICountingMode = (unsigned char) data[5]; |
106 +----------------------------------------------------------------------------+
107 | Output Parameters : - |
108 +----------------------------------------------------------------------------+
109 | Return Value : 0: No error |
110 | -1: The handle parameter of the board is wrong |
111 | -2: The module parameter is wrong |
112 | -3: The module is not a SSI module |
113 | -4: The selected SSI profile length is wrong |
114 | -5: The selected SSI position data length is wrong |
115 | -6: The selected SSI turn counter data length is wrong |
116 | -7: The selected PCI input clock is wrong |
117 | -8: The selected SSI output clock is wrong |
118 | -9: The selected SSI counting mode parameter is wrong |
119 +----------------------------------------------------------------------------+
122 int i_APCI1710_InsnConfigInitSSI(struct comedi_device *dev, struct comedi_subdevice *s,
123 struct comedi_insn *insn, unsigned int *data)
125 int i_ReturnValue = 0;
126 unsigned int ui_TimerValue;
127 unsigned char b_ModulNbr, b_SSIProfile, b_PositionTurnLength, b_TurnCptLength,
128 b_PCIInputClock, b_SSICountingMode;
129 unsigned int ul_SSIOutputClock;
131 b_ModulNbr = CR_AREF(insn->chanspec);
132 b_SSIProfile = (unsigned char) data[0];
133 b_PositionTurnLength = (unsigned char) data[1];
134 b_TurnCptLength = (unsigned char) data[2];
135 b_PCIInputClock = (unsigned char) data[3];
136 ul_SSIOutputClock = (unsigned int) data[4];
137 b_SSICountingMode = (unsigned char) data[5];
139 i_ReturnValue = insn->n;
140 /**************************/
141 /* Test the module number */
142 /**************************/
144 if (b_ModulNbr < 4) {
145 /***********************/
146 /* Test if SSI counter */
147 /***********************/
149 if ((devpriv->s_BoardInfos.
150 dw_MolduleConfiguration[b_ModulNbr] &
151 0xFFFF0000UL) == APCI1710_SSI_COUNTER) {
152 /*******************************/
153 /* Test the SSI profile length */
154 /*******************************/
156 /* CG 22/03/00 b_SSIProfile >= 2 anstatt b_SSIProfile > 2 */
157 if (b_SSIProfile >= 2 && b_SSIProfile < 33) {
158 /*************************************/
159 /* Test the SSI position data length */
160 /*************************************/
162 if (b_PositionTurnLength > 0
163 && b_PositionTurnLength < 32) {
164 /*****************************************/
165 /* Test the SSI turn counter data length */
166 /*****************************************/
168 if (b_TurnCptLength > 0
169 && b_TurnCptLength < 32) {
170 /***************************/
171 /* Test the profile length */
172 /***************************/
174 if ((b_TurnCptLength +
175 b_PositionTurnLength)
177 /****************************/
178 /* Test the PCI input clock */
179 /****************************/
181 if (b_PCIInputClock ==
188 /*************************/
189 /* Test the output clock */
190 /*************************/
192 if ((b_PCIInputClock == APCI1710_30MHZ && (ul_SSIOutputClock > 228 && ul_SSIOutputClock <= 5000000UL)) || (b_PCIInputClock == APCI1710_33MHZ && (ul_SSIOutputClock > 251 && ul_SSIOutputClock <= 5000000UL))) {
193 if (b_SSICountingMode == APCI1710_BINARY_MODE || b_SSICountingMode == APCI1710_GRAY_MODE) {
194 /**********************/
195 /* Save configuration */
196 /**********************/
211 b_PositionTurnLength;
221 /*********************************/
222 /* Initialise the profile length */
223 /*********************************/
225 if (b_SSICountingMode == APCI1710_BINARY_MODE) {
227 outl(b_SSIProfile + 1, devpriv->s_BoardInfos.ui_Address + 4 + (64 * b_ModulNbr));
230 outl(b_SSIProfile, devpriv->s_BoardInfos.ui_Address + 4 + (64 * b_ModulNbr));
233 /******************************/
234 /* Calculate the output clock */
235 /******************************/
241 ((unsigned int) (b_PCIInputClock) * 500000UL) / ul_SSIOutputClock);
243 /************************/
244 /* Initialise the timer */
245 /************************/
247 outl(ui_TimerValue, devpriv->s_BoardInfos.ui_Address + (64 * b_ModulNbr));
249 /********************************/
250 /* Initialise the counting mode */
251 /********************************/
253 outl(7 * b_SSICountingMode, devpriv->s_BoardInfos.ui_Address + 12 + (64 * b_ModulNbr));
263 /*****************************************************/
264 /* The selected SSI counting mode parameter is wrong */
265 /*****************************************************/
267 DPRINTK("The selected SSI counting mode parameter is wrong\n");
273 /******************************************/
274 /* The selected SSI output clock is wrong */
275 /******************************************/
277 DPRINTK("The selected SSI output clock is wrong\n");
283 /*****************************************/
284 /* The selected PCI input clock is wrong */
285 /*****************************************/
287 DPRINTK("The selected PCI input clock is wrong\n");
292 /********************************************/
293 /* The selected SSI profile length is wrong */
294 /********************************************/
296 DPRINTK("The selected SSI profile length is wrong\n");
300 /******************************************************/
301 /* The selected SSI turn counter data length is wrong */
302 /******************************************************/
304 DPRINTK("The selected SSI turn counter data length is wrong\n");
308 /**************************************************/
309 /* The selected SSI position data length is wrong */
310 /**************************************************/
312 DPRINTK("The selected SSI position data length is wrong\n");
316 /********************************************/
317 /* The selected SSI profile length is wrong */
318 /********************************************/
320 DPRINTK("The selected SSI profile length is wrong\n");
324 /**********************************/
325 /* The module is not a SSI module */
326 /**********************************/
328 DPRINTK("The module is not a SSI module\n");
332 /***********************/
333 /* Module number error */
334 /***********************/
336 DPRINTK("Module number error\n");
340 return i_ReturnValue;
344 +----------------------------------------------------------------------------+
345 | Function Name : _INT_ i_APCI1710_Read1SSIValue |
346 | (unsigned char_ b_BoardHandle, |
347 | unsigned char_ b_ModulNbr, |
348 | unsigned char_ b_SelectedSSI, |
349 | PULONG_ pul_Position, |
350 | PULONG_ pul_TurnCpt)
351 int i_APCI1710_ReadSSIValue(struct comedi_device *dev,struct comedi_subdevice *s,
352 struct comedi_insn *insn,unsigned int *data) |
353 +----------------------------------------------------------------------------+
357 Read the selected SSI counter (b_SelectedSSI) from |
358 | selected module (b_ModulNbr).
359 or Read all SSI counter (b_SelectedSSI) from |
360 | selected module (b_ModulNbr). |
361 +----------------------------------------------------------------------------+
362 | Input Parameters : unsigned char_ b_BoardHandle : Handle of board APCI-1710|
363 | unsigned char_ b_ModulNbr : Module number to |
364 | configure (0 to 3) |
365 | unsigned char_ b_SelectedSSI : Selection from SSI |
368 b_ModulNbr = (unsigned char) CR_AREF(insn->chanspec);
369 b_SelectedSSI = (unsigned char) CR_CHAN(insn->chanspec); (in case of single ssi)
370 b_ReadType = (unsigned char) CR_RANGE(insn->chanspec);
372 +----------------------------------------------------------------------------+
373 | Output Parameters : PULONG_ pul_Position : SSI position in the turn |
374 | PULONG_ pul_TurnCpt : Number of turns
376 pul_Position = (unsigned int *) &data[0];
377 pul_TurnCpt = (unsigned int *) &data[1]; |
378 +----------------------------------------------------------------------------+
379 | Return Value : 0: No error |
380 | -1: The handle parameter of the board is wrong |
381 | -2: The module parameter is wrong |
382 | -3: The module is not a SSI module |
383 | -4: SSI not initialised see function |
384 | "i_APCI1710_InitSSI" |
385 | -5: The selected SSI is wrong |
386 +----------------------------------------------------------------------------+
389 int i_APCI1710_InsnReadSSIValue(struct comedi_device *dev, struct comedi_subdevice *s,
390 struct comedi_insn *insn, unsigned int *data)
392 int i_ReturnValue = 0;
394 unsigned char b_Length;
395 unsigned char b_Schift;
396 unsigned char b_SSICpt;
398 unsigned int dw_And1;
399 unsigned int dw_And2;
400 unsigned int dw_StatusReg;
401 unsigned int dw_CounterValue;
402 unsigned char b_ModulNbr;
403 unsigned char b_SelectedSSI;
404 unsigned char b_ReadType;
405 unsigned int *pul_Position;
406 unsigned int *pul_TurnCpt;
407 unsigned int *pul_Position1;
408 unsigned int *pul_TurnCpt1;
410 i_ReturnValue = insn->n;
411 pul_Position1 = (unsigned int *) &data[0];
413 pul_TurnCpt1 = (unsigned int *) &data[1];
415 pul_Position = (unsigned int *) &data[0]; /* 0-2 */
416 pul_TurnCpt = (unsigned int *) &data[3]; /* 3-5 */
417 b_ModulNbr = (unsigned char) CR_AREF(insn->chanspec);
418 b_SelectedSSI = (unsigned char) CR_CHAN(insn->chanspec);
419 b_ReadType = (unsigned char) CR_RANGE(insn->chanspec);
421 /**************************/
422 /* Test the module number */
423 /**************************/
425 if (b_ModulNbr < 4) {
426 /***********************/
427 /* Test if SSI counter */
428 /***********************/
430 if ((devpriv->s_BoardInfos.
431 dw_MolduleConfiguration[b_ModulNbr] &
432 0xFFFF0000UL) == APCI1710_SSI_COUNTER) {
433 /***************************/
434 /* Test if SSI initialised */
435 /***************************/
437 if (devpriv->s_ModuleInfo[b_ModulNbr].
438 s_SSICounterInfo.b_SSIInit == 1) {
440 switch (b_ReadType) {
442 case APCI1710_SSI_READ1VALUE:
443 /****************************************/
444 /* Test the selected SSI counter number */
445 /****************************************/
447 if (b_SelectedSSI < 3) {
448 /************************/
449 /* Start the conversion */
450 /************************/
452 outl(0, devpriv->s_BoardInfos.
457 /*******************/
458 /* Read the status */
459 /*******************/
466 } while ((dw_StatusReg & 0x1)
469 /******************************/
470 /* Read the SSI counter value */
471 /******************************/
477 (b_SelectedSSI * 4) +
487 if ((b_Length * 2) !=
502 b_PositionTurnLength;
516 b_PositionTurnLength;
546 /*****************************/
547 /* The selected SSI is wrong */
548 /*****************************/
550 DPRINTK("The selected SSI is wrong\n");
555 case APCI1710_SSI_READALLVALUE:
561 s_ModuleInfo[b_ModulNbr].
563 b_PositionTurnLength; b_Cpt++) {
564 dw_And1 = dw_And1 * 2;
572 s_ModuleInfo[b_ModulNbr].
574 b_TurnCptLength; b_Cpt++) {
575 dw_And2 = dw_And2 * 2;
578 /************************/
579 /* Start the conversion */
580 /************************/
582 outl(0, devpriv->s_BoardInfos.
587 /*******************/
588 /* Read the status */
589 /*******************/
596 } while ((dw_StatusReg & 0x1) != 0);
598 for (b_SSICpt = 0; b_SSICpt < 3;
600 /******************************/
601 /* Read the SSI counter value */
602 /******************************/
618 if ((b_Length * 2) !=
633 b_PositionTurnLength;
635 pul_Position[b_SSICpt] =
638 pul_Position[b_SSICpt] =
639 pul_Position[b_SSICpt] &
642 pul_TurnCpt[b_SSICpt] =
645 pul_TurnCpt[b_SSICpt] =
646 pul_TurnCpt[b_SSICpt] &
652 printk("Read Type Inputs Wrong\n");
654 } /* switch ending */
657 /***********************/
658 /* SSI not initialised */
659 /***********************/
661 DPRINTK("SSI not initialised\n");
665 /**********************************/
666 /* The module is not a SSI module */
667 /**********************************/
669 DPRINTK("The module is not a SSI module\n");
674 /***********************/
675 /* Module number error */
676 /***********************/
678 DPRINTK("Module number error\n");
682 return i_ReturnValue;
686 +----------------------------------------------------------------------------+
687 | Function Name : _INT_ i_APCI1710_ReadSSI1DigitalInput |
688 | (unsigned char_ b_BoardHandle, |
689 | unsigned char_ b_ModulNbr, |
690 | unsigned char_ b_InputChannel, |
691 | unsigned char *_ pb_ChannelStatus) |
692 +----------------------------------------------------------------------------+
694 (0) Set the digital output from selected SSI moule |
696 (1) Set the digital output from selected SSI moule |
698 (2)Read the status from selected SSI digital input |
700 (3)Read the status from all SSI digital inputs from |
701 | selected SSI module (b_ModulNbr) |
702 +----------------------------------------------------------------------------+
703 | Input Parameters : unsigned char_ b_BoardHandle : Handle of board APCI-1710|
704 | unsigned char_ b_ModulNbr CR_AREF : Module number to |
705 | configure (0 to 3) |
706 | unsigned char_ b_InputChannel CR_CHAN : Selection from digital |
707 | data[0] which IOTYPE input ( 0 to 2) |
708 +----------------------------------------------------------------------------+
709 | Output Parameters : unsigned char *_ pb_ChannelStatus : Digital input channel |
711 | 0 : Channle is not active|
712 | 1 : Channle is active |
713 +----------------------------------------------------------------------------+
714 | Return Value : 0: No error |
715 | -1: The handle parameter of the board is wrong |
716 | -2: The module parameter is wrong |
717 | -3: The module is not a SSI module |
718 | -4: The selected SSI digital input is wrong |
719 +----------------------------------------------------------------------------+
722 int i_APCI1710_InsnBitsSSIDigitalIO(struct comedi_device *dev, struct comedi_subdevice *s,
723 struct comedi_insn *insn, unsigned int *data)
725 int i_ReturnValue = 0;
726 unsigned int dw_StatusReg;
727 unsigned char b_ModulNbr;
728 unsigned char b_InputChannel;
729 unsigned char *pb_ChannelStatus;
730 unsigned char *pb_InputStatus;
731 unsigned char b_IOType;
732 i_ReturnValue = insn->n;
733 b_ModulNbr = (unsigned char) CR_AREF(insn->chanspec);
734 b_IOType = (unsigned char) data[0];
736 /**************************/
737 /* Test the module number */
738 /**************************/
740 if (b_ModulNbr < 4) {
741 /***********************/
742 /* Test if SSI counter */
743 /***********************/
745 if ((devpriv->s_BoardInfos.
746 dw_MolduleConfiguration[b_ModulNbr] &
747 0xFFFF0000UL) == APCI1710_SSI_COUNTER) {
749 case APCI1710_SSI_SET_CHANNELON:
750 /*****************************/
751 /* Set the digital output ON */
752 /*****************************/
754 outl(1, devpriv->s_BoardInfos.ui_Address + 16 +
758 case APCI1710_SSI_SET_CHANNELOFF:
759 /******************************/
760 /* Set the digital output OFF */
761 /******************************/
763 outl(0, devpriv->s_BoardInfos.ui_Address + 16 +
767 case APCI1710_SSI_READ_1CHANNEL:
768 /******************************************/
769 /* Test the digital imnput channel number */
770 /******************************************/
772 b_InputChannel = (unsigned char) CR_CHAN(insn->chanspec);
773 pb_ChannelStatus = (unsigned char *) &data[0];
775 if (b_InputChannel <= 2) {
776 /**************************/
777 /* Read all digital input */
778 /**************************/
781 inl(devpriv->s_BoardInfos.
782 ui_Address + (64 * b_ModulNbr));
784 (unsigned char) (((~dw_StatusReg) >> (4 +
788 /********************************/
789 /* Selected digital input error */
790 /********************************/
792 DPRINTK("Selected digital input error\n");
797 case APCI1710_SSI_READ_ALLCHANNEL:
798 /**************************/
799 /* Read all digital input */
800 /**************************/
801 pb_InputStatus = (unsigned char *) &data[0];
804 inl(devpriv->s_BoardInfos.ui_Address +
807 (unsigned char) (((~dw_StatusReg) >> 4) & 7);
811 printk("IO type wrong\n");
815 /**********************************/
816 /* The module is not a SSI module */
817 /**********************************/
819 DPRINTK("The module is not a SSI module\n");
823 /***********************/
824 /* Module number error */
825 /***********************/
827 DPRINTK("Module number error\n");
831 return i_ReturnValue;