Screen update event.

This commit is contained in:
Balazs Kelemen 2022-01-13 09:19:36 +01:00
parent f7c8cabdfe
commit c5b95ed3c0
7 changed files with 55 additions and 19 deletions

View File

@ -34,7 +34,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "mesh-pb-constants.h" #include "mesh-pb-constants.h"
#include "mesh/Channels.h" #include "mesh/Channels.h"
#include "plugins/TextMessagePlugin.h" #include "plugins/TextMessagePlugin.h"
#include "plugins/CannedMessagePlugin.h"
#include "sleep.h" #include "sleep.h"
#include "target_specific.h" #include "target_specific.h"
#include "utils.h" #include "utils.h"
@ -821,9 +820,9 @@ void Screen::setup()
nodeStatusObserver.observe(&nodeStatus->onNewStatus); nodeStatusObserver.observe(&nodeStatus->onNewStatus);
if (textMessagePlugin) if (textMessagePlugin)
textMessageObserver.observe(textMessagePlugin); textMessageObserver.observe(textMessagePlugin);
// TODO: find a nicer way to notify screen about refresh
if (cannedMessagePlugin) // Plugins can notify screen about refresh
cannedMessageObserver.observe(cannedMessagePlugin); MeshPlugin::observeUIEvents(&uiFrameEventObserver);
} }
void Screen::forceDisplay() void Screen::forceDisplay()
@ -1461,14 +1460,21 @@ int Screen::handleTextMessage(const MeshPacket *packet)
return 0; return 0;
} }
int Screen::handleCannedMessage(const meshtastic::Status *packet) int Screen::handleUIFrameEvent(const UIFrameEvent *event)
{ {
if (showingNormalScreen) { if (showingNormalScreen) {
setFrames(); // Regen the list of screens (will show new text message) if (event->frameChanged)
{
setFrames(); // Regen the list of screens (will show new text message)
}
else if (event->needRedraw)
{
setFastFramerate();
// TODO: We might also want switch to corresponding frame,
// but we don't know the exact frame number.
//ui.switchToFrame(0);
}
} }
// TODO: We might also want switch to corresponding frame,
// but we don't know the exact frame number.
//ui.switchToFrame(0);
return 0; return 0;
} }

View File

@ -40,6 +40,7 @@ class Screen
#include "concurrency/OSThread.h" #include "concurrency/OSThread.h"
#include "power.h" #include "power.h"
#include <string> #include <string>
#include "mesh/MeshPlugin.h"
// 0 to 255, though particular variants might define different defaults // 0 to 255, though particular variants might define different defaults
#ifndef BRIGHTNESS_DEFAULT #ifndef BRIGHTNESS_DEFAULT
@ -90,8 +91,8 @@ class Screen : public concurrency::OSThread
CallbackObserver<Screen, const meshtastic::Status *>(this, &Screen::handleStatusUpdate); CallbackObserver<Screen, const meshtastic::Status *>(this, &Screen::handleStatusUpdate);
CallbackObserver<Screen, const MeshPacket *> textMessageObserver = CallbackObserver<Screen, const MeshPacket *> textMessageObserver =
CallbackObserver<Screen, const MeshPacket *>(this, &Screen::handleTextMessage); CallbackObserver<Screen, const MeshPacket *>(this, &Screen::handleTextMessage);
CallbackObserver<Screen, const meshtastic::Status *> cannedMessageObserver = CallbackObserver<Screen, const UIFrameEvent *> uiFrameEventObserver =
CallbackObserver<Screen, const meshtastic::Status *>(this, &Screen::handleCannedMessage); CallbackObserver<Screen, const UIFrameEvent *>(this, &Screen::handleUIFrameEvent);
public: public:
Screen(uint8_t address, int sda = -1, int scl = -1); Screen(uint8_t address, int sda = -1, int scl = -1);
@ -220,7 +221,7 @@ class Screen : public concurrency::OSThread
int handleStatusUpdate(const meshtastic::Status *arg); int handleStatusUpdate(const meshtastic::Status *arg);
int handleTextMessage(const MeshPacket *arg); int handleTextMessage(const MeshPacket *arg);
int handleCannedMessage(const meshtastic::Status *arg); int handleUIFrameEvent(const UIFrameEvent *arg);
/// Used to force (super slow) eink displays to draw critical frames /// Used to force (super slow) eink displays to draw critical frames
void forceDisplay(); void forceDisplay();

