Using an internal timer and SPI at the same time

I found this code over at adafruit that’s great for taking the work out of my 5-way joystick (5 buttons). I have now idea how the heart of it works, as I’m only familiar with the Arduino IDE, with no C++ or experience. It calls functions and stuff to trigger a timer to check the buttons independently of my code.
I don’t really like not knowing how parts of my code work, but I think this is way over my head. So I would just like to know that this timer interrupt thing will work with all my other code. Mainly, I’ll be checking an RTC over SPI every few seconds. This timer interrupt won’t butt in on that and make a glitch at random times, will it?
Thanks,
here a copy of the code from adafruit.

#define DEBOUNCE 10  // button debouncer, how many ms to debounce, 5+ ms is usually plenty

// here is where we define the buttons that we'll use. button "1" is the first, button "6" is the 6th, etc
byte buttons[] = {14, 15, 16, 17, 18, 19}; // the analog 0-5 pins are also known as 14-19
// This handy macro lets us determine how big the array up above is, by checking the size
#define NUMBUTTONS sizeof(buttons)
// we will track if a button is just pressed, just released, or 'currently pressed' 
volatile byte pressed[NUMBUTTONS], justpressed[NUMBUTTONS], justreleased[NUMBUTTONS];

void setup() {
  byte i;

  // set up serial port
  Serial.begin(9600);
  Serial.print("Button checker with ");
  Serial.print(NUMBUTTONS, DEC);
  Serial.println(" buttons");

  // pin13 LED
  pinMode(13, OUTPUT);

  // Make input & enable pull-up resistors on switch pins
  for (i=0; i< NUMBUTTONS; i++) {
    pinMode(buttons[i], INPUT);
    digitalWrite(buttons[i], HIGH);
  }

  // Run timer2 interrupt every 15 ms 
  TCCR2A = 0;
  TCCR2B = 1<<CS22 | 1<<CS21 | 1<<CS20;

  //Timer2 Overflow Interrupt Enable
  TIMSK2 |= 1<<TOIE2;

}

SIGNAL(TIMER2_OVF_vect) {
  check_switches();
}

void check_switches()
{
  static byte previousstate[NUMBUTTONS];
  static byte currentstate[NUMBUTTONS];
  static long lasttime;
  byte index;

  if (millis() < lasttime) {
     // we wrapped around, lets just try again
     lasttime = millis();
  }

  if ((lasttime + DEBOUNCE) > millis()) {
    // not enough time has passed to debounce
    return;
  }
  // ok we have waited DEBOUNCE milliseconds, lets reset the timer
  lasttime = millis();

  for (index = 0; index < NUMBUTTONS; index++) {

    currentstate[index] = digitalRead(buttons[index]);   // read the button

    /*     
    Serial.print(index, DEC);
    Serial.print(": cstate=");
    Serial.print(currentstate[index], DEC);
    Serial.print(", pstate=");
    Serial.print(previousstate[index], DEC);
    Serial.print(", press=");
    */

    if (currentstate[index] == previousstate[index]) {
      if ((pressed[index] == LOW) && (currentstate[index] == LOW)) {
          // just pressed
          justpressed[index] = 1;
      }
      else if ((pressed[index] == HIGH) && (currentstate[index] == HIGH)) {
          // just released
          justreleased[index] = 1;
      }
      pressed[index] = !currentstate[index];  // remember, digital HIGH means NOT pressed
    }
    //Serial.println(pressed[index], DEC);
    previousstate[index] = currentstate[index];   // keep a running tally of the buttons
  }
}

void loop() {
  for (byte i = 0; i < NUMBUTTONS; i++) {
    if (justpressed[i]) {
      justpressed[i] = 0;
      Serial.print(i, DEC);
      Serial.println(" Just pressed");
      // remember, check_switches() will CLEAR the 'just pressed' flag
    }
    if (justreleased[i]) {
      justreleased[i] = 0;
      Serial.print(i, DEC);
      Serial.println(" Just released");
      // remember, check_switches() will CLEAR the 'just pressed' flag
    }
    if (pressed[i]) {
      Serial.print(i, DEC);
      Serial.println(" pressed");
      // is the button pressed down at this moment
    }
  }
}

Please note that the "volatile byte" arrays are separate from the "static byte" arrays even though they have the same name. The static ones exist only to the code inside check_switches(). All the other code uses the volatile ones. You should probably get rid of the static ones.

:relaxed: Hugh? I think I know what volatile means. ...I use that when I'm going to have an interrupt pin change a variable. I don't know static or why it's used. (I didn't write this code, I just found it at adafruit) So you're saying that the code isn't stable? I see where it has:

volatile byte pressed[NUMBUTTONS], justpressed[NUMBUTTONS], justreleased[NUMBUTTONS];

and also

  static byte previousstate[NUMBUTTONS];
  static byte currentstate[NUMBUTTONS];
  static long lasttime;

...so somethings' not right with this? Should I replace the word static with volatile??

Oops... My mistake. I thought the (global) volatile arrays and the (local) static arrays had the same name.

Nevermind.

That’s ok. I’ve read up on static variables. Didn’t know about that. I have a lot of variables I declare at the beginning (global) but they can actually be static. They are only used in 1 function, but that function needs to remember them. I’m going to move all my globals to static that don’t need to be global. I guess this is good practice?
It will make my code neater and easier for me to read.

ps. So this timer thing that’s programmed directly in (note my original post). …It must not interrupt my SPI transmission, or anything else important? It’s all working, seemingly.
Here’s the code that I really don’t know what it does, it’s not normal Arduino code…

 // Run timer2 interrupt every 15 ms 
  TCCR2A = 0;
  TCCR2B = 1<<CS22 | 1<<CS21 | 1<<CS20;

  //Timer2 Overflow Interrupt Enable
  TIMSK2 |= 1<<TOIE2;

SouthernAtHeart:
I guess this is good practice? It will make my code neater and easier for me to read.

Then it’s good practice.

…It must not interrupt my SPI transmission, or anything else important?

Transmitting each byte is handled by hardware so individual bytes won’t be interrupted. There will be a delay between bytes while your interrupt service routine runs. But SPI is very resistant to “random” delays. I would be very surprised if you had problems.

Here’s the code that I really don’t know what it does, it’s not normal Arduino code…

The processors’s datasheet is helpful for code like that.

TCCR2A = 0;
…sets timer 2 to run as a simple timer. Count up to 0xFF then rollover to 0x00. No PWM output.

TCCR2B = 1<<CS22 | 1<<CS21 | 1<<CS20;
…sets timer 2 to run as a simple timer (the configuration is split between the two registers). Sets the “prescaler” to 1024. The timer “ticks” each 1 / (F_CPU / 1024) seconds (64 microseconds).

TIMSK2 |= 1<<TOIE2;
…sets bit TOIE2 to 1 in the TIMSK2 register. This enables the “overflow” interrupt. When the timer’s value rolls-over from 0xFF to 0x00 an interrupt is generated. This occurs every 64 microseconds * 256 = 16.384 milliseconds.