wackazong Posted September 11, 2008 Report Share Posted September 11, 2008 Yeah, I am using these right now, but I love to scramble :) I am almost finished with a descramble code in C, will post it here later. Quote Link to comment Share on other sites More sharing options...
wackazong Posted September 11, 2008 Report Share Posted September 11, 2008 Here we go. Its largely based on the syx_dump example, but does some descrambling. The function you are interested in is SYSEX_Cmd_GetDataBytes. Comments on the efficiency and style of coding as always very welcome, I have very little experience in C and assembler. // $Id: sysex.c 441 2008-08-13 21:27:08Z tk $ /* * SysEx Parser Demo * see README.txt for details * * ========================================================================== * * Copyright (C) 2008 Thorsten Klose (tk@midibox.org) * Licensed for personal non-commercial use only. * All other rights reserved. * * ========================================================================== */ //wackazong: Differences to original //I use a format that has only one command byte (with the MSB = 0) and then //8bit data coded into 7bit values //The length of the message depends on the command byte ///////////////////////////////////////////////////////////////////////////// // Include files ///////////////////////////////////////////////////////////////////////////// #include <cmios.h> #include <sysex.h> #include <knoepfli.h> ///////////////////////////////////////////////////////////////////////////// // Internal Prototypes ///////////////////////////////////////////////////////////////////////////// void SYSEX_SendAck(unsigned char ack_code, unsigned char ack_arg); void SYSEX_CmdFinished(void); void SYSEX_SendFooter(unsigned char force); void SYSEX_Cmd(unsigned char cmd_state, unsigned char midi_in); void SYSEX_Cmd_GetDataBytes(unsigned char cmd_state, unsigned char midi_in); void SYSEX_Cmd_Ping(unsigned char cmd_state, unsigned char midi_in); ///////////////////////////////////////////////////////////////////////////// // Global Variables ///////////////////////////////////////////////////////////////////////////// sysex_state_t sysex_state; unsigned char sysex_cmd; unsigned char sysex_data_size; //size of the sysex data part in bytes unsigned char sysex_checksum; unsigned char sysex_received_checksum; unsigned int sysex_receive_ctr; //counts the number of sysex bytes received unsigned int sysex_data_receive_ctr; //counts the number of data bytes received (8bit) unsigned char sysex_bit_pointer; //for unscrambling, tells how many bits of the received 7 already belong to the next bit unsigned char sysex_buffer[8]; //8byte buffer containing the sysex message converted to 8bit format ///////////////////////////////////////////////////////////////////////////// // Static definitions ///////////////////////////////////////////////////////////////////////////// // should be changed for your own application // Headers used by MIDIbox applications are documented here: // http://svnmios.midibox.org/filedetails.php?repname=svn.mios&path=%2Ftrunk%2Fdoc%2FSYSEX_HEADERS // if you decide to use "F0 00 00 7E" prefix, please ensure that your // own ID (here: 0x7f) will be entered into this document. // Otherwise please use a different header const unsigned char sysex_header[] = { 0xf0, 0x00, 0x00, 0x7e, 0x7f }; ///////////////////////////////////////////////////////////////////////////// // This function initializes the SysEx handler ///////////////////////////////////////////////////////////////////////////// void SYSEX_Init(void) { sysex_state.ALL = 0; } ///////////////////////////////////////////////////////////////////////////// // This function parses an incoming sysex stream for SysEx messages ///////////////////////////////////////////////////////////////////////////// void SYSEX_Parser(unsigned char midi_in) { // ignore realtime messages (see MIDI spec - realtime messages can // always be injected into events/streams, and don't change the running status) if( midi_in >= 0xf8 ) return; // branch depending on state if( !sysex_state.MY_SYSEX ) { if( midi_in != sysex_header[sysex_state.CTR] ) { // incoming byte doesn't match SYSEX_CmdFinished(); } else { if( ++sysex_state.CTR == sizeof(sysex_header) ) { // complete header received, waiting for data sysex_state.MY_SYSEX = 1; // disable merger forwarding until end of sysex message MIOS_MPROC_MergerDisable(); } } } else { // check for end of SysEx message or invalid status byte if( midi_in >= 0x80 ) { if( midi_in == 0xf7 && sysex_state.CMD ) { SYSEX_Cmd(SYSEX_CMD_STATE_END, midi_in); } SYSEX_CmdFinished(); } else { // check if command byte has been received if( !sysex_state.CMD ) { sysex_state.CMD = 1; sysex_cmd = midi_in; SYSEX_Cmd(SYSEX_CMD_STATE_BEGIN, midi_in); } else SYSEX_Cmd(SYSEX_CMD_STATE_CONT, midi_in); } } } ///////////////////////////////////////////////////////////////////////////// // This function sends a SysEx acknowledge to notify the user about the received command // expects acknowledge code (e.g. 0x0f for good, 0x0e for error) and additional argument ///////////////////////////////////////////////////////////////////////////// void SYSEX_SendAck(unsigned char ack_code, unsigned char ack_arg) { int i; unsigned char checksum; unsigned char c; // send header for(i=0; i<sizeof(sysex_header); ++i) MIOS_MIDI_TxBufferPut(sysex_header[i]); // send ack code and argument MIOS_MIDI_TxBufferPut(ack_code); MIOS_MIDI_TxBufferPut(ack_arg); // send footer MIOS_MIDI_TxBufferPut(0xf7); } ///////////////////////////////////////////////////////////////////////////// // This function is called at the end of a sysex command or on // an invalid message ///////////////////////////////////////////////////////////////////////////// void SYSEX_CmdFinished(void) { // clear all status variables sysex_state.ALL = 0; sysex_cmd = 0; // enable MIDI forwarding again MIOS_MPROC_MergerEnable(); } ///////////////////////////////////////////////////////////////////////////// // This function sends the SysEx footer if merger enabled // if force == 1, send the footer regardless of merger state ///////////////////////////////////////////////////////////////////////////// void SYSEX_SendFooter(unsigned char force) { if( force || (MIOS_MIDI_MergerGet() & 0x01) ) MIOS_MIDI_TxBufferPut(0xf7); } ///////////////////////////////////////////////////////////////////////////// // This function handles the sysex commands ///////////////////////////////////////////////////////////////////////////// void SYSEX_Cmd(unsigned char cmd_state, unsigned char midi_in) { // enter the commands here switch( sysex_cmd ) { case 0x01: //set color of one LED sysex_data_size = 10; SYSEX_Cmd_GetDataBytes(cmd_state,midi_in); break; case 0x02: // break; case 0x0f: SYSEX_Cmd_Ping(cmd_state, midi_in); break; default: // unknown command SYSEX_SendFooter(0); SYSEX_SendAck(SYSEX_DISACK, SYSEX_DISACK_INVALID_COMMAND); SYSEX_CmdFinished(); } } ///////////////////////////////////////////////////////////////////////////// // Receive the data bytes of the command ///////////////////////////////////////////////////////////////////////////// void SYSEX_Cmd_GetDataBytes(unsigned char cmd_state, unsigned char midi_in) { int i; unsigned char tmp; switch( cmd_state ) { case SYSEX_CMD_STATE_BEGIN: sysex_checksum = 0; // clear checksum sysex_receive_ctr = 0; // clear byte counter sysex_data_receive_ctr = 0; sysex_received_checksum = 0; sysex_bit_pointer = 0; break; case SYSEX_CMD_STATE_CONT: if( sysex_receive_ctr < sysex_data_size ) { // add to checksum sysex_checksum += midi_in; //do some unscrambling //shift the midi_in one to the left, then the LSB is 0 and has no meaning midi_in <<= 1; //move the right bits over to the last buffer char for (i = 0; i < sysex_bit_pointer; ++i) { //set the bit to be changed to 0 //sysex_buffer[sysex_data_receive_ctr-1] & ~(0x01 << i); //it is zero anyway //isolate the bit to be set into tmp. Its always the MSB! tmp = midi_in & 0x80; //shift the bit to be set from midi_in to the right place tmp >>= (7-sysex_bit_pointer+i+1); //set the new bit value sysex_buffer[sysex_data_receive_ctr-1] |= tmp; //shift midi_in to the left, now the next bit we are interested in is again the MSB midi_in <<= 1; }; //store the received byte in the buffer sysex_buffer[sysex_data_receive_ctr] = midi_in; //increase the pointer if(sysex_bit_pointer==7) { sysex_bit_pointer = 0; } else { ++sysex_bit_pointer; ++sysex_data_receive_ctr; } #if SYSEX_CHECKSUM_PROTECTION } else if( sysex_receive_ctr == sysex_data_size ) { // store received checksum sysex_received_checksum = midi_in; #endif } else { // wait for F7 } // increment counter ++sysex_receive_ctr; break; default: // SYSEX_CMD_STATE_END SYSEX_SendFooter(0); #if SYSEX_CHECKSUM_PROTECTION //increase the sysex_data_size by the checksum byte ++sysex_data_size #endif //prepare here for new packet in the same sysex session. if( sysex_receive_ctr < sysex_data_size) { // not enough bytes received SYSEX_SendAck(SYSEX_DISACK, SYSEX_DISACK_LESS_BYTES_THAN_EXP); } else if( sysex_receive_ctr > sysex_data_size) { // too many bytes received SYSEX_SendAck(SYSEX_DISACK, SYSEX_DISACK_MORE_BYTES_THAN_EXP); #if SYSEX_CHECKSUM_PROTECTION } else if( sysex_received_checksum != ((sysex_checksum ^ 0xff) & 0x7f) ) { // notify that wrong checksum has been received SYSEX_SendAck(SYSEX_DISACK, SYSEX_DISACK_WRONG_CHECKSUM); #endif } else { // call the command as a function returning 0 or 1 depending on success // put your function where the 0 is if( 0 ) { // write failed (bankstick not available) SYSEX_SendAck(SYSEX_DISACK, SYSEX_DISACK_BS_NOT_AVAILABLE); } else { // notify that bytes have been received SYSEX_SendAck(SYSEX_ACK, 0x00); } } break; } } ///////////////////////////////////////////////////////////////////////////// // Command 0F: Ping (just send back acknowledge) ///////////////////////////////////////////////////////////////////////////// void SYSEX_Cmd_Ping(unsigned char cmd_state, unsigned char midi_in) { switch( cmd_state ) { case SYSEX_CMD_STATE_BEGIN: // nothing to do break; case SYSEX_CMD_STATE_CONT: // nothing to do break; default: // SYSEX_CMD_STATE_END SYSEX_SendFooter(0); // send acknowledge SYSEX_SendAck(SYSEX_ACK, 0x00); break; } } Quote Link to comment Share on other sites More sharing options...
audiocommander Posted September 12, 2008 Report Share Posted September 12, 2008 cool...these are two very informative options.for my next MB project I will just wait one year until it's implemented in MIOS ;Dhehe..I'll keep you updated as well -cheers!Michael Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.