This program generates sound by using FM tone generator YMF825 via SPI.
fmtone.c@0:c54d59d6fb78, 2018-01-05 (annotated)
- Committer:
- hasebems
- Date:
- Fri Jan 05 22:58:49 2018 +0000
- Revision:
- 0:c54d59d6fb78
???????????????
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
hasebems | 0:c54d59d6fb78 | 1 | // fmtone.c |
hasebems | 0:c54d59d6fb78 | 2 | #include "fmtype.h" |
hasebems | 0:c54d59d6fb78 | 3 | #include "fmtone.h" |
hasebems | 0:c54d59d6fb78 | 4 | #include "fmsd1.h" |
hasebems | 0:c54d59d6fb78 | 5 | |
hasebems | 0:c54d59d6fb78 | 6 | #define IMMUTABLE_TONE_MAX 8 |
hasebems | 0:c54d59d6fb78 | 7 | #define MUTABLE_TONE_MAX IMMUTABLE_TONE_MAX |
hasebems | 0:c54d59d6fb78 | 8 | #define AVAILABLE_TONE_NUMBER (IMMUTABLE_TONE_MAX+MUTABLE_TONE_MAX) |
hasebems | 0:c54d59d6fb78 | 9 | #define MAX_EXCLUSIVE_HEADER_SIZE 5 |
hasebems | 0:c54d59d6fb78 | 10 | |
hasebems | 0:c54d59d6fb78 | 11 | #define MAX_ELEMENT_PRM 2 |
hasebems | 0:c54d59d6fb78 | 12 | #define OPERATOR_PRM_REG_SZ 7 |
hasebems | 0:c54d59d6fb78 | 13 | #define MAX_TONE_PRM_SZ (MAX_FM_OPERATOR*OPERATOR_PRM_REG_SZ + MAX_ELEMENT_PRM) |
hasebems | 0:c54d59d6fb78 | 14 | |
hasebems | 0:c54d59d6fb78 | 15 | typedef enum { |
hasebems | 0:c54d59d6fb78 | 16 | WAIT_DATA, |
hasebems | 0:c54d59d6fb78 | 17 | DURING_SETTING, |
hasebems | 0:c54d59d6fb78 | 18 | SET_STATE_MAX |
hasebems | 0:c54d59d6fb78 | 19 | } SET_STATE; |
hasebems | 0:c54d59d6fb78 | 20 | |
hasebems | 0:c54d59d6fb78 | 21 | // Variable |
hasebems | 0:c54d59d6fb78 | 22 | static SET_STATE _toneSetState; |
hasebems | 0:c54d59d6fb78 | 23 | static int _tprmIndex; |
hasebems | 0:c54d59d6fb78 | 24 | static ToneData _userTone[MUTABLE_TONE_MAX]; |
hasebems | 0:c54d59d6fb78 | 25 | static const ToneData TPRM[IMMUTABLE_TONE_MAX] = { |
hasebems | 0:c54d59d6fb78 | 26 | |
hasebems | 0:c54d59d6fb78 | 27 | { // GrandPiano |
hasebems | 0:c54d59d6fb78 | 28 | 0x0b, // VoiceCommon |
hasebems | 0:c54d59d6fb78 | 29 | { // KC | AR | DR | SR | RR | SL | TL | VB | PT | WS |
hasebems | 0:c54d59d6fb78 | 30 | {0x01,0x0f,0x07,0x00,0x06,0x0f,0x27,0x00,0x01,0x08}, // op1 |
hasebems | 0:c54d59d6fb78 | 31 | {0x07,0x0e,0x03,0x02,0x03,0x02,0x28,0x00,0x05,0x00}, // op2 |
hasebems | 0:c54d59d6fb78 | 32 | {0x00,0x0d,0x01,0x01,0x04,0x03,0x22,0x01,0x01,0x00}, // op3 |
hasebems | 0:c54d59d6fb78 | 33 | {0x06,0x0d,0x02,0x02,0x06,0x04,0x00,0x01,0x01,0x00} // op4 |
hasebems | 0:c54d59d6fb78 | 34 | } |
hasebems | 0:c54d59d6fb78 | 35 | }, |
hasebems | 0:c54d59d6fb78 | 36 | { // E.Piano |
hasebems | 0:c54d59d6fb78 | 37 | 0x0d, // VoiceCommon |
hasebems | 0:c54d59d6fb78 | 38 | { // KC | AR | DR | SR | RR | SL | TL | VB | PT | WS |
hasebems | 0:c54d59d6fb78 | 39 | {0x54,0x0f,0x04,0x05,0x0c,0x0b,0x23,0x44,0x07,0x12}, // op1 |
hasebems | 0:c54d59d6fb78 | 40 | {0x02,0x0f,0x02,0x01,0x08,0x0f,0x04,0x45,0x01,0x00}, // op2 |
hasebems | 0:c54d59d6fb78 | 41 | {0x25,0x0f,0x00,0x01,0x0b,0x01,0x12,0x44,0x01,0x00}, // op3 |
hasebems | 0:c54d59d6fb78 | 42 | {0x04,0x0f,0x02,0x01,0x07,0x0f,0x04,0x41,0x01,0x00} // op4 |
hasebems | 0:c54d59d6fb78 | 43 | } |
hasebems | 0:c54d59d6fb78 | 44 | }, |
hasebems | 0:c54d59d6fb78 | 45 | { // TenorSax |
hasebems | 0:c54d59d6fb78 | 46 | 0x0d, // VoiceCommon |
hasebems | 0:c54d59d6fb78 | 47 | { // KC | AR | DR | SR | RR | SL | TL | VB | PT | WS |
hasebems | 0:c54d59d6fb78 | 48 | {0x36,0x07,0x03,0x00,0x00,0x00,0x05,0x44,0x01,0x01}, // op1 |
hasebems | 0:c54d59d6fb78 | 49 | {0x00,0x07,0x02,0x00,0x09,0x00,0x0f,0x43,0x01,0x08}, // op2 |
hasebems | 0:c54d59d6fb78 | 50 | {0x36,0x07,0x03,0x00,0x00,0x00,0x08,0x44,0x01,0x09}, // op3 |
hasebems | 0:c54d59d6fb78 | 51 | {0x02,0x07,0x02,0x00,0x09,0x00,0x0d,0x43,0x01,0x00} // op4 |
hasebems | 0:c54d59d6fb78 | 52 | } |
hasebems | 0:c54d59d6fb78 | 53 | }, |
hasebems | 0:c54d59d6fb78 | 54 | { // PickBass |
hasebems | 0:c54d59d6fb78 | 55 | 0x0b, // VoiceCommon |
hasebems | 0:c54d59d6fb78 | 56 | { // KC | AR | DR | SR | RR | SL | TL | VB | PT | WS |
hasebems | 0:c54d59d6fb78 | 57 | {0x56,0x0f,0x07,0x02,0x03,0x01,0x13,0x44,0x01,0x00}, // op1 |
hasebems | 0:c54d59d6fb78 | 58 | {0x04,0x0c,0x0b,0x04,0x06,0x07,0x15,0x44,0x07,0x00}, // op2 |
hasebems | 0:c54d59d6fb78 | 59 | {0x06,0x0f,0x09,0x02,0x06,0x02,0x17,0x44,0x02,0x00}, // op3 |
hasebems | 0:c54d59d6fb78 | 60 | {0x04,0x0b,0x02,0x06,0x08,0x06,0x00,0x44,0x01,0x00} // op4 |
hasebems | 0:c54d59d6fb78 | 61 | } |
hasebems | 0:c54d59d6fb78 | 62 | }, |
hasebems | 0:c54d59d6fb78 | 63 | { // TnklBell |
hasebems | 0:c54d59d6fb78 | 64 | 0x0d, // VoiceCommon |
hasebems | 0:c54d59d6fb78 | 65 | { // KC | AR | DR | SR | RR | SL | TL | VB | PT | WS |
hasebems | 0:c54d59d6fb78 | 66 | {0x31,0x0f,0x06,0x03,0x04,0x05,0x10,0x44,0x0e,0x00}, // op1 |
hasebems | 0:c54d59d6fb78 | 67 | {0x02,0x0c,0x06,0x07,0x06,0x0e,0x0b,0x44,0x02,0x00}, // op2 |
hasebems | 0:c54d59d6fb78 | 68 | {0x00,0x0c,0x06,0x02,0x02,0x05,0x1e,0x44,0x77,0x01}, // op3 |
hasebems | 0:c54d59d6fb78 | 69 | {0x00,0x0f,0x05,0x04,0x05,0x0d,0x01,0x54,0x06,0x00} // op4 |
hasebems | 0:c54d59d6fb78 | 70 | } |
hasebems | 0:c54d59d6fb78 | 71 | }, |
hasebems | 0:c54d59d6fb78 | 72 | { // NewAgePd |
hasebems | 0:c54d59d6fb78 | 73 | 0x0d, // VoiceCommon |
hasebems | 0:c54d59d6fb78 | 74 | { // KC | AR | DR | SR | RR | SL | TL | VB | PT | WS |
hasebems | 0:c54d59d6fb78 | 75 | {0x54,0x0f,0x0f,0x03,0x03,0x00,0x26,0x44,0x07,0x01}, // op1 |
hasebems | 0:c54d59d6fb78 | 76 | {0x02,0x0f,0x07,0x04,0x04,0x00,0x0b,0x44,0x05,0x00}, // op2 |
hasebems | 0:c54d59d6fb78 | 77 | {0x62,0x06,0x01,0x00,0x01,0x00,0x18,0x03,0x71,0x01}, // op3 |
hasebems | 0:c54d59d6fb78 | 78 | {0x02,0x08,0x01,0x00,0x05,0x01,0x00,0x03,0x01,0x00} // op4 |
hasebems | 0:c54d59d6fb78 | 79 | } |
hasebems | 0:c54d59d6fb78 | 80 | }, |
hasebems | 0:c54d59d6fb78 | 81 | { // Rim Shot |
hasebems | 0:c54d59d6fb78 | 82 | 0x0d, // VoiceCommon |
hasebems | 0:c54d59d6fb78 | 83 | { // KC | AR | DR | SR | RR | SL | TL | VB | PT | WS |
hasebems | 0:c54d59d6fb78 | 84 | {0x7c,0x0f,0x00,0x05,0x05,0x00,0x05,0x44,0x0c,0x02}, // op1 |
hasebems | 0:c54d59d6fb78 | 85 | {0x0c,0x0f,0x07,0x07,0x07,0x07,0x00,0x44,0x0b,0x00}, // op2 |
hasebems | 0:c54d59d6fb78 | 86 | {0x08,0x0f,0x0a,0x06,0x06,0x08,0x00,0x44,0x0c,0x00}, // op3 |
hasebems | 0:c54d59d6fb78 | 87 | {0x08,0x0f,0x07,0x07,0x07,0x07,0x00,0x44,0x07,0x02} // op4 |
hasebems | 0:c54d59d6fb78 | 88 | } |
hasebems | 0:c54d59d6fb78 | 89 | }, |
hasebems | 0:c54d59d6fb78 | 90 | { // Castanet |
hasebems | 0:c54d59d6fb78 | 91 | 0x0d, // VoiceCommon |
hasebems | 0:c54d59d6fb78 | 92 | { // KC | AR | DR | SR | RR | SL | TL | VB | PT | WS |
hasebems | 0:c54d59d6fb78 | 93 | {0x68,0x0f,0x07,0x05,0x09,0x0f,0x02,0x44,0x07,0x01}, // op1 |
hasebems | 0:c54d59d6fb78 | 94 | {0x0c,0x0a,0x08,0x05,0x0f,0x0f,0x00,0x44,0x05,0x06}, // op2 |
hasebems | 0:c54d59d6fb78 | 95 | {0x08,0x0f,0x05,0x06,0x05,0x00,0x27,0x44,0x02,0x05}, // op3 |
hasebems | 0:c54d59d6fb78 | 96 | {0x08,0x0c,0x0a,0x09,0x09,0x0a,0x14,0x44,0x05,0x00} // op4 |
hasebems | 0:c54d59d6fb78 | 97 | } |
hasebems | 0:c54d59d6fb78 | 98 | } |
hasebems | 0:c54d59d6fb78 | 99 | }; |
hasebems | 0:c54d59d6fb78 | 100 | const unsigned char tExcCheck[MAX_EXCLUSIVE_HEADER_SIZE] = { |
hasebems | 0:c54d59d6fb78 | 101 | 0x43, // Exclusive:1, Yamaha ID |
hasebems | 0:c54d59d6fb78 | 102 | 0x7f, // Exclusive:2, Make/DIY ID1 |
hasebems | 0:c54d59d6fb78 | 103 | 0x02, // Exclusive:3, Make/DIY ID2 |
hasebems | 0:c54d59d6fb78 | 104 | 0x00, // Exclusive:4, YMF825 ID |
hasebems | 0:c54d59d6fb78 | 105 | 0x00 // Exclusive:5, reserved |
hasebems | 0:c54d59d6fb78 | 106 | }; |
hasebems | 0:c54d59d6fb78 | 107 | void Tone_init( void ) |
hasebems | 0:c54d59d6fb78 | 108 | { |
hasebems | 0:c54d59d6fb78 | 109 | int i; |
hasebems | 0:c54d59d6fb78 | 110 | for ( i=0; i<MUTABLE_TONE_MAX; i++ ){ |
hasebems | 0:c54d59d6fb78 | 111 | _userTone[i] = TPRM[i]; |
hasebems | 0:c54d59d6fb78 | 112 | } |
hasebems | 0:c54d59d6fb78 | 113 | _toneSetState = WAIT_DATA; |
hasebems | 0:c54d59d6fb78 | 114 | _tprmIndex = 0; |
hasebems | 0:c54d59d6fb78 | 115 | |
hasebems | 0:c54d59d6fb78 | 116 | Tone_sendTone(); |
hasebems | 0:c54d59d6fb78 | 117 | } |
hasebems | 0:c54d59d6fb78 | 118 | void Tone_setToneExc( unsigned char data, int excNum ) |
hasebems | 0:c54d59d6fb78 | 119 | { |
hasebems | 0:c54d59d6fb78 | 120 | if ( _toneSetState == WAIT_DATA ){ |
hasebems | 0:c54d59d6fb78 | 121 | if (( excNum == 1 ) && ( data == tExcCheck[0] )){ |
hasebems | 0:c54d59d6fb78 | 122 | _toneSetState = DURING_SETTING; |
hasebems | 0:c54d59d6fb78 | 123 | } |
hasebems | 0:c54d59d6fb78 | 124 | } |
hasebems | 0:c54d59d6fb78 | 125 | else if ( _toneSetState == DURING_SETTING ){ |
hasebems | 0:c54d59d6fb78 | 126 | if ( excNum-1 < MAX_EXCLUSIVE_HEADER_SIZE ){ |
hasebems | 0:c54d59d6fb78 | 127 | if ( data != tExcCheck[excNum-1] ){ _toneSetState = WAIT_DATA; } |
hasebems | 0:c54d59d6fb78 | 128 | } |
hasebems | 0:c54d59d6fb78 | 129 | else if ( excNum == 6 ){ |
hasebems | 0:c54d59d6fb78 | 130 | if ( data < MUTABLE_TONE_MAX ){ _tprmIndex = data; } |
hasebems | 0:c54d59d6fb78 | 131 | else { _toneSetState = WAIT_DATA; } |
hasebems | 0:c54d59d6fb78 | 132 | } |
hasebems | 0:c54d59d6fb78 | 133 | else if ( excNum == 7 ){ |
hasebems | 0:c54d59d6fb78 | 134 | _userTone[_tprmIndex].voiceCommon = data; |
hasebems | 0:c54d59d6fb78 | 135 | } |
hasebems | 0:c54d59d6fb78 | 136 | else if ( excNum < 48 ){ |
hasebems | 0:c54d59d6fb78 | 137 | _userTone[_tprmIndex].opPrm[(excNum-8)/MAX_OPERATOR_PRM][(excNum-8)%MAX_OPERATOR_PRM] = data; |
hasebems | 0:c54d59d6fb78 | 138 | } |
hasebems | 0:c54d59d6fb78 | 139 | else { _toneSetState = WAIT_DATA; } |
hasebems | 0:c54d59d6fb78 | 140 | } |
hasebems | 0:c54d59d6fb78 | 141 | } |
hasebems | 0:c54d59d6fb78 | 142 | void Tone_sendTone( void ) |
hasebems | 0:c54d59d6fb78 | 143 | { |
hasebems | 0:c54d59d6fb78 | 144 | int i,j; |
hasebems | 0:c54d59d6fb78 | 145 | unsigned char regImage[MAX_TONE_PRM_SZ*AVAILABLE_TONE_NUMBER + 1 + 4]; // 485 |
hasebems | 0:c54d59d6fb78 | 146 | |
hasebems | 0:c54d59d6fb78 | 147 | // top |
hasebems | 0:c54d59d6fb78 | 148 | regImage[0] = 0x80 + AVAILABLE_TONE_NUMBER; |
hasebems | 0:c54d59d6fb78 | 149 | |
hasebems | 0:c54d59d6fb78 | 150 | for ( i=0; i<AVAILABLE_TONE_NUMBER; i++ ){ |
hasebems | 0:c54d59d6fb78 | 151 | unsigned char* riPtr = ®Image[MAX_TONE_PRM_SZ*i + 1]; |
hasebems | 0:c54d59d6fb78 | 152 | |
hasebems | 0:c54d59d6fb78 | 153 | ToneData* td; |
hasebems | 0:c54d59d6fb78 | 154 | if ( i < IMMUTABLE_TONE_MAX ){ |
hasebems | 0:c54d59d6fb78 | 155 | td = (ToneData*)&(TPRM[i]); |
hasebems | 0:c54d59d6fb78 | 156 | } |
hasebems | 0:c54d59d6fb78 | 157 | else { |
hasebems | 0:c54d59d6fb78 | 158 | td = (ToneData*)&(_userTone[i-IMMUTABLE_TONE_MAX]); |
hasebems | 0:c54d59d6fb78 | 159 | } |
hasebems | 0:c54d59d6fb78 | 160 | |
hasebems | 0:c54d59d6fb78 | 161 | riPtr[0] = (td->voiceCommon & 0x60)>>5; |
hasebems | 0:c54d59d6fb78 | 162 | riPtr[1] = ((td->voiceCommon & 0x18)<<3) | (td->voiceCommon & 0x07); |
hasebems | 0:c54d59d6fb78 | 163 | |
hasebems | 0:c54d59d6fb78 | 164 | for ( j=0; j<MAX_FM_OPERATOR; j++ ){ |
hasebems | 0:c54d59d6fb78 | 165 | 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); |
hasebems | 0:c54d59d6fb78 | 166 | riPtr[MAX_ELEMENT_PRM+OPERATOR_PRM_REG_SZ*j+1] = (td->opPrm[j][4] << 4) | td->opPrm[j][2]; |
hasebems | 0:c54d59d6fb78 | 167 | riPtr[MAX_ELEMENT_PRM+OPERATOR_PRM_REG_SZ*j+2] = (td->opPrm[j][1] << 4) | td->opPrm[j][5]; |
hasebems | 0:c54d59d6fb78 | 168 | riPtr[MAX_ELEMENT_PRM+OPERATOR_PRM_REG_SZ*j+3] = (td->opPrm[j][6] << 2) | (td->opPrm[j][0] & 0x03); |
hasebems | 0:c54d59d6fb78 | 169 | riPtr[MAX_ELEMENT_PRM+OPERATOR_PRM_REG_SZ*j+4] = td->opPrm[j][7]; |
hasebems | 0:c54d59d6fb78 | 170 | riPtr[MAX_ELEMENT_PRM+OPERATOR_PRM_REG_SZ*j+5] = ((td->opPrm[j][8] & 0x0f) << 4) | ((td->opPrm[j][8] & 0xf0) >> 4); |
hasebems | 0:c54d59d6fb78 | 171 | riPtr[MAX_ELEMENT_PRM+OPERATOR_PRM_REG_SZ*j+6] = (td->opPrm[j][9] << 3) | ((td->opPrm[j][0] & 0x70) >> 4); |
hasebems | 0:c54d59d6fb78 | 172 | } |
hasebems | 0:c54d59d6fb78 | 173 | } |
hasebems | 0:c54d59d6fb78 | 174 | |
hasebems | 0:c54d59d6fb78 | 175 | // end |
hasebems | 0:c54d59d6fb78 | 176 | regImage[MAX_TONE_PRM_SZ*AVAILABLE_TONE_NUMBER + 1] = 0x80; |
hasebems | 0:c54d59d6fb78 | 177 | regImage[MAX_TONE_PRM_SZ*AVAILABLE_TONE_NUMBER + 2] = 0x03; |
hasebems | 0:c54d59d6fb78 | 178 | regImage[MAX_TONE_PRM_SZ*AVAILABLE_TONE_NUMBER + 3] = 0x81; |
hasebems | 0:c54d59d6fb78 | 179 | regImage[MAX_TONE_PRM_SZ*AVAILABLE_TONE_NUMBER + 4] = 0x80; |
hasebems | 0:c54d59d6fb78 | 180 | |
hasebems | 0:c54d59d6fb78 | 181 | // Soft Reset |
hasebems | 0:c54d59d6fb78 | 182 | // writeSingle(26,0xa3); |
hasebems | 0:c54d59d6fb78 | 183 | // writeSingle(26,0x00); |
hasebems | 0:c54d59d6fb78 | 184 | writeSingle(8,0xf6); |
hasebems | 0:c54d59d6fb78 | 185 | delayMs(1); |
hasebems | 0:c54d59d6fb78 | 186 | writeSingle(8,0x00); |
hasebems | 0:c54d59d6fb78 | 187 | |
hasebems | 0:c54d59d6fb78 | 188 | writeBurst( 7, regImage, MAX_TONE_PRM_SZ*AVAILABLE_TONE_NUMBER + 5 ); |
hasebems | 0:c54d59d6fb78 | 189 | } |