<commit_before>/*
  Q Light Controller - Fixture Definition Editor
  app.cpp

  Copyright (C) Heikki Junnila

  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at

      http://www.apache.org/licenses/LICENSE-2.0.txt

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
*/

#include <QDesktopWidget>
#include <QMdiSubWindow>
#include <QApplication>
#include <QCloseEvent>
#include <QFileDialog>
#include <QWidgetList>
#include <QMessageBox>
#include <QSettings>
#include <QMdiArea>
#include <QMenuBar>
#include <QToolBar>
#include <QToolTip>
#include <QAction>
#include <QLabel>
#include <QColor>
#include <QDebug>
#include <QMenu>
#include <QIcon>
#include <QUrl>

#include "qlcfixturedefcache.h"
#include "qlcfixturedef.h"
#include "qlcchannel.h"
#include "qlcconfig.h"
#include "qlcfile.h"
#include "avolitesd4parser.h"

#include "app.h"
#include "aboutbox.h"
#include "docbrowser.h"
#include "fixtureeditor.h"

#define SETTINGS_GEOMETRY "workspace/geometry"
#define SETTINGS_OPENDIALOGSTATE "workspace/opendialog"
#define SETTINGS_WORKINGPATH "workspace/workingpath"

App* _app;

App::App(QWidget* parent) : QMainWindow(parent)
{
    _app = this;

    m_fileMenu = NULL;
    m_helpMenu = NULL;
    m_toolBar = NULL;

    m_copyChannel = NULL;

    setWindowTitle(App::longName());
    setWindowIcon(QIcon(":/qlcplus-fixtureeditor.png"));
    setCentralWidget(new QMdiArea(this));

    QCoreApplication::setOrganizationName("qlcplus");
    QCoreApplication::setOrganizationDomain("sf.net");
    QCoreApplication::setApplicationName(FXEDNAME);

    initActions();
    //initMenuBar();
    initToolBar();

    QSettings settings;
    QVariant var = settings.value(SETTINGS_GEOMETRY);
    if (var.isValid() == true)
        restoreGeometry(var.toByteArray());

    QVariant dir = settings.value(SETTINGS_WORKINGPATH);
    if (dir.isValid() == false || QDir(dir.toString()).exists() == false)
        m_workingDirectory = QLCFixtureDefCache::userDefinitionDirectory();
    else
        m_workingDirectory = QDir(dir.toString());

    this->raise();
}

App::~App()
{
    QSettings settings;
    settings.setValue(SETTINGS_GEOMETRY, saveGeometry());

    setCopyChannel(NULL);

    // Remove the reference to the application
    _app = NULL;
}

QString App::longName()
{
    return QString("%1 - %2").arg(APPNAME).arg(FXEDNAME);
}

QString App::version()
{
    return QString("Version %1").arg(APPVERSION);
}

void App::loadFixtureDefinition(const QString& path)
{
    QLCFixtureDef* fixtureDef = NULL;

    /* Attempt to create a fixture definition from the selected file */
    QString error(tr("Unrecognized file extension: %1").arg(path));
    if (path.toLower().endsWith(KExtFixture) == true)
        fixtureDef = loadQXF(path, error);
    else if (path.toLower().endsWith(KExtAvolitesFixture) == true)
        fixtureDef = loadD4(path, error);
    else
        fixtureDef = NULL;

    if (fixtureDef != NULL)
    {
        /* Create a new sub window and put a fixture editor widget
           in that sub window with the newly-created fixture def */
        QMdiSubWindow* sub = new QMdiSubWindow(centralWidget());
        QLCFixtureEditor* editor = new QLCFixtureEditor(sub, fixtureDef, path);

        sub->setWidget(editor);
        sub->setAttribute(Qt::WA_DeleteOnClose);
        qobject_cast<QMdiArea*> (centralWidget())->addSubWindow(sub);

        editor->show();
        sub->show();
    }
    else
    {
        QMessageBox::warning(this, tr("Fixture loading failed"),
                             tr("Unable to load fixture definition: ") + error);
    }
}

QLCFixtureDef* App::loadQXF(const QString& path, QString& errorMsg) const
{
    QLCFixtureDef* fixtureDef = new QLCFixtureDef;
    Q_ASSERT(fixtureDef != NULL);

    QFile::FileError error = fixtureDef->loadXML(path);
    if (error != QFile::NoError)
    {
        delete fixtureDef;
        fixtureDef = NULL;
        errorMsg = QLCFile::errorString(error);
    }

    return fixtureDef;
}

QLCFixtureDef* App::loadD4(const QString& path, QString& errorMsg) const
{
    QLCFixtureDef* fixtureDef = NULL;

    AvolitesD4Parser parser;
    if (parser.loadXML(path) == false)
    {
        errorMsg = parser.lastError();
    }
    else
    {
        fixtureDef = new QLCFixtureDef;
        Q_ASSERT(fixtureDef != NULL);
        if (parser.fillFixtureDef(fixtureDef) == false)
        {
            errorMsg = parser.lastError();
            delete fixtureDef;
            fixtureDef = NULL;
        }
    }

    return fixtureDef;
}

void App::closeEvent(QCloseEvent* e)
{
    /* Accept the close event by default */
    e->accept();

    QListIterator <QMdiSubWindow*> it(
        qobject_cast<QMdiArea*> (centralWidget())->subWindowList());
    while (it.hasNext() == true)
    {
        QLCFixtureEditor* editor;
        QMdiSubWindow* sub;

        sub = it.next();
        Q_ASSERT(sub != NULL);

        editor = static_cast<QLCFixtureEditor*> (sub->widget());
        Q_ASSERT(editor != NULL);

        editor->show();
        editor->setFocus();

        if (editor->close() == false)
        {
            /* Ignore the close event if just one editor refuses */
            e->ignore();
            break;
        }
    }
}

/*****************************************************************************
 * Copy channel
 *****************************************************************************/

void App::setCopyChannel(QLCChannel* ch)
{
    if (m_copyChannel != NULL)
        delete m_copyChannel;
    m_copyChannel = NULL;

    if (ch != NULL)
        m_copyChannel = new QLCChannel(ch);

    emit clipboardChanged();
}

QLCChannel* App::copyChannel() const
{
    return m_copyChannel;
}

/*****************************************************************************
 * Actions, toolbar & menubar
 *****************************************************************************/

void App::initActions()
{
    /* File actions */
    m_fileNewAction = new QAction(QIcon(":/filenew.png"),
                                  tr("&New"), this);
    m_fileNewAction->setShortcut(QKeySequence(tr("CTRL+N", "File|New")));
    connect(m_fileNewAction, SIGNAL(triggered(bool)),
            this, SLOT(slotFileNew()));

    m_fileOpenAction = new QAction(QIcon(":/fileopen.png"),
                                   tr("&Open"), this);
    m_fileOpenAction->setShortcut(QKeySequence(tr("CTRL+O", "File|Open")));
    connect(m_fileOpenAction, SIGNAL(triggered(bool)),
            this, SLOT(slotFileOpen()));

    m_fileSaveAction = new QAction(QIcon(":/filesave.png"),
                                   tr("&Save"), this);
    m_fileSaveAction->setShortcut(QKeySequence(tr("CTRL+S", "File|Save")));
    connect(m_fileSaveAction, SIGNAL(triggered(bool)),
            this, SLOT(slotFileSave()));

    m_fileSaveAsAction = new QAction(QIcon(":/filesaveas.png"),
                                     tr("Save &As..."), this);
    m_fileSaveAsAction->setShortcut(QKeySequence(tr("CTRL+SHIFT+S", "File|Save As...")));
    connect(m_fileSaveAsAction, SIGNAL(triggered(bool)),
            this, SLOT(slotFileSaveAs()));

    m_fileQuitAction = new QAction(QIcon(":/exit.png"),
                                   tr("&Quit"), this);
    m_fileQuitAction->setShortcut(QKeySequence(tr("CTRL+Q", "File|Quit")));
    connect(m_fileQuitAction, SIGNAL(triggered(bool)),
            this, SLOT(slotFileQuit()));

    /* Help actions */
    m_helpIndexAction = new QAction(QIcon(":/help.png"),
                                    tr("Index"), this);
    m_helpIndexAction->setShortcut(QKeySequence(tr("SHIFT+F1", "Help|Index")));
    connect(m_helpIndexAction, SIGNAL(triggered(bool)),
            this, SLOT(slotHelpIndex()));

    m_helpAboutAction = new QAction(QIcon(":/qlcplus.png"),
                                    tr("About Fixture Definition Editor..."), this);
    connect(m_helpAboutAction, SIGNAL(triggered(bool)),
            this, SLOT(slotHelpAbout()));

    m_helpAboutQtAction = new QAction(QIcon(":/qt.png"),
                                      tr("About Qt..."), this);
    connect(m_helpAboutQtAction, SIGNAL(triggered(bool)),
            this, SLOT(slotHelpAboutQt()));
}

void App::initToolBar()
{
    m_toolBar = new QToolBar(App::longName(), this);
    m_toolBar->setIconSize(QSize(24, 24));
    addToolBar(m_toolBar);
    m_toolBar->setMovable(false);

    m_toolBar->addAction(m_fileNewAction);
    m_toolBar->addAction(m_fileOpenAction);
    m_toolBar->addAction(m_fileSaveAction);
    m_toolBar->addAction(m_fileSaveAsAction);

    m_toolBar->addSeparator();

    m_toolBar->addAction(m_helpIndexAction);
    m_toolBar->addAction(m_helpAboutAction);
}

void App::initMenuBar()
{
    /* File Menu */
    m_fileMenu = new QMenu(menuBar());
    m_fileMenu->setTitle(tr("&File"));
    m_fileMenu->addAction(m_fileNewAction);
    m_fileMenu->addAction(m_fileOpenAction);
    m_fileMenu->addAction(m_fileSaveAction);
    m_fileMenu->addAction(m_fileSaveAsAction);
    m_fileMenu->addSeparator();
    m_fileMenu->addAction(m_fileQuitAction);

    /* Help menu */
    m_helpMenu = new QMenu(menuBar());
    m_helpMenu->setTitle(tr("&Help"));
    m_helpMenu->addAction(m_helpIndexAction);
    m_helpMenu->addSeparator();
    m_helpMenu->addAction(m_helpAboutAction);
    m_helpMenu->addAction(m_helpAboutQtAction);

    menuBar()->addMenu(m_fileMenu);
    menuBar()->addMenu(m_helpMenu);
}

/*****************************************************************************
 * File action slots
 *****************************************************************************/

void App::slotFileNew()
{
    QLCFixtureEditor* editor;
    QMdiSubWindow* sub;

    sub = new QMdiSubWindow(centralWidget());
    editor = new QLCFixtureEditor(sub, new QLCFixtureDef());

    sub->setWidget(editor);
    sub->setAttribute(Qt::WA_DeleteOnClose);
    sub->setWindowIcon(QIcon(":/fixture.png"));

    qobject_cast<QMdiArea*> (centralWidget())->addSubWindow(sub);

    editor->show();
    sub->show();
}

void App::slotFileOpen()
{
    QSettings settings;

    /* Create a file open dialog */
    QFileDialog dialog(this);
    dialog.setWindowTitle(tr("Open a fixture definition"));
    dialog.setFileMode(QFileDialog::ExistingFiles);
    dialog.setAcceptMode(QFileDialog::AcceptOpen);

    QStringList filters;
    filters << KAllFilter;
    filters << KQXFFilter;
    filters << KD4Filter;
    dialog.setNameFilters(filters);

    QVariant var = settings.value(SETTINGS_OPENDIALOGSTATE);
    if (var.isValid() == true)
    {
        dialog.restoreState(var.toByteArray());
    }

    dialog.setDirectory(m_workingDirectory);

    /* Execute the dialog */
    if (dialog.exec() != QDialog::Accepted)
        return;

    /* Get a file name */
    QStringListIterator it(dialog.selectedFiles());
    while (it.hasNext() == true)
        loadFixtureDefinition(it.next());

    settings.setValue(SETTINGS_OPENDIALOGSTATE, dialog.saveState());
    m_workingDirectory = dialog.directory();
    settings.setValue(SETTINGS_WORKINGPATH, m_workingDirectory.absolutePath());
}

void App::slotFileSave()
{
    QLCFixtureEditor* editor;
    QMdiSubWindow* sub;

    sub = (qobject_cast<QMdiArea*> (centralWidget()))->activeSubWindow();
    if (sub == NULL)
        return;

    editor = static_cast<QLCFixtureEditor*> (sub->widget());
    if (editor == NULL)
        return;

    editor->save();
}

void App::slotFileSaveAs()
{
    QLCFixtureEditor* editor;
    QMdiSubWindow* sub;

    sub = (qobject_cast<QMdiArea*> (centralWidget()))->activeSubWindow();
    if (sub == NULL)
        return;

    editor = static_cast<QLCFixtureEditor*> (sub->widget());
    if (editor == NULL)
        return;

    editor->saveAs();
}

void App::slotFileQuit()
{
    close();
}

/*****************************************************************************
 * Help action slots
 *****************************************************************************/

void App::slotHelpIndex()
{
    DocBrowser::createAndShow(this);
}

void App::slotHelpAbout()
{
    AboutBox aboutbox(this);
    aboutbox.exec();
}

