This program generates sound by using FM tone generator YMF825 via SPI.
Embed:
(wiki syntax)
Show/hide line numbers
fmtone.c
00001 // fmtone.c 00002 #include "fmtype.h" 00003 #include "fmtone.h" 00004 #include "fmsd1.h" 00005 00006 #define IMMUTABLE_TONE_MAX 8 00007 #define MUTABLE_TONE_MAX IMMUTABLE_TONE_MAX 00008 #define AVAILABLE_TONE_NUMBER (IMMUTABLE_TONE_MAX+MUTABLE_TONE_MAX) 00009 #define MAX_EXCLUSIVE_HEADER_SIZE 5 00010 00011 #define MAX_ELEMENT_PRM 2 00012 #define OPERATOR_PRM_REG_SZ 7 00013 #define MAX_TONE_PRM_SZ (MAX_FM_OPERATOR*OPERATOR_PRM_REG_SZ + MAX_ELEMENT_PRM) 00014 00015 typedef enum { 00016 WAIT_DATA, 00017 DURING_SETTING, 00018 SET_STATE_MAX 00019 } SET_STATE; 00020 00021 // Variable 00022 static SET_STATE _toneSetState; 00023 static int _tprmIndex; 00024 static ToneData _userTone[MUTABLE_TONE_MAX]; 00025 static const ToneData TPRM[IMMUTABLE_TONE_MAX] = { 00026 00027 { // GrandPiano 00028 0x0b, // VoiceCommon 00029 { // KC | AR | DR | SR | RR | SL | TL | VB | PT | WS 00030 {0x01,0x0f,0x07,0x00,0x06,0x0f,0x27,0x00,0x01,0x08}, // op1 00031 {0x07,0x0e,0x03,0x02,0x03,0x02,0x28,0x00,0x05,0x00}, // op2 00032 {0x00,0x0d,0x01,0x01,0x04,0x03,0x22,0x01,0x01,0x00}, // op3 00033 {0x06,0x0d,0x02,0x02,0x06,0x04,0x00,0x01,0x01,0x00} // op4 00034 } 00035 }, 00036 { // E.Piano 00037 0x0d, // VoiceCommon 00038 { // KC | AR | DR | SR | RR | SL | TL | VB | PT | WS 00039 {0x54,0x0f,0x04,0x05,0x0c,0x0b,0x23,0x44,0x07,0x12}, // op1 00040 {0x02,0x0f,0x02,0x01,0x08,0x0f,0x04,0x45,0x01,0x00}, // op2 00041 {0x25,0x0f,0x00,0x01,0x0b,0x01,0x12,0x44,0x01,0x00}, // op3 00042 {0x04,0x0f,0x02,0x01,0x07,0x0f,0x04,0x41,0x01,0x00} // op4 00043 } 00044 }, 00045 { // TenorSax 00046 0x0d, // VoiceCommon 00047 { // KC | AR | DR | SR | RR | SL | TL | VB | PT | WS 00048 {0x36,0x07,0x03,0x00,0x00,0x00,0x05,0x44,0x01,0x01}, // op1 00049 {0x00,0x07,0x02,0x00,0x09,0x00,0x0f,0x43,0x01,0x08}, // op2 00050 {0x36,0x07,0x03,0x00,0x00,0x00,0x08,0x44,0x01,0x09}, // op3 00051 {0x02,0x07,0x02,0x00,0x09,0x00,0x0d,0x43,0x01,0x00} // op4 00052 } 00053 }, 00054 { // PickBass 00055 0x0b, // VoiceCommon 00056 { // KC | AR | DR | SR | RR | SL | TL | VB | PT | WS 00057 {0x56,0x0f,0x07,0x02,0x03,0x01,0x13,0x44,0x01,0x00}, // op1 00058 {0x04,0x0c,0x0b,0x04,0x06,0x07,0x15,0x44,0x07,0x00}, // op2 00059 {0x06,0x0f,0x09,0x02,0x06,0x02,0x17,0x44,0x02,0x00}, // op3 00060 {0x04,0x0b,0x02,0x06,0x08,0x06,0x00,0x44,0x01,0x00} // op4 00061 } 00062 }, 00063 { // TnklBell 00064 0x0d, // VoiceCommon 00065 { // KC | AR | DR | SR | RR | SL | TL | VB | PT | WS 00066 {0x31,0x0f,0x06,0x03,0x04,0x05,0x10,0x44,0x0e,0x00}, // op1 00067 {0x02,0x0c,0x06,0x07,0x06,0x0e,0x0b,0x44,0x02,0x00}, // op2 00068 {0x00,0x0c,0x06,0x02,0x02,0x05,0x1e,0x44,0x77,0x01}, // op3 00069 {0x00,0x0f,0x05,0x04,0x05,0x0d,0x01,0x54,0x06,0x00} // op4 00070 } 00071 }, 00072 { // NewAgePd 00073 0x0d, // VoiceCommon 00074 { // KC | AR | DR | SR | RR | SL | TL | VB | PT | WS 00075 {0x54,0x0f,0x0f,0x03,0x03,0x00,0x26,0x44,0x07,0x01}, // op1 00076 {0x02,0x0f,0x07,0x04,0x04,0x00,0x0b,0x44,0x05,0x00}, // op2 00077 {0x62,0x06,0x01,0x00,0x01,0x00,0x18,0x03,0x71,0x01}, // op3 00078 {0x02,0x08,0x01,0x00,0x05,0x01,0x00,0x03,0x01,0x00} // op4 00079 } 00080 }, 00081 { // Rim Shot 00082 0x0d, // VoiceCommon 00083 { // KC | AR | DR | SR | RR | SL | TL | VB | PT | WS 00084 {0x7c,0x0f,0x00,0x05,0x05,0x00,0x05,0x44,0x0c,0x02}, // op1 00085 {0x0c,0x0f,0x07,0x07,0x07,0x07,0x00,0x44,0x0b,0x00}, // op2 00086 {0x08,0x0f,0x0a,0x06,0x06,0x08,0x00,0x44,0x0c,0x00}, // op3 00087 {0x08,0x0f,0x07,0x07,0x07,0x07,0x00,0x44,0x07,0x02} // op4 00088 } 00089 }, 00090 { // Castanet 00091 0x0d, // VoiceCommon 00092 { // KC | AR | DR | SR | RR | SL | TL | VB | PT | WS 00093 {0x68,0x0f,0x07,0x05,0x09,0x0f,0x02,0x44,0x07,0x01}, // op1 00094 {0x0c,0x0a,0x08,0x05,0x0f,0x0f,0x00,0x44,0x05,0x06}, // op2 00095 {0x08,0x0f,0x05,0x06,0x05,0x00,0x27,0x44,0x02,0x05}, // op3 00096 {0x08,0x0c,0x0a,0x09,0x09,0x0a,0x14,0x44,0x05,0x00} // op4 00097 } 00098 } 00099 }; 00100 const unsigned char tExcCheck[MAX_EXCLUSIVE_HEADER_SIZE] = { 00101 0x43, // Exclusive:1, Yamaha ID 00102 0x7f, // Exclusive:2, Make/DIY ID1 00103 0x02, // Exclusive:3, Make/DIY ID2 00104 0x00, // Exclusive:4, YMF825 ID 00105 0x00 // Exclusive:5, reserved 00106 }; 00107 void Tone_init( void ) 00108 { 00109 int i; 00110 for ( i=0; i<MUTABLE_TONE_MAX; i++ ){ 00111 _userTone[i] = TPRM[i]; 00112 } 00113 _toneSetState = WAIT_DATA; 00114 _tprmIndex = 0; 00115 00116 Tone_sendTone(); 00117 } 00118 void Tone_setToneExc( unsigned char data, int excNum ) 00119 { 00120 if ( _toneSetState == WAIT_DATA ){ 00121 if (( excNum == 1 ) && ( data == tExcCheck[0] )){ 00122 _toneSetState = DURING_SETTING; 00123 } 00124 } 00125 else if ( _toneSetState == DURING_SETTING ){ 00126 if ( excNum-1 < MAX_EXCLUSIVE_HEADER_SIZE ){ 00127 if ( data != tExcCheck[excNum-1] ){ _toneSetState = WAIT_DATA; } 00128 } 00129 else if ( excNum == 6 ){ 00130 if ( data < MUTABLE_TONE_MAX ){ _tprmIndex = data; } 00131 else { _toneSetState = WAIT_DATA; } 00132 } 00133 else if ( excNum == 7 ){ 00134 _userTone[_tprmIndex].voiceCommon = data; 00135 } 00136 else if ( excNum < 48 ){ 00137 _userTone[_tprmIndex].opPrm[(excNum-8)/MAX_OPERATOR_PRM][(excNum-8)%MAX_OPERATOR_PRM] = data; 00138 } 00139 else { _toneSetState = WAIT_DATA; } 00140 } 00141 } 00142 void Tone_sendTone( void ) 00143 { 00144 int i,j; 00145 unsigned char regImage[MAX_TONE_PRM_SZ*AVAILABLE_TONE_NUMBER + 1 + 4]; // 485 00146 00147 // top 00148 regImage[0] = 0x80 + AVAILABLE_TONE_NUMBER; 00149 00150 for ( i=0; i<AVAILABLE_TONE_NUMBER; i++ ){ 00151 unsigned char* riPtr = ®Image[MAX_TONE_PRM_SZ*i + 1]; 00152 00153 ToneData* td; 00154 if ( i < IMMUTABLE_TONE_MAX ){ 00155 td = (ToneData*)&(TPRM[i]); 00156 } 00157 else { 00158 td = (ToneData*)&(_userTone[i-IMMUTABLE_TONE_MAX]); 00159 } 00160 00161 riPtr[0] = (td->voiceCommon & 0x60)>>5; 00162 riPtr[1] = ((td->voiceCommon & 0x18)<<3) | (td->voiceCommon & 0x07); 00163 00164 for ( j=0; j<MAX_FM_OPERATOR; j++ ){ 00165 riPtr[MAX_ELEMENT_PRM+OPERATOR_PRM_REG_SZ*j+0] = (td->opPrm[j][3] << 4) | (td->opPrm[j][0] & 0x08) | ((td->opPrm[j][0] & 0x04)>>2); 00166 riPtr[MAX_ELEMENT_PRM+OPERATOR_PRM_REG_SZ*j+1] = (td->opPrm[j][4] << 4) | td->opPrm[j][2]; 00167 riPtr[MAX_ELEMENT_PRM+OPERATOR_PRM_REG_SZ*j+2] = (td->opPrm[j][1] << 4) | td->opPrm[j][5]; 00168 riPtr[MAX_ELEMENT_PRM+OPERATOR_PRM_REG_SZ*j+3] = (td->opPrm[j][6] << 2) | (td->opPrm[j][0] & 0x03); 00169 riPtr[MAX_ELEMENT_PRM+OPERATOR_PRM_REG_SZ*j+4] = td->opPrm[j][7]; 00170 riPtr[MAX_ELEMENT_PRM+OPERATOR_PRM_REG_SZ*j+5] = ((td->opPrm[j][8] & 0x0f) << 4) | ((td->opPrm[j][8] & 0xf0) >> 4); 00171 riPtr[MAX_ELEMENT_PRM+OPERATOR_PRM_REG_SZ*j+6] = (td->opPrm[j][9] << 3) | ((td->opPrm[j][0] & 0x70) >> 4); 00172 } 00173 } 00174 00175 // end 00176 regImage[MAX_TONE_PRM_SZ*AVAILABLE_TONE_NUMBER + 1] = 0x80; 00177 regImage[MAX_TONE_PRM_SZ*AVAILABLE_TONE_NUMBER + 2] = 0x03; 00178 regImage[MAX_TONE_PRM_SZ*AVAILABLE_TONE_NUMBER + 3] = 0x81; 00179 regImage[MAX_TONE_PRM_SZ*AVAILABLE_TONE_NUMBER + 4] = 0x80; 00180 00181 // Soft Reset 00182 // writeSingle(26,0xa3); 00183 // writeSingle(26,0x00); 00184 writeSingle(8,0xf6); 00185 delayMs(1); 00186 writeSingle(8,0x00); 00187 00188 writeBurst( 7, regImage, MAX_TONE_PRM_SZ*AVAILABLE_TONE_NUMBER + 5 ); 00189 }
Generated on Wed Jul 13 2022 08:46:10 by 1.7.2