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

Subversion Repositories s6soc

[/] [s6soc/] [trunk/] [sw/] [dev/] [doorbell2.c] - Diff between revs 15 and 45

Go to most recent revision | Only display areas with differences | Details | Blame | View Log

Rev 15 Rev 45
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
//
//
// Filename:    doorbell2.c
// Filename:    doorbell2.c
//
//
// Project:     CMod S6 System on a Chip, ZipCPU demonstration project
// Project:     CMod S6 System on a Chip, ZipCPU demonstration project
//
//
// Purpose:     A modification to the original doorbell.c program.
// Purpose:     A modification to the original doorbell.c program that played
//              seconds.  Listening to that test is ... getting old.
//              a doorbell sound every ten seconds.  Listening to that test is
 
//      ... getting old.
//
//
//      Let's let this one do the following:
//      Let's let this one do the following:
//              1. Display the time on the display (it will be impossible to
//              1. Display the time on the display (it will be impossible to
//                      change the time, sadly, but we can at least display it.)
//                      change the time, sadly, but we can at least display it.)
//              2. On button press ...
//              2. On button press ...
//                      - Play the doorbell sound
//                      - Play the doorbell sound
//                      - Display "Doorbell!\n" on the Display, clearing the
//                      - Display "Doorbell!\n" on the Display, clearing the
//                              time
//                              time
//                      - Send "Doorbell\n"  to the UART, and then keeping the
//                      - Send "Doorbell\n"  to the UART, and then keeping the
//                              UART silent for 30 seconds.
//                              UART silent for 30 seconds.
//              4. Send the time to the UART as well, but only once a minute.
//              4. Send the time to the UART as well, but only once a minute.
//                      (and that if the Doorbell hasn't been rung in the last
//                      (and that if the Doorbell hasn't been rung in the last
//                      30 seconds ...)
//                      30 seconds ...)
//
//
// Creator:     Dan Gisselquist, Ph.D.
// Creator:     Dan Gisselquist, Ph.D.
//              Gisselquist Technology, LLC
//              Gisselquist Technology, LLC
//
//
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
//
//
// Copyright (C) 2015-2016, Gisselquist Technology, LLC
// Copyright (C) 2015-2017, Gisselquist Technology, LLC
//
//
// This program is free software (firmware): you can redistribute it and/or
// This program is free software (firmware): you can redistribute it and/or
// modify it under the terms of  the GNU General Public License as published
// modify it under the terms of  the GNU General Public License as published
// by the Free Software Foundation, either version 3 of the License, or (at
// by the Free Software Foundation, either version 3 of the License, or (at
// your option) any later version.
// your option) any later version.
//
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
// for more details.
// for more details.
//
//
// You should have received a copy of the GNU General Public License along
// You should have received a copy of the GNU General Public License along
// with this program.  (It's in the $(ROOT)/doc directory, run make with no
// with this program.  (It's in the $(ROOT)/doc directory, run make with no
// target there if the PDF file isn't present.)  If not, see
// target there if the PDF file isn't present.)  If not, see
// <http://www.gnu.org/licenses/> for a copy.
// <http://www.gnu.org/licenses/> for a copy.
//
//
// License:     GPL, v3, as defined and found on www.gnu.org,
// License:     GPL, v3, as defined and found on www.gnu.org,
//              http://www.gnu.org/licenses/gpl.html
//              http://www.gnu.org/licenses/gpl.html
//
//
//
//
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
//
//
//
//
#include "asmstartup.h"
#include "asmstartup.h"
#include "board.h"
#include "board.h"
#include "rtcsim.h"
#include "rtcsim.h"
#include "display.h"
#include "display.h"
 
#include "string.h"
 
#include "txfns.h"
 
 
#include "samples.c"
#include "samples.c"
 
 
void    zip_halt(void);
void    zip_halt(void);
 
 
void    build_dpymsg(char *msg, unsigned clkval);
void    build_dpymsg(char *msg, unsigned clkval);
void    build_uartmsg(char *msg, unsigned clkval);
void    build_uartmsg(char *msg, unsigned clkval);
void    showval(int val);
void    showval(int val);
void    txval(int val);
 
 
#define CLEAR_WATCHDOG  _sys->io_watchdog = 0
 
