/* * * DISCLAIMER: * * This program is provided as a service to the programmer * community to demonstrate one or more features of the Amiga * personal computer. These code samples may be freely used * for commercial or noncommercial purposes. * * Commodore Electronics, Ltd ("Commodore") makes no * warranties, either expressed or implied, with respect * to the program described herein, its quality, performance, * merchantability, or fitness for any particular purpose. * This program is provided "as is" and the entire risk * as to its quality and performance is with the user. * Should the program prove defective following its * purchase, the user (and not the creator of the program, * Commodore, their distributors or their retailers) * assumes the entire cost of all necessary damages. In * no event will Commodore be liable for direct, indirect, * incidental or consequential damages resulting from any * defect in the program even if it has been advised of the * possibility of such damages. Some laws do not allow * the exclusion or limitation of implied warranties or * liabilities for incidental or consequential damages, * so the above limitation or exclusion may not apply. * */ /* SIMPLE TIMER EXAMPLE PROGRAM: * * Includes dynamic allocation of data structures needed to communicate * with the timer device as well as the actual device IO * * Author: Rob Peck, 12/1/85 */ #include "exec/types.h" #include "exec/nodes.h" #include "exec/lists.h" #include "exec/memory.h" #include "exec/interrupts.h" #include "exec/ports.h" #include "exec/libraries.h" #include "exec/io.h" #include "exec/tasks.h" #include "exec/execbase.h" #include "exec/devices.h" #include "devices/timer.h" long TimerBase; /* to get at the time comparison functions */ main() { LONG error; LONG days, minutes,seconds; struct timeval mytimeval; struct timeval oldtimeval; /* save what system thinks is * the time.... we'll advance it * temporarily */ printf("\ntimer test"); TimeDelay(2,0,0); printf("\nAfter 2 seconds delay"); TimeDelay(4,0,0); printf("\nAfter 4 seconds delay"); TimeDelay(0,500000,0); /* 500,000 seconds = 1/2 second */ printf("\nAfter 1/2 second delay"); printf("\n\n"); error = Execute("date",0,0); /* normal system startup file * opens dos.library, so it is * ok in such cases to use dos calls */ GetSysTime(&oldtimeval); printf("\nCurrent system time is %ld current seconds", oldtimeval.tv_secs); printf("\nSetting a new system time"); days = 1000 + oldtimeval.tv_secs / (24*60*60); minutes = (oldtimeval.tv_secs % (24*60*60)) / 60; seconds = (oldtimeval.tv_secs % (24*60*60)) % 60; SetNewTime(days, minutes, seconds); /* (if user executes the AmigaDOS DATE command now, he will * see that the time has advanced something over 1000 days */ printf("\n\n"); error = Execute("date",0,0); /* normal system startup file * opens dos.library, so it is * ok in such cases to use dos calls */ GetSysTime(&mytimeval); printf("\nCurrent system time is %ld.%06ld", mytimeval.tv_secs,mytimeval.tv_micro); GetSysTime(&mytimeval); printf("\nCurrent system time is %ld.%06ld", mytimeval.tv_secs,mytimeval.tv_micro); GetSysTime(&mytimeval); printf("\nCurrent system time is %ld.%06ld", mytimeval.tv_secs,mytimeval.tv_micro); /* added the microseconds part to show that time keeps * increasing even though you ask many times in a row */ printf("\nResetting to former time"); days = oldtimeval.tv_secs / (24*60*60); minutes = (oldtimeval.tv_secs % (24*60*60)) / 60; seconds = (oldtimeval.tv_secs % (24*60*60)) % 60; SetNewTime(days, minutes, seconds); GetSysTime(&mytimeval); printf("\nCurrent system time is %ld.%06ld", mytimeval.tv_secs,mytimeval.tv_micro); TimerBase = GetTimerBase(); /* just shows how to set up for using * the timer functions, does not demonstrate * the functions themselves. (TimerBase must * have a legal value before AddTime, SubTime or CmpTime * are performed. */ } /* *********************************************************************** */ /* Timer function - timedelay(seconds,microseconds) Your task is put to sleep for the specified time interval. If seconds > 0, then UNIT_VBLANK is used, delay is in multiples of 60ths of a second. If seconds < 0, then UNIT_MICROHZ is used for more precision. Returns value of 0 if no errors, nonzero (and no task sleeping) Notice that since this is a multi-tasking system, the delays shown here must be considered to be only approximate. Also note that this function is used primarily to show how a timer device is accessed, including the creation of the message port and a message structure (IOStdReq). Note that there is a Delay(interval) function already in the DOS.library. (See the DOS developer's manual for details). */ /* *********************************************************************** */ extern struct MsgPort *CreatePort(); extern struct IORequest *CreateExtIO(); struct timerequest *PrepareTimer(precision) SHORT precision; { /* return a pointer to a time request. If any problem, return NULL */ int error; SHORT whichunit; struct MsgPort *timerport; struct timerequest *timermsg; timerport = CreatePort(0,0); if (timerport == NULL) return(NULL); /* Error during CreatePort */ timermsg = (struct timerequest *)CreateExtIO( timerport,sizeof(struct timerequest)); if (timermsg == NULL) { DeletePort(timerport); return(NULL); /* Error during CreateExtIO */ } if(precision) /* if true, use precision timer ( under 1 second ) */ whichunit = UNIT_MICROHZ; else whichunit = UNIT_VBLANK; error = OpenDevice(TIMERNAME, whichunit, timermsg, 0); if (error != 0) { DeleteExtIO(timermsg,sizeof(struct timerequest)); DeletePort(timerport); return(NULL); /* Error during OpenDevice */ } return(timermsg); } int GetTimerBase() { int tbase; struct timerequest *tr; tr = PrepareTimer(); tbase = (int)tr->tr_node.io_Device; DeleteTimer(tr); return(tbase); } int TimeDelay(seconds,microseconds,precision) /* more precise timer than AmigaDOS Delay() */ ULONG seconds,microseconds; int precision; { int precise; struct timerequest *tr; if(seconds < 0 || precision != 0) /* do delay in terms of microseconds */ precise = TRUE; /* yes, use the precision timer. */ else precise = FALSE; /* no, not necessary */ tr = PrepareTimer(precise); /* get a pointer to an initialized * timer request block */ if(tr == NULL) return(-1); /* any nonzero return says timedelay * routine didn't work. */ WaitForTimer(tr,seconds,microseconds); DeleteTimer(tr); /* deallocate temporary structures */ return(0); } /* end of timedelay */ int WaitForTimer(tr,seconds,microseconds) ULONG seconds,microseconds; struct timerequest *tr; { tr->tr_node.io_Command = TR_ADDREQUEST; /* add a new timer request */ tr->tr_time.tv_secs = seconds; /* seconds */ tr->tr_time.tv_micro = microseconds; /* microseconds */ DoIO( tr ); /* post request to the timer */ /* goes to sleep till done */ return(0); } int SetNewTime(day,min,sec) LONG day, min,sec; /* days since 1 Jan 78 plus minutes */ { struct timerequest *tr; tr = PrepareTimer(TRUE); /* MUST use Precise timer for this */ if(tr == 0) return(-1); /* non zero return says error */ tr->tr_node.io_Command = TR_SETSYSTIME; tr->tr_time.tv_secs = (24 * 60 * 60 * day) + (60 * min) + sec; tr->tr_time.tv_micro = 0; DoIO( tr ); DeleteTimer(tr); return(0); } int GetSysTime(tv) struct timeval *tv; { struct timerequest *tr; tr = PrepareTimer(TRUE); /* MUST use Precise timer for this */ if(tr == 0) return(-1); /* non zero return says error */ tr->tr_node.io_Command = TR_GETSYSTIME; DoIO( tr ); tv->tv_secs = tr->tr_time.tv_secs; tv->tv_micro = tr->tr_time.tv_micro; DeleteTimer(tr); return(0); } int DeleteTimer(tr) struct timerequest *tr; { struct MsgPort *tp; tp = tr->tr_node.io_Message.mn_ReplyPort; if(tr != 0) { CloseDevice(tr); DeleteExtIO(tr,sizeof(struct timerequest)); } if(tp != 0) DeletePort(tp); return(0); } /*********************************************************************** * * Exec Support Function -- Extended IO Request * ***********************************************************************/ extern APTR AllocMem(); /****** exec_support/CreateExtIO ************************************** * * NAME * CreateExtIO() -- create an Extended IO request * * SYNOPSIS * ioReq = CreateExtIO(ioReplyPort,size); * * FUNCTION * Allocates memory for and initializes a new IO request block * of a user-specified number of bytes. * * INPUTS * ioReplyPort - a pointer to an already initialized * message port to be used for this IO request's reply port. * * RESULT * Returns a pointer to the new block. Pointer is of the type * struct IORequest. * * 0 indicates inability to allocate enough memory for the request block * or not enough signals available. * * EXAMPLE * struct IORequest *myBlock; * if( (myBlock = CreateExtIO(myPort,sizeof(struct IOExtTD)) == NULL) * exit(NO_MEM_OR_SIGNALS); * * example used to allocate space for IOExtTD (trackdisk driver * IO Request block for extended IO operations). * * SEE ALSO * DeleteExtIO * ***********************************************************************/ struct IORequest *CreateExtIO(ioReplyPort,size) struct MsgPort *ioReplyPort; LONG size; { struct IORequest *ioReq; if (ioReplyPort == 0) return ((struct IORequest *) 0); ioReq = (struct IORequest *)AllocMem (size, MEMF_CLEAR | MEMF_PUBLIC); if (ioReq == 0) return ((struct IORequest *) 0); ioReq -> io_Message.mn_Node.ln_Type = NT_MESSAGE; ioReq -> io_Message.mn_Node.ln_Pri = 0; ioReq -> io_Message.mn_ReplyPort = ioReplyPort; return (ioReq); } /****** exec_support/DeleteExtIO ************************************** * * NAME * DeleteExtIO() - return memory allocated for extended IO request * * SYNOPSIS * DeleteExtIO(ioReq,size); * * FUNCTION * See summary line at NAME. Also frees the signal bit which * had been allocated by the call to CreateExtIO. * * INPUTS * A pointer to the IORequest block whose resources are to be freed. * * RESULT * Frees the memory. Returns (no error conditions shown) * * EXAMPLE * struct IORequest *myBlock; * DeleteExtIO(myBlock,(sizeof(struct IOExtTD))); * * example shows that CreateExtIO had been used to create a trackdisk * (extended) IO Request block. * * SEE ALSO * CreateExtIO * **************************************************************************/ DeleteExtIO(ioExt,size) struct IORequest *ioExt; LONG size; { ioExt -> io_Message.mn_Node.ln_Type = 0xff; ioExt -> io_Device = (struct Device *) -1; ioExt -> io_Unit = (struct Unit *) -1; FreeMem (ioExt, size); }