Browse Source

warn when selecting frequency below supported range

Fabian Peter Hammerle 3 years ago
parent
commit
91b19abd96
3 changed files with 46 additions and 0 deletions
  1. 1 0
      CHANGELOG.md
  2. 17 0
      cc1101/__init__.py
  3. 28 0
      tests/test_config.py

+ 1 - 0
CHANGELOG.md

@@ -7,6 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
 ## [Unreleased]
 ### Added
 - added command `cc1101-transmit` to transmit via command-line interface
+- warn when selecting frequency below supported range
 
 ## [2.4.0] - 2020-12-13
 ### Added

+ 17 - 0
cc1101/__init__.py

@@ -21,6 +21,7 @@ import fcntl
 import logging
 import math
 import typing
+import warnings
 
 import spidev
 
@@ -143,6 +144,11 @@ class CC1101:
     # > f_carrier = f_XOSC / 2**16 * (FREQ + CHAN * ((256 + CHANSPC_M) * 2**CHANSPC_E-2))
     _FREQUENCY_CONTROL_WORD_HERTZ_FACTOR = _CRYSTAL_OSCILLATOR_FREQUENCY_HERTZ / 2 ** 16
 
+    # roughly estimated / tested with SDR receiver, docs specify:
+    # > can [...] be programmed for operation at other frequencies
+    # > in the 300-348 MHz, 387-464 MHz and 779-928 MHz bands.
+    _TRANSMIT_MIN_FREQUENCY_HERTZ = 281.7e6
+
     def __init__(
         self, spi_bus: int = 0, spi_chip_select: int = 0, lock_spi_device: bool = False
     ) -> None:
@@ -598,6 +604,17 @@ class CC1101:
         )
 
     def set_base_frequency_hertz(self, freq: float) -> None:
+        if freq < (self._TRANSMIT_MIN_FREQUENCY_HERTZ - 50e3):
+            # > [use] warnings.warn() in library code if the issue is avoidable
+            # > and the client application should be modified to eliminate the warning[.]
+            # > [use] logging.warning() if there is nothing the client application
+            # > can do about the situation, but the event should still be noted.
+            # https://docs.python.org/3/howto/logging.html#when-to-use-logging
+            warnings.warn(
+                "CC1101 is unable to transmit at frequencies below {:.1f} MHz".format(
+                    self._TRANSMIT_MIN_FREQUENCY_HERTZ / 1e6
+                )
+            )
         self._set_base_frequency_control_word(
             self._hertz_to_frequency_control_word(freq)
         )

+ 28 - 0
tests/test_config.py

@@ -16,6 +16,7 @@
 # along with this program.  If not, see <https://www.gnu.org/licenses/>.
 
 import unittest.mock
+import warnings
 
 import pytest
 
@@ -373,3 +374,30 @@ def test_set_packet_length_mode(transceiver, pktctrl0_before, pktctrl0_after, mo
     ):
         transceiver.set_packet_length_mode(mode)
     xfer_mock.assert_called_once_with([0x08 | 0x40, pktctrl0_after])
+
+
+@pytest.mark.parametrize(
+    ("freq_hz", "warn"),
+    (
+        (100e6, True),
+        (281.6e6, True),
+        (281.65e6, False),  # within tolerance
+        (281.7e6, False),
+        (433.92e6, False),
+    ),
+)
+def test_set_base_frequency_hertz_low_warning(transceiver, freq_hz, warn):
+    with unittest.mock.patch.object(
+        transceiver, "_set_base_frequency_control_word"
+    ) as set_control_word_mock:
+        with warnings.catch_warnings(record=True) as caught_warnings:
+            transceiver.set_base_frequency_hertz(freq_hz)
+    assert set_control_word_mock.call_count == 1
+    if warn:
+        assert len(caught_warnings) == 1
+        assert (
+            str(caught_warnings[0].message)
+            == "CC1101 is unable to transmit at frequencies below 281.7 MHz"
+        )
+    else:
+        assert not caught_warnings