Subversion Repositories shark

Rev

Rev 1676 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1676 tullio 1
%----------------------------------------------------------------------------
2
\chapter{The Input Library}
3
%----------------------------------------------------------------------------
4
 
5
This library allow the user to interact with applications. Is composed by a
6
lower lever which must be initialized at the beginning. On top of this layer we
7
can find different peripherals:
8
 
9
\begin{itemize}
10
\item Keyboard;
11
\item Mouse;
12
\item Joystick;
13
\item Speaker;
14
\item Event debugger.
15
\end{itemize}
16
 
17
Each one can work independently from the others. In order to use the low lever
18
functions, the files \texttt{drivers/shark\_input26.h} must be included. It
19
contains the prototypes of the declared functions. First of all, the keyboard
20
needs be initialized by the calling \texttt{KEYB26\_init} primitive into the
21
\texttt{\_\_init\_\_} function in the initialization file or in any other point
22
of the application code.
23
 
24
\vspace{7mm}
25
 
26
\begin{intest}
27
INPUT26\_INIT\index{INPUT26\_init()}
28
\end{intest}
29
 
30
\begin{description}
31
\item [\textbf{int INPUT26\_init(void);}]
32
\item [\textbf{Description:}]It initializes the low lever input interface and
33
the library's internal data structures.
34
\item [\textbf{Return value:}] 0 if the operation is performed successfully; a
35
value less than 0, otherwise.
36
\end{description}
37
 
38
\vspace{7mm}
39
 
40
The following code shows an example of input drivers initialization for the
41
system:
42
 
43
\begin{description}
44
\item [Example:]
45
\end{description}
46
 
47
\begin{verbatim}
48
int res;
49
KEYB_PARMS kparms = BASE_KEYB;
50
MOUSE_PARMS mparms = BASE_MOUSE;
51
 
52
LINUXC26_register_module(TRUE);
53
INPUT26_init();
54
 
55
keyb_def_map(kparms, KEYMAP_IT);
56
 
57
keyb_def_ctrlC(kparms, NULL);
58
 
59
KEYB26_init(&kparms);
60
 
61
mouse_def_threshold(mparms, 5);
62
mouse_def_xmin(mparms, 0);
63
mouse_def_ymin(mparms, 0);
64
mouse_def_xmax(mparms, 639);
65
mouse_def_ymax(mparms, 479);
66
MOUSE26_init(&mparms);
67
 
68
SPEAK26_init();
69
JOY26_init();
70
...
71
\end{verbatim}
72
 
73
\vspace{7mm}
74
 
75
The event debugger is used to have an output of the raw data coming from an
76
input device for which a driver is not present. It can be stanter, stopper and
77
is possible to control the actual status.
78
 
79
\vspace{7mm}
80
 
81
\begin{intest}
82
EVBUG26\_INIT\index{EVBUG26\_init()}
83
\end{intest}
84
 
85
\begin{description}
86
\item [\textbf{int EVBUG26\_init(void);}]
87
\item [\textbf{Description:}]It initializes the event debugger interface and the
88
library's internal data structures.
89
\item [\textbf{Return value:}] 0 if the operation is performed successfully; a
90
value less than 0, otherwise.
91
\end{description}
92
 
93
\begin{intest}
94
EVBUG26\_CLOSE\index{EVBUG26\_close()}
95
\end{intest}
96
 
97
\begin{description}
98
\item [\texttt{int EVBUG26\_close(void);}]
99
\item [\textbf{Description:}]It close the event debugger interface.
100
\item [\textbf{Return value:}] 0 if the operation is performed successfully; -1
101
if the interface in not installed.
102
\end{description}
103
 
104
\begin{intest}
105
EVBUG26\_INSTALLED\index{EVBUG26\_installed()}
106
\end{intest}
107
 
108
\begin{description}
109
\item [\texttt{int EVBUG26\_installed(void);}]
110
\item [\textbf{Description:}]Return if the event debugger is actually installed.
111
\item [\textbf{Return value}:] 0 if the module is installed; 1 otherwise.
112
\end{description}
113
 
114
%----------------------------------------------------------------------------
115
\section{The keyboard library}
116
%----------------------------------------------------------------------------
117
 
118
In order to use the keyboard handling functions, the
119
\texttt{drivers/shark\_keyb26.h} header file, containing the interface
120
functions' prototypes, has to be included in the application program.
121
 
122
First of all, the keyboard needs be initialized by the calling
123
\texttt{KEYB26\_init} primitive into the \texttt{\_\_init\_\_} function in the
124
initialization file or in any other point of the application code and the input
125
low level driver must be already installed. A programmer can either initialize
126
the keyboard using the default settings or define his own parameters which are
127
encapsulated into a structure having \texttt{KEY\_PARMS} type. The strucuture
128
can be initialized with the default set of values by setting it equal to
129
\texttt{BASE\_KEYB}; the \texttt{keyb\_def\_...} macros can be used before
130
calling \texttt{KEYB26\_init} to modify each setting. Afterwards, it is possible
131
to read the ASCII code of any stroken key by calling the \texttt{keyb\_getch()}
132
function. This function requires a parameter which determines whether the task
133
should block until a key is hit or not. In the latter case, if no key has been
134
hit, the function returns 0 (behaving like \texttt{kbhit()}).
135
 
136
If we are interested in the key's scan code, we can call the
137
\texttt{keyb\_getcode()} function, which returns a struct containing either the
138
scan code or the ascii code and a byte containing information on the ALT, SHIFT
139
or CTRL key being pressed.
140
 
141
The following code shows an example of usage for the function:
142
 
143
\begin{verbatim}
144
KEY_EVT k;
145
...
146
 
147
if (keyb_getcode(&k, NON_BLOCK) {
148
   if (isRightCtrl(k) || isLeftCtrl(k)) && (k.ascii == 'x')) {
149
 
150
      /* Ctrl + `x' has been pressed */
151
      ...
152
   }
153
}
154
...
155
\end{verbatim}
156
 
157
\noindent Finally, it is possible to define a function to be automatically
158
called every time a specific key (or a specific combination of keys) is pressed.
159
This is done by calling the \texttt{keyb\_hook()} function, which receives as
160
arguments a data structure containing the required combination of keys and the
161
function to be called.
162
 
163
\vspace{7mm}
164
 
165
\begin{intest}
166
KEYB26\_INIT\index{KEYB26\_init()}
167
\end{intest}
168
 
