@springfield/ham-radio-utils 4.10.0 → 4.10.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -306,5 +306,53 @@
306
306
  "frequency": 162525000
307
307
  }
308
308
  ]
309
+ },
310
+ {
311
+ "id": "8edabffb-dbaf-4302-b7eb-c6d467bc67d8",
312
+ "name": "Weather Radio-8",
313
+ "wavelength": 1.85,
314
+ "lowerFrequency": 161650000,
315
+ "upperFrequency": 161650000,
316
+ "frequencyDisplayBaseMultiplier": 1000000,
317
+ "frequencyDisplayNumberDecimals": 3,
318
+ "privileges": ["9689b06f-dfb0-4ae6-8fdc-f9a4e6e1b88e"],
319
+ "channels": [
320
+ {
321
+ "name": "WX8",
322
+ "frequency": 161650000
323
+ }
324
+ ]
325
+ },
326
+ {
327
+ "id": "c0217f5d-54b8-42c3-b6ad-63d63972b19f",
328
+ "name": "Weather Radio-9",
329
+ "wavelength": 1.85,
330
+ "lowerFrequency": 161775000,
331
+ "upperFrequency": 161775000,
332
+ "frequencyDisplayBaseMultiplier": 1000000,
333
+ "frequencyDisplayNumberDecimals": 3,
334
+ "privileges": ["9689b06f-dfb0-4ae6-8fdc-f9a4e6e1b88e"],
335
+ "channels": [
336
+ {
337
+ "name": "WX9",
338
+ "frequency": 161775000
339
+ }
340
+ ]
341
+ },
342
+ {
343
+ "id": "8e2ccfe6-5be5-43c2-bbec-f80be8939464",
344
+ "name": "Weather Radio-10",
345
+ "wavelength": 1.85,
346
+ "lowerFrequency": 163275000,
347
+ "upperFrequency": 163275000,
348
+ "frequencyDisplayBaseMultiplier": 1000000,
349
+ "frequencyDisplayNumberDecimals": 3,
350
+ "privileges": ["9689b06f-dfb0-4ae6-8fdc-f9a4e6e1b88e"],
351
+ "channels": [
352
+ {
353
+ "name": "WX10",
354
+ "frequency": 163275000
355
+ }
356
+ ]
309
357
  }
310
358
  ]
@@ -25,6 +25,10 @@ export declare class MemoryMapRadioCodec implements RadioCodec {
25
25
  private readonly logger;
26
26
  constructor(options: MemoryMapRadioCodecOptions);
27
27
  decode(memory: RadioMemory): RadioProgram;
28
+ /**
29
+ * Patch `program` into a copy of `memory`. Existing image length is preserved
30
+ * (packed driver reads stay packed; sparse images stay sparse).
31
+ */
28
32
  encode(program: RadioProgram, memory: RadioMemory): RadioMemory;
29
33
  }
