Skip to content

Commit

Permalink
Merge pull request #3995 from thinkyhead/rc_nonblocking_buzzer
Browse files Browse the repository at this point in the history
New feature: Non blocking tone queue
  • Loading branch information
thinkyhead authored Jun 10, 2016
2 parents 27d5794 + d13c86f commit 74060f1
Show file tree
Hide file tree
Showing 16 changed files with 448 additions and 133 deletions.
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 with BOARD_BQ_ZUM_MEGA_3D and BQ_LCD_SMART_CONTROLLER
#
- 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 BQ_LCD_SMART_CONTROLLER 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

0 comments on commit 74060f1

Please sign in to comment.