diff --git a/apps/bad/ChangeLog b/apps/bad/ChangeLog new file mode 100644 index 000000000..263d4078d --- /dev/null +++ b/apps/bad/ChangeLog @@ -0,0 +1 @@ +0.01: attempt to import diff --git a/apps/bad/README.md b/apps/bad/README.md new file mode 100644 index 000000000..156b34cbf --- /dev/null +++ b/apps/bad/README.md @@ -0,0 +1,8 @@ +# Bad Apple demo ![](app.png) + +"Bad Apple" is like "Hello World" for graphics system. So this is it +for Bangle.js2. Watch have no speaker, so vibration motor is used, +instead, to produce (pretty quiet) sound. + +Tools for preparing bad.araw and bad.vraw are in prep/ directory. Full +3 minute demo should actually fit to the watch. \ No newline at end of file diff --git a/apps/bad/app-icon.js b/apps/bad/app-icon.js new file mode 100644 index 000000000..e153d6397 --- /dev/null +++ b/apps/bad/app-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEwgIifiAFWj//Aod///gAgMH///+AFBn4FB/AQDAoYEB//8gEBAokDAoX+ApguCAAIFqGoYFNLIZHBApZxFAoyDCAoqJCSoqsBUIcPAoKtF4AFBJAS/DHIQAeA=")) diff --git a/apps/bad/app.png b/apps/bad/app.png new file mode 100644 index 000000000..e3e3dad82 Binary files /dev/null and b/apps/bad/app.png differ diff --git a/apps/bad/bad.app.js b/apps/bad/bad.app.js new file mode 100644 index 000000000..453f0003c --- /dev/null +++ b/apps/bad/bad.app.js @@ -0,0 +1,65 @@ +/* sox Rear_Right.wav -r 4k -b 8 -c 1 -e unsigned-integer 0.raw vol 2 + aplay -r 4000 /tmp/0.raw +*/ + +/* https://forum.espruino.com/conversations/348912/ */ + +let pin = D19; + +function play(name, callback) { + function playChar(offs) { + var l = 10240; + var s = require("Storage").read(name, offs, l); + //print("Waveform " + name + " " + s.length); + if (!s.length) { + digitalWrite(pin,0); + if (callback) callback(); + return; + } + var w = new Waveform(s.length); + var b = w.buffer; + b.set(s); + //print("Buffer", s.length); + //for (var i=s.length-1;i>=0;i--)b[i]/=4; + w.startOutput(pin, 4000); + w.on("finish", function(buf) { + playChar(offs+l); + }); + } + analogWrite(pin, 0.1, {freq:40000}); + playChar(0); +} + +function video(name, callback) { + function frame() { + var s = require("Storage").read(name, offs, l); + if (!s) + return; + g.drawImage(s, 0, 0, { scale: 2 }); + g.flip(); + offs += l; + } + g.clear(); + var offs = 0; + //var l = 3875; for 176x176 + //var l = 515; for 64x64 + var l = 971; + setInterval(frame, 200); +} + +function run() { + clearInterval(i); + print("Running"); + play('bad.araw'); + t1 = getTime(); + video('bad.vraw'); + print("100 frames in ", getTime()-t1); + // 1.7s, unscaled + // 2.68s, scale 1.01 + // 5.73s, scale 2.00 + // 9.93s, scale 2, full screen + // 14.4s scaled. 176/64 +} + +print("Loaded"); +i = setInterval(run, 100); \ No newline at end of file diff --git a/apps/bad/bad.araw b/apps/bad/bad.araw new file mode 100644 index 000000000..cfe5f4fdd Binary files /dev/null and b/apps/bad/bad.araw differ diff --git a/apps/bad/bad.vraw b/apps/bad/bad.vraw new file mode 100644 index 000000000..ff8fec1b0 Binary files /dev/null and b/apps/bad/bad.vraw differ diff --git a/apps/bad/metadata.json b/apps/bad/metadata.json new file mode 100644 index 000000000..882b7f066 --- /dev/null +++ b/apps/bad/metadata.json @@ -0,0 +1,16 @@ +{ "id": "bad", + "name": "Bad Apple", + "version":"0.01", + "description": "Bad Apple demo", + "icon": "app.png", + "readme": "README.md", + "supports" : ["BANGLEJS2"], + "allow_emulator": false, + "tags": "game", + "storage": [ + {"name":"bad.app.js","url":"bad.app.js"}, + {"name":"bad.vraw","url":"bad.vraw"}, + {"name":"bad.araw","url":"bad.araw"}, + {"name":"bad.img","url":"app-icon.js","evaluate":true} + ] +} diff --git a/apps/bad/prep/img_convert.py b/apps/bad/prep/img_convert.py new file mode 100755 index 000000000..2edbbdef5 --- /dev/null +++ b/apps/bad/prep/img_convert.py @@ -0,0 +1,32 @@ +#!/usr/bin/python3 + +from PIL import Image +import os + +def convert_image(input_path, output_width, output_height): + img = Image.open(input_path) + img_resized = img.resize((output_width, output_height), Image.ANTIALIAS) + img_gray = img_resized.convert('L') + img_1bpp = img_gray.point(lambda x: 0 if x < 128 else 255, '1') + return img_1bpp + +def convert_and_append_header(input_directory, size): + input_files = [f for f in os.listdir(input_directory) if f.startswith("image_") and f.endswith(".png")] + input_files.sort() + header_bytes = size.to_bytes(1, byteorder='big') + size.to_bytes(1, byteorder='big') + b'\x01' + + for i, input_file in enumerate(input_files): + input_path = os.path.join(input_directory, input_file) + img_1bpp = convert_image(input_path, size, size) + output_file = input_path + ".raw" + + with open(output_file, 'wb') as raw_file: + raw_file.write(header_bytes) + raw_file.write(img_1bpp.tobytes()) + +if __name__ == "__main__": + input_directory = "." # Replace with the path to your image directory + output_width = 88 + output_file_path = "output_with_header.raw" # Replace with the desired output file path + + convert_and_append_header(input_directory, output_width) diff --git a/apps/bad/prep/run b/apps/bad/prep/run new file mode 100755 index 000000000..907e711f3 --- /dev/null +++ b/apps/bad/prep/run @@ -0,0 +1,20 @@ +#!/bin/bash + +# aplay -r 4000 /tmp/0.raw +#bug: Terminal exists on b.js, it is dumb terminal, not vt100. + +rm image_*.png image_*.png.raw output.wav ../bad.araw ../bad.vraw + +I=bad.mp4 +S=1:18 +E=1:50 + +ffmpeg -i $I -ss $S -to $E -vn -acodec pcm_u8 -ar 4000 -ac 1 -y output.wav +./wav_divider.py +mv output.raw ../bad.araw + +ffmpeg -i $I -ss $S -to $E -r 5 -vf fps=5 image_%04d.png +./img_convert.py +cat *.png.raw > ../bad.vraw + +ls -al ../bad.* diff --git a/apps/bad/prep/wav_divider.py b/apps/bad/prep/wav_divider.py new file mode 100755 index 000000000..9ce08e28b --- /dev/null +++ b/apps/bad/prep/wav_divider.py @@ -0,0 +1,13 @@ +#!/usr/bin/python3 + +def divide_bytes(input_file, output_file): + with open(input_file, 'rb') as infile: + with open(output_file, 'wb') as outfile: + byte = infile.read(1) + while byte: + # Convert byte to integer, divide by 4, and write back as byte + new_byte = bytes([int.from_bytes(byte, byteorder='big') // 3]) + outfile.write(new_byte) + byte = infile.read(1) + +divide_bytes("output.wav", "output.raw")