<commit_before>/* BEGIN_COMMON_COPYRIGHT_HEADER
 * (c)LGPL2+
 *
 * LXQt - a lightweight, Qt based, desktop toolset
 * https://lxqt.org
 *
 * Copyright: 2015 LXQt team
 * Authors:
 *   Dmitriy Zhukov <zjesclean@gmail.com>
 *
 * This program or library is free software; you can redistribute it
 * and/or modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library 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
 * Lesser General Public License for more details.
 * You should have received a copy of the GNU Lesser General
 * Public License along with this library; if not, write to the
 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301 USA
 *
 * END_COMMON_COPYRIGHT_HEADER */

#include <QDebug>
#include <QProcess>
#include "kbdstateconfig.h"
#include "ui_kbdstateconfig.h"
#include "settings.h"

KbdStateConfig::KbdStateConfig(QWidget *parent) :
    QDialog(parent),
    m_ui(new Ui::KbdStateConfig)
{
    setAttribute(Qt::WA_DeleteOnClose);
    m_ui->setupUi(this);

    connect(m_ui->showCaps,   &QCheckBox::clicked, this, &KbdStateConfig::save);
    connect(m_ui->showNum,    &QCheckBox::clicked, this, &KbdStateConfig::save);
    connect(m_ui->showScroll, &QCheckBox::clicked, this, &KbdStateConfig::save);
    connect(m_ui->showLayout, &QGroupBox::clicked, this, &KbdStateConfig::save);

    connect(m_ui->modes, static_cast<void (QButtonGroup::*)(int)>(&QButtonGroup::buttonClicked),
        [this](int){
            KbdStateConfig::save();
        }
    );

    connect(m_ui->btns, &QDialogButtonBox::clicked, [this](QAbstractButton *btn){
        if (m_ui->btns->buttonRole(btn) == QDialogButtonBox::ResetRole){
            Settings::instance().restore();
            load();
        }
    });

    connect(m_ui->configureLayouts, &QPushButton::clicked, this, &KbdStateConfig::configureLayouts);

    load();
}

KbdStateConfig::~KbdStateConfig()
{
    delete m_ui;
}

void KbdStateConfig::load()
{
    Settings & sets = Settings::instance();

    m_ui->showCaps->setChecked(sets.showCapLock());
    m_ui->showNum->setChecked(sets.showNumLock());
    m_ui->showScroll->setChecked(sets.showScrollLock());
    m_ui->showLayout->setChecked(sets.showLayout());

    switch(sets.keeperType()){
    case KeeperType::Global:
        m_ui->switchGlobal->setChecked(true);
        break;
    case KeeperType::Window:
        m_ui->switchWindow->setChecked(true);
        break;
    case KeeperType::Application:
        m_ui->switchApplication->setChecked(true);
        break;
    }
}

void KbdStateConfig::save()
{
    Settings & sets = Settings::instance();

    sets.setShowCapLock(m_ui->showCaps->isChecked());
    sets.setShowNumLock(m_ui->showNum->isChecked());
    sets.setShowScrollLock(m_ui->showScroll->isChecked());
    sets.setShowLayout(m_ui->showLayout->isChecked());

    if (m_ui->switchGlobal->isChecked())
        sets.setKeeperType(KeeperType::Global);
    if (m_ui->switchWindow->isChecked())
        sets.setKeeperType(KeeperType::Window);
    if (m_ui->switchApplication->isChecked())
        sets.setKeeperType(KeeperType::Application);
}

void KbdStateConfig::configureLayouts()
{
    QProcess::startDetached(QLatin1String("lxqt-config-input"));
}
<commit_msg>plugin-kbindicator: Go directly to the Keyboard Layout config page<commit_after>/* BEGIN_COMMON_COPYRIGHT_HEADER
 * (c)LGPL2+
 *
 * LXQt - a lightweight, Qt based, desktop toolset
 * https://lxqt.org
 *
 * Copyright: 2015 LXQt team
 * Authors:
 *   Dmitriy Zhukov <zjesclean@gmail.com>
 *
 * This program or library is free software; you can redistribute it
 * and/or modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library 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
 * Lesser General Public License for more details.
 * You should have received a copy of the GNU Lesser General
 * Public License along with this library; if not, write to the
 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301 USA
 *
 * END_COMMON_COPYRIGHT_HEADER */

#include <LXQt/Globals>

#include <QDebug>
#include <QProcess>

#include "kbdstateconfig.h"
#include "ui_kbdstateconfig.h"
#include "settings.h"

KbdStateConfig::KbdStateConfig(QWidget *parent) :
    QDialog(parent),
    m_ui(new Ui::KbdStateConfig)
{
    setAttribute(Qt::WA_DeleteOnClose);
    m_ui->setupUi(this);

    connect(m_ui->showCaps,   &QCheckBox::clicked, this, &KbdStateConfig::save);
    connect(m_ui->showNum,    &QCheckBox::clicked, this, &KbdStateConfig::save);
    connect(m_ui->showScroll, &QCheckBox::clicked, this, &KbdStateConfig::save);
    connect(m_ui->showLayout, &QGroupBox::clicked, this, &KbdStateConfig::save);

    connect(m_ui->modes, static_cast<void (QButtonGroup::*)(int)>(&QButtonGroup::buttonClicked),
        [this](int){
            KbdStateConfig::save();
        }
    );

    connect(m_ui->btns, &QDialogButtonBox::clicked, [this](QAbstractButton *btn){
        if (m_ui->btns->buttonRole(btn) == QDialogButtonBox::ResetRole){
            Settings::instance().restore();
            load();
        }
    });

    connect(m_ui->configureLayouts, &QPushButton::clicked, this, &KbdStateConfig::configureLayouts);

    load();
}

KbdStateConfig::~KbdStateConfig()
{
    delete m_ui;
}

void KbdStateConfig::load()
{
    Settings & sets = Settings::instance();

    m_ui->showCaps->setChecked(sets.showCapLock());
    m_ui->showNum->setChecked(sets.showNumLock());
    m_ui->showScroll->setChecked(sets.showScrollLock());
    m_ui->showLayout->setChecked(sets.showLayout());

    switch(sets.keeperType()){
    case KeeperType::Global:
        m_ui->switchGlobal->setChecked(true);
        break;
    case KeeperType::Window:
        m_ui->switchWindow->setChecked(true);
        break;
    case KeeperType::Application:
        m_ui->switchApplication->setChecked(true);
        break;
    }
}

void KbdStateConfig::save()
{
    Settings & sets = Settings::instance();

    sets.setShowCapLock(m_ui->showCaps->isChecked());
    sets.setShowNumLock(m_ui->showNum->isChecked());
    sets.setShowScrollLock(m_ui->showScroll->isChecked());
    sets.setShowLayout(m_ui->showLayout->isChecked());

    if (m_ui->switchGlobal->isChecked())
        sets.setKeeperType(KeeperType::Global);
    if (m_ui->switchWindow->isChecked())
        sets.setKeeperType(KeeperType::Window);
    if (m_ui->switchApplication->isChecked())
        sets.setKeeperType(KeeperType::Application);
}

void KbdStateConfig::configureLayouts()
{
    QProcess::startDetached(QL1S("lxqt-config-input --show-page \"Keyboard Layout\""));
}
<|endoftext|>


<commit_before>#include <SFML/Audio.hpp>
#include <SFML/Graphics.hpp>
#include "game.h"
#include "particlesystem.h"
#include "util.h"
#include <sstream>
#include <fstream>

using namespace std;

const char* savefile = "save";

int loadHighscore() {
    int ret = 0;

    ifstream f(savefile);
    if (f.good()) {
        f >> ret;
    }
    f.close();

    return ret;
}

void saveHighscore(int high) {
    ofstream f(savefile);
    f << high << endl;
    f.close();
}

