1 //
2 // Copyright (c) 2010-2023 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 Antmicro.Renode.Peripherals.Bus;
9 using Antmicro.Renode.Peripherals.Sensor;
10 using Antmicro.Renode.Peripherals.I2C;
11 using Antmicro.Renode.Utilities;
12 using Antmicro.Renode.Logging;
13 using Antmicro.Renode.Core.Structure.Registers;
14 
15 namespace Antmicro.Renode.Peripherals.Sensors
16 {
17     public class LSM330_Gyroscope : ST_I2CSensorBase<LSM330_Gyroscope.Registers>
18     {
LSM330_Gyroscope()19         public LSM330_Gyroscope()
20         {
21             Reset();
22         }
23 
Reset()24         public override void Reset()
25         {
26             base.Reset();
27             UpdateSensitivity(0);
28         }
29 
30         public decimal AngularRateX { get; set; }
31 
32         public decimal AngularRateY { get; set; }
33 
34         public decimal AngularRateZ { get; set; }
35 
DefineRegisters()36         protected override void DefineRegisters()
37         {
38             Registers.Control4.Define(this)
39                 .WithTaggedFlag("SIM", 0)
40                 .WithReservedBits(1, 3)
41                 .WithValueField(4, 2, name: "FS: Full-scale selection", writeCallback: (_, val) => UpdateSensitivity((uint)val))
42                 .WithTaggedFlag("BLE", 6)
43                 .WithTaggedFlag("BDU", 7)
44             ;
45 
46             Registers.OutputXLow.Define(this)
47                 .WithValueField(0, 8, FieldMode.Read, name: "OUT_X_L_G", valueProviderCallback: _ => GetScaledValue(AngularRateX, sensitivity, false))
48             ;
49 
50             Registers.OutputXHigh.Define(this)
51                 .WithValueField(0, 8, FieldMode.Read, name: "OUT_X_H_G", valueProviderCallback: _ => GetScaledValue(AngularRateX, sensitivity, true))
52             ;
53 
54             Registers.OutputYLow.Define(this)
55                 .WithValueField(0, 8, FieldMode.Read, name: "OUT_Y_L_G", valueProviderCallback: _ => GetScaledValue(AngularRateY, sensitivity, false))
56             ;
57 
58             Registers.OutputYHigh.Define(this)
59                 .WithValueField(0, 8, FieldMode.Read, name: "OUT_Y_H_G", valueProviderCallback: _ => GetScaledValue(AngularRateY, sensitivity, true))
60             ;
61 
62             Registers.OutputZLow.Define(this)
63                 .WithValueField(0, 8, FieldMode.Read, name: "OUT_Z_L_G", valueProviderCallback: _ => GetScaledValue(AngularRateZ, sensitivity, false))
64             ;
65 
66             Registers.OutputZHigh.Define(this)
67                 .WithValueField(0, 8, FieldMode.Read, name: "OUT_Z_H_G", valueProviderCallback: _ => GetScaledValue(AngularRateZ, sensitivity, true))
68             ;
69         }
70 
UpdateSensitivity(uint val)71         private void UpdateSensitivity(uint val)
72         {
73             var range = 0;
74             switch(val)
75             {
76                 case 0:
77                     range = 250;
78                     break;
79                 case 1:
80                     range = 500;
81                     break;
82                 // yes, both cases 0b10 and 0b11 encodes scale of 2000 dps
83                 case 2:
84                 case 3:
85                     range = 2000;
86                     break;
87                 default:
88                     this.Log(LogLevel.Warning, "Tried to set an unsupported sensitivity value: {0}", val);
89                     return;
90             }
91 
92             sensitivity = CalculateScale(-range, range, OutputWidth);
93         }
94 
95         private short sensitivity;
96 
97         private const int OutputWidth = 16;
98 
99         public enum Registers
100         {
101             WhoaAmI = 0x0F,
102 
103             Control1 = 0x20,
104             Control2 = 0x21,
105             Control3 = 0x22,
106             Control4 = 0x23,
107             Control5 = 0x24,
108 
109             Reference = 0x25,
110             TemperatureOutput = 0x26,
111             Status = 0x27,
112 
113             OutputXLow = 0x28,
114             OutputXHigh = 0x29,
115             OutputYLow = 0x2A,
116             OutputYHigh = 0x2B,
117             OutputZLow = 0x2C,
118             OutputZHigh = 0x2D,
119 
120             FifoControl = 0x2E,
121             FifoSource = 0x2F,
122 
123             InterruptConfig = 0x30,
124             InterruptSource = 0x31,
125             InterruptThresholdXHigh = 0x32,
126             InterruptThresholdXLow = 0x33,
127             InterruptThresholdYHigh = 0x34,
128             InterruptThresholdYLow = 0x35,
129             InterruptThresholdZHigh = 0x36,
130             InterruptThresholdZLow = 0x37,
131             InterruptDuration = 0x38,
132         }
133     }
134 }
135