ECE 371 Lab 9 -- AD / DA Experiment

It is at the discretion of you lab TA exactly which experiment you will be doing.

Alternatives:
Sample data from the function generator using the external AD DA device.  Then output the sampled data to the DA and read in on the CRO.  Use channel 1 to display the function generator signal.  Use channel 2 to display the output from the DA line.  Compare the signals and see if they match. (With the exception of a phase shift.)
 

Interesting concepts:
1.  Demonstrate the Niquist Sampling therom/rate.

Word document from Drake: AD

Email from Dr. Drake:

The following is a copy of the A/D and D/A lab that replaces the Stanton A/D and
D/A laboratory.  A copy of also present on my web page
(http://tldrake-pc.ces.clemson.edu/e371/e371adla.htm).  I will do  some more
proof reading before I distribute this laboratory to the students later this
week.

Some problems with this lab are as follows:

        The default address of the PC-Multilab boards is 0x220.  This same
address is used by sound cards.  I don't think the PCs int he lab have sound
cards so this default address is not a problem.  The base address of PC-Multilab
board is jumper selectable and could be changed to 0x230 if there is a problem.

        The examples code that is shown uses IR4 as the interrupt request line.
The interrupt request line is selectable by software.

        I have the PC-Multilab board interface to a Zenith in my PC.  This Zenith
is an XT and is very slow and can not run at a 10 Khz sampling rate.  I had to
select a sampling rate of 5/8 Khz to make this board work on my PC.

        The laboratory writeup has a lot of information relative to DSP chips.
This has been added for educational purposes to educate the students.

                               A/D D/A LAB (PC-MULTILAB)
                                   DIGITAL FILTERING

OBJECTIVE:  In this lab, the student will use the A/D, D/A, 8253 timer, and
interrupt facilities of the PC-Multilab data acquisition board.  A signal will be
recorded over a T (5 seconds) second interval.  The 8253 timer on the PC-Multilab
board will produce 8,000 interrupts per second to generate the sampling frequency
of 8 KHz.  The samples will be double buffered and written to a disk file.  The
samples will then be filtered, using a digital filter routine provided by the
student.  Finally, both the filtered and the unfiltered sampled signals will be
played back via the D/A using double buffering and 8253 interrupts.

PCL-711S PC-MULTILAB INTERFACE:

Port Address Map:

        Location                Read                    Write
        BASE+0          8253 Counter 0  8253 Counter 0
        BASE+1          8253 Counter 1  8253 Counter 1
        BASE+2          8253 Counter 2  8253 Counter 2
        BASE+3          N/A                     8253 Control
        BASE+4          A/D Low         D/A Low
        BASE+5          A/D High + Status       D/A High
        BASE+6          D/I Low         N/A
        BASE+7          D/I High                N/A
        BASE+8          N/A                     Clear Interrupt Request
        BASE+9          N/A                     Gain Control
        BASE+10         N/A                     Multiplexer Channel
        BASE+11         N/A                     Mode + Interrupt Control
        BASE+12         N/A                     Software A/D Trigger
        BASE+13         N/A                     D/O Low
        BASE+14         N/A                     D/O High
        BASE+15         N/A                     N/A

A/D Data Registers:

        The A/D converter consists of an 8 channel multilpexer, amplifier, and a
12-bit A/D converter.  The analog input is bipolar (-5 to +5 Volts) while the
digital output is unipolar (0 to 4095).  The relationship between input and
output for an amplifier gain of 1 is as follows:

                ad_output = (ad_input + 5)*4096/10

That is, an input of -5 Volts produces an output of 0, an input of 0 Volts
produces an output of 2048, and an input of 2.5 Volts produces an output of 3072.

        The register coding is as follows:

                BASE+4: AD7..AD0
                BASE+5: DRDY, AD11..AD8

                DRDY=0  Conversion Complete
                DRDY=1  Conversion not Complete
                                                Set after read BASE+4

A/D Gain Control Register:

        There in an amplifier between the multiplexer and the A/D converter.  The
input range of the A/D converter is -5 Volts to +5 Volts.

                BASE+9: 0       x1
      1       x2
      2       x4
      3       x8
      4       x16

Multiplexer A/D Channel:

        The multiplexer has 8 channels.  This system is a single ended system
where all signals share a common ground.

                BASE+10:        0       Channel 0
      1       Channel 1
      2       Channel 2
      3       Channel 3
      4       Channel 4
      5       Channel 5
      6       Channel 6
      7       Channel 7

Mode and Interrupt Control Register:

        The A/D conversion can be triggered by software, by the 8253 pacer clock,
or by an external pulse.  The converted A/D data can be transferred to the
computer by software (busy waits) or by interrupt.  In addition, the interrupt
request line is selectable.

                BASE+11:        0xIM

                        M       0       S/W Trigger and Data Transfer
                        M       1       S/W Trigger and Data Transfer
                        M       2       Ext. Trigger and S/W Data Transfer
                        M       3       Ext. Trigger and Interrupt Transfer
                        M       4       8253 Trigger and S/W Data Transfer
                        M       5       Reserved
                        M       6       8253 Trigger and Interrupt Transfer
                        M       7       Reserved

                        I       0       IRQ2
                        I       1       N/A
                        I       2       IRQ2
                        I       3       IRQ3
                        I       4       IRQ4
                        I       5       IRQ5
                        I       6       IRQ6
                        I       7       IRQ7

        For example, a value of 0x56 states that the A/D will be triggered by the
8253 and the A/D will generate an interrupt on IRQ5 when the conversion is
complete.

Clear Interrupt Status:

        Any write to BASE+8 will clear the interrupt status.  This register must
be cleared initially and by the interrupt handler on each interrupt.

Software Trigger:

        Any write to BASE+12 will initiate an A/D conversion.

D/A Conversion:

        The D/A converter is a 12-bit unipolar input (0 to 4095) and 5 Volt
unipolar output (0 to 5 Volts).  The relationship between the digital input and
the analog output is

                Vda = 5*digital_input/4096

Therefore, a digital input of 2048 produces an output of approximately +2.5
volts.

        The register map for the D/A is as follows:

                BASE+4: Low byte
                BASE+5: High byte (MSB 4-bits)

The low byte should be loaded before the high byte.  The D/A is double buffered
and the D/A changes whenever the high byte is written.

Pacer 8253 Programming:

        The pacer clock is implemented with both Counter 1 and Counter 2.  Both
must be programmed in mode 2 respectively with values of C1 and C2.  The pacer
rate is determined as follows:

                Pacer rate = (2 Mhz)/(C1*C2)

        The following program sets the pacer rate is 5 KHZ.

        outportb(BASE+3,0x74); // Counter 1, mode 2, binary
        outportb(BASE+1,40);     // Counter 1= C1=40 Low Byte
        outportb(BASE+1,0);       // Counter 1=C1=40 High Byte

        outportb(BASE+3,0xb4); // Counter 2, mode 2, binary
        outportb(BASE+2,10);     // Counter 2=C2=10 Low Byte
        outportb(BASE+2,0);       // Counter 2=C2=10 High Byte

Programming Example - D/A Conversion:

        unsigned int da;
        outportb(BASE+4,da&0xff);// Low Byte First
        outportb(BASE+5,da>>8));  // High Byte Second

