« 2020年5月 | メイン | 2020年7月 »

2020年6月13日 (土)

dsPICでSSBトランシーバー(SSBミキサー)

カテゴリ<SDR>

dsPIC33FJにて、AD変換、デジタルLPF、DA変換の基本動作が出来るようになりましたので、このデジタルLPFを音声源信号のBPFに変え、その後ろにサブキャリアによるミキサーを追加する事にします。

サブキャリアの周波数は自由に決められる訳ではなく、ADCのサンプリング周波数に依存します。 サブキャリアの最高周波数は、サンプリング周波数の1/4で、これより1/2づつ低い周波数、1/8とか、1/16の周波数になります。

今回のADCのサンプリング周波数は39.0625KHzですから、サブキャリアは、その1/4の9.765625KHzとなります。 サブキャリアとしては、10KHzとか12KHzのようなキリの良い周波数にしたくても、dsPICのクロック条件などにより、このような半端な周波数になってしまいます。 しかし、今では、Hz単位で任意の周波数を発振させられるDDSがありますので、中途半端なサブキャリアでも、高周波IFに変換する際、キリの良い周波数に変換できますから、支障は生じません。

まず、ミキサーの前に、SSB信号として必要な音声帯域のフィルターを用意します。 今回は61TAPの200-2800HzのBPFを用意しました。

Bpf2002800

上は、ホワイトノイズを入力した時の、BPFの様子です。低域のキレが良くありませんが、最終的に、SSB信号を取り出せるようになったら、TAP数や遮断周波数をトリミングしてみるつもりです。

この後に、ミキサーを繋ぎますが、まず、サブキャリアの信号を作らねばなりません。 サブキャリアはADCのサンプリング周波数の1/4としますので、Timer3のタイミングでADCが出力するたびに、1/4サイクル分のサイン信号をADC出力に掛け算してやれば良い訳です。

一番簡単な4分割のサイン信号は{sin0度、sin90度、 sin180度、sin270度}で、これを順番に掛け算する事になります。 この数値を実数で表すと{0, 1, 0, -1}であり、HEXで表すと{0x0000, 0x7FFF、0x0000, 0x8000}となります。 この4つのデータをリング状にして、ADCがデータ出力する都度、順番に掛け算をさせる為に、リングメモリーが必要になります。 dsPIC33Fの中には、リングメモリーを2つ作る事ができますが、これは、ミキサーの前のBPFと、ミキサー後にUSBもしくはLSBを切り取るBPFで使いますので、ミキサーでは使えません。 そこで、このリングメモリはアセンブラで直接作っています。

1khz_mixing_2

1khz_mixing_wave

上のスペクトルは、1KHzの音声信号とサブキャリアをミキシングした時の、ものです。 本来はサブキャリのレベルはゼロにならなければなりませんが、ADCに直流成分が含まれており、これが為に、キャリア漏れの現象が生じているものです。 ADC入力に与える直流バイアスを調整する、多回転可変抵抗で、これをキャンセルするポイントを見つける事はできますが、かなりクリチカルです。 デジタル処理だから、調整箇所は無いと思っていましたが、これは誤算でした。 DSB信号から一方のサイドバンドだけを切り取るとき、サブキャリアは、問題ないレベルまで減少することを期待する事にします。

左上の波形は、上が、ADCの入力である1KHzです。下はサブキャリアで変調されたDSB信号です。

10khz_mixing

上のスペクトルは、ホワイトノイズを変調した時のDSB信号です。 ミキサーの前にある61TAPのBPF(ファイル名はLPFですが、実体はBPFです)の特性が、サブキャリアを中心に両サイドに広がっています。

ここまでのソフトは以下です。

SSB_generator_1.cをダウンロード

float_Tap2800LPF.hをダウンロード

FIRフィルターのDSPアセンブラの意味を以下に示します。

//FIR LPF処理
asm("mov _repeat3k_Num,W11"); //リピート回数をW11にセット
asm("mov _Tap_coef3k_adr,W10");//TAP係数格納の先頭番地をW10に格納
asm("mov W0,[W8++]");//W0のデータをW8が示すアドレスにコピーした後W8を+2する。

asm("clr A, [W8]+=2,W4,[W10]+=2,W5");//アキュムレーターAをクリアし、
          //W8が示すアドレスのデータをW4にコピー後、W8を+2する。
          //W10が示すアドレスのデータをW5にコピー後、W10を+2する。
