Skip to content

Commit

Permalink
ir: restructure and add more settings
Browse files Browse the repository at this point in the history
Declare settings under it's own namespace, where previous version used
function prefix. Allow to have configurable timeout and buffer size for
rx; default series, repeats and delay values for tx.

Values are reloaded with the appropriate configure() function from the
namespace, unless they apply to the IR{send,recv} object itself.

Also, no need to define 'default' fields for either of the Payload
structures. After parsing is done, pass all of string views to the
function defined in the .cpp that will prepare the resulting value.
  • Loading branch information
mcspr committed Oct 3, 2021
1 parent 1dd4e33 commit ddb9f67
Show file tree
Hide file tree
Showing 6 changed files with 207 additions and 117 deletions.
5 changes: 5 additions & 0 deletions code/espurna/config/general.h
Original file line number Diff line number Diff line change
Expand Up @@ -1587,6 +1587,11 @@
// (can be overriden in the MQTT payload for the specific message)
#endif

#ifndef IR_TX_REPEATS
#define IR_TX_REPEATS 0 // (number) additional number of times that the message will be sent per series
// (can be overriden in the MQTT payload for the specific message)
#endif

#ifndef IR_TX_DELAY
#define IR_TX_DELAY 100 // (ms) minimum amount of time to wait before transmitting another message
// (when using series >1, will also wait between the same message)
Expand Down
255 changes: 178 additions & 77 deletions code/espurna/ir.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,119 @@ To (re)create the string -> Payload decoder .inc files, add `re2c` to the $PATH

