wackazong Posted September 11, 2008 Report 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
wackazong Posted September 11, 2008 Report 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
audiocommander Posted September 12, 2008 Report 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
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.