-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Interrupts for rotary encoder and buttons, timer0 based sound generat…
…or, timer1 based tap tempo, basic metronome
- Loading branch information
1 parent
a346c93
commit 25bae8d
Showing
7 changed files
with
264 additions
and
14 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,5 @@ | ||
# metronome | ||
# metronome | ||
|
||
``` | ||
make flash | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
#ifndef __interrupts_h__ | ||
#define __interrupts_h__ | ||
|
||
ISR(PCINT2_vect) { | ||
clearBit(SPEAKER_DIR, SPEAKER); | ||
bool btnPushed = bit_is_clear(ROTARY_PIN, ROTARY_BTN); | ||
if (bit_is_clear(ROTARY_PIN, ROTARY_A)) | ||
{ | ||
if (bit_is_clear(ROTARY_PIN, ROTARY_B)) | ||
{ | ||
if (btnPushed) | ||
{ | ||
if (cursor) | ||
{ | ||
--cursor; | ||
} | ||
else | ||
{ | ||
cursor = 3u; | ||
} | ||
} | ||
else | ||
{ | ||
updateActiveParam(-1); | ||
} | ||
} | ||
else | ||
{ | ||
if (btnPushed) | ||
{ | ||
++cursor; | ||
cursor %= 4u; | ||
} | ||
else | ||
{ | ||
updateActiveParam(1); | ||
} | ||
} | ||
|
||
t_beep = 6000u / bpm; | ||
t_sleep = 54000u / bpm; | ||
|
||
update_display(); | ||
// force a little down time before continuing | ||
_delay_ms(2); | ||
// wait until R1 comes back high | ||
while (bit_is_clear(ROTARY_PIN, ROTARY_A)) | ||
; | ||
} | ||
|
||
if (bit_is_clear(TAP_PIN, TAP_BTN)) | ||
{ | ||
sound_locked = false; | ||
play_note(120u, t_beep); | ||
sound_locked = true; | ||
// tap tempo handler | ||
if (tap_started) | ||
{ | ||
if (tap_interval_counter < 2001u && tap_interval_counter > 130u) | ||
{ | ||
t_beep = tap_interval_counter >> 4; | ||
t_sleep = tap_interval_counter - t_beep; | ||
bpm = 60000u / tap_interval_counter; | ||
update_display(); | ||
} | ||
} | ||
else | ||
{ | ||
tap_started = true; | ||
sound_locked = true; | ||
} | ||
// start counting | ||
tap_interval_counter = 0u; | ||
//TCCR2A = 0; | ||
TCCR2B = 0x4; | ||
TCNT2 = TAP_TIMER_INITIAL_OFFSET; // 131 ticks until overflow | ||
} | ||
} | ||
|
||
// tap tempo timer (1ms) overflow | ||
ISR(TIMER2_OVF_vect) | ||
{ | ||
if (tap_interval_counter < 2001u) | ||
{ | ||
++tap_interval_counter; | ||
TCNT2 = TAP_TIMER_INITIAL_OFFSET; | ||
} | ||
else | ||
{ | ||
// dismiss tap tempo in case of timeout (over 2000ms) | ||
tap_started = false; | ||
TCCR2B &= ~(TCCR2B & 0x7); | ||
sound_locked = false; | ||
} | ||
} | ||
|
||
#endif //__interrupts_h__ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,153 @@ | ||
#define F_CPU 8000000 | ||
|
||
#ifndef BAUD | ||
#define BAUD 9600 | ||
#endif | ||
|
||
#include <util/setbaud.h> | ||
#include <util/delay.h> | ||
#include <avr/power.h> | ||
#include <avr/interrupt.h> | ||
#include <stdio.h> | ||
|
||
#include "util.h" | ||
#include "setup.h" | ||
#include "lcd.h" | ||
|
||
volatile uint8_t cursor; | ||
volatile uint16_t bpm; | ||
volatile uint8_t signature; // e.g. 0100 0100 for 4/4 time signature | ||
volatile uint16_t t_beep; | ||
volatile uint16_t t_sleep; | ||
volatile uint8_t volume; | ||
volatile uint16_t tap_interval_counter; | ||
volatile bool tap_started; | ||
volatile bool sound_locked; | ||
uint8_t signatures[2] = { 0x44, 0x34 }; | ||
char firstLineBuffer[LCD_SIZE+1]; | ||
char secondLineBuffer[LCD_SIZE+1]; | ||
|
||
static void setup(void); | ||
|
||
static void loop(void); | ||
|
||
inline static void update_display(void) { | ||
snprintf(firstLineBuffer, 17, "%c %3uBPM %c %2u/%1u ", | ||
cursorVisible(cursor, 0), | ||
bpm, | ||
cursorVisible(cursor, 1), | ||
signatures[signature] >> 4, | ||
signatures[signature] & 0x0f); | ||
snprintf(secondLineBuffer, 17, "%c %3u%% %c %s", | ||
cursorVisible(cursor, 2), | ||
volume, | ||
cursorVisible(cursor, 3), | ||
"SOUND"); | ||
lcd_string_xy(0, 0, firstLineBuffer); | ||
lcd_string_xy(1, 0, secondLineBuffer); | ||
} | ||
|
||
static void updateActiveParam(int delta) { | ||
switch (cursor) { | ||
case 0u: | ||
if (bpm > 80u && bpm < 350u) | ||
bpm += delta; | ||
break; | ||
case 1u: | ||
signature += delta; | ||
signature %= 2; | ||
break; | ||
case 2u: | ||
if (volume > 0u && volume < 100u) | ||
volume += delta; | ||
break; | ||
case 3u: | ||
break; | ||
default: | ||
break; | ||
} | ||
} | ||
|
||
inline static void init_interrupts(void) { | ||
// enable pin change interrupts on PORTD | ||
PCICR |= (1 << PCIE2); | ||
|
||
// pin change interrupt mask | ||
PCMSK2 |= ((1 << ROTARY_A) | (1 << ROTARY_B) | (1 << TAP_BTN)); | ||
|
||
// enable interrupts globally | ||
sei(); | ||
} | ||
|
||
inline static void init_tap_timer(void) { | ||
TIMSK2 = (1 << TOIE2); | ||
} | ||
|
||
inline static void init_sound_timer(void) { | ||
setBit(TCCR0A, WGM01); | ||
setBit(TCCR0A, COM0A0); | ||
setBit(TCCR0B, CS00); | ||
setBit(TCCR0B, CS01); | ||
} | ||
|
||
inline static void play_note(uint8_t wavelength, uint8_t duration) { | ||
OCR0A = wavelength; | ||
if (!sound_locked) { | ||
setBit(SPEAKER_DIR, SPEAKER); | ||
while (duration) { | ||
_delay_ms(1u); | ||
--duration; | ||
} | ||
clearBit(SPEAKER_DIR, SPEAKER); | ||
} | ||
} | ||
|
||
// IMPORTANT: this must be included right here | ||
#include "interrupts.h" | ||
|
||
int main(void) { | ||
while (true); | ||
setup(); | ||
loop(); | ||
return (0); | ||
} | ||
} | ||
|
||
static void setup(void) { | ||
// clk / 1 | ||
clock_prescale_set(CLK_NO_DIVIDE); | ||
|
||
// TODO Read stored settings from internal EEPROM | ||
cursor = 0u; | ||
bpm = DEFAULT_BPM; | ||
volume = DEFAULT_VOL; | ||
signature = DEFAULT_SIGNATURE; | ||
t_beep = 6000u / bpm; | ||
t_sleep = 54000u / bpm; | ||
tap_interval_counter = 0u; | ||
tap_started = false; | ||
sound_locked = false; | ||
|
||
lcd_init(); | ||
init_tap_timer(); | ||
init_sound_timer(); | ||
init_interrupts(); | ||
|
||
setInputPullup(ROTARY_DIR, ROTARY_PORT, ROTARY_A); | ||
setInputPullup(ROTARY_DIR, ROTARY_PORT, ROTARY_B); | ||
setInputPullup(ROTARY_DIR, ROTARY_PORT, ROTARY_BTN); | ||
setInputPullup(TAP_DIR, TAP_PORT, TAP_BTN); | ||
|
||
update_display(); | ||
} | ||
|
||
static void loop(void) { | ||
uint8_t i = 0u; | ||
while (true) { | ||
play_note(100u, t_beep); | ||
_delay_ms(t_sleep); | ||
for (i = 0u; i < (signatures[signature] >> 4) - 1; ++i) { | ||
play_note(120u, t_beep); | ||
_delay_ms(t_sleep); | ||
} | ||
} | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters