/** \file message.c:
 *  Contains functions for sending the edit buffer and for creating MIDI
 *  Messages for all possible parameter configurations.
 */

/**
 * This function sends the edit buffer from the internal edit buffer "array" over MIDI
 * the header is replaced before transmission
 */
void sendEditBuffer() __critical
{
	int i;

	MIOS_MIDI_BeginStream();
	MIOS_MIDI_TxBufferPut(0xF0);

	for(i=0;i<eb_request.dump.header_length;i++)
		MIOS_MIDI_TxBufferPut(edit_buffer_header[i]);

	for (i=0;i<eb_request.dump.edit_buffer_length;i++)
		MIOS_MIDI_TxBufferPut(readEditBuffer(i));

	MIOS_MIDI_TxBufferPut(checksum(1));
	MIOS_MIDI_TxBufferPut(0xF7);
	MIOS_MIDI_EndStream();
}


/*
 //von marcel


	EB_Length=edit_buffer0[0]<<8|edit_buffer0[1];
	for(i=0;i<=EB_Length;i++)
		MIOS_MIDI_TxBufferPut(readEditBuffer(i+2));

//von holle
		unsigned long i,addr=((long)(eb_request.dump_addr))+((long)7)+BASE_DYNMEM+DYNBLOCK_LENGTH*device+eb_request.dump.length;
		int edit_ram;

		MIOS_MIDI_BeginStream;
		MIOS_MIDI_TxBufferPut(0xF0);
		MIOS_MIDI_TxBufferPut(0x00);

	for(i=0;i<eb_request.dump.header_length;i++)
		MIOS_MIDI_TxBufferPut(readBank(addr+i));


		MIOS_MIDI_TxBufferPut(0xF7);
		MIOS_MIDI_EndStream;

*/

/**
 * This function builds and sends your dynamic midi message
 * \param number number of handled encoder/knob
 * \param incrementer incrementer from ENC_NotifyChange
 */
