File Coverage

blib/lib/Device/Chip/BV4243.pm
Criterion Covered Total %
statement 156 156 100.0
branch 2 2 100.0
condition 1 2 50.0
subroutine 30 30 100.0
pod 22 22 100.0
total 211 212 99.5


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, 2015-2020 -- leonerd@leonerd.org.uk
5              
6 5     5   440952 use v5.26;
  5         57  
7 5     5   2600 use Object::Pad 0.19;
  5         34624  
  5         27  
8              
9             package Device::Chip::BV4243 0.03;
10             class Device::Chip::BV4243
11 1     1   583 extends Device::Chip;
  1         14343  
  1         65  
12              
13 5     5   2323 use utf8;
  5         23  
  5         34  
14              
15 5     5   668 use Future::AsyncAwait;
  5         950  
  5         27  
16              
17             =encoding UTF-8
18              
19             =head1 NAME
20              
21             C - chip driver for a F
22              
23             =head1 SYNOPSIS
24              
25             use Device::Chip::BV4243;
26             use Future::AsyncAwait;
27              
28             my $chip = Device::Chip::BV4243->new;
29             await $chip->mount( Device::Chip::Adapter::...->new );
30              
31             await $chip->lcd_reset;
32             await $chip->lcd_string( "Hello, world!" );
33              
34             =head1 DESCRIPTION
35              
36             This L subclass provides specific communication to a F
37             F LCD/touchpad display module attached to a computer via an I²C
38             adapter.
39              
40             The reader is presumed to be familiar with the general operation of this
41             module; the documention here will not attempt to explain or define
42             module-specific concpets or features, only the use of this module to access
43             them.
44              
45             =cut
46              
47 5     5   325 use constant PROTOCOL => "I2C";
  5         10  
  5         756  
48              
49             use constant {
50 5         15425 CMD_CLEAR_KEYS => 1,
51             CMD_GET_N_KEYS => 2, # => u8 count
52             CMD_GET_KEY => 3, # => u8 key
53             CMD_FIND_KEY => 4, # u8 key => u8 pos
54             CMD_GET_SCANCODE => 5, # => u8 code
55             CMD_BEEP => 6, # u8 msec
56             CMD_READ_CHAN => 10, # => u16 * 8
57             CMD_READ_DELTA => 11, # => u16 * 8
58             CMD_EEPROM_RESET => 20,
59             CMD_SLEEP => 21,
60              
61             CMD_LCD_RESET => 30,
62             CMD_LCD_COMMAND => 31, # u8 cmd
63             CMD_LCD_DATA => 32, # u8 data
64             CMD_LCD_STRING => 33, # strZ string
65             CMD_LCD_SIGNON => 35,
66             CMD_LCD_BACKLIGHT => 36, # u8 * 3 rgb - range 0-10
67              
68             CMD_SYS_READ_EEPROM => 0x90, # u8 addr => u8 val
69             CMD_SYS_WRITE_EEPROM => 0x91, # u8 addr, u8 val
70              
71             CMD_RESET => 0x95,
72              
73             CMD_VERSION => 0xA0, # => u16
74             CMD_DEVICE_ID => 0xA1, # => u16
75 5     5   39 };
  5         10  
76              
77 21         35 async method _command ( $cmd, $data = "", $readlen = 0 )
  21         35  
  21         42  
  21         32  
  21         30  
78 21         46 {
79 21 100       57 if( $readlen ) {
80 9         37 await $self->protocol->write_then_read( pack( "C a*", $cmd, $data ), $readlen );
81             }
82             else {
83 12         42 await $self->protocol->write( pack( "C a*", $cmd, $data ) );
84             }
85 21     21   44 }
86              
87             =head1 METHODS
88              
89             The following methods documented in an C expression return L
90             instances.
91              
92             =cut
93              
94 4         9 async method mount ( $adapter, %params )
  4         9  
  4         9  
  4         7  
95 4         13 {
96 4         35 await $self->SUPER::mount( $adapter, %params );
97              
98 4         2446 await $self->protocol->configure(
99             addr => 0x3C,
100              
101             # Chip seems to misbehave at 100kHz; run it at 50
102             max_bitrate => 50E3,
103             );
104              
105 4         672 return $self;
106 4     4 1 1370 }
107              
108             # Command wrappers
109              
110             =head2 clear_keys
111              
112             await $chip->clear_keys;
113              
114             Clears the keypad buffer.
115              
116             =cut
117              
118 1         2 async method clear_keys ()
  1         2  