namespace ir {
namespace {
namespace tx {
namespace build {

// pin that the transmitter is attached to
constexpr unsigned char pin() {
return IR_TX_PIN;
}

// (optional) number of times that the message will be sent immediately
// (i.e. when the [:<repeats>] is omitted from the MQTT payload)
constexpr uint16_t repeats() {
return IR_TX_REPEATS;
}

// (optional) number of times that the message will be scheduled in the TX queue
// (i.e. when the [:<series>] is omitted from the MQTT payload)
constexpr uint8_t series() {
return IR_TX_SERIES;
}

// (ms)
constexpr unsigned long delay() {
return IR_TX_DELAY;
}

} // namespace build

namespace settings {

unsigned char pin() {
return getSetting("irTx", build::pin());
}

uint16_t repeats() {
return getSetting("rxTxRepeats", build::repeats());
}

uint8_t series() {
return getSetting("rxTxSeries", build::series());
}

unsigned long delay() {
return getSetting("irTxDelay", build::delay());
}

} // namespace settings

namespace internal {

uint16_t repeats { build::repeats() };
uint8_t series { build::series() };
unsigned long delay { build::delay() };

} // namespace internal
} // namespace tx

namespace rx {
namespace build {

// pin that the receiver is attached to
constexpr unsigned char pin() {
return IR_TX_PIN;
}

// internally, lib uses an u16[] of this size
constexpr uint16_t bufferSize() {
return IR_RX_BUFFER_SIZE;
}

// to be isr-friendly, will allocate second u16[]
// that will be used as a storage when decode()'ing
constexpr bool bufferSave() {
return true;
}

// (ms)
constexpr uint8_t timeout() {
return IR_RX_TIMEOUT;
}

// (ms) minimal time in-between decode() calls
constexpr unsigned long delay() {
return IR_RX_DELAY;
}

} // namespace build

namespace settings {

unsigned char pin() {
return getSetting("irRx", build::pin());
}

uint16_t bufferSize() {
return getSetting("irRxBuffer", build::bufferSize());
}

unsigned long delay() {
return getSetting("irRxDelay", build::delay());
}

uint8_t timeout() {
return getSetting("irRxTimeout", build::timeout());
}

} // namespace settings

namespace internal {

unsigned long delay { build::delay() };

} // namespace internal
} // namespace rx

// TODO: some internal-only code instead of std::string_view and std::optional
// currently, b/c of the -std=c++11. and might behave slightly different
Expand Down Expand Up @@ -256,65 +369,6 @@ unsigned long sized(const StringView& view) {
return 0;
}

namespace build {

// gpio settings create two different objects
// one for transmitting
constexpr unsigned char tx() {
return IR_TX_PIN;
}

// and one for receiving
constexpr unsigned char rx() {
return IR_TX_PIN;
}

// internally, lib uses an u16[] of this size
constexpr uint16_t rxBufferSize() {
return IR_RX_BUFFER_SIZE;
}

// to be isr-friendly, will allocate second u16[]
// that will be used as a storage when decode()'ing
constexpr bool rxBufferSave() {
return true;
}

// (optional) number of times that the message will be scheduled in the TX queue
// (i.e. when the [:<series>] is omitted from the MQTT payload)
constexpr uint8_t txSeries() {
return IR_TX_SERIES;
}

// (ms)
constexpr unsigned txDelay() {
return IR_TX_DELAY;
}

// (ms)
constexpr uint8_t rxTimeout() {
return IR_RX_TIMEOUT;
}

// (ms) minimal time in-between decode() calls
constexpr unsigned long rxDelay() {
return IR_RX_DELAY;
}

} // namespace build

namespace settings {

unsigned char tx() {
return getSetting("irTx", build::tx());
}

unsigned char rx() {
return getSetting("irRx", build::rx());
}

} // namespace settings

// Simple messages that transmit the numeric 'value' (up to 8 bytes)
//
// Transmitting:
Expand Down Expand Up @@ -347,12 +401,12 @@ unsigned char rx() {
namespace simple {

struct Payload {
decode_type_t type { decode_type_t::UNKNOWN };
uint64_t value { 0 };
uint16_t bits { 0 };
uint16_t repeats { 0 };
uint8_t series { build::txSeries() };
unsigned long delay { build::txDelay() };
decode_type_t type;
uint64_t value;
uint16_t bits;
uint16_t repeats;
uint8_t series;
unsigned long delay;
};

namespace value {
Expand Down Expand Up @@ -452,6 +506,33 @@ unsigned long delay(const StringView& value) {

} // namespace payload

Payload prepare(StringView type, StringView value, StringView bits, StringView repeats, StringView series, StringView delay) {
Payload result;
result.type = payload::type(type);
result.value = payload::value(value);
result.bits = payload::bits(bits);

if (repeats) {
result.repeats = payload::repeats(repeats);
} else {
result.repeats = tx::internal::repeats;
}

if (series) {
result.series = payload::series(series);
} else {
result.series = tx::internal::series;
}

if (delay) {
result.delay = payload::delay(delay);
} else {
result.delay = tx::internal::delay;
}

return result;
}

#include "ir_parse_simple.re.cpp.inc"

} // namespace simple
Expand All @@ -473,12 +554,10 @@ unsigned long delay(const StringView& value) {

namespace raw {

constexpr uint16_t DefaultFrequency { 38 }; // kHz

struct Payload {
uint16_t frequency { DefaultFrequency };
uint8_t series { build::txSeries() };
unsigned long delay { build::txDelay() };
uint16_t frequency;
uint8_t series;
unsigned long delay;
std::vector<uint16_t> time;
};

Expand Down Expand Up @@ -539,6 +618,16 @@ uint16_t time(const StringView& value) {

} // namespace payload

Payload prepare(StringView frequency, StringView series, StringView delay, decltype(Payload::time)&& time) {
Payload result;
result.frequency = payload::frequency(frequency);
result.series = payload::series(series);
result.delay = payload::delay(delay);
result.time = std::move(time);

return result;
}

#include "ir_parse_raw.re.cpp.inc"

} // namespace raw
Expand Down Expand Up @@ -592,13 +681,17 @@ struct Lock {
}
};

void configure() {
internal::delay = settings::delay();
}

void setup(BasePinPtr&& pin) {
internal::pin = std::move(pin);
internal::instance = std::make_unique<IRrecv>(
internal::pin->pin(),
build::rxBufferSize(),
build::rxTimeout(),
build::rxBufferSave());
settings::bufferSize(),
settings::timeout(),
build::bufferSave());
internal::instance->enableIRIn();
}

Expand Down Expand Up @@ -841,6 +934,12 @@ void loop() {
}
}

void configure() {
internal::delay = settings::delay();
internal::series = settings::series();
internal::repeats = settings::repeats();
}

void setup(BasePinPtr&& pin) {
internal::pin = std::move(pin);
internal::instance = std::make_unique<IRsend>(internal::pin->pin());
Expand Down Expand Up @@ -1239,9 +1338,9 @@ void loop() {
return;
}

static unsigned long last { millis() - build::rxDelay() - 1ul };
static unsigned long last { millis() - internal::delay - 1ul };
unsigned long ts { millis() };
if (ts - last < build::rxDelay()) {
if (ts - last < internal::delay) {
return;
}

Expand Down Expand Up @@ -1291,20 +1390,22 @@ void setup() {
#endif

void configure() {
rx::configure();
tx::configure();
#if MQTT_SUPPORT
mqtt::configure();
#endif
}

void setup() {
auto rxPin = gpioRegister(settings::rx());
auto rxPin = gpioRegister(rx::settings::pin());
if (rxPin) {
DEBUG_MSG_P(PSTR("[IR] Receiver on GPIO%hhu\n"), rxPin->pin());
} else {
DEBUG_MSG_P(PSTR("[IR] No receiver configured\n"));
}

auto txPin = gpioRegister(settings::tx());
auto txPin = gpioRegister(tx::settings::pin());
if (txPin) {
DEBUG_MSG_P(PSTR("[IR] Transmitter on GPIO%hhu\n"), txPin->pin());
} else {
Expand Down
11 changes: 5 additions & 6 deletions code/espurna/ir_parse_raw.re
Original file line number Diff line number Diff line change
Expand Up @@ -93,12 +93,11 @@ ParseResult<Payload> parse(StringView view) {

update_out:
{
Payload result;
result.frequency = payload::frequency(StringView{f0, f1});
result.series = payload::series(StringView{s0, s1});
result.delay = payload::delay(StringView{d0, d1});
result.time = std::move(time);
out = std::move(result);
out = prepare(
StringView{f0, f1},
StringView{s0, s1},
StringView{d0, d1},
std::move(time));
}

return_out:
Expand Down
11 changes: 5 additions & 6 deletions code/espurna/ir_parse_raw.re.cpp.inc
Original file line number Diff line number Diff line change
Expand Up @@ -202,12 +202,11 @@ yy19:

update_out:
{
Payload result;
result.frequency = payload::frequency(StringView{f0, f1});
result.series = payload::series(StringView{s0, s1});
result.delay = payload::delay(StringView{d0, d1});
result.time = std::move(time);
out = std::move(result);
out = prepare(
StringView{f0, f1},
StringView{s0, s1},
StringView{d0, d1},
std::move(time));
}

return_out:
Expand Down
Loading

0 comments on commit ddb9f67

Please sign in to comment.