2020.01.18

Cosmo-K-の基板を修正

特電の製品でCosmo-Kというのがあります。

Kintex-7を中心にDDR3メモリ、USB3.0、GPIO、SATA、10Gbpsの光ファイバを何個か備えたボードです。

なぜか今月に入って注文がぽぽぽぽーんと入ってきたので、生基板の在庫が切れてしまいました。

そこで、新しく生基板から作ることにしたのですが、せっかくなので基板の改版を行うことにしました。

Cosmok1

 

直したいところは「VCCAUX_IOを2.0Vにする」ということと「SFPケージの穴を大きくする」ということの2つです。

 

Kintex-7にはVCCAUX_IOという謎の電源ピンがあります。VCCAUXは通常は1.8Vですが、VCCAUX_IOはI/Oの出力バッファに割り当てられている電源のようで、DDR3メモリを最高速度でアクセスするには2.0Vにする必要があります。

Cosmok2

現在の基板がこんな状態で、ほとんどあまりのピンがない状態です。

それでも何とかVCCAUX_IOの端子を切り分けて、コンデンサを内側に1個追加し、配線を引き出すことができました。

Cosmok3

次に、光ファイバのモジュールであるSFPを収めている箱「ケージ」のピンの穴が狭かったので、これを太くしました。

使用している部品は、Anphenolの10127103-101LFとTE Connectivityの2007198-1です。

これらの部品には、たくさんの卵型の突起が生えていて、この突起を基板にはんだ付けすることで固定します。


Cage1

データシートには穴の直径は1.05mmと書かれているのですが、絶対に1.05mmの穴には入りません。

Cage2

今まではラジオペンチでこの卵型の突起をつぶして細くして基板に差し込んでいたのですが、「このデータシート、ゼッタイ変だよな~」と思いつつ、穴を限界まで太くすることにしました。

これで完成です。

Cosmok4_20200119003901

今回の修正は主にこの2か所なのですが、いままでの基板とパターンやステンシル、レジストなどに予期せぬ相違が発生していないかを念入りにチェックしなければなりません。

ガーバのDIFFっていうのがあれば便利なのですが、そういうのはなさそうなのでGCPrevieを使って念入りに見比べて、ようやく出図です。軽微な修正のはずだったのに5時間くらいかかってしまいました。

来週の木曜日には生基板が出来上がってくる予定です。

| | コメント (0)

2020.01.07

内層クリアランス

ある基板が在庫が切れてしまったので、再生産することになりました。

以前はP〇.comで作っていたのですが、P社の内層クリアランスは0.5mm必要で、Viaが0.3mm径の場合のみ0.4mmでよいとのことでした。

製造基準書には丁寧に内層クリアランス径は1.1mmと書かれているので、下の図のようなイメージで間違っていないのでしょう。

Naisou_clear1

内層クリアランスというのはViaの端から何mm開けなければならないかということです。

そもそも、なぜこれが必要なのかというと、Viaを作るためのメッキ液が染み込むとかいう化学的な理由なのかもしれません。そのあたりは詳しくありません。

まぁいずれにせよ、1.0mmピッチという比較的端子幅の広いBGAに対しても1.1mmの内層クリアランス径となると、下の図のようにベタパターンの分離が起きてしまいます。

Beta_bundan

GNDは内挿のベタのプレーンを作って、ベタパターンで配線するのが普通ですが、内層クリアランスが大きいと分断されてしまうのです。

いままでは、島ができてしまった部分には、自分ではんだ面や他の内層ら接続したりしていたのですが、前回作っていた基板ではそれを忘れていてP社の人が気づいて向こうで修正してくれていました。

Naisou_clear3

今回の製造からは、日本の国産基板メーカーに変えることにしたのですが、製造会社に修正されたことをすっかりわすれていて、ガーバを出してから1分後に気が付き、あわてて基板キャンセルを行いました。

今回の基板メーカーに「内層クリアランスはどのくらいですか」と聞いてみたところ、0.15mmという回答でした。

つまり、図にするとこうなります。

Naisou_clear2

ホント大丈夫か?

ちょっと不安になってしまう。

特急コースなら6層基板が2日で仕上がってP社の5日コース(実働10日くらいのイメージ)より安いという。

