TimerTask.h |
---|
#ifndef TIMERTASK #define TIMERTASK #include "InterruptTask.h" /** * 単純なタイマーを基本として運用するタスク * タイマーが開始されたときにタスクが開始するように設計されている。 * handleTimeoutメソッドがタイムアウトが起こった * 時によばれる。 * タイマーは再開(restart)されることができ、あるいは * タスクは終了することができる。 * * 典型的な使用法はTaskManager用いた音発生である。 * これはタイマーが走っている間に他のタスクが実行できる。 * handleTimeoutメソッドは同様に定義される。 * デフォールトでinterruptメソッドを呼ぶことは * タイマーを止めます。 */ class TimerTask : public InterruptTask { public: const static int timeout = 1; TimerTask(){}; bool handleInterrupt ( int interruptValue ); virtual bool handleTimeout () ; bool timerRunning (); void execute (); void sleep ( int hi, int lo ); void sleep ( int timeMS ); void sleepSec ( int timeS ); }; #endif |
TimerTask.cpp |
---|
#include "TimerTask.h" /** * 単純なタイマーを基本として運用するタスク * タイマーが開始されたときにタスクが開始するように設計されている。 * handleTimeoutメソッドがタイムアウトが起こった * 時によばれる。 * タイマーは再開(restart)されることができ、あるいは * タスクは終了することができる。 * * 典型的な使用法はTaskManager用いた音発生である。 * これはタイマーが走っている間に他のタスクが実行できる。 * handleTimeoutメソッドは同様に定義される。 * デフォールトでinterruptメソッドを呼ぶことは * タイマーを止めます。 */ bool TimerTask::handleTimeout () { }; /** * 割り込みが起動されたときに呼ばれる * もしサブクラスがこの状態を処理するならば、再定義される。 * * 戻り:boolean false */ bool TimerTask::handleInterrupt ( int interruptValue ) { return false ; } /** * タイマーが走っているかどうかをチェックする。 * * 戻り:boolean true: タイマーが入っていれば */ bool TimerTask::timerRunning () { return state == checkTimer ; } /** * TaskManagerに呼ばれるタスク実行ルーチン */ void TimerTask::execute () { switch ( state ) { case interrupt: if ( handleInterrupt ( interruptValue )) resumeInterrupt () ; else nextState ( terminate ) ; break ; case timeout: if ( handleTimeout ()) break ; // タイムアウトが処理されたら続ける // でなければ、タスクをstop()するように下に落ちる default: stop () ; break ; } } /** * Start timer and call on timeout. * タイムアウト時にタイマーを開始し、handleTimeout()を呼ぶ。 * 入力:int hi タイムアウト値、詳しくはTimer.timeout(hi,lo)を見よ * 入力:int lo タイムアウト値 */ void TimerTask::sleep ( int hi, int lo ) { Task::sleep ( timeout, hi, lo ) ; resume () ; } /** * タイムアウト時にタイマーを開始し、handleTimeout()を呼ぶ。 * * 入力:int timeMS: ミリ秒単位のタイムアウト値 */ void TimerTask::sleep ( int timeMS ) { // スーパークラスを用いる Task::sleep ( timeout, timeMS ) ; resume () ; } /** * タイムアウト時にタイマーを開始し、handleTimeout()を呼ぶ。 * * 入力:int timeS: 秒単位のタイムアウト値 */ void TimerTask::sleepSec ( int timeS ) { Task::sleepSec ( timeout, timeS ); resume () ; } |
TaskToneGenerator.h |
---|
#ifndef TASKGENERATOR #define TASKGENERATOR #include "TimerTask.h" #include "mbed.h" /** * TaskManagerを用いた音発生器 * * TaskTimerサポートを用いて指定された期間音を発生させる。 * Soundがしていたようにwaitは用いていない。 */ class TaskToneGenerator : public TimerTask { protected: PwmOut* pwm ; PinName pin ; int* tones ; int tonesLength; int tonesIndex ; bool pwmRunning; int halfCycleTime; /** * 出力周波数を設定する * * 入力:int frequency 1ヘルツ単位の周波数 */ void setFrequency ( unsigned int frequency ); void update(int high, int low); void playToneNow ( int frequency, int time ); void pwmstart(); void pwmstop(); /* 内部ルーチン */ void startNextTone (); public: static int endTone; // 終了時の状態 static int noMoreTones; /** * 音発生出力を設定する * * 入力: int pin: p21のように出力ピンを設定する */ TaskToneGenerator ( PinName pin ); /** * タスク名を得る * * 戻り:String タスク名 */ char* name (); /** * 固定時間だけ音を発生する * * 入力:int frequency 1ヘルツ単位の周波数 * 入力:int time ミリ秒単位の持続時間 */ void playTone (int frequency, int time); /** * 音の組を発生する。配列は偶数個の要素が含まれる。 * 要素の始めの値は周波数 * 二番目は持続時間 * 配列に少なくとも二つないと何もしない。 * * 入力:int[] tones: 音の配列(frequency, duration)の対 */ void playTones ( int tones[], int n); /** * 音が出ていれば音の発生を切る */ void stopTone (); /** * 音が出ていれば音の発生を切る。TimerTaskからの override * * 入力:int interruptValue: 無視される * * 戻り:タスクが停止したときfalse */ bool handleInterrupt ( int interruptValue ); /** * TaskManagerで呼ばれるタスク実行ルーチン * * 戻り:boolean: 終了したときfalse、残りがあるときtrue */ bool handleTimeout (); bool running(); }; #endif |
TaskToneGenerator.cpp |
---|
#include "TaskToneGenerator.h" #include "mbed.h" /** * TaskManagerを用いた音発生器 * * TaskTimerサポートを用いて指定された期間音を発生させる。 */ /** * 出力周波数を設定する * * 入力:int frequency 1ヘルツ単位の周波数 */ void TaskToneGenerator::setFrequency ( unsigned int frequency ) { if ( frequency < 1 ) frequency = 1 ; halfCycleTime = (unsigned int)50000 / frequency ; // 要修正 update ( halfCycleTime, halfCycleTime ) ; } void TaskToneGenerator::update(int high, int low) { pwm->period_us( high+low) ; pwm->pulsewidth_us(high); } /* Internal routine */ void TaskToneGenerator::playToneNow ( int frequency, int time ) { // PWMを設定する setFrequency ( frequency ) ; // PWMとタスクがすでに入っているかどうかチェックする if ( ! pwmRunning ) { pwmRunning = true ; // mbedではできない // pwm->start () ; // PWMを開始する pwmstart(); } /* 指定した時間Sleepする * 後でtimerRunningのstatusを設定するからtimerRunning * のチェックをした後に実行しなければならない */ TimerTask::sleep(time) ; // } void TaskToneGenerator::pwmstart() { update(halfCycleTime,halfCycleTime); } void TaskToneGenerator::pwmstop() { update(0,halfCycleTime); } /* 内部ルーチン */ void TaskToneGenerator::startNextTone () { // tonesIndexはいつも正しい対を参照する playToneNow ( tones[tonesIndex], tones[tonesIndex+1] ) ; tonesIndex += 2 ; // リストの中の最後の音かどうかtonesIndexを調整する if (( tonesIndex + 2 ) > tonesLength ) { tonesIndex = noMoreTones ; } } TaskToneGenerator::TaskToneGenerator ( PinName pin ) { pwmRunning = false ; this->pin = pin ; pwm = new PwmOut ( pin ) ; } /** * タスク名を得る * * 戻り:String タスク名 */ char* name () { return "TaskToneGenerator" ; } /** * 固定時間だけ音を発生する * * 入力:int frequency 1ヘルツ単位の周波数 * 入力:int time ミリ秒単位の持続時間 */ void TaskToneGenerator::playTone (int frequency, int time) { tonesIndex = noMoreTones ; playToneNow ( frequency, time ) ; } /** * 音の組を発生する。配列は偶数個の要素が含まれる。 * 要素の始めの値は周波数 * 二番目は持続時間 * 配列に少なくとも二つないと何もしない。 * * 入力:int[] tones: 音の配列(frequency, duration)の対 */ void TaskToneGenerator::playTones ( int tones[], int n) { tonesLength = n; if ( tonesLength >= 2 ) { this->tones = tones ; tonesIndex = 0 ; startNextTone () ; } } /** * 音が出ていれば音の発生を切る */ void TaskToneGenerator::stopTone () { Interrupt ( 0 ) ; } /** * 音が出ていれば音の発生を切る。TimerTaskからの override * * 入力:int interruptValue: 無視される * * 戻り:タスクが停止したときfalse */ bool TaskToneGenerator::handleInterrupt ( int interruptValue ) { if ( pwmRunning ) { tonesIndex = noMoreTones ; //次のタイムアウトでdisableにする handleTimeout () ; //タイムアウトさせる } return false ; } /** * TaskManagerで呼ばれるタスク実行ルーチン * * 戻り:boolean: 終了したときfalse、残りがあるときtrue */ bool TaskToneGenerator::handleTimeout () { if ( tonesIndex == noMoreTones ) { // 残りの音がないときPWMを切る pwmRunning = false ; pwmstop(); // 音を切る return false ; // タスクを停止 } else { // Get next tone startNextTone () ; // タイマーと次の音を開始 return true ; // タスクを続ける } } /** * */ bool TaskToneGenerator::running() { if( pwmRunning ) return true; return false; } int TaskToneGenerator::endTone=1; // 終了時の状態 int TaskToneGenerator::noMoreTones=-1; |
MultitaskingTest3.h |
---|
#include "Task.h" #include "TaskToneGenerator.h" #include "common.h" class MultitaskingTest3 : public InterruptTask { static const int waitForToneDone = 1 ; static const int waitForTonesDone = 2 ; public: // 音リストは周波数と持続時間(msec)の対の組である static int toneList [];// = { 120, 50, 240, 50, 360, 50 } ; TaskToneGenerator* toneGenerator; MultitaskingTest3(); protected: void execute (); }; |
MultitaskingTest3.cpp |
---|
#include "MultitaskingTest3.h" MultitaskingTest3::MultitaskingTest3() { toneGenerator = new TaskToneGenerator ( p21 ) ; // state = 0; } void MultitaskingTest3::execute () { switch ( state ) { case initialState: pc.printf ( "Initial state\n" ) ; toneGenerator->playTone ( 200, 1000 ) ; nextState ( waitForToneDone ) ; break ; case waitForToneDone: if ( toneGenerator->running ()) { pc.printf ( "Waiting for tone to end\n" ) ; } else { toneGenerator->playTones ( toneList, 16 ) ; nextState ( waitForTonesDone ) ; } break ; case waitForTonesDone: if ( toneGenerator->running ()) { pc.printf ( "Waiting for tone list to end\n" ) ; } else { stop () ; } break ; default: // 異常な状態を捕獲し停止するためにdefaultにする stop () ; break; } } //int MultitaskingTest3::toneList [] = { 120, 3000, 240, 3000, 360, 5000 } ; // 1200Hz,3秒,2400Hz,3秒,3.6kHz,5秒 int MultitaskingTest3::toneList [] = { 26, 500, 29, 500, 33, 500,35,500,39,500,44,500,49,500,52,500 } ; // 音階 |
main.cpp |
---|
#include "mbed.h" #include "MultitaskingTest3.h" Serial pc(USBTX, USBRX); // tx, rx int main() { pc.baud(115200); MultitaskingTest3 Mt3; Task::TaskManager () ; pc.printf( "All done\n" ) ; } |