diff options
author | Alexey 'Cluster' Avdyukhin <clusterrr@clusterrr.com> | 2022-04-10 19:35:29 +0300 |
---|---|---|
committer | Alexey 'Cluster' Avdyukhin <clusterrr@clusterrr.com> | 2022-04-10 19:35:29 +0300 |
commit | 8f5b64e68f33a2079d99615e1e0653e482a2c303 (patch) | |
tree | d1f31011b2add1bdd44f8bdda98bad81f5351152 /demo_scripts |
First commit
Diffstat (limited to 'demo_scripts')
-rw-r--r-- | demo_scripts/necrc.py | 67 | ||||
-rw-r--r-- | demo_scripts/rc6.py | 82 | ||||
-rw-r--r-- | demo_scripts/receiver-test.py | 27 | ||||
-rw-r--r-- | demo_scripts/transmitter-test.py | 20 |
4 files changed, 196 insertions, 0 deletions
diff --git a/demo_scripts/necrc.py b/demo_scripts/necrc.py new file mode 100644 index 0000000..646b48b --- /dev/null +++ b/demo_scripts/necrc.py @@ -0,0 +1,67 @@ +NEC_LEADING_PULSE = 9000 +NEC_LEADING_GAP = 4500 +NEC_GAP = 562 +NEC_PULSE_0 = 562 +NEC_PULSE_1 = 1600 +NEC_PRECITION = 0.25 +NEC_REPEAT_GAP = 2250 + +def nec_decode(s): + b = bytes.fromhex(s) + values = [int.from_bytes(b[i:i+2], byteorder='little') for i in range(0, len(b), 2)] + if not (NEC_LEADING_PULSE * (1 - NEC_PRECITION) <= values[0] <= NEC_LEADING_PULSE * (1 + NEC_PRECITION)): + raise ValueError(f"Invalid leading pulse length: {values[0]}") + if not (NEC_LEADING_GAP * (1 - NEC_PRECITION) <= values[1] <= NEC_LEADING_GAP * (1 + NEC_PRECITION)): + raise ValueError(f"Invalid leading gap length: {values[1]}") + if not (NEC_GAP * (1 - NEC_PRECITION) <= values[2] <= NEC_GAP * (1 + NEC_PRECITION)): + raise ValueError(f"Invalid first pulse length: {values[2]}") + i = 0 + for p in range(3, 3 + 2 * 32, 2): + v = values[p] + v = 1 if v > (NEC_PULSE_0 + NEC_PULSE_1) / 2 else 0 + i = (i >> 1) | (v << 31) + return int.to_bytes(i, length=4, byteorder='little') + +def nec_encode(h): + # Type check + if type(h) == int: + h = int.to_bytes(h, length=4, byteorder='little') + elif type(h) is list: + h = bytes(h) + elif type(h) is bytes: + pass + else: + raise TypeError(f"Invalid type of input data: {type(h)}") + # Length check + if len(h) == 2: + h = bytes([h[0], h[0] ^ 0xFF, h[1], h[1] ^ 0xFF]) + elif len(h) == 3: + h = bytes([h[0], h[1], h[2], h[2] ^ 0xFF]) + elif len(h) == 4: + pass + else: + raise ValueError(f"Invalid length of input data: {len(h)}") + # Encoding + len2str = lambda i: f"{((i >> 8) | (i << 8)) & 0xFFFF:04x}" + i = int.from_bytes(h, byteorder='little') + pulses = [NEC_PULSE_1 if i & (1 << bit) > 0 else NEC_PULSE_0 for bit in range(32)] + s = ( + len2str(NEC_LEADING_PULSE) + + len2str(NEC_LEADING_GAP) + + len2str(NEC_GAP) + + len2str(NEC_GAP).join([len2str(pulse) for pulse in pulses]) + + len2str(NEC_GAP) + ) + return s + +def is_nec_repeat(s): + b = bytes.fromhex(s) + values = [int.from_bytes(b[i:i+2], byteorder='little') for i in range(0, len(b), 2)] + if len(values) > 3: return False + if not (NEC_LEADING_PULSE * (1 - NEC_PRECITION) <= values[0] <= NEC_LEADING_PULSE * (1 + NEC_PRECITION)): + return False + if not (NEC_REPEAT_GAP * (1 - NEC_PRECITION) <= values[1] <= NEC_REPEAT_GAP * (1 + NEC_PRECITION)): + return False + if not (NEC_GAP * (1 - NEC_PRECITION) <= values[2] <= NEC_GAP * (1 + NEC_PRECITION)): + return False + return True diff --git a/demo_scripts/rc6.py b/demo_scripts/rc6.py new file mode 100644 index 0000000..dc215fb --- /dev/null +++ b/demo_scripts/rc6.py @@ -0,0 +1,82 @@ +RC6_T = 444 +RC6_PRECITION = 0.5 + +def rc6_decode(s): + b = bytes.fromhex(s) + values = [int.from_bytes(b[i:i+2], byteorder='little') for i in range(0, len(b), 2)] + if len(values) % 2 != 0: values.append(65535) + if not (RC6_T * (6 - RC6_PRECITION) <= values[0] <= RC6_T * (6 + RC6_PRECITION)): + raise ValueError(f"Invalid leading pulse length: {values[0]}") + if not (RC6_T * (2 - RC6_PRECITION) <= values[1] <= RC6_T * (2 + RC6_PRECITION)): + raise ValueError(f"Invalid leading gap length: {values[1]}") + i = 0 + bit = 0 + pos = 2 + while bit <= 20: + i = i << 1 + bit = bit + 1 + if pos % 2 == 1: i = i | 1 + if values[pos] < RC6_T*3/2 if (pos != 10) else RC6_T*3: + pos = pos + 2 + else: + pos = pos + 1 + info = i & 0xFF + control = (i >> 8) & 0xFF + toggle = (i >> 16) & 1 + mode = (i >> 17) & 0b111 + return {"info": info, "control": control, "toggle": toggle, "mode": mode} + +def rc6_encode(command, control = 0, toggle = 0, mode = 0): + if type(command) == dict: + info = command.get("info", 0) + control = command.get("control", 0) + toggle = command.get("toggle", 0) + mode = command.get("mode", 0) + elif type(command) == tuple: + info = command[0] + control = command[1] if len(command) > 1 else 0 + toggle = command[2] if len(command) > 2 else 0 + mode = command[3] if len(command) > 3 else 0 + elif type(command) == int: + info = command + else: + raise ValueError(f"Invalid command type: {type(command)}") + + pulses = [] + bits = [] + data = (1 << 20) | ((mode & 0b111) << 17) | ((toggle & 1) << 16) | ((control & 0xFF) << 8) | (info & 0xFF) + # Leading pulse + bits.append((1, RC6_T*6)) + bits.append((0, RC6_T*2)) + pulses.append(RC6_T*6) + pulses.append(RC6_T*2) + # Data + for i in range(20, -1, -1): + T = RC6_T if i != 16 else RC6_T * 2 + if ((data >> i) & 1 == 0): + bits.append(i) + bits.append(0) + bits.append((0, T)) + bits.append((1, T)) + if (len(pulses) % 2) == 0: + pulses[len(pulses) - 1] = pulses[len(pulses) - 1] + T + pulses.append(T) + else: + pulses.append(T) + pulses.append(T) + else: + bits.append(i) + bits.append(1) + bits.append((1, T)) + bits.append((0, T)) + if (len(pulses) % 2) == 1: + pulses[len(pulses) - 1] = pulses[len(pulses) - 1] + T + pulses.append(T) + else: + pulses.append(T) + pulses.append(T) + if (len(pulses) % 2 == 0): + pulses = pulses[0:len(pulses) - 1] + len2str = lambda i: f"{((i >> 8) | (i << 8)) & 0xFFFF:04x}" + s = "".join([len2str(pulse) for pulse in pulses]) + return s diff --git a/demo_scripts/receiver-test.py b/demo_scripts/receiver-test.py new file mode 100644 index 0000000..3057717 --- /dev/null +++ b/demo_scripts/receiver-test.py @@ -0,0 +1,27 @@ +#!/usr/bin/python3 + +from necrc import * +from rc6 import * + +DEVICE = "/dev/rc" + +with open(DEVICE, "r") as f: + while True: + raw = f.readline().strip() + # Try to decode button data using different encoding methods + try: + decoded = nec_decode(raw) + print("Decoded as NEC:", " ".join(f"{b:02x}" for b in decoded)) + continue + except: + pass + if is_nec_repeat(raw): + print("Decoded as NEC repeat code") + continue + try: + decoded = rc6_decode(raw) + print("Decoded as RC6:", decoded) + continue + except: + pass + print("Can't decode, raw data:", raw) diff --git a/demo_scripts/transmitter-test.py b/demo_scripts/transmitter-test.py new file mode 100644 index 0000000..152c95d --- /dev/null +++ b/demo_scripts/transmitter-test.py @@ -0,0 +1,20 @@ +#!/usr/bin/python3 + +from necrc import * +from rc6 import * +from time import sleep + +DEVICE = "/dev/rc" + +with open(DEVICE, "w") as f: + # Send '0' button code for Philips TV + raw = rc6_encode(command=0, control=0, toggle=0, mode=0) + f.write(raw + "\n") + f.flush() + + sleep(0.1) + + # Send NEC code + raw = nec_encode([0x00, 0xef, 0x03, 0xfc]) + f.write(raw + "\n") + f.flush() |