169
\begin{description}
170
\item [\textbf{int KEYB26\_init(KEYB\_PARMS {*}parms);}]
171
\item [\textbf{Description:}]It initializes the keyboard interface and the
172
library's internal data structures. It can be called using NULL as
173
\texttt{parms} to initialize the keyboard interface to default values. \\ Note
174
that to be proper initialized, you need also to initialize the HARTPORT
175
modules.
176
\item [\textbf{Return value:}] 0 if the operation is performed successfully; a
177
value less than 0, otherwise.
178
\end{description}
179
 
180
\begin{intest}
181
KEYB26\_CLOSE\index{KEYB26\_close()}
182
\end{intest}
183
 
184
\begin{description}
185
\item [\textbf{int KEYB26\_close(void);}]
186
\item [\textbf{Description:}]It close the keyboard interface.
187
\item [\textbf{Return value:}] 0 if the operation is performed successfully; -1
188
if the keyboard in not installed.
189
\end{description}
190
 
191
\begin{intest}
192
KEYB26\_INSTALLED\index{KEYB26\_installed()}
193
\end{intest}
194
 
195
\begin{description}
196
\item [\texttt{int KEYB26\_installed(void);}]
197
\item [Description:]Return if the keyboard driver is actually installed.
198
\item [\textbf{Return value:}] 0 if the keyboard is installed; 1 otherwise.
199
\end{description}
200
 
201
\begin{intest}
202
KEYB\_DEFAULT\_PARM\index{keyb\_default\_parm()}
203
\end{intest}
204
 
205
\begin{description}
206
\item [\textbf{void keyb\_default\_parm(KEYB\_PARMS parms);}]
207
\item [\textbf{Description:}] It changes the values of parms to the same vales
208
as the BASE\_KEYB default initializer.
209
\end{description}
210
 
211
\begin{intest}
212
KEYB\_DEF\_MAP\index{keyb\_def\_map()}
213
\end{intest}
214
 
215
\begin{description}
216
\item [\textbf{void keyb\_def\_map(KEYB\_PARMS parms, unsigned char map);}]
217
\item [\textbf{Description:}]It changes the default map used for the keyboard:
218
\texttt{map} can be \texttt{KEYMAP\_US} for an english keyboard or
219
\texttt{KEYMAP\_IT} for an italian keyboard. The default is english keyboard
220
layout.
221
\end{description}
222
 
223
\begin{intest}
224
KEYB\_DEF\_CTRLC\index{keyb\_def\_ctrlC()}
225
\end{intest}
226
 
227
\begin{description}
228
\item [\textbf{void keyb\_def\_ctrlC(KEYB\_PARMS parms, void
229
({*}ctrlcfunc)(KEY\_EVT {*}k));}]
230
\item [\textbf{Description:}] It enables the execution of a function when the
231
{}``ctrl\-C'' combination is pressed. By default, if this macro is not used, the
232
\texttt{ctrl\-C} combination results in calling \texttt{sys\_end()}. Note that a
233
small message is printed also on the console. The message is only visible if the
234
system is in text mode. If you are running a graphic application, remember to
235
redefine the Ctrl-C Handler!
236
\end{description}
237
 
238
\begin{intest}
239
KEYB\_DEF\_TASK\index{keyb\_def\_task()}
240
\end{intest}
241
\begin{description}
242
\item [\textbf{void keyb\_def\_task(KEYB\_PARMS parms, TASK\_MODEL {*} m);}]
243
\item [\textbf{Description:}] It specifies the parameters of the keyboard
244
server. The \texttt{TASK\_MODEL} {*} should be a valid pointer to a Task Model,
245
or \texttt{KEYB\_DEFAULT} if you want to specify the default behaviour. \\
246
This macro should be used every time the default server Task Model does not
247
adapt well to the configuration of the scheduling modules registered in the
248
system. \\
249
The default server Task Model is equivalent to this initialization:\\
250
\texttt{soft\_task\_default\_model(base\_m);}\\
251
\texttt{soft\_task\_def\_wcet(base\_m,2000);}\\
252
\texttt{soft\_task\_def\_met(base\_m,800);}\\
253
\texttt{soft\_task\_def\_period(base\_m,25000);}\\
254
\texttt{soft\_task\_def\_system(base\_m);}\\
255
\texttt{soft\_task\_def\_nokill(base\_m);}\\
256
\texttt{soft\_task\_def\_aperiodic(base\_m);}
257
\end{description}
258
 
259
\begin{intest}
260
KEYB\_GETCH, KEYB\_GETCHAR \index{keyb\_getch()} \index{keyb\_getchar()}
261
\end{intest}
262
 
263
\begin{description}
264
\item [\textbf{int keyb\_getch(BYTE wait);}]
265
\item [\textbf{int keyb\_getchar(void);}] (macro)
266
\item [\textbf{Description:}]If the keyboard queue is not empty,
267
\texttt{keyb\_getch()} returns the ASCII code of the pressed key. If the queue
268
is empty, the function's behaviour depends on the value of the \texttt{wait}
269
parameter: if it is \texttt{BLOCK}, then the calling task is blocked until a key
270
is pressed; if it is \texttt{NON\_BLOCK}, the function returns 0.
271
\texttt{keyb\_getchar()} is a macro for \texttt{keyb\_getch(BLOCK)}.
272
\item [\textbf{Return value:}] the ASCII code of the pressed key, if the buffer
273
is not empty; 0 otherwise.
274
\end{description}
275
 
276
\begin{intest}
277
KEYB\_GETCODE\index{keyb\_getcode()}
278
\end{intest}
279
\begin{description}
280
\item [\texttt{int}]\texttt{keyb\_getcode(KEY\_EVT
281
{*}k,
282
BYTE
283
wait);}
284
\item [\textbf{Description:}] It fetches the \texttt{KEY\_EVT} from the
285
keyboard's queue and copies it into the structure pointed by \texttt{k}. If the
286
queue is empty, the function behaves as \texttt{key\_getch()}.
287
\item [\textbf{Return value:}] 1 if a key was pressed, 0 otherwise.
288
\end{description}
289
 
290
\begin{intest}
291
KEYB\_HOOK\index{keyb\_hook()}
292
\end{intest}
293
 
