Quick start
CASH.DLL v4.1.1.5

Step by step instructions to implement the CASH-Interface into your own application.

QuickLinks: CASH-Interface   HOPPER-Interface   COUNTER-Board


CASH-Interface

Integration CASH.DLL

1. Add the function and procedure declarations to your USES clause.

Delphi:
implementation
{$R *.DFM}
uses cashdll;


Visual Basic 6:
Simply add the DLL import unit 'cashdll.bas' to your project:
=> Project, add file, cashdll.bas

Visual Basic .NET:
Simply add the DLL import unit 'cashdll.vb' to your project:
=> Project, add existing element, cashdll.vb

All functions and procedures of the CASH.DLL are now available in your project.



Open and close the COM Port to the CASH-Interface

1. Open the COM Port to the CASH-Interface at the OnCreate routine of the main form

Delphi:
procedure TForm1.FormCreate(Sender: TObject);
begin
  CASH_OPENCOM(1);         // open COM1 
  CASH_TOTALBLOCKING_OFF;  // enable devices
end;
Visual Basic 6:
Private Sub Form_Load()
  CASH_OPENCOM(1)          'open COM1 
  CASH_TOTALBLOCKING_OFF   'enable devices
End Sub
Visual Basic .NET:
Private Sub Form1_Load(ByVal eventSender As System.Object, 
ByVal eventArgs As System.EventArgs) Handles MyBase.Load
  CASH_OPENCOM(1)          'open COM1 
  CASH_TOTALBLOCKING_OFF   'enable devices
End Sub
If the COM port cannot be opened you get a return value of -1 from the CASH_OPENCOM function.
This can be checked like this:

Delphi:
procedure TForm1.FormCreate(Sender: TObject);
begin
  if CASH_OPENCOM(1) = -1 then 
    MessageDlg('Error opening the COM-Port!', mtError, [mbOK], 0) else
    CASH_TOTALBLOCKING_OFF;
end;
Visual Basic 6:
Private Sub Form_Load()
  If CASH_OPENCOM(1) = -1 Then 
    MsgBox "Error opening the COM-Port!"
  ELSE
    CASH_TOTALBLOCKING_OFF
  End If
End Sub
Visual Basic .NET:
Private Sub Form1_Load(ByVal eventSender As System.Object, 
ByVal eventArgs As System.EventArgs) Handles MyBase.Load
  If CASH_OPENCOM(1) = -1 Then
    MsgBox "Error opening the COM-Port!"
  Else
    CASH_TOTALBLOCKING_OFF
  End If
End Sub
The COM-Port to the CASH-Interface is now open and data can be read.

2. Close the COM Port to the CASH-Interface at the OnClose routine of the main form

Delphi:
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  CASH_CLOSECOM;
end;
Visual Basic 6:
Private Sub Form_Unload(Cancel As Integer)
  CASH_CLOSECOM
End Sub
Visual Basic .NET:
Private Sub Form1_FormClosed(ByVal eventSender As System.Object, 
ByVal eventArgs As System.Windows.Forms.FormClosedEventArgs) 
Handles Me.FormClosed
  CASH_CLOSECOM()
End Sub



Read data from the CASH-Interface

1. Define global variables which are needed for work with the CASH.DLL

Delphi:
var
  Form1     : TForm1;
  iCredits  : Integer;                   // Credits total
  iRead     : Integer;                   // databyte
  iReadLast : Integer;                   // Last databyte
  iParallel : Integer;                   // PARALLEL mode channel no.
  aData     : Array[1..8] of Boolean;    // data flags
  aCoinPayed : Array[1..15] of Boolean;  // Coin payed backup
  aCoinValue : Array[1..15] of Integer;  // PARALLEL mode #1-#6 or 
                                         // BINARY mode coin values #1-#15
  aBillPayed : Array[1..15] of Boolean;  // BINARY bill payed backup
  aBillValue : Array[1..15] of Integer;  // BINARY mode bill values #1-#15
  LowNibble : Byte;                      // BINARY mode lower 4 bits of
                                         // the databyte
Visual Basic 6:
Dim iCredits As Long                     'Credits total
Dim iRead As Long                        'databyte
Dim iReadLast As Long                    'Last databyte
Dim iParallel As Long                    'Parallel value
Dim aData(1 To 8) As Boolean             'data flags
Dim aCoinPayed(1 To 15) As Boolean       'Coin payed backup
Dim aCoinValue(1 To 15) As Long          'PARALLEL mode #1-#6 or 
                                         'BINARY mode coin values #1-#15
Dim aBillPayed(1 To 15) As Boolean       'BINARY mode bill payed backup
Dim aBillValue(1 To 15) As Long          'BINARY mode bill values #1-#15
Dim LowNibble As Long                    'BINARY mode lower 4 bits 
                                         'of the databyte
Visual Basic .NET:
Dim iCredits As Integer                  'Credits total
Dim iRead As Integer                     'databyte
Dim iReadLast As Integer                 'Last databyte
Dim iParallel As Integer                 'Parallel value
Dim aData(8) As Boolean                  'data flags
Dim aCoinPayed(15) As Boolean            'Coin payed backup
Dim aCoinValue(15) As Integer            'PARALLEL mode #1-#6 or 
                                         'BINARY mode coin values #1-#15
