File Coverage

blib/lib/Device/Chip/OPT3001.pm
Criterion Covered Total %
statement 50 56 89.2
branch n/a
condition n/a
subroutine 13 14 92.8
pod 3 5 60.0
total 66 75 88.0


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   203894 use v5.26;
  3         26  
7 3     3   502 use Object::Pad 0.40;
  3         8656  
  3         15  
8              
9             package Device::Chip::OPT3001 0.01;
10             class Device::Chip::OPT3001
11 3     3   1609 extends Device::Chip::Base::RegisteredI2C;
  3         23504  
  3         135  
12              
13 3     3   1869 use Device::Chip::Sensor -declare;
  3         4582  
  3         12  
14              
15 3     3   1651 use Data::Bitfield qw( bitfield enumfield boolfield intfield );
  3         5810  
  3         234  
16 3     3   23 use Future::AsyncAwait;
  3         5  
  3         19  
17 3     3   1583 use Future::IO;
  3         14284  
  3         140  
18              
19 3     3   25 use constant REG_DATA_SIZE => 16;
  3         6  
  3         525  
20              
21             =encoding UTF-8
22              
23             =head1 NAME
24              
25             C - chip driver for F
26              
27             =head1 SYNOPSIS
28              
29             use Device::Chip::OPT3001;
30             use Future::AsyncAwait;
31              
32             my $chip = Device::Chip::OPT3001->new;
33             await $chip->mount( Device::Chip::Adapter::...->new );
34              
35             await $chip->power(1);
36              
37             sleep 1; # Wait for one integration cycle
38              
39             printf "Current ambient light level is %.2f lux\n",
40             scalar await $chip->read_lux;
41              
42             =head1 DESCRIPTION
43              
44             This L subclass provides specific communication to a
45             F F ambient light sensor attached to a computer
46             via an I²C adapter.
47              
48             The reader is presumed to be familiar with the general operation of this chip;
49             the documentation here will not attempt to explain or define chip-specific
50             concepts or features, only the use of this module to access them.
51              
52             =cut
53              
54             method I2C_options
55 2     2 0 850 {
56             return (
57 2         17 addr => 0x44,
58             max_bitrate => 400E3,
59             );
60             }
61              
62             use constant {
63 3         2512 REG_RESULT => 0x00,
64             REG_CONFIG => 0x01,
65             REG_LIML => 0x02,
66             REG_LIMH => 0x03,
67              
68             REG_MANUF_ID => 0x7E,
69             REG_PROD_ID => 0x7F,
70 3     3   21 };
  3         6  
71              
72             bitfield { format => "integer" }, CONFIG =>
73             RN => intfield(12, 4),
74             CT => enumfield(11, qw( 100 800 )),
75             M => enumfield(9, qw( shutdown single cont cont )),
76             OVF => boolfield(8),
77             CRF => boolfield(7),
78             FH => boolfield(6),
79             FL => boolfield(5),
80             L => boolfield(4),
81             POL => enumfield(3, qw( active-low active-high )),
82             ME => boolfield(2),
83             FC => enumfield(0, qw( 1 2 4 8 ));
84              
85             =head2 read_config
86              
87             $config = await $chip->read_config
88              
89             Returns a C reference containing the chip config, using fields named
90             from the data sheet.
91              
92             RN => 0 .. 15
93             CT => 100 | 800
94             M => "shutdown" | "single" | "cont"
95             OVF => bool
96             CRF => bool
97             FH => bool
98             FL => bool
99             L => bool
100             POL => "active-low" | "active-high"
101             ME => bool
102             FC => 1 | 2 | 4 | 8
103              
104             =cut
105              
106 4         5 async method read_config ()
  4         6  
107 4         10 {
108 4         13 my $bytes = await $self->cached_read_reg( REG_CONFIG, 1 );
109              
110 4         8652 return { unpack_CONFIG( unpack "S>", $bytes ) };
111 4     4 1 2933 }
112              
113             =head2 change_config
114              
115             await $chip->change_config( %changes )
116              
117             Writes updates to the configuration registers.
118              
119             Note that these two methods use a cache of configuration bytes to make
120             subsequent modifications more efficient.
121              
122             =cut
123              
124 1         2 async method change_config ( %changes )
  1         2  
  1         2  
125 1         3 {
126 1         2 my $config = await $self->read_config;
127              
128 1         130 my $bytes = pack "S>", pack_CONFIG( %$config, %changes );
129              
130 1         245 await $self->cached_write_reg( REG_CONFIG, $bytes );
131 1     1 1 2523 }
132              
133 0         0 async method initialize_sensors ()
  0         0  
134 0         0 {
135 0         0 await $self->change_config( M => "cont" );
136              
137             # Give it a moment or two to start up
138 0         0 await Future::IO->sleep( 0.900 );
139 0     0 0 0 }
140              
141             declare_sensor light =>
142             method => "read_lux",
143             units => "lux",
144             precision => 2;
145              
146             =head2 read_lux
147              
148             $lux = await $chip->read_lux
149              
150             Reads the latest light level conversion value and returns the value in Lux.
151              
152             =cut
153              
154 1         2 async method read_lux ()
  1         1  
155 1         3 {
156 1         6 my $raw = unpack "S>", await $self->read_reg( REG_RESULT, 1 );
157              
158             # Unpack the 4.12 floating point format
159 1         7948 my $exp = ( $raw >> 12 );
160 1         5 my $lux = ( $raw & 0x0FFF ) * ( 2 ** $exp ) * 0.01;
161              
162 1         5 return $lux;
163 1     1 1 221 }
164              
165             =head1 AUTHOR
166              
167             Paul Evans
168              
169             =cut
170              
171             0x55AA;