asm("repeat W11");//次の行をW11の回数分繰り返す。
asm("mac W4 * W5, A, [W8]+=2, W4,[W10]+=2,W5");//W4とW5 を掛け算し、結果をアキュムレータ―Aに加算
           //W8が示すアドレスのデータをW4にコピー後、W8を+2する。
           //W10が示すアドレスのデータをW5にコピー後、W10を+2する。
asm("mac W4 * W5,A");//W4とW5 を掛け算し、結果をアキュムレータ―Aに加算
asm("sac A,W0");//アキュムレーターAのデータをまるめ処理してW0にコピー

asm("mov W0,W4");//W0のデータをW4にコピー

 

プログラム上は、このミキサーの後に、281 TAPのBPFを挿入し、新スプリアス対応可能なSSB信号を取り出します。 追加するBPFはPre BPFのTAP数とTAP係数が異なるだけで、そのプログラムの構成は同じですから、Pre BPFの部分をコピペして、必要な修正を行うだけで、楽勝と思っていましたが、落とし穴にはまり、一日棒に振った後、なんとか解決して出てきた出力のスペクトルは以下です。

10khlsbspectra1

約9.8KHzのキャリア周波数を持つ、LSB信号のみを取り出し成功です。 後は、Pre BPFとPost BPFの設定値を見直し、送信に耐える特性にした後、不動在庫の24MHzクリスタルを使い、クリスタルフィルターを作り、24MHzの中間周波数を作ります。

ここで、今回遭遇した落とし穴を紹介して置きます。  結論は、リングメモリーを制御するワーキングレジスタを指定した後は、そのレジスタを、他の用途に使ってはいけないという事でした。 今回、Xメモリー域とYメモリー域に、各1組、合計2組のリングメモリーを設定し、Xリングメモリーのコントロール用にW8を指定しました。 この時、Yメモリー域に配置した、TAP係数の読み出しの為にW10を使いました。 ここまでは良かったのですが、 Yメモリー域に配置したリングメモリーのコントロール用にW10を指定したら、Post BPFが動かなくなってしまいました。 結局、YリングメモリーのコントロールレジスタはW11とし、かつ、Xメモリーに配置したTAP係数の読み出しはW9を当てる事で解決しました。 (参考:W8,9はXメモリーのアドレス用、W10,11はYメモリーのアドレス用として設定されている)

今やろうとしている、この方法は、昔、リング変調器と455KHzのメカニカルフィルターでSSB信号を取り出していた時の構成を、最新のデジタル技術で出来るようにしたもので、この基本形は1999年くらいから提唱されていたようです。 「おじさん工房」が提案した、第4の方法のSSBジェネレーターの考え方も、これと同じですが、IFに変換した時のもう一方のイメージを、ラフなクリスタルフィルターでカットするというアイデアが振るっています。 そこで、次はこのクリスタルフィルターの検討になります。

LSB信号を取り出すまでのソフトは以下です。

SSB_generator_2.cをダウンロード

float_Tap-151_2800BPF.hをダウンロード

float_Tap8000BPF.hをダウンロード

このプログラムで、DSP処理にかかるFcYは463サイクルでした。 ただし、このインラインアセンブラの前後で、Cによる割り込み処理と、復帰処理がありますので、実際はこのサイクルより多くなっているはずです。 許容可能な最大サイクルは1024ですが、どのくらい余裕が有るかわ判りません。 従い、PREとPOSTのFIRフィルターのTAP数は合計で500くらいを目途に進める事にします。

 

中間周波数は25MHz付近とする事は決まっていますが、あいにく、25MHzのXtalが有りません。そこで、手持ちのXtalを使って、特性を取ってみる事にしました。

下は、特性測定用に用意したテスト回路図と、テスト治具です。

Xtal_filter_schema

Xtal_filter_testjig

そして、手動でSSGをスイープさせ、それをスペアナでMAX Holdした時のデータが以下の4枚です。 左上から順番に、16MHz, 20MHz,  24MHz  26MHzのデータとなります。

_re16mhz

_re20mhz

_re24mhz

_re26mhz

Act_re_24mhz

4つの周波数で一番適した特性は24MHzです。 そこで、このXtal Filterの特性に合致するように、第2局発(LO2)の周波数を決めたのが、左の画像です。

DSP内で作ったSSB信号のサブキャリアは9.766KHzでしたので、これを中心にして、LSB またはUSBの信号がフィルターの先頭のフラット部分にくるように配置すると、LO2の周波数は、24006.766KHzとなります。 そして、LO2により生じたイメージ信号は、グラフ右側の特性がディップした帯域にはまります。

