* Lab6B.asm * Mike Dawdy * Port A assignment part B, use interrupts #define AxiomEVB ;comment this out if not Axiom EVB #ifdef AxiomEVB Program equ $2000 ;for Axiom EVBU #else Program equ $c000 ;for Motorola EVB #endif * This program generates a 22 ms positive pulse on * PA3 whenever a positive edge is detected on PA0 * The program uses the interrupt generated by IC3 to detect * the positive edge on PA0; the timer input capture function * allows use of the time of the pulse as the start of the 22 ms * The program may choose any of OC1 to OC5 to set the 22 ms * duration of the pulse on PA3; avoid OC1 and OC5 because * they have extra unneeded functions; OC5 is used by Buffalo, * and we must disable it anyway, so arbitrarily choose OC4 * The program begins the pulse on PA3 by BSETing %00001000 * to Port A; it ends the pulse by BCLRing %00001000 to Port A. * Writes to Port A pins configured for IC or OC do not * change the pin state; PA3 is by default configured for O5 * so the program must turn off OC5 [and implicitly choose I4, * which is disabled by bits 6&7 of TCtl2] in order to write * to PA3. This action also interferes with the Buffalo Trace * command, making the debugging of this program inconvenient * The following summarizes Port A and timer information * useful to understanding this program * PA0 and PA3 information: * IC is Input Capture; OC is Output Compare * any Port A pin not used as a timer can be general I/O * reads return the logic level of the pin * port A outputs are sync'd to falling edge of E clock * PA3 has a data direction bit DDRA3 in PACtl * PA3 has an output latch * PA3 can be either general I/O or timer IC/OC or both * PA3 alternates are IC4/OC5/OC1 [avoid OC5 re text page 292] * PA3 level can be controlled by output compare registers; * example: if OM5,OL5 in TCtl1 = 1,1 then when OC5 triggers * PA3 will be set; this would be useful if a periodic * pulse were needed on PA3; not useful for this program * * PA0 is fixed as input only * PA0 is either general input, or edge sensitive timer IC * PA0 alternate is IC3 * PA0 is an input pin when IC is not needed; it is an * edge triggered interrupt with it's own interrupt vector; * the relevant edge is selected thru TCtl2; software can * clear a pending interrupt before enabling it * Timer information: * basic clock is 8 MHz [crystal osc connected to XTAL and EXTAL] * E clock is 2 MHz [1/4 of the crystal frequency] * instruction cycle time is 0.5 micro seconds [500 ns] * the free running counter is TCnt at $100e and $100f * read with LDD, LDX or LDY to obtain consistant 16 bits * the prescale factor is PR1 and PR0 in TMsk2 at $1024 * PR1,PR0 on EVB are pseudo read only and cannot be easily changed * 16 bits = 65536 counts; resolution / minimum interval is: * prescale factor 1 => 500 ns / 32.77 ms: the default * prescale factor 2 => 2 microsec / 131.1 ms * * prescale factor 4 => 4 microsec / 262.1 ms *difficult for EVB * prescale factor 16 => 8 microsec / 524.3 ms * * TOF is set each time the free running counter [FRC] overflows * from $ffff to $0000; an interrupt occurs if TOI is set * there is no way to reset the FRC Registers equ $1000 ;indexed addressing mode for registers PortA equ $00 ;Port A register TCnt equ $0e ;free running timer, Hi Byte TIC3 equ $14 ;Timer Input Capture 3, Hi Byte TOC4 equ $1c ;Timer Output Compare 4, Hi Byte TCtl2 equ $21 ;Timer Control 2 register TMsk1 equ $22 ;Timer Interrupt Mask 1 register TFlg1 equ $23 ;Timer Interrupt Flag 1 register PACtl equ $26 ;Pulse Accumulator Control register * 22 ms = 22000 microsecs = 44000 clk ticks = $abe0 clk ticks ms22 equ $abe0 ;22 ms org Program * 1. Initialization section: once-only code ldx #Registers ;set IX pointing to $1000 registers bset PACtl,X,#%00001100 ;set data direction for PA3 to output * bit 2 == 1 is not choosing I4; it is ensuring O5 is not chosen! * if O5 were chosen by bit 2 == 0, we could not write to PA3; * [I4 is disabled by bits 6&7 of TCtl2 being [00] at reset] bclr PortA,X,%00001000 ;turn off PA3 * set up for interrupts on PA0/IC3 bclr TFlg1,X,%11111110 ;clear any pending interrupt on PA0/IC3 bset TCtl2,X,%00000001 ;detect a rising edge on PA0/IC3 ; bset TCtl2,X,%00000010 ;detect a falling edge on PA0/IC3 ldy #PA0_ISR sty $00e3 ;EVB int vect for PA0/IC3 bset TMsk1,X,%00000001 ;enable IC3 interrupt * set up for timer interrupts from OC4 bclr TFlg1,X,%11101111 ;clear any pending interrupt on OC4 ldy #OC4_ISR sty $00d7 ;EVB int vect for TOC4 cli ;global interrupt enable * 2. Indefinite loop to be interrupted by PA0/IC3 and OC4 events InDefiniteLoop wai ;stack the registers and wait bra InDefiniteLoop * 3. PA0/IC3 Interrupt Service Routine * come to here when a positive edge is detected on PA0 * generate a 22 ms positive pulse on PA3 * use output compare reg OC4 to time the 22 ms * the experiment allowed us to get insight into the timing * within an instruction execution using an oscilliscope; * see the pink book pages 10-17 to 10-19 PA0_ISR bclr TFlg1,X,%11111110 ;clear the interrupt on PA0/IC3 bclr TMsk1,X,%00000001 ;inhibit further PA0/IC3 interrupts bclr TFlg1,X,%11101111 ;clear any pending interrupt on OC4 ldd TIC3,X ;timer interrupt 22 ms from pulse ; ldd TCnt,X ;timer interrupt 22 ms from now addd #ms22 ; addd #100 ;experiment, too large ; addd #20 ;experiment, too small ; addd #50 ;experiment, OK std TOC4,X bset PortA,X,%00001000 ;turn on PA3 bset TMsk1,X,%00010000 ;set the interrupt mask bit for OC4 rti * 4. OC4 Interrupt Service Routine * come to here 22 ms after OC4 is set up in PA0_ISR * first stop generating the pulse on PA3, then clear * and inhibit the interrupt so that it will not recurr OC4_ISR bclr PortA,X,%00001000 ;turn off PA3 bclr TFlg1,X,%11101111 ;clear the interrupt on OC4 bclr TMsk1,X,%00010000 ;inhibit OC4 output-compare interrupt bset TMsk1,X,%00000001 ;re-enable IC3 interrupt rti