// This demo-program illustrates continuous reading and display of all four
// axes. All encoders are initialized to resolution = 4 clocks per cycle.
// Besides, the usage of encoder's Event Signal and the interrupt feature
// are demonstrated for encoders A and D:
// * The source of the Event Signal of Encoder A is adjusted to its Index
//   (Marker) pulse. The source of Chip #1 interrupt is set to the Event
//   Signal of Encoder A. Consequently, upon Index occurrence, Chip #1
//   interrupt is generated.
// * The source of the Event Signal of Encoder D is adjusted to SetPoint =
//   1000. The source of Chip #2 interrupt is set to the Event Signal of
//   Encoder D. Consequently, upon SetPoint occurrence, Chip #2 interrupt
//   is generated.
// Note that in order to utilize the interrupt feature you should put one
// short on card's jumpers per each used interrupt. It's recommended to use
// different IRQ's for the two chips in order to distinguish between the
// events. For example, select IRQ5 for Chip #1 and IRQ 7 for Chip #2.
// The following is quoted from your User's Guide:
//    Either IRQ5 or IRQ7 may be selected for each chip. There's an
//    individual selection for each chip, independent of the selection
//    of the other chip.
//    The selection for Chip #1 is done in JP100.
//    The selection for Chip #2 is done in JP101.
//    For IRQ5 selection, shorten the left  pair in JP100 or JP101.
//    For IRQ7 selection, shorten the right pair in JP100 or JP101.
// The program displays how many times each IRQ (5 or 7) occurred.

#include <bios.h>
#include <dos.h>
#include <stdio.h>
#include <conio.h>

#include "enc.h"

#define IRQ5_INTERRUPT_NUMBER            0x0D
#define IRQ7_INTERRUPT_NUMBER            0x0F

void  interrupt irq5_routine (...) ;
void  interrupt irq7_routine (...) ;
void  interrupt ( *original5 ) (...);
void  interrupt ( *original7 ) (...);
void CommunicationError(void);
char irq5_flag ;      // (same concept as with irq7_flag)
char irq7_flag ;      // 1 - IRQ7 occured.
		      //     irq7_flag is set to 1 by the interrupt
		      //     routine (irq7_routine).
		      // 0 - IRQ7 did NOT occur.
		      //     irq7_flag is cleared to 0:
		      //     1. By the initialization.
		      //     2. By main polling loop, after detecting that
		      //        irq7_flag has been set to 1 by irq7_routine.
int irq5_counter ;
int irq7_counter ;

