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.Collections.Generic; 8 using System.Linq; 9 10 using Antmicro.Renode.Core; 11 using Antmicro.Renode.Core.Structure; 12 using Antmicro.Renode.Core.Structure.Registers; 13 using Antmicro.Renode.Logging; 14 using Antmicro.Renode.Utilities; 15 using Antmicro.Renode.Peripherals.Bus; 16 17 namespace Antmicro.Renode.Peripherals.I2C 18 { 19 [AllowedTranslations(AllowedTranslation.DoubleWordToByte)] 20 public class S32K3XX_LowPowerInterIntegratedCircuit : SimpleContainer<II2CPeripheral>, IDoubleWordPeripheral, IProvidesRegisterCollection<DoubleWordRegisterCollection>, IKnownSize 21 { S32K3XX_LowPowerInterIntegratedCircuit(IMachine machine)22 public S32K3XX_LowPowerInterIntegratedCircuit(IMachine machine) : base(machine) 23 { 24 IRQ = new GPIO(); 25 26 rxQueue = new Queue<byte>(); 27 txQueue = new Queue<byte>(); 28 29 RegistersCollection = new DoubleWordRegisterCollection(this); 30 DefineRegisters(); 31 } 32 ReadDoubleWord(long offset)33 public uint ReadDoubleWord(long offset) 34 { 35 return RegistersCollection.Read(offset); 36 } 37 WriteDoubleWord(long offset, uint value)38 public void WriteDoubleWord(long offset, uint value) 39 { 40 RegistersCollection.Write(offset, value); 41 } 42 Reset()43 public override void Reset() 44 { 45 RegistersCollection.Reset(); 46 47 rxQueue.Clear(); 48 txQueue.Clear(); 49 UpdateInterrupts(); 50 } 51 52 public DoubleWordRegisterCollection RegistersCollection { get; } 53 public GPIO IRQ { get; } 54 public long Size => 0x1000; 55 UpdateInterrupts()56 private void UpdateInterrupts() 57 { 58 var interrupt = false; 59 interrupt |= transmitDataInterruptEnabled.Value; 60 interrupt |= receiveDataInterruptEnabled.Value && ReceiveDataFlag; 61 interrupt |= stopDetectFlag.Value && stopDetectInterruptEnabled.Value; 62 interrupt |= endPacketFlag.Value && endPacketInterruptEnabled.Value; 63 interrupt |= nackDetectFlag.Value && nackDetectInterruptEnabled.Value; 64 65 this.Log(LogLevel.Debug, "IRQ={0}, transmitDataInterrupt={1}, receiveDataInterrupt={2}, stopDetectInterrupt={3}, endPacketInterrupt={4}, nackDetectInterrupt={5}", 66 interrupt, 67 transmitDataInterruptEnabled.Value, 68 receiveDataInterruptEnabled.Value && ReceiveDataFlag, 69 stopDetectFlag.Value && stopDetectInterruptEnabled.Value, 70 endPacketFlag.Value && endPacketInterruptEnabled.Value, 71 nackDetectFlag.Value && nackDetectInterruptEnabled.Value); 72 IRQ.Set(interrupt); 73 } 74 HandleCommand(Command command)75 private void HandleCommand(Command command) 76 { 77 if(command != Command.TransmitData) 78 { 79 TryFlushTransmitFIFO(); 80 } 81 82 switch(command) 83 { 84 case Command.TransmitData: 85 if(AssertActivePeripheral("transmit data")) 86 { 87 txQueue.Enqueue((byte)transmitData.Value); 88 UpdateInterrupts(); 89 } 90 break; 91 92 case Command.ReceiveData: 93 case Command.ReceiveDataAndDiscard: 94 if(!AssertActivePeripheral("receive data")) 95 { 96 break; 97 } 98 99 // transmitData now contains `amount of data - 1` we would want to receive 100 var receivedData = activePeripheral.Read((int)transmitData.Value + 1); 101 102 if(command != Command.ReceiveDataAndDiscard) 103 { 104 rxQueue.EnqueueRange(RunDataMatcher(receivedData)); 105 UpdateInterrupts(); 106 } 107 break; 108 109 case Command.GenerateSTOP: 110 GenerateStopCondition(); 111 break; 112 113 case Command.Start: 114 case Command.HiSpeedStart: 115 if(activePeripheral != null) 116 { 117 // This is RESTART condition 118 endPacketFlag.Value = true; 119 UpdateInterrupts(); 120 } 121 122 if(automaticSTOPGeneration.Value) 123 { 124 GenerateStopCondition(); 125 } 126 127 // transmitData now contains I2C address 128 if(!TryGetByAddress((int)transmitData.Value >> 1, out activePeripheral)) 129 { 130 nackDetectFlag.Value = true; 131 UpdateInterrupts(); 132 } 133 134 break; 135 136 case Command.StartExpectsNACK: 137 case Command.HiSpeedStartExpectsNACK: 138 if(activePeripheral != null) 139 { 140 // This is RESTART condition 141 endPacketFlag.Value = true; 142 UpdateInterrupts(); 143 } 144 145 if(TryGetByAddress((int)transmitData.Value, out var _)) 146 { 147 // We should write 1 to NACK Detect Flag (NDF) in case we don't expect ACK 148 nackDetectFlag.Value = true; 149 UpdateInterrupts(); 150 } 151 152 break; 153 } 154 } 155 RunDataMatcher(IEnumerable<byte> bytes)156 private IEnumerable<byte> RunDataMatcher(IEnumerable<byte> bytes) 157 { 158 if(matchConfiguration.Value == MatchMode.Disabled || matchConfiguration.Value == MatchMode.Reserved) 159 { 160 return bytes; 161 } 162 163 int? found = null; 164 var bytesIterator = bytes; 165 switch(matchConfiguration.Value) 166 { 167 case MatchMode.FirstMatch0OrMatch1: 168 bytesIterator = bytesIterator.Take(1); 169 goto case MatchMode.AnyMatch0OrMatch1; 170 case MatchMode.AnyMatch0OrMatch1: 171 found = bytesIterator 172 .Select((Byte, Index) => new { Byte, Index }) 173 .FirstOrDefault(item => item.Byte == match0Value.Value || item.Byte == match1Value.Value) 174 ?.Index; 175 break; 176 177 case MatchMode.FirstMatch0ThenMatch1: 178 bytesIterator = bytesIterator.Take(2); 179 goto case MatchMode.AnyMatch0ThenMatch1; 180 case MatchMode.AnyMatch0ThenMatch1: 181 found = bytesIterator 182 .Zip(bytesIterator.Skip(1), (First, Second) => new { First, Second }) 183 .Select((Byte, Index) => new { Byte, Index }) 184 .FirstOrDefault(item => item.Byte.First == match0Value.Value && item.Byte.Second == match1Value.Value) 185 ?.Index; 186 break; 187 188 case MatchMode.FirstAndMatch1EqualMatch0AndMatch1: 189 bytesIterator = bytesIterator.Take(1); 190 goto case MatchMode.AnyAndMatch1EqualMatch0AndMatch1; 191 case MatchMode.AnyAndMatch1EqualMatch0AndMatch1: 192 var maskedValue = match0Value.Value & match1Value.Value; 193 found = bytesIterator 194 .Select((Byte, Index) => new { Byte, Index }) 195 .FirstOrDefault(item => (item.Byte & match1Value.Value) == maskedValue) 196 ?.Index; 197 break; 198 } 199 200 dataMatchFlag.Value |= found.HasValue; 201 UpdateInterrupts(); 202 203 if(receiveDataMatchOnly.Value) 204 { 205 return found.HasValue ? bytes.Skip(found.Value) : Enumerable.Empty<byte>(); 206 } 207 return bytes; 208 } 209 GenerateStopCondition()210 private void GenerateStopCondition() 211 { 212 TryFlushTransmitFIFO(); 213 activePeripheral?.FinishTransmission(); 214 activePeripheral = null; 215 stopDetectFlag.Value = true; 216 endPacketFlag.Value = true; 217 UpdateInterrupts(); 218 } 219 AssertActivePeripheral(string reason)220 private bool AssertActivePeripheral(string reason) 221 { 222 if(activePeripheral == null) 223 { 224 this.Log(LogLevel.Warning, "Tried to {0}, but target device wasn't chosen", reason); 225 return false; 226 } 227 return true; 228 } 229 TryFlushTransmitFIFO()230 private void TryFlushTransmitFIFO() 231 { 232 if(txQueue.Count > 0 && controllerEnabled.Value) 233 { 234 activePeripheral?.Write(txQueue.ToArray()); 235 } 236 237 txQueue.Clear(); 238 UpdateInterrupts(); 239 } 240 DefineRegisters()241 private void DefineRegisters() 242 { 243 Registers.VersionID.Define(this, 0x1203) 244 .WithTag("FeatureSpecificationNumber", 0, 16) 245 .WithTag("MinorVersionNumber", 16, 8) 246 .WithTag("MajorVersionNumber", 24, 8) 247 ; 248 249 Registers.Parameter.Define(this, 0x22) 250 .WithTag("ControllerTransmitFIFOSize", 0, 4) 251 .WithReservedBits(4, 4) 252 .WithTag("ControllerReceiveFIFOSize", 8, 4) 253 .WithReservedBits(12, 20) 254 ; 255 256 Registers.ControllerControl.Define(this) 257 .WithFlag(0, out controllerEnabled, name: "ControllerEnable", 258 changeCallback: (_, value) => { if(value) TryFlushTransmitFIFO(); }) 259 .WithTaggedFlag("SoftwareReset", 1) 260 .WithTaggedFlag("DozeModeEnable", 2) 261 .WithTaggedFlag("DebugEnable", 3) 262 .WithReservedBits(4, 4) 263 .WithFlag(8, FieldMode.Read | FieldMode.WriteOneToClear, name: "ResetTransmitFIFO", 264 // If controller is enabled, we really shouldn't have anything in the FIFO anyway, so 265 // we can try to flush instead of just clearing buffer 266 writeCallback: (_, value) => { if(value) TryFlushTransmitFIFO(); }) 267 .WithFlag(9, FieldMode.Read | FieldMode.WriteOneToClear, name: "ResetReceiveFIFO", 268 writeCallback: (_, value) => { if(value) rxQueue.Clear(); }) 269 .WithReservedBits(10, 22) 270 .WithWriteCallback((_, __) => UpdateInterrupts()) 271 ; 272 273 Registers.ControllerStatus.Define(this, 0x1) 274 .WithFlag(0, FieldMode.Read, name: "TransmitDataFlag", 275 valueProviderCallback: _ => true) 276 .WithFlag(1, FieldMode.Read, name: "ReceiveDataFlag", 277 valueProviderCallback: _ => ReceiveDataFlag) 278 .WithReservedBits(2, 6) 279 .WithFlag(8, out endPacketFlag, FieldMode.Read | FieldMode.WriteOneToClear, name: "EndPacketFlag") 280 .WithFlag(9, out stopDetectFlag, FieldMode.Read | FieldMode.WriteOneToClear, name: "STOPDetectFlag") 281 .WithFlag(10, out nackDetectFlag, FieldMode.Read | FieldMode.WriteOneToClear, name: "NACKDetectFlag") 282 .WithTaggedFlag("ArbitrationLostFlag", 11) 283 .WithTaggedFlag("FIFOErrorFlag", 12) 284 .WithTaggedFlag("PinLowTimeoutFlag", 13) 285 .WithFlag(14, out dataMatchFlag, FieldMode.Read | FieldMode.WriteOneToClear, name: "DataMatchFlag") 286 .WithReservedBits(15, 9) 287 .WithTaggedFlag("ControllerBusyFlag", 24) 288 .WithTaggedFlag("BusBusyFlag", 25) 289 .WithReservedBits(26, 6) 290 .WithChangeCallback((_, __) => UpdateInterrupts()); 291 ; 292 293 Registers.ControllerInterruptEnable.Define(this) 294 .WithFlag(0, out transmitDataInterruptEnabled, name: "TransmitDataInterruptEnable") 295 .WithFlag(1, out receiveDataInterruptEnabled, name: "ReceiveDataInterruptEnable") 296 .WithReservedBits(2, 6) 297 .WithFlag(8, out endPacketInterruptEnabled, name: "EndPacketInterruptEnable") 298 .WithFlag(9, out stopDetectInterruptEnabled, name: "STOPDetectInterruptEnable") 299 .WithFlag(10, out nackDetectInterruptEnabled, name: "NACKDetectInterruptEnable") 300 .WithTaggedFlag("ArbitrationLostInterruptEnable", 11) 301 .WithTaggedFlag("FIFOErrorInterruptEnable", 12) 302 .WithTaggedFlag("PinLowTimeoutInterruptEnable", 13) 303 .WithFlag(14, out dataMatchInterruptEnabled, name: "DataMatchInterruptEnable") 304 .WithReservedBits(15, 7) 305 .WithChangeCallback((_, __) => UpdateInterrupts()); 306 ; 307 308 Registers.ControllerDMAEnable.Define(this) 309 .WithTaggedFlag("TransmitDataDMAEnable", 0) 310 .WithTaggedFlag("ReceiveDataDMAEnable", 1) 311 .WithReservedBits(3, 29) 312 ; 313 314 Registers.ControllerConfiguration0.Define(this) 315 .WithTaggedFlag("HostRequestEnable", 0) 316 .WithTaggedFlag("HostRequestPolarity", 1) 317 .WithTaggedFlag("HostRequestSelect", 2) 318 .WithReservedBits(3, 5) 319 .WithTaggedFlag("CircularFIFOEnable", 8) 320 .WithFlag(9, out receiveDataMatchOnly, name: "ReceiveDataMatchOnly") 321 .WithReservedBits(10, 12) 322 ; 323 324 Registers.ControllerConfiguration1.Define(this) 325 .WithTag("Prescaler", 0, 3) 326 .WithReservedBits(4, 4) 327 .WithFlag(8, out automaticSTOPGeneration, name: "AutomaticSTOPGeneration") 328 .WithTaggedFlag("IgnoreNACK", 9) 329 .WithTaggedFlag("TimeoutConfiguration", 10) 330 .WithReservedBits(11, 5) 331 .WithEnumField(16, 3, out matchConfiguration, name: "MatchConfiguration") 332 .WithReservedBits(19, 4) 333 .WithTag("PinConfiguration", 24, 3) 334 .WithReservedBits(27, 5) 335 ; 336 337 Registers.ControllerConfiguration2.Define(this) 338 .WithTag("BusIdleTimeout", 0, 12) 339 .WithReservedBits(12, 4) 340 .WithTag("GlitchFilterSCL", 16, 4) 341 .WithReservedBits(20, 4) 342 .WithTag("GlitchFilterSDA", 24, 4) 343 .WithReservedBits(28, 4) 344 ; 345 346 Registers.ControllerConfiguration3.Define(this) 347 .WithReservedBits(0, 8) 348 .WithTag("PinLowTimeout", 8, 12) 349 .WithReservedBits(20, 12) 350 ; 351 352 Registers.ControllerDataMatch.Define(this) 353 .WithValueField(0, 8, out match0Value, name: "Match0Value") 354 .WithReservedBits(8, 8) 355 .WithValueField(16, 8, out match1Value, name: "Match1Value") 356 .WithReservedBits(24, 8) 357 ; 358 359 Registers.ControllerClockConfiguration0.Define(this) 360 .WithTag("ClockLowPeriod", 0, 6) 361 .WithReservedBits(6, 2) 362 .WithTag("ClockHighPeriod", 8, 5) 363 .WithReservedBits(14, 2) 364 .WithTag("SetupHoldDelay", 16, 6) 365 .WithReservedBits(22, 2) 366 .WithTag("DataValidDelay", 24, 6) 367 .WithReservedBits(30, 2) 368 ; 369 370 Registers.ControllerClockConfiguration1.Define(this) 371 .WithTag("ClockLowPeriod", 0, 6) 372 .WithReservedBits(6, 2) 373 .WithTag("ClockHighPeriod", 8, 5) 374 .WithReservedBits(14, 2) 375 .WithTag("SetupHoldDelay", 16, 6) 376 .WithReservedBits(22, 2) 377 .WithTag("DataValidDelay", 24, 6) 378 .WithReservedBits(30, 2) 379 ; 380 381 Registers.ControllerFIFOControl.Define(this) 382 .WithValueField(0, 2, out txWatermark, name: "TransmitFIFOWatermark") 383 .WithReservedBits(2, 14) 384 .WithValueField(16, 2, out rxWatermark, name: "ReceiveFIFOWatermark") 385 .WithReservedBits(18, 14) 386 .WithChangeCallback((_, __) => UpdateInterrupts()) 387 ; 388 389 Registers.ControllerFIFOStatus.Define(this) 390 .WithValueField(0, 2, FieldMode.Read, name: "TransmitFIFOCount", 391 valueProviderCallback: _ => 0) 392 .WithReservedBits(2, 14) 393 .WithValueField(16, 2, FieldMode.Read, name: "ReceiveFIFOCount", 394 valueProviderCallback: _ => (ulong)rxQueue.Count.Clamp(0, 2)) 395 .WithReservedBits(18, 14) 396 ; 397 398 Registers.ControllerTransmitData.Define(this) 399 .WithValueField(0, 8, out transmitData, name: "TransmitData") 400 .WithEnumField<DoubleWordRegister, Command>(8, 3, name: "CommandData", 401 writeCallback: (_, value) => HandleCommand(value)) 402 .WithReservedBits(11, 21) 403 ; 404 405 Registers.ControllerReceiveData.Define(this) 406 .WithValueField(0, 8, FieldMode.Read, name: "ReceiveData", 407 valueProviderCallback: _ => 408 { 409 if(!rxQueue.TryDequeue(out var b)) 410 { 411 this.Log(LogLevel.Warning, "Trying to read from empty rx fifo"); 412 return default(byte); 413 } 414 if(rxQueue.Count == 0 && automaticSTOPGeneration.Value) 415 { 416 GenerateStopCondition(); 417 } 418 return b; 419 }) 420 .WithReservedBits(8, 6) 421 .WithFlag(14, FieldMode.Read, name: "ReceiveEmpty", 422 valueProviderCallback: _ => rxQueue.Count == 0) 423 .WithReservedBits(15, 17) 424 .WithReadCallback((_, __) => UpdateInterrupts()) 425 ; 426 427 Registers.TargetControl.Define(this) 428 .WithTaggedFlag("TargetEnable", 0) 429 .WithTaggedFlag("SoftwareReset", 1) 430 .WithReservedBits(2, 2) 431 .WithTaggedFlag("FilterEnable", 4) 432 .WithTaggedFlag("FilterDozeEnable", 5) 433 .WithReservedBits(6, 2) 434 .WithTaggedFlag("ResetTransmitFIFO", 8) 435 .WithTaggedFlag("ResetReceiveFIFO", 9) 436 .WithReservedBits(10, 22) 437 ; 438 439 Registers.TargetStatus.Define(this) 440 .WithTaggedFlag("TransmitDataFlag", 0) 441 .WithTaggedFlag("ReceiveDataFlag", 1) 442 .WithTaggedFlag("AddressValidFlag", 2) 443 .WithTaggedFlag("TransmitACKFlag", 3) 444 .WithReservedBits(4, 4) 445 .WithTaggedFlag("RepeatedStartFlag", 8) 446 .WithTaggedFlag("STOPDetectFlag", 9) 447 .WithTaggedFlag("BitErrorFlag", 10) 448 .WithTaggedFlag("FIFOErrorFlag", 11) 449 .WithTaggedFlag("AddressMatch0Flag", 12) 450 .WithTaggedFlag("AddressMatch1Flag", 13) 451 .WithTaggedFlag("GeneralCallFlag", 14) 452 .WithTaggedFlag("SMBusAlertResponseFlag", 15) 453 .WithReservedBits(16, 8) 454 .WithTaggedFlag("TargetBusyFlag", 24) 455 .WithTaggedFlag("BusBusyFlag", 25) 456 .WithReservedBits(26, 6) 457 ; 458 459 Registers.TargetInterruptEnable.Define(this) 460 .WithTaggedFlag("TransmitDataInterruptEnable", 0) 461 .WithTaggedFlag("ReceiveDataInterruptEnable", 1) 462 .WithTaggedFlag("AddressValidInterruptEnable", 2) 463 .WithTaggedFlag("TransmitACKInterruptEnable", 3) 464 .WithReservedBits(4, 4) 465 .WithTaggedFlag("RepeatedStartInterruptEnable", 8) 466 .WithTaggedFlag("STOPDetectInterruptEnable", 9) 467 .WithTaggedFlag("BitErrorInterruptEnable", 10) 468 .WithTaggedFlag("FIFOErrorInterruptEnable", 11) 469 .WithTaggedFlag("AddressMatch0InterruptEnable", 12) 470 .WithTaggedFlag("AddressMatch1InterruptEnable", 13) 471 .WithTaggedFlag("GeneralCallInterruptEnable", 14) 472 .WithTaggedFlag("SMBusAlertResponseInterruptEnable", 15) 473 .WithReservedBits(16, 16) 474 ; 475 476 Registers.TargetDMAEnable.Define(this) 477 .WithTaggedFlag("TransmitDataDMAEnable", 0) 478 .WithTaggedFlag("ReceiveDataDMAEnable", 1) 479 .WithTaggedFlag("AddressValidDMAEnable", 2) 480 .WithReservedBits(3, 29) 481 ; 482 483 Registers.TargetConfiguration1.Define(this) 484 .WithTaggedFlag("AddressSCLStall", 0) 485 .WithTaggedFlag("RXSCLStall", 1) 486 .WithTaggedFlag("TransmitDataSCLStall", 2) 487 .WithTaggedFlag("ACKSCLStall", 3) 488 .WithReservedBits(4, 4) 489 .WithTaggedFlag("GeneralCallEnable", 8) 490 .WithTaggedFlag("SMBusAlertEnable", 9) 491 .WithTaggedFlag("TransmitFlagConfiguration", 10) 492 .WithTaggedFlag("ReceiveDataConfiguration", 11) 493 .WithTaggedFlag("IgnoreNACK", 12) 494 .WithTaggedFlag("HighSpeedModeEnable,", 13) 495 .WithReservedBits(14, 2) 496 .WithTag("AddressConfiguration", 16, 3) 497 .WithReservedBits(19, 13) 498 ; 499 500 Registers.TargetConfiguration2.Define(this) 501 .WithTag("ClockHoldTime", 0, 4) 502 .WithReservedBits(4, 4) 503 .WithTag("DataValidDelay", 8, 4) 504 .WithReservedBits(14, 2) 505 .WithTag("GlitchFilterSCL", 16, 4) 506 .WithTag("GlitchFilterSDA", 24, 4) 507 ; 508 509 Registers.TargetAddressMatch.Define(this) 510 .WithReservedBits(0, 1) 511 .WithTag("Address0Value", 1, 10) 512 .WithReservedBits(11, 6) 513 .WithTag("Address0Value", 17, 10) 514 .WithReservedBits(27, 5) 515 ; 516 517 Registers.TargetAddressStatus.Define(this) 518 .WithTag("ReceivedAddress", 0, 11) 519 .WithReservedBits(11, 3) 520 .WithTaggedFlag("AddressNotValid", 14) 521 .WithReservedBits(15, 17) 522 ; 523 524 Registers.TargetTransmitACK.Define(this) 525 .WithTaggedFlag("TransmitNACK", 0) 526 .WithReservedBits(1, 31) 527 ; 528 529 Registers.TargetTransmitData.Define(this) 530 .WithTag("TransmitData", 0, 8) 531 .WithReservedBits(8, 24) 532 ; 533 534 Registers.TargetReceiveData.Define(this) 535 .WithTag("ReceiveData", 0, 8) 536 .WithTag("ReceivedAddress", 8, 3) 537 .WithReservedBits(11, 3) 538 .WithTaggedFlag("ReceiveEmpty", 14) 539 .WithTaggedFlag("StartOfFrame", 15) 540 .WithReservedBits(16, 16) 541 ; 542 } 543 544 private bool ReceiveDataFlag => rxQueue.Count > (int)rxWatermark.Value; 545 546 private readonly Queue<byte> txQueue; 547 private readonly Queue<byte> rxQueue; 548 549 private II2CPeripheral activePeripheral; 550 551 private IEnumRegisterField<MatchMode> matchConfiguration; 552 553 private IValueRegisterField transmitData; 554 private IValueRegisterField txWatermark; 555 private IValueRegisterField rxWatermark; 556 private IValueRegisterField match0Value; 557 private IValueRegisterField match1Value; 558 559 private IFlagRegisterField controllerEnabled; 560 private IFlagRegisterField automaticSTOPGeneration; 561 562 private IFlagRegisterField endPacketFlag; 563 private IFlagRegisterField nackDetectFlag; 564 private IFlagRegisterField stopDetectFlag; 565 private IFlagRegisterField dataMatchFlag; 566 567 private IFlagRegisterField transmitDataInterruptEnabled; 568 private IFlagRegisterField receiveDataInterruptEnabled; 569 private IFlagRegisterField endPacketInterruptEnabled; 570 private IFlagRegisterField nackDetectInterruptEnabled; 571 private IFlagRegisterField stopDetectInterruptEnabled; 572 private IFlagRegisterField dataMatchInterruptEnabled; 573 private IFlagRegisterField receiveDataMatchOnly; 574 575 private enum MatchMode 576 { 577 Disabled, 578 Reserved, 579 FirstMatch0OrMatch1, 580 AnyMatch0OrMatch1, 581 FirstMatch0ThenMatch1, 582 AnyMatch0ThenMatch1, 583 FirstAndMatch1EqualMatch0AndMatch1, 584 AnyAndMatch1EqualMatch0AndMatch1, 585 } 586 587 private enum Command 588 { 589 TransmitData, 590 ReceiveData, 591 GenerateSTOP, 592 ReceiveDataAndDiscard, 593 Start, 594 StartExpectsNACK, 595 HiSpeedStart, 596 HiSpeedStartExpectsNACK 597 } 598 599 private enum Registers 600 { 601 VersionID = 0x0, 602 Parameter = 0x4, 603 ControllerControl = 0x10, 604 ControllerStatus = 0x14, 605 ControllerInterruptEnable = 0x18, 606 ControllerDMAEnable = 0x1c, 607 ControllerConfiguration0 = 0x20, 608 ControllerConfiguration1 = 0x24, 609 ControllerConfiguration2 = 0x28, 610 ControllerConfiguration3 = 0x2C, 611 ControllerDataMatch = 0x40, 612 ControllerClockConfiguration0 = 0x48, 613 ControllerClockConfiguration1 = 0x50, 614 ControllerFIFOControl = 0x58, 615 ControllerFIFOStatus = 0x5C, 616 ControllerTransmitData = 0x60, 617 ControllerReceiveData = 0x70, 618 TargetControl = 0x110, 619 TargetStatus = 0x114, 620 TargetInterruptEnable = 0x118, 621 TargetDMAEnable = 0x11C, 622 TargetConfiguration1 = 0x124, 623 TargetConfiguration2 = 0x128, 624 TargetAddressMatch = 0x140, 625 TargetAddressStatus = 0x150, 626 TargetTransmitACK = 0x154, 627 TargetTransmitData = 0x160, 628 TargetReceiveData = 0x170, 629 } 630 } 631 } 632