// *******************************************************************
// KJ10-30 Chords, Phase 3					              S215 11 1010
// *******************************************************************
#include "s215-header23-f46-NWDT.h"
#include "08 Interrupts.h"
#include "kj10-30-chords-phase3-ADDTL-CODE1.c"
	/* Contents:
		- Interrupt set-up.
		- Function prototype for CheckForSwitchErrors.
		- Definition of INT_ENABLE.
	*/
//|||||||||||||||||||||| GLOBAL VARIABLES, ETC. ||||||||||||||||||||||
unsigned char	
	t0intho;		//Timer 0 interrupt has occurred.
unsigned short
	t0delay;		//Timer 0 delay.

//||||||||||||||||||| BEGINNING OF MAIN PROGRAM ||||||||||||||||||||||
void main (void)
{
extern unsigned char
	t0intho;				//Timer 0 interrupt has occurred.
extern unsigned short
	t0delay;
unsigned short
	swp0, swp1, swp2, swp3;		//Square-wave periods 0 to 3.
short
	/* The two rows in chordarray represent two different key
	   signatures.There are three chords in each row, with each chord
	    having four notes. */ 
	chordarray[2][4][4] =	
	{
	  	{{ 0, 0, 0, 1}, { 0, 0, 2, 1}, { 0, 3, 2, 1}, {3, 3, 2, 1}}, 
	  	{{ 1, 1, 1, 1}, { 2, 2, 2, 2}, { 2, 2, 2, 2}, {2, 2, 2, 2}},
	},
	*capointer = &chordarray[0][0][0];	//Pointer to first element of
										// chordarray. 
#define CHORDARRAY capointer, 2, 4, 4	//chordarray parameters 
										//(pointer to array; numbers
										//of rows, columns, and 
										//elements)
unsigned char chord, key, i, juststarted=1;

INT_ENABLE = 0;						//Disable interrupts.
//### OSCCON = OSCCON | 0b01110000;		//16 MHz clock
InitPorts();
t0delay = 62500; //Timer 0 delay=0.5 sec. (4us*4*31250=500000)
T0CON = 1;	//Timer 0 Prescale.
	/* Prescale values: 0 = 1:2, 1 = 1:4, 2 = 1:8, 3 = 1:16, 
	4 = 1:32, 5 = 1:64, 6 = 1:128, 7 = 1:256. If instruction clock
	period is 0.25 us. 1:2 gives a period of 0.5 us, 1:4 gives a
	Timer 0 period of 1 us, etc.*/

while (1==1)
{
//||||||||||||||||||||||||||| PRIMARY LOOP |||||||||||||||||||||||||||

if (juststarted)
{
juststarted=0;
InterruptServiceLow();
}
CheckForSwitchErrors( );
key = (SWITCHES & 0b00001100) >> 2;
chord = SWITCHES & 0b00000011;

swp0 = GetChordNote(key, chord, 0, CHORDARRAY);
SerialOut(swp0, 0);

/* Use GetChordNote to get periods for swp1 and swp2, and send them
to SerialOut--with 0 as the second argument.

Use GetChordNote to get period for swp3 */

SerialOut(swp3, 1);	//The second argument is 1, which means that the
//data is ready to latch.

//||||||||||||||||||||||| END OF PRIMARY LOOP ||||||||||||||||||||||||		
}
}
//|||||||||||||||||||||||| END OF MAIN PROGRAM |||||||||||||||||||||||

//|||||||||||||||||||||||||||| FUNCTIONS |||||||||||||||||||||||||||||
void
SerialOut(unsigned short d, unsigned char finished)
//SEND OUT SERIAL DATA
{
//SOCLK		Serial out clock.
//SODATA	Serial out data.
//SOLATCHIT Serial out latch-it (all the data has been sent).
//SOCLK, SODATA, and SOLATCHIT are defined in 
//  kj10-30-chords-phase3-ADDTL-CODE1.c
extern unsigned char
	t0intho;				//Timer 0 interrupt has occurred.
unsigned char
	cyclecnt,				//Cycle counter.
	dbit,					//Data bit to be sent.
	i;						//Index.

for (i=0; i<=1; i++)	//###############
{
//-------------------------------------------------------------------
	dbit = (d >> i) & 1;

	for (cyclecnt=0; cyclecnt<=3; cyclecnt++)
	{
		while (t0intho==0) Nop();			//Wait for interrupt.
		t0intho = 0;
		
		switch (cyclecnt)
		{	case 0:
				SODATA = dbit;
				SOCLK = 0;
				break;
			case 1:
				SOCLK = 1;
				break;
			case 2:
				SOCLK = 1;
				break;
			case 3:
				SOCLK = 0;
		} //End switch		
	} //End for
//-------------------------------------------------------------------
}	//End for
if (finished)
{	SODATA = 0;
	for (cyclecnt=0; cyclecnt<=4; cyclecnt++)
	{
		while (t0intho==0) Nop();			//Wait for interrupt.
		t0intho = 0;
		
		switch (cyclecnt)
		{	case 0:
				SOLATCHIT = 1;
				SOCLK = 0;
				break;
			case 1:
				SOCLK = 1;
				break;
			case 2:
				SOCLK = 1;
				break;
			case 3:
				SOCLK = 0;
				break;
			case 4:
				SOLATCHIT = 0;
		} //End switch		
	} //End for
}

}	//End of function.

//||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
void
CheckForSwitchErrors(void)
{
unsigned char key, chord;
/*
Switches 3 and 2 select the key.
Switches 1 and 0 select the note.

|   7   |   6   |   5   |   4   |   3   |   2   |   1   |   0   |
              					|<==== Key ====>|<=== Chord ===>|   
*/

//If "key" is too large, display "Error" and keep getting numbers  
//fromswitches 3 and 2 until "key" contains a number that's OK.
key = (SWITCHES & 0b00001100) >> 2;
while (key > 1)
{	Error();
	key = (SWITCHES & 0b00001100) >> 2;
}

Clrdisp();
}

//||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
#include "kj10-30-chords-phase3-ADDTL-CODE2.c"
/* Contents:
void InterruptServiceLow(void)
	- Creates Timer 0 interrupts at time intervals based on t0delay.
*/