<commit_before>/*
 * Copyright (C) 2008 Nokia Corporation.
 *
 * Contact: Marius Vollmer <marius.vollmer@nokia.com>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public License
 * version 2.1 as published by the Free Software Foundation.
 *
 * This library is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA
 *
 */

#include "dbusnamelistener.h"
#include "safedbuspendingcallwatcher.h"
#include "sconnect.h"
#include "logging.h"

#include <QDBusConnectionInterface>
#include <QPair>
#include <QMap>
#include <QString>

namespace ContextSubscriber {

/*! \class DBusNameListener

  \brief Listens for changes in a specific service name on a D-Bus bus,
  optionally gets the initial state of the service name.

  When you create an instance of this class, it won't open any D-Bus
  connections. When startListening is called, the instance connects to
  the NameOwnerChanged D-Bus signal.  It can also check the current
  status of the service by executing an asynchronous NameHasOwner
  call.

  If the specified service appears on D-Bus, it will emit the \c
  nameAppeared() signal, if disappears, then the nameDisappeared()
  signal.  An initial query and signal emission will be done if \c
  initialCheck is true, which is the default.

  Anytime you can check with <tt>isServicePresent()</tt> if according
  to our current knowledge (last signal emission) the service is
  present or not.  This means that if \c initialCheck is false,
  <tt>isServicePresent()</tt> can return false, even though the service
  is present.
*/
DBusNameListener::DBusNameListener(QDBusConnection::BusType busType, const QString &busName, QObject *parent) :
    QObject(parent), servicePresent(Unknown), busType(busType), busName(busName), listeningStarted(false), connection(0)
{
    // Don't do anything, until the user initiates the listening by calling startListening.
}

DBusNameListener::DBusNameListener(const QDBusConnection bus, const QString &busName, QObject *parent) :
    QObject(parent), servicePresent(Unknown), busName(busName), listeningStarted(false), connection(0)
{
    // we copy the connection so we can safely delete it in the destructor
    connection = new QDBusConnection(bus);
}

DBusNameListener::~DBusNameListener()
{
    delete connection;
    connection = 0;
}

/// Start listening to the NameOwnerChanged signal over D-Bus. If \a
/// nameHasOwnerCheck is true, also send a NameHasOwner query to D-Bus
/// (asyncronously).
void DBusNameListener::startListening(bool nameHasOwnerCheck)
{
    if (listeningStarted) return;

    listeningStarted = true;
    // if we were initialized without a connection, we have to create our own
    if (connection == 0) {
        if (busType == QDBusConnection::SystemBus) {
            connection = new QDBusConnection(QDBusConnection::systemBus());
        }
        else if (busType == QDBusConnection::SessionBus) {
            connection = new QDBusConnection(QDBusConnection::sessionBus());
        }
        else {
            return;
        }
    }

    sconnect(connection->interface(),
             SIGNAL(serviceOwnerChanged(const QString&, const QString&, const QString&)),
             this,
             SLOT(onServiceOwnerChanged(const QString&, const QString&, const QString&)));

    // Check if the service is already there
    if (nameHasOwnerCheck) {
        QDBusPendingCall nameHasOwnerCall = connection->interface()->asyncCall("NameHasOwner", busName);
        SafeDBusPendingCallWatcher *watcher = new SafeDBusPendingCallWatcher(nameHasOwnerCall, this);
        sconnect(watcher, SIGNAL(finished(QDBusPendingCallWatcher *)),
                 this, SLOT(onNameHasOwnerFinished(QDBusPendingCallWatcher *)));
    }
}

/// This slot is called when DBusNameOwnerChanged signal arrives and
/// it just filters the name and if we are interested in the name it
/// emits the <tt>nameAppeared()</tt> or <tt>nameDisappeared()</tt>
/// signal.
void DBusNameListener::onServiceOwnerChanged(const QString &name, const QString &oldOwner, const QString &newOwner)
{
    contextDebug() << "name owner change" << name << oldOwner << newOwner;
    if (name == busName) {
        if (oldOwner == "") {
            setServicePresent();
        } else if (newOwner == "") {
            setServiceGone();
        }
    }
}

void DBusNameListener::setServicePresent()
{
    if (servicePresent != Present) {
        servicePresent = Present;
        emit nameAppeared();
    }
}

void DBusNameListener::setServiceGone()
{
    if (servicePresent != NotPresent) {
        servicePresent = NotPresent;
        emit nameDisappeared();
    }
}

/// Handling of the asynchronous reply of the initial query.
void DBusNameListener::onNameHasOwnerFinished(QDBusPendingCallWatcher* watcher)
{
    QDBusPendingReply<bool> reply = *watcher;
    if (reply.isError() == false && reply.argumentAt<0>() == true) {
        // The name has an owner
        setServicePresent();
    }
    else {
        // PropertyHandle's are waiting for any signal if they have initiated the
        // "is commander there" check. So notify also the opposite case.
        setServiceGone();
    }
}

/// Return our current understanding (not present, present, unknown)
/// of the presence of the watched service.
DBusNameListener::ServicePresence DBusNameListener::isServicePresent() const
{
    return servicePresent;
}

} // end namespace
<commit_msg>libcontextsubscriber fix: If we cannot connect to D-Bus, we assume that services are not-present. (This enables us to use libcontextsubcriber without session bus.)<commit_after>/*
 * Copyright (C) 2008 Nokia Corporation.
 *
 * Contact: Marius Vollmer <marius.vollmer@nokia.com>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public License
 * version 2.1 as published by the Free Software Foundation.
 *
 * This library is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA
 *
 */

#include "dbusnamelistener.h"
#include "safedbuspendingcallwatcher.h"
#include "sconnect.h"
#include "logging.h"

#include <QDBusConnectionInterface>
#include <QPair>
#include <QMap>
#include <QString>

namespace ContextSubscriber {

/*! \class DBusNameListener

  \brief Listens for changes in a specific service name on a D-Bus bus,
  optionally gets the initial state of the service name.

  When you create an instance of this class, it won't open any D-Bus
  connections. When startListening is called, the instance connects to
  the NameOwnerChanged D-Bus signal.  It can also check the current
  status of the service by executing an asynchronous NameHasOwner
  call.

  If the specified service appears on D-Bus, it will emit the \c
  nameAppeared() signal, if disappears, then the nameDisappeared()
  signal.  An initial query and signal emission will be done if \c
  initialCheck is true, which is the default.

  Anytime you can check with <tt>isServicePresent()</tt> if according
  to our current knowledge (last signal emission) the service is
  present or not.  This means that if \c initialCheck is false,
  <tt>isServicePresent()</tt> can return false, even though the service
  is present.
*/
DBusNameListener::DBusNameListener(QDBusConnection::BusType busType, const QString &busName, QObject *parent) :
    QObject(parent), servicePresent(Unknown), busType(busType), busName(busName), listeningStarted(false), connection(0)
{
    // Don't do anything, until the user initiates the listening by calling startListening.
}

DBusNameListener::DBusNameListener(const QDBusConnection bus, const QString &busName, QObject *parent) :
    QObject(parent), servicePresent(Unknown), busName(busName), listeningStarted(false), connection(0)
{
    // we copy the connection so we can safely delete it in the destructor
    connection = new QDBusConnection(bus);
}

DBusNameListener::~DBusNameListener()
{
    delete connection;
    connection = 0;
}

/// Start listening to the NameOwnerChanged signal over D-Bus. If \a
/// nameHasOwnerCheck is true, also send a NameHasOwner query to D-Bus
/// (asyncronously).
void DBusNameListener::startListening(bool nameHasOwnerCheck)
{
    if (listeningStarted) return;

    listeningStarted = true;
    // if we were initialized without a connection, we have to create our own
    if (connection == 0) {
        if (busType == QDBusConnection::SystemBus) {
            connection = new QDBusConnection(QDBusConnection::systemBus());
        }
        else if (busType == QDBusConnection::SessionBus) {
            connection = new QDBusConnection(QDBusConnection::sessionBus());
        }
        else {
            return;
        }
    }

    sconnect(connection->interface(),
             SIGNAL(serviceOwnerChanged(const QString&, const QString&, const QString&)),
             this,
             SLOT(onServiceOwnerChanged(const QString&, const QString&, const QString&)));

    // Check if the service is already there
    if (nameHasOwnerCheck) {
        if (connection->isConnected() == false) {
            setServiceGone();
        }
        QDBusPendingCall nameHasOwnerCall = connection->interface()->asyncCall("NameHasOwner", busName);
        SafeDBusPendingCallWatcher *watcher = new SafeDBusPendingCallWatcher(nameHasOwnerCall, this);
        sconnect(watcher, SIGNAL(finished(QDBusPendingCallWatcher *)),
                 this, SLOT(onNameHasOwnerFinished(QDBusPendingCallWatcher *)));
    }
}

/// This slot is called when DBusNameOwnerChanged signal arrives and
/// it just filters the name and if we are interested in the name it
/// emits the <tt>nameAppeared()</tt> or <tt>nameDisappeared()</tt>
/// signal.
void DBusNameListener::onServiceOwnerChanged(const QString &name, const QString &oldOwner, const QString &newOwner)
{
    contextDebug() << "name owner change" << name << oldOwner << newOwner;
    if (name == busName) {
        if (oldOwner == "") {
            setServicePresent();
        } else if (newOwner == "") {
            setServiceGone();
        }
    }
}

void DBusNameListener::setServicePresent()
{
    if (servicePresent != Present) {
        servicePresent = Present;
        emit nameAppeared();
    }
}

void DBusNameListener::setServiceGone()
{
    if (servicePresent != NotPresent) {
        servicePresent = NotPresent;
        emit nameDisappeared();
    }
}

/// Handling of the asynchronous reply of the initial query.
void DBusNameListener::onNameHasOwnerFinished(QDBusPendingCallWatcher* watcher)
{
    QDBusPendingReply<bool> reply = *watcher;
    if (reply.isError() == false && reply.argumentAt<0>() == true) {
        // The name has an owner
        setServicePresent();
    }
    else {
        // PropertyHandle's are waiting for any signal if they have initiated the
        // "is commander there" check. So notify also the opposite case.
        setServiceGone();
    }
}

/// Return our current understanding (not present, present, unknown)
/// of the presence of the watched service.
DBusNameListener::ServicePresence DBusNameListener::isServicePresent() const
{
    return servicePresent;
}

} // end namespace
<|endoftext|>


<commit_before>//
// Copyright (c) 2016, Paul R. Swan
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice,
//    this list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice,
//    this list of conditions and the following disclaimer in the documentation
//    and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
// OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
// COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
// TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
// EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
#include "CSpaceInvadersBaseGame.h"
#include "C8080DedicatedCpu.h"
#include "CRamCheck.h"

//
// Probe Head GND:
//   The 8080 specific probe head must be used.
//
// Watchdog Disable:
//   TBD.
//
// Board Designations:
//   's' - Sound board.
//   'c' - CPU board.
//   'r' - ROM board.
//
// CPU Compatibility Notes
//   * READY is used to hold off the CPU. This is for holding off access to the shared VRAM.
//

//
// RAM region is the same for all games on this board set.
//
static const RAM_REGION s_ramRegion[] PROGMEM = { //                                        "012", "012345"
                                                  {NO_BANK_SWITCH, 0x2000, 0x3FFF, 2, 0x01, "c33", "VRAM1A"}, // Video RAM - 1A
                                                  {NO_BANK_SWITCH, 0x2000, 0x3FFF, 2, 0x02, "c31", "VRAM2A"}, // Video RAM - 2A
                                                  {NO_BANK_SWITCH, 0x2000, 0x3FFF, 2, 0x04, "c25", "VRAM3A"}, // Video RAM - 3A
                                                  {NO_BANK_SWITCH, 0x2000, 0x3FFF, 2, 0x08, "c23", "VRAM4A"}, // Video RAM - 4A
                                                  {NO_BANK_SWITCH, 0x2000, 0x3FFF, 2, 0x10, "c21", "VRAM5A"}, // Video RAM - 5A
                                                  {NO_BANK_SWITCH, 0x2000, 0x3FFF, 2, 0x20, "c17", "VRAM6A"}, // Video RAM - 6A
                                                  {NO_BANK_SWITCH, 0x2000, 0x3FFF, 2, 0x40, "c15", "VRAM7A"}, // Video RAM - 7A
                                                  {NO_BANK_SWITCH, 0x2000, 0x3FFF, 2, 0x80, "c10", "VRAM8A"}, // Video RAM - 8A
                                                  {NO_BANK_SWITCH, 0x2001, 0x3FFF, 2, 0x01, "c32", "VRAM1B"}, // Video RAM - 1B
                                                  {NO_BANK_SWITCH, 0x2001, 0x3FFF, 2, 0x02, "c30", "VRAM2B"}, // Video RAM - 2B
                                                  {NO_BANK_SWITCH, 0x2001, 0x3FFF, 2, 0x04, "c24", "VRAM3B"}, // Video RAM - 3B
                                                  {NO_BANK_SWITCH, 0x2001, 0x3FFF, 2, 0x08, "c22", "VRAM4B"}, // Video RAM - 4B
                                                  {NO_BANK_SWITCH, 0x2001, 0x3FFF, 2, 0x10, "c20", "VRAM5B"}, // Video RAM - 5B
                                                  {NO_BANK_SWITCH, 0x2001, 0x3FFF, 2, 0x20, "c16", "VRAM6B"}, // Video RAM - 6B
                                                  {NO_BANK_SWITCH, 0x2001, 0x3FFF, 2, 0x40, "c14", "VRAM7B"}, // Video RAM - 7B
                                                  {NO_BANK_SWITCH, 0x2001, 0x3FFF, 2, 0x80, "c9 ", "VRAM8B"}, // Video RAM - 8B
                                                  {0}
                                                }; // end of list