この特性から、DSPは、LSB及びUSBを選択的に出力して、第1可変局発(LO1)とIFキャリア周波数23997KHzをMIXし、7MHz帯でLSBもしくはUSBのSSB信号を作り出す事ができます。

従い、DSPの機能は以下のブロックのような動作が実現できれば良いのですが、これが、トラブルの連続で、まだ実現出来ていません。 なんとか目途がついたら、紹介します。

Dsp_block

約1週間、格闘した結果、なんとか使えるSSBジェネレーターが出来ました。

PRE BPFもPOST BPFも251TAPとして、送信/受信の切り替え時、同じリングメモリーが使えるようにしました。 この状態で、USB信号を取り出した時のスペクトルは以下です。

Usbnoise251tapx2

Lsbout_tx

Usbout_tx

左上は、送信モードで1KHz変調のLSBを、右上は同じく1KHz変調のUSBを取り出した時のスペクトルです。

Lsbin_rx

Usbin_rx

左上は、サブキャリアに1KHzで変調されたLSBを復調した状態、右上は、同じくUSBを復調した状態です。

これまでで、一番、苦労したところは、送信/受信 および LSB/USBモードの切り替えでした。 切り替えSWを追加し、ソフトを弄り回しましたが、うまく動作しません。 結局、取った手段は、送信/受信とLSB/USBの初期設定をした上で、RESETをかけるという荒業で、なんとか使えるようになりました。 トランシーバーを構成するには、Si5351AのDDSを制御したり、周波数を表示したりするために、dsPICとは別に、メインのマイコンが必要です。 このメインマイコンからdsPICにRESETをかける事にします。  私の技量では、動作中のモード切替は不可と悟るまで1週間かかったというのが実態です。

モード切替以外にAGC電圧の取り出しを仕込みました。 出力されるDC信号は、高入力のとき、3Vが出力され、信号が次第に小さくなると、ゼロVに近づくというもので、DUALゲートのFETを使ったAGCアンプの制御電圧とは逆になります。 この電圧を利用して、Sメーター表示やAGC電圧を作るには、dsPIC側では荷が重すぎますので、これをPWMにてDA変換し、システムコントローラー側に送り、システムコントローラーは再度これをAD変換するという面倒な事を行いますが、Sメーターの振れ具合や、AGCのかかり具合を細かく調整するには、必要な処理になります。

また、システムコントローラーとなるPIC16F1938には、PWMの極性を反転する機能がありますので、処理が簡単です。ただし、以下の回路図にはまだ反映されていません。

以上の回路図 SSB_generator_3.pdfをダウンロード

ここまでのソフトです。

SSB_generator_3.cをダウンロード

float_Tap10kUSB_BPF.hをダウンロード

float_Tap10kLSB_BPF.hをダウンロード

float_Tap2800BPF.hをダウンロード

 

SSBジェネレーターが完成したので、今回のSSBトランシーバーの全体構想を練ってみました。 24MHzのクリスタルフィルターとその前後のミキサーはSDR-3を真似て、双方向回路にしてあります。 今後これをベースに少しづつ、開発を進めていく事にします。

Ssb_trx_dspic_1

 dsPICでSSBトランシーバー(制作開始)へ続く

INDEXに戻る

2020年6月 9日 (火)

ホワイトノイズ発生器

dsPICを使ったSSBジェネレーターを開発中ですが、そのなかで、デジタルフィルターも作成します。 このフィルターが完成した時の特性が、当初の狙い通りに出来ているか、確認を必要とします。 それに使えるホワイトノイズ発生器の制作です。

Whtnoise_generator 

ノイズ発生源はトランジスタのベース、エミッタ間に逆電圧をかけ、BE間がブレークダウンした時に発生する広帯域ノイズをICで40dBくらい増幅します。

Ng_pcb

上がその回路図で、左が、それを実際に組み立てた状態です。

48mm x 30mmくらいの基板に組みました。 一応100KHzくらいまではフラットであるように期待して、完成した後、勤務先のスペアナを借りて、休み時間に測定してみました。

左下が10Hzより2KHzまでをピークホールドでスキャンしたデータです。

右下は、同じくピークホールドで10Hzから100KHzまでスキャンしたデータです。 2KHz以上は、ほとんどフラットで、1KHzで-6dBくらいのレベルダウンがあります。 2KHz以下の周波数で下降しているのは、スペアナの入力の周波数特性が影響しているもので、下の方にある、低周波領域でのスペクトルは、60Hzくらいまで、ほぼフラットです。