Dim aBillPayed(15) As Boolean            'BINARY mode bill payed backup
Dim aBillValue(15) As Integer            'BINARY mode bill values #1-#15
Dim LowNibble As Long                    'BINARY mode lower 4 bits
                                         'of the databyte
2. Place a Timer component onto your main form and set the interval to 20 ms.

3. Place a Label component onto your main form to display the data (Label1).

4. Place a Label component onto your main form to display the credits (Label2).

5. Write the coin and bill values in the create method into an array.
For PARALLEL mode the assignment is made in the array aCoinValue 1-6
For BINARY mode the assignment is made in the array aCoinValue 1-15 and aBillValue 1-15

Delphi:
procedure TForm1.FormCreate(Sender: TObject);
begin
  ...

  // example PARALLEL mode
  aCoinValue[1] := 500;    // bill validator channel 1 = 5 Euro bill
  aCoinValue[2] := 1000;   // bill validator channel 2 = 10 Euro bill
  aCoinValue[3] := 2000;   // bill validator channel 3 = 20 Euro bill
  aCoinValue[4] := 5000;   // bill validator channel 4 = 50 Euro bill
  aCoinValue[5] := 100;    // coin validator channel 5 = 1 Euro coin
  aCoinValue[6] := 200;    // coin validator channel 6 = 2 Euro coin
end;
Visual Basic 6:
Private Sub Form_Load()
...
  'example PARALLEL mode
  aCoinValue(1) = 500;     'bill validator channel 1 = 5 Euro bill
  aCoinValue(2) = 1000;    'bill validator channel 2 = 10 Euro bill
  aCoinValue(3) = 2000;    'bill validator channel 3 = 20 Euro bill
  aCoinValue(4) = 5000;    'bill validator channel 4 = 50 Euro bill
  aCoinValue(5) = 100;     'coin validator channel 5 = 1 Euro coin
  aCoinValue(6) = 200;     'coin validator channel 6 = 2 Euro coin
End Sub
Visual Basic .NET:
Private Sub Form1_Load(ByVal eventSender As System.Object, 
ByVal eventArgs As System.EventArgs) Handles MyBase.Load
...

  'example PARALLEL mode
  aCoinValue(1) = 500;     'bill validator channel 1 = 5 Euro bill
  aCoinValue(2) = 1000;    'bill validator channel 2 = 10 Euro bill
  aCoinValue(3) = 2000;    'bill validator channel 3 = 20 Euro bill
  aCoinValue(4) = 5000;    'bill validator channel 4 = 50 Euro bill
  aCoinValue(5) = 100;     'coin validator channel 5 = 1 Euro coin
  aCoinValue(6) = 200;     'coin validator channel 6 = 2 Euro coin
End Sub

Reading data from the cash interface is done at the OnTimer procedure.

Delphi:
procedure TForm1.Timer1Timer(Sender: TObject);
begin
  // read databyte via dll function "CASH_READ"
  iRead := CASH_READ;
  // we will only work if something has changed!
  if iRead = iReadLast then Exit;
  // store the current read byte
  iReadLast := iRead;
  // show databyte in dezimal view
  Label1.Caption := IntToStr(iRead);
end;
Visual Basic 6:
Private Sub TimerPoll_Timer()
  'read databyte via dll function "CASH_READ"
  iRead = CASH_READ
  'we will only work if something has changed!
  if iRead = iReadLast then Exit Sub
  'store the current read byte
  iReadLast = iRead
  'show databyte in dezimal view
  Label_CASH_READ = iRead
End Sub
Visual Basic .NET:
Private Sub TimerPoll_Tick(ByVal eventSender As System.Object, 
ByVal eventArgs As System.EventArgs) Handles TimerPoll.Tick
  'read databyte via dll function "CASH_READ"
  iRead = CASH_READ
  'we will only work if something has changed!
  If iRead = iReadLast Then Exit Sub
  'store the current read byte
  iReadLast = iRead
  'show databyte in dezimal view
  Label_CASH_READ.Text = CStr(iRead)
End Sub
Start your application and watch the data value while inserting money to a device.



Evaluating data from the CASH-Interface

1. The data "iRead" needs to be splitted to it's single bits.

"iRead" data byte format:
Bit1 = Channel 1
Bit2 = Channel 2
Bit3 = Channel 3
Bit4 = Channel 4
Bit5 = Channel 5
Bit6 = Channel 6
Bit7 = BUSY signal of the NVx
Bit8 = Power supply ok

Splitting "iRead" into bits is made at the OnTimer procedure.

Delphi:
procedure TForm1.Timer1Timer(Sender: TObject);
begin
  // read databyte via dll function "CASH_READ"
  iRead := CASH_READ;
  // we will only work if something has changed!
  if iRead = iReadLast then Exit;
  // store the current read byte
  iReadLast := iRead;
  // show databyte in dezimal view
  Label1.Caption := IntToStr(iRead);

  // clear the flags array and split databyte into flags Array
  FillChar(aData[1], Length(aData)*sizeof(aData[1]), 0);
  if ((iRead AND 1) > 0) then aData[1] := true;
  if ((iRead AND 2) > 0) then aData[2] := true;
  if ((iRead AND 4) > 0) then aData[3] := true;
  if ((iRead AND 8) > 0) then aData[4] := true;
  if ((iRead AND 16) > 0) then aData[5] := true;
  if ((iRead AND 32) > 0) then aData[6] := true;
  if ((iRead AND 64) > 0) then aData[7] := true;
  if ((iRead AND 128) > 0) then aData[8] := true;
