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 Antmicro.Renode.Peripherals; 9 using Antmicro.Renode.Logging; 10 using Antmicro.Renode.Core; 11 using Antmicro.Renode.Core.Structure.Registers; 12 using Antmicro.Renode.Peripherals.I2C; 13 using Antmicro.Renode.Peripherals.Sensor; 14 15 namespace Antmicro.Renode.Peripherals.Sensors 16 { 17 public partial class ICM20948 18 { TryGetI2CPeripherial(out II2CPeripheral pheriperial)19 private bool TryGetI2CPeripherial(out II2CPeripheral pheriperial) 20 { 21 if(!i2cContainer.TryGetByAddress((int)slaveAddress0.Value, out pheriperial)) 22 { 23 this.WarningLog("Selecting unconnected IIC slave address: 0x{0:X}", slaveAddress0.Value); 24 return false; 25 } 26 this.DebugLog("Selected slave address 0x{0:X}", slaveAddress0.Value); 27 return true; 28 } 29 WriteI2CPeripherial(II2CPeripheral selectedI2CSlave, byte[] data)30 private void WriteI2CPeripherial(II2CPeripheral selectedI2CSlave, byte[] data) 31 { 32 selectedI2CSlave.Write(data); 33 selectedI2CSlave.FinishTransmission(); 34 } 35 ReadI2CPeripherial(II2CPeripheral selectedI2CSlave, int length)36 private void ReadI2CPeripherial(II2CPeripheral selectedI2CSlave, int length) 37 { 38 if(length > externalSlaveSensorData.Length) 39 { 40 this.Log(LogLevel.Warning, "Requested read length is greater than the number of available external sensor data registers. Clamping to the maximum available length."); 41 length = externalSlaveSensorData.Length; 42 } 43 byte[] data = selectedI2CSlave.Read(length); 44 selectedI2CSlave.FinishTransmission(); 45 for(int i = 0; i < data.Length; i++) 46 { 47 externalSlaveSensorData[i].Value = data[i]; 48 } 49 } 50 ReadSensorData()51 private void ReadSensorData() 52 { 53 if(!TryGetI2CPeripherial(out var selectedI2CSlave)) 54 { 55 return; 56 } 57 WriteI2CPeripherial(selectedI2CSlave, new byte[] { (byte)slaveTransactionRegisterAddress0.Value } ); 58 ReadI2CPeripherial(selectedI2CSlave, (int)slaveTransferLength0.Value ); 59 } 60 DefineGyroAccelUserBank3Registers()61 private void DefineGyroAccelUserBank3Registers() 62 { 63 GyroAccelUserBank3Registers.I2CIDRMasterConfig.Define(gyroAccelUserBank3Registers) 64 .WithReservedBits(4, 4) 65 .WithTag("I2C_MST_ODR_CONFIG", 0, 4) 66 ; 67 68 GyroAccelUserBank3Registers.I2CMasterControl.Define(gyroAccelUserBank3Registers) 69 .WithTag("MULT_MST_EN", 7, 1) 70 .WithReservedBits(5, 2) 71 .WithTag("I2C_MST_P_NSR", 4, 1) 72 .WithTag("I2C_MST_CLK", 0, 4) 73 ; 74 75 GyroAccelUserBank3Registers.I2CMasterDelayControl.Define(gyroAccelUserBank3Registers) 76 .WithTag("DELAY_ES_SHADOW", 7, 1) 77 .WithReservedBits(5, 2) 78 .WithTag("I2C_SLV4_DELAY_EN", 4, 1) 79 .WithTag("I2C_SLV3_DELAY_EN", 3, 1) 80 .WithTag("I2C_SLV2_DELAY_EN", 2, 1) 81 .WithTag("I2C_SLV1_DELAY_EN", 1, 1) 82 .WithTag("I2C_SLV0_DELAY_EN", 0, 1) 83 ; 84 85 GyroAccelUserBank3Registers.I2CSlave0Address.Define(gyroAccelUserBank3Registers) 86 .WithFlag(7, out slaveRWBit0, name: "I2C_SLV0_RNW") 87 .WithValueField(0, 7, out slaveAddress0, name: "I2C_ID_0") 88 ; 89 90 GyroAccelUserBank3Registers.I2CSlave0Register.Define(gyroAccelUserBank3Registers) 91 .WithValueField(0, 8, out slaveTransactionRegisterAddress0, name: "I2C_SLV0_REG") 92 ; 93 94 GyroAccelUserBank3Registers.I2CSlave0Control.Define(gyroAccelUserBank3Registers) 95 .WithFlag(7, out var slaveEnable0, name: "I2C_SLV0_EN", 96 writeCallback: (_, value) => 97 { 98 if(!value) 99 { 100 magFeederThread?.Stop(); 101 return; 102 } 103 magFeederThread?.Stop(); 104 var machine = this.GetMachine(); 105 Action feedSample = () => 106 { 107 ReadSensorData(); 108 }; 109 Func<bool> stopCondition = () => false; 110 magFeederThread = machine.ObtainManagedThread(feedSample, (uint)InternalSampleRateHz, "Magnetometer stream thread", this, stopCondition); 111 this.Log(LogLevel.Debug, "Starting reading magnetometer samples at frequency {0}Hz", InternalSampleRateHz); 112 magFeederThread.Start(); 113 }) 114 .WithTag("I2C_SLV0_BYTE_SW", 6, 1) 115 .WithTag("I2C_SLV0_REG_DIS", 5, 1) 116 .WithTag("I2C_SLV0_GRP", 4, 1) 117 .WithValueField(0, 4, out slaveTransferLength0, name: "I2C_SLV0_LENG") 118 ; 119 120 GyroAccelUserBank3Registers.I2CSlave0DataOut.Define(gyroAccelUserBank3Registers) 121 .WithValueField(0, 8, out slaveDataOut0, name: "I2C_SLV0_DO", 122 writeCallback: (_, val) => 123 { 124 if(!TryGetI2CPeripherial(out var selectedI2CSlave)) 125 { 126 return; 127 } 128 WriteI2CPeripherial(selectedI2CSlave, new byte[] { (byte)slaveTransactionRegisterAddress0.Value, (byte)val } ); 129 }) 130 ; 131 132 GyroAccelUserBank3Registers.I2CSlave1Address.Define(gyroAccelUserBank3Registers) 133 .WithTag("I2C_SLV1_RNW", 7, 1) 134 .WithTag("I2C_ID_1", 0, 7) 135 ; 136 137 GyroAccelUserBank3Registers.I2CSlave1Register.Define(gyroAccelUserBank3Registers) 138 .WithTag("I2C_SLV1_REG", 0, 8) 139 ; 140 141 GyroAccelUserBank3Registers.I2CSlave1Control.Define(gyroAccelUserBank3Registers) 142 .WithTag("I2C_SLV1_EN", 7, 1) 143 .WithTag("I2C_SLV1_BYTE_SW", 6, 1) 144 .WithTag("I2C_SLV1_REG_DIS", 5, 1) 145 .WithTag("I2C_SLV1_GRP", 4, 1) 146 .WithTag("I2C_SLV1_LENG", 0, 4) 147 ; 148 149 GyroAccelUserBank3Registers.I2CSlave1DataOut.Define(gyroAccelUserBank3Registers) 150 .WithTag("I2C_SLV1_DO", 0, 8) 151 ; 152 153 GyroAccelUserBank3Registers.I2CSlave2Address.Define(gyroAccelUserBank3Registers) 154 .WithTag("I2C_SLV2_RNW", 7, 1) 155 .WithTag("I2C_ID_2", 0, 7) 156 ; 157 158 GyroAccelUserBank3Registers.I2CSlave2Register.Define(gyroAccelUserBank3Registers) 159 .WithTag("I2C_SLV2_REG", 0, 8) 160 ; 161 162 GyroAccelUserBank3Registers.I2CSlave2Control.Define(gyroAccelUserBank3Registers) 163 .WithTag("I2C_SLV2_EN", 7, 1) 164 .WithTag("I2C_SLV2_BYTE_SW", 6, 1) 165 .WithTag("I2C_SLV2_REG_DIS", 5, 1) 166 .WithTag("I2C_SLV2_GRP", 4, 1) 167 .WithTag("I2C_SLV2_LENG", 0, 4) 168 ; 169 170 GyroAccelUserBank3Registers.I2CSlave2DataOut.Define(gyroAccelUserBank3Registers) 171 .WithTag("I2C_SLV2_DO", 0, 8) 172 ; 173 174 GyroAccelUserBank3Registers.I2CSlave3Address.Define(gyroAccelUserBank3Registers) 175 .WithTag("I2C_SLV3_RNW", 7, 1) 176 .WithTag("I2C_ID_3", 0, 7) 177 ; 178 179 GyroAccelUserBank3Registers.I2CSlave3Register.Define(gyroAccelUserBank3Registers) 180 .WithTag("I2C_SLV3_REG", 0, 8) 181 ; 182 183 GyroAccelUserBank3Registers.I2CSlave3Control.Define(gyroAccelUserBank3Registers) 184 .WithTag("I2C_SLV3_EN", 7, 1) 185 .WithTag("I2C_SLV3_BYTE_SW", 6, 1) 186 .WithTag("I2C_SLV3_REG_DIS", 5, 1) 187 .WithTag("I2C_SLV3_GRP", 4, 1) 188 .WithTag("I2C_SLV3_LENG", 0, 4) 189 ; 190 191 GyroAccelUserBank3Registers.I2CSlave3DataOut.Define(gyroAccelUserBank3Registers) 192 .WithTag("I2C_SLV3_DO", 0, 8) 193 ; 194 195 GyroAccelUserBank3Registers.I2CSlave4Address.Define(gyroAccelUserBank3Registers) 196 .WithTag("I2C_SLV4_RNW", 7, 1) 197 .WithTag("I2C_ID_4", 0, 7) 198 ; 199 200 GyroAccelUserBank3Registers.I2CSlave4Register.Define(gyroAccelUserBank3Registers) 201 .WithTag("I2C_SLV4_REG", 0, 8) 202 ; 203 204 GyroAccelUserBank3Registers.I2CSlave4Control.Define(gyroAccelUserBank3Registers) 205 .WithTag("I2C_SLV4_EN", 7, 1) 206 .WithTag("I2C_SLV4_BYTE_SW", 6, 1) 207 .WithTag("I2C_SLV4_REG_DIS", 5, 1) 208 .WithTag("I2C_SLV4_DLY", 0, 5) 209 ; 210 211 GyroAccelUserBank3Registers.I2CSlave4DataOut.Define(gyroAccelUserBank3Registers) 212 .WithTag("I2C_SLV4_DO", 0, 8) 213 ; 214 215 GyroAccelUserBank3Registers.I2CSlave4DataIn.Define(gyroAccelUserBank3Registers) 216 .WithTag("I2C_SLV4_DI", 0, 8) 217 ; 218 219 DefineBankSelectRegister(gyroAccelUserBank3Registers); 220 } 221 222 private IManagedThread magFeederThread; 223 224 private IValueRegisterField slaveAddress0; 225 private IFlagRegisterField slaveRWBit0; 226 private IValueRegisterField slaveTransactionRegisterAddress0; 227 private IValueRegisterField slaveTransferLength0; 228 private IValueRegisterField slaveDataOut0; 229 230 private enum GyroAccelUserBank3Registers : byte 231 { 232 I2CIDRMasterConfig = 0x0, 233 I2CMasterControl = 0x1, 234 I2CMasterDelayControl = 0x2, 235 I2CSlave0Address = 0x3, 236 I2CSlave0Register = 0x4, 237 I2CSlave0Control = 0x5, 238 I2CSlave0DataOut = 0x6, 239 I2CSlave1Address = 0x7, 240 I2CSlave1Register = 0x8, 241 I2CSlave1Control = 0x9, 242 I2CSlave1DataOut = 0xA, 243 I2CSlave2Address = 0xB, 244 I2CSlave2Register = 0xC, 245 I2CSlave2Control = 0xD, 246 I2CSlave2DataOut = 0xE, 247 I2CSlave3Address = 0xF, 248 I2CSlave3Register = 0x10, 249 I2CSlave3Control = 0x11, 250 I2CSlave3DataOut = 0x12, 251 I2CSlave4Address = 0x13, 252 I2CSlave4Register = 0x14, 253 I2CSlave4Control = 0x15, 254 I2CSlave4DataOut = 0x16, 255 I2CSlave4DataIn = 0x17, 256 } 257 258 private enum I2CTransactionDirection 259 { 260 Unset, 261 Read, 262 Write, 263 } 264 } 265 } 266