MP1: Interrupts

Assigned: Jan 26, 2010

1.0   Objective

Text Box: The purpose of this project is to learn how to program interrupts in a PC. In particular, we are going to write a C program that will i) use timer interrupts to generate a square wave out of a printer port;  ii) use printer and timer interrupts to measure the frequency of this square wave.

  

 

 

2.0  Background

This project is based on a submission to the "Design Ideas" section of EDN magazine.  In this article, Radovan Stojanovic, presents the following ideas: "A simple, low cost, precision frequency meter uses only two pins of a PC parallel port (Figure 1). The TTL-level periodic input signal with frequency fIN connects to the  pin of LPT1.  This input produces an IRQ7 (or IRQ5) hardware interrupt on every rising edge (Figure 2).  The software counts the number of the IRQ interrupts in the time unit of timebase T.  If this timebase is 1 sec., the frequency of the input signal equals the number of IRQ7 interrupts in 1 sec.  You can use many ways to precisely generate the timebase, T, such as using the delay() or sleep() functions in C. 

Figure 2

 
You can also use software calibration loops.  Unfortunately, these techniques are unreliable because they are based on polling.  The best choice is to use a second interrupt, such as IRQ0.  This interrupt is related to the internal PC times and occurs 18.2 times/sec. For precise measurements, you can use proportional constants.  For example, if your timebase equals the 18 IRQ0, you must correct the result by a factor of 18.2/18."

Since we do not have multiple square wave generators, you can generate one by programming the least significant data bit (pin 2) of the parallel port to output a 1 and a 0 alternatively. Its period will be determined by the timer interrupts. This square wave can then be fed into  pin of the printer point for measurement.

     

3.0  Program Description

First off, there are two basic interrupt functions needed, one for the timer and one for the printer.  Each one needs to keep a count of the number of times it is executed.  In the main function of your C program you will have to put an IF statement that tests for the timer count to be 18, and when it is, you will need to display the frequency whish is the number of times the printer interrupt function was called, multiplied by a factor = 18.2/18. to account for the fact that the timer has only counted out 18, not 18.2 ticks of the clock.

S10: we can program the timer any way we want, since we are not using any OS, certainly not MS-DOS.

The interrupt handler routine in C is written as:

void _interrupt inthandler() {

 

}

Before returning, the interrupt controller must be reset to accept interrupts.  To do this you need a statement of the form:

outp(ISR, EOI);

In reading S&S, pages 386-393, you will recall that there are two registers in the interrupt controller.  The first, ISR = 0x20, is needed to reset the controller after an interrupt.  The second, IMR = 0x21, is the mask register which is set to have zeros wherever an interrupt request is to be granted.  So bit 7 is for IRQ7 and bit 0 is for IRQ0.  The EOI value is 0x20.

S10: we are not using MS-DOS, so ignore the following paragraph. Use the SAPC library, but be sure you know how it works!

There are several more things to consider.  First, how do you redirect an interrupt to your code and not the MS-DOS code that an interrupt already points to?  Second, how do you get the printer to generate an interrupt?  The first answer is to use the MS-DOS system call, _dos_setvect(intnum, int_handler).  Interrupt numbers include 0x08 for the timer and 0x0f for the printer.  A good practice is to save an interrupt vector before setting it so that it can be restored before your program exits and returns to MS-DOS.  So there is a corresponding function, _dos_getvect(intnum)returns the old vector.  Your program should define a place to hold the old vector and the proper definition is, for the timer:

void (_interrupt _far *oldtimer)();

Also, you must restore the vector before exiting your program.

Now to answer the second question, how to make the printer cause an interrupt.  The answer is to set the interrupt enable bit in the printer control register.  The parallel port registers and the bits within the registers are described in S&S pages 627-633.

Third, your program should locate a parallel port and loop until a key is pressed.  Note that not all machines use the same physical address for the parallel port.  Some use 0x3BC, some use 0x378, and others use 0x278.  The question is how does MS-DOS or Windows locate and organize the parallel ports so that they are symbolically known as LPT1:, LPT2:, and LPT3:? 

There is one last thing to do and this is true for all programs.  Every program you submit must be self-identifying.  That means it should start by displaying the course name and number, names of your group members, and the date.  It should be followed by any comments, such as what is expected by the program, that determine what the user must do to run the program.  You may also use _kbhit() as the method for terminating the program, and provide a comment that pressing any key while the program is running will stop the program.

Finally, a reminder and a warning. The reminder is that not all PCs seem to implement IRQ7 the same way.  In the CS445 lab where we have different machines we have found that we needed to set the printer to IRQ5 to get it to work if it boots up under MS-DOS.  Interestingly, if you boot to Windows 98, IRQ7 does work.  This is probably because of the way Win98 rearranges the BIOS after it takes control.  Thus, all the statements above regarding IRQ7 must be changed to IRQ5 if you are to complete this project using MS-DOS on the laboratory machines.  My suggestion is for you to test your program under Win98 and avoid the hassle of resetting the printer IRQ.  S10: don’t worry, SAPCs have IRQ7 for LPT1.

S10: use SAPC as a first implementation. Connect the strobe pin on LPT1 on one system to the ACK pin of LPT1 on another system. In fact, two pairs of SAPCs have cables with this connection already, for cs644. Write two programs, one gensignal.c to generate the pulses in a known way and the other monsignal.c to time them and report on their frequency.

 

4.0  Deliverables

At the due date, you have to submit a written project report and files which contains the software( mp1.c, mp1.exe and mp1.doc files). Label your disk with the project number, date, group number and group member names. In particular, the project report should include:

1.      Title Page: Project number and name, date, group number and name of group members

2.      Introduction : Purpose of the project and your approach to the project

3.      Program documentation: Explain how your program works.  Include flow charts if necessary. Describe how you tested your code. If  the hardware forces requirements on the software (timing constraints, PC configuration considerations such as which parallel port works or does it have to be bi-directional or power requirements), you should explain this as well

4.      Summary: Write several sentences about what you found or learned working on the project, and on any other similar kinds of questions that occur to you. What problems did you encounter in developing your solution?  What things might have been made clearer in the project description?  What information was missing?  What might have been discussed in class to make things easier?

 

5.0  Grading

The value of this project is 30 points.