├── LICENSE ├── README.md ├── manual ├── algo.png ├── eq.png ├── fbd_spec1.md ├── fbd_spec2.md ├── fbd_spec3.md ├── sd1-pitch.xlsx ├── spi_burst.png ├── spi_read.png ├── spi_single.png └── ws.png ├── sample1 └── ymf825board_sample1 │ └── ymf825board_sample1.ino ├── sample2 ├── arduino │ ├── fmboard.h │ ├── fmsd1_ino.cpp │ └── ymf825board_sample2.ino ├── common │ ├── fmasgn.c │ ├── fmasgn.h │ ├── fmif.c │ ├── fmif.h │ ├── fmnote.c │ ├── fmnote.h │ ├── fmpart.c │ ├── fmpart.h │ ├── fmsd1.h │ ├── fmtone.c │ ├── fmtone.h │ ├── fmtype.h │ ├── fmvoice.c │ └── fmvoice.h ├── raspi │ ├── fmboard.h │ └── fmsd1_raspi.c └── readme.md └── tonedata ├── sysexspec.md └── tonedata.txt /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Yamaha Corporation 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # YMF825Board 2 | 3 | ## Directory 4 | ### manual 5 | IF Specification of YMF825Board 6 | 7 | ### sample1 8 | Sample Program that generates "Do-Re-Mi-Fa-So" automatically on Arduino Uno 9 | 10 | ### sample2 11 | Software Module that makes YMF825 a MIDI tone generator written in C Language 12 | 13 | ### tonedata 14 | Tone data of YMF825 15 | 16 | ## copyright & license 17 | **Copyright (c) 2017 Yamaha Corporation released under the MIT license.** 18 | This software is released under the MIT License, see LICENSE. 19 | 20 | 21 | 22 | ## ディレクトリ 23 | ### manual 24 | YMF825Board のIF仕様 25 | 26 | ### sample1 27 | Arduinoで「ドレミファソ」が自動で発音するサンプルプログラム 28 | 29 | ### sample2 30 | YMF825をMIDI音源化するC言語のソフトウェアモジュール 31 | 32 | ### tonedata 33 | YMF825の音色データ 34 | 35 | ## 著作権とライセンス 36 | **Copyright (c) 2017 Yamaha Corporation released under the MIT license.** 37 | このソフトウェアは、MITライセンスのもとで公開しています。詳しくは LICENSE をご参照ください。 38 | 39 | -------------------------------------------------------------------------------- /manual/algo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danielrfry/ymf825board/aa526f3dae0c161b562515ecd2e59efaeaa1d062/manual/algo.png -------------------------------------------------------------------------------- /manual/eq.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danielrfry/ymf825board/aa526f3dae0c161b562515ecd2e59efaeaa1d062/manual/eq.png -------------------------------------------------------------------------------- /manual/fbd_spec1.md: -------------------------------------------------------------------------------- 1 | # YMF825(SD-1) IF specification 2 | 3 | ## Caution 4 | 5 | Although this manual is created based on the SD-1 specifications, only the information necessary for YMF825Board is described. Therefore, please understand beforehand that it is not a complete specification of SD-1. 6 | In addition, please understand that we will not guarantee any results by using SD-1 based on the contents posted in this manual. 7 | 8 | 9 | ## Features 10 | 11 | + 16-voice polyphonic FM synthesizer 12 | + 29 on-chip operator-waveforms and 8 algorithms offers a whole variety of sound 13 | + Synchronous serial data link for host controller interface 14 | + Integrated loudspeaker driver (Also supports external amplifier connection) 15 | + Integrated 3-band equalizer 16 | + Integrated 16-bit monaural DAC 17 | 18 | ## Interface Register 19 | 20 | ### System Setting 21 | 22 | + I_ADR#0-2, 4, 29 can be accessed even when the ALRST is "1". 23 | As might be expected, other registers can be accessed only when the ALRST is "0". 24 | 25 | 26 | | I_ADR | Name | W/R | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 | Reset Value | 27 | |-|-|-|-|-|-|-|-|-|-|-|-| 28 | |#0| Clock Enable |W/R|"0"|"0"|"0"|"0"|"0"|"0"|"0"|CLKE|00H | 29 | |#1|Reset|W/R|ALRST|"0"|"0"|"0"|"0"|"0"|"0"|"0"|80H| 30 | |#2|Analog Block Power-down control|W/R|"0"|"0"|"0"|"0"|AP3|AP2|AP1|AP0| 0FH| 31 | |#3|Speaker Amplifier Gain Setting|W/R|"0"|"0"|"0"|"0"|"0"|"0"|GAIN1|GAIN0|01H| 32 | |#4|Hardware ID|R|"0"|"0"|"0"|"0"|"0"|"0"|"0"|"1"|01H| 33 | |#5|Interrupt|W/R R|"0"|"0"|"0"|EMP_DW|"0"|FIFO|"0"|SQ_STP|00H| 34 | |#6||W/R|"0"|EIRQ|"0"|EEMP_DW|"0"|EFIFO|"0"|ESQ_STP|00H| 35 | |#7|Contents Data Write Port|W|DT7|DT6|DT5|DT4|DT3|DT2|DT1|DT0|00H| 36 | |#8|Sequencer Setting|W/R|AllKeyOff|AllMute|AllEGRst|R_FIFOR|REP_SQ|R_SEQ| R_FIFO|START|00H| 37 | |#9||W/R|SEQ_Vol4|SEQ_Vol3|SEQ_Vol2|SEQ_Vol1|SEQ_Vol0|DIR_SV|"0"|SIZE8|00H| 38 | |#10||W/R|SIZE7|SIZE6|SIZE5|SIZE4|SIZE3|SIZE2|SIZE1|SIZE0|00H| 39 | |#11|Synthesizer Setting|W/R|"0"|"0"|"0"|"0"|CRGD_VNO3|CRGD_VNO2|CRGD_VNO1|CRGD_VNO0|00H| 40 | |#12||W|"0"|VoVol4|VoVol3|VoVol2|VoVol1|VoVol0|"0"|"0"|60H| 41 | |#13||W|"0"|"0"|FNUM9|FNUM8|FNUM7|BLOCK2|BLOCK1|BLOCK0|00H| 42 | |#14||W|"0"|FNUM6|FNUM5|FNUM4|FNUM3|FNUM2|FNUM1|FNUM0|00H| 43 | |#15||W|"0"|KeyOn|Mute|EG_RST|ToneNum3|ToneNum2|ToneNum1|ToneNum0|00H| 44 | |#16||W|"0"|ChVol4|ChVol3|ChVol2|ChVol1|ChVol0|"0"|DIR_CV|60H| 45 | |#17||W|"0"|"0"|"0"|"0"|"0"|XVB2|XVB1|XVB0|00H| 46 | |#18||W|"0"|"0"|"0"|INT1|INT0|FRAC8|FRAC7|FRAC6|08H| 47 | |#19||W|"0"|FRAC5|FRAC4|FRAC3|FRAC2|FRAC1|FRAC0|"0"|00H| 48 | |#20||W|"0"|"0"|"0"|"0"|"0"|"0"|"0"|DIR_MT|00H| 49 | |#21|Control Register Read Port|W/R|RDADR_CRG7|RDADR_CRG6|RDADR_CRG5|RDADR_CRG4|RDADR_CRG3|RDADR_CRG2|RDADR_CRG1|RDADR_CRG0|00H| 50 | |#22||R|"0"|RDDATA_CRG6|RDDATA_CRG5|RDDATA_CRG4|RDDATA_CRG3|RDDATA_CRG2|RDDATA_CRG1|RDDATA_CRG0|-| 51 | |#23|Sequencer Time unit Setting|W/R|"0"|MS_S13|MS_S12|MS_S11|MS_S10|MS_S9|MS_S8|MS_S7|00H| 52 | |#24||W/R|"0"|MS_S6|MS_S5|MS_S4|MS_S3|MS_S2|MS_S1|MS_S0|00H| 53 | |#25|Master Volume|W/R|MASTER_VOL5|MASTER_VOL4|MASTER_VOL3|MASTER_VOL2|MASTER_VOL1|MASTER_VOL0|"0"|"0"|00H| 54 | |#26|Soft Reset|W/R|SFTRST7|SFTRST6|SFTRST5|SFTRST4|SFTRST3|SFTRST2|SFTRST1|SFTRST0|00H| 55 | |#27|Sequencer Delay, Recovery Function Setting, Volume Interpolation Setting|W/R|"0"|DADJT|MUTE_ITIME1|MUTE_ITIME0|CHVOL_ITIME1|CHVOL_ITIME0|MVOL_ITIME1|MVOL_ITIME0|00H| 56 | |#28|LFO Reset|W/R|"0"|"0"|"0"|"0"|"0"|"0"|"0"|LFO_RST|00H| 57 | |#29|Power Rail Selection|W/R|"0"|"0"|"0"|"0"|"0"|"0"|"0"|DRV_SEL|00H| 58 | |#30|Reserved||||||||||| 59 | |#31|Reserved||||||||||| 60 | 61 | Note 62 | + Before you write I_ADR#12-19 of Synthesizer Setting, you first have to write channel number to CRGD_VNO[3:0] (I_ADR#11). 63 | 64 | 65 | ### EQ Coeffcient Setting 66 | 67 | |I_ADR|Name|W/R|D7-D0|Reset Value| 68 | |-|-|-|-|-| 69 | |#32|EQ BAND0 coefficient Write Port|W|W_CEQ0[7:0]|00H| 70 | |#33|EQ BAND1 coefficient Write Port|W|W_CEQ1[7:0]|00H| 71 | |#34|EQ BAND2 coefficient Write Port|W|W_CEQ2[7:0]|00H| 72 | |#35|Equalizer Coefficient Read Ports|R|CEQ00[23:16]|10H| 73 | |#36||R|CEQ00[15:8]|00H| 74 | |#37||R|CEQ00[7:0]|00H| 75 | |#38||R|CEQ01[23:16]|00H| 76 | |#39||R|CEQ01[15:8]|00H| 77 | |#40||R|CEQ01[7:0]|00H| 78 | |#41||R|CEQ02[23:16]|00H| 79 | |#42||R|CEQ02[15:8]|00H| 80 | |#43||R|CEQ02[7:0]|00H| 81 | |#44||R|CEQ03[23:16]|00H| 82 | |#45||R|CEQ03[15:8]|00H| 83 | |#46||R|CEQ03[7:0]|00H| 84 | |#47||R|CEQ04[23:16]|00H| 85 | |#48||R|CEQ04[15:8]|00H| 86 | |#49||R|CEQ04[7:0]|00H| 87 | |#50||R|CEQ10[23:16]|10H| 88 | |#51||R|CEQ10[15:8]|00H| 89 | |#52||R|CEQ10[7:0]|00H| 90 | |#53||R|CEQ11[23:16]|00H| 91 | |#54||R|CEQ11[15:8]|00H| 92 | |#55||R|CEQ11[7:0]|00H| 93 | |#56||R|CEQ12[23:16]|00H| 94 | |#57||R|CEQ12[15:8]|00H| 95 | |#58||R|CEQ12[7:0]|00H| 96 | |#59||R|CEQ13[23:16]|00H| 97 | |#60||R|CEQ13[15:8]|00H| 98 | |#61||R|CEQ13[7:0]|00H| 99 | |#62||R|CEQ14[23:16]|00H| 100 | |#63||R|CEQ14[15:8]|00H| 101 | |#64||R|CEQ14[7:0]|00H| 102 | |#65||R|CEQ20[23:16]|10H| 103 | |#66||R|CEQ20[15:8]|00H| 104 | |#67||R|CEQ20[7:0]|00H| 105 | |#68||R|CEQ21[23:16]|00H| 106 | |#69||R|CEQ21[15:8]|00H| 107 | |#70||R|CEQ21[7:0]|00H| 108 | |#71||R|CEQ22[23:16]|00H| 109 | |#72||R|CEQ22[15:8]|00H| 110 | |#73||R|CEQ22[7:0]|00H| 111 | |#74||R|CEQ23[23:16]|00H| 112 | |#75||R|CEQ23[15:8]|00H| 113 | |#76||R|CEQ23[7:0]|00H| 114 | |#77||R|CEQ24[23:16]|00H| 115 | |#78||R|CEQ24[15:8]|00H| 116 | |#79||R|CEQ24[7:0]|00H| 117 | 118 | ### Software Communication Check 119 | 120 | | I_ADR | Name | W/R | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 | Reset Value | 121 | |-|-|-|-|-|-|-|-|-|-|-|-| 122 | |#80|Software test communication|W/R|COMM7|COMM6|COMM5|COMM4|COMM3|COMM2|COMM1|COMM0|00H| 123 | 124 | 125 | ## Read/Write Accesses to Interface Registers 126 | 127 | ### SPI Specification 128 | + MSB first 129 | + Mode 0 130 | + max 10MHz 131 | 132 | ### Single Write 133 | 134 | 2 bytes (16 bits) is needed for one write access: 1-byte write command and 1-byte write data. 135 | Be sure to access the register in two bytes (16 bits). 136 | The /SS pin should be set to "H" for each two-byte write access. 137 | 138 | ![Single Write](spi_single.png) 139 | 140 | ### Burst Write 141 | 142 | In the burst write operation, data can be written into the same interface register address in succession. 143 | Enter multiple data consecutively for one write command like this: [write command + data + data +...]. 144 | This device interprets the /SS pin being "H" as the end of the write access; therefore, be sure to set this pin to "H" after the 145 | burst write operation. 146 | Each data should be one byte. If the /SS pin is set to "H" at less than 1 byte, such as 6 bits, unusual operation may occur 147 | because of an illegal write operation. 148 | 149 | ![Burst Write](spi_burst.png) 150 | 151 | ### Read Access 152 | 153 | Setting the bit WR (command) to "1" indicates a read access command. 154 | The read data is transmitted in synchronization with the falling edges of the SCK from the 9th clock. 155 | The data is in MSB first format (D7→D0). 156 | The following shows the details of the SO pin: 157 | + During the latter 8 clock cycles, the read data (D[7:0]) is transmitted in MSB first format. 158 | + The SO pin goes to a high-impedance state (Hi-Z) whenever the data is not being read. 159 | 160 | ![Single Read](spi_read.png) 161 | 162 | 163 | ## Tone Parameter Memory Map 164 | 165 | |T_ADR|Name|D7|D6|D5|D4|D3|D2|D1|D0| 166 | |-|-|-|-|-|-|-|-|-|-| 167 | |#0+30x[tn]|Entire Tone Setting|"0"|"0"|"0"|"0"|"0"|"0"|BO1|BO0| 168 | |#1+30x[tn]||LFO1|LFO0|"0"|"0"|"0"|ALG2|ALG1|ALG0| 169 | |#2+30x[tn]|Operator1 Setting|SR3|SR2|SR1|SR0|XOF|"0"|"0"|KSR| 170 | |#3+30x[tn]||RR3|RR2|RR1|RR0|DR3|DR2|DR1|DR0| 171 | |#4+30x[tn]||AR3|AR2|AR1|AR0|SL3|SL2|SL1|SL0| 172 | |#5+30x[tn]||TL5|TL4|TL3|TL2|TL1|TL0|KSL1|KSL0| 173 | |#6+30x[tn]||"0"|DAM1|DAM0|EAM|"0"|DVB1|DVB0|EVB| 174 | |#7+30x[tn]||MULTI3|MULTI2|MULTI1|MULTI0|"0"|DT2|DT1|DT0| 175 | |#8+30x[tn]||WS4|WS3|WS2|WS1|WS0|FB2|FB1|FB0| 176 | |#9+30x[tn]|Operator2 Setting|SR3|SR2|SR1|SR0|XOF|"0"|"0"|KSR| 177 | |#10+30x[tn]||RR3|RR2|RR1|RR0|DR3|DR2|DR1|DR0| 178 | |#11+30x[tn]||AR3|AR2|AR1|AR0|SL3|SL2|SL1|SL0| 179 | |#12+30x[tn]||TL5|TL4|TL3|TL2|TL1|TL0|KSL1|KSL0| 180 | |#13+30x[tn]||"0"|DAM1|DAM0|EAM|"0"|DVB1|DVB0|EVB| 181 | |#14+30x[tn]||MULTI3|MULTI2|MULTI1|MULTI0|"0"|DT2|DT1|DT0| 182 | |#15+30x[tn]||WS4|WS3|WS2|WS1|WS0|"0"|"0"|"0"| 183 | |#16+30x[tn]|Operator3 Setting|SR3|SR2|SR1|SR0|XOF|"0"|"0"|KSR| 184 | |#17+30x[tn]||RR3|RR2|RR1|RR0|DR3|DR2|DR1|DR0| 185 | |#18+30x[tn]||AR3|AR2|AR1|AR0|SL3|SL2|SL1|SL0| 186 | |#19+30x[tn]||TL5|TL4|TL3|TL2|TL1|TL0|KSL1|KSL0| 187 | |#20+30x[tn]||"0"|DAM1|DAM0|EAM|"0"|DVB1|DVB0|EVB| 188 | |#21+30x[tn]||MULTI3|MULTI2|MULTI1|MULTI0|"0"|DT2|DT1|DT0| 189 | |#22+30x[tn]||WS4|WS3|WS2|WS1|WS0|FB2|FB1|FB0| 190 | |#23+30x[tn]|Operator4 Setting|SR3|SR2|SR1|SR0|XOF|"0"|"0"|KSR| 191 | |#24+30x[tn]||RR3|RR2|RR1|RR0|DR3|DR2|DR1|DR0| 192 | |#25+30x[tn]||AR3|AR2|AR1|AR0|SL3|SL2|SL1|SL0| 193 | |#26+30x[tn]||TL5|TL4|TL3|TL2|TL1|TL0|KSL1|KSL0| 194 | |#27+30x[tn]||"0"|DAM1|DAM0|EAM|"0"|DVB1|DVB0|EVB| 195 | |#28+30x[tn]||MULTI3|MULTI2|MULTI1|MULTI0|"0"|DT2|DT1|DT0| 196 | |#29+30x[tn]||WS4|WS3|WS2|WS1|WS0|"0"|"0"|"0"| 197 | 198 | Note 199 | + T_ADR means Tone Setting format of Cotents Format(below). 200 | + tn: Tone Number(0-15) 201 | 202 | 203 | ### Contents Format 204 | 205 | The contents format specifies tone parameters and the sequence of data that can be played back with this device consists of melody contents. 206 | The contents are written into the register (I_ADR#7: CONTENTS_DATA_REG) via the CPU interface. 207 | 208 | #### Data format 209 | 210 | + Header: 1byte(80H + Maximum Tone Number) 211 | + Tone Setting 30 to 480bytes(it depends on the number of the configured tones) 212 | + Sequence Data(any size) 213 | + End(80H,03H,81H,80H) 214 | 215 | #### Tone Setting 216 | 217 | The tone parameters are set by the number of tones set to the Header. 218 | The parameter consists of 30 bytes of data for one tone. 219 | The data are transferred and assigned to the Tone parameter memory from Tone 0 in the order they are written; therefore, parameters of an intermediate Tone number cannot be written first. 220 | For details of the tone parameters, see "Tone Parameter"(fbd_spec3.md). 221 | 222 | ## Initialization Procedure 223 | 224 | 1. Supply the power to the device. 225 | 226 | The power supply should be powered with RST_N pin held "L" when the power-on reset requirements cannot be satisfied. 227 | 228 | 1. Wait for 100us after supply voltages rise 229 | 230 | up to the specified level. 231 | This period of time is the time required for the regulator stabilization. 232 | 233 | 1. Set the RST_N pin to "H". 234 | 235 | The hardware reset state is removed. 236 | No need to set to "H" when this device is used with RST_N pin held "H". 237 | 238 | 1. Set DRV_SEL to "0" when this device is used in single 5-V power supply 239 | configuration. 240 | Set DRV_SEL to "1" when this device is used in dual power supply configuration. 241 | 242 | The power rail is selected. 243 | 244 | 1. Set the AP0 to "0". The VREF is powered. 245 | 246 | 1. Wait until the clock becomes stable. 247 | 248 | The duration of the time required for stable crystal oscillation. 249 | 250 | 1. Set the CLKE to "1". 251 | 252 | Clocks are supplied to the internal circuit. 253 | 254 | 1. Set the ALRST to "0". 255 | 256 | The reset state of the internal circuits is removed. 257 | 258 | 1. Set the SFTRST to "A3H". 259 | 260 | The synthesizer block is initialized. 261 | 262 | 1. Set the SFTRST to "00H". 263 | 264 | 1. Wait for 30ms after the step 10. 265 | 266 | This period of time is the time required for the VREF stabilization and the SFTRST completion. 267 | 268 | 1. Set the AP1 and the AP3 to "0". 269 | 270 | The power-down state of Audio Out is removed. 271 | 272 | 1. Wait for 10us. 273 | 274 | This period of time is the time required for preventing pop noise. Use this time for setting the synthesizer etc. 275 | 276 | 1. Set the AP2 to "0". 277 | 278 | The power-down state of the Audio Out is removed. 279 | 280 | 281 | -------------------------------------------------------------------------------- /manual/fbd_spec2.md: -------------------------------------------------------------------------------- 1 | ## System Setting 2 | 3 | ### CLKE 4 | 5 | |I_ADR|W/R|D7|D6|D5|D4|D3|D2|D1|D0|Reset Value| 6 | |-|-|-|-|-|-|-|-|-|-|-| 7 | |#0|W/R|"0"|"0"|"0"|"0"|"0"|"0"|"0"|CLKE|00H| 8 | 9 | #### Description 10 | The CLKE is the register bit for controlling the internal master clock gating 11 | (ENABLE/DISABLE). 12 | To activate the clock, set the CLKE to "1" with the ALRST set to "1". 13 | See "Initialization Procedure" for details of controlling the clock. 14 | + "0": Clock disabled (reset value) 15 | + "1": Clock enabled 16 | 17 | #### Reset Conditions 18 | 1. When the power supplies are turned on (power-on reset). 19 | 2. When the hardware reset is applied (RST_N= "L"). 20 | 21 | 22 | ### ALRST 23 | 24 | | I_ADR | W/R | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 | Reset Value | 25 | |-|-|-|-|-|-|-|-|-|-|-| 26 | |#1|W/R|ALRST|"0"|"0"|"0"|"0"|"0"|"0"|"0"|80H| 27 | 28 | #### Description 29 | The ALRST is the register used to reset all the interface register. 30 | + "0": Out of the reset state. 31 | + "1": Resets the interface registers. (reset value) 32 | 33 | The following interface registers are reset: 34 | + I_ADR#3, #5 to #28, and from #32 to #79 35 | 36 | The following interface registers including the control registers are not reset with this register 37 | bit: 38 | + I_ADR#0: CLKE 39 | + I_ADR#1: ALRST (this register bit) 40 | + I_ADR#2: AP0-3 41 | + I_ADR#29: DRV_SEL 42 | + I_ADR#80: COMM 43 | 44 | 45 | #### Reset Conditions 46 | 1. When the power supplies are turned on (power-on reset). 47 | 2. When the hardware reset is applied (RST_N= "L"). 48 | 49 | 50 | ### AP0, AP1, AP2, AP3 51 | 52 | | I_ADR | W/R | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 | Reset Value | 53 | |-|-|-|-|-|-|-|-|-|-|-| 54 | |#2|W/R|"0"|"0"|"0"|"0"|AP3|AP2|AP1|AP0|0FH| 55 | 56 | #### Description 57 | The AP0-3 is the power-down control register bits in the analog block. 58 | When setting a register bit to "1" (reset value), its power-down state is established, resulting in lower power consumption. The correspondence between each register bit and its controllable 59 | 60 | blocks is as follows: 61 | + AP0: VREF, IREF 62 | + AP1: SPAMP, SPOUT1 63 | + AP2: SPAMP, SPOUT2 64 | + AP3: DAC 65 | 66 | #### Reset Conditions 67 | 1. When the power supplies are turned on (power-on reset). 68 | 2. When the hardware reset is applied (RST_N= "L"). 69 | 70 | 71 | ### GAIN 72 | 73 | | I_ADR | W/R | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 | Reset Value | 74 | |-|-|-|-|-|-|-|-|-|-|-| 75 | |#3|W/R|"0"|"0"|"0"|"0"|"0"|"0"|GAIN1|GAIN0|01H| 76 | 77 | 78 | #### Description 79 | 80 | The GAIN is the register used for selecting a speaker amplifier gain as shown below: 81 | 82 | |GAIN1|GAIN0|SPAmplifier|Gain| 83 | |-|-|-|-| 84 | |"0"|"0"|SPOUT|gain =5.0dB| 85 | |"0"|"1"|SPOUT|gain =6.5dB (reset value)| 86 | |"1"|"0"|SPOUT|gain =7.0dB| 87 | |"1"|"1"|SPOUT|gain =7.5dB| 88 | 89 | Note) Gain values above assume no-load conditions. 90 | With 8ohm loaded, the gains become lower by about 0.2 dB (typ.). 91 | 92 | #### Reset Conditions 93 | 94 | 1. When the power supplies are turned on (power-on reset). 95 | 2. When the hardware reset is applied (RST_N= "L"). 96 | 3. When the ALRST is set to "1". 97 | 98 | 99 | ### HW_ID 100 | 101 | | I_ADR | W/R | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 | Reset Value | 102 | |-|-|-|-|-|-|-|-|-|-|-| 103 | |#4|R|"0"|"0"|"0"|"0"|"0"|"0"|"0"|"1"|01H| 104 | 105 | #### Description 106 | The HW_ID is the register used to hold the hardware version and read-only. 107 | The value is "01H" (fixed). 108 | The value can be read even if the ALRST bit is set to "1". 109 | 110 | 111 | ### CONTENTS_DATA_REG 112 | 113 | | I_ADR | W/R | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 | Reset Value | 114 | |-|-|-|-|-|-|-|-|-|-|-| 115 | |#7|W|DT7|DT6|DT5|DT4|DT3|DT2|DT1|DT0|-| 116 | 117 | #### Description 118 | The register is used to write contents data. 119 | 120 | ### Sequencer Setting 121 | 122 | | I_ADR | W/R | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 | Reset Value | 123 | |-|-|-|-|-|-|-|-|-|-|-| 124 | |#8|W/R|AllKeyOff|AllMute|AllEGRst|R_FIFOR|REP_SQ|R_SEQ| R_FIFO|START|00H| 125 | 126 | ### AllKeyOff 127 | #### Description 128 | The AllKeyOff is the register bit used to set the KeyOn registers of all the voices to "0". 129 | 130 | + "0": no processing (reset value) 131 | + "1": Sets the KeyOn registers to "0". 132 | 133 | After setting the register bit to "1", wait for more than 6us and then return it to "0". 134 | 135 | #### Reset Conditions 136 | 1. When the power supplies are turned on (power-on reset). 137 | 2. When the hardware reset is applied (RST_N= "L"). 138 | 3. When the ALRST is set to "1". 139 | 140 | ### AllMute 141 | #### Description 142 | The AllMute is the register bit used to set the Mute registers of all the voices to "1". 143 | + "0": no processing (reset value) 144 | + "1": Sets the Mute registers to "1". 145 | 146 | After setting the register bit to "1", wait for more than 6us and then return it to "0". 147 | 148 | #### Reset Conditions 149 | 1. When the power supplies are turned on (power-on reset). 150 | 2. When the hardware reset is applied (RST_N= "L"). 151 | 3. When the ALRST is set to "1". 152 | 153 | ### AllEGRst 154 | #### Description 155 | The AllEGRst is used to set the EG_RST registers of all the voices to "1". 156 | + "0": no processing (reset value) 157 | + "1": Sets the EG_RST registers to "1". 158 | 159 | After setting the register bit to "1", wait for more than 6us and then return it to "0". 160 | 161 | #### Reset Conditions 162 | 1. When the power supplies are turned on (power-on reset). 163 | 2. When the hardware reset is applied (RST_N= "L"). 164 | 3. When the ALRST is set to "1". 165 | 166 | 167 | ### SEQ_Vol 168 | 169 | | I_ADR | W/R | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 | Reset Value | 170 | |-|-|-|-|-|-|-|-|-|-|-| 171 | |#9|W/R|SEQ_Vol4|SEQ_Vol3|SEQ_Vol2|SEQ_Vol1|SEQ_Vol0|DIR_SV|"0"|SIZE8|00H| 172 | |#10|W/R|SIZE7|SIZE6|SIZE5|SIZE4|SIZE3|SIZE2|SIZE1|SIZE0|00H| 173 | 174 | 175 | #### Description 176 | The SEQ_Vol is the volume setting register of the sequencer volume. 177 | 178 | #### Reset Conditions 179 | 1. When the power supplies are turned on (power-on reset). 180 | 2. When the hardware reset is applied (RST_N= "L"). 181 | 3. When the ALRST is set to "1". 182 | 183 | |Value(HEX)|Volume[dB]| 184 | |-|-| 185 | |00H|mute| 186 | |01H|-47.9| 187 | |02H|-42.6| 188 | |03H|-37.2| 189 | |04H|-33.1| 190 | |05H|-29.8| 191 | |06H|-27.0| 192 | |07H|-24.6| 193 | |08H|-22.4| 194 | |09H|-20.6| 195 | |0AH|-18.9| 196 | |0BH|-17.3| 197 | |0CH|-15.9| 198 | |0DH|-14.6| 199 | |0EH|-13.4| 200 | |0FH|-12.2| 201 | |10H|-11.1| 202 | |11H|-10.1| 203 | |12H|-9.2| 204 | |13H|-8.3| 205 | |14H|-7.4| 206 | |15H|-6.6| 207 | |16H|-5.8| 208 | |17H|-5.1| 209 | |18H|-4.4| 210 | |19H|-3.6| 211 | |1AH|-3.0| 212 | |1BH|-2.3| 213 | |1CH|-1.7| 214 | |1DH|-1.1| 215 | |1EH|-0.6| 216 | |1FH|0.0| 217 | 218 | ### DIR_SV 219 | 220 | #### Description 221 | 222 | The DIR_SV register bit controls whether to apply the interpolation to the SEQ_Vol and the ChVol0-15. 223 | When the register bit is set to "1", the interpolation is not applied to the SEQ_Vol and the ChVol0-15 regardless of the settings of the DIR_CV0?15 and the CHVOL_ITIME. 224 | When it is set to "0" (reset value), the interpolation is dependent on the DIR_CV0?15 and CHVOL_ITIME settings. 225 | 226 | #### Reset Conditions 227 | 1. When the power supplies are turned on (power-on reset). 228 | 2. When the hardware reset is applied (RST_N= "L"). 229 | 3. When the ALRST is set to "1". 230 | 231 | ### SIZE 232 | 233 | #### Description 234 | The SIZE is the register used to set the size of sequence data in bytes. 235 | 236 | 237 | ## Synthesizer Setting 238 | 239 | ### CRGD_VNO 240 | 241 | | I_ADR | W/R | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 | Reset Value | 242 | |-|-|-|-|-|-|-|-|-|-|-| 243 | |#11|W/R|"0"|"0"|"0"|"0"|CRGD_VNO3|CRGD_VNO2|CRGD_VNO1|CRGD_VNO0|00H| 244 | 245 | #### Description 246 | The CRGD_VNO is used to specify a tone number. 247 | 248 | #### Reset Conditions 249 | 1. When the power supplies are turned on (power-on reset). 250 | 2. When the hardware reset is applied (RST_N="L"). 251 | 3. When the ALRST is set to "1". 252 | 253 | 254 | ## Control Register Write Registers 255 | 256 | | I_ADR | W/R | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 | 257 | |-|-|-|-|-|-|-|-|-|-| 258 | |#12|W|"0"|VoVol4|VoVol3|VoVol2|VoVol1|VoVol0|"0"|"0"| 259 | |#13|W|"0"|"0"|FNUM9|FNUM8|FNUM7|BLOCK2|BLOCK1|BLOCK0| 260 | |#14|W|"0"|FNUM6|FNUM5|FNUM4|FNUM3|FNUM2|FNUM1|FNUM0| 261 | |#15|W|"0"|KeyOn|Mute|EG_RST|ToneNum3|ToneNum2|ToneNum1|ToneNum0| 262 | |#16|W|"0"|ChVol4|ChVol3|ChVol2|ChVol1|ChVol0|"0"|DIR_CV| 263 | |#17|W|"0"|"0"|"0"|"0"|"0"|XVB2|XVB1|XVB0| 264 | |#18|W|"0"|"0"|"0"|INT1|INT0|FRAC8|FRAC7|FRAC6| 265 | |#19|W|"0"|FRAC5|FRAC4|FRAC3|FRAC2|FRAC1|FRAC0|"0"| 266 | |#20|W|"0"|"0"|"0"|"0"|"0"|"0"|"0"|DIR_MT| 267 | 268 | ### VoVol 269 | 270 | #### Description 271 | The VoVol is the volume setting registers for each voice number. 272 | The relationship between setting values and volume gain values is the same as that of ChVol and SEQ_Vol. 273 | The interpolation function is not provided for these volume setting registers. 274 | 275 | #### Reset Value 276 | + 00H (Mute) 277 | 278 | ### FNUM, BLOCK 279 | 280 | #### Description 281 | + BLOCK: Specifies an octave. 282 | + FNUM: Sets the frequency information for one octave. 283 | 284 | They are set for each voice. 285 | 286 | #### Reset Value 287 | + FNUM : 000H 288 | + BLOCK: 00H 289 | 290 | #### Pitch Table 291 | 292 | |Note|Frequency|BLOCK|FNUM| 293 | |-|-|-|-| 294 | |C2 |130.8 |3 |357| 295 | |C#2 |138.6 |3 |378| 296 | |D2 |146.8 |3 |401| 297 | |D#2 |155.6 |3 |425| 298 | |E2 |164.8 |3 |450| 299 | |F2 |174.6 |3 |477| 300 | |F#2 |185 |3 |505| 301 | |G2 |196 |3 |535| 302 | |G#2 |207.7 |3 |567| 303 | |A2 |220 |3 |601| 304 | |A#2 |233.1 |3 |637| 305 | |B2 |246.9 |3 |674| 306 | |C3 |261.6 |4 |357| 307 | |C#3 |277.2 |4 |378| 308 | |D3 |293.7 |4 |401| 309 | |D#3 |311.1 |4 |425| 310 | |E3 |329.6 |4 |450| 311 | |F3 |349.2 |4 |477| 312 | |F#3 |370 |4 |505| 313 | |G3 |392 |4 |535| 314 | |G#3 |415.3 |4 |567| 315 | |A3 |440 |4 |601| 316 | |A#3 |466.2 |4 |637| 317 | |B3 |493.9 |4 |674| 318 | |C4 |523.3 |5 |357| 319 | 320 | ### ToneNum 321 | 322 | #### Description 323 | The ToneNum is used to select a tone parameter to use. 324 | This register is provided for each voice. 325 | 326 | #### Reset Value 327 | + 00H 328 | 329 | ### KeyOn 330 | 331 | #### Description 332 | The KeyOn is used to control the sound generation. 333 | + "0": KeyOff (reset value) 334 | + "1": KeyOn 335 | 336 | This register is provided for each voice. 337 | 338 | ### Mute 339 | 340 | #### Description 341 | The Mute is the mute control register. 342 | This register is provided for each voice. 343 | + "0: Cancels the mute (reset value) 344 | + "1": Shifts to the mute state. 345 | 346 | The volume of a voice with the Mute set to "1" shifts to a mute state according to the DIR_MT(I_ADR#20) and the MUTE_ITIME(I_ADR#27) settings; however, when the mute is cancelled, the interpolation is not performed regardless of these settings. 347 | 348 | ### EG_RST 349 | 350 | #### Description 351 | A voice with the EG_RST set to "1" shifts to a mute state immediately regardless of the DIR_MT and MUTE_ITIME settings. 352 | This register is provided for each voice. 353 | Reset Value is "0". 354 | 355 | ### ChVol 356 | 357 | #### Description 358 | This volume setting register is provided for each voice. 359 | The interpolation function is provided for this volume setting register. 360 | The relationship between setting values and volume gain values is the same as that of VoVol and SEQ_Vol. 361 | Reset Value is "18H" (-4.4 dB) 362 | 363 | ### DIR_CV 364 | 365 | #### Description 366 | The DIR_CV controls the interpolation of the SEQ_Vol and ChVol. 367 | This register is provided for each voice. 368 | 369 | DIR_CV="1": 370 | No interpolation in the SEQ_Vol and the ChVol# regardless of the DIR_SV and CHVOL_ITIME settings. 371 | 372 | DIR_CV# = "0" (reset value): 373 | The interpolation depends on the DIR_SV and CHVOL_ITIME settings. 374 | 375 | ### XVB 376 | 377 | #### Description 378 | The XVB is used to set a vibrato modulation. 379 | This register is provided for each voice. 380 | A setting value relatively acts on a DVB setting value of the voice parameter, as shown below. 381 | When the calculation (add) result exceeds "3", "3"is used for the processing. 382 | 383 | + "0": OFF (reset value) 384 | + "1": 1 x (DVB value is used as is.) 385 | + "2": 2 x (DVB += 1) 386 | + "3": 2 x (DVB += 1) 387 | + "4": 4 x (DVB += 2) 388 | + "5": 4 x (DVB += 2) 389 | + "6": 8 x (DVB += 3) 390 | + "7": 8 x (DVB += 3) 391 | 392 | ### INT, FRAC 393 | 394 | #### Description 395 | These registers specify a multiplier to the generated audio frequency. This number and frequency are proportional. 396 | The INT is an integer part and FRAC is a fraction part. 397 | These registers are provided for each voice. 398 | 399 | #### Reset Value 400 | + INT : "01H" 401 | + FRAC: "000H" 402 | 403 | 404 | ### DIR_MT 405 | 406 | The DIR_MT is used to control the interpolation in a mute state. This register bit works for all the 16 voices. 407 | + "0": Enables the interpolation. (reset value) 408 | + "1": Disables the interpolation. 409 | 410 | When this register bit is set to "0", the MUTE_ITIME (I_ADR#27) setting becomes valid; however, the interpolation is not performed when the mute is cancelled regardless of this register and MUTE_ITIME setting. 411 | 412 | 413 | ## Volume Settings 414 | 415 | ### MASTER_VOL 416 | 417 | | I_ADR | W/R | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 | Reset Value | 418 | |-|-|-|-|-|-|-|-|-|-|-| 419 | |#25|W/R|MASTER_VOL5|MASTER_VOL4|MASTER_VOL3|MASTER_VOL2|MASTER_VOL1|MASTER_VOL0|"0"|"0"|00H| 420 | 421 | #### Description 422 | The MASTER_VOL is used to control the master volume level. 423 | The interpolation function is available. 424 | 425 | |DEC|HEX|Volume Level[dB]| 426 | |-|-|-| 427 | |0 |00H |muted | 428 | |1 |01H |-50 | 429 | |2 |02H |-49 | 430 | |3 |03H |-48 | 431 | |4 |04H |-47 | 432 | |5 |05H |-46 | 433 | |6 |06H |-45 | 434 | |7 |07H |-44 | 435 | |8 |08H |-43 | 436 | |9 |09H |-42 | 437 | |10 |0AH |-41 | 438 | |11 |0BH |-40 | 439 | |12 |0CH |-39 | 440 | |13 |0DH |-38 | 441 | |14 |0EH |-37 | 442 | |15 |0FH |-36 | 443 | |16 |10H |-35 | 444 | |17 |11H |-34 | 445 | |18 |12H |-33 | 446 | |19 |13H |-32 | 447 | |20 |14H |-31 | 448 | |21 |15H |-30 | 449 | |22 |16H |-29 | 450 | |23 |17H |-28 | 451 | |24 |18H |-27 | 452 | |25 |19H |-26 | 453 | |26 |1AH |-25 | 454 | |27 |1BH |-24 | 455 | |28 |1CH |-23 | 456 | |29 |1DH |-22 | 457 | |30 |1EH |-21 | 458 | |31 |1FH |-20 | 459 | |32 |20H |-19 | 460 | |33 |21H |-18| 461 | |34 |22H |-17| 462 | |35 |23H |-16| 463 | |36 |24H |-15| 464 | |37 |25H |-14| 465 | |38 |26H |-13| 466 | |39 |27H |-12| 467 | |40 |28H |-11| 468 | |41 |29H |-10| 469 | |42 |2AH |-9| 470 | |43 |2BH |-8| 471 | |44 |2CH |-7| 472 | |45 |2DH |-6| 473 | |46 |2EH |-5| 474 | |47 |2FH |-4| 475 | |48 |30H |-3| 476 | |49 |31H |-2| 477 | |40 |32H |-1| 478 | |51 |33H |0| 479 | |52 |34H |+1| 480 | |53 |35H |+2| 481 | |54 |36H |+3| 482 | |55 |37H |+4| 483 | |56 |38H |+5| 484 | |57 |39H |+6| 485 | |58 |3AH |+7| 486 | |59 |3BH |+8| 487 | |60 |3CH |+9| 488 | |61 |3DH |+10| 489 | |62 |3EH |+11| 490 | |63 |3FH |+12| 491 | 492 | 493 | ### MUTE_ITIME 494 | 495 | | I_ADR | W/R | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 | Reset Value | 496 | |-|-|-|-|-|-|-|-|-|-|-| 497 | |#27|W/R|"0"|DADJT|MUTE_ITIME1|MUTE_ITIME0|CHVOL_ITIME1|CHVOL_ITIME0|MVOL_ITIME1|MVOL_ITIME0|00H| 498 | 499 | #### Description 500 | The MUTE_ITIME is used to specify the volume level variation under the muted condition when the DIR_MT is "0". 501 | + "00b": No interpolation (reset value) 502 | + "01b": Setting prohibited 503 | + "10b": Enables the interpolation. (in 0.3750dB steps, 128/fs (0dB <-> Mute (approx. 2.7 ms)) 504 | + "11b": Enables the interpolation. (in 0.1875dB steps, 256/fs (0dB <-> Mute (approx. 5.3 ms)) 505 | 506 | When the DIR_MT is "1", no interpolation is selected regardless of this register setting. 507 | 508 | ### CHVOL_ITIME 509 | 510 | #### Description 511 | The CHVOL_ITIME is used to specify the volume level variation time of the SEQ_Vol and the ChVol0-15. 512 | This variation time becomes valid only for voices with the DIR_SV set to "0"and the DIR_CV0-15 set to "1". 513 | + "00b": No interpolation (reset value) 514 | + "01b": Setting prohibited 515 | + "10b": Enables the interpolation. (approx. 0.2dB steps, 256/fs (0dB <-> Mute: approx. 5.3ms)) 516 | + "11b": Enables the interpolation. (approx. 0.05 dB steps, 1024/fs (0dB <-> Mute: approx. 21.3ms)) 517 | 518 | ### MVOL_ITIME 519 | 520 | #### Description 521 | The MVOL_ITIME is used to specify the master volume level variation time. 522 | + "00b": No interpolation (The setting value in the MASTER_VOL (I_ADR#25) is immediately reflected.) (reset value) 523 | + "01b": Enables the interpolation. (approx. 0.2 dB steps, 512/fs (+12dB <-> Mute: approx. 10.6ms)) 524 | + "10b": Enables the interpolation. (approx. 0.1 dB steps, 1024/fs (+12dB <-> Mute: approx. 21.3 ms)) 525 | + "11b": Enables the interpolation. (approx. 0.05 dB steps, 2048/fs (+12dB <-> Mute: approx. 42.6 ms)) 526 | 527 | ### LFO_RST 528 | 529 | | I_ADR | W/R | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 | Reset Value | 530 | |-|-|-|-|-|-|-|-|-|-|-| 531 | |#28|W/R|"0"|"0"|"0"|"0"|"0"|"0"|"0"|LFO_RST|00H| 532 | 533 | #### Description 534 | The LFO_RST is used to reset the phase of the LFO (Low Frequency Oscillator). 535 | + "0": No processing (reset value) 536 | * "1": Reset 537 | 538 | Write "0" into the register bit after writing "1" to the bit. 539 | 540 | ### W_CEQ0/1/2 541 | 542 | | I_ADR | W/R | D7-D0 | Reset Value | 543 | |-|-|-|-| 544 | |#32|W|W_CEQ0|-| 545 | |#33|W|W_CEQ1|-| 546 | |#34|W|W_CEQ2|-| 547 | 548 | #### Description 549 | The W_CEQ registers are used to set equalizer coefficients. 550 | There are 3 bytes x 5 coefficients (CEQ#0[23:0] to CEQ#4[23:0]) for each band and they correspond to the coefficient setting registers as follows: 551 | + W_CEQ0: Band 0 coefficients (CEQ00[23:0] to CEQ04[23:0]) 552 | + W_CEQ1: Band 1 coefficients (CEQ10[23:0] to CEQ14[23:0]) 553 | + W_CEQ2: Band 2 coefficients (CEQ20[23:0] to CEQ24[23:0]) 554 | 555 | The setting is independent one another. Write the coefficients to the registers in this order, as 556 | shown below: 557 | 558 | | No. | W_CEQ0 | W_CEQ1 | W_CEQ2 | 559 | |-|-|-|-| 560 | |1|CEQ00[23:16]|CEQ10[23:16]|CEQ20[23:16]| 561 | |2|CEQ00[15:8]|CEQ10[15:8]|CEQ20[15:8]| 562 | |3|CEQ00[7:0]|CEQ10[7:0]|CEQ20[7:0]| 563 | |4|CEQ01[23:16]|CEQ11[23:16]|CEQ21[23:16]| 564 | |5|CEQ01[15:8]|CEQ11[15:8]|CEQ21[15:8]| 565 | |6|CEQ01[7:0]|CEQ11[7:0]|CEQ21[7:0]| 566 | |7|CEQ02[23:16]|CEQ12[23:16]|CEQ22[23:16]| 567 | |8|CEQ02[15:8]|CEQ12[15:8]|CEQ22[15:8]| 568 | |9|CEQ02[7:0]|CEQ12[7:0]|CEQ22[7:0]| 569 | |10|CEQ03[23:16]|CEQ13[23:16]|CEQ23[23:16]| 570 | |11|CEQ03[15:8]|CEQ13[15:8]|CEQ23[15:8]| 571 | |12|CEQ03[7:0]|CEQ13[7:0]|CEQ23[7:0]| 572 | |13|CEQ04[23:16]|CEQ14[23:16]|CEQ24[23:16]| 573 | |14|CEQ04[15:8]|CEQ14[15:8]|CEQ24[15:8]| 574 | |15|CEQ04[7:0]|CEQ14[7:0]|CEQ24[7:0]| 575 | 576 | The 15-byte coefficient values are reflected at the moment when the 15th coefficient (CEQ#4[7:0]) is written. 577 | Write 15 bytes of coefficients in burst mode for each band. 578 | If the write operation is stopped in the middle (less than 15 bytes), values are not reflected. 579 | And on the contrary, if the write operation continues even after the 15th bytes, the 15-byte 580 | coefficients are overwritten when all the next 15 coefficients are written. 581 | 582 | The coefficient data format is as follows: 583 | Sign bit: 1 bit (CEQ##[23]), integer part: 3 bits (CEQ##[22:20]) and fraction part: 20 bits 584 | (CEQ##[19:0]) 585 | in 2'complement. 586 | The figure bellows shows the relationship between the coefficients and the circuit configuration. 587 | 588 | ![EQ](eq.png) 589 | -------------------------------------------------------------------------------- /manual/fbd_spec3.md: -------------------------------------------------------------------------------- 1 | ## Tone Parameter 2 | 3 | #### Notes 4 | + [tn] means "Tone Number". Ymf825 has a maximum of 16 tones. 5 | + [op] means "FM Operator". Ymf825 has 4 operators per voice. 6 | 7 | ### BO 8 | 9 | |T_ADR|Name|D7|D6|D5|D4|D3|D2|D1|D0| 10 | |-|-|-|-|-|-|-|-|-|-| 11 | |#0+30x[tn]|BO|"0"|"0"|"0"|"0"|"0"|"0"|BO1|BO0| 12 | 13 | #### Description 14 | BO means Basic Octave. BO controls an octave setting. 15 | 16 | + BO=0 : 2^1 17 | + BO=1 : 2^0 18 | + BO=2 : 2^-1 19 | + BO=3 : 2^-2 20 | 21 | ### LFO, ALG 22 | 23 | |T_ADR|Name|D7|D6|D5|D4|D3|D2|D1|D0| 24 | |-|-|-|-|-|-|-|-|-|-| 25 | |#1+30x[tn]|LFO,ALG|LFO1|LFO0|"0"|"0"|"0"|ALG2|ALG1|ALG0| 26 | 27 | #### Description 28 | 29 | LFO means a frequency of low frequency oscillator. 30 | 31 | + LFO=0 : 1.8Hz 32 | + LFO=1 : 4.0Hz 33 | + LFO=2 : 5.9Hz 34 | + LFO=3 : 7.0Hz 35 | 36 | ALG means FM Algorithm. 8 algorithms can be selected. 37 | 38 | ![FM Algorithm](algo.png) 39 | 40 | 41 | ### SR, XOF, KSR 42 | 43 | |T_ADR|Name|D7|D6|D5|D4|D3|D2|D1|D0| 44 | |-|-|-|-|-|-|-|-|-|-| 45 | |#2+30x[tn]+7x[op]|SR, XOF, KSR|SR3|SR2|SR1|SR0|XOF|"0"|"0"|KSR| 46 | 47 | #### Description 48 | 49 | SR controls sustain rate of each operator. 50 | if SR is set to 0, sound level is retained. 51 | XOF controls ignoring keyoff. 52 | Evenif keyoff is set, any changes will not happen. 53 | KSR means key scale sensitivity for AEG rate. if KSR bit is on, high F-num EG rate changes faster. 54 | 55 | 56 | ### RR, DR 57 | 58 | |T_ADR|Name|D7|D6|D5|D4|D3|D2|D1|D0| 59 | |-|-|-|-|-|-|-|-|-|-| 60 | |#3+30x[tn]+7x[op]|RR,DR|RR3|RR2|RR1|RR0|DR3|DR2|DR1|DR0| 61 | 62 | #### Description 63 | 64 | RR controls release rate of each operator. 65 | DR controls decay rate of each operator. 66 | 67 | ### AR, SL 68 | 69 | |T_ADR|Name|D7|D6|D5|D4|D3|D2|D1|D0| 70 | |-|-|-|-|-|-|-|-|-|-| 71 | |#4+30x[tn]+7x[op]|AR,SL|AR3|AR2|AR1|AR0|SL3|SL2|SL1|SL0| 72 | 73 | #### Description 74 | 75 | AR controls attack rate of each operator. 76 | SL controls sustain level of each operator. Sustain Level is the level just after decay rate. 77 | 78 | ### TL, KSL 79 | 80 | |T_ADR|Name|D7|D6|D5|D4|D3|D2|D1|D0| 81 | |-|-|-|-|-|-|-|-|-|-| 82 | |#5+30x[tn]+7x[op]|TL,KSL|TL5|TL4|TL3|TL2|TL1|TL0|KSL1|KSL0| 83 | 84 | #### Description 85 | TL means total level.TL controls operator level. 86 | 87 | KSL means key scaling level sensitivity.In natural instruments, the volume attenuates as the pitch increases.KSL simulates this phenomenon. 88 | + KSL=0 : 0 89 | + KSL=1 : 3dB/oct 90 | + KSR=2 : 1.5dB/oct 91 | + KSR=3 : 6.0dB/oct 92 | 93 | 94 | ### DAM, EAM, DVB, EVB 95 | 96 | |T_ADR|Name|D7|D6|D5|D4|D3|D2|D1|D0| 97 | |-|-|-|-|-|-|-|-|-|-| 98 | |#6+30x[tn]+7x[op]|DAM,EAM,DVB,EVB|"0"|DAM1|DAM0|EAM|"0"|DVB1|DVB0|EVB| 99 | 100 | #### Description 101 | 102 | EAM means enable amplitude modulation.EAM set amplitude modulation. 103 | DAM means amplitude modulation depth. 104 | + DAM=0 : 1.3dB 105 | + DAM=1 : 2.8dB 106 | + DAM=2 : 5.8dB 107 | + DAM=3 : 11.8dB 108 | 109 | EVB means enable vibrato.EVB set vibrato. 110 | DVB means vibrato depth. 111 | + DVB=0 : 3.4cent 112 | + DVB=1 : 6.7cent 113 | + DVB=2 : 13.5cent 114 | + DVB=3 : 26.8cent 115 | 116 | 117 | ### MULTI, DT 118 | 119 | |T_ADR|Name|D7|D6|D5|D4|D3|D2|D1|D0| 120 | |-|-|-|-|-|-|-|-|-|-| 121 | |#7+30x[tn]+7x[op]|MULTI, DT|MULTI3|MULTI2|MULTI1|MULTI0|"0"|DT2|DT1|DT0| 122 | 123 | #### Description 124 | MULTI controls magnification of frequency. 125 | 126 | |MULTI|0|1|2|3|4|5|6|7|8|9|10,11|12,13|14,15| 127 | |-|-|-|-|-|-|-|-|-|-|-|-|-|-| 128 | |magnification|1/2|1|2|3|4|5|6|7|8|9|10|12|15| 129 | 130 | DT means detune. 131 | 132 | 133 | ### WS, FB 134 | 135 | |T_ADR|Name|D7|D6|D5|D4|D3|D2|D1|D0| 136 | |-|-|-|-|-|-|-|-|-|-| 137 | |#8+30x[tn]+7x[op]|WS,FB|WS4|WS3|WS2|WS1|WS0|FB2|FB1|FB0| 138 | 139 | #### Description 140 | WS means wave shape each operator generates. 141 | 29 wave shapes can be selected. 142 | 143 | ![wave shapes](ws.png) 144 | 145 | FB means FM feedback level. 146 | + FB=0 : 0 147 | + FB=1 : pi/16 148 | + FB=2 : pi/8 149 | + FB=3 : pi/4 150 | + FB=4 : pi/2 151 | + FB=5 : pi 152 | + FB=6 : 2pi 153 | + FB=7 : 4pi 154 | 155 | 156 | -------------------------------------------------------------------------------- /manual/sd1-pitch.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danielrfry/ymf825board/aa526f3dae0c161b562515ecd2e59efaeaa1d062/manual/sd1-pitch.xlsx -------------------------------------------------------------------------------- /manual/spi_burst.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danielrfry/ymf825board/aa526f3dae0c161b562515ecd2e59efaeaa1d062/manual/spi_burst.png -------------------------------------------------------------------------------- /manual/spi_read.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danielrfry/ymf825board/aa526f3dae0c161b562515ecd2e59efaeaa1d062/manual/spi_read.png -------------------------------------------------------------------------------- /manual/spi_single.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danielrfry/ymf825board/aa526f3dae0c161b562515ecd2e59efaeaa1d062/manual/spi_single.png -------------------------------------------------------------------------------- /manual/ws.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danielrfry/ymf825board/aa526f3dae0c161b562515ecd2e59efaeaa1d062/manual/ws.png -------------------------------------------------------------------------------- /sample1/ymf825board_sample1/ymf825board_sample1.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Conditions only for Arduino UNO 3 | RST_N- Pin9 4 | SS - Pin10 5 | MOSI - Pin11 6 | MISO - Pin12 7 | SCK - Pin13 8 | */ 9 | #include 10 | //0 :5V 1:3.3V 11 | #define OUTPUT_power 0 12 | 13 | // only for Arduino UNO 14 | void set_ss_pin(int val) { 15 | if(val ==HIGH) PORTB |= (4); 16 | else PORTB &= ~(4); 17 | } 18 | 19 | // only for Arduino UNO 20 | void set_rst_pin(int val) { 21 | if(val ==HIGH) PORTB |= (2); 22 | else PORTB &= ~(2); 23 | } 24 | 25 | void if_write(char addr,unsigned char* data,char num){ 26 | char i; 27 | char snd; 28 | set_ss_pin(LOW); 29 | SPI.transfer(addr); 30 | for(i=0;i 2 | #define ARDUINO 3 | -------------------------------------------------------------------------------- /sample2/arduino/fmsd1_ino.cpp: -------------------------------------------------------------------------------- 1 | // fmsd1_ino.cpp 2 | #include 3 | 4 | void writeSingleCPP( unsigned char adrs, unsigned char data ) 5 | { 6 | digitalWrite(10, LOW); // select slave 7 | SPI.transfer(adrs); 8 | SPI.transfer(data); 9 | digitalWrite(10, HIGH); 10 | delay(1); 11 | } 12 | extern "C" void writeSingle( unsigned char adrs, unsigned char data ){ writeSingleCPP(adrs,data);} 13 | extern "C" void writeBurst( unsigned char adrs, unsigned char* data, int count ) 14 | { 15 | digitalWrite(10, LOW); 16 | SPI.transfer(adrs); 17 | for (int i = 0; i 0x48 ){ note = 0x3c;} 33 | } 34 | -------------------------------------------------------------------------------- /sample2/common/fmasgn.c: -------------------------------------------------------------------------------- 1 | // fmasgn.c 2 | #include "fmtype.h" 3 | #include "fmasgn.h" 4 | #include "fmvoice.h" 5 | 6 | // Variable 7 | static Fmvoice _fmvc[MAX_FM_VOICE]; 8 | static Fmvoice* _firstEmptyVc; // old 9 | static Fmvoice* _lastEmptyVc; // new 10 | static Fmvoice* _firstOccupiedVc; // old 11 | static Fmvoice* _lastOccupiedVc; // new 12 | 13 | // Prototype 14 | static void setToEmptyList( Fmvoice* prevVc, Fmvoice* rlsVc ); 15 | 16 | // setter 17 | void Asgn_setFirstEmptyVc( Fmvoice* vc ){ _firstEmptyVc = vc; } 18 | void Asgn_setLastEmptyVc( Fmvoice* vc ){ _lastEmptyVc = vc; } 19 | 20 | // getter 21 | Fmvoice* Asgn_voice( int num ){ return &(_fmvc[num]); } 22 | Fmvoice* Asgn_firstEmptyVc( void ){ return _firstEmptyVc; } 23 | Fmvoice* Asgn_lastEmptyVc( void ){ return _lastEmptyVc; } 24 | 25 | void Asgn_init( void ) 26 | { 27 | int i; 28 | 29 | for ( i=0; i 4 | #include "fmvoice.h" 5 | 6 | #define MAX_FM_VOICE 16 7 | 8 | // public 9 | extern void Asgn_init( void ); 10 | extern bool Asgn_chkEmpty( void ); 11 | extern Fmvoice* Asgn_getEmptyVc( void ); 12 | extern void Asgn_releaseOneVc( void ); 13 | extern void Asgn_releaseParticularVc( Fmvoice* pvc ); 14 | 15 | // setter 16 | extern void Asgn_setFirstEmptyVc( Fmvoice* vc ); 17 | extern void Asgn_setLastEmptyVc( Fmvoice* vc ); 18 | 19 | // getter 20 | extern Fmvoice* Asgn_voice( int num ); 21 | extern Fmvoice* Asgn_firstEmptyVc( void ); 22 | extern Fmvoice* Asgn_lastEmptyVc( void ); 23 | 24 | #endif -------------------------------------------------------------------------------- /sample2/common/fmif.c: -------------------------------------------------------------------------------- 1 | // fmif.c 2 | #include "fmpart.h" 3 | 4 | // Variable 5 | static Part _part; 6 | static unsigned char _midiCmdCounter; 7 | static unsigned char _midiStatus; 8 | static unsigned char _midiDataByte1; 9 | static unsigned char _midiDataByte2; 10 | 11 | // Prototype 12 | static void receiveDataByte( unsigned char byteStream ); 13 | static void generateMidiCmd(void); 14 | 15 | void Fmdriver_init( void ) 16 | { 17 | _midiCmdCounter = 0; 18 | _midiStatus = 0; 19 | _midiDataByte1 = 0; 20 | _midiDataByte2 = 0; 21 | 22 | Part_init(&_part); 23 | Part_pc(&_part,0); 24 | } 25 | void Fmdriver_sendMidi( unsigned char byteStream ) 26 | { 27 | if ( byteStream & 0x80 ){ 28 | if ( byteStream == 0xf7 ){ 29 | Tone_sendTone(); 30 | _midiStatus = 0; 31 | _midiCmdCounter = 0; 32 | } 33 | else { 34 | _midiStatus = byteStream; 35 | _midiCmdCounter = 1; 36 | } 37 | } 38 | else if ( _midiStatus == 0xf0 ){ 39 | Tone_setToneExc(byteStream,_midiCmdCounter); 40 | _midiCmdCounter += 1; 41 | } 42 | else if ( _midiStatus != 0 ){ 43 | receiveDataByte(byteStream); 44 | } 45 | } 46 | static void receiveDataByte( unsigned char byteStream ) 47 | { 48 | switch (_midiCmdCounter){ 49 | case 0: case 1:{ 50 | _midiDataByte1 = byteStream; 51 | switch ( _midiStatus & 0xf0 ){ 52 | case 0xc0: case 0xd0:{ 53 | _midiCmdCounter = 0; 54 | generateMidiCmd(); 55 | break; 56 | } 57 | default:{ 58 | _midiCmdCounter = 2; 59 | break; 60 | } 61 | } 62 | break; 63 | } 64 | case 2:{ 65 | _midiDataByte2 = byteStream; 66 | _midiCmdCounter = 0; 67 | generateMidiCmd(); 68 | break; 69 | } 70 | default: break; 71 | } 72 | } 73 | static void generateMidiCmd( void ) 74 | { 75 | switch ( _midiStatus ){ // receive only MIDI ch.1 76 | case 0x80: Part_note( &_part, _midiDataByte1, 0 ); break; 77 | case 0x90: Part_note( &_part, _midiDataByte1, _midiDataByte2 ); break; 78 | case 0xb0: Part_cc( &_part, _midiDataByte1, _midiDataByte2 ); break; 79 | case 0xc0: Part_pc( &_part, _midiDataByte1 ); break; 80 | case 0xe0: Part_pbend( &_part, _midiDataByte1, _midiDataByte2 ); break; 81 | default: break; 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /sample2/common/fmif.h: -------------------------------------------------------------------------------- 1 | #ifndef FMIF_H 2 | #define FMIF_H 3 | // public 4 | extern void Fmdriver_init( void ); 5 | extern void Fmdriver_sendMidi( unsigned char byteStream ); 6 | #endif -------------------------------------------------------------------------------- /sample2/common/fmnote.c: -------------------------------------------------------------------------------- 1 | // fmnote.c 2 | #include "fmtype.h" 3 | #include "fmnote.h" 4 | #include "fmpart.h" 5 | #include "fmtone.h" 6 | #include "fmasgn.h" 7 | 8 | // Prototype 9 | static void obtainNecessaryVoice(Note* _this); 10 | 11 | // setter 12 | void Note_setPrevPtr( Note* _this, Note* pn ){ _this->_prevPtr = pn; } 13 | void Note_setNextPtr( Note* _this, Note* nn ){ _this->_nextPtr = nn; } 14 | void Note_setPart( Note* _this, void* pt ){ _this->_parent = pt; } 15 | void Note_setHold( Note* _this, bool hold ){ _this->_hold = hold; } 16 | // getter 17 | bool Note_isInUse( Note* _this ){ return _this->_inUse; } 18 | bool Note_isKeyOn( Note* _this ){ return _this->_keyon; } 19 | bool Note_isHeld( Note* _this ){ return _this->_hold; } 20 | Note* Note_prevPtr( Note* _this ){ return _this->_prevPtr;} 21 | Note* Note_nextPtr( Note* _this ){ return _this->_nextPtr;} 22 | unsigned char Note_note(Note* _this){ return _this->_note; } 23 | unsigned char Note_velocity(Note* _this){ return _this->_velocity; } 24 | 25 | void Note_init( Note* _this ) 26 | { 27 | _this->_prevPtr = 0; 28 | _this->_nextPtr = 0; 29 | _this->_inUse = false; 30 | _this->_keyon = false; 31 | _this->_hold = false; 32 | _this->_note = 0; 33 | _this->_parent = 0; 34 | _this->_velocity = 0; 35 | } 36 | 37 | bool Note_keyon( Note* _this, ToneData* newTone, unsigned char newNote, unsigned char newVelocity ) 38 | { 39 | if ( _this->_parent == FMNULL){ return false; } 40 | 41 | _this->_note = newNote; 42 | _this->_velocity = newVelocity; 43 | 44 | // obtain necessary voices 45 | obtainNecessaryVoice( _this); 46 | 47 | Fmvoice_keyon(_this->_vc, _this, _this->_parent, newTone, newNote, newVelocity); 48 | 49 | // set variables 50 | _this->_keyon = true; 51 | _this->_inUse = true; 52 | _this->_hold = false; 53 | return true; 54 | } 55 | void Note_keyoff( Note* _this ) 56 | { 57 | Fmvoice_keyoff( _this->_vc ); 58 | _this->_keyon = false; 59 | _this->_hold = false; 60 | } 61 | void Note_damp( Note* _this ) 62 | { 63 | if (_this->_vc != FMNULL) { 64 | Asgn_releaseParticularVc(_this->_vc); 65 | } 66 | } 67 | void Note_releaseVc( Note* _this, Fmvoice* rlsVc ) 68 | { 69 | if ( rlsVc == _this->_vc ) { 70 | _this->_vc = FMNULL; 71 | } 72 | Note_release(_this); 73 | } 74 | void Note_release( Note* _this ) 75 | { 76 | if (_this->_parent == FMNULL){ return; } 77 | Part_releaseNote((Part*)_this->_parent,_this); 78 | _this->_prevPtr = _this->_nextPtr = FMNULL; 79 | _this->_keyon = false; 80 | _this->_inUse = false; 81 | _this->_hold = false; 82 | } 83 | void Note_chgVibDpt( Note* _this ) 84 | { 85 | if (_this->_parent == FMNULL){ return; } 86 | Part* pt = (Part*)_this->_parent; 87 | if (pt == FMNULL) { return; } 88 | Fmvoice_chgVibDpt(_this->_vc, Part_cc1(pt)); 89 | } 90 | void Note_chgPit( Note* _this ) 91 | { 92 | if (_this->_parent == FMNULL) { return; } 93 | Part* pt = (Part*)_this->_parent; 94 | if (pt == FMNULL) { return; } 95 | Fmvoice_chgPit(_this->_vc, Part_pb(pt)); 96 | } 97 | static void obtainNecessaryVoice(Note* _this) 98 | { 99 | while (Asgn_chkEmpty() != true) { 100 | Asgn_releaseOneVc(); 101 | } 102 | _this->_vc = Asgn_getEmptyVc(); 103 | } -------------------------------------------------------------------------------- /sample2/common/fmnote.h: -------------------------------------------------------------------------------- 1 | #ifndef FMNOTE_H 2 | #define FMNOTE_H 3 | #include "fmtone.h" 4 | #include "fmvoice.h" 5 | 6 | // Note Class 7 | typedef struct _Note Note; 8 | struct _Note { 9 | unsigned char _note; 10 | unsigned char _velocity; 11 | bool _inUse; 12 | bool _keyon; 13 | bool _hold; 14 | 15 | Note* _prevPtr; 16 | Note* _nextPtr; 17 | void* _parent; 18 | Fmvoice* _vc; 19 | }; 20 | 21 | // public 22 | extern void Note_init( Note* _this ); 23 | extern bool Note_keyon( Note* _this, ToneData* newTone, unsigned char note, unsigned char velocity ); 24 | extern void Note_keyoff( Note* _this ); 25 | extern void Note_releaseVc( Note* _this, Fmvoice* rlsVc ); 26 | extern void Note_release( Note* _this ); 27 | extern void Note_damp( Note* _this ); 28 | extern void Note_chgVibDpt( Note* _this ); 29 | extern void Note_chgPit( Note* _this ); 30 | 31 | // setter 32 | extern void Note_setPrevPtr( Note* _this, Note* pn ); 33 | extern void Note_setNextPtr( Note* _this, Note* nn ); 34 | extern void Note_setPart( Note* _this, void* pt ); 35 | extern void Note_setHold( Note* _this, bool hold ); 36 | // getter 37 | extern bool Note_isInUse( Note* _this ); 38 | extern bool Note_isKeyOn( Note* _this ); 39 | extern bool Note_isHeld( Note* _this ); 40 | extern Note* Note_prevPtr( Note* _this ); 41 | extern Note* Note_nextPtr( Note* _this ); 42 | extern unsigned char Note_note(Note* _this); 43 | extern unsigned char Note_velocity(Note* _this); 44 | #endif -------------------------------------------------------------------------------- /sample2/common/fmpart.c: -------------------------------------------------------------------------------- 1 | // fmpart.c 2 | #include "fmtype.h" 3 | #include "fmpart.h" 4 | #include "fmsd1.h" 5 | #include "fmasgn.h" 6 | #include "fmtone.h" 7 | 8 | // Prototype 9 | static Note* getNote(Part* _this); 10 | 11 | // getter 12 | unsigned char Part_cc1(Part* _this){ return _this->_cc1; } 13 | unsigned char Part_cc7(Part* _this){ return _this->_cc7; } 14 | unsigned short Part_pb(Part* _this){ return _this->_pbvalue; } 15 | unsigned char Part_toneNumber(Part* _this){ return _this->_toneNumber; } 16 | 17 | void Part_init( Part* _this ) 18 | { 19 | int i; 20 | 21 | Asgn_init(); 22 | Tone_init(); 23 | 24 | _this->_topNt = 0; 25 | _this->_endNt = 0; 26 | _this->_cc1 = 0; 27 | _this->_cc7 = 100; 28 | _this->_cc64 = 0; 29 | _this->_pbvalue = 0x2000; 30 | _this->_toneNumber = 0; 31 | 32 | for ( i=0; i_note[i]); 34 | Note_setPart(&_this->_note[i], (void*)_this); 35 | } 36 | } 37 | void Part_note( Part* _this, unsigned char note, unsigned char velocity ) 38 | { 39 | if ( velocity != 0 ){ 40 | // keyon 41 | Note* newNt = getNote(_this); 42 | if ( Note_keyon(newNt,&_this->_tone,note,velocity) == true ){ 43 | if ( _this->_endNt != FMNULL ){ 44 | Note_setNextPtr( _this->_endNt,newNt ); 45 | Note_setPrevPtr( newNt,_this->_endNt ); 46 | } 47 | _this->_endNt = newNt; 48 | if ( _this->_topNt ==FMNULL ){ 49 | _this->_topNt = newNt; 50 | } 51 | } 52 | } 53 | else { 54 | // keyoff 55 | Note* nt = _this->_topNt; 56 | while( nt != 0 ){ 57 | if (( Note_note(nt) == note ) && 58 | ( Note_isKeyOn(nt) == true ) && 59 | ( Note_isHeld(nt) == false )){ 60 | if ( _this->_cc64 < 64 ){ 61 | Note_keyoff(nt); 62 | } 63 | else { 64 | Note_setHold(nt,true); 65 | } 66 | break; 67 | } 68 | nt = Note_nextPtr(nt); 69 | } 70 | } 71 | } 72 | void Part_releaseNote( Part* _this, Note* nt ) 73 | { 74 | Note* prevPtr = Note_prevPtr(nt); 75 | if ( _this->_endNt == nt ){ 76 | _this->_endNt = prevPtr; 77 | } 78 | if ( prevPtr != FMNULL ){ 79 | Note_setNextPtr(prevPtr, Note_nextPtr(nt)); 80 | } 81 | 82 | Note* nextPtr = Note_nextPtr(nt); 83 | if ( _this->_topNt == nt ){ 84 | _this->_topNt = nextPtr; 85 | } 86 | if ( nextPtr != FMNULL ){ 87 | Note_setPrevPtr(nextPtr, Note_prevPtr(nt)); 88 | } 89 | } 90 | void Part_cc( Part* _this, unsigned char ccnum, unsigned char value ) 91 | { 92 | Note* nt = _this->_topNt; 93 | 94 | // Limit 95 | if (value > 127) { value = 127; } 96 | 97 | switch (ccnum) { 98 | case 1: { 99 | _this->_cc1 = value; 100 | while ( nt != FMNULL ) { 101 | Note_chgVibDpt(nt); 102 | nt = Note_nextPtr(nt); 103 | } 104 | break; 105 | } 106 | case 7: { 107 | _this->_cc7 = value; 108 | writeSingle( REG_MASTER_VOL, (value<<1)&0xfc ); 109 | break; 110 | } 111 | case 64: { 112 | _this->_cc64 = value; 113 | if ( value < 64 ){ 114 | while ( nt != FMNULL ) { 115 | if ( Note_isHeld(nt) == true ){ 116 | Note_keyoff(nt); 117 | } 118 | nt = Note_nextPtr(nt); 119 | } 120 | } 121 | break; 122 | } 123 | default: break; 124 | } 125 | } 126 | void Part_pc( Part* _this, unsigned char num ) 127 | { 128 | Note* nt = _this->_topNt; 129 | Note* nextNt; 130 | 131 | // Damp 132 | while ( nt != FMNULL ) { 133 | nextNt = Note_nextPtr(nt); 134 | Note_damp(nt); 135 | nt = nextNt; 136 | } 137 | 138 | _this->_toneNumber = num; 139 | } 140 | void Part_pbend( Part* _this, unsigned char lsb, unsigned char msb ) 141 | { 142 | Note* nt = _this->_topNt; 143 | _this->_pbvalue = (msb<<7)|(lsb&0x7f); 144 | while ( nt != FMNULL ) { 145 | Note_chgPit(nt); 146 | nt = Note_nextPtr(nt); 147 | } 148 | } 149 | static Note* getNote( Part* _this ) 150 | { 151 | int i; 152 | Note* newNt = 0; 153 | for ( i=0; i_note[i]); 155 | if ( Note_isInUse(newNt) == false ){ 156 | return newNt; 157 | } 158 | } 159 | // if nothing 160 | newNt = _this->_topNt; 161 | Note_damp(newNt); 162 | return newNt; 163 | } 164 | -------------------------------------------------------------------------------- /sample2/common/fmpart.h: -------------------------------------------------------------------------------- 1 | #ifndef FMPART_H 2 | #define FMPART_H 3 | #include "fmnote.h" 4 | #include "fmtone.h" 5 | #include "fmasgn.h" 6 | 7 | #define MAX_NOTE_OBJECT 20 8 | 9 | // Part Class 10 | typedef struct _Part Part; 11 | struct _Part{ 12 | 13 | ToneData _tone; 14 | Note _note[MAX_NOTE_OBJECT]; 15 | 16 | Note* _topNt; // old 17 | Note* _endNt; // latest 18 | 19 | unsigned char _cc1; 20 | unsigned char _cc7; 21 | unsigned char _cc64; 22 | unsigned short _pbvalue; // 0 - 16383 23 | unsigned char _toneNumber; 24 | }; 25 | 26 | // public 27 | extern void Part_init( Part* _this ); 28 | extern void Part_note( Part* _this, unsigned char note, unsigned char velocity ); 29 | extern void Part_cc( Part* _this, unsigned char ccnum, unsigned char value ); 30 | extern void Part_pbend( Part* _this, unsigned char lsb, unsigned char msb ); 31 | extern void Part_pc( Part* _this, unsigned char num ); 32 | extern void Part_releaseNote( Part* _this, Note* nt); 33 | 34 | // getter 35 | extern unsigned char Part_cc1( Part* _this ); 36 | extern unsigned char Part_cc7( Part* _this ); 37 | extern unsigned short Part_pb( Part* _this ); 38 | extern unsigned char Part_toneNumber( Part* _this ); 39 | #endif -------------------------------------------------------------------------------- /sample2/common/fmsd1.h: -------------------------------------------------------------------------------- 1 | #ifndef FMSD1_H 2 | #define FMSD1_H 3 | 4 | // public 5 | void initSPI( void ); 6 | void initSD1( void ); 7 | void delayMs( int ms ); 8 | void writeSingle( unsigned char adrs, unsigned char data ); 9 | void writeBurst( unsigned char adrs, unsigned char* data, int count ); 10 | 11 | static const unsigned char REG_TOP_ADRS = 12; 12 | static const unsigned char REG_VOL = 0; 13 | static const unsigned char REG_BLK = 1; 14 | static const unsigned char REG_FNUM = 2; 15 | static const unsigned char REG_CTRL = 3; 16 | static const unsigned char REG_CH_VOL = 4; 17 | static const unsigned char REG_XVB = 5; 18 | static const unsigned char REG_INT = 6; 19 | static const unsigned char REG_FRC = 7; 20 | static const unsigned char REG_MASTER_VOL = 25; 21 | #endif 22 | -------------------------------------------------------------------------------- /sample2/common/fmtone.c: -------------------------------------------------------------------------------- 1 | // fmtone.c 2 | #include "fmtype.h" 3 | #include "fmtone.h" 4 | #include "fmsd1.h" 5 | 6 | #define IMMUTABLE_TONE_MAX 8 7 | #define MUTABLE_TONE_MAX IMMUTABLE_TONE_MAX 8 | #define AVAILABLE_TONE_NUMBER (IMMUTABLE_TONE_MAX+MUTABLE_TONE_MAX) 9 | #define MAX_EXCLUSIVE_HEADER_SIZE 5 10 | 11 | #define MAX_ELEMENT_PRM 2 12 | #define OPERATOR_PRM_REG_SZ 7 13 | #define MAX_TONE_PRM_SZ (MAX_FM_OPERATOR*OPERATOR_PRM_REG_SZ + MAX_ELEMENT_PRM) 14 | 15 | typedef enum { 16 | WAIT_DATA, 17 | DURING_SETTING, 18 | SET_STATE_MAX 19 | } SET_STATE; 20 | 21 | // Variable 22 | static SET_STATE _toneSetState; 23 | static int _tprmIndex; 24 | static ToneData _userTone[MUTABLE_TONE_MAX]; 25 | static const ToneData TPRM[IMMUTABLE_TONE_MAX] = { 26 | 27 | { // GrandPiano 28 | 0x0b, // VoiceCommon 29 | { // KC | AR | DR | SR | RR | SL | TL | VB | PT | WS 30 | {0x01,0x0f,0x07,0x00,0x06,0x0f,0x27,0x00,0x01,0x08}, // op1 31 | {0x07,0x0e,0x03,0x02,0x03,0x02,0x28,0x00,0x05,0x00}, // op2 32 | {0x00,0x0d,0x01,0x01,0x04,0x03,0x22,0x01,0x01,0x00}, // op3 33 | {0x06,0x0d,0x02,0x02,0x06,0x04,0x00,0x01,0x01,0x00} // op4 34 | } 35 | }, 36 | { // E.Piano 37 | 0x0d, // VoiceCommon 38 | { // KC | AR | DR | SR | RR | SL | TL | VB | PT | WS 39 | {0x54,0x0f,0x04,0x05,0x0c,0x0b,0x23,0x44,0x07,0x12}, // op1 40 | {0x02,0x0f,0x02,0x01,0x08,0x0f,0x04,0x45,0x01,0x00}, // op2 41 | {0x25,0x0f,0x00,0x01,0x0b,0x01,0x12,0x44,0x01,0x00}, // op3 42 | {0x04,0x0f,0x02,0x01,0x07,0x0f,0x04,0x41,0x01,0x00} // op4 43 | } 44 | }, 45 | { // TenorSax 46 | 0x0d, // VoiceCommon 47 | { // KC | AR | DR | SR | RR | SL | TL | VB | PT | WS 48 | {0x36,0x07,0x03,0x00,0x00,0x00,0x05,0x44,0x01,0x01}, // op1 49 | {0x00,0x07,0x02,0x00,0x09,0x00,0x0f,0x43,0x01,0x08}, // op2 50 | {0x36,0x07,0x03,0x00,0x00,0x00,0x08,0x44,0x01,0x09}, // op3 51 | {0x02,0x07,0x02,0x00,0x09,0x00,0x0d,0x43,0x01,0x00} // op4 52 | } 53 | }, 54 | { // PickBass 55 | 0x0b, // VoiceCommon 56 | { // KC | AR | DR | SR | RR | SL | TL | VB | PT | WS 57 | {0x56,0x0f,0x07,0x02,0x03,0x01,0x13,0x44,0x01,0x00}, // op1 58 | {0x04,0x0c,0x0b,0x04,0x06,0x07,0x15,0x44,0x07,0x00}, // op2 59 | {0x06,0x0f,0x09,0x02,0x06,0x02,0x17,0x44,0x02,0x00}, // op3 60 | {0x04,0x0b,0x02,0x06,0x08,0x06,0x00,0x44,0x01,0x00} // op4 61 | } 62 | }, 63 | { // TnklBell 64 | 0x0d, // VoiceCommon 65 | { // KC | AR | DR | SR | RR | SL | TL | VB | PT | WS 66 | {0x31,0x0f,0x06,0x03,0x04,0x05,0x10,0x44,0x0e,0x00}, // op1 67 | {0x02,0x0c,0x06,0x07,0x06,0x0e,0x0b,0x44,0x02,0x00}, // op2 68 | {0x00,0x0c,0x06,0x02,0x02,0x05,0x1e,0x44,0x77,0x01}, // op3 69 | {0x00,0x0f,0x05,0x04,0x05,0x0d,0x01,0x54,0x06,0x00} // op4 70 | } 71 | }, 72 | { // NewAgePd 73 | 0x0d, // VoiceCommon 74 | { // KC | AR | DR | SR | RR | SL | TL | VB | PT | WS 75 | {0x54,0x0f,0x0f,0x03,0x03,0x00,0x26,0x44,0x07,0x01}, // op1 76 | {0x02,0x0f,0x07,0x04,0x04,0x00,0x0b,0x44,0x05,0x00}, // op2 77 | {0x62,0x06,0x01,0x00,0x01,0x00,0x18,0x03,0x71,0x01}, // op3 78 | {0x02,0x08,0x01,0x00,0x05,0x01,0x00,0x03,0x01,0x00} // op4 79 | } 80 | }, 81 | { // Rim Shot 82 | 0x0d, // VoiceCommon 83 | { // KC | AR | DR | SR | RR | SL | TL | VB | PT | WS 84 | {0x7c,0x0f,0x00,0x05,0x05,0x00,0x05,0x44,0x0c,0x02}, // op1 85 | {0x0c,0x0f,0x07,0x07,0x07,0x07,0x00,0x44,0x0b,0x00}, // op2 86 | {0x08,0x0f,0x0a,0x06,0x06,0x08,0x00,0x44,0x0c,0x00}, // op3 87 | {0x08,0x0f,0x07,0x07,0x07,0x07,0x00,0x44,0x07,0x02} // op4 88 | } 89 | }, 90 | { // Castanet 91 | 0x0d, // VoiceCommon 92 | { // KC | AR | DR | SR | RR | SL | TL | VB | PT | WS 93 | {0x68,0x0f,0x07,0x05,0x09,0x0f,0x02,0x44,0x07,0x01}, // op1 94 | {0x0c,0x0a,0x08,0x05,0x0f,0x0f,0x00,0x44,0x05,0x06}, // op2 95 | {0x08,0x0f,0x05,0x06,0x05,0x00,0x27,0x44,0x02,0x05}, // op3 96 | {0x08,0x0c,0x0a,0x09,0x09,0x0a,0x14,0x44,0x05,0x00} // op4 97 | } 98 | } 99 | }; 100 | const unsigned char tExcCheck[MAX_EXCLUSIVE_HEADER_SIZE] = { 101 | 0x43, // Exclusive:1, Yamaha ID 102 | 0x7f, // Exclusive:2, Make/DIY ID1 103 | 0x02, // Exclusive:3, Make/DIY ID2 104 | 0x00, // Exclusive:4, YMF825 ID 105 | 0x00 // Exclusive:5, reserved 106 | }; 107 | void Tone_init( void ) 108 | { 109 | int i; 110 | for ( i=0; ivoiceCommon & 0x60)>>5; 162 | riPtr[1] = ((td->voiceCommon & 0x18)<<3) | (td->voiceCommon & 0x07); 163 | 164 | for ( j=0; jopPrm[j][3] << 4) | (td->opPrm[j][0] & 0x08) | ((td->opPrm[j][0] & 0x04)>>2); 166 | riPtr[MAX_ELEMENT_PRM+OPERATOR_PRM_REG_SZ*j+1] = (td->opPrm[j][4] << 4) | td->opPrm[j][2]; 167 | riPtr[MAX_ELEMENT_PRM+OPERATOR_PRM_REG_SZ*j+2] = (td->opPrm[j][1] << 4) | td->opPrm[j][5]; 168 | riPtr[MAX_ELEMENT_PRM+OPERATOR_PRM_REG_SZ*j+3] = (td->opPrm[j][6] << 2) | (td->opPrm[j][0] & 0x03); 169 | riPtr[MAX_ELEMENT_PRM+OPERATOR_PRM_REG_SZ*j+4] = td->opPrm[j][7]; 170 | riPtr[MAX_ELEMENT_PRM+OPERATOR_PRM_REG_SZ*j+5] = ((td->opPrm[j][8] & 0x0f) << 4) | ((td->opPrm[j][8] & 0xf0) >> 4); 171 | riPtr[MAX_ELEMENT_PRM+OPERATOR_PRM_REG_SZ*j+6] = (td->opPrm[j][9] << 3) | ((td->opPrm[j][0] & 0x70) >> 4); 172 | } 173 | } 174 | 175 | // end 176 | regImage[MAX_TONE_PRM_SZ*AVAILABLE_TONE_NUMBER + 1] = 0x80; 177 | regImage[MAX_TONE_PRM_SZ*AVAILABLE_TONE_NUMBER + 2] = 0x03; 178 | regImage[MAX_TONE_PRM_SZ*AVAILABLE_TONE_NUMBER + 3] = 0x81; 179 | regImage[MAX_TONE_PRM_SZ*AVAILABLE_TONE_NUMBER + 4] = 0x80; 180 | 181 | // Soft Reset 182 | // writeSingle(26,0xa3); 183 | // writeSingle(26,0x00); 184 | writeSingle(8,0xf6); 185 | delayMs(1); 186 | writeSingle(8,0x00); 187 | 188 | writeBurst( 7, regImage, MAX_TONE_PRM_SZ*AVAILABLE_TONE_NUMBER + 5 ); 189 | } -------------------------------------------------------------------------------- /sample2/common/fmtone.h: -------------------------------------------------------------------------------- 1 | #ifndef FMTONE_H 2 | #define FMTONE_H 3 | 4 | #define MAX_FM_OPERATOR 4 5 | #define MAX_OPERATOR_PRM 10 6 | 7 | // ToneData Class 8 | typedef struct { 9 | unsigned char voiceCommon; // BO(2) | LFO(2) | ALG(3) 10 | unsigned char opPrm[MAX_FM_OPERATOR][MAX_OPERATOR_PRM]; 11 | } ToneData; 12 | 13 | // public 14 | extern void Tone_init( void ); 15 | extern void Tone_setToneExc( unsigned char data, int excNum ); 16 | extern void Tone_sendTone( void ); 17 | #endif 18 | -------------------------------------------------------------------------------- /sample2/common/fmtype.h: -------------------------------------------------------------------------------- 1 | #ifndef FMTYPE_H 2 | #define FMTYPE_H 3 | 4 | #define FMNULL ((void*)0) 5 | 6 | #define FMASSERT(cd) if(!(cd)){while(1);} 7 | 8 | #endif -------------------------------------------------------------------------------- /sample2/common/fmvoice.c: -------------------------------------------------------------------------------- 1 | // fmvoice.c 2 | #include "fmtype.h" 3 | #include "fmvoice.h" 4 | #include "fmtone.h" 5 | #include "fmnote.h" 6 | #include "fmsd1.h" 7 | #include "fmpart.h" 8 | #include "fmboard.h" 9 | 10 | // setter 11 | void Fmvoice_setVoiceNum( Fmvoice* _this, unsigned char vn ){ _this->_vnum = vn; } 12 | void Fmvoice_setNextVc( Fmvoice* _this, Fmvoice* vc ){ _this->_nextVc = vc; } 13 | 14 | // getter 15 | unsigned char Fmvoice_vnum( Fmvoice* _this ){ return _this->_vnum; } 16 | bool Fmvoice_isKeyon( Fmvoice* _this ){ return _this->_keyon;} 17 | Fmvoice* Fmvoice_nextVc( Fmvoice* _this ){ return _this->_nextVc; } 18 | 19 | #ifdef ARDUINO 20 | static const unsigned short PROGMEM tPitTbl[256] = { 21 | #else 22 | static const unsigned short tPitTbl[256] = { 23 | #endif 24 | 256,257,259,260,262,263,264,266,267,269,270,272,273,275,276,278, 25 | 279,281,282,284,285,287,288,290,292,293,295,296,298,300,301,303, 26 | 304,306,308,309,311,313,314,316,318,320,321,323,325,327,328,330, 27 | 332,334,336,337,339,341,343,345,347,349,350,352,354,356,358,360, 28 | 362,364,366,368,370,372,374,376,378,380,382,384,386,388,391,393, 29 | 395,397,399,401,403,406,408,410,412,415,417,419,421,424,426,428, 30 | 431,433,435,438,440,442,445,447,450,452,454,457,459,462,464,467, 31 | 470,472,475,477,480,482,485,488,490,493,496,498,501,504,506,509, 32 | 512,515,518,520,523,526,529,532,535,538,540,543,546,549,552,555, 33 | 558,561,564,567,571,574,577,580,583,586,589,593,596,599,602,606, 34 | 609,612,616,619,622,626,629,632,636,639,643,646,650,653,657,660, 35 | 664,668,671,675,679,682,686,690,693,697,701,705,709,712,716,720, 36 | 724,728,732,736,740,744,748,752,756,760,764,769,773,777,781,785, 37 | 790,794,798,803,807,811,816,820,825,829,834,838,843,847,852,856, 38 | 861,866,870,875,880,885,890,894,899,904,909,914,919,924,929,934, 39 | 939,944,949,954,960,965,970,975,981,986,991,997,1002,1007,1013,1023 40 | }; 41 | #ifdef ARDUINO 42 | static const unsigned short PROGMEM tFreq[240] = { 43 | #else 44 | static const unsigned short tFreq[240] = { 45 | #endif 46 | 347,348,349,350,351,352,353,354,355,356, 357,358,359,360,361,362,363,365,366,367, 47 | 368,369,370,371,372,373,374,375,376,377, 378,380,381,382,383,384,385,386,387,388, 48 | 390,391,392,393,394,395,396,397,399,400, 401,402,403,404,406,407,408,409,410,412, 49 | 413,414,415,416,417,419,420,421,422,424, 425,426,427,428,430,431,432,433,435,436, 50 | 437,439,440,441,442,444,445,446,447,449, 450,451,453,454,455,457,458,459,461,462, 51 | 463,465,466,467,469,470,471,473,474,475, 477,478,480,481,482,484,485,487,488,489, 52 | 491,492,494,495,496,498,499,501,502,504, 505,507,508,510,511,513,514,515,517,518, 53 | 520,521,523,524,526,528,529,531,532,534, 535,537,538,540,541,543,545,546,548,549, 54 | 551,552,554,556,557,559,561,562,564,565, 567,569,570,572,574,575,577,579,580,582, 55 | 584,585,587,589,590,592,594,596,597,599, 601,602,604,606,608,609,611,613,615,617, 56 | 618,620,622,624,626,627,629,631,633,635, 636,638,640,642,644,646,648,649,651,653, 57 | 655,657,659,661,663,665,667,668,670,672, 674,676,678,680,682,684,686,688,690,692 58 | }; 59 | void Fmvoice_init( Fmvoice* _this ) 60 | { 61 | _this->_keyon = (false); 62 | _this->_nextVc = FMNULL; 63 | } 64 | void Fmvoice_keyon( Fmvoice* _this, void* nt, void* pt, void* tn, unsigned char note, unsigned char vel ) 65 | { 66 | Part* ptp = (Part*)pt; 67 | 68 | _this->_parent = nt; 69 | _this->_keyon = true; 70 | _this->_nextVc = FMNULL; 71 | 72 | // set voice number 73 | writeSingle( 11, _this->_vnum ); 74 | 75 | // Damp 76 | writeSingle( REG_TOP_ADRS+REG_CTRL, 0x30 ); 77 | 78 | // FNUM,BLOCK 79 | Fmvoice_setBasicPit( _this, note ); 80 | 81 | // Vol 82 | writeSingle( REG_TOP_ADRS+REG_VOL, vel&0xfc ); 83 | 84 | // ChVol 85 | writeSingle( REG_TOP_ADRS+REG_CH_VOL, 0x71 ); 86 | 87 | // XVB 88 | Fmvoice_chgVibDpt(_this, Part_cc1(ptp)); 89 | 90 | // INT, FRAC 91 | Fmvoice_chgPit(_this, Part_pb(ptp)); 92 | 93 | // KeyOn, ToneNum 94 | writeSingle( REG_TOP_ADRS+REG_CTRL, 0x40 + Part_toneNumber(ptp) ); 95 | } 96 | void Fmvoice_keyoff( Fmvoice* _this ) 97 | { 98 | _this->_keyon = false; 99 | writeSingle( 11, _this->_vnum ); 100 | writeSingle( REG_TOP_ADRS+REG_CTRL, 0 ); 101 | } 102 | void Fmvoice_release( Fmvoice* _this ) 103 | { 104 | _this->_keyon = false; 105 | if ( _this->_parent != FMNULL ){ 106 | Note* nt = (Note*)_this->_parent; 107 | Note_releaseVc(nt,_this); 108 | } 109 | _this->_nextVc = FMNULL; 110 | 111 | writeSingle( 11, _this->_vnum ); 112 | writeSingle( REG_TOP_ADRS+REG_CTRL, 0x30 ); 113 | } 114 | void Fmvoice_chgPit( Fmvoice* _this, unsigned short pb ) 115 | { 116 | unsigned char reg[2]; 117 | unsigned char pit = pb/64; 118 | #ifdef ARDUINO 119 | unsigned short pitTableData = pgm_read_word_near(tPitTbl + pit); 120 | reg[1] = (unsigned char)((pitTableData<<1) & 0x007e); 121 | reg[0] = (unsigned char)(((pitTableData<<2) & 0x1f00)>>8); 122 | #else 123 | reg[1] = (unsigned char)((tPitTbl[pit]<<1) & 0x007e); 124 | reg[0] = (unsigned char)(((tPitTbl[pit]<<2) & 0x1f00)>>8); 125 | #endif 126 | 127 | writeSingle( 11, _this->_vnum ); 128 | writeSingle( REG_TOP_ADRS+REG_INT, reg[0] ); 129 | writeSingle( REG_TOP_ADRS+REG_FRC, reg[1] ); 130 | } 131 | void Fmvoice_chgVibDpt( Fmvoice* _this, unsigned char vibDpt ) 132 | { 133 | vibDpt = vibDpt >>4; 134 | if ( vibDpt == 0 ){ vibDpt = 1;} 135 | writeSingle( 11, _this->_vnum ); 136 | writeSingle( REG_TOP_ADRS+REG_XVB, vibDpt ); 137 | } 138 | void Fmvoice_setBasicPit( Fmvoice* _this, unsigned char note ) 139 | { 140 | signed short realNote = note; 141 | while ( realNote > 128 ){ realNote -= 12;} 142 | while ( realNote < 0 ){ realNote += 12;} 143 | 144 | int tblIndex = (realNote % 12) * 20; 145 | 146 | unsigned char reg[2]; 147 | #ifdef ARDUINO 148 | unsigned short fr = pgm_read_word_near(tFreq + tblIndex); 149 | #else 150 | unsigned short fr = tFreq[tblIndex]; 151 | #endif 152 | unsigned char oct = realNote/12 - 1; 153 | reg[0] = (unsigned char)(((fr & 0x0380)>>4) | oct); 154 | reg[1] = (unsigned char)(fr & 0x007f); 155 | 156 | writeSingle( 11, _this->_vnum ); 157 | writeSingle( REG_TOP_ADRS+REG_BLK, reg[0] ); 158 | writeSingle( REG_TOP_ADRS+REG_FNUM, reg[1] ); 159 | } -------------------------------------------------------------------------------- /sample2/common/fmvoice.h: -------------------------------------------------------------------------------- 1 | #ifndef FMVOICE_H 2 | #define FMVOICE_H 3 | #include 4 | 5 | // Fmvoice Class 6 | typedef struct _Fmvoice Fmvoice; 7 | struct _Fmvoice { 8 | unsigned char _vnum; 9 | bool _keyon; 10 | Fmvoice* _nextVc; 11 | void* _parent; 12 | }; 13 | 14 | // public 15 | extern void Fmvoice_init( Fmvoice* _this ); 16 | extern void Fmvoice_keyon( Fmvoice* _this, void* nt, void* pt, void* tn, unsigned char note, unsigned char vel ); 17 | extern void Fmvoice_keyoff( Fmvoice* _this ); 18 | extern void Fmvoice_release( Fmvoice* _this ); 19 | extern void Fmvoice_chgVibDpt( Fmvoice* _this, unsigned char vibDpt ); 20 | extern void Fmvoice_chgPit( Fmvoice* _this, unsigned short pb ); 21 | extern void Fmvoice_setBasicPit( Fmvoice* _this, unsigned char note ); 22 | 23 | // setter 24 | extern void Fmvoice_setVoiceNum( Fmvoice* _this, unsigned char vn ); 25 | extern void Fmvoice_setNextVc( Fmvoice* _this, Fmvoice* vc ); 26 | 27 | // getter 28 | extern unsigned char Fmvoice_vnum( Fmvoice* _this ); 29 | extern bool Fmvoice_isKeyon( Fmvoice* _this ); 30 | extern Fmvoice* Fmvoice_nextVc( Fmvoice* _this ); 31 | #endif -------------------------------------------------------------------------------- /sample2/raspi/fmboard.h: -------------------------------------------------------------------------------- 1 | #define RASPI 2 | -------------------------------------------------------------------------------- /sample2/raspi/fmsd1_raspi.c: -------------------------------------------------------------------------------- 1 | // fmsd1_raspi.c 2 | #include 3 | #include 4 | #include 5 | 6 | #define PIN_OUT RPI_V2_GPIO_P1_22 7 | #define RST RPI_V2_GPIO_P1_36 8 | 9 | void ss(int en) 10 | { 11 | if (en == HIGH){ bcm2835_gpio_write(PIN_OUT, HIGH);} 12 | else { bcm2835_gpio_write(PIN_OUT, LOW);} 13 | } 14 | void writeSingle( unsigned char adrs, unsigned char data ) 15 | { 16 | ss(LOW); 17 | bcm2835_spi_transfer(adrs); 18 | bcm2835_spi_transfer(data); 19 | ss(HIGH); 20 | } 21 | void writeBurst( unsigned char adrs, unsigned char* data, int count ) 22 | { 23 | int i; 24 | ss(LOW); 25 | bcm2835_spi_transfer(adrs); 26 | for (i = 0; i