class NRF24

Constants

ARC
ARC_CNT
ARD

SETUP_RETR

COMMANDS
CRCO
EN_ACK_PAY
EN_CRC
EN_DPL

FEATURE

EN_DYN_ACK
FIFO_RX_EMPTY
FIFO_RX_FULL
FIFO_TX_EMPTY
FIFO_TX_FULL
LNA_HCURR
MASK_MAX_RT
MASK_RX_DR

CONFIG

MASK_TX_DS
MAX_RT
PLL_LOCK
PLOS_CNT

observe_tx

PRIM_RX
PWR_UP
REGISTER_MASK
REGS
RF_DR_HIGH
RF_DR_LOW

RF_SETUP

RF_PWR_HIGH
RF_PWR_LOW
RX_DR

STATUS

RX_P_NO
TX_DS
TX_FULL
TX_REUSE

FIFO_STATUS

VERSION

Attributes

cepin[R]
csnpin[R]
spi[R]
static_payload_size[R]

Public Class Methods

begin(*opts, &block) click to toggle source
# File lib/nrf24/nrf24-ruby.rb, line 12
def self.begin *opts, &block
  nrf = NRF24.new *opts
  nrf.instance_eval &block if block_given?
ensure
  nrf.send :radio_deinit
end
new(opts = {}) click to toggle source
# File lib/nrf24/nrf24-ruby.rb, line 375
def initialize opts = {}
  opts = {cepin: 22, csnpin: 8, static_payload_size: 32, channel: 76, driver: Bcm2835Driver}.merge opts

  @cepin = opts[:cepin]
  @csnpin = opts[:csnpin]
  @static_payload_size = [opts[:static_payload_size], 32].min
  @channel = opts[:channel]

  extend opts[:driver]

  init_io
  radio_init

  @pipe0_reading_address = nil
end

Public Instance Methods

activate() click to toggle source
# File lib/nrf24/nrf24-ruby.rb, line 325
def activate
  send_command :activate, 0x73
end
address_width() click to toggle source
# File lib/nrf24/nrf24-ruby.rb, line 261
def address_width
  @address_width || (get_register(:setup_aw) + 2)
end
channel() click to toggle source
# File lib/nrf24/nrf24-ruby.rb, line 185
def channel
  get_register :rf_ch
end
clear_interrupt_flags() click to toggle source
# File lib/nrf24/nrf24-ruby.rb, line 321
def clear_interrupt_flags
  set_register :nrf_status, (1 << RX_DR) | (1 << TX_DS) | (1 << MAX_RT)
end
close_reading_pipe(pipe) click to toggle source
# File lib/nrf24/nrf24-ruby.rb, line 132
def close_reading_pipe pipe
  set_register :en_rxaddr, get_register(:en_rxaddr) & inv_bv(pipe)
end
crc_length() click to toggle source
# File lib/nrf24/nrf24-ruby.rb, line 228
def crc_length
  config = get_register(:config)

  if config[EN_CRC] > 0 or get_register(:en_aa) > 0
    config[CRCO] == 1 ? :crc_16 : :crc_8
  else
    :crc_none
  end
end
data_available?() click to toggle source
# File lib/nrf24/nrf24-ruby.rb, line 285
def data_available?
  (status >> RX_P_NO) & 0b111 if not fifo_rx_empty?
end
datarate() click to toggle source
# File lib/nrf24/nrf24-ruby.rb, line 216
def datarate
  rf_setup = get_register :rf_setup

  if rf_setup[RF_DR_LOW] == 1
    :rate_250kbps
  elsif rf_setup[RF_DR_HIGH] == 1
    :rate_2mbps
  else
    :rate_1mbps
  end
end
disable_auto_ack(pipes = :all) click to toggle source
# File lib/nrf24/nrf24-ruby.rb, line 96
def disable_auto_ack pipes = :all
  if pipes == :all
    set_register :en_aa, 0
  elsif pipes.is_a? Enumerable
    pipes.map { |p| disable_auto_ack p }
  else
    return if pipes > 5
    set_register :en_aa, get_register(:en_aa) & inv_bv(pipes)
  end
end
disable_crc() click to toggle source
# File lib/nrf24/nrf24-ruby.rb, line 249
def disable_crc
  set_register :config, get_register(:config) & inv_bv(EN_CRC)
end
disable_dynamic_payloads() click to toggle source
# File lib/nrf24/nrf24-ruby.rb, line 162
def disable_dynamic_payloads
  set_register :feature, get_register(:feature) & inv_bv(EN_DPL)
  set_register :dynpd, 0
