1 // 2 // Copyright (c) 2010-2022 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 System.IO; 10 using Antmicro.Renode.Core; 11 using Antmicro.Renode.Core.Structure.Registers; 12 using Antmicro.Renode.Logging; 13 using Antmicro.Renode.Peripherals.I2C; 14 using Antmicro.Renode.Peripherals.Sensor; 15 using Antmicro.Renode.Exceptions; 16 17 namespace Antmicro.Renode.Peripherals.Sensors 18 { 19 public class MC3635 : II2CPeripheral, IProvidesRegisterCollection<ByteRegisterCollection>, ISensor 20 { MC3635(IMachine machine)21 public MC3635(IMachine machine) 22 { 23 this.machine = machine; 24 RegistersCollection = new ByteRegisterCollection(this); 25 accelerationFifo = new SensorSamplesFifo<Vector3DSample>(); 26 DefineRegisters(); 27 IRQ = new GPIO(); 28 } 29 Reset()30 public void Reset() 31 { 32 initialized = false; 33 maximumValue = MaximumValue.bits6; 34 range = GRange.G2; 35 mode.Value = Modes.Sleep; 36 continuousPowerMode.Value = PowerModes.Low; 37 sniffPowerMode.Value = PowerModes.Low; 38 39 registerAddress = 0; 40 samplingRate = 100; 41 samplingRateRegister.Value = 0; 42 sampleRead = true; 43 interruptClearOnlyOnWrite.Value = false; 44 dataOverwritten.Value = false; 45 wrapAfterStatus.Value = false; 46 47 xAxisDisabled.Value = false; 48 yAxisDisabled.Value = false; 49 zAxisDisabled.Value = false; 50 51 ClearInterrupts(); 52 StopCollection(); 53 } 54 Write(byte[] data)55 public void Write(byte[] data) 56 { 57 if(data.Length == 0) 58 { 59 this.Log(LogLevel.Warning, "Unexpected write with no data"); 60 return; 61 } 62 63 registerAddress = data[0]; 64 this.Log(LogLevel.Noisy, "Register set to {0}", (Registers)registerAddress); 65 66 if(data.Length > 2) 67 { 68 this.Log(LogLevel.Error, "Received write transaction with multiple bytes to write. As burst writes are not specified for this peripheral, redundant bytes will be ignored."); 69 } 70 71 if(data.Length > 1) 72 { 73 RegistersCollection.Write(registerAddress, data[1]); 74 this.Log(LogLevel.Noisy, "Writing 0x{0:X}", data[1]); 75 } 76 } 77 78 // For the purpose of direct acces from the monitor RegisterWrite(byte offset, byte value)79 public void RegisterWrite(byte offset, byte value) 80 { 81 RegistersCollection.Write(offset, value); 82 } 83 84 // For the purpose of direct acces from the monitor RegisterRead(byte offset)85 public byte RegisterRead(byte offset) 86 { 87 return RegistersCollection.Read(offset); 88 } 89 Read(int count = 0)90 public byte[] Read(int count = 0) 91 { 92 var ret = new byte[count]; 93 94 for(int i = 0; i < count; i++) 95 { 96 ret[i] = RegistersCollection.Read(registerAddress); 97 this.Log(LogLevel.Noisy, "Reading from {0}: 0x{1:X}", (Registers)registerAddress, ret[i]); 98 99 if(registerAddress == (uint)(wrapAfterStatus.Value ? Registers.Status2 : Registers.ZoutMsb)) 100 { 101 registerAddress = (byte)Registers.XoutLsb; 102 } 103 else 104 { 105 registerAddress++; 106 } 107 } 108 return ret; 109 } 110 FeedAccelerationSample(decimal x, decimal y, decimal z, uint repeat = 1)111 public void FeedAccelerationSample(decimal x, decimal y, decimal z, uint repeat = 1) 112 { 113 var sample = new Vector3DSample(x, y, z); 114 115 for(var i = 0; i < repeat; i++) 116 { 117 accelerationFifo.FeedSample(sample); 118 } 119 } 120 FeedAccelerationSample(string path)121 public void FeedAccelerationSample(string path) 122 { 123 accelerationFifo.FeedSamplesFromFile(path); 124 } 125 FinishTransmission()126 public void FinishTransmission() 127 { 128 // Intentionally left blank 129 } 130 131 public decimal CurrentAccelerationX 132 { 133 get => accelerationFifo.Sample.X; 134 } 135 136 public decimal CurrentAccelerationY 137 { 138 get => accelerationFifo.Sample.Y; 139 } 140 141 public decimal CurrentAccelerationZ 142 { 143 get => accelerationFifo.Sample.Z; 144 } 145 146 public decimal DefaultAccelerationX 147 { 148 get => accelerationFifo.DefaultSample.X; 149 set 150 { 151 accelerationFifo.DefaultSample.X = value; 152 } 153 } 154 155 public decimal DefaultAccelerationY 156 { 157 get => accelerationFifo.DefaultSample.Y; 158 set 159 { 160 accelerationFifo.DefaultSample.Y = value; 161 } 162 } 163 164 public decimal DefaultAccelerationZ 165 { 166 get => accelerationFifo.DefaultSample.Z; 167 set 168 { 169 accelerationFifo.DefaultSample.Z = value; 170 } 171 } 172 173 public GPIO IRQ { get; } 174 175 public ByteRegisterCollection RegistersCollection { get; } 176 UpdateInterrupts()177 private void UpdateInterrupts() 178 { 179 var wake = wakeInterrupt.Value && wakeInterruptEnable.Value; 180 var acquired = acquiredInterrupt.Value && acquiredInterruptEnable.Value; 181 var fifoEmpty = fifoEmptyInterrupt.Value && fifoEmptyInterruptEnable.Value; 182 var fifoFull = fifoFullInterrupt.Value && fifoFullInterruptEnable.Value; 183 var fifoThreshold = fifoThresholdInterrupt.Value && fifoThresholdInterruptEnable.Value; 184 var sniff = sniffInterrupt.Value && sniffInterruptEnable.Value; 185 186 IRQ.Set(wake || acquired || fifoEmpty || fifoFull || fifoThreshold || sniff); 187 } 188 IsInterruptPending()189 private bool IsInterruptPending() 190 { 191 return wakeInterrupt.Value || acquiredInterrupt.Value || fifoEmptyInterrupt.Value 192 || fifoFullInterrupt.Value || fifoThresholdInterrupt.Value || sniffInterrupt.Value; 193 } 194 RaiseInterrupt(ref IFlagRegisterField interrupt)195 private void RaiseInterrupt(ref IFlagRegisterField interrupt) 196 { 197 interrupt.Value = true; 198 UpdateInterrupts(); 199 } 200 ClearInterrupts()201 private void ClearInterrupts() 202 { 203 wakeInterrupt.Value = false; 204 acquiredInterrupt.Value = false; 205 fifoEmptyInterrupt.Value = false; 206 fifoFullInterrupt.Value = false; 207 fifoThresholdInterrupt.Value = false; 208 sniffInterrupt.Value = false; 209 UpdateInterrupts(); 210 } 211 LoadNextSample()212 private void LoadNextSample() 213 { 214 this.Log(LogLevel.Debug, "Acquiring next sample"); 215 if(sampleRead) 216 { 217 sampleRead = false; 218 dataOverwritten.Value = false; 219 } 220 else 221 { 222 dataOverwritten.Value = true; 223 this.Log(LogLevel.Warning, "Data Overwritten"); 224 } 225 accelerationFifo.TryDequeueNewSample(); 226 RaiseInterrupt(ref acquiredInterrupt); 227 } 228 StartSampleCollection()229 private void StartSampleCollection() 230 { 231 StopCollection(); 232 LoadNextSample(); 233 234 samplingThread = machine.ObtainManagedThread(LoadNextSample, samplingRate); 235 samplingThread.Start(); 236 this.Log(LogLevel.Debug, "Sample acquisition thread started"); 237 } 238 StopCollection()239 private void StopCollection() 240 { 241 if(samplingThread != null) 242 { 243 samplingThread.Dispose(); 244 samplingThread = null; 245 this.Log(LogLevel.Debug, "Sample acquisition thread stopped"); 246 } 247 } 248 GetScaledValue(decimal value, MaximumValue maximumVal, GRange range, bool upperByte)249 private byte GetScaledValue(decimal value, MaximumValue maximumVal, GRange range, bool upperByte) 250 { 251 var scaled = (short)(value * (uint)maximumVal / (uint)range); 252 sampleRead = true; 253 return upperByte 254 ? (byte)(scaled >> 8) 255 : (byte)scaled; 256 } 257 SetSamplingFrequency()258 private void SetSamplingFrequency() 259 { 260 if(samplingRateRegister.Value == 0xF) 261 { 262 this.Log(LogLevel.Warning, "This model does not confirm if all necessary steps for setting the highest sampling rate ware taken. Please make sure to follow the flow from '(0X11) RATE REGISTER 1` chapter"); 263 } 264 265 var currentMode = (mode.Value == Modes.Sniff ? sniffPowerMode : continuousPowerMode); 266 267 switch(currentMode.Value) 268 { 269 // As there is no pattern, all possibilities must be handled manually 270 case PowerModes.UltraLow: 271 switch(samplingRateRegister.Value) 272 { 273 case 0x6: 274 samplingRate = 25; break; 275 case 0x7: 276 samplingRate = 50; break; 277 case 0x8: 278 samplingRate = 100; break; 279 case 0x9: 280 samplingRate = 190; break; 281 case 0xA: 282 samplingRate = 380; break; 283 case 0xB: 284 samplingRate = 750; break; 285 case 0xC: 286 samplingRate = 1100; break; 287 case 0xF: 288 samplingRate = 1300; break; 289 default: 290 this.Log(LogLevel.Error, "0x{0:X} is not a legal RATE setting in {1} power mode. Setting the lowest possible value", samplingRateRegister.Value, continuousPowerMode); 291 goto case 0x6; 292 } 293 break; 294 case PowerModes.Low: 295 switch(samplingRateRegister.Value) 296 { 297 case 0x5: 298 samplingRate = 14; break; 299 case 0x6: 300 samplingRate = 28; break; 301 case 0x7: 302 samplingRate = 54; break; 303 case 0x8: 304 samplingRate = 105; break; 305 case 0x9: 306 samplingRate = 210; break; 307 case 0xA: 308 samplingRate = 400; break; 309 case 0xB: 310 samplingRate = 600; break; 311 case 0xF: 312 samplingRate = 750; break; 313 default: 314 this.Log(LogLevel.Error, "0x{0:X} is not a legal RATE setting in {1} power mode. Setting the lowest possible value", samplingRateRegister.Value, continuousPowerMode); 315 goto case 0x5; 316 } 317 break; 318 case PowerModes.Precision: 319 switch(samplingRateRegister.Value) 320 { 321 case 0x5: 322 samplingRate = 14; break; 323 case 0x6: 324 samplingRate = 28; break; 325 case 0x7: 326 samplingRate = 55; break; 327 case 0x8: 328 samplingRate = 80; break; 329 case 0xF: 330 samplingRate = 100; break; 331 default: 332 this.Log(LogLevel.Error, "0x{0:X} is not a legal RATE setting in {1} power mode. Setting the lowest possible value", samplingRateRegister.Value, continuousPowerMode); 333 goto case 0x5; 334 } 335 break; 336 default: 337 throw new ArgumentException($"Invalid power mode: {continuousPowerMode}"); 338 } 339 this.Log(LogLevel.Debug, "Sampling rate set to {0} Hz", samplingRate); 340 } 341 DefineRegisters()342 private void DefineRegisters() 343 { 344 Registers.ExtendedStatus1.Define(this) 345 .WithReservedBits(0, 3) 346 .WithTag("I2C_AD0", 3, 1) 347 .WithReservedBits(4, 4); 348 Registers.ExtendedStatus2.Define(this, 0x4) 349 .WithFlag(0, out dataOverwritten, name: "OVR_DATA") 350 .WithTaggedFlag("PD_CLK_STAT", 1) // Clocks are disabled 351 .WithReservedBits(2, 3) 352 .WithTaggedFlag("OPT_BUSY", 5) // OTP_VDD is enabled, OTP is powered 353 .WithTaggedFlag("SNIFF_EN", 6) // SNIFF mode is active 354 .WithTaggedFlag("SNIFF_DETECT", 7); // Sniff event detected. move to CWAKE mode 355 Registers.XoutLsb.Define(this) 356 .WithValueField(0, 8, FieldMode.Read, 357 valueProviderCallback: _ => GetScaledValue(xAxisDisabled.Value ? 0 : accelerationFifo.Sample.X, maximumValue, range, upperByte: false), 358 name: "XOUT_LSB"); 359 Registers.XoutMsb.Define(this) 360 .WithValueField(0, 8, FieldMode.Read, 361 valueProviderCallback: _ => GetScaledValue(xAxisDisabled.Value ? 0 : accelerationFifo.Sample.X, maximumValue, range, upperByte: true), 362 name: "XOUT_MSB"); 363 Registers.YoutLsb.Define(this) 364 .WithValueField(0, 8, FieldMode.Read, 365 valueProviderCallback: _ => GetScaledValue(yAxisDisabled.Value ? 0 : accelerationFifo.Sample.Y, maximumValue, range, upperByte: false), 366 name: "YOUT_LSB"); 367 Registers.YoutMsb.Define(this) 368 .WithValueField(0, 8, FieldMode.Read, 369 valueProviderCallback: _ => GetScaledValue(yAxisDisabled.Value ? 0 : accelerationFifo.Sample.Y, maximumValue, range, upperByte: true), 370 name: "YOUT_MSB"); 371 Registers.ZoutLsb.Define(this) 372 .WithValueField(0, 8, FieldMode.Read, 373 valueProviderCallback: _ => GetScaledValue(zAxisDisabled.Value ? 0 : accelerationFifo.Sample.Z, maximumValue, range, upperByte: false), 374 name: "ZOUT_LSB"); 375 Registers.ZoutMsb.Define(this) 376 .WithValueField(0, 8, FieldMode.Read, 377 valueProviderCallback: _ => GetScaledValue(zAxisDisabled.Value ? 0 : accelerationFifo.Sample.Z, maximumValue, range, upperByte: true), 378 name: "ZOUT_MSB"); 379 Registers.Status1.Define(this) 380 .WithValueField(0, 3, FieldMode.Read, name: "MODE") 381 .WithFlag(3, FieldMode.Read, valueProviderCallback: _ => !sampleRead, name: "NEW_DATA") 382 .WithTaggedFlag("FIFO_EMPTY", 4) 383 .WithTaggedFlag("FIFO_FULL", 5) 384 .WithTaggedFlag("FIFO_THRESH", 6) 385 .WithFlag(7, FieldMode.Read, valueProviderCallback: (_) => IsInterruptPending(), name: "INT_PEND"); 386 Registers.Status2.Define(this) 387 .WithReservedBits(0, 2) 388 .WithFlag(2, out wakeInterrupt, FieldMode.Read, name: "INT_WAKE") 389 .WithFlag(3, out acquiredInterrupt, FieldMode.Read, name: "INT_ACQ") 390 .WithFlag(4, out fifoEmptyInterrupt, FieldMode.Read, name: "INT_FIFO_EMPTY") 391 .WithFlag(5, out fifoFullInterrupt, FieldMode.Read, name: "INT_FIFO_FULL") 392 .WithFlag(6, out fifoThresholdInterrupt, FieldMode.Read, name: "INT_FIFO_THRESH") 393 .WithFlag(7, out sniffInterrupt, FieldMode.Read, name: "INT_SWAKE") 394 .WithReadCallback((_, __) => { if(!interruptClearOnlyOnWrite.Value) ClearInterrupts(); }) 395 .WithWriteCallback((_, __) => ClearInterrupts()); 396 Registers.Feature1.Define(this) 397 .WithReservedBits(0, 3, 0b000) 398 .WithTaggedFlag("FREEZE", 3) 399 .WithTaggedFlag("INTSC_EN", 4) 400 .WithTaggedFlag("SPI3_EN", 5) 401 .WithFlag(6, FieldMode.Read, name: "I2C_EN") 402 .WithFlag(7, writeCallback: (_, val) => { if(val) this.Log(LogLevel.Error, "SPI interface is not supported"); }, name: "SPI_EN"); 403 Registers.Feature2.Define(this) 404 .WithFlag(0, out wrapAfterStatus, name: "WRAPA") 405 .WithTaggedFlag("FIFO_BURST", 1) 406 .WithTaggedFlag("SPI_STAT_EN", 2) 407 .WithTaggedFlag("FIFO_STAT_EN", 3) 408 .WithFlag(4, out interruptClearOnlyOnWrite, name: "I2CINT_WRCLRE") 409 .WithTaggedFlag("FIFO_STREAM", 5) 410 .WithTaggedFlag("EXT_TRIG_POL", 6) 411 .WithTaggedFlag("EXT_TRIG_EN", 7); 412 Registers.Initialization1.Define(this, 0x40) 413 .WithValueField(0, 8, writeCallback: (_, val) => 414 { 415 if(val == 0x42) 416 { 417 initialized = true; 418 } 419 else 420 { 421 this.Log(LogLevel.Error, "INIT_1 should always be written with 0x42, got 0x{0:x}", val); 422 } 423 }, valueProviderCallback: (_) => { return initialized ? 0x43u : 0x40u; }, name: "INIT_1"); 424 Registers.ModeControl.Define(this) 425 .WithEnumField(0, 3, out mode, writeCallback: (_, __) => 426 { 427 switch(mode.Value) 428 { 429 case Modes.Cwake: 430 StartSampleCollection(); 431 break; 432 case Modes.Sniff: 433 case Modes.Swake: 434 this.Log(LogLevel.Error, "{0} mode unimplemented. Switching to Standby", mode.Value); 435 mode.Value = Modes.Standby; 436 break; 437 default: 438 // SLEEP and STANDBY 439 StopCollection(); 440 break; 441 } 442 this.Log(LogLevel.Debug, "Changed mode to {0}", mode); 443 SetSamplingFrequency(); 444 }, name: "MCTRL") 445 .WithReservedBits(3, 1) 446 .WithFlag(4, out xAxisDisabled, name: "X_AXIS_PD") 447 .WithFlag(5, out yAxisDisabled, name: "Y_AXIS_PD") 448 .WithFlag(6, out zAxisDisabled, name: "Z_AXIS_PD") 449 .WithTaggedFlag("TRIG_CMD", 7); 450 Registers.Rate1.Define(this) 451 .WithValueField(0, 4, out samplingRateRegister, writeCallback: (_, __) => SetSamplingFrequency(), name: "RATE_1") 452 .WithReservedBits(4, 4); 453 Registers.SniffControl.Define(this) 454 .WithTag("SNIFF_RR", 0, 4) 455 .WithReservedBits(4, 1, 0b0) 456 .WithTag("STB_RATE", 5, 3); 457 Registers.SniffThresholdControl.Define(this) 458 .WithTag("SNIFF_TH", 0, 6) 459 .WithTaggedFlag("SNIFF_AND_OR", 6) 460 .WithTaggedFlag("SNIFF_MODE", 7); 461 Registers.SniffConfiguration.Define(this) 462 .WithTag("SNIFF_THARD", 0, 2) 463 .WithTaggedFlag("SNIFF_CNTEN", 3) 464 .WithTag("SNIFF_MUX", 4, 2) 465 .WithTaggedFlag("SNIFF_RESET", 7); 466 Registers.RangeResolutionControl.Define(this) 467 .WithValueField(0, 3, writeCallback: (_, val) => 468 { 469 switch(val) 470 { 471 case 0b000: //6 bits 472 maximumValue = MaximumValue.bits6; 473 break; 474 case 0b001: //7 bits 475 maximumValue = MaximumValue.bits7; 476 break; 477 case 0b010: //8 bits 478 maximumValue = MaximumValue.bits8; 479 break; 480 case 0b011: //10 bits 481 maximumValue = MaximumValue.bits10; 482 break; 483 case 0b100: //12 bits 484 maximumValue = MaximumValue.bits12; 485 break; 486 case 0b101: //14 bits (only 12-bits if FIFO enabled) 487 maximumValue = MaximumValue.bits14; 488 break; 489 default: 490 this.Log(LogLevel.Error, "Invalid RANGE.RES value. Setting to default"); 491 goto case 0b000; 492 } 493 this.Log(LogLevel.Debug, "Bit width set to {0}", maximumValue); 494 }, name: "RES") 495 .WithReservedBits(3, 1) 496 .WithValueField(4, 3, writeCallback: (_, val) => 497 { 498 switch(val) 499 { 500 case 0b000: // ±2g 501 range = GRange.G2; 502 break; 503 case 0b001: // ±4g 504 range = GRange.G4; 505 break; 506 case 0b010: // ±8g 507 range = GRange.G8; 508 break; 509 case 0b011: // ±16g 510 range = GRange.G16; 511 break; 512 case 0b100: // ±12g 513 range = GRange.G12; 514 break; 515 default: 516 this.Log(LogLevel.Error, "Invalid RANGE.RANGE value. Setting to default"); 517 goto case 0b000; 518 } 519 this.Log(LogLevel.Debug, "Range set to {0}", range); 520 }, name: "RANGE") 521 .WithReservedBits(7, 1); 522 Registers.FifoControl.Define(this) 523 .WithTag("FIFO_TH", 0, 4) 524 .WithTaggedFlag("FIFO_MODE", 5) 525 .WithTaggedFlag("FIFO_EN", 6) 526 .WithTaggedFlag("FIFO_RESET", 7); 527 Registers.InterruptControl.Define(this) 528 .WithTaggedFlag("IPP", 0) 529 .WithTaggedFlag("IAH", 1) 530 .WithFlag(2, out wakeInterruptEnable, name: "INT_WAKE") 531 .WithFlag(3, out acquiredInterruptEnable, name: "INT_ACQ") 532 .WithFlag(4, out fifoEmptyInterruptEnable, name: "INT_FIFO_EMPTY") 533 .WithFlag(5, out fifoFullInterruptEnable, name: "INT_FIFO_FULL") 534 .WithFlag(6, out fifoThresholdInterruptEnable, name: "INT_FIFO_THRESH") 535 .WithFlag(7, out sniffInterruptEnable, name: "INT_SWAKE") 536 .WithWriteCallback((_, __) => UpdateInterrupts()); 537 Registers.Initialization3.Define(this) 538 .WithTag("INIT_3", 0, 8) 539 .WithWriteCallback((_, val) => { if(val != 0x0) this.Log(LogLevel.Error, "INIT_3 should always be written with 0x0, got 0x{0:x}", val); }); 540 Registers.Scratchpad.Define(this) 541 .WithValueField(0, 8, name: "SCRATCH"); // Any value can be written and read-back, this is a part of the initialization 542 Registers.PowerModeControl.Define(this) 543 .WithEnumField(0, 2, out continuousPowerMode, writeCallback: (_ , __) => SetSamplingFrequency(), name: "CSPM") 544 .WithReservedBits(3, 1) 545 .WithEnumField(4, 3, out sniffPowerMode, writeCallback: (_ , __) => SetSamplingFrequency(), name: "SPM") 546 .WithTaggedFlag("SPI_HS_EN", 7); 547 Registers.DriveMotionX.Define(this) 548 .WithReservedBits(0, 2, 0b01) 549 .WithTaggedFlag("DPX", 2) 550 .WithTaggedFlag("DNX", 3) 551 .WithReservedBits(4, 4, 0b0000); 552 Registers.DriveMotionY.Define(this) 553 .WithReservedBits(0, 2, 0b00) 554 .WithTaggedFlag("DPY", 2) 555 .WithTaggedFlag("DNY", 3) 556 .WithReservedBits(4, 4, 0b1000); 557 Registers.DriveMotionZ.Define(this) 558 .WithReservedBits(0, 2, 0b00) 559 .WithTaggedFlag("DPZ", 2) 560 .WithTaggedFlag("DNZ", 3) 561 .WithReservedBits(4, 4, 0b0000); 562 Registers.Reset.Define(this) 563 .WithReservedBits(0, 6) 564 .WithFlag(6, writeCallback: (_, val) => { if(val) Reset(); }, name: "RESET") 565 .WithTaggedFlag("RELOAD", 7); 566 Registers.Initialization2.Define(this) 567 .WithTag("INIT_2", 0, 8) 568 .WithWriteCallback((_, val) => { if(val != 0x0) this.Log(LogLevel.Error, "INIT_2 should always be written with 0x0, got 0x{0:x}", val); }); 569 Registers.TrigggerCount.Define(this) 570 .WithTag("TRIGC", 0, 8); 571 Registers.XOffsetLSB.Define(this) 572 .WithTag("XOFFL", 0, 8); 573 Registers.XOffsetMSB.Define(this) 574 .WithTag("XOFFH", 0, 7) 575 .WithTag("XGAINH", 7, 1); 576 Registers.YOffsetLSB.Define(this) 577 .WithTag("YOFFL", 0, 8); 578 Registers.YOffsetMSB.Define(this) 579 .WithTag("YOFFH", 0, 7) 580 .WithTag("YGAINH", 7, 1); 581 Registers.ZOffsetLSB.Define(this) 582 .WithTag("ZOFFL", 0, 8); 583 Registers.ZOffsetMSB.Define(this) 584 .WithTag("ZOFFH", 0, 7) 585 .WithTag("ZGAINH", 7, 1); 586 Registers.GainX.Define(this) 587 .WithTag("XGAINL", 0, 8); 588 Registers.GainY.Define(this) 589 .WithTag("YGAINL", 0, 8); 590 Registers.GainZ.Define(this) 591 .WithTag("ZGAINL", 0, 8); 592 } 593 594 private bool sampleRead; 595 private bool initialized; 596 private uint registerAddress; 597 private uint samplingRate; 598 private IValueRegisterField samplingRateRegister; 599 600 private GRange range; 601 private MaximumValue maximumValue; 602 603 private IManagedThread samplingThread; 604 private readonly IMachine machine; 605 606 private readonly SensorSamplesFifo<Vector3DSample> accelerationFifo; 607 608 private IEnumRegisterField<PowerModes> continuousPowerMode; 609 private IEnumRegisterField<PowerModes> sniffPowerMode; 610 private IEnumRegisterField<Modes> mode; 611 612 private IFlagRegisterField dataOverwritten; 613 private IFlagRegisterField interruptClearOnlyOnWrite; 614 private IFlagRegisterField wrapAfterStatus; 615 private IFlagRegisterField xAxisDisabled; 616 private IFlagRegisterField yAxisDisabled; 617 private IFlagRegisterField zAxisDisabled; 618 619 private IFlagRegisterField acquiredInterruptEnable; 620 private IFlagRegisterField fifoEmptyInterruptEnable; 621 private IFlagRegisterField fifoFullInterruptEnable; 622 private IFlagRegisterField fifoThresholdInterruptEnable; 623 private IFlagRegisterField sniffInterruptEnable; 624 private IFlagRegisterField wakeInterruptEnable; 625 626 private IFlagRegisterField acquiredInterrupt; 627 private IFlagRegisterField fifoEmptyInterrupt; 628 private IFlagRegisterField fifoFullInterrupt; 629 private IFlagRegisterField fifoThresholdInterrupt; 630 private IFlagRegisterField sniffInterrupt; 631 private IFlagRegisterField wakeInterrupt; 632 633 private enum GRange: ushort 634 { 635 G2 = 2, 636 G4 = 4, 637 G8 = 8, 638 G12 = 12, 639 G16 = 16, 640 } 641 642 private enum MaximumValue 643 { 644 //Maixmum value that can be written with current bit width 645 bits6 = (1 << 6) - 1, 646 bits7 = (1 << 7) - 1, 647 bits8 = (1 << 8) - 1, 648 bits10 = (1 << 10) - 1, 649 bits12 = (1 << 12) - 1, 650 bits14 = (1 << 14) - 1, 651 } 652 653 private enum Modes 654 { 655 Sleep = 0b000, 656 Standby = 0b001, 657 Sniff = 0b010, 658 Cwake = 0b101, 659 Swake = 0b110, 660 } 661 662 private enum PowerModes 663 { 664 Low = 0b000, 665 UltraLow = 0b011, 666 Precision = 0b100, 667 } 668 669 private enum Registers : byte 670 { 671 ExtendedStatus1 = 0x00, 672 ExtendedStatus2 = 0x01, 673 XoutLsb = 0x02, 674 XoutMsb = 0x03, 675 YoutLsb = 0x04, 676 YoutMsb = 0x05, 677 ZoutLsb = 0x06, 678 ZoutMsb = 0x07, 679 Status1 = 0x08, 680 Status2 = 0x09, 681 // 0x0A – 0x0C RESERVED 682 Feature1 = 0x0D, 683 Feature2 = 0x0E, 684 Initialization1 = 0x0F, 685 ModeControl = 0x10, 686 Rate1 = 0x11, 687 SniffControl = 0x12, 688 SniffThresholdControl = 0x13, 689 SniffConfiguration = 0x14, 690 RangeResolutionControl = 0x15, 691 FifoControl = 0x16, 692 InterruptControl = 0x17, 693 // 0x18 – 0x19 RESERVED 694 Initialization3 = 0x1A, 695 Scratchpad = 0x1B, 696 PowerModeControl = 0x1C, 697 // 0x1D – 0x1F RESERVED 698 DriveMotionX = 0x20, 699 DriveMotionY = 0x21, 700 DriveMotionZ = 0x22, 701 // 0x23 RESERVED 702 Reset = 0x24, 703 // 0x25 – 0x27 RESERVED 704 Initialization2 = 0x28, 705 TrigggerCount = 0x29, 706 XOffsetLSB = 0x2A, 707 XOffsetMSB = 0x2B, 708 YOffsetLSB = 0x2C, 709 YOffsetMSB = 0x2D, 710 ZOffsetLSB = 0x2E, 711 ZOffsetMSB = 0x2F, 712 GainX = 0x30, 713 GainY = 0x31, 714 GainZ = 0x32, 715 // 0x33 – 0x3F RESERVED 716 } 717 } 718 } 719