ECE 471 LAB 4 FALL 2008 PURPOSE: MORE PRACTICE WITH INTERRUPTS: INPUT CAPTURES AND SCI INTERRUPTS. EXERCISE: This program will build on Lab 3. You will add independent functionality which will investigate switch bounce while running lab 3 code. Additional functionality is given below. For this lab we will hook a push button switch to one of the input capture inputs and set it up to cause an interrupt each time the input changes. Clock cycles between signal changes will be printed in the comm window. Your program will include two interrupt service routines and two "circular buffers": a "time buffer" and a "print buffer". The time buffer will record the times at which rising and falling edges are detected on the switch input. The print buffer will hold characters to be printed on the screen, which represent the time delays between each successive edge. The main program will (in addition to what it did for lab 3) read the time buffer and compose the characters to be put into the print buffer. The input capture interrupt service routine (ISR) will simply store the time that the input changed (TICx) in the time buffer, clear the Input Capture flag, ICxF (by writing a 1 to it), and return from interrupt. The SCI transmit ISR will send the characters in the print buffer to the comm window. Since the SCI system we use is external and not the actual SCI system, we will "fake" this interrupt by using a TOC interrupt. This TOC interrupt will interrupt every 500 microseconds. If this ISR finds the TDRE flag is clear or the print buffer is empty, the ISR will simply return. If not, the ISR will pull the next character from the print buffer and send it to the TDR (Transmit Data register). Return from interrupt when done. Your main program previously included a main loop which waited for button presses. For this lab it will also check the time buffer to see if it is non-empty. If it is non-empty, the first (oldest) time in the buffer is subtracted from a value in memory called "prevtime". The difference will then be printed on the terminal by way of the next paragraph. The first (oldest) time will then be copied to "prevtime" as it is pulled from the buffer (i.e., the buffer start pointer is incremented - twice, as it is a two byte value). To print the difference we will convert it to decimal and place the ASCII digits into the print buffer for printing by the SCI transmit ISR. For this, divide the difference by 10000. The quotient should be less than 10. Convert it to ASCII (add '0') and pass it to a "sendchar" subroutine (see below). Take the remainder and divide it by 1000. The quotient should again be less than 10. Convert to ASCII and pass to "sendchar". Similarly, divide the successive remainders by 100 and then 10, converting the quotients to ASCII and passing to sendchar. Take the final remainder, convert to ASCII, and then pass to "sendchar". Finally pass a carriage return ($0D) and line feed ($0A) to "sendchar". The "sendchar" routine will take the given character and add it to the print buffer. The two buffers will be 256 byte circular FIFO buffers: simply place these buffers on 256 byte boundaries (i.e., begin at $XX00) and when incrementing buffer pointers, only increment the least significant byte (without a carry to the most significant digit) - easy for pointers in memory. Two pointers are associated with each buffer: a start pointer and an end pointer. The buffer is empty when the two pointers are equal. To add a value to a buffer, place the value at the location pointed to by the end pointer, and then increment the end pointer. The start pointer points to the next value to be read from the buffer. To remove this value after access, increment the start pointer. (Use two increments for pointers to double bytes). Notes: When a button is pressed/released, the times between signal changes as the switch is bouncing will be printed. The first value printed will always be meaningless, as the timer will have overflowed many times since the previous press/release. Also, for this reason, "prevtime" does not have to be initialized at the start of the program. You must hook a pushbutton with pull up resistor to one of the input capture pins. Try different switches and record results in your notebook. Do as little as possible in interrupt routines. You don't want to miss anything. MISCELLANEOUS INITIALIZATION: Same as Lab 3. Also initialize all buffer pointers to point to the start of their buffers. OUTPUT COMPARE INTERRUPT INITIALIZATION: Same as Lab 3 INPUT CAPTURE INTERRUPT INITIALIZATION (ASSUMES INPUT CAPTURE 1 IS USED): 1) Insert interrupt vector in the jump vector table: Memory $FFEE contains $00E8, so insert a JMP XXXX instruction at $00E8 (where XXXX is the address of your TIC1 service routine. 2) Set the IC1I bit in the TMSK1 register (pg. 391) to enable TIC1 interrupts. You might want to use BSET for this and for setting OC3I in this register (TOC3 initialization). This way you can have separate, independent sections of code handle setting up each interrupt. 3) Clear the IC1F bit in TFLG1 to clear any previous interrupt condition. (pg. 391). IMPORTANT!!! Note that you must write a 1 to this bit to clear it! Do not use BSET! See the discussion on page 387. Note that this wierdness only applies to timer flag bits, not interrupt enable bits. 4) Write to the EDG1B and EDG1A bits in the TCTL2 register to cause input captures to occur on every edge of the input pin (pg. 392). SCI TRANSMIT (AKA TOCx) INTERRUPT INITIALIZATION: Same as for TOC3 TOC3 SERVICE ROUTINE: Same as Lab 3 TIC1 SERVICE ROUTINE: 1) Store TIC1 (pg. 390) in the "time buffer". 2) Clear the IC1F bit in TFLG1 to clear the interrupt condition (SEE ABOVE). 3) Return from interrupt when done (pg. 181). SCI (AKA TOCx) INTERRUPT SERVICE ROUTINE: 1) If the TDRE flag is clear or the print buffer is empty, skip step 2). 2) If the print buffer is non empty, remove the next character from the the print buffer and send it (write to TDR). 3) Clear the condition that caused the interrupt (clear the flag). 4) Return from interrupt when done (pg. 181).