Justin Howard / Mbed 2 deprecated AdaFruit_RGBLCD

Dependencies:   AdaFruit_RGBLCDShield MCP23017 mbed RTclock

Dependents:   SX1276_GPS

Fork of MCP_test by Wim Huiskamp

MenuManager/MenuManager.cpp

Committer:
vtraveller
Date:
2014-10-10
Revision:
28:fbcd3bac0cd7
Parent:
27:b6c3dd9a1d8c

File content as of revision 28:fbcd3bac0cd7:

#include "mbed.h"
#include "module.h"
#include "extra_chars.h"

#include "MenuManager.h"

MenuManager::MenuManager
(
    Module **               in_pModules,
    size_t                  in_nModules,
    LCD &                   in_cLCD,
    Keys &                  in_cKeys
)
    : m_pModules(in_pModules)
    , m_nModules(in_nModules)
    , m_cLCD(in_cLCD)
    , m_cKeys(in_cKeys)
    , m_eMode(Module::eModeLast)
    , m_nMenuPos(0)
    , m_nIndex(0)
    , m_nCursorX(0)
    , m_nCursorY(0)
{
}

void MenuManager::changeModule(bool in_bUp)
{
    size_t nModule = (m_nMenuPos + m_nCursorY) % m_nModules;
    m_pModules[nModule]->change(m_nIndex,in_bUp);
}

void MenuManager::createChars()
{
    //uint8_t k_aUp[] = { 0x4,0xe,0x1f,0x15,0x4,0x4,0x4,0x4 };
    //uint8_t k_aDown[] = { 0x4,0x4,0x4,0x4,0x15,0x1f,0xe,0x4 };
    
    uint8_t k_aUp[] = { 0x0,0x0,0x4,0xe,0x1f,0x0,0x0 };
    uint8_t k_aDown[] = { 0x0,0x0,0x1f,0xe,0x4,0x0,0x0 };
    uint8_t k_aRight[] = { 0x0,0x8,0xc,0xe,0xc,0x8,0x0 };
    uint8_t k_aLeft[] = { 0x0,0x2,0x6,0xe,0x6,0x2,0x0 };
    uint8_t k_aDegree[] = { 0xc,0x12,0x12,0xc,0x0,0x0,0x0,0x0 };

    m_cLCD.createChar(eUp,k_aUp);
    m_cLCD.createChar(eDown,k_aDown);
    m_cLCD.createChar(eRight,k_aRight);
    m_cLCD.createChar(eLeft,k_aLeft);    
    m_cLCD.createChar(eDegree,k_aDegree);    
}

void MenuManager::initialise()
{
    createChars();

    m_cLCD.setCursor(0,0);
    m_cLCD._putc(eUp);

    m_cLCD.setCursor(0,m_cLCD.rows() - 1);
    m_cLCD._putc(eDown);
    
    m_nCursorX = 2;
    m_nCursorY = 0;
}

void MenuManager::loop()
{
    setMode(Module::eModeMenu);
    
    m_nMenuPos = 0;    
    m_nIndex = 0;    

    initialise();
    
    showModules();
       
    while (true)
    {
        uint8_t nKeys = m_cKeys.readButtons();
        if (Keys::eButtonNone != nKeys)
        {
            processKeys(nKeys);
        }
        else
        {
            switch (m_eMode)
            {
                case Module::eModeMenu:
                    showModules(true);
                    
                    int nOffsetX = m_pModules[m_nMenuPos]->getCursorOffset(m_nIndex);
                    m_cLCD.setCursor(m_nCursorY + nOffsetX,m_nCursorY);
                    break;
            }
        }
        
        wait(0.2);
    }
}

