Hello sigrok developers,

debugging a WS281x driver I was very confused to see #000000 values in
sigrok when my LEDs lit up. Please pull from [1] or see below.

As I'm currently facing unrelated problems ([2] and somethign more) with
my Hantek oscilloscope, I'd appreciate if this were tested on known-good
data before merging.

Best regards,
and thanks for maintaining sigrok and pulseview!
chrysn

[1]: https://codeberg.org/chrysn-pull-requests/libsigrokdecode.git -b 
ws281x_is_time_based
[2]: https://sigrok.org/bug/1884

---

From d22372bfaf1810c53003159e56ab68d57796fd2c Mon Sep 17 00:00:00 2001
From: chrysn <chr...@fsfe.org>
Date: Wed, 16 Aug 2023 22:00:11 +0200
Subject: [PATCH] rgb_led_ws281x: Evaluate timing rather than duty cycle

The duty cycle criterion is precise only if the source adheres to both
the high and the low time -- but what the recipients actually evaluate
is the high time, as long as the low time doesn't fall on the reset side
of things. Thus, the criterion for recognizing a bit is changed from
duty cycle to time.

This also allows doing away with the workaround of using a previous
period length for the last bit that ends at the reset condition and thus
has no period of its own.

Sources: Experimentation on SK6812 and "Timing" section of 
https://blog.kubovy.eu/2019/02/17/ws281x-using-pic/
---
 decoders/rgb_led_ws281x/pd.py | 19 ++++++-------------
 1 file changed, 6 insertions(+), 13 deletions(-)

diff --git a/decoders/rgb_led_ws281x/pd.py b/decoders/rgb_led_ws281x/pd.py
index 099a2ce..486834e 100644
--- a/decoders/rgb_led_ws281x/pd.py
+++ b/decoders/rgb_led_ws281x/pd.py
@@ -107,6 +107,8 @@ def start(self):
     def metadata(self, key, value):
         if key == srd.SRD_CONF_SAMPLERATE:
             self.samplerate = value
+            # Number of ticks that represent 480ns, which is a value between 
the T0H upper bound (380ns) and the T1H lower bound (580ns)
+            self.t1h_threshold = 480e-9 * self.samplerate
 
     def putg(self, ss, es, cls, text):
         self.put(ss, es, self.out_ann, [cls, text])
@@ -202,7 +204,6 @@ def decode(self):
         # adjacent to that bit time.
         cond_bit_starts = {0: 'r'}
         cond_inbit_edge = {0: 'f'}
-        samples_625ns = int(self.samplerate * 625e-9)
         samples_50us = round(self.samplerate * 50e-6)
         cond_reset_pulse = {'skip': samples_50us + 1}
         conds = [cond_bit_starts, cond_inbit_edge, cond_reset_pulse]
@@ -227,17 +228,8 @@ def decode(self):
                 ss_rst, es_rst = inv_bit, self.samplenum
 
                 if ss_bit and inv_bit and es_bit:
-                    # Decode last bit value. Use the last processed bit's
-                    # width for comparison when available. Fallback to an
-                    # arbitrary threshold otherwise (which can result in
-                    # false detection of value 1 for those captures where
-                    # high and low pulses are of similar width).
                     duty = inv_bit - ss_bit
-                    thres = samples_625ns
-                    if self.bits:
-                        period = self.bits[-1][2] - self.bits[-1][1]
-                        thres = period * 0.5
-                    bit_value = 1 if duty >= thres else 0
+                    bit_value = 1 if duty > self.t1h_threshold else 0
                     self.handle_bit(ss_bit, inv_bit, bit_value, True)
 
                 if ss_rst and es_rst:
@@ -258,8 +250,9 @@ def decode(self):
                     es_bit = self.samplenum
                     period = es_bit - ss_bit
                     duty = inv_bit - ss_bit
-                    # Ideal duty for T0H: 33%, T1H: 66%.
-                    bit_value = 1 if (duty / period) > 0.5 else 0
+                    # The period cycle is not used; the controllers evaluate 
the
+                    # high time and not the duty cycle.
+                    bit_value = 1 if duty > self.t1h_threshold else 0
                     self.handle_bit(ss_bit, es_bit, bit_value)
                 ss_bit, inv_bit, es_bit = self.samplenum, None, None
             if self.matched[1]: # and not pin:
-- 
2.40.1

Attachment: signature.asc
Description: PGP signature

_______________________________________________
sigrok-devel mailing list
sigrok-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/sigrok-devel

Reply via email to