diff options
author | Gerhard Sittig <gerhard.sittig@gmx.net> | 2023-07-29 16:59:43 +0200 |
---|---|---|
committer | Gerhard Sittig <gerhard.sittig@gmx.net> | 2023-07-29 21:29:11 +0200 |
commit | 17b2579a517489ce06756943529986921e194ef9 (patch) | |
tree | ceeaeb0b2f47d635ad01b2c64960edade1b89d49 /decoders | |
parent | 5e8090d7d30fb0915fc1b54f3ec098c69a417745 (diff) | |
download | libsigrokdecode-17b2579a517489ce06756943529986921e194ef9.tar.gz libsigrokdecode-17b2579a517489ce06756943529986921e194ef9.zip |
rgb_led_ws281x: support more colour component orders (wire, and text)
The 'type' option was not good enough. Replace it by 'wireorder' (order
of colour components on the wire, depends on the RGB LED chip type), and
'textorder' (presentation to users in annotations).
Support many more layouts of colour components on the wire. Cover all
permutations of R, G, and B. Support a few RGB plus W layouts that are
known to be in use. Adding more is just a matter of adding more choices
in the option, the implementation transparently follows.
Support a few text orders: Reflect the very order of bits on the wire.
Automatic support for RGB with optional White, or fixed RGB or RGB-W
variants (all are users' choices, default remains "RGB" for backwards
compatibility). Support arbitrary combinations of wire order and text
order in emitted annotations.
Keep support for the weird RGWB text format, which the previous decoder
implementation used for "all" RGBW types, and which is referenced by
existing test cases. It is uncertain which chip type is supposed to
generate this specific RGBW traffic. It is as uncertain why this text
order was chosen, which neither is the human readable RGBW format nor
matches the wire order. The previous implementation was introduced in
commit 47ff9910f7e1, but neither commented nor referenced literature or
external sources nor did the commit message contain any clues.
This current implementation needs more tests and reviews, but lends
itself better to maintenance, fixes and enhancements.
Diffstat (limited to 'decoders')
-rw-r--r-- | decoders/rgb_led_ws281x/pd.py | 72 |
1 files changed, 61 insertions, 11 deletions
diff --git a/decoders/rgb_led_ws281x/pd.py b/decoders/rgb_led_ws281x/pd.py index 5f35594..7c8ead4 100644 --- a/decoders/rgb_led_ws281x/pd.py +++ b/decoders/rgb_led_ws281x/pd.py @@ -23,6 +23,9 @@ from common.srdhelper import bitpack_msb class SamplerateError(Exception): pass +class DecoderError(Exception): + pass + ( ANN_BIT, ANN_RESET, ANN_RGB, ) = range(3) class Decoder(srd.Decoder): @@ -48,8 +51,11 @@ class Decoder(srd.Decoder): ('rgb-vals', 'RGB values', (ANN_RGB,)), ) options = ( - {'id': 'type', 'desc': 'RGB or RGBW', 'default': 'RGB', - 'values': ('RGB', 'RGBW')}, + {'id': 'wireorder', 'desc': 'colour components order (wire)', + 'default': 'GRB', + 'values': ('BGR', 'BRG', 'GBR', 'GRB', 'RBG', 'RGB', 'RWBG', 'RGBW')}, + {'id': 'textorder', 'desc': 'components output order (text)', + 'default': 'RGB', 'values': ('wire', 'RGB[W]', 'RGB', 'RGBW', 'RGWB')}, ) def __init__(self): @@ -72,15 +78,32 @@ class Decoder(srd.Decoder): def handle_bits(self): if len(self.bits) < self.need_bits: return - grb = bitpack_msb(self.bits, 0) - if self.options['type'] == 'RGB': - rgb = (grb & 0xff0000) >> 8 | (grb & 0x00ff00) << 8 | (grb & 0x0000ff) - text = '#{:06x}'.format(rgb) - else: - rgb = (grb & 0xff0000) >> 8 | (grb & 0x00ff00) << 8 | (grb & 0xff0000ff) - text = '#{:08x}'.format(rgb) ss_packet, es_packet = self.bits[0][1], self.bits[-1][2] - self.putg(ss_packet, es_packet, ANN_RGB, [text]) + r, g, b, w = 0, 0, 0, None + comps = [] + for i, c in enumerate(self.wireformat): + first_idx, after_idx = 8 * i, 8 * i + 8 + comp_bits = self.bits[first_idx:after_idx] + comp_ss, comp_es = comp_bits[0][1], comp_bits[-1][2] + comp_value = bitpack_msb(comp_bits, 0) + comp_item = (comp_ss, comp_es, comp_value) + comps.append(comp_item) + if c.lower() == 'r': + r = comp_value + elif c.lower() == 'g': + g = comp_value + elif c.lower() == 'b': + b = comp_value + elif c.lower() == 'w': + w = comp_value + wt = '' if w is None else '{:02x}'.format(w) + if self.textformat == 'wire': + rgb_text = ['{:02x}'.format(c[-1]) for c in comps] + rgb_text = '#' + ''.join(rgb_text) + else: + rgb_text = self.textformat.format(r = r, g = g, b = b, w = w, wt = wt) + if rgb_text: + self.putg(ss_packet, es_packet, ANN_RGB, [rgb_text]) self.bits.clear() def handle_bit(self, ss, es, value, ann_late = False): @@ -97,7 +120,34 @@ class Decoder(srd.Decoder): def decode(self): if not self.samplerate: raise SamplerateError('Cannot decode without samplerate.') - self.need_bits = len(self.options['type']) * 8 + + # Preprocess options here, to simplify logic which executes + # much later in loops while settings have the same values. + wireorder = self.options['wireorder'].lower() + self.wireformat = [c for c in wireorder if c in 'rgbw'] + self.need_bits = len(self.wireformat) * 8 + textorder = self.options['textorder'].lower() + if textorder == 'wire': + self.textformat = 'wire' + elif textorder == 'rgb[w]': + self.textformat = '#{r:02x}{g:02x}{b:02x}{wt:s}' + else: + self.textformat = { + # "Obvious" permutations of R/G/B. + 'bgr': '#{b:02x}{g:02x}{r:02x}', + 'brg': '#{b:02x}{r:02x}{g:02x}', + 'gbr': '#{g:02x}{b:02x}{r:02x}', + 'grb': '#{g:02x}{r:02x}{b:02x}', + 'rbg': '#{r:02x}{b:02x}{g:02x}', + 'rgb': '#{r:02x}{g:02x}{b:02x}', + # RGB plus White. Only one of them useful? + 'rgbw': '#{r:02x}{g:02x}{b:02x}{w:02x}', + # Weird RGBW permutation for compatibility to test case. + # Neither used RGBW nor the 'wire' order. Obsolete now? + 'rgwb': '#{r:02x}{g:02x}{w:02x}{b:02x}', + }.get(textorder, None) + if self.textformat is None: + raise DecoderError('Unsupported text output format.') # Either check for edges which communicate bit values, or for # long periods of idle level which represent a reset pulse. |