Saturday, July 25, 2015
MPG-200 PCBs ordered from DirtyPCBs
I ordered what is hopefully the final version of the MPG-200 cards from DirtyPCBs last night. If all things go to plan I will get approximately 40 boards somewhere next month. Exciting!
Tuesday, July 21, 2015
WebMIDI and the MPG-200
A couple of days ago I put the final touches on a settings editor that can generate sysex for changing the MPG-200 internal settings like CC mappings and midi channel etc.
I wrote everything using javascript and HTML, and initially made it generate a sysex file that you could download and send using your favourite tool.
As an experiment, I thought I'd make it possible to send the data directly to the device using the newly available WebMIDI standard. I had a few issues but now it seems to work nicely.
I have been using Google Chrome to do the development, and there are a few things to be aware of:
1) In WebMIDI you have to ask the user for access to sysex messages. In Chrome, this cannot be done if the javascript file is accessed as a local file or from a local html file (file://...). Neither can it be accessed through an insecure connection (I assume this means you have to use HTTPS).
To get around this, I installed a tiny webserver (The TinyWeb actually) locally and ran the code through it. Works like a charm.
2) You have to send the complete sysex message in one go - it must start with F0 and end with F7. You cannot send the messages in blocks so the message has to be calculated up front.
3) Running status is not allowed, as with the sysex message each message has to be self contained and complete.
The sysex editor and my WebMIDI code is found on the Xonik webside, but as I said, you cannot use the WebMIDI part directly as it is not served over HTTPS.
I wrote everything using javascript and HTML, and initially made it generate a sysex file that you could download and send using your favourite tool.
As an experiment, I thought I'd make it possible to send the data directly to the device using the newly available WebMIDI standard. I had a few issues but now it seems to work nicely.
I have been using Google Chrome to do the development, and there are a few things to be aware of:
1) In WebMIDI you have to ask the user for access to sysex messages. In Chrome, this cannot be done if the javascript file is accessed as a local file or from a local html file (file://...). Neither can it be accessed through an insecure connection (I assume this means you have to use HTTPS).
To get around this, I installed a tiny webserver (The TinyWeb actually) locally and ran the code through it. Works like a charm.
2) You have to send the complete sysex message in one go - it must start with F0 and end with F7. You cannot send the messages in blocks so the message has to be calculated up front.
3) Running status is not allowed, as with the sysex message each message has to be self contained and complete.
The sysex editor and my WebMIDI code is found on the Xonik webside, but as I said, you cannot use the WebMIDI part directly as it is not served over HTTPS.
MPG-200 final hw version finished
Just finished what I hope will be the final version of the MPG-200 hardware, correcting the small mistakes with the previous verson. Will probably order a batch from dirtypcbs soon.
Friday, July 10, 2015
Decoding the 68b01 keyboard scanner
Returning to the Prophet VS service manual, I noticed that the output bus from the keyboard scanner runs through a set of latches. This means that bus communication is one way only. In addition to the bus, the only pins connecting the scanner to the main MCU are the KYBD and KYINT lines. Thus, the communication protocol should be fairly simple.
I connected logic probes to various parts of the 68B01 and its surrounding components. First to the CD4022 octal counter to see how the keyboard lines are scanned. Then to the rows to see which ones are connected to the first and second set of keys. I registered the data on the output bus while pressing keys to understand the protocol. I also checked the KYBD and KYINT lines while monitoring the data bus to see how the MCUs interacted.
The velocity was a bit trickier to get right. I needed to know the interval between hitting the first key and the second key, and at the same time registering the data bus output. I only have 8 probes on my logic decoder, but luckily, the velocity is 7 bit only, and by ignoring the least significant bit I could still get quite accurate velocity measurements.
What I found was that certain number of rounds of scanning the keys in between first and second keys made contact corresponded to a certain velocity. In other words, there is no 'free running' counter used for calculating velocity, one only needs to know how many times the keys have been scanned. This makes sense, as the only legal intervals corresponds to the times the keys are scanned.
I got a nice surprise when I made a plot of the velocity versus the scan cycle count. It turns out the velocity is a faux exponential curve, much like the way an analog audio-scale potentiometer works. For the first quarter of the measured cycles the velocity follows a steep line. For the other three quarters it follows a much flatter line. This, of course, makes calculating the velocity much easier (without the use of a lookup table. In that case any curve would be equally simple).
(Disclaimer: The lines measured are not perfectly flat even if I try correcting for a +/- 1 error. This means that there is actually some kind of timer involved that is not connected directly to the keyscanner cycles. However, when recreating the program it will be sufficient to count cycles as long as cycle lengths are constant)
Here are some details about the scanner:
The keys are scanned column-by-column. The first column is turned on for about 70uS, the rest for 52uS. The total period (time between successive scans of the same column) is 432uS, giving a scan frequency of about 2.3kHz.
The columns are scanned by clocking a CD4022 octal counter. Each clock pulse is approximately 2.5uS wide. The carry out from the CD4022 alternates between 0 and 1 every four clock pulses.
Data transfer works like this:
When the scanner has something to send, it lowers the KYINT line. At the same time, it puts the data on the output bus. Approximately 10uS later, the main MCU lowers the KYBD line. This turns on the 74HC367 transparent latches and puts the data on the databus, and at the same time signals to the scanner that it is reading data. KYBD stays low for about 0.25uS. The scanner waits an additional 10uS and then puts the next data byte on the output bus. The main MCU seems to read the data bus until it gets a 0 (0 on the bus is not a valid note on or velocity).
The data format is equally simple:
Note on is sent as two bytes: Note and Velocity
Note off is sent as a single byte: Note.
Both note and velocity are seven bit values. To differenciate between Note on and off, the MSB is always 1 for note on and 0 for note off. MSB is always 0 for velocities.
The lowest key on the keyboard, C0, is sent as x0100100 (x being 1 or 0 depending on note on/off), so the note value to send is simply 36 + key number.
Velocities:
Time t from key is pressed until it reaches bottom is x * 432uS + 571uS, where x is the number of times the first switch is scanned before it reaches bottom.
An approximation to the velocity transfer curve is as follows (not rounded):
[0, 1]: y = 127
[2,19]: y = 124 + (1867uS - t) / 80
[20,69]: y = 38 + (8779uS - t) / 570
[70, ->: y = 0
If more than 70 scan cycles are reached without the key hitting the bottom, a note on with velocity 0 is sent (and a note off is sent when the key is released later).
where
x = number of key scan cycles
y = velocity sent to master
This will of course not be an easily calculateable curve, so one is better off using a lookup table.
Important I/O pins:
Pins 13-20 corresponds to row 0-7 of the key press start switches
Pins 37-30 corresponds to row 0-7 of the key at bottom switches (NB: reverse order!)
Pins 22-29 are the output data bus pins
Pin 8 is clocking the CD4022 column selector
Pin 9 reads the carry bit from the CD4022
Pin 12 is the KYINT bit that must be set low before data transfer
Pin 39 is the KYBD bit that can be used to detect that the master reads the data.
I connected logic probes to various parts of the 68B01 and its surrounding components. First to the CD4022 octal counter to see how the keyboard lines are scanned. Then to the rows to see which ones are connected to the first and second set of keys. I registered the data on the output bus while pressing keys to understand the protocol. I also checked the KYBD and KYINT lines while monitoring the data bus to see how the MCUs interacted.
The velocity was a bit trickier to get right. I needed to know the interval between hitting the first key and the second key, and at the same time registering the data bus output. I only have 8 probes on my logic decoder, but luckily, the velocity is 7 bit only, and by ignoring the least significant bit I could still get quite accurate velocity measurements.
What I found was that certain number of rounds of scanning the keys in between first and second keys made contact corresponded to a certain velocity. In other words, there is no 'free running' counter used for calculating velocity, one only needs to know how many times the keys have been scanned. This makes sense, as the only legal intervals corresponds to the times the keys are scanned.
I got a nice surprise when I made a plot of the velocity versus the scan cycle count. It turns out the velocity is a faux exponential curve, much like the way an analog audio-scale potentiometer works. For the first quarter of the measured cycles the velocity follows a steep line. For the other three quarters it follows a much flatter line. This, of course, makes calculating the velocity much easier (without the use of a lookup table. In that case any curve would be equally simple).
Plot of cycles vs velocity |
(Disclaimer: The lines measured are not perfectly flat even if I try correcting for a +/- 1 error. This means that there is actually some kind of timer involved that is not connected directly to the keyscanner cycles. However, when recreating the program it will be sufficient to count cycles as long as cycle lengths are constant)
Here are some details about the scanner:
The keys are scanned column-by-column. The first column is turned on for about 70uS, the rest for 52uS. The total period (time between successive scans of the same column) is 432uS, giving a scan frequency of about 2.3kHz.
The three first columns and their scan pulses |
Data transfer works like this:
When the scanner has something to send, it lowers the KYINT line. At the same time, it puts the data on the output bus. Approximately 10uS later, the main MCU lowers the KYBD line. This turns on the 74HC367 transparent latches and puts the data on the databus, and at the same time signals to the scanner that it is reading data. KYBD stays low for about 0.25uS. The scanner waits an additional 10uS and then puts the next data byte on the output bus. The main MCU seems to read the data bus until it gets a 0 (0 on the bus is not a valid note on or velocity).
The data format is equally simple:
Note on is sent as two bytes: Note and Velocity
Note off is sent as a single byte: Note.
Both note and velocity are seven bit values. To differenciate between Note on and off, the MSB is always 1 for note on and 0 for note off. MSB is always 0 for velocities.
The lowest key on the keyboard, C0, is sent as x0100100 (x being 1 or 0 depending on note on/off), so the note value to send is simply 36 + key number.
Velocities:
Time t from key is pressed until it reaches bottom is x * 432uS + 571uS, where x is the number of times the first switch is scanned before it reaches bottom.
An approximation to the velocity transfer curve is as follows (not rounded):
[0, 1]: y = 127
[2,19]: y = 124 + (1867uS - t) / 80
[20,69]: y = 38 + (8779uS - t) / 570
[70, ->: y = 0
If more than 70 scan cycles are reached without the key hitting the bottom, a note on with velocity 0 is sent (and a note off is sent when the key is released later).
where
x = number of key scan cycles
y = velocity sent to master
This will of course not be an easily calculateable curve, so one is better off using a lookup table.
Important I/O pins:
Pins 13-20 corresponds to row 0-7 of the key press start switches
Pins 37-30 corresponds to row 0-7 of the key at bottom switches (NB: reverse order!)
Pins 22-29 are the output data bus pins
Pin 8 is clocking the CD4022 column selector
Pin 9 reads the carry bit from the CD4022
Pin 12 is the KYINT bit that must be set low before data transfer
Pin 39 is the KYBD bit that can be used to detect that the master reads the data.
Please don't butcher your synths!
A friend of mine recently brought me a Prophet VS he bought some time ago. The synth had some serious issues - while it worked perfectly over MIDI, 24 of the keys on the keyboard did not work as they should. 16 of the keys did not work at all, while 8 worked but always triggered the notes at maximum velocity. He considered selling the synth, but I was intrigued by the problem and asked him to wait for a while so I could look into the problem.
After consulting the service manual, I quickly realised that the keys in question were connected to three row-input lines of the keyboard scanning circuit. This got my hopes up, as it could simply be a matter of a few corroded or short circuited data lines.
I opened up the synth and within seconds came to the conclusion that it had to be something way more serious. Someone had, quite visibly, tried to fix this synth before. Aside from the fact that most of the screws holding the lid were missing, there were a few modifications, repair jobs and even a custom replacement for one of the CEM5580 sample and hold chips. Not a problem in itself, but surely a sign that this synth was in need of some love and care.
The biggest shock came when looking at the keyboard scanner chip. This chip, a Sequential Circuits 68B01, is a rebranded (or cloned) motorola 6801 microcontroller. Take a look at the pictures below:
Someone has cut deep grooves into the packaging and soldered new pins to the exposed internal connectors! I can only guess why - perhaps they cut the legs to get the chip loose from a PCB instead of trying to desolder it, or maybe one or more of the legs broke and they had to dig into the chip to reattach it. Whatever the reason, the person doing this must either have been well informed and highly competent, extremely brave or just desperate. The 68b01 is a very rare chip, and replacing it with a off-the-shelf 6801 will not work as it contains custom firmware. I guess if I owned this synth and the chip died, I could have tried something similar, after all you have little to lose if it does not work in the first place.
The chip even had a small wire connecting the first and second key switches for one of the rows. Now, the first switch detects when the key leaves the top position and the second when it reaches the bottom. The time between is used to calculate velocity. When they are connected, the effect will be that the synth thinks the key instantly hits the bottom position. This explains why 8 of the keys only played at maximum volume.
I tried resoldering the pins and even removing the wire, but this did not help. The chip is defective.
Luckily it seemed that the only defective parts are the row inputs. The chip still sends keypresses for most of the keys, which means it would be possible to decode the protocol. This lead to the only sane conclusion - I had to create a custom drop-in replacement. Challenge accepted!
After consulting the service manual, I quickly realised that the keys in question were connected to three row-input lines of the keyboard scanning circuit. This got my hopes up, as it could simply be a matter of a few corroded or short circuited data lines.
I opened up the synth and within seconds came to the conclusion that it had to be something way more serious. Someone had, quite visibly, tried to fix this synth before. Aside from the fact that most of the screws holding the lid were missing, there were a few modifications, repair jobs and even a custom replacement for one of the CEM5580 sample and hold chips. Not a problem in itself, but surely a sign that this synth was in need of some love and care.
This is probably a factory fix but still looks funny |
This could also be a factory fix, but the left resistors look horrible |
Someone has smudged the print on this SaH chip. Maybe we could do a finger print analysis? |
One of the CEM5510s has been replaced with a cool looking mod. |
The biggest shock came when looking at the keyboard scanner chip. This chip, a Sequential Circuits 68B01, is a rebranded (or cloned) motorola 6801 microcontroller. Take a look at the pictures below:
Someone has cut deep grooves into the packaging and soldered new pins to the exposed internal connectors! I can only guess why - perhaps they cut the legs to get the chip loose from a PCB instead of trying to desolder it, or maybe one or more of the legs broke and they had to dig into the chip to reattach it. Whatever the reason, the person doing this must either have been well informed and highly competent, extremely brave or just desperate. The 68b01 is a very rare chip, and replacing it with a off-the-shelf 6801 will not work as it contains custom firmware. I guess if I owned this synth and the chip died, I could have tried something similar, after all you have little to lose if it does not work in the first place.
The chip even had a small wire connecting the first and second key switches for one of the rows. Now, the first switch detects when the key leaves the top position and the second when it reaches the bottom. The time between is used to calculate velocity. When they are connected, the effect will be that the synth thinks the key instantly hits the bottom position. This explains why 8 of the keys only played at maximum volume.
I tried resoldering the pins and even removing the wire, but this did not help. The chip is defective.
Luckily it seemed that the only defective parts are the row inputs. The chip still sends keypresses for most of the keys, which means it would be possible to decode the protocol. This lead to the only sane conclusion - I had to create a custom drop-in replacement. Challenge accepted!
Subscribe to:
Posts (Atom)