diff options
Diffstat (limited to 'drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.c')
-rw-r--r-- | drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.c | 3588 |
1 files changed, 3588 insertions, 0 deletions
diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.c new file mode 100644 index 000000000000..5ddd092a656a --- /dev/null +++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.c @@ -0,0 +1,3588 @@ +/** +@verbatim + +Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module. + + ADDI-DATA GmbH + Dieselstrasse 3 + D-77833 Ottersweier + Tel: +19(0)7223/9493-0 + Fax: +49(0)7223/9493-92 + http://www.addi-data-com + info@addi-data.com + +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. + +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. + +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 + +You shoud also find the complete GPL in the COPYING file accompanying this source code. + +@endverbatim +*/ +/* + + +-----------------------------------------------------------------------+ + | (C) ADDI-DATA GmbH Dieselstraße 3 D-77833 Ottersweier | + +-----------------------------------------------------------------------+ + | Tel : +49 (0) 7223/9493-0 | email : info@addi-data.com | + | Fax : +49 (0) 7223/9493-92 | Internet : http://www.addi-data.com | + +-----------------------------------------------------------------------+ + | Project : API APCI1710 | Compiler : gcc | + | Module name : PWM.C | Version : 2.96 | + +-------------------------------+---------------------------------------+ + | Project manager: Eric Stolz | Date : 02/12/2002 | + +-----------------------------------------------------------------------+ + | Description : APCI-1710 Wulse wide modulation module | + | | + | | + +-----------------------------------------------------------------------+ + | UPDATES | + +-----------------------------------------------------------------------+ + | Date | Author | Description of updates | + +-----------------------------------------------------------------------+ + | 08/05/00 | Guinot C | - 0400/0228 All Function in RING 0 | + | | | available | + +-----------------------------------------------------------------------+ +*/ + +/* ++----------------------------------------------------------------------------+ +| Included files | ++----------------------------------------------------------------------------+ +*/ + +#include "APCI1710_Pwm.h" + +/* ++----------------------------------------------------------------------------+ +| Function Name :INT i_APCI1710_InsnConfigPWM(struct comedi_device *dev, +struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data) | ++----------------------------------------------------------------------------+ +| Task : Pwm Init and Get Pwm Initialisation | ++----------------------------------------------------------------------------+ +| Input Parameters : ++----------------------------------------------------------------------------+ +| Output Parameters : - | ++----------------------------------------------------------------------------+ +| Return Value : ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_InsnConfigPWM(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + BYTE b_ConfigType; + INT i_ReturnValue = 0; + b_ConfigType = CR_CHAN(insn->chanspec); + + switch (b_ConfigType) { + case APCI1710_PWM_INIT: + i_ReturnValue = i_APCI1710_InitPWM(dev, (BYTE) CR_AREF(insn->chanspec), // b_ModulNbr + (BYTE) data[0], //b_PWM + (BYTE) data[1], // b_ClockSelection + (BYTE) data[2], // b_TimingUnit + (ULONG) data[3], //ul_LowTiming + (ULONG) data[4], //ul_HighTiming + (PULONG) & data[0], //pul_RealLowTiming + (PULONG) & data[1] //pul_RealHighTiming + ); + break; + + case APCI1710_PWM_GETINITDATA: + i_ReturnValue = i_APCI1710_GetPWMInitialisation(dev, (BYTE) CR_AREF(insn->chanspec), // b_ModulNbr + (BYTE) data[0], //b_PWM + (PBYTE) & data[0], //pb_TimingUnit + (PULONG) & data[1], //pul_LowTiming + (PULONG) & data[2], //pul_HighTiming + (PBYTE) & data[3], // pb_StartLevel + (PBYTE) & data[4], // pb_StopMode + (PBYTE) & data[5], // pb_StopLevel + (PBYTE) & data[6], // pb_ExternGate + (PBYTE) & data[7], // pb_InterruptEnable + (PBYTE) & data[8] // pb_Enable + ); + break; + + default: + printk(" Config Parameter Wrong\n"); + } + + if (i_ReturnValue >= 0) + i_ReturnValue = insn->n; + return (i_ReturnValue); +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : _INT_ i_APCI1710_InitPWM | +| (BYTE_ b_BoardHandle, | +| BYTE_ b_ModulNbr, | +| BYTE_ b_PWM, | +| BYTE_ b_ClockSelection, | +| BYTE_ b_TimingUnit, | +| ULONG_ ul_LowTiming, | +| ULONG_ ul_HighTiming, | +| PULONG_ pul_RealLowTiming, | +| PULONG_ pul_RealHighTiming) | ++----------------------------------------------------------------------------+ +| Task : Configure the selected PWM (b_PWM) from selected module| +| (b_ModulNbr). The ul_LowTiming, ul_HighTiming and | +| ul_TimingUnit determine the low/high timing base for | +| the period. pul_RealLowTiming, pul_RealHighTiming | +| return the real timing value. | +| You must calling this function be for you call any | +| other function witch access of the PWM. | ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 | +| BYTE_ b_ModulNbr : Module number to configure| +| (0 to 3) | +| BYTE_ b_PWM : Selected PWM (0 or 1). | +| BYTE_ b_ClockSelection : Selection from PCI bus | +| clock | +| - APCI1710_30MHZ : | +| The PC have a 30 MHz | +| PCI bus clock | +| - APCI1710_33MHZ : | +| The PC have a 33 MHz | +| PCI bus clock | +| - APCI1710_40MHZ | +| The APCI-1710 have a | +| integrated 40Mhz | +| quartz. | +| BYTE_ b_TimingUnit : Base timing Unit (0 to 4) | +| 0 : ns | +| 1 : æs | +| 2 : ms | +| 3 : s | +| 4 : mn | +| ULONG_ ul_LowTiming : Low base timing value. | +| ULONG_ ul_HighTiming : High base timing value. | ++----------------------------------------------------------------------------+ +| Output Parameters : PULONG_ pul_RealLowTiming : Real low base timing | +| value. | +| PULONG_ pul_RealHighTiming : Real high base timing | +| value. | ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: Module selection wrong | +| -3: The module is not a PWM module | +| -4: PWM selection is wrong | +| -5: The selected input clock is wrong | +| -6: Timing Unit selection is wrong | +| -7: Low base timing selection is wrong | +| -8: High base timing selection is wrong | +| -9: You can not used the 40MHz clock selection with | +| this board | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_InitPWM(struct comedi_device * dev, + BYTE b_ModulNbr, + BYTE b_PWM, + BYTE b_ClockSelection, + BYTE b_TimingUnit, + ULONG ul_LowTiming, + ULONG ul_HighTiming, + PULONG pul_RealLowTiming, PULONG pul_RealHighTiming) +{ + INT i_ReturnValue = 0; + ULONG ul_LowTimerValue = 0; + ULONG ul_HighTimerValue = 0; + DWORD dw_Command; + double d_RealLowTiming = 0; + double d_RealHighTiming = 0; + + /**************************/ + /* Test the module number */ + /**************************/ + + if (b_ModulNbr < 4) { + /***************/ + /* Test if PWM */ + /***************/ + + if ((devpriv->s_BoardInfos. + dw_MolduleConfiguration[b_ModulNbr] & + 0xFFFF0000UL) == APCI1710_PWM) { + /**************************/ + /* Test the PWM selection */ + /**************************/ + + if (b_PWM <= 1) { + /******************/ + /* Test the clock */ + /******************/ + + if ((b_ClockSelection == APCI1710_30MHZ) || + (b_ClockSelection == APCI1710_33MHZ) || + (b_ClockSelection == APCI1710_40MHZ)) { + /************************/ + /* Test the timing unit */ + /************************/ + + if (b_TimingUnit <= 4) { + /*********************************/ + /* Test the low timing selection */ + /*********************************/ + + if (((b_ClockSelection == + APCI1710_30MHZ) + && (b_TimingUnit + == 0) + && (ul_LowTiming + >= 266) + && (ul_LowTiming + <= + 0xFFFFFFFFUL)) + || ((b_ClockSelection == + APCI1710_30MHZ) + && (b_TimingUnit + == 1) + && (ul_LowTiming + >= 1) + && (ul_LowTiming + <= + 571230650UL)) + || ((b_ClockSelection == + APCI1710_30MHZ) + && (b_TimingUnit + == 2) + && (ul_LowTiming + >= 1) + && (ul_LowTiming + <= + 571230UL)) + || ((b_ClockSelection == + APCI1710_30MHZ) + && (b_TimingUnit + == 3) + && (ul_LowTiming + >= 1) + && (ul_LowTiming + <= + 571UL)) + || ((b_ClockSelection == + APCI1710_30MHZ) + && (b_TimingUnit + == 4) + && (ul_LowTiming + >= 1) + && (ul_LowTiming + <= 9UL)) + || ((b_ClockSelection == + APCI1710_33MHZ) + && (b_TimingUnit + == 0) + && (ul_LowTiming + >= 242) + && (ul_LowTiming + <= + 0xFFFFFFFFUL)) + || ((b_ClockSelection == + APCI1710_33MHZ) + && (b_TimingUnit + == 1) + && (ul_LowTiming + >= 1) + && (ul_LowTiming + <= + 519691043UL)) + || ((b_ClockSelection == + APCI1710_33MHZ) + && (b_TimingUnit + == 2) + && (ul_LowTiming + >= 1) + && (ul_LowTiming + <= + 519691UL)) + || ((b_ClockSelection == + APCI1710_33MHZ) + && (b_TimingUnit + == 3) + && (ul_LowTiming + >= 1) + && (ul_LowTiming + <= + 520UL)) + || ((b_ClockSelection == + APCI1710_33MHZ) + && (b_TimingUnit + == 4) + && (ul_LowTiming + >= 1) + && (ul_LowTiming + <= 8UL)) + || ((b_ClockSelection == + APCI1710_40MHZ) + && (b_TimingUnit + == 0) + && (ul_LowTiming + >= 200) + && (ul_LowTiming + <= + 0xFFFFFFFFUL)) + || ((b_ClockSelection == + APCI1710_40MHZ) + && (b_TimingUnit + == 1) + && (ul_LowTiming + >= 1) + && (ul_LowTiming + <= + 429496729UL)) + || ((b_ClockSelection == + APCI1710_40MHZ) + && (b_TimingUnit + == 2) + && (ul_LowTiming + >= 1) + && (ul_LowTiming + <= + 429496UL)) + || ((b_ClockSelection == + APCI1710_40MHZ) + && (b_TimingUnit + == 3) + && (ul_LowTiming + >= 1) + && (ul_LowTiming + <= + 429UL)) + || ((b_ClockSelection == + APCI1710_40MHZ) + && (b_TimingUnit + == 4) + && (ul_LowTiming + >= 1) + && (ul_LowTiming + <= + 7UL))) { + /**********************************/ + /* Test the High timing selection */ + /**********************************/ + + if (((b_ClockSelection == APCI1710_30MHZ) && (b_TimingUnit == 0) && (ul_HighTiming >= 266) && (ul_HighTiming <= 0xFFFFFFFFUL)) || ((b_ClockSelection == APCI1710_30MHZ) && (b_TimingUnit == 1) && (ul_HighTiming >= 1) && (ul_HighTiming <= 571230650UL)) || ((b_ClockSelection == APCI1710_30MHZ) && (b_TimingUnit == 2) && (ul_HighTiming >= 1) && (ul_HighTiming <= 571230UL)) || ((b_ClockSelection == APCI1710_30MHZ) && (b_TimingUnit == 3) && (ul_HighTiming >= 1) && (ul_HighTiming <= 571UL)) || ((b_ClockSelection == APCI1710_30MHZ) && (b_TimingUnit == 4) && (ul_HighTiming >= 1) && (ul_HighTiming <= 9UL)) || ((b_ClockSelection == APCI1710_33MHZ) && (b_TimingUnit == 0) && (ul_HighTiming >= 242) && (ul_HighTiming <= 0xFFFFFFFFUL)) || ((b_ClockSelection == APCI1710_33MHZ) && (b_TimingUnit == 1) && (ul_HighTiming >= 1) && (ul_HighTiming <= 519691043UL)) || ((b_ClockSelection == APCI1710_33MHZ) && (b_TimingUnit == 2) && (ul_HighTiming >= 1) && (ul_HighTiming <= 519691UL)) || ((b_ClockSelection == APCI1710_33MHZ) && (b_TimingUnit == 3) && (ul_HighTiming >= 1) && (ul_HighTiming <= 520UL)) || ((b_ClockSelection == APCI1710_33MHZ) && (b_TimingUnit == 4) && (ul_HighTiming >= 1) && (ul_HighTiming <= 8UL)) || ((b_ClockSelection == APCI1710_40MHZ) && (b_TimingUnit == 0) && (ul_HighTiming >= 200) && (ul_HighTiming <= 0xFFFFFFFFUL)) || ((b_ClockSelection == APCI1710_40MHZ) && (b_TimingUnit == 1) && (ul_HighTiming >= 1) && (ul_HighTiming <= 429496729UL)) || ((b_ClockSelection == APCI1710_40MHZ) && (b_TimingUnit == 2) && (ul_HighTiming >= 1) && (ul_HighTiming <= 429496UL)) || ((b_ClockSelection == APCI1710_40MHZ) && (b_TimingUnit == 3) && (ul_HighTiming >= 1) && (ul_HighTiming <= 429UL)) || ((b_ClockSelection == APCI1710_40MHZ) && (b_TimingUnit == 4) && (ul_HighTiming >= 1) && (ul_HighTiming <= 7UL))) { + /**************************/ + /* Test the board version */ + /**************************/ + + if (((b_ClockSelection == APCI1710_40MHZ) && (devpriv->s_BoardInfos.b_BoardVersion > 0)) || (b_ClockSelection != APCI1710_40MHZ)) { + + /************************************/ + /* Calculate the low division fator */ + /************************************/ + + fpu_begin + (); + + switch (b_TimingUnit) { + /******/ + /* ns */ + /******/ + + case 0: + + /******************/ + /* Timer 0 factor */ + /******************/ + + ul_LowTimerValue + = + (ULONG) + (ul_LowTiming + * + (0.00025 * b_ClockSelection)); + + /*******************/ + /* Round the value */ + /*******************/ + + if ((double)((double)ul_LowTiming * (0.00025 * (double)b_ClockSelection)) >= ((double)((double)ul_LowTimerValue + 0.5))) { + ul_LowTimerValue + = + ul_LowTimerValue + + + 1; + } + + /*****************************/ + /* Calculate the real timing */ + /*****************************/ + + *pul_RealLowTiming + = + (ULONG) + (ul_LowTimerValue + / + (0.00025 * (double)b_ClockSelection)); + d_RealLowTiming + = + (double) + ul_LowTimerValue + / + (0.00025 + * + (double) + b_ClockSelection); + + if ((double)((double)ul_LowTimerValue / (0.00025 * (double)b_ClockSelection)) >= (double)((double)*pul_RealLowTiming + 0.5)) { + *pul_RealLowTiming + = + *pul_RealLowTiming + + + 1; + } + + ul_LowTiming + = + ul_LowTiming + - + 1; + ul_LowTimerValue + = + ul_LowTimerValue + - + 2; + + if (b_ClockSelection != APCI1710_40MHZ) { + ul_LowTimerValue + = + (ULONG) + ( + (double) + (ul_LowTimerValue) + * + 1.007752288); + } + + break; + + /******/ + /* æs */ + /******/ + + case 1: + + /******************/ + /* Timer 0 factor */ + /******************/ + + ul_LowTimerValue + = + (ULONG) + (ul_LowTiming + * + (0.25 * b_ClockSelection)); + + /*******************/ + /* Round the value */ + /*******************/ + + if ((double)((double)ul_LowTiming * (0.25 * (double)b_ClockSelection)) >= ((double)((double)ul_LowTimerValue + 0.5))) { + ul_LowTimerValue + = + ul_LowTimerValue + + + 1; + } + + /*****************************/ + /* Calculate the real timing */ + /*****************************/ + + *pul_RealLowTiming + = + (ULONG) + (ul_LowTimerValue + / + (0.25 * (double)b_ClockSelection)); + d_RealLowTiming + = + (double) + ul_LowTimerValue + / + ( + (double) + 0.25 + * + (double) + b_ClockSelection); + + if ((double)((double)ul_LowTimerValue / (0.25 * (double)b_ClockSelection)) >= (double)((double)*pul_RealLowTiming + 0.5)) { + *pul_RealLowTiming + = + *pul_RealLowTiming + + + 1; + } + + ul_LowTiming + = + ul_LowTiming + - + 1; + ul_LowTimerValue + = + ul_LowTimerValue + - + 2; + + if (b_ClockSelection != APCI1710_40MHZ) { + ul_LowTimerValue + = + (ULONG) + ( + (double) + (ul_LowTimerValue) + * + 1.007752288); + } + + break; + + /******/ + /* ms */ + /******/ + + case 2: + + /******************/ + /* Timer 0 factor */ + /******************/ + + ul_LowTimerValue + = + ul_LowTiming + * + (250.0 + * + b_ClockSelection); + + /*******************/ + /* Round the value */ + /*******************/ + + if ((double)((double)ul_LowTiming * (250.0 * (double)b_ClockSelection)) >= ((double)((double)ul_LowTimerValue + 0.5))) { + ul_LowTimerValue + = + ul_LowTimerValue + + + 1; + } + + /*****************************/ + /* Calculate the real timing */ + /*****************************/ + + *pul_RealLowTiming + = + (ULONG) + (ul_LowTimerValue + / + (250.0 * (double)b_ClockSelection)); + d_RealLowTiming + = + (double) + ul_LowTimerValue + / + (250.0 + * + (double) + b_ClockSelection); + + if ((double)((double)ul_LowTimerValue / (250.0 * (double)b_ClockSelection)) >= (double)((double)*pul_RealLowTiming + 0.5)) { + *pul_RealLowTiming + = + *pul_RealLowTiming + + + 1; + } + + ul_LowTiming + = + ul_LowTiming + - + 1; + ul_LowTimerValue + = + ul_LowTimerValue + - + 2; + + if (b_ClockSelection != APCI1710_40MHZ) { + ul_LowTimerValue + = + (ULONG) + ( + (double) + (ul_LowTimerValue) + * + 1.007752288); + } + + break; + + /*****/ + /* s */ + /*****/ + + case 3: + /******************/ + /* Timer 0 factor */ + /******************/ + + ul_LowTimerValue + = + (ULONG) + (ul_LowTiming + * + (250000.0 + * + b_ClockSelection)); + + /*******************/ + /* Round the value */ + /*******************/ + + if ((double)((double)ul_LowTiming * (250000.0 * (double)b_ClockSelection)) >= ((double)((double)ul_LowTimerValue + 0.5))) { + ul_LowTimerValue + = + ul_LowTimerValue + + + 1; + } + + /*****************************/ + /* Calculate the real timing */ + /*****************************/ + + *pul_RealLowTiming + = + (ULONG) + (ul_LowTimerValue + / + (250000.0 + * + (double) + b_ClockSelection)); + d_RealLowTiming + = + (double) + ul_LowTimerValue + / + (250000.0 + * + (double) + b_ClockSelection); + + if ((double)((double)ul_LowTimerValue / (250000.0 * (double)b_ClockSelection)) >= (double)((double)*pul_RealLowTiming + 0.5)) { + *pul_RealLowTiming + = + *pul_RealLowTiming + + + 1; + } + + ul_LowTiming + = + ul_LowTiming + - + 1; + ul_LowTimerValue + = + ul_LowTimerValue + - + 2; + + if (b_ClockSelection != APCI1710_40MHZ) { + ul_LowTimerValue + = + (ULONG) + ( + (double) + (ul_LowTimerValue) + * + 1.007752288); + } + + break; + + /******/ + /* mn */ + /******/ + + case 4: + + /******************/ + /* Timer 0 factor */ + /******************/ + + ul_LowTimerValue + = + (ULONG) + ( + (ul_LowTiming + * + 60) + * + (250000.0 + * + b_ClockSelection)); + + /*******************/ + /* Round the value */ + /*******************/ + + if ((double)((double)(ul_LowTiming * 60.0) * (250000.0 * (double)b_ClockSelection)) >= ((double)((double)ul_LowTimerValue + 0.5))) { + ul_LowTimerValue + = + ul_LowTimerValue + + + 1; + } + + /*****************************/ + /* Calculate the real timing */ + /*****************************/ + + *pul_RealLowTiming + = + (ULONG) + (ul_LowTimerValue + / + (250000.0 + * + (double) + b_ClockSelection)) + / + 60; + d_RealLowTiming + = + ( + (double) + ul_LowTimerValue + / + (250000.0 + * + (double) + b_ClockSelection)) + / + 60.0; + + if ((double)(((double)ul_LowTimerValue / (250000.0 * (double)b_ClockSelection)) / 60.0) >= (double)((double)*pul_RealLowTiming + 0.5)) { + *pul_RealLowTiming + = + *pul_RealLowTiming + + + 1; + } + + ul_LowTiming + = + ul_LowTiming + - + 1; + ul_LowTimerValue + = + ul_LowTimerValue + - + 2; + + if (b_ClockSelection != APCI1710_40MHZ) { + ul_LowTimerValue + = + (ULONG) + ( + (double) + (ul_LowTimerValue) + * + 1.007752288); + } + + break; + } + + /*************************************/ + /* Calculate the high division fator */ + /*************************************/ + + switch (b_TimingUnit) { + /******/ + /* ns */ + /******/ + + case 0: + + /******************/ + /* Timer 0 factor */ + /******************/ + + ul_HighTimerValue + = + (ULONG) + (ul_HighTiming + * + (0.00025 * b_ClockSelection)); + + /*******************/ + /* Round the value */ + /*******************/ + + if ((double)((double)ul_HighTiming * (0.00025 * (double)b_ClockSelection)) >= ((double)((double)ul_HighTimerValue + 0.5))) { + ul_HighTimerValue + = + ul_HighTimerValue + + + 1; + } + + /*****************************/ + /* Calculate the real timing */ + /*****************************/ + + *pul_RealHighTiming + = + (ULONG) + (ul_HighTimerValue + / + (0.00025 * (double)b_ClockSelection)); + d_RealHighTiming + = + (double) + ul_HighTimerValue + / + (0.00025 + * + (double) + b_ClockSelection); + + if ((double)((double)ul_HighTimerValue / (0.00025 * (double)b_ClockSelection)) >= (double)((double)*pul_RealHighTiming + 0.5)) { + *pul_RealHighTiming + = + *pul_RealHighTiming + + + 1; + } + + ul_HighTiming + = + ul_HighTiming + - + 1; + ul_HighTimerValue + = + ul_HighTimerValue + - + 2; + + if (b_ClockSelection != APCI1710_40MHZ) { + ul_HighTimerValue + = + (ULONG) + ( + (double) + (ul_HighTimerValue) + * + 1.007752288); + } + + break; + + /******/ + /* æs */ + /******/ + + case 1: + + /******************/ + /* Timer 0 factor */ + /******************/ + + ul_HighTimerValue + = + (ULONG) + (ul_HighTiming + * + (0.25 * b_ClockSelection)); + + /*******************/ + /* Round the value */ + /*******************/ + + if ((double)((double)ul_HighTiming * (0.25 * (double)b_ClockSelection)) >= ((double)((double)ul_HighTimerValue + 0.5))) { + ul_HighTimerValue + = + ul_HighTimerValue + + + 1; + } + + /*****************************/ + /* Calculate the real timing */ + /*****************************/ + + *pul_RealHighTiming + = + (ULONG) + (ul_HighTimerValue + / + (0.25 * (double)b_ClockSelection)); + d_RealHighTiming + = + (double) + ul_HighTimerValue + / + ( + (double) + 0.25 + * + (double) + b_ClockSelection); + + if ((double)((double)ul_HighTimerValue / (0.25 * (double)b_ClockSelection)) >= (double)((double)*pul_RealHighTiming + 0.5)) { + *pul_RealHighTiming + = + *pul_RealHighTiming + + + 1; + } + + ul_HighTiming + = + ul_HighTiming + - + 1; + ul_HighTimerValue + = + ul_HighTimerValue + - + 2; + + if (b_ClockSelection != APCI1710_40MHZ) { + ul_HighTimerValue + = + (ULONG) + ( + (double) + (ul_HighTimerValue) + * + 1.007752288); + } + + break; + + /******/ + /* ms */ + /******/ + + case 2: + + /******************/ + /* Timer 0 factor */ + /******************/ + + ul_HighTimerValue + = + ul_HighTiming + * + (250.0 + * + b_ClockSelection); + + /*******************/ + /* Round the value */ + /*******************/ + + if ((double)((double)ul_HighTiming * (250.0 * (double)b_ClockSelection)) >= ((double)((double)ul_HighTimerValue + 0.5))) { + ul_HighTimerValue + = + ul_HighTimerValue + + + 1; + } + + /*****************************/ + /* Calculate the real timing */ + /*****************************/ + + *pul_RealHighTiming + = + (ULONG) + (ul_HighTimerValue + / + (250.0 * (double)b_ClockSelection)); + d_RealHighTiming + = + (double) + ul_HighTimerValue + / + (250.0 + * + (double) + b_ClockSelection); + + if ((double)((double)ul_HighTimerValue / (250.0 * (double)b_ClockSelection)) >= (double)((double)*pul_RealHighTiming + 0.5)) { + *pul_RealHighTiming + = + *pul_RealHighTiming + + + 1; + } + + ul_HighTiming + = + ul_HighTiming + - + 1; + ul_HighTimerValue + = + ul_HighTimerValue + - + 2; + + if (b_ClockSelection != APCI1710_40MHZ) { + ul_HighTimerValue + = + (ULONG) + ( + (double) + (ul_HighTimerValue) + * + 1.007752288); + } + + break; + + /*****/ + /* s */ + /*****/ + + case 3: + + /******************/ + /* Timer 0 factor */ + /******************/ + + ul_HighTimerValue + = + (ULONG) + (ul_HighTiming + * + (250000.0 + * + b_ClockSelection)); + + /*******************/ + /* Round the value */ + /*******************/ + + if ((double)((double)ul_HighTiming * (250000.0 * (double)b_ClockSelection)) >= ((double)((double)ul_HighTimerValue + 0.5))) { + ul_HighTimerValue + = + ul_HighTimerValue + + + 1; + } + + /*****************************/ + /* Calculate the real timing */ + /*****************************/ + + *pul_RealHighTiming + = + (ULONG) + (ul_HighTimerValue + / + (250000.0 + * + (double) + b_ClockSelection)); + d_RealHighTiming + = + (double) + ul_HighTimerValue + / + (250000.0 + * + (double) + b_ClockSelection); + + if ((double)((double)ul_HighTimerValue / (250000.0 * (double)b_ClockSelection)) >= (double)((double)*pul_RealHighTiming + 0.5)) { + *pul_RealHighTiming + = + *pul_RealHighTiming + + + 1; + } + + ul_HighTiming + = + ul_HighTiming + - + 1; + ul_HighTimerValue + = + ul_HighTimerValue + - + 2; + + if (b_ClockSelection != APCI1710_40MHZ) { + ul_HighTimerValue + = + (ULONG) + ( + (double) + (ul_HighTimerValue) + * + 1.007752288); + } + + break; + + /******/ + /* mn */ + /******/ + + case 4: + + /******************/ + /* Timer 0 factor */ + /******************/ + + ul_HighTimerValue + = + (ULONG) + ( + (ul_HighTiming + * + 60) + * + (250000.0 + * + b_ClockSelection)); + + /*******************/ + /* Round the value */ + /*******************/ + + if ((double)((double)(ul_HighTiming * 60.0) * (250000.0 * (double)b_ClockSelection)) >= ((double)((double)ul_HighTimerValue + 0.5))) { + ul_HighTimerValue + = + ul_HighTimerValue + + + 1; + } + + /*****************************/ + /* Calculate the real timing */ + /*****************************/ + + *pul_RealHighTiming + = + (ULONG) + (ul_HighTimerValue + / + (250000.0 + * + (double) + b_ClockSelection)) + / + 60; + d_RealHighTiming + = + ( + (double) + ul_HighTimerValue + / + (250000.0 + * + (double) + b_ClockSelection)) + / + 60.0; + + if ((double)(((double)ul_HighTimerValue / (250000.0 * (double)b_ClockSelection)) / 60.0) >= (double)((double)*pul_RealHighTiming + 0.5)) { + *pul_RealHighTiming + = + *pul_RealHighTiming + + + 1; + } + + ul_HighTiming + = + ul_HighTiming + - + 1; + ul_HighTimerValue + = + ul_HighTimerValue + - + 2; + + if (b_ClockSelection != APCI1710_40MHZ) { + ul_HighTimerValue + = + (ULONG) + ( + (double) + (ul_HighTimerValue) + * + 1.007752288); + } + + break; + } + + fpu_end(); + /****************************/ + /* Save the clock selection */ + /****************************/ + + devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_PWMModuleInfo. + b_ClockSelection + = + b_ClockSelection; + + /************************/ + /* Save the timing unit */ + /************************/ + + devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_PWMModuleInfo. + s_PWMInfo + [b_PWM]. + b_TimingUnit + = + b_TimingUnit; + + /****************************/ + /* Save the low base timing */ + /****************************/ + + devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_PWMModuleInfo. + s_PWMInfo + [b_PWM]. + d_LowTiming + = + d_RealLowTiming; + + devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_PWMModuleInfo. + s_PWMInfo + [b_PWM]. + ul_RealLowTiming + = + *pul_RealLowTiming; + + /****************************/ + /* Save the high base timing */ + /****************************/ + + devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_PWMModuleInfo. + s_PWMInfo + [b_PWM]. + d_HighTiming + = + d_RealHighTiming; + + devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_PWMModuleInfo. + s_PWMInfo + [b_PWM]. + ul_RealHighTiming + = + *pul_RealHighTiming; + + /************************/ + /* Write the low timing */ + /************************/ + + outl(ul_LowTimerValue, devpriv->s_BoardInfos.ui_Address + 0 + (20 * b_PWM) + (64 * b_ModulNbr)); + + /*************************/ + /* Write the high timing */ + /*************************/ + + outl(ul_HighTimerValue, devpriv->s_BoardInfos.ui_Address + 4 + (20 * b_PWM) + (64 * b_ModulNbr)); + + /***************************/ + /* Set the clock selection */ + /***************************/ + + dw_Command + = + inl + (devpriv-> + s_BoardInfos. + ui_Address + + + 8 + + + (20 * b_PWM) + (64 * b_ModulNbr)); + + dw_Command + = + dw_Command + & + 0x7F; + + if (b_ClockSelection == APCI1710_40MHZ) { + dw_Command + = + dw_Command + | + 0x80; + } + + /***************************/ + /* Set the clock selection */ + /***************************/ + + outl(dw_Command, devpriv->s_BoardInfos.ui_Address + 8 + (20 * b_PWM) + (64 * b_ModulNbr)); + + /*************/ + /* PWM init. */ + /*************/ + devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_PWMModuleInfo. + s_PWMInfo + [b_PWM]. + b_PWMInit + = + 1; + } else { + /***************************************************/ + /* You can not used the 40MHz clock selection with */ + /* this board */ + /***************************************************/ + DPRINTK("You can not used the 40MHz clock selection with this board\n"); + i_ReturnValue + = + -9; + } + } else { + /***************************************/ + /* High base timing selection is wrong */ + /***************************************/ + DPRINTK("High base timing selection is wrong\n"); + i_ReturnValue = + -8; + } + } else { + /**************************************/ + /* Low base timing selection is wrong */ + /**************************************/ + DPRINTK("Low base timing selection is wrong\n"); + i_ReturnValue = -7; + } + } // if ((b_TimingUnit >= 0) && (b_TimingUnit <= 4)) + else { + /**********************************/ + /* Timing unit selection is wrong */ + /**********************************/ + DPRINTK("Timing unit selection is wrong\n"); + i_ReturnValue = -6; + } // if ((b_TimingUnit >= 0) && (b_TimingUnit <= 4)) + } // if ((b_ClockSelection == APCI1710_30MHZ) || (b_ClockSelection == APCI1710_33MHZ) || (b_ClockSelection == APCI1710_40MHZ)) + else { + /*******************************/ + /* The selected clock is wrong */ + /*******************************/ + DPRINTK("The selected clock is wrong\n"); + i_ReturnValue = -5; + } // if ((b_ClockSelection == APCI1710_30MHZ) || (b_ClockSelection == APCI1710_33MHZ) || (b_ClockSelection == APCI1710_40MHZ)) + } // if (b_PWM >= 0 && b_PWM <= 1) + else { + /******************************/ + /* Tor PWM selection is wrong */ + /******************************/ + DPRINTK("Tor PWM selection is wrong\n"); + i_ReturnValue = -4; + } // if (b_PWM >= 0 && b_PWM <= 1) + } else { + /**********************************/ + /* The module is not a PWM module */ + /**********************************/ + DPRINTK("The module is not a PWM module\n"); + i_ReturnValue = -3; + } + } else { + /***********************/ + /* Module number error */ + /***********************/ + DPRINTK("Module number error\n"); + i_ReturnValue = -2; + } + + return (i_ReturnValue); +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : _INT_ i_APCI1710_GetPWMInitialisation | +| (BYTE_ b_BoardHandle, | +| BYTE_ b_ModulNbr, | +| BYTE_ b_PWM, | +| PBYTE_ pb_TimingUnit, | +| PULONG_ pul_LowTiming, | +| PULONG_ pul_HighTiming, | +| PBYTE_ pb_StartLevel, | +| PBYTE_ pb_StopMode, | +| PBYTE_ pb_StopLevel, | +| PBYTE_ pb_ExternGate, | +| PBYTE_ pb_InterruptEnable, | +| PBYTE_ pb_Enable) | ++----------------------------------------------------------------------------+ +| Task : Return the PWM (b_PWM) initialisation from selected | +| module (b_ModulNbr). You must calling the | +| "i_APCI1710_InitPWM" function be for you call this | +| function. | ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 | +| BYTE_ b_ModulNbr : Selected module number (0 to 3) | +| BYTE_ b_PWM : Selected PWM (0 or 1) | ++----------------------------------------------------------------------------+ +| Output Parameters : PBYTE_ pb_TimingUnit : Base timing Unit (0 to 4) | +| 0 : ns | +| 1 : æs | +| 2 : ms | +| 3 : s | +| 4 : mn | +| PULONG_ pul_LowTiming : Low base timing value. | +| PULONG_ pul_HighTiming : High base timing value. | +| PBYTE_ pb_StartLevel : Start period level | +| selection | +| 0 : The period start | +| with a low level | +| 1 : The period start | +| with a high level| +| PBYTE_ pb_StopMode : Stop mode selection | +| 0 : The PWM is stopped | +| directly after the | +| "i_APCI1710_DisablePWM"| +| function and break the| +| last period | +| 1 : After the | +| "i_APCI1710_DisablePWM"| +| function the PWM is | +| stopped at the end | +| from last period cycle| +| PBYTE_ pb_StopLevel : Stop PWM level selection | +| 0 : The output signal | +| keep the level after| +| the | +| "i_APCI1710_DisablePWM"| +| function | +| 1 : The output signal is| +| set to low after the| +| "i_APCI1710_DisablePWM"| +| function | +| 2 : The output signal is| +| set to high after | +| the | +| "i_APCI1710_DisablePWM"| +| function | +| PBYTE_ pb_ExternGate : Extern gate action | +| selection | +| 0 : Extern gate signal | +| not used. | +| 1 : Extern gate signal | +| used. | +| PBYTE_ pb_InterruptEnable : Enable or disable the PWM | +| interrupt. | +| - APCI1710_ENABLE : | +| Enable the PWM interrupt| +| A interrupt occur after | +| each period | +| - APCI1710_DISABLE : | +| Disable the PWM | +| interrupt | +| PBYTE_ pb_Enable : Indicate if the PWM is | +| enabled or no | +| 0 : PWM not enabled | +| 1 : PWM enabled | ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: Module selection wrong | +| -3: The module is not a PWM module | +| -4: PWM selection is wrong | +| -5: PWM not initialised see function | +| "i_APCI1710_InitPWM" | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_GetPWMInitialisation(struct comedi_device * dev, + BYTE b_ModulNbr, + BYTE b_PWM, + PBYTE pb_TimingUnit, + PULONG pul_LowTiming, + PULONG pul_HighTiming, + PBYTE pb_StartLevel, + PBYTE pb_StopMode, + PBYTE pb_StopLevel, + PBYTE pb_ExternGate, PBYTE pb_InterruptEnable, PBYTE pb_Enable) +{ + INT i_ReturnValue = 0; + DWORD dw_Status; + DWORD dw_Command; + + /**************************/ + /* Test the module number */ + /**************************/ + + if (b_ModulNbr < 4) { + /***************/ + /* Test if PWM */ + /***************/ + + if ((devpriv->s_BoardInfos. + dw_MolduleConfiguration[b_ModulNbr] & + 0xFFFF0000UL) == APCI1710_PWM) { + /**************************/ + /* Test the PWM selection */ + /**************************/ + + if (b_PWM <= 1) { + /***************************/ + /* Test if PWM initialised */ + /***************************/ + + dw_Status = inl(devpriv->s_BoardInfos. + ui_Address + 12 + (20 * b_PWM) + + (64 * b_ModulNbr)); + + if (dw_Status & 0x10) { + /***********************/ + /* Read the low timing */ + /***********************/ + + *pul_LowTiming = + inl(devpriv->s_BoardInfos. + ui_Address + 0 + (20 * b_PWM) + + (64 * b_ModulNbr)); + + /************************/ + /* Read the high timing */ + /************************/ + + *pul_HighTiming = + inl(devpriv->s_BoardInfos. + ui_Address + 4 + (20 * b_PWM) + + (64 * b_ModulNbr)); + + /********************/ + /* Read the command */ + /********************/ + + dw_Command = inl(devpriv->s_BoardInfos. + ui_Address + 8 + (20 * b_PWM) + + (64 * b_ModulNbr)); + + *pb_StartLevel = + (BYTE) ((dw_Command >> 5) & 1); + *pb_StopMode = + (BYTE) ((dw_Command >> 0) & 1); + *pb_StopLevel = + (BYTE) ((dw_Command >> 1) & 1); + *pb_ExternGate = + (BYTE) ((dw_Command >> 4) & 1); + *pb_InterruptEnable = + (BYTE) ((dw_Command >> 3) & 1); + + if (*pb_StopLevel) { + *pb_StopLevel = + *pb_StopLevel + + (BYTE) ((dw_Command >> + 2) & 1); + } + + /********************/ + /* Read the command */ + /********************/ + + dw_Command = inl(devpriv->s_BoardInfos. + ui_Address + 8 + (20 * b_PWM) + + (64 * b_ModulNbr)); + + *pb_Enable = + (BYTE) ((dw_Command >> 0) & 1); + + *pb_TimingUnit = devpriv-> + s_ModuleInfo[b_ModulNbr]. + s_PWMModuleInfo. + s_PWMInfo[b_PWM].b_TimingUnit; + } // if (dw_Status & 0x10) + else { + /***********************/ + /* PWM not initialised */ + /***********************/ + DPRINTK("PWM not initialised\n"); + i_ReturnValue = -5; + } // if (dw_Status & 0x10) + } // if (b_PWM >= 0 && b_PWM <= 1) + else { + /******************************/ + /* Tor PWM selection is wrong */ + /******************************/ + DPRINTK("Tor PWM selection is wrong\n"); + i_ReturnValue = -4; + } // if (b_PWM >= 0 && b_PWM <= 1) + } else { + /**********************************/ + /* The module is not a PWM module */ + /**********************************/ + DPRINTK("The module is not a PWM module\n"); + i_ReturnValue = -3; + } + } else { + /***********************/ + /* Module number error */ + /***********************/ + DPRINTK("Module number error\n"); + i_ReturnValue = -2; + } + + return (i_ReturnValue); +} + +/* ++----------------------------------------------------------------------------+ +| Function Name :INT i_APCI1710_InsnWritePWM(struct comedi_device *dev, +struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data) | ++----------------------------------------------------------------------------+ +| Task : Pwm Enable Disable and Set New Timing | ++----------------------------------------------------------------------------+ +| Input Parameters : ++----------------------------------------------------------------------------+ +| Output Parameters : - | ++----------------------------------------------------------------------------+ +| Return Value : ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_InsnWritePWM(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + BYTE b_WriteType; + INT i_ReturnValue = 0; + b_WriteType = CR_CHAN(insn->chanspec); + + switch (b_WriteType) { + case APCI1710_PWM_ENABLE: + i_ReturnValue = i_APCI1710_EnablePWM(dev, + (BYTE) CR_AREF(insn->chanspec), + (BYTE) data[0], + (BYTE) data[1], + (BYTE) data[2], + (BYTE) data[3], (BYTE) data[4], (BYTE) data[5]); + break; + + case APCI1710_PWM_DISABLE: + i_ReturnValue = i_APCI1710_DisablePWM(dev, + (BYTE) CR_AREF(insn->chanspec), (BYTE) data[0]); + break; + + case APCI1710_PWM_NEWTIMING: + i_ReturnValue = i_APCI1710_SetNewPWMTiming(dev, + (BYTE) CR_AREF(insn->chanspec), + (BYTE) data[0], + (BYTE) data[1], (ULONG) data[2], (ULONG) data[3]); + break; + + default: + printk("Write Config Parameter Wrong\n"); + } + + if (i_ReturnValue >= 0) + i_ReturnValue = insn->n; + return (i_ReturnValue); +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : _INT_ i_APCI1710_EnablePWM | +| (BYTE_ b_BoardHandle, | +| BYTE_ b_ModulNbr, | +| BYTE_ b_PWM, | +| BYTE_ b_StartLevel, | +| BYTE_ b_StopMode, | +| BYTE_ b_StopLevel, | +| BYTE_ b_ExternGate, | +| BYTE_ b_InterruptEnable) | ++----------------------------------------------------------------------------+ +| Task : Enable the selected PWM (b_PWM) from selected module | +| (b_ModulNbr). You must calling the "i_APCI1710_InitPWM"| +| function be for you call this function. | +| If you enable the PWM interrupt, the PWM generate a | +| interrupt after each period. | +| See function "i_APCI1710_SetBoardIntRoutineX" and the | +| Interrupt mask description chapter. | ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 | +| BYTE_ b_ModulNbr : Selected module number | +| (0 to 3) | +| BYTE_ b_PWM : Selected PWM (0 or 1) | +| BYTE_ b_StartLevel : Start period level selection | +| 0 : The period start with a | +| low level | +| 1 : The period start with a | +| high level | +| BYTE_ b_StopMode : Stop mode selection | +| 0 : The PWM is stopped | +| directly after the | +| "i_APCI1710_DisablePWM" | +| function and break the | +| last period | +| 1 : After the | +| "i_APCI1710_DisablePWM" | +| function the PWM is | +| stopped at the end from| +| last period cycle. | +| BYTE_ b_StopLevel : Stop PWM level selection | +| 0 : The output signal keep | +| the level after the | +| "i_APCI1710_DisablePWM" | +| function | +| 1 : The output signal is set| +| to low after the | +| "i_APCI1710_DisablePWM" | +| function | +| 2 : The output signal is set| +| to high after the | +| "i_APCI1710_DisablePWM" | +| function | +| BYTE_ b_ExternGate : Extern gate action selection | +| 0 : Extern gate signal not | +| used. | +| 1 : Extern gate signal used.| +| BYTE_ b_InterruptEnable : Enable or disable the PWM | +| interrupt. | +| - APCI1710_ENABLE : | +| Enable the PWM interrupt | +| A interrupt occur after | +| each period | +| - APCI1710_DISABLE : | +| Disable the PWM interrupt | ++----------------------------------------------------------------------------+ +| Output Parameters : - | ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: Module selection wrong | +| -3: The module is not a PWM module | +| -4: PWM selection is wrong | +| -5: PWM not initialised see function | +| "i_APCI1710_InitPWM" | +| -6: PWM start level selection is wrong | +| -7: PWM stop mode selection is wrong | +| -8: PWM stop level selection is wrong | +| -9: Extern gate signal selection is wrong | +| -10: Interrupt parameter is wrong | +| -11: Interrupt function not initialised. | +| See function "i_APCI1710_SetBoardIntRoutineX" | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_EnablePWM(struct comedi_device * dev, + BYTE b_ModulNbr, + BYTE b_PWM, + BYTE b_StartLevel, + BYTE b_StopMode, + BYTE b_StopLevel, BYTE b_ExternGate, BYTE b_InterruptEnable) +{ + INT i_ReturnValue = 0; + DWORD dw_Status; + DWORD dw_Command; + + devpriv->tsk_Current = current; // Save the current process task structure + /**************************/ + /* Test the module number */ + /**************************/ + + if (b_ModulNbr < 4) { + /***************/ + /* Test if PWM */ + /***************/ + + if ((devpriv->s_BoardInfos. + dw_MolduleConfiguration[b_ModulNbr] & + 0xFFFF0000UL) == APCI1710_PWM) { + /**************************/ + /* Test the PWM selection */ + /**************************/ + + if (b_PWM <= 1) { + /***************************/ + /* Test if PWM initialised */ + /***************************/ + + dw_Status = inl(devpriv->s_BoardInfos. + ui_Address + 12 + (20 * b_PWM) + + (64 * b_ModulNbr)); + + if (dw_Status & 0x10) { + /**********************************/ + /* Test the start level selection */ + /**********************************/ + + if (b_StartLevel <= 1) { + /**********************/ + /* Test the stop mode */ + /**********************/ + + if (b_StopMode <= 1) { + /***********************/ + /* Test the stop level */ + /***********************/ + + if (b_StopLevel <= 2) { + /*****************************/ + /* Test the extern gate mode */ + /*****************************/ + + if (b_ExternGate + <= 1) { + /*****************************/ + /* Test the interrupt action */ + /*****************************/ + + if (b_InterruptEnable == APCI1710_ENABLE || b_InterruptEnable == APCI1710_DISABLE) { + /******************************************/ + /* Test if interrupt function initialised */ + /******************************************/ + + /********************/ + /* Read the command */ + /********************/ + + dw_Command + = + inl + (devpriv-> + s_BoardInfos. + ui_Address + + + 8 + + + (20 * b_PWM) + (64 * b_ModulNbr)); + + dw_Command + = + dw_Command + & + 0x80; + + /********************/ + /* Make the command */ + /********************/ + + dw_Command + = + dw_Command + | + b_StopMode + | + (b_InterruptEnable + << + 3) + | + (b_ExternGate + << + 4) + | + (b_StartLevel + << + 5); + + if (b_StopLevel & 3) { + dw_Command + = + dw_Command + | + 2; + + if (b_StopLevel & 2) { + dw_Command + = + dw_Command + | + 4; + } + } + + devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_PWMModuleInfo. + s_PWMInfo + [b_PWM]. + b_InterruptEnable + = + b_InterruptEnable; + + /*******************/ + /* Set the command */ + /*******************/ + + outl(dw_Command, devpriv->s_BoardInfos.ui_Address + 8 + (20 * b_PWM) + (64 * b_ModulNbr)); + + /******************/ + /* Enable the PWM */ + /******************/ + outl(1, devpriv->s_BoardInfos.ui_Address + 12 + (20 * b_PWM) + (64 * b_ModulNbr)); + } // if (b_InterruptEnable == APCI1710_ENABLE || b_InterruptEnable == APCI1710_DISABLE) + else { + /********************************/ + /* Interrupt parameter is wrong */ + /********************************/ + DPRINTK("Interrupt parameter is wrong\n"); + i_ReturnValue + = + -10; + } // if (b_InterruptEnable == APCI1710_ENABLE || b_InterruptEnable == APCI1710_DISABLE) + } // if (b_ExternGate >= 0 && b_ExternGate <= 1) + else { + /*****************************************/ + /* Extern gate signal selection is wrong */ + /*****************************************/ + DPRINTK("Extern gate signal selection is wrong\n"); + i_ReturnValue + = + -9; + } // if (b_ExternGate >= 0 && b_ExternGate <= 1) + } // if (b_StopLevel >= 0 && b_StopLevel <= 2) + else { + /*************************************/ + /* PWM stop level selection is wrong */ + /*************************************/ + DPRINTK("PWM stop level selection is wrong\n"); + i_ReturnValue = + -8; + } // if (b_StopLevel >= 0 && b_StopLevel <= 2) + } // if (b_StopMode >= 0 && b_StopMode <= 1) + else { + /************************************/ + /* PWM stop mode selection is wrong */ + /************************************/ + DPRINTK("PWM stop mode selection is wrong\n"); + i_ReturnValue = -7; + } // if (b_StopMode >= 0 && b_StopMode <= 1) + } // if (b_StartLevel >= 0 && b_StartLevel <= 1) + else { + /**************************************/ + /* PWM start level selection is wrong */ + /**************************************/ + DPRINTK("PWM start level selection is wrong\n"); + i_ReturnValue = -6; + } // if (b_StartLevel >= 0 && b_StartLevel <= 1) + } // if (dw_Status & 0x10) + else { + /***********************/ + /* PWM not initialised */ + /***********************/ + DPRINTK("PWM not initialised\n"); + i_ReturnValue = -5; + } // if (dw_Status & 0x10) + } // if (b_PWM >= 0 && b_PWM <= 1) + else { + /******************************/ + /* Tor PWM selection is wrong */ + /******************************/ + DPRINTK("Tor PWM selection is wrong\n"); + i_ReturnValue = -4; + } // if (b_PWM >= 0 && b_PWM <= 1) + } else { + /**********************************/ + /* The module is not a PWM module */ + /**********************************/ + DPRINTK("The module is not a PWM module\n"); + i_ReturnValue = -3; + } + } else { + /***********************/ + /* Module number error */ + /***********************/ + DPRINTK("Module number error\n"); + i_ReturnValue = -2; + } + + return (i_ReturnValue); +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : _INT_ i_APCI1710_DisablePWM (BYTE_ b_BoardHandle, | +| BYTE_ b_ModulNbr, | +| BYTE_ b_PWM) | ++----------------------------------------------------------------------------+ +| Task : Disable the selected PWM (b_PWM) from selected module | +| (b_ModulNbr). The output signal level depend of the | +| initialisation by the "i_APCI1710_EnablePWM". | +| See the b_StartLevel, b_StopMode and b_StopLevel | +| parameters from this function. | ++----------------------------------------------------------------------------+ +| Input Parameters :BYTE_ b_BoardHandle : Handle of board APCI-1710 | +| BYTE_ b_ModulNbr : Selected module number (0 to 3) | +| BYTE_ b_PWM : Selected PWM (0 or 1) | ++----------------------------------------------------------------------------+ +| Output Parameters : - | ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: Module selection wrong | +| -3: The module is not a PWM module | +| -4: PWM selection is wrong | +| -5: PWM not initialised see function | +| "i_APCI1710_InitPWM" | +| -6: PWM not enabled see function | +| "i_APCI1710_EnablePWM" | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_DisablePWM(struct comedi_device * dev, BYTE b_ModulNbr, BYTE b_PWM) +{ + INT i_ReturnValue = 0; + DWORD dw_Status; + + /**************************/ + /* Test the module number */ + /**************************/ + + if (b_ModulNbr < 4) { + /***************/ + /* Test if PWM */ + /***************/ + + if ((devpriv->s_BoardInfos. + dw_MolduleConfiguration[b_ModulNbr] & + 0xFFFF0000UL) == APCI1710_PWM) { + /**************************/ + /* Test the PWM selection */ + /**************************/ + + if (b_PWM <= 1) { + /***************************/ + /* Test if PWM initialised */ + /***************************/ + + dw_Status = inl(devpriv->s_BoardInfos. + ui_Address + 12 + (20 * b_PWM) + + (64 * b_ModulNbr)); + + if (dw_Status & 0x10) { + /***********************/ + /* Test if PWM enabled */ + /***********************/ + + if (dw_Status & 0x1) { + /*******************/ + /* Disable the PWM */ + /*******************/ + outl(0, devpriv->s_BoardInfos. + ui_Address + 12 + + (20 * b_PWM) + + (64 * b_ModulNbr)); + } // if (dw_Status & 0x1) + else { + /*******************/ + /* PWM not enabled */ + /*******************/ + DPRINTK("PWM not enabled\n"); + i_ReturnValue = -6; + } // if (dw_Status & 0x1) + } // if (dw_Status & 0x10) + else { + /***********************/ + /* PWM not initialised */ + /***********************/ + DPRINTK(" PWM not initialised\n"); + i_ReturnValue = -5; + } // if (dw_Status & 0x10) + } // if (b_PWM >= 0 && b_PWM <= 1) + else { + /******************************/ + /* Tor PWM selection is wrong */ + /******************************/ + DPRINTK("Tor PWM selection is wrong\n"); + i_ReturnValue = -4; + } // if (b_PWM >= 0 && b_PWM <= 1) + } else { + /**********************************/ + /* The module is not a PWM module */ + /**********************************/ + DPRINTK("The module is not a PWM module\n"); + i_ReturnValue = -3; + } + } else { + /***********************/ + /* Module number error */ + /***********************/ + DPRINTK("Module number error\n"); + i_ReturnValue = -2; + } + + return (i_ReturnValue); +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : _INT_ i_APCI1710_SetNewPWMTiming | +| (BYTE_ b_BoardHandle, | +| BYTE_ b_ModulNbr, | +| BYTE_ b_PWM, | +| BYTE_ b_ClockSelection, | +| BYTE_ b_TimingUnit, | +| ULONG_ ul_LowTiming, | +| ULONG_ ul_HighTiming) | ++----------------------------------------------------------------------------+ +| Task : Set a new timing. The ul_LowTiming, ul_HighTiming and | +| ul_TimingUnit determine the low/high timing base for | +| the period. | ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 | +| BYTE_ b_ModulNbr : Module number to configure| +| (0 to 3) | +| BYTE_ b_PWM : Selected PWM (0 or 1). | +| BYTE_ b_TimingUnit : Base timing Unit (0 to 4) | +| 0 : ns | +| 1 : æs | +| 2 : ms | +| 3 : s | +| 4 : mn | +| ULONG_ ul_LowTiming : Low base timing value. | +| ULONG_ ul_HighTiming : High base timing value. | ++----------------------------------------------------------------------------+ +| Output Parameters : - | ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: Module selection wrong | +| -3: The module is not a PWM module | +| -4: PWM selection is wrong | +| -5: PWM not initialised | +| -6: Timing Unit selection is wrong | +| -7: Low base timing selection is wrong | +| -8: High base timing selection is wrong | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_SetNewPWMTiming(struct comedi_device * dev, + BYTE b_ModulNbr, + BYTE b_PWM, BYTE b_TimingUnit, ULONG ul_LowTiming, ULONG ul_HighTiming) +{ + BYTE b_ClockSelection; + INT i_ReturnValue = 0; + ULONG ul_LowTimerValue = 0; + ULONG ul_HighTimerValue = 0; + ULONG ul_RealLowTiming = 0; + ULONG ul_RealHighTiming = 0; + DWORD dw_Status; + DWORD dw_Command; + double d_RealLowTiming = 0; + double d_RealHighTiming = 0; + + /**************************/ + /* Test the module number */ + /**************************/ + + if (b_ModulNbr < 4) { + /***************/ + /* Test if PWM */ + /***************/ + + if ((devpriv->s_BoardInfos. + dw_MolduleConfiguration[b_ModulNbr] & + 0xFFFF0000UL) == APCI1710_PWM) { + /**************************/ + /* Test the PWM selection */ + /**************************/ + + if (b_PWM <= 1) { + /***************************/ + /* Test if PWM initialised */ + /***************************/ + + dw_Status = inl(devpriv->s_BoardInfos. + ui_Address + 12 + (20 * b_PWM) + + (64 * b_ModulNbr)); + + if (dw_Status & 0x10) { + b_ClockSelection = devpriv-> + s_ModuleInfo[b_ModulNbr]. + s_PWMModuleInfo. + b_ClockSelection; + + /************************/ + /* Test the timing unit */ + /************************/ + + if (b_TimingUnit <= 4) { + /*********************************/ + /* Test the low timing selection */ + /*********************************/ + + if (((b_ClockSelection == + APCI1710_30MHZ) + && (b_TimingUnit + == 0) + && (ul_LowTiming + >= 266) + && (ul_LowTiming + <= + 0xFFFFFFFFUL)) + || ((b_ClockSelection == + APCI1710_30MHZ) + && (b_TimingUnit + == 1) + && (ul_LowTiming + >= 1) + && (ul_LowTiming + <= + 571230650UL)) + || ((b_ClockSelection == + APCI1710_30MHZ) + && (b_TimingUnit + == 2) + && (ul_LowTiming + >= 1) + && (ul_LowTiming + <= + 571230UL)) + || ((b_ClockSelection == + APCI1710_30MHZ) + && (b_TimingUnit + == 3) + && (ul_LowTiming + >= 1) + && (ul_LowTiming + <= + 571UL)) + || ((b_ClockSelection == + APCI1710_30MHZ) + && (b_TimingUnit + == 4) + && (ul_LowTiming + >= 1) + && (ul_LowTiming + <= 9UL)) + || ((b_ClockSelection == + APCI1710_33MHZ) + && (b_TimingUnit + == 0) + && (ul_LowTiming + >= 242) + && (ul_LowTiming + <= + 0xFFFFFFFFUL)) + || ((b_ClockSelection == + APCI1710_33MHZ) + && (b_TimingUnit + == 1) + && (ul_LowTiming + >= 1) + && (ul_LowTiming + <= + 519691043UL)) + || ((b_ClockSelection == + APCI1710_33MHZ) + && (b_TimingUnit + == 2) + && (ul_LowTiming + >= 1) + && (ul_LowTiming + <= + 519691UL)) + || ((b_ClockSelection == + APCI1710_33MHZ) + && (b_TimingUnit + == 3) + && (ul_LowTiming + >= 1) + && (ul_LowTiming + <= + 520UL)) + || ((b_ClockSelection == + APCI1710_33MHZ) + && (b_TimingUnit + == 4) + && (ul_LowTiming + >= 1) + && (ul_LowTiming + <= 8UL)) + || ((b_ClockSelection == + APCI1710_40MHZ) + && (b_TimingUnit + == 0) + && (ul_LowTiming + >= 200) + && (ul_LowTiming + <= + 0xFFFFFFFFUL)) + || ((b_ClockSelection == + APCI1710_40MHZ) + && (b_TimingUnit + == 1) + && (ul_LowTiming + >= 1) + && (ul_LowTiming + <= + 429496729UL)) + || ((b_ClockSelection == + APCI1710_40MHZ) + && (b_TimingUnit + == 2) + && (ul_LowTiming + >= 1) + && (ul_LowTiming + <= + 429496UL)) + || ((b_ClockSelection == + APCI1710_40MHZ) + && (b_TimingUnit + == 3) + && (ul_LowTiming + >= 1) + && (ul_LowTiming + <= + 429UL)) + || ((b_ClockSelection == + APCI1710_40MHZ) + && (b_TimingUnit + == 4) + && (ul_LowTiming + >= 1) + && (ul_LowTiming + <= + 7UL))) { + /**********************************/ + /* Test the High timing selection */ + /**********************************/ + + if (((b_ClockSelection == APCI1710_30MHZ) && (b_TimingUnit == 0) && (ul_HighTiming >= 266) && (ul_HighTiming <= 0xFFFFFFFFUL)) || ((b_ClockSelection == APCI1710_30MHZ) && (b_TimingUnit == 1) && (ul_HighTiming >= 1) && (ul_HighTiming <= 571230650UL)) || ((b_ClockSelection == APCI1710_30MHZ) && (b_TimingUnit == 2) && (ul_HighTiming >= 1) && (ul_HighTiming <= 571230UL)) || ((b_ClockSelection == APCI1710_30MHZ) && (b_TimingUnit == 3) && (ul_HighTiming >= 1) && (ul_HighTiming <= 571UL)) || ((b_ClockSelection == APCI1710_30MHZ) && (b_TimingUnit == 4) && (ul_HighTiming >= 1) && (ul_HighTiming <= 9UL)) || ((b_ClockSelection == APCI1710_33MHZ) && (b_TimingUnit == 0) && (ul_HighTiming >= 242) && (ul_HighTiming <= 0xFFFFFFFFUL)) || ((b_ClockSelection == APCI1710_33MHZ) && (b_TimingUnit == 1) && (ul_HighTiming >= 1) && (ul_HighTiming <= 519691043UL)) || ((b_ClockSelection == APCI1710_33MHZ) && (b_TimingUnit == 2) && (ul_HighTiming >= 1) && (ul_HighTiming <= 519691UL)) || ((b_ClockSelection == APCI1710_33MHZ) && (b_TimingUnit == 3) && (ul_HighTiming >= 1) && (ul_HighTiming <= 520UL)) || ((b_ClockSelection == APCI1710_33MHZ) && (b_TimingUnit == 4) && (ul_HighTiming >= 1) && (ul_HighTiming <= 8UL)) || ((b_ClockSelection == APCI1710_40MHZ) && (b_TimingUnit == 0) && (ul_HighTiming >= 200) && (ul_HighTiming <= 0xFFFFFFFFUL)) || ((b_ClockSelection == APCI1710_40MHZ) && (b_TimingUnit == 1) && (ul_HighTiming >= 1) && (ul_HighTiming <= 429496729UL)) || ((b_ClockSelection == APCI1710_40MHZ) && (b_TimingUnit == 2) && (ul_HighTiming >= 1) && (ul_HighTiming <= 429496UL)) || ((b_ClockSelection == APCI1710_40MHZ) && (b_TimingUnit == 3) && (ul_HighTiming >= 1) && (ul_HighTiming <= 429UL)) || ((b_ClockSelection == APCI1710_40MHZ) && (b_TimingUnit == 4) && (ul_HighTiming >= 1) && (ul_HighTiming <= 7UL))) { + /************************************/ + /* Calculate the low division fator */ + /************************************/ + + fpu_begin(); + switch (b_TimingUnit) { + /******/ + /* ns */ + /******/ + + case 0: + + /******************/ + /* Timer 0 factor */ + /******************/ + + ul_LowTimerValue + = + (ULONG) + (ul_LowTiming + * + (0.00025 * b_ClockSelection)); + + /*******************/ + /* Round the value */ + /*******************/ + + if ((double)((double)ul_LowTiming * (0.00025 * (double)b_ClockSelection)) >= ((double)((double)ul_LowTimerValue + 0.5))) { + ul_LowTimerValue + = + ul_LowTimerValue + + + 1; + } + + /*****************************/ + /* Calculate the real timing */ + /*****************************/ + + ul_RealLowTiming + = + (ULONG) + (ul_LowTimerValue + / + (0.00025 * (double)b_ClockSelection)); + d_RealLowTiming + = + (double) + ul_LowTimerValue + / + (0.00025 + * + (double) + b_ClockSelection); + + if ((double)((double)ul_LowTimerValue / (0.00025 * (double)b_ClockSelection)) >= (double)((double)ul_RealLowTiming + 0.5)) { + ul_RealLowTiming + = + ul_RealLowTiming + + + 1; + } + + ul_LowTiming + = + ul_LowTiming + - + 1; + ul_LowTimerValue + = + ul_LowTimerValue + - + 2; + + if (b_ClockSelection != APCI1710_40MHZ) { + ul_LowTimerValue + = + (ULONG) + ( + (double) + (ul_LowTimerValue) + * + 1.007752288); + } + + break; + + /******/ + /* æs */ + /******/ + + case 1: + + /******************/ + /* Timer 0 factor */ + /******************/ + + ul_LowTimerValue + = + (ULONG) + (ul_LowTiming + * + (0.25 * b_ClockSelection)); + + /*******************/ + /* Round the value */ + /*******************/ + + if ((double)((double)ul_LowTiming * (0.25 * (double)b_ClockSelection)) >= ((double)((double)ul_LowTimerValue + 0.5))) { + ul_LowTimerValue + = + ul_LowTimerValue + + + 1; + } + + /*****************************/ + /* Calculate the real timing */ + /*****************************/ + + ul_RealLowTiming + = + (ULONG) + (ul_LowTimerValue + / + (0.25 * (double)b_ClockSelection)); + d_RealLowTiming + = + (double) + ul_LowTimerValue + / + ( + (double) + 0.25 + * + (double) + b_ClockSelection); + + if ((double)((double)ul_LowTimerValue / (0.25 * (double)b_ClockSelection)) >= (double)((double)ul_RealLowTiming + 0.5)) { + ul_RealLowTiming + = + ul_RealLowTiming + + + 1; + } + + ul_LowTiming + = + ul_LowTiming + - + 1; + ul_LowTimerValue + = + ul_LowTimerValue + - + 2; + + if (b_ClockSelection != APCI1710_40MHZ) { + ul_LowTimerValue + = + (ULONG) + ( + (double) + (ul_LowTimerValue) + * + 1.007752288); + } + + break; + + /******/ + /* ms */ + /******/ + + case 2: + + /******************/ + /* Timer 0 factor */ + /******************/ + + ul_LowTimerValue + = + ul_LowTiming + * + (250.0 + * + b_ClockSelection); + + /*******************/ + /* Round the value */ + /*******************/ + + if ((double)((double)ul_LowTiming * (250.0 * (double)b_ClockSelection)) >= ((double)((double)ul_LowTimerValue + 0.5))) { + ul_LowTimerValue + = + ul_LowTimerValue + + + 1; + } + + /*****************************/ + /* Calculate the real timing */ + /*****************************/ + + ul_RealLowTiming + = + (ULONG) + (ul_LowTimerValue + / + (250.0 * (double)b_ClockSelection)); + d_RealLowTiming + = + (double) + ul_LowTimerValue + / + (250.0 + * + (double) + b_ClockSelection); + + if ((double)((double)ul_LowTimerValue / (250.0 * (double)b_ClockSelection)) >= (double)((double)ul_RealLowTiming + 0.5)) { + ul_RealLowTiming + = + ul_RealLowTiming + + + 1; + } + + ul_LowTiming + = + ul_LowTiming + - + 1; + ul_LowTimerValue + = + ul_LowTimerValue + - + 2; + + if (b_ClockSelection != APCI1710_40MHZ) { + ul_LowTimerValue + = + (ULONG) + ( + (double) + (ul_LowTimerValue) + * + 1.007752288); + } + + break; + + /*****/ + /* s */ + /*****/ + + case 3: + + /******************/ + /* Timer 0 factor */ + /******************/ + + ul_LowTimerValue + = + (ULONG) + (ul_LowTiming + * + (250000.0 + * + b_ClockSelection)); + + /*******************/ + /* Round the value */ + /*******************/ + + if ((double)((double)ul_LowTiming * (250000.0 * (double)b_ClockSelection)) >= ((double)((double)ul_LowTimerValue + 0.5))) { + ul_LowTimerValue + = + ul_LowTimerValue + + + 1; + } + + /*****************************/ + /* Calculate the real timing */ + /*****************************/ + + ul_RealLowTiming + = + (ULONG) + (ul_LowTimerValue + / + (250000.0 + * + (double) + b_ClockSelection)); + d_RealLowTiming + = + (double) + ul_LowTimerValue + / + (250000.0 + * + (double) + b_ClockSelection); + + if ((double)((double)ul_LowTimerValue / (250000.0 * (double)b_ClockSelection)) >= (double)((double)ul_RealLowTiming + 0.5)) { + ul_RealLowTiming + = + ul_RealLowTiming + + + 1; + } + + ul_LowTiming + = + ul_LowTiming + - + 1; + ul_LowTimerValue + = + ul_LowTimerValue + - + 2; + + if (b_ClockSelection != APCI1710_40MHZ) { + ul_LowTimerValue + = + (ULONG) + ( + (double) + (ul_LowTimerValue) + * + 1.007752288); + } + + break; + + /******/ + /* mn */ + /******/ + + case 4: + + /******************/ + /* Timer 0 factor */ + /******************/ + + ul_LowTimerValue + = + (ULONG) + ( + (ul_LowTiming + * + 60) + * + (250000.0 + * + b_ClockSelection)); + + /*******************/ + /* Round the value */ + /*******************/ + + if ((double)((double)(ul_LowTiming * 60.0) * (250000.0 * (double)b_ClockSelection)) >= ((double)((double)ul_LowTimerValue + 0.5))) { + ul_LowTimerValue + = + ul_LowTimerValue + + + 1; + } + + /*****************************/ + /* Calculate the real timing */ + /*****************************/ + + ul_RealLowTiming + = + (ULONG) + (ul_LowTimerValue + / + (250000.0 + * + (double) + b_ClockSelection)) + / + 60; + d_RealLowTiming + = + ( + (double) + ul_LowTimerValue + / + (250000.0 + * + (double) + b_ClockSelection)) + / + 60.0; + + if ((double)(((double)ul_LowTimerValue / (250000.0 * (double)b_ClockSelection)) / 60.0) >= (double)((double)ul_RealLowTiming + 0.5)) { + ul_RealLowTiming + = + ul_RealLowTiming + + + 1; + } + + ul_LowTiming + = + ul_LowTiming + - + 1; + ul_LowTimerValue + = + ul_LowTimerValue + - + 2; + + if (b_ClockSelection != APCI1710_40MHZ) { + ul_LowTimerValue + = + (ULONG) + ( + (double) + (ul_LowTimerValue) + * + 1.007752288); + } + + break; + } + + /*************************************/ + /* Calculate the high division fator */ + /*************************************/ + + switch (b_TimingUnit) { + /******/ + /* ns */ + /******/ + + case 0: + + /******************/ + /* Timer 0 factor */ + /******************/ + + ul_HighTimerValue + = + (ULONG) + (ul_HighTiming + * + (0.00025 * b_ClockSelection)); + + /*******************/ + /* Round the value */ + /*******************/ + + if ((double)((double)ul_HighTiming * (0.00025 * (double)b_ClockSelection)) >= ((double)((double)ul_HighTimerValue + 0.5))) { + ul_HighTimerValue + = + ul_HighTimerValue + + + 1; + } + + /*****************************/ + /* Calculate the real timing */ + /*****************************/ + + ul_RealHighTiming + = + (ULONG) + (ul_HighTimerValue + / + (0.00025 * (double)b_ClockSelection)); + d_RealHighTiming + = + (double) + ul_HighTimerValue + / + (0.00025 + * + (double) + b_ClockSelection); + + if ((double)((double)ul_HighTimerValue / (0.00025 * (double)b_ClockSelection)) >= (double)((double)ul_RealHighTiming + 0.5)) { + ul_RealHighTiming + = + ul_RealHighTiming + + + 1; + } + + ul_HighTiming + = + ul_HighTiming + - + 1; + ul_HighTimerValue + = + ul_HighTimerValue + - + 2; + + if (b_ClockSelection != APCI1710_40MHZ) { + ul_HighTimerValue + = + (ULONG) + ( + (double) + (ul_HighTimerValue) + * + 1.007752288); + } + + break; + + /******/ + /* æs */ + /******/ + + case 1: + + /******************/ + /* Timer 0 factor */ + /******************/ + + ul_HighTimerValue + = + (ULONG) + (ul_HighTiming + * + (0.25 * b_ClockSelection)); + + /*******************/ + /* Round the value */ + /*******************/ + + if ((double)((double)ul_HighTiming * (0.25 * (double)b_ClockSelection)) >= ((double)((double)ul_HighTimerValue + 0.5))) { + ul_HighTimerValue + = + ul_HighTimerValue + + + 1; + } + + /*****************************/ + /* Calculate the real timing */ + /*****************************/ + + ul_RealHighTiming + = + (ULONG) + (ul_HighTimerValue + / + (0.25 * (double)b_ClockSelection)); + d_RealHighTiming + = + (double) + ul_HighTimerValue + / + ( + (double) + 0.25 + * + (double) + b_ClockSelection); + + if ((double)((double)ul_HighTimerValue / (0.25 * (double)b_ClockSelection)) >= (double)((double)ul_RealHighTiming + 0.5)) { + ul_RealHighTiming + = + ul_RealHighTiming + + + 1; + } + + ul_HighTiming + = + ul_HighTiming + - + 1; + ul_HighTimerValue + = + ul_HighTimerValue + - + 2; + + if (b_ClockSelection != APCI1710_40MHZ) { + ul_HighTimerValue + = + (ULONG) + ( + (double) + (ul_HighTimerValue) + * + 1.007752288); + } + + break; + + /******/ + /* ms */ + /******/ + + case 2: + + /******************/ + /* Timer 0 factor */ + /******************/ + + ul_HighTimerValue + = + ul_HighTiming + * + (250.0 + * + b_ClockSelection); + + /*******************/ + /* Round the value */ + /*******************/ + + if ((double)((double)ul_HighTiming * (250.0 * (double)b_ClockSelection)) >= ((double)((double)ul_HighTimerValue + 0.5))) { + ul_HighTimerValue + = + ul_HighTimerValue + + + 1; + } + + /*****************************/ + /* Calculate the real timing */ + /*****************************/ + + ul_RealHighTiming + = + (ULONG) + (ul_HighTimerValue + / + (250.0 * (double)b_ClockSelection)); + d_RealHighTiming + = + (double) + ul_HighTimerValue + / + (250.0 + * + (double) + b_ClockSelection); + + if ((double)((double)ul_HighTimerValue / (250.0 * (double)b_ClockSelection)) >= (double)((double)ul_RealHighTiming + 0.5)) { + ul_RealHighTiming + = + ul_RealHighTiming + + + 1; + } + + ul_HighTiming + = + ul_HighTiming + - + 1; + ul_HighTimerValue + = + ul_HighTimerValue + - + 2; + + if (b_ClockSelection != APCI1710_40MHZ) { + ul_HighTimerValue + = + (ULONG) + ( + (double) + (ul_HighTimerValue) + * + 1.007752288); + } + + break; + + /*****/ + /* s */ + /*****/ + + case 3: + + /******************/ + /* Timer 0 factor */ + /******************/ + + ul_HighTimerValue + = + (ULONG) + (ul_HighTiming + * + (250000.0 + * + b_ClockSelection)); + + /*******************/ + /* Round the value */ + /*******************/ + + if ((double)((double)ul_HighTiming * (250000.0 * (double)b_ClockSelection)) >= ((double)((double)ul_HighTimerValue + 0.5))) { + ul_HighTimerValue + = + ul_HighTimerValue + + + 1; + } + + /*****************************/ + /* Calculate the real timing */ + /*****************************/ + + ul_RealHighTiming + = + (ULONG) + (ul_HighTimerValue + / + (250000.0 + * + (double) + b_ClockSelection)); + d_RealHighTiming + = + (double) + ul_HighTimerValue + / + (250000.0 + * + (double) + b_ClockSelection); + + if ((double)((double)ul_HighTimerValue / (250000.0 * (double)b_ClockSelection)) >= (double)((double)ul_RealHighTiming + 0.5)) { + ul_RealHighTiming + = + ul_RealHighTiming + + + 1; + } + + ul_HighTiming + = + ul_HighTiming + - + 1; + ul_HighTimerValue + = + ul_HighTimerValue + - + 2; + + if (b_ClockSelection != APCI1710_40MHZ) { + ul_HighTimerValue + = + (ULONG) + ( + (double) + (ul_HighTimerValue) + * + 1.007752288); + } + + break; + + /******/ + /* mn */ + /******/ + + case 4: + + /******************/ + /* Timer 0 factor */ + /******************/ + + ul_HighTimerValue + = + (ULONG) + ( + (ul_HighTiming + * + 60) + * + (250000.0 + * + b_ClockSelection)); + + /*******************/ + /* Round the value */ + /*******************/ + + if ((double)((double)(ul_HighTiming * 60.0) * (250000.0 * (double)b_ClockSelection)) >= ((double)((double)ul_HighTimerValue + 0.5))) { + ul_HighTimerValue + = + ul_HighTimerValue + + + 1; + } + + /*****************************/ + /* Calculate the real timing */ + /*****************************/ + + ul_RealHighTiming + = + (ULONG) + (ul_HighTimerValue + / + (250000.0 + * + (double) + b_ClockSelection)) + / + 60; + d_RealHighTiming + = + ( + (double) + ul_HighTimerValue + / + (250000.0 + * + (double) + b_ClockSelection)) + / + 60.0; + + if ((double)(((double)ul_HighTimerValue / (250000.0 * (double)b_ClockSelection)) / 60.0) >= (double)((double)ul_RealHighTiming + 0.5)) { + ul_RealHighTiming + = + ul_RealHighTiming + + + 1; + } + + ul_HighTiming + = + ul_HighTiming + - + 1; + ul_HighTimerValue + = + ul_HighTimerValue + - + 2; + + if (b_ClockSelection != APCI1710_40MHZ) { + ul_HighTimerValue + = + (ULONG) + ( + (double) + (ul_HighTimerValue) + * + 1.007752288); + } + + break; + } + + fpu_end(); + + /************************/ + /* Save the timing unit */ + /************************/ + + devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_PWMModuleInfo. + s_PWMInfo + [b_PWM]. + b_TimingUnit + = + b_TimingUnit; + + /****************************/ + /* Save the low base timing */ + /****************************/ + + devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_PWMModuleInfo. + s_PWMInfo + [b_PWM]. + d_LowTiming + = + d_RealLowTiming; + + devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_PWMModuleInfo. + s_PWMInfo + [b_PWM]. + ul_RealLowTiming + = + ul_RealLowTiming; + + /****************************/ + /* Save the high base timing */ + /****************************/ + + devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_PWMModuleInfo. + s_PWMInfo + [b_PWM]. + d_HighTiming + = + d_RealHighTiming; + + devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_PWMModuleInfo. + s_PWMInfo + [b_PWM]. + ul_RealHighTiming + = + ul_RealHighTiming; + + /************************/ + /* Write the low timing */ + /************************/ + + outl(ul_LowTimerValue, devpriv->s_BoardInfos.ui_Address + 0 + (20 * b_PWM) + (64 * b_ModulNbr)); + + /*************************/ + /* Write the high timing */ + /*************************/ + + outl(ul_HighTimerValue, devpriv->s_BoardInfos.ui_Address + 4 + (20 * b_PWM) + (64 * b_ModulNbr)); + + /***************************/ + /* Set the clock selection */ + /***************************/ + + dw_Command = + inl + (devpriv-> + s_BoardInfos. + ui_Address + + 8 + + (20 * b_PWM) + (64 * b_ModulNbr)); + + dw_Command = + dw_Command + & 0x7F; + + if (b_ClockSelection == APCI1710_40MHZ) { + dw_Command + = + dw_Command + | + 0x80; + } + + /***************************/ + /* Set the clock selection */ + /***************************/ + + outl(dw_Command, + devpriv-> + s_BoardInfos. + ui_Address + + 8 + + (20 * b_PWM) + (64 * b_ModulNbr)); + } else { + /***************************************/ + /* High base timing selection is wrong */ + /***************************************/ + DPRINTK("High base timing selection is wrong\n"); + i_ReturnValue = + -8; + } + } else { + /**************************************/ + /* Low base timing selection is wrong */ + /**************************************/ + DPRINTK("Low base timing selection is wrong\n"); + i_ReturnValue = -7; + } + } // if ((b_TimingUnit >= 0) && (b_TimingUnit <= 4)) + else { + /**********************************/ + /* Timing unit selection is wrong */ + /**********************************/ + DPRINTK("Timing unit selection is wrong\n"); + i_ReturnValue = -6; + } // if ((b_TimingUnit >= 0) && (b_TimingUnit <= 4)) + } // if (dw_Status & 0x10) + else { + /***********************/ + /* PWM not initialised */ + /***********************/ + DPRINTK("PWM not initialised\n"); + i_ReturnValue = -5; + } // if (dw_Status & 0x10) + } // if (b_PWM >= 0 && b_PWM <= 1) + else { + /******************************/ + /* Tor PWM selection is wrong */ + /******************************/ + DPRINTK("Tor PWM selection is wrong\n"); + i_ReturnValue = -4; + } // if (b_PWM >= 0 && b_PWM <= 1) + } else { + /**********************************/ + /* The module is not a PWM module */ + /**********************************/ + DPRINTK("The module is not a PWM module\n"); + i_ReturnValue = -3; + } + } else { + /***********************/ + /* Module number error */ + /***********************/ + DPRINTK("Module number error\n"); + i_ReturnValue = -2; + } + + return (i_ReturnValue); +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : _INT_ i_APCI1710_GetPWMStatus | +| (BYTE_ b_BoardHandle, | +| BYTE_ b_ModulNbr, | +| BYTE_ b_PWM, | +| PBYTE_ pb_PWMOutputStatus, | +| PBYTE_ pb_ExternGateStatus) | ++----------------------------------------------------------------------------+ +| Task : Return the status from selected PWM (b_PWM) from | +| selected module (b_ModulNbr). | ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 | +| BYTE_ b_PWM : Selected PWM (0 or 1) | +| BYTE_ b_ModulNbr : Selected module number (0 to 3) + b_ModulNbr =(BYTE) CR_AREF(insn->chanspec); + b_PWM =(BYTE) data[0]; + + | ++----------------------------------------------------------------------------+ +| Output Parameters : PBYTE_ pb_PWMOutputStatus : Return the PWM output | +| level status. | +| 0 : The PWM output level| +| is low. | +| 1 : The PWM output level| +| is high. | +| PBYTE_ pb_ExternGateStatus : Return the extern gate | +| level status. | +| 0 : The extern gate is | +| low. | +| 1 : The extern gate is | +| high. + pb_PWMOutputStatus =(PBYTE) data[0]; + pb_ExternGateStatus =(PBYTE) data[1]; | ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: Module selection wrong | +| -3: The module is not a PWM module | +| -4: PWM selection is wrong | +| -5: PWM not initialised see function | +| "i_APCI1710_InitPWM" | +| -6: PWM not enabled see function "i_APCI1710_EnablePWM"| ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_InsnReadGetPWMStatus(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + INT i_ReturnValue = 0; + DWORD dw_Status; + + BYTE b_ModulNbr; + BYTE b_PWM; + PBYTE pb_PWMOutputStatus; + PBYTE pb_ExternGateStatus; + + i_ReturnValue = insn->n; + b_ModulNbr = (BYTE) CR_AREF(insn->chanspec); + b_PWM = (BYTE) CR_CHAN(insn->chanspec); + pb_PWMOutputStatus = (PBYTE) & data[0]; + pb_ExternGateStatus = (PBYTE) & data[1]; + + /**************************/ + /* Test the module number */ + /**************************/ + + if (b_ModulNbr < 4) { + /***************/ + /* Test if PWM */ + /***************/ + + if ((devpriv->s_BoardInfos. + dw_MolduleConfiguration[b_ModulNbr] & + 0xFFFF0000UL) == APCI1710_PWM) { + /**************************/ + /* Test the PWM selection */ + /**************************/ + + if (b_PWM <= 1) { + /***************************/ + /* Test if PWM initialised */ + /***************************/ + + dw_Status = inl(devpriv->s_BoardInfos. + ui_Address + 12 + (20 * b_PWM) + + (64 * b_ModulNbr)); + + if (dw_Status & 0x10) { + /***********************/ + /* Test if PWM enabled */ + /***********************/ + + if (dw_Status & 0x1) { + *pb_PWMOutputStatus = + (BYTE) ((dw_Status >> 7) + & 1); + *pb_ExternGateStatus = + (BYTE) ((dw_Status >> 6) + & 1); + } // if (dw_Status & 0x1) + else { + /*******************/ + /* PWM not enabled */ + /*******************/ + + DPRINTK("PWM not enabled \n"); + i_ReturnValue = -6; + } // if (dw_Status & 0x1) + } // if (dw_Status & 0x10) + else { + /***********************/ + /* PWM not initialised */ + /***********************/ + + DPRINTK("PWM not initialised\n"); + i_ReturnValue = -5; + } // if (dw_Status & 0x10) + } // if (b_PWM >= 0 && b_PWM <= 1) + else { + /******************************/ + /* Tor PWM selection is wrong */ + /******************************/ + + DPRINTK("Tor PWM selection is wrong\n"); + i_ReturnValue = -4; + } // if (b_PWM >= 0 && b_PWM <= 1) + } else { + /**********************************/ + /* The module is not a PWM module */ + /**********************************/ + + DPRINTK("The module is not a PWM module\n"); + i_ReturnValue = -3; + } + } else { + /***********************/ + /* Module number error */ + /***********************/ + + DPRINTK("Module number error\n"); + i_ReturnValue = -2; + } + + return (i_ReturnValue); +} + +INT i_APCI1710_InsnBitsReadPWMInterrupt(struct comedi_device * dev, + struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data) +{ + data[0] = devpriv->s_InterruptParameters. + s_FIFOInterruptParameters[devpriv-> + s_InterruptParameters.ui_Read].b_OldModuleMask; + data[1] = devpriv->s_InterruptParameters. + s_FIFOInterruptParameters[devpriv-> + s_InterruptParameters.ui_Read].ul_OldInterruptMask; + data[2] = devpriv->s_InterruptParameters. + s_FIFOInterruptParameters[devpriv-> + s_InterruptParameters.ui_Read].ul_OldCounterLatchValue; + + /**************************/ + /* Increment the read FIFO */ + /***************************/ + + devpriv-> + s_InterruptParameters. + ui_Read = (devpriv-> + s_InterruptParameters.ui_Read + 1) % APCI1710_SAVE_INTERRUPT; + + return insn->n; + +} |