private void PrepareRegisters() { registers = new DoubleWordRegisterCollection(this, new Dictionary <long, DoubleWordRegister> { { (long)Registers.PortAData, new DoubleWordRegister(this) .WithValueField(0, 32, writeCallback: (_, val) => { var bits = BitHelper.GetBits(val); for (int i = 0; i < bits.Length; i++) { if (PortDataDirection[i] == PinDirection.Output) { Connections[i].Set(bits[i]); State[i] = bits[i]; } } }, valueProviderCallback: _ => { return(BitHelper.GetValueFromBitsArray(State)); }) }, { (long)Registers.PortADataDirection, new DoubleWordRegister(this) .WithValueField(0, 32, writeCallback: (_, val) => Array.Copy(BitHelper.GetBits(val).Select(x => x ? PinDirection.Output : PinDirection.Input).ToArray(), PortDataDirection, 32), valueProviderCallback: _ => BitHelper.GetValueFromBitsArray(PortDataDirection.Select(x => x == PinDirection.Output))) }, { (long)Registers.InterruptEnable, new DoubleWordRegister(this) .WithValueField(0, 32, writeCallback: (_, val) => { Array.Copy(BitHelper.GetBits(val), InterruptEnable, 32); RefreshInterrupts(); }, valueProviderCallback: _ => BitHelper.GetValueFromBitsArray(InterruptEnable)) }, { (long)Registers.InterruptType, new DoubleWordRegister(this) // true = edge sensitive; false = level sensitive .WithValueField(0, 32, out interruptTypeField, writeCallback: (_, val) => CalculateInterruptTypes()) }, { (long)Registers.InterruptPolarity, new DoubleWordRegister(this) // true = rising edge / active high; false = falling edge / active low .WithValueField(0, 32, out interruptPolarityField, writeCallback: (_, val) => CalculateInterruptTypes()) }, { (long)Registers.InterruptBothEdgeType, new DoubleWordRegister(this) .WithValueField(0, 32, out interruptBothEdgeField, writeCallback: (_, val) => CalculateInterruptTypes()) }, { (long)Registers.InterruptMask, new DoubleWordRegister(this) .WithValueField(0, 32, writeCallback: (_, val) => { Array.Copy(BitHelper.GetBits(val), InterruptMask, 32); RefreshInterrupts(); }, valueProviderCallback: _ => BitHelper.GetValueFromBitsArray(InterruptMask)) }, { (long)Registers.PortAExternalPort, new DoubleWordRegister(this) .WithValueField(0, 32, FieldMode.Read, valueProviderCallback: _ => BitHelper.GetValueFromBitsArray(State)) }, { (long)Registers.ClearInterrupt, new DoubleWordRegister(this) .WithValueField(0, 32, FieldMode.Write, writeCallback: (_, val) => { foreach (var bit in BitHelper.GetSetBits(val)) { activeInterrupts[bit] = false; } RefreshInterrupts(); }) }, { (long)Registers.InterruptStatus, new DoubleWordRegister(this) .WithValueField(0, 32, FieldMode.Read, valueProviderCallback: _ => BitHelper.GetValueFromBitsArray(activeInterrupts.Zip(InterruptMask, (isActive, isMasked) => isActive && !isMasked))) }, { (long)Registers.RawInterruptStatus, new DoubleWordRegister(this) .WithValueField(0, 32, FieldMode.Read, valueProviderCallback: _ => BitHelper.GetValueFromBitsArray(activeInterrupts)) } }); }
public void DosDateTimeToFileTimeTest() { var ft = new DateTime(2019, 10, 29, 13, 51, 24, DateTimeKind.Local).ToFileTimeStruct(); Assert.That(FileTimeToDosDateTime(ft, out var fatDate, out var fatTime), ResultIs.Successful); Assert.That(BitHelper.GetBits(fatDate, 5, 4), Is.EqualTo(10)); Assert.That(DosDateTimeToFileTime(fatDate, fatTime, out var outFt), ResultIs.Successful); Assert.That(outFt.ToUInt64(), Is.EqualTo(ft.ToUInt64())); }
private void RefreshConnectionsState() { var outputBits = BitHelper.GetBits(outputEnable.Value); var bits = BitHelper.GetBits(output.Value); for (var i = 0; i < 32; i++) { Connections[i].Set(bits[i] && outputBits[i]); } }
private void ActionOnChannels(Action <Channel, bool> action, uint selector) { var index = 0; foreach (var bit in BitHelper.GetBits(selector)) { action(channels[index], bit); index++; } }
private void CreateRegisters() { var regs = new Dictionary <long, DoubleWordRegister>() { { (long)Registers.ExternalInterruptPortSelectLow, new DoubleWordRegister(this) .WithValueField(0, 32, changeCallback: (oldValue, newValue) => ReroutePort(oldValue, newValue, false), name: "EXTIPSEL") }, { (long)Registers.ExternalInterruptPortSelectHigh, new DoubleWordRegister(this) .WithValueField(0, 32, changeCallback: (oldValue, newValue) => ReroutePort(oldValue, newValue, true), name: "EXTIPSEL") }, { (long)Registers.ExternalInterruptPinSelectLow, new DoubleWordRegister(this, 0x32103210) .WithValueField(0, 32, changeCallback: (oldValue, newValue) => ReroutePin(oldValue, newValue, false), name: "EXTIPINSEL") }, { (long)Registers.ExternalInterruptPinSelectHigh, new DoubleWordRegister(this, 0x32103210) .WithValueField(0, 32, changeCallback: (oldValue, newValue) => ReroutePin(oldValue, newValue, true), name: "EXTIPINSEL") }, { (long)Registers.ExternalInterruptRisingEdgeTrigger, new DoubleWordRegister(this) .WithValueField(0, 16, changeCallback: (_, value) => SetEdgeSensitivity(value, InterruptTrigger.RisingEdge)) }, { (long)Registers.ExternalInterruptFallingEdgeTrigger, new DoubleWordRegister(this) .WithValueField(0, 16, changeCallback: (_, value) => SetEdgeSensitivity(value, InterruptTrigger.FallingEdge)) }, { (long)Registers.InterruptFlag, new DoubleWordRegister(this) .WithValueField(0, 16, FieldMode.Read, valueProviderCallback: (_) => BitHelper.GetValueFromBitsArray(externalInterrupt), name: "EXT") .WithTag("EM4WU", 16, 16) }, { (long)Registers.InterruptFlagSet, new DoubleWordRegister(this) .WithValueField(0, 16, FieldMode.Write, writeCallback: (_, value) => UpdateExternalInterruptBits(value, true), name: "EXT") .WithTag("EM4WU", 16, 16) }, { (long)Registers.InterruptFlagClear, new DoubleWordRegister(this) .WithValueField(0, 16, writeCallback: (_, value) => UpdateExternalInterruptBits(value, false), valueProviderCallback: (_) => { var result = BitHelper.GetValueFromBitsArray(externalInterrupt); for (var i = 0; i < NumberOfExternalInterrupts; ++i) { externalInterrupt[i] = false; } UpdateInterrupts(); return(result); }, name: "EXT") .WithTag("EM4WU", 16, 16) }, { (long)Registers.InterruptEnable, new DoubleWordRegister(this) .WithValueField(0, 16, writeCallback: (_, value) => { Array.Copy(BitHelper.GetBits(value), interruptEnable, NumberOfExternalInterrupts); UpdateInterrupts(); }, valueProviderCallback: (_) => BitHelper.GetValueFromBitsArray(interruptEnable), name: "EXT") .WithTag("EM4WU", 16, 16) }, { (long)Registers.ConfigurationLock, new DoubleWordRegister(this) .WithValueField(0, 16, writeCallback: (_, value) => configurationLocked = (value != UnlockCode), valueProviderCallback: (_) => configurationLocked ? 1 : 0u, name: "LOCKKEY") }, }; for (var i = 0; i < NumberOfPorts; ++i) { CreatePortRegisters(regs, i); } registers = new DoubleWordRegisterCollection(this, regs); }
public SimplePeripheral(Machine machine) : base(machine) { IValueRegisterField value; Registers.Base.Define(this) .WithValueField(0, 32, out value, FieldMode.Write); Registers.Multiplier.Define(this) .WithValueField(0, 32, FieldMode.Read, valueProviderCallback: _ => value.Value * 2); Registers.BitCounter.Define(this) .WithValueField(0, 32, FieldMode.Read, valueProviderCallback: _ => (uint)BitHelper.GetBits(value.Value).Where(x => x).Select(x => 1).Sum(x => x)); }
private void MipChanged(uint mip) { var previousMip = BitHelper.GetBits(TlibGetMip()); var currentMip = BitHelper.GetBits(mip); foreach (var gpio in intTypeToVal.Lefts) { intTypeToVal.TryGetValue(gpio, out IrqType decodedType); if (previousMip[(int)decodedType] != currentMip[(int)decodedType]) { OnGPIO(gpio, currentMip[(int)decodedType]); } } }
private void SetOutputEnableMasked(uint value, bool lower) { var offset = lower ? 0 : 16; var data = BitHelper.GetBits(value & 0xFFFF); var mask = BitHelper.GetBits(value >> 16); for (var i = 0; i < 16; ++i) { if (mask[i]) { directOutputEnabled[i + offset] = data[i]; } } UpdateConnections(); }
private void SetEdgeSensitivity(uint value, InterruptTrigger trigger) { var bits = BitHelper.GetBits(value); for (var i = 0; i < interruptTriggers.Length; ++i) { if (bits[i]) { interruptTriggers[i] |= trigger; } else { interruptTriggers[i] ^= trigger; } } }
public SiFive_GPIO(Machine machine) : base(machine, 32) { locker = new object(); var registersMap = new Dictionary <long, DoubleWordRegister> { { (long)Registers.OutputPortValue, new DoubleWordRegister(this) .WithValueField(0, 32, valueProviderCallback: _ => { lock (locker) { return(BitHelper.GetValueFromBitsArray(Connections.Where(x => x.Key >= 0).OrderBy(x => x.Key).Select(x => x.Value.IsSet))); } }, writeCallback: (_, val) => { lock (locker) { var bits = BitHelper.GetBits(val); for (var i = 0; i < bits.Length; i++) { Connections[i].Set(State[i] || bits[i]); } } }) }, { (long)Registers.RiseInterruptPending, new DoubleWordRegister(this) .WithValueField(0, 32, writeCallback: (_, val) => { lock (locker) { var bits = BitHelper.GetBits(val); for (var i = 0; i < bits.Length; i++) { if (bits[i]) { Connections[i].Set(State[i]); } } } }) } }; registers = new DoubleWordRegisterCollection(this, registersMap); }
private void DefineRegisters() { // according to LiteX-generated `csr.h` this register is readable Registers.Leds.Define(this) .WithValueField(0, LedsCount, valueProviderCallback: _ => BitHelper.GetValueFromBitsArray(Connections.Where(x => x.Key >= 0).OrderBy(x => x.Key).Select(x => x.Value.IsSet)), writeCallback: (_, val) => { var bits = BitHelper.GetBits(val); for (var i = 0; i < LedsCount; i++) { Connections[i].Set(bits[i]); } }) ; Registers.Switches.Define(this) .WithValueField(0, SwitchesCount, FieldMode.Read, valueProviderCallback: _ => BitHelper.GetValueFromBitsArray(this.State.Skip(LedsCount).Take(SwitchesCount))) ; Registers.ButtonsStatus.Define(this) .WithValueField(0, ButtonsCount, FieldMode.Read, valueProviderCallback: _ => BitHelper.GetValueFromBitsArray(this.State.Skip(LedsCount + SwitchesCount).Take(ButtonsCount))) ; Registers.ButtonsPending.Define(this) .WithValueField(0, ButtonsCount, valueProviderCallback: _ => BitHelper.GetValueFromBitsArray(buttonsPending), writeCallback: (_, val) => { foreach (var bit in BitHelper.GetSetBits(val)) { buttonsPending[bit] = false; } UpdateInterrupt(); }) ; Registers.ButtonsEnabled.Define(this) .WithValueField(0, ButtonsCount, out buttonsEnabled, writeCallback: (_, __) => { UpdateInterrupt(); }) ; }
private int DefineOutRegisters(long offset) { var size = 0; ((Registers)offset).Define(this) .WithValueField(0, NumberOfPins, name: "Out", writeCallback: (_, val) => { var bits = BitHelper.GetBits(val); for (var i = 0; i < bits.Length; i++) { Connections[i].Set(bits[i]); } }, valueProviderCallback: _ => BitHelper.GetValueFromBitsArray(Connections.Where(x => x.Key >= 0).OrderBy(x => x.Key).Select(x => x.Value.IsSet))); size += 0x4; return(size); }
private void AddTargetEnablesRegister(Dictionary <long, DoubleWordRegister> registersMap, long address, uint hartId, PrivilegeLevel level, int numberOfSources) { var maximumSourceDoubleWords = (int)Math.Ceiling((numberOfSources + 1) / 32.0) * 4; for (var offset = 0u; offset < maximumSourceDoubleWords; offset += 4) { var lOffset = offset; registersMap.Add(address + offset, new DoubleWordRegister(this).WithValueField(0, 32, writeCallback: (_, value) => { lock (irqSources) { // Each source is represented by one bit. offset and lOffset indicate the offset in double words from TargetXEnables, // `bit` is the bit number in the given double word, // and `sourceIdBase + bit` indicate the source number. var sourceIdBase = lOffset * 8; var bits = BitHelper.GetBits(value); for (var bit = 0u; bit < bits.Length; bit++) { var sourceNumber = sourceIdBase + bit; if (sourceNumber == 0) { // Source number 0 is not used. continue; } if (irqSources.Length <= sourceNumber) { if (bits[bit]) { this.Log(LogLevel.Noisy, "Trying to enable non-existing source: {0}", sourceNumber); } continue; } this.Log(LogLevel.Noisy, "{0} source #{1} for hart {2} on level {3}", bits[bit] ? "Enabling" : "Disabling", sourceNumber, hartId, level); irqTargets[hartId].levels[(int)level].EnableSource(irqSources[sourceNumber], bits[bit]); } RefreshInterrupts(); } })); } }
public uint ReadDoubleWord(long offset) { lock (locker) { if (offset < 0x400) { var mask = BitHelper.GetBits((uint)(offset >> 2) & 0xFF); var bits = BitHelper.GetBits(registers.Read(0)); var result = new bool[8]; for (var i = 0; i < 8; i++) { if (mask[i]) { result[i] = bits[i]; } } return(BitHelper.GetValueFromBitsArray(result)); } return(registers.Read(offset)); } }
public void WriteDoubleWord(long offset, uint value) { lock (locker) { if (offset < 0x400) { var mask = BitHelper.GetBits((uint)(offset >> 2) & 0xFF); var bits = BitHelper.GetBits(value); for (var i = 0; i < 8; i++) { if (mask[i]) { Connections[i].Set(bits[i]); State[i] = bits[i]; } } } else { registers.Write(offset, value); } } }
public PSE_GPIO(Machine machine) : base(machine, 32) { locker = new object(); IRQ = new GPIO(); irqManager = new GPIOInterruptManager(IRQ, State); var registersMap = new Dictionary <long, DoubleWordRegister> { { (long)Registers.InterruptRegister, new DoubleWordRegister(this) .WithValueField(0, 32, writeCallback: (_, val) => { foreach (var i in BitHelper.GetSetBits(val)) { irqManager.ClearInterrupt(i); if ((irqManager.PinDirection[i] & GPIOInterruptManager.Direction.Input) != 0) { Connections[i].Set(false); } } }, valueProviderCallback: _ => BitHelper.GetValueFromBitsArray(irqManager.ActiveInterrupts), name: "INTR") }, { (long)Registers.InputRegister, new DoubleWordRegister(this) .WithValueField(0, 32, out inputReg, FieldMode.Read, valueProviderCallback: val => { var pins = irqManager.PinDirection.Select(x => (x & GPIOInterruptManager.Direction.Input) != 0); var result = pins.Zip(State, (pin, state) => pin && state); return(BitHelper.GetValueFromBitsArray(result)); }, name: "GPIN") }, { (long)Registers.OutputRegister, new DoubleWordRegister(this) .WithValueField(0, 32, valueProviderCallback: val => { var pins = irqManager.PinDirection.Select(x => (x & GPIOInterruptManager.Direction.Output) != 0); var result = pins.Zip(Connections.Values, (pin, state) => pin && state.IsSet); return(BitHelper.GetValueFromBitsArray(result)); }, writeCallback: (_, val) => { // Potentially we should raise an exception, as GPIO is bidirectional, // but we do not have such infrastructure. var bits = BitHelper.GetBits(val); for (var i = 0; i < bits.Length; i++) { if ((irqManager.PinDirection[i] & GPIOInterruptManager.Direction.Output) != 0) { Connections[i].Set(bits[i]); } } }, name: "GPOUT") }, { (long)Registers.ClearRegister, new DoubleWordRegister(this) .WithValueField(0, 32, writeCallback: (_, val) => SetRegisterBits(val, false), name: "CLEAR_BITS") }, { (long)Registers.SetRegister, new DoubleWordRegister(this) .WithValueField(0, 32, writeCallback: (_, val) => SetRegisterBits(val, true), name: "SET_BITS") }, }; var intTypeToVal = new TwoWayDictionary <GPIOInterruptManager.InterruptTrigger, uint>(); intTypeToVal.Add(GPIOInterruptManager.InterruptTrigger.ActiveHigh, 0); intTypeToVal.Add(GPIOInterruptManager.InterruptTrigger.ActiveLow, 1); intTypeToVal.Add(GPIOInterruptManager.InterruptTrigger.RisingEdge, 2); intTypeToVal.Add(GPIOInterruptManager.InterruptTrigger.FallingEdge, 3); intTypeToVal.Add(GPIOInterruptManager.InterruptTrigger.BothEdges, 4); for (var i = 0; i < RegisterLength; i++) { var j = i; registersMap.Add(i * RegisterOffset, new DoubleWordRegister(this) .WithFlag(0, writeCallback: (_, val) => { if (val) { irqManager.PinDirection[j] |= GPIOInterruptManager.Direction.Output; } else { irqManager.PinDirection[j] &= ~GPIOInterruptManager.Direction.Output; } }, valueProviderCallback: _ => (irqManager.PinDirection[j] & GPIOInterruptManager.Direction.Output) != 0, name: "OutputRegEnable") .WithFlag(1, writeCallback: (_, value) => { if (value) { irqManager.PinDirection[j] |= GPIOInterruptManager.Direction.Input; } else { irqManager.PinDirection[j] &= ~GPIOInterruptManager.Direction.Input; } }, valueProviderCallback: _ => (irqManager.PinDirection[j] & GPIOInterruptManager.Direction.Input) != 0, name: "InputRegEnable") .WithTag("OutputBufferEnable", 2, 1) .WithFlag(3, writeCallback: (_, v) => { irqManager.InterruptEnable[j] = v; }, valueProviderCallback: _ => irqManager.InterruptEnable[j], name: "InterruptEnable") .WithReservedBits(4, 1) .WithValueField(5, 3, writeCallback: (_, value) => { if (!intTypeToVal.TryGetValue(value, out var type)) { this.Log(LogLevel.Warning, "Invalid interrupt type for pin #{0}: {1}", j, value); return; } irqManager.InterruptType[j] = type; }, valueProviderCallback: _ => intTypeToVal[irqManager.InterruptType[j]], name: "InterruptType")); } registers = new DoubleWordRegisterCollection(this, registersMap); }
public Raptor_GPIO(Machine machine) : base(machine, NumberOfPins) { locker = new object(); pins = new Pin[NumberOfPins]; var registersMap = new Dictionary <long, DoubleWordRegister> { { (long)Registers.GPIO_DATA, new DoubleWordRegister(this) .WithValueField(0, 16, valueProviderCallback: val => { var readOperations = pins.Select(x => (x.pinOperation & Operation.Read) != 0); // select pins configured as input pins var result = readOperations.Zip(State, (operation, state) => operation && state); // update with the incoming signals return(BitHelper.GetValueFromBitsArray(result)); // register value after adjusting the read value for read pins }) .WithValueField(16, 16, valueProviderCallback: val => { var writeOperations = pins.Select(x => (x.pinOperation & Operation.Write) != 0); // select pins configured as output pins var result = writeOperations.Zip(Connections.Values, (operation, state) => operation && state.IsSet); // update with outgoing signals return(BitHelper.GetValueFromBitsArray(result)); }) }, { (long)Registers.GPIO_ENB, new DoubleWordRegister(this) .WithValueField(0, 16, writeCallback: (_, val) => { var bits = BitHelper.GetBits(val); // put the register bits in an array after they are written for (var i = 0; i < bits.Length; i++) { if (bits[i]) // input { pins[i].pinOperation = Operation.Read; } else // output { pins[i].pinOperation = Operation.Write; } } }) .WithTag("RESERVED", 16, 16) }, { (long)Registers.GPIO_PUB, new DoubleWordRegister(this) .WithValueField(0, 16, writeCallback: (_, val) => { var bits = BitHelper.GetBits(val); // put the register bits in an array after they are written for (var i = 0; i < bits.Length; i++) { //if(bits[i] == 1) // pullup // todo: not currently supported } }) .WithTag("RESERVED", 16, 16) }, { (long)Registers.GPIO_PDB, new DoubleWordRegister(this) .WithValueField(0, 16, writeCallback: (_, val) => { var bits = BitHelper.GetBits(val); // put the register bits in an array after they are written for (var i = 0; i < bits.Length; i++) { //if(bits[i] == 1) // pulldown // todo: not currently supported } }) .WithTag("RESERVED", 16, 16) } }; registers = new DoubleWordRegisterCollection(this, registersMap); }
private void CreatePortRegisters(Dictionary <long, DoubleWordRegister> regs, int portNumber) { var regOffset = PortOffset * portNumber; var pinOffset = portNumber * NumberOfPins; regs.Add((long)Registers.PortAControl + regOffset, new DoubleWordRegister(this, 0x700070) .WithTag("DRIVESTRENGTH", 0, 1) .WithTag("SLEWRATE", 4, 3) .WithTag("DINDIS", 12, 1) .WithTag("DRIVESTRENGTHALT", 16, 1) .WithTag("SLEWRATEALT", 20, 3) .WithTag("DINDISALT", 28, 1) ); var gpioModeLow = new DoubleWordRegister(this); var gpioModeHigh = new DoubleWordRegister(this); for (var pinNumber = 0; pinNumber < 8; ++pinNumber) { pinModes[pinOffset + pinNumber] = gpioModeLow.DefineEnumField <PinMode>(pinNumber * 4, 4, name: "MODEX"); //TODO: pin locking } for (var pinNumber = 8; pinNumber < 16; ++pinNumber) { pinModes[pinOffset + pinNumber] = gpioModeHigh.DefineEnumField <PinMode>((pinNumber - 8) * 4, 4, name: "MODEX"); //TODO: pin locking } regs.Add((long)Registers.PortAModeLow + regOffset, gpioModeLow); regs.Add((long)Registers.PortAModeHigh + regOffset, gpioModeHigh); regs.Add((long)Registers.PortADataOut + regOffset, new DoubleWordRegister(this) .WithValueField(0, 16, writeCallback: (_, newValue) => { var bits = BitHelper.GetBits(newValue); for (var i = 0; i < 16; i++) { var pin = pinOffset + i; if (IsOutput(pinModes[pin].Value) && unlockedPins[pin].Value) { Connections[pin].Set(bits[i]); } } }, valueProviderCallback: _ => BitHelper.GetValueFromBitsArray(Connections.Where(x => x.Key >= 0).OrderBy(x => x.Key).Select(x => x.Value.IsSet)))); regs.Add((long)Registers.PortADataOutToggle + regOffset, new DoubleWordRegister(this) .WithValueField(0, 16, FieldMode.Write, writeCallback: (_, newValue) => { var bits = BitHelper.GetSetBits(newValue); foreach (var bit in bits) { var pin = pinOffset + bit; if (IsOutput(pinModes[pin].Value) && unlockedPins[pin].Value) { Connections[pin].Toggle(); } } })); regs.Add((long)Registers.PortADataIn + regOffset, new DoubleWordRegister(this) .WithValueField(0, 16, FieldMode.Read, valueProviderCallback: (oldValue) => BitHelper.GetValueFromBitsArray(State.Skip(pinOffset).Take(NumberOfPins)))); var unlockedPinsRegister = new DoubleWordRegister(this, 0xFFFF); for (var pinNumber = 0; pinNumber < NumberOfPins; ++pinNumber) { unlockedPins[pinNumber + pinOffset] = unlockedPinsRegister.DefineFlagField(pinNumber, FieldMode.WriteZeroToClear); } regs.Add((long)Registers.PortAUnlockedPins + regOffset, unlockedPinsRegister); }
// pixels private static Color[] DecodeUncompressedPixelDataToColors(byte[] pixelData, int bpp, int width, int height, bool palette) { Color[] pixels; int pIdx = 0; switch (bpp) { case 32: { pixels = new Color[width * height]; if (palette) { for (int i = 0; i < pixelData.Length; i += 4) { pixels[pIdx++] = Color.FromArgb(BitConverter.ToInt32(pixelData, i)); } } else { for (int y = height - 1; y >= 0; y--) { for (int x = 0; x < width; x++, pIdx += 4) { pixels[x + y * width] = Color.FromArgb(BitConverter.ToInt32(pixelData, pIdx)); } } } } break; case 24: { pixels = new Color[width * height]; if (palette) { for (int i = 0; i < pixelData.Length; i += 3) { pixels[pIdx++] = Color.FromArgb(pixelData[i + 2], pixelData[i + 1], pixelData[i]); } } else { for (int y = height - 1; y >= 0; y--) { for (int x = 0; x < width; x++, pIdx += 3) { pixels[x + y * width] = Color.FromArgb(pixelData[pIdx + 2], pixelData[pIdx + 1], pixelData[pIdx]); } } } } break; case 16: { pixels = new Color[width * height]; for (int y = height - 1; y >= 0; y--) { for (int x = 0; x < width; x++, pIdx += 2) { ushort color = BitConverter.ToUInt16(pixelData, pIdx); pixels[x + (height - 1 - y) * width] = Color.FromArgb( BitHelper.IsBitSet(color, 15) ? 0 : byte.MaxValue, // a BitHelper.GetBits(color, 5, 0) << 3, // r BitHelper.GetBits(color, 5, 5) << 3, // g BitHelper.GetBits(color, 5, 10) << 3); // b } } } break; default: throw new System.NotImplementedException(); } return(pixels); }
private void PrepareRegisters() { registers = new DoubleWordRegisterCollection(this, new Dictionary <long, DoubleWordRegister> { { (long)Registers.Data, new DoubleWordRegister(this) .WithValueField(0, 8, writeCallback: (_, val) => { var bits = BitHelper.GetBits(val); for (int i = 0; i < 8; i++) { if (irqManager.PinDirection[i] == GPIOInterruptManager.Direction.Input) { Connections[i].Set(bits[i]); State[i] = bits[i]; } } }, valueProviderCallback: _ => { return(BitHelper.GetValueFromBitsArray(State)); }) }, { (long)Registers.DataDirection, new DoubleWordRegister(this) .WithValueField(0, 8, writeCallback: (_, val) => { var bits = BitHelper.GetBits(val); for (var i = 0; i < 8; i++) { irqManager.PinDirection[i] = bits[i] ? GPIOInterruptManager.Direction.Output : GPIOInterruptManager.Direction.Input; } }, valueProviderCallback: _ => BitHelper.GetValueFromBitsArray(irqManager.PinDirection.Select(x => x == GPIOInterruptManager.Direction.Output))) }, { (long)Registers.InterruptSense, new DoubleWordRegister(this) .WithValueField(0, 8, out interruptSenseField, writeCallback: (_, val) => CalculateInterruptTypes()) }, { (long)Registers.InterruptBothEdges, new DoubleWordRegister(this) .WithValueField(0, 8, out interruptBothEdgeField, writeCallback: (_, val) => CalculateInterruptTypes()) }, { (long)Registers.InterruptEvent, new DoubleWordRegister(this) .WithValueField(0, 8, out interruptEventField, writeCallback: (_, val) => CalculateInterruptTypes()) }, { (long)Registers.InterruptEnable, new DoubleWordRegister(this) .WithValueField(0, 8, writeCallback: (_, val) => { var bits = BitHelper.GetBits(val); for (var i = 0; i < 8; i++) { irqManager.InterruptEnable[i] = bits[i]; irqManager.InterruptMask[i] = bits[i]; } irqManager.RefreshInterrupts(); }, valueProviderCallback: _ => BitHelper.GetValueFromBitsArray(irqManager.InterruptEnable)) }, { (long)Registers.RawInterruptStatus, new DoubleWordRegister(this) .WithValueField(0, 8, valueProviderCallback: _ => BitHelper.GetValueFromBitsArray(irqManager.ActiveInterrupts)) }, { (long)Registers.MaskedInterruptStatus, new DoubleWordRegister(this) .WithValueField(0, 8, valueProviderCallback: _ => CalculateMaskedInterruptValue()) }, { (long)Registers.InterruptClear, new DoubleWordRegister(this) .WithValueField(0, 8, FieldMode.Write, writeCallback: (_, val) => { var bits = BitHelper.GetBits(val); for (var i = 0; i < 8; i++) { if (bits[i]) { irqManager.ClearInterrupt(i); } } }) }, { (long)Registers.ModeControlSelect, new DoubleWordRegister(this) .WithTag("AFSEL", 0, 32) }, { (long)Registers.PortEdgeControl, new DoubleWordRegister(this) .WithTag("P_EDGE_CTRL", 0, 32) }, { (long)Registers.PowerUpInterruptEnable, new DoubleWordRegister(this) .WithTag("PI_IEN", 0, 32) }, { (long)Registers.IOPortsIRQDetectACK, new DoubleWordRegister(this) .WithTag("IRQ_DETECT_ACK", 0, 32) }, { (long)Registers.MaskedIRQDetectACK, new DoubleWordRegister(this) .WithTag("IRQ_DETECT_UNMASK", 0, 32) } }); }
public MiV_CoreGPIO(Machine machine) : base(machine, NumberOfInterrupts) { innerLock = new object(); IRQ = new GPIO(); irqManager = new GPIOInterruptManager(IRQ, State); var registersMap = new Dictionary <long, DoubleWordRegister> { { (long)Registers.OutputRegister, new DoubleWordRegister(this).WithValueField(0, 32, FieldMode.Write, writeCallback: (_, value) => { lock (innerLock) { var bits = BitHelper.GetBits(value); for (var i = 0; i < bits.Length; i++) { Connections[i].Set(bits[i]); } } }) }, { (long)Registers.InputRegister, new DoubleWordRegister(this).WithValueField(0, 32, FieldMode.Read, valueProviderCallback: _ => { lock (innerLock) { return(BitHelper.GetValueFromBitsArray(State)); } }) }, { (long)Registers.InterruptClearRegister, new DoubleWordRegister(this).WithValueField(0, 32, writeCallback: (_, value) => { lock (innerLock) { foreach (var i in BitHelper.GetSetBits(value)) { irqManager.ClearInterrupt((uint)i); } } }, valueProviderCallback: _ => { lock (innerLock) { return(BitHelper.GetValueFromBitsArray(irqManager.ActiveInterrupts)); } }) } }; var intTypeToVal = new TwoWayDictionary <GPIOInterruptManager.InterruptTrigger, uint>(); intTypeToVal.Add(GPIOInterruptManager.InterruptTrigger.ActiveHigh, 0); intTypeToVal.Add(GPIOInterruptManager.InterruptTrigger.ActiveLow, 1); intTypeToVal.Add(GPIOInterruptManager.InterruptTrigger.RisingEdge, 2); intTypeToVal.Add(GPIOInterruptManager.InterruptTrigger.FallingEdge, 3); intTypeToVal.Add(GPIOInterruptManager.InterruptTrigger.BothEdges, 4); for (var i = 0; i < NumberOfInterrupts; i++) { var j = i; registersMap.Add((long)Registers.ConfigurationRegisterBase + i * 0x4, new DoubleWordRegister(this) .WithFlag(0, writeCallback: (_, v) => { if (v) { irqManager.PinDirection[j] |= GPIOInterruptManager.Direction.Output; } else { irqManager.PinDirection[j] &= ~GPIOInterruptManager.Direction.Output; } }, valueProviderCallback: _ => (irqManager.PinDirection[j] & GPIOInterruptManager.Direction.Output) != 0, name: "OUTREG") .WithFlag(1, writeCallback: (_, value) => { if (value) { irqManager.PinDirection[j] |= GPIOInterruptManager.Direction.Input; } else { irqManager.PinDirection[j] &= ~GPIOInterruptManager.Direction.Input; } }, valueProviderCallback: _ => (irqManager.PinDirection[j] & GPIOInterruptManager.Direction.Input) != 0, name: "INREG") .WithTag("OUTBUFF", 2, 1) .WithFlag(3, writeCallback: (_, v) => { irqManager.InterruptEnable[j] = v; }, valueProviderCallback: _ => irqManager.InterruptEnable[j], name: "INTENABLE") //bit 4 unused .WithValueField(5, 3, writeCallback: (_, value) => { if (!intTypeToVal.TryGetValue(value, out var type)) { this.Log(LogLevel.Warning, "Invalid interrupt type for pin #{0}: {1}", j, value); return; } irqManager.InterruptType[j] = type; }, valueProviderCallback: _ => { if (!intTypeToVal.TryGetValue(irqManager.InterruptType[j], out var value)) { throw new ArgumentOutOfRangeException($"Unknown interrupt trigger type: {irqManager.InterruptType[j]}"); } return(value); }, name: "INTTYPE")); } registers = new DoubleWordRegisterCollection(this, registersMap); }
private void HandleClockRising(bool[] signals) { switch (state) { case State.Address: { this.Log(LogLevel.Noisy, "Appending address bit #{0}: {1}", bufferToDevice.Count, signals[DataSignal]); bufferToDevice.Push(signals[DataSignal]); if (bufferToDevice.Count == 7) { var address = (int)BitHelper.GetValueFromBitsArray(bufferToDevice.PopAll()); this.Log(LogLevel.Noisy, "Address decoded: 0x{0:X}", address); state = State.Operation; if (!TryGetByAddress(address, out slave)) { this.Log(LogLevel.Warning, "Trying to access a non-existing I2C device at address 0x{0:X}", address); } } break; } case State.Operation: { isRead = signals[DataSignal]; this.Log(LogLevel.Noisy, "Operation decoded: {0}", isRead ? "read" : "write"); // write ACK(false) or NACK(true) bufferFromDevice.Enqueue(slave == null); state = State.AddressAck; break; } case State.AddressAck: { if (slave == null) { // ignore the rest of transmission until the next (repeated) start condition state = State.Idle; } else if (isRead) { this.Log(LogLevel.Noisy, "Reading from device"); foreach (var @byte in slave.Read(6)) { foreach (var bit in BitHelper.GetBits(@byte).Take(8).Reverse()) { this.Log(LogLevel.Noisy, "Enqueuing bit: {0}", bit); bufferFromDevice.Enqueue(bit); } } tickCounter = 0; state = State.Read; } else // it must be write { state = State.Write; } break; } case State.Read: { tickCounter++; if (tickCounter == 8) { state = State.ReadAck; } break; } case State.ReadAck: { tickCounter = 0; state = State.Read; break; } case State.Write: { this.Log(LogLevel.Noisy, "Latching data bit #{0}: {1}", bufferToDevice.Count, signals[DataSignal]); bufferToDevice.Push(signals[DataSignal]); if (bufferToDevice.Count == 8) { state = State.WriteAck; } break; } case State.WriteAck: { DebugHelper.Assert(bufferToDevice.Count == 8); var dataByte = (byte)BitHelper.GetValueFromBitsArray(bufferToDevice.PopAll()); this.Log(LogLevel.Noisy, "Decoded data byte #{0}: 0x{1:X}", bytesToDevice.Count, dataByte); bytesToDevice.Enqueue(dataByte); // ACK this.Log(LogLevel.Noisy, "Enqueuing ACK"); bufferFromDevice.Enqueue(false); state = State.Write; break; } } }
private void UpdateInterrupt() { var enabled = BitHelper.GetBits(buttonsEnabled.Value).Take(ButtonsCount); IRQ.Set(enabled.Zip(buttonsPending, (en, pe) => en && pe).Any()); }
public PlatformLevelInterruptController(Machine machine, int numberOfSources, int numberOfTargets = 1, bool prioritiesEnabled = true) { if (numberOfTargets != 1) { throw new ConstructionException($"Current {this.GetType().Name} implementation does not support more than one target"); } // numberOfSources has to fit between these two registers, one bit per source if (Math.Ceiling((numberOfSources + 1) / 32.0) * 4 > Registers.Target1Enables - Registers.Target0Enables) { throw new ConstructionException($"Current {this.GetType().Name} implementation more than {Registers.Target1Enables - Registers.Target0Enables} sources"); } this.prioritiesEnabled = prioritiesEnabled; this.machine = machine; IRQ = new GPIO(); // irqSources are initialized from 1, as the source "0" is not used. irqSources = new IrqSource[numberOfSources + 1]; for (var i = 1; i <= numberOfSources; i++) { irqSources[i] = new IrqSource(); } activeInterrupts = new Stack <uint>(); var registersMap = new Dictionary <long, DoubleWordRegister> { { (long)Registers.Target0ClaimComplete, new DoubleWordRegister(this).WithValueField(0, 32, valueProviderCallback: _ => { return(AcknowledgePendingInterrupt()); }, writeCallback: (_, value) => { CompleteHandlingInterrupt(value); } ) } }; registersMap.Add((long)Registers.Source0Priority, new DoubleWordRegister(this) .WithValueField(0, 3, FieldMode.Read, writeCallback: (_, value) => { if (value != 0) { this.Log(LogLevel.Warning, $"Trying to set priority {value} to Source 0, which is illegal"); } })); for (var i = 1; i <= numberOfSources; i++) { var j = i; registersMap[(long)Registers.Source1Priority * i] = new DoubleWordRegister(this) .WithValueField(0, 3, valueProviderCallback: (_) => irqSources[j].Priority, writeCallback: (_, value) => { if (prioritiesEnabled) { irqSources[j].Priority = value; } }); } var vectorWidth = (uint)Registers.Target1Enables - (uint)Registers.Target0Enables; var maximumSourceDoubleWords = (int)Math.Ceiling((numberOfSources + 1) / 32.0) * 4; // When writing to TargetXEnables registers, the user will get an error in log when he tries to write to an // unused bit of a register that is at least partially used. A warning will be issued on a usual undefined register access otherwise. for (var target = 0u; target < numberOfTargets; target++) { for (var offset = 0u; offset < maximumSourceDoubleWords; offset += 4) { var lTarget = target; var lOffset = offset; registersMap.Add((long)Registers.Target0Enables + (vectorWidth * target) + offset, new DoubleWordRegister(this).WithValueField(0, 32, writeCallback: (_, value) => { lock (irqSources) { // Each source is represented by one bit. offset and lOffset indicate the offset in double words from TargetXEnables, // `bit` is the bit number in the given double word, // and `sourceIdBase + bit` indicate the source number. var sourceIdBase = lOffset * 8; var bits = BitHelper.GetBits(value); for (var bit = 0u; bit < bits.Length; bit++) { if (sourceIdBase + bit == 0) { //Source number 0 is not used. continue; } if (irqSources.Length <= (sourceIdBase + bit)) { if (bits[bit]) { this.Log(LogLevel.Error, "Trying to enable non-existing source: {0}", sourceIdBase + bit); } continue; } var targets = irqSources[sourceIdBase + bit].EnabledTargets; if (bits[bit]) { targets.Add(lTarget); } else { targets.Remove(lTarget); } } RefreshInterrupts(); } })); } } registers = new DoubleWordRegisterCollection(this, registersMap); }
public SiFive_GPIO(Machine machine) : base(machine, NumberOfPins) { locker = new object(); pins = new Pin[NumberOfPins]; var registersMap = new Dictionary <long, DoubleWordRegister> { { (long)Registers.PinValue, new DoubleWordRegister(this) .WithValueField(0, 32, valueProviderCallback: _ => { var readOperations = pins.Select(x => (x.pinOperation & Operation.Read) != 0); var result = readOperations.Zip(State, (operation, state) => operation && state); return(BitHelper.GetValueFromBitsArray(result)); }) }, { (long)Registers.PinInputEnable, new DoubleWordRegister(this) .WithValueField(0, 32, writeCallback: (_, val) => { var bits = BitHelper.GetBits(val); for (var i = 0; i < bits.Length; i++) { Misc.FlipFlag(ref pins[i].pinOperation, Operation.Read, bits[i]); } }) }, { (long)Registers.PinOutputEnable, new DoubleWordRegister(this) .WithValueField(0, 32, writeCallback: (_, val) => { var bits = BitHelper.GetBits(val); for (var i = 0; i < bits.Length; i++) { Misc.FlipFlag(ref pins[i].pinOperation, Operation.Write, bits[i]); } }) }, { (long)Registers.OutputPortValue, new DoubleWordRegister(this) .WithValueField(0, 32, writeCallback: (_, val) => { lock (locker) { var bits = BitHelper.GetBits(val); for (var i = 0; i < bits.Length; i++) { if ((pins[i].pinOperation & Operation.Write) != 0) { State[i] = bits[i]; Connections[i].Set(bits[i]); } } } }) }, { (long)Registers.RiseInterruptPending, new DoubleWordRegister(this) .WithValueField(0, 32, writeCallback: (_, val) => { lock (locker) { var bits = BitHelper.GetBits(val); for (var i = 0; i < bits.Length; i++) { if (bits[i]) { Connections[i].Set(State[i]); } } } }) } }; registers = new DoubleWordRegisterCollection(this, registersMap); }