Does this environment allow me to write a custom interrupt handler?

I need a few interrupt handlers that are not the standard "external interrupts" as defined by the attachInterrupt() capability... I'm working with hardware that is very similar to the MEGA 2560, and the design has INT7 wired to a device. The second one would be for use with the MEGA2560's timer capture capability. Is it possible to write this level of code in the arduino environment? If not, is there any how-to's on adding this into the current environment? I'm willing to look into that if generally useful. Thanks, Ed

Is it possible to write this level of code in the arduino environment?

Yes it can be done, it's just not supported with user friendly functions or libraries in the Arduino core functions. It's all about reading and understanding the AVR datasheet for your specific processor and writing the register level code needed to support that level of the hardware. There are software gurus around here that might be able to help you out once you have the basic understanding of what you want to do.

Lefty

Great. I'm still getting up to speed with this whole arduino environment. I've rebuilt the stk500v2 bootloader to deal with the '!!!' problem (works for me anyway), so I understand that end of the package. Still haven't dug into the connection between Arduino and the underlying 'C' that (I'm assuming) is generated. Since one of my needs is to just hang a handler off INT7, would it be easier to add this to the attachInterrupt() facility or just write my own hook independent of that? Ed

Adding your own hook would be easier, provided you've read the datasheets and can handle setting/clearing bits in registers. Think about Arduino as a set of library functions on top of the avr-gcc compiler: there's no generated C code, you're writing C code.

Ok, got it... For some reason, I just didn' think to try putting ISRs directly in the sketch. Got what I wanted working... Thanks for the input. Ed

For those browsing this, a good point of reference (for me anyway) was... // http://www.nongnu.org/avr-libc/user-manual/group__avr__interrupts.html

For those who may find it useful here’s a working example
that uses two timer/capture pins (MEGA2560) to process
incoming IR from the InfraRed Keychain Remote at Sparkfun.
Since I derived it from the “cheapo” code and forum input,
it seems only right to give it back…

// IR Receiver code:
// This code assumes that an IR receiver is attached to pins PL0/ICP4
// and PL1/ICP5 on a MEGA2560; using both pins in input-capture mode.
// One pin is configured to trigger on the falling edge of the incoming
// pulse stream and the other pin ins configured to trigger on the
// rising edge of the pulses. Both triggers are also configured to
// interrupt the the processor, and all pulse-stream capture is done in
// interrupt space.
// Refer to
// http://www.nongnu.org/avr-libc/user-manual/group__avr__interrupts.html
// For information on interrupt handling.
//
// Acknowledgement:
// This code was derived from the example code provided by Sparkfun at
// http://www.sparkfun.com/datasheets/Components/General/Cheapo_IR_Control.pde

// TODO:
// Modify the code to support the possibility that multiples characters
// may be received from the IR transmitter before being processed by the main
// loop.

////////////////////////////////////////////////////////////////////
// States used to allow the interrupts to transition through a state
// machine to retrieve the pulse-widths that accumulate into a 
// message from the remote IR transmitter...
#define IRRCVR_WAIT4START 0
#define IRRCVR_GOTSTART   1
#define IRRCVR_GOTDATA    2

////////////////////////////////////////////////////////////////////
// These values represent the duration of the start bit, and the one/zero bits
// based on the fact that the capture clock is configured as clk/64 and we
// are running with a 16Mhz main clock...
#define IRRCVR_STARTBIT  (550)
#define IRRCVR_ONEBIT    (250)
#define IRRCVR_ZEROBIT    (100)

////////////////////////////////////////////////////////////////////
// Variables used by this feature...
volatile  int IRRcvr_Data, IRRcvr_Total;
volatile char IRRcvr_State, IRRcvr_Didx;
volatile char IRRcvr_TransitionedLow;

////////////////////////////////////////////////////////////////////
// Interrupt handler for timer-4 capture event
// (this is the detection of a falling edge).
ISR(TIMER4_CAPT_vect)
{
  IRRcvr_TransitionedLow = 1;
}

////////////////////////////////////////////////////////////////////
// Interrupt handler for timer-5 capture event.
// (this is the detectino of a rising edge).
ISR(TIMER5_CAPT_vect)
{
  int pulsewidth;

  if ((IRRcvr_TransitionedLow == 0) || (IRRcvr_State == IRRCVR_GOTDATA))
    return;

  IRRcvr_TransitionedLow = 0;
  pulsewidth = ICR5 - ICR4;

  if (pulsewidth > IRRCVR_STARTBIT)
  {
    IRRcvr_Didx = 0;
    IRRcvr_Data = 0;
    IRRcvr_State = IRRCVR_GOTSTART;
    return;
  }
  if (IRRcvr_State != IRRCVR_GOTSTART)
    return;

  if (pulsewidth > IRRCVR_ONEBIT)
  {
    IRRcvr_Data |= (1 << IRRcvr_Didx);
    IRRcvr_Didx++;
  }
  else if (pulsewidth > IRRCVR_ZEROBIT)
  {
    IRRcvr_Didx++;
  }
  else
  {
    IRRcvr_State = IRRCVR_WAIT4START;
    return;
  }

  if (IRRcvr_Didx == 11) {
    switch(IRRcvr_Data)
    {
      case 144:
      case 145:
      case 146:
      case 147:
      case 148:
      case 165:
      case 149:
        IRRcvr_State = IRRCVR_GOTDATA;
        IRRcvr_Total++;
        break;
      default:
        IRRcvr_State = IRRCVR_WAIT4START;
        break;
    }
  }
}

////////////////////////////////////////////////////////////////////
// IRRcv_check():
// Called by loop() to flush any character that may have been 
// received since the last call.
void
IRRcv_check()
{
  if(IRRcvr_State == IRRCVR_GOTDATA)
  {
    switch(IRRcvr_Data)
    {
      case 144: Serial.println("CH Up");  break;
      case 145: Serial.println("CH Down"); break;
      case 146: Serial.println("VOL Right"); break;
      case 147: Serial.println("VOL Left"); break;
      case 148: Serial.println("Mute"); break;
      case 165: Serial.println("AV/TV"); break;
      case 149: Serial.println("Power"); break;
      default: Serial.print("??:"); Serial.println(IRRcvr_Data); break;
    }
    IRRcvr_State = IRRCVR_WAIT4START;
  }
}

////////////////////////////////////////////////////////////////////
// IRRcv_init():
// Called by setup() to initialize variables and set up the
// timer-capture configuration.
void
IRRcv_init()
{
  IRRcvr_Data = 0;
  IRRcvr_Didx = 0;
  IRRcvr_Total = 0;
  IRRcvr_TransitionedLow = 0;
  IRRcvr_State = IRRCVR_WAIT4START;

  // ICP4 & ICP5 are tied to the input line of the IR Receiver.
  // We set up an input capture event to trigger the start of
  // an incoming IR stream by catching the start bit.
  TCCR4A = 0;
  TCCR4B = 0x83;   // Noise-canceller enabled; Falling-edge triggered; clk/64
  TCCR5A = 0;
  TCCR5B = 0xC3;   // Noise-canceller enabled; Rising-edge triggered; clk/64
  TIMSK4 = 0x20;   // Enable interrupts.
  TIMSK5 = 0x20;
}

It works for me, if it doesn’t work for you, let me know.