//
// RAM region is the same for all games on this board set.
// This description is used for the byte-wide intensive random access memory test.
//
static const RAM_REGION s_ramRegionByteOnly[] PROGMEM = { //                                        "012", "012345"
                                                          {NO_BANK_SWITCH, 0x2000, 0x3FFF, 2, 0xFF, "cA ", "VRAM  "}, // Video RAM, top bank
                                                          {NO_BANK_SWITCH, 0x2001, 0x3FFF, 2, 0xFF, "cB ", "VRAM  "}, // Video RAM, bottom bank
                                                          {NO_BANK_SWITCH, 0x2000, 0x3FFF, 1, 0xFF, "cAB", "VRAM  "}, // Video RAM, both
                                                          {0}
                                                        }; // end of list

//
// No write-only RAM on this platform. Yay!
//
static const RAM_REGION s_ramRegionWriteOnly[] PROGMEM = { {0} }; // end of list

//
// Input region is the same for all games on this board set.
//
static const INPUT_REGION s_inputRegion[] PROGMEM = { //                               "012", "012345"
                                                      {NO_BANK_SWITCH, 0x10000L, 0xFF, "   ", "IN0   "}, // Switch Inputs (IN0)
                                                      {NO_BANK_SWITCH, 0x10001L, 0xFF, "   ", "IN1   "}, // Switch Inputs (IN1)
                                                      {NO_BANK_SWITCH, 0x10002L, 0xFF, "   ", "IN2   "}, // Switch Inputs (IN2)
                                                      {NO_BANK_SWITCH, 0x10003L, 0xFF, "   ", "ShiftR"}, // Shift Result
                                                      {0}
                                                    }; // end of list

//
// Output region is the same for all versions on this board set.
//
static const OUTPUT_REGION s_outputRegion[] PROGMEM = { //
                                                        // Note that in order to hear the sounds the Sound On bit must be high.
                                                        // Describing that in the invert mask leaves the sound always on so that
                                                        // the decay after trigger can be heard.
                                                        //
                                                        //                                     "012", "012345"
                                                        {NO_BANK_SWITCH, 0x10003L, 0x01, 0x20, "S0 ", "Ufo   "}, // S0 - SM1
                                                        {NO_BANK_SWITCH, 0x10003L, 0x02, 0x20, "S1 ", "Fire  "}, // S1 - SM2
                                                        {NO_BANK_SWITCH, 0x10003L, 0x04, 0x20, "S2 ", "BseHit"}, // S2 - SM3
                                                        {NO_BANK_SWITCH, 0x10003L, 0x08, 0x20, "S3 ", "InvHit"}, // S3 - SM4
                                                        {NO_BANK_SWITCH, 0x10003L, 0x10, 0x20, "S4 ", "Bonus "}, // S4 - SM5
                                                        {NO_BANK_SWITCH, 0x10003L, 0x20, 0x00, "S5 ", "Snd On"}, // S5 - Sound On
                                                        {NO_BANK_SWITCH, 0x10005L, 0x01, 0x00, "S6 ", "Step01"}, // S6 - Step Bit 1
                                                        {NO_BANK_SWITCH, 0x10005L, 0x02, 0x00, "S7 ", "Step02"}, // S7 - Step Bit 2
                                                        {NO_BANK_SWITCH, 0x10005L, 0x04, 0x00, "S8 ", "Step04"}, // S8 - Step Bit 4
                                                        {NO_BANK_SWITCH, 0x10005L, 0x08, 0x00, "S9 ", "Step08"}, // S9 - Step Bit 8
                                                        {NO_BANK_SWITCH, 0x10005L, 0x10, 0x00, "S10", "UfoHit"}, // S10 - UFO Hit
                                                        {NO_BANK_SWITCH, 0x10005L, 0x20, 0x00, "S11", "Flip  "}, // S11 - Flip screen
                                                        {NO_BANK_SWITCH, 0x10004L, 0xFF, 0x00, "   ", "ShiftD"}, // Shift Data
                                                        {NO_BANK_SWITCH, 0x10002L, 0x07, 0x00, "   ", "ShiftC"}, // Shift Count
                                                        {NO_BANK_SWITCH, 0x10006L, 0x01, 0x00, "   ", "Wd Res"}, // Watchdog Reset
                                                        {0}
                                                      }; // end of list

//
// Custom functions implemented for this game.
//
static const CUSTOM_FUNCTION s_customFunction[] PROGMEM = { //                                            "0123456789"
                                                            {CSpaceInvadersBaseGame::testShifter,         "Test Shift"},
                                                            {NO_CUSTOM_FUNCTION}}; // end of list

CSpaceInvadersBaseGame::CSpaceInvadersBaseGame(
    const ROM_REGION    *romRegion
) : CGame( romRegion,
           s_ramRegion,
           s_ramRegionByteOnly,
           s_ramRegionWriteOnly,
           s_inputRegion,
           s_outputRegion,
           s_customFunction)
{
    m_cpu = new C8080DedicatedCpu();
    m_cpu->idle();

    //
    // Space Invaders uses INT with an external vector where the
    // vector depends on the video count triggering it
    // (0xcf and 0xd7)
    //
    m_interrupt = ICpu::IRQ0;
    m_interruptAutoVector = false;
}

CSpaceInvadersBaseGame::~CSpaceInvadersBaseGame(
)
{
    delete m_cpu;
    m_cpu = (ICpu *) NULL;
}

//
// TBD.
//
PERROR
CSpaceInvadersBaseGame::interruptCheck(
)
{
    return errorNotImplemented;
}

//
// Test the shifter circuit.
//
PERROR
CSpaceInvadersBaseGame::testShifter(
    void *context
)
{
    CSpaceInvadersBaseGame *thisGame = (CSpaceInvadersBaseGame *) context;
    PERROR error = errorNotImplemented;
    return error;
}
<commit_msg>8080: Implementation of a custom test function to test the Space Invaders shifter circuit.<commit_after>//
// Copyright (c) 2016, Paul R. Swan
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice,
//    this list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice,
//    this list of conditions and the following disclaimer in the documentation
//    and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
// OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
// COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
// TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
// EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
#include "CSpaceInvadersBaseGame.h"
#include "C8080DedicatedCpu.h"
#include "CRamCheck.h"

//
// Probe Head GND:
//   The 8080 specific probe head must be used.
//
// Watchdog Disable:
//   TBD.
//
// Board Designations:
//   's' - Sound board.
//   'c' - CPU board.
//   'r' - ROM board.
//
// CPU Compatibility Notes
//   * READY is used to hold off the CPU. This is for holding off access to the shared VRAM.
//

//
// The shifter port mappings
//
static const UINT32 s_shifterCount  = 0x10002L;
static const UINT32 s_shifterResult = 0x10003L;
static const UINT32 s_shifterData   = 0x10004L;

//
// RAM region is the same for all games on this board set.
//
static const RAM_REGION s_ramRegion[] PROGMEM = { //                                        "012", "012345"
                                                  {NO_BANK_SWITCH, 0x2000, 0x3FFF, 2, 0x01, "c33", "VRAM1A"}, // Video RAM - 1A
                                                  {NO_BANK_SWITCH, 0x2000, 0x3FFF, 2, 0x02, "c31", "VRAM2A"}, // Video RAM - 2A
                                                  {NO_BANK_SWITCH, 0x2000, 0x3FFF, 2, 0x04, "c25", "VRAM3A"}, // Video RAM - 3A
                                                  {NO_BANK_SWITCH, 0x2000, 0x3FFF, 2, 0x08, "c23", "VRAM4A"}, // Video RAM - 4A
                                                  {NO_BANK_SWITCH, 0x2000, 0x3FFF, 2, 0x10, "c21", "VRAM5A"}, // Video RAM - 5A
                                                  {NO_BANK_SWITCH, 0x2000, 0x3FFF, 2, 0x20, "c17", "VRAM6A"}, // Video RAM - 6A
                                                  {NO_BANK_SWITCH, 0x2000, 0x3FFF, 2, 0x40, "c15", "VRAM7A"}, // Video RAM - 7A
                                                  {NO_BANK_SWITCH, 0x2000, 0x3FFF, 2, 0x80, "c10", "VRAM8A"}, // Video RAM - 8A
                                                  {NO_BANK_SWITCH, 0x2001, 0x3FFF, 2, 0x01, "c32", "VRAM1B"}, // Video RAM - 1B
                                                  {NO_BANK_SWITCH, 0x2001, 0x3FFF, 2, 0x02, "c30", "VRAM2B"}, // Video RAM - 2B
                                                  {NO_BANK_SWITCH, 0x2001, 0x3FFF, 2, 0x04, "c24", "VRAM3B"}, // Video RAM - 3B
                                                  {NO_BANK_SWITCH, 0x2001, 0x3FFF, 2, 0x08, "c22", "VRAM4B"}, // Video RAM - 4B
                                                  {NO_BANK_SWITCH, 0x2001, 0x3FFF, 2, 0x10, "c20", "VRAM5B"}, // Video RAM - 5B
                                                  {NO_BANK_SWITCH, 0x2001, 0x3FFF, 2, 0x20, "c16", "VRAM6B"}, // Video RAM - 6B
                                                  {NO_BANK_SWITCH, 0x2001, 0x3FFF, 2, 0x40, "c14", "VRAM7B"}, // Video RAM - 7B
                                                  {NO_BANK_SWITCH, 0x2001, 0x3FFF, 2, 0x80, "c9 ", "VRAM8B"}, // Video RAM - 8B
                                                  {0}
                                                }; // end of list

//
// RAM region is the same for all games on this board set.
// This description is used for the byte-wide intensive random access memory test.
//
static const RAM_REGION s_ramRegionByteOnly[] PROGMEM = { //                                        "012", "012345"
                                                          {NO_BANK_SWITCH, 0x2000, 0x3FFF, 2, 0xFF, "cA ", "VRAM  "}, // Video RAM, top bank
                                                          {NO_BANK_SWITCH, 0x2001, 0x3FFF, 2, 0xFF, "cB ", "VRAM  "}, // Video RAM, bottom bank
                                                          {NO_BANK_SWITCH, 0x2000, 0x3FFF, 1, 0xFF, "cAB", "VRAM  "}, // Video RAM, both
                                                          {0}
                                                        }; // end of list

//
// No write-only RAM on this platform. Yay!
//
static const RAM_REGION s_ramRegionWriteOnly[] PROGMEM = { {0} }; // end of list

//
// Input region is the same for all games on this board set.
//
static const INPUT_REGION s_inputRegion[] PROGMEM = { //                                      "012", "012345"
                                                      {NO_BANK_SWITCH, 0x10000L,        0xFF, "   ", "IN0   "}, // Switch Inputs (IN0)
                                                      {NO_BANK_SWITCH, 0x10001L,        0xFF, "   ", "IN1   "}, // Switch Inputs (IN1)
                                                      {NO_BANK_SWITCH, 0x10002L,        0xFF, "   ", "IN2   "}, // Switch Inputs (IN2)
                                                      {NO_BANK_SWITCH, s_shifterResult, 0xFF, "   ", "ShiftR"}, // Shift Result
                                                      {0}
                                                    }; // end of list