294
\begin{description}
295
\item [\texttt{void}]\texttt{keyb\_hook(KEY\_EVT key, void ({*}hook)(KEY\_EVT
296
{*}keypressed), unsigned char lock);}
297
\item [\textbf{Description:}] Whenever the key combination specified in
298
\texttt{key} is pressed, the function \texttt{hook()} is invoked, getting
299
\texttt{key} as input parameter. If lock is set to \texttt{FALSE} after
300
executing the function \texttt{hook()}the key will be lost, otherwise it will be
301
inserted in the queue.
302
\end{description}
303
 
304
\begin{description}
305
\item [Example:]
306
\end{description}
307
 
308
\begin{verbatim}
309
#include <drivers/shark_keyb26.h>
310
 
311
void hook_func(KEY_EVT *keypressed) {
312
    switch (keypressed->ascii) {
313
        case 'w':
314
            /* if 'CTRL-w' is pressed... */
315
            ...
316
            break;
317
        case 'x':
318
            if (isLeftAlt(keypressed) || isRightAlt(keypressed)) {
319
                /* if 'ALT-x' is pressed... */
320
                ...
321
            } else {
322
                /* if 'x' is pressed... */
323
                ...
324
            }
325
    }
326
}
327
 
328
int main(int argc,char *argv[]) {
329
    KEY_EVT key;
330
 
331
    /* keyboard initialization */
332
 
333
    /* to hook 'CTRL-w' key */
334
 
335
    key.ascii = 'w';
336
    key.scan = KEY_W;
337
    key.status = KEY_PRESSED;
338
    key.flag = CNTR_BIT;
339
    keyb_hook(key,hook_func,FALSE);
340
 
341
    /* to hook key 'x' */
342
 
343
    key.ascii = 'x';
344
    key.scan = KEY_X;
345
    key.status = KEY_PRESSED;
346
    key.flag = 0;
347
    keyb_hook(key,hook_func, FALSE);
348
 
349
    /* to hook 'ALT-x' key */
350
 
351
    key.flag = ALTL_BIT | ALTR_BIT;
352
    keyb_hook(key,hook_func, FALSE);
353
    ...
354
}
355
\end{verbatim}
356
 
357
\begin{intest}
358
KEYB\_DISABLE\index{keyb\_disable()}
359
\end{intest}
360
 
361
\begin{description}
362
\item [\textbf{void keyb\_disable(void);}]
363
\item [\textbf{Description:}] Throw away the data arriving from the hardware
364
instead of processing them inside the driver.
365
\end{description}
366
 
367
\begin{intest}
368
KEYB\_ENABLE\index{keyb\_enable()}
369
\end{intest}
370
 
371
\begin{description}
372
\item [\textbf{void keyb\_enable(void);}]
373
\item [\textbf{Description:}] Allow the driver to receive data from the
374
hardware.
375
\end{description}
376
 
377
\begin{intest}
378
KEYB\_SET\_MAP\index{keyb\_set\_map()}
379
\end{intest}
380
 
381
\begin{description}
382
\item [\textbf{int keyb\_set\_map(unsigned char map);}]
383
\item [\textbf{Description:}] It changes the default map used for the keyboard:
384
\texttt{map} can be \texttt{KEYMAP\_US} for an english keyboard or
385
\texttt{KEYMAP\_IT} for an italian keyboard.
386
\item [\textbf{Return value:}] the keyboard map identifier effectively applied.
387
\end{description}
388
 
389
\begin{intest}
390
KEYB\_GET\_MAP\index{keyb\_get\_map()}
391
\end{intest}
392
\begin{description}
393
\item [\texttt{int}]\texttt{keyb\_get\_map(void);}
394
\item [\textbf{Description:}] Return the identifier of the keyboard map actually
395
in use.
396
\end{description}
397
 
398
\begin{intest}
399
KEY\_EVT\index{KEY\_EVT, structure}
400
\end{intest}
401
 
402
\begin{description}
403
\item [\textbf{Description:}] it is a data structure containing the following
404
fields:
405
 
406
\begin{description}
407
\item [ascii:]ascii code of the key;
408
\item [scan:]scan code of the key;
409
\item [status:]the key can be pressed, repeated or released. When used to set an
410
hook more than one status can be selected. The \texttt{status} field can be
411
accessed by one of the following macros, whose usage is self-explaining:
412
 
413
\begin{itemize}
414
\item isPressed(\&k)
415
\item isRepeated(\&k)
416
\item isReleased(\&k)
417
\end{itemize}
418
 
419
\item [flag:]codes of the ALT, SHIFT and CTRL keys. \\
420
The \texttt{flag} field can be accessed by one of the following macros, whose
421
usage is self-explaining:
422
 
423
\begin{itemize}
424
\item isScanCode(\&k), decides whether the hit key has an ASCII code or not;
425
\item isLeftShift(\&k)
426
\item isRightShift(\&k)
427
\item isLeftAlt(\&k)
428
\item isRightAlt(\&k)
429
\item isLeftCtrl(\&k)
430
\item isRightCtrl(\&k)
431
\end{itemize}
432
\end{description}
433
\end{description}
434
 
435
%----------------------------------------------------------------------------
436
\section{The mouse library}
437
%----------------------------------------------------------------------------
438
 
439
To use the mouse into an application program, the user must call the
440
\texttt{MOUSE26\_init} function. Then, all mouse functions are available until a
441
call to the \texttt{MOUSE26\_close} function. The initialization of the mouse
442
library is performed by \texttt{MOUSE26\_init}, which requires a parameter of
443
\texttt{MOUSE\_PARMS} type to initialize the mouse. The following example shows
444
a possible mouse initialization:
445
 
446
\begin{verbatim}
447
int main(int argc,char *argv[]) {
448
    int result;
449
    MOUSE_PARMS params = BASE_MOUSE;
450
 
451
    result = MOUSE26_init(&params);
452
    if (result!=0) {
453
        // the mouse can't be initialized
454
    }
455
    // other mouse functions
456
    MOUSE26_close();
457
}
458
\end{verbatim}
459
 
460
The \texttt{MOUSE26\_close} function is not required but can be used to release
461
all the hardware resources that the library acquires. The NULL constant can be
462
passed to the \texttt{MOUSE26\_init()} function for a default initialization.
463
The \texttt{params} variable can be used to change the default setting of the
464
initialization procedure using some macros, whose names start with
465
\texttt{mouse\_def\_}. All the mouse functions can be found in the include file
466
\texttt{drivers/shark\_mouse26.h}.
467
 
