This program generates sound by using FM tone generator YMF825 via SPI.

Dependencies:   microbit

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers fmtone.c Source File

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 = &regImage[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 }