Programming Example - A/D Conversion, S/W Trigger and Transfer:

        unsigned char channel:  // A/D Channel Number
        unsigned int ad;
        --
        outportb(BASE+10,channel);      // Select A/D Channel
        outportb(BASE+9,0);             // Set Amplifier Gain = 1
        outportb(BASE+11,0x40); // S/W Trigger and Transfer, IRQ=4
        outportb(BASE+12,0);    // Start A/D Conversion
        while((inportb(BASE+5)&0x10)==0x10);  // Wait While Converting
        ad = ((inportb(BASE+5)&0xf)<<8) + inportb(BASE+4); // Read AD
        /* Make another conversion */
        outportb(BASE+12,0);    // Start A/D Conversion
        while((inportb(BASE+5)&0x10)==0x10);  // Wait While Converting
        ad = ((inportb(BASE+5)&0xf)<<8) + inportb(BASE+4); // Read AD

Programming Example - A/D Conversion, Pacer Trigger, Interrupt:

        /* Set C1 and C2 of 8253 Pacer Clock */
           --
        /* Set mode to pacer interrupt, transfer on IRQ4 */
        outportb(BASE+11,0x46);
        /* Clear interrupt status */
        outportb(BASE+8,0);             // Clear Interrupt on Board
        /* Unmask IR4 of 8259 if required */
        disable();
        outportb(0x21,inportb(0x21)&0xef);
        enable();
        --
        void interrupt adisr4(void)
        { int adv;
           /* read AD - optional */
           adval = ((inportb(BASE+5)&0xf)<<8)+inportb(BASE+4);
           outportb(BASE+8,0);  // clear status - required
           outportb(0x20,0x20); // 8259 EOI
        }