#define TOUCH_WATCHDOG  _sys->io_watchdog = 500000
 
 
void entry(void) {
void entry(void) {
        register IOSPACE        *sys = (IOSPACE *)0x0100;
        register volatile IOSPACE *const sys = _sys;
        char    dpymsg[16], *dpyptr;
        char    dpymsg[64], *dpyptr;
        char    uartmsg[40], *uartptr;
        char    uartmsg[160], *uartptr;
        int     newmsgtime = 0, leastmsgtime = -1, lstmsgtime = 0;
        int     newmsgtime = 0, leastmsgtime = -1, lstmsgtime = 0;
 
 
 
        CLEAR_WATCHDOG;
 
 
 
        txstr("\r\nREBOOT!\r\n");
 
        txstr("Scope Control = "); txval(_scope->s_ctrl);
 
        if (_scope->s_ctrl & WBSCOPE_STOPPED) {
 
                int     ln = WBSCOPE_LENGTH(_scope->s_ctrl);
 
                for(int i=0; i<ln; i++)
 
                        txval(_scope->s_data);
 
                txval((int)_sys->io_buserr);
 
                txstr("\r\n\r\nEndScope\r\n");
 
        } else {
 
                txstr("\r\n");
 
                _scope->s_ctrl = 20;
 
        }
 
 
        dpymsg[0] = 0;
        dpymsg[0] = 0;
        dpyptr = dpymsg;
        dpyptr = dpymsg;
 
 
        uartmsg[0] = 0;
        uartmsg[0] = 0;
        build_uartmsg(uartmsg, 0);
        build_uartmsg(uartmsg, 0);
        uartptr = uartmsg;
        uartptr = uartmsg;
 
 
        sys->io_timb = 0;
        sys->io_watchdog = 0;
        sys->io_pic = 0x07fffffff; // Acknowledge and turn off all interrupts
        sys->io_pic = INT_CLEARPIC; // Acknowledge and turn off all interrupts
 
 
        sys->io_spio = 0x0f4;
        sys->io_spio = 0x0f4;
        newmsgtime = sys->io_tima;
        newmsgtime = sys->io_timer;
        leastmsgtime = -1;
        leastmsgtime = -1;
        lstmsgtime = newmsgtime;
        lstmsgtime = newmsgtime;
        while(1) {
        while(1) {
                int     seconds, pic;
                int     seconds, pic;
                const int       *sptr;
                const short     *sptr;
 
 
                // LED's off ... nothing to report
                // LED's off ... nothing to report
                sys->io_spio = 0x0f0;
                sys->io_spio = 0x0f0;
 
 
                // Turn the audio off (initially)
                // Turn the audio off (initially)
                sys->io_pwm_audio = 0x0018000;
                sys->io_pwm_audio = 0x0018000;
 
 
                // Set for one ticks per second, 80M clocks per tick
                // Set for one ticks per second, 80M clocks per tick
                sys->io_tima = TM_ONE_SECOND | TM_REPEAT;
                sys->io_timer = TM_ONE_SECOND | TM_REPEAT;
 
 
                // We start by waiting for a doorbell
                // We start by waiting for a doorbell
                while(((pic=sys->io_pic) & INT_BUTTON)==0) {
                while(((pic=sys->io_pic) & INT_BUTTON)==0) {
                        if (uartmsg[10] == 0) {
                        TOUCH_WATCHDOG;
                                sys->io_spio = 0x0fe;
 
                                zip_halt();
                        if (pic & INT_TIMER) {// top of second
                        }
                                sys->io_pic = INT_TIMER;
                        if (pic & INT_TIMA) {// top of second
 
                                sys->io_pic = INT_TIMA;
 
                                rtcclock = rtcnext(rtcclock);
                                rtcclock = rtcnext(rtcclock);
 
 
                                // Turn all LED off (again)
                                // Turn all LED off (again)
                                sys->io_spio = 0x0f0;
                                sys->io_spio = 0x0f0;
                                if (*dpyptr == '\0') {
                                if (*dpyptr == '\0') {
                                        // Build a message for the display
                                        // Build a message for the display
                                        build_dpymsg(dpymsg, rtcclock);
                                        build_dpymsg(dpymsg, rtcclock);
                                        dpyptr = dpymsg;
                                        dpyptr = dpymsg;
                                }if(((rtcclock & 0x0ff)==0)&&(*uartptr=='\0')){
                                }if(((rtcclock & 0x0ff)==0)&&(*uartptr=='\0')){
                                        build_uartmsg(uartmsg, rtcclock);
                                        build_uartmsg(uartmsg, rtcclock);
                                        uartptr = uartmsg;
                                        uartptr = uartmsg;
 
 
                                        // Turn one LED on--top of minute
                                        // Turn one LED on--top of minute
                                        sys->io_spio = 0x0f1;
                                        sys->io_spio = 0x0f1;
                                        newmsgtime = sys->io_tima;
                                        newmsgtime = sys->io_timer;
                                        lstmsgtime = -1;
                                        lstmsgtime = -1;
                                        leastmsgtime = -1;
                                        leastmsgtime = -1;
                                }
                                }
                        }
                        }
                        /*
 
                        if (uartmsg[10] == 0) {
 
                                sys->io_spio = 0x0fc;
 
                                zip_halt();
 
                        }
 
                        */
 
                        if (*uartptr) {
                        if (*uartptr) {
                                if (pic & INT_UARTTX) {
                                if (pic & INT_UARTTX) {
                                        sys->io_uart = *uartptr++;
                                        sys->io_uart = *uartptr++;
                                        sys->io_spio = 0x22;
                                        sys->io_spio = 0x22;
                                        sys->io_pic = INT_UARTTX;
                                        sys->io_pic = INT_UARTTX;
                                        if (uartptr > &uartmsg[13]) {
 
                                                sys->io_spio = 0x0fd;
 
                                                zip_halt();
 
                                        }
 
 
 
                                        if (lstmsgtime != -1) {
                                        if (lstmsgtime != -1) {
                                                int tmp;
                                                int tmp;
                                                tmp = (lstmsgtime-sys->io_tima);
                                                tmp = (lstmsgtime-sys->io_timer);
                                                if ((leastmsgtime<0)||(tmp<leastmsgtime))
                                                if ((leastmsgtime<0)||(tmp<leastmsgtime))
                                                        leastmsgtime = tmp;
                                                        leastmsgtime = tmp;
                                        } lstmsgtime = sys->io_tima;
                                        } lstmsgtime = sys->io_timer;
                                }
                                }
                        } else {
                        } else {
                                sys->io_spio = 0x20;
                                sys->io_spio = 0x20;
                                /*
 
                                if (newmsgtime != 0) {
 
                                        int thistime = sys->io_tima;
 
                                        thistime = newmsgtime - thistime;
 
                                        showval(thistime);
 
                                        txval(thistime);
 
                                        txval(leastmsgtime);
 
                                        txval(lstmsgtime);
 
                                        zip_halt();
 
                                        newmsgtime = 0;
 
                                }
 
                                for(int i=0; i<12; i++)
 
                                        if (uartmsg[i] == 0) {
 
                                                sys->io_spio = i+0xf0;
 
                                                zip_halt();
 
                                        }
 
                                */
 
                        }
                        }
                        if (*dpyptr) {
                        if (*dpyptr) {
                                // This will take a long time.  It should be an
                                // This will take a long time.  It should be an
                                // interruptable task ... but, sigh, we're not
                                // interruptable task ... but, sigh, we're not
                                // there yet.
                                // there yet.
                                dispchar(*dpyptr++);
                                dispchar(*dpyptr++);
                                sys->io_spio = 0x44;
                                sys->io_spio = 0x44;
                        } else {
                        } else {
                                sys->io_spio = 0x40;
                                sys->io_spio = 0x40;
                        } // sys->io_pic = (pic & (INT_TIMA|INT_UARTTX));
                        } // sys->io_pic = (pic & (INT_TIMER|INT_UARTTX));
                }
                }
 
 
 
                TOUCH_WATCHDOG;
                // DOORBELL!!!!!!
                // DOORBELL!!!!!!
                // Set the Display message
                // Set the Display message
                dpymsg[0] = (0x1b<<24)|('['<<16)|('j'<<8)|'D';
                strcpy(dpymsg, "a[jDoorbell!");
                dpymsg[1] = ('o'<<24)|('o'<<16)|('r'<<8)|'b';
                dpymsg[0] = 0x1b;
                dpymsg[2] = ('e'<<24)|('l'<<16)|('l'<<8)|'!';
 
                dpymsg[3] = 0;
 
                dpyptr = dpymsg;
                dpyptr = dpymsg;
                // And the UART message / 18 characters
                // And the UART message / 18 characters
                uartptr = uartmsg;
                uartptr = uartmsg;
                *uartptr++ = '\r'; *uartptr++ = '\n';
                strcat(uartptr, "\r\nDoorbell!\r\n\r\n");
                *uartptr++ = 'D';
 
                *uartptr++ = 'o';
 
                *uartptr++ = 'o';
 
                *uartptr++ = 'r';
 
                *uartptr++ = 'b';
 
                *uartptr++ = 'e';
 
                *uartptr++ = 'l';
 
                *uartptr++ = 'l';
 
                *uartptr++ = '!';
 
                *uartptr++ = '\r'; *uartptr++ = '\n';
 
                *uartptr++ = '\r'; *uartptr++ = '\n';
 
                *uartptr++ = '\0';
 
                uartptr = uartmsg;
                uartptr = uartmsg;
 
 
 
 
                seconds = 0;
                seconds = 0;
                sys->io_spio = 0x0ff; // All LED's on: we got one!
                sys->io_spio = 0x0ff; // All LED's on: we got one!
                sptr = sound_data;
                sptr = sound_data;
                sys->io_pwm_audio = 0x0310000; // Turn on the audio
                sys->io_pwm_audio = 0x0310000; // Turn on the audio
                while(sptr < &sound_data[NSAMPLE_WORDS]) {
                while(sptr < &sound_data[NSAMPLE_WORDS]) {
                        do {
                        do {
 
                                TOUCH_WATCHDOG;
                                pic = sys->io_pic;
                                pic = sys->io_pic;
                                if (pic & INT_TIMA) {
                                if (pic & INT_TIMER) {
                                        sys->io_pic = INT_TIMA;
                                        sys->io_pic = INT_TIMER;
                                        seconds++;
                                        seconds++;
                                        rtcclock = rtcnext(rtcclock);
                                        rtcclock = rtcnext(rtcclock);
                                } if ((pic & INT_UARTTX)&&(*uartptr)) {
                                } if ((pic & INT_UARTTX)&&(*uartptr)) {
                                        sys->io_uart = *uartptr++;
                                        sys->io_uart = *uartptr++;
                                        sys->io_pic = INT_UARTTX;
                                        sys->io_pic = INT_UARTTX;
                                        sys->io_spio = 0x22;
                                        sys->io_spio = 0x22;
                                } else if (!*uartptr)
                                } else if (!*uartptr)
                                        sys->io_spio = 0x20;
                                        sys->io_spio = 0x20;
                                if (*dpyptr) {
                                if (*dpyptr) {
                                // This will take a long time.  It should be an
                                // This will take a long time.  It should be an
                                // interruptable task ... but, sigh, we're not
                                // interruptable task ... but, sigh, we're not
                                // there yet.
                                // there yet.
                                        dispchar(*dpyptr++);
                                        dispchar(*dpyptr++);
                                        sys->io_spio = 0x44;
                                        sys->io_spio = 0x45;
                                } else
                                } else
                                        sys->io_spio = 0x40;
                                        sys->io_spio = 0x40;
                        } while((pic & INT_AUDIO)==0);
                        } while((pic & INT_AUDIO)==0);
                        sys->io_pwm_audio = (*sptr >> 16)&0x0ffff;
                        sys->io_pwm_audio = (*sptr++) & 0x0ffff;
                        // Now, turn off the audio interrupt since it doesn't
                        // Now, turn off the audio interrupt since it doesn't
                        // reset itself ...
                        // reset itself ...
                        sys->io_pic = INT_AUDIO;
                        sys->io_pic = INT_AUDIO;
 
 
                        do {
 
                                pic = sys->io_pic;
 
 
 
                                if (pic & INT_TIMA) {
 
                                        sys->io_pic = INT_TIMA;
 
                                        seconds++;
 
                                        rtcclock = rtcnext(rtcclock);
 
                                } if ((pic & INT_UARTTX)&&(*uartptr)) {
 
                                        sys->io_uart = *uartptr++;
 
                                        sys->io_pic = INT_UARTTX;
 
                                        sys->io_spio = 0x22;
 
                                } else if (!*uartptr)
 
                                        sys->io_spio = 0x20;
 
                                if (*dpyptr) {
 
                                // This will take a long time.  It should be an
 
                                // interruptable task ... but, sigh, we're not
 
                                // there yet.
 
                                        dispchar(*dpyptr++);
 
                                        sys->io_spio = 0x44;
 
                                } else
 
                                        sys->io_spio = 0x40;
 
                        } while((pic & INT_AUDIO)==0);
 
                        sys->io_pwm_audio = (*sptr++) & 0x0ffff;
 
 
 
                        // and turn off the audio interrupt again ...
 
                        sys->io_pic = INT_AUDIO;
 
                } sys->io_pic = INT_BUTTON;
                } sys->io_pic = INT_BUTTON;
 
                sys->io_spio = 0x10;
 
 
 
                TOUCH_WATCHDOG;
                // Now we wait for the end of our 30 second window
                // Now we wait for the end of our 30 second window
                sys->io_spio = 0x0f8;
                sys->io_spio = 0x0f8;
                sys->io_pwm_audio = 0x018000; // Turn off the Audio device
                sys->io_pwm_audio = 0x018000; // Turn off the Audio device
                while(seconds < 30) {
                while(seconds < 30) {
 
                        TOUCH_WATCHDOG;
                        pic = sys->io_pic;
                        pic = sys->io_pic;
                        if (pic & INT_TIMA) {
                        if (pic & INT_TIMER) {
                                sys->io_pic = INT_TIMA;
                                sys->io_pic = INT_TIMER;
                                seconds++;
                                seconds++;
                                rtcclock = rtcnext(rtcclock);
                                rtcclock = rtcnext(rtcclock);
                        } if (pic & INT_BUTTON) {
                        } if (pic & INT_BUTTON) {
                                sys->io_pic = INT_BUTTON;
                                sys->io_pic = INT_BUTTON;
                                seconds = 0;
                                seconds = 0;
                        }
                        }
                } sys->io_pic = INT_BUTTON;
                } sys->io_pic = INT_BUTTON;
 
                TOUCH_WATCHDOG;
        }
        }
}
}
 
 
void    build_dpymsg(char *msg, unsigned clk) {
void    build_dpymsg(char *msg, unsigned clk) {
        *msg++ = (0x1b<<24)|('['<<16)|('j'<<8)|'C'; // Clear, and start 'C'
        msg[0] = 0x1b;
        *msg++ = ('l'<<24)|('o'<<16)|('c'<<8)|'k';
        strcpy(++msg, "[jClock : ");
        *msg = (' '<<24)|(':'<<16)|(' '<<8);
        msg += strlen(msg);
 
 
        if ((clk>>20)&0x0f)
        if ((clk>>20)&0x0f)
                *msg++ |= (((clk>>20)&0x0f)+'0');
                *msg++ |= (((clk>>20)&0x0f)+'0');
        else
        else
                *msg++ |= ' ';
                *msg++ |= ' ';
        *msg++ = ((((clk>>16)&0x0f)+'0')<<24)
        *msg++ = (((clk>>16)&0x0f)+'0');
                |(':'<<16)
        *msg++ = ':';
                |((((clk>>12)&0x0f)+'0')<< 8)   // Minutes
        *msg++ = (((clk>>12)&0x0f)+'0');
                |((((clk>> 8)&0x0f)+'0')    );
        *msg++ = (((clk>> 8)&0x0f)+'0');
        *msg++ = (':'<<24)
        *msg++ = ':';
                |((((clk>> 4)&0x0f)+'0')<<16)   // Seconds
        *msg++ = (((clk>> 4)&0x0f)+'0');
                |((((clk    )&0x0f)+'0')<< 8);
        *msg++ = (((clk    )&0x0f)+'0');
        *msg++ = 0;
 
        *msg++ = 0;
 
        *msg++ = 0;
 
        *msg++ = 0;
        *msg++ = 0;
}
}
 
 
void    build_uartmsg(char *msg, unsigned clk) {
void    build_uartmsg(char *msg, unsigned clk) {
        *msg++ = 'T';                   // 0
        strcpy(msg, "Time: ");
        *msg++ = 'i';                   // 1
        msg += strlen(msg);
        *msg++ = 'm';                   // 2
 
        *msg++ = 'e';                   // 3
 
        *msg++ = ':';                   // 4
 
        *msg++ = ' ';
 
        *msg++ = ((clk>>20)&0x03)+'0'; // Hrs
        *msg++ = ((clk>>20)&0x03)+'0'; // Hrs
        *msg++ = ((clk>>16)&0x0f)+'0';
        *msg++ = ((clk>>16)&0x0f)+'0';
        *msg++ = ':';
        *msg++ = ':';
        *msg++ = ((clk>>12)&0x0f)+'0'; // Mins
        *msg++ = ((clk>>12)&0x0f)+'0'; // Mins
        *msg++ = ((clk>> 8)&0x0f)+'0';
        *msg++ = ((clk>> 8)&0x0f)+'0';
        *msg++ = '\r';                  // 11
        *msg++ = '\r';                  // 11
        *msg++ = '\n';                  // 12
        *msg++ = '\n';                  // 12
        *msg++ = '\0';
        *msg++ = '\0';
        *msg++ = '\0';
        *msg++ = '\0';
}
}
 
 
void    showval(int val) {
void    showval(int val) {
        // Clear and home
        // Clear and home
        dispchar(0x1b);
        dispchar(0x1b);
        dispchar('[');
        dispchar('[');
        dispchar('j');
        dispchar('j');
        for(int i=28; i>=0; i-=4) {
        for(int i=28; i>=0; i-=4) {
                int ch = ((val>>i)&0x0f)+'0';
                int ch = ((val>>i)&0x0f)+'0';
                if (ch > '9')
                if (ch > '9')
                        ch = ch - '0'+'A'-10;
                        ch = ch - '0'+'A'-10;
                dispchar(ch);
                dispchar(ch);
        }
        }
}
}
 
 
void    txch(int val) {
 
        register IOSPACE        *sys = (IOSPACE *)0x0100;
 
 
 
        // To read whether or not the transmitter is ready, you must first
 
        // clear the interrupt bit.
 
        sys->io_pic = INT_UARTTX;
 
        for(int i=0; i<5000; i++)
 
                asm("noop");
 
        sys->io_pic = INT_UARTTX;
 
        // If the interrupt bit sets itself again immediately, the transmitter
 
        // is ready.  Otherwise, wait until the transmitter becomes ready.
 
        while((sys->io_pic&INT_UARTTX)==0)
 
                ;
 
        sys->io_uart = (val&0x0ff);
 
        // Give the transmitter a chance to finish, and then to create an
 
        // interrupt when done
 
        sys->io_pic = INT_UARTTX;
 
}
 
 
 
void    txval(int val) {
 
        txch('\r');
 
        txch('\n');
 
        txch('0');
 
        txch('x');
 
        for(int i=28; i>=0; i-=4) {
 
                int ch = ((val>>i)&0x0f)+'0';
 
                if (ch > '9')
 
                        ch = ch - '0'+'A'-10;
 
                txch(ch);
 
        }
 
}
 
 
 
// PPONP16P
 
// 00120O91
 
// 00120NM3
 
// 00120E91 = 1183377 ~= 91029 / char, at 0x208d 8333/baud, 83,330 per char
 
 
 
 No newline at end of file
 No newline at end of file

powered by: WebSVN 2.1.0

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