end
dynamic_payload_enabled?() click to toggle source
# File lib/nrf24/nrf24-ruby.rb, line 167
def dynamic_payload_enabled?
  get_register(:feature)[EN_DPL] > 0
end
enable_auto_ack(pipes = :all) click to toggle source
# File lib/nrf24/nrf24-ruby.rb, line 85
def enable_auto_ack pipes = :all
  if pipes == :all
    set_register :en_aa, 0b111111
  elsif pipes.is_a? Enumerable
    pipes.map { |p| enable_auto_ack p }
  else
    return if pipes > 5
    set_register :en_aa, get_register(:en_aa) | bv(pipes)
  end
end
enable_dynamic_payloads() click to toggle source
# File lib/nrf24/nrf24-ruby.rb, line 157
def enable_dynamic_payloads
  set_register :feature, get_register(:feature) | bv(EN_DPL)
  set_register :dynpd, 63 # Enable for all pipes
end
fifo_flags() click to toggle source
# File lib/nrf24/nrf24-ruby.rb, line 305
def fifo_flags
  flags = []
  fifo_status = get_register(:fifo_status)

  flags << :tx_full if fifo_tx_full?
  flags << :tx_empty if fifo_tx_empty?
  flags << :rx_full if fifo_rx_full?
  flags << :rx_empty if fifo_rx_empty?

  flags
end
fifo_rx_empty?() click to toggle source
# File lib/nrf24/nrf24-ruby.rb, line 301
def fifo_rx_empty?
  get_register(:fifo_status)[FIFO_RX_EMPTY] > 0
end
fifo_rx_full?() click to toggle source
# File lib/nrf24/nrf24-ruby.rb, line 297
def fifo_rx_full?
  get_register(:fifo_status)[FIFO_RX_FULL] > 0
end
fifo_tx_empty?() click to toggle source
# File lib/nrf24/nrf24-ruby.rb, line 293
def fifo_tx_empty?
  get_register(:fifo_status)[FIFO_TX_EMPTY] > 0
end
fifo_tx_full?() click to toggle source
# File lib/nrf24/nrf24-ruby.rb, line 289
def fifo_tx_full?
  get_register(:fifo_status)[FIFO_TX_FULL] > 0
end
flush_rx() click to toggle source
# File lib/nrf24/nrf24-ruby.rb, line 275
def flush_rx
  send_command :flush_rx
end
flush_tx() click to toggle source
# File lib/nrf24/nrf24-ruby.rb, line 271
def flush_tx
  send_command :flush_tx
end
get_dynamic_payload_size() click to toggle source
# File lib/nrf24/nrf24-ruby.rb, line 153
def get_dynamic_payload_size
  send_command :r_rx_pl_wid, 1
end
get_register(reg, len = 1) click to toggle source
# File lib/nrf24/nrf24-ruby.rb, line 343
def get_register reg, len = 1
  reg = REGS[reg] unless reg.is_a? Numeric
  with_csn {
    spi.write(COMMANDS[:r_register] | (REGISTER_MASK & reg))
    len == 1 ? spi.read : spi.read(len) # do not return an array when len == 1
  } if reg
end
open_reading_pipe(pipe, address) click to toggle source
# File lib/nrf24/nrf24-ruby.rb, line 117
def open_reading_pipe pipe, address
  @pipe0_reading_address = address if pipe == 0

  if pipe <= 5
    if pipe < 2
      set_register REGS[:rx_addr_p0] + pipe, address
    else
      set_register REGS[:rx_addr_p0] + pipe, address.first # Only LSB TODO Handle Numeric (byte) address
    end
    set_register REGS[:rx_pw_p0] + pipe, static_payload_size

    set_register :en_rxaddr, get_register(:en_rxaddr) | bv(pipe)
  end
end
open_writing_pipe(address) click to toggle source
# File lib/nrf24/nrf24-ruby.rb, line 71
def open_writing_pipe address
  set_register :rx_addr_p0, address
  set_register :tx_addr, address
  set_register :rx_pw_p0, static_payload_size
end
payload_size() click to toggle source
# File lib/nrf24/nrf24-ruby.rb, line 136
def payload_size
  if dynamic_payload_enabled?
    get_dynamic_payload_size
  else
    static_payload_size
  end
end
power_down() click to toggle source
# File lib/nrf24/nrf24-ruby.rb, line 179
def power_down
  ce_low
  config = get_register(:config) & inv_bv(PWR_UP)
  set_register :config, config