end;
Visual Basic 6:
Private Sub TimerPoll_Timer()
  'read databyte via dll function "CASH_READ"
  iRead = CASH_READ
  'we will only work if something has changed!
  If iRead = iReadLast Then Exit Sub
  'store the current read byte
  iReadLast = iRead
  'show databyte in dezimal view
  Label_CASH_READ = iRead
  
  'clear the flags array and split the databyte into flags array
  Erase aData
  If ((iRead And 1) > 0) Then aData(1) = True
  If ((iRead And 2) > 0) Then aData(2) = True
  If ((iRead And 4) > 0) Then aData(3) = True
  If ((iRead And 8) > 0) Then aData(4) = True
  If ((iRead And 16) > 0) Then aData(5) = True
  If ((iRead And 32) > 0) Then aData(6) = True
  If ((iRead And 64) > 0) Then aData(7) = True
  If ((iRead And 128) > 0) Then aData(8) = True
End Sub
Visual Basic .NET:
Private Sub TimerPoll_Tick(ByVal eventSender As System.Object, 
ByVal eventArgs As System.EventArgs) Handles TimerPoll.Tick
  'read databyte via dll function "CASH_READ"
  iRead = CASH_READ
  'we will only work if something has changed!
  If iRead = iReadLast Then Exit Sub
  'store the current read byte
  iReadLast = iRead
  'show databyte in dezimal view
  Label_CASH_READ.Text = CStr(iRead)
		
  'clear the flags array and split the databyte into flags array
  Array.Clear(aData, 1, 8)
  If ((iRead And 1) > 0) Then aData(1) = True
  If ((iRead And 2) > 0) Then aData(2) = True
  If ((iRead And 4) > 0) Then aData(3) = True
  If ((iRead And 8) > 0) Then aData(4) = True
  If ((iRead And 16) > 0) Then aData(5) = True
  If ((iRead And 32) > 0) Then aData(6) = True
  If ((iRead And 64) > 0) Then aData(7) = True
  If ((iRead And 128) > 0) Then aData(8) = True
End Sub
The single bits are available now in the Array aData.


2. Evaluating the single bits

Because we poll every 64 milliseconds and the signal is longer we must prevent to count the same signal twice! The solution is to store the last value. We also use flag no.8 to detect the power supply. Remember the acceptor works with active LOW, so no power will detect a LOW and would count credits. Using a AND operation here, it will not count any credits while power failure.

PARALLEL Modus:
First we create a integer number (iParallel) with the active channel, this number is used also to read the value of the coin or bill out of the corresponding array.

BINARY Modus:
First we create a integer number (LowNibble) with the active channel, this number is used also to read the value of the coin or bill out of the corresponding array.

Delphi PARALLEL Mode:
// create a integer value out of the 6 Channels
iParallel := 0;
if aData[1] then iParallel := 1;
if aData[2] then iParallel := 2;
if aData[3] then iParallel := 3;
if aData[4] then iParallel := 4;
if aData[5] then iParallel := 5;
if aData[6] then iParallel := 6;

// we store a backup flag in aCoinPayed to prevent doubble counts

if (iParallel > 0) AND aData[8] then begin     
  if NOT aCoinPayed[iParallel] then begin
    aCoinPayed[iParallel] := true;
    inc(iCredits, aCoinValue[iParallel]);
    LabelCredits.Caption := IntToStr(iCredits);
  end;
end;
Delphi BINARY Mode:
// We work with the LowNibble => channel1-4, 
// so we can detect 15 different bills and 15 different coins

LowNibble := iRead AND $0F;

// *****************************************************************
//  BILL VALIDATOR BINARY MODE (bill signals bit6 is NOT set)
// *****************************************************************

// we store a backup flag in aBillPayed to prevent doubble counts

if (LowNibble > 0) AND aData[8] AND NOT aData[6] then begin
  if NOT aBillPayed[LowNibble] then begin
    aBillPayed[LowNibble] := true;
    inc(iCredits, aBillValue[LowNibble]);
    LabelCredits.Caption := IntToStr(iCredits);
  end;
end else

// *****************************************************************
//  COIN VALIDATOR BINARY MODE (coin signals bit6 is set)
// *****************************************************************

// we store a backup flag in aCoinPayed to prevent doubble counts

if (LowNibble > 0) AND aData[8] AND aData[6] then begin
  if NOT aCoinPayed[LowNibble] then begin
    aCoinPayed[LowNibble] := true;
    inc(iCredits, aCoinValue[LowNibble]);
    LabelCredits.Caption := IntToStr(iCredits);
  end;
end;

Visual Basic 6 PARALLEL Mode:
' create a integer value out of the 6 Channels
iParallel = 0
If aData(1) Then iParallel = 1
If aData(2) Then iParallel = 2
If aData(3) Then iParallel = 3
If aData(4) Then iParallel = 4
If aData(5) Then iParallel = 5
If aData(6) Then iParallel = 6

