Class: NRF24
- Inherits:
-
Object
- Object
- NRF24
- Defined in:
- lib/nrf24/version.rb,
lib/nrf24/constants.rb,
lib/nrf24/nrf24-ruby.rb,
lib/nrf24/bcm2835_driver.rb
Defined Under Namespace
Modules: Bcm2835Driver Classes: OverSizedPayload, TX_Timeout
Constant Summary collapse
- VERSION =
'0.5.1'
- COMMANDS =
{ :r_register => 0x00, :w_register => 0x20, :activate => 0x50, # non-plus register only :r_rx_pl_wid => 0x60, :r_rx_payload => 0x61, :w_tx_payload => 0xa0, :w_ack_payload => 0xa8, :w_tx_payload_noack => 0xb0, :flush_tx => 0xe1, :flush_rx => 0xe2, :reuse_tx_pl => 0xe3, :nop => 0xff }
- REGS =
{ :config => 0x00, # Configuration Register :en_aa => 0x01, # Enable ‘Auto Acknowledgment’ Function Disable this functionality to be compatible with nRF2401, :en_rxaddr => 0x02, # Enabled RX Addresses :setup_aw => 0x03, # Setup of Address Widths (common for all data pipes) :setup_retr => 0x04, # Setup of Automatic Retransmission :rf_ch => 0x05, # RF Channel :rf_setup => 0x06, # RF Setup Register (power, rate) :nrf_status => 0x07, # a.k.a. nrf24l01.rbStatus :status => 0x07, :observe_tx => 0x08, # Transmit observe register (packets lost, retransmits) :cd => 0x09, # Legacy (nRF24l01 non+) name :rpd => 0x09, # Received power detection (1 == > -64dBm) :rx_addr_p0 => 0x0a, # Receive address data pipe 0. 5 Bytes maximum length. (LSByte is written first. Write the number of bytes defined by SETUP_AW) :rx_addr_p1 => 0x0b, # Receive address data pipe 1. 5 Bytes maximum length. (LSByte is written first. Write the number of bytes defined by SETUP_AW) :rx_addr_p2 => 0x0c, # Receive address data pipe 2. Only LSB. MSBytes are equal to RX_ADDR_P1[39:8] :rx_addr_p3 => 0x0d, # Receive address data pipe 3. Only LSB. MSBytes are equal to RX_ADDR_P1[39:8] :rx_addr_p4 => 0x0e, # Receive address data pipe 4. Only LSB. MSBytes are equal to RX_ADDR_P1[39:8] :rx_addr_p5 => 0x0f, # Receive address data pipe 5. Only LSB. MSBytes are equal to RX_ADDR_P1[39:8] :tx_addr => 0x10, # Transmit address. Used for a PTX device only. (LSByte is written first) Set RX_ADDR_P0 equal to this address to handle automatic acknowledge if this is a PTX device with Enhanced ShockBurst™ enabled. :rx_pw_p0 => 0x11, # Number of bytes in RX payload in data pipe 0-5 (1 to 32 bytes). :rx_pw_p1 => 0x12, # :rx_pw_p2 => 0x13, # 0 Pipe not used :rx_pw_p3 => 0x14, # 1 = 1 byte :rx_pw_p4 => 0x15, # … :rx_pw_p5 => 0x16, # 32 = 32 bytes :fifo_status => 0x17, # FIFO Status Register :dynpd => 0x1c, :feature => 0x1d }
- MASK_RX_DR =
CONFIG
6
- MASK_TX_DS =
5
- MASK_MAX_RT =
4
- EN_CRC =
3
- CRCO =
2
- PWR_UP =
1
- PRIM_RX =
0
- ARD =
SETUP_RETR
4
- ARC =
0
- RX_DR =
STATUS
6
- TX_DS =
Data Ready RX FIFO interrupt
5
- MAX_RT =
Data Sent TX FIFO interrupt
4
- RX_P_NO =
Maximum number of TX retransmits interrupt Write 1 to clear bit. If MAX_RT is asserted it must be cleared to enable further communication.
1
- TX_FULL =
bit 3:1 Data pipe number for the payload available for reading from RX_FIFO 000-101: Data Pipe Number 110: Not Used 111: RX FIFO Empty
0
- PLOS_CNT =
observe_tx
4
- ARC_CNT =
7:4 Count lost packets. The counter is overflow protected to 15, and discontinues at max until reset. The counter is reset by writing to RF_CH.
0
- TX_REUSE =
FIFO_STATUS
6
- FIFO_TX_FULL =
5
- FIFO_TX_EMPTY =
4
- FIFO_RX_FULL =
1
- FIFO_RX_EMPTY =
0
- EN_DPL =
FEATURE
2
- EN_ACK_PAY =
1
- EN_DYN_ACK =
0
- RF_DR_LOW =
RF_SETUP
5
- PLL_LOCK =
4
- RF_DR_HIGH =
3
- RF_PWR_LOW =
1
- RF_PWR_HIGH =
2
- LNA_HCURR =
0
- REGISTER_MASK =
0x1F
Instance Attribute Summary collapse
-
#static_payload_size ⇒ Object
readonly
Returns the value of attribute static_payload_size.
Class Method Summary collapse
Instance Method Summary collapse
- #activate ⇒ Object
- #address_width ⇒ Object
- #channel ⇒ Object
- #clear_interrupt_flags ⇒ Object
- #close_reading_pipe(pipe) ⇒ Object
- #crc_length ⇒ Object
- #data_available? ⇒ Boolean
- #datarate ⇒ Object
- #disable_auto_ack(pipes = :all) ⇒ Object
- #disable_crc ⇒ Object
- #disable_dynamic_payloads ⇒ Object
- #dynamic_payload_enabled? ⇒ Boolean
- #enable_auto_ack(pipes = :all) ⇒ Object
- #enable_dynamic_payloads ⇒ Object
- #fifo_flags ⇒ Object
- #fifo_rx_empty? ⇒ Boolean
- #fifo_rx_full? ⇒ Boolean
- #fifo_tx_empty? ⇒ Boolean
- #fifo_tx_full? ⇒ Boolean
- #flush_rx ⇒ Object
- #flush_tx ⇒ Object
- #get_dynamic_payload_size ⇒ Object
- #get_register(reg, len = 1) ⇒ Object
- #open_reading_pipe(pipe, address) ⇒ Object
- #open_writing_pipe(address) ⇒ Object
- #payload_size ⇒ Object
- #power_down ⇒ Object
- #power_up ⇒ Object
- #print_regs ⇒ Object
- #read ⇒ Object
- #read_payload ⇒ Object
- #received_power ⇒ Object
- #reuse_tx_payload ⇒ Object
- #rf_setup(datarate = :rate_1mbps, power = :max_power) ⇒ Object
- #send_command(command, data_len = 0) ⇒ Object
- #set_ack_payload(pipe, payload) ⇒ Object
- #set_address_width(aw = 5) ⇒ Object (also: #address_width=)
- #set_channel(ch) ⇒ Object (also: #channel=)
- #set_crc_length(length) ⇒ Object (also: #crc_length=)
- #set_payload_size(pipe, size) ⇒ Object
- #set_register(reg, value) ⇒ Object
- #set_retries(delay, count) ⇒ Object
- #set_tx_address(addr) ⇒ Object (also: #tx_address=)
- #start_listening ⇒ Object
- #status ⇒ Object
- #stop_listening ⇒ Object
- #write(payload, type = :ack, timeout = 2) ⇒ Object
- #write_no_ack(payload, *args) ⇒ Object
- #write_payload(payload, type = :ack) ⇒ Object
Instance Attribute Details
#static_payload_size ⇒ Object (readonly)
Returns the value of attribute static_payload_size.
10 11 12 |
# File 'lib/nrf24/nrf24-ruby.rb', line 10 def static_payload_size @static_payload_size end |
Class Method Details
.begin(*opts, &block) ⇒ Object
12 13 14 15 16 17 |
# 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 |
Instance Method Details
#activate ⇒ Object
325 326 327 |
# File 'lib/nrf24/nrf24-ruby.rb', line 325 def activate send_command :activate, 0x73 end |
#address_width ⇒ Object
261 262 263 |
# File 'lib/nrf24/nrf24-ruby.rb', line 261 def address_width @address_width || (get_register(:setup_aw) + 2) end |
#channel ⇒ Object
185 186 187 |
# File 'lib/nrf24/nrf24-ruby.rb', line 185 def channel get_register :rf_ch end |
#clear_interrupt_flags ⇒ Object
321 322 323 |
# 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) ⇒ Object
132 133 134 |
# 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 ⇒ Object
228 229 230 231 232 233 234 235 236 |
# 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? ⇒ Boolean
285 286 287 |
# File 'lib/nrf24/nrf24-ruby.rb', line 285 def data_available? (status >> RX_P_NO) & 0b111 if not fifo_rx_empty? end |
#datarate ⇒ Object
216 217 218 219 220 221 222 223 224 225 226 |
# 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) ⇒ Object
96 97 98 99 100 101 102 103 104 105 |
# 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 ⇒ Object
249 250 251 |
# 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 ⇒ Object
162 163 164 165 |
# 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? ⇒ Boolean
167 168 169 |
# File 'lib/nrf24/nrf24-ruby.rb', line 167 def dynamic_payload_enabled? get_register(:feature)[EN_DPL] > 0 end |
#enable_auto_ack(pipes = :all) ⇒ Object
85 86 87 88 89 90 91 92 93 94 |
# 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 ⇒ Object
157 158 159 160 |
# 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 ⇒ Object
305 306 307 308 309 310 311 312 313 314 315 |
# 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? ⇒ Boolean
301 302 303 |
# File 'lib/nrf24/nrf24-ruby.rb', line 301 def fifo_rx_empty? get_register(:fifo_status)[FIFO_RX_EMPTY] > 0 end |
#fifo_rx_full? ⇒ Boolean
297 298 299 |
# File 'lib/nrf24/nrf24-ruby.rb', line 297 def fifo_rx_full? get_register(:fifo_status)[FIFO_RX_FULL] > 0 end |
#fifo_tx_empty? ⇒ Boolean
293 294 295 |
# File 'lib/nrf24/nrf24-ruby.rb', line 293 def fifo_tx_empty? get_register(:fifo_status)[FIFO_TX_EMPTY] > 0 end |
#fifo_tx_full? ⇒ Boolean
289 290 291 |
# File 'lib/nrf24/nrf24-ruby.rb', line 289 def fifo_tx_full? get_register(:fifo_status)[FIFO_TX_FULL] > 0 end |
#flush_rx ⇒ Object
275 276 277 |
# File 'lib/nrf24/nrf24-ruby.rb', line 275 def flush_rx send_command :flush_rx end |
#flush_tx ⇒ Object
271 272 273 |
# File 'lib/nrf24/nrf24-ruby.rb', line 271 def flush_tx send_command :flush_tx end |
#get_dynamic_payload_size ⇒ Object
153 154 155 |
# 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) ⇒ Object
343 344 345 346 347 348 349 |
# 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) ⇒ Object
117 118 119 120 121 122 123 124 125 126 127 128 129 130 |
# 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) ⇒ Object
71 72 73 74 75 |
# 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 ⇒ Object
136 137 138 139 140 141 142 |
# 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 ⇒ Object
179 180 181 182 183 |
# 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 ⇒ Object
171 172 173 174 175 176 177 |
# 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 ⇒ Object
359 360 361 362 363 364 |
# File 'lib/nrf24/nrf24-ruby.rb', line 359 def print_regs REGS.each do |i, v| len = [:rx_addr_p0, :rx_addr_p1, :tx_addr].include?(i) ? address_width : 1 puts "register #{v.to_s(16).rjust(2, "0")} (#{i}): #{get_register i, len}" end end |
#read ⇒ Object
107 108 109 110 111 |
# File 'lib/nrf24/nrf24-ruby.rb', line 107 def read payload = read_payload clear_interrupt_flags payload end |
#read_payload ⇒ Object
113 114 115 |
# File 'lib/nrf24/nrf24-ruby.rb', line 113 def read_payload send_command :r_rx_payload, payload_size end |
#received_power ⇒ Object
317 318 319 |
# File 'lib/nrf24/nrf24-ruby.rb', line 317 def received_power get_register(:rpd) end |
#reuse_tx_payload ⇒ Object
279 280 281 282 283 |
# 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) ⇒ Object
193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 |
# 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) ⇒ Object
351 352 353 354 355 356 357 |
# 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) ⇒ Object
77 78 79 80 81 82 83 |
# 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) ⇒ Object Also known as: address_width=
265 266 267 268 269 |
# 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 |
#set_channel(ch) ⇒ Object Also known as: channel=
189 190 191 |
# File 'lib/nrf24/nrf24-ruby.rb', line 189 def set_channel ch set_register :rf_ch, ch end |
#set_crc_length(length) ⇒ Object Also known as: crc_length=
238 239 240 241 242 243 244 245 246 247 |
# 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 |
#set_payload_size(pipe, size) ⇒ Object
144 145 146 147 148 149 150 151 |
# 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) ⇒ Object
335 336 337 338 339 340 341 |
# 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) ⇒ Object
253 254 255 |
# 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) ⇒ Object Also known as: tx_address=
257 258 259 |
# File 'lib/nrf24/nrf24-ruby.rb', line 257 def set_tx_address addr set_register :tx_addr, addr end |
#start_listening ⇒ Object
19 20 21 22 23 24 25 26 27 |
# 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 ⇒ Object
329 330 331 332 333 |
# File 'lib/nrf24/nrf24-ruby.rb', line 329 def status with_csn { spi.read } end |
#stop_listening ⇒ Object
29 30 31 32 33 34 |
# 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) ⇒ Object
40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
# 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) ⇒ Object
36 37 38 |
# 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) ⇒ Object
56 57 58 59 60 61 62 63 64 65 66 67 68 69 |
# 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 |