e-tipsmemo

ごった煮

Rust レイトレーシング ④ 球体


sphereとshape_opを追加した。

shpereは色を持つ。ついでにColorにnewメンバ関数を追加ておく。


光が当たったところを記録する。hit関数によって返される。当たった点pと法線ベクトルnと光源からの距離t。


後々のためにHIT Traitを定義。「HIT Traitを実装しているものを引数にとる。」のようにできる。
hitはhitヒットしていないかもしれないので、Option型で返す。
rustbyexample.com
ダメそうだったらNoneを返す。


HIT Traitの実装。球と直線が交わるか計算。
使わない引数・変数は _hogeとするか、そのものを_にするかしないと、コンパイラから警告がでる。


matchを使うことで、Optionで帰ってくるものを綺麗に書ける。いちいちboolを返してtrueなら~という二度手間感がない。



球を追加する。

実行結果。
f:id:katakanan:20180130105946p:plain:w300
f:id:katakanan:20180130110736p:plain
よさそう。


Programming Rust: Fast, Safe Systems Development

Programming Rust: Fast, Safe Systems Development

EZ-USB FX2 Bulkloop ③

e-tipsmemo.hatenablog.com


BulkloopのTD_pollを見ていく。

BulkloopではPCからinのEPに送られてきたデータをoutのEPからPCに送り返すものであった(はず)

読み取り先のEPのステータスをチェックして


書き込み先のEPのステータスをチェックする。

EPのバッファー間でコピーする方法として、AUTOPTRを利用している。
EPのFIFOの先頭アドレスを、読み込み書き込みするたびにさしているアドレスがインクリメントされる、AUTOPTRセットしてforで回している。

互換性保持のために冗長にしている?
16bitなので

EP8のバッファのカウンタをコピーしたサイズ値にする

EP4BCLの8bit目はSKIPビットというもので
p93による。

Rust レイトレーシング ③ マルチスレッド

e-tipsmemo.hatenablog.com

続き。

見通しをよくするためにcolor構造体を利用することにした。

各色は0.0~1.0しか取らないので適当にclampしてやる必要があるのでそういった細かい関数は

へ書くことにした。



色は基本的にシーン内で計算することにした。



マルチスレッドになっているものを可変にする。
実行時引数を利用する。


それほど難しいことはなく、以下を参考にすればよい。
rustbyexample.com

ついでに時間を測り始めた。

time crateが必要。
Rust multithread 実行時間測定 - e-tipsmemo

cargoで引数を渡すには--を付ける。

$ cargo run -- 1
    Finished dev [unoptimized + debuginfo] target(s) in 0.26 secs
     Running `target/debug/rust_ray01 1`
Hello, world!
thread:1
time:5031427000 ns
$
$ cargo run -- 3
    Finished dev [unoptimized + debuginfo] target(s) in 0.0 secs
     Running `target/debug/rust_ray01 3`
Hello, world!
thread:3
time:1781288000 ns

速くなっている。。?

結果は変わらない。
f:id:katakanan:20180121110300p:plain:w300


Programming Rust: Fast, Safe Systems Development

Programming Rust: Fast, Safe Systems Development

EZ-USB FX2 Bulkloop ②

e-tipsmemo.hatenablog.com

の続き。


CPUのクロックを48MHzに設定
http://www.cypress.com/file/126446/download
p83にクロックツリーの・ようなものがある。

The slave FIFO interface can be clocked from either an
internal or an external source. The EZ-USB’s internal clock
source can be configured to run at either 30 or 48 MHz, and
it can optionally be output on the interface clock (IFCLK) pin.
If the EZ-USB is configured to use an external clock source,
the IFCLK pin can be driven at any frequency between 5
MHz and 48 MHz. On a hard reset, the EZ-USB defaults to
the internal source at 48 MHz, normal polarity, with the
IFCLK output disabled. See Figure 9-6

IFCONFIGの8bit目はリセット時に1なので以下のようなクロックとなる。外部のロジックはIFCLK(かIFCLKの反転したもの)と同期して動かす。
f:id:katakanan:20180114143435p:plain

