forked from dbrgn/RPLCD
-
Notifications
You must be signed in to change notification settings - Fork 0
/
lcdtest.py
executable file
·209 lines (184 loc) · 8.23 KB
/
lcdtest.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
Copyright (C) 2013-2017 Danilo Bargen
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
"""
from __future__ import print_function, division, absolute_import, unicode_literals
import sys
import RPi.GPIO as GPIO
from RPLCD import i2c, gpio
# Import supported tests
import lcdtests.show_charmap as show_charmap
import lcdtests.testsuite_20x4 as testsuite_20x4
import lcdtests.testsuite_16x2 as testsuite_16x2
# Globals
options = {}
no_default = object()
def print_usage(error=None):
print('Usage: %s i2c <test> <options>' % sys.argv[0])
print(' %s gpio <test> <options>' % sys.argv[0])
print('')
print('<test> Which test to run:')
print('')
print(' show_charmap - Displays all characters in the charmap')
print(' testsuite - Tests display formatting, 20x4 and 16x2 displays supported.')
print('')
# Options for i2c mode
if ((len(sys.argv) > 1) and (sys.argv[1] == 'i2c')):
print('<options> i2c options:')
print('')
print(' expander - Supported I²C port expanders are PCF8574, MCP23008 and MCP23017')
print(' addr - The I²C address (in hex format) can be found with')
print(' `i2cdetect 1` from the i2c-tools package.')
print(' port - The I²C port. For the first RPi with 256MB RAM this is 0, else 1')
print(' Default: 1')
print(' cols - The number of columns on your LCD, e.g. 16')
print(' rows - The number of rows on your LCD, e.g. 2')
print(' charmap - Which character map to use. Either A00 or A02. If your display')
print(' contains Japanese characters, it probably uses the A00 charmap,')
print(' otherwise A02. Default: A00')
print('')
print(' Expander specific options:')
print('')
print(' MCP23017: gpio_bank - Either A or B')
print('')
print('Examples:')
print('')
print(sys.argv[0] + ' i2c testsuite expander=PCF8574 addr=0x27 port=1 '
'cols=20 rows=4 charmap=A00')
print(sys.argv[0] + ' i2c testsuite expander=MCP23017 addr=0x20 port=1 '
'kols=20 rows=4 charmap=A00 gpio_bank=A')
# Options for GPIO mode
elif ((len(sys.argv) > 1) and (sys.argv[1] == 'gpio')):
print('<options> gpio options:')
print('')
print(' mode - GPIO numbering mode, either BOARD or BCM')
print(' cols - The number of columns on your LCD, e.g. 16')
print(' rows - The number of rows on your LCD, e.g. 2')
print(' rs - RS pin number')
print(' rw - RW pin number. Default: None')
print(' e - E pin number')
print(' bl - Backlight pin number. Default: None')
print(' data - Data (d0-d7) gpio pin numbers, 4 or 8 numbers depending')
print(' on if you want 4 or 8 bit mode, separated by commas.')
print(' Example: data=1,2,3,4,5,6,7,8 (for 8-bit mode)')
print(' data=5,6,7,8 (for 4-bit mode)')
print(' charmap - Which character map to use. Either A00 or A02. If your display')
print(' contains Japanese characters, it probably uses the A00 charmap,')
print(' otherwise A02. Default: A00')
print('')
print('Example:')
print('')
print(sys.argv[0] + ' gpio testsuite cols=20 rows=4 mode=BCM rs=15 rw=None e=16 '
'bl=None data=21,22,23,24 charmap=A00')
else:
print('<options> For info about options run:')
print('')
print(' %s i2c' % sys.argv[0])
print(' %s gpio' % sys.argv[0])
print('')
if error is not None:
print('\nError: ' + error)
sys.exit(1)
def options_pop(value, default=no_default):
''' Pops value from options with error checking
value: which option to pop and check.
default: optional, sets a default if not defined.
returns: a string corresponding to the option on the command line
'''
global options
try:
# If no default value is defined
if default is no_default:
return_value = options.pop(value)
else:
return_value = options.pop(value, default)
except KeyError:
print_usage('Option %s is not defined.' % value)
except ValueError as e:
print_usage('The value for %s is not valid.\n%s' % (value, e))
except Exception as e:
raise e
if return_value == '':
print_usage('Option %s can\'t be blank.' % value)
return return_value
if __name__ == '__main__':
if len(sys.argv) < 3:
print_usage()
lcdmode = sys.argv[1]
test = sys.argv[2]
# Parse options into a dictionary
try:
options = dict([arg.split('=', 1) for arg in sys.argv[3:]])
except ValueError:
print_usage('Malformed option detected, must be in the form option=value')
# Common options
cols = int(options_pop('cols'))
rows = int(options_pop('rows'))
charmap = options_pop('charmap', 'A00')
if lcdmode == 'i2c':
if len(sys.argv) < 5:
print_usage()
# i2c options, pop all required options, pass remaining options to expander_params
i2c_expander = options_pop('expander')
address = int(options_pop('addr'), 16)
port = int(options_pop('port', '1'))
try:
lcd = i2c.CharLCD(i2c_expander, address, port=port, charmap=charmap, cols=cols,
rows=rows, expander_params=options)
except IOError:
print_usage('IOError: Usually caused by the wrong i2c address/port '
'or device not connected properly')
elif lcdmode == 'gpio':
if len(sys.argv) < 8:
print_usage()
# gpio options
mode = options_pop('mode')
if mode == 'BCM':
numbering_mode = GPIO.BCM
elif mode == 'BOARD':
numbering_mode = GPIO.BOARD
else:
print_usage('Invalid GPIO numbering mode: %s, must be either BOARD or BCM' % mode)
data = options_pop('data')
rs = int(options_pop('rs'))
e = int(options_pop('e'))
rw = options_pop('rw', 'None')
rw = None if rw == 'None' else int(rw)
bl = options_pop('bl', 'None')
bl = None if bl == 'None' else int(bl)
# Parse data pins into a list
pins_data = {}
pins_data = data.split(',')
# Convert data pins to int
pins_data = [int(pin) for pin in pins_data]
lcd = gpio.CharLCD(pin_rs=rs, pin_rw=rw, pin_e=e, pins_data=pins_data, pin_backlight=bl,
numbering_mode=numbering_mode, cols=cols, rows=rows, charmap=charmap)
else:
print_usage('Connection type %s is not supported. Must be either i2c or gpio' % lcdmode)
# Run selected test
if test == 'show_charmap':
show_charmap.run(lcd, rows, cols)
elif test == 'testsuite':
if cols == 20 and rows == 4:
testsuite_20x4.run(lcd)
elif cols == 16 and rows == 2:
testsuite_16x2.run(lcd)
else:
print_usage('%sx%s displays are not supported in this test.' % (cols, rows))
else:
print_usage('Test \'%s\' is not supported.' % test)