Interfacing with an LTC1298 dualchannel, 12-bit A/D


/* LTC1298_1.C  (Flashlite V25)
**
** Illustrates how to interface with a Linear LTC1298 Dual 12-bit A/D.
**
** For a data sheet on the LTC1298, see http://www.linear.com.
**
** Flashlite                              LTC1298
**                                ------ Dout (term 6)
**                               |
**                            1K |
** P2.2 DAT  --------------------------  Din (term 5)
** P2.1 CLK  --------------------------  Clk (term 7)
** P2.0 NOT_CS ------------------------ /CS (term 1)
**
** Routine performs an A/D conversion on Ch 0 (term 2 of LTC1298) and
** displays.  Repeats for Ch 1 (term 3).  Continually loops.
**
** Note the use of general functions put_bit and get bit to set a
** specified bit on a specified port to the specified state and to
** read a specific bit on a specified port.
**
** copyright, Peter H. Anderson, Baltimore, MD, Sept, '00
*/

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

#define SEG 0xf000
#define P2_OFFSET 0xff10
#define PM2_OFFSET 0xff11
#define PMC2_OFFSET 0xff12

typedef unsigned char byte;

#define NOT_CS 0
#define CLK 1
#define DAT 2

#define OUT 0
#define IN 1

int LTC1298_get_adc(byte far *p, byte ch);
void put_bit(byte far *p, byte bit_num, byte state);
byte get_bit(byte far *p, byte bit_num);


byte dirs;

void main(void)
{
   byte far *p2, *pm2, *pmc2;
   int ad_val;

   p2 = MK_FP(SEG, P2_OFFSET);
   pm2 = MK_FP(SEG, PM2_OFFSET);
   pmc2 = MK_FP(SEG, PMC2_OFFSET);

   *pmc2 = 0x00;  /* not special purpose */
   dirs = 0xff;
   *pm2 = dirs;     /* all of port 2 are inputs */

   while(1)
   {

      ad_val = LTC1298_get_adc(p2, 0);   /* perform a meas on Ch 0 */
      printf("Ch0   %4x\n", ad_val);
      ad_val = LTC1298_get_adc(p2, 1);   /* perform a meas on Ch 1 */
      printf("Ch1   %4x\n", ad_val);

      delay(1000);
   }
}

int LTC1298_get_adc(byte far *p, byte ch)
{
    int ad_val = 0x0000;
    byte n, ad_command;

    if (ch == 0)
    {
        ad_command = 0x0d;
    }

    else
    {
        ad_command = 0x0f;
    }

    dirs = dirs & (~0x07); /* make lower three bits outputs */
    *(p+1) = dirs;

    put_bit(p, NOT_CS, 1);   /* initial conditions */
    put_bit(p, CLK, 1);

    put_bit(p, NOT_CS, 0);   /* bring CS low - resets LTC1298 */

    for (n=0; n<4; n++) /* send the 4-bit command, most sig bit first */
    {
        if (ad_command & 0x08)
        {
           put_bit(p, DAT, 1);
        }
        else
        {
           put_bit(p, DAT, 0);
        }

        put_bit(p, CLK, 0);
        put_bit(p, CLK, 1);

        ad_command = ad_command << 1;
    }

    put_bit(p, CLK, 0);   /* dummy clock pulse */
    put_bit(p, CLK, 1);

    dirs = dirs | (0x01 << DAT); /* make DAT an input */
    *(p+1) = dirs;

    for (n=0; n<12; n++)   /* fetch the result, most sig bit first */
    {

     put_bit(p, CLK, 0);
     put_bit(p, CLK, 1);

     ad_val = (ad_val << 1) | get_bit(p, DAT);
    }

    put_bit(p, NOT_CS, 1);   /* turn off device */

    return(ad_val);
}


void put_bit(byte far *p, byte bit_num, byte state)
{
    byte mask_0, mask_1;
    mask_1 = 0x01 << bit_num;
    mask_0 = ~mask_1;

    if (state == 0)
    {
        *p = *p & mask_0;
    }
    else
    {
        *p = *p | mask_1;
    }
}

byte get_bit(byte far *p, byte bit_num)
{
    byte mask_1;
    mask_1 = 0x01 << bit_num;
    if (*p & mask_1)
    {
        return(1);
    }
    else
    {
        return(0);
    }
}