119 1         4 {
120 1         3 await $self->_command( CMD_CLEAR_KEYS );
121 1     1 1 103 }
122              
123             =head2 get_keycount
124              
125             $count = await $chip->get_keycount;
126              
127             Returns the number of keys waiting in the keypad buffer.
128              
129             =cut
130              
131 1         3 async method get_keycount ()
  1         2  
132 1         10 {
133 1         6 return unpack "C", await $self->_command( CMD_GET_N_KEYS, "", 1 );
134 1     1 1 12632 }
135              
136             =head2 get_key
137              
138             $key = await $chip->get_key;
139              
140             Returns the next key from the keypad buffer, or 0 if there are none.
141              
142             =cut
143              
144 1         3 async method get_key ()
  1         1  
145 1         5 {
146 1         4 return unpack "C", await $self->_command( CMD_GET_KEY, "", 1 );
147 1     1 1 4394 }
148              
149             =head2 find_key
150              
151             $pos = await $chip->find_key( $key );
152              
153             Returns the position in the key buffer of the given key, or 0 if is not there.
154              
155             =cut
156              
157 1         3 async method find_key ( $key )
  1         2  
  1         3  
158 1         5 {
159 1         6 return unpack "C", await $self->_command( CMD_FIND_KEY, pack( "C", $key ), 1 );
160 1     1 1 4112 }
161              
162             =head2 get_scancode
163              
164             $code = await $chip->get_scancode;
165              
166             Returns the scan value from the keypad scanning matrix. This will be 0 if no
167             key is being touched, or an integer value with at least two bits set if a key
168             is being held.
169              
170             =cut
171              
172 1         2 async method get_scancode ()
  1         2  
173 1         4 {
174 1         5 return unpack "C", await $self->_command( CMD_GET_SCANCODE, "", 1 );
175 1     1 1 4458 }
176              
177             =head2 beep
178              
179             await $chip->beep( $msec );
180              
181             Turns on the C output line for the specified number of miliseconds.
182              
183             =cut
184              
185 1         2 async method beep ( $msec )
  1         1  
  1         2  
186 1         4 {
187 1         9 await $self->_command( CMD_BEEP, pack( "C", $msec ) );
188 1     1 1 107 }
189              
190             =head2 read_chan
191              
192             @channels = await $chip->read_chan;
193              
194             Returns the raw touchpad sensor values as 8 16bit integers.
195              
196             =cut
197              
198 1         2 async method read_chan ()
  1         2  
199 1         5 {
200 1         6 return unpack "(S>)8", await $self->_command( CMD_READ_CHAN, "", 16 );
201 1     1 1 4109 }
202              
203             =head2 read_delta
204              
205             @deltas = await $chip->read_delta;
206              
207             Returns the touchpad sensor values minus the trigger value.
208              
209             =cut
210              
211 1         3 async method read_delta ()
  1         2  
212 1         6 {
213 1         5 return unpack "(S>)8", await $self->_command( CMD_READ_DELTA, "", 16 );
214 1     1 1 4255 }
215              
216             =head2 sleep
217              
218             await $chip->sleep;
219              
220             Puts the device into sleep mode. It stops scanning the keypad, but will still
221             respond to another command which will wake it up again.
222              
223             =cut
224              
225 1         3 async method sleep ()
  1         2  
226 1         8 {
227 1         5 await $self->_command( CMD_SLEEP );
228 1     1 1 13085 }
229              
230             =head2 lcd_reset
231              
232             await $chip->lcd_reset;
233              
234             Resets the LCD.
235              
236             =cut
237              
238 1         2 async method lcd_reset ()
  1         2  
239 1         4 {
240 1         4 await $self->_command( CMD_LCD_RESET );
241 1     1 1 105 }
242              
243             =head2 lcd_command
244              
245             await $chip->lcd_command( $cmd );
246              
247             Sends a numeric command to the LCD controller.
248              
249             =cut
250              
251 1         3 async method lcd_command ( $cmd )
  1         2  
  1         1  
252 1         4 {
253 1         17 await $self->_command( CMD_LCD_COMMAND, pack "C", $cmd );
254 1     1 1 12260 }
255              
256             =head2 lcd_data
257              
258             await $chip->lcd_data( $data );
259              
260             Sends a byte of numerical data to the LCD controller.
261              
262             =cut
263              
264 1         3 async method lcd_data ( $data )
  1         2  
  1         2  
