This program generates sound by using FM tone generator YMF825 via SPI.
fmtone.c
- Committer:
- hasebems
- Date:
- 2018-01-05
- Revision:
- 0:c54d59d6fb78
File content as of revision 0:c54d59d6fb78:
// fmtone.c #include "fmtype.h" #include "fmtone.h" #include "fmsd1.h" #define IMMUTABLE_TONE_MAX 8 #define MUTABLE_TONE_MAX IMMUTABLE_TONE_MAX #define AVAILABLE_TONE_NUMBER (IMMUTABLE_TONE_MAX+MUTABLE_TONE_MAX) #define MAX_EXCLUSIVE_HEADER_SIZE 5 #define MAX_ELEMENT_PRM 2 #define OPERATOR_PRM_REG_SZ 7 #define MAX_TONE_PRM_SZ (MAX_FM_OPERATOR*OPERATOR_PRM_REG_SZ + MAX_ELEMENT_PRM) typedef enum { WAIT_DATA, DURING_SETTING, SET_STATE_MAX } SET_STATE; // Variable static SET_STATE _toneSetState; static int _tprmIndex; static ToneData _userTone[MUTABLE_TONE_MAX]; static const ToneData TPRM[IMMUTABLE_TONE_MAX] = { { // GrandPiano 0x0b, // VoiceCommon { // KC | AR | DR | SR | RR | SL | TL | VB | PT | WS {0x01,0x0f,0x07,0x00,0x06,0x0f,0x27,0x00,0x01,0x08}, // op1 {0x07,0x0e,0x03,0x02,0x03,0x02,0x28,0x00,0x05,0x00}, // op2 {0x00,0x0d,0x01,0x01,0x04,0x03,0x22,0x01,0x01,0x00}, // op3 {0x06,0x0d,0x02,0x02,0x06,0x04,0x00,0x01,0x01,0x00} // op4 } }, { // E.Piano 0x0d, // VoiceCommon { // KC | AR | DR | SR | RR | SL | TL | VB | PT | WS {0x54,0x0f,0x04,0x05,0x0c,0x0b,0x23,0x44,0x07,0x12}, // op1 {0x02,0x0f,0x02,0x01,0x08,0x0f,0x04,0x45,0x01,0x00}, // op2 {0x25,0x0f,0x00,0x01,0x0b,0x01,0x12,0x44,0x01,0x00}, // op3 {0x04,0x0f,0x02,0x01,0x07,0x0f,0x04,0x41,0x01,0x00} // op4 } }, { // TenorSax 0x0d, // VoiceCommon { // KC | AR | DR | SR | RR | SL | TL | VB | PT | WS {0x36,0x07,0x03,0x00,0x00,0x00,0x05,0x44,0x01,0x01}, // op1 {0x00,0x07,0x02,0x00,0x09,0x00,0x0f,0x43,0x01,0x08}, // op2 {0x36,0x07,0x03,0x00,0x00,0x00,0x08,0x44,0x01,0x09}, // op3 {0x02,0x07,0x02,0x00,0x09,0x00,0x0d,0x43,0x01,0x00} // op4 } }, { // PickBass 0x0b, // VoiceCommon { // KC | AR | DR | SR | RR | SL | TL | VB | PT | WS {0x56,0x0f,0x07,0x02,0x03,0x01,0x13,0x44,0x01,0x00}, // op1 {0x04,0x0c,0x0b,0x04,0x06,0x07,0x15,0x44,0x07,0x00}, // op2 {0x06,0x0f,0x09,0x02,0x06,0x02,0x17,0x44,0x02,0x00}, // op3 {0x04,0x0b,0x02,0x06,0x08,0x06,0x00,0x44,0x01,0x00} // op4 } }, { // TnklBell 0x0d, // VoiceCommon { // KC | AR | DR | SR | RR | SL | TL | VB | PT | WS {0x31,0x0f,0x06,0x03,0x04,0x05,0x10,0x44,0x0e,0x00}, // op1 {0x02,0x0c,0x06,0x07,0x06,0x0e,0x0b,0x44,0x02,0x00}, // op2 {0x00,0x0c,0x06,0x02,0x02,0x05,0x1e,0x44,0x77,0x01}, // op3 {0x00,0x0f,0x05,0x04,0x05,0x0d,0x01,0x54,0x06,0x00} // op4 } }, { // NewAgePd 0x0d, // VoiceCommon { // KC | AR | DR | SR | RR | SL | TL | VB | PT | WS {0x54,0x0f,0x0f,0x03,0x03,0x00,0x26,0x44,0x07,0x01}, // op1 {0x02,0x0f,0x07,0x04,0x04,0x00,0x0b,0x44,0x05,0x00}, // op2 {0x62,0x06,0x01,0x00,0x01,0x00,0x18,0x03,0x71,0x01}, // op3 {0x02,0x08,0x01,0x00,0x05,0x01,0x00,0x03,0x01,0x00} // op4 } }, { // Rim Shot 0x0d, // VoiceCommon { // KC | AR | DR | SR | RR | SL | TL | VB | PT | WS {0x7c,0x0f,0x00,0x05,0x05,0x00,0x05,0x44,0x0c,0x02}, // op1 {0x0c,0x0f,0x07,0x07,0x07,0x07,0x00,0x44,0x0b,0x00}, // op2 {0x08,0x0f,0x0a,0x06,0x06,0x08,0x00,0x44,0x0c,0x00}, // op3 {0x08,0x0f,0x07,0x07,0x07,0x07,0x00,0x44,0x07,0x02} // op4 } }, { // Castanet 0x0d, // VoiceCommon { // KC | AR | DR | SR | RR | SL | TL | VB | PT | WS {0x68,0x0f,0x07,0x05,0x09,0x0f,0x02,0x44,0x07,0x01}, // op1 {0x0c,0x0a,0x08,0x05,0x0f,0x0f,0x00,0x44,0x05,0x06}, // op2 {0x08,0x0f,0x05,0x06,0x05,0x00,0x27,0x44,0x02,0x05}, // op3 {0x08,0x0c,0x0a,0x09,0x09,0x0a,0x14,0x44,0x05,0x00} // op4 } } }; const unsigned char tExcCheck[MAX_EXCLUSIVE_HEADER_SIZE] = { 0x43, // Exclusive:1, Yamaha ID 0x7f, // Exclusive:2, Make/DIY ID1 0x02, // Exclusive:3, Make/DIY ID2 0x00, // Exclusive:4, YMF825 ID 0x00 // Exclusive:5, reserved }; void Tone_init( void ) { int i; for ( i=0; i<MUTABLE_TONE_MAX; i++ ){ _userTone[i] = TPRM[i]; } _toneSetState = WAIT_DATA; _tprmIndex = 0; Tone_sendTone(); } void Tone_setToneExc( unsigned char data, int excNum ) { if ( _toneSetState == WAIT_DATA ){ if (( excNum == 1 ) && ( data == tExcCheck[0] )){ _toneSetState = DURING_SETTING; } } else if ( _toneSetState == DURING_SETTING ){ if ( excNum-1 < MAX_EXCLUSIVE_HEADER_SIZE ){ if ( data != tExcCheck[excNum-1] ){ _toneSetState = WAIT_DATA; } } else if ( excNum == 6 ){ if ( data < MUTABLE_TONE_MAX ){ _tprmIndex = data; } else { _toneSetState = WAIT_DATA; } } else if ( excNum == 7 ){ _userTone[_tprmIndex].voiceCommon = data; } else if ( excNum < 48 ){ _userTone[_tprmIndex].opPrm[(excNum-8)/MAX_OPERATOR_PRM][(excNum-8)%MAX_OPERATOR_PRM] = data; } else { _toneSetState = WAIT_DATA; } } } void Tone_sendTone( void ) { int i,j; unsigned char regImage[MAX_TONE_PRM_SZ*AVAILABLE_TONE_NUMBER + 1 + 4]; // 485 // top regImage[0] = 0x80 + AVAILABLE_TONE_NUMBER; for ( i=0; i<AVAILABLE_TONE_NUMBER; i++ ){ unsigned char* riPtr = ®Image[MAX_TONE_PRM_SZ*i + 1]; ToneData* td; if ( i < IMMUTABLE_TONE_MAX ){ td = (ToneData*)&(TPRM[i]); } else { td = (ToneData*)&(_userTone[i-IMMUTABLE_TONE_MAX]); } riPtr[0] = (td->voiceCommon & 0x60)>>5; riPtr[1] = ((td->voiceCommon & 0x18)<<3) | (td->voiceCommon & 0x07); for ( j=0; j<MAX_FM_OPERATOR; j++ ){ 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); riPtr[MAX_ELEMENT_PRM+OPERATOR_PRM_REG_SZ*j+1] = (td->opPrm[j][4] << 4) | td->opPrm[j][2]; riPtr[MAX_ELEMENT_PRM+OPERATOR_PRM_REG_SZ*j+2] = (td->opPrm[j][1] << 4) | td->opPrm[j][5]; riPtr[MAX_ELEMENT_PRM+OPERATOR_PRM_REG_SZ*j+3] = (td->opPrm[j][6] << 2) | (td->opPrm[j][0] & 0x03); riPtr[MAX_ELEMENT_PRM+OPERATOR_PRM_REG_SZ*j+4] = td->opPrm[j][7]; riPtr[MAX_ELEMENT_PRM+OPERATOR_PRM_REG_SZ*j+5] = ((td->opPrm[j][8] & 0x0f) << 4) | ((td->opPrm[j][8] & 0xf0) >> 4); riPtr[MAX_ELEMENT_PRM+OPERATOR_PRM_REG_SZ*j+6] = (td->opPrm[j][9] << 3) | ((td->opPrm[j][0] & 0x70) >> 4); } } // end regImage[MAX_TONE_PRM_SZ*AVAILABLE_TONE_NUMBER + 1] = 0x80; regImage[MAX_TONE_PRM_SZ*AVAILABLE_TONE_NUMBER + 2] = 0x03; regImage[MAX_TONE_PRM_SZ*AVAILABLE_TONE_NUMBER + 3] = 0x81; regImage[MAX_TONE_PRM_SZ*AVAILABLE_TONE_NUMBER + 4] = 0x80; // Soft Reset // writeSingle(26,0xa3); // writeSingle(26,0x00); writeSingle(8,0xf6); delayMs(1); writeSingle(8,0x00); writeBurst( 7, regImage, MAX_TONE_PRM_SZ*AVAILABLE_TONE_NUMBER + 5 ); }