norns, crow, txo: native ii commands causing issues

hi everyone,
currently I finished my diy txo built and now I am experimenting with the txo as a crow expander.
I came across the following problem which I can not understand/solve on my own …

In short: When using the native ii commands for txo (e.g. crow.ii.txo.tr_pulse(1)) it occurs regularly that norns’ screen freezes and only comes back to life when I repower my eurorack case (power cycle crow). But when I am using the crow.ii.raw command the problem does not occur …

Now I am wondering, why my self implemented commands work better than the standard commands? The problem further affects the performance of fastly sent commands. with the native commands pulses of 1/32 length are missed regularly, but with raw they work totally fine.

To the setup: I am using crow (v 3.0.1), with norns shield (latest update) and txo (latest firmware). The pulses are generated in a clock routine which is started from a mod pre_init. The mod is going to be a “crow’s new workout” type of thing!

Do you have any ideas what causes the problem? I only discovered the issue because I thought it is maybe safer to not use my own implemented commands …

This is very strange to see it freezing norns. I can imagine something going haywire on crow, but seems strange to propogate to norns.

Could you post the simplest form of your script that still causes the issue?

1 Like

hi @Galapagoose , thanks for jumping in.

i reduced the script to the following which reproduces the error consistently. you can still ;restart but this want solve the issue, only repowering both norns and crow will reset everything.

engine.name = 'PolySub'

txo_command = function (cmd,out,value)
  local msg = string.char(cmd)
  if out then msg = msg .. string.char(out) end
  
  if value then
    value = math.floor(value) & 0xFFFF
    local str = string.format("%04x",value)
    local len = string.len(str)
    str = string.sub(str,len-3,len)
    
    local msb = tonumber(string.sub(str,1,2),16)
    local lsb = tonumber(string.sub(str,3,4),16)
  
    msg = msg .. string.char(msb) .. string.char(lsb)
  end
  
  crow.ii.raw(0x60,msg)
end

function init()
  -- SCREEN LOOP
  clock.run(
    function ()
      while true do
        redraw()
        clock.sleep(1/10)
      end
    end
  )
  
  -- OTHER LOOP
  clock.run(
    function ()
      clock.sleep(3)
      while true do
        crow.ii.disting.midi(0xB0,123)
        clock.sync(1/2)
      end
    end
  )
  
  -- TXO LOOP
  clock.run(
    function ()
      for n=1,4 do crow.ii.txo.tr_time(n, clock.get_beat_sec()/16*1000) end
      --for n=1,4 do txo_command(0x02,n-1,50) end
      clock.sync(1)
      while true do
        for n=1,4 do crow.ii.txo.tr_pulse(n) end
        --for n=1,4 do txo_command(0x05,n-1) end
        clock.sync(1/8)
      end
    end
  )
end

function redraw()
  screen.clear()
  screen.move(62,32)
  screen.level(15)
  screen.text(util.round(clock.get_beats(),0.25))
  screen.update()
end

I included the raw alternative which helps to avoid the problem.
I assume that it is related to the clock system, since under some conditions I still could enter the norns menu and when i reentered the script, the screen was updated but did not continue to update automatically.

Thank you already in advance!

The way the raw alternative works, but the built-in (well-tested) system doesn’t, suggests the issue might be to do with speed. When you’re building the raw command it’s taking a lot longer on the norns side, than using a built-in crow function.

This makes me think the issue could be to do with the usb connection between the devices being overrun. One thing I’d try is transposing the tr_pulse call so the for loop happens on crow:

-- current version. loop runs on norns. sends 4 msgs to crow
for n=1,4 do crow.ii.txo.tr_pulse(n) end

-- alternative. loop runs on crow. only 1 msg to crow
crow[[for n=1,4 do ii.txo.tr_pulse(n) end]]

Also, just to be sure we’re not on the wrong track, try commenting out the disting clock to prove there is no interaction with that code.

sorry, I was not clear in my last post. I included the disting command, since the error occurs in combination with the really slow call of the disting command. I included it in that manner to make it reproducible, in the original script, such commands were send as a response to some changes of settings.

without the disting command the native ii commands work fine.

your suggestion works with the disting command!

can elaborate a little bit on the syntax? I am by now quite familiar with lua on norns but I have not seen any thing like this syntax before?

sure i think this usage is undocumented, or at least underdocumented.

rather than use the crow.* namespace to call crow functions, you can just send chunks of lua code to crow. the formal function for the this is norns.crow.send(...) but there is a shortcut to do this by calling the crow table itself.

the double-square brackets are the symbol for denoting multi-line strings in lua. and in lua, you can call a function without parentheses if you have a single string argument (or single table arg). so it’s a bunch of shortcuts to convert it like this:

-- longform with single-line string
norns.crow.send( "for n=1,4 do ii.txo.tr_pulse(n) end" )

-- shortcut to make it clear you're running the following code on crow
crow[[
  for n=1,4 do ii.txo.tr_pulse(n) end
]]

all of the crow.* calls use this norns.crow.send(...) function under the hood, but just try to make it feel more continuous in style.

@Galapagoose wondering if O_SYNC is slowing down command throughput (untested speculation)

!!! would definitely be worth regression testing with the previous norns release (assuming the change got rolled into the most recent norns update?)

no it’s always been there. taking a cue from your discovery of the libmonome bug, thought i’d check this line

1 Like