A circuit for midi control of panasonic video mixers

in january i started what i thought would be a fairly small “winter project” - expecting some fab delays due to Lunar NY , but with no way to predict that China would be closed in febuary, and then rest of the world in march&april ! now its almost summer and i still need to send out some prototype pcbs to testers. but im hoping to to have something you can try soon ! and meanwhile thought could document some about this project and the process so far :slight_smile:

introducing _transcribe_ :

for midi control of panasonic video mixers

for all the details you can refer to the github repo - there i try to introduce the idea:

some people in the video-art community are performing with old hardware video-mixers such as in the Pansonic_WJ_AVE and Pansonic_WJ_MX lines. some of these mixers have a RS232 serial input for interfacing with them digitally. this is especially useful for live performance where sequencing can assist physical actions. there are some cool examples of software specifically written to interface with these mixers (such as Freds excel app and Klifs MaxPatch ) , but there are many more programs and devices that are made to interface digitally using MIDI.

the aim of this project is to create a small utility module that can transcribe MIDI , a protocol used commonly in live/performance instruments to the specific RS232 panasonic video-mixer spec , to better equip these retired workstations for their new life of glamour on stage

getting started / level-shifting

this idea (for me) came from seeing a demo of Klif’s work and talking with him at Fu:bar Festival in October ( :heart: :pray: @v3d & Dina ). sometime after this @autr and i spent a weekend in berlin trying to figure out the serial conversion needed to send commands from an arduino to the panasonic mixers we had. we needed to level-shift the serial from Arduino’s TTL voltages to the Panasonic’s RS232 voltages. The tidiest way i could find to do this used a max232n capacitor pump circuit - so then decided to lay out a small pcb to handle this.

midi control

with the rs232 serial output now working i needed to decide how to receive midi messages. i had created a small opto-isolating circuit before to receive serial midi messages for recur based on the midi spec. the hardest part about this was deciding whether to use the traditional din5 midi jack footprint or the newer 3.5mm trs option. after some though i decided on a solution to please everyone:

most midi these days is sent over usb. since many arduinos have usb jacks i assumed this should be quite easy to also support. turns out usb is not so simple:

  • the ATmega328P on Arduino Uno/Nano does not support usb directly - these arduinos use external circuitry to convert the usb messages to serial which is sent to the atmega.
  • the ATmega32u4 (as seen on Arduino Leonardo) can act as a usb device - I decided to use the sparkfun ProMicro due to its usb capacities, its small size and its low cost. these can be configured to appear as a USB_MIDI_DEVICE when connected to a computer ( usb host )
  • although sequencing from a computer is pretty cool, i also wanted to be able to control my mixer with the Korg Nanokontrol midi controller i already have.
    this controller is a usb device and i discovered the usb protocol does not allow connections device-to-device or host-to-host (this is why you rarely see usb cables with the same plug-type on both ends)

image

you can find arduino shields (compatible additional circuitry) based around the MAX3421E for adding usb_host features to a project. i decided on one called the Mini USB Host Shield -> it seems the original creator of this shield (circuits@home?/DunioFun?) no longer exists but plenty of clones are available from ~$5 from china to ~$15 on amazon etc and a great library with midi_host examples exists. (note: a trace needs to be cut and a voltage regulator used to make this 3.3v ic work with the 5v usb/pro-micro - but the SPI data lines seemed to work fine between the host and uC)

finally i added the options to output serial midi (with buffers) and input rs232 serial too so the hardware can be reused for other purposes - the panasonic_ave55 i have takes serial on a 3.5mm TSR jack but some other mixers use the more common dsub-9 plug so both are also included here

some firmware challenges

meanwhile waiting over 2+ months for the boards to be fab’d, i started writing some code to do the transcribing. even if you are comfortable with c/c++ style languages (which im not really - cue montage of me watching youtube videos all night: what are pointers ? simple C pointers explained C Pointers - a REALLY SIMPLE explanation) embedded programming can be challenging:

  • you are lucky if things that break bother to tell you - more likely the program compiles and runs but then just starts acting different or all weird out of nowhere !
  • no real debugger - i ended up using serial print lines on almost every line just to stay sane
  • really limited space compared to coding for computers (both memory available for the program and the size of the compiled code itself )
  • (for me) writing ‘nice’ code and functional code seemed to conflict more often here (than in python at least!) - im still learning, hope to improve this
  • arduinoIDE is not a real ide - i recommend VisualStudioCode if you are looking for something. at first i used the arduino vscode extension, but now have switched to using PlatformIO - maybe i will make another topic about this but just say i am happy with it so far
  • finding a middle ground between providing a fixed out-of-the-box mapping, with no extra coding required, and empowering users to easily create their own non-standard maps.
  • the pro-micro has an annoying problem where it sometimes just stops receiving new code uploads. theres some combinations of reset pins, bootloader modes and perfect timing that supposedly unlocks them again - but in the end i found it much easier just to use another arduino to reburn the bootloader onto the pro-micro whenever this happens - only takes a moment and fixes it every time :slight_smile:

an example of space restraints and ‘not-so-nice’ code:

to change the wipe mode (WIPE_SQUARE_CORNER_UL) you need to send the mixer this command VWP:001. there are quite a lot of different commands (~200 or so). forget about strings and their self managed / dynamic length. even by specifically declaring constant char arrays of size 7, when you need 200 of these most of the space available (ram/flash) is full. a hack i tried that helped was replacing these char arrays with a single 8bit integer, and then in the main loop infer what the prefix should be with a giant if/else block (this works because each number is unique)

in hindsight maybe it would work better to define these commands using pre-compiler flags (#define WIPE_SQUARE_CORNER_UL "VWP:001") :thinking: but yes just an example of the kind of challenges that can arise from seemingly simple ideas…

another example is the commands that takes multiple parameters as inputs. (for example scene_select which has an x and y component, or the chromakey_select which takes r g and b ) midi doesnt have inputs with multiple params so these need to be split between difference cc channels (eg cc0 for x_position, cc1 for y_position ) but for this to work the current x and y positions need to be stored in the program (so an input on cc0 or cc1 knows where to place x and y). there is a temptation to over-engineer a solution that works for all cases but in reality there is only a few of these multi-param exceptions and it was much simpler to hard code the additional logic just for these cases.

in spite of these challenges and more the firmware is in a usable state that i am happy to share for an initial round. i want some feedback from people using it to help inform what to change for the next iteration.

v0.1 pcbs

finally got a few prototype pcbs. there are some small improvements i need to make but these are mostly working. i will update here (and elsewhere - im cyberboy666 on instagram too) when i have the v0.2 board tested incase anyone wants to try building it or eventually getting some kits or something from me

small video example:

here is a test using ableton to sequence x_select, y_select and mix_amount to some music. i will make a better demo for this when i find time

note: not all panasonic video mixers have serial control. mx10, mx12 and ave5 are too old i think. to sequence them with midi would require modifications to the circuit itself

11 Likes

um? excuse me? this is SICK

i had similar goals in soldering CV inputs to all the pots in my mx50. it’s good to know there will be other options for programmable control of non-midi mixers !

2 Likes
  • (for me) writing ‘nice’ code and functional code seemed to conflict more often here (than in python at least!) - im still learning, hope to improve this

yeah the thing about coding is the lower level you go you have to like conciously choose between the “nice” and the “useful” and to a large extent most of what you’d like to do to keep it quickly parsable by humans will actually mean it compiles worse. i’ve never actually learnt how to write nice code, my approach has usually been figure out how it compiles and interacts with the hardware and work from there on up. also pretty reasonably comfortable with c/c++ and the wonderful world of pointers at this point ( seems like the only reasonable way to deal with any streams of data and signal processing in code) so feel free to drop me a line. would be down to test this and/or throw a build and test workshop for this over at phase space whenever we get to open up to the public again!

a hack i tried that helped was replacing these char arrays with a single 8bit integer, and then in the main loop infer what the prefix should be with a giant if/else block (this works because each number is unique)

i think a lot of digital midi implementations actually use 7 bits for ccs, for the midi parameter locking code i wrote i used unsigned chars for storing all the cc information and then dynamically add smoothing via lerp and convert them into floats before they actually get used, i’m planning on sticking this into all my rpi synths once its finished up bc it also helps a lot with the steppiness of the nanokontrol2 (love the form factor and price of these but fuckin a they have some low low resolution). but yeah this is on the rpi3b, so in that context even having a couple seconds worth of buffers for 16 paramteters in chars is a drop in the bucket.

1 Like

This was a super cool project! Was using it for a music video these last weeks and it was lush to use improvisationally. Some ideas I had were:

  • Splitting fader controls across two CC values (ie. the WJ resolution is double MIDI’s 0 - 127)

  • Alternatively, ye ol’ smoothing on a continuous loop: floatyVal = ( (float)incomingVal * 0.1 ) + ( floatyVal * 0.9 ); sendCC( (int)floatyVal );

  • Perhaps manually assigning sets of wipes to a CC values, ie. while an assign key is pressed, all wipe notes are added to an array of wipes, assigned to a CC val. At this stage though probably starts making sense to think about LCDs :slight_smile:

I was also building a web GUI for managing and organising the serial specs into standardised configs when we were testing it out (the idea being to auto-generate routable interfaces), so happy to say this is making its way into 3F (eventuaaaallly).

3 Likes

the double midi cc for higher resolution is also the standard trick for high resolution digital midi, lsbs on one cc, msbs on the other for 14 bit resolution

1 Like

There is ovkours MIDI 2.0 spec out now but will be waiting until its added to alsa first.

Hi all,

finally got my components to build this – but going through and matching up the parts I’ve just realised my PCB is the older v0.1 board and the part list doesn’t quite match up with what’s on the github for v0.2 (extra diode in v0.2?).

Is there anything I need to keep in mind or should read before I start building? :slight_smile: :slight_smile:

I’ll be able to test with MX30 and MX50 when done, are there any particular combinations that need beta testing?

1 Like

Hey @doctea ! Excited you will test this out ! I have some of the v0.2 boards here , can send you if you if you want. The main difference is the footprint for the dsub connector fits the socket part now , which will be useful for mx50 / mx30 I think… since they have dsub ports.

Also yah the commands in the code are only from the ave55, I think the others will use a similar protocol but could be some small differences. We can try figure this out together when you start testing. Keep me posted ! As soon as I finish testing this 0.2 board myself happy to send out a few more boards to those interested in testing this too :innocent:

1 Like

hi @cyberboy666 :slight_smile:
in a meanwhile i got mx50. roel sent me a patch he did for mx50 and apparently many commands are similar to ave55 commands i used in my patches. the rest of commands can be digged from the manual of mx70 that has serial protocol in it. i would be interested in the boards for testing too…

hii @klif ! that is good news - yes havnt yet tried with a mx50. i was just looking through the mx70 manual we have here on scanlines wiki page but cant see the commands - are they in another manual ?

i will send u a board ! (write me your address in a pm)

I’ve submitted a PR with the protocol reference for the AG-HMX100 – as best as I can tell this is a superset of the commands for several older mixers like the MX50. At least I was able to use these commands to send wipe positions and stuff from a Python script -> USB/serial dongle -> MX50 at one point. Here is the script, used for manually typing in commands to send to the mixer, on the off chance that’s useful.

Python test code for Panasonic mixers
# dependencies (Python >= 3.5):
# aioconsole==0.1.10
# pyserial==3.4
# pyserial-asyncio==0.4

import asyncio

import aioconsole
import serial
import serial_asyncio


class WJMx50(asyncio.Protocol):
    def connection_made(self, transport):
        print('connected')
        self.transport = transport
        asyncio.ensure_future(self.repl())

    async def repl(self):
        while True:
            cmd = await aioconsole.ainput('?? ')
            self.write(cmd.encode())
        
    def write(self, cmd):
        print('-> {}'.format(cmd))
        msg = b'\x02' + cmd + b'\x03'
        self.transport.write(msg)

    def data_received(self, data):
        reply = data.strip(b'\x23')
        if not reply:
            return
        for i, byte in enumerate(reply):
            if byte == 0x15: 
                print('\n<- NAK', flush=True)
                self.prompt()
            elif byte == 0x06:
                print('\n<- ACK', flush=True)
                self.prompt()
            elif byte == 0x02:
                self.start_message()
            elif byte == 0x03:
                self.end_message()
            else:
                self.feed_message(byte)
    
    def start_message(self):
        self.reply = bytearray()

    def feed_message(self, byte):
        self.reply.append(byte)

    def end_message(self):
        print('\n<- {}'.format(bytes(self.reply)), flush=True)
        self.prompt()

    def prompt(self):
        print('?? ', end='', flush=True) 

loop = asyncio.get_event_loop()
coro = serial_asyncio.create_serial_connection(
    loop,
    WJMx50,
    'COM3',  # or whatever yr comport is
    bytesize=serial.SEVENBITS,
    parity=serial.PARITY_ODD,
    stopbits=serial.STOPBITS_ONE
)
loop.run_until_complete(coro)
loop.run_forever()
loop.close()

I believe I originally found this PDF at this link.

1 Like

thanks @csboling thats super useful ! will use this to add to the transcribe project / support more mixers :smiley:

1 Like

i made a mistake, it was AG-HMX100 manual :smiley:

I’ve got a Sony FXE-100 at the center of my rig but I can’t for the life of me tell for sure whether or not it will respond to RS-232 control in real time. It has a bunch of RS232 and RS422 output capability, but it looks like the input might only be for uploading and downloading EDL data. But the manual’s really vague on the topic, and also mentions using it with an external edit controller with no details at all.

I don’t have any way to test it unfortunately, but if anyone has any insight and it DOES turn out to respond to real time control I’d love to build one and help in any way I could with adapting it to Sony hardware.

Seems like a bit of a long shot unfortuantely but maybe I’m missing something.

EDIT: every manual I’ve been able to find since I got it 4 years ago is a variation of this one:
https://www.manualslib.com/manual/907683/Sony-Fxe-100.html

1 Like

I couldn’t find any documentation for the Kramer VS-88V matrix switch that we were talking about in the cheap gear thread, but someone has already made a VVVV patch for controlling it so that should be a good starting point if you were interested in adding support. MIDI control of a matrix switcher would be excellent, especially if it was possible to map MIDI channel to device number so multiple daisy chained switches could be controlled on different MIDI channels from a single control board.

Being able to sequence complex routing changes (or change them generatively) is really powerful, and MIDI control would make it possible without using a computer, even if it was something as simple as mapping MIDI notes to the VS-88v’s user memory locations would do a lot.

If you’re interested in trying it I’d be happy to build a board and help test it.

chat.scanlines.xyz