f:id:katakanan:20180103104645p:plain
この設定のいずれかになるように設定する。バッファのサイズが足りない場合は無視される。
EPを設定する場合は使うものから設定する
Config 11ならEP2(enable, size:1024 :Buf:3)->EP8(enable, size:512, Buf:2)->EP4(disable)->EP6(disable)
各設定の間にはレジスタに値が設定されるまで待つためのクロックサイクルが必要なので
SYNCDELAYを入れる。

AUTOPTRとは

■Set APTRnINC=0 to freeze the address pointer, APTRnINC=1 to automatically increment it for every read or write of an XAUTODATn register. This bit defaults to ‘1’, enabling the auto increment feature.
■To enable the autopointer, set APTREN=1. Enabling the Autopointers has one side-effect: any code access (an instruction
fetch, for instance) from addresses 0xE67B and 0xE67C return the AUTODATA values, rather than the code-memory values at these two addresses. This introduces a two-byte ‘hole’ in the code memory.

XAUTODATnを読んでいくとアドレスをインクリメントしてくれる機能らしい。

SlaveFIFOで使うならクロックの設定とEPの設定以外変更の必要はなさそう。(EPの設定もデフォルトで十分かもしれない)

Rust レイトレーシング ② レイを飛ばす

e-tipsmemo.hatenablog.com


前回は画像を表示することが可能になったのでRayを飛ばす。
必要なものはカメラとスクリーンとそれらをまとめるシーンとレイ

レイトレーシングをいろいろと検索すると何故かz軸正の方向から原点を見下ろすシーンが多いようだが理由がよくわからない。
なので今回はカメラをどの位置においても良いように書いた。

座標・方向・右手方向・fov
Vector3やPoint3の型をTとしてジェネリックに書くこともできるが、
今回はシンプルにするためにとりあえずf64で行う。

デフォルトコンストラクタなどはないので自分でそれ用のメソッドを実装する。
(たいていnewという名前で実装してあったりする。)
カメラ位置と見ている点からカメラを決定するようにした。



スクリーンはカメラの視線と直行していてほしいので角度を求めてその分だけ傾ける。
f:id:katakanan:20180113233357p:plain
Rotation3で指定したベクトルを軸として、thetaだけ回転する回転行列を計算でき、それをz軸正方向ベクトルに掛けることで
スクリーンの3次元空間中でのyベクトルを求める。xベクトルはカメラの視線とyの外積をとった。(rightと平行でもある)

nalgebraのdocument
nalgebra

fovはググればたくさん説明があるので省略。
スクリーンとカメラの距離が1であることを前提にしている。


それらをまとめるシーンと指定されたスクリーン上の座標からレイを求める関数。


特筆すべきことはない。

同じscene構造体を複数のスレッド間で共有するためには

のArcが必要


宣言時にArcポインタ?でくくって
スレッド引数時にcloneする。
(よってArcによって共有されるオブジェクトはClone Traitを実装していなければならない(ような気がする))

レイを飛ばす部分

projectionはRayをスクリーンへ投影したときのu,v座標を得る関数で結局tはvと同じである。
v座標の割合によってグラデーションさせた(lerp関数)色を書き込みreturnする。

結果は以下のようになった。
スレッド数を複数にしても同じである。

f:id:katakanan:20180114103130p:plain:w300

Programming Rust: Fast, Safe Systems Development

Programming Rust: Fast, Safe Systems Development

Rustでレイトレーシング 1.5 画像出力

e-tipsmemo.hatenablog.com

の補足。

後々にレイトレーシングをマルチスレッド化していこうと思っているので
まずは画像出力をマルチスレッド化した。

階層はこのような感じ
f:id:katakanan:20180105233635p:plain
実行結果は以下の様になる
f:id:katakanan:20180105002231p:plain:w300
上から3つのスレッドがそれぞれ画素を計算している事がわかる。

最終的なイメージも渡してmutexのlockをして各スレッドから一枚絵を作る方法もあるが、
とりあえず今回の方向性では採用しないことにした。

画像の分割は縦のピクセルを等分して余った分は最後に含めているので
スレッド数が7のときは
画像サイズが
800x85が6個と800x90を1個計算して
最後にまとめる。

