10 IF(FRE(0)<600) PRINT "Out of memory.":END 20 C=FRE(1)+4 OR 3 ' COMMAND BUFFER 30 B=C+9 ' DATA BUFFER 100 POKE &BCR1 ,%$600E ' CS0 SPACE 8BIT 110 POKE &BCR2 ,%$FDEE ' 1 WAIT READ AFTRE WRITE 120 POKE &WCR1 ,%$FFF3 ' 3 WAIT 130 POKE &PACRL3,%$03FF ' PORT A:USE SCI2,SCI3,A5..A0 140 POKE &PACRL1,%$1115 ' PA14,12,10=RD,WRL,CS 150 POKE &PACRL2,%$5000 160 POKE &PBCR1 ,%$0000 ' PORT B:USE A17,A16 170 POKE &PBCR2 ,%$0005 180 POKE &PDCRL2,%$0000 ' PORT D:USE D7..D0 190 POKE &PDCRL1,%$00FF 200 POKE &PECRH ,%$0FFF ' PORT E:USE A15..A6 210 POKE &PECRL1,%$0000 220 POKE &PECRL2,%$FF00 230 POKE &PEDRL ,%$FFFF ' PORT EL:INITIAL DATA IS ALL 'H' 240 POKE &PEIORL,%$7FFF ' PORT EL:BIT15=IN,OTHER OUT 300 ' 310 BCLR &PEDRL,%11 ' BUFFER(LVC125) ENABLE 320 FOR I=1 TO 80 ' 80 PULSES 330 BCLR &PEDRL,%12:BSET &PEDRL,%12 ' DUMMY CLOCK 340 NEXT 350 BCLR &PEDRL,%14 ' /CS='L' 360 POKE C,$40,0,0,0,0,$95 ' CMD0( GO IDLE STATE ) 370 GOSUB *PUTCMD 380 GOSUB *GETRES 390 BSET &PEDRL,%14 ' /CS='H' 400 REPEAT 410 BCLR &PEDRL,%14 ' /CS='L' 420 POKE C,$41,0,0,0,0,1 ' CMD1( SEND OP COND ) 430 GOSUB *PUTCMD 440 GOSUB *GETRES 450 BSET &PEDRL,%14 ' /CS='H' 460 UNTIL (R=0) OR (R>1) 470 IF(R>1) PRINT "Bad response code : ",HEX(R):END 1000 WHILE 1 1010 INPUT "Sector No.?(-1:END)",S 1020 IF(S<0) BREAK 1030 GOSUB *GETBLK 1040 IF(R<>0) { 1050 PRINT "Bad response code : ",HEX%(R) 1060 }{ 1070 DUMP B,512 1080 } 1090 WEND 2000 END 10000 ' 10010 *PUTCMD:LOCAL I,J 10020 FOR I=0 TO 5 10030 FOR J=7 TO 0 STEP -1 10040 BCLR &PEDRL,%12 ' CLK='L' 10050 BSET &PEDRL,%13,BTST@(C+I,J) ' PUT DATA 10060 BSET &PEDRL,%12 ' CLK='H' 10070 NEXT 10080 NEXT:RETURN 11000 ' 11010 *GETRES:LOCAL I 11020 REPEAT 11030 BCLR &PEDRL,%12 ' CLK='L' 11040 BSET &PEDRL,%12 ' CLK='H' 11050 UNTIL BTST%@(&PEDRL,15)=0 ' WAIT FOR START BIT 11060 R=0 11070 FOR I=1 TO 7 11080 BCLR &PEDRL,%12 ' CLK='L' 11090 BSET &PEDRL,%12 ' CLK='H' 11100 R=R+R+BTST%@(&PEDRL,15) ' GET DATA 11110 NEXT 11120 GOSUB *DUMMY8:RETURN ' RETURN R=RESPONSE CODE 11200 ' 11210 *DUMMY8:LOCAL I ' 8 PULSES DUMMY CLOCK 11220 BSET &PEDRL,%13 ' DATA='H' 11230 FOR I=0 TO 7 11240 BCLR &PEDRL,%12 ' CLK='L' 11250 BSET &PEDRL,%12 ' CLK='H' 11260 NEXT:RETURN 11500 ' 11510 *GETBYTE 11520 LOCAL I 11530 D=0 11540 FOR I=0 TO 7 11550 BCLR &PEDRL,%12 ' CLK='L' 11560 BSET &PEDRL,%12 ' CLK='H' 11570 D=D+D+BTST%@(&PEDRL,15) ' GET DATA 11580 NEXT:RETURN ' RETURN D=DATA 12000 ' 12010 *GETBLK:LOCAL I,J,D 12020 BCLR &PEDRL,%14 ' /CS='L' 12030 POKE C,$51,#S*512,1 ' CMD17( READ SINGLE BLOCK ) 12040 GOSUB *PUTCMD 12050 GOSUB *GETRES 12060 IF(R=0) { 12070 REPEAT 12080 GOSUB *GETBYTE 12090 UNTIL D<>$FF ' WAIT FOR DATA OR ERROR TOKEN 12100 IF(D<>$FE) { 12110 R=D*256 ' RETURN R=ERROR TOKEN*256 12120 }{ 12130 FOR I=0 TO 513 ' 514 BYTES( DATA512 + CRC2 ) 12140 GOSUB *GETBYTE 12150 POKE B+I,D 12160 NEXT 12170 } ' RETURN R=0 12180 } 12190 GOSUB *DUMMY8 12200 BSET &PEDRL,%14 ' /CS='H' 12210 RETURN |
このプログラムを入力後、フリーエリアが600バイト無かった場合エラー表示して終了します。コマンドバッファとセクタバッファ合わせて500バイト強のメモリが必要だからです。
変数Cにはコマンドバッファの番地を入れます。なんか妙な計算やってますが、コマンドパケット6バイトの中央4バイトが、ロングワード境界に合うようにするための計算です。境界があっていないとPOKE文一発でパラメータ指定することができません。
変数Bにはセクタデータバッファの番地を入れます。以後、変数C,Bの値は変化しません。
ひょっとして外付けRAMが必要になるかもしれないと思い、一応外付けRAMが使えるようにバスを設定しています。
ポートEの設定です。デフォルトとして全端子’H’を出力しておき、ビット15だけ入力、他は全部出力にします。
74LVC125をイネーブルにして、マルチメディアカードに80パルスのダミークロックを送ります。
マルチメディアカードの/CSを’L’にしてCMD0を送り、レスポンスコードを受け取ります。これによりマルチメディアカードはSPIモードになります。なお、このプログラムは手を抜いてタイムアウトチェックをしていないので、マルチメディアカードが挿さって入ないと永遠にレスポンスコードを待ちつづけます。
レスポンスコードとして0が返るまでCMD1を送りつづけます。ここでレスポンスコードに0でも1でもない値が返ってきた場合、回路の配線を間違っているか、またはマルチメディアカードが壊れています。
メイン処理です。INPUT文でセクタ番号を入力し、その内容をダンプします。
コマンドバッファの内容をマルチメディアカードに送ります。
マルチメディアカードからレスポンスコードを受け取ります。前半、スタートビットを待ち、後半7ビットのレスポンスコードを受け取ります。最後にDUMMY8を呼び出して8クロックのダミークロックを送ります。
DATA(マルチメディアカードのDI)を’H’にして8クロックのダミークロックを送ります。最初これをやらないでいたら、全然思ったように動いてくれず、死ぬほど悩みました。
マルチメディアカードから1バイトのデータを受け取り、結果を変数Dに入れます。
変数Sが指すセクタのデータをセクタデータバッファに読み込みます。
12030番でコマンドバッファにブロックリードコマンドを作っています。このPOKE文でS*512の値を一発で書き込みたいがために20番の計算をやったわけです。ところで、最初はここでセクタ番号を指定するものと思っていましたが、実はバイト単位のポジションを指定するのが正しいんですね。1セクタ512バイトだからSに512をかけています。
12050番でレスポンスコードを受け取ります。これで返ってきたのが0ならとりあえず「コマンドは受け入れられた」わけですが、まだ安心はできません。
12070〜12090番でデータトークンまたはエラートークンを待ちます。この時点でエラーが返ってくることもあるわけです。返ってきた値が$FFでも$FEでもない場合、それはエラートークンですのでデータは受け取れません。
返ってきた値が$FEならそれはデータトークンですので、12130〜12160番で514バイトのデータを受け取ります。SPIモードの場合CRCはいらないのですが、CRCデータのぶんのクロック(2バイト、16クロック)も出す必要があるようです。
最後に、エラーでも正常でも8クロックのダミークロックを送ります。