Esempio n. 1
0
 /// <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);
 }
Esempio n. 2
0
        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);
        }
Esempio n. 3
0
        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));
        }
Esempio n. 4
0
        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();
            }
        }
Esempio n. 5
0
        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));
        }
Esempio n. 6
0
        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));
        }
Esempio n. 7
0
        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));
        }