end
power_up() click to toggle source
# File lib/nrf24/nrf24-ruby.rb, line 171
def power_up
  config = get_register(:config)
  if config[PWR_UP] == 0
    set_register :config, config | bv(PWR_UP)
    sleep 0.01
  end
end
print_regs() click to toggle source
read() click to toggle source
# File lib/nrf24/nrf24-ruby.rb, line 107
def read
  payload = read_payload
  clear_interrupt_flags
  payload
end
read_payload() click to toggle source
# File lib/nrf24/nrf24-ruby.rb, line 113
def read_payload
  send_command :r_rx_payload, payload_size
end
received_power() click to toggle source
# File lib/nrf24/nrf24-ruby.rb, line 317
def received_power
  get_register(:rpd)
end
reuse_tx_payload() click to toggle source
# File lib/nrf24/nrf24-ruby.rb, line 279
def reuse_tx_payload
  set_register :nrf_status, bv(MAX_RT)
  send_commnad :reuse_tx_pl
  pulse_ce
end
rf_setup(datarate = :rate_1mbps, power = :max_power) click to toggle source
# File lib/nrf24/nrf24-ruby.rb, line 193
def rf_setup datarate = :rate_1mbps, power = :max_power
  available_rates = {
      :rate_250kbps => 32, 250 => 32,
      :rate_1mbps => 0, 1 => 0, 1000 => 0,
      :rate_2mbps => 8, 2 => 8, 2000 => 8
  }

  pa_settings = {
      :min_power => 0, -18 => 0, 18 => 0,
      :low_power => 2, -12 => 2, 12 => 2,
      :high_power => 4, -6 => 4, 6 => 4,
      :max_power => 6, 0 => 6
  }

  rate = available_rates[datarate]
  power = pa_settings[power]

  return nil unless rate && power

  set_register :rf_setup, (rate | power)
  get_register :rf_setup
end
send_command(command, data_len = 0) click to toggle source
# File lib/nrf24/nrf24-ruby.rb, line 351
def send_command command, data_len = 0
  command = COMMANDS[command] unless command.is_a? Numeric
  with_csn {
    spi.write command
    spi.read(data_len) if data_len > 0
  }
end
set_ack_payload(pipe, payload) click to toggle source
# File lib/nrf24/nrf24-ruby.rb, line 77
def set_ack_payload pipe, payload
  raise OverSizedPayload, "ack payload can be 32 bytes max!" if payload.size > 32
  with_csn {
    spi.write COMMANDS[:w_ack_payload] | (pipe & 7)
    spi.write payload
  }
end
set_address_width(aw = 5) click to toggle source
# File lib/nrf24/nrf24-ruby.rb, line 265
def set_address_width aw = 5
  aw = (aw - 2) % 4;
  set_register :setup_aw, aw
  @address_width = aw + 2
end
Also aliased as: address_width=
set_channel(ch) click to toggle source
# File lib/nrf24/nrf24-ruby.rb, line 189
def set_channel ch
  set_register :rf_ch, ch
end
Also aliased as: channel=
set_crc_length(length) click to toggle source
# File lib/nrf24/nrf24-ruby.rb, line 238
def set_crc_length length
  config = get_register(:config) & (~(bv(CRCO) | bv(EN_CRC)) & 0xff)

  if [:crc_16, 16, 2].include? length
    config |= (bv(EN_CRC) | bv(CRCO))
  elsif [:crc_8, 8, 1].include? length
    config |= bv(EN_CRC)
  end
  set_register :config, config
end
Also aliased as: crc_length=
set_payload_size(pipe, size) click to toggle source
# File lib/nrf24/nrf24-ruby.rb, line 144
def set_payload_size pipe, size
  if pipe.is_a? Enumerable
    pipe.map { |p| set_payload_size p, size }
  else
    return if pipe > 5 # Lets make sure not to screw up other regs
    set_register(REGS[:rx_pw_p0] + pipe, size)
  end
end
set_register(reg, value) click to toggle source
# File lib/nrf24/nrf24-ruby.rb, line 335
def set_register reg, value
  reg = REGS[reg] unless reg.is_a? Numeric
  with_csn {
    spi.write(COMMANDS[:w_register] | (REGISTER_MASK & reg))
    spi.write value
  }
