Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for slowing down emulation #3

Open
jessemillar opened this issue Apr 9, 2018 · 9 comments
Open

Add support for slowing down emulation #3

jessemillar opened this issue Apr 9, 2018 · 9 comments

Comments

@jessemillar
Copy link

Running my .hex file in the sim_arduboy binary results in a play experience roughly 3x faster than it is on the physical Arduboy. Is there a way to limit the draw rate or CPU clock speed in the emulator to more closely match the Arduboy hardware?

@dxxb
Copy link
Owner

dxxb commented Apr 11, 2018

Hi @jessemillar, this function

static void avr_callback_sleep_sync(
should already take care of it. It seemed to work pretty well last time I checked but maybe it doesn't in all cases. Do you mind hacking that function to print out deadline_ns and runtime_ns (or a running average of their difference)? I'd like to see what values you are getting on your test machine. Thank you.

@jessemillar
Copy link
Author

jessemillar commented Apr 11, 2018

Sure! I added #include <inttypes.h> to the top of src/arduboy_avr.c and printf("runtime_ns: %" PRIu64 " deadline_ns: %" PRIu64 "\n", runtime_ns, deadline_ns); to avr_callback_sleep_sync(), ran make and then ran sim_arduboy -p 3 ~/Documents/Projects/crates/crates.ino.leonardo.hex like I usually do. The output of starting my game and playing for about a minute is below:

Keymap: 1073741906,1073741905,1073741904,1073741903,122,120
SSD1306: 37uS is 592 cycles for your AVR
SSD1306: 1uS is 16 cycles for your AVR
runtime_ns: 219934594 deadline_ns: 15144062
runtime_ns: 219957972 deadline_ns: 15252562
runtime_ns: 219968177 deadline_ns: 16276562
runtime_ns: 219976056 deadline_ns: 17300562
runtime_ns: 219983666 deadline_ns: 18324562
runtime_ns: 219990446 deadline_ns: 19348562
runtime_ns: 9974704962 deadline_ns: 17505172562
runtime_ns: 17525916577 deadline_ns: 17520532562
runtime_ns: 17525934199 deadline_ns: 17521556562
runtime_ns: 17528812419 deadline_ns: 17537940562
Exiting with error: Invalid argument

This line (runtime_ns: 9974704962 deadline_ns: 17505172562) represents a pause of about two seconds after hitting "play" in my game's menu before it actually starts the game. I'm not sure why that pause happens since it doesn't occur on Arduboy hardware or in ProjectABE (https://felipemanga.github.io/ProjectABE/?skin=Arduboy&url=https://rawgit.com/jessemillar/crates/master/crates.ino.leonardo.hex).

@dxxb
Copy link
Owner

dxxb commented Apr 11, 2018

Some stuttering especially on start maybe inevitable. The issue is that sim-arduboy uses simavr which is more of a simulator than an emulator. It tries to simulate interaction execution timing and pin state changes so they happen with the right timing with respect to the simulated clock but with no regards to wall clock (except for the function I mentioned in my first reply).

What seems very strange is that I expected that function to be called a lot more often. Did you add your print statement above this line?

if (runtime_ns >= deadline_ns) {

@jessemillar
Copy link
Author

I did add it above that line. I was confused why it wasn't called more frequently too. This is what my copy of avr_callback_sleep_sync() looks like currently:

static void avr_callback_sleep_sync(
                avr_t *avr,
                avr_cycle_count_t how_long)
{
        struct timespec tp;

        /* figure out how long we should wait to match the sleep deadline */
        uint64_t deadline_ns = avr_cycles_to_nsec(avr, avr->cycle + how_long);
        clock_gettime(CLOCK_MONOTONIC_RAW, &tp);
        uint64_t runtime_ns = (tp.tv_sec*1000000000+tp.tv_nsec) - mod_s.start_time_ns;
        printf("runtime_ns: %" PRIu64 " deadline_ns: %" PRIu64 "\n", runtime_ns, deadline_ns);
        if (runtime_ns >= deadline_ns) {
                return;
        }

        uint64_t sleep_us = (deadline_ns - runtime_ns)/1000;
        usleep(sleep_us);
        return;
}

@dxxb
Copy link
Owner

dxxb commented Apr 11, 2018

Need to double check under which conditions avr_callback_sleep_sync() is called currently but I suspect for some reason the game is not letting the CPU idle often so the sleep function does not get called.

@jessemillar
Copy link
Author

...a pause of about two seconds after hitting "play" in my game's menu before it actually starts the game. I'm not sure why that pause happens since it doesn't occur on Arduboy hardware or in ProjectABE...

I just realized that I'm calling arduboy.initRandomSeed() when the user presses "PLAY". initRandomSeed() reads from an IO pin which the simulator probably doesn't have access too which would potentially explain the delay.

@dlancer
Copy link

dlancer commented Oct 9, 2018

@dxxb as I see sim-arduboy do not have any ADC related code.
I assume simulation for ADC with floating pin is possible?
We can feed ADC port from system random or if this is too slow, just use some pseudo random generator.

@dxxb
Copy link
Owner

dxxb commented Oct 9, 2018

I believe libasimavr supports simulating the ADC. If so, it would be a matter of hooking sim-arduboy into it and feeding the ADC result with some random source.

@dlancer
Copy link

dlancer commented Oct 14, 2018

I added PR #12 with adc feeding. It pass my tests,but unfortunately delay on start in the Crates game is not related for initRandomSeed()...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants