Teletype MIDI IN ops [experimental]

this is a thread for discussing and testing teletype MIDI IN ops. this feature should be considered experimental for now - there might be some possible issues, it should be tested with more devices, and the ops themselves can change based on the discussion here.

the most obvious use cases are using a MIDI keyboard with the teletype converting notes to i2c ops so you could play just friends / er-301 / txo (with possibly some additional transformation done by teletype - how about using the param knob as an octave switcher?) and using a MIDI controller to control the scene itself or various txo / er-301 / disting ex etc parameters. the cool thing is - you can use teletype to additionally process MIDI events, so in essence you get a scriptable MIDI-CV and MIDI-I2C controller.

it should be noted that while it should be okay in most cases to plug your MIDI device to teletype USB port directly, it’s best to power it externally (using monome switch or two>one or a y-cable etc) if you have the older edition teletype (green PCB). and make sure you have extra 500ma available on your +5v rail!

so far i’ve tested and can confirm it works with: faderfox mx12, faderfox pc12, midi twister, arturia player keyboard. it didn’t work with nakedboards mc 24 - i have a suspicion it’s teensy based, and teensy based devices that report themselves as serial might not get properly recognized. will investigate later.


here is how it works: first, you use an op to assign a script to a MIDI event. then, whenever an event is received, it will execute the assigned script. additional ops allow you to get specific event details - note, velocity, controller number/value etc.

MI.$ event_type
MI.$ event_type script

assign a script to an event or get the currently assigned script
event_type is one of the following:

0 - all events
1 - note on
2 - note off
3 - controller change
4 - clock
5 - start
6 - stop
7 - continue

the clock is not supported for now (need to figure out how it should work, more details later).
if there is no script assigned to a given event type it returns -1.
similarly, if you want to remove the assigned script, just assign any value outside of 1…10 range.
if you want to remove all assigned scripts do MI.$ 0 -1


once the assigned script is triggered, you can use the following ops to get the details:

MI.LE
get the latest event type - useful when multiple events are assigned to the same script

MI.LCH
get the latest channel

MI.LN
get the latest note on 0…127

MI.LNV
get the latest note on scaled to teletype range (shortcut for N MI.LN)

MI.LV
get the latest velocity 0…127

MI.LVV
get the latest velocity scaled to 0…16383 range (0…+10V)

MI.LO
get the latest note off

MI.LC
get the latest controller number

MI.LCC
get the latest controller value

MI.LCCV
get the latest controller value scaled to 0…16383 range (0…+10V)


now comes the tricky part. in order to make teletype being able to handle other tasks, scripts assigned to MIDI events are triggered only every 50ms. this means it’s possible more than one MIDI event happened since the last time a script was executed - think chords or multiple knobs turned etc.

you can still process all these events properly, but you’ll want to do it in a loop. and since you’ll likely use a loop the ops that return event details for each event use I variable as the index. for instance, to send all midi note on events to just friends you could simply do:

L 1 MI.NL: JF.NOTE MI.NV MI.VV
what this means: send a note to just friends for each note on event. the event count gets reset each time the assigned script is executed.

MI.NL
get the number of note on events

MI.NCH
get the note on event channel at I index

MI.N
get the note on at I index

MI.NV
get the note on at I index scaled to 0…+10V range

MI.V
get the velocity at I index

MI.VV
get the velocity at I index scaled to 0…+10V range

MI.OL
get the number of note off events

MI.OCH
get the note off event channel at I index

MI.O
get the note off at I index

MI.CL
get the number of controller events

MI.CCH
get the controller event channel at I index

MI.C
get the controller number at I index

MI.CC
get the controller value at I index

MI.CCV
get the controller value at I index scaled to 0…+10V range


beta midi in firmware (will always contain what’s in the latest beta in Teletype 3.2+ feature requests and discussions):

updating the firmware will erase your presets!

MIDI IN 3 july 30

teletype.hex (659.4 KB)
teletype.zip (190.5 KB)

changelog

  • new ops: MI.LCH, MI.NCH, MI.OCH, MI.CCH, MI.LE [2]
  • changed script timer to run every 25ms [2]
  • rebased on the latest beta firmware [2]
  • fixed a bug where assigning a script to all events (MI.$ 0 x) didn’t work [3]

for devs, the branch is here: https://github.com/scanner-darkly/teletype/tree/midi_in

37 Likes

some video demos (this use an earlier version so the ops are slightly different):

video 1
video 2
video 3
video 4

a couple of basic scene examples:

just friends with midi keyboard:

#I
JF.MODE 1
MI.$ 1 1