void App::slotHelpAboutQt()
{
    QMessageBox::aboutQt(this, App::longName());
}
<commit_msg>Uniform fixture editor background across platforms<commit_after>/*
  Q Light Controller - Fixture Definition Editor
  app.cpp

  Copyright (C) Heikki Junnila

  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at

      http://www.apache.org/licenses/LICENSE-2.0.txt

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
*/

#include <QDesktopWidget>
#include <QMdiSubWindow>
#include <QApplication>
#include <QCloseEvent>
#include <QFileDialog>
#include <QWidgetList>
#include <QMessageBox>
#include <QSettings>
#include <QMdiArea>
#include <QMenuBar>
#include <QToolBar>
#include <QToolTip>
#include <QAction>
#include <QLabel>
#include <QColor>
#include <QDebug>
#include <QMenu>
#include <QIcon>
#include <QUrl>

#include "qlcfixturedefcache.h"
#include "qlcfixturedef.h"
#include "qlcchannel.h"
#include "qlcconfig.h"
#include "qlcfile.h"
#include "avolitesd4parser.h"

#include "app.h"
#include "aboutbox.h"
#include "docbrowser.h"
#include "fixtureeditor.h"

#define SETTINGS_GEOMETRY "workspace/geometry"
#define SETTINGS_OPENDIALOGSTATE "workspace/opendialog"
#define SETTINGS_WORKINGPATH "workspace/workingpath"

App* _app;

App::App(QWidget* parent) : QMainWindow(parent)
{
    _app = this;

    m_fileMenu = NULL;
    m_helpMenu = NULL;
    m_toolBar = NULL;

    m_copyChannel = NULL;

    setWindowTitle(App::longName());
    setWindowIcon(QIcon(":/qlcplus-fixtureeditor.png"));
    QMdiArea *mdiArea = new QMdiArea(this);
    mdiArea->setBackground(QBrush(QColor(0x60, 0x60, 0x60)));
    setCentralWidget(mdiArea);

    QCoreApplication::setOrganizationName("qlcplus");
    QCoreApplication::setOrganizationDomain("sf.net");
    QCoreApplication::setApplicationName(FXEDNAME);

    initActions();
    //initMenuBar();
    initToolBar();

    QSettings settings;
    QVariant var = settings.value(SETTINGS_GEOMETRY);
    if (var.isValid() == true)
        restoreGeometry(var.toByteArray());

    QVariant dir = settings.value(SETTINGS_WORKINGPATH);
    if (dir.isValid() == false || QDir(dir.toString()).exists() == false)
        m_workingDirectory = QLCFixtureDefCache::userDefinitionDirectory();
    else
        m_workingDirectory = QDir(dir.toString());

    this->raise();
}

App::~App()
{
    QSettings settings;
    settings.setValue(SETTINGS_GEOMETRY, saveGeometry());

    setCopyChannel(NULL);

    // Remove the reference to the application
    _app = NULL;
}

QString App::longName()
{
    return QString("%1 - %2").arg(APPNAME).arg(FXEDNAME);
}

QString App::version()
{
    return QString("Version %1").arg(APPVERSION);
}

void App::loadFixtureDefinition(const QString& path)
{
    QLCFixtureDef* fixtureDef = NULL;

    /* Attempt to create a fixture definition from the selected file */
    QString error(tr("Unrecognized file extension: %1").arg(path));
    if (path.toLower().endsWith(KExtFixture) == true)
        fixtureDef = loadQXF(path, error);
    else if (path.toLower().endsWith(KExtAvolitesFixture) == true)
        fixtureDef = loadD4(path, error);
    else
        fixtureDef = NULL;

    if (fixtureDef != NULL)
    {
        /* Create a new sub window and put a fixture editor widget
           in that sub window with the newly-created fixture def */
        QMdiSubWindow* sub = new QMdiSubWindow(centralWidget());
        QLCFixtureEditor* editor = new QLCFixtureEditor(sub, fixtureDef, path);

        sub->setWidget(editor);
        sub->setAttribute(Qt::WA_DeleteOnClose);
        qobject_cast<QMdiArea*> (centralWidget())->addSubWindow(sub);

        editor->show();
        sub->show();
    }
    else
    {
        QMessageBox::warning(this, tr("Fixture loading failed"),
                             tr("Unable to load fixture definition: ") + error);
    }
}

QLCFixtureDef* App::loadQXF(const QString& path, QString& errorMsg) const
{
    QLCFixtureDef* fixtureDef = new QLCFixtureDef;
    Q_ASSERT(fixtureDef != NULL);

    QFile::FileError error = fixtureDef->loadXML(path);
    if (error != QFile::NoError)
    {
        delete fixtureDef;
        fixtureDef = NULL;
        errorMsg = QLCFile::errorString(error);
    }

    return fixtureDef;
}

QLCFixtureDef* App::loadD4(const QString& path, QString& errorMsg) const
{
    QLCFixtureDef* fixtureDef = NULL;

    AvolitesD4Parser parser;
    if (parser.loadXML(path) == false)
    {
        errorMsg = parser.lastError();
    }
    else
    {
        fixtureDef = new QLCFixtureDef;
        Q_ASSERT(fixtureDef != NULL);
        if (parser.fillFixtureDef(fixtureDef) == false)
        {
            errorMsg = parser.lastError();
            delete fixtureDef;
            fixtureDef = NULL;
        }
    }

    return fixtureDef;
}

void App::closeEvent(QCloseEvent* e)
{
    /* Accept the close event by default */
    e->accept();

    QListIterator <QMdiSubWindow*> it(
        qobject_cast<QMdiArea*> (centralWidget())->subWindowList());
    while (it.hasNext() == true)
    {
        QLCFixtureEditor* editor;
        QMdiSubWindow* sub;

        sub = it.next();
        Q_ASSERT(sub != NULL);

        editor = static_cast<QLCFixtureEditor*> (sub->widget());
        Q_ASSERT(editor != NULL);

        editor->show();
        editor->setFocus();

        if (editor->close() == false)
        {
            /* Ignore the close event if just one editor refuses */
            e->ignore();
            break;
        }
    }
}

/*****************************************************************************
 * Copy channel
 *****************************************************************************/

void App::setCopyChannel(QLCChannel* ch)
{
    if (m_copyChannel != NULL)
        delete m_copyChannel;
    m_copyChannel = NULL;

    if (ch != NULL)
        m_copyChannel = new QLCChannel(ch);

    emit clipboardChanged();
}

QLCChannel* App::copyChannel() const
{
    return m_copyChannel;
}

/*****************************************************************************
 * Actions, toolbar & menubar
 *****************************************************************************/

void App::initActions()
{
    /* File actions */
    m_fileNewAction = new QAction(QIcon(":/filenew.png"),
                                  tr("&New"), this);
    m_fileNewAction->setShortcut(QKeySequence(tr("CTRL+N", "File|New")));
    connect(m_fileNewAction, SIGNAL(triggered(bool)),
            this, SLOT(slotFileNew()));

    m_fileOpenAction = new QAction(QIcon(":/fileopen.png"),
                                   tr("&Open"), this);
    m_fileOpenAction->setShortcut(QKeySequence(tr("CTRL+O", "File|Open")));
    connect(m_fileOpenAction, SIGNAL(triggered(bool)),
            this, SLOT(slotFileOpen()));

    m_fileSaveAction = new QAction(QIcon(":/filesave.png"),
                                   tr("&Save"), this);
    m_fileSaveAction->setShortcut(QKeySequence(tr("CTRL+S", "File|Save")));
    connect(m_fileSaveAction, SIGNAL(triggered(bool)),
            this, SLOT(slotFileSave()));

    m_fileSaveAsAction = new QAction(QIcon(":/filesaveas.png"),
                                     tr("Save &As..."), this);
    m_fileSaveAsAction->setShortcut(QKeySequence(tr("CTRL+SHIFT+S", "File|Save As...")));
    connect(m_fileSaveAsAction, SIGNAL(triggered(bool)),
            this, SLOT(slotFileSaveAs()));

    m_fileQuitAction = new QAction(QIcon(":/exit.png"),
                                   tr("&Quit"), this);
    m_fileQuitAction->setShortcut(QKeySequence(tr("CTRL+Q", "File|Quit")));
    connect(m_fileQuitAction, SIGNAL(triggered(bool)),
            this, SLOT(slotFileQuit()));

    /* Help actions */
    m_helpIndexAction = new QAction(QIcon(":/help.png"),
                                    tr("Index"), this);
    m_helpIndexAction->setShortcut(QKeySequence(tr("SHIFT+F1", "Help|Index")));
    connect(m_helpIndexAction, SIGNAL(triggered(bool)),
            this, SLOT(slotHelpIndex()));

    m_helpAboutAction = new QAction(QIcon(":/qlcplus.png"),
                                    tr("About Fixture Definition Editor..."), this);
    connect(m_helpAboutAction, SIGNAL(triggered(bool)),
            this, SLOT(slotHelpAbout()));

    m_helpAboutQtAction = new QAction(QIcon(":/qt.png"),
                                      tr("About Qt..."), this);
    connect(m_helpAboutQtAction, SIGNAL(triggered(bool)),
            this, SLOT(slotHelpAboutQt()));
}

void App::initToolBar()
{
    m_toolBar = new QToolBar(App::longName(), this);
    m_toolBar->setIconSize(QSize(24, 24));
    addToolBar(m_toolBar);
    m_toolBar->setMovable(false);

    m_toolBar->addAction(m_fileNewAction);
    m_toolBar->addAction(m_fileOpenAction);
    m_toolBar->addAction(m_fileSaveAction);
    m_toolBar->addAction(m_fileSaveAsAction);

    m_toolBar->addSeparator();

    m_toolBar->addAction(m_helpIndexAction);
    m_toolBar->addAction(m_helpAboutAction);
}

void App::initMenuBar()
{
    /* File Menu */
    m_fileMenu = new QMenu(menuBar());
    m_fileMenu->setTitle(tr("&File"));
    m_fileMenu->addAction(m_fileNewAction);
    m_fileMenu->addAction(m_fileOpenAction);
    m_fileMenu->addAction(m_fileSaveAction);
    m_fileMenu->addAction(m_fileSaveAsAction);
    m_fileMenu->addSeparator();
    m_fileMenu->addAction(m_fileQuitAction);

    /* Help menu */
    m_helpMenu = new QMenu(menuBar());
    m_helpMenu->setTitle(tr("&Help"));
    m_helpMenu->addAction(m_helpIndexAction);
    m_helpMenu->addSeparator();
    m_helpMenu->addAction(m_helpAboutAction);
    m_helpMenu->addAction(m_helpAboutQtAction);

    menuBar()->addMenu(m_fileMenu);
    menuBar()->addMenu(m_helpMenu);
}

/*****************************************************************************
 * File action slots
 *****************************************************************************/

void App::slotFileNew()
{
    QLCFixtureEditor* editor;
    QMdiSubWindow* sub;

    sub = new QMdiSubWindow(centralWidget());
    editor = new QLCFixtureEditor(sub, new QLCFixtureDef());

    sub->setWidget(editor);
    sub->setAttribute(Qt::WA_DeleteOnClose);
    sub->setWindowIcon(QIcon(":/fixture.png"));

    qobject_cast<QMdiArea*> (centralWidget())->addSubWindow(sub);

    editor->show();
    sub->show();
}

void App::slotFileOpen()
{
    QSettings settings;

    /* Create a file open dialog */
    QFileDialog dialog(this);
    dialog.setWindowTitle(tr("Open a fixture definition"));
    dialog.setFileMode(QFileDialog::ExistingFiles);
    dialog.setAcceptMode(QFileDialog::AcceptOpen);

    QStringList filters;
    filters << KAllFilter;
    filters << KQXFFilter;
    filters << KD4Filter;
    dialog.setNameFilters(filters);

    QVariant var = settings.value(SETTINGS_OPENDIALOGSTATE);
    if (var.isValid() == true)
    {
        dialog.restoreState(var.toByteArray());
    }

    dialog.setDirectory(m_workingDirectory);

    /* Execute the dialog */
    if (dialog.exec() != QDialog::Accepted)
        return;

    /* Get a file name */
    QStringListIterator it(dialog.selectedFiles());
    while (it.hasNext() == true)
        loadFixtureDefinition(it.next());

    settings.setValue(SETTINGS_OPENDIALOGSTATE, dialog.saveState());
    m_workingDirectory = dialog.directory();
    settings.setValue(SETTINGS_WORKINGPATH, m_workingDirectory.absolutePath());
}

void App::slotFileSave()
{
    QLCFixtureEditor* editor;
    QMdiSubWindow* sub;

    sub = (qobject_cast<QMdiArea*> (centralWidget()))->activeSubWindow();
    if (sub == NULL)
        return;

    editor = static_cast<QLCFixtureEditor*> (sub->widget());
    if (editor == NULL)
        return;

    editor->save();
}

void App::slotFileSaveAs()
{
    QLCFixtureEditor* editor;
    QMdiSubWindow* sub;

    sub = (qobject_cast<QMdiArea*> (centralWidget()))->activeSubWindow();
    if (sub == NULL)
        return;

    editor = static_cast<QLCFixtureEditor*> (sub->widget());
    if (editor == NULL)
        return;

    editor->saveAs();
}

void App::slotFileQuit()
{
    close();
}

