📄 sdcard.java
字号:
crc = (short)(((crc >> 8) & 0x0FF) | (crc << 8));
crc ^= (data[i] & 0x0FF);
crc ^= (crc & 0x0FF) >> 4;;
crc ^= (crc << 8) << 4;
crc ^= ((crc & 0xFF) << 4) << 1;
}
/*
short crc = 0;
for(int i = 0; i < len; i++)
{
for(int x = 7; x >= 0; x--)
{
boolean flip = (crc & 0x8000) == 0x8000;
crc <<= 1;
crc |= ((data[offset + i] >> x) & 1);
if(flip)
{
crc ^= 0x1021;
}
}
}
for(int x = 0; x < 16; x++)
{
boolean flip = (crc & 0x8000) == 0x8000;
crc <<= 1;
if(flip)
{
crc ^= 0x1021;
}
}
*/
return crc;
}
private CachedSector getCachedSector(int address, int length)
{
CachedSector sector;
for(int i = 0; i < cache.size(); i++)
{
sector = (CachedSector)cache.elementAt(i);
if(sector.isSector(address, length))
{
cache.removeElementAt(i);
cache.insertElementAt(sector, 0);
return sector;
}
}
if(cache.size() == CACHE_SIZE)
{
sector = (CachedSector)cache.lastElement();
if(sector.dirty)
{
writeblock(sector);
}
cache.removeElement(sector);
cache.insertElementAt(sector, 0);
sector.address = address - (address % blockSize);
readblock(sector);
sector.dirty = false;
}
else
{
sector = new CachedSector(address - (address % blockSize));
cache.insertElementAt(sector, 0);
}
return sector;
}
private boolean readblock(CachedSector sector)
{
int result;
cmd[1] = (byte)((sector.address & 0xff000000) >> 24);
cmd[2] = (byte)((sector.address & 0x00ff0000) >> 16);
cmd[3] = (byte)((sector.address & 0x0000ff00) >> 8);
cmd[4] = (byte)(sector.address & 0x000000ff);
try
{
if(sendCommand(CMD17_READ_SINGLE_BLOCK) != R1_NOERROR)
{
return false;
}
receiveData(sector.cache, 0, blockSize + 2);
verifyCRC16(sector.cache, 0, blockSize,(short)((sector.cache[blockSize] << 8) | (sector.cache[blockSize + 1] & 0x0FF)));
return true;
}
catch(Exception ex)
{
return false;
}
}
private boolean writeblock(CachedSector sector)
{
short crc = crc16(sector.cache, 0, blockSize);
sector.cache[blockSize + 0] = (byte)(crc >> 8);
sector.cache[blockSize + 1] = (byte)(crc & 0x00ff);
// This byte address is stored MSB-first in the argument buffer
cmd[1] = (byte)((sector.address & 0xff000000) >> 24);
cmd[2] = (byte)((sector.address & 0x00ff0000) >> 16);
cmd[3] = (byte)((sector.address & 0x0000ff00) >> 8);
cmd[4] = (byte)(sector.address & 0x000000ff);
try
{
// Transmit the write command plus the byte address argument
if(sendCommand(CMD24_WRITE_BLOCK) != R1_NOERROR)
{
return false;
}
}
catch(Exception x)
{
return false;
}
sendSPI((byte)0xFE);
spi.xmit(sector.cache, 0, blockSize + 2);
byte recv;
int tries = 0;
do
{
if(tries++ > 32768)
{
return false;
}
recv = sendSPI((byte)0xFF);
}
while(((recv & 0x10) != 0) || ((recv & 0x01) == 0));
tries = 0;
do
{
if(tries++ > 32768)
{
return false;
}
recv = sendSPI((byte)0xFF);
} while(recv != (byte)0xFF);
return true;
}
public void init(String[] args)
{
//TODO
/*
int interval = 2000;
int count;
if(args.length > 0)
{
interval = Integer.parseInt(args[0]);
}
immediateWrite = false;
if(interval == 0)
{
immediateWrite = true;
}
else if(interval == -1)
{
}
else
{
count = 1;
if(args.length > 1)
{
count = Integer.parseInt(args[1]);
}
(new FlushThread(interval, count)).start();
}
*/
}
private class FlushThread extends Thread
{
private int delay;
private int count;
FlushThread(int interval, int count)
{
this.delay = interval;
this.count = count;
}
public void run()
{
while(true)
{
try
{
Thread.sleep(delay);
int cnt = count;
synchronized (cache)
{
for(int i = 0; i < cache.size(); i++)
{
CachedSector sector = (CachedSector)cache.elementAt(i);
if(sector.dirty)
{
writeblock(sector);
sector.dirty = false;
if(--cnt == 0)
{
break;
}
}
}
}
}
catch(Exception x)
{
}
}
}
}
public void setOffset(int offset)
{
startAddress = offset;
}
//TODO handle reads across multiple sectors (or at least throw an exception).
public boolean read(int address, byte[] buff, int offset, int length)
{
address += startAddress;
synchronized (cache)
{
CachedSector sector = getCachedSector(address, length);
System.arraycopy(sector.cache, address - sector.address, buff, offset, length);
}
return true;
}
//TODO - need to handle writes across multiple sectors (or at least throw an exception).
public boolean write(int address, byte[] buff, int offset, int length)
{
address += startAddress;
synchronized (cache)
{
CachedSector sector = getCachedSector(address, length);
System.arraycopy(buff, offset, sector.cache, (address - sector.address), length);
sector.dirty = true;
if(immediateWrite)
{
flush();
}
}
return true;
}
public void flush()
{
synchronized (cache)
{
for(int i = 0; i < cache.size(); i++)
{
CachedSector sector = (CachedSector)cache.elementAt(i);
if(sector.dirty)
{
writeblock(sector);
sector.dirty = false;
}
}
}
}
public int size()
{
return cardSize;
}
/*
public static void dumpData(byte[] b, int off, int len)
{
int x, c;
int line;
String newLine = System.getProperty("line.separator");
StringBuffer sb = new StringBuffer();
sb.append("ADDR| 0 1 2 3 4 5 6 7 8 9 A B C D E F | ASCII");
sb.append(newLine);
sb.append("------------------------------------------------------------------------");
sb.append(newLine);
for(line = 0; line < ((len % 16 != 0) ? (len / 16) + 1 : (len / 16)); line++)
{
String hex = toHexString(line * 16, 4);
sb.append(hex);
sb.append("| ");
for(x = 0; x < 16; x++)
{
if(x + (line * 16) < len)
{
c = b[off + x + line * 16];
hex = toHexString(c, 2);
sb.append(hex);
sb.append(" ");
}
else
{
sb.append(" ");
}
}
sb.append("| ");
for(x = 0; x < 16; x++)
{
if(x + (line * 16) < len)
{
c = b[off + x + line * 16];
if((c > 0x1f) && (c < 0x7f))
{
sb.append((char)c);
}
else
{
sb.append(".");
}
}
else
{
sb.append(" ");
}
}
sb.append(newLine);
}
sb.append("------------------------------------------------------------------------");
FATFS.sendMessage(sb.toString());
}
private static String toHexString(int x, int len)
{
int mask = (1 << (len * 4)) - 1;
x = x & mask;
String ret = Integer.toHexString(x);
while(ret.length() < len)
{
ret = '0' + ret;
}
return ret;
}
*/
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -