セクタダンププログラム

戻る



   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

・解説

10番

 このプログラムを入力後、フリーエリアが600バイト無かった場合エラー表示して終了します。コマンドバッファとセクタバッファ合わせて500バイト強のメモリが必要だからです。

20〜30番

 変数Cにはコマンドバッファの番地を入れます。なんか妙な計算やってますが、コマンドパケット6バイトの中央4バイトが、ロングワード境界に合うようにするための計算です。境界があっていないとPOKE文一発でパラメータ指定することができません。
 変数Bにはセクタデータバッファの番地を入れます。以後、変数C,Bの値は変化しません。

100〜220番

 ひょっとして外付けRAMが必要になるかもしれないと思い、一応外付けRAMが使えるようにバスを設定しています。

230〜240番

 ポートEの設定です。デフォルトとして全端子’H’を出力しておき、ビット15だけ入力、他は全部出力にします。

300〜340番

 74LVC125をイネーブルにして、マルチメディアカードに80パルスのダミークロックを送ります。

350〜390番

 マルチメディアカードの/CSを’L’にしてCMD0を送り、レスポンスコードを受け取ります。これによりマルチメディアカードはSPIモードになります。なお、このプログラムは手を抜いてタイムアウトチェックをしていないので、マルチメディアカードが挿さって入ないと永遠にレスポンスコードを待ちつづけます。

400〜470番

 レスポンスコードとして0が返るまでCMD1を送りつづけます。ここでレスポンスコードに0でも1でもない値が返ってきた場合、回路の配線を間違っているか、またはマルチメディアカードが壊れています。

1000〜2000番

 メイン処理です。INPUT文でセクタ番号を入力し、その内容をダンプします。

10000〜10080番

 コマンドバッファの内容をマルチメディアカードに送ります。

11000〜11120番

 マルチメディアカードからレスポンスコードを受け取ります。前半、スタートビットを待ち、後半7ビットのレスポンスコードを受け取ります。最後にDUMMY8を呼び出して8クロックのダミークロックを送ります。

11200〜11260番

 DATA(マルチメディアカードのDI)を’H’にして8クロックのダミークロックを送ります。最初これをやらないでいたら、全然思ったように動いてくれず、死ぬほど悩みました。

11500〜11580番

 マルチメディアカードから1バイトのデータを受け取り、結果を変数Dに入れます。

12000〜12210番

 変数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クロックのダミークロックを送ります。