マジ神!

内層クリアランスが少なくてもよいと言われても経験的に広く取ってきた身としてはやはり怖いので、基本的に1.1mm径のルールで作って、最小限のGND島の部分だけ狭くして通り道を作ることにします。

 

 

| | コメント (0)

2020.01.06

「Cosmo-Z」にユーザ回路を追加する方法(後編)

ZYNQ搭載高速ADCボード「Cosmo-Z」にユーザ回路を追加する方法の続きです。

フィルタの追加

FilterブロックにはADCで計測された生データが流れているので、ここに適当なフィルタを追加します。

適当なフィルタということでCICフィルタを選びました。

CICフィルタとは

CICフィルタというのは足し算とデシメーションだけでできている単純なローパスフィルタで、特性は急峻ではありませんが、構造は簡単です。

詳しいことは当ブログの過去記事

http://nahitafu.cocolog-nifty.com/nahitafu/2015/08/cosmo-z18bit-ec.html

の記事をご覧ください。

SLICEモジュールの改造

VivadoでIPコアとして使えるCICフィルタは、AXI Streamを前提としていて、生のデータは入れられないようです。

そこで、前回作ったSLICEモジュールを改造して、8chのデータが詰まった96bitのAXI Streamを、16bitのAXI Stream 8chに分解するようにしました。

元のADCデータは12bit×8chなのですが、これを12bitのAXI Stream 8本に分けたところ、VivadoがWarningを出してきました。

どうやら、AXI Streamはビット幅が8の倍数でないと正しく動作しないかもしれないそうなのです。

CICフィルタに入れるデータは2の補数表現であろうから、リニア→2の補数表現に変換しなければなりません。

せっかくなので、CH1をCH1,2,3,4にコピーして、CH2をCH5,6,7,8にコピーする機能もSliceモジュールに持たせましょう。