Ng_pk2khz

Ng_pk100khz

このホワイトノイズを15TAP 3KHzのLPFを通し、Wave Spectraで表示させた時のPC画像が以下です。

3khz_lpf

Noise_off

上が、ノイズをONしたとき、下がノイズOFFのときです。 一応、3KHz付近を境に高域がカットされた傾きを示しています。 Wave Spectraにピークホールド機能があれば、きれいに見えるのでしょうが、高級スペアナのようにはいきませんね。

このホワイトノイズ発生器を実際に使っている例はこちらにあります。

しばらく重宝しておりましたが、PC上で動くWave Generatorの中にホワイトノイズとピンクノイズの発生手段があり、かつSSBの2-tone信号も出せる事から、この基板はジャンク箱行きとなりました。

INDEXに戻る

2020年6月 6日 (土)

dsPICでSSBトランシーバー(SSBジェネレーター)

カテゴリ<SDR> [DSP 自作 7MHz ]

HDSDRというフリーのSDRソフトを使った、SSBトランシーバーは完成しましたが、いざ完成すると、それはそれで、色々と不満も出てきます。  HDSDRの+/-48KHzのバンドスコープは、ワッチする場合、大変便利ですが、交信するにははなはだ、不便でなりませんでした。 とにかく了解度が悪く、交信相手に、こちらの信号は59で届いているのに、相手の信号は29から39でしかありません。 この同じ信号をTS-930で受信すると、59です。 この原因は、広帯域の受信バンドの為、S/Nが悪化していること、強レベルの隣接局によるAGCの為、ノイズフロアが常に上下している事などが考えられます。 HDSDRの機能の中に、ノイズリダクションやノイズブランカ―、オーディオ帯の周波数可変可能なBPFやノッチフィルターなど、了解度を改善する機能が満載されている理由が判るような気がします。 そして、これらの機能を駆使しても、通常の会話は了解出来ても、コールサインの確認に手間取る状態でした。

これを改善するには、多くのメーカー製トランシーバーが採用しているように、バンドスコープ用IFと復調用IFを完全に分離するしかないようです。 一方、バンドスコープ用IFと復調用IFを共用しながら、バンドスコーブの幅を必要最小限に狭めたSDRトランシーバー SDR-3 が、「おじさん工房」から商品化されております。 多分ここまで、狭めたら、受信能力の悪化は小さいと予想されますので、今度はこれを手本として、どこまで自作できるかトライする事にします。

Fir31tapgraf

このプロジェクトを開始するに当たり、そのノウハウをパクってきた元はJA1QVM OMのブログです。 これから、SDRの勉強をしようとインターネットを検索していましたら、探していた情報がそのまま出ていました。 OM Very TKS.

左のグラフは、OMの記事を真似て作った、31TAPのFIR LPFの実測データです。 ここまでできると、SSBジェネレーターに必要な300-500TAPのフィルターは簡単にできてしまうと考えましたが、300や500のTAP係数をどうやって入力するのかが最大の課題となりました。  また、メモリーの配置はリンカー任せにしないと、トラブルの連続でしたので、そこも解決しなければなりません。

Ssb_genarator_0_2

まずは、OMに習って、ハードの回路図からです。

 dsPICはdsPIC33Fj64GP802です。 これを始めた2020年6月の時点では、dsPIC33CHがメインとなっている状況ですが、この最新のdsPICに対する情報は少なく、ひと昔前の33Fで勉強し、最終的には33CHに乗せ換えるという魂胆です。 

後日、dsPIC33CHも使いましたが、SSBジェネレーター用としては使いにくく、このdsPIC33FJが最適なようです。

この回路図もOMのプログからのパクリですが、最初、VR1を固定抵抗で済ませていたところ、いざADCが動き出すと、片側からサチってしまうので、オリジナル通り、半固定抵抗に変えました。 しかし、後日、ミキサーを実装したところ、この半固定抵抗の合わせ次第で、サブキャリア漏れが大幅に悪化する事が判りました。 結局、この半固定抵抗は多回転タイプに変更し、かなりクリチカルな調整が必要なようです。  また、DACはL/R出力となっていますが、R-chはまだ配線されておりません。

