├── .gitignore ├── README.md ├── SSG ├── SSG.cpp ├── SSG.h ├── SSG.ino └── music.h └── doc ├── YM2149.pdf ├── YM2149_OCR.pdf ├── YM2151.pdf ├── YM2151_OCR.pdf ├── YM2203.pdf └── YM2203_OCR.pdf /.gitignore: -------------------------------------------------------------------------------- 1 | # Windows shortcuts 2 | *.lnk 3 | 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Arduino-YM-Sound-Chips 2 | Using Yamaha Sound Chips as Audio Device for Arduino 3 | 4 | 5 | ### The idea and the objectives 6 | The purpose of this project is to provide an Arduino compatible library, very simple to use and with the minimum need of additional components to work with oldschool Yamaha Sound Chips. 7 | The library does not aim to use the sound chips to their full potential, but rather to allow their use in third-party projects without difficulty. 8 |
9 | 10 | If you are interested about more advanced use of the YM2149 (SSG) chip, like streaming, reading SNDH files, I recommend the work of [![FlorentFlament](https://avatars2.githubusercontent.com/u/6681007?s=20&v=4) FlorentFlament](https://github.com/FlorentFlament) : 11 | * [FlorentFlament/ym2149-test](https://github.com/FlorentFlament/ym2149-test) 12 | * [FlorentFlament/ym2149-streamer](https://github.com/FlorentFlament/ym2149-streamer) 13 | * [FlorentFlament/ym2149-sndh](https://github.com/FlorentFlament/ym2149-sndh) 14 | 15 | These works really help me at the beginning of the project. 16 | 17 | 18 | ## State of progress 19 | 20 | | Sound Chip | Work in progress | Works | 21 | | ------------ | :--------------: | :---: | 22 | | YM2149 (SSG) | :white_circle: | :white_check_mark: | 23 | | YM2203 (OPN) | :white_check_mark: | :x: | 24 | | YM2151 (OPM) | :x: | :x: | 25 | 26 | 27 | ## Stage of work in progress 28 | 29 | | Sound Chip | Write to chip | Music (A/B/C) | Noise | Mixer | Level control | Envelope | 30 | | ------------ | :-----------: | :-----------: | :---: | :---: | :-----------: | :------: | 31 | | YM2149 (SSG) | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | 32 | 33 | | Sound Chip | OPN as SSG | 34 | | ------------ | :--------: | 35 | | YM2203 (OPN) | :x: | 36 | 37 | 38 | ## Yamaha sound chips cheat sheet 39 | 40 | ### Sound chips list 41 | 42 | | Sound Chip | Common name | Other chip required | Do I have it ? | 43 | | :--------: | :---------: | :-----------------: | :--------------------: | 44 | | YM2149F | SSG | :white_circle: | :white_check_mark: | 45 | | | | | | 46 | | YM3526 | OPL | YM3014 | Awaiting delivery | 47 | | YM2413 | OPLL | | Awaiting delivery | 48 | | Y8950 | MSX-AUDIO | YM3014 | :x: | 49 | | YM3812 | OPL2 | YM3014 | Awaiting delivery | 50 | | YMF262 | OPL3 | YAC512 | :x: | 51 | | YMF289 | OPL3-L | :grey_question: | :x: | 52 | | YMF278 | OPL4 | :grey_question: | :x: | 53 | | | | | | 54 | | YM2203 | OPN | YM3014 | :white_check_mark: | 55 | | YM2608 | OPNA | YM3016 | Awaiting delivery | 56 | | YM2610 | OPNB | YM3016 | Awaiting delivery | 57 | | YM2612 | OPN2 | | :x: | 58 | | YM3438 | OPN2C | | Awaiting delivery | 59 | | YMF276 | OPN2L | DAC :grey_question: | :x: | 60 | | YMF288 | OPN3 | DAC :grey_question: | :x: | 61 | | | | | | 62 | | YM2151 | OPM | YM3012 | :white_check_mark: | 63 | | YM2164 | OPP | YM3012 :grey_question: | :x::heavy_dollar_sign: | 64 | | YM2154 | RYP4 | :grey_question: | :x: | 65 | | YM2414 | OPZ | :grey_question: | :x: | 66 | 67 | 68 | 69 | ### Accessory chips list 70 | 71 | | Chip | Other name | Usage | Do I have it ? | 72 | | :--------: | :---------: | :--------: | :----------------: | 73 | | YM3014 | Y3014B | DAC | :white_check_mark: | 74 | | YAC512 | | DAC | :x: | 75 | | YM3016 | YM3016-D | DAC | Awaiting delivery | 76 | | YM3012 | | DAC | :white_check_mark: | 77 | 78 | 79 | ## Play Songs 80 | 81 | To play and store a song, we have to convert a music score into C arrays which can be interpreted by the program. 82 | A Python script to transform a channel from a midi file into an array will be available soon. 83 | 84 | ### SSG 85 | 86 | At first, a song is loaded, then we need to call an update function (song_next_iteration()) to update the SSG register. 87 | For now, we want an SSG song to command the following elements. 88 | 89 | * 3 square wave channel (note and duration) 90 | * 1 noise (frequency and duration) 91 | 92 | For each channel, we use two arrays, one for note and one for duration. 93 | The note array is read when the previous note has finished and we update the channel frequency with it's information. If value is 0, the channel is muted 94 | The duration array is read when the previous note has finished and we update the couter (which is decremented every time the update function is called) with the value in the duration array. 95 | For memory reason, we use char (8 bits) to store thoses information, but if a duration is longer than 255 call, we can use a word (16 bits) using 3 cases of the array, one for a 0 flag and two for 16 bits duration. 96 | 97 | ``` 98 | {0, 0x01, 0x90} // 400 call duration. 99 | ``` 100 | 101 | The tempo is set by the delay between each call to the update function. For this reason, the duration has no absolute relation with "note value", if the update is called 4 times per BPM, a "4" duration is a 𝅘𝅥 but if the update is called 8 times per BPM, it's a 𝅘𝅥𝅮. 102 | 103 | In our future example, we use the following table as default 104 | 105 | | Duration | Equivalent in note value | 106 | | :---------: | :----------------------: | 107 | | 1 | 𝅘𝅥𝅲 | 108 | | 2 | 𝅘𝅥𝅱 | 109 | | 4 | 𝅘𝅥𝅰 | 110 | | 8 | 𝅘𝅥𝅯 | 111 | | 16 | 𝅘𝅥𝅮 | 112 | | 32 | 𝅘𝅥 | 113 | | 48 | 𝅘𝅥. | 114 | | 64 | 𝅗𝅥 | 115 | | 96 | 𝅗𝅥. | 116 | | 128 | 𝅝 | 117 | | 256 (0,1,0) | 𝅝𝆊𝅝 | 118 | -------------------------------------------------------------------------------- /SSG/SSG.cpp: -------------------------------------------------------------------------------- 1 | #include "SSG.h" 2 | 3 | SSG::SSG() 4 | { 5 | pinMode(DA0, OUTPUT); 6 | pinMode(DA1, OUTPUT); 7 | pinMode(DA2, OUTPUT); 8 | pinMode(DA3, OUTPUT); 9 | pinMode(DA4, OUTPUT); 10 | pinMode(DA5, OUTPUT); 11 | pinMode(DA6, OUTPUT); 12 | pinMode(DA7, OUTPUT); 13 | 14 | pinMode(BC1, OUTPUT); 15 | pinMode(BC2, OUTPUT); 16 | pinMode(BDIR, OUTPUT); 17 | 18 | digitalWrite(DA0, LOW); 19 | digitalWrite(DA1, LOW); 20 | digitalWrite(DA2, LOW); 21 | digitalWrite(DA3, LOW); 22 | digitalWrite(DA4, LOW); 23 | digitalWrite(DA5, LOW); 24 | digitalWrite(DA6, LOW); 25 | digitalWrite(DA7, LOW); 26 | 27 | digitalWrite(BC1, LOW); 28 | digitalWrite(BC2, LOW); 29 | digitalWrite(BDIR, LOW); 30 | 31 | unsigned int i; 32 | 33 | for(i=0; i<16; i++) { 34 | write_data(i, 0); 35 | } 36 | 37 | // Default settings 38 | mixer_status = 0b11111000; 39 | 40 | write_data(7, mixer_status); 41 | 42 | write_data(8, 0x0f); 43 | write_data(9, 0x0f); 44 | write_data(0xA, 0x0f); 45 | } 46 | 47 | word SSG::note_to_YM(word note, word octave) 48 | { 49 | return round(fMaster / (16*pgm_read_float(¬e_frequency[note][octave]))); 50 | } 51 | 52 | void SSG::set_mode_inactive() 53 | { 54 | digitalWrite(BC1, HIGH); 55 | digitalWrite(BC2, LOW); 56 | digitalWrite(BDIR, HIGH); 57 | } 58 | 59 | void SSG::set_mode_write() 60 | { 61 | digitalWrite(BC1, LOW); 62 | digitalWrite(BC2, HIGH); 63 | digitalWrite(BDIR, HIGH); 64 | } 65 | 66 | void SSG::set_mode_address() 67 | { 68 | digitalWrite(BC1, HIGH); 69 | digitalWrite(BC2, HIGH); 70 | digitalWrite(BDIR, HIGH); 71 | } 72 | 73 | void SSG::set_address(char address) 74 | { 75 | set_mode_address(); 76 | delayMicroseconds(us_delay); 77 | 78 | // write address 79 | delayMicroseconds(us_delay); 80 | digitalWrite(DA0, (address & 0b00000001)); 81 | digitalWrite(DA1, (address & 0b00000010)); 82 | digitalWrite(DA2, (address & 0b00000100)); 83 | digitalWrite(DA3, (address & 0b00001000)); 84 | digitalWrite(DA4, 0); 85 | digitalWrite(DA5, 0); 86 | digitalWrite(DA6, 0); 87 | digitalWrite(DA7, 0); 88 | delayMicroseconds(us_delay); 89 | 90 | set_mode_inactive(); 91 | delayMicroseconds(100); 92 | } 93 | 94 | void SSG::set_data(char data) 95 | { 96 | set_mode_write(); 97 | delayMicroseconds(us_delay); 98 | 99 | // write data 100 | delayMicroseconds(100); 101 | digitalWrite(DA0, (data & 0b00000001)); 102 | digitalWrite(DA1, (data & 0b00000010)); 103 | digitalWrite(DA2, (data & 0b00000100)); 104 | digitalWrite(DA3, (data & 0b00001000)); 105 | digitalWrite(DA4, (data & 0b00010000)); 106 | digitalWrite(DA5, (data & 0b00100000)); 107 | digitalWrite(DA6, (data & 0b01000000)); 108 | digitalWrite(DA7, (data & 0b10000000)); 109 | delayMicroseconds(us_delay); 110 | 111 | set_mode_inactive(); 112 | delayMicroseconds(us_delay); 113 | } 114 | 115 | void SSG::write_data(char address, char data) 116 | { 117 | set_address(address); 118 | set_data(data); 119 | } 120 | 121 | void SSG::set_chan_frequency(word note, word octave, char chan) 122 | { 123 | word fT = note_to_YM(note, octave); 124 | 125 | if(chan & chanA) 126 | { 127 | write_data(0, (fT & 0xff)); 128 | write_data(1, (fT >> 8)); 129 | } 130 | if(chan & chanB) 131 | { 132 | write_data(2, (fT & 0xff)); 133 | write_data(3, (fT >> 8)); 134 | } 135 | if(chan & chanC) 136 | { 137 | write_data(4, (fT & 0xff)); 138 | write_data(5, (fT >> 8)); 139 | } 140 | } 141 | 142 | void SSG::set_chan_frequency_null(char chan) 143 | { 144 | if(chan & chanA) 145 | { 146 | write_data(0, 0); 147 | write_data(1, 0); 148 | } 149 | if(chan & chanB) 150 | { 151 | write_data(2, 0); 152 | write_data(3, 0); 153 | } 154 | if(chan & chanC) 155 | { 156 | write_data(4, 0); 157 | write_data(5, 0); 158 | } 159 | } 160 | 161 | void SSG::set_chanA_frequency(int note, int octave) 162 | { 163 | set_chan_frequency(note, octave, chanA); 164 | } 165 | 166 | void SSG::set_chanB_frequency(int note, int octave) 167 | { 168 | set_chan_frequency(note, octave, chanB); 169 | } 170 | 171 | void SSG::set_chanC_frequency(int note, int octave) 172 | { 173 | set_chan_frequency(note, octave, chanC); 174 | } 175 | 176 | void SSG::set_chan_level(char level, char chan = 7) 177 | { 178 | if(level > 0b1111) 179 | level = 0x0f; 180 | else 181 | level &= ~(1 << 4); 182 | 183 | if(chan & chanA) 184 | { 185 | write_data(8, level); 186 | } 187 | if(chan & chanB) 188 | { 189 | write_data(9, level); 190 | } 191 | if(chan & chanC) 192 | { 193 | write_data(0xA, level); 194 | } 195 | } 196 | 197 | void SSG::set_chan_level_null(char chan = 7) 198 | { 199 | set_chan_level(0, chan); 200 | } 201 | 202 | void SSG::set_chanA_level(char level) 203 | { 204 | set_chan_level(level, chanA); 205 | } 206 | 207 | void SSG::set_chanB_level(char level) 208 | { 209 | set_chan_level(level, chanB); 210 | } 211 | 212 | void SSG::set_chanC_level(char level) 213 | { 214 | set_chan_level(level, chanC); 215 | } 216 | 217 | void SSG::set_noise_frequency(char NP) 218 | { 219 | // Noise frequency (fN) is obtained with this formula : 220 | // fN = fMaster / (16*NP) 221 | // NP is a 5 bit value 222 | write_data(6, (NP & 0b00011111)); 223 | } 224 | 225 | void SSG::set_chan_mixer(bool music, bool noise, char chan) 226 | { 227 | if(chan & chanA) 228 | { 229 | if(music) 230 | mixer_status &= ~(1 << 0); 231 | else 232 | mixer_status |= 1 << 0; 233 | 234 | if(noise) 235 | mixer_status &= ~(1 << 3); 236 | else 237 | mixer_status |= 1 << 3; 238 | } 239 | if(chan & chanB) 240 | { 241 | if(music) 242 | mixer_status &= ~(1 << 1); 243 | else 244 | mixer_status |= 1 << 1; 245 | 246 | if(noise) 247 | mixer_status &= ~(1 << 4); 248 | else 249 | mixer_status |= 1 << 4; 250 | } 251 | if(chan & chanC) 252 | { 253 | if(music) 254 | mixer_status &= ~(1 << 2); 255 | else 256 | mixer_status |= 1 << 2; 257 | 258 | if(noise) 259 | mixer_status &= ~(1 << 5); 260 | else 261 | mixer_status |= 1 << 5; 262 | } 263 | 264 | write_data(7, mixer_status); 265 | } 266 | 267 | void SSG::set_chan_mixer_mute(char chan) 268 | { 269 | set_chan_mixer(false, false, chan); 270 | } 271 | 272 | void SSG::set_chanA_mixer(bool music, bool noise) 273 | { 274 | set_chan_mixer(music, noise, chanA); 275 | } 276 | 277 | void SSG::set_chanB_mixer(bool music, bool noise) 278 | { 279 | set_chan_mixer(music, noise, chanB); 280 | } 281 | 282 | void SSG::set_chanC_mixer(bool music, bool noise) 283 | { 284 | set_chan_mixer(music, noise, chanC); 285 | } 286 | 287 | void SSG::set_envelope_frequency(word EP) 288 | { 289 | // Envelope repetition frequency (fE) is obtained with this formula : 290 | // fE = fMaster / (256*EP) 291 | // EP is a 16 bit value 292 | // The period of the actual frequency fE used for the envelope 293 | // generated is 1/32 of the envelope repetition period (1/fE) 294 | // Check the YM2149 datasheet page 7 for more informations. 295 | 296 | write_data(0xB, (EP & 0xff)); 297 | write_data(0xC, (EP >> 8)); 298 | } 299 | 300 | void SSG::set_envelope_shape(bool cont, bool att, bool alt, bool hold) 301 | { 302 | // Check the YM2149 datasheet page 7 and 8 to view the 10 envelope possible shapes. 303 | word RD = 0; 304 | 305 | if(cont) 306 | RD |= 1 << 3; 307 | if(att) 308 | RD |= 1 << 2; 309 | if(alt) 310 | RD |= 1 << 1; 311 | if(hold) 312 | RD |= 1; 313 | 314 | write_data(0xD, RD); 315 | } 316 | 317 | void SSG::set_chan_use_envelope(char chan) 318 | { 319 | if(chan & chanA) 320 | { 321 | write_data(8, 0x1f); 322 | } 323 | if(chan & chanB) 324 | { 325 | write_data(9, 0x1f); 326 | } 327 | if(chan & chanC) 328 | { 329 | write_data(0xA, 0x1f); 330 | } 331 | } 332 | 333 | void SSG::set_chanA_use_envelope() 334 | { 335 | set_chan_use_envelope(chanA); 336 | } 337 | 338 | void SSG::set_chanB_use_envelope() 339 | { 340 | set_chan_use_envelope(chanB); 341 | } 342 | 343 | void SSG::set_chanC_use_envelope() 344 | { 345 | set_chan_use_envelope(chanC); 346 | } 347 | -------------------------------------------------------------------------------- /SSG/SSG.h: -------------------------------------------------------------------------------- 1 | #ifndef SSG_H 2 | #define SSG_H 3 | 4 | #include "Arduino.h" 5 | 6 | // Include notes frequencies 7 | #include "music.h" 8 | 9 | // Define IO pinout 10 | #define DA0 5 11 | #define DA1 6 12 | #define DA2 7 13 | #define DA3 8 14 | #define DA4 9 15 | #define DA5 10 16 | #define DA6 11 17 | #define DA7 12 18 | #define BC1 4 19 | #define BC2 3 20 | #define BDIR 2 21 | 22 | // Delay in microseconds we allow the chip to react after mode changes or register access 23 | #define us_delay 100 24 | 25 | // We use a 4Mhz crystal oscillator and set /SEL to low, the input clock is divided by 2 and equal 2Mhz 26 | #define fMaster 2000000 27 | 28 | // channels for SSG::set_chan_frequency 29 | #define chanA 0b001 30 | #define chanB 0b010 31 | #define chanC 0b100 32 | 33 | class SSG 34 | { 35 | public: 36 | SSG(); 37 | 38 | // Music 39 | void set_chan_frequency(word note, word octave, char chan = 7); 40 | void set_chan_frequency_null(char chan = 7); 41 | void set_chanA_frequency(int note, int octave); 42 | void set_chanB_frequency(int note, int octave); 43 | void set_chanC_frequency(int note, int octave); 44 | 45 | // Level control 46 | // Using the level control, you disable the use of the envelope 47 | void set_chan_level(char level, char chan = 7); 48 | void set_chan_level_null(char chan = 7); 49 | void set_chanA_level(char level); 50 | void set_chanB_level(char level); 51 | void set_chanC_level(char level); 52 | 53 | // Noise 54 | void set_noise_frequency(char NP); 55 | 56 | // Mixer 57 | void set_chan_mixer(bool music, bool noise, char chan = 7); 58 | void set_chan_mixer_mute(char chan = 7); 59 | void set_chanA_mixer(bool music, bool noise); 60 | void set_chanB_mixer(bool music, bool noise); 61 | void set_chanC_mixer(bool music, bool noise); 62 | 63 | // Envelope 64 | // To use the the envelope, you need to enable it on channels 65 | void set_envelope_frequency(word EP); 66 | void set_envelope_shape(bool cont, bool att, bool alt, bool hold); 67 | void set_chan_use_envelope(char chan = 7); 68 | void set_chanA_use_envelope(); 69 | void set_chanB_use_envelope(); 70 | void set_chanC_use_envelope(); 71 | 72 | private: 73 | // convert note and octave into a word 74 | word note_to_YM(word note, word octave); 75 | 76 | // Modes 77 | /* We only use 3 possible state of BC1, BC2, BDIR combination. 78 | * 79 | * | BC1 | BC2 | BDIR | 80 | * Inactive | 1 | 0 | 1 | 81 | * Write | 0 | 1 | 1 | 82 | * Address | 1 | 1 | 1 | 83 | * 84 | * We could remove the digitalWrite(BDIR, HIGH), 85 | * but we still keep it if we want to use the read functions. 86 | */ 87 | void set_mode_inactive(); 88 | void set_mode_write(); 89 | void set_mode_address(); 90 | 91 | // Write 92 | void set_address(char address); 93 | void set_data(char data); 94 | void write_data(char address, char data); 95 | 96 | // Mixer current status 97 | char mixer_status; 98 | }; 99 | 100 | #endif 101 | -------------------------------------------------------------------------------- /SSG/SSG.ino: -------------------------------------------------------------------------------- 1 | #include "SSG.h" 2 | 3 | SSG ssg; 4 | 5 | /* Same as delay(d) (or delay(d-1) if d%2 == 1 6 | * Make the builtin led blink on half the time of the delay 7 | */ 8 | void delay_blink(unsigned long d) 9 | { 10 | unsigned long d_2 = d / 2; 11 | 12 | digitalWrite(LED_BUILTIN, HIGH); 13 | delay(d_2); 14 | digitalWrite(LED_BUILTIN, LOW); 15 | delay(d_2); 16 | } 17 | 18 | void setup() { 19 | unsigned int i; 20 | Serial.begin(115200); 21 | pinMode(LED_BUILTIN, OUTPUT); 22 | digitalWrite(LED_BUILTIN, LOW); 23 | } 24 | 25 | void loop() { 26 | unsigned int i; 27 | 28 | // 1 - Test Music 29 | 30 | ssg.set_chan_level(0b1111, chanA | chanB | chanC); 31 | ssg.set_chan_mixer_mute(chanA | chanB | chanC); 32 | ssg.set_chan_mixer(true, false, chanA); 33 | 34 | for(i = 1; i < 6; ++i) 35 | { 36 | ssg.set_chanA_frequency(C, i); 37 | delay_blink(200); 38 | ssg.set_chanA_frequency(D, i); 39 | delay_blink(200); 40 | ssg.set_chanA_frequency(E, i); 41 | delay_blink(200); 42 | ssg.set_chanA_frequency(F, i); 43 | delay_blink(200); 44 | ssg.set_chanA_frequency(G, i); 45 | delay_blink(200); 46 | ssg.set_chanA_frequency(A, i); 47 | delay_blink(200); 48 | ssg.set_chanA_frequency(B, i); 49 | delay_blink(200); 50 | } 51 | ssg.set_chan_mixer(true, false, chanA | chanB | chanC); 52 | 53 | ssg.set_chanA_frequency(C, 3); 54 | ssg.set_chanB_frequency(E, 4); 55 | ssg.set_chanC_frequency(G, 5); 56 | delay_blink(1000); 57 | 58 | ssg.set_chan_frequency(C, 4, chanA | chanB | chanC); 59 | delay_blink(1000); 60 | 61 | ssg.set_chanA_frequency(C, 4); 62 | ssg.set_chanB_frequency(E, 5); 63 | ssg.set_chanC_frequency(G, 6); 64 | delay_blink(1000); 65 | 66 | 67 | // 2 - Noise and Mixer 68 | ssg.set_noise_frequency(0b01111); 69 | delay_blink(1000); 70 | 71 | ssg.set_chanA_mixer(false, true); 72 | delay_blink(1000); 73 | ssg.set_chanB_mixer(false, true); 74 | delay_blink(1000); 75 | ssg.set_chanC_mixer(false, true); 76 | delay_blink(1000); 77 | 78 | ssg.set_noise_frequency(0b11111); 79 | delay_blink(1000); 80 | 81 | ssg.set_chan_mixer(false, false, chanA | chanB | chanC); 82 | delay_blink(1000); 83 | ssg.set_chanA_mixer(true, false); 84 | ssg.set_chanB_mixer(false, false); 85 | ssg.set_chanC_mixer(false, false); 86 | delay_blink(1000); 87 | 88 | 89 | // 3 - Test Level 90 | 91 | ssg.set_chanA_level(0b1111); 92 | ssg.set_chanA_frequency(A, 4); 93 | delay_blink(1000); 94 | 95 | for(i = 0; i < 0b1111; ++i) 96 | { 97 | ssg.set_chanA_level(i); 98 | delay_blink(200); 99 | } 100 | 101 | 102 | // 4 - Test Envelope 103 | 104 | ssg.set_envelope_shape(true, false, true, false); 105 | ssg.set_chanA_use_envelope(); 106 | 107 | ssg.set_envelope_frequency(32); 108 | delay_blink(1000); 109 | 110 | ssg.set_envelope_frequency(64); 111 | delay_blink(1000); 112 | 113 | ssg.set_envelope_frequency(128); 114 | delay_blink(1000); 115 | 116 | ssg.set_envelope_frequency(256); 117 | delay_blink(1000); 118 | 119 | ssg.set_envelope_frequency(512); 120 | delay_blink(1000); 121 | 122 | ssg.set_envelope_frequency(1024); 123 | delay_blink(1000); 124 | 125 | ssg.set_envelope_frequency(2048); 126 | delay_blink(1000); 127 | 128 | 129 | ssg.set_envelope_shape(false, false, false, false); 130 | ssg.set_chanA_use_envelope(); 131 | 132 | ssg.set_envelope_frequency(512); 133 | delay_blink(1000); 134 | 135 | ssg.set_envelope_shape(false, true, false, false); 136 | ssg.set_chanA_use_envelope(); 137 | 138 | ssg.set_envelope_frequency(512); 139 | delay_blink(1000); 140 | 141 | 142 | ssg.set_envelope_shape(true, false, false, false); 143 | ssg.set_chanA_use_envelope(); 144 | 145 | ssg.set_envelope_frequency(32); 146 | delay_blink(1000); 147 | 148 | ssg.set_envelope_frequency(64); 149 | delay_blink(1000); 150 | 151 | ssg.set_envelope_frequency(128); 152 | delay_blink(1000); 153 | 154 | ssg.set_envelope_frequency(256); 155 | delay_blink(1000); 156 | 157 | ssg.set_envelope_frequency(512); 158 | delay_blink(1000); 159 | 160 | ssg.set_envelope_frequency(1024); 161 | delay_blink(1000); 162 | 163 | ssg.set_envelope_frequency(2048); 164 | delay_blink(1000); 165 | } 166 | -------------------------------------------------------------------------------- /SSG/music.h: -------------------------------------------------------------------------------- 1 | #ifndef MUSIC_H 2 | #define MUSIC_H 3 | 4 | // Define notes places in frequency array 5 | #define C 0 6 | #define Cd 1 7 | 8 | #define Db 1 9 | #define D 2 10 | #define Dd 3 11 | 12 | #define Eb 3 13 | #define E 4 14 | 15 | #define F 5 16 | #define Fd 6 17 | 18 | #define Gb 6 19 | #define G 7 20 | #define Gd 8 21 | 22 | #define Ab 8 23 | #define A 9 24 | #define Ad 10 25 | 26 | #define Bb 10 27 | #define B 11 28 | 29 | // Define notes frequencies 30 | const float PROGMEM note_frequency[12][11] = { 31 | {16.35, 32.70, 65.41, 130.81, 261.63, 523.25, 1046.50, 2093.00, 4186.01, 8372.02, 16744.04}, 32 | {17.33, 34.65, 69.30, 138.59, 277.18, 554.37, 1108.73, 2217.46, 4434.92, 8869.84, 17739.68}, 33 | {18.36, 36.71, 73.42, 146.83, 293.66, 587.33, 1174.66, 2349.32, 4698.64, 9397.28, 18794.56}, 34 | {19.45, 38.89, 77.78, 155.56, 311.13, 622.25, 1244.51, 2489.02, 4978.03, 9956.06, 19912.12}, 35 | {20.60, 41.20, 82.41, 164.81, 329.63, 659.26, 1318.51, 2637.02, 5274.04, 10548.08, 21096.16}, 36 | {21.83, 43.65, 87.31, 174.61, 349.23, 698.46, 1396.91, 2793.83, 5587.65, 11175.30, 22350.60}, 37 | {23.13, 46.25, 92.50, 185.00, 369.99, 739.99, 1479.98, 2959.96, 5919.91, 11839.82, 23679.64}, 38 | {24.50, 49.00, 98.00, 196.00, 392.00, 783.99, 1567.98, 3135.96, 6271.93, 12543.86, 25087.72}, 39 | {25.96, 51.91, 103.83, 207.65, 415.30, 830.61, 1661.22, 3322.44, 6644.88, 13289.76, 26579.52}, 40 | {27.50, 55.00, 110.00, 220.00, 440.00, 880.00, 1760.00, 3520.00, 7040.00, 14080.00, 28160.00}, 41 | {29.14, 58.27, 116.54, 233.08, 466.16, 932.33, 1864.66, 3729.31, 7458.62, 14917.24, 29834.48}, 42 | {30.87, 61.74, 123.47, 246.94, 493.88, 987.77, 1975.53, 3951.07, 7902.13, 15804.26, 31608.52} 43 | }; 44 | 45 | #endif 46 | -------------------------------------------------------------------------------- /doc/YM2149.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Yt-trium/Arduino-YM-Sound-Chips/3911d55328540c379d8fb22cab646f89a9b0793b/doc/YM2149.pdf -------------------------------------------------------------------------------- /doc/YM2149_OCR.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Yt-trium/Arduino-YM-Sound-Chips/3911d55328540c379d8fb22cab646f89a9b0793b/doc/YM2149_OCR.pdf -------------------------------------------------------------------------------- /doc/YM2151.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Yt-trium/Arduino-YM-Sound-Chips/3911d55328540c379d8fb22cab646f89a9b0793b/doc/YM2151.pdf -------------------------------------------------------------------------------- /doc/YM2151_OCR.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Yt-trium/Arduino-YM-Sound-Chips/3911d55328540c379d8fb22cab646f89a9b0793b/doc/YM2151_OCR.pdf -------------------------------------------------------------------------------- /doc/YM2203.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Yt-trium/Arduino-YM-Sound-Chips/3911d55328540c379d8fb22cab646f89a9b0793b/doc/YM2203.pdf -------------------------------------------------------------------------------- /doc/YM2203_OCR.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Yt-trium/Arduino-YM-Sound-Chips/3911d55328540c379d8fb22cab646f89a9b0793b/doc/YM2203_OCR.pdf --------------------------------------------------------------------------------