architecture Behavioral of cosmoz_data_slice is
ATTRIBUTE X_INTERFACE_INFO : STRING;
ATTRIBUTE X_INTERFACE_INFO of tdata_i : SIGNAL is "xilinx.com:interface:axis:1.0 DIN TDATA";
ATTRIBUTE X_INTERFACE_INFO of tvalid_i : SIGNAL is "xilinx.com:interface:axis:1.0 DIN TVALID";
ATTRIBUTE X_INTERFACE_INFO of tdata0_o : SIGNAL is "xilinx.com:interface:axis:1.0 DOUT0 TDATA";
ATTRIBUTE X_INTERFACE_INFO of tvalid0_o : SIGNAL is "xilinx.com:interface:axis:1.0 DOUT0 TVALID";
ATTRIBUTE X_INTERFACE_INFO of tdata1_o : SIGNAL is "xilinx.com:interface:axis:1.0 DOUT1 TDATA";
ATTRIBUTE X_INTERFACE_INFO of tvalid1_o : SIGNAL is "xilinx.com:interface:axis:1.0 DOUT1 TVALID";
ATTRIBUTE X_INTERFACE_INFO of tdata2_o : SIGNAL is "xilinx.com:interface:axis:1.0 DOUT2 TDATA";
ATTRIBUTE X_INTERFACE_INFO of tvalid2_o : SIGNAL is "xilinx.com:interface:axis:1.0 DOUT2 TVALID";
ATTRIBUTE X_INTERFACE_INFO of tdata3_o : SIGNAL is "xilinx.com:interface:axis:1.0 DOUT3 TDATA";
ATTRIBUTE X_INTERFACE_INFO of tvalid3_o : SIGNAL is "xilinx.com:interface:axis:1.0 DOUT3 TVALID";
ATTRIBUTE X_INTERFACE_INFO of tdata4_o : SIGNAL is "xilinx.com:interface:axis:1.0 DOUT4 TDATA";
ATTRIBUTE X_INTERFACE_INFO of tvalid4_o : SIGNAL is "xilinx.com:interface:axis:1.0 DOUT4 TVALID";
ATTRIBUTE X_INTERFACE_INFO of tdata5_o : SIGNAL is "xilinx.com:interface:axis:1.0 DOUT5 TDATA";
ATTRIBUTE X_INTERFACE_INFO of tvalid5_o : SIGNAL is "xilinx.com:interface:axis:1.0 DOUT5 TVALID";
ATTRIBUTE X_INTERFACE_INFO of tdata6_o : SIGNAL is "xilinx.com:interface:axis:1.0 DOUT6 TDATA";
ATTRIBUTE X_INTERFACE_INFO of tvalid6_o : SIGNAL is "xilinx.com:interface:axis:1.0 DOUT6 TVALID";
ATTRIBUTE X_INTERFACE_INFO of tdata7_o : SIGNAL is "xilinx.com:interface:axis:1.0 DOUT7 TDATA";
ATTRIBUTE X_INTERFACE_INFO of tvalid7_o : SIGNAL is "xilinx.com:interface:axis:1.0 DOUT7 TVALID";
begin
tvalid0_o <= tvalid_i;
tvalid1_o <= tvalid_i;
tvalid2_o <= tvalid_i;
tvalid3_o <= tvalid_i;
tvalid4_o <= tvalid_i;
tvalid5_o <= tvalid_i;
tvalid6_o <= tvalid_i;
tvalid7_o <= tvalid_i;
tdata0_o <= (tdata_i(ADC_BITS * (0 + 1) - 1 downto ADC_BITS * 0) - x"800") & "0000";
tdata1_o <= (tdata_i(ADC_BITS * (0 + 1) - 1 downto ADC_BITS * 0) - x"800") & "0000";
tdata2_o <= (tdata_i(ADC_BITS * (0 + 1) - 1 downto ADC_BITS * 0) - x"800") & "0000";
tdata3_o <= (tdata_i(ADC_BITS * (0 + 1) - 1 downto ADC_BITS * 0) - x"800") & "0000";
tdata4_o <= (tdata_i(ADC_BITS * (1 + 1) - 1 downto ADC_BITS * 1) - x"800") & "0000";
tdata5_o <= (tdata_i(ADC_BITS * (1 + 1) - 1 downto ADC_BITS * 1) - x"800") & "0000";
tdata6_o <= (tdata_i(ADC_BITS * (1 + 1) - 1 downto ADC_BITS * 1) - x"800") & "0000";
tdata7_o <= (tdata_i(ADC_BITS * (1 + 1) - 1 downto ADC_BITS * 1) - x"800") & "0000";

こんなふうになりました。

Combineモジュールの改良

Combineモジュールでは逆にこれらのデータを束ねます。


  ATTRIBUTE X_INTERFACE_INFO : STRING;
