OpenCores
URL https://opencores.org/ocsvn/s6soc/s6soc/trunk

Subversion Repositories s6soc

[/] [s6soc/] [trunk/] [sw/] [zipos/] [doorbell.c] - Blame information for rev 39

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 22 dgisselq
////////////////////////////////////////////////////////////////////////////////
2
//
3
// Filename:    doorbell.c
4
//
5
// Project:     CMod S6 System on a Chip, ZipCPU demonstration project
6
//
7 29 dgisselq
// Purpose:     This is the user program, or perhaps more appropriately
8
//              user program(s), associated with running the ZipOS on the
9
//      CMod-S6.  To run within the ZipOS, a user program must implement
10
//      two functions: kntasks() and kinit(TASKP *).  The first one is simple.
11
//      it simply returns the number of tasks the kernel needs to allocate 
12
//      space for.  The second routine needs to allocate space for each task,
13
//      set up any file descriptors associated with (each) task, and identify
14
//      the entry point of each task.  These are the only two routines
15
//      associated with user tasks called from kernel space.  Examples of each
16
//      are found within here.
17 22 dgisselq
//
18
// Creator:     Dan Gisselquist, Ph.D.
19
//              Gisselquist Technology, LLC
20
//
21
////////////////////////////////////////////////////////////////////////////////
22
//
23
// Copyright (C) 2015-2016, Gisselquist Technology, LLC
24
//
25
// This program is free software (firmware): you can redistribute it and/or
26
// modify it under the terms of  the GNU General Public License as published
27
// by the Free Software Foundation, either version 3 of the License, or (at
28
// your option) any later version.
29
//
30
// This program is distributed in the hope that it will be useful, but WITHOUT
31
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
32
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
33
// for more details.
34
//
35
// You should have received a copy of the GNU General Public License along
36
// with this program.  (It's in the $(ROOT)/doc directory, run make with no
37
// target there if the PDF file isn't present.)  If not, see
38
// <http://www.gnu.org/licenses/> for a copy.
39
//
40
// License:     GPL, v3, as defined and found on www.gnu.org,
41
//              http://www.gnu.org/licenses/gpl.html
42
//
43
//
44
////////////////////////////////////////////////////////////////////////////////
45
//
46
//
47
#include "zipsys.h"
48
#include "board.h"
49
#include "ksched.h"
50
#include "kfildes.h"
51
#include "taskp.h"
52
#include "syspipe.h"
53
#include "ktraps.h"
54
#include "errno.h"
55
#include "swint.h"
56
 
57
#include "../dev/display.h"
58
#include "../dev/rtcsim.h"
59 29 dgisselq
#include "../dev/keypad.h"
60 22 dgisselq
 
61
/* Our system will need some pipes to handle ... life.  How about these:
62
 *
63
 *      rxpipe  - read()s from this pipe read from the UART
64
 *                      Interrupt fed
65
 *      txpipe  - write()s to this pipe write to the UART
66
 *                      Interrupt consumed
67
 *      keypipe - read()s from this pipe return values read by the keypad
68
 *      lcdpipe - write()s to this pipe write to the LCD display SPI port
69
 *      pwmpipe - write()s to this pipe will send values to the audio port
70
 *                      Interrupt consumed
71
 *
72 29 dgisselq
 * These pipes are allocated within the kernel setup function, ksetup().
73 22 dgisselq
 */
74
 
75
/* We'll need some tasks as well:
76
 *      User command task
77
 *              Handles user interaction
78
 *                      Reads from pipe--either the keypad or the UARTRX pipe
79
 *                      (Might be two such tasks in the system, one for each.)
80
 *              Sets clock upon request
81
 *              Reads from a pipe (rxpipe or keypipe), Writes to the txpipe pipe
82
 *      Doorbell task
83
 *              Maintains system time on the clock      : TIME: HH:MM:SS
84
 *              Maintains system status on display      : Light is (dis/en)abled
85
 *              Transitions when the doorbell is rung to: (fixed time line)
86
 *                                                      : DOORBELL!!
87
 *              When the doorbell is clear, returns to the original task.
88
 *              ---
89
 *              Waits on events, writes to the lcdpipe and pwmpipe.
90
 *              Reads from a command pipe, so that it can handle any user menu's
91
 *                      Command pipe.  This, though, is tricky.  It requires
92
 *                      a task that can be interrupted by either an event or a
93
 *                      pipe.  Blocking is going to be more tricky ...
94
 *      Keypad task
95
 *              Normally, you might think this should be an interrupt task.
96
 *              But, it needs state in order to have timeouts and to debounce
97
 *              the input pin.  So ... let's leave this as a task.
98
 *              ---
99
 *              Waits on events(keypad/timer), writes to the keypipe
100
 *      Display task
101
 *              The display does *not* need to be written to at an interrupt
102
 *              level.  It really needs to be written to at a task level, so
103
 *              let's make a display task.
104
 *              ---
105
 *              Reads from the lcdpipe
106
 *      Real-time Clock Task
107
 *              Gets called once per second to update the real-time clock
108
 *              and to post those updates as an event to other tasks that might
109
 *              be interested in it.
110
 *              ---
111
 *              Waits on system tasks, uses two semaphores
112
 */