468
\vspace{7mm}
469
 
470
\begin{intest}
471
MOUSE26\_INIT\index{MOUSE26\_init()}
472
\end{intest}
473
 
474
\begin{description}
475
\item [\texttt{int}]\texttt{MOUSE26\_init(KEYB\_PARMS
476
{*}parms);}
477
\item [\textbf{Description:}] It initializes the mouse interface and the
478
library's internal data structures. It can be called using NULL as
479
\texttt{parms} to initialize the mouse interface to default values.
480
\item [\textbf{Return value:}] 0 if the operation is performed successfully; a
481
value less than 0, otherwise.
482
\end{description}
483
\begin{intest}
484
MOUSE26\_CLOSE\index{MOUSE26\_close()}
485
\end{intest}
486
\begin{description}
487
\item [\texttt{int}]\texttt{MOUSE26\_close(void);}
488
\item [\textbf{Description:}] It
489
close
490
the
491
mouse
492
interface.
493
\item [\textbf{Return value:}]
494
 
495
if
496
the
497
operation
498
is
499
performed
500
successfully;
501
-1
502
if
503
the
504
mouse
505
in
506
not
507
installed.
508
\end{description}
509
\begin{intest}
510
MOUSE26\_INSTALLED\index{MOUSE26\_installed()}
511
\end{intest}
512
\begin{description}
513
\item [\texttt{int}]\texttt{MOUSE26\_installed(void);}
514
\item [\textbf{Description:}] Return
515
if
516
the
517
mouse
518
driver
519
is
520
actually
521
installed.
522
\item [\textbf{Return value:}]
523
 
524
if
525
the
526
mouse
527
is
528
installed;
529
1
530
otherwise.
531
\end{description}
532
\begin{intest}
533
MOUSE\_DEFAULT\_PARM\index{mouse\_default\_parm()}
534
\end{intest}
535
\begin{description}
536
\item [\texttt{void}]\texttt{mouse\_default\_parm(KEYB\_PARMS
537
parms);}
538
\item [\textbf{Description:}] It
539
changes
540
the
541
values
542
of
543
parms
544
to
545
the
546
same
547
vales
548
as
549
the
550
BASE\_MOUSE
551
default
552
initializer.
553
\end{description}
554
\begin{intest}
555
MOUSE\_DEF\_THRESHOLD\index{mousedef\_def\_threshold()}
556
\end{intest}
557
\begin{description}
558
\item [\texttt{void}]\texttt{mouse\_def\_threshold(MOUSE\_PARMS
559
parms,
560
int
561
thr);}
562
\item [\textbf{Description:}] It
563
changes
564
the
565
default
566
threshold
567
(i.e.,
568
the
569
mouse
570
sensitivity)
571
value
572
used
573
in
574
the
575
mouse
576
driver.
577
Is
578
a
579
scaling
580
factor
581
between
582
the
583
hardware
584
position
585
increment
586
and
587
the
588
logical
589
increment
590
in
591
the
592
mouse
593
position.
594
The
595
higher
596
the
597
value,
598
the
599
lower
600
the
601
sensitivity.
602
The
603
default
604
is
605
10.
606
\end{description}
607
\begin{intest}
608
MOUSE\_DEF\_X0,
609
MOUSE\_DEF\_Y0,
610
MOUSE\_DEF\_Z0\index{mousedef\_def\_x0()} \index{mousedef\_def\_y0()}
611
\index{mousedef\_def\_z0()}
612
\end{intest}
613
\begin{description}
614
\item [\texttt{void}]\texttt{mouse\_def\_x0(MOUSE\_PARMS
615
parms,
616
int
617
xvalue);}
618
\item [\texttt{void}]\texttt{mouse\_def\_y0(MOUSE\_PARMS
619
parms,
620
int
621
yvalue);}
622
\item [\texttt{void}]\texttt{mouse\_def\_z0(MOUSE\_PARMS
623
parms,
624
int
625
zvalue);}
626
\item [\textbf{Description:}] These
627
functions
628
change
629
the
630
initial
631
value
632
of
633
the
634
mouse
635
position.
636
The
637
default
638
vilue
639
for
640
each
641
parameter
642
is
643
 
