void MD_PZone::effectDissolve(bool bIn) // Dissolve the current message in/out { switch (_fsmState) { case INITIALISE: // bIn = true case PAUSE: // bIn = false case GET_FIRST_CHAR: // first stage dissolve PRINT_STATE("IO DISS"); for (uint16_t i=ZONE_START_COL(_zoneStart); i<=ZONE_END_COL(_zoneEnd); i++) { uint8_t col = DATA_BAR(_MX->getColumn(i)); col |= (i&1 ? 0x55 : 0xaa); // checkerboard pattern _MX->setColumn(i, DATA_BAR(col)); } _fsmState = GET_NEXT_CHAR; break; case GET_NEXT_CHAR: // second stage dissolve PRINT_STATE("IO DISS"); zoneClear(); if (bIn) commonPrint(); for (uint16_t i=ZONE_START_COL(_zoneStart); i<=ZONE_END_COL(_zoneEnd); i++) { uint8_t col = DATA_BAR(_MX->getColumn(i)); col |= (i&1 ? 0xaa : 0x55); // alternate checkerboard pattern _MX->setColumn(i, DATA_BAR(col)); } _fsmState = PUT_CHAR; break; case PUT_CHAR: PRINT_STATE("IO DISS"); zoneClear(); if (bIn) commonPrint(); _fsmState = (bIn ? PAUSE : END); break; default: PRINT_STATE("IO DISS"); _fsmState = (bIn ? PAUSE : END); } }
void MD_PZone::effectPrint(bool bIn) // Just print the message in the justification selected { if (bIn) // incoming { commonPrint(); _fsmState = PAUSE; } else //exiting { zoneClear(); _fsmState = END; } }
void MD_PZone::effectVScroll(bool bUp, bool bIn) // Scroll the display horizontally up of down, depending on the selected effect { if (bIn) // incoming { switch (_fsmState) { case INITIALISE: PRINT_STATE("I VSCROLL"); _nextPos = 0; _MX->control(_zoneStart, _zoneEnd, MD_MAX72XX::WRAPAROUND, MD_MAX72XX::OFF); _fsmState = PUT_CHAR; // fall through to next state case GET_FIRST_CHAR: case GET_NEXT_CHAR: case PUT_CHAR: case PAUSE: PRINT_STATE("I VSCROLL"); zoneClear(); commonPrint(); for (uint8_t i = _nextPos; i < 7; i++) // scroll the whole display so that the message appears to be animated // Note: Directions are reversed because we start with the message in the // middle position thru commonPrint() and to see it animated move DOWN we // need to scroll it UP, and vice versa. _MX->transform(_zoneStart, _zoneEnd, bUp ? MD_MAX72XX::TSD : MD_MAX72XX::TSU); // check if we have finished if (_nextPos == 7) _fsmState = PAUSE; _nextPos++; break; default: PRINT_STATE("I VSCROLL"); _fsmState = PAUSE; } } else // exiting { switch (_fsmState) { case PAUSE: case INITIALISE: PRINT_STATE("O VSCROLL"); _nextPos = 0; _fsmState = PUT_CHAR; // fall through to next state case GET_FIRST_CHAR: case GET_NEXT_CHAR: case PUT_CHAR: PRINT_STATE("O VSCROLL"); _MX->transform(_zoneStart, _zoneEnd, bUp ? MD_MAX72XX::TSU : MD_MAX72XX::TSD); // check if we have finished if (_nextPos == 7) _fsmState = END; _nextPos++; break; default: PRINT_STATE("O VSCROLL"); _fsmState = END; break; } } }
void MD_PZone::effectClose(bool bLightBar, bool bIn) // Dissolve the current message in/out { if (bIn) { switch (_fsmState) { case INITIALISE: case GET_FIRST_CHAR: case GET_NEXT_CHAR: PRINT_STATE("I CLOSE"); _nextPos = 0; zoneClear(); if (bLightBar) { _MX->setColumn(_limitLeft, LIGHT_BAR); _MX->setColumn(_limitRight,LIGHT_BAR); } _fsmState = PUT_CHAR; // fall through case PUT_CHAR: PRINT_STATE("I CLOSE"); FSMPRINT(" - offset ", _nextPos); zoneClear(); commonPrint(); { const int16_t halfWidth = (_limitLeft - _limitRight)/2; if (_nextPos > halfWidth) { _fsmState = PAUSE; } else { for (int16_t i = _limitRight + _nextPos + 1; i < _limitLeft - _nextPos; i++) _MX->setColumn(i, EMPTY_BAR); _nextPos++; if (bLightBar && (_nextPos <= halfWidth)) { _MX->setColumn(_limitLeft - _nextPos, LIGHT_BAR); _MX->setColumn(_limitRight + _nextPos, LIGHT_BAR); } } } break; default: PRINT_STATE("I CLOSE"); _fsmState = PAUSE; } } else // exiting { switch (_fsmState) { case PAUSE: case GET_FIRST_CHAR: case GET_NEXT_CHAR: PRINT_STATE("O CLOSE"); FSMPRINT(" - limits R:", _limitRight); FSMPRINT(" L:", _limitLeft); _nextPos = (_limitLeft-_limitRight)/2; FSMPRINT(" O:", _nextPos); zoneClear(); commonPrint(); if (bLightBar) { _MX->setColumn(_limitLeft - _nextPos, LIGHT_BAR); _MX->setColumn(_limitRight + _nextPos, LIGHT_BAR); } _fsmState = PUT_CHAR; break; case PUT_CHAR: PRINT_STATE("O CLOSE"); FSMPRINT(" - offset ", _nextPos); if (_nextPos < 0) { _fsmState = END; } else { _MX->setColumn(_limitLeft - _nextPos, EMPTY_BAR); _MX->setColumn(_limitRight + _nextPos, EMPTY_BAR); _nextPos--; if (bLightBar && (_nextPos >= 0)) { _MX->setColumn(_limitLeft - _nextPos, LIGHT_BAR); _MX->setColumn(_limitRight + _nextPos, LIGHT_BAR); } } break; default: PRINT_STATE("O CLOSE"); _fsmState = END; } } }
void MD_PZone::effectSlice(bool bIn) { if (bIn) { switch(_fsmState) { case INITIALISE: case GET_FIRST_CHAR: PRINT_STATE("I SLICE"); if ((_charCols = getFirstChar()) == 0) { _fsmState = END; break; } zoneClear(); _countCols = 0; _nextPos = ZONE_START_COL(_zoneStart); _endPos = _limitLeft; _fsmState = PUT_CHAR; break; case GET_NEXT_CHAR: // Load the next character from the font table PRINT_STATE("I SLICE"); // have we reached the end of the characters string? if ((_charCols = getNextChar()) == 0) { _fsmState = PAUSE; break; } _countCols = 0; _fsmState = PUT_CHAR; // !! fall through to next state to start displaying case PUT_CHAR: // display the next part of the character PRINT_STATE("I SLICE"); FSMPRINT(" - Next ", _endPos); FSMPRINT(", anim ", _nextPos); if (_cBuf[_countCols] == 0) { _nextPos = _endPos; // pretend we just animated it! } else { // clear the column and animate the next one if (_nextPos != _endPos) _MX->setColumn(_nextPos, EMPTY_BAR); _nextPos++; _MX->setColumn(_nextPos, DATA_BAR(_cBuf[_countCols])); } // set up for the next time if (_nextPos == _endPos) { _nextPos = ZONE_START_COL(_zoneStart); _countCols++; _endPos--; } if (_countCols == _charCols) _fsmState = GET_NEXT_CHAR; break; default: _fsmState = PAUSE; } } else // exiting { switch(_fsmState) { case PAUSE: PRINT_STATE("O SLICE"); _nextPos = _endPos = _limitLeft; _fsmState = PUT_CHAR; // fall through case GET_FIRST_CHAR: case GET_NEXT_CHAR: case PUT_CHAR: PRINT_STATE("O SLICE"); FSMPRINT(" - Next ", _endPos); FSMPRINT(", anim ", _nextPos); while(_MX->getColumn(_nextPos) == EMPTY_BAR && _endPos >= _limitRight) _nextPos = _endPos--; // pretend we just animated it! if (_endPos <= _limitRight) _fsmState = END; //reached the end else { // Move the column over to the left and blank out previous position if (_nextPos < ZONE_END_COL(_zoneEnd)) _MX->setColumn(_nextPos+1, _MX->getColumn(_nextPos)); _MX->setColumn(_nextPos, EMPTY_BAR); _nextPos++; // set up for the next time if (_nextPos == ZONE_END_COL(_zoneEnd)+1) _nextPos = _endPos--; } break; default: _fsmState = END; } } }
bool MD_PZone::zoneAnimate(void) { if (_fsmState == END) return(true); // work through things that stop us running this at all if (((_fsmState == PAUSE) && (millis() - _lastRunTime < _pauseTime)) || (millis() - _lastRunTime < _tickTime) || (_suspend)) return(false); // save the time now, before we run the animation, so that the animation is part of the // delay between animations giving more accurate frame timing. _lastRunTime = millis(); // any text to display? if (_pText != NULL) { switch (_fsmState) { case END: // do nothing in this state PRINT_STATE("ANIMATE"); break; case INITIALISE: PRINT_STATE("ANIMATE"); setInitialConditions(); zoneClear(); _moveIn = true; // fall through to process the effect, first call will be with INITIALISE default: // All state except END are handled by the special effect functions switch (_moveIn ? _effectIn : _effectOut) { case PRINT: effectPrint(_moveIn); break; case SLICE: effectSlice(_moveIn); break; case WIPE: effectWipe(false, _moveIn); break; case WIPE_CURSOR: effectWipe(true, _moveIn); break; case OPENING: effectOpen(false, _moveIn); break; case OPENING_CURSOR: effectOpen(true, _moveIn); break; case CLOSING: effectClose(false, _moveIn); break; case CLOSING_CURSOR: effectClose(true, _moveIn); break; case BLINDS: effectBlinds(_moveIn); break; case DISSOLVE: effectDissolve(_moveIn); break; case SCAN_HORIZ: effectHScan(_moveIn); break; case SCAN_VERT: effectVScan(_moveIn); break; case GROW_UP: effectGrow(true, _moveIn); break; case GROW_DOWN: effectGrow(false, _moveIn); break; case SCROLL_UP: effectVScroll(true, _moveIn); break; case SCROLL_DOWN: effectVScroll(false, _moveIn); break; case SCROLL_LEFT: effectHScroll(true, _moveIn); break; case SCROLL_RIGHT: effectHScroll(false, _moveIn); break; case SCROLL_UP_LEFT: effectDiag(true, true, _moveIn); break; case SCROLL_UP_RIGHT: effectDiag(true, false, _moveIn); break; case SCROLL_DOWN_LEFT: effectDiag(false, true, _moveIn); break; case SCROLL_DOWN_RIGHT: effectDiag(false, false, _moveIn); break; default: _fsmState = END; } // one way toggle for input to output, reset on initialize _moveIn = _moveIn && !(_fsmState == PAUSE); break; } } TIME_PROFILE("\nAnimation time "); TIME_PROFILE(": Cycle time "); return(_fsmState == END); }