113
 
114
 
115
/*
116
 * Read the keypad, write the results to an output pipe
117
 */
118
// #define      KEYPAD_TASK     keypad_task_id
119
/*
120 29 dgisselq
 * Read from the keypad, and set up a series of menu screens on the Display,
121
 * so that we can:
122
 *
123
 *      1. Set time
124
 *      2. Set dawn
125
 *      3. Set dusk
126
 */
127
#define MENU_TASK       menu_task_id
128
/*
129 22 dgisselq
 * Maintain a realtime clock
130
 */
131
#define RTCCLOCK_TASK   rtccclock_task_id
132
/*
133
 * Read from an incoming pipe, write results to the SPI port controlling the
134
 * display.
135
 */
136
#define DISPLAY_TASK    display_task_id
137
 
138
/*
139
 * Wait for a button press, and then based upon the clock set a light
140
 */
141
#define DOORBELL_TASK   doorbell_task_id
142
 
143
#define LAST_TASK       last_task_id
144
 
145
typedef enum    {
146
#ifdef  RTCCLOCK_TASK
147
        RTCCLOCK_TASK,
148
#endif
149
#ifdef  DOORBELL_TASK
150
#ifdef  DISPLAY_TASK
151
        DOORBELL_TASK, DISPLAY_TASK,
152
#endif
153
#endif
154 29 dgisselq
//#ifdef        KEYPAD_TASK
155
        //KEYPAD_TASK,
156
//#endif
157
#ifdef  MENU_TASK
158
        MENU_TASK,
159 22 dgisselq
#endif
160
#ifdef  COMMAND_TASK
161
        COMMAND_TASK,
162
#endif
163
        LAST_TASK
164
} TASKNAME;
165
 
166
 
167
void    rtctask(void),
168
        doorbell_task(void),
169
        display_task(void),
170
        keypad_task(void),
171 29 dgisselq
        menu_task(void);
172 22 dgisselq
        // idle_task ... is accomplished within the kernel
173
extern  void    restore_context(int *), save_context(int *);
174
extern  SYSPIPE *rxpipe, *txpipe, *pwmpipe, *lcdpipe;
175
SYSPIPE *midpipe;
176
extern  KDEVICE *pipedev;
177
 
