unit k9cio;
{
   Moduli k9c-IO -kortin .dll kirjaston kutsuille.

   Author:  Vesa Lappalainen
   Date:    15.3.1997
   Changes: 29.12.1997

   Tipin lisäykset:

   EnableBitIrq(i,b);        // kovo keskeytys => mahdollista
   SetBitInputDFilter(i,0);  // 0 = 0.1 ms, 1=0.5 ms, 2= ms, 3=50 ms
   WaitBitConditionOn(i,timeout,handle); // => 0 = bit, 10 = stop,
                   Off                   // 100 = set handle, 1000 = timeout
   SendStopEvent;           // Kaikki sammuu



}

interface
// Default virtual counters:
const CntFysVirDef = 1;

type iword = integer;
type Handle = integer;

//const nGates = 6;
//const nBits = nGates*8;

const CounterCount = 12;  // clk + 3 counters
const clkFys  : integer = 2;
const cntFys  : integer = 1;
const cntFys2 : integer = 3;
const cntFys3 : integer = 4;
const cntFys4 : integer = 5;
const cntFys5 : integer = 7;
const cntFys6 : integer = 8;
const cntFys7 : integer = 9;
const cntFys8 : integer = 11;
const cntFys9 : integer = 12;
const cntFys10 : integer = 13;
const cntFys11 : integer = 15;
const cntFys12 : integer = 16;

const CounterIndexPointers : array[0..CounterCount] of ^integer =
  (@clkFys,  @cntFys,  @cntFys2,@cntFys3,
   @cntFys4, @cntFys5, @cntFys6,
   @cntFys7, @cntFys8, @cntFys9,
   @cntFys10,@cntFys11,@cntFys12
   );
//const
var   CounterIndexies : array[0..CounterCount] of integer =
   (2,1,3,4,  5,7,8,  9,11,12,  13,15,16);

var   CounterNames : array[0..CounterCount] of string =
   ('Timer 1',
    'Counter 1','Counter 2','Counter 3',
    'Counter 4','Counter 5','Counter 6',
    'Counter 7','Counter 8','Counter 9',
    'Counter 10','Counter 11','Counter 12'
    );

//function ReadCounterB(cnt:iword):double;
//	Returns counter value multiplied by multiplier.

//function ReadCntSpeedB(cnt:iword):double;
//	Returns counter speed as SpeedMultiplier * steps/sek.

//procedure SetCounterB(cnt:iword; value: double);

{$ifdef NEW_K9C_INTERFACE}
function GetCountOfBits():integer; stdcall; far; external 'k9cdrv.dll';
// Returns total number of bits available

function GetCountOfBitsOnCard(card:integer):integer; stdcall; far; external 'k9cdrv.dll';
// Retuens number of bits on specified card

function GetCountOfCards():integer; stdcall; far; external 'k9cdrv.dll';
// Returns number of cards connected to this driver

function GetCountOfFysCounters():integer; stdcall; far; external 'k9cdrv.dll';
// Returns number of counters supported totally

function GetCountOfFysCountersOnCard(card:integer):integer; stdcall; far; external 'k9cdrv.dll';
// Returns number of counters locating on card
{$else}
function GetCountOfBits():integer;
function GetCountOfBitsOnCard(card:integer):integer;
function GetCountOfCards():integer;
function GetCountOfFysCounters():integer;
function GetCountOfFysCountersOnCard(card:integer):integer;
{$endif}

function NewLogicalCounter(fcnt:iword;mulref:iword):integer; stdcall; far; external 'k9cdrv.dll';
//	Creates new logical counter, which refers to physical counter fcnt.
//  Logical counter can have multiplier referencied other counter.

function ReadCounterPhysValue(cnt:iword):integer; stdcall; far; external 'k9cdrv.dll';
//	Returns counter value without any multip. and no overflow checking

function ReadCounterLong(cnt:iword):integer; stdcall; far; external 'k9cdrv.dll';
//	Returns counter value in counter steps.

function ReadFCounter(cnt:iword):double; stdcall; far; external 'k9cdrv.dll' name 'ReadCounter';
//	Returns counter value multiplied by multiplier.