' we store a backup flag in aCoinPayed to prevent doubble counts

If (iParallel > 0) And aData(8) Then
  If Not aCoinPayed(iParallel) Then
    aCoinPayed(iParallel) = True
    iCredits = iCredits + aCoinValue(iParallel)
  End If
End If
Visual Basic 6 BINARY Mode:
' We work with the LowNibble => channel1-4, 
' so we can detect 15 different bills and 15 different coins
LowNibble = iRead And &HF
  
' *****************************************************************
'  BILL VALIDATOR BINARY MODE (bill signals bit6 is NOT set)
' *****************************************************************

' we store a backup flag in aBillPayed to prevent doubble counts

If (LowNibble > 0) And aData(8) And Not aData(6) Then
  If Not aBillPayed(LowNibble) Then
    aBillPayed(LowNibble) = True
    iCredits = iCredits + aBillValue(LowNibble)
  End If

' *****************************************************************
'  COIN VALIDATOR BINARY MODE (coin signals bit6 is set)
' *****************************************************************

' we store a backup flag in aCoinPayed to prevent doubble counts

ElseIf (LowNibble > 0) And aData(8) And aData(6) Then
  If Not aCoinPayed(LowNibble) Then
    aCoinPayed(LowNibble) = True
    iCredits = iCredits + aCoinValue(LowNibble)
  End If
End If

Visual Basic .NET PARALLEL Mode:
' create a integer value out of the 6 Channels
iParallel = 0
If aData(1) Then iParallel = 1
If aData(2) Then iParallel = 2
If aData(3) Then iParallel = 3
If aData(4) Then iParallel = 4
If aData(5) Then iParallel = 5
If aData(6) Then iParallel = 6

' we store a backup flag in aCoinPayed to prevent doubble counts

If (iParallel > 0) And aData(8) Then          
  If Not aCoinPayed(iParallel) Then
     aCoinPayed(iParallel) = True
     iCredits = iCredits + aCoinValue(iParallel)
   End If
End If
Visual Basic .NET BINARY Mode:
' We work with the LowNibble => channel1-4, 
' so we can detect 15 different bills and 15 different coins
LowNibble = iRead And &HF

' *****************************************************************
'  BILL VALIDATOR BINARY MODE (bill signals bit6 is NOT set)
' *****************************************************************

' we store a backup flag in aBillPayed to prevent doubble counts

If (LowNibble > 0) And aData(8) And Not aData(6) Then
  If Not aBillPayed(LowNibble) Then
    aBillPayed(LowNibble) = True
    iCredits = iCredits + aBillValue(LowNibble)
  End If

' *****************************************************************
'  COIN VALIDATOR BINARY MODE (coin signals bit6 is set)
' *****************************************************************

' we store a backup flag in aCoinPayed to prevent doubble counts

ElseIf (LowNibble > 0) And aData(8) And aData(6) Then
  If Not aCoinPayed(LowNibble) Then
    aCoinPayed(LowNibble) = True
    iCredits = iCredits + aCoinValue(LowNibble)
  End If
End If

Here is the complete timer procedure for PARALLEL mode in Delphi:
procedure TForm1.TimerPollTimer(Sender: TObject);
begin
  // read databyte via dll function "CASH_READ(comport)"
  iRead := CASH_READ;
  // we will only work if something has changed!
  if iRead = iReadLast then Exit;
  // stop the timer while working
  TimerPoll.Enabled := false;
  // store the current read byte
  iReadLast := iRead;
  // show databyte in dezimal view
  LabelRead.Caption := IntToStr(iRead);

  // clear the backup array if we have no more cash signals
  // 128 = no cash signals  OR  192 = NVx busy
  if ((iRead = 128) OR (iRead = 192)) then begin
    FillChar(aCoinPayed[1], Length(aCoinPayed)*sizeof(aCoinPayed[1]), 0);
  end;  

  // clear the flags array and split databyte into flags Array
  FillChar(aData[1], Length(aData)*sizeof(aData[1]), 0);
  if ((iRead AND 1) > 0) then aData[1] := true;
  if ((iRead AND 2) > 0) then aData[2] := true;
  if ((iRead AND 4) > 0) then aData[3] := true;
  if ((iRead AND 8) > 0) then aData[4] := true;
  if ((iRead AND 16) > 0) then aData[5] := true;
  if ((iRead AND 32) > 0) then aData[6] := true;
  if ((iRead AND 64) > 0) then aData[7] := true;
  if ((iRead AND 128) > 0) then aData[8] := true;

  // Because we poll every 20 milliseconds and the signal is longer
  // we must prevent to count the same signal twice! The solution is
  // to store the last value. We also use flag no.8 to detect the power 
  // supply. Remember the acceptor works with active LOW, so no power
  // will detect a LOW and would count credits. Using a AND operation 
  // here, it will not count any credits while power failure.
 
  // bit 1 = channel 1
  // bit 2 = channel 2
  // bit 3 = channel 3
  // bit 4 = channel 4
  // bit 5 = channel 5
  // bit 6 = channel 6
  // bit 7 = NV busy
  // bit 8 = power supply ok

  // create a integer value out of the 6 Channels
  iParallel := 0;
  if aData[1] then iParallel := 1;
  if aData[2] then iParallel := 2;
  if aData[3] then iParallel := 3;
  if aData[4] then iParallel := 4;
  if aData[5] then iParallel := 5;
  if aData[6] then iParallel := 6;

  // we store a backup flag in aCoinPayed to prevent doubble counts
 
  if (iParallel > 0) AND aData[8] then begin       
    if NOT aCoinPayed[iParallel] then begin
      aCoinPayed[iParallel] := true;
      inc(iCredits, aCoinValue[iParallel]);
      LabelCredits.Caption := IntToStr(iCredits);
    end;
  end;

  // start the timer again
  TimerPoll.Enabled := true;
