File Coverage

blib/lib/Device/BusPirate/Chip/nRF24L01P.pm
Criterion Covered Total %
statement 30 198 15.1
branch 0 68 0.0
condition 0 37 0.0
subroutine 10 54 18.5
pod 11 20 55.0
total 51 377 13.5


line stmt bran cond sub pod time code
1             # You may distribute under the terms of either the GNU General Public License
2             # or the Artistic License (the same terms as Perl itself)
3             #
4             # (C) Paul Evans, 2014 -- leonerd@leonerd.org.uk
5              
6             package Device::BusPirate::Chip::nRF24L01P;
7              
8 1     1   567 use strict;
  1         2  
  1         34  
9 1     1   4 use warnings;
  1         1  
  1         26  
10 1     1   25 use 5.010;
  1         2  
  1         26  
11 1     1   4 use base qw( Device::BusPirate::Chip );
  1         1  
  1         466  
12              
13             our $VERSION = '0.01';
14              
15 1     1   311 use Carp;
  1         1  
  1         59  
16              
17 1     1   3 use constant CHIP => "nRF24L01+";
  1         2  
  1         47  
18 1     1   4 use constant MODE => "SPI";
  1         1  
  1         31  
19              
20 1     1   4 use constant DEFAULT_SPEED => "1M";
  1         1  
  1         175  
21              
22             =head1 NAME
23              
24             C - use an F chip with C
25              
26             =head1 DESCRIPTION
27              
28             This L subclass provides specific communication to a
29             F F chip attached to the F via
30             SPI.
31              
32             The reader is presumed to be familiar with the general operation of this chip;
33             the documentation here will not attempt to explain or define chip-specific
34             concepts or features, only the use of this module to access them.
35              
36             =cut
37              
38             sub new
39             {
40 0     0 1   my $class = shift;
41 0           my ( $bp, %opts ) = @_;
42              
43 0           my $self = $class->SUPER::new( @_ );
44              
45 0           $self->{$_} = $opts{$_} for qw( open_drain speed );
46              
47 0           $self->{registers} = []; # cache of the values we write to config registers
48              
49 0           return $self;
50             }
51              
52             sub mount
53             {
54 0     0 1   my $self = shift;
55 0           my ( $mode ) = @_;
56              
57             $self->SUPER::mount( $mode )
58             ->then( sub {
59 0   0 0     $mode->configure(
60             open_drain => $self->{open_drain},
61             speed => $self->{speed} // DEFAULT_SPEED,
62             );
63             })
64 0           }
65              
66             =head1 METHODS
67              
68             =cut
69              
70             # Commands
71             use constant {
72 1         208 CMD_R_REGISTER => 0x00,
73             CMD_W_REGISTER => 0x20,
74             CMD_R_RX_PAYLOAD => 0x61,
75             CMD_W_TX_PAYLOAD => 0xA0,
76             CMD_FLUSH_TX => 0xE1,
77             CMD_FLUSH_RX => 0xE2,
78             CMD_REUSE_TX_PL => 0xE3,
79             CMD_R_RX_PL_WID => 0x60,
80             CMD_W_ACK_PAYLOAD => 0xA8,
81             CMD_W_TX_PAYLOAD_NO_ACK => 0xB0,
82             CMD_NOP => 0xFF,
83 1     1   4 };
  1         1  