//
// Output region is the same for all versions on this board set.
//
static const OUTPUT_REGION s_outputRegion[] PROGMEM = { //
                                                        // Note that in order to hear the sounds the Sound On bit must be high.
                                                        // Describing that in the invert mask leaves the sound always on so that
                                                        // the decay after trigger can be heard.
                                                        //
                                                        //                                           "012", "012345"
                                                        {NO_BANK_SWITCH, 0x10003L,       0x01, 0x20, "S0 ", "Ufo   "}, // S0 - SM1
                                                        {NO_BANK_SWITCH, 0x10003L,       0x02, 0x20, "S1 ", "Fire  "}, // S1 - SM2
                                                        {NO_BANK_SWITCH, 0x10003L,       0x04, 0x20, "S2 ", "BseHit"}, // S2 - SM3
                                                        {NO_BANK_SWITCH, 0x10003L,       0x08, 0x20, "S3 ", "InvHit"}, // S3 - SM4
                                                        {NO_BANK_SWITCH, 0x10003L,       0x10, 0x20, "S4 ", "Bonus "}, // S4 - SM5
                                                        {NO_BANK_SWITCH, 0x10003L,       0x20, 0x00, "S5 ", "Snd On"}, // S5 - Sound On
                                                        {NO_BANK_SWITCH, 0x10005L,       0x01, 0x00, "S6 ", "Step01"}, // S6 - Step Bit 1
                                                        {NO_BANK_SWITCH, 0x10005L,       0x02, 0x00, "S7 ", "Step02"}, // S7 - Step Bit 2
                                                        {NO_BANK_SWITCH, 0x10005L,       0x04, 0x00, "S8 ", "Step04"}, // S8 - Step Bit 4
                                                        {NO_BANK_SWITCH, 0x10005L,       0x08, 0x00, "S9 ", "Step08"}, // S9 - Step Bit 8
                                                        {NO_BANK_SWITCH, 0x10005L,       0x10, 0x00, "S10", "UfoHit"}, // S10 - UFO Hit
                                                        {NO_BANK_SWITCH, 0x10005L,       0x20, 0x00, "S11", "Flip  "}, // S11 - Flip screen
                                                        {NO_BANK_SWITCH, s_shifterData,  0xFF, 0x00, "   ", "ShiftD"}, // Shift Data
                                                        {NO_BANK_SWITCH, s_shifterCount, 0x07, 0x00, "   ", "ShiftC"}, // Shift Count
                                                        {NO_BANK_SWITCH, 0x10006L,       0x01, 0x00, "   ", "Wd Res"}, // Watchdog Reset
                                                        {0}
                                                      }; // end of list

//
// Custom functions implemented for this game.
//
static const CUSTOM_FUNCTION s_customFunction[] PROGMEM = { //                                            "0123456789"
                                                            {CSpaceInvadersBaseGame::testShifter,         "Test Shift"},
                                                            {NO_CUSTOM_FUNCTION}}; // end of list

CSpaceInvadersBaseGame::CSpaceInvadersBaseGame(
    const ROM_REGION    *romRegion
) : CGame( romRegion,
           s_ramRegion,
           s_ramRegionByteOnly,
           s_ramRegionWriteOnly,
           s_inputRegion,
           s_outputRegion,
           s_customFunction)
{
    m_cpu = new C8080DedicatedCpu();
    m_cpu->idle();

    //
    // Space Invaders uses INT with an external vector where the
    // vector depends on the video count triggering it
    // (0xcf and 0xd7)
    //
    m_interrupt = ICpu::IRQ0;
    m_interruptAutoVector = false;
}

CSpaceInvadersBaseGame::~CSpaceInvadersBaseGame(
)
{
    delete m_cpu;
    m_cpu = (ICpu *) NULL;
}

//
// TBD.
//
PERROR
CSpaceInvadersBaseGame::interruptCheck(
)
{
    return errorNotImplemented;
}

//
// Test the shifter circuit, that performs the following (from MAME):
//
// WRITE8_MEMBER( mb14241_device::shift_count_w )
// {
//   m_shift_count = ~data & 0x07;
// }
//
// WRITE8_MEMBER( mb14241_device::shift_data_w )
// {
//   m_shift_data = (m_shift_data >> 8) | ((UINT16)data << 7);
// }
//
// READ8_MEMBER( mb14241_device::shift_result_r )
// {
//   return m_shift_data >> m_shift_count;
// }
//
PERROR
CSpaceInvadersBaseGame::testShifter(
    void *context
)
{
    CSpaceInvadersBaseGame *thisGame = (CSpaceInvadersBaseGame *) context;
    C8080DedicatedCpu *cpu = thisGame->m_cpu;
    PERROR error = errorSuccess;
    UINT16 shiftData;
    UINT16 shiftCount;
    UINT16 shiftExpResult;
    UINT16 shiftRecResult;

    // Sliding 1's
    for (shiftData = 1 ; shiftData != 0 ; shiftData = (shiftData << 1))
    {
        CHECK_CPU_WRITE_EXIT(error, cpu, s_shifterData, (shiftData >> 0));
        CHECK_CPU_WRITE_EXIT(error, cpu, s_shifterData, (shiftData >> 8));

        for (shiftCount = 0 ; shiftCount < 8 ; shiftCount++)
        {
            CHECK_CPU_WRITE_EXIT(error, cpu, s_shifterCount, (~shiftCount & 0x7));
            CHECK_CPU_READ_EXIT(error, cpu, s_shifterResult, &shiftRecResult);

            shiftExpResult = (shiftData >> (shiftCount + 1)) & 0xFF;

            if (shiftRecResult != shiftExpResult)
            {
                error = errorCustom;
                error->code = ERROR_FAILED;
                error->description = "E:";
                STRING_UINT16_HEX(error->description, shiftData);
                error->description += " ";
                error->description += shiftCount;
                STRING_UINT8_HEX(error->description, shiftExpResult);
                STRING_UINT8_HEX(error->description, shiftRecResult);
                goto Exit;
            }

            CHECK_UINT8_VALUE_EXIT(error, shiftCount, shiftRecResult, shiftExpResult)
        }
    }

Exit:
    return error;
}
<|endoftext|>


<commit_before>#include "mbed.h"
#include "main.h"
#include "sx1272-hal.h"
#include "debug.h"

/* Set this flag to '1' to display debug messages on the console */
#define DEBUG_MESSAGE   0

/* Set this flag to '1' to use the LoRa modulation or to '0' to use FSK modulation */
#define USE_MODEM_LORA  1
#define USE_MODEM_FSK   !USE_MODEM_LORA

#define RF_FREQUENCY                                    868000000 // Hz
#define TX_OUTPUT_POWER                                 14        // 14 dBm

#if USE_MODEM_LORA == 1

    #define LORA_BANDWIDTH                              2         // [0: 125 kHz,
                                                                  //  1: 250 kHz,
                                                                  //  2: 500 kHz,
                                                                  //  3: Reserved]
    #define LORA_SPREADING_FACTOR                       7         // [SF7..SF12]
    #define LORA_CODINGRATE                             1         // [1: 4/5,
                                                                  //  2: 4/6,
                                                                  //  3: 4/7,
                                                                  //  4: 4/8]
    #define LORA_PREAMBLE_LENGTH                        8         // Same for Tx and Rx
    #define LORA_SYMBOL_TIMEOUT                         5         // Symbols
    #define LORA_FIX_LENGTH_PAYLOAD_ON                  false
    #define LORA_FHSS_ENABLED                           false
    #define LORA_NB_SYMB_HOP                            4
    #define LORA_IQ_INVERSION_ON                        false
    #define LORA_CRC_ENABLED                            true

#elif USE_MODEM_FSK == 1

    #define FSK_FDEV                                    25000     // Hz
    #define FSK_DATARATE                                19200     // bps
    #define FSK_BANDWIDTH                               50000     // Hz
    #define FSK_AFC_BANDWIDTH                           83333     // Hz
    #define FSK_PREAMBLE_LENGTH                         5         // Same for Tx and Rx
    #define FSK_FIX_LENGTH_PAYLOAD_ON                   false
    #define FSK_CRC_ENABLED                             true

#else
    #error "Please define a modem in the compiler options."
#endif

#define RX_TIMEOUT_VALUE                                3500000   // in us
#define BUFFER_SIZE                                     32        // Define the payload size here

#if( defined ( TARGET_KL25Z ) || defined ( TARGET_LPC11U6X ) )
DigitalOut led(LED2);
#else
DigitalOut led(LED1);
#endif

/*
 *  Global variables declarations
 */
typedef RadioState States_t;
volatile States_t State = LOWPOWER;

SX1272MB1xAS Radio( OnTxDone, OnTxTimeout, OnRxDone, OnRxTimeout, OnRxError, NULL, NULL );

const uint8_t PingMsg[] = "PING";
const uint8_t PongMsg[] = "PONG";

uint16_t BufferSize = BUFFER_SIZE;
uint8_t Buffer[BUFFER_SIZE];

int16_t RssiValue = 0.0;
int8_t SnrValue = 0.0;

void radioRegistersPrint()
{
	printf("--REGS--\n\r");
	for (int i = REG_OPMODE; i <= REG_PLL; ++i)
	{
		printf("REG %.2x = %.2x\r\n", i, Radio.Read(i));
	}
}

int main()
{
    uint8_t i;
    bool isMaster = true;

    debug( "\n\n\r     SX1276 Ping Pong Demo Application \n\n\r" );

    // verify the connection with the board
    while( Radio.Read( REG_VERSION ) == 0x00  )
    {
        debug( "Radio could not be detected!\n\r", NULL );
        wait( 1 );
    }

    Radio.SetChannel( RF_FREQUENCY );

#if USE_MODEM_LORA == 1

    debug_if( LORA_FHSS_ENABLED, "\n\n\r             > LORA FHSS Mode < \n\n\r");
    debug_if( !LORA_FHSS_ENABLED, "\n\n\r             > LORA Mode < \n\n\r");

    Radio.SetTxConfig( MODEM_LORA, TX_OUTPUT_POWER, 0, LORA_BANDWIDTH,
                         LORA_SPREADING_FACTOR, LORA_CODINGRATE,
                         LORA_PREAMBLE_LENGTH, LORA_FIX_LENGTH_PAYLOAD_ON,
                         LORA_CRC_ENABLED, LORA_FHSS_ENABLED, LORA_NB_SYMB_HOP,
                         LORA_IQ_INVERSION_ON, 2000000 );

    Radio.SetRxConfig( MODEM_LORA, LORA_BANDWIDTH, LORA_SPREADING_FACTOR,
                         LORA_CODINGRATE, 0, LORA_PREAMBLE_LENGTH,
                         LORA_SYMBOL_TIMEOUT, LORA_FIX_LENGTH_PAYLOAD_ON, 0,
                         LORA_CRC_ENABLED, LORA_FHSS_ENABLED, LORA_NB_SYMB_HOP,
                         LORA_IQ_INVERSION_ON, true );

#elif USE_MODEM_FSK == 1

    debug("\n\n\r              > FSK Mode < \n\n\r");
    Radio.SetTxConfig( MODEM_FSK, TX_OUTPUT_POWER, FSK_FDEV, 0,
                         FSK_DATARATE, 0,
                         FSK_PREAMBLE_LENGTH, FSK_FIX_LENGTH_PAYLOAD_ON,
                         FSK_CRC_ENABLED, 0, 0, 0, 2000000 );

    Radio.SetRxConfig( MODEM_FSK, FSK_BANDWIDTH, FSK_DATARATE,
                         0, FSK_AFC_BANDWIDTH, FSK_PREAMBLE_LENGTH,
                         0, FSK_FIX_LENGTH_PAYLOAD_ON, 0, FSK_CRC_ENABLED,
                         0, 0, false, true );

#else

#error "Please define a modem in the compiler options."

#endif

    debug_if( DEBUG_MESSAGE, "Starting Ping-Pong loop\r\n" );

    led = 0;

    Radio.Rx( RX_TIMEOUT_VALUE );

    while( 1 )
    {
        switch( State )
        {
        case RX:
            if( isMaster == true )
            {
                if( BufferSize > 0 )
                {
                    if( strncmp( ( const char* )Buffer, ( const char* )PongMsg, 4 ) == 0 )
                    {
                        led = !led;
                        debug( "...Pong\r\n" );
                        // Send the next PING frame
                        strcpy( ( char* )Buffer, ( char* )PingMsg );
                        // We fill the buffer with numbers for the payload
                        for( i = 4; i < BufferSize; i++ )
                        {
                            Buffer[i] = i - 4;
                        }
                        wait_ms( 10 );
                        Radio.Send( Buffer, BufferSize );
                    }
                    else if( strncmp( ( const char* )Buffer, ( const char* )PingMsg, 4 ) == 0 )
                    { // A master already exists then become a slave
                        debug( "...Ping\r\n" );
                        led = !led;
                        isMaster = false;
                        // Send the next PONG frame
                        strcpy( ( char* )Buffer, ( char* )PongMsg );
                        // We fill the buffer with numbers for the payload
                        for( i = 4; i < BufferSize; i++ )
                        {
                            Buffer[i] = i - 4;
                        }
                        wait_ms( 10 );
                        Radio.Send( Buffer, BufferSize );
                    }
                    else // valid reception but neither a PING or a PONG message
                    {    // Set device as master ans start again
                        isMaster = true;
                        Radio.Rx( RX_TIMEOUT_VALUE );
                    }
                }
            }
            else
            {
                if( BufferSize > 0 )
                {
                    if( strncmp( ( const char* )Buffer, ( const char* )PingMsg, 4 ) == 0 )
                    {
                        led = !led;
                        debug( "...Ping\r\n" );
                        // Send the reply to the PING string
                        strcpy( ( char* )Buffer, ( char* )PongMsg );
                        // We fill the buffer with numbers for the payload
                        for( i = 4; i < BufferSize; i++ )
                        {
                            Buffer[i] = i - 4;
                        }
                        wait_ms( 10 );
                        Radio.Send( Buffer, BufferSize );
                    }
                    else // valid reception but not a PING as expected
                    {    // Set device as master and start again
                        isMaster = true;
                        Radio.Rx( RX_TIMEOUT_VALUE );
                    }
                }
            }
            State = LOWPOWER;
            break;
        case TX:
            led = !led;
            if( isMaster == true )
            {
                debug( "Ping...\r\n" );
            }
            else
            {
                debug( "Pong...\r\n" );
            }
            Radio.Rx( RX_TIMEOUT_VALUE );
            State = LOWPOWER;
            break;
        case RX_TIMEOUT:
            if( isMaster == true )
            {
                // Send the next PING frame
                strcpy( ( char* )Buffer, ( char* )PingMsg );
                for( i = 4; i < BufferSize; i++ )
                {
                    Buffer[i] = i - 4;
                }
                wait_ms( 10 );
                Radio.Send( Buffer, BufferSize );
            }
            else
            {
                Radio.Rx( RX_TIMEOUT_VALUE );
            }
            State = LOWPOWER;
            break;
        case RX_ERROR:
            // We have received a Packet with a CRC error, send reply as if packet was correct
            if( isMaster == true )
            {
                // Send the next PING frame
                strcpy( ( char* )Buffer, ( char* )PingMsg );
                for( i = 4; i < BufferSize; i++ )
                {
                    Buffer[i] = i - 4;
                }
                wait_ms( 10 );
                Radio.Send( Buffer, BufferSize );
            }
            else
            {
                // Send the next PONG frame
                strcpy( ( char* )Buffer, ( char* )PongMsg );
                for( i = 4; i < BufferSize; i++ )
                {
                    Buffer[i] = i - 4;
                }
                wait_ms( 10 );
                Radio.Send( Buffer, BufferSize );
            }
            State = LOWPOWER;
            break;
        case TX_TIMEOUT:
            Radio.Rx( RX_TIMEOUT_VALUE );
            State = LOWPOWER;
            break;
        case LOWPOWER:
            break;
        default:
            State = LOWPOWER;
            break;
        }
    }
}