end;

Here is the complete timer procedure for BINARY mode in Delphi:
procedure TForm1.TimerPollTimer(Sender: TObject);
begin
  // read databyte via dll function "CASH_READ(comport)"
  iRead := CASH_READ;
  // we will only work if something has changed!
  if iRead = iReadLast then Exit;
  // stop the timer while working
  TimerPoll.Enabled := false;
  // store the current read byte
  iReadLast := iRead;
  // show databyte in dezimal view
  LabelRead.Caption := IntToStr(iRead);

  // clear the backup array if we have no more cash signals
  // 128 = no cash signals  OR  192 = NVx busy
  if ((iRead = 128) OR (iRead = 192)) then begin
    FillChar(aCoinPayed[1], Length(aCoinPayed)*sizeof(aCoinPayed[1]), 0);
    FillChar(aBillPayed[1], Length(aBillPayed)*sizeof(aBillPayed[1]), 0);
  end;  

  // clear the flags array and split databyte into flags Array
  FillChar(aData[1], Length(aData)*sizeof(aData[1]), 0);
  if ((iRead AND 1) > 0) then aData[1] := true;
  if ((iRead AND 2) > 0) then aData[2] := true;
  if ((iRead AND 4) > 0) then aData[3] := true;
  if ((iRead AND 8) > 0) then aData[4] := true;
  if ((iRead AND 16) > 0) then aData[5] := true;
  if ((iRead AND 32) > 0) then aData[6] := true;
  if ((iRead AND 64) > 0) then aData[7] := true;
  if ((iRead AND 128) > 0) then aData[8] := true;

  // Because we poll every 20 milliseconds and the signal is longer
  // we must prevent to count the same signal twice! The solution is
  // to store the last value. We also use flag no.8 to detect the power 
  // supply. Remember the acceptor works with active LOW, so no power
  // will detect a LOW and would count credits. Using a AND operation 
  // here, it will not count any credits while power failure.

  // bit 1 = channel 1
  // bit 2 = channel 2
  // bit 3 = channel 3
  // bit 4 = channel 4
  // bit 5 = not used
  // bit 6 = coin validator binary line
  // bit 7 = NV busy
  // bit 8 = power supply ok

  // We work with the LowNibble => channel1-4, 
  // so we can detect 15 different bills and 15 different coins
  LowNibble := iRead AND $0F;

  // *****************************************************************
  //  BILL VALIDATOR BINARY MODE (bill signals bit6 is NOT set)
  // *****************************************************************

  // we store a backup flag in aBillPayed to prevent doubble counts

  if (LowNibble > 0) AND aData[8] AND NOT aData[6] then begin
    if NOT aBillPayed[LowNibble] then begin
      aBillPayed[LowNibble] := true;
      inc(iCredits, aBillValue[LowNibble]);
      LabelCredits.Caption := IntToStr(iCredits);
    end;
  end else

  // *****************************************************************
  //  COIN VALIDATOR BINARY MODE (coin signals bit6 is set)
  // *****************************************************************

  // we store a backup flag in aCoinPayed to prevent doubble counts

  if (LowNibble > 0) AND aData[8] AND aData[6] then begin
    if NOT aCoinPayed[LowNibble] then begin
      aCoinPayed[LowNibble] := true;
      inc(iCredits, aCoinValue[LowNibble]);
      LabelCredits.Caption := IntToStr(iCredits);
    end;
  end;

  // start the timer again
  TimerPoll.Enabled := true;
end;

