File Coverage

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