Programming Rust: Fast, Safe Systems Development

Programming Rust: Fast, Safe Systems Development

EZ-USB FX2 Bulkloop

fw.cを見る

初期化があった後に(Bulkloop.cにある)

ここでDevice Descriptorをそれぞれの構造体へ読む。
EP0でコントロールコマンドが来た時に必要。

で割り込みを有効にしているらしいが、関数呼び出しかと思わせておいてdefineで定義されている単なるレジスタへの代入。

#define EZUSB_IRQ_ENABLE()   EUSB = 1
#define EZUSB_IRQ_DISABLE()   EUSB = 0

(なぜこのように書いているか)
レジスタへのアクセスは8bit単位はもちろん
SDCCへの拡張命令?でその中のビット単位でのアクセスが可能のようだ

__sfr __at (0xE8) EIE     ; // EIE Bit Values differ from Reg320
          /*  EIE  */
          __sbit __at (0xE8+0) EUSB     ;
          __sbit __at (0xE8+1) EI2C     ;
          __sbit __at (0xE8+2) EIEX4    ;
          __sbit __at (0xE8+3) EIEX5    ;
          __sbit __at (0xE8+4) EIEX6    ;

この幾つかのレジスタは8051には無いSpecial Function Registerとして機能しており、
Cypress EZ-USB FX2LP Technical Reference Manual
のp211には書いていなかった。項目が別にある。
f:id:katakanan:20180107020317p:plain

次も割り込みを許可する

これもレジスタアクセスだが8051のオリジナルレジスタである。
書き方がSFRの代入とは違うがこれはビット単位ではアクセスできない?代わりにビット代入のための定義がある。

/* Interrupt 2 & 4 Setup (INTSETUP) */
#define bmAV2EN      bmBIT3
#define INT4IN       bmBIT1
#define bmAV4EN      bmBIT0
#define bmBIT0   0x01
#define bmBIT1   0x02
#define bmBIT2   0x04
#define bmBIT3   0x08
#define bmBIT4   0x10
#define bmBIT5   0x20
#define bmBIT6   0x40
#define bmBIT7   0x80

これはUSB Control and Status Registerのようで、

http://www.cypress.com/file/113936/download
p6によると、

USBCSレジスタ (USB制御およびステータス) の2つの制御ビットは、DISCONおよびRENUMというReNumerationプロセスを制御します。
USBの切断をシミュレートするには、ファームウェアはDISCONを1にセットします。
再接続するには、 ファームウェアはDISCONを0にクリアします。
再接続前に、ファームウェアはRENUMビットを設定またはクリアし、
ファームウェアとデフォルトのUSBデバイスのいずれがエンドポイントゼロによってデバイス要求を処理するかを示します。
RENUMが0のときは、デフォルトのUSBデバイスがデバイス要求を処理し、RENUMが1のときは、 ファームウェアが要求を処理します。

コメントにはとくに何かが変わるわけではないとあるのでそのまま。

CKCON はSFRのうちの一つでClock Control Register
各タイマーのクロックソースを選択するようだ。

Stretchとは何だといことだが、
http://www.cypress.com/file/126446/download
のp177の
12.1.2
Stretch Memory Cyclesに書いてある。
Stretch Valueを入れることで外部の遅いもののMOVXで書き込むときに追加のクロックサイクルを調節してくれる?

ストレッチメモリサイクル機能により、EZ-USBファームウェアはプログラムメモリアクセスではなく、
データメモリアクセスの速度を調整することができます。
標準ストローブ幅タイミングを含む詳細は、テクニカルリファレンスマニュアルの12.1.2節をご参照ください。
アドレスサイクル幅はこれらから解釈することができます。

(アセンブリを見たらわかる気がする。が後で)

Sleepをfalseにクリアする
割り込みでSleepがTrueになるとメインループでスリープmodeに入る(のがオリジナルのコードだったが必要ないので消した。)

メインループ

GotSUDはグローバルな変数でEP0でコマンドが送られてきたときに割り込みでTrueになる。消してはいけない。

諸々の設定は最初にあったTD_Init()内にあるらしいので次回はそことTD_Poll(),SetupCommand()を見てゆく。