sjl / cl-chip8

chip-8 emulator in common lisp
MIT License
83 stars 3 forks source link

Skew in timing #1

Open npatrick04 opened 7 years ago

npatrick04 commented 7 years ago

Hey Steve,

I was planning on commenting on your blog...but since there is no way to do that...and you linked to your github account, I figured I'd put this here.

The sleeps you're doing in run-cpu, emulate-cycle, run-sound, and run-timers all will result in skew that varies from cycle to cycle. It'd be better to use a constant frequency tick for those things. I actually have a library that could be used (though it's probably more complicated than what this needs).

Using https://github.com/npatrick04/timer-wheel,

(defconstant +cycles-per-second+ 500)
(defconstant +cycles-before-sleep+ 10)
(defconstant +cycles-period+ (/ +cycles-before-sleep+ +cycles-per-second+))

(defparameter cycle-lock (bt:make-lock))
(defparameter cycle-cv (bt:make-condition-variable))

(defun timeout (wheel timer)
  (bt:with-lock-held (cycle-lock)
    (bt:condition-notify cycle-cv))
  (tw:schedule-timer wheel timer :seconds +cycles-period+))

(defun wait ()
  (bt:with-lock-held (cycle-lock)
    (bt:condition-wait cycle-cv cycle-lock)))

(defun run-cpu (chip)
  (let ((wheel (tw:make-wheel))
    (timer (tw:make-timer #'timeout)))
    (tw:with-timer-wheel wheel
      (tw:schedule-timer wheel timer :seconds +cycles-period+)
      (iterate
      (while (chip-running chip))
      (emulate-cycle chip)
    (for tick :every-nth +cycles-before-sleep+ :do (wait))))))
npatrick04 commented 7 years ago

Or shorter and more understandable using https://github.com/npatrick04/rate-monotonic...

(defconstant +cycles-per-second+ 500)
(defconstant +cycles-before-sleep+ 10)
(defconstant +cycles-period+ (/ +cycles-before-sleep+ +cycles-per-second+))

(defun run-cpu (chip)
  (let ((cycle-period (rm:make-timer-period)))
    (rm:with-timer-period (+cycles-period+)
      ;; Kick the first period off
      (rm:period cycle-period :seconds +cycles-period+)
      (iterate
      (while (chip-running chip))
      (emulate-cycle chip)
    (for tick :every-nth +cycles-before-sleep+
         :do (rm:period cycle-period :seconds +cycles-period+))))))