ATTRIBUTE X_INTERFACE_INFO of tdata_o : SIGNAL is "xilinx.com:interface:axis:1.0 DOUT TDATA";
ATTRIBUTE X_INTERFACE_INFO of tvalid_o : SIGNAL is "xilinx.com:interface:axis:1.0 DOUT TVALID";
ATTRIBUTE X_INTERFACE_INFO of tdata0_i : SIGNAL is "xilinx.com:interface:axis:1.0 DIN0 TDATA";
ATTRIBUTE X_INTERFACE_INFO of tvalid0_i : SIGNAL is "xilinx.com:interface:axis:1.0 DIN0 TVALID";
ATTRIBUTE X_INTERFACE_INFO of tdata1_i : SIGNAL is "xilinx.com:interface:axis:1.0 DIN1 TDATA";
ATTRIBUTE X_INTERFACE_INFO of tvalid1_i : SIGNAL is "xilinx.com:interface:axis:1.0 DIN1 TVALID";
ATTRIBUTE X_INTERFACE_INFO of tdata2_i : SIGNAL is "xilinx.com:interface:axis:1.0 DIN2 TDATA";
ATTRIBUTE X_INTERFACE_INFO of tvalid2_i : SIGNAL is "xilinx.com:interface:axis:1.0 DIN2 TVALID";
ATTRIBUTE X_INTERFACE_INFO of tdata3_i : SIGNAL is "xilinx.com:interface:axis:1.0 DIN3 TDATA";
ATTRIBUTE X_INTERFACE_INFO of tvalid3_i : SIGNAL is "xilinx.com:interface:axis:1.0 DIN3 TVALID";
ATTRIBUTE X_INTERFACE_INFO of tdata4_i : SIGNAL is "xilinx.com:interface:axis:1.0 DIN4 TDATA";
ATTRIBUTE X_INTERFACE_INFO of tvalid4_i : SIGNAL is "xilinx.com:interface:axis:1.0 DIN4 TVALID";
ATTRIBUTE X_INTERFACE_INFO of tdata5_i : SIGNAL is "xilinx.com:interface:axis:1.0 DIN5 TDATA";
ATTRIBUTE X_INTERFACE_INFO of tvalid5_i : SIGNAL is "xilinx.com:interface:axis:1.0 DIN5 TVALID";
ATTRIBUTE X_INTERFACE_INFO of tdata6_i : SIGNAL is "xilinx.com:interface:axis:1.0 DIN6 TDATA";
ATTRIBUTE X_INTERFACE_INFO of tvalid6_i : SIGNAL is "xilinx.com:interface:axis:1.0 DIN6 TVALID";
ATTRIBUTE X_INTERFACE_INFO of tdata7_i : SIGNAL is "xilinx.com:interface:axis:1.0 DIN7 TDATA";
ATTRIBUTE X_INTERFACE_INFO of tvalid7_i : SIGNAL is "xilinx.com:interface:axis:1.0 DIN7 TVALID";
begin
tvalid_o <= tvalid0_i;
tdata_o(ADC_BITS * (0 + 1) - 1 downto ADC_BITS * 0) <= tdata0_i(15 downto 4) - x"800";
tdata_o(ADC_BITS * (1 + 1) - 1 downto ADC_BITS * 1) <= tdata1_i(15 downto 4) - x"800";
tdata_o(ADC_BITS * (2 + 1) - 1 downto ADC_BITS * 2) <= tdata2_i(15 downto 4) - x"800";
tdata_o(ADC_BITS * (3 + 1) - 1 downto ADC_BITS * 3) <= tdata3_i(15 downto 4) - x"800";
tdata_o(ADC_BITS * (4 + 1) - 1 downto ADC_BITS * 4) <= tdata4_i(15 downto 4) - x"800";
tdata_o(ADC_BITS * (5 + 1) - 1 downto ADC_BITS * 5) <= tdata5_i(15 downto 4) - x"800";
tdata_o(ADC_BITS * (6 + 1) - 1 downto ADC_BITS * 6) <= tdata6_i(15 downto 4) - x"800";
tdata_o(ADC_BITS * (7 + 1) - 1 downto ADC_BITS * 7) <= tdata7_i(15 downto 4) - x"800";

Block Designを配線する

SliceモジュールとCombineモジュールをRTLモジュールとして作り、間にCICフィルタを挟みます。

1_20200109041201

ADCに入ってくる信号はCH1(正弦波)とCH2(矩形波:トリガ信号)で、それを以下のような方針で8chに振り分けます。

  • ADC CH1→そのまま→CH1
  • ADC CH1→CICフィルタ(め)→CH2
  • ADC CH1→CICフィルタ(ふつう)→CH3
  • ADC CH1→CICフィルタ(きつめ)→CH4
  • ADC CH2→そのまま→CH5
  • ADC CH2→CICフィルタ(ゆるめ)→CH6
  • ADC CH2→CICフィルタ(ふつう)→CH7
  • ADC CH2→CICフィルタ(きつめ)→CH8

VivadoのIPのCICフィルタの設定は以下のとおりです。

ゆるめ フィルタ

2_20200109041201

ふつう フィルタ

3_20200109041301

きつめ フィルタ

4_20200109041301

入出力ビット幅

フィルタの設定がきつくなると力バスのビット幅も増えてきます。

同じ条件で評価したいので、いずれのフィルタも、入出力データは16bit幅でTruncationの設定にしています。

5_20200109041301

ちょっと失敗したこと

SliceとCombineをRTLモジュールにしたことが失敗でした。

なぜなら、RTLモジュールでAXI Streamを作ると、Varidateをしたときにバスの速度が自動的に推定されないようで、全部手作業で設定しなければいけないようでした。ポートをクリックして、Block Interface PropertyをつっついてCONFIGの中のFREQ_HZを全部設定しなおさなければなりません。