30
34
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"memory-map-radio-codec.d.ts","sourceRoot":"","sources":["../../src/memory/memory-map-radio-codec.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,UAAU,EACV,WAAW,EACX,iBAAiB,EACjB,cAAc,EACd,YAAY,EACZ,YAAY,EACb,MAAM,4BAA4B,CAAC;AACpC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAG1C;;GAEG;AACH,wBAAgB,eAAe,CAAC,YAAY,EAAE,iBAAiB,GAAG,MAAM,CAGvE;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,SAAS,EAAE,MAAM,GAAG,UAAU,CAIpE;AAED,MAAM,WAAW,0BAA0B;IACzC,UAAU,EAAE,YAAY,CAAC;IACzB,SAAS,EAAE,cAAc,CAAC;IAC1B,YAAY,EAAE,iBAAiB,CAAC;IAChC,MAAM,CAAC,EAAE,SAAS,CAAC;CACpB;AAED;;;GAGG;AACH,qBAAa,mBAAoB,YAAW,UAAU;IACpD,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAe;IAC1C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAiB;IAC3C,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAoB;IACjD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAwB;IAE/C,YAAY,OAAO,EAAE,0BAA0B,EAK9C;IAED,MAAM,CAAC,MAAM,EAAE,WAAW,GAAG,YAAY,CAOxC;IAED,MAAM,CAAC,OAAO,EAAE,YAAY,EAAE,MAAM,EAAE,WAAW,GAAG,WAAW,CA0B9D;CACF;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,0BAA0B,GAAG,UAAU,CAEpF"}
1
+ {"version":3,"file":"memory-map-radio-codec.d.ts","sourceRoot":"","sources":["../../src/memory/memory-map-radio-codec.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,UAAU,EACV,WAAW,EACX,iBAAiB,EACjB,cAAc,EACd,YAAY,EACZ,YAAY,EACb,MAAM,4BAA4B,CAAC;AACpC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAG1C;;GAEG;AACH,wBAAgB,eAAe,CAAC,YAAY,EAAE,iBAAiB,GAAG,MAAM,CAGvE;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,SAAS,EAAE,MAAM,GAAG,UAAU,CAIpE;AAED,MAAM,WAAW,0BAA0B;IACzC,UAAU,EAAE,YAAY,CAAC;IACzB,SAAS,EAAE,cAAc,CAAC;IAC1B,YAAY,EAAE,iBAAiB,CAAC;IAChC,MAAM,CAAC,EAAE,SAAS,CAAC;CACpB;AAED;;;GAGG;AACH,qBAAa,mBAAoB,YAAW,UAAU;IACpD,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAe;IAC1C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAiB;IAC3C,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAoB;IACjD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAwB;IAE/C,YAAY,OAAO,EAAE,0BAA0B,EAK9C;IAED,MAAM,CAAC,MAAM,EAAE,WAAW,GAAG,YAAY,CAOxC;IAED;;;OAGG;IACH,MAAM,CAAC,OAAO,EAAE,YAAY,EAAE,MAAM,EAAE,WAAW,GAAG,WAAW,CAY9D;CACF;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,0BAA0B,GAAG,UAAU,CAEpF"}
@@ -38,21 +38,12 @@ export class MemoryMapRadioCodec {
38
38
  return { channels: [], settings: {} };
39
39
  }
40
40
  }
