Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New feature: Non blocking tone queue #3962

Closed
9 changes: 9 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,15 @@ script:
- opt_enable_adv DUAL_X_CARRIAGE
- build_marlin
#
# Test SPEAKER
#
- restore_configs
- opt_set MOTHERBOARD BOARD_BQ_ZUM_MEGA_3D
- opt_set LCD_FEEDBACK_FREQUENCY_DURATION_MS 10
- opt_set LCD_FEEDBACK_FREQUENCY_HZ 100
- opt_enable SPEAKER
- build_marlin
#
### LCDS ###
#
#
Expand Down
30 changes: 23 additions & 7 deletions Marlin/Conditionals.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,7 @@
#endif

#ifndef CONFIGURATION_LCD // Get the LCD defines which are needed first

#define CONFIGURATION_LCD
#define CONFIGURATION_LCD

#define LCD_HAS_DIRECTIONAL_BUTTONS (BUTTON_EXISTS(UP) || BUTTON_EXISTS(DWN) || BUTTON_EXISTS(LFT) || BUTTON_EXISTS(RT))

Expand Down Expand Up @@ -154,11 +153,6 @@
#define ENCODER_STEPS_PER_MENU_ITEM 1
#endif

#if ENABLED(LCD_USE_I2C_BUZZER)
#define LCD_FEEDBACK_FREQUENCY_HZ 1000
#define LCD_FEEDBACK_FREQUENCY_DURATION_MS 100
#endif

#define ULTIPANEL
#define NEWPANEL
#endif
Expand Down Expand Up @@ -806,5 +800,27 @@
#endif
#endif

/**
* Buzzer/Speaker
*/
#if ENABLED(LCD_USE_I2C_BUZZER)
#ifndef LCD_FEEDBACK_FREQUENCY_HZ
#define LCD_FEEDBACK_FREQUENCY_HZ 1000
#endif
#ifndef LCD_FEEDBACK_FREQUENCY_DURATION_MS
#define LCD_FEEDBACK_FREQUENCY_DURATION_MS 100
#endif
#elif PIN_EXISTS(BEEPER)
#ifndef LCD_FEEDBACK_FREQUENCY_HZ
#define LCD_FEEDBACK_FREQUENCY_HZ 5000
#endif
#ifndef LCD_FEEDBACK_FREQUENCY_DURATION_MS
#define LCD_FEEDBACK_FREQUENCY_DURATION_MS 2
#endif
#else
#ifndef LCD_FEEDBACK_FREQUENCY_DURATION_MS
#define LCD_FEEDBACK_FREQUENCY_DURATION_MS 2
#endif
#endif
#endif //CONFIGURATION_LCD
#endif //CONDITIONALS_H
11 changes: 11 additions & 0 deletions Marlin/Marlin.h
Original file line number Diff line number Diff line change
Expand Up @@ -373,4 +373,15 @@ extern uint8_t active_extruder;

void calculate_volumetric_multipliers();

// Buzzer
#if HAS_BUZZER
#if ENABLED(SPEAKER)
#include "speaker.h"
extern Speaker buzzer;
#else
#include "buzzer.h"
extern Buzzer buzzer;
#endif
#endif

#endif //MARLIN_H
41 changes: 29 additions & 12 deletions Marlin/Marlin_main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,6 @@
#include "language.h"
#include "pins_arduino.h"
#include "math.h"
#include "buzzer.h"

#if ENABLED(USE_WATCHDOG)
#include "watchdog.h"
Expand Down Expand Up @@ -354,6 +353,15 @@ static millis_t stepper_inactive_time = (DEFAULT_STEPPER_DEACTIVE_TIME) * 1000UL
Stopwatch print_job_timer = Stopwatch();
#endif

// Buzzer
#if HAS_BUZZER
#if ENABLED(SPEAKER)
Speaker buzzer;
#else
Buzzer buzzer;
#endif
#endif

static uint8_t target_extruder;

#if ENABLED(AUTO_BED_LEVELING_FEATURE)
Expand Down Expand Up @@ -1233,7 +1241,7 @@ inline bool code_value_bool() { return code_value_byte() > 0; }

#if ENABLED(TEMPERATURE_UNITS_SUPPORT)
inline void set_input_temp_units(TempUnit units) { input_temp_units = units; }

