#use "default.h"
#use "kdm.lib"

/*
  ADSAMPL3.C

  A/D EXPANSION BOARD SAMPLE PROGRAM #3

  PROGRAM OPERATION
  -----------------
  This program builds a signal table with 1 entry for each of the 18 A/D
  channel numbers. Each channel is read and the actual voltage calculated
  using the calibration coefficients stored in the A/D board's EEPROM. The
  voltage is then displayed in the STDIO window.

  Each display will pause while waiting for a keypress to continue.
  Press <F4 if using DC for DOS> to enable keyboard input once the program
  is running.

  Apply input voltages to the various input pairs and observe their values
  when the appropriate channel is displayed.

  To obtain an actual voltage of a signal (pair) at the wago terminals
  the following steps must be performed:

  1) The analog mux must be set to select the proper input channel.
  2) A 400us mux settle time (maximum) must occur before accurate reading 
     of the A/D if the mux has been changed.
  3) The A/D must be read from the proper channel 0-17 depending on
     the desired gain of the input signal, polarity of the A/D read,
     and desired mode (differential or single-ended) of the input 
     lines.
  4) The resultant 12-bit number returned by the A/D must be converted
     to an actual voltage value.

  INPUT CHANNELS
  --------------
  "Input channel" refers to the analog input pair, AN0 thru AN7, that
  is selected by the analog mux.  Each input pair can be read at all
  18 A/D channels. In this example, the input channel for each A/D 
  channel is set to the modulo 8 value of the A/D channel number.
  Thus the mux is set to AN0+/- for analog channels 0,8,16; AN1+/- for 
  1,9,17; etc.
  

  A/D CHANNELS
  ------------
  Note: Although the A/D has 8 physical channels, channel numbers of 
        0-17 are used to utilize various combinations of gains,
        polarity, and single/differential-ended modes.  When calling
        a function that requests an A/D channel number, the channel 
        number determines which combination to use:
  
         ch#   Polarity    Input                         Gain Stage ?
       -----   --------    -------------------------     ------------
          0:   Bipolar     ANx+ w/respect to A/D gnd          No 
          1:   Bipolar     ANx- w/respect to A/D gnd          No 
        2-7:   Bipolar     ANx+/- differential           Yes (2 to 202)
          8:   Unipolar    ANx+ w/respect to A/D gnd          No 
          9:   Unipolar    ANx- w/respect to A/D gnd          No 
      10-15:   Unipolar    ANx+/- differential           Yes (2 to 202)
         16:   Bipolar     ANx+/- differential                No 
         17:   Unipolar    ANx+/- differential                No 

      * ANx refers to the input mux pair selection AN0 through AN7
      * Channels 2-7, 10-15 have gains of 2,202,22,42,102,6 respectively.
   

  SIGNAL TABLE - "adtab"
  ------------
  A signal table called "adtab" is constructed before reading the A/D. 
  The table is used by the expansion library and must be initialized   
  in the application with the statement:

    struct signal_rec adtab[SIZE];

  where SIZE is the number of entries in the table.  The structure
  signal_rec is defined in plc_exp.lib.  The entries are added to the
  table with the function add_sig_table.  Once this is accomplished,
  accessing signals is a straightforward matter.

**************************************************************************

  EEPROM Calibration Table Format - 18 records x 4-byte record = 72 bytes
     Each A/D board must have this information to use calibration.

   4-Byte Records
   --------------------------------------------------------------
     0-7:  Bipolar Channels, single-ended  (A/D channels 0-7)
    8-15:  Unipolar Channels, single-ended (A/D channels 0-7)
      16:  Bipolar, Differental pair (A/D ch 0(+)/1(-) )
      17:  Unipolar, Differental pair (A/D ch 0(+)/1(-) )

  RECORD FORMAT
  ---------------------------------------------------------------
  Zero offset:     1-byte  - Channel Zero offset in A/D counts (sign extended)
  Gain Integer:    1-byte  - integer value of gain 0-255
  Gain Fraction:   2-bytes - Fractional value of gain / 64K.

*/

#define BUSWR  0x00ce

