Thank you. Let's see. Thank you. Come on. Oh, you got a shiny surface here. I'm old fashioned. I like to use a mouse. I'd like to thank Marcus for having me here. I just wanted to see what that looked like. Okay. And I'm going to run a bash grip right now. Okay. So this should be fairly automated. Oh, well. Okay. Hi, I'm Lance. And I like to build stuff and quick streams, software I've built. It's a new flow graph framework. Okay. Okay. What is quick stream? The biggest part of it is it's an application programming library, application programming interface library. Okay, not like the APIs you hear about on the web, I get, but they seem to change the word API to have a different meaning than what I'm used to. So that's the core runtime library. It's the biggest part of it. Okay. And with that library, we built, oh, this isn't going to work so good on that, is it? I'll come over here. We built blocks, similar to new radio blocks. Okay. There are simple blocks that do computation. You connect the simple blocks together and then you're going to get flow graph. And also hierarchical blocks, I call them super blocks. New radio calls them here blocks. I like the word super. Okay. There are two programs that come with it. A command line program and a graphical user program. Both these programs do the same thing. I'm going to write the command line program options first and then I integrate them into the GUI because I need tests to make sure my code works. And so the command line interface is really nice for doing the tests that checks that my code is correct. Okay. And it's all written in C with very few required dependencies. Okay. Oh, I'll just jump right into it here. Okay. So I click on that guy there and I didn't click right so I got to go back. Click this. Okay. Okay. How does that look? Okay. It's a bash shell and this is the demo for the command line program. Okay. I type in QUI. How many people here have done command line programming? Good. Okay. So this is, it has a complete, well not as complete as I could think of if you have more things you want in bash completion, I'll code them in. So I can hit tab a few times and I see there are four programs installed from the quickstream installation. Two of them I'm going to go over and demo and then the others came about from necessity and I want to have time to go into those. So I'm going to hit space and hit tab a few more times and we can see what the options are for this command line program. There are, let me hit another dash there. Okay. And hit tab again. I like that long options better. I always use the long options in my test programs too because the shorter options do the same thing but they're limited to one character so if I change an interface then it breaks all my tests and so on. But the long option names are probably not going to change their name given they'll have the ability to stay unique because they're a long character set. Okay. So I want to run this program then with some kind of option. Okay. So it has a semi decent help in it and it's a long help dash dash help option and I'm going to pipe it to the pager. Bless. And so it looks something like a man page. Let's see how that came out pretty good. All right. So we can scroll through the man page and there you have it. You're used to looking at this kind of stuff but so it's there. It's documented this much at this point. That'll turn into a man page of course and it will be auto generated when you build the software and install it from this text which is actually in a separate program. It launches a separate program because there's too much too many characters in this program. I thought it would get bigger. I wanted to keep it small so it launches the help separately from another program which you don't have to worry about. Okay. As you're using it. Okay. Let me quit this. So this is bash bash has this wonderful thing called history. We all know about and I've preloaded a history in here because I would spend at least half an hour trying to type in one command line to get a flow graph running. So instead of sitting here for dittling on my keyboard. Yeah, maybe wouldn't take a half an hour to type in that command. With the bash completion you can find the blocks in a list of blocks that come up when you hit the tab. So it has tab file completion on the block files themselves. Okay. And I was going to show that but I skipped it because I want to make sure I got enough time here. So I've got to run this thing, right? Okay. So there is running. Okay. So what did I just do? So this was the display command that was in the command line. You can run the display command as many times as you want. You could load a block, display it, then load another block, display it again. Then you see two blocks then on the second display that you show. And then you keep on adding to it. This is really too much to look at in a presentation like this. But it shows the flow graph. The blue lines are what I call control parameters. And the red lines, there's only two red lines. They are stream data, similar to GNU radios stream data. Okay. Let me just cue that thing. Everybody is familiar with image magic? Okay. And this is from the graph viz program that uses this dot file format. That's really easy to print out a graph. And it displays it for you magically. And my formatting kind of stinks there. I've got to get better at dot programming. You get a better display than that. It gives you all the things you can configure and connect in the block in that mess there. Okay. So we don't need to be concerned with that right now. Okay. So this is this one program I'm running from that command line. And we can see it's using the GNU radio QT GUI sync, which has this nice thing. I like the constellation plot. Let's see if I can pick this up. Yeah, I can saturate it. Yeah. Quickstream writing house has some GUIs there. One GUI per block where a GUI would be a slider here. Like I can change the frequency and the gain of this thing. I can maybe desaturate that. Yeah, there you go. I just smudged it. I can also kill that and then run it again with the GUI. Okay. So what that's doing is I have a block that is a Unix pipe block. And then Unix has an option to say what program to run to pipe to. And so it pipes to a radio, a Python script in this case, which I pre-constructed obviously. Okay. Let me kill this and move on to another slide. Okay, so ctrl-C again, ctrl-D, and back to the slides. All right, so that was okay. So why on earth would I do such a thing? I wanted to write blocks with one source file, one C file. Okay. And well, of course, you may have to make a make file or just at least having the top of the file, a compiler line, how to make the damn thing when you get there. That would be good for simple blocks. Of course, you can use many files to make these linked to other libraries. It doesn't care. Or I can make the blocks in C plus plus if I like. Kind of partial to C for some reason. Or for that matter, I could probably write blocks in Fortran. Fortran and C get along very well. Okay, like the linear algebra libraries, nobody wants to rewrite those. Those things are amazing. They'll agglise the matrix and you try to get all ones and it's like one point, you know, whoever wrote that code is, you know, oh, you wrote it? So, oh, so another feature is that workflow, when you're building whatever it is you're building through your end user application, Quickstream GUI and Quickstream command line both output a block. The block is itself your end user application. That block can be reloaded back into Quickstream GUI or Quickstream command line. They both do the same thing. And so we have a cyclic workflow then. So we output stuff, use stuff, that same stuff we can reload back in, even if you edit it. Because the runtime library knows about what that stuff is and when it loads it up it's just loading up a dynamic shared object and it looks for the symbols that are in it. As long as you didn't like change the names of all your functions and stuff, it's still going to be able to find all those functions and be able to call them when it reloads it. OK, so workflow being cyclic, typical use case GNU radio is you output a Python script from GNU radio companion or you output C++ code that you compile. Once those files are output, they don't go back in. So that workflow is not cycled. In the typical use case of GNU radio companion. But if you were to output the hierarchical block, then you could have a cyclic workflow. And I think that could probably bleed back some benefit into the whole thing if you get that cyclic workflow in there. OK, so next feature we can assign threads to blocks on the fly. Well the flow graph is running while all the code is running, what have you. So and we can give it arbitrary thread numbers of thread pools and threads in those thread pools and say here I assign you to this block, I assign you to this block and so on. And I'll illustrate that in the next GUI demo. It also has a pass through buffers where your input and your output are the same size then you don't have to do a memory copy for them with the input to the output. And so you can get an optimization where you're eliminating all the memory copy in the block by using the pass through buffer. And that can go through the next block and the next block if they have the same amount of input as output. So it's not a decimator or what's the other thing? Yeah, it can't get bigger or smaller as it comes in and out. OK, and the flow graphs can have loops. OK, both the pass through buffers and flow graphs with loops, both of those things I think will be in GNU Radio 4.0, my guess. All right, assignment of threads on the fly, I don't know about that. Workflow being cyclic, I want to push that one too. So you'd have to take the hierarchy of blocks and be careful how you construct them such that it's easy for the user to then make their app from that. Yeah, I don't know. So there's a little work to be done on that too. But that was one of my biggest incentives is to get that cyclic workflow. All right, so let me move on to the next demo here. OK, so I just click on this thing here and now it launches the next demo. So this is QuickStream GUI. So you see I named it QuickStream. I should have named it QuickStream GUI, I don't know. I can have a vote here later. What should I call this program? OK, so on the side here, it looks something like GNU Radio Companion. And we have core blocks that are installed from in the package. And this is two actually, but these are test blocks. You wouldn't want to use test blocks in your end user application because what these test blocks do is nasty things like testing to see if a block can fail by, you know, you know, committing suicide and what have you. So you want to test all the different failure modes that are in your software in these test blocks. But it so happens that I'm going to use a test block to demonstrate today. So I can load, so we see I just did a right click on the block in this little directory tree here with files in it. These files are blocks. I can load it into the graph. Here, let me load it into the graph. There it is. Oh, yeah, so I named this one Fostum 2024. Now, that's not as interesting to look at as when I loaded it differently. OK, so let me make another tab. So that right now that's a flow graph that's running in that tab. All right, so let me load it again though, but I'm going to load it as a flattened super block. So boom, there it is. OK, this one's kind of a mess. I don't think you want to, I don't know. These blocks are translucent so you can see the connections easily in them. Because when you start making connections that loop around the blocks, like this one here has a connection going from its input to its output. OK, now what does this block do? OK, so it's got a sequence generator. That's generating just random bits. And I encode them as hex characters because I like to program on units where you always use ASCII text for everything, right? And then I put them through sequence checkers. And that's just testing out that the stream works. OK, and so I've tested this thing out by running this thing for days. I come back, yep, still running, yep. And it's checking every single bit that goes through these blocks to make sure that they're working. Then I can also check out the speed and what have you. See how it's doing the performance. Now, the button bar in this thing is pretty unusual, I guess, but it's got a translucent button bar here. It's got a run buttons here, I'll run it. So now you are in the matrix. OK, that's a little matrix converter block. It was just ASCII text before, but then I say, hey, this is going to be cool for this demo. There's also a halt button. OK, there's a difference between halt and run. A very, very good difference. So halt, right there, I just hit it, will stop all the threads from working. And the blocks don't know anything about it. As far as they're concerned, when you unhalt, it never halted. The blocks just don't know. All right, so run though will run the stream, the stream's in the photograph. The other inner block communication methods are already running. They never stop, like the control parameters. A control parameter, for example, so the stream lines are the red lines. A control parameter is like this purple line here. See, I'm jiggling this block up here. It's got a button on it that will hit a run, and I've got blocks that will run the flow graph for you in the flow graph. That's a little tricky because then it has to be very asynchronous, and it's got a sort of, hey, I request to run later sometime because I don't want to crap on myself because all these threads, others threads are running and I can't modify the data structures to get it to do that yet. But I'm going to have you do this later. So it has to be an asynchronous form of a program. It's kind of like if you've done JavaScript quite a bit, I was influenced quite a bit by JavaScript in the way they run things asynchronously all the time. Any blocking call is asynchronous usually unless you take, unless you do the synchronous one, which is probably not a great design. So let's see, there it is running. Now, I wanted to show Htop here, and Htop is nice. It's not so nice right now. Let me do a F4, and I'll type in bin, what do I type in so far? Bin slash QUI. Okay, now I have it searching for the quickstream GUI process, and we can see there are two threads working hard. Okay, this is unthrottled, so that's what you get. That's what I want in my case because I'm testing this thing, and I want to put it through as hard as I can because this is a test. Now, oops, why did I do that? Okay, what I have in the GUI here is I just clicked on the layout window. That's the top level window there where all the blocks are, and I've got a lot of options in there I can do. So it's a matter of right click mostly to find stuff in this quickstream GUI program. So right click. So I want to manage the thread pools. And so right now you see it says two, and there are two threads in this thread pool that are running this flow graph. And what I want to do is mess around with the number of threads that are running this thing. An easy way to do that is to create a new thread pool by clicking that button there, and then I want to tell it, I want to eight threads because I've got, supposedly, eight cores on this computer. And, you know, I'm not trying to do a performance test. And now, let's see, did I get the eight clicked in yet? No, I got to hit enter or something. There you go. No. Oh, so what's going on here? Why didn't it go? This is probably good that I screwed that up. I still have that thread pool there, and I haven't assigned blocks to it yet. Duh. Okay, so these kinds of duhs happen all the time. So let me just remove that thread pool, and now they have to migrate to the other thread pool. Oh, thank you. Okay, so now I have eight CPUs being used freely well, except not very well. The punchline here is that this has what's it called hyperthreading. So I can only expect 50% on each one. Okay, so let me go get to the next part of this demo, which is real quick. It's in the examples here, and I'm going to run, oops, not that one there. I need a new tab. Okay. Load as graph. This is the same example that I ran before from the command line. It's exactly the same, and I can run it here. And ta-da. Okay, and this has a GUI too. I could go to this control parameter here and set its value as it's running here and tell it it's true, and then it'll show up with the same widgets that we're showing before. And yeah, that's it. Let's see. So, I thought I'd leave two minutes for questions. Okay. So, you have a thread pool. That means your blocks are, you're choosing to run blocks on pools, and they're not like in radio 3 where they all have the same thread basically running on its own, deciding when to do the stuff on its own. Yes. If I want to set CPU affinity, then I need to make thread pools with one thread. And then I can control that CPU affinity. Yeah. So, the thread pool picks the next block to start the next slow project. They just end up in the same queues and shared in that thread queue, and then all the blocks are just going through that queue and saying, here's your job, I call them jobs, Micah. I mean, your terminology in GNU radio is different than mine in Quistream, sure. Any more questions? Oh, okay. And you can assign thread pools for different blocks, or it's always for the whole... Whatever you like. Whatever. Yeah. The GUI had another menu that would go through, and you'd have a list of all the simple blocks, which is the ones that actually compute stuff. And you can select the thread pool and the little thing beside it. Or you can do it on the command line with a command line interface, yeah. You'd have to name the thread pools, though, so that you could refer to it in the command line, or the GUI, too. Yeah. I did it. Any more questions? So, Lance, thanks again. Thank you.