float code_value_temp_abs() {
switch (input_temp_units) {
case TEMPUNIT_C:
Expand Down Expand Up @@ -5689,10 +5697,13 @@ inline void gcode_M226() {
* M300: Play beep sound S<frequency Hz> P<duration ms>
*/
inline void gcode_M300() {
uint16_t beepS = code_seen('S') ? code_value_ushort() : 110;
uint32_t beepP = code_seen('P') ? code_value_ulong() : 1000;
if (beepP > 5000) beepP = 5000; // limit to 5 seconds
buzz(beepP, beepS);
uint16_t const frequency = code_seen('S') ? code_value_ushort() : 260;
uint16_t duration = code_seen('P') ? code_value_ushort() : 1000;

// Limits the tone duration to 0-5 seconds.
NOMORE(duration, 5000);

buzzer.tone(duration, frequency);
}

#endif // HAS_BUZZER
Expand Down Expand Up @@ -6173,7 +6184,7 @@ inline void gcode_M428() {
SERIAL_ERRORLNPGM(MSG_ERR_M428_TOO_FAR);
LCD_ALERTMESSAGEPGM("Err: Too far!");
#if HAS_BUZZER
buzz(200, 40);
buzzer.tone(200, 40);
#endif
err = true;
break;
Expand All @@ -6190,8 +6201,8 @@ inline void gcode_M428() {
report_current_position();
LCD_MESSAGEPGM(MSG_HOME_OFFSETS_APPLIED);
#if HAS_BUZZER
buzz(200, 659);
buzz(200, 698);
buzzer.tone(200, 659);
buzzer.tone(200, 698);
#endif
}
}
Expand Down Expand Up @@ -8076,17 +8087,23 @@ void idle(
bool no_stepper_sleep/*=false*/
#endif
) {
thermalManager.manage_heater();
lcd_update();
host_keepalive();
manage_inactivity(
#if ENABLED(FILAMENTCHANGEENABLE)
no_stepper_sleep
#endif
);
host_keepalive();
lcd_update();

thermalManager.manage_heater();

#if ENABLED(PRINTCOUNTER)
print_job_timer.tick();
#endif

#if HAS_BUZZER
buzzer.tick();
#endif
}

/**
Expand Down
57 changes: 0 additions & 57 deletions Marlin/buzzer.cpp

This file was deleted.

115 changes: 109 additions & 6 deletions Marlin/buzzer.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,114 @@
*
*/

#ifndef BUZZER_H
#define BUZZER_H
#ifndef __BUZZER_H__
#define __BUZZER_H__

#if HAS_BUZZER
void buzz(long duration, uint16_t freq);
#endif
#include "fastio.h"
#include "watchdog.h"
#include "circularqueue.h"

#endif //BUZZER_H
#define TONE_QUEUE_LENGTH 4

/**
* @brief Tone structure
* @details Simple abstration of a tone based on a duration and a frequency.
*
*/
struct tone_t {
uint16_t duration;
uint16_t frequency;
};

/**
* @brief Buzzer class
*/
class Buzzer {
private:
struct state_t {
tone_t tone;
uint32_t timestamp;
} state;

protected:
CircularQueue<tone_t, TONE_QUEUE_LENGTH> buffer;

/**
* @brief Inverts the sate of a digital PIN
* @details This will invert the current state of an digital IO pin.
*/
void invert() {
WRITE(BEEPER_PIN, !READ(BEEPER_PIN));
}

/**
* @brief Turn off a digital PIN
* @details Alias of digitalWrite(PIN, LOW) using FastIO
*/
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);
}

/**
* @brief Resets the state of the class
* @details Brings the class state to a known one.
*/
void reset() {
this->off();
this->state.timestamp = 0;
}

public:
/**
* @brief Class constructor
*/
Buzzer() {
SET_OUTPUT(BEEPER_PIN);
this->reset();
}

/**
* @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 tone(uint16_t const &duration, uint16_t const &frequency = 0) {
while (buffer.isFull()) {
delay(5);
this->tick();
#if ENABLED(USE_WATCHDOG)
watchdog_reset();
#endif
}
this->buffer.enqueue((tone_t) { duration, frequency });
}

/**
* @brief Loop function
* @details This function should be called at loop, it will take care of
* playing the tones in the queue.
*/
virtual void tick() {
if (!this->state.timestamp) {
if (this->buffer.isEmpty()) return;

this->state.tone = this->buffer.dequeue();
this->state.timestamp = millis() + this->state.tone.duration;
if (this->state.tone.frequency > 0) this->on();
}
else if (millis() >= this->state.timestamp) this->reset();
}
};

#endif
Loading