static char ash,bsh;

/* Define the analog signal table - 18 entries
---------------------------------------------- */
struct signal_rec adtab[18];

int view_table(int entry_number);

main()
{
int bd,ch,read,i;
float voltage;

  /* Prelim-Setup 
  --------------- */
	reset_pbus();           // reset the plcbus
	reset_pbus_wait();      // wait for reset to end   

	if(sysclock() > 0x1e00)
		reset_pbus_wait();   // for boards faster than 9 Mhz
									// double wait.         
  bd = plcad_addr(3);

  /* Build signal table for 18 signals
  ------------------------------------ */
  for (i=0; i<18; i++)          
    add_sig_table(i,bd,i%8,i,1); 

  /* Display table entries to crt for review
  ------------------------------------------ */
  for (i=0; i<18; i++)
  { view_table(i);               /* display table entries */
    getchar();                   /* Wait for keypress */
    hitwd();
   }

  /* Read 1st 8 channels the easy (slow) way and display values
  ------------------------------------------------------------- */
  for(i=0;i<8;i++)
  { voltage = slow_plad12(i);
    printf("a/d ch %d: %f volts\n",i,voltage); 
    getchar();
    hitwd();
   }

  /* Read channels 8-17 the fast way and display values
  ----------------------------------------------------- */
  for(i=0;i<18;i++)
  { set_mux(i);                  /* Set mux for signal #0 */
    mxdel18();                   /* Analog mux requires settle time */
    ch = adch(i);                /* get AD channel # */
    read = plad_rd12(ch);        /* read A/D */
    voltage = ad_conv(i,read);   /* handles all conversion, compensation */
    printf("a/d ch %d: %x = %f volts\n\n",i,read,ad_conv(i,read));
    getchar();
    hitwd();
   }

}

/*************************************************************************
 view_table - displays the contents of an entry in the entry table
*************************************************************************/

int view_table(int sig)
{
 static char gstr[18][20] =
 { "0 (x1 +inp only)","1 (x1 -inp only)","2 (x2)","3 (x202)","4 (x22)",
   "5 (x42)","6 (x102)",
   "7 (x6)","8 (x1 +inp only)","9 (x1 -inp only)","10 (x2)","11 (x202)",
   "12 (x22)","13 (x42)","14 (x102)","15 (x6)","16 (x1)","17 (x1)" };
                

  printf("\nANALOG TABLE ENTRY #%d\n",sig);
  printf("Board Addr: %x  Input Channel: AN%d  A/D Channel: %s \n",
          adtab[sig].address,adtab[sig].input_ch,gstr[adtab[sig].ad_ch]);

    printf("Compensation Coef: %9.8f   Zero Offset: %d counts\n",    
            adtab[sig].cal_coef,csign_ext(adtab[sig].zero_offset));
  
  if (polarity(adtab[sig].ad_ch) == UNIPOLAR)
    printf("Polarity: UNIPOLAR   ");
  else
    printf("Polarity: BIPOLAR    ");

  if (adtab[sig].comp_flag)
    printf("Compensation: ON   ");
  else
    printf("Compensation: OFF  ");

  if (adtab[sig].ad_ch < 16)
    printf("A/D Mode: SINGLE-ENDED\n");
  else
    printf("A/D Mode: DIFFERENTIAL\n");
}

/****************************************************************************
  dispcal - display eeprom calibration record for given channel
****************************************************************************/
dispcal(int bd, int ad_ch)
{ int zoff, gi, gf1, gf2, gf;
  float gain;

  bd=0x190;
  set4adr(bd|BREG);
  zoff = csign_ext(adee_rd(bd,ad_ch*4));
  gi = adee_rd(bd,ad_ch*4+1);
  gf1 = adee_rd(bd,ad_ch*4+2);
  gf2 = adee_rd(bd,ad_ch*4+3);
  gain = gi + ((gf2 << 8) + gf1)/4096.;

  printf("CALIBRATION RECORD FOR CHANNEL: %d\n",ad_ch);
  printf("zero offset: %d counts   Channel Gain: %8.4f\n",zoff,gain);
}



