Timing issues

Hi All, I am having major “bug” issues within an app I am developing which simulates the operation of a cpu for educational purposes. The bugs are all around asynchronous delays in performWithDelay (and also to a certain extent transition.to.

The core of the app is a loop which fetches instructions, decodes them and executes them (just like a CPU!!). To be usable the loop needs to be quite a lot slower than Corona lua is capable of, otherwise the program flies by in a few microseconds and the user sees the final result but not any of the intermediate stages, negating the point of the app.

What I would like to do (tried and failed) is a loop like this (pseudocode)

repeat

   get instruction

   decode instruction

   execute instruction

until instruction is stop

there would/could be up to 100 iterations of the loop as the “memory” has 100 locations.

to slow it down I need to add some delays (using performWithDelay) for every section

so

repeat

  performWithDelay(300,get instruction)

  performWithDelay (300,decode instruction)

  performWithDelay (300, execute instruction)

until instruction = stop

this doesn’t work for two reasons:

  1. as the delays are asynchronous they get fired much faster than it looks, in fact almost instantaneously and all finishing at about the same time too.

  2. also because of this the final condition seems to never get triggered and it ends up in an infinite loop.

I ended up with the following

for i= 0,99 do

   timer=performWithDelay (200*i,singlestep)

end

then singlestep is a routine that looks like this

function singlestep()

if notfinished then

   fetch instruction

   execute instruction

end

end

This all works ok, but there are up to 100 simultaneous timers running and when i gets to about 50 the timers have delays up to 50*200 = 5 seconds. Again this worked fine. but the time for the program run was either too slow or too quick depending on what the user wanted to see and I needed to add a variable called runspeed, which could be altered with a widget between 1-5

the code became:

for i = 0,99 do

   timer = performWithDelay(100*(6-runspeed)*i, singlestep)

end

this gives variable results, sometimes the loop goes slowly, then with the same runspeed setting it will go fast, then sometimes somewhere in the middle.

Any ideas, either a) How to tidy the whole thing up to fire of sequential timers without my workaround or b) how to make my runspeed work.

thanks

Martin
 

May I ask what you are emulating? I am dabbling with an emulation project when I have some free time to kill :slight_smile:

Hi Danny, it is emulating a model von Neumann architecture. All done, except the timing issue makes the loop and visual experience very amateur and in practice I take the runspeed function out which isn’t right from an educational perspective.

Martin

Hi Danny,

do have a look at the pr stuff on my website, www.kilkiesoft.com, the app is called Babbage, for obvious reasons.

this will be version 4.

version 1 was in Fortran on an IBM mainframe, then TurboPascal, then Visual Basic (all in the 1980s) now the new app in lua/ Corona.

Your loop construct is not going to work the way you think it will.  When you call timer.performWithDelay() you’re just queuing up events that happen after some delay.

What you really want is a repeating timer, more like:

timer.performWithDelay(1000, doMyLoopParts, 0)

That will ever second run the function doMyLoopParts indefinitely.  Then doMyLoopParts could look like:

local function doMyLoopParts()

  performWithDelay(1,get instruction)

  performWithDelay (334,decode instruction)

  performWithDelay (667, execute instruction)

end

You would in effect get a step triggered every 333ms (I’m making up numbers here, you would need to have to figure out your timing)

The other way to do timing things is to use an enterFrame Runtime listener which fires every 1/30th of a second (or 1/60th if your fps is set to 60).  You could use a counter to control how fast you execute an instruction.  Corona SDK does not have the concept of a sleep() or a delay() type function.

Rob

HI again Rob, to the rescue. I see what you mean, and yes I do want a delay and it is much more elegant, but how would I break out of the loop?

Also how would I then alter the speed in the loop, could I do (also how to break the loop?)

timer0 = performWithDelay(1000,domyloopparts,0)

local function doMyLoopParts()

   timer1=performWithDelay (1* (6-runspeed), get instruction)

  timer2 =  performwithDelay (300*(6-runspeed),decode instruction)

   timer 3 = performWithDelay (600*(6-runspeed),execute instruction)

   if instruction = stop then timer0.cancel()

end

tried that, it all works great, timing is spot on, until I try to break out of the infinite loop with timer.cancel(timer0)

I get error -  File ?  “attempt to index a nil value”

Ah, final error was just a bug, I must have leant on the keyboard and put a few stray characters in, sorted. all runs tickety boo now. Great solution Rob. Also solves all of my other timing issues (except telling jokes) as I now understand how to throw those delays in.

thanks

Martin

Glad to help

Rob

May I ask what you are emulating? I am dabbling with an emulation project when I have some free time to kill :slight_smile:

Hi Danny, it is emulating a model von Neumann architecture. All done, except the timing issue makes the loop and visual experience very amateur and in practice I take the runspeed function out which isn’t right from an educational perspective.

Martin

Hi Danny,

do have a look at the pr stuff on my website, www.kilkiesoft.com, the app is called Babbage, for obvious reasons.

this will be version 4.

version 1 was in Fortran on an IBM mainframe, then TurboPascal, then Visual Basic (all in the 1980s) now the new app in lua/ Corona.

Your loop construct is not going to work the way you think it will.  When you call timer.performWithDelay() you’re just queuing up events that happen after some delay.

What you really want is a repeating timer, more like:

timer.performWithDelay(1000, doMyLoopParts, 0)

That will ever second run the function doMyLoopParts indefinitely.  Then doMyLoopParts could look like:

local function doMyLoopParts()

  performWithDelay(1,get instruction)

  performWithDelay (334,decode instruction)

  performWithDelay (667, execute instruction)

end

You would in effect get a step triggered every 333ms (I’m making up numbers here, you would need to have to figure out your timing)

The other way to do timing things is to use an enterFrame Runtime listener which fires every 1/30th of a second (or 1/60th if your fps is set to 60).  You could use a counter to control how fast you execute an instruction.  Corona SDK does not have the concept of a sleep() or a delay() type function.

Rob

HI again Rob, to the rescue. I see what you mean, and yes I do want a delay and it is much more elegant, but how would I break out of the loop?

Also how would I then alter the speed in the loop, could I do (also how to break the loop?)

timer0 = performWithDelay(1000,domyloopparts,0)

local function doMyLoopParts()

   timer1=performWithDelay (1* (6-runspeed), get instruction)

  timer2 =  performwithDelay (300*(6-runspeed),decode instruction)

   timer 3 = performWithDelay (600*(6-runspeed),execute instruction)

   if instruction = stop then timer0.cancel()

end

tried that, it all works great, timing is spot on, until I try to break out of the infinite loop with timer.cancel(timer0)

I get error -  File ?  “attempt to index a nil value”

Ah, final error was just a bug, I must have leant on the keyboard and put a few stray characters in, sorted. all runs tickety boo now. Great solution Rob. Also solves all of my other timing issues (except telling jokes) as I now understand how to throw those delays in.

thanks

Martin

Glad to help

Rob