Здравствуйте!
Прошу прокомментировать следующий код
#pragma once
#include <Arduino.h>
#define BPR_PULSE_MS 200
#define BPR_PAUSE_MS 0
#define BPR_REPEAT_COUNT 1 // 0 - forever
#define BPR_ON (_is_inverse ? LOW : HIGH)
#define BPR_OFF (_is_inverse ? HIGH : LOW)
class Beeper {
public:
Beeper(const uint8_t pin, const bool is_inverse = false) {
_pin = pin;
_is_inverse = is_inverse;
pinMode(_pin, OUTPUT);
digitalWrite(_pin, BPR_OFF);
init(BPR_PULSE_MS, BPR_PAUSE_MS, BPR_REPEAT_COUNT);
_is_active = false;
}
void execute(void) {
static uint32_t time_mark;
if (!_is_active) return;
uint32_t current_time = millis();
switch (_step) {
case 0:
digitalWrite(_pin, BPR_ON);
time_mark = current_time;
_step = 1;
break;
case 1:
if ((uint16_t)(current_time - time_mark) >= _pulse_ms) {
if (_pause_ms) {
digitalWrite(_pin, BPR_OFF);
time_mark = current_time;
_step = 2;
} else {
_step = 3;
}
}
break;
case 2:
if ((uint16_t)(current_time - time_mark) >= _pause_ms) {
_step = 3;
}
break;
case 3:
if (!_repeat_count /*beep forever*/ || ++_repeat < _repeat_count) {
_step = 0;
} else {
digitalWrite(_pin, BPR_OFF);
_is_active = false;
}
break;
}
}
void start(const uint16_t pulse_ms = BPR_PULSE_MS, const uint16_t pause_ms = BPR_PAUSE_MS, const int8_t repeat_count = BPR_REPEAT_COUNT) {
if (!pulse_ms) return;
init(pulse_ms, pause_ms, repeat_count);
_is_active = true;
execute();
}
void stop(void) {
digitalWrite(_pin, BPR_OFF);
_is_active = false;
}
private:
void init(const uint16_t pulse_ms = BPR_PULSE_MS, const uint16_t pause_ms = BPR_PAUSE_MS, const int8_t repeat_count = BPR_REPEAT_COUNT) {
_pulse_ms = pulse_ms;
_pause_ms = pause_ms;
_repeat_count = repeat_count;
_step = 0;
_repeat = 0;
}
private:
bool _is_active, _is_inverse;
uint8_t _pin, _step, _repeat, _repeat_count;
uint16_t _pulse_ms, _pause_ms;
};
Это класс бипера. У бипера есть активный уровень (импульс), когда он пищит, есть пауза для молчания. Задается в мсек. Также можно задать количество повторов последовательности импульсов и пауз. Если в процессе работы бипера пришла новая команда пищать, он исполняет новую.
Запускается вызовом Beeper::start(…), вызывается в основном цикле по Beeper::execute().
Пример:
#include "beeper.h"
#define PIN_BPR 5
Beeper bpr(PIN_BPR);
void setup() {
}
void loop() {
if (/*какое-то условие*/) {
bpr.start(500, 200, 5); // 5 повторений импульса в 500 мс и паузы в 200 мсек
}
bpr.execute(); // выполнение программы бипера (если неактивен, то просто выход из нее)
}
Несколько вопросов:
- Инициализация бипера и старт его работы предполагаются при постоянных параметрах бипера (импульс, пауза, количество повторов). Уместно ли здесь ключевое слово const, в т.ч., для булевых параметров? Или в данном случае его применение не нужно (не обязательно)?
- В функции execute() есть ли смысл менять порядок объявления переменной static и проверки активности бипера? Вообще, если при объявлении переменной я использую директиву static, означает ли это, что память под нее выделяется сразу при первом вызове функции вне зависимости от того дошла да нее программа или она выделится впервые только, если выполнится условие перед объявлением переменной в примере (функция execute())?
- А если я использую в функции переменную без static (предположим, что в вышеуказанном примере uint32_t time_mark объявлена без static ), то под нее выделяется память всегда при вызове функции (а потом освобождается при выходе из нее)? Вне зависимости от того, в каком месте функции она объявлена?
- По самому алгоритму бипера и его оптимальности (реализации), также прошу высказать замечания.