Author Topic: alternative delay timer loop  (Read 3302 times)

0 Members and 1 Guest are viewing this topic.

RAIN CODE

  • Guest
alternative delay timer loop
« on: June 27, 2014, 01:06:46 AM »
Hi guys

Noticed that (getvar "cdate") or (getvar "millisecs") returns result in every 15 or 16 millisecs. It fails to trap anything below 15 ms.

If you run lisp below you will know what I mean.
(repeat 100
  (princ "millisecs = ") (princ (getvar "millisecs"))
)

Running a delay under 15 ms will get zero.
Now am trying to work around this problem using lisp below. It works fine on my P4 but dont know if it will work on faster PC.

would someone be kind enough to run Glo once then run Dlop few times. Dlop argument  ms is the millisecs, if it returns results in a range of +- 15 then it works. Try Dlop with argument 100 for few times, 500 for few times and 20 for few times. If use 15 it retuns 0 or 15 becos it cant trap anything below that but it did do the delay loop for 15 ms.

Thanks

(defun c:Glo (/ stime)
  (setq gaddct 0
            stime (getvar "millisecs"))
(while (< (- (getvar "millisecs") stime) 1000)
  (setq gaddct (1+ gaddct))
)
(setq gaddct  (fix (/ (* gaddct 2.6) 1000))
          daddct gaddct)
(princ)
)

(defun Dlop (ms / repnum stime bct )
  (setq repnum (* gaddct ms)
                  bct 0)
   (setq stime (getvar "millisecs"))
  (repeat (fix repnum)
      (setq bct (1+ bct))
   )
   (princ "Total time = ") (princ (- (getvar "millisecs") stime))
  (princ)
)




danallen

  • Guest
Re: alternative delay timer loop
« Reply #1 on: June 27, 2014, 01:12:12 AM »
my result in Bricscad 14 on

OS Name   Microsoft Windows 7 Professional
Version   6.1.7601 Service Pack 1 Build 7601
Other OS Description    Not Available
OS Manufacturer   Microsoft Corporation
System Manufacturer   Apple Inc.
System Model   iMac12,2
System Type   x64-based PC
Processor   Intel(R) Core(TM) i7-2600 CPU @ 3.40GHz, 3401 Mhz, 4 Core(s), 8 Logical Processor(s)
BIOS Version/Date   Apple Inc. IM121.88Z.0047.B1D.1110171110, 10/17/2011

Code: [Select]
: (dlop 100)
Total time = 62
: (dlop 100)
Total time = 32
: (dlop 100)
Total time = 47
: (dlop 500)
Total time = 125
: (dlop 500)
Total time = 156
: (dlop 500)
Total time = 125
: (dlop 20)
Total time = 0
: (dlop 20)
Total time = 16
: (dlop 20)
Total time = 15
: (dlop 20)
Total time = 16
: (dlop 20)
Total time = 16
: (dlop 20)
Total time = 15
: (dlop 20)
Total time = 0
: (dlop 20)
Total time = 0
: (dlop 20)
Total time = 0
: (dlop 20)
Total time = 16

RAIN CODE

  • Guest
Re: alternative delay timer loop
« Reply #2 on: June 27, 2014, 04:25:34 AM »
my result in Bricscad 14 on

OS Name   Microsoft Windows 7 Professional
Version   6.1.7601 Service Pack 1 Build 7601
Other OS Description    Not Available
OS Manufacturer   Microsoft Corporation
System Manufacturer   Apple Inc.
System Model   iMac12,2
System Type   x64-based PC
Processor   Intel(R) Core(TM) i7-2600 CPU @ 3.40GHz, 3401 Mhz, 4 Core(s), 8 Logical Processor(s)
BIOS Version/Date   Apple Inc. IM121.88Z.0047.B1D.1110171110, 10/17/2011

Code: [Select]
: (dlop 100)
Total time = 62
: (dlop 100)
Total time = 32
: (dlop 100)
Total time = 47
: (dlop 500)
Total time = 125
: (dlop 500)
Total time = 156
: (dlop 500)
Total time = 125
: (dlop 20)
Total time = 0
: (dlop 20)
Total time = 16
: (dlop 20)
Total time = 15
: (dlop 20)
Total time = 16
: (dlop 20)
Total time = 16
: (dlop 20)
Total time = 15
: (dlop 20)
Total time = 0
: (dlop 20)
Total time = 0
: (dlop 20)
Total time = 0
: (dlop 20)
Total time = 16

Thanks danallen, for the quick reply.

