{*********************************************************}

{   AP10PC.PAS                                            }

{   by Miaochen Wu                                        }

{                                                         }

{   Accessing the ADS1210 Demo Board with Your PC         }

{   Application Note AB-113                               }

{   Burr-Brown Corp., 1997                                }

{                                                         }

{   Turbo Pascal 7.0                                      }

{*********************************************************}



program AP10PC;



uses    CRT, DOS;



const

   MCwrite51            = $00;

   MCretrieve           = $20;

   MCwrite1210          = $40;

   MCread1210           = $60;

   MCreadback           = $80;

   MCconvert            = $A0;

   MCsync               = $C0;

   MCpcgetl             = $E0;



var

   strbaddr             : Word;

   wraddr               : Word;

   rdaddr               : Word;

   pPrintPort           : ^word;

   RADSSetup            : Longint;

   INSRegCode           : Byte;

   CMRegCode            : Longint;

   OCRegCode            : Longint;

   FCRegCode            : Longint;



   XAddr_DOR2           : Byte;

   XAddr_DOR1           : Byte;

   XAddr_DOR0           : Byte;

   XAddr_INSR           : Byte;

   XAddr_CMR3           : Byte;

   XAddr_CMR2           : Byte;

   XAddr_CMR1           : Byte;

   XAddr_CMR0           : Byte;

   XAddr_OCR2           : Byte;

   XAddr_OCR1           : Byte;

   XAddr_OCR0           : Byte;

   XAddr_FCR2           : Byte;

   XAddr_FCR1           : Byte;

   XAddr_FCR0           : Byte;

   XAddr_ADS            : Byte;

   ADSID                : Byte;



   XAddr_READADD0       : Byte;

   XAddr_READADD1       : Byte;

   XAddr_READADD2       : Byte;



   Nbyte2x              : Byte;

   INSRaddr             : Byte;

   Readback             : Boolean;







procedure ADSRback; forward;

procedure ReadSetup(var SURdError : Boolean;

          ADSSetupCode : longint); forward;

procedure ReadData(Nt : longint; ConvertTime : Real;

          var OldReadTime : Real; var DRdError : Boolean);

          forward;





procedure MC51write(MC51code : byte);

var

   busy         : Byte;

   K            : Word;



begin

  { busy=H in board, busy7=L in code }

  K :=0;

  busy := PORT[rdaddr] AND $80;

  while (busy <> $80) AND (K<=80000) do

    begin

    busy := PORT[rdaddr] AND $80;

    inc(K);

    end;



  PORT[wraddr] := MC51code;

  delay(1);

  PORT[strbaddr] := 1;

  delay(0);

  PORT[strbaddr] := 0;

  delay(1);



  if K >= 80000 then

    begin

    sound(1000);

    delay(200);

    nosound;

    writeln;

    writeln('Program halted as System Setup Errors detected.');

    writeln('Possible causes include: Power supply off, Bad cables,Program halted as System Setup Errors detected.');

    writeln('Wrong PC Parallel Port, ADS1210 not installed.');

    sound(1000);

    delay(300);

    nosound;

    halt;

    end;

end;





procedure revbit(revin : byte; var revcode : byte);

var

   i    : word;

   j    : word;



begin

  revcode := 0;

  j := 1;

  for i := 0 to 7 do

    begin

    revcode := revcode SHL 1;

    if revin AND j > 0 then

    revcode := revcode + 1;

    j := j SHL 1;

    end;

end;





procedure Renew;

type

    NewCType    = array[1..3] of Byte;

var

   CMRbyte      : Byte;

   OCRbyte      : Byte;

   FCRbyte      : Byte;

   revcode      : Byte;

   CC           : Byte;

   NewCode      : NewCType;



