/// <summary> /// Get the RSSI correction constant. /// </summary> /// <returns></returns> private int GetRssiCorrection() { // Page 87 in Semtech SX1276 datasheet. return(RegisterManager.Read <CommonRegisterOpMode>().LowFrequencyModeOn == CommonRegisterOpMode.LowFrequencyModeOnEnum.HighFrequencyMode ? -157 : -164); }
protected Transceiver(SpiDevice spiDevice, TransceiverSettings settings, TransceiverPinSettings pinSettings) { Settings = settings; _spiCommController = new SpiCommController(spiDevice); SpiComm = _spiCommController.Create(pinSettings.ChipSelectPinNumber); Pins = CreatePins(pinSettings); Pins.Dio0.ValueChanged += Dio0Pin_ValueChanged; RegisterManager = new RegisterManager(SpiComm); }
private void EnterReceiveMode() { RegisterManager.Write(new CommonRegisterOpMode( CommonRegisterOpMode.LongRangeModeEnum.LoRaMode, CommonRegisterOpMode.AccessSharedRegEnum.AccessLoRaRegisterPage, CommonRegisterOpMode.LowFrequencyModeOnEnum.HighFrequencyMode, CommonRegisterOpMode.DeviceModeEnum.ReceiveContinuous)); RegisterManager.Write(new CommonRegisterDioMapping1( CommonRegisterDioMapping1.Dio0MappingEnum.RxDone, CommonRegisterDioMapping1.Dio1MappingEnum.RxTimeout, CommonRegisterDioMapping1.Dio2MappingEnum.FhssChangeChannel1, CommonRegisterDioMapping1.Dio3MappingEnum.CadDone)); }
private void HandleTransmission(Transmission transmission) { try { lock (_registerFifoLock) { // Allow the full FIFO size for transmission RegisterManager.Write(new LoraRegisterFifoTxBaseAddr(0)); // Position at the beginning of the FIFO RegisterManager.Write(new LoraRegisterFifoAddrPtr(0)); // The message data foreach (byte b in transmission.Buffer) { RegisterManager.Write(new CommonRegisterFifo(b)); } // Write the message length RegisterManager.Write(new LoraRegisterPayloadLength((byte)transmission.Buffer.Length)); _transmissionCompletedEventSlim.Reset(); // Start the transmitter EnterTransmitMode(); } try { // Wait for the transmission to finish. _transmissionCompletedEventSlim.Wait(transmission.CancellationToken); } catch (OperationCanceledException) { } // Was it cancelled? transmission.TransmissionCompletionSource.SetResult(!transmission.CancellationToken.IsCancellationRequested); } catch (Exception exception) { transmission.TransmissionCompletionSource.SetException(exception); } finally { // Go back to receiver-mode. EnterReceiveMode(); } }
private void EnterTransmitMode() { RegisterManager.Write(new CommonRegisterOpMode( CommonRegisterOpMode.LongRangeModeEnum.LoRaMode, CommonRegisterOpMode.AccessSharedRegEnum.AccessLoRaRegisterPage, CommonRegisterOpMode.LowFrequencyModeOnEnum.HighFrequencyMode, CommonRegisterOpMode.DeviceModeEnum.Transmit)); // Interrupt on TxDone RegisterManager.Write(new CommonRegisterDioMapping1( CommonRegisterDioMapping1.Dio0MappingEnum.TxDone, CommonRegisterDioMapping1.Dio1MappingEnum.RxTimeout, CommonRegisterDioMapping1.Dio2MappingEnum.FhssChangeChannel1, CommonRegisterDioMapping1.Dio3MappingEnum.CadDone)); }
private void Dio0Pin_ValueChanged(GpioPin sender, GpioPinValueChangedEventArgs args) { if (args.Edge != GpioPinEdge.RisingEdge) { return; } LoraRegisterIrqFlags.FlagsEnum irqFlags = RegisterManager.Read <LoraRegisterIrqFlags>().Flags; if (irqFlags.HasFlag(LoraRegisterIrqFlags.FlagsEnum.TxDone)) { TransmittedOkCount++; _transmissionCompletedEventSlim.Set(); } if (irqFlags.HasFlag(LoraRegisterIrqFlags.FlagsEnum.RxDone)) { ReceivedMessage message = GetReceivedMessage(); OnMessageReceived?.Invoke(this, new ReceivedMessageEventArgs(message)); } // Clear all IRQ flags RegisterManager.Write(new LoraRegisterIrqFlags(0xFF)); }
private ReceivedMessage GetReceivedMessage() { DateTime timestamp = DateTime.UtcNow; LoraRegisterIrqFlags.FlagsEnum irqFlags = RegisterManager.Read <LoraRegisterIrqFlags>().Flags; bool timeout; if (irqFlags.HasFlag(LoraRegisterIrqFlags.FlagsEnum.RxTimeout)) { timeout = true; ReceivedTimeoutCount++; } else { timeout = false; } bool crcOk; if (irqFlags.HasFlag(LoraRegisterIrqFlags.FlagsEnum.PayloadCrcError)) { crcOk = false; ReceivedBadCrcCount++; } else { crcOk = true; } if (!timeout && crcOk) { ReceivedOkCount++; } lock (_registerFifoLock) { // Get the FIFO-address of the last received packet byte currentFifoAddr = RegisterManager.Read <LoraRegisterFifoRxCurrentAddr>().Addr; // Go to that address RegisterManager.Write(new LoraRegisterFifoAddrPtr(currentFifoAddr)); // Get the number of received bytes byte receivedCount = RegisterManager.Read <LoraRegisterRxNbBytes>().FifoRxBytesNb; // Prepare a buffer to copy to from the FIFO queue var buffer = new byte[receivedCount]; // Copy from the FIFO queue for (int i = 0; i < receivedCount; i++) { buffer[i] = RegisterManager.Read <CommonRegisterFifo>().Value; } // Get the RSSI correction value int rssiCorrection = GetRssiCorrection(); // Get the adjusted RSSI value int rssi = RegisterManager.Read <LoraRegisterRssiValue>().Rssi + rssiCorrection; // Get the adjusted RSSI value of the packet int pktRssi = RegisterManager.Read <LoraRegisterPktRssiValue>().PacketRssi + rssiCorrection; // Get the packet signal-to-noise ratio float pktSnr = (float)Math.Round(RegisterManager.Read <LoraRegisterPktSnrValue>().PacketSnr / 4d, 1); #if DEBUG Debug.WriteLine($"Packet RSSI: {pktRssi}, RSSI: {rssi}, SNR: {pktSnr}, Length: {buffer.Length}"); #endif return(new ReceivedMessage(buffer, rssi, pktRssi, pktSnr, crcOk, timeout, timestamp)); } }
protected override async Task Init() { Pins.Reset.Write(GpioPinValue.Low); await Task.Delay(10); Pins.Reset.Write(GpioPinValue.High); await Task.Delay(10); CommonRegisterVersion version = RegisterManager.Read <CommonRegisterVersion>(); if (version.Value == 0x12) { Debug.WriteLine("SX1276/77/78/79 detected, starting."); } else { throw new Exception("Unrecognized transceiver."); } RegisterManager.Write(new CommonRegisterOpMode( CommonRegisterOpMode.LongRangeModeEnum.LoRaMode, CommonRegisterOpMode.AccessSharedRegEnum.AccessLoRaRegisterPage, CommonRegisterOpMode.LowFrequencyModeOnEnum.HighFrequencyMode, CommonRegisterOpMode.DeviceModeEnum.Sleep)); uint frf = (uint)(((ulong)Settings.Frequency << 19) / 32000000); RegisterManager.Write(new CommonRegisterFrf(frf)); RegisterManager.Write(new LoraRegisterSyncWord(Settings.LoraSyncWord.Value)); RegisterManager.Write(new LoraRegisterModemConfig1( ConvertBandWidth(Settings.BandWidth), ConvertCodingRate(Settings.CodingRate), LoraRegisterModemConfig1.HeaderModeEnum.ExplicitHeaderMode)); RegisterManager.Write(new LoraRegisterModemConfig2( ConvertSpreadingFactor(Settings.SpreadingFactor), LoraRegisterModemConfig2.TxModeEnum.NormalMode, Settings.CrcEnabled ? LoraRegisterModemConfig2.RxPayloadCrcEnum.CrcEnabled : LoraRegisterModemConfig2.RxPayloadCrcEnum.CrcDisabled, Settings.SymbolTimeout)); RegisterManager.Write(new LoraRegisterModemConfig3( Settings.EnableLowDataRateOptimize ? LoraRegisterModemConfig3.LowDataRateOptimizeEnum.Enabled : LoraRegisterModemConfig3.LowDataRateOptimizeEnum.Disabled, LoraRegisterModemConfig3.AgcAutoEnum.Enabled)); RegisterManager.Write(new LoraRegisterMaxPayloadLength(0x80)); RegisterManager.Write(new LoraRegisterPayloadLength(0x40)); RegisterManager.Write(new LoraRegisterHopPeriod(0xFF)); RegisterManager.Write(new LoraRegisterFifoRxBaseAddr(0x00)); RegisterManager.Write(new LoraRegisterFifoTxBaseAddr(0x80)); byte fifoRxBaseAddr = RegisterManager.Read <LoraRegisterFifoRxBaseAddr>().FifoRxBaseAddr; RegisterManager.Write(new LoraRegisterFifoAddrPtr(fifoRxBaseAddr)); RegisterManager.Write(new CommonRegisterLna( CommonRegisterLna.LnaGainEnum.G1Max, CommonRegisterLna.LnaBoostLfEnum.DefaultLnaCurrent, CommonRegisterLna.LnaBoostHfEnum.BoostOn)); RegisterManager.Write(new CommonRegisterOpMode( CommonRegisterOpMode.LongRangeModeEnum.LoRaMode, CommonRegisterOpMode.AccessSharedRegEnum.AccessLoRaRegisterPage, CommonRegisterOpMode.LowFrequencyModeOnEnum.HighFrequencyMode, CommonRegisterOpMode.DeviceModeEnum.ReceiveContinuous)); }