void OnTxDone( void )
{
    Radio.Sleep( );
    State = TX;
    debug_if( DEBUG_MESSAGE, "> OnTxDone\n\r" );
}

void OnRxDone( uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr)
{
    Radio.Sleep( );
    BufferSize = size;
    memcpy( Buffer, payload, BufferSize );
    RssiValue = rssi;
    SnrValue = snr;
    State = RX;
    debug_if( DEBUG_MESSAGE, "> OnRxDone\n\r" );
}

void OnTxTimeout( void )
{
    Radio.Sleep( );
    State = TX_TIMEOUT;
    debug_if( DEBUG_MESSAGE, "> OnTxTimeout\n\r" );
}

void OnRxTimeout( void )
{
    Radio.Sleep( );
    Buffer[ BufferSize ] = 0;
    State = RX_TIMEOUT;
    debug_if( DEBUG_MESSAGE, "> OnRxTimeout\n\r" );
}

void OnRxError( void )
{
    Radio.Sleep( );
    State = RX_ERROR;
    debug_if( DEBUG_MESSAGE, "> OnRxError\n\r" );
}

<commit_msg>fixed SX1272MB1xAS constructor<commit_after>#include "mbed.h"
#include "main.h"
#include "sx1272-hal.h"
#include "debug.h"

/* Set this flag to '1' to display debug messages on the console */
#define DEBUG_MESSAGE   0

/* Set this flag to '1' to use the LoRa modulation or to '0' to use FSK modulation */
#define USE_MODEM_LORA  1
#define USE_MODEM_FSK   !USE_MODEM_LORA

#define RF_FREQUENCY                                    868000000 // Hz
#define TX_OUTPUT_POWER                                 14        // 14 dBm

#if USE_MODEM_LORA == 1

    #define LORA_BANDWIDTH                              2         // [0: 125 kHz,
                                                                  //  1: 250 kHz,
                                                                  //  2: 500 kHz,
                                                                  //  3: Reserved]
    #define LORA_SPREADING_FACTOR                       7         // [SF7..SF12]
    #define LORA_CODINGRATE                             1         // [1: 4/5,
                                                                  //  2: 4/6,
                                                                  //  3: 4/7,
                                                                  //  4: 4/8]
    #define LORA_PREAMBLE_LENGTH                        8         // Same for Tx and Rx
    #define LORA_SYMBOL_TIMEOUT                         5         // Symbols
    #define LORA_FIX_LENGTH_PAYLOAD_ON                  false
    #define LORA_FHSS_ENABLED                           false
    #define LORA_NB_SYMB_HOP                            4
    #define LORA_IQ_INVERSION_ON                        false
    #define LORA_CRC_ENABLED                            true

#elif USE_MODEM_FSK == 1

    #define FSK_FDEV                                    25000     // Hz
    #define FSK_DATARATE                                19200     // bps
    #define FSK_BANDWIDTH                               50000     // Hz
    #define FSK_AFC_BANDWIDTH                           83333     // Hz
    #define FSK_PREAMBLE_LENGTH                         5         // Same for Tx and Rx
    #define FSK_FIX_LENGTH_PAYLOAD_ON                   false
    #define FSK_CRC_ENABLED                             true

#else
    #error "Please define a modem in the compiler options."
#endif

#define RX_TIMEOUT_VALUE                                3500000   // in us
#define BUFFER_SIZE                                     32        // Define the payload size here

#if( defined ( TARGET_KL25Z ) || defined ( TARGET_LPC11U6X ) )
DigitalOut led(LED2);
#else
DigitalOut led(LED1);
#endif

/*
 *  Global variables declarations
 */
typedef RadioState States_t;
volatile States_t State = LOWPOWER;

SX1272MB1xAS Radio( OnTxDone, OnTxTimeout, OnRxDone, OnRxTimeout, OnRxError, NULL, NULL,
               RF_SPI_MOSI, RF_SPI_MISO, RF_SPI_SCK, RF_SPI_CS,
               RF_RESET, RF_DIO0, RF_DIO1, RF_DIO2, RF_DIO3, RF_DIO4, RF_DIO5, RF_RXTX_SW );

const uint8_t PingMsg[] = "PING";
const uint8_t PongMsg[] = "PONG";

uint16_t BufferSize = BUFFER_SIZE;
uint8_t Buffer[BUFFER_SIZE];

int16_t RssiValue = 0.0;
int8_t SnrValue = 0.0;

void radioRegistersPrint()
{
	printf("--REGS--\n\r");
	for (int i = REG_OPMODE; i <= REG_PLL; ++i)
	{
		printf("REG %.2x = %.2x\r\n", i, Radio.Read(i));
	}
}

int main()
{
    uint8_t i;
    bool isMaster = true;

    debug( "\n\n\r     SX1276 Ping Pong Demo Application \n\n\r" );

    // verify the connection with the board
    while( Radio.Read( REG_VERSION ) == 0x00  )
    {
        debug( "Radio could not be detected!\n\r", NULL );
        wait( 1 );
    }

    Radio.SetChannel( RF_FREQUENCY );

#if USE_MODEM_LORA == 1

    debug_if( LORA_FHSS_ENABLED, "\n\n\r             > LORA FHSS Mode < \n\n\r");
    debug_if( !LORA_FHSS_ENABLED, "\n\n\r             > LORA Mode < \n\n\r");

    Radio.SetTxConfig( MODEM_LORA, TX_OUTPUT_POWER, 0, LORA_BANDWIDTH,
                         LORA_SPREADING_FACTOR, LORA_CODINGRATE,
                         LORA_PREAMBLE_LENGTH, LORA_FIX_LENGTH_PAYLOAD_ON,
                         LORA_CRC_ENABLED, LORA_FHSS_ENABLED, LORA_NB_SYMB_HOP,
                         LORA_IQ_INVERSION_ON, 2000000 );

    Radio.SetRxConfig( MODEM_LORA, LORA_BANDWIDTH, LORA_SPREADING_FACTOR,
                         LORA_CODINGRATE, 0, LORA_PREAMBLE_LENGTH,
                         LORA_SYMBOL_TIMEOUT, LORA_FIX_LENGTH_PAYLOAD_ON, 0,
                         LORA_CRC_ENABLED, LORA_FHSS_ENABLED, LORA_NB_SYMB_HOP,
                         LORA_IQ_INVERSION_ON, true );

#elif USE_MODEM_FSK == 1

    debug("\n\n\r              > FSK Mode < \n\n\r");
    Radio.SetTxConfig( MODEM_FSK, TX_OUTPUT_POWER, FSK_FDEV, 0,
                         FSK_DATARATE, 0,
                         FSK_PREAMBLE_LENGTH, FSK_FIX_LENGTH_PAYLOAD_ON,
                         FSK_CRC_ENABLED, 0, 0, 0, 2000000 );

    Radio.SetRxConfig( MODEM_FSK, FSK_BANDWIDTH, FSK_DATARATE,
                         0, FSK_AFC_BANDWIDTH, FSK_PREAMBLE_LENGTH,
                         0, FSK_FIX_LENGTH_PAYLOAD_ON, 0, FSK_CRC_ENABLED,
                         0, 0, false, true );

#else

#error "Please define a modem in the compiler options."

#endif

    debug_if( DEBUG_MESSAGE, "Starting Ping-Pong loop\r\n" );

    led = 0;

    Radio.Rx( RX_TIMEOUT_VALUE );

    while( 1 )
    {
        switch( State )
        {
        case RX:
            if( isMaster == true )
            {
                if( BufferSize > 0 )
                {
                    if( strncmp( ( const char* )Buffer, ( const char* )PongMsg, 4 ) == 0 )
                    {
                        led = !led;
                        debug( "...Pong\r\n" );
                        // Send the next PING frame
                        strcpy( ( char* )Buffer, ( char* )PingMsg );
                        // We fill the buffer with numbers for the payload
                        for( i = 4; i < BufferSize; i++ )
                        {
                            Buffer[i] = i - 4;
                        }
                        wait_ms( 10 );
                        Radio.Send( Buffer, BufferSize );
                    }
                    else if( strncmp( ( const char* )Buffer, ( const char* )PingMsg, 4 ) == 0 )
                    { // A master already exists then become a slave
                        debug( "...Ping\r\n" );
                        led = !led;
                        isMaster = false;
                        // Send the next PONG frame
                        strcpy( ( char* )Buffer, ( char* )PongMsg );
                        // We fill the buffer with numbers for the payload
                        for( i = 4; i < BufferSize; i++ )
                        {
                            Buffer[i] = i - 4;
                        }
                        wait_ms( 10 );
                        Radio.Send( Buffer, BufferSize );
                    }
                    else // valid reception but neither a PING or a PONG message
                    {    // Set device as master ans start again
                        isMaster = true;
                        Radio.Rx( RX_TIMEOUT_VALUE );
                    }
                }
            }
            else
            {
                if( BufferSize > 0 )
                {
                    if( strncmp( ( const char* )Buffer, ( const char* )PingMsg, 4 ) == 0 )
                    {
                        led = !led;
                        debug( "...Ping\r\n" );
                        // Send the reply to the PING string
                        strcpy( ( char* )Buffer, ( char* )PongMsg );
                        // We fill the buffer with numbers for the payload
                        for( i = 4; i < BufferSize; i++ )
                        {
                            Buffer[i] = i - 4;
                        }
                        wait_ms( 10 );
                        Radio.Send( Buffer, BufferSize );
                    }
                    else // valid reception but not a PING as expected
                    {    // Set device as master and start again
                        isMaster = true;
                        Radio.Rx( RX_TIMEOUT_VALUE );
                    }
                }
            }
            State = LOWPOWER;
            break;
        case TX:
            led = !led;
            if( isMaster == true )
            {
                debug( "Ping...\r\n" );
            }
            else
            {
                debug( "Pong...\r\n" );
            }
            Radio.Rx( RX_TIMEOUT_VALUE );
            State = LOWPOWER;
            break;
        case RX_TIMEOUT:
            if( isMaster == true )
            {
                // Send the next PING frame
                strcpy( ( char* )Buffer, ( char* )PingMsg );
                for( i = 4; i < BufferSize; i++ )
                {
                    Buffer[i] = i - 4;
                }
                wait_ms( 10 );
                Radio.Send( Buffer, BufferSize );
            }
            else
            {
                Radio.Rx( RX_TIMEOUT_VALUE );
            }
            State = LOWPOWER;
            break;
        case RX_ERROR:
            // We have received a Packet with a CRC error, send reply as if packet was correct
            if( isMaster == true )
            {
                // Send the next PING frame
                strcpy( ( char* )Buffer, ( char* )PingMsg );
                for( i = 4; i < BufferSize; i++ )
                {
                    Buffer[i] = i - 4;
                }
                wait_ms( 10 );
                Radio.Send( Buffer, BufferSize );
            }
            else
            {
                // Send the next PONG frame
                strcpy( ( char* )Buffer, ( char* )PongMsg );
                for( i = 4; i < BufferSize; i++ )
                {
                    Buffer[i] = i - 4;
                }
                wait_ms( 10 );
                Radio.Send( Buffer, BufferSize );
            }
            State = LOWPOWER;
            break;
        case TX_TIMEOUT:
            Radio.Rx( RX_TIMEOUT_VALUE );
            State = LOWPOWER;
            break;
        case LOWPOWER:
            break;
        default:
            State = LOWPOWER;
            break;
        }
    }
}

