¿ªÔÆÌåÓý

Coding for JackAl


Jack Purdum
 


Are the filters/equalizer/etc. compatible (as blocks) with that Teensy visual system audio library they have?

All:

JackAl uses the audio board and its library, so, yes, very much so.

Please note: Because I feel very strongly about the safety that type checking brings to the table, there are are currently 12 source code files: one *.ino file, one *.h file, and ten *.cpp files. One of those files carries a fairly stern warning in a comment at the top about making changes to it, as messing that file up may well ripple through the rest of the code, especially the filters that we've added.

Of course, we encourage everyone to experiment with the JackAl board and is the primary reason that we picked an expensive processor: You have a mega-munch of memory resources (currently over 800K idle), a small knot of empty I/O pins, and a 10x clock speed to experiment with. That said, I strongly urge experimenters to create a new *.cpp file for your changes/additions. There's nothing magical about using *.cpp instead of *.ino. For the most part, it can be straight C code. Because I choose to do things this way, I needed to add a header file (MyButtons.h, which I will likely rename to JackAl.h) which contains little more than symbolic constants, prototype definitions, EEPROM offsets, and extern declarations for the project. The header file is important so that type checking takes place across files. That is, if you write a new function:

??? void MySlickFeature(int whichButton, int whichDisplayPage)
??? {
??????? // all your new code...
??? }

Then the function prototype in the header file is just a copy of the function's signature:

??? void MySlickFeature(int whichButton, int whichDisplayPage);????// Add to header file
?

Doing this makes sure you call it with two integer variables and that you don't try to use it as though it has a return value:

??? callDone = void MySlickFeature(int whichButton, int whichDisplayPage);?? // ERROR!!

?as that would be an error since it's a void function. Also, suppose you have a global name slickFeatureColor defined in your new *.cpp file, but you must let other files know about it so those files can use it. The header file would then need this statement:

??? extern int slickFeatureColor;

The extern keyword tells the compiler: "You're going to see a variable used in several files named slickFeatureColor. Even though you don't know its memory address right now, you may use it as an int data type in those files." What this does is allows the compiler to create an attribute list (e.g., name and type) in the symbol table, but put two question marks in that table for where it resides in memory (its lvalue). (This is precisely what a data declaration is, but most programmers use the term declaration and declare when they should say "define". The terms "define" and "declare" are TOTALLY different things. That is, a data declaration is an attribute list, but without a defined memory space.) Then in your CPP file you have:

??? int slickFeatureColor;

When the compiler sees this statement, it uses the Memory Manager to find a memory location where slickFeatureColor will live (i.e., its lvalue). Now, when the linker pass ties everything together, it can use the symbol table to take the proper memory address and put it where the two question marks are. If you define a variable, its memory address is known, unlike a data declaration.

So, what do you gain for this extra work?

First, debugging will be easier because you now can't call a function with the improper number of function parameters, you can't call it with improper types of parameters, and you can try to use it improperly in an assignment statement (i.e., if the function returns a float but you try to assign the return value into an int). This is the real value win for not using all *.ino files. However, there is another one.

Second, the GCC compiler that hides below the IDE can do "incremental compiles". As you work, suppose you are only changing your new *.cpp file. The compiler has a "dirty flag" for each file. If you're mucking about in only one file, only that file has its dirty flag set. When you go to compile, the compiler looks to see which files have the dirty file set. Since only one file has a set dirty flag, only that file gets recompiled! The linker can then take the old object files and splice the newly-compiled code into it, saving somme time. When I start work in the morning (i.e., all? dirty flags set), it takes almost two minutes to compile the JackAl code, and my machine is no speed slouch. However, because one tends to work with only one or two source files at a time, subsequent compiles may take 15 seconds to compile/load. While a reduction of 1.75 minutes may not seem like much, run that out to a 100 compiles a week and you're talking about almost wasting 3 hours twiddling your thumbs.

This is a long explanation, but hopefully it serves two purposes: 1) to explain why JackAl has only one INO file, and 2) to encourage you to make your additions as CPP files.

Jack, W8TEE



On Tuesday, May 22, 2018, 8:28:45 AM EDT, bobh_us <rwhinric@...> wrote:


Agreed. Great work.
Mine will have that plexiglass panel. Makes the display pop. All kinds of gamer pc lighting possibilities. And the visual ¡°works¡± very Mr. Machine-like.

Are the filters/equalizer/etc. compatible (as blocks) with that Teensy visual system audio library they have??


Can¡¯t wait.


 

On Tue, May 22, 2018 at 07:34 am, Jack Purdum wrote:
JackAl uses the audio board and its library, so, yes, very much so.
Outstanding.?
Will comply.
At what sample rate is the processing done?
Do you have a jpg of the audio graph in the deliverable?
...so I can get a head start :-)


 

¿ªÔÆÌåÓý

Jack,