178
int     kntasks(void) {
179
        return LAST_TASK;
180
} void  kinit(TASKP *tasklist) {
181
#ifdef  RTCCLOCK_TASK
182
        //
183
        tasklist[RTCCLOCK_TASK]    = new_task(16, rtctask);
184
#endif
185
 
186
#ifdef  DOORBELL_TASK
187
#ifdef  DISPLAY_TASK
188 27 dgisselq
        // 13 + 10 +9(uwrite)+4(uarthex)+2(uartstr)+2(uartchr)
189 29 dgisselq
        tasklist[DOORBELL_TASK]    = new_task(96, doorbell_task);
190
//      tasklist[DOORBELL_TASK]->fd[FILENO_STDOUT]= kopen((int)lcdpipe,pipedev);
191
        tasklist[DOORBELL_TASK]->fd[FILENO_STDERR]= kopen((int)txpipe, pipedev);
192
        tasklist[DOORBELL_TASK]->fd[FILENO_AUX] = kopen((int)pwmpipe,  pipedev);
193 22 dgisselq
 
194
        //
195
        tasklist[DISPLAY_TASK] = new_task(32, display_task);
196 29 dgisselq
        tasklist[DISPLAY_TASK]->fd[FILENO_STDIN] = kopen((int)lcdpipe,pipedev);
197 22 dgisselq
#endif
198
#endif
199
 
200
 
201
#ifdef  KEYPAD_TASK
202 29 dgisselq
        // Stack = 7 + 9(uwrite) + 2*4
203
        tasklist[KEYPAD_TASK] = new_task(32, keypad_task);
204
        tasklist[KEYPAD_TASK]->fd[FILENO_STDOUT] = kopen((int)keypipe,pipedev);
205 22 dgisselq
#endif
206 29 dgisselq
#ifdef  MENU_TASK
207
        // Stack = 18 + 10(showbell/shownow) + 9(uwrite) + 2(menu_readkey)
208
        //              + 18 (time_menu/dawn_menu/dusk_menu)
209
        tasklist[MENU_TASK] = new_task(72, menu_task);
210
        // tasklist[MENU_TASK]->fd[FILENO_STDIN] = kopen((int)keypipe,pipedev);
211
        tasklist[MENU_TASK]->fd[FILENO_STDOUT]= kopen((int)lcdpipe,pipedev);
212
        tasklist[MENU_TASK]->fd[FILENO_STDERR]= kopen((int)txpipe, pipedev);
213
#endif
214 22 dgisselq
}
215
 
216
// #define      HALF_HOUR_S     1800    // Seconds per half hour
217
// #define      HALF_HOUR_S     180     // Seconds per three minutes--for test
218
#define HALF_HOUR_S     30      // 3 Mins is to long, here's 3 seconds
219
 
220 29 dgisselq
#ifdef  MENU_TASK
221
unsigned        dawn = 0x060000, dusk = 0x180000;
222
#else
223 22 dgisselq
const unsigned  dawn = 0x060000, dusk = 0x180000;
224 29 dgisselq
#endif
225 22 dgisselq
 
226
void    shownow(unsigned now) { // Uses 10 stack slots + 8 for write()
227
        char    dmsg[9];
228
        dmsg[0] = PACK(0x1b,'[','j','T');
229
        dmsg[1] = PACK('i','m','e',':');
230
        dmsg[2] = PACK(' ',((now>>20)&0x3)+'0',
231
                        ((now>>16)&0xf)+'0',':');
232
        dmsg[3] = PACK( ((now>>12)&0xf)+'0',
233
                        ((now>> 8)&0xf)+'0',
234
                        ':',
235
                        ((now>> 4)&0xf)+'0');
236
        dmsg[4] = PACK( ((now    )&0xf)+'0',
237
                        0x1b, '[', '1');
238
        dmsg[5] = PACK(';','0','H',' ');
239
        if ((now < dawn)||(now > dusk)) {
240
                dmsg[6] = PACK('N','i','g','h');
241
                dmsg[7] = PACK('t',' ','t','i');
242
                dmsg[8] = PACK('m','e',0,0);
243
        } else {
244
                dmsg[6] = PACK('D','a','y','l');
245
                dmsg[7] = PACK('i','g','h','t');
246
                dmsg[8] = PACK('!',' ',0,0);
247
        } write(FILENO_STDOUT, dmsg, 9);
248
}
249
 
250
void    showbell(unsigned now) {        // Uses 10 stack slots + 8 for write()
251
        char    dmsg[9];
252
        dmsg[0] = PACK(0x1b,'[','j','T');
253
        dmsg[1] = PACK('i','m','e',':');
254
        dmsg[2] = PACK(' ',((now>>20)&0x3)+'0',
255
                        ((now>>16)&0xf)+'0',':');
256
        dmsg[3] = PACK( ((now>>12)&0xf)+'0',
257
                        ((now>> 8)&0xf)+'0',
258
                        ':',
259
                        ((now>> 4)&0xf)+'0');
260
        dmsg[4] = PACK( ((now    )&0xf)+'0',
261
                        0x1b, '[', '1');
262
        dmsg[5] = PACK(';','0','H',' ');
263
        dmsg[6] = PACK('D','o','o','r');
264
        dmsg[7] = PACK('b','e','l','l');
265
        dmsg[8] = PACK('!',' ',0,0);
266
        write(FILENO_STDOUT, dmsg, 9);
267
}
268
 