int main()
{
    // Create the main window
    sf::RenderWindow window(sf::VideoMode(800, 600), "Icebearino");
    Game game;
    game.init(&window);

    // Create a graphical text to display
    sf::Font font;
    if (!font.loadFromFile("res/fonts/Cinzel-Bold.ttf"))
        return EXIT_FAILURE;

    // Death sound
    sf::SoundBuffer deathSoundBuffer;
    loadSoundBuffer(deathSoundBuffer, "res/sound/death.ogg");
    sf::Sound deathSound;
    deathSound.setBuffer(deathSoundBuffer);

    // Icebearino sound
    sf::SoundBuffer icebearinoBuffer;
    loadSoundBuffer(icebearinoBuffer, "res/sound/icebearino.ogg");
    sf::Sound icebearinoSound;
    icebearinoSound.setBuffer(icebearinoBuffer);

    // Fact sounds
    sf::SoundBuffer factBuffers[6];
    loadSoundBuffer(factBuffers[0], "res/sound/facts-01.ogg");
    loadSoundBuffer(factBuffers[1], "res/sound/facts-02.ogg");
    loadSoundBuffer(factBuffers[2], "res/sound/facts-03.ogg");
    loadSoundBuffer(factBuffers[3], "res/sound/facts-04.ogg");
    loadSoundBuffer(factBuffers[4], "res/sound/facts-05.ogg");
    loadSoundBuffer(factBuffers[5], "res/sound/facts-06.ogg");
    sf::Sound factSound;

    float elapsedTime = 0.0f;

    // Zimmer sound
    sf::SoundBuffer zimmerBuffer;
    loadSoundBuffer(zimmerBuffer, "res/sound/zimmer.ogg");
    sf::Sound zimmerSound;
    zimmerSound.setBuffer(zimmerBuffer);

    // Snow effect
    ParticleSystem snow(1000, ParticleMode::Snow, "res/img/snowflake.png");

    bool gamerunning = false;
    int highscore = loadHighscore();

    sf::Clock gameTimer;

    sf::Text intro1("CLIMATE CHANGE IS REAL", font, 50.0f);
    sf::Text intro2a("THE ARCTIC WORLD", font, 50.0f);
    sf::Text intro2b("IS SHRINKING", font, 50.0f);
    sf::Text intro3a("YOU ARE THE LAST", font, 50.0f);
    sf::Text intro3b("OF YOUR KIND", font, 50.0f);
    sf::Text intro4("WILL YOU SURVIVE?", font, 50.0f);

    centerText(intro1);
    centerText(intro2a);
    centerText(intro2b);
    centerText(intro3a);
    centerText(intro3b);
    centerText(intro4);

    intro1.setPosition(400, 200);
    intro2a.setPosition(400, 200);
    intro2b.setPosition(400, 250);
    intro3a.setPosition(400, 200);
    intro3b.setPosition(400, 250);
    intro4.setPosition(400, 200);

    const float perText = 4.0f;
    const int numTexts = 4;

	sf::Music music;
	music.openFromFile("res/sound/music.ogg");
	music.setLoop(true);
	music.setVolume(50);
	bool musicPlaying = false;

    bool gameStarted = false;

    // Start the game loop
    sf::Clock deltaClock;
    float dt = 0.0f;
    while (window.isOpen())
    {
        // Process events
        sf::Event event;
        while (window.pollEvent(event))
        {
            // Close window: exit
            if (event.type == sf::Event::Closed)
                window.close();
        }

        if (sf::Keyboard::isKeyPressed(sf::Keyboard::Key::Escape))
            window.close();

        // Update game
        if (gamerunning) {
            game.update(dt);
            if (game.over) {
                highscore = max(game.score, highscore);
                saveHighscore(highscore);
                gamerunning = false;
                deathSound.play();
                game.cleanup();
            }
        } else {
            snow.update(dt);

            if (sf::Keyboard::isKeyPressed(sf::Keyboard::Key::Return)) {
                gameStarted = true;
                game.init(&window);
                gamerunning = true;
				deathSound.stop();
                zimmerSound.stop();
                icebearinoSound.stop();
            }
        }

        float fade = 0.0f;

        // Clear screen
        window.clear();

        // Render game
        if (gamerunning) {
			if (!musicPlaying){
				musicPlaying = true;
				music.play();
			}
            game.render();
        } else if (!gamerunning) {
			if (musicPlaying)
				music.stop(), musicPlaying = false;
            sf::Text title("ICEBEARINO", font, 100.0f);
            sf::Text pressEnter("Press enter to start the game", font, 20.0f);
            sf::Text credits("Made by Karl Lundstig and Fredrik Hernqvist for Ludum Dare 38", font, 16.0f);

        	stringstream ss;
        	ss << "Highscore: " << highscore;
            sf::Text hs(ss.str(), font, 20.0f);

            centerText(title);
            title.setPosition(sf::Vector2f(400, 250));

            centerText(pressEnter);
            pressEnter.setPosition(sf::Vector2f(400, 320));

            centerText(hs);
            hs.setPosition(sf::Vector2f(400, 400));

            centerText(credits);
            credits.setPosition(sf::Vector2f(400, 580));

            auto curTime = gameTimer.getElapsedTime();
            if (gameStarted || curTime > sf::seconds(numTexts * perText)) {
                float t = (curTime - sf::seconds(perText * numTexts)).asSeconds();
                fade = gameStarted ? 1.0f : 1.0f - max(0.0f, min(1.0f, 2.0f - t));
                if (t > 1.0f && t < 2.0f && icebearinoSound.getStatus() != sf::SoundSource::Status::Playing)
                    icebearinoSound.play();

                window.draw(title);
                window.draw(pressEnter);
                window.draw(hs);
                window.draw(credits);
            }

            if (!gameStarted) {
                if (curTime > sf::seconds(0.0f * perText) && curTime < sf::seconds(1.0f * perText)) {
                    float t = (curTime - sf::seconds(perText * 0.0f)).asSeconds();
                    fade = 1.0f - max(0.0f, min(1.0f, abs(2.0f - t)));
                    window.draw(intro1);
                    if (t > 1.0f && t < 2.0f && zimmerSound.getStatus() != sf::SoundSource::Status::Playing)
                        zimmerSound.play();
                }
                if (curTime > sf::seconds(1.0f * perText) && curTime < sf::seconds(2.0f * perText)) {
                    float t = (curTime - sf::seconds(perText * 1.0f)).asSeconds();
                    fade = 1.0f - max(0.0f, min(1.0f, abs(2.0f - t)));
                    window.draw(intro2a);
                    window.draw(intro2b);
                    if (t > 1.0f && t < 2.0f && zimmerSound.getStatus() != sf::SoundSource::Status::Playing)
                        zimmerSound.play();
                }
                if (curTime > sf::seconds(2.0f * perText) && curTime < sf::seconds(3.0f * perText)) {
                    float t = (curTime - sf::seconds(perText * 2.0f)).asSeconds();
                    fade = 1.0f - max(0.0f, min(1.0f, abs(2.0f - t)));
                    window.draw(intro3a);
                    window.draw(intro3b);
                    if (t > 1.0f && t < 2.0f && zimmerSound.getStatus() != sf::SoundSource::Status::Playing)
                        zimmerSound.play();
                }
                if (curTime > sf::seconds(3.0f * perText) && curTime < sf::seconds(4.0f * perText)) {
                    float t = (curTime - sf::seconds(perText * 3.0f)).asSeconds();
                    fade = 1.0f - max(0.0f, min(1.0f, abs(2.0f - t)));
                    window.draw(intro4);
                    if (t > 1.0f && t < 2.0f && zimmerSound.getStatus() != sf::SoundSource::Status::Playing)
                        zimmerSound.play();
                }
            }

            sf::RectangleShape fadeRect(sf::Vector2f(800.0f, 600.0f));
            fadeRect.setPosition(0.0f, 0.0f);
            fadeRect.setFillColor(sf::Color(0, 0, 0, 255*(1.0f-fade)));
            window.draw(fadeRect);

            window.draw(snow);
        }

        elapsedTime += dt;
        if (elapsedTime > 15.0f && gameStarted) {
            elapsedTime = 0.0f;
            if (rnd() < 0.1f) {
                factSound.setBuffer(factBuffers[rand() % 6]);
                factSound.play();
            }
        }

        // Update the window
        window.display();

        dt = deltaClock.restart().asSeconds();
    }
    return EXIT_SUCCESS;
}
<commit_msg>Center intro text<commit_after>#include <SFML/Audio.hpp>
#include <SFML/Graphics.hpp>
#include "game.h"
#include "particlesystem.h"
#include "util.h"
#include <sstream>
#include <fstream>

using namespace std;

const char* savefile = "save";

int loadHighscore() {
    int ret = 0;

    ifstream f(savefile);
    if (f.good()) {
        f >> ret;
    }
    f.close();

    return ret;
}

void saveHighscore(int high) {
    ofstream f(savefile);
    f << high << endl;
    f.close();
}

