Compare commits

...

4 commits

Author SHA1 Message Date
af7007f77f Makefile: add make test target.
This may be faster than `make coverage`.

Signed-off-by: Jeff Epler <jepler@gmail.com>
2025-08-27 11:58:18 -05:00
ac8b14f7f2 uwwvb: Avoid creating lists in get_am_bcd.
& remove unused bcd_weights.

Signed-off-by: Jeff Epler <jepler@gmail.com>
2025-08-27 11:58:03 -05:00
9f26e319da uwwvb: Improve checking of marks & zeros.
Signed-off-by: Jeff Epler <jepler@gmail.com>
2025-08-27 11:54:58 -05:00
54d0b4f0f2 testuwwvb: Add (failing) test of spurious MARKs 2025-08-27 11:41:21 -05:00
3 changed files with 36 additions and 11 deletions

View file

@ -36,6 +36,10 @@ coverage:
$(Q)$(PYTHON) -mcoverage xml $(COVERAGE_INCLUDE) $(Q)$(PYTHON) -mcoverage xml $(COVERAGE_INCLUDE)
$(Q)$(PYTHON) -mcoverage report --fail-under=100 $(COVERAGE_INCLUDE) $(Q)$(PYTHON) -mcoverage report --fail-under=100 $(COVERAGE_INCLUDE)
.PHONY: test
test:
$(Q)env PYTHONPATH=src $(PYTHON) -munittest discover -s test
.PHONY: test_venv .PHONY: test_venv
test_venv: test_venv:
$(Q)$(PYTHON) -mvenv --clear _env $(Q)$(PYTHON) -mvenv --clear _env

View file

@ -19,7 +19,6 @@ ZERO, ONE, MARK = range(3)
always_mark = set((0, 9, 19, 29, 39, 49, 59)) always_mark = set((0, 9, 19, 29, 39, 49, 59))
always_zero = set((4, 10, 11, 14, 20, 21, 34, 35, 44, 54)) always_zero = set((4, 10, 11, 14, 20, 21, 34, 35, 44, 54))
bcd_weights = (1, 2, 4, 8, 10, 20, 40, 80, 100, 200, 400, 800)
WWVBMinute = namedtuple("WWVBMinute", ["year", "days", "hour", "minute", "dst", "ut1", "ls", "ly"]) WWVBMinute = namedtuple("WWVBMinute", ["year", "days", "hour", "minute", "dst", "ut1", "ls", "ly"])
@ -76,16 +75,16 @@ class WWVBDecoder:
def get_am_bcd(seq: list[int], *poslist: int) -> int | None: def get_am_bcd(seq: list[int], *poslist: int) -> int | None:
"""Convert the bits seq[positions[0]], ... seq[positions[len(positions-1)]] [in MSB order] from BCD to decimal""" """Convert the bits seq[positions[0]], ... seq[positions[len(positions-1)]] [in MSB order] from BCD to decimal"""
pos = list(poslist)[::-1] k = len(poslist)
val = [int(seq[p]) for p in pos]
while len(val) % 4 != 0:
val.append(0)
result = 0 result = 0
base = 1 base = 1
for i in range(0, len(val), 4): while k >= 0:
digit = 0 digit = 0
for j in range(4): for j in range(4):
digit += 1 << j if val[i + j] else 0 k -= 1
if k < 0:
break
digit += 1 << j if seq[poslist[k]] else 0
if digit > 9: if digit > 9:
return None return None
result += digit * base result += digit * base
@ -99,10 +98,17 @@ def decode_wwvb(
"""Convert a received minute of wwvb symbols to a WWVBMinute. Returns None if any error is detected.""" """Convert a received minute of wwvb symbols to a WWVBMinute. Returns None if any error is detected."""
if not t: if not t:
return None return None
if not all(t[i] == MARK for i in always_mark): for i in range(len(t)):
return None is_mark: bool = t[i] == MARK
if not all(t[i] == ZERO for i in always_zero): is_zero: bool = t[i] == ZERO
return None expect_mark = i in always_mark or i == 60
expect_zero = i in always_zero
if expect_mark != is_mark:
return None
if expect_zero and not is_zero:
return None
# Checking redundant DUT1 sign bits # Checking redundant DUT1 sign bits
if t[36] == t[37]: if t[36] == t[37]:
return None return None

View file

@ -197,6 +197,21 @@ class WWVBRoundtrip(unittest.TestCase):
decoded = uwwvb.decode_wwvb(test_input) decoded = uwwvb.decode_wwvb(test_input)
self.assertIsNone(decoded) self.assertIsNone(decoded)
def test_noise4(self) -> None:
"""Test of the full minute decoder with marks at every never-mark position"""
minute = wwvb.WWVBMinuteIERS.from_datetime(
datetime.datetime(2012, 6, 30, 23, 50, tzinfo=datetime.timezone.utc),
)
timecode = minute.as_timecode()
for position in range(60):
if position in uwwvb.always_mark:
continue
with self.subTest(test=position):
test_input = [int(i) for i in timecode.am]
test_input[position] = uwwvb.MARK
decoded = uwwvb.decode_wwvb(test_input)
self.assertIsNone(decoded)
def test_str(self) -> None: def test_str(self) -> None:
"""Test the str() of a WWVBDecoder""" """Test the str() of a WWVBDecoder"""
self.assertEqual(str(uwwvb.WWVBDecoder()), "<WWVBDecoder 1 []>") self.assertEqual(str(uwwvb.WWVBDecoder()), "<WWVBDecoder 1 []>")