added support for teensy ARM versions timers. only tested on teensy LC so far, but should work on other ARM versions as well. PS: tested using teensyduino with arduino environment

pull/7/head
midilab 4 years ago
parent 719a60a81f
commit 01409980bf
  1. 100
      src/uClock.cpp
  2. 6
      src/uClock.h

@ -3,7 +3,7 @@
* Project BPM clock generator for Arduino * Project BPM clock generator for Arduino
* @brief A Library to implement BPM clock tick calls using hardware timer1 interruption. Tested on ATmega168/328, ATmega16u4/32u4 and ATmega2560. * @brief A Library to implement BPM clock tick calls using hardware timer1 interruption. Tested on ATmega168/328, ATmega16u4/32u4 and ATmega2560.
* Derived work from mididuino MidiClock class. (c) 2008 - 2011 - Manuel Odendahl - wesen@ruinwesen.com * Derived work from mididuino MidiClock class. (c) 2008 - 2011 - Manuel Odendahl - wesen@ruinwesen.com
* @version 0.8.3 * @version 0.9.0
* @author Romulo Silva * @author Romulo Silva
* @date 08/21/2020 * @date 08/21/2020
* @license MIT - (c) 2020 - Romulo Silva - contact@midilab.co * @license MIT - (c) 2020 - Romulo Silva - contact@midilab.co
@ -26,16 +26,61 @@
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE. * DEALINGS IN THE SOFTWARE.
*/ */
#include "uClock.h"
// TODO: use float for decimal timming precision: 120.10, 120.20 #define ATOMIC(X) noInterrupts(); X; interrupts();
// each 0.1 bpm equals 15.625 intervals on 16Mhz clock
// each 1 bpm equals 156.250 intervals on 16Mhz clock
#include "uClock.h" //
// Timer setup
// Work clock at: 62.5kHz/16usec
//
#if defined(TEENSYDUINO)
IntervalTimer _teensyTimer;
void teensyInterrupt();
void initTeensyTimer()
{
_teensyTimer.begin(teensyInterrupt, 16);
// Set the interrupt priority level, controlling which other interrupts
// this timer is allowed to interrupt. Lower numbers are higher priority,
// with 0 the highest and 255 the lowest. Most other interrupts default to 128.
// As a general guideline, interrupt routines that run longer should be given
// lower priority (higher numerical values).
//_teensyTimer.priority(128);
}
#else
void initArduinoTimer()
{
//
// Configure timers and prescale
// Timmer1: ATMega128, ATMega328, AtMega16U4 and AtMega32U4
// Clock Speed Selection
// CS10: Clock (No prescaling)
// Waveform Generation Mode (WGM) 16-bit timer settings
// (WGM10, WGM12) Mode 5
// Fast Pulse Width Modulation (PWM), 8-bit:
// TOP: 0x00FF (255)
// OCR1x Update: BOTTOM
// TOV1 Flag: TOP
// Overflow Interrupt Enable
ATOMIC(
TCCR1A = 0;
TCCR1A = _BV(WGM10);
TCCR1B = 0;
TCCR1B = _BV(CS10) | _BV(WGM12);
TIMSK1 |= _BV(TOIE1);
)
}
#endif
namespace umodular { namespace clock { void initWorkTimer() {
#if defined(TEENSYDUINO)
initTeensyTimer();
#else
initArduinoTimer();
#endif
}
uint8_t _tmpSREG; namespace umodular { namespace clock {
static inline uint32_t phase_mult(uint32_t val) static inline uint32_t phase_mult(uint32_t val)
{ {
@ -54,7 +99,8 @@ static inline uint16_t clock_diff(uint16_t old_clock, uint16_t new_clock)
uClockClass::uClockClass() uClockClass::uClockClass()
{ {
// 11 is good for native 31250bps midi interface // 11 is good for native 31250bps midi interface
// 4 is good for usb-to-midi hid // 4 is good for usb-to-midi hid on leonardo
// 1 is good on teensy lc usb midi
drift = 11; drift = 11;
pll_x = 220; pll_x = 220;
start_timer = 0; start_timer = 0;
@ -72,19 +118,7 @@ uClockClass::uClockClass()
void uClockClass::init() void uClockClass::init()
{ {
setTempo(120); setTempo(120);
// initWorkTimer();
// Configure timers and prescale
// Timmer1: ATMega128, ATMega328, AtMega16U4 and AtMega32U4
_tmpSREG = SREG;
cli();
// Waveform Generation Mode (WGM) 16-bit timer settings
// (WGM10, WGM12) Mode 5: Fast Pulse Width Modulation (PWM), 8-bit
// Clock Speed Selection
// CS10: Clock (No prescaling)
TCCR1A = _BV(WGM10);
TCCR1B = _BV(CS10) | _BV(WGM12);
TIMSK1 |= _BV(TOIE1);
SREG = _tmpSREG;
} }
void uClockClass::start() void uClockClass::start()
@ -138,12 +172,12 @@ void uClockClass::setTempo(uint16_t bpm)
return; return;
} }
_tmpSREG = SREG;
cli();
tempo = bpm; tempo = bpm;
ATOMIC(
//interval = 62500 / (tempo * 24 / 60) - drift; //interval = 62500 / (tempo * 24 / 60) - drift;
interval = (uint16_t)(156250 / tempo) - drift; interval = (uint16_t)(156250 / tempo) - drift;
SREG = _tmpSREG; )
} }
uint16_t uClockClass::getTempo() uint16_t uClockClass::getTempo()
@ -156,7 +190,9 @@ uint16_t uClockClass::getTempo()
void uClockClass::setDrift(uint8_t value) void uClockClass::setDrift(uint8_t value)
{ {
ATOMIC(
drift = value; drift = value;
)
} }
uint8_t uClockClass::getMode() uint8_t uClockClass::getMode()
@ -172,7 +208,9 @@ void uClockClass::setMode(uint8_t tempo_mode)
void uClockClass::clockMe() void uClockClass::clockMe()
{ {
if (mode == EXTERNAL_CLOCK) { if (mode == EXTERNAL_CLOCK) {
handleClock(); ATOMIC(
handleExternalClock()
)
} }
} }
@ -200,7 +238,7 @@ void uClockClass::shuffle()
// shuffle me // shuffle me
} }
void uClockClass::handleClock() void uClockClass::handleExternalClock()
{ {
uint16_t cur_clock = _clock; uint16_t cur_clock = _clock;
uint16_t diff = clock_diff(last_clock, cur_clock); uint16_t diff = clock_diff(last_clock, cur_clock);
@ -231,7 +269,6 @@ void uClockClass::handleClock()
} }
break; break;
} }
} }
void uClockClass::handleTimerInt() void uClockClass::handleTimerInt()
@ -342,9 +379,14 @@ volatile uint16_t _clock = 0;
volatile uint32_t _timer = 0; volatile uint32_t _timer = 0;
// //
// TIMER1 HANDLER INTERRUPT // TIMER INTERRUPT HANDLER
// Clocked at: 62.5kHz/16usec
// //
#if defined(TEENSYDUINO)
void teensyInterrupt()
#else
ISR(TIMER1_OVF_vect) ISR(TIMER1_OVF_vect)
#endif
{ {
// global timer counter // global timer counter
_timer = millis(); _timer = millis();
@ -354,5 +396,3 @@ ISR(TIMER1_OVF_vect)
uClock.handleTimerInt(); uClock.handleTimerInt();
} }
} }