/*****************************************************************************
 * Help action slots
 *****************************************************************************/

void App::slotHelpIndex()
{
    DocBrowser::createAndShow(this);
}

void App::slotHelpAbout()
{
    AboutBox aboutbox(this);
    aboutbox.exec();
}

void App::slotHelpAboutQt()
{
    QMessageBox::aboutQt(this, App::longName());
}
<|endoftext|>


<commit_before>#pragma once
//=====================================================================//
/*!	@file
	@brief	R8C メイン・ヘッダー
	@author	平松邦仁 (hira@rvf-rc45.net)
*/
//=====================================================================//
#include "port.hpp"
#include "common/intr_utils.hpp"
#include "common/uart_io.hpp"
#include "common/trb_io.hpp"
#include "common/adc_io.hpp"
#include "common/flash_io.hpp"
#include "common/ds1371_io.hpp"
#include "common/lcd_io.hpp"
#include "common/monograph.hpp"

typedef device::uart_io<device::UART0, 16, 16> uart0;

typedef device::trb_io<utils::null_task> timer_b;

typedef device::adc_io adc;

typedef device::flash_io flash;

typedef graphics::monograph mono_graph;

// DS1371 I2C ポートの定義クラス
// P1_B7: SCL
// P4_B5: SDA
struct scl_sda {
	void init() const {  // オープン・ドレイン設定
		device::POD1.B7 = 1;
		device::POD4.B5 = 1;
	}
	void scl_dir(bool b) const { device::PD1.B7 = b; }  // SCL 方向 (0:in, 1:out)
	void scl_out(bool b) const { device::P1.B7 = b; }   // SCL 出力
	bool scl_inp() const { return device::P1.B7(); }    // SCL 入力
	void sda_dir(bool b) const { device::PD4.B5 = b; }  // SDA 方向 (0:in, 1:out)
	void sda_out(bool b) const { device::P4.B5 = b; }   // SDA 出力
	bool sda_inp() const { return device::P4.B5(); }    // SDA 入力
};

typedef device::ds1371_io<scl_sda> ds1371;

// LCD SCL: P4_2(1)
// LCD SDA: P4_5(12)
// LCD A0:  P3_3(11)
// LCD /CS: P3_7(2)
struct spi_base {
	void init() const {
		device::PD4.B2 = 1;
		device::PD4.B5 = 1;
	}
	void scl_out(bool b) const { device::P4.B2 = b; }
	void sda_out(bool b) const { device::P4.B5 = b; }
};

struct spi_ctrl {
	void init() const {
		device::PD3.B3 = 1;
		device::PD3.B7 = 1;
	}
	void a0_out(bool b) const { device::P3.B3 = b; }
	void cs_out(bool b) const { device::P3.B7 = b; }
};

typedef device::lcd_io<spi_base, spi_ctrl> lcd;
<commit_msg>update spi_ctrl class<commit_after>#pragma once
//=====================================================================//
/*!	@file
	@brief	R8C メイン・ヘッダー
	@author	平松邦仁 (hira@rvf-rc45.net)
*/
//=====================================================================//
#include "port.hpp"
#include "common/intr_utils.hpp"
#include "common/uart_io.hpp"
#include "common/trb_io.hpp"
#include "common/adc_io.hpp"
#include "common/flash_io.hpp"
#include "common/ds1371_io.hpp"
#include "common/lcd_io.hpp"
#include "common/monograph.hpp"

typedef device::uart_io<device::UART0, 16, 16> uart0;

typedef device::trb_io<utils::null_task> timer_b;

typedef device::adc_io adc;

typedef device::flash_io flash;

typedef graphics::monograph mono_graph;

// DS1371 I2C ポートの定義クラス
// P1_B7: SCL
// P4_B5: SDA
struct scl_sda {
	void init() const {  // オープン・ドレイン設定
		device::POD1.B7 = 1;
		device::POD4.B5 = 1;
	}
	void scl_dir(bool b) const { device::PD1.B7 = b; }  // SCL 方向 (0:in, 1:out)
	void scl_out(bool b) const { device::P1.B7 = b; }   // SCL 出力
	bool scl_inp() const { return device::P1.B7(); }    // SCL 入力
	void sda_dir(bool b) const { device::PD4.B5 = b; }  // SDA 方向 (0:in, 1:out)
	void sda_out(bool b) const { device::P4.B5 = b; }   // SDA 出力
	bool sda_inp() const { return device::P4.B5(); }    // SDA 入力
};

typedef device::ds1371_io<scl_sda> ds1371;

// LCD SCL: P4_2(1)
// LCD SDA: P4_5(12)
// LCD A0:  P3_3(11)
// LCD /CS: P3_7(2)
struct spi_base {
	void init() const {
		device::PD4.B2 = 1;
		device::PD4.B5 = 1;
	}
	void scl_out(bool b) const { device::P4.B2 = b; }
	void sda_out(bool b) const { device::P4.B5 = b; }
};

struct spi_ctrl {
	void init() const {
		device::PD3.B3 = 1;
		device::PD3.B7 = 1;
	}
	void a0_out(bool b) const { device::P3.B3 = b; }
	void cs0_out(bool b) const { device::P3.B7 = b; }
};

typedef device::lcd_io<spi_base, spi_ctrl> lcd;
<|endoftext|>


<commit_before>#ifndef FORMATS_XML_OSMXMLPARSER_HPP_INCLUDED
#define FORMATS_XML_OSMXMLPARSER_HPP_INCLUDED

#include "BoundingBox.hpp"
#include "formats/FormatTypes.hpp"

#include <boost/foreach.hpp>
#include <boost/property_tree/xml_parser.hpp>
#include <boost/property_tree/ptree.hpp>

#include <cstdint>

namespace utymap { namespace formats {

template<typename Visitor>
class OsmXmlParser
{
    using ptree = boost::property_tree::ptree;

public:
    /// Parses osm xml data from stream calling visitor.
    void parse(std::istream& istream, Visitor& visitor)
    {
        ptree pt;
        read_xml(istream, pt);

        BOOST_FOREACH(ptree::value_type const& child, pt.get_child("osm"))
        {
            if (child.first == "node")
                parseNode(visitor, child);
            else if (child.first == "way")
                parseWays(visitor, child);
            else if (child.first == "relation")
                parseRelations(visitor, child);
            else if (child.first == "bounds")
                parseBounds(visitor, child);
        }
    }

private:

    static void parseBounds(Visitor& visitor, ptree::value_type const& node)
    {
        const ptree & attributes = node.second.get_child("<xmlattr>");

        GeoCoordinate minPoint, maxPoint;
        minPoint.latitude = attributes.get_child("minlat").get_value<double>();
        minPoint.longitude = attributes.get_child("minlon").get_value<double>();
        maxPoint.latitude = attributes.get_child("maxlat").get_value<double>();
        maxPoint.longitude = attributes.get_child("maxlon").get_value<double>();

        visitor.visitBounds(BoundingBox(minPoint, maxPoint));
    }

    static void parseTag(ptree::value_type const& node, Tags& tags)
    {
        const ptree & attributes = node.second.get_child("<xmlattr>");
        tags.push_back(Tag(attributes.get_child("k").data(), attributes.get_child("v").data()));
    }

    static void parseNode(Visitor& visitor, ptree::value_type const& node)
    {
        const ptree & attributes = node.second.get_child("<xmlattr>");

        GeoCoordinate coordinate;
        uint64_t id = attributes.get_child("id").get_value<uint64_t>();
        coordinate.latitude = attributes.get_child("lat").get_value<double>();
        coordinate.longitude = attributes.get_child("lon").get_value<double>();

        Tags tags;
        tags.reserve(2);
        BOOST_FOREACH(ptree::value_type const& child, node.second)
        {
            if (child.first == "tag")
                parseTag(child, tags);
        }

        visitor.visitNode(id, coordinate, tags);
    }

    static void parseWays(Visitor& visitor, ptree::value_type const& node)
    {
        uint64_t id = node.second.get_child("<xmlattr>")
            .get_child("id")
            .get_value<uint64_t>();

        std::vector<uint64_t> nodeIds;
        Tags tags;
        nodeIds.reserve(4);
        tags.reserve(2);
        BOOST_FOREACH(ptree::value_type const& child, node.second)
        {
            if (child.first == "nd")
            {
                uint64_t refId = child.second.get_child("<xmlattr>")
                    .get_child("ref")
                    .get_value<uint64_t>();
                nodeIds.push_back(refId);
            }
            else if (child.first == "tag")
                parseTag(child, tags);
        }

        visitor.visitWay(id, nodeIds, tags);
    }

    static void parseRelations(Visitor& visitor, ptree::value_type const& node)
    {
        uint64_t id = node.second.get_child("<xmlattr>")
            .get_child("id")
            .get_value<uint64_t>();

        Tags tags;
        RelationMembers members;
        tags.reserve(2);
        members.reserve(2);
        BOOST_FOREACH(ptree::value_type const& child, node.second)
        {
            if (child.first == "member")
            {
                RelationMember member;
                const ptree& attributes = child.second.get_child("<xmlattr>");

                member.refId = attributes.get_child("ref").get_value<uint64_t>();
                member.type = getType(attributes);
                member.role = attributes.get_child("role").get_value<std::string>();
                members.push_back(member);
            }
            else if (child.first == "tag")
                parseTag(child, tags);
        }
        visitor.visitRelation(id, members, tags);
    }

    static std::string getType(const ptree& attributes)
    {
        auto type = attributes.get_child("type").get_value<std::string>();
        if (type == "node")
            return "n";
        if (type == "way")
            return "w";

        return "r";
    }
};

}}

#endif  // FORMATS_XML_OSMXMLPARSER_HPP_INCLUDED
<commit_msg>core: xml parse style cleanup<commit_after>#ifndef FORMATS_XML_OSMXMLPARSER_HPP_INCLUDED
#define FORMATS_XML_OSMXMLPARSER_HPP_INCLUDED

#include "BoundingBox.hpp"
#include "formats/FormatTypes.hpp"

#include <boost/property_tree/xml_parser.hpp>
#include <boost/property_tree/ptree.hpp>

#include <cstdint>

namespace utymap { namespace formats {

template<typename Visitor>
class OsmXmlParser
{
    using ptree = boost::property_tree::ptree;

public:
    /// Parses osm xml data from stream calling visitor.
    void parse(std::istream& istream, Visitor& visitor)
    {
        ptree pt;
        read_xml(istream, pt);

        for (const ptree::value_type& child : pt.get_child("osm")) {
            if (child.first == "node")
                parseNode(visitor, child);
            else if (child.first == "way")
                parseWays(visitor, child);
            else if (child.first == "relation")
                parseRelations(visitor, child);
            else if (child.first == "bounds")
                parseBounds(visitor, child);
        }
    }

private:

    static void parseBounds(Visitor& visitor, ptree::value_type const& node)
    {
        const ptree & attributes = node.second.get_child("<xmlattr>");

        GeoCoordinate minPoint, maxPoint;
        minPoint.latitude = attributes.get_child("minlat").get_value<double>();
        minPoint.longitude = attributes.get_child("minlon").get_value<double>();
        maxPoint.latitude = attributes.get_child("maxlat").get_value<double>();
        maxPoint.longitude = attributes.get_child("maxlon").get_value<double>();

        visitor.visitBounds(BoundingBox(minPoint, maxPoint));
    }

    static void parseTag(ptree::value_type const& node, Tags& tags)
    {
        const ptree & attributes = node.second.get_child("<xmlattr>");
        tags.push_back(Tag(attributes.get_child("k").data(), attributes.get_child("v").data()));
    }

    static void parseNode(Visitor& visitor, ptree::value_type const& node)
    {
        const ptree & attributes = node.second.get_child("<xmlattr>");

        GeoCoordinate coordinate;
        uint64_t id = attributes.get_child("id").get_value<uint64_t>();
        coordinate.latitude = attributes.get_child("lat").get_value<double>();
        coordinate.longitude = attributes.get_child("lon").get_value<double>();

        Tags tags;
        tags.reserve(2);
        for (const ptree::value_type& child : node.second) {
            if (child.first == "tag")
                parseTag(child, tags);
        }

        visitor.visitNode(id, coordinate, tags);
    }

    static void parseWays(Visitor& visitor, ptree::value_type const& node)
    {
        uint64_t id = node.second.get_child("<xmlattr>")
            .get_child("id")
            .get_value<uint64_t>();

        std::vector<uint64_t> nodeIds;
        Tags tags;
        nodeIds.reserve(4);
        tags.reserve(2);
        for (const ptree::value_type& child : node.second) {
            if (child.first == "nd") {
                uint64_t refId = child.second.get_child("<xmlattr>")
                    .get_child("ref")
                    .get_value<uint64_t>();
                nodeIds.push_back(refId);
            }
            else if (child.first == "tag")
                parseTag(child, tags);
        }

        visitor.visitWay(id, nodeIds, tags);
    }

