quadrants: my 256 splitter

  • So in a fit of procrastination from actual work over the past couple of days I decided to forge ahead with my generic 256 splitter patch. The code is a mess, but it seems, for the most part, to work.

    There are a few caveats. Each app needs its own prefix, so you can only run one unmodified old-style /box app, for instance. There is the possibility of apps interfering with one another. (My hacked up version of step was drawing /led_rows on the box that flin was attached to, and also hijacked mlr's file list.) If you're running apps from different environments (ie: both Max/MSP and ChucK), you'll need to set up a port-forwarder, since they can't both bind to 8000 and there's (currently) no way to change ports on a per-app basis in quadrants. Also, /frame only sort of works, converting it to 64 individual /led messages seems to bottleneck Max's udp objects, but I don't think too many apps actually use /frame anyway.

    And of course, there is no guarantee that this will actually work for you. Although I'd love to hear feedback from people with different set-ups.

  • curious, why does frame only sort of work? i would think for quadrants this would be the easiest method to use.

    i use frame and _row almost exclusively, but im beginning to think im a bit of a freak now as most apps seem to only use /led.

  • Ultimately, /frame will be a great way to send split data to the 256, but (at least as of the OS X version from a few weeks ago) MonomeSerial doesn't seem to support the quadrant specifying part of the serial protocol. To get around this my patch splits it up into 8 /led_row messages, which are then themselves each split into 8 /led messages. And when you start sending 64 /led messages in a row at any faster than a couple of times a second, packets start dropping.

    I'm a big fan of /frame, /led_col, and /led_row. Future versions of this patch might take into account whether an /led_row is on the left half or an /led_col is on the top, and not split it up, in order to save the overhead. And it might actually be a nice feature of MonomeSerial to take an offset to either (and then convert to /led messages at the driver level) so that you could change the right/bottom half without disrupting the corresponding left/top.

  • i think you're right, in terms of led col/row-- specifying an offset rather than multiple bytes is probably more useful. what do you think?

    /led_row 2 0 255

    row 2, offset 0, data 255

    /led_col 4 1 127

    col 4, offset 1, data 127

    more useful than

    /led_col 0 255 255 255 255

    col 0, data 255 x 4


    also i didn't realize monomeserial had frame bugs. i'll have to check. what's the problem specifically?

    also how would you rate the optimization on your router? latency?

  • I hadn't done any re-testing of /frame since the first monomeSerial that supported the 256 (018A?) at which point it had some hiccups. The newest version seems to work fine with offsets (rather than the quadrant specification in the serial protocol) which makes a lot of sense, keeps it compatible with the 40h, and argues for going the offset route for /led_col and /led_row as well. I'll have to go back and de-complicate the /frame part of my patch.

    Optimisation almost certainly falls somewhere on the scale between "less than idea" and "completely pathetic". I did some cleanup as I went, but a lot of the patch is cobbled together and then left alone once things were working.

    As far as latency goes, I haven't noticed any real problems. However I do have a relatively fast computer and no real capacity for keeping a beat, so I'm not sure that I'd be able to judge if things were falling slightly out of sync.

  • Well, MonomeSerial does still have the /frame offset bugs as described here:

    http://post.monome.org/comments.php?DiscussionID=98

    Works fine if offsets are multiples of 8, but buggy with other offsets (whether specified in the OSC message or in MonomeSerial).

  • probably the most hardcore math work ive done in the whole monome serial project was getting frame, _row and _col to work on the newest monome serial (osx and windows). it was more of a priority for me than for brian and steve probably, because i use them more than led (i like to do all the silly bit-math in reaktor, for whatever reason i find it fun, plus its easier when doping midi-clocked led updates).

    the quadrants work in monome serial via the first 2 args, which are offsets. so, 8 8 for the lower right. that was the hard part, getting it to work with arbitrary offsets (like, offsets 2 2, and frame offsets 7 3, as an example, which only a psycopath would ever do).

  • I am that psychopath. I can think of at least two reasons where that situation (at least on one axis) could be useful:

    1. With two side-by-side 40hs there's about a button column's width taken up by the borders of the faceplates. For some apps (mlr, for example) you'd obviously want to span the two devices with one continuous grid regardless. But for more display-centric apps (life, which doesn't use frames, but other apps might) it could be useful to set the X offset of the second device to 9 rather than 8 in order to provide more continuity to the visual field.

    2. Imagine a scrolling ticker. You set the device's X offset at 7 in MonomeSerial, so that the rightmost column of the frame will display in the leftmost column of the device when the frame's X offset is 0. Then you scroll by incrementing the frame offset and re-displaying.

    This works on the 40h (although it does turn off LEDs outside of the frame bounds, as described in that other post, which is actually useful in this application, but ultimately a bug).

    But it does not work on the 256. Frame offsets 0-6 display nothing. 7 correctly displays the frame in the upper-right quadrant. 8 steps the frame two columns instead of one. 9-14 add another column each (shifted one from where they should be). 15 doesn't move (so it's in the right place). 16 steps two columns again. &c. With device offsets other than 7, the frame will sometimes actually jump back and forth. In other words, it seems as if something is still a little amiss with the math.

  • thanks for the examples, which are very insightful =)

    i believe the 40h frame bug is fixed now, at least i thought i fixed it.

    the 256 frame math is always going to be a little off. brian originally thought that non-8-devisable frame offsets should create the frame with _col values. this is a good idea, since values on the left and right of the X offsets will not be affected. this requires alot more work, though, and alot more processing (still not a problem, the app overall is pretty lightweight). what i ended up doing instead, was using _row's. so, Y offsets will leave unafffected areas above and below the frame, but any frame offsets > osc offsets will affect both sides of the 256. frame offsets < osc offset will only affect the left side, but will still turn leds off on the far right of the left half.

    frame is _row based, so i thought this was another reason using _rows instead of _cols would make sense.

    the only way, afaik, to get it working perfectly, is if you instead sent 64 led messages. and, im sorry, but that is a bit rediculous to me, and would probably start slowing the device and monome serial down if you sent rapid /frame commands. but, unless we ended up doing that, frame will never be perfect on the 256 (well, if you all could think of anything, id be pretty grateful!).

  • Don't know how the version numbers match up, or if Steve's incorporated your up-to-date col/row/frame code into the OS X version of MonomeSerial, but the 40h frame bug still exists in 018D.

    Certainly converting a /frame into 8 /led_rows makes sense. And is relatively easy. Converting to 64 /led messages may be a little bit overkill, but it's probably the direction that I would take. Maybe what's to be taken away from all of this is that while /frame is a nice idea, it's not as apropos to the 256 as the 40h/64.

    The only possible solution that springs to my mind, and this is actually something that I've been thinking about for some time for other reasons, is to keep a 2d array in MonomeSerial for each prefix used that stores the current LED states. That way you could convert an offset /frame into /led_rows but also fill in the rest of the row info from stored memory so as not to turn it off.

  • stored memory has been discussed with me and brian. im personally not into it. it would have to be per-device, because per-prefix would entail a 2d array of 0 to Int32 Max (which is possible, but kind of a memory waste i think, although not as much if it used bits instead of bytes per cell, but that adds to the complexity). also, this introduces alot more rom for bugs and errors. id be more inclined to start on this after alot of other issues are resolved first, like better cross-platform code, per-device osc ports, and /sys/serial commands/using serial numbers to select devices for /sys commands. of course, the project is open source, and i wouldnt mind adding any OSX code changes to the Windows version, especially if they were nice and used standard c/c++ code (which of course this probably would, no reason to use Cocoa for something like this).

    i think you nailed it on the head, bean: "Maybe what's to be taken away from all of this is that while /frame is a nice idea, it's not as apropos to the 256 as the 40h/64."

    i think frame is ok on the 256 as long as you respect the fact that it doesnt work perfectly with offsets. otherwise, its not worth it.