Convert "old" electronic piano to play MIDI, programming help

Hi,
I’m new to arduino and have only basic knowledge in programing. I’m now deep inside a project where I have bite off way more than I can chew, and now need some help.

My project is to convert an “old” electronic piano (Yamaha CP25) to play MIDI by an Arduino Uno Rev.3 with a “Musical Instrument Shield”. SparkFun Music Instrument Shield - DEV-10587 - SparkFun Electronics

So far I have managed to break out and convert the signal inside the piano into digital signals.
The 5 signal I getting out from the piano is ordered like this:
SY: Synchronization signal. Pulse positive 1us every 48us to sync all the signals (us=microsec.)
KC1/KC2/KC3/KC4: These simultaneously sends a 4-bit key code every 1us that contain all the information needed. 3 nibbles (=3us) is needed to represent a happening (for example a key is pressed down).
See http://ebookbrowse.com/yamaha-cp-35-service-manual-pdf-d426696899 page 14 (-15-)

1: I read that “Each machine instruction requires one clock cycle at 16MHz”. Does that mean I can write approx. 15 instructions in between every 1us reading? Is there any way to know now exactly how many machine instruction a specific loop takes? I gess I can put in a write to LedPin and measure the loop whith my osiloscope, or is it possible to compile the code into machine code and just look at it?

2: I know I probably need to prescale the arduino timer to get a higher resolution, but how will this affect the rest of the code, and how will it work with the MIDI serial protocol that operates at 31,250 bits per second? Or is there a better way getting the 1us sampling? Do I set booth the baud rate and the prescaler in the setup code?

3: This is how I think the program should be built up, but sins my lack of knowledge/ experience I would really appreciate some input on this, and maybe even get a better suggestion on how to structure the code.

Setup
   Prescale to 0.5us resolution
   Set MIDI baud rate: 31250 (for output onley?)
   Sync arduino clock to SY-signal
loop 
	if  (SYpin == HIGH)		Wait for SY-signal to trigger
	   for  (int i=0; i=16; ++1)	Loop 16times (16*3=48us). 
              for (int j=0; j=3; ++1)	Loops for 3nibbles (3us)
    	         PORTD* 		Read KC1-4 simultaneously every 1us	
 	         nop(delay)             To make the for loop take 1us	
 	      If.. else..		Some code to translate PORTDs data into MIDI-signal
 	      Write 			Send MIDI-command to shield

*Will the PORTD overwrite its own data every time it’s reading new values, or is there a way to avoid this?

Or is this code better sense it minimize the code in between the readings and avoid PORTD overwriting its data.

Setup
   Prescale to 0.5us resolution
   Set MIDI baud rate: 31250 
   Sync arduino clock to SY-signal
loop 
	if  (SYpin == HIGH)		Wait for SY-signal to trigger
	   for  (int i=0; i=16; ++1)	Loop 16times (16*3=48us). 
  		PORTD		        Read the 1:th nibble	
    	        If.. (translate)	prepare MIDI code
	        Store			
		nop(delay)
		PORTD		        Read the 2:nd nibble		
    	        If.. (translate)	prepare MIDI code
	        Store				
		nop(delay)
  		PORTD		        Read the 3:d nibble		
    	        If.. (translate)	prepare MIDI code
	        Store			
	        Write			Send MIDI-command to shield
	        nop(delay)

It is possible to have a assembly/S-file/map/something file output, that shows the assembly code with the code address.

This is typically something to do in hardware.
I'm not sure how to do it.
My first idea is to use two cascaded parallel-in-serial-out chips (74HC165). And use the clock signals for the chips and for an interrupt to the Arduino. The Arduino has to read 16 bits parallel every 48 us.
However, you have to read 4 (or 7 ?) of those serial data lines. So you would need 42 74HC165 chips and 416 input pins and process all of that in 48us.
I think that is not possible.

The interrupt itself uses already 5us, http://gammon.com.au/interrupts

Midi output is easy: http://arduino.cc/en/Tutorial/Midi

Could it be made with a dedicated Arduino ? or dedicated avr chip without the extra hardware that only reads the serial input ? I think not.
The code you suggested to read the input stream will work, but you have to get the data out somehow and that is the problem.

You might want to share the work between two arduinos, one to listen to the piano and only send information when something changes, and the other to read that info and change it to MIDI.

Even though the information comes quickly, most of the time it will be the same as before.

1: I read that “Each machine instruction requires one clock cycle at 16MHz”. Does that mean I can write approx. 15 instructions in between every 1us reading? Is there any way to know now exactly how many machine instruction a specific loop takes? I gess I can put in a write to LedPin and measure the loop whith my osiloscope, or is it possible to compile the code into machine code and just look at it?

Instructions are typically 1 to 3 clock cycles. It's all documented in the datasheet, near the end.

That seems incredibly fast for a keyboard.

2: I know I probably need to prescale the arduino timer to get a higher resolution, but how will this affect the rest of the code, and how will it work with the MIDI serial protocol that operates at 31,250 bits per second? Or is there a better way getting the 1us sampling? Do I set booth the baud rate and the prescaler in the setup code?