269 27 dgisselq
void    uartchr(char v) {
270
        if (write(FILENO_STDERR, &v, 1) != 1)
271
                write(FILENO_STDERR, "APPLE-PANIC", 11);
272
}
273
 
274
void    uartstr(const char *str) {
275
        int     cnt=0;
276
        while(str[cnt])
277
                cnt++;
278
        if (cnt != write(FILENO_STDERR, str, cnt))
279
                write(FILENO_STDERR, "PIPE-PANIC", 10);
280
}
281
 
282
void    uarthex(int num) {
283
        for(int ds=28; ds>=0; ds-=4) {
284
                int ch;
285
                ch = (num>>ds)&0x0f;
286
                if (ch >= 10)
287
                        ch = 'A'+ch-10;
288
                else
289
                        ch += '0';
290
                uartchr(ch);
291 29 dgisselq
        } uartstr("\r\n");
292 27 dgisselq
}
293
 
294 29 dgisselq
#ifdef DOORBELL_TASK
295
#include "../dev/samples.c"
296
 
297
void    belllight(unsigned now) {
298
        IOSPACE *sys = (IOSPACE *)IOADDR;
299
        if ((now < dawn)||(now > dusk))
300
                sys->io_spio = 0x088; // Turn our light on
301
        else
302
                sys->io_spio = 0x80; // Turn light off
303
}
304
 
305 22 dgisselq
void    doorbell_task(void) {
306
        // Controls LED 0x08
307
 
308
        // Start by initializing the display to GT Gisselquist\nTechnology
309
        // write(KFD_STDOUT, disp_build_backslash,sizeof(disp_build_backslash));
310
        // write(KFD_STDOUT, disp_build_gtlogo, sizeof(disp_build_gtlogo));
311
        // write(KFD_STDOUT, disp_reset_data, sizeof(disp_reset_data));
312
        // write(KFD_STDOUT, disp_gtech_data, sizeof(disp_gtech_data));
313
        IOSPACE *sys = (IOSPACE *)IOADDR;
314
 
315
        while(1) {
316
                int     event;
317
                // Initial state: doorbell is not ringing.  In this state, we
318
                // can wait forever for an event
319
                sys->io_spio = 0x080; // Turn our light off
320
                event = wait(INT_BUTTON|SWINT_PPS,-1);
321 29 dgisselq
 
322
#ifndef MENU_TASK
323 22 dgisselq
                unsigned when = rtcclock;
324
                if (event & INT_BUTTON)
325
                        showbell(when);
326
                else if (event & SWINT_PPS)
327
                        shownow(when);
328 29 dgisselq
#else
329
                if (event & INT_BUTTON)
330
                        post(SWINT_DOORBELL);
331
#endif
332 22 dgisselq
 
333
                while(event & INT_BUTTON) {
334
                        // Next state, the button has been pressed, the
335
                        // doorbell is ringing
336
 
337
                        // Seconds records the number of seconds since the
338
                        // button was last pressed.
339
                        int     seconds = 0;
340
 
341
                        // Check time: should we turn our light on or not?
342 39 dgisselq
                        belllight((volatile unsigned)rtcclock);
343 22 dgisselq
                        const int *sptr = sound_data;
344 27 dgisselq
                        // uartchr('N');
345 22 dgisselq
                        while(sptr < &sound_data[NSAMPLE_WORDS]) {
346
                                int     len = &sound_data[NSAMPLE_WORDS]-sptr;
347
                                if (len > 256)
348
                                        len = 256;
349
 
350 27 dgisselq
                                // We will stall here, if the audio FIFO is full
351 22 dgisselq
                                write(FILENO_AUX, sptr, len);
352
                                sptr += len;
353 27 dgisselq
 
354 22 dgisselq
                                // If the user presses the button more than
355
                                // once, we start the sound over as well as
356
                                // our light counter.
357
                                event = wait(INT_BUTTON|SWINT_PPS, 0);
358
                                if (event&INT_BUTTON) {
359 29 dgisselq
                                        if (sptr > &sound_data[1024]) {
360 22 dgisselq
                                                sptr = sound_data;
361
                                                seconds = 0;
362 29 dgisselq
#ifndef MENU_TASK
363 22 dgisselq
                                                when = (volatile unsigned)rtcclock;
364
                                                showbell(when);
365 29 dgisselq
#else
366
                                                post(SWINT_DOORBELL);
367
#endif
368 22 dgisselq
                                        }
369
                                } else if (event&SWINT_PPS) {
370
                                        seconds++;
371 39 dgisselq
                                        belllight((volatile unsigned)rtcclock);
372 29 dgisselq
#ifndef MENU_TASK
373 22 dgisselq
                                        showbell(when);
374 29 dgisselq
#endif
375 22 dgisselq
                                }
376
                        }
377
 
378
                        // Next state: the doorbell is no longer ringing, but
379
                        // we have yet to return to normal--the light is still
380
                        // on.
381
                        while((seconds < HALF_HOUR_S)&&
382
                                (((event=wait(INT_BUTTON|SWINT_PPS,-1))&INT_BUTTON)==0)) {
383
                                seconds++;
384 39 dgisselq
                                belllight((volatile unsigned)rtcclock);
385 29 dgisselq
#ifndef MENU_TASK
386 22 dgisselq
                                showbell(when);
387 29 dgisselq
#endif
388 22 dgisselq
                        }
389
                        if (event&INT_BUTTON) {
390 29 dgisselq
#ifndef MENU_TASK
391 22 dgisselq
                                when = (volatile unsigned)rtcclock;
392
                                showbell(when);
393 29 dgisselq
#endif
394 22 dgisselq
                        }
395
                }
396
        }
397
}
398
#endif
399
 
