defmodule AirPlay.Ntp do
@moduledoc """
NTP 64-bit timestamps for the AirPlay/RAOP timing channel.
An NTP timestamp is `seconds-since-1900 (32 bits) . fraction (32 bits)`. The
RAOP timing packets (`0xd2`/`0xd3`) carry these so the receiver can align its
clock to ours.
"""
import Bitwise
# Seconds between the NTP epoch (1900-01-01) and the Unix epoch (1970-01-01).
@ntp_unix_offset 2_208_988_800
@doc "Current time as a 64-bit NTP timestamp (integer)."
@spec now() :: non_neg_integer()
def now, do: from_unix_ns(System.os_time(:nanosecond))
@doc "Convert Unix nanoseconds to a 64-bit NTP timestamp."
@spec from_unix_ns(integer()) :: non_neg_integer()
def from_unix_ns(ns) do
secs = div(ns, 1_000_000_000) + @ntp_unix_offset
frac = (rem(ns, 1_000_000_000) * (1 <<< 32)) |> div(1_000_000_000)
secs * (1 <<< 32) + frac
end
end