end
set_retries(delay, count) click to toggle source
# File lib/nrf24/nrf24-ruby.rb, line 253
def set_retries delay, count
  set_register :setup_retr, ((delay & 0xf) << ARD) | ((count & 0xf) << ARC)
end
set_tx_address(addr) click to toggle source
# File lib/nrf24/nrf24-ruby.rb, line 257
def set_tx_address addr
  set_register :tx_addr, addr
end
Also aliased as: tx_address=
start_listening() click to toggle source
# File lib/nrf24/nrf24-ruby.rb, line 19
def start_listening
  set_register :config, get_register(:config) | bv(PRIM_RX)
  clear_interrupt_flags
  ce_high

  set_register :rx_addr_p0, @pipe0_reading_address if @pipe0_reading_address # Restore address, as this could be overwritten during a PTX cycle (Pipe 0 is used for receiving auto-acks)

  flush_tx if get_register(:feature)[EN_ACK_PAY] > 0
end
status() click to toggle source
# File lib/nrf24/nrf24-ruby.rb, line 329
def status
  with_csn {
    spi.read
  }
end
stop_listening() click to toggle source
# File lib/nrf24/nrf24-ruby.rb, line 29
def stop_listening
  ce_low
  flush_tx if get_register(:feature)[EN_ACK_PAY] > 0
  set_register :config, get_register(:config) & inv_bv(PRIM_RX)
  set_register :en_rxaddr, get_register(:en_rxaddr) | 1
end
write(payload, type = :ack, timeout = 2) click to toggle source
# File lib/nrf24/nrf24-ruby.rb, line 40
def write payload, type = :ack, timeout = 2
  start = Time.now

  while fifo_tx_full?
    if status[MAX_RT] > 0
      set_register :nrf_status, bv(MAX_RT)
      return :max_rt
    end
    raise TX_Timeout, "TX FIFO full" if Time.now - start > timeout
  end

  write_payload payload, type

  pulse_ce
end
write_no_ack(payload, *args) click to toggle source
# File lib/nrf24/nrf24-ruby.rb, line 36
def write_no_ack payload, *args
  write(payload, :no_ack, *args)
end
write_payload(payload, type = :ack) click to toggle source
# File lib/nrf24/nrf24-ruby.rb, line 56
def write_payload payload, type = :ack
  if dynamic_payload_enabled?
    raise OverSizedPayload if payload.size > 32
  else
    raise OverSizedPayload if payload.size > static_payload_size
    padding = static_payload_size - payload.size
  end

  with_csn {
    spi.write COMMANDS[type == :no_ack ? :w_tx_payload_noack : :w_tx_payload]
    spi.write payload
    spi.write ([0] * padding)
  }
end

Private Instance Methods

address_width=(aw = 5)
Alias for: set_address_width
bv(d) click to toggle source

Low level bit vector stuff

# File lib/nrf24/nrf24-ruby.rb, line 438
def bv d
  1 << d
end
channel=(ch)
Alias for: set_channel
crc_length=(length)
Alias for: set_crc_length
inv_bv(d, mask = 0xff) click to toggle source
# File lib/nrf24/nrf24-ruby.rb, line 442
def inv_bv d, mask = 0xff
  ~(1 << d) & mask
end
pulse_ce(us = 10) click to toggle source
# File lib/nrf24/nrf24-ruby.rb, line 431
def pulse_ce us = 10
  ce_high
  sleep(0.000001 * us)
  ce_low
end
radio_deinit() click to toggle source
# File lib/nrf24/nrf24-ruby.rb, line 410
def radio_deinit
  ce_low
  radio_init
  rf_setup
  set_channel 0
end
radio_init() click to toggle source
# File lib/nrf24/nrf24-ruby.rb, line 391
def radio_init
  activate # nrf24l01 (non-plus) compatibility

  set_address_width

  set_channel @channel

  set_payload_size (0..5), static_payload_size
  disable_dynamic_payloads
  enable_auto_ack

  set_register :config, ((1 << EN_CRC) | (1 << CRCO) | (1 << PWR_UP) | (1 << PRIM_RX))

  clear_interrupt_flags

  flush_rx
  flush_tx
end
tx_address=(addr)
Alias for: set_tx_address
with_ce() { || ... } click to toggle source
# File lib/nrf24/nrf24-ruby.rb, line 424
def with_ce
  ce_high
  ret = yield
  ce_low
  ret
end
with_csn() { || ... } click to toggle source
# File lib/nrf24/nrf24-ruby.rb, line 417
def with_csn
  csn_low
  ret = yield
  csn_high
  ret
end