Sample Program  Program Transfer:

/* PCL-711S PC-MULTILAB Test Program
   Written by T. Drake
   April 9, 1999

   Initialize PC-MULTILAB System
   Pacer triggers AD
   AD transfer under program control
   AD data is output via DA

*/
#include <stdio.h>
#include <conio.h>
#include <dos.h>
#define BASE 0X220  // Base address of PCL-711S

int main()
{int adl,da,adh,adv,*pda;
 unsigned char flag,c;
/* test using interrupts */
printf("Test using program transfers \n\r");
printf("AD1 is input, DA output \n\r");
printf("Terminate test on 's'\n\r");
/* set up pacer clock to 5/8 Khz */
/* setup up timer 1 */
outportb(BASE+3,0x74);
outportb(BASE+1,40);
outportb(BASE+1,0);
/* setup timer 2 */
outportb(BASE+3,0xb4);
outportb(BASE+2,80);
outportb(BASE+2,0);
/* select gain of amplifier to 1 */
outportb(BASE+9,0);
/*select channel 1 for ad */
outportb(BASE+10,1);
/* set 8253 triggering */
outportb(BASE+11,0x44);
flag=1;
while(flag)
{while((inportb(BASE+5)&0x10)==0x10);
 adh=inportb(BASE+5)&0xf;
 adl=inportb(BASE+4);
 outportb(BASE+4,adl);
 outportb(BASE+5,adh);
 adv=(adh<<8) + adl;
if(kbhit()){c=getch(); printf("char is %c adval %x \n\r",c,adv);
 if (c=='s') flag=0;}
}
/* exit */
return 0;
}

Sample Program  Interrupt Transfer:

/* PCL-711S PC-MULTILAB Test Program
   Written by T. Drake
   April 9, 1999

   Initialize PC-MULTILAB System
   Pacer triggers AD
   Assumes IR4 is used
   AD interrupt computer
   AD data is output via DA

*/
#include <stdio.h>
#include <conio.h>
#include <dos.h>
#define BASE 0X220  // Base address of PCL-711S
int adv;
void interrupt newisr(void)
{ unsigned char adl, adh;
  /* interrupt generated by A/D completion
     read A/D
     write A/D value to D/A
     clear A/D interrupt
  */
  adh=inportb(BASE+5)&0x0f; // read ad
  adl=inportb(BASE+4);
  outportb(BASE+8,0);  // clear interrupt
  outportb(BASE+4,adl); // load da
  outportb(BASE+5,adh);
  adv=(adh<<8)+adl;
  outportb(0x20,0x20); // 8259 EIO
}
void (interrupt *oldisr)(void);
int main()
{int ad,da,*pda;
 unsigned char flag,c;
/* test using interrupts */
printf("Test using interrupts \n\r");
printf("AD1 is input, DA output \n\r");
printf("Terminate test on 's'\n\r");
disable();  // disable interrupts during setup
oldisr=getvect(8+4); // save interrupt vector
setvect(8+4,newisr); // new interrupt vector
/* set up pacer clock to 5/8 Khz */
/* setup up timer 1 */
outportb(BASE+3,0x74);
outportb(BASE+1,40);
outportb(BASE+1,0);
/* setup timer 2 */
outportb(BASE+3,0xb4);
outportb(BASE+2,80);
outportb(BASE+2,0);
/* select gain of amplifier to 1 */
outportb(BASE+9,0);
/*select channel 1 for ad */
outportb(BASE+10,1);
/* disconnect 8250 from ir4 */
outportb(0x3f8+4,0);
/* set 8253 triggering and ir */
/* change to use a different IR request line */
outportb(BASE+11,0x46);
//outportb(0x21,inportb(0x21)|0x10);
outportb(0x21,inportb(0x21)&0xef); /* unmask ir4 */
outportb(BASE+8,0); // clear interrupt
  outportb(BASE+4,adl); // load da
  outportb(BASE+5,adh);
  adv=(adh<<8)+adl;
  outportb(0x20,0x20); // 8259 EIO
}
void (interrupt *oldisr)(void);
int main()
{int ad,da,*pda;
 unsigned char flag,c;
/* test using interrupts */
printf("Test using interrupts \n\r");
printf("AD1 is input, DA output \n\r");
printf("Terminate test on 's'\n\r");
disable();  // disable interrupts during setup
oldisr=getvect(8+4); // save interrupt vector
setvect(8+4,newisr); // new interrupt vector
/* set up pacer clock to 5/8 Khz */
/* setup up timer 1 */
outportb(BASE+3,0x74);
outportb(BASE+1,40);
outportb(BASE+1,0);
/* setup timer 2 */
outportb(BASE+3,0xb4);
outportb(BASE+2,80);
outportb(BASE+2,0);
/* select gain of amplifier to 1 */
outportb(BASE+9,0);
/*select channel 1 for ad */
outportb(BASE+10,1);
/* disconnect 8250 from ir4 */
outportb(0x3f8+4,0);
/* set 8253 triggering and ir */
/* change to use a different IR request line */
outportb(BASE+11,0x46);
//outportb(0x21,inportb(0x21)|0x10);
outportb(0x21,inportb(0x21)&0xef); /* unmask ir4 */
outportb(BASE+8,0); // clear interrupt
enable();  // now ready to handle data
flag=1;
while(flag)
{c=getch(); printf("char is %c adval %x \n\r",c,adv);
 if (c=='s') flag=0;
}
/* restore interrupts and exit */
outportb(0x21,inportb(0x21)|0x10);  // mask ir4
setvect(8+4,oldisr);
return 0;
}Digital Filter:

        One digital filter outputs the average of the last n inputs with the
