diff --git a/lib/.rfm69.ex.swp b/lib/.rfm69.ex.swp new file mode 100644 index 0000000..47f73f7 Binary files /dev/null and b/lib/.rfm69.ex.swp differ diff --git a/lib/rfm69.ex b/lib/rfm69.ex index ea06f37..6acc522 100644 --- a/lib/rfm69.ex +++ b/lib/rfm69.ex @@ -9,33 +9,61 @@ defmodule RFM69 do # @fifo_threshold 20 @transfer_sleep trunc(@fifo_size / 4) # time to wait for fifo to be processed during transfer - def write_and_read(packet_bytes, timeout_ms) do - write(packet_bytes) - read(timeout_ms) - end - - def write(packet_bytes) do - clear_fifo() - set_mode(:standby) - set_auto_modes([:enter_condition_fifo_not_empty, :exit_condition_fifo_empty, :intermediate_mode_tx]) - transmit(packet_bytes <> <<0x00::8>>, @fifo_size) - set_mode(:sleep) + def set_base_frequency(mhz) do + @device.write_frequency(trunc(mhz * 1_000_000)) end def read(timeout_ms) do set_auto_modes([]) set_mode(:receiver) @device.await_interrupt() - receive do + result = receive do {:ok, :interrupt_received} -> - Logger.info "I can't believe this worked" - # read rssi - bytes = read_until_null(<<>>) + Logger.info "Received response" + rssi = read_rssi() + bytes = read_until_null(<<>>) Logger.debug fn() -> "response: #{Base.encode16(bytes)}" end + {:ok, %{data: bytes, rssi: rssi}} after - timeout_ms -> Logger.info "I got nothin'" + timeout_ms -> + Logger.info "Timeout reached" + @device.cancel_interrupt() + {:error, :timeout} end set_mode(:sleep) + result + end + + def write(packet_bytes, repetitions, repetition_delay, timeout_ms, initial \\ true) do + if initial == true do + clear_fifo() + set_mode(:standby) + end + + case repetitions do + r when r >= 1 -> + _write(packet_bytes, timeout_ms) + :timer.sleep(repetition_delay) + write(packet_bytes, repetitions - 1, repetition_delay, timeout_ms, false) + true -> + set_mode(:sleep) + {:ok, ""} + end + end + + def _write(packet_bytes, _timeout_ms) do + modes = [:enter_condition_fifo_not_empty, :exit_condition_fifo_empty, :intermediate_mode_tx] + set_auto_modes(modes) + transmit(packet_bytes <> <<0x00::8>>, @fifo_size) + end + + def write_and_read(packet_bytes, timeout_ms) do + write(packet_bytes, timeout_ms, 1, 0) + read(timeout_ms) + end + + def clear_buffers do + clear_fifo() end defp read_until_null(data) do @@ -46,7 +74,7 @@ defmodule RFM69 do end defp transmit(bytes, available_buffer_bytes) when byte_size(bytes) <= available_buffer_bytes do - Logger.debug fn() -> "Transmitting remaining: #{Base.encode16(bytes)}, available_buffer_bytes: #{available_buffer_bytes}" end + # Logger.debug fn() -> "Transmitting remaining: #{Base.encode16(bytes)}, available_buffer_bytes: #{available_buffer_bytes}" end _transmit(bytes) wait_for_mode(:standby) end @@ -68,7 +96,7 @@ defmodule RFM69 do @reg_irq_flags2 0x28 @fifo_overrun 0x10 defp clear_fifo() do - Logger.debug "Clearing FIFO" + # Logger.debug "Clearing FIFO" @device.write_single(@reg_irq_flags2, @fifo_overrun) end @@ -78,10 +106,10 @@ defmodule RFM69 do end defp wait_for_buffer_to_become_available() do - Logger.debug "Waiting for buffer to become available" + # Logger.debug "Waiting for buffer to become available" case fifo_threshold_exceeded?() do true -> wait_for_buffer_to_become_available() - false -> Logger.debug "Buffer available" + false -> nil # Logger.debug "Buffer available" end end @@ -104,7 +132,7 @@ defmodule RFM69 do case mode do ^current_mode -> true _ -> - Logger.debug fn() -> "Setting mode to #{inspect(mode)}" end + # Logger.debug fn() -> "Setting mode to #{inspect(mode)}" end @device.write_single(@reg_op_mode, mode) wait_for_mode_ready(mode) end @@ -152,6 +180,12 @@ defmodule RFM69 do end end + @reg_rssi_val 0x24 + defp read_rssi do + {:ok, <>} = @device.read_burst(@reg_rssi_val, 1) + -1 * trunc(raw_rssi) / 2 + end + # def read_hardware_version() do # <<_::8, version::4, metal_mask::4>> = SPI.transfer(<<0x1000::16>>) # IO.puts "Version: #{version}, Metal Version: #{metal_mask}" diff --git a/lib/rfm69/device.ex b/lib/rfm69/device.ex index 100f4e7..cb9ebd2 100644 --- a/lib/rfm69/device.ex +++ b/lib/rfm69/device.ex @@ -38,11 +38,11 @@ defmodule RFM69.Device do def write_single(location, data), do: write_burst(location, <>) def reset, do: GenServer.call(__MODULE__, {:reset}) def await_interrupt, do: GenServer.call(__MODULE__, {:await_interrupt}) + def cancel_interrupt, do: GenServer.call(__MODULE__, {:cancel_interrupt}) @configuration_start 0x01 def write_configuration(rf_config = %Configuration{}) do configuration_bytes = Configuration.to_binary(rf_config) - Logger.debug "Writing full configuration" :ok = write_burst(@configuration_start, configuration_bytes) end @@ -50,12 +50,18 @@ defmodule RFM69.Device do byte_count = byte_size(Configuration.to_binary(%Configuration{})) {:ok, response_bytes} = read_burst(@configuration_start, byte_count) rf_config = Configuration.from_binary(response_bytes) - Logger.debug fn() -> "Configuration: #{inspect(rf_config, limit: -1)}" end rf_config end + @frf_location 0x07 + def write_frequency(frequency_in_hz) do + register_values = Configuration.frequency_to_registers(frequency_in_hz) + register_bytes = <> + :ok = write_burst(@frf_location, register_bytes) + {:ok} + end + def handle_call({:reset}, _from, state = %{reset_pid: reset_pid}) do - Logger.debug "Resetting device" GPIO.write(reset_pid, 1) :timer.sleep(1) GPIO.write(reset_pid, 0) @@ -66,7 +72,6 @@ defmodule RFM69.Device do @write_mode 0x80 def handle_call({:write_burst, location, data}, _from, state = %{spi_pid: spi_pid}) do tx_bytes = <<(@write_mode ||| location)::8>> <> data - # Logger.debug fn() -> "Writing #{Base.encode16(tx_bytes)}" end SPI.transfer(spi_pid, tx_bytes) {:reply, :ok, state} end @@ -75,20 +80,20 @@ defmodule RFM69.Device do size_bits = byte_count * 8 tx_bytes = <> <<_::8, rx_bytes::binary>> = SPI.transfer(spi_pid, tx_bytes) - # Logger.debug fn() -> "Received #{Base.encode16(rx_bytes)}" end {:reply, {:ok, rx_bytes}, state} end def handle_call({:await_interrupt}, {sender, _}, state = %{interrupt_pid: interrupt_pid}) do - Logger.debug "Setting interrupt on pin" GPIO.set_int(interrupt_pid, :rising) - new_state = Map.put(state, :awaiting_interrupt, sender) - {:reply, :ok, new_state} + {:reply, :ok, Map.put(state, :awaiting_interrupt, sender)} + end + + def handle_call({:cancel_interrupt}, {_, _}, state = %{interrupt_pid: interrupt_pid}) do + GPIO.set_int(interrupt_pid, :none) + {:reply, :ok, Map.delete(state, :awaiting_interrupt)} end - def handle_info({:gpio_interrupt, _, :rising}, state) do - %{awaiting_interrupt: awaiting_interrupt, interrupt_pid: interrupt_pid} = state - Logger.debug "Received interrupt on pin" + def handle_info({:gpio_interrupt, _, :rising}, state = %{awaiting_interrupt: awaiting_interrupt, interrupt_pid: interrupt_pid}) do GPIO.set_int(interrupt_pid, :none) send(awaiting_interrupt, {:ok, :interrupt_received}) {:noreply, Map.delete(state, :awaiting_interrupt)}