644
if
645
permitted
646
by
647
mouse
648
position
649
bounds.
650
\end{description}
651
\begin{intest}
652
MOUSE\_DEF\_XMIN,
653
MOUSE\_DEF\_XMAX\index{mousedef\_def\_xmin()} \index{mousedef\_def\_xmax()}
654
\end{intest}
655
\begin{description}
656
\item [\texttt{void}]\texttt{mouse\_def\_xmin(MOUSE\_PARMS
657
parms,
658
int
659
minvalue);}
660
\item [\texttt{void}]\texttt{mouse\_def\_xmax(MOUSE\_PARMS
661
parms,
662
int
663
maxvalue);}
664
\item [\textbf{Description:}] It
665
changes
666
the
667
minimum
668
and
669
maximum
670
allowed
671
value
672
for
673
the
674
x
675
coordinate.
676
\end{description}
677
\begin{intest}
678
MOUSE\_DEF\_YMIN,
679
MOUSE\_DEF\_YMAX\index{mousedef\_def\_ymin()} \index{mousedef\_def\_ymax()}
680
\end{intest}
681
\begin{description}
682
\item [\texttt{void}]\texttt{mouse\_def\_ymin(MOUSE\_PARMS
683
parms,
684
int
685
minvalue);}
686
\item [\texttt{void}]\texttt{mouse\_def\_ymax(MOUSE\_PARMS
687
parms,
688
int
689
maxvalue);}
690
\item [\textbf{Description:}] It
691
changes
692
the
693
minimum
694
and
695
maximum
696
allowed
697
value
698
for
699
the
700
y
701
coordinate.
702
\end{description}
703
\begin{intest}
704
MOUSE\_DEF\_TASK\index{mouse\_def\_task()}
705
\end{intest}
706
\begin{description}
707
\item [\texttt{void}]\texttt{mouse\_def\_task(MOUSE\_PARMS
708
parms,
709
TASK\_MODEL
710
{*}
711
m);}
712
\item [\textbf{Description:}] This
713
macro
714
defines
715
the
716
parameters
717
for
718
the
719
mouse
720
handling
721
task.
722
The
723
\texttt{TASK\_MODEL}
724
{*}
725
should
726
be
727
a
728
valid
729
pointer
730
to
731
a
732
Task
733
Model,
734
or
735
\texttt{MOUSE\_DEFAULT}
736
if
737
you
738
want
739
to
740
specify
741
the
742
default
743
behaviour.
744
\\
745
This
746
macro
747
should
748
be
749
used
750
every
751
time
752
the
753
default
754
Task
755
Model
756
does
757
not
758
adapt
759
well
760
to
761
the
762
configuration
763
of
764
the
765
scheduling
766
modules
767
registered
768
in
769
the
770
system.
771
\\
772
The
773
default
774
Task
775
Model
776
is
777
equivalent
778
to
779
this
780
initialization:\\
781
\texttt{soft\_task\_default\_model(base\_m);
782
}~\\
783
\texttt{soft\_task\_def\_wcet(base\_m,2000);
784
}~\\
785
\texttt{soft\_task\_def\_met(base\_m,500);
786
}~\\
787
\texttt{soft\_task\_def\_period(base\_m,8000);
788
}~\\
789
\texttt{soft\_task\_def\_system(base\_m);
790
}~\\
791
\texttt{soft\_task\_def\_nokill(base\_m);
792
}~\\
793
\texttt{soft\_task\_def\_aperiodic(base\_m);}
794
\end{description}
795
\begin{intest}
796
MOUSE\_ENABLE\index{mouse\_enable()}
797
\end{intest}
798
\begin{description}
799
\item [\texttt{void}]\texttt{mouse\_enable(void);}
800
\item [\textbf{Description:}] Allow
801
the
802
driver
803
to
804
receive
805
data
806
from
807
the
808
hardware.
809
\end{description}
810
\begin{intest}
811
MOUSE\_DISABLE\index{mouse\_disable()}
812
\end{intest}
813
\begin{description}
814
\item [\texttt{void}]\texttt{mouse\_disable(void);}
815
\item [\textbf{Description:}] This
816
function
817
disable
818
the
819
mouse;
820
the
821
driver
822
stop
823
to
824
respond
825
to
826
the
827
data
828
arriving
829
from
830
the
831
hardware.
832
\end{description}
833
\begin{intest}
834
MOUSE\_SETPOSITION\index{mouse\_setstatus()}
835
\end{intest}
836
\begin{description}
837
\item [\texttt{void}]\texttt{mouse\_setposition(int
838
x,
839
int
840
y,
841
int
842
z);}
843
\item [\textbf{Description:}] Set
844
values
845
for
846
axes
847
and
848
wheel.
849
Values
850
for
851
x
852
and
853
y
854
axis
855
are
856
compared
857
against
858
bounds
859
for
860
the
861
allowed
862
zone.
863
\end{description}
864
\begin{intest}
865
MOUSE\_GETPOSITION\index{mouse\_getstatus()}
866
\end{intest}
867
\begin{description}
868
\item [\texttt{void}]\texttt{mouse\_getposition(int
869
{*}x,
870
int
871
{*}y,
872
int
873
{*}z,
874
unsigned
875
long
876
{*}buttons);}
877
\item [\textbf{Description:}] Get
878
values
879
for
880
axes,
881
wheel
882
and
883
buttons.
884
In
885
the
886
\texttt{buttons}
887
variable
888
each
889
bit
890
rappresent
891
the
892
status
893
of
894
a
895
button.
896
\end{description}
897
\begin{intest}
898
MOUSE\_SETLIMITS\index{mouse\_setlimits()}
899
\end{intest}
900
\begin{description}
901
\item [\texttt{void}]\texttt{mouse\_setlimits(int
902
xmin,
903
int
904
ymin,
905
int
906
xmax,
907
int
908
ymax);}
909
\item [\textbf{Description:}] It
910
changes
911
the
912
minimum
913
and
914
maximum
915
allowed
916
value
917
for
918
x
919
and
920
y
921
coordinate.
922
\end{description}
923
\begin{intest}
924
MOUSE\_GETLIMITS\index{mouse\_getlimits()}
925
\end{intest}
926
\begin{description}
927
\item [\texttt{void}]\texttt{mouse\_getlimits(int
928
{*}xmin,
929
int
930
{*}ymin,
931
int
932
{*}xmax,
933
int
934
{*}ymax);}
935
\item [\textbf{Description:}] Allow
936
to
937
obtain
938
the
939
minimum
940
and
941
maximum
942
permited
943
value
944
for
945
x
946
and
947
y
948
coordinate.
949
\end{description}
950
\begin{intest}
951
MOUSE\_SETTHRESHOLD\index{mouse\_setthreshold()}
952
\end{intest}
953
\begin{description}
954
\item [\texttt{void}]\texttt{mouse\_setthreshold(int
955
th);}
956
\item [\textbf{Description:}] It
957
changes
958
the
959
threshold
960
value
961
used
962
in
963
the
964
mouse
965
driver.
966
Is
967
a
968
scaling
969
factor
970
between
971
the
972
hardware
973
position
974
increment
975
and
976
the
977
logical
978
increment
979
in
980
the
981
mouse
982
position.
983
The
984
default
985
is
986
10.
987
\end{description}
988
\begin{intest}
989
MOUSE\_GETTHRESHOLD\index{mouse\_getthreshold()}
990
\end{intest}
991
\begin{description}
992
\item [\texttt{void}]\texttt{mouse\_getthreshold(int
993
th);}
994
\item [\textbf{Description:}] Return
995
the
996
threshold
997
value
998
used
999
in
1000
the
1001
mouse
1002
driver.
1003
Is
1004
a
1005
scaling
1006
factor
1007
between
1008
the
1009
hardware
1010
position
1011
increment
1012
and
1013
the
1014
logical
1015
increment
1016
in
1017
the
1018
mouse
1019
position.
1020
The
1021
default
1022
is
1023
10.
1024
\end{description}
1025
\begin{intest}
1026
MOUSE\_HOOK\index{mouse\_hook()}
1027
\end{intest}
1028
\begin{description}
1029
\item [\texttt{void}]\texttt{mouse\_hook(MOUSE\_HANDLER
1030
hook);}
1031
\item [\textbf{Description:}] Whenever
1032
the
1033
driver
1034
receive
1035
data
1036
from
1037
the
1038
hardware
1039
the
1040
function
1041
\texttt{hook()}
1042
is
1043
invoked
1044
with
1045
a
1046
\texttt{MOUSE\_EVT}
1047
as
1048
parameter.
1049
To
1050
detach
1051
a
1052
previously
1053
defined
1054
hook
1055
with
1056
NULL
1057
as
1058
parameter.
1059
\end{description}
1060
 
