nrf24l01-ruby 0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 80a9154047d11cb58a2a2da3656ad3ad2c56199a
4
+ data.tar.gz: f1ba069e70574c42536902817ce1fcdb28b66c55
5
+ SHA512:
6
+ metadata.gz: b361d65c676843f806d9dd6fc2f5acf61c9f19a9cd338eb80203a60530e15415d834bd05b9232c024c23a7941bcc64871daa1ba9c6f02bf6f75fef05ae7f3f9e
7
+ data.tar.gz: 68f63fa0d582514e17fdb317018236d21d0417e5ddfb33a3e78970a67409e701ef600bc70caf099ed22d952910f5f478178f030c0a1895e7453069b99480296a
data/.gitignore ADDED
@@ -0,0 +1,10 @@
1
+ /.idea/*
2
+ /.bundle/
3
+ /.yardoc
4
+ /Gemfile.lock
5
+ /_yardoc/
6
+ /coverage/
7
+ /doc/
8
+ /pkg/
9
+ /spec/reports/
10
+ /tmp/
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in nrf24-ruby.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2016 Rogier Lodewijks
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,98 @@
1
+ # nRF24 lib for Ruby
2
+
3
+ nrf24-ruby is a pure Ruby library for controlling the ubiquitous nRF24l01(+) radio module. Currently primary target is
4
+ the Raspberry Pi, but it shouldn't be too hard to port to a different platform (supporting SPI).
5
+
6
+ No webserver, no message bus, no frills, yet a fully functional lib written in clear Ruby. (If you're in need of frills,
7
+ bells, whistles and the like. This library gem works merrily together with all kinds of whistle implementing gems :smile:)
8
+
9
+ This gem was based on the [C++ RF24 library by tmrh20](https://github.com/TMRh20/RF24). I made the Ruby implementation
10
+ mostly because wrapping C++ from Ruby sucks donkey balls.
11
+
12
+ ## Installing
13
+ Currently there's only one hardware driver included, which relies on the bcm2835 gem that wraps the [bcm2835 C library](http://www.airspayce.com/mikem/bcm2835). Therefore we need
14
+ this C lib installed on our system.
15
+
16
+ Build the lib
17
+
18
+ wget http://www.airspayce.com/mikem/bcm2835/bcm2835-1.49.tar.gz
19
+ tar zxvf bcm2835-1.49.tar.gz
20
+ cd bcm2835-1.49
21
+ ./configure
22
+ make
23
+ sudo make check
24
+
25
+ Make the shared library (.so file) and copy into the correct location
26
+
27
+ cd src
28
+ gcc -shared -o libbcm2835.so bcm2835.o
29
+ sudo cp libbcm2835.so /usr/local/lib
30
+
31
+ _In case you don't feel like building the lib yourself, it's included in /binlib at your convenience._
32
+
33
+ **Caveat:** currently we're calling directly into the BCM2835's protected memory space, so we need to run as root.
34
+
35
+ Add this line to your application's Gemfile:
36
+
37
+ ```ruby
38
+ gem 'nrf24-ruby'
39
+ ```
40
+
41
+ And then execute:
42
+
43
+ $ bundle
44
+
45
+ Or install it yourself as:
46
+
47
+ $ gem install nrf24-ruby
48
+
49
+
50
+
51
+ ## Examples
52
+
53
+ ```ruby
54
+ require 'nrf24-ruby'
55
+ ```
56
+
57
+ The lib may be called using a block
58
+
59
+ ```ruby
60
+ NRF24.begin {
61
+
62
+ set_channel 23
63
+
64
+ print_regs
65
+
66
+ open_reading_pipe 1, [65, 65, 65, 65, 65]
67
+
68
+ start_listening
69
+
70
+ loop do
71
+ p read if data_available?
72
+ sleep 0.01
73
+ end
74
+
75
+ }
76
+ ```
77
+ Or use the plain old instance based approach
78
+
79
+ ```ruby
80
+ nrf = NRF24.new(channel: 0x4c)
81
+
82
+ nrf.rf_setup :rate_250kbps, :max_power
83
+
84
+ address = 'AAAAA'.unpack('c*')
85
+ nrf.open_reading_pipe 1, address
86
+
87
+ nrf.start_listening
88
+
89
+ loop do
90
+ if pipe = nrf.data_available?
91
+ puts "data on pipe #{pipe}, fifo flags: #{nrf.fifo_flags}"
92
+ data = nrf.read
93
+ p data
94
+ end
95
+
96
+ sleep 0.1 # Currently interrupt handling is not supported on Raspberry Pi, so we need to poll for new data
97
+ end
98
+ ```
Binary file
@@ -0,0 +1,51 @@
1
+ require 'msgpack'
2
+ require 'nrf24-ruby'
3
+
4
+ def with_block
5
+
6
+ NRF24.begin(channel: 85) {
7
+ puts "setting channel to #{ch = rand 125}"
8
+ # ch=85
9
+ # set_channel ch
10
+ print_regs
11
+
12
+ rf_setup :rate_250kbps, :max_power
13
+ open_reading_pipe 1, 'AAAAA'.unpack('c*')
14
+ start_listening
15
+
16
+ loop do
17
+ if data_available?
18
+ p read
19
+ puts "bytes received: #{read.count}"
20
+ end
21
+ end
22
+
23
+ }
24
+ end
25
+
26
+ def classic
27
+ nrf = NRF24.new channel: 85
28
+
29
+ nrf.rf_setup :rate_250kbps, :max_power
30
+
31
+ address = 'AAAAA'.unpack('c*')
32
+ nrf.open_reading_pipe 1, address
33
+
34
+ nrf.start_listening
35
+
36
+ nrf.print_regs
37
+ nrf.flush_rx
38
+
39
+ loop do
40
+ if pipe = nrf.data_available?
41
+ puts "Got data on pipe #{pipe}, FIFO flags: #{nrf.fifo_flags}"
42
+ data = nrf.read
43
+ p data
44
+ end
45
+
46
+ sleep 0.1
47
+ end
48
+
49
+ end
50
+
51
+ classic
data/lib/nrf24-ruby.rb ADDED
@@ -0,0 +1,4 @@
1
+ require 'nrf24/version'
2
+ require 'nrf24/constants'
3
+ require 'nrf24/nrf24-ruby'
4
+ require 'nrf24/bcm2835_driver'
@@ -0,0 +1,31 @@
1
+ require 'bcm2835'
2
+
3
+ class NRF24
4
+ module Bcm2835Driver
5
+
6
+ def init_io
7
+ @spi = Bcm2835::SPI.begin
8
+ spi.clock Bcm2835::SPI::CLOCK_DIVIDER_128
9
+ spi.bit_order(Bcm2835::SPI::MSBFIRST)
10
+ Bcm2835::GPIO.output cepin
11
+ Bcm2835::GPIO.output csnpin
12
+ end
13
+
14
+ def ce_high
15
+ Bcm2835::GPIO.set cepin
16
+ end
17
+
18
+ def ce_low
19
+ Bcm2835::GPIO.clear cepin
20
+ end
21
+
22
+ def csn_high
23
+ Bcm2835::GPIO.set csnpin
24
+ end
25
+
26
+ def csn_low
27
+ Bcm2835::GPIO.clear csnpin
28
+ end
29
+
30
+ end
31
+ end
@@ -0,0 +1,99 @@
1
+ class NRF24
2
+
3
+ COMMANDS = {
4
+ :r_register => 0x00,
5
+ :w_register => 0x20,
6
+ :activate => 0x50, # non-plus register only
7
+ :r_rx_pl_wid => 0x60,
8
+ :r_rx_payload => 0x61,
9
+ :w_tx_payload => 0xa0,
10
+ :w_ack_payload => 0xa8,
11
+ :w_tx_payload_noack => 0xb0,
12
+ :flush_tx => 0xe1,
13
+ :flush_rx => 0xe2,
14
+ :reuse_tx_pl => 0xe3,
15
+ :nop => 0xff
16
+ }
17
+
18
+ REGS = {
19
+ :config => 0x00, # Configuration Register
20
+ :en_aa => 0x01, # Enable ‘Auto Acknowledgment’ Function Disable this functionality to be compatible with nRF2401,
21
+ :en_rxaddr => 0x02, # Enabled RX Addresses
22
+ :setup_aw => 0x03, # Setup of Address Widths (common for all data pipes)
23
+ :setup_retr => 0x04, # Setup of Automatic Retransmission
24
+ :rf_ch => 0x05, # RF Channel
25
+ :rf_setup => 0x06, # RF Setup Register (power, rate)
26
+ :nrf_status => 0x07, # a.k.a. nrf24l01.rbStatus
27
+ :status => 0x07,
28
+ :observe_tx => 0x08, # Transmit observe register (packets lost, retransmits)
29
+ :cd => 0x09, # Legacy (nRF24l01 non+) name
30
+ :rpd => 0x09, # Received power detection (1 == > -64dBm)
31
+
32
+ :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)
33
+ :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)
34
+ :rx_addr_p2 => 0x0c, # Receive address data pipe 2. Only LSB. MSBytes are equal to RX_ADDR_P1[39:8]
35
+ :rx_addr_p3 => 0x0d, # Receive address data pipe 3. Only LSB. MSBytes are equal to RX_ADDR_P1[39:8]
36
+ :rx_addr_p4 => 0x0e, # Receive address data pipe 4. Only LSB. MSBytes are equal to RX_ADDR_P1[39:8]
37
+ :rx_addr_p5 => 0x0f, # Receive address data pipe 5. Only LSB. MSBytes are equal to RX_ADDR_P1[39:8]
38
+
39
+ :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.
40
+
41
+ :rx_pw_p0 => 0x11, # Number of bytes in RX payload in data pipe 0-5 (1 to 32 bytes).
42
+ :rx_pw_p1 => 0x12, #
43
+ :rx_pw_p2 => 0x13, # 0 Pipe not used
44
+ :rx_pw_p3 => 0x14, # 1 = 1 byte
45
+ :rx_pw_p4 => 0x15, # …
46
+ :rx_pw_p5 => 0x16, # 32 = 32 bytes
47
+
48
+ :fifo_status => 0x17, # FIFO Status Register
49
+ :dynpd => 0x1c,
50
+ :feature => 0x1d
51
+ }
52
+
53
+ # CONFIG
54
+ MASK_RX_DR = 6
55
+ MASK_TX_DS = 5
56
+ MASK_MAX_RT = 4
57
+ EN_CRC = 3
58
+ CRCO = 2
59
+ PWR_UP = 1
60
+ PRIM_RX = 0
61
+
62
+ # SETUP_RETR
63
+ ARD = 4
64
+ ARC = 0
65
+
66
+ # STATUS
67
+ RX_DR = 6 # Data Ready RX FIFO interrupt
68
+ TX_DS = 5 # Data Sent TX FIFO interrupt
69
+ MAX_RT = 4 # Maximum number of TX retransmits interrupt Write 1 to clear bit. If MAX_RT is asserted it must be cleared to enable further communication.
70
+ RX_P_NO = 1 # 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
71
+ TX_FULL = 0 # TX FIFO full flag. 1: TX FIFO full. 0: Available locations in TX FIFO.
72
+
73
+ # observe_tx
74
+ PLOS_CNT = 4 # 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.
75
+ ARC_CNT = 0 # 3:0 Count retransmitted packets.
76
+
77
+ # FIFO_STATUS
78
+ TX_REUSE = 6
79
+ FIFO_TX_FULL = 5
80
+ FIFO_TX_EMPTY = 4
81
+ FIFO_RX_FULL = 1
82
+ FIFO_RX_EMPTY = 0
83
+
84
+ # FEATURE
85
+ EN_DPL = 2
86
+ EN_ACK_PAY = 1
87
+ EN_DYN_ACK = 0
88
+
89
+ # RF_SETUP
90
+ RF_DR_LOW = 5
91
+ PLL_LOCK = 4
92
+ RF_DR_HIGH = 3
93
+ RF_PWR_LOW = 1
94
+ RF_PWR_HIGH = 2
95
+ LNA_HCURR = 0
96
+
97
+ REGISTER_MASK = 0x1F
98
+
99
+ end
@@ -0,0 +1,446 @@
1
+ require_relative 'constants'
2
+ class NRF24
3
+
4
+ class OverSizedPayload < RuntimeError
5
+ end
6
+
7
+ class TX_Timeout < RuntimeError
8
+ end
9
+
10
+ attr_reader :static_payload_size
11
+
12
+ def self.begin *opts, &block
13
+ nrf = NRF24.new *opts
14
+ nrf.instance_eval &block if block_given?
15
+ ensure
16
+ nrf.send :radio_deinit
17
+ end
18
+
19
+ def start_listening
20
+ set_register :config, get_register(:config) | bv(PRIM_RX)
21
+ clear_interrupt_flags
22
+ ce_high
23
+
24
+ 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)
25
+
26
+ flush_tx if get_register(:feature)[EN_ACK_PAY] > 0
27
+ end
28
+
29
+ def stop_listening
30
+ ce_low
31
+ flush_tx if get_register(:feature)[EN_ACK_PAY] > 0
32
+ set_register :config, get_register(:config) & inv_bv(PRIM_RX)
33
+ set_register :en_rxaddr, get_register(:en_rxaddr) | 1
34
+ end
35
+
36
+ def write_no_ack payload, *args
37
+ write(payload, :no_ack, *args)
38
+ end
39
+
40
+ def write payload, type = :ack, timeout = 2
41
+ start = Time.now
42
+
43
+ while fifo_tx_full?
44
+ if status[MAX_RT] > 0
45
+ set_register :nrf_status, bv(MAX_RT)
46
+ return :max_rt
47
+ end
48
+ raise TX_Timeout, "TX FIFO full" if Time.now - start > timeout
49
+ end
50
+
51
+ write_payload payload, type
52
+
53
+ pulse_ce
54
+ end
55
+
56
+ def write_payload payload, type = :ack
57
+ if dynamic_payload_enabled?
58
+ raise OverSizedPayload if payload.size > 32
59
+ else
60
+ raise OverSizedPayload if payload.size > static_payload_size
61
+ padding = static_payload_size - payload.size
62
+ end
63
+
64
+ with_csn {
65
+ spi.write COMMANDS[type == :no_ack ? :w_tx_payload_noack : :w_tx_payload]
66
+ spi.write payload
67
+ spi.write ([0] * padding)
68
+ }
69
+ end
70
+
71
+ def open_writing_pipe address
72
+ set_register :rx_addr_p0, address
73
+ set_register :tx_addr, address
74
+ set_register :rx_pw_p0, static_payload_size
75
+ end
76
+
77
+ def set_ack_payload pipe, payload
78
+ raise OverSizedPayload, "ack payload can be 32 bytes max!" if payload.size > 32
79
+ with_csn {
80
+ spi.write COMMANDS[:w_ack_payload] | (pipe & 7)
81
+ spi.write payload
82
+ }
83
+ end
84
+
85
+ def enable_auto_ack pipes = :all
86
+ if pipes == :all
87
+ set_register :en_aa, 0b111111
88
+ elsif pipes.is_a? Enumerable
89
+ pipes.map { |p| enable_auto_ack p }
90
+ else
91
+ return if pipes > 5
92
+ set_register :en_aa, get_register(:en_aa) | bv(pipes)
93
+ end
94
+ end
95
+
96
+ def disable_auto_ack pipes = :all
97
+ if pipes == :all
98
+ set_register :en_aa, 0
99
+ elsif pipes.is_a? Enumerable
100
+ pipes.map { |p| disable_auto_ack p }
101
+ else
102
+ return if pipes > 5
103
+ set_register :en_aa, get_register(:en_aa) & inv_bv(pipes)
104
+ end
105
+ end
106
+
107
+ def read
108
+ payload = read_payload
109
+ clear_interrupt_flags
110
+ payload
111
+ end
112
+
113
+ def read_payload
114
+ send_command :r_rx_payload, payload_size
115
+ end
116
+
117
+ def open_reading_pipe pipe, address
118
+ @pipe0_reading_address = address if pipe == 0
119
+
120
+ if pipe <= 5
121
+ if pipe < 2
122
+ set_register REGS[:rx_addr_p0] + pipe, address
123
+ else
124
+ set_register REGS[:rx_addr_p0] + pipe, address.first # Only LSB TODO Handle Numeric (byte) address
125
+ end
126
+ set_register REGS[:rx_pw_p0] + pipe, static_payload_size
127
+
128
+ set_register :en_rxaddr, get_register(:en_rxaddr) | bv(pipe)
129
+ end
130
+ end
131
+
132
+ def close_reading_pipe pipe
133
+ set_register :en_rxaddr, get_register(:en_rxaddr) & inv_bv(pipe)
134
+ end
135
+
136
+ def payload_size
137
+ if dynamic_payload_enabled?
138
+ get_dynamic_payload_size
139
+ else
140
+ static_payload_size
141
+ end
142
+ end
143
+
144
+ def set_payload_size pipe, size
145
+ if pipe.is_a? Enumerable
146
+ pipe.map { |p| set_payload_size p, size }
147
+ else
148
+ return if pipe > 5 # Lets make sure not to screw up other regs
149
+ set_register(REGS[:rx_pw_p0] + pipe, size)
150
+ end
151
+ end
152
+
153
+ def get_dynamic_payload_size
154
+ send_command :r_rx_pl_wid, 1
155
+ end
156
+
157
+ def enable_dynamic_payloads
158
+ set_register :feature, get_register(:feature) | bv(EN_DPL)
159
+ set_register :dynpd, 63 # Enable for all pipes
160
+ end
161
+
162
+ def disable_dynamic_payloads
163
+ set_register :feature, get_register(:feature) & inv_bv(EN_DPL)
164
+ set_register :dynpd, 0
165
+ end
166
+
167
+ def dynamic_payload_enabled?
168
+ get_register(:feature)[EN_DPL] > 0
169
+ end
170
+
171
+ def power_up
172
+ config = get_register(:config)
173
+ if config[PWR_UP] == 0
174
+ set_register :config, config | bv(PWR_UP)
175
+ sleep 0.01
176
+ end
177
+ end
178
+
179
+ def power_down
180
+ ce_low
181
+ config = get_register(:config) & inv_bv(PWR_UP)
182
+ set_register :config, config
183
+ end
184
+
185
+ def channel
186
+ get_register :rf_ch
187
+ end
188
+
189
+ def set_channel ch
190
+ set_register :rf_ch, ch
191
+ end
192
+
193
+ def rf_setup datarate = :rate_1mbps, power = :max_power
194
+ available_rates = {
195
+ :rate_250kbps => 32, 250 => 32,
196
+ :rate_1mbps => 0, 1 => 0, 1000 => 0,
197
+ :rate_2mbps => 8, 2 => 8, 2000 => 8
198
+ }
199
+
200
+ pa_settings = {
201
+ :min_power => 0, -18 => 0, 18 => 0,
202
+ :low_power => 2, -12 => 2, 12 => 2,
203
+ :high_power => 4, -6 => 4, 6 => 4,
204
+ :max_power => 6, 0 => 6
205
+ }
206
+
207
+ rate = available_rates[datarate]
208
+ power = pa_settings[power]
209
+
210
+ return nil unless rate && power
211
+
212
+ set_register :rf_setup, (rate | power)
213
+ get_register :rf_setup
214
+ end
215
+
216
+ def datarate
217
+ rf_setup = get_register :rf_setup
218
+
219
+ if rf_setup[RF_DR_LOW] == 1
220
+ :rate_250kbps
221
+ elsif rf_setup[RF_DR_HIGH] == 1
222
+ :rate_2mbps
223
+ else
224
+ :rate_1mbps
225
+ end
226
+ end
227
+
228
+ def crc_length
229
+ config = get_register(:config)
230
+
231
+ if config[EN_CRC] > 0 or get_register(:en_aa) > 0
232
+ config[CRCO] == 1 ? :crc_16 : :crc_8
233
+ else
234
+ :crc_none
235
+ end
236
+ end
237
+
238
+ def set_crc_length length
239
+ config = get_register(:config) & (~(bv(CRCO) | bv(EN_CRC)) & 0xff)
240
+
241
+ if [:crc_16, 16, 2].include? length
242
+ config |= (bv(EN_CRC) | bv(CRCO))
243
+ elsif [:crc_8, 8, 1].include? length
244
+ config |= bv(EN_CRC)
245
+ end
246
+ set_register :config, config
247
+ end
248
+
249
+ def disable_crc
250
+ set_register :config, get_register(:config) & inv_bv(EN_CRC)
251
+ end
252
+
253
+ def set_retries delay, count
254
+ set_register :setup_retr, ((delay & 0xf) << ARD) | ((count & 0xf) << ARC)
255
+ end
256
+
257
+ def set_tx_address addr
258
+ set_register :tx_addr, addr
259
+ end
260
+
261
+ def address_width
262
+ @address_width || (get_register(:setup_aw) + 2)
263
+ end
264
+
265
+ def set_address_width aw = 5
266
+ aw = (aw - 2) % 4;
267
+ set_register :setup_aw, aw
268
+ @address_width = aw + 2
269
+ end
270
+
271
+ def flush_tx
272
+ send_command :flush_tx
273
+ end
274
+
275
+ def flush_rx
276
+ send_command :flush_rx
277
+ end
278
+
279
+ def reuse_tx_payload
280
+ set_register :nrf_status, bv(MAX_RT)
281
+ send_commnad :reuse_tx_pl
282
+ pulse_ce
283
+ end
284
+
285
+ def data_available?
286
+ (status >> RX_P_NO) & 0b111 if not fifo_rx_empty?
287
+ end
288
+
289
+ def fifo_tx_full?
290
+ get_register(:fifo_status)[FIFO_TX_FULL] > 0
291
+ end
292
+
293
+ def fifo_tx_empty?
294
+ get_register(:fifo_status)[FIFO_TX_EMPTY] > 0
295
+ end
296
+
297
+ def fifo_rx_full?
298
+ get_register(:fifo_status)[FIFO_RX_FULL] > 0
299
+ end
300
+
301
+ def fifo_rx_empty?
302
+ get_register(:fifo_status)[FIFO_RX_EMPTY] > 0
303
+ end
304
+
305
+ def fifo_flags
306
+ flags = []
307
+ fifo_status = get_register(:fifo_status)
308
+
309
+ flags << :tx_full if fifo_tx_full?
310
+ flags << :tx_empty if fifo_tx_empty?
311
+ flags << :rx_full if fifo_rx_full?
312
+ flags << :rx_empty if fifo_rx_empty?
313
+
314
+ flags
315
+ end
316
+
317
+ def received_power
318
+ get_register(:rpd)
319
+ end
320
+
321
+ def clear_interrupt_flags
322
+ set_register :nrf_status, (1 << RX_DR) | (1 << TX_DS) | (1 << MAX_RT)
323
+ end
324
+
325
+ def activate
326
+ send_command :activate, 0x73
327
+ end
328
+
329
+ def status
330
+ with_csn {
331
+ spi.read
332
+ }
333
+ end
334
+
335
+ def set_register reg, value
336
+ reg = REGS[reg] unless reg.is_a? Numeric
337
+ with_csn {
338
+ spi.write(COMMANDS[:w_register] | (REGISTER_MASK & reg))
339
+ spi.write value
340
+ }
341
+ end
342
+
343
+ def get_register reg, len = 1
344
+ reg = REGS[reg] unless reg.is_a? Numeric
345
+ with_csn {
346
+ spi.write(COMMANDS[:r_register] | (REGISTER_MASK & reg))
347
+ len == 1 ? spi.read : spi.read(len) # do not return an array when len == 1
348
+ } if reg
349
+ end
350
+
351
+ def send_command command, data_len = 0
352
+ command = COMMANDS[command] unless command.is_a? Numeric
353
+ with_csn {
354
+ spi.write command
355
+ spi.read(data_len) if data_len > 0
356
+ }
357
+ end
358
+
359
+ def print_regs
360
+ REGS.each do |i, v|
361
+ len = [:rx_addr_p0, :rx_addr_p1, :tx_addr].include?(i) ? address_width : 1
362
+ puts "register #{v.to_s(16).rjust(2, "0")} (#{i}): #{get_register i, len}"
363
+ end
364
+ end
365
+
366
+ private
367
+
368
+ alias_method :channel=, :set_channel
369
+ alias_method :tx_address=, :set_tx_address
370
+ alias_method :address_width=, :set_address_width
371
+ alias_method :crc_length=, :set_crc_length
372
+
373
+ attr_reader :spi, :cepin, :csnpin
374
+
375
+ def initialize opts = {}
376
+ opts = {cepin: 22, csnpin: 8, static_payload_size: 32, channel: 76, driver: Bcm2835Driver}.merge opts
377
+
378
+ @cepin = opts[:cepin]
379
+ @csnpin = opts[:csnpin]
380
+ @static_payload_size = [opts[:static_payload_size], 32].min
381
+ @channel = opts[:channel]
382
+
383
+ extend opts[:driver]
384
+
385
+ init_io
386
+ radio_init
387
+
388
+ @pipe0_reading_address = nil
389
+ end
390
+
391
+ def radio_init
392
+ activate # nrf24l01 (non-plus) compatibility
393
+
394
+ set_address_width
395
+
396
+ set_channel @channel
397
+
398
+ set_payload_size (0..5), static_payload_size
399
+ disable_dynamic_payloads
400
+ enable_auto_ack
401
+
402
+ set_register :config, ((1 << EN_CRC) | (1 << CRCO) | (1 << PWR_UP) | (1 << PRIM_RX))
403
+
404
+ clear_interrupt_flags
405
+
406
+ flush_rx
407
+ flush_tx
408
+ end
409
+
410
+ def radio_deinit
411
+ ce_low
412
+ radio_init
413
+ rf_setup
414
+ set_channel 0
415
+ end
416
+
417
+ def with_csn
418
+ csn_low
419
+ ret = yield
420
+ csn_high
421
+ ret
422
+ end
423
+
424
+ def with_ce
425
+ ce_high
426
+ ret = yield
427
+ ce_low
428
+ ret
429
+ end
430
+
431
+ def pulse_ce us = 10
432
+ ce_high
433
+ sleep(0.000001 * us)
434
+ ce_low
435
+ end
436
+
437
+ # Low level bit vector stuff
438
+ def bv d
439
+ 1 << d
440
+ end
441
+
442
+ def inv_bv d, mask = 0xff
443
+ ~(1 << d) & mask
444
+ end
445
+
446
+ end
@@ -0,0 +1,3 @@
1
+ class NRF24
2
+ VERSION = '0.5'
3
+ end
@@ -0,0 +1,24 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'nrf24/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "nrf24l01-ruby"
8
+ spec.version = NRF24::VERSION
9
+ spec.authors = ["Rogier Lodewijks"]
10
+ spec.email = ["rogier@lodewijks.org"]
11
+
12
+ spec.summary = %q{nrf24-ruby is a pure Ruby library for controlling the ubiquitous Nordic nRF24l01(+) radio module.}
13
+ spec.description = %q{nrf24-ruby is a pure Ruby library for controlling the ubiquitous Nordic nRF24l01(+) radio module. Currently primary target is the Raspberry Pi, but it shouldn't be too hard to port to a different platform (supporting SPI). No webserver, no message bus, no frills, yet a fully functional lib written in clear Ruby.}
14
+
15
+ spec.homepage = "https://github.com/eflukx/nrf24-ruby"
16
+ spec.license = "MIT"
17
+
18
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
19
+ spec.bindir = "exe"
20
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
21
+ spec.require_paths = ["lib", "lib/nrf24"]
22
+
23
+ spec.add_dependency 'bcm2835', '~> 0.0', '>= 0.0.1'
24
+ end
metadata ADDED
@@ -0,0 +1,81 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: nrf24l01-ruby
3
+ version: !ruby/object:Gem::Version
4
+ version: '0.5'
5
+ platform: ruby
6
+ authors:
7
+ - Rogier Lodewijks
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2016-04-03 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bcm2835
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '0.0'
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: 0.0.1
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - "~>"
28
+ - !ruby/object:Gem::Version
29
+ version: '0.0'
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: 0.0.1
33
+ description: nrf24-ruby is a pure Ruby library for controlling the ubiquitous Nordic
34
+ nRF24l01(+) radio module. Currently primary target is the Raspberry Pi, but it shouldn't
35
+ be too hard to port to a different platform (supporting SPI). No webserver, no message
36
+ bus, no frills, yet a fully functional lib written in clear Ruby.
37
+ email:
38
+ - rogier@lodewijks.org
39
+ executables: []
40
+ extensions: []
41
+ extra_rdoc_files: []
42
+ files:
43
+ - ".gitignore"
44
+ - Gemfile
45
+ - LICENSE.txt
46
+ - README.md
47
+ - binlib/libbcm2835.so
48
+ - example/nrf24_listening_example.rb
49
+ - lib/nrf24-ruby.rb
50
+ - lib/nrf24/bcm2835_driver.rb
51
+ - lib/nrf24/constants.rb
52
+ - lib/nrf24/nrf24-ruby.rb
53
+ - lib/nrf24/version.rb
54
+ - nrf24-ruby.gemspec
55
+ homepage: https://github.com/eflukx/nrf24-ruby
56
+ licenses:
57
+ - MIT
58
+ metadata: {}
59
+ post_install_message:
60
+ rdoc_options: []
61
+ require_paths:
62
+ - lib
63
+ - lib/nrf24
64
+ required_ruby_version: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ required_rubygems_version: !ruby/object:Gem::Requirement
70
+ requirements:
71
+ - - ">="
72
+ - !ruby/object:Gem::Version
73
+ version: '0'
74
+ requirements: []
75
+ rubyforge_project:
76
+ rubygems_version: 2.2.5
77
+ signing_key:
78
+ specification_version: 4
79
+ summary: nrf24-ruby is a pure Ruby library for controlling the ubiquitous Nordic nRF24l01(+)
80
+ radio module.
81
+ test_files: []