Please note: Because I feel very strongly about the safety that type checking brings to the table, there are are currently 12 source code files: one *.ino file, one *.h file, and ten *.cpp files. One of those files carries a fairly stern warning in a comment at the top about making changes to it, as messing that file up may well ripple through the rest of the code, especially the filters that we've added.

Have you considered directly provisioning for this by making an "empty" extensions header/code file, perhaps named MyExtensions.h & MyExtensions.cpp, and including these files in the framework.? I'd go so far as to include a MyExtensionsSetup() function called from setup(), and a MyExtensions() function called from the loop().

Anyway, that is how I'd start with an adaptation of your (or anyone else's) codebase.

Daniel


Jack Purdum
 

Hi Daniel:

No, I haven't. One reason is because I have tried to keep all function prototypes, globals, and symbolic constants in one place. When you eventually see that header file, you will also find that I've tried to keep all of those files and variables in alphabetical order within the header file. If users write functions that belong in setup() rather than loop() (or elsewhere), I would call such a function MyExtensionsInitializations() rather than use the word setup in its name. This makes it easy to locate the setup() function using the search function in the IDE editor. It would also make it easier to find your initialization routine. Also, programs that can search multiple files for a certain string (e.g., grep, wingrep, powergrep) work better, too.

Obviously, this is a style issue and there are a bazillion permutations possible. Pick one you like and use it consistently.

Jack, W8TEE

On Tuesday, May 22, 2018, 11:52:16 AM EDT, D. Daniel McGlothin KB3MUN <kb3mun@...> wrote:


Jack,

Please note: Because I feel very strongly about the safety that type checking brings to the table, there are are currently 12 source code files: one *.ino file, one *.h file, and ten *.cpp files. One of those files carries a fairly stern warning in a comment at the top about making changes to it, as messing that file up may well ripple through the rest of the code, especially the filters that we've added.

Have you considered directly provisioning for this by making an "empty" extensions header/code file, perhaps named MyExtensions.h & MyExtensions.cpp, and including these files in the framework.? I'd go so far as to include a MyExtensionsSetup() function called from setup(), and a MyExtensions() function called from the loop().

Anyway, that is how I'd start with an adaptation of your (or anyone else's) codebase.

Daniel


Jack Purdum
 

We have several graphs of the filters and the equalizer. For example:

Inline image
Inline image

Specifically what are you looking for?

Jack, W8TEE

On Tuesday, May 22, 2018, 11:44:24 AM EDT, bobh_us <rwhinric@...> wrote:


On Tue, May 22, 2018 at 07:34 am, Jack Purdum wrote:
JackAl uses the audio board and its library, so, yes, very much so.
Outstanding.?
Will comply.
At what sample rate is the processing done?
Do you have a jpg of the audio graph in the deliverable?
...so I can get a head start :-)


 

Thanks Jack.
Not what you¡¯ve already done. But for something I could add.
Are your filters running at 44.1K or 8K sps for example.
You might have a connection graph of your flow from that visual designer. Like below.
You are probably very busy and I won¡¯t take up more of your time.
thanks


 

Jack,

Dang, those filter frequency responses look good !

73 Kees K5BCQ


Jack Purdum
 

Al is the brains behind the filters, so I'll let him respond:


Thanks for the suggestion.? We have this sort of documentation ready for the user Manual, describing the filter topology, etc.? Our filters are based on digital BiQuad filters, which are sampled at 44.1Khz. This allows for a potential bandwidth of 22KHz.? While interesting for experimenters, this sort of detail is beyond normal marketing data.? We will be creating several articles and White Papers on the methods used once we get the product in production.? We will let everyone know when the material is ready.

Thanks,

Al Peter

AC8GY



On Tuesday, May 22, 2018, 1:22:38 PM EDT, bobh_us <rwhinric@...> wrote:


Thanks Jack.
Not what you¡¯ve already done. But for something I could add.
Are your filters running at 44.1K or 8K sps for example.
You might have a connection graph of your flow from that visual designer. Like below.
You are probably very busy and I won¡¯t take up more of your time.
thanks


 

Thanks Jack and Al.
That sample rate is pretty high. Maybe some surprises in store.
Will look forward to the articles.


 

The Teensy 3.6 has a floating point unit and can do FIR filtering and more at that sample rate with the audio library.

So the IIR filters used here, which are at least an order of magnitude more CPU efficient, and should not be an issue for the Teensy 3.6.

One very interesting feature that opens up with this combination of CPU and library is the USB audio device emulation that would allow a computer to connect via USB for digital modes without a digital interface.

Plus the real possibility of on-board decoding and encoding of digital modes as well as built-in SDR.

Mind boggling and a hacker's dream that thing is.

73, John (VK2ETA)


 

I need some education...? Don't you need i+q signals for SDR?


rOn

On May 22, 2018 at 5:16 PM John <vk2eta@...> wrote:

The Teensy 3.6 has a floating point unit and can do FIR filtering and more at that sample rate with the audio library.

So the IIR filters used here, which are at least an order of magnitude more CPU efficient, and should not be an issue for the Teensy 3.6.

