Code:
define OSC 16
DEFINE HSER_BAUD 19200
DEFINE HSER_CLROERR 1 ' Auto clear over-run errors
DEFINE HSER_RCSTA 90h
DEFINE HSER_TXSTA 20h
OSCCON = OSCCON | %01110000 ' set internal clock to 16 MHz incase of switchover
SDI Var PORTC.4 ' SPI data in
SDI_TRIS Var TRISC.4 ' SPI data in direction
SCL Var PORTC.3 ' SPI clock
SCL_TRIS Var TRISC.3 ' SPI clock direction
SD_CS Var PORTA.5 ' SD card chip select
SD_CS_TRIS Var TRISA.5 ' SD card chip select direction
SD_CD Var PORTB.4 ' SD card detect
SD_CD_TRIS Var TRISB.4 ' SD card detect direction
SDO Var PORTC.5 ' SPI data out
SDO_TRIS Var TRISC.5 ' SPI data out direction
i2cSDA VAR PORTD.1
i2cSCL VAR PORTD.0
SSPEN Var SSPCON1.5 ' SSP enable
WCOL Var SSPCON1.7 ' SSP write collision
BF Var SSPSTAT.0 ' SSP buffer full
SSPIF Var PIR1.3 ' SSP interrupt flag
accx var byte
accx2 var byte
accx_axis var word
fail var byte
read_loop var byte
NODATA Con 0
MOREDATA Con 1
MEDIA_SECTOR_SIZE Con 512
FAT_BUFFER_SIZE Con MEDIA_SECTOR_SIZE
' Indexes into command table
GO_IDLE_STATE Con 0
SEND_OP_COND Con 1
SET_BLOCKLEN Con 2
READ_SINGLE_BLOCK Con 3
WRITE_SINGLE_BLOCK Con 4
CRC_ON_OFF Con 5
sdcCardDataRejected Con 8
SDC_address Var Long
SDC_buffer Var Byte[MEDIA_SECTOR_SIZE]
SDC_cmd Var Byte
SDC_CmdCode Var Byte
SDC_CRC Var Byte
SDC_data_in Var Byte
SDC_data_out Var Byte
SDC_index Var Word
SDC_moredataexpected Var Byte
SDC_response Var Byte
SDC_sector_addr Var Long
SDC_status Var Byte
SDC_timeout Var Long
SDC_timeout1 Var Word
sdcValid Con 0
sdcCardInitCommFailure Con 1
sdcCardNotInitFailure Con 2
sdcCardInitTimeout Con 3
FAT_error Var Byte
FAT_error = 0
DATA_START_TOKEN Con $fe
DATA_ACCEPTED Con $05
SDC_FLOATING_BUS Con $ff
SDC_BAD_RESPONSE Con SDC_FLOATING_BUS
FALSE Con 0
TRUE Con 1
'SDC_UseHardSPI Var Byte
'Include "SDFS.PBP"
trisa = %00000000
trisd = %00000000
trisc = %00000000
adcon0.0 = 0
ANSELA = 0
ANSELB = 0
ANSELC = 0
ANSELD = 0
ANSELE = 0
ADCON1 = 15 ' All I/O pins digital
pause 1000
I2CWRITE i2cSDA,i2cSCL, $a6, $2d, [0]
pauseus 5
I2CWRITE i2cSDA,i2cSCL, $a6, $2d, [16]
pauseus 5
I2CWRITE i2cSDA,i2cSCL, $a6, $2d, [8]
pauseus 5
I2CWRITE i2cSDA,i2cSCL, $a6, $31, [8]
pause 1000
i2cread i2cSDA,i2cSCL,$a7,50,[accx,accx2],error
accx_axis = accx+(accx2 &03)*256
hserout [$d,$a,#accx_axis,$d,$d]
fail = 0
'while (fail <5 & FAT_error != 0)
fail = fail+1
SD_CS = 1 ' SD card not selected.
SD_CS_TRIS = 0 ' Output SD card chip select.
SD_CD_TRIS = 1 ' Input card detect.
'SD_WE_TRIS = 1 ' Input write protect.
SDO = 1 ' Start SPI data out high.
SDO_TRIS = 0 ' Output SPI data out.
SDI_TRIS = 1 ' Input SPI data in.
SCL = 1 ' SPI clock idles high.
SCL_TRIS = 0 ' Output SPI clock.
pause 1
SSPSTAT = %00000000 ' Sample at middle of data output time, Mode 1, 1: Transmit on idle to active clock transition.
SSPCON1 = %00010010 ' SPI master mode, clock = Fosc/64, Mode 1, 1: Clock idle high.
SSPEN = 1 ' Enable hardware SPI port.
pause 1
For SDC_timeout1 = 1 To 10
hserout [$d,$a,"sdc timeout: ",#SDC_timeout1]
SDC_data_out = $ff ' Data pin must be high.
SDC_data_in = SSPBUF ' Clear the buffer.
SSPIF = 0 ' Clear the interrupt flag.
SSPBUF = SDC_data_out' Send the byte.
If (WCOL) Then Return' Check for write collision.
While !SSPIF ' Wait for send to complete.
Wend
Next SDC_timeout1
pause 1
hserout [$d,$a,"Go idle"]
SDC_cmd = GO_IDLE_STATE
SDC_address = 0
gosub send_receive_SD_loop
SDC_data_out = $ff ' Data pin must be high.
gosub write_byte
If (!SDC_moredataexpected) Then
SD_CS = 1
Endif
If (SDC_response = SDC_BAD_RESPONSE) Then
SDC_status = sdcCardInitCommFailure
Goto InitError
Endif
If ((SDC_response & $F7) != $01) Then
SDC_status = sdcCardNotInitFailure
Goto InitError
Endif
For SDC_timeout1 = $fff To 0 Step -1
hserout [$d,$a,"Op cond"]
SDC_cmd = SEND_OP_COND
SDC_address = 0
gosub send_receive_SD_loop
' Generate 8 clock cycles.
SDC_data_out = $ff ' Data pin must be high.
SDC_data_in = SSPBUF ' Clear the buffer.
SSPIF = 0 ' Clear the interrupt flag.
SSPBUF = SDC_data_out ' Send the byte.
If (WCOL) Then Return ' Check for write collision.
While !SSPIF ' Wait for send to complete.
Wend
If (!SDC_moredataexpected) Then
SD_CS = 1
Endif
If (SDC_response = $00) Then SDC_timeout1 = 0 ' Got a response, end the loop.
Next SDC_timeout1
If (SDC_response != $00) Then
SDC_status = sdcCardInitTimeout
Goto InitError
Endif
Pause 1
SSPSTAT = %00000000 ' Sample at middle of data output time, Mode 1, 1: Transmit on idle to active clock transition.
SSPCON1 = %00010000 ' SPI master mode, clock = Fosc/64, Mode 1, 1: Clock idle high.
SSPEN = 1
hserout [$d,$a,"CRC On/Off"]
SDC_cmd = CRC_ON_OFF
SDC_address = 0
gosub send_receive_SD_loop
SDC_data_out = $ff
gosub write_byte
If (!SDC_moredataexpected) Then
SD_CS = 1
Endif
hserout [$d,$a,"Set Block Length"]
SDC_cmd = SET_BLOCKLEN
SDC_address = MEDIA_SECTOR_SIZE
gosub send_receive_SD_loop
SDC_data_out = $ff
gosub write_byte
pause 1
'##############################################################
'SectorWrite:
hserout[$d,$a,"Sector write"]
SDC_sector_addr = 200
SDC_cmd = WRITE_SINGLE_BLOCK
SDC_address = SDC_sector_addr << 9
gosub send_receive_SD_loop
If (SDC_response != 0) Then
hserout[$d,$a,"Not accepted!",$d,$a]
gosub stop_read
else
hserout[$d,$a,"Accepted!",$d,$a]
endif
SDC_data_out = DATA_START_TOKEN
Gosub write_byte
SDC_data_out = 72 'store 'HELLO'
Gosub write_byte
SDC_data_out = 69
Gosub write_byte
SDC_data_out = 76
Gosub write_byte
SDC_data_out = 76
Gosub write_byte
SDC_data_out = 79
Gosub write_byte
For SDC_index = 0 To (MEDIA_SECTOR_SIZE - 6)
hserout[$d,#SDC_index]
SDC_data_out = $47
Gosub write_byte
Next SDC_index
' Send the CRC bytes.
SDC_data_out = $ff
gosub write_byte ' Just sends 16 1s.
gosub write_byte
SDC_data_in = SSPBUF ' Clear the buffer.
SSPIF = 0 ' Clear the interrupt flag.
SSPBUF = $ff ' Shift out a dummy byte.
While !SSPIF ' Wait for receive byte.
Wend
SDC_data_in = SSPBUF ' Get the byte.
If ((SDC_data_in & $0f) != DATA_ACCEPTED) Then
SDC_status = sdcCardDataRejected
hserout[$d,$a,"Rejected!"]
gosub stop_read
Else
' The card is writing data into the storage media.
' Wait for the card to return non-zero (not busy) or a timeout.
For SDC_timeout = 0 To 10000
SDC_data_in = SSPBUF ' Clear the buffer.
SSPIF = 0 ' Clear the interrupt flag.
SSPBUF = $ff ' Shift out a dummy byte.
While !SSPIF ' Wait for receive byte.
Wend
SDC_data_in = SSPBUF ' Get the byte.
If (SDC_data_in != 0) Then
hserout[$d,$a,"Got a write response at ",#SDC_timeout]
SDC_timeout = 10000 ' Got a response, end the loop.
endif
Next SDC_timeout
hserout[$d,$a,"SDC data in = ",#SDC_data_in]
If (SDC_data_in = 0) Then
hserout[$d,$a,"SDC Card timeout"]
gosub stop_read
endif
Endif
SDC_data_out = $ff ' Data pin must be high.
gosub write_byte
SD_CS = 1
'##################################################################
pause 1
for read_loop = 10 to 12
hserout[$d,$a,"SDC sector address: ",#read_loop]
gosub SectorRead
next read_loop
End
error:
HSEROUT["Error"]
RETURN
InitError:
HSEROUT [$d,$a,"Error unknown", $d, $a]
return
write_byte:
' Write Byte SDC_data_out.
SDC_data_in = SSPBUF ' Clear the buffer.
SSPIF = 0 ' Clear the interrupt flag.
SSPBUF = SDC_data_out ' Send the byte.
If (WCOL) Then
HSEROUT [$d,$a,"Error: collision", $d, $a]
Return ' Check for write collision.
endif
While !SSPIF ' Wait for send to complete.
Wend
return
write_SPI:
SD_CS = 0
Lookup SDC_cmd, [$40, $41, $50, $51, $58, $7b], SDC_CmdCode
Lookup SDC_cmd, [$95, $f9, $ff, $ff, $ff, $25], SDC_CRC
Lookup SDC_cmd, [NODATA, NODATA, NODATA, MOREDATA, MOREDATA, NODATA], SDC_moredataexpected
SDC_data_out = SDC_CmdCode
gosub write_byte
SDC_data_out = SDC_address.Byte3
gosub write_byte
SDC_data_out = SDC_address.Byte2
gosub write_byte
SDC_data_out = SDC_address.Byte1
gosub write_byte
SDC_data_out = SDC_address.Byte0
gosub write_byte
SDC_data_out = SDC_CRC
gosub write_byte
return
send_receive_SD_loop:
SD_CS = 0
pause 1
gosub write_SPI
hserout [$d,$a,"Test card for response: ",$d,$a]
For SDC_timeout = 8 To 0 Step -1
' Read Byte SDC_data_in from SPI bus. Returns SDC_data_in.
SDC_data_in = SSPBUF ' Clear the buffer.
SSPIF = 0 ' Clear the interrupt flag.
SSPBUF = $ff ' Shift out a dummy byte.
While !SSPIF ' Wait for receive byte.
Wend
SDC_data_in = SSPBUF ' Get the byte.
hserout ["Countdown timeout: ",#SDC_timeout,$d,$a]
SDC_response = SDC_data_in
If (SDC_response != SDC_FLOATING_BUS) Then
hserout ["Got a response at: ",#SDC_timeout]
SDC_timeout = 0 ' Got a response, end the loop.
endif
Next SDC_timeout
hserout[$d,$a,"SDC_response: ",#SDC_response]
return
SectorRead:
hserout[$d,$a,$a,"Entering SectorRead loop"]
SDC_sector_addr = 200
SDC_status = sdcValid ' Set default error code.
SDC_cmd = READ_SINGLE_BLOCK
SDC_address = SDC_sector_addr << 9
Gosub send_receive_SD_loop ' Send Byte SDC_cmd to Long SDC_address, Returns Word SDC_response.
hserout[$d,$a,"SectorRead error: ",bin SDC_response,8]
If (SDC_response != 0) Then
Gosub send_receive_SD_loop ' Try once more to send Byte SDC_cmd to Long SDC_address, Returns Word SDC_response.
If (SDC_response != 0) Then
hserout[$d,$a,"Not accepted!"]
hserout[$d,$a,"SectorRead error: ",bin SDC_response,8]
gosub stop_read 'stops the algorithm totally
else
hserout[$d,$a,"Accepted on 2nd attempt!",$d,$a]
Endif
Endif
hserout[$d,$a,"Passed initial read command and address send",$d,$a]
Pauseus 40 ' Timing delay- at least 8 clock cycles.
For SDC_timeout = $2ff To 0 Step -1
SDC_data_in = SSPBUF ' Clear the buffer.
SSPIF = 0 ' Clear the interrupt flag.
SSPBUF = $ff ' Shift out a dummy byte.
While !SSPIF ' Wait for receive byte.
Wend
SDC_data_in = SSPBUF ' Read Byte SDC_data_in from SPI bus. Returns SDC_data_in.
Pauseus 40 ' Timing delay- at least 8 clock cycles.
If (SDC_data_in != SDC_FLOATING_BUS) Then SDC_timeout = 0 ' Got a response, end the loop.
Next SDC_timeout
If (SDC_data_in != DATA_START_TOKEN) Then
hserout["Timeout!!!!"]
gosub stop_read 'stops the algorithm totally
else
hserout["Data token received!",$d,$a]
endif
For SDC_index = 0 To (MEDIA_SECTOR_SIZE - 1)
SDC_data_in = SSPBUF ' Clear the buffer.
SSPIF = 0 ' Clear the interrupt flag.
SSPBUF = $ff ' Shift out a dummy byte.
While !SSPIF ' Wait for receive byte.
Wend
SDC_data_in = SSPBUF ' Read Byte SDC_data_in from SPI bus. Returns SDC_data_in.
hserout[SDC_data_in]
Next SDC_index
SDC_data_out = $ff ' Data pin must be high.
Gosub write_byte ' Just sends 16 clocks.
gosub write_byte
SD_CS = 1 ' Return Byte SDC_status.
pause 1
return
stop_read:
SSPEN = 0
stop
Bookmarks