Browse Source

transmit(): prepend length byte in variable packet length mode internally
to avoid accidental incomplete transmissions and TX FIFO underflows

Fabian Peter Hammerle 3 years ago
parent
commit
03494733f3
4 changed files with 16 additions and 24 deletions
  1. 3 0
      CHANGELOG.md
  2. 9 7
      cc1101/__init__.py
  3. 3 3
      examples/transmit_variable_length.py
  4. 1 14
      tests/test_transmit.py

+ 3 - 0
CHANGELOG.md

@@ -5,6 +5,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
 and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
 
 ## [Unreleased]
+### Changed
+- `transmit()`: prepend length byte in variable packet length mode internally
+  to avoid accidental incomplete transmissions and TX FIFO underflows
 
 ## [1.2.0] - 2020-12-02
 ### Added

+ 9 - 7
cc1101/__init__.py

@@ -501,13 +501,19 @@ class CC1101:
 
     def transmit(self, payload: bytes) -> None:
         """
-        > In variable packet length mode [.set/get_packet_length_mode()],
+        The most significant bit is transmitted first.
+
+        In variable packet length mode,
+        a byte indicating the packet's length will be prepended.
+
+        > In variable packet length mode,
         > the packet length is configured by the first byte [...].
         > The packet length is defined as the payload data,
         > excluding the length byte and the optional CRC.
         from "15.2 Packet Format"
 
-        The most significant bit is transmitted first.
+        Call .set_packet_length_mode(cc1101.PacketLengthMode.FIXED)
+        to switch to fixed packet length mode.
         """
         # see "15.2 Packet Format"
         # > In variable packet length mode, [...]
@@ -517,11 +523,6 @@ class CC1101:
         if packet_length_mode == PacketLengthMode.VARIABLE:
             if not payload:
                 raise ValueError("empty payload {!r}".format(payload))
-            if payload[0] == 0:
-                raise ValueError(
-                    "in variable packet length mode the first byte of the payload must not be null"
-                    + "\npayload: {!r}".format(payload)
-                )
             if len(payload) > packet_length:
                 raise ValueError(
                     "payload exceeds maximum payload length of {} bytes".format(
@@ -530,6 +531,7 @@ class CC1101:
                     + "\nsee .get_packet_length_bytes()"
                     + "\npayload: {!r}".format(payload)
                 )
+            payload = int.to_bytes(len(payload), length=1, byteorder="big") + payload
         elif (
             packet_length_mode == PacketLengthMode.FIXED
             and len(payload) != packet_length

+ 3 - 3
examples/transmit_variable_length.py

@@ -18,9 +18,9 @@ with cc1101.CC1101() as transceiver:
     print("symbol rate", transceiver.get_symbol_rate_baud(), "Baud")
     print("modulation format", transceiver.get_modulation_format().name)
     print("starting transmission")
-    transceiver.transmit(b"\x0a\xff\x00 message")
+    transceiver.transmit(b"\xff\xaa\x00 message")
     time.sleep(1.0)
-    transceiver.transmit(bytes([0x02, 0b10101010, 0xFF]))
+    transceiver.transmit(bytes([0, 0b10101010, 0xFF]))
     for i in range(16):
         time.sleep(1.0)
-        transceiver.transmit(bytes([1, i]))
+        transceiver.transmit(bytes([i, i, i]))

+ 1 - 14
tests/test_transmit.py

@@ -19,19 +19,6 @@ def test_transmit_empty_payload(transceiver):
             transceiver.transmit([])
 
 
-@pytest.mark.parametrize("payload", (b"\0\x01\x02", [0, 127]))
-def test_transmit_first_null(transceiver, payload):
-    with unittest.mock.patch.object(
-        transceiver,
-        "get_packet_length_mode",
-        return_value=cc1101.options.PacketLengthMode.VARIABLE,
-    ), unittest.mock.patch.object(
-        transceiver, "get_packet_length_bytes", return_value=21
-    ):
-        with pytest.raises(ValueError, match=r"\bfirst byte\b.*\bmust not be null\b"):
-            transceiver.transmit(payload)
-
-
 @pytest.mark.parametrize(
     ("max_packet_length", "payload"),
     ((3, "\x04\x01\x02\x03"), (4, [7, 21, 42, 0, 0, 1, 2, 3])),
@@ -107,6 +94,6 @@ def test_transmit_variable(transceiver, payload):
         transceiver.transmit(payload)
     assert transceiver._spi.xfer.call_args_list == [
         unittest.mock.call([0x3B]),  # flush
-        unittest.mock.call([0x3F | 0x40] + list(payload)),
+        unittest.mock.call([0x3F | 0x40] + [len(payload)] + list(payload)),
         unittest.mock.call([0x35]),  # start transmission
     ]