home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Gold Fish 1
/
GoldFishApril1994_CD1.img
/
d1xx
/
d128
/
ledclock
/
leds.c
< prev
next >
Wrap
C/C++ Source or Header
|
1988-01-02
|
11KB
|
347 lines
/* LedClock (C)1987 Ali T. Ozer. A clock program for interlaced screens. */
#include <exec/types.h>
#include <functions.h>
#include <intuition/intuition.h>
#include <exec/devices.h>
#include <devices/timer.h>
#include <graphics/gfxmacros.h>
/* LedClock is freely distributable and NOT for sale.
**
** Author: Ali T. Ozer, ARPA: ali@score.stanford.edu,
** REAL: Box 7703, Stanford, CA 94309
**
** A clock program for interlaced screens. This one uses
** numbers that resemble the numbers used in 7-segment LED and LCD
** clock displays. Various options are provided as compile time "#define"s:
**
** TWENTYFOURHOUR 0 or 1, determines if the clock is 24-hour or not
** WINDOWXLOC starting X location for the window in the WB screen
** WINDOWYLOC starting Y location for the window in the WB screen
** FANCYPANIC 0 or 1, determines if a error message box is shown in
** case the clock can't run...
**
** LedClock works best with interlaced screens --- It will look ugly on a
** "normal" WorkBench screen. (It will probably look fine on a lo-res, non
** interlaced screen, except it will be too big, way too big.)
**
** LedClock can be compiled by Manx 3.40a. Use the "+c" and "+d" switches
** while linking to assure that the static images go into CHIP ram:
**
** cc ledclock.c
** ln +cd ledclock.o -lc
** run ledclock
**
** During linking you'll get warnings about _cli_parse and _wb_parse being
** redefined; you can safely ignore these messages.
**
** Various corners have been cut from this program to make the executable small.
** With Manx 3.40a, the executable is somewhere around 3.1 Kbytes. One can
** probably achieve half that size in assembly.
**
** Programmers might wish to fool around with the code to customize the
** clock. It's amazing how many parameters one can think of if one tries
** to make a general program... So, rather than trying to provide zillions
** of command line arguments, I took the easy way out and just threw out
** all generality... If you wish to create your customized clocks from
** this code, feel free to do so --- but please keep my original copyright
** notice (in the screen title bar) intact, along with any additional
** copyright notices you might add.
*/
/* The next few define's can be changed for different runtime parameters... */
#define TWENTYFOURHOUR 1
#define FANCYPANIC 0
#define WINDOWXLOC 20
#define WINDOWYLOC 14
#define COPYRIGHT "LedClock 1.0 (C)1987 Ali T. Ozer"
#if FANCYPANIC
#define Panic(arg) WarnUser(arg)
#else
#define Panic(arg) CloseThings(1)
#endif
#define DIGITMAXX 18
#define DIGITMAXY 32
#define WINDOWX 0
#define WINDOWY 9
#define DIGIT1X (WINDOWX + 3)
#define DIGIT2X (DIGIT1X + DIGITMAXX + 3)
#define DIGIT3X (DIGIT2X + DIGITMAXX + 10)
#define DIGIT4X (DIGIT3X + DIGITMAXX + 3)
#define DIGITY (WINDOWY + 3)
#define WINDOWWIDTH (DIGIT4X + DIGITMAXX + 3)
#define WINDOWHEIGHT (DIGITY + DIGITMAXY + 3)
#define COLONX (DIGIT3X - 6)
#define COLONY (DIGITY + 11)
/* The "leds" (the segments making up the digits) are named in the standard
** (clockwise) fashion, with a = top led, b = right top, ... f = left top, and
** g = middle.
**
** The following describes the vertical leds ("b", "c", "e", and "f")
*/
USHORT vled [] = {
0xdfff, 0x8fff, 0x8fff, 0x8fff, 0x8fff, 0x8fff, 0x8fff,
0x1fff, 0x1fff, 0x1fff, 0x1fff, 0x1fff, 0x1fff, 0xbfff
};
/* The following is the bitmap description of leds a and d.
*/
USHORT hled [] = {0x807f, 0x003f, 0x807f};
/* The following is the bitmap description of the middle ("g") led.
*/
USHORT mled [] = {0x80ff, 0x007f, 0x80ff};
/* The following describes the bitmap for the colon and the image.
*/
USHORT colondata [] = {
0x8fff, 0x8fff, 0x8fff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0x1fff, 0x1fff, 0x1fff
};
struct Image colon = { 0, 0, 4, 11, 1, colondata, 1, 0, NULL};
/* The following describes the Image structures for all 7 leds, "a".."g"
*/
struct Image leds [] = {
{ 6, 0, 10, 3, 1, &hled[0], 1, 0, NULL},
{15, 2, 4, 14, 1, &vled[0], 1, 0, NULL},
{13, 17, 4, 14, 1, &vled[0], 1, 0, NULL},
{ 3, 30, 10, 3, 1, &hled[0], 1, 0, NULL},
{ 0, 17, 4, 14, 1, &vled[0], 1, 0, NULL},
{ 2, 2, 4, 14, 1, &vled[0], 1, 0, NULL},
{ 5, 15, 9, 3, 1, &mled[0], 1, 0, NULL}
};
/* In the following each byte determines what leds are lit for the
** corresponding digit. The bits are ordered "xgfedcba" and a 1 means the
** led is lit.
*/
UBYTE lled [] = {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F};
struct Window *MyWin;
struct RastPort *MyRP;
struct Library *IntuitionBase;
struct Library *GfxBase;
struct timerequest MyTR;
unsigned long WindowSig, TimerSig;
int curminutes;
/* Draw digit puts a 7-segment digit at the specified location. If digit is
** negative, then the area is erased but nothing is drawn.
*/
DrawDigit (rp, digit, xloc, yloc)
struct RastPort *rp;
int digit, xloc, yloc;
{
register int ledmask, ledcnt = 0;
/* First erase it */
RectFill (rp, (long)xloc, (long)yloc,
(long)(xloc + DIGITMAXX), (long)(yloc + DIGITMAXY));
if (digit >= 0) {
ledmask = lled[digit];
while (ledcnt != 7) {
if (ledmask & 1) DrawImage (rp, &leds[ledcnt], (long)xloc, (long)yloc);
ledcnt++; ledmask >>= 1;
}
}
}
/* OpenTimer will open the timer device and also do all the initialization
** necessary to send timer requests...
*/
OpenTimer (tr)
struct timerequest *tr;
{
struct MsgPort *timerport;
while ((timerport = CreatePort (NULL, 0L)) == NULL) Panic ("No port");
OpenDevice (TIMERNAME, UNIT_VBLANK, tr, 0L);
tr->tr_node.io_Message.mn_ReplyPort = timerport;
tr->tr_node.io_Command = TR_ADDREQUEST;
}
/* OpenThings opens the Amiga libraries, the window. and the timer.
** If something goes wrong, a requester will pop up to warn the user.
** (If FANCYPANIC is defined as zero, then no requester pops up --- the
** program just quits.)
*/
OpenThings ()
{
static struct NewWindow MyWinInfo =
{ WINDOWXLOC, WINDOWYLOC, WINDOWWIDTH, WINDOWHEIGHT, /* Lft,Top,Wd,Hgt */
-1,-1, /* Detail pen, Block pen (-1 = use screens) */
CLOSEWINDOW, /* IDCMPflags */
SMART_REFRESH | WINDOWDEPTH | WINDOWDRAG | WINDOWCLOSE | NOCAREREFRESH,
NULL, NULL, NULL, /* FirstGadget, Menu Checkmark, Title */
NULL, NULL, /* Screen, Bitmap */
0, 0, 0, 0, /* Min Width/Height Max Width/Height */
WBENCHSCREEN /* Type */
};
if (((IntuitionBase = OpenLibrary("intuition.library",0L)) == NULL) ||
((GfxBase = OpenLibrary("graphics.library",0L)) == NULL)) CloseThings (1);
while (!(MyWin = OpenWindow(&MyWinInfo))) Panic ("No window");
SetWindowTitles (MyWin, NULL, COPYRIGHT);
MyRP = MyWin->RPort;
WindowSig = 1L << MyWin->UserPort->mp_SigBit;
SetOPen (MyRP, 1L);
SetAPen (MyRP, 1L);
OpenTimer(&MyTR);
TimerSig = 1L << MyTR.tr_node.io_Message.mn_ReplyPort->mp_SigBit;
}
/* SendTimerRequest sends a timer request for the indicated amount of seconds.
** Assumes the timer request block pointed to by tr has already been properly
** setup --- including the io_Command field.
*/
SendTimerRequest (tr, seconds)
struct timerequest *tr;
unsigned long seconds;
{
tr->tr_time.tv_micro = 0L;
tr->tr_time.tv_secs = seconds;
SendIO (tr);
}
#if FANCYPANIC
/* WarnUser is called when something goes wrong during initialization.
** WarnUser assumes Intuition is opened! (Now if that's not the case,
** then you're in trouble...)
*/
WarnUser (reason)
UBYTE *reason;
{
static struct IntuiText postxt = {3,1,COMPLEMENT,4,4,NULL,(UBYTE *)"Retry",NULL};
static struct IntuiText negtxt = {3,1,COMPLEMENT,4,4,NULL,(UBYTE *)"Sigh",NULL};
static struct IntuiText bodytxt = {3,1,COMPLEMENT,4,6,NULL,NULL,NULL};
bodytxt.IText = reason;
if (AutoRequest (NULL,&bodytxt,&postxt,&negtxt,0L,0L,300L,60L) == FALSE)
CloseThings (1);
}
#endif
/* CloseTimer closes the timer pointed to by tr. If no reply port is present,
** then CloseTimer assumes the timer was never opened.
*/
CloseTimer (tr)
struct timerequest *tr;
{
struct MsgPort *msgp;
if (msgp = tr->tr_node.io_Message.mn_ReplyPort) {
DeletePort (msgp);
CloseDevice (tr);
}
}
/* CloseThings releases all the resources obtained by the program.
*/
CloseThings(error_code)
int error_code;
{
CloseTimer(&MyTR);
if (MyWin) CloseWindow(MyWin);
if (GfxBase) CloseLibrary(GfxBase);
if (IntuitionBase) CloseLibrary(IntuitionBase);
exit (error_code);
}
static int ht = -1, ho = -1, mt = -1, mo = -1;
/* WriteTime writes out the new time.
*/
WriteTime (minutes)
int minutes;
{
int hours, htens, hones, mtens, mones;
#if TWENTYFOURHOUR
hours = minutes / 60;
#else
hours = (minutes / 60 + 11) % 12 + 1;
#endif
/* AM if minutes < 720, but we don't worry about this... */
if ((htens = hours / 10) != ht)
DrawDigit (MyRP, ((ht = htens) ? ht : -1), DIGIT1X, DIGITY);
if ((hones = hours % 10) != ho)
DrawDigit (MyRP, ho = hones, DIGIT2X, DIGITY);
if ((mtens = (minutes % 60) / 10) != mt)
DrawDigit (MyRP, mt = mtens, DIGIT3X, DIGITY);
if ((mones = (minutes % 10)) != mo)
DrawDigit (MyRP, mo = mones, DIGIT4X, DIGITY);
}
/* ShowTheTime reads the time, updates the display, and sends a new timer
** request.
*/
ShowTheTime ()
{
long timevec[3];
DateStamp (&timevec[0]);
curminutes = (int)(timevec[1]);
WriteTime (curminutes);
/* Timer request for the next top of minute */
SendTimerRequest (&MyTR, 60L - (long)(timevec[2] / 50L));
}
main ()
{
struct Task *me;
OpenThings ();
/* Bump the priority up to 5. Not too serious, as under normal conditions
** this program will wake up only every 60 seconds.
*/
if (me = FindTask (NULL)) SetTaskPri (me, 5L);
/* Clear the window and draw in the ":".
*/
RectFill (MyRP, (long)WINDOWX, (long)WINDOWY,
WINDOWWIDTH-1L, WINDOWHEIGHT-1L);
DrawImage (MyRP, &colon, (long)COLONX, (long)COLONY);
/* Now sit down, relax, and wait for either an IDCMP or a timer event...
*/
while (1) {
ShowTheTime ();
if (Wait (WindowSig | TimerSig) & TimerSig)
(void) GetMsg (MyTR.tr_node.io_Message.mn_ReplyPort);
else {
AbortIO (&MyTR); /* Don't even get the message, assume it's CLOSEWINDOW */
CloseThings (0);
}
}
}
/* Including the following two lines prevents the linker from bringing in
** the two functions _wb_parse and _cli_parse called by the initialization
** code in _main. Reduces code size by about 900 bytes for Manx 3.40a.
*/
void _wb_parse () {}
void _cli_parse () {}