/*
 * MIOS SDCC Wrapper
 *
 * ==========================================================================
 *
 *  Copyright (C) <year>  <name> (<email>)
 *  Licensed for personal non-commercial use only.
 *  All other rights reserved.
 *
 * ==========================================================================
 */

#include "cmios.h"
#include "pic18f452.h"
#include "../common/include/display.h"
#include "../common/include/tunnel.h"
//#include "../common/lc_big_font.xpm"

#define CURENT_DISPLAY 1

unsigned char sysex;           					// Flag for the progress of a sysex-message
unsigned char disp_func_flag;							// Flag for the used Display function
unsigned char disp_func_buf;							// Buffer for the function, here only used for x-coordinate of setCursor
unsigned char inc_buffer_1;				 				// 3 Bufferbytes for tunneled Sysex-Data
unsigned char inc_buffer_2;
unsigned char inc_buffer_3;



/////////////////////////////////////////////////////////////////////////////
// This function is called by MIOS after startup to initialize the
// application
/////////////////////////////////////////////////////////////////////////////
void Init(void) __wparam
{

 	MIOS_LCD_TypeSet(7,0,0);

 	sysex = 0xFF;

}

/////////////////////////////////////////////////////////////////////////////
// This function is called by MIOS in the mainloop when nothing else is to do
/////////////////////////////////////////////////////////////////////////////
void Tick(void) __wparam
{
}

/////////////////////////////////////////////////////////////////////////////
// This function is periodically called by MIOS. The frequency has to be
// initialized with MIOS_Timer_Set
/////////////////////////////////////////////////////////////////////////////
void Timer(void) __wparam
{
}

/////////////////////////////////////////////////////////////////////////////
// This function is called by MIOS when the display content should be
// initialized. Thats the case during startup and after a temporary message
// has been printed on the screen
/////////////////////////////////////////////////////////////////////////////
void DISPLAY_Init(void) __wparam
{
	MIOS_LCD_Clear();
	MIOS_GLCD_GCursorSet(0,0);
}

/////////////////////////////////////////////////////////////////////////////
//  This function is called in the mainloop when no temporary message is shown
//  on screen. Print the realtime messages here
/////////////////////////////////////////////////////////////////////////////
void DISPLAY_Tick(void) __wparam
{
	/*MIOS_GLCD_GCursorSet(0,1);
	MIOS_LCD_PrintBCD1(9);
	MIOS_LCD_PrintBCD2(9);
	MIOS_LCD_PrintBCD3(9);
	MIOS_LCD_PrintBCD4(9);*/
}

/////////////////////////////////////////////////////////////////////////////
//  This function is called by MIOS when a complete MIDI event has been received
/////////////////////////////////////////////////////////////////////////////
void MPROC_NotifyReceivedEvnt(unsigned char evnt0, unsigned char evnt1, unsigned char evnt2) __wparam
{
}

/////////////////////////////////////////////////////////////////////////////
// This function is called by MIOS when a MIDI event has been received
// which has been specified in the MIOS_MPROC_EVENT_TABLE
/////////////////////////////////////////////////////////////////////////////
void MPROC_NotifyFoundEvent(unsigned entry, unsigned char evnt0, unsigned char evnt1, unsigned char evnt2) __wparam
{
}

/////////////////////////////////////////////////////////////////////////////
// This function is called by MIOS when a MIDI event has not been completly
// received within 2 seconds
/////////////////////////////////////////////////////////////////////////////
void MPROC_NotifyTimeout(void) __wparam
{
}

