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.Migrant; 11 using Antmicro.Renode.Core; 12 using Antmicro.Renode.Core.Structure; 13 using Antmicro.Renode.Core.Structure.Registers; 14 using Antmicro.Renode.Debugging; 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 23 namespace Antmicro.Renode.Peripherals.UART 24 { 25 [AllowedTranslations(AllowedTranslation.ByteToDoubleWord)] 26 public class RenesasRA8M1_SCI : IUART, IDoubleWordPeripheral, IProvidesRegisterCollection<DoubleWordRegisterCollection>, IKnownSize, 27 IPeripheralContainer<IUART, NullRegistrationPoint>, 28 IPeripheralContainer<ISPIPeripheral, NullRegistrationPoint>, 29 IPeripheralContainer<II2CPeripheral, NumberRegistrationPoint<int>> 30 { RenesasRA8M1_SCI(IMachine machine, ulong frequency)31 public RenesasRA8M1_SCI(IMachine machine, ulong frequency) 32 { 33 this.machine = machine; 34 this.frequency = frequency; 35 36 ReceiveIRQ = new GPIO(); 37 TransmitIRQ = new GPIO(); 38 TransmitEndIRQ = new GPIO(); 39 40 receiveQueue = new Queue<ushort>(); 41 iicTransmitQueue = new Queue<byte>(); 42 43 uartContainer = new NullRegistrationPointContainerHelper<IUART>(machine, this); 44 spiContainer = new NullRegistrationPointContainerHelper<ISPIPeripheral>(machine, this); 45 i2cContainer = new SimpleContainerHelper<II2CPeripheral>(machine, this); 46 47 RegistersCollection = new DoubleWordRegisterCollection(this); 48 DefineRegisters(); 49 50 Reset(); 51 } 52 ReadDoubleWord(long offset)53 public uint ReadDoubleWord(long offset) 54 { 55 return RegistersCollection.Read(offset); 56 } 57 WriteDoubleWord(long offset, uint value)58 public void WriteDoubleWord(long offset, uint value) 59 { 60 RegistersCollection.Write(offset, value); 61 } 62 WriteChar(byte value)63 public void WriteChar(byte value) 64 { 65 if(!receiveEnabled.Value) 66 { 67 this.Log(LogLevel.Warning, "Receiving is not enabled, ignoring byte 0x{0:X}", value); 68 return; 69 } 70 71 receiveQueue.Enqueue(value); 72 UpdateInterrupts(); 73 } 74 Reset()75 public void Reset() 76 { 77 receiveQueue.Clear(); 78 iicTransmitQueue.Clear(); 79 80 ReceiveIRQ.Unset(); 81 TransmitIRQ.Unset(); 82 TransmitEndIRQ.Unset(); 83 RegistersCollection.Reset(); 84 85 currentPeripheralMode = PeripheralMode.UART; 86 } 87 GetRegistrationPoints(ISPIPeripheral peripheral)88 public IEnumerable<NullRegistrationPoint> GetRegistrationPoints(ISPIPeripheral peripheral) 89 { 90 return spiContainer.GetRegistrationPoints(peripheral); 91 } 92 Register(ISPIPeripheral peripheral, NullRegistrationPoint registrationPoint)93 public void Register(ISPIPeripheral peripheral, NullRegistrationPoint registrationPoint) 94 { 95 spiContainer.Register(peripheral, registrationPoint); 96 } 97 Unregister(ISPIPeripheral peripheral)98 public void Unregister(ISPIPeripheral peripheral) 99 { 100 spiContainer.Unregister(peripheral); 101 } 102 GetRegistrationPoints(IUART peripheral)103 public IEnumerable<NullRegistrationPoint> GetRegistrationPoints(IUART peripheral) 104 { 105 return uartContainer.GetRegistrationPoints(peripheral); 106 } 107 Register(IUART peripheral, NullRegistrationPoint registrationPoint)108 public void Register(IUART peripheral, NullRegistrationPoint registrationPoint) 109 { 110 uartContainer.Register(peripheral, registrationPoint); 111 } 112 Unregister(IUART peripheral)113 public void Unregister(IUART peripheral) 114 { 115 uartContainer.Unregister(peripheral); 116 } 117 Register(II2CPeripheral peripheral, NumberRegistrationPoint<int> registrationPoint)118 public virtual void Register(II2CPeripheral peripheral, NumberRegistrationPoint<int> registrationPoint) 119 { 120 i2cContainer.Register(peripheral, registrationPoint); 121 } 122 Unregister(II2CPeripheral peripheral)123 public virtual void Unregister(II2CPeripheral peripheral) 124 { 125 i2cContainer.Unregister(peripheral); 126 } 127 GetRegistrationPoints(II2CPeripheral peripheral)128 public IEnumerable<NumberRegistrationPoint<int>> GetRegistrationPoints(II2CPeripheral peripheral) 129 { 130 return i2cContainer.GetRegistrationPoints(peripheral); 131 } 132 133 IEnumerable<IRegistered<IUART, NullRegistrationPoint>> IPeripheralContainer<IUART, NullRegistrationPoint>.Children => uartContainer.Children; 134 IEnumerable<IRegistered<ISPIPeripheral, NullRegistrationPoint>> IPeripheralContainer<ISPIPeripheral, NullRegistrationPoint>.Children => spiContainer.Children; 135 IEnumerable<IRegistered<II2CPeripheral, NumberRegistrationPoint<int>>> IPeripheralContainer<II2CPeripheral, NumberRegistrationPoint<int>>.Children => i2cContainer.Children; 136 137 public DoubleWordRegisterCollection RegistersCollection { get; } 138 139 public GPIO ReceiveIRQ { get; } 140 public GPIO TransmitIRQ { get; } 141 public GPIO TransmitEndIRQ { get; } 142 143 public uint BaudRate 144 { 145 get 146 { 147 var n = clockSelect.Value == 0 ? 1UL : 2UL << (2 * (ushort)clockSelect.Value - 1); 148 return (uint)(frequency / (64UL * n * bitRate.Value)) - 1; 149 } 150 } 151 152 public Bits StopBits => useTwoStopBits.Value ? Bits.Two : Bits.One; 153 154 public Parity ParityBit 155 { 156 get 157 { 158 if(!parityEnabled.Value) 159 { 160 return Parity.None; 161 } 162 163 return useOddParity.Value ? Parity.Odd : Parity.Even; 164 } 165 } 166 167 public long Size => 0x100; 168 169 [field: Transient] 170 public event Action<byte> CharReceived; 171 UpdateInterrupts()172 private void UpdateInterrupts() 173 { 174 if(currentPeripheralMode == PeripheralMode.IIC) 175 { 176 UpdateInterruptsInIICMode(); 177 return; 178 } 179 var rxState = receiveInterruptEnabled.Value && IsReceiveDataFull; 180 var txState = transmitInterruptEnabled.Value && IsDataTransmitted; 181 var teState = transmitEndInterruptEnabled.Value; 182 this.DebugLog("ReceiveIRQ: {0}blinking, TransmitIRQ: {1}blinking, TransmitEndIRQ: {2}blinking", rxState ? "" : "not ", txState ? "" : "not ", teState ? "" : "not "); 183 184 if(rxState) 185 { 186 ReceiveIRQ.Blink(); 187 } 188 if(txState) 189 { 190 TransmitIRQ.Blink(); 191 } 192 if(teState) 193 { 194 TransmitEndIRQ.Blink(); 195 } 196 } 197 UpdateInterruptsInIICMode()198 private void UpdateInterruptsInIICMode() 199 { 200 // This does not update the Transmit/Receive interrupts, as there are not status flags in this mode and they are expected just to blink 201 bool teState = transmitEndInterruptEnabled.Value && conditionCompletedFlag.Value; 202 this.DebugLog("TransmitEndIRQ: {0}.", teState ? "set" : "unset"); 203 204 if(teState) 205 { 206 TransmitEndIRQ.Blink(); 207 } 208 } 209 BlinkTxIRQ()210 private void BlinkTxIRQ() 211 { 212 DebugHelper.Assert(currentPeripheralMode == PeripheralMode.IIC); 213 214 if(transmitInterruptEnabled.Value) 215 { 216 TransmitIRQ.Blink(); 217 } 218 } 219 FlushIICTransmitQueue()220 private void FlushIICTransmitQueue() 221 { 222 if(iicTransmitQueue.Count != 0) 223 { 224 selectedIICSlave.Write(iicTransmitQueue.ToArray()); 225 iicTransmitQueue.Clear(); 226 } 227 } 228 EmulateIICStartStopCondition(IICCondition condition)229 private void EmulateIICStartStopCondition(IICCondition condition) 230 { 231 conditionCompletedFlag.Value = true; 232 if(condition == IICCondition.Stop) 233 { 234 if(selectedIICSlave == null) 235 { 236 this.WarningLog("No slave selected. This condition will have no effect"); 237 return; 238 } 239 240 switch(iicDirection) 241 { 242 case IICTransactionDirection.Write: 243 FlushIICTransmitQueue(); 244 break; 245 case IICTransactionDirection.Read: 246 receiveQueue.Clear(); 247 break; 248 default: 249 throw new ArgumentException("Unknown IIC direction"); 250 } 251 selectedIICSlave.FinishTransmission(); 252 selectedIICSlave = null; 253 } 254 else if(condition == IICCondition.Restart) 255 { 256 //Flush the register address 257 FlushIICTransmitQueue(); 258 } 259 260 iicState = IICState.Idle; 261 iicDirection = IICTransactionDirection.Unset; 262 UpdateInterruptsInIICMode(); 263 } 264 SetPeripheralMode()265 private void SetPeripheralMode() 266 { 267 switch(nonSmartCommunicationMode.Value) 268 { 269 case CommunicationMode.SimpleI2C: 270 if(i2cContainer.ChildCollection.Count != 0) 271 { 272 currentPeripheralMode = PeripheralMode.IIC; 273 return; 274 } 275 break; 276 case CommunicationMode.SimpleSPI: 277 if(spiContainer.RegisteredPeripheral != null) 278 { 279 currentPeripheralMode = PeripheralMode.SPI; 280 return; 281 } 282 break; 283 default: 284 break; 285 } 286 currentPeripheralMode = PeripheralMode.UART; 287 } 288 DefineRegisters()289 private void DefineRegisters() 290 { 291 Registers.ReceiveData.Define(this) 292 .WithReservedBits(29, 3) 293 .WithTag("FER", 28, 1) 294 .WithTag("PER", 27, 1) 295 .WithReservedBits(25, 2) 296 .WithTag("ORER", 24, 1) 297 .WithReservedBits(13, 11) 298 .WithTag("FFER", 12, 1) 299 .WithTag("FPER", 11, 1) 300 .WithTag("DR", 10, 1) 301 .WithTag("MPB", 9, 1) 302 .WithValueField(0, 9, FieldMode.Read, name: "RDAT", 303 valueProviderCallback: _ => 304 { 305 if(currentPeripheralMode == PeripheralMode.IIC) 306 { 307 if(iicState != IICState.InTransaction) 308 { 309 this.WarningLog("Trying to read the received data in the wrong state"); 310 } 311 BlinkTxIRQ(); 312 return TryReadFromIICSlave(); 313 } 314 315 if(!receiveQueue.TryDequeue(out var result)) 316 { 317 this.Log(LogLevel.Warning, "Queue is empty, returning 0."); 318 return 0; 319 } 320 UpdateInterrupts(); 321 return result; 322 }); 323 324 Registers.TransmitData.Define(this) 325 .WithReservedBits(13, 19) 326 .WithTag("TSYNC", 12, 1) 327 .WithReservedBits(10, 2) 328 .WithTag("MPBT", 9, 1) 329 .WithValueField(0, 9, FieldMode.Write, name: "TDAT", 330 writeCallback: (_, value) => 331 { 332 if(!transmitEnabled.Value) 333 { 334 this.Log(LogLevel.Warning, "Transmission is not enabled, ignoring byte 0x{0:X}", value); 335 return; 336 } 337 338 switch(currentPeripheralMode) 339 { 340 case PeripheralMode.UART: 341 TransmitUART((byte)value); 342 break; 343 case PeripheralMode.SPI: 344 TransmitSPI((byte)value); 345 break; 346 case PeripheralMode.IIC: 347 TransmitIICData((byte)value); 348 // No need to update the interrupts - in IIC mode we just blink the Tx interrupt 349 return; 350 default: 351 throw new Exception("unreachable"); 352 } 353 354 UpdateInterrupts(); 355 }); 356 357 Registers.CommonControl0.Define(this) 358 .WithReservedBits(25, 7) 359 .WithTag("SSE", 24, 1) 360 .WithReservedBits(22, 2) 361 .WithFlag(21, out transmitEndInterruptEnabled, name: "TEIE") 362 .WithFlag(20, out transmitInterruptEnabled, name: "TIE") 363 .WithReservedBits(17, 3) 364 .WithFlag(16, out receiveInterruptEnabled, name: "RIE") 365 .WithReservedBits(11, 5) 366 .WithTag("IDSEL", 10, 1) 367 .WithTag("DCME", 9, 1) 368 .WithTag("MPIE", 8, 1) 369 .WithReservedBits(5, 3) 370 .WithFlag(4, out transmitEnabled, name: "TE", writeCallback: (_, val) => 371 { 372 if(!val) 373 { 374 conditionCompletedFlag.Value = false; 375 } 376 }) 377 .WithReservedBits(1, 3) 378 .WithFlag(0, out receiveEnabled, name: "RE") 379 .WithChangeCallback((_, __) => 380 { 381 // The documentation states that the TXI interrupt should be fired when both TE and TIE are set 382 // with a single write operation. On the hardware however it takes some time to actually do that. 383 // The delay mechanism introduced below will prevent Renode from activating the interrupt too soon, 384 // because in some cases interrupts could be handled in the wrong order. 385 if(transmitEnabled.Value && transmitInterruptEnabled.Value) 386 { 387 machine.ScheduleAction(TimeInterval.FromMilliseconds(InterruptDelay), ___ => UpdateInterrupts()); 388 return; 389 } 390 UpdateInterrupts(); 391 }); 392 393 Registers.CommonControl1.Define(this) 394 .WithReservedBits(30, 2) 395 .WithTag("NFM", 29, 1) 396 .WithTag("NFEN", 28, 1) 397 .WithReservedBits(27, 1) 398 .WithTag("NFCS", 24, 3) 399 .WithReservedBits(21, 3) 400 .WithTag("SHARPS", 20, 1) 401 .WithReservedBits(17, 3) 402 .WithTag("SPLP", 16, 1) 403 .WithReservedBits(14, 2) 404 .WithTag("RINV", 13, 1) 405 .WithTag("TINV", 12, 1) 406 .WithReservedBits(10, 2) 407 .WithFlag(9, out useOddParity, name: "PM") 408 .WithFlag(8, out parityEnabled, name: "PE") 409 .WithReservedBits(6, 2) 410 .WithTag("SPB2IO", 5, 1) 411 .WithTag("SPB2DT", 4, 1) 412 .WithReservedBits(2, 2) 413 .WithTag("CTSPEN", 1, 1) 414 .WithTag("CTSE", 0, 1); 415 416 Registers.CommonControl2.Define(this) 417 .WithTag("MDDR", 24, 8) 418 .WithReservedBits(22, 2) 419 .WithValueField(20, 2, out clockSelect, name: "CKS") 420 .WithReservedBits(17, 3) 421 .WithTag("BRME", 16, 1) 422 .WithValueField(8, 8, out bitRate, name: "BRR") 423 .WithTag("ABCSE2", 7, 1) 424 .WithTag("ABCSE", 6, 1) 425 .WithTag("ABCS", 5, 1) 426 .WithTag("BGDM", 4, 1) 427 .WithReservedBits(3, 1) 428 .WithTag("BCP", 0, 3); 429 430 Registers.CommonControl3.Define(this) 431 .WithReservedBits(30, 2) 432 .WithTag("BLK", 29, 1) 433 .WithTag("GM", 28, 1) 434 .WithReservedBits(27, 1) 435 .WithTag("ACS0", 26, 1) 436 .WithTag("CKE", 24, 2) 437 .WithReservedBits(22, 2) 438 .WithTag("DEN", 21, 1) 439 .WithTag("FM", 20, 1) 440 .WithTag("MP", 19, 1) 441 .WithEnumField<DoubleWordRegister, CommunicationMode>(16, 3, out nonSmartCommunicationMode, 442 writeCallback: (_, __) => SetPeripheralMode(), name: "MOD") 443 .WithTag("RXDESEL", 15, 1) 444 .WithFlag(14, out useTwoStopBits, name: "STP") 445 .WithTag("SINV", 13, 1) 446 .WithTag("LSBF", 12, 1) 447 .WithReservedBits(10, 2) 448 .WithTag("CHR", 8, 2) 449 .WithTag("BPEN", 7, 1) 450 .WithReservedBits(2, 5) 451 .WithTag("CPOL", 1, 1) 452 .WithTag("CPHA", 0, 1); 453 454 Registers.CommonControl4.Define(this) 455 .WithTag("AET", 31, 1) 456 .WithTag("ATT", 28, 3) 457 .WithTag("AJD", 27, 1) 458 .WithTag("AST", 24, 3) 459 .WithReservedBits(20, 4) 460 .WithTag("SCKSEL", 19, 1) 461 .WithReservedBits(18, 1) 462 .WithTag("ATEN", 17, 1) 463 .WithTag("ASEN", 16, 1) 464 .WithReservedBits(9, 7) 465 .WithTag("CMPD", 0, 9); 466 467 Registers.CommunicationEnableStatus.Define(this) 468 .WithReservedBits(5, 27) 469 .WithFlag(4, FieldMode.Read, name: "TIST", valueProviderCallback: _ => transmitEnabled.Value) 470 .WithReservedBits(1, 3) 471 .WithFlag(0, FieldMode.Read, name: "RIST", valueProviderCallback: _ => receiveEnabled.Value); 472 473 Registers.SimpleIICControl.Define(this) 474 .WithReservedBits(24, 8) 475 .WithTag("IICSCLS", 22, 2) 476 .WithTag("IICSDAS", 20, 2) 477 .WithReservedBits(19, 1) 478 .WithFlag(18, FieldMode.WriteOneToClear, writeCallback: (_, val) => 479 { 480 if(val) 481 { 482 this.DebugLog("Stop Condition Requested!"); 483 EmulateIICStartStopCondition(IICCondition.Stop); 484 } 485 }, name: "IICSTPREQ") 486 .WithFlag(17, FieldMode.WriteOneToClear, writeCallback: (_, val) => 487 { 488 if(val) 489 { 490 this.DebugLog("Restart Condition Requested!"); 491 EmulateIICStartStopCondition(IICCondition.Restart); 492 } 493 }, name: "IICRSTAREQ") 494 .WithFlag(16, FieldMode.WriteOneToClear, writeCallback: (_, val) => 495 { 496 if(val) 497 { 498 this.DebugLog("Start Condition Requested!"); 499 EmulateIICStartStopCondition(IICCondition.Start); 500 } 501 }, name: "IICSTAREQ") 502 .WithReservedBits(14, 2) 503 .WithFlag(13, 504 writeCallback: (_, val) => 505 { 506 if(useRxTxInterrupts.Value) 507 { 508 return; 509 } 510 if(val) 511 { 512 BlinkTxIRQ(); 513 } 514 }, name:"IICACKT") 515 .WithReservedBits(10, 3) 516 .WithTag("IICCSC", 9, 1) 517 .WithFlag(8, out useRxTxInterrupts, name: "IICINTM") 518 .WithReservedBits(5, 3) 519 .WithTag("IICDL", 0, 5) 520 .WithWriteCallback((_, val) => 521 { 522 var conditionRequestBits = val & 0x70000; 523 if(conditionRequestBits != 0 && ((conditionRequestBits & (conditionRequestBits - 1)) != 0)) 524 { 525 this.WarningLog("More than one IIC condition requested at the same register acces"); 526 } 527 else if(conditionRequestBits == 0) 528 { 529 // conditionCompletedFlag being zeroed 530 UpdateInterruptsInIICMode(); 531 } 532 }); 533 534 Registers.FIFOControl.Define(this) 535 .WithReservedBits(29, 3) 536 .WithTag("RSTRG", 24, 5) 537 .WithTag("RFRST[]", 23, 1) 538 .WithReservedBits(21, 2) 539 .WithTag("RTRG", 16, 5) 540 .WithTag("TFRST", 15, 1) 541 .WithReservedBits(13, 2) 542 .WithTag("TTRG", 8, 5) 543 .WithReservedBits(1, 7) 544 .WithTag("DRES", 0, 1); 545 546 Registers.ManchesterControl.Define(this) 547 .WithReservedBits(27, 5) 548 .WithTag("SBEREN", 26, 1) 549 .WithTag("SYEREN", 25, 1) 550 .WithTag("PFEREN", 24, 1) 551 .WithReservedBits(22, 2) 552 .WithTag("RPPAT", 20, 2) 553 .WithTag("RPLEN", 16, 4) 554 .WithReservedBits(14, 2) 555 .WithTag("TPPAT", 12, 2) 556 .WithTag("TPLEN", 8, 4) 557 .WithReservedBits(7, 1) 558 .WithTag("SBSEL", 6, 1) 559 .WithTag("SYNSEL", 5, 1) 560 .WithTag("SYNVAL", 4, 1) 561 .WithReservedBits(3, 1) 562 .WithTag("ERTEN", 2, 1) 563 .WithTag("TMPOL", 1, 1) 564 .WithTag("RMPOL", 0, 1); 565 566 Registers.DriverControl.Define(this) 567 .WithReservedBits(21, 11) 568 .WithTag("DENGT", 16, 5) 569 .WithReservedBits(13, 3) 570 .WithTag("DEAST", 8, 5) 571 .WithReservedBits(1, 7) 572 .WithTag("DEPOL", 0, 1); 573 574 Registers.SimpleLINControl0.Define(this) 575 .WithReservedBits(26, 6) 576 .WithTag("BCCS", 24, 2) 577 .WithReservedBits(23, 1) 578 .WithTag("AEDIE", 22, 1) 579 .WithTag("COFIE", 21, 1) 580 .WithTag("BFDIE", 20, 1) 581 .WithReservedBits(18, 2) 582 .WithTag("BCDIE", 17, 1) 583 .WithTag("BFOIE", 16, 1) 584 .WithTag("PIBS", 13, 3) 585 .WithTag("PIBE", 12, 1) 586 .WithTag("CF1DS", 10, 2) 587 .WithTag("CF0RE", 9, 1) 588 .WithTag("BFE", 8, 1) 589 .WithReservedBits(2, 6) 590 .WithTag("TCCS", 0, 2); 591 592 Registers.SimpleLINControl1.Define(this) 593 .WithTag("CF1CE", 24, 8) 594 .WithTag("SCF1D", 16, 8) 595 .WithTag("PCF1D", 8, 8) 596 .WithReservedBits(6, 2) 597 .WithTag("BMEN", 5, 1) 598 .WithTag("SDST", 4, 1) 599 .WithReservedBits(1, 3) 600 .WithTag("TCST", 0, 1); 601 602 Registers.SimpleLINControl2.Define(this) 603 .WithTag("BFLW", 16, 16) 604 .WithTag("CF0CE", 8, 8) 605 .WithTag("CF0D", 0, 8); 606 607 Registers.CommonStatus.Define(this) 608 .WithTag("RDRF", 31, 1) 609 .WithFlag(30, FieldMode.Read, valueProviderCallback: _ => true, name: "TEND") 610 .WithTag("TDRE", 29, 1) 611 .WithTag("FER", 28, 1) 612 .WithTag("PER", 27, 1) 613 .WithTag("MFF", 26, 1) 614 .WithReservedBits(25, 1) 615 .WithTag("ORER", 24, 1) 616 .WithReservedBits(19, 5) 617 .WithTag("DFER", 18, 1) 618 .WithTag("DPER", 17, 1) 619 .WithTag("DCMF", 16, 1) 620 .WithTag("RXDMON", 15, 1) 621 .WithReservedBits(5, 10) 622 .WithTag("ERS", 4, 1) 623 .WithReservedBits(0, 4); 624 625 Registers.SimpleIICStatus.Define(this) 626 .WithReservedBits(4, 28) 627 .WithFlag(3, out conditionCompletedFlag, FieldMode.Read, name: "IICSTIF") 628 .WithReservedBits(1, 2) 629 .WithTag("IICACKR", 0, 1); 630 631 Registers.FIFOReceiveStatus.Define(this) 632 .WithReservedBits(30, 2) 633 .WithTag("FNUM", 24, 6) 634 .WithReservedBits(22, 2) 635 .WithTag("PNUM", 16, 6) 636 .WithReservedBits(14, 2) 637 .WithTag("R", 8, 6) 638 .WithReservedBits(1, 7) 639 .WithTag("DR", 0, 1); 640 641 Registers.FIFOTransmitStatus.Define(this) 642 .WithReservedBits(6, 26) 643 .WithTag("T", 0, 6); 644 645 Registers.ManchesterStatus.Define(this) 646 .WithReservedBits(7, 25) 647 .WithTag("RSYNC", 6, 1) 648 .WithReservedBits(5, 1) 649 .WithTag("MER", 4, 1) 650 .WithReservedBits(3, 1) 651 .WithTag("SBER", 2, 1) 652 .WithTag("SYER", 1, 1) 653 .WithTag("PFER", 0, 1); 654 655 Registers.SimpleLINStatus0.Define(this) 656 .WithTag("CF1RD", 24, 8) 657 .WithTag("CF0RD", 16, 8) 658 .WithTag("AEDF", 15, 1) 659 .WithTag("COF", 14, 1) 660 .WithTag("PIBDF", 13, 1) 661 .WithTag("CF1MF", 12, 1) 662 .WithTag("CF0MF", 11, 1) 663 .WithTag("BFDF", 10, 1) 664 .WithTag("BCDF", 9, 1) 665 .WithTag("BFOF", 8, 1) 666 .WithReservedBits(2, 6) 667 .WithTag("RXDSF", 1, 1) 668 .WithTag("SFSF", 0, 1); 669 670 Registers.SimpleIICStatus1.Define(this) 671 .WithReservedBits(16, 16) 672 .WithTag("TCNT", 0, 16); 673 674 Registers.CommonFlagClear.Define(this) 675 .WithTag("RDRFC", 31, 1) 676 .WithReservedBits(30, 1) 677 .WithTag("TDREC", 29, 1) 678 .WithTag("FERC", 28, 1) 679 .WithTag("PERC", 27, 1) 680 .WithTag("MFFC", 26, 1) 681 .WithReservedBits(25, 1) 682 .WithTag("ORERC", 24, 1) 683 .WithReservedBits(19, 5) 684 .WithTag("DFERC", 18, 1) 685 .WithTag("DPERC", 17, 1) 686 .WithTag("DCMFC", 16, 1) 687 .WithReservedBits(5, 11) 688 .WithTag("ERSC", 4, 1) 689 .WithReservedBits(0, 4); 690 691 Registers.SimpleIICFlagCLear.Define(this) 692 .WithReservedBits(4, 28) 693 .WithFlag(3, name: "IICSTIFC", writeCallback: (_, val) => 694 { 695 if(val) 696 { 697 conditionCompletedFlag.Value = false; 698 } 699 }) 700 .WithReservedBits(0, 3); 701 702 Registers.FIFOFlagClear.Define(this) 703 .WithReservedBits(1, 31) 704 .WithTag("DRC", 0, 1); 705 706 Registers.ManchesterFlagClear.Define(this) 707 .WithReservedBits(5, 27) 708 .WithTag("MERC", 4, 1) 709 .WithReservedBits(3, 1) 710 .WithTag("SBERC", 2, 1) 711 .WithTag("SYERC", 1, 1) 712 .WithTag("PFERC", 0, 1); 713 714 Registers.SimpleLINFlagClear.Define(this) 715 .WithReservedBits(16, 16) 716 .WithTag("AEDC", 15, 1) 717 .WithTag("COFC", 14, 1) 718 .WithTag("PIBDC", 13, 1) 719 .WithTag("CF1MC", 12, 1) 720 .WithTag("CF0MC", 11, 1) 721 .WithTag("BFDC", 10, 1) 722 .WithTag("BCDC", 9, 1) 723 .WithTag("BFOC", 8, 1) 724 .WithReservedBits(0, 8); 725 } 726 TransmitUART(byte value)727 private void TransmitUART(byte value) 728 { 729 CharReceived?.Invoke(value); 730 } 731 TransmitSPI(byte value)732 private void TransmitSPI(byte value) 733 { 734 if(spiContainer.RegisteredPeripheral == null) 735 { 736 this.WarningLog("No SPI peripheral connected"); 737 return; 738 } 739 740 receiveQueue.Enqueue(spiContainer.RegisteredPeripheral.Transmit(value)); 741 } 742 TryReadFromIICSlave()743 private ulong TryReadFromIICSlave() 744 { 745 ushort readByte; 746 if(selectedIICSlave == null) 747 { 748 this.WarningLog("No peripheral selected. Will not perform read"); 749 return 0UL; 750 } 751 if(!receiveQueue.TryDequeue(out readByte)) 752 { 753 // 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 754 receiveQueue.EnqueueRange(selectedIICSlave.Read(IICReadBufferCount).Select(element => (ushort)element)); 755 756 if(!receiveQueue.TryDequeue(out readByte)) 757 { 758 this.ErrorLog("Unable to get bytes from the peripheral"); 759 return 0ul; 760 } 761 } 762 return readByte; 763 } 764 TransmitUARTData(byte value)765 private void TransmitUARTData(byte value) 766 { 767 CharReceived?.Invoke(value); 768 } 769 TransmitIICData(byte value)770 private void TransmitIICData(byte value) 771 { 772 DebugHelper.Assert((iicState == IICState.Idle) || (iicDirection != IICTransactionDirection.Unset), $"Incorrect communication direction {iicDirection} in state {iicState}"); 773 switch(iicState) 774 { 775 case IICState.Idle: 776 // Addressing frame 777 var rwBit = (value & 0x1); 778 var slaveAddress = value >> 1; 779 780 iicDirection = (rwBit == 1) ? IICTransactionDirection.Read : IICTransactionDirection.Write; 781 if(!i2cContainer.TryGetByAddress((int)slaveAddress, out selectedIICSlave)) 782 { 783 this.WarningLog("Selecting unconnected IIC slave address: 0x{0:X}", slaveAddress); 784 } 785 this.DebugLog("Selected slave address 0x{0:X} for {1}", slaveAddress, iicDirection); 786 iicState = IICState.InTransaction; 787 conditionCompletedFlag.Value = false; 788 BlinkTxIRQ(); 789 break; 790 case IICState.InTransaction: 791 if(iicDirection == IICTransactionDirection.Write) 792 { 793 iicTransmitQueue.Enqueue(value); 794 BlinkTxIRQ(); 795 } 796 else 797 { 798 if(value == DummyTransmitByte) 799 { 800 this.DebugLog("Ignoring the dummy transmission"); 801 BlinkTxIRQ(); 802 } 803 } 804 break; 805 default: 806 throw new Exception("Unreachable"); 807 } 808 } 809 TransmitSPIData(byte value)810 private void TransmitSPIData(byte value) 811 { 812 if(spiContainer.RegisteredPeripheral == null) 813 { 814 this.WarningLog("No SPI peripheral connected"); 815 return; 816 } 817 receiveQueue.Enqueue(spiContainer.RegisteredPeripheral.Transmit((byte)value)); 818 } 819 820 // This is used in the non-FIFO mode where there is room just for a single byte, hence "full" means non-empty queue 821 private bool IsReceiveDataFull => receiveQueue.Count > 0; 822 // This is used in the non-FIFO. Single character is transmitted instantly so this is always true 823 private bool IsDataTransmitted => true; 824 825 private readonly IMachine machine; 826 private readonly Queue<ushort> receiveQueue; 827 private readonly SimpleContainerHelper<II2CPeripheral> i2cContainer; 828 private readonly Queue<byte> iicTransmitQueue; 829 830 private IICState iicState; 831 private II2CPeripheral selectedIICSlave; 832 private IICTransactionDirection iicDirection; 833 834 private readonly NullRegistrationPointContainerHelper<IUART> uartContainer; 835 private readonly NullRegistrationPointContainerHelper<ISPIPeripheral> spiContainer; 836 837 private readonly ulong frequency; 838 839 private PeripheralMode currentPeripheralMode; 840 841 private IFlagRegisterField transmitEndInterruptEnabled; 842 private IFlagRegisterField transmitInterruptEnabled; 843 private IFlagRegisterField receiveInterruptEnabled; 844 private IFlagRegisterField transmitEnabled; 845 private IFlagRegisterField receiveEnabled; 846 847 private IFlagRegisterField parityEnabled; 848 private IFlagRegisterField useOddParity; 849 850 private IFlagRegisterField useTwoStopBits; 851 852 private IValueRegisterField clockSelect; 853 private IValueRegisterField bitRate; 854 855 private IFlagRegisterField conditionCompletedFlag; 856 857 private IFlagRegisterField useRxTxInterrupts; 858 859 private IEnumRegisterField<CommunicationMode> nonSmartCommunicationMode; 860 861 private const int InterruptDelay = 1; 862 private const int IICReadBufferCount = 24; 863 // This byte is used to trigger reception on IIC bus. It should not be transmitted 864 private const byte DummyTransmitByte = 0xFF; 865 866 private enum Registers 867 { 868 ReceiveData = 0x0, 869 TransmitData = 0x4, 870 CommonControl0 = 0x8, 871 CommonControl1 = 0xC, 872 CommonControl2 = 0x10, 873 CommonControl3 = 0x14, 874 CommonControl4 = 0x18, 875 CommunicationEnableStatus = 0x1C, 876 SimpleIICControl = 0x20, 877 FIFOControl = 0x24, 878 ManchesterControl = 0x2C, 879 DriverControl = 0x30, 880 SimpleLINControl0 = 0x34, 881 SimpleLINControl1 = 0x38, 882 SimpleLINControl2 = 0x3C, 883 CommonStatus = 0x48, 884 SimpleIICStatus = 0x4C, 885 FIFOReceiveStatus = 0x50, 886 FIFOTransmitStatus = 0x54, 887 ManchesterStatus = 0x58, 888 SimpleLINStatus0 = 0x5C, 889 SimpleIICStatus1 = 0x60, 890 CommonFlagClear = 0x68, 891 SimpleIICFlagCLear = 0x6C, 892 FIFOFlagClear = 0x70, 893 ManchesterFlagClear = 0x74, 894 SimpleLINFlagClear = 0x78, 895 } 896 897 private enum CommunicationMode 898 { 899 Asynchronous = 0b000, 900 SmartCardInterface = 0b001, 901 ClockSynchronous = 0b010, 902 SimpleSPI = 0b011, 903 SimpleI2C = 0b100, 904 Machnester = 0b101, 905 SimpleLIN = 0b111, 906 } 907 908 private enum PeripheralMode 909 { 910 UART, 911 SPI, 912 IIC, 913 } 914 915 private enum IICState 916 { 917 Idle = 0, 918 InTransaction = 1, 919 } 920 921 private enum IICTransactionDirection 922 { 923 Unset, 924 Read, 925 Write, 926 } 927 928 private enum IICCondition 929 { 930 Start, 931 Stop, 932 Restart, 933 } 934 } 935 } 936 937 938