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

Subversion Repositories s6soc

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

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

powered by: WebSVN 2.1.0

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