firmware/src/plugins/CannedMessagePlugin.cpp

189 lines
5.0 KiB
C++
Raw Normal View History

2022-01-04 18:42:28 +00:00
#include "configuration.h"
#include "CannedMessagePlugin.h"
#include "MeshService.h"
#include "main.h"
#include <assert.h>
#define PIN_PUSH 21
#define PIN_A 22
#define PIN_B 23
// TODO: add UP-DOWN mode
#define ROTARY_MODE
CannedMessagePlugin *cannedMessagePlugin;
void IRAM_ATTR EXT_INT_PUSH()
{
cannedMessagePlugin->select();
}
void IRAM_ATTR EXT_INT_DIRECTION_A()
{
cannedMessagePlugin->directionA();
}
void IRAM_ATTR EXT_INT_DIRECTION_B()
{
cannedMessagePlugin->directionB();
}
CannedMessagePlugin::CannedMessagePlugin()
: SinglePortPlugin("canned", PortNum_TEXT_MESSAGE_APP), concurrency::OSThread("CannedMessagePlugin")
{
// TODO: make pins configurable
pinMode(PIN_PUSH, INPUT_PULLUP);
pinMode(PIN_A, INPUT_PULLUP);
pinMode(PIN_B, INPUT_PULLUP);
attachInterrupt(PIN_PUSH, EXT_INT_PUSH, RISING);
#ifdef ROTARY_MODE
attachInterrupt(PIN_A, EXT_INT_DIRECTION_A, CHANGE);
attachInterrupt(PIN_B, EXT_INT_DIRECTION_B, CHANGE);
this->rotaryLevelA = digitalRead(PIN_A);
this->rotaryLevelB = digitalRead(PIN_B);
#endif
}
2022-01-04 18:43:06 +00:00
void CannedMessagePlugin::sendText(NodeNum dest,
const char* message,
bool wantReplies)
2022-01-04 18:42:28 +00:00
{
MeshPacket *p = allocDataPacket();
p->to = dest;
2022-01-04 21:02:16 +00:00
p->decoded.payload.size = strlen(message);
memcpy(p->decoded.payload.bytes, message, p->decoded.payload.size);
2022-01-04 18:42:28 +00:00
// PacketId prevPacketId = p->id; // In case we need it later.
DEBUG_MSG("Sending message id=%d, msg=%.*s\n",
p->id, p->decoded.payload.size, p->decoded.payload.bytes);
service.sendToMesh(p);
}
int32_t CannedMessagePlugin::runOnce()
{
2022-01-04 21:02:16 +00:00
if (this->sendingState == SENDING_STATE_ACTIVE)
{
// TODO: might have some feedback of sendig state
this->sendingState = SENDING_STATE_NONE;
this->notifyObservers(NULL);
}
else if ((this->action != ACTION_NONE)
2022-01-04 18:43:06 +00:00
&& (this->currentMessageIndex == -1))
2022-01-04 18:42:28 +00:00
{
2022-01-04 18:43:06 +00:00
this->currentMessageIndex = 0;
DEBUG_MSG("First touch. Current message:%s\n",
this->getCurrentMessage());
2022-01-04 18:42:28 +00:00
}
2022-01-04 18:43:06 +00:00
else if (this->action == ACTION_PRESSED)
2022-01-04 18:42:28 +00:00
{
2022-01-04 18:43:06 +00:00
sendText(
NODENUM_BROADCAST,
cannedMessagePluginMessages[this->currentMessageIndex],
true);
2022-01-04 21:02:16 +00:00
this->sendingState = SENDING_STATE_ACTIVE;
this->currentMessageIndex = -1;
return 2000;
2022-01-04 18:42:28 +00:00
}
else if (this->action == ACTION_UP)
{
this->currentMessageIndex = getPrevIndex();
2022-01-04 18:43:06 +00:00
DEBUG_MSG("MOVE UP. Current message:%s\n",
this->getCurrentMessage());
2022-01-04 18:42:28 +00:00
}
else if (this->action == ACTION_DOWN)
{
this->currentMessageIndex = this->getNextIndex();
2022-01-04 18:43:06 +00:00
DEBUG_MSG("MOVE DOWN. Current message:%s\n",
this->getCurrentMessage());
2022-01-04 18:42:28 +00:00
}
2022-01-04 18:43:06 +00:00
if (this->action != ACTION_NONE)
{
this->action = ACTION_NONE;
this->notifyObservers(NULL);
}
return 30000;
2022-01-04 18:42:28 +00:00
}
void CannedMessagePlugin::select()
{
this->action = ACTION_PRESSED;
setInterval(20);
}
/**
* @brief Rotary action implementation.
* We assume, the following pin setup:
* A --||
* GND --||]========
* B --||
*
* @return The new level of the actual pin (that is actualPinCurrentLevel).
*/
void CannedMessagePlugin::directionA()
{
#ifdef ROTARY_MODE
// CW rotation (at least on most common rotary encoders)
int currentLevelA = digitalRead(PIN_A);
if (this->rotaryLevelA == currentLevelA)
{
return;
}
this->rotaryLevelA = currentLevelA;
bool pinARaising = currentLevelA == HIGH;
if (pinARaising && (this->rotaryLevelB == LOW))
{
if (this->rotaryStateCCW == EVENT_CLEARED)
{
this->rotaryStateCCW = EVENT_OCCURRED;
if ((this->action == ACTION_NONE)
|| (this->action == (cwRotationMeaning == ACTION_UP ? ACTION_UP : ACTION_DOWN)))
{
this->action = cwRotationMeaning == ACTION_UP ? ACTION_DOWN : ACTION_UP;
}
}
}
else if (!pinARaising && (this->rotaryLevelB == HIGH))
{
// Logic to prevent bouncing.
this->rotaryStateCCW = EVENT_CLEARED;
}
#endif
setInterval(30);
}
void CannedMessagePlugin::directionB()
{
#ifdef ROTARY_MODE
// CW rotation (at least on most common rotary encoders)
int currentLevelB = digitalRead(PIN_B);
if (this->rotaryLevelB == currentLevelB)
{
return;
}
this->rotaryLevelB = currentLevelB;
bool pinBRaising = currentLevelB == HIGH;
if (pinBRaising && (this->rotaryLevelA == LOW))
{
if (this->rotaryStateCW == EVENT_CLEARED)
{
this->rotaryStateCW = EVENT_OCCURRED;
if ((this->action == ACTION_NONE)
|| (this->action == (cwRotationMeaning == ACTION_UP ? ACTION_DOWN : ACTION_UP)))
{
this->action = cwRotationMeaning == ACTION_UP ? ACTION_UP : ACTION_DOWN;
}
}
}
else if (!pinBRaising && (this->rotaryLevelA == HIGH))
{
// Logic to prevent bouncing.
this->rotaryStateCW = EVENT_CLEARED;
}
#endif
setInterval(30);
}