function ReadTotalCounter(cnt:iword):double; stdcall; far; external 'k9cdrv.dll';
//	Returns total counter value multiplied by multiplier.

function ReadCntSpeed(cnt:iword):double; stdcall; far; external 'k9cdrv.dll';
//	Returns counter speed as SpeedMultiplier * steps/sek.

procedure SetFCounter(cnt:iword; value: double); stdcall; far; external 'k9cdrv.dll' name 'SetCounter';
//	Sets counter value to given value. Internal (at io-card) counter is
//   set to 0.

procedure SetFCounterAtIndex(cnt:iword; value: double); stdcall; far; external 'k9cdrv.dll' name 'SetCounterAtIndex';
//	Sets counter value to given value. Internal (at io-card) counter is
//   set to 0.

function SetCounterDirectionInverse(cnt:iword; inverse:wordBool):wordBool; stdcall; far; external 'k9cdrv.dll';
//	Sets counter inversion.

procedure SetCounterMultiplier(cnt:iword; mult:double); stdcall; far; external 'k9cdrv.dll';
//	Sets counter multiplier.

procedure SetCntSpeedMultiplier(cnt:iword; mult:double); stdcall; far; external 'k9cdrv.dll';
//	Sets counter SpeedMultiplier.

procedure SetCntSpeed(cnt:iword; speed:double); stdcall; far; external 'k9cdrv.dll';
//	Sets counter Speed (on simulation).

function SetCounterSimulated(cnt:iword; simu:wordBool):wordBool; stdcall; far; external 'k9cdrv.dll';
//	Sets counter as simulated.

function IsCounterSimulated(cnt:iword):wordBool; stdcall; far; external 'k9cdrv.dll';
//	return the counter simulation status.

function GetCounterSimulatedDir(cnt:iword):integer; stdcall; far; external 'k9cdrv.dll';
//	return the counter simulation direction.

procedure SetCounterGoal(cnt:iword; value:double); stdcall; far; external 'k9cdrv.dll';
//	Set position where counter generates an interrupt.

function EnableCounter(cnt:iword; enable:wordBool):wordBool; stdcall; far; external 'k9cdrv.dll';
//	Enables counting.

function EnableCounterAtGoalInterrupt(cnt:iword; enable:wordBool):wordBool; stdcall; far; external 'k9cdrv.dll';
//	Enables interrupt at goal.

function IsCardOK:wordBool; stdcall; far; external 'k9cdrv.dll';
//	Checks is the card OK. See. GetLastError()

function EnableIO(enable:wordBool):wordBool; stdcall; far; external 'k9cdrv.dll';
//	Enables or disables io-buffers.

procedure SetBit(bit:integer; value:wordBool); stdcall; far; external 'k9cdrv.dll';
//	Sets bit value. Bit is at range 0..nIoBits-1.

function GetBit(bit:integer):wordBool; stdcall; far; external 'k9cdrv.dll';
//	Returns bit value. Bit is at range 0..nIoBits-1.

procedure SetBitInverted(bit:integer; value:wordBool); stdcall; far; external 'k9cdrv.dll';
//	Sets bit value. Bit is at range 0..nIoBits-1.

function GetBitInverted(bit:integer):wordBool; stdcall; far; external 'k9cdrv.dll';
//	Returns bit value. Bit is at range 0..nIoBits-1.

procedure SetGate(gate:iword; value:byte); stdcall; far; external 'k9cdrv.dll';
//	Sets gate value. Gate is at range 0..nGates-1 or
//   predefined value G1A,G1B,G1C,G2A,G2B,G2C.

function GetGate(gate:iword):Byte; stdcall; far; external 'k9cdrv.dll';
//	Returns gate value. Gate is at range 0..nGates-1 or
//   predefined value G1A, G1B,  G1C,  G2A,  G2B,  G2C.
//    gate              0   1     2     3     4     5
//    bitit           0-7 8-15  16-23 24-31 32-39 40-47


procedure SetBitSimulated(bit:iword;s:boolean);  stdcall; far; external 'k9cdrv.dll';
//	Sets bit simulated.

function GetBitSimulated(bit:iword):boolean;  stdcall; far; external 'k9cdrv.dll';
//	Gets bit simulated.