400 29 dgisselq
#ifdef  MENU_TASK
401
void    entered_menu_str(char *str, unsigned now,int pos) {
402
        //
403
        // Set current time
404
        //   xx:xx:xx
405
        //
406
        str[0] = PACK(0x1b, '[', '1',';');
407
        str[1] = PACK('0','H',' ',' ');
408
        str[2] = PACK(' ','x','x',':');
409
        str[3] = PACK('x','x',' ',' ');
410
        //str[3]=PACK('x','x',':','x');
411
        str[4] = PACK(' ','\0','\0','\0');
412 27 dgisselq
 
413 29 dgisselq
        if (pos>0) {
414
                int ch = ((now >> 20)&0x0f)+'0';
415
                str[2] &= ~0x0ff0000;
416
                str[2] |= (ch<<16);
417 27 dgisselq
 
418 29 dgisselq
                if (pos > 1) {
419
                        int ch = ((now >> 16)&0x0f)+'0';
420
                        str[2] &= ~0x0ff00;
421
                        str[2] |= (ch<<8);
422 27 dgisselq
 
423 29 dgisselq
                if (pos > 2) {
424
                        int ch = ((now >> 12)&0x0f)+'0';
425
                        str[3] &= ~0xff000000;
426
                        str[3] |= (ch<<24);
427 27 dgisselq
 
428 29 dgisselq
                if (pos > 3) {
429
                        int ch = ((now >> 8)&0x0f)+'0';
430
                        str[3] &= ~0x0ff0000;
431
                        str[3] |= (ch<<16);
432 27 dgisselq
 
433 29 dgisselq
                if (pos > 4) {
434
                        int ch = ((now >> 4)&0x0f)+'0';
435
                        str[3] &= ~0x0ff00;
436
                        str[3] |= ':'<<8;
437
                        str[3] &= ~0x0ff;
438
                        str[3] |= (ch);
439 27 dgisselq
 
440 29 dgisselq
                        if (pos > 5)
441
                                ch = (now&0x0f)+'0';
442
                        else
443
                                ch = 'x';
444
                        str[4] &= ~0x0ff000000;
445
                        str[4] |= (ch<<24);
446
        }}}}}
447
}
448
 
449
void    show_time_menu(unsigned when, int posn) {
450
        char    dmsg[10];
451
        dmsg[0] = PACK(0x1b,'[','j','S');
452
        dmsg[1] = PACK('e','t',' ','c');
453
        dmsg[2] = PACK('u','r','r','e');
454
        dmsg[3] = PACK('n','t',' ','t');
455
        dmsg[4] = PACK('i','m','e',':');
456
        entered_menu_str(&dmsg[5], when, posn);
457
        write(FILENO_STDOUT, dmsg, 9);
458
}
459
 
