[comp.sys.ibm.pc] Help with delay funct for MSC

paul@crash.cts.com (Paul Palacios) (11/29/87)

In article <9394@shemp.UCLA.EDU> claus@CS.UCLA.EDU () writes:
>I am writing an application in MSC 4.0, and I wish to incorporate time
>delays that are independed of the speed of the machine on which the
>application is run. I couldn't find any appropriate routine in the
>MSC documentation (yes I do have the manual). 
>Something like DELAY(x), where x is 1/18 seconds, would be ideal.
>
>I'm sure something like this exists, can anyone help?

I believe that MS-C supports sleep() which is passed an unsigned int of the 
number of seconds to sleep (wait / delay).  If this is not sufficient or
in fact is not supported by MS-C then you could possibly do the following.

The simplest way I can think of providing this functionality is as follows:

It will be necessary, of course, to create this function, assuming that there
is no apparent equivalent function provided in the libraries of the MSC 4.0
release.

The following function will provide your functionality, but will only sleep
approximately the number of tics passed.  After assembling it, you will have
to link it in to any code which uses the function.

Note:  the following depicts the interface to MSC ver 3.xx.  I believe that it
       would be the same or very similar for MSC v. 4.0.

8088 assembly code to interface to MS-C follows:

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;     Author: Paul Palacios
;    Address:
;	    UUCP: {cbosgd, hplabs!hp-sdd, sdcsvax, nosc}!crash!portnoy!paul
;	    INET: paul@portnoy.cts.com
;	    ARPA: crash!portnoy!paul@nosc.mil
;
; This code is copyright (c) 1987 by Paul Palacios to enforce that:
;
; This code, or any part herein, is to be considered public domain and is to
; be used in any way by any one who cares to make use of it, with the sole
; restriction that it, in all forms, must not be product, or part of a product,
; for sale.  Any use of this code, or part herein, for other than free
; distribution, or in part to any product, or package, must have the expressed
; written consent of the original author (Paul Palacios) to do so.  This code,
; if redistributed or modified and subsequently redistributed, must preserve
; this header.  Any who distribute the binaries of this code, or modified
; versions, must make it clear to the receiving party that the source code is
; available to anyone, at any time, free of charge and must be provided to
; that receiving party upon demand.  All receiving parties must abide by and to
; this copyright notice.
; 
;
;	    ***** Please do not remove this header, thank you. *******
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; Functions:
;
;	(void)
;	tsleep(tics) -      number of tics to sleep (18.2tics=approx. 1 sec)
;	unsigned int tics;
;
;	bugs:
;		sleeps only approximately the specified number of tics
;		max sleep for approx. one hour; for more than a second, sleep()
;		should be used.
;
;
;	(void)
;	sleep(seconds) -      number of seconds to sleep 
;	unsigned int second;
;
;	bugs:
;		sleeps only approximately the specified number of seconds
;

_TEXT	SEGMENT  BYTE PUBLIC 'CODE'
_TEXT	ENDS
CONST	SEGMENT  WORD PUBLIC 'CONST'
CONST	ENDS
_BSS	SEGMENT  WORD PUBLIC 'BSS'
_BSS	ENDS
_DATA	SEGMENT  WORD PUBLIC 'DATA'
_DATA	ENDS
DGROUP	GROUP	CONST,	_BSS,	_DATA
	ASSUME  CS: _TEXT, DS: DGROUP, SS: DGROUP, ES: DGROUP
PUBLIC  _tsleep, _sleep
_TEXT      SEGMENT
	PUBLIC	_tsleep
	PUBLIC	_sleep

; tsleep(tics)
; unsigned int tics;
;
_tsleep	proc	near
	push	bp
	mov	bp,sp			; save stack pointer
	sub	sp,2			; space for automatic variable
	push	ax
	push	bx
	push	cx			; save affected registers
	push	dx
	xor	ax,ax			; want function 0 of int 1Ah
	int	1Ah			; (the time of day function)
	mov	[bp-2],dx		; store original time
_ts1:
	xor	ax,ax
	int	1Ah
	mov	bx,[bp-2]
	cmp	bx,dx
	jbe	_ts2
	mov	ax,0ffffh
	sub	ax,bx
	add	dx,ax
	jmp	short _ts3
_ts2:
	sub	dx,bx
_ts3:	
	cmp	dx,[bp+4]		; compare to what was passed to us
	jb	_ts1

	pop	dx
	pop	cx
	pop	bx
	pop	ax
	mov	sp,bp
	pop	bp
	ret
_tsleep	endp

; sleep(seconds)
; unsigned int seconds;
;
_sleep	proc	near
	push	bp
	mov	bp,sp
	push	cx
	mov	cx,18			; or replace with code that calculates
	push	cx			; to 18.2 tic / sec requested
	mov	cx,[bp+4]
_sl1:
	call	_tsleep
	loop	_sl1
	add	sp,2
	pop	cx
	pop	bp
	ret
_sleep	endp

_TEXT	ENDS
END
_TEXT	ENDS
END


If there should be a need for further assistance, please feel free to send
me mail.  My address is contained in the copyright notice above.

ssnyder@tybalt.caltech.edu (Scott S. Snyder) (11/30/87)

In article <9394@shemp.UCLA.EDU> claus@CS.UCLA.EDU () writes:
>I am writing an application in MSC 4.0, and I wish to incorporate time
>delays that are independed of the speed of the machine on which the
>application is run. I couldn't find any appropriate routine in the
>MSC documentation (yes I do have the manual). 
>Something like DELAY(x), where x is 1/18 seconds, would be ideal.
>
>I'm sure something like this exists, can anyone help?

