Interrupt multiplexing with MCP23008

I’m having an issue with handling multiple interrupts. I have a Microchip I2C I/O expander connected to my Arduino board. The INT pin of the MCP is connected to pin 2 on the Arduino (Interrupt 0), and the I/O pins on the MCP are connected to switches and other junk that I want to capture interrupts from. This side works fine, they’re all working properly. The Interrupts on the Arduino are enabled, and it works if I ground the line myself… the problem is that the MCP23008 should be doing this itself. I’ve gone through the data sheet several times, trying to figure it out, and I just can’t seem to make it all work properly.

Can anyone offer any advice/suggestions? Here is the code I’m using. The Lcd functions are in a separate file, work perfectly fine by themselves, and don’t touch anything except LCD pins and such. : |

/* Alarm clock "Proof of concept"
 */

#include <Wire.h>      // I2C library from Wire.
//#include <avr/pgmspace.h>  // Program memory from Atmel
#include <stdio.h>     // printf and family

/*-----------------------------------------------------------------
--               LCD communication pin definitions               --
-----------------------------------------------------------------*/
const int int_pin = 2;   // Pin Arduino is using Interrupts on
const int lcd_rs = 3;    // RS pin of LCD
const int lcd_rw = 4;    // R/W pin of LCD
const int lcd_en = 5;    // Enable pin of LCD
const int lcd_db[] = {6, 7, 8, 9, 10, 11, 12, 13}; // LCD data pins
const int lcd_db_size = 8;  // # data pins in array

/*-----------------------------------------------------------------
--                      Strings and buffers                      --
-----------------------------------------------------------------*/
char string_buffer[17];     // 16 characters + null
const char str_12hr_time[] = "   %2x:%02x:%02x%cM   ";
const char str_24hr_time[] = "    %02x:%02x:%02x    ";
const char str_date[]      = "  %3s, %3s %02x  ";
const char str_weekday[][4] = {"Sun", "Mon", "Tue", "Wed", "Thr", "Fri", "Sat"};
const char str_months[][4]  = {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
                                 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};

/*-----------------------------------------------------------------
--                    Interrupt Shennanigans                     --
-----------------------------------------------------------------*/
volatile bool int_flag;         // Place to hold interrupt flag
byte int_mask;                  // Bit mask of each interrupt line that was toggled.
const byte int_active = B00011111; // I/O expander lines with something that triggers interrupts

// Interrupt service function
void Interrupt()
{
  // All we need to do is indicate that an interrupt's been fired.
  int_flag = true;
}

// Setup junk.
void setup()
{
  // Set up I2C first.
  Wire.begin(12);
  Serial.begin(9600);
  
  pinMode(2, INPUT);
  
  Serial.println("Yo!");
  
  // Configure RTC for 1Hz Clockout
  Wire.beginTransmission(0x51);
  Wire.send(0x0D);
  Wire.send(0x83);
  Wire.endTransmission();
  
  // Set up the I/O Expander to produce interrupts
  Wire.beginTransmission(0x20);
  Wire.send(0x00);
  Wire.send(0xFF);
  Wire.send(0x00);
  Wire.send(int_active);
  Wire.send(int_active);
  Wire.send(int_active);
  Wire.send(0x04);
  Wire.endTransmission();
  
  // Fire up the LCD
  LcdInit();
  
  //Wire.beginTransmission(0x20);
  //Wire.send(0x00);
  //Wire.endTransmission();
  
  Wire.requestFrom(0x51, 11);
  while (Wire.available())
  {
    Serial.println(Wire.receive(), BIN);
  }
  
  // Start interrupts to falling edge
  attachInterrupt(0, Interrupt, FALLING);
}

// The main guts.
void loop()
{
  // Check if an interrupt has fired.
  if (int_flag)
  {
    // Clear the interrput flag now - if our routine takes too long, we might (will) miss
    // the next interrupt, which WILL fuck things up.
    int_flag = false;
    // Get data from the I/O expander to see which buggers fired.
    Wire.beginTransmission(0x20);
    Wire.send(0x07);
    Wire.endTransmission();
    
    Wire.requestFrom(0x20, 2);
    Serial.println(int_mask = Wire.receive(), BIN);
    Serial.println(Wire.receive(), BIN);
    
    // Do ... something.
    if (int_mask & 0x01)
    {
      byte sec, mins, hrs, day, wkd, mth;
      // CLKOUT fired. Update LCD.
      Wire.beginTransmission(0x51);
      Wire.send(0x02);
      Wire.endTransmission();
      
      Wire.requestFrom(0x51, 6);
      sec = Wire.receive() & B01111111;
      mins = Wire.receive() & B01111111;
      hrs = Wire.receive() & B00111111;
      day = Wire.receive() & B00111111;
      wkd = Wire.receive() & B00000111;
      mth = Wire.receive() & B00011111;
      
      // Write new time
      LcdSetPos(0,0);
      sprintf(string_buffer, str_24hr_time, hrs, mins, sec);
      Serial.println(string_buffer);
      LcdPrint(string_buffer);
      sprintf(string_buffer, str_date, str_weekday[wkd], str_months[mth - 1], day);
      Serial.println(string_buffer);
      LcdSetPos(1, 0);
      LcdPrint(string_buffer);
    }
  }
}

Did you connect the grounds of the Arduino board and the MCP23008 together ?

Yup. The Arduino 5V and Ground are the only power connections I have in this circuit.