My Marlin configs for Fabrikator Mini and CTC i3 Pro B
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

sound_player.cpp 3.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. /********************
  2. * sound_player.cpp *
  3. ********************/
  4. /****************************************************************************
  5. * Written By Marcio Teixeira 2018 - Aleph Objects, Inc. *
  6. * *
  7. * This program is free software: you can redistribute it and/or modify *
  8. * it under the terms of the GNU General Public License as published by *
  9. * the Free Software Foundation, either version 3 of the License, or *
  10. * (at your option) any later version. *
  11. * *
  12. * This program is distributed in the hope that it will be useful, *
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of *
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
  15. * GNU General Public License for more details. *
  16. * *
  17. * To view a copy of the GNU General Public License, go to the following *
  18. * location: <https://www.gnu.org/licenses/>. *
  19. ****************************************************************************/
  20. #include "ftdi_extended.h"
  21. #if ENABLED(FTDI_EXTENDED)
  22. namespace FTDI {
  23. SoundPlayer sound; // Global sound player object
  24. void SoundPlayer::set_volume(uint8_t vol) {
  25. CLCD::mem_write_8(REG::VOL_SOUND, vol);
  26. }
  27. uint8_t SoundPlayer::get_volume() {
  28. return CLCD::mem_read_8(REG::VOL_SOUND);
  29. }
  30. void SoundPlayer::play(effect_t effect, note_t note) {
  31. #if ENABLED(TOUCH_UI_DEBUG)
  32. SERIAL_ECHO_MSG("Playing note ", note, ", instrument ", effect);
  33. #endif
  34. // Play the note
  35. CLCD::mem_write_16(REG::SOUND, (note == REST) ? 0 : (((note ? note : NOTE_C4) << 8) | effect));
  36. CLCD::mem_write_8(REG::PLAY, 1);
  37. }
  38. note_t SoundPlayer::frequency_to_midi_note(const uint16_t frequency_hz) {
  39. const float f0 = 440;
  40. return note_t(NOTE_A4 + (log(frequency_hz)-log(f0))*12/log(2) + 0.5);
  41. }
  42. // Plays a tone of a given frequency and duration. Since the FTDI FT810 only
  43. // supports MIDI notes, we round down to the nearest note.
  44. void SoundPlayer::play_tone(const uint16_t frequency_hz, const uint16_t duration_ms) {
  45. play(ORGAN, frequency_to_midi_note(frequency_hz));
  46. // Schedule silence to squelch the note after the duration expires.
  47. sequence = silence;
  48. wait = duration_ms;
  49. timer.start();
  50. }
  51. void SoundPlayer::play(const sound_t* seq, play_mode_t mode) {
  52. sequence = seq;
  53. wait = 250; // Adding this delay causes the note to not be clipped, not sure why.
  54. timer.start();
  55. if (mode == PLAY_ASYNCHRONOUS) return;
  56. // If playing synchronously, then play all the notes here
  57. while (has_more_notes()) {
  58. onIdle();
  59. TERN_(TOUCH_UI_FTDI_EVE, ExtUI::yield());
  60. }
  61. }
  62. bool SoundPlayer::is_sound_playing() {
  63. return CLCD::mem_read_8( REG::PLAY ) & 0x1;
  64. }
  65. void SoundPlayer::onIdle() {
  66. if (!sequence) return;
  67. const bool ready_for_next_note = (wait == 0) ? !is_sound_playing() : timer.elapsed(wait);
  68. if (ready_for_next_note) {
  69. const effect_t fx = effect_t(pgm_read_byte(&sequence->effect));
  70. const note_t nt = note_t(pgm_read_byte(&sequence->note));
  71. const uint32_t ms = uint32_t(pgm_read_byte(&sequence->sixteenths)) * 1000 / 16;
  72. if (ms == 0 && fx == SILENCE && nt == END_SONG) {
  73. sequence = 0;
  74. play(SILENCE, REST);
  75. }
  76. else {
  77. wait = ms;
  78. timer.start();
  79. play(fx, nt);
  80. sequence++;
  81. }
  82. }
  83. }
  84. } // namespace FTDI
  85. #endif // FTDI_EXTENDED