EDIT: Soz guys, just saw you are steaming ahead with the PHP stuff!! Thought this would be good for anyone stumbling upon the thread from scratch anyways... and my code at the bottom is basically your PHP code but for Arduino
Yep, its an Arduino + MIDI I/O + x8 MUXs with an LCD display connector. It has 48 analog or digital inputs and 16 digital only inputs or outputs which are grouped into '8' ports, each with 8 connections. Each port can be set to input or output.you're designing a PCB that has the Arduino-based hardware, all the muxes and the I/O, all on one board?
Not too difficult when you know how! DjNecro is correct, by using the MIDI outputted for the Denon HC4500. When you add a HC4500 to your list of controllers, Traktor will start to output MIDI for the track name, artist and time. Its not an option you can select in the 'add out' section in Traktor, it happens in the background as soon as you add the DN4500 controller and select a MIDI OUT port. I used the Denon MIDI sheet to get the infoand my big question would be, how the hell are you getting the track title / artist information out of Traktor?! There isn't any way that I know of (and I've tried literally everything!) apart from using the shoutcast/podcast hack. The problem with that is the title information gets exported after a long delay which obviously isn't ideal.
Here is the sheet I used, Denon MIDI (page 7) : DN-S3700
As only 7 bits of the MIDI data messages are available (the first bit is used to identify the message type) and the LCD needs 8 bits of data to display a character, each character needs to be transmitted in two control change messages. The first bit is used to idenfify the message, nothing to do with LCD but will be used in your code by the MIDI IN routine. The next three bits are discarded, and the final 4 bits are used for the data. The first control change message contains the first 4 bits of the 8-bit LCD character data, and the second CC message contains the second 4 bits, so....
X000AAAA
+
X000BBBB
=
AAAABBBB
Where X is the message identifier bit, the '0s' are discarded, A is the first CC and B is the second CC.
Assuming you have Arduino sucessfully receiving MIDI CC, by loading two CC messages into cc_data1 and cc_data2 the following code is a simplified way of getting the MIDI messages to the LCD. The actual code uses bitwise (see arduino website) to join the two nibbles together and simplified looks like this...
This line shifts the first 4 bits of the first message along 4 places to make
0000AAAA into AAAA0000
lcd_nibble1 = (cc_data1 << 4);
This line takes the data from the second CC message and passes it to a variable for the LCD routine
lcd_nibble2 = cc_data2;
Now we have the following
lcd_nibble1 = AAAA0000
lcd_nibble2 = 0000BBBB
Now we need to merge the two using the bitwise OR operator...
lcd_output = lcd_nibble1 | lcd_nibble2;
so now 'lcd_output' is AAAABBBB, a complete byte which can be passed straight to the lcd.print command using the standard Arduino LCD library...
lcd.print(lcd_output);
Now this code could be better as the library will break the byte up back into nibbles to pass to the LCD using the 4-bit interface (as my design uses 4-bit connection) so when I get some time, ill most likely make a few mods to the library to save some considerable processing time! However at the moment in development, this method works great and is a good way to simply use the standard Arduino LCD library in 4 or 8 bit mode.
There is one more thing, I described how to pass the CC data to the LCD but nothing about CC numbers. The value of the CC message relates to the character but the CC number determines both the character position and identifies whether the message is the first or second nibble of data. Its all in the Denon MIDI sheet. For example....
If you (or Traktor!) wanted to display the letter 'A' in the second (of 16) character position and on the first line you would use the following...
The character 8-bit code (from Denon or Hitachi LCD datasheet) is 0100 for the first nibble and 0001 for the second nibble, so...
CC message 1 = 0001 = 1 (in decimal)
CC message 2 = 0100 = 4
From the Denon sheet, CC number 2 (0x02 in hex) represents the first nibble for the second character on the first line of the display. CC number 34 (0x22 in hex) represents the second nibble for the second character on the first line of the display, so...
CC#02 value 1
CC#34 value 4
will display the letter 'A' in the second char position on the first line. BTW Deck A will output all this info on channel 1 and Deck B will output it on channel 2... so my advice if your designing a controller with the Denon LCD system, reserve ch1 and ch2 for the LCD data!
Here is the actual code with bits removed that dont relate to the LCD (easier to understand! ), please note the MIDI channel is currently ignored but a simple if or switch statement could be included to check the channel is correct or identify whether the data is from deck A or deck B, just havent got round to doing it yet! to use this code the receiveMIDI routine is fired whenever the serial port data is read and verified to be a recognised MIDI message. The following variables must be passed to the routine...
statusType = type of message, CC, note on, note off etc...
MIDIchannel = self explanatory!
param1 = first parameter of data (for CC this would be the CC number)
param2 = second parameter of data (for CC this would be the CC value)
Code:void receiveMIDI(byte statusType, byte MIDIchannel, byte param1, byte param2){ switch (statusType) { break; case 0xB0: ///// IF MESSAGE IS CONTROL CHANGE MESSAGE (0xB0) ///// switch(param1){ // CHECKS CC NUMBER, MSB GETS PUT IN tn_byte1 case 0x01: tn_byte1 = (param2 << 4); break; case 0x02: tn_byte1 = (param2 << 4); break; case 0x03: tn_byte1 = (param2 << 4); break; case 0x04: tn_byte1 = (param2 << 4); break; case 0x05: tn_byte1 = (param2 << 4); break; case 0x07: tn_byte1 = (param2 << 4); break; case 0x08: tn_byte1 = (param2 << 4); break; case 0x09: tn_byte1 = (param2 << 4); break; case 0x21: // BEGIN LSB, MSB IS READY IN tn_byte1 tn_byte2 = param2; tn_output = tn_byte1 | tn_byte2; track_name(0 , 0 , tn_output); // FIRES LCD PRINT WITH CO-ORDS AND CHAR DATA break; case 0x22: tn_byte2 = param2; tn_output = tn_byte1 | tn_byte2; track_name(1 , 0 , tn_output); break; case 0x23: tn_byte2 = param2; tn_output = tn_byte1 | tn_byte2; track_name(2 , 0 , tn_output); break; case 0x24: tn_byte2 = param2; tn_output = tn_byte1 | tn_byte2; track_name(3 , 0 , tn_output); break; case 0x25: tn_byte2 = param2; tn_output = tn_byte1 | tn_byte2; track_name(4 , 0 , tn_output); break; case 0x27: tn_byte2 = param2; tn_output = tn_byte1 | tn_byte2; track_name(5 , 0 , tn_output); break; case 0x28: tn_byte2 = param2; tn_output = tn_byte1 | tn_byte2; track_name(6 , 0 , tn_output); break; case 0x29: tn_byte2 = param2; tn_output = tn_byte1 | tn_byte2; track_name(7 , 0 , tn_output); break; } } } void track_name(byte lcd_col, byte lcd_row, byte lcd_data){ lcd.setCursor(lcd_col , lcd_row); lcd.print(lcd_data); }
Bookmarks