File Coverage

blib/lib/Device/Chip/MAX44009.pm
Criterion Covered Total %
statement 51 51 100.0
branch n/a
condition n/a
subroutine 13 13 100.0
pod 3 4 75.0
total 67 68 98.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, 2021-2023 -- leonerd@leonerd.org.uk
5              
6 3     3   514407 use v5.26;
  3         28  
7 3     3   16 use warnings;
  3         4  
  3         99  
8 3     3   528 use Object::Pad 0.800;
  3         10521  
  3         190  
9              
10             package Device::Chip::MAX44009 0.05;
11             class Device::Chip::MAX44009
12 3     3   1612 :isa(Device::Chip::Base::RegisteredI2C);
  3         23763  
  3         102  
13              
14 3     3   1593 use Device::Chip::Sensor -declare;
  3         7569  
  3         12  
15              
16 3     3   1551 use Data::Bitfield qw( bitfield enumfield boolfield );
  3         5554  
  3         209  
17 3     3   20 use Future::AsyncAwait;
  3         6  
  3         15  
18              
19             =encoding UTF-8
20              
21             =head1 NAME
22              
23             C - chip driver for F
24              
25             =head1 SYNOPSIS
26              
27             use Device::Chip::MAX44009;
28             use Future::AsyncAwait;
29              
30             my $chip = Device::Chip::MAX44009->new;
31             await $chip->mount( Device::Chip::Adapter::...->new );
32              
33             await $chip->power(1);
34              
35             sleep 1; # Wait for one integration cycle
36              
37             printf "Current ambient light level is %.2f lux\n",
38             scalar await $chip->read_lux;
39              
40             =head1 DESCRIPTION
41              
42             This L subclass provides specific communication to a
43             F F ambient light sensor attached to a computer
44             via an I²C adapter.
45              
46             The reader is presumed to be familiar with the general operation of this chip;
47             the documentation here will not attempt to explain or define chip-specific
48             concepts or features, only the use of this module to access them.
49              
50             =cut
51              
52             method I2C_options
53 2     2 0 826 {
54             return (
55 2         13 addr => 0x4A,
56             max_bitrate => 400E3,
57             );
58             }
59              
60             use constant {
61 3         2788 REG_INTSTATUS => 0x00,
62             REG_INTENABLE => 0x01,
63             REG_CONFIG => 0x02,
64             REG_LUXH => 0x03,
65             REG_LUXL => 0x04,
66             REG_THRESHU => 0x05,
67             REG_THRESHL => 0x06,
68             REG_THRESHTIM => 0x07,
69 3     3   510 };
  3         6  
70              
71             bitfield { format => "bytes-LE" }, CONFIG =>
72             CONT => boolfield(7),
73             MANUAL => boolfield(6),
74             CDR => boolfield(3),
75             TIM => enumfield(0, qw( 800 400 200 100 50 25 12.5 6.25 ) );
76              
77             =head2 read_config
78              
79             $config = await $chip->read_config
80              
81             Returns a C reference containing the chip config, using fields named
82             from the data sheet.
83              
84             CONT => bool
85             MANUAL => bool
86             CDR => bool
87             TIM => 800 | 400 | 200 | 100 | 50 | 25 | 12.5 | 6.25
88              
89             =cut
90              
91 4         6 async method read_config ()
  4         5  
92 4         16 {
93 4         16 my $bytes = await $self->cached_read_reg( REG_CONFIG, 1 );
94              
95 4         8832 return { unpack_CONFIG( $bytes ) };
96 4     4 1 3379 }
97              
98             =head2 change_config
99              
100             await $chip->change_config( %changes )
101              
102             Writes updates to the configuration registers.
103              
104             Note that these two methods use a cache of configuration bytes to make
105             subsequent modifications more efficient.
106              
107             =cut
108              
109 1         3 async method change_config ( %changes )
  1         2  
  1         1  
110 1         3 {
111 1         4 my $config = await $self->read_config;
112              
113 1         77 my $bytes = pack_CONFIG( %$config, %changes );
114              
115 1         102 await $self->cached_write_reg( REG_CONFIG, $bytes );
116 1     1 1 3260 }
117              
118             declare_sensor light =>
119             method => "read_lux",
120             units => "lux",
121             precision => 2;
122              
123             =head2 read_lux
124              
125             $lux = await $chip->read_lux
126              
127             Reads the latest light level conversion value and returns the value in Lux.
128              
129             =cut
130              
131 1         2 async method read_lux ()
  1         1  
132 1         10 {
133             # MAX44009 can't do a 2-byte register read.
134             # Nor should we just do two 1-byte reads because of nonatomic updates
135             # Ugh.
136 1     1   7414 my $raw = await $self->protocol->txn(async sub {
137 1         3 my ( $helper ) = @_;
138 1         5 return unpack "S>", join "",
139             await $helper->write_then_read( ( pack "C", REG_LUXH ), 1 ),
140             await $helper->write_then_read( ( pack "C", REG_LUXL ), 1 );
141 1         4 });
142              
143             # Unpack the weird 16bit EEEEMMMM....MMMM format
144 1         3593 my $exp = $raw >> 12;
145 1         3 my $mant = ( ( $raw >> 4 ) & 0xF0 ) | ( $raw & 0x0F );
146              
147 1         3 my $lux = ( $mant / 16 ) * ( 2 ** $exp );
148              
149 1         5 return $lux;
150 1     1 1 420 }
151              
152             =head1 AUTHOR
153              
154             Paul Evans
155              
156             =cut
157              
158             0x55AA;