So-net無料ブログ作成

Raspberry Pi用pigpio Library - その9 [Raspberry Pi]

pigpioライブラリの概観(その1その2その3その4その5その6その7その8)の続き。あと残りはもうすこしだけ。今日はwaveformとpthread関連について。

2.12  Wave

pigpioライブラリを使うとデジタルの任意波形を任意のピンから出力できる。サイトではWave、あるいはwaveformと呼んでいる。waveformと言ってもアナログではなくデジタルなので、いろんな時間間隔のHigh - Low信号が作れるということになる。そのための設定はちょっとめんどくさい。

まずライブラリ内部にwaveformを作るための作業領域がある、と考える。そしてひとつのパルス(立ち上がり立ち下がりの位置)をちょっと変わった構造体
typedef struct
{
    uint32_t gpioOn;
    uint32_t gpioOff;
    uint32_t usDelay;
} gpioPulse_t;
で表現する。これはgpioOnでオンにするピンの位置にあたるビットを立てることで指定して、gpioOffで同様にオフにするピンを指定する。usDelayは次のパルスまでの時間をμsecで指定する。ピンの指定は0だとその指定が無視されるようになっている。

例えば
    gpioPulse_t pulse;
    pulse.gpioOn    = 0x00000003;
    pulse.gpioOff   = 0x0000000C;
    pulse.usDelay   = 200;
とすると、0番と1番のピンをオンにして、2番と3番のピンをオフにして、次のパルスまで200μsec待つ、という意味になる。

当然waveformを出力するためには
int gpioSetMode(unsigned gpio, unsigned mode);
で使うピンをPI_OUTPUT、つまり出力に設定しておかないといけないようである。

waveformを作るためにはまず
int gpioWaveClear(void);
で作業領域をクリアする。そして
int gpioWaveAddGeneric(unsigned numPulses, gpioPulse_t *pulses);
でパルスの配列を付け加える。そして
int gpioWaveCreate(void);
を呼ぶと作業領域にあるwaveformにwave_idというハンドルが与えられてその値が返ってくる。

そのあと、
int gpioWaveTxSend(unsigned wave_id, unsigned wave_mode);
を呼ぶとwave_idで指定されたwaveformが出力される。wave_modeには
#define PI_WAVE_MODE_ONE_SHOT      0
#define PI_WAVE_MODE_REPEAT        1
#define PI_WAVE_MODE_ONE_SHOT_SYNC 2
#define PI_WAVE_MODE_REPEAT_SYNC   3
の4通りが指定できる。名前で意味はわかると思うけど、SYNCのついた値はwaveformを出力し終わるまでgpioWaveTxSend関数はブロックする、ということだろう。ということはSYNCの付いていないモードは設定し終わったらすぐ返ってくるということだろう。ということはPI_WAVE_MODE_REPEAT_SYNCでは死ぬまで返ってこない、ということではないんだろうか。専用のスレッドを走らせて、止めるときは外からやれ、ということだろうか。それならSYNCなしと同じじゃないのか。

SYNCのないモードの場合は
int gpioWaveTxBusy(void);
で、終わったかどうか判断して、
int gpioWaveTxStop(void);
で強制的に止めることもできる。

全部終わったら
int gpioWaveDelete(unsigned wave_id);
でwaveformを破棄する、という手順である。

基本は以上だけど、ユーティリティ関数として
int gpioWaveTxAt(void);		//どのidのwaveformが出力中か
int gpioWaveGetMicros(void);	//出力中のwaveformのmicro sec単位の長さ
int gpioWaveGetHighMicros(void);//ライブラリを初期化してから一番長かったwaveform
int gpioWaveGetMaxMicros(void);	//可能な長さの最大
int gpioWaveGetPulses(void);	//出力中のパルスの長さ
int gpioWaveGetHighPulses(void);
int gpioWaveGetMaxPulses(void);
などがある。

このwaveformを使ってたとえばUARTの出力をソフトウェアでエミュレートできる。bit bang serialには読む関数しか用意されていなかったのは、書く方はこれを使え、ということなのかと思っている。しかしこのままではめんどくさいので、そのためには任意のバイト列をwaveformの構造体に変換するようなラッパを作った方がいい。僕はとりあえず使う必要はないのでやらないけど。

2.13  その他の関数

2.13.1  pthread関係

スレッドを起動したり終了したり、が簡単にできる。
pthread_t *gpioStartThread(gpioThreadFunc_t f, void *userdata);
void gpioStopThread(pthread_t *pth);
これは単なるpthreadのラッパで、ライブラリ内部で使っているのをプログラマに解放しただけである。使い勝手はpthreadと全く同じで、キー入力削減の意味しかない。でも、Raspberry Pi 2や3では4コアを使い倒さないともったいないし、一つのコアそのものはパフォーマンスが低いので、いわゆるLチカ以上のことをしようとするとマルチスレッドは必要になる。普段からpthreadを使い倒してるプログラマにとってはちょっとした親切ではある。
nice!(0)  コメント(0)  トラックバック(0) 

nice! 0

コメント 0

コメントを書く

お名前:
URL:
コメント:
画像認証:
下の画像に表示されている文字を入力してください。

トラックバック 0

メッセージを送る