マイコン工作実験日記

Microcontroller を用いての工作、実験記録

DTMFを検出する

2008-11-30 21:11:03 | SLIC
フッキング操作の検出と、ダイアルトーンの送出はできたので、次はいよいよダイアル番号の検出をせねばなりません。ダイアルされた番号は電話機の設定に応じてDTMF(トーン)信号またはパルス信号で送出されてきますので、このどちらか(あるいは両方)を検出してやる必要があります。先の記事で書いたように、今更パルス信号でもないので、おのずとDTMF信号を検出することになります。ところが、Si3215ではDTMF検出の機能はサポートされていません。Si3210やSi3216を使えば、DTMFの検出ができるのですが。。

そういうわけで、DTMFの検出はマイコン側でやってやらねばなりません。電話機が生成したDTMF音はu-LawにエンコードされたPCM信号としてAT91SAM7XのSSCで受信できるので、これを解析してDTMF検出することになります。Googleさんに助けを求めてARM用のコードを探すと、簡単にonARMにあるSTM32用のコードが見つかりました。ターゲットはSTM32用となっていますが、DTMF検出の部分は全てCで書いてあるのでAT91SAM7Xで使うことには何の問題も無さそうです。ただし、Keil/ARMの息がかかっているので、KeilのuVisionで使うことという条件付きになってしまっていました。

しかたなくもう少し探したところ、NXPのサイトでLPC2138を使った電話の自動応答装置のプロジェクトを見つけました。しっかりとした説明とソースも含まれており、かなり参考になる記事です。ちょっと調べてみたら、NXPの前身であるPhilipsが2005年に開催したARM Design Contestで最優秀賞をとったTAM-TAMという作品のようです。ENC28J60を使ってethernetをつなぎ、TCP/IPにはuIPを使うという定番がキッチリおさえられています。基板もきれいにこさえて、開発にはuVision/Keil使っているみたいなので、やはり玄人さんが趣味で作った作品という感じでしょうか。こちらのコードもすべてCで書いてあり、Goertzelのアルゴリズムに基づいてDTMFが使う8つの周波数成分毎のエネルギーを計算しています。Keilのコードもそうでしたが、整数演算で済むようにあらかじめ入力されるサンプルの値はオーバフローが発生しないようにレベルを調整しておく必要があります。このTAM-TAMの場合にはサンプルの値は-256~256の範囲にあることを想定しているようです。

SLICからのPCM信号はu-Lawになっているので、これを展開して-256~255の範囲におさままるようにテーブルで変換してからTAMA-TAMのDTMFprocess()関数を呼び出してやると、いとも簡単にDTMF検出できちゃいました。うーん、デジタル信号処理って素晴らしいですねぇ。実際のところ、変換しないでu-Lawのままで直接 DTMFprocess()関数を呼び出しても DTMF検出できてしまったのですが、誤検出する可能性が高くなるかもしれないので、一応変換してから処理することにしました。

以下、動作の様子です。
]]] MMnetSAM7X Console Monitor [[[
> slic init
ProSLIC detected.
1652ms
> dtmf start

"dtmf start"でDTMF検出を呼び出すPCM受信タスクを起動しています。
> Off-Hook.
DTMF: 0
DTMF: 1
DTMF: 2
DTMF: 3
DTMF: 4
DTMF: 5
DTMF: 6
DTMF: 7
DTMF: 8
DTMF: 9
DTMF: *
DTMF: 0
DTMF: #

受話器を取り上げて、ボタンを順番に押していくと、きれいに認識できています。
On-Hook.
Off-Hook.
DTMF: 0
DTMF: 1
DTMF: 2
DTMF: 3
DTMF: 4
DTMF: 5
DTMF: 6
DTMF: 7
DTMF: 8
DTMF: 9
DTMF: *
DTMF: 0
DTMF: #

> On-Hook.

いったんオンフックして、再度オフフック。今度は、リダイアル・ボタンを押してみました。さきぼどの順番で欠けることなくきれいに認識できています。思わず、ヤッター!と声が出てしまいました。DTMFの検出なんてコードの実装に時間かかるんじゃないかと心配していたのですが、あっけなくできちゃってビックリです。

最新の画像もっと見る

コメントを投稿

ブログ作成者から承認されるまでコメントは反映されません。