I tried to create an avr timer, reading maxembedded introduction
but I am not able to make it work.
I recreated a simple program using timers to let you know what I am trying to do.
I believe this is pretty straightforward:
my midi array is composed of 128 bytes,
I want the timer to interrupt everytime I need to send a byte.
If the 128 bytes have been read, I want to go back to the start of the sequence.
Equally, if I push start_button, I want the sequence to start at (flow = 0).
#include <Bounce2.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#define LED 5
#define startbutton 2
Bounce start_button;
byte start_at_zero = 0;
int flow = 0;
float clock_frequency = 0.0000625;
int tempo = 100;
void setup()
{
Serial.begin(32500);
pinMode(LED, OUTPUT);
pinMode(startbutton, INPUT);
start_button.attach(startbutton);
start_button.interval(5);
digitalWrite(LED, LOW);
//Starts here..
float clock_frequency = 0.0000625; //16Mhz on arduino uno
cli();
TCCR1A = 0;
TCCR1B = 0;
// I set the first timer for comparison
// (6000/tempo*4/128) = 1 mesure divided by 128 events;
OCR1A = (6000/tempo*4/128)/clock_frequency - 1;
// CTC mode on for second timer:
TCCR1B |= (1 << WGM12);
// timer compare interrupt:
TIMSK1 |= (1 << OCIE1A);
sei();
}
ISR(TIMER1_COMPA_vect)
{
if (new_start == 1)
flow = new_start = 0;
if (flow == 0)
digitalWrite(LED, HIGH);
else if (flow == 64)
digitalWrite(LED, LOW);
flow++;
if (flow >= 128)
flow = 0;
}
void loop()
{
if (start_button.update() && start_button.read() == HIGH)
new_start = 1;
}
Would you help me to find what is going wrong ?
I am pretty sure the code is "almost" good and the modification to make it work,
not huge.
float clock_frequency = 0.0000625; //16Mhz on arduino uno
A local variable with the same name as a global variable is NEVER a good thing.
OCR1A = (6000/tempo*4/128)/clock_frequency - 1;
Do you KNOW, without having to look, the order that the operands will be evaluated in? Does that result in the value that you expect in OCR1A? Use parentheses to force the operands to be evaluated in the order you expect.
Variables used in ISRs and other functions (like new_start and flow) need to be volatile.
I want the timer to interrupt everytime I need to send a byte.
So, where are you actually sending a byte somewhere?
If the 128 bytes have been read
Read? You said send in the previous sentence. Which is it? Where are you reading anything?
clock_frequency is only a global variable here.
I think I know the order of operands, yes.
Here, I want to calculate the time between every note I play:
I divide a second by my tempo and multiply it by 4, to have the duration of a measure (4 times).
Then, I divide it by 128 to have the duration between every note.
So, this becomes the required delay.
Then, if I understand well, I divide it by by the clock_frequency, to have the timer count.
That way, I obtain 29.999. Is that the good way to do it ?
I am not actually reading or sending any byte in this code, but this is what I want my code to be for.
Flow is the value that would be used to read a byte in a string and send it to the midi output.
I just didn't want it to appear here not to make the code complex.
The problem is that nothing is happening and I don't know how to test it,
as I can't print anything inside the ISR.
So, my guess is the timer is badly set up,
or the comparison between the timers never occurs, as the led never blinks.
Still, I am not able to fully understand how to set up a timer...