예제 #1
0
 private void SelectDevice(Device device)
 {
     lock (selectedDeviceLock)
     {
         if (!ChildCollection.TryGetValue((int)device, out selectedDevice))
         {
             this.Log(LogLevel.Debug, "Selected non existing device");
             selectedDevice = null;
         }
     }
 }
예제 #2
0
        private bool TryResolveSelectedSlave(out II2CPeripheral selectedSlave)
        {
            var slaveAddress = (byte)(transmitBuffer.Value >> 1);

            if (!ChildCollection.TryGetValue(slaveAddress, out selectedSlave))
            {
                this.Log(LogLevel.Warning, "Addressing unregistered slave: 0x{0:X}", slaveAddress);
                receivedAckFromSlaveNegated.Value = true;
                return(true);
            }

            receivedAckFromSlaveNegated.Value = false;
            return(false);
        }
        private void HandleWriteToSlaveCommand()
        {
            if (generateStartCondition.Value)
            {
                generateStartCondition.Value = false;
                if (transactionInProgress)
                {
                    // repeated start - finish previous transaction first
                    SendDataToSlave();
                }
                else
                {
                    transactionInProgress = true;
                }

                var slaveAddress    = (byte)(transmitBuffer.Value >> 1);
                var isReadOperation = BitHelper.IsBitSet(transmitBuffer.Value, 0);
                if (!ChildCollection.TryGetValue(slaveAddress, out selectedSlave))
                {
                    this.Log(LogLevel.Warning, "Addressing unregistered slave: 0x{0:X}", slaveAddress);
                    receivedAckFromSlaveNegated.Value = true;
                }
                else
                {
                    if (isReadOperation)
                    {
                        foreach (var b in selectedSlave.Read())
                        {
                            dataFromSlave.Enqueue(b);
                        }
                    }
                    receivedAckFromSlaveNegated.Value = false;
                }
            }
            else
            {
                if (!transactionInProgress)
                {
                    this.Log(LogLevel.Warning, "Writing to slave without generating START signal");
                    return;
                }
                dataToSlave.Enqueue((byte)transmitBuffer.Value);
            }
            interruptFlag.Value = true;
        }
예제 #4
0
 private uint ReadData(uint oldVal)
 {
     if (configEnabled.Value)
     {
         if (!ChildCollection.TryGetValue((int)deviceNumber.Value, out selectedDevice))
         {
             this.Log(LogLevel.Warning, "Selected unregistered device number : {0}", deviceNumber.Value);
             selectedDevice = null;
             return(0);
         }
         //Address is multiplied by 4 cause Read function take offset as argument
         return(selectedDevice.ConfigurationReadDoubleWord(registerNumber.Value * 4));
     }
     else
     {
         this.Log(LogLevel.Warning, "Reading data from device in unhandled state");
     }
     return(0);
 }
예제 #5
0
        private void HandleReadFromSlaveCommand()
        {
            var slaveAddress    = (byte)(transmitBuffer.Value >> 1);
            var isReadOperation = BitHelper.IsBitSet(transmitBuffer.Value, 0);

            if (ChildCollection.TryGetValue(slaveAddress, out selectedSlave))
            {
                foreach (var b in selectedSlave.Read())
                {
                    dataFromSlave.Enqueue(b);
                }
            }
            if (dataFromSlave.Count == 0)
            {
                this.Log(LogLevel.Warning, "Trying to read from slave, but no data is available");
                receiveBuffer.Value = 0;
                return;
            }

            receiveBuffer.Value = dataFromSlave.Dequeue();
        }
예제 #6
0
 protected bool TryGetByAddress(int address, out T peripheral)
 {
     return(ChildCollection.TryGetValue(address, out peripheral));
 }