procedure SetGateSimulatedBits(gate:iword; value:byte); stdcall; far; external 'k9cdrv.dll';
//	Sets gate bits simulated. Gate is at range 0..nGates-1 or
//   predefined value G1A,G1B,G1C,G2A,G2B,G2C.

function GetGateSimulatedBits(gate:iword):Byte; stdcall; far; external 'k9cdrv.dll';
//	Returns gate simulated bits. Gate is at range 0..nGates-1 or
//   predefined value G1A,G1B,G1C,G2A,G2B,G2C.

procedure SetGateInverse(gate:iword; value:byte); stdcall; far; external 'k9cdrv.dll';
//	Sets gate value. Gate is at range 0..nGates-1 or
//   predefined value G1A,G1B,G1C,G2A,G2B,G2C.

function GetGateInverse(gate:iword):Byte; stdcall; far; external 'k9cdrv.dll';
//	Returns gate value. Gate is at range 0..nGates-1 or
//   predefined value G1A,G1B,G1C,G2A,G2B,G2C.

procedure SetPort(port:iword; value:iword); stdcall; far; external 'k9cdrv.dll';
//	Sets port value. Port is at range 0..nPorts-1. Due to internal card
//   logic gates and ports does not follow numbering directly. It is preferable
//   to use SetGate function to setting port bits. See card techical documentation.

function GetPort(port:iword):iword; stdcall; far; external 'k9cdrv.dll';
//	returns port value. Port is at range 0..nPorts-1. Due to internal card
//   logic gates and ports does not follow numbering directly. It is preferable
//   to use GetGate function to getting port bits. See card techical documentation.

procedure SetGateDirection(output:wordBool); stdcall; far; external 'k9cdrv.dll';
//	Set gate to input (false) or output (true) gate.

//function LoadK9cIoCardChips(bool force=false, void *Wnd=NULL,
//		bool (*StopF)(void *wnd ,int value, const char *msg)=NULL):wordBool; stdcall; far; external 'k9cdrv.dll';
//	Reloads chips if necessary. By setting force to true it forces reload.
//   StopF callback function must be defined with three parameters:
//      wnd	: = given Parameter Wnd.
//      value	: Process progress in %. -1 means that progress should not be set
//      msg	: Message from process. NULL means no message.
//
//   Example:
//		static bool StopF(void *Dlg,int value, const char *msg)
//		{
//			if (Dlg==NULL) return true;
//			if (value>=0) ((TLoadDlg *)Dlg)->ProgressBar->SetValue(value);
//		   if (msg!=NULL) ((TLoadDlg *)Dlg)->SetDlgItemText(IDC_MESSAGE_CONTROL,msg);
//		   return ((TLoadDlg *)Dlg)->MessageChecker.CheckStop();
//		}


function GetMasterStatus:iword; stdcall; far; external 'k9cdrv.dll';
//	Returns current status of io-card. See technical documentation.

procedure SetMasterControl(control:iword); stdcall; far; external 'k9cdrv.dll';
function GetMasterControl:iword; stdcall; far; external 'k9cdrv.dll';
function LoadK9cIoCardChips(force:wordbool; wnd:integer; callback:integer) : wordbool; stdcall; far; external 'k9cdrv.dll';

function PossibleBitHWIRQ(bit:iword):boolean;  stdcall; far; external 'k9cdrv.dll';
//	Returns can the bit have hardware IRQ.
//   Input:	bit	- bit number
//   Returns: false	- bit can use only software IRQ
//   			true	- bit can use hardware IRQ

function SetBitHWIRQ(bit:iword;set_:boolean):boolean;  stdcall; far; external 'k9cdrv.dll';
//   Input:	bit	- bit number
// kovo keskeytys => mahdollista

function GetBitHWIRQ(bit:iword):boolean;  stdcall; far; external 'k9cdrv.dll';

