// Interrupt handlers Interrupts.c // Rev 9/1/05
//Copyright (C) 2005 Alex Brown rbirac@cox.net
//This program is free software; See license at the end of this file for details.
#include //for registers
#include //for i/o prototypes
//External variables
//Misc
extern unsigned int time;
//Encoders
long int enc0, enc1, enc2;
// I2C compass
extern int I2Ccount;
extern int compass;
int I2Cbuff; //dummy buffer
//Accelerometers
int AccStartX, AccStartY;
int AccIntX, AccIntY;
int AccEndX,AccEndY;
//Function Prototypes
void rtexec(void);
//-------------------------------------------------------------------------
// Real Time Clock Interrupt
#pragma interrupt_handler rti_handler()
void rti_handler()
{CRGFLG = 0x80; //Clear RTI flag
time += 1; //Increment time counter
INTR_ON(); //Turn interrupts back on to handle encoders & accel
rtexec(); //Run Real Time executive
}
//-------------------------------------------------------------------------
// Encoder interrupts.
// encoder clicks are counted into a long int (32 bit). The compiler would do
// this with a slow function call. Hence, the increments are performed using
// assembly code.
// PORT P interrupt handler for Encoders 0 & 1
#pragma interrupt_handler PORTP_handler()
void PORTP_handler()
{
if(PIFP & 0x20) //if interrupt bit 5 set (encoder 0)
{if(PTP & 0x40) //if encoder direction bit set
{ asm(" ldd %enc0+2"); //done in assembly for speed. Done in two words
asm(" addd #1"); //with carry.
asm(" std %enc0+2");
asm(" bcc ab");
asm(" ldd %enc0");
asm(" addd #1");
asm(" std %enc0");
asm(" ab:");
}
else
{ asm(" ldd %enc0+2");
asm(" subd #1");
asm(" std %enc0+2");
asm(" bcc ab1");
asm(" ldd %enc0");
asm(" subd #1");
asm(" std %enc0");
asm(" ab1:");
}
PIFP |= 0x20; //reset interrupt flag
}
}
// PORT H interrupt handler for Encoder 1
#pragma interrupt_handler PORTH_handler()
void PORTH_handler()
{
if(PIFH & 0x02) //if interrupt bit 1 set (encoder 1)
{if(PTH & 0x01) //if encoder direction bit set
{ asm(" ldd %enc1+2"); //done in assembly for speed. Done in two words
asm(" addd #1"); //with carry.
asm(" std %enc1+2");
asm(" bcc ab4");
asm(" ldd %enc1");
asm(" addd #1");
asm(" std %enc1");
asm(" ab4:");
}
else
{ asm(" ldd %enc1+2");
asm(" subd #1");
asm(" std %enc1+2");
asm(" bcc ab5");
asm(" ldd %enc1");
asm(" subd #1");
asm(" std %enc1");
asm(" ab5:");
}
PIFH |= 0x02; //reset interrupt flag
}
}
// IRQ interrupt handler for Encoder 2
#pragma interrupt_handler IRQ_handler()
void IRQ_handler()
{
if(PTP & 0x10) //if encoder direction bit set
{ asm(" ldd %enc2+2"); //done in assembly for speed. Done in two words
asm(" addd #1"); //with carry.
asm(" std %enc2+2");
asm(" bcc ab2");
asm(" ldd %enc2");
asm(" addd #1");
asm(" std %enc2");
asm(" ab2:");
}
else
{ asm(" ldd %enc2+2");
asm(" subd #1");
asm(" std %enc2+2");
asm(" bcc ab3");
asm(" ldd %enc2");
asm(" subd #1");
asm(" std %enc2");
asm(" ab3:");
}
PIFP |= 0x08; //reset interrupt flag
}
//-------------------------------------------------------------------------
// Accelerometer interrupts.
// These read a start time for the accel duty cycle leading edge and calculate
// the interval on the falling edge. The times are read from the timer
// register which counts up to 50000 in 1 usec intervals.
// The resulting calculated interval may be negative if the timer rolls over
// before the second value is taken. This can be corrected in the using
// software by adding 50000.
// PORT J interrupt handler for dual axis accelerometer
#pragma interrupt_handler PORTJ_handler()
void PORTJ_handler()
{
if(PIFJ & 0x01) //if interrupt bit 0 set (accel ? axis)
{if(PPSJ & 0x01) //if input bit set (rising edge)
{ AccStartX = TCNT;
PPSJ &= ~0x01; //set for next interrupt to trip on falling edge
//printf("Int %d ",AccStartX);
}
else
{ AccEndX = TCNT;
AccIntX = AccEndX - AccStartX;
PPSJ |= 0x01; //set for next interrupt to trip on rising edge
//printf("%d %d\n",AccEndX,AccIntX);
};
PIFJ |= 0x01; //reset interrupt flag for bit 0
}
if(PIFJ & 0x02) //if interrupt bit 1 set (accel ? axis)
{if(PPSJ & 0x02) //if input bit set (rising edge)
{ AccStartY = TCNT;
PPSJ &= ~0x02; //set for next interrupt to trip on falling edge
}
else
{ AccEndY = TCNT;
AccIntY = AccEndY - AccStartY;
PPSJ |= 0x02; //set for next interrupt to trip on rising edge
};
PIFJ |= 0x02; //reset interrupt flag for bit 0
}
}
//-------------------------------------------------------------------------
// I2C Interrupt
#pragma interrupt_handler I2C_handler()
void I2C_handler()
{ IBSR = 0x02; //clear IBIF
if(IBSR & 0x10)
{ printf("Int # %x \n",IBCR); //if arbitration lost error
//occasionally, get arb error. next line resets IBAL in IBSR to see if heals
IBSR = 0x10;
}
if(IBSR & 0x40) printf("Int @"); //if addressed as slave error
switch (I2Ccount) //cycle through each byte of the message
{
case 0:
IICDR = 0x02; //send 16 bit heading subaddress
break;
case 1:
IBCR |= 0x04; //repeated start
IICDR = 0xC1; //Compass address in receive mode
break;
case 2:
IBCR &= ~0x10; //change to receive mode
I2Cbuff = IICDR; //dummy read to start receive
break;
case 3:
IBCR |= 0x08; //terminate data xfr (see note 1 below)
compass = IICDR break;
case 4:
IBCR &= ~0x30; //stop
compass += IICDR; //read in 2nd byte of data
break;
}
I2Ccount++;
}
// OPEN SOURCE SOFTWARE LICENSE
/* Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/