1 // 2 // Copyright (c) 2010-2025 Antmicro 3 // 4 // This file is licensed under the MIT License. 5 // Full license text is available in 'licenses/MIT.txt'. 6 // 7 8 using System; 9 using System.Collections.Generic; 10 using System.Linq; 11 using Antmicro.Renode.Core; 12 using Antmicro.Renode.Core.Structure; 13 using Antmicro.Renode.Core.Structure.Registers; 14 using Antmicro.Renode.Logging; 15 using Antmicro.Renode.Peripherals.Bus; 16 using Antmicro.Renode.Peripherals.DMA; 17 using Antmicro.Renode.Utilities; 18 19 namespace Antmicro.Renode.Peripherals.I2C 20 { 21 public class SAM4S_TWI : SimpleContainer<II2CPeripheral>, IDoubleWordPeripheral, IKnownSize, 22 IProvidesRegisterCollection<DoubleWordRegisterCollection>, ISamPdcBytePeripheral, ISamPdcBlockBytePeripheral 23 { SAM4S_TWI(Machine machine)24 public SAM4S_TWI(Machine machine) : base(machine) 25 { 26 RegistersCollection = new DoubleWordRegisterCollection(this); 27 DefineRegisters(); 28 pdc = new SAM_PDC(machine, this, (long)Registers.PdcReceivePointer, HandlePdcStatusChange); 29 } 30 ReadDoubleWord(long offset)31 public uint ReadDoubleWord(long offset) 32 { 33 return RegistersCollection.Read(offset); 34 } 35 WriteDoubleWord(long offset, uint value)36 public void WriteDoubleWord(long offset, uint value) 37 { 38 RegistersCollection.Write(offset, value); 39 } 40 DmaByteRead()41 public byte? DmaByteRead() => ReadByteFromBuffer(); 42 public void DmaByteWrite(byte data) => WriteByteToBuffer(data); 43 DmaBlockByteRead(int count)44 public byte[] DmaBlockByteRead(int count) => ReadBuffer(count); 45 DmaBlockByteWrite(byte[] data)46 public void DmaBlockByteWrite(byte[] data) 47 { 48 if(state == State.WriteFinished) 49 { 50 state = State.Write; 51 } 52 WriteBuffer(data); 53 } 54 Reset()55 public override void Reset() 56 { 57 state = State.Idle; 58 delayRxReady = false; 59 rxBuffer.Clear(); 60 txBuffer.Clear(); 61 RegistersCollection.Reset(); 62 selectedPeripheral = FindPeripheral(); 63 pdc.Reset(); 64 UpdateInterrupts(); 65 } 66 67 public GPIO IRQ { get; } = new GPIO(); 68 69 public DoubleWordRegisterCollection RegistersCollection { get; } 70 71 public long Size => 0x128; 72 73 public TransferType DmaReadAccessWidth => TransferType.Byte; 74 public TransferType DmaWriteAccessWidth => TransferType.Byte; 75 DefineRegisters()76 private void DefineRegisters() 77 { 78 Registers.Control.Define(this) 79 .WithFlag(0, out var start, FieldMode.Write, name: "START", 80 changeCallback: (_, value) => { if(value) SendInternalAddress(); }) 81 .WithFlag(1, out var stop, FieldMode.Write, name: "STOP") 82 .WithFlag(2, out masterEnabled, FieldMode.Set, name: "MSEN - Master Mode Enabled") 83 .WithFlag(3, FieldMode.WriteOneToClear, name: "MSDIS - Master Mode Disabled", 84 writeCallback: (_, value) => 85 { 86 if(value) 87 { 88 this.Log(LogLevel.Error, "Tried to disable master mode! Only master mode is supported"); 89 } 90 }) 91 .WithFlag(4, FieldMode.Set, name: "SVEN - Slave Mode Enabled", 92 writeCallback: (_, value) => 93 { 94 if(value) 95 { 96 this.Log(LogLevel.Error, "Tried to enable slave mode! Only master mode is supported"); 97 } 98 }) 99 .WithFlag(5, FieldMode.WriteOneToClear, name: "SVDIS - Slave Mode Disabled") 100 .WithReservedBits(6, 1) 101 .WithFlag(7, FieldMode.Set, writeCallback: (_, value) => { if(value) Reset(); }, name: "SWRST") 102 .WithReservedBits(8, 24) 103 .WithWriteCallback((_, __) => TriggerAction(start.Value, stop.Value)) 104 ; 105 106 Registers.MasterMode.Define(this) 107 .WithReservedBits(0, 8) 108 .WithEnumField(8, 2, out internalAddressSize, name: "IADRSZ - Internal Device Address Size") 109 .WithReservedBits(10, 2) 110 .WithEnumField(12, 1, out readDirection, name: "MREAD - Master Read Direction") 111 .WithReservedBits(13, 3) 112 .WithValueField(16, 7, out deviceAddress, name: "DADR - Device Address") 113 .WithReservedBits(23, 9) 114 .WithChangeCallback((_, __) => 115 { 116 selectedPeripheral = FindPeripheral(); 117 if(selectedPeripheral == null) 118 { 119 this.WarningLog("Selected SPI peripheral is not registered"); 120 } 121 switch(readDirection.Value) 122 { 123 case ReadDirection.MasterWrite: 124 state = State.Write; 125 break; 126 case ReadDirection.MasterRead: 127 state = State.Idle; 128 break; 129 default: 130 throw new Exception("Unreachable"); 131 } 132 }) 133 ; 134 135 Registers.SlaveMode.Define(this) 136 .WithReservedBits(0, 16) 137 .WithTag("SADR - Slave Address", 16, 7) 138 .WithReservedBits(23, 9) 139 ; 140 141 Registers.InternalAddress.Define(this) 142 .WithValueField(0, 24, out internalAddress, name: "IADR - Internal Address") 143 .WithReservedBits(24, 8) 144 ; 145 146 Registers.ClockWaveformGenerator.Define(this) 147 .WithTag("CLDIV - Clock Low Divider", 0, 8) 148 .WithTag("CHDIV - Clock High Divider", 8, 8) 149 .WithTag("CKDIV - Clock Divide", 16, 3) 150 .WithReservedBits(19, 13) 151 ; 152 153 Registers.Status.Define(this) 154 .WithFlag(0, out txCompleted, FieldMode.Read, name: "TXCOMP") 155 .WithFlag(1, FieldMode.Read, name: "RXDRY", 156 valueProviderCallback: _ => 157 { 158 // NOTE: This is a simple delay mechanism for data receive with PDC 159 // it assumes that Status register is read in interrupt handler 160 var value = RxReady && !delayRxReady; 161 delayRxReady = false; 162 return value; 163 }) 164 .WithFlag(2, FieldMode.Read, valueProviderCallback: _ => masterEnabled.Value, name: "TXRDY") 165 .WithFlag(3, FieldMode.Read, valueProviderCallback: _ => false, name: "SVREAD") 166 .WithTaggedFlag("SVACC", 4) 167 .WithTaggedFlag("GACC", 5) 168 .WithTaggedFlag("OVRE", 6) 169 .WithReservedBits(7, 1) 170 .WithFlag(8, out notAcknowledged, FieldMode.Read, name: "NACK") 171 .WithTaggedFlag("ARBLST", 9) 172 .WithTaggedFlag("SCLWS", 10) 173 .WithTaggedFlag("EOSACC", 11) 174 .WithFlag(12, FieldMode.Read, valueProviderCallback: _ => EndOfRxBuffer, name: "ENDRX") 175 .WithFlag(13, FieldMode.Read, valueProviderCallback: _ => EndOfTxBuffer, name: "ENDTX") 176 .WithFlag(14, FieldMode.Read, valueProviderCallback: _ => RxBufferFull, name: "RXBUFF") 177 .WithFlag(15, FieldMode.Read, valueProviderCallback: _ => TxBufferEmpty, name: "TXBUFE") 178 .WithReservedBits(16, 16) 179 ; 180 181 Registers.InterruptEnable.Define(this) 182 .WithFlag(0, FieldMode.Set, writeCallback: (_, value) => { if(value) txCompletedInterruptEnable.Value = true; }, name: "TXCOMP") 183 .WithFlag(1, FieldMode.Set, writeCallback: (_, value) => { if(value) rxDataReadyInterruptEnable.Value = true; }, name: "RXRDY") 184 .WithFlag(2, FieldMode.Set, writeCallback: (_, value) => { if(value) txDataReadyInterruptEnable.Value = true; }, name: "TXRDY") 185 .WithReservedBits(3, 1) 186 .WithFlag(4, FieldMode.Set, writeCallback: (_, value) => { if(value) slaveAccessInterruptEnable.Value = true; }, name: "SVACC") 187 .WithFlag(5, FieldMode.Set, writeCallback: (_, value) => { if(value) generalCallAccessInterruptEnable.Value = true; }, name: "GACC") 188 .WithFlag(6, FieldMode.Set, writeCallback: (_, value) => { if(value) overrunErrorInterruptEnable.Value = true; }, name: "OVRE") 189 .WithReservedBits(7, 1) 190 .WithFlag(8, FieldMode.Set, writeCallback: (_, value) => { if(value) notAcknowledgeInterruptEnable.Value = true; }, name: "NACK") 191 .WithFlag(9, FieldMode.Set, writeCallback: (_, value) => { if(value) arbitrationLostInterruptEnable.Value = true; }, name: "ARBLST") 192 .WithFlag(10, FieldMode.Set, writeCallback: (_, value) => { if(value) clockWaitStateInterruptEnable.Value = true; }, name: "SCL_WS") 193 .WithFlag(11, FieldMode.Set, writeCallback: (_, value) => { if(value) endOfSlaveAccessInterruptEnable.Value = true; }, name: "EOSACC") 194 .WithFlag(12, FieldMode.Set, writeCallback: (_, value) => { if(value) endOfRxBufferInterruptEnable.Value = true; }, name: "ENDRX") 195 .WithFlag(13, FieldMode.Set, writeCallback: (_, value) => { if(value) endOfTxBufferInterruptEnable.Value = true; }, name: "ENDTX") 196 .WithFlag(14, FieldMode.Set, writeCallback: (_, value) => { if(value) rxBufferFullInterruptEnable.Value = true; }, name: "RXBUFF") 197 .WithFlag(15, FieldMode.Set, writeCallback: (_, value) => { if(value) txBufferEmptyInterruptEnable.Value = true; }, name: "TXBUFE") 198 .WithWriteCallback((_, __) => UpdateInterrupts()) 199 ; 200 201 Registers.InterruptDisable.Define(this) 202 .WithFlag(0, FieldMode.WriteOneToClear, writeCallback: (_, value) => { if(value) txCompletedInterruptEnable.Value = false; }, name: "TXCOMP") 203 .WithFlag(1, FieldMode.WriteOneToClear, writeCallback: (_, value) => { if(value) rxDataReadyInterruptEnable.Value = false; }, name: "RXRDY") 204 .WithFlag(2, FieldMode.WriteOneToClear, writeCallback: (_, value) => { if(value) txDataReadyInterruptEnable.Value = false; }, name: "TXRDY") 205 .WithReservedBits(3, 1) 206 .WithFlag(4, FieldMode.WriteOneToClear, writeCallback: (_, value) => { if(value) slaveAccessInterruptEnable.Value = false; }, name: "SVACC") 207 .WithFlag(5, FieldMode.WriteOneToClear, writeCallback: (_, value) => { if(value) generalCallAccessInterruptEnable.Value = false; }, name: "GACC") 208 .WithFlag(6, FieldMode.WriteOneToClear, writeCallback: (_, value) => { if(value) overrunErrorInterruptEnable.Value = false; }, name: "OVRE") 209 .WithReservedBits(7, 1) 210 .WithFlag(8, FieldMode.WriteOneToClear, writeCallback: (_, value) => { if(value) notAcknowledgeInterruptEnable.Value = false; }, name: "NACK") 211 .WithFlag(9, FieldMode.WriteOneToClear, writeCallback: (_, value) => { if(value) arbitrationLostInterruptEnable.Value = false; }, name: "ARBLST") 212 .WithFlag(10, FieldMode.WriteOneToClear, writeCallback: (_, value) => { if(value) clockWaitStateInterruptEnable.Value = false; }, name: "SCL_WS") 213 .WithFlag(11, FieldMode.WriteOneToClear, writeCallback: (_, value) => { if(value) endOfSlaveAccessInterruptEnable.Value = false; }, name: "EOSACC") 214 .WithFlag(12, FieldMode.WriteOneToClear, writeCallback: (_, value) => { if(value) endOfRxBufferInterruptEnable.Value = false; }, name: "ENDRX") 215 .WithFlag(13, FieldMode.WriteOneToClear, writeCallback: (_, value) => { if(value) endOfTxBufferInterruptEnable.Value = false; }, name: "ENDTX") 216 .WithFlag(14, FieldMode.WriteOneToClear, writeCallback: (_, value) => { if(value) rxBufferFullInterruptEnable.Value = false; }, name: "RXBUFF") 217 .WithFlag(15, FieldMode.WriteOneToClear, writeCallback: (_, value) => { if(value) txBufferEmptyInterruptEnable.Value = false; }, name: "TXBUFE") 218 .WithWriteCallback((_, __) => UpdateInterrupts()) 219 ; 220 221 Registers.InterruptMask.Define(this) 222 .WithFlag(0, out txCompletedInterruptEnable, FieldMode.Read, name: "TXCOMP") 223 .WithFlag(1, out rxDataReadyInterruptEnable, FieldMode.Read, name: "RXRDY") 224 .WithFlag(2, out txDataReadyInterruptEnable, FieldMode.Read, name: "TXRDY") 225 .WithReservedBits(3, 1) 226 .WithFlag(4, out slaveAccessInterruptEnable, FieldMode.Read, name: "SVACC") 227 .WithFlag(5, out generalCallAccessInterruptEnable, FieldMode.Read, name: "GACC") 228 .WithFlag(6, out overrunErrorInterruptEnable, FieldMode.Read, name: "OVRE") 229 .WithReservedBits(7, 1) 230 .WithFlag(8, out notAcknowledgeInterruptEnable, FieldMode.Read, name: "NACK") 231 .WithFlag(9, out arbitrationLostInterruptEnable, FieldMode.Read, name: "ARBLST") 232 .WithFlag(10, out clockWaitStateInterruptEnable, FieldMode.Read, name: "SCL_WS") 233 .WithFlag(11, out endOfSlaveAccessInterruptEnable, FieldMode.Read, name: "EOSACC") 234 .WithFlag(12, out endOfRxBufferInterruptEnable, FieldMode.Read, name: "ENDRX") 235 .WithFlag(13, out endOfTxBufferInterruptEnable, FieldMode.Read, name: "ENDTX") 236 .WithFlag(14, out rxBufferFullInterruptEnable, FieldMode.Read, name: "RXBUFF") 237 .WithFlag(15, out txBufferEmptyInterruptEnable, FieldMode.Read, name: "TXBUFE") 238 ; 239 240 Registers.ReceiveHolding.Define(this) 241 .WithValueField(0, 8, FieldMode.Read, name: "RXDATA", 242 valueProviderCallback: _ => 243 { 244 var data = ReadByteFromBuffer(dmaAccess: false) ?? 0x0; 245 246 switch(state) 247 { 248 case State.ReadLastButOne: 249 state = State.ReadLast; 250 break; 251 case State.ReadLast: 252 state = State.ReadFinished; 253 rxBuffer.Clear(); 254 selectedPeripheral?.FinishTransmission(); 255 break; 256 } 257 return data; 258 }) 259 .WithReservedBits(8, 24) 260 .WithReadCallback((_, __) => UpdateInterrupts()) 261 ; 262 263 Registers.TransmitHolding.Define(this) 264 .WithValueField(0, 8, FieldMode.Write, name: "TXDATA", 265 writeCallback: (_, value) => 266 { 267 WriteByteToBuffer((byte)value, dmaAccess: false); 268 if(state == State.WriteLast) 269 { 270 state = State.WriteFinished; 271 FinalizeWrite(); 272 txCompleted.Value = true; 273 selectedPeripheral?.FinishTransmission(); 274 } 275 UpdateInterrupts(); 276 }) 277 .WithReservedBits(8, 24) 278 ; 279 } 280 281 /// <summary> 282 /// Find peripheral from bus based on <see cref="deviceAddress"/> and <see cref="internalAddress"/> 283 /// </summary> 284 /// <returns><see cref="II2CPeripheral"/> when found or null when not found</returns> FindPeripheral()285 private II2CPeripheral FindPeripheral() 286 { 287 slaveAddress = 0; 288 289 // 10-bit addressing 290 if(BitHelper.GetValue(deviceAddress.Value, offset: 2, size: 5) == _10BitAddressingPrefix) 291 { 292 if(internalAddressSize.Value == InternalAddressSize.None) 293 { 294 this.ErrorLog("Decoding 10-bit target address from data is not implemented"); 295 } 296 slaveAddress.ReplaceBits(deviceAddress.Value, width: 2, destinationPosition: 7); 297 slaveAddress.ReplaceBits(internalAddress.Value, width: 8, destinationPosition: 0); 298 } 299 else 300 { 301 slaveAddress = BitHelper.GetValue(deviceAddress.Value, offset: 0, size: 7); 302 } 303 304 this.NoisyLog("Selected slave 0x{0:X}", slaveAddress); 305 return ChildCollection.GetOrDefault((int)slaveAddress); 306 } 307 308 /// <summary> 309 /// Convert <see cref="internalAddress"/> to byte array 310 /// </summary> 311 /// <returns> 312 /// Byte array which length equals <see cref="internalAddressSize"/> or null if it's either 0 or > 3 313 /// </returns> GetInternalAddressBytes()314 private byte[] GetInternalAddressBytes() 315 { 316 if(internalAddressSize.Value == InternalAddressSize.None) 317 { 318 return null; 319 } 320 return BitHelper.GetBytesFromValue(internalAddress.Value, (int)internalAddressSize.Value); 321 } 322 ReadByteFromBuffer(bool dmaAccess = true)323 private byte? ReadByteFromBuffer(bool dmaAccess = true) 324 { 325 return ReadBuffer(1, dmaAccess)?[0]; 326 } 327 ReadBuffer(int count, bool dmaAccess = true)328 private byte[] ReadBuffer(int count, bool dmaAccess = true) 329 { 330 FinalizeWrite(); 331 332 if(dmaAccess && state != State.Read) 333 { 334 return null; 335 } 336 337 if(!ReadMode) 338 { 339 this.WarningLog("Attempted to perform read, but it's not enabled"); 340 return null; 341 } 342 343 EnsureRxDataReady(count); 344 var data = rxBuffer.DequeueRange(count); 345 this.NoisyLog("Reading from slave 0x{0:X}: {1}", slaveAddress, data.ToLazyHexString()); 346 return data; 347 } 348 WriteByteToBuffer(byte value, bool dmaAccess = true)349 private void WriteByteToBuffer(byte value, bool dmaAccess = true) 350 { 351 WriteBuffer(new byte[] { value }, dmaAccess); 352 } 353 WriteBuffer(byte[] data, bool dmaAccess = true)354 private void WriteBuffer(byte[] data, bool dmaAccess = true) 355 { 356 if(!WriteMode) 357 { 358 this.WarningLog("Attempted to perform write{0}, but it's not enabled", dmaAccess ? " via dma" : ""); 359 return; 360 } 361 362 if(selectedPeripheral == null) 363 { 364 notAcknowledged.Value = true; 365 return; 366 } 367 368 if(dmaAccess && txBuffer.Count == 0) 369 { 370 // This is a first write initiated by PDC, 371 // so the internal address is sent as it's start of a new frame 372 SendInternalAddress(); 373 } 374 375 txBuffer.EnqueueRange(data); 376 } 377 FinalizeWrite()378 private void FinalizeWrite() 379 { 380 if(txBuffer.Count == 0) 381 { 382 return; 383 } 384 var data = txBuffer.ToArray(); 385 this.NoisyLog("Writing to slave 0x{0:X}: {1}", slaveAddress, data.ToLazyHexString()); 386 selectedPeripheral.Write(data); 387 txBuffer.Clear(); 388 } 389 EnsureRxDataReady(int count)390 private void EnsureRxDataReady(int count) 391 { 392 if(rxBuffer.Count >= count) 393 { 394 return; 395 } 396 397 IEnumerable<byte> data; 398 if(selectedPeripheral == null) 399 { 400 this.DebugLog("SPI peripheral not connected, reading zeros"); 401 data = Enumerable.Repeat<byte>(0x0, count); 402 } 403 else 404 { 405 data = selectedPeripheral.Read(count); 406 } 407 rxBuffer.EnqueueRange(data); 408 } 409 SendInternalAddress()410 private void SendInternalAddress() 411 { 412 if(selectedPeripheral == null) 413 { 414 notAcknowledged.Value = true; 415 return; 416 } 417 418 var addressBytes = GetInternalAddressBytes(); 419 if(addressBytes != null) 420 { 421 this.NoisyLog("Writing to slave 0x{0:X}: {1}", slaveAddress, addressBytes.ToLazyHexString()); 422 selectedPeripheral.Write(addressBytes); 423 } 424 } 425 HandlePdcStatusChange()426 private void HandlePdcStatusChange() 427 { 428 delayRxReady = EndOfRxBuffer || RxBufferFull; 429 UpdateInterrupts(); 430 } 431 TriggerAction(bool start, bool stop)432 private void TriggerAction(bool start, bool stop) 433 { 434 this.NoisyLog("TWI_CR.START={0}, TWI_CR.STOP={1}, TWI_MMR.MREAD={2}", start, stop, readDirection.Value); 435 if(!start && !stop) 436 { 437 return; 438 } 439 440 if(start) 441 { 442 notAcknowledged.Value = false; 443 txCompleted.Value = false; 444 445 if(selectedPeripheral == null) 446 { 447 this.NoisyLog("No action performed, SPI peripheral not found"); 448 notAcknowledged.Value = true; 449 UpdateInterrupts(); 450 return; 451 } 452 } 453 454 switch(readDirection.Value) 455 { 456 case ReadDirection.MasterWrite: 457 state = stop ? State.WriteLast : State.Write; 458 break; 459 case ReadDirection.MasterRead: 460 if(start && stop) 461 { 462 state = State.ReadLast; 463 } 464 else if(start) 465 { 466 state = State.Read; 467 pdc.TriggerReceiver(); 468 } 469 else 470 { 471 state = State.ReadLastButOne; 472 } 473 break; 474 default: 475 throw new Exception("Unreachable"); 476 } 477 UpdateInterrupts(); 478 } 479 UpdateInterrupts()480 private void UpdateInterrupts() 481 { 482 var state = (txCompletedInterruptEnable.Value && txCompleted.Value) 483 || (rxDataReadyInterruptEnable.Value && RxReady && !delayRxReady) 484 || (txDataReadyInterruptEnable.Value && masterEnabled.Value) 485 || (notAcknowledgeInterruptEnable.Value && notAcknowledged.Value) 486 || (endOfRxBufferInterruptEnable.Value && EndOfRxBuffer) 487 || (endOfTxBufferInterruptEnable.Value && EndOfTxBuffer) 488 || (rxBufferFullInterruptEnable.Value && RxBufferFull) 489 || (txBufferEmptyInterruptEnable.Value && TxBufferEmpty) 490 ; 491 492 this.DebugLog("IRQ {0}", state ? "set" : "unset"); 493 IRQ.Set(state); 494 } 495 496 private bool EndOfRxBuffer => pdc?.EndOfRxBuffer ?? false; 497 private bool EndOfTxBuffer => pdc?.EndOfTxBuffer ?? false; 498 private bool RxBufferFull => pdc?.RxBufferFull ?? false; 499 private bool TxBufferEmpty => pdc?.TxBufferEmpty ?? false; 500 501 private bool RxReady 502 { 503 get 504 { 505 switch(state) 506 { 507 case State.Read: 508 case State.ReadLastButOne: 509 case State.ReadLast: 510 return true; 511 default: 512 return false; 513 } 514 } 515 } 516 517 private bool ReadMode => RxReady; 518 519 private bool WriteMode 520 { 521 get 522 { 523 switch(state) 524 { 525 case State.Write: 526 case State.WriteLast: 527 return true; 528 default: 529 return false; 530 } 531 } 532 } 533 534 private State state; 535 private bool delayRxReady; 536 private ulong slaveAddress; 537 private IFlagRegisterField masterEnabled; 538 private IEnumRegisterField<InternalAddressSize> internalAddressSize; 539 private IEnumRegisterField<ReadDirection> readDirection; 540 private IValueRegisterField deviceAddress; 541 private IValueRegisterField internalAddress; 542 private IFlagRegisterField txCompleted; 543 private IFlagRegisterField notAcknowledged; 544 private IFlagRegisterField txBufferEmptyInterruptEnable; 545 private IFlagRegisterField rxBufferFullInterruptEnable; 546 private IFlagRegisterField endOfTxBufferInterruptEnable; 547 private IFlagRegisterField endOfRxBufferInterruptEnable; 548 private IFlagRegisterField endOfSlaveAccessInterruptEnable; 549 private IFlagRegisterField clockWaitStateInterruptEnable; 550 private IFlagRegisterField arbitrationLostInterruptEnable; 551 private IFlagRegisterField notAcknowledgeInterruptEnable; 552 private IFlagRegisterField overrunErrorInterruptEnable; 553 private IFlagRegisterField generalCallAccessInterruptEnable; 554 private IFlagRegisterField slaveAccessInterruptEnable; 555 private IFlagRegisterField txDataReadyInterruptEnable; 556 private IFlagRegisterField rxDataReadyInterruptEnable; 557 private IFlagRegisterField txCompletedInterruptEnable; 558 559 private II2CPeripheral selectedPeripheral; 560 561 private readonly Queue<byte> rxBuffer = new Queue<byte>(); 562 private readonly Queue<byte> txBuffer = new Queue<byte>(); 563 private readonly SAM_PDC pdc; 564 565 private const ulong _10BitAddressingPrefix = 0x1e; 566 567 private enum State 568 { 569 Idle, 570 Read, 571 ReadLastButOne, 572 ReadLast, 573 ReadFinished, 574 Write, 575 WriteLast, 576 WriteFinished, 577 } 578 579 public enum InternalAddressSize 580 { 581 None = 0, 582 OneByte, 583 TwoByte, 584 ThreeByte 585 } 586 587 public enum ReadDirection 588 { 589 MasterWrite = 0x00, 590 MasterRead = 0x01 591 } 592 593 public enum Registers : uint 594 { 595 Control = 0x00, 596 MasterMode = 0x04, 597 SlaveMode = 0x08, 598 InternalAddress = 0x0C, 599 ClockWaveformGenerator = 0x10, 600 Reserved1 = 0x14, 601 Reserved2 = 0x1C, 602 Status = 0x20, 603 InterruptEnable = 0x24, 604 InterruptDisable = 0x28, 605 InterruptMask = 0x2C, 606 ReceiveHolding = 0x30, 607 TransmitHolding = 0x34, 608 PdcReceivePointer = 0x100, 609 PdcReceiveCounter = 0x104, 610 PdcTransmitPointer = 0x108, 611 PdcTransmitCounter = 0x10C, 612 PdcReceiveNextPointer = 0x110, 613 PdcReceiveNextCounter = 0x114, 614 PdcTransmitNextPointer = 0x118, 615 PdcTransmitNextCounter = 0x11C, 616 PdcTransferControl = 0x120, 617 PdcTransferStatus = 0x124, 618 } 619 } 620 } 621