Hello, I am working on a harddrive clock of my own utilizing the excellent firmware from Giles F. Hall as a starting point. I am integrating the clock functionality into the arduino, whereas Giles had the arduino read the colours to be drawn and the position from a serial port at 115200 baud.
However, I have encountered a problem with Giles’s ISR code breaking millis() and the Time library which I need. I have a hunch that the Giles’s ISR timing on timer #2 (which I have trouble grasping) is breaking millis(), which Time is reliant upon.
Here is a simplified version of the relevant code which sets ISR timing:
//---at the top of the program:-----
#ifndef F_CPU
#define F_CPU 16000000UL // 16 MHz
#endif
#include <stdlib.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <Time.h>
#include <buttons.h> //debouncing library
#undef int
#include <stdio.h>
#define DIVISIONS 0xFF
#define RGB(R,G,B) (R << RED | G << GRN | B << BLU)
#define FREQ_DIV_8 (F_CPU / 8)
#define MILLITICK (FREQ_DIV_8 * .001)
#define SPURIOUS_INT (2 * MILLITICK)
#define bitset(var,bitno) ((var) |= (1 << (bitno)))
#define bitclr(var,bitno) ((var) &= ~(1 << (bitno)))
#define bittst(var,bitno) (var& (1 << (bitno)))
#define DEBOUNCETIME 50
//----in the setup:-----
cli(); // disable global interrupts
TCCR0A = 0; // setup timer0 - 8bit for timing the LEDs
TCCR0B = 0;
bitset(TCCR0A, WGM01); // select CTC mode
bitset(TCCR0B, CS01); // select prescaler clk / 8
bitset(TIMSK0, OCIE0A); // enable compare interrupt
TCCR1B = 0; // setup timer1 - 16bit for timing the rotation of the platter
TCCR1A = 0;
bitset(TCCR1B, CS11); // select prescaler clk / 8
TCNT1 = 0; // reset timer
bitset(TIMSK1, TOIE1); // enable overflow interrupt
EICRA = _BV(ISC01); // configure the platter interrupt PIN
EIMSK |= _BV(INT0); // Enable the hardware interrupt.
period = 0; // set the rotational period to 0
init_pages();
sei(); // enable global interrupts
//----after the void loop():-----
ISR(INT0_vect) // This interrupt is called on every pulse of the sensor
{
// Capture the 16bit count on timer1, this represents one revolution
period = TCNT1;
if(period < SPURIOUS_INT)
{
return;
}
// Reset timer1 and timer 0 for next revolution and for light painting
TCNT1 = 0;
TCNT0 = 0;
flip_to_next_page();
PORTD = FrameBuffer[page_visible][0]; // Write out the LED value to the Frame Buffer
OCR0A = (period / divisions);
current_slice = 1;
}
// This interrupt is called every time timer0 counts up to the 8bit value
// stored in the register "ORC0A", which is configured in INT0 interrupt.
ISR(TIMER0_COMPA_vect) {
PORTD = FrameBuffer[page_visible][current_slice];
current_slice = ((current_slice + 1) % divisions);
}
// If the platter spin time overflows timer1, this is called
ISR(TIMER1_OVF_vect) {
}
Any help greatly appreciated!