-
Notifications
You must be signed in to change notification settings - Fork 0
/
device.tcl
372 lines (258 loc) · 12.3 KB
/
device.tcl
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
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
# device.tcl - a script to parse parameters from device calls
# vh, 30 April 2017
# ----------------------------------------------------------------------
source SenseHat.tcl
package require cmdline
proc device {action args} {
global device
# TODO: implement a namespace for configuration variables
# The first arg could be a data string. Check this out.
# TODO: eliminate the possibility that the text string might include - as the first character.
set first_arg [lindex $args 0]
if {[string index $first_arg 0] != "-"} {
puts "This call had a data item as its first argument: data"
set device(data) $first_arg
set args [lrange $args 1 end]
puts "args are now:$args"
}
set user_args $args
puts $args
set options {
{name.arg "" "Name to be used to device this device. TODO: auto setup various parameters from the name"}
{data.arg "" "Data to be displayed. If data is specified, will consume all other parameters, then attempt to display data."}
{font.arg 1 "font name to load. Will look for a filename called font${arg}.tcl to load. Font will be loaded immediately."}
{font_file.arg "" "A filename from which to load font data. Font will be loaded immediately."}
{font_data.arg "" "The font definition data, a list of 2-parameter list \{charname \{8 X hex, format(0x%4.4X)\}\}). Usually set by software"}
{fg_colour.arg "white" "colour name"}
{bg_colour.arg "white" "colour name"}
{pause.arg 500 "pause after display, milliseconds for page display. pause/8 is used for scrolling display."}
{delay.arg 500 "delay before display, milliseconds"}
{bpp.arg 2 "bytes of colour per pixel"}
{colour_bytes.arg 2 "count of bytes used to define colours"}
{colour_data.arg "" "colour data"}
{rotation.arg "0" "rotation of screen. Valid values: 0, 90, 180, 270"}
{transform_matrix.arg "" "raw transformation mapping matrix data."}
{syspath.arg "/graphics/fb1" "path to frame buffer. Usually set by software"}
{reset.arg "" "reset the given arg parameter to default"}
{reset "" "reset all parameters to default"}
{font_data.arg "" "The font definition data, a list of 2-parameter list \{charname \{8 X hex, format(0x%4.4X)\}\}). Usually set by software"}
{width.arg "" "device width, which is also the frame buffer width. Usually set by software."}
{height.arg "" "device width, which is also the frame buffer width. Usually set by software."}
{method.arg "" "Communication method for this device. Allowable values: fb, gpio, i2c, spi"}
{package_gpio.arg "piio" "The package used to interface with gpio hardware"}
{package_i2c.arg "piio" "The package used to interface with i2c hardware"}
{package_spi.arg "piio" "The package used to interface with spi hardware"}
{brightness.arg 8 "pixel brighness, on a scale from 1 to \$device(max_brighness)."}
{brightness_max.arg 10 "The max pixel brighness. This allows the users to define the brighness scale"}
{mode.arg "scroll" "display mode. valid value: scroll, page"}
{endless "false" "repeat the display of input data endlessly? boolean"}
{record.arg "" "capture the output of this action to an animated gif. The argument is the filename (.file extension not necessary)"}
{path.arg "" "current user-defined pixel display path"}
{path_list "" "a nested list of predefined pixel display paths"}
{fade_steps.arg "1" "for path display, the number of pixel steps it takes to fade to zero brightness"}
{debug "false" "this flag will stop the execution of scripts at predefined points and display appropriate messages."}
}
# puts "options=$options"
set usage ": device <action> \[options] ...\noptions:"
# # If the user selected the help option, display the useage text.
# if {[catch {array set options [cmdline::getoptions ::argv $parameters $usage]}]} {puts [cmdline::usage $parameters $usage]}
try {
array set params [::cmdline::getoptions args $options $usage]
} trap {CMDLINE USAGE} {msg o} {
# Trap the usage signal, print the message, and exit the application.
# Note: Other errors are not caught and passed through to higher levels!
puts $msg
exit 1
}
# strip out any parameter items that were not provided by the user
# puts "attempting to remove unspecified parameters from cmdline return"
foreach i [array names params] {
# puts "checking $i: [lsearch $user_args -$i]"
if {[lsearch $user_args "-${i}"] ==-1} {
# puts "removing parameter $i because it was not specified by the user"
unset params($i)
}
}
puts "parameters received: [array names params]"
set action_flag 0
# If the action requested it "get", display whatever was requested and end.
if {$action=="get"} {
foreach i [array names params] {
# This parameter might not be set, so we have to catch the error
if {[catch {puts -nonewline "$device($i) "} err ]} {puts ""}
}
puts ""
exit 1
}
# Cycle through each of the input parameters and do what is required with it.
foreach i [array names params] {
switch -exact -- $i {
{data} {
# puts "working on $i: $params($i)"
set device(data) $params($i)
# data has been provided, so continue to display function after all other parameters have been considered."
set action_flag 1
}
{font} {
# puts "working on $i: $params($i)"
set device(font) $params($i)
# TODO: load the font
}
{font_file} {
puts "working on $i: $params($i)"
set device(font) $params($i)
# TODO: load the font file
}
{font_data} {
puts "working on $i: $params($i)"
# TODO: Figure out what we want to do. Should we validate, then replace the font definitions?
}
{fg_colour} {
puts "working on $i: $params($i)"
# TODO: validate the colour entered
set device(fg_colour) $params($i)
}
{bg_colour} {
puts "working on $i: $params($i)"
# TODO: validate the colour entered
set device(bg_colour) $params($i)
}
{pause} {
# puts "working on $i: $params($i)"
set device(pause) $params($i)
}
{bpp} {puts "working on $i: $params($i)"}
{colour_bytes} {puts "working on $i: $params($i)"}
{colour_data} {puts "working on $i: $params($i)"}
{rotation} {
puts "working on $i: $params($i)"
set device(rotation) $params($i)
}
{transform_matrix} {puts "working on $i: $params($i)"}
{syspath} {
# puts "working on $i: $params($i)"
set device(syspath $params($i)
}
{path} {
# puts "working on $i: $params($i)"
# if we have received non-integer, this must be a call for a pre-defined path definition
# TODO: add this check
# if this is a list of integers, add this as a path definition
set device(path) $params($i)
# take note that we will action this command once we have consumed all the parameters
set action_flag true
}
{path_list} {
# puts "working on $i: $params($i)"
# TODO: do we need this?
}
{delay} {puts "working on $i: $params($i)"}
{reset} {puts "working on $i: $params($i)"}
{height} {puts "working on $i: $params($i)"}
{width} {puts "working on $i: $params($i)"}
{method} {puts "working on $i: $params($i)"}
{package_gpio} {puts "working on $i: $params($i)"}
{package_i2c} {puts "working on $i: $params($i)"}
{package_spi} {puts "working on $i: $params($i)"}
{name} {
# puts "working on $i: $params($i)"
set device(name) $params($i)
}
{bg_brightness} {
# puts "working on $i: $params($i)"
set device(bg_brighness) $params($i)
}
{fg_frightness} {
# puts "working on $i: $params($i)"
set device(fg_brighness) $params($i)
}
{brightness} {
puts "working on $i: $params($i)"
set device(brightness) $params($i)
}
{brightness_max} {
puts "working on $i: $params($i)"
set device(brightness_max) $params($i)
}
{endless} {
puts "working on $i: $params($i)"
set device(endless) $params($i)
}
{mode} {
# TODO: validate mode
puts "working on $i: $params($i)"
set device(mode) $params($i)
}
{record} {
puts "working on $i: $params($i)"
set device(record) true
if {$params($i) == ""} {
set device(gif_output) "animated_gif.gif"
} else {
set device(gif_output) [file root $params($i)].gif
}
# load the Tk package (needed for the gif file manipulation
package require Tk
wm withdraw .
}
{fade_steps} {
# puts "working on $i: $params($i)"
set device(fade_steps) $params($i)
}
{debug} {
set device(debug) $params($i)
}
{default} {return -code error "discovered parameter $i: should not be able to get here."}
}
}
# Consistency checks - some parameters cannot be used together
# -data and -path - we can only do one at a time...
# Do something for each action
switch -exact $action {
{config} {
puts "action received is config"
# No more action is required.
# TODO: If a -data item was received, should we just go ahead and display?
if {[info exists $params(data)} {puts "a display -data item was given."}
}
{get} {
# TODO: figure out how to properly implement the get command (the way the cmdline procedure is implemented, it demands parameters for all the values, so this command cannot be used... )
puts "action received is get"
}
{display} {
set action_flag 1
puts "action received is display"
if {$action_flag} {
# The input received includes a request for action. Execute
# the display function with all the parameters that have been set.
if {[lsearch [array names params] "path"] !=-1} {
# puts "executing the 'display' command with -path attribute"
# puts "rotation is:$device(rotation)"
# puts "path is: $device(path)"
display_path $device(path)
} else {
puts "executing the 'display' command with -data attribute"
puts "rotation is:$device(rotation)"
display $device(data)
}
# Cleanup after the display is finished
if {$device(record)} {
# look for .raw frame buffer dump files and assemble them into an animated gif
if {[catch {gif_assemble} err]} {
puts "unable to assemble animated gif file. Error was:$err"
}
}
}
}
{default} {error "Error: valid keywords for 'device' command are: config, get, display. Got '${action}'"}
}
return
}
# -----------------------------------------------------------------------------------------------
# Testing examples
# device display -help
# device display
# device display -data "Example" -font 1 -fg_colour blue -bg_colour black -pause 100 -rotation 0
# device display "example text" -fg_colour red -bg_colour "white" -pause 500 -rotation 90
# device config -font 1 -fg_colour blue -bg_colour black -pause 100 -sleep 222 -colour_bytes 2 -rotation 0
# ----------------------------------------------------------------------