public override void Reset() { RegisteredPeripheral?.Reset(); RegistersCollection.Reset(); irqManager.Reset(); internalBuffer.Clear(); }
public uint ReadDoubleWord(long offset) { switch ((Registers)offset) { case Registers.Control: return(controlRegister); case Registers.Status: return(HandleStatusRegister()); case Registers.Data: IRQ.Unset(); if (RegisteredPeripheral != null) { dataRegister = RegisteredPeripheral.Read(); } return(dataRegister); case Registers.ClockDivisor: return(clkDivRegister); case Registers.InterruptIdentification: return(IRQ.IsSet ? 1u : 0u); default: return(idHelper.Read(offset)); } }
public void Dispose() { if (RegisteredPeripheral != null) { RegisteredPeripheral.Dispose(); } }
private void WriteData() { var data = writerDataBuffer.Take((int)blockSize).ToArray(); this.Log(LogLevel.Noisy, "Writing data: {0}", Misc.PrettyPrintCollectionHex(data)); RegisteredPeripheral.WriteData(data); }
private void sendCommand(uint command, uint length) { //TODO: Endianess writeOccured = true; transferFIFODataCount = 0; this.Log(LogLevel.Warning, "Flash command {0:X}", command); switch ((SPIFlashCommand)(command & 0xff)) { case SPIFlashCommand.ReadID: //TODO: polarization var ID = 0xffffffffu; //return 0xffffffff if there is no flash attached if (RegisteredPeripheral != null) { ID = RegisteredPeripheral.ReadID(); } registers.ReceiveData = ID; receiveFIFODataCount += 1; break; default: receiveFIFODataCount += 1; //XXX: ugly this.Log(LogLevel.Warning, "Unimplemented SPI Flash command {0:X}", command); break; } }
private void TryFinishTransmission() { bytesSent++; if (bytesSent == totalBytes) { RegisteredPeripheral.FinishTransmission(); } }
private void DisableSSI(bool oldValue, bool newValue) { this.Log(LogLevel.Debug, "SSI {0}.", newValue ? "enabled" : "disabled"); receiveFifo.Clear(); RefreshInterrupt(); if (!newValue && oldValue) { RegisteredPeripheral.FinishTransmission(); } }
private void ReadData() { if (blockCount != 1) { this.Log(LogLevel.Warning, "This model curently supports only reading a sinlge block at a time, but the block count is set to {0}", blockCount); return; } readerDataBuffer = RegisteredPeripheral.ReadData(blockSize); this.Log(LogLevel.Noisy, "Received data is: {0}", Misc.PrettyPrintCollectionHex(readerDataBuffer)); }
public void WriteChar(byte value) { if (RegisteredPeripheral != null) { return; } var charReceived = CharReceived; var read = RegisteredPeripheral.Transmit(value); charReceived(read); }
private void WriteData() { writerAddress &= 0xffffffff; var data = Machine.SystemBus.ReadBytes(writerAddress, (int)writerLength.Value); #if DEBUG_PACKETS this.Log(LogLevel.Noisy, "Writing {0} bytes of data read from 0x{1:X} to the device: {2}", data.Length, writerAddress, Misc.PrettyPrintCollectionHex(data)); #endif RegisteredPeripheral.WriteData(data); }
private void ReadData() { readerAddress &= 0xffffffff; var data = RegisteredPeripheral.ReadData(readerLength.Value); #if DEBUG_PACKETS this.Log(LogLevel.Noisy, "Reading {0} bytes of data from device: {1}. Writing it to 0x{2:X}", data.Length, Misc.PrettyPrintCollectionHex(data), readerAddress); #endif Machine.SystemBus.WriteBytes(data, readerAddress); }
public PicoRV_SPI(Machine machine) : base(machine) { bbHelper = new BitBangHelper(8, loggingParent: this, outputMsbFirst: true); var registers = new Dictionary <long, DoubleWordRegister> { { (long)Registers.Config1, new DoubleWordRegister(this) .WithFlag(0, out var data0, FieldMode.Write, name: "data0") .WithFlag(1, FieldMode.Write, name: "data1") // data 1-3 used in QSPI only .WithFlag(2, FieldMode.Write, name: "data2") .WithFlag(3, FieldMode.Write, name: "data3") .WithFlag(4, out var clock, FieldMode.Write, name: "clk") .WithFlag(5, out var chipSelectNegated, FieldMode.Write, name: "cs_n") .WithReservedBits(6, 2) .WithWriteCallback((_, val) => { if (memioEnable.Value) { this.Log(LogLevel.Warning, "MEMIO mode not enabled - bit banging not supported in this mode"); return; } if (qspiEnable.Value) { this.Log(LogLevel.Warning, "QSPI mode not yet supported"); return; } if (RegisteredPeripheral == null) { this.Log(LogLevel.Warning, "Trying to send bytes over SPI, but there is no device attached"); return; } if (chipSelectNegated.Value && !previousChipSelectNegated) { this.Log(LogLevel.Noisy, "ChipSelect signal down - finishing the transmission"); RegisteredPeripheral.FinishTransmission(); bbHelper.ResetOutput(); } previousChipSelectNegated = chipSelectNegated.Value; // do not latch bits when MEMIO is enabled or chipSelect is not set if (bbHelper.Update(clock.Value, data0.Value, !memioEnable.Value && !chipSelectNegated.Value)) { this.Log(LogLevel.Noisy, "Sending byte 0x{0:X}", bbHelper.DecodedOutput); var input = RegisteredPeripheral.Transmit((byte)bbHelper.DecodedOutput); this.Log(LogLevel.Noisy, "Received byte 0x{0:X}", input); bbHelper.SetInputBuffer(input); } }) },
private void HandleByteReception() { var receivedByte = RegisteredPeripheral.Transmit(0); if (bytesToSkip > 0) { bytesToSkip--; } else { TryReceive(receivedByte); } TryFinishTransmission(); }
public LiteX_SPI_Flash(Machine machine) : base(machine) { bbHelper = new BitBangHelper(8, loggingParent: this, outputMsbFirst: true); var registers = new Dictionary <long, DoubleWordRegister> { { (long)Registers.BitBang, new DoubleWordRegister(this) .WithFlag(0, out var valueSignal, FieldMode.Write, name: "value") .WithFlag(1, out var clockSignal, FieldMode.Write, name: "clk") .WithFlag(2, out var chipSelectNegatedSignal, FieldMode.Write, name: "cs_n") .WithFlag(3, out var dqInputSignal, FieldMode.Write, name: "dq_input") .WithWriteCallback((_, val) => { if (!bitBangEnabled.Value) { this.Log(LogLevel.Warning, "Write to not-enabled BitBang register ignored"); return; } if (RegisteredPeripheral == null) { this.Log(LogLevel.Warning, "Trying to send bytes over SPI, but there is no device attached"); return; } if (chipSelectNegatedSignal.Value && !previousChipSelectNegatedSignal) { this.Log(LogLevel.Noisy, "ChipSelect signal down - finishing the transmission"); RegisteredPeripheral.FinishTransmission(); } previousChipSelectNegatedSignal = chipSelectNegatedSignal.Value; // do not latch bits when dqInputSignal is set or chipSelect is not set if (bbHelper.Update(clockSignal.Value, valueSignal.Value, !dqInputSignal.Value && !chipSelectNegatedSignal.Value)) { this.Log(LogLevel.Noisy, "Sending byte 0x{0:X}", bbHelper.DecodedOutput); var input = RegisteredPeripheral.Transmit((byte)bbHelper.DecodedOutput); this.Log(LogLevel.Noisy, "Received byte 0x{0:X}", input); bbHelper.SetInputBuffer(input); } }) },
private void TryStartTransmission() { if (!txEnable.Value || command != Commands.TransferData) { this.Log(LogLevel.Debug, "Tried to issue a transaction without full configuration."); return; } if (RegisteredPeripheral == null) { this.Log(LogLevel.Warning, "Trying to issue a transaction to a slave peripheral, but nothing is connected"); return; } foreach (var b in Machine.SystemBus.ReadBytes(txTransferAddress.Value, (int)txTransferBufferSize.Value)) { RegisteredPeripheral.Transmit(b); } RegisteredPeripheral.FinishTransmission(); command = Commands.None; TxIRQ.Blink(); }
private void WriteData(uint unused, uint data) { if (!ssiEnabled.Value) { return; } if (transferMode.Value == TransferMode.ReceiveOnly || transferMode.Value == TransferMode.EEPROMRead) { // note that number of data frames (NDF field in second control register) is important in this transfer mode // see datasheet for details this.Log(LogLevel.Error, "Unhandled transfer mode {0}.", transferMode); } RefreshInterrupt(true); // although we immediately transfer the byte, the interrupt line has to be turned off for the moment var result = RegisteredPeripheral.Transmit((byte)data); if (transferMode.Value == TransferMode.TransmitAndReceive) { receiveFifo.Enqueue(result); } RefreshInterrupt(); }
private void SendData(byte b) { if (!enabled) { this.Log(LogLevel.Warning, "Trying to send data, but the controller is disabled"); return; } if (RegisteredPeripheral == null) { this.Log(LogLevel.Warning, "No device connected"); return; } if (receiveFifo.Count == ReceiveBufferSize) { this.Log(LogLevel.Warning, "Buffers full, ignoring data"); return; } // there is no need to queue transmitted bytes - let's send them right away var result = RegisteredPeripheral.Transmit(b); lock (receiveFifo) { receiveFifo.Enqueue(result); // the READY event is generated // only when the head // of the queue changes if (receiveFifo.Count == 1) { readyPending.Value = true; UpdateInterrupts(); } } }
public void WriteDoubleWord(long offset, uint value) { switch ((Registers)offset) { case Registers.Control: controlRegister = value; break; case Registers.Data: if (RegisteredPeripheral != null) { RegisteredPeripheral.Write((byte)value); } break; case Registers.ClockDivisor: clkDivRegister = value; break; default: this.LogUnhandledWrite(offset, value); break; } }
private void TryStartReception() { if (!rxEnable.Value || command != Commands.ReceiveData) { this.Log(LogLevel.Debug, "Tried to issue a transaction without full configuration."); return; } if (RegisteredPeripheral == null) { this.Log(LogLevel.Warning, "Trying to issue a transaction to a slave peripheral, but nothing is connected"); return; } var receiveQueue = new Queue <byte>(); for (int i = 0; i < (int)rxTransferBufferSize.Value; i++) { receiveQueue.Enqueue(RegisteredPeripheral.Transmit(0)); } RegisteredPeripheral.FinishTransmission(); Machine.SystemBus.WriteBytes(receiveQueue.ToArray(), rxTransferAddress.Value); receiveQueue.Clear(); command = Commands.None; RxIRQ.Blink(); }
private void HandleByteReception() { TryReceive(RegisteredPeripheral.Transmit(0)); TryFinishTransmission(); }
private void HandleByteTransmission(uint val) { RegisteredPeripheral.Transmit((byte)val); TryFinishTransmission(); }
public void Dispose() { RegisteredPeripheral?.Dispose(); }
protected override void SendSdConfigurationValue() { byte[] data = BitConverter.GetBytes(RegisteredPeripheral.SendSdConfigurationValue()); DmaTransfer(data, 8, DataDirection.ReadFromSD); }
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); }
public uint ReadDoubleWord(long offset) { return(xipMode.Value ? RegisteredPeripheral.ReadDoubleWord(BitHelper.SetBitsFrom((uint)offset, upperAddress.Value, 24, 8)) : registers.Read(offset)); }
protected uint[] ExecuteCommand(uint command, uint args, bool sendInitSequence, bool dataTransfer) { var response = new uint[4]; if (RegisteredPeripheral == null) { return(response); } switch ((Commands)command) { case Commands.GoIdleState: if (sendInitSequence) { response[0] = RegisteredPeripheral.GoIdleState(); } break; case Commands.SendOpCond: case Commands.IoSendOpCond: response[0] = RegisteredPeripheral.SendOpCond(); break; case Commands.SendStatus: response[0] = RegisteredPeripheral.SendStatus(dataTransfer); break; case Commands.SendSdConfiguration: SendSdConfigurationValue(); break; case Commands.SetRelativeAddress: response[0] = RegisteredPeripheral.SetRelativeAddress(); break; case Commands.SelectDeselectCard: response[0] = RegisteredPeripheral.SelectDeselectCard(); break; case Commands.SendExtendedCardSpecificData: response[0] = RegisteredPeripheral.SendExtendedCardSpecificData(); break; case Commands.SendCardSpecificData: response = RegisteredPeripheral.SendCardSpecificData(); break; case Commands.AllSendCid: return(RegisteredPeripheral.AllSendCardIdentification()); case Commands.AppCommand: response[0] = RegisteredPeripheral.AppCommand(args); break; case Commands.Switch: response[0] = RegisteredPeripheral.Switch(); break; case Commands.MmcSendAppOpCode: response[0] = RegisteredPeripheral.SendAppOpCode(args); break; case Commands.ReadMultipleBlocks: TransferDataFromCard(args, ByteCount); break; case Commands.ReadSingleBlock: TransferDataFromCard(args, BlockSize); break; case Commands.WriteMultipleBlocks: TransferDataToCard(args, ByteCount); break; default: this.Log(LogLevel.Warning, "Unhandled MMC command: 0x{0:X} with args 0x{1:X}", command, args); break; } return(response); }
protected void WriteToCard(uint cardOffset, byte[] data) { RegisteredPeripheral.WriteData((long)BlockSize * cardOffset, data.Length, data); }
protected byte[] ReadFromCard(uint cardOffset, int bytes) { return(RegisteredPeripheral.ReadData((long)BlockSize * cardOffset, bytes)); }
public override void Reset() { RegisteredPeripheral.Reset(); }
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); }