// Подключаем библиотеку для работы с мелодиями в формате RTTTL #include // Подключаем библиотеку для работы с четырёхразрядным дисплеем #include // Подключаем библиотеку для работы с кнопками #include // Создаём объект дисплея на шине SPI и пине 10 QuadDisplay qd(10); // Создаём объекты кнопок на пинах: 2, 3, 4 и 5 TroykaButton buttonS1(5); TroykaButton buttonS2(2); TroykaButton buttonS3(3); TroykaButton buttonS4(4); // Даём понятное имя пину A2 с пищалкой constexpr uint8_t BUZZER_PIN = A2; // Мелодия «Имперский марш» в формате RTTTL const char imperM[] PROGMEM = "imperMarch:d=8,o=5,b=95:" "4a4,4a4,4a4,f.4,16c,4a4,f.4,16c," "2a4,4e,4e,4e,f.,16c,4g#4,f.4," "16c,2a4,4a,a.4,16a4,4a,g#.,16g," "16f#,16e,f,p,a#4,4d#,d.,16c#,16c," "16b4,c,p,f4,4g#4,f.4,16a4,4c," "a.4,16c,2e,4a,a.4,16a4,4a,g#.," "16g,16f#,16e,f,p,a#4,4d#,d.," "16c#,16c,16b4,c,p,f4,4g#4,f.4," "16c,4a4,f.4,16c,2a4"; // Мелодия «Марио» в формате RTTTL const char marioB[] PROGMEM = "marioBroth:d=4,o=5,b=100:" "16e6,16e6,32p,8e6,16c6,8e6,8g6,8p," "8g,8p,8c6,16p,8g,16p,8e,16p," "8a,8b,16a#,8a,16g.,16e6,16g6,8a6," "16f6,8g6,8e6,16c6,16d6,8b,16p,8c6," "16p,8g,16p,8e,16p,8a,8b,16a#," "8a,16g.,16e6,16g6,8a6,16f6,8g6,8e6," "16c6,16d6,8b,8p,16g6,16f#6,16f6,16d#6," "16p,16e6,16p,16g#,16a,16c6,16p,16a," "16c6,16d6,8p,16g6,16f#6,16f6,16d#6,16p," "16e6,16p,16c7,16p,16c7,16c7,p,16g6," "16f#6,16f6,16d#6,16p,16e6,16p,16g#,16a," "16c6,16p,16a,16c6,16d6,8p,16d#6,8p," "16d6,8p,16c6"; // Мелодия «Миссия невыполнима» в формате RTTTL const char misImp[] PROGMEM = "missionImp:d=16,o=6,b=95:" "32d,32d#,32d,32d#,32d,32d#,32d,32d#," "32d,32d,32d#,32e,32f,32f#,32g,g,8p," "g,8p,a#,p,c7,p,g,8p," "g,8p,f,p,f#,p,g,8p," "g,8p,a#,p,c7,p,g,8p," "g,8p,f,p,f#,p,a#,g," "2d,32p,a#,g,2c#,32p,a#,g," "2c,a#5,8c,2p,32p,a#5,g5,2f#," "32p,a#5,g5,2f,32p,a#5,g5,2e," "d#,8d"; // Мелодия «Тетрис» в формате RTTTL const char tetris[] PROGMEM = "tetris:d=4,o=5,b=160:" "e6,8b,8c6,8d6,16e6,16d6,8c6,8b," "a,8a,8c6,e6,8d6,8c6,b,8b," "8c6,d6,e6,c6,a,2a,8p,d6," "8f6,a6,8g6,8f6,e6,8e6,8c6,e6," "8d6,8c6,b,8b,8c6,d6,e6,c6," "a,a"; // Мелодия «Европа» в формате RTTTL const char europe[] PROGMEM = "Europe:d=4,o=5,b=140:" "16c#6,32b,32p,8c#.6,16p,f#,p.,32d6,32p," "32c#6,32p,32d6,16p.,32c#6,16p.,b.,p," "32d6,32p,32c#6,32p,d6,f#,p.,32b," "32p,32a,32p,32b,16p.,32a,16p.,32g#," "16p.,32b,16p.,a.,32c#6,32p,32b,32p," "c#6,2f#,p,16p,32d6,32p,32c#6,32p,32d6," "16p.,32c#6,16p.,b.,p,32d6,32p,32c#6,32p," "d6,f#,p.,32b,32p,32a,32p,32b," "16p.,32a,16p.,32g#,16p.,32b,16p.,2a," "16p,32g#,32p,32a,32p,b.,16a,16b," "8c#6,8b,8a,8g#,f#,d6,1c#6,8p," "16c#6,16d6,16c#6,16b,2c#.6,16p"; // Создаём переменную для хранения номера трека uint8_t songID; // Задаём константы минимального и максимального номеров трека constexpr uint8_t minSongID = 1; constexpr uint8_t maxSongID = 5; // Создаём переменную для хранения паузы bool pause = false; // Создаём перечисление состояний плеера с соответствующей переменной enum { PLAY_OFF, // «Плеер не играет» PLAY_ON, // «Плеер играет» } playState; void setup() { // Инициализируем дисплей qd.begin(); // Инициализируем кнопки buttonS1.begin(); buttonS2.begin(); buttonS3.begin(); buttonS4.begin(); // Настраиваем пин с пищалкой в режим выхода pinMode(BUZZER_PIN, OUTPUT); // Устанавливаем режим «Плеер не играет» playState = PLAY_OFF; // Устанавливаем трек №1 songID = 1; } void loop() { // Считываем состояния с кнопок readButtons(); // Обновляем трек с помощью кнопок updateSongIDButtons(); // Выводим выбранный трек на индикатор printDisplaySongID(); // Проверяем состояние плеера switch (playState) { // Если установлен режим «Плеер не играет» case PLAY_OFF: // Переходим в функцию обработки режима «Плеер не играет» handlePlayOff(); break; // Если установлен режим «Плеер играет» case PLAY_ON: // Переходим в функцию обработки режима «Плеер играет» handlePlayOn(); break; } } // Функция обработки режима «Плеер не играет» void handlePlayOff() { // Если был клик по кнопке S1 if (buttonS1.isClick()) { // Выбираем трек к воспроизведению setSongID(); // Устанавливаем режим «Плеер играет» playState = PLAY_ON; } } // Функция обработки режима «Плеер играет» void handlePlayOn() { // Включаем трек playSongID(); // Если был клик по кнопке S1 if (buttonS1.isClick()) { // Останавливаем трек stopSongID(); // Устанавливаем режим «Плеер не играет» playState = PLAY_OFF; } // Если был клик по кнопке S4 if (buttonS4.isClick()) { // Ставим на паузу текущий трек pause = !pause; } } // Функция считывания состояний с кнопок void readButtons() { buttonS1.read(); buttonS2.read(); buttonS3.read(); buttonS4.read(); } // Функция обновления текущего трека с помощью кнопок void updateSongIDButtons() { if (buttonS3.isClick()) { songID++; } if (buttonS2.isClick()) { songID--; } // Корректируем номер трека в рамки диапазона [min;max] wrapSongID(); } // Функция корректировки номеров трека в диапазон [min;max] void wrapSongID() { if (songID > maxSongID) { songID = minSongID; } if (songID < minSongID) { songID = maxSongID; } } // Функция вывода текущего трека на индикатор void printDisplaySongID() { if (songID == 1) { qd.displayDigits(QD_P, QD_0, QD_0, QD_1); } else if (songID == 2) { qd.displayDigits(QD_P, QD_0, QD_0, QD_2); } else if (songID == 3) { qd.displayDigits(QD_P, QD_0, QD_0, QD_3); } else if (songID == 4) { qd.displayDigits(QD_P, QD_0, QD_0, QD_4); } else if (songID == 5) { qd.displayDigits(QD_P, QD_0, QD_0, QD_5); } else { qd.displayDigits(QD_E, QD_r, QD_r, QD_NONE); } } // Функция выбора трека void setSongID() { if (songID == 1) { anyrtttl::nonblocking::begin_P(BUZZER_PIN, imperM); } else if (songID == 2) { anyrtttl::nonblocking::begin_P(BUZZER_PIN, marioB); } else if (songID == 3) { anyrtttl::nonblocking::begin_P(BUZZER_PIN, misImp); } else if (songID == 4) { anyrtttl::nonblocking::begin_P(BUZZER_PIN, tetris); } else if (songID == 5) { anyrtttl::nonblocking::begin_P(BUZZER_PIN, europe); } } // Функция воспроизведения трека void playSongID() { // Если не включена пауза if (pause == false) { // Продолжаем играть трек anyrtttl::nonblocking::play(); } // Если трек завершился if (anyrtttl::nonblocking::done()) { // Устанавливаем режим «Плеер не играет» playState = PLAY_OFF; } } // Функция остановки трека void stopSongID() { // Останавливаем трек anyrtttl::nonblocking::stop(); }