Here is the complete timer procedure for PARALLEL mode in Visual Basic 6:
Private Sub TimerPoll_Timer()
  'read databyte via dll function "CASH_READ"
  iRead = CASH_READ
  
  'we will only work if something has changed!
  If iRead = iReadLast Then Exit Sub
  
  'stop the timer while working
  TimerPoll.Enabled = False
  
  'store the current read byte
  iReadLast = iRead
  
  'show databyte in dezimal view
  Label_CASH_READ.Caption = iRead
  
  ' clear the backup array if we have no more cash signals
  ' 128 = no cash signals  OR  192 = NVx busy
  If ((iRead = 128) Or (iRead = 192)) Then
    Erase aCoinPayed
  End If
    
  'clear the flags array and split the databyte into flags array
  Erase aData
  If ((iRead And 1) > 0) Then aData(1) = True
  If ((iRead And 2) > 0) Then aData(2) = True
  If ((iRead And 4) > 0) Then aData(3) = True
  If ((iRead And 8) > 0) Then aData(4) = True
  If ((iRead And 16) > 0) Then aData(5) = True
  If ((iRead And 32) > 0) Then aData(6) = True
  If ((iRead And 64) > 0) Then aData(7) = True
  If ((iRead And 128) > 0) Then aData(8) = True
  
  'bit 1 = channel 1
  'bit 2 = channel 2
  'bit 3 = channel 3
  'bit 4 = channel 4
  'bit 5 = channel 5
  'bit 6 = channel 6
  'bit 7 = NV busy
  'bit 8 = power supply ok

  'if this two flags are set to high we have the wrong com port
  If aData(1) And aData(2) Then
    TimerPoll.Enabled = True
    Exit Sub
  End If

  ' create a integer value out of the 6 Channels
  iParallel = 0
  If aData(1) Then iParallel = 1
  If aData(2) Then iParallel = 2
  If aData(3) Then iParallel = 3
  If aData(4) Then iParallel = 4
  If aData(5) Then iParallel = 5
  If aData(6) Then iParallel = 6

  'we store a backup flag in aCoinPayed to prevent doubble counts

  If iParallel > 0 And aData(8) Then 
    If Not aCoinPayed(iParallel) Then
      aCoinPayed(iParallel) = True
      iCredits = iCredits + aCoinValue(iParallel)
    End If
  End If
  
  'show the Credits
  Label_Credits.Caption = iCredits
  
  'start the timer again
  TimerPoll.Enabled = True
End Sub

Here is the complete timer procedure for BINARY mode in Visual Basic 6:
Private Sub TimerPoll_Timer()
  'read databyte via dll function "CASH_READ"
  iRead = CASH_READ
  
  'we will only work if something has changed!
  If iRead = iReadLast Then Exit Sub
  
  'stop the timer while working
  TimerPoll.Enabled = False
  
  'store the current read byte
  iReadLast = iRead
  
  'show databyte in dezimal view
  Label_CASH_READ.Caption = iRead
  
  ' clear the backup array if we have no more cash signals
  ' 128 = no cash signals  OR  192 = NVx busy
  If ((iRead = 128) Or (iRead = 192)) Then
    Erase aCoinPayed
    Erase aBillPayed
  End If
    
  'clear the flags array and split the databyte into flags array
  Erase aData
  If ((iRead And 1) > 0) Then aData(1) = True
  If ((iRead And 2) > 0) Then aData(2) = True
  If ((iRead And 4) > 0) Then aData(3) = True
  If ((iRead And 8) > 0) Then aData(4) = True
  If ((iRead And 16) > 0) Then aData(5) = True
  If ((iRead And 32) > 0) Then aData(6) = True
  If ((iRead And 64) > 0) Then aData(7) = True
  If ((iRead And 128) > 0) Then aData(8) = True
  
  'bit 1 = channel 1
  'bit 2 = channel 2
  'bit 3 = channel 3
  'bit 4 = channel 4
  'bit 5 = not used
  'bit 6 = coin validator binary line
  'bit 7 = NV busy
  'bit 8 = power supply ok
  
  'We work with the LowNibble => channel1-4, 
  'so we can detect 15 different bills and 15 different coins
  LowNibble = iRead And &HF
  
  ' ***********************************************************************
  '  BILL VALIDATOR BINARY MODE (bill signals bit6 is NOT set)
  ' ***********************************************************************

  ' we store a backup flag in aBillPayed to prevent doubble counts

  If (LowNibble > 0) And aData(8) And Not aData(6) Then
    If Not aBillPayed(LowNibble) Then
      aBillPayed(LowNibble) = True
      iCredits = iCredits + aBillValue(LowNibble)
    End If

  ' ***********************************************************************
  '  COIN VALIDATOR BINARY MODE (coin signals bit6 is set)
  ' ***********************************************************************

  ' we store a backup flag in aCoinPayed to prevent doubble counts

  ElseIf (LowNibble > 0) And aData(8) And aData(6) Then
    If Not aCoinPayed(LowNibble) Then
      aCoinPayed(LowNibble) = True
      iCredits = iCredits + aCoinValue(LowNibble)
    End If
  End If
  
  'show the Credits
  Label_Credits.Caption = iCredits
  
  'start the timer again
  TimerPoll.Enabled = True
End Sub

