include "modedefs.bas"
DEFINE OSC 10 'Adjust to suit your design
ADCON1 = 7 'Adjust ADC for your needs
OPTION_REG.7 = 1 'PORTB internal pull-ups = off (0=on)
' Set receive register to receiver enabled
DEFINE HSER_BAUD 19200 'Baud = 19200
DEFINE HSER_CLROERR 1 'Hser clear overflow automatically
XON con $11
XOFF con $13
'I2C Variables
ctl con $A0 'EEPROM control code
edata var BYTE 'Data byte to be written
'For the SDMM3F and MMSD3F Boards
'***************** PIC PIN ASSIGNMENTS *****************
TRISC = %10010000 ' Set data-direction on PortC for SPI,UART and
I2C
'I2C Eeprom Pins
scl var PORTC.0 'I2C SCL for ext eeprom
sda var PORTC.1 'I2C SDA for ext eeprom
'SD/MMC Connections
SCK var PORTC.3 ' Clock pin SD/MMC pin 5
SO var PORTC.4 ' Data from SD/MMC pin 7
SS var PORTC.2 ' Slave select pin 1
SI var PORTC.5 ' Data to SD/MMC pin 2
'Added Jan 2005
trisA.0=0
Cts var portA.0
low cts
'Test CTS pin
'tmpy:
'low cts
'pause 1000
'high cts
'pause 1000
'goto tmpy
'***************** General MMC Variables used
**************************
'Variables used (may be some that are no longer in use --
haven't cleaned up as yet!)
mmc_status var byte
mmc_status = $0000
addr var word
addr_H var word ' MMC Address is a 32 bit address, addr_h is
bits 31-16
addr_L var word ' and addr_l is is bits 0-15
arg0 var byte ' args used
arg1 var byte
arg2 var byte
arg3 var byte
arg4 var byte
cmd var byte 'command var
crc var byte 'crc var
dat var byte 'data var
i var byte 'counter var
x var word 'counter var
y var byte 'counter var
j var byte
c var byte
res var byte 'response var
reswr var byte 'response w/r
res2 var word 'response var
hex_nibble var byte
erase_flag var byte
erase_flag = 0
idx var byte
eaddr1 var word 'ext eeprom addr vars
eaddr2 var word
e_addr var word
in_dat var byte 'Serial vars
chk var byte
cntr var byte
in_array var BYTE[64] 'In coming array
in_ctl var BYTE[10] 'In coming control array
buff_count var BYTE 'General count
carry_flag var STATUS.0
addr = $0000 'Used for eeprom etc
chk_flag var byte
w_tmp1 var word
w_tmp2 var word
w_addr var word
file_info var byte[12]
cnt var byte
'Diagnostic LEDs
wr_led var PORTB.7
err_led var PORTB.6
ok_led var PORTB.5
TRISB.7 = 0
TRISB.6 = 0
TRISB.5 = 0
pause 500 'Let things settle a bit
'For debugging
'serout2 out_pin,ser_baud,["Start",10,13] 'Display on terminal
hserout ["Trying....",10,13]
' ***** Jump over the subroutines **************
goto main
'Initialize MMC
'Initialize MMC
init_mmc:
pause 500
chk_flag = 0 : w_tmp2 = 0
hserout ["Trying...",10,13]
SS = 1
dat =$ff
cnt = 10
gosub shiftout_dat
ss = 0
pause 50
cmd = $40 'MMC Command 0
crc = $95
cmd0:
dat = cmd
Shiftout SI, SCK, MSBFIRST,[dat]
dat = 0
cnt = 4
gosub shiftout_dat
dat = crc
Shiftout SI, SCK, MSBFIRST,[dat]
chk = 1
gosub chk_res
if chk_flag = 1 then hserout ["No response",10,13]
ss = 1
pause 50
ss = 0
if chk_flag = 1 then init_mmc
HSerout ["Cmd0 OK",10,13]
CMD1:
'TO DO: Need to insert a 'time-out' after 255 attempts and
branch to error routine
w_tmp2 = 0
while res <> 0
ss = 1
dat = $ff
Shiftout SI, SCK, MSBFIRST,[dat]
gosub shiftin_res
ss = 0
dat = $41 'MMC Command 1
Shiftout SI, SCK, MSBFIRST,[dat]
'arg4 = $41
'gosub shiftout1
dat = 0
cnt = 4
gosub shiftout_dat
dat = $ff
gosub shiftout2
gosub shiftin_res
w_tmp2 = w_tmp2 + 1
if w_tmp2 > $0FFF then init_mmc
wend
dat = $ff
'MMC now successfully initialized in SPI mode
'For debugging
chk_ok2:
hserout ["MMC INIT OK!",10,13] 'Display on terminal
high ok_led
return
'MMC Writing subroutine write 512 bytes stored in the I2C eeprom
'This routine will write whatever is in I2C eeprom locations
eaddr1 to eaddr2
'Check response
chk_res:
'time-out after several attempts and branch to error routine
w_tmp2 =0 : chk_flag = 0
while res <> chk
Shiftin SO, SCK, MSBPRE, [res]
w_tmp2 = w_tmp2 + 1
if w_tmp2 > $1000 then no_go1
wend
goto chk_ok1
no_go1: chk_flag = 1
chk_ok1:
return
mwrite:
high wr_led
ss = 1
arg4 = $ff
gosub shiftout1
gosub shiftin_res
ss = 0
arg0 = $58
arg1 = addr_H.BYTE1
arg2 = addr_H.BYTE0
arg3 = addr_L.BYTE1
arg4 = addr_L.BYTE0
gosub shiftout5
arg4 = $ff
gosub shiftout1
gosub shiftin_res
chk = 0
gosub chk_res
'if chk_flag = 1 then hserout ["Write Error Resp not 0",10,13]
'Write command was a success
'File token tells the MMC data is to follow
arg4 = $FE
gosub shiftout1
'MMC now ready to write data in blocks of 512 bytes assumes
eeprom address in eaddr1, eaddr2
for addr = eaddr1 to eaddr2
'READ addr,dat 'Read from internal eeprom if it has 512 byte
capacity
I2CREAD sda,scl,ctl,addr,[dat] 'Read from I2C ext eeprom
Shiftout SI, SCK, MSBFIRST,[dat] 'Send it to the MMC
next addr
dat=$ff
cnt = 2
gosub shiftout_dat
gosub shiftin_res
y=res & $0f
gosub shiftin_res
'time-out after several attempts and branch out
while res = 0 'MMC is busy writing until response is not = 0
Shiftin SO, SCK, MSBPRE, [res]
wend
gosub mstatus 'Get write status
low wr_led
return
'MMC Reading routine, assumes addr_H and addr_L have the MMC 32
bit address
mread:
ss = 1
arg4 = $ff
gosub shiftout1
gosub shiftin_res
ss = 0
arg0 = $51
arg1 = addr_H.BYTE1
arg2 = addr_H.BYTE0
arg3 = addr_L.BYTE1
arg4 = addr_L.BYTE0
gosub shiftout5
arg4 = $ff
gosub shiftout1
gosub shiftin_res
chk = 0
gosub chk_res
if chk_flag = 1 then hserout ["Read Error Resp not 0",10,13]
chk = $FE
gosub chk_res
if chk_flag = 1 then hserout ["Read Error Resp not $FE",10,13]
'Read cmd successful
'Read the MMC data and save in eeprom assumes eaddr1 and eaddr2
is given
for e_addr = eaddr1 to eaddr2 'We will read 512 bytes can be any
number
Shiftin SO, SCK, MSBPRE, [dat]
'We now have a byte do something with it!
I2CWRITE sda,scl,ctl,e_addr,[dat] 'Write to eeprom from eaddr1
to eaddr2
next e_addr
'Required after a MMCread
gosub shiftin_res
gosub shiftin_res
gosub mstatus 'Get read status
return
'Set block length (must lie with sector boundaries minimum
default is 512)
mset_blk:
'Cmd16:
cmd = $50
gosub send_cmd
return
'MMC tag beginning and end of an earse block
tag_start:
'MMC tag block
'Block START TAG
'Cmd32
cmd = $60
gosub send_cmd
return
tag_end:
'Cmd33
cmd = $61
gosub send_cmd
return
'MMC erase tagged block
merase:
'ERASE BLOCK at addr_h,addr_L
'Cmd38
cmd = $66
gosub send_cmd
return
'=============================
'Send a command to the mmc assumes CMD, addr_H and addr_L
send_cmd:
ss = 1
arg4 = $ff
gosub shiftout1
gosub shiftin_res
ss = 0
arg0 = cmd
arg1 = addr_H.BYTE1
arg2 = addr_H.BYTE0
arg3 = addr_L.BYTE1
arg4 = addr_L.BYTE0
gosub shiftout5
Dat = $FF
cnt = 2
gosub shiftout_dat
gosub shiftin_res
chk = 0
gosub chk_res
if chk_flag = 1 then hserout ["Cmd error Resp not 0",10,13]
return
'MMC status
mstatus:
ss = 1
dat = $ff
Shiftout SI, SCK, MSBFIRST,[dat]
gosub shiftin_res
ss = 0
arg4 = $4D
gosub shiftout1
dat = 0
cnt = 4
gosub shiftout_dat
arg4 = $ff
gosub shiftout1
Shiftin SO, SCK, MSBPRE, [res2\16]
mmc_status = res2
return
'Shift out the same data. Assumes DAT and CNT
shiftout_dat:
for y = 1 to cnt
Shiftout SI, SCK, MSBFIRST,[dat]
next y
return
'Shift out 5 (ARG0-ARG4)
shiftout5: Shiftout SI, SCK, MSBFIRST,[arg0,arg1,arg2,arg3,arg4]
: return
shiftout4: Shiftout SI, SCK, MSBFIRST,[arg1,arg2,arg3,arg4] :
return
shiftout3: Shiftout SI, SCK, MSBFIRST,[arg2,arg3,arg4]: return
shiftout2: Shiftout SI, SCK, MSBFIRST,[arg3, arg4]: return
shiftout1: Shiftout SI, SCK, MSBFIRST,[arg4]: return
'Shiftin RES
shiftin_res:
Shiftin SO, SCK, MSBPRE, [res]
return
'====================== END OF MMC GENERAL ROUTINES
=========================
'Subroutine used by this application
disp:
'serout2 out_pin,ser_baud,["Data from MMC",10,13] 'Display on
terminal
hserout ["Data from MMC",10,13]
'Display data to terminal, assumes eaddr1,eaddr2 are given
for e_addr = eaddr1 to eaddr2
I2CREAD sda,scl,ctl,e_addr,[dat]
'serout2 out_pin,ser_baud,[dat] 'Display on terminal
hserout [dat]
next e_addr
return
'*************** M A I N P R O G R A M ****************
Main:
'Initialize the MMC
gosub init_mmc
'Set block length (minimum 512 bytes when writing) default is
512 bytes
addr_H = $0000
addr_L = $0200
gosub mset_blk
'Set an I2C eeprom address (512 bytes)
eaddr1 = 0
eaddr2 = $01FF
goto Term
'======== Added Jul 13th 2002 for I/O =========
'MAIN LOOP Get the initial parameters
'Params Index: 0 = Option, 1 & 2 = buffer_count, 3-6 = Addr_H,
7-10 = Addr_L
'
Term:
low cts
hserout ["Waiting..",10,13]
get_param:
pause 100
high cts
hserin [wait ("@"),STR in_ctl\11]
low cts
for idx = 0 to 10
Lookdown in_ctl[idx],["0123456789ABCDEF"],hex_nibble
in_ctl[idx]=hex_nibble
next idx
j=in_ctl[0]
buff_count =(in_ctl[1]<<4) | in_ctl[2]
addr_H.byte1 =(in_ctl[3]<<4) | in_ctl[4]
addr_H.byte0 =(in_ctl[5]<<4) | in_ctl[6]
addr_L.byte1 =(in_ctl[7]<<4) | in_ctl[8]
addr_L.byte0 =(in_ctl[9]<<4) | in_ctl[10]
if buff_count = 0 then buff_count = 1
'Options
if j = 0 then mmc_read_hex
if j = 1 then mmc_read_asc
if j = 2 then mmc_write
if j = 3 then mmc_erase
if j = 4 then mmc_tag
goto get_param
'=========== CONTINUE LOOPING ===========
'Options
'Read from MMC to eeprom, the MMC address is assumed to be in
addr_H and addr_L
mmc_read_hex:
' addr_h = $0000
' addr_L = $0000
hserout ["Addr:",hex4 addr_H,hex4 addr_L,10,13]
for c = 1 to buff_count
gosub mread
for e_addr = eaddr1 to eaddr2
I2CREAD sda,scl,ctl,e_addr,[dat]
hserout [hex2 dat]
next e_addr
addr_L = addr_L + $0200
if carry_flag = 1 then
addr_H = addr_H + 1
endif
next c
goto get_param
mmc_read_asc:
' addr_h = $0000
'addr_L = $0000
hserout ["Addr:",hex4 addr_H,hex4 addr_L,10,13]
for c = 1 to buff_count
gosub mread
for e_addr = eaddr1 to eaddr2
I2CREAD sda,scl,ctl,e_addr,[dat]
if dat = 10 then lfcr
if dat = 13 then lfcr
if (dat > 126) OR (dat < 32) then cont_read 'strip non-ascii
lfcr:
hserout [dat]
cont_read:
next e_addr
addr_L = addr_L + $0200
if carry_flag = 1 then
addr_H = addr_H + 1
endif
next c
goto get_param
mmc_write:
for c = 1 to buff_count
'Load 512 bytes into eeprom
e_addr = $0000
for idx = 1 to 8
high cts
hserin 5000,WrErr,[STR in_array\64]
low cts
I2CWRITE sda,scl,ctl,e_addr,[STR in_array\64]
e_addr = e_addr + 64
next idx
gosub mwrite
addr_L = addr_L + $0200
if carry_flag = 1 then
addr_H = addr_H + 1
endif
next c
goto cont2
WrErr:
low cts
hserout ["Write Error!",13,10]
goto get_param
Cont2:
hserout ["Data Written",13,10]
goto get_param
mmc_erase:
goto get_param
mmc_tag:
goto get_param
goto get_param 'Safety net!
end