リード部品の整形治具 [3D_printer]
高機能なロムライタである TL866II Plus で旧式の UVEPROM の書込みを可能にするために作ったものが、我ながら便利だったので BOOTH で試験的に VppConverter としてを販売してみました。
今までは自分用の基板の製作だったので外観にはそれ程拘っていませんでしたが、他の人に提供する物を作るとなるとピンヘッダの切り口等も気になってきます(今回はヤスリ掛けしました)。表面実装部品やリード部品が混在している構成であり部品数もそれなりに多いので同じものを何個も半田付けする作業は結構大変でした。
抵抗等のリード部品はラジオペンチで整形していましたが、専用の治具があった方が作業効率が良いと感じました。サンハヤト製のリードベンダーを使用している人も多いのではないでしょうか?
3Dプリンタを使ってリードを整形する治具( Lead Adjuster と命名) を作ってみました。下図が今回設計した治具の CAD 画面をキャプチャしたものです。
設計は1個ですが、同じパーツを2個組み合わせて一つの治具になるようにしました。柄の部分の三角形の山と谷は横ずれ防止のためのものです。14 の数字の部分がリード幅が 14 mm で 0.5 mm 間隔でリード受け用のくぼみを付けました。 14 の数字の上の溝は幅が 1 mm 毎に少なくなっているリード受けに付けたマークです。
下の写真は3Dプリンタで出力した部品です。リード受けの部分は径が小さいので積層ピッチは 0.2 mm を推奨します。「ガスカートリッジ(OD缶)用スタビライザーの製作」の記事の後半で記載した手法を採用して回転部分の軸はフィラメントをそのまま使用するようにしました。
フィラメントの出っ張った部分はニッパーで切断し、使用しているうちに外れてくるようであれば片側を瞬間接着剤で固定します。
同じような写真に見えますが下の写真は外側の様子です。
この治具は片方だけ使用してもリードを整形できますが、より直角に整形するためにリードを上下から挟んで整形することもできるようにしてみました。
必要とする人はあまり居ないとは思いますが、下記のリンクから STL ファイルをダウンロードできます。商用利用以外であれば自由に使用可能とします。
Twitter に投稿した動画付きメッセージを貼っておきます。文章で説明するよりも動画の方が一目瞭然ですね。
今までは自分用の基板の製作だったので外観にはそれ程拘っていませんでしたが、他の人に提供する物を作るとなるとピンヘッダの切り口等も気になってきます(今回はヤスリ掛けしました)。表面実装部品やリード部品が混在している構成であり部品数もそれなりに多いので同じものを何個も半田付けする作業は結構大変でした。
抵抗等のリード部品はラジオペンチで整形していましたが、専用の治具があった方が作業効率が良いと感じました。サンハヤト製のリードベンダーを使用している人も多いのではないでしょうか?
3Dプリンタを使ってリードを整形する治具( Lead Adjuster と命名) を作ってみました。下図が今回設計した治具の CAD 画面をキャプチャしたものです。
CAD での LeadAdjuster 設計 |
|
設計は1個ですが、同じパーツを2個組み合わせて一つの治具になるようにしました。柄の部分の三角形の山と谷は横ずれ防止のためのものです。14 の数字の部分がリード幅が 14 mm で 0.5 mm 間隔でリード受け用のくぼみを付けました。 14 の数字の上の溝は幅が 1 mm 毎に少なくなっているリード受けに付けたマークです。
下の写真は3Dプリンタで出力した部品です。リード受けの部分は径が小さいので積層ピッチは 0.2 mm を推奨します。「ガスカートリッジ(OD缶)用スタビライザーの製作」の記事の後半で記載した手法を採用して回転部分の軸はフィラメントをそのまま使用するようにしました。
回転部へのフィラメント取付状況 |
|
フィラメントの出っ張った部分はニッパーで切断し、使用しているうちに外れてくるようであれば片側を瞬間接着剤で固定します。
完成した LeadAdjuster (内側) |
|
同じような写真に見えますが下の写真は外側の様子です。
完成した LeadAdjuster (外側) |
|
この治具は片方だけ使用してもリードを整形できますが、より直角に整形するためにリードを上下から挟んで整形することもできるようにしてみました。
完成した LeadAdjuster (曲げた状態) |
|
必要とする人はあまり居ないとは思いますが、下記のリンクから STL ファイルをダウンロードできます。商用利用以外であれば自由に使用可能とします。
Twitter に投稿した動画付きメッセージを貼っておきます。文章で説明するよりも動画の方が一目瞭然ですね。
BOOTHに出品したことでリードの整形治具の必要性を感じました
— skyriver (@wcinp) October 31, 2022
サンハヤト製のリードベンダーを使っている人も多いのではないでしょうか?
3Dプリンタで治具を作ってみました
カメラが邪魔であまりうまく整形できていませんが実際はもっときれいに成形できますhttps://t.co/yecAbkxeLQ#リードベンダー pic.twitter.com/dfexlGLrpu
テンパズル(make10)の解法プログラム [Puzzle]
自動車のナンバープレートを見ると4つの数字から四則演算で10にする遊びをついやってしまいます。この遊びはテンパズル(10パズル)若しくは make10 と呼ぶようで wikipadia にも載っています。
Twitter で下記のメッセージを見かけ面白そうなのでプログラムを作ってみました。
こういう探索系で目的は単純明快だけれどもどう実装するか色々考えさせられそうな問題は結構好きです ^^
このような処理の結果を欲しがる人はほとんど居ないと思いますが、上記のようなパターンの縮退(枝刈り)処理はそれほど時間が掛からないので長時間かかりそうな探索処理をする場合等に有効な概念ではないかと思います。
また、ソースコードが膨大に蓄積されたネットから使えそうなソースを探して動かすことよりも、このように自分で考えたロジックを組み立てて動かすことの方がプログラミングの醍醐味を(私は)感じます。
★追記 2022/10/21 {
バグ発見につき見直し中 ^^;;;;;
}
★変更 2022/10/24 {
RPNから展開した式を正規化する際に分数の表現に揺らぎがありました。このバグを修正し、下記の内容に反映しました。
}
結果から先に書くと作成したプログラムの処理が間違っていなければ上記のメッセージへの回答は1314 1170 通りで、このパターンを用いて 0000 から 9999 までの1万通り中で 10 にできるものを確認すると 8147 通り検出され上記の wikipedia の数値と一致します。
始めは括弧の配置パターンを考えてみたりしましたが括弧式と言えばスタックを使った逆ポーランド記法と言うことで下記の方針で処理してみました。
★追記 2022/10/25 {
テンパズルの回答を表示する簡単な CGI を作成してみました。順番を入れ替えない回答を表示します。縮退データを利用しているのでサーバに優しい処理になっていますw
}
★追記 2024/02/06 {
今回実施した手法では正規化する際にまだ未発見の揺らぎが残存した場合、縮退数は更に小さくなるので真の値は今回求めた縮退数以下と言えます。
一方で冒頭で紹介した Twitter メッセージの投稿者は全ての RPN 式に対して各変数を0~9にした場合の計算結果が等しい場合、同じグループに分類するという手法を使用したとのことです。この場合、変数が0~9の範囲外の時、同一グループでも計算結果が異なる可能性もあるので真の値はグルーピング数以上ということになります。
以上から、真の値は縮退数以下で、かつグルーピング数以上ということになり、結果として「縮退数=グルーピング数」だったので「今回求めた縮退数は真の値である」と言えます。
}
以上が今回実装した処理の概要になります。参考としてサイズは大きいですが縮退後の全パターンを貼っておきます。
Twitter で下記のメッセージを見かけ面白そうなのでプログラムを作ってみました。
make10がらみで、4変数の四則演算だけの式って本質的にいくつあるんだろうと思ってコードを書いて調べてみ。本質的にというのは例えばa/b/cとa/(b*c)を同一視するということ。間違ってなければ1170通りあるみたい。誰か正解を知らないかな? |
---|
こういう探索系で目的は単純明快だけれどもどう実装するか色々考えさせられそうな問題は結構好きです ^^
このような処理の結果を欲しがる人はほとんど居ないと思いますが、上記のようなパターンの縮退(枝刈り)処理はそれほど時間が掛からないので長時間かかりそうな探索処理をする場合等に有効な概念ではないかと思います。
また、ソースコードが膨大に蓄積されたネットから使えそうなソースを探して動かすことよりも、このように自分で考えたロジックを組み立てて動かすことの方がプログラミングの醍醐味を(私は)感じます。
★追記 2022/10/21 {
バグ発見につき見直し中 ^^;;;;;
}
★変更 2022/10/24 {
RPNから展開した式を正規化する際に分数の表現に揺らぎがありました。このバグを修正し、下記の内容に反映しました。
}
結果から先に書くと作成したプログラムの処理が間違っていなければ上記のメッセージへの回答は
始めは括弧の配置パターンを考えてみたりしましたが括弧式と言えばスタックを使った逆ポーランド記法と言うことで下記の方針で処理してみました。
- 逆ポーランド記法( RPN 式)での全パターンの抽出
4 つの数字(a,b,c,d)を使った四則演算(+,-,*,/)の式を網羅すればいいので数字の順列のそれぞれパターンに対して 3 つの演算子を注入していく処理をすればいいことになります。
数字の順列は単純な再起呼出しで作成できますし、それぞれの数字の順列パターンに対して先頭から数値または演算子(重複可)を並べていくように再帰呼出しすれば全パターンが作成できます。
数字を選択したらスタック数をインクリメントし、演算子を選択したらスタックをデクリメントします。演算子は全て二項演算なのでスタックに 2 個以上のデータがある場合に選択できるという条件を付けます。合計で7文字に達することがリターンの条件です。この条件で再帰呼出しすれば全てのパターン( 7680 通り)が得られます。
例:ad-c+b/
- RPN 式の括弧式変換
RPN 式を括弧に展開します。一般式と違い RPN 式は非常に扱い易いですね。
例:ad-c+b/ ⇒ ((a-d)+c)/b
- 括弧の展開
上記の括弧式をできるだけ括弧を使わない式に展開します。一般式と違い二項演算部は必ず括弧で囲まれているので両端の項の外部との結合を気にする必要がないので楽です。
下記の 3 パターンに場合分けして処理しました。w, x, y, z が変数 [a-d] で @ は演算子 [+-*/] です。式からカッコ内に括弧を含まない最も内側の純粋な括弧式を抽出して展開するという処理を除算の分母以外の括弧が無くなるまで繰り返しました。
- x @ ( y @ z )
- ( x @ y ) @ z
- ( w @ x ) @ ( y @ z )
例:((a-d)+c)/b ⇒ a/b-d/b+c/b
- 式の正規化(ソート)
冒頭に書いた Twitter のメッセージにあるように異なる数式でも本質的に同じ場合は一つにまとめるために多項式の場合は項の順番を一定の規則で並び替える必要があります。また項内に複数の変数がある場合にも項内の変数を並び替える必要があります。下記のように処理することで本質的に同一な計算式は同じ式に正規化されます。
- 項内ソート
乗算演算子を前方に置き、除算演算子は後方になるように並び替えた後、乗算群と除算群のそれぞれに対して変数の順番をソートしました。
- 項のソート
数式を '+','-' の二つの演算子で項に分離し、'-' の項を式の後方に配置し直した後、'+' 群と '-' 群のそれぞれに対して項をソートして並び替えました。
- 分数の変換 ★追記 2022/10/24
分母にマイナスの演算子を含み、分数全体がマイナス項であった場合、分母と分子に -1 を掛け、分数全体をプラスの項に変換しました。
また、分母の式に分数項があった場合、分数項の分母を分母と分子に掛け分母の式に分数が入らないようにしました。
- 項内ソート
- 正規化した式での縮退
全ての RPN 式について導出された正規化した式で同じものをグルーピングしてグループ数(=縮退数)を求めました。このグループ数が冒頭に書いた Twitter のメッセージへの回答となるはずです。
例:((a-d)+c)/b ⇒ a/b-d/b+c/b ⇒ a/b+c/b-d/b
(a-d)/(c-b) ⇒ a/(c-b)-d/(c-b) ⇒ a/(c-b)+d/(b-c)
★追記 2022/10/25 {
テンパズルの回答を表示する簡単な CGI を作成してみました。順番を入れ替えない回答を表示します。縮退データを利用しているのでサーバに優しい処理になっていますw
}
★追記 2024/02/06 {
今回実施した手法では正規化する際にまだ未発見の揺らぎが残存した場合、縮退数は更に小さくなるので真の値は今回求めた縮退数以下と言えます。
一方で冒頭で紹介した Twitter メッセージの投稿者は全ての RPN 式に対して各変数を0~9にした場合の計算結果が等しい場合、同じグループに分類するという手法を使用したとのことです。この場合、変数が0~9の範囲外の時、同一グループでも計算結果が異なる可能性もあるので真の値はグルーピング数以上ということになります。
以上から、真の値は縮退数以下で、かつグルーピング数以上ということになり、結果として「縮退数=グルーピング数」だったので「今回求めた縮退数は真の値である」と言えます。
}
以上が今回実装した処理の概要になります。参考としてサイズは大きいですが縮退後の全パターンを貼っておきます。
RPN 式の正規化後の縮退結果 |
|
超小型Z80マイコン(その5)Z80 INIR命令の中断 [Z80]
以前、PIC24 を使った 3 チップ構成の Z80 シングルボードを開発した際に「レトロマイコンZ80ボードの構想(その10)CP/M80 BIOS検討2 」の記事で Z80 が HALT 状態( HALT 命令を繰り返している状態)の時にメモリ上の HALT のコードを別のコード(例えば NOP )に書き換えることで HALT から抜け出せないか実験したことを書きました。メモリ上の HALT コードを書き換えても HALT 状態は継続されるという結果でした(コメント欄に書いたように適切なタイミングでリセット信号をアクティブにすると HALT から抜け出せる: Z80 スペシャルリセットと言うようです)。
今回の開発では「超小型Z80マイコン(その3)hello表示」の記事に書いたように I/O 入力データを HL の示すメモリに書き込む動作を B レジスタ 分繰り返す INIR 命令のコードを PIC がデータバスに直接出力することで Z80 の初期起動( boot )を実現しています。
ここで素朴な疑問が湧いてきました。
INIR 命令実行中にメモリの内容を別の命令に書き換えたら Z80 はどう動くのか?
気になりますねぇ ・・・ 確かめてみました。
今回開発中の Z80PicCompact では ROM を実装していないため、Z80 を boot する際に PIC 側から INIR のコードをデータバス上に出力して Z80 に実行させています。Z80 が I/O 入力した際も PIC がロードしたいプログラムのコードをデータバス上に出力しています。
boot 処理用のデータを下記のように B レジスタの値を実際にロードするコードより 32 増やした状態にして INIR の命令を 4 回目に実行するタイミングで、Z80 に対して JP 0100H( C3H,00H,01H )の命令を渡した場合( Z80 からはメモリ上のコードが突然ジャンプ命令に変わったように見える)の挙動を確認してみました。
下図が上述したことを実行した際のロジアナ波形です。
黄色い矢印部分がそれぞれ INIR 命令を実行している箇所です。この 3 回の INIR 命令によってメモリ上の 0x0100 のアドレスに JP 0100H のコードが書き込まれます。カーソルで囲った部分で PIC が INIR 命令の代わりに JP 0100H 命令( 0xc3, 0x00, 0x01 )をデータバスに出力しています。
その直後の 0.84 us と時間表示されている部分がメモリの 0100H 上にある JP 0100H を始めて実行している部分で(Z80 は 12MHz 動作で JP は10クロック必要)、その後ジャンプ命令でループしています。
従って確認結果は「Z80 は INCR 命令を連続して実行中にフェッチコードが別の命令になった場合にはフェッチした命令を実行する」と言うことになります。
Z80PicCompact の boot 処理では、 INIR 命令を実行する前に B レジスタを設定していました( I/O アドレスは何でもいいので C レジスタは設定していません)。
しかし、今回の結果から B レジスタ自体の設定も不要であり、ロードするコードのバイト数も 256 バイト以上でも問題ないということが判りました。面白いですね。
[TOP] [ 前へ ] 連載記事一覧 [ 次へ ]
今回の開発では「超小型Z80マイコン(その3)hello表示」の記事に書いたように I/O 入力データを HL の示すメモリに書き込む動作を B レジスタ 分繰り返す INIR 命令のコードを PIC がデータバスに直接出力することで Z80 の初期起動( boot )を実現しています。
ここで素朴な疑問が湧いてきました。
INIR 命令実行中にメモリの内容を別の命令に書き換えたら Z80 はどう動くのか?
気になりますねぇ ・・・ 確かめてみました。
今回開発中の Z80PicCompact では ROM を実装していないため、Z80 を boot する際に PIC 側から INIR のコードをデータバス上に出力して Z80 に実行させています。Z80 が I/O 入力した際も PIC がロードしたいプログラムのコードをデータバス上に出力しています。
boot 処理用のデータを下記のように B レジスタの値を実際にロードするコードより 32 増やした状態にして INIR の命令を 4 回目に実行するタイミングで、Z80 に対して JP 0100H( C3H,00H,01H )の命令を渡した場合( Z80 からはメモリ上のコードが突然ジャンプ命令に変わったように見える)の挙動を確認してみました。
Z80PicCompact の boot処理用のデータ(抜粋) |
---|
#define PROG_START 0x0100 // program start address #define PROG_SIZE ( sizeof( Prog ) / sizeof( uint8_t ) ) // program size const uint8_t Prog[] = { // must be smaller than 0x0100 0xc3 ,0x00 ,0x01 }; const uint8_t LoadCode[] = { 0x21 // LD HL,PROG_START ,PROG_START & 0x00ff ,PROG_START / 256 ,0x06 // LD B,PROG_SIZE ,PROG_SIZE + 32 // ,0xed // INIR // ,0xb2 }; |
下図が上述したことを実行した際のロジアナ波形です。
INIR 命令を JP 命令に変更した際の挙動(サンプリング:25MHz) |
|
黄色い矢印部分がそれぞれ INIR 命令を実行している箇所です。この 3 回の INIR 命令によってメモリ上の 0x0100 のアドレスに JP 0100H のコードが書き込まれます。カーソルで囲った部分で PIC が INIR 命令の代わりに JP 0100H 命令( 0xc3, 0x00, 0x01 )をデータバスに出力しています。
その直後の 0.84 us と時間表示されている部分がメモリの 0100H 上にある JP 0100H を始めて実行している部分で(Z80 は 12MHz 動作で JP は10クロック必要)、その後ジャンプ命令でループしています。
従って確認結果は「Z80 は INCR 命令を連続して実行中にフェッチコードが別の命令になった場合にはフェッチした命令を実行する」と言うことになります。
Z80PicCompact の boot 処理では、 INIR 命令を実行する前に B レジスタを設定していました( I/O アドレスは何でもいいので C レジスタは設定していません)。
しかし、今回の結果から B レジスタ自体の設定も不要であり、ロードするコードのバイト数も 256 バイト以上でも問題ないということが判りました。面白いですね。
[TOP] [ 前へ ] 連載記事一覧 [ 次へ ]
超小型Z80マイコン(その4)GAME言語で動作確認 [Z80]
前回の記事で Z80 からの表示要求により hello 表示ができたことを書きましたが、色々弄っていると動作が不安定であることが判りました^^;
データバスへの出力タイミングやウェイトの開放タイミング等を見直し、漸く安定動作するようになり、動作確認のために GAME 言語を入れてみました。
前回の記事で書いた boot ROM 機能では最大 256 バイトのコードまでしか対応できないので、これを何回か繰り返して大きなサイズに対応する方法も考えられますが、以前作成した 256 バイトに収まる Hex ファイルのローダーを移植してみることにしました。
下記が Hex ファイルローダーのソースリストになります。ロード完了後に ロード対象の開始アドレスにジャンプする機能を追加しました。
GAME 言語のコンソール入出力部分も Z80PicCompact に合わせて変更する必要がありますが、下記のように極めてシンプルなものになります。
動作確認のために所有している GAME 言語のソースの中で一番大きなもの(=コンパイラ)を使って確認した結果、安定に動作することが確認できました。表題からは GAME 言語でチェックプログラムでも作ったのかと思われた方もいらっしゃったかもしれませんがコンパイラを動かしてみたという落ちでしたw
今回使用している USB 機能内蔵 PIC での CDC(Communication Device Class) クラスでは usb_device_cdc.c 内にある CDCInitEP() の処理内で line_coding.dwDTERate にボーレートを 9600 で設定している部分があるのですが、この値に関わらずパソコンとの通信速度は爆速です。TeraTerm 側の通信速度設定の影響も受けないようです。
Twitterに投稿した動画付きコメントを貼っておきます。GAME 言語のコンパイラをコンパイルしているだけですが、ロードの爆速ぶりとコンパイラのなつかしさを堪能してください。
[TOP] [ 前へ ] 連載記事一覧 [ 次へ ]
データバスへの出力タイミングやウェイトの開放タイミング等を見直し、漸く安定動作するようになり、動作確認のために GAME 言語を入れてみました。
前回の記事で書いた boot ROM 機能では最大 256 バイトのコードまでしか対応できないので、これを何回か繰り返して大きなサイズに対応する方法も考えられますが、以前作成した 256 バイトに収まる Hex ファイルのローダーを移植してみることにしました。
下記が Hex ファイルローダーのソースリストになります。ロード完了後に ロード対象の開始アドレスにジャンプする機能を追加しました。
Z80PicCompacy 用 Hex ファイルローダー( Z80 アセンブラ) |
|
GAME 言語のコンソール入出力部分も Z80PicCompact に合わせて変更する必要がありますが、下記のように極めてシンプルなものになります。
GAME 言語用の入出力処理( Z80 アセンブラ) |
---|
8C96 CD 8C9F GETCH: CALL CONIN 8C99 C3 8CA2 PUTCH: JP CONOUT 8C9C C3 8CA5 KBHIT: JP CONSTS 8C9F DB 00 CONIN: IN A,(DATPORT) 8CA1 C9 RET 8CA2 D3 00 CONOUT: OUT (DATPORT),A 8CA4 C9 RET 8CA5 DB 01 CONSTS: IN A,(CMDPORT) 8CA7 0F RRCA 8CA8 C9 RET |
動作確認のために所有している GAME 言語のソースの中で一番大きなもの(=コンパイラ)を使って確認した結果、安定に動作することが確認できました。表題からは GAME 言語でチェックプログラムでも作ったのかと思われた方もいらっしゃったかもしれませんがコンパイラを動かしてみたという落ちでしたw
今回使用している USB 機能内蔵 PIC での CDC(Communication Device Class) クラスでは usb_device_cdc.c 内にある CDCInitEP() の処理内で line_coding.dwDTERate にボーレートを 9600 で設定している部分があるのですが、この値に関わらずパソコンとの通信速度は爆速です。TeraTerm 側の通信速度設定の影響も受けないようです。
Twitterに投稿した動画付きコメントを貼っておきます。GAME 言語のコンパイラをコンパイルしているだけですが、ロードの爆速ぶりとコンパイラのなつかしさを堪能してください。
20ピンのPIC使用の3チップ構成小型Z80ボードを検討中
— skyriver (@wcinp) October 10, 2022
Z80からのhello表示は出来たものの動作が不安定だったのでタイミングを見直して動作が安定になった^^
動作確認のためにHexローダーを移植しGAME言語のコンパイラをコンパイルしてみたhttps://t.co/bcOONd4TcV#Z80PicCompact #Z80 #PIC18F14K50 pic.twitter.com/yQUuZmJjVQ
[TOP] [ 前へ ] 連載記事一覧 [ 次へ ]
超小型Z80マイコン(その3)hello表示 [Z80]
今回開発予定の USB 対応の 20 ピンの PIC ( PIC18F14K50 )を使った 3 チップ構成( Z80、PIC 及び SRAM )の小型 Z80 マイコン( Z80PicCompact )について前回の記事では PIC が出力するコードを直接 Z80 が実行できたことについて書きました。
今回は前回の記事の末尾で書いたように hello 表示の実現について書いてみます。
Z80 上のプログラムから hello を表示するためには PIC から Z80 へプログラムコードをロードする boot ROM 機能と Z80 からの文字出力要求に対して PIC 側が Z80 から出力データ受け取り、USB 経由でパソコンへ送信する USB I/F 機能(= I/O 機能の一部)を実現する必要があります。
それではそれぞれの機能の実現方法について書いてみます。
以上が、hello 表示を実現させるために行った作業の概要になります。
今回の実験途中にインストールしたばかりの MPLABX Ver6.0 が不調になってしまいましたorz
具体的な症状としては下図のようにプロジェクトのプロパティ変更ができない( 「OK」ボタンが押せない)状態になり、別のプロジェクトで試しても同様に変更できませんでした。
再インストールしても問題が再発する可能性もあるので、従来使っていた MPLABX Ver5.45 を使って上記の確認作業を継続しました。
[TOP] [ 前へ ] 連載記事一覧 [ 次へ ]
今回は前回の記事の末尾で書いたように hello 表示の実現について書いてみます。
Z80 上のプログラムから hello を表示するためには PIC から Z80 へプログラムコードをロードする boot ROM 機能と Z80 からの文字出力要求に対して PIC 側が Z80 から出力データ受け取り、USB 経由でパソコンへ送信する USB I/F 機能(= I/O 機能の一部)を実現する必要があります。
それではそれぞれの機能の実現方法について書いてみます。
- boot ROM 機能
前回の記事で書いたように PIC からのプログラムコードを Z80 が実行できるようになったので B レジスタ回数分 I/O 入力したデータを HL レジスタの示すメモリに書き込む命令である INIR 命令を使ってプロムラムをメモリ上にロードするようにしました。PIC 側が出力したコードを Z80 がメモリ上に保存した後、PIC からのジャンプ命令を受けて、保存したプログラムを Z80 が実行するようにしています。
このロード動作をするためのコードは PIC 側がデータバスに直接出力しているのでロード対象プログラムを任意のアドレスにロードすることが出来ます(ロードするためのコードの実行アドレスと重なっていても問題ありません)。
0100H から始まる JP 命令でループ動作を繰り返すプロムラム( 0C3H, 00H, 01H )をロード & 実行してみた時のロジアナ波形が下図になります。
"JP 0100H" の繰り返し時のロジアナ波形例(サンプリング:25MHz)
カーソルで囲った部分がロードされた JP 命令 を初めて実行している部分でウェイト無しで実行時間は 0.84 us になっています。JP XXXX 命令は 10 クロック必要なので上図から Z80 は 12MHz で動作していることが判ります(計算上は 0.833 us ですがロジアナのサンプリングが遅いために 0.84 us に見えている)。
下図は boot 処置中の INIR 命令実行部分のロジアナ波形です。INIR 命令は 21 クロック必要なのでウェイト無しで実行した場合の時間は 1.75 us です。下図では ウェイトが入っているため 5 us 掛かっているので boot 処理時の速度は 4.2 MHz 相当(=1/(5/21)) と言うことになります。
INIR 実行時のロジアナ波形例(サンプリング:25MHz)
- USB I/F 機能
boot ROM機能で boot 後、 Z80 は I/O 命令を使って PIC とインターフェースをとります。
Z80 は自らの IORQ/ でウェイト状態になるようにしているので PIC 側はウェイト状態を監視しておもむろに対応する処理を行うことができます。また、Z80 は I/O 命令以外はウェイト無しで動作するようになります。
PIC 側の I/O ピン数が少ないため、アドレス線は A0 しか監視していません。
Z80 の I/O 命令で A0 が 1 の場合はコマンドポート、0 の場合はデータポートとして割り振りました。
具体的な割り振りは下表のとおりです。
No. A0 R/W memo 1 1 write モード設定 2 1 read ステータス読出し 3 0 write データ書込み 4 0 read データ読出し
モードとしては暫定的に下記のようにしました。ストリングモードは USB へ文字列データを一括して渡すので効率よく処理できます。
キャラクタモード : 1 文字単位でのシリアル入出力
ストリングモード : 文字列単位でのシリアル出力
下のリストが今回作成した Z80 側の hello 表示プログラムです。キャラクタモードを使用しています。
Z80 側の hello 表示プログラム( Z80 アセンブラ) ;++++++++++++++++++++++++++++++++++++ ; hello program for Z80PicCompact ; Ver 0.01 2022/10/05 by skyriver ;++++++++++++++++++++++++++++++++++++ 0000 DATPORT EQU 0 ; data port 0001 CMDPORT EQU 1 ; command port 0001 SIO_CHAR EQU 1 ; char mode 1000 STACK EQU 1000H 0000' ASEG ORG 0100H 0100 31 1000 START: LD SP,STACK 0103 3E 01 LD A,SIO_CHAR 0105 D3 01 OUT (CMDPORT),A ; set character mode 0107 21 0119 LD HL,msg 010A CD 0110 CALL PUTS 010D C3 010D JP $ ; PUTS : put string to serial ; HL <- message address 0110 7E PUTS: LD A,(HL) 0111 23 INC HL 0112 B7 OR A 0113 C8 RET Z 0114 D3 00 OUT (DATPORT),A 0116 C3 0110 JP PUTS 0119 68 65 6C 6C msg: DB "hello, world", 13, 10, 0 011D 6F 2C 20 77 0121 6F 72 6C 64 0125 0D 0A 00 END Macros: Symbols: 0001 CMDPORT 0000 DATPORT 0119 MSG 0110 PUTS 0001 SIO_CHAR 1000 STACK 0100 START No Fatal error(s)
下図は hello 実行時の Z80 が OUT 命令を実行している部分のロジアナ波形です。 PIC 側はデータを受け取った後に USB 関連の関数をコールしているため、結構時間が掛かっています。
hello 実行時の OUT 命令部のロジアナ波形例(サンプリング:25MHz)
2文字目の 'e' を出力した後の Z80 の処理部分を拡大したものが下図になります。 OUT 命令から解放されて次の文字を準備するために 5 個の命令を実行後に OUT 命令で再度ウェイト状態になっています。
'e' を出力後の Z80 の動作部の拡大波形例(サンプリング:25MHz)
今回の実験の成果として hello が表示された画面のキャプチャが下図になります。
"Start" の文字列は PIC が USB 初期化後に表示しているもので、 2 行目の文字列が Z80 からの要求により表示されたものです。TeraTerm へは 38400 bps で接続していますが、外付けの USB-Serial 変換を介していないので好きなボーレイトで接続可能です。
hello 表示画面(サンプリング:25MHz)
★追記 2022/10/08 {
ストリングモードで hello 表示を行った場合の OUT 命令実行部のロジアナ波形を追記します。上記のキャラクタモードより 5 倍程度速くなっています。
ストリングモードでの OUT 命令部のロジアナ波形例(サンプリング:25MHz)
以上が、hello 表示を実現させるために行った作業の概要になります。
今回の実験途中にインストールしたばかりの MPLABX Ver6.0 が不調になってしまいましたorz
具体的な症状としては下図のようにプロジェクトのプロパティ変更ができない( 「OK」ボタンが押せない)状態になり、別のプロジェクトで試しても同様に変更できませんでした。
再インストールしても問題が再発する可能性もあるので、従来使っていた MPLABX Ver5.45 を使って上記の確認作業を継続しました。
MPLAB Ver6.0の問題発生画面 |
|
[TOP] [ 前へ ] 連載記事一覧 [ 次へ ]