View File

@ -235,3 +235,18 @@ std::vector<MeshPlugin *> MeshPlugin::GetMeshPluginsWithUIFrames()
} }
return pluginsWithUIFrames; return pluginsWithUIFrames;
} }
void MeshPlugin::observeUIEvents(
Observer<const UIFrameEvent *> *observer)
{
std::vector<MeshPlugin *> pluginsWithUIFrames;
for (auto i = plugins->begin(); i != plugins->end(); ++i) {
auto &pi = **i;
Observable<const UIFrameEvent *> *observable =
pi.getUIFrameObservable();
if (observable != NULL) {
DEBUG_MSG("Plugin wants a UI Frame\n");
observer->observe(observable);
}
}
}

View File

@ -21,6 +21,14 @@ enum class ProcessMessage
STOP = 1, STOP = 1,
}; };
/*
* This struct is used by Screen to figure out whether screen frame should be updated.
*/
typedef struct _UIFrameEvent {
bool frameChanged;
bool needRedraw;
} UIFrameEvent;
/** A baseclass for any mesh "plugin". /** A baseclass for any mesh "plugin".
* *
* A plugin allows you to add new features to meshtastic device code, without needing to know messaging details. * A plugin allows you to add new features to meshtastic device code, without needing to know messaging details.
@ -48,6 +56,7 @@ class MeshPlugin
static void callPlugins(const MeshPacket &mp, RxSource src = RX_SRC_RADIO); static void callPlugins(const MeshPacket &mp, RxSource src = RX_SRC_RADIO);
static std::vector<MeshPlugin *> GetMeshPluginsWithUIFrames(); static std::vector<MeshPlugin *> GetMeshPluginsWithUIFrames();
static void observeUIEvents(Observer<const UIFrameEvent *> *observer);
#ifndef NO_SCREEN #ifndef NO_SCREEN
virtual void drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y) { return; } virtual void drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y) { return; }
#endif #endif
@ -119,6 +128,7 @@ class MeshPlugin
* @return true if you want to be alloced a UI screen frame * @return true if you want to be alloced a UI screen frame
*/ */
virtual bool wantUIFrame() { return false; } virtual bool wantUIFrame() { return false; }
virtual Observable<const UIFrameEvent *>* getUIFrameObservable() { return NULL; }
MeshPacket *allocAckNak(Routing_Error err, NodeNum to, PacketId idFrom, ChannelIndex chIndex); MeshPacket *allocAckNak(Routing_Error err, NodeNum to, PacketId idFrom, ChannelIndex chIndex);

View File