Sigh...sigh....very disappointed it didnt work. Back to the drawing board again.
Have to crack my head on this problem again.


irneb

  • Water Moccasin
  • Posts: 1794
  • ACad R9-2016, Revit Arch 6-2016
Re: alternative delay timer loop
« Reply #3 on: June 27, 2014, 06:30:04 AM »
You're absolutely correct! It doesn't seem to count in smaller than 15 or 16 ms.
Code - Auto/Visual Lisp: [Select]
  1. (defun test-time  (run var func / val result)
  2.   (repeat run
  3.     (setq val    (apply func (list (getvar var)))
  4.           result (if (= (caar result) val)
  5.                    (cons (cons val (1+ (cdar result))) (cdr result))
  6.                    (cons (cons val 1) result))))
  7.   (mapcar (function (lambda (item prev) (list (car item) (- (car item) (car prev)) (cdr item))))
  8.           result
  9.           (cdr result)))
Then this produces a list containing items in the following format:
(<returned-value> <difference-from-previous> <repeated-same-value-count>)
Code: [Select]
_$ (test-time 10000 'millisecs (function (lambda (v) v)))
((15712358 16 926) (15712342 15 1858) (15712327 16 2985) (15712311 16 2841))
_$ (test-time 1000 'date (function (lambda (v) (fix (rem (* v 1000000000.0) 2147483648.0)))))
((1380298545 12 153) (1380298533 12 155) (1380298521 11 156) (1380298510 11 154) (1380298499 12 156) (1380298487 12 156))
_$ (test-time 100 'cputicks (function (lambda (v) v)))
((4.23054e+013 12643.0 1) (4.23054e+013 12646.0 1) (4.23054e+013 12388.0 1) (4.23054e+013 12237.0 1) (4.23054e+013 12360.0 1) (4.23054e+013 12443.0 1) (4.23054e+013 14265.0 1) (4.23054e+013 12240.0 1) (4.23054e+013 12335.0 1) (4.23054e+013 12249.0 1) (4.23054e+013 12486.0 1) (4.23054e+013 12413.0 1) (4.23054e+013 12766.0 1) (4.23054e+013 12317.0 1)...
It seems using the date sysvar gives a slightly more finer grained difference. MilliSecs between 15 and 16 ms, and Date between 11 and 12. Obviously cputicks are much more fine grained - but then you get into the scenario where one PC's cputicks are different from another's.

What you could try though is to test a CPU's speed and then apply the average around that:
Code - Auto/Visual Lisp: [Select]
  1. (defun CpuHertz  (/ time ticks)
  2.   (setq time (+ (getvar 'millisecs) 1000)
  3.         ticks (getvar 'cputicks))
  4.   (while (< (getvar 'millisecs) time))
  5.   (/ (- (getvar 'cputicks) ticks) 1e0))
  6.  
  7. (setq *cputick-time* nil)
  8. (defun getSecondsTimer  (/ time prev)
  9.   (if *cputick-time*
  10.     (* *cputick-time* (getvar 'cputicks))
  11.     (progn (setq *cputick-time* (/ 1.0 (CpuHertz))) (getSecondsTimer))))
So now it would measure the clockspeed of the cpu on first use, thereafter it will convert the cputicks to a real value in seconds. It seems very fine grained in deed
Code: [Select]
_$ (test-time 500 'date (function (lambda (v) (fix (rem (* (getSecondsTimer) 1000.0) 2147483648.0)))))
((17538368 1 22) (17538367 1 124) (17538366 1 123) (17538365 1 126))
So definitely better than 1 ms. Actually a cputick would be the 1sec / Hz, which on my CPU (2.67GHz) would equal 0.0000000003745318 sec or 0.374532 nano seconds (ns).

But the testing itself is taking up some time (especially when you now get into this infinitesimal period):
Code: [Select]
_$ (test-time 5 'date (function (lambda (v) (fix (rem (* (getSecondsTimer) 1000000.0) 2147483648.0)))))
((385220994 8 1) (385220986 8 1) (385220978 7 1) (385220971 12 1))
So the test itself takes around 7 to 12 micro seconds (μs), or 7000ns to 12000ns, or thus between 18000 and 32000 cputicks. Of course you're also getting a bit of floating point errors in that.
« Last Edit: June 27, 2014, 06:35:13 AM by irneb »
Common sense - the curse in disguise. Because if you have it, you have to live with those that don't.

irneb

  • Water Moccasin
  • Posts: 1794
  • ACad R9-2016, Revit Arch 6-2016
Re: alternative delay timer loop
« Reply #4 on: June 27, 2014, 07:51:39 AM »
An alternative way to get the CPU's Hz from registry:
Code - Auto/Visual Lisp: [Select]
  1. (defun CpuHertzReg  (/)
  2.   (* (vl-registry-read "HKEY_LOCAL_MACHINE\\HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0" "~MHz")
  3.      1000000.0))
The value stored in registry is in MHz (Mega Hertz) as an integer, so for mine it reads 2660. The returned real value from this is in Hertz (i.e. ticks per second), so with a 2.66GHz it should read 2 660 000 000 Hz.

This is rather close to the other method's calculation (which varies slightly due to background processes and inaccuracies):
Code: [Select]
_$ (CpuHertz)
2.66445e+009
_$ (rtos (CpuHertz) 2 0)
"2680190625"

Of course the variance is reasonably small it seems. On this 2.66GHz it varies between 2.64 and 2.68 - so around 0.75% variance either way from 2.66. I guess in the game it shouldn't make such a great difference if the timing varies by such a small fraction -> 7.5ms = 7.5/1000 seconds

Edit: Given that most movies work on 25 Hz (or thereabouts) = 0.04s = 40ms (due to most people not being able to notice the frames at such intervals). And newer HD on 60Hz = 0.017s = 17ms (similar to the maximum setting for most newer games - e.g. Need for Speed). It may just interfere slightly, but over the average it's probably not noticeable.

Unfortunately I don't think you're going to get much better than that - not inside AutoCad anyway. It's not really meant as a real-time graphics system.
« Last Edit: June 27, 2014, 07:56:21 AM by irneb »
Common sense - the curse in disguise. Because if you have it, you have to live with those that don't.

RAIN CODE

  • Guest
Re: alternative delay timer loop
« Reply #5 on: June 27, 2014, 10:28:23 AM »

A refined version. Hope someone can run this again to chk if this works.
Thanks.

(defun c:Glo (/  stime badct nt ttimeused timeused)
  (setq gaddct 0
            stime (getvar "millisecs") )
  (while (< (- (getvar "millisecs") stime) 1000)
     (setq gaddct (1+ gaddct))
  )
  (setq nt 3.0
            ttimeused 0)
   (repeat (fix nt)
      (setq badct 0
                stime (getvar "millisecs"))
       (repeat (fix gaddct)
          (setq badct (1+ badct))
        )
        (princ"\nTotal time = ") (princ (setq timeused (- (getvar "millisecs") stime)))
         (setq ttimeused (+ ttimeused timeused))
  )
  (setq gaddct (fix (/ (*gaddct (/ 1000 (/  ttimeused nt))) 1000))
            daddct gaddct)
  (princ)
)

(defun Dlop (ms / repnum stime badct)
  (setq repnum (* gaddct ms)
             stime (getvar "millisecs")
             badct 0)
  (repeat (fix repnum)
     (setq badct (1+ badct))
  )
   (princ"\nTotal time = ") (princ (- (getvar "millisecs") stime))
   (princ)
)

------>> to irneb

While you posted your reply, I refined my lisp but dunno if it works.

I have to digest your solution (Lisps) becos I can link my phone to my PC and have to type it in my pc to see result.


       

RAIN CODE

  • Guest
Re: alternative delay timer loop
« Reply #6 on: June 27, 2014, 10:52:43 AM »

What you could try though is to test a CPU's speed and then apply the average around that
 

I am trying to do that with my first lisp but  with no good result.
Yesterday I studied the game Troy written by Terry Milller. He uesd this method which I have followed. If his  delay Lisp worked then I dun understand why mine failed to work.

His idea is good becos he gauged the PC speed using count then use repeat loop nos of count. This way, like what you said that no matter what is running in the backgrd will not affect the speed gauging

CAB

  • Global Moderator
  • Seagull
  • Posts: 10401
Re: alternative delay timer loop
« Reply #7 on: June 27, 2014, 01:38:09 PM »
Total time = 281
Total time = 296
Total time = 281; error: no function definition: *GADDCT
; reset after error
I've reached the age where the happy hour is a nap. ()
Windows 10 core i7 4790k 4Ghz 32GB GTX 970
Please support this web site.

chlh_jd

  • Guest
Re: alternative delay timer loop
« Reply #8 on: June 27, 2014, 04:55:52 PM »
For me
Total time = 359
Total time = 374
Total time = 359

RAIN CODE

  • Guest
Re: alternative delay timer loop
« Reply #9 on: June 28, 2014, 03:10:17 AM »
Sorry, typing error becos of using phone and the text is small to see, missed out the space but now corrected.
Tried on cybercafe fast pc it is almost there.
+- about 15 to 25.

But the bigger the argument (ms) the bigger the differences are. But will only use this for anything below 20 ms and anything above 20 ms will use the getvar millisecs.

Thanks guys for posting the result even there is an error.

Thanks irneb for the lengthy explanation. You are a very knowledgeable person.


(defun c:Glo (/  stime badct nt ttimeused timeused)
  (setq gaddct 0
            stime (getvar "millisecs") )
  (while (< (- (getvar "millisecs") stime) 1000)
     (setq gaddct (1+ gaddct))
  )
  (setq nt 3.0
            ttimeused 0)
   (repeat (fix nt)
      (setq badct 0
                stime (getvar "millisecs"))
       (repeat (fix gaddct)
          (setq badct (1+ badct))
        )
        (princ"\nTotal time = ") (princ (setq timeused (- (getvar "millisecs") stime)))
         (setq ttimeused (+ ttimeused timeused))
  )
  (setq gaddct (fix (/ (* gaddct (/ 1000 (/  ttimeused nt))) 1000))
            daddct gaddct)
  (princ)
)

(defun Dlop (ms / repnum stime badct)
  (setq repnum (* gaddct ms)
             stime (getvar "millisecs")
             badct 0)
  (repeat (fix repnum)
     (setq badct (1+ badct))
  )
   (princ"\nTotal time = ") (princ (- (getvar "millisecs") stime))
   (princ)
)
« Last Edit: June 28, 2014, 03:19:48 AM by RAIN CODE »

RAIN CODE

  • Guest
Re: alternative delay timer loop
« Reply #10 on: July 09, 2014, 06:55:09 AM »
to irneb

The speed issue regarding inconsistent of speed is resolved.

But I am sorry that I took the easy way out by just balancing the speed and didnt follow your method.

 I hope you understand becos if I were to revise using your method, alot of coding are tie to it and will cause more bugs, given my programming skill.
 
But I will try it on my next project. Start afresh using your method. I believed your method is the actual way of writing games becos a year ago I tried to run Resident Evil 5 on my underpowered P4 and noticed the frame rate lagged and can see the object running animation discontinued (skipped frame) just like what you said.

I understand prefectly how your method works and will use it on my next project.

Thanks again

irneb

  • Water Moccasin
  • Posts: 1794
  • ACad R9-2016, Revit Arch 6-2016
Re: alternative delay timer loop
« Reply #11 on: July 09, 2014, 07:40:44 AM »
You're welcome, and I understand fully why you used the balanced CPU timer - i.e. because acad doesn't give you fine enough control over timing checks.

Personally, I think any form of real-time software isn't conducive inside the acad environment. If you really want to do some game programming I'd advise you move outside of acad. Notice most game programming engines are built using C/C++ http://en.wikipedia.org/wiki/List_of_game_engines

There are some other languages like Java/Haskell/Pascal, but not too many. From some other discussions I've had with professional game developers they tend to use C/C++ for the portions where timing is critical (actually not huge areas of the game - tends towards about 10% of the entire program), while the rest they write in something like Lua (or some even use Common Lisp).

Apparently all of these games use Corman Common Lisp for the logic and and tying it all together, then C++ for the actual rendering and hardware interfacing.
Common sense - the curse in disguise. Because if you have it, you have to live with those that don't.

RAIN CODE

  • Guest
Re: alternative delay timer loop
« Reply #12 on: July 10, 2014, 03:56:18 AM »
Personally, I think any form of real-time software isn't conducive inside the acad environment. If you really want to do some game programming I'd advise you move outside of acad. Notice most game programming engines are built using C/C++ http://en.wikipedia.org/wiki/List_of_game_engines

It will take me years of training to get to the professional level or I may not get there at all.
To learn a new language at my age will be tiring. If I am still in my 30s I may give it a try.
 
In fact writing games using Acad is easier then Qbasic. To create an image in Qbasic, if I remember correctly I have to define the image using Peek and Poke, it was troublesome compare to Acad I just block the object.
 
But thanks for the info becos I am always curious about what languages the pro use for creating games.

[ Correction - I remembered I installed RE 5 game on a laptop and not on a P4 ]
« Last Edit: July 10, 2014, 04:07:05 AM by RAIN CODE »