add passcode generator

This commit is contained in:
Graham McIntire 2025-06-15 22:17:28 -05:00
parent 94ef1e22b8
commit b6260a950f
No known key found for this signature in database

View file

@ -15,7 +15,7 @@ defmodule Aprs.Passcode do
## Examples ## Examples
iex> Aprs.Passcode.generate("W5ISP") iex> Aprs.Passcode.generate("W5ISP")
12345 15748
""" """
def generate(callsign) when is_binary(callsign) do def generate(callsign) when is_binary(callsign) do
# Split on '-' and take first part, uppercase, and limit to 10 chars # Split on '-' and take first part, uppercase, and limit to 10 chars
@ -32,22 +32,22 @@ defmodule Aprs.Passcode do
# Initial hash value # Initial hash value
hash = 0x73E2 hash = 0x73E2
# Process characters in pairs # Process characters in pairs, incrementing by 2 each time
hash = hash =
Enum.reduce_every(chars, 2, hash, fn [char1, char2], acc -> Enum.reduce(0..div(length(chars) - 1, 2), hash, fn i, acc ->
acc current_char = Enum.at(chars, i * 2)
|> Bitwise.bxor(Bitwise.bsl(char1, 8)) next_char = if i * 2 + 1 < length(chars), do: Enum.at(chars, i * 2 + 1), else: nil
|> Bitwise.bxor(char2) step1 = Bitwise.bxor(acc, Bitwise.bsl(current_char, 8))
end)
# Handle odd length callsigns step2 =
hash = if next_char do
if rem(length(chars), 2) == 1 do Bitwise.bxor(step1, next_char)
last_char = List.last(chars) else
Bitwise.bxor(hash, Bitwise.bsl(last_char, 8)) step1
else end
hash
end step2
end)
# Return final hash masked to 15 bits # Return final hash masked to 15 bits
Bitwise.band(hash, 0x7FFF) Bitwise.band(hash, 0x7FFF)