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; }
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 byte TransferByte(byte input) { switch (_state) { case SdState.Idle: { if (_responseQueue.Count > 0) { return(_responseQueue.Dequeue()); } if ((input & 0b11000000) == 0b01000000) { _state = SdState.ReadCommand; _commandQueue.Enqueue(input); } return(0xFF); } case SdState.ReadCommand: { _commandQueue.Enqueue(input); if (_commandQueue.Count == 6) { var command = (byte)(_commandQueue.Dequeue() - 0x40); uint param = 0; for (var i = 0; i < 4; i++) { param = (param << 8) + _commandQueue.Dequeue(); } _commandQueue.Dequeue(); // skip CRC ProcessCommand(command, param); if (_state == SdState.ReadCommand) { _state = SdState.Idle; } } return(0); } case SdState.ReadBlock: { // break on CMD12 if (input == 12 + 0x40) { _state = SdState.ReadCommand; _commandQueue.Enqueue(input); return(0); } if (_responseQueue.Count > 0) { return(_responseQueue.Dequeue()); } var result = _currentBlock[_currentByteNo++]; if (_currentByteNo == _blockSize) { // fake CRC _responseQueue.Enqueue(0x00); _responseQueue.Enqueue(0x00); if (_blockCount > 0 || _blockCount == null) { InitReadMultiple(); } else { _state = SdState.Idle; _blockCount = null; } } return(result); } case SdState.WriteSingleIdle: { if (input == 0xFE) { _currentBlock = new byte[_blockSize]; _currentByteNo = 0; _state = SdState.WriteSingle; } return(0); } case SdState.WriteSingle: { if (_currentByteNo < _blockSize) { _currentBlock[_currentByteNo++] = input; // read block } else if (_currentByteNo < _blockSize + 2) { _currentByteNo++; // read CRC (2 bytes) } else { FinishWrite(); _state = SdState.Idle; return(0x05); } return(0); } case SdState.WriteMultipleIdle: { // break on stop tran token if (input == 0xFD) { _state = SdState.ReadCommand; _commandQueue.Enqueue(input); return(0); } if (input == 0xFC) { _currentBlock = new byte[_blockSize]; _currentByteNo = 0; _state = SdState.WriteMultiple; } return(0); } case SdState.WriteMultiple: { if (_currentByteNo < _blockSize) { _currentBlock[_currentByteNo++] = input; // read block } else if (_currentByteNo < _blockSize + 2) { _currentByteNo++; // read CRC (2 bytes) } else { FinishWrite(); _state = SdState.WriteMultipleIdle; return(0x05); } return(0); } } 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; }
public void ProcessCommand(byte command, UInt32 param) { if (_acmd) { _acmd = false; switch (command) { // SET_WR_BLOCK_ERASE_COUNT case 23: _responseQueue.Enqueue(0x00); break; // APP_SEND_OP_COND case 41: _responseQueue.Enqueue(0x00); break; } } else { switch (command) { // GO_IDLE_STATE case 0: _responseQueue.Enqueue((byte)R1Flags.InIdleState); break; // SEND_OP_COND case 1: _responseQueue.Enqueue((byte)R1Flags.InIdleState); break; // SEND_IF_COND case 8: _responseQueue.Enqueue((byte)R1Flags.InIdleState); _responseQueue.Enqueue(0x00); _responseQueue.Enqueue(0x00); _responseQueue.Enqueue(0x01); _responseQueue.Enqueue(0xAA); break; // SEND_CSD case 9: _responseQueue.Enqueue(0x00); break; // SEND_CID case 10: _responseQueue.Enqueue(0x00); break; // STOP_TRANSMISSION case 12: _blockCount = null; _currentBlock = new byte[0]; _currentBlockNo = 0; _currentByteNo = 0; _responseQueue.Enqueue(0x00); // stuff byte _responseQueue.Enqueue(0x00); break; // SET_BLOCKLEN case 16: _blockSize = (int)param; _responseQueue.Enqueue(0x00); break; // READ_SINGLE_BLOCK case 17: _blockCount = 1; _currentBlockNo = (int)param; _responseQueue.Enqueue(0x00); InitReadMultiple(); _state = SdState.ReadBlock; break; // READ_MULTIPLE_BLOCK case 18: _currentBlockNo = (int)param; _responseQueue.Enqueue(0x00); InitReadMultiple(); _state = SdState.ReadBlock; break; // SET_BLOCK_COUNT case 23: _blockCount = (int)param; _responseQueue.Enqueue(0x00); break; // WRITE_BLOCK case 24: _currentBlockNo = (int)param; _responseQueue.Enqueue(0x00); _state = SdState.WriteSingleIdle; break; // WRITE_MULTIPLE_BLOCK case 25: _currentBlockNo = (int)param; _responseQueue.Enqueue(0x00); _state = SdState.WriteMultipleIdle; break; // APP_CMD (ACMD prefix) case 55: _acmd = true; _responseQueue.Enqueue((byte)R1Flags.InIdleState); break; // READ_OCR case 58: _responseQueue.Enqueue(0x00); break; default: _responseQueue.Enqueue((byte)R1Flags.IllegalCommand); break; } } }