41
+ /**
42
+ * Patch `program` into a copy of `memory`. Existing image length is preserved
43
+ * (packed driver reads stay packed; sparse images stay sparse).
44
+ */
41
45
  encode(program, memory) {
42
- const totalSize = memoryImageSize(this.memoryConfig);
43
- const contents = memory.contents.length > 0 ? new Uint8Array(memory.contents) : createEmptyMemoryImage(totalSize);
44
- if (contents.length < totalSize) {
45
- const expanded = createEmptyMemoryImage(totalSize);
46
- expanded.set(contents);
47
- try {
48
- encodeRadioProgram(this.memoryMap, program, expanded, this.memoryConfig);
49
- }
50
- catch (error) {
51
- this.logger?.withError(error).warn('Failed to encode radio program into memory map');
52
- }
53
- this.logger?.debug(`Memory size: ${expanded.length} bytes`);
54
- return { contents: expanded, radioModel: this.radioModel };
55
- }
46
+ const contents = memory.contents.length > 0 ? new Uint8Array(memory.contents) : createEmptyMemoryImage(memoryImageSize(this.memoryConfig));
56
47
  try {
57
48
  encodeRadioProgram(this.memoryMap, program, contents, this.memoryConfig);
58
49
  }
@@ -1 +1 @@
1
- {"version":3,"file":"memory-map-radio-codec.js","sourceRoot":"","sources":["../../src/memory/memory-map-radio-codec.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAElF;;GAEG;AACH,MAAM,UAAU,eAAe,CAAC,YAA+B;IAC7D,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IACvF,OAAO,IAAI,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC;AAC/B,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,sBAAsB,CAAC,SAAiB;IACtD,MAAM,MAAM,GAAG,IAAI,UAAU,CAAC,SAAS,CAAC,CAAC;IACzC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAClB,OAAO,MAAM,CAAC;AAChB,CAAC;AASD;;;GAGG;AACH,MAAM,OAAO,mBAAmB;IACb,UAAU,CAAe;IACzB,SAAS,CAAiB;IAC1B,YAAY,CAAoB;IAChC,MAAM,CAAwB;IAE/C,YAAY,OAAmC;QAC7C,IAAI,CAAC,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC;QACrC,IAAI,CAAC,SAAS,GAAG,OAAO,CAAC,SAAS,CAAC;QACnC,IAAI,CAAC,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC;QACzC,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAC/B,CAAC;IAED,MAAM,CAAC,MAAmB;QACxB,IAAI,CAAC;YACH,OAAO,kBAAkB,CAAC,IAAI,CAAC,SAAS,EAAE,MAAM,CAAC,QAAQ,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC;QAChF,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,MAAM,EAAE,SAAS,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,gDAAgD,CAAC,CAAC;YACrF,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;QACxC,CAAC;IACH,CAAC;IAED,MAAM,CAAC,OAAqB,EAAE,MAAmB;QAC/C,MAAM,SAAS,GAAG,eAAe,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QACrD,MAAM,QAAQ,GACZ,MAAM,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,UAAU,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,sBAAsB,CAAC,SAAS,CAAC,CAAC;QAEnG,IAAI,QAAQ,CAAC,MAAM,GAAG,SAAS,EAAE,CAAC;YAChC,MAAM,QAAQ,GAAG,sBAAsB,CAAC,SAAS,CAAC,CAAC;YACnD,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;YACvB,IAAI,CAAC;gBACH,kBAAkB,CAAC,IAAI,CAAC,SAAS,EAAE,OAAO,EAAE,QAAQ,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC;YAC3E,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,IAAI,CAAC,MAAM,EAAE,SAAS,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,gDAAgD,CAAC,CAAC;YACvF,CAAC;YAED,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,gBAAgB,QAAQ,CAAC,MAAM,QAAQ,CAAC,CAAC;YAC5D,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,UAAU,EAAE,IAAI,CAAC,UAAU,EAAE,CAAC;QAC7D,CAAC;QAED,IAAI,CAAC;YACH,kBAAkB,CAAC,IAAI,CAAC,SAAS,EAAE,OAAO,EAAE,QAAQ,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC;QAC3E,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,MAAM,EAAE,SAAS,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,gDAAgD,CAAC,CAAC;QACvF,CAAC;QAED,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,gBAAgB,QAAQ,CAAC,MAAM,QAAQ,CAAC,CAAC;QAC5D,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,IAAI,CAAC,UAAU,EAAE,CAAC;IACnD,CAAC;CACF;AAED;;GAEG;AACH,MAAM,UAAU,oBAAoB,CAAC,OAAmC;IACtE,OAAO,IAAI,mBAAmB,CAAC,OAAO,CAAC,CAAC;AAC1C,CAAC","sourcesContent":["import type {\n RadioCodec,\n RadioMemory,\n RadioMemoryConfig,\n RadioMemoryMap,\n RadioModelId,\n RadioProgram,\n} from '@springfield/ham-radio-api';\nimport type { ILogLayer } from 'loglayer';\nimport { decodeRadioProgram, encodeRadioProgram } from './memory-map-channels.js';\n\n/**\n * Compute the sparse image size that covers every configured memory segment.\n */\nexport function memoryImageSize(memoryConfig: RadioMemoryConfig): number {\n const ends = Object.values(memoryConfig.segments).map((segment) => segment.endAddress);\n return Math.max(...ends) + 1;\n}\n\n/**\n * Create a Chirp-like empty EEPROM image filled with 0xFF.\n */\nexport function createEmptyMemoryImage(totalSize: number): Uint8Array {\n const memory = new Uint8Array(totalSize);\n memory.fill(0xff);\n return memory;\n}\n\nexport interface MemoryMapRadioCodecOptions {\n radioModel: RadioModelId;\n memoryMap: RadioMemoryMap;\n memoryConfig: RadioMemoryConfig;\n logger?: ILogLayer;\n}\n\n/**\n * Generic RadioCodec driven entirely by a JSON memory map + memoryConfig.\n * Radio modules that ship DSL JSON do not need TypeScript codecs.\n */\nexport class MemoryMapRadioCodec implements RadioCodec {\n private readonly radioModel: RadioModelId;\n private readonly memoryMap: RadioMemoryMap;\n private readonly memoryConfig: RadioMemoryConfig;\n private readonly logger: ILogLayer | undefined;\n\n constructor(options: MemoryMapRadioCodecOptions) {\n this.radioModel = options.radioModel;\n this.memoryMap = options.memoryMap;\n this.memoryConfig = options.memoryConfig;\n this.logger = options.logger;\n }\n\n decode(memory: RadioMemory): RadioProgram {\n try {\n return decodeRadioProgram(this.memoryMap, memory.contents, this.memoryConfig);\n } catch (error) {\n this.logger?.withError(error).warn('Failed to decode radio program from memory map');\n return { channels: [], settings: {} };\n }\n }\n\n encode(program: RadioProgram, memory: RadioMemory): RadioMemory {\n const totalSize = memoryImageSize(this.memoryConfig);\n const contents =\n memory.contents.length > 0 ? new Uint8Array(memory.contents) : createEmptyMemoryImage(totalSize);\n\n if (contents.length < totalSize) {\n const expanded = createEmptyMemoryImage(totalSize);\n expanded.set(contents);\n try {\n encodeRadioProgram(this.memoryMap, program, expanded, this.memoryConfig);\n } catch (error) {\n this.logger?.withError(error).warn('Failed to encode radio program into memory map');\n }\n\n this.logger?.debug(`Memory size: ${expanded.length} bytes`);\n return { contents: expanded, radioModel: this.radioModel };\n }\n\n try {\n encodeRadioProgram(this.memoryMap, program, contents, this.memoryConfig);\n } catch (error) {\n this.logger?.withError(error).warn('Failed to encode radio program into memory map');\n }\n\n this.logger?.debug(`Memory size: ${contents.length} bytes`);\n return { contents, radioModel: this.radioModel };\n }\n}\n\n/**\n * Create a memory-map codec from hydrated radio config fields.\n */\nexport function createMemoryMapCodec(options: MemoryMapRadioCodecOptions): RadioCodec {\n return new MemoryMapRadioCodec(options);\n}\n"]}
1
+ {"version":3,"file":"memory-map-radio-codec.js","sourceRoot":"","sources":["../../src/memory/memory-map-radio-codec.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAElF;;GAEG;AACH,MAAM,UAAU,eAAe,CAAC,YAA+B;IAC7D,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IACvF,OAAO,IAAI,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC;AAC/B,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,sBAAsB,CAAC,SAAiB;IACtD,MAAM,MAAM,GAAG,IAAI,UAAU,CAAC,SAAS,CAAC,CAAC;IACzC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAClB,OAAO,MAAM,CAAC;AAChB,CAAC;AASD;;;GAGG;AACH,MAAM,OAAO,mBAAmB;IACb,UAAU,CAAe;IACzB,SAAS,CAAiB;IAC1B,YAAY,CAAoB;IAChC,MAAM,CAAwB;IAE/C,YAAY,OAAmC;QAC7C,IAAI,CAAC,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC;QACrC,IAAI,CAAC,SAAS,GAAG,OAAO,CAAC,SAAS,CAAC;QACnC,IAAI,CAAC,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC;QACzC,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAC/B,CAAC;IAED,MAAM,CAAC,MAAmB;QACxB,IAAI,CAAC;YACH,OAAO,kBAAkB,CAAC,IAAI,CAAC,SAAS,EAAE,MAAM,CAAC,QAAQ,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC;QAChF,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,MAAM,EAAE,SAAS,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,gDAAgD,CAAC,CAAC;YACrF,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;QACxC,CAAC;IACH,CAAC;IAED;;;OAGG;IACH,MAAM,CAAC,OAAqB,EAAE,MAAmB;QAC/C,MAAM,QAAQ,GACZ,MAAM,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,UAAU,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,sBAAsB,CAAC,eAAe,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC;QAE5H,IAAI,CAAC;YACH,kBAAkB,CAAC,IAAI,CAAC,SAAS,EAAE,OAAO,EAAE,QAAQ,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC;QAC3E,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,MAAM,EAAE,SAAS,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,gDAAgD,CAAC,CAAC;QACvF,CAAC;QAED,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,gBAAgB,QAAQ,CAAC,MAAM,QAAQ,CAAC,CAAC;QAC5D,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,IAAI,CAAC,UAAU,EAAE,CAAC;IACnD,CAAC;CACF;AAED;;GAEG;AACH,MAAM,UAAU,oBAAoB,CAAC,OAAmC;IACtE,OAAO,IAAI,mBAAmB,CAAC,OAAO,CAAC,CAAC;AAC1C,CAAC","sourcesContent":["import type {\n RadioCodec,\n RadioMemory,\n RadioMemoryConfig,\n RadioMemoryMap,\n RadioModelId,\n RadioProgram,\n} from '@springfield/ham-radio-api';\nimport type { ILogLayer } from 'loglayer';\nimport { decodeRadioProgram, encodeRadioProgram } from './memory-map-channels.js';\n\n/**\n * Compute the sparse image size that covers every configured memory segment.\n */\nexport function memoryImageSize(memoryConfig: RadioMemoryConfig): number {\n const ends = Object.values(memoryConfig.segments).map((segment) => segment.endAddress);\n return Math.max(...ends) + 1;\n}\n\n/**\n * Create a Chirp-like empty EEPROM image filled with 0xFF.\n */\nexport function createEmptyMemoryImage(totalSize: number): Uint8Array {\n const memory = new Uint8Array(totalSize);\n memory.fill(0xff);\n return memory;\n}\n\nexport interface MemoryMapRadioCodecOptions {\n radioModel: RadioModelId;\n memoryMap: RadioMemoryMap;\n memoryConfig: RadioMemoryConfig;\n logger?: ILogLayer;\n}\n\n/**\n * Generic RadioCodec driven entirely by a JSON memory map + memoryConfig.\n * Radio modules that ship DSL JSON do not need TypeScript codecs.\n */\nexport class MemoryMapRadioCodec implements RadioCodec {\n private readonly radioModel: RadioModelId;\n private readonly memoryMap: RadioMemoryMap;\n private readonly memoryConfig: RadioMemoryConfig;\n private readonly logger: ILogLayer | undefined;\n\n constructor(options: MemoryMapRadioCodecOptions) {\n this.radioModel = options.radioModel;\n this.memoryMap = options.memoryMap;\n this.memoryConfig = options.memoryConfig;\n this.logger = options.logger;\n }\n\n decode(memory: RadioMemory): RadioProgram {\n try {\n return decodeRadioProgram(this.memoryMap, memory.contents, this.memoryConfig);\n } catch (error) {\n this.logger?.withError(error).warn('Failed to decode radio program from memory map');\n return { channels: [], settings: {} };\n }\n }\n\n /**\n * Patch `program` into a copy of `memory`. Existing image length is preserved\n * (packed driver reads stay packed; sparse images stay sparse).\n */\n encode(program: RadioProgram, memory: RadioMemory): RadioMemory {\n const contents =\n memory.contents.length > 0 ? new Uint8Array(memory.contents) : createEmptyMemoryImage(memoryImageSize(this.memoryConfig));\n\n try {\n encodeRadioProgram(this.memoryMap, program, contents, this.memoryConfig);\n } catch (error) {\n this.logger?.withError(error).warn('Failed to encode radio program into memory map');\n }\n\n this.logger?.debug(`Memory size: ${contents.length} bytes`);\n return { contents, radioModel: this.radioModel };\n }\n}\n\n/**\n * Create a memory-map codec from hydrated radio config fields.\n */\nexport function createMemoryMapCodec(options: MemoryMapRadioCodecOptions): RadioCodec {\n return new MemoryMapRadioCodec(options);\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@springfield/ham-radio-utils",
3
- "version": "4.10.0",
3
+ "version": "4.10.2",
4
4
  "author": "Bryan Hunt",
5
5
  "license": "MIT",
6
6
  "readme": "README.md",
package/src/db/bands.json CHANGED
@@ -306,5 +306,53 @@
306
306
  "frequency": 162525000
307
307
  }
308
308
  ]
309
+ },
310
+ {
311
+ "id": "8edabffb-dbaf-4302-b7eb-c6d467bc67d8",
312
+ "name": "Weather Radio-8",
313
+ "wavelength": 1.85,
314
+ "lowerFrequency": 161650000,
315
+ "upperFrequency": 161650000,
316
+ "frequencyDisplayBaseMultiplier": 1000000,
317
+ "frequencyDisplayNumberDecimals": 3,
318
+ "privileges": ["9689b06f-dfb0-4ae6-8fdc-f9a4e6e1b88e"],
319
+ "channels": [
320
+ {
321
+ "name": "WX8",
322
+ "frequency": 161650000
323
+ }
324
+ ]
325
+ },
326
+ {
327
+ "id": "c0217f5d-54b8-42c3-b6ad-63d63972b19f",
328
+ "name": "Weather Radio-9",
329
+ "wavelength": 1.85,
330
+ "lowerFrequency": 161775000,
331
+ "upperFrequency": 161775000,
332
+ "frequencyDisplayBaseMultiplier": 1000000,
333
+ "frequencyDisplayNumberDecimals": 3,
334
+ "privileges": ["9689b06f-dfb0-4ae6-8fdc-f9a4e6e1b88e"],
335
+ "channels": [
336
+ {
337
+ "name": "WX9",
338
+ "frequency": 161775000
339
+ }
340
+ ]
341
+ },
342
+ {
343
+ "id": "8e2ccfe6-5be5-43c2-bbec-f80be8939464",
344
+ "name": "Weather Radio-10",
345
+ "wavelength": 1.85,
346
+ "lowerFrequency": 163275000,
347
+ "upperFrequency": 163275000,
348
+ "frequencyDisplayBaseMultiplier": 1000000,
349
+ "frequencyDisplayNumberDecimals": 3,
350
+ "privileges": ["9689b06f-dfb0-4ae6-8fdc-f9a4e6e1b88e"],
351
+ "channels": [
352
+ {
353
+ "name": "WX10",
354
+ "frequency": 163275000
355
+ }
356
+ ]
309
357
  }
310
358
  ]
@@ -59,23 +59,13 @@ export class MemoryMapRadioCodec implements RadioCodec {
59
59
  }
60
60
  }