IPとして作れば、おそらく自動で設定されます。

RTLモジュールはIPコアと違い、ツールがラッパを作ってアトリビュートを設定することができないのでしょう。

論理合成して実行

これを論理合成して、計測を行ってみました。

結果は次の図の波形のとおり。

7_20200109041301

フィルタがきつくなるにつれ、遅延が増えていくのがわかります。

時間軸的に拡大してみると、フィルタを通したほうはすべてカクカクしています。

これはCICフィルタがデシメーションをしているためで、4回に1回しかデータを出力しないからです。

8_20200109041301

灰色の線(CH8)は矩形波の反射による鋭いヒゲを除去できているのでLPFとしての効果はありそうです。

CICフィルタの周波数特性とノイズ除去性能

LPFなので、どのくらいノイズが除去できるか気になるところです。

今回使っている正弦波の発振器は、安物なので、波形が歪んでいます。

9_20200109041301

そのため、FFTをすると結構な高調波が乗ってしまうのですが・・・

10_20200109041301

CICフィルタを通すと、

(ゆるめ)

11_20200109041301

(ふつう)

12_20200109041301

(きつめ)

13_20200109041301

全体的にノイズは減っているのでしょうが、CICフィルタ自体が緩すぎて、あまり効果は感じられません。

サンプリング周波数の1/8付近(10MHz付近)のノイズは落ちていますが、20MHz付近ではかえってノイズが増えているように見えます。

矩形波もフィルタした結果のFFT

トリガの矩形波もCICフィルタに掛けているので、そのFFTでスペクトラムを見てみます。

矩形波のスペクトラムはくし型になります。

14_20200109041301

まずは「ゆるめ」のフィルタ。fs/4の20MHzで急峻に切れています。

15_20200109041401

次は「ふつう」のフィルタ。10MHz付近の減衰が少しだけ大きくなっています。

16_20200109041401

最後は「きつめ」のフィルタ。

10MHzと30MHz付近で大きくカットできました。

17_20200109041401

元が幅が広がったスペクトラムのほうがフィルタの特性は把握しやすいですね。

きっと、10MHz、20MHz、30MHz、40MHzのすべての部分で急峻に切れているのでしょう。

まとめ

いかがでしたでしょうか。

Cosmo-ZのFilterブロックでAXI Streamをほどいて再結合させ、その間にリアルタイムな信号処理を追加することができました。

 

| | コメント (2)

2020.01.05

「Cosmo-Z」にユーザ回路を追加する方法(前編)

ZYNQ搭載の高速ADCボード「Cosmo-Z」(コスモゼット)は、FPGAをユーザがカスタマイズすることができる高速データ収集装置です。

Cosmo-Zをカスタマイズしてユーザ回路でデータを処理するやり方の例を紹介します。

1_20200109035401

ダウンロードとプロジェクトの生成

まずは「Cosmo-ZのFPGAソース公開とビルド方法」の記事を読み、ダウンロードとプロジェクトの生成を行ってください。

Vivadoのプロジェクトを起動すると、以下のようなBlockDesignが現れます。

2_20200109035401

Signal Processブロック

上の図で左下にあるSignalProcessをクリックして開きます。

SignalProcessは階層構造になっていて、様々なモジュールが中に入っています。

SignalProcessブロックでは、ADCBlock→Filter→UPP(汎用パルス処理)→TRIGGER→trigdelay(トリガディレイ)→captureという順に信号が流れていきます。

ユーザがカスタマイズできるのは、FilterとTRIGGERの2種類です。

Filterをカスタマイズすることで、

  • ADCで計測された信号をFPGAでリアルタイム処理するために取り出す
  • 独自のリアルタイム処理するフィルタを追加

することができます。

3

信号の規格

各ブロックを接続している信号はAXI Streamという標準的なバス規格ですが、バスのビット幅はADC_MAXCH × ADC_BITSでパラメタライズできるようになっています。

ADC_MAXCHはADCのチャネル数、ADC_BITSはADCのビット数で、デフォルトではADC_MAXCH=8、ADC_BITS=12となっています。

この値を変更するには、BlockDesignのトップにあるコメントを書き換え、