void OnTxDone( void )
{
    Radio.Sleep( );
    State = TX;
    debug_if( DEBUG_MESSAGE, "> OnTxDone\n\r" );
}

void OnRxDone( uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr)
{
    Radio.Sleep( );
    BufferSize = size;
    memcpy( Buffer, payload, BufferSize );
    RssiValue = rssi;
    SnrValue = snr;
    State = RX;
    debug_if( DEBUG_MESSAGE, "> OnRxDone\n\r" );
}

void OnTxTimeout( void )
{
    Radio.Sleep( );
    State = TX_TIMEOUT;
    debug_if( DEBUG_MESSAGE, "> OnTxTimeout\n\r" );
}

void OnRxTimeout( void )
{
    Radio.Sleep( );
    Buffer[ BufferSize ] = 0;
    State = RX_TIMEOUT;
    debug_if( DEBUG_MESSAGE, "> OnRxTimeout\n\r" );
}

void OnRxError( void )
{
    Radio.Sleep( );
    State = RX_ERROR;
    debug_if( DEBUG_MESSAGE, "> OnRxError\n\r" );
}

<|endoftext|>


<commit_before>/* +---------------------------------------------------------------------------+
   |                     Mobile Robot Programming Toolkit (MRPT)               |
   |                          http://www.mrpt.org/                             |
   |                                                                           |
   | Copyright (c) 2005-2014, Individual contributors, see AUTHORS file        |
   | See: http://www.mrpt.org/Authors - All rights reserved.                   |
   | Released under BSD License. See details in http://www.mrpt.org/License    |
   +---------------------------------------------------------------------------+ */

#include "base-precomp.h"  // Precompiled headers

#include <mrpt/poses/CPose2D.h>
#include <mrpt/poses/CPose3D.h>
#include <mrpt/poses/CRobot2DPoseEstimator.h>

using namespace mrpt;
using namespace mrpt::poses;
using namespace mrpt::math;
using namespace mrpt::utils;
using namespace mrpt::synch;
using namespace mrpt::system;
using namespace std;

/* --------------------------------------------------------
				Ctor
   -------------------------------------------------------- */
CRobot2DPoseEstimator::CRobot2DPoseEstimator()
{
	reset();
}

/* --------------------------------------------------------
				Dtor
   -------------------------------------------------------- */
CRobot2DPoseEstimator::~CRobot2DPoseEstimator()
{
}

/* --------------------------------------------------------
				reset
   -------------------------------------------------------- */
void CRobot2DPoseEstimator::reset()
{
	CCriticalSectionLocker   lock(&m_cs);

	m_last_loc_time	= INVALID_TIMESTAMP;
	m_last_odo_time	= INVALID_TIMESTAMP;

	m_last_loc		= TPose2D(0,0,0);
	m_loc_odo_ref	= TPose2D(0,0,0);
	m_last_odo		= TPose2D(0,0,0);

	m_robot_v    = 0;
	m_robot_w    = 0;
}

/** Updates the filter so the pose is tracked to the current time */
void CRobot2DPoseEstimator::processUpdateNewPoseLocalization(
	const TPose2D &newPose,
	const CMatrixDouble33 &newPoseCov,
	TTimeStamp cur_tim)
{
	CCriticalSectionLocker   lock(&m_cs);

	// Overwrite old localization data:
	m_last_loc_time	= cur_tim;
	m_last_loc		= newPose;
	m_last_loc_cov  = newPoseCov;

	// And create interpolated odometry data to work as "reference pose":
	if (m_last_odo_time!=INVALID_TIMESTAMP)
	{
		const double dT = timeDifference(m_last_odo_time,cur_tim);
		extrapolateRobotPose(
			m_last_odo,m_robot_v,m_robot_w,
			dT,
			m_loc_odo_ref);
	}
}

/** Updates the filter so the pose is tracked to the current time */
void CRobot2DPoseEstimator::processUpdateNewOdometry(
	const TPose2D &newGlobalOdometry,
	TTimeStamp cur_tim,
	bool hasVelocities,
	float v,
	float w)
{
	MRPT_START

	CCriticalSectionLocker   lock(&m_cs);

	if (m_last_odo_time!=INVALID_TIMESTAMP)
	{
		const double dT = timeDifference(m_last_odo_time,cur_tim);
		if (dT<=0) std::cerr << "[CRobot2DPoseEstimator::processUpdateNewOdometry] WARNING: Diff. in timestamps between odometry should be >0, and it's " << dT << "\n";
	}

	// First, update velocities:
	if (hasVelocities)
	{
		m_robot_v = v;
		m_robot_w = w;
	}
	else
	{
		if (m_last_odo_time!=INVALID_TIMESTAMP)
		{
			// make something up!
			const double dT = timeDifference(m_last_odo_time,cur_tim);
			ASSERTMSG_(dT>0, "timestamp must be newer than the last one")

			m_robot_w = (newGlobalOdometry.phi-m_last_odo.phi)/dT;
			m_robot_v = ::hypot(newGlobalOdometry.x-m_last_odo.x, newGlobalOdometry.y-m_last_odo.y)/dT;
			// sign of v:
			if (fabs(atan2(newGlobalOdometry.y-m_last_odo.y,newGlobalOdometry.x-m_last_odo.x))>0.5*M_PI)
				m_robot_v *=-1;
		}
		else
		{	// Nothing we can do here...
			m_robot_v = 0;
			m_robot_w = 0;
		}
	}

	// And now times & odo:
	m_last_odo_time = cur_tim;
	m_last_odo		= newGlobalOdometry;

	MRPT_END
}

/** get the current estimate
* \return true is the estimate can be trusted. False if the real observed data is too old.
*/
bool CRobot2DPoseEstimator::getCurrentEstimate(
	TPose2D &pose, float &v, float &w,
	TTimeStamp tim_query
	) const
{
	if (m_last_odo_time==INVALID_TIMESTAMP || m_last_loc_time==INVALID_TIMESTAMP )
		return false;

	const double dTimeLoc = timeDifference(m_last_loc_time,tim_query);
	if (dTimeLoc>params.max_localiz_age)
		return false;

	// Constant speed model:
	v = m_robot_v;
	w = m_robot_w;

	//  Overall estimate:
	// last_loc (+) [ last_odo (-) odo_ref ] (+) extrapolation_from_vw
	const TPose2D p = TPose2D(  CPose2D(m_last_loc) + ( CPose2D(m_last_odo) - CPose2D(m_loc_odo_ref) ) );

	// Add the extrapolation:
	const double dTimeOdo = timeDifference(m_last_odo_time,tim_query);
	if (dTimeOdo >params.max_odometry_age)
		return false;

	extrapolateRobotPose(
		p,m_robot_v,m_robot_w,
		dTimeOdo,
		pose);

	return true;
}

/** get the current estimate
* \return true is the estimate can be trusted. False if the real observed data is too old.
*/
bool CRobot2DPoseEstimator::getLatestRobotPose(TPose2D &pose) const
{
	if (m_last_odo_time==INVALID_TIMESTAMP && m_last_loc_time==INVALID_TIMESTAMP )
		return false;

	bool ret_odo;
	if (m_last_odo_time!=INVALID_TIMESTAMP && m_last_loc_time!=INVALID_TIMESTAMP)
			ret_odo = (m_last_odo_time>m_last_loc_time);
	else if (m_last_odo_time!=INVALID_TIMESTAMP)
			ret_odo=true;
	else 	ret_odo=false;

	if (ret_odo)
		pose= CPose2D(m_last_loc) + ( CPose2D(m_last_odo) - CPose2D(m_loc_odo_ref) );
	else
		pose= m_last_loc;

	return true;
}

// An auxiliary method to extrapolate the pose of a robot located at "p"
//  with velocities (v,w) after a time delay "delta_time".
void CRobot2DPoseEstimator::extrapolateRobotPose(
	const TPose2D &p,
	const float v,
	const float w,
	const double delta_time,
	TPose2D &new_p)
{
	if (v==0 && w==0)
	{	// Still
		new_p = p;
	}
	else
	if (w==0)
	{	// Straight
		const double len = delta_time*v;
		new_p.x = p.x + cos(p.phi)*len;
		new_p.y = p.y + sin(p.phi)*len;
		new_p.phi = p.phi;
	}
	else
	{
		// generic arc:
		const double R = v/w; // Radius
		const double theta = w*delta_time; // traversed arc
		const double cc = cos(p.phi);
		const double ss = sin(p.phi);

		const double arc_x = R*sin(theta);
		const double arc_y = R*(1-cos(theta));

		new_p.x = p.x + cc*arc_x - ss*arc_y;
		new_p.y = p.y + ss*arc_x + cc*arc_y;
		new_p.phi = p.phi + theta;
	}
}

bool CRobot2DPoseEstimator::getCurrentEstimate( mrpt::poses::CPose2D &pose, float &v, float &w, mrpt::system::TTimeStamp tim_query) const
{
	mrpt::math::TPose2D  p;
	bool ret = getCurrentEstimate(p,v,w,tim_query);
	if (ret)
		pose = CPose2D(p);
	return ret;
}

bool CRobot2DPoseEstimator::getLatestRobotPose(CPose2D &pose) const
{
	mrpt::math::TPose2D p;
	bool v = getLatestRobotPose(p);
	if (v)
	{
		pose.x(p.x);
		pose.y(p.y);
		pose.phi(p.phi);
	}
	return v;
}
<commit_msg>CRobot2DPoseEstimator: Fix potential bug in w estimation<commit_after>/* +---------------------------------------------------------------------------+
   |                     Mobile Robot Programming Toolkit (MRPT)               |
   |                          http://www.mrpt.org/                             |
   |                                                                           |
   | Copyright (c) 2005-2014, Individual contributors, see AUTHORS file        |
   | See: http://www.mrpt.org/Authors - All rights reserved.                   |
   | Released under BSD License. See details in http://www.mrpt.org/License    |
   +---------------------------------------------------------------------------+ */

#include "base-precomp.h"  // Precompiled headers

#include <mrpt/poses/CPose2D.h>
#include <mrpt/poses/CPose3D.h>
#include <mrpt/poses/CRobot2DPoseEstimator.h>
#include <mrpt/math/wrap2pi.h>

using namespace mrpt;
using namespace mrpt::poses;
using namespace mrpt::math;
using namespace mrpt::utils;
using namespace mrpt::synch;
using namespace mrpt::system;
using namespace std;

/* --------------------------------------------------------
				Ctor
   -------------------------------------------------------- */
CRobot2DPoseEstimator::CRobot2DPoseEstimator()
{
	reset();
}

/* --------------------------------------------------------
				Dtor
   -------------------------------------------------------- */
CRobot2DPoseEstimator::~CRobot2DPoseEstimator()
{
}

/* --------------------------------------------------------
				reset
   -------------------------------------------------------- */
void CRobot2DPoseEstimator::reset()
{
	CCriticalSectionLocker   lock(&m_cs);

	m_last_loc_time	= INVALID_TIMESTAMP;
	m_last_odo_time	= INVALID_TIMESTAMP;

	m_last_loc		= TPose2D(0,0,0);
	m_loc_odo_ref	= TPose2D(0,0,0);
	m_last_odo		= TPose2D(0,0,0);

	m_robot_v    = 0;
	m_robot_w    = 0;
}

