Пример #1
0
        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;
        }
Пример #2
0
        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);
        }
Пример #3
0
        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);
        }
Пример #4
0
        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;
        }
Пример #5
0
        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;
                }
            }
        }