void main(void)
{
int ReturnCode ;
int CardNumber ;
//int EncoderNumber ;
//int ChipNumber ;
int ChipInputsMirror ;
long PositionCounterA, PositionCounterB, PositionCounterC, PositionCounterD ;
long SetPoint ;

   original5 = getvect ( IRQ5_INTERRUPT_NUMBER );
   original7 = getvect ( IRQ7_INTERRUPT_NUMBER );
   setvect (IRQ5_INTERRUPT_NUMBER, irq5_routine) ;
   setvect (IRQ7_INTERRUPT_NUMBER, irq7_routine) ;
   outportb(0x21,0);         // Clear the PIC's Interrupt Disable Register
   irq5_flag = 0;                     // Interrupt not active
   irq5_counter = 0 ;
   irq7_flag = 0;                     // Interrupt not active
   irq7_counter = 0 ;

   CardNumber = 6 ;

   ReturnCode = SetActiveChip(CardNumber, Chip1) ;
   if (ReturnCode == 0)   CommunicationError();

   ReturnCode = SetEncoderResolution (CardNumber, Encoder1, Clock4);
   if (ReturnCode == 0)   CommunicationError();

   ReturnCode = SetEncoderResolution (CardNumber, Encoder2, Clock4);
   if (ReturnCode == 0)   CommunicationError();

   ReturnCode = SetIndexPulsePolarity (CardNumber, Encoder1, ActiveOnHigh);
   if (ReturnCode == 0)   CommunicationError();

   ReturnCode = SetIndexResetsPositionCounter (CardNumber, Encoder1, SetEnabled);
   if (ReturnCode == 0)   CommunicationError();

   ReturnCode = SetEncoderEventFlagSource (CardNumber, Encoder1, EventFlagSourceIndex);
   if (ReturnCode == 0)   CommunicationError();

   ReturnCode = SetEncoderEventFlagPolarity (CardNumber, Encoder1, ActiveOnHigh);
   if (ReturnCode == 0)   CommunicationError();

   ReturnCode = SetInterruptMode (CardNumber, SetEnabled);
   if (ReturnCode == 0)   CommunicationError();

   ReturnCode = SetInterruptPolarity (CardNumber, ActiveOnLow);
   if (ReturnCode == 0)   CommunicationError();

   ReturnCode = SetInterruptSource (CardNumber, InterruptSourceEncoder1Event);
   if (ReturnCode == 0)   CommunicationError();


   ReturnCode = SetActiveChip(CardNumber, Chip2) ;
   if (ReturnCode == 0)   CommunicationError();

   ReturnCode = SetEncoderResolution (CardNumber, Encoder1, Clock4);
   if (ReturnCode == 0)   CommunicationError();

   ReturnCode = SetEncoderResolution (CardNumber, Encoder2, Clock4);
   if (ReturnCode == 0)   CommunicationError();

   ReturnCode = SetIndexPulsePolarity (CardNumber, Encoder2, ActiveOnHigh);
   if (ReturnCode == 0)   CommunicationError();

   ReturnCode = SetIndexResetsPositionCounter (CardNumber, Encoder2, SetEnabled);
   if (ReturnCode == 0)   CommunicationError();

   ReturnCode = SetSetPoint (CardNumber, Encoder2,  1000L);
   if (ReturnCode == 0)   CommunicationError();

   ReturnCode = GetSetPoint (CardNumber, Encoder2,  &SetPoint);
   if (ReturnCode == 0)   CommunicationError();

   ReturnCode = SetEncoderEventFlagSource (CardNumber, Encoder2, EventFlagSourceSetPoint);
   if (ReturnCode == 0)   CommunicationError();

   ReturnCode = SetEncoderEventFlagPolarity (CardNumber, Encoder2, ActiveOnHigh);
   if (ReturnCode == 0)   CommunicationError();

   ReturnCode = SetInterruptMode (CardNumber, SetEnabled);
   if (ReturnCode == 0)   CommunicationError();

   ReturnCode = SetInterruptPolarity (CardNumber, ActiveOnLow);
   if (ReturnCode == 0)   CommunicationError();

   ReturnCode = SetInterruptSource (CardNumber, InterruptSourceEncoder2Event);
   if (ReturnCode == 0)   CommunicationError();

   ChipInputsMirror = 0 ;
   clrscr() ;

   gotoxy (2,17) ;
   printf ("Trigger for Encoder-A Event: Index (Marker) Signal") ;

   gotoxy (2,18) ;
   printf ("Trigger for Encoder-D Event: SetPoint = %lu", SetPoint) ;

   gotoxy (2,20) ;
   printf ("Press any key to stop -") ;

   while (bioskey(1) == 0) {  // Pressing any key stops the loop
      ReturnCode = SetActiveChip(CardNumber, Chip1) ;
      if (ReturnCode == 0)   CommunicationError();
      ReturnCode = RequestPositionCounter (CardNumber, Encoder1, ChipInputsMirror) ;
      if (ReturnCode == 0)   CommunicationError();
      ReturnCode = ReadPositionCounter (CardNumber, Encoder1, &PositionCounterA) ;
      if (ReturnCode == 0)   CommunicationError();
      ReturnCode = RequestPositionCounter (CardNumber, Encoder2, ChipInputsMirror) ;
      if (ReturnCode == 0)   CommunicationError();
      ReturnCode = ReadPositionCounter (CardNumber, Encoder2, &PositionCounterB) ;
      if (ReturnCode == 0)   CommunicationError();

      ReturnCode = SetActiveChip(CardNumber, Chip2) ;
      if (ReturnCode == 0)   CommunicationError();
      ReturnCode = RequestPositionCounter (CardNumber, Encoder1, ChipInputsMirror) ;
      if (ReturnCode == 0)   CommunicationError();
      ReturnCode = ReadPositionCounter (CardNumber, Encoder1, &PositionCounterC) ;
      if (ReturnCode == 0)   CommunicationError();
      ReturnCode = RequestPositionCounter (CardNumber, Encoder2, ChipInputsMirror) ;
      if (ReturnCode == 0)   CommunicationError();
      ReturnCode = ReadPositionCounter (CardNumber, Encoder2, &PositionCounterD) ;
      if (ReturnCode == 0)   CommunicationError();

      gotoxy (2,3) ;
      printf ("A = %8lu", PositionCounterA) ;
      clreol();

      gotoxy (2,4) ;
      printf ("B = %8lu", PositionCounterB) ;
      clreol();

      gotoxy (2,5) ;
      printf ("C = %8lu", PositionCounterC) ;
      clreol();

      gotoxy (2,6) ;
      printf ("D = %8lu", PositionCounterD) ;
      clreol();

      if (irq5_flag) {  // Interrupt 5 occurred
         irq5_flag = 0 ;
         gotoxy (2,11) ;
         printf ("Interrupt 5 occurred %d times.", irq5_counter) ;
        }
      if (irq7_flag) {  // Interrupt 7 occurred
         irq7_flag = 0 ;
         gotoxy (2,12) ;
         printf ("Interrupt 7 occurred %d times.", irq7_counter) ;
        }
   }
   clrscr() ;
}

void  interrupt irq5_routine (...)
{
  irq5_flag = 1 ;
  outportb(0x20,0x20);
  ++irq5_counter ;
}

void  interrupt irq7_routine (...)
{
  irq7_flag = 1 ;
  outportb(0x20,0x20);
  ++irq7_counter ;
}

void CommunicationError(void)
{
 gotoxy (2,20) ;
 printf ("Communication Error, Press any key to terminate.") ;
 while (bioskey(1) == 0) ;
}

