High speed screen updates for oscilloscope

Jondroid

Member
Licensed User
Longtime User
Dear all,

First a big thank you to Erel. I really love B4A, thanks for the good work! :sign0098:

Now, I'm trying to build an oscilloscope (similar to the IOIOscope elsewhere in this forum) but I want to have the best performance for screen updates. In order to test this I wrote a simple application which just alternates between a line and a sine. Also, I measure the time needed for those updates.
On my phone (800MHz, single core) I get about 120-130 ms for those two updates. This appears on the screen obviously not smooth but is flickering.

The question now is, if my approach in the attached file is valid or if there is another method to make high speed drawing possible.

The second question is: video files will obviously play on all devices with the same speed and one will have some 20-30 screen updates per second. Is there a way to draw my lines in a video buffer and then play this video buffer?

Many thanks in advance,
Jon
 

Attachments

  • scope-v3.zip
    4.3 KB · Views: 481

Jondroid

Member
Licensed User
Longtime User
Hi Erel,
thanks for your comments. Yes, I understand that instead of using the while loop it is more common to use a timer. And I've tried this in fact before using this approach. But the screen update rate was not higher.
Regarding your second comment, yes, I've seen (and used in a different program) the Activity.Invalidate2 command. But the very purpose of this program is to see what the maximum "full-screen" refresh is and obviously in that case I should use Invalidate.

Any pointers to how to get video mode screen updates working (or a work around for it) would be highly appreciated. I mean, it's obvious that android can do nice animations so I believe that there must be a way to get this somehow to work.

I understand that my problem might seem very specific but I believe that a solution can be very useful in many other applications as well.

Looking forward to any suggestions.
 
Upvote 0

Jondroid

Member
Licensed User
Longtime User
previous version 2 with timer

attached is the previous version, which is using a timer. The seekbar allows to control the timer variable. The number to the right displays the timer1 value in ms and the left number (white) the time consumed to plot the sine and the green line.

On my phone there is no way that I get the left number to a value below 100ms. Which is not faster than the solution posted previously.
 

Attachments

  • scope-v2_timer.zip
    4.4 KB · Views: 394
Upvote 0

Jondroid

Member
Licensed User
Longtime User
I'm testing on a real device. How did you measure the 4ms? Did you use the v2 or v3? Or did you modify the code yourself?

The funny thing is that with v2 (using the timers) I have about 100ms and sometimes it goes up to 200ms or even 300ms.

A friend has the Samsung Galaxy S2 with two cores and 1.6 GHz and he reports that he has about 25ms (for the two updates with v3) and 33ms for the two updates with v2.

So obviously I would be very much interested to know which device you use.

Is there maybe a way to use OpenGL or another hardware acceleration to make the screen update faster?

I've looked into your break-out game (Arkanoid) and sure, in that case partial redraw is fine but what should I do if I want/ have to update the full screen very fast (e.g. like when having a video game or so).
 
Upvote 0

vb1992

Well-Known Member
Licensed User
Longtime User
Erel is there any speed performance by using colors.transparent
to clear the display?

Rect1.Initialize(0dip, 0dip, 800dip, 480dip)'clear display
Canvas1.DrawRect(Rect1, Colors.black, True, 5dip)

vs

Rect1.Initialize(0dip, 0dip, 800dip, 480dip)'clear display
Canvas1.DrawRect(Rect1, Colors.Transparent, True, 5dip)
 
Upvote 0

Jondroid

Member
Licensed User
Longtime User
Hi vb1992,
I've tried your suggestion but I don't see a significant improvement. But thanks for the suggestion.
Jon
 
Upvote 0

DarkMann

Member
Licensed User
Longtime User
Hi,

I think your time calculation is flawed.

In your timer-enabled code, modify the commented line to this to see what I mean.

B4X:
'zeit2=DateTime.Now

replace with

B4X:
zeit1=DateTime.Now

This will display the time for each frame - half a cycle, but it still includes the length of the timer delay - you could subtract this from your displayed result I suppose.

On my 800MHz Acer Liquid I get around 10 to 15ms per draw, I suppose it's nearer to average of 20ms for the full cycle.

Your timing loop is counting the time to draw, plus the timer delay then the time to draw again. Thats one complete cycle, two draw events and the timer delay in between. This obviously doesn't make it easy to find the drawing speed. If I set the delay to anything more than 20ms then I get both label1 and label2 appearing as 20. any delay less than 20 and i get the lower figures.

By modern standards 800MHz is a slow phone and I am only on Android 2.2. If Erel used a newer one than me I would expect it to be much quicker.

Hope that helps,

David
 
Upvote 0

Jondroid

