aboutsummaryrefslogtreecommitdiff
path: root/amforth-6.5/common/lib/hardware/spi-mmc.frt
blob: 7513e5834a5f15becd649c5e570c8034874c9d83 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98


: spi.init ( -- )
    +spi
    spi.mode0 spi.setmode
    -spi2x
;

: spi.mmc.dummy ( x -- )
    0 ?do $ff c!spi loop 
;

: spi.mmc.init ( -- )
    sd.init
    spi.init
    $11 spi.sd.dummy
;

\ every command has 48 bits=6bytes
: mmc.cmd ( n1 n2 ... n6 -- ) 
  -mmc 	20 ms	  \ de-select the card
  $FF c!spi       \ some random bits
  +mmc   20 ms 	  \ re-select the card
  $40 or 	  \ set bit 6 if the first byte assuming bit7 is 0
  &6 0 do c!spi loop ; \ send 48bits


\ response actions
\ there are different resonses: r1, r2, r3, r7
\ r1 is the single byte response ( 0 means no error)
\ 0 b6 b5 b4 b3 b2 b1 b0
\   |  |  |  |  |  |  |
\   |  |  |  |  |  |  In idle state
\   |  |  |  |  |  Erase Reset
\   |  |  |  |  Illegal Command
\   |  |  |  Command CRC error
\   |  |  Erase Sequence Error
\   |  Address Error
\   Parameter Error

\ waiting for cmd response
: mmc.cresp ( -- c|-1 )
    $FF 0 do
      c@spi dup $80 and 0=   \ bit7=0?
      if unloop exit then  \ -- c, 0=ok
      drop                 \ --
    loop -1 ;              \ -- -1, timeout


\ waiting for data response
: mmc.dresp ( -- c|-1 )
    $FF 0 do
      c@spi dup $11 and 1 =  \ xxx0ccc1
      if
        $0F and unloop exit \ -- c, 5=ok
      then
      drop                 \ --
    loop -1 ;              \ -- -1, timeout

: R1 ( -- f ) 
  mmc.cresp
;

: cmd0    ( -- f ) $95 0 0 0 0 0 mmc.cmd R1 1 = ;   \ GO_IDLE_STATE - reset 
: cmd1    ( -- f ) $ff 0 0 0 0 1 mmc.cmd R1 0= ;  	 \ SEND_OP_COND init
: cmd16   ( -- )   $FF 0 0 2 0 16 mmc.cmd R1 drop ; \ SET_BLOCKLEN default 512 

\ waiting for data token
 
: mmc.wait_data_token ( -- f ) 0 16 0 do c@spi $FE = if drop true leave then loop ; 

\ read CSD and CID into a 16 byte buffer
16 buffer: mmc.infoblock

: mmc.readblock ( addr len -- )
  mmc.wait_data_token 
  if
    bounds do c@spi i c! loop
  else abort" Could not read MMC data block"
  then ;

: cmd9    ( -- )   $ff 0 0 0 0  9 mmc.cmd R1 mmc.infoblock 16 mmc.readblock ; \ SEND_CSD
: cmd10   ( -- )   $ff 0 0 0 0 10 mmc.cmd R1 mmc.infoblock 16 mmc.readblock ; \ SEND_CID

\ READ SINGLE BLOCK
: cmd17 ( addr n -- f )
   >r $ff ( CRC ) r> s>d 17 mmc.cmd R1 mmc.readblock ;

: mmc.writeblock ( addr len -- )
  mmc.wait_data_token 
  if
    bounds do i c@ c!spi loop
  else abort" Could not write MMC data block"
  then ;

\ WRITE SINGLE BLOCK (n=512 bytes)
: cmd24 ( addr n -- f )
  >r $ff ( CRC ) r> s>d 24 mmc.cmd R1 mmc.writeblock ;