Program Listing for File hardware_test_menu.cpp

Return to documentation for file (src/tap/display/hardware_test_menu.cpp)

/*
 * Copyright (c) 2020-2021 Advanced Robotics at the University of Washington <robomstr@uw.edu>
 *
 * This file is part of Taproot.
 *
 * Taproot is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Taproot is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Taproot.  If not, see <https://www.gnu.org/licenses/>.
 */

#include "hardware_test_menu.hpp"

#include <algorithm>

#include "tap/control/command.hpp"
#include "tap/control/command_scheduler.hpp"
#include "tap/control/subsystem.hpp"
#include "tap/drivers.hpp"

namespace tap
{
namespace display
{
HardwareTestMenu::HardwareTestMenu(
    modm::ViewStack<DummyAllocator<modm::IAbstractView> >* vs,
    Drivers* drivers)
    : AbstractMenu<DummyAllocator<modm::IAbstractView> >(vs, HARDWARE_TEST_MENU_ID),
      drivers(drivers),
      vertScrollHandler(drivers, 0, MAX_ENTRIES_DISPLAYED)
{
}

void HardwareTestMenu::update() {}

void HardwareTestMenu::shortButtonPress(modm::MenuButtons::Button button)
{
    if (button == modm::MenuButtons::LEFT)
    {
        drivers->commandScheduler.stopAllHardwareTests();
        this->remove();
    }
    else if (button == modm::MenuButtons::OK)
    {
        if (vertScrollHandler.getCursorIndex() == 0)
        {
            if (drivers->commandScheduler.countRunningHardwareTests() != 0)
            {
                drivers->commandScheduler.stopAllHardwareTests();
            }
            else
            {
                drivers->commandScheduler.runAllHardwareTests();
            }
            return;
        }

        int subsystemIndex = 1;
        for (auto it = drivers->commandScheduler.subMapBegin();
             it != drivers->commandScheduler.subMapEnd();
             it++)
        {
            if ((*it)->getTestCommand() != nullptr)
            {
                if (subsystemIndex++ == vertScrollHandler.getCursorIndex())
                {
                    if (drivers->commandScheduler.isRunningTest(*it))
                    {
                        drivers->commandScheduler.stopHardwareTest(*it);
                    }
                    else
                    {
                        drivers->commandScheduler.runHardwareTest(*it);
                    }
                    return;
                }
            }
        }
    }
    else
    {
        vertScrollHandler.onShortButtonPress(button);
    }
}

bool HardwareTestMenu::hasChanged()
{
    int runningTests = drivers->commandScheduler.countRunningHardwareTests();

    bool changed =
        vertScrollHandler.acknowledgeCursorChanged() || (runningTests != this->runningTests);
    this->runningTests = runningTests;
    return changed;
}

void HardwareTestMenu::draw()
{
    // Only do this once because it is assumed that all subsystems will be registered once
    // at the beginning of the program and subsystemListSize is not free
    if (vertScrollHandler.getSize() == 0)
    {
        int testableSubsystems = 0;
        for (auto it = drivers->commandScheduler.subMapBegin();
             it != drivers->commandScheduler.subMapEnd();
             it++)
        {
            if ((*it)->getTestCommand() != nullptr)
            {
                testableSubsystems++;
            }
        }
        vertScrollHandler.setSize(testableSubsystems + 1);
    }

    modm::GraphicDisplay& display = getViewStack()->getDisplay();
    display.clear();
    display.setCursor(0, 2);
    display << HardwareTestMenu::getMenuName() << modm::endl;

    if (drivers->commandScheduler.countRunningHardwareTests() != 0)
    {
        display << "Running " << drivers->commandScheduler.countRunningHardwareTests() << " tests."
                << modm::endl;
        display << ((vertScrollHandler.getCursorIndex() == 0) ? ">" : " ");
        display << "[stop all] " << modm::endl;
    }
    else
    {
        display << "No tests running." << modm::endl;
        display << ((vertScrollHandler.getCursorIndex() == 0) ? ">" : " ");
        display << "[run all]" << modm::endl;
    }

    int subsystemIndex = 1;
    std::for_each(
        drivers->commandScheduler.subMapBegin(),
        drivers->commandScheduler.subMapEnd(),
        [&](control::Subsystem* sub)
        {
            if (sub->getTestCommand() != nullptr)
            {
                if (subsystemIndex <= (vertScrollHandler.getLargestIndexDisplayed()) &&
                    subsystemIndex >= (vertScrollHandler.getSmallestIndexDisplayed()))
                {
                    display << ((subsystemIndex == vertScrollHandler.getCursorIndex()) ? ">" : " ")
                            << ((drivers->commandScheduler.hasPassedTest(sub)) ? " + " : " x ")
                            << (drivers->commandScheduler.isRunningTest(sub) ? "[stop] "
                                                                             : "[run]  ")
                            << sub->getName() << modm::endl;
                }
                subsystemIndex++;
            }
        });
}
}  // namespace display
}  // namespace tap