#1
L 1 MI.NL: JF.NOTE MI.NV MI.VV`

this is velocity sensitive (if supported by the keyboard). notes are allocated by just friends, and note length is controlled by just friends. i’ll post about also supporting proper note length separately as it involves a couple of tricks.

er-301 with midi controller:

#I
MI.$ 3 1

#1
L 1 MI.CL: SC.CV MI.C MI.CCV

this will send any controller values to the corresponding SC.CV port on er-301. you can also add these 2 lines to watch the values in the pattern view:

L 1 MI.CL: PN 0 MI.C
L 1 MI.CL: PN 1 MI.CC
L 1 MI.CL: PN 2 MI.CCV
11 Likes

Does this mean (translated to lay-mans speak) that if I play a note it will take 0-50ms for the teletype to realize this and call assigned script? That would be bad news, since playing notes would be with sloppy timing. If so, how about the possibility to decrease this like MI.TIME 10 or something? This would allow the user to “go into record mode”, play some melody into the teletype (with almost everything else “disabled” to allow the teletype to handle the stress), and then set it back to 50ms and resume normal operation.

Maybe I’m missing something entirely, just got so excited about the prospect of recording notes into the teletype :slight_smile:

I wonder if these shouldn’t read 0…1000 range? I think this is how VV scaled values are usually handled by teletype with 100 representing 1 V.

Hi @scanner_darkly. I tested the Faderfox UC4 and it works perfectly well with my green board teletype.

One doubt about the script though. The one above send all cc controls to sc.cv port 1. How can I send cc 1 to port 1, cc 2 to port 2 and so on? Sorry for the dumb question!

I’m testing with a Launchcontrol and a 301 with the script you’ve provided.
Does the TT listen to every midi channels or only a specific channel ?

My Novation Launchcontrol is stuck on channel 9 ( I can’t modify the internal script because their software is not compatible with Catalina), the 301 doesn’t seem to receive anything so far.

I’m going to try with another controller. I’ve tried with an OP-1, but it doesn’t pair well with Teletype. (TT shuts down immediately even if the “USB-Charge” mode is set to off on the OP-1)

my er301 is receiving info sent by my faderfox uc4, regardless of the midi channel.

1 Like

Oh ok, it might be an issue with the Launchcontrol then. It could also have been an issue with my i2c bus but I’ve just tried with these additional lines in order to monitor the midi data in pattern view, directly on TT, but nothing…

Ok, I’ve re-flashed TT, tested with Roli Blocks in Fader mode. This one is working. And now it’s sending SC.CV to the 301, all routed to SC.CV 1 though

same here! But I also don’t get any response on the pattern view when introducing the additional commands.

For the pattern view, I think the controller value is missing you can try with

L 1 MI.CL: PN 0 MI.C MI.CC

And for the 301:

L 1 MI.CL: SC.CV MI.CC MI.CCV

I don’t know if it’s the correct way to do that, it briefly worked for me. but TT has just crashed, the Roli Blocks are battery powered though

Now I can read the values on the pattern page but the values are not sent to the ER301!

don’t remember why i chose this number specifically but yeah it could be reduced. i probably wouldn’t go lower than 20 though, since teletype needs to handle other tasks as well. let’s see how it feels with 50 and we’ll go from there.

MI.LV is the latest velocity, MI.LVV is that scaled it to 0…16383 range (it’s actually the same as doing * MI.LV 129 since 127*129=16383). you can scale it to any other range with SCALE, this is just to have a shortcut for likely the most common use case.

it should response to MIDI events on any channel, yes. if it’s helpful, i could add ops to get the channel as well.

yeah, sorry - had the script wrong. the correct script:
L 1 MI.CL: SC.CV MI.C MI.CCV

MI.C is the controller number.

you want MI.C (controller number) instead of MI.CC (controller value 0…127) here.

i imagine it would still try to pull power from USB. try powering it externally via monome switch or two>one, if you have those.

can you post your script?

1 Like

now it’s working. it was due to the previous error on the script. :slight_smile:

edit: my script was the one you posted initially

1 Like

I think I would have use cases for channel number.

Thanks, as always, for being so generous with your brilliance, @scanner_darkly! This looks fantastic. Can’t wait to try it out.

1 Like

Is it possible to connect both the usb controller and keyboard via a small USB hub? I don’t want to try, afraid I blow up something :smiley:

you won’t break anything but it won’t work - teletype does not support usb hubs unfortunately.

eheh. thanks for clarifying!

new MIDI IN 2 version posted. the script timer will now run every 25ms, let’s see how this works.

also added new ops to get the channel:

MI.LCH
get the channel for the latest event

MI.NCH
get the channel for the note on event at index I

MI.OCH
same for the note off

MI.CCH
same for controller

finally, added a new op to get the latest event type: MI.LE. this will be useful if you assign multiple event types to the same script. for instance, let’s say you have a sequencer scene driven by metro where variable O holds the current step, and you want to make it respond to MIDI start/stop/continue. you could do something like this:

#I
L 5 7: MI.$ I 1

#1
IF == MI.LE 5: O 0; M.ACT 1
ELIF == MI.LE 6: M.ACT 0
ELIF: M.ACT 1

the init script assigns event types 5-7 (start/stop/continue) to script 1, then in script 1 we enable/disable the metro script accordingly, and for the start event we additionally reset the current step.

4 Likes

Thank you! This is incredible.
Works perfectly with my korg nanoKONTROL2 and ER-301.

Script i used to test:

#I
MI.$ 3 1
MI.$ 1 2

#1
L 1 MI.CL: SC.CV MI.C MI.CCV

#2
L 1 MI.NL: SC.TR.P MI.N

and layout:

2 Likes