460
void    show_dawn_menu(unsigned when, int posn) {
461
        char    dmsg[10];
462
        dmsg[0] = PACK(0x1b,'[','j','S');
463
        dmsg[1] = PACK('e','t',' ','s');
464
        dmsg[2] = PACK('u','n','r','i');
465
        dmsg[3] = PACK('s','e',':','\0');
466
        entered_menu_str(&dmsg[4], when, posn);
467
        write(FILENO_STDOUT, dmsg, 8);
468
}
469
 
470
void    show_dusk_menu(unsigned when, int posn) {
471
        char    dmsg[10];
472
        dmsg[0] = PACK(0x1b,'[','j','S');
473
        dmsg[1] = PACK('e','t',' ','s');
474
        dmsg[2] = PACK('u','n','s','e');
475
        dmsg[3] = PACK('t',':','\0','\0');
476
        entered_menu_str(&dmsg[4], when, posn);
477
        write(FILENO_STDOUT, dmsg, 8);
478
}
479
 
480
int     menu_readkey(void) {
481
        int     key;
482
        wait(0,3);
483
        key = keypadread();
484
        keypad_wait_for_release();
485
        clear(INT_KEYPAD);
486
        return key;
487
}
488
 
489
void    time_menu(void) {
490
        int     timeout = 60;
491
        unsigned newclock = 0;
492
        for(int p=0; p<6; p++) {
493
                int     key, event;
494
                show_time_menu(newclock, p);
495
                do {
496
                        event = wait(SWINT_PPS|INT_KEYPAD,-1);
497
                        if (event&SWINT_PPS) {
498
                                timeout--;
499
                                if (timeout == 0)
500
                                        return;
501
                        } if (event&INT_KEYPAD) {
502
                                timeout = 60;
503
                                key = menu_readkey();
504
                                if ((key >= 0)&&(key < 10)) {
505
                                        int     sh;
506
                                        sh = (5-p)*4;
507
                                        newclock &= ~(0x0f<<sh);
508
                                        newclock |= (key<<sh);
509
                                } else if (key == 12) {
510
                                        if (p>=0)
511
                                                p--;
512
                                } else {
513
                                        if (p > 4)
514
                                                break;
515
                                        else
516
                                                return;
517
                                }
518
                        }
519
                } while(0==(event&INT_KEYPAD));
520
        }
521
 
522 39 dgisselq
        // Here's the trick here: without semaphores, we can't prevent a 
523
        // race condition on the clock.  It may be that the clock simulator
524
        // has read the clock value and is in the process of updating it, only
525
        // to have our task swapped in.  The risk here is that the RTC simulator
526
        // will write the updated value after we update our value here.  If it
527
        // does that, it will then set the SWINT_PPS interrupt.  So let's clear
528
        // this interrupt and then set our clock.  If the interrupt then
529
        // takes place in short order, we'll set the clock again.  That way,
530
        // if the RTC device was in the process of setting the clock, and then
531
        // sets it, we can adjust it again.
532
        //
533
        // Of course ... this won't work if it takes the clock longer than 
534
        // a millisecond to finish setting the clock ... but this is such a
535
        // rare race condition, and the consequences so minor, that this will
536
        // probably continue to work for now.
537 29 dgisselq
        clear(SWINT_PPS);
538
        rtcclock = newclock;
539
        if (wait(SWINT_PPS, 1))
540
                rtcclock = newclock;
541
}
542
 
543
void    dawn_menu(void) {
544
        int     timeout = 60;
545
        unsigned newdawn = 0;
546
        for(int p=0; p<6; p++) {
547
                int     key, event;
548
                show_dawn_menu(newdawn, p);
549
                do {
550
                        event = wait(SWINT_PPS|INT_KEYPAD,-1);
551
                        if (event&SWINT_PPS) {
552
                                timeout--;
553
                                if (timeout == 0)
554
                                        return;
555
                        } if (event&INT_KEYPAD) {
556
                                timeout = 60;
557
                                key = menu_readkey();
558
                                if ((key >= 0)&&(key < 10)) {
559
                                        int     sh = (5-p)*4;
560
                                        newdawn &= ~(0x0f<<sh);
561
                                        newdawn |= key<<sh;
562
                                } else if (key == 12) {
563
                                        if (p>=0)
564
                                                p--;
565
                                } else {
566
                                        if (p > 4)
567
                                                break;
568
                                        else
569
                                                return;
570
                                }
571
                        }
572
                } while(0 == (event&INT_KEYPAD));
573
        } dawn = newdawn;
574
}
575
 
