первый
This commit is contained in:
475
GyverEncoder.cpp
Normal file
475
GyverEncoder.cpp
Normal file
@@ -0,0 +1,475 @@
|
||||
#include "GyverEncoder.h"
|
||||
#include "mbed.h"
|
||||
#include <debounce.h>
|
||||
|
||||
#if defined(PRECISE_ALGORITHM)
|
||||
const int8_t KNOBDIR[] = {
|
||||
0,
|
||||
-1,
|
||||
1,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
-1,
|
||||
-1,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
1,
|
||||
-1,
|
||||
0,
|
||||
};
|
||||
int8_t encPos = 0;
|
||||
#endif
|
||||
|
||||
// ================= CONSTRUCTOR =================
|
||||
Encoder::Encoder()
|
||||
{
|
||||
flags.use_button = true;
|
||||
}
|
||||
|
||||
Encoder::Encoder(PinName clk, PinName dt, PinName sw, bool type)
|
||||
{
|
||||
|
||||
if (sw != NC) {
|
||||
_SW = new DigitalIn(sw, PullUp);
|
||||
flags.use_button = true;
|
||||
} else {
|
||||
flags.use_button = false;
|
||||
}
|
||||
flags.enc_type = type;
|
||||
|
||||
_CLK = new DigitalIn(clk, PullUp);
|
||||
_DT = new DigitalIn(dt, PullUp);
|
||||
|
||||
flags.invBtn = (DEFAULT_BTN_PULL == HIGH_PULL) ? true : false;
|
||||
|
||||
#if defined(FAST_ALGORITHM)
|
||||
prevState = digitalRead(_CLK);
|
||||
#else
|
||||
prevState = (_CLK->read() | _DT->read() << 1);
|
||||
#endif
|
||||
|
||||
flags.isDouble_f = false;
|
||||
flags.isPress_f = false;
|
||||
flags.isRelease_f = false;
|
||||
flags.isHolded_f = false;
|
||||
flags.butt_flag = false;
|
||||
flags.hold_flag = false;
|
||||
|
||||
debounce_timer = Kernel::Clock::now();
|
||||
|
||||
encThread = new Thread(osPriorityNormal, 1024, NULL, "Encoder Thread");
|
||||
}
|
||||
|
||||
void Encoder::start()
|
||||
{
|
||||
// _CLK->fall(callback(this, &Encoder::encoderThread));
|
||||
// _CLK->rise(callback(this, &Encoder::encoderThread));
|
||||
|
||||
// _SW->fall(callback(this, &Encoder::encoderThread));
|
||||
// _SW->rise(callback(this, &Encoder::encoderThread));
|
||||
encThread->start(callback(this, &Encoder::encoderThread));
|
||||
}
|
||||
|
||||
void Encoder::stop()
|
||||
{
|
||||
encThread->terminate();
|
||||
}
|
||||
|
||||
void Encoder::encoderThread()
|
||||
{
|
||||
|
||||
for (;;) {
|
||||
this->tick();
|
||||
|
||||
ThisThread::sleep_for(1ms);
|
||||
}
|
||||
}
|
||||
|
||||
// ================= SET =================
|
||||
void Encoder::setDirection(bool direction)
|
||||
{
|
||||
if (direction) {
|
||||
// uint8_t buf = _CLK;
|
||||
// _CLK = _DT;
|
||||
// _DT = buf;
|
||||
}
|
||||
}
|
||||
void Encoder::setPinMode(bool mode)
|
||||
{
|
||||
_CLK->mode((mode) ? PullDown : PullUp);
|
||||
_DT->mode((mode) ? PullDown : PullUp);
|
||||
}
|
||||
void Encoder::setBtnPinMode(bool mode)
|
||||
{
|
||||
|
||||
_SW->mode((mode) ? PullDown : PullUp);
|
||||
flags.invBtn = (mode) ? 0 : 1;
|
||||
}
|
||||
void Encoder::setType(bool type)
|
||||
{
|
||||
flags.enc_type = type;
|
||||
}
|
||||
void Encoder::setTickMode(bool tickMode)
|
||||
{
|
||||
flags.enc_tick_mode = tickMode;
|
||||
}
|
||||
void Encoder::setFastTimeout(Kernel::Clock::duration timeout)
|
||||
{
|
||||
_fast_timeout = timeout;
|
||||
}
|
||||
|
||||
// ================= IS =================
|
||||
// повороты
|
||||
bool Encoder::isTurn()
|
||||
{
|
||||
if (flags.enc_tick_mode)
|
||||
Encoder::tick();
|
||||
if (flags.isTurn_f) {
|
||||
flags.isTurn_f = false;
|
||||
return true;
|
||||
} else
|
||||
return false;
|
||||
}
|
||||
bool Encoder::isRight()
|
||||
{
|
||||
if (flags.enc_tick_mode)
|
||||
Encoder::tick();
|
||||
if (encState == 2) {
|
||||
encState = 0;
|
||||
return true;
|
||||
} else
|
||||
return false;
|
||||
}
|
||||
bool Encoder::isLeft()
|
||||
{
|
||||
if (flags.enc_tick_mode)
|
||||
Encoder::tick();
|
||||
if (encState == 1) {
|
||||
encState = 0;
|
||||
return true;
|
||||
} else
|
||||
return false;
|
||||
}
|
||||
bool Encoder::isRightH()
|
||||
{
|
||||
if (flags.enc_tick_mode)
|
||||
Encoder::tick();
|
||||
if (encState == 4) {
|
||||
encState = 0;
|
||||
return true;
|
||||
} else
|
||||
return false;
|
||||
}
|
||||
bool Encoder::isLeftH()
|
||||
{
|
||||
if (flags.enc_tick_mode)
|
||||
Encoder::tick();
|
||||
if (encState == 3) {
|
||||
encState = 0;
|
||||
return true;
|
||||
} else
|
||||
return false;
|
||||
}
|
||||
bool Encoder::isFastR()
|
||||
{
|
||||
if (flags.enc_tick_mode)
|
||||
Encoder::tick();
|
||||
if (flags.isFastR_f) {
|
||||
flags.isFastR_f = false;
|
||||
return true;
|
||||
} else
|
||||
return false;
|
||||
}
|
||||
bool Encoder::isFastL()
|
||||
{
|
||||
if (flags.enc_tick_mode)
|
||||
Encoder::tick();
|
||||
if (flags.isFastL_f) {
|
||||
flags.isFastL_f = false;
|
||||
return true;
|
||||
} else
|
||||
return false;
|
||||
}
|
||||
|
||||
// кнопка
|
||||
bool Encoder::isPress()
|
||||
{
|
||||
if (flags.enc_tick_mode)
|
||||
Encoder::tick();
|
||||
if (flags.isPress_f) {
|
||||
flags.isPress_f = false;
|
||||
return true;
|
||||
} else
|
||||
return false;
|
||||
}
|
||||
bool Encoder::isRelease()
|
||||
{
|
||||
if (flags.enc_tick_mode)
|
||||
Encoder::tick();
|
||||
if (flags.isRelease_f) {
|
||||
flags.isRelease_f = false;
|
||||
return true;
|
||||
} else
|
||||
return false;
|
||||
}
|
||||
bool Encoder::isClick()
|
||||
{
|
||||
if (flags.enc_tick_mode)
|
||||
Encoder::tick();
|
||||
if (flags.isRelease_f) {
|
||||
flags.isRelease_f = false;
|
||||
return true;
|
||||
} else
|
||||
return false;
|
||||
}
|
||||
bool Encoder::isHolded()
|
||||
{
|
||||
if (flags.enc_tick_mode)
|
||||
Encoder::tick();
|
||||
if (flags.hold_flag && flags.isHolded_f) {
|
||||
flags.isHolded_f = false;
|
||||
return true;
|
||||
} else
|
||||
return false;
|
||||
}
|
||||
bool Encoder::isSingle()
|
||||
{
|
||||
if (flags.enc_tick_mode)
|
||||
Encoder::tick();
|
||||
if (flags.isSingle_f) {
|
||||
flags.isSingle_f = false;
|
||||
flags.isDouble_f = false;
|
||||
return true;
|
||||
} else
|
||||
return false;
|
||||
}
|
||||
bool Encoder::isDouble()
|
||||
{
|
||||
// if (flags.enc_tick_mode)
|
||||
// Encoder::tick();
|
||||
// if (flags.isDouble_f)
|
||||
// {
|
||||
// flags.isDouble_f = false;
|
||||
// flags.isSingle_f = false;
|
||||
// return true;
|
||||
// }
|
||||
// else
|
||||
// return false;
|
||||
if (flags.isDouble_f) {
|
||||
flags.isDouble_f = false;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool Encoder::isHold()
|
||||
{
|
||||
if (flags.enc_tick_mode)
|
||||
Encoder::tick();
|
||||
return (SW_state);
|
||||
}
|
||||
|
||||
// ================= TICK =================
|
||||
void Encoder::tick(bool clk, bool dt, bool sw)
|
||||
{
|
||||
extTick = true;
|
||||
flags.extCLK = clk;
|
||||
flags.extDT = dt;
|
||||
flags.extSW = sw;
|
||||
Encoder::tick();
|
||||
extTick = false;
|
||||
}
|
||||
|
||||
void Encoder::tick()
|
||||
{
|
||||
thisMls = Kernel::Clock::now();
|
||||
debounceDelta = thisMls - debounce_timer;
|
||||
// int butstate;
|
||||
|
||||
#ifdef ENC_WITH_BUTTON
|
||||
// static etl::debounce<DEBOUNCE_COUNT, HOLD_COUNT, REPEAT_COUNT> key_state;
|
||||
// static etl::debounce<DEBOUNCE_COUNT, HOLD_COUNT, REPEAT_COUNT> key_invState;
|
||||
// // butstate = *_SW;
|
||||
|
||||
// if (key_state.add(*_SW == 0)) {
|
||||
// if (key_state.is_set() && flags.isRelease_f == true) {
|
||||
// flags.isPress_f = true;
|
||||
// flags.butt_flag = true;
|
||||
// flags.isRelease_f = false;
|
||||
// }
|
||||
// if (key_state.is_held()) {
|
||||
// flags.isHolded_f = true;
|
||||
// flags.butt_flag = false;
|
||||
|
||||
// } else
|
||||
|
||||
// if (key_state.is_repeating()) {
|
||||
// flags.isDouble_f = true;
|
||||
// }
|
||||
// }
|
||||
// // if (flags.butt_flag) {
|
||||
// if (key_invState.add(*_SW == 1)) {
|
||||
// if (key_invState.is_set()) {
|
||||
// flags.isPress_f = false;
|
||||
// flags.isRelease_f = true;
|
||||
// flags.butt_flag = false;
|
||||
// // }
|
||||
// }
|
||||
// }
|
||||
|
||||
if (flags.use_button) {
|
||||
if (!extTick)
|
||||
// if (_SW->read() == 0) { // читаем состояние кнопки SW
|
||||
SW_state = _SW->read() ^ flags.invBtn;
|
||||
// } else {
|
||||
// SW_state = false ^ flags.invBtn;
|
||||
// }
|
||||
else
|
||||
SW_state = flags.extSW;
|
||||
|
||||
if (SW_state && !flags.butt_flag && (debounceDelta > ENC_DEBOUNCE_BUTTON)) {
|
||||
flags.butt_flag = true;
|
||||
flags.turn_flag = false;
|
||||
debounce_timer = thisMls;
|
||||
debounceDelta = 0ms;
|
||||
flags.isPress_f = true;
|
||||
flags.isHolded_f = true;
|
||||
flags.doubleAllow = true;
|
||||
}
|
||||
if (!SW_state && flags.butt_flag && (debounceDelta > ENC_DEBOUNCE_BUTTON)) {
|
||||
if (!flags.turn_flag && !flags.hold_flag) { // если кнопка отпущена и ручка не поворачивалась
|
||||
flags.turn_flag = false;
|
||||
flags.isRelease_f = true;
|
||||
}
|
||||
if (debounceDelta > ENC_HOLD_TIMEOUT)
|
||||
flags.isReleaseHold_f = true;
|
||||
flags.butt_flag = false;
|
||||
debounce_timer = thisMls;
|
||||
debounceDelta = 0ms;
|
||||
flags.hold_flag = false;
|
||||
|
||||
if (flags.doubleAllow && !flags.doubleFlag) {
|
||||
flags.doubleFlag = true;
|
||||
flags.countFlag = false;
|
||||
} else {
|
||||
flags.countFlag = true;
|
||||
}
|
||||
}
|
||||
if (flags.doubleFlag && debounceDelta > ENC_DOUBLE_TIMEOUT) {
|
||||
if (!flags.turn_flag) {
|
||||
if (!flags.countFlag)
|
||||
flags.isSingle_f = true;
|
||||
else
|
||||
flags.isDouble_f = true;
|
||||
}
|
||||
flags.doubleFlag = false;
|
||||
}
|
||||
if (flags.butt_flag && debounceDelta > ENC_HOLD_TIMEOUT && !flags.turn_flag) {
|
||||
if (SW_state) {
|
||||
flags.hold_flag = true;
|
||||
flags.doubleAllow = false;
|
||||
} else {
|
||||
flags.butt_flag = false;
|
||||
flags.hold_flag = false;
|
||||
debounce_timer = thisMls;
|
||||
debounceDelta = 0ms;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(FAST_ALGORITHM)
|
||||
uint8_t curState = (extTick) ? (flags.extCLK) : (digitalRead(_CLK));
|
||||
|
||||
if (curState != prevState
|
||||
#if (ENC_DEBOUNCE_TURN > 0)
|
||||
&& (debounceDelta > ENC_DEBOUNCE_TURN)
|
||||
#endif
|
||||
) {
|
||||
encState = 0;
|
||||
turnFlag = !turnFlag;
|
||||
if (turnFlag || !flags.enc_type) {
|
||||
if (((extTick) ? (flags.extDT) : digitalRead(_DT)) != prevState) {
|
||||
encState = 1;
|
||||
} else {
|
||||
encState = 2;
|
||||
}
|
||||
}
|
||||
|
||||
#elif defined(BINARY_ALGORITHM)
|
||||
uint8_t curState = (extTick) ? (flags.extCLK | (flags.extDT << 1)) : (_CLK->read() | (_DT->read() << 1));
|
||||
|
||||
if (curState != prevState
|
||||
//#if (ENC_DEBOUNCE_TURN > 0)
|
||||
&& (debounceDelta > ENC_DEBOUNCE_TURN)
|
||||
//#endif
|
||||
) {
|
||||
encState = 0;
|
||||
if (curState == 0b11) {
|
||||
switch (prevState) {
|
||||
case 0b10:
|
||||
encState = 1;
|
||||
break;
|
||||
case 0b01:
|
||||
encState = 2;
|
||||
break;
|
||||
}
|
||||
} else if (curState == 0b00 && !flags.enc_type) {
|
||||
switch (prevState) {
|
||||
case 0b01:
|
||||
encState = 1;
|
||||
break;
|
||||
case 0b10:
|
||||
encState = 2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#elif defined(PRECISE_ALGORITHM)
|
||||
uint8_t curState = (extTick) ? (flags.extCLK | (flags.extDT << 1)) : (_CLK->read() | (_DT->read() << 1));
|
||||
|
||||
if (prevState != curState
|
||||
//#if (ENC_DEBOUNCE_TURN > 0)
|
||||
// && (debounceDelta > ENC_DEBOUNCE_TURN)
|
||||
//#endif
|
||||
) {
|
||||
encState = 0;
|
||||
encPos += KNOBDIR[curState | (prevState << 2)];
|
||||
if (flags.enc_type) {
|
||||
if (curState == 0x3 && encPos != 0) {
|
||||
encState = (encPos == 4) ? 1 : 2;
|
||||
encPos = 0;
|
||||
}
|
||||
} else {
|
||||
if ((curState == 0x3 || !curState) && encPos != 0) {
|
||||
encState = (encPos == 2) ? 1 : 2;
|
||||
encPos = 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (encState != 0) {
|
||||
flags.isTurn_f = true;
|
||||
if (thisMls - fast_timer < _fast_timeout) {
|
||||
if (encState == 1)
|
||||
flags.isFastL_f = true;
|
||||
else if (encState == 2)
|
||||
flags.isFastR_f = true;
|
||||
fast_timer = thisMls;
|
||||
} else
|
||||
fast_timer = thisMls;
|
||||
#ifdef ENC_WITH_BUTTON
|
||||
// if (flags.use_button)
|
||||
// if (SW_state)
|
||||
// encState += 2;
|
||||
#endif
|
||||
}
|
||||
prevState = curState;
|
||||
flags.turn_flag = true;
|
||||
debounce_timer = thisMls;
|
||||
debounceDelta = 0ms;
|
||||
}
|
||||
}
|
||||
167
GyverEncoder.h
Normal file
167
GyverEncoder.h
Normal file
@@ -0,0 +1,167 @@
|
||||
#pragma once
|
||||
#include "mbed.h"
|
||||
|
||||
/*
|
||||
GyverEncoder - библиотека для отработки энкодера. Возможности:
|
||||
- Отработка поворота энкодера
|
||||
- Отработка "нажатого поворота"
|
||||
- Отработка "быстрого поворота"
|
||||
- Несколько алгоритмов опроса энкодера
|
||||
- Выбор подтяжки подключения энкодера
|
||||
- Работа с двумя типами экнодеров
|
||||
- Работа с внешним энкодером (через расширитель пинов и т.п.)
|
||||
- Отработка нажатия/удержания кнопки с антидребезгом
|
||||
|
||||
Документацию читай здесь: https://alexgyver.ru/encoder/
|
||||
Для максимально быстрого (в 2 раза быстрее) опроса энкодера рекомендуется использовать ядро GyverCore https://alexgyver.ru/gyvercore/
|
||||
|
||||
Версии:
|
||||
- 3.6 от 16.09.2019 - Возвращены дефайны настроек
|
||||
- 4.0 от 13.11.2019
|
||||
- Оптимизирован код
|
||||
- Исправлены баги
|
||||
- Добавлены другие алгоритмы опроса
|
||||
- Добавлена возможность полностью убрать кнопку (экономия памяти)
|
||||
- Добавлена возможность подключения внешнего энкодера
|
||||
- Добавлена настройка подтяжки пинов
|
||||
- 4.1
|
||||
- Исправлено изменение подтяжек
|
||||
|
||||
- 4.2
|
||||
- Добавлена поддержка TYPE1 для алгоритма PRECISE_ALGORITHM
|
||||
- Добавлена отработка двойного клика: isSingle / isDouble
|
||||
*/
|
||||
// ========= КОНСТАНТЫ ==========
|
||||
#define ENC_NO_BUTTON -1 // константа для работы без пина
|
||||
#define TYPE1 0 // полушаговый энкодер
|
||||
#define TYPE2 1 // полношаговый
|
||||
#define NORM 0 // направление вращения обычное
|
||||
#define REVERSE 1 // обратное
|
||||
#define MANUAL 0 // нужно вызывать функцию tick() вручную
|
||||
#define AUTO 1 // tick() входит во все остальные функции и опрашивается сама!
|
||||
#define HIGH_PULL 0 // внутренняя подтяжка к питанию (pinMode INPUT_PULLUP)
|
||||
#define LOW_PULL 1 // внешняя подтяжка к GND (pinMode INPUT)
|
||||
|
||||
// =========== НАСТРОЙКИ ===========
|
||||
// закомментируй строку, чтобы полностью убрать отработку кнопки из кода
|
||||
#define ENC_WITH_BUTTON
|
||||
|
||||
// тип подключения энкодера по умолчанию (LOW_PULL или HIGH_PULL)
|
||||
//#define DEFAULT_ENC_PULL LOW_PULL
|
||||
#define DEFAULT_ENC_PULL HIGH_PULL
|
||||
|
||||
// тип подключения кнопки энкодера по умолчанию (LOW_PULL или HIGH_PULL)
|
||||
//#define DEFAULT_BTN_PULL LOW_PULL
|
||||
#define DEFAULT_BTN_PULL HIGH_PULL
|
||||
|
||||
// алгоритмы опроса энкодера (раскомментировать нужный)
|
||||
//#define FAST_ALGORITHM // тик 10 мкс, быстрый, не справляется с люфтами
|
||||
//#define BINARY_ALGORITHM // тик 14 мкс, лучше справляется с люфтами
|
||||
#define PRECISE_ALGORITHM // тик 16 мкс, медленнее, но работает даже с убитым энкодером (по мотивам https://github.com/mathertel/RotaryEncoder)
|
||||
|
||||
// настройка антидребезга энкодера, кнопки, таймаута удержания и таймаута двойного клика
|
||||
#define ENC_DEBOUNCE_TURN 1ms
|
||||
#define ENC_DEBOUNCE_BUTTON 10ms
|
||||
#define ENC_HOLD_TIMEOUT 700ms
|
||||
#define ENC_DOUBLE_TIMEOUT 300ms
|
||||
|
||||
// The sample time in ms.
|
||||
const int SAMPLE_TIME = 1;
|
||||
|
||||
// The number of samples that must agree before a key state change is recognised.
|
||||
// 50 = 50ms for 1ms sample time.
|
||||
const int DEBOUNCE_COUNT = 50;
|
||||
|
||||
// The number of samples that must agree before a key held state is recognised.
|
||||
// 1000 = 1s for 1ms sample time.
|
||||
const int HOLD_COUNT = 1000;
|
||||
|
||||
// The number of samples that must agree before a key repeat state is recognised.
|
||||
// 200 = 200ms for 1ms sample time.
|
||||
const int REPEAT_COUNT = 200;
|
||||
|
||||
#pragma pack(push, 1)
|
||||
typedef struct
|
||||
{
|
||||
bool hold_flag : 1;
|
||||
bool butt_flag : 1;
|
||||
bool turn_flag : 1;
|
||||
bool isTurn_f : 1;
|
||||
bool isPress_f : 1;
|
||||
bool isRelease_f : 1;
|
||||
bool isHolded_f : 1;
|
||||
bool isFastR_f : 1;
|
||||
bool isFastL_f : 1;
|
||||
bool isReleaseHold_f : 1;
|
||||
bool enc_tick_mode : 1;
|
||||
bool enc_type : 1;
|
||||
bool use_button : 1;
|
||||
bool extCLK : 1;
|
||||
bool extDT : 1;
|
||||
bool extSW : 1;
|
||||
bool invBtn : 1;
|
||||
bool isSingle_f : 1;
|
||||
bool isDouble_f : 1;
|
||||
bool countFlag : 1;
|
||||
bool doubleFlag : 1;
|
||||
bool doubleAllow : 1;
|
||||
} GyverEncoderFlags;
|
||||
#pragma pack(pop)
|
||||
|
||||
// Варианты инициализации:
|
||||
// Encoder enc; // не привязан к пину
|
||||
// Encoder enc(пин CLK, пин DT); // энкодер без кнопки (ускоренный опрос)
|
||||
// Encoder enc(пин CLK, пин DT, пин SW); // энкодер с кнопкой
|
||||
// Encoder enc(пин CLK, пин DT, пин SW, тип); // энкодер с кнопкой и указанием типа
|
||||
// Encoder enc(пин CLK, пин DT, ENC_NO_BUTTON, тип); // энкодер без кнопкой и с указанием типа
|
||||
|
||||
class Encoder {
|
||||
public:
|
||||
Encoder(); // для непривязанного к пинам энкодера
|
||||
Encoder(PinName clk, PinName dt, PinName sw, bool type = false); // CLK, DT, SW, тип (TYPE1 / TYPE2) TYPE1 одношаговый, TYPE2 двухшаговый. Если ваш энкодер работает странно, смените тип
|
||||
|
||||
void tick(); // опрос энкодера, нужно вызывать постоянно или в прерывании
|
||||
void tick(bool clk, bool dt, bool sw = 0); // опрос "внешнего" энкодера
|
||||
void setType(bool type); // TYPE1 / TYPE2 - тип энкодера TYPE1 одношаговый, TYPE2 двухшаговый. Если ваш энкодер работает странно, смените тип
|
||||
void setPinMode(bool mode); // тип подключения энкодера, подтяжка HIGH_PULL (внутренняя) или LOW_PULL (внешняя на GND)
|
||||
void setBtnPinMode(bool mode); // тип подключения кнопки, подтяжка HIGH_PULL (внутренняя) или LOW_PULL (внешняя на GND)
|
||||
void setTickMode(bool tickMode); // MANUAL / AUTO - ручной или автоматический опрос энкодера функцией tick(). (по умолчанию ручной)
|
||||
void setDirection(bool direction); // NORM / REVERSE - направление вращения энкодера
|
||||
void setFastTimeout(Kernel::Clock::duration timeout); // установка таймаута быстрого поворота
|
||||
|
||||
bool isTurn(); // возвращает true при любом повороте, сама сбрасывается в false
|
||||
bool isRight(); // возвращает true при повороте направо, сама сбрасывается в false
|
||||
bool isLeft(); // возвращает true при повороте налево, сама сбрасывается в false
|
||||
bool isRightH(); // возвращает true при удержании кнопки и повороте направо, сама сбрасывается в false
|
||||
bool isLeftH(); // возвращает true при удержании кнопки и повороте налево, сама сбрасывается в false
|
||||
bool isFastR(); // возвращает true при быстром повороте
|
||||
bool isFastL(); // возвращает true при быстром повороте
|
||||
|
||||
bool isPress(); // возвращает true при нажатии кнопки, сама сбрасывается в false
|
||||
bool isRelease(); // возвращает true при отпускании кнопки, сама сбрасывается в false
|
||||
bool isClick(); // возвращает true при нажатии и отпускании кнопки, сама сбрасывается в false
|
||||
bool isHolded(); // возвращает true при удержании кнопки, сама сбрасывается в false
|
||||
bool isHold(); // возвращает true при удержании кнопки, НЕ СБРАСЫВАЕТСЯ
|
||||
bool isSingle(); // возвращает true при одиночном клике (после таймаута), сама сбрасывается в false
|
||||
bool isDouble(); // возвращает true при двойном клике, сама сбрасывается в false
|
||||
void start();
|
||||
void stop();
|
||||
|
||||
private:
|
||||
Thread* encThread;
|
||||
GyverEncoderFlags flags;
|
||||
Kernel::Clock::duration _fast_timeout = 50ms; // таймаут быстрого поворота
|
||||
uint8_t prevState = 0;
|
||||
uint8_t encState = 0; // 0 не крутился, 1 лево, 2 право, 3 лево нажат, 4 право нажат
|
||||
Kernel::Clock::time_point debounce_timer;
|
||||
Kernel::Clock::time_point fast_timer;
|
||||
DigitalIn* _CLK;
|
||||
DigitalIn* _DT;
|
||||
DigitalIn* _SW;
|
||||
|
||||
Kernel::Clock::duration debounceDelta;
|
||||
Kernel::Clock::time_point thisMls;
|
||||
|
||||
bool turnFlag = false, extTick = false, SW_state = false;
|
||||
void encoderThread();
|
||||
};
|
||||
575
debounce.h
Normal file
575
debounce.h
Normal file
@@ -0,0 +1,575 @@
|
||||
///\file
|
||||
|
||||
/******************************************************************************
|
||||
The MIT License(MIT)
|
||||
|
||||
Embedded Template Library.
|
||||
https://github.com/ETLCPP/etl
|
||||
https://www.etlcpp.com
|
||||
|
||||
Copyright(c) 2016 jwellbelove
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files(the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions :
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef ETL_DEBOUNCE_INCLUDED
|
||||
#define ETL_DEBOUNCE_INCLUDED
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
// #include "platform.h"
|
||||
// #include "static_assert.h"
|
||||
|
||||
namespace etl
|
||||
{
|
||||
namespace private_debounce
|
||||
{
|
||||
class debounce_base
|
||||
{
|
||||
public:
|
||||
typedef uint_least8_t flags_t;
|
||||
typedef uint16_t count_t;
|
||||
|
||||
//*************************************************************************
|
||||
/// Adds the new sample and clears the state change flag.
|
||||
/// If the sample has changed then the counter is reset.
|
||||
/// The last sample state is stored as a bit in the flags.
|
||||
//*************************************************************************
|
||||
void add_sample(bool sample)
|
||||
{
|
||||
// Changed from last time?
|
||||
if (sample != bool((flags & SAMPLE) != 0))
|
||||
{
|
||||
count = 0;
|
||||
flags = (flags & ~SAMPLE) | (sample ? SAMPLE : 0);
|
||||
}
|
||||
|
||||
flags &= ~CHANGE;
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Gets the current debouncer change state.
|
||||
///\return 'true' if the debouncer has changed state.
|
||||
//*************************************************************************
|
||||
bool has_changed() const
|
||||
{
|
||||
return (flags & CHANGE) != 0;
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Gets the current debouncer state.
|
||||
///\return 'true' if the debouncer is in the true state.
|
||||
//*************************************************************************
|
||||
bool is_set() const
|
||||
{
|
||||
return ((flags & STATE) > OFF);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Gets the debouncer hold state.
|
||||
///\return 'true' if the debouncer is in the hold state.
|
||||
//*************************************************************************
|
||||
bool is_held() const
|
||||
{
|
||||
return (flags & STATE) > ON;
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Gets the debouncer repeat state.
|
||||
///\return 'true' if the debouncer is repeating.
|
||||
//*************************************************************************
|
||||
bool is_repeating() const
|
||||
{
|
||||
return ((flags & STATE) == REPEATING);
|
||||
}
|
||||
|
||||
enum states
|
||||
{
|
||||
OFF = 0,
|
||||
ON = 1,
|
||||
HELD = 2,
|
||||
REPEATING = 3,
|
||||
STATE = 0x03,
|
||||
SAMPLE = 4,
|
||||
CHANGE = 8
|
||||
};
|
||||
|
||||
protected:
|
||||
//*************************************************************************
|
||||
/// Constructor.
|
||||
//*************************************************************************
|
||||
debounce_base(bool initial_state)
|
||||
: flags(initial_state ? ON : OFF),
|
||||
count(0)
|
||||
{
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Destructor.
|
||||
//*************************************************************************
|
||||
~debounce_base()
|
||||
{
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Gets the next state based on the inputs.
|
||||
//*************************************************************************
|
||||
void get_next(bool sample, bool condition_set, bool condition_clear, uint_least8_t state_table[][2])
|
||||
{
|
||||
int index1 = ((flags & STATE) * 2) + (sample ? 1 : 0);
|
||||
int index2 = (sample ? (condition_set ? 0 : 1) : (condition_clear ? 0 : 1));
|
||||
|
||||
flags_t next = flags;
|
||||
|
||||
next &= ~STATE;
|
||||
next |= state_table[index1][index2];
|
||||
|
||||
if (next != flags)
|
||||
{
|
||||
next |= CHANGE;
|
||||
}
|
||||
else
|
||||
{
|
||||
next &= ~CHANGE;
|
||||
}
|
||||
|
||||
flags = next;
|
||||
}
|
||||
|
||||
flags_t flags;
|
||||
count_t count;
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
/// State change logic for 2 state debounce.
|
||||
//***************************************************************************
|
||||
class debounce2 : public debounce_base
|
||||
{
|
||||
protected:
|
||||
debounce2(bool initial_state)
|
||||
: debounce_base(initial_state)
|
||||
{
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Destructor.
|
||||
//*************************************************************************
|
||||
~debounce2()
|
||||
{
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
///
|
||||
//*************************************************************************
|
||||
void set_state(bool sample, bool condition_set, bool condition_clear)
|
||||
{
|
||||
static uint_least8_t state_table[4][2] =
|
||||
{
|
||||
/* OFF 0 */ {debounce_base::OFF, debounce_base::OFF},
|
||||
/* OFF 1 */ {debounce_base::ON, debounce_base::OFF},
|
||||
/* ON 0 */ {debounce_base::OFF, debounce_base::ON},
|
||||
/* ON 1 */ {debounce_base::ON, debounce_base::ON},
|
||||
};
|
||||
|
||||
get_next(sample, condition_set, condition_clear, state_table);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
///
|
||||
//*************************************************************************
|
||||
bool process(bool sample, count_t valid_count)
|
||||
{
|
||||
add_sample(sample);
|
||||
|
||||
if (count < UINT16_MAX)
|
||||
{
|
||||
++count;
|
||||
|
||||
bool valid = (count == valid_count);
|
||||
|
||||
switch (flags & STATE)
|
||||
{
|
||||
case OFF:
|
||||
{
|
||||
set_state(sample, valid, valid);
|
||||
break;
|
||||
}
|
||||
|
||||
case ON:
|
||||
{
|
||||
set_state(sample, valid, valid);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (flags & CHANGE)
|
||||
{
|
||||
count = 0;
|
||||
}
|
||||
|
||||
return (flags & CHANGE);
|
||||
}
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
/// State change logic for 3 state debounce.
|
||||
//***************************************************************************
|
||||
class debounce3 : public debounce_base
|
||||
{
|
||||
protected:
|
||||
debounce3(bool initial_state)
|
||||
: debounce_base(initial_state)
|
||||
{
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Destructor.
|
||||
//*************************************************************************
|
||||
~debounce3()
|
||||
{
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
///
|
||||
//*************************************************************************
|
||||
void set_state(bool sample, bool condition_set, bool condition_clear)
|
||||
{
|
||||
static uint_least8_t state_table[6][2] =
|
||||
{
|
||||
/* OFF 0 */ {debounce_base::OFF, debounce_base::OFF},
|
||||
/* OFF 1 */ {debounce_base::ON, debounce_base::OFF},
|
||||
/* ON 0 */ {debounce_base::OFF, debounce_base::ON},
|
||||
/* ON 1 */ {debounce_base::HELD, debounce_base::ON},
|
||||
/* HELD 0 */ {debounce_base::OFF, debounce_base::HELD},
|
||||
/* HELD 1 */ {debounce_base::HELD, debounce_base::HELD}};
|
||||
|
||||
get_next(sample, condition_set, condition_clear, state_table);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
///
|
||||
//*************************************************************************
|
||||
bool process(bool sample, count_t valid_count, count_t hold_count)
|
||||
{
|
||||
add_sample(sample);
|
||||
|
||||
if (count < UINT16_MAX)
|
||||
{
|
||||
++count;
|
||||
|
||||
bool valid = (count == valid_count);
|
||||
bool hold = (count == hold_count);
|
||||
|
||||
switch (flags & STATE)
|
||||
{
|
||||
case OFF:
|
||||
{
|
||||
set_state(sample, valid, valid);
|
||||
break;
|
||||
}
|
||||
|
||||
case ON:
|
||||
{
|
||||
set_state(sample, hold, valid);
|
||||
break;
|
||||
}
|
||||
|
||||
case HELD:
|
||||
{
|
||||
set_state(sample, hold, valid);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (flags & CHANGE)
|
||||
{
|
||||
count = 0;
|
||||
}
|
||||
|
||||
return (flags & CHANGE);
|
||||
}
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
/// State change logic for 4 state debounce.
|
||||
//***************************************************************************
|
||||
class debounce4 : public debounce_base
|
||||
{
|
||||
protected:
|
||||
debounce4(bool initial_state)
|
||||
: debounce_base(initial_state)
|
||||
{
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Destructor.
|
||||
//*************************************************************************
|
||||
~debounce4()
|
||||
{
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
///
|
||||
//*************************************************************************
|
||||
void set_state(bool sample, bool condition_set, bool condition_clear)
|
||||
{
|
||||
static uint_least8_t state_table[8][2] =
|
||||
{
|
||||
/* OFF 0 */ {debounce_base::OFF, debounce_base::OFF},
|
||||
/* OFF 1 */ {debounce_base::ON, debounce_base::OFF},
|
||||
/* ON 0 */ {debounce_base::OFF, debounce_base::ON},
|
||||
/* ON 1 */ {debounce_base::HELD, debounce_base::ON},
|
||||
/* HELD 0 */ {debounce_base::OFF, debounce_base::HELD},
|
||||
/* HELD 1 */ {debounce_base::REPEATING, debounce_base::HELD},
|
||||
/* REPEATING 0 */ {debounce_base::OFF, debounce_base::REPEATING},
|
||||
/* REPEATING 1 */ {debounce_base::REPEATING, debounce_base::REPEATING}};
|
||||
|
||||
get_next(sample, condition_set, condition_clear, state_table);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
///
|
||||
//*************************************************************************
|
||||
bool process(bool sample, count_t valid_count, count_t hold_count, count_t repeat_count)
|
||||
{
|
||||
add_sample(sample);
|
||||
|
||||
if (count < UINT16_MAX)
|
||||
{
|
||||
++count;
|
||||
|
||||
bool valid = (count == valid_count);
|
||||
bool hold = (count == hold_count);
|
||||
bool repeat = (count == repeat_count);
|
||||
|
||||
switch (flags & STATE)
|
||||
{
|
||||
case OFF:
|
||||
{
|
||||
set_state(sample, valid, valid);
|
||||
break;
|
||||
}
|
||||
|
||||
case ON:
|
||||
{
|
||||
set_state(sample, hold, valid);
|
||||
break;
|
||||
}
|
||||
|
||||
case HELD:
|
||||
{
|
||||
set_state(sample, repeat, valid);
|
||||
break;
|
||||
}
|
||||
|
||||
case REPEATING:
|
||||
{
|
||||
set_state(sample, repeat, valid);
|
||||
|
||||
if (sample && repeat)
|
||||
{
|
||||
count = 0;
|
||||
flags |= CHANGE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (flags & CHANGE)
|
||||
{
|
||||
count = 0;
|
||||
}
|
||||
|
||||
return (flags & CHANGE);
|
||||
}
|
||||
};
|
||||
} // namespace private_debounce
|
||||
|
||||
//***************************************************************************
|
||||
/// A class to debounce signals.
|
||||
/// Fixed Valid/Hold/Repeating values.
|
||||
//***************************************************************************
|
||||
template <const uint16_t VALID_COUNT = 0, const uint16_t HOLD_COUNT = 0, const uint16_t REPEAT_COUNT = 0>
|
||||
class debounce : public private_debounce::debounce4
|
||||
{
|
||||
public:
|
||||
//*************************************************************************
|
||||
/// Constructor.
|
||||
//*************************************************************************
|
||||
debounce(bool initial_state = false)
|
||||
: debounce4(initial_state)
|
||||
{
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Adds a new sample.
|
||||
/// Returns 'true' if the debouncer changes state.
|
||||
///\param sample The new sample.
|
||||
///\return 'true' if the debouncer changed state.
|
||||
//*************************************************************************
|
||||
bool add(bool sample)
|
||||
{
|
||||
return process(sample, VALID_COUNT, HOLD_COUNT, REPEAT_COUNT);
|
||||
}
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
/// A class to debounce signals.
|
||||
/// Fixed Valid/Hold values.
|
||||
//***************************************************************************
|
||||
template <const uint16_t VALID_COUNT, const uint16_t HOLD_COUNT>
|
||||
class debounce<VALID_COUNT, HOLD_COUNT, 0> : public private_debounce::debounce3
|
||||
{
|
||||
public:
|
||||
//*************************************************************************
|
||||
/// Constructor.
|
||||
//*************************************************************************
|
||||
debounce(bool initial_state = false)
|
||||
: debounce3(initial_state)
|
||||
{
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Adds a new sample.
|
||||
/// Returns 'true' if the debouncer changes state from...
|
||||
/// 1. Clear to Set.
|
||||
/// 2. Set to Clear.
|
||||
/// 3. Not Held to Held.
|
||||
///\param sample The new sample.
|
||||
///\return 'true' if the debouncer changed state.
|
||||
//*************************************************************************
|
||||
bool add(bool sample)
|
||||
{
|
||||
return process(sample, VALID_COUNT, HOLD_COUNT);
|
||||
}
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
/// A class to debounce signals.
|
||||
/// Fixed Valid value.
|
||||
//***************************************************************************
|
||||
template <const uint16_t VALID_COUNT>
|
||||
class debounce<VALID_COUNT, 0, 0> : public private_debounce::debounce2
|
||||
{
|
||||
public:
|
||||
//*************************************************************************
|
||||
/// Constructor.
|
||||
//*************************************************************************
|
||||
debounce(bool initial_state = false)
|
||||
: debounce2(initial_state)
|
||||
{
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Adds a new sample.
|
||||
/// Returns 'true' if the debouncer changes state from...
|
||||
/// 1. Clear to Set.
|
||||
/// 2. Set to Clear.
|
||||
///\param sample The new sample.
|
||||
///\return 'true' if the debouncer changed state.
|
||||
//*************************************************************************
|
||||
bool add(bool sample)
|
||||
{
|
||||
return process(sample, VALID_COUNT);
|
||||
}
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
/// A class to debounce signals.
|
||||
/// Variable Valid/Hold/Repeating values.
|
||||
//***************************************************************************
|
||||
template <>
|
||||
class debounce<0, 0, 0> : public private_debounce::debounce4
|
||||
{
|
||||
public:
|
||||
//*************************************************************************
|
||||
/// Constructor.
|
||||
///\param initial_state The initial state. Default = false.
|
||||
//*************************************************************************
|
||||
debounce(bool initial_state = false)
|
||||
: debounce4(initial_state),
|
||||
valid_count(1),
|
||||
hold_count(0),
|
||||
repeat_count(0)
|
||||
{
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Constructor.
|
||||
///\param valid_count The count for a valid state..
|
||||
///\param hold_count The count after valid_count for a hold state. Default = 0.
|
||||
///\param repeat_count The count after hold_count for a key repeat. Default = 0.
|
||||
//*************************************************************************
|
||||
debounce(count_t valid, count_t hold = 0, count_t repeat = 0)
|
||||
: debounce4(false)
|
||||
{
|
||||
set(valid, hold, repeat);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Constructor.
|
||||
//*************************************************************************
|
||||
void set(count_t valid, count_t hold = 0, count_t repeat = 0)
|
||||
{
|
||||
valid_count = valid;
|
||||
hold_count = hold;
|
||||
repeat_count = repeat;
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Adds a new sample.
|
||||
/// Returns 'true' if the debouncer changes state from...
|
||||
/// 1. Clear to Set.
|
||||
/// 2. Set to Clear.
|
||||
/// 3. Not Held to Held.
|
||||
/// 4. Key repeats.
|
||||
///\param sample The new sample.
|
||||
///\return 'true' if the debouncer changed state.
|
||||
//*************************************************************************
|
||||
bool add(bool sample)
|
||||
{
|
||||
return process(sample, valid_count, hold_count, repeat_count);
|
||||
}
|
||||
|
||||
private:
|
||||
count_t valid_count;
|
||||
count_t hold_count;
|
||||
count_t repeat_count;
|
||||
};
|
||||
} // namespace etl
|
||||
|
||||
#endif
|
||||
13
library.json
Executable file
13
library.json
Executable file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"name": "Gyver Encoder",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/AlexGyver/GyverLibs"
|
||||
},
|
||||
"build": {
|
||||
"srcFilter": [
|
||||
"+<*>"
|
||||
],
|
||||
"flags": "-I./"
|
||||
}
|
||||
}
|
||||
134
platform.h
Normal file
134
platform.h
Normal file
@@ -0,0 +1,134 @@
|
||||
///\file
|
||||
|
||||
/******************************************************************************
|
||||
The MIT License(MIT)
|
||||
|
||||
Embedded Template Library.
|
||||
https://github.com/ETLCPP/etl
|
||||
https://www.etlcpp.com
|
||||
|
||||
Copyright(c) 2016 jwellbelove
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files(the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions :
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef ETL_PLATFORM_INCLUDED
|
||||
#define ETL_PLATFORM_INCLUDED
|
||||
|
||||
#include <stdint.h>
|
||||
#include <limits.h>
|
||||
|
||||
// Some targets do not support 8bit types.
|
||||
#define ETL_8BIT_SUPPORT (CHAR_BIT == 8)
|
||||
|
||||
// Define a debug macro
|
||||
#if !defined(ETL_DEBUG)
|
||||
#if defined(_DEBUG) || defined(DEBUG)
|
||||
#define ETL_DEBUG
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Determine the bit width of the platform.
|
||||
#define ETL_PLATFORM_16BIT (UINT16_MAX == UINTPTR_MAX)
|
||||
#define ETL_PLATFORM_32BIT (UINT32_MAX == UINTPTR_MAX)
|
||||
#define ETL_PLATFORM_64BIT (UINT64_MAX == UINTPTR_MAX)
|
||||
|
||||
// Include the user's profile definition.
|
||||
#include "etl_profile.h"
|
||||
|
||||
// Figure out things about the compiler, if haven't already done so in etl_profile.h
|
||||
#include "profiles/determine_compiler_version.h"
|
||||
#include "profiles/determine_compiler_language_support.h"
|
||||
|
||||
// See if we can determine the OS we're compiling on, if haven't already done so in etl_profile.h
|
||||
#include "profiles/determine_development_os.h"
|
||||
|
||||
#if defined(ETL_FORCE_EXPLICIT_STRING_CONVERSION_FROM_CHAR)
|
||||
#define ETL_EXPLICIT_STRING_FROM_CHAR explicit
|
||||
#else
|
||||
#define ETL_EXPLICIT_STRING_FROM_CHAR
|
||||
#endif
|
||||
|
||||
// The macros below are dependent on the profile.
|
||||
// C++11
|
||||
#if ETL_CPP11_SUPPORTED && !defined(ETL_FORCE_NO_ADVANCED_CPP)
|
||||
#define ETL_CONSTEXPR constexpr
|
||||
#define ETL_CONST_OR_CONSTEXPR constexpr
|
||||
#define ETL_DELETE = delete
|
||||
#define ETL_EXPLICIT explicit
|
||||
#define ETL_OVERRIDE override
|
||||
#define ETL_FINAL final
|
||||
#define ETL_NORETURN [[noreturn]]
|
||||
|
||||
#if defined(ETL_EXCEPTIONS_DISABLED)
|
||||
#define ETL_NOEXCEPT
|
||||
#define ETL_NOEXCEPT_EXPR(expression)
|
||||
#else
|
||||
#define ETL_NOEXCEPT noexcept
|
||||
#define ETL_NOEXCEPT_EXPR(expression) noexcept(expression)
|
||||
#endif
|
||||
#else
|
||||
#define ETL_CONSTEXPR
|
||||
#define ETL_CONST_OR_CONSTEXPR const
|
||||
#define ETL_DELETE
|
||||
#define ETL_EXPLICIT
|
||||
#define ETL_OVERRIDE
|
||||
#define ETL_FINAL
|
||||
#define ETL_NORETURN
|
||||
#define ETL_NOEXCEPT
|
||||
#define ETL_NOEXCEPT_EXPR(expression)
|
||||
#endif
|
||||
|
||||
// C++14
|
||||
#if ETL_CPP14_SUPPORTED && !defined(ETL_FORCE_NO_ADVANCED_CPP)
|
||||
#define ETL_CONSTEXPR14 constexpr
|
||||
#define ETL_DEPRECATED [[deprecated]]
|
||||
#define ETL_DEPRECATED_REASON(reason) [[deprecated(reason)]]
|
||||
#else
|
||||
#define ETL_CONSTEXPR14
|
||||
#define ETL_DEPRECATED
|
||||
#define ETL_DEPRECATED_REASON(reason)
|
||||
#endif
|
||||
|
||||
// C++17
|
||||
#if ETL_CPP17_SUPPORTED && !defined(ETL_FORCE_NO_ADVANCED_CPP)
|
||||
#define ETL_CONSTEXPR17 constexpr
|
||||
#define ETL_IF_CONSTEXPR constexpr
|
||||
#define ETL_NODISCARD [[nodiscard]]
|
||||
#define ETL_FALLTHROUGH [[fallthrough]]
|
||||
#else
|
||||
#define ETL_CONSTEXPR17
|
||||
#define ETL_IF_CONSTEXPR
|
||||
#define ETL_NODISCARD
|
||||
#define ETL_FALLTHROUGH
|
||||
#endif
|
||||
|
||||
// C++20
|
||||
#if ETL_CPP20_SUPPORTED && !defined(ETL_FORCE_NO_ADVANCED_CPP)
|
||||
#define ETL_LIKELY [[likely]]
|
||||
#define ETL_UNLIKELY [[unlikely]]
|
||||
#else
|
||||
#define ETL_LIKELY
|
||||
#define ETL_UNLIKELY
|
||||
#endif
|
||||
|
||||
// Sort out namespaces for STL/No STL options.
|
||||
#include "private/choose_namespace.h"
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user