@ -146,17 +146,19 @@ int32_t CannedMessagePlugin::runOnce()
return 30000; // TODO: should return MAX_VAL return 30000; // TODO: should return MAX_VAL
} }
DEBUG_MSG("Check status\n"); DEBUG_MSG("Check status\n");
UIFrameEvent e = {false, true};
if (this->sendingState == SENDING_STATE_ACTIVE) if (this->sendingState == SENDING_STATE_ACTIVE)
{ {
// TODO: might have some feedback of sendig state // TODO: might have some feedback of sendig state
this->sendingState = SENDING_STATE_NONE; this->sendingState = SENDING_STATE_NONE;
this->notifyObservers(NULL); this->notifyObservers(&e);
} }
else if ((this->action != CANNED_MESSAGE_ACTION_NONE) else if ((this->action != CANNED_MESSAGE_ACTION_NONE)
&& (this->currentMessageIndex == -1)) && (this->currentMessageIndex == -1))
{ {
this->currentMessageIndex = 0; this->currentMessageIndex = 0;
DEBUG_MSG("First touch.\n"); DEBUG_MSG("First touch.\n");
e.frameChanged = true;
} }
else if (this->action == CANNED_MESSAGE_ACTION_SELECT) else if (this->action == CANNED_MESSAGE_ACTION_SELECT)
{ {
@ -166,7 +168,7 @@ int32_t CannedMessagePlugin::runOnce()
true); true);
this->sendingState = SENDING_STATE_ACTIVE; this->sendingState = SENDING_STATE_ACTIVE;
this->currentMessageIndex = -1; this->currentMessageIndex = -1;
this->notifyObservers(NULL); this->notifyObservers(&e);
return 2000; return 2000;
} }
else if (this->action == CANNED_MESSAGE_ACTION_UP) else if (this->action == CANNED_MESSAGE_ACTION_UP)
@ -182,7 +184,7 @@ int32_t CannedMessagePlugin::runOnce()
if (this->action != CANNED_MESSAGE_ACTION_NONE) if (this->action != CANNED_MESSAGE_ACTION_NONE)
{ {
this->action = CANNED_MESSAGE_ACTION_NONE; this->action = CANNED_MESSAGE_ACTION_NONE;
this->notifyObservers(NULL); this->notifyObservers(&e);
} }
return 30000; // TODO: should return MAX_VAL return 30000; // TODO: should return MAX_VAL

View File

@ -17,11 +17,12 @@ enum cannedMessagePluginSendigState
SENDING_STATE_ACTIVE SENDING_STATE_ACTIVE
}; };
#define CANNED_MESSAGE_PLUGIN_MESSAGE_MAX_COUNT 50 #define CANNED_MESSAGE_PLUGIN_MESSAGE_MAX_COUNT 50
class CannedMessagePlugin : class CannedMessagePlugin :
public SinglePortPlugin, public SinglePortPlugin,
public Observable<const meshtastic::Status *>, public Observable<const UIFrameEvent *>,
private concurrency::OSThread private concurrency::OSThread
{ {
CallbackObserver<CannedMessagePlugin, const InputEvent *> inputObserver = CallbackObserver<CannedMessagePlugin, const InputEvent *> inputObserver =
@ -53,6 +54,7 @@ class CannedMessagePlugin :
int handleInputEvent(const InputEvent *event); int handleInputEvent(const InputEvent *event);
virtual bool wantUIFrame() { return this->shouldDraw(); } virtual bool wantUIFrame() { return this->shouldDraw(); }
virtual Observable<const UIFrameEvent *>* getUIFrameObservable() { return this; }
virtual void drawFrame( virtual void drawFrame(
OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y); OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y);

View File

@ -65,7 +65,7 @@ int32_t RotaryEncoderInterruptBase::runOnce()
this->action = ROTARY_ACTION_NONE; this->action = ROTARY_ACTION_NONE;
return 30000; return 30000; // TODO: technically this can be MAX_INT
} }
@ -73,7 +73,7 @@ void RotaryEncoderInterruptBase::intPressHandler()
{ {
this->action = ROTARY_ACTION_PRESSED; this->action = ROTARY_ACTION_PRESSED;
runned(millis()); runned(millis());
setInterval(20); setInterval(20); // TODO: this modifies a non-volatile variable!
} }
void RotaryEncoderInterruptBase::intAHandler() void RotaryEncoderInterruptBase::intAHandler()
@ -144,7 +144,7 @@ RotaryEncoderInterruptBaseStateType RotaryEncoderInterruptBase::intHandler(
newState = ROTARY_EVENT_CLEARED; newState = ROTARY_EVENT_CLEARED;
} }
runned(millis()); runned(millis());
setInterval(50); setInterval(50); // TODO: this modifies a non-volatile variable!
return newState; return newState;
} }