Ejemplo n.º 1
0
        private void DefineRegisters()
        {
            PhyRegisters.CardDetect.Define(this)
            // note: `true` means *no* card
            .WithFlag(0, FieldMode.Read, name: "card_detect", valueProviderCallback: _ => RegisteredPeripheral == null)
            .WithReservedBits(1, 31);

            CoreRegisters.Argument.DefineMany(coreRegistersCollection, 4, (register, idx) =>
            {
                register
                .WithValueField(0, 8, name: $"argument{idx}", writeCallback: (_, val) =>
                {
                    BitHelper.ReplaceBits(ref argumentValue, width: 8, source: val, destinationPosition: 24 - idx * 8);
                })
                .WithIgnoredBits(8, 24);
            });

            CoreRegisters.Command0.Define(coreRegistersCollection)
            .WithIgnoredBits(0, 32);

            CoreRegisters.Command1.Define(coreRegistersCollection)
            .WithIgnoredBits(0, 32);

            CoreRegisters.Command2.Define(coreRegistersCollection)
            .WithValueField(0, 7, out commandIndexField, name: "command_index")
            .WithReservedBits(7, 1)
            .WithIgnoredBits(8, 24);

            CoreRegisters.Command3.Define(coreRegistersCollection)
            .WithEnumField <DoubleWordRegister, ResponseType>(0, 3, out responseTypeField, name: "respone_type")
            .WithReservedBits(3, 2)
            .WithEnumField <DoubleWordRegister, TransferType>(5, 3, out transferTypeField, name: "transfer_type")
            .WithIgnoredBits(8, 24);

            CoreRegisters.IssueCommand.Define(coreRegistersCollection)
            .WithFlag(0, FieldMode.WriteOneToClear, name: "issue_command", writeCallback: (_, val) =>
            {
                if (!val)
                {
                    // we are only interested in `true`
                    return;
                }

                if (RegisteredPeripheral == null)
                {
                    this.Log(LogLevel.Warning, "Issued a 0x{0:X} command with 0x{1:X} argument, but there is no SD card attached", commandIndexField.Value, argumentValue);
                    return;
                }

                this.Log(LogLevel.Noisy, "Issuing command #{0}, transfer type is {1}, response type is {2}", commandIndexField.Value, transferTypeField.Value, responseTypeField.Value);

                var resp = RegisteredPeripheral.HandleCommand(commandIndexField.Value, argumentValue).AsByteArray();

                this.Log(LogLevel.Noisy, "Received response of size {0}", resp.Length);
#if DEBUG_PACKETS
                this.Log(LogLevel.Noisy, Misc.PrettyPrintCollectionHex(resp));
#endif

                var expectedResponseLength = 0;

                switch (responseTypeField.Value)
                {
                case ResponseType.Short:
                    expectedResponseLength = 4;
                    break;

                case ResponseType.Long:
                    expectedResponseLength = 16;
                    break;
                }

                if (resp.Length != expectedResponseLength)
                {
                    this.Log(LogLevel.Warning, "Expected response of length {0} bytes, but received {1} bytes", expectedResponseLength, resp.Length);
                    return;
                }

                for (var i = 0; i < resp.Length; i++)
                {
                    responseBuffer[ResponseBufferLength - 1 - i] = resp[i];
                }

                switch (transferTypeField.Value)
                {
                case TransferType.Read:
                    if (readerStartFlag.Value)
                    {
                        readerStartFlag.Value = false;
                        ReadData();
                    }
                    break;

                case TransferType.Write:
                    if (writerStartFlag.Value)
                    {
                        writerStartFlag.Value = false;
                        WriteData();
                    }
                    break;
                }
            })
            .WithReservedBits(1, 7)
            .WithReservedBits(8, 24);

            CoreRegisters.Response.DefineMany(coreRegistersCollection, ResponseBufferLength, (register, idx) =>
            {
                register
                .WithValueField(0, 8, FieldMode.Read, name: $"Response{idx}", valueProviderCallback: _ =>
                {
                    return(responseBuffer[idx]);
                })
                .WithIgnoredBits(8, 24);
            });

            CoreRegisters.CommandEvent0.Define(coreRegistersCollection)
            .WithIgnoredBits(0, 32);

            CoreRegisters.CommandEvent1.Define(coreRegistersCollection)
            .WithIgnoredBits(0, 32);

            CoreRegisters.CommandEvent2.Define(coreRegistersCollection)
            .WithIgnoredBits(0, 32);

            CoreRegisters.CommandEvent3.Define(coreRegistersCollection)
            .WithFlag(0, FieldMode.Read, name: "cmddone", valueProviderCallback: _ => true)
            .WithReservedBits(1, 1)
            .WithTag("cerrtimeout", 2, 1)
            .WithTag("cerrcrc", 3, 1)
            .WithReservedBits(4, 4)
            .WithIgnoredBits(8, 24);

            CoreRegisters.DataEvent0.Define(coreRegistersCollection)
            .WithIgnoredBits(0, 32);

            CoreRegisters.DataEvent1.Define(coreRegistersCollection)
            .WithIgnoredBits(0, 32);

            CoreRegisters.DataEvent2.Define(coreRegistersCollection)
            .WithIgnoredBits(0, 32);

            CoreRegisters.DataEvent3.Define(coreRegistersCollection)
            .WithFlag(0, FieldMode.Read, name: "datadone", valueProviderCallback: _ => true)
            .WithTag("derrwrite", 1, 1)
            .WithTag("derrtimeout", 2, 1)
            .WithTag("derrcrc", 3, 1)
            .WithReservedBits(4, 4)
            .WithIgnoredBits(8, 24);
            ;

            CoreRegisters.BlockSize.DefineMany(coreRegistersCollection, 2, (register, idx) =>
            {
                register
                .WithValueField(0, 8, name: $"BlockSize{idx}", writeCallback: (_, val) =>
                {
                    BitHelper.ReplaceBits(ref blockSize, width: 8, source: val, destinationPosition: 8 - idx * 8);
                })
                .WithIgnoredBits(8, 24);
            });

            CoreRegisters.BlockCount.DefineMany(coreRegistersCollection, 4, (register, idx) =>
            {
                register
                .WithValueField(0, 8, name: $"BlockCount{idx}", writeCallback: (_, val) =>
                {
                    BitHelper.ReplaceBits(ref blockCount, width: 8, source: val, destinationPosition: 24 - idx * 8);
                })
                .WithIgnoredBits(8, 24);
            });

            ReaderRegisters.ReaderReset.Define(readerRegistersCollection)
            .WithIgnoredBits(0, 1)     // reset bit, no need for handling this
            .WithReservedBits(1, 7)
            .WithIgnoredBits(8, 24);

            ReaderRegisters.ReaderStart.Define(readerRegistersCollection)
            .WithFlag(0, out readerStartFlag, name: "start")
            .WithReservedBits(1, 7)
            .WithIgnoredBits(8, 24);

            ReaderRegisters.ReaderDone.Define(readerRegistersCollection)
            .WithFlag(0, FieldMode.Read, name: "done", valueProviderCallback: _ => true)
            .WithReservedBits(1, 7)
            .WithIgnoredBits(8, 24);

            WriterRegisters.WriterReset.Define(writerRegistersCollection)
            .WithIgnoredBits(0, 1)     // reset bit, no need for handling this
            .WithReservedBits(1, 7)
            .WithIgnoredBits(8, 24);

            WriterRegisters.WriterStart.Define(writerRegistersCollection)
            .WithFlag(0, out writerStartFlag, name: "start")
            .WithReservedBits(1, 7)
            .WithIgnoredBits(8, 24);

            WriterRegisters.WriterDone.Define(writerRegistersCollection)
            .WithFlag(0, FieldMode.Read, name: "done", valueProviderCallback: _ => true)
            .WithReservedBits(1, 7)
            .WithIgnoredBits(8, 24);
        }
        private void DefineRegisters()
        {
            PhyRegisters.CardDetect.Define(this)
            // note: `true` means *no* card
            .WithFlag(0, FieldMode.Read, name: "card_detect", valueProviderCallback: _ => RegisteredPeripheral == null)
            .WithReservedBits(1, 31);

            CoreRegisters.Argument.Define(coreRegistersCollection)
            .WithValueField(0, 32, out argumentValue, name: "argument");

            CoreRegisters.Command.Define(coreRegistersCollection)
            .WithEnumField <DoubleWordRegister, ResponseType>(0, 2, out responseTypeField, name: "respone_type")
            .WithReservedBits(2, 3)
            .WithEnumField <DoubleWordRegister, TransferType>(5, 2, out transferTypeField, name: "transfer_type")
            .WithReservedBits(7, 1)
            .WithValueField(8, 6, out commandIndexField, name: "command_index")
            .WithReservedBits(14, 18);

            CoreRegisters.IssueCommand.Define(coreRegistersCollection)
            .WithFlag(0, FieldMode.WriteOneToClear, name: "issue_command", writeCallback: (_, val) =>
            {
                if (!val)
                {
                    // we are only interested in `true`
                    return;
                }

                if (RegisteredPeripheral == null)
                {
                    this.Log(LogLevel.Warning, "Issued a 0x{0:X} command with 0x{1:X} argument, but there is no SD card attached", commandIndexField.Value, argumentValue.Value);
                    return;
                }

                this.Log(LogLevel.Noisy, "Issuing command #{0}, transfer type is {1}, response type is {2}", commandIndexField.Value, transferTypeField.Value, responseTypeField.Value);

                var resp = RegisteredPeripheral.HandleCommand(commandIndexField.Value, argumentValue.Value).AsByteArray();

                this.Log(LogLevel.Noisy, "Received response of size {0}", resp.Length);
#if DEBUG_PACKETS
                this.Log(LogLevel.Noisy, Misc.PrettyPrintCollectionHex(resp));
#endif

                var expectedResponseLength = 0;

                switch (responseTypeField.Value)
                {
                case ResponseType.Short:
                    expectedResponseLength = 4;
                    break;

                case ResponseType.Long:
                    expectedResponseLength = 16;
                    break;
                }

                if (resp.Length != expectedResponseLength)
                {
                    this.Log(LogLevel.Warning, "Expected response of length {0} bytes, but received {1} bytes", expectedResponseLength, resp.Length);
                    return;
                }

                for (var i = 0; i < resp.Length; i++)
                {
                    responseBuffer[ResponseBufferLength - 1 - i] = resp[i];
                    //responseBuffer[i] = resp[i];
                }

                switch (transferTypeField.Value)
                {
                case TransferType.Read:
                    if (dmaReaderEnabled.Value)
                    {
                        ReadData();
                    }
                    break;

                case TransferType.Write:
                    if (dmaWriterEnabled.Value)
                    {
                        WriteData();
                    }
                    break;
                }
            })
            .WithReservedBits(1, 7)
            .WithReservedBits(8, 24);

            CoreRegisters.Response.DefineMany(coreRegistersCollection, ResponseBufferLength / 4, (register, idx) =>
            {
                register
                .WithValueField(0, 8, FieldMode.Read, name: $"Response{(4 * idx + 0)}", valueProviderCallback: _ => responseBuffer[4 * idx + 3])
                .WithValueField(8, 8, FieldMode.Read, name: $"Response{(4 * idx + 1)}", valueProviderCallback: _ => responseBuffer[4 * idx + 2])
                .WithValueField(16, 8, FieldMode.Read, name: $"Response{(4 * idx + 2)}", valueProviderCallback: _ => responseBuffer[4 * idx + 1])
                .WithValueField(24, 8, FieldMode.Read, name: $"Response{(4 * idx + 3)}", valueProviderCallback: _ => responseBuffer[4 * idx + 0]);
            });

            CoreRegisters.CommandEvent.Define(coreRegistersCollection)
            .WithFlag(0, FieldMode.Read, name: "cmddone", valueProviderCallback: _ => true)
            .WithTag("cerrwrite", 1, 1)
            .WithTag("cerrtimeout", 2, 1)
            .WithTag("cerrcrc", 3, 1)
            .WithReservedBits(4, 28);

            CoreRegisters.DataEvent.Define(coreRegistersCollection)
            .WithFlag(0, FieldMode.Read, name: "datadone", valueProviderCallback: _ => true)
            .WithTag("derrwrite", 1, 1)
            .WithTag("derrtimeout", 2, 1)
            .WithTag("derrcrc", 3, 1)
            .WithReservedBits(4, 28);

            CoreRegisters.BlockSize.Define(coreRegistersCollection)
            .WithValueField(0, 10, out blockSize, name: "BlockSize")
            .WithReservedBits(10, 22);

            CoreRegisters.BlockCount.Define(coreRegistersCollection)
            .WithValueField(0, 32, out blockCount, name: "BlockSize");

            ReaderRegisters.DmaBase.DefineMany(readerRegistersCollection, 2, (register, idx) =>
            {
                register
                .WithValueField(0, 32, name: $"ReaderAddress{idx}",
                                writeCallback: (_, val) => BitHelper.ReplaceBits(ref readerAddress, val, width: 32, destinationPosition: 32 - idx * 32),
                                valueProviderCallback: _ => (uint)BitHelper.GetValue(readerAddress, offset: 32 - idx * 32, size: 32));
            });

            ReaderRegisters.DmaLength.Define(readerRegistersCollection)
            .WithValueField(0, 32, out readerLength, name: "ReaderLength");

            ReaderRegisters.DmaEnable.Define(readerRegistersCollection)
            .WithFlag(0, out dmaReaderEnabled, name: "enable")
            .WithReservedBits(1, 31);

            ReaderRegisters.DmaDone.Define(readerRegistersCollection)
            .WithFlag(0, name: "done", valueProviderCallback: _ => true)
            .WithReservedBits(1, 31);

            ReaderRegisters.DmaLoop.Define(readerRegistersCollection)
            .WithTag("loop", 0, 1)
            .WithReservedBits(1, 31);

            WriterRegisters.DmaBase.DefineMany(writerRegistersCollection, 2, (register, idx) =>
            {
                register
                .WithValueField(0, 32, name: $"WriterAddress{idx}",
                                writeCallback: (_, val) => BitHelper.ReplaceBits(ref writerAddress, val, width: 32, destinationPosition: 32 - idx * 32),
                                valueProviderCallback: _ => (uint)BitHelper.GetValue(writerAddress, offset: 32 - idx * 32, size: 32));
            });

            WriterRegisters.DmaLength.Define(writerRegistersCollection)
            .WithValueField(0, 32, out writerLength, name: "WriterLength");

            WriterRegisters.DmaEnable.Define(writerRegistersCollection)
            .WithFlag(0, out dmaWriterEnabled, name: "enable")
            .WithReservedBits(1, 31);

            WriterRegisters.DmaDone.Define(writerRegistersCollection)
            .WithFlag(0, name: "done", valueProviderCallback: _ => true)
            .WithReservedBits(1, 31);

            WriterRegisters.DmaLoop.Define(writerRegistersCollection)
            .WithTag("loop", 0, 1)
            .WithReservedBits(1, 31);
        }