Member
Licensed User
Longtime User
Hi David,
thank you very much for your detailed reply. Yes, I agree that the displayed time should be halfed. However, I don't think that one can just subtract the timer as I believe the system is pretty occupied for a few ms to redraw the screen. That was the very point why I rewrote the thing not to use timers but to do it explicitly. E.g. an infinity loop (see my first post with v. 3) There I don't use any timers but only do twice the Doevents and Activity.Invalidate. This should give the maximum speed I would believe. Sure, one has to do half of it as we do two screen updates in that loop but that figure doesn't go to less than 100ms (which means 50ms per full screen refresh) and my friends 33ms (e.g. 17ms per one screen refresh).
I would be interested to know what you get on your 800 MHz phone with the program posted in the first post.
 
Upvote 0

Jondroid

Member
Licensed User
Longtime User
vb1922, thanks for the video and the link. I will test it on my phone. For some reason I wasn't yet able to install your apk from post #9, but will try later again. Cheers.
 
Upvote 0

Jondroid

Member
Licensed User
Longtime User
vb1992, thanks for the zip and the brownian motion thing. The Brownian motion program works with about 2-3 screen updates per second. Now the funny thing is that there was this demo in the google sdk (i will look it up in a minute) which had something similar (but with images) and it was really smooth and fast on my device.

With regard to the moving sine I get about 40-50 (for the left label). Lower values than this are not possible on my device.

But, as I said, I will look up the google code I tested the other day so that we can compare it with eachother.
 
Upvote 0

Gigatron

Member
Licensed User
Longtime User
I have played with your source

In this source there is no flicker efect visible..
I used panel instead activity drawing.. etc...

Sorry for my bad english .

B4X:
Sub Process_Globals
   Dim zeit1,zeit2 As Long
   
End Sub
Sub Globals

   Dim volts As Double
   Dim Timer1 As Timer
   Dim Canvas1 As Canvas
   Dim x,y,hx(),hy() As Int
   
   Dim btnLED As ToggleButton
   Dim Label1 As Label
   Dim i As Int
   Dim d As Int
   Dim lastvalue As Double
   Dim SeekBar1 As SeekBar
   Dim Label2 As Label
      
   Dim Panel1 As Panel
   Dim Rect1 As Rect
        
        Dim factor as Int
      
End Sub

Sub Activity_Create(FirstTime As Boolean)
 
      Activity.LoadLayout("Main")
      Canvas1.Initialize(Panel1)
       
      d=1000
      Timer1.Initialize("Timer1", d)
      lastvalue=240
      Timer1.Enabled=True
      i=0
      Rect1.Initialize(0dip, 0dip, 800dip, 480dip)'clear display
    
End Sub

Sub Activity_Resume
End Sub

Sub Activity_Pause (UserClosed As Boolean)
End Sub


Sub Timer1_Tick
      label1.Text=DateTime.Now - zeit1 
      zeit1=DateTime.Now
      draw_Oscillator
End Sub   

Sub draw_Oscillator
   
      Canvas1.DrawRect(Rect1, Colors.Black, True, 5dip)
      
      For x=0 To 800 Step 5
          volts=Sin(x/800*3*2*3.14159)
         y = 180-(volts*factor)'scale for scope display   scale factor=variable 
         canvas1.DrawLine(x-5,lastvalue,x,y,Colors.Yellow,5dip)
         lastvalue=y
      Next   
                factor=factor+1

                if factor>150 then factor=1  ' limit scale factor to 150 .... and restart with 1

         canvas1.DrawLine(0,180,800,180,Colors.green,5dip)
      
    panel1.Invalidate 
End Sub

Sub SeekBar1_ValueChanged (Value As Int, UserChanged As Boolean)
   d=Value
   Timer1.Interval=d
   Label2.Text=d
End Sub

' Factor variable added .. Now it's running at 60fps without flickering :) if time tick under 30 milliseconds



Later
 
Last edited:
Upvote 0

Jondroid

Member
Licensed User
Longtime User
Hi Gigatron,
thanks a lot for your work. I would like to test it but I get some Java Exceptions when running on the device. Could you please export the project as zip and upload that?
Many thanks,
Jon
 
Upvote 0

klaus

Expert
Licensed User
Longtime User
Attached you have your version 3 modified:
Mean time on my Nexus One (800 * 480 * 240) ~ 7 - 8 ms
In the Emulator (480 * 320 * 160) ~20 22 ms

I removed the second screen refresh and the two DoEvents.
Moved all identical calculations outsides the loops.
Replaced 800dip and 480dip by 100%x and 100%y.

Best regards.
 

Attachments

  • scope-v31.zip
    4.3 KB · Views: 347
Upvote 0

Gigatron

Member
Licensed User
Longtime User
Hi Gigatron,
thanks a lot for your work. I would like to test it but I get some Java Exceptions when running on the device. Could you please export the project as zip and upload that?
Many thanks,
Jon

Ok, here the source code ..
 

Attachments

  • Oscillator.zip
    4.4 KB · Views: 394
Upvote 0
Top