4

Tcl窓にNahiConfigByCommentと入力します。

5

Tclスクリプトが走り、プロジェクト内のすべてのモジュールのADC_BITSとMAX_ADCCHが一斉に書き換えられます。

それに伴い、AXI Streamのビット幅も自動的に調整されます。

Filterブロックをカスタマイズしよう

BlockDesignにあるFilterブロックを開けてみると、実は、中身は空っぽです。
6

このFilterは、BlockDesignの階層になっていて、ユーザが自分で回路を作りこむようになっています。

モジュールの追加

まず、FilterブロックをIPインテグレータで開いたら、 

7

VivadoのSourcesにある+ボタンをクリックし、

8

Add or Create Designを行います。

9

プロジェクトのsrcの中にあるdata_combine.vhdとdata_slice.vhdを追加します。

10

追加したら、BlockDesignの何もないところで右クリックし、Add moduleを行ってRTLソースを追加します。

11

 

以下のような2つのモジュールが追加されます。

12

SliceとCombine

SLICEはCosmo-Zの計測データが流れているAXI Streamを1つ1つのチャネルのデータに分解してくれるものです。

※XILINXのコアにも似たようなのはあるのですが、SLICEが12bit単位とか14bit単位とかできなさそうです。

Sliceの中身

Sliceモジュールの中身は


    tvalid_o   <= tvalid_i;
tdata0_o <= tdata_i(ADC_BITS * (0 + 1) - 1 downto ADC_BITS * 0);
tdata1_o <= tdata_i(ADC_BITS * (1 + 1) - 1 downto ADC_BITS * 1);
tdata2_o <= tdata_i(ADC_BITS * (2 + 1) - 1 downto ADC_BITS * 2);
tdata3_o <= tdata_i(ADC_BITS * (3 + 1) - 1 downto ADC_BITS * 3);
tdata4_o <= tdata_i(ADC_BITS * (4 + 1) - 1 downto ADC_BITS * 4);
tdata5_o <= tdata_i(ADC_BITS * (5 + 1) - 1 downto ADC_BITS * 5);
tdata6_o <= tdata_i(ADC_BITS * (6 + 1) - 1 downto ADC_BITS * 6);
tdata7_o <= tdata_i(ADC_BITS * (7 + 1) - 1 downto ADC_BITS * 7);

Combineモジュールの中身は


    tvalid_o   <= tvalid_i;
tdata_o(ADC_BITS * (0 + 1) - 1 downto ADC_BITS * 0) <= tdata0_i;
tdata_o(ADC_BITS * (1 + 1) - 1 downto ADC_BITS * 1) <= tdata1_i;
tdata_o(ADC_BITS * (2 + 1) - 1 downto ADC_BITS * 2) <= tdata2_i;
tdata_o(ADC_BITS * (3 + 1) - 1 downto ADC_BITS * 3) <= tdata3_i;
tdata_o(ADC_BITS * (4 + 1) - 1 downto ADC_BITS * 4) <= tdata4_i;
tdata_o(ADC_BITS * (5 + 1) - 1 downto ADC_BITS * 5) <= tdata5_i;
tdata_o(ADC_BITS * (6 + 1) - 1 downto ADC_BITS * 6) <= tdata6_i;
tdata_o(ADC_BITS * (7 + 1) - 1 downto ADC_BITS * 7) <= tdata7_i;

です。

本当に単純にばらしたりくっつけたりしているだけです。

デフォルトの直結で動作させた場合

まずは分解したデータをそのままつないで結合するデザインを作ります。

13  

いきなりですがこれを論理合成してFPGAに書き込んで動かしてみます。

論理合成の途中経過は省略します。

Cosmo-ZのCH1にはファンクションジェネレータから100kHzの正弦波を、CH2にはTTLレベルのトリガ信号を入れます。

CH3~CH8はオープンにしています。

14

Webオシロで見てみると、茶色の線(CH1)には正弦波が、赤色の線(CH2)には矩形波が映っています。

CH3~CH8には何も入力していないのでノイズが見えています。

15

CH3~CH8に、FPGA内部の配線をつなぐ

