Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of Sound_Generator by
piano4int.cpp
00001 /****************************************************************************** 00002 * DISCLAIMER 00003 * This software is supplied by Renesas Electronics Corporation and is only 00004 * intended for use with Renesas products. No other uses are authorized. This 00005 * software is owned by Renesas Electronics Corporation and is protected under 00006 * all applicable laws, including copyright laws. 00007 * THIS SOFTWARE IS PROVIDED "AS IS" AND RENESAS MAKES NO WARRANTIES REGARDING 00008 * THIS SOFTWARE, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING BUT NOT 00009 * LIMITED TO WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE 00010 * AND NON-INFRINGEMENT. ALL SUCH WARRANTIES ARE EXPRESSLY DISCLAIMED. 00011 * TO THE MAXIMUM EXTENT PERMITTED NOT PROHIBITED BY LAW, NEITHER RENESAS 00012 * ELECTRONICS CORPORATION NOR ANY OF ITS AFFILIATED COMPANIES SHALL BE LIABLE 00013 * FOR ANY DIRECT, INDIRECT, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES FOR 00014 * ANY REASON RELATED TO THIS SOFTWARE, EVEN IF RENESAS OR ITS AFFILIATES HAVE 00015 * BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 00016 * Renesas reserves the right, without notice, to make changes to this software 00017 * and to discontinue the availability of this software. By using this software, 00018 * you agree to the additional terms and conditions found by accessing the 00019 * following link: 00020 * http://www.renesas.com/disclaimer 00021 * Copyright (C) 2012 - 2015 Renesas Electronics Corporation. All 00022 * rights reserved. 00023 ******************************************************************************/ 00024 00025 /****************************************************************************** 00026 Includes <System Includes> , "Project Includes" 00027 ******************************************************************************/ 00028 #include <stdio.h> 00029 #include <ctype.h> 00030 #include <stdint.h> 00031 extern "C" { 00032 #include "iodefine.h" 00033 #include "dev_drv.h" 00034 #include "devdrv_sdg.h" 00035 } 00036 #include "mbed.h" 00037 #include "PinNames.h" 00038 00039 #include "piano4int.h" 00040 00041 /****************************************************************************** 00042 Macro definitions 00043 ******************************************************************************/ 00044 #define ASSERT( eval ) \ 00045 if (!(eval)) { \ 00046 printf( \ 00047 "%s: failed! at %d in %s\n", \ 00048 #eval, \ 00049 __LINE__, \ 00050 __FILE__); \ 00051 } 00052 00053 /* message to caller */ 00054 #define UNIT_MSG (32) 00055 00056 00057 /****************************************************************************** 00058 Typedef definitions 00059 ******************************************************************************/ 00060 /* a sound generator unit */ 00061 typedef struct { 00062 uint16_t speed; /* count of a tempo */ 00063 uint8_t loudness; /* current loudness */ 00064 uint16_t count; /* remain of time */ 00065 NOTE note; /* a next note */ 00066 const int8_t *score; /* a next score */ 00067 const int8_t *top; /* top of a score */ 00068 uint8_t channel; /* channel number */ 00069 #ifdef UNIT_MSG 00070 char msg[UNIT_MSG]; /* message */ 00071 #endif 00072 } UNIT; 00073 00074 00075 /****************************************************************************** 00076 Imported global variables and functions (from other files) 00077 ******************************************************************************/ 00078 00079 00080 /****************************************************************************** 00081 Exported global variables and functions (to be accessed by other files) 00082 ******************************************************************************/ 00083 00084 00085 /****************************************************************************** 00086 Private global variables and functions 00087 ******************************************************************************/ 00088 /* interrupt routine */ 00089 static void play_score(void); 00090 00091 00092 /* all work area for piano */ 00093 struct { 00094 UNIT unit[SDG_CH_TOTAL]; 00095 uint16_t fin; 00096 Ticker metronome; /* base tempo */ 00097 PIANO4INT_CB callback; 00098 } pianoT; 00099 00100 00101 /* init params for sound generator */ 00102 static const struct { 00103 uint16_t channel; 00104 R_SDG_CLOCK clock; 00105 } unitHW[SDG_CH_TOTAL] = { 00106 { DEVDRV_CH_0, R_SDG_CLOCK_4 }, 00107 { DEVDRV_CH_1, R_SDG_CLOCK_4 }, 00108 { DEVDRV_CH_2, R_SDG_CLOCK_4 }, 00109 { DEVDRV_CH_3, R_SDG_CLOCK_4 }, 00110 }; 00111 00112 00113 /* dummy entry of score (no sounds)*/ 00114 static const int8_t noscore[] = ""; 00115 00116 /* parameters of a rest */ 00117 static const NOTE rest4 = { 00118 0, /* tone */ 00119 0, /* sfs */ 00120 0, /* loud */ 00121 0, /* attenuation */ 00122 }; 00123 00124 00125 /* table of notes */ 00126 static const struct { 00127 uint8_t tone; 00128 uint8_t sfs; 00129 } note_timing[MAXOCTAVE][MAXNOTE] = { 00130 { /* octave 0 */ 00131 { 0, 0 }, /* -A */ 00132 { 0, 0 }, /* -A# */ 00133 { 0, 0 }, /* -B */ 00134 { 124, 255 }, /* -C */ 00135 { 117, 255 }, /* -C# */ 00136 { 111, 255 }, /* -D */ 00137 { 105, 255 }, /* -D# */ 00138 { 99, 255 }, /* -E */ 00139 { 93, 255 }, /* -F */ 00140 { 88, 255 }, /* -F# */ 00141 { 83, 255 }, /* -G */ 00142 { 78, 255 }, /* -G# */ 00143 { 0, 0 }, /* -R */ 00144 }, 00145 { /* octave 1 */ 00146 { 86, 220 }, /* A */ 00147 { 81, 220 }, /* A# */ 00148 { 76, 220 }, /* B */ 00149 { 72, 220 }, /* C */ 00150 { 68, 220 }, /* C# */ 00151 { 64, 220 }, /* D */ 00152 { 60, 220 }, /* D# */ 00153 { 57, 220 }, /* E */ 00154 { 54, 220 }, /* F */ 00155 { 51, 220 }, /* F# */ 00156 { 48, 220 }, /* G */ 00157 { 45, 220 }, /* G# */ 00158 { 0, 0 }, /* R */ 00159 }, 00160 { /* octave 2 */ 00161 { 49, 190 }, /* +A */ 00162 { 47, 190 }, /* +A# */ 00163 { 44, 190 }, /* +B */ 00164 { 41, 190 }, /* +C */ 00165 { 39, 190 }, /* +C# */ 00166 { 37, 190 }, /* +D */ 00167 { 35, 190 }, /* +D# */ 00168 { 33, 190 }, /* +E */ 00169 { 31, 190 }, /* +F */ 00170 { 29, 190 }, /* +F# */ 00171 { 27, 190 }, /* +G */ 00172 { 26, 190 }, /* +G# */ 00173 { 0, 0 }, /* +R */ 00174 }, 00175 { /* octave 3 */ 00176 { 31, 150 }, /* *A */ 00177 { 29, 150 }, /* *A# */ 00178 { 28, 150 }, /* *B */ 00179 { 26, 150 }, /* *C */ 00180 { 25, 150 }, /* *C# */ 00181 { 23, 150 }, /* *D */ 00182 { 22, 150 }, /* *D# */ 00183 { 21, 150 }, /* *E */ 00184 { 19, 150 }, /* *F */ 00185 { 18, 150 }, /* *F# */ 00186 { 17, 150 }, /* *G */ 00187 { 16, 150 }, /* *G# */ 00188 { 0, 0 }, /* *R */ 00189 }, 00190 }; 00191 00192 00193 /* name table of notes */ 00194 #ifdef UNIT_MSG 00195 static const char *note_name[MAXNOTE] = { 00196 "A", 00197 "A#", 00198 "B", 00199 "C", 00200 "C#", 00201 "D", 00202 "D#", 00203 "E", 00204 "F", 00205 "F#", 00206 "G", 00207 "G#", 00208 "R", 00209 }; 00210 #endif /*UNIT_MSG*/ 00211 00212 00213 /****************************************************************************** 00214 * Function Name: piano4int_start 00215 * Description : Play the score thru sound generator. 00216 * : This function receives the sound language, 00217 * : and plays specified sound language. 00218 * Arguments : const int8_t *scores : score 00219 * : PIANO4INT_CB callback : callback function 00220 * Return Value : none 00221 ******************************************************************************/ 00222 void piano4int_start(const int8_t *scores[SDG_CH_TOTAL], PIANO4INT_CB callback) 00223 { 00224 const int8_t *score; /* pointer to score */ 00225 uint16_t speed; /* sound speed */ 00226 int32_t ch; /* channel no */ 00227 int32_t ret; /* function result */ 00228 00229 /* prepare for playing the score */ 00230 for (ch = 0; ch < SDG_CH_TOTAL; ch++) { 00231 if (scores[ch] == NULL) { 00232 /* score is not specified */ 00233 pianoT.unit[ch].score = noscore; 00234 pianoT.unit[ch].top = noscore; 00235 } else { 00236 /* prepare for playing a score */ 00237 score = scores[ch]; 00238 00239 /* get the speed */ 00240 speed = 0; 00241 while (isdigit(*score)) { 00242 speed = (speed * 10) + ((*score++) - '0'); 00243 } 00244 if (0 == speed) { 00245 /* can not play the score */ 00246 printf("speed[%d]:%d, can not play, there is no speed information.\n", (int)ch, speed); 00247 return; 00248 } else { 00249 printf("speed[%d]:%d\n", (int)ch, speed); 00250 /* calculate a base speed for ticker */ 00251 pianoT.unit[ch].speed = BASESPEED / speed; 00252 00253 /* default loudness (unsupported to change) */ 00254 pianoT.unit[ch].loudness = DEFLOUDNESS; 00255 00256 /* set top of a score */ 00257 pianoT.unit[ch].top = score; 00258 pianoT.unit[ch].score = score; 00259 00260 /* play no sounds */ 00261 pianoT.unit[ch].count = 0; 00262 00263 /* rest4 */ 00264 pianoT.unit[ch].note = rest4; 00265 00266 /* channel number */ 00267 pianoT.unit[ch].channel = unitHW[ch].channel; 00268 00269 #ifdef UNIT_MSG 00270 /* message */ 00271 pianoT.unit[ch].msg[0] = '\0'; 00272 #endif 00273 00274 /* Initialize Sound Generator */ 00275 ret = R_SDG_Open(unitHW[ch].channel, unitHW[ch].clock); 00276 ASSERT(0 == ret); 00277 } 00278 } 00279 } 00280 00281 /* set callback function */ 00282 pianoT.callback = callback; 00283 00284 /* clear flags to finish playing */ 00285 pianoT.fin = 0; 00286 00287 /* start the metronome (unit: 1ms) */ 00288 pianoT.metronome.attach_us(&play_score, 1000.0); 00289 } 00290 00291 /****************************************************************************** 00292 * Function Name: piano4int_stop 00293 * Description : Stop the sounds through sound generator. 00294 * Arguments : bool force : flag to stop forcedly (now, ignored) 00295 * Return Value : none 00296 ******************************************************************************/ 00297 void piano4int_stop(bool force) 00298 { 00299 int32_t ch; 00300 int32_t ret; 00301 00302 /* wait until sounds stop */ 00303 do { 00304 /* wait 10.0 sec */ 00305 wait_us(10.0 * 1000.0); 00306 #ifdef UNIT_MSG 00307 for (ch = 0; ch < SDG_CH_TOTAL; ch++) { 00308 if ('\0' != pianoT.unit[ch].msg[0]) { 00309 printf(&pianoT.unit[ch].msg[0]); 00310 pianoT.unit[ch].msg[0] = '\0'; 00311 } 00312 } 00313 #endif /*UNIT_MSG*/ 00314 } while (pianoT.fin != ((1 << SDG_CH_TOTAL) - 1)); 00315 /* all scores finished */ 00316 00317 /* stops the metronome */ 00318 pianoT.metronome.detach(); 00319 00320 /* stop all sound generators */ 00321 for (ch = 0; ch < SDG_CH_TOTAL; ch++) { 00322 if (pianoT.unit[ch].top != noscore) { 00323 /* stop sound generator */ 00324 ret = R_SDG_Close(unitHW[ch].channel); 00325 ASSERT(0 == ret); 00326 } 00327 } 00328 } 00329 00330 /****************************************************************************** 00331 * Function Name: piano4int_status 00332 * Description : Get the flag to finish playing the score 00333 * Arguments : none 00334 * Return Value : The flag 00335 * Note : Output the comment if the macro "UNIT_MSG" is defined 00336 ******************************************************************************/ 00337 bool piano4int_status(void) 00338 { 00339 #ifdef UNIT_MSG 00340 int32_t ch; 00341 00342 /* output the comments from interrupts */ 00343 for (ch = 0; ch < SDG_CH_TOTAL; ch++) { 00344 if ('\0' != pianoT.unit[ch].msg[0]) { 00345 printf(&pianoT.unit[ch].msg[0]); 00346 pianoT.unit[ch].msg[0] = '\0'; 00347 } 00348 } 00349 #endif 00350 00351 return (pianoT.fin != ((1 << SDG_CH_TOTAL) - 1)); 00352 } 00353 00354 00355 /****************************************************************************** 00356 * Function Name: play_score 00357 * Description : Play the score on interrupt 00358 * Arguments : none 00359 * Return Value : none 00360 ******************************************************************************/ 00361 void play_score(void) 00362 { 00363 UNIT *unit; 00364 const int8_t *score; 00365 uint16_t octave; 00366 uint16_t key; 00367 uint16_t pitch; 00368 uint16_t dot; 00369 uint16_t tie; 00370 uint8_t loud; 00371 uint16_t duration; 00372 uint16_t value; 00373 uint16_t ch; 00374 bool err; 00375 00376 for (ch = 0; ch < SDG_CH_TOTAL; ch++) { 00377 /* Check finish flag */ 00378 if (0 != (pianoT.fin & (1 << ch))) { 00379 continue; /* finish */ 00380 } 00381 00382 if (0 == pianoT.unit[ch].count) { 00383 unit = &pianoT.unit[ch]; 00384 score = unit->score; 00385 00386 if ('\0' == *score) { 00387 /* set finish flag */ 00388 pianoT.fin |= (1 << ch); 00389 continue; 00390 } 00391 00392 /* Initialize parameters */ 00393 octave = 0; 00394 key = 0; 00395 pitch = 0; 00396 dot = 0; 00397 tie = 0; 00398 err = false; 00399 00400 /* skip some spaces */ 00401 while (' ' == *score) { 00402 score++; 00403 } 00404 00405 /* octave */ 00406 switch (*score) { 00407 case OCTAVE0_CHAR: { octave = OCTAVE_LEVEL_0; score++; break; } 00408 case OCTAVE1_CHAR: { octave = OCTAVE_LEVEL_1; score++; break; } 00409 case OCTAVE2_CHAR: { octave = OCTAVE_LEVEL_2; score++; break; } 00410 case OCTAVE3_CHAR: { octave = OCTAVE_LEVEL_3; score++; break; } 00411 default: { octave = OCTAVE_LEVEL_1; break; } 00412 } 00413 00414 /* key */ 00415 switch (toupper(*score)) { 00416 case NOTE_DO_CHAR: { key = KEY_C; score++; break; } 00417 case NOTE_RE_CHAR: { key = KEY_D; score++; break; } 00418 case NOTE_MI_CHAR: { key = KEY_E; score++; break; } 00419 case NOTE_FA_CHAR: { key = KEY_F; score++; break; } 00420 case NOTE_SO_CHAR: { key = KEY_G; score++; break; } 00421 case NOTE_RA_CHAR: { key = KEY_A; score++; break; } 00422 case NOTE_SI_CHAR: { key = KEY_B; score++; break; } 00423 case NOTE_REST_CHAR:{ key = KEY_R; score++; break; } 00424 default: 00425 err = true; 00426 } 00427 00428 if (((KEY_A == key) && (OCTAVE_LEVEL_0 == octave)) || 00429 ((KEY_B == key) && (OCTAVE_LEVEL_0 == octave))) { 00430 err = true; 00431 } 00432 00433 /* sharp */ 00434 if (NOTE_SHARP == (*score)) { 00435 if (KEY_R == key) { 00436 err = true; 00437 } else { 00438 key++; 00439 score++; 00440 } 00441 } 00442 00443 /* pitch */ 00444 if (isdigit(*score)) { 00445 pitch = ((*score++) - '0'); 00446 if (isdigit(*score)) { 00447 pitch = (pitch * 10) + ((*score++) - '0'); 00448 } 00449 } else { 00450 err = true; 00451 } 00452 00453 /* dotted */ 00454 if (NOTE_DOT == (*score)) { 00455 dot = DOTTED_NOTE; 00456 score++; 00457 } else { 00458 dot = NOT_DOTTED_NONE; 00459 } 00460 00461 /* tie */ 00462 if (NOTE_TIE == (*score)) { 00463 tie = TIED_NOTE; 00464 score++; 00465 } else { 00466 tie = NOT_TIED_NONE; 00467 } 00468 00469 /* set score */ 00470 unit->score = score; 00471 00472 #ifdef UNIT_MSG 00473 snprintf(&unit->msg[0], UNIT_MSG - 1, "%d)%d%s%d -> %d/%d/%d\n", 00474 unit->channel, 00475 octave, 00476 note_name[key], 00477 pitch, 00478 note_timing[octave][key].tone, 00479 note_timing[octave][key].sfs, 00480 unit->speed / pitch); 00481 #endif /* UNIT_MSG */ 00482 00483 if (!err) { 00484 /* set the sound volume */ 00485 loud = (0 == note_timing[octave][key].sfs) ? (0): (unit->loudness); 00486 /* set */ 00487 duration = unit->speed / pitch; 00488 if (dot) { 00489 duration += (duration >> 1); 00490 } 00491 00492 /* set next note or rest */ 00493 unit->note.tone = note_timing[octave][key].tone; 00494 unit->note.sfs = note_timing[octave][key].sfs; 00495 unit->note.loud = loud; 00496 unit->note.attenuation = tie; 00497 00498 R_SDG_Tone(pianoT.unit[ch].channel, &pianoT.unit[ch].note); 00499 pianoT.unit[ch].count = duration; 00500 } else { 00501 pianoT.fin |= (1 << ch); 00502 } 00503 00504 /* marker */ 00505 if (NOTE_MARKER == (*score)) { 00506 score++; 00507 value = 0; 00508 if (isdigit(*score)) { 00509 value = ((*score++) - '0'); 00510 if (isdigit(*score)) { 00511 value = (value * 10) + ((*score++) - '0'); 00512 } 00513 } 00514 unit->score = score; 00515 00516 if (NULL != pianoT.callback) { 00517 pianoT.callback(pianoT.unit[ch].channel, value); 00518 } 00519 } 00520 } else { 00521 pianoT.unit[ch].count--; 00522 } 00523 } 00524 } 00525 00526 /* End of File */
Generated on Fri Jul 15 2022 04:21:34 by
1.7.2
