//Based on ymf825board_sample1
// 音色データの追加と和音演奏
// 音色パラメータによる音色データの生成
// 西洋音階での演奏
/*
Conditions only for Arduino UNO
RST_N- Pin9
SS - Pin10
MOSI - Pin11
MISO - Pin12
SCK - Pin13
*/
#include <SPI.h>
//0 :5V 1:3.3V
#define OUTPUT_power 0
const int RST_Pin = 9;
const int slaveSelectPin = 10;
//西洋音階
int noteFnum[12]={357,378,401,425,450,477,505,535,567,601,637,674};//ピアノの白鍵黒鍵
int wholeStep[7]={0,2,4,5,7,9,11};//ドレミファソラシ
//音色パラメーター(Yamahaの音色設計から抽出)
int const TONES=4;
//GrandPiano,TenorSax,NewAgePd,PickBass
byte BO[TONES]= {0x01,0x00,0x00,0x00};//0-3
byte LFO[TONES]= {0x01,0x01,0x01,0x01};//0-3
byte ALG[TONES]= {0x03,0x05,0x05,0x03};//0-7
byte SR[TONES][4]={ {0x00,0x02,0x01,0x02},
{0x00,0x00,0x00,0x00},
{0x03,0x04,0x00,0x00},
{0x02,0x04,0x02,0x06}};//0-7
byte XOF[TONES][4]={ {0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00}};//0-1
byte KSR[TONES][4]={ {0x00,0x01,0x00,0x01},
{0x01,0x00,0x01,0x00},
{0x01,0x00,0x00,0x00},
{0x01,0x01,0x01,0x01}};//0-1
byte RR[TONES][4]={ {0x06,0x03,0x04,0x06},
{0x00,0x09,0x00,0x09},
{0x00,0x09,0x00,0x09},
{0x03,0x06,0x06,0x08}};//0-15
byte DR[TONES][4]={ {0x07,0x03,0x01,0x02},
{0x03,0x02,0x03,0x02},
{0x0F,0x07,0x01,0x01},
{0x07,0x0b,0x09,0x02}};//0-15
byte AR[TONES][4]={ {0x0F,0x0E,0x0D,0x0D},
{0x07,0x07,0x07,0x07},
{0x0F,0x0F,0x06,0x08},
{0x0f,0x0c,0x0f,0x0b}};//0-15
byte SL[TONES][4]={ {0x0f,0x02,0x03,0x04},
{0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x01},
{0x01,0x07,0x02,0x06}};//0-15
byte TL[TONES][4]={ {0x27,0x28,0x22,0x00},
{0x05,0x0f,0x08,0x0d},
{0x26,0x0b,0x18,0x00},
{0x13,0x15,0x17,0x00}};//0-63
byte KSL[TONES][4]={ {0x01,0x03,0x00,0x02},
{0x02,0x00,0x02,0x02},
{0x00,0x02,0x02,0x02},
{0x02,0x00,0x02,0x00}};//0-3
byte DAM[TONES][4]={ {0x00,0x00,0x00,0x00},
{0x02,0x02,0x02,0x02},
{0x02,0x02,0x00,0x00},
{0x02,0x02,0x02,0x02}};//0-3
byte EAM[TONES][4]={ {0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00}};//0-1
byte DVB[TONES][4]={ {0x00,0x00,0x00,0x00},
{0x02,0x01,0x02,0x01},
{0x02,0x02,0x01,0x01},
{0x02,0x02,0x02,0x02}};//0-3
byte EVB[TONES][4]={ {0x00,0x00,0x01,0x01},
{0x00,0x01,0x00,0x01},
{0x00,0x00,0x01,0x01},
{0x00,0x00,0x01,0x01}};//0-1
byte MULTI[TONES][4]={ {0x01,0x05,0x01,0x01},
{0x01,0x01,0x01,0x01},
{0x07,0x05,0x01,0x01},
{0x01,0x07,0x02,0x01}};//0-15
byte DT[TONES][4]={ {0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00},
{0x00,0x00,0x07,0x00},
{0x00,0x00,0x00,0x00}};//0-7
byte WS[TONES][4]={ {0x08,0x00,0x00,0x00},
{0x01,0x08,0x09,0x00},
{0x01,0x00,0x01,0x00},
{0x00,0x00,0x00,0x00}};//0-31
byte FB[TONES][4]={ {0x00,0x00,0x00,0x00},
{0x03,0x00,0x03,0x00},
{0x05,0x00,0x06,0x00},
{0x05,0x00,0x00,0x00}};//0-7
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
Serial.println("ymf825_demo180213");
pinMode(RST_Pin,OUTPUT);
pinMode(slaveSelectPin,OUTPUT);
digitalWrite(slaveSelectPin, HIGH);
SPI.setBitOrder(MSBFIRST);
SPI.setClockDivider(SPI_CLOCK_DIV8);
SPI.setDataMode(SPI_MODE0);
SPI.begin();
init_825();
set_tone();
set_ch();
}
void loop() {
for(int t=0;t<4;t++){
for(int i=0;i<3;i++){
midiNote(t, 0, 24);
midiNote(t, 1, 28);
midiNote(t, 2, 31);
delay(200);
keyoffVn(0);
keyoffVn(1);
keyoffVn(2);
delay(10);
}
for(int i=0;i<3;i++){
midiNote(t, 0, 31);
midiNote(t, 1, 36);
midiNote(t, 2, 40);
delay(400);
keyoffVn(0);
keyoffVn(1);
keyoffVn(2);
delay(10);
}
for(int i=0;i<3;i++){
midiNote(t, 0, 40);
midiNote(t, 1, 43);
midiNote(t, 2, 48);
delay(200);
keyoffVn(0);
keyoffVn(1);
keyoffVn(2);
delay(10);
}
delay(0);
for(int i=1;i<8;i++){
for(int j=0;j<7;j++){
int note0=i*12 + wholeStep[j];
int note1=(7-i)*12+wholeStep[(6-j)];
midiNote(t, 0, note0);
midiNote(t, 1, note1);
delay(200);
keyoffVn(0);
keyoffVn(1);
delay(10);
}
}
for(int i=7;i>=1;i--){
for(int j=6;j>=0;j--){
int note=i*12 + wholeStep[j];
midiNote(t, 0, note);
delay(200);
keyoffVn(0);
delay(10);
}
}
delay(2000);
}
}
void midiNote(int tnum, int voice, int note){
int fnum=noteFnum[note%12];
byte block=(byte)note/12;
byte fnumh=((0x380 & fnum)>>4)|block; //(0,0,f9,f8,f7,b2,b1,b0)
byte fnuml=0x7f&fnum; //(0,f6,f5,f4,f3,f2,f1,f0)
keyonVn(tnum,voice,fnumh,fnuml);
}
void init_825(void) {
digitalWrite(RST_Pin, LOW);
delay(1);
digitalWrite(RST_Pin, HIGH);
if_s_write( 0x1D, OUTPUT_power );
if_s_write( 0x02, 0x0E );
delay(1);
if_s_write( 0x00, 0x01 );//CLKEN
if_s_write( 0x01, 0x00 ); //AKRST
if_s_write( 0x1A, 0xA3 );
delay(1);
if_s_write( 0x1A, 0x00 );
delay(30);
if_s_write( 0x02, 0x04 );//AP1,AP3
delay(1);
if_s_write( 0x02, 0x00 );
//add
if_s_write( 0x19, 0xF0 );//MASTER VOL
if_s_write( 0x1B, 0x3F );//interpolation
if_s_write( 0x14, 0x00 );//interpolation
if_s_write( 0x03, 0x01 );//Analog Gain
if_s_write( 0x08, 0xF6 );
delay(21);
if_s_write( 0x08, 0x00 );
if_s_write( 0x09, 0xF8 );
if_s_write( 0x0A, 0x00 );
if_s_write( 0x17, 0x40 );//MS_S
if_s_write( 0x18, 0x00 );
}
void set_ch(void){
if_s_write( 0x0F, 0x30 );// keyon = 0
if_s_write( 0x10, 0x71 );// chvol
if_s_write( 0x11, 0x00 );// XVB
if_s_write( 0x12, 0x08 );// FRAC
if_s_write( 0x13, 0x00 );// FRAC
}
void keyonVn(unsigned char tnum, unsigned char voice, unsigned char fnumh, unsigned char fnuml){
byte keyTone=0x40|(tnum&0x0f);
if_s_write( 0x0B, voice );//voice num
if_s_write( 0x0C, 0x54 );//vovol
if_s_write( 0x0D, fnumh );//fnum
if_s_write( 0x0E, fnuml );//fnum
if_s_write( 0x0F, keyTone );//keyon = 1
}
void keyoffVn(unsigned char voice){
if_s_write( 0x0B, voice );//voice num
if_s_write( 0x0F, 0x00 );//keyon = 0
}
void set_tone(){
int const COUNT=TONES*30+5;
byte tone_data[COUNT];
tone_data[0]=0x80+TONES;//Header
for(int i=0;i<TONES;i++){
tone_data[1+i*30]=BO[i] & 0x03;
tone_data[2+i*30]=(LFO[i]<<6)|(ALG[i]&0x07);
tone_data[3+i*30]=(SR[i][0]<<4)|(XOF[i][0]<<3)|KSR[i][0];
tone_data[10+i*30]=(SR[i][1]<<4)|(XOF[i][1]<<3)|KSR[i][1];
tone_data[17+i*30]=(SR[i][2]<<4)|(XOF[i][2]<<3)|KSR[i][2];
tone_data[24+i*30]=(SR[i][3]<<4)|(XOF[i][3]<<3)|KSR[i][3];
tone_data[4+i*30]=(RR[i][0]<<4)|DR[i][0];
tone_data[11+i*30]=(RR[i][1]<<4)|DR[i][1];
tone_data[18+i*30]=(RR[i][2]<<4)|DR[i][2];
tone_data[25+i*30]=(RR[i][3]<<4)|DR[i][3];
tone_data[5+i*30]=(AR[i][0]<<4)|SL[i][0];
tone_data[12+i*30]=(AR[i][1]<<4)|SL[i][1];
tone_data[19+i*30]=(AR[i][2]<<4)|SL[i][2];
tone_data[26+i*30]=(AR[i][3]<<4)|SL[i][3];
tone_data[6+i*30]=(TL[i][0]<<2)|KSL[i][0];
tone_data[13+i*30]=(TL[i][1]<<2)|KSL[i][1];
tone_data[20+i*30]=(TL[i][2]<<2)|KSL[i][2];
tone_data[27+i*30]=(TL[i][3]<<2)|KSL[i][3];
tone_data[7+i*30]=(DAM[i][0]<<5)|(EAM[i][0]<<4)|(DVB[i][0]<<1)|EVB[i][0];
tone_data[14+i*30]=(DAM[i][1]<<5)|(EAM[i][1]<<4)|(DVB[i][1]<<1)|EVB[i][1];
tone_data[21+i*30]=(DAM[i][2]<<5)|(EAM[i][2]<<4)|(DVB[i][2]<<1)|EVB[i][2];
tone_data[28+i*30]=(DAM[i][3]<<5)|(EAM[i][3]<<4)|(DVB[i][3]<<1)|EVB[i][3];
tone_data[8+i*30]=(MULTI[i][0]<<4)|DT[i][0];
tone_data[15+i*30]=(MULTI[i][1]<<4)|DT[i][1];
tone_data[22+i*30]=(MULTI[i][2]<<4)|DT[i][2];
tone_data[29+i*30]=(MULTI[i][3]<<4)|DT[i][3];
tone_data[9+i*30]=(WS[i][0]<<3)|FB[i][0];
tone_data[16+i*30]=(WS[i][1]<<3)|FB[i][1];
tone_data[23+i*30]=(WS[i][2]<<3)|FB[i][2];
tone_data[30+i*30]=(WS[i][3]<<3)|FB[i][3];
}
//modified at 180213
tone_data[1+TONES*30]=0x80;//Footer
tone_data[2+TONES*30]=0x03;
tone_data[3+TONES*30]=0x81;
tone_data[4+TONES*30]=0x80;
if_s_write( 0x08, 0xF6 );
delay(1);
if_s_write( 0x08, 0x00 );
if_write( 0x07, &tone_data[0], TONES*30+5 );//write to FIFO
}
void if_write(char addr,unsigned char* data,char num){
char i;
char snd;
digitalWrite(slaveSelectPin, LOW);
SPI.transfer(addr);
for(i=0;i<num;i++){
SPI.transfer(data[i]);
}
digitalWrite(slaveSelectPin, HIGH);
}
void if_s_write(char addr,unsigned char data){
if_write(addr,&data,1);
}
unsigned char if_s_read(char addr){
unsigned char rcv;
digitalWrite(slaveSelectPin, LOW);
SPI.transfer(0x80|addr);
rcv = SPI.transfer(0x00);
digitalWrite(slaveSelectPin, HIGH);
return rcv;
}