int main()
{
    // Create the main window
    sf::RenderWindow window(sf::VideoMode(800, 600), "Icebearino");
    Game game;
    game.init(&window);

    // Create a graphical text to display
    sf::Font font;
    if (!font.loadFromFile("res/fonts/Cinzel-Bold.ttf"))
        return EXIT_FAILURE;

    // Death sound
    sf::SoundBuffer deathSoundBuffer;
    loadSoundBuffer(deathSoundBuffer, "res/sound/death.ogg");
    sf::Sound deathSound;
    deathSound.setBuffer(deathSoundBuffer);

    // Icebearino sound
    sf::SoundBuffer icebearinoBuffer;
    loadSoundBuffer(icebearinoBuffer, "res/sound/icebearino.ogg");
    sf::Sound icebearinoSound;
    icebearinoSound.setBuffer(icebearinoBuffer);

    // Fact sounds
    sf::SoundBuffer factBuffers[6];
    loadSoundBuffer(factBuffers[0], "res/sound/facts-01.ogg");
    loadSoundBuffer(factBuffers[1], "res/sound/facts-02.ogg");
    loadSoundBuffer(factBuffers[2], "res/sound/facts-03.ogg");
    loadSoundBuffer(factBuffers[3], "res/sound/facts-04.ogg");
    loadSoundBuffer(factBuffers[4], "res/sound/facts-05.ogg");
    loadSoundBuffer(factBuffers[5], "res/sound/facts-06.ogg");
    sf::Sound factSound;

    float elapsedTime = 0.0f;

    // Zimmer sound
    sf::SoundBuffer zimmerBuffer;
    loadSoundBuffer(zimmerBuffer, "res/sound/zimmer.ogg");
    sf::Sound zimmerSound;
    zimmerSound.setBuffer(zimmerBuffer);

    // Snow effect
    ParticleSystem snow(1000, ParticleMode::Snow, "res/img/snowflake.png");

    bool gamerunning = false;
    int highscore = loadHighscore();

    sf::Clock gameTimer;

    sf::Text intro1("CLIMATE CHANGE IS REAL", font, 50.0f);
    sf::Text intro2a("THE ARCTIC WORLD", font, 50.0f);
    sf::Text intro2b("IS SHRINKING", font, 50.0f);
    sf::Text intro3a("YOU ARE THE LAST", font, 50.0f);
    sf::Text intro3b("OF YOUR KIND", font, 50.0f);
    sf::Text intro4("WILL YOU SURVIVE?", font, 50.0f);

    centerText(intro1);
    centerText(intro2a);
    centerText(intro2b);
    centerText(intro3a);
    centerText(intro3b);
    centerText(intro4);

    intro1.setPosition(400, 300);
    intro2a.setPosition(400, 250);
    intro2b.setPosition(400, 300);
    intro3a.setPosition(400, 250);
    intro3b.setPosition(400, 300);
    intro4.setPosition(400, 300);

    const float perText = 4.0f;
    const int numTexts = 4;

	sf::Music music;
	music.openFromFile("res/sound/music.ogg");
	music.setLoop(true);
	music.setVolume(50);
	bool musicPlaying = false;

    bool gameStarted = false;

    // Start the game loop
    sf::Clock deltaClock;
    float dt = 0.0f;
    while (window.isOpen())
    {
        // Process events
        sf::Event event;
        while (window.pollEvent(event))
        {
            // Close window: exit
            if (event.type == sf::Event::Closed)
                window.close();
        }

        if (sf::Keyboard::isKeyPressed(sf::Keyboard::Key::Escape))
            window.close();

        // Update game
        if (gamerunning) {
            game.update(dt);
            if (game.over) {
                highscore = max(game.score, highscore);
                saveHighscore(highscore);
                gamerunning = false;
                deathSound.play();
                game.cleanup();
            }
        } else {
            snow.update(dt);

            if (sf::Keyboard::isKeyPressed(sf::Keyboard::Key::Return)) {
                gameStarted = true;
                game.init(&window);
                gamerunning = true;
				deathSound.stop();
                zimmerSound.stop();
                icebearinoSound.stop();
            }
        }

        float fade = 0.0f;

        // Clear screen
        window.clear();

        // Render game
        if (gamerunning) {
			if (!musicPlaying){
				musicPlaying = true;
				music.play();
			}
            game.render();
        } else if (!gamerunning) {
			if (musicPlaying)
				music.stop(), musicPlaying = false;
            sf::Text title("ICEBEARINO", font, 100.0f);
            sf::Text pressEnter("Press enter to start the game", font, 20.0f);
            sf::Text credits("Made by Karl Lundstig and Fredrik Hernqvist for Ludum Dare 38", font, 16.0f);

        	stringstream ss;
        	ss << "Highscore: " << highscore;
            sf::Text hs(ss.str(), font, 20.0f);

            centerText(title);
            title.setPosition(sf::Vector2f(400, 250));

            centerText(pressEnter);
            pressEnter.setPosition(sf::Vector2f(400, 320));

            centerText(hs);
            hs.setPosition(sf::Vector2f(400, 400));

            centerText(credits);
            credits.setPosition(sf::Vector2f(400, 580));

            auto curTime = gameTimer.getElapsedTime();
            if (gameStarted || curTime > sf::seconds(numTexts * perText)) {
                float t = (curTime - sf::seconds(perText * numTexts)).asSeconds();
                fade = gameStarted ? 1.0f : 1.0f - max(0.0f, min(1.0f, 2.0f - t));
                if (t > 1.0f && t < 2.0f && icebearinoSound.getStatus() != sf::SoundSource::Status::Playing)
                    icebearinoSound.play();

                window.draw(title);
                window.draw(pressEnter);
                window.draw(hs);
                window.draw(credits);
            }

            if (!gameStarted) {
                if (curTime > sf::seconds(0.0f * perText) && curTime < sf::seconds(1.0f * perText)) {
                    float t = (curTime - sf::seconds(perText * 0.0f)).asSeconds();
                    fade = 1.0f - max(0.0f, min(1.0f, abs(2.0f - t)));
                    window.draw(intro1);
                    if (t > 1.0f && t < 2.0f && zimmerSound.getStatus() != sf::SoundSource::Status::Playing)
                        zimmerSound.play();
                }
                if (curTime > sf::seconds(1.0f * perText) && curTime < sf::seconds(2.0f * perText)) {
                    float t = (curTime - sf::seconds(perText * 1.0f)).asSeconds();
                    fade = 1.0f - max(0.0f, min(1.0f, abs(2.0f - t)));
                    window.draw(intro2a);
                    window.draw(intro2b);
                    if (t > 1.0f && t < 2.0f && zimmerSound.getStatus() != sf::SoundSource::Status::Playing)
                        zimmerSound.play();
                }
                if (curTime > sf::seconds(2.0f * perText) && curTime < sf::seconds(3.0f * perText)) {
                    float t = (curTime - sf::seconds(perText * 2.0f)).asSeconds();
                    fade = 1.0f - max(0.0f, min(1.0f, abs(2.0f - t)));
                    window.draw(intro3a);
                    window.draw(intro3b);
                    if (t > 1.0f && t < 2.0f && zimmerSound.getStatus() != sf::SoundSource::Status::Playing)
                        zimmerSound.play();
                }
                if (curTime > sf::seconds(3.0f * perText) && curTime < sf::seconds(4.0f * perText)) {
                    float t = (curTime - sf::seconds(perText * 3.0f)).asSeconds();
                    fade = 1.0f - max(0.0f, min(1.0f, abs(2.0f - t)));
                    window.draw(intro4);
                    if (t > 1.0f && t < 2.0f && zimmerSound.getStatus() != sf::SoundSource::Status::Playing)
                        zimmerSound.play();
                }
            }

            sf::RectangleShape fadeRect(sf::Vector2f(800.0f, 600.0f));
            fadeRect.setPosition(0.0f, 0.0f);
            fadeRect.setFillColor(sf::Color(0, 0, 0, 255*(1.0f-fade)));
            window.draw(fadeRect);

            window.draw(snow);
        }

        elapsedTime += dt;
        if (elapsedTime > 15.0f && gameStarted) {
            elapsedTime = 0.0f;
            if (rnd() < 0.1f) {
                factSound.setBuffer(factBuffers[rand() % 6]);
                factSound.play();
            }
        }

        // Update the window
        window.display();

        dt = deltaClock.restart().asSeconds();
    }
    return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>#include <iostream>
#include <vector>
#include <cstring>
using namespace std;

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <boost/tokenizer.hpp>

#include "Base.h"
#include "Cmd.h"
#include "Or.h"
#include "And.h"
#include "Semi.h"
using namespace std;
using namespace boost;

void Tokenize (const string& str, vector<string>& vec) { //splits string into tokens
    typedef tokenizer<char_separator<char> > tokenizer;
    char_separator<char> sep(";&|#()", ";&|#()", boost::keep_empty_tokens);
    tokenizer tok(str, sep);

    for(tokenizer::iterator tok_iter = tok.begin(); tok_iter != tok.end(); ++tok_iter) {
        vec.push_back(*tok_iter);
        if(*tok_iter == "&" || *tok_iter == "|") {tok_iter++; tok_iter++;}
    }
    for(unsigned int a = 0; a < vec.size(); ++a) { //check for a delete empty spaces
        if(vec.at(a) == " " || vec.at(a) == "") {vec.erase(vec.begin() + a);}
    }

}
void _Tokenize (const string& str, vector<string>& vec) { //splits string into tokens
    typedef tokenizer<char_separator<char> > tokenizer;
    char_separator<char> sep(" ");
    tokenizer tok(str, sep);

    for(tokenizer::iterator tok_iter = tok.begin(); tok_iter != tok.end(); ++tok_iter) {
        vec.push_back(*tok_iter);
        //if(*tok_iter == "&" || *tok_iter == "|") {tok_iter++;}
    }

}

void commentCheck(vector<string>& tok) { //if a # is detected, remove all following tokens
    if(tok.size() >= 2) {
        if (tok.at(1) == "#") {tok.clear();}
    }
    //else {
        for(unsigned int i = 0; i < tok.size(); ++i) {
            if(tok.at(i) == "#") {
                tok.erase(tok.begin() + i, tok.end());
            }
        }
    //}

}

bool Execute(vector<string> input) {
    vector<string> arguments;
    string executable;
    Cmd* command;
    Connector* connect;
    bool done = false;
    bool skip = false;
    int i = 0;

    while(input.size() != 0) {

        if(input.size() == 1) { //base case: no connectors
            arguments.clear();
            _Tokenize(input.at(i), arguments);
            //commentCheck(arguments);
            //if(arguments.size() == 0) {return true;}
            executable = arguments.front();
            arguments.erase(arguments.begin());
            //cout << executable << ", " << arguments.at(0) << endl;
            command = new Cmd(executable, arguments);
            return command->execute(done);

        }
        arguments.clear();
        _Tokenize(input.at(i), arguments);
        executable = arguments.front();
        arguments.erase(arguments.begin());
        command = new Cmd(executable, arguments);

        input.erase(input.begin());

        if(input.at(i) == ";") {
            connect = new Semi(command);
        }
        else if(input.at(i) == "&") {
            connect = new And(command);
        }
        else if(input.at(i) == "|") {
            connect = new Or(command);
        }
        input.erase(input.begin());

        done = command->execute(done);
        skip = connect->execute(done);

        if(skip == true) { //check if the first OR condition executed
            input.erase(input.begin());
            while(input.size() != 0) {
                if(input.at(0) == "|") {
                    input.erase(input.begin());
                    input.erase(input.begin());
                }
                if(input.size() == 0) {break;}
                if(input.at(0) == "&") {
                    input.erase(input.begin());
                    break;
                }
            }
        }
    }
    return 0;
}

bool ParenthExecute(vector<string>& input, bool in) {
    vector<string> arguments;
    string executable;
    Cmd* command;
    Connector* connect;
    bool done = false;
    bool skip = false;
    bool recursion = false;
    bool rightClosed = false;
    int i = 0;

    while(input.size() != 0) {

        if(input.size() == 1) { //base case: no connectors
            arguments.clear();
            _Tokenize(input.at(i), arguments);
            //commentCheck(arguments);
            //if(arguments.size() == 0) {return true;}
            executable = arguments.front();
            arguments.erase(arguments.begin());
            //cout << executable << ", " << arguments.at(0) << endl;
            command = new Cmd(executable, arguments);
            return command->execute(done);
        }
       // for(unsigned int a = 0; a < input.size(); ++a) {cout << input.at(a) << ", "; } cout << endl;

        if(input.at(i) == "(") { //check for beginning parentheses, if found ENTER RECURSION
            input.erase(input.begin());
            recursion = ParenthExecute(input, recursion);
            rightClosed = true;
            //for(unsigned int a = 0; a < input.size(); ++a) {cout << input.at(a) << ", "; } cout << endl;
            if(input.size() == 0) {break;}
        }

        if(input.at(i) == ")") {/*return false;*/ return recursion;}

        if(input.at(i) != ";" && input.at(i) != "&" && input.at(i) != "|") {
        arguments.clear();                    //parse first command
        _Tokenize(input.at(i), arguments);
        executable = arguments.front();
        arguments.erase(arguments.begin());
        command = new Cmd(executable, arguments);
        input.erase(input.begin());
        }

        if(input.at(i) == ")") {return command->execute(done);} //check if there is a single command contained within parentheses

        if(input.at(i) == ";") {
            connect = new Semi(command);
        }
        else if(input.at(i) == "&") {
            connect = new And(command);
        }
        else if(input.at(i) == "|") {
            connect = new Or(command);
        }
        input.erase(input.begin());

        if(rightClosed != true) {done = command->execute(done); rightClosed = false;} //execute command and return success
        skip = connect->execute(done); //execute connector to determine if rightCmd needs to be executed
        recursion = done;

        if(skip == true) { //verify that first OR condition succeeded
            input.erase(input.begin());
            while(input.size() != 0) {
                if(input.at(0) == ")") {/*return done;*/ return recursion;}
                if(input.at(0) == "(") {
                    input.erase(input.begin());
                    input.erase(input.begin());
                }
                if(input.at(0) == "|") {
                    input.erase(input.begin());
                    input.erase(input.begin());
                }
                if(input.size() == 0) {break;}
                if(input.at(0) == "&") {
                    input.erase(input.begin());
                    break;
                }
            }
        }
    }
    return 0;
}

void ParenthCheck(vector<string> input) {
    int leftParenth = 0;
    int rightParenth = 0;

    for(unsigned int i = 0; i < input.size(); ++i) {
        if(input.at(i) == "(") {leftParenth++;}
        if(input.at(i) == ")") {rightParenth++;}
    }
    if(leftParenth != rightParenth) {
        cout << "Error: Uneven number of parentheses." << endl;
    }
    if(leftParenth == rightParenth && leftParenth != 0 && rightParenth != 0) {
        ParenthExecute(input, 0);
    }
    if (leftParenth == 0 && rightParenth == 0) {
        Execute(input);
    }
}

int main() {
    string executable = "";
        vector<string> tok;
   while(1) {
        tok.clear();

        cout << "$ ";
        getline(cin, executable);

        Tokenize(executable, tok);
        commentCheck(tok);
        ParenthCheck(tok);
        //Execute(tok);
   }
}

<commit_msg>Precedence operators full functional<commit_after>#include <iostream>
#include <vector>
#include <cstring>
using namespace std;

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <boost/tokenizer.hpp>

#include "Base.h"
#include "Cmd.h"
#include "Or.h"
#include "And.h"
#include "Semi.h"
using namespace std;
using namespace boost;

void Tokenize (const string& str, vector<string>& vec) { //splits string into tokens
    typedef tokenizer<char_separator<char> > tokenizer;
    char_separator<char> sep(";&|#()", ";&|#()", boost::keep_empty_tokens);
    tokenizer tok(str, sep);

    for(tokenizer::iterator tok_iter = tok.begin(); tok_iter != tok.end(); ++tok_iter) {
        vec.push_back(*tok_iter);
        if(*tok_iter == "&" || *tok_iter == "|") {tok_iter++; tok_iter++;}
    }
    for(unsigned int a = 0; a < vec.size(); ++a) { //check for a delete empty spaces
        if(vec.at(a) == " " || vec.at(a) == "") {vec.erase(vec.begin() + a);}
    }

}
void _Tokenize (const string& str, vector<string>& vec) { //splits string into tokens
    typedef tokenizer<char_separator<char> > tokenizer;
    char_separator<char> sep(" ");
    tokenizer tok(str, sep);

    for(tokenizer::iterator tok_iter = tok.begin(); tok_iter != tok.end(); ++tok_iter) {
        vec.push_back(*tok_iter);
        //if(*tok_iter == "&" || *tok_iter == "|") {tok_iter++;}
    }

}

void commentCheck(vector<string>& tok) { //if a # is detected, remove all following tokens
    if(tok.size() >= 2) {
        if (tok.at(1) == "#") {tok.clear();}
    }
    for(unsigned int i = 0; i < tok.size(); ++i) {
        if(tok.at(i) == "#") {
            tok.erase(tok.begin() + i, tok.end());
        }
    }
}

bool Execute(vector<string> input) {
    vector<string> arguments;
    string executable;
    Cmd* command;
    Connector* connect;
    bool done = false;
    bool skip = false;
    int i = 0;

    while(input.size() != 0) {

        if(input.size() == 1) { //base case: no connectors
            arguments.clear();
            _Tokenize(input.at(i), arguments);
            //commentCheck(arguments);
            //if(arguments.size() == 0) {return true;}
            executable = arguments.front();
            arguments.erase(arguments.begin());
            //cout << executable << ", " << arguments.at(0) << endl;
            command = new Cmd(executable, arguments);
            return command->execute(done);

        }
        arguments.clear();
        _Tokenize(input.at(i), arguments);
        executable = arguments.front();
        arguments.erase(arguments.begin());
        command = new Cmd(executable, arguments);

        input.erase(input.begin());

        if(input.at(i) == ";") {
            connect = new Semi(command);
        }
        else if(input.at(i) == "&") {
            connect = new And(command);
        }
        else if(input.at(i) == "|") {
            connect = new Or(command);
        }
        input.erase(input.begin());

        done = command->execute(done);
        skip = connect->execute(done);

        if(skip == true) { //check if the first OR condition executed
            input.erase(input.begin());
            while(input.size() != 0) {
                if(input.at(0) == "|") {
                    input.erase(input.begin());
                    input.erase(input.begin());
                }
                if(input.size() == 0) {break;}
                if(input.at(0) == "&") {
                    input.erase(input.begin());
                    break;
                }
            }
        }
    }
    return 0;
}

bool ParenthExecute(vector<string>& input, bool in) {
    vector<string> arguments;
    string executable;
    Cmd* command;
    Connector* connect;
    bool done = false;
    bool skip = false;
    bool recursion = false; //used to track whether commands in parentheses succeeded
    bool rightClosed = false; //check if the parentheses have closed
    bool andVal = false;
    int i = 0;

    while(input.size() != 0) {
        //for(unsigned int j = 0; j < input.size(); ++j) {cout << input.at(j) << ", ";} cout << endl;
        if(input.size() == 1) { //BASE CASE: no connectors left
            arguments.clear();
            _Tokenize(input.at(i), arguments);
            executable = arguments.front();
            arguments.erase(arguments.begin());
            command = new Cmd(executable, arguments);
            return command->execute(done);
        }

        if(input.at(i) == "(") { //check for beginning parentheses, if found ENTER RECURSION
            input.erase(input.begin());
            //for(unsigned int j = 0; j < input.size(); ++j) {cout << input.at(j) << ", ";} cout << endl;
            recursion = ParenthExecute(input, recursion);
            rightClosed = true;
            if(input.size() == 0) {break;}
        }

        if(input.at(i) == ")") { //checks for empty parentheses
            input.erase(input.begin());
            //for(unsigned int j = 0; j < input.size(); ++j) {cout << input.at(j) << ", ";} cout << endl;
            return recursion;
        }

        if(input.at(i) != ";" && input.at(i) != "&" && input.at(i) != "|") { //check if a new command must be parsed
            arguments.clear();                    //parse first command
            _Tokenize(input.at(i), arguments);
            executable = arguments.front();
            arguments.erase(arguments.begin());
            command = new Cmd(executable, arguments);
            input.erase(input.begin());
            //for(unsigned int j = 0; j < input.size(); ++j) {cout << input.at(j) << ", ";} cout << endl;
        }

        if(input.at(i) == ")") { //check if there is a single command left within parentheses
            input.erase(input.begin());
            //for(unsigned int j = 0; j < input.size(); ++j) {cout << input.at(j) << ", ";} cout << endl;
            return command->execute(done);
        }

        if(input.at(i) == ";") { //check for appropriate connector
            connect = new Semi(command);
            input.erase(input.begin());
            andVal = true;
        }
        else if(input.at(i) == "&") {
            connect = new And(command);
            input.erase(input.begin());
            andVal = true;
        }
        else if(input.at(i) == "|") {
            connect = new Or(command);
            input.erase(input.begin());
        } //for(unsigned int j = 0; j < input.size(); ++j) {cout << input.at(j) << ", ";} cout << endl;

        //if l-value is parentheses, set new command (r-value)
        if(rightClosed == true) {
            arguments.clear();
            _Tokenize(input.at(i), arguments);
            executable = arguments.front();
            arguments.erase(arguments.begin());
            command = new Cmd(executable, arguments);
            input.erase(input.begin());
        }

        if(recursion != true || andVal == true) {
            andVal = false;
            done = command->execute(done); //execute command and return success
            recursion = done;
            rightClosed = false;
            skip = connect->execute(done);
        }

        else { //if l-value succeeded, no need to re-execute command, simply figure out if skipping commands is necessary
            skip = connect->execute(recursion);
        } //execute connector to determine if rightCmd needs to be executed

        if(skip == true && input.size() >= 1) { //verify that first OR condition succeeded
            input.erase(input.begin());
            while(input.size() != 0) {
                if(input.at(0) == ")") {input.erase(input.begin()); return recursion;}
                //for(unsigned int j = 0; j < input.size(); ++j) {cout << input.at(j) << ", ";} cout << endl; return recursion;}
                if(input.at(0) == "(") {
                    input.erase(input.begin());
                    input.erase(input.begin());
                    //for(unsigned int j = 0; j < input.size(); ++j) {cout << input.at(j) << ", ";} cout << endl;
                }
                if(input.at(0) == "|") {
                    input.erase(input.begin());
                    input.erase(input.begin());
                    //for(unsigned int j = 0; j < input.size(); ++j) {cout << input.at(j) << ", ";} cout << endl;
                }
                if(input.size() == 0) {break;}
                if(input.at(0) == "&") {
                    input.erase(input.begin());
                    //for(unsigned int j = 0; j < input.size(); ++j) {cout << input.at(j) << ", ";} cout << endl;
                    break;
                }
            }
        }

    }
    return 0;
}

void ParenthCheck(vector<string> input) {
    int leftParenth = 0;
    int rightParenth = 0;

    for(unsigned int i = 0; i < input.size(); ++i) {
        if(input.at(i) == "(") {leftParenth++;}
        if(input.at(i) == ")") {rightParenth++;}
    }
    if(leftParenth != rightParenth) {
        cout << "Error: Uneven number of parentheses." << endl;
    }
    if(leftParenth == rightParenth && leftParenth != 0 && rightParenth != 0) {
        ParenthExecute(input, 0);
    }
    if (leftParenth == 0 && rightParenth == 0) {
        Execute(input);
    }
}

int main() {
    string executable = "";
        vector<string> tok;
   while(1) {
        tok.clear();

        cout << "$ ";
        getline(cin, executable);

        Tokenize(executable, tok);
        commentCheck(tok);
        ParenthCheck(tok);
        //Execute(tok);
   }
}

<|endoftext|>


<commit_before>#include "mraa.h"
#include <chrono>
#include <thread>
#include <stdio.h>
#include <string.h>
#include <curl/curl.h>

enum COMMAND
{
    IDLE = 0,
    FORWARD = 1,
    REVERSE = 2,
    LEFT = 4,
    RIGHT = 8
};
const char* COMMAND_NAMES[] = {"IDLE","FORWARD","REVERSE","INVALID","LEFT","INVALID","INVALID","INVALID","RIGHT"};

int getCommand();
void loop(mraa_gpio_context gpio_context);

int gMagnitude = 0;
bool gReverseEnabled = false;
const char* RC_ADDRESS = "http://192.168.1.243:8080/CommandServer/currentCommand";

#define DRIVE_MOTOR_GPIO 31 //GP44
#define REVERSE_ENGAGE_GPIO 32 //GP46
#define DEFAULT_WAIT_TIME_MS 300

int main(int argc, char** argv)
{
    curl_global_init(CURL_GLOBAL_DEFAULT);
    mraa_init();
    mraa_gpio_context drive_context = mraa_gpio_init(DRIVE_MOTOR_GPIO);
    if(drive_context == NULL || mraa_gpio_dir(drive_context, MRAA_GPIO_OUT) != MRAA_SUCCESS) exit(1);
    mraa_gpio_write(drive_context, false);
    mraa_gpio_context reverse_context = mraa_gpio_init(REVERSE_ENGAGE_GPIO);
    if(reverse_context == NULL || mraa_gpio_dir(reverse_context, MRAA_GPIO_OUT) != MRAA_SUCCESS) exit(1);
    mraa_gpio_write(reverse_context, false);

    printf("%s Wifi RC Interface\n", mraa_get_platform_name());

    while(true) loop(drive_context);

    curl_global_cleanup();
    mraa_deinit();

    return 0;

}

size_t curl_write_function(void* buffer, size_t size, size_t nmemb, int* p)
{
    static const char* NAME_STRING = "Name";
    static const char* VALUE_STRING = "Value";
    static const char* RESPONSE_STRING = "Response";
    static const char* TERMINAL_STRING = "Terminal";
    static const char* directionTerminal = "direction";
    static const char* magnitudeTerminal = "magnitude";

    char test[64];
    char name[64];
    char value[64];
    char* parse = strstr((char*)buffer, RESPONSE_STRING)+strlen(RESPONSE_STRING)+1;
    memset(test, '\0', 64);
    memcpy(test, parse+3, strlen(RESPONSE_STRING));
    while(strcmp(test, RESPONSE_STRING))
    {
        parse = strstr(parse, TERMINAL_STRING)+strlen(TERMINAL_STRING)+1;
        parse = strstr(parse, NAME_STRING)+strlen(NAME_STRING)+1;
        int length = strchr(parse, '<')-parse;
        memset(name, '\0', 64);
        memcpy(name, parse, length);
        parse = strstr(parse, VALUE_STRING)+strlen(VALUE_STRING)+1;
        length = strchr(parse, '<')-parse;
        memset(value, '\0', 64);
        memcpy(value, parse, length);
        parse = strstr(parse, TERMINAL_STRING)+strlen(TERMINAL_STRING)+1;
        memset(test, '\0', 64);
        memcpy(test, parse+3, strlen(RESPONSE_STRING));
        if(!strcmp(name, directionTerminal))
        {
            *p = atoi(value);
        }
        if(!strcmp(name, magnitudeTerminal))
        {
            gMagnitude = atoi(value);
        }
    }

    return size*nmemb;
}

int getCommand()
{
    int command = IDLE;
    CURL* pCURL = curl_easy_init();
    if(pCURL)
    {
        int temp;
        curl_easy_setopt(pCURL, CURLOPT_URL, RC_ADDRESS);
        curl_easy_setopt(pCURL, CURLOPT_WRITEFUNCTION, curl_write_function);
        curl_easy_setopt(pCURL, CURLOPT_WRITEDATA, &temp);
        CURLcode result = curl_easy_perform(pCURL);
        if(result == CURLE_OK)
        {
            command = temp;
        }
        curl_easy_cleanup(pCURL);
    }

    return command;

}

void enableReverse(bool enabled, mraa_gpio_context gpio_context)
{
    mraa_gpio_write(gpio_context, false);
    std::this_thread::sleep_for(std::chrono::milliseconds(DEFAULT_WAIT_TIME_MS));
    //Shift into/out of reverse here
    gReverseEnabled = enabled;
}

void loop(mraa_gpio_context gpio_context)
{
    int raw = getCommand();

    int value = raw;
    if(value > 3) value &= 0xC;
    printf("%s\n", COMMAND_NAMES[value]);

    bool killReverse = true;
    bool shouldDrive = false;
    switch(raw &= 0x3)
    {
        case FORWARD:
            shouldDrive = true;
            break;
        case REVERSE:
            killReverse = false;
            if(!gReverseEnabled) enableReverse(true, gpio_context);
            shouldDrive = true;
            break;
        case IDLE:
        default:
            break;
    }
    if(gReverseEnabled && killReverse) enableReverse(false, gpio_context);
    mraa_gpio_write(gpio_context, shouldDrive);
    std::this_thread::sleep_for(std::chrono::milliseconds(gMagnitude > 0 ? gMagnitude: DEFAULT_WAIT_TIME_MS));
}
<commit_msg>Enable reverse gear<commit_after>#include "mraa.h"
#include <chrono>
#include <thread>
#include <stdio.h>
#include <string.h>
#include <curl/curl.h>

enum COMMAND
{
    IDLE = 0,
    FORWARD = 1,
    REVERSE = 2,
    LEFT = 4,
    RIGHT = 8
};
const char* COMMAND_NAMES[] = {"IDLE","FORWARD","REVERSE","INVALID","LEFT","INVALID","INVALID","INVALID","RIGHT"};

struct context
{
    mraa_gpio_context drive_context;
    mraa_gpio_context reverse_context;
};

int getCommand();
void loop(context& gpio_context);

int gMagnitude = 0;
bool gReverseEnabled = false;
const char* RC_ADDRESS = "http://192.168.1.243:8080/CommandServer/currentCommand";

#define DRIVE_MOTOR_GPIO 31 //GP44
#define REVERSE_ENGAGE_GPIO 32 //GP46
#define DEFAULT_WAIT_TIME_MS 300

int main(int argc, char** argv)
{
    curl_global_init(CURL_GLOBAL_DEFAULT);
    mraa_init();
    mraa_gpio_context drive_context = mraa_gpio_init(DRIVE_MOTOR_GPIO);
    if(drive_context == NULL || mraa_gpio_dir(drive_context, MRAA_GPIO_OUT) != MRAA_SUCCESS) exit(1);
    mraa_gpio_write(drive_context, false);
    mraa_gpio_context reverse_context = mraa_gpio_init(REVERSE_ENGAGE_GPIO);
    if(reverse_context == NULL || mraa_gpio_dir(reverse_context, MRAA_GPIO_OUT) != MRAA_SUCCESS) exit(1);
    mraa_gpio_write(reverse_context, false);

    printf("%s Wifi RC Interface\n", mraa_get_platform_name());

    context session;
    session.drive_context = drive_context;
    session.reverse_context = reverse_context;
    while(true) loop(session);

    curl_global_cleanup();
    mraa_deinit();

    return 0;

}

size_t curl_write_function(void* buffer, size_t size, size_t nmemb, int* p)
{
    static const char* NAME_STRING = "Name";
    static const char* VALUE_STRING = "Value";
    static const char* RESPONSE_STRING = "Response";
    static const char* TERMINAL_STRING = "Terminal";
    static const char* directionTerminal = "direction";
    static const char* magnitudeTerminal = "magnitude";

    char test[64];
    char name[64];
    char value[64];
    char* parse = strstr((char*)buffer, RESPONSE_STRING)+strlen(RESPONSE_STRING)+1;
    memset(test, '\0', 64);
    memcpy(test, parse+3, strlen(RESPONSE_STRING));
    while(strcmp(test, RESPONSE_STRING))
    {
        parse = strstr(parse, TERMINAL_STRING)+strlen(TERMINAL_STRING)+1;
        parse = strstr(parse, NAME_STRING)+strlen(NAME_STRING)+1;
        int length = strchr(parse, '<')-parse;
        memset(name, '\0', 64);
        memcpy(name, parse, length);
        parse = strstr(parse, VALUE_STRING)+strlen(VALUE_STRING)+1;
        length = strchr(parse, '<')-parse;
        memset(value, '\0', 64);
        memcpy(value, parse, length);
        parse = strstr(parse, TERMINAL_STRING)+strlen(TERMINAL_STRING)+1;
        memset(test, '\0', 64);
        memcpy(test, parse+3, strlen(RESPONSE_STRING));
        if(!strcmp(name, directionTerminal))
        {
            *p = atoi(value);
        }
        if(!strcmp(name, magnitudeTerminal))
        {
            gMagnitude = atoi(value);
        }
    }

    return size*nmemb;
}

int getCommand()
{
    int command = IDLE;
    CURL* pCURL = curl_easy_init();
    if(pCURL)
    {
        int temp;
        curl_easy_setopt(pCURL, CURLOPT_URL, RC_ADDRESS);
        curl_easy_setopt(pCURL, CURLOPT_WRITEFUNCTION, curl_write_function);
        curl_easy_setopt(pCURL, CURLOPT_WRITEDATA, &temp);
        CURLcode result = curl_easy_perform(pCURL);
        if(result == CURLE_OK)
        {
            command = temp;
        }
        curl_easy_cleanup(pCURL);
    }

    return command;

}

void enableReverse(bool enabled, context& gpio_context)
{
    mraa_gpio_write(gpio_context.drive_context, false);
    std::this_thread::sleep_for(std::chrono::milliseconds(DEFAULT_WAIT_TIME_MS));
    mraa_gpio_write(gpio_context.reverse_context, enabled);
    gReverseEnabled = enabled;
}

void loop(context& gpio_context)
{
    int raw = getCommand();

    int value = raw;
    if(value > 3) value &= 0xC;
    printf("%s\n", COMMAND_NAMES[value]);

    bool killReverse = true;
    bool shouldDrive = false;
    switch(raw &= 0x3)
    {
        case FORWARD:
            shouldDrive = true;
            break;
        case REVERSE:
            killReverse = false;
            if(!gReverseEnabled) enableReverse(true, gpio_context);
            shouldDrive = true;
            break;
        case IDLE:
        default:
            break;
    }
    if(gReverseEnabled && killReverse) enableReverse(false, gpio_context);
    mraa_gpio_write(gpio_context.drive_context, shouldDrive);
    std::this_thread::sleep_for(std::chrono::milliseconds(gMagnitude > 0 ? gMagnitude: DEFAULT_WAIT_TIME_MS));
}
<|endoftext|>


<commit_before>#include <iostream>
#include <fstream>
#include <cstdint>
#include <algorithm>
#include <memory>
#include <chrono>

#include <boost/thread.hpp>

//#include <SFML/System.hpp>
#include <SFML/Window.hpp>
#include <SFML/Graphics.hpp>
#include <SFML/Graphics/Texture.hpp>

#include "dcpu.hpp"
#include "disassembler.hpp"

#include "gclock.hpp"
//#include "fake_lem1802.hpp"
#include "lem1802.hpp"
#include "lem1803.hpp"
#include "cgm.hpp"

using namespace cpu;

/*
const long TOTALCPUS    = 215*16;
const long PERTHREAD    = 16;  // At 16 looks that is the ideal for the FX-4100
#define THREADS           (TOTALCPUS/PERTHREAD)
const long CYCLES       = 1000*1000;

const int BATCH         = 10;
*/

//std::vector<std::vector<std::shared_ptr<DCPU>>> threads;
uint16_t* data;
size_t size = 0;

//void benchmark();
void step();
void run();

void renderGuy(sf::RenderWindow* win, std::shared_ptr<cpu::AbstractMonitor> mon);

//void cpu_in_thread(int n);

int main (int argc, char **argv)
{

    char* filename;
    std::ifstream binfile;

    if (argc <= 1) {
        std::cerr << "Missing input file\n";
        return 0;
    }

    filename = argv[1];
    std::cout <<  "Input BIN File : " << filename << "\n";

    binfile.open (filename, std::ios::in | std::ios::binary );

    if (!binfile) {
        std::cerr << "ERROR: I can open file\n";
        exit (1);
    }

    // get length of file:
    binfile.seekg (0, binfile.end);
    size = binfile.tellg();
    binfile.seekg (0, binfile.beg);

    data = new uint16_t[size / 2 + 1]();
    std::fill_n (data, size / 2, 0); // Clean it

    int i = 0;

    while (! binfile.eof() ) {
        uint16_t word = 0;
        binfile.read ( (char*) &word, 2);
        unsigned char tmp = ( (word & 0xFF00) >> 8) & 0x00FF;
        word = ( (word & 0x00FF) << 8) | tmp;
        data[i] = word;
        i++;
    }

    binfile.close();

    std::cout << "Readed " << size << " bytes - " << size / 2 << " words\n";
    size /= 2;

badchar:
    std::cout << "Select what to do :" << std::endl;
    std::cout << "\ts -> step execution\n\tr-> run";
    std::cout << std::endl << std::endl;
    char choose;
    std::cin >> choose;

/*    if (choose == 'b' || choose == 'B') {
        benchmark();
    } else*/ if ( choose == 's' || choose == 'S') {
        step();
    } else if ( choose == 'r' || choose == 'R') {
        run();
    } else {
        goto badchar; /// HATE ME!!!!
    }

    delete[] data;

    return 0;
}

/*
void benchmark()
{
    // Load program to all CPUs
    for (int u=0; u< THREADS; u++) {
        std::vector<std::shared_ptr<DCPU>> cpus;
        cpus.reserve (PERTHREAD);
        for (int i = 0; i< PERTHREAD; i++) {
            auto cpu = std::make_shared<DCPU>();
            //auto screen = std::make_shared<Fake_Lem1802>();
            //screen->setEnable(false); // We not desire to write to stdout
            //cpu->attachHardware (screen);
            cpu->reset();
            cpu->loadProgram (data, size);

            cpus.push_back(cpu);
        }

        threads.push_back(cpus);

    }

    sf::Thread* tds[THREADS];

    std::cout << "Threads " << THREADS << "\t CPU PerThread " << PERTHREAD;
    std::cout << "\t N cpus " << PERTHREAD * THREADS << std::endl;
    std::cout << "Cycles " << CYCLES << std::endl;

    auto start = std::chrono::high_resolution_clock::now();

    for (int i=0; i< THREADS; i++) {
        tds[i] = new sf::Thread(cpu_in_thread, i);
        tds[i]->launch();
    }

    for (int i=0; i< THREADS; i++) {
        delete tds[i]; //wait() is automatically called
    }

	auto end = std::chrono::high_resolution_clock::now();
    auto dur = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
	std::cout << "Measured time: " << dur.count() << "ms" << std::endl;

}
*/
void step() {
    using namespace std;
    auto cpu = make_shared<DCPU>();

    auto screen = make_shared<lem::Lem1802>();
    cpu->attachHardware (screen);

    sf::RenderWindow win(sf::VideoMode(
                                screen->phyWidth()  + screen->borderSize()*2,
                                screen->phyHeight() + screen->borderSize()*2),
                            "DCPU-16");

    auto clock = make_shared<Generic_Clock>();
    cpu->attachHardware (clock);

    cpu->reset();
    cpu->loadProgram (data, size);

    char c = getchar();
    while (1) {
        c = getchar();
        if (c == 'f' || c == 'q' || c == '\n' )
            break;
    }

    win.setActive(false);
    boost::thread thr_render (renderGuy, &win,
            std::static_pointer_cast<cpu::AbstractMonitor>(screen));

    while (c != 'q' && win.isOpen()) {
        cout << cpu->dumpRegisters() << endl;
        cout << "T cycles " << dec << cpu->getTotCycles() << endl;
        cout << "> " << cpu->dumpRam() << " - ";
        string s = disassembly(cpu->getMem() + cpu->GetPC(), 3);
        cout << s << endl;

        if (cpu->GetSP() != 0x0000)
            cout << "STACK : "<< cpu->dumpRam(cpu->GetSP(), 0xFFFF) << endl;

        if (c == 'f') {
            for (int i = 0; i < 100; i++)
                cpu->step();
                //cpu->tick();
        } else {
            cpu->step();
            /*if (cpu->tick())
                cout << "Execute! ";*/
        }
        cout << endl;

        while (1) {
            c = getchar();
            if (c == 'f' || c == 'q' || c == '\n' )
                break;
        }

    }
    if (win.isOpen())
        win.close();

    if (thr_render.joinable())
        thr_render.join();

}

void run() {

    using namespace std;
    using namespace std::chrono;

    auto cpu = make_shared<DCPU>();

    auto screen = make_shared<cgm::CGM>();
    cpu->attachHardware (screen);

    sf::RenderWindow win(sf::VideoMode(
                                screen->phyWidth()  + screen->borderSize()*2,
                                screen->phyHeight() + screen->borderSize()*2),
                            "DCPU-16");

    auto clock = make_shared<Generic_Clock>();
    cpu->attachHardware (clock);

    cpu->reset();
    cpu->loadProgram (data, size);

    high_resolution_clock::time_point t = high_resolution_clock::now();
    high_resolution_clock::time_point t2;

    win.setActive(false);
    boost::thread thr_render (renderGuy, &win,
            std::static_pointer_cast<cpu::AbstractMonitor>(screen));

    while (win.isOpen() ) { //&& wincgm.isOpen()) {
        t2 =  high_resolution_clock::now();

        cpu->tick();

        //auto rest = nanoseconds(1000000000/cpu->cpu_clock)-delta;

        if ((cpu->getTotCycles() % 50000) == 0) { // Not show running speed every clock tick
            auto delta = duration_cast<chrono::nanoseconds>(t2 - t);
            //double p = nanoseconds(1000000000/cpu->cpu_clock).count() /
            //    (double)(delta.count() + rest.count());
            cerr << "Delta :" << delta.count() << " ns " << endl;
            //cerr << "Rest :" << rest.count() << " ns ";
            //cerr << " Running at "<< p*100.0 << " % speed." << endl;
        }

        t = t2;
    }
    if (thr_render.joinable())
        thr_render.join();

    cout << "Finish" << endl;

}

/*

// Runs PERTHREAD cpus, doing CYCLES cycles
void cpu_in_thread(int n) {
    auto cpus = threads[n];
    for (long i=0; i < CYCLES; i+= BATCH) {
        for (auto c = cpus.begin(); c != cpus.end(); c++) {
            for ( int j=0; j < BATCH; j++)
                (*c)->tick();
        }
    }
}
*/

void renderGuy(sf::RenderWindow* win, std::shared_ptr<cpu::AbstractMonitor> mon)
{
    sf::Texture texture_lem;

    while (win->isOpen()) {
        sf::Event event;
        while (win->pollEvent(event)) {
            if (event.type == sf::Event::Closed) {
                win->close();
                continue;
            }
        }

        win->clear(mon->getBorder());

        sf::Image* scr = mon->updateScreen();
        texture_lem.create(mon->width(), mon->height());
        texture_lem.loadFromImage(*scr);
        sf::Sprite sprite_lem(texture_lem);
        sprite_lem.scale(
                mon->phyWidth()  / (float)(mon->width() ) ,
                mon->phyHeight() / (float)(mon->height()) );
        sprite_lem.setPosition(mon->borderSize(), mon->borderSize());

        win->draw(sprite_lem);
        win->display();

        delete scr;
    }
}

<commit_msg>CGM and LEM1803 at sametime in run mode: TOFIX: error when finish execution and bad texture size<commit_after>#include <iostream>
#include <fstream>
#include <cstdint>
#include <algorithm>
#include <memory>
#include <chrono>

#include <boost/thread.hpp>

//#include <SFML/System.hpp>
#include <SFML/Window.hpp>
#include <SFML/Graphics.hpp>
#include <SFML/Graphics/Texture.hpp>

#include "dcpu.hpp"
#include "disassembler.hpp"

#include "gclock.hpp"
//#include "fake_lem1802.hpp"
#include "lem1802.hpp"
#include "lem1803.hpp"
#include "cgm.hpp"

using namespace cpu;

/*
const long TOTALCPUS    = 215*16;
const long PERTHREAD    = 16;  // At 16 looks that is the ideal for the FX-4100
#define THREADS           (TOTALCPUS/PERTHREAD)
const long CYCLES       = 1000*1000;

const int BATCH         = 10;
*/

//std::vector<std::vector<std::shared_ptr<DCPU>>> threads;
uint16_t* data;
size_t size = 0;

//void benchmark();
void step();
void run();

void renderGuy(sf::RenderWindow* win, std::shared_ptr<cpu::AbstractMonitor> mon);

//void cpu_in_thread(int n);

int main (int argc, char **argv)
{

    char* filename;
    std::ifstream binfile;

    if (argc <= 1) {
        std::cerr << "Missing input file\n";
        return 0;
    }

    filename = argv[1];
    std::cout <<  "Input BIN File : " << filename << "\n";

    binfile.open (filename, std::ios::in | std::ios::binary );

    if (!binfile) {
        std::cerr << "ERROR: I can open file\n";
        exit (1);
    }

    // get length of file:
    binfile.seekg (0, binfile.end);
    size = binfile.tellg();
    binfile.seekg (0, binfile.beg);

    data = new uint16_t[size / 2 + 1]();
    std::fill_n (data, size / 2, 0); // Clean it

    int i = 0;

    while (! binfile.eof() ) {
        uint16_t word = 0;
        binfile.read ( (char*) &word, 2);
        unsigned char tmp = ( (word & 0xFF00) >> 8) & 0x00FF;
        word = ( (word & 0x00FF) << 8) | tmp;
        data[i] = word;
        i++;
    }

    binfile.close();

    std::cout << "Readed " << size << " bytes - " << size / 2 << " words\n";
    size /= 2;

badchar:
    std::cout << "Select what to do :" << std::endl;
    std::cout << "\ts -> step execution\n\tr-> run";
    std::cout << std::endl << std::endl;
    char choose;
    std::cin >> choose;

/*    if (choose == 'b' || choose == 'B') {
        benchmark();
    } else*/ if ( choose == 's' || choose == 'S') {
        step();
    } else if ( choose == 'r' || choose == 'R') {
        run();
    } else {
        goto badchar; /// HATE ME!!!!
    }

    delete[] data;

    return 0;
}

/*
void benchmark()
{
    // Load program to all CPUs
    for (int u=0; u< THREADS; u++) {
        std::vector<std::shared_ptr<DCPU>> cpus;
        cpus.reserve (PERTHREAD);
        for (int i = 0; i< PERTHREAD; i++) {
            auto cpu = std::make_shared<DCPU>();
            //auto screen = std::make_shared<Fake_Lem1802>();
            //screen->setEnable(false); // We not desire to write to stdout
            //cpu->attachHardware (screen);
            cpu->reset();
            cpu->loadProgram (data, size);

            cpus.push_back(cpu);
        }

        threads.push_back(cpus);

    }

    sf::Thread* tds[THREADS];

    std::cout << "Threads " << THREADS << "\t CPU PerThread " << PERTHREAD;
    std::cout << "\t N cpus " << PERTHREAD * THREADS << std::endl;
    std::cout << "Cycles " << CYCLES << std::endl;

    auto start = std::chrono::high_resolution_clock::now();

    for (int i=0; i< THREADS; i++) {
        tds[i] = new sf::Thread(cpu_in_thread, i);
        tds[i]->launch();
    }

    for (int i=0; i< THREADS; i++) {
        delete tds[i]; //wait() is automatically called
    }

	auto end = std::chrono::high_resolution_clock::now();
    auto dur = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
	std::cout << "Measured time: " << dur.count() << "ms" << std::endl;

}
*/
void step() {
    using namespace std;
    auto cpu = make_shared<DCPU>();

    auto screen = make_shared<lem::Lem1802>();
    cpu->attachHardware (screen);

    sf::RenderWindow win(sf::VideoMode(
                                screen->phyWidth()  + screen->borderSize()*2,
                                screen->phyHeight() + screen->borderSize()*2),
                            "DCPU-16");

    auto clock = make_shared<Generic_Clock>();
    cpu->attachHardware (clock);

    cpu->reset();
    cpu->loadProgram (data, size);

    char c = getchar();
    while (1) {
        c = getchar();
        if (c == 'f' || c == 'q' || c == '\n' )
            break;
    }

    win.setActive(false);
    boost::thread thr_render (renderGuy, &win,
            std::static_pointer_cast<cpu::AbstractMonitor>(screen));

    while (c != 'q' && win.isOpen()) {
        cout << cpu->dumpRegisters() << endl;
        cout << "T cycles " << dec << cpu->getTotCycles() << endl;
        cout << "> " << cpu->dumpRam() << " - ";
        string s = disassembly(cpu->getMem() + cpu->GetPC(), 3);
        cout << s << endl;

        if (cpu->GetSP() != 0x0000)
            cout << "STACK : "<< cpu->dumpRam(cpu->GetSP(), 0xFFFF) << endl;

        if (c == 'f') {
            for (int i = 0; i < 100; i++)
                cpu->step();
                //cpu->tick();
        } else {
            cpu->step();
            /*if (cpu->tick())
                cout << "Execute! ";*/
        }
        cout << endl;

        while (1) {
            c = getchar();
            if (c == 'f' || c == 'q' || c == '\n' )
                break;
        }

    }
    if (win.isOpen())
        win.close();

    if (thr_render.joinable())
        thr_render.join();

}

void run() {

    using namespace std;
    using namespace std::chrono;

    auto cpu = make_shared<DCPU>();

    auto screen = make_shared<cgm::CGM>();
    cpu->attachHardware (screen);

    sf::RenderWindow win(sf::VideoMode(
                                screen->phyWidth()  + screen->borderSize()*2,
                                screen->phyHeight() + screen->borderSize()*2),
                            "DCPU-16 CGM1084");

    auto screen2 = make_shared<lem::Lem1803>();
    cpu->attachHardware (screen2);

    sf::RenderWindow win2(sf::VideoMode(
                                screen->phyWidth()  + screen->borderSize()*2,
                                screen->phyHeight() + screen->borderSize()*2),
                            "DCPU-16 LEM1803");

    auto clock = make_shared<Generic_Clock>();
    cpu->attachHardware (clock);

    cpu->reset();
    cpu->loadProgram (data, size);

    high_resolution_clock::time_point t = high_resolution_clock::now();
    high_resolution_clock::time_point t2;

    win.setActive(false);
    boost::thread thr_render (renderGuy, &win,
            std::static_pointer_cast<cpu::AbstractMonitor>(screen));

    win2.setActive(false);
    boost::thread thr_render2 (renderGuy, &win2,
            std::static_pointer_cast<cpu::AbstractMonitor>(screen2));

    while (win.isOpen() && win2.isOpen() ) { //&& wincgm.isOpen()) {
        t2 =  high_resolution_clock::now();

        cpu->tick();

        //auto rest = nanoseconds(1000000000/cpu->cpu_clock)-delta;

        if ((cpu->getTotCycles() % 50000) == 0) { // Not show running speed every clock tick
            auto delta = duration_cast<chrono::nanoseconds>(t2 - t);
            //double p = nanoseconds(1000000000/cpu->cpu_clock).count() /
            //    (double)(delta.count() + rest.count());
            cerr << "Delta :" << delta.count() << " ns " << endl;
            //cerr << "Rest :" << rest.count() << " ns ";
            //cerr << " Running at "<< p*100.0 << " % speed." << endl;
        }

        t = t2;
    }

    if (win.isOpen())
        win.close();
    if (win2.isOpen())
        win2.close();

    if (thr_render.joinable())
        thr_render.join();

    if (thr_render2.joinable())
        thr_render.join();

    cout << "Finish" << endl;

}

/*

// Runs PERTHREAD cpus, doing CYCLES cycles
void cpu_in_thread(int n) {
    auto cpus = threads[n];
    for (long i=0; i < CYCLES; i+= BATCH) {
        for (auto c = cpus.begin(); c != cpus.end(); c++) {
            for ( int j=0; j < BATCH; j++)
                (*c)->tick();
        }
    }
}
*/

void renderGuy(sf::RenderWindow* win, std::shared_ptr<cpu::AbstractMonitor> mon)
{
    sf::Texture texture_lem;

    while (win->isOpen()) {
        sf::Event event;
        while (win->pollEvent(event)) {
            if (event.type == sf::Event::Closed) {
                win->close();
                continue;
            }
        }

        win->clear(mon->getBorder());

        sf::Image* scr = mon->updateScreen();
        texture_lem.create(mon->width(), mon->height());
        texture_lem.loadFromImage(*scr);
        sf::Sprite sprite_lem(texture_lem);
        sprite_lem.scale(
                mon->phyWidth()  / (float)(mon->width() ) ,
                mon->phyHeight() / (float)(mon->height()) );
        sprite_lem.setPosition(mon->borderSize(), mon->borderSize());

        win->draw(sprite_lem);
        win->display();

        delete scr;
    }
}

<|endoftext|>


<commit_before>/******************************************************************************
 * Fake Frog                                                                  *
 * An Arduino-based project to build a frog-shaped temperature logger.        *
 * Author: David Lougheed. Copyright 2017.                                    *
 ******************************************************************************/

#define VERSION "0.1.0"

// Includes

#include <Arduino.h>
#include <Wire.h>
#include <LiquidCrystal.h>

#include <SD.h>
#include <RTClib.h>

// Compile-Time Settings

#define SERIAL_LOGGING          true    // Log to the serial display for debug.
#define FILE_LOGGING            true    // Log to file on SD card. (recommended)
#define DISPLAY_ENABLED         true    // Show menus and information on an LCD.
#define NUM_SAMPLES             10      // Samples get averaged to reduce noise.
#define SAMPLE_DELAY            10      // Milliseconds between samples.

// Hardware Settings

#define THERMISTOR_PIN          A0
#define THERMISTOR_SERIES_RES   10000
#define THERMISTOR_RES_NOM      10000   // Nominal resistance, R0.
#define THERMISTOR_B_COEFF      3950    // Beta coefficient of the thermistor.
#define THERMISTOR_TEMP_NOM     25      // Nominal temperature of R0.

#define SD_CARD_PIN             10
#define RTC_PIN_1               4
#define RTC_PIN_2               5
#define LCD_PIN_RS              6
#define LCD_PIN_EN              7
#define LCD_PIN_DB4             8
#define LCD_PIN_DB5             9
#define LCD_PIN_DB6             11
#define LCD_PIN_DB7             12

#define LCD_ROWS                2
#define LCD_COLUMNS             16

#define RTC_TYPE                RTC_PCF8523

// Other Compile-Time Constants

#define MAX_LOG_FILES           1000
#define MAX_DATA_FILES          1000

// Globals

bool serial_logging_started = false;

File log_file;
File data_file;

RTC_TYPE rtc;

LiquidCrystal* lcd;

// To save memory, use global data point variables.
DateTime now;
char formatted_timestamp[] = "0000-00-00T00:00:00";
char* data_file_entry_buffer = (char*) malloc(sizeof(char) * 50);
double latest_resistance;
double latest_temperature;

/*
    DISPLAY MODES (ALL WITH LOGGING)
    0: Idle
    1: Information (clock, space usage)
    2: RTC Editor
*/
uint8_t display_mode = 0;

uint16_t i; // 16-bit iterator

// Utility Methods

// Log a generic message.
void log(const char* msg, bool with_newline = true) {
    if (SERIAL_LOGGING) {
        if(!serial_logging_started) {
            Serial.begin(9600);
            Serial.println();
            serial_logging_started = true;
        }

        if (with_newline) {
            Serial.println(msg);
        } else {
            Serial.print(msg);
        }
    }

    if (FILE_LOGGING) {
        if (log_file) {
            if (with_newline) {
                log_file.println(msg);
            } else {
                log_file.print(msg);
            }
            log_file.flush();
        }
    }
}

// Log an error message. Uses standard log method, then hangs forever.
void log_error(const char* msg, bool with_newline = true) {
    log(msg, with_newline);
    while (true); // Loop forever
}

void update_screen() {
    if (DISPLAY_ENABLED && lcd) {
        lcd->clear();

        switch (display_mode) {
            case 1:
                lcd->print("TBD");
                break;
            case 2:
                lcd->print("TBD");
                break;
            case 0:
            default:
                break;
        }
    }
}

void switch_display_mode(uint8_t m) {
    display_mode = m;
    update_screen();
}

// Data Methods

// Update the global formatted timestamp string with the contents of 'now'.
void update_formatted_timestamp() {
    sprintf(formatted_timestamp, "%u-%u-%uT%u:%u:%u", now.year(),
        now.month(), now.day(), now.hour(), now.minute(), now.second());
}

double resistance_to_temperature(double resistance) {
    // Formula: T = 1/(1/B * ln(R/R_0) + (1/T0)) - 273.15 (celcius)
    return 1 / ((log(resistance / THERMISTOR_RES_NOM) / THERMISTOR_B_COEFF) + 1
        / (THERMISTOR_TEMP_NOM + 273.15)) - 273.15;
}

void take_reading() {
    now = rtc.now();

    latest_resistance = 0;

    for (i = 0; i < NUM_SAMPLES; i++) {
        latest_resistance += (double) analogRead(THERMISTOR_PIN);
        delay(SAMPLE_DELAY);
    }

    // Formulas: R = sr / (1023 / mean_of_samples - 1)
    //           sr = thermistor series resistance

    latest_resistance = THERMISTOR_SERIES_RES
        / (1023 / (latest_resistance / NUM_SAMPLES) - 1); // Resistance
    latest_temperature = resistance_to_temperature(latest_resistance);

    // TODO: Error calculations
}

void save_reading_to_card() {
    if (data_file) {
        update_formatted_timestamp();
        sprintf(data_file_entry_buffer, "%.2f,%s", latest_temperature,
            formatted_timestamp);
        data_file.println(data_file_entry_buffer);
        data_file.flush();
    }
}

// Main Methods

void setup() {
    // TODO: Set up pins

    // SET UP EXTERNAL ANALOG VOLTAGE REFERENCE
    // Typically from 3.3V Arduino supply. This reduces the voltage noise seen
    // from reading analog values.
    analogReference(EXTERNAL);

    // INITIALIZE SD CARD
    log("Initializing SD card... ", false);
    pinMode(SD_CARD_PIN, OUTPUT);
    if (!SD.begin()) {
        log_error("Failed.");
    }
    log("Done.");

    // SET UP LOG FILE
    if (FILE_LOGGING) {
        log("Creating log file... ", false);
        char log_file_name[] = "log_000.txt";
        for (i = 0; i < MAX_LOG_FILES; i++) {
            // Increment until we can find a log file slot.

            // Need to add 32 to get ASCII number characters.
            log_file_name[6] = i / 100 + 32;
            log_file_name[7] = i / 10 + 32;
            log_file_name[8] = i % 10 + 32;

            if (!SD.exists(log_file_name)) {
                log_file = SD.open(log_file_name, FILE_WRITE);
                break;
            }
        }
        if (log_file) {
            log("Done.");
        } else {
            log_error("Failed.");
        }
    }

    // SET UP RTC
    log("Initializing RTC...", false);
    Wire.begin();
    if (!rtc.begin()) {
        log_error("Failed.");
    }
    log("Done.");

    // TODO: Calibrate RTC

    // SET UP DATA FILE
    log("Creating data file...");
    char data_file_name[] = "data_000.csv";
    for (i = 0; i < MAX_DATA_FILES; i++) {
        // Increment until we can find a data file slot.

        // Need to add 32 to get ASCII digit characters.
        data_file_name[6] = i / 100 + 32;
        data_file_name[7] = i / 10 + 32;
        data_file_name[8] = i % 10 + 32;

        if (!SD.exists(data_file_name)) {
            data_file = SD.open(data_file_name, FILE_WRITE);
            break;
        }
    }
    if (data_file) {
        log("Done.");
    } else {
        log_error("Failed.");
    }

    // PRINT DATA FILE CSV HEADERS
    data_file.println("Timestamp,Temperature");
    data_file.flush();

    // SET UP LCD
    if (DISPLAY_ENABLED) {
        lcd = new LiquidCrystal(LCD_PIN_RS, LCD_PIN_EN, LCD_PIN_DB4,
            LCD_PIN_DB5, LCD_PIN_DB6, LCD_PIN_DB7);
        lcd->begin(LCD_COLUMNS, LCD_ROWS);
    }

    // Finished everything!
    now = rtc.now();
    update_formatted_timestamp();
    log("Data logger started at ", false);
    log(formatted_timestamp, false);
    log(". Software version: ", false);
    log(VERSION);
}

void loop() {
    // TODO: (Optional) Exit sleep

    take_reading();
    save_reading_to_card();

    // TODO: (Optional) Enter sleep

    delay(1000);
}
<commit_msg>Add proper reading interval timing (without sleep).<commit_after>/******************************************************************************
 * Fake Frog                                                                  *
 * An Arduino-based project to build a frog-shaped temperature logger.        *
 * Author: David Lougheed. Copyright 2017.                                    *
 ******************************************************************************/

#define VERSION "0.1.0"

// Includes

#include <Arduino.h>
#include <Wire.h>
#include <LiquidCrystal.h>

#include <SD.h>
#include <RTClib.h>

// Compile-Time Settings

#define SERIAL_LOGGING          true    // Log to the serial display for debug.
#define FILE_LOGGING            true    // Log to file on SD card. (recommended)
#define DISPLAY_ENABLED         true    // Show menus and information on an LCD.
#define NUM_SAMPLES             10      // Samples get averaged to reduce noise.
#define SAMPLE_DELAY            10      // Milliseconds between samples.
#define READING_INTERVAL        60      // Seconds between readings.

// Hardware Settings

#define THERMISTOR_PIN          A0
#define THERMISTOR_SERIES_RES   10000
#define THERMISTOR_RES_NOM      10000   // Nominal resistance, R0.
#define THERMISTOR_B_COEFF      3950    // Beta coefficient of the thermistor.
#define THERMISTOR_TEMP_NOM     25      // Nominal temperature of R0.

#define SD_CARD_PIN             10
#define RTC_PIN_1               4
#define RTC_PIN_2               5
#define LCD_PIN_RS              6
#define LCD_PIN_EN              7
#define LCD_PIN_DB4             8
#define LCD_PIN_DB5             9
#define LCD_PIN_DB6             11
#define LCD_PIN_DB7             12

#define LCD_ROWS                2
#define LCD_COLUMNS             16

#define RTC_TYPE                RTC_PCF8523

// Other Compile-Time Constants

#define MAX_LOG_FILES           1000
#define MAX_DATA_FILES          1000

// Globals

bool serial_logging_started = false;

File log_file;
File data_file;

RTC_TYPE rtc;

LiquidCrystal* lcd;

// To save memory, use global data point variables.
DateTime now;
char formatted_timestamp[] = "0000-00-00T00:00:00";
char* data_file_entry_buffer = (char*) malloc(sizeof(char) * 50);
double latest_resistance;
double latest_temperature;

/*
    DISPLAY MODES (ALL WITH LOGGING)
    0: Idle
    1: Information (clock, space usage)
    2: RTC Editor
*/
uint8_t display_mode = 0;

uint16_t i; // 16-bit iterator
uint8_t timer = 0; // Counts seconds

// Utility Methods

// Log a generic message.
void log(const char* msg, bool with_newline = true) {
    if (SERIAL_LOGGING) {
        if(!serial_logging_started) {
            Serial.begin(9600);
            Serial.println();
            serial_logging_started = true;
        }

        if (with_newline) {
            Serial.println(msg);
        } else {
            Serial.print(msg);
        }
    }

    if (FILE_LOGGING) {
        if (log_file) {
            if (with_newline) {
                log_file.println(msg);
            } else {
                log_file.print(msg);
            }
            log_file.flush();
        }
    }
}

// Log an error message. Uses standard log method, then hangs forever.
void log_error(const char* msg, bool with_newline = true) {
    log(msg, with_newline);
    while (true); // Loop forever
}

void update_screen() {
    if (DISPLAY_ENABLED && lcd) {
        lcd->clear();

        switch (display_mode) {
            case 1:
                lcd->print("TBD");
                break;
            case 2:
                lcd->print("TBD");
                break;
            case 0:
            default:
                break;
        }
    }
}

void switch_display_mode(uint8_t m) {
    display_mode = m;
    update_screen();
}

// Data Methods

// Update the global formatted timestamp string with the contents of 'now'.
void update_formatted_timestamp() {
    sprintf(formatted_timestamp, "%u-%u-%uT%u:%u:%u", now.year(),
        now.month(), now.day(), now.hour(), now.minute(), now.second());
}

double resistance_to_temperature(double resistance) {
    // Formula: T = 1/(1/B * ln(R/R_0) + (1/T0)) - 273.15 (celcius)
    return 1 / ((log(resistance / THERMISTOR_RES_NOM) / THERMISTOR_B_COEFF) + 1
        / (THERMISTOR_TEMP_NOM + 273.15)) - 273.15;
}

void take_reading() {
    now = rtc.now();

    latest_resistance = 0;

    for (i = 0; i < NUM_SAMPLES; i++) {
        latest_resistance += (double) analogRead(THERMISTOR_PIN);
        delay(SAMPLE_DELAY);
    }

    // Formulas: R = sr / (1023 / mean_of_samples - 1)
    //           sr = thermistor series resistance

    latest_resistance = THERMISTOR_SERIES_RES
        / (1023 / (latest_resistance / NUM_SAMPLES) - 1); // Resistance
    latest_temperature = resistance_to_temperature(latest_resistance);

    // TODO: Error calculations
}

void save_reading_to_card() {
    if (data_file) {
        update_formatted_timestamp();
        sprintf(data_file_entry_buffer, "%.2f,%s", latest_temperature,
            formatted_timestamp);
        data_file.println(data_file_entry_buffer);
        data_file.flush();
    }
}

// Main Methods

void setup() {
    // TODO: Set up pins

    // SET UP EXTERNAL ANALOG VOLTAGE REFERENCE
    // Typically from 3.3V Arduino supply. This reduces the voltage noise seen
    // from reading analog values.
    analogReference(EXTERNAL);

    // INITIALIZE SD CARD
    log("Initializing SD card... ", false);
    pinMode(SD_CARD_PIN, OUTPUT);
    if (!SD.begin()) {
        log_error("Failed.");
    }
    log("Done.");

    // SET UP LOG FILE
    if (FILE_LOGGING) {
        log("Creating log file... ", false);
        char log_file_name[] = "log_000.txt";
        for (i = 0; i < MAX_LOG_FILES; i++) {
            // Increment until we can find a log file slot.

            // Need to add 32 to get ASCII number characters.
            log_file_name[6] = i / 100 + 32;
            log_file_name[7] = i / 10 + 32;
            log_file_name[8] = i % 10 + 32;

            if (!SD.exists(log_file_name)) {
                log_file = SD.open(log_file_name, FILE_WRITE);
                break;
            }
        }
        if (log_file) {
            log("Done.");
        } else {
            log_error("Failed.");
        }
    }

    // SET UP RTC
    log("Initializing RTC...", false);
    Wire.begin();
    if (!rtc.begin()) {
        log_error("Failed.");
    }
    log("Done.");

    // TODO: Calibrate RTC

    // SET UP DATA FILE
    log("Creating data file...");
    char data_file_name[] = "data_000.csv";
    for (i = 0; i < MAX_DATA_FILES; i++) {
        // Increment until we can find a data file slot.

        // Need to add 32 to get ASCII digit characters.
        data_file_name[6] = i / 100 + 32;
        data_file_name[7] = i / 10 + 32;
        data_file_name[8] = i % 10 + 32;

        if (!SD.exists(data_file_name)) {
            data_file = SD.open(data_file_name, FILE_WRITE);
            break;
        }
    }
    if (data_file) {
        log("Done.");
    } else {
        log_error("Failed.");
    }

    // PRINT DATA FILE CSV HEADERS
    data_file.println("Timestamp,Temperature");
    data_file.flush();

    // SET UP LCD
    if (DISPLAY_ENABLED) {
        lcd = new LiquidCrystal(LCD_PIN_RS, LCD_PIN_EN, LCD_PIN_DB4,
            LCD_PIN_DB5, LCD_PIN_DB6, LCD_PIN_DB7);
        lcd->begin(LCD_COLUMNS, LCD_ROWS);
    }

    // Finished everything!
    now = rtc.now();
    update_formatted_timestamp();
    log("Data logger started at ", false);
    log(formatted_timestamp, false);
    log(". Software version: ", false);
    log(VERSION);
}

void loop() {
    if (timer == READING_INTERVAL) {
        timer = 0;
        take_reading();
        save_reading_to_card();
    }

    timer++;
    delay(1000);
}
<|endoftext|>