led-matrix-controllers 0.2.2 → 0.2.3

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.
@@ -1,89 +1,89 @@
1
- import { GAMMA } from '../../../hardware-constants.js';
2
- import { Command, IDENTITY_STR_LEN } from './commands.js';
3
-
4
- export class CommandAbstractionLayer {
5
- constructor(portMutex = null) {
6
- this.portMutex = portMutex;
7
- }
8
-
9
- async bootloader() {
10
- await this.portMutex.acquire(async p => {
11
- await p.tx([Command.BOOTLOADER]);
12
- });
13
- }
14
-
15
- async identityString() {
16
- let ident = null;
17
-
18
- await this.portMutex.acquire(async p => {
19
- await p.tx([Command.IDENTITY_STRING]);
20
- ident = await p.rx(IDENTITY_STR_LEN);
21
- });
22
-
23
- return String.fromCharCode(...ident);
24
- }
25
-
26
- async setPixelPwm(r, c, brightness) {
27
- await this.portMutex.acquire(
28
- async p => {
29
- await p.tx([Command.SET_PX_PWM, c, r, brightness]);
30
- }
31
- );
32
- }
33
-
34
- async setGlobalPwm(brightness) {
35
- await this.portMutex.acquire(
36
- async p => {
37
- await p.tx([Command.SET_CONST_PWM, brightness]);
38
- }
39
- );
40
- }
41
-
42
- async setMatrixPwm(matrix) {
43
- // Only execute the most recent call
44
- await this.portMutex.acquireIdempotent(
45
- 'drawMatrix',
46
- async p => {
47
- await p.tx(
48
- [Command.DRAW_PWM].concat(
49
- matrix.flat().map(v =>
50
- GAMMA[Math.floor((v ?? 0) * 255)]
51
- )
52
- )
53
- );
54
- }
55
- );
56
- }
57
-
58
- async setPixelAnalog(r, c, brightness) {
59
- await this.portMutex.acquire(
60
- async p => {
61
- await p.tx([Command.SET_PX_SCALE, c, r, brightness]);
62
- }
63
- );
64
- }
65
-
66
- async setGlobalAnalog(brightness) {
67
- await this.portMutex.acquire(
68
- async p => {
69
- await p.tx([Command.SET_CONST_SCALE, brightness]);
70
- }
71
- );
72
- }
73
-
74
- async setMatrixAnalog(matrix) {
75
- // Only execute the most recent call
76
- await this.portMutex.acquireIdempotent(
77
- 'drawMatrix',
78
- async p => {
79
- await p.tx(
80
- [Command.DRAW_SCALE].concat(
81
- matrix.flat().map(v =>
82
- GAMMA[Math.floor((v ?? 0) * 255)]
83
- )
84
- )
85
- );
86
- }
87
- );
88
- }
89
- }
1
+ import { GAMMA } from '../../../hardware-constants.js';
2
+ import { Command, IDENTITY_STR_LEN } from './commands.js';
3
+
4
+ export class CommandAbstractionLayer {
5
+ constructor(portMutex = null) {
6
+ this.portMutex = portMutex;
7
+ }
8
+
9
+ async bootloader() {
10
+ await this.portMutex.acquire(async p => {
11
+ await p.tx([Command.BOOTLOADER]);
12
+ });
13
+ }
14
+
15
+ async identityString() {
16
+ let ident = null;
17
+
18
+ await this.portMutex.acquire(async p => {
19
+ await p.tx([Command.IDENTITY_STRING]);
20
+ ident = await p.rx(IDENTITY_STR_LEN);
21
+ });
22
+
23
+ return String.fromCharCode(...ident);
24
+ }
25
+
26
+ async setPixelPwm(r, c, brightness) {
27
+ await this.portMutex.acquire(
28
+ async p => {
29
+ await p.tx([Command.SET_PX_PWM, c, r, brightness]);
30
+ }
31
+ );
32
+ }
33
+
34
+ async setGlobalPwm(brightness) {
35
+ await this.portMutex.acquire(
36
+ async p => {
37
+ await p.tx([Command.SET_CONST_PWM, brightness]);
38
+ }
39
+ );
40
+ }
41
+
42
+ async setMatrixPwm(matrix) {
43
+ // Only execute the most recent call
44
+ await this.portMutex.acquireIdempotent(
45
+ 'drawMatrix',
46
+ async p => {
47
+ await p.tx(
48
+ [Command.DRAW_PWM].concat(
49
+ matrix.flat().map(v =>
50
+ GAMMA[Math.floor((v ?? 0) * 255)]
51
+ )
52
+ )
53
+ );
54
+ }
55
+ );
56
+ }
57
+
58
+ async setPixelAnalog(r, c, brightness) {
59
+ await this.portMutex.acquire(
60
+ async p => {
61
+ await p.tx([Command.SET_PX_SCALE, c, r, brightness]);
62
+ }
63
+ );
64
+ }
65
+
66
+ async setGlobalAnalog(brightness) {
67
+ await this.portMutex.acquire(
68
+ async p => {
69
+ await p.tx([Command.SET_CONST_SCALE, brightness]);
70
+ }
71
+ );
72
+ }
73
+
74
+ async setMatrixAnalog(matrix) {
75
+ // Only execute the most recent call
76
+ await this.portMutex.acquireIdempotent(
77
+ 'drawMatrix',
78
+ async p => {
79
+ await p.tx(
80
+ [Command.DRAW_SCALE].concat(
81
+ matrix.flat().map(v =>
82
+ GAMMA[Math.floor((v ?? 0) * 255)]
83
+ )
84
+ )
85
+ );
86
+ }
87
+ );
88
+ }
89
+ }
@@ -1,50 +1,50 @@
1
- import { close, getPort } from '../../../web-serial/port.js';
2
- import { PortMutex } from '../../../web-serial/PortMutex.js';
3
- import { PortOperations } from '../../../web-serial/PortOperations.js';
4
- import { CommandAbstractionLayer } from './CommandAbstractionLayer.js';
5
- import { IDENTITY_STR_REGEX } from './commands.js';
6
-
7
- export class SigrootController extends CommandAbstractionLayer {
8
- async bootloader() {
9
- await super.bootloader();
10
- }
11
-
12
- async connect() {
13
- const port = await getPort();
14
-
15
- if (port?.connected) {
16
- await close(port);
17
- await port.open({ baudRate: 115200 });
18
- this.portMutex = new PortMutex(new PortOperations(port));
19
- }
20
- }
21
-
22
- async draw(matrix) {
23
- if (!this.#scaleInitialized) {
24
- await super.setGlobalAnalog(0x20);
25
- this.#scaleInitialized = true;
26
- }
27
-
28
- await super.setMatrixPwm(matrix);
29
- }
30
-
31
- async verifyFirmware() {
32
- return await this.version() != null;
33
- }
34
-
35
- async version() {
36
- const ident = await super.identityString();
37
- const match = ident.match(IDENTITY_STR_REGEX);
38
-
39
- if (match && match.length == 3) {
40
- return {
41
- major: match[1],
42
- minor: match[2]
43
- }
44
- } else {
45
- return null;
46
- }
47
- }
48
-
49
- #scaleInitialized;
50
- }
1
+ import { close, getPort } from '../../../web-serial/port.js';
2
+ import { PortMutex } from '../../../web-serial/PortMutex.js';
3
+ import { PortOperations } from '../../../web-serial/PortOperations.js';
4
+ import { CommandAbstractionLayer } from './CommandAbstractionLayer.js';
5
+ import { IDENTITY_STR_REGEX } from './commands.js';
6
+
7
+ export class SigrootController extends CommandAbstractionLayer {
8
+ async bootloader() {
9
+ await super.bootloader();
10
+ }
11
+
12
+ async connect() {
13
+ const port = await getPort();
14
+
15
+ if (port?.connected) {
16
+ await close(port);
17
+ await port.open({ baudRate: 115200 });
18
+ this.portMutex = new PortMutex(new PortOperations(port));
19
+ }
20
+ }
21
+
22
+ async draw(matrix) {
23
+ if (!this.#scaleInitialized) {
24
+ await super.setGlobalAnalog(0x20);
25
+ this.#scaleInitialized = true;
26
+ }
27
+
28
+ await super.setMatrixPwm(matrix);
29
+ }
30
+
31
+ async verifyFirmware() {
32
+ return await this.version() != null;
33
+ }
34
+
35
+ async version() {
36
+ const ident = await super.identityString();
37
+ const match = ident.match(IDENTITY_STR_REGEX);
38
+
39
+ if (match && match.length == 3) {
40
+ return {
41
+ major: match[1],
42
+ minor: match[2]
43
+ }
44
+ } else {
45
+ return null;
46
+ }
47
+ }
48
+
49
+ #scaleInitialized;
50
+ }
@@ -1,26 +1,26 @@
1
- export const Command = Object.freeze({
2
- /* 000 */ NOOP: 0x00,
3
- /* 'd' */ ANIMATION_DIAMOND: 0x64,
4
- /* 'b' */ ANIMATION_FIRE: 0x62,
5
- /* 'f' */ ANIMATION_FIREPLACE: 0x66,
6
- /* 'g' */ ANIMATION_GEAR: 0x67,
7
- /* 'r' */ ANIMATION_RING: 0x72,
8
- /* 'a' */ ANIMATION_STARTUP: 0x61,
9
- /* 'A' */ ANIMATION_STARTUP_ONCE: 0x41,
10
- /* 'e' */ BOOTLOADER: 0x65,
11
- /* 'm' */ DRAW_PWM: 0x6D,
12
- /* 'M' */ DRAW_PWM_BLOCKING: 0x4D,
13
- /* 'n' */ DRAW_SCALE: 0x6E,
14
- /* 'N' */ DRAW_SCALE_BLOCKING: 0x4E,
15
- /* 'c' */ FLUSH_CMD_QUEUE: 0x63,
16
- /* 't' */ TEST_PATTERN: 0x74,
17
- /* 'w' */ SET_CONST_PWM: 0x77,
18
- /* 's' */ SET_CONST_SCALE: 0x73,
19
- /* 'p' */ SET_PX_PWM: 0x70,
20
- /* 'q' */ SET_PX_SCALE: 0x71,
21
- /* 127 */ IDENTITY_STRING: 0x7F,
22
- });
23
-
24
- export const IDENTITY_STR_LEN = 25;
25
-
26
- export const IDENTITY_STR_REGEX = /^Sig\sFW\sLED\sMatrix\sFW\sV(\d+)\.(\d+)$/;
1
+ export const Command = Object.freeze({
2
+ /* 000 */ NOOP: 0x00,
3
+ /* 'd' */ ANIMATION_DIAMOND: 0x64,
4
+ /* 'b' */ ANIMATION_FIRE: 0x62,
5
+ /* 'f' */ ANIMATION_FIREPLACE: 0x66,
6
+ /* 'g' */ ANIMATION_GEAR: 0x67,
7
+ /* 'r' */ ANIMATION_RING: 0x72,
8
+ /* 'a' */ ANIMATION_STARTUP: 0x61,
9
+ /* 'A' */ ANIMATION_STARTUP_ONCE: 0x41,
10
+ /* 'e' */ BOOTLOADER: 0x65,
11
+ /* 'm' */ DRAW_PWM: 0x6D,
12
+ /* 'M' */ DRAW_PWM_BLOCKING: 0x4D,
13
+ /* 'n' */ DRAW_SCALE: 0x6E,
14
+ /* 'N' */ DRAW_SCALE_BLOCKING: 0x4E,
15
+ /* 'c' */ FLUSH_CMD_QUEUE: 0x63,
16
+ /* 't' */ TEST_PATTERN: 0x74,
17
+ /* 'w' */ SET_CONST_PWM: 0x77,
18
+ /* 's' */ SET_CONST_SCALE: 0x73,
19
+ /* 'p' */ SET_PX_PWM: 0x70,
20
+ /* 'q' */ SET_PX_SCALE: 0x71,
21
+ /* 127 */ IDENTITY_STRING: 0x7F,
22
+ });
23
+
24
+ export const IDENTITY_STR_LEN = 25;
25
+
26
+ export const IDENTITY_STR_REGEX = /^Sig\sFW\sLED\sMatrix\sFW\sV(\d+)\.(\d+)$/;
@@ -1,115 +1,115 @@
1
- import { GAMMA } from '../../../hardware-constants.js';
2
- import { Commands, Reports } from './reports.js';
3
-
4
- export class ReportAbstractionLayer {
5
- constructor(device = null) {
6
- this.device = device;
7
- }
8
-
9
- async info() {
10
- const infoRaw = await this.device.request(Reports.GLITTER_DEVICE_INFO);
11
-
12
- return {
13
- sleep_pin: infoRaw.getUint8(1),
14
- dip1_pin: infoRaw.getUint8(2),
15
- intb_pin: infoRaw.getUint8(3),
16
- state_flags: infoRaw.getUint8(4),
17
- id_reg: infoRaw.getUint8(5),
18
- config_reg: infoRaw.getUint8(6),
19
- global_brightness: infoRaw.getUint8(7),
20
- display_width: infoRaw.getUint8(8),
21
- display_height: infoRaw.getUint8(9),
22
- timeout_ms: infoRaw.getUint32(10),
23
- version_major: infoRaw.getUint8(14),
24
- version_minor: infoRaw.getUint8(15),
25
- };
26
- }
27
-
28
- async wake() {
29
- await this.device.send(
30
- Reports.GLITTER_BASIC_CMD,
31
- [Commands.GLITTER_CMD_SLEEP, false]
32
- );
33
- }
34
-
35
- async sleep() {
36
- await this.device.send(
37
- Reports.GLITTER_BASIC_CMD,
38
- [Commands.GLITTER_CMD_SLEEP, true]
39
- );
40
- }
41
-
42
- async disableSleep() {
43
- await this.device.send(
44
- Reports.GLITTER_BASIC_CMD,
45
- [Commands.GLITTER_CMD_SET_SLEEP_TIMEOUT, 0xff, 0xff, 0xff, 0xff]
46
- );
47
- }
48
-
49
- async disableDeepSleep() {
50
- await this.device.send(
51
- Reports.GLITTER_BASIC_CMD,
52
- [Commands.GLITTER_CMD_WAKE_ON_COMMAND, 0x01]
53
- );
54
- }
55
-
56
- async disableSleepTimer() {
57
- await this.device.send(
58
- Reports.GLITTER_BASIC_CMD,
59
- [Commands.GLITTER_CMD_SET_SLEEP_TIMEOUT, 0x00, 0x00, 0x00, 0x00]
60
- );
61
- }
62
-
63
- async enableDeepSleep() {
64
- await this.device.send(
65
- Reports.GLITTER_BASIC_CMD,
66
- [Commands.GLITTER_CMD_WAKE_ON_COMMAND, 0x00]
67
- );
68
- }
69
-
70
- async enableSleepTimer(milliseconds) {
71
- const view = new DataView(new ArrayBuffer(4));
72
- const littleEndian = false;
73
- view.setInt32(0, milliseconds, littleEndian);
74
- await this.device.send(
75
- Reports.GLITTER_BASIC_CMD,
76
- [
77
- Commands.GLITTER_CMD_SET_SLEEP_TIMEOUT,
78
- view.getUint8(0),
79
- view.getUint8(1),
80
- view.getUint8(2),
81
- view.getUint8(3),
82
- ]
83
- );
84
- }
85
-
86
- async reboot(mode) {
87
- await this.device.send(
88
- Reports.GLITTER_BASIC_CMD,
89
- [Commands.GLITTER_CMD_REBOOT, mode]
90
- );
91
- }
92
-
93
- async drawMatrix(matrix) {
94
- await this.device.send(
95
- Reports.GLITTER_GRID_PWM_CNTL,
96
- matrix.flat().map(v => GAMMA[Math.floor((v ?? 0) * 255)])
97
- );
98
- }
99
-
100
- async drawPixel(r, c, brightness) {
101
- await this.device.send(
102
- Reports.GLITTER_BASIC_CMD,
103
- [Commands.GLITTER_CMD_DRAW_PIXEL, c, r, brightness]
104
- );
105
- }
106
-
107
- async drawLine({r1, c1}, {r2, c2}, brightness) {
108
- await this.device.send(
109
- Reports.GLITTER_BASIC_CMD,
110
- [Commands.GLITTER_CMD_DRAW_PIXEL, r1, c1, r2, c2, brightness]
111
- );
112
- }
113
-
114
- device;
115
- }
1
+ import { GAMMA } from '../../../hardware-constants.js';
2
+ import { Commands, Reports } from './reports.js';
3
+
4
+ export class ReportAbstractionLayer {
5
+ constructor(device = null) {
6
+ this.device = device;
7
+ }
8
+
9
+ async info() {
10
+ const infoRaw = await this.device.request(Reports.GLITTER_DEVICE_INFO);
11
+
12
+ return {
13
+ sleep_pin: infoRaw.getUint8(1),
14
+ dip1_pin: infoRaw.getUint8(2),
15
+ intb_pin: infoRaw.getUint8(3),
16
+ state_flags: infoRaw.getUint8(4),
17
+ id_reg: infoRaw.getUint8(5),
18
+ config_reg: infoRaw.getUint8(6),
19
+ global_brightness: infoRaw.getUint8(7),
20
+ display_width: infoRaw.getUint8(8),
21
+ display_height: infoRaw.getUint8(9),
22
+ timeout_ms: infoRaw.getUint32(10),
23
+ version_major: infoRaw.getUint8(14),
24
+ version_minor: infoRaw.getUint8(15),
25
+ };
26
+ }
27
+
28
+ async wake() {
29
+ await this.device.send(
30
+ Reports.GLITTER_BASIC_CMD,
31
+ [Commands.GLITTER_CMD_SLEEP, false]
32
+ );
33
+ }
34
+
35
+ async sleep() {
36
+ await this.device.send(
37
+ Reports.GLITTER_BASIC_CMD,
38
+ [Commands.GLITTER_CMD_SLEEP, true]
39
+ );
40
+ }
41
+
42
+ async disableSleep() {
43
+ await this.device.send(
44
+ Reports.GLITTER_BASIC_CMD,
45
+ [Commands.GLITTER_CMD_SET_SLEEP_TIMEOUT, 0xff, 0xff, 0xff, 0xff]
46
+ );
47
+ }
48
+
49
+ async disableDeepSleep() {
50
+ await this.device.send(
51
+ Reports.GLITTER_BASIC_CMD,
52
+ [Commands.GLITTER_CMD_WAKE_ON_COMMAND, 0x01]
53
+ );
54
+ }
55
+
56
+ async disableSleepTimer() {
57
+ await this.device.send(
58
+ Reports.GLITTER_BASIC_CMD,
59
+ [Commands.GLITTER_CMD_SET_SLEEP_TIMEOUT, 0x00, 0x00, 0x00, 0x00]
60
+ );
61
+ }
62
+
63
+ async enableDeepSleep() {
64
+ await this.device.send(
65
+ Reports.GLITTER_BASIC_CMD,
66
+ [Commands.GLITTER_CMD_WAKE_ON_COMMAND, 0x00]
67
+ );
68
+ }
69
+
70
+ async enableSleepTimer(milliseconds) {
71
+ const view = new DataView(new ArrayBuffer(4));
72
+ const littleEndian = false;
73
+ view.setInt32(0, milliseconds, littleEndian);
74
+ await this.device.send(
75
+ Reports.GLITTER_BASIC_CMD,
76
+ [
77
+ Commands.GLITTER_CMD_SET_SLEEP_TIMEOUT,
78
+ view.getUint8(0),
79
+ view.getUint8(1),
80
+ view.getUint8(2),
81
+ view.getUint8(3),
82
+ ]
83
+ );
84
+ }
85
+
86
+ async reboot(mode) {
87
+ await this.device.send(
88
+ Reports.GLITTER_BASIC_CMD,
89
+ [Commands.GLITTER_CMD_REBOOT, mode]
90
+ );
91
+ }
92
+
93
+ async drawMatrix(matrix) {
94
+ await this.device.send(
95
+ Reports.GLITTER_GRID_PWM_CNTL,
96
+ matrix.flat().map(v => GAMMA[Math.floor((v ?? 0) * 255)])
97
+ );
98
+ }
99
+
100
+ async drawPixel(r, c, brightness) {
101
+ await this.device.send(
102
+ Reports.GLITTER_BASIC_CMD,
103
+ [Commands.GLITTER_CMD_DRAW_PIXEL, c, r, brightness]
104
+ );
105
+ }
106
+
107
+ async drawLine({r1, c1}, {r2, c2}, brightness) {
108
+ await this.device.send(
109
+ Reports.GLITTER_BASIC_CMD,
110
+ [Commands.GLITTER_CMD_DRAW_PIXEL, r1, c1, r2, c2, brightness]
111
+ );
112
+ }
113
+
114
+ device;
115
+ }
@@ -1,50 +1,50 @@
1
- import { HEIGHT, WIDTH } from '../../../hardware-constants.js';
2
- import { getDevice } from '../../../web-hid/device.js';
3
- import { HIDOperations } from '../../../web-hid/HIDOperations.js';
4
- import { ReportAbstractionLayer } from './ReportAbstractionLayer.js';
5
- import { BootMode } from './reports.js';
6
-
7
- export class SparkleController extends ReportAbstractionLayer {
8
- async bootloader() {
9
- await super.reboot(BootMode.BOOTSEL);
10
- }
11
-
12
- async connect() {
13
- const device = await getDevice();
14
- if (device) {
15
- await device.open();
16
- this.device = new HIDOperations(device);
17
- }
18
- }
19
-
20
- async draw(matrix) {
21
- await super.drawMatrix(matrix);
22
- }
23
-
24
- async verifyFirmware() {
25
- try {
26
- const info = await super.info();
27
- return (
28
- info.display_height == HEIGHT &&
29
- info.display_width == WIDTH
30
- );
31
- } catch {
32
- return false;
33
- }
34
- }
35
-
36
- async version() {
37
- const info = await super.info();
38
- if (info.version_major != undefined
39
- && info.version_minor != undefined
40
- && (info.version_major > 0 || info.version_minor > 0)) {
41
- return {
42
- major: info.version_major,
43
- minor: info.version_minor
44
- }
45
- } else {
46
- // Sparkle <=1.1.1: Glitter version unavailable
47
- return { major: 1, minor: 0 };
48
- }
49
- }
50
- }
1
+ import { HEIGHT, WIDTH } from '../../../hardware-constants.js';
2
+ import { getDevice } from '../../../web-hid/device.js';
3
+ import { HIDOperations } from '../../../web-hid/HIDOperations.js';
4
+ import { ReportAbstractionLayer } from './ReportAbstractionLayer.js';
5
+ import { BootMode } from './reports.js';
6
+
7
+ export class SparkleController extends ReportAbstractionLayer {
8
+ async bootloader() {
9
+ await super.reboot(BootMode.BOOTSEL);
10
+ }
11
+
12
+ async connect() {
13
+ const device = await getDevice();
14
+ if (device) {
15
+ await device.open();
16
+ this.device = new HIDOperations(device);
17
+ }
18
+ }
19
+
20
+ async draw(matrix) {
21
+ await super.drawMatrix(matrix);
22
+ }
23
+
24
+ async verifyFirmware() {
25
+ try {
26
+ const info = await super.info();
27
+ return (
28
+ info.display_height == HEIGHT &&
29
+ info.display_width == WIDTH
30
+ );
31
+ } catch {
32
+ return false;
33
+ }
34
+ }
35
+
36
+ async version() {
37
+ const info = await super.info();
38
+ if (info.version_major != undefined
39
+ && info.version_minor != undefined
40
+ && (info.version_major > 0 || info.version_minor > 0)) {
41
+ return {
42
+ major: info.version_major,
43
+ minor: info.version_minor
44
+ }
45
+ } else {
46
+ // Sparkle <=1.1.1: Glitter version unavailable
47
+ return { major: 1, minor: 0 };
48
+ }
49
+ }
50
+ }