SSブログ
English Version

超小型Z80マイコン(その14)開発機のケース製作 [Z80]

 前回の記事で書いたようにユニバーサル基板を用いてポリウレタン線で手配線した開発用基板が 20MHz で動作しハード弄りは一段落しました。Z80 を使った簡単な実験を行う場合はやはり速い方がいいのでこの開発機を結構使っています。
 基板の裏面はカバーで保護していますが、今後も安定した状態で使っていきたいのでケースを作ることにしました。

 開発機なのであまり凝らずに下図のような3ピース構成にしてみました。右側面の穴は USB コネクタと TF カード用のものです。

Z80PicCompact開発機のケース設計01(CAD画面)


 各ピースの間隔を空けると下図のようになります。各パーツは下の方からベースプレート、サイドパーツ、トッププレートと呼ぶことにします。

Z80PicCompact開発機のケース設計02(CAD画面)


 下図はスケルトン表示になります。ベースプレートとトッププレートはネジでサイドパーツに固定します。

Z80PicCompact開発機のケース設計03(CAD画面)


 今までとほとんど同じ状態ですがベースプレートに開発基板を取り付けた状態が下の写真です。TF カードは外した状態です。今回ケースを作成する際にTF コネクタを汎用基板に直付けしようと試みたのですが、失敗してコネクタを1個壊してしまったので従来通り市販のコネクタ基板を使うことにしました。

ベースプレートに取付けた開発基板


 下の写真はサイドパーツを取り付けた後の状態です。汎用基板は四隅がベースプレートとサイドパーツで固定されます。

サイドパーツを取り付けた開発基板01 サイドパーツを取り付けた開発基板02


 左下の写真は TF カード基板を取り付けた状態のものでサイドパーツで支えられています。右下はベースプレート面の写真でネジの頭部が出っ張らないように頭部用のホールを設けています。

TF カード基板装着後 ベースプレート面


 トッププレートを取り付けた状態が下の写真です。本来であればアクリル板を CNC で加工して透明で文字入りのパネルにしたいのですが手抜きでトッププレートもFDM式の3Dプリンタで出力しました。以前、実験的にSLA式の3Dプリンタでパネル作成したこともありましたが、レジンは強度的にケース等には適さないということが判りました。

トッププレート取付け後


 しかし、基板に実装した部品が全く見えないのも面白くないので今回使用しているフィラメントである透明の PETG での造形物を透明化する簡単な実験を行いました。

 実験は次の二通りでやってみました。両者共に溶剤は手持ちのノルマルプロピルアルコール(NPA)を使い2倍程度に薄めて使いました。
  1. 2液式エポキシ接着剤でのコーティング
    参考:「これは超便利!何でも強力にコーティングできる激安エポキシクリアの自作実験をご紹介します!」
  2. 透明のUVレジンでのコーティング

 不要になったサイドパーツ部品にコーティングし評価しました。評価方法はペン型テスタのパネルに表示された "Auto" の文字の見え方で効果を判断しました(コーティング物からピンセットを使って約 1cm 離した状態で目視)。一応写真も撮りましたが、写真では目視での感覚をあまり表現できていません。
 結果を下表に示します。評価は5段階で数字が大きい程、良い結果ということにしています。

No.写真コーティング素材備考評価
1 コーティング無し無加工1
2 エポキシ原液1回コーティング
光の透過性はかなり向上したが表面に凹凸感がある
4
3 エポキシ(2倍希釈) サンドペーパーの600番で軽くヤスった後に1回コーティング
手間を掛けた割にはあまり透けない
3
4 レジン(2倍希釈) 1回コーティング
透明度がやや増した
2
5 レジン(2倍希釈) 2回コーティング
透明度が更に増した
4
6 レジン(2倍希釈) 3回コーティング
2回コーティングとほとんど同じ
4


 上記表の結果から No5 の手法でトッププレートをコーティングしてみました。片面はベッドに接している平らな面なのでベッドと反対側のみコーティングしました。結果が下の写真です。

トッププレートをコーティング後の状態


 評価で用いたサイドパーツと違いトッププレートはメッシュ状に積層されているのでメッシュ状に細かい気泡がありなかなか透明度は上がりませんでしたが、ICチップの位置が見えるようになりました。
 「Pic24MC68Kマイコン(その8)ケース作成」の記事の最後の方に書いたように以前、透明の PETG フィラメントで作ったケースにエアブラシで UV カット塗料を塗布したことがあります。同じ材料で比較できていませんが効果は同レベルなのでは無いかと思います。今回の手法はエアブラシで塗料を塗布するよりはお手軽なので今後活用できる場面があるのではないかと思います。


★追記 2023/05/14 {
 UV レジンをコーティングしたものはベトツキ感がなかなか取れない(レジンにも依存すると思いますが)という短所があったのでエポキシを使ってリベンジしてみました。
 前回からの変更点は
  • 濃度は高め
     上記では2倍(エポキシと溶剤を等分)に希釈していましたが、コーティングで効果を上げるため少し濃いめ(エポキシ:溶剤=3:2程度)にし、塗布回数は1回にしました。
  • 積層パターン
     外面(一番下面と一番上面)の積層パターンをメッシュから同心円に変更しました。
  • コーティング対象面
     前回はベッド面はコーティングしていませんでしたが、今回はベッド面も含め両面にコーティングしました。
結果として、エポキシでも前回のレジン2回塗布と同程度の効果(ベッド面もコーティングしたことで透明度は更に増している)が得られることが判りました。
 更にエポキシの場合、乾くのが早いし、コーティング面がすぐにサラサラな状態になるというメリットがあります。

エポキシでのトッププレートコーティング結果

 尚、筆を駄目にしたくないので割り箸と爪楊枝を使って塗布しています。
}



[TOP] [ 前へ ] 連載記事一覧 [ 次へ ]

nice!(0)  コメント(0) 