begin

    {Write CMR byte 3}

    CMRbyte := ( CMRegCode SHR 24 ) AND $FF;

    MC51write((MCwrite51 OR XAddr_CMR3));

    revbit(CMRbyte,revcode);

    MC51write(revcode);

    {Write CMR byte 2}

    CMRbyte := ( CMRegCode SHR 16 ) AND $FF;

    MC51write((MCwrite51 OR XAddr_CMR2));

    revbit(CMRbyte,revcode);

    MC51write(revcode);

    {Write CMR byte 1}

    CMRbyte := ( CMRegCode SHR 8 ) AND $FF;

    MC51write((MCwrite51 OR XAddr_CMR1));

    revbit(CMRbyte,revcode);

    MC51write(revcode);

    {Write CMR byte 0}

    CMRbyte := CMRegCode AND $FF;

    MC51write((MCwrite51 OR XAddr_CMR0));

    revbit(CMRbyte,revcode);

    MC51write(revcode);



    {Write INSR}

    delay(100);

    MC51write((MCwrite51 OR XAddr_INSR));

    MC51write($64);



    {Programming ADS1210}

    MC51write(MCwrite1210);



    {Write OCR}

    delay(100);

    OCRbyte := ( OCRegCode SHR 16 ) AND $FF;

    MC51write((MCwrite51 OR XAddr_OCR2));

    revbit(OCRbyte,revcode);

    MC51write(revcode);

    OCRbyte := ( OCRegCode SHR 8 ) AND $FF;

    MC51write((MCwrite51 OR XAddr_OCR1));

    revbit(OCRbyte,revcode);

    MC51write(revcode);

    OCRbyte := OCRegCode AND $FF;

    MC51write((MCwrite51 OR XAddr_OCR0));

    revbit(OCRbyte,revcode);

    MC51write(revcode);

    delay(100);

    MC51write((MCwrite51 OR XAddr_INSR));

    MC51write($48);

    MC51write(MCwrite1210);



    {Write FCR}

    delay(100);

    FCRbyte := ( FCRegCode SHR 16 ) AND $FF;

    MC51write((MCwrite51 OR XAddr_FCR2));

    revbit(FCRbyte,revcode);

    MC51write(revcode);

    FCRbyte := ( FCRegCode SHR 8 ) AND $FF;

    MC51write((MCwrite51 OR XAddr_FCR1));

    revbit(FCRbyte,revcode);

    MC51write(revcode);

    FCRbyte := FCRegCode AND $FF;

    MC51write((MCwrite51 OR XAddr_FCR0));

    revbit(FCRbyte,revcode);

    MC51write(revcode);

    delay(100);

    MC51write((MCwrite51 OR XAddr_INSR));

    MC51write($4C);

    MC51write(MCwrite1210);



    {Read back ADS1210}

    NewCode[1] := $E4;

    NewCode[2] := $C8;

    NewCode[3] := $CC;

    for CC := 1 to 3 do

      begin

      delay(100);

      INSRegCode := NewCode[CC];

      Nbyte2x := (INSRegCode AND $60) SHR 5;

      Nbyte2x := Nbyte2x + 1;

      Nbyte2x := Nbyte2x SHL 1;

      INSRaddr := INSRegCode AND $1F;

      MC51write((MCwrite51 OR XAddr_INSR));

      MC51write(INSRegCode);

      MC51write(MCread1210);

      delay(100);

      ReadBack := True;

      ADSRBack;

      end;

end;





procedure SetINSR;

var

   I            : Byte;



begin

  Nbyte2x := (INSRegCode AND $60) SHR 5;

  Nbyte2x := Nbyte2x + 1;

  Nbyte2x := Nbyte2x SHL 1;

  INSRaddr := INSRegCode AND $1F;

  MC51write((MCwrite51 OR XAddr_INSR));

  MC51write(INSRegCode);

  I := INSRegCode AND $80;

  case I of

    $00:  begin

          if ((INSRaddr = $00) OR (INSRaddr = $01)

          OR (INSRaddr = $02)) then

            writeln('Don''t write data register. ')

          else

            MC51write(MCwrite1210);

          end;

    $80:  begin

          MC51write(MCread1210);

          ReadBack := True;

          ADSRBack;

          end;

  end;

end;





procedure SetCMR;

var

  CMRbyte       : Byte;

  revcode       : Byte;



begin

     {CMR Byte 3}

     CMRbyte := ( CMRegCode SHR 24 ) AND $FF;

     MC51write((MCwrite51 OR XAddr_CMR3));

     revbit(CMRbyte,revcode);

     MC51write(revcode);

     {CMR Byte 2}

     CMRbyte := ( CMRegCode SHR 16 ) AND $FF;

     MC51write((MCwrite51 OR XAddr_CMR2));

     revbit(CMRbyte,revcode);

     MC51write(revcode);

     {CMR Byte 1}

     CMRbyte := ( CMRegCode SHR 8 ) AND $FF;

     MC51write((MCwrite51 OR XAddr_CMR1));

     revbit(CMRbyte,revcode);

     MC51write(revcode);

     {CMR Byte 0}

     CMRbyte := CMRegCode AND $FF;

     MC51write((MCwrite51 OR XAddr_CMR0));

     revbit(CMRbyte,revcode);

     MC51write(revcode);



     { Setup for reading back }

     INSRegCode := $64;

     Nbyte2x := (INSRegCode AND $60) SHR 5;

     Nbyte2x := Nbyte2x + 1;

     Nbyte2x := Nbyte2x SHL 1;

     INSRaddr := INSRegCode AND $1F;

     Delay(10);

     MC51write((MCwrite51 OR XAddr_INSR));

     MC51write(INSRegCode);

     MC51write(MCwrite1210);

     delay(100);

     INSRegCode := $E4;

     MC51write((MCwrite51 OR XAddr_INSR));

     MC51write(INSRegCode);

     MC51write(MCread1210);

     delay(100);

     ReadBack := True;

     ADSRback;