/////////////////////////////////////////////////////////////////////////////
// This function is called by MIOS when a MIDI byte has been received
/////////////////////////////////////////////////////////////////////////////
void MPROC_NotifyReceivedByte(unsigned char byte) __wparam
{
	if (byte == 0xF0)									// Sysex-Start?
		sysex = 0x00;									// Byte number of Sysexmessage

	switch (sysex) {									// Core-relevant Sysex-Message? no -> sysex = 0xFF -> Tunnel
	  													//            	                            yes -> sysex = number of bytes
		case 0x00:
			if (byte == 0xF0) {							// Sysex?
				inc_buffer_1 = byte;					// keep recent byte in buffer
				sysex = 0x01;
			}
			break;
		case 0x01:
			if(byte == 0x55) {							// manufacturer code MIDIbox GLCD?
				inc_buffer_2 = byte;					// keep recent byte in buffer
				sysex = 0x02;
			}
			else {
				MIOS_MIDI_BeginStream;
				MIOS_MIDI_TxBufferPut (inc_buffer_1);	        //if not in core relevant message anymore,
				MIOS_MIDI_TxBufferPut (byte);			//put buffer and recent byte to output
				MIOS_MIDI_EndStream;
				sysex = 0xFF;							//exit Core-relevant - Sysex
			}
	  		break;
		case 0x02:
			if(byte == 0x4D) {							// M?
				inc_buffer_3 = byte;					// keep recent byte in buffer
				sysex = 0x03;
			}
			else {
				MIOS_MIDI_BeginStream;
				MIOS_MIDI_TxBufferPut (inc_buffer_1);	//if not in core relevant message anymore,
				MIOS_MIDI_TxBufferPut (inc_buffer_2);	//put buffer and recent byte to output
				MIOS_MIDI_TxBufferPut (byte);
				MIOS_MIDI_EndStream;
				sysex = 0xFF;							//exit Core-relevant - Sysex
			}
			break;
		case 0x03:
			if(byte == 0x42) 							// B?
				sysex = 0x04;
			else {
				MIOS_MIDI_BeginStream;
				MIOS_MIDI_TxBufferPut (inc_buffer_1);	//if not in core relevant message anymore,
				MIOS_MIDI_TxBufferPut (inc_buffer_2);	//put buffer and recent byte to output
				MIOS_MIDI_TxBufferPut (inc_buffer_3);
				MIOS_MIDI_TxBufferPut (byte);
				MIOS_MIDI_EndStream;
				sysex = 0xFF;							//exit Core-relevante - Sysex
			}
			break;
		case 0x04:
			disp_func_flag = byte;						// keeping the active display function in disp_func_flag
			sysex = 0x05;
			break;
		case 0x05:
			if (byte == CURENT_DISPLAY) 				// chose active display?
				sysex = 0x06;
			break;
		case 0x06:
			switch (disp_func_flag) {					//which displayfunction was used?
				case FUNC_PRINT_CHAR:					//PrintCHAR
					MIOS_LCD_PrintChar (byte);
					break;
				case FUNC_CLEAR_LCD:					//ClearLCD
					MIOS_LCD_Clear();
					sysex = 0xFF;						// go to tunnel mode
					return;
				case FUNC_SET_CURSOR:					//SetCursor
					disp_func_buf = byte;
					break;
				case FUNC_PRINT_STRING:					//PrintString
					MIOS_LCD_PrintChar (byte);
					break;
				case FUNC_PRINT_BCD1:
					MIOS_LCD_PrintBCD1 (byte);			//PrintBCD1
					break;
				case FUNC_PRINT_BCD2:
					MIOS_LCD_PrintBCD2 (byte);			//PrintBCD2
					break;
				case FUNC_PRINT_BCD3:
					MIOS_LCD_PrintBCD3 (byte);			//PrintBCD3
					break;
				case FUNC_PRINT_BCD4:					//Print BCD4, keep one byte for int
					disp_func_buf = byte;
					break;
				case FUNC_PRINT_BCD5:					//Print BCD5, keep one byte for int
					disp_func_buf = byte;
					break;
			}
			sysex = 0x07;
	  		break;
		case 0x07:
			if (byte == 0xF7) {							// If message over, goto tunnel mode
				sysex = 0xFF;
				return;
			}
			else
				if (disp_func_flag == 0x02)				// for SETCURSOR
					MIOS_GLCD_GCursorSet(disp_func_buf,byte);	// position Cursor
				else
					if (disp_func_flag == 0x03)
						MIOS_LCD_PrintChar(byte);			//for PrintString write next Character
					else
						if (disp_func_flag == 0x07)
							MIOS_LCD_PrintBCD4 ((int)((disp_func_buf)<<7)|(int)(byte));			//PrintBCD4
						else
							if (disp_func_flag == 0x08)
							MIOS_LCD_PrintBCD5 ((int)((disp_func_buf)<<7)|(int)(byte));			//PrintBCD5
			break;
		case 0xFF:										// tunnel mode
			MIOS_MIDI_BeginStream;
			MIOS_MIDI_TxBufferPut (byte);				// send MIDI-Byte from input to output
			MIOS_MIDI_EndStream;
			return;
	}
}

/////////////////////////////////////////////////////////////////////////////
// This function is called by MIOS before the shift register are loaded
/////////////////////////////////////////////////////////////////////////////
void SR_Service_Prepare(void) __wparam
{
}

/////////////////////////////////////////////////////////////////////////////
// This function is called by MIOS after the shift register have been loaded
/////////////////////////////////////////////////////////////////////////////
void SR_Service_Finish(void) __wparam
{
}

/////////////////////////////////////////////////////////////////////////////
// This function is called by MIOS when an button has been toggled
// pin_value is 1 when button released, and 0 when button pressed
/////////////////////////////////////////////////////////////////////////////
void DIN_NotifyToggle(unsigned char pin, unsigned char pin_value) __wparam
{
}

/////////////////////////////////////////////////////////////////////////////
// This function is called by MIOS when an encoder has been moved
// incrementer is positive when encoder has been turned clockwise, else
// it is negative
/////////////////////////////////////////////////////////////////////////////
void ENC_NotifyChange(unsigned char encoder, char incrementer) __wparam
{
}

/////////////////////////////////////////////////////////////////////////////
// This function is called by MIOS when a pot has been moved
/////////////////////////////////////////////////////////////////////////////
void AIN_NotifyChange(unsigned char pin, unsigned int pin_value) __wparam
{
}
