annotate Source/Utility/TimerNode.cpp @ 56:b4a2d2ae43cf tip

merge
author Andrew McPherson <andrewm@eecs.qmul.ac.uk>
date Fri, 23 Nov 2018 15:48:14 +0000
parents 3580ffe87dc8
children
rev   line source
andrewm@0 1 /*
andrewm@0 2 TouchKeys: multi-touch musical keyboard control software
andrewm@0 3 Copyright (c) 2013 Andrew McPherson
andrewm@0 4
andrewm@0 5 This program is free software: you can redistribute it and/or modify
andrewm@0 6 it under the terms of the GNU General Public License as published by
andrewm@0 7 the Free Software Foundation, either version 3 of the License, or
andrewm@0 8 (at your option) any later version.
andrewm@0 9
andrewm@0 10 This program is distributed in the hope that it will be useful,
andrewm@0 11 but WITHOUT ANY WARRANTY; without even the implied warranty of
andrewm@0 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
andrewm@0 13 GNU General Public License for more details.
andrewm@0 14
andrewm@0 15 You should have received a copy of the GNU General Public License
andrewm@0 16 along with this program. If not, see <http://www.gnu.org/licenses/>.
andrewm@0 17
andrewm@0 18 =====================================================================
andrewm@0 19
andrewm@0 20 TimerNode.cpp: creates a Node object which runs its own thread to generate
andrewm@0 21 timestamps.
andrewm@0 22 */
andrewm@0 23
andrewm@0 24 #include "TimerNode.h"
andrewm@0 25
andrewm@0 26 using std::cout;
andrewm@0 27 using std::endl;
andrewm@0 28
andrewm@0 29 // Start the timer, if it isn't already running. The update rate is set elsewhere.
andrewm@0 30 void TimerNode::start(timestamp_type where) {
andrewm@0 31 if(isRunning_)
andrewm@0 32 return;
andrewm@0 33 startingTimestamp_ = where;
andrewm@0 34 startThread();
andrewm@0 35 isRunning_ = true;
andrewm@0 36 }
andrewm@0 37
andrewm@0 38 // Stop the timer if it is currently running. This kills the associated thread.
andrewm@0 39 void TimerNode::stop() {
andrewm@0 40 if(!isRunning_)
andrewm@0 41 return;
andrewm@0 42 signalThreadShouldExit();
andrewm@0 43 notify();
andrewm@0 44 stopThread(-1); // Ask the thread to stop; no timeout
andrewm@0 45 isRunning_ = false;
andrewm@0 46 }
andrewm@0 47
andrewm@0 48 // This function runs in its own thread, as managed by the Juce Thread parent class. It produces
andrewm@0 49 // data points approximately separated in time by intervalMicros_. The resolution of the system
andrewm@0 50 // timer affects how precise the spacing will be. Though the ticks may jitter, there shouldn't
andrewm@0 51 // be any systematic drift unless intervalMicros_ is smaller than the execution time of the loop.
andrewm@0 52 // (For example, 1000 will be fine; 1 is too short)
andrewm@0 53
andrewm@0 54 void TimerNode::run() {
andrewm@0 55 unsigned long long targetMicros = 0;
andrewm@0 56
andrewm@0 57 // Find the start time, against which our offsets will be measured.
andrewm@0 58 double startTime = Time::getMillisecondCounterHiRes();
andrewm@0 59 double nextTime;
andrewm@0 60
andrewm@0 61 while(!threadShouldExit()) {
andrewm@0 62 // Get the current time relative to when we started, using it as the "official" timestamp
andrewm@0 63 // for the data source.
andrewm@0 64 insert(startingTimestamp_ + microseconds_to_timestamp(targetMicros), milliseconds_to_timestamp(Time::getMillisecondCounterHiRes() - startTime));
andrewm@0 65 targetMicros += intervalMicros_;
andrewm@0 66
andrewm@0 67 // Next millisecond time according to Juce timer
andrewm@0 68 nextTime = startTime + (double)targetMicros/1000.0;
andrewm@0 69
andrewm@0 70 // Sleep until we get to the next tick.
andrewm@0 71 // thread_.sleep(startTime + microseconds(target_micros));
andrewm@0 72 wait((int)(nextTime - Time::getMillisecondCounterHiRes()));
andrewm@0 73 }
andrewm@0 74 }