void MenuManager::processKeys(uint8_t in_nKeys)
{
    // Change mode based on select
    if (in_nKeys & Keys::eButtonSelect)
    {
        Module::EModes eMode = (Module::EModes)((m_eMode + 1) % Module::eModeLast);        
        setMode(eMode);
        
        // Start at top corner or first good item
        if (Module::eModeSelect == m_eMode)
        {
            m_nIndex = 0;
            m_nCursorY = 0;
            
            // Move to next valid module for editing
            for (size_t i = 0; i < m_cLCD.rows(); i++)
            {
                size_t nPos = (m_nMenuPos + i) % m_nModules;
                
                if (-1 != m_pModules[nPos]->getCursorOffset(i))
                {
                    m_nCursorY = i;
                    break;
                }
            }            
        }
    }

    switch (m_eMode)
    {                
        case Module::eModeMenu:
            setCursor(false,false);
            showTracking(false);
                                
            if (in_nKeys & Keys::eButtonUp) m_nMenuPos--;
            if (in_nKeys & Keys::eButtonDown) m_nMenuPos++;
            
            m_nMenuPos = m_nMenuPos % m_nModules;                    
            break;
            
        case Module::eModeSelect:
            setCursor(true,false);
            showTracking(true);
                                                    
            if (m_nCursorY > 0 && (in_nKeys & Keys::eButtonUp)) m_nCursorY--;
            if ((m_nCursorY < m_cLCD.rows() - 1) && (in_nKeys & Keys::eButtonDown)) m_nCursorY++;
                                
            if (in_nKeys & Keys::eButtonLeft) m_nIndex--;
            if (in_nKeys & Keys::eButtonRight) m_nIndex++;
            break;
            
        case Module::eModeChange:
            setCursor(false,true);
            showTracking(true);
            
            if (in_nKeys & (Keys::eButtonUp | Keys::eButtonDown))
            {                    
                bool bUp = (in_nKeys & Keys::eButtonUp) ? true : false;
                changeModule(bUp);
            }
            
            if (in_nKeys & Keys::eButtonLeft) m_nIndex--;
            if (in_nKeys & Keys::eButtonRight) m_nIndex++;
            break;
    }

    updateDisplay();
}

void MenuManager::setCursor(bool in_bCursor,bool in_bBlink)
{
    m_cLCD.showCursor(in_bCursor);
    m_cLCD.showBlink(in_bBlink);
}

void MenuManager::setMode(Module::EModes in_eMode)
{
    m_eMode = in_eMode;
    
    for (size_t i = 0; i < m_nModules; i++)
    {    
        m_pModules[i]->onModeChange(m_eMode);
    }
}

void MenuManager::showModules(bool in_bRefresh)
{
    for (size_t i = 0; i < m_cLCD.rows(); i++)
    {
        size_t nPos = (m_nMenuPos + i) % m_nModules;
        m_cLCD.setCursor(2,i);
    
        if (m_pModules[nPos]->canRefresh() || !in_bRefresh) m_pModules[nPos]->show(in_bRefresh);
    }
}

void MenuManager::showTracking(bool in_bShow)
{
    int nX = (m_cLCD.rows() >= 4) ? 0:1;
    int nTop = nX ? 0:1;
    int nBottom = m_cLCD.rows() - (nX ? 1:2);
    
    if (in_bShow)
    {
        m_cLCD.setCursor(nX,nTop);
        m_cLCD._putc(eLeft);
        
        m_cLCD.setCursor(nX,nBottom);
        m_cLCD._putc(eRight);
    }
    else
    {
        m_cLCD.setCursor(nX,nTop);
        m_cLCD._putc(' ');
        
        m_cLCD.setCursor(nX,nBottom);
        m_cLCD._putc(' ');                              
    }
}

void MenuManager::updateDisplay()
{
    showModules();
    
    size_t nCurrent = (m_nMenuPos + m_nCursorY) % m_nModules;
    
    int nOffsetX = m_pModules[nCurrent]->getCursorOffset(m_nIndex);
                
    // If we didn't have anything, move the line
    if (-1 == nOffsetX)
    {
        m_nCursorY = (m_nCursorY + 1) % m_cLCD.rows();
        
        nCurrent = (m_nMenuPos  + m_nCursorY) % m_nModules;
        
        m_nIndex = 0;
        nOffsetX = m_pModules[nCurrent]->getCursorOffset(m_nIndex);
    }
        
    if ((size_t)-1 != m_nIndex)
    {
        // Move cursor to new position
        m_cLCD.setCursor(m_nCursorX + nOffsetX,m_nCursorY);
    }
    else
    {
        // If nothing to show - hide everything
        setCursor(false,false);
    }
}