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 using System; 8 using System.Collections.Generic; 9 using System.Linq; 10 using Antmicro.Renode.Core; 11 using Antmicro.Renode.Core.Structure.Registers; 12 using Antmicro.Renode.Core.Structure; 13 using Antmicro.Renode.Debugging; 14 using Antmicro.Renode.Exceptions; 15 using Antmicro.Renode.Logging; 16 using Antmicro.Renode.Peripherals.Bus; 17 using Antmicro.Renode.Peripherals.I2C; 18 using Antmicro.Renode.Peripherals.SPI; 19 using Antmicro.Renode.Peripherals.UART; 20 using Antmicro.Renode.Time; 21 using Antmicro.Renode.Utilities; 22 using Antmicro.Migrant; 23 24 namespace Antmicro.Renode.Peripherals.SCI 25 { 26 // Due to unusual register offsets we cannot use address translations 27 public class RenesasRA6M5_SCI : NullRegistrationPointPeripheralContainer<ISPIPeripheral>, IUART, IWordPeripheral, IBytePeripheral, IProvidesRegisterCollection<WordRegisterCollection>, IKnownSize, 28 IPeripheralContainer<IUART, NullRegistrationPoint>, IPeripheralContainer<II2CPeripheral, NumberRegistrationPoint<int>> 29 { RenesasRA6M5_SCI(IMachine machine, ulong frequency, bool enableManchesterMode, bool enableFIFO, bool fullModel = true)30 public RenesasRA6M5_SCI(IMachine machine, ulong frequency, bool enableManchesterMode, bool enableFIFO, bool fullModel = true) : base(machine) 31 { 32 this.machine = machine; 33 this.frequency = frequency; 34 i2cContainer = new SimpleContainerHelper<II2CPeripheral>(machine, this); 35 ReceiveIRQ = new GPIO(); 36 TransmitIRQ = new GPIO(); 37 TransmitEndIRQ = new GPIO(); 38 receiveQueue = new Queue<ushort>(); 39 iicTransmitQueue = new Queue<byte>(); 40 RegistersCollection = new WordRegisterCollection(this); 41 42 DefineRegisters(enableManchesterMode, enableFIFO, fullModel); 43 Size = fullModel ? 0x100 : 0x20; 44 Reset(); 45 } 46 ReadWord(long offset)47 public ushort ReadWord(long offset) 48 { 49 return RegistersCollection.Read(offset); 50 } 51 WriteWord(long offset, ushort value)52 public void WriteWord(long offset, ushort value) 53 { 54 RegistersCollection.Write(offset, value); 55 } 56 ReadByte(long offset)57 public byte ReadByte(long offset) 58 { 59 return (byte)RegistersCollection.Read(offset); 60 } 61 WriteByte(long offset, byte value)62 public void WriteByte(long offset, byte value) 63 { 64 RegistersCollection.Write(offset, value); 65 } 66 WriteChar(byte value)67 public void WriteChar(byte value) 68 { 69 receiveQueue.Enqueue(value); 70 UpdateInterrupts(); 71 } 72 Reset()73 public override void Reset() 74 { 75 fifoMode = false; 76 manchesterMode = false; 77 receiveQueue.Clear(); 78 iicTransmitQueue.Clear(); 79 80 ReceiveIRQ.Unset(); 81 TransmitIRQ.Unset(); 82 TransmitEndIRQ.Unset(); 83 RegistersCollection.Reset(); 84 peripheralMode = PeripheralMode.UART; 85 } 86 Register(IUART peripheral, NullRegistrationPoint registrationPoint)87 public void Register(IUART peripheral, NullRegistrationPoint registrationPoint) 88 { 89 if(registeredUartPeripheral != null) 90 { 91 throw new RegistrationException($"UART peripheral alredy registered"); 92 } 93 94 machine.RegisterAsAChildOf(this, peripheral, registrationPoint); 95 96 CharReceived += peripheral.WriteChar; 97 peripheral.CharReceived += WriteChar; 98 99 registeredUartPeripheral = peripheral; 100 } 101 Unregister(IUART peripheral)102 public void Unregister(IUART peripheral) 103 { 104 CharReceived -= peripheral.WriteChar; 105 peripheral.CharReceived -= WriteChar; 106 107 registeredUartPeripheral = null; 108 } 109 GetRegistrationPoints(IUART peripheral)110 public IEnumerable<NullRegistrationPoint> GetRegistrationPoints(IUART peripheral) 111 { 112 return registeredUartPeripheral != null ? 113 new[] { NullRegistrationPoint.Instance } : 114 Enumerable.Empty<NullRegistrationPoint>(); 115 } 116 Register(II2CPeripheral peripheral, NumberRegistrationPoint<int> registrationPoint)117 public virtual void Register(II2CPeripheral peripheral, NumberRegistrationPoint<int> registrationPoint) => i2cContainer.Register(peripheral, registrationPoint); 118 Unregister(II2CPeripheral peripheral)119 public virtual void Unregister(II2CPeripheral peripheral) => i2cContainer.Unregister(peripheral); 120 121 public IEnumerable<NumberRegistrationPoint<int>> GetRegistrationPoints(II2CPeripheral peripheral) => i2cContainer.GetRegistrationPoints(peripheral); 122 123 public bool IsDataReadyFIFO { get => (ulong)receiveQueue.Count < receiveFIFOTriggerCount.Value; } 124 125 public bool IsReceiveFIFOFull { get => (ulong)receiveQueue.Count >= receiveFIFOTriggerCount.Value; } 126 127 // This is used in the non-FIFO mode where there is room just for a single byte, hence "full" means non-empty queue 128 public bool IsReceiveDataFull { get => receiveQueue.Count > 0; } 129 130 public WordRegisterCollection RegistersCollection { get; } 131 132 public GPIO ReceiveIRQ { get; } 133 134 public GPIO TransmitIRQ { get; } 135 136 public GPIO TransmitEndIRQ { get; } 137 138 public uint BaudRate 139 { 140 get 141 { 142 var n = clockSource.Value == 0 ? 1UL : 2UL << (2 * (ushort)clockSource.Value - 1); 143 return (uint)(frequency / (64UL * n * bitRate.Value)) - 1; 144 } 145 } 146 147 public Bits StopBits => hasTwoStopBits.Value ? Bits.Two : Bits.One; 148 149 public Parity ParityBit => parityEnabled.Value ? parityBit : Parity.None; 150 151 public long Size { get; } 152 153 IEnumerable<IRegistered<IUART, NullRegistrationPoint>> IPeripheralContainer<IUART, NullRegistrationPoint>.Children 154 { 155 get => registeredUartPeripheral != null ? 156 new [] { Registered.Create(registeredUartPeripheral, NullRegistrationPoint.Instance) } : 157 Enumerable.Empty<IRegistered<IUART, NullRegistrationPoint>>(); 158 } 159 160 IEnumerable<IRegistered<II2CPeripheral, NumberRegistrationPoint<int>>> IPeripheralContainer<II2CPeripheral, NumberRegistrationPoint<int>>.Children => 161 i2cContainer.Children; 162 163 [field: Transient] 164 public event Action<byte> CharReceived; 165 UpdateInterrupts()166 private void UpdateInterrupts() 167 { 168 if(peripheralMode == PeripheralMode.IIC) 169 { 170 UpdateInterruptsInIICMode(); 171 return; 172 } 173 var rxState = receiveInterruptEnabled.Value && (fifoMode ? IsReceiveFIFOFull : IsReceiveDataFull); 174 var txState = transmitInterruptEnabled.Value && (fifoMode ? transmitFIFOEmpty.Value : true); 175 var teState = transmitEndInterruptEnabled.Value; 176 177 this.DebugLog("ReceiveIRQ: {0}, TransmitIRQ: {1}, TransmitEndIRQ: {2}.", rxState ? "set" : "unset", txState ? "set" : "unset", teState ? "set" : "unset"); 178 if(rxState) 179 { 180 ReceiveIRQ.Blink(); 181 } 182 if(txState) 183 { 184 TransmitIRQ.Blink(); 185 } 186 if(teState) 187 { 188 TransmitEndIRQ.Blink(); 189 } 190 } 191 UpdateInterruptsInIICMode()192 private void UpdateInterruptsInIICMode() 193 { 194 // This does not update the Transmit/Receive interrupts, as there are not status flags in this mode and they are expected just to blink 195 bool teState = transmitEndInterruptEnabled.Value && conditionCompletedFlag.Value; 196 this.DebugLog("TransmitEndIRQ: {0}.", teState ? "set" : "unset"); 197 198 TransmitEndIRQ.Set(teState); 199 } 200 BlinkTxIRQ()201 private void BlinkTxIRQ() 202 { 203 DebugHelper.Assert(peripheralMode == PeripheralMode.IIC); 204 205 if(transmitInterruptEnabled.Value) 206 { 207 TransmitIRQ.Blink(); 208 } 209 } 210 FlushIICTransmitQueue()211 private void FlushIICTransmitQueue() 212 { 213 if(iicTransmitQueue.Count != 0) 214 { 215 selectedIICSlave.Write(iicTransmitQueue.ToArray()); 216 iicTransmitQueue.Clear(); 217 } 218 } 219 EmulateIICStartStopCondition(IICCondition condition)220 private void EmulateIICStartStopCondition(IICCondition condition) 221 { 222 conditionCompletedFlag.Value = true; 223 transmitEnd.Value = true; 224 if(condition == IICCondition.Stop) 225 { 226 if(selectedIICSlave == null) 227 { 228 this.WarningLog("No slave selected. This condition will have no effect"); 229 return; 230 } 231 232 switch(iicDirection) 233 { 234 case IICTransactionDirection.Write: 235 FlushIICTransmitQueue(); 236 break; 237 case IICTransactionDirection.Read: 238 receiveQueue.Clear(); 239 break; 240 default: 241 throw new ArgumentException("Unknown IIC direction"); 242 } 243 selectedIICSlave.FinishTransmission(); 244 } 245 else if(condition == IICCondition.Restart) 246 { 247 //Flush the register address 248 FlushIICTransmitQueue(); 249 } 250 251 iicState = IICState.Idle; 252 iicDirection = IICTransactionDirection.Unset; 253 selectedIICSlave = null; 254 UpdateInterruptsInIICMode(); 255 } 256 SetPeripheralMode()257 private void SetPeripheralMode() 258 { 259 if(smartCardMode.Value) 260 { 261 peripheralMode = PeripheralMode.SmartCardInterface; 262 if(i2cMode.Value) 263 { 264 this.Log(LogLevel.Warning, 265 "The IICM flag in the {0} register (SIMR1) should be unset for Smart Card Interface mode; it's set", 266 nameof(Registers.IICMode1) 267 ); 268 } 269 return; 270 } 271 272 if(i2cMode.Value) 273 { 274 peripheralMode = PeripheralMode.IIC; 275 if(nonSmartCommunicationMode.Value != CommunicationMode.AsynchOrSimpleIIC) 276 { 277 this.Log(LogLevel.Warning, 278 "The CM flag in the {0} register (SMR) should be unset ({1}) for Simple I2C mode; it's set ({2})", 279 nameof(Registers.SerialModeNonSmartCard), CommunicationMode.AsynchOrSimpleIIC, CommunicationMode.SynchOrSimpleSPI 280 ); 281 } 282 283 if(dataTransferDirection.Value != DataTransferDirection.MSBFirst) 284 { 285 this.Log(LogLevel.Warning, 286 "The SDIR flag in the {0} should be set ({1}) for Simple I2Cmode; it's unset ({2})", 287 nameof(Registers.SmartCardMode), DataTransferDirection.MSBFirst, DataTransferDirection.LSBFirst 288 ); 289 } 290 return; 291 } 292 293 switch(nonSmartCommunicationMode.Value) 294 { 295 case CommunicationMode.AsynchOrSimpleIIC: 296 if(i2cContainer.ChildCollection.Count != 0) 297 { 298 peripheralMode = PeripheralMode.IIC; 299 return; 300 } 301 break; 302 case CommunicationMode.SynchOrSimpleSPI: 303 if(RegisteredPeripheral != null) 304 { 305 peripheralMode = PeripheralMode.SPI; 306 return; 307 } 308 break; 309 default: 310 break; 311 } 312 peripheralMode = PeripheralMode.UART; 313 } 314 DefineRegisters(bool enableManchesterMode, bool enableFIFO, bool fullModel)315 private void DefineRegisters(bool enableManchesterMode, bool enableFIFO, bool fullModel) 316 { 317 // Non-Smart Card Mode 318 Registers.SerialModeNonSmartCard.DefineConditional(this, () => !smartCardMode.Value) 319 .WithValueField(0, 2, out clockSource, name: "CKS") 320 .WithTaggedFlag("MP", 2) 321 .WithFlag(3, out hasTwoStopBits, name: "STOP") 322 .WithFlag(4, name: "PM", 323 valueProviderCallback: _ => parityBit == Parity.Odd, 324 writeCallback: (_, value) => parityBit = value ? Parity.Odd : Parity.Even) 325 .WithFlag(5, out parityEnabled, name: "PE") 326 .WithTaggedFlag("CHR", 6) 327 .WithEnumField<WordRegister, CommunicationMode>(7, 1, out nonSmartCommunicationMode, 328 writeCallback: (_, __) => SetPeripheralMode(), name: "CM") 329 .WithReservedBits(8, 8); 330 331 // Smart Card Mode 332 Registers.SerialModeSmartCard.DefineConditional(this, () => smartCardMode.Value) 333 .WithTag("CKS", 0, 2) 334 .WithTag("BCP", 2, 2) 335 .WithTag("PM", 4, 1) 336 .WithTag("PE", 5, 1) 337 .WithTag("BLK", 6, 1) 338 .WithTag("GM", 7, 1) 339 .WithReservedBits(8, 8); 340 341 Registers.BitRate.Define(this, 0xff) 342 .WithValueField(0, 8, out bitRate, 343 writeCallback: (oldVal, newVal) => bitRate.Value = (!transmitEnabled.Value && !receiveEnabled.Value) ? newVal : oldVal, 344 name: "BRR") 345 .WithReservedBits(8, 8); 346 347 // Non-Smart Card Mode 348 Registers.SerialControlNonSmartCard.DefineConditional(this, () => !smartCardMode.Value) 349 .WithTag("CKE", 0, 2) 350 .WithFlag(2, out transmitEndInterruptEnabled, name: "TEIE") 351 .WithTaggedFlag("MPIE", 3) 352 .WithFlag(4, out receiveEnabled, name: "RE") 353 .WithFlag(5, out transmitEnabled, name: "TE") 354 .WithFlag(6, out receiveInterruptEnabled, name: "RIE") 355 .WithFlag(7, out transmitInterruptEnabled, name: "TIE") 356 .WithReservedBits(8, 8) 357 .WithChangeCallback((_, __) => 358 { 359 // The documentation states that the TXI interrupt should be fired when both TE and TIE are set 360 // with a single write operation. On the hardware however it takes some time to actually do that. 361 // The delay mechanism introduced below will prevent Renode from activating the interrupt too soon, 362 // because in some cases interrupts could be handled in the wrong order. 363 if(transmitEnabled.Value && transmitInterruptEnabled.Value) 364 { 365 machine.ScheduleAction(TimeInterval.FromMilliseconds(InterruptDelay), ___ => UpdateInterrupts()); 366 return; 367 } 368 UpdateInterrupts(); 369 }); 370 371 // Smart Card Mode 372 Registers.SerialControlSmartCard.DefineConditional(this, () => smartCardMode.Value) 373 .WithTag("CKS", 0, 2) 374 .WithTag("TEIE", 2, 1) 375 .WithTag("MPIE", 3, 1) 376 .WithTag("RE", 4, 1) 377 .WithTag("TE", 5, 1) 378 .WithTag("RIE", 6, 1) 379 .WithTag("TIE", 7, 1) 380 .WithReservedBits(8, 8); 381 382 Registers.TransmitData.Define(this) 383 .WithValueField(0, 8, FieldMode.Write, name: "TDR", 384 writeCallback: (_, value) => 385 { 386 if(!transmitEnabled.Value) 387 { 388 this.Log(LogLevel.Warning, "Transmission is not enabled, ignoring byte 0x{0:X}", value); 389 return; 390 } 391 switch(peripheralMode) { 392 case PeripheralMode.UART: 393 TransmitUARTData((byte)value); 394 break; 395 case PeripheralMode.IIC: 396 TransmitIICData((byte)value); 397 // No need to update the interrupts - in IIC mode we just blink the Tx interrupt 398 return; 399 case PeripheralMode.SPI: 400 TransmitSPIData((byte)value); 401 break; 402 default: 403 throw new Exception($"Unknown peripheral mode {peripheralMode}"); 404 } 405 UpdateInterrupts(); 406 }) 407 .WithReservedBits(8, 8); 408 409 // Non-Smart Card, Non-FIFO, Non-Manchester 410 Registers.SerialStatusNonSmartCardNonFIFO.DefineConditional(this, () => !smartCardMode.Value && !fifoMode && !manchesterMode, 0x84) 411 .WithTaggedFlag("MPBT", 0) 412 .WithTaggedFlag("MPB", 1) 413 .WithFlag(2, out transmitEnd, FieldMode.Read, name: "TEND") 414 .WithTaggedFlag("PER", 3) 415 .WithTaggedFlag("FER", 4) 416 .WithTaggedFlag("ORER", 5) 417 .WithFlag(6, FieldMode.Read, valueProviderCallback: _ => IsReceiveDataFull, name: "RDRF") 418 .WithFlag(7, FieldMode.Read, valueProviderCallback: _ => true, name: "TDRE") 419 .WithReservedBits(8, 8) 420 .WithChangeCallback((_, __) => UpdateInterrupts()); 421 422 if(enableFIFO) 423 { 424 // Non-Smart Card, FIFO, Non-manchester 425 Registers.SerialStatusNonSmartCardFIFO.DefineConditional(this, () => !smartCardMode.Value && fifoMode && !manchesterMode, 0x84) 426 .WithFlag(0, FieldMode.Read, valueProviderCallback: _ => IsDataReadyFIFO, name: "DR") 427 .WithReservedBits(1, 1) 428 .WithFlag(2, FieldMode.Read, valueProviderCallback: _ => true, name: "TEND") 429 .WithTaggedFlag("PER", 3) 430 .WithTaggedFlag("FER", 4) 431 .WithTaggedFlag("ORER", 5) 432 .WithFlag(6, FieldMode.Read, valueProviderCallback: _ => IsReceiveFIFOFull, name: "RDF") 433 .WithFlag(7, out transmitFIFOEmpty, FieldMode.Read | FieldMode.WriteZeroToClear, name: "TDFE") 434 .WithReservedBits(8, 8); 435 } 436 437 // Smart Card, Non-manchester 438 Registers.SerialStatusSmartCard.DefineConditional(this, () => smartCardMode.Value && !manchesterMode, 0x84) 439 .WithTaggedFlag("MPBT", 0) 440 .WithTaggedFlag("MPB", 1) 441 .WithTaggedFlag("TEND", 2) 442 .WithTaggedFlag("PER", 3) 443 .WithTaggedFlag("ERS", 4) 444 .WithTaggedFlag("ORER", 5) 445 .WithTaggedFlag("RDRF", 6) 446 .WithTaggedFlag("TDRE", 7) 447 .WithReservedBits(8, 8); 448 449 // Non-Smart Card, Manchester 450 Registers.SerialStatusManchesterMode.DefineConditional(this, () => !smartCardMode.Value && manchesterMode, 0x84) 451 .WithTaggedFlag("MER", 0) 452 .WithTaggedFlag("MPB", 1) 453 .WithTaggedFlag("TEND", 2) 454 .WithTaggedFlag("PER", 3) 455 .WithTaggedFlag("FER", 4) 456 .WithTaggedFlag("ORER", 5) 457 .WithTaggedFlag("RDRF", 6) 458 .WithTaggedFlag("TDRE", 7) 459 .WithReservedBits(8, 8); 460 461 Registers.ReceiveData.Define(this) 462 .WithValueField(0, 8, FieldMode.Read, name: "RDR", 463 valueProviderCallback: _ => 464 { 465 if(peripheralMode == PeripheralMode.IIC) 466 { 467 if(iicState != IICState.InTransaction) 468 { 469 this.WarningLog("Trying to read the received data in the wrong state"); 470 } 471 BlinkTxIRQ(); 472 return TryReadFromIICSlave(); 473 } 474 475 if(!receiveQueue.TryDequeue(out var result)) 476 { 477 this.Log(LogLevel.Warning, "Queue is empty, returning 0."); 478 return 0; 479 } 480 UpdateInterrupts(); 481 return result; 482 }) 483 .WithReservedBits(8, 8); 484 485 Registers.SmartCardMode.Define(this, 0xf2) 486 .WithFlag(0, out smartCardMode, name: "SMIF") 487 .WithReservedBits(1, 1) 488 .WithTaggedFlag("SINV", 2) 489 .WithEnumField(3, 1, out dataTransferDirection, name: "SDIR") 490 .WithTaggedFlag("CHR1", 4) 491 .WithReservedBits(5, 2) 492 .WithTaggedFlag("BCP2", 7) 493 .WithReservedBits(8, 8) 494 .WithChangeCallback((_, __) => SetPeripheralMode()); 495 496 Registers.SerialExtendedMode.Define(this) 497 .WithTaggedFlag("ACS0", 0) 498 .WithTaggedFlag("PADIS", 1) 499 .WithTaggedFlag("BRME", 2) 500 .WithTaggedFlag("ABCSE", 3) 501 .WithTaggedFlag("ABCS", 4) 502 .WithTaggedFlag("NFEN", 5) 503 .WithTaggedFlag("BGDM", 6) 504 .WithTaggedFlag("RXDESEL", 7) 505 .WithReservedBits(8, 8); 506 507 Registers.NoiseFilterSetting.Define(this) 508 .WithTag("NFCS", 0, 3) 509 .WithReservedBits(3, 13); 510 511 Registers.IICMode1.Define(this) 512 .WithFlag(0, out i2cMode, changeCallback: (_, __) => SetPeripheralMode(), name: "IICM") 513 .WithReservedBits(1, 2) 514 .WithTag("IICDL", 3, 5) 515 .WithReservedBits(8, 8); 516 517 Registers.IICMode2.Define(this) 518 .WithTag("IICINTM", 0, 1) 519 .WithTaggedFlag("IICCSC", 1) 520 .WithReservedBits(2, 3) 521 .WithFlag(5, writeCallback: (_, val) => { if(val) BlinkTxIRQ(); }, name:"IICACKT") 522 .WithReservedBits(6, 10); 523 524 Registers.IICMode3.Define(this) 525 .WithFlag(0, FieldMode.WriteOneToClear, writeCallback: (_, val) => 526 { 527 if(val) 528 { 529 this.DebugLog("Start Condition Requested!"); 530 EmulateIICStartStopCondition(IICCondition.Start); 531 } 532 }, name: "IICSTAREQ") 533 .WithFlag(1, FieldMode.WriteOneToClear, writeCallback: (_, val) => 534 { 535 if(val) 536 { 537 this.DebugLog("Restart Condition Requested!"); 538 EmulateIICStartStopCondition(IICCondition.Restart); 539 } 540 }, name: "IICRSTAREQ") 541 .WithFlag(2, FieldMode.WriteOneToClear, writeCallback: (_, val) => 542 { 543 if(val) 544 { 545 this.DebugLog("Stop Condition Requested!"); 546 EmulateIICStartStopCondition(IICCondition.Stop); 547 } 548 }, name: "IICSTPREQ") 549 .WithFlag(3, out conditionCompletedFlag, FieldMode.WriteZeroToClear,name: "IICSTIF") 550 .WithValueField(4, 2, name: "IICSDAS") 551 .WithValueField(6, 2, name: "IICSCLS") 552 .WithReservedBits(8, 8) 553 .WithWriteCallback((_, val) => 554 { 555 var conditionRequestBits = val & 0b111; 556 if(conditionRequestBits != 0 && ((conditionRequestBits & (conditionRequestBits - 1)) != 0)) 557 { 558 this.WarningLog("More than one IIC condition requested at the same register acces"); 559 } 560 else if(conditionRequestBits == 0) 561 { 562 // conditionCompletedFlag being zeroed 563 UpdateInterruptsInIICMode(); 564 } 565 }); 566 567 Registers.IICStatus.Define(this) 568 .WithTaggedFlag("IICACKR", 0) 569 .WithReservedBits(1, 7) 570 .WithReservedBits(8, 8); 571 572 Registers.SPIMode.Define(this) 573 .WithTaggedFlag("SSE", 0) 574 .WithTaggedFlag("CTSE", 1) 575 .WithTaggedFlag("MSS", 2) 576 .WithTaggedFlag("CTSPEN", 3) 577 .WithTaggedFlag("MFF", 4) 578 .WithReservedBits(5, 1) 579 .WithTaggedFlag("CKPOL", 6) 580 .WithTaggedFlag("CKPH", 7) 581 .WithReservedBits(8, 8); 582 583 Registers.TransmitDataNonManchesterMode.DefineConditional(this, () => !manchesterMode && !fifoMode, 0xff) 584 .WithTag("TDAT", 0, 9) 585 .WithReservedBits(9, 7); 586 587 Registers.TransmitDataManchesterMode.DefineConditional(this, () => manchesterMode && !fifoMode, 0xff) 588 .WithTag("TDAT", 0, 9) 589 .WithTaggedFlag("MPBT", 9) 590 .WithReservedBits(10, 2) 591 .WithTaggedFlag("TSYNC", 12) 592 .WithReservedBits(13, 3); 593 594 if(enableFIFO) 595 { 596 // TransmitFIFODataLowByte (below) is an 8-bits wide window of this register 597 Registers.TransmitFIFOData.DefineConditional(this, () => fifoMode, 0xff) 598 .WithValueField(0, 9, FieldMode.Write, name: "TDAT", 599 writeCallback: (_, val) => 600 { 601 TransmitUARTData((byte)(val >> 8)); 602 TransmitUARTData((byte)val); 603 transmitFIFOEmpty.Value = true; 604 UpdateInterrupts(); 605 }) 606 .WithTaggedFlag("MPBT", 9) 607 .WithReservedBits(10, 6); 608 609 // this is the upper 8-bits of transmitFIFOData register 610 Registers.TransmitFIFODataLowByte.DefineConditional(this, () => fifoMode, 0xff) 611 .WithValueField(0, 8, FieldMode.Write, name: "TDATL", 612 writeCallback: (_, val) => 613 { 614 TransmitUARTData((byte)val); 615 transmitFIFOEmpty.Value = true; 616 UpdateInterrupts(); 617 }) 618 .WithReservedBits(9, 7); 619 } 620 621 Registers.ReceiveDataNonManchesterMode.DefineConditional(this, () => !manchesterMode && !fifoMode) 622 .WithTag("RDAT", 0, 9) 623 .WithReservedBits(9, 7); 624 625 Registers.ReceiveDataManchesterMode.DefineConditional(this, () => manchesterMode && !fifoMode) 626 .WithReservedBits(10, 2) 627 .WithTaggedFlag("RSYNC", 12) 628 .WithReservedBits(13, 3); 629 630 if(enableFIFO) 631 { 632 Registers.ReceiveFIFOData.DefineConditional(this, () => fifoMode) 633 .WithValueField(0, 9, FieldMode.Read, name: "RDAT", 634 valueProviderCallback: _ => 635 { 636 if(!receiveQueue.TryDequeue(out var result)) 637 { 638 this.Log(LogLevel.Warning, "Queue is empty, returning 0."); 639 return 0; 640 } 641 UpdateInterrupts(); 642 return result; 643 }) 644 .WithTaggedFlag("MPB", 9) 645 .WithFlag(10, FieldMode.Read, valueProviderCallback: _ => IsDataReadyFIFO, name: "DR") 646 .WithTaggedFlag("PER", 11) 647 .WithTaggedFlag("FER", 12) 648 .WithTaggedFlag("ORER", 13) 649 .WithFlag(14, FieldMode.Read, valueProviderCallback: _ => IsReceiveFIFOFull, name: "RDF") 650 .WithReservedBits(15, 1); 651 } 652 653 Registers.ModulationDuty.Define(this, 0xff) 654 .WithTag("MDDR", 0, 8) 655 .WithReservedBits(8, 8); 656 657 Registers.DataCompareMatchControl.Define(this, 0x40) 658 .WithTaggedFlag("DCMF", 0) 659 .WithReservedBits(1, 2) 660 .WithTaggedFlag("DPER", 3) 661 .WithTaggedFlag("DFER", 4) 662 .WithReservedBits(5, 1) 663 .WithTaggedFlag("IDSEL", 6) 664 .WithTaggedFlag("DCME", 7) 665 .WithReservedBits(8, 8); 666 667 if(enableFIFO) 668 { 669 Registers.FIFOControl.Define(this, 0xF800) 670 .WithFlag(0, name: "FM", 671 writeCallback: (_, val) => fifoMode = val, 672 valueProviderCallback: _ => fifoMode) 673 .WithFlag(1, FieldMode.Read | FieldMode.WriteOneToClear, name: "RFRST", 674 writeCallback: (_, __) => 675 { 676 if(fifoMode) 677 { 678 receiveQueue.Clear(); 679 } 680 }) 681 .WithTaggedFlag("TFRST", 2) 682 .WithTaggedFlag("DRES", 3) 683 .WithTaggedFlag("TTRG", 4) 684 .WithValueField(8, 4, out receiveFIFOTriggerCount, name: "RTRG") 685 .WithTag("RSTRG", 12, 4); 686 687 Registers.FIFODataCount.Define(this) 688 .WithValueField(0, 5, FieldMode.Read, name: "R", 689 valueProviderCallback: _ => (ulong)receiveQueue.Count >= MaxFIFOSize ? MaxFIFOSize : (ulong)receiveQueue.Count) 690 .WithReservedBits(5, 3) 691 .WithTag("T", 8, 5) 692 .WithReservedBits(13, 3); 693 } 694 695 Registers.LineStatus.Define(this) 696 .WithTaggedFlag("ORER", 0) 697 .WithReservedBits(1, 1) 698 .WithTag("FNUM", 2, 5) 699 .WithReservedBits(7, 1) 700 .WithTag("PNUM", 8, 5) 701 .WithReservedBits(13, 3); 702 703 Registers.CompareMatchData.Define(this) 704 .WithTag("CMPD", 0, 9) 705 .WithReservedBits(9, 7); 706 707 Registers.SerialPort.Define(this, 0x03) 708 .WithTaggedFlag("RXDMON", 0) 709 .WithTaggedFlag("SPB2DT", 1) 710 .WithTaggedFlag("SPB2IO", 2) 711 .WithReservedBits(3, 1) 712 .WithTaggedFlag("RINV", 4) 713 .WithTaggedFlag("TINV", 5) 714 .WithTaggedFlag("ASEN", 6) 715 .WithTaggedFlag("ATEN", 7) 716 .WithReservedBits(8, 8); 717 718 Registers.AdjustmentCommunicationTiming.Define(this) 719 .WithTag("AST", 0, 3) 720 .WithTaggedFlag("AJD", 3) 721 .WithTag("ATT", 4, 3) 722 .WithTaggedFlag("AET", 7) 723 .WithReservedBits(8, 8); 724 725 if(!fullModel) 726 { 727 return; 728 } 729 730 if(enableManchesterMode) 731 { 732 Registers.ManchesterMode.Define(this) 733 .WithTag("RMPOL", 0, 1) 734 .WithTag("TMPOL", 1, 1) 735 .WithTag("ERTEN", 2, 1) 736 .WithReservedBits(3, 1) 737 .WithTag("SYNVAL", 4, 1) 738 .WithTag("SYNSEL", 5, 1) 739 .WithTag("SBSEL", 6, 1) 740 .WithFlag(7, name: "MANEN", 741 writeCallback: (_, val) => manchesterMode = val, 742 valueProviderCallback: _ => manchesterMode) 743 .WithReservedBits(8, 8); 744 745 Registers.TransmitManchesterPrefaceSetting.Define(this) 746 .WithTag("TPLEN", 0, 3) 747 .WithTag("TPPAT", 4, 2) 748 .WithReservedBits(6, 10); 749 750 Registers.ReceiveManchesterPrefaceSetting.Define(this) 751 .WithTag("RPLEN", 0, 3) 752 .WithTag("RPPAT", 4, 2) 753 .WithReservedBits(6, 10); 754 755 Registers.ManchesterExtendedErrorStatus.Define(this) 756 .WithTag("PFER", 0, 1) 757 .WithTag("SYER", 1, 1) 758 .WithTag("SBER", 2, 1) 759 .WithReservedBits(3, 13); 760 761 Registers.ManchesterExtendedErrorControl.Define(this) 762 .WithTag("PFEREN", 0, 1) 763 .WithTag("SYEREN", 1, 1) 764 .WithTag("SBEREN", 2, 1) 765 .WithReservedBits(3, 13); 766 } 767 else 768 { 769 Registers.ExtendedSerialModuleEnable.Define(this) 770 .WithReservedBits(1, 7) 771 .WithTag("ESME", 0, 1) 772 .WithReservedBits(8, 8); 773 774 Registers.Control1.Define(this) 775 .WithTag("PIBS", 5, 3) 776 .WithTag("PIBE", 4, 1) 777 .WithTag("CF1DS", 2, 2) 778 .WithTag("CF0RE", 1, 1) 779 .WithTag("BFE", 0, 1) 780 .WithReservedBits(8, 8); 781 782 Registers.Control2.Define(this) 783 .WithTag("RTS", 6, 2) 784 .WithTag("BSSS", 4, 2) 785 .WithReservedBits(3, 1) 786 .WithTag("DFCS", 0, 3) 787 .WithReservedBits(8, 8); 788 789 Registers.Control3.Define(this) 790 .WithReservedBits(1, 7) 791 .WithTag("SDST", 0, 1) 792 .WithReservedBits(8, 8); 793 794 Registers.PortControl.Define(this) 795 .WithReservedBits(5, 3) 796 .WithTag("SHARPS", 4, 1) 797 .WithReservedBits(2, 2) 798 .WithTag("RXDXPS", 1, 1) 799 .WithTag("TXDXPS", 0, 1) 800 .WithReservedBits(8, 8); 801 } 802 803 Registers.Control0.Define(this) 804 .WithReservedBits(4, 4) 805 .WithTag("BRME", 3, 1) 806 .WithTag("RXDSF", 2, 1) 807 .WithTag("SFSF", 1, 1) 808 .WithReservedBits(0, 1) 809 .WithReservedBits(8, 8); 810 811 Registers.InterruptControl.Define(this) 812 .WithReservedBits(6, 2) 813 .WithTag("AEDIE", 5, 1) 814 .WithTag("BCDIE", 4, 1) 815 .WithTag("PBDIE", 3, 1) 816 .WithTag("CF1MIE", 2, 1) 817 .WithTag("CF0MIE", 1, 1) 818 .WithTag("BFDIE", 0, 1) 819 .WithReservedBits(8, 8); 820 821 Registers.Status.Define(this) 822 .WithReservedBits(6, 2) 823 .WithTag("AEDF", 5, 1) 824 .WithTag("BCDF", 4, 1) 825 .WithTag("PIBDF", 3, 1) 826 .WithTag("CF1MF", 2, 1) 827 .WithTag("CF0MF", 1, 1) 828 .WithTag("BFDF", 0, 1) 829 .WithReservedBits(8, 8); 830 831 Registers.StatusClear.Define(this) 832 .WithReservedBits(6, 2) 833 .WithTag("AEDCL", 5, 1) 834 .WithTag("BCDCL", 4, 1) 835 .WithTag("PIBDCL", 3, 1) 836 .WithTag("CF1MCL", 2, 1) 837 .WithTag("CF0MCL", 1, 1) 838 .WithTag("BFDCL", 0, 1) 839 .WithReservedBits(8, 8); 840 841 Registers.ControlField0Data.Define(this) 842 .WithReservedBits(0, 8) 843 .WithReservedBits(8, 8); 844 845 Registers.ControlField0CompareEnable.Define(this) 846 .WithTag("CF0CE7", 7, 1) 847 .WithTag("CF0CE6", 6, 1) 848 .WithTag("CF0CE5", 5, 1) 849 .WithTag("CF0CE4", 4, 1) 850 .WithTag("CF0CE3", 3, 1) 851 .WithTag("CF0CE2", 2, 1) 852 .WithTag("CF0CE1", 1, 1) 853 .WithTag("CF0CE0", 0, 1) 854 .WithReservedBits(8, 8); 855 856 Registers.ControlField0RecieveData.Define(this) 857 .WithReservedBits(0, 8) 858 .WithReservedBits(8, 8); 859 860 Registers.PrimaryControlField1Data.Define(this) 861 .WithReservedBits(0, 8) 862 .WithReservedBits(8, 8); 863 864 Registers.SecondaryControlField1Data.Define(this) 865 .WithReservedBits(0, 8) 866 .WithReservedBits(8, 8); 867 868 Registers.ControlField1CompareEnable.Define(this) 869 .WithTag("CF1CE7", 7, 1) 870 .WithTag("CF1CE6", 6, 1) 871 .WithTag("CF1CE5", 5, 1) 872 .WithTag("CF1CE4", 4, 1) 873 .WithTag("CF1CE3", 3, 1) 874 .WithTag("CF1CE2", 2, 1) 875 .WithTag("CF1CE1", 1, 1) 876 .WithTag("CF1CE0", 0, 1) 877 .WithReservedBits(8, 8); 878 879 Registers.ControlField1ReceiveData.Define(this) 880 .WithReservedBits(0, 8) 881 .WithReservedBits(8, 8); 882 883 Registers.TimerControl.Define(this) 884 .WithReservedBits(1, 7) 885 .WithTag("TCST", 0, 1) 886 .WithReservedBits(8, 8); 887 888 Registers.TimerMode.Define(this) 889 .WithReservedBits(7, 1) 890 .WithTag("TCSS", 4, 3) 891 .WithTag("TWRC", 3, 1) 892 .WithReservedBits(2, 1) 893 .WithTag("TOMS", 0, 2) 894 .WithReservedBits(8, 8); 895 896 Registers.TimerPrescaler.Define(this) 897 .WithReservedBits(0, 8) 898 .WithReservedBits(8, 8); 899 900 Registers.TimerCount.Define(this) 901 .WithReservedBits(0, 8) 902 .WithReservedBits(8, 8); 903 } 904 TryReadFromIICSlave()905 private ulong TryReadFromIICSlave() 906 { 907 ushort readByte; 908 if(selectedIICSlave == null) 909 { 910 this.WarningLog("No peripheral selected. Will not perform read"); 911 return 0UL; 912 } 913 if(!receiveQueue.TryDequeue(out readByte)) 914 { 915 // This will obviously try to read too much bytes, but this is necessary, as we have no way of guessing how many bytes the driver intends to read 916 receiveQueue.EnqueueRange(selectedIICSlave.Read(IICReadBufferCount).Select(element => (ushort)element)); 917 918 if(!receiveQueue.TryDequeue(out readByte)) 919 { 920 this.ErrorLog("Unable to get bytes from the peripheral"); 921 return 0ul; 922 } 923 } 924 return readByte; 925 } 926 TransmitUARTData(byte value)927 private void TransmitUARTData(byte value) 928 { 929 CharReceived?.Invoke(value); 930 } 931 TransmitIICData(byte value)932 private void TransmitIICData(byte value) 933 { 934 DebugHelper.Assert((iicState == IICState.Idle) || (iicDirection != IICTransactionDirection.Unset), $"Incorrect communication direction {iicDirection} in state {iicState}"); 935 switch(iicState) 936 { 937 case IICState.Idle: 938 // Addressing frame 939 var rwBit = (value & 0x1); 940 var slaveAddress = value >> 1; 941 iicDirection = (rwBit == 1) ? IICTransactionDirection.Read : IICTransactionDirection.Write; 942 if(!i2cContainer.TryGetByAddress((int)slaveAddress, out selectedIICSlave)) 943 { 944 this.WarningLog("Selecting unconnected IIC slave address: 0x{0:X}", slaveAddress); 945 } 946 this.DebugLog("Selected slave address 0x{0:X} for {1}", slaveAddress, iicDirection); 947 iicState = IICState.InTransaction; 948 conditionCompletedFlag.Value = false; 949 BlinkTxIRQ(); 950 break; 951 case IICState.InTransaction: 952 if(iicDirection == IICTransactionDirection.Write) 953 { 954 iicTransmitQueue.Enqueue(value); 955 BlinkTxIRQ(); 956 } 957 else 958 { 959 if(value == DummyTransmitByte) 960 { 961 this.DebugLog("Ignoring the dummy transmission"); 962 BlinkTxIRQ(); 963 } 964 } 965 break; 966 default: 967 throw new Exception("Unreachable"); 968 } 969 } 970 TransmitSPIData(byte value)971 private void TransmitSPIData(byte value) 972 { 973 if(RegisteredPeripheral == null) 974 { 975 this.WarningLog("No SPI peripheral connected"); 976 return; 977 } 978 receiveQueue.Enqueue(RegisteredPeripheral.Transmit((byte)value)); 979 } 980 981 // This peripheral might work in a 9-bit mode, 982 private readonly Queue<ushort> receiveQueue; 983 private readonly Queue<byte> iicTransmitQueue; 984 private readonly ulong frequency; 985 private readonly IMachine machine; 986 private readonly SimpleContainerHelper<II2CPeripheral> i2cContainer; 987 private Parity parityBit = Parity.Even; 988 989 private IUART registeredUartPeripheral; 990 991 private bool manchesterMode; 992 private bool fifoMode; 993 private IICState iicState; 994 private II2CPeripheral selectedIICSlave; 995 private IICTransactionDirection iicDirection; 996 private PeripheralMode peripheralMode; 997 998 private IFlagRegisterField transmitEnabled; 999 private IFlagRegisterField hasTwoStopBits; 1000 private IFlagRegisterField parityEnabled; 1001 private IFlagRegisterField transmitEndInterruptEnabled; 1002 private IFlagRegisterField transmitEnd; 1003 private IFlagRegisterField receiveEnabled; 1004 private IFlagRegisterField receiveInterruptEnabled; 1005 private IFlagRegisterField transmitInterruptEnabled; 1006 private IFlagRegisterField smartCardMode; 1007 private IFlagRegisterField transmitFIFOEmpty; 1008 private IFlagRegisterField conditionCompletedFlag; 1009 private IFlagRegisterField i2cMode; 1010 private IValueRegisterField receiveFIFOTriggerCount; 1011 private IValueRegisterField bitRate; 1012 private IValueRegisterField clockSource; 1013 private IEnumRegisterField<DataTransferDirection> dataTransferDirection; 1014 private IEnumRegisterField<CommunicationMode> nonSmartCommunicationMode; 1015 1016 1017 private const ulong MaxFIFOSize = 16; 1018 private const int InterruptDelay = 1; 1019 private const int IICReadBufferCount = 24; 1020 // This byte is used to trigger reception on IIC bus. It should not be transmitted 1021 private const byte DummyTransmitByte = 0xFF; 1022 1023 private enum DataTransferDirection 1024 { 1025 LSBFirst = 0, 1026 MSBFirst = 1, 1027 } 1028 1029 private enum IICCondition 1030 { 1031 Start, 1032 Stop, 1033 Restart, 1034 } 1035 1036 private enum CommunicationMode 1037 { 1038 AsynchOrSimpleIIC = 0, 1039 SynchOrSimpleSPI = 1, 1040 } 1041 1042 private enum IICState 1043 { 1044 Idle = 0, 1045 InTransaction = 1, 1046 } 1047 1048 private enum IICTransactionDirection 1049 { 1050 Unset, 1051 Read, 1052 Write, 1053 } 1054 1055 private enum PeripheralMode 1056 { 1057 UART, 1058 SPI, 1059 IIC, 1060 SmartCardInterface, 1061 } 1062 1063 private enum Registers 1064 { 1065 SerialModeNonSmartCard = 0x00, // SMR 1066 SerialModeSmartCard = 0x00, // SMR_SMCI 1067 BitRate = 0x01, // BRR 1068 SerialControlNonSmartCard = 0x02, // SCR 1069 SerialControlSmartCard = 0x02, // SCR_SMCI 1070 TransmitData = 0x03, // TDR 1071 SerialStatusNonSmartCardNonFIFO = 0x04, // SSR 1072 SerialStatusNonSmartCardFIFO = 0x04, // SSR_FIFO 1073 SerialStatusSmartCard = 0x04, // SSR_SMCI 1074 SerialStatusManchesterMode = 0x04, // SSR_MANC 1075 ReceiveData = 0x05, // RDR 1076 SmartCardMode = 0x06, // SCMR 1077 SerialExtendedMode = 0x07, // SEMR 1078 NoiseFilterSetting = 0x08, // SNFR 1079 IICMode1 = 0x09, // SIMR1 1080 IICMode2 = 0x0A, // SIMR2 1081 IICMode3 = 0x0B, // SIMR3 1082 IICStatus = 0x0C, // SISR 1083 SPIMode = 0x0D, // SPMR 1084 TransmitDataNonManchesterMode = 0xE, // TDRHL 1085 TransmitDataManchesterMode = 0xE, // TDRHL_MAN 1086 TransmitFIFOData = 0xE, // FTDRHL 1087 TransmitFIFODataLowByte = 0xF, // FTDRL 1088 ReceiveDataNonManchesterMode = 0x10, // RDRHL 1089 ReceiveDataManchesterMode = 0x10, // RDRHL_MAN 1090 ReceiveFIFOData = 0x10, // FRDRHL 1091 ModulationDuty = 0x12, // MDDR 1092 DataCompareMatchControl = 0x13, // DCCR 1093 FIFOControl = 0x14, // FCR 1094 FIFODataCount = 0x16, // FDR 1095 LineStatus = 0x18, // LSR 1096 CompareMatchData = 0x1A, // CDR 1097 SerialPort = 0x1C, // SPTR 1098 AdjustmentCommunicationTiming = 0x1D, // ACTR 1099 ExtendedSerialModuleEnable = 0x20, // ESMER 1100 ManchesterMode = 0x20, // MMR 1101 Control0 = 0x21, // CR0 1102 Control1 = 0x22, // CR1 1103 TransmitManchesterPrefaceSetting = 0x22, // TMPR 1104 Control2 = 0x23, // CR2 1105 ReceiveManchesterPrefaceSetting = 0x23, // RMPR 1106 Control3 = 0x24, // CR3 1107 ManchesterExtendedErrorStatus = 0x24, // MESR 1108 PortControl = 0x25, // PCR 1109 ManchesterExtendedErrorControl = 0x25, // MECR 1110 InterruptControl = 0x26, // ICR 1111 Status = 0x27, // STR 1112 StatusClear = 0x28, // STCR 1113 ControlField0Data = 0x29, // CF0DR 1114 ControlField0CompareEnable = 0x2A, // CF0CR 1115 ControlField0RecieveData = 0x2B, // CF0RR 1116 PrimaryControlField1Data = 0x2C, // PCF1DR 1117 SecondaryControlField1Data = 0x2D, // SCF1DR 1118 ControlField1CompareEnable = 0x2E, // CF1CR 1119 ControlField1ReceiveData = 0x2F, // CF1RR 1120 TimerControl = 0x30, // TCR 1121 TimerMode = 0x31, // TMR 1122 TimerPrescaler = 0x32, // TPRE 1123 TimerCount = 0x33, // TCNT 1124 } 1125 } 1126 } 1127