File Coverage

blib/lib/Device/Chip/AD5691R.pm
Criterion Covered Total %
statement 61 61 100.0
branch 3 6 50.0
condition 3 4 75.0
subroutine 13 13 100.0
pod 4 5 80.0
total 84 89 94.3


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