public void Reset() { currState = SdState.IDLE; argCnt = 0; cmd = SdCommand.INVALID; dataBlockLen = 512; dataCnt = 0; csdCnt = 0; cidCnt = 0; ocrCnt = 0; r7_Cnt = 0; appCmd = false; wrPos = UInt32.MaxValue; }
private SdState GetRespondType() { if (!appCmd) { switch (cmd) { case SdCommand.APP_CMD: appCmd = true; return(SdState.R1); case SdCommand.GO_IDLE_STATE: case SdCommand.SEND_OP_COND: case SdCommand.SET_BLOCKLEN: case SdCommand.READ_SINGLE_BLOCK: case SdCommand.READ_MULTIPLE_BLOCK: case SdCommand.CRC_ON_OFF: case SdCommand.STOP_TRANSMISSION: case SdCommand.SEND_CSD: case SdCommand.SEND_CID: return(SdState.R1); case SdCommand.READ_OCR: return(SdState.R3); case SdCommand.SEND_IF_COND: return(SdState.R7); case SdCommand.WRITE_BLOCK: return(SdState.RD_DATA_SIG); case SdCommand.WRITE_MULTIPLE_BLOCK: return(SdState.RD_DATA_SIG_MUL); } } else { appCmd = false; switch (cmd) { case SdCommand.SD_SEND_OP_COND: return(SdState.R1); } } cmd = SdCommand.INVALID; return(SdState.R1); }
public byte Rd() { if (fstream == null) { return(0xFF); } switch (cmd) { case SdCommand.GO_IDLE_STATE: if (currState == SdState.R1) { // Cmd = CMD.INVALID; currState = SdState.IDLE; return(1); } break; case SdCommand.SEND_OP_COND: if (currState == SdState.R1) { // Cmd = CMD.INVALID; currState = SdState.IDLE; return(0); } break; case SdCommand.SET_BLOCKLEN: if (currState == SdState.R1) { // Cmd = CMD.INVALID; currState = SdState.IDLE; return(0); } break; case SdCommand.SEND_IF_COND: if (currState == SdState.R7) { switch (r7_Cnt++) { case 0: return(0x01); // R1 case 1: return(0x00); case 2: return(0x00); case 3: return(0x01); default: currState = SdState.IDLE; r7_Cnt = 0; return((byte)(arg & 0xFF)); // echo-back } } break; case SdCommand.READ_OCR: if (currState == SdState.R3) { switch (ocrCnt++) { case 0: return(0x00); // R1 case 1: return(0x80); case 2: return(0xFF); case 3: return(0x80); default: currState = SdState.IDLE; ocrCnt = 0; return(0x00); } } break; case SdCommand.APP_CMD: if (currState == SdState.R1) { currState = SdState.IDLE; return(0); } break; case SdCommand.SD_SEND_OP_COND: if (currState == SdState.R1) { currState = SdState.IDLE; return(0); } break; case SdCommand.CRC_ON_OFF: if (currState == SdState.R1) { currState = SdState.IDLE; return(0); } break; case SdCommand.STOP_TRANSMISSION: switch (currState) { case SdState.R1: dataCnt = 0; currState = SdState.R1b; return(0); case SdState.R1b: currState = SdState.IDLE; return(0xFF); } break; case SdCommand.READ_SINGLE_BLOCK: switch (currState) { case SdState.R1: currState = SdState.DELAY_S; return(0); case SdState.DELAY_S: currState = SdState.STARTBLOCK; return(0xFF); case SdState.STARTBLOCK: currState = SdState.WR_DATA; dataCnt = 0; return(0xFE); case SdState.WR_DATA: { byte Val = buff[dataCnt++]; if (dataCnt == dataBlockLen) { dataCnt = 0; currState = SdState.WR_CRC16_1; } return(Val); } case SdState.WR_CRC16_1: currState = SdState.WR_CRC16_2; return(0xFF); // crc case SdState.WR_CRC16_2: currState = SdState.IDLE; cmd = SdCommand.INVALID; return(0xFF); // crc } // Cmd = CMD.INVALID; break; case SdCommand.READ_MULTIPLE_BLOCK: switch (currState) { case SdState.R1: currState = SdState.DELAY_S; return(0); case SdState.DELAY_S: currState = SdState.STARTBLOCK; return(0xFF); case SdState.STARTBLOCK: currState = SdState.IDLE; dataCnt = 0; return(0xFE); case SdState.IDLE: { if (dataCnt < dataBlockLen) { byte Val = buff[dataCnt++]; if (dataCnt == dataBlockLen) { fstream.Read(buff, 0, dataBlockLen); } return(Val); } else if (dataCnt > (dataBlockLen + 8)) { dataCnt = 0; return(0xFE); // next startblock } else { dataCnt++; return(0xFF); // crc & pause } } } break; case SdCommand.SEND_CSD: switch (currState) { case SdState.R1: currState = SdState.DELAY_S; return(0); case SdState.DELAY_S: currState = SdState.STARTBLOCK; return(0xFF); case SdState.STARTBLOCK: currState = SdState.WR_DATA; return(0xFE); case SdState.WR_DATA: { byte Val = csd[csdCnt++]; if (csdCnt == 16) { csdCnt = 0; currState = SdState.IDLE; cmd = SdCommand.INVALID; } return(Val); } } // Cmd = CMD.INVALID; break; case SdCommand.SEND_CID: switch (currState) { case SdState.R1: currState = SdState.DELAY_S; return(0); case SdState.DELAY_S: currState = SdState.STARTBLOCK; return(0xFF); case SdState.STARTBLOCK: currState = SdState.WR_DATA; return(0xFE); case SdState.WR_DATA: { byte Val = cid[cidCnt++]; if (cidCnt == 16) { cidCnt = 0; currState = SdState.IDLE; cmd = SdCommand.INVALID; } return(Val); } } // Cmd = CMD.INVALID; break; case SdCommand.WRITE_BLOCK: // printf(__FUNCTION__" cmd=0x%X, St=0x%X\n", Cmd, CurrState); switch (currState) { case SdState.R1: currState = SdState.RD_DATA_SIG; return(0xFE); case SdState.WR_DATA_RESP: { currState = SdState.IDLE; byte Resp = (((byte)SdStatus.DATA_ACCEPTED) << 1) | 1; return(Resp); } } break; case SdCommand.WRITE_MULTIPLE_BLOCK: switch (currState) { case SdState.R1: currState = SdState.RD_DATA_SIG_MUL; return(0xFE); case SdState.WR_DATA_RESP: { currState = SdState.RD_DATA_SIG_MUL; byte Resp = (((byte)SdStatus.DATA_ACCEPTED) << 1) | 1; return(Resp); } } break; } if (currState == SdState.R1) // CMD.INVALID { currState = SdState.IDLE; return(0x05); } return(0xFF); }
public void Wr(byte val) { SdState NextState = SdState.IDLE; if (fstream == null) { return; } switch (currState) { case SdState.IDLE: { if ((val & 0xC0) != 0x40) { break; } cmd = (SdCommand)(val & 0x3F); if (!appCmd) { switch (cmd) { case SdCommand.SEND_CSD: csdCnt = 0; break; case SdCommand.SEND_CID: cidCnt = 0; break; case SdCommand.READ_OCR: ocrCnt = 0; break; case SdCommand.SEND_IF_COND: r7_Cnt = 0; break; } } NextState = SdState.RD_ARG; argCnt = 0; } break; case SdState.RD_ARG: NextState = SdState.RD_ARG; SetByte(ref arg, 3 - argCnt++, val); if (argCnt == 4) { if (!appCmd) { switch (cmd) { case SdCommand.SET_BLOCKLEN: if (arg <= 4096) { dataBlockLen = (int)arg; } break; case SdCommand.READ_SINGLE_BLOCK: fstream.Seek(arg, SeekOrigin.Begin); fstream.Read(buff, 0, dataBlockLen); break; case SdCommand.READ_MULTIPLE_BLOCK: fstream.Seek(arg, SeekOrigin.Begin); fstream.Read(buff, 0, dataBlockLen); break; case SdCommand.WRITE_BLOCK: break; case SdCommand.WRITE_MULTIPLE_BLOCK: wrPos = arg; break; } } NextState = SdState.RD_CRC; argCnt = 0; } break; case SdState.RD_CRC: NextState = GetRespondType(); break; case SdState.RD_DATA_SIG: if (val == 0xFE) // Проверка сигнатуры данных { dataCnt = 0; NextState = SdState.RD_DATA; } else { NextState = SdState.RD_DATA_SIG; } break; case SdState.RD_DATA_SIG_MUL: switch (val) { case 0xFC: // Проверка сигнатуры данных dataCnt = 0; NextState = SdState.RD_DATA_MUL; break; case 0xFD: // Окончание передачи dataCnt = 0; NextState = SdState.IDLE; break; default: NextState = SdState.RD_DATA_SIG_MUL; break; } break; case SdState.RD_DATA: // Прием данных в буфер { buff[dataCnt++] = val; NextState = SdState.RD_DATA; if (dataCnt == dataBlockLen) // Запись данных в SD карту { dataCnt = 0; fstream.Seek(arg, SeekOrigin.Begin); fstream.Write(buff, 0, dataBlockLen); NextState = SdState.WR_DATA_RESP; } } break; case SdState.RD_DATA_MUL: // Прием данных в буфер { buff[dataCnt++] = val; NextState = SdState.RD_DATA_MUL; if (dataCnt == dataBlockLen) // Запись данных в SD карту { dataCnt = 0; fstream.Seek(wrPos, SeekOrigin.Begin); fstream.Write(buff, 0, dataBlockLen); wrPos += (uint)dataBlockLen; NextState = SdState.RD_DATA_SIG_MUL; } } break; case SdState.RD_CRC16_1: // Чтение старшего байта CRC16 NextState = SdState.RD_CRC16_2; break; case SdState.RD_CRC16_2: // Чтение младшего байта CRC16 NextState = SdState.WR_DATA_RESP; break; default: return; } currState = NextState; }