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.Collections.ObjectModel; 10 using System.Linq; 11 using Antmicro.Renode.Core; 12 using Antmicro.Renode.Core.Structure.Registers; 13 using Antmicro.Renode.Logging; 14 using Antmicro.Renode.Peripherals.SPI; 15 using Antmicro.Renode.Peripherals.Wireless.IEEE802_15_4; 16 using Antmicro.Renode.Utilities; 17 18 namespace Antmicro.Renode.Peripherals.Wireless 19 { 20 public sealed class CC2520: IRadio, ISPIPeripheral, INumberedGPIOOutput, IGPIOReceiver 21 { CC2520()22 public CC2520() 23 { 24 CreateRegisters(); 25 RegisterInstructions(); 26 var dict = new Dictionary<int, IGPIO>(); 27 for(var i = 0; i < NumberOfGPIOs; ++i) 28 { 29 dict[i] = new GPIO(); 30 } 31 Connections = new ReadOnlyDictionary<int, IGPIO>(dict); 32 Reset(); 33 } 34 Reset()35 public void Reset() 36 { 37 isRxEnabled = false; 38 inReset = true; 39 vregEnabled = false; 40 oscillatorRunning = false; 41 wasLastFrameSent = false; 42 43 currentFrame = null; 44 45 txFifo.Clear(); 46 rxFifo.Clear(); 47 memory = new byte[GeneralMemorySize]; 48 sourceAddressTable = new byte[SourceAddressTableSize]; 49 sourceAddressMatchingResult = new byte[SourceAddressMatchingResultSize]; 50 sourceAddressMatchingControl = new byte[SourceAddressMatchingControlSize]; 51 localAddressInfo = new byte[LocalAddressInfoSize]; 52 53 localExtendedAddress = new Address(new ArraySegment<byte>(localAddressInfo, 0, 8)); 54 localShortAddress = new Address(new ArraySegment<byte>(localAddressInfo, 10, 2)); 55 56 currentInstruction = null; 57 58 registers.Reset(); 59 foreach(var gpio in Connections.Values) 60 { 61 gpio.Unset(); 62 } 63 } 64 OnGPIO(int number, bool value)65 public void OnGPIO(int number, bool value) 66 { 67 const int voltageRegulatorEnable = 0; 68 const int notReset = 1; 69 if(number == notReset) 70 { 71 inReset = !value; 72 if(!inReset) 73 { 74 oscillatorRunning = true; 75 } 76 } 77 else if(number == voltageRegulatorEnable) 78 { 79 vregEnabled = value; 80 } 81 else 82 { 83 //we don't want to accidentally reset on another input 84 return; 85 } 86 if(inReset && !vregEnabled) 87 { 88 this.Log(LogLevel.Debug, "Resetting radio..."); 89 Reset(); 90 } 91 UpdateInterrupts(); 92 } 93 Irqs()94 public bool[] Irqs() 95 { 96 return Connections.Values.Select(x => x.IsSet).ToArray(); 97 } 98 Transmit(byte data)99 public byte Transmit(byte data) 100 { 101 this.Log(LogLevel.Noisy, "Writing to radio: 0x{0:X}", data); 102 if(currentInstruction == null) 103 { 104 if(!decoderRoot.TryParseOpcode(data, out currentInstruction)) 105 { 106 this.Log(LogLevel.Error, "Cannot find opcode in value 0b{0} (0x{1:X})".FormatWith(Convert.ToString(data, 2).PadLeft(8,'0'), data)); 107 return 0; 108 } 109 this.Log(LogLevel.Debug, "Setting command to: {0}", currentInstruction.Name); 110 } 111 var returnValue = currentInstruction.Parse(data); 112 if(currentInstruction.IsFinished) 113 { 114 currentInstruction = null; 115 } 116 return returnValue; 117 } 118 FinishTransmission()119 public void FinishTransmission() 120 { 121 currentInstruction = null; 122 this.Log(LogLevel.Debug, "Finish transmission"); 123 } 124 ReceiveFrame(byte[] bytes, IRadio sender)125 public void ReceiveFrame(byte[] bytes, IRadio sender) 126 { 127 if(isRxEnabled) 128 { 129 //this allows to have proper CCA values easily. 130 currentFrame = bytes; 131 HandleFrame(bytes); 132 currentFrame = null; 133 } 134 else 135 { 136 currentFrame = bytes; 137 this.DebugLog("Radio is not listening right now - this frame is being deffered."); 138 } 139 } 140 141 public int Channel 142 { 143 get 144 { 145 return ChannelValueFromFrequency((uint)channel.Value); 146 } 147 148 set 149 { 150 this.Log(LogLevel.Info, "Setting channel to {0}", value); 151 channel.Value = ChannelNumberToFrequency(value); 152 } 153 } 154 155 public IReadOnlyDictionary<int, IGPIO> Connections 156 { 157 get; private set; 158 } 159 160 public event Action<IRadio, byte[]> FrameSent; 161 HandleFrame(byte[] bytes)162 private void HandleFrame(byte[] bytes) 163 { 164 Frame ackFrame = null; 165 166 SetException(ExceptionFlags.StartOfFrameDelimiter); 167 var frame = new Frame(bytes); 168 var isCrcOk = frame.CheckCRC(); 169 170 var autoPendingResult = false; 171 byte sourceMatchingIndex = NoSourceIndex; 172 173 if(frameFilteringEnabled.Value) 174 { 175 if(!ShouldAcceptFrame(frame)) 176 { 177 this.Log(LogLevel.Debug, "Not accepting the frame"); 178 return; 179 } 180 SetException(ExceptionFlags.RxFrameAccepted); 181 182 if(sourceMatchingEnabled.Value) 183 { 184 //algorithm described in the docs, chapter 20.3.3 185 var sourceMatchingMask = 0u; 186 if(frame.SourceAddressingMode == AddressingMode.ShortAddress) 187 { 188 uint sourceMatchingShortEnabled = (uint)((shortAddressMatchingEnabled[2].Value << 16) | (shortAddressMatchingEnabled[1].Value << 8) | shortAddressMatchingEnabled[0].Value); 189 for(byte i = 0; i < 24; ++i) 190 { 191 var mask = 1u << i; 192 if((sourceMatchingShortEnabled & mask) == 0) 193 { 194 continue; 195 } 196 if(frame.AddressInformation.SourcePan == GetSourceAddressMatchingPanId(i) 197 && frame.AddressInformation.SourceAddress.GetValue() == GetSourceAddressMatchingShortAddress(i)) 198 { 199 sourceMatchingMask |= mask; 200 if(sourceMatchingIndex == NoSourceIndex) 201 { 202 autoPendingResult = VerifyAutoPending(frame.SourceAddressingMode, frame.Type, i); 203 sourceMatchingIndex = (byte)(i | (autoPendingResult ? 1 << 6 : 0)); 204 } 205 } 206 } 207 } 208 else if(frame.SourceAddressingMode == AddressingMode.ExtendedAddress) 209 { 210 uint sourceMatchingExtendedEnabled = (uint)((extendedAddressMatchingEnabled[2].Value << 16) | (extendedAddressMatchingEnabled[1].Value << 8) | extendedAddressMatchingEnabled[0].Value); 211 for(byte i = 0; i < 12; ++i) 212 { 213 var mask = 3u << (2 * i); 214 if((sourceMatchingExtendedEnabled & mask) == 0) 215 { 216 continue; 217 } 218 if(frame.AddressInformation.SourceAddress.GetValue() == GetSourceAddressMatchingExtendedAddress(i)) 219 { 220 sourceMatchingMask |= mask; 221 if(sourceMatchingIndex == NoSourceIndex) 222 { 223 autoPendingResult = VerifyAutoPending(frame.SourceAddressingMode, frame.Type, i); 224 sourceMatchingIndex = (byte)(i | 0x20 | (autoPendingResult ? 1 << 6 : 0)); 225 } 226 } 227 } 228 } 229 BitConverter.GetBytes(sourceMatchingMask).CopyTo(sourceAddressMatchingResult, 0); 230 sourceAddressMatchingResult[3] = sourceMatchingIndex; 231 SetException(ExceptionFlags.SourceMatchingDone); 232 if(sourceMatchingIndex != NoSourceIndex) 233 { 234 SetException(ExceptionFlags.SourceMatchingFound); 235 } 236 } 237 } 238 if(autoCrc.Value) 239 { 240 byte secondByte = 0; 241 if(isCrcOk) 242 { 243 secondByte |= 1 << 7; 244 } 245 if(appendDataMode.Value) 246 { 247 //Theoretically sourceMatchingIndex might not be valid here if the matching was not performed. 248 //This set of conditions is defined in the docs, though. 249 secondByte |= sourceMatchingIndex; 250 } 251 else 252 { 253 secondByte |= 100; // correlation value 100 means near maximum quality 254 } 255 frame.Bytes[frame.Bytes.Length - 2] = 70; //as in CC2538 256 frame.Bytes[frame.Bytes.Length - 1] = secondByte; 257 } 258 rxFifo.Enqueue(frame.Length); 259 foreach(var item in frame.Bytes) 260 { 261 rxFifo.Enqueue(item); 262 } 263 //Not filtering for length because a full frame was received. This might be an issue in a more general sense, as we do not support partial frames. 264 SetException(ExceptionFlags.FifoThresholdReached); 265 266 SetException(ExceptionFlags.RxFrameDone); 267 if(isCrcOk && autoAck.Value 268 && frame.AcknowledgeRequest 269 && frame.Type != FrameType.Beacon 270 && frame.Type != FrameType.ACK) 271 { 272 ackFrame = Frame.CreateACK(frame.DataSequenceNumber, autoPendingResult || pendingAlwaysOn.Value); 273 } 274 var frameSent = FrameSent; 275 if(frameSent != null && ackFrame != null) 276 { 277 frameSent(this, ackFrame.Bytes); 278 SetException(ExceptionFlags.TxAckDone); 279 } 280 } 281 VerifyAutoPending(AddressingMode mode, FrameType type, byte i)282 bool VerifyAutoPending(AddressingMode mode, FrameType type, byte i) 283 { 284 if(!autoPendingFlag.Value) 285 { 286 return false; 287 } 288 if(pendingDataRequestOnly.Value && type != FrameType.Data) 289 { 290 return false; 291 } 292 var index = i / 8; 293 var position = (byte)(i % 8); 294 if(mode == AddressingMode.ShortAddress) 295 { 296 //first three bytes are for extended addresses, then three short addresses 297 index += 3; 298 } 299 return BitHelper.IsBitSet(sourceAddressMatchingControl[index], position); 300 } 301 GetSourceAddressMatchingPanId(int i)302 private ushort GetSourceAddressMatchingPanId(int i) 303 { 304 return BitConverter.ToUInt16(sourceAddressTable, 4 * i); 305 } 306 GetSourceAddressMatchingShortAddress(int i)307 private ushort GetSourceAddressMatchingShortAddress(int i) 308 { 309 return BitConverter.ToUInt16(sourceAddressTable, 4 * i + 2); 310 } 311 GetSourceAddressMatchingExtendedAddress(int i)312 private ulong GetSourceAddressMatchingExtendedAddress(int i) 313 { 314 return BitConverter.ToUInt64(sourceAddressTable, 8 * i); 315 } 316 ShouldAcceptFrame(Frame frame)317 private bool ShouldAcceptFrame(Frame frame) 318 { 319 var frameType = frame.Type; 320 switch(modifyFrameTypeFilter.Value) 321 { 322 case ModifyFieldTypeMode.InvertMSB: 323 frameType = (FrameType)((int)frameType ^ 4); 324 break; 325 case ModifyFieldTypeMode.SetMSB: 326 frameType = (FrameType)((int)frameType | 4); 327 break; 328 case ModifyFieldTypeMode.UnsetMSB: 329 frameType = (FrameType)((int)frameType & 3); 330 break; 331 } 332 333 //1. Check minimum frame length 334 //2. Check reserved FCF bits 335 if((((frame.FrameControlField >> 7) & 7) & frameControlFieldReservedMask.Value) != 0) 336 { 337 this.Log(LogLevel.Noisy, "Wrong FCF reserved field. Dropping frame."); 338 return false; 339 } 340 341 //3. Check frame version 342 if(frame.FrameVersion > maxFrameVersion.Value) 343 { 344 this.Log(LogLevel.Noisy, "Frame version too high. Got 0x{0:X}, expected at most 0x{1:X}. Dropping frame.", frame.FrameVersion, maxFrameVersion.Value); 345 return false; 346 } 347 348 //4. Check address modes 349 if(frame.SourceAddressingMode == AddressingMode.Reserved) 350 { 351 this.Log(LogLevel.Noisy, "Reserved source addressing mode. Dropping frame."); 352 return false; 353 } 354 if(frame.DestinationAddressingMode == AddressingMode.Reserved) 355 { 356 this.Log(LogLevel.Noisy, "Reserved destination addressing mode. Dropping frame."); 357 return false; 358 } 359 360 //5. Check destination address 361 if(frame.DestinationAddressingMode != AddressingMode.None) 362 { 363 //this IntraPAN is kind of a guess. We could use source PAN Id instead, but the documentation says clearly: "If a destination PAN ID is included in the frame" 364 if(!frame.IntraPAN && frame.AddressInformation.DestinationPan != GetPanId() && frame.AddressInformation.DestinationPan != BroadcastPanIdentifier) 365 { 366 this.Log(LogLevel.Noisy, "Invalid destination PAN: got 0x{0:X}, expected 0x{1:X} or 0x{2:X}. Dropping frame.", frame.AddressInformation.DestinationPan, GetPanId(), BroadcastPanIdentifier); 367 return false; 368 } 369 if(frame.DestinationAddressingMode == AddressingMode.ShortAddress) 370 { 371 if(!frame.AddressInformation.DestinationAddress.IsShortBroadcast && !frame.AddressInformation.DestinationAddress.Equals(localShortAddress)) 372 { 373 this.Log(LogLevel.Noisy, "Invalid destination short address (I'm {0}, but the message is directed to {1}). Dropping frame.", localShortAddress.GetValue(), frame.AddressInformation.DestinationAddress.GetValue()); 374 return false; 375 } 376 } 377 // (5.3) check destination extended address 378 else if(frame.DestinationAddressingMode == AddressingMode.ExtendedAddress) 379 { 380 if(!frame.AddressInformation.DestinationAddress.Equals(localExtendedAddress)) 381 { 382 this.Log(LogLevel.Noisy, "Invalid destination extended address (I'm {0}, but the message is directed to {1}). Dropping frame.", localExtendedAddress.GetValue(), frame.AddressInformation.DestinationAddress.GetValue()); 383 return false; 384 } 385 } 386 } 387 //6. Check frame type 388 switch(frameType) 389 { 390 case FrameType.Beacon: 391 if(!acceptBeaconFrames.Value 392 || frame.Length < 9 393 || frame.DestinationAddressingMode != AddressingMode.None 394 || (frame.SourceAddressingMode != AddressingMode.ShortAddress && frame.SourceAddressingMode != AddressingMode.ExtendedAddress) 395 || (frame.AddressInformation.SourcePan != BroadcastPanIdentifier && frame.AddressInformation.SourcePan != GetPanId())) 396 { 397 this.Log(LogLevel.Noisy, "Beacon frame not accepted. Dropping frame."); 398 return false; 399 } 400 break; 401 case FrameType.Data: 402 if(!acceptDataFrames.Value 403 || frame.Length < 9 404 || (frame.DestinationAddressingMode == AddressingMode.None && frame.SourceAddressingMode == AddressingMode.None) 405 || (frame.DestinationAddressingMode == AddressingMode.None 406 && (!panCoordinator.Value || frame.AddressInformation.SourcePan != GetPanId()))) 407 { 408 this.Log(LogLevel.Noisy, "Data frame not accepted. Dropping frame."); 409 return false; 410 } 411 break; 412 case FrameType.ACK: 413 if(!acceptAckFrames.Value || frame.Length != 5) 414 { 415 this.Log(LogLevel.Noisy, "ACK frame not accepted. Dropping frame."); 416 return false; 417 } 418 break; 419 case FrameType.MACControl: 420 if(!acceptMacCommandFrames.Value 421 || frame.Length < 9 422 || (frame.DestinationAddressingMode == AddressingMode.None 423 && (!panCoordinator.Value || frame.AddressInformation.SourcePan != GetPanId()))) 424 { 425 this.Log(LogLevel.Noisy, "MAC control frame not accepted. Dropping frame."); 426 return false; 427 } 428 break; 429 default: 430 if(!acceptReservedFrames.Value || frame.Length < 9) 431 { 432 this.Log(LogLevel.Noisy, "Reserved frame not accepted. Dropping frame."); 433 return false; 434 } 435 break; 436 } 437 return true; 438 } 439 SendFrame()440 private void SendFrame() 441 { 442 var length = txFifo.Peek(); 443 var data = txFifo.Skip(1).ToArray(); 444 Frame frame; 445 if(autoCrc.Value) 446 { 447 var crc = Frame.CalculateCRC(data); 448 frame = new Frame(data.Concat(crc).ToArray()); 449 } 450 else 451 { 452 frame = new Frame(data); 453 } 454 if(length > frame.Length && !ignoreTxUnderflow.Value) 455 { 456 SetException(ExceptionFlags.TxUnderflow); 457 this.Log(LogLevel.Warning, "Frame dropped because of TX underflow. Expected length: {0}. Frame length: {1}.", length, frame.Length); 458 return; 459 //ignoreTxUnderflow should probably transmit whatever data is written to the tx fifo after this transfer. This would be difficult to model, as we do not support "wrong" frames yet. 460 } 461 this.DebugLog("Sending frame {0}.", frame.Bytes.Select(x => "0x{0:X}".FormatWith(x)).Stringify()); 462 var frameSent = FrameSent; 463 if(frameSent != null) 464 { 465 frameSent(this, frame.Bytes); 466 } 467 wasLastFrameSent = true; 468 SetException(ExceptionFlags.StartOfFrameDelimiter); 469 SetException(ExceptionFlags.TxFrameDone); 470 } 471 SetException(ExceptionFlags flag)472 private void SetException(ExceptionFlags flag) 473 { 474 var regNumber = (int)flag / 8; 475 var bit = (int)flag % 8; 476 this.Log(LogLevel.Noisy, "Setting flag {0}", flag); 477 pendingExceptionFlag[regNumber].Value |= 1u << bit; 478 UpdateInterrupts(); 479 } 480 UnsetException(ExceptionFlags flag)481 private void UnsetException(ExceptionFlags flag) 482 { 483 var regNumber = (int)flag / 8; 484 var bit = (int)flag % 8; 485 this.Log(LogLevel.Noisy, "Unsetting flag {0}", flag); 486 pendingExceptionFlag[regNumber].Value &= ~(1u << bit); 487 UpdateInterrupts(); 488 } 489 IsExceptionSet(ExceptionFlags flag)490 private bool IsExceptionSet(ExceptionFlags flag) 491 { 492 var regNumber = (int)flag / 8; 493 var bit = (int)flag % 8; 494 return (pendingExceptionFlag[regNumber].Value & (1u << bit)) != 0; 495 } 496 UpdateInterrupts()497 private void UpdateInterrupts() 498 { 499 Connections[(int)GPIOs.Cca].Set(currentFrame == null); 500 Connections[(int)GPIOs.Sfd].Set(IsExceptionSet(ExceptionFlags.StartOfFrameDelimiter)); 501 Connections[(int)GPIOs.Fifop].Set(IsExceptionSet(ExceptionFlags.FifoThresholdReached)); 502 Connections[(int)GPIOs.Fifo].Set(rxFifo.Count > 0 && rxFifo.Count <= RxFifoMemorySize); 503 } 504 GetStatus()505 private byte GetStatus() 506 { 507 return (byte)(((oscillatorRunning ? 1 : 0) << 7) 508 | ((isRxEnabled ? 1 : 0) << 6) 509 | ((currentInstruction != null && currentInstruction.HighPriority.HasValue && currentInstruction.HighPriority.Value ? 1 : 0) << 3) 510 | ((currentInstruction != null && currentInstruction.HighPriority.HasValue && !currentInstruction.HighPriority.Value ? 1 : 0) << 2) 511 | ((isRxEnabled ? 1 : 0) << 0)); 512 //bits 0 and 1 are responsible for RX/TX states. TX is active after STXON[CCA] command, so it's not interruptible with GetStatus read. 513 //RX is active when isRxEnabled == true, but TX is not active. Again, since cpu will not get status on TX, we ignore the second condition. 514 //DPU bits are mutually exclusive at the moment, but we should implement priorities someday, so I leave them as independent. 515 //EXCEPTION channel A and B bits should be implemented 516 //RSSI is always assumed to be valid in RX mode 517 } 518 GetPanId()519 private uint GetPanId() 520 { 521 return (uint)((localAddressInfo[9] << 8) | localAddressInfo[8]); 522 } 523 ChannelValueFromFrequency(uint frequency)524 private int ChannelValueFromFrequency(uint frequency) 525 { 526 //According to documentation, chapter 16: 527 //"Channels are numbered 11 through 26 and are 5MHz apart" 528 return ((int)frequency - 11) / 5 + 11; 529 } 530 ChannelNumberToFrequency(int channelNumber)531 private uint ChannelNumberToFrequency(int channelNumber) 532 { 533 //According to documentation, chapter 16: 534 //"Channels are numbered 11 through 26 and are 5MHz apart" 535 return (uint)(11 + 5 * (channelNumber - 11)); 536 } 537 CreateRegisters()538 private void CreateRegisters() 539 { 540 var dict = new Dictionary<long, ByteRegister> 541 { 542 {(long)Registers.FrameFiltering0, new ByteRegister(this, 0xD) 543 .WithValueField(4, 3, out frameControlFieldReservedMask, name: "FCF_RESERVED_MASK") 544 .WithValueField(2, 2, out maxFrameVersion, name: "MAX_FRAME_VERSION") 545 .WithFlag(1, out panCoordinator, name: "PAN_COORDINATOR") 546 .WithFlag(0, out frameFilteringEnabled, name: "FRAME_FILTER_EN") 547 }, 548 {(long)Registers.FrameFiltering1, new ByteRegister(this, 0x78) 549 .WithFlag(7, out acceptReservedFrames, name: "ACCEPT_FT_4TO7_RESERVED") 550 .WithFlag(6, out acceptMacCommandFrames, name: "ACCEPT_FT_3_MAC_CMD") 551 .WithFlag(5, out acceptAckFrames, name: "ACCEPT_FT_2_ACK") 552 .WithFlag(4, out acceptDataFrames, name: "ACCEPT_FT_1_DATA") 553 .WithFlag(3, out acceptBeaconFrames, name: "ACCEPT_FT_0_BEACON") 554 .WithEnumField(1, 2, out modifyFrameTypeFilter, name: "MODIFY_FT_FILTER") 555 }, 556 {(long)Registers.SourceMatching, new ByteRegister(this, 0x7) 557 .WithFlag(2, out pendingDataRequestOnly, name: "PEND_DATAREQ_ONLY") 558 .WithFlag(1, out autoPendingFlag, name: "AUTOPEND") 559 .WithFlag(0, out sourceMatchingEnabled, name: "SRC_MATCH_EN") 560 }, 561 {(long)Registers.ShortAddressMatchingEnabled0, new ByteRegister(this) 562 .WithValueField(0, 8, out shortAddressMatchingEnabled[0], name: "SHORT_ADDR_EN[7:0]") 563 }, 564 {(long)Registers.ShortAddressMatchingEnabled1, new ByteRegister(this) 565 .WithValueField(0, 8, out shortAddressMatchingEnabled[1], name: "SHORT_ADDR_EN[15:8]") 566 }, 567 {(long)Registers.ShortAddressMatchingEnabled2, new ByteRegister(this) 568 .WithValueField(0, 8, out shortAddressMatchingEnabled[2], name: "SHORT_ADDR_EN[23:16]") 569 }, 570 {(long)Registers.ExtendedAddressMatchingEnabled0, new ByteRegister(this) 571 .WithValueField(0, 8, out extendedAddressMatchingEnabled[0], name: "EXT_ADDR_EN[7:0]") 572 }, 573 {(long)Registers.ExtendedAddressMatchingEnabled1, new ByteRegister(this) 574 .WithValueField(0, 8, out extendedAddressMatchingEnabled[1], name: "EXT_ADDR_EN[15:8]") 575 }, 576 {(long)Registers.ExtendedAddressMatchingEnabled2, new ByteRegister(this) 577 .WithValueField(0, 8, out extendedAddressMatchingEnabled[2], name: "EXT_ADDR_EN[23:16]") 578 }, 579 {(long)Registers.FrameControl0, new ByteRegister(this, 0x40) 580 .WithFlag(7, out appendDataMode, name: "APPEND_DATA_MODE") 581 .WithFlag(6, out autoCrc, name: "AUTOCRC") 582 .WithFlag(5, out autoAck, name: "AUTOACK") 583 .WithTag("ENERGY_SCAN", 4, 1) 584 .WithTag("RX_MODE", 2, 2) //I doubt these two will be useful, they are test modes 585 .WithTag("TX_MODE", 0, 2) 586 }, 587 {(long)Registers.FrameControl1, new ByteRegister(this, 0x1) 588 .WithFlag(2, out pendingAlwaysOn, name: "PENDING_OR") 589 .WithFlag(1, out ignoreTxUnderflow, name: "IGNORE_TX_UNDERF") 590 .WithTag("SET_RXENMASK_ON_TX", 0, 1) 591 }, 592 {(long)Registers.PendingExceptionFlags0, new ByteRegister(this) 593 .WithValueField(0, 8, out pendingExceptionFlag[0], FieldMode.Read | FieldMode.WriteZeroToClear, name: "EXCFLAG0") 594 }, 595 {(long)Registers.PendingExceptionFlags1, new ByteRegister(this) 596 .WithValueField(0, 8, out pendingExceptionFlag[1], FieldMode.Read | FieldMode.WriteZeroToClear, name: "EXCFLAG1") 597 }, 598 {(long)Registers.PendingExceptionFlags2, new ByteRegister(this) 599 .WithValueField(0, 8, out pendingExceptionFlag[2], FieldMode.Read | FieldMode.WriteZeroToClear, name: "EXCFLAG2") 600 }, 601 {(long)Registers.ExceptionMaskA0, new ByteRegister(this) 602 .WithValueField(0, 8, out pendingExceptionMaskA[0], name: "EXCMASKA0") 603 }, 604 {(long)Registers.ExceptionMaskA1, new ByteRegister(this) 605 .WithValueField(0, 8, out pendingExceptionMaskA[1], name: "EXCMASKA1") 606 }, 607 {(long)Registers.ExceptionMaskA2, new ByteRegister(this) 608 .WithValueField(0, 8, out pendingExceptionMaskA[2], name: "EXCMASKA2") 609 }, 610 {(long)Registers.ExceptionMaskB0, new ByteRegister(this) 611 .WithValueField(0, 8, out pendingExceptionMaskB[0], name: "EXCMASKB0") 612 }, 613 {(long)Registers.ExceptionMaskB1, new ByteRegister(this) 614 .WithValueField(0, 8, out pendingExceptionMaskB[1], name: "EXCMASKB1") 615 }, 616 {(long)Registers.ExceptionMaskB2, new ByteRegister(this) 617 .WithValueField(0, 8, out pendingExceptionMaskB[2], name: "EXCMASKB2") 618 }, 619 {(long)Registers.FrequencyControl, new ByteRegister(this, 0x0B) 620 .WithValueField(0, 7, out channel, changeCallback: (_, chanVal) => this.Log(LogLevel.Info, "Setting channel to {0}", ChannelValueFromFrequency((uint)chanVal)), name: "FREQ") 621 }, 622 {(long)Registers.TxPower, new ByteRegister(this, 0x6) 623 .WithValueField(0, 8, name: "PA_POWER") 624 }, 625 {(long)Registers.FifoPControl, new ByteRegister(this, 0x40) 626 .WithValueField(0, 7, out fifopThreshold, name: "FIFOP_THR") 627 }, 628 {(long)Registers.CCAThreshold, new ByteRegister(this, 0xE0) 629 .WithValueField(0, 8, name: "CCA_THR") 630 }, 631 {(long)Registers.RSSIValidStatus, new ByteRegister(this) 632 .WithFlag(0, FieldMode.Read, valueProviderCallback: (_) => isRxEnabled, name: "RSSISTAT") 633 }, 634 {(long)Registers.RxFirstByte, new ByteRegister(this) 635 .WithValueField(0, 8, FieldMode.Read, valueProviderCallback: (_) => rxFifo.Count == 0 ? 0u : rxFifo.Peek(), name: "RXFIRST") 636 }, 637 {(long)Registers.RxFifoCount, new ByteRegister(this) 638 .WithValueField(0, 8, FieldMode.Read, valueProviderCallback: (_) => (byte)rxFifo.Count, name: "RXFIFOCNT") 639 }, 640 {(long)Registers.TxFifoCount, new ByteRegister(this) 641 .WithValueField(0, 8, FieldMode.Read, valueProviderCallback: (_) => (byte)txFifo.Count, name: "TXFIFOCNT") 642 }, 643 {(long)Registers.ChipId, new ByteRegister(this, 0x84) 644 .WithValueField(0, 8, FieldMode.Read, name: "CHIPID") 645 }, 646 {(long)Registers.ExternalClock, new ByteRegister(this, 0x20) 647 .WithTag("EXTCLOCK_EN", 5, 1) //if this is set and we have a gpio configured for external clock, then it means we need an internal timer implemented here. 648 .WithValueField(0, 5, name: "EXT_FREQ") 649 }, 650 {(long)Registers.ModemControl0, new ByteRegister(this, 0x45) 651 .WithValueField(6, 2, name: "DEM_NUM_ZEROS") 652 .WithTag("DEMOD_AVG_MODE", 5, 1) 653 .WithTag("PREAMBLE_LENGTH", 1, 4) 654 .WithTag("TX_FILTER", 0, 1) 655 }, 656 {(long)Registers.ModemControl1, new ByteRegister(this, 0x2E) 657 .WithFlag(5, name: "CORR_THR_SFD") 658 .WithValueField(0, 4, name: "CORR_THR") 659 }, 660 {(long)Registers.RxModuleTuning, new ByteRegister(this, 0x29) 661 .WithValueField(0, 8) 662 }, 663 {(long)Registers.SynthesizerTuning, new ByteRegister(this, 0x55) 664 .WithValueField(0, 8) 665 }, 666 {(long)Registers.VCOTuning1, new ByteRegister(this, 0x29) 667 .WithValueField(0, 8) 668 }, 669 {(long)Registers.AGCTuning1, new ByteRegister(this, 0xE) 670 .WithValueField(0, 8) 671 }, 672 {(long)Registers.ADCTest0, new ByteRegister(this, 0x66) 673 .WithValueField(0, 8) 674 }, 675 {(long)Registers.ADCTest1, new ByteRegister(this, 0xA) 676 .WithValueField(0, 8) 677 }, 678 {(long)Registers.ADCTest2, new ByteRegister(this, 0x5) 679 .WithValueField(0, 8) 680 }, 681 }; 682 registers = new ByteRegisterCollection(this, dict); 683 } 684 ReadMemory(uint address)685 private byte ReadMemory(uint address) 686 { 687 byte value = 0; 688 if(address < RegisterMemorySize) 689 { 690 if(!registers.TryRead(address, out value)) 691 { 692 this.Log(LogLevel.Warning, "Failed to read register {0}", (Registers)address); 693 if((address >= 0x64 && address <= 0x79)) 694 { 695 //Other addresses do not trigger the exception 696 SetException(ExceptionFlags.MemoryAddressError); 697 } 698 return 0; 699 } 700 this.Log(LogLevel.Debug, "Successfully read register {0}, value 0x{1:X}", (Registers)address, value); 701 } 702 else if(address >= TxFifoMemoryStart && address < TxFifoMemoryStart + TxFifoMemorySize) 703 { 704 this.Log(LogLevel.Error, "Direct access to txFifo is not supported. Trying to access 0x{0:X}", address); 705 } 706 else if(address >= RxFifoMemoryStart && address < RxFifoMemoryStart + RxFifoMemorySize) 707 { 708 this.Log(LogLevel.Error, "Direct access to rxFifo is not supported. Trying to access 0x{0:X}", address); 709 } 710 else if(address >= GeneralMemoryStart && address < GeneralMemoryStart + GeneralMemorySize) 711 { 712 value = memory[address - GeneralMemoryStart]; 713 this.Log(LogLevel.Debug, "Read memory 0x{0:X}, value 0x{1:X}", address, value); 714 } 715 else if(address >= SourceAddressTableStart && address < SourceAddressTableStart + SourceAddressTableSize) 716 { 717 value = sourceAddressTable[address - SourceAddressTableStart]; 718 this.Log(LogLevel.Debug, "Read sourceAddressTable 0x{0:X}, value 0x{1:X}", address, value); 719 } 720 else if(address >= SourceAddressMatchingResultStart && address < SourceAddressMatchingResultStart + SourceAddressMatchingResultSize) 721 { 722 value = sourceAddressMatchingResult[address - SourceAddressMatchingResultStart]; 723 this.Log(LogLevel.Debug, "Read sourceAddressMatchingResult 0x{0:X}, value 0x{1:X}", address, value); 724 } 725 else if(address >= SourceAddressMatchingControlStart && address < SourceAddressMatchingControlStart + SourceAddressMatchingControlSize) 726 { 727 value = sourceAddressMatchingControl[address - SourceAddressMatchingControlStart]; 728 this.Log(LogLevel.Debug, "Read sourceAddressMatchingControl 0x{0:X}, value 0x{1:X}", address, value); 729 } 730 else if(address >= LocalAddressInfoStart && address < LocalAddressInfoStart + LocalAddressInfoSize) 731 { 732 value = localAddressInfo[address - LocalAddressInfoStart]; 733 this.Log(LogLevel.Debug, "Read localAddressInfo 0x{0:X}, value 0x{1:X}", address, value); 734 } 735 else 736 { 737 SetException(ExceptionFlags.MemoryAddressError); 738 } 739 return value; 740 } 741 WriteMemory(uint address, byte value)742 private void WriteMemory(uint address, byte value) 743 { 744 if(address < RegisterMemorySize) 745 { 746 if(!registers.TryWrite(address, value)) 747 { 748 this.Log(LogLevel.Warning, "Failed to write register {0}, value 0x{1:X}", (Registers)address, value); 749 if((address >= 0x64 && address <= 0x79)) 750 { 751 //Other addresses do not trigger the exception 752 SetException(ExceptionFlags.MemoryAddressError); 753 } 754 } 755 this.Log(LogLevel.Debug, "Successfully written register {0}, value 0x{1:X}", (Registers)address, value); 756 } 757 else if(address >= TxFifoMemoryStart && address < TxFifoMemoryStart + TxFifoMemorySize) 758 { 759 this.Log(LogLevel.Error, "Direct access to txFifo is not supported. Trying to access 0x{0:X}, value 0x{1:X}", address, value); 760 } 761 else if(address >= RxFifoMemoryStart && address < RxFifoMemoryStart + RxFifoMemorySize) 762 { 763 this.Log(LogLevel.Error, "Direct access to rxFifo is not supported. Trying to access 0x{0:X}, value 0x{1:X}", address, value); 764 } 765 else if(address >= GeneralMemoryStart && address < GeneralMemoryStart + GeneralMemorySize) 766 { 767 memory[address - GeneralMemoryStart] = value; 768 this.Log(LogLevel.Debug, "Written mem 0x{0:X}, value 0x{1:X}", address, value); 769 } 770 else if(address >= SourceAddressTableStart && address < SourceAddressTableStart + SourceAddressTableSize) 771 { 772 sourceAddressTable[address - SourceAddressTableStart] = value; 773 this.Log(LogLevel.Debug, "Written sourceAddressTable 0x{0:X}, value 0x{1:X}", address, value); 774 } 775 else if(address >= SourceAddressMatchingResultStart && address < SourceAddressMatchingResultStart + SourceAddressMatchingResultSize) 776 { 777 sourceAddressMatchingResult[address - SourceAddressMatchingResultStart] = value; 778 this.Log(LogLevel.Debug, "Written sourceAddressMatchingResult 0x{0:X}, value 0x{1:X}", address, value); 779 } 780 else if(address >= SourceAddressMatchingControlStart && address < SourceAddressMatchingControlStart + SourceAddressMatchingControlSize) 781 { 782 sourceAddressMatchingControl[address - SourceAddressMatchingControlStart] = value; 783 this.Log(LogLevel.Debug, "Written sourceAddressMatchingControl 0x{0:X}, value 0x{1:X}", address, value); 784 } 785 else if(address >= LocalAddressInfoStart && address < LocalAddressInfoStart + LocalAddressInfoSize) 786 { 787 localAddressInfo[address - LocalAddressInfoStart] = value; 788 this.Log(LogLevel.Debug, "Written localAddressInfo 0x{0:X}, value 0x{1:X}", address, value); 789 } 790 else 791 { 792 SetException(ExceptionFlags.MemoryAddressError); 793 } 794 } 795 RegisterInstructions()796 private void RegisterInstructions() 797 { 798 decoderRoot.AddOpcode(0x00, 8, () => new SNOP { Parent = this }); 799 decoderRoot.AddOpcode(0x10, 4, () => new MEMRD { Parent = this }); 800 decoderRoot.AddOpcode(0x20, 4, () => new MEMWR { Parent = this }); 801 decoderRoot.AddOpcode(0x30, 8, () => new RXBUF { Parent = this }); 802 decoderRoot.AddOpcode(0x32, 7, () => new RXBUFMOV { Parent = this }); 803 decoderRoot.AddOpcode(0x3A, 8, () => new TXBUF { Parent = this }); 804 decoderRoot.AddOpcode(0x40, 8, () => new SXOSCON { Parent = this }); 805 decoderRoot.AddOpcode(0x42, 8, () => new SRXON { Parent = this }); 806 decoderRoot.AddOpcode(0x44, 8, () => new STXONCCA { Parent = this }); 807 decoderRoot.AddOpcode(0x45, 8, () => new SRFOFF { Parent = this }); 808 decoderRoot.AddOpcode(0x46, 8, () => new SXOSCOFF { Parent = this }); 809 decoderRoot.AddOpcode(0x47, 8, () => new SFLUSHRX { Parent = this }); 810 decoderRoot.AddOpcode(0x48, 8, () => new SFLUSHTX { Parent = this }); 811 decoderRoot.AddOpcode(0x80, 2, () => new REGRD { Parent = this }); 812 decoderRoot.AddOpcode(0xC0, 2, () => new REGWR { Parent = this }); 813 } 814 815 private IValueRegisterField frameControlFieldReservedMask; 816 private IValueRegisterField maxFrameVersion; 817 private IFlagRegisterField panCoordinator; 818 private IFlagRegisterField frameFilteringEnabled; 819 820 private IFlagRegisterField acceptBeaconFrames; 821 private IFlagRegisterField acceptDataFrames; 822 private IFlagRegisterField acceptAckFrames; 823 private IFlagRegisterField acceptMacCommandFrames; 824 private IFlagRegisterField acceptReservedFrames; 825 826 private IEnumRegisterField<ModifyFieldTypeMode> modifyFrameTypeFilter; 827 828 private IFlagRegisterField pendingDataRequestOnly; 829 private IFlagRegisterField autoPendingFlag; 830 private IFlagRegisterField sourceMatchingEnabled; 831 832 private readonly IValueRegisterField[] shortAddressMatchingEnabled = new IValueRegisterField[3]; 833 private readonly IValueRegisterField[] extendedAddressMatchingEnabled = new IValueRegisterField[3]; 834 835 private IFlagRegisterField autoCrc; 836 private IFlagRegisterField autoAck; 837 private IFlagRegisterField appendDataMode; 838 839 private IFlagRegisterField ignoreTxUnderflow; 840 private IFlagRegisterField pendingAlwaysOn; 841 842 private IValueRegisterField channel; 843 844 private IValueRegisterField fifopThreshold; 845 846 private readonly IValueRegisterField[] pendingExceptionFlag = new IValueRegisterField[3]; 847 private readonly IValueRegisterField[] pendingExceptionMaskA = new IValueRegisterField[3]; 848 private readonly IValueRegisterField[] pendingExceptionMaskB = new IValueRegisterField[3]; 849 850 private bool isRxEnabled; 851 private bool inReset; 852 private bool vregEnabled; 853 private bool oscillatorRunning; 854 private bool wasLastFrameSent; 855 856 private byte[] currentFrame; 857 858 private readonly Queue<byte> txFifo = new Queue<byte>(); 859 private readonly Queue<byte> rxFifo = new Queue<byte>(); 860 private byte[] memory; 861 private byte[] sourceAddressTable; 862 private byte[] sourceAddressMatchingResult; 863 private byte[] sourceAddressMatchingControl; 864 private byte[] localAddressInfo; 865 private Address localShortAddress; 866 private Address localExtendedAddress; 867 868 private Instruction currentInstruction; 869 private ByteRegisterCollection registers; 870 871 private SimpleInstructionDecoder<Instruction> decoderRoot = new SimpleInstructionDecoder<Instruction>(); 872 873 private const int RegisterMemorySize = 0x80; 874 private const uint TxFifoMemoryStart = 0x100; 875 private const int TxFifoMemorySize = 0x80; 876 private const uint RxFifoMemoryStart = 0x180; 877 private const int RxFifoMemorySize = 0x80; 878 private const uint GeneralMemoryStart = 0x200; 879 private const int GeneralMemorySize = 0x180; 880 private const uint SourceAddressTableStart = 0x380; 881 private const int SourceAddressTableSize = 0x60; 882 private const uint SourceAddressMatchingResultStart = 0x3E0; 883 private const int SourceAddressMatchingResultSize = 0x4; 884 private const uint SourceAddressMatchingControlStart = 0x3E4; 885 private const int SourceAddressMatchingControlSize = 0x6; 886 private const uint LocalAddressInfoStart = 0x3EA; 887 private const int LocalAddressInfoSize = 0xC; 888 private const int NumberOfGPIOs = 6; 889 890 private const int BroadcastPanIdentifier = 0xFFFF; 891 private const byte NoSourceIndex = 0x3F; 892 893 private abstract class Instruction 894 { Parse(byte value)895 public byte Parse(byte value) 896 { 897 CurrentByteCount++; 898 return ParseInner(value); 899 } 900 901 public CC2520 Parent { protected get; set; } 902 public string Name { get; private set; } 903 public bool IsFinished 904 { 905 get 906 { 907 return CurrentByteCount == Length; 908 } 909 } 910 911 public bool? HighPriority { get; protected set; } //tristate, because non-null value sets DPUx_ACTIVE in status 912 Instruction()913 protected Instruction() 914 { 915 Name = GetType().Name; 916 Length = 1; 917 } 918 ParseInner(byte value)919 protected virtual byte ParseInner(byte value) 920 { 921 return Parent.GetStatus(); 922 } 923 924 protected virtual bool IsCommandStrobe 925 { 926 get { return Length == 1; } 927 } 928 929 protected int Length; 930 protected int CurrentByteCount; 931 protected uint AddressA; 932 protected uint CountC; 933 } 934 935 private sealed class SNOP : Instruction 936 { 937 protected override bool IsCommandStrobe 938 { 939 get { return false; } 940 } 941 } 942 943 private sealed class SXOSCON : Instruction 944 { ParseInner(byte value)945 protected override byte ParseInner(byte value) 946 { 947 Parent.oscillatorRunning = true; 948 return base.ParseInner(value); 949 } 950 951 protected override bool IsCommandStrobe 952 { 953 get { return false; } 954 } 955 } 956 957 private sealed class SRXON : Instruction 958 { ParseInner(byte value)959 protected override byte ParseInner(byte value) 960 { 961 Parent.isRxEnabled = true; 962 if(Parent.currentFrame != null) 963 { 964 Parent.HandleFrame(Parent.currentFrame); 965 Parent.currentFrame = null; 966 } 967 return base.ParseInner(value); 968 } 969 } 970 971 private sealed class STXONCCA : Instruction 972 { ParseInner(byte value)973 protected override byte ParseInner(byte value) 974 { 975 Parent.SendFrame(); 976 return base.ParseInner(value); 977 } 978 } 979 980 private sealed class SRFOFF : Instruction 981 { ParseInner(byte value)982 protected override byte ParseInner(byte value) 983 { 984 if(Parent.isRxEnabled && Parent.currentFrame != null) 985 { 986 Parent.SetException(ExceptionFlags.RxFrameAborted); 987 Parent.currentFrame = null; 988 } 989 Parent.isRxEnabled = false; 990 return base.ParseInner(value); 991 } 992 } 993 994 private sealed class SXOSCOFF : Instruction 995 { ParseInner(byte value)996 protected override byte ParseInner(byte value) 997 { 998 if(Parent.isRxEnabled) 999 { 1000 Parent.SetException(ExceptionFlags.UsageError); 1001 if(Parent.currentFrame != null) 1002 { 1003 Parent.SetException(ExceptionFlags.RxFrameAborted); 1004 Parent.currentFrame = null; 1005 } 1006 } 1007 Parent.oscillatorRunning = false; 1008 return base.ParseInner(value); 1009 } 1010 } 1011 1012 private sealed class MEMRD : Instruction 1013 { MEMRD()1014 public MEMRD() 1015 { 1016 Length = 0; 1017 } 1018 ParseInner(byte value)1019 protected override byte ParseInner(byte value) 1020 { 1021 switch(CurrentByteCount) 1022 { 1023 case 1: 1024 AddressA = (uint)(value & 0xF) << 8; 1025 return Parent.GetStatus(); 1026 case 2: 1027 AddressA |= value; 1028 return Parent.GetStatus(); 1029 default: 1030 var registerValue = Parent.ReadMemory(AddressA); 1031 AddressA = (AddressA + 1) % 0x3FF; //0x3FF is the highest RAM address. It is not explicitly stated that MEMWR/MEMRD should wrap 1032 return registerValue; 1033 } 1034 } 1035 } 1036 1037 private sealed class MEMWR : Instruction 1038 { MEMWR()1039 public MEMWR() 1040 { 1041 Length = 0; 1042 } 1043 ParseInner(byte value)1044 protected override byte ParseInner(byte value) 1045 { 1046 switch(CurrentByteCount) 1047 { 1048 case 1: 1049 AddressA = (uint)(value & 0xF) << 8; 1050 return Parent.GetStatus(); 1051 case 2: 1052 AddressA |= value; 1053 return Parent.GetStatus(); 1054 default: 1055 var registerValue = Parent.ReadMemory(AddressA); 1056 Parent.WriteMemory(AddressA, value); 1057 AddressA = (AddressA + 1) % 0x3FF; //0x3FF is the highest RAM address. It is not explicitly stated that MEMWR/MEMRD should wrap 1058 return registerValue; 1059 } 1060 } 1061 } 1062 1063 private sealed class RXBUF : Instruction 1064 { RXBUF()1065 public RXBUF() 1066 { 1067 Length = 0; 1068 } 1069 ParseInner(byte value)1070 protected override byte ParseInner(byte value) 1071 { 1072 switch(CurrentByteCount) 1073 { 1074 case 1: 1075 return base.ParseInner(value); 1076 default: 1077 if(Parent.rxFifo.Count > 0) 1078 { 1079 var data = Parent.rxFifo.Dequeue(); 1080 if(Parent.rxFifo.Count <= (int)Parent.fifopThreshold.Value) 1081 { 1082 Parent.UnsetException(ExceptionFlags.FifoThresholdReached); 1083 } 1084 Parent.UpdateInterrupts(); 1085 return data; 1086 } 1087 Parent.SetException(ExceptionFlags.RxUnderflow); 1088 return 0; 1089 } 1090 } 1091 } 1092 1093 private sealed class TXBUF : Instruction 1094 { TXBUF()1095 public TXBUF() 1096 { 1097 Length = 0; 1098 } 1099 ParseInner(byte value)1100 protected override byte ParseInner(byte value) 1101 { 1102 switch(CurrentByteCount) 1103 { 1104 case 1: 1105 return base.ParseInner(value); 1106 default: 1107 if(Parent.wasLastFrameSent) 1108 { 1109 Parent.txFifo.Clear(); 1110 Parent.wasLastFrameSent = false; 1111 } 1112 var count = Parent.txFifo.Count; 1113 if(count <= TxFifoMemorySize) 1114 { 1115 Parent.txFifo.Enqueue(value); 1116 } 1117 else 1118 { 1119 Parent.SetException(ExceptionFlags.TxOverflow); 1120 } 1121 return (byte)count; 1122 } 1123 } 1124 } 1125 1126 private sealed class SFLUSHRX : Instruction 1127 { ParseInner(byte value)1128 protected override byte ParseInner(byte value) 1129 { 1130 Parent.rxFifo.Clear(); 1131 Parent.UnsetException(ExceptionFlags.FifoThresholdReached); 1132 Parent.UpdateInterrupts(); 1133 return base.ParseInner(value); 1134 } 1135 } 1136 1137 private sealed class SFLUSHTX : Instruction 1138 { ParseInner(byte value)1139 protected override byte ParseInner(byte value) 1140 { 1141 Parent.txFifo.Clear(); 1142 Parent.UpdateInterrupts(); 1143 return base.ParseInner(value); 1144 } 1145 } 1146 1147 private sealed class REGRD : Instruction 1148 { REGRD()1149 public REGRD() 1150 { 1151 Length = 0; 1152 } 1153 ParseInner(byte value)1154 protected override byte ParseInner(byte value) 1155 { 1156 if(CurrentByteCount == 1) 1157 { 1158 AddressA = BitHelper.GetValue(value, 0, 6); 1159 return base.ParseInner(value); 1160 } 1161 var registerValue = Parent.ReadMemory(AddressA); 1162 AddressA = (AddressA + 1) % 0x7F; //the operation wraps on 0x7F 1163 return registerValue; 1164 } 1165 } 1166 1167 private sealed class REGWR : Instruction 1168 { REGWR()1169 public REGWR() 1170 { 1171 Length = 0; 1172 } 1173 ParseInner(byte value)1174 protected override byte ParseInner(byte value) 1175 { 1176 if(CurrentByteCount == 1) 1177 { 1178 AddressA = BitHelper.GetValue(value, 0, 6); 1179 return Parent.GetStatus(); 1180 } 1181 var registerValue = Parent.ReadMemory(AddressA); 1182 Parent.WriteMemory(AddressA, value); 1183 AddressA = (AddressA + 1) % 0x7F; //the operation wraps on 0x7F 1184 return registerValue; 1185 } 1186 } 1187 1188 private sealed class RXBUFMOV : Instruction 1189 { RXBUFMOV()1190 public RXBUFMOV() 1191 { 1192 Length = 4; 1193 } 1194 ParseInner(byte value)1195 protected override byte ParseInner(byte value) 1196 { 1197 switch(CurrentByteCount) 1198 { 1199 case 1: 1200 HighPriority = (value & 0x1u) != 0; 1201 return Parent.GetStatus(); 1202 case 2: 1203 CountC = value; 1204 return (byte)Parent.rxFifo.Count; 1205 case 3: 1206 AddressA = (uint)(value & 0xF) << 8; 1207 return Parent.GetStatus(); 1208 default: 1209 AddressA |= value; 1210 if(Parent.rxFifo.Count < CountC) 1211 { 1212 Parent.SetException(ExceptionFlags.RxBufferMoveTimeout); 1213 CountC = (uint)Parent.rxFifo.Count; 1214 Parent.Log(LogLevel.Warning, "Rx buffer underflow during RXBUFMOV instruction. A status register should be set, but it's not well specified which one."); 1215 } 1216 for(var i = 0; i < CountC; ++i) 1217 { 1218 var data = Parent.rxFifo.Dequeue(); 1219 Parent.WriteMemory(AddressA, data); 1220 AddressA++; 1221 Parent.SetException(HighPriority.Value ? ExceptionFlags.DPUDoneHigh : ExceptionFlags.DPUDoneLow); 1222 } 1223 if(Parent.rxFifo.Count <= (int)Parent.fifopThreshold.Value) 1224 { 1225 Parent.UnsetException(ExceptionFlags.FifoThresholdReached); 1226 } 1227 Parent.UpdateInterrupts(); 1228 return Parent.GetStatus(); 1229 } 1230 } 1231 } 1232 1233 1234 1235 private enum Registers 1236 { 1237 //FREG registers 1238 FrameFiltering0 = 0x00, //FRMFILT0 1239 FrameFiltering1 = 0x01, 1240 SourceMatching = 0x02, 1241 ShortAddressMatchingEnabled0 = 0x04, 1242 ShortAddressMatchingEnabled1 = 0x05, 1243 ShortAddressMatchingEnabled2 = 0x06, 1244 ExtendedAddressMatchingEnabled0 = 0x08, 1245 ExtendedAddressMatchingEnabled1 = 0x09, 1246 ExtendedAddressMatchingEnabled2 = 0x0A, 1247 FrameControl0 = 0x0C, 1248 FrameControl1 = 0x0D, 1249 RXENABLE0 = 0x0E, 1250 RXENABLE1 = 0x0F, 1251 PendingExceptionFlags0 = 0x10, 1252 PendingExceptionFlags1 = 0x11, 1253 PendingExceptionFlags2 = 0x12, 1254 ExceptionMaskA0 = 0x14, 1255 ExceptionMaskA1 = 0x15, 1256 ExceptionMaskA2 = 0x16, 1257 ExceptionMaskB0 = 0x18, 1258 ExceptionMaskB1 = 0x19, 1259 ExceptionMaskB2 = 0x1A, 1260 EXCBINDX0 = 0x1C, 1261 EXCBINDX1 = 0x1D, 1262 EXCBINDY0 = 0x1E, 1263 EXCBINDY1 = 0x1F, 1264 GPIOCTRL0 = 0x20, 1265 GPIOCTRL1 = 0x21, 1266 GPIOCTRL2 = 0x22, 1267 GPIOCTRL3 = 0x23, 1268 GPIOCTRL4 = 0x24, 1269 GPIOCTRL5 = 0x25, 1270 GPIOPOLARITY = 0x26, 1271 GPIOCTRL = 0x28, 1272 DPUCON = 0x2A, 1273 DPUSTAT = 0x2C, 1274 FrequencyControl = 0x2E, 1275 FREQTUNE = 0x2F, 1276 TxPower = 0x30, 1277 TXCTRL = 0x31, 1278 FSMSTAT0 = 0x32, 1279 FSMSTAT1 = 0x33, 1280 FifoPControl = 0x34, 1281 FSMCTRL = 0x35, 1282 CCAThreshold = 0x36, 1283 CCACTRL1 = 0x37, 1284 RSSI = 0x38, 1285 RSSIValidStatus = 0x39, 1286 RxFirstByte = 0x3C, 1287 RxFifoCount = 0x3E, 1288 TxFifoCount = 0x3F, 1289 //SREG registers 1290 ChipId = 0x40, 1291 Version = 0x42, 1292 ExternalClock = 0x44, 1293 ModemControl0 = 0x46, 1294 ModemControl1 = 0x47, 1295 FREQEST = 0x48, 1296 RxModuleTuning = 0x4A, 1297 SynthesizerTuning = 0x4C, 1298 FSCAL0 = 0x4E, 1299 VCOTuning1 = 0x4F, 1300 FSCAL2 = 0x50, 1301 FSCAL3 = 0x51, 1302 AGCCTRL0 = 0x52, 1303 AGCTuning1 = 0x53, 1304 AGCCTRL2 = 0x54, 1305 AGCCTRL3 = 0x55, 1306 ADCTest0 = 0x56, 1307 ADCTest1 = 0x57, 1308 ADCTest2 = 0x58, 1309 MDMTEST0 = 0x5A, 1310 MDMTEST1 = 0x5B, 1311 DACTEST0 = 0x5C, 1312 DACTEST1 = 0x5D, 1313 ATEST = 0x5E, 1314 DACTEST2 = 0x5F, 1315 PTEST0 = 0x60, 1316 PTEST1 = 0x61, 1317 RESERVED = 0x62, 1318 DPUBIST = 0x7A, 1319 ACTBIST = 0x7C, 1320 RAMBIST = 0x7E 1321 } 1322 1323 private enum ExceptionFlags 1324 { 1325 RFIdle = 0, 1326 TxFrameDone = 1, 1327 TxAckDone = 2, 1328 TxUnderflow = 3, 1329 TxOverflow = 4, 1330 RxUnderflow = 5, 1331 RxOverflow = 7, 1332 RxEnableZero = 8, 1333 RxFrameDone = 9, 1334 RxFrameAccepted = 10, 1335 SourceMatchingDone = 11, 1336 SourceMatchingFound = 12, 1337 FifoThresholdReached = 13, 1338 StartOfFrameDelimiter = 14, 1339 DPUDoneLow = 15, 1340 DPUDoneHigh = 16, 1341 MemoryAddressError = 17, 1342 UsageError = 18, 1343 OperandError = 19, 1344 SPIError = 20, 1345 RFNoLock = 21, 1346 RxFrameAborted = 22, 1347 RxBufferMoveTimeout = 23 1348 } 1349 1350 private enum GPIOs 1351 { 1352 //these are the default functions of reconfigurable gpios. This is not robust. 1353 Clock = 0, 1354 Fifo = 1, 1355 Fifop = 2, 1356 Cca = 3, 1357 Sfd = 4, 1358 In = 5 1359 } 1360 1361 private enum ModifyFieldTypeMode 1362 { 1363 Leave, 1364 InvertMSB, 1365 SetMSB, 1366 UnsetMSB 1367 } 1368 } 1369 } 1370