Skip to content

Commit a589780

Browse files
authored
Merge pull request #3 from crossan007/adjust_frame_notifications
add frame notification bounceyness
2 parents 35d7962 + 22c7eef commit a589780

File tree

2 files changed

+109
-1
lines changed

2 files changed

+109
-1
lines changed

src/OLEDDisplayUi.cpp

Lines changed: 79 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ OLEDDisplayUi::OLEDDisplayUi(OLEDDisplay *display) {
4646
indicatorDirection = LEFT_RIGHT;
4747
activeSymbol = ANIMATION_activeSymbol;
4848
inactiveSymbol = ANIMATION_inactiveSymbol;
49+
notifyingFrameOffsetAmplitude = 10;
4950
frameAnimationDirection = SLIDE_RIGHT;
5051
lastTransitionDirection = 1;
5152
frameCount = 0;
@@ -56,6 +57,7 @@ OLEDDisplayUi::OLEDDisplayUi(OLEDDisplay *display) {
5657
updateInterval = 33;
5758
state.lastUpdate = 0;
5859
state.ticksSinceLastStateSwitch = 0;
60+
state.ticks = 0;
5961
state.frameState = FIXED;
6062
state.currentFrame = 0;
6163
state.frameTransitionDirection = 1;
@@ -66,6 +68,7 @@ OLEDDisplayUi::OLEDDisplayUi(OLEDDisplay *display) {
6668
autoTransition = true;
6769
setTimePerFrame(5000);
6870
setTimePerTransition(500);
71+
frameNotificationCallbackFunction = nullptr;
6972
}
7073

7174
void OLEDDisplayUi::init() {
@@ -220,6 +223,54 @@ void OLEDDisplayUi::transitionToFrame(uint8_t frame) {
220223
this->state.frameTransitionDirection = frame < this->state.currentFrame ? -1 : 1;
221224
}
222225

226+
bool OLEDDisplayUi::addFrameToNotifications(uint32_t frameToAdd, bool force) {
227+
switch (this->state.frameState) {
228+
case IN_TRANSITION:
229+
if(!force && this->state.transitionFrameTarget == frameToAdd)
230+
// if we're in transition, and being asked to set the to-be-current frame
231+
// as having a notifiction, just don't (unless we're forced)
232+
return false;
233+
break;
234+
case FIXED:
235+
if(!force && this->state.currentFrame == frameToAdd)
236+
// if we're on a fixed frame, and being asked to set the current frame
237+
// as having a notifiction, just don't (unless we're forced)
238+
return false;
239+
break;
240+
}
241+
// nothing is preventing us from setting the requested frame as having a notification, so
242+
// do it.
243+
this->state.notifyingFrames.push_back(frameToAdd);
244+
return true;
245+
}
246+
247+
bool OLEDDisplayUi::removeFrameFromNotifications(uint32_t frameToRemove) {
248+
// We've been told that a frame no longer needs to be notifying
249+
250+
auto it = std::find(this->state.notifyingFrames.begin(), this->state.notifyingFrames.end(), frameToRemove);
251+
if (it != this->state.notifyingFrames.end()) {
252+
using std::swap;
253+
// swap the one to be removed with the last element
254+
// and remove the item at the end of the container
255+
// to prevent moving all items after '5' by one
256+
swap(*it, this->state.notifyingFrames.back());
257+
this->state.notifyingFrames.pop_back();
258+
return true;
259+
}
260+
return false;
261+
}
262+
263+
void OLEDDisplayUi::setFrameNotificationCallback(FrameNotificationCallback* frameNotificationCallbackFunction) {
264+
this->frameNotificationCallbackFunction = frameNotificationCallbackFunction;
265+
}
266+
267+
uint32_t OLEDDisplayUi::getFirstNotifyingFrame() {
268+
if (this->state.notifyingFrames.size() == 0){
269+
return -1;
270+
}
271+
return this->state.notifyingFrames[0];
272+
}
273+
223274

224275
// -/----- State information -----\-
225276
OLEDDisplayUiState* OLEDDisplayUi::getUiState(){
@@ -256,6 +307,7 @@ int16_t OLEDDisplayUi::update(){
256307

257308
void OLEDDisplayUi::tick() {
258309
this->state.ticksSinceLastStateSwitch++;
310+
this->state.ticks++;
259311

260312
switch (this->state.frameState) {
261313
case IN_TRANSITION:
@@ -350,6 +402,10 @@ void OLEDDisplayUi::drawFrame(){
350402
this->state.transitionFrameRelationship = INCOMING;
351403
//Since we're IN_TRANSITION, draw the mew frame in a sliding-in position
352404
(this->frameFunctions[this->getNextFrameNumber()])(this->display, &this->state, x1, y1);
405+
// tell the consumer of this API that the frame that's coming into focus
406+
// normally this would be to remove the notifications for this frame
407+
if (frameNotificationCallbackFunction != nullptr)
408+
(*frameNotificationCallbackFunction)(this->getNextFrameNumber(), this);
353409

354410
// Build up the indicatorDrawState
355411
if (drawenCurrentFrame && !this->state.isIndicatorDrawen) {
@@ -377,6 +433,10 @@ void OLEDDisplayUi::drawFrame(){
377433
this->state.transitionFrameRelationship = NONE;
378434
//Since we're not transitioning, just draw the current frame at the origin
379435
(this->frameFunctions[this->state.currentFrame])(this->display, &this->state, 0, 0);
436+
// tell the consumer of this API that the frame that's coming into focus
437+
// normally this would be to remove the notifications for this frame
438+
if (frameNotificationCallbackFunction != nullptr)
439+
(*frameNotificationCallbackFunction)(this->state.currentFrame, this);
380440
break;
381441
}
382442
}
@@ -460,17 +520,35 @@ void OLEDDisplayUi::drawIndicator() {
460520
image = this->inactiveSymbol;
461521
}
462522

523+
if (this->state.notifyingFrames.size() > 0) {
524+
for(uint8_t q=0;q<this->state.notifyingFrames.size();q++) {
525+
// if the symbol for the frame we're currently drawing (i)
526+
// is equal to the symbol in the array we're looking at (notff[q])
527+
// then we should adjust `y` by the SIN function (actualOffset)
528+
if (i == (this->state.notifyingFrames[q])) {
529+
#define MILISECONDS_PER_BUBBLE_BOUNDS 5000
530+
uint8_t actualOffset = abs((sin(this->state.ticks*PI/(MILISECONDS_PER_BUBBLE_BOUNDS/updateInterval)) * notifyingFrameOffsetAmplitude));
531+
// is the indicator (symbol / dot) we're currently drawing one that's requesting notification
532+
y = y - actualOffset;
533+
//display->drawString(0,0,String(actualOffset));
534+
//display->drawString(0,30,String(this->state.ticks));
535+
}
536+
}
537+
}
538+
463539
this->display->drawFastImage(x, y, 8, 8, image);
464540
}
465541
}
466542

543+
467544
void OLEDDisplayUi::drawOverlays() {
468545
for (uint8_t i=0;i<this->overlayCount;i++){
469546
(this->overlayFunctions[i])(this->display, &this->state);
470547
}
471548
}
472549

473550
uint8_t OLEDDisplayUi::getNextFrameNumber(){
474-
if (this->nextFrameNumber != -1) return this->nextFrameNumber;
551+
if (this->nextFrameNumber != -1)
552+
return this->nextFrameNumber;
475553
return (this->state.currentFrame + this->frameCount + this->state.frameTransitionDirection) % this->frameCount;
476554
}

src/OLEDDisplayUi.h

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,12 +91,15 @@ const uint8_t ANIMATION_inactiveSymbol[] PROGMEM = {
9191
struct OLEDDisplayUiState {
9292
uint64_t lastUpdate;
9393
uint16_t ticksSinceLastStateSwitch;
94+
uint16_t ticks;
95+
9496

9597
FrameState frameState;
9698
uint8_t currentFrame;
9799
uint8_t transitionFrameTarget;
98100
TransitionRelationship transitionFrameRelationship;
99101

102+
std::vector<uint32_t> notifyingFrames;
100103
bool isIndicatorDrawen;
101104

102105
// Normal = 1, Inverse = -1;
@@ -116,6 +119,7 @@ struct LoadingStage {
116119
typedef void (*FrameCallback)(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y);
117120
typedef void (*OverlayCallback)(OLEDDisplay *display, OLEDDisplayUiState* state);
118121
typedef void (*LoadingDrawFunction)(OLEDDisplay *display, LoadingStage* stage, uint8_t progress);
122+
typedef void (*FrameNotificationCallback)(uint32_t FrameNumber, void* UI);
119123

120124
class OLEDDisplayUi {
121125
private:
@@ -141,7 +145,9 @@ class OLEDDisplayUi {
141145
bool autoTransition;
142146

143147
FrameCallback* frameFunctions;
148+
FrameNotificationCallback* frameNotificationCallbackFunction;
144149
uint8_t frameCount;
150+
uint8_t notifyingFrameOffsetAmplitude;
145151

146152
// Internally used to transition to a specific frame
147153
int8_t nextFrameNumber;
@@ -264,6 +270,30 @@ class OLEDDisplayUi {
264270
*/
265271
void setInactiveSymbol(const uint8_t* symbol);
266272

273+
/**
274+
* Adds a frame to the list of frames with active notifications
275+
*/
276+
bool addFrameToNotifications(uint32_t frameToAdd, bool force=false);
277+
278+
/**
279+
* Removes a frame from the list of frames with active notifications
280+
*/
281+
bool removeFrameFromNotifications(uint32_t frameToRemove);
282+
283+
/**
284+
* Sets a callback function to be called when a frame comes into focus
285+
* Normally this function will remove the frame from the list of
286+
* active notifications
287+
*/
288+
289+
void setFrameNotificationCallback(FrameNotificationCallback* frameNotificationCallbackFunction);
290+
291+
/**
292+
* Returns the number of the frist frame having notifications
293+
* This is most likely to be used when attempting to "jump"
294+
* to the oldest notification
295+
*/
296+
uint32_t getFirstNotifyingFrame();
267297

268298
// Frame settings
269299

0 commit comments

Comments
 (0)