1 //
2 // Copyright (c) 2010-2024 Antmicro
3 // Copyright (c) 2011-2015 Realtime Embedded
4 //
5 // This file is licensed under the MIT License.
6 // Full license text is available in 'licenses/MIT.txt'.
7 //
8 using System;
9 using System.Linq;
10 using Antmicro.Renode.Core;
11 using Antmicro.Renode.Core.Structure;
12 using System.Collections.Generic;
13 using System.Collections.ObjectModel;
14 using Antmicro.Renode.UserInterface;
15 using Antmicro.Renode.Logging;
16 using Antmicro.Renode.Utilities;
17 
18 namespace Antmicro.Renode.Peripherals.GPIOPort
19 {
20     [Icon("gpio")]
21     public abstract class BaseGPIOPort : INumberedGPIOOutput, IPeripheralRegister<IGPIOReceiver, NullRegistrationPoint>,
22         IPeripheralRegister<IGPIOSender, NullRegistrationPoint>, IPeripheralRegister<IGPIOReceiver, NumberRegistrationPoint<int>>,
23         IPeripheral, IGPIOReceiver, IPeripheralRegister<IGPIOSender, NumberRegistrationPoint<int>>
24     {
Register(IGPIOSender peripheral, NumberRegistrationPoint<int> registrationPoint)25         public void Register(IGPIOSender peripheral, NumberRegistrationPoint<int> registrationPoint)
26         {
27             machine.RegisterAsAChildOf(this, peripheral, registrationPoint);
28         }
29 
Unregister(IGPIOSender peripheral)30         public void Unregister(IGPIOSender peripheral)
31         {
32             machine.UnregisterAsAChildOf(this, peripheral);
33         }
34 
Register(IGPIOSender peripheral, NullRegistrationPoint registrationPoint)35         public void Register(IGPIOSender peripheral, NullRegistrationPoint registrationPoint)
36         {
37             machine.RegisterAsAChildOf(this, peripheral, registrationPoint);
38         }
39 
Register(IGPIOReceiver peripheral, NullRegistrationPoint registrationPoint)40         public void Register(IGPIOReceiver peripheral, NullRegistrationPoint registrationPoint)
41         {
42             machine.RegisterAsAChildOf(this, peripheral, registrationPoint);
43         }
44 
Unregister(IGPIOReceiver peripheral)45         public void Unregister(IGPIOReceiver peripheral)
46         {
47             machine.UnregisterAsAChildOf(this, peripheral);
48             foreach(var gpio in Connections.Values)
49             {
50                 var endpoints = gpio.Endpoints;
51                 for(var i = 0; i < endpoints.Count; ++i)
52                 {
53                     if(endpoints[i].Number == 0 && endpoints[i].Receiver == peripheral)
54                     {
55                         gpio.Disconnect(endpoints[i]);
56                     }
57                 }
58             }
59         }
60 
Register(IGPIOReceiver peripheral, NumberRegistrationPoint<int> registrationPoint)61         public void Register(IGPIOReceiver peripheral, NumberRegistrationPoint<int> registrationPoint)
62         {
63             machine.RegisterAsAChildOf(this, peripheral, registrationPoint);
64         }
65 
Reset()66         public virtual void Reset()
67         {
68             foreach(var connection in Connections.Values)
69             {
70                 connection.Unset();
71             }
72             for(int i = 0; i < State.Length; ++i)
73             {
74                 State[i] = false;
75             }
76         }
77 
BaseGPIOPort(IMachine machine, int numberOfConnections)78         protected BaseGPIOPort(IMachine machine, int numberOfConnections)
79         {
80             var innerConnections = new Dictionary<int, IGPIO>();
81             this.NumberOfConnections = numberOfConnections;
82             State = new bool[numberOfConnections];
83             for(var i = 0; i < numberOfConnections; i++)
84             {
85                 innerConnections[i] = new GPIO();
86             }
87             this.machine = machine;
88             Connections = new ReadOnlyDictionary<int, IGPIO>(innerConnections);
89         }
90 
SetConnectionsStateUsingBits(uint bits)91         protected void SetConnectionsStateUsingBits(uint bits)
92         {
93             foreach(var cn in Connections)
94             {
95                 if((bits & 1u << cn.Key) != 0)
96                 {
97                     cn.Value.Set();
98                 }
99                 else
100                 {
101                     cn.Value.Unset();
102                 }
103             }
104         }
105 
GetSetConnectionBits()106         protected uint GetSetConnectionBits()
107         {
108             return BitHelper.GetValueFromBitsArray(Connections.Where(x => x.Key >= 0).OrderBy(x => x.Key).Select(x => x.Value.IsSet));
109         }
110 
CheckPinNumber(int number)111         protected bool CheckPinNumber(int number)
112         {
113             if(number < 0 || number >= NumberOfConnections)
114             {
115                 this.Log(LogLevel.Error, $"This peripheral supports gpio inputs from 0 to {NumberOfConnections}, but {number} was called.");
116                 return false;
117             }
118             return true;
119         }
120 
OnGPIO(int number, bool value)121         public virtual void OnGPIO(int number, bool value)
122         {
123             if(!CheckPinNumber(number))
124             {
125                 return;
126             }
127 
128             State[number] = value;
129         }
130 
131         public IReadOnlyDictionary<int, IGPIO> Connections { get; }
132 
133         protected readonly int NumberOfConnections;
134         protected bool[] State;
135         protected readonly IMachine machine;
136     }
137 }
138 
139