delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp-workers/2002/12/07/13:48:24

From: sandmann AT clio DOT rice DOT edu (Charles Sandmann)
Message-Id: <10212071847.AA13093@clio.rice.edu>
Subject: Re: XP delay() again - potential solution
To: djgpp-workers AT delorie DOT com
Date: Sat, 7 Dec 2002 12:47:48 -0600 (CST)
In-Reply-To: <001a01c29db4$6ee30100$0100a8c0@p4> from "Andrew Cottrell" at Dec 07, 2002 04:49:08 PM
X-Mailer: ELM [version 2.5 PL2]
Mime-Version: 1.0
Reply-To: djgpp-workers AT delorie DOT com
Errors-To: nobody AT delorie DOT com
X-Mailing-List: djgpp-workers AT delorie DOT com
X-Unsubscribes-To: listserv AT delorie DOT com

> This was discussed a while ago and I cannot remember if there was a solution
> proposed, except one I worked on.  Below is a modified delay.c that works on
> XP. It does have some problems in that it is only accuate to approx 27
> milliseconds as the TOD tick is updated every 54.9 millisends and I do a
> manual rounding check in the code in order to try to make the delay a bit
> more accurate.

I also worked on something similar - my WIP from last year is attached at
the bottom.  I was trying to get more accuracy, but due to the unsync
between the counter and tick rollover, I think there were bugs I hadn't
fixed in the stuff below (it didn't work?).  I also tried to call the 
int15 call and checked for success, just in case they fixed it some day.

Yours looks fine, and I think we ought to get it into the library for the next
release.  Maybe document the accuracy issue. Maybe do some yields in the busy
loop.  Thanks for working on this, I'm just completely swamped.


/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */
#include <dos.h>
#include <dpmi.h>

void delay(unsigned msec)
{
  __dpmi_regs r;
  while (msec)
  {
    unsigned usec;
    unsigned msec_this = msec;
    if (msec_this > 4000)
      msec_this = 4000;
    usec = msec_this * 1000;
    r.h.ah = 0x86;
    r.x.cx = usec>>16;
    r.x.dx = usec & 0xffff;
    __dpmi_int(0x15, &r);
    if(r.x.flags & 1) {
      unsigned char lsb, msb, omsb;
      int msbcount = msec * 4661;		/* Actually 1193180/256 */

      outportb(0x43, 0x34);		/* Program as counter */
      outportb(0x40, 0xff);
      outportb(0x40, 0xff);

      outportb(0x43, 0x00);
      lsb = inportb(0x40);
      omsb = inportb(0x40) ^ 0xff;
      do {
/*        printf("msbcount %d\n",msbcount); */
        outportb(0x43, 0x00);
        lsb = inportb(0x40);
        msb = inportb(0x40) ^ 0xff;
        if(msb >= omsb) {
          msbcount -= (unsigned)msb - (unsigned)omsb;
        } else {
          msbcount -= (unsigned)msb + 256 - (unsigned)omsb;
        }
        omsb = msb;
      } while (msbcount > 0);
      printf("int 15 failed!\n");
      return;
    }
    msec -= msec_this;
  }
}

int main(int argc, char **argv)
{
  int i;
  i = atoi(argv[1]);
  if(i) delay(i);
  return 0;
}

- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019