this repo has no description

Move more broadly-useful helper functions to their own files

harperandrews.org e6e07e62 f4f0bb7e

verified
+104 -101
+6 -101
src/applets/UnfoldedHexToSony.ts
··· 1 1 import { question, type PromptValidator } from "@topcli/prompts"; 2 2 import type { Applet } from "../Applet.js"; 3 - 4 - /* 5 - * Information on the Sony IR protocol (SIRC): 6 - * http://www.sbprojects.net/knowledge/ir/sirc.php 7 - */ 8 - 9 - interface SonyProtocolVariation { 10 - commandLengthBits: 7; 11 - deviceTypeLengthBits: 5 | 8; 12 - extensionLengthBits: 0 | 8; 13 - } 14 - 15 - const SONY_PROTOCOL_12_BITS: SonyProtocolVariation = { 16 - commandLengthBits: 7, 17 - deviceTypeLengthBits: 5, 18 - extensionLengthBits: 0, 19 - }; 20 - const SONY_PROTOCOL_15_BITS: SonyProtocolVariation = { 21 - commandLengthBits: 7, 22 - deviceTypeLengthBits: 8, 23 - extensionLengthBits: 0, 24 - }; 25 - const SONY_PROTOCOL_20_BITS: SonyProtocolVariation = { 26 - commandLengthBits: 7, 27 - deviceTypeLengthBits: 5, 28 - extensionLengthBits: 8, 29 - }; 30 - const DATA_LENGTH_BITS_TO_SONY_PROTOCOL_VARIATION = new Map< 31 - number, 32 - SonyProtocolVariation 33 - >([ 34 - [12, SONY_PROTOCOL_12_BITS], 35 - [15, SONY_PROTOCOL_15_BITS], 36 - [20, SONY_PROTOCOL_20_BITS], 37 - ]); 3 + import { DATA_LENGTH_BITS_TO_SONY_PROTOCOL_VARIATION } from "../util/sony.ts"; 4 + import { extractNum } from "../util/bit-manipulation.ts"; 5 + import { 6 + parseUnfoldedHex, 7 + UNFOLDED_CIRCLE_PROTOCOL_SONY, 8 + } from "../util/unfolded-circle.ts"; 38 9 39 10 // `<string>` is commented out and we have to check the type because of https://github.com/TopCli/prompts/issues/147 40 11 const sonyUnfoldedHexValidator: PromptValidator /*<string>*/ = { ··· 122 93 console.log(`Extension: ${extension}`); 123 94 }, 124 95 }; 125 - 126 - ///////////////////////////// 127 - 128 - const UNFOLDED_CIRCLE_PROTOCOL_SONY = 4; 129 - 130 - interface ParsedUnfoldedHex { 131 - protocolNum: number; 132 - data: number; 133 - dataLengthBits: number; 134 - repeatCount: number; 135 - } 136 - 137 - function parseUnfoldedHex(unfoldedHex: string): ParsedUnfoldedHex | undefined { 138 - const match = unfoldedHex.match( 139 - /(?<protocolNum>\d+);(?<hexData>0x[0-9A-Fa-f]+);(?<dataLengthBits>\d+);(?<repeatCount>\d+)/, 140 - ); 141 - if (match == null) { 142 - return undefined; 143 - } 144 - 145 - return { 146 - protocolNum: Number.parseInt(match.groups!["protocolNum"]!), 147 - data: Number.parseInt(match.groups!["hexData"]!), 148 - dataLengthBits: Number.parseInt(match.groups!["dataLengthBits"]!), 149 - repeatCount: Number.parseInt(match.groups!["repeatCount"]!), 150 - }; 151 - } 152 - 153 - function getMaxUnsignedInt(lengthBits: number): number { 154 - return (1 << lengthBits) - 1; 155 - } 156 - 157 - function extractNum(params: { 158 - input: number; 159 - extractedNumLengthBits: number; 160 - leastSignificantBit: number; 161 - reverseResultBits: boolean; 162 - }): number { 163 - const mask = 164 - getMaxUnsignedInt(params.extractedNumLengthBits) << 165 - params.leastSignificantBit; 166 - let result = params.input & mask; 167 - result = result >> params.leastSignificantBit; 168 - 169 - if (params.reverseResultBits) { 170 - result = reverseBits(result, params.extractedNumLengthBits); 171 - } 172 - return result; 173 - } 174 - 175 - // Copied (with type annotations added and a parameter renamed) from https://stackoverflow.com/a/67064710 176 - // under the CC BY-SA 4.0 license (https://creativecommons.org/licenses/by-sa/4.0/) 177 - function reverseBits(integer: number, sizeBits: number): number { 178 - if (sizeBits > 32) { 179 - throw Error( 180 - "Bit manipulation is limited to <= 32 bit numbers in JavaScript.", 181 - ); 182 - } 183 - 184 - let result = 0; 185 - for (let i = 0; i < sizeBits; i++) { 186 - result |= ((integer >> i) & 1) << (sizeBits - 1 - i); 187 - } 188 - 189 - return result >>> 0; // >>> 0 makes it unsigned even if bit 32 (the sign bit) was set 190 - }
+38
src/util/bit-manipulation.ts
··· 1 + export function extractNum(params: { 2 + input: number; 3 + extractedNumLengthBits: number; 4 + leastSignificantBit: number; 5 + reverseResultBits: boolean; 6 + }): number { 7 + const mask = 8 + getMaxUnsignedInt(params.extractedNumLengthBits) << 9 + params.leastSignificantBit; 10 + let result = params.input & mask; 11 + result = result >> params.leastSignificantBit; 12 + 13 + if (params.reverseResultBits) { 14 + result = reverseBits(result, params.extractedNumLengthBits); 15 + } 16 + return result; 17 + } 18 + 19 + // Copied (with type annotations added and a parameter renamed) from https://stackoverflow.com/a/67064710 20 + // under the CC BY-SA 4.0 license (https://creativecommons.org/licenses/by-sa/4.0/) 21 + export function reverseBits(integer: number, sizeBits: number): number { 22 + if (sizeBits > 32) { 23 + throw Error( 24 + "Bit manipulation is limited to <= 32 bit numbers in JavaScript.", 25 + ); 26 + } 27 + 28 + let result = 0; 29 + for (let i = 0; i < sizeBits; i++) { 30 + result |= ((integer >> i) & 1) << (sizeBits - 1 - i); 31 + } 32 + 33 + return result >>> 0; // >>> 0 makes it unsigned even if bit 32 (the sign bit) was set 34 + } 35 + 36 + export function getMaxUnsignedInt(lengthBits: number): number { 37 + return (1 << lengthBits) - 1; 38 + }
+34
src/util/sony.ts
··· 1 + /* 2 + * Information on the Sony IR protocol (SIRC): 3 + * http://www.sbprojects.net/knowledge/ir/sirc.php 4 + */ 5 + 6 + export interface SonyProtocolVariation { 7 + commandLengthBits: 7; 8 + deviceTypeLengthBits: 5 | 8; 9 + extensionLengthBits: 0 | 8; 10 + } 11 + 12 + const SONY_PROTOCOL_12_BITS: SonyProtocolVariation = { 13 + commandLengthBits: 7, 14 + deviceTypeLengthBits: 5, 15 + extensionLengthBits: 0, 16 + }; 17 + const SONY_PROTOCOL_15_BITS: SonyProtocolVariation = { 18 + commandLengthBits: 7, 19 + deviceTypeLengthBits: 8, 20 + extensionLengthBits: 0, 21 + }; 22 + const SONY_PROTOCOL_20_BITS: SonyProtocolVariation = { 23 + commandLengthBits: 7, 24 + deviceTypeLengthBits: 5, 25 + extensionLengthBits: 8, 26 + }; 27 + export const DATA_LENGTH_BITS_TO_SONY_PROTOCOL_VARIATION = new Map< 28 + number, 29 + SonyProtocolVariation 30 + >([ 31 + [12, SONY_PROTOCOL_12_BITS], 32 + [15, SONY_PROTOCOL_15_BITS], 33 + [20, SONY_PROTOCOL_20_BITS], 34 + ]);
+26
src/util/unfolded-circle.ts
··· 1 + export const UNFOLDED_CIRCLE_PROTOCOL_SONY = 4; 2 + 3 + export interface ParsedUnfoldedHex { 4 + protocolNum: number; 5 + data: number; 6 + dataLengthBits: number; 7 + repeatCount: number; 8 + } 9 + 10 + export function parseUnfoldedHex( 11 + unfoldedHex: string, 12 + ): ParsedUnfoldedHex | undefined { 13 + const match = unfoldedHex.match( 14 + /(?<protocolNum>\d+);(?<hexData>0x[0-9A-Fa-f]+);(?<dataLengthBits>\d+);(?<repeatCount>\d+)/, 15 + ); 16 + if (match == null) { 17 + return undefined; 18 + } 19 + 20 + return { 21 + protocolNum: Number.parseInt(match.groups!["protocolNum"]!), 22 + data: Number.parseInt(match.groups!["hexData"]!), 23 + dataLengthBits: Number.parseInt(match.groups!["dataLengthBits"]!), 24 + repeatCount: Number.parseInt(match.groups!["repeatCount"]!), 25 + }; 26 + }