from microbit import *
RST_Pin = pin8
SS_PIN  = pin16
HIGH    = 1
LOW     = 0

def digitalWrite(pin,val):
	pin.write_digital(val)

def mosiChar(adrs, data):
	mosi(adrs,data,1)

def mosi(adrs, data, size):
	digitalWrite(SS_PIN,LOW) 
	dt = bytearray([adrs])
	if size==1:
		dt.append(data)
	else:
		for cnt in range(size):
			dt.append(data[cnt])
	spi.write(dt)
	digitalWrite(SS_PIN,HIGH) 
	sleep(1)

class Ymf825:

	tone_data = [
		0x81,                               # 80H + Tone Number
		0x01,                               # BO (Basic Octave)
		0x43,                               # LFO,ALG
		0x00,0x67,0xFF,0x9D,0x00,0x10,0x40, # Operator1 Setting
		0x21,0x33,0xE2,0xA3,0x00,0x50,0x00, # Operator2 Setting
		0x10,0x41,0xD3,0x88,0x01,0x10,0x00, # Operator3 Setting
		0x21,0x62,0xD4,0x02,0x01,0x10,0x00, # Operator4 Setting
		0x80,0x03,0x81,0x80]                # Footer

	noteFnum = (357,378,401,425,450,477,505,535,567,601,637,674)  #piano

	def __init__(self):
		#digitalWrite(RST_Pin,LOW) 
		#sleep(1)
		#digitalWrite(RST_Pin,HIGH) 
		mosiChar( 0x1D, 0 )
		mosiChar( 0x02, 0x0e )
		sleep(1)
		mosiChar( 0x00, 0x01 )
		mosiChar( 0x01, 0x00 )
		mosiChar( 0x1A, 0xa3 )
		sleep(1)
		mosiChar( 0x1A, 0x00 )
		sleep(30)
		mosiChar( 0x02, 0x04 )
		sleep(1)
		mosiChar( 0x02, 0x00 )
		mosiChar( 0x19, 0xcc )
		mosiChar( 0x1B, 0x3f )
		mosiChar( 0x14, 0x00 )
		mosiChar( 0x03, 0x01 )
		mosiChar( 0x09, 0xf8 )

	def setTone(self):
		mosiChar( 0x08, 0xf6 )
		sleep(1)
		mosiChar( 0x08, 0x00 )
		mosi( 0x07, self.tone_data, 35 )

	def setAlgorithm(self,num):
		self.tone_data[2] = 0x40|num
		mosiChar( 0x08, 0xf6 )
		sleep(1)
		mosiChar( 0x08, 0x00 )
		mosi( 0x07, self.tone_data, 35 )

	def setChannel(self):
		mosiChar( 0x0F, 0x30 ); # KeyOn=0/MUTE=1/EG_RST=1
		mosiChar( 0x10, 0x71 ); # ch volume
		mosiChar( 0x11, 0x00 ); # Vibrato modulation
		mosiChar( 0x12, 0x08 ); # This registers specify a multiplier to
		mosiChar( 0x13, 0x00 ); # the generated audio frequency.

	def keyoff(self,channel):
		mosiChar( 0x0B, channel)
		mosiChar( 0x0F, 0x00)  # KeyOn=0:reset/Mute=0:Cancels the mute

	def keyon(self, toneIndex, channel, note):
		freqNum=self.noteFnum[note%12]
		block=int(note/12)
		freqNumH=((0x0380 & freqNum)>>4)|block
		freqNumL=0x7f&freqNum

		mosiChar( 0x0B, channel)
		mosiChar( 0x0C, 0x54)
		mosiChar( 0x0D, freqNumH)
		mosiChar( 0x0E, freqNumL)
		keyTone=0x40|(toneIndex&0x0f)  # 0x40:KeyOn
		mosiChar( 0x0F, keyTone)

def main():

	spi.init(baudrate=115200, bits=8, mode=0, sclk=pin13, mosi=pin15, miso=pin14)

	ymf = Ymf825()
	ymf.setTone()
	ymf.setChannel()

	notes = {'z':[60,'C'],'s':[61,'C#'],'x':[62,'D'],'d':[63,'D#'],'c':[64,'E'],'v':[65,'F'],'g':[66,'F#'],'b':[67,'G'],'h':[68,'G#'],'n':[69,'A'],'j':[70,'A#'],'m':[71,'B'],',':[72,'c'], \
	         'Z':[72,'c'],'S':[73,'c#'],'X':[74,'d'],'D':[75,'d#'],'C':[76,'e'],'V':[77,'f'],'G':[78,'f#'],'B':[79,'g'],'H':[80,'g#'],'N':[81,'a'],'J':[82,'a#'],'M':[83,'b'],'<':[84,'c\'']}

	uart.write('\r\n')

	while True:
		if uart.any():
			s = uart.read()
			key = chr(ord(s))
			if key == 'q':
				break
			elif key >= '0' and key <= '7':
				ymf.setAlgorithm(int(key))
				uart.write('Algorithm=' + key + '\r\n')
			elif key in notes:
				note = notes[key][0]
				ymf.keyon(0, 0, note)
				uart.write('note=' + notes[key][1] + '\r\n')
				sleep(200)
				ymf.keyoff(0);
				sleep(10);
			else:
				continue
