Morse Encoder With Codaic

by oliver-hrkltz in Circuits > Apple

17 Views, 0 Favorites, 0 Comments

Morse Encoder With Codaic

MorseEncoder_1.png
MorseEncoder_0.png

This example demonstrates how to convert text into Morse code using the haptic feedback module (vibrator) on iOS devices. When completed, your project should look similar to these pictures.

Supplies

  1. iPhone with iOS 26+
  2. Codaic v1.4+

Introduction


The foundation of this example is the Morse code alphabet. For detailed information, see Wikipedia.


Here's a Lua representation that maps letters and numbers to their Morse code symbols:

local morseDict = {
["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"] = "--..",
["0"] = "-----",
["1"] = ".----",
["2"] = "..---",
["3"] = "...--",
["4"] = "....-",
["5"] = ".....",
["6"] = "-....",
["7"] = "--...",
["8"] = "---..",
["9"] = "----."
}


Next, consider the timing rules for Morse code:

  1. A dot/dit equals one unit (called the dit length)
  2. A dash/dah equals three units
  3. A space between letter parts equals one unit
  4. A space between letters equals three units
  5. A space between words equals seven units

We'll set the dot/dit length to 100 ms, which is the minimum interval at which Codaic can toggle the vibrator. This makes a dash/dah 300 ms long.

Implementation

After collecting all the basic information, it's time to start the project. First, add a new project and give it a name. Then open it and place the nodes as shown above. You will need a Custom node (Morse-Encoder), the Log node, and the Vibrator node. For the Log and Vibrator nodes, you can simply use the provided implementations without modification.


Morse-Encoder Node

This custom node converts a word into Morse code and generates the output signal to control the haptic feedback module (vibrator).

The code is organized into three main sections:

  1. Setup: Initializes the Morse code dictionary that maps each letter and digit to its corresponding symbol (dots and dashes).
  2. Helper Functions:
  3. wordToMorse() - Transforms an entire word into Morse code by converting each character to uppercase (for dictionary lookup) and joining them with proper spacing
  4. Main Loop: Continuously reads the word "Codaic", converts it to Morse code, and then iterates through each symbol to:
  5. Determine if it's a dot, dash, or space
  6. Control the vibrator duration accordingly (100ms for dot, 300ms for dash) and send it to the log
  7. Add appropriate gaps between symbols and words


-- Morse-Encoder Node
-- Setup
local morseDict = {
["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"] = "--..",
["0"] = "-----",
["1"] = ".----",
["2"] = "..---",
["3"] = "...--",
["4"] = "....-",
["5"] = ".....",
["6"] = "-....",
["7"] = "--...",
["8"] = "---..",
["9"] = "----."
}

-- Extract the Morse code for the symbol.
local function letterToMorse(symbol)
return morseDict[symbol]
end

-- Converts a word to Morse code
local function wordToMorse(word, dict)
local morseCode = {}

-- Transform the word character by character.
-- 1. upper() -> Convert "Codaic" to "CODAIC" since the morseDict only contains uppercase letters.
-- 2. gmatch(".") -> Split the word into individual characters for iteration.
for character in word:upper():gmatch(".") do
local morseSequence = morseDict[character]
-- Only append if the character exists in the dictionary (prevents nil errors).
if morseSequence then
table.insert(morseCode, morseSequence)
end
end

-- Join each Morse "letter" with a one unit break represented as space.
return table.concat(morseCode, " ")
end

-- Loop
while true do
-- The word to encode and output.
local word = "Codaic"
-- Use 100 ms as the time unit for a dot/dit.
local unit = 0.1

local morseCode = wordToMorse(word, morseDict)

-- Send the word to the Log Node.
System.Output(0, word .. " -> " .. morseCode)
-- Give the Log node a bit time to read his input before writing the next one.
System.Sleep(0.01)

-- Use an indexed loop to access each symbol in the Morse code.
for i = 1, #morseCode do
local morseSymbol = morseCode:sub(i, i)

if morseSymbol == " " then
-- Gap between letters (300ms)
System.Sleep(unit*3)
else
if morseSymbol == "." then
-- Turn the vibrator on for 100ms (dot).
System.Output(1, "1")
System.Output(0, "> . " .. unit*1000 .. "ms")
System.Sleep(unit)
System.Output(1, "0")
elseif morseSymbol == "-" then
-- Turn the vibrator on for 300ms (dash).
System.Output(1, "1")
System.Output(0, "> - " .. unit*3 .. "ms")
System.Sleep(unit*3)
System.Output(1, "0")
end

-- Add intra-letter gap (100ms) only if the next symbol is a dot or dash.
local nextMorseSymbol = morseCode:sub(i + 1, i + 1)
if nextMorseSymbol == "." or nextMorseSymbol == "-" then
System.Sleep(unit)
end
end
end

-- Finally apply the word gap (700ms).
System.Sleep(unit*7)
end

Outlook

That's it! Now press the play button in the top right corner and listen to your phone. Congratulations on completing your first Codaic project!

For an extra challenge, try replacing the Vibrator node with the Torch node to create a visual representation of your Morse code using light pulses. In the meantime, I will continue improving Codaic and provide more examples.


Transparency Note: I am the developer of Codaic. While I hope you find this example and the app useful, please be aware of this potential conflict of interest. I welcome your feedback, suggestions, or questions—your input helps me improve Codaic for everyone.


Best, Oliver