Z80での高速な乗算処理(その3)2バイト乗算への適用検討 [Z80]

 「Z80での高速な乗算処理」の記事の「応用編」で1バイトの乗算処理を使った2バイト乗算処理への拡張では今回提案しているマイナス二乗法の効果は確認できませんでした。1バイトの乗算処理では2.4倍程度速くなったマイナス二乗法の2バイト乗算処理への適用について再度考えてみました。

  1. 以前の簡易2バイト対応
     上記の記事で書いたマイナス二乗法の簡易的な2バイト乗算への適用は下記の式に示すように2バイト変数をバイトに分離して計算しました。


        (28*x1 + x0)*(28*y1 + y0) 
      = 216*x1*y1 + 28*(x0*y1 + x1*y0) + x0*y0 
     

     マイナス二乗法では1回の掛け算で二乗テーブルを3回引くので、上記の2バイト乗算では1バイトの乗算を4回実装する必要があることから、二乗テーブルを合計で12回引くことになります。


  2. マイナス二乗法の2バイト乗算への適用検討

    [二乗計算の高速化
     マイナス二乗法は下記の計算式で乗算値を求める方式です。


         (x - y)2 = x2 - 2*x*y + y2 
      ⇒ x*y = ( x2 + y2 - (x - y)2 ) / 2 
     

     従って2バイトの乗算に適用するためには2バイトの二乗を高速に計算する必要があります。2バイトの二乗をテーブルから丸ごと引く為にはメモリが大量に必要になるので、従来通り1バイトの二乗テーブルを使うことにしたいと思います。
     2バイトのデータを上位バイトと下位バイトに分けて考えると、二乗計算は下記のようになります。


        X = 28*x1 + x0 
      X2 = (28*x1 + x0)2 
           = 216*x12 + 29*x1*x0 + x02 
     

     ここで上記のマイナス二乗法の計算式より、x1*x0=(x12+x02-(x1-x0)2)/2 なので


        (28*X1 + x0)2 
     = 216*x12 + x02 + 29x1*x0 
     = 216*x12 + x02 + 28*(x12 + x02 - (x1 - x0)2
     = (216 + 28)*x12 + (28 + 1)*x02 - 28*(x1 - x0)2 
     

    となり、1バイト用の二乗テーブルを3回引くことで2バイトの二乗を求めることができるということになります。

    ★追記 2023/04/30 {
     下記の様に (28 + 1) を共通項にすることで若干最適化しました。


     = (216 + 28)*x12 + (28 + 1)*x02 - 28*(x1 - x0)2 
     = (28 + 1)*(28*x12 + x02) - 28*(x1 - x0)2 
     
    }


    [乗算の計算方法]
     符号付の乗算を考えると MSB は符号情報であることから、乗数と被乗数の絶対値を求めてから符号無し乗算処理を実施後に再度、符号付整数にするという処理になります。
     従って実際に乗算する値は絶対値であり、2バイト乗算の場合は符号無しの15ビット整数を掛け合わせることになります。
     そのため冒頭で書いた「Z80での高速な乗算処理」の記事の出だしで書いている


     (X + Y)2 - (X - Y)2 = 4*X*Y 
     ⇒ X*Y = ((X + Y)2 - (X - Y)2) / 4 
     
     

    を使用しても (X + Y) が16ビットになるので桁あふれせずに前述の二乗テーブル引きにより、2バイトの二乗の値を求めることができます。

     計算のコストの目安として仮に二乗テーブルを引く回数とすると、上記の方法による2バイトの乗算処理でテーブルを引く回数は6回(=2x3回)となり、前項で書いた以前の簡易適用の場合(12回)の半分で済むことになります(但し、二乗を求めた後に複数の加算処理等が必要になる)。
     どうでしょう。中々見込みがありそうになってきたと思いませんか?


  3. コード化
     机上の方式検討だけでは評価できないので、簡易的にコード化して評価してみたいと思います。但し、今回考案した処理内容の評価が主要な目的なのでコード自体の最適化はあまり行っていません。

    [標準的な乗算処理]
     比較のために標準的な筆算方式による符号無し2バイトの乗算処理を作ってみました。
     ネットを探せば見つかりそうではありますが処理的にも単純なので自前でコードを起こしました。レジスタのみで処理が完結しているのでそれなりに高速な乗算処理になったのではないかと思います(引数とリターン値へのレジスタ割り振りを下記の乗算処理と合わせるために先頭と末尾で調整しています)。

    筆算方式による標準的な2バイト乗算処理(Z80アセンブラ)
    ; normal unsigned 16 bits mul ; DE <- val1 ; HL <- val2 ; HLBC -> val1 * val2 ; ; BCHL vs DE 02A1 3E 10 MUL16: LD A,16 02A3 44 LD B,H 02A4 4D LD C,L 02A5 21 0000 LD HL,0 02A8 29 MUL16L: ADD HL,HL 02A9 CB 11 RL C 02AB CB 10 RL B 02AD 30 04 JR NC,MUL16N 02AF 19 ADD HL,DE 02B0 30 01 JR NC,MUL16N 02B2 03 INC BC 02B3 3D MUL16N: DEC A 02B4 C2 02A8 JP NZ,MUL16L 02B7 59 LD E,C 02B8 50 LD D,B 02B9 EB EX DE,HL 02BA 4B LD C,E 02BB 42 LD B,D 02BC C9 RET


    [以前の簡易乗算処理]
     冒頭で書いた以前行った2バイトを上位バイトと下位バイトに分割した簡易的な乗算処理も再度コードを起こしてみました。高速化のためにローカルな変数領域は使用せずにレジスタとスタックのみで処理するようにしています。

    バイト分割による乗算処理(Z80アセンブラ)
    ; ; (256*x1 + x0)*(256*y1 + y0) ; = 2^16x1y1 + 2^8(x0*y1 + x1*y0) + x0*y0 ; ; | . | . | . | . | ; <--- x1y1 ---> ; <--- x0y1 ---> ; <--- x1y0 ---> ; <--- x0y0 ---> ; unsigned 15 bits mul ; DE <- val1(X) ; HL <- val2(Y) ; HLBC -> val1 * val2 0359 E5 FMul16: PUSH HL ; (SP):Y 035A D5 PUSH DE ; (SP):Y,X 035B 55 LD D,L ; DE: y0:x0 035C 6B LD L,E ; HL: y1:x0 035D E5 PUSH HL ; (SP):Y,X,y1:x0 035E CD 038B CALL FMul8 ; HL<-x0*y0 0361 E3 EX (SP),HL ; (SP):Y,X,x0*y0, HL:y1:x0 0362 EB EX DE,HL ; DE:y1:x0 0363 CD 038B CALL FMul8 ; HL:x0*y1 0366 D1 POP DE ; (SP):Y,X DE:x0*y0 0367 C1 POP BC ; (SP):Y BC:x1:x0 0368 E3 EX (SP),HL ; (SP):x0*y1, HL:y1:y0 0369 D5 PUSH DE ; (SP):x0*y1,x0*y0 036A 50 LD D,B 036B 5D LD E,L ; DE:x1:y0 036C 68 LD L,B ; HL:y1:x1 036D E5 PUSH HL ; (SP):x0*y1,x0*y0,y1:x1 036E CD 038B CALL FMul8 ; HL:x1*y0 0371 E3 EX (SP),HL ; (SP):x0*y1,x0*y0,x1*y0, HL:y1:x1 0372 EB EX DE,HL ; DE:y1:x1 0373 CD 038B CALL FMul8 ; HL:x1*y1 0376 D1 POP DE ; (SP):x0*y1,x0*y0 DE:x1*y0 0377 7C LD A,H 0378 65 LD H,L 0379 2E 00 LD L,0 037B 19 ADD HL,DE 037C CE 00 ADC A,0 037E C1 POP BC ; (SP):x0*y1 BC:x0*y0 037F D1 POP DE ; (SP):none DE:x0*y1 0380 19 ADD HL,DE 0381 16 00 LD D,0 0383 58 LD E,B 0384 8A ADC A,D ; D:0 0385 19 ADD HL,DE 0386 8A ADC A,D ; D:0 0387 45 LD B,L 0388 6C LD L,H 0389 67 LD H,A 038A C9 RET ; unsigned 8 bits fast multi(my method) ; x*y = (x^2 + y^2 - (x-y)^2)/2 ; E <- data0 ; D <- data1 ; HL -> data0 * data1 038B 6A FMul8: LD L,D ; 4 038C 7B LD A,E ; 4 038D A5 AND L ; 4 038E 1F RRA ; 4 038F 26 06 LD H,HIGH(MULTB2) ; 7 0391 54 LD D,H ; 4 0392 1A LD A,(DE) ; 7 0393 8E ADC A,(HL) ; 7 0394 4F LD C,A ; 4 0395 14 INC D ; 4 0396 24 INC H ; 4 0397 1A LD A,(DE) ; 7 0398 8E ADC A,(HL) ; 7 0399 57 LD D,A ; 4 039A 7B LD A,E ; 4 039B 95 SUB L ; 4 039C 30 02 JR NC,FFMu10 ; 12/7 039E ED 44 NEG ; 8 03A0 6F FFMU10: LD L,A ; 4 03A1 5E LD E,(HL) ; 7 03A2 25 DEC H ; 4 03A3 79 LD A,C ; 4 03A4 96 SUB (HL) ; 7 03A5 6F LD L,A ; 4 03A6 7A LD A,D ; 4 03A7 9B SBC A,E ; 4 03A8 67 LD H,A ; 4 03A9 C9 RET ; 10 ; (8bit ^ 2) / 2 table 0600 00 00 02 04 MULTB2: DB 000H,000H,002H,004H,008H,00CH,012H,018H ; low byte 0604 08 0C 12 18 0608 20 28 32 3C DB 020H,028H,032H,03CH,048H,054H,062H,070H 060C 48 54 62 70 0610 80 90 A2 B4 DB 080H,090H,0A2H,0B4H,0C8H,0DCH,0F2H,008H 0614 C8 DC F2 08 0618 20 38 52 6C DB 020H,038H,052H,06CH,088H,0A4H,0C2H,0E0H 061C 88 A4 C2 E0 0620 00 20 42 64 DB 000H,020H,042H,064H,088H,0ACH,0D2H,0F8H 0624 88 AC D2 F8 0628 20 48 72 9C DB 020H,048H,072H,09CH,0C8H,0F4H,022H,050H 062C C8 F4 22 50 0630 80 B0 E2 14 DB 080H,0B0H,0E2H,014H,048H,07CH,0B2H,0E8H 0634 48 7C B2 E8 0638 20 58 92 CC DB 020H,058H,092H,0CCH,008H,044H,082H,0C0H 063C 08 44 82 C0 0640 00 40 82 C4 DB 000H,040H,082H,0C4H,008H,04CH,092H,0D8H 0644 08 4C 92 D8 0648 20 68 B2 FC DB 020H,068H,0B2H,0FCH,048H,094H,0E2H,030H 064C 48 94 E2 30 0650 80 D0 22 74 DB 080H,0D0H,022H,074H,0C8H,01CH,072H,0C8H 0654 C8 1C 72 C8 0658 20 78 D2 2C DB 020H,078H,0D2H,02CH,088H,0E4H,042H,0A0H 065C 88 E4 42 A0 0660 00 60 C2 24 DB 000H,060H,0C2H,024H,088H,0ECH,052H,0B8H 0664 88 EC 52 B8 0668 20 88 F2 5C DB 020H,088H,0F2H,05CH,0C8H,034H,0A2H,010H 066C C8 34 A2 10 0670 80 F0 62 D4 DB 080H,0F0H,062H,0D4H,048H,0BCH,032H,0A8H 0674 48 BC 32 A8 0678 20 98 12 8C DB 020H,098H,012H,08CH,008H,084H,002H,080H 067C 08 84 02 80 0680 00 80 02 84 DB 000H,080H,002H,084H,008H,08CH,012H,098H 0684 08 8C 12 98 0688 20 A8 32 BC DB 020H,0A8H,032H,0BCH,048H,0D4H,062H,0F0H 068C 48 D4 62 F0 0690 80 10 A2 34 DB 080H,010H,0A2H,034H,0C8H,05CH,0F2H,088H 0694 C8 5C F2 88 0698 20 B8 52 EC DB 020H,0B8H,052H,0ECH,088H,024H,0C2H,060H 069C 88 24 C2 60 06A0 00 A0 42 E4 DB 000H,0A0H,042H,0E4H,088H,02CH,0D2H,078H 06A4 88 2C D2 78 06A8 20 C8 72 1C DB 020H,0C8H,072H,01CH,0C8H,074H,022H,0D0H 06AC C8 74 22 D0 06B0 80 30 E2 94 DB 080H,030H,0E2H,094H,048H,0FCH,0B2H,068H 06B4 48 FC B2 68 06B8 20 D8 92 4C DB 020H,0D8H,092H,04CH,008H,0C4H,082H,040H 06BC 08 C4 82 40 06C0 00 C0 82 44 DB 000H,0C0H,082H,044H,008H,0CCH,092H,058H 06C4 08 CC 92 58 06C8 20 E8 B2 7C DB 020H,0E8H,0B2H,07CH,048H,014H,0E2H,0B0H 06CC 48 14 E2 B0 06D0 80 50 22 F4 DB 080H,050H,022H,0F4H,0C8H,09CH,072H,048H 06D4 C8 9C 72 48 06D8 20 F8 D2 AC DB 020H,0F8H,0D2H,0ACH,088H,064H,042H,020H 06DC 88 64 42 20 06E0 00 E0 C2 A4 DB 000H,0E0H,0C2H,0A4H,088H,06CH,052H,038H 06E4 88 6C 52 38 06E8 20 08 F2 DC DB 020H,008H,0F2H,0DCH,0C8H,0B4H,0A2H,090H 06EC C8 B4 A2 90 06F0 80 70 62 54 DB 080H,070H,062H,054H,048H,03CH,032H,028H 06F4 48 3C 32 28 06F8 20 18 12 0C DB 020H,018H,012H,00CH,008H,004H,002H,000H 06FC 08 04 02 00 0700 00 00 00 00 DB 000H,000H,000H,000H,000H,000H,000H,000H ; high byte 0704 00 00 00 00 0708 00 00 00 00 DB 000H,000H,000H,000H,000H,000H,000H,000H 070C 00 00 00 00 0710 00 00 00 00 DB 000H,000H,000H,000H,000H,000H,000H,001H 0714 00 00 00 01 0718 01 01 01 01 DB 001H,001H,001H,001H,001H,001H,001H,001H 071C 01 01 01 01 0720 02 02 02 02 DB 002H,002H,002H,002H,002H,002H,002H,002H 0724 02 02 02 02 0728 03 03 03 03 DB 003H,003H,003H,003H,003H,003H,004H,004H 072C 03 03 04 04 0730 04 04 04 05 DB 004H,004H,004H,005H,005H,005H,005H,005H 0734 05 05 05 05 0738 06 06 06 06 DB 006H,006H,006H,006H,007H,007H,007H,007H 073C 07 07 07 07 0740 08 08 08 08 DB 008H,008H,008H,008H,009H,009H,009H,009H 0744 09 09 09 09 0748 0A 0A 0A 0A DB 00AH,00AH,00AH,00AH,00BH,00BH,00BH,00CH 074C 0B 0B 0B 0C 0750 0C 0C 0D 0D DB 00CH,00CH,00DH,00DH,00DH,00EH,00EH,00EH 0754 0D 0E 0E 0E 0758 0F 0F 0F 10 DB 00FH,00FH,00FH,010H,010H,010H,011H,011H 075C 10 10 11 11 0760 12 12 12 13 DB 012H,012H,012H,013H,013H,013H,014H,014H 0764 13 13 14 14 0768 15 15 15 16 DB 015H,015H,015H,016H,016H,017H,017H,018H 076C 16 17 17 18 0770 18 18 19 19 DB 018H,018H,019H,019H,01AH,01AH,01BH,01BH 0774 1A 1A 1B 1B 0778 1C 1C 1D 1D DB 01CH,01CH,01DH,01DH,01EH,01EH,01FH,01FH 077C 1E 1E 1F 1F 0780 20 20 21 21 DB 020H,020H,021H,021H,022H,022H,023H,023H 0784 22 22 23 23 0788 24 24 25 25 DB 024H,024H,025H,025H,026H,026H,027H,027H 078C 26 26 27 27 0790 28 29 29 2A DB 028H,029H,029H,02AH,02AH,02BH,02BH,02CH 0794 2A 2B 2B 2C 0798 2D 2D 2E 2E DB 02DH,02DH,02EH,02EH,02FH,030H,030H,031H 079C 2F 30 30 31 07A0 32 32 33 33 DB 032H,032H,033H,033H,034H,035H,035H,036H 07A4 34 35 35 36 07A8 37 37 38 39 DB 037H,037H,038H,039H,039H,03AH,03BH,03BH 07AC 39 3A 3B 3B 07B0 3C 3D 3D 3E DB 03CH,03DH,03DH,03EH,03FH,03FH,040H,041H 07B4 3F 3F 40 41 07B8 42 42 43 44 DB 042H,042H,043H,044H,045H,045H,046H,047H 07BC 45 45 46 47 07C0 48 48 49 4A DB 048H,048H,049H,04AH,04BH,04BH,04CH,04DH 07C4 4B 4B 4C 4D 07C8 4E 4E 4F 50 DB 04EH,04EH,04FH,050H,051H,052H,052H,053H 07CC 51 52 52 53 07D0 54 55 56 56 DB 054H,055H,056H,056H,057H,058H,059H,05AH 07D4 57 58 59 5A 07D8 5B 5B 5C 5D DB 05BH,05BH,05CH,05DH,05EH,05FH,060H,061H 07DC 5E 5F 60 61 07E0 62 62 63 64 DB 062H,062H,063H,064H,065H,066H,067H,068H 07E4 65 66 67 68 07E8 69 6A 6A 6B DB 069H,06AH,06AH,06BH,06CH,06DH,06EH,06FH 07EC 6C 6D 6E 6F 07F0 70 71 72 73 DB 070H,071H,072H,073H,074H,075H,076H,077H 07F4 74 75 76 77 07F8 78 79 7A 7B DB 078H,079H,07AH,07BH,07CH,07DH,07EH,07FH 07FC 7C 7D 7E 7F


    [今回提案の乗算処理]
     上述の今回考えた乗算処理をコード化したものが下記になります。今回の方式は乗算値を求める際には乗数と被乗数のプラスとマイナスの二乗を用いるプラマイ二乗法を採用していますが、各項の二乗を求める際にマイナス二乗の式を用いていることから従来通りマイナス二乗法と呼称することにします。
     尚、下記の乗算処理と上記の2つの乗算処理は乗数及び被乗数が0x0000~0x7fffの範囲内で計算結果が同じであることを確認しています。

    今回提案の乗算処理(Z80アセンブラ)
    ; unsigned 15 bits mul ; DE <- val1 ; HL <- val2 ; HLBC -> val1 * val2 ; ; X*Y = ((X + Y)^2 - (X - Y)^2) / 4 ; 02BD D5 FMUL15: PUSH DE 02BE E5 PUSH HL 02BF 19 ADD HL,DE 02C0 EB EX DE,HL 02C1 CD 02F0 CALL Square2B ; DEBC<-DE^2 02C4 E1 POP HL 02C5 EB EX DE,HL 02C6 E3 EX (SP),HL 02C7 C5 PUSH BC 02C8 AF XOR A 02C9 ED 52 SBC HL,DE 02CB 30 05 JR NC,FMU150 02CD 95 SUB L ; A:0 02CE 6F LD L,A 02CF 9F SBC A,A 02D0 94 SUB H 02D1 67 LD H,A 02D2 EB FMU150: EX DE,HL 02D3 CD 02F0 CALL Square2B 02D6 E1 POP HL 02D7 B7 OR A 02D8 ED 42 SBC HL,BC 02DA 44 LD B,H 02DB 4D LD C,L 02DC E1 POP HL 02DD ED 52 SBC HL,DE 02DF CB 3C SRL H 02E1 CB 1D RR L 02E3 CB 18 RR B 02E5 CB 19 RR C 02E7 CB 3C SRL H 02E9 CB 1D RR L 02EB CB 18 RR B 02ED CB 19 RR C 02EF C9 RET ; square unsigned 16bit ; DE <- input value ; DEBC -> value^2 ; ; ; X = 2^8*x1 + x0 ; X^2 = 2^16+x1^2 + 2^9*x1*x0 + x0^2 ; = 2^16*x1^2 + x0^2 + 2^8*(x1^2 + x0^2 - (x1 - x0)^2) ; = (2^16 + 2^8)*x1^2 + (2^8 + 1)*x0^2 - 2^8*(x1-x0)^2 ; = (2^8 + 1)*(2^8*x1^2 + x0^2) - 2^8*(x1-x0)^2 ; ; 3H-3L:2H-2L:1H-1L:0H-0L ; ; x1^2 <+++++++++> ; x1^2 <+++++++++> ; dif^2 <---------> ; x0^2 <+++++++++> ; x0^2 <+++++++++> 02F0 Square2B: 02F0 26 04 LD H,HIGH(MULTBL) 02F2 6B LD L,E 02F3 7E LD A,(HL) 02F4 08 EX AF,AF' 02F5 24 INC H 02F6 4E LD C,(HL) ; CA:x0^2 02F7 6A LD L,D 02F8 7A LD A,D 02F9 93 SUB E 02FA 30 02 JR NC,SquV20 02FC ED 44 NEG 02FE 56 SquV20: LD D,(HL) 02FF 25 DEC H 0300 5E LD E,(HL) ; DE:x1^2 0301 6F LD L,A ; abs(x1-x0) 0302 AF XOR A 0303 47 LD B,A 0304 EB EX DE,HL 0305 09 ADD HL,BC 0306 08 EX AF,AF' 0307 4F LD C,A 0308 08 EX AF,AF' 0309 45 LD B,L 030A 8C ADC A,H ; AHL=A3:A2:A1 030B 09 ADD HL,BC 030C CE 00 ADC A,0 030E EB EX DE,HL 030F 4E LD C,(HL) 0310 24 INC H 0311 46 LD B,(HL) ; BC:dif^2 0312 EB EX DE,HL 0313 ED 42 SBC HL,BC ; CY:0 0315 DE 00 SBC A,0 0317 57 LD D,A 0318 5C LD E,H 0319 45 LD B,L 031A 08 EX AF,AF' 031B 4F LD C,A 031C C9 RET ORG ($ + 255) AND 0FF00H ; 8bit ^ 2 table 0400 00 01 04 09 MULTBL: DB 000H,001H,004H,009H,010H,019H,024H,031H ; low byte 0404 10 19 24 31 0408 40 51 64 79 DB 040H,051H,064H,079H,090H,0A9H,0C4H,0E1H 040C 90 A9 C4 E1 0410 00 21 44 69 DB 000H,021H,044H,069H,090H,0B9H,0E4H,011H 0414 90 B9 E4 11 0418 40 71 A4 D9 DB 040H,071H,0A4H,0D9H,010H,049H,084H,0C1H 041C 10 49 84 C1 0420 00 41 84 C9 DB 000H,041H,084H,0C9H,010H,059H,0A4H,0F1H 0424 10 59 A4 F1 0428 40 91 E4 39 DB 040H,091H,0E4H,039H,090H,0E9H,044H,0A1H 042C 90 E9 44 A1 0430 00 61 C4 29 DB 000H,061H,0C4H,029H,090H,0F9H,064H,0D1H 0434 90 F9 64 D1 0438 40 B1 24 99 DB 040H,0B1H,024H,099H,010H,089H,004H,081H 043C 10 89 04 81 0440 00 81 04 89 DB 000H,081H,004H,089H,010H,099H,024H,0B1H 0444 10 99 24 B1 0448 40 D1 64 F9 DB 040H,0D1H,064H,0F9H,090H,029H,0C4H,061H 044C 90 29 C4 61 0450 00 A1 44 E9 DB 000H,0A1H,044H,0E9H,090H,039H,0E4H,091H 0454 90 39 E4 91 0458 40 F1 A4 59 DB 040H,0F1H,0A4H,059H,010H,0C9H,084H,041H 045C 10 C9 84 41 0460 00 C1 84 49 DB 000H,0C1H,084H,049H,010H,0D9H,0A4H,071H 0464 10 D9 A4 71 0468 40 11 E4 B9 DB 040H,011H,0E4H,0B9H,090H,069H,044H,021H 046C 90 69 44 21 0470 00 E1 C4 A9 DB 000H,0E1H,0C4H,0A9H,090H,079H,064H,051H 0474 90 79 64 51 0478 40 31 24 19 DB 040H,031H,024H,019H,010H,009H,004H,001H 047C 10 09 04 01 0480 00 01 04 09 DB 000H,001H,004H,009H,010H,019H,024H,031H 0484 10 19 24 31 0488 40 51 64 79 DB 040H,051H,064H,079H,090H,0A9H,0C4H,0E1H 048C 90 A9 C4 E1 0490 00 21 44 69 DB 000H,021H,044H,069H,090H,0B9H,0E4H,011H 0494 90 B9 E4 11 0498 40 71 A4 D9 DB 040H,071H,0A4H,0D9H,010H,049H,084H,0C1H 049C 10 49 84 C1 04A0 00 41 84 C9 DB 000H,041H,084H,0C9H,010H,059H,0A4H,0F1H 04A4 10 59 A4 F1 04A8 40 91 E4 39 DB 040H,091H,0E4H,039H,090H,0E9H,044H,0A1H 04AC 90 E9 44 A1 04B0 00 61 C4 29 DB 000H,061H,0C4H,029H,090H,0F9H,064H,0D1H 04B4 90 F9 64 D1 04B8 40 B1 24 99 DB 040H,0B1H,024H,099H,010H,089H,004H,081H 04BC 10 89 04 81 04C0 00 81 04 89 DB 000H,081H,004H,089H,010H,099H,024H,0B1H 04C4 10 99 24 B1 04C8 40 D1 64 F9 DB 040H,0D1H,064H,0F9H,090H,029H,0C4H,061H 04CC 90 29 C4 61 04D0 00 A1 44 E9 DB 000H,0A1H,044H,0E9H,090H,039H,0E4H,091H 04D4 90 39 E4 91 04D8 40 F1 A4 59 DB 040H,0F1H,0A4H,059H,010H,0C9H,084H,041H 04DC 10 C9 84 41 04E0 00 C1 84 49 DB 000H,0C1H,084H,049H,010H,0D9H,0A4H,071H 04E4 10 D9 A4 71 04E8 40 11 E4 B9 DB 040H,011H,0E4H,0B9H,090H,069H,044H,021H 04EC 90 69 44 21 04F0 00 E1 C4 A9 DB 000H,0E1H,0C4H,0A9H,090H,079H,064H,051H 04F4 90 79 64 51 04F8 40 31 24 19 DB 040H,031H,024H,019H,010H,009H,004H,001H 04FC 10 09 04 01 0500 00 00 00 00 DB 000H,000H,000H,000H,000H,000H,000H,000H ; high byte 0504 00 00 00 00 0508 00 00 00 00 DB 000H,000H,000H,000H,000H,000H,000H,000H 050C 00 00 00 00 0510 01 01 01 01 DB 001H,001H,001H,001H,001H,001H,001H,002H 0514 01 01 01 02 0518 02 02 02 02 DB 002H,002H,002H,002H,003H,003H,003H,003H 051C 03 03 03 03 0520 04 04 04 04 DB 004H,004H,004H,004H,005H,005H,005H,005H 0524 05 05 05 05 0528 06 06 06 07 DB 006H,006H,006H,007H,007H,007H,008H,008H 052C 07 07 08 08 0530 09 09 09 0A DB 009H,009H,009H,00AH,00AH,00AH,00BH,00BH 0534 0A 0A 0B 0B 0538 0C 0C 0D 0D DB 00CH,00CH,00DH,00DH,00EH,00EH,00FH,00FH 053C 0E 0E 0F 0F 0540 10 10 11 11 DB 010H,010H,011H,011H,012H,012H,013H,013H 0544 12 12 13 13 0548 14 14 15 15 DB 014H,014H,015H,015H,016H,017H,017H,018H 054C 16 17 17 18 0550 19 19 1A 1A DB 019H,019H,01AH,01AH,01BH,01CH,01CH,01DH 0554 1B 1C 1C 1D 0558 1E 1E 1F 20 DB 01EH,01EH,01FH,020H,021H,021H,022H,023H 055C 21 21 22 23 0560 24 24 25 26 DB 024H,024H,025H,026H,027H,027H,028H,029H 0564 27 27 28 29 0568 2A 2B 2B 2C DB 02AH,02BH,02BH,02CH,02DH,02EH,02FH,030H 056C 2D 2E 2F 30 0570 31 31 32 33 DB 031H,031H,032H,033H,034H,035H,036H,037H 0574 34 35 36 37 0578 38 39 3A 3B DB 038H,039H,03AH,03BH,03CH,03DH,03EH,03FH 057C 3C 3D 3E 3F 0580 40 41 42 43 DB 040H,041H,042H,043H,044H,045H,046H,047H 0584 44 45 46 47 0588 48 49 4A 4B DB 048H,049H,04AH,04BH,04CH,04DH,04EH,04FH 058C 4C 4D 4E 4F 0590 51 52 53 54 DB 051H,052H,053H,054H,055H,056H,057H,059H 0594 55 56 57 59 0598 5A 5B 5C 5D DB 05AH,05BH,05CH,05DH,05FH,060H,061H,062H 059C 5F 60 61 62 05A0 64 65 66 67 DB 064H,065H,066H,067H,069H,06AH,06BH,06CH 05A4 69 6A 6B 6C 05A8 6E 6F 70 72 DB 06EH,06FH,070H,072H,073H,074H,076H,077H 05AC 73 74 76 77 05B0 79 7A 7B 7D DB 079H,07AH,07BH,07DH,07EH,07FH,081H,082H 05B4 7E 7F 81 82 05B8 84 85 87 88 DB 084H,085H,087H,088H,08AH,08BH,08DH,08EH 05BC 8A 8B 8D 8E 05C0 90 91 93 94 DB 090H,091H,093H,094H,096H,097H,099H,09AH 05C4 96 97 99 9A 05C8 9C 9D 9F A0 DB 09CH,09DH,09FH,0A0H,0A2H,0A4H,0A5H,0A7H 05CC A2 A4 A5 A7 05D0 A9 AA AC AD DB 0A9H,0AAH,0ACH,0ADH,0AFH,0B1H,0B2H,0B4H 05D4 AF B1 B2 B4 05D8 B6 B7 B9 BB DB 0B6H,0B7H,0B9H,0BBH,0BDH,0BEH,0C0H,0C2H 05DC BD BE C0 C2 05E0 C4 C5 C7 C9 DB 0C4H,0C5H,0C7H,0C9H,0CBH,0CCH,0CEH,0D0H 05E4 CB CC CE D0 05E8 D2 D4 D5 D7 DB 0D2H,0D4H,0D5H,0D7H,0D9H,0DBH,0DDH,0DFH 05EC D9 DB DD DF 05F0 E1 E2 E4 E6 DB 0E1H,0E2H,0E4H,0E6H,0E8H,0EAH,0ECH,0EEH 05F4 E8 EA EC EE 05F8 F0 F2 F4 F6 DB 0F0H,0F2H,0F4H,0F6H,0F8H,0FAH,0FCH,0FEH 05FC F8 FA FC FE
    ★変更 2023/04/30 上記の共通項化することで約 15% スピードアップしました。



  4. 評価結果
     評価方法としては上記の3つの乗算処理に対して乗数及び被乗数を 0x0000 ~ 0x7fff の範囲で 0 から16 づつ増やしていった二重ループ処理の合計時間を計ってみました。従って乗算処理のみならず、乗数と被乗数の加算及び範囲チェック等のロジックも処理に含まれてしまいますが、実際のアプリでの使用状況により近づくのではないかと思います。

    No.methodtime[s]ratio
    1Normal method231.61.00
    2Minus square method
    (previous 1byte square)
    216.31.07
    3Minus square method
    (new 2bytes square)
    175.01.32
    ※2023/04/30 new method's ratio is up to 1.32 from 1.14

     色々書いてきた割にはあまり高速化していませんね^^;;;
     2バイト以上のバイト長の乗算計算は他の画期的なブレークスルーが無いと2倍以上の高速化は難しそうです。

     上記の処理時間測定時の画面のハードコピーも貼っておきます。Z80 が 20MHz で動作している自作ボードで CP/M 環境を使って ZSID でブレークを掛けて測定しました。時間測定自体は TeraTerm のマクロで自動的に計測しています。

    実行時間比較画面


★追記 2024/03/08
 「HD64180Compact(その6)16bit乗算処理」の記事に HD64180 の 8bit 乗算命令を使って作成した 16bit 乗算処理の演算速度について記載しました。



[TOP] [ 前へ ] 連載記事一覧 [ 次へ ]

nice!(0)  コメント(0) 

超小型Z80マイコン(その13)クロック20MHz化 [Z80]

 前回の記事でプリント基板化してほぼ Z80 のチップサイズと同程度のサイズの基板にできたことを書きましたが、今回は Z80 のクロックを12MHz から 20MHz に変更した場合の動作を確認しましたので結果を記録しておきたいと思います。

 但し、今回の3チップ構成での Z80 のチップサイズのプリント基板は弄らずに開発用に汎用基板で手配線した基板に 74HCU04 と 20MHz のクリスタルを追加して動作を確認して見ました。元々あった 12MHz のクロックは USB 機能を実現するために必要なので変更できないのです。
 一発では動作しませんでしたが、Z80 側のソフトウェアをタイミング調整することで 12MHz と 20MHz の両方で CP/M が動作するようになりました(上記以外のハードの変更は発生しませんでした)。

 下の写真は改造後の開発用基板です。Z80 のクロックはジャンパーピンで 12MHz と 20MHz のどちらか一方に切り替えられるようにしました。

開発用基板


 下図はもともとの 12MHz の状態で ASCIIART を実行した結果になります。

ASCIIART実行結果(12MHz)


 20MHz 動作では1分を切ることができました。上の 12MHz の時間からクロック反比例での予測時間は 57.4s(= 95.6 x 12 / 20)なのでほぼ計算値通りということになります。

ASCIIART実行結果(20MHz)



[TOP] [ 前へ ] 連載記事一覧 [ 次へ ]

nice!(0)  コメント(0) 

CP/M用hexローダーの製作 [Z80]

 CP/M-80 用のプログラムをアセンブリ言語で書く場合、パソコン上のエディタを使ってソースを編集したいものです。従来は、パソコンで編集したアセンブラソースを Z80 ボードに XMODEM で転送して動かしていました。
 しかし、パソコン上で CP/M エミュレータを使ってアセンブル&リンクして作成した HEX ファイルを TeraTerm 上にドラッグ&ドロップして実行できたらより効率的です。

 そこで CP/M 上で動作する HEX ローダーを作成してみました。このローダーの機能(特徴)は下記の通りです。
  1. コンソールから入力されるインテル HEX 形式のデータをメモリ上に展開します
  2. ロード完了後にHEX ファイルの先頭行のアドレスにジャンプします(ロードプログラムが自動起動します)
  3. CP/M の標準プログラムである 0100H から始まるものもダウンロードできるようにするために自身のコードを 0080H に移動してから実行します
  4. 高速化のために BIOS の機能を直にコールしています

 CP/M 側でこのローダーを起動後に、普通に作成した HEX ファイルを TeraTerm にドラッグ&ドロップすればロード後に自動的に実行されるので転送作業がかなり楽になりました。

 下記のリンクに公開しました。商用利用以外であれば自由に使用可能とします。
[history]
2023/05/15 Ver 0.03 set 00h to 0080H by skyriver
2023/03/26 Ver 0.02 can break by ^C
2023/03/26 Ver 0.01 published


 ソースも貼っておきます。

CP/M-80 用 HEX ローダー(アセンブラ)
;************************************************ ; HexLoader for CP/M ; Ver0.02 2023/03/26 can break by ^C by skyriver ; Ver0.03 2023/05/15 set 00h to 0080H by skyriver ;************************************************ 0001 WBOOTAD EQU 0001H ; wboot address 0080 PROGST EQU 0080H ; bios service No from wboot 0002 CONIN EQU 2 0003 CONOUT EQU 3 ; BDOS service 0005 BDOS EQU 0005H 0009 PrnStr EQU 9 ; print string 0000' ASEG ORG 0100H 0100 3A 0080 HexLd: LD A,(PROGST) 0103 B7 OR A 0104 28 06 JR Z,EXEC 0106 11 0146 LD DE,HlpMsg 0109 C3 00EB JP Puts 010C 21 0170 EXEC: LD HL,CODE_ST 010F 11 0080 LD DE,PROGST 0112 01 007D LD BC,CODE_EN - CODE_ST 0115 ED B0 LDIR 0117 2A 0001 LD HL,(WBOOTAD) 011A EB EX DE,HL 011B 21 0007 LD HL,3 * CONIN + 1 011E 19 ADD HL,DE 011F 4E LD C,(HL) 0120 23 INC HL 0121 46 LD B,(HL) 0122 ED 43 00F1 LD (CONINA),BC 0126 21 000A LD HL,3 * CONOUT + 1 0129 19 ADD HL,DE 012A 4E LD C,(HL) 012B 23 INC HL 012C 46 LD B,(HL) 012D ED 43 00F5 LD (CONOUTA),BC 0131 C3 0080 JP PROGST 0134 48 65 78 4C HexMsg: DB 'HexLoader Start',13,10,'$' 0138 6F 61 64 65 013C 72 20 53 74 0140 61 72 74 0D 0144 0A 24 0146 48 45 58 4C HlpMsg: DB 'HEXLOAD Ver 0.03 2023/05/15 by skyriver',13,10,'$' 014A 4F 41 44 20 014E 56 65 72 20 0152 30 2E 30 33 0156 20 32 30 32 015A 33 2F 30 35 015E 2F 31 35 20 0162 62 79 20 73 0166 6B 79 72 69 016A 76 65 72 0D 016E 0A 24 0170 CODE_ST EQU $ .phase PROGST 0080 00 NOP ; command parameter length 0081 11 0134 LD DE,HexMsg 0084 CD 00EB CALL Puts 0087 16 00 LD D,0 ; first flag 0089 CD 00F0 LOAD: CALL GETCH 008C FE 03 CP 'C' - 40H 008E CA 0000 JP Z,0 0091 FE 3A CP ':' 0093 20 F4 JR NZ,LOAD 0095 CD 00D5 CALL RDBYTE ; get byte count 0098 47 LD B,A 0099 CD 00E2 CALL RDWORD ; get address 009C 7A LD A,D 009D B7 OR A 009E 20 03 JR NZ,RDTYPE 00A0 16 01 LD D,1 ; clear flag 00A2 E5 PUSH HL ; set execute address 00A3 CD 00D5 RDTYPE: CALL RDBYTE ; get record type 00A6 5F LD E,A ; save type 00A7 FE 01 CP 1 00A9 28 14 JR Z,DSPTYP ; end of data 00AB B7 OR A 00AC 20 0C JR NZ,LdErr ; data record 00AE CD 00D5 RDDATA: CALL RDBYTE 00B1 77 LD (HL),A 00B2 23 INC HL 00B3 10 F9 DJNZ RDDATA 00B5 CD 00BF CALL DSPTYP 00B8 18 CF JR LOAD 00BA 21 00F7 LdErr: LD HL,ErrMsg ; error occur 00BD 18 2C JR Puts 00BF CD 00D5 DSPTYP: CALL RDBYTE ; read check sum 00C2 CD 00F0 CALL GETCH ; read delimitor 00C5 7B LD A,E ; get type 00C6 C6 30 ADD A,'0' 00C8 18 29 JR PUTCH ; read hex nible ; A -> data 00CA CD 00F0 RDNBL: CALL GETCH 00CD D6 30 SUB '0' 00CF FE 0A CP 10 00D1 D8 RET C 00D2 C6 F9 ADD A,10 + '0' - 'A' 00D4 C9 RET ; read byte data ; A -> byte data 00D5 CD 00CA RDBYTE: CALL RDNBL 00D8 07 RLCA 00D9 07 RLCA 00DA 07 RLCA 00DB 07 RLCA 00DC 4F LD C,A 00DD CD 00CA CALL RDNBL 00E0 B1 OR C 00E1 C9 RET ; read hex word ; HL -> data 00E2 CD 00D5 RDWORD: CALL RDBYTE 00E5 67 LD H,A 00E6 CD 00D5 CALL RDBYTE 00E9 6F LD L,A 00EA C9 RET ; display message ; DE <- message address 00EB 0E 09 Puts: LD C,PrnStr 00ED C3 0005 JP BDOS 00F0 C3 GETCH: DB 0C3H 00F1 0000 CONINA: DW 0 00F3 4F PUTCH: LD C,A 00F4 C3 DB 0C3H 00F5 CONOUTA: 00F5 0000 DW 0 00F7 65 72 72 0D ErrMsg: DB 'err',13,10,0 00FB 0A 00 .dephase 01ED CODE_EN EQU $ END Macros: Symbols: 0005 BDOS 01ED CODE_EN 0170 CODE_ST 0002 CONIN 00F1 CONINA 0003 CONOUT 00F5 CONOUTA 00BF DSPTYP 00F7 ERRMSG 010C EXEC 00F0 GETCH 0100 HEXLD 0134 HEXMSG 0146 HLPMSG 00BA LDERR 0089 LOAD 0009 PRNSTR 0080 PROGST 00F3 PUTCH 00EB PUTS 00D5 RDBYTE 00AE RDDATA 00CA RDNBL 00A3 RDTYPE 00E2 RDWORD 0001 WBOOTAD No Fatal error(s)


nice!(0)  コメント(3) 

Z80エクステンダの製作 [Z80]

 Z80関連で実機でちょっと実験したい場合に手軽に動かせる環境があると便利です。
 しかし、今まで作成したZ80ボードはバスや信号線をコネクタで出していないのでハードウェアの実験には使い辛いものになっています。

 「超小型Z80マイコン(その12)PCBへの部品実装」の記事で書いた下図の下駄が思いの外便利だったので、この考え方を踏襲した実験用の下駄(エクステンダ)を作成してみようと思います。

Z80 信号測定用の下駄


 実験ではプログラマブルなディバイスがあった方が便利なので GAL22V10 も実装することにします。
 回路は下図のように至って簡単なものでグランドのベタ化は行わず、電源のトラックを切断すれば他の 40 ピンCPUでも流用し易い様にしました。

Z80 エクステンダの回路図


 パターン図が下図で、これ以上無いほど単純なものになっています。

Z80 エクステンダパターン図


 トップ面の3D表示が下図です。Z80に重なっているピンコネクタは実際にはZ80の右隣のピンコネクタと共にボトム面に細ピンヘッダを付けて既存のZ80ボードのCPUソケットに差し込みます。
 各ICの一つのピンに付きピンコネクタが2個あるので、ブレッドボードの様にジャンパー線で信号を繋ぐことができます。実験に必要な追加部品はブレッドボードに付けで本ボードと接続するか、孫基板に必要部品を実装して本エクステンダのピンヘッダに接続します。

 ロジアナでの信号確認も容易なので結構便利なものになるのではないかと思います。

Z80 エクステンダ3D表示(トップ面)


 下図はボトム面の3D表示です。前述のようにボトム面にはZ80のソケットに刺さるように細ピンヘッダを付けます。また、実験で使うであろう3.3Vを生成するレギュレータもボトム面に実装しました。

Z80 エクステンダ3D表示(ボトム面)


nice!(0)  コメント(0)