L O ・-・・ --- / L D R ・-・ ・-・・ -・・ ※ / = 二語の間隔だと思って読んでください。 H→Eの間に3点、HELLOとWORLDの間に7点分の空白があるイメージ 2026年9月13日(日) iOSDC Japan 2026 スマートフォンでモールス信号を送受信する 〜スマートフォンのLEDとカメラで作る光通信の設計と実装〜 31
• {AS} {1...}:「〜分待ってください」の意味 • 例)〇〇 DE ▲▲ K • 例)〇〇 DE ▲▲ AS 1 ※受信側もDEの前後を入れ替え、同じフォーマットで返す 2026年9月13日(日) iOSDC Japan 2026 スマートフォンでモールス信号を送受信する 〜スマートフォンのLEDとカメラで作る光通信の設計と実装〜 37
• {AS} {1...}:「〜分待ってください」の意味 • 例)〇〇 DE ▲▲ K • 例)〇〇 DE ▲▲ AS 1 ※K,AS の終止符号は相手にターンを渡すときの符号 2026年9月13日(日) iOSDC Japan 2026 スマートフォンでモールス信号を送受信する 〜スマートフォンのLEDとカメラで作る光通信の設計と実装〜 38
}:2通目以降の通報の開始符号 • { ・-・-・ }:欧文の場合の終止記号 • { ・・・-・ }:和文の場合の終止記号 • { NIL }:(2通以上ある場合)他に送る通報なし • 例)▲▲ DE 〇〇 HR TEST MESSAGE ONE ・-・-・ • 例)▲▲ DE 〇〇 AHR TEST MESSAGE TWO ・-・-・ NIL K 2026年9月13日(日) iOSDC Japan 2026 スマートフォンでモールス信号を送受信する 〜スマートフォンのLEDとカメラで作る光通信の設計と実装〜 42
extension Element { var units: Int { switch self { case .dot: 1 case .dash: 3 } } } // 各空白の定義 enum Spacing { static let element = 1 // 1符号内 static let symbol = 3 // 符号間 static let word // 語間 2026年9月13日(日) iOSDC Japan 2026 } =7 スマートフォンでモールス信号を送受信する 〜スマートフォンのLEDとカメラで作る光通信の設計と実装〜 61
Symbol → Sign → Element extension Message { func unitSequence() -> [(isOn: Bool, units: Int)] { var out: [(Bool, Int)] = [] for (wi, word) in words.enumerated() { if wi > 0 { out.append((false, Spacing.word)) } // 7 for (si, symbol) in word.symbols.enumerated() { if si > 0 { out.append((false, Spacing.symbol)) } // 3 var isFirst = true for sign in symbol.signs { for element in sign.elements { と入れ子を取り出すと、 if !isFirst { out.append((false, Spacing.element)) } // 1 信号列に変換できる構造 isFirst = false out.append((true, element.units)) 2026年9月13日(日) iOSDC Japan 2026 スマートフォンでモールス信号を送受信する 〜スマートフォンのLEDとカメラで作る光通信の設計と実装〜 62
second: UInt8 = 0, third: UInt8 = 0, fourth: UInt8 = 0 for y in ... { for x in ... { let value = line[x] if value <= fourth { continue } // 大半の画素はここで終わる if value > first { fourth = third; third = second; second = first; first = value } else if value > second { fourth = third; third = second; second = value } else if value > third { fourth = third; third = value } else { fourth = value } }} // このマスの輝度。輝度を1つの値に畳んだ結果 cells[row * columns + column] = UInt8((Int(first)+Int(second)+Int(third)+Int(fourth)) / 4) 2026年9月13日(日) iOSDC Japan 2026 スマートフォンでモールス信号を送受信する 〜スマートフォンのLEDとカメラで作る光通信の設計と実装〜 92