following algorithm:

        y(k) =(x(k) + x(k-1) + ^Å + x(k-n+1))/n

        For n=4, the filter would be implemented as follows:

                x[3] = x[2];
                x[2] = x[1];
                x[1] = x[0];
                x[0] = input;
                y = (x[3] + x[2] + x[1] + x[0])/4;

Digital Signal Processing Chips:

        Digital Signal Processing (DSP) is now a very hot area since digital
systems have now become fast enough and cheap enough to perform operations that
have been performed traditionally by analog systems.  For example, look at the
April 1005 issue of the IEEE Spectrum on Digital TV.

        Aaarticles in recent issues of the IEEE Spectrum and IEEE Proceedings
state that a DSP chip can perform an accumulation and a product in a one clock
cycle.  That is, the following the computation can be performed in one clock
cycle:

        Sum = Sum + A(i)*B(i)

        Besides performing a multiplication and a sum on each clock, this
statement also implies that two operands must be fetched from memory on the same
clock.  To support operand fetching plus input/output, the DSP chip usually has
multiple memory busses and multiple memory modules.  A(i) is fetched from one
memory module using one bus, B(i) is fetched from another memory module using a
different memory bus, instruction is fetched from yet a different memory module
using a different bus, etc.  These chips usually have DMA to support concurrent
input and output while computation is being performed using a different memory
bus.

        To maintain speed, hardware often supports ring buffers (circular
buffers).  When the end of the buffer is reached, the buffer pointer is
automatically set back to the beginning of the buffer.  General purpose computers
have to test  using instructions for end of buffer conditions and reset the
pointer back to the beginning when the end conditions are satisfied.

        DSP chips often support floating point arithmetic as well as integer
arithmetic.  The DSP chips have the hardware necessary to support a one chip
stand alone system.

        ECE 330 and ECE 467 would prepare (application sequence for CPE) would
give basic DSP background to effectively use these chips.
DSP Algorithms:

        A FIR (Finite impulse response) filter is defined by the following
equation.

        Y9n) = A(0)*X(n) + A(1)*X(n-1) + ^Å + A(k)*X(n-k)

        A C language implementation of this algorithm is as follows:

        #define N ---;
        float a[N], x[N], y;
        while (TRUE)
          { x[0] = input;
             for(k=0, y=0.0; k<N; k++)
                {y = y + a[k]*x[k];
                  if (k>0) x[k] = x[k-1];}
             output = y;
           }

        If a[k] = 1/N, the output would be the average of the last N inputs.  The