CH3~CH8はコネクタには何もつながっていないので、ノイズしか入ってきませんでした。

ノイズを見てもしようがないので、FPGAの中でCH1とCH2の信号をコピーしてつないでみましょう。

16  

結果は下の図のとおり。CH3,4,5にはCH1のコピーが、CH6,7,8にはCH2のコピーが入りました。

17

まとめ

Filterブロックの中から信号を取り出すことで、計測したままのデータをそのまま扱うことができるようになりました。

 

| | コメント (0)

2020.01.04

Trenz製品紹介サイトのよくある質問とその答えをまとめたった

特殊電子回路㈱が運営するTrenz製品販売サイトでは、購入前のボード選定に関するご質問や、購入後の使い方の質問をよくいただきます。

いつも調べてメールで返答しているのですが、そういったお問い合わせや無償サポートの内容をまとめて公開したら、今後、ご購入いただく方や今悩んでいる方たちのためになるかと思い、2年分くらいをまとめました。

こちらのページです。

https://www.trenz.jp/qanda/index.html

Qanda

納期や価格の問い合わせは省き、他の人にも有益となるようなお問い合わせだけをまとめました。

質問の内容や回答にお客様の秘密が含まれるような場合はその部分を削除し、一部加筆訂正しています。

今のところ、

という記事があります。

記事の全文は検索可能ですので、Trenz製品に興味を持ってみたらぜひとも読んで検索してみてください。

 

| | コメント (0)

2020.01.03

風水プログラミング

今日は趣向を変えて風水のプログラミングをしてみます。

オカルトな世界にもいろいろあるのですが、(玄空飛星)風水、九星気学、四柱推命は計算のアルゴリズムがしっかりと確立していて、入力が同じならば出力は同じになるという特徴を持っています。

例えば、(玄空飛星)風水ならば、竣工年と建物の向きが決まれば、結果は一意に定まります。

四柱推命ならば誕生の年月日と時間で結果は一意に決まります。

そのアルゴリズムは、ちゃんとした本を読めば書いてあります。(ドクター〇パとか李〇●竹とかを読んでも書いていません)

 

作ったプログラムの一部を示しましょう。

PHPで書いてあります。

