File Coverage

blib/lib/Device/Chip/AD5691R.pm
Criterion Covered Total %
statement 64 64 100.0
branch 3 6 50.0
condition 3 4 75.0
subroutine 14 14 100.0
pod 4 5 80.0
total 88 93 94.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, 2017-2023 -- leonerd@leonerd.org.uk
5              
6 2     2   319645 use v5.26;
  2         20  
7 2     2   12 use warnings;
  2         4  
  2         65  
8 2     2   632 use Object::Pad 0.800;
  2         11166  
  2         120  
9              
10             package Device::Chip::AD5691R 0.15;
11             class Device::Chip::AD5691R
12 1     1   620 :isa(Device::Chip);
  1         17053  
  1         59  
13              
14 2     2   564 use Carp;
  2         4  
  2         172  
15 2     2   17 use Future::AsyncAwait;
  2         3  
  2         10  
16              
17 2     2   1158 use Data::Bitfield qw( bitfield boolfield enumfield );
  2         4497  
  2         190  
18              
19 2     2   16 use constant PROTOCOL => "I2C";
  2         6  
  2         183  
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::AD5691R;
30             use Future::AsyncAwait;
31              
32             my $chip = Device::Chip::AD5691R->new;
33             await $chip->mount( Device::Chip::Adapter::...->new );
34              
35             my $voltage = 1.23;
36             await $chip->write_dac( 4096 * $voltage / 2.5 );
37             print "Output is now set to 1.23V\n";
38              
39             =head1 DESCRIPTION
40              
41             This L subclass provides specific communications to an
42             F F attached to the computer via an I²C adapter.
43              
44             The reader is presumed to be familiar with the general operation of this chip;
45             the documentation here will not attempt to explain or define chip-specific
46             concepts or features, only the use of this module to access them.
47              
48             =cut
49              
50             use constant {
51 2         2629 CMD_WRITE_INPUT => 0x10,
52             CMD_UPDATE_DAC => 0x20,
53             CMD_WRITE_AND_UPDATE => 0x30,
54             CMD_WRITE_CTRL => 0x40,
55 2     2   15 };
  2         4  
56              
57             =head1 MOUNT PARAMETERS
58              
59             =head2 addr
60              
61             The I²C address of the device. Can be specified in decimal, octal or hex with
62             leading C<0> or C<0x> prefixes.
63              
64             =cut
65              
66             sub I2C_options ( $, %params )
67 1     1 0 445 {
  1         2  
  1         18  
68 1   50     11 my $addr = delete $params{addr} // 0x4C;
69 1 50       7 $addr = oct $addr if $addr =~ m/^0/;
70              
71             return (
72 1         8 addr => $addr,
73             max_bitrate => 400E3,
74             );
75             }
76              
77             =head1 ACCESSORS
78              
79             The following methods documented in an C expression return L
80             instances.
81              
82             =cut
83              
84             bitfield CONFIG =>
85             GAIN => enumfield( 0, qw( 1 2 )),
86             REF => enumfield( 1, qw( 1 0 )),
87             PD => enumfield( 2, qw( normal 1k 100k hiZ ));
88              
89             =head2 read_config
90              
91             $config = await $chip->read_config;
92              
93             Returns a C reference containing the chip's current configuration
94              
95             GAIN => 1 | 2
96             REF => 0 | 1
97             PD => "normal" | "1k" | "100k" | "hiZ"
98              
99             Note that since the chip does not itself allow reading of its configuration,
100             this method simply returns the internally-cached values. This cache is
101             initialised to power-on defaults, and tracked by the C method.
102              
103             =cut
104              
105             field $_config;
106              
107 3         7 async method read_config ()
  3         5  
108 3         10 {
109             # The chip doesn't allow us to read its config. These are the power-on
110             # defaults. We'll track updates.
111 3   100     16 $_config //= 0;
112              
113 3         13 return { unpack_CONFIG( $_config ) };
114 3     3 1 270 }
115              
116             =head2 change_config
117              
118             await $chip->change_config( %changes );
119              
120             Changes the configuration. Any field names not mentioned will be preserved at
121             their existing values.
122              
123             =cut
124              
125 1         2 async method change_config ( %changes )
  1         3  
  1         3  
126 1         4 {
127 1         3 my $config = await $self->read_config;
128              
129 1         110 $_config = pack_CONFIG( %$config, %changes );
130              
131 1         116 await $self->protocol->write( pack "C S>",
132             CMD_WRITE_CTRL, $_config << 11 );
133 1     1 1 5416 }
134              
135             =head1 METHODS
136              
137             =cut
138              
139             =head2 write_dac
140              
141             await $chip->write_dac( $dac, $update );
142              
143             Writes a new value for the DAC output.
144              
145             If C<$update> is true this will use the "update" form of write command, which
146             writes both the DAC register and the input register. If false it only writes
147             the input register, requiring a pulse on the F pin to actually change
148             the output voltage.
149              
150             =cut
151              
152 2         5 async method write_dac ( $value, $update = 0 )
  2         4  
  2         4  
  2         5  
153 2         10 {
154 2         10 await $self->protocol->write( pack "C S>",
155             ( $update ? CMD_WRITE_AND_UPDATE : CMD_WRITE_INPUT ), $value << 4 );
156 2     2 1 13685 }
157              
158             =head2 write_dac_voltage
159              
160             await $chip->write_dac_voltage( $voltage );
161              
162             Writes a new value for the DAC output immediately, converting the given
163             voltage to the required raw value, taking into account the setting of the
164             C config bit.
165              
166             =cut
167              
168 1         3 async method write_dac_voltage ( $voltage )
  1         2  
  1         3  
169 1         4 {
170 1         3 my $config = await $self->read_config;
171              
172 1         114 my $value = $voltage * ( 1 << 12 ) / 2.5;
173 1         3 $value /= $config->{GAIN};
174              
175 1 50       7 croak "Cannot set DAC voltage to $voltage - too high"
176             if $value >= ( 1 << 12 );
177 1 50       5 croak "Cannot set DAC voltage to $voltage - too low"
178             if $value < 0;
179              
180 1         3 await $self->write_dac( $value, 1 );
181 1     1 1 4625 }
182              
183             =head1 AUTHOR
184              
185             Paul Evans
186              
187             =cut
188              
189             0x55AA;