Here is the complete timer procedure for PARALLEL mode in Visual Basic .NET:
Private Sub TimerPoll_Tick(ByVal sender As System.Object, 
ByVal e As System.EventArgs) Handles TimerPoll.Tick
  'read databyte via dll function "CASH_READ"
  iRead = CASH_READ

  'we will only work if something has changed!
  If iRead = iReadLast Then Exit Sub

  'stop the timer while working
  TimerPoll.Enabled = False

  'store the current read byte
  iReadLast = iRead

  'show databyte in dezimal view
  Label_CASH_READ.Text = CStr(iRead)

  ' clear the backup array if we have no more cash signals
  ' 128 = no cash signals  OR  192 = NVx busy
  If ((iRead = 128) Or (iRead = 192)) Then
      Array.Clear(aCoinPayed, 1, 15)
  End If

  'clear the flags array and split the databyte into flags array
  Array.Clear(aData, 1, 8)
  If ((iRead And 1) > 0) Then aData(1) = True
  If ((iRead And 2) > 0) Then aData(2) = True
  If ((iRead And 4) > 0) Then aData(3) = True
  If ((iRead And 8) > 0) Then aData(4) = True
  If ((iRead And 16) > 0) Then aData(5) = True
  If ((iRead And 32) > 0) Then aData(6) = True
  If ((iRead And 64) > 0) Then aData(7) = True
  If ((iRead And 128) > 0) Then aData(8) = True

  ' bit 1 = channel 1
  ' bit 2 = channel 2
  ' bit 3 = channel 3
  ' bit 4 = channel 4
  ' bit 5 = channel 5
  ' bit 6 = channel 6
  ' bit 7 = NV busy
  ' bit 8 = power supply ok

  'if this two flags are set to high we have the wrong com port
  If aData(1) And aData(2) Then
    TimerPoll.Enabled = True
    Exit Sub
  End If

  ' create a integer value out of the 6 Channels
  iParallel = 0
  If aData(1) Then iParallel = 1
  If aData(2) Then iParallel = 2
  If aData(3) Then iParallel = 3
  If aData(4) Then iParallel = 4
  If aData(5) Then iParallel = 5
  If aData(6) Then iParallel = 6

  ' we store a backup flag in aCoinPayed to prevent doubble counts
  If (iParallel > 0) And aData(8) Then
    If Not aCoinPayed(iParallel) Then
      aCoinPayed(iParallel) = True
      iCredits = iCredits + aCoinValue(iParallel)
    End If
  End If

  'show the Credits
  Label_Credits.Text = CStr(iCredits)

  'start the timer again
  TimerPoll.Enabled = True
End Sub
Here is the complete timer procedure for BINARY mode in Visual Basic .NET:
Private Sub TimerPoll_Tick(ByVal sender As System.Object, 
ByVal e As System.EventArgs) Handles TimerPoll.Tick
  'read databyte via dll function "CASH_READ"
  iRead = CASH_READ

  'we will only work if something has changed!
  If iRead = iReadLast Then Exit Sub

  'stop the timer while working
  TimerPoll.Enabled = False

  'store the current read byte
  iReadLast = iRead

  'show databyte in dezimal view
  Label_CASH_READ.Text = CStr(iRead)

  'clear the backup array if we have no more cash signals
  '128 = no cash signals  OR  192 = NVx busy
  If ((iRead = 128) Or (iRead = 192)) Then
      Array.Clear(aCoinPayed, 1, 15)
      Array.Clear(aBillPayed, 1, 15)
  End If

  'clear the flags array and split the databyte into flags array
  Array.Clear(aData, 1, 8)
  If ((iRead And 1) > 0) Then aData(1) = True
  If ((iRead And 2) > 0) Then aData(2) = True
  If ((iRead And 4) > 0) Then aData(3) = True
  If ((iRead And 8) > 0) Then aData(4) = True
  If ((iRead And 16) > 0) Then aData(5) = True
  If ((iRead And 32) > 0) Then aData(6) = True
  If ((iRead And 64) > 0) Then aData(7) = True
  If ((iRead And 128) > 0) Then aData(8) = True

  'bit 1 = channel 1
  'bit 2 = channel 2
  'bit 3 = channel 3
  'bit 4 = channel 4
  'bit 5 = not used
  'bit 6 = coin validator binary line
  'bit 7 = NV busy
  'bit 8 = power supply ok

  'We work with the LowNibble => channel1-4, 
  'so we can detect 15 different bills and 15 different coins
  LowNibble = iRead And &HF

  '***********************************************************************
  ' BILL VALIDATOR BINARY MODE (bill signals bit6 is NOT set)
  '***********************************************************************

  'we store a backup flag in aBillPayed to prevent doubble counts

  If (LowNibble > 0) And aData(8) And Not aData(6) Then
    If Not aBillPayed(LowNibble) Then
      aBillPayed(LowNibble) = True
      iCredits = iCredits + aBillValue(LowNibble)
    End If

  '***********************************************************************
  ' COIN VALIDATOR BINARY MODE (coin signals bit6 is set)
  '***********************************************************************

  'we store a backup flag in aCoinPayed to prevent doubble counts

  ElseIf (LowNibble > 0) And aData(8) And aData(6) Then
    If Not aCoinPayed(LowNibble) Then
      aCoinPayed(LowNibble) = True
      iCredits = iCredits + aCoinValue(LowNibble)
    End If
  End If

  'show the Credits
  Label_Credits.Text = CStr(iCredits)

  'start the timer again
  TimerPoll.Enabled = True
End Sub


HOPPER-Interface:

Open and close the COM Port to the HOPPER-Interface

1. Open the COM Port to the CASH-Interface at the OnCreate routine of the main form

Delphi:
procedure TForm1.FormCreate(Sender: TObject);
begin
  HOPPER_OPENCOM(1);         // open COM1
end;
Visual Basic 6:
Private Sub Form_Load()
  HOPPER_OPENCOM(1)          'open COM1
End Sub
Visual Basic .NET:
Private Sub Form1_Load(ByVal eventSender As System.Object, 
ByVal eventArgs As System.EventArgs) Handles MyBase.Load
  HOPPER_OPENCOM(1)          'open COM1