    static void parseRelations(Visitor& visitor, ptree::value_type const& node)
    {
        uint64_t id = node.second.get_child("<xmlattr>")
            .get_child("id")
            .get_value<uint64_t>();

        Tags tags;
        RelationMembers members;
        tags.reserve(2);
        members.reserve(2);
        for(const ptree::value_type& child : node.second) {
            if (child.first == "member") {
                RelationMember member;
                const ptree& attributes = child.second.get_child("<xmlattr>");

                member.refId = attributes.get_child("ref").get_value<uint64_t>();
                member.type = getType(attributes);
                member.role = attributes.get_child("role").get_value<std::string>();
                members.push_back(member);
            }
            else if (child.first == "tag")
                parseTag(child, tags);
        }
        visitor.visitRelation(id, members, tags);
    }

    static std::string getType(const ptree& attributes)
    {
        auto type = attributes.get_child("type").get_value<std::string>();
        if (type == "node")
            return "n";
        if (type == "way")
            return "w";

        return "r";
    }
};

}}

#endif  // FORMATS_XML_OSMXMLPARSER_HPP_INCLUDED
<|endoftext|>


<commit_before>/*
 *
 * Copyright 2019 gRPC authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */
#include <grpc/support/port_platform.h>

#include "src/core/lib/iomgr/port.h"
#if GRPC_ARES == 1 && defined(GRPC_UV)

#include <ares.h>
#include <uv.h>

#include "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.h"

#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/string_util.h>
#include <grpc/support/time.h>
#include "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h"
#include "src/core/lib/gpr/string.h"
#include "src/core/lib/iomgr/work_serializer.h"

namespace grpc_core {

void ares_uv_poll_cb(uv_poll_t* handle, int status, int events);

void ares_uv_poll_close_cb(uv_handle_t* handle) { delete handle; }

class GrpcPolledFdLibuv : public GrpcPolledFd {
 public:
  GrpcPolledFdLibuv(ares_socket_t as,
                    std::shared_ptr<WorkSerializer> work_serializer)
      : as_(as), work_serializer_(std::move(work_serializer)) {
    gpr_asprintf(&name_, "c-ares socket: %" PRIdPTR, (intptr_t)as);
    handle_ = new uv_poll_t();
    uv_poll_init_socket(uv_default_loop(), handle_, as);
    handle_->data = this;
  }

  ~GrpcPolledFdLibuv() { gpr_free(name_); }

  void RegisterForOnReadableLocked(grpc_closure* read_closure) override {
    GPR_ASSERT(read_closure_ == nullptr);
    GPR_ASSERT((poll_events_ & UV_READABLE) == 0);
    read_closure_ = read_closure;
    poll_events_ |= UV_READABLE;
    uv_poll_start(handle_, poll_events_, ares_uv_poll_cb);
  }

  void RegisterForOnWriteableLocked(grpc_closure* write_closure) override {
    GPR_ASSERT(write_closure_ == nullptr);
    GPR_ASSERT((poll_events_ & UV_WRITABLE) == 0);
    write_closure_ = write_closure;
    poll_events_ |= UV_WRITABLE;
    uv_poll_start(handle_, poll_events_, ares_uv_poll_cb);
  }

  bool IsFdStillReadableLocked() override {
    /* uv_poll_t is based on poll, which is level triggered. So, if cares
     * leaves some data unread, the event will trigger again. */
    return false;
  }

  void ShutdownInternalLocked(grpc_error* /*error*/) {
    uv_poll_stop(handle_);
    uv_close(reinterpret_cast<uv_handle_t*>(handle_), ares_uv_poll_close_cb);
    if (read_closure_ != nullptr) {
      grpc_core::ExecCtx::Run(DEBUG_LOCATION, read_closure_,
                              GRPC_ERROR_CANCELLED);
    }
    if (write_closure_ != nullptr) {
      grpc_core::ExecCtx::Run(DEBUG_LOCATION, write_closure_,
                              GRPC_ERROR_CANCELLED);
    }
  }

  void ShutdownLocked(grpc_error* error) override {
    if (grpc_core::ExecCtx::Get() == nullptr) {
      grpc_core::ExecCtx exec_ctx;
      ShutdownInternalLocked(error);
    } else {
      ShutdownInternalLocked(error);
    }
  }

  ares_socket_t GetWrappedAresSocketLocked() override { return as_; }

  const char* GetName() override { return name_; }

  char* name_;
  ares_socket_t as_;
  uv_poll_t* handle_;
  grpc_closure* read_closure_ = nullptr;
  grpc_closure* write_closure_ = nullptr;
  int poll_events_ = 0;
  std::shared_ptr<WorkSerializer> work_serializer_;
};

struct AresUvPollCbArg {
  AresUvPollCbArg(uv_poll_t* handle, int status, int events)
      : handle(handle), status(status), events(events) {}

  uv_poll_t* handle;
  int status;
  int events;
};

static void ares_uv_poll_cb_locked(AresUvPollCbArg* arg) {
  std::unique_ptr<AresUvPollCbArg> arg_struct(arg);
  uv_poll_t* handle = arg_struct->handle;
  int status = arg_struct->status;
  int events = arg_struct->events;
  GrpcPolledFdLibuv* polled_fd =
      reinterpret_cast<GrpcPolledFdLibuv*>(handle->data);
  grpc_error* error = GRPC_ERROR_NONE;
  if (status < 0) {
    error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("cares polling error");
    error =
        grpc_error_set_str(error, GRPC_ERROR_STR_OS_ERROR,
                           grpc_slice_from_static_string(uv_strerror(status)));
  }
  if (events & UV_READABLE) {
    GPR_ASSERT(polled_fd->read_closure_ != nullptr);
    grpc_core::ExecCtx::Run(DEBUG_LOCATION, polled_fd->read_closure_, error);
    polled_fd->read_closure_ = nullptr;
    polled_fd->poll_events_ &= ~UV_READABLE;
  }
  if (events & UV_WRITABLE) {
    GPR_ASSERT(polled_fd->write_closure_ != nullptr);
    grpc_core::ExecCtx::Run(DEBUG_LOCATION, polled_fd->write_closure_, error);
    polled_fd->write_closure_ = nullptr;
    polled_fd->poll_events_ &= ~UV_WRITABLE;
  }
  uv_poll_start(handle, polled_fd->poll_events_, ares_uv_poll_cb);
}

void ares_uv_poll_cb(uv_poll_t* handle, int status, int events) {
  grpc_core::ExecCtx exec_ctx;
  GrpcPolledFdLibuv* polled_fd =
      reinterpret_cast<GrpcPolledFdLibuv*>(handle->data);
  AresUvPollCbArg* arg = new AresUvPollCbArg(handle, status, events);
  polled_fd->work_serializer_->Run([arg]() { ares_uv_poll_cb_locked(arg); },
                                   DEBUG_LOCATION);
}

class GrpcPolledFdFactoryLibuv : public GrpcPolledFdFactory {
 public:
  GrpcPolledFd* NewGrpcPolledFdLocked(
      ares_socket_t as, grpc_pollset_set* driver_pollset_set,
      std::shared_ptr<WorkSerializer> work_serializer) override {
    return new GrpcPolledFdLibuv(as, std::move(work_serializer));
  }

  void ConfigureAresChannelLocked(ares_channel channel) override {}
};

std::unique_ptr<GrpcPolledFdFactory> NewGrpcPolledFdFactory(
    std::shared_ptr<WorkSerializer> /*work_serializer*/) {
  return absl::make_unique<GrpcPolledFdFactoryLibuv>();
}

}  // namespace grpc_core

#endif /* GRPC_ARES == 1 && defined(GRPC_UV) */
<commit_msg>Remove unused parameter comment<commit_after>/*
 *
 * Copyright 2019 gRPC authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */
#include <grpc/support/port_platform.h>

#include "src/core/lib/iomgr/port.h"
#if GRPC_ARES == 1 && defined(GRPC_UV)

#include <ares.h>
#include <uv.h>

#include "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.h"

#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/string_util.h>
#include <grpc/support/time.h>
#include "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h"
#include "src/core/lib/gpr/string.h"
#include "src/core/lib/iomgr/work_serializer.h"

namespace grpc_core {

void ares_uv_poll_cb(uv_poll_t* handle, int status, int events);

void ares_uv_poll_close_cb(uv_handle_t* handle) { delete handle; }

class GrpcPolledFdLibuv : public GrpcPolledFd {
 public:
  GrpcPolledFdLibuv(ares_socket_t as,
                    std::shared_ptr<WorkSerializer> work_serializer)
      : as_(as), work_serializer_(std::move(work_serializer)) {
    gpr_asprintf(&name_, "c-ares socket: %" PRIdPTR, (intptr_t)as);
    handle_ = new uv_poll_t();
    uv_poll_init_socket(uv_default_loop(), handle_, as);
    handle_->data = this;
  }

  ~GrpcPolledFdLibuv() { gpr_free(name_); }

  void RegisterForOnReadableLocked(grpc_closure* read_closure) override {
    GPR_ASSERT(read_closure_ == nullptr);
    GPR_ASSERT((poll_events_ & UV_READABLE) == 0);
    read_closure_ = read_closure;
    poll_events_ |= UV_READABLE;
    uv_poll_start(handle_, poll_events_, ares_uv_poll_cb);
  }

  void RegisterForOnWriteableLocked(grpc_closure* write_closure) override {
    GPR_ASSERT(write_closure_ == nullptr);
    GPR_ASSERT((poll_events_ & UV_WRITABLE) == 0);
    write_closure_ = write_closure;
    poll_events_ |= UV_WRITABLE;
    uv_poll_start(handle_, poll_events_, ares_uv_poll_cb);
  }

  bool IsFdStillReadableLocked() override {
    /* uv_poll_t is based on poll, which is level triggered. So, if cares
     * leaves some data unread, the event will trigger again. */
    return false;
  }

  void ShutdownInternalLocked(grpc_error* error) {
    uv_poll_stop(handle_);
    uv_close(reinterpret_cast<uv_handle_t*>(handle_), ares_uv_poll_close_cb);
    if (read_closure_ != nullptr) {
      grpc_core::ExecCtx::Run(DEBUG_LOCATION, read_closure_,
                              GRPC_ERROR_CANCELLED);
    }
    if (write_closure_ != nullptr) {
      grpc_core::ExecCtx::Run(DEBUG_LOCATION, write_closure_,
                              GRPC_ERROR_CANCELLED);
    }
  }

  void ShutdownLocked(grpc_error* error) override {
    if (grpc_core::ExecCtx::Get() == nullptr) {
      grpc_core::ExecCtx exec_ctx;
      ShutdownInternalLocked(error);
    } else {
      ShutdownInternalLocked(error);
    }
  }

  ares_socket_t GetWrappedAresSocketLocked() override { return as_; }

  const char* GetName() override { return name_; }

  char* name_;
  ares_socket_t as_;
  uv_poll_t* handle_;
  grpc_closure* read_closure_ = nullptr;
  grpc_closure* write_closure_ = nullptr;
  int poll_events_ = 0;
  std::shared_ptr<WorkSerializer> work_serializer_;
};

struct AresUvPollCbArg {
  AresUvPollCbArg(uv_poll_t* handle, int status, int events)
      : handle(handle), status(status), events(events) {}

  uv_poll_t* handle;
  int status;
  int events;
};

static void ares_uv_poll_cb_locked(AresUvPollCbArg* arg) {
  std::unique_ptr<AresUvPollCbArg> arg_struct(arg);
  uv_poll_t* handle = arg_struct->handle;
  int status = arg_struct->status;
  int events = arg_struct->events;
  GrpcPolledFdLibuv* polled_fd =
      reinterpret_cast<GrpcPolledFdLibuv*>(handle->data);
  grpc_error* error = GRPC_ERROR_NONE;
  if (status < 0) {
    error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("cares polling error");
    error =
        grpc_error_set_str(error, GRPC_ERROR_STR_OS_ERROR,
                           grpc_slice_from_static_string(uv_strerror(status)));
  }
  if (events & UV_READABLE) {
    GPR_ASSERT(polled_fd->read_closure_ != nullptr);
    grpc_core::ExecCtx::Run(DEBUG_LOCATION, polled_fd->read_closure_, error);
    polled_fd->read_closure_ = nullptr;
    polled_fd->poll_events_ &= ~UV_READABLE;
  }
  if (events & UV_WRITABLE) {
    GPR_ASSERT(polled_fd->write_closure_ != nullptr);
    grpc_core::ExecCtx::Run(DEBUG_LOCATION, polled_fd->write_closure_, error);
    polled_fd->write_closure_ = nullptr;
    polled_fd->poll_events_ &= ~UV_WRITABLE;
  }
  uv_poll_start(handle, polled_fd->poll_events_, ares_uv_poll_cb);
}

void ares_uv_poll_cb(uv_poll_t* handle, int status, int events) {
  grpc_core::ExecCtx exec_ctx;
  GrpcPolledFdLibuv* polled_fd =
      reinterpret_cast<GrpcPolledFdLibuv*>(handle->data);
  AresUvPollCbArg* arg = new AresUvPollCbArg(handle, status, events);
  polled_fd->work_serializer_->Run([arg]() { ares_uv_poll_cb_locked(arg); },
                                   DEBUG_LOCATION);
}

class GrpcPolledFdFactoryLibuv : public GrpcPolledFdFactory {
 public:
  GrpcPolledFd* NewGrpcPolledFdLocked(
      ares_socket_t as, grpc_pollset_set* driver_pollset_set,
      std::shared_ptr<WorkSerializer> work_serializer) override {
    return new GrpcPolledFdLibuv(as, std::move(work_serializer));
  }

