File Coverage

blib/lib/Device/Chip/OPT3001.pm
Criterion Covered Total %
statement 53 59 89.8
branch n/a
condition n/a
subroutine 14 15 93.3
pod 3 5 60.0
total 70 79 88.6


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