/** Updates the filter so the pose is tracked to the current time */
void CRobot2DPoseEstimator::processUpdateNewPoseLocalization(
	const TPose2D &newPose,
	const CMatrixDouble33 &newPoseCov,
	TTimeStamp cur_tim)
{
	CCriticalSectionLocker   lock(&m_cs);

	// Overwrite old localization data:
	m_last_loc_time	= cur_tim;
	m_last_loc		= newPose;
	m_last_loc_cov  = newPoseCov;

	// And create interpolated odometry data to work as "reference pose":
	if (m_last_odo_time!=INVALID_TIMESTAMP)
	{
		const double dT = timeDifference(m_last_odo_time,cur_tim);
		extrapolateRobotPose(
			m_last_odo,m_robot_v,m_robot_w,
			dT,
			m_loc_odo_ref);
	}
}

/** Updates the filter so the pose is tracked to the current time */
void CRobot2DPoseEstimator::processUpdateNewOdometry(
	const TPose2D &newGlobalOdometry,
	TTimeStamp cur_tim,
	bool hasVelocities,
	float v,
	float w)
{
	MRPT_START

	CCriticalSectionLocker   lock(&m_cs);

	if (m_last_odo_time!=INVALID_TIMESTAMP)
	{
		const double dT = timeDifference(m_last_odo_time,cur_tim);
		if (dT<=0) std::cerr << "[CRobot2DPoseEstimator::processUpdateNewOdometry] WARNING: Diff. in timestamps between odometry should be >0, and it's " << dT << "\n";
	}

	// First, update velocities:
	if (hasVelocities)
	{
		m_robot_v = v;
		m_robot_w = w;
	}
	else
	{
		if (m_last_odo_time!=INVALID_TIMESTAMP)
		{
			// make something up!
			const double dT = timeDifference(m_last_odo_time,cur_tim);
			ASSERTMSG_(dT>0, "timestamp must be newer than the last one")

			m_robot_w = mrpt::math::angDistance(m_last_odo.phi,newGlobalOdometry.phi)/dT;
			m_robot_v = ::hypot(newGlobalOdometry.x-m_last_odo.x, newGlobalOdometry.y-m_last_odo.y)/dT;
			// sign of v:
			if (fabs(atan2(newGlobalOdometry.y-m_last_odo.y,newGlobalOdometry.x-m_last_odo.x))>0.5*M_PI)
				m_robot_v *=-1;
		}
		else
		{	// Nothing we can do here...
			m_robot_v = 0;
			m_robot_w = 0;
		}
	}

	// And now times & odo:
	m_last_odo_time = cur_tim;
	m_last_odo		= newGlobalOdometry;

	MRPT_END
}

/** get the current estimate
* \return true is the estimate can be trusted. False if the real observed data is too old.
*/
bool CRobot2DPoseEstimator::getCurrentEstimate(
	TPose2D &pose, float &v, float &w,
	TTimeStamp tim_query
	) const
{
	if (m_last_odo_time==INVALID_TIMESTAMP || m_last_loc_time==INVALID_TIMESTAMP )
		return false;

	const double dTimeLoc = timeDifference(m_last_loc_time,tim_query);
	if (dTimeLoc>params.max_localiz_age)
		return false;

	// Constant speed model:
	v = m_robot_v;
	w = m_robot_w;

	//  Overall estimate:
	// last_loc (+) [ last_odo (-) odo_ref ] (+) extrapolation_from_vw
	const TPose2D p = TPose2D(  CPose2D(m_last_loc) + ( CPose2D(m_last_odo) - CPose2D(m_loc_odo_ref) ) );

	// Add the extrapolation:
	const double dTimeOdo = timeDifference(m_last_odo_time,tim_query);
	if (dTimeOdo >params.max_odometry_age)
		return false;

	extrapolateRobotPose(
		p,m_robot_v,m_robot_w,
		dTimeOdo,
		pose);

	return true;
}

/** get the current estimate
* \return true is the estimate can be trusted. False if the real observed data is too old.
*/
bool CRobot2DPoseEstimator::getLatestRobotPose(TPose2D &pose) const
{
	if (m_last_odo_time==INVALID_TIMESTAMP && m_last_loc_time==INVALID_TIMESTAMP )
		return false;

	bool ret_odo;
	if (m_last_odo_time!=INVALID_TIMESTAMP && m_last_loc_time!=INVALID_TIMESTAMP)
			ret_odo = (m_last_odo_time>m_last_loc_time);
	else if (m_last_odo_time!=INVALID_TIMESTAMP)
			ret_odo=true;
	else 	ret_odo=false;

	if (ret_odo)
		pose= CPose2D(m_last_loc) + ( CPose2D(m_last_odo) - CPose2D(m_loc_odo_ref) );
	else
		pose= m_last_loc;

	return true;
}

// An auxiliary method to extrapolate the pose of a robot located at "p"
//  with velocities (v,w) after a time delay "delta_time".
void CRobot2DPoseEstimator::extrapolateRobotPose(
	const TPose2D &p,
	const float v,
	const float w,
	const double delta_time,
	TPose2D &new_p)
{
	if (v==0 && w==0)
	{	// Still
		new_p = p;
	}
	else
	if (w==0)
	{	// Straight
		const double len = delta_time*v;
		new_p.x = p.x + cos(p.phi)*len;
		new_p.y = p.y + sin(p.phi)*len;
		new_p.phi = p.phi;
	}
	else
	{
		// generic arc:
		const double R = v/w; // Radius
		const double theta = w*delta_time; // traversed arc
		const double cc = cos(p.phi);
		const double ss = sin(p.phi);

		const double arc_x = R*sin(theta);
		const double arc_y = R*(1-cos(theta));

		new_p.x = p.x + cc*arc_x - ss*arc_y;
		new_p.y = p.y + ss*arc_x + cc*arc_y;
		new_p.phi = p.phi + theta;
	}
}

bool CRobot2DPoseEstimator::getCurrentEstimate( mrpt::poses::CPose2D &pose, float &v, float &w, mrpt::system::TTimeStamp tim_query) const
{
	mrpt::math::TPose2D  p;
	bool ret = getCurrentEstimate(p,v,w,tim_query);
	if (ret)
		pose = CPose2D(p);
	return ret;
}

bool CRobot2DPoseEstimator::getLatestRobotPose(CPose2D &pose) const
{
	mrpt::math::TPose2D p;
	bool v = getLatestRobotPose(p);
	if (v)
	{
		pose.x(p.x);
		pose.y(p.y);
		pose.phi(p.phi);
	}
	return v;
}
<|endoftext|>


<commit_before>r##"#pragma once

//for std::abort
#include <cstdlib>
//for std::move
#include <utility>
//for std::conditional
#include <type_traits>

#include "rust_str.h"

#include "c_BtAddr.h"

