diff --git a/docs/Commands.js b/docs/Commands.js index 4120397..ff21d4b 100644 --- a/docs/Commands.js +++ b/docs/Commands.js @@ -993,6 +993,17 @@ function commandDRAW(args) { } } +async function commandWS_LED(args) { + // フルカラーLED用の色情報を送信する + const numLED = args[0], numRepeat = args.length > 1 ? args[1] : 1; + if (numLED <= 0 || numRepeat <= 0 || numLED * 3 > ARRAY_SIZE) return; + const colorData = []; + for (let i = 0; i < numLED; i++) { + colorData.push([readArray(i * 3 + 0) & 0xff, readArray(i * 3 + 1) & 0xff, readArray(i * 3 + 2) & 0xff]); + } + await wsLedManager.sendColors(colorData, numRepeat, ["led"]); +} + async function commandSEC_PUBKEY(args) { // Ed25519の秘密鍵から公開鍵を求める // args[0] : 公開鍵(出力)の仮想アドレス diff --git a/docs/Compiler.js b/docs/Compiler.js index 261f539..4adcf1e 100644 --- a/docs/Compiler.js +++ b/docs/Compiler.js @@ -360,7 +360,7 @@ const basicCommands = { "IoT.OUT": {func: commandIoT_OUT, minArg: 1, maxArg: 3}, "SWITCH" : {func: commandSWITCH, minArg: 0, maxArg: 2}, "DRAW" : {func: commandDRAW, minArg: 2, maxArg: 5}, - "WS.LED" : null, + "WS.LED" : {func: commandWS_LED, minArg: 1, maxArg: 2}, "SEC.PUBKEY" : {func: commandSEC_PUBKEY, minArg: 2, maxArg: 2}, "SEC.SIGN" : {func: commandSEC_SIGN, minArg: 4, maxArg: 4}, "PC.CLEAR" : {func: commandPC_CLEAR, minArg: 1, maxArg: 1}, diff --git a/docs/IO.js b/docs/IO.js index 1698c62..8f3fa73 100644 --- a/docs/IO.js +++ b/docs/IO.js @@ -526,3 +526,51 @@ const i2cManager = (function() { "performI2C": performI2C, }; })(); + +const wsLedManager = (function() { + // 以下の仕様の関数(非同期可)の配列 + // 引数 + // data : 色データ (3要素の配列の、1要素以上の配列) + // 各要素となる配列は、色を表す0~255の値を前(先に送信する)から順に格納する + // WS2812では緑、赤、青 (GRB) の順 + // numRepeat : 繰り返し回数 (1以上の整数) + // ports : 出力対象のポートID (文字列) の配列 + // 返り値 + // ドントケア + const wsLedDevices = []; + + // デバイスを追加する + function addDevice(device) { + wsLedDevices.push(device); + } + + // LEDの色情報を送信する + // 引数 + // data : 色データ (3要素の配列の、1要素以上の配列) + // 各要素となる配列は、色を表す0~255の値を前(先に送信する)から順に格納する + // WS2812では緑、赤、青 (GRB) の順 + // numRepeat : 繰り返し回数 (1以上の整数) + // ports : 出力対象のポートID (文字列) の配列 + // 返り値 + // なし + async function sendColors(data, numRepeat, ports) { + console.log(data, numRepeat, ports); + const devicePromises = []; + for (let i = 0; i < wsLedDevices.length; i++) { + const deviceFunction = wsledDevicees[i]; + devicePromises.push(new Promise(async function(resolve, reject) { + try { + resolve(await deviceFunction(data, numRepeat, ports)); + } catch (error) { + reject(error); + } + })); + } + await Promise.allSettled(devicePromises); + } + + return { + "addDevice": addDevice, + "sendColors": sendColors, + }; +})(); diff --git a/docs/Usr.js b/docs/Usr.js index f261c1b..348d3c1 100644 --- a/docs/Usr.js +++ b/docs/Usr.js @@ -1,5 +1,10 @@ "use strict"; +const wsLedPorts = { + 0x5000: [null, null, null, null, null, "in3", "in4", null, null, null, "in1", "in2"], + 0x5001: ["out1", "out2", "out3", "out4", null, "led", null, null, "out5", "out6"], +}; + const apiMap = { 0x2100: { // rnd "tableAddr": 0xC0, @@ -174,8 +179,37 @@ const apiMap = { 0x212E: { // ws_led "tableAddr": 0xEE, "returnsValue": false, - "func": function(env, countrepeat, data, gpiomask) { - throw "Not implemented: WS_LED"; + "func": async function(env, countrepeat, data, gpiomask) { + console.log(countrepeat, data.toString(16), gpiomask.toString(16)); + // 出力先のポートを取得する + const gpioMaskUpper = (gpiomask >>> 16) & 0xffff, gpioMaskLower = gpiomask & 0xffff; + if (!(gpioMaskUpper in wsLedPorts) || gpioMaskLower >= 0x4000) return; + const portStatus = ioManager.getPortStatus(); + const portList = wsLedPorts[gpioMaskUpper]; + const portsToOutput = []; + for (let i = 0; i < portList.length; i++) { + if ((gpioMaskLower >> (2 + i)) & 1) { + const port = portList[i]; + if (port in portStatus && portStatus[port].status === "output_binary") { + portsToOutput.push(port); + } + } + } + if (portsToOutput.length === 0) return; + // 出力するデータを取得する + // TODO + // ・端数のデータも出力する + // ・短い間に連続して呼ばれた場合、切らずに前回の続きとして出力する + const colorData = []; + for (let i = 0; i < countrepeat - 2; i += 3) { + const colorElement = [0, 0, 0]; + for (let j = 0; j < 3; j++) { + colorElement[j] = env.readMemory((data + i + j) >>> 0, 1, false); + } + colorData.push(colorElement); + } + // 出力する + await wsLedManager.sendColors(colorData, 1, portsToOutput); }, }, };