end;





procedure SetOCR;

var

  OCRByte       : Byte;

  revcode       : Byte;



begin

     {OCR Byte 3}

     OCRbyte := ( OCRegCode SHR 16 ) AND $FF;

     MC51write((MCwrite51 OR XAddr_OCR2));

     revbit(OCRbyte,revcode);

     MC51write(revcode);

     {OCR byte 2}

     OCRbyte := ( OCRegCode SHR 8 ) AND $FF;

     MC51write((MCwrite51 OR XAddr_OCR1));

     revbit(OCRbyte,revcode);

     MC51write(revcode);

     {OCR byte 0}

     OCRbyte := OCRegCode AND $FF;

     MC51write((MCwrite51 OR XAddr_OCR0));

     revbit(OCRbyte,revcode);

     MC51write(revcode);



     {Setup for reading back}

     INSRegCode := $48;

     Nbyte2x := (INSRegCode AND $60) SHR 5;

     Nbyte2x := Nbyte2x + 1;

     Nbyte2x := Nbyte2x SHL 1;

     INSRaddr := INSRegCode AND $1F;

     Delay(10);

     MC51write((MCwrite51 OR XAddr_INSR));

     MC51write(INSRegCode);

     MC51write(MCwrite1210);

     delay(100);

     INSRegCode := $C8;

     MC51write((MCwrite51 OR XAddr_INSR));

     MC51write(INSRegCode);

     MC51write(MCread1210);

     delay(100);

     ReadBack := True;

     ADSRBack;



end;





procedure SetFCR;

var

  FCRbyte       : Byte;

  revcode       : Byte;



begin

     {FCR Byte 2}

     FCRbyte := ( FCRegCode SHR 16 ) AND $FF;

     MC51write((MCwrite51 OR XAddr_FCR2));

     revbit(FCRbyte,revcode);

     MC51write(revcode);

     {FCR byte 1}

     FCRbyte := ( FCRegCode SHR 8 ) AND $FF;

     MC51write((MCwrite51 OR XAddr_FCR1));

     revbit(FCRbyte,revcode);

     MC51write(revcode);

     {FCR byte 0}

     FCRbyte := FCRegCode AND $FF;

     MC51write((MCwrite51 OR XAddr_FCR0));

     revbit(FCRbyte,revcode);

     MC51write(revcode);



     {Setup for reading back}

     INSRegCode := $4C;

     Nbyte2x := (INSRegCode AND $60) SHR 5;

     Nbyte2x := Nbyte2x + 1;

     Nbyte2x := Nbyte2x SHL 1;

     INSRaddr := INSRegCode AND $1F;

     Delay(10);

     MC51write((MCwrite51 OR XAddr_INSR));

     MC51write(INSRegCode);

     MC51write(MCwrite1210);

     delay(100);

     INSRegCode :=$CC;

     MC51write((MCwrite51 OR XAddr_INSR));

     MC51write(INSRegCode);

     MC51write(MCread1210);

     delay(100);

     ReadBack := True;

     ADSRBack;



end;





procedure ADSsync;



begin

     MC51write((MCwrite51 OR XAddr_ADS));

     MC51write(ADSID);

     MC51write(MCsync);

end;





procedure ADSRback;

var

  NRbackBit       : Byte;

  Dbyte3          : Byte;

  Dbyte2          : Byte;

  Dbyte1          : Byte;

  Dbyte0          : Byte;

  coderev         : Byte;

  RdError         : Boolean;

  codetype        : string[4];



