diff --git a/apps.json b/apps.json index 641c7b340..3257454cf 100644 --- a/apps.json +++ b/apps.json @@ -1512,5 +1512,17 @@ "data": [ {"name": "ballmaze.json"} ] + }, + { "id": "hidjoystick", + "name": "Bluetooth Joystick", + "shortName": "Joystick", + "icon": "app.png", + "version":"0.01", + "description": "Use the accelerometer as Joystick with 5 buttons.", + "tags": "bluetooth", + "storage": [ + {"name":"hidjoystick.app.js","url":"app.js"}, + {"name":"hidjoystick.img","url":"app-icon.js","evaluate":true} + ] } ] diff --git a/apps/boot/boot0.js b/apps/boot/boot0.js index dd3b3a9ba..9b9d4bb69 100644 --- a/apps/boot/boot0.js +++ b/apps/boot/boot0.js @@ -4,7 +4,7 @@ E.setFlags({pretokenise:1}); var s = require('Storage').readJSON('setting.json',1)||{}; if (s.ble!==false) { if (s.HID) { // Human interface device - Bangle.HID = E.toUint8Array(atob("BQEJBqEBhQIFBxngKecVACUBdQGVCIEClQF1CIEBlQV1AQUIGQEpBZEClQF1A5EBlQZ1CBUAJXMFBxkAKXOBAAkFFQAm/wB1CJUCsQLABQwJAaEBhQEVACUBdQGVAQm1gQIJtoECCbeBAgm4gQIJzYECCeKBAgnpgQIJ6oECwA==")); + Bangle.HID = E.toUint8Array(atob("BQEJBqEBhQIFBxngKecVACUBdQGVCIEClQF1CIEBlQV1AQUIGQEpBZEClQF1A5EBlQZ1CBUAJXMFBxkAKXOBAAkFFQAm/wB1CJUCsQLABQwJAaEBhQEVACUBdQGVAQm1gQIJtoECCbeBAgm4gQIJzYECCeKBAgnpgQIJ6oECwAUBCQShAYUDCQGhAAUJGQEpBRUAJQGVBXUBgQKVA3UBgQMFAQkwCTEVgSV/dQiVAoECwMA=")); NRF.setServices({}, {uart:true, hid:Bangle.HID}); } } diff --git a/apps/hidjoystick/app-icon.js b/apps/hidjoystick/app-icon.js new file mode 100644 index 000000000..2e5609d94 --- /dev/null +++ b/apps/hidjoystick/app-icon.js @@ -0,0 +1 @@ +E.toArrayBuffer(atob("MDCEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADd3QAAAAAAAAAAAAAAAAAAAAAAAAAAAN3d3d0AAAAAAAAAAAAAAAAAAAAAAAAADd3d3d3QAAAAAAAAAAAAAAAAAAAAAAAADd3d3d3QAAAAAAAAAAAAAAAAAAAAAAAA3d3d3d3dAAAAAAAAAAAAAAAAAAAAAAAA3d3d3d3dAAAAAAAAAAAAAAAAAAAAAAAA3d3d3d3dAAAAAAAAAAAAAAAAAAAAAAAA3d3d3d3dAAAAAAAAAAAAAAAAAAAAAAAADd3d3d3QAAAAAAAAAAAAAAAAAAAAAAAADd3d3d3QAAAAAAAAAAAAAAAAAAAAAAAAAN3d3d0AAAAAAAAAAAAAAAAAAAAAAAAAAABN1AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAzMwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAzMwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAzMwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAzMwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAzMwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAzMwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAzMwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAzMwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAzMwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAREQAAAAAAAAAAAAAAAAAAAAAAAAAAABEREREAAAAAAAAAAAAAAAAAAADd3dAAAREREREQAAAAAAAAAAAAAAAAAADd3dAAAREREREQAAAAAAAAAAAAAAAIiIiIiIiIiIiIiIiIiIiIiIiAAAAAAACIiIiIiIiIiIiIiIiIiIiIiIiIAAAAAACIiIiIiIiIiIiIiIiIiIiIiIiIAAAAAACIiIiIiIiIiIiIiIiIiIiIiIiIAAAAAACIiIiIiIiIiIiIiIiIiIiIiIiIAAAAAACIiIiIiIiIiIiIiIiIiIiIiIiIAAAAAACIiIiIiIiIiIiIiIiIiIiIiIiIAAAAAACIiIiIiIiIiIiIiIiIiIiIiIiIAAAAAACIiIiIiIiIiIiIiIiIiIiIiIiIAAAAAACIiIiIiIiIiIiIiIiIiIiIiIiIAAAAAACIiIiIiIiIiIiIiIiIiIiIiIiIAAAAAAAIiIiIiIiIiIiIiIiIiIiIiIiAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==")) diff --git a/apps/hidjoystick/app.js b/apps/hidjoystick/app.js new file mode 100644 index 000000000..25e71e9b8 --- /dev/null +++ b/apps/hidjoystick/app.js @@ -0,0 +1,59 @@ +var sendInProgress = false; // Only send one message at a time, do not flood + +const sendHid = function (x, y, btn1, btn2, btn3, btn4, btn5, cb) { + try { + const buttons = (btn5<<4) | (btn4<<3) | (btn3<<2) | (btn2<<1) | (btn1<<0); + if (!sendInProgress) { + sendInProgress = true; + NRF.sendHIDReport([3, buttons, x, y], () => { + sendInProgress = false; + if (cb) cb(); + }); + } + } catch(e) { + print(e); + } +}; + +function drawApp() { + g.clear(); + g.setFont("6x8",2); + g.setFontAlign(0,0); + g.drawString("Joystick", 120, 120); + const d = g.getWidth() - 18; + + function c(a) { + return { + width: 8, + height: a.length, + bpp: 1, + buffer: (new Uint8Array(a)).buffer + }; + } + + g.drawImage(c([16,56,124,254,16,16,16,16]),d,40); + g.drawImage(c([16,16,16,16,254,124,56,16]),d,194); + g.drawImage(c([0,8,12,14,255,14,12,8]),d,116); +} + +function update() { + const btn1 = BTN1.read(); + const btn2 = BTN2.read(); + const btn3 = BTN3.read(); + const btn4 = BTN4.read(); + const btn5 = BTN5.read(); + const acc = Bangle.getAccel(); + var x = acc.x*-127; + var y = acc.y*-127; + + // check limits + if (x > 127) x = 127; + else if (x < -127) x = -127; + if (y > 127) y = 127; + else if (y < -127) y = -127; + + sendHid(x & 0xff, y & 0xff, btn1, btn2, btn3, btn4, btn5); +} + +drawApp(); +setInterval(update, 100); // 10 Hz