今回は本当に開発メモ。
カートリッジを分解してプローブをあてたら普通の 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 使えたっけ?
というわけで
大変。