576
void    dusk_menu(void) {
577
        int     timeout = 60;
578
        unsigned newdusk = 0;
579
        for(int p=0; p<6; p++) {
580
                int     key, event;
581
                show_dusk_menu(newdusk, p);
582
                do {
583
                        event = wait(SWINT_PPS|INT_KEYPAD,-1);
584
                        if (event&SWINT_PPS) {
585
                                timeout--;
586
                                if (timeout == 0)
587
                                        return;
588
                        } if (event&INT_KEYPAD) {
589
                                key = menu_readkey();
590
                                if ((key >= 0)&&(key < 10)) {
591
                                        int     sh = (5-p)*4;
592
                                        newdusk &= ~(0x0f<<sh);
593
                                        newdusk |= key<<sh;
594
                                } else if (key == 12) {
595
                                        if (p>=0)
596
                                                p--;
597
                                } else {
598
                                        if (p > 4)
599
                                                break;
600
                                        else
601
                                                return;
602
                                }
603
                        }
604
                } while(0 == (event&INT_KEYPAD));
605
        } dusk = newdusk;
606
}
607
 
608
void    unknown_menu(void) {
609
        //      0123456789ABCDEF
610
        //      Unknown Cmd Key
611
        //      A/Tm B/Dwn C/Dsk
612
        char    dmsg[11];
613
        dmsg[0] = PACK(0x1b,'[','j','U');
614
        dmsg[1] = PACK('n','k','n','o');
615
        dmsg[2] = PACK('w','n',' ','C');
616
        dmsg[3] = PACK('m','d',' ','K');
617
        dmsg[4] = PACK('e','y','\0','\0');
618
        dmsg[5] = PACK(0x1b,'[','1',';');
619
        dmsg[6] = PACK('0','H','A','/');
620
        dmsg[7] = PACK('T','m',' ','B');
621
        dmsg[8] = PACK('/','D','w','n');
622
        dmsg[9] = PACK(' ','C','/','D');
623
        dmsg[10] = PACK('s','k',0,0);
624
        write(FILENO_STDOUT, dmsg, 11);
625
}
626
void    menu_task(void) {
627
        // Controls LED 0x08
628
 
629
        // Start by initializing the display to GT Gisselquist\nTechnology
630
        // write(KFD_STDOUT, disp_build_backslash,sizeof(disp_build_backslash));
631
        // write(KFD_STDOUT, disp_build_gtlogo, sizeof(disp_build_gtlogo));
632
        // write(KFD_STDOUT, disp_reset_data, sizeof(disp_reset_data));
633
        // write(KFD_STDOUT, disp_gtech_data, sizeof(disp_gtech_data));
634 39 dgisselq
        // IOSPACE      *sys = (IOSPACE *)IOADDR;
635 29 dgisselq
        unsigned belltime = 0, when;
636
 
637
 
638 39 dgisselq
        when = (volatile unsigned)rtcclock;
639 29 dgisselq
        while(1) {
640
                int     event;
641
                // Initial state: doorbell is not ringing.  In this state, we
642
                // can wait forever for an event
643
                event = wait(SWINT_DOORBELL|SWINT_PPS|INT_KEYPAD,-1);
644
                if (event & SWINT_DOORBELL) {
645
                        showbell(when);
646
                        belltime = time();
647
                } else if (event & SWINT_PPS) {
648
                        unsigned        now = time();
649
                        if ((now-belltime)<HALF_HOUR_S)
650
                                showbell(when);
651
                        else {
652 39 dgisselq
                                when = (volatile unsigned)rtcclock;
653 29 dgisselq
                                shownow(when);
654
                        }
655
                }
656
 
657
                if (event & INT_KEYPAD) {
658
                        int     key;
659
                        key = menu_readkey();
660
                        switch(key) {
661
                                case 10: time_menu();
662 39 dgisselq
                                        when = (volatile unsigned)rtcclock;
663 29 dgisselq
                                        break;
664
                                case 11: dawn_menu(); break;
665
                                case 12: dusk_menu(); break;
666
                                default:
667
                                        unknown_menu();
668
                                        wait(0,3000);
669
                        } clear(INT_KEYPAD);
670
                }
671
        }
672
}
673
#endif
674
 

powered by: WebSVN 2.1.0

© copyright 1999-2022 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.