1 // 2 // Copyright (c) 2010-2023 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 Antmicro.Renode.Core; 10 using Antmicro.Renode.Core.Structure; 11 using Antmicro.Renode.Core.Structure.Registers; 12 using Antmicro.Renode.Exceptions; 13 using Antmicro.Renode.Logging; 14 using Antmicro.Renode.Peripherals.Bus; 15 using Antmicro.Renode.Peripherals.SPI; 16 using Antmicro.Renode.Utilities; 17 18 namespace Antmicro.Renode.Peripherals.UART.Silabs 19 { 20 public abstract class EFR32_GenericUSART : UARTBase, IUARTWithBufferState, IPeripheralContainer<ISPIPeripheral, NullRegistrationPoint> 21 { EFR32_GenericUSART(IMachine machine, uint clockFrequency)22 public EFR32_GenericUSART(IMachine machine, uint clockFrequency) : base(machine) 23 { 24 TransmitIRQ = new GPIO(); 25 ReceiveIRQ = new GPIO(); 26 RxDataAvailableRequest = new GPIO(); 27 RxDataAvailableSingleRequest = new GPIO(); 28 TxBufferLowRequest = new GPIO(); 29 TxBufferLowSingleRequest = new GPIO(); 30 TxEmptyRequest = new GPIO(); 31 RxDataAvailableRightRequest = new GPIO(); 32 RxDataAvailableRightSingleRequest = new GPIO(); 33 TxBufferLowRightRequest = new GPIO(); 34 TxBufferLowRightSingleRequest = new GPIO(); 35 TxEmptyRequest.Set(true); 36 TxBufferLowRequest.Set(true); 37 38 interruptsManager = new InterruptManager<Interrupt>(this); 39 40 uartClockFrequency = clockFrequency; 41 } 42 Reset()43 public override void Reset() 44 { 45 base.Reset(); 46 interruptsManager.Reset(); 47 spiSlaveDevice = null; 48 TxEmptyRequest.Set(true); 49 TxBufferLowRequest.Set(true); 50 } 51 Register(ISPIPeripheral peripheral, NullRegistrationPoint registrationPoint)52 public void Register(ISPIPeripheral peripheral, NullRegistrationPoint registrationPoint) 53 { 54 if(spiSlaveDevice != null) 55 { 56 throw new RegistrationException("Cannot register more than one peripheral."); 57 } 58 Machine.RegisterAsAChildOf(this, peripheral, registrationPoint); 59 spiSlaveDevice = peripheral; 60 } 61 Unregister(ISPIPeripheral peripheral)62 public void Unregister(ISPIPeripheral peripheral) 63 { 64 if(peripheral != spiSlaveDevice) 65 { 66 throw new RegistrationException("Trying to unregister not registered device."); 67 } 68 69 Machine.UnregisterAsAChildOf(this, peripheral); 70 spiSlaveDevice = null; 71 } 72 GetRegistrationPoints(ISPIPeripheral peripheral)73 public IEnumerable<NullRegistrationPoint> GetRegistrationPoints(ISPIPeripheral peripheral) 74 { 75 if(peripheral != spiSlaveDevice) 76 { 77 throw new RegistrationException("Trying to obtain a registration point for a not registered device."); 78 } 79 80 return new[] { NullRegistrationPoint.Instance }; 81 } 82 WriteChar(byte value)83 public override void WriteChar(byte value) 84 { 85 if(BufferState == BufferState.Full) 86 { 87 this.Log(LogLevel.Warning, "RX buffer is full. Dropping incoming byte (0x{0:X})", value); 88 return; 89 } 90 base.WriteChar(value); 91 } 92 93 IEnumerable<IRegistered<ISPIPeripheral, NullRegistrationPoint>> IPeripheralContainer<ISPIPeripheral, NullRegistrationPoint>.Children 94 { 95 get 96 { 97 return new[] { Registered.Create(spiSlaveDevice, NullRegistrationPoint.Instance) }; 98 } 99 } 100 101 [IrqProvider("transmit irq", 0)] 102 public GPIO TransmitIRQ { get; } 103 104 [IrqProvider("receive irq", 1)] 105 public GPIO ReceiveIRQ { get; } 106 107 public GPIO RxDataAvailableRequest { get; } 108 public GPIO RxDataAvailableSingleRequest { get; } 109 public GPIO TxBufferLowRequest { get; } 110 public GPIO TxBufferLowSingleRequest { get; } 111 public GPIO TxEmptyRequest { get; } 112 public GPIO RxDataAvailableRightRequest { get; } 113 public GPIO RxDataAvailableRightSingleRequest { get; } 114 public GPIO TxBufferLowRightRequest { get; } 115 public GPIO TxBufferLowRightSingleRequest { get; } 116 117 public override Parity ParityBit { get { return parityBitModeField.Value; } } 118 119 public override Bits StopBits { get { return stopBitsModeField.Value; } } 120 121 public override uint BaudRate 122 { 123 get 124 { 125 //This calculation, according to the documentation, could be written as: 126 //return uartClockFrequency / (multiplier * (1 + (fractionalClockDividerField.Value << 3) / 256)); 127 //But the result differs much from the one calculated by the driver, most probably due to 128 //invalid integer division. 129 //This code mimics the one in emlib driver. 130 var oversample = 1u; 131 var factor = 0u; 132 switch(oversamplingField.Value) 133 { 134 case OversamplingMode.Times16: 135 oversample = 1; 136 factor = 256 / 16; 137 break; 138 case OversamplingMode.Times8: 139 oversample = 1; 140 factor = 256 / 8; 141 break; 142 case OversamplingMode.Times6: 143 oversample = 3; 144 factor = 256 / 2; 145 break; 146 case OversamplingMode.Times4: 147 oversample = 1; 148 factor = 256 / 4; 149 break; 150 } 151 var divisor = oversample * (256 + ((uint)fractionalClockDividerField.Value << 3)); 152 var quotient = uartClockFrequency / divisor; 153 var remainder = uartClockFrequency % divisor; 154 return (factor * quotient) + (factor * remainder) / divisor; 155 } 156 } 157 158 public BufferState BufferState 159 { 160 get 161 { 162 return bufferState; 163 } 164 165 private set 166 { 167 if(bufferState == value) 168 { 169 return; 170 } 171 bufferState = value; 172 BufferStateChanged?.Invoke(value); 173 switch(bufferState) 174 { 175 case BufferState.Empty: 176 RxDataAvailableRequest.Set(false); 177 RxDataAvailableSingleRequest.Set(false); 178 break; 179 case BufferState.Ready: 180 RxDataAvailableRequest.Set(false); 181 RxDataAvailableSingleRequest.Set(true); 182 break; 183 case BufferState.Full: 184 RxDataAvailableRequest.Set(true); 185 break; 186 default: 187 throw new Exception("Unreachable code. Invalid BufferState value."); 188 } 189 } 190 } 191 192 public event Action<BufferState> BufferStateChanged; 193 CharWritten()194 protected override void CharWritten() 195 { 196 interruptsManager.SetInterrupt(Interrupt.ReceiveDataValid); 197 receiveDataValidFlag.Value = true; 198 BufferState = Count == BufferSize ? BufferState.Full : BufferState.Ready; 199 } 200 QueueEmptied()201 protected override void QueueEmptied() 202 { 203 interruptsManager.ClearInterrupt(Interrupt.ReceiveDataValid); 204 receiveDataValidFlag.Value = false; 205 BufferState = BufferState.Empty; 206 } 207 208 protected override bool IsReceiveEnabled => receiverEnableFlag.Value; 209 GenerateControlRegister()210 protected DoubleWordRegister GenerateControlRegister() => new DoubleWordRegister(this) 211 .WithEnumField(0, 1, out operationModeField, name: "SYNC") 212 .WithTaggedFlag("LOOPBK", 1) 213 .WithTaggedFlag("CCEN", 2) 214 .WithTaggedFlag("MPM", 3) 215 .WithTaggedFlag("MPAB", 4) 216 .WithEnumField(5, 2, out oversamplingField, name: "OVS") 217 .WithReservedBits(7, 1) 218 .WithTaggedFlag("CLKPOL", 8) 219 .WithTaggedFlag("CLKPHA", 9) 220 .WithTaggedFlag("MSBF", 10) 221 .WithTaggedFlag("CSMA", 11) 222 .WithTaggedFlag("TXBIL", 12) 223 .WithTaggedFlag("RXINV", 13) 224 .WithTaggedFlag("TXINV", 14) 225 .WithTaggedFlag("CSINV", 15) 226 .WithTaggedFlag("AUTOCS", 16) 227 .WithTaggedFlag("AUTOTRI", 17) 228 .WithTaggedFlag("SCMODE", 18) 229 .WithTaggedFlag("SCRETRANS", 19) 230 .WithTaggedFlag("SKIPPERRF", 20) 231 .WithTaggedFlag("BIT8DV", 21) 232 .WithTaggedFlag("ERRSDMA", 22) 233 .WithTaggedFlag("ERRSRX", 23) 234 .WithTaggedFlag("ERRSTX", 24) 235 .WithTaggedFlag("SSSEARLY", 25) 236 .WithReservedBits(26, 2) 237 .WithTaggedFlag("BYTESWAP", 28) 238 .WithTaggedFlag("AUTOTX", 29) 239 .WithTaggedFlag("MVDIS", 30) 240 .WithTaggedFlag("SMSDELAY", 31); 241 GenerateFrameFormatRegister()242 protected DoubleWordRegister GenerateFrameFormatRegister() => new DoubleWordRegister(this, 0x1005) 243 .WithTag("DATABITS", 0, 4) 244 .WithReservedBits(4, 4) 245 .WithEnumField(8, 2, out parityBitModeField, name: "PARITY") 246 .WithReservedBits(10, 2) 247 .WithEnumField(12, 2, out stopBitsModeField, name: "STOPBITS") 248 .WithReservedBits(14, 18); 249 GenerateTriggerControlRegister()250 protected DoubleWordRegister GenerateTriggerControlRegister() => new DoubleWordRegister(this) 251 .WithReservedBits(0, 4) 252 .WithTaggedFlag("RXTEN", 4) 253 .WithTaggedFlag("TXTEN", 5) 254 .WithTaggedFlag("AUTOTXTEN", 6) 255 .WithTaggedFlag("TXARX0EN", 7) 256 .WithTaggedFlag("TXARX1EN", 8) 257 .WithTaggedFlag("TXARX2EN", 9) 258 .WithTaggedFlag("RXATX0EN", 10) 259 .WithTaggedFlag("RXATX1EN", 11) 260 .WithTaggedFlag("RXATX2EN", 12) 261 .WithReservedBits(13, 3) 262 .WithTag("TSEL", 16, 4) 263 .WithReservedBits(20, 12); 264 GenerateCommandRegister()265 protected DoubleWordRegister GenerateCommandRegister() => new DoubleWordRegister(this) 266 .WithFlag(0, FieldMode.Set, writeCallback: (_, newValue) => { if(newValue) receiverEnableFlag.Value = true; }, name: "RXEN") 267 .WithFlag(1, FieldMode.Set, writeCallback: (_, newValue) => { if(newValue) receiverEnableFlag.Value = false; }, name: "RXDIS") 268 .WithFlag(2, FieldMode.Set, writeCallback: (_, newValue) => 269 { 270 if(newValue) 271 { 272 transmitterEnableFlag.Value = true; 273 interruptsManager.SetInterrupt(Interrupt.TransmitBufferLevel); 274 } 275 }, name: "TXEN") 276 .WithFlag(3, FieldMode.Set, writeCallback: (_, newValue) => { if(newValue) transmitterEnableFlag.Value = false; }, name: "TXDIS") 277 .WithTaggedFlag("MASTEREN", 4) 278 .WithTaggedFlag("MASTERDIS", 5) 279 .WithTaggedFlag("RXBLOCKEN", 6) 280 .WithTaggedFlag("RXBLOCKDIS", 7) 281 .WithTaggedFlag("TXTRIEN", 8) 282 .WithTaggedFlag("TXTRIDIS", 9) 283 .WithTaggedFlag("CLEARTX", 10) 284 .WithFlag(11, FieldMode.Set, writeCallback: (_, newValue) => { if(newValue) ClearBuffer(); }, name: "CLEARRX") 285 .WithReservedBits(12, 20); 286 GenerateStatusRegister()287 protected DoubleWordRegister GenerateStatusRegister() => new DoubleWordRegister(this, 0x40) 288 .WithFlag(0, out receiverEnableFlag, FieldMode.Read, name: "RXENS") 289 .WithFlag(1, out transmitterEnableFlag, FieldMode.Read, name: "TXENS") 290 .WithTaggedFlag("MASTER", 2) 291 .WithTaggedFlag("RXBLOCK", 3) 292 .WithTaggedFlag("TXTRI", 4) 293 .WithFlag(5, out transferCompleteFlag, FieldMode.Read, name: "TXC") 294 .WithTaggedFlag("TXBL", 6) 295 .WithFlag(7, out receiveDataValidFlag, FieldMode.Read, name: "RXDATAV") 296 .WithFlag(8, FieldMode.Read, valueProviderCallback: _ => Count == BufferSize, name: "RXFULL") 297 .WithTaggedFlag("TXBDRIGHT", 9) 298 .WithTaggedFlag("TXBSRIGHT", 10) 299 .WithTaggedFlag("RXDATAVRIGHT", 11) 300 .WithTaggedFlag("RXFULLRIGHT", 12) 301 .WithFlag(13, FieldMode.Read, valueProviderCallback: _ => true, name: "TXIDLE") 302 .WithTaggedFlag("TIMERRESTARTED", 14) 303 .WithReservedBits(15, 1) 304 .WithValueField(16, 2, FieldMode.Read, valueProviderCallback: _ => 0, name: "TXBUFCNT") 305 .WithReservedBits(18, 14); 306 GenerateClockControlRegister()307 protected DoubleWordRegister GenerateClockControlRegister() => new DoubleWordRegister(this) 308 .WithReservedBits(0, 3) 309 .WithValueField(3, 20, out fractionalClockDividerField, name: "DIV") 310 .WithReservedBits(23, 8) 311 .WithTaggedFlag("AUTOBAUDEN", 31); 312 GenerateRxBufferDataExtendedRegister()313 protected DoubleWordRegister GenerateRxBufferDataExtendedRegister() => new DoubleWordRegister(this) 314 .WithTag("RXDATA", 0, 8) 315 .WithReservedBits(8, 5) 316 .WithTaggedFlag("PERR", 14) 317 .WithTaggedFlag("FERR", 15) 318 .WithReservedBits(16, 16); 319 GenerateRxBufferDataRegister()320 protected DoubleWordRegister GenerateRxBufferDataRegister() => new DoubleWordRegister(this) 321 .WithValueField(0, 8, FieldMode.Read, valueProviderCallback: (_) => ReadBuffer(), name: "RXDATA") 322 .WithReservedBits(8, 24); 323 GenerateRxBufferDoubleDataExtendedRegister()324 protected DoubleWordRegister GenerateRxBufferDoubleDataExtendedRegister() => new DoubleWordRegister(this) 325 .WithTag("RXDATA0", 0, 8) 326 .WithReservedBits(8, 5) 327 .WithTaggedFlag("PERR0", 14) 328 .WithTaggedFlag("FERR0", 15) 329 .WithTag("RXDATA1", 16, 8) 330 .WithReservedBits(24, 5) 331 .WithTaggedFlag("PERR1", 30) 332 .WithTaggedFlag("FERR1", 31); 333 GenerateRxBufferDoubleDataRegister()334 protected DoubleWordRegister GenerateRxBufferDoubleDataRegister() => new DoubleWordRegister(this) 335 .WithTag("RXDATA0", 0, 8) 336 .WithTag("RXDATA1", 8, 8) 337 .WithReservedBits(16, 16); 338 GenerateRxBufferDataExtendedPeekRegister()339 protected DoubleWordRegister GenerateRxBufferDataExtendedPeekRegister() => new DoubleWordRegister(this) 340 .WithTag("RXDATAP", 0, 8) 341 .WithReservedBits(8, 5) 342 .WithTaggedFlag("PERRP", 14) 343 .WithTaggedFlag("FERRP", 15) 344 .WithReservedBits(16, 16); 345 GenerateRxBufferDoubleDataExtendedPeekRegister()346 protected DoubleWordRegister GenerateRxBufferDoubleDataExtendedPeekRegister() => new DoubleWordRegister(this) 347 .WithTag("RXDATAP0", 0, 8) 348 .WithReservedBits(8, 5) 349 .WithTaggedFlag("PERRP0", 14) 350 .WithTaggedFlag("FERRP0", 15) 351 .WithTag("RXDATAP1", 16, 8) 352 .WithReservedBits(24, 5) 353 .WithTaggedFlag("PERRP1", 30) 354 .WithTaggedFlag("FERRP1", 31); 355 GenerateTxBufferDataExtendedRegister()356 protected DoubleWordRegister GenerateTxBufferDataExtendedRegister() => new DoubleWordRegister(this) 357 .WithTag("TXDATAX", 0, 8) 358 .WithReservedBits(8, 2) 359 .WithTaggedFlag("UBRXAT", 11) 360 .WithTaggedFlag("TXTRIAT", 12) 361 .WithTaggedFlag("TXBREAK", 13) 362 .WithTaggedFlag("TXDISAT", 14) 363 .WithTaggedFlag("RXENAT", 15) 364 .WithReservedBits(16, 16); 365 GenerateTxBufferDataRegister()366 protected DoubleWordRegister GenerateTxBufferDataRegister() => new DoubleWordRegister(this) 367 .WithValueField(0, 8, FieldMode.Write, writeCallback: (_, v) => HandleTxBufferData((byte)v), name: "TXDATA") 368 .WithReservedBits(8, 24); 369 GenerateTxBufferDoubleDataExtendedRegister()370 protected DoubleWordRegister GenerateTxBufferDoubleDataExtendedRegister() => new DoubleWordRegister(this) 371 .WithTag("TXDATA0", 0, 8) 372 .WithReservedBits(8, 2) 373 .WithTaggedFlag("UBRXAT0", 11) 374 .WithTaggedFlag("TXTRIAT0", 12) 375 .WithTaggedFlag("TXBREAK0", 13) 376 .WithTaggedFlag("TXDISAT0", 14) 377 .WithTaggedFlag("RXENAT0", 15) 378 .WithTag("TXDATA1", 16, 8) 379 .WithReservedBits(24, 2) 380 .WithTaggedFlag("UBRXAT1", 27) 381 .WithTaggedFlag("TXTRIAT1", 28) 382 .WithTaggedFlag("TXBREAK1", 29) 383 .WithTaggedFlag("TXDISAT1", 30) 384 .WithTaggedFlag("RXENAT1", 31); 385 GenerateTxBufferDoubleDataRegister()386 protected DoubleWordRegister GenerateTxBufferDoubleDataRegister() => new DoubleWordRegister(this) 387 .WithTag("TXDATA0", 0, 8) 388 .WithTag("TXDATA1", 8, 8) 389 .WithReservedBits(16, 16); 390 GenerateIrDAControlRegister()391 protected DoubleWordRegister GenerateIrDAControlRegister() => new DoubleWordRegister(this) 392 .WithTaggedFlag("IREN", 0) 393 .WithTag("IRPW", 1, 2) 394 .WithTaggedFlag("IRFILT", 3) 395 .WithReservedBits(4, 3) 396 .WithTaggedFlag("IRPRSEN", 7) 397 .WithTag("IRPRSSEL", 8, 4) 398 .WithReservedBits(12, 20); 399 GenerateUSARTInputRegister()400 protected DoubleWordRegister GenerateUSARTInputRegister() => new DoubleWordRegister(this) 401 .WithTag("RXPRSSEL", 0, 4) 402 .WithReservedBits(4, 3) 403 .WithTaggedFlag("RXPRS", 7) 404 .WithTag("CLKPRSSEL", 8, 4) 405 .WithReservedBits(12, 3) 406 .WithTaggedFlag("CLKPRS", 15) 407 .WithReservedBits(16, 16); 408 GenerateI2SControlRegister()409 protected DoubleWordRegister GenerateI2SControlRegister() => new DoubleWordRegister(this) 410 .WithTaggedFlag("EN", 0) 411 .WithTaggedFlag("MONO", 1) 412 .WithTaggedFlag("JUSTIFY", 2) 413 .WithTaggedFlag("DMASPLIT", 3) 414 .WithTaggedFlag("DELAY", 4) 415 .WithReservedBits(5, 3) 416 .WithTag("FORMAT", 8, 3) 417 .WithReservedBits(11, 21); 418 GenerateTimingRegister()419 protected DoubleWordRegister GenerateTimingRegister() => new DoubleWordRegister(this) 420 .WithReservedBits(0, 16) 421 .WithTag("TXDELAY", 16, 2) 422 .WithReservedBits(19, 1) 423 .WithTag("CSSETUP", 20, 3) 424 .WithReservedBits(23, 1) 425 .WithTag("ICS", 24, 3) 426 .WithReservedBits(27, 1) 427 .WithTag("CSHOLD", 28, 3) 428 .WithReservedBits(31, 1); 429 GenerateControlExtendedRegister()430 protected DoubleWordRegister GenerateControlExtendedRegister() => new DoubleWordRegister(this) 431 .WithTaggedFlag("DBHALT", 0) 432 .WithTaggedFlag("CTSINV", 1) 433 .WithTaggedFlag("CTSEN", 2) 434 .WithTaggedFlag("RTSINV", 3) 435 .WithReservedBits(4, 27) 436 .WithTaggedFlag("GPIODELAYXOREN", 31); 437 GenerateTimeCompare0Register()438 protected DoubleWordRegister GenerateTimeCompare0Register() => new DoubleWordRegister(this) 439 .WithTag("TCMPVAL", 0, 8) 440 .WithReservedBits(8, 8) 441 .WithTag("TSTART", 16, 3) 442 .WithReservedBits(19, 1) 443 .WithTag("TSTOP", 20, 3) 444 .WithReservedBits(23, 1) 445 .WithTaggedFlag("RESTARTEN", 24) 446 .WithReservedBits(25, 7); 447 GenerateTimeCompare1Register()448 protected DoubleWordRegister GenerateTimeCompare1Register() => new DoubleWordRegister(this) 449 .WithTag("TCMPVAL", 0, 8) 450 .WithReservedBits(8, 8) 451 .WithTag("TSTART", 16, 3) 452 .WithReservedBits(19, 1) 453 .WithTag("TSTOP", 20, 3) 454 .WithReservedBits(23, 1) 455 .WithTaggedFlag("RESTARTEN", 24) 456 .WithReservedBits(25, 7); 457 GenerateTimeCompare2Register()458 protected DoubleWordRegister GenerateTimeCompare2Register() => new DoubleWordRegister(this) 459 .WithTag("TCMPVAL", 0, 8) 460 .WithReservedBits(8, 8) 461 .WithTag("TSTART", 16, 3) 462 .WithReservedBits(19, 1) 463 .WithTag("TSTOP", 20, 3) 464 .WithReservedBits(23, 1) 465 .WithTaggedFlag("RESTARTEN", 24) 466 .WithReservedBits(25, 7); 467 GenerateTestRegister()468 protected DoubleWordRegister GenerateTestRegister() => new DoubleWordRegister(this) 469 .WithTaggedFlag("GPIODELAYSTABLE", 0) 470 .WithTaggedFlag("GPIODELAYXOR", 1) 471 .WithReservedBits(2, 30); 472 GenerateInterruptFlagRegister()473 protected DoubleWordRegister GenerateInterruptFlagRegister() => interruptsManager.GetMaskedInterruptFlagRegister<DoubleWordRegister>(); 474 GenerateInterruptEnableRegister()475 protected DoubleWordRegister GenerateInterruptEnableRegister() => interruptsManager.GetInterruptEnableRegister<DoubleWordRegister>(); 476 GenerateInterruptFlagSetRegister()477 protected DoubleWordRegister GenerateInterruptFlagSetRegister() => interruptsManager.GetInterruptSetRegister<DoubleWordRegister>(); 478 GenerateInterruptFlagClearRegister()479 protected DoubleWordRegister GenerateInterruptFlagClearRegister() => interruptsManager.GetInterruptClearRegister<DoubleWordRegister>(); 480 HandleTxBufferData(byte data)481 private void HandleTxBufferData(byte data) 482 { 483 if(!transmitterEnableFlag.Value) 484 { 485 this.Log(LogLevel.Warning, "Trying to send data, but the transmitter is disabled: 0x{0:X}", data); 486 return; 487 } 488 489 transferCompleteFlag.Value = false; 490 if(operationModeField.Value == OperationMode.Synchronous) 491 { 492 if(spiSlaveDevice != null) 493 { 494 var result = spiSlaveDevice.Transmit(data); 495 WriteChar(result); 496 } 497 else 498 { 499 this.Log(LogLevel.Warning, "Writing data in synchronous mode, but no device is currently connected."); 500 WriteChar(0x0); 501 } 502 } 503 else 504 { 505 interruptsManager.SetInterrupt(Interrupt.TransmitBufferLevel); 506 TransmitCharacter(data); 507 interruptsManager.SetInterrupt(Interrupt.TransmitComplete); 508 } 509 transferCompleteFlag.Value = true; 510 } 511 ReadBuffer()512 private byte ReadBuffer() 513 { 514 byte character; 515 return TryGetCharacter(out character) ? character : (byte)0; 516 } 517 518 private readonly InterruptManager<Interrupt> interruptsManager; 519 private IEnumRegisterField<OversamplingMode> oversamplingField; 520 private IEnumRegisterField<OperationMode> operationModeField; 521 private IEnumRegisterField<Parity> parityBitModeField; 522 private IEnumRegisterField<Bits> stopBitsModeField; 523 private IValueRegisterField fractionalClockDividerField; 524 private IFlagRegisterField transferCompleteFlag; 525 private IFlagRegisterField receiveDataValidFlag; 526 private IFlagRegisterField receiverEnableFlag; 527 private IFlagRegisterField transmitterEnableFlag; 528 private readonly uint uartClockFrequency; 529 private ISPIPeripheral spiSlaveDevice; 530 private BufferState bufferState; 531 532 private const int BufferSize = 3; // with shift register 533 534 private enum OperationMode 535 { 536 Asynchronous, 537 Synchronous 538 } 539 540 private enum OversamplingMode 541 { 542 Times16, 543 Times8, 544 Times6, 545 Times4 546 } 547 548 private enum Interrupt 549 { 550 [Subvector(0)] 551 TransmitComplete, 552 [Subvector(0), NotSettable] 553 TransmitBufferLevel, 554 [Subvector(1), NotSettable] 555 ReceiveDataValid, 556 [Subvector(1)] 557 ReceiveBufferFull, 558 [Subvector(1)] 559 ReceiveOverflow, 560 [Subvector(1)] 561 ReceiveUnderflow, 562 [Subvector(0)] 563 TransmitOverflow, 564 [Subvector(0)] 565 TransmitUnderflow, 566 [Subvector(1)] 567 ParityError, 568 [Subvector(1)] 569 FramingError, 570 [Subvector(1)] 571 MultiProcessorAddressFrame, 572 [Subvector(1)] 573 SlaveSelectInMasterMode, 574 [Subvector(0)] 575 CollisionCheckFail, 576 [Subvector(0)] 577 TransmitIdle, 578 [Subvector(1)] 579 TimerComparator0, 580 [Subvector(1)] 581 TimerComparator1, 582 [Subvector(1)] 583 TimerComparator2 584 } 585 } 586 }