All 3 timers can be prescaled by 1, which means they count once every clock cycle. The serial hardware outputs regardless of the timer prescalers (it has its own registers which control baud rate based on the system clock).

miol:
KC1/KC2/KC3/KC4: These simultaneously sends a 4-bit key code every 1us that contain all the information needed. 3 nibbles (=3us) is needed to represent a happening (for example a key is pressed down).

I don't quite read page 16 as saying you need to do things every 1 µs.

For one thing CKT is a 3 µS pulse, based on the system clock of 1 µS.

Secondly, what you really need is transitions, I gather that the four signals you mention merely correspond to keypresses, and you aren't going to be pressing keys every µS.

It all looks rather complex, it might be easier to just get the keypresses for each key and feed them into a number of input shift registers, and poll those, as Erdin suggested.

Thanks for all the input and I will consider to use a second arduino I think, but I starting to doubt that even that is enough? I didn’t realized the time it takes to write with that slow baud rate. I need at least 320us just to send one MIDI data byte(10bit) and I need to send 3 of does for a complete MIDI message. This is looking really bad indeed.

As suggested it is a lot of data that repeats itself, but by the way the signal is build up it is hard to sort it out. There is possible to read the signals for 6us and then pause for 9us for the arduino to work , and also it repeat itself every 48us for most of the time. By looking at the transitions every 48us and run dual arduinos I might be able to pull this off?

How do I make the PORTD not overwrite its own data when it repeats for up to 2x48cycles?

miol:
Thanks for all the input and I will consider to use a second arduino I think, but I starting to doubt that even that is enough? I didn’t realized the time it takes to write with that slow baud rate. I need at least 320us just to send one MIDI data byte(10bit) and I need to send 3 of does for a complete MIDI message. This is looking really bad indeed.

Not at all. How do you think MIDI works, if the MIDI rate is that slow?

Take a look at this:

That was done with an Arduino, and the playing is faster than I can play.

In that video not only is the MIDI being sent down one serial port, another one is sending the stuff you see echoed on the screen, greatly expanded to make it readable.

Thanks for the inspiring video and no, Midi isn’t slow for its purpose but my signal in is too fast and whit only microseconds to send data it seems slow.

But how to make the PORTD not overwrite its own data when it repeats for several times? Do I really need an external input shift registers for this, or can I just use a software Linear Feedback Shift Register(LFSR).

miol:
But how to make the PORTD not overwrite its own data when it repeats for several times?

I'm not sure I really understand this question. What "own data"?

miol:
Thanks for the inspiring video and no, Midi isn’t slow for its purpose but my signal in is too fast and whit only microseconds to send data it seems slow.

The figures on the left of my video are microseconds, and you can see that even in the fast passages the notes are something like 2000 µS apart.

I'm not sure I really understand this question. What "own data"?

Sense I need to need to run the PORTD for several cycles/loops it will write to the same pin(=bit/variable?) every 1us for at least 48us to compare it to the next cycle of 48us.
But the pin will only store the last value given it, and I need it to store all 48 values in the cycle.

Probably there is me that don’t understand how pin registrations and data storage (or PORTD) really works?

Thanks for helping!

miol:
Sense I need to need to run the PORTD for several cycles/loops it will write to the same pin(=bit/variable?) every 1us for at least 48us to compare it to the next cycle of 48us.
But the pin will only store the last value given it, and I need it to store all 48 values in the cycle.

Probably there is me that don’t understand how pin registrations and data storage (or PORTD) really works?

I'm sorry but that doesn't make a lot of sense: "run the PORTD for several cycles/loops"

But the pin will only store the last value given it, and I need it to store all 48 values in the cycle.

The cycle?

I thought you were reading from the piano hardware, not writing to it. Reading from the keyboard and writing MIDI. Or don't I have the right end of the stick?

Way doesn't make a lot of sense? Remember that I am a rookie in programming

Yes that is correct, but the piano signals is already coded in 3x16nibbles=48nibbles and there for I need to read 48PORTD for 48us to get the complete signal to convert into MIDI. The word cycles maybe the wrong word to use.

Well for a start the relevant clock is every 3 µS not every 1 µS, namely CKT.

Next I don't think you need to read at that rate. Note that a keypress seems to correspond with a change in BRT or MKT, so surely just waiting for those (eg. on an interrupt) to change would be sufficient?

Once you get that change you simply query what the other signals are (B3T, B2T, B1T etc.). It looks like you may only have 3 µS to do that before the change goes away, so timing will be tight.

Something like the MCP23017 port-expander could work. You can plug 16 inputs into it and it can generate an interrupt when any of those change.

That particular device will remember the state of all of its ports upon an interrupt, so you would then be able to query all of the signal lines to see which were set and which were not.

I need to read 48PORTD for 48us to get the complete signal to convert into MIDI. The word cycles maybe the wrong word to use.

PORTD is an output port. To read it you need to read PIND.

Plus I don't really see how doing it "for 48 µS" helps. You have to do it continuously. This is why I suggest interrupts.