  void ConfigureAresChannelLocked(ares_channel channel) override {}
};

std::unique_ptr<GrpcPolledFdFactory> NewGrpcPolledFdFactory(
    std::shared_ptr<WorkSerializer> work_serializer) {
  return absl::make_unique<GrpcPolledFdFactoryLibuv>();
}

}  // namespace grpc_core

#endif /* GRPC_ARES == 1 && defined(GRPC_UV) */
<|endoftext|>


<commit_before>//===-- X86MCInstLower.cpp - Convert X86 MachineInstr to an MCInst --------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains code to lower X86 MachineInstrs to their corresponding
// MCInst records.
//
//===----------------------------------------------------------------------===//

#include "X86ATTAsmPrinter.h"
#include "X86MCAsmInfo.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCInst.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/Support/FormattedStream.h"
#include "llvm/Support/Mangler.h"
#include "llvm/ADT/SmallString.h"
using namespace llvm;

MCSymbol *X86ATTAsmPrinter::GetPICBaseSymbol() {
  // FIXME: the actual label generated doesn't matter here!  Just mangle in
  // something unique (the function number) with Private prefix.
  SmallString<60> Name;

  if (Subtarget->isTargetDarwin()) {
    raw_svector_ostream(Name) << 'L' << getFunctionNumber() << "$pb";
  } else {
    assert(Subtarget->isTargetELF() && "Don't know how to print PIC label!");
    raw_svector_ostream(Name) << ".Lllvm$" << getFunctionNumber()<<".$piclabel";
  }
  return OutContext.GetOrCreateSymbol(Name.str());
}

static void lower_subreg32(MCInst *MI, unsigned OpNo) {
  // Convert registers in the addr mode according to subreg32.
  unsigned Reg = MI->getOperand(OpNo).getReg();
  if (Reg != 0)
    MI->getOperand(OpNo).setReg(getX86SubSuperRegister(Reg, MVT::i32));
}

static void lower_lea64_32mem(MCInst *MI, unsigned OpNo) {
  // Convert registers in the addr mode according to subreg64.
  for (unsigned i = 0; i != 4; ++i) {
    if (!MI->getOperand(i).isReg()) continue;

    unsigned Reg = MI->getOperand(i).getReg();
    if (Reg == 0) continue;

    MI->getOperand(i).setReg(getX86SubSuperRegister(Reg, MVT::i64));
  }
}

/// LowerGlobalAddressOperand - Lower an MO_GlobalAddress operand to an
/// MCOperand.
MCSymbol *X86ATTAsmPrinter::GetGlobalAddressSymbol(const MachineOperand &MO) {
  const GlobalValue *GV = MO.getGlobal();

  const char *Suffix = "";
  if (MO.getTargetFlags() == X86II::MO_DARWIN_STUB)
    Suffix = "$stub";
  else if (MO.getTargetFlags() == X86II::MO_DARWIN_NONLAZY ||
           MO.getTargetFlags() == X86II::MO_DARWIN_NONLAZY_PIC_BASE ||
           MO.getTargetFlags() == X86II::MO_DARWIN_HIDDEN_NONLAZY_PIC_BASE)
    Suffix = "$non_lazy_ptr";

  std::string Name = Mang->getMangledName(GV, Suffix, Suffix[0] != '\0');
  if (Subtarget->isTargetCygMing())
    DecorateCygMingName(Name, GV);

  switch (MO.getTargetFlags()) {
  default: llvm_unreachable("Unknown target flag on GV operand");
  case X86II::MO_NO_FLAG:                // No flag.
  case X86II::MO_GOT_ABSOLUTE_ADDRESS:   // Doesn't modify symbol name.
  case X86II::MO_PIC_BASE_OFFSET:        // Doesn't modify symbol name.
    break;
  case X86II::MO_DLLIMPORT:
    // Handle dllimport linkage.
    Name = "__imp_" + Name;
    break;
  case X86II::MO_DARWIN_NONLAZY:
  case X86II::MO_DARWIN_NONLAZY_PIC_BASE:
    GVStubs[Name] = Mang->getMangledName(GV);
    break;
  case X86II::MO_DARWIN_HIDDEN_NONLAZY_PIC_BASE:
    HiddenGVStubs[Name] = Mang->getMangledName(GV);
    break;
  case X86II::MO_DARWIN_STUB:
    FnStubs[Name] = Mang->getMangledName(GV);
    break;
  // FIXME: These probably should be a modifier on the symbol or something??
  case X86II::MO_TLSGD:     Name += "@TLSGD";     break;
  case X86II::MO_GOTTPOFF:  Name += "@GOTTPOFF";  break;
  case X86II::MO_INDNTPOFF: Name += "@INDNTPOFF"; break;
  case X86II::MO_TPOFF:     Name += "@TPOFF";     break;
  case X86II::MO_NTPOFF:    Name += "@NTPOFF";    break;
  case X86II::MO_GOTPCREL:  Name += "@GOTPCREL";  break;
  case X86II::MO_GOT:       Name += "@GOT";       break;
  case X86II::MO_GOTOFF:    Name += "@GOTOFF";    break;
  case X86II::MO_PLT:       Name += "@PLT";       break;
  }

  return OutContext.GetOrCreateSymbol(Name);
}

MCSymbol *X86ATTAsmPrinter::GetExternalSymbolSymbol(const MachineOperand &MO) {
  std::string Name = Mang->makeNameProper(MO.getSymbolName());
  if (MO.getTargetFlags() == X86II::MO_DARWIN_STUB) {
    FnStubs[Name+"$stub"] = Name;
    Name += "$stub";
  }

  return OutContext.GetOrCreateSymbol(Name);
}

MCSymbol *X86ATTAsmPrinter::GetJumpTableSymbol(const MachineOperand &MO) {
  SmallString<256> Name;
  raw_svector_ostream(Name) << MAI->getPrivateGlobalPrefix() << "JTI"
    << getFunctionNumber() << '_' << MO.getIndex();

  switch (MO.getTargetFlags()) {
  default:
    llvm_unreachable("Unknown target flag on GV operand");
  case X86II::MO_NO_FLAG:    // No flag.
  case X86II::MO_PIC_BASE_OFFSET:
  case X86II::MO_DARWIN_NONLAZY_PIC_BASE:
  case X86II::MO_DARWIN_HIDDEN_NONLAZY_PIC_BASE:
    break;
  }

  // Create a symbol for the name.
  return OutContext.GetOrCreateSymbol(Name.str());
}

MCSymbol *X86ATTAsmPrinter::
GetConstantPoolIndexSymbol(const MachineOperand &MO) {
  SmallString<256> Name;
  raw_svector_ostream(Name) << MAI->getPrivateGlobalPrefix() << "CPI"
  << getFunctionNumber() << '_' << MO.getIndex();

  switch (MO.getTargetFlags()) {
  default:
    llvm_unreachable("Unknown target flag on GV operand");
  case X86II::MO_NO_FLAG:    // No flag.
  case X86II::MO_PIC_BASE_OFFSET:
  case X86II::MO_DARWIN_NONLAZY_PIC_BASE:
  case X86II::MO_DARWIN_HIDDEN_NONLAZY_PIC_BASE:
    break;
  }

  // Create a symbol for the name.
  return OutContext.GetOrCreateSymbol(Name.str());
}

MCOperand X86ATTAsmPrinter::LowerSymbolOperand(const MachineOperand &MO,
                                               MCSymbol *Sym) {
  // FIXME: We would like an efficient form for this, so we don't have to do a
  // lot of extra uniquing.
  const MCExpr *Expr = MCSymbolRefExpr::Create(Sym, OutContext);

  switch (MO.getTargetFlags()) {
  default: llvm_unreachable("Unknown target flag on GV operand");
  case X86II::MO_NO_FLAG:    // No flag.

  // These affect the name of the symbol, not any suffix.
  case X86II::MO_DARWIN_NONLAZY:
  case X86II::MO_DLLIMPORT:
  case X86II::MO_DARWIN_STUB:
  case X86II::MO_TLSGD:
  case X86II::MO_GOTTPOFF:
  case X86II::MO_INDNTPOFF:
  case X86II::MO_TPOFF:
  case X86II::MO_NTPOFF:
  case X86II::MO_GOTPCREL:
  case X86II::MO_GOT:
  case X86II::MO_GOTOFF:
  case X86II::MO_PLT:
    break;
  case X86II::MO_PIC_BASE_OFFSET:
  case X86II::MO_DARWIN_NONLAZY_PIC_BASE:
  case X86II::MO_DARWIN_HIDDEN_NONLAZY_PIC_BASE:
    // Subtract the pic base.
    Expr = MCBinaryExpr::CreateSub(Expr,
                                   MCSymbolRefExpr::Create(GetPICBaseSymbol(),
                                                           OutContext),
                                   OutContext);
    break;
  case X86II::MO_GOT_ABSOLUTE_ADDRESS: {
    // For this, we want to print something like:
    //   MYSYMBOL + (. - PICBASE)
    // However, we can't generate a ".", so just emit a new label here and refer
    // to it.  We know that this operand flag occurs at most once per function.
    SmallString<64> Name;
    raw_svector_ostream(Name) << MAI->getPrivateGlobalPrefix() << "picbaseref"
      << getFunctionNumber();
    MCSymbol *DotSym = OutContext.GetOrCreateSymbol(Name.str());
    OutStreamer.EmitLabel(DotSym);

    const MCExpr *DotExpr = MCSymbolRefExpr::Create(DotSym, OutContext);
    const MCExpr *PICBase = MCSymbolRefExpr::Create(GetPICBaseSymbol(),
                                                    OutContext);
    DotExpr = MCBinaryExpr::CreateSub(DotExpr, PICBase, OutContext);
    Expr = MCBinaryExpr::CreateAdd(Expr, DotExpr, OutContext);
    break;
  }
  }

  if (!MO.isJTI() && MO.getOffset())
    Expr = MCBinaryExpr::CreateAdd(Expr, MCConstantExpr::Create(MO.getOffset(),
                                                                OutContext),
                                   OutContext);
  return MCOperand::CreateExpr(Expr);
}

void X86ATTAsmPrinter::
printInstructionThroughMCStreamer(const MachineInstr *MI) {

  MCInst TmpInst;

  switch (MI->getOpcode()) {
  case TargetInstrInfo::DBG_LABEL:
  case TargetInstrInfo::EH_LABEL:
  case TargetInstrInfo::GC_LABEL:
    printLabel(MI);
    return;
  case TargetInstrInfo::INLINEASM:
    O << '\t';
    printInlineAsm(MI);
    return;
  case TargetInstrInfo::IMPLICIT_DEF:
    printImplicitDef(MI);
    return;
  case X86::MOVPC32r: {
    // This is a pseudo op for a two instruction sequence with a label, which
    // looks like:
    //     call "L1$pb"
    // "L1$pb":
    //     popl %esi

    // Emit the call.
    MCSymbol *PICBase = GetPICBaseSymbol();
    TmpInst.setOpcode(X86::CALLpcrel32);
    // FIXME: We would like an efficient form for this, so we don't have to do a
    // lot of extra uniquing.
    TmpInst.addOperand(MCOperand::CreateExpr(MCSymbolRefExpr::Create(PICBase,
                                                                 OutContext)));
    printInstruction(&TmpInst);

    // Emit the label.
    OutStreamer.EmitLabel(PICBase);

    // popl $reg
    TmpInst.setOpcode(X86::POP32r);
    TmpInst.getOperand(0) = MCOperand::CreateReg(MI->getOperand(0).getReg());
    printInstruction(&TmpInst);
    return;
    }
  }

  TmpInst.setOpcode(MI->getOpcode());

  for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
    const MachineOperand &MO = MI->getOperand(i);

    MCOperand MCOp;
    switch (MO.getType()) {
    default:
      O.flush();
      errs() << "Cannot lower operand #" << i << " of :" << *MI;
      llvm_unreachable("Unimp");
    case MachineOperand::MO_Register:
      MCOp = MCOperand::CreateReg(MO.getReg());
      break;
    case MachineOperand::MO_Immediate:
      MCOp = MCOperand::CreateImm(MO.getImm());
      break;
    case MachineOperand::MO_MachineBasicBlock:
      MCOp = MCOperand::CreateMBBLabel(getFunctionNumber(),
                                       MO.getMBB()->getNumber());
      break;
    case MachineOperand::MO_GlobalAddress:
      MCOp = LowerSymbolOperand(MO, GetGlobalAddressSymbol(MO));
      break;
    case MachineOperand::MO_ExternalSymbol:
      MCOp = LowerSymbolOperand(MO, GetExternalSymbolSymbol(MO));
      break;
    case MachineOperand::MO_JumpTableIndex:
      MCOp = LowerSymbolOperand(MO, GetJumpTableSymbol(MO));
      break;
    case MachineOperand::MO_ConstantPoolIndex:
      MCOp = LowerSymbolOperand(MO, GetConstantPoolIndexSymbol(MO));
      break;
    }

    TmpInst.addOperand(MCOp);
  }

  switch (TmpInst.getOpcode()) {
  case X86::LEA64_32r:
    // Handle the 'subreg rewriting' for the lea64_32mem operand.
    lower_lea64_32mem(&TmpInst, 1);
    break;
  case X86::MOV16r0:
    TmpInst.setOpcode(X86::MOV32r0);
    lower_subreg32(&TmpInst, 0);
    break;
  case X86::MOVZX16rr8:
    TmpInst.setOpcode(X86::MOVZX32rr8);
    lower_subreg32(&TmpInst, 0);
    break;
  case X86::MOVZX16rm8:
    TmpInst.setOpcode(X86::MOVZX32rm8);
    lower_subreg32(&TmpInst, 0);
    break;
  }

  printInstruction(&TmpInst);
}
<commit_msg>add a bunch more evil lowering code to work around various :subreg32 modifiers in the .td files.  This gets us down to 18 failures in codegen/x86 with the new asmprinter.<commit_after>//===-- X86MCInstLower.cpp - Convert X86 MachineInstr to an MCInst --------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains code to lower X86 MachineInstrs to their corresponding
// MCInst records.
//
//===----------------------------------------------------------------------===//