예제 #7
0
        private void DefineRegisters()
        {
            Registers.Control.Define(this)
            .WithTag("CR2", 7, 1)
            .WithFlag(6, out isCoreEnabled, name: "ens1")
            .WithFlag(5, FieldMode.WriteOneToClear | FieldMode.Read, name: "sta",
                      writeCallback: (_, val) =>
            {
                if (!val)
                {
                    return;
                }

                switch (CurrentState)
                {
                case State.Idle:
                case State.SlaveAddressReadBitTransmittedAckNotReceived:
                case State.SlaveAddressWriteBitTransmittedAckNotReceived:
                    pendingMasterTransaction = true;
                    CurrentState             = State.StartConditionTransmitted;
                    break;

                case State.StartConditionTransmitted:
                case State.RepeatedStartConditionTransmitted:
                    SendDataToSlave();
                    CurrentState = State.RepeatedStartConditionTransmitted;
                    break;

                case State.DataTransmittedAckReceived:
                    if (pendingMasterTransaction)
                    {
                        isReadOperation = true;
                        CurrentState    = State.RepeatedStartConditionTransmitted;
                    }
                    break;

                default:
                    this.Log(LogLevel.Warning, "Setting START bit in unhandled state: {0}", CurrentState);
                    break;
                }
            })
            .WithFlag(4, FieldMode.WriteOneToClear | FieldMode.Read, name: "sto",
                      writeCallback: (_, val) =>
            {
                if (val)
                {
                    selectedSlave            = null;
                    isReadOperation          = false;
                    pendingMasterTransaction = false;
                    CurrentState             = State.Idle;
                }
            })
            .WithFlag(3, out serialInterruptFlag, name: "si", writeCallback: (previousValue, currentValue) =>
            {
                if (!(previousValue && !currentValue))
                {
                    // writing 0 clears the interrupt
                    return;
                }
                if (Interlocked.Decrement(ref irqResubmitCounter) > 0)
                {
                    // if there are any queued irqs set the flag again
                    serialInterruptFlag.Value = true;
                }
                else
                {
                    Interlocked.Increment(ref irqResubmitCounter);
                }
                UpdateInterrupt();
            })
            .WithFlag(2, name: "aa")
            .WithTag("CR0/CR1", 0, 2);


            Registers.Status.Define(this)
            .WithEnumField <ByteRegister, State>(0, 8, FieldMode.Read,
                                                 valueProviderCallback: _ =>
            {
                return(CurrentState);
            }
                                                 );


            Registers.Data.Define(this)
            .WithValueField(0, 8, name: "sd",
                            valueProviderCallback: _ =>
            {
                if (receiveBuffer.Count == 0)
                {
                    this.Log(LogLevel.Warning, "{0} trying to read from empty data buffer, transaction will halt", pendingMasterTransaction ? "Master" : "Slave");
                    if (pendingMasterTransaction)
                    {
                        pendingMasterTransaction = false;
                        CurrentState             = State.DataReceivedAckNotReturned;
                    }
                    else
                    {
                        CurrentState = State.Stop;
                    }
                    return(0);
                }
                var result = receiveBuffer.Dequeue();
                if (receiveBuffer.Count > 0)
                {
                    // the state machine requires states in which master and slave are reading from the data register
                    CurrentState = pendingMasterTransaction ? State.DataReceivedAckReturned : State.PreviouslyAddressedWithOwnAddressDataReceivedAckReturned;
                }
                return(result);
            },
                            writeCallback: (_, val) =>
            {
                switch (CurrentState)
                {
                case State.StartConditionTransmitted:
                case State.RepeatedStartConditionTransmitted:
                    var slaveAddress = val >> 1;
                    isReadOperation  = BitHelper.IsBitSet(val, 0);
                    if (!ChildCollection.TryGetValue((int)slaveAddress, out selectedSlave))
                    {
                        this.Log(LogLevel.Warning, "Addressing unregistered slave: 0x{0:X}", slaveAddress);
                        CurrentState = (isReadOperation) ? State.SlaveAddressReadBitTransmittedAckNotReceived : State.SlaveAddressWriteBitTransmittedAckNotReceived;
                    }
                    else
                    {
                        if (isReadOperation)
                        {
                            var bytes = selectedSlave.Read();
                            if (bytes.Length > 0)
                            {
                                foreach (var b in bytes)
                                {
                                    receiveBuffer.Enqueue(b);
                                }
                                CurrentState = State.DataReceivedAckReturned;
                            }
                        }
                        else
                        {
                            CurrentState = State.SlaveAddressWriteBitTransmittedAckReceived;
                        }
                    }
                    break;

                case State.SlaveAddressWriteBitTransmittedAckReceived:
                case State.DataTransmittedAckReceived:
                    transferBuffer.Enqueue((byte)val);
                    SendDataToSlave();
                    break;

                default:
                    this.Log(LogLevel.Warning, "Writing to data register in unhandled state: {0}", CurrentState);
                    break;
                }
            });

            Registers.Slave0Address.Define(this)
            .WithValueField(1, 7, name: "adr")
            .WithFlag(0, name: "gc");

            Registers.Slave1Address.Define(this)
            .WithValueField(1, 7, name: "adr")
            .WithFlag(0, name: "gc");
        }