/*
 * Scan Matrix Example #1
 *
 * ==========================================================================
 *
 *  Copyright 2006 Thorsten Klose (tk@midibox.org)
 *  Licensed for personal non-commercial use only.
 *  All other rights reserved.
 *
 * ==========================================================================
 */

#include "cmios.h"
#include "pic18f452.h"

/////////////////////////////////////////////////////////////////////////////
// Local variables
/////////////////////////////////////////////////////////////////////////////
#include "main.h"
#include "keyboard.h" //keyboard map

#include "var.h"
//#include "variables.h"
#include "mclock.h"
#include "sm_simple.h"


#include "leds.c" // LIT UPPER LEDS
#include "ain.c" // ANALOG INPUTS (POTS)


//#include "bankstick.c"//Load/Save
//#include "tracker.c"
#include "init.c"
#include "prg_change.c"
#include "keyboard.c"



#include "push.c"
#include "freeplay.c"



//#include "arp.c"//arpeggiator




////////////////////////////////////////////////////////////////////////////
// Global variables
/////////////////////////////////////////////////////////////////////////////

// status of application (see bitfield declaration in main.h)
app_flags_t app_flags;
kb_t kb;
pg_t pg;





/////////////////////////////////////////////////////////////////////////////
// This function is called by MIOS in the mainloop when nothing else is to do
/////////////////////////////////////////////////////////////////////////////
void Tick(void) __wparam
{
  // call the scan matrix button handler
  SM_ButtonHandler();
   // this routine sends the MIDI clock (and Start/Continue/Stop) if requested
  MCLOCK_Tick();
}

/////////////////////////////////////////////////////////////////////////////
// This function is periodically called by MIOS. The frequency has to be
// initialized with MIOS_Timer_Set
/////////////////////////////////////////////////////////////////////////////
void Timer(void) __wparam
{
  // forward timer event to MIDI clock module (-> mclock.c)
  MCLOCK_Timer();
}

/////////////////////////////////////////////////////////////////////////////
// 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
{
	//def();//Display main page
	app_flags.DISPLAY_UPDATE_REQ = 1;
	led_num(0);//LITE LED 1
	MIOS_LCD_CursorSet(0x00);
	MIOS_LCD_PrintCString(" .: SIDABITBOX64 :. ");
}




/////////////////////////////////////////////////////////////////////////////
//  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
{
  // update display only when requested to minimize the CPU load
  if( !app_flags.DISPLAY_UPDATE_REQ )
    return;
  app_flags.DISPLAY_UPDATE_REQ = 0;


  // print BPM
  //MIOS_LCD_CursorSet(0x51);
  //MIOS_LCD_PrintBCD3(MCLOCK_BPMGet());

	// print the steps
	/*
	MIOS_LCD_CursorSet(0x10);//upper right
	MIOS_LCD_PrintChar('[');
	MIOS_LCD_PrintBCD2(step);
	MIOS_LCD_PrintChar(']');
	*/

// print the meter
 // MIOS_LCD_PrintBCD2(song_pos + 1);
 // MIOS_LCD_PrintChar('/');
 // MIOS_LCD_PrintBCD1(mclock_ctr_beats + 1);

}




/////////////////////////////////////////////////////////////////////////////
//  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
{
}

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

  // LSDJ SYNC !!!
  if( mclock_pin_state.CLK_REQ ) {// Send one byte on j14 :)
    mclock_pin_state.CLK_REQ = 0;
    PORTDbits.RD4 = 1;    PORTDbits.RD4 = 0;
    PORTDbits.RD4 = 1;    PORTDbits.RD4 = 0;
    PORTDbits.RD4 = 1;    PORTDbits.RD4 = 0;
    PORTDbits.RD4 = 1;    PORTDbits.RD4 = 0;
    PORTDbits.RD4 = 1;    PORTDbits.RD4 = 0;
    PORTDbits.RD4 = 1;    PORTDbits.RD4 = 0;
    PORTDbits.RD4 = 1;    PORTDbits.RD4 = 0;
    PORTDbits.RD4 = 1;    PORTDbits.RD4 = 0;
  } else {
    PORTDbits.RD4 = 0;
  }


  // call the Scan Matrix Driver
  SM_PrepareCol();

}

