Aleph: serial bus control

Continuing the discussion from Aleph Grains:

@rick_monster said:

Once module release is out I’ll be keen to work on BEES op for communicating with a connected laptop via osc (lets me trigger sampler or resonators with my existing boomerang-compatible lisp/linux midi looper). Even better - make any BEES param respond to osc from a host laptop/embedded linux device.

If people like the ad-hoc ‘patch matrix’ paradigm in the new module it would be good to formalise that code and integrate with BEES. BEES module for polling analysis params could index the patch matrix. The bfin module should be able to assign namestring for each patch-matrix-index without building that knowledge into bees.

as for automating bees from serial input: this is something @tehn wanted; he worked on it but as far as i know it was never really finished - something was working, then it was broken by my changes to the descriptor system and abandoned. there is some kind of python code here [ https://github.com/tehn/aleph/blob/dev/utils/aleph-com/aleph-com.py2 ] and a lot of commented out code in here [ https://github.com/tehn/aleph/blob/dev/avr32_lib/src/serial.c1 ] but i’m not sure how any of it worked. (it looks like it is just intended to expose DSP parameters to the serial stream, not the whole bees network.) i later added the super-basic SERIAL op for output from aleph->laptop so i could use the aleph as a controller in performances. controlling the bees network remotely is a cool idea though, and not inherently too difficult.

1 Like

so in order to get it so I can remotely control the sampler in grains from my linux sequencer, think all that’s required is to somehow connect the outputs of op_serial up to incoming serial data. Sure the other stuff would be nice eventually but as usual next step should be the simplest possible useful thing.

Just did a quick test/read-through-code and it doesn’t seem like the outputs on that operator currently do anything so I will try to plumb them in. Unless I’m missing something? I notice that serial/A 32-127 outputs ascii chars interleaved with the debug messages. So actually that gives me a pretty good start figuring out the serial protocol (looks like just stuffing all 4 bytes of A & B down the wire every time A or B is triggered from bees network)…

yea, op_serial doesn’t deal with input to the aleph at all, just something added quickly for very basic output. i have no idea if anyone but myself uses it, and it’s obviously not very elegant.

for serial input, it looks like we already have a USART interrupt and event type set up. this is in the avr32_lib layer:
[ https://github.com/tehn/aleph/blob/dev/avr32_lib/src/interrupts.c#L244 ]
[ https://github.com/tehn/aleph/blob/dev/avr32_lib/src/serial.c#L84 ]

(all the dead code in serial.c should be removed.)

BEES and other control apps need to assign a handler to the kSerialEventType. that dead code was moved here already, and i think it is actually pretty functional.

here’s the handler:
[ https://github.com/tehn/aleph/blob/dev/apps/bees/src/handler.c#L172 ]

and here’s the protocol processing:
[ https://github.com/tehn/aleph/blob/dev/apps/bees/src/ser.c#L60 ]

it’s been commented out so that right now there is just a loopback. but brian made a whole protocol for controlling the blackfin parameters directly from a host computer. again, it worked fine up to the point when i broke it by moving the parameter descriptor stuff off of the blackfin; fixing that would be easy, but even better would be to extend the protocol to give more general access to the control network, and to get stuff back from the aleph in a more structured way than just blasting a couple of arbitrary bytes.

Hmm so just read the page on framing linked from @tehn’s old code - that’s got my brain whirring.

Here’s a protocol between aleph & host which should allow to trigger & query bees inputs/bfin params from my lisp environment, as well as receive async callbacks from bees via op_serial.:

https://github.com/rick-monster/aleph/blob/dev/apps/bees/host-serial-protocol.org

capitalised values in the message specification here are members of a char enum of message-type identifiers. No ack/nack, checksum or transactional behaviour built in - easier to just make host application somewhat fault-tolerant (I hope).

back up - there’s too much tricky plumbing between the aleph & lisp in order to get this ambitious proposal going all at once.

First step will be to make the simple functionality of op_serial bidirectional, then trigger bees network from my lisp program.

Once that hurdle is overcome, using a named pipe on my laptop to emulate bfin serial usb device, develop & test the C code for aleph-side protocol on linux. As soon as there’s one command in each direction, deploy to aleph & test, then finish the rest of the protocol commands…

seems like a good plan.

updating ops from serial input wouldn’t be too different from using HID / midi / grid input, which similarly generate main-loop events from their respective peripheral interrupts.

for each of those types of input, we do something like:

  • maintain a list of operators that deal with that kind of data
  • maintain a data buffer that is filled from the event handler
  • set a timer that checks the input buffer and updates the relevant operator(s)

i think the only real reason for the polling step is to be able to arbitrarily throttle the update rate.

for first tests, could probably skip the polling step and the op list:

  • keep a pointer to a singleton SERIAL op (last one created, or whatever)
  • call that op’s handler directly on processing a kSerialEvent.

( if an extensive protocol is developed for controlling all operator inputs / reporting all outputs, then there’s no need for a dedicated op anyways)

ok interesting that you think the way forward is just report all outputs. Didn’t occur to me to do it like that I’ll have to think a little how the whole thing would hang together in that case. Well anyway that is a little way in the future - the next steps are clear enough.

Thanks for those pointers on polling vs. callback in bees. Just hacked something really terrible together - hopefully I can now send numbers on op_serial output by hitting keys in miniterm. time to time to crack a beer and put on some vinyl while the hex flashes…

piece o’ cake mwahaha! so first contact between aleph & lisp was much easier than expected. This whole thing’ll be up & running in a jiffy…

1 Like

cool!

well ok, i dunno about reporting all outputs all the time; timing takes a hit as one notices with debug builds. but maybe, say, an option for outputs analogous to the SHOW/HIDE option for inputs? just a thought

garrr what happened!? There’s no beer left in the fridge, I have a pounding headache and woke up next to a complete stranger, namely a mostly-untested but finished-looking prototype of aleph side serial communications. Probably riddled with bugs…

3 Likes

It’s working now - querying & reading all the dummy values correctly between aleph & emacs/slime! Bit of work still to connect the dummy values with real ones & figure out how to incorporate another show/hide song & dance into the UI. Looks to me like alt-button3 on bees outputs screen is still up for grabs.

OK just found a silly bug with char escaping & one more typo in the lisp host library - think I’ve tested all the edge cases with framing now. Should be good to go! Also worth saying that exisiting debug messages don’t contain the magic numbers for framing so ye olde print_dbg doesn’t blow things up…

i’m happy to do the aleph UI changes if you want, it’s old familiar territory.

somewhat tangentially, i’m curious what kind of environment you’re using on the host side. i’m not a huge Lisper but i do use emacs… are you using a particular terminal extension? are you planning to publish the lisp stuff?

1 Like

UI code is normally the craziest part I guess - probably not much sense me learning that bit of the codebase. May well never want to tweak bees UI again - much more interested in the DSP side, especially once block processing is up & running.

I do want to add a feature for flashing bfin program through serial cable without rebooting bees and destruction-testing SD card connector. Must be feasible right? Hmm guess this also would require a little bees UI knowledge.

Speaking of eliminating DSP drudgery, I mostly nailed down a pretty accurate emulation of blackfin built-ins during grains dev (at least the fractx32 parts). Even probing dsp blocks ad-hoc by recompiling each time is a massive improvement on the sdcard-reflash/aleph-reboot cycle.

Another time-saver for new dsp is my lisp-scope program. It uses a lisp->jack bridge to get opengl-accelerated quad scrolling scope & data capture. Think I can also chuck lisp-scope up on github - lemme have a quick check through the source code check everything in there is mine to share…

Will start a new topic for lisp midilooper once I’m back working on it (it needs quite a bit of work). For now this beasty lives in my alsa midi bindings here:

https://github.com/rick-monster/cl-alsaseq

oh and to to answer your question my lisp environment is sbcl common lisp in slime (Superior Lisp Interaction Mode for Emacs)

Hang fire on adding that feature to bees UI here’s another suggestion - maybe better and certainly easier to just add a command to serial protocol enabling/disabling serial message on particular bees output. Makes more sense than adding a front-panel feature for something invisible to front-panel-only users.

On the other hand displaying bees output on front-panel could be a good new feature for the same UI widget. Saves connecting interesting outputs (e.g from op_param) to some dummy input to get front-panel readout.

Reading through some of the midi code couldn’t see any of the event throttling you describe. So just ploughed ahead calling net_activate straight from the event handler (with NULL calling-op). Right now plumbing in that switchable serial output to net_activate whenever a real op calls net_activate…

ok, sounds reasonable.

hm, you’re right, my description of the throttling was inaccurate, sorry. what actually happens is that e.g. midi input is polled on a timer. the timer ISR kicks off an asynchronous read in the USB host controller:
[ https://github.com/tehn/aleph/blob/dev/apps/bees/src/app_timers.c#L111 ]

when the read finishes, if it got something, then a midi input event is raised, and the network handles it ASAP.

anyways for serial input we probably don’t need to go through that rigamarole since we can just control how fast the host is sending stuff.

what i was wondering about re: your lisp environment, is really what kind of host-side program you’re envisioning. would it have to run in emacs? (sorry if this is a dumb question)

so slime is a dev environment for common lisp that allows emacs to connect to an already-running lisp over a socket. You can zoom around the codebase with meta-dot, expand macros, interactively recompile parts of the program while it runs, inspect all the objects making up the program while it runs, interactively debug - loads of incredible techniques remembered from the days of lisp machines.

It will be possible to deploy the lisp program to a little arm board, run the application there (with or without slime capabilities) and noone ever has to know it’s harboring secret alien technology. Unfortunately my first attempt at lisp bindings to alsa midi are too inefficient (really wasteful) for embedded deployment. think I’ve figured out how to rectify that - as I say needs more work…

harumph so I think there’s no way to add the serial output feature without refactoring net_activate.

Currently the last input to net_activate is pointer to the operator responsible for triggering the event. This variable is only ever used to check if it was an op that triggered, or NULL. Furthermore can’t see any way to find which output triggered it.

How about swapping the last argument to net_activate for the triggering outIdx, or -1 for non-bees trigger events?

yes i think that would totally work. pretty sure the only time net_activate is called with a null op pointer, is from net_retrigger_inputs(). and that function isn’t used anymore; i just erased its definition and was still able to compile.

of course that’s a lot of calls to net_activate() in the op sources, that need fixing… i guess a sed script or emacs macro could do it by copy-pasting the output index from the first arg.

remote bees triggering totally working/tested now + param reads + bees input reads! Just a couple of little things in there that needed a tweak but basically was straightforward. Gonna plough straight into a foolhardy net_activate refactor off on a feature branch…

there’s a deeper problem here than the donkey work (or automation) of modifying 100-odd calls to net_activate:

  • one level up in the operator code with all those net_activate calls the outIdx is also not available.

  • the level above that is op_set_in_val, so I see ouputs are always indexed relative to the operator & op_t does not know the index of it’s first output.

  • to add the desired functionality of sending absolute outId & data val based on relative outIdx & operator pointer, it will be necessary to store outIds in an array on the operator object. That array is initialised with all -1 values. Then when serial output is toggled on some out, the appropriate array element on the op gets set with it’s absolute outIdx (or back to -1).

  • the refactor of net_activate would still be required.

Pretty sure that would work (eventually), but instead of this tricky change I could simply refactor op_serial as a two-input, no-output operator. First input is address, second input is data. Serial output is only triggered when the data input gets banged. This enables multiplexed communication from bees network to the computer with a lot less fettling…