File Coverage

blib/lib/Device/Chip/MAX44009.pm
Criterion Covered Total %
statement 48 48 100.0
branch n/a
condition n/a
subroutine 12 12 100.0
pod 3 4 75.0
total 63 64 98.4


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