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::commonPrint(void)
{
	int16_t	nextPos;

	FSMPRINTS("\ncommonPrint");
	nextPos = _limitLeft;
	_charCols = getFirstChar();
	_countCols = 0;

	while (nextPos >= _limitRight)
	{
		if (_countCols == _charCols)
		{
			_charCols = getNextChar();
			_countCols = 0;
		}

		// now put something on the display
		_MX->setColumn(nextPos--, DATA_BAR(_cBuf[_countCols++]));
	}
}
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;
        }
    }
}