One very interesting feature that opens up with this combination of CPU and library is the USB audio device emulation that would allow a computer to connect via USB for digital modes without a digital interface.

Plus the real possibility of on-board decoding and encoding of digital modes as well as built-in SDR.

Mind boggling and a hacker's dream that thing is.

73, John (VK2ETA)


 

Yes Ron,

The SDR implementation needs an additional quadrature sampler, from reading the documentation the rest of the hardware is already there in the uBitx.

See?

73, John (VK2ETA)



 

Nope.

Often in SDR, they use the I and Q channels to retain information regarding
the phase of the local oscillator vs the incoming signal, this is then used
digitally in the computations to distinguish the signals above the local oscillator
from those that are below the local oscillator.

On the uBitx, we mix it with the local oscillator, then extract just the
upper sideband or the lower sideband in the analog domain using that?
narrow 12mhz crystal filter.? ?No need for that phase information.

Jerry


On Tue, May 22, 2018 at 02:58 pm, W2CTX wrote:

I need some education...? Don't you need i+q signals for SDR?

?


 

That's the other way to do it.
This JackAl board is just sampling the audio that we normally hear when listening to the radio.

I'd call them both "SDR".
Some may disagree.

Jerry


On Tue, May 22, 2018 at 03:23 pm, John wrote:
Yes Ron,

The SDR implementation needs an additional quadrature sampler, from reading the documentation the rest of the hardware is already there in the uBitx.

See?

73, John (VK2ETA)


 

That was my understanding, reading between the lines in Jack's post:
? ??/g/BITX20/message/49882
I could be wrong.

Much of what they are doing could be done in a form factor to match the current Raduino,
so it's easily swapped in.? As per the last paragraph here:
? ??/g/BITX20/message/49519?
?
It's very easy and fun to speculate about what can be done.
I've been thinking about an ARM based Raduino for the last year and a half:
? ??/g/BITX20/message/19340

But have so much fun figuring out how I would cram a spectrum analyzer and VNA
and oscilloscope and ... into that Raduino that I never get around to actually doing anything.
Much more difficult to successfully do something..

Jerry, KE7ER


On Tue, May 22, 2018 at 03:27 pm, Jerry Gaffke wrote:
This JackAl board is just sampling the audio that we normally hear when listening to the radio.


 

If you need phase information for a digital ham mode you can generate IQ locally in the baseband audio signal from the uBitx with the Hilbert Transform. Like in those old telephone modems. There may be advantages to doing it at IF (like before an AGC).


 

Jerry,

Would the following make sense then (software mods and Si5351 i2c bus address aside for now):

- $37 Elektor SDR board?

SDR board RF input connected after the first IF filter (or before?), uBitx Si5351 clocks #0 and #1 disabled (2nd IF and BFO off), 192kHz I/Q audio out to Teensy audio input with modded SDR software.

Tx chain as standard uBitx.

So many toys, so little time.

73, John (VK2ETA)





 

That could make sense as a very fun toy.?
A hackable 0-30 mhz receiver.
I'm not convinced it's a good fit as an add-on to the uBitx.

Jerry


On Tue, May 22, 2018 at 05:07 pm, John wrote:
Would the following make sense then (software mods and Si5351 i2c bus address aside for now):

- $37 Elektor SDR board?

SDR board RF input connected after the first IF filter (or before?), uBitx Si5351 clocks #0 and #1 disabled (2nd IF and BFO off), 192kHz I/Q audio out to Teensy audio input with modded SDR software.

Tx chain as standard uBitx.

So many toys, so little time.


Jack Purdum
 

Hmmm...perhaps you guessed the primary reason for selecting a relatively expensive processor.

Jack, W8TEE

On Tuesday, May 22, 2018, 5:16:10 PM EDT, John <vk2eta@...> wrote:


The Teensy 3.6 has a floating point unit and can do FIR filtering and more at that sample rate with the audio library.

So the IIR filters used here, which are at least an order of magnitude more CPU efficient, and should not be an issue for the Teensy 3.6.

One very interesting feature that opens up with this combination of CPU and library is the USB audio device emulation that would allow a computer to connect via USB for digital modes without a digital interface.

Plus the real possibility of on-board decoding and encoding of digital modes as well as built-in SDR.

Mind boggling and a hacker's dream that thing is.

73, John (VK2ETA)


 

I¡¯ve messed with this board a bunch. You can always replace (at your own risk) the existing generated code for what you want. ?If you mess it up, reload the virgin Jackal code. Nothing ?lost.?

?

Dr.?William J. Schmidt - K9HZ

?


On May 22, 2018, at 11:22 AM, bobh_us <rwhinric@...> wrote:

Thanks Jack.
Not what you¡¯ve already done. But for something I could add.
Are your filters running at 44.1K or 8K sps for example.
You might have a connection graph of your flow from that visual designer. Like below.
You are probably very busy and I won¡¯t take up more of your time.
thanks

<4EB0AB41_B22A_4E6B_855B_47205A0F276E.jpeg>