#include "X86ATTAsmPrinter.h"
#include "X86MCAsmInfo.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCInst.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/Support/FormattedStream.h"
#include "llvm/Support/Mangler.h"
#include "llvm/ADT/SmallString.h"
using namespace llvm;

MCSymbol *X86ATTAsmPrinter::GetPICBaseSymbol() {
  // FIXME: the actual label generated doesn't matter here!  Just mangle in
  // something unique (the function number) with Private prefix.
  SmallString<60> Name;

  if (Subtarget->isTargetDarwin()) {
    raw_svector_ostream(Name) << 'L' << getFunctionNumber() << "$pb";
  } else {
    assert(Subtarget->isTargetELF() && "Don't know how to print PIC label!");
    raw_svector_ostream(Name) << ".Lllvm$" << getFunctionNumber()<<".$piclabel";
  }
  return OutContext.GetOrCreateSymbol(Name.str());
}

static void lower_subreg32(MCInst *MI, unsigned OpNo) {
  // Convert registers in the addr mode according to subreg32.
  unsigned Reg = MI->getOperand(OpNo).getReg();
  if (Reg != 0)
    MI->getOperand(OpNo).setReg(getX86SubSuperRegister(Reg, MVT::i32));
}

static void lower_lea64_32mem(MCInst *MI, unsigned OpNo) {
  // Convert registers in the addr mode according to subreg64.
  for (unsigned i = 0; i != 4; ++i) {
    if (!MI->getOperand(OpNo+i).isReg()) continue;

    unsigned Reg = MI->getOperand(OpNo+i).getReg();
    if (Reg == 0) continue;

    MI->getOperand(OpNo+i).setReg(getX86SubSuperRegister(Reg, MVT::i64));
  }
}

/// LowerGlobalAddressOperand - Lower an MO_GlobalAddress operand to an
/// MCOperand.
MCSymbol *X86ATTAsmPrinter::GetGlobalAddressSymbol(const MachineOperand &MO) {
  const GlobalValue *GV = MO.getGlobal();

  const char *Suffix = "";
  if (MO.getTargetFlags() == X86II::MO_DARWIN_STUB)
    Suffix = "$stub";
  else if (MO.getTargetFlags() == X86II::MO_DARWIN_NONLAZY ||
           MO.getTargetFlags() == X86II::MO_DARWIN_NONLAZY_PIC_BASE ||
           MO.getTargetFlags() == X86II::MO_DARWIN_HIDDEN_NONLAZY_PIC_BASE)
    Suffix = "$non_lazy_ptr";

  std::string Name = Mang->getMangledName(GV, Suffix, Suffix[0] != '\0');
  if (Subtarget->isTargetCygMing())
    DecorateCygMingName(Name, GV);

  switch (MO.getTargetFlags()) {
  default: llvm_unreachable("Unknown target flag on GV operand");
  case X86II::MO_NO_FLAG:                // No flag.
  case X86II::MO_GOT_ABSOLUTE_ADDRESS:   // Doesn't modify symbol name.
  case X86II::MO_PIC_BASE_OFFSET:        // Doesn't modify symbol name.
    break;
  case X86II::MO_DLLIMPORT:
    // Handle dllimport linkage.
    Name = "__imp_" + Name;
    break;
  case X86II::MO_DARWIN_NONLAZY:
  case X86II::MO_DARWIN_NONLAZY_PIC_BASE:
    GVStubs[Name] = Mang->getMangledName(GV);
    break;
  case X86II::MO_DARWIN_HIDDEN_NONLAZY_PIC_BASE:
    HiddenGVStubs[Name] = Mang->getMangledName(GV);
    break;
  case X86II::MO_DARWIN_STUB:
    FnStubs[Name] = Mang->getMangledName(GV);
    break;
  // FIXME: These probably should be a modifier on the symbol or something??
  case X86II::MO_TLSGD:     Name += "@TLSGD";     break;
  case X86II::MO_GOTTPOFF:  Name += "@GOTTPOFF";  break;
  case X86II::MO_INDNTPOFF: Name += "@INDNTPOFF"; break;
  case X86II::MO_TPOFF:     Name += "@TPOFF";     break;
  case X86II::MO_NTPOFF:    Name += "@NTPOFF";    break;
  case X86II::MO_GOTPCREL:  Name += "@GOTPCREL";  break;
  case X86II::MO_GOT:       Name += "@GOT";       break;
  case X86II::MO_GOTOFF:    Name += "@GOTOFF";    break;
  case X86II::MO_PLT:       Name += "@PLT";       break;
  }

  return OutContext.GetOrCreateSymbol(Name);
}

MCSymbol *X86ATTAsmPrinter::GetExternalSymbolSymbol(const MachineOperand &MO) {
  std::string Name = Mang->makeNameProper(MO.getSymbolName());
  if (MO.getTargetFlags() == X86II::MO_DARWIN_STUB) {
    FnStubs[Name+"$stub"] = Name;
    Name += "$stub";
  }

  return OutContext.GetOrCreateSymbol(Name);
}

MCSymbol *X86ATTAsmPrinter::GetJumpTableSymbol(const MachineOperand &MO) {
  SmallString<256> Name;
  raw_svector_ostream(Name) << MAI->getPrivateGlobalPrefix() << "JTI"
    << getFunctionNumber() << '_' << MO.getIndex();

  switch (MO.getTargetFlags()) {
  default:
    llvm_unreachable("Unknown target flag on GV operand");
  case X86II::MO_NO_FLAG:    // No flag.
  case X86II::MO_PIC_BASE_OFFSET:
  case X86II::MO_DARWIN_NONLAZY_PIC_BASE:
  case X86II::MO_DARWIN_HIDDEN_NONLAZY_PIC_BASE:
    break;
  }

  // Create a symbol for the name.
  return OutContext.GetOrCreateSymbol(Name.str());
}

MCSymbol *X86ATTAsmPrinter::
GetConstantPoolIndexSymbol(const MachineOperand &MO) {
  SmallString<256> Name;
  raw_svector_ostream(Name) << MAI->getPrivateGlobalPrefix() << "CPI"
  << getFunctionNumber() << '_' << MO.getIndex();

  switch (MO.getTargetFlags()) {
  default:
    llvm_unreachable("Unknown target flag on GV operand");
  case X86II::MO_NO_FLAG:    // No flag.
  case X86II::MO_PIC_BASE_OFFSET:
  case X86II::MO_DARWIN_NONLAZY_PIC_BASE:
  case X86II::MO_DARWIN_HIDDEN_NONLAZY_PIC_BASE:
    break;
  }

  // Create a symbol for the name.
  return OutContext.GetOrCreateSymbol(Name.str());
}

MCOperand X86ATTAsmPrinter::LowerSymbolOperand(const MachineOperand &MO,
                                               MCSymbol *Sym) {
  // FIXME: We would like an efficient form for this, so we don't have to do a
  // lot of extra uniquing.
  const MCExpr *Expr = MCSymbolRefExpr::Create(Sym, OutContext);

  switch (MO.getTargetFlags()) {
  default: llvm_unreachable("Unknown target flag on GV operand");
  case X86II::MO_NO_FLAG:    // No flag.

  // These affect the name of the symbol, not any suffix.
  case X86II::MO_DARWIN_NONLAZY:
  case X86II::MO_DLLIMPORT:
  case X86II::MO_DARWIN_STUB:
  case X86II::MO_TLSGD:
  case X86II::MO_GOTTPOFF:
  case X86II::MO_INDNTPOFF:
  case X86II::MO_TPOFF:
  case X86II::MO_NTPOFF:
  case X86II::MO_GOTPCREL:
  case X86II::MO_GOT:
  case X86II::MO_GOTOFF:
  case X86II::MO_PLT:
    break;
  case X86II::MO_PIC_BASE_OFFSET:
  case X86II::MO_DARWIN_NONLAZY_PIC_BASE:
  case X86II::MO_DARWIN_HIDDEN_NONLAZY_PIC_BASE:
    // Subtract the pic base.
    Expr = MCBinaryExpr::CreateSub(Expr,
                                   MCSymbolRefExpr::Create(GetPICBaseSymbol(),
                                                           OutContext),
                                   OutContext);
    break;
  case X86II::MO_GOT_ABSOLUTE_ADDRESS: {
    // For this, we want to print something like:
    //   MYSYMBOL + (. - PICBASE)
    // However, we can't generate a ".", so just emit a new label here and refer
    // to it.  We know that this operand flag occurs at most once per function.
    SmallString<64> Name;
    raw_svector_ostream(Name) << MAI->getPrivateGlobalPrefix() << "picbaseref"
      << getFunctionNumber();
    MCSymbol *DotSym = OutContext.GetOrCreateSymbol(Name.str());
    OutStreamer.EmitLabel(DotSym);

    const MCExpr *DotExpr = MCSymbolRefExpr::Create(DotSym, OutContext);
    const MCExpr *PICBase = MCSymbolRefExpr::Create(GetPICBaseSymbol(),
                                                    OutContext);
    DotExpr = MCBinaryExpr::CreateSub(DotExpr, PICBase, OutContext);
    Expr = MCBinaryExpr::CreateAdd(Expr, DotExpr, OutContext);
    break;
  }
  }

  if (!MO.isJTI() && MO.getOffset())
    Expr = MCBinaryExpr::CreateAdd(Expr, MCConstantExpr::Create(MO.getOffset(),
                                                                OutContext),
                                   OutContext);
  return MCOperand::CreateExpr(Expr);
}

void X86ATTAsmPrinter::
printInstructionThroughMCStreamer(const MachineInstr *MI) {

  MCInst TmpInst;

  switch (MI->getOpcode()) {
  case TargetInstrInfo::DBG_LABEL:
  case TargetInstrInfo::EH_LABEL:
  case TargetInstrInfo::GC_LABEL:
    printLabel(MI);
    return;
  case TargetInstrInfo::INLINEASM:
    O << '\t';
    printInlineAsm(MI);
    return;
  case TargetInstrInfo::IMPLICIT_DEF:
    printImplicitDef(MI);
    return;
  case X86::MOVPC32r: {
    // This is a pseudo op for a two instruction sequence with a label, which
    // looks like:
    //     call "L1$pb"
    // "L1$pb":
    //     popl %esi

    // Emit the call.
    MCSymbol *PICBase = GetPICBaseSymbol();
    TmpInst.setOpcode(X86::CALLpcrel32);
    // FIXME: We would like an efficient form for this, so we don't have to do a
    // lot of extra uniquing.
    TmpInst.addOperand(MCOperand::CreateExpr(MCSymbolRefExpr::Create(PICBase,
                                                                 OutContext)));
    printInstruction(&TmpInst);

    // Emit the label.
    OutStreamer.EmitLabel(PICBase);

    // popl $reg
    TmpInst.setOpcode(X86::POP32r);
    TmpInst.getOperand(0) = MCOperand::CreateReg(MI->getOperand(0).getReg());
    printInstruction(&TmpInst);
    return;
    }
  }

  TmpInst.setOpcode(MI->getOpcode());

  for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
    const MachineOperand &MO = MI->getOperand(i);

    MCOperand MCOp;
    switch (MO.getType()) {
    default:
      O.flush();
      errs() << "Cannot lower operand #" << i << " of :" << *MI;
      llvm_unreachable("Unimp");
    case MachineOperand::MO_Register:
      MCOp = MCOperand::CreateReg(MO.getReg());
      break;
    case MachineOperand::MO_Immediate:
      MCOp = MCOperand::CreateImm(MO.getImm());
      break;
    case MachineOperand::MO_MachineBasicBlock:
      MCOp = MCOperand::CreateMBBLabel(getFunctionNumber(),
                                       MO.getMBB()->getNumber());
      break;
    case MachineOperand::MO_GlobalAddress:
      MCOp = LowerSymbolOperand(MO, GetGlobalAddressSymbol(MO));
      break;
    case MachineOperand::MO_ExternalSymbol:
      MCOp = LowerSymbolOperand(MO, GetExternalSymbolSymbol(MO));
      break;
    case MachineOperand::MO_JumpTableIndex:
      MCOp = LowerSymbolOperand(MO, GetJumpTableSymbol(MO));
      break;
    case MachineOperand::MO_ConstantPoolIndex:
      MCOp = LowerSymbolOperand(MO, GetConstantPoolIndexSymbol(MO));
      break;
    }

    TmpInst.addOperand(MCOp);
  }

  switch (TmpInst.getOpcode()) {
  case X86::LEA64_32r:
    // Handle the 'subreg rewriting' for the lea64_32mem operand.
    lower_lea64_32mem(&TmpInst, 1);
    break;
  case X86::MOV16r0:
    TmpInst.setOpcode(X86::MOV32r0);
    lower_subreg32(&TmpInst, 0);
    break;
  case X86::MOVZX16rr8:
    TmpInst.setOpcode(X86::MOVZX32rr8);
    lower_subreg32(&TmpInst, 0);
    break;
  case X86::MOVZX16rm8:
    TmpInst.setOpcode(X86::MOVZX32rm8);
    lower_subreg32(&TmpInst, 0);
    break;
  case X86::MOVSX16rr8:
    TmpInst.setOpcode(X86::MOVSX32rr8);
    lower_subreg32(&TmpInst, 0);
    break;
  case X86::MOVSX16rm8:
    TmpInst.setOpcode(X86::MOVSX32rm8);
    lower_subreg32(&TmpInst, 0);
    break;
  case X86::MOVZX64rr32:
    TmpInst.setOpcode(X86::MOV32rr);
    lower_subreg32(&TmpInst, 0);
    break;
  case X86::MOVZX64rm32:
    TmpInst.setOpcode(X86::MOV32rm);
    lower_subreg32(&TmpInst, 0);
    break;
  case X86::MOV64ri64i32:
    TmpInst.setOpcode(X86::MOV32ri);
    lower_subreg32(&TmpInst, 0);
    break;
  case X86::MOVZX64rr8:
    TmpInst.setOpcode(X86::MOVZX32rr8);
    lower_subreg32(&TmpInst, 0);
    break;
  case X86::MOVZX64rm8:
    TmpInst.setOpcode(X86::MOVZX32rm8);
    lower_subreg32(&TmpInst, 0);
    break;
  case X86::MOVZX64rr16:
    TmpInst.setOpcode(X86::MOVZX32rr16);
    lower_subreg32(&TmpInst, 0);
    break;
  case X86::MOVZX64rm16:
    TmpInst.setOpcode(X86::MOVZX32rm16);
    lower_subreg32(&TmpInst, 0);
    break;
  }

  printInstruction(&TmpInst);
}
<|endoftext|>