output is an approximation to the average value of the input.

        A DSP chip has been optimized to perform the above computations often
using floating point arithmetic.  That is, the chip in one clock cycle can do the
following:
      1.      fetch instruction

2.      fetch a[k]
3.      fetch x[k]
4.      perform y=y+a[k]*x[k] computation
5.      perform indexing with auto increment and circular lists
6.      perform input and output
7.      handle counting and indexing

The DSP chip has a pipeline and can repeat a sequence of instructions that are
present in the pipeline.  DSP chips are widely used to implement digital filter
functions inside lots of equipment.

The chip is also designed to perform Fast Fourier Transform (FFT) and IIR.  An
IIR (Infinite Impulse Response) filter is given by the equation

Y(n) = A(0)*X*n) + .. + A(k)*X(n-k) + B(1)*Y(n-1) + ^Å + B(m)*Y(n-m)

Aliasing:

        A signal must be sampled at least 2 times the highest frequency present
in the signal to avoid aliasing.

        If the frequency of the signal is in the following range,

                N*fsamp  fsamp/2 <= fsignal <= N*fsamp

then

                foutput = N*fsamp  fsignal

If the frequency of the signal is in the following range,

                N*fsamp <= fsignal <= N*fsamp + fsamp/2

then

                Foutput = fsignal  N*fsamp.

        TV produces 30 pictures per second on the screen and is effectively
sampling with a sample frequency of 30 samples per second.  If a wheel is turning
at 30 revolutions per second, then it appears to not be turning.  If a wheel is
turning at 28 revolutions per second, then it appears to be rotating backwards at
2 revolutions per second.  If a wheel is turning at 33 revolutions per second,
then it appears to be turning forwards at 3 revolutions per second.

PRELAB:
      1.      Study the description of the PC-Multilab data acquisition board.
      The 8253 pacer timer always triggers an A/D conversion and the interrupt
      results from the completion of the conversion.  Either software or
      interrupt transfers are supported by the A/D.

      2.      Read over the entire lab write-up to make sure you see the ^Óbig
      picture.^Ô  Included in the lab write-up are sample programs that operate
      the PC-Multilab boards with and without interrupts.

      3.      Write software to implement a digital filter where the output is
      set equal to the input.  The software must initialize the 8253 pacer timer
      to initiate A/D conversion.  The software must determine completion, read
      the A/D, and output the converted value to the D/A.

      4.      Write software to implement a digitial filter.  The software must
      initialize the 8253 pacer timer to initiate A/D conversions.  The sotware
      must determine completion, read the A/D, perform the filter computation,
      and output the filtered value to the D/A.  Let the output of the filter be
      average of the last N inputs with N being a parameter.

      5.      Write software to implement a digital filter.  The software must
      initialize the 8253 pacer timer, set up interrupts, and service the
      interrupt requests from the timer.  On each interrupt, data is input from
      the A/D, and the filtered data is output via the D/A.  Let the output of
      the filter be the average of the last N inputs with N being a parameter.

DURING LAB:
      1.      Experimentally determine the effects of aliasing of your digital
      filter that you implement in Step 2 of the Pre-Lab.  An oscilloscope is
      present to measure the amplitude of both the input and output.  Aliasing
      occurs when the input frequency is above ½ the sample frequency.  Note the
      frequency of the input and the output.

      2.      Experimentally determine the frequency response of your digital
      filter than you implemented in Step 3 of the Pre-lab.  You are only
      interested in frequencies below ½ of the sampling frequency.  An audio
      oscillator is present to provide the input.  An oscilloscope is present to
      measure the amplitude of both the input and the output.

      3.      Experimentally determine the frequency response of your digital
      filter that you implemented in Step 4 of the Pre-lab.  You are only
      interested in frequencies below ½ of the sampling frequency.  An audio
      oscillator is present to provide the input.  An oscilloscope is present to
      measure the amplitude of both the input and the output.

      4.      Experimentally determine the frequency response of your digital
      filter that you implemented in Step 5 of the Pre-lab.  You are only
      interested in frequencies below ½ the sampling frequency.  An audio
      oscillator is present to provide the input.  An oscilloscope is present to
      measure the amplitude of both the input and the output.

POST-LAB:
      1.      Write a report.  Include a listing of your program code.