// include required libraries
#include <avr/interrupt.h>
#include <avr/sleep.h>
//array of different frequencies
float timerFreq[] = { 0.5, 1, 2, 4, 8 };
/*
index to keep track of current frequency
1 sec is selected as initial frequency
*/
volatile int currFreqIndex = 1;
/*
varible to keep track of timer frequency
need to calcualte TCNT1
*/
volatile float count1;
/*
booleans to keep track if any of the switch is pressed
*/
volatile bool switch1Pressed = false;
volatile bool switch2Pressed = false;
/*
debug variable
print debug statements if debug =1
else do not print the statements
*/
int debug = 1;
/*
the function to calculate count value
it takes frequency as input and return count value
which is used in TCNT1 = 0xFFFF - count1
to calculate value of timer 1
*/
float countValue(float frequency) {
/*
refrence for the equation - https://oscarliang.com/arduino-timer-and-interrupt-tutorial/
1024 is set a pre-scalar
*/
return (16 * pow(10, 6)) / (frequency * 1024);
}
//setup function
void setup() {
// clear global interrupt
cli();
//set pin 6 (port D & 6) as output
DDRD |= B01000000;
//set pin 7 (port D & 7) as input
DDRD &= B01111111;
//set pin 8 (port B & 0) as input
DDRB &= B111110;
/*
control registers for PCINT
enable PCINT0 (pin 8) and PCINT2 (pin 7)
*/
PCICR |= B00000101;
// select PCINT0 mask (pin 8)
PCMSK0 |= B00000001;
// select PCINT2 mask (pin 7)
PCMSK2 |= B10000000;
// set timer 1 to normal mode
TCCR1A = B00000000;
// set pre-scaler to 1024
TCCR1B = B00000101;
// turn ON OVF
TIMSK1 = B00000001;
// calcualte count value for 1 sec
count1 = countValue(timerFreq[currFreqIndex]);
// initial Timer1 value
TCNT1 = 0xFFFF - count1;
//enable serial begin for printing
if (debug) {
Serial.begin(9600);
}
/*
set sleep mode
since we are using timer and clk_IO
sleep mode must be set to SLEEP_MODE_IDLE
*/
set_sleep_mode(SLEEP_MODE_IDLE);
//turn on global interrupt
sei();
}
//Timer1 ISR
ISR(TIMER1_OVF_vect) {
//toggle LED (pin 6; port D & 6)
PORTD ^= B01000000;
// if switch 1 is pressed
if (switch1Pressed) {
/*
if it is the lowest frequency i.e. 0.5 hz
set switch preseed to false
*/
if (currFreqIndex == 0) {
switch1Pressed = false;
}
/*
if it is not the lowest frequency,
keep decreasing the index and frequency
and print message
*/
else {
currFreqIndex--;
if (debug) {
Serial.print("Timer frequency decreased to ");
Serial.println(timerFreq[currFreqIndex]);
}
}
}
// if switch 2 is pressed
if (switch2Pressed) {
/*
if it is the highest frequency i.e. 8 hz
set switch preseed to false
*/
if (currFreqIndex == 4) {
switch2Pressed = false;
}
/*
if it is not the highest frequency,
keep increasing the index and frequency
and print message
*/
else {
currFreqIndex++;
if (debug) {
Serial.print("Timer frequency increased to ");
Serial.println(timerFreq[currFreqIndex]);
}
}
}
// get the count value for current frequency
count1 = countValue(timerFreq[currFreqIndex]);
// update Timer1 value
TCNT1 = 0xFFFF - count1;
}
// PCINT0 ISR for pin 8
ISR(PCINT0_vect) {
/*
get state of pin 8 (port B & 0) using bit math instead of digitalRead()
reference -- https://arduinotoavr.wordpress.com/digitalread/
since the interrupt is raised on both raisign and fallling edge
we only make changes when button state is HIGH
*/
int buttonState = (PINB & (1 << PINB0) == 1);
/*
if button state is HIGH, set switch pressed to true
and set another switch pressed to false
*/
if (buttonState == HIGH) {
switch1Pressed = true;
switch2Pressed = false;
if (debug) {
Serial.println("Switch 1 (pin 8) pressed. ");
}
}
}
// PCINT0 ISR for pin 7
ISR(PCINT2_vect) {
/*
get state of pin 7 (port D & 7) using bit math instead of digitalRead()
reference -- https://arduinotoavr.wordpress.com/digitalread/
since the interrupt is raised on both raisign and fallling edge
we only make changes when button state is HIGH
*/
int buttonState = (PIND & (1 << PIND7)) == 128;
/*
if button state is HIGH, set switch pressed to true
and set another switch pressed to false
*/
if (buttonState == HIGH) {
switch2Pressed = true;
switch1Pressed = false;
if (debug) {
Serial.println("Switch 2 (pin 7) pressed. ");
}
}
}
//main loop
void loop() {
//sleep mode on
sleep_mode();
}