I’m still not sure what is wrong in my program, but I did get an example of this working when I attempted to write a demo that did little else but switch interrupt pins. There’s an additional timer interrupt because I didn’t have a debounced switch handy.
/**********************************************************
Description
===========
1. Demonstrates an attempt to change input capture IO pins during runtime.
2. Initializes IC1 for both rising and falling edge interrupts on PG3
3. Second trigger of interrupt sets flag
4. Flag set to true switches interrupt pin to next input pin (PG3, PG1, PG5, PC3)
Instructions
============
1. Compile and run this program.
2. Trigger interrupts on PG3
3. Observe STDIO output
4. Attempt to trigger interrupts on PG1
5. Observe lack of SDTIO output
*************************************************************************/
#class auto
#define TRUE 1
#define FALSE 0
char myflag; //if true, toggle switch IO
char count;
char timerbcount;
void incap_isr();
void timerb_isr();
void setInterrupt(char pin){
switch(pin){
case 1:
WrPortI(ICS1R, NULL, 0xDD); //set to PG3
printf("PG3 will now trigger interrupts");
break;
case 2:
WrPortI(ICS1R, NULL, 0xCC); //set to PG1
printf("PG1 will now trigger interrupts");
break;
case 3:
WrPortI(ICS1R, NULL, 0xEE); //set to PG5
printf("PG5 will now trigger interrupts");
break;
case 4:
WrPortI(ICS1R, NULL, 0x11); //set to PC3
printf("PC3 will now trigger interrupts");
break;
}
}
void main()
{
char io; // 1 => PG3, 2=> PG1, 3=>PG5, 4=>PC3
count=0;
myflag=FALSE;
io=1;
timerbcount=0;
//Initialize Input Capture 1 interrupts
//setup input capture interrupt
#if __SEPARATE_INST_DATA__ && (_RK_FIXED_VECTORS)
interrupt_vector inputcap_intvec incap_isr;
#else
SetVectIntern(0x1A, incap_isr); // set up ISR
SetVectIntern(0x1A, GetVectIntern(0x1A)); // re-setup ISR to show example of retrieving ISR address
#endif
//Setup timerb interrupt
#if __SEPARATE_INST_DATA__ && (_RK_FIXED_VECTORS)
interrupt_vector timerb_intvec timerb_isr;
#else
SetVectIntern(0x0B, timerb_isr); // set up ISR
SetVectIntern(0x0B, GetVectIntern(0x0B)); // re-setup ISR to show example of retrieving ISR address
#endif
//Setup timer b interupts
WrPortI(TBCR, &TBCRShadow, 0x00); // set to 1 to clock timer B with (perclk/2) and set interrupt level to 1
WrPortI(TBM1R, NULL, 0x00); // set initial match!
WrPortI(TBL1R, NULL, 0x00);
WrPortI(TBCSR, &TBCSRShadow, 0x03); // Setup timer B and B1 match interrupts. Enable in rising edge
//Setup Input Captur interrupts
WrPortI(ICS1R, NULL, 0xDD); //11011101 -- PG3 set for start and stop conditions of channel 1 (az)
WrPortI(ICS2R, NULL, 0x00); //use PC1 for start and stop conditions
// WrPortI(ICS2R, NULL, 0xCC); //11001100 -- PG1 set for start and stop conditions of channel 2 (el)
//use freq_divider for input capture prescaler
//(freq_divider-1) runs at 19200*16Hz, multiply by 4 for better range
WrPortI(TAT8R, NULL, freq_divider*4 - 1); //(TA8 prescaler)
WrPortI(ICCSR,NULL, 0x3C); //Enable ONLY input capture 1, for rising and falling.
WrPortI(ICCR, NULL, 0x01); //xxxx xx01 Interrupts have priority 1 (lowest priority)
WrPortI(ICT1R, NULL, 0x06); //disable the counter, disable latching, start is a rising, stop is a falling
WrPortI(ICT2R, NULL, 0x00); //disable IC2
count=0; //interrupt always runs after setting, reset variables
myflag=0;
printf("PG3 will now trigger interrupts");
while(1)
{
if(myflag==TRUE){
io=(io==4)? 1 : io + 1; //increment io from 1 to 4 with wrap
setInterrupt(io);
myflag=FALSE;
}
}
}
////////////////////////////////////////////////////////////////////////////////
// interrupt routine for timer B
//
// When InputCapture triggers, IC interrupts are disabled while TimerB interrupts
// are enabled
//
// TimerB runs for max period and increments timerbcount until overflow ~4ms
// this provides ample time for debounce on the input
//
// When timerbcount overflows, count is incremented. If count == 2,
// then {count=0; myflag=TRUE;)
//
////////////////////////////////////////////////////////////////////////////////
//nodebug
#asm nodebug root
timerb_isr::
push af ; save registers
push hl
push de
; load B1, B2 interrupt flags (clears flag); this
ioi ld a, (TBCSR) ; should be done as soon as possible in the ISR
; we don't care what the flags are, though
ld a, (timerbcount)
inc a ; increment counter
and 0x3F ;a = a & 0x3f -- mask off a for 4ms run
ld (timerbcount), a
cp 0 ;Increment does not set zero flags. Compare 0 with a
jp nz,tmrdone ;if not zero, we're done
overflow:
ld a, 0x00 ;disable timer interupts
ioi ld (TBCR), a
ld (TBCRShadow), a
ld a,(count)
inc a
and 0x01
ld (count),a
jp z,zeroed
jp enableedge
zeroed:
ld a,TRUE
ld (myflag),a
enableedge:
; ld a,0x00 ;Apparently unneeded
; ld (edge),a
ld a, 0x01 ;re-enable edge interrupts
ioi ld (ICCR), a
ioi ld a, (ICCSR) ;clear the interrupt flags
tmrdone:
ld a, 00h ; set up next B1 match (at timer=0000h)
ioi ld (TBM1R), a ; NOTE: you _need_ to reload the match
ioi ld (TBL1R), a ; register after every interrupt!
pop de
pop hl
pop af ; restore registers
ipres ; restore interrupts
ret ; return
#endasm
////////////////////////////////////////////////////////////////////////////////
// interrupt routine for input capture
//
// This is called on either the rising or the falling edge of either capture,
// depending on how ICCSR is setup
//
////////////////////////////////////////////////////////////////////////////////
//set as debug to allow breakpoints, won't break on first ioi line for some raisin.
#asm nodebug root
incap_isr::
push af ; save registers
push hl
push de
ioi ld a, (ICCSR) ; input capture status register
; almost every time we enter it shows a rising and a falling edge
; because the bounce is so great, so we can't reliably care why
;it triggered
ld a, 0x00 ;disable future interupts
ioi ld (ICCR), a
ioi ld a, (ICCSR) ;clear the next interrupt, too.
;This prevents the interrupt from firing immediately on next enabling
settimer:
ioi ld a, (TBCSR) ;clear pending timer interrupt
ld a, 00h ; set up next B1 match (at timer=0000h)
ioi ld (TBM1R), a ; NOTE: you _need_ to reload the match
ioi ld (TBL1R), a ;register or the timer won't trigger.
ld a, 0x01 ;enable timer interupts
ioi ld (TBCR), a
ld (TBCRShadow), a
done:
pop de
pop hl ; restore registers
pop af
ipres ; restore interrupts
ret ; return
#endasm