EEPROM アクセス実装検討中

今回は本当に開発メモ。

カートリッジを分解してプローブをあてたら普通の 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 使えたっけ?

というわけで

大変。