Aleph: reading DSP params in BEES

Continuing the discussion from Aleph Grains:

long ago i had parameter names/descriptors built into the blackfin executable, and the avr32 would query them. but since the LDR is limited to 64kb, and the blackfin doesn’t actually have any direct use for namestrings, this started to look like a very bad use of limited static memory (not to mention SPI bus traffic.) hence the current system of offline param descriptor files, which of course bees already knows about. an ugly but minor hack could make the PARAM operator (or whatever) display strings from the parameter descriptor lists, instead of numerical values, for inputs that correspond to DSP param indices. ( the hack would go here: [ https://github.com/tehn/aleph/blob/dev/apps/bees/src/pages/page_ins.c#L78 ])

ok simple analysis module for SPI testbench is working now. It runs linear slew-limited envelope tracking on CV1, log slewing envelope tracking on CV2, pitch tracking on CV3 & CV4 just a DC CV source from bees. I’ll send a pull request with the grains code & this simple analysis module…

1 Like

… and now got a param operator compiling & running on the aleph - copied from op_timer. Doesn’t work as I expect though. Will try peppering the relevant parts with printfs tomorrow see if I can understand why this doesn’t work:

net_activate(param->outs[0], bfin_get_param(v), param)

so is this an operator that would allow us to feed a DSP amplitude level into the Bees network? does it become part of an existing module or would it exist just within bees?

1 Like

@dspk: this is an operator that will read parameter values from the blackfin, back into bees. for this to be useful it also requires that a module update its own parameters.

@rick_monster: that line looks ok to me. i don’t see the operator in your pull request though (which i just merged,) so i don’t know what else is going on or where this output is triggered. (personally, i wouldn’t give it a dedicated timer, but allow it to be arbitrarily polled from a METRO, switch, or whatever.) i guess it’s also worth mentioning that bfin_get_param() disables interrupts during its execution - i don’t see that being a problem but maybe bear it in mind when debugging.

also, looking at the ‘analyser’ module source, i don’t see it actually updating its parameter values. for this to work, it would have to do something like calling module_set_param() from module_process_frame(), for each analysis result, in addition to updating the physical CV outputs.

EDIT: sorry, a correction. analyser.c should call param_setup() or the equivalent - it needs to update the low-level parameter fields with the values to be sent to the avr32. [ gModuleData->paramData[id].value ]

i’m also realizing that analyser doesn’t declare parameters for analysis results, just for envelope and fixed CV output settings. each thing that you want to report to avr32 should be a separate parameter in its own right.

1 Like

non-working param operator is on my dev branch - I didn’t add it in the pull request…

Wrote analyser before digesting what you wrote about blackfin SPI state machine etc - so didn’t understand at that point the analysis params are the same data structure as regular module control params.

Digging into bees having realised this, my first try was to read back one of the regular module control params (the one indexed at 0). Was getting back some value after first module load, then 0 after changing that param from bees. Just hacked on analyser.c a bit following instructions in that last post - maybe this will just work

seems to be spitting zeroes interspersed with random numbers. Must be pretty close (only spewing junk on the param indices that are being twiddled with module_set_param) but falling asleep at the keyboard here - will try to get up early and get something done before work tomorrow.

Btw - nothing special about copying the timer op other than it had 1 out / 1 in. Just needed an example op as starting point…

hm… well this is sort of unknown territory; thanks for taking the plunge! reading back a regular param value after setting seems like a fine test.

maybe try throwing a bfin_wait() into bfin_set_param at avr32_lib/src/bfin.c. that pauses the avr32 until the blackfin is done processing the current audio frame. (at the moment, audio frame processing is done in an ISR, and additional interrupts coming in will be masked.)

bfin_wait seems to squelch the zeroes, which is good, but still not reading any sane numbers back. Looking again at net.c I see that scaler_get_in is subsequently called on the raw bfin param vals. I guess this is the step to convert between bees’ native 16 bit and bfin native 32 bit according to the radix & param type set in the parameter descriptor file.

However what I don’t see is how to navigate from an instance of op_param_t (the new subclass of op_t for the param operator) to the param scaler in extern ctlnet_t* net;. Reading around a little more I deduce that param scaler is implemented as a function pointer. Not totally familiar with function pointers in C I have to admit, though I guess it’s just a poor man’s lambda…

Guess a good first thing to try would be ensure all those analysis params have radix 16 for now (so I will try to shift-right 16 and hope for the best). There’ll be time to worry about arbitrary param scaler plumbing another day. Here goes nothing…

SUCCESS! awesome thanks for the pointers @zebra - maybe I still have the strength to grok arcane mysteries of the param scalers tonight…

2 Likes

ah, great!

of course, i forgot that params will also need to be scaled back to bees representation.

yeah, a param scaler is basically just two functions, one to convert in either direction. many scaler types also have lookup tables. for those types, backward conversion involves reverse lookup and is relatively slow, but for linear fixed-point types, it’s not a big deal.

accessing the scalers will need to be through the control net, so need a new accessor in net.h / net.c, something like

io_t net_unscale_param(u32 idx, s32 val) { 
   return scaler_get_in( &(net->params[idx].scaler), val)
}
1 Like

so I must have goofed up somewhere - thought I’d tried exactly that last night - existing code was clear enough! Probably some clerical error like not copying updated hex file onto the SD card.

param scalers work today anyhow - hurrah!

would this be a good way to check bfin register values? looking for a way to “print_debug” the bfin…