diff --git a/Marlin/src/Marlin.cpp b/Marlin/src/Marlin.cpp index b14cf9eb7..a432eead0 100644 --- a/Marlin/src/Marlin.cpp +++ b/Marlin/src/Marlin.cpp @@ -258,6 +258,10 @@ #include "libs/duration_t.h" #include "gcode/parser.h" +#if HAS_BUZZER && DISABLED(LCD_USE_I2C_BUZZER) + #include "libs/buzzer.h" +#endif + #if HAS_ABL #include "libs/vector_3.h" #if ENABLED(AUTO_BED_LEVELING_LINEAR) @@ -271,10 +275,6 @@ #include "module/planner_bezier.h" #endif -#if HAS_BUZZER && DISABLED(LCD_USE_I2C_BUZZER) - #include "libs/buzzer.h" -#endif - #if ENABLED(MAX7219_DEBUG) #include "feature/leds/Max7219_Debug_LEDs.h" #endif @@ -495,16 +495,6 @@ static millis_t stepper_inactive_time = (DEFAULT_STEPPER_DEACTIVE_TIME) * 1000UL Stopwatch print_job_timer = Stopwatch(); #endif -// Buzzer - I2C on the LCD or a BEEPER_PIN -#if ENABLED(LCD_USE_I2C_BUZZER) - #define BUZZ(d,f) lcd_buzz(d, f) -#elif PIN_EXISTS(BEEPER) - Buzzer buzzer; - #define BUZZ(d,f) buzzer.tone(d, f) -#else - #define BUZZ(d,f) NOOP -#endif - static uint8_t target_extruder; #if HAS_BED_PROBE diff --git a/Marlin/src/lcd/ultralcd.cpp b/Marlin/src/lcd/ultralcd.cpp index 1adb40cd0..7e40a438e 100644 --- a/Marlin/src/lcd/ultralcd.cpp +++ b/Marlin/src/lcd/ultralcd.cpp @@ -34,10 +34,6 @@ #include "../Marlin.h" -#if HAS_BUZZER && DISABLED(LCD_USE_I2C_BUZZER) - #include "../libs/buzzer.h" -#endif - #if ENABLED(PRINTCOUNTER) #include "../module/printcounter.h" #include "../libs/duration_t.h" @@ -59,6 +55,11 @@ #include "../feature/bedlevel/bedlevel.h" #endif +// For i2c define BUZZ to use lcd_buzz +#if DISABLED(LCD_USE_I2C_BUZZER) + #include "../libs/buzzer.h" +#endif + // Initialized by settings.load() int16_t lcd_preheat_hotend_temp[2], lcd_preheat_bed_temp[2], lcd_preheat_fan_speed[2]; @@ -679,7 +680,7 @@ void kill_screen(const char* lcd_msg) { * Audio feedback for controller clicks * */ - void lcd_buzz(long duration, uint16_t freq) { + void lcd_buzz(const long duration, const uint16_t freq) { #if ENABLED(LCD_USE_I2C_BUZZER) lcd.buzz(duration, freq); #elif PIN_EXISTS(BEEPER) @@ -4803,11 +4804,7 @@ void lcd_reset_alert_level() { lcd_status_message_level = 0; } #if ENABLED(AUTO_BED_LEVELING_UBL) void chirp_at_user() { - #if ENABLED(LCD_USE_I2C_BUZZER) - lcd.buzz(LCD_FEEDBACK_FREQUENCY_DURATION_MS, LCD_FEEDBACK_FREQUENCY_HZ); - #elif PIN_EXISTS(BEEPER) - buzzer.tone(LCD_FEEDBACK_FREQUENCY_DURATION_MS, LCD_FEEDBACK_FREQUENCY_HZ); - #endif + lcd_buzz(LCD_FEEDBACK_FREQUENCY_DURATION_MS, LCD_FEEDBACK_FREQUENCY_HZ); } bool ubl_lcd_clicked() { return LCD_CLICKED; } diff --git a/Marlin/src/lcd/ultralcd.h b/Marlin/src/lcd/ultralcd.h index ceed68eed..1ceb972ee 100644 --- a/Marlin/src/lcd/ultralcd.h +++ b/Marlin/src/lcd/ultralcd.h @@ -56,7 +56,7 @@ inline void lcd_refresh() { lcdDrawUpdate = LCDVIEW_CLEAR_CALL_REDRAW; } #if HAS_BUZZER - void lcd_buzz(long duration, uint16_t freq); + void lcd_buzz(const long duration, const uint16_t freq); #endif #if ENABLED(LCD_PROGRESS_BAR) && PROGRESS_MSG_EXPIRE > 0 diff --git a/Marlin/src/libs/buzzer.cpp b/Marlin/src/libs/buzzer.cpp new file mode 100644 index 000000000..117104001 --- /dev/null +++ b/Marlin/src/libs/buzzer.cpp @@ -0,0 +1,73 @@ +/** + * Marlin 3D Printer Firmware + * Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin] + * + * Based on Sprinter and grbl. + * Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +#include "../inc/MarlinConfig.h" + +#if DISABLED(LCD_USE_I2C_BUZZER) && PIN_EXISTS(BEEPER) + +#include "buzzer.h" +#include "../module/temperature.h" + +Buzzer::state_t Buzzer::state; +CircularQueue Buzzer::buffer; +Buzzer buzzer; + +/** + * @brief Add a tone to the queue + * @details Adds a tone_t structure to the ring buffer, will block IO if the + * queue is full waiting for one slot to get available. + * + * @param duration Duration of the tone in milliseconds + * @param frequency Frequency of the tone in hertz + */ +void Buzzer::tone(const uint16_t duration, const uint16_t frequency/*=0*/) { + while (buffer.isFull()) { + tick(); + thermalManager.manage_heater(); + } + tone_t tone = { duration, frequency }; + buffer.enqueue(tone); +} + +void Buzzer::tick() { + const millis_t now = millis(); + + if (!state.endtime) { + if (buffer.isEmpty()) return; + + state.tone = buffer.dequeue(); + state.endtime = now + state.tone.duration; + + if (state.tone.frequency > 0) { + #if ENABLED(SPEAKER) + CRITICAL_SECTION_START; + ::tone(BEEPER_PIN, state.tone.frequency, state.tone.duration); + CRITICAL_SECTION_END; + #else + on(); + #endif + } + } + else if (ELAPSED(now, state.endtime)) reset(); +} + +#endif // !LCD_USE_I2C_BUZZER && BEEPER diff --git a/Marlin/src/libs/buzzer.h b/Marlin/src/libs/buzzer.h index ef183ead4..9cc23695c 100644 --- a/Marlin/src/libs/buzzer.h +++ b/Marlin/src/libs/buzzer.h @@ -23,11 +23,14 @@ #ifndef __BUZZER_H__ #define __BUZZER_H__ -#include "types.h" -#include "circularqueue.h" -#include "temperature.h" +#include "../inc/MarlinConfig.h" + +// Make a buzzer and macro +#if ENABLED(LCD_USE_I2C_BUZZER) + // BUZZ() will be defined in ultralcd.h +#elif PIN_EXISTS(BEEPER) -#include "MarlinConfig.h" +#include "circularqueue.h" #define TONE_QUEUE_LENGTH 4 @@ -44,46 +47,44 @@ struct tone_t { * @brief Buzzer class */ class Buzzer { - private: - struct state_t { + public: + + typedef struct { tone_t tone; uint32_t endtime; - } state; + } state_t; + + private: + static state_t state; protected: - CircularQueue buffer; + static CircularQueue buffer; /** * @brief Inverts the sate of a digital PIN * @details This will invert the current state of an digital IO pin. */ - void invert() { - TOGGLE(BEEPER_PIN); - } + FORCE_INLINE static void invert() { TOGGLE(BEEPER_PIN); } /** * @brief Turn off a digital PIN * @details Alias of digitalWrite(PIN, LOW) using FastIO */ - void off() { - WRITE(BEEPER_PIN, LOW); - } + FORCE_INLINE static void off() { WRITE(BEEPER_PIN, LOW); } /** * @brief Turn on a digital PIN * @details Alias of digitalWrite(PIN, HIGH) using FastIO */ - void on() { - WRITE(BEEPER_PIN, HIGH); - } + FORCE_INLINE static void on() { WRITE(BEEPER_PIN, HIGH); } /** * @brief Resets the state of the class * @details Brings the class state to a known one. */ - void reset() { - this->off(); - this->state.endtime = 0; + inline static void reset() { + off(); + state.endtime = 0; } public: @@ -92,7 +93,7 @@ class Buzzer { */ Buzzer() { SET_OUTPUT(BEEPER_PIN); - this->reset(); + reset(); } /** @@ -103,43 +104,24 @@ class Buzzer { * @param duration Duration of the tone in milliseconds * @param frequency Frequency of the tone in hertz */ - void tone(const uint16_t &duration, const uint16_t &frequency = 0) { - while (buffer.isFull()) { - this->tick(); - thermalManager.manage_heater(); - } - tone_t tone = { duration, frequency }; - this->buffer.enqueue(tone); - } + static void tone(const uint16_t duration, const uint16_t frequency=0); /** - * @brief Loop function + * @brief Tick function * @details This function should be called at loop, it will take care of * playing the tones in the queue. */ - virtual void tick() { - const millis_t now = millis(); - - if (!this->state.endtime) { - if (this->buffer.isEmpty()) return; - - this->state.tone = this->buffer.dequeue(); - this->state.endtime = now + this->state.tone.duration; - - if (this->state.tone.frequency > 0) { - #if ENABLED(SPEAKER) - CRITICAL_SECTION_START; - ::tone(BEEPER_PIN, this->state.tone.frequency, this->state.tone.duration); - CRITICAL_SECTION_END; - #else - this->on(); - #endif - } - } - else if (ELAPSED(now, this->state.endtime)) this->reset(); - } + static void tick(); }; -extern Buzzer buzzer; + // Provide a buzzer instance + extern Buzzer buzzer; + #define BUZZ(d,f) buzzer.tone(d, f) + +#else // No buzz capability + + #define BUZZ(d,f) NOOP + +#endif #endif