procedure SetBitInputDFilter(bit:iword;filter:integer); stdcall; far; external 'k9cdrv.dll';
// 0 = no, 1=0.01 ms, 2=0.05 ms, 3=0.1 ms jne...
function GetBitInputDFilter(bit:iword):integer; stdcall; far; external 'k9cdrv.dll';
function WaitBitConditionOn(bit:iword;timeout:LongInt;event:Handle):integer; stdcall; far; external 'k9cdrv.dll';
// => 0 = bit, 10 = stop, 100 = set handle, 1000 = timeout
function WaitBitConditionOff(bit:iword;timeout:LongInt;event:Handle):integer; stdcall; far; external 'k9cdrv.dll';
procedure SendStopEvent;  stdcall; far; external 'k9cdrv.dll';
// Kaikki sammuu
function GetModuleCount:integer;  stdcall; far; external 'k9cdrv.dll';

function CreateDriver(const IniName:PChar;ForcTTF:boolean):boolean;  stdcall; far; external 'k9cdrv.dll';
procedure DeleteDriver;  stdcall; far; external 'k9cdrv.dll';

function IsVCounterSimulated(icnt:iword):boolean;
procedure EnableVCounter(icnt:iword; Enabled: boolean);
function ReadVCounter(icnt:iword):double;
function ReadVCounterSpeed(icnt:iword):double;
procedure SetVCounterSpeed(icnt:iword; value: double);
procedure SetVCounter(icnt:iword; value: double);
procedure SetVCounterAtIndex(icnt:iword; value: double; LeaveEnabled: boolean);
procedure ResetSetVCounterAtIndex(icnt:iword);
procedure JoinVCounter(icnt:iword; ifyscnt:iword);
function ReadVCounterFysCnt(icnt:iword) : iword;
procedure PushVCounters;
procedure PopVCounters;

//------------------------------------------------------------------------------
const CntF=1;
const CntP=2;
const CntB=3;
const CntR=4;

implementation

//------------------------------------------------------------------------------
const MaxVCnt = 200;
type TVCounters = array[0..MaxVCnt] of double;
type TFysVCounters = array[0..MaxVCnt] of iword;

var
  Zeros,Saved : TVCounters;
  FysCnts : TFysVCounters;

//------------------------------------------------------------------------------
{$ifndef NEW_K9C_INTERFACE}
function GetCountOfBits():integer; begin  Result := 48; end;
function GetCountOfBitsOnCard(card:integer):integer; begin  Result := 48; end;
function GetCountOfCards():integer; begin  Result := 1; end;
function GetCountOfFysCounters():integer; begin  Result := 4; end;
function GetCountOfFysCountersOnCard(card:integer):integer; begin  Result := 4; end;
{$endif}

//------------------------------------------------------------------------------
function IsVCounterSimulated(icnt:iword):boolean;
begin
  result:=true;
  if ( icnt < 0 ) or ( MaxVCnt < icnt ) then exit;
  result:=IsCounterSimulated(CounterIndexies[FysCnts[icnt]]);
end;

//------------------------------------------------------------------------------
procedure EnableVCounter(icnt:iword; Enabled: boolean);
begin
  if ( icnt < 0 ) or ( MaxVCnt < icnt ) then exit;
  EnableCounter(CounterIndexies[FysCnts[icnt]],Enabled);
end;

//------------------------------------------------------------------------------
function ReadVCounter(icnt:iword):double;
begin
  Result := 0;
  if ( icnt < 0 ) or ( MaxVCnt < icnt ) then exit;
  Result := ReadFCounter(CounterIndexies[FysCnts[icnt]]) - Zeros[icnt];
end;

//------------------------------------------------------------------------------
function ReadVCounterSpeed(icnt:iword):double;
begin
  Result := 0;
  if ( icnt < 0 ) or ( MaxVCnt < icnt ) then exit;
  Result := ReadCntSpeed(CounterIndexies[FysCnts[icnt]]);
end;

//------------------------------------------------------------------------------
procedure SetVCounterSpeed(icnt:iword; value: double);
begin
  if ( icnt < 0 ) or ( MaxVCnt < icnt ) then exit;
  SetCntSpeed(CounterIndexies[FysCnts[icnt]],value);
end;

//------------------------------------------------------------------------------
procedure SetVCounterAtIndex(icnt:iword; value: double; LeaveEnabled: boolean);
begin
  if ( icnt < 0 ) or ( MaxVCnt < icnt ) then exit;
  EnableCounter(CounterIndexies[FysCnts[icnt]],LeaveEnabled);
  SetFCounterAtIndex(CounterIndexies[FysCnts[icnt]],value);
  SetVCounter(icnt,value);