$運星 = array(); // 
$運星["東南"] = 剰余($era + 8); //
$運星["南" ] = 剰余($era + 4); //
$運星["南西"] = 剰余($era + 6); //
$運星["東" ] = 剰余($era + 7); //
$運星["中央"] = 剰余($era + 0); //
$運星["西"] = 剰余($era + 2); //
$運星["北東"] = 剰余($era + 3); //
$運星["北"] = 剰余($era + 5); //
$運星["北西"] = 剰余($era + 1); //
switch($向) {
case "N1": case "N2": case "N3":
$中央水星 = $運星["北"];
$中央山星 = $運星["南"];
break;
case "NE1": case "NE2": case "NE3":
$中央水星 = $運星["北東"];
$中央山星 = $運星["南西"];
break;
case "E1": case "E2": case "E3":
$中央水星 = $運星["西"];
$中央山星 = $運星["東"];

とか、

	if($中央山星 == 5) {
if( (preg_match("/[23]/",$向) && !($era % 2)) // 偶数で区分2か3
|| (preg_match("/[1]/",$向) && ($era % 2))) { // 奇数で区分1
$山星順行 = true;
}
else {
$山星順行 = false;
}
}
if($中央水星 == 5) {
if( (preg_match("/[23]/",$向) && !($era % 2)) // 偶数で区分2か3
|| (preg_match("/[1]/",$向) && ($era % 2))) { // 奇数で区分1
$水星順行 = true;
}

なんだかとても怪しげなプログラムですね。

PHPは変数名に普通に漢字が使えるし、連想配列が使えるのでわかりやすく書けました。

もし、英数字しか使えないとどうやって英語に訳せばよいかわからなくて困るでしょう。

 

さて、これは何を計算するプログラムなのかというと、風水のチャートを作るプログラムなのです。

Chart

この数字がわかると、建物の部屋の吉方向や凶方向、場所の運勢や適した用途がわかります。

計算で求められるのはこの数字までで、その数字をどうやって解釈するかは風水師の経験にゆだねるところが多いのです。

このツールの良いところは、年飛星も表示できることと、北を上にして表示できること。

 

下の図は、卯山酉向(西向き)で第7運(1984~2003年)に建てられた物件のチャート。

7_w2_20200104223801

だいたいどの風水本も風水サイトも南が上で表示されているので、北が上にするというオプションも付けました。

北が上のほうがわかりやすいですよね。

| | コメント (0)

2020.01.02

Trenzサイトの本文を検索できるようにしました

Trenz製品販売日本語サイトの見えないところをリニューアルしました。

見えない部分だけど大事な仕事。

 

まず、今までTrenzサイトでは検索窓にカーソルを合わせることが困難でした。

どうやら2018年にスライダーを起動するJavascriptが追加された際に、スライダーの枠のdivが、実際の画像のサイズよりも大きいheightで定義されていて、その枠の見えない部分にバリアされて検索窓にカーソルが合わせられなかったようです。

そのため、スクロールする一瞬だけ検索ができるということになっていました。

この不具合を1年4か月くらい放置していました。いけないですね。

Search_blocked

 

せっかく検索ができるようになったので、本文を全文検索できるようにしました。

Trenz製品販売日本語サイトをはじめ、特電の作るWebページはtkcmsというCMS(コンテンツマネージメントシステム)で作られていますが、そのデータは以下のような感じでデータベースに入っています。(実際には1つのレコードには30個くらいの項目があるのですが簡単にしています。)

Contents_array

そして、過去のページ内容をいつでも復元できように、すべてのページのすべての時点のデータを全保存しています。

だから、元になるテーブルを全検索しては、すでに無効になっている記事や更新される前のデータもひっかかってしまいます。

 

このようなテーブルに対して全検索を行うには、まず、アクティブな記事のリストを作り(ここでSELECTを1回)、各記事のURLやタイトルをキーとして内容を取り出すためのSELECT文を記事の数だけforeachで回すことになります。

合計、ページ数+1回のSELECT文を回さなければならなくなり、重くなります。

 

そこで考えたのが、検索用のキャッシュテーブルを作ること。

全記事のデータの中から現在アクティブかつ最新のものを取り出し、HTMLのタグを外し、全角英数字を半角英数字に変換したテーブルを作ります。

Search_cache

そして、この検索用キャッシュテーブルに対して検索を行います。

全角半角で揺れても大丈夫になるし、1回のSELECT文で済むし、各ページの検索スコアを設定することもできるようになりました。

例えばZynqberryで検索したときの結果は以下のとおり。

Search_result

商品情報だけではなく、記事全文からテキスト検索できるようになりました。

 

| | コメント (0)

2020.01.01

あけましておめでとうございます

あけましておめでとうございます!

今年もよろしくお願いします。

 

今年の抱負は、「Facebookをがんばる」「レスポンシブデザインをがんばる」にしたいと思います。

かなえられない高い目標よりも、まずは現実的な目標を。。

 

さて、

HyperFDACとか、Cosmo-K DVIとか、JTAGチャレンジ基板とか、一昨年までにやっていて完成させていなかった製品を、やっぱり完成させたいですね。

 

それから、Web版MITOUJTAGの開発も再開したいと思っています。

Web版MITOUJTAGは、Webブラウザ経由でJTAGが使えるというクラウドアプリで、サーバ上でJTAGの複雑な処理をするというものなのですが、今までに2回作りました。

1回目は「MITOUJTAG Air」の名前で出したのですが、ソースコードがぐちゃぐちゃになって失敗。2回目はMITOUJTAGオンラインの名前で出して、ユーザ間のコミュニケーションができるようにしたもので、キャラクタが出てきてオンラインゲーム風でした。やはりソースコードがぐちゃぐちゃになったのと、ブラウザからUSB-JTAGにアクセスするためにActiveXを使っていたことで崩壊。

3度目を今年はやりたい。FPGAのデバッグではなく、CPUのデバッグにも広げたい。その方策は考えてある。

 

手を付けていて完成していなかったものをすべて片づけて、それから組み込みとかIoTとかFPGAではない、次の世界にいきたい。

それが今年の目標です。

| | コメント (0)

«2019年をふりかえって