begin



  If (ReadBack = True) then

    begin

      case INSRaddr of

        $04,$05,$06,$07:  begin

                          codetype :='CMR';

                          ReadSetup(RdError,CMRegCode);

                          end;

        $08,$09,$0A:      begin

                          codetype := 'OCR';

                          ReadSetup(RdError,OCRegCode);

                          end;

        $0C,$0D,$0E:      begin

                          codetype := 'FCR';

                          ReadSetup(RdError,FCRegCode);

                          end;

      else

        RdError := True;

      end;

    end;



  if (RdError = True) then

    writeln('Setup Readback Error.')

  else

    writeln('The ' ,codetype, ' readback is  ', RADSSetup);



end;





procedure Retrieve;

var

  Hour          : Word;

  Minute        : Word;

  Second        : Word;

  Sec100        : Word;

  Nt            : longint;

  RdError       : Boolean;

  OldReadTime   : Real;

  ConvertTime   : Real;



begin

  GetTime(Hour, Minute, Second, Sec100);

  OldReadTime := 3600*Hour + 60*Minute + Second + Sec100 div 100;

  ConvertTime := 0.01; {ADS1210 Data Rate = 100Hz}

  Nt := 16; { Number of Data point }

  Nbyte2x := 6;

  ReadData(Nt, ConvertTime, OldReadTime, RdError);

  if(RdError = True) then

    writeln('Data Retrieval Error.');



end;





{Procedure ReadSetup reads back ADS1210 data }

procedure ReadSetup(var SURdError : Boolean; ADSSetupCode : longint);

var

   FNum         : Longint;

   readbkloop   : Longint;

   BusyBit      : Byte;    { data ready bit }

   nib          : Byte;    { nibble from MC51 }

   iRd          : Word;

   K            : Word;

   coderev      : Byte;



begin

  SURdError := False;

  Fnum := $FFFFFFFF;

  if SURdError = False then

    begin

    readbkloop := 0;

    WHILE ((FNUM AND $FFFFFFFF) <> (ADSSetupCode AND $FFFFFFFF))

    AND (readbkloop < 1) DO

      BEGIN

      readbkloop := readbkloop + 1;

      Fnum := 0;

      for iRd := 1 to NByte2x do

        begin

        K :=0;

        BusyBit := PORT[rdaddr] AND $80;

        while (BusyBit <> $80) AND (K <= 200000)  do

          begin

          BusyBit := PORT[rdaddr] AND $80;

          inc(K);

          if (K mod 40) = 0 then delay(1);

          if K = 200000 then SURdError := True;

          end;

        PORT[wraddr] := $80;

        delay(1);

        PORT[strbaddr] := 1;

        delay(0);

        PORT[strbaddr] := 0;

        delay(1);

        nib := (PORT[rdaddr] AND $78) SHL 1;

        revbit(nib,coderev);

        Fnum := Fnum SHL 4;

        FNum := Fnum OR coderev;

        end; { end of NByte2x nibbles}

      RADSSetup := FNum;

      END;

    end;



  { end read setup code }

  K :=0;

  BusyBit := PORT[rdaddr] AND $80;

  While (BusyBit <> $80) AND (K <= 200000) do

    begin

    BusyBit := PORT[rdaddr] AND $80;

    inc(K);

    if (K mod 80) = 0 then delay(1);

    if K = 200000 then SURdError := True;

    end;

  PORT[wraddr] := $E0;

  delay(1);

  PORT[strbaddr] := 1;

  delay(0);

  PORT[strbaddr] := 0;

  delay(1);



end;





procedure ReadData(Nt : longint; ConvertTime : Real;

                      var OldReadTime : Real;

                      var DRdError : Boolean);