namespace org_examples {

template<bool>
class BtAddrWrapper;
using BtAddr = BtAddrWrapper<true>;
using BtAddrRef = BtAddrWrapper<false>;

template<bool OWN_DATA>
class BtAddrWrapper {
public:"##;
<commit_msg>update test case to expect cassert header<commit_after>r##"#pragma once

//for assert
#include <cassert>
//for std::abort
#include <cstdlib>
//for std::move
#include <utility>
//for std::conditional
#include <type_traits>

#include "rust_str.h"

#include "c_BtAddr.h"

namespace org_examples {

template<bool>
class BtAddrWrapper;
using BtAddr = BtAddrWrapper<true>;
using BtAddrRef = BtAddrWrapper<false>;

template<bool OWN_DATA>
class BtAddrWrapper {
public:"##;
<|endoftext|>


<commit_before>#include "Math/Cartesian3D.h"
#include "Math/Point3D.h"
#include "Math/Vector3D.h"
#include "Math/Vector4D.h"
#include "Math/GenVector/Rotation3D.h"
#include "Math/GenVector/EulerAngles.h"
#include "Math/GenVector/AxisAngle.h"
#include "Math/GenVector/Quaternion.h"
#include "Math/GenVector/RotationX.h"
#include "Math/GenVector/RotationY.h"
#include "Math/GenVector/RotationZ.h"
#include "Math/GenVector/RotationZYX.h"
#include "Math/GenVector/LorentzRotation.h"
#include "Math/GenVector/Boost.h"
#include "Math/GenVector/BoostX.h"
#include "Math/GenVector/BoostY.h"
#include "Math/GenVector/BoostZ.h"
#include "Math/GenVector/Transform3D.h"
#include "Math/GenVector/Plane3D.h"
#include "Math/GenVector/VectorUtil.h"

#include "Math/Math_vectypes.hxx"

#include "benchmark/benchmark.h"

#include <random>

static bool is_aligned(const void *__restrict__ ptr, size_t align)
{
   return (uintptr_t)ptr % align == 0;
}

template <typename T>
using Point = ROOT::Math::PositionVector3D<ROOT::Math::Cartesian3D<T>, ROOT::Math::DefaultCoordinateSystemTag>;
template <typename T>
using Vector = ROOT::Math::DisplacementVector3D<ROOT::Math::Cartesian3D<T>, ROOT::Math::DefaultCoordinateSystemTag>;
template <typename T>
using Plane = ROOT::Math::Impl::Plane3D<T>;

static std::default_random_engine ggen;

static std::uniform_real_distribution<double> p_x(1, 2), p_y(2, 3), p_z(3, 4);
static std::uniform_real_distribution<double> d_x(1, 2), d_y(2, 3), d_z(3, 4);
static std::uniform_real_distribution<double> c_x(1, 2), c_y(2, 3), c_z(3, 4);
static std::uniform_real_distribution<double> p0(-0.002, 0.002), p1(-0.2, 0.2), p2(0.97, 0.99), p3(-1300, 1300);

static void BM_Cartesian3D_CreateEmpty(benchmark::State &state)
{
   while (state.KeepRunning()) ROOT::Math::Cartesian3D<ROOT::Double_v> c;
}
BENCHMARK(BM_Cartesian3D_CreateEmpty);

template <typename T>
static void BM_Cartesian3D_Theta(benchmark::State &state)
{
   ROOT::Math::Cartesian3D<T> c(1., 2., 3.);
   // std::cout << is_aligned(&c, 16) << std::endl;
   while (state.KeepRunning()) c.Theta();
}
BENCHMARK_TEMPLATE(BM_Cartesian3D_Theta, double)->Range(8, 8 << 10)->Complexity(benchmark::o1);
BENCHMARK_TEMPLATE(BM_Cartesian3D_Theta, ROOT::Double_v)->Range(8, 8 << 10)->Complexity(benchmark::o1);
BENCHMARK_TEMPLATE(BM_Cartesian3D_Theta, float)->Range(8, 8 << 10)->Complexity(benchmark::o1);
BENCHMARK_TEMPLATE(BM_Cartesian3D_Theta, ROOT::Float_v)->Range(8, 8 << 10)->Complexity(benchmark::o1);

template <typename T>
static void BM_Cartesian3D_Phi(benchmark::State &state)
{
   ROOT::Math::Cartesian3D<T> c(1., 2., 3.);
   // std::cout << is_aligned(&c, 16) << std::endl;
   while (state.KeepRunning()) c.Phi();
   state.SetComplexityN(state.range(0));
}
BENCHMARK_TEMPLATE(BM_Cartesian3D_Phi, double)->Range(8, 8 << 10)->Complexity(benchmark::o1);
BENCHMARK_TEMPLATE(BM_Cartesian3D_Phi, ROOT::Double_v)->Range(8, 8 << 10)->Complexity(benchmark::o1);
BENCHMARK_TEMPLATE(BM_Cartesian3D_Phi, float)->Range(8, 8 << 10)->Complexity(benchmark::o1);
BENCHMARK_TEMPLATE(BM_Cartesian3D_Phi, ROOT::Float_v)->Range(8, 8 << 10)->Complexity(benchmark::o1);

template <typename T>
static void BM_Cartesian3D_Mag2(benchmark::State &state)
{

   ROOT::Math::Cartesian3D<T> c(1., 2., 3.);
   // std::cout << is_aligned(&c, 16) << std::endl;
   while (state.KeepRunning()) c.Mag2();
}
BENCHMARK_TEMPLATE(BM_Cartesian3D_Mag2, double)->Range(8, 8 << 10)->Complexity(benchmark::o1);
BENCHMARK_TEMPLATE(BM_Cartesian3D_Mag2, ROOT::Double_v)->Range(8, 8 << 10)->Complexity(benchmark::o1);

template <typename T>
static void BM_Point3D(benchmark::State &state)
{
   while (state.KeepRunning()) Point<T> sp1, sp2, sp3, sp4, sp5, sp6;
}

BENCHMARK_TEMPLATE(BM_Point3D, double)->Range(8, 8 << 10)->Complexity(benchmark::o1);
BENCHMARK_TEMPLATE(BM_Point3D, ROOT::Double_v)->Range(8, 8 << 10)->Complexity(benchmark::o1);

template <typename T>
static void BM_Point3D_Gen(benchmark::State &state)
{
   while (state.KeepRunning()) {
      Point<T> sp1(p_x(ggen), p_y(ggen), p_z(ggen));
   }
}
BENCHMARK_TEMPLATE(BM_Point3D_Gen, double)->Range(8, 8 << 10)->Complexity(benchmark::o1);
BENCHMARK_TEMPLATE(BM_Point3D_Gen, ROOT::Double_v)->Range(8, 8 << 10)->Complexity(benchmark::o1);

template <typename T>
static void BM_Transform3D(benchmark::State &state)
{
   Point<T> sp1(p_x(ggen), p_y(ggen), p_z(ggen));
   Point<T> sp2(p_x(ggen), p_y(ggen), p_z(ggen));
   Point<T> sp3(p_x(ggen), p_y(ggen), p_z(ggen));
   Point<T> sp4(p_x(ggen), p_y(ggen), p_z(ggen));
   Point<T> sp5(p_x(ggen), p_y(ggen), p_z(ggen));
   Point<T> sp6(p_x(ggen), p_y(ggen), p_z(ggen));
   while (state.KeepRunning()) {
      ROOT::Math::Impl::Transform3D<T> st(sp1, sp2, sp3, sp4, sp5, sp6);
      st.Translation();
   }
}
// BENCHMARK_TEMPLATE(BM_Transform3D, double)->Range(8, 8<<10)->Complexity(benchmark::o1);
// BENCHMARK_TEMPLATE(BM_Transform3D, float)->Range(8, 8<<10)->Complexity(benchmark::o1);
// BENCHMARK_TEMPLATE(BM_Transform3D, ROOT::Double_v)->Range(8, 8<<10)->Complexity(benchmark::o1);
// BENCHMARK_TEMPLATE(BM_Transform3D, ROOT::Float_v)->Range(8, 8<<10)->Complexity(benchmark::o1);

template <typename T>
static void BM_Plane3D(benchmark::State &state)
{
   const double a(p0(ggen)), b(p1(ggen)), c(p2(ggen)), d(p3(ggen));
   while (state.KeepRunning()) {
      Plane<T> sc_plane(a, b, c, d);
   }
}
BENCHMARK_TEMPLATE(BM_Plane3D, double)->Range(8, 8 << 10)->Complexity(benchmark::o1);
BENCHMARK_TEMPLATE(BM_Plane3D, ROOT::Double_v)->Range(8, 8 << 10)->Complexity(benchmark::o1);
BENCHMARK_TEMPLATE(BM_Plane3D, ROOT::Float_v)->Range(8, 8 << 10)->Complexity(benchmark::o1);

template <typename T>
static void BM_Plane3D_Hessian(benchmark::State &state)
{
   const double a(p0(ggen)), b(p1(ggen)), c(p2(ggen)), d(p3(ggen));
   while (state.KeepRunning()) {
      Plane<T> sc_plane(a, b, c, d);
      sc_plane.HesseDistance();
   }
}
BENCHMARK_TEMPLATE(BM_Plane3D_Hessian, double)->Range(8, 8 << 10)->Complexity(benchmark::o1);
BENCHMARK_TEMPLATE(BM_Plane3D_Hessian, ROOT::Double_v)->Range(8, 8 << 10)->Complexity(benchmark::o1);

template <typename T>
static void BM_Plane3D_Normal(benchmark::State &state)
{
   const double a(p0(ggen)), b(p1(ggen)), c(p2(ggen)), d(p3(ggen));
   while (state.KeepRunning()) {
      Plane<T> sc_plane(a, b, c, d);
      sc_plane.Normal();
   }
}
BENCHMARK_TEMPLATE(BM_Plane3D_Normal, double)->Range(8, 8 << 10)->Complexity(benchmark::o1);
;
BENCHMARK_TEMPLATE(BM_Plane3D_Normal, ROOT::Double_v)->Range(8, 8 << 10)->Complexity(benchmark::o1);
BENCHMARK_TEMPLATE(BM_Plane3D_Normal, ROOT::Float_v)->Range(8, 8 << 10)->Complexity(benchmark::o1);

// Define our main.
BENCHMARK_MAIN();
<commit_msg>Revert "Add missing include."<commit_after>#include "Math/Cartesian3D.h"
#include "Math/Point3D.h"
#include "Math/Vector3D.h"
#include "Math/Vector4D.h"
#include "Math/GenVector/Rotation3D.h"
#include "Math/GenVector/EulerAngles.h"
#include "Math/GenVector/AxisAngle.h"
#include "Math/GenVector/Quaternion.h"
#include "Math/GenVector/RotationX.h"
#include "Math/GenVector/RotationY.h"
#include "Math/GenVector/RotationZ.h"
#include "Math/GenVector/RotationZYX.h"
#include "Math/GenVector/LorentzRotation.h"
#include "Math/GenVector/Boost.h"
#include "Math/GenVector/BoostX.h"
#include "Math/GenVector/BoostY.h"
#include "Math/GenVector/BoostZ.h"
#include "Math/GenVector/Transform3D.h"
#include "Math/GenVector/Plane3D.h"
#include "Math/GenVector/VectorUtil.h"

#include "Math/Math_vectypes.hxx"

#include "benchmark/benchmark.h"

static bool is_aligned(const void *__restrict__ ptr, size_t align)
{
   return (uintptr_t)ptr % align == 0;
}

template <typename T>
using Point = ROOT::Math::PositionVector3D<ROOT::Math::Cartesian3D<T>, ROOT::Math::DefaultCoordinateSystemTag>;
template <typename T>
using Vector = ROOT::Math::DisplacementVector3D<ROOT::Math::Cartesian3D<T>, ROOT::Math::DefaultCoordinateSystemTag>;
template <typename T>
using Plane = ROOT::Math::Impl::Plane3D<T>;

static std::default_random_engine ggen;

static std::uniform_real_distribution<double> p_x(1, 2), p_y(2, 3), p_z(3, 4);
static std::uniform_real_distribution<double> d_x(1, 2), d_y(2, 3), d_z(3, 4);
static std::uniform_real_distribution<double> c_x(1, 2), c_y(2, 3), c_z(3, 4);
static std::uniform_real_distribution<double> p0(-0.002, 0.002), p1(-0.2, 0.2), p2(0.97, 0.99), p3(-1300, 1300);

static void BM_Cartesian3D_CreateEmpty(benchmark::State &state)
{
   while (state.KeepRunning()) ROOT::Math::Cartesian3D<ROOT::Double_v> c;
}
BENCHMARK(BM_Cartesian3D_CreateEmpty);

template <typename T>
static void BM_Cartesian3D_Theta(benchmark::State &state)
{
   ROOT::Math::Cartesian3D<T> c(1., 2., 3.);
   // std::cout << is_aligned(&c, 16) << std::endl;
   while (state.KeepRunning()) c.Theta();
}
BENCHMARK_TEMPLATE(BM_Cartesian3D_Theta, double)->Range(8, 8 << 10)->Complexity(benchmark::o1);
BENCHMARK_TEMPLATE(BM_Cartesian3D_Theta, ROOT::Double_v)->Range(8, 8 << 10)->Complexity(benchmark::o1);
BENCHMARK_TEMPLATE(BM_Cartesian3D_Theta, float)->Range(8, 8 << 10)->Complexity(benchmark::o1);
BENCHMARK_TEMPLATE(BM_Cartesian3D_Theta, ROOT::Float_v)->Range(8, 8 << 10)->Complexity(benchmark::o1);

template <typename T>
static void BM_Cartesian3D_Phi(benchmark::State &state)
{
   ROOT::Math::Cartesian3D<T> c(1., 2., 3.);
   // std::cout << is_aligned(&c, 16) << std::endl;
   while (state.KeepRunning()) c.Phi();
   state.SetComplexityN(state.range(0));
}
BENCHMARK_TEMPLATE(BM_Cartesian3D_Phi, double)->Range(8, 8 << 10)->Complexity(benchmark::o1);
BENCHMARK_TEMPLATE(BM_Cartesian3D_Phi, ROOT::Double_v)->Range(8, 8 << 10)->Complexity(benchmark::o1);
BENCHMARK_TEMPLATE(BM_Cartesian3D_Phi, float)->Range(8, 8 << 10)->Complexity(benchmark::o1);
BENCHMARK_TEMPLATE(BM_Cartesian3D_Phi, ROOT::Float_v)->Range(8, 8 << 10)->Complexity(benchmark::o1);

template <typename T>
static void BM_Cartesian3D_Mag2(benchmark::State &state)
{

   ROOT::Math::Cartesian3D<T> c(1., 2., 3.);
   // std::cout << is_aligned(&c, 16) << std::endl;
   while (state.KeepRunning()) c.Mag2();
}
BENCHMARK_TEMPLATE(BM_Cartesian3D_Mag2, double)->Range(8, 8 << 10)->Complexity(benchmark::o1);
BENCHMARK_TEMPLATE(BM_Cartesian3D_Mag2, ROOT::Double_v)->Range(8, 8 << 10)->Complexity(benchmark::o1);

template <typename T>
static void BM_Point3D(benchmark::State &state)
{
   while (state.KeepRunning()) Point<T> sp1, sp2, sp3, sp4, sp5, sp6;
}

BENCHMARK_TEMPLATE(BM_Point3D, double)->Range(8, 8 << 10)->Complexity(benchmark::o1);
BENCHMARK_TEMPLATE(BM_Point3D, ROOT::Double_v)->Range(8, 8 << 10)->Complexity(benchmark::o1);

template <typename T>
static void BM_Point3D_Gen(benchmark::State &state)
{
   while (state.KeepRunning()) {
      Point<T> sp1(p_x(ggen), p_y(ggen), p_z(ggen));
   }
}
BENCHMARK_TEMPLATE(BM_Point3D_Gen, double)->Range(8, 8 << 10)->Complexity(benchmark::o1);
BENCHMARK_TEMPLATE(BM_Point3D_Gen, ROOT::Double_v)->Range(8, 8 << 10)->Complexity(benchmark::o1);

template <typename T>
static void BM_Transform3D(benchmark::State &state)
{
   Point<T> sp1(p_x(ggen), p_y(ggen), p_z(ggen));
   Point<T> sp2(p_x(ggen), p_y(ggen), p_z(ggen));
   Point<T> sp3(p_x(ggen), p_y(ggen), p_z(ggen));
   Point<T> sp4(p_x(ggen), p_y(ggen), p_z(ggen));
   Point<T> sp5(p_x(ggen), p_y(ggen), p_z(ggen));
   Point<T> sp6(p_x(ggen), p_y(ggen), p_z(ggen));
   while (state.KeepRunning()) {
      ROOT::Math::Impl::Transform3D<T> st(sp1, sp2, sp3, sp4, sp5, sp6);
      st.Translation();
   }
}
// BENCHMARK_TEMPLATE(BM_Transform3D, double)->Range(8, 8<<10)->Complexity(benchmark::o1);
// BENCHMARK_TEMPLATE(BM_Transform3D, float)->Range(8, 8<<10)->Complexity(benchmark::o1);
// BENCHMARK_TEMPLATE(BM_Transform3D, ROOT::Double_v)->Range(8, 8<<10)->Complexity(benchmark::o1);
// BENCHMARK_TEMPLATE(BM_Transform3D, ROOT::Float_v)->Range(8, 8<<10)->Complexity(benchmark::o1);

template <typename T>
static void BM_Plane3D(benchmark::State &state)
{
   const double a(p0(ggen)), b(p1(ggen)), c(p2(ggen)), d(p3(ggen));
   while (state.KeepRunning()) {
      Plane<T> sc_plane(a, b, c, d);
   }
}
BENCHMARK_TEMPLATE(BM_Plane3D, double)->Range(8, 8 << 10)->Complexity(benchmark::o1);
BENCHMARK_TEMPLATE(BM_Plane3D, ROOT::Double_v)->Range(8, 8 << 10)->Complexity(benchmark::o1);
BENCHMARK_TEMPLATE(BM_Plane3D, ROOT::Float_v)->Range(8, 8 << 10)->Complexity(benchmark::o1);

template <typename T>
static void BM_Plane3D_Hessian(benchmark::State &state)
{
   const double a(p0(ggen)), b(p1(ggen)), c(p2(ggen)), d(p3(ggen));
   while (state.KeepRunning()) {
      Plane<T> sc_plane(a, b, c, d);
      sc_plane.HesseDistance();
   }
}
BENCHMARK_TEMPLATE(BM_Plane3D_Hessian, double)->Range(8, 8 << 10)->Complexity(benchmark::o1);
BENCHMARK_TEMPLATE(BM_Plane3D_Hessian, ROOT::Double_v)->Range(8, 8 << 10)->Complexity(benchmark::o1);

template <typename T>
static void BM_Plane3D_Normal(benchmark::State &state)
{
   const double a(p0(ggen)), b(p1(ggen)), c(p2(ggen)), d(p3(ggen));
   while (state.KeepRunning()) {
      Plane<T> sc_plane(a, b, c, d);
      sc_plane.Normal();
   }
}
BENCHMARK_TEMPLATE(BM_Plane3D_Normal, double)->Range(8, 8 << 10)->Complexity(benchmark::o1);
;
BENCHMARK_TEMPLATE(BM_Plane3D_Normal, ROOT::Double_v)->Range(8, 8 << 10)->Complexity(benchmark::o1);
BENCHMARK_TEMPLATE(BM_Plane3D_Normal, ROOT::Float_v)->Range(8, 8 << 10)->Complexity(benchmark::o1);

// Define our main.
BENCHMARK_MAIN();
<|endoftext|>


<commit_before>#include "Crown.h"
#include "Terrain.h"
#include "FPSSystem.h"
#include "Game.h"

using namespace crown;

class WndCtrl: public KeyboardListener
{
public:

	WndCtrl()
	{
		device()->input_manager()->register_keyboard_listener(this);
	}

	void key_released(const KeyboardEvent& event)
	{
		if (event.key == KC_ESCAPE)
		{
			device()->stop();
		}
	}
};

class MainScene
{

public:

	MainScene() :
		optShowSkybox(true),
		optShowCrate(true),
		optShowTerrain(true),
		camera_active(true)
	{
		mouseRightPressed = false;
		mouseLeftPressed = false;
	}

	~MainScene()
	{
	}

	void poll_input()
	{
		Keyboard* keyb = device()->keyboard();
		Mouse* mouse = device()->mouse();

		if (keyb->key_pressed(KC_1))
		{
			terrain.PlotCircle(2, 2, 2, 2);
		}

		if (keyb->key_pressed(KC_2))
		{
			terrain.PlotCircle(4, 4, 4, 2);
		}

		if (keyb->key_pressed(KC_3))
		{
			terrain.PlotCircle(8, 8, 8, 2);
		}

		if (keyb->key_pressed(KC_F5))
		{
			device()->reload(grass);
		}

		if (keyb->key_pressed(KC_SPACE))
		{
			camera_active = !camera_active;
		}

		mouseLeftPressed = mouse->button_pressed(MB_LEFT);
		mouseRightPressed = mouse->button_pressed(MB_RIGHT);
	}

	void on_load()
	{
		crown::Renderer* renderer = crown::device()->renderer();

		Vec3 start = Vec3(0.0f, 10.0f, 0.0f);

		// Add a movable camera
		cam = CE_NEW(m_allocator, Camera)(start, 90.0f, 1.6f);
		system = CE_NEW(m_allocator, FPSSystem)(cam, 10.0f, 2.5f);

		terrain.CreateTerrain(64, 64, 1, 0.0f);
		terrain.PlotCircle(4, 4, 4, 2);
		terrain.UpdateVertexBuffer(true);

		// red_north = device()->load("textures/red_north.tga");
		// red_south = device()->load("textures/red_south.tga");
		// red_east  = device()->load("textures/red_east.tga");
		// red_west  = device()->load("textures/red_west.tga");
		// red_up    = device()->load("textures/red_up.tga");
		// red_down  = device()->load("textures/red_down.tga");
		grass     	 = device()->load("textures/grass.tga");

		device()->resource_manager()->flush();

		TextureResource* grass_texture = (TextureResource*)device()->data(grass);
		grass_id = device()->renderer()->create_texture(grass_texture->width(), grass_texture->height(), grass_texture->format(), grass_texture->data());
	}

	void on_unload()
	{
		device()->unload(grass);

		device()->unload(red_north);
		device()->unload(red_south);
		device()->unload(red_east);
		device()->unload(red_west);
		device()->unload(red_up);
		device()->unload(red_down);

		CE_DELETE(m_allocator, system);
		CE_DELETE(m_allocator, cam);
	}

	void update(float dt)
	{
		poll_input();

		Renderer* renderer = device()->renderer();

		renderer->set_clear_color(Color4::LIGHTBLUE);

		if (camera_active)
		{
			system->set_view_by_cursor();
		}
		system->update(dt);

		renderer->set_texturing(0, false);

		ray.set_origin(cam->position());
		ray.set_direction(cam->look_at());

		/* Render the terrain */
		renderer->set_ambient_light(Color4(0.5f, 0.5f, 0.5f, 1.0f));

		renderer->set_matrix(MT_MODEL, Mat4::IDENTITY);

		if (device()->is_loaded(grass))
		{
			renderer->set_texturing(0, true);
			renderer->bind_texture(0, grass_id);
		}

		terrain.Render();

		/* Test for intersection */
		Triangle tri, tri2;
		float dist;
		if (terrain.TraceRay(ray, tri, tri2, dist))
		{
			renderer->set_depth_test(false);
			Vec3 intersectionPoint = ray.origin() + (ray.direction() * dist);
			if (mouseLeftPressed)
			{
				terrain.ApplyBrush(intersectionPoint, 0.09f);
				terrain.UpdateVertexBuffer(true);
			}
			if (mouseRightPressed)
			{
				terrain.ApplyBrush(intersectionPoint, -0.09f);
				terrain.UpdateVertexBuffer(true);
			}
			renderer->set_depth_test(true);
		}
	}

private:

	HeapAllocator m_allocator;
	FPSSystem* system;
	Camera* cam;
	Mat4 ortho;
	Terrain terrain;

	// Resources
	ResourceId grass;
	ResourceId red_north;
	ResourceId red_south;
	ResourceId red_east;
	ResourceId red_west;
	ResourceId red_up;
	ResourceId red_down;
	TextureId grass_id;
	RenderBufferId rb_id;
	VertexShaderId vs_id;
	PixelShaderId ps_id;
	GPUProgramId gpu_program_id;

	ResourceId script;

	bool optShowSkybox;
	bool optShowCrate;
	bool optShowTerrain;
	bool mouseLeftPressed;
	bool mouseRightPressed;
	float wheel;
	bool camera_active;
	Ray ray;
};

MainScene m_scene;
WndCtrl m_ctrl;

} // namespace crown

void init()
{
	crown::m_scene.on_load();
}
void shutdown()
{
	crown::m_scene.on_unload();
}

void frame(float dt)
{
	crown::m_scene.update(dt);
}

<commit_msg>TODO: find the function that cause error 998(vs)<commit_after>#include "Crown.h"
#include "Terrain.h"
#include "FPSSystem.h"
#include "Game.h"

using namespace crown;

class WndCtrl: public KeyboardListener
{
public:

	//WndCtrl()
	//{
	//	device()->input_manager()->register_keyboard_listener(this);
	//}

	//void key_released(const KeyboardEvent& event)
	//{
	//	if (event.key == KC_ESCAPE)
	//	{
	//		device()->stop();
	//	}
	//}
};

class MainScene
{

public:

	//MainScene() :
	//	optShowSkybox(true),
	//	optShowCrate(true),
	//	optShowTerrain(true),
	//	camera_active(true)
	//{
	//	mouseRightPressed = false;
	//	mouseLeftPressed = false;
	//}

	//~MainScene()
	//{
	//}

	//void poll_input()
	//{
	//	Keyboard* keyb = device()->keyboard();
	//	Mouse* mouse = device()->mouse();

	//	if (keyb->key_pressed(KC_1))
	//	{
	//		terrain.PlotCircle(2, 2, 2, 2);
	//	}

	//	if (keyb->key_pressed(KC_2))
	//	{
	//		terrain.PlotCircle(4, 4, 4, 2);
	//	}

	//	if (keyb->key_pressed(KC_3))
	//	{
	//		terrain.PlotCircle(8, 8, 8, 2);
	//	}

	//	if (keyb->key_pressed(KC_F5))
	//	{
	//		device()->reload(grass);
	//	}

	//	if (keyb->key_pressed(KC_SPACE))
	//	{
	//		camera_active = !camera_active;
	//	}

	//	mouseLeftPressed = mouse->button_pressed(MB_LEFT);
	//	mouseRightPressed = mouse->button_pressed(MB_RIGHT);
	//}
	//
	//void on_load()
	//{
	//	crown::Renderer* renderer = crown::device()->renderer();
	//
	//	Vec3 start = Vec3(0.0f, 10.0f, 0.0f);

	//	// Add a movable camera
	//	cam = CE_NEW(m_allocator, Camera)(start, 90.0f, 1.6f);
	//	system = CE_NEW(m_allocator, FPSSystem)(cam, 10.0f, 2.5f);

	//	terrain.CreateTerrain(64, 64, 1, 0.0f);
	//	terrain.PlotCircle(4, 4, 4, 2);
	//	terrain.UpdateVertexBuffer(true);

	//	// red_north = device()->load("textures/red_north.tga");
	//	// red_south = device()->load("textures/red_south.tga");
	//	// red_east  = device()->load("textures/red_east.tga");
	//	// red_west  = device()->load("textures/red_west.tga");
	//	// red_up    = device()->load("textures/red_up.tga");
	//	// red_down  = device()->load("textures/red_down.tga");
	//	grass     	 = device()->load("textures/grass.tga");

	//	device()->resource_manager()->flush();

	//	TextureResource* grass_texture = (TextureResource*)device()->data(grass);
	//	grass_id = device()->renderer()->create_texture(grass_texture->width(), grass_texture->height(), grass_texture->format(), grass_texture->data());
	//}

	//void on_unload()
	//{
	//	device()->unload(grass);

	//	device()->unload(red_north);
	//	device()->unload(red_south);
	//	device()->unload(red_east);
	//	device()->unload(red_west);
	//	device()->unload(red_up);
	//	device()->unload(red_down);

	//	CE_DELETE(m_allocator, system);
	//	CE_DELETE(m_allocator, cam);
	//}

	//void update(float dt)
	//{
	//	poll_input();

	//	Renderer* renderer = device()->renderer();

	//	renderer->set_clear_color(Color4::LIGHTBLUE);
	//
	//	if (camera_active)
	//	{
	//		system->set_view_by_cursor();
	//	}
	//	system->update(dt);

	//	renderer->set_texturing(0, false);

	//	ray.set_origin(cam->position());
	//	ray.set_direction(cam->look_at());

	//	/* Render the terrain */
	//	renderer->set_ambient_light(Color4(0.5f, 0.5f, 0.5f, 1.0f));

	//	renderer->set_matrix(MT_MODEL, Mat4::IDENTITY);

	//	if (device()->is_loaded(grass))
	//	{
	//		renderer->set_texturing(0, true);
	//		renderer->bind_texture(0, grass_id);
	//	}

	//	terrain.Render();

	//	/* Test for intersection */
	//	Triangle tri, tri2;
	//	float dist;
	//	if (terrain.TraceRay(ray, tri, tri2, dist))
	//	{
	//		renderer->set_depth_test(false);
	//		Vec3 intersectionPoint = ray.origin() + (ray.direction() * dist);
	//		if (mouseLeftPressed)
	//		{
	//			terrain.ApplyBrush(intersectionPoint, 0.09f);
	//			terrain.UpdateVertexBuffer(true);
	//		}
	//		if (mouseRightPressed)
	//		{
	//			terrain.ApplyBrush(intersectionPoint, -0.09f);
	//			terrain.UpdateVertexBuffer(true);
	//		}
	//		renderer->set_depth_test(true);
	//	}
	//}

//private:

	//HeapAllocator m_allocator;
	//FPSSystem* system;
	//Camera* cam;
	//Mat4 ortho;
	//Terrain terrain;

	//// Resources
	//ResourceId grass;
	//ResourceId red_north;
	//ResourceId red_south;
	//ResourceId red_east;
	//ResourceId red_west;
	//ResourceId red_up;
	//ResourceId red_down;
	//TextureId grass_id;
	//RenderBufferId rb_id;
	//VertexShaderId vs_id;
	//PixelShaderId ps_id;
	//GPUProgramId gpu_program_id;

	//ResourceId script;

	//bool optShowSkybox;
	//bool optShowCrate;
	//bool optShowTerrain;
	//bool mouseLeftPressed;
	//bool mouseRightPressed;
	//float wheel;
	//bool camera_active;
	//Ray ray;
public:
	inline void dumb_func()
	{
		if (device()->is_init())
		{
			os::printf("SEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n");
		}
	}
};

MainScene m_scene;
//WndCtrl m_ctrl;

void init()
{
	//m_scene.on_load();
	m_scene.dumb_func();
}
void shutdown_1()
{
	//m_scene.on_unload();
}

void frame(float dt)
{
	//m_scene.update(dt);
}

<|endoftext|>