End Sub
If the COM port cannot be opened you get a return value of -1 from the CASH_OPENCOM function.
This can be checked like this:

Delphi:
procedure TForm1.FormCreate(Sender: TObject);
begin
  if HOPPER_OPENCOM(1) = -1 then 
    MessageDlg('Error opening the COM-Port!', mtError, [mbOK], 0);
end;
Visual Basic 6:
Private Sub Form_Load()
  If HOPPER_OPENCOM(1) = -1 Then 
    MsgBox "Error opening the COM-Port!"
  End If
End Sub
Visual Basic .NET:
Private Sub Form1_Load(ByVal eventSender As System.Object, 
ByVal eventArgs As System.EventArgs) Handles MyBase.Load
  If HOPPER_OPENCOM(1) = -1 Then
    MsgBox "Error opening the COM-Port!"
  End If
End Sub
The COM-Port to the HOPPER-Interface is now open.

2. Close the COM Port to the HOPPER-Interface at the OnClose routine of the main form

Delphi:
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  HOPPER_CLOSECOM;
end;
Visual Basic 6:
Private Sub Form_Unload(Cancel As Integer)
  HOPPER_CLOSECOM
End Sub
Visual Basic .NET:
Private Sub Form1_FormClosed(ByVal eventSender As System.Object, 
ByVal eventArgs As System.Windows.Forms.FormClosedEventArgs) 
Handles Me.FormClosed
  HOPPER_CLOSECOM()
End Sub



Pay out coins

The easiest way to pay out coins is to use the function HOPPER1_PAYOUT(n) for hopper 1 and HOPPER2_PAYOUT(n) for hopper 2.

Delphi:
  Label_HOPPER1_PAYOUT.Caption := IntToStr(HOPPER1_PAYOUT(1));
  Label_HOPPER2_PAYOUT.Caption := IntToStr(HOPPER2_PAYOUT(1));
Visual Basic 6:
  Label_HOPPER1_PAYOUT.Caption = HOPPER1_PAYOUT(1)
  Label_HOPPER2_PAYOUT.Caption = HOPPER2_PAYOUT(1)
Visual Basic .NET:
  Label_HOPPER1_PAYOUT.Text = CStr(HOPPER1_PAYOUT(1))
  Label_HOPPER2_PAYOUT.Text = CStr(HOPPER2_PAYOUT(1))

For more possibilities and informations see CASH.DLL reference, Tips to control the hopper



COUNTER-Board:

Open and close the COM Port to the COUNTER-Board

1. Open the COM Port to the COUNTER-Board at the OnCreate routine of the main form

Delphi:
procedure TForm1.FormCreate(Sender: TObject);
begin
  COUNTER_OPENCOM(1);         // open COM1
end;
Visual Basic 6:
Private Sub Form_Load()
  COUNTER_OPENCOM(1)          'open COM1
End Sub
Visual Basic .NET:
Private Sub Form1_Load(ByVal eventSender As System.Object, 
ByVal eventArgs As System.EventArgs) Handles MyBase.Load
  COUNTER_OPENCOM(1)          'open COM1
End Sub
If the COM port cannot be opened you get a return value of -1 from the COUNTER_OPENCOM function.
This can be checked like this:

Delphi:
procedure TForm1.FormCreate(Sender: TObject);
begin
  if COUNTER_OPENCOM(1) = -1 then 
    MessageDlg('Error opening the COM-Port!', mtError, [mbOK], 0);
end;
Visual Basic 6:
Private Sub Form_Load()
  If COUNTER_OPENCOM(1) = -1 Then 
    MsgBox "Error opening the COM-Port!"
  End If
End Sub
Visual Basic .NET:
Private Sub Form1_Load(ByVal eventSender As System.Object, 
ByVal eventArgs As System.EventArgs) Handles MyBase.Load
  If COUNTER_OPENCOM(1) = -1 Then
    MsgBox "Error opening the COM-Port!"
  End If
End Sub
The COM-Port to the COUNTER-Board is now open.

2. Close the COM Port to the COUNTER-Board at the OnClose routine of the main form

Delphi:
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  COUNTER_CLOSECOM;
end;
Visual Basic 6:
Private Sub Form_Unload(Cancel As Integer)
  COUNTER_CLOSECOM
End Sub
Visual Basic .NET:
Private Sub Form1_FormClosed(ByVal eventSender As System.Object, 
ByVal eventArgs As System.Windows.Forms.FormClosedEventArgs) 
Handles Me.FormClosed
  COUNTER_CLOSECOM()
End Sub



Count

Counting is done with the function COUNTER_COUNT1(COUNT, SPEED) for counter 1 and COUNTER_COUNT2(COUNT, SPEED) for counter 2.

Delphi:
  COUNTER_COUNT1(1, 50);
  COUNTER_COUNT2(1, 50);
Visual Basic 6:
  Call COUNTER_COUNT1(1, 50)
  Call COUNTER_COUNT2(1, 50)
Visual Basic .NET:
  COUNTER_COUNT1(1, 50)
  COUNTER_COUNT2(1, 50)




Hint: You can find Delphi, Visual Basic 6 and Visual Basic .NET demo projects in the corresponding
subdirectory /example


Copyright © 2009 by bksoft