今回は本当に開発メモ。
カートリッジを分解してプローブをあてたら普通の I2C 信号が来てた。 read は 1 byte アクセスを何度もやる感じで、 sequentical read をなぜかやらないがちょっと気になる。たぶん、プログラムが適当ということにしておこう。
スクリプトを書き出して、追加が必要な関数を把握する。
const I2C_ADDRESS_WRITE = 0; const I2C_ADDRESS_READ = 0x40; function cpu_ram_access(d, pagesize, banksize) { cpu_write_after_wait(d, 1); i2c_start(d); i2c_address(d, 0, I2C_ADDRESS_WRITE); i2c_start(d); //read sequencial i2c_address(d, 0, I2C_ADDRESS_READ); for(local i = 0; i < pagesize * banksize; i++){ for(local k = 0; k < 8; k++){ cpu_write(d, 0x800d, 0x60); cpu_write(d, 0x800d, 0xe0); cpu_read_bit_msb(d, 0x6000, 4); } //send ack cpu_write(d, 0x800d, 0); cpu_write(d, 0x800d, 0x40); } //write sequencial /* i2c_address(d, 0, I2C_ADDRESS_WRITE); for(local i = 0; i < pagesize * banksize; i++){ for(local k = 0; k < 8; k++){ local n = 0; cpu_write(d, 0x800d, n); if(cpu_fetch_msb(d) != 0){ n |= 1 << 6; } cpu_write(d, 0x800d, n); n |= 1 << 5; cpu_write(d, 0x800d, n); } i2c_ack_wait(d); } */ i2c_stop(d); }
cpu_write_after_wait
I2C EEPROM はアクセススピードが遅い方なので、 write の後に wait をいれたほうがいいかもしれない。しかし、USB のパケットを受け取って IO を書いてたら結構いい時間を消費するのでいらん気もする。
READ/WRITE のパラメータを得る方法を作る
read/write sequencial で分岐させないとだめ。RAM 以外だとこうなる。
cpu_read_bit_msb
指定アドレスの指定 bit を取り込んで 8bit 単位でアドレス+= 1。 msb か lsbでシフト方向が変わる。 msb/lsb じゃなくて right/left のほうがいいのか?
cpu_fetch_msb
cpu_write_bit_msb みたいにすると実装に無理があったので fetch なるものを用意。write 用バッファから1bitとりだす。これは msb/lsb でよさそう。こちらも8bitごとにバッファアドレス += 1
偽 cpu_read
これが一番の悩ませどころ。
function i2c_ack_wait(d) { do{ cpu_write(d, 0x800d, 0x00); cpu_write(d, 0x800d, 0x20); cpu_write(d, 0x800d, 0xa0); local n = cpu_read(d, 0x6000); }while(n != 0x10); }
busy flag を取って来ないといけない。このため取り出したデータをスクリプト内で扱う必要がある。anago はスクリプト記述に矛盾がないように本番前に1回通すのだが、テスト時にこのループで無限ループしない仕組みも作らないといけない。
そもそも Squierrel って do-while 使えたっけ?
というわけで
大変。