dsPICでSDRを構築する、あるいは、その要素技術を公開するインターネットサイトは、沢山ある訳では無く、限られた情報を基に、自分で考えないとダメみたいです。 そして、その数少ないサイトのなかから、XC16によるプログラム例を探して、それを、今回の目的に合うようにアレンジしていくわけですが、コンパイルすると、エラーになったり、ものすごい数のワーニングが出たりします。 そこで、今まで読んだ事が無かった、XC16コンパイラのマニュアルを一通り読んでみました。 その中で、興味が沸いたのは、CCI という構文です。 これから、何年か、プログラムのコピペに耐えられようにしようとすると、従来の構文では、不都合が生じる可能性があり、後日、困るのは本人ですから、このSSBジェネレーターは、CCI 構文で進行する事にしました。 以前のXC16の構文を理解していない事が幸いし、以外と楽に乗り換えが出来ました。

まずは、CCI 準拠ですが、XC16-GCCの Option categorise:の中にあるPreprocessing and messagesを開き、その中にある、Use CCI syntaxにチェックマークを入れます。

Xc16_cci

次に、XC16(Global Options)を開き、Additonal options:の枠に -menable-fixed の文字を追加し、最後に下の方にある [Apply]を押します。 これはCCI とは関係ありませんが、 固定小数点形式の数値を使う為の処置です。  後日判明した事ですが、XC16(Global Options)ではなく、XC16-gccのOptionに記述するのが正しいようです。ただし、記事の中でも出てきますが、結局、固定小数点は使いませんでした。

Xc16_add_option

今回、構想するSSBトランシーバーの原型は、「おじさん工房」のSDR-3にあることに触れましたが、使おうとしているdsPICは、SDR-3を構成するハードやソフトにはとても及びませんので、せめて、SDR-3の構成は維持したまま、基本部分を慣れ親しんだPICで実現しようともくろみます。 従い、SSBの発生も「おじさん工房」が提案した第4の方法とします。 

まず、ADCやDACのサンプリングレートですが、ADCとDACのレートを一緒にし、余計な処理が生じないようにしようとすると、サンプリング周波数は、限られた周波数しか使用できません。

ADCのサンプリングレートはFcy=40MHzを80くらいから65535までの任意の整数で割った周波数に設定できます。 一方DACのクロックレートはfvco=160MHzから、1,2,4,8,16,32,64,128,256の8種類の数字のどれかで割り算した周波数(ACLK)をさらに256で割った周波数になります。 この条件から、DSP内部で作るミキサーのサブキャリア周波数を8KHz以上にしようとすると、ADCのクロックレートは40MHz/1024の39.0625KHzしか有りません。 これより低い周波数は、この1/2の19KHz台となり、ミキシングして得られたUSB信号がナイキスト周波数以上になってしまいます。 この39KHz台の場合、dspの処理時間は1024サイクル以下でなければならず、十分な特性のフィルターを作れない可能性がありますが、その限界が見えたら、さっさと、33CHに乗り換える事にします。

一方、DACも同じく39.0625KHzにするには、DACのクロック(ACLK)は39.0625 x 256=10MHzであれば良いので、Fvco(160MHz)を1/16に設定すれば良い事が判ります。

従い、Xtal OSCの周波数は、不動在庫している24MHzとして、これからPLL周波数の160MHzを作る事にしました。

SSB_generator_0.cをダウンロード

float_Tap.hをダウンロード

このCファイルは、後述のクロック条件の下で、ADCから入力された信号をFIRフィルター処理して、DACから出力するまでのプログラムです。 Hファイルは、TAP係数を羅列したファイルです。

実装されているTAP係数は15TAPのFIR LPF用ですが、この実装方法は後程、詳しく説明いたします。

dsPICはそのクロック周波数を高くする必要から、PLLを使いますが、この設定です。

Xtal=24MHzを1/3に分周し、8MHzにします。  この時の分周比 3がデータシートに出てくるN1となります。 そして、PLLPREの設定値は3-2=1です。

また8MHzを20倍して160MHzのPLL VCO周波数をつくりますが、20がデータシートのMとなります。 そして、PLLDIVの設定値は20-2=18です。

160MHzを2分周して80MHzのfoscを作りますが、このときの分周比 2がN2となります。 そして、PLLPOSTの設定値は2-2=0です。

foscが80MHzとなると、PIC内のシステムクロックはその1/2の40MHzとなり、これで、このdsPICは最高速度で動作する事になります。

DACのACLKはfvcoを1/16しますので、APSTSCLRの設定値は 3 になります。