1061
\begin{intest}
1062
MOUSE\_EVT\index{MOUSE\_EVT, structure}
1063
\end{intest}
1064
 
1065
\begin{description}
1066
\item [\textbf{Description:}] it is a data structure containing the following
1067
fields:
1068
 
1069
\begin{description}
1070
\item [x,y,z:]actual mouse position;
1071
\item [dx,dy,dz:]increments from the last event;
1072
\item [buttons:]each bit in the parameter rappresent the status of one button of
1073
the mouse.
1074
\end{description}
1075
 
1076
\item [The]following code shows an example of usage for the function
1077
\texttt{mouse\_hook} and the structure \texttt{MOUSE\_EVT}:
1078
\end{description}
1079
 
1080
\begin{description}
1081
\item [Example:]
1082
\end{description}
1083
 
1084
\begin{verbatim}
1085
#include <drivers/shark_mouse26.h>
1086
 
1087
void hook_func(MOUSE_EVT *mevt) {
1088
    if (mevt->button & 0x1) {
1089
 
1090
        /* The 1st button is pressed... */
1091
        ...
1092
    }
1093
    if ((mevt->dx > 10) || (mevt->dx > 10)) {
1094
 
1095
        /* Increment on x or y axis major than 10... */
1096
        ...
1097
    }
1098
    if (mevt->dz > 0) {
1099
 
1100
    /* Wheel position changed... */
1101
    ...
1102
}
1103
 
1104
int main(int argc,char *argv[]) {
1105
 
1106
    /* mouse hook initialization */
1107
 
1108
    mouse_hook(hook_func);
1109
    ...
1110
}
1111
\end{verbatim}
1112
 
1113
\begin{intest}
1114
ISLEFTBUTTON, ISCENTRALBUTTON, ISRIGHTBUTTON\index{isLeftButton()}
1115
\index{isCentralButton()} \index{isRightButton()}
1116
\end{intest}
1117
 
1118
\begin{description}
1119
\item [\textbf{isLeftButton(int button)}]
1120
\item [\textbf{isCentralButton(int button)}]
1121
\item [\textbf{isRightButton(int button)}]
1122
\item [\textbf{Description:}] These macros are used to test whether a specific
1123
mouse button is pressed.
1124
\end{description}
1125
 
1126
%----------------------------------------------------------------------------
1127
\subsection{The mouse graphics functions}
1128
%----------------------------------------------------------------------------
1129
 
1130
The system provide a set of function to quickly draw the mouse cursor both in
1131
text and graphic mode. For each mode we can find 2 functions. The first used to
1132
set the cursor shape and the second to enable/disable the cursor visualization.
1133
 
1134
ATTENTION: In text mode the mouse position is taken considering characters,
1135
while in graphics values are pixels as mining.
1136
 
1137
\vspace{7mm}
1138
 
1139
\begin{intest}
1140
MOUSE\_TXTCURSOR,\index{mouse\_txtcursor()}MOUSE\_GRXCURSOR\index{
1141
mouse\_grxcursor()}
1142
\end{intest}
1143
 
1144
\begin{description}
1145
\item [\textbf{void mouse\_txtcursor(int cmd);}]
1146
\item [\textbf{void mouse\_grxcursor(int cmd, int bpp);}]
1147
\item [\textbf{Description:}] This function enables/disables the
1148
textual/grafical autocursor features of the library; \texttt{cmd} can be:
1149
\texttt{DISABLE} (disable cursor), \texttt{ENABLE} (enable a cursor). The
1150
graphic version need and other parameter \texttt{bpp} which is depth of the
1151
screen in bytes. These commands can be composite with two flags:
1152
 
1153
\begin{itemize}
1154
\item \texttt{AUTOOFF}: if a user mouse handler is called, then during this call
1155
the mouse is off (if you use a \texttt{mouse\_off()} you can hang the mouse
1156
task).
1157
\item \texttt{WITHOUTSEM}: the autocursor mouse functions are not protected by a
1158
semaphore (so tasks cannot be blocked, but garbage can be displayed).
1159
\end{itemize}
1160
 
1161
\end{description}
1162
 
1163
\begin{intest}
1164
MOUSE\_TXTSHAPE\index{mouse\_txtshape()}
1165
\end{intest}
1166
 
1167
\begin{description}
1168
\item [\textbf{void mouse\_txtshape(DWORD shape);}]
1169
\item [\textbf{Description:}] This function defines the shape of the text
1170
cursor; ``shape'' is a DWORD that is used to display the cursor: the text
1171
character and attributes are taken from the text memory, these values are and-ed
1172
with the low word of \texttt{shape} and the result is XOR-ed with the high word
1173
of \texttt{shape}, the result is written into the text memory. For examples, the
1174
default mouse cursor shape is 0x7700ffff; the character and attribute that are
1175
taken from the the memory are and-ed with 0xffff, so they do not change, and
1176
then are xor-ed with 0x7700: the character is xor-ed with 0x00 and the attribute
1177
byte is xor-ed with 0x77; the character remains the same but the attribute byte
1178
is inverted; so the mouse cursor is displayed inverting the colors of the
1179
character (the attribute byte contains the character foreground and background
1180
color and is coded in the usually EGA/VGA mode; you can read a book about VGA
1181
display adapters to find more
1182
informations).
1183
\end{description}
1184
 
1185
\begin{intest}
1186
MOUSE\_GRXSHAPE\index{mouse\_grxshape()}
1187
\end{intest}
1188
 
1189
\begin{description}
1190
\item [\textbf{void mouse\_grxshape(BYTE {*}img, BYTE {*}mask, int bpp);}]
1191
\item [\textbf{Description:}] This function defines the shape of the graphical
1192
cursor; \texttt{img} is a pointer to an image of 16x16 that can be used with the
1193
\texttt{grx\_putimage()} function, or can be \texttt{NULL} (in this case a
1194
default cursor is used); before putting the image into the screen's memory, the
1195
image is and-ed with \texttt{mask}. The parameter \texttt{bpp} is depth of the
1196
screen in bytes.
1197
\item [Example:]
1198
 
1199
\begin{tt}
1200
\begin{verbatim}
1201
/*
1202
 * the resolution is 640x480 with 2 BYTE for pixel
1203
 */
1204
 
1205
/* WHITE,RED,GREEN and MAGENTA are defined into <cons.h>*/
1206
 
1207
#define W rgb16(255, 255, 255)
1208
#define R rgb16(255,   0,   0)
1209
#define G rgb16(  0, 255,   0)
1210
#define M rbg16(255,   0, 255)
1211
 
1212
/* mouse shape */
1213
 
1214
WORD my_mouse_cursor[16 * 16] = {
1215
   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1216
   0,W,W,W,W,0,0,0,0,0,0,W,W,W,W,0,
1217
   0,W,M,0,0,0,0,0,0,0,0,0,0,M,W,0,
1218
   0,W,0,M,0,0,0,0,0,0,0,0,M,0,W,0,
1219
   0,W,0,0,M,0,0,0,0,0,0,M,0,0,W,0,
1220
   0,0,0,0,0,M,0,0,0,0,M,0,0,0,0,0,
1221
   0,0,0,0,0,0,G,G,G,G,0,0,0,0,0,0,
1222
   0,0,0,0,0,0,G,0,0,G,0,0,0,0,0,0,
1223
   0,0,0,0,0,0,G,0,0,G,0,0,0,0,0,0,
1224
   0,0,0,0,0,0,G,0,0,G,0,0,0,0,0,0,
1225
   0,0,0,0,0,0,G,G,G,G,0,0,0,0,0,0,
1226
   0,0,0,0,0,0,M,M,M,M,0,0,0,0,0,0,
1227
   0,0,0,0,0,0,M,M,M,M,0,0,0,0,0,0,
1228
   0,0,0,0,0,M,M,M,M,M,M,0,0,0,0,0,
1229
   0,0,0,0,M,M,M,M,M,M,M,M,0,0,0,0,
1230
   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1231
};
1232
 
1233
/* mask for pixels (2 bytes in this case) */
1234
/* 0xffff means that the background image is used */
1235
/* 0x0000 means tha the background image is cleared */
1236
/*        prior to draw the mouse cursor */
1237
 
1238
#define F 0xffff
1239
#define B 0x0000
1240
 
1241
/* mouse mask */
1242
WORD my_mouse_mask[16 * 16] = {
1243
   B,B,B,B,B,B,F,F,F,F,B,B,B,B,B,B,
1244
   B,0,0,0,0,B,F,F,F,F,B,0,0,0,0,B,
1245
   B,0,0,B,B,F,F,F,F,F,B,B,B,0,0,B,
1246
   B,0,B,0,B,F,F,F,F,F,F,B,0,B,0,B,
1247
   B,0,B,B,0,B,F,F,F,F,B,0,B,B,0,B,
1248
   B,B,B,F,B,0,B,B,B,B,0,B,F,B,B,B,
1249
   F,F,F,F,F,B,0,0,0,0,B,F,F,F,F,F,
1250
   F,F,F,F,F,B,0,B,B,0,B,F,F,F,F,F,
1251
   F,F,F,F,F,B,0,B,B,0,B,F,F,F,F,F,
1252
   F,F,F,F,F,B,0,B,B,0,B,F,F,F,F,F,
1253
   F,F,F,F,F,B,0,0,0,0,B,F,F,F,F,F,
1254
   F,F,F,F,F,B,0,0,0,0,B,F,F,F,F,F,
1255
   F,F,F,F,F,B,0,0,0,0,B,F,F,F,F,F,
1256
   F,F,F,F,B,0,0,0,0,0,0,B,F,F,F,F,
1257
   F,F,F,B,0,0,0,0,0,0,0,0,B,F,F,F,
1258
   F,F,F,B,B,B,B,B,B,B,B,B,B,F,F,F,
1259
};
1260
 
1261
int main(int argc, char *argv[]) {
1262
  MOUSE_PARMS mouse = BASE_MOUSE;
1263
 
1264
  /*
1265
   * mouse initialization
1266
   */
1267
  MOUSE26_init(&mouse);
1268
 
1269
  /* a resolution of 640x480 is used */
1270
  mouse_setlimit(XMINLIMIT(640,480),
1271
      YMINLIMIT(640,480),
1272
      XMAXLIMIT(640,480),
1273
      YMAXLIMIT(640,480));
1274
 
1275
  /* initial position */
1276
  mouse_setposition(320,280);
1277
 
1278
  /* mouse threshold */
1279
  mouse_setthreshold(2);
1280
 
1281
  /* my new mouse shape */
1282
  mouse_grxshape(my_mouse_cursor,my_mouse_mask, 2);
1283
 
1284
  /* automatic graphics mouse cursor enabled */
1285
  mouse_grxcursor(ENABLE, 2);
1286
 
1287
  /* mouse displayed into the screen */
1288
  mouse_on();  
1289
  ...
1290
}
1291
\end{verbatim}
1292
\end{tt}
1293
 
1294
\end{description}
1295
 
1296
\begin{intest}
1297
MOUSE\_OFF, MOUSE\_ON \index{mouse\_off()}\index{mouse\_on()}
1298
\end{intest}
1299
 
1300
\begin{description}
1301
\item [\textbf{void mouse\_off(void);}]
1302
\item [\textbf{void mouse\_on(void);}]
1303
\item [\textbf{Description:}] This functions disables and enables the display of
1304
the mouse cursor on the screen (the mouse events are handled).
1305
\item [\textbf{Warning:}]These functions must be called before/after calling any
1306
graphic function that modifies the screen.
1307
\end{description}
1308
 
1309
%----------------------------------------------------------------------------
1310
\section{The joystick library}
1311
%----------------------------------------------------------------------------
1312
 
1313
In order to use the gameport handling functions, the
1314
\texttt{drivers/shark\_joy26.h} header file, containing the interface functions'
1315
prototypes, has to be included in the application program.
1316
 
1317
First of all, the joystick needs be initialized by the calling
1318
\texttt{JOY26\_init} primitive into the \texttt{\_\_init\_\_} function in the
1319
initialization file or in any other point of the application code.
1320
 
1321
ATTENTION: The driver only work with gameport that emulate the ``old
1322
SoundBlaster'' gameport interface. Other kind of gameports will not be
1323
identified.
1324
 
1325
\vspace{7mm}
1326
 
1327
\begin{intest}
1328
JOY26\_INIT\index{JOY26\_init()}
1329
\end{intest}
1330
 
1331
\begin{description}
1332
\item [\textbf{int JOY26\_init(void);}]
1333
\item [\textbf{Description:}] It initializes the joystick interface and the
1334
library's internal data structures.
1335
\item [\textbf{Return value:}] 0 if the operation is performed successfully; a
1336
value less than 0, otherwise.
1337
\end{description}
1338
 
1339
\begin{intest}
1340
JOY26\_CLOSE\index{JOY26\_close()}
1341
\end{intest}
1342
\begin{description}
1343
\item [\texttt{int}]\texttt{MOUSE26\_close(void);}
1344
\item [\textbf{Description:}] It close the joystick interface.
1345
\item [\textbf{Return value:}] 0 if the operation is performed successfully; -1
1346
if the joystick in not installed.
1347
\end{description}
1348
 
1349
\begin{intest}
1350
JOY26\_INSTALLED\index{JOY26\_installed()}
1351
\end{intest}
1352
 
1353
\begin{description}
1354
\item [\textbf{int JOY26\_installed(void);}]
1355
\item [\textbf{Description:}] Return if the joystick driver is actually installed.
1356
\item [\textbf{Return value:}] 0 if the joystick is installed; 1 otherwise.
1357
\end{description}
1358
 
1359
\begin{intest}
1360
JOY\_ENABLE\index{joy\_enable()}
1361
\end{intest}
1362
 
1363
\begin{description}
1364
\item [\textbf{void joy\_enable(void);}]
1365
\item [\textbf{Description:}] Allow the driver to receive data from the hardware.
1366
\end{description}
1367
 
1368
\begin{intest}
1369
JOY\_DISABLE\index{joy\_disable()}
1370
\end{intest}
1371
 
1372
\begin{description}
1373
\item [\texttt{void}]\texttt{joy\_disable(void);}
1374
\item [\textbf{Description:}] Throw away the data arriving from the hardware
1375
instead of processing them inside the driver.
1376
\end{description}
1377
 
1378
\begin{intest}
1379
JOY\_SETSTATUS\index{joy\_setstatus()}
1380
\end{intest}
1381
 
1382
\begin{description}
1383
\item [\textbf{void joy\_setstatus(int axe0, int axe1, int axe2, int axe3, int buttons);}]
1384
\item [\textbf{Description:}] Set values for axes and buttons. Usually
1385
\texttt{axe0} and \texttt{axe1} are x and y axis for the first joystick while
1386
\texttt{axe2} and \texttt{axe3} are x and y axis for the second one. In the
1387
\texttt{buttons} parameter each bit rapresents the status of one button.
1388
\end{description}
1389
 
1390
\begin{intest}
1391
JOY\_GETSTATUS\index{joy\_getstatus()}
1392
\end{intest}
1393
 
1394
\begin{description}
1395
\item [\textbf{void joy\_getstatus(int {*}axe0, int {*}axe1, int {*}axe2, int {*}axe3, int {*}buttons);}]
1396
\item [\textbf{Description:}] Get values for axes and buttons. Usually
1397
\texttt{axe0} and \texttt{axe1} are x and y axis for the first joystick while
1398
\texttt{axe2} and \texttt{axe3} are x and y axis for the second one. In the
1399
\texttt{buttons} parameter each bit rappresent the status of one button.
1400
\end{description}
1401
 
1402
%----------------------------------------------------------------------------
1403
\section{The speaker library}
1404
%----------------------------------------------------------------------------
1405
 
1406
The system provide a driver to use the internal PC speaker. It can play a note
1407
at a given frequency for a predefined period or in a endless loop. In order to
1408
use the speaker handling functions, the \texttt{drivers/shark\_spk26.h} header
1409
file, containing the interface functions' prototypes, has to be included in the
1410
application program.
1411
 
1412
First of all, the mouse needs be initialized by the calling
1413
\texttt{SPEAK26\_init} primitive into the \texttt{\_\_init\_\_} function in the
1414
initialization file or in any other point of the application code and the input
1415
low level driver must be already installed.
1416
 
1417
\vspace{7mm}
1418
 
1419
\begin{intest}
1420
SPEAK26\_INIT\index{SPEAK26\_init()}
1421
\end{intest}
1422
 
1423
\begin{description}
1424
\item [\textbf{int SPEAK26\_init(void);}]
1425
\item [\textbf{Description:}] It initializes the speaker interface and the
1426
library's internal data structures.
1427
\item [\textbf{Return value:}] 0 if the operation is performed successfully; a
1428
value less than 0, otherwise.
1429
\end{description}
1430
 
1431
\begin{intest}
1432
SPEAK26\_CLOSE\index{SPEAK26\_close()}
1433
\end{intest}
1434
 
1435
\begin{description}
1436
\item [\textbf{int SPEAK26\_close(void);}]
1437
\item [\textbf{Description:}] It close the speaker interface.
1438
\item [\textbf{Return value:}] 0 if the operation is performed successfully; -1
1439
if the speaker in not installed.
1440
\end{description}
1441
 
1442
\begin{intest}
1443
SPEAK26\_INSTALLED\index{SPEAK26\_installed()}
1444
\end{intest}
1445
 
1446
\begin{description}
1447
\item [\textbf{int SPEAK26\_installed(void);}]
1448
\item [\textbf{Description:}] Return if the speaker driver is actually installed.
1449
\item [\textbf{Return value:}] 0 if the speaker is installed; 1 otherwise.
1450
\end{description}
1451
 
1452
\begin{intest}
1453
SPEAKER\_SOUND\index{speaker\_sound()}
1454
\end{intest}
1455
 
1456
\begin{description}
1457
\item [\textbf{void speaker\_sound(unsigned int hz, unsigned int ticks);}]
1458
\item [\textbf{Description:}] Generate a note at a frequency given using the
1459
parameter \texttt{hz}. The parameter \texttt{ticks} is the duration of the note;
1460
if set to 0 the note is repeated in an endless loop.
1461
\end{description}
1462
 
1463
\begin{intest}
1464
SPEAKER\_MUTE\index{speaker\_mute()}
1465
\end{intest}
1466
 
1467
\begin{description}
1468
\item [\texttt{int}]\texttt{speaker\_mute(void);}
1469
\item [\textbf{Description:}] Reset the internal speaker making it silent.
1470
\end{description}
1471