/*
 * Copyright(C) Paul und Scherer (mct.de/mct.net)
 *
 * This example demonstrates how to...
 *
 *  ... use the timers to generate sound.
 */

#include <stdio.h>
#include <conio.h>
#include <target.h>
#include "delay.h"

/*
 * Beep at hz Hertz (0 =off) at P4.2 using Timer1.
 */
static void
beep(unsigned hz)
{
	if (hz) {
		Intern_t1con    = 0;		// disable
		Intern_t1ld     = _CCLK/2/hz;	// set period
		Intern_gp4con  |= 0x300;	// configure PLA
		Intern_plaelm10 = 0x246;	//  to toggle P4.2
		Intern_placlk   = 0x50;		//  on t1 counter underflow
		Intern_t1con    = 0xc0;		// periodic @cclk
	} else	Intern_gp4con  &= ~0x300;	// disconnect P4.2
}

/*
 * Play melody using beep() and delay()
 * (connect P4.2 via 20kOhm to line in).
 */
int
main(void)
{
	int hld = 1;				// hold (=staccato off)
	int dly = 3;				// tempo
	int oct = 1;				// octave shift

	puts("Playing...\n\n"
	     ". : toggle staccato\n"
	     "+ : faster\n"
	     "- : slower\n"
	     "> : octave up\n"
	     "< : octave down\n"
	);
	while (1) {
		static short const ftbl[] =	// frequency table for notes
		{				//  (rounded to ints)
			  0,			//  - code =@
			220,			// a0       A
			247,			// b0       B
			262,			// c1       C
			294,			// d1       D
			330,			// e1       E
			349,			// f1       F
			392,			// g1       G
			440,			// a1       H
			494,			// b1       I
			523			// c2       J
		};

		/*
		 * Melody
		 */
		char *p = "GGGFEGJDEEEECCJCHHHICIJHGGGGEEEEG@@FEGCDEED@C@JCDD@DC@B@CCCCC@@@@@@@"
			  "CCDDEEC@CCDDEEC@EEFFGGG@EEFFGGG@GHGFEECJGHGFE@CCJJGGJJJ@JJGGJJJ@@@@@"
			  "CEFGGGG@CEFGGGG@CEFGGEECCE@EDDD@DEDCC@JEEG@GFFF@FEFG@EECCDDCCCC@@@@@";

		int last;			// last note

		for (last = 0; *p; p++) {
			if (kbhit()) switch (getchar()) {
			case '.': hld = !hld; break;
			case '+': dly--;      break;
			case '-': dly++;      break;
			case '>': oct++;      break;
			case '<': oct--;      break;
			}

			if (dly > 9) dly = 0;
			if (dly < 0) dly = 9;
			if (oct > 3) oct = 0;
			if (oct < 0) oct = 3;

			if (*p != last) beep(ftbl[(last = *p)-'@']<<oct);
			if (!hld) delay(40), beep(0);
			delay((dly+hld+1)*40);
		}
		hld = !hld;			// toggle staccato
		dly--;				// speed up
		oct++;				// shift up
	}
}