<commit_before><commit_msg>Portability improvements.<commit_after><|endoftext|>


<commit_before>/*
	SFE_BMP180.cpp
	Bosch BMP180 pressure sensor library for the Arduino microcontroller
	Mike Grusin, SparkFun Electronics

	Uses floating-point equations from the Weather Station Data Logger project
	http://wmrx00.sourceforge.net/
	http://wmrx00.sourceforge.net/Arduino/BMP085-Calcs.pdf

	Forked from BMP085 library by M.Grusin

	version 1.0 2013/09/20 initial version

	Our example code uses the "beerware" license. You can do anything
	you like with this code. No really, anything. If you find it useful,
	buy me a (root) beer someday.
*/

#include <SFE_BMP180.h>
#include <Wire.h>
#include <stdio.h>
#include <math.h>

SFE_BMP180::SFE_BMP180()
// Base library type
{
}

char SFE_BMP180::begin()
// Initialize library for subsequent pressure measurements
{
	double c3,c4,b1;

	// Start up the Arduino's "wire" (I2C) library:

	Wire.begin();

	// The BMP180 includes factory calibration data stored on the device.
	// Each device has different numbers, these must be retrieved and
	// used in the calculations when taking pressure measurements.

	// Retrieve calibration data from device:

	if (readInt(0xAA,AC1) &&
		readInt(0xAC,AC2) &&
		readInt(0xAE,AC3) &&
		readUInt(0xB0,AC4) &&
		readUInt(0xB2,AC5) &&
		readUInt(0xB4,AC6) &&
		readInt(0xB6,VB1) &&
		readInt(0xB8,VB2) &&
		readInt(0xBA,MB) &&
		readInt(0xBC,MC) &&
		readInt(0xBE,MD))
	{

		// All reads completed successfully!

		// If you need to check your math using known numbers,
		// you can uncomment one of these examples.
		// (The correct results are commented in the below functions.)

		// Example from Bosch datasheet
		// AC1 = 408; AC2 = -72; AC3 = -14383; AC4 = 32741; AC5 = 32757; AC6 = 23153;
		// B1 = 6190; B2 = 4; MB = -32768; MC = -8711; MD = 2868;

		// Example from http://wmrx00.sourceforge.net/Arduino/BMP180-Calcs.pdf
		// AC1 = 7911; AC2 = -934; AC3 = -14306; AC4 = 31567; AC5 = 25671; AC6 = 18974;
		// VB1 = 5498; VB2 = 46; MB = -32768; MC = -11075; MD = 2432;

		/*
		Serial.print("AC1: "); Serial.println(AC1);
		Serial.print("AC2: "); Serial.println(AC2);
		Serial.print("AC3: "); Serial.println(AC3);
		Serial.print("AC4: "); Serial.println(AC4);
		Serial.print("AC5: "); Serial.println(AC5);
		Serial.print("AC6: "); Serial.println(AC6);
		Serial.print("VB1: "); Serial.println(VB1);
		Serial.print("VB2: "); Serial.println(VB2);
		Serial.print("MB: "); Serial.println(MB);
		Serial.print("MC: "); Serial.println(MC);
		Serial.print("MD: "); Serial.println(MD);
		*/

		// Compute floating-point polynominals:

		c3 = 160.0 * pow(2,-15) * AC3;
		c4 = pow(10,-3) * pow(2,-15) * AC4;
		b1 = pow(160,2) * pow(2,-30) * VB1;
		c5 = (pow(2,-15) / 160) * AC5;
		c6 = AC6;
		mc = (pow(2,11) / pow(160,2)) * MC;
		md = MD / 160.0;
		x0 = AC1;
		x1 = 160.0 * pow(2,-13) * AC2;
		x2 = pow(160,2) * pow(2,-25) * VB2;
		y0 = c4 * pow(2,15);
		y1 = c4 * c3;
		y2 = c4 * b1;
		p0 = (3791.0 - 8.0) / 1600.0;
		p1 = 1.0 - 7357.0 * pow(2,-20);
		p2 = 3038.0 * 100.0 * pow(2,-36);

		/*
		Serial.println();
		Serial.print("c3: "); Serial.println(c3);
		Serial.print("c4: "); Serial.println(c4);
		Serial.print("c5: "); Serial.println(c5);
		Serial.print("c6: "); Serial.println(c6);
		Serial.print("b1: "); Serial.println(b1);
		Serial.print("mc: "); Serial.println(mc);
		Serial.print("md: "); Serial.println(md);
		Serial.print("x0: "); Serial.println(x0);
		Serial.print("x1: "); Serial.println(x1);
		Serial.print("x2: "); Serial.println(x2);
		Serial.print("y0: "); Serial.println(y0);
		Serial.print("y1: "); Serial.println(y1);
		Serial.print("y2: "); Serial.println(y2);
		Serial.print("p0: "); Serial.println(p0);
		Serial.print("p1: "); Serial.println(p1);
		Serial.print("p2: "); Serial.println(p2);
		*/

		// Success!
		return(1);
	}
	else
	{
		// Error reading calibration data; bad component or connection?
		return(0);
	}
}

char SFE_BMP180::readInt(char address, int16_t &value)
// Read a signed integer (two bytes) from device
// address: register to start reading (plus subsequent register)
// value: external variable to store data (function modifies value)
{
	unsigned char data[2];

	data[0] = address;
	if (readBytes(data,2))
	{
		value = (((int16_t)data[0]<<8)|(int16_t)data[1]);
		//if (*value & 0x8000) *value |= 0xFFFF0000; // sign extend if negative
		return(1);
	}
	value = 0;
	return(0);
}

char SFE_BMP180::readUInt(char address, uint16_t &value)
// Read an unsigned integer (two bytes) from device
// address: register to start reading (plus subsequent register)
// value: external variable to store data (function modifies value)
{
	unsigned char data[2];

	data[0] = address;
	if (readBytes(data,2))
	{
		value = (((uint16_t)data[0]<<8)|(uint16_t)data[1]);
		return(1);
	}
	value = 0;
	return(0);
}

char SFE_BMP180::readBytes(unsigned char *values, char length)
// Read an array of bytes from device
// values: external array to hold data. Put starting register in values[0].
// length: number of bytes to read
{
	char x;

	Wire.beginTransmission(BMP180_ADDR);
	Wire.write(values[0]);
	_error = Wire.endTransmission();
	if (_error == 0)
	{
		Wire.requestFrom(BMP180_ADDR,length);
		while(Wire.available() != length) ; // wait until bytes are ready
		for(x=0;x<length;x++)
		{
			values[x] = Wire.read();
		}
		return(1);
	}
	return(0);
}

char SFE_BMP180::writeBytes(unsigned char *values, char length)
// Write an array of bytes to device
// values: external array of data to write. Put starting register in values[0].
// length: number of bytes to write
{
	char x;

	Wire.beginTransmission(BMP180_ADDR);
	Wire.write(values,length);
	_error = Wire.endTransmission();
	if (_error == 0)
		return(1);
	else
		return(0);
}

char SFE_BMP180::startTemperature(void)
// Begin a temperature reading.
// Will return delay in ms to wait, or 0 if I2C error
{
	unsigned char data[2], result;

	data[0] = BMP180_REG_CONTROL;
	data[1] = BMP180_COMMAND_TEMPERATURE;
	result = writeBytes(data, 2);
	if (result) // good write?
		return(5); // return the delay in ms (rounded up) to wait before retrieving data
	else
		return(0); // or return 0 if there was a problem communicating with the BMP
}

char SFE_BMP180::getTemperature(double &T)
// Retrieve a previously-started temperature reading.
// Requires begin() to be called once prior to retrieve calibration parameters.
// Requires startTemperature() to have been called prior and sufficient time elapsed.
// T: external variable to hold result.
// Returns 1 if successful, 0 if I2C error.
{
	unsigned char data[2];
	char result;
	double tu, a;

	data[0] = BMP180_REG_RESULT;

	result = readBytes(data, 2);
	if (result) // good read, calculate temperature
	{
		tu = (data[0] * 256.0) + data[1];

		//example from Bosch datasheet
		//tu = 27898;

		//example from http://wmrx00.sourceforge.net/Arduino/BMP085-Calcs.pdf
		//tu = 0x69EC;

		a = c5 * (tu - c6);
		T = a + (mc / (a + md));

		/*
		Serial.println();
		Serial.print("tu: "); Serial.println(tu);
		Serial.print("a: "); Serial.println(a);
		Serial.print("T: "); Serial.println(*T);
		*/
	}
	return(result);
}

char SFE_BMP180::startPressure(char oversampling)
// Begin a pressure reading.
// Oversampling: 0 to 3, higher numbers are slower, higher-res outputs.
// Will return delay in ms to wait, or 0 if I2C error.
{
	unsigned char data[2], result, delay;

	data[0] = BMP180_REG_CONTROL;

	switch (oversampling)
	{
		case 0:
			data[1] = BMP180_COMMAND_PRESSURE0;
			delay = 5;
		break;
		case 1:
			data[1] = BMP180_COMMAND_PRESSURE1;
			delay = 8;
		break;
		case 2:
			data[1] = BMP180_COMMAND_PRESSURE2;
			delay = 14;
		break;
		case 3:
			data[1] = BMP180_COMMAND_PRESSURE3;
			delay = 26;
		break;
		default:
			data[1] = BMP180_COMMAND_PRESSURE0;
			delay = 5;
		break;
	}
	result = writeBytes(data, 2);
	if (result) // good write?
		return(delay); // return the delay in ms (rounded up) to wait before retrieving data
	else
		return(0); // or return 0 if there was a problem communicating with the BMP
}

char SFE_BMP180::getPressure(double &P, double &T)
// Retrieve a previously started pressure reading, calculate abolute pressure in mbars.
// Requires begin() to be called once prior to retrieve calibration parameters.
// Requires startPressure() to have been called prior and sufficient time elapsed.
// Requires recent temperature reading to accurately calculate pressure.

// P: external variable to hold pressure.
// T: previously-calculated temperature.
// Returns 1 for success, 0 for I2C error.

// Note that calculated pressure value is absolute mbars, to compensate for altitude call sealevel().
{
	unsigned char data[3];
	char result;
	double pu,s,x,y,z;

	data[0] = BMP180_REG_RESULT;

	result = readBytes(data, 3);
	if (result) // good read, calculate pressure
	{
		pu = (data[0] * 256.0) + data[1] + (data[2]/256.0);

		//example from Bosch datasheet
		//pu = 23843;

		//example from http://wmrx00.sourceforge.net/Arduino/BMP085-Calcs.pdf, pu = 0x982FC0;
		//pu = (0x98 * 256.0) + 0x2F + (0xC0/256.0);

		s = T - 25.0;
		x = (x2 * pow(s,2)) + (x1 * s) + x0;
		y = (y2 * pow(s,2)) + (y1 * s) + y0;
		z = (pu - x) / y;
		P = (p2 * pow(z,2)) + (p1 * z) + p0;

		/*
		Serial.println();
		Serial.print("pu: "); Serial.println(pu);
		Serial.print("T: "); Serial.println(*T);
		Serial.print("s: "); Serial.println(s);
		Serial.print("x: "); Serial.println(x);
		Serial.print("y: "); Serial.println(y);
		Serial.print("z: "); Serial.println(z);
		Serial.print("P: "); Serial.println(*P);
		*/
	}
	return(result);
}