void sendMessage(unsigned char number, signed char incrementer) {

	unsigned char sendMessageMemory;
	unsigned char evnt[3];
	unsigned int relativ;
	parameter *param;

	unsigned long i,x;

/*
	MIOS_MIDI_BeginStream();
	MIOS_MIDI_TxBufferPut(0xF0);
	MIOS_MIDI_TxBufferPut(0x55);
	MIOS_MIDI_TxBufferPut(potis[number]);
	MIOS_MIDI_TxBufferPut(0xF7);
	MIOS_MIDI_EndStream();
*/

	param = 0;
	sendMessageMemory=0x00;
	relativ=0x0000;

		if (number<=7)
			param = &parametersleft[number%8];
		else
			if (number>7)
				param = &parametersright[number%8];



	eb_convert(param->value[0],((param->edit&0x0FFF)-1),potis[number]);


	do {

		switch (param->messageChannel|0x0F) {


			case  (0x7F): 								  //send SYSEX


				if (param->edit&0x1000) {
					if (!send_editbuffer)
						send_editbuffer=0x50;
					//update=0x20;
					return;
				}

				MIOS_MIDI_BeginStream;
				MIOS_MIDI_TxBufferPut(0xF0);
				for(i=0,x=((param->number[0]<<8)|param->number[1])+BASE_DYNMEM+device*DYNBLOCK_LENGTH+sizeof(SysexStruct);i<param->sysex.length;i++)
					send_buffer[i]=readBank(i+x);
				//convert
				convert(param->sysex.convert_func,send_buffer,potis[number],param->sysex.convert_func_addr);

				for(i=0;i<param->sysex.length;i++)
					//debugc(send_buffer[i]);
					MIOS_MIDI_TxBufferPut(send_buffer[i]);
				MIOS_MIDI_TxBufferPut(0xF7);
				MIOS_MIDI_EndStream;
				return;



/*
				//for(i=0;i<param->sysex.length;i++)
				send_buffer[0]=0xF0;
				send_buffer[1]=0x32;
				send_buffer[2]=0x32;
				send_buffer[3]=0x32;
				send_buffer[4]=0x32;
				send_buffer[5]=0x32;
				send_buffer[6]=0x32;
				send_buffer[7]=0xF7;
				convert(2,send_buffer,potis[number],0x05);

				MIOS_MIDI_BeginStream;
				for(i=0;i<param->sysex.length;i++)
					MIOS_MIDI_TxBufferPut(send_buffer[i]);
				MIOS_MIDI_EndStream;
				return;
*/


			case (0x1F):                              	  //NOTE, AFTERTOUCH, PITCHBEND
				switch (param->modeSelect|0x0F) {
					case (0x0F):                          //NOTE
						if ((potis[number]&0x7F)==0){
							evnt[0]=(0x80|(param->messageChannel&0x0F));
							evnt[1]=(param->number[0]&0x7F);
							evnt[2]=(0x64);
						} else {
							evnt[0]=(0x90|(param->messageChannel&0x0F));
							evnt[1]=(param->number[0]&0x7F);
							evnt[2]=(potis[number]&0x7F);
						}
						break;

					case (0x1F):                          //AFTERTOUCH //CHANNEL PRESSURE
						evnt[0]=(0xA0|(param->messageChannel&0x0F));
						evnt[1]=(param->number[0]&0x7F);
						evnt[2]=(potis[number]&0x7F);
						break;


					case (0x2F):                           //POLYPHONIC PRESSURE
						evnt[0]=(0xD0|(param->messageChannel&0x0F));
						evnt[1]=(potis[number]&0x7F);
						MIOS_MIDI_BeginStream();
						MIOS_MIDI_TxBufferPut(evnt[0]);
						MIOS_MIDI_TxBufferPut(evnt[1]);
						MIOS_MIDI_EndStream();
						return;

					case (0x3F):                          //PITCHBEND
						evnt[0]=(0xE0|(param->messageChannel&0x0F));
						evnt[1]=((potis[number]&0x7F)*((param->modeSelect&0x02)>>1));
						evnt[2]=((potis[number]>>(7*((param->modeSelect&0x02)>>1)))&0x7F);
						break;
			   }
			   break;

			case (0x5F):                                 //NRPN
			case (0x6F):                                 //RPN
				if (sendMessageMemory<0x02){
					evnt[0]=(0xB0|(param->messageChannel&0x0F));
						if ((param->messageChannel|0x0F)==0x5F) {
							if (sendMessageMemory==0x00) {
								evnt[1]=0x63;
							} else {
								evnt[1]=0x62;
							}
						}
						if ((param->messageChannel|0x0F)==0x6F) {
							if (sendMessageMemory==0x00) {
								evnt[1]=0x65;
							} else {
								evnt[1]=0x64;
							}
						}
						evnt[2]=(param->number[sendMessageMemory]&0x7F);
						sendMessageMemory+=0x01;
						break;
				}

			case (0x3F):                                 //CONTROL CHANGE
				evnt[0]=(0xB0|(param->messageChannel&0x0F));
				if (param->modeSelect&0x02) {				//14BIT?
					if (!(sendMessageMemory&0x01)) {
						if (sendMessageMemory&0x02) {
							evnt[1]=0x06;
						} else {
							evnt[1]=param->number[0];
						}
						switch (param->modeSelect|0x0F) {
							case (0x0F):					//ABSOLUTE
								evnt[2]=((potis[number]>>7)&0x7F);
								break;

							case(0x1F):						//RELATIVE1
								evnt[2]=(((relativ+incrementer)>>7)&0x7F);
								break;

							case(0x2F):						//RELATIVE2
								relativ=0x4000;
								evnt[2]=(((relativ+incrementer)>>7)&0x7F);
								break;

							case(0x3F):						//RELATIVE3
								relativ=0x4000;
								if (incrementer<0)
									evnt[2]=((((relativ+1)+(~incrementer))>>7)&0x7F);
								else
									evnt[2]=(((relativ+(incrementer))>>7)&0x7F);
								break;
						}
						sendMessageMemory|=0x01;
						break;
					}

				}
				if (!(param->modeSelect&0x40)) {
					if (sendMessageMemory&0x02) {
						evnt[1]=(0x06+(((param->modeSelect&0x02)>>1)*0x20));
					} else {
						evnt[1]=((param->number[0])+(((param->modeSelect&0x02)>>1)*0x20));
					}
				}

				switch (param->modeSelect|0x0F) {
					case (0x0F):							//ABSOLUTE
						evnt[2]=((potis[number])&0x7F);
						sendMessageMemory=0x00;
						break;

					case(0x1F):								//RELATIVE1
						evnt[2]=((relativ+incrementer)&0x7F);
						break;

					case(0x2F):								//RELATIVE2
						if (!(param->modeSelect&0x02)) {
							relativ=0x40;
						}
						evnt[2]=((relativ+incrementer)&0x7F);
						break;

					case(0x3F):								//RELATIVE3
						if (!(param->modeSelect&0x02))
							relativ=0x40;
						if (incrementer<0)
							evnt[2]=(((relativ+1)+(~incrementer))&0x7F);
						else
							evnt[2]=((relativ+(incrementer))&0x7F);
						break;
					case(0x4F):								//INC/DEC
						evnt[2]=0x01;
						if (!(sendMessageMemory&0x01)) {
							if (incrementer>0) {
								evnt[1]=0x60;
							} else {
								evnt[1]=0x61;
								incrementer=((~incrementer)+1);
							}
						}
						sendMessageMemory|=0x01;
						incrementer--;
						if (!(incrementer))
							sendMessageMemory=0x00;
						break;
				}
				break;

		   	case (0x4F):                                 //PROGRAM CHANGE
				if (((param->modeSelect)&0x10)&&(sendMessageMemory==0x00)) { //MSB
					evnt[0]=(0xB0|(param->messageChannel&0x0F));
					evnt[1]=0x00;
					evnt[2]=param->number[0];
					++sendMessageMemory;
					break;
				}
				if (((param->modeSelect)&0x20)&&(sendMessageMemory<0x02)) {  //LSB
					evnt[0]=(0xB0|(param->messageChannel&0x0F));
					evnt[1]=0x20;
					evnt[2]=param->number[1];
					sendMessageMemory+=2;
					break;
				}
				evnt[0]=(0xC0|(param->messageChannel&0x0F));
				evnt[1]=(potis[number]&0x7F);
				MIOS_MIDI_BeginStream();
				MIOS_MIDI_TxBufferPut(evnt[0]);
				MIOS_MIDI_TxBufferPut(evnt[1]);
				MIOS_MIDI_EndStream();
				return;
				break;

		}
		MIOS_MIDI_BeginStream();
		MIOS_MIDI_TxBufferPut(evnt[0]);
		MIOS_MIDI_TxBufferPut(evnt[1]);
		MIOS_MIDI_TxBufferPut(evnt[2]);
		MIOS_MIDI_EndStream();
	} while (!(sendMessageMemory==0x00));
	return;

}
