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

Dependencies:   microbit

Committer:
hasebems
Date:
Fri Jan 05 22:58:49 2018 +0000
Revision:
0:c54d59d6fb78
???????????????

Who changed what in which revision?

UserRevisionLine numberNew contents of line
hasebems 0:c54d59d6fb78 1 // fmvoice.c
hasebems 0:c54d59d6fb78 2 #include "fmtype.h"
hasebems 0:c54d59d6fb78 3 #include "fmvoice.h"
hasebems 0:c54d59d6fb78 4 #include "fmtone.h"
hasebems 0:c54d59d6fb78 5 #include "fmnote.h"
hasebems 0:c54d59d6fb78 6 #include "fmsd1.h"
hasebems 0:c54d59d6fb78 7 #include "fmpart.h"
hasebems 0:c54d59d6fb78 8
hasebems 0:c54d59d6fb78 9 // setter
hasebems 0:c54d59d6fb78 10 void Fmvoice_setVoiceNum( Fmvoice* _this, unsigned char vn ){ _this->_vnum = vn; }
hasebems 0:c54d59d6fb78 11 void Fmvoice_setNextVc( Fmvoice* _this, Fmvoice* vc ){ _this->_nextVc = vc; }
hasebems 0:c54d59d6fb78 12
hasebems 0:c54d59d6fb78 13 // getter
hasebems 0:c54d59d6fb78 14 unsigned char Fmvoice_vnum( Fmvoice* _this ){ return _this->_vnum; }
hasebems 0:c54d59d6fb78 15 bool Fmvoice_isKeyon( Fmvoice* _this ){ return _this->_keyon;}
hasebems 0:c54d59d6fb78 16 Fmvoice* Fmvoice_nextVc( Fmvoice* _this ){ return _this->_nextVc; }
hasebems 0:c54d59d6fb78 17
hasebems 0:c54d59d6fb78 18 void Fmvoice_init( Fmvoice* _this )
hasebems 0:c54d59d6fb78 19 {
hasebems 0:c54d59d6fb78 20 _this->_keyon = (false);
hasebems 0:c54d59d6fb78 21 _this->_nextVc = FMNULL;
hasebems 0:c54d59d6fb78 22 }
hasebems 0:c54d59d6fb78 23 void Fmvoice_keyon( Fmvoice* _this, void* nt, void* pt, void* tn, unsigned char note, unsigned char vel )
hasebems 0:c54d59d6fb78 24 {
hasebems 0:c54d59d6fb78 25 Part* ptp = (Part*)pt;
hasebems 0:c54d59d6fb78 26
hasebems 0:c54d59d6fb78 27 _this->_parent = nt;
hasebems 0:c54d59d6fb78 28 _this->_keyon = true;
hasebems 0:c54d59d6fb78 29 _this->_nextVc = FMNULL;
hasebems 0:c54d59d6fb78 30
hasebems 0:c54d59d6fb78 31 // set voice number
hasebems 0:c54d59d6fb78 32 writeSingle( 11, _this->_vnum );
hasebems 0:c54d59d6fb78 33
hasebems 0:c54d59d6fb78 34 // Damp
hasebems 0:c54d59d6fb78 35 writeSingle( REG_TOP_ADRS+REG_CTRL, 0x30 );
hasebems 0:c54d59d6fb78 36
hasebems 0:c54d59d6fb78 37 // FNUM,BLOCK
hasebems 0:c54d59d6fb78 38 Fmvoice_setBasicPit( _this, note );
hasebems 0:c54d59d6fb78 39
hasebems 0:c54d59d6fb78 40 // Vol
hasebems 0:c54d59d6fb78 41 writeSingle( REG_TOP_ADRS+REG_VOL, vel&0xfc );
hasebems 0:c54d59d6fb78 42
hasebems 0:c54d59d6fb78 43 // ChVol
hasebems 0:c54d59d6fb78 44 writeSingle( REG_TOP_ADRS+REG_CH_VOL, 0x71 );
hasebems 0:c54d59d6fb78 45
hasebems 0:c54d59d6fb78 46 // XVB
hasebems 0:c54d59d6fb78 47 Fmvoice_chgVibDpt(_this, Part_cc1(ptp));
hasebems 0:c54d59d6fb78 48
hasebems 0:c54d59d6fb78 49 // INT, FRAC
hasebems 0:c54d59d6fb78 50 Fmvoice_chgPit(_this, Part_pb(ptp));
hasebems 0:c54d59d6fb78 51
hasebems 0:c54d59d6fb78 52 // KeyOn, ToneNum
hasebems 0:c54d59d6fb78 53 writeSingle( REG_TOP_ADRS+REG_CTRL, 0x40 + Part_toneNumber(ptp) );
hasebems 0:c54d59d6fb78 54 }
hasebems 0:c54d59d6fb78 55 void Fmvoice_keyoff( Fmvoice* _this )
hasebems 0:c54d59d6fb78 56 {
hasebems 0:c54d59d6fb78 57 _this->_keyon = false;
hasebems 0:c54d59d6fb78 58 writeSingle( 11, _this->_vnum );
hasebems 0:c54d59d6fb78 59 writeSingle( REG_TOP_ADRS+REG_CTRL, 0 );
hasebems 0:c54d59d6fb78 60 }
hasebems 0:c54d59d6fb78 61 void Fmvoice_release( Fmvoice* _this )
hasebems 0:c54d59d6fb78 62 {
hasebems 0:c54d59d6fb78 63 _this->_keyon = false;
hasebems 0:c54d59d6fb78 64 if ( _this->_parent != FMNULL ){
hasebems 0:c54d59d6fb78 65 Note* nt = (Note*)_this->_parent;
hasebems 0:c54d59d6fb78 66 Note_releaseVc(nt,_this);
hasebems 0:c54d59d6fb78 67 }
hasebems 0:c54d59d6fb78 68 _this->_nextVc = FMNULL;
hasebems 0:c54d59d6fb78 69
hasebems 0:c54d59d6fb78 70 writeSingle( 11, _this->_vnum );
hasebems 0:c54d59d6fb78 71 writeSingle( REG_TOP_ADRS+REG_CTRL, 0x30 );
hasebems 0:c54d59d6fb78 72 }
hasebems 0:c54d59d6fb78 73 void Fmvoice_chgPit( Fmvoice* _this, unsigned short pb )
hasebems 0:c54d59d6fb78 74 {
hasebems 0:c54d59d6fb78 75 static const unsigned short tPitTbl[256] = {
hasebems 0:c54d59d6fb78 76 256,257,259,260,262,263,264,266,267,269,270,272,273,275,276,278,
hasebems 0:c54d59d6fb78 77 279,281,282,284,285,287,288,290,292,293,295,296,298,300,301,303,
hasebems 0:c54d59d6fb78 78 304,306,308,309,311,313,314,316,318,320,321,323,325,327,328,330,
hasebems 0:c54d59d6fb78 79 332,334,336,337,339,341,343,345,347,349,350,352,354,356,358,360,
hasebems 0:c54d59d6fb78 80 362,364,366,368,370,372,374,376,378,380,382,384,386,388,391,393,
hasebems 0:c54d59d6fb78 81 395,397,399,401,403,406,408,410,412,415,417,419,421,424,426,428,
hasebems 0:c54d59d6fb78 82 431,433,435,438,440,442,445,447,450,452,454,457,459,462,464,467,
hasebems 0:c54d59d6fb78 83 470,472,475,477,480,482,485,488,490,493,496,498,501,504,506,509,
hasebems 0:c54d59d6fb78 84 512,515,518,520,523,526,529,532,535,538,540,543,546,549,552,555,
hasebems 0:c54d59d6fb78 85 558,561,564,567,571,574,577,580,583,586,589,593,596,599,602,606,
hasebems 0:c54d59d6fb78 86 609,612,616,619,622,626,629,632,636,639,643,646,650,653,657,660,
hasebems 0:c54d59d6fb78 87 664,668,671,675,679,682,686,690,693,697,701,705,709,712,716,720,
hasebems 0:c54d59d6fb78 88 724,728,732,736,740,744,748,752,756,760,764,769,773,777,781,785,
hasebems 0:c54d59d6fb78 89 790,794,798,803,807,811,816,820,825,829,834,838,843,847,852,856,
hasebems 0:c54d59d6fb78 90 861,866,870,875,880,885,890,894,899,904,909,914,919,924,929,934,
hasebems 0:c54d59d6fb78 91 939,944,949,954,960,965,970,975,981,986,991,997,1002,1007,1013,1023 };
hasebems 0:c54d59d6fb78 92
hasebems 0:c54d59d6fb78 93 unsigned char reg[2];
hasebems 0:c54d59d6fb78 94 unsigned char pit = pb/64;
hasebems 0:c54d59d6fb78 95 reg[1] = (unsigned char)((tPitTbl[pit]<<1) & 0x007e);
hasebems 0:c54d59d6fb78 96 reg[0] = (unsigned char)(((tPitTbl[pit]<<2) & 0x1f00)>>8);
hasebems 0:c54d59d6fb78 97
hasebems 0:c54d59d6fb78 98 writeSingle( 11, _this->_vnum );
hasebems 0:c54d59d6fb78 99 writeSingle( REG_TOP_ADRS+REG_INT, reg[0] );
hasebems 0:c54d59d6fb78 100 writeSingle( REG_TOP_ADRS+REG_FRC, reg[1] );
hasebems 0:c54d59d6fb78 101 }
hasebems 0:c54d59d6fb78 102 void Fmvoice_chgVibDpt( Fmvoice* _this, unsigned char vibDpt )
hasebems 0:c54d59d6fb78 103 {
hasebems 0:c54d59d6fb78 104 vibDpt = vibDpt >>4;
hasebems 0:c54d59d6fb78 105 if ( vibDpt == 0 ){ vibDpt = 1;}
hasebems 0:c54d59d6fb78 106 writeSingle( 11, _this->_vnum );
hasebems 0:c54d59d6fb78 107 writeSingle( REG_TOP_ADRS+REG_XVB, vibDpt );
hasebems 0:c54d59d6fb78 108 }
hasebems 0:c54d59d6fb78 109 void Fmvoice_setBasicPit( Fmvoice* _this, unsigned char note )
hasebems 0:c54d59d6fb78 110 {
hasebems 0:c54d59d6fb78 111 static const unsigned short tFreq[240] = {
hasebems 0:c54d59d6fb78 112 347,348,349,350,351,352,353,354,355,356, 357,358,359,360,361,362,363,365,366,367,
hasebems 0:c54d59d6fb78 113 368,369,370,371,372,373,374,375,376,377, 378,380,381,382,383,384,385,386,387,388,
hasebems 0:c54d59d6fb78 114 390,391,392,393,394,395,396,397,399,400, 401,402,403,404,406,407,408,409,410,412,
hasebems 0:c54d59d6fb78 115 413,414,415,416,417,419,420,421,422,424, 425,426,427,428,430,431,432,433,435,436,
hasebems 0:c54d59d6fb78 116 437,439,440,441,442,444,445,446,447,449, 450,451,453,454,455,457,458,459,461,462,
hasebems 0:c54d59d6fb78 117 463,465,466,467,469,470,471,473,474,475, 477,478,480,481,482,484,485,487,488,489,
hasebems 0:c54d59d6fb78 118 491,492,494,495,496,498,499,501,502,504, 505,507,508,510,511,513,514,515,517,518,
hasebems 0:c54d59d6fb78 119 520,521,523,524,526,528,529,531,532,534, 535,537,538,540,541,543,545,546,548,549,
hasebems 0:c54d59d6fb78 120 551,552,554,556,557,559,561,562,564,565, 567,569,570,572,574,575,577,579,580,582,
hasebems 0:c54d59d6fb78 121 584,585,587,589,590,592,594,596,597,599, 601,602,604,606,608,609,611,613,615,617,
hasebems 0:c54d59d6fb78 122 618,620,622,624,626,627,629,631,633,635, 636,638,640,642,644,646,648,649,651,653,
hasebems 0:c54d59d6fb78 123 655,657,659,661,663,665,667,668,670,672, 674,676,678,680,682,684,686,688,690,692};
hasebems 0:c54d59d6fb78 124
hasebems 0:c54d59d6fb78 125 signed short realNote = note;
hasebems 0:c54d59d6fb78 126 while ( realNote > 128 ){ realNote -= 12;}
hasebems 0:c54d59d6fb78 127 while ( realNote < 0 ){ realNote += 12;}
hasebems 0:c54d59d6fb78 128
hasebems 0:c54d59d6fb78 129 int tblIndex = (realNote % 12) * 20;
hasebems 0:c54d59d6fb78 130
hasebems 0:c54d59d6fb78 131 unsigned char reg[2];
hasebems 0:c54d59d6fb78 132 unsigned short fr = tFreq[tblIndex];
hasebems 0:c54d59d6fb78 133 unsigned char oct = realNote/12 - 1;
hasebems 0:c54d59d6fb78 134 reg[0] = (unsigned char)(((fr & 0x0380)>>4) | oct);
hasebems 0:c54d59d6fb78 135 reg[1] = (unsigned char)(fr & 0x007f);
hasebems 0:c54d59d6fb78 136
hasebems 0:c54d59d6fb78 137 writeSingle( 11, _this->_vnum );
hasebems 0:c54d59d6fb78 138 writeSingle( REG_TOP_ADRS+REG_BLK, reg[0] );
hasebems 0:c54d59d6fb78 139 writeSingle( REG_TOP_ADRS+REG_FNUM, reg[1] );
hasebems 0:c54d59d6fb78 140 }