シーケンス全体の制御は容易でしたので、肝心かなめのモデム信号部分の生成です。モデム信号はV.23 1200bpsに準拠していますが、発信者番号情報を電話機に対して送信すれば良いだけであり、受信処理はありません。また変調方式はV.23 1200bpsの固定となっていますので、ネゴの手順も必要ありません。FSK(周波数変調)と言ってもデジタル信号の変調ですので、送信するデータの内容に応じて bit 0を2100Hz, bit 1を1300Hzの周波数で送出すれば良いだけということになります。
送信すべきデータの内容はNTTが公開している技術参考資料で説明されています。以下のフォーマットはその資料からの引用です。
![](https://blogimg.goo.ne.jp/user_image/48/4f/db5d2a4aa165802fc2a274f9f932aa3b.png)
60ms以上のマークビットに続いて、定められたフォーマットで発信者番号を送出してやる必要があります。この図ではビット送出順序も表現されており、情報データ部分の各オクテットは最下位のb1から送出することになっていますが、最後の2オクテット(16bit)のCRC部分については最上位ビットから送出することになっています。また、bpはパリティビットを示していますので、データ部分については偶数パリティを付けて、最下位ビットから送出してやる必要があります。
![](https://blogimg.goo.ne.jp/user_image/09/28/62d38129dba53de01010683dbc0bc4b2.png)
データ部分ならびにCRCの各オクテットは上図のようにスタートビットとストップビットをつける必要が有ります。つまりはUARTで送信するのと同じように送信せよということですね。UARTの出力を使って変調をかけることを意識しての設計になっているのでしょうか。しかし、今回はDACでの出力が必要ですので、ソフトウェアでデータビットに対応した周波数の相当のDACに出力すべきデータ列を生成してやります。
CRC部分についてはSTM32L476にCRC演算機能が備わっているので、これを使ってみることにしました。STM32CubeMXでの設定は次のとおり。生成多項式の係数を指定できるようになっています。X16の項はお約束の部分なので省略して指定するようです。
![](https://blogimg.goo.ne.jp/user_image/63/a9/02b720f50be618fdfe90bebc11965bac.png)
生成するモデム信号は1200bpsですので、24KHzでサンプリングした場合には1ビット分に相当するサンプル数は24000/1200 = 20サンプルとなります。スタート/ストップを含めると元データの1バイトの送出には10ビットが必要ですので、 200サンプル(400バイト)分のDAC出力信号に展開してやり出力すればいいことになります。マークビットの長さも、これに合わせて10ビットの倍数である80ビットを選択。これで66ms相当の信号となり、NTTの定める仕様(60ms以上)を満足することができます。
![](https://blogimg.goo.ne.jp/user_image/16/75/cc0e2acee385cc87ed2d2599abdacd06.jpg)
こうして生成した出力サンプルデータをDMAを使ってDACへ送信してやると、Ag1171sを介して電話機にモデム信号が出力されて、めでたく電話機に数字を表示することができました。
![](https://blogimg.goo.ne.jp/user_image/72/cb/4ef51a6d249ce867cd5a3718a7281854.png)
上図に実際のシーケンス全体の信号の様子を示します。試験プログラムでは、呼び出し信号に応答(オフフック)後にダイアルトーンを送出しています。モデム信号が送出される前にはオフフックしていますので、ナンバーディスプレイに対応していない電話機(あるいは設定でナンバーディスプレイ機能を無効に設定した電話機)を接続すれば、実際に流れるモデム信号を耳で聞くこともできます。
![](https://blogimg.goo.ne.jp/user_image/44/c1/a7fcc24ab698e566bc648c35aea15f53.png)
モデム信号部分を拡大してみました。左1/3くらいはマークビットの部分です。ビット1が連続しているので、1300Hzの波形が続いています。その後ろがDLEから始まる実際の信号部分の頭の部分です。頑張れば目視によるデコードもできるかも?
送信すべきデータの内容はNTTが公開している技術参考資料で説明されています。以下のフォーマットはその資料からの引用です。
![](https://blogimg.goo.ne.jp/user_image/48/4f/db5d2a4aa165802fc2a274f9f932aa3b.png)
60ms以上のマークビットに続いて、定められたフォーマットで発信者番号を送出してやる必要があります。この図ではビット送出順序も表現されており、情報データ部分の各オクテットは最下位のb1から送出することになっていますが、最後の2オクテット(16bit)のCRC部分については最上位ビットから送出することになっています。また、bpはパリティビットを示していますので、データ部分については偶数パリティを付けて、最下位ビットから送出してやる必要があります。
![](https://blogimg.goo.ne.jp/user_image/09/28/62d38129dba53de01010683dbc0bc4b2.png)
データ部分ならびにCRCの各オクテットは上図のようにスタートビットとストップビットをつける必要が有ります。つまりはUARTで送信するのと同じように送信せよということですね。UARTの出力を使って変調をかけることを意識しての設計になっているのでしょうか。しかし、今回はDACでの出力が必要ですので、ソフトウェアでデータビットに対応した周波数の相当のDACに出力すべきデータ列を生成してやります。
CRC部分についてはSTM32L476にCRC演算機能が備わっているので、これを使ってみることにしました。STM32CubeMXでの設定は次のとおり。生成多項式の係数を指定できるようになっています。X16の項はお約束の部分なので省略して指定するようです。
![](https://blogimg.goo.ne.jp/user_image/63/a9/02b720f50be618fdfe90bebc11965bac.png)
生成するモデム信号は1200bpsですので、24KHzでサンプリングした場合には1ビット分に相当するサンプル数は24000/1200 = 20サンプルとなります。スタート/ストップを含めると元データの1バイトの送出には10ビットが必要ですので、 200サンプル(400バイト)分のDAC出力信号に展開してやり出力すればいいことになります。マークビットの長さも、これに合わせて10ビットの倍数である80ビットを選択。これで66ms相当の信号となり、NTTの定める仕様(60ms以上)を満足することができます。
![](https://blogimg.goo.ne.jp/user_image/16/75/cc0e2acee385cc87ed2d2599abdacd06.jpg)
こうして生成した出力サンプルデータをDMAを使ってDACへ送信してやると、Ag1171sを介して電話機にモデム信号が出力されて、めでたく電話機に数字を表示することができました。
![](https://blogimg.goo.ne.jp/user_image/72/cb/4ef51a6d249ce867cd5a3718a7281854.png)
上図に実際のシーケンス全体の信号の様子を示します。試験プログラムでは、呼び出し信号に応答(オフフック)後にダイアルトーンを送出しています。モデム信号が送出される前にはオフフックしていますので、ナンバーディスプレイに対応していない電話機(あるいは設定でナンバーディスプレイ機能を無効に設定した電話機)を接続すれば、実際に流れるモデム信号を耳で聞くこともできます。
![](https://blogimg.goo.ne.jp/user_image/44/c1/a7fcc24ab698e566bc648c35aea15f53.png)
モデム信号部分を拡大してみました。左1/3くらいはマークビットの部分です。ビット1が連続しているので、1300Hzの波形が続いています。その後ろがDLEから始まる実際の信号部分の頭の部分です。頑張れば目視によるデコードもできるかも?
山の波形のみで区別しているのですが0と1の波形の中間が存在して明確に区別できません。何かフイルターをかける必要があるでしょうか?
サンプル数は48000Hzです。
ノイズ成分の乗り方によってはフィルタリングが必要かもしれませんね。
ep.com.pl/antoniak/
Minimodule CLIPという記事がAVRを使ってデコードしているようです。ポーランドの人なので、発信者番号の表現フォーマットは異なりますが、v.23のデコードの参考にはなるかと思われまs。
ネット上にはナンバーディスプレイの記事が殆ど無く困っていました、ここにたどり着いて貴重な情報を頂き本当に感謝しています。
ご提示のサイトもハードウエア中心のようですがSoftware based CLIP decoderを開くと図解によるFrame for byte value 00111010bが非常に参考になりました。
私の波形の見方が想像以上に間違っていたことに気づきました。
神対応に感謝します。
ちゃんとコードを読まないと詳細はわかりませんが、Softwareware basedの方がパルス間の時間を計測しているのに対して、Minimoduleの方はADCを使って電圧を測定しているようです。興味深いです。
今までの開発中の疑問がとけました。
まだ完成していませんがとりあえずお礼まで!!
私もハードウエアーは手がけたこともありましたが、最近はマイコンにしても手半田ができるICが激減して非常に残念です。
貴殿のご活躍を心よりお祈りいたします。