double SFE_BMP180::sealevel(double P, double A)
// Given a pressure P (mb) taken at a specific altitude (meters),
// return the equivalent pressure (mb) at sea level.
// This produces pressure readings that can be used for weather measurements.
{
	return(P/pow(1-(A/44330.0),5.255));
}

double SFE_BMP180::altitude(double P, double P0)
// Given a pressure measurement P (mb) and the pressure at a baseline P0 (mb),
// return altitude (meters) above baseline.
{
	return(44330.0*(1-pow(P/P0,1/5.255)));
}

char SFE_BMP180::getError(void)
	// If any library command fails, you can retrieve an extended
	// error code using this command. Errors are from the wire library:
	// 0 = Success
	// 1 = Data too long to fit in transmit buffer
	// 2 = Received NACK on transmit of address
	// 3 = Received NACK on transmit of data
	// 4 = Other error
{
	return(_error);
}
<commit_msg>Update SFE_BMP180.cpp<commit_after>/*
	SFE_BMP180.cpp
	Bosch BMP180 pressure sensor library for the Arduino microcontroller
	Mike Grusin, SparkFun Electronics

	Uses floating-point equations from the Weather Station Data Logger project
	http://wmrx00.sourceforge.net/
	http://wmrx00.sourceforge.net/Arduino/BMP085-Calcs.pdf

	Forked from BMP085 library by M.Grusin

	version 1.0 2013/09/20 initial version

	Our example code uses the "beerware" license. You can do anything
	you like with this code. No really, anything. If you find it useful,
	buy me a (root) beer someday.
*/

#include "SFE_BMP180.h"
#include <stdio.h>
#include <math.h>

SFE_BMP180::SFE_BMP180()
// Base library type
{
}

char SFE_BMP180::begin()
// Initialize library for subsequent pressure measurements
{
	double c3,c4,b1;

	// Start up the Arduino's "wire" (I2C) library:

	Wire.begin();

	// The BMP180 includes factory calibration data stored on the device.
	// Each device has different numbers, these must be retrieved and
	// used in the calculations when taking pressure measurements.

	// Retrieve calibration data from device:

	if (readInt(0xAA,AC1) &&
		readInt(0xAC,AC2) &&
		readInt(0xAE,AC3) &&
		readUInt(0xB0,AC4) &&
		readUInt(0xB2,AC5) &&
		readUInt(0xB4,AC6) &&
		readInt(0xB6,VB1) &&
		readInt(0xB8,VB2) &&
		readInt(0xBA,MB) &&
		readInt(0xBC,MC) &&
		readInt(0xBE,MD))
	{

		// All reads completed successfully!

		// If you need to check your math using known numbers,
		// you can uncomment one of these examples.
		// (The correct results are commented in the below functions.)

		// Example from Bosch datasheet
		// AC1 = 408; AC2 = -72; AC3 = -14383; AC4 = 32741; AC5 = 32757; AC6 = 23153;
		// B1 = 6190; B2 = 4; MB = -32768; MC = -8711; MD = 2868;

		// Example from http://wmrx00.sourceforge.net/Arduino/BMP180-Calcs.pdf
		// AC1 = 7911; AC2 = -934; AC3 = -14306; AC4 = 31567; AC5 = 25671; AC6 = 18974;
		// VB1 = 5498; VB2 = 46; MB = -32768; MC = -11075; MD = 2432;

		/*
		Serial.print("AC1: "); Serial.println(AC1);
		Serial.print("AC2: "); Serial.println(AC2);
		Serial.print("AC3: "); Serial.println(AC3);
		Serial.print("AC4: "); Serial.println(AC4);
		Serial.print("AC5: "); Serial.println(AC5);
		Serial.print("AC6: "); Serial.println(AC6);
		Serial.print("VB1: "); Serial.println(VB1);
		Serial.print("VB2: "); Serial.println(VB2);
		Serial.print("MB: "); Serial.println(MB);
		Serial.print("MC: "); Serial.println(MC);
		Serial.print("MD: "); Serial.println(MD);
		*/

		// Compute floating-point polynominals:

		c3 = 160.0 * pow(2,-15) * AC3;
		c4 = pow(10,-3) * pow(2,-15) * AC4;
		b1 = pow(160,2) * pow(2,-30) * VB1;
		c5 = (pow(2,-15) / 160) * AC5;
		c6 = AC6;
		mc = (pow(2,11) / pow(160,2)) * MC;
		md = MD / 160.0;
		x0 = AC1;
		x1 = 160.0 * pow(2,-13) * AC2;
		x2 = pow(160,2) * pow(2,-25) * VB2;
		y0 = c4 * pow(2,15);
		y1 = c4 * c3;
		y2 = c4 * b1;
		p0 = (3791.0 - 8.0) / 1600.0;
		p1 = 1.0 - 7357.0 * pow(2,-20);
		p2 = 3038.0 * 100.0 * pow(2,-36);

		/*
		Serial.println();
		Serial.print("c3: "); Serial.println(c3);
		Serial.print("c4: "); Serial.println(c4);
		Serial.print("c5: "); Serial.println(c5);
		Serial.print("c6: "); Serial.println(c6);
		Serial.print("b1: "); Serial.println(b1);
		Serial.print("mc: "); Serial.println(mc);
		Serial.print("md: "); Serial.println(md);
		Serial.print("x0: "); Serial.println(x0);
		Serial.print("x1: "); Serial.println(x1);
		Serial.print("x2: "); Serial.println(x2);
		Serial.print("y0: "); Serial.println(y0);
		Serial.print("y1: "); Serial.println(y1);
		Serial.print("y2: "); Serial.println(y2);
		Serial.print("p0: "); Serial.println(p0);
		Serial.print("p1: "); Serial.println(p1);
		Serial.print("p2: "); Serial.println(p2);
		*/

		// Success!
		return(1);
	}
	else
	{
		// Error reading calibration data; bad component or connection?
		return(0);
	}
}

char SFE_BMP180::readInt(char address, int16_t &value)
// Read a signed integer (two bytes) from device
// address: register to start reading (plus subsequent register)
// value: external variable to store data (function modifies value)
{
	unsigned char data[2];

	data[0] = address;
	if (readBytes(data,2))
	{
		value = (((int16_t)data[0]<<8)|(int16_t)data[1]);
		//if (*value & 0x8000) *value |= 0xFFFF0000; // sign extend if negative
		return(1);
	}
	value = 0;
	return(0);
}

char SFE_BMP180::readUInt(char address, uint16_t &value)
// Read an unsigned integer (two bytes) from device
// address: register to start reading (plus subsequent register)
// value: external variable to store data (function modifies value)
{
	unsigned char data[2];

	data[0] = address;
	if (readBytes(data,2))
	{
		value = (((uint16_t)data[0]<<8)|(uint16_t)data[1]);
		return(1);
	}
	value = 0;
	return(0);
}

char SFE_BMP180::readBytes(unsigned char *values, char length)
// Read an array of bytes from device
// values: external array to hold data. Put starting register in values[0].
// length: number of bytes to read
{
	char x;

	Wire.beginTransmission(BMP180_ADDR);
	Wire.write(values[0]);
	_error = Wire.endTransmission();
	if (_error == 0)
	{
		Wire.requestFrom(BMP180_ADDR,length);
		while(Wire.available() != length) ; // wait until bytes are ready
		for(x=0;x<length;x++)
		{
			values[x] = Wire.read();
		}
		return(1);
	}
	return(0);
}

char SFE_BMP180::writeBytes(unsigned char *values, char length)
// Write an array of bytes to device
// values: external array of data to write. Put starting register in values[0].
// length: number of bytes to write
{
	char x;

	Wire.beginTransmission(BMP180_ADDR);
	Wire.write(values,length);
	_error = Wire.endTransmission();
	if (_error == 0)
		return(1);
	else
		return(0);
}

char SFE_BMP180::startTemperature(void)
// Begin a temperature reading.
// Will return delay in ms to wait, or 0 if I2C error
{
	unsigned char data[2], result;

	data[0] = BMP180_REG_CONTROL;
	data[1] = BMP180_COMMAND_TEMPERATURE;
	result = writeBytes(data, 2);
	if (result) // good write?
		return(5); // return the delay in ms (rounded up) to wait before retrieving data
	else
		return(0); // or return 0 if there was a problem communicating with the BMP
}

char SFE_BMP180::getTemperature(double &T)
// Retrieve a previously-started temperature reading.
// Requires begin() to be called once prior to retrieve calibration parameters.
// Requires startTemperature() to have been called prior and sufficient time elapsed.
// T: external variable to hold result.
// Returns 1 if successful, 0 if I2C error.
{
	unsigned char data[2];
	char result;
	double tu, a;

	data[0] = BMP180_REG_RESULT;

	result = readBytes(data, 2);
	if (result) // good read, calculate temperature
	{
		tu = (data[0] * 256.0) + data[1];

		//example from Bosch datasheet
		//tu = 27898;

		//example from http://wmrx00.sourceforge.net/Arduino/BMP085-Calcs.pdf
		//tu = 0x69EC;

		a = c5 * (tu - c6);
		T = a + (mc / (a + md));

		/*
		Serial.println();
		Serial.print("tu: "); Serial.println(tu);
		Serial.print("a: "); Serial.println(a);
		Serial.print("T: "); Serial.println(*T);
		*/
	}
	return(result);
}

char SFE_BMP180::startPressure(char oversampling)
// Begin a pressure reading.
// Oversampling: 0 to 3, higher numbers are slower, higher-res outputs.
// Will return delay in ms to wait, or 0 if I2C error.
{
	unsigned char data[2], result, delay;

	data[0] = BMP180_REG_CONTROL;

	switch (oversampling)
	{
		case 0:
			data[1] = BMP180_COMMAND_PRESSURE0;
			delay = 5;
		break;
		case 1:
			data[1] = BMP180_COMMAND_PRESSURE1;
			delay = 8;
		break;
		case 2:
			data[1] = BMP180_COMMAND_PRESSURE2;
			delay = 14;
		break;
		case 3:
			data[1] = BMP180_COMMAND_PRESSURE3;
			delay = 26;
		break;
		default:
			data[1] = BMP180_COMMAND_PRESSURE0;
			delay = 5;
		break;
	}
	result = writeBytes(data, 2);
	if (result) // good write?
		return(delay); // return the delay in ms (rounded up) to wait before retrieving data
	else
		return(0); // or return 0 if there was a problem communicating with the BMP
}

char SFE_BMP180::getPressure(double &P, double &T)
// Retrieve a previously started pressure reading, calculate abolute pressure in mbars.
// Requires begin() to be called once prior to retrieve calibration parameters.
// Requires startPressure() to have been called prior and sufficient time elapsed.
// Requires recent temperature reading to accurately calculate pressure.

// P: external variable to hold pressure.
// T: previously-calculated temperature.
// Returns 1 for success, 0 for I2C error.

// Note that calculated pressure value is absolute mbars, to compensate for altitude call sealevel().
{
	unsigned char data[3];
	char result;
	double pu,s,x,y,z;

	data[0] = BMP180_REG_RESULT;

	result = readBytes(data, 3);
	if (result) // good read, calculate pressure
	{
		pu = (data[0] * 256.0) + data[1] + (data[2]/256.0);

		//example from Bosch datasheet
		//pu = 23843;

		//example from http://wmrx00.sourceforge.net/Arduino/BMP085-Calcs.pdf, pu = 0x982FC0;
		//pu = (0x98 * 256.0) + 0x2F + (0xC0/256.0);

		s = T - 25.0;
		x = (x2 * pow(s,2)) + (x1 * s) + x0;
		y = (y2 * pow(s,2)) + (y1 * s) + y0;
		z = (pu - x) / y;
		P = (p2 * pow(z,2)) + (p1 * z) + p0;

		/*
		Serial.println();
		Serial.print("pu: "); Serial.println(pu);
		Serial.print("T: "); Serial.println(*T);
		Serial.print("s: "); Serial.println(s);
		Serial.print("x: "); Serial.println(x);
		Serial.print("y: "); Serial.println(y);
		Serial.print("z: "); Serial.println(z);
		Serial.print("P: "); Serial.println(*P);
		*/
	}
	return(result);
}

double SFE_BMP180::sealevel(double P, double A)
// Given a pressure P (mb) taken at a specific altitude (meters),
// return the equivalent pressure (mb) at sea level.
// This produces pressure readings that can be used for weather measurements.
{
	return(P/pow(1-(A/44330.0),5.255));
}

double SFE_BMP180::altitude(double P, double P0)
// Given a pressure measurement P (mb) and the pressure at a baseline P0 (mb),
// return altitude (meters) above baseline.
{
	return(44330.0*(1-pow(P/P0,1/5.255)));
}

char SFE_BMP180::getError(void)
	// If any library command fails, you can retrieve an extended
	// error code using this command. Errors are from the wire library:
	// 0 = Success
	// 1 = Data too long to fit in transmit buffer
	// 2 = Received NACK on transmit of address
	// 3 = Received NACK on transmit of data
	// 4 = Other error
{
	return(_error);
}
<|endoftext|>