287XLへの入出力操作は次のようなコードで行えます。特に変わったことはしておらず、データシート通りに信号をH やLにするだけです。
#define FWAIT while(!(PINC & 0b00000001)) #define WAIT_PRQ while(!(PINC & 0b00000010)) #define ACK_PRQ PORTA = PORTA & 0b11110111 #define FREE_PRQ PORTA = PORTA | 0b00001000 nsigned din() { DDRF = 0x00; DDRK = 0x00; return (PINF << 8) | PINK; } void dout(unsigned data) { DDRF = 0xff; DDRK = 0xff; PORTF = data >> 8; PORTK = data & 0xff; } void wrOp(unsigned opc) { unsigned swapped; swapped = (opc << 8) | (opc >> 8); PORTA = 0b11101000; /* NPS2=H CMD0=L CMD1=L NPS#=L */ dout(swapped); /* opc */ PORTA = 0b10101000; /* NPS2=H CMD0=L CMD1=L NPS#=L NPWR#=L */ PORTA = 0b01101000; /* NPS2=L CMD0=L CMD1=L NPS#=L NPWR#=H */ } void wrData(unsigned data) { PORTA = 0b11101001; /* NPS2=H CMD0=H CMD1=L NPS#=L */ dout(data); /* opc */ PORTA = 0b10101001; /* NPS2=H CMD0=H CMD1=L NPS#=L NPWR#=L */ PORTA = 0b01101001; /* NPS2=L CMD0=H CMD1=L NPS#=L NPWR#=H */ din(); } unsigned rdData() { unsigned data; PORTA = 0b11101001; /* NPS2=H CMD0=H CMD1=L NPS#=L */ PORTA = 0b11001001; /* NPS2=H CMD0=H CMD1=L NPS#=L NPRD#=L */ data = din(); /* read data */ PORTA = 0b01101001; /* NPS2=L CMD0=H CMD1=L NPS#=L NPRD#=H */ return data; }
287のコマンドごとに入出力関数を呼び出すコードを書いてくのはかなり面倒なので、書きやすいように287のコマンドを下のようにマクロで定義しています。
#define FISUB16(d) wrOpWr1(0xda20, (d)) #define FSUB(i) wrOpc(0xd8e0 | ((i) & 0x03)) /* FSUB ST, ST(i) */ #define FSUBd(i) wrOpc(0xdce8 | ((i) & 0x03)) /* FSUB ST(i), ST */ void wrOpc(unsigned opc) { wrOp(opc); FWAIT; } void wrOpWr1(unsigned opc, unsigned d) { wrOp(opc); WAIT_PRQ; ACK_PRQ; wrData(d); FREE_PRQ; FWAIT; }
試しに、287XLを使ってマンデルブロ集合のASCIIARTを動かすコードを書いてみたところ、 実行時間は2.6秒でした。
287XLを使わずソフトウェアで実行すると、Arduino Megaは結構速く、2.1秒程度で実行できてしまいます。Arduinoに接続した場合、I/Oポートを介して操作するオーバーヘッドが大きかったり、1コマンドを実行するためにステップ数が多くなるので、あまり速くできないようです。
GitHubにコードを公開しておきます。https://github.com/4sun5bu/287Hack