*BUILD LOG* 'CDJ 2000'-style DIY Traktor controller - Page 17
Page 17 of 21 FirstFirst ... 7131415161718192021 LastLast
Results 161 to 170 of 209
  1. #161
    Tech Wizard Siytek's Avatar
    Join Date
    Apr 2011
    Location
    UK
    Posts
    36

    Default

    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

    you're designing a PCB that has the Arduino-based hardware, all the muxes and the I/O, all on one board?
    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.

    and 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.
    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 info

    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); 
      
      
    }
    Last edited by Siytek; 04-14-2011 at 06:33 AM.

  2. #162
    Tech Guru MiL0's Avatar
    Join Date
    May 2009
    Location
    Brighton / Bangkok
    Posts
    1,386

    Default

    that's some next level bizness you've got going there man

    so do you plan to commercialise the pcb you're prototyping? you could make a tidy sum if they came fully programmed and with all the components soldered on to the board.

    edit: this probably needs a new thread?

    you could add your findings to this thread: http://www.djtechtools.com/forum/showthread.php?t=18512

    or start a new one...

  3. #163
    Tech Mentor oskars's Avatar
    Join Date
    Jul 2010
    Location
    Stockholm
    Posts
    140

    Default

    Siytek, do I need anything else than a Arduino + Display to make that hack possible?
    Why buy something, when you can build it yourself for the double cost?

    Check my project! DIY DJ Controller (gamepad PCB)
    http://www.djtechtools.com/forum/showthread.php?t=18627

  4. #164
    Tech Wizard Siytek's Avatar
    Join Date
    Apr 2011
    Location
    UK
    Posts
    36

    Default

    so do you plan to commercialise the pcb you're prototyping? you could make a tidy sum if they came fully programmed and with all the components soldered on to the board.
    MiL0, I started out making for fun and with intention to make custom controllers for my synths and live set but I really love the electronics and have defiantly been considering making up some boards if there is a market. This forum is the first time I have told anyone about my project less my friends and family and a bit on facebook, I guess im at a stage where a lot of my development stuff is working as it should be but I need to know what people want in order to design a finished product people will want! Maybe the idea is something like the MIDIBOX64, but based around Arduino to make it easy for people to program, and the boards can be purchased complete or as a kit instead of it just being a load of designs like the uCapps stuff

    edit: this probably needs a new thread?
    I will defo be posting about the project a bit often in the near future, im mega-busy programming a live set at the moment but after the gig I shall put in some more time. I posted on here as I thought I should start getting involved with people who are playing with Arduino for music tech and DJ purposes, swapping knowledge and ideas is always good, I just wanted to show people what I could do with it so I could maybe pass on any ideas for the project this thread is about

    do I need anything else than a Arduino + Display to make that hack possible?
    oskars, additional to the display you just need a MIDI IN connector on your Arduino. I believe some people use the Roland Serial to USB MIDI driver and actually use the Arduino programmer USB cable to transmit the MIDI to the Arduino, I have never tried this but im sure there is some stuff on google. I use an opto-isolator to connect the MIDI plug straight to the RX on the ATMega, basically a MIDI IN shield

    You can buy a MIDI IN shield like this one from sparkfun (it has I and O)... http://www.sparkfun.com/products/9595

    or you can make one like this... http://www.instructables.com/id/Arduino-MIDI-in-shield/

    Anyways... I dont want to get too off the track of the thread! when my project is documented ill post a link / make a thread etc... ill continue to be involved with this thread tho, im interested to see if anyone develops the LCD stuff a bit more

  5. #165

  6. #166
    Tech Mentor
    Join Date
    Feb 2011
    Location
    Southern Ontario, Canada
    Posts
    244

    Default

    Quote Originally Posted by Siytek View Post
    Here is the sheet I used, Denon MIDI (page 7) : DN-S3700
    You may want to take a look at the spec sheet for the hc4500 (the controller that traktor supports) ... It seems as though a few of the midi commands specific to the font and the segments have changed...

    Compare the pdf you posted with this one (taken from the hc4500 product page): http://www.denondj.com/Assets/DImage...1916faea9a.pdf

    Thanks so much for your code and post.. I'm going to have fun picking through it in a bit. Depending on my available time I may even turn it into a library to make things easier for all

    MiL0: You may want to look into converting the hex to decimal and then (assuming ahk has the ability) use something similar to chr() to print out the ascii... That should get you all the text from the font table (you won't get the custom characters that way though).

  7. #167
    Tech Guru MiL0's Avatar
    Join Date
    May 2009
    Location
    Brighton / Bangkok
    Posts
    1,386

    Default

    okay, so without any understanding of Autohotkey syntax(!), does this look like it would do the job:

    Code:
    !F1::			          ; adds a windows hothey (alt+F1)
     X:= 0x32                     ; Hex 32 is equivalent to Decimal 50
     X:= X + 0                    ; adding zero to a Hex number converts it to Dec
     Msgbox X=%X%            ; this Msgbox command should display Dec 50
     msgbox % Chr(X)	   ; this Msgbox command should display Chr 2
    
     RETURN
    Now I just need it to read certain hex characters from midi and then output the text to the LCD.

  8. #168
    Tech Mentor
    Join Date
    Feb 2011
    Location
    Southern Ontario, Canada
    Posts
    244

    Default

    Quote Originally Posted by MiL0 View Post
    okay, so without any understanding of Autohotkey syntax(!), does this look like it would do the job:

    Code:
    !F1::			          ; adds a windows hothey (alt+F1)
     X:= 0x32                     ; Hex 32 is equivalent to Decimal 50
     X:= X + 0                    ; adding zero to a Hex number converts it to Dec
     Msgbox X=%X%            ; this Msgbox command should display Dec 50
     msgbox % Chr(X)	   ; this Msgbox command should display Chr 2
    
     RETURN
    Now I just need it to read certain hex characters from midi and then output the text to the LCD.
    It seems okay to me (looks odd though ) I'm not sure abut the last line though... it seems different than the previous command that does the same thing (displays something).

    Wouldn't it be something like: Msgbox X= Chr(%X%) ? Though I don't know the language... however, assuming X is the decimal value, and Chr() works as it does everywhere else, that should work...

  9. #169
    Tech Mentor
    Join Date
    Feb 2011
    Location
    Southern Ontario, Canada
    Posts
    244

    Default

    Here's what I came up with... It's not a library, but it is fairly self contained (independent of the midi code):

    Code:
    #include <WProgram.h>
    #include <LiquidCrystal.h>
    #include <Midi.h>
    
    struct DENON_SEGMENT {
      boolean valid;
      byte seg;
      byte col;
      byte val;
    };
    
    class MyMidi : public Midi {
      public:
    
      MyMidi(HardwareSerial &s) : Midi(s) {}
    
      void handleControlChange(unsigned int channel, unsigned int controller, unsigned int value) {
        if (channel == 1 || channel == 2) {
          DENON_SEGMENT data = checkForSegmentData(controller, value);
          if (data.valid == true) track_name(data.seg, data.col+2, data.val); // col+2 to center it on my 2x16 screen (the denon only has a 2x12)
        }
      }
    };
    
    MyMidi midi(Serial);
    LiquidCrystal lcd(8, 11, 9, 4, 5, 6, 7); // initialize the library with the numbers of the interface pins
    
    void setup() {
      lcd.begin(2, 16);
      digitalWrite(14, HIGH);
      midi.begin(0);
    }
    
    void loop() {
      midi.poll();
    }
    
    struct DENON_SEGMENT checkForSegmentData(byte controller, byte value) {
      static byte seg1MSB, seg2MSB = 0;
      if ((controller >= 0x01 && controller <= 0x05) || (controller >= 0x07 && controller <= 0x0D)) { // segment 1 MSB
        seg1MSB = value;
        return (DENON_SEGMENT){false,0,0,0}; // incomplete packet
      }
      if (controller >= 0x0E && controller <= 0x19) { // segment 2 MSB
        seg2MSB = value;
        return (DENON_SEGMENT){false,0,0,0}; // incomplete packet
      }
      if ((controller >= 0x21 && controller <= 0x25) || (controller >= 0x27 && controller <= 0x2D)) { // segment 1 LSB
        return (DENON_SEGMENT){true, 0, getColumn(controller, 1), ((seg1MSB<<4) + value)}; // return completed packet
      }
      if (controller >= 0x2E && controller <= 0x39) { // segment 2 LSB
        return (DENON_SEGMENT){true, 1, getColumn(controller, 2), ((seg2MSB<<4) + value)}; // return completed packet
      }
    }
    
    // parameters: cc- controller number, seg- segment number
    // returns: column number (zero indexed) or 255 if invalid segment
    byte getColumn(byte cc, byte seg) {
      byte col=255;
      if (seg == 1) {
        col = cc - 33; // convert into segment number (column)
        if (col >= 6) col--; // work around the fact that Denon skipped 0x06 for segment 1-6 (they got segment 2 correct)
      } else if (seg == 2) {
        col = cc - 46; // convert into segment number (column)
      }
      return col;
    }
    
    void track_name(byte lcd_row, byte lcd_col, byte lcd_data){
      lcd.setCursor(lcd_col, lcd_row);
      lcd.print(lcd_data); 
    }
    AAAAANNNND A video

    http://www.youtube.com/watch?v=vWo-atD1ufw
    Last edited by DjNecro; 04-14-2011 at 09:02 PM.

  10. #170
    Tech Wizard Siytek's Avatar
    Join Date
    Apr 2011
    Location
    UK
    Posts
    36

    Default

    Nice!! I like the code that deals with the fact that Denon missed out CC#06, I know the switch case was prob not the neatest way of doing it!

    It seems as though a few of the midi commands specific to the font and the segments have changed...
    I think thats just the 4500 only giving you CCs for 12 segments for the LCD (im guessing because it only has 12 segments per line on its displays), the DNS3700 sheet shows CCs for 16 segments
    ...dreams in binary

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •