?? driver.c
字號:
//--------------------------------------------------------------------------d
//
// PCL-836 Driver
//
//--------------------------------------------------------------------------
#include <dos.h>
#include <stdio.h>
#include <bios.h>
#include <conio.h>
#include <stdlib.h>
#include "..\driver.h"
// Global variables
USHORT usBaseAddr[10] = {0,0,0,0,0,0,0,0,0,0}; // save base address location
USHORT usPreState[10][2]; // digital output previous state
USHORT usFirstCount[10][6]; // first read counter value for event counter
ULONG ulOverflow[10][6]; // overflow flag for event counter
USHORT usPreCount[10][6]; // previous count state for event counter
USHORT usFoutCtrReg[10]; // frequency output control register
USHORT usModeCtrReg[10][6]; // control clock input mode control register
// Function prototypes
ULONG DoSection(USHORT ,USHORT, USHORT ,USHORT);
ULONG DiSection(USHORT, USHORT, USHORT *);
ULONG GetDoStatus(USHORT, USHORT, USHORT *);
//-------------------------------------------------------------------
// Function : DeviceOpen
// PURPOSE : Retrieves the parameters pertaining to the device
// operation from Global Variable , and store it for
// quick reference. This function must be called
// before any other functions
// Parameters : DeviceNumber (IN), BaseAddr(OUT)
// Return : NULL (success)
// ErrorCode (failure)
// Call/Called procedure cross reference :
// Call Called Explanation
//------------------------------------------------------------------
ULONG DeviceOpen(USHORT DeviceNumber, USHORT BaseAddr)
{
USHORT usIndex;
// Is DeviceNumber out of range ?
if (DeviceNumber > MaxBoardNumber)
return ((ULONG) InvalidDeviceNumber);
// Is BaseAddr valid ?
if (BaseAddr == NULL)
return ((ULONG) InvalidBaseAddr);
// Is BaseAddr in use ?
if (usBaseAddr[DeviceNumber] != NULL)
return ((ULONG) DeviceIsBusy); // If you have this error, you
// can call DeviceClose to reset it.
// everything is OK then initiate some Global variables by DeviceNumber
usPreState[DeviceNumber][0] = 0; // for digital output port 0
usPreState[DeviceNumber][1] = 0; // for digital output port 1
for (usIndex=0 ; usIndex < MaxCounterNumber ; usIndex++)
{
// use by event counter
usFirstCount[DeviceNumber][usIndex] = 0;
ulOverflow[DeviceNumber][usIndex] = 0;
usPreCount[DeviceNumber][usIndex] = 0;
usFoutCtrReg[DeviceNumber] = 0;
usModeCtrReg[DeviceNumber][usIndex] = 0;
}
// set Global variable by DeviceNumber
usBaseAddr[DeviceNumber] = BaseAddr;
// return success
return ((ULONG) NULL);
}
//------------------------------------------------------------------
// Function : DeviceClose
// PURPOSE : Resets Device by DeviceNumber.
// Parameters : DeviceNumber (IN)
// Return : NULL (success)
// ErrorCode (failure)
// Call/Called procedure cross reference :
// Call Called Explanation
// CounterReset
//------------------------------------------------------------------
ULONG DeviceClose(USHORT DeviceNumber)
{
USHORT usIndex;
// Is DeviceNumber out of range ?
if (DeviceNumber > MaxBoardNumber)
return ((ULONG) InvalidDeviceNumber);
// Is BaseAddr valid ?
if (usBaseAddr[DeviceNumber] == NULL)
return ((ULONG) LostBaseAddr);
// Reset counters by DeviceNumber
for (usIndex=0 ; usIndex < MaxCounterNumber ; usIndex++)
CounterReset(DeviceNumber, usIndex);
// Reset Golbal variable
usBaseAddr[DeviceNumber] = 0;
return ((ULONG) NULL);
}
//------------------------------------------------------------------
// Function : CounterConfig
// PURPOSE : This function config the counter mode of specified counter
// (default is positive edge without filter)
// Parameters : DeviceNumber(IN), counter(IN), CounterEdge(IN)
// MaxInFreq(IN)
// 312K is high limitation of MaxInFreq.
// Return : NULL (success)
// ErrorCode (failure)
// Call/Called procedure cross reference :
// Call Called Explanation
//------------------------------------------------------------------
extern ULONG CounterConfig(USHORT DeviceNumber, USHORT counter,
USHORT CounterEdge, FLOAT MaxInFreq)
{
USHORT usCount;
USHORT usCtrByte, usLowByte, usHighByte;
ULONG retCode;
FLOAT fFout;
// Is DeviceNumber out of range ?
if (DeviceNumber > MaxBoardNumber)
return ((ULONG) InvalidDeviceNumber);
// Is BaseAddr valid ?
if (usBaseAddr[DeviceNumber] == NULL)
return ((ULONG) LostBaseAddr);
// check input param correct ?
if (counter > MaxCounterNumber)
return((ULONG) InvalidCounterChannel);
// check MaxInFreq is out of range ?
if (MaxInFreq > (FLOAT)312000.0)
return((ULONG) InvalidFreqRange);
usModeCtrReg[DeviceNumber][counter] = 0x00;
if (CounterEdge == 1) // this mode is negative edge
usModeCtrReg[DeviceNumber][counter] = 0x04;
if (MaxInFreq != (FLOAT)0.0)
{
// set control with digital filter
usModeCtrReg[DeviceNumber][counter] |= 0x01;
// set filter wide
fFout = MaxInFreq*8*2;
retCode = FreqOutStart(DeviceNumber, counter, fFout);
if (retCode != 0L)
return(retCode);
}
return ((ULONG) 0);
}
//------------------------------------------------------------------
// Function : CounterPulseStart
// PURPOSE : Configures the specified counter for pulse
// output and starts the counter.
// Parameters : DeviceNumber(IN), counter(IN),
// period(IN) in ms
// UpCycle(IN) in ms
// Return : NULL (success)
// ErrorCode (failure)
// Call/Called procedure cross reference :
// Call Called Explanation
//------------------------------------------------------------------
ULONG CounterPulseStart(USHORT DeviceNumber,USHORT counter,
FLOAT period, FLOAT UpCycle)
{
USHORT usBase;
DWORD divisor;
USHORT usCtrByte, usLowByte, usHighByte;
FLOAT fUserHz;
FLOAT fFout;
USHORT usCount0, usCount3;
ULONG retCode;
// Is DeviceNumber out of range ?
if (DeviceNumber > MaxBoardNumber)
return ((ULONG) InvalidDeviceNumber);
// Is BaseAddr valid ?
if (usBaseAddr[DeviceNumber] == NULL)
return ((ULONG) LostBaseAddr);
// check input param correct ?
if (counter > MaxPWMNumber)
return((ULONG) InvalidCounterChannel);
// check Period is out of range ?
if ((period > (FLOAT)10000) || (UpCycle > (FLOAT)10000) ||
(period == 0) || (UpCycle == 0) ||
(UpCycle >= period))
return((ULONG) InvalidInputParam);
// get base address
usBase = usBaseAddr[DeviceNumber];
/* configure counter for external clocking */
outportb(usBase+counter+18, 0x03);
// configures counter 0 and counter 3 (for PWM channel 0)
// configures counter 1 and counter 4 (for PWM channel 1)
// configures counter 2 and counter 5 (for PWM channel 2)
fUserHz = (FLOAT)((FLOAT)1.0/period)*1000;
if (fUserHz > (FLOAT)2500000.0) // check out of 2.5Mhz
return((ULONG) InvalidFreqRange);
// FOUT select
if (fUserHz >= (FLOAT)F100HZ)
fFout = (FLOAT)5000000.0;
else if (fUserHz >= (FLOAT)F10HZ)
fFout = (FLOAT)500000.0;
else if (fUserHz >= (FLOAT)F1HZ)
fFout = (FLOAT)50000.0;
else if (fUserHz >= (FLOAT)F0_1HZ)
fFout = (FLOAT)5000.0;
usCount3 = (USHORT)(fFout/fUserHz);
// FOUT enable
retCode = FreqOutStart(DeviceNumber, counter, fFout);
if (retCode != 0L)
return(retCode);
// set counter 3 (or 4, 5)
usCtrByte = (counter%3) << 6;
usCtrByte |= 0x34;
usLowByte = (USHORT)(usCount3 & 0x000000FF);
usHighByte = (USHORT)((usCount3 & 0x0000FF00) >> 8);
outportb(usBase+counter+21, 0x02); /* set internal clock */
outportb(usBase+15, usCtrByte);
outportb(usBase+counter+12, usLowByte); /* write low byte */
outportb(usBase+counter+12, usHighByte); /* write high byte */
// set counter 0 (or 1, 2)
usCount0 = usCount3*((FLOAT)(period-UpCycle)/period);
usCtrByte = (counter%3) << 6;
usCtrByte |= 0x3a;
usLowByte = (USHORT)(usCount0 & 0x000000FF);
usHighByte = (USHORT)((usCount0 & 0x0000FF00) >> 8);
outportb(usBase+counter+18, 0x03); /* set internal clock */
outportb(usBase+11, usCtrByte);
outportb(usBase+counter+8, usLowByte); /* write low byte */
outportb(usBase+counter+8, usHighByte); /* write high byte */
return 0L;
}
//------------------------------------------------------------------
// Function : FreqOutStart
// PURPOSE : Configures the specified counter for frequency output
// and starts the counter. (internal base clock is 10MHZ)
// Parameters : DeviceNumber(IN), counter(IN), fout(IN)
// fout range is from 153HZ to 5MHZ
// Return : NULL (success)
// ErrorCode (failure)
// Call/Called procedure cross reference :
// Call Called Explanation
//------------------------------------------------------------------
ULONG FreqOutStart(USHORT DeviceNumber, USHORT counter, FLOAT fout)
{
USHORT usBase, usCount;
USHORT usCtrByte, usLowByte, usHighByte;
FLOAT fBalance;
// Is DeviceNumber out of range ?
if (DeviceNumber > MaxBoardNumber)
return ((ULONG) InvalidDeviceNumber);
// Is BaseAddr valid ?
if (usBaseAddr[DeviceNumber] == NULL)
return ((ULONG) LostBaseAddr);
// check input param correct ?
if (counter > MaxCounterNumber)
return((ULONG) InvalidCounterChannel);
// get base address
usBase = usBaseAddr[DeviceNumber];
// check input fout is out of range ?
if (( fout > (float)5000000.0) || ( fout < (float)153.0))
return((ULONG) InvalidFreqRange);
fBalance = (float)10000000.0f / fout;
usCount = (USHORT) fBalance;
if (((FLOAT)fBalance*10 - (FLOAT)usCount*10) > 4)
usCount ++;
usLowByte = (USHORT)(usCount & 0x000000FF);
usHighByte = (USHORT)((usCount & 0x0000FF00) >> 8);
usCtrByte = (counter%3) << 6;
usCtrByte |= 0x36;
if (counter < 3)
{
outportb(usBase+3, usCtrByte); // Mode 3
outportb(usBase+counter, usLowByte); /* write low byte */
outportb(usBase+counter, usHighByte); /* write high byte */
}
else
{
outportb(usBase+7, usCtrByte); // Mode 3
outportb(usBase+(counter%3)+4, usLowByte); /* write low byte */
outportb(usBase+(counter%3)+4, usHighByte); /* write high byte */
}
// enable frequency output control reg.
usCtrByte = 0x01;
usCtrByte = usCtrByte << counter;
usFoutCtrReg[DeviceNumber] |= usCtrByte;
outportb(usBase+24, usFoutCtrReg[DeviceNumber]);
return 0L;
}
//------------------------------------------------------------------
// Function : FreqOutStop
// PURPOSE : This function stop the Frequency out of specified counter
// Parameters : DeviceNumber(IN), counter(IN)
// Return : NULL (success)
// ErrorCode (failure)
// Call/Called procedure cross reference :
// Call Called Explanation
//------------------------------------------------------------------
ULONG FreqOutReset(USHORT DeviceNumber, USHORT counter)
{
USHORT usBase, usCtrByte;
// Is DeviceNumber out of range ?
if (DeviceNumber > MaxBoardNumber)
return ((ULONG) InvalidDeviceNumber);
// Is BaseAddr valid ?
if (usBaseAddr[DeviceNumber] == NULL)
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -