Browse Source

added symbol rate setter

Fabian Peter Hammerle 3 years ago
parent
commit
348c38f0e0
3 changed files with 55 additions and 9 deletions
  1. 33 0
      cc1101/__init__.py
  2. 2 1
      example.py
  3. 20 8
      tests/test_cc1101.py

+ 33 - 0
cc1101/__init__.py

@@ -1,5 +1,6 @@
 import enum
 import logging
+import math
 import typing
 
 import spidev
@@ -152,12 +153,21 @@ class CC1101:
         """
         return self._read_single_byte(self._SPIAddress.MDMCFG4) & 0b00001111
 
+    def _set_symbol_rate_exponent(self, exponent: int):
+        mdmcfg4 = self._read_single_byte(self._SPIAddress.MDMCFG4)
+        mdmcfg4 &= 0b11110000
+        mdmcfg4 |= exponent
+        self._write_burst(start_register=self._SPIAddress.MDMCFG4, values=[mdmcfg4])
+
     def _get_symbol_rate_mantissa(self) -> int:
         """
         MDMCFG3.DRATE_M
         """
         return self._read_single_byte(self._SPIAddress.MDMCFG3)
 
+    def _set_symbol_rate_mantissa(self, mantissa: int) -> int:
+        self._write_burst(start_register=self._SPIAddress.MDMCFG3, values=[mantissa])
+
     @classmethod
     def _symbol_rate_floating_point_to_real(cls, mantissa: int, exponent: int) -> float:
         # see "12 Data Rate Programming"
@@ -168,12 +178,35 @@ class CC1101:
             / (2 ** 28)
         )
 
+    @classmethod
+    def _symbol_rate_real_to_floating_point(cls, real: float) -> typing.Tuple[int, int]:
+        # see "12 Data Rate Programming"
+        assert real > 0, real
+        exponent = math.floor(
+            math.log2(real / cls._CRYSTAL_OSCILLATOR_FREQUENCY_HERTZ) + 20
+        )
+        mantissa = round(
+            real * 2 ** 28 / cls._CRYSTAL_OSCILLATOR_FREQUENCY_HERTZ / 2 ** exponent
+            - 256
+        )
+        if mantissa == 256:
+            exponent += 1
+            mantissa = 0
+        assert 0 < exponent <= 2 ** 4, exponent
+        assert mantissa <= 2 ** 8, mantissa
+        return mantissa, exponent
+
     def get_symbol_rate_baud(self) -> float:
         return self._symbol_rate_floating_point_to_real(
             mantissa=self._get_symbol_rate_mantissa(),
             exponent=self._get_symbol_rate_exponent(),
         )
 
+    def set_symbol_rate_baud(self, real: float) -> None:
+        mantissa, exponent = self._symbol_rate_real_to_floating_point(real)
+        self._set_symbol_rate_mantissa(mantissa)
+        self._set_symbol_rate_exponent(exponent)
+
     def get_modulation_format(self) -> ModulationFormat:
         mdmcfg2 = self._read_single_byte(self._SPIAddress.MDMCFG2)
         return self.ModulationFormat((mdmcfg2 >> 4) & 0b111)

+ 2 - 1
example.py

@@ -7,8 +7,9 @@ import cc1101
 logging.basicConfig(level=logging.INFO)
 
 with cc1101.CC1101() as transceiver:
-    print(transceiver)
+    print("defaults:", transceiver)
     transceiver.set_base_frequency_hertz(433e6)
+    transceiver.set_symbol_rate_baud(1000)
     print(transceiver)
     print("state", transceiver.get_marc_state().name)
     print("base frequency", transceiver.get_base_frequency_hertz(), "Hz")

+ 20 - 8
tests/test_cc1101.py

@@ -26,17 +26,29 @@ def test__hertz_to_frequency_control_word(control_word, hertz):
     assert cc1101.CC1101._hertz_to_frequency_control_word(hertz) == control_word
 
 
+_SYMBOL_RATE_MANTISSA_EXPONENT_REAL_PARAMS = [
+    # > The default values give a data rate of 115.051 kBaud
+    # > (closest setting to 115.2 kBaud), assuming a 26.0 MHz crystal.
+    (34, 12, 115051),
+    (34, 12 + 1, 115051 * 2),
+    (34, 12 - 1, 115051 / 2),
+]
+
+
 @pytest.mark.parametrize(
-    ("mantissa", "exponent", "real"),
-    [
-        # > The default values give a data rate of 115.051 kBaud
-        # > (closest setting to 115.2 kBaud), assuming a 26.0 MHz crystal.
-        (34, 12, 115051),
-        (34, 12 + 1, 115051 * 2),
-        (34, 12 - 1, 115051 / 2),
-    ],
+    ("mantissa", "exponent", "real"), _SYMBOL_RATE_MANTISSA_EXPONENT_REAL_PARAMS
 )
 def test__symbol_rate_floating_point_to_real(mantissa, exponent, real):
     assert cc1101.CC1101._symbol_rate_floating_point_to_real(
         mantissa=mantissa, exponent=exponent
     ) == pytest.approx(real, rel=1e-5)
+
+
+@pytest.mark.parametrize(
+    ("mantissa", "exponent", "real"), _SYMBOL_RATE_MANTISSA_EXPONENT_REAL_PARAMS
+)
+def test__symbol_rate_real_to_floating_point(mantissa, exponent, real):
+    assert cc1101.CC1101._symbol_rate_real_to_floating_point(real) == (
+        mantissa,
+        exponent,
+    )