Welcome to the new FlexRadio Community! Please review the new Community Rules and other important new Community information on the Message Board.
If you are having a problem, please refer to the product documentation or check the Help Center for known solutions.
Need technical support from FlexRadio? It's as simple as Creating a HelpDesk ticket.

Android App

Options
1568101115

Comments

  • Walt - KZ1F
    Walt - KZ1F Member ✭✭
    edited November 2016
    Options
    With that, as this is really William's thread, I don't want to hijack it. Sorry William. When I create my own thread it will be show and tell time. But I will not commingle it with William's.
  • Walt - KZ1F
    Walt - KZ1F Member ✭✭
    edited November 2016
    Options
    William, that looks incredible! How do you do the video? Do you put everything up on YouTube first. I have yet to look up how to do that.
  • W4WHL
    W4WHL Member ✭✭
    edited July 2016
    Options
    yes I put it on youtube.

     I still have scaling issues with the  chart.  The data coming in is opposite of what I want to graph.  The stronger the signal the lower the number.  This sounds good in theory based on 0,0 upper left corner.  But autoscaling the chart based on this causes the noise floor to jump around.  Its hard to explain, but imagine a flat chart scale vs an active chart with many strong signals.  Scaling on signal range causes scaling values to alternate rapidly.  Since the noise floor is the higher value, the noise floor bounces with scaling changes.  This is very annoying.

    I would prefer the noise floor to be the constant, and scaling to only affect the signal peaks.  Currently I'm setting the scale based on the min value.  Since the minimum value average is fairly consistent (noise floor), the scale does not change much.  However then the graph does not scale for strong or weak signals.

    I am not 100% sure how to solve this, but I have a few ideas to experiment with.  I would like the panadapter to scale automatically  with the signals that are present. What I would like to do is have the noise floor be the min value (y~0) and then have the chart scale automatically base on present signal strengths.  On a small screen, I

    Not sure if any of this rambling makes any since to anyone :)  Its really hard for me to explain. 

    William
  • Walt - KZ1F
    Walt - KZ1F Member ✭✭
    edited November 2016
    Options
    But when last we spoke the opposite was occurring and the numbers were correct, relative to where 0,0 was supposed to be. Ah, you eliminated the drawing package, right? So now are you drawing straight to the canvas, e.g. drawLines(float[] pts...)?
    Are you drawing that in the worker thread? It should autoscale, this is why as you + the SSDR graph you don't see signals going off the top of the view, you'll also notice the db scale on the right side changes too. Maybe explain what you are doing to scale. The values coming back are based on the dimensions of the view, if max(Y) is 20 then it won't send a value back greater than 20 and the noise floor would likely be in the low single digits. If, on SSDR, you modify the pan size while it is displaying it, too, will jump around, similarly if you slide the x axis, it will jump around then too.

    Here is precisely how I used to solve that, yes, it is/was common in the Windows and OS/2 days. so you are about to update a view, right before you update it you disable it, update, then re-enable.  In Android land prior to the drawLines() lock the canvas. After you are done, unlockCanvasAndPost(). I think that should do it.
  • W4WHL
    W4WHL Member ✭✭
    edited July 2016
    Options
    Doh!  I feel kinda ****, I found my issue that was causing all my scaling problems.  My command that was creating the panadapter was wrong.  When creating the panadapter, the program gets the height of the canvas, and sets the y value.  However I had an silly error in the code.  So I was creating the panadapter the wrong size.  I have yet to test this, but I'm pretty sure that was my issue.

    Yes I'm using the drawline to canvas.  I'm also using runnable / view.post runnable.  To make this more clear.  There is an asynctask that does the UDP and dumps the data in a array queue.  Then there is a runnable that takes the data from the queue, does some math, then a view.post (runnable) that actually does the drawing.  As I understand it, you have to draw from UI thread.

    William
  • Walt - KZ1F
    Walt - KZ1F Member ✭✭
    edited November 2016
    Options
    You still want to lock the canvas (lockCanvas())when you draw and then unLockCanvasAndPost() when you are done. No, you don't want to do that, you do the canvas work in the service thread then post to do the physical drawing. Look up SurfaceView...or, you can wait until you see mine.
  • Walt - KZ1F
    Walt - KZ1F Member ✭✭
    edited November 2016
    Options
    I am not sure what just happened. You want to:
    1) be certain to lockCanvas() before you draw and unlockCanvasAndPost after.
    2) use SurfaceView. <- look it up or you can see the results when you see mine.

    Weird, when I posted this second one, the first one hadn't yet drawn.
  • W4WHL
    W4WHL Member ✭✭
    edited July 2016
    Options
    I will research this, thanks for the pointer.

    On another note, i solved all my scaling issues.  I know its been said several times, but my thick skull never soaked it in.  I need to manipulate the panadapter via the radio.  Adjusting the min/max dbm etc is what I needed to do and just let my app draw.  I was trying to manipulate and scale in my app, but this was wrong.  I need to add ui controls to my app to allow tweaking these parameters via the radio.

    I will look into implementing the surface holder as you suggested.  Just one question.  I assume by implementing surface, I can do all this inside a worker thread?

    Thanks

    William
  • Walt - KZ1F
    Walt - KZ1F Member ✭✭
    edited November 2016
    Options
    That is what one is supposed to do. This was established as a 'best practice' back in the 80's
  • W4WHL
    W4WHL Member ✭✭
    edited July 2016
    Options
    Walt,

    I did a quick test with this, it works, however it is very SLOW.  Not sure why.

    Runnable drawpan = new Runnable() {
                    public void run() {
                        Canvas canvas = Panholder.lockCanvas();
                        canvas.drawColor(0, PorterDuff.Mode.CLEAR);
                        int w = canvas.getWidth();
                        int h = canvas.getHeight();
                        scale = h/panY;
                        float xInc = (float) w / (fftint.length - 1);
                        paint.setColor(Color.BLUE);
                        canvas.drawLine(w / 2, 0, w / 2, h, paint);
                        paint.setColor(Color.GREEN);
                        for (
                                int i = 0;
                                i < fftint.length - 2; i++)

                        {
                            if (fftint[i] != 0) {
                                float x1 = i * xInc;
                                float y1 = scale * fftint[i];
                                float x2 = (i++) * xInc;
                                float y2 = scale * fftint[i + 1];
                                canvas.drawLine(x1, y1, x2, y2, paint);

                            }
                        }


                        Panholder.unlockCanvasAndPost(canvas);
                    }


    Any ideas why its slow?
  • Walt - KZ1F
    Walt - KZ1F Member ✭✭
    edited November 2016
    Options
    Did you remove all your sleeps? Did you remove your progress indicators? Did you remove all the other things in your UI thread. Try removing the " canvas.drawColor(0, PorterDuff.Mode.CLEAR);" I don't know why it's there and pretty sure you don't want it. The default is OVER and that is what you want.  Also, make sure you aren't trying to draw the entire screen, verify your x and y limits.

    Also, I've been meaning to tell you, Google has a very thorough tutorial on Android programming, from basics to graphics to communications etc. You might want to start at A and work your way through it. 

    The other thing is, it's is really much much easier to test a segment in isolation. It other words, write a **** app that all it does is draw the spectrum. Set everything up as if the only view that exists is the spectrum display. Make it some reasonable size, like 600x200. Then you can play with different drawing scenarios, like in the UI thread in a separate thread etc etc. The other thing is hidden costs. It is expensive to start a thread. Before someone yells at me, yes, there are more expensive things but creating a new thread frequently is expensive. Start an ExecutorService at the outset with 5 threads. Then you call simply issue a
    ExecutorService executorService = Executors.newFixedThreadPool(5);

    DrawPan foo = new DrawPan(...);
    executorService.execute(foo);

    If, for every bin you are creating a new thread that is a lot of new thread creates. Also, AsyncTasks use CGroup, which is a Linux control group. When one defines a cgroup they can apportion resources to it, for instance, that cgroup can only take 10% of the CPU.

    But, again, if you have a separate app that all it does is draw a spectrum display you can play with different dispatch mechanisms in isolation from the main whole full blown control surface.

    Ah, and then simply test it in the virtual device under Android Studio.
  • Walt - KZ1F
    Walt - KZ1F Member ✭✭
    edited November 2016
    Options
    The thing about the ExecutorService is it implements Leader-Follower pattern. Once you create the service those 5 threads are started and warmed up and just waiting for something to do. If a thread terminates unexpectedly, the runtime replaces it, such that, in this case, you will always have 5 available threads.
    You could add the following as the first statement of drawpan.
    Thread.currentThread().setPriority(Thread.NORM_PRIORITY - 1); // set priority just below UI thread.

    But play with it. Get a feel for how these things work.
  • Walt - KZ1F
    Walt - KZ1F Member ✭✭
    edited November 2016
    Options
    For threads that ONLY read UDP data from the radio and populates the linked blocking queue, that should be NORM_Priority+1, as it should run higher than the drawing thread. What you absolutely do not want is a CPU bound thread running at a higher priority than the ui thread.
  • W4WHL
    W4WHL Member ✭✭
    edited July 2016
    Options
    Thanks for the input, I will play with it!  You gave me a ton to work through, and I appreciate it.  Time is not on my side lately, but I will play when I get the time.

    Also I found a sleep I had in there for testing, this was the main cause to the slowdown.  Its currently working real well.  No UI hangs at all.  But I agree, I have tons to learn, as I add more stuff, I need to better understand threading and its impacts.

    Regards,

    William
  • W4WHL
    W4WHL Member ✭✭
    edited July 2016
    Options
    Here is how it looks using surfaceview.  Seems to be more responsive.


    https://www.youtube.com/watch?v=Dm8ukwQuPU0

  • Walt - KZ1F
    Walt - KZ1F Member ✭✭
    edited November 2016
    Options
    No doubt William, that is cool. Yes, it is a slow process, but with the slowness comes an infinite number of eureka moments (moments of absolute joy). So, absolutely, do not despair. I understand I am throwing an awful lot of advanced stuff at you, but do things like pull of the animated drawing sections to little activity fragments of their own and experiment, at the end of the day, that's how we all learn. Non of us were born being experts at any of this. It takes time and patience and most of all, it takes desire.
  • Ken - NM9P
    Ken - NM9P Member ✭✭✭
    edited December 2016
    Options
    William, I'm impressed at how much you are learning, and how quickly!  You are WAY past my level!

    I hope to get back to the MIDI DJ Controller sometime soon, but I have work projects and antenna projects to finish first, so that project, and the learning associated with it, is on hold for now.

    Ken - NM9P
  • W4WHL
    W4WHL Member ✭✭
    edited November 2016
    Options
    here is a little demo of tuning around with panadapter. 


    https://www.youtube.com/watch?v=LiGZ1wOGnhU

  • Walt - KZ1F
    Walt - KZ1F Member ✭✭
    edited November 2016
    Options
    Hi WIlliam, in reference to your comment on the SSDR EULA, that deals with the binary and then the API. API stands for Application Program Interface. That is, the name of the public routines within FlexLib as have been exposed. The GNU license deals with people who write their own program on top of the exposed API such they are still using FlexLib.dll as distributed underneath their program. This would be DDUtil, HRD, etc. Somewhere buried in DDUtil and HRD subdirs is the GNU license that governs FlexRadio API. In this case, a derived work would be a program that ultimately makes calls in their code as described by Eric here: https://community.flexradio.com/flexradio/topics/first_steps_with_flexlib.
    Neither you, Stu, nor I are using FlexLib.
  • W4WHL
    W4WHL Member ✭✭
    edited July 2016
    Options
    Thanks!  Good to know. 

    William
  • Walt - KZ1F
    Walt - KZ1F Member ✭✭
    edited November 2016
    Options
    William, are you processing the OpusStream yet or was the audio from the speaker plugged into the radio itself?
  • W4WHL
    W4WHL Member ✭✭
    edited July 2016
    Options
    I wish. Yes it's lineout William
  • James Whiteway
    edited May 2015
    Options
    Just gets better and better. james
  • Walt - KZ1F
    Walt - KZ1F Member ✭✭
    edited November 2016
    Options
    I didn't mention this but I really like the little red dot on the tuner knob plus the reflection off the knob rim. Very nice indeed!
  • W4WHL
    W4WHL Member ✭✭
    edited July 2016
    Options
    The knob was a freeware photoshop I found online.  So I can't take credit for the design :)  However I agree, it is a very cool design.

    It is from a freeware JS source  http://dmonzon.com/freebies/fully-functioning-jog-wheel-a-file-for-app-designers-and-developers/

    But I only used the photoshop, as the source was in javascript.

    William

  • Walt - KZ1F
    Walt - KZ1F Member ✭✭
    edited November 2016
    Options
    The knobs are definitely very realistic looking but they do take up a lot of real estate.
    All versions of S(er)SDR will look remarkably like SSDR. There will, however, be more views available and the controls will be 3D.
  • W4WHL
    W4WHL Member ✭✭
    edited November 2016
    Options
    I did some playing around with waterfall stream.  However I am not having any luck.  I tried BitmapFactory.decodeByteArray to decode the data.  But it always returns null.

    I was able to capture buffer and **** the header off the waterfall packets, but no clue how to decode the data.  I was hoping I just could decode it directly to a bitmap, but this does not seem to work.

    Is there any documentation on the waterfall data?  Steve your documentation explaining FFT was very helpful, do you have any similar guidance for the waterfall data?

    William

  • Walt - KZ1F
    Walt - KZ1F Member ✭✭
    edited November 2016
    Options
    try creating an InputStream from the short[] and BitmapFactory.decodeStream().
    Make sure you actually are processing the tiles correctly.
    You'll need to look at Waterfall.cs and WaterfallTile.cs and VitaWaterfallPacket.cs
  • Bob G   W1GLV
    Bob G W1GLV Member ✭✭
    edited June 2020
    Options
    Bill, fantastic app. Works like a charm. Love it tried it on my Nexus 7.
  • Javier, KC2QII
    Javier, KC2QII Member ✭✭
    edited June 2016
    Options
    Bob, William,

      Where do  I find the latest android apk file?  I just got a hold of a recycled Nexus 7 (aka, hand me down) and would like to give it a try.

    73 Javier
    kC2QII

Leave a Comment

Rich Text Editor. To edit a paragraph's style, hit tab to get to the paragraph menu. From there you will be able to pick one style. Nothing defaults to paragraph. An inline formatting menu will show up when you select text. Hit tab to get into that menu. Some elements, such as rich link embeds, images, loading indicators, and error messages may get inserted into the editor. You may navigate to these using the arrow keys inside of the editor and delete them with the delete or backspace key.