diff --git a/apps.json b/apps.json index eb90e1240..e31fd9e57 100644 --- a/apps.json +++ b/apps.json @@ -384,6 +384,18 @@ {"name":"*hrings","url":"hypno-rings-icon.js","evaluate":true} ] }, + { "id": "morse", + "name": "Morse Code", + "icon": "morse-code.png", + "description": "Learn morse code by hearing/seeing/feeling the code. Tap to toggle buzz!", + "tags": "morse,sound,visual,input", + "type":"app", + "storage": [ + {"name":"+morse","url":"morse-code.json"}, + {"name":"-morse","url":"morse-code.js"}, + {"name":"*morse","url":"morse-code-icon.js","evaluate":true} + ] + }, { "id": "blescan", "name": "BLE Scanner", diff --git a/apps/morse-code.js b/apps/morse-code.js new file mode 100644 index 000000000..72e58d6eb --- /dev/null +++ b/apps/morse-code.js @@ -0,0 +1,147 @@ +/** + * Teach a user morse code +*/ +/** + * Constants +*/ +const FONT_NAME = 'Vector12'; +const FONT_SIZE = 80; +const SCREEN_PIXELS = 240; +const UNIT = 100; +const MORSE_MAP = { + A: '.-', + B: '-...', + C: '-.-.', + D: '-..', + E: '.', + F: '..-.', + G: '--.', + H: '....', + I: '..', + J: '.---', + K: '-.-', + L: '.-..', + M: '--', + N: '-.', + O: '---', + P: '.--.', + Q: '--.-', + R: '.-.', + S: '...', + T: '-', + U: '..-', + V: '...-', + W: '.--', + X: '-..-', + Y: '-.--', + Z: '--..', + '1': '.----', + '2': '..---', + '3': '...--', + '4': '....-', + '5': '.....', + '6': '-....', + '7': '--...', + '8': '---..', + '9': '----.', + '0': '-----', +}; + +/** + * Set the local state +*/ +let INDEX = 0; +let BEEPING = false; +let BUZZING = true; +let UNIT_INDEX = 0; +let UNITS = MORSE_MAP[Object.keys(MORSE_MAP)[INDEX]].split(''); +/** + * Utility functions for writing text, changing state +*/ +const writeText = (txt) => { + g.clear(); + const width = g.stringWidth(txt); + g.drawString(txt, (SCREEN_PIXELS / 2) - (width / 2), SCREEN_PIXELS / 2); +}; +const writeLetter = () => { + writeText(Object.keys(MORSE_MAP)[INDEX]); +}; +const writeCode = () => { + writeText(MORSE_MAP[Object.keys(MORSE_MAP)[INDEX]]); +}; +const setUnits = () => { + UNITS = MORSE_MAP[Object.keys(MORSE_MAP)[INDEX]].split(''); +}; +/** + * Bootstrapping +*/ +g.clear(); +g.setFont(FONT_NAME, FONT_SIZE); +g.setColor(0, 1, 0); +g.setFontAlign(-1, 0, 0); +/** + * The length of a dot is one unit + * The length of a dash is three units + * The length of a space is one unit + * The space between letters is three units + * The space between words is seven units +*/ +const beepItOut = () => { + // If we are starting the beeps, use a timeout for pause of three units + const wait = UNIT_INDEX === 0 ? UNIT * 3 : 0; + setTimeout(() => { + Promise.all([ + Bangle.beep(UNITS[UNIT_INDEX] === '.' ? UNIT : 3 * UNIT), + // Could make buzz optional or switchable potentially + BUZZING ? Bangle.buzz(UNITS[UNIT_INDEX] === '.' ? UNIT : 3 * UNIT) : null + ]) + .then(() => { + if (UNITS[UNIT_INDEX + 1]) { + setTimeout(() => { + UNIT_INDEX++; + beepItOut(); + }, UNIT); + } else { + setTimeout(() => { + BEEPING = false; + UNIT_INDEX = 0; + writeLetter(); + }, 3 * UNIT); + } + }); + }, wait); +}; +const startBeep = () => { + if (BEEPING) return; + else { + BEEPING = true; + writeCode(); + beepItOut(); + } +}; + +const step = (positive) => () => { + if (BEEPING) return; + if (positive) { + INDEX = INDEX + 1; + if (INDEX > Object.keys(MORSE_MAP).length - 1) INDEX = 0; + } else { + INDEX = INDEX - 1; + if (INDEX < 0) INDEX = Object.keys(MORSE_MAP).length - 1; + } + setUnits(); + writeLetter(); +}; + +const toggleBuzzing = () => (BUZZING = !BUZZING); + +writeLetter(); + +// Press the middle button to hear the morse code translation +setWatch(startBeep, BTN2, { repeat: true }); +// Allow user to switch between letters +setWatch(step(true), BTN1, { repeat: true }); +setWatch(step(false), BTN3, { repeat: true }); +// Toggle buzzing/beeping with the touchscreen +setWatch(toggleBuzzing, BTN4, { repeat: true }); +setWatch(toggleBuzzing, BTN5, { repeat: true }); \ No newline at end of file diff --git a/apps/morse-code.json b/apps/morse-code.json new file mode 100644 index 000000000..bbd142c18 --- /dev/null +++ b/apps/morse-code.json @@ -0,0 +1,5 @@ +{ + "name":"Morse Code","type":"app", + "icon":"*morse", + "src":"-morse" +} \ No newline at end of file diff --git a/apps/morse-code.png b/apps/morse-code.png new file mode 100644 index 000000000..41e1b405f Binary files /dev/null and b/apps/morse-code.png differ