end;

//------------------------------------------------------------------------------
procedure ResetSetVCounterAtIndex(icnt:iword);
var val:double;
begin
  if ( icnt < 0 ) or ( MaxVCnt < icnt ) then exit;
  val := ReadFCounter(CounterIndexies[FysCnts[icnt]]);
  SetFCounter(CounterIndexies[FysCnts[icnt]],val);
end;

//------------------------------------------------------------------------------
procedure SetVCounter(icnt:iword; value: double);
begin
  if ( icnt < 0 ) or ( MaxVCnt < icnt ) then exit;
  Zeros[icnt] := ReadFCounter(CounterIndexies[FysCnts[icnt]]) - value;
  Saved[icnt] := value;
end;

//------------------------------------------------------------------------------
procedure JoinVCounter(icnt:iword; ifyscnt:iword);
begin
  if ( icnt < 0 ) or ( MaxVCnt < icnt ) then exit; // or ( ifyscnt < 0 ) then exit;
  if ( ifyscnt < 0 ) then
    FysCnts[icnt] := 1
  else
    FysCnts[icnt] := ifyscnt;
end;

//------------------------------------------------------------------------------
function ReadVCounterFysCnt(icnt:iword) : iword;
begin
  Result:=1;
  if ( icnt < 0 ) or ( MaxVCnt < icnt ) then exit;
  result:=FysCnts[icnt];
end;

//------------------------------------------------------------------------------
procedure PushVCounters;
var i:integer;
begin
  for i:=0 to MaxVCnt do
    Saved[i] := ReadVCounter(i);
end;

//------------------------------------------------------------------------------
procedure PopVCounters;
var i:integer;
begin
  for i:=0 to MaxVCnt do
    SetVCounter(i,Saved[i]);
end;

//------------------------------------------------------------------------------
procedure InitVCounters;
var i:integer;
begin
  for i:=0 to MaxVCnt do
    FysCnts[i] := 1;
end;


(*
{$l obj\k9c_drv.obj}
{$l driverx\hardlib.obj}
{$l driverx\whc.obj}      *)
//uses Windows;
//var Cri:TRTLCriticalSection; t:integer;
(*
function ReadCounterB(cnt:iword):double;
//	Returns counter value multiplied by multiplier.
begin
  If ( Cri.LockCount >= 0 ) then begin
    t := 1;
  end;
  EnterCriticalSection(Cri);
  Result := ReadCounter(cnt);
  LeaveCriticalSection(Cri);
end;

function ReadCntSpeedB(cnt:iword):double;
//	Returns counter speed as SpeedMultiplier * steps/sek.
begin
  If ( Cri.LockCount >= 0 ) then begin
    t := 2;
  end;
  EnterCriticalSection(Cri);
  Result := ReadCntSpeed(cnt);
  LeaveCriticalSection(Cri);
end;


procedure SetCounterB(cnt:iword; value: double);
begin
  If ( Cri.LockCount >= 0 ) then begin
    t := 3;
  end;
  EnterCriticalSection(Cri);
  SetCounter(cnt,value);
  LeaveCriticalSection(Cri);
end;
*)
{
procedure SetBitSimulated(bit:iword;s:boolean);
//	Sets bit simulated.
var b,mask,gate,gval : iword;
begin
  gate := bit div 8;
  b := bit mod 8;
  mask := 1 shl b;
  gval := GetGateSimulatedBits(gate);
  if ( s ) then gval := gval OR mask
           else gval := gval AND (not mask);
  SetGateSimulatedBits(gate,gval);
end;

function GetBitSimulated(bit:iword):boolean;
var b,mask,gate,gval : iword;
begin
  gate := bit div 8;
  b := bit mod 8;
  mask := 1 shl b;
  gval := GetGateSimulatedBits(gate);
  result := (gval and mask) = mask;
end;
}

initialization begin
  InitVCounters;
//  InitializeCriticalSection(Cri);
//  CreateDriver;
end;

finalization begin
//  DeleteCriticalSection(Cri);
end;


end.