265 1         4 {
266 1         5 await $self->_command( CMD_LCD_DATA, pack "C", $data );
267 1     1 1 3554 }
268              
269             =head2 lcd_string
270              
271             await $chip->lcd_string( $str );
272              
273             Sends a string of data to the LCD controller. This is a more efficient version
274             of sending each byte of the string individually using L.
275              
276             =cut
277              
278 1         2 async method lcd_string ( $str )
  1         3  
  1         1  
279 1         5 {
280 1         4 await $self->_command( CMD_LCD_STRING, $str . "\0" );
281 1     1 1 3479 }
282              
283             =head2 lcd_signon
284              
285             await $chip->lcd_signon;
286              
287             Displays the signon string stored the in EEPROM.
288              
289             =cut
290              
291 1         3 async method lcd_signon ()
  1         1  
292 1         5 {
293 1         3 await $self->_command( CMD_LCD_SIGNON );
294 1     1 1 3526 }
295              
296             =head2 lcd_backlight
297              
298             await $chip->lcd_backlight( $red, $green, $blue );
299              
300             Sets the level of each of the three backlight channels. Each must be a numeric
301             value between 0 and 10 (inclusive). For single-backlight displays, use the
302             C<$red> channel.
303              
304             =cut
305              
306 1         4 async method lcd_backlight ( $red, $green, $blue )
  1         1  
  1         2  
  1         3  
  1         1  
307 1         5 {
308             # Clamp to 0..10
309 1   50     8 $_ > 10 and $_ = 10 for $red, $green, $blue;
310              
311 1         8 await $self->_command( CMD_LCD_BACKLIGHT, pack "CCC", $red, $green, $blue )
312 1     1 1 3492 }
313              
314             =head2 reset
315              
316             $chip->reset
317              
318             Resets the device.
319              
320             =cut
321              
322 1         2 async method reset ()
  1         3  
323 1         4 {
324 1         3 await $self->_command( CMD_RESET );
325 1     1 1 4019 }
326              
327             =head2 device_id
328              
329             $id = await $chip->device_id;
330              
331             Returns the device ID value as a 16 bit integer
332              
333             =cut
334              
335 1         3 async method device_id ()
  1         2  
336 1         4 {
337 1         4 return unpack "S>", await $self->_command( CMD_DEVICE_ID, "", 2 );
338 1     1 1 132 }
339              
340             =head2 version
341              
342             $id = await $chip->version;
343              
344             Returns the device firmware version as a 16 bit integer
345              
346             =cut
347              
348 1         3 async method version ()
  1         2  
349 1         6 {
350 1         4 return unpack "S>", await $self->_command( CMD_VERSION, "", 2 );
351 1     1 1 12812 }
352              
353             =head2 eeprom_reset
354              
355             await $chip->eeprom_reset;
356              
357             Resets the configuration EEPROM back to default values.
358              
359             =cut
360              
361 1         3 async method eeprom_reset ()
  1         2  
362 1         5 {
363 1         3 await $self->_command( CMD_EEPROM_RESET );
364 1     1 1 3901 }
365              
366             =head2 eeprom_read
367              
368             $val = await $chip->eeprom_read( $addr );
369              
370             Reads a byte from the configuration EEPROM.
371              
372             =cut
373              
374 1         3 async method eeprom_read ( $addr )
  1         3  
  1         1  
375 1         4 {
376 1         7 return unpack "C", await $self->_command( CMD_SYS_READ_EEPROM, pack( "C", $addr ), 1 );
377 1     1 1 3970 }
378              
379             =head2 eeprom_write
380              
381             await $chip->eeprom_write( $addr, $val );
382              
383             Writes a byte to the configuration EEPROM.
384              
385             =cut
386              
387 1         3 async method eeprom_write ( $addr, $val )
  1         3  
  1         2  
  1         1  
388 1         5 {
389 1         7 await $self->_command( CMD_SYS_WRITE_EEPROM, pack( "C C", $addr, $val ) );
390 1     1 1 4770 }
391              
392             =head1 SEE ALSO
393              
394             L
395              
396             =cut
397              
398             =head1 AUTHOR
399              
400             Paul Evans
401              
402             =cut
403              
404             0x55AA;