dsp部分で積和演算を行うために、リングメモリが必要となりますが、その設定をX_MODset()という関数で作っています。 ここは、理屈抜きで、このように記述すればOKですが、ここで、TAP数により設定値を変える必要があります。 リングメモリーの先頭番地は、リンカーで決められますので、それをベースに計算する事にしています。従い、プログラム上からは、判りません。

initmain()のなかで、各種初期設定をおこないますが、各設定の順序は、試行錯誤した結果です。 コメントのみ変更して再コンパイルしたら、動かないとか、訳の分からないトラブルを軽減(完全になくすではありません)出来ました。 また、CAST変換がうまくいかずに、時々動かないという問題を少なくするために、デイレーを何か所かに入れてあります。 うまく動かないときは、このディレーを長くしたり、場所を変えたり、時にはPICkit3を外してみたりして、現在の状態に落ち着いています。

後日判明した事ですが、プログラムが動かなかったり、単純な再コンパイルで動作不調になる原因の一つが、リングメモリーの制御用に指定したワーキングレジスタをリンカーが勝手に他の用途に使ってしまう事にあるようです。 リングメモリーを使う時は、リンカーが勝手にワーキングレジスタを使わないようにユーザーが設定しなければならないとコンパイラの説明書に書いてありました。 具体的な方法はこちらを参照して下さい。dsPIC33CHの記事ですがdsPIC33FJも同じです。

Timer3からの割り込みの中に、DSP処理が全部はいりますが、今回は、FIR LPFを動作させるだけのプログラムがインラインアセンブラで記述されています。 ここまでは、JA1QVM OMの記事の通りです。 ただ、絶対アドレスをリンカー任せにしていますので、その記述が異なります。

XC16内で定義した変数は、その先頭にアンダバーをつけると(XC16で定義した変数がabcの場合、_abcとする)、アセンブラでも同じ変数として認識してくれますので、この手法で、XC16で得た各変数の絶対アドレスをアセンブラの中に埋め込んで、絶対アドレスの問題は解決しました。

main()処理は、main()が回っているインジケーターとしてLEDの点滅だけです。 このLEDの点滅を割り込み処理の中にいれ、DSPの速度測定をしようとすると、ADCが動かなったり、ソフトが止まったりしますので、DSPの処理時間を調べる別の方法を考えねばなりません。

次に、このプログラムにFIR係数を実装する方法を説明します。

FIRフィルターの係数計算は、色々な方法がありますが、私はここで計算した値を使っています。

Fir_tap_make0_2

TAP数や、遮断周波数の係数を入力して、出てきた数値の後ろに[,]がつくようにチェックマークを入れておきます。 

まず、必要とする遮断周波数を正規化値として入れる必要があります。この正規化値は次のようにして求めます。

求めたい遮断周波数 / ADCのサンプリング周波数

求めたい遮断周波数が3000Hz、サンプリング周波数(ADCのクロック周波数)が39.0625KHzの場合、正規化値は3/39.0625=0.0768となります。 この係数の最大値は0.5です。

Fir_tap_make1 

これで計算した結果が上のPC画面ショットのごとく、左側に縦に羅列されますので、これをすべてコピーします。 そして、float_Tap.hというファイルの中にペーストしておきます。 また、最初の行に、TAP数(Tap_Num)を記入して置きます。

 

このようにすることで、後程、TAP数や遮断周波数を変えたTAP係数の作成が簡単に行えます。

ここに示した、プログラムファイルは、ADCのデータをとりあえず3KHzのLPFを通しただけのものです。 このプログラムを作成する上で、一番トラブったのは、CASTでした。  TAP係数はdouble形式で提供されますので、XC16の中の変数に代入するとき、floatに変換し、これを固定小数点形式に変換する必要があります。  XC16 で固定小数点は _Fract と明示する事になっていますが、いくらやってもうまくいきません。 結局、float形式を16bitのsigned intに変換する事で、DACの出力が出るようになりました。 後日、判った事ですが、極性付き整数は、極性付き固定小数点の一形式と同じで、かつこの逆も言えるという事でした。

今後、これにサブキャリアによるミキサーと、USBのみ取り出すBPFを仕込み、約10KHzのサブキャリアで変調したUSBジェネレーターを完成させることにしますが、どうやって実装するかは、全く白紙状態です。 いつになることやら!

下のスペクトルは1KHz信号を加え、DACの出力をWave Spectraで表示させたものです。

Spectra_with_15tap_lpf

dsPICでSSBトランシーバー(SSBミキサー)へ続く。

INDEXに戻る