/////////////////////////////////////////////////////////////////////////////
// This function is called by MIOS after the shift register have been loaded
/////////////////////////////////////////////////////////////////////////////
void SR_Service_Finish(void) __wparam
{
  // call the Scan Matrix Driver
  SM_GetRow();
}

/////////////////////////////////////////////////////////////////////////////
// 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 NOT called by MIOS, but by the scan matrix handler
// in sm_simple.asm, when a pin of the scan matrix has been toggled
// Note: in addition to "pin" and "value", the "sm_button_column" and
// "sm_button_row" are available as global variables (defined in sm_simple.h)
/////////////////////////////////////////////////////////////////////////////



void SM_NotifyToggle(unsigned char pin, unsigned char value) __wparam
{
	last_mx_pin=pin;		//MAP KEYBOARD
	
	//display key number to upper right lcd
	//MIOS_LCD_CursorSet(0xD2);	//DEBUG
	//MIOS_LCD_PrintBCD2(pin);	//DEBUG


	// KEYBOARD OVERRIDE //

/*
	if(pg.EDIT==1){//EDIT PHRASE
		MIOS_LCD_CursorSet(0x00);
		MIOS_LCD_PrintCString("[EDIT PHRASE]     ");
		//if(value)EDITOR();
		return;
	}


	if(pg.REC==1){//STEP EDIT PATTERN
		MIOS_LCD_CursorSet(0x00);
		MIOS_LCD_PrintCString("[EDIT PATTERN]    ");
		//if(value)REC();
		return;
	}
*/

	/*	
	
	if(PRG==1){//PRG CHANGE (INPUT MODE)
		if(value)PRG_IN();return;
	}

	if(CC==1){//PRG CHANGE (INPUT MODE)
		if(value)CC_edit();return;
	}
	
	*/

	/////////////////////////////////////


	// ESCAPE : 57
	// CTRL : 58
	// SPACE : 60
	// RSHIFT : 12
	// LSHIFT : 51
	// RETURN : 1
	// RUNSTOP : 59
	// COMMODORE : 61
	// F1-F2 : 7
	// F3-F4 : 6
	// F5-F6 : 5
	// F7-F8 : 4


	switch(pin){//SPECIAL KEYS

		case 59:
			if(!value)return;
			if(kb.RUNSTOP==0){//PLAY
				kb.RUNSTOP=1;
				MCLOCK_DoPlay();
			}else{//STOP
				kb.RUNSTOP=0;
				MCLOCK_DoStop();
				_tik=0;//16 step reset
				step=0;//16 step reset
			}
			break;


		//kb.CTRL = kb.CTRL ? 0 : 1;
		//value ? kb.CTRL=0 : kb.CTRL=1;
		//case 58:value ? kb.CTRL=0 : kb.CTRL=1;break;//CTRL
		case 58:if(value){kb.CTRL=0; }else{kb.CTRL=1;}break;//CTRL
		case 61:if(value){kb.COMMODORE=0;}else{kb.COMMODORE=1;}break;//COMMODORE
		case 60:if(value){kb.SPACE=0;}else{kb.SPACE=1;}break;//SPACE
		case 12:if(value){kb.RSHIFT=0;}else{kb.RSHIFT=1;}break;//RSHIFT
		case 15:if(value){kb.LSHIFT=0;}else{kb.LSHIFT=1;}break;//LSHIFT

		case 7:transpose=72;break;// F1-F2
		case 6:transpose=60;break;// F3-F4
		case 5:transpose=48;break;// F5-F6
		case 4:transpose=36;break;// F7-F8

		case 0:break;//ALL NOTES OFF

	}



	if(kb.CTRL==1){if(value)CTROL(pin);return;}// (keyboard.c)
/*

	//if(kb.CTRL){if(value)CTROL(pin);return;}
	if(SPACE==1){if(value)SPCE(pin);return;}
	if(COMMODORE==1){if(value)COMODORE(pin);return;}
*/
	

	KEY_NOTE(value);//FREE PLAY (freeplay.c)

	return;
}



