led-matrix-controllers 0.2.7 → 0.2.8
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.
- package/dist/led-matrix-controllers.browser.mjs +1 -1
- package/dist/led-matrix-controllers.browser.mjs.map +1 -1
- package/dist/led-matrix-controllers.umd.min.js +1 -1
- package/dist/led-matrix-controllers.umd.min.js.map +1 -1
- package/package.json +1 -1
- package/src/{web-hid → environments/web/usb-hid}/device.js +1 -1
- package/src/{web-serial → environments/web/usb-serial}/PortOperations.js +10 -2
- package/src/{web-serial → environments/web/usb-serial}/port.js +7 -4
- package/src/index.js +8 -7
- package/src/supported-firmware/FrameworkComputer/inputmodule-rs/CommandAbstractionLayer.js +29 -1
- package/src/supported-firmware/FrameworkComputer/inputmodule-rs/DefaultController.js +3 -3
- package/src/supported-firmware/sigroot/FW_LED_Matrix_Firmware/SigrootController.js +3 -3
- package/src/supported-firmware/vddCore/sparkle-fw16/SparkleController.js +2 -2
- /package/src/{web-hid → environments/web/usb-hid}/HIDOperations.js +0 -0
- /package/src/{web-hid → environments/web/usb-hid}/util.js +0 -0
- /package/src/{web-serial → environments/web/usb-serial}/PortMutex.js +0 -0
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
const t=9,e=34,a=12972,r=[50,172],i=32,n=[0,32],s=Object.freeze([0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,4,4,4,4,4,4,5,5,5,5,6,6,6,6,6,7,7,7,7,8,8,8,9,9,9,10,10,10,11,11,11,12,12,12,13,13,14,14,14,15,15,16,16,17,17,17,18,18,19,19,20,20,21,22,22,23,23,24,24,25,26,26,27,27,28,29,29,30,31,32,32,33,34,34,35,36,37,38,38,39,40,41,42,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,66,67,68,69,70,71,73,74,75,76,78,79,80,82,83,84,86,87,88,90,91,93,94,96,97,99,100,102,103,105,106,108,110,111,113,115,116,118,120,121,123,125,127,128,130,132,134,136,138,140,141,143,145,147,149,151,153,155,157,159,161,164,166,168,170,172,174,177,179,181,183,186,188,190,193,195,197,200,202,205,207,210,212,215,217,220,222,225,228,230,233,236,238,241,244,247,249,252,255]),o=[{usbVendorId:a,usbProductId:32}];class c extends Error{constructor(){super("User cancelled port selection."),this.name=this.constructor.name,this.date=new Date}}class u extends Error{constructor(){super("Selected port already in use."),this.name=this.constructor.name,this.date=new Date}}async function l(){try{return navigator.serial.requestPort?await navigator.serial.requestPort({filters:o}):null}catch(t){switch(t.name){case"NotFoundError":throw new c;case"InvalidStateError":throw new u;case"SecurityError":return null;default:throw t}}}const d=new class{used=new Set;unused=[];async getOrFetchUnused(){let t=this.unused.pop();if(!t){const e=await navigator.serial.getPorts({filters:o});this.#t(e),t=this.unused.pop()}if(!t){const e=await l();this.#t([e]),t=this.unused.pop()}return t&&this.used.add(t),t}#t(t){if(t)for(const e of t)!e||this.used.has(e)||this.unused.includes(e)||this.unused.push(e)}};async function w(){await l()}async function h(){return await d.getOrFetchUnused()}async function p(t){try{await t.close()}catch(t){if("InvalidStateError"!=t.name&&t.message.includes("The port is already closed"))throw t}}class y{constructor(t){this.#e=`port-mutex-${Math.random().toString()}`,this.#a=new Map,this.#r=t}async acquire(t){const e=new Error("created bad cb").stack;await this.#i(async()=>{try{await t(this.#r)}catch(t){console.error("Error occured in anonymous callback."),console.error("Original error:",t),console.error("--- This callback was created at ---\n",e)}})}async acquireIdempotent(t,e){const a=new Error("created bad cb").stack;this.#a.has(t)&&console.info(`"${t}" request coalesced.`),this.#a.set(t,async()=>{try{await e(this.#r)}catch(t){console.error("Error occured in anonymous callback."),console.error("Original error:",t),console.error("--- This callback was created at ---\n",a)}}),await this.#i(()=>this.#n(t))}async#i(t){return navigator.locks.request(this.#e,t)}async#n(t){if(this.#a.has(t)){const e=this.#a.get(t);this.#a.delete(t),await e()}}#e;#a;#r}class f{constructor(t){this.#s=t}async rx(t,e=3e3){if(null===this.#s)throw new Error("attempted RX before port initialization.");if(this.#s.readable.locked)throw new Error("attempted RX while port locked.");const a=[],r=this.#s.readable.getReader(),i=setTimeout(()=>r.cancel(),e);try{for(;a.length<t;){const{value:t,done:e}=await r.read();if(a.push(...t??[]),e||!t)break}}finally{clearTimeout(i),r.releaseLock()}return a}async tx(t){if(null===this.#s)throw new Error("attempted TX before port initialization.");if(this.#s.writable.locked)throw new Error("attempted TX while port locked.");const e=this.#s.writable.getWriter();try{await e.write(new Uint8Array(t))}finally{await e.close()}}#s}const E=Object.freeze({ANIMATE:4,BRIGHTNESS:0,BOOTLOADER:2,DRAW:6,DRAW_GREY_COL_BUFFER:8,GAME_CTRL:17,GAME_STATUS:18,PANIC:5,PATTERN:1,SLEEP:3,STAGE_GREY_COL:7,START_GAME:16,VERSION:32}),_=Object.freeze({GRAY_8BIT:"8-bit",MONO_1BIT:"1-bit"});let x=class{constructor(t=null){this.portMutex=t}async bootloader(){await this.portMutex.acquire(async t=>{await t.tx([...r,E.BOOTLOADER])})}async brightness(t){await this.portMutex.acquire(async e=>{await e.tx([...r,E.BRIGHTNESS,t])})}async draw(t){let e=0,a=new Uint8Array(39).fill(0);for(let r=0;r<34;r++)for(let i=0;i<9;i++)t[r][i]&&(a[e>>3]|=1<<e%8),e++;await this.portMutex.acquireIdempotent("drawMatrix",async t=>{await t.tx([...r,E.DRAW,...a])})}async drawGrayscale(t){const e=Array.from({length:9},(e,a)=>Array.from({length:34},(e,r)=>s[Math.floor(255*(t[r][a]??0))]));await this.portMutex.acquireIdempotent("drawMatrix",async t=>{for(let a=0;a<9;a++)await t.tx([...r,E.STAGE_GREY_COL,a,...e[a]]);await t.tx([...r,E.DRAW_GREY_COL_BUFFER])})}async asleep(){let t=!1;return await this.portMutex.acquire(async e=>{await e.tx([...r,E.SLEEP]),t=await e.rx(32),t=0!=t[0]}),t}async sleep(){await this.portMutex.acquire(async t=>{await t.tx([...r,E.SLEEP,1])})}async wake(){await this.portMutex.acquire(async t=>{await t.tx([...r,E.SLEEP])})}async pattern(t){await this.portMutex.acquireIdempotent("drawMatrix",async e=>{await e.tx([...r,E.PATTERN,t])})}async percent(t){await this.portMutex.acquireIdempotent("drawMatrix",async e=>{await e.tx([...r,E.PATTERN,Pattern.PERCENTAGE,t])})}async version(){let t={};return await this.portMutex.acquire(async e=>{await e.tx([...r,E.VERSION]);const a=await e.rx(32);t.major=a[0],t.minor=a[1]>>4,t.patch=15&a[1],t.preRelease=1==a[2]}),t}};class m extends x{async bootloader(){await super.bootloader()}async connect(){const t=await h();if(!t?.connected)throw new Error("No Port Found");await p(t),await t.open({baudRate:115200}),this.portMutex=new y(new f(t))}async draw(t){switch(this.bitDepth??_.MONO_1BIT){case _.GRAY_8BIT:await super.drawGrayscale(t);break;case _.MONO_1BIT:await super.draw(t);break;default:console.error(`Unsupported bitdepth: ${this.bitDepth}`)}}async verifyFirmware(){try{const t=await super.version();return t&&null!=t.major&&null!=t.minor&&null!=t.patch&&null!=t.preRelease}catch{return!1}}async version(){return super.version()}}const A=Object.freeze({NOOP:0,ANIMATION_DIAMOND:100,ANIMATION_FIRE:98,ANIMATION_FIREPLACE:102,ANIMATION_GEAR:103,ANIMATION_RING:114,ANIMATION_STARTUP:97,ANIMATION_STARTUP_ONCE:65,BOOTLOADER:101,DRAW_PWM:109,DRAW_PWM_BLOCKING:77,DRAW_SCALE:110,DRAW_SCALE_BLOCKING:78,FLUSH_CMD_QUEUE:99,TEST_PATTERN:116,SET_CONST_PWM:119,SET_CONST_SCALE:115,SET_PX_PWM:112,SET_PX_SCALE:113,IDENTITY_STRING:127}),T=/^Sig\sFW\sLED\sMatrix\sFW\sV(\d+)\.(\d+)$/;class b{constructor(t=null){this.portMutex=t}async bootloader(){await this.portMutex.acquire(async t=>{await t.tx([A.BOOTLOADER])})}async identityString(){let t=null;return await this.portMutex.acquire(async e=>{await e.tx([A.IDENTITY_STRING]),t=await e.rx(25)}),String.fromCharCode(...t)}async setPixelPwm(t,e,a){await this.portMutex.acquire(async r=>{await r.tx([A.SET_PX_PWM,e,t,a])})}async setGlobalPwm(t){await this.portMutex.acquire(async e=>{await e.tx([A.SET_CONST_PWM,t])})}async setMatrixPwm(t){await this.portMutex.acquireIdempotent("drawMatrix",async e=>{await e.tx([A.DRAW_PWM].concat(t.flat().map(t=>s[Math.floor(255*(t??0))])))})}async setPixelAnalog(t,e,a){await this.portMutex.acquire(async r=>{await r.tx([A.SET_PX_SCALE,e,t,a])})}async setGlobalAnalog(t){await this.portMutex.acquire(async e=>{await e.tx([A.SET_CONST_SCALE,t])})}async setMatrixAnalog(t){await this.portMutex.acquireIdempotent("drawMatrix",async e=>{await e.tx([A.DRAW_SCALE].concat(t.flat().map(t=>s[Math.floor(255*(t??0))])))})}}class g extends b{async bootloader(){await super.bootloader()}async connect(){const t=await h();t?.connected&&(await p(t),await t.open({baudRate:115200}),this.portMutex=new y(new f(t)))}async draw(t){if(this.#o)throw new Error("No Port Found");await super.setGlobalAnalog(32),this.#o=!0,await super.setMatrixPwm(t)}async verifyFirmware(){return null!=await this.version()}async version(){const t=(await super.identityString()).match(T);return t&&3==t.length?{major:t[1],minor:t[2]}:null}#o}const M=[{vendorId:a,productId:32}];class v extends Error{constructor(){super("User cancelled device selection."),this.name=this.constructor.name,this.date=new Date}}async function S(){try{return navigator.serial.requestPort?await navigator.serial.requestDevice({filters:M}):null}catch(t){switch(t.name){case"NotFoundError":throw new v;case"SecurityError":return null;default:throw t}}}const O=new class{used=new Set;unused=[];async getOrFetchUnused(){let t=this.unused.pop();if(!t){const e=await navigator.hid.getDevices({filters:M});this.#t(e),t=this.unused.pop()}if(!t){const e=await S();this.#t([e]),t=this.unused.pop()}return t&&this.used.add(t),t}#t(t){if(t)for(const e of t)!e||this.used.has(e)||this.unused.includes(e)||this.unused.push(e)}};async function I(){await S()}async function R(){return await O.getOrFetchUnused()}class N{constructor(t){this.#c=t}async send(t,e){if(e.length<t.bytes)e=function(t,e,a=0){return t.concat(new Array(e-t.length).fill(a))}(e,t.bytes);else if(e.length>t.bytes)throw new Error("Unable to send report: too many bytes");const a=new Uint8Array(e).buffer;t.feature?await this.#c.sendFeatureReport(t.id,a):await this.#c.sendReport(t.id,a)}async request(t){let e=[];if(!t.feature)throw new Error("Invalid operation");if(e=await this.#c.receiveFeatureReport(t.id),e.byteLength!=t.bytes){const a=t.bytes,r=e.byteLength;console.error(`reply length=${r} (expected ${a})`)}return e}#c}const q={id:1,bytes:307,feature:!0},U={id:2,bytes:16,feature:!0},P={id:4,bytes:306,feature:!0},D=0,L=1,F=2,C=3,G=5,k=0;class W{constructor(t=null){this.device=t}async info(){const t=await this.device.request(q);return{sleep_pin:t.getUint8(1),dip1_pin:t.getUint8(2),intb_pin:t.getUint8(3),state_flags:t.getUint8(4),id_reg:t.getUint8(5),config_reg:t.getUint8(6),global_brightness:t.getUint8(7),display_width:t.getUint8(8),display_height:t.getUint8(9),timeout_ms:t.getUint32(10),version_major:t.getUint8(14),version_minor:t.getUint8(15)}}async wake(){await this.device.send(U,[L,!1])}async sleep(){await this.device.send(U,[L,!0])}async disableSleep(){await this.device.send(U,[C,255,255,255,255])}async disableDeepSleep(){await this.device.send(U,[F,1])}async disableSleepTimer(){await this.device.send(U,[C,0,0,0,0])}async enableDeepSleep(){await this.device.send(U,[F,0])}async enableSleepTimer(t){const e=new DataView(new ArrayBuffer(4));e.setInt32(0,t,!1),await this.device.send(U,[C,e.getUint8(0),e.getUint8(1),e.getUint8(2),e.getUint8(3)])}async reboot(t){await this.device.send(U,[D,t])}async drawMatrix(t){await this.device.send(P,t.flat().map(t=>s[Math.floor(255*(t??0))]))}async drawPixel(t,e,a){await this.device.send(U,[G,e,t,a])}async drawLine({r1:t,c1:e},{r2:a,c2:r},i){await this.device.send(U,[G,t,e,a,r,i])}device}class B extends W{async bootloader(){await super.reboot(k)}async connect(){const t=await R();if(!t)throw new Error("No Device Found");await t.open(),this.device=new N(t)}async draw(t){await super.drawMatrix(t)}async verifyFirmware(){try{const t=await super.info();return 34==t.display_height&&9==t.display_width}catch{return!1}}async version(){const t=await super.info();return null!=t.version_major&&null!=t.version_minor&&(t.version_major>0||t.version_minor>0)?{major:t.version_major,minor:t.version_minor}:{major:1,minor:0}}}class j{static async detectSerial(){const t=new m,e=new g;return await t.connect(),await t.verifyFirmware()?t:(await e.connect(),await e.verifyFirmware()?e:null)}static async detectHID(){const t=new B;return await t.connect(),await t.verifyFirmware()?t:null}}export{m as DefaultController,v as DeviceSelectionCancelled,s as GAMMA,e as HEIGHT,j as HardwareControllerFactory,i as PID,n as PID_ARR,c as PortSelectionCancelled,u as PortUnavailable,g as SigrootController,B as SparkleController,a as VID,r as VID_ARR,t as WIDTH,p as close,R as getUnusedDevice,h as getUnusedPort,I as reqestDeviceForWorker,w as requestPortForWorker};
|
|
1
|
+
const t=9,e=34,a=[50,172],r=Object.freeze([0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,4,4,4,4,4,4,5,5,5,5,6,6,6,6,6,7,7,7,7,8,8,8,9,9,9,10,10,10,11,11,11,12,12,12,13,13,14,14,14,15,15,16,16,17,17,17,18,18,19,19,20,20,21,22,22,23,23,24,24,25,26,26,27,27,28,29,29,30,31,32,32,33,34,34,35,36,37,38,38,39,40,41,42,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,66,67,68,69,70,71,73,74,75,76,78,79,80,82,83,84,86,87,88,90,91,93,94,96,97,99,100,102,103,105,106,108,110,111,113,115,116,118,120,121,123,125,127,128,130,132,134,136,138,140,141,143,145,147,149,151,153,155,157,159,161,164,166,168,170,172,174,177,179,181,183,186,188,190,193,195,197,200,202,205,207,210,212,215,217,220,222,225,228,230,233,236,238,241,244,247,249,252,255]),i=[{usbVendorId:12972,usbProductId:32}];class n extends Error{constructor(){super("User cancelled port selection."),this.name=this.constructor.name,this.date=new Date}}class s extends Error{constructor(){super("Selected port already in use."),this.name=this.constructor.name,this.date=new Date}}async function o(){try{return navigator.serial.requestPort?Object.assign(await navigator.serial.requestPort({filters:i}),{pickedByUser:!0}):null}catch(t){switch(t.name){case"NotFoundError":throw new n;case"InvalidStateError":throw new s;case"SecurityError":return null;default:throw t}}}const c=new class{used=new Set;unused=[];async getOrFetchUnused(){let t=this.unused.pop();if(!t){const e=await navigator.serial.getPorts({filters:i});this.#t(e),t=this.unused.pop()}if(!t){const e=await o();this.#t([e]),t=this.unused.pop()}return t&&this.used.add(t),t}#t(t){if(t)for(const e of t)!e||this.used.has(e)||this.unused.includes(e)||this.unused.push(e)}};async function u(){await o()}async function l(){return await c.getOrFetchUnused()}async function d(t){try{await t.close()}catch(t){if("InvalidStateError"!=t.name&&t.message.includes("The port is already closed"))throw t}}class w{constructor(t){this.#e=`port-mutex-${Math.random().toString()}`,this.#a=new Map,this.#r=t}async acquire(t){const e=new Error("created bad cb").stack;await this.#i(async()=>{try{await t(this.#r)}catch(t){console.error("Error occured in anonymous callback."),console.error("Original error:",t),console.error("--- This callback was created at ---\n",e)}})}async acquireIdempotent(t,e){const a=new Error("created bad cb").stack;this.#a.has(t)&&console.info(`"${t}" request coalesced.`),this.#a.set(t,async()=>{try{await e(this.#r)}catch(t){console.error("Error occured in anonymous callback."),console.error("Original error:",t),console.error("--- This callback was created at ---\n",a)}}),await this.#i(()=>this.#n(t))}async#i(t){return navigator.locks.request(this.#e,t)}async#n(t){if(this.#a.has(t)){const e=this.#a.get(t);this.#a.delete(t),await e()}}#e;#a;#r}class h{constructor(t){this.#s=t}async rx(t,e=3e3){if(null===this.#s)throw new Error("attempted RX on uninitialized port.");if(null===this.#s.readable)throw new Error("attempted RX on closed port.");if(this.#s.readable.locked)throw new Error("attempted RX while port locked.");const a=[],r=this.#s.readable.getReader(),i=setTimeout(()=>r.cancel(),e);try{for(;a.length<t;){const{value:t,done:e}=await r.read();if(a.push(...t??[]),e||!t)break}}finally{clearTimeout(i),r.releaseLock()}return a}async tx(t){if(null===this.#s)throw new Error("attempted TX on uninitialized port.");if(null===this.#s.writable)throw new Error("attempted TX on closed port.");if(this.#s.writable.locked)throw new Error("attempted TX while port locked.");const e=this.#s.writable.getWriter();try{await e.write(new Uint8Array(t))}finally{await e.close()}}#s}const p=Object.freeze({ANIMATE:4,BRIGHTNESS:0,BOOTLOADER:2,DRAW:6,DRAW_GREY_COL_BUFFER:8,GAME_CTRL:17,GAME_STATUS:18,PANIC:5,PATTERN:1,SLEEP:3,STAGE_GREY_COL:7,START_GAME:16,VERSION:32}),y=Object.freeze({DISPLAY_LOTUS_HORIZONTAL:3,DISPLAY_LOTUS_VERTICAL:7,DISPLAY_PANIC:6,DOUBLE_GRADIENT:2,FULL_BRIGHTNESS:5,GRADIENT:1,PERCENTAGE:0,ZIG_ZAG:4}),E=Object.freeze({GRAY_8BIT:"8-bit",MONO_1BIT:"1-bit"});let f=class{constructor(t=null){this.portMutex=t}async bootloader(){await this.portMutex.acquire(async t=>{await t.tx([...a,p.BOOTLOADER])})}async brightness(t){await this.portMutex.acquire(async e=>{await e.tx([...a,p.BRIGHTNESS,t])})}async draw(t){let e=0,r=new Uint8Array(39).fill(0);for(let a=0;a<34;a++)for(let i=0;i<9;i++)t[a][i]&&(r[e>>3]|=1<<e%8),e++;await this.portMutex.acquireIdempotent("drawMatrix",async t=>{await t.tx([...a,p.DRAW,...r])})}async drawGrayscale(t){const e=Array.from({length:9},(e,a)=>Array.from({length:34},(e,i)=>r[Math.floor(255*(t[i][a]??0))]));await this.portMutex.acquireIdempotent("drawMatrix",async t=>{for(let r=0;r<9;r++)await t.tx([...a,p.STAGE_GREY_COL,r,...e[r]]);await t.tx([...a,p.DRAW_GREY_COL_BUFFER])})}async asleep(){let t=!1;return await this.portMutex.acquire(async e=>{await e.tx([...a,p.SLEEP]),t=await e.rx(32),t=0!=t[0]}),t}async sleep(){await this.portMutex.acquire(async t=>{await t.tx([...a,p.SLEEP,1])})}async wake(){await this.portMutex.acquire(async t=>{await t.tx([...a,p.SLEEP])})}async pattern(t){await this.portMutex.acquireIdempotent("drawMatrix",async e=>{await e.tx([...a,p.PATTERN,t])})}async percent(t){t=Math.min(t,100),t=Math.max(t,0),t=Math.round(t),await this.portMutex.acquireIdempotent("drawMatrix",async e=>{await e.tx([...a,p.PATTERN,y.PERCENTAGE,t])})}async version(){let t={};return await this.portMutex.acquire(async e=>{await e.tx([...a,p.VERSION]);const r=await e.rx(32);t.major=r[0],t.minor=r[1]>>4,t.patch=15&r[1],t.preRelease=1==r[2]}),t}async scrolling(){let t=!1;return await this.portMutex.acquire(async e=>{await e.tx([...a,p.ANIMATE]),t=await e.rx(32),t=0!=t[0]}),t}async startScrolling(){await this.portMutex.acquire(async t=>{await t.tx([...a,p.ANIMATE,1])})}async stopScrolling(){await this.portMutex.acquire(async t=>{await t.tx([...a,p.ANIMATE,0])})}};class A extends f{async bootloader(){await super.bootloader()}async connect(){const t=await l();if(!t?.connected)throw new Error("No Port Found");await d(t),await t.open({baudRate:115200}),this.portMutex=new w(new h(t))}async draw(t){switch(this.bitDepth??E.MONO_1BIT){case E.GRAY_8BIT:await super.drawGrayscale(t);break;case E.MONO_1BIT:await super.draw(t);break;default:console.error(`Unsupported bitdepth: ${this.bitDepth}`)}}async verifyFirmware(){try{const t=await super.version();return t&&null!=t.major&&null!=t.minor&&null!=t.patch&&null!=t.preRelease}catch{return!1}}async version(){return super.version()}}const _=Object.freeze({NOOP:0,ANIMATION_DIAMOND:100,ANIMATION_FIRE:98,ANIMATION_FIREPLACE:102,ANIMATION_GEAR:103,ANIMATION_RING:114,ANIMATION_STARTUP:97,ANIMATION_STARTUP_ONCE:65,BOOTLOADER:101,DRAW_PWM:109,DRAW_PWM_BLOCKING:77,DRAW_SCALE:110,DRAW_SCALE_BLOCKING:78,FLUSH_CMD_QUEUE:99,TEST_PATTERN:116,SET_CONST_PWM:119,SET_CONST_SCALE:115,SET_PX_PWM:112,SET_PX_SCALE:113,IDENTITY_STRING:127}),x=/^Sig\sFW\sLED\sMatrix\sFW\sV(\d+)\.(\d+)$/;class T{constructor(t=null){this.portMutex=t}async bootloader(){await this.portMutex.acquire(async t=>{await t.tx([_.BOOTLOADER])})}async identityString(){let t=null;return await this.portMutex.acquire(async e=>{await e.tx([_.IDENTITY_STRING]),t=await e.rx(25)}),String.fromCharCode(...t)}async setPixelPwm(t,e,a){await this.portMutex.acquire(async r=>{await r.tx([_.SET_PX_PWM,e,t,a])})}async setGlobalPwm(t){await this.portMutex.acquire(async e=>{await e.tx([_.SET_CONST_PWM,t])})}async setMatrixPwm(t){await this.portMutex.acquireIdempotent("drawMatrix",async e=>{await e.tx([_.DRAW_PWM].concat(t.flat().map(t=>r[Math.floor(255*(t??0))])))})}async setPixelAnalog(t,e,a){await this.portMutex.acquire(async r=>{await r.tx([_.SET_PX_SCALE,e,t,a])})}async setGlobalAnalog(t){await this.portMutex.acquire(async e=>{await e.tx([_.SET_CONST_SCALE,t])})}async setMatrixAnalog(t){await this.portMutex.acquireIdempotent("drawMatrix",async e=>{await e.tx([_.DRAW_SCALE].concat(t.flat().map(t=>r[Math.floor(255*(t??0))])))})}}class m extends T{async bootloader(){await super.bootloader()}async connect(){const t=await l();t?.connected&&(await d(t),await t.open({baudRate:115200}),this.portMutex=new w(new h(t)))}async draw(t){if(this.#o)throw new Error("No Port Found");await super.setGlobalAnalog(32),this.#o=!0,await super.setMatrixPwm(t)}async verifyFirmware(){return null!=await this.version()}async version(){const t=(await super.identityString()).match(x);return t&&3==t.length?{major:t[1],minor:t[2]}:null}#o}const M=[{vendorId:12972,productId:32}];class I extends Error{constructor(){super("User cancelled device selection."),this.name=this.constructor.name,this.date=new Date}}async function g(){try{return navigator.serial.requestPort?await navigator.serial.requestDevice({filters:M}):null}catch(t){switch(t.name){case"NotFoundError":throw new I;case"SecurityError":return null;default:throw t}}}const S=new class{used=new Set;unused=[];async getOrFetchUnused(){let t=this.unused.pop();if(!t){const e=await navigator.hid.getDevices({filters:M});this.#t(e),t=this.unused.pop()}if(!t){const e=await g();this.#t([e]),t=this.unused.pop()}return t&&this.used.add(t),t}#t(t){if(t)for(const e of t)!e||this.used.has(e)||this.unused.includes(e)||this.unused.push(e)}};async function b(){await g()}class O{constructor(t){this.#c=t}async send(t,e){if(e.length<t.bytes)e=function(t,e,a=0){return t.concat(new Array(e-t.length).fill(a))}(e,t.bytes);else if(e.length>t.bytes)throw new Error("Unable to send report: too many bytes");const a=new Uint8Array(e).buffer;t.feature?await this.#c.sendFeatureReport(t.id,a):await this.#c.sendReport(t.id,a)}async request(t){let e=[];if(!t.feature)throw new Error("Invalid operation");if(e=await this.#c.receiveFeatureReport(t.id),e.byteLength!=t.bytes){const a=t.bytes,r=e.byteLength;console.error(`reply length=${r} (expected ${a})`)}return e}#c}const N={id:1,bytes:307,feature:!0},v={id:2,bytes:16,feature:!0},R={id:4,bytes:306,feature:!0},q=0,U=1,P=2,D=3,L=5,G=0;class C{constructor(t=null){this.device=t}async info(){const t=await this.device.request(N);return{sleep_pin:t.getUint8(1),dip1_pin:t.getUint8(2),intb_pin:t.getUint8(3),state_flags:t.getUint8(4),id_reg:t.getUint8(5),config_reg:t.getUint8(6),global_brightness:t.getUint8(7),display_width:t.getUint8(8),display_height:t.getUint8(9),timeout_ms:t.getUint32(10),version_major:t.getUint8(14),version_minor:t.getUint8(15)}}async wake(){await this.device.send(v,[U,!1])}async sleep(){await this.device.send(v,[U,!0])}async disableSleep(){await this.device.send(v,[D,255,255,255,255])}async disableDeepSleep(){await this.device.send(v,[P,1])}async disableSleepTimer(){await this.device.send(v,[D,0,0,0,0])}async enableDeepSleep(){await this.device.send(v,[P,0])}async enableSleepTimer(t){const e=new DataView(new ArrayBuffer(4));e.setInt32(0,t,!1),await this.device.send(v,[D,e.getUint8(0),e.getUint8(1),e.getUint8(2),e.getUint8(3)])}async reboot(t){await this.device.send(v,[q,t])}async drawMatrix(t){await this.device.send(R,t.flat().map(t=>r[Math.floor(255*(t??0))]))}async drawPixel(t,e,a){await this.device.send(v,[L,e,t,a])}async drawLine({r1:t,c1:e},{r2:a,c2:r},i){await this.device.send(v,[L,t,e,a,r,i])}device}class F extends C{async bootloader(){await super.reboot(G)}async connect(){const t=await async function(){return await S.getOrFetchUnused()}();if(!t)throw new Error("No Device Found");await t.open(),this.device=new O(t)}async draw(t){await super.drawMatrix(t)}async verifyFirmware(){try{const t=await super.info();return 34==t.display_height&&9==t.display_width}catch{return!1}}async version(){const t=await super.info();return null!=t.version_major&&null!=t.version_minor&&(t.version_major>0||t.version_minor>0)?{major:t.version_major,minor:t.version_minor}:{major:1,minor:0}}}class k{static async detectSerial(){const t=new A,e=new m;return await t.connect(),await t.verifyFirmware()?t:(await e.connect(),await e.verifyFirmware()?e:null)}static async detectHID(){const t=new F;return await t.connect(),await t.verifyFirmware()?t:null}}export{E as BitDepth,A as DefaultController,I as DeviceSelectionCancelled,e as HEIGHT,k as HardwareControllerFactory,y as Pattern,n as PortSelectionCancelled,s as PortUnavailable,m as SigrootController,F as SparkleController,t as WIDTH,b as reqestDeviceForWorker,u as requestPortForWorker};
|
|
2
2
|
//# sourceMappingURL=led-matrix-controllers.browser.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"led-matrix-controllers.browser.mjs","sources":["../src/hardware-constants.js","../src/web-serial/port.js","../src/web-serial/PortMutex.js","../src/web-serial/PortOperations.js","../src/supported-firmware/FrameworkComputer/inputmodule-rs/commands.js","../src/supported-firmware/FrameworkComputer/inputmodule-rs/CommandAbstractionLayer.js","../src/supported-firmware/FrameworkComputer/inputmodule-rs/DefaultController.js","../src/supported-firmware/sigroot/FW_LED_Matrix_Firmware/commands.js","../src/supported-firmware/sigroot/FW_LED_Matrix_Firmware/CommandAbstractionLayer.js","../src/supported-firmware/sigroot/FW_LED_Matrix_Firmware/SigrootController.js","../src/web-hid/device.js","../src/web-hid/HIDOperations.js","../src/web-hid/util.js","../src/supported-firmware/vddCore/sparkle-fw16/reports.js","../src/supported-firmware/vddCore/sparkle-fw16/ReportAbstractionLayer.js","../src/supported-firmware/vddCore/sparkle-fw16/SparkleController.js","../src/HardwareControllerFactory.js"],"sourcesContent":["export const WIDTH = 9;\nexport const HEIGHT = 34;\nexport const VID = 0x32AC;\nexport const VID_ARR = [0x32, 0xAC];\nexport const PID = 0x0020;\nexport const PID_ARR = [0x00, 0x20];\n\n// For PWM dimming (not for analog dimming/constant-current reduction!)\nexport const GAMMA = Object.freeze([\n 0, 0, 0, 0, 0, 0, 0, 1, \n 1, 1, 1, 1, 1, 1, 1, 1, \n 1, 1, 1, 1, 1, 1, 1, 1, \n 1, 1, 1, 1, 1, 1, 1, 1, \n 1, 1, 1, 2, 2, 2, 2, 2, \n 2, 2, 2, 2, 3, 3, 3, 3, \n 3, 3, 3, 4, 4, 4, 4, 4, \n 4, 5, 5, 5, 5, 6, 6, 6, \n 6, 6, 7, 7, 7, 7, 8, 8, \n 8, 9, 9, 9, 10, 10, 10, 11, \n 11, 11, 12, 12, 12, 13, 13, 14, \n 14, 14, 15, 15, 16, 16, 17, 17, \n 17, 18, 18, 19, 19, 20, 20, 21, \n 22, 22, 23, 23, 24, 24, 25, 26, \n 26, 27, 27, 28, 29, 29, 30, 31, \n 32, 32, 33, 34, 34, 35, 36, 37, \n 38, 38, 39, 40, 41, 42, 42, 43, \n 44, 45, 46, 47, 48, 49, 50, 51, \n 52, 53, 54, 55, 56, 57, 58, 59, \n 60, 61, 62, 63, 64, 66, 67, 68, \n 69, 70, 71, 73, 74, 75, 76, 78, \n 79, 80, 82, 83, 84, 86, 87, 88, \n 90, 91, 93, 94, 96, 97, 99, 100, \n 102, 103, 105, 106, 108, 110, 111, 113, \n 115, 116, 118, 120, 121, 123, 125, 127, \n 128, 130, 132, 134, 136, 138, 140, 141, \n 143, 145, 147, 149, 151, 153, 155, 157, \n 159, 161, 164, 166, 168, 170, 172, 174, \n 177, 179, 181, 183, 186, 188, 190, 193, \n 195, 197, 200, 202, 205, 207, 210, 212, \n 215, 217, 220, 222, 225, 228, 230, 233, \n 236, 238, 241, 244, 247, 249, 252, 255\n]);\n","import { PID, VID } from '../hardware-constants.js';\n\nconst filters = [{ usbVendorId: VID, usbProductId: PID }];\n\nexport class PortSelectionCancelled extends Error {\n constructor() {\n super('User cancelled port selection.');\n this.name = this.constructor.name;\n this.date = new Date();\n }\n}\n\nexport class PortUnavailable extends Error {\n constructor() {\n super('Selected port already in use.');\n this.name = this.constructor.name;\n this.date = new Date();\n }\n}\n\nasync function requestPort() {\n try {\n if (navigator.serial.requestPort) {\n return await navigator.serial.requestPort({ filters });\n } else {\n return null; // Web Worker\n }\n } catch (e) {\n switch (e.name) {\n case ('NotFoundError'):\n throw new PortSelectionCancelled();\n case ('InvalidStateError'):\n throw new PortUnavailable();\n case ('SecurityError'): // No user gesture\n return null;\n default:\n throw e;\n }\n }\n}\n\nclass KnownPorts {\n used = new Set();\n unused = [];\n\n async getOrFetchUnused() {\n let port = this.unused.pop();\n \n if (!port) {\n const systemPorts = await navigator.serial.getPorts({ filters });\n this.#enqueueUnique(systemPorts);\n port = this.unused.pop();\n }\n\n if (!port) {\n const manualPort = await requestPort();\n this.#enqueueUnique([manualPort]);\n port = this.unused.pop();\n }\n\n if (port) {\n this.used.add(port);\n }\n \n return port;\n }\n\n #enqueueUnique(ports) {\n if (ports) {\n for (const port of ports) {\n if (port && !this.used.has(port) && !this.unused.includes(port)) {\n this.unused.push(port);\n }\n }\n }\n }\n}\n\nconst knownPorts = new KnownPorts();\n\n/**\n * Adds user-selected port to permitted ports. Only for use outside of Web \n * Worker to establish permission for use within Web Worker.\n * @returns {null}\n */\nexport async function requestPortForWorker() {\n const _ = await requestPort();\n}\n\n/**\n * Never returns the same port twice. \n * @returns {(SerialPort|null)}\n */\nexport async function getUnusedPort() {\n return await knownPorts.getOrFetchUnused();\n}\n\n/**\n * Close port without throwing if already closed.\n * @param {SerialPort} port \n */\nexport async function close(port) {\n try {\n await port.close();\n } catch(e) {\n if (e.name != 'InvalidStateError') {\n if (e.message.includes('The port is already closed')) {\n throw e;\n }\n }\n }\n}\n","export class PortMutex {\n constructor(portOperations) {\n this.#lockName = `port-mutex-${Math.random().toString()}`;\n this.#deduper = new Map();\n this.#portOps = portOperations;\n }\n\n async acquire(fn) {\n const trace = new Error('created bad cb').stack;\n\n await this.#enqueue(async () => {\n try {\n await fn(this.#portOps);\n } catch (e) {\n console.error('Error occured in anonymous callback.');\n console.error('Original error:', e);\n console.error('--- This callback was created at ---\\n', trace);\n }\n });\n }\n\n async acquireIdempotent(key, fn) {\n const trace = new Error('created bad cb').stack;\n\n if (this.#deduper.has(key)) {\n console.info(`\"${key}\" request coalesced.`);\n }\n\n this.#deduper.set(key, async () => {\n try {\n await fn(this.#portOps);\n } catch (e) {\n console.error('Error occured in anonymous callback.');\n console.error('Original error:', e);\n console.error('--- This callback was created at ---\\n', trace);\n }\n });\n\n await this.#enqueue(() => this.#execDedupedOp(key));\n }\n\n async #enqueue(fn) {\n // `navigator.locks` maintains queue and provides mutual exclusion.\n return navigator.locks.request(this.#lockName, fn);\n }\n\n async #execDedupedOp(key) {\n if (this.#deduper.has(key)) {\n const fn = this.#deduper.get(key);\n this.#deduper.delete(key);\n await fn();\n }\n }\n\n #lockName;\n #deduper;\n #portOps;\n}\n","export class PortOperations {\n constructor(port) {\n this.#port = port;\n }\n\n async rx(length, timeout=3000) {\n if (this.#port === null) {\n throw new Error('attempted RX before port initialization.');\n }\n\n /*\n * ReadableStream's built-in locking mechanism cannot be awaited or otherwise\n * asynchronously acquired. A PortMutex must be used.\n */\n if (this.#port.readable.locked) {\n throw new Error('attempted RX while port locked.');\n }\n\n const response = [];\n const reader = this.#port.readable.getReader();\n const timeoutHandle = setTimeout(() => reader.cancel(), timeout);\n\n try {\n // Response may be divided across multiple reads\n while (response.length < length) {\n const { value, done } = await reader.read();\n response.push(...(value ?? []));\n if (done || !value) break;\n }\n } finally {\n clearTimeout(timeoutHandle);\n reader.releaseLock();\n }\n\n return response;\n }\n\n async tx(buffer) {\n if (this.#port === null) {\n throw new Error('attempted TX before port initialization.');\n }\n \n /*\n * WritableStream's built-in locking mechanism cannot be awaited or otherwise\n * asynchronously acquired. A PortMutex must be used.\n */\n if (this.#port.writable.locked) {\n throw new Error('attempted TX while port locked.');\n }\n\n const writer = this.#port.writable.getWriter();\n\n try {\n await writer.write(new Uint8Array(buffer));\n } finally {\n /* \n * The writer must be completely torn down between every single write.\n * Many parsers can't handle delayed flushing and write coalescing.\n * Command sequences will fail if `releaseLock()` is used here.\n */\n await writer.close();\n }\n }\n\n #port;\n}\n","// All replies to all commands are 32 bytes\nexport const RX_PACKET_SZ = 32;\n\nexport const Command = Object.freeze({\n ANIMATE: 0x04,\n BRIGHTNESS: 0x00,\n BOOTLOADER: 0x02,\n DRAW: 0x06,\n DRAW_GREY_COL_BUFFER: 0x08,\n GAME_CTRL: 0x11,\n GAME_STATUS: 0x12,\n PANIC: 0x05,\n PATTERN: 0x01,\n SLEEP: 0x03,\n STAGE_GREY_COL: 0x07,\n START_GAME: 0x10,\n VERSION: 0x20,\n});\n\n// Used with Command.PATTERN\nexport const Pattern = Object.freeze({\n DISPLAY_LOTUS_HORIZONTAL: 0x03,\n DISPLAY_LOTUS_VERTICAL: 0x07,\n DISPLAY_PANIC: 0x06,\n DOUBLE_GRADIENT: 0x02,\n FULL_BRIGHTNESS: 0x05,\n GRADIENT: 0x01,\n PERCENTAGE: 0x00,\n ZIG_ZAG: 0x04,\n});\n\n// DRAW or DRAW_GREY_COL_BUFFER\nexport const BitDepth = Object.freeze({\n GRAY_8BIT: '8-bit',\n MONO_1BIT: '1-bit',\n})\n","import { GAMMA, HEIGHT, VID_ARR, WIDTH } from '../../../hardware-constants.js';\nimport { Command, RX_PACKET_SZ } from './commands.js';\n\nexport class CommandAbstractionLayer {\n constructor(portMutex = null) {\n this.portMutex = portMutex;\n }\n\n async bootloader() {\n await this.portMutex.acquire(async p => {\n await p.tx([...VID_ARR, Command.BOOTLOADER]);\n });\n }\n\n async brightness(brightness) {\n await this.portMutex.acquire(async p => {\n await p.tx([...VID_ARR, Command.BRIGHTNESS, brightness]);\n });\n }\n\n async draw(matrix) {\n let index = 0;\n let output = new Uint8Array(39).fill(0);\n\n // Pack cells into bits\n for (let r = 0; r < HEIGHT; r++) {\n for (let c = 0; c < WIDTH; c++) {\n if (matrix[r][c]) {\n output[index >> 3] |= 1 << index % 8;\n }\n index++;\n }\n }\n\n await this.portMutex.acquireIdempotent(\n 'drawMatrix', \n async p => {\n await p.tx([...VID_ARR, Command.DRAW, ...output]);\n }\n );\n }\n\n async drawGrayscale(matrix) {\n // Transpose & Gamma Correction\n const buffers = Array.from(\n { length: WIDTH }, \n (_, c) => Array.from(\n { length: HEIGHT }, \n (_, r) => GAMMA[Math.floor((matrix[r][c] ?? 0) * 255)]\n )\n );\n\n // Only execute the most recent call \n await this.portMutex.acquireIdempotent(\n 'drawMatrix', \n async p => {\n for (let i = 0; i < WIDTH; i++) {\n await p.tx([...VID_ARR, Command.STAGE_GREY_COL, i, ...buffers[i]]);\n }\n await p.tx([...VID_ARR, Command.DRAW_GREY_COL_BUFFER]);\n }\n );\n }\n\n async asleep() {\n let asleep = false;\n\n await this.portMutex.acquire(async p => {\n await p.tx([...VID_ARR, Command.SLEEP]);\n asleep = await p.rx(RX_PACKET_SZ);\n asleep = asleep[0] != 0x00;\n });\n\n return asleep;\n }\n\n async sleep() {\n await this.portMutex.acquire(async p => {\n await p.tx([...VID_ARR, Command.SLEEP, 0x01]);\n });\n }\n\n async wake() {\n await this.portMutex.acquire(async p => {\n await p.tx([...VID_ARR, Command.SLEEP]);\n });\n }\n\n async pattern(pattern) {\n await this.portMutex.acquireIdempotent(\n 'drawMatrix',\n async p => {\n await p.tx([...VID_ARR, Command.PATTERN, pattern]);\n }\n );\n }\n\n async percent(percent) {\n await this.portMutex.acquireIdempotent(\n 'drawMatrix',\n async p => {\n await p.tx([...VID_ARR, Command.PATTERN, Pattern.PERCENTAGE, percent]);\n }\n );\n }\n\n async version() {\n let ver = {};\n\n await this.portMutex.acquire(async p => {\n await p.tx([...VID_ARR, Command.VERSION]);\n const response = await p.rx(RX_PACKET_SZ);\n\n // MMMMMMMM mmmmPPPP 0000000p\n ver.major = response[0];\n ver.minor = response[1] >> 4;\n ver.patch = response[1] & 0x0F;\n ver.preRelease = response[2] == 1;\n });\n\n return ver;\n }\n}\n","import { close, getUnusedPort } from '../../../web-serial/port.js';\nimport { PortMutex } from '../../../web-serial/PortMutex.js';\nimport { PortOperations } from '../../../web-serial/PortOperations.js';\nimport { CommandAbstractionLayer } from './CommandAbstractionLayer.js';\nimport { BitDepth } from './commands.js';\n\nexport class DefaultController extends CommandAbstractionLayer {\n async bootloader() {\n await super.bootloader();\n }\n\n async connect() {\n const port = await getUnusedPort();\n\n if (port?.connected) {\n await close(port);\n await port.open({ baudRate: 115200 });\n this.portMutex = new PortMutex(new PortOperations(port));\n } else {\n throw new Error('No Port Found');\n }\n }\n\n async draw(matrix) {\n switch (this.bitDepth ?? BitDepth.MONO_1BIT) {\n\n case (BitDepth.GRAY_8BIT):\n await super.drawGrayscale(matrix);\n break;\n\n case (BitDepth.MONO_1BIT):\n await super.draw(matrix);\n break;\n\n default:\n console.error(`Unsupported bitdepth: ${this.bitDepth}`);\n }\n }\n\n async verifyFirmware() {\n try {\n const version = await super.version();\n\n return version\n && version.major != undefined\n && version.minor != undefined\n && version.patch != undefined\n && version.preRelease != undefined;\n \n } catch {\n return false;\n }\n }\n\n async version() {\n return super.version();\n }\n}\n","export const Command = Object.freeze({\n /* 000 */ NOOP: 0x00,\n /* 'd' */ ANIMATION_DIAMOND: 0x64,\n /* 'b' */ ANIMATION_FIRE: 0x62,\n /* 'f' */ ANIMATION_FIREPLACE: 0x66,\n /* 'g' */ ANIMATION_GEAR: 0x67,\n /* 'r' */ ANIMATION_RING: 0x72,\n /* 'a' */ ANIMATION_STARTUP: 0x61,\n /* 'A' */ ANIMATION_STARTUP_ONCE: 0x41,\n /* 'e' */ BOOTLOADER: 0x65,\n /* 'm' */ DRAW_PWM: 0x6D,\n /* 'M' */ DRAW_PWM_BLOCKING: 0x4D,\n /* 'n' */ DRAW_SCALE: 0x6E,\n /* 'N' */ DRAW_SCALE_BLOCKING: 0x4E,\n /* 'c' */ FLUSH_CMD_QUEUE: 0x63,\n /* 't' */ TEST_PATTERN: 0x74,\n /* 'w' */ SET_CONST_PWM: 0x77,\n /* 's' */ SET_CONST_SCALE: 0x73,\n /* 'p' */ SET_PX_PWM: 0x70,\n /* 'q' */ SET_PX_SCALE: 0x71,\n /* 127 */ IDENTITY_STRING: 0x7F,\n});\n\nexport const IDENTITY_STR_LEN = 25;\n\nexport const IDENTITY_STR_REGEX = /^Sig\\sFW\\sLED\\sMatrix\\sFW\\sV(\\d+)\\.(\\d+)$/;\n","import { GAMMA } from '../../../hardware-constants.js';\nimport { Command, IDENTITY_STR_LEN } from './commands.js';\n\nexport class CommandAbstractionLayer {\n constructor(portMutex = null) {\n this.portMutex = portMutex;\n }\n\n async bootloader() {\n await this.portMutex.acquire(async p => {\n await p.tx([Command.BOOTLOADER]);\n });\n }\n\n async identityString() {\n let ident = null;\n\n await this.portMutex.acquire(async p => {\n await p.tx([Command.IDENTITY_STRING]);\n ident = await p.rx(IDENTITY_STR_LEN);\n });\n\n return String.fromCharCode(...ident);\n }\n\n async setPixelPwm(r, c, brightness) {\n await this.portMutex.acquire(\n async p => {\n await p.tx([Command.SET_PX_PWM, c, r, brightness]);\n }\n );\n }\n\n async setGlobalPwm(brightness) {\n await this.portMutex.acquire(\n async p => {\n await p.tx([Command.SET_CONST_PWM, brightness]);\n }\n );\n }\n\n async setMatrixPwm(matrix) {\n // Only execute the most recent call \n await this.portMutex.acquireIdempotent(\n 'drawMatrix', \n async p => {\n await p.tx(\n [Command.DRAW_PWM].concat(\n matrix.flat().map(v => \n GAMMA[Math.floor((v ?? 0) * 255)]\n )\n )\n );\n }\n );\n }\n\n async setPixelAnalog(r, c, brightness) {\n await this.portMutex.acquire(\n async p => {\n await p.tx([Command.SET_PX_SCALE, c, r, brightness]);\n }\n );\n }\n\n async setGlobalAnalog(brightness) {\n await this.portMutex.acquire(\n async p => {\n await p.tx([Command.SET_CONST_SCALE, brightness]);\n }\n );\n }\n\n async setMatrixAnalog(matrix) {\n // Only execute the most recent call \n await this.portMutex.acquireIdempotent(\n 'drawMatrix', \n async p => {\n await p.tx(\n [Command.DRAW_SCALE].concat(\n matrix.flat().map(v => \n GAMMA[Math.floor((v ?? 0) * 255)]\n )\n )\n );\n }\n );\n }\n}\n","import { close, getUnusedPort } from '../../../web-serial/port.js';\nimport { PortMutex } from '../../../web-serial/PortMutex.js';\nimport { PortOperations } from '../../../web-serial/PortOperations.js';\nimport { CommandAbstractionLayer } from './CommandAbstractionLayer.js';\nimport { IDENTITY_STR_REGEX } from './commands.js';\n\nexport class SigrootController extends CommandAbstractionLayer {\n async bootloader() {\n await super.bootloader();\n }\n\n async connect() {\n const port = await getUnusedPort();\n\n if (port?.connected) {\n await close(port);\n await port.open({ baudRate: 115200 });\n this.portMutex = new PortMutex(new PortOperations(port));\n }\n }\n\n async draw(matrix) {\n if (!this.#scaleInitialized) {\n await super.setGlobalAnalog(0x20);\n this.#scaleInitialized = true;\n } else {\n throw new Error('No Port Found');\n }\n\n await super.setMatrixPwm(matrix);\n }\n\n async verifyFirmware() { \n return await this.version() != null;\n }\n\n async version() {\n const ident = await super.identityString();\n const match = ident.match(IDENTITY_STR_REGEX);\n\n if (match && match.length == 3) {\n return {\n major: match[1],\n minor: match[2]\n }\n } else {\n return null;\n }\n }\n\n #scaleInitialized;\n}\n","import { PID, VID } from '../hardware-constants.js';\n\nconst filters = [{ vendorId: VID, productId: PID }];\n\nexport class DeviceSelectionCancelled extends Error {\n constructor() {\n super('User cancelled device selection.');\n this.name = this.constructor.name;\n this.date = new Date();\n }\n}\n\nasync function requestDevice() {\n try {\n if (navigator.serial.requestPort) {\n return await navigator.serial.requestDevice({ filters });\n } else {\n return null; // Web Worker\n }\n } catch (e) {\n switch (e.name) {\n case ('NotFoundError'):\n throw new DeviceSelectionCancelled();\n case ('SecurityError'): // No user gesture\n return null;\n default:\n throw e;\n }\n }\n}\n\nclass KnownDevices {\n used = new Set();\n unused = [];\n\n async getOrFetchUnused() {\n let device = this.unused.pop();\n\n if (!device) {\n const systemDevices = await navigator.hid.getDevices({ filters });\n this.#enqueueUnique(systemDevices);\n device = this.unused.pop();\n }\n\n if (!device) {\n const manualDevices = await requestDevice();\n this.#enqueueUnique([manualDevices]);\n device = this.unused.pop();\n }\n\n if (device) {\n this.used.add(device);\n }\n\n return device;\n }\n\n #enqueueUnique(devices) {\n if (devices) {\n for (const dev of devices) {\n if (dev && !this.used.has(dev) && !this.unused.includes(dev)) {\n this.unused.push(dev);\n }\n }\n }\n }\n}\n\nconst knownDevices = new KnownDevices();\n\n/**\n * Adds user-selected device to permitted device. Only for use outside of Web \n * Worker to establish permission for use within Web Worker.\n * @returns {null}\n */\nexport async function reqestDeviceForWorker() {\n const _ = await requestDevice();\n}\n\n/**\n * Never returns the same device twice. \n * @returns {(HIDDevice|null)}\n */\nexport async function getUnusedDevice() {\n return await knownDevices.getOrFetchUnused();\n}\n","import { pad } from './util.js';\n\nexport class HIDOperations {\n constructor(device) {\n this.#device = device;\n }\n\n async send(report, data) {\n if (data.length < report.bytes) {\n data = pad(data, report.bytes);\n } else if (data.length > report.bytes) {\n throw new Error('Unable to send report: too many bytes');\n }\n\n const buffer = new Uint8Array(data).buffer;\n\n if (report.feature) {\n await this.#device.sendFeatureReport(report.id, buffer);\n } else {\n await this.#device.sendReport(report.id, buffer);\n }\n }\n\n async request(report) {\n let reply = [];\n\n if (report.feature) {\n reply = await this.#device.receiveFeatureReport(report.id);\n } else {\n /* \n * HID input reports are used for unprompted data.\n * See WebHID `HIDInputReportEvent`\n */\n throw new Error('Invalid operation');\n }\n\n if (reply.byteLength != report.bytes) {\n const exp = report.bytes;\n const act = reply.byteLength;\n console.error(`reply length=${act} (expected ${exp})`);\n }\n\n return reply;\n }\n\n #device;\n}\n","export function pad(arr, len, val=0x00) {\n return arr.concat(new Array(len - arr.length).fill(val));\n}\n","export const Reports = {\n GLITTER_DEVICE_INFO: {\n id: 0x01,\n bytes: 307,\n feature: true,\n },\n GLITTER_BASIC_CMD: {\n id: 0x02,\n bytes: 16,\n feature: true,\n },\n GLITTER_GRID_PWM_CNTL: {\n id: 0x03,\n bytes: 306,\n feature: true,\n },\n GLITTER_GRID_PWM_CNTL: {\n id: 0x04,\n bytes: 306,\n feature: true,\n }\n}\n\nexport const Commands = {\n GLITTER_CMD_REBOOT: 0x00,\n GLITTER_CMD_SLEEP: 0x01,\n GLITTER_CMD_WAKE_ON_COMMAND: 0x02,\n GLITTER_CMD_SET_SLEEP_TIMEOUT: 0x03,\n GLITTER_CMD_SET_GLOBAL_BRIGHTNESS: 0x04,\n GLITTER_CMD_DRAW_PIXEL: 0x05,\n GLITTER_CMD_DRAW_LINE: 0x06\n}\n\nexport const BootMode = {\n BOOTSEL: 0x00,\n NORMAL: 0x01,\n}\n","import { GAMMA } from '../../../hardware-constants.js';\nimport { Commands, Reports } from './reports.js';\n\nexport class ReportAbstractionLayer {\n constructor(device = null) {\n this.device = device;\n }\n\n async info() {\n const infoRaw = await this.device.request(Reports.GLITTER_DEVICE_INFO);\n\n return {\n sleep_pin: infoRaw.getUint8(1),\n dip1_pin: infoRaw.getUint8(2),\n intb_pin: infoRaw.getUint8(3),\n state_flags: infoRaw.getUint8(4),\n id_reg: infoRaw.getUint8(5),\n config_reg: infoRaw.getUint8(6),\n global_brightness: infoRaw.getUint8(7),\n display_width: infoRaw.getUint8(8),\n display_height: infoRaw.getUint8(9),\n timeout_ms: infoRaw.getUint32(10),\n version_major: infoRaw.getUint8(14),\n version_minor: infoRaw.getUint8(15),\n };\n }\n\n async wake() {\n await this.device.send(\n Reports.GLITTER_BASIC_CMD,\n [Commands.GLITTER_CMD_SLEEP, false]\n );\n }\n\n async sleep() {\n await this.device.send(\n Reports.GLITTER_BASIC_CMD,\n [Commands.GLITTER_CMD_SLEEP, true]\n );\n }\n\n async disableSleep() {\n await this.device.send(\n Reports.GLITTER_BASIC_CMD, \n [Commands.GLITTER_CMD_SET_SLEEP_TIMEOUT, 0xff, 0xff, 0xff, 0xff]\n );\n }\n\n async disableDeepSleep() {\n await this.device.send(\n Reports.GLITTER_BASIC_CMD, \n [Commands.GLITTER_CMD_WAKE_ON_COMMAND, 0x01]\n );\n }\n\n async disableSleepTimer() {\n await this.device.send(\n Reports.GLITTER_BASIC_CMD, \n [Commands.GLITTER_CMD_SET_SLEEP_TIMEOUT, 0x00, 0x00, 0x00, 0x00]\n );\n }\n \n async enableDeepSleep() {\n await this.device.send(\n Reports.GLITTER_BASIC_CMD, \n [Commands.GLITTER_CMD_WAKE_ON_COMMAND, 0x00]\n );\n }\n\n async enableSleepTimer(milliseconds) {\n const view = new DataView(new ArrayBuffer(4));\n const littleEndian = false;\n view.setInt32(0, milliseconds, littleEndian);\n await this.device.send(\n Reports.GLITTER_BASIC_CMD, \n [\n Commands.GLITTER_CMD_SET_SLEEP_TIMEOUT, \n view.getUint8(0), \n view.getUint8(1), \n view.getUint8(2), \n view.getUint8(3),\n ]\n );\n }\n\n async reboot(mode) {\n await this.device.send(\n Reports.GLITTER_BASIC_CMD, \n [Commands.GLITTER_CMD_REBOOT, mode]\n );\n }\n\n async drawMatrix(matrix) {\n await this.device.send(\n Reports.GLITTER_GRID_PWM_CNTL,\n matrix.flat().map(v => GAMMA[Math.floor((v ?? 0) * 255)])\n );\n }\n\n async drawPixel(r, c, brightness) {\n await this.device.send(\n Reports.GLITTER_BASIC_CMD,\n [Commands.GLITTER_CMD_DRAW_PIXEL, c, r, brightness]\n );\n }\n\n async drawLine({r1, c1}, {r2, c2}, brightness) {\n await this.device.send(\n Reports.GLITTER_BASIC_CMD,\n [Commands.GLITTER_CMD_DRAW_PIXEL, r1, c1, r2, c2, brightness]\n );\n }\n\n device;\n}\n","import { HEIGHT, WIDTH } from '../../../hardware-constants.js';\nimport { getUnusedDevice } from '../../../web-hid/device.js';\nimport { HIDOperations } from '../../../web-hid/HIDOperations.js';\nimport { ReportAbstractionLayer } from './ReportAbstractionLayer.js';\nimport { BootMode } from './reports.js';\n\nexport class SparkleController extends ReportAbstractionLayer {\n async bootloader() {\n await super.reboot(BootMode.BOOTSEL);\n }\n\n async connect() {\n const device = await getUnusedDevice();\n\n if (device) {\n await device.open();\n this.device = new HIDOperations(device);\n } else {\n throw new Error('No Device Found');\n }\n }\n \n async draw(matrix) {\n await super.drawMatrix(matrix);\n }\n\n async verifyFirmware() {\n try {\n const info = await super.info();\n return (\n info.display_height == HEIGHT &&\n info.display_width == WIDTH\n );\n } catch {\n return false;\n }\n }\n\n async version() {\n const info = await super.info();\n\n if (info.version_major != undefined \n && info.version_minor != undefined\n && (info.version_major > 0 || info.version_minor > 0)) {\n return {\n major: info.version_major,\n minor: info.version_minor\n }\n } else {\n // Sparkle <=1.1.1: Glitter version unavailable \n return { major: 1, minor: 0 };\n }\n }\n}\n","import { DefaultController } from './supported-firmware/FrameworkComputer/inputmodule-rs/DefaultController.js';\nimport { SigrootController } from './supported-firmware/sigroot/FW_LED_Matrix_Firmware/SigrootController.js';\nimport { SparkleController } from './supported-firmware/vddCore/sparkle-fw16/SparkleController.js';\n\nexport class HardwareControllerFactory {\n static async detectSerial() {\n const c1 = new DefaultController();\n const c2 = new SigrootController();\n\n await c1.connect();\n if (await c1.verifyFirmware()) {\n return c1;\n }\n \n await c2.connect()\n if (await c2.verifyFirmware()) {\n return c2;\n } \n \n return null;\n }\n\n static async detectHID() {\n const c1 = new SparkleController();\n\n await c1.connect();\n if (await c1.verifyFirmware()) {\n return c1;\n } \n \n return null;\n }\n}\n"],"names":["WIDTH","HEIGHT","VID","VID_ARR","PID","PID_ARR","GAMMA","Object","freeze","filters","usbVendorId","usbProductId","PortSelectionCancelled","Error","constructor","super","this","name","date","Date","PortUnavailable","async","requestPort","navigator","serial","e","knownPorts","used","Set","unused","getOrFetchUnused","port","pop","systemPorts","getPorts","enqueueUnique","manualPort","add","ports","has","includes","push","requestPortForWorker","getUnusedPort","close","message","PortMutex","portOperations","lockName","Math","random","toString","deduper","Map","portOps","acquire","fn","trace","stack","enqueue","console","error","acquireIdempotent","key","info","set","execDedupedOp","locks","request","get","delete","PortOperations","rx","length","timeout","readable","locked","response","reader","getReader","timeoutHandle","setTimeout","cancel","value","done","read","clearTimeout","releaseLock","tx","buffer","writable","writer","getWriter","write","Uint8Array","Command","ANIMATE","BRIGHTNESS","BOOTLOADER","DRAW","DRAW_GREY_COL_BUFFER","GAME_CTRL","GAME_STATUS","PANIC","PATTERN","SLEEP","STAGE_GREY_COL","START_GAME","VERSION","BitDepth","GRAY_8BIT","MONO_1BIT","CommandAbstractionLayer$1","portMutex","bootloader","p","brightness","draw","matrix","index","output","fill","r","c","drawGrayscale","buffers","Array","from","_","floor","i","asleep","sleep","wake","pattern","percent","Pattern","PERCENTAGE","version","ver","major","minor","patch","preRelease","DefaultController","CommandAbstractionLayer","connect","connected","open","baudRate","bitDepth","verifyFirmware","undefined","NOOP","ANIMATION_DIAMOND","ANIMATION_FIRE","ANIMATION_FIREPLACE","ANIMATION_GEAR","ANIMATION_RING","ANIMATION_STARTUP","ANIMATION_STARTUP_ONCE","DRAW_PWM","DRAW_PWM_BLOCKING","DRAW_SCALE","DRAW_SCALE_BLOCKING","FLUSH_CMD_QUEUE","TEST_PATTERN","SET_CONST_PWM","SET_CONST_SCALE","SET_PX_PWM","SET_PX_SCALE","IDENTITY_STRING","IDENTITY_STR_REGEX","identityString","ident","String","fromCharCode","setPixelPwm","setGlobalPwm","setMatrixPwm","concat","flat","map","v","setPixelAnalog","setGlobalAnalog","setMatrixAnalog","SigrootController","scaleInitialized","match","vendorId","productId","DeviceSelectionCancelled","requestDevice","knownDevices","device","systemDevices","hid","getDevices","manualDevices","devices","dev","reqestDeviceForWorker","getUnusedDevice","HIDOperations","send","report","data","bytes","arr","len","val","pad","feature","sendFeatureReport","id","sendReport","reply","receiveFeatureReport","byteLength","exp","act","Reports","Commands","BootMode","ReportAbstractionLayer","infoRaw","sleep_pin","getUint8","dip1_pin","intb_pin","state_flags","id_reg","config_reg","global_brightness","display_width","display_height","timeout_ms","getUint32","version_major","version_minor","disableSleep","disableDeepSleep","disableSleepTimer","enableDeepSleep","enableSleepTimer","milliseconds","view","DataView","ArrayBuffer","setInt32","reboot","mode","drawMatrix","drawPixel","drawLine","r1","c1","r2","c2","SparkleController","HardwareControllerFactory","detectSerial","detectHID"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"led-matrix-controllers.browser.mjs","sources":["../src/hardware-constants.js","../src/environments/web/usb-serial/port.js","../src/environments/web/usb-serial/PortMutex.js","../src/environments/web/usb-serial/PortOperations.js","../src/supported-firmware/FrameworkComputer/inputmodule-rs/commands.js","../src/supported-firmware/FrameworkComputer/inputmodule-rs/CommandAbstractionLayer.js","../src/supported-firmware/FrameworkComputer/inputmodule-rs/DefaultController.js","../src/supported-firmware/sigroot/FW_LED_Matrix_Firmware/commands.js","../src/supported-firmware/sigroot/FW_LED_Matrix_Firmware/CommandAbstractionLayer.js","../src/supported-firmware/sigroot/FW_LED_Matrix_Firmware/SigrootController.js","../src/environments/web/usb-hid/device.js","../src/environments/web/usb-hid/HIDOperations.js","../src/environments/web/usb-hid/util.js","../src/supported-firmware/vddCore/sparkle-fw16/reports.js","../src/supported-firmware/vddCore/sparkle-fw16/ReportAbstractionLayer.js","../src/supported-firmware/vddCore/sparkle-fw16/SparkleController.js","../src/HardwareControllerFactory.js"],"sourcesContent":["export const WIDTH = 9;\nexport const HEIGHT = 34;\nexport const VID = 0x32AC;\nexport const VID_ARR = [0x32, 0xAC];\nexport const PID = 0x0020;\nexport const PID_ARR = [0x00, 0x20];\n\n// For PWM dimming (not for analog dimming/constant-current reduction!)\nexport const GAMMA = Object.freeze([\n 0, 0, 0, 0, 0, 0, 0, 1, \n 1, 1, 1, 1, 1, 1, 1, 1, \n 1, 1, 1, 1, 1, 1, 1, 1, \n 1, 1, 1, 1, 1, 1, 1, 1, \n 1, 1, 1, 2, 2, 2, 2, 2, \n 2, 2, 2, 2, 3, 3, 3, 3, \n 3, 3, 3, 4, 4, 4, 4, 4, \n 4, 5, 5, 5, 5, 6, 6, 6, \n 6, 6, 7, 7, 7, 7, 8, 8, \n 8, 9, 9, 9, 10, 10, 10, 11, \n 11, 11, 12, 12, 12, 13, 13, 14, \n 14, 14, 15, 15, 16, 16, 17, 17, \n 17, 18, 18, 19, 19, 20, 20, 21, \n 22, 22, 23, 23, 24, 24, 25, 26, \n 26, 27, 27, 28, 29, 29, 30, 31, \n 32, 32, 33, 34, 34, 35, 36, 37, \n 38, 38, 39, 40, 41, 42, 42, 43, \n 44, 45, 46, 47, 48, 49, 50, 51, \n 52, 53, 54, 55, 56, 57, 58, 59, \n 60, 61, 62, 63, 64, 66, 67, 68, \n 69, 70, 71, 73, 74, 75, 76, 78, \n 79, 80, 82, 83, 84, 86, 87, 88, \n 90, 91, 93, 94, 96, 97, 99, 100, \n 102, 103, 105, 106, 108, 110, 111, 113, \n 115, 116, 118, 120, 121, 123, 125, 127, \n 128, 130, 132, 134, 136, 138, 140, 141, \n 143, 145, 147, 149, 151, 153, 155, 157, \n 159, 161, 164, 166, 168, 170, 172, 174, \n 177, 179, 181, 183, 186, 188, 190, 193, \n 195, 197, 200, 202, 205, 207, 210, 212, \n 215, 217, 220, 222, 225, 228, 230, 233, \n 236, 238, 241, 244, 247, 249, 252, 255\n]);\n","import { PID, VID } from '../../../hardware-constants.js';\n\nconst filters = [{ usbVendorId: VID, usbProductId: PID }];\n\nexport class PortSelectionCancelled extends Error {\n constructor() {\n super('User cancelled port selection.');\n this.name = this.constructor.name;\n this.date = new Date();\n }\n}\n\nexport class PortUnavailable extends Error {\n constructor() {\n super('Selected port already in use.');\n this.name = this.constructor.name;\n this.date = new Date();\n }\n}\n\nasync function requestPort() {\n try {\n if (navigator.serial.requestPort) {\n return Object.assign(\n await navigator.serial.requestPort({ filters }),\n { pickedByUser: true }\n );\n } else {\n return null; // Web Worker\n }\n } catch (e) {\n switch (e.name) {\n case ('NotFoundError'):\n throw new PortSelectionCancelled();\n case ('InvalidStateError'):\n throw new PortUnavailable();\n case ('SecurityError'): // No user gesture\n return null;\n default:\n throw e;\n }\n }\n}\n\nclass KnownPorts {\n used = new Set();\n unused = [];\n\n async getOrFetchUnused() {\n let port = this.unused.pop();\n \n if (!port) {\n const knownPorts = await navigator.serial.getPorts({ filters });\n this.#enqueueUnique(knownPorts);\n port = this.unused.pop();\n }\n\n if (!port) {\n const manualPort = await requestPort();\n this.#enqueueUnique([manualPort]);\n port = this.unused.pop();\n }\n\n if (port) {\n this.used.add(port);\n }\n \n return port;\n }\n\n #enqueueUnique(ports) {\n if (ports) {\n for (const port of ports) {\n if (port && !this.used.has(port) && !this.unused.includes(port)) {\n this.unused.push(port);\n }\n }\n }\n }\n}\n\nconst knownPorts = new KnownPorts();\n\n/**\n * Adds user-selected port to permitted ports. Only for use outside of Web \n * Worker to establish permission for use within Web Worker.\n * @returns {null}\n */\nexport async function requestPortForWorker() {\n const _ = await requestPort();\n}\n\n/**\n * Never returns the same port twice. \n * @returns {(SerialPort|null)}\n */\nexport async function getUnusedPort() {\n return await knownPorts.getOrFetchUnused();\n}\n\n/**\n * Close port without throwing if already closed.\n * @param {SerialPort} port \n */\nexport async function close(port) {\n try {\n await port.close();\n } catch(e) {\n if (e.name != 'InvalidStateError') {\n if (e.message.includes('The port is already closed')) {\n throw e;\n }\n }\n }\n}\n","export class PortMutex {\n constructor(portOperations) {\n this.#lockName = `port-mutex-${Math.random().toString()}`;\n this.#deduper = new Map();\n this.#portOps = portOperations;\n }\n\n async acquire(fn) {\n const trace = new Error('created bad cb').stack;\n\n await this.#enqueue(async () => {\n try {\n await fn(this.#portOps);\n } catch (e) {\n console.error('Error occured in anonymous callback.');\n console.error('Original error:', e);\n console.error('--- This callback was created at ---\\n', trace);\n }\n });\n }\n\n async acquireIdempotent(key, fn) {\n const trace = new Error('created bad cb').stack;\n\n if (this.#deduper.has(key)) {\n console.info(`\"${key}\" request coalesced.`);\n }\n\n this.#deduper.set(key, async () => {\n try {\n await fn(this.#portOps);\n } catch (e) {\n console.error('Error occured in anonymous callback.');\n console.error('Original error:', e);\n console.error('--- This callback was created at ---\\n', trace);\n }\n });\n\n await this.#enqueue(() => this.#execDedupedOp(key));\n }\n\n async #enqueue(fn) {\n // `navigator.locks` maintains queue and provides mutual exclusion.\n return navigator.locks.request(this.#lockName, fn);\n }\n\n async #execDedupedOp(key) {\n if (this.#deduper.has(key)) {\n const fn = this.#deduper.get(key);\n this.#deduper.delete(key);\n await fn();\n }\n }\n\n #lockName;\n #deduper;\n #portOps;\n}\n","export class PortOperations {\n constructor(port) {\n this.#port = port;\n }\n\n async rx(length, timeout=3000) {\n if (this.#port === null) {\n throw new Error('attempted RX on uninitialized port.');\n }\n\n if (this.#port.readable === null) {\n throw new Error('attempted RX on closed port.');\n }\n\n /*\n * ReadableStream's built-in locking mechanism cannot be awaited or otherwise\n * asynchronously acquired. A PortMutex must be used.\n */\n if (this.#port.readable.locked) {\n throw new Error('attempted RX while port locked.');\n }\n\n const response = [];\n const reader = this.#port.readable.getReader();\n const timeoutHandle = setTimeout(() => reader.cancel(), timeout);\n\n try {\n // Response may be divided across multiple reads\n while (response.length < length) {\n const { value, done } = await reader.read();\n response.push(...(value ?? []));\n if (done || !value) break;\n }\n } finally {\n clearTimeout(timeoutHandle);\n reader.releaseLock();\n }\n\n return response;\n }\n\n async tx(buffer) {\n if (this.#port === null) {\n throw new Error('attempted TX on uninitialized port.');\n }\n\n if (this.#port.writable === null) {\n throw new Error('attempted TX on closed port.');\n }\n \n /*\n * WritableStream's built-in locking mechanism cannot be awaited or otherwise\n * asynchronously acquired. A PortMutex must be used.\n */\n if (this.#port.writable.locked) {\n throw new Error('attempted TX while port locked.');\n }\n\n const writer = this.#port.writable.getWriter();\n\n try {\n await writer.write(new Uint8Array(buffer));\n } finally {\n /* \n * The writer must be completely torn down between every single write.\n * Many parsers can't handle delayed flushing and write coalescing.\n * Command sequences will fail if `releaseLock()` is used here.\n */\n await writer.close();\n }\n }\n\n #port;\n}\n","// All replies to all commands are 32 bytes\nexport const RX_PACKET_SZ = 32;\n\nexport const Command = Object.freeze({\n ANIMATE: 0x04,\n BRIGHTNESS: 0x00,\n BOOTLOADER: 0x02,\n DRAW: 0x06,\n DRAW_GREY_COL_BUFFER: 0x08,\n GAME_CTRL: 0x11,\n GAME_STATUS: 0x12,\n PANIC: 0x05,\n PATTERN: 0x01,\n SLEEP: 0x03,\n STAGE_GREY_COL: 0x07,\n START_GAME: 0x10,\n VERSION: 0x20,\n});\n\n// Used with Command.PATTERN\nexport const Pattern = Object.freeze({\n DISPLAY_LOTUS_HORIZONTAL: 0x03,\n DISPLAY_LOTUS_VERTICAL: 0x07,\n DISPLAY_PANIC: 0x06,\n DOUBLE_GRADIENT: 0x02,\n FULL_BRIGHTNESS: 0x05,\n GRADIENT: 0x01,\n PERCENTAGE: 0x00,\n ZIG_ZAG: 0x04,\n});\n\n// DRAW or DRAW_GREY_COL_BUFFER\nexport const BitDepth = Object.freeze({\n GRAY_8BIT: '8-bit',\n MONO_1BIT: '1-bit',\n})\n","import { GAMMA, HEIGHT, VID_ARR, WIDTH } from '../../../hardware-constants.js';\nimport { Command, Pattern, RX_PACKET_SZ } from './commands.js';\n\nexport class CommandAbstractionLayer {\n constructor(portMutex = null) {\n this.portMutex = portMutex;\n }\n\n async bootloader() {\n await this.portMutex.acquire(async p => {\n await p.tx([...VID_ARR, Command.BOOTLOADER]);\n });\n }\n\n async brightness(brightness) {\n await this.portMutex.acquire(async p => {\n await p.tx([...VID_ARR, Command.BRIGHTNESS, brightness]);\n });\n }\n\n async draw(matrix) {\n let index = 0;\n let output = new Uint8Array(39).fill(0);\n\n // Pack cells into bits\n for (let r = 0; r < HEIGHT; r++) {\n for (let c = 0; c < WIDTH; c++) {\n if (matrix[r][c]) {\n output[index >> 3] |= 1 << index % 8;\n }\n index++;\n }\n }\n\n await this.portMutex.acquireIdempotent(\n 'drawMatrix', \n async p => {\n await p.tx([...VID_ARR, Command.DRAW, ...output]);\n }\n );\n }\n\n async drawGrayscale(matrix) {\n // Transpose & Gamma Correction\n const buffers = Array.from(\n { length: WIDTH }, \n (_, c) => Array.from(\n { length: HEIGHT }, \n (_, r) => GAMMA[Math.floor((matrix[r][c] ?? 0) * 255)]\n )\n );\n\n // Only execute the most recent call \n await this.portMutex.acquireIdempotent(\n 'drawMatrix', \n async p => {\n for (let i = 0; i < WIDTH; i++) {\n await p.tx([...VID_ARR, Command.STAGE_GREY_COL, i, ...buffers[i]]);\n }\n await p.tx([...VID_ARR, Command.DRAW_GREY_COL_BUFFER]);\n }\n );\n }\n\n async asleep() {\n let asleep = false;\n\n await this.portMutex.acquire(async p => {\n await p.tx([...VID_ARR, Command.SLEEP]);\n asleep = await p.rx(RX_PACKET_SZ);\n asleep = asleep[0] != 0x00;\n });\n\n return asleep;\n }\n\n async sleep() {\n await this.portMutex.acquire(async p => {\n await p.tx([...VID_ARR, Command.SLEEP, 0x01]);\n });\n }\n\n async wake() {\n await this.portMutex.acquire(async p => {\n await p.tx([...VID_ARR, Command.SLEEP]);\n });\n }\n\n async pattern(pattern) {\n await this.portMutex.acquireIdempotent(\n 'drawMatrix',\n async p => {\n await p.tx([...VID_ARR, Command.PATTERN, pattern]);\n }\n );\n }\n\n async percent(percent) {\n percent = Math.min(percent, 100);\n percent = Math.max(percent, 0);\n percent = Math.round(percent);\n\n await this.portMutex.acquireIdempotent(\n 'drawMatrix',\n async p => {\n await p.tx([...VID_ARR, Command.PATTERN, Pattern.PERCENTAGE, percent]);\n }\n );\n }\n\n async version() {\n let ver = {};\n\n await this.portMutex.acquire(async p => {\n await p.tx([...VID_ARR, Command.VERSION]);\n const response = await p.rx(RX_PACKET_SZ);\n\n // MMMMMMMM mmmmPPPP 0000000p\n ver.major = response[0];\n ver.minor = response[1] >> 4;\n ver.patch = response[1] & 0x0F;\n ver.preRelease = response[2] == 1;\n });\n\n return ver;\n }\n\n async scrolling() {\n let scrolling = false;\n\n await this.portMutex.acquire(async p => {\n await p.tx([...VID_ARR, Command.ANIMATE]);\n scrolling = await p.rx(RX_PACKET_SZ);\n scrolling = scrolling[0] != 0x00;\n });\n\n return scrolling;\n }\n\n async startScrolling() {\n await this.portMutex.acquire(async p => {\n await p.tx([...VID_ARR, Command.ANIMATE, 0x01]);\n });\n }\n\n async stopScrolling() {\n await this.portMutex.acquire(async p => {\n await p.tx([...VID_ARR, Command.ANIMATE, 0x00]);\n });\n }\n}\n","import { close, getUnusedPort } from '../../../environments/web/usb-serial/port.js';\nimport { PortMutex } from '../../../environments/web/usb-serial/PortMutex.js';\nimport { PortOperations } from '../../../environments/web/usb-serial/PortOperations.js';\nimport { CommandAbstractionLayer } from './CommandAbstractionLayer.js';\nimport { BitDepth } from './commands.js';\n\nexport class DefaultController extends CommandAbstractionLayer {\n async bootloader() {\n await super.bootloader();\n }\n\n async connect() {\n const port = await getUnusedPort();\n\n if (port?.connected) {\n await close(port);\n await port.open({ baudRate: 115200 });\n this.portMutex = new PortMutex(new PortOperations(port));\n } else {\n throw new Error('No Port Found');\n }\n }\n\n async draw(matrix) {\n switch (this.bitDepth ?? BitDepth.MONO_1BIT) {\n\n case (BitDepth.GRAY_8BIT):\n await super.drawGrayscale(matrix);\n break;\n\n case (BitDepth.MONO_1BIT):\n await super.draw(matrix);\n break;\n\n default:\n console.error(`Unsupported bitdepth: ${this.bitDepth}`);\n }\n }\n\n async verifyFirmware() {\n try {\n const version = await super.version();\n\n return version\n && version.major != undefined\n && version.minor != undefined\n && version.patch != undefined\n && version.preRelease != undefined;\n \n } catch {\n return false;\n }\n }\n\n async version() {\n return super.version();\n }\n}\n","export const Command = Object.freeze({\n /* 000 */ NOOP: 0x00,\n /* 'd' */ ANIMATION_DIAMOND: 0x64,\n /* 'b' */ ANIMATION_FIRE: 0x62,\n /* 'f' */ ANIMATION_FIREPLACE: 0x66,\n /* 'g' */ ANIMATION_GEAR: 0x67,\n /* 'r' */ ANIMATION_RING: 0x72,\n /* 'a' */ ANIMATION_STARTUP: 0x61,\n /* 'A' */ ANIMATION_STARTUP_ONCE: 0x41,\n /* 'e' */ BOOTLOADER: 0x65,\n /* 'm' */ DRAW_PWM: 0x6D,\n /* 'M' */ DRAW_PWM_BLOCKING: 0x4D,\n /* 'n' */ DRAW_SCALE: 0x6E,\n /* 'N' */ DRAW_SCALE_BLOCKING: 0x4E,\n /* 'c' */ FLUSH_CMD_QUEUE: 0x63,\n /* 't' */ TEST_PATTERN: 0x74,\n /* 'w' */ SET_CONST_PWM: 0x77,\n /* 's' */ SET_CONST_SCALE: 0x73,\n /* 'p' */ SET_PX_PWM: 0x70,\n /* 'q' */ SET_PX_SCALE: 0x71,\n /* 127 */ IDENTITY_STRING: 0x7F,\n});\n\nexport const IDENTITY_STR_LEN = 25;\n\nexport const IDENTITY_STR_REGEX = /^Sig\\sFW\\sLED\\sMatrix\\sFW\\sV(\\d+)\\.(\\d+)$/;\n","import { GAMMA } from '../../../hardware-constants.js';\nimport { Command, IDENTITY_STR_LEN } from './commands.js';\n\nexport class CommandAbstractionLayer {\n constructor(portMutex = null) {\n this.portMutex = portMutex;\n }\n\n async bootloader() {\n await this.portMutex.acquire(async p => {\n await p.tx([Command.BOOTLOADER]);\n });\n }\n\n async identityString() {\n let ident = null;\n\n await this.portMutex.acquire(async p => {\n await p.tx([Command.IDENTITY_STRING]);\n ident = await p.rx(IDENTITY_STR_LEN);\n });\n\n return String.fromCharCode(...ident);\n }\n\n async setPixelPwm(r, c, brightness) {\n await this.portMutex.acquire(\n async p => {\n await p.tx([Command.SET_PX_PWM, c, r, brightness]);\n }\n );\n }\n\n async setGlobalPwm(brightness) {\n await this.portMutex.acquire(\n async p => {\n await p.tx([Command.SET_CONST_PWM, brightness]);\n }\n );\n }\n\n async setMatrixPwm(matrix) {\n // Only execute the most recent call \n await this.portMutex.acquireIdempotent(\n 'drawMatrix', \n async p => {\n await p.tx(\n [Command.DRAW_PWM].concat(\n matrix.flat().map(v => \n GAMMA[Math.floor((v ?? 0) * 255)]\n )\n )\n );\n }\n );\n }\n\n async setPixelAnalog(r, c, brightness) {\n await this.portMutex.acquire(\n async p => {\n await p.tx([Command.SET_PX_SCALE, c, r, brightness]);\n }\n );\n }\n\n async setGlobalAnalog(brightness) {\n await this.portMutex.acquire(\n async p => {\n await p.tx([Command.SET_CONST_SCALE, brightness]);\n }\n );\n }\n\n async setMatrixAnalog(matrix) {\n // Only execute the most recent call \n await this.portMutex.acquireIdempotent(\n 'drawMatrix', \n async p => {\n await p.tx(\n [Command.DRAW_SCALE].concat(\n matrix.flat().map(v => \n GAMMA[Math.floor((v ?? 0) * 255)]\n )\n )\n );\n }\n );\n }\n}\n","import { close, getUnusedPort } from '../../../environments/web/usb-serial/port.js';\nimport { PortMutex } from '../../../environments/web/usb-serial/PortMutex.js';\nimport { PortOperations } from '../../../environments/web/usb-serial/PortOperations.js';\nimport { CommandAbstractionLayer } from './CommandAbstractionLayer.js';\nimport { IDENTITY_STR_REGEX } from './commands.js';\n\nexport class SigrootController extends CommandAbstractionLayer {\n async bootloader() {\n await super.bootloader();\n }\n\n async connect() {\n const port = await getUnusedPort();\n\n if (port?.connected) {\n await close(port);\n await port.open({ baudRate: 115200 });\n this.portMutex = new PortMutex(new PortOperations(port));\n }\n }\n\n async draw(matrix) {\n if (!this.#scaleInitialized) {\n await super.setGlobalAnalog(0x20);\n this.#scaleInitialized = true;\n } else {\n throw new Error('No Port Found');\n }\n\n await super.setMatrixPwm(matrix);\n }\n\n async verifyFirmware() { \n return await this.version() != null;\n }\n\n async version() {\n const ident = await super.identityString();\n const match = ident.match(IDENTITY_STR_REGEX);\n\n if (match && match.length == 3) {\n return {\n major: match[1],\n minor: match[2]\n }\n } else {\n return null;\n }\n }\n\n #scaleInitialized;\n}\n","import { PID, VID } from '../../../hardware-constants.js';\n\nconst filters = [{ vendorId: VID, productId: PID }];\n\nexport class DeviceSelectionCancelled extends Error {\n constructor() {\n super('User cancelled device selection.');\n this.name = this.constructor.name;\n this.date = new Date();\n }\n}\n\nasync function requestDevice() {\n try {\n if (navigator.serial.requestPort) {\n return await navigator.serial.requestDevice({ filters });\n } else {\n return null; // Web Worker\n }\n } catch (e) {\n switch (e.name) {\n case ('NotFoundError'):\n throw new DeviceSelectionCancelled();\n case ('SecurityError'): // No user gesture\n return null;\n default:\n throw e;\n }\n }\n}\n\nclass KnownDevices {\n used = new Set();\n unused = [];\n\n async getOrFetchUnused() {\n let device = this.unused.pop();\n\n if (!device) {\n const systemDevices = await navigator.hid.getDevices({ filters });\n this.#enqueueUnique(systemDevices);\n device = this.unused.pop();\n }\n\n if (!device) {\n const manualDevices = await requestDevice();\n this.#enqueueUnique([manualDevices]);\n device = this.unused.pop();\n }\n\n if (device) {\n this.used.add(device);\n }\n\n return device;\n }\n\n #enqueueUnique(devices) {\n if (devices) {\n for (const dev of devices) {\n if (dev && !this.used.has(dev) && !this.unused.includes(dev)) {\n this.unused.push(dev);\n }\n }\n }\n }\n}\n\nconst knownDevices = new KnownDevices();\n\n/**\n * Adds user-selected device to permitted device. Only for use outside of Web \n * Worker to establish permission for use within Web Worker.\n * @returns {null}\n */\nexport async function reqestDeviceForWorker() {\n const _ = await requestDevice();\n}\n\n/**\n * Never returns the same device twice. \n * @returns {(HIDDevice|null)}\n */\nexport async function getUnusedDevice() {\n return await knownDevices.getOrFetchUnused();\n}\n","import { pad } from './util.js';\n\nexport class HIDOperations {\n constructor(device) {\n this.#device = device;\n }\n\n async send(report, data) {\n if (data.length < report.bytes) {\n data = pad(data, report.bytes);\n } else if (data.length > report.bytes) {\n throw new Error('Unable to send report: too many bytes');\n }\n\n const buffer = new Uint8Array(data).buffer;\n\n if (report.feature) {\n await this.#device.sendFeatureReport(report.id, buffer);\n } else {\n await this.#device.sendReport(report.id, buffer);\n }\n }\n\n async request(report) {\n let reply = [];\n\n if (report.feature) {\n reply = await this.#device.receiveFeatureReport(report.id);\n } else {\n /* \n * HID input reports are used for unprompted data.\n * See WebHID `HIDInputReportEvent`\n */\n throw new Error('Invalid operation');\n }\n\n if (reply.byteLength != report.bytes) {\n const exp = report.bytes;\n const act = reply.byteLength;\n console.error(`reply length=${act} (expected ${exp})`);\n }\n\n return reply;\n }\n\n #device;\n}\n","export function pad(arr, len, val=0x00) {\n return arr.concat(new Array(len - arr.length).fill(val));\n}\n","export const Reports = {\n GLITTER_DEVICE_INFO: {\n id: 0x01,\n bytes: 307,\n feature: true,\n },\n GLITTER_BASIC_CMD: {\n id: 0x02,\n bytes: 16,\n feature: true,\n },\n GLITTER_GRID_PWM_CNTL: {\n id: 0x03,\n bytes: 306,\n feature: true,\n },\n GLITTER_GRID_PWM_CNTL: {\n id: 0x04,\n bytes: 306,\n feature: true,\n }\n}\n\nexport const Commands = {\n GLITTER_CMD_REBOOT: 0x00,\n GLITTER_CMD_SLEEP: 0x01,\n GLITTER_CMD_WAKE_ON_COMMAND: 0x02,\n GLITTER_CMD_SET_SLEEP_TIMEOUT: 0x03,\n GLITTER_CMD_SET_GLOBAL_BRIGHTNESS: 0x04,\n GLITTER_CMD_DRAW_PIXEL: 0x05,\n GLITTER_CMD_DRAW_LINE: 0x06\n}\n\nexport const BootMode = {\n BOOTSEL: 0x00,\n NORMAL: 0x01,\n}\n","import { GAMMA } from '../../../hardware-constants.js';\nimport { Commands, Reports } from './reports.js';\n\nexport class ReportAbstractionLayer {\n constructor(device = null) {\n this.device = device;\n }\n\n async info() {\n const infoRaw = await this.device.request(Reports.GLITTER_DEVICE_INFO);\n\n return {\n sleep_pin: infoRaw.getUint8(1),\n dip1_pin: infoRaw.getUint8(2),\n intb_pin: infoRaw.getUint8(3),\n state_flags: infoRaw.getUint8(4),\n id_reg: infoRaw.getUint8(5),\n config_reg: infoRaw.getUint8(6),\n global_brightness: infoRaw.getUint8(7),\n display_width: infoRaw.getUint8(8),\n display_height: infoRaw.getUint8(9),\n timeout_ms: infoRaw.getUint32(10),\n version_major: infoRaw.getUint8(14),\n version_minor: infoRaw.getUint8(15),\n };\n }\n\n async wake() {\n await this.device.send(\n Reports.GLITTER_BASIC_CMD,\n [Commands.GLITTER_CMD_SLEEP, false]\n );\n }\n\n async sleep() {\n await this.device.send(\n Reports.GLITTER_BASIC_CMD,\n [Commands.GLITTER_CMD_SLEEP, true]\n );\n }\n\n async disableSleep() {\n await this.device.send(\n Reports.GLITTER_BASIC_CMD, \n [Commands.GLITTER_CMD_SET_SLEEP_TIMEOUT, 0xff, 0xff, 0xff, 0xff]\n );\n }\n\n async disableDeepSleep() {\n await this.device.send(\n Reports.GLITTER_BASIC_CMD, \n [Commands.GLITTER_CMD_WAKE_ON_COMMAND, 0x01]\n );\n }\n\n async disableSleepTimer() {\n await this.device.send(\n Reports.GLITTER_BASIC_CMD, \n [Commands.GLITTER_CMD_SET_SLEEP_TIMEOUT, 0x00, 0x00, 0x00, 0x00]\n );\n }\n \n async enableDeepSleep() {\n await this.device.send(\n Reports.GLITTER_BASIC_CMD, \n [Commands.GLITTER_CMD_WAKE_ON_COMMAND, 0x00]\n );\n }\n\n async enableSleepTimer(milliseconds) {\n const view = new DataView(new ArrayBuffer(4));\n const littleEndian = false;\n view.setInt32(0, milliseconds, littleEndian);\n await this.device.send(\n Reports.GLITTER_BASIC_CMD, \n [\n Commands.GLITTER_CMD_SET_SLEEP_TIMEOUT, \n view.getUint8(0), \n view.getUint8(1), \n view.getUint8(2), \n view.getUint8(3),\n ]\n );\n }\n\n async reboot(mode) {\n await this.device.send(\n Reports.GLITTER_BASIC_CMD, \n [Commands.GLITTER_CMD_REBOOT, mode]\n );\n }\n\n async drawMatrix(matrix) {\n await this.device.send(\n Reports.GLITTER_GRID_PWM_CNTL,\n matrix.flat().map(v => GAMMA[Math.floor((v ?? 0) * 255)])\n );\n }\n\n async drawPixel(r, c, brightness) {\n await this.device.send(\n Reports.GLITTER_BASIC_CMD,\n [Commands.GLITTER_CMD_DRAW_PIXEL, c, r, brightness]\n );\n }\n\n async drawLine({r1, c1}, {r2, c2}, brightness) {\n await this.device.send(\n Reports.GLITTER_BASIC_CMD,\n [Commands.GLITTER_CMD_DRAW_PIXEL, r1, c1, r2, c2, brightness]\n );\n }\n\n device;\n}\n","import { HEIGHT, WIDTH } from '../../../hardware-constants.js';\nimport { getUnusedDevice } from '../../../environments/web/usb-hid/device.js';\nimport { HIDOperations } from '../../../environments/web/usb-hid/HIDOperations.js';\nimport { ReportAbstractionLayer } from './ReportAbstractionLayer.js';\nimport { BootMode } from './reports.js';\n\nexport class SparkleController extends ReportAbstractionLayer {\n async bootloader() {\n await super.reboot(BootMode.BOOTSEL);\n }\n\n async connect() {\n const device = await getUnusedDevice();\n\n if (device) {\n await device.open();\n this.device = new HIDOperations(device);\n } else {\n throw new Error('No Device Found');\n }\n }\n \n async draw(matrix) {\n await super.drawMatrix(matrix);\n }\n\n async verifyFirmware() {\n try {\n const info = await super.info();\n return (\n info.display_height == HEIGHT &&\n info.display_width == WIDTH\n );\n } catch {\n return false;\n }\n }\n\n async version() {\n const info = await super.info();\n\n if (info.version_major != undefined \n && info.version_minor != undefined\n && (info.version_major > 0 || info.version_minor > 0)) {\n return {\n major: info.version_major,\n minor: info.version_minor\n }\n } else {\n // Sparkle <=1.1.1: Glitter version unavailable \n return { major: 1, minor: 0 };\n }\n }\n}\n","import { DefaultController } from './supported-firmware/FrameworkComputer/inputmodule-rs/DefaultController.js';\nimport { SigrootController } from './supported-firmware/sigroot/FW_LED_Matrix_Firmware/SigrootController.js';\nimport { SparkleController } from './supported-firmware/vddCore/sparkle-fw16/SparkleController.js';\n\nexport class HardwareControllerFactory {\n static async detectSerial() {\n const c1 = new DefaultController();\n const c2 = new SigrootController();\n\n await c1.connect();\n if (await c1.verifyFirmware()) {\n return c1;\n }\n \n await c2.connect()\n if (await c2.verifyFirmware()) {\n return c2;\n } \n \n return null;\n }\n\n static async detectHID() {\n const c1 = new SparkleController();\n\n await c1.connect();\n if (await c1.verifyFirmware()) {\n return c1;\n } \n \n return null;\n }\n}\n"],"names":["WIDTH","HEIGHT","VID_ARR","GAMMA","Object","freeze","filters","usbVendorId","usbProductId","PortSelectionCancelled","Error","constructor","super","this","name","date","Date","PortUnavailable","async","requestPort","navigator","serial","assign","pickedByUser","e","knownPorts","used","Set","unused","getOrFetchUnused","port","pop","getPorts","enqueueUnique","manualPort","add","ports","has","includes","push","requestPortForWorker","getUnusedPort","close","message","PortMutex","portOperations","lockName","Math","random","toString","deduper","Map","portOps","acquire","fn","trace","stack","enqueue","console","error","acquireIdempotent","key","info","set","execDedupedOp","locks","request","get","delete","PortOperations","rx","length","timeout","readable","locked","response","reader","getReader","timeoutHandle","setTimeout","cancel","value","done","read","clearTimeout","releaseLock","tx","buffer","writable","writer","getWriter","write","Uint8Array","Command","ANIMATE","BRIGHTNESS","BOOTLOADER","DRAW","DRAW_GREY_COL_BUFFER","GAME_CTRL","GAME_STATUS","PANIC","PATTERN","SLEEP","STAGE_GREY_COL","START_GAME","VERSION","Pattern","DISPLAY_LOTUS_HORIZONTAL","DISPLAY_LOTUS_VERTICAL","DISPLAY_PANIC","DOUBLE_GRADIENT","FULL_BRIGHTNESS","GRADIENT","PERCENTAGE","ZIG_ZAG","BitDepth","GRAY_8BIT","MONO_1BIT","CommandAbstractionLayer$1","portMutex","bootloader","p","brightness","draw","matrix","index","output","fill","r","c","drawGrayscale","buffers","Array","from","_","floor","i","asleep","sleep","wake","pattern","percent","min","max","round","version","ver","major","minor","patch","preRelease","scrolling","startScrolling","stopScrolling","DefaultController","CommandAbstractionLayer","connect","connected","open","baudRate","bitDepth","verifyFirmware","undefined","NOOP","ANIMATION_DIAMOND","ANIMATION_FIRE","ANIMATION_FIREPLACE","ANIMATION_GEAR","ANIMATION_RING","ANIMATION_STARTUP","ANIMATION_STARTUP_ONCE","DRAW_PWM","DRAW_PWM_BLOCKING","DRAW_SCALE","DRAW_SCALE_BLOCKING","FLUSH_CMD_QUEUE","TEST_PATTERN","SET_CONST_PWM","SET_CONST_SCALE","SET_PX_PWM","SET_PX_SCALE","IDENTITY_STRING","IDENTITY_STR_REGEX","identityString","ident","String","fromCharCode","setPixelPwm","setGlobalPwm","setMatrixPwm","concat","flat","map","v","setPixelAnalog","setGlobalAnalog","setMatrixAnalog","SigrootController","scaleInitialized","match","vendorId","productId","DeviceSelectionCancelled","requestDevice","knownDevices","device","systemDevices","hid","getDevices","manualDevices","devices","dev","reqestDeviceForWorker","HIDOperations","send","report","data","bytes","arr","len","val","pad","feature","sendFeatureReport","id","sendReport","reply","receiveFeatureReport","byteLength","exp","act","Reports","Commands","BootMode","ReportAbstractionLayer","infoRaw","sleep_pin","getUint8","dip1_pin","intb_pin","state_flags","id_reg","config_reg","global_brightness","display_width","display_height","timeout_ms","getUint32","version_major","version_minor","disableSleep","disableDeepSleep","disableSleepTimer","enableDeepSleep","enableSleepTimer","milliseconds","view","DataView","ArrayBuffer","setInt32","reboot","mode","drawMatrix","drawPixel","drawLine","r1","c1","r2","c2","SparkleController","getUnusedDevice","HardwareControllerFactory","detectSerial","detectHID"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).LedMatrixControllers={})}(this,function(e){"use strict";const t=12972,a=[50,172],r=Object.freeze([0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,4,4,4,4,4,4,5,5,5,5,6,6,6,6,6,7,7,7,7,8,8,8,9,9,9,10,10,10,11,11,11,12,12,12,13,13,14,14,14,15,15,16,16,17,17,17,18,18,19,19,20,20,21,22,22,23,23,24,24,25,26,26,27,27,28,29,29,30,31,32,32,33,34,34,35,36,37,38,38,39,40,41,42,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,66,67,68,69,70,71,73,74,75,76,78,79,80,82,83,84,86,87,88,90,91,93,94,96,97,99,100,102,103,105,106,108,110,111,113,115,116,118,120,121,123,125,127,128,130,132,134,136,138,140,141,143,145,147,149,151,153,155,157,159,161,164,166,168,170,172,174,177,179,181,183,186,188,190,193,195,197,200,202,205,207,210,212,215,217,220,222,225,228,230,233,236,238,241,244,247,249,252,255]),i=[{usbVendorId:t,usbProductId:32}];class n extends Error{constructor(){super("User cancelled port selection."),this.name=this.constructor.name,this.date=new Date}}class s extends Error{constructor(){super("Selected port already in use."),this.name=this.constructor.name,this.date=new Date}}async function o(){try{return navigator.serial.requestPort?await navigator.serial.requestPort({filters:i}):null}catch(e){switch(e.name){case"NotFoundError":throw new n;case"InvalidStateError":throw new s;case"SecurityError":return null;default:throw e}}}const c=new class{used=new Set;unused=[];async getOrFetchUnused(){let e=this.unused.pop();if(!e){const t=await navigator.serial.getPorts({filters:i});this.#e(t),e=this.unused.pop()}if(!e){const t=await o();this.#e([t]),e=this.unused.pop()}return e&&this.used.add(e),e}#e(e){if(e)for(const t of e)!t||this.used.has(t)||this.unused.includes(t)||this.unused.push(t)}};async function u(){return await c.getOrFetchUnused()}async function l(e){try{await e.close()}catch(e){if("InvalidStateError"!=e.name&&e.message.includes("The port is already closed"))throw e}}class d{constructor(e){this.#t=`port-mutex-${Math.random().toString()}`,this.#a=new Map,this.#r=e}async acquire(e){const t=new Error("created bad cb").stack;await this.#i(async()=>{try{await e(this.#r)}catch(e){console.error("Error occured in anonymous callback."),console.error("Original error:",e),console.error("--- This callback was created at ---\n",t)}})}async acquireIdempotent(e,t){const a=new Error("created bad cb").stack;this.#a.has(e)&&console.info(`"${e}" request coalesced.`),this.#a.set(e,async()=>{try{await t(this.#r)}catch(e){console.error("Error occured in anonymous callback."),console.error("Original error:",e),console.error("--- This callback was created at ---\n",a)}}),await this.#i(()=>this.#n(e))}async#i(e){return navigator.locks.request(this.#t,e)}async#n(e){if(this.#a.has(e)){const t=this.#a.get(e);this.#a.delete(e),await t()}}#t;#a;#r}class w{constructor(e){this.#s=e}async rx(e,t=3e3){if(null===this.#s)throw new Error("attempted RX before port initialization.");if(this.#s.readable.locked)throw new Error("attempted RX while port locked.");const a=[],r=this.#s.readable.getReader(),i=setTimeout(()=>r.cancel(),t);try{for(;a.length<e;){const{value:e,done:t}=await r.read();if(a.push(...e??[]),t||!e)break}}finally{clearTimeout(i),r.releaseLock()}return a}async tx(e){if(null===this.#s)throw new Error("attempted TX before port initialization.");if(this.#s.writable.locked)throw new Error("attempted TX while port locked.");const t=this.#s.writable.getWriter();try{await t.write(new Uint8Array(e))}finally{await t.close()}}#s}const h=Object.freeze({ANIMATE:4,BRIGHTNESS:0,BOOTLOADER:2,DRAW:6,DRAW_GREY_COL_BUFFER:8,GAME_CTRL:17,GAME_STATUS:18,PANIC:5,PATTERN:1,SLEEP:3,STAGE_GREY_COL:7,START_GAME:16,VERSION:32}),p=Object.freeze({GRAY_8BIT:"8-bit",MONO_1BIT:"1-bit"});let y=class{constructor(e=null){this.portMutex=e}async bootloader(){await this.portMutex.acquire(async e=>{await e.tx([...a,h.BOOTLOADER])})}async brightness(e){await this.portMutex.acquire(async t=>{await t.tx([...a,h.BRIGHTNESS,e])})}async draw(e){let t=0,r=new Uint8Array(39).fill(0);for(let a=0;a<34;a++)for(let i=0;i<9;i++)e[a][i]&&(r[t>>3]|=1<<t%8),t++;await this.portMutex.acquireIdempotent("drawMatrix",async e=>{await e.tx([...a,h.DRAW,...r])})}async drawGrayscale(e){const t=Array.from({length:9},(t,a)=>Array.from({length:34},(t,i)=>r[Math.floor(255*(e[i][a]??0))]));await this.portMutex.acquireIdempotent("drawMatrix",async e=>{for(let r=0;r<9;r++)await e.tx([...a,h.STAGE_GREY_COL,r,...t[r]]);await e.tx([...a,h.DRAW_GREY_COL_BUFFER])})}async asleep(){let e=!1;return await this.portMutex.acquire(async t=>{await t.tx([...a,h.SLEEP]),e=await t.rx(32),e=0!=e[0]}),e}async sleep(){await this.portMutex.acquire(async e=>{await e.tx([...a,h.SLEEP,1])})}async wake(){await this.portMutex.acquire(async e=>{await e.tx([...a,h.SLEEP])})}async pattern(e){await this.portMutex.acquireIdempotent("drawMatrix",async t=>{await t.tx([...a,h.PATTERN,e])})}async percent(e){await this.portMutex.acquireIdempotent("drawMatrix",async t=>{await t.tx([...a,h.PATTERN,Pattern.PERCENTAGE,e])})}async version(){let e={};return await this.portMutex.acquire(async t=>{await t.tx([...a,h.VERSION]);const r=await t.rx(32);e.major=r[0],e.minor=r[1]>>4,e.patch=15&r[1],e.preRelease=1==r[2]}),e}};class f extends y{async bootloader(){await super.bootloader()}async connect(){const e=await u();if(!e?.connected)throw new Error("No Port Found");await l(e),await e.open({baudRate:115200}),this.portMutex=new d(new w(e))}async draw(e){switch(this.bitDepth??p.MONO_1BIT){case p.GRAY_8BIT:await super.drawGrayscale(e);break;case p.MONO_1BIT:await super.draw(e);break;default:console.error(`Unsupported bitdepth: ${this.bitDepth}`)}}async verifyFirmware(){try{const e=await super.version();return e&&null!=e.major&&null!=e.minor&&null!=e.patch&&null!=e.preRelease}catch{return!1}}async version(){return super.version()}}const E=Object.freeze({NOOP:0,ANIMATION_DIAMOND:100,ANIMATION_FIRE:98,ANIMATION_FIREPLACE:102,ANIMATION_GEAR:103,ANIMATION_RING:114,ANIMATION_STARTUP:97,ANIMATION_STARTUP_ONCE:65,BOOTLOADER:101,DRAW_PWM:109,DRAW_PWM_BLOCKING:77,DRAW_SCALE:110,DRAW_SCALE_BLOCKING:78,FLUSH_CMD_QUEUE:99,TEST_PATTERN:116,SET_CONST_PWM:119,SET_CONST_SCALE:115,SET_PX_PWM:112,SET_PX_SCALE:113,IDENTITY_STRING:127}),_=/^Sig\sFW\sLED\sMatrix\sFW\sV(\d+)\.(\d+)$/;class x{constructor(e=null){this.portMutex=e}async bootloader(){await this.portMutex.acquire(async e=>{await e.tx([E.BOOTLOADER])})}async identityString(){let e=null;return await this.portMutex.acquire(async t=>{await t.tx([E.IDENTITY_STRING]),e=await t.rx(25)}),String.fromCharCode(...e)}async setPixelPwm(e,t,a){await this.portMutex.acquire(async r=>{await r.tx([E.SET_PX_PWM,t,e,a])})}async setGlobalPwm(e){await this.portMutex.acquire(async t=>{await t.tx([E.SET_CONST_PWM,e])})}async setMatrixPwm(e){await this.portMutex.acquireIdempotent("drawMatrix",async t=>{await t.tx([E.DRAW_PWM].concat(e.flat().map(e=>r[Math.floor(255*(e??0))])))})}async setPixelAnalog(e,t,a){await this.portMutex.acquire(async r=>{await r.tx([E.SET_PX_SCALE,t,e,a])})}async setGlobalAnalog(e){await this.portMutex.acquire(async t=>{await t.tx([E.SET_CONST_SCALE,e])})}async setMatrixAnalog(e){await this.portMutex.acquireIdempotent("drawMatrix",async t=>{await t.tx([E.DRAW_SCALE].concat(e.flat().map(e=>r[Math.floor(255*(e??0))])))})}}class m extends x{async bootloader(){await super.bootloader()}async connect(){const e=await u();e?.connected&&(await l(e),await e.open({baudRate:115200}),this.portMutex=new d(new w(e)))}async draw(e){if(this.#o)throw new Error("No Port Found");await super.setGlobalAnalog(32),this.#o=!0,await super.setMatrixPwm(e)}async verifyFirmware(){return null!=await this.version()}async version(){const e=(await super.identityString()).match(_);return e&&3==e.length?{major:e[1],minor:e[2]}:null}#o}const A=[{vendorId:t,productId:32}];class T extends Error{constructor(){super("User cancelled device selection."),this.name=this.constructor.name,this.date=new Date}}async function b(){try{return navigator.serial.requestPort?await navigator.serial.requestDevice({filters:A}):null}catch(e){switch(e.name){case"NotFoundError":throw new T;case"SecurityError":return null;default:throw e}}}const g=new class{used=new Set;unused=[];async getOrFetchUnused(){let e=this.unused.pop();if(!e){const t=await navigator.hid.getDevices({filters:A});this.#e(t),e=this.unused.pop()}if(!e){const t=await b();this.#e([t]),e=this.unused.pop()}return e&&this.used.add(e),e}#e(e){if(e)for(const t of e)!t||this.used.has(t)||this.unused.includes(t)||this.unused.push(t)}};async function M(){return await g.getOrFetchUnused()}class v{constructor(e){this.#c=e}async send(e,t){if(t.length<e.bytes)t=function(e,t,a=0){return e.concat(new Array(t-e.length).fill(a))}(t,e.bytes);else if(t.length>e.bytes)throw new Error("Unable to send report: too many bytes");const a=new Uint8Array(t).buffer;e.feature?await this.#c.sendFeatureReport(e.id,a):await this.#c.sendReport(e.id,a)}async request(e){let t=[];if(!e.feature)throw new Error("Invalid operation");if(t=await this.#c.receiveFeatureReport(e.id),t.byteLength!=e.bytes){const a=e.bytes,r=t.byteLength;console.error(`reply length=${r} (expected ${a})`)}return t}#c}const I={id:1,bytes:307,feature:!0},S={id:2,bytes:16,feature:!0},O={id:4,bytes:306,feature:!0},R=0,N=1,P=2,q=3,U=5,D=0;class C{constructor(e=null){this.device=e}async info(){const e=await this.device.request(I);return{sleep_pin:e.getUint8(1),dip1_pin:e.getUint8(2),intb_pin:e.getUint8(3),state_flags:e.getUint8(4),id_reg:e.getUint8(5),config_reg:e.getUint8(6),global_brightness:e.getUint8(7),display_width:e.getUint8(8),display_height:e.getUint8(9),timeout_ms:e.getUint32(10),version_major:e.getUint8(14),version_minor:e.getUint8(15)}}async wake(){await this.device.send(S,[N,!1])}async sleep(){await this.device.send(S,[N,!0])}async disableSleep(){await this.device.send(S,[q,255,255,255,255])}async disableDeepSleep(){await this.device.send(S,[P,1])}async disableSleepTimer(){await this.device.send(S,[q,0,0,0,0])}async enableDeepSleep(){await this.device.send(S,[P,0])}async enableSleepTimer(e){const t=new DataView(new ArrayBuffer(4));t.setInt32(0,e,!1),await this.device.send(S,[q,t.getUint8(0),t.getUint8(1),t.getUint8(2),t.getUint8(3)])}async reboot(e){await this.device.send(S,[R,e])}async drawMatrix(e){await this.device.send(O,e.flat().map(e=>r[Math.floor(255*(e??0))]))}async drawPixel(e,t,a){await this.device.send(S,[U,t,e,a])}async drawLine({r1:e,c1:t},{r2:a,c2:r},i){await this.device.send(S,[U,e,t,a,r,i])}device}class L extends C{async bootloader(){await super.reboot(D)}async connect(){const e=await M();if(!e)throw new Error("No Device Found");await e.open(),this.device=new v(e)}async draw(e){await super.drawMatrix(e)}async verifyFirmware(){try{const e=await super.info();return 34==e.display_height&&9==e.display_width}catch{return!1}}async version(){const e=await super.info();return null!=e.version_major&&null!=e.version_minor&&(e.version_major>0||e.version_minor>0)?{major:e.version_major,minor:e.version_minor}:{major:1,minor:0}}}e.DefaultController=f,e.DeviceSelectionCancelled=T,e.GAMMA=r,e.HEIGHT=34,e.HardwareControllerFactory=class{static async detectSerial(){const e=new f,t=new m;return await e.connect(),await e.verifyFirmware()?e:(await t.connect(),await t.verifyFirmware()?t:null)}static async detectHID(){const e=new L;return await e.connect(),await e.verifyFirmware()?e:null}},e.PID=32,e.PID_ARR=[0,32],e.PortSelectionCancelled=n,e.PortUnavailable=s,e.SigrootController=m,e.SparkleController=L,e.VID=t,e.VID_ARR=a,e.WIDTH=9,e.close=l,e.getUnusedDevice=M,e.getUnusedPort=u,e.reqestDeviceForWorker=async function(){await b()},e.requestPortForWorker=async function(){await o()}});
|
|
1
|
+
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self).LedMatrixControllers={})}(this,function(t){"use strict";const e=[50,172],a=Object.freeze([0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,4,4,4,4,4,4,5,5,5,5,6,6,6,6,6,7,7,7,7,8,8,8,9,9,9,10,10,10,11,11,11,12,12,12,13,13,14,14,14,15,15,16,16,17,17,17,18,18,19,19,20,20,21,22,22,23,23,24,24,25,26,26,27,27,28,29,29,30,31,32,32,33,34,34,35,36,37,38,38,39,40,41,42,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,66,67,68,69,70,71,73,74,75,76,78,79,80,82,83,84,86,87,88,90,91,93,94,96,97,99,100,102,103,105,106,108,110,111,113,115,116,118,120,121,123,125,127,128,130,132,134,136,138,140,141,143,145,147,149,151,153,155,157,159,161,164,166,168,170,172,174,177,179,181,183,186,188,190,193,195,197,200,202,205,207,210,212,215,217,220,222,225,228,230,233,236,238,241,244,247,249,252,255]),r=[{usbVendorId:12972,usbProductId:32}];class i extends Error{constructor(){super("User cancelled port selection."),this.name=this.constructor.name,this.date=new Date}}class n extends Error{constructor(){super("Selected port already in use."),this.name=this.constructor.name,this.date=new Date}}async function s(){try{return navigator.serial.requestPort?Object.assign(await navigator.serial.requestPort({filters:r}),{pickedByUser:!0}):null}catch(t){switch(t.name){case"NotFoundError":throw new i;case"InvalidStateError":throw new n;case"SecurityError":return null;default:throw t}}}const o=new class{used=new Set;unused=[];async getOrFetchUnused(){let t=this.unused.pop();if(!t){const e=await navigator.serial.getPorts({filters:r});this.#t(e),t=this.unused.pop()}if(!t){const e=await s();this.#t([e]),t=this.unused.pop()}return t&&this.used.add(t),t}#t(t){if(t)for(const e of t)!e||this.used.has(e)||this.unused.includes(e)||this.unused.push(e)}};async function c(){return await o.getOrFetchUnused()}async function u(t){try{await t.close()}catch(t){if("InvalidStateError"!=t.name&&t.message.includes("The port is already closed"))throw t}}class l{constructor(t){this.#e=`port-mutex-${Math.random().toString()}`,this.#a=new Map,this.#r=t}async acquire(t){const e=new Error("created bad cb").stack;await this.#i(async()=>{try{await t(this.#r)}catch(t){console.error("Error occured in anonymous callback."),console.error("Original error:",t),console.error("--- This callback was created at ---\n",e)}})}async acquireIdempotent(t,e){const a=new Error("created bad cb").stack;this.#a.has(t)&&console.info(`"${t}" request coalesced.`),this.#a.set(t,async()=>{try{await e(this.#r)}catch(t){console.error("Error occured in anonymous callback."),console.error("Original error:",t),console.error("--- This callback was created at ---\n",a)}}),await this.#i(()=>this.#n(t))}async#i(t){return navigator.locks.request(this.#e,t)}async#n(t){if(this.#a.has(t)){const e=this.#a.get(t);this.#a.delete(t),await e()}}#e;#a;#r}class d{constructor(t){this.#s=t}async rx(t,e=3e3){if(null===this.#s)throw new Error("attempted RX on uninitialized port.");if(null===this.#s.readable)throw new Error("attempted RX on closed port.");if(this.#s.readable.locked)throw new Error("attempted RX while port locked.");const a=[],r=this.#s.readable.getReader(),i=setTimeout(()=>r.cancel(),e);try{for(;a.length<t;){const{value:t,done:e}=await r.read();if(a.push(...t??[]),e||!t)break}}finally{clearTimeout(i),r.releaseLock()}return a}async tx(t){if(null===this.#s)throw new Error("attempted TX on uninitialized port.");if(null===this.#s.writable)throw new Error("attempted TX on closed port.");if(this.#s.writable.locked)throw new Error("attempted TX while port locked.");const e=this.#s.writable.getWriter();try{await e.write(new Uint8Array(t))}finally{await e.close()}}#s}const w=Object.freeze({ANIMATE:4,BRIGHTNESS:0,BOOTLOADER:2,DRAW:6,DRAW_GREY_COL_BUFFER:8,GAME_CTRL:17,GAME_STATUS:18,PANIC:5,PATTERN:1,SLEEP:3,STAGE_GREY_COL:7,START_GAME:16,VERSION:32}),h=Object.freeze({DISPLAY_LOTUS_HORIZONTAL:3,DISPLAY_LOTUS_VERTICAL:7,DISPLAY_PANIC:6,DOUBLE_GRADIENT:2,FULL_BRIGHTNESS:5,GRADIENT:1,PERCENTAGE:0,ZIG_ZAG:4}),p=Object.freeze({GRAY_8BIT:"8-bit",MONO_1BIT:"1-bit"});let y=class{constructor(t=null){this.portMutex=t}async bootloader(){await this.portMutex.acquire(async t=>{await t.tx([...e,w.BOOTLOADER])})}async brightness(t){await this.portMutex.acquire(async a=>{await a.tx([...e,w.BRIGHTNESS,t])})}async draw(t){let a=0,r=new Uint8Array(39).fill(0);for(let e=0;e<34;e++)for(let i=0;i<9;i++)t[e][i]&&(r[a>>3]|=1<<a%8),a++;await this.portMutex.acquireIdempotent("drawMatrix",async t=>{await t.tx([...e,w.DRAW,...r])})}async drawGrayscale(t){const r=Array.from({length:9},(e,r)=>Array.from({length:34},(e,i)=>a[Math.floor(255*(t[i][r]??0))]));await this.portMutex.acquireIdempotent("drawMatrix",async t=>{for(let a=0;a<9;a++)await t.tx([...e,w.STAGE_GREY_COL,a,...r[a]]);await t.tx([...e,w.DRAW_GREY_COL_BUFFER])})}async asleep(){let t=!1;return await this.portMutex.acquire(async a=>{await a.tx([...e,w.SLEEP]),t=await a.rx(32),t=0!=t[0]}),t}async sleep(){await this.portMutex.acquire(async t=>{await t.tx([...e,w.SLEEP,1])})}async wake(){await this.portMutex.acquire(async t=>{await t.tx([...e,w.SLEEP])})}async pattern(t){await this.portMutex.acquireIdempotent("drawMatrix",async a=>{await a.tx([...e,w.PATTERN,t])})}async percent(t){t=Math.min(t,100),t=Math.max(t,0),t=Math.round(t),await this.portMutex.acquireIdempotent("drawMatrix",async a=>{await a.tx([...e,w.PATTERN,h.PERCENTAGE,t])})}async version(){let t={};return await this.portMutex.acquire(async a=>{await a.tx([...e,w.VERSION]);const r=await a.rx(32);t.major=r[0],t.minor=r[1]>>4,t.patch=15&r[1],t.preRelease=1==r[2]}),t}async scrolling(){let t=!1;return await this.portMutex.acquire(async a=>{await a.tx([...e,w.ANIMATE]),t=await a.rx(32),t=0!=t[0]}),t}async startScrolling(){await this.portMutex.acquire(async t=>{await t.tx([...e,w.ANIMATE,1])})}async stopScrolling(){await this.portMutex.acquire(async t=>{await t.tx([...e,w.ANIMATE,0])})}};class f extends y{async bootloader(){await super.bootloader()}async connect(){const t=await c();if(!t?.connected)throw new Error("No Port Found");await u(t),await t.open({baudRate:115200}),this.portMutex=new l(new d(t))}async draw(t){switch(this.bitDepth??p.MONO_1BIT){case p.GRAY_8BIT:await super.drawGrayscale(t);break;case p.MONO_1BIT:await super.draw(t);break;default:console.error(`Unsupported bitdepth: ${this.bitDepth}`)}}async verifyFirmware(){try{const t=await super.version();return t&&null!=t.major&&null!=t.minor&&null!=t.patch&&null!=t.preRelease}catch{return!1}}async version(){return super.version()}}const E=Object.freeze({NOOP:0,ANIMATION_DIAMOND:100,ANIMATION_FIRE:98,ANIMATION_FIREPLACE:102,ANIMATION_GEAR:103,ANIMATION_RING:114,ANIMATION_STARTUP:97,ANIMATION_STARTUP_ONCE:65,BOOTLOADER:101,DRAW_PWM:109,DRAW_PWM_BLOCKING:77,DRAW_SCALE:110,DRAW_SCALE_BLOCKING:78,FLUSH_CMD_QUEUE:99,TEST_PATTERN:116,SET_CONST_PWM:119,SET_CONST_SCALE:115,SET_PX_PWM:112,SET_PX_SCALE:113,IDENTITY_STRING:127}),A=/^Sig\sFW\sLED\sMatrix\sFW\sV(\d+)\.(\d+)$/;class T{constructor(t=null){this.portMutex=t}async bootloader(){await this.portMutex.acquire(async t=>{await t.tx([E.BOOTLOADER])})}async identityString(){let t=null;return await this.portMutex.acquire(async e=>{await e.tx([E.IDENTITY_STRING]),t=await e.rx(25)}),String.fromCharCode(...t)}async setPixelPwm(t,e,a){await this.portMutex.acquire(async r=>{await r.tx([E.SET_PX_PWM,e,t,a])})}async setGlobalPwm(t){await this.portMutex.acquire(async e=>{await e.tx([E.SET_CONST_PWM,t])})}async setMatrixPwm(t){await this.portMutex.acquireIdempotent("drawMatrix",async e=>{await e.tx([E.DRAW_PWM].concat(t.flat().map(t=>a[Math.floor(255*(t??0))])))})}async setPixelAnalog(t,e,a){await this.portMutex.acquire(async r=>{await r.tx([E.SET_PX_SCALE,e,t,a])})}async setGlobalAnalog(t){await this.portMutex.acquire(async e=>{await e.tx([E.SET_CONST_SCALE,t])})}async setMatrixAnalog(t){await this.portMutex.acquireIdempotent("drawMatrix",async e=>{await e.tx([E.DRAW_SCALE].concat(t.flat().map(t=>a[Math.floor(255*(t??0))])))})}}class x extends T{async bootloader(){await super.bootloader()}async connect(){const t=await c();t?.connected&&(await u(t),await t.open({baudRate:115200}),this.portMutex=new l(new d(t)))}async draw(t){if(this.#o)throw new Error("No Port Found");await super.setGlobalAnalog(32),this.#o=!0,await super.setMatrixPwm(t)}async verifyFirmware(){return null!=await this.version()}async version(){const t=(await super.identityString()).match(A);return t&&3==t.length?{major:t[1],minor:t[2]}:null}#o}const _=[{vendorId:12972,productId:32}];class m extends Error{constructor(){super("User cancelled device selection."),this.name=this.constructor.name,this.date=new Date}}async function M(){try{return navigator.serial.requestPort?await navigator.serial.requestDevice({filters:_}):null}catch(t){switch(t.name){case"NotFoundError":throw new m;case"SecurityError":return null;default:throw t}}}const I=new class{used=new Set;unused=[];async getOrFetchUnused(){let t=this.unused.pop();if(!t){const e=await navigator.hid.getDevices({filters:_});this.#t(e),t=this.unused.pop()}if(!t){const e=await M();this.#t([e]),t=this.unused.pop()}return t&&this.used.add(t),t}#t(t){if(t)for(const e of t)!e||this.used.has(e)||this.unused.includes(e)||this.unused.push(e)}};class S{constructor(t){this.#c=t}async send(t,e){if(e.length<t.bytes)e=function(t,e,a=0){return t.concat(new Array(e-t.length).fill(a))}(e,t.bytes);else if(e.length>t.bytes)throw new Error("Unable to send report: too many bytes");const a=new Uint8Array(e).buffer;t.feature?await this.#c.sendFeatureReport(t.id,a):await this.#c.sendReport(t.id,a)}async request(t){let e=[];if(!t.feature)throw new Error("Invalid operation");if(e=await this.#c.receiveFeatureReport(t.id),e.byteLength!=t.bytes){const a=t.bytes,r=e.byteLength;console.error(`reply length=${r} (expected ${a})`)}return e}#c}const b={id:1,bytes:307,feature:!0},g={id:2,bytes:16,feature:!0},O={id:4,bytes:306,feature:!0},v=0,N=1,R=2,q=3,P=5,U=0;class D{constructor(t=null){this.device=t}async info(){const t=await this.device.request(b);return{sleep_pin:t.getUint8(1),dip1_pin:t.getUint8(2),intb_pin:t.getUint8(3),state_flags:t.getUint8(4),id_reg:t.getUint8(5),config_reg:t.getUint8(6),global_brightness:t.getUint8(7),display_width:t.getUint8(8),display_height:t.getUint8(9),timeout_ms:t.getUint32(10),version_major:t.getUint8(14),version_minor:t.getUint8(15)}}async wake(){await this.device.send(g,[N,!1])}async sleep(){await this.device.send(g,[N,!0])}async disableSleep(){await this.device.send(g,[q,255,255,255,255])}async disableDeepSleep(){await this.device.send(g,[R,1])}async disableSleepTimer(){await this.device.send(g,[q,0,0,0,0])}async enableDeepSleep(){await this.device.send(g,[R,0])}async enableSleepTimer(t){const e=new DataView(new ArrayBuffer(4));e.setInt32(0,t,!1),await this.device.send(g,[q,e.getUint8(0),e.getUint8(1),e.getUint8(2),e.getUint8(3)])}async reboot(t){await this.device.send(g,[v,t])}async drawMatrix(t){await this.device.send(O,t.flat().map(t=>a[Math.floor(255*(t??0))]))}async drawPixel(t,e,a){await this.device.send(g,[P,e,t,a])}async drawLine({r1:t,c1:e},{r2:a,c2:r},i){await this.device.send(g,[P,t,e,a,r,i])}device}class L extends D{async bootloader(){await super.reboot(U)}async connect(){const t=await async function(){return await I.getOrFetchUnused()}();if(!t)throw new Error("No Device Found");await t.open(),this.device=new S(t)}async draw(t){await super.drawMatrix(t)}async verifyFirmware(){try{const t=await super.info();return 34==t.display_height&&9==t.display_width}catch{return!1}}async version(){const t=await super.info();return null!=t.version_major&&null!=t.version_minor&&(t.version_major>0||t.version_minor>0)?{major:t.version_major,minor:t.version_minor}:{major:1,minor:0}}}t.BitDepth=p,t.DefaultController=f,t.DeviceSelectionCancelled=m,t.HEIGHT=34,t.HardwareControllerFactory=class{static async detectSerial(){const t=new f,e=new x;return await t.connect(),await t.verifyFirmware()?t:(await e.connect(),await e.verifyFirmware()?e:null)}static async detectHID(){const t=new L;return await t.connect(),await t.verifyFirmware()?t:null}},t.Pattern=h,t.PortSelectionCancelled=i,t.PortUnavailable=n,t.SigrootController=x,t.SparkleController=L,t.WIDTH=9,t.reqestDeviceForWorker=async function(){await M()},t.requestPortForWorker=async function(){await s()}});
|
|
2
2
|
//# sourceMappingURL=led-matrix-controllers.umd.min.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"led-matrix-controllers.umd.min.js","sources":["../src/hardware-constants.js","../src/web-serial/port.js","../src/web-serial/PortMutex.js","../src/web-serial/PortOperations.js","../src/supported-firmware/FrameworkComputer/inputmodule-rs/commands.js","../src/supported-firmware/FrameworkComputer/inputmodule-rs/CommandAbstractionLayer.js","../src/supported-firmware/FrameworkComputer/inputmodule-rs/DefaultController.js","../src/supported-firmware/sigroot/FW_LED_Matrix_Firmware/commands.js","../src/supported-firmware/sigroot/FW_LED_Matrix_Firmware/CommandAbstractionLayer.js","../src/supported-firmware/sigroot/FW_LED_Matrix_Firmware/SigrootController.js","../src/web-hid/device.js","../src/web-hid/HIDOperations.js","../src/web-hid/util.js","../src/supported-firmware/vddCore/sparkle-fw16/reports.js","../src/supported-firmware/vddCore/sparkle-fw16/ReportAbstractionLayer.js","../src/supported-firmware/vddCore/sparkle-fw16/SparkleController.js","../src/HardwareControllerFactory.js"],"sourcesContent":["export const WIDTH = 9;\nexport const HEIGHT = 34;\nexport const VID = 0x32AC;\nexport const VID_ARR = [0x32, 0xAC];\nexport const PID = 0x0020;\nexport const PID_ARR = [0x00, 0x20];\n\n// For PWM dimming (not for analog dimming/constant-current reduction!)\nexport const GAMMA = Object.freeze([\n 0, 0, 0, 0, 0, 0, 0, 1, \n 1, 1, 1, 1, 1, 1, 1, 1, \n 1, 1, 1, 1, 1, 1, 1, 1, \n 1, 1, 1, 1, 1, 1, 1, 1, \n 1, 1, 1, 2, 2, 2, 2, 2, \n 2, 2, 2, 2, 3, 3, 3, 3, \n 3, 3, 3, 4, 4, 4, 4, 4, \n 4, 5, 5, 5, 5, 6, 6, 6, \n 6, 6, 7, 7, 7, 7, 8, 8, \n 8, 9, 9, 9, 10, 10, 10, 11, \n 11, 11, 12, 12, 12, 13, 13, 14, \n 14, 14, 15, 15, 16, 16, 17, 17, \n 17, 18, 18, 19, 19, 20, 20, 21, \n 22, 22, 23, 23, 24, 24, 25, 26, \n 26, 27, 27, 28, 29, 29, 30, 31, \n 32, 32, 33, 34, 34, 35, 36, 37, \n 38, 38, 39, 40, 41, 42, 42, 43, \n 44, 45, 46, 47, 48, 49, 50, 51, \n 52, 53, 54, 55, 56, 57, 58, 59, \n 60, 61, 62, 63, 64, 66, 67, 68, \n 69, 70, 71, 73, 74, 75, 76, 78, \n 79, 80, 82, 83, 84, 86, 87, 88, \n 90, 91, 93, 94, 96, 97, 99, 100, \n 102, 103, 105, 106, 108, 110, 111, 113, \n 115, 116, 118, 120, 121, 123, 125, 127, \n 128, 130, 132, 134, 136, 138, 140, 141, \n 143, 145, 147, 149, 151, 153, 155, 157, \n 159, 161, 164, 166, 168, 170, 172, 174, \n 177, 179, 181, 183, 186, 188, 190, 193, \n 195, 197, 200, 202, 205, 207, 210, 212, \n 215, 217, 220, 222, 225, 228, 230, 233, \n 236, 238, 241, 244, 247, 249, 252, 255\n]);\n","import { PID, VID } from '../hardware-constants.js';\n\nconst filters = [{ usbVendorId: VID, usbProductId: PID }];\n\nexport class PortSelectionCancelled extends Error {\n constructor() {\n super('User cancelled port selection.');\n this.name = this.constructor.name;\n this.date = new Date();\n }\n}\n\nexport class PortUnavailable extends Error {\n constructor() {\n super('Selected port already in use.');\n this.name = this.constructor.name;\n this.date = new Date();\n }\n}\n\nasync function requestPort() {\n try {\n if (navigator.serial.requestPort) {\n return await navigator.serial.requestPort({ filters });\n } else {\n return null; // Web Worker\n }\n } catch (e) {\n switch (e.name) {\n case ('NotFoundError'):\n throw new PortSelectionCancelled();\n case ('InvalidStateError'):\n throw new PortUnavailable();\n case ('SecurityError'): // No user gesture\n return null;\n default:\n throw e;\n }\n }\n}\n\nclass KnownPorts {\n used = new Set();\n unused = [];\n\n async getOrFetchUnused() {\n let port = this.unused.pop();\n \n if (!port) {\n const systemPorts = await navigator.serial.getPorts({ filters });\n this.#enqueueUnique(systemPorts);\n port = this.unused.pop();\n }\n\n if (!port) {\n const manualPort = await requestPort();\n this.#enqueueUnique([manualPort]);\n port = this.unused.pop();\n }\n\n if (port) {\n this.used.add(port);\n }\n \n return port;\n }\n\n #enqueueUnique(ports) {\n if (ports) {\n for (const port of ports) {\n if (port && !this.used.has(port) && !this.unused.includes(port)) {\n this.unused.push(port);\n }\n }\n }\n }\n}\n\nconst knownPorts = new KnownPorts();\n\n/**\n * Adds user-selected port to permitted ports. Only for use outside of Web \n * Worker to establish permission for use within Web Worker.\n * @returns {null}\n */\nexport async function requestPortForWorker() {\n const _ = await requestPort();\n}\n\n/**\n * Never returns the same port twice. \n * @returns {(SerialPort|null)}\n */\nexport async function getUnusedPort() {\n return await knownPorts.getOrFetchUnused();\n}\n\n/**\n * Close port without throwing if already closed.\n * @param {SerialPort} port \n */\nexport async function close(port) {\n try {\n await port.close();\n } catch(e) {\n if (e.name != 'InvalidStateError') {\n if (e.message.includes('The port is already closed')) {\n throw e;\n }\n }\n }\n}\n","export class PortMutex {\n constructor(portOperations) {\n this.#lockName = `port-mutex-${Math.random().toString()}`;\n this.#deduper = new Map();\n this.#portOps = portOperations;\n }\n\n async acquire(fn) {\n const trace = new Error('created bad cb').stack;\n\n await this.#enqueue(async () => {\n try {\n await fn(this.#portOps);\n } catch (e) {\n console.error('Error occured in anonymous callback.');\n console.error('Original error:', e);\n console.error('--- This callback was created at ---\\n', trace);\n }\n });\n }\n\n async acquireIdempotent(key, fn) {\n const trace = new Error('created bad cb').stack;\n\n if (this.#deduper.has(key)) {\n console.info(`\"${key}\" request coalesced.`);\n }\n\n this.#deduper.set(key, async () => {\n try {\n await fn(this.#portOps);\n } catch (e) {\n console.error('Error occured in anonymous callback.');\n console.error('Original error:', e);\n console.error('--- This callback was created at ---\\n', trace);\n }\n });\n\n await this.#enqueue(() => this.#execDedupedOp(key));\n }\n\n async #enqueue(fn) {\n // `navigator.locks` maintains queue and provides mutual exclusion.\n return navigator.locks.request(this.#lockName, fn);\n }\n\n async #execDedupedOp(key) {\n if (this.#deduper.has(key)) {\n const fn = this.#deduper.get(key);\n this.#deduper.delete(key);\n await fn();\n }\n }\n\n #lockName;\n #deduper;\n #portOps;\n}\n","export class PortOperations {\n constructor(port) {\n this.#port = port;\n }\n\n async rx(length, timeout=3000) {\n if (this.#port === null) {\n throw new Error('attempted RX before port initialization.');\n }\n\n /*\n * ReadableStream's built-in locking mechanism cannot be awaited or otherwise\n * asynchronously acquired. A PortMutex must be used.\n */\n if (this.#port.readable.locked) {\n throw new Error('attempted RX while port locked.');\n }\n\n const response = [];\n const reader = this.#port.readable.getReader();\n const timeoutHandle = setTimeout(() => reader.cancel(), timeout);\n\n try {\n // Response may be divided across multiple reads\n while (response.length < length) {\n const { value, done } = await reader.read();\n response.push(...(value ?? []));\n if (done || !value) break;\n }\n } finally {\n clearTimeout(timeoutHandle);\n reader.releaseLock();\n }\n\n return response;\n }\n\n async tx(buffer) {\n if (this.#port === null) {\n throw new Error('attempted TX before port initialization.');\n }\n \n /*\n * WritableStream's built-in locking mechanism cannot be awaited or otherwise\n * asynchronously acquired. A PortMutex must be used.\n */\n if (this.#port.writable.locked) {\n throw new Error('attempted TX while port locked.');\n }\n\n const writer = this.#port.writable.getWriter();\n\n try {\n await writer.write(new Uint8Array(buffer));\n } finally {\n /* \n * The writer must be completely torn down between every single write.\n * Many parsers can't handle delayed flushing and write coalescing.\n * Command sequences will fail if `releaseLock()` is used here.\n */\n await writer.close();\n }\n }\n\n #port;\n}\n","// All replies to all commands are 32 bytes\nexport const RX_PACKET_SZ = 32;\n\nexport const Command = Object.freeze({\n ANIMATE: 0x04,\n BRIGHTNESS: 0x00,\n BOOTLOADER: 0x02,\n DRAW: 0x06,\n DRAW_GREY_COL_BUFFER: 0x08,\n GAME_CTRL: 0x11,\n GAME_STATUS: 0x12,\n PANIC: 0x05,\n PATTERN: 0x01,\n SLEEP: 0x03,\n STAGE_GREY_COL: 0x07,\n START_GAME: 0x10,\n VERSION: 0x20,\n});\n\n// Used with Command.PATTERN\nexport const Pattern = Object.freeze({\n DISPLAY_LOTUS_HORIZONTAL: 0x03,\n DISPLAY_LOTUS_VERTICAL: 0x07,\n DISPLAY_PANIC: 0x06,\n DOUBLE_GRADIENT: 0x02,\n FULL_BRIGHTNESS: 0x05,\n GRADIENT: 0x01,\n PERCENTAGE: 0x00,\n ZIG_ZAG: 0x04,\n});\n\n// DRAW or DRAW_GREY_COL_BUFFER\nexport const BitDepth = Object.freeze({\n GRAY_8BIT: '8-bit',\n MONO_1BIT: '1-bit',\n})\n","import { GAMMA, HEIGHT, VID_ARR, WIDTH } from '../../../hardware-constants.js';\nimport { Command, RX_PACKET_SZ } from './commands.js';\n\nexport class CommandAbstractionLayer {\n constructor(portMutex = null) {\n this.portMutex = portMutex;\n }\n\n async bootloader() {\n await this.portMutex.acquire(async p => {\n await p.tx([...VID_ARR, Command.BOOTLOADER]);\n });\n }\n\n async brightness(brightness) {\n await this.portMutex.acquire(async p => {\n await p.tx([...VID_ARR, Command.BRIGHTNESS, brightness]);\n });\n }\n\n async draw(matrix) {\n let index = 0;\n let output = new Uint8Array(39).fill(0);\n\n // Pack cells into bits\n for (let r = 0; r < HEIGHT; r++) {\n for (let c = 0; c < WIDTH; c++) {\n if (matrix[r][c]) {\n output[index >> 3] |= 1 << index % 8;\n }\n index++;\n }\n }\n\n await this.portMutex.acquireIdempotent(\n 'drawMatrix', \n async p => {\n await p.tx([...VID_ARR, Command.DRAW, ...output]);\n }\n );\n }\n\n async drawGrayscale(matrix) {\n // Transpose & Gamma Correction\n const buffers = Array.from(\n { length: WIDTH }, \n (_, c) => Array.from(\n { length: HEIGHT }, \n (_, r) => GAMMA[Math.floor((matrix[r][c] ?? 0) * 255)]\n )\n );\n\n // Only execute the most recent call \n await this.portMutex.acquireIdempotent(\n 'drawMatrix', \n async p => {\n for (let i = 0; i < WIDTH; i++) {\n await p.tx([...VID_ARR, Command.STAGE_GREY_COL, i, ...buffers[i]]);\n }\n await p.tx([...VID_ARR, Command.DRAW_GREY_COL_BUFFER]);\n }\n );\n }\n\n async asleep() {\n let asleep = false;\n\n await this.portMutex.acquire(async p => {\n await p.tx([...VID_ARR, Command.SLEEP]);\n asleep = await p.rx(RX_PACKET_SZ);\n asleep = asleep[0] != 0x00;\n });\n\n return asleep;\n }\n\n async sleep() {\n await this.portMutex.acquire(async p => {\n await p.tx([...VID_ARR, Command.SLEEP, 0x01]);\n });\n }\n\n async wake() {\n await this.portMutex.acquire(async p => {\n await p.tx([...VID_ARR, Command.SLEEP]);\n });\n }\n\n async pattern(pattern) {\n await this.portMutex.acquireIdempotent(\n 'drawMatrix',\n async p => {\n await p.tx([...VID_ARR, Command.PATTERN, pattern]);\n }\n );\n }\n\n async percent(percent) {\n await this.portMutex.acquireIdempotent(\n 'drawMatrix',\n async p => {\n await p.tx([...VID_ARR, Command.PATTERN, Pattern.PERCENTAGE, percent]);\n }\n );\n }\n\n async version() {\n let ver = {};\n\n await this.portMutex.acquire(async p => {\n await p.tx([...VID_ARR, Command.VERSION]);\n const response = await p.rx(RX_PACKET_SZ);\n\n // MMMMMMMM mmmmPPPP 0000000p\n ver.major = response[0];\n ver.minor = response[1] >> 4;\n ver.patch = response[1] & 0x0F;\n ver.preRelease = response[2] == 1;\n });\n\n return ver;\n }\n}\n","import { close, getUnusedPort } from '../../../web-serial/port.js';\nimport { PortMutex } from '../../../web-serial/PortMutex.js';\nimport { PortOperations } from '../../../web-serial/PortOperations.js';\nimport { CommandAbstractionLayer } from './CommandAbstractionLayer.js';\nimport { BitDepth } from './commands.js';\n\nexport class DefaultController extends CommandAbstractionLayer {\n async bootloader() {\n await super.bootloader();\n }\n\n async connect() {\n const port = await getUnusedPort();\n\n if (port?.connected) {\n await close(port);\n await port.open({ baudRate: 115200 });\n this.portMutex = new PortMutex(new PortOperations(port));\n } else {\n throw new Error('No Port Found');\n }\n }\n\n async draw(matrix) {\n switch (this.bitDepth ?? BitDepth.MONO_1BIT) {\n\n case (BitDepth.GRAY_8BIT):\n await super.drawGrayscale(matrix);\n break;\n\n case (BitDepth.MONO_1BIT):\n await super.draw(matrix);\n break;\n\n default:\n console.error(`Unsupported bitdepth: ${this.bitDepth}`);\n }\n }\n\n async verifyFirmware() {\n try {\n const version = await super.version();\n\n return version\n && version.major != undefined\n && version.minor != undefined\n && version.patch != undefined\n && version.preRelease != undefined;\n \n } catch {\n return false;\n }\n }\n\n async version() {\n return super.version();\n }\n}\n","export const Command = Object.freeze({\n /* 000 */ NOOP: 0x00,\n /* 'd' */ ANIMATION_DIAMOND: 0x64,\n /* 'b' */ ANIMATION_FIRE: 0x62,\n /* 'f' */ ANIMATION_FIREPLACE: 0x66,\n /* 'g' */ ANIMATION_GEAR: 0x67,\n /* 'r' */ ANIMATION_RING: 0x72,\n /* 'a' */ ANIMATION_STARTUP: 0x61,\n /* 'A' */ ANIMATION_STARTUP_ONCE: 0x41,\n /* 'e' */ BOOTLOADER: 0x65,\n /* 'm' */ DRAW_PWM: 0x6D,\n /* 'M' */ DRAW_PWM_BLOCKING: 0x4D,\n /* 'n' */ DRAW_SCALE: 0x6E,\n /* 'N' */ DRAW_SCALE_BLOCKING: 0x4E,\n /* 'c' */ FLUSH_CMD_QUEUE: 0x63,\n /* 't' */ TEST_PATTERN: 0x74,\n /* 'w' */ SET_CONST_PWM: 0x77,\n /* 's' */ SET_CONST_SCALE: 0x73,\n /* 'p' */ SET_PX_PWM: 0x70,\n /* 'q' */ SET_PX_SCALE: 0x71,\n /* 127 */ IDENTITY_STRING: 0x7F,\n});\n\nexport const IDENTITY_STR_LEN = 25;\n\nexport const IDENTITY_STR_REGEX = /^Sig\\sFW\\sLED\\sMatrix\\sFW\\sV(\\d+)\\.(\\d+)$/;\n","import { GAMMA } from '../../../hardware-constants.js';\nimport { Command, IDENTITY_STR_LEN } from './commands.js';\n\nexport class CommandAbstractionLayer {\n constructor(portMutex = null) {\n this.portMutex = portMutex;\n }\n\n async bootloader() {\n await this.portMutex.acquire(async p => {\n await p.tx([Command.BOOTLOADER]);\n });\n }\n\n async identityString() {\n let ident = null;\n\n await this.portMutex.acquire(async p => {\n await p.tx([Command.IDENTITY_STRING]);\n ident = await p.rx(IDENTITY_STR_LEN);\n });\n\n return String.fromCharCode(...ident);\n }\n\n async setPixelPwm(r, c, brightness) {\n await this.portMutex.acquire(\n async p => {\n await p.tx([Command.SET_PX_PWM, c, r, brightness]);\n }\n );\n }\n\n async setGlobalPwm(brightness) {\n await this.portMutex.acquire(\n async p => {\n await p.tx([Command.SET_CONST_PWM, brightness]);\n }\n );\n }\n\n async setMatrixPwm(matrix) {\n // Only execute the most recent call \n await this.portMutex.acquireIdempotent(\n 'drawMatrix', \n async p => {\n await p.tx(\n [Command.DRAW_PWM].concat(\n matrix.flat().map(v => \n GAMMA[Math.floor((v ?? 0) * 255)]\n )\n )\n );\n }\n );\n }\n\n async setPixelAnalog(r, c, brightness) {\n await this.portMutex.acquire(\n async p => {\n await p.tx([Command.SET_PX_SCALE, c, r, brightness]);\n }\n );\n }\n\n async setGlobalAnalog(brightness) {\n await this.portMutex.acquire(\n async p => {\n await p.tx([Command.SET_CONST_SCALE, brightness]);\n }\n );\n }\n\n async setMatrixAnalog(matrix) {\n // Only execute the most recent call \n await this.portMutex.acquireIdempotent(\n 'drawMatrix', \n async p => {\n await p.tx(\n [Command.DRAW_SCALE].concat(\n matrix.flat().map(v => \n GAMMA[Math.floor((v ?? 0) * 255)]\n )\n )\n );\n }\n );\n }\n}\n","import { close, getUnusedPort } from '../../../web-serial/port.js';\nimport { PortMutex } from '../../../web-serial/PortMutex.js';\nimport { PortOperations } from '../../../web-serial/PortOperations.js';\nimport { CommandAbstractionLayer } from './CommandAbstractionLayer.js';\nimport { IDENTITY_STR_REGEX } from './commands.js';\n\nexport class SigrootController extends CommandAbstractionLayer {\n async bootloader() {\n await super.bootloader();\n }\n\n async connect() {\n const port = await getUnusedPort();\n\n if (port?.connected) {\n await close(port);\n await port.open({ baudRate: 115200 });\n this.portMutex = new PortMutex(new PortOperations(port));\n }\n }\n\n async draw(matrix) {\n if (!this.#scaleInitialized) {\n await super.setGlobalAnalog(0x20);\n this.#scaleInitialized = true;\n } else {\n throw new Error('No Port Found');\n }\n\n await super.setMatrixPwm(matrix);\n }\n\n async verifyFirmware() { \n return await this.version() != null;\n }\n\n async version() {\n const ident = await super.identityString();\n const match = ident.match(IDENTITY_STR_REGEX);\n\n if (match && match.length == 3) {\n return {\n major: match[1],\n minor: match[2]\n }\n } else {\n return null;\n }\n }\n\n #scaleInitialized;\n}\n","import { PID, VID } from '../hardware-constants.js';\n\nconst filters = [{ vendorId: VID, productId: PID }];\n\nexport class DeviceSelectionCancelled extends Error {\n constructor() {\n super('User cancelled device selection.');\n this.name = this.constructor.name;\n this.date = new Date();\n }\n}\n\nasync function requestDevice() {\n try {\n if (navigator.serial.requestPort) {\n return await navigator.serial.requestDevice({ filters });\n } else {\n return null; // Web Worker\n }\n } catch (e) {\n switch (e.name) {\n case ('NotFoundError'):\n throw new DeviceSelectionCancelled();\n case ('SecurityError'): // No user gesture\n return null;\n default:\n throw e;\n }\n }\n}\n\nclass KnownDevices {\n used = new Set();\n unused = [];\n\n async getOrFetchUnused() {\n let device = this.unused.pop();\n\n if (!device) {\n const systemDevices = await navigator.hid.getDevices({ filters });\n this.#enqueueUnique(systemDevices);\n device = this.unused.pop();\n }\n\n if (!device) {\n const manualDevices = await requestDevice();\n this.#enqueueUnique([manualDevices]);\n device = this.unused.pop();\n }\n\n if (device) {\n this.used.add(device);\n }\n\n return device;\n }\n\n #enqueueUnique(devices) {\n if (devices) {\n for (const dev of devices) {\n if (dev && !this.used.has(dev) && !this.unused.includes(dev)) {\n this.unused.push(dev);\n }\n }\n }\n }\n}\n\nconst knownDevices = new KnownDevices();\n\n/**\n * Adds user-selected device to permitted device. Only for use outside of Web \n * Worker to establish permission for use within Web Worker.\n * @returns {null}\n */\nexport async function reqestDeviceForWorker() {\n const _ = await requestDevice();\n}\n\n/**\n * Never returns the same device twice. \n * @returns {(HIDDevice|null)}\n */\nexport async function getUnusedDevice() {\n return await knownDevices.getOrFetchUnused();\n}\n","import { pad } from './util.js';\n\nexport class HIDOperations {\n constructor(device) {\n this.#device = device;\n }\n\n async send(report, data) {\n if (data.length < report.bytes) {\n data = pad(data, report.bytes);\n } else if (data.length > report.bytes) {\n throw new Error('Unable to send report: too many bytes');\n }\n\n const buffer = new Uint8Array(data).buffer;\n\n if (report.feature) {\n await this.#device.sendFeatureReport(report.id, buffer);\n } else {\n await this.#device.sendReport(report.id, buffer);\n }\n }\n\n async request(report) {\n let reply = [];\n\n if (report.feature) {\n reply = await this.#device.receiveFeatureReport(report.id);\n } else {\n /* \n * HID input reports are used for unprompted data.\n * See WebHID `HIDInputReportEvent`\n */\n throw new Error('Invalid operation');\n }\n\n if (reply.byteLength != report.bytes) {\n const exp = report.bytes;\n const act = reply.byteLength;\n console.error(`reply length=${act} (expected ${exp})`);\n }\n\n return reply;\n }\n\n #device;\n}\n","export function pad(arr, len, val=0x00) {\n return arr.concat(new Array(len - arr.length).fill(val));\n}\n","export const Reports = {\n GLITTER_DEVICE_INFO: {\n id: 0x01,\n bytes: 307,\n feature: true,\n },\n GLITTER_BASIC_CMD: {\n id: 0x02,\n bytes: 16,\n feature: true,\n },\n GLITTER_GRID_PWM_CNTL: {\n id: 0x03,\n bytes: 306,\n feature: true,\n },\n GLITTER_GRID_PWM_CNTL: {\n id: 0x04,\n bytes: 306,\n feature: true,\n }\n}\n\nexport const Commands = {\n GLITTER_CMD_REBOOT: 0x00,\n GLITTER_CMD_SLEEP: 0x01,\n GLITTER_CMD_WAKE_ON_COMMAND: 0x02,\n GLITTER_CMD_SET_SLEEP_TIMEOUT: 0x03,\n GLITTER_CMD_SET_GLOBAL_BRIGHTNESS: 0x04,\n GLITTER_CMD_DRAW_PIXEL: 0x05,\n GLITTER_CMD_DRAW_LINE: 0x06\n}\n\nexport const BootMode = {\n BOOTSEL: 0x00,\n NORMAL: 0x01,\n}\n","import { GAMMA } from '../../../hardware-constants.js';\nimport { Commands, Reports } from './reports.js';\n\nexport class ReportAbstractionLayer {\n constructor(device = null) {\n this.device = device;\n }\n\n async info() {\n const infoRaw = await this.device.request(Reports.GLITTER_DEVICE_INFO);\n\n return {\n sleep_pin: infoRaw.getUint8(1),\n dip1_pin: infoRaw.getUint8(2),\n intb_pin: infoRaw.getUint8(3),\n state_flags: infoRaw.getUint8(4),\n id_reg: infoRaw.getUint8(5),\n config_reg: infoRaw.getUint8(6),\n global_brightness: infoRaw.getUint8(7),\n display_width: infoRaw.getUint8(8),\n display_height: infoRaw.getUint8(9),\n timeout_ms: infoRaw.getUint32(10),\n version_major: infoRaw.getUint8(14),\n version_minor: infoRaw.getUint8(15),\n };\n }\n\n async wake() {\n await this.device.send(\n Reports.GLITTER_BASIC_CMD,\n [Commands.GLITTER_CMD_SLEEP, false]\n );\n }\n\n async sleep() {\n await this.device.send(\n Reports.GLITTER_BASIC_CMD,\n [Commands.GLITTER_CMD_SLEEP, true]\n );\n }\n\n async disableSleep() {\n await this.device.send(\n Reports.GLITTER_BASIC_CMD, \n [Commands.GLITTER_CMD_SET_SLEEP_TIMEOUT, 0xff, 0xff, 0xff, 0xff]\n );\n }\n\n async disableDeepSleep() {\n await this.device.send(\n Reports.GLITTER_BASIC_CMD, \n [Commands.GLITTER_CMD_WAKE_ON_COMMAND, 0x01]\n );\n }\n\n async disableSleepTimer() {\n await this.device.send(\n Reports.GLITTER_BASIC_CMD, \n [Commands.GLITTER_CMD_SET_SLEEP_TIMEOUT, 0x00, 0x00, 0x00, 0x00]\n );\n }\n \n async enableDeepSleep() {\n await this.device.send(\n Reports.GLITTER_BASIC_CMD, \n [Commands.GLITTER_CMD_WAKE_ON_COMMAND, 0x00]\n );\n }\n\n async enableSleepTimer(milliseconds) {\n const view = new DataView(new ArrayBuffer(4));\n const littleEndian = false;\n view.setInt32(0, milliseconds, littleEndian);\n await this.device.send(\n Reports.GLITTER_BASIC_CMD, \n [\n Commands.GLITTER_CMD_SET_SLEEP_TIMEOUT, \n view.getUint8(0), \n view.getUint8(1), \n view.getUint8(2), \n view.getUint8(3),\n ]\n );\n }\n\n async reboot(mode) {\n await this.device.send(\n Reports.GLITTER_BASIC_CMD, \n [Commands.GLITTER_CMD_REBOOT, mode]\n );\n }\n\n async drawMatrix(matrix) {\n await this.device.send(\n Reports.GLITTER_GRID_PWM_CNTL,\n matrix.flat().map(v => GAMMA[Math.floor((v ?? 0) * 255)])\n );\n }\n\n async drawPixel(r, c, brightness) {\n await this.device.send(\n Reports.GLITTER_BASIC_CMD,\n [Commands.GLITTER_CMD_DRAW_PIXEL, c, r, brightness]\n );\n }\n\n async drawLine({r1, c1}, {r2, c2}, brightness) {\n await this.device.send(\n Reports.GLITTER_BASIC_CMD,\n [Commands.GLITTER_CMD_DRAW_PIXEL, r1, c1, r2, c2, brightness]\n );\n }\n\n device;\n}\n","import { HEIGHT, WIDTH } from '../../../hardware-constants.js';\nimport { getUnusedDevice } from '../../../web-hid/device.js';\nimport { HIDOperations } from '../../../web-hid/HIDOperations.js';\nimport { ReportAbstractionLayer } from './ReportAbstractionLayer.js';\nimport { BootMode } from './reports.js';\n\nexport class SparkleController extends ReportAbstractionLayer {\n async bootloader() {\n await super.reboot(BootMode.BOOTSEL);\n }\n\n async connect() {\n const device = await getUnusedDevice();\n\n if (device) {\n await device.open();\n this.device = new HIDOperations(device);\n } else {\n throw new Error('No Device Found');\n }\n }\n \n async draw(matrix) {\n await super.drawMatrix(matrix);\n }\n\n async verifyFirmware() {\n try {\n const info = await super.info();\n return (\n info.display_height == HEIGHT &&\n info.display_width == WIDTH\n );\n } catch {\n return false;\n }\n }\n\n async version() {\n const info = await super.info();\n\n if (info.version_major != undefined \n && info.version_minor != undefined\n && (info.version_major > 0 || info.version_minor > 0)) {\n return {\n major: info.version_major,\n minor: info.version_minor\n }\n } else {\n // Sparkle <=1.1.1: Glitter version unavailable \n return { major: 1, minor: 0 };\n }\n }\n}\n","import { DefaultController } from './supported-firmware/FrameworkComputer/inputmodule-rs/DefaultController.js';\nimport { SigrootController } from './supported-firmware/sigroot/FW_LED_Matrix_Firmware/SigrootController.js';\nimport { SparkleController } from './supported-firmware/vddCore/sparkle-fw16/SparkleController.js';\n\nexport class HardwareControllerFactory {\n static async detectSerial() {\n const c1 = new DefaultController();\n const c2 = new SigrootController();\n\n await c1.connect();\n if (await c1.verifyFirmware()) {\n return c1;\n }\n \n await c2.connect()\n if (await c2.verifyFirmware()) {\n return c2;\n } \n \n return null;\n }\n\n static async detectHID() {\n const c1 = new SparkleController();\n\n await c1.connect();\n if (await c1.verifyFirmware()) {\n return c1;\n } \n \n return null;\n }\n}\n"],"names":["VID","VID_ARR","GAMMA","Object","freeze","filters","usbVendorId","usbProductId","PortSelectionCancelled","Error","constructor","super","this","name","date","Date","PortUnavailable","async","requestPort","navigator","serial","e","knownPorts","used","Set","unused","getOrFetchUnused","port","pop","systemPorts","getPorts","enqueueUnique","manualPort","add","ports","has","includes","push","getUnusedPort","close","message","PortMutex","portOperations","lockName","Math","random","toString","deduper","Map","portOps","acquire","fn","trace","stack","enqueue","console","error","acquireIdempotent","key","info","set","execDedupedOp","locks","request","get","delete","PortOperations","rx","length","timeout","readable","locked","response","reader","getReader","timeoutHandle","setTimeout","cancel","value","done","read","clearTimeout","releaseLock","tx","buffer","writable","writer","getWriter","write","Uint8Array","Command","ANIMATE","BRIGHTNESS","BOOTLOADER","DRAW","DRAW_GREY_COL_BUFFER","GAME_CTRL","GAME_STATUS","PANIC","PATTERN","SLEEP","STAGE_GREY_COL","START_GAME","VERSION","BitDepth","GRAY_8BIT","MONO_1BIT","CommandAbstractionLayer$1","portMutex","bootloader","p","brightness","draw","matrix","index","output","fill","r","c","drawGrayscale","buffers","Array","from","_","floor","i","asleep","sleep","wake","pattern","percent","Pattern","PERCENTAGE","version","ver","major","minor","patch","preRelease","DefaultController","CommandAbstractionLayer","connect","connected","open","baudRate","bitDepth","verifyFirmware","undefined","NOOP","ANIMATION_DIAMOND","ANIMATION_FIRE","ANIMATION_FIREPLACE","ANIMATION_GEAR","ANIMATION_RING","ANIMATION_STARTUP","ANIMATION_STARTUP_ONCE","DRAW_PWM","DRAW_PWM_BLOCKING","DRAW_SCALE","DRAW_SCALE_BLOCKING","FLUSH_CMD_QUEUE","TEST_PATTERN","SET_CONST_PWM","SET_CONST_SCALE","SET_PX_PWM","SET_PX_SCALE","IDENTITY_STRING","IDENTITY_STR_REGEX","identityString","ident","String","fromCharCode","setPixelPwm","setGlobalPwm","setMatrixPwm","concat","flat","map","v","setPixelAnalog","setGlobalAnalog","setMatrixAnalog","SigrootController","scaleInitialized","match","vendorId","productId","DeviceSelectionCancelled","requestDevice","knownDevices","device","systemDevices","hid","getDevices","manualDevices","devices","dev","getUnusedDevice","HIDOperations","send","report","data","bytes","arr","len","val","pad","feature","sendFeatureReport","id","sendReport","reply","receiveFeatureReport","byteLength","exp","act","Reports","Commands","BootMode","ReportAbstractionLayer","infoRaw","sleep_pin","getUint8","dip1_pin","intb_pin","state_flags","id_reg","config_reg","global_brightness","display_width","display_height","timeout_ms","getUint32","version_major","version_minor","disableSleep","disableDeepSleep","disableSleepTimer","enableDeepSleep","enableSleepTimer","milliseconds","view","DataView","ArrayBuffer","setInt32","reboot","mode","drawMatrix","drawPixel","drawLine","r1","c1","r2","c2","SparkleController","detectSerial","detectHID"],"mappings":"2PAAY,MAECA,EAAM,MACNC,EAAU,CAAC,GAAM,KAKjBC,EAAQC,OAAOC,OAAO,CACjC,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EACrB,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EACrB,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EACrB,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EACrB,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EACrB,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EACrB,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EACrB,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EACrB,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EACrB,EAAG,EAAG,EAAG,EAAG,GAAI,GAAI,GAAI,GACxB,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAC5B,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAC5B,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAC5B,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAC5B,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAC5B,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAC5B,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAC5B,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAC5B,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAC5B,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAC5B,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAC5B,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAC5B,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,IAC5B,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IACnC,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IACnC,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IACnC,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IACnC,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IACnC,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IACnC,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IACnC,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IACnC,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,MCtC/BC,EAAU,CAAC,CAAEC,YAAaN,EAAKO,aDElB,KCAZ,MAAMC,UAA+BC,MAC1C,WAAAC,GACEC,MAAM,kCACNC,KAAKC,KAAOD,KAAKF,YAAYG,KAC7BD,KAAKE,KAAO,IAAIC,IAClB,EAGK,MAAMC,UAAwBP,MACnC,WAAAC,GACEC,MAAM,iCACNC,KAAKC,KAAOD,KAAKF,YAAYG,KAC7BD,KAAKE,KAAO,IAAIC,IAClB,EAGFE,eAAeC,IACb,IACE,OAAIC,UAAUC,OAAOF,kBACNC,UAAUC,OAAOF,YAAY,CAAAb,QAAEA,IAErC,IAEX,CAAE,MAAOgB,GACP,OAAQA,EAAER,MACR,oBACE,MAAM,IAAIL,EACZ,wBACE,MAAM,IAAIQ,EACZ,oBACE,OAAO,KACT,QACE,MAAMK,EAEZ,CACF,CAuCA,MAAMC,EAAa,IArCnB,MACEC,KAAO,IAAIC,IACXC,OAAS,GAET,sBAAMC,GACJ,IAAIC,EAAOf,KAAKa,OAAOG,MAEvB,IAAKD,EAAM,CACT,MAAME,QAAoBV,UAAUC,OAAOU,SAAS,CAAAzB,QAAEA,IACtDO,MAAKmB,EAAeF,GACpBF,EAAOf,KAAKa,OAAOG,KACrB,CAEA,IAAKD,EAAM,CACT,MAAMK,QAAmBd,IACzBN,MAAKmB,EAAe,CAACC,IACrBL,EAAOf,KAAKa,OAAOG,KACrB,CAMA,OAJID,GACFf,KAAKW,KAAKU,IAAIN,GAGTA,CACT,CAEA,EAAAI,CAAeG,GACb,GAAIA,EACF,IAAK,MAAMP,KAAQO,GACbP,GAASf,KAAKW,KAAKY,IAAIR,IAAUf,KAAKa,OAAOW,SAAST,IACxDf,KAAKa,OAAOY,KAAKV,EAIzB,GAkBKV,eAAeqB,IACpB,aAAahB,EAAWI,kBAC1B,CAMOT,eAAesB,EAAMZ,GAC1B,UACQA,EAAKY,OACb,CAAE,MAAMlB,GACN,GAAc,qBAAVA,EAAER,MACAQ,EAAEmB,QAAQJ,SAAS,8BACrB,MAAMf,CAGZ,CACF,CC/GO,MAAMoB,EACX,WAAA/B,CAAYgC,GACV9B,MAAK+B,EAAY,cAAcC,KAAKC,SAASC,aAC7ClC,MAAKmC,EAAW,IAAIC,IACpBpC,MAAKqC,EAAWP,CAClB,CAEA,aAAMQ,CAAQC,GACZ,MAAMC,EAAQ,IAAI3C,MAAM,kBAAkB4C,YAEpCzC,MAAK0C,EAASrC,UAClB,UACQkC,EAAGvC,MAAKqC,EAChB,CAAE,MAAO5B,GACPkC,QAAQC,MAAM,wCACdD,QAAQC,MAAM,kBAAmBnC,GACjCkC,QAAQC,MAAM,yCAA0CJ,EAC1D,GAEJ,CAEA,uBAAMK,CAAkBC,EAAKP,GAC3B,MAAMC,EAAQ,IAAI3C,MAAM,kBAAkB4C,MAEtCzC,MAAKmC,EAASZ,IAAIuB,IACpBH,QAAQI,KAAK,IAAID,yBAGnB9C,MAAKmC,EAASa,IAAIF,EAAKzC,UACrB,UACQkC,EAAGvC,MAAKqC,EAChB,CAAE,MAAO5B,GACPkC,QAAQC,MAAM,wCACdD,QAAQC,MAAM,kBAAmBnC,GACjCkC,QAAQC,MAAM,yCAA0CJ,EAC1D,UAGIxC,MAAK0C,EAAS,IAAM1C,MAAKiD,EAAeH,GAChD,CAEA,OAAMJ,CAASH,GAEb,OAAOhC,UAAU2C,MAAMC,QAAQnD,MAAK+B,EAAWQ,EACjD,CAEA,OAAMU,CAAeH,GACnB,GAAI9C,MAAKmC,EAASZ,IAAIuB,GAAM,CAC1B,MAAMP,EAAKvC,MAAKmC,EAASiB,IAAIN,GAC7B9C,MAAKmC,EAASkB,OAAOP,SACfP,GACR,CACF,CAEAR,GACAI,GACAE,GCxDK,MAAMiB,EACX,WAAAxD,CAAYiB,GACVf,MAAKe,EAAQA,CACf,CAEA,QAAMwC,CAAGC,EAAQC,EAAQ,KACvB,GAAmB,OAAfzD,MAAKe,EACP,MAAM,IAAIlB,MAAM,4CAOlB,GAAIG,MAAKe,EAAM2C,SAASC,OACtB,MAAM,IAAI9D,MAAM,mCAGlB,MAAM+D,EAAW,GACXC,EAAS7D,MAAKe,EAAM2C,SAASI,YAC7BC,EAAgBC,WAAW,IAAMH,EAAOI,SAAUR,GAExD,IAEE,KAAOG,EAASJ,OAASA,GAAQ,CAC/B,MAAMU,MAAEA,EAAKC,KAAEA,SAAeN,EAAOO,OAErC,GADAR,EAASnC,QAASyC,GAAS,IACvBC,IAASD,EAAO,KACtB,CACF,CAAC,QACCG,aAAaN,GACbF,EAAOS,aACT,CAEA,OAAOV,CACT,CAEA,QAAMW,CAAGC,GACP,GAAmB,OAAfxE,MAAKe,EACP,MAAM,IAAIlB,MAAM,4CAOlB,GAAIG,MAAKe,EAAM0D,SAASd,OACtB,MAAM,IAAI9D,MAAM,mCAGlB,MAAM6E,EAAS1E,MAAKe,EAAM0D,SAASE,YAEnC,UACQD,EAAOE,MAAM,IAAIC,WAAWL,GACpC,CAAC,cAMOE,EAAO/C,OACf,CACF,CAEAZ,GC/DK,MAEM+D,EAAUvF,OAAOC,OAAO,CACnCuF,QAAS,EACTC,WAAY,EACZC,WAAY,EACZC,KAAM,EACNC,qBAAsB,EACtBC,UAAW,GACXC,YAAa,GACbC,MAAO,EACPC,QAAS,EACTC,MAAO,EACPC,eAAgB,EAChBC,WAAY,GACZC,QAAS,KAgBEC,EAAWrG,OAAOC,OAAO,CACpCqG,UAAW,QACXC,UAAW,UC/BN,IAAAC,EAAA,MACL,WAAAjG,CAAYkG,EAAY,MACtBhG,KAAKgG,UAAYA,CACnB,CAEA,gBAAMC,SACEjG,KAAKgG,UAAU1D,QAAQjC,gBACrB6F,EAAE3B,GAAG,IAAIlF,EAASyF,EAAQG,cAEpC,CAEA,gBAAMkB,CAAWA,SACTnG,KAAKgG,UAAU1D,QAAQjC,gBACrB6F,EAAE3B,GAAG,IAAIlF,EAASyF,EAAQE,WAAYmB,KAEhD,CAEA,UAAMC,CAAKC,GACT,IAAIC,EAAQ,EACRC,EAAS,IAAI1B,WAAW,IAAI2B,KAAK,GAGrC,IAAK,IAAIC,EAAI,EAAGA,ELxBE,GKwBUA,IAC1B,IAAK,IAAIC,EAAI,EAAGA,EL1BD,EK0BYA,IACrBL,EAAOI,GAAGC,KACZH,EAAOD,GAAS,IAAM,GAAKA,EAAQ,GAErCA,UAIEtG,KAAKgG,UAAUnD,kBACnB,aACAxC,gBACQ6F,EAAE3B,GAAG,IAAIlF,EAASyF,EAAQI,QAASqB,KAG/C,CAEA,mBAAMI,CAAcN,GAElB,MAAMO,EAAUC,MAAMC,KACpB,CAAEtD,OL7Ca,GK8Cf,CAACuD,EAAGL,IAAMG,MAAMC,KACd,CAAEtD,OL9CY,IK+Cd,CAACuD,EAAGN,IAAMnH,EAAM0C,KAAKgF,MAA4B,KAArBX,EAAOI,GAAGC,IAAM,aAK1C1G,KAAKgG,UAAUnD,kBACnB,aACAxC,UACE,IAAK,IAAI4G,EAAI,EAAGA,ELxDH,EKwDcA,UACnBf,EAAE3B,GAAG,IAAIlF,EAASyF,EAAQW,eAAgBwB,KAAML,EAAQK,WAE1Df,EAAE3B,GAAG,IAAIlF,EAASyF,EAAQK,wBAGtC,CAEA,YAAM+B,GACJ,IAAIA,GAAS,EAQb,aANMlH,KAAKgG,UAAU1D,QAAQjC,gBACrB6F,EAAE3B,GAAG,IAAIlF,EAASyF,EAAQU,QAChC0B,QAAehB,EAAE3C,GDpEK,ICqEtB2D,EAAsB,GAAbA,EAAO,KAGXA,CACT,CAEA,WAAMC,SACEnH,KAAKgG,UAAU1D,QAAQjC,gBACrB6F,EAAE3B,GAAG,IAAIlF,EAASyF,EAAQU,MAAO,KAE3C,CAEA,UAAM4B,SACEpH,KAAKgG,UAAU1D,QAAQjC,gBACrB6F,EAAE3B,GAAG,IAAIlF,EAASyF,EAAQU,SAEpC,CAEA,aAAM6B,CAAQA,SACNrH,KAAKgG,UAAUnD,kBACnB,aACAxC,gBACQ6F,EAAE3B,GAAG,IAAIlF,EAASyF,EAAQS,QAAS8B,KAG/C,CAEA,aAAMC,CAAQA,SACNtH,KAAKgG,UAAUnD,kBACnB,aACAxC,gBACQ6F,EAAE3B,GAAG,IAAIlF,EAASyF,EAAQS,QAASgC,QAAQC,WAAYF,KAGnE,CAEA,aAAMG,GACJ,IAAIC,EAAM,CAAA,EAaV,aAXM1H,KAAKgG,UAAU1D,QAAQjC,gBACrB6F,EAAE3B,GAAG,IAAIlF,EAASyF,EAAQa,UAChC,MAAM/B,QAAiBsC,EAAE3C,GD9GH,ICiHtBmE,EAAIC,MAAQ/D,EAAS,GACrB8D,EAAIE,MAAQhE,EAAS,IAAM,EAC3B8D,EAAIG,MAAsB,GAAdjE,EAAS,GACrB8D,EAAII,WAA4B,GAAflE,EAAS,KAGrB8D,CACT,GCnHK,MAAMK,UAA0BC,EACrC,gBAAM/B,SACElG,MAAMkG,YACd,CAEA,aAAMgC,GACJ,MAAMlH,QAAaW,IAEnB,IAAIX,GAAMmH,UAKR,MAAM,IAAIrI,MAAM,uBAJV8B,EAAMZ,SACNA,EAAKoH,KAAK,CAAEC,SAAU,SAC5BpI,KAAKgG,UAAY,IAAInE,EAAU,IAAIyB,EAAevC,GAItD,CAEA,UAAMqF,CAAKC,GACT,OAAQrG,KAAKqI,UAAYzC,EAASE,WAEhC,KAAMF,EAAkB,gBAChB7F,MAAM4G,cAAcN,GAC1B,MAEF,KAAMT,EAAkB,gBAChB7F,MAAMqG,KAAKC,GACjB,MAEF,QACE1D,QAAQC,MAAM,yBAAyB5C,KAAKqI,YAElD,CAEA,oBAAMC,GACJ,IACE,MAAMb,QAAgB1H,MAAM0H,UAE5B,OAAOA,GACec,MAAjBd,EAAQE,OACSY,MAAjBd,EAAQG,OACSW,MAAjBd,EAAQI,OACcU,MAAtBd,EAAQK,UAEf,CAAE,MACA,OAAO,CACT,CACF,CAEA,aAAML,GACJ,OAAO1H,MAAM0H,SACf,ECxDK,MAAM3C,EAAUvF,OAAOC,OAAO,CACzBgJ,KAAM,EACNC,kBAAmB,IACnBC,eAAgB,GAChBC,oBAAqB,IACrBC,eAAgB,IAChBC,eAAgB,IAChBC,kBAAmB,GACnBC,uBAAwB,GACxB9D,WAAY,IACZ+D,SAAU,IACVC,kBAAmB,GACnBC,WAAY,IACZC,oBAAqB,GACrBC,gBAAiB,GACjBC,aAAc,IACdC,cAAe,IACfC,gBAAiB,IACjBC,WAAY,IACZC,aAAc,IACdC,gBAAiB,MAKhBC,EAAqB,4CCtB3B,MAAM3B,EACX,WAAAlI,CAAYkG,EAAY,MACtBhG,KAAKgG,UAAYA,CACnB,CAEA,gBAAMC,SACEjG,KAAKgG,UAAU1D,QAAQjC,gBACrB6F,EAAE3B,GAAG,CAACO,EAAQG,cAExB,CAEA,oBAAM2E,GACJ,IAAIC,EAAQ,KAOZ,aALM7J,KAAKgG,UAAU1D,QAAQjC,gBACrB6F,EAAE3B,GAAG,CAACO,EAAQ4E,kBACpBG,QAAc3D,EAAE3C,GDIU,MCDrBuG,OAAOC,gBAAgBF,EAChC,CAEA,iBAAMG,CAAYvD,EAAGC,EAAGP,SAChBnG,KAAKgG,UAAU1D,QACnBjC,gBACQ6F,EAAE3B,GAAG,CAACO,EAAQ0E,WAAY9C,EAAGD,EAAGN,KAG5C,CAEA,kBAAM8D,CAAa9D,SACXnG,KAAKgG,UAAU1D,QACnBjC,gBACQ6F,EAAE3B,GAAG,CAACO,EAAQwE,cAAenD,KAGzC,CAEA,kBAAM+D,CAAa7D,SAEXrG,KAAKgG,UAAUnD,kBACnB,aACAxC,gBACQ6F,EAAE3B,GACN,CAACO,EAAQkE,UAAUmB,OACjB9D,EAAO+D,OAAOC,IAAIC,GAChBhL,EAAM0C,KAAKgF,MAAiB,KAAVsD,GAAK,SAMnC,CAEA,oBAAMC,CAAe9D,EAAGC,EAAGP,SACnBnG,KAAKgG,UAAU1D,QACnBjC,gBACQ6F,EAAE3B,GAAG,CAACO,EAAQ2E,aAAc/C,EAAGD,EAAGN,KAG9C,CAEA,qBAAMqE,CAAgBrE,SACdnG,KAAKgG,UAAU1D,QACnBjC,gBACQ6F,EAAE3B,GAAG,CAACO,EAAQyE,gBAAiBpD,KAG3C,CAEA,qBAAMsE,CAAgBpE,SAEdrG,KAAKgG,UAAUnD,kBACnB,aACAxC,gBACQ6F,EAAE3B,GACN,CAACO,EAAQoE,YAAYiB,OACnB9D,EAAO+D,OAAOC,IAAIC,GAChBhL,EAAM0C,KAAKgF,MAAiB,KAAVsD,GAAK,SAMnC,ECjFK,MAAMI,UAA0B1C,EACrC,gBAAM/B,SACElG,MAAMkG,YACd,CAEA,aAAMgC,GACJ,MAAMlH,QAAaW,IAEfX,GAAMmH,kBACFvG,EAAMZ,SACNA,EAAKoH,KAAK,CAAEC,SAAU,SAC5BpI,KAAKgG,UAAY,IAAInE,EAAU,IAAIyB,EAAevC,IAEtD,CAEA,UAAMqF,CAAKC,GACT,GAAKrG,MAAK2K,EAIR,MAAM,IAAI9K,MAAM,uBAHVE,MAAMyK,gBAAgB,IAC5BxK,MAAK2K,GAAoB,QAKrB5K,MAAMmK,aAAa7D,EAC3B,CAEA,oBAAMiC,GACJ,OAA+B,YAAlBtI,KAAKyH,SACpB,CAEA,aAAMA,GACJ,MACMmD,SADc7K,MAAM6J,kBACNgB,MAAMjB,GAE1B,OAAIiB,GAAyB,GAAhBA,EAAMpH,OACV,CACLmE,MAAOiD,EAAM,GACbhD,MAAOgD,EAAM,IAGR,IAEX,CAEAD,GChDF,MAAMlL,EAAU,CAAC,CAAEoL,SAAUzL,EAAK0L,UVEf,KUAZ,MAAMC,UAAiClL,MAC5C,WAAAC,GACEC,MAAM,oCACNC,KAAKC,KAAOD,KAAKF,YAAYG,KAC7BD,KAAKE,KAAO,IAAIC,IAClB,EAGFE,eAAe2K,IACb,IACE,OAAIzK,UAAUC,OAAOF,kBACNC,UAAUC,OAAOwK,cAAc,CAAEvL,YAEvC,IAEX,CAAE,MAAOgB,GACP,OAAQA,EAAER,MACR,oBACE,MAAM,IAAI8K,EACZ,oBACE,OAAO,KACT,QACE,MAAMtK,EAEZ,CACF,CAuCA,MAAMwK,EAAe,IArCrB,MACEtK,KAAO,IAAIC,IACXC,OAAS,GAET,sBAAMC,GACJ,IAAIoK,EAASlL,KAAKa,OAAOG,MAEzB,IAAKkK,EAAQ,CACX,MAAMC,QAAsB5K,UAAU6K,IAAIC,WAAW,CAAE5L,YACvDO,MAAKmB,EAAegK,GACpBD,EAASlL,KAAKa,OAAOG,KACvB,CAEA,IAAKkK,EAAQ,CACX,MAAMI,QAAsBN,IAC5BhL,MAAKmB,EAAe,CAACmK,IACrBJ,EAASlL,KAAKa,OAAOG,KACvB,CAMA,OAJIkK,GACFlL,KAAKW,KAAKU,IAAI6J,GAGTA,CACT,CAEA,EAAA/J,CAAeoK,GACb,GAAIA,EACF,IAAK,MAAMC,KAAOD,GACZC,GAAQxL,KAAKW,KAAKY,IAAIiK,IAASxL,KAAKa,OAAOW,SAASgK,IACtDxL,KAAKa,OAAOY,KAAK+J,EAIzB,GAkBKnL,eAAeoL,IACpB,aAAaR,EAAanK,kBAC5B,CCnFO,MAAM4K,EACX,WAAA5L,CAAYoL,GACVlL,MAAKkL,EAAUA,CACjB,CAEA,UAAMS,CAAKC,EAAQC,GACjB,GAAIA,EAAKrI,OAASoI,EAAOE,MACvBD,ECTC,SAAaE,EAAKC,EAAKC,EAAI,GAChC,OAAOF,EAAI5B,OAAO,IAAItD,MAAMmF,EAAMD,EAAIvI,QAAQgD,KAAKyF,GACrD,CDOaC,CAAIL,EAAMD,EAAOE,YACnB,GAAID,EAAKrI,OAASoI,EAAOE,MAC9B,MAAM,IAAIjM,MAAM,yCAGlB,MAAM2E,EAAS,IAAIK,WAAWgH,GAAMrH,OAEhCoH,EAAOO,cACHnM,MAAKkL,EAAQkB,kBAAkBR,EAAOS,GAAI7H,SAE1CxE,MAAKkL,EAAQoB,WAAWV,EAAOS,GAAI7H,EAE7C,CAEA,aAAMrB,CAAQyI,GACZ,IAAIW,EAAQ,GAEZ,IAAIX,EAAOO,QAOT,MAAM,IAAItM,MAAM,qBAGlB,GATE0M,QAAcvM,MAAKkL,EAAQsB,qBAAqBZ,EAAOS,IASrDE,EAAME,YAAcb,EAAOE,MAAO,CACpC,MAAMY,EAAMd,EAAOE,MACba,EAAMJ,EAAME,WAClB9J,QAAQC,MAAM,gBAAgB+J,eAAiBD,KACjD,CAEA,OAAOH,CACT,CAEArB,GE7CK,MAAM0B,EACU,CACnBP,GAAI,EACJP,MAAO,IACPK,SAAS,GAJAS,EAMQ,CACjBP,GAAI,EACJP,MAAO,GACPK,SAAS,GATAS,EAgBY,CACrBP,GAAI,EACJP,MAAO,IACPK,SAAS,GAIAU,EACS,EADTA,EAEQ,EAFRA,EAGkB,EAHlBA,EAIoB,EAJpBA,EAMa,EAIbC,EACF,EC/BJ,MAAMC,EACX,WAAAjN,CAAYoL,EAAS,MACnBlL,KAAKkL,OAASA,CAChB,CAEA,UAAMnI,GACJ,MAAMiK,QAAgBhN,KAAKkL,OAAO/H,QAAQyJ,GAE1C,MAAO,CACLK,UAAWD,EAAQE,SAAS,GAC5BC,SAAUH,EAAQE,SAAS,GAC3BE,SAAUJ,EAAQE,SAAS,GAC3BG,YAAaL,EAAQE,SAAS,GAC9BI,OAAQN,EAAQE,SAAS,GACzBK,WAAYP,EAAQE,SAAS,GAC7BM,kBAAmBR,EAAQE,SAAS,GACpCO,cAAeT,EAAQE,SAAS,GAChCQ,eAAgBV,EAAQE,SAAS,GACjCS,WAAYX,EAAQY,UAAU,IAC9BC,cAAeb,EAAQE,SAAS,IAChCY,cAAed,EAAQE,SAAS,IAEpC,CAEA,UAAM9F,SACEpH,KAAKkL,OAAOS,KAChBiB,EACA,CAACC,GAA4B,GAEjC,CAEA,WAAM1F,SACEnH,KAAKkL,OAAOS,KAChBiB,EACA,CAACC,GAA4B,GAEjC,CAEA,kBAAMkB,SACE/N,KAAKkL,OAAOS,KAChBiB,EACA,CAACC,EAAwC,IAAM,IAAM,IAAM,KAE/D,CAEA,sBAAMmB,SACEhO,KAAKkL,OAAOS,KAChBiB,EACA,CAACC,EAAsC,GAE3C,CAEA,uBAAMoB,SACEjO,KAAKkL,OAAOS,KAChBiB,EACA,CAACC,EAAwC,EAAM,EAAM,EAAM,GAE/D,CAEA,qBAAMqB,SACElO,KAAKkL,OAAOS,KAChBiB,EACA,CAACC,EAAsC,GAE3C,CAEA,sBAAMsB,CAAiBC,GACrB,MAAMC,EAAO,IAAIC,SAAS,IAAIC,YAAY,IAE1CF,EAAKG,SAAS,EAAGJ,GADI,SAEfpO,KAAKkL,OAAOS,KAChBiB,EACA,CACEC,EACAwB,EAAKnB,SAAS,GACdmB,EAAKnB,SAAS,GACdmB,EAAKnB,SAAS,GACdmB,EAAKnB,SAAS,IAGpB,CAEA,YAAMuB,CAAOC,SACL1O,KAAKkL,OAAOS,KAChBiB,EACA,CAACC,EAA6B6B,GAElC,CAEA,gBAAMC,CAAWtI,SACTrG,KAAKkL,OAAOS,KAChBiB,EACAvG,EAAO+D,OAAOC,IAAIC,GAAKhL,EAAM0C,KAAKgF,MAAiB,KAAVsD,GAAK,MAElD,CAEA,eAAMsE,CAAUnI,EAAGC,EAAGP,SACdnG,KAAKkL,OAAOS,KAChBiB,EACA,CAACC,EAAiCnG,EAAGD,EAAGN,GAE5C,CAEA,cAAM0I,EAASC,GAACA,EAAEC,GAAEA,IAAKC,GAACA,EAAEC,GAAEA,GAAK9I,SAC3BnG,KAAKkL,OAAOS,KAChBiB,EACA,CAACC,EAAiCiC,EAAIC,EAAIC,EAAIC,EAAI9I,GAEtD,CAEA+E,OC3GK,MAAMgE,UAA0BnC,EACrC,gBAAM9G,SACElG,MAAM0O,OAAO3B,EACrB,CAEA,aAAM7E,GACJ,MAAMiD,QAAeO,IAErB,IAAIP,EAIF,MAAM,IAAIrL,MAAM,yBAHVqL,EAAO/C,OACbnI,KAAKkL,OAAS,IAAIQ,EAAcR,EAIpC,CAEA,UAAM9E,CAAKC,SACHtG,MAAM4O,WAAWtI,EACzB,CAEA,oBAAMiC,GACJ,IACE,MAAMvF,QAAahD,MAAMgD,OACzB,Of5BgB,Ie6BdA,EAAK2K,gBf9BQ,Ge+Bb3K,EAAK0K,aAET,CAAE,MACA,OAAO,CACT,CACF,CAEA,aAAMhG,GACJ,MAAM1E,QAAahD,MAAMgD,OAEzB,OAA0BwF,MAAtBxF,EAAK8K,eACkBtF,MAAtBxF,EAAK+K,gBACJ/K,EAAK8K,cAAgB,GAAK9K,EAAK+K,cAAgB,GAC5C,CACLnG,MAAO5E,EAAK8K,cACZjG,MAAO7E,EAAK+K,eAIP,CAAEnG,MAAO,EAAGC,MAAO,EAE9B,wEfnDoB,+BgBGf,MACL,yBAAauH,GACX,MAAMJ,EAAK,IAAIhH,EACTkH,EAAK,IAAIvE,EAGf,aADMqE,EAAG9G,gBACC8G,EAAGzG,iBACJyG,SAGHE,EAAGhH,gBACCgH,EAAG3G,iBACJ2G,EAGF,KACT,CAEA,sBAAaG,GACX,MAAML,EAAK,IAAIG,EAGf,aADMH,EAAG9G,gBACC8G,EAAGzG,iBACJyG,EAGF,IACT,ShB3BiB,aACI,CAAC,EAAM,2HALT,0EU2Ed1O,uBACW2K,GAClB,yBTQO3K,uBACWC,GAClB"}
|
|
1
|
+
{"version":3,"file":"led-matrix-controllers.umd.min.js","sources":["../src/hardware-constants.js","../src/environments/web/usb-serial/port.js","../src/environments/web/usb-serial/PortMutex.js","../src/environments/web/usb-serial/PortOperations.js","../src/supported-firmware/FrameworkComputer/inputmodule-rs/commands.js","../src/supported-firmware/FrameworkComputer/inputmodule-rs/CommandAbstractionLayer.js","../src/supported-firmware/FrameworkComputer/inputmodule-rs/DefaultController.js","../src/supported-firmware/sigroot/FW_LED_Matrix_Firmware/commands.js","../src/supported-firmware/sigroot/FW_LED_Matrix_Firmware/CommandAbstractionLayer.js","../src/supported-firmware/sigroot/FW_LED_Matrix_Firmware/SigrootController.js","../src/environments/web/usb-hid/device.js","../src/environments/web/usb-hid/HIDOperations.js","../src/environments/web/usb-hid/util.js","../src/supported-firmware/vddCore/sparkle-fw16/reports.js","../src/supported-firmware/vddCore/sparkle-fw16/ReportAbstractionLayer.js","../src/supported-firmware/vddCore/sparkle-fw16/SparkleController.js","../src/HardwareControllerFactory.js"],"sourcesContent":["export const WIDTH = 9;\nexport const HEIGHT = 34;\nexport const VID = 0x32AC;\nexport const VID_ARR = [0x32, 0xAC];\nexport const PID = 0x0020;\nexport const PID_ARR = [0x00, 0x20];\n\n// For PWM dimming (not for analog dimming/constant-current reduction!)\nexport const GAMMA = Object.freeze([\n 0, 0, 0, 0, 0, 0, 0, 1, \n 1, 1, 1, 1, 1, 1, 1, 1, \n 1, 1, 1, 1, 1, 1, 1, 1, \n 1, 1, 1, 1, 1, 1, 1, 1, \n 1, 1, 1, 2, 2, 2, 2, 2, \n 2, 2, 2, 2, 3, 3, 3, 3, \n 3, 3, 3, 4, 4, 4, 4, 4, \n 4, 5, 5, 5, 5, 6, 6, 6, \n 6, 6, 7, 7, 7, 7, 8, 8, \n 8, 9, 9, 9, 10, 10, 10, 11, \n 11, 11, 12, 12, 12, 13, 13, 14, \n 14, 14, 15, 15, 16, 16, 17, 17, \n 17, 18, 18, 19, 19, 20, 20, 21, \n 22, 22, 23, 23, 24, 24, 25, 26, \n 26, 27, 27, 28, 29, 29, 30, 31, \n 32, 32, 33, 34, 34, 35, 36, 37, \n 38, 38, 39, 40, 41, 42, 42, 43, \n 44, 45, 46, 47, 48, 49, 50, 51, \n 52, 53, 54, 55, 56, 57, 58, 59, \n 60, 61, 62, 63, 64, 66, 67, 68, \n 69, 70, 71, 73, 74, 75, 76, 78, \n 79, 80, 82, 83, 84, 86, 87, 88, \n 90, 91, 93, 94, 96, 97, 99, 100, \n 102, 103, 105, 106, 108, 110, 111, 113, \n 115, 116, 118, 120, 121, 123, 125, 127, \n 128, 130, 132, 134, 136, 138, 140, 141, \n 143, 145, 147, 149, 151, 153, 155, 157, \n 159, 161, 164, 166, 168, 170, 172, 174, \n 177, 179, 181, 183, 186, 188, 190, 193, \n 195, 197, 200, 202, 205, 207, 210, 212, \n 215, 217, 220, 222, 225, 228, 230, 233, \n 236, 238, 241, 244, 247, 249, 252, 255\n]);\n","import { PID, VID } from '../../../hardware-constants.js';\n\nconst filters = [{ usbVendorId: VID, usbProductId: PID }];\n\nexport class PortSelectionCancelled extends Error {\n constructor() {\n super('User cancelled port selection.');\n this.name = this.constructor.name;\n this.date = new Date();\n }\n}\n\nexport class PortUnavailable extends Error {\n constructor() {\n super('Selected port already in use.');\n this.name = this.constructor.name;\n this.date = new Date();\n }\n}\n\nasync function requestPort() {\n try {\n if (navigator.serial.requestPort) {\n return Object.assign(\n await navigator.serial.requestPort({ filters }),\n { pickedByUser: true }\n );\n } else {\n return null; // Web Worker\n }\n } catch (e) {\n switch (e.name) {\n case ('NotFoundError'):\n throw new PortSelectionCancelled();\n case ('InvalidStateError'):\n throw new PortUnavailable();\n case ('SecurityError'): // No user gesture\n return null;\n default:\n throw e;\n }\n }\n}\n\nclass KnownPorts {\n used = new Set();\n unused = [];\n\n async getOrFetchUnused() {\n let port = this.unused.pop();\n \n if (!port) {\n const knownPorts = await navigator.serial.getPorts({ filters });\n this.#enqueueUnique(knownPorts);\n port = this.unused.pop();\n }\n\n if (!port) {\n const manualPort = await requestPort();\n this.#enqueueUnique([manualPort]);\n port = this.unused.pop();\n }\n\n if (port) {\n this.used.add(port);\n }\n \n return port;\n }\n\n #enqueueUnique(ports) {\n if (ports) {\n for (const port of ports) {\n if (port && !this.used.has(port) && !this.unused.includes(port)) {\n this.unused.push(port);\n }\n }\n }\n }\n}\n\nconst knownPorts = new KnownPorts();\n\n/**\n * Adds user-selected port to permitted ports. Only for use outside of Web \n * Worker to establish permission for use within Web Worker.\n * @returns {null}\n */\nexport async function requestPortForWorker() {\n const _ = await requestPort();\n}\n\n/**\n * Never returns the same port twice. \n * @returns {(SerialPort|null)}\n */\nexport async function getUnusedPort() {\n return await knownPorts.getOrFetchUnused();\n}\n\n/**\n * Close port without throwing if already closed.\n * @param {SerialPort} port \n */\nexport async function close(port) {\n try {\n await port.close();\n } catch(e) {\n if (e.name != 'InvalidStateError') {\n if (e.message.includes('The port is already closed')) {\n throw e;\n }\n }\n }\n}\n","export class PortMutex {\n constructor(portOperations) {\n this.#lockName = `port-mutex-${Math.random().toString()}`;\n this.#deduper = new Map();\n this.#portOps = portOperations;\n }\n\n async acquire(fn) {\n const trace = new Error('created bad cb').stack;\n\n await this.#enqueue(async () => {\n try {\n await fn(this.#portOps);\n } catch (e) {\n console.error('Error occured in anonymous callback.');\n console.error('Original error:', e);\n console.error('--- This callback was created at ---\\n', trace);\n }\n });\n }\n\n async acquireIdempotent(key, fn) {\n const trace = new Error('created bad cb').stack;\n\n if (this.#deduper.has(key)) {\n console.info(`\"${key}\" request coalesced.`);\n }\n\n this.#deduper.set(key, async () => {\n try {\n await fn(this.#portOps);\n } catch (e) {\n console.error('Error occured in anonymous callback.');\n console.error('Original error:', e);\n console.error('--- This callback was created at ---\\n', trace);\n }\n });\n\n await this.#enqueue(() => this.#execDedupedOp(key));\n }\n\n async #enqueue(fn) {\n // `navigator.locks` maintains queue and provides mutual exclusion.\n return navigator.locks.request(this.#lockName, fn);\n }\n\n async #execDedupedOp(key) {\n if (this.#deduper.has(key)) {\n const fn = this.#deduper.get(key);\n this.#deduper.delete(key);\n await fn();\n }\n }\n\n #lockName;\n #deduper;\n #portOps;\n}\n","export class PortOperations {\n constructor(port) {\n this.#port = port;\n }\n\n async rx(length, timeout=3000) {\n if (this.#port === null) {\n throw new Error('attempted RX on uninitialized port.');\n }\n\n if (this.#port.readable === null) {\n throw new Error('attempted RX on closed port.');\n }\n\n /*\n * ReadableStream's built-in locking mechanism cannot be awaited or otherwise\n * asynchronously acquired. A PortMutex must be used.\n */\n if (this.#port.readable.locked) {\n throw new Error('attempted RX while port locked.');\n }\n\n const response = [];\n const reader = this.#port.readable.getReader();\n const timeoutHandle = setTimeout(() => reader.cancel(), timeout);\n\n try {\n // Response may be divided across multiple reads\n while (response.length < length) {\n const { value, done } = await reader.read();\n response.push(...(value ?? []));\n if (done || !value) break;\n }\n } finally {\n clearTimeout(timeoutHandle);\n reader.releaseLock();\n }\n\n return response;\n }\n\n async tx(buffer) {\n if (this.#port === null) {\n throw new Error('attempted TX on uninitialized port.');\n }\n\n if (this.#port.writable === null) {\n throw new Error('attempted TX on closed port.');\n }\n \n /*\n * WritableStream's built-in locking mechanism cannot be awaited or otherwise\n * asynchronously acquired. A PortMutex must be used.\n */\n if (this.#port.writable.locked) {\n throw new Error('attempted TX while port locked.');\n }\n\n const writer = this.#port.writable.getWriter();\n\n try {\n await writer.write(new Uint8Array(buffer));\n } finally {\n /* \n * The writer must be completely torn down between every single write.\n * Many parsers can't handle delayed flushing and write coalescing.\n * Command sequences will fail if `releaseLock()` is used here.\n */\n await writer.close();\n }\n }\n\n #port;\n}\n","// All replies to all commands are 32 bytes\nexport const RX_PACKET_SZ = 32;\n\nexport const Command = Object.freeze({\n ANIMATE: 0x04,\n BRIGHTNESS: 0x00,\n BOOTLOADER: 0x02,\n DRAW: 0x06,\n DRAW_GREY_COL_BUFFER: 0x08,\n GAME_CTRL: 0x11,\n GAME_STATUS: 0x12,\n PANIC: 0x05,\n PATTERN: 0x01,\n SLEEP: 0x03,\n STAGE_GREY_COL: 0x07,\n START_GAME: 0x10,\n VERSION: 0x20,\n});\n\n// Used with Command.PATTERN\nexport const Pattern = Object.freeze({\n DISPLAY_LOTUS_HORIZONTAL: 0x03,\n DISPLAY_LOTUS_VERTICAL: 0x07,\n DISPLAY_PANIC: 0x06,\n DOUBLE_GRADIENT: 0x02,\n FULL_BRIGHTNESS: 0x05,\n GRADIENT: 0x01,\n PERCENTAGE: 0x00,\n ZIG_ZAG: 0x04,\n});\n\n// DRAW or DRAW_GREY_COL_BUFFER\nexport const BitDepth = Object.freeze({\n GRAY_8BIT: '8-bit',\n MONO_1BIT: '1-bit',\n})\n","import { GAMMA, HEIGHT, VID_ARR, WIDTH } from '../../../hardware-constants.js';\nimport { Command, Pattern, RX_PACKET_SZ } from './commands.js';\n\nexport class CommandAbstractionLayer {\n constructor(portMutex = null) {\n this.portMutex = portMutex;\n }\n\n async bootloader() {\n await this.portMutex.acquire(async p => {\n await p.tx([...VID_ARR, Command.BOOTLOADER]);\n });\n }\n\n async brightness(brightness) {\n await this.portMutex.acquire(async p => {\n await p.tx([...VID_ARR, Command.BRIGHTNESS, brightness]);\n });\n }\n\n async draw(matrix) {\n let index = 0;\n let output = new Uint8Array(39).fill(0);\n\n // Pack cells into bits\n for (let r = 0; r < HEIGHT; r++) {\n for (let c = 0; c < WIDTH; c++) {\n if (matrix[r][c]) {\n output[index >> 3] |= 1 << index % 8;\n }\n index++;\n }\n }\n\n await this.portMutex.acquireIdempotent(\n 'drawMatrix', \n async p => {\n await p.tx([...VID_ARR, Command.DRAW, ...output]);\n }\n );\n }\n\n async drawGrayscale(matrix) {\n // Transpose & Gamma Correction\n const buffers = Array.from(\n { length: WIDTH }, \n (_, c) => Array.from(\n { length: HEIGHT }, \n (_, r) => GAMMA[Math.floor((matrix[r][c] ?? 0) * 255)]\n )\n );\n\n // Only execute the most recent call \n await this.portMutex.acquireIdempotent(\n 'drawMatrix', \n async p => {\n for (let i = 0; i < WIDTH; i++) {\n await p.tx([...VID_ARR, Command.STAGE_GREY_COL, i, ...buffers[i]]);\n }\n await p.tx([...VID_ARR, Command.DRAW_GREY_COL_BUFFER]);\n }\n );\n }\n\n async asleep() {\n let asleep = false;\n\n await this.portMutex.acquire(async p => {\n await p.tx([...VID_ARR, Command.SLEEP]);\n asleep = await p.rx(RX_PACKET_SZ);\n asleep = asleep[0] != 0x00;\n });\n\n return asleep;\n }\n\n async sleep() {\n await this.portMutex.acquire(async p => {\n await p.tx([...VID_ARR, Command.SLEEP, 0x01]);\n });\n }\n\n async wake() {\n await this.portMutex.acquire(async p => {\n await p.tx([...VID_ARR, Command.SLEEP]);\n });\n }\n\n async pattern(pattern) {\n await this.portMutex.acquireIdempotent(\n 'drawMatrix',\n async p => {\n await p.tx([...VID_ARR, Command.PATTERN, pattern]);\n }\n );\n }\n\n async percent(percent) {\n percent = Math.min(percent, 100);\n percent = Math.max(percent, 0);\n percent = Math.round(percent);\n\n await this.portMutex.acquireIdempotent(\n 'drawMatrix',\n async p => {\n await p.tx([...VID_ARR, Command.PATTERN, Pattern.PERCENTAGE, percent]);\n }\n );\n }\n\n async version() {\n let ver = {};\n\n await this.portMutex.acquire(async p => {\n await p.tx([...VID_ARR, Command.VERSION]);\n const response = await p.rx(RX_PACKET_SZ);\n\n // MMMMMMMM mmmmPPPP 0000000p\n ver.major = response[0];\n ver.minor = response[1] >> 4;\n ver.patch = response[1] & 0x0F;\n ver.preRelease = response[2] == 1;\n });\n\n return ver;\n }\n\n async scrolling() {\n let scrolling = false;\n\n await this.portMutex.acquire(async p => {\n await p.tx([...VID_ARR, Command.ANIMATE]);\n scrolling = await p.rx(RX_PACKET_SZ);\n scrolling = scrolling[0] != 0x00;\n });\n\n return scrolling;\n }\n\n async startScrolling() {\n await this.portMutex.acquire(async p => {\n await p.tx([...VID_ARR, Command.ANIMATE, 0x01]);\n });\n }\n\n async stopScrolling() {\n await this.portMutex.acquire(async p => {\n await p.tx([...VID_ARR, Command.ANIMATE, 0x00]);\n });\n }\n}\n","import { close, getUnusedPort } from '../../../environments/web/usb-serial/port.js';\nimport { PortMutex } from '../../../environments/web/usb-serial/PortMutex.js';\nimport { PortOperations } from '../../../environments/web/usb-serial/PortOperations.js';\nimport { CommandAbstractionLayer } from './CommandAbstractionLayer.js';\nimport { BitDepth } from './commands.js';\n\nexport class DefaultController extends CommandAbstractionLayer {\n async bootloader() {\n await super.bootloader();\n }\n\n async connect() {\n const port = await getUnusedPort();\n\n if (port?.connected) {\n await close(port);\n await port.open({ baudRate: 115200 });\n this.portMutex = new PortMutex(new PortOperations(port));\n } else {\n throw new Error('No Port Found');\n }\n }\n\n async draw(matrix) {\n switch (this.bitDepth ?? BitDepth.MONO_1BIT) {\n\n case (BitDepth.GRAY_8BIT):\n await super.drawGrayscale(matrix);\n break;\n\n case (BitDepth.MONO_1BIT):\n await super.draw(matrix);\n break;\n\n default:\n console.error(`Unsupported bitdepth: ${this.bitDepth}`);\n }\n }\n\n async verifyFirmware() {\n try {\n const version = await super.version();\n\n return version\n && version.major != undefined\n && version.minor != undefined\n && version.patch != undefined\n && version.preRelease != undefined;\n \n } catch {\n return false;\n }\n }\n\n async version() {\n return super.version();\n }\n}\n","export const Command = Object.freeze({\n /* 000 */ NOOP: 0x00,\n /* 'd' */ ANIMATION_DIAMOND: 0x64,\n /* 'b' */ ANIMATION_FIRE: 0x62,\n /* 'f' */ ANIMATION_FIREPLACE: 0x66,\n /* 'g' */ ANIMATION_GEAR: 0x67,\n /* 'r' */ ANIMATION_RING: 0x72,\n /* 'a' */ ANIMATION_STARTUP: 0x61,\n /* 'A' */ ANIMATION_STARTUP_ONCE: 0x41,\n /* 'e' */ BOOTLOADER: 0x65,\n /* 'm' */ DRAW_PWM: 0x6D,\n /* 'M' */ DRAW_PWM_BLOCKING: 0x4D,\n /* 'n' */ DRAW_SCALE: 0x6E,\n /* 'N' */ DRAW_SCALE_BLOCKING: 0x4E,\n /* 'c' */ FLUSH_CMD_QUEUE: 0x63,\n /* 't' */ TEST_PATTERN: 0x74,\n /* 'w' */ SET_CONST_PWM: 0x77,\n /* 's' */ SET_CONST_SCALE: 0x73,\n /* 'p' */ SET_PX_PWM: 0x70,\n /* 'q' */ SET_PX_SCALE: 0x71,\n /* 127 */ IDENTITY_STRING: 0x7F,\n});\n\nexport const IDENTITY_STR_LEN = 25;\n\nexport const IDENTITY_STR_REGEX = /^Sig\\sFW\\sLED\\sMatrix\\sFW\\sV(\\d+)\\.(\\d+)$/;\n","import { GAMMA } from '../../../hardware-constants.js';\nimport { Command, IDENTITY_STR_LEN } from './commands.js';\n\nexport class CommandAbstractionLayer {\n constructor(portMutex = null) {\n this.portMutex = portMutex;\n }\n\n async bootloader() {\n await this.portMutex.acquire(async p => {\n await p.tx([Command.BOOTLOADER]);\n });\n }\n\n async identityString() {\n let ident = null;\n\n await this.portMutex.acquire(async p => {\n await p.tx([Command.IDENTITY_STRING]);\n ident = await p.rx(IDENTITY_STR_LEN);\n });\n\n return String.fromCharCode(...ident);\n }\n\n async setPixelPwm(r, c, brightness) {\n await this.portMutex.acquire(\n async p => {\n await p.tx([Command.SET_PX_PWM, c, r, brightness]);\n }\n );\n }\n\n async setGlobalPwm(brightness) {\n await this.portMutex.acquire(\n async p => {\n await p.tx([Command.SET_CONST_PWM, brightness]);\n }\n );\n }\n\n async setMatrixPwm(matrix) {\n // Only execute the most recent call \n await this.portMutex.acquireIdempotent(\n 'drawMatrix', \n async p => {\n await p.tx(\n [Command.DRAW_PWM].concat(\n matrix.flat().map(v => \n GAMMA[Math.floor((v ?? 0) * 255)]\n )\n )\n );\n }\n );\n }\n\n async setPixelAnalog(r, c, brightness) {\n await this.portMutex.acquire(\n async p => {\n await p.tx([Command.SET_PX_SCALE, c, r, brightness]);\n }\n );\n }\n\n async setGlobalAnalog(brightness) {\n await this.portMutex.acquire(\n async p => {\n await p.tx([Command.SET_CONST_SCALE, brightness]);\n }\n );\n }\n\n async setMatrixAnalog(matrix) {\n // Only execute the most recent call \n await this.portMutex.acquireIdempotent(\n 'drawMatrix', \n async p => {\n await p.tx(\n [Command.DRAW_SCALE].concat(\n matrix.flat().map(v => \n GAMMA[Math.floor((v ?? 0) * 255)]\n )\n )\n );\n }\n );\n }\n}\n","import { close, getUnusedPort } from '../../../environments/web/usb-serial/port.js';\nimport { PortMutex } from '../../../environments/web/usb-serial/PortMutex.js';\nimport { PortOperations } from '../../../environments/web/usb-serial/PortOperations.js';\nimport { CommandAbstractionLayer } from './CommandAbstractionLayer.js';\nimport { IDENTITY_STR_REGEX } from './commands.js';\n\nexport class SigrootController extends CommandAbstractionLayer {\n async bootloader() {\n await super.bootloader();\n }\n\n async connect() {\n const port = await getUnusedPort();\n\n if (port?.connected) {\n await close(port);\n await port.open({ baudRate: 115200 });\n this.portMutex = new PortMutex(new PortOperations(port));\n }\n }\n\n async draw(matrix) {\n if (!this.#scaleInitialized) {\n await super.setGlobalAnalog(0x20);\n this.#scaleInitialized = true;\n } else {\n throw new Error('No Port Found');\n }\n\n await super.setMatrixPwm(matrix);\n }\n\n async verifyFirmware() { \n return await this.version() != null;\n }\n\n async version() {\n const ident = await super.identityString();\n const match = ident.match(IDENTITY_STR_REGEX);\n\n if (match && match.length == 3) {\n return {\n major: match[1],\n minor: match[2]\n }\n } else {\n return null;\n }\n }\n\n #scaleInitialized;\n}\n","import { PID, VID } from '../../../hardware-constants.js';\n\nconst filters = [{ vendorId: VID, productId: PID }];\n\nexport class DeviceSelectionCancelled extends Error {\n constructor() {\n super('User cancelled device selection.');\n this.name = this.constructor.name;\n this.date = new Date();\n }\n}\n\nasync function requestDevice() {\n try {\n if (navigator.serial.requestPort) {\n return await navigator.serial.requestDevice({ filters });\n } else {\n return null; // Web Worker\n }\n } catch (e) {\n switch (e.name) {\n case ('NotFoundError'):\n throw new DeviceSelectionCancelled();\n case ('SecurityError'): // No user gesture\n return null;\n default:\n throw e;\n }\n }\n}\n\nclass KnownDevices {\n used = new Set();\n unused = [];\n\n async getOrFetchUnused() {\n let device = this.unused.pop();\n\n if (!device) {\n const systemDevices = await navigator.hid.getDevices({ filters });\n this.#enqueueUnique(systemDevices);\n device = this.unused.pop();\n }\n\n if (!device) {\n const manualDevices = await requestDevice();\n this.#enqueueUnique([manualDevices]);\n device = this.unused.pop();\n }\n\n if (device) {\n this.used.add(device);\n }\n\n return device;\n }\n\n #enqueueUnique(devices) {\n if (devices) {\n for (const dev of devices) {\n if (dev && !this.used.has(dev) && !this.unused.includes(dev)) {\n this.unused.push(dev);\n }\n }\n }\n }\n}\n\nconst knownDevices = new KnownDevices();\n\n/**\n * Adds user-selected device to permitted device. Only for use outside of Web \n * Worker to establish permission for use within Web Worker.\n * @returns {null}\n */\nexport async function reqestDeviceForWorker() {\n const _ = await requestDevice();\n}\n\n/**\n * Never returns the same device twice. \n * @returns {(HIDDevice|null)}\n */\nexport async function getUnusedDevice() {\n return await knownDevices.getOrFetchUnused();\n}\n","import { pad } from './util.js';\n\nexport class HIDOperations {\n constructor(device) {\n this.#device = device;\n }\n\n async send(report, data) {\n if (data.length < report.bytes) {\n data = pad(data, report.bytes);\n } else if (data.length > report.bytes) {\n throw new Error('Unable to send report: too many bytes');\n }\n\n const buffer = new Uint8Array(data).buffer;\n\n if (report.feature) {\n await this.#device.sendFeatureReport(report.id, buffer);\n } else {\n await this.#device.sendReport(report.id, buffer);\n }\n }\n\n async request(report) {\n let reply = [];\n\n if (report.feature) {\n reply = await this.#device.receiveFeatureReport(report.id);\n } else {\n /* \n * HID input reports are used for unprompted data.\n * See WebHID `HIDInputReportEvent`\n */\n throw new Error('Invalid operation');\n }\n\n if (reply.byteLength != report.bytes) {\n const exp = report.bytes;\n const act = reply.byteLength;\n console.error(`reply length=${act} (expected ${exp})`);\n }\n\n return reply;\n }\n\n #device;\n}\n","export function pad(arr, len, val=0x00) {\n return arr.concat(new Array(len - arr.length).fill(val));\n}\n","export const Reports = {\n GLITTER_DEVICE_INFO: {\n id: 0x01,\n bytes: 307,\n feature: true,\n },\n GLITTER_BASIC_CMD: {\n id: 0x02,\n bytes: 16,\n feature: true,\n },\n GLITTER_GRID_PWM_CNTL: {\n id: 0x03,\n bytes: 306,\n feature: true,\n },\n GLITTER_GRID_PWM_CNTL: {\n id: 0x04,\n bytes: 306,\n feature: true,\n }\n}\n\nexport const Commands = {\n GLITTER_CMD_REBOOT: 0x00,\n GLITTER_CMD_SLEEP: 0x01,\n GLITTER_CMD_WAKE_ON_COMMAND: 0x02,\n GLITTER_CMD_SET_SLEEP_TIMEOUT: 0x03,\n GLITTER_CMD_SET_GLOBAL_BRIGHTNESS: 0x04,\n GLITTER_CMD_DRAW_PIXEL: 0x05,\n GLITTER_CMD_DRAW_LINE: 0x06\n}\n\nexport const BootMode = {\n BOOTSEL: 0x00,\n NORMAL: 0x01,\n}\n","import { GAMMA } from '../../../hardware-constants.js';\nimport { Commands, Reports } from './reports.js';\n\nexport class ReportAbstractionLayer {\n constructor(device = null) {\n this.device = device;\n }\n\n async info() {\n const infoRaw = await this.device.request(Reports.GLITTER_DEVICE_INFO);\n\n return {\n sleep_pin: infoRaw.getUint8(1),\n dip1_pin: infoRaw.getUint8(2),\n intb_pin: infoRaw.getUint8(3),\n state_flags: infoRaw.getUint8(4),\n id_reg: infoRaw.getUint8(5),\n config_reg: infoRaw.getUint8(6),\n global_brightness: infoRaw.getUint8(7),\n display_width: infoRaw.getUint8(8),\n display_height: infoRaw.getUint8(9),\n timeout_ms: infoRaw.getUint32(10),\n version_major: infoRaw.getUint8(14),\n version_minor: infoRaw.getUint8(15),\n };\n }\n\n async wake() {\n await this.device.send(\n Reports.GLITTER_BASIC_CMD,\n [Commands.GLITTER_CMD_SLEEP, false]\n );\n }\n\n async sleep() {\n await this.device.send(\n Reports.GLITTER_BASIC_CMD,\n [Commands.GLITTER_CMD_SLEEP, true]\n );\n }\n\n async disableSleep() {\n await this.device.send(\n Reports.GLITTER_BASIC_CMD, \n [Commands.GLITTER_CMD_SET_SLEEP_TIMEOUT, 0xff, 0xff, 0xff, 0xff]\n );\n }\n\n async disableDeepSleep() {\n await this.device.send(\n Reports.GLITTER_BASIC_CMD, \n [Commands.GLITTER_CMD_WAKE_ON_COMMAND, 0x01]\n );\n }\n\n async disableSleepTimer() {\n await this.device.send(\n Reports.GLITTER_BASIC_CMD, \n [Commands.GLITTER_CMD_SET_SLEEP_TIMEOUT, 0x00, 0x00, 0x00, 0x00]\n );\n }\n \n async enableDeepSleep() {\n await this.device.send(\n Reports.GLITTER_BASIC_CMD, \n [Commands.GLITTER_CMD_WAKE_ON_COMMAND, 0x00]\n );\n }\n\n async enableSleepTimer(milliseconds) {\n const view = new DataView(new ArrayBuffer(4));\n const littleEndian = false;\n view.setInt32(0, milliseconds, littleEndian);\n await this.device.send(\n Reports.GLITTER_BASIC_CMD, \n [\n Commands.GLITTER_CMD_SET_SLEEP_TIMEOUT, \n view.getUint8(0), \n view.getUint8(1), \n view.getUint8(2), \n view.getUint8(3),\n ]\n );\n }\n\n async reboot(mode) {\n await this.device.send(\n Reports.GLITTER_BASIC_CMD, \n [Commands.GLITTER_CMD_REBOOT, mode]\n );\n }\n\n async drawMatrix(matrix) {\n await this.device.send(\n Reports.GLITTER_GRID_PWM_CNTL,\n matrix.flat().map(v => GAMMA[Math.floor((v ?? 0) * 255)])\n );\n }\n\n async drawPixel(r, c, brightness) {\n await this.device.send(\n Reports.GLITTER_BASIC_CMD,\n [Commands.GLITTER_CMD_DRAW_PIXEL, c, r, brightness]\n );\n }\n\n async drawLine({r1, c1}, {r2, c2}, brightness) {\n await this.device.send(\n Reports.GLITTER_BASIC_CMD,\n [Commands.GLITTER_CMD_DRAW_PIXEL, r1, c1, r2, c2, brightness]\n );\n }\n\n device;\n}\n","import { HEIGHT, WIDTH } from '../../../hardware-constants.js';\nimport { getUnusedDevice } from '../../../environments/web/usb-hid/device.js';\nimport { HIDOperations } from '../../../environments/web/usb-hid/HIDOperations.js';\nimport { ReportAbstractionLayer } from './ReportAbstractionLayer.js';\nimport { BootMode } from './reports.js';\n\nexport class SparkleController extends ReportAbstractionLayer {\n async bootloader() {\n await super.reboot(BootMode.BOOTSEL);\n }\n\n async connect() {\n const device = await getUnusedDevice();\n\n if (device) {\n await device.open();\n this.device = new HIDOperations(device);\n } else {\n throw new Error('No Device Found');\n }\n }\n \n async draw(matrix) {\n await super.drawMatrix(matrix);\n }\n\n async verifyFirmware() {\n try {\n const info = await super.info();\n return (\n info.display_height == HEIGHT &&\n info.display_width == WIDTH\n );\n } catch {\n return false;\n }\n }\n\n async version() {\n const info = await super.info();\n\n if (info.version_major != undefined \n && info.version_minor != undefined\n && (info.version_major > 0 || info.version_minor > 0)) {\n return {\n major: info.version_major,\n minor: info.version_minor\n }\n } else {\n // Sparkle <=1.1.1: Glitter version unavailable \n return { major: 1, minor: 0 };\n }\n }\n}\n","import { DefaultController } from './supported-firmware/FrameworkComputer/inputmodule-rs/DefaultController.js';\nimport { SigrootController } from './supported-firmware/sigroot/FW_LED_Matrix_Firmware/SigrootController.js';\nimport { SparkleController } from './supported-firmware/vddCore/sparkle-fw16/SparkleController.js';\n\nexport class HardwareControllerFactory {\n static async detectSerial() {\n const c1 = new DefaultController();\n const c2 = new SigrootController();\n\n await c1.connect();\n if (await c1.verifyFirmware()) {\n return c1;\n }\n \n await c2.connect()\n if (await c2.verifyFirmware()) {\n return c2;\n } \n \n return null;\n }\n\n static async detectHID() {\n const c1 = new SparkleController();\n\n await c1.connect();\n if (await c1.verifyFirmware()) {\n return c1;\n } \n \n return null;\n }\n}\n"],"names":["VID_ARR","GAMMA","Object","freeze","filters","usbVendorId","usbProductId","PortSelectionCancelled","Error","constructor","super","this","name","date","Date","PortUnavailable","async","requestPort","navigator","serial","assign","pickedByUser","e","knownPorts","used","Set","unused","getOrFetchUnused","port","pop","getPorts","enqueueUnique","manualPort","add","ports","has","includes","push","getUnusedPort","close","message","PortMutex","portOperations","lockName","Math","random","toString","deduper","Map","portOps","acquire","fn","trace","stack","enqueue","console","error","acquireIdempotent","key","info","set","execDedupedOp","locks","request","get","delete","PortOperations","rx","length","timeout","readable","locked","response","reader","getReader","timeoutHandle","setTimeout","cancel","value","done","read","clearTimeout","releaseLock","tx","buffer","writable","writer","getWriter","write","Uint8Array","Command","ANIMATE","BRIGHTNESS","BOOTLOADER","DRAW","DRAW_GREY_COL_BUFFER","GAME_CTRL","GAME_STATUS","PANIC","PATTERN","SLEEP","STAGE_GREY_COL","START_GAME","VERSION","Pattern","DISPLAY_LOTUS_HORIZONTAL","DISPLAY_LOTUS_VERTICAL","DISPLAY_PANIC","DOUBLE_GRADIENT","FULL_BRIGHTNESS","GRADIENT","PERCENTAGE","ZIG_ZAG","BitDepth","GRAY_8BIT","MONO_1BIT","CommandAbstractionLayer$1","portMutex","bootloader","p","brightness","draw","matrix","index","output","fill","r","c","drawGrayscale","buffers","Array","from","_","floor","i","asleep","sleep","wake","pattern","percent","min","max","round","version","ver","major","minor","patch","preRelease","scrolling","startScrolling","stopScrolling","DefaultController","CommandAbstractionLayer","connect","connected","open","baudRate","bitDepth","verifyFirmware","undefined","NOOP","ANIMATION_DIAMOND","ANIMATION_FIRE","ANIMATION_FIREPLACE","ANIMATION_GEAR","ANIMATION_RING","ANIMATION_STARTUP","ANIMATION_STARTUP_ONCE","DRAW_PWM","DRAW_PWM_BLOCKING","DRAW_SCALE","DRAW_SCALE_BLOCKING","FLUSH_CMD_QUEUE","TEST_PATTERN","SET_CONST_PWM","SET_CONST_SCALE","SET_PX_PWM","SET_PX_SCALE","IDENTITY_STRING","IDENTITY_STR_REGEX","identityString","ident","String","fromCharCode","setPixelPwm","setGlobalPwm","setMatrixPwm","concat","flat","map","v","setPixelAnalog","setGlobalAnalog","setMatrixAnalog","SigrootController","scaleInitialized","match","vendorId","productId","DeviceSelectionCancelled","requestDevice","knownDevices","device","systemDevices","hid","getDevices","manualDevices","devices","dev","HIDOperations","send","report","data","bytes","arr","len","val","pad","feature","sendFeatureReport","id","sendReport","reply","receiveFeatureReport","byteLength","exp","act","Reports","Commands","BootMode","ReportAbstractionLayer","infoRaw","sleep_pin","getUint8","dip1_pin","intb_pin","state_flags","id_reg","config_reg","global_brightness","display_width","display_height","timeout_ms","getUint32","version_major","version_minor","disableSleep","disableDeepSleep","disableSleepTimer","enableDeepSleep","enableSleepTimer","milliseconds","view","DataView","ArrayBuffer","setInt32","reboot","mode","drawMatrix","drawPixel","drawLine","r1","c1","r2","c2","SparkleController","getUnusedDevice","detectSerial","detectHID"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -5,7 +5,11 @@ export class PortOperations {
|
|
|
5
5
|
|
|
6
6
|
async rx(length, timeout=3000) {
|
|
7
7
|
if (this.#port === null) {
|
|
8
|
-
throw new Error('attempted RX
|
|
8
|
+
throw new Error('attempted RX on uninitialized port.');
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
if (this.#port.readable === null) {
|
|
12
|
+
throw new Error('attempted RX on closed port.');
|
|
9
13
|
}
|
|
10
14
|
|
|
11
15
|
/*
|
|
@@ -37,7 +41,11 @@ export class PortOperations {
|
|
|
37
41
|
|
|
38
42
|
async tx(buffer) {
|
|
39
43
|
if (this.#port === null) {
|
|
40
|
-
throw new Error('attempted TX
|
|
44
|
+
throw new Error('attempted TX on uninitialized port.');
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
if (this.#port.writable === null) {
|
|
48
|
+
throw new Error('attempted TX on closed port.');
|
|
41
49
|
}
|
|
42
50
|
|
|
43
51
|
/*
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { PID, VID } from '
|
|
1
|
+
import { PID, VID } from '../../../hardware-constants.js';
|
|
2
2
|
|
|
3
3
|
const filters = [{ usbVendorId: VID, usbProductId: PID }];
|
|
4
4
|
|
|
@@ -21,7 +21,10 @@ export class PortUnavailable extends Error {
|
|
|
21
21
|
async function requestPort() {
|
|
22
22
|
try {
|
|
23
23
|
if (navigator.serial.requestPort) {
|
|
24
|
-
return
|
|
24
|
+
return Object.assign(
|
|
25
|
+
await navigator.serial.requestPort({ filters }),
|
|
26
|
+
{ pickedByUser: true }
|
|
27
|
+
);
|
|
25
28
|
} else {
|
|
26
29
|
return null; // Web Worker
|
|
27
30
|
}
|
|
@@ -47,8 +50,8 @@ class KnownPorts {
|
|
|
47
50
|
let port = this.unused.pop();
|
|
48
51
|
|
|
49
52
|
if (!port) {
|
|
50
|
-
const
|
|
51
|
-
this.#enqueueUnique(
|
|
53
|
+
const knownPorts = await navigator.serial.getPorts({ filters });
|
|
54
|
+
this.#enqueueUnique(knownPorts);
|
|
52
55
|
port = this.unused.pop();
|
|
53
56
|
}
|
|
54
57
|
|
package/src/index.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
export
|
|
2
|
-
export
|
|
3
|
-
export
|
|
4
|
-
export
|
|
5
|
-
export
|
|
6
|
-
export
|
|
7
|
-
export
|
|
1
|
+
export { HEIGHT, WIDTH } from './hardware-constants.js'
|
|
2
|
+
export { HardwareControllerFactory } from './HardwareControllerFactory.js';
|
|
3
|
+
export { DefaultController } from './supported-firmware/FrameworkComputer/inputmodule-rs/DefaultController.js';
|
|
4
|
+
export { BitDepth, Pattern } from './supported-firmware/FrameworkComputer/inputmodule-rs/commands.js';
|
|
5
|
+
export { SigrootController } from './supported-firmware/sigroot/FW_LED_Matrix_Firmware/SigrootController.js'
|
|
6
|
+
export { SparkleController } from './supported-firmware/vddCore/sparkle-fw16/SparkleController.js';
|
|
7
|
+
export { DeviceSelectionCancelled, reqestDeviceForWorker } from './environments/web/usb-hid/device.js';
|
|
8
|
+
export { PortSelectionCancelled, PortUnavailable, requestPortForWorker } from './environments/web/usb-serial/port.js';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { GAMMA, HEIGHT, VID_ARR, WIDTH } from '../../../hardware-constants.js';
|
|
2
|
-
import { Command, RX_PACKET_SZ } from './commands.js';
|
|
2
|
+
import { Command, Pattern, RX_PACKET_SZ } from './commands.js';
|
|
3
3
|
|
|
4
4
|
export class CommandAbstractionLayer {
|
|
5
5
|
constructor(portMutex = null) {
|
|
@@ -96,6 +96,10 @@ export class CommandAbstractionLayer {
|
|
|
96
96
|
}
|
|
97
97
|
|
|
98
98
|
async percent(percent) {
|
|
99
|
+
percent = Math.min(percent, 100);
|
|
100
|
+
percent = Math.max(percent, 0);
|
|
101
|
+
percent = Math.round(percent);
|
|
102
|
+
|
|
99
103
|
await this.portMutex.acquireIdempotent(
|
|
100
104
|
'drawMatrix',
|
|
101
105
|
async p => {
|
|
@@ -120,4 +124,28 @@ export class CommandAbstractionLayer {
|
|
|
120
124
|
|
|
121
125
|
return ver;
|
|
122
126
|
}
|
|
127
|
+
|
|
128
|
+
async scrolling() {
|
|
129
|
+
let scrolling = false;
|
|
130
|
+
|
|
131
|
+
await this.portMutex.acquire(async p => {
|
|
132
|
+
await p.tx([...VID_ARR, Command.ANIMATE]);
|
|
133
|
+
scrolling = await p.rx(RX_PACKET_SZ);
|
|
134
|
+
scrolling = scrolling[0] != 0x00;
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
return scrolling;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
async startScrolling() {
|
|
141
|
+
await this.portMutex.acquire(async p => {
|
|
142
|
+
await p.tx([...VID_ARR, Command.ANIMATE, 0x01]);
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
async stopScrolling() {
|
|
147
|
+
await this.portMutex.acquire(async p => {
|
|
148
|
+
await p.tx([...VID_ARR, Command.ANIMATE, 0x00]);
|
|
149
|
+
});
|
|
150
|
+
}
|
|
123
151
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { close, getUnusedPort } from '../../../web-serial/port.js';
|
|
2
|
-
import { PortMutex } from '../../../web-serial/PortMutex.js';
|
|
3
|
-
import { PortOperations } from '../../../web-serial/PortOperations.js';
|
|
1
|
+
import { close, getUnusedPort } from '../../../environments/web/usb-serial/port.js';
|
|
2
|
+
import { PortMutex } from '../../../environments/web/usb-serial/PortMutex.js';
|
|
3
|
+
import { PortOperations } from '../../../environments/web/usb-serial/PortOperations.js';
|
|
4
4
|
import { CommandAbstractionLayer } from './CommandAbstractionLayer.js';
|
|
5
5
|
import { BitDepth } from './commands.js';
|
|
6
6
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { close, getUnusedPort } from '../../../web-serial/port.js';
|
|
2
|
-
import { PortMutex } from '../../../web-serial/PortMutex.js';
|
|
3
|
-
import { PortOperations } from '../../../web-serial/PortOperations.js';
|
|
1
|
+
import { close, getUnusedPort } from '../../../environments/web/usb-serial/port.js';
|
|
2
|
+
import { PortMutex } from '../../../environments/web/usb-serial/PortMutex.js';
|
|
3
|
+
import { PortOperations } from '../../../environments/web/usb-serial/PortOperations.js';
|
|
4
4
|
import { CommandAbstractionLayer } from './CommandAbstractionLayer.js';
|
|
5
5
|
import { IDENTITY_STR_REGEX } from './commands.js';
|
|
6
6
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { HEIGHT, WIDTH } from '../../../hardware-constants.js';
|
|
2
|
-
import { getUnusedDevice } from '../../../web-hid/device.js';
|
|
3
|
-
import { HIDOperations } from '../../../web-hid/HIDOperations.js';
|
|
2
|
+
import { getUnusedDevice } from '../../../environments/web/usb-hid/device.js';
|
|
3
|
+
import { HIDOperations } from '../../../environments/web/usb-hid/HIDOperations.js';
|
|
4
4
|
import { ReportAbstractionLayer } from './ReportAbstractionLayer.js';
|
|
5
5
|
import { BootMode } from './reports.js';
|
|
6
6
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|