{ Needs 32 bit CMR code from main program.

This procedure checks data valid untill ready,

read the word 4 bits at a time, MSB first,

reassemble it, determines data format,(unipolar

2's completement MSByte), returns a final 24bit

number (Fnum) in the proper format}



var

  FNum          : Longint;

  readbkloop    : Longint;

  J             : Longint;

  BusyBit       : Byte;    { data ready bit }

  nib           : Byte;    { nibble from MC51 }

  Hour          : Word;

  Minute        : Word;

  Second        : Word;

  Sec100        : Word;

  RdError       : Boolean;

  iRd           : Word;

  K             : Word;

  normdata      : Real;

  FScale        : Real;

  NewReadTime   : Real;

  DelTime       : Real;

  DataTime      : Real;

  coderev       : Byte;

  Dbyte2        : Byte;

  Dbyte1        : Byte;

  Dbyte0        : Byte;



begin



  DataTime := (Nt+100) * ConvertTime;

  DelTime := 0;

  while DelTime < DataTime do

    begin

    GetTime(Hour, Minute, Second, Sec100);

    NewReadTime := 3600*Hour + 60*Minute + Second + Sec100/100;

    DelTime := NewReadTime - OldReadTime;

    if KeyPressed AND (ReadKey = chr(27)) then DelTime := DataTime;

    end;



  FScale := 16777216;



  {Send MCODE=MCretrive to evaluation board}

  DRdError :=  False;

  K := 0;

  Busybit := PORT[rdaddr] AND $80;

  while (Busybit <> $80) AND (K <= 200000)  do

    begin

    Busybit := PORT[rdaddr] AND $80;

    inc(K);

    if (K mod 80) = 0 then delay(1);

    if K = 200000 then DRdError := True;

    end;



  PORT[wraddr] := $20;

  delay(1);

  PORT[strbaddr] := 1;

  delay(0);

  PORT[strbaddr] := 0;

  delay(1);



  {Wait for evaluation board data valid}

  K := 0;

  BusyBit := PORT[rdaddr] AND $80;

  While (BusyBit <> $80) AND (K <= 200000) do

    begin

    BusyBit := PORT[rdaddr] AND $80;

    inc(K);

    if (K mod 80) = 0 then delay(1);

    if K = 200000 then DRdError := True;

    end;



  if DRdError = False then

    begin

    for J := Nt-1 downto 0 do

      begin

      Fnum := 0;

      for iRd := 1 to NByte2x do

        begin

        PORT[strbaddr] := $02;

        delay(0);

        PORT[strbaddr] := 0;

        delay(1);

        nib := (PORT[rdaddr] AND $78) SHL 1;

        revbit(nib,coderev);

        Fnum := Fnum SHL 4;

        FNum := Fnum OR coderev;

        end;



{ In the case of MSByte first, MSB first and 2's complement }

      if (Fnum AND $800000) > 1 then

        Fnum := Fnum OR $FF000000

      else

        Fnum := Fnum AND $7FFFFF;

      normdata :=  Fnum / FScale;

      writeln('The Data [',J,'] = ',10*normdata:8:7, '  Volts');

      end;

    end;



  K :=0;

  BusyBit := PORT[rdaddr] AND $80;

  While (BusyBit <> $80) AND (K <= 200000) do

    begin

    BusyBit := PORT[rdaddr] AND $80;

    inc(K);

    if (K mod 80) = 0 then delay(1);

    if K = 200000 then DRdError := True;

    end;

  PORT[wraddr] := $E0;

  delay(1);

  PORT[strbaddr] := 1;

  delay(0);

  PORT[strbaddr] := 0;

  delay(1);



  GetTime(Hour, Minute, Second, Sec100);

  OldReadTime := 3600*Hour + 60*Minute + Second + Sec100/100;



end;





procedure PCPort;



begin

  {Get LPT1 or LPT2 Address from BIOS Memory}

  {LPT1}

  pPrintPort := Ptr($40,$08);

  {LPT2}

  {pPrintPort := Ptr($40,$0A);}

  wraddr := pPrintPort^;

  rdaddr := wraddr + 1;

  strbaddr := wraddr + 2;

end;





{***********************}

{***  Main Program   ***}

{***********************}





begin



{ ADS1210 Configuration }

  {INSR = 01100100}

  INSRegCode := $64;

  {CMR = 01000010_00100000_00000001_01000110}

  CMRegCode := $40200146;

  {OCR = 00000000_00000000_00000000}

  OCRegCode := $000000;

  {FCR = 10100011_01110101_10010100}

  FCRegCode := $A37594;



{Address Definiton}

  XAddr_DOR2 := $00;

  XAddr_DOR1 := $01;

  XAddr_DOR0 := $02;

  XAddr_INSR := $03;

  XAddr_CMR3 := $04;

  XAddr_CMR2 := $05;

  XAddr_CMR1 := $06;

  XAddr_CMR0 := $07;

  XAddr_OCR2 := $08;

  XAddr_OCR1 := $09;

  XAddr_OCR0 := $0A;

  XAddr_FCR2 := $0C;

  XAddr_FCR1 := $0D;

  XAddr_FCR0 := $0E;

  XAddr_ADS  := $0B;

{ADSID = $00 for ADS1210/11 and $01 for ADS1212/13 }

  ADSID      := $00;



  Nbyte2x    := 6;

  ReadBack   := False;



{Run procedures}

  writeln('AP10PC Program (SPISC)');

  PCPort;

  delay(1000);

  Renew;

  delay(1000);

  Retrieve;



end.

