| 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" ) ;
}
|