@ -3,7 +3,7 @@
* Project BPM clock generator for Arduino * Project BPM clock generator for Arduino
* @brief A Library to implement BPM clock tick calls using hardware timer1 interruption. Tested on ATmega168/328, ATmega16u4/32u4 and ATmega2560. * @brief A Library to implement BPM clock tick calls using hardware timer1 interruption. Tested on ATmega168/328, ATmega16u4/32u4 and ATmega2560.
* Derived work from mididuino MidiClock class. (c) 2008 - 2011 - Manuel Odendahl - wesen@ruinwesen.com * Derived work from mididuino MidiClock class. (c) 2008 - 2011 - Manuel Odendahl - wesen@ruinwesen.com
* @version 0.8.3 * @version 0.9.0
* @author Romulo Silva * @author Romulo Silva
* @date 08/21/2020 * @date 08/21/2020
* @license MIT - (c) 2020 - Romulo Silva - contact@midilab.co * @license MIT - (c) 2020 - Romulo Silva - contact@midilab.co
@ -67,7 +67,7 @@ class uClockClass {
uint32_t div16th_counter; uint32_t div16th_counter;
uint8_t mod6_counter; uint8_t mod6_counter;
uint8_t inmod6_counter; uint8_t inmod6_counter;
uint16_t interval; volatile uint16_t interval;
uint16_t counter; uint16_t counter;
uint16_t last_clock; uint16_t last_clock;
uint16_t last_interval; uint16_t last_interval;
@ -105,8 +105,8 @@ class uClockClass {
} }
void init(); void init();
void handleClock();
void handleTimerInt(); void handleTimerInt();
void handleExternalClock();
void resetCounters(); void resetCounters();
// external class control // external class control

Loading…
Cancel
Save