61
61
 
62
+ /**
63
+ * Patch `program` into a copy of `memory`. Existing image length is preserved
64
+ * (packed driver reads stay packed; sparse images stay sparse).
65
+ */
62
66
  encode(program: RadioProgram, memory: RadioMemory): RadioMemory {
63
- const totalSize = memoryImageSize(this.memoryConfig);
64
67
  const contents =
65
- memory.contents.length > 0 ? new Uint8Array(memory.contents) : createEmptyMemoryImage(totalSize);
66
-
67
- if (contents.length < totalSize) {
68
- const expanded = createEmptyMemoryImage(totalSize);
69
- expanded.set(contents);
70
- try {
71
- encodeRadioProgram(this.memoryMap, program, expanded, this.memoryConfig);
72
- } catch (error) {
73
- this.logger?.withError(error).warn('Failed to encode radio program into memory map');
74
- }
75
-
76
- this.logger?.debug(`Memory size: ${expanded.length} bytes`);
77
- return { contents: expanded, radioModel: this.radioModel };
78
- }
68
+ memory.contents.length > 0 ? new Uint8Array(memory.contents) : createEmptyMemoryImage(memoryImageSize(this.memoryConfig));
79
69
 
80
70
  try {
81
71
  encodeRadioProgram(this.memoryMap, program, contents, this.memoryConfig);