I usually use something like:

#include <stdio.h>
#include <time.h>

sleep(secs)
int secs;
{
  time_t t, t0;

  t0 = time((time_t *)NULL);

  do {
    t = time((time_t *)NULL);
  } while (t - t0 < secs);
}

If more accuracy is required, ftime() can be used instead of time().

sss

pozar@hoptoad.uucp (Tim Pozar) (11/30/87)

In article <9394@shemp.UCLA.EDU> claus@CS.UCLA.EDU () writes:
>I am writing an application in MSC 4.0, and I wish to incorporate time
>delays that are independed of the speed of the machine on which the
>application is run. I couldn't find any appropriate routine in the
>MSC documentation (yes I do have the manual). 
>Something like DELAY(x), where x is 1/18 seconds, would be ideal.
>
>I'm sure something like this exists, can anyone help?

   This a sleep that will work with basicly MSC 2.0 through MSC
5.0.   It is currently set up for whole seconds, but can be
changed to whatever you want...
	      Tim
---


/*
 * get_time(n)
 * TIME_PTR n;
 *
 * fills timetype structure n with current time using DOS interrupt 21
 *
 */

get_time(n)
TIME_PTR n;
{
  union REGS inregs;
  union REGS outregs;

  inregs.h.ah = GET_TIME;

  int86(DOS_INT, &inregs, &outregs);

  n->hour = outregs.h.ch;
  n->minute  = outregs.h.cl;
  n->sec  = outregs.h.dh;
  n->hsec = outregs.h.dl;

  return(0);
}

sleep(x)
int x;
{
  int i;
  unsigned s;
  TIME n;               /* current time record */

  i = 0;
  get_time(&n);
  s = n.sec;

  while (i < x){
    while (s == n.sec)
      get_time(&n);
    s = n.sec;
    ++i;
  }
}
---

-- 
=======================================================================
| ...sun!hoptoad!\                                     Tim Pozar      |
|                 >fidogate!pozar               Fido:  1:125/406      |
|  ...lll-winken!/                            PaBell:  (415) 788-3904 |
|         USNail:  KKSF  77 Maiden Lane  San Francisco CA 94108       |
=======================================================================

manes@dasys1.UUCP (Steve Manes) (12/01/87)

In article <2056@crash.cts.com> crash!crash.CTS.COM!paul (Paul Palacios) writes:
>In article <9394@shemp.UCLA.EDU> claus@CS.UCLA.EDU () writes:
>>I am writing an application in MSC 4.0, and I wish to incorporate time
>>delays that are independed of the speed of the machine on which the
>>application is run. I couldn't find any appropriate routine in the
>>MSC documentation (yes I do have the manual). 

A less involved solution is simply to read the BIOS timer variables
directly via a 'peek' function (I know it's not in the MSC4 library but
there are dozens to be found on just about any respectable programmer-
oriented BBS so I'll not duplicate one here).

void ticks(snooze)
long snooze;	/* make this a long for longer delay values */
{
	unsigned count;

	while (snooze--) {
		count = peek(0x40, 0x6C);
		while (count == peek(0x40, 0x6C) );
	}
}

Simply call 'ticks' with the number of clock cycles you want to pause.
You can set up some global defines, like
#define ONESEC	18L
#define ONEMIN	(ONESEC * 60)
etc...

The one problem with the (very well-written!) Assy approach submitted
earlier is that it calls Int 1Ah, which produces that date rollover bug
for a lot of folks.

-- 
+-----------------------------------------------------------------------
+ Steve Manes         Roxy Recorders, Inc.                 NYC
+ decvax!philabs!cmcl2!hombre!magpie!manes       Magpie BBS: 212-420-0527
+ uunet!iuvax!bsu-cs!zoo-hq!magpie!manes              300/1200/2400

paul@crash.cts.com (Paul Palacios) (12/02/87)

In article <2120@dasys1.UUCP> manes@dasys1.UUCP (Steve Manes) writes:
>
>
>void ticks(snooze)
>long snooze;	/* make this a long for longer delay values */
>{
>	unsigned count;
>
>	while (snooze--) {
>		count = peek(0x40, 0x6C);
>		while (count == peek(0x40, 0x6C) );
>	}
>}

This approach is fine and yes much simpler, however, keep in mind that 
the value can roll over and cause problems.  Also, I may be wrong, unless it
a macro or some thing, but I don't recall a peek function in MSC.  Now I'm
only really familiar with MSC 3.xx and I could see something to the effect:

#define TPD	0x1800b0		/* Tics per Day	*/

void tsleep(tics)
long tics;
{
    long far *timer;
    long start_time, t;

    FP_SEG(timer) = 0x40;
    FP_OFF(timer) = 0x6c;

    start_time = *timer;

    while ( ((t = *timer - start_time) >= 0 && t < tics) ||
	(t < 0 && (t - TPD + *timer  < tics)) ) ;
}

----                                                                      ----
-- 
Paul Palacios  UUCP: {cbosgd, hplabs!hp-sdd, sdcsvax, nosc}!crash!portnoy!paul 
POBox 842,(CA) INET: paul@portnoy.cts.com              VOICE: wk:(619)458-0230
Bonita, 92002  ARPA: crash!portnoy!paul@nosc.mil              hm:(619)420-5776