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); }