1 //
2 // Copyright (c) 2010-2024 Antmicro
3 //
4 // This file is licensed under the MIT License.
5 // Full license text is available in 'licenses/MIT.txt'.
6 //
7 using System;
8 using System.Collections.Generic;
9 using Antmicro.Renode.Logging;
10 using Antmicro.Renode.Peripherals.Sensor;
11 using Antmicro.Renode.Utilities;
12 
13 namespace Antmicro.Renode.Network.ExternalControl
14 {
15     public class ADC : BaseCommand, IInstanceBasedCommand<IADC>
16     {
ADC(ExternalControlServer parent)17         public ADC(ExternalControlServer parent)
18             : base(parent)
19         {
20             Instances = new InstanceCollection<IADC>();
21         }
22 
23         public override Response Invoke(List<byte> data) => this.InvokeHandledWithInstance(data);
24 
Invoke(IADC instance, List<byte> data)25         public Response Invoke(IADC instance, List<byte> data)
26         {
27             if(data.Count < 1)
28             {
29                 return Response.CommandFailed(Identifier, $"Expected at least {1 + InstanceBasedCommandHeaderSize} bytes of payload");
30             }
31             var command = (ADCCommand)data[0];
32 
33             var expectedCount = GetExpectedPayloadCount(command);
34             if(expectedCount != data.Count)
35             {
36                 return Response.CommandFailed(Identifier, $"Expected {expectedCount + InstanceBasedCommandHeaderSize} bytes of payload");
37             }
38 
39             switch(command)
40             {
41                 case ADCCommand.GetCount:
42                     var channelCount = instance.ADCChannelCount;
43                     parent.Log(LogLevel.Debug, "Executing ADC GetCount command, returned {0}", channelCount);
44                     return Response.Success(Identifier, channelCount.AsRawBytes());
45 
46                 case ADCCommand.GetValue:
47                     DecodeChannelArgument(data, out var channel);
48                     var value = instance.GetADCValue(channel);
49                     parent.Log(LogLevel.Debug, "Executing ADC GetValue command, channel #{0} returned {1}", channel, value);
50                     return Response.Success(Identifier, value.AsRawBytes());
51 
52                 case ADCCommand.SetValue:
53                     DecodeSetValueArguments(data, out channel, out value);
54                     parent.Log(LogLevel.Debug, "Executing ADC SetValue command, channel #{0} set to {1}", channel, value);
55                     instance.SetADCValue(channel, value);
56                     return Response.Success(Identifier);
57 
58                 default:
59                     return Response.CommandFailed(Identifier, "Unexpected command format");
60             }
61         }
62 
63         public InstanceCollection<IADC> Instances { get; }
64 
65         public override Command Identifier => Command.ADC;
66         public override byte Version => 0x0;
67 
GetExpectedPayloadCount(ADCCommand command)68         private int GetExpectedPayloadCount(ADCCommand command)
69         {
70             switch(command)
71             {
72                 case ADCCommand.GetValue:
73                     return sizeof(byte) + sizeof(uint);
74                 case ADCCommand.SetValue:
75                     return sizeof(byte) + sizeof(uint) * 2;
76                 default:
77                     return sizeof(byte);
78             }
79         }
80 
DecodeChannelArgument(List<byte> data, out int channel)81         private void DecodeChannelArgument(List<byte> data, out int channel)
82         {
83             channel = BitConverter.ToInt32(data.GetRange(1, sizeof(uint)).ToArray(), 0);
84         }
85 
DecodeSetValueArguments(List<byte> data, out int channel, out uint value)86         private void DecodeSetValueArguments(List<byte> data, out int channel, out uint value)
87         {
88             DecodeChannelArgument(data, out channel);
89             value = BitConverter.ToUInt32(data.GetRange(5, sizeof(uint)).ToArray(), 0);
90         }
91 
92         private const int InstanceBasedCommandHeaderSize = IInstanceBasedCommandExtensions.HeaderSize;
93 
94         private enum ADCCommand : byte
95         {
96             GetCount = 0,
97             GetValue,
98             SetValue,
99         }
100     }
101 }
102