84              
85             # Register numbers and lengths, and bitfields
86             use constant {
87 1         3144 REG_CONFIG => [ 0x00, 1 ],
88             MASK_RX_RD => 1<<6,
89             MASK_TX_DS => 1<<5,
90             MASK_MAX_RT => 1<<4,
91             EN_CRC => 1<<3,
92             CRCO => 1<<2,
93             PWR_UP => 1<<1,
94             PRIM_RX => 1<<0,
95             REG_EN_AA => [ 0x01, 1 ],
96             # per-pipe bitmask
97             REG_EN_RXADDR => [ 0x02, 1 ],
98             # per-pipe bitmask
99             REG_SETUP_AW => [ 0x03, 1 ],
100             # int
101             REG_SETUP_RETR => [ 0x04, 1 ],
102             ARD => 0x0f<<4,
103             ARC => 0x0f,
104             REG_RF_CH => [ 0x05, 1 ],
105             # int
106             REG_RF_SETUP => [ 0x06, 1 ],
107             CONT_WAVE => 1<<7,
108             RF_DR_LOW => 1<<5,
109             PLL_LOCK => 1<<4,
110             RF_DR_HIGH => 1<<3,
111             RF_PWR => 3<<1,
112             REG_STATUS => [ 0x07, 1 ],
113             RX_DR => 1<<6,
114             TX_DS => 1<<5,
115             MAX_RT => 1<<4,
116             RX_P_NO => 7<<1,
117             TX_FULL_STAT => 1<<0,
118             REG_OBSERVE_TX => [ 0x08, 1 ],
119             PLOS_CNT => 0x0f<<4,
120             ARC_CNT => 0x0f,
121             REG_RPD => [ 0x09, 1 ],
122             # bool
123             REG_RX_ADDR_P0 => [ 0x0A, 5 ],
124             REG_RX_ADDR_P1 => [ 0x0B, 5 ],
125             REG_RX_ADDR_P2 => [ 0x0C, 1 ],
126             REG_RX_ADDR_P3 => [ 0x0D, 1 ],
127             REG_RX_ADDR_P4 => [ 0x0E, 1 ],
128             REG_RX_ADDR_P5 => [ 0x0F, 1 ],
129             REG_TX_ADDR => [ 0x10, 5 ],
130             # addresses
131             REG_RX_PW_P0 => [ 0x11, 1 ],
132             REG_RX_PW_P1 => [ 0x12, 1 ],
133             REG_RX_PW_P2 => [ 0x13, 1 ],
134             REG_RX_PW_P3 => [ 0x14, 1 ],
135             REG_RX_PW_P4 => [ 0x15, 1 ],
136             REG_RX_PW_P5 => [ 0x16, 1 ],
137             # ints
138             REG_FIFO_STATUS => [ 0x17, 1 ],
139             TX_REUSE => 1<<6,
140             TX_FULL => 1<<5,
141             TX_EMPTY => 1<<4,
142             RX_FULL => 1<<1,
143             RX_EMPTY => 1<<0,
144             REG_DYNPD => [ 0x1C, 1 ],
145             # per-pipe bitmask
146             REG_FEATURE => [ 0x1D, 1 ],
147             EN_DPL => 1<<2,
148             EN_ACK_PAY => 1<<1,
149             EN_DYN_ACK => 1<<0,
150 1     1   5 };
  1         1  
151              
152             =head2 $nrf->clear_caches
153              
154             The chip object stores a cache of the register values it last read or wrote,
155             so it can optimise updates of configuration. This method clears these caches,
156             ensuring a fresh SPI transfer next time the register needs to be read.
157              
158             This should not normally be necessary, other than for debugging.
159              
160             =cut
161              
162             sub clear_caches
163             {
164 0     0 1   my $self = shift;
165 0           undef @{ $self->{registers} };
  0            
166             }
167              
168             =head2 $status = $nrf->latest_status
169              
170             Returns the latest cached copy of the status register from the most recent SPI
171             interaction. As this method does not perform any IO, it returns its result
172             immediately rather than via a Future.
173              
174             Returns a HASH reference containing the following boolean fields
175              
176             RX_DR TX_DS MAX_RT TX_FULL
177              
178             Also returned is a field called C, which is either a pipe number (0
179             to 5) or undef.
180              
181             =cut
182              
183             sub _decode_status
184             {
185 0     0     my ( $status ) = @_;
186              
187 0           my $rx_p_no = ( $status & RX_P_NO ) >> 1;
188 0 0         undef $rx_p_no if $rx_p_no > 5;
189              
190             return {
191 0           RX_DR => !!( $status & RX_DR ),
192             TX_DS => !!( $status & TX_DS ),
193             MAX_RT => !!( $status & MAX_RT ),
194             RX_P_NO => $rx_p_no,
195             TX_FULL => !!( $status & TX_FULL_STAT ), # different mask to FIFO_STATUS
196             }
197             }
198              
199             sub latest_status
200             {
201 0     0 1   my $self = shift;
202 0           return _decode_status $self->{latest_status};
203             }
204              
205             =head2 $nrf->reset_interrupt->get
206              
207             Clears the interrupt flags in the C register.
208              
209             =cut
210              
211             sub reset_interrupt
212             {
213 0     0 0   my $self = shift;
214              
215 0           $self->_write_register_volatile( REG_STATUS, chr( RX_DR | TX_DS | MAX_RT ) );
216             }
217              
218             sub _do_command
219             {
220 0     0     my $self = shift;
221 0           my ( $cmd, $data ) = @_;
222 0   0       $data //= "";
223              
224             $self->mode->writeread_cs( chr( $cmd ) . $data )->then( sub {
225 0     0     my ( $buf ) = @_;
226 0           $self->{latest_status} = ord substr $buf, 0, 1, "";
227 0           Future->done( $buf );
228 0           });
229             }
230              
231             =head2 $status = $nrf->read_status->get
232              
233             Reads and returns the current content of the status register as a HASH
234             reference as per C.
235              
236             =cut
237              
238             sub read_status
239             {
240 0     0 0   my $self = shift;
241             $self->_do_command( CMD_NOP )->then( sub {
242 0     0     Future->done( $self->latest_status )
243 0           });
244             }
245              
246             # Always performs an SPI operation
247             sub _read_register_volatile
248             {
249 0     0     my $self = shift;
250 0           my ( $reg ) = @_;
251              
252 0           my ( $regnum, $len ) = @$reg;
253              
254             $self->_do_command( CMD_R_REGISTER | $regnum, ( "\0" x $len ) )
255             ->on_done( sub {
256 0     0     $self->{registers}[$regnum] = $_[0];
257 0           });
258             }
259              
260             # Returns the cached value if present
261             sub _read_register
262             {
263 0     0     my $self = shift;
264 0           my ( $reg ) = @_;
265              
266 0           my ( $regnum ) = @$reg;
267              
268 0 0         defined $self->{registers}[$regnum] ?
269             Future->done( $self->{registers}[$regnum] ) :
270             $self->_read_register_volatile( $reg );
271             }
272              
273             # Always performs an SPI operation
274             sub _write_register_volatile
275             {
276 0     0     my $self = shift;
277 0           my ( $reg, $data ) = @_;
278              
279 0           my ( $regnum, $len ) = @$reg;
280 0 0         $len == length $data or croak "Attempted to write the wrong length";
281              
282             $self->_do_command( CMD_W_REGISTER | $regnum, $data )
283             ->then( sub {
284 0     0     $self->{registers}[$regnum] = $data;
285 0           Future->done()
286 0           });
287             }
288              
289             # Doesn't bother if no change
290             sub _write_register
291             {
292 0     0     my $self = shift;
293 0           my ( $reg, $data ) = @_;
294              
295 0           my ( $regnum ) = @$reg;
296              
297 0 0 0       return Future->done() if
298             defined $self->{registers}[$regnum] and $self->{registers}[$regnum] eq $data;
299              
300 0           return $self->_write_register_volatile( $reg, $data );
301             }
302              
303             =head2 $config = $nrf->read_config->get
304              
305             =head2 $nrf->change_config( %config )->get
306              
307             Reads or writes the chip-wide configuration. This is an amalgamation of all
308             the non-pipe-specific configuration registers; C, C,
309             C, C, C, C and C.
310              
311             When reading, the fields are returned in a HASH reference whose names are the
312             original bitfield names found in the F data sheet. When
313             writing, these fields are accepted as named parameters to the C
314             method directly.
315              
316             Some of the fields have special processing for convenience. They are:
317              
318             =over 4
319              
320             =item * CRCO
321              
322             Gives the CRC length in bytes, as either 1 or 2.
323              
324             =item * AW
325              
326             Gives the full address width in bytes, between 3 and 5.
327              
328             =item * ARD
329              
330             Gives the auto retransmit delay in microseconds directly; a multiple of 250
331             between 250 and 4000.
332              
333             =item * RF_DR
334              
335             Gives the RF data rate in bytes/sec; omits the C and C
336             fields; as 250000, 1000000 or 2000000
337              
338             =item * RF_PWR
339              
340             Gives the RF output power in dBm directly, as -18, -12, -6 or 0.
341              
342             =item * TX_ADDR
343              
344             Gives the PTX address as a string of 5 capital hexadecimal encoded octets,
345             separated by colons.
346              
347             =back
348              
349             Whenever the config is read it is cached within the C<$chip> instance.
350             Whenever it is written, any missing fields in the passed configuration are
351             pre-filled by the cached config, and only those registers that need writing
352             will be written.
353              
354             =cut
355              
356             my @CRCOs = ( 1, 2 );
357             my @AWs = ( undef, 3, 4, 5 );
358             my @ARDs = map { ( $_ + 1 ) * 250 } 0 .. 15;
359             my @RF_DRs = ( 1E6, 2E6, 250E3, undef );
360             my @RF_PWRs = ( -18, -12, -6, 0 );
361              
362             sub _idx_of
363             {
364 0     0     my $want = shift;
365 0           foreach my $idx ( 0 .. $#_ ) {
366 0 0 0       defined $_[$idx] and $_[$idx] == $want and return $idx;
367             }
368 0           return undef;
369             }
370              
371             sub _unpack_addr
372             {
373 0     0     my ( $addr ) = @_;
374 0           return join ":", map { sprintf "%02X", ord } split //, $addr;
  0            
375             }
376              
377             sub _pack_addr
378             {
379 0     0     my ( $addr ) = @_;
380 0           return join "", map { chr hex } split m/:/, $addr;
  0            
381             }
382              
383             sub _unpack_config
384             {
385 0     0     my %regs = @_;
386              
387 0           my $config = $regs{config};
388 0           my $setup_retr = $regs{setup_retr};
389 0           my $rf_setup = $regs{rf_setup};
390 0           my $feature = $regs{feature};
391              
392             return
393             # REG_CONFIG
394             MASK_RX_RD => !!( $config & MASK_RX_RD ),
395             MASK_TX_DS => !!( $config & MASK_TX_DS ),
396             MASK_MAX_RT => !!( $config & MASK_MAX_RT ),
397             EN_CRC => !!( $config & EN_CRC ),
398             CRCO => $CRCOs[!!( $config & CRCO )],
399             PWR_UP => !!( $config & PWR_UP ),
400             PRIM_RX => !!( $config & PRIM_RX ),
401              
402             # REG_SETUP_AW
403             AW => $AWs[ $regs{setup_aw} & 0x03 ],
404              
405             # REG_SETUP_RETR
406             ARD => $ARDs[( $setup_retr & ARD ) >> 4],
407             ARC => ( $setup_retr & ARC ),
408              
409             # REG_RF_CH
410             RF_CH => $regs{rf_ch},
411              
412             # REG_RF_SETUP
413             CONT_WAVE => !!( $rf_setup & CONT_WAVE ),
414             PLL_LOCK => !!( $rf_setup & PLL_LOCK ),
415 0           RF_DR => do {
416 0           my $rf_dr = 2*!!( $rf_setup & RF_DR_LOW ) + !!( $rf_setup & RF_DR_HIGH );
417 0           $RF_DRs[$rf_dr] },
418             RF_PWR => $RF_PWRs[( $rf_setup & RF_PWR ) >> 1],
419              
420             # REG_TX_ADDR
421             TX_ADDR => _unpack_addr( $regs{tx_addr} ),
422              
423             # REG_FEATURE
424             EN_DPL => !!( $feature & EN_DPL ),
425             EN_ACK_PAY => !!( $feature & EN_ACK_PAY ),
426             EN_DYN_ACK => !!( $feature & EN_DYN_ACK ),
427             }
428              
429             sub _pack_config
430             {
431 0     0     my %config = @_;
432              
433             return
434             config => (
435             ( $config{MASK_RX_RD} ? MASK_RX_RD : 0 ) |
436             ( $config{MASK_TX_DS} ? MASK_TX_DS : 0 ) |
437             ( $config{MASK_MAX_RT} ? MASK_MAX_RT : 0 ) |
438             ( $config{EN_CRC} ? EN_CRC : 0 ) |
439             ( ( _idx_of $config{CRCO}, @CRCOs ) // croak "Unsupported 'CRCO'" ) * CRCO |
440             ( $config{PWR_UP} ? PWR_UP : 0 ) |
441             ( $config{PRIM_RX} ? PRIM_RX : 0 ) ),
442              
443             setup_aw => (
444             ( _idx_of $config{AW}, @AWs ) // croak "Unsupported 'AW'" ),
445              
446             setup_retr => (
447             ( ( _idx_of $config{ARD}, @ARDs ) // croak "Unsupported 'ARD'" ) << 4 |
448             $config{ARC} ),
449              
450             rf_ch => $config{RF_CH},
451              
452 0 0 0       rf_setup => do {
    0 0        
    0 0        
    0          
    0          
    0          
    0          
    0          
    0          
453 0   0       my $rf_dr = ( _idx_of $config{RF_DR}, @RF_DRs ) // croak "Unsupported 'RF_DR'";
454              
455 0 0 0       ( $config{CONT_WAVE} ? CONT_WAVE : 0 ) |
    0          
    0          
    0          
456             ( ( $rf_dr & 2 ) ? RF_DR_LOW : 0 ) |
457             ( $config{PLL_LOCK} ? PLL_LOCK : 0 ) |
458             ( ( $rf_dr & 1 ) ? RF_DR_HIGH : 0 ) |
459             ( ( _idx_of $config{RF_PWR}, @RF_PWRs ) // croak "Unsupported 'RF_PWR'" ) << 1
460             },
461              
462             tx_addr => _pack_addr( $config{TX_ADDR} ),
463              
464             feature => (
465             ( $config{EN_DPL} ? EN_DPL : 0 ) |
466             ( $config{EN_ACK_PAY} ? EN_ACK_PAY : 0 ) |
467             ( $config{EN_DYN_ACK} ? EN_DYN_ACK : 0 ) );
468             }
469              
470             sub read_config
471             {
472 0     0 0   my $self = shift;
473              
474 0           Future->needs_all(
475             map { $self->_read_register( $_ ) }
476             REG_CONFIG, REG_SETUP_AW, REG_SETUP_RETR, REG_RF_CH, REG_RF_SETUP, REG_TX_ADDR, REG_FEATURE,
477             )->then( sub {
478 0     0     $_ = ord $_ for @_[0,1,2,3,4,6]; # [5] is TX_ADDR
479 0           my %regs;
480 0           @regs{qw( config setup_aw setup_retr rf_ch rf_setup tx_addr feature )} = @_;
481              
482 0           Future->done( { _unpack_config %regs } );
483 0           });
484             }
485              
486             sub change_config
487             {
488 0     0 1   my $self = shift;
489 0           my %changes = @_;
490              
491             $self->read_config
492             ->then( sub {
493 0     0     my ( $config ) = @_;
494 0           my %new_registers = _pack_config %$config, %changes;
495              
496 0           my @f;
497 0           foreach (qw( config setup_aw setup_retr rf_ch rf_setup feature )) {
498 0           push @f, $self->_write_register( $self->${\"REG_\U$_"}, chr $new_registers{$_} );
  0            
499             }
500 0           push @f, $self->_write_register( REG_TX_ADDR, $new_registers{tx_addr} );
501              
502 0           Future->needs_all( @f )
503 0           })->then_done();
504             }
505              
506             =head2 $config = $nrf->read_rx_config( $pipeno )->get
507              
508             =head2 $nrf->change_rx_config( $pipeno, %config )->get
509              
510             Reads or writes the per-pipe RX configuration. This is composed of the
511             per-pipe bits of the C and C registers and its
512             C register.
513              
514             Addresses are given as a string of 5 octets in capitalised hexadecimal
515             notation, separated by colons.
516              
517             When reading an address from pipes 2 to 5, the address of pipe 1 is used to
518             build a complete address string to return. When writing and address to these
519             pipes, all but the final byte is ignored.
520              
521             =cut
522              
523             sub read_rx_config
524             {
525 0     0 1   my $self = shift;
526 0           my ( $pipeno ) = @_;
527              
528 0 0 0       $pipeno >= 0 and $pipeno < 6 or croak "Invalid pipe number $pipeno";
529 0           my $mask = 1 << $pipeno;
530              
531 0           Future->needs_all(
532 0           map { $self->_read_register( $_ ) }
533             REG_EN_AA, REG_EN_RXADDR, REG_DYNPD, # bitwise
534 0           $self->${\"REG_RX_PW_P$pipeno"}, $self->${\"REG_RX_ADDR_P$pipeno"},
535             # Pipes 2 to 5 share the first 4 octects of PIPE1's address
536             ( $pipeno >= 2 ? REG_RX_ADDR_P1 : () ),
537             )->then( sub {
538 0     0     my ( $en_aa, $en_rxaddr, $dynpd, $width, $addr, $p1addr ) = @_;
539 0           $_ = ord $_ for $en_aa, $en_rxaddr, $dynpd, $width;
540              
541 0 0         $addr = substr( $p1addr, 0, 4 ) . $addr if $pipeno >= 2;
542              
543 0           Future->done( {
544             EN_AA => !!( $en_aa & $mask ),
545             EN_RXADDR => !!( $en_rxaddr & $mask ),
546             DYNPD => !!( $dynpd & $mask ),
547             RX_PW => $width,
548             RX_ADDR => _unpack_addr $addr,
549             } );
550 0 0         });
551             }
552              
553             sub change_rx_config
554             {
555 0     0 1   my $self = shift;
556 0           my ( $pipeno, %changes ) = @_;
557              
558 0 0 0       $pipeno >= 0 and $pipeno < 6 or croak "Invalid pipe number $pipeno";
559 0           my $mask = 1 << $pipeno;
560              
561 0           my $REG_RX_PW_Pn = $self->${\"REG_RX_PW_P$pipeno"};
  0            
562 0           my $REG_RX_ADDR_Pn = $self->${\"REG_RX_ADDR_P$pipeno"};
  0            
563              
564 0           Future->needs_all(
565             map { $self->_read_register( $_ ) }
566             REG_EN_AA, REG_EN_RXADDR, REG_DYNPD, $REG_RX_PW_Pn, $REG_RX_ADDR_Pn
567             )->then( sub {
568 0     0     my ( $en_aa, $en_rxaddr, $dynpd, $width, $addr ) = @_;
569 0           $_ = ord $_ for $en_aa, $en_rxaddr, $dynpd, $width;
570              
571 0 0         if( exists $changes{EN_AA} ) {
572 0           $en_aa &= ~$mask;
573 0 0         $en_aa |= $mask if $changes{EN_AA};
574             }
575 0 0         if( exists $changes{EN_RXADDR} ) {
576 0           $en_rxaddr &= ~$mask;
577 0 0         $en_rxaddr |= $mask if $changes{EN_RXADDR};
578             }
579 0 0         if( exists $changes{DYNPD} ) {
580 0           $dynpd &= ~$mask;
581 0 0         $dynpd |= $mask if $changes{DYNPD};
582             }
583 0 0         if( exists $changes{RX_PW} ) {
584 0           $width = $changes{RX_PW};
585             }
586 0 0         if( exists $changes{RX_ADDR} ) {
587 0           $addr = _pack_addr $changes{RX_ADDR};
588 0 0         $addr = substr( $addr, -1 ) if $pipeno >= 2;
589             }
590              
591             Future->needs_all(
592 0           $self->_write_register( REG_EN_AA, chr $en_aa ),
593             $self->_write_register( REG_EN_RXADDR, chr $en_rxaddr ),
594             $self->_write_register( REG_DYNPD, chr $dynpd ),
595             $self->_write_register( $REG_RX_PW_Pn, chr $width ),
596             $self->_write_register( $REG_RX_ADDR_Pn, $addr ),
597             );
598 0           })->then_done();
599             }
600              
601             =head2 $counts = $nrf->observe_tx_counts->get
602              
603             Reads the C register and returns the two counts from it.
604              
605             =cut
606              
607             sub observe_tx_counts
608             {
609 0     0 0   my $self = shift;
610              
611             $self->_read_register_volatile( REG_OBSERVE_TX )->then( sub {
612 0     0     my ( $buf ) = @_;
613 0           $buf = ord $buf;
614              
615 0           Future->done( {
616             PLOS_CNT => ( $buf & PLOS_CNT ) >> 4,
617             ARC_CNT => ( $buf & ARC_CNT ),
618             } );
619 0           });
620             }
621              
622             =head2 $rpd = $nrf->rpd->get
623              
624             Reads the C register
625              
626             =cut
627              
628             sub rpd
629             {
630 0     0 0   my $self = shift;
631              
632             $self->_read_register_volatile( REG_RPD )->then( sub {
633 0     0     my ( $buf ) = @_;
634 0           $buf = ord $buf;
635              
636 0           Future->done( $buf & 1 );
637 0           });
638             }
639              
640             =head2 $status = $nrf->fifo_status->get
641              
642             Reads the C register and returns the five bit fields from it.
643              
644             =cut
645              
646             sub fifo_status
647             {
648 0     0 0   my $self = shift;
649              
650             $self->_read_register_volatile( REG_FIFO_STATUS )->then( sub {
651 0     0     my ( $buf ) = @_;
652 0           $buf = ord $buf;
653              
654 0           Future->done( {
655             TX_REUSE => !!( $buf & TX_REUSE ),
656             TX_FULL => !!( $buf & TX_FULL ),
657             TX_EMPTY => !!( $buf & TX_EMPTY ),
658              
659             RX_FULL => !!( $buf & RX_FULL ),
660             RX_EMPTY => !!( $buf & RX_EMPTY ),
661             } );
662 0           });
663             }
664              
665             =head2 $nrf->pwr_up( $pwr )->get
666              
667             A convenient shortcut to setting the C configuration bit.
668              
669             =cut
670              
671             sub pwr_up
672             {
673 0     0 1   my $self = shift;
674 0           $self->change_config( PWR_UP => shift );
675             }
676              
677             =head2 $nrf->chip_enable( $ce )->get
678              
679             A wrapper around the underlying C method. This presumes that the C
680             pin is attached to the C F line.
681              
682             =cut
683              
684             sub chip_enable
685             {
686 0     0 1   my $self = shift;
687 0           $self->aux( @_ );
688             }
689              
690             =head2 $len = $nrf->read_rx_payload_width->get
691              
692             Returns the width of the most recently received payload, when in C mode.
693             Remember that C needs to be enabled (using C) on both the
694             transmitter and receiver before this will work.
695              
696             =cut
697              
698             sub read_rx_payload_width
699             {
700 0     0 0   my $self = shift;
701              
702             $self->_do_command( CMD_R_RX_PL_WID, "\0" )->then( sub {
703 0     0     my ( $buf ) = @_;
704 0           Future->done( ord $buf );
705 0           });
706             }
707              
708             =head2 $data = $nrf->read_rx_payload( $len )->get
709              
710             Reads the most recently received RX FIFO payload buffer.
711              
712             =cut
713              
714             sub read_rx_payload
715             {
716 0     0 1   my $self = shift;
717 0           my ( $len ) = @_;
718              
719 0 0 0       $len > 0 and $len <= 32 or croak "Invalid RX payload length $len";
720              
721 0           $self->_do_command( CMD_R_RX_PAYLOAD, "\0" x $len )
722             }
723              
724             =head2 $nrf->write_tx_payload( $data, %opts )->get
725              
726             Writes the next TX FIFO payload buffer. Takes the following options:
727              
728             =over 4
729              
730             =item no_ack => BOOL
731              
732             If true, uses the C command, requesting that this payload
733             does not requre auto-ACK.
734              
735             =back
736              
737             =cut
738              
739             sub write_tx_payload
740             {
741 0     0 1   my $self = shift;
742 0           my ( $data, %opts ) = @_;
743              
744 0           my $len = length $data;
745 0 0 0       $len > 0 and $len <= 32 or croak "Invalid TX payload length $len";
746              
747 0 0         my $cmd = $opts{no_ack} ? CMD_W_TX_PAYLOAD_NO_ACK : CMD_W_TX_PAYLOAD;
748              
749 0           $self->_do_command( $cmd, $data )
750             ->then_done();
751             }
752              
753             =head2 $nrf->flush_rx_fifo->get
754              
755             =head2 $nrf->flush_tx_fifo->get
756              
757             Flush the RX or TX FIFOs, discarding all their contents.
758              
759             =cut
760              
761             sub flush_rx_fifo
762             {
763 0     0 0   my $self = shift;
764              
765 0           $self->_do_command( CMD_FLUSH_RX )
766             ->then_done();
767             }
768              
769             sub flush_tx_fifo
770             {
771 0     0 0   my $self = shift;
772              
773 0           $self->_do_command( CMD_FLUSH_TX )
774             ->then_done();
775             }
776              
777             =head1 AUTHOR
778              
779             Paul Evans
780              
781             =cut
782              
783             0x55AA;