<commit_before>/*
    OpenDeck MIDI platform firmware
    Copyright (C) 2015-2018 Igor Petrovic

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include "interface/Interface.h"
#include "Version.h"

MIDI midi;
bool processingEnabled;

void init()
{
    board.init();
    database.init();
    sysEx.init();

    #if defined(BOARD_OPEN_DECK) || defined(BOARD_A_LEO) || defined(BOARD_A_PRO_MICRO) || defined(BOARD_T_2PP)
    midi.setUSBMIDIstate(true);
    #endif

    #if defined(BOARD_OPEN_DECK) || defined(BOARD_A_LEO) || defined(BOARD_A_PRO_MICRO) || defined(BOARD_T_2PP)
    midi.setDINMIDIstate(database.read(DB_BLOCK_MIDI, dbSection_midi_feature, midiFeatureDinEnabled));
    #endif

    #ifdef BOARD_A_MEGA
    //always enable (for now)
    midi.setDINMIDIstate(true);
    #endif

    #ifdef BOARD_A_UNO
    //always enable
    midi.setDINMIDIstate(true);
    #endif

    midi.setOneByteParseDINstate(true);
    midi.setInputChannel(MIDI_CHANNEL_OMNI);
    midi.setNoteOffMode((noteOffType_t)database.read(DB_BLOCK_MIDI, dbSection_midi_feature, midiFeatureStandardNoteOff));
    midi.setRunningStatusState(database.read(DB_BLOCK_MIDI, dbSection_midi_feature, midiFeatureRunningStatus));
    midi.setChannelSendZeroStart(true);

    #if !defined(BOARD_A_MEGA) && !defined(BOARD_A_UNO)
    board.ledFlashStartup(board.checkNewRevision());
    #endif

    //enable global interrupts
    sei();

    leds.init();

    #ifdef DISPLAY_SUPPORTED
    if (database.read(DB_BLOCK_DISPLAY, dbSection_display_features, displayFeatureEnable))
    {
        display.init((displayController_t)database.read(DB_BLOCK_DISPLAY, dbSection_display_hw, displayHwController), (displayResolution_t)database.read(DB_BLOCK_DISPLAY, dbSection_display_hw, displayHwResolution));
        display.displayHome();
        display.setRetentionState(database.read(DB_BLOCK_DISPLAY, dbSection_display_features, displayFeatureMIDIeventRetention));
        display.setRetentionTime(database.read(DB_BLOCK_DISPLAY, dbSection_display_features, displayFeatureMIDIeventTime) * 1000);
    }
    #endif

    processingEnabled = true;
}

int main()
{
    init();

    while(1)
    {
        #if defined(BOARD_A_LEO) || defined(BOARD_OPEN_DECK) || defined(BOARD_A_PRO_MICRO) || defined(BOARD_T_2PP)
        if (midi.read(usbInterface))
        {
            //new message on usb
            midiMessageType_t messageType = midi.getType(usbInterface);
            uint8_t data1 = midi.getData1(usbInterface);
            uint8_t data2 = midi.getData2(usbInterface);
            uint8_t channel = midi.getChannel(usbInterface);

            switch(messageType)
            {
                case midiMessageSystemExclusive:
                sysEx.handleMessage(midi.getSysExArray(usbInterface), midi.getSysExArrayLength(usbInterface));
                break;

                case midiMessageNoteOn:
                //we're using received note data to control LED color
                leds.noteToState(data1, data2, channel);
                #ifdef DISPLAY_SUPPORTED
                display.displayMIDIevent(displayEventIn, midiMessageNoteOn_display, data1, data2, channel+1);
                #endif
                break;

                case midiMessageNoteOff:
                //always turn led off when note off is received
                leds.noteToState(data1, 0, channel);
                #ifdef DISPLAY_SUPPORTED
                display.displayMIDIevent(displayEventIn, midiMessageNoteOff_display, data1, data2, channel+1);
                #endif
                break;

                case midiMessageControlChange:
                //control change is used to control led blinking
                leds.ccToBlink(data1, data2, channel);
                #ifdef DISPLAY_SUPPORTED
                display.displayMIDIevent(displayEventIn, midiMessageControlChange_display, data1, data2, channel+1);
                #endif
                break;

                default:
                break;
            }
        }
        #endif

        #if !defined(BOARD_A_MEGA) && !defined(BOARD_A_UNO)
        if (midi.getDINMIDIstate())
        {
            //check for incoming MIDI messages on USART
            if (!database.read(DB_BLOCK_MIDI, dbSection_midi_feature, midiFeatureMergeEnabled))
            {
                midi.read(dinInterface);
                midiMessageType_t messageType = midi.getType(dinInterface);
                uint8_t data1 = midi.getData1(dinInterface);
                uint8_t data2 = midi.getData2(dinInterface);
                uint8_t channel = midi.getChannel(dinInterface);

                switch(messageType)
                {
                    case midiMessageNoteOn:
                    //we're using received note data to control LED color
                    leds.noteToState(data1, data2, channel);
                    #ifdef DISPLAY_SUPPORTED
                    display.displayMIDIevent(displayEventIn, midiMessageNoteOn_display, data1, data2, channel+1);
                    #endif
                    break;

                    case midiMessageNoteOff:
                    //always turn led off when note off is received
                    leds.noteToState(data1, 0, channel);
                    #ifdef DISPLAY_SUPPORTED
                    display.displayMIDIevent(displayEventIn, midiMessageNoteOff_display, data1, data2, channel+1);
                    #endif
                    break;

                    case midiMessageControlChange:
                    //control change is used to control led blinking
                    leds.ccToBlink(data1, data2, channel);
                    #ifdef DISPLAY_SUPPORTED
                    display.displayMIDIevent(displayEventIn, midiMessageControlChange_display, data1, data2, channel+1);
                    #endif
                    break;

                    default:
                    break;
                }
            }
            else
            {
                switch(database.read(DB_BLOCK_MIDI, dbSection_midi_merge, midiMergeInterface))
                {
                    case midiMergeInterfaceUSB:
                    //dump everything from MIDI in to USB MIDI out
                    midi.read(dinInterface, THRU_FULL_USB);
                    break;

                    case midiMergeInterfaceDIN:
                    //dump everything from MIDI in to MIDI out
                    midi.read(dinInterface, THRU_FULL_DIN);
                    break;

                    case midiMergeInterfaceAll:
                    //dump everything from MIDI in to USB MIDI out and MIDI out
                    midi.read(dinInterface, THRU_FULL_ALL);
                    break;

                    default:
                    break;
                }
            }
        }
        #endif

        #if defined(BOARD_A_MEGA) || defined(BOARD_A_UNO)
        //din interface here is actually translated usb traffic from 16u2
        if (midi.read(dinInterface))
        {
            midiMessageType_t messageType = midi.getType(dinInterface);
            uint8_t data1 = midi.getData1(dinInterface);
            uint8_t data2 = midi.getData2(dinInterface);
            uint8_t channel = midi.getChannel(dinInterface);

            switch(messageType)
            {
                case midiMessageSystemExclusive:
                sysEx.handleMessage(midi.getSysExArray(dinInterface), midi.getSysExArrayLength(dinInterface));
                break;

                case midiMessageNoteOn:
                //we're using received note data to control LED color
                leds.noteToState(data1, data2, channel);
                #ifdef DISPLAY_SUPPORTED
                display.displayMIDIevent(displayEventIn, midiMessageNoteOn_display, data1, data2, channel+1);
                #endif
                break;

                case midiMessageNoteOff:
                //always turn led off when note off is received
                leds.noteToState(data1, 0, channel);
                #ifdef DISPLAY_SUPPORTED
                display.displayMIDIevent(displayEventIn, midiMessageNoteOff_display, data1, data2, channel+1);
                #endif
                break;

                case midiMessageControlChange:
                //control change is used to control led blinking
                leds.ccToBlink(data1, data2, channel);
                #ifdef DISPLAY_SUPPORTED
                display.displayMIDIevent(displayEventIn, midiMessageControlChange_display, data1, data2, channel+1);
                #endif
                break;

                default:
                break;
            }
        }
        #endif

        if (processingEnabled)
        {
            digitalInput.update();
            analog.update();
            leds.update();
        }

        #ifdef DISPLAY_SUPPORTED
        display.update();
        #endif
    }
}
<commit_msg>enable validity checks for now<commit_after>/*
    OpenDeck MIDI platform firmware
    Copyright (C) 2015-2018 Igor Petrovic

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include "interface/Interface.h"
#include "Version.h"

MIDI midi;
bool processingEnabled;

void init()
{
    board.init();
    database.init();
    sysEx.init();

    #if defined(BOARD_OPEN_DECK) || defined(BOARD_A_LEO) || defined(BOARD_A_PRO_MICRO) || defined(BOARD_T_2PP)
    midi.setUSBMIDIstate(true);
    #endif

    #if defined(BOARD_OPEN_DECK) || defined(BOARD_A_LEO) || defined(BOARD_A_PRO_MICRO) || defined(BOARD_T_2PP)
    midi.setDINMIDIstate(database.read(DB_BLOCK_MIDI, dbSection_midi_feature, midiFeatureDinEnabled));
    #endif

    #ifdef BOARD_A_MEGA
    //always enable (for now)
    midi.setDINMIDIstate(true);
    #endif

    #ifdef BOARD_A_UNO
    //always enable
    midi.setDINMIDIstate(true);
    #endif

    midi.setOneByteParseDINstate(true);
    midi.setDINvalidityCheckState(true);
    midi.setInputChannel(MIDI_CHANNEL_OMNI);
    midi.setNoteOffMode((noteOffType_t)database.read(DB_BLOCK_MIDI, dbSection_midi_feature, midiFeatureStandardNoteOff));
    midi.setRunningStatusState(database.read(DB_BLOCK_MIDI, dbSection_midi_feature, midiFeatureRunningStatus));
    midi.setChannelSendZeroStart(true);

    #if !defined(BOARD_A_MEGA) && !defined(BOARD_A_UNO)
    board.ledFlashStartup(board.checkNewRevision());
    #endif

    //enable global interrupts
    sei();

    leds.init();

    #ifdef DISPLAY_SUPPORTED
    if (database.read(DB_BLOCK_DISPLAY, dbSection_display_features, displayFeatureEnable))
    {
        display.init((displayController_t)database.read(DB_BLOCK_DISPLAY, dbSection_display_hw, displayHwController), (displayResolution_t)database.read(DB_BLOCK_DISPLAY, dbSection_display_hw, displayHwResolution));
        display.displayHome();
        display.setRetentionState(database.read(DB_BLOCK_DISPLAY, dbSection_display_features, displayFeatureMIDIeventRetention));
        display.setRetentionTime(database.read(DB_BLOCK_DISPLAY, dbSection_display_features, displayFeatureMIDIeventTime) * 1000);
    }
    #endif

    processingEnabled = true;
}

int main()
{
    init();

    while(1)
    {
        #if defined(BOARD_A_LEO) || defined(BOARD_OPEN_DECK) || defined(BOARD_A_PRO_MICRO) || defined(BOARD_T_2PP)
        if (midi.read(usbInterface))
        {
            //new message on usb
            midiMessageType_t messageType = midi.getType(usbInterface);
            uint8_t data1 = midi.getData1(usbInterface);
            uint8_t data2 = midi.getData2(usbInterface);
            uint8_t channel = midi.getChannel(usbInterface);

            switch(messageType)
            {
                case midiMessageSystemExclusive:
                sysEx.handleMessage(midi.getSysExArray(usbInterface), midi.getSysExArrayLength(usbInterface));
                break;

                case midiMessageNoteOn:
                //we're using received note data to control LED color
                leds.noteToState(data1, data2, channel);
                #ifdef DISPLAY_SUPPORTED
                display.displayMIDIevent(displayEventIn, midiMessageNoteOn_display, data1, data2, channel+1);
                #endif
                break;

                case midiMessageNoteOff:
                //always turn led off when note off is received
                leds.noteToState(data1, 0, channel);
                #ifdef DISPLAY_SUPPORTED
                display.displayMIDIevent(displayEventIn, midiMessageNoteOff_display, data1, data2, channel+1);
                #endif
                break;

                case midiMessageControlChange:
                //control change is used to control led blinking
                leds.ccToBlink(data1, data2, channel);
                #ifdef DISPLAY_SUPPORTED
                display.displayMIDIevent(displayEventIn, midiMessageControlChange_display, data1, data2, channel+1);
                #endif
                break;

                default:
                break;
            }
        }
        #endif

        #if !defined(BOARD_A_MEGA) && !defined(BOARD_A_UNO)
        if (midi.getDINMIDIstate())
        {
            //check for incoming MIDI messages on USART
            if (!database.read(DB_BLOCK_MIDI, dbSection_midi_feature, midiFeatureMergeEnabled))
            {
                midi.read(dinInterface);
                midiMessageType_t messageType = midi.getType(dinInterface);
                uint8_t data1 = midi.getData1(dinInterface);
                uint8_t data2 = midi.getData2(dinInterface);
                uint8_t channel = midi.getChannel(dinInterface);

                switch(messageType)
                {
                    case midiMessageNoteOn:
                    //we're using received note data to control LED color
                    leds.noteToState(data1, data2, channel);
                    #ifdef DISPLAY_SUPPORTED
                    display.displayMIDIevent(displayEventIn, midiMessageNoteOn_display, data1, data2, channel+1);
                    #endif
                    break;

                    case midiMessageNoteOff:
                    //always turn led off when note off is received
                    leds.noteToState(data1, 0, channel);
                    #ifdef DISPLAY_SUPPORTED
                    display.displayMIDIevent(displayEventIn, midiMessageNoteOff_display, data1, data2, channel+1);
                    #endif
                    break;

                    case midiMessageControlChange:
                    //control change is used to control led blinking
                    leds.ccToBlink(data1, data2, channel);
                    #ifdef DISPLAY_SUPPORTED
                    display.displayMIDIevent(displayEventIn, midiMessageControlChange_display, data1, data2, channel+1);
                    #endif
                    break;

                    default:
                    break;
                }
            }
            else
            {
                switch(database.read(DB_BLOCK_MIDI, dbSection_midi_merge, midiMergeInterface))
                {
                    case midiMergeInterfaceUSB:
                    //dump everything from MIDI in to USB MIDI out
                    midi.read(dinInterface, THRU_FULL_USB);
                    break;

                    case midiMergeInterfaceDIN:
                    //dump everything from MIDI in to MIDI out
                    midi.read(dinInterface, THRU_FULL_DIN);
                    break;

                    case midiMergeInterfaceAll:
                    //dump everything from MIDI in to USB MIDI out and MIDI out
                    midi.read(dinInterface, THRU_FULL_ALL);
                    break;

                    default:
                    break;
                }
            }
        }
        #endif

        #if defined(BOARD_A_MEGA) || defined(BOARD_A_UNO)
        //din interface here is actually translated usb traffic from 16u2
        if (midi.read(dinInterface))
        {
            midiMessageType_t messageType = midi.getType(dinInterface);
            uint8_t data1 = midi.getData1(dinInterface);
            uint8_t data2 = midi.getData2(dinInterface);
            uint8_t channel = midi.getChannel(dinInterface);

            switch(messageType)
            {
                case midiMessageSystemExclusive:
                sysEx.handleMessage(midi.getSysExArray(dinInterface), midi.getSysExArrayLength(dinInterface));
                break;

                case midiMessageNoteOn:
                //we're using received note data to control LED color
                leds.noteToState(data1, data2, channel);
                #ifdef DISPLAY_SUPPORTED
                display.displayMIDIevent(displayEventIn, midiMessageNoteOn_display, data1, data2, channel+1);
                #endif
                break;

                case midiMessageNoteOff:
                //always turn led off when note off is received
                leds.noteToState(data1, 0, channel);
                #ifdef DISPLAY_SUPPORTED
                display.displayMIDIevent(displayEventIn, midiMessageNoteOff_display, data1, data2, channel+1);
                #endif
                break;

                case midiMessageControlChange:
                //control change is used to control led blinking
                leds.ccToBlink(data1, data2, channel);
                #ifdef DISPLAY_SUPPORTED
                display.displayMIDIevent(displayEventIn, midiMessageControlChange_display, data1, data2, channel+1);
                #endif
                break;

                default:
                break;
            }
        }
        #endif

        if (processingEnabled)
        {
            digitalInput.update();
            analog.update();
            leds.update();
        }

        #ifdef DISPLAY_SUPPORTED
        display.update();
        #endif
    }
}
<|endoftext|>


<commit_before>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2016 Artem Pavlenko
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

#ifndef MAPNIK_FILE_IO_HPP
#define MAPNIK_FILE_IO_HPP

// mapnik
#include <mapnik/make_unique.hpp>
#include <mapnik/util/noncopyable.hpp>
#include <mapnik/util/utf_conv_win.hpp>

// stl
#include <cstdio>
#include <memory>
#include <string>

namespace mapnik { namespace util {

class file : public util::noncopyable
{
public:
    using file_ptr = std::unique_ptr<std::FILE, int (*)(std::FILE *)>;
    using data_type = std::unique_ptr<char[]>;

    explicit file(std::string const& filename)
#ifdef _WINDOWS
     : file_(_wfopen(mapnik::utf8_to_utf16(filename).c_str(), L"rb"), std::fclose),
#else
     : file_(std::fopen(filename.c_str(),"rb"), std::fclose),
#endif
       size_(0)

     {
        if (file_)
        {
            std::fseek(file_.get(), 0, SEEK_END);
            size_ = std::ftell(file_.get());
            std::fseek(file_.get(), 0, SEEK_SET);
        }
     }

    inline bool is_open() const
    {
        return file_ ? true : false;
    }

    explicit operator bool() const
    {
        return this->is_open();
    }

    inline std::FILE * get() const
    {
        return file_.get();
    }

    inline std::size_t size() const
    {
        return size_;
    }

    inline data_type data() const
    {
        if (!size_) return nullptr;
        std::fseek(file_.get(), 0, SEEK_SET);
        data_type buffer(new char[size_]);
        std::fread(buffer.get(), size_, 1, file_.get());
        return buffer;
    }
private:
    file_ptr file_;
    std::size_t size_;
};

}}

#endif // FILE_IO
<commit_msg>Revert back again fixing a typo! (thanks @springmeyer https://github.com/mapnik/mapnik/commit/2f55f0962ec965c54f7b8f068341e0e687fc9398#commitcomment-20461372) "It doesn't work with GCC reverting back "disable [-Wunused-result] warning GCC : https://gcc.gnu.org/bugzilla/show_bug.cgi?id=25509""<commit_after>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2016 Artem Pavlenko
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

#ifndef MAPNIK_FILE_IO_HPP
#define MAPNIK_FILE_IO_HPP

// mapnik
#include <mapnik/make_unique.hpp>
#include <mapnik/util/noncopyable.hpp>
#include <mapnik/util/utf_conv_win.hpp>

// stl
#include <cstdio>
#include <memory>
#include <string>

namespace mapnik { namespace util {

class file : public util::noncopyable
{
public:
    using file_ptr = std::unique_ptr<std::FILE, int (*)(std::FILE *)>;
    using data_type = std::unique_ptr<char[]>;

    explicit file(std::string const& filename)
#ifdef _WINDOWS
     : file_(_wfopen(mapnik::utf8_to_utf16(filename).c_str(), L"rb"), std::fclose),
#else
     : file_(std::fopen(filename.c_str(),"rb"), std::fclose),
#endif
       size_(0)

     {
        if (file_)
        {
            std::fseek(file_.get(), 0, SEEK_END);
            size_ = std::ftell(file_.get());
            std::fseek(file_.get(), 0, SEEK_SET);
        }
     }

    inline bool is_open() const
    {
        return file_ ? true : false;
    }

    explicit operator bool() const
    {
        return this->is_open();
    }

    inline std::FILE * get() const
    {
        return file_.get();
    }

    inline std::size_t size() const
    {
        return size_;
    }

    inline data_type data() const
    {
        if (!size_) return nullptr;
        std::fseek(file_.get(), 0, SEEK_SET);
        data_type buffer(new char[size_]);
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunknown-pragmas"
#pragma GCC diagnostic ignored "-Wunused-result"
        std::fread(buffer.get(), size_, 1, file_.get());
#pragma GCC diagnostic pop
        return buffer;
    }
private:
    file_ptr file_;
    std::size_t size_;
};

}}

#endif // FILE_IO
<|endoftext|>


<commit_before>/*

Copyright (c) 2015, Project OSRM contributors
All rights reserved.

Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:

Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
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.

*/

#ifndef SERVER_CONFIG_HPP
#define SERVER_CONFIG_HPP

#include <osrm/server_paths.hpp>

struct libosrm_config
{
    libosrm_config(const libosrm_config &) = delete;
    libosrm_config()
        : max_locations_distance_table(100), max_locations_map_matching(-1),
          use_shared_memory(false)
    {
    }

    libosrm_config(const ServerPaths &paths, const bool flag, const int max_table, const int max_matching)
        : server_paths(paths), max_locations_distance_table(max_table),
          max_locations_map_matching(max_matching), use_shared_memory(flag)
    {
    }

    ServerPaths server_paths;
    int max_locations_distance_table;
    int max_locations_map_matching;
    bool use_shared_memory;
};

#endif // SERVER_CONFIG_HPP
<commit_msg>Use shared memory if no server paths are provided.<commit_after>/*

Copyright (c) 2015, Project OSRM contributors
All rights reserved.

Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:

Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
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.

*/

#ifndef SERVER_CONFIG_HPP
#define SERVER_CONFIG_HPP

#include <osrm/server_paths.hpp>

struct libosrm_config
{
    libosrm_config(const libosrm_config &) = delete;
    libosrm_config()
        : max_locations_distance_table(100), max_locations_map_matching(-1),
          use_shared_memory(true)
    {
    }

    libosrm_config(const ServerPaths &paths, const bool flag, const int max_table, const int max_matching)
        : server_paths(paths), max_locations_distance_table(max_table),
          max_locations_map_matching(max_matching), use_shared_memory(flag)
    {
    }

    ServerPaths server_paths;
    int max_locations_distance_table;
    int max_locations_map_matching;
    bool use_shared_memory;
};

#endif // SERVER_CONFIG_HPP
<|endoftext|>


<commit_before>//
// Copyright (c) 2013-2014 Christoph Malek
// See LICENSE for more information.
//

#ifndef RJ_CORE_GAME_GAME_HPP
#define RJ_CORE_GAME_GAME_HPP

#include "game_updater.hpp"
#include "game_window.hpp"
#include <rectojump/game/debug_info.hpp>
#include <rectojump/game/world.hpp>
#include <rectojump/global/common.hpp>

namespace rj
{
	class game
	{
		game_window& m_window;

		// gameworld
		world m_world{*this};

	public:
		game(game_window& window) :
			m_window{window}
		{ }

		void update(dur duration)
		{
			m_world.update(duration);
		}

		void render()
		{
			m_world.render();
		}

		void load_level(const entity_proto_vec& entities)
		{
			m_world.load_level(entities);
		}

		void render_object(const sf::Drawable& object)
		{m_window.draw(object);}

		world& get_world()
		{return m_world;}
	};
}

#endif // RJ_CORE_GAME_GAME_HPP
<commit_msg>game: added level_mgr pointer<commit_after>//
// Copyright (c) 2013-2014 Christoph Malek
// See LICENSE for more information.
//

#ifndef RJ_CORE_GAME_GAME_HPP
#define RJ_CORE_GAME_GAME_HPP

#include "game_updater.hpp"
#include "game_window.hpp"
#include <rectojump/game/debug_info.hpp>
#include <rectojump/game/world.hpp>
#include <rectojump/global/common.hpp>
#include <rectojump/shared/level_manager/level_manager.hpp>

namespace rj
{
	class game
	{
		game_window& m_window;
		level_manager* m_lvmgr{nullptr};

		// gameworld
		world m_world{*this};

	public:
		game(game_window& window) :
			m_window{window}
		{ }

		void update(dur duration)
		{
			m_world.update(duration);
		}

		void render()
		{
			m_world.render();
		}

		void load_level(const level_id& id)
		{
			if(m_lvmgr == nullptr)
				mlk::lerr(errors::cl_nullptr_access)["rj::game"];

			auto& lv(m_lvmgr->get_level(id));
			m_world.load_level(lv.entities);
		}

		void render_object(const sf::Drawable& object)
		{m_window.draw(object);}

		void set_levelmgr(level_manager* lm)
		{m_lvmgr = lm;}

		world& get_world()
		{return m_world;}
	};
}

#endif // RJ_CORE_GAME_GAME_HPP
<|endoftext|>


<commit_before>#ifndef SIMDIFY_UTIL_MALLOC_HPP
#define SIMDIFY_UTIL_MALLOC_HPP

#include <type_traits>
#include <exception>
#include <cstdlib>
#include <cstdint>
#include "noexcept.hpp"

namespace simd {

    namespace detail {
#ifdef __GLIBCXX__
        // type_traits is buggered in libstdc++ up until GCC 5
        template <typename T>
        using is_trivially_default_constructible = std::has_trivial_default_constructor<T>;
#else
        template <typename T>
        using is_trivially_default_constructible = std::is_trivially_default_constructible<T>;
#endif

        template <std::size_t x>
        using is_power_of_2 = std::integral_constant<bool, x && (x & (x - 1)) == 0>;
    }

    template <typename T, std::size_t Align>
    T* aligned_malloc(std::size_t count)
    {
        static_assert(detail::is_power_of_2<Align>::value, "alignment must be a power of 2");
        auto size = (sizeof(T) * count) + sizeof(void*) + Align - 1;
        auto orig = std::malloc(size);
        if (orig == nullptr) return nullptr;
        auto aligned = reinterpret_cast<T*>((reinterpret_cast<std::uintptr_t>(orig) + sizeof(void*) + Align - 1) & ~(Align - 1));
        reinterpret_cast<void**>(aligned)[-1] = orig; // save orig right before the start of user data
        return aligned;
    }

    template <typename T>
    void aligned_free(T* aligned)
    {
        if (aligned == nullptr) return;
        auto orig = reinterpret_cast<void**>(aligned)[-1]; // restore orig from right before the start of user data
        std::free(orig);
    }

    struct aligned_deleter {
        template <typename T>
        void operator()(T* ptr) {
            simd::aligned_free(ptr);
        }
    };

    // aligned allocator
    template <typename T, std::size_t Align>
    struct aligned_allocator {
        using value_type = T;

        aligned_allocator() = default;
        template <typename S>
        aligned_allocator(const aligned_allocator<S, Align>&) {}

        T* allocate(std::size_t count) const SIMDIFY_NOEXCEPT {
            return simd::aligned_malloc<T, Align>(count);
        }

        void deallocate(T* ptr, std::size_t) const SIMDIFY_NOEXCEPT {
            simd::aligned_free(ptr);
        }

        // destroy is a no-op if possible
        void destroy(T* ptr) const SIMDIFY_NOEXCEPT_IF(std::is_nothrow_destructible<T>::value) {
            if (!std::is_trivially_destructible<T>::value) {
                ptr->~T();
            }
        }

        // construct without arguments is a no-op if possible
        void construct(T* ptr) const SIMDIFY_NOEXCEPT_IF(std::is_nothrow_constructible<T>::value) {
            if (!detail::is_trivially_default_constructible<T>::value) {
                new (ptr)T;
            }
        }

        // construct with arguments forwarded to placement new
        template <typename A1, typename... A>
        void construct(T* ptr, A1&& a1, A&&... a2) const {
            new (ptr)T(std::forward<A1>(a1), std::forward<A...>(a2)...);
        }

        // default rebind should do just this, doesn't seem to work in MSVC though
        template <typename S>
        struct rebind {
            using other = aligned_allocator<S, Align>;
        };
    };

    // allocator equality
    template <typename T, typename U, std::size_t TS, std::size_t US>
    bool operator==(const aligned_allocator<T, TS>&, const aligned_allocator<U, US>&) { return true; }
    template <typename T, typename U, std::size_t TS, std::size_t US>
    bool operator!=(const aligned_allocator<T, TS>&, const aligned_allocator<U, US>&) { return false; }

    // allocator that throws when used to construct/destroy anything
    template <typename T>
    struct dummy_allocator {
        using value_type = T;

        T* allocate(std::size_t) const { return nullptr; }
        void deallocate(T*, std::size_t) const {}
        void destroy(T*) const { throw std::runtime_error("dummy_allocator::destroy() used"); }

        template <typename... A>
        void construct(T*, A&&...) const { throw std::runtime_error("dummy_allocator::construct() used"); }
    };

    template <typename T, typename U>
    bool operator==(const dummy_allocator<T>&, const dummy_allocator<U>&) { return true; }
    template <typename T, typename U>
    bool operator!=(const dummy_allocator<T>&, const dummy_allocator<U>&) { return false; }

}

#endif // SIMDIFY_UTIL_MALLOC_HPP
<commit_msg>Enable using is_trivially_default_constructible in libstdc++ 5<commit_after>#ifndef SIMDIFY_UTIL_MALLOC_HPP
#define SIMDIFY_UTIL_MALLOC_HPP

#include <type_traits>
#include <exception>
#include <cstdlib>
#include <cstdint>
#include "noexcept.hpp"

namespace simd {

    namespace detail {
#if defined(__GLIBCXX__) && __GLIBCXX__ <= 20150626
        // type_traits is buggered in libstdc++ up until GCC 5
        template <typename T>
        using is_trivially_default_constructible = std::has_trivial_default_constructor<T>;
#else
        template <typename T>
        using is_trivially_default_constructible = std::is_trivially_default_constructible<T>;
#endif

        template <std::size_t x>
        using is_power_of_2 = std::integral_constant<bool, x && (x & (x - 1)) == 0>;
    }

    template <typename T, std::size_t Align>
    T* aligned_malloc(std::size_t count)
    {
        static_assert(detail::is_power_of_2<Align>::value, "alignment must be a power of 2");
        auto size = (sizeof(T) * count) + sizeof(void*) + Align - 1;
        auto orig = std::malloc(size);
        if (orig == nullptr) return nullptr;
        auto aligned = reinterpret_cast<T*>((reinterpret_cast<std::uintptr_t>(orig) + sizeof(void*) + Align - 1) & ~(Align - 1));
        reinterpret_cast<void**>(aligned)[-1] = orig; // save orig right before the start of user data
        return aligned;
    }

    template <typename T>
    void aligned_free(T* aligned)
    {
        if (aligned == nullptr) return;
        auto orig = reinterpret_cast<void**>(aligned)[-1]; // restore orig from right before the start of user data
        std::free(orig);
    }

    struct aligned_deleter {
        template <typename T>
        void operator()(T* ptr) {
            simd::aligned_free(ptr);
        }
    };

    // aligned allocator
    template <typename T, std::size_t Align>
    struct aligned_allocator {
        using value_type = T;

        aligned_allocator() = default;
        template <typename S>
        aligned_allocator(const aligned_allocator<S, Align>&) {}

        T* allocate(std::size_t count) const SIMDIFY_NOEXCEPT {
            return simd::aligned_malloc<T, Align>(count);
        }

        void deallocate(T* ptr, std::size_t) const SIMDIFY_NOEXCEPT {
            simd::aligned_free(ptr);
        }

        // destroy is a no-op if possible
        void destroy(T* ptr) const SIMDIFY_NOEXCEPT_IF(std::is_nothrow_destructible<T>::value) {
            if (!std::is_trivially_destructible<T>::value) {
                ptr->~T();
            }
        }

        // construct without arguments is a no-op if possible
        void construct(T* ptr) const SIMDIFY_NOEXCEPT_IF(std::is_nothrow_constructible<T>::value) {
            if (!detail::is_trivially_default_constructible<T>::value) {
                new (ptr)T;
            }
        }

        // construct with arguments forwarded to placement new
        template <typename A1, typename... A>
        void construct(T* ptr, A1&& a1, A&&... a2) const {
            new (ptr)T(std::forward<A1>(a1), std::forward<A...>(a2)...);
        }

        // default rebind should do just this, doesn't seem to work in MSVC though
        template <typename S>
        struct rebind {
            using other = aligned_allocator<S, Align>;
        };
    };

    // allocator equality
    template <typename T, typename U, std::size_t TS, std::size_t US>
    bool operator==(const aligned_allocator<T, TS>&, const aligned_allocator<U, US>&) { return true; }
    template <typename T, typename U, std::size_t TS, std::size_t US>
    bool operator!=(const aligned_allocator<T, TS>&, const aligned_allocator<U, US>&) { return false; }

    // allocator that throws when used to construct/destroy anything
    template <typename T>
    struct dummy_allocator {
        using value_type = T;

        T* allocate(std::size_t) const { return nullptr; }
        void deallocate(T*, std::size_t) const {}
        void destroy(T*) const { throw std::runtime_error("dummy_allocator::destroy() used"); }

        template <typename... A>
        void construct(T*, A&&...) const { throw std::runtime_error("dummy_allocator::construct() used"); }
    };

    template <typename T, typename U>
    bool operator==(const dummy_allocator<T>&, const dummy_allocator<U>&) { return true; }
    template <typename T, typename U>
    bool operator!=(const dummy_allocator<T>&, const dummy_allocator<U>&) { return false; }

}

#endif // SIMDIFY_UTIL_MALLOC_HPP
<|endoftext|>


<commit_before>
#include "motion.h"
#include "pwm.h"
#include "mathfunc.h"
#include "coms.h"
#include "canbus.h"
#include "storedconf.h"

float g_angleOffset = 0;      // Offset from phase position to actuator position.
float g_actuatorRatio = 7.0 * 21.0; // Gear ratio

float g_endStopMin = 0;    // Minimum angle
float g_endStopMax = M_PI*2; // Maximum angle
float g_absoluteMaxTorque = 20.0; // Maximum torque allowed
float g_uncalibratedTorqueLimit = 4.0; // Maximum torque allowed in un-calibrated mode.

const int g_positionIndexCount = 4;
float g_absoluteIndexPosition[g_positionIndexCount]; // Position of indexes
bool g_haveIndexPositionSample[g_positionIndexCount];
float g_measuredIndexPosition[g_positionIndexCount]; // Measured position

enum MotionCalibrationT g_motionCalibration = MC_Uncalibrated;
enum PositionReferenceT g_motionPositionReference = PR_Relative;
enum ControlStateT g_controlState = CS_StartUp;
enum FaultCodeT g_lastFaultCode = FC_Ok;
bool g_indicatorState = false;
bool g_newCalibrationData = false;

uint8_t g_otherJointId = 0;
float g_relativePositionGain = 1.0;
float g_relativePositionOffset = 0.0;

void MotionResetCalibration() {
  for(int i = 0;i < g_positionIndexCount;i++) {
    g_haveIndexPositionSample[i] = false;
  }
  bool changed = g_motionCalibration != MC_Uncalibrated;
  g_motionCalibration = MC_Uncalibrated;
  if(changed) {
    SendParamUpdate(CPI_PositionCal);
  }
}

static int EndStopUpdateOffset(bool newState,bool velocityPositive)
{
  return (newState ? 1 : 0) + ((velocityPositive ? 2 : 0));
}

void MotionUpdateEndStop(int num,bool state,float position,float velocity)
{
  if(g_motionCalibration != MC_Uncalibrated && num == 2) {
    int entry = EndStopUpdateOffset(state,velocity > 0);
    if(!g_haveIndexPositionSample[entry]) {
      g_haveIndexPositionSample[entry] = true;
    }
    g_newCalibrationData = true;
    g_measuredIndexPosition[entry] = position;
  }
}

bool MotionEstimateOffset(float &value)
{
  int points = 0;
  float offset = 0;

  int off1,off2;
  for(int i = 0;i < 2;i++) {
    if(i == 0) {
      off1 = EndStopUpdateOffset(true,true);
      off2 = EndStopUpdateOffset(false,false);
    } else {
      off1 = EndStopUpdateOffset(false,true);
      off2 = EndStopUpdateOffset(true,false);
    }
    if(g_haveIndexPositionSample[off1] && g_haveIndexPositionSample[off2]) {
      offset += (g_measuredIndexPosition[off1] + g_absoluteIndexPosition[off2])/2.0;
      points++;
    }
  }
  if(points <= 0)
    return false;
  value = offset / (float) points;
  return true;
}

uint8_t g_requestedJointMode = 0;
int16_t g_requestedJointPosition = 0;
uint8_t g_otherJointMode = 0;
int16_t g_otherJointPosition = 0;
float g_otherPhaseOffset = 0; // Last reported position of other joint.

static float DemandToPhasePosition(int16_t position)
{
  return (((float) position) * g_actuatorRatio * M_PI * 4.0/ 65535.0);
}

static int16_t PhasePositionToDemand(float angle)
{
  return (angle * 65535.0) / (g_actuatorRatio * M_PI * 4.0);
}

bool UpdateRequestedPosition()
{
  float posf = DemandToPhasePosition(g_requestedJointPosition);

  if((g_requestedJointMode & 0x1) != 0) { // Calibrated position ?
    if(g_motionCalibration != MC_Calibrated)
      return false;
    posf += g_angleOffset;
  }

  if((g_motionPositionReference & 0x2) != 0) { // relative position ?
    // If we want a calibrated position and the other joint is uncalibrated then
    // give up.
    if((g_otherJointMode & 0x1) == 0 && (g_motionPositionReference & 0x1) != 0) {
      return false;
    }
    g_otherPhaseOffset =  DemandToPhasePosition(g_otherJointPosition) * g_relativePositionGain + g_relativePositionOffset;
    posf += g_otherPhaseOffset;
  }

  g_demandPhasePosition = posf;
  return true;
}

bool MotionSetPosition(uint8_t mode,int16_t position,uint16_t torqueLimit)
{
  g_requestedJointMode = mode;
  g_torqueLimit = ((float) torqueLimit) * g_absoluteMaxTorque / (65536.0);
  g_requestedJointPosition = position;

  return UpdateRequestedPosition();
}

bool MotionOtherJointUpdate(int16_t position,int16_t torque,uint8_t mode)
{
  g_otherJointPosition = position;
  g_otherJointMode = mode;
  if((g_motionPositionReference & 0x2) != 0)
    return UpdateRequestedPosition();
  return true;
}

bool MotionReport(int16_t position,int16_t torque,PositionReferenceT posRef)
{
  uint8_t mode = posRef & 0x3;

  // Report endstop switches.
#if 0
  if(palReadPad(GPIOC, GPIOC_PIN6))
    mode |= 1 << 3;
  if(palReadPad(GPIOC, GPIOC_PIN7))
    mode |= 1 << 4;
#endif
  if(palReadPad(GPIOC, GPIOC_PIN8))
    mode |= 1 << 3;

  if(g_canBridgeMode) {
    PacketServoReportC servo;
    servo.m_packetType = CPT_ServoReport;
    servo.m_deviceId = g_deviceId;
    servo.m_mode = mode;
    servo.m_position = position;
    servo.m_torque = torque;
    USBSendPacket(reinterpret_cast<uint8_t *>(&servo),sizeof(PacketServoReportC));
  }
  if(g_deviceId != 0) {
    CANSendServoReport(g_deviceId,position,torque,mode);
  }
  return true;
}

void CalibrationCheckFailed() {
  if(g_motionCalibration == MC_Uncalibrated)
    return ;
  g_motionCalibration = MC_Uncalibrated;
  FaultDetected(FC_PositionLost);
  SendParamUpdate(CPI_PositionCal);
}

bool MotionCalZero()
{
  // Can only calibrate if pwm loop is running and we are updating our position.
  if(!g_pwmRun)
    return false;

  // Make sure we don't fly off somewhere.
  g_requestedJointMode = 0;
  g_requestedJointPosition = g_currentPhasePosition;

  g_angleOffset = g_currentPhasePosition;
  g_motionCalibration = MC_Calibrated;

  SendParamUpdate(CPI_CalibrationOffset);
  SendParamUpdate(CPI_PositionCal);
  return true;
}

void MotionStep()
{
#if 1
  int16_t torque = g_torqueAverage * (65535.0/g_absoluteMaxTorque);

  // Should we
  switch(g_motionCalibration)
  {
    case MC_Uncalibrated:
      break;
    case MC_Measuring:
      // Establishing a new calibration
      if(g_newCalibrationData) {
        g_newCalibrationData = false;
        if(MotionEstimateOffset(g_angleOffset)) {
          g_motionCalibration = MC_Calibrated;
          SendParamUpdate(CPI_CalibrationOffset);
          SendParamUpdate(CPI_PositionCal);
        }
      }
      break;
    case MC_Calibrated: {
      // If we're calibrated, we're just going to check all is fine.
      if(g_newCalibrationData) {
        g_newCalibrationData = false;
#if 0
        MotionEstimateOffset(g_angleOffset);
        SendParamUpdate(CPI_CalibrationOffset);
#else
#if 0
        float estimate;
        if(!MotionEstimateOffset(estimate)) {
          CalibrationCheckFailed();
        }
        if(fabs(estimate - g_angleOffset) > (M_PI/2.0)) {
          CalibrationCheckFailed();
        }
#endif
#endif
      }
    } break;
  }

  float position = g_currentPhasePosition;

  enum PositionReferenceT posRef = g_motionPositionReference;

  switch(g_motionPositionReference)
  {
    case PR_OtherJointAbsolute:
      position -= g_otherPhaseOffset;
      /* no break */
    case PR_Absolute: {
      if(g_motionCalibration == MC_Calibrated) {
        position -= g_angleOffset;
      } else {
        // Without calibration we can only send relative positions.
        position = g_currentPhasePosition;
        posRef = PR_Relative;
      }
      uint16_t reportPosition = PhasePositionToDemand(position);
      MotionReport(reportPosition,torque,posRef);
    } break;
    case PR_OtherJointRelative:
      position -= g_otherPhaseOffset;
      /* no break */
    case PR_Relative: {
      uint16_t reportPosition = PhasePositionToDemand(position);
      MotionReport(reportPosition,torque,posRef);
    } break;
  }
#endif
}

enum FaultCodeT LoadSetup(void) {
  if(!g_eeInitDone) {
    StoredConf_Init();
    g_eeInitDone = true;
  }
  StoredConf_Load(&g_storedConfig);

  g_deviceId = g_storedConfig.deviceId;
  g_otherJointId = g_storedConfig.otherJointId;
  g_relativePositionGain = g_storedConfig.m_relativePositionGain;
  g_relativePositionOffset = g_storedConfig.m_relativePositionOffset;
  g_motionPositionReference = (enum PositionReferenceT) g_storedConfig.m_motionPositionReference;

  // Setup angles.
  for(int i = 0;i < 12;i++) {
    g_phaseAngles[i][0] = g_storedConfig.phaseAngles[i][0];
    g_phaseAngles[i][1] = g_storedConfig.phaseAngles[i][1];
    g_phaseAngles[i][2] = g_storedConfig.phaseAngles[i][2];
  }

  // Should send an announce as this could change our id ?
  //uint8_t oldDevice = g_deviceId;
  //if(oldDevice != g_deviceId) {}

  return FC_Ok;
}

enum FaultCodeT SaveSetup(void) {
  if(!g_eeInitDone) {
    StoredConf_Init();
    g_eeInitDone = true;
  }

  g_storedConfig.configState = 1;
  g_storedConfig.deviceId = g_deviceId;
  g_storedConfig.otherJointId = g_otherJointId;

  g_storedConfig.m_relativePositionGain = g_relativePositionGain;
  g_storedConfig.m_relativePositionOffset =  g_relativePositionOffset;
  g_storedConfig.m_motionPositionReference = (int) g_motionPositionReference;

  for(int i = 0;i < 12;i++) {
    g_storedConfig.phaseAngles[i][0] = g_phaseAngles[i][0];
    g_storedConfig.phaseAngles[i][1] = g_phaseAngles[i][1];
    g_storedConfig.phaseAngles[i][2] = g_phaseAngles[i][2];
  }
  if(!StoredConf_Save(&g_storedConfig)) {
    return FC_InternalStoreFailed;
  }
  return FC_Ok;
}
<commit_msg>Fix calibration.<commit_after>
#include "motion.h"
#include "pwm.h"
#include "mathfunc.h"
#include "coms.h"
#include "canbus.h"
#include "storedconf.h"

float g_angleOffset = 0;      // Offset from phase position to actuator position.
float g_actuatorRatio = 7.0 * 21.0; // Gear ratio

float g_endStopMin = 0;    // Minimum angle
float g_endStopMax = M_PI*2; // Maximum angle
float g_absoluteMaxTorque = 20.0; // Maximum torque allowed
float g_uncalibratedTorqueLimit = 4.0; // Maximum torque allowed in un-calibrated mode.

const int g_positionIndexCount = 4;
float g_absoluteIndexPosition[g_positionIndexCount]; // Position of indexes
bool g_haveIndexPositionSample[g_positionIndexCount];
float g_measuredIndexPosition[g_positionIndexCount]; // Measured position

enum MotionCalibrationT g_motionCalibration = MC_Uncalibrated;
enum PositionReferenceT g_motionPositionReference = PR_Relative;
enum ControlStateT g_controlState = CS_StartUp;
enum FaultCodeT g_lastFaultCode = FC_Ok;
bool g_indicatorState = false;
bool g_newCalibrationData = false;

uint8_t g_otherJointId = 0;
float g_relativePositionGain = 1.0;
float g_relativePositionOffset = 0.0;

void MotionResetCalibration() {
  for(int i = 0;i < g_positionIndexCount;i++) {
    g_haveIndexPositionSample[i] = false;
  }
  bool changed = g_motionCalibration != MC_Uncalibrated;
  g_motionCalibration = MC_Uncalibrated;
  if(changed) {
    SendParamUpdate(CPI_PositionCal);
  }
}

static int EndStopUpdateOffset(bool newState,bool velocityPositive)
{
  return (newState ? 1 : 0) + ((velocityPositive ? 2 : 0));
}

void MotionUpdateEndStop(int num,bool state,float position,float velocity)
{
  if(g_motionCalibration != MC_Uncalibrated && num == 2) {
    int entry = EndStopUpdateOffset(state,velocity > 0);
    if(!g_haveIndexPositionSample[entry]) {
      g_haveIndexPositionSample[entry] = true;
    }
    g_newCalibrationData = true;
    g_measuredIndexPosition[entry] = position;
  }
}

bool MotionEstimateOffset(float &value)
{
  int points = 0;
  float offset = 0;

  int off1,off2;
  for(int i = 0;i < 2;i++) {
    if(i == 0) {
      off1 = EndStopUpdateOffset(true,true);
      off2 = EndStopUpdateOffset(false,false);
    } else {
      off1 = EndStopUpdateOffset(false,true);
      off2 = EndStopUpdateOffset(true,false);
    }
    if(g_haveIndexPositionSample[off1] && g_haveIndexPositionSample[off2]) {
      offset += (g_measuredIndexPosition[off1] + g_measuredIndexPosition[off2])/2.0;
      points++;
    }
  }
  if(points <= 0)
    return false;
  value = offset / (float) points;
  return true;
}

uint8_t g_requestedJointMode = 0;
int16_t g_requestedJointPosition = 0;
uint8_t g_otherJointMode = 0;
int16_t g_otherJointPosition = 0;
float g_otherPhaseOffset = 0; // Last reported position of other joint.

static float DemandToPhasePosition(int16_t position)
{
  return (((float) position) * g_actuatorRatio * M_PI * 4.0/ 65535.0);
}

static int16_t PhasePositionToDemand(float angle)
{
  return (angle * 65535.0) / (g_actuatorRatio * M_PI * 4.0);
}

bool UpdateRequestedPosition()
{
  float posf = DemandToPhasePosition(g_requestedJointPosition);

  if((g_requestedJointMode & 0x1) != 0) { // Calibrated position ?
    if(g_motionCalibration != MC_Calibrated)
      return false;
    posf += g_angleOffset;
  }

  if((g_motionPositionReference & 0x2) != 0) { // relative position ?
    // If we want a calibrated position and the other joint is uncalibrated then
    // give up.
    if((g_otherJointMode & 0x1) == 0 && (g_motionPositionReference & 0x1) != 0) {
      return false;
    }
    g_otherPhaseOffset =  DemandToPhasePosition(g_otherJointPosition) * g_relativePositionGain + g_relativePositionOffset;
    posf += g_otherPhaseOffset;
  }

  g_demandPhasePosition = posf;
  return true;
}

bool MotionSetPosition(uint8_t mode,int16_t position,uint16_t torqueLimit)
{
  g_requestedJointMode = mode;
  g_torqueLimit = ((float) torqueLimit) * g_absoluteMaxTorque / (65536.0);
  g_requestedJointPosition = position;

  return UpdateRequestedPosition();
}

bool MotionOtherJointUpdate(int16_t position,int16_t torque,uint8_t mode)
{
  g_otherJointPosition = position;
  g_otherJointMode = mode;
  if((g_motionPositionReference & 0x2) != 0)
    return UpdateRequestedPosition();
  return true;
}

bool MotionReport(int16_t position,int16_t torque,PositionReferenceT posRef)
{
  uint8_t mode = posRef & 0x3;

  // Report endstop switches.
#if 0
  if(palReadPad(GPIOC, GPIOC_PIN6))
    mode |= 1 << 3;
  if(palReadPad(GPIOC, GPIOC_PIN7))
    mode |= 1 << 4;
#endif
  if(palReadPad(GPIOC, GPIOC_PIN8))
    mode |= 1 << 3;

  if(g_canBridgeMode) {
    PacketServoReportC servo;
    servo.m_packetType = CPT_ServoReport;
    servo.m_deviceId = g_deviceId;
    servo.m_mode = mode;
    servo.m_position = position;
    servo.m_torque = torque;
    USBSendPacket(reinterpret_cast<uint8_t *>(&servo),sizeof(PacketServoReportC));
  }
  if(g_deviceId != 0) {
    CANSendServoReport(g_deviceId,position,torque,mode);
  }
  return true;
}

void CalibrationCheckFailed() {
  if(g_motionCalibration == MC_Uncalibrated)
    return ;
  g_motionCalibration = MC_Uncalibrated;
  FaultDetected(FC_PositionLost);
  SendParamUpdate(CPI_PositionCal);
}

bool MotionCalZero()
{
  // Can only calibrate if pwm loop is running and we are updating our position.
  if(!g_pwmRun)
    return false;

  // Make sure we don't fly off somewhere.
  g_requestedJointMode = 0;
  g_requestedJointPosition = g_currentPhasePosition;

  g_angleOffset = g_currentPhasePosition;
  g_motionCalibration = MC_Calibrated;

  SendParamUpdate(CPI_CalibrationOffset);
  SendParamUpdate(CPI_PositionCal);
  return true;
}

void MotionStep()
{
#if 1
  int16_t torque = g_torqueAverage * (65535.0/g_absoluteMaxTorque);

  // Should we
  switch(g_motionCalibration)
  {
    case MC_Uncalibrated:
      break;
    case MC_Measuring:
      // Establishing a new calibration
      if(g_newCalibrationData) {
        g_newCalibrationData = false;
        if(MotionEstimateOffset(g_angleOffset)) {
          g_motionCalibration = MC_Calibrated;
          SendParamUpdate(CPI_CalibrationOffset);
          SendParamUpdate(CPI_PositionCal);
        }
      }
      break;
    case MC_Calibrated: {
      // If we're calibrated, we're just going to check all is fine.
      if(g_newCalibrationData) {
        g_newCalibrationData = false;
#if 0
        MotionEstimateOffset(g_angleOffset);
        SendParamUpdate(CPI_CalibrationOffset);
#else
#if 0
        float estimate;
        if(!MotionEstimateOffset(estimate)) {
          CalibrationCheckFailed();
        }
        if(fabs(estimate - g_angleOffset) > (M_PI/2.0)) {
          CalibrationCheckFailed();
        }
#endif
#endif
      }
    } break;
  }

  float position = g_currentPhasePosition;

  enum PositionReferenceT posRef = g_motionPositionReference;

  switch(g_motionPositionReference)
  {
    case PR_OtherJointAbsolute:
      position -= g_otherPhaseOffset;
      /* no break */
    case PR_Absolute: {
      if(g_motionCalibration == MC_Calibrated) {
        position -= g_angleOffset;
      } else {
        // Without calibration we can only send relative positions.
        position = g_currentPhasePosition;
        posRef = PR_Relative;
      }
      uint16_t reportPosition = PhasePositionToDemand(position);
      MotionReport(reportPosition,torque,posRef);
    } break;
    case PR_OtherJointRelative:
      position -= g_otherPhaseOffset;
      /* no break */
    case PR_Relative: {
      uint16_t reportPosition = PhasePositionToDemand(position);
      MotionReport(reportPosition,torque,posRef);
    } break;
  }
#endif
}

enum FaultCodeT LoadSetup(void) {
  if(!g_eeInitDone) {
    StoredConf_Init();
    g_eeInitDone = true;
  }
  StoredConf_Load(&g_storedConfig);

  g_deviceId = g_storedConfig.deviceId;
  g_otherJointId = g_storedConfig.otherJointId;
  g_relativePositionGain = g_storedConfig.m_relativePositionGain;
  g_relativePositionOffset = g_storedConfig.m_relativePositionOffset;
  g_motionPositionReference = (enum PositionReferenceT) g_storedConfig.m_motionPositionReference;

  // Setup angles.
  for(int i = 0;i < 12;i++) {
    g_phaseAngles[i][0] = g_storedConfig.phaseAngles[i][0];
    g_phaseAngles[i][1] = g_storedConfig.phaseAngles[i][1];
    g_phaseAngles[i][2] = g_storedConfig.phaseAngles[i][2];
  }

  // Should send an announce as this could change our id ?
  //uint8_t oldDevice = g_deviceId;
  //if(oldDevice != g_deviceId) {}

  return FC_Ok;
}

enum FaultCodeT SaveSetup(void) {
  if(!g_eeInitDone) {
    StoredConf_Init();
    g_eeInitDone = true;
  }

  g_storedConfig.configState = 1;
  g_storedConfig.deviceId = g_deviceId;
  g_storedConfig.otherJointId = g_otherJointId;

  g_storedConfig.m_relativePositionGain = g_relativePositionGain;
  g_storedConfig.m_relativePositionOffset =  g_relativePositionOffset;
  g_storedConfig.m_motionPositionReference = (int) g_motionPositionReference;

  for(int i = 0;i < 12;i++) {
    g_storedConfig.phaseAngles[i][0] = g_phaseAngles[i][0];
    g_storedConfig.phaseAngles[i][1] = g_phaseAngles[i][1];
    g_storedConfig.phaseAngles[i][2] = g_phaseAngles[i][2];
  }
  if(!StoredConf_Save(&g_storedConfig)) {
    return FC_InternalStoreFailed;
  }
  return FC_Ok;
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: salogl.hxx,v $
 *
 *  $Revision: 1.2 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-09 13:59:01 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    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., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef _SV_SALOGL_HXX
#define _SV_SALOGL_HXX

#define _OPENGL_EXT

#ifndef _SV_WINCOMP_HXX
#include <wincomp.hxx>
#endif
#ifndef _GEN_HXX
#include <tools/gen.hxx>
#endif
#ifndef _SV_SV_H
#include <sv.h>
#endif
#ifndef _SV_SALOTYPE_HXX
#include <salotype.hxx>
#endif

// -----------------
// - State defines -
// -----------------

#define OGL_STATE_UNLOADED      (0x00000000)
#define OGL_STATE_INVALID       (0x00000001)
#define OGL_STATE_VALID         (0x00000002)

// -------------
// - SalOpenGL -
// -------------

class SalGraphics;
class String;

class SalOpenGL
{
private:
    static HGLRC        mhOGLContext;
    static HDC          mhOGLLastDC;
    static ULONG        mnOGLState;

private:
    static BOOL         ImplInitLib();
    static BOOL         ImplInit();
    static void         ImplFreeLib();

public:
                        SalOpenGL( SalGraphics* pGraphics );
                        ~SalOpenGL();

    static BOOL         Create();
    static void         Release();
    static ULONG        GetState() { return SalOpenGL::mnOGLState; }
    static BOOL         IsValid()  { return( OGL_STATE_VALID == SalOpenGL::mnOGLState ); }

    static void*        GetOGLFnc( const char* pFncName );

    static void         OGLEntry( SalGraphics* pGraphics );
    static void         OGLExit( SalGraphics* pGraphics );
};

#endif // _SV_SALOGL_HXX
<commit_msg>INTEGRATION: CWS vgbugs07 (1.2.606); FILE MERGED 2007/06/04 13:30:02 vg 1.2.606.1: #i76605# Remove -I .../inc/module hack introduced by hedaburemove01<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: salogl.hxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: hr $ $Date: 2007-06-27 20:54:47 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    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., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef _SV_SALOGL_HXX
#define _SV_SALOGL_HXX

#define _OPENGL_EXT

#ifndef _SV_WINCOMP_HXX
#include <wincomp.hxx>
#endif
#ifndef _GEN_HXX
#include <tools/gen.hxx>
#endif
#ifndef _SV_SV_H
#include <vcl/sv.h>
#endif
#ifndef _SV_SALOTYPE_HXX
#include <vcl/salotype.hxx>
#endif

// -----------------
// - State defines -
// -----------------

#define OGL_STATE_UNLOADED      (0x00000000)
#define OGL_STATE_INVALID       (0x00000001)
#define OGL_STATE_VALID         (0x00000002)

// -------------
// - SalOpenGL -
// -------------

class SalGraphics;
class String;

class SalOpenGL
{
private:
    static HGLRC        mhOGLContext;
    static HDC          mhOGLLastDC;
    static ULONG        mnOGLState;

private:
    static BOOL         ImplInitLib();
    static BOOL         ImplInit();
    static void         ImplFreeLib();

public:
                        SalOpenGL( SalGraphics* pGraphics );
                        ~SalOpenGL();

    static BOOL         Create();
    static void         Release();
    static ULONG        GetState() { return SalOpenGL::mnOGLState; }
    static BOOL         IsValid()  { return( OGL_STATE_VALID == SalOpenGL::mnOGLState ); }

    static void*        GetOGLFnc( const char* pFncName );

    static void         OGLEntry( SalGraphics* pGraphics );
    static void         OGLExit( SalGraphics* pGraphics );
};

#endif // _SV_SALOGL_HXX
<|endoftext|>


<commit_before>#pragma once

#include <gcl/mp/type_traits.hpp>
#include <tuple>

namespace gcl::mp::type_traits
{
    // Limitations : compilers support
    //  Clang   11.0.0  : does not support "Lambdas in unevaluated contexts" (P0315R4)
    //  MsVC    19.28   : "error C2057: expected constant expression" in consteval context
    //                    (like static_assert<std::is_same_v<>>)
    //  GCC     10.2    : OK
    // template <
    //     typename T,
    //     template <typename...> class PackType = std::tuple,
    //     typename = std::enable_if_t<type_traits::is_template_v<T>>>
    // using pack_arguments = std::remove_reference_t<decltype([]<template <typename...> typename Type, typename... Ts>(
    //     Type<Ts...>) constexpr { return PackType<Ts...>{}; }(std::declval<T>()))>;
    template <
        typename T,
        template <typename...> class PackType = std::tuple,
        typename = std::enable_if_t<type_traits::is_template_v<T>>>
    class pack_arguments {
        template <template <typename...> typename Type, typename... Ts>
        static auto impl(Type<Ts...>)
        {   // type deducer
            return PackType<Ts...>{};
        }

      public:
        using type = decltype(impl(std::declval<T>()));
    };
    template <
        typename T,
        template <typename...> class PackType = std::tuple,
        typename = std::enable_if_t<type_traits::is_template_v<T>>>
    using pack_arguments_t = typename pack_arguments<T, PackType>::type;

    template <typename T, typename U>
    struct concatenate;
    template <template <typename...> typename T, typename ... Ts, typename ... Us>
    struct concatenate<T<Ts...>, T<Us...>>
    {
        using type = T<Ts..., Us...>;
    };
    template <typename T, typename U>
    using concatenate_t = typename concatenate<T,U>::type;

    template <std::size_t N, typename... Ts>
    using type_at = typename std::tuple_element<N, std::tuple<Ts...>>;
    template <std::size_t N, typename... Ts>
    using type_at_t = typename type_at<N, Ts...>::type;

    // todo : index_of

    template <typename T, typename... Ts>
    using contains = std::disjunction<std::is_same<T, Ts>...>;
    template <typename T, typename... Ts>
    static constexpr inline auto contains_v = contains<T, Ts...>::value;

    template <typename T, template <typename> typename trait>
    struct filters;
    template <template <typename...> typename T, template <typename> typename trait, typename... Ts>
    struct filters<T<Ts...>, trait> {
        template <typename Type>
        using impl = std::conditional_t<trait<Type>::value, std::tuple<Type>, std::tuple<>>;

      public:
        using type = pack_arguments_t<decltype(std::tuple_cat(impl<Ts>{}...)), T>;
    };
    template <typename T, template <typename> typename trait>
    using filters_t = typename filters<T, trait>::type;
}
namespace gcl::mp
{
    template <typename T, typename = std::enable_if_t<gcl::mp::type_traits::is_template_v<T>>>
    struct pack_traits;
    template <template <typename...> typename T, typename... Ts>
    struct pack_traits<T<Ts...>> {
        using type = T<Ts...>;
        using arguments = type_traits::pack_arguments_t<type>;
        template <template <class...> class template_type>
        using unpack_as = type_traits::pack_arguments_t<type, template_type>;
        template <size_t N>
        using type_at = type_traits::type_at_t<N, Ts...>; // typename std::tuple_element<N, arguments>::type;

        static constexpr inline auto size = std::tuple_size_v<arguments>;
        template <typename U>
        static constexpr inline auto contains = type_traits::contains_v<U, Ts...>;
        template <template <class...> class template_type>
        static inline constexpr auto is_instance_of_v = type_traits::is_instance_of_v<type, template_type>;

        template <template <typename> typename trait>
        using satisfy_trait_t = std::conjunction<trait<Ts>...>;
        template <template <typename> typename trait>
        constexpr static inline bool satisfy_trait_v = satisfy_trait_t<trait>::value; //(trait<Ts>::value && ...)

        template <template <typename> typename trait>
        using filters = type_traits::filters_t<T<Ts...>, trait>;
    };
    template <typename... Ts>
    struct pack_type { // empty type that has variadic template-type parameters
                       // use this instead of std::tuple to pack template-type parameters,
                       // if your optimization level does not skip unused variables for some reasons
    };
    template <typename... Ts>
    struct super : Ts... {};
    template <template <typename...> class base_type, typename... Ts>
    struct partial {
        // differs type instanciation with partial template-type parameters
        template <typename... Us, typename = std::enable_if_t<sizeof...(Us) >= 1>>
        using type = base_type<Ts..., Us...>;
    };
}

namespace gcl::mp::type_traits::tests
{
    static_assert(std::is_same_v<gcl::mp::type_traits::type_at_t<2, char, bool, int, float>, int>);
    static_assert(gcl::mp::type_traits::contains_v<int, char, bool, int, float>);

    static_assert(gcl::mp::partial<std::is_same, int>::type<int>::value);
    static_assert(gcl::mp::partial<std::is_same>::type<int, int>::value);

    namespace pack_arguments
    {
        template <typename... Ts>
        struct pack_type {};

        using toto = typename gcl::mp::type_traits::pack_arguments_t<pack_type<int, double, float>, std::tuple>;
        using titi = typename gcl::mp::type_traits::pack_arguments_t<pack_type<int, double, float>>;
        static_assert(std::is_same_v<titi, toto>);
        static_assert(std::is_same_v<titi, std::tuple<int, double, float>>);
        static_assert(
            std::is_same_v<pack_type<int, double, float>, gcl::mp::type_traits::pack_arguments_t<titi, pack_type>>);
    }
    namespace concatenate
    {
        template <typename... Ts>
        struct pack {};
        using T1 = pack<int, double>;
        using T2 = pack<char, float>;
        static_assert(std::is_same_v<concatenate_t<T1, T2>, pack<int, double, char, float>>);
    }
    namespace filters
    {
        template <typename... Ts>
        struct pack {};
        using T1 = pack<int, int*,char, char*, float>;
        static_assert(std::is_same_v<filters_t<T1, std::is_pointer>, pack<int*, char*>>);
    }
}
namespace gcl::mp::tests::pack_traits
{
    template <typename... Ts>
    struct pack_type {};

    using base_type = pack_type<int, char, float>;
    using pack_traits_type = gcl::mp::pack_traits<base_type>;

    static_assert(std::is_same_v<pack_traits_type::type, base_type>);
    static_assert(pack_traits_type::size == 3);
    static_assert(pack_traits_type::size == std::tuple_size_v<pack_traits_type::arguments>);
    static_assert(std::is_same_v<pack_traits_type::arguments, std::tuple<int, char, float>>);
    static_assert(std::is_same_v<base_type, pack_traits_type::unpack_as<pack_type>>);

    static_assert(pack_traits_type::is_instance_of_v<pack_type>);

    static_assert(std::is_same_v<pack_traits_type::type_at<1>, char>);
    static_assert(pack_traits_type::contains<char>);

    static_assert(pack_traits_type::satisfy_trait_v<std::is_standard_layout>);
    static_assert(not pack_traits_type::satisfy_trait_v<std::is_pointer>);

    namespace filters
    {
        using T1 = pack_type<int, int*, char, char*, float>;
        using T1_pack_trait = gcl::mp::pack_traits<T1>;
        static_assert(std::is_same_v<pack_type<int*, char*>, T1_pack_trait::filters<std::is_pointer>>);
    }
}
<commit_msg>[mp::pack_traits] : add index_of<commit_after>#pragma once

#include <gcl/mp/type_traits.hpp>
#include <tuple>

namespace gcl::mp::type_traits
{
    // Limitations : compilers support
    //  Clang   11.0.0  : does not support "Lambdas in unevaluated contexts" (P0315R4)
    //  MsVC    19.28   : "error C2057: expected constant expression" in consteval context
    //                    (like static_assert<std::is_same_v<>>)
    //  GCC     10.2    : OK
    // template <
    //     typename T,
    //     template <typename...> class PackType = std::tuple,
    //     typename = std::enable_if_t<type_traits::is_template_v<T>>>
    // using pack_arguments = std::remove_reference_t<decltype([]<template <typename...> typename Type, typename... Ts>(
    //     Type<Ts...>) constexpr { return PackType<Ts...>{}; }(std::declval<T>()))>;
    template <
        typename T,
        template <typename...> class PackType = std::tuple,
        typename = std::enable_if_t<type_traits::is_template_v<T>>>
    class pack_arguments {
        template <template <typename...> typename Type, typename... Ts>
        static auto impl(Type<Ts...>)
        {   // type deducer
            return PackType<Ts...>{};
        }

      public:
        using type = decltype(impl(std::declval<T>()));
    };
    template <
        typename T,
        template <typename...> class PackType = std::tuple,
        typename = std::enable_if_t<type_traits::is_template_v<T>>>
    using pack_arguments_t = typename pack_arguments<T, PackType>::type;

    template <typename T, typename U>
    struct concatenate;
    template <template <typename...> typename T, typename ... Ts, typename ... Us>
    struct concatenate<T<Ts...>, T<Us...>>
    {
        using type = T<Ts..., Us...>;
    };
    template <typename T, typename U>
    using concatenate_t = typename concatenate<T,U>::type;

    template <std::size_t N, typename... Ts>
    using type_at = typename std::tuple_element<N, std::tuple<Ts...>>;
    template <std::size_t N, typename... Ts>
    using type_at_t = typename type_at<N, Ts...>::type;

    template <typename to_find, typename pack_type>
    class index_of {
        template <template <typename...> class PackType, typename... PackArgs>
        consteval static auto impl(PackType<PackArgs...>)
        {
            constexpr auto index =
                []<typename TupleType, std::size_t... I>(TupleType, std::index_sequence<I...>) consteval
            {
                constexpr bool matches[] = {std::is_same_v<to_find, std::tuple_element_t<I, TupleType>>...};
                static_assert(std::size(matches) == sizeof...(I));
                return std::distance(matches, std::find(matches, matches + sizeof...(I), true));
            }
            (std::tuple<PackArgs...>{}, std::make_index_sequence<sizeof...(PackArgs)>{});
            static_assert(index != sizeof...(PackArgs), "index_of : no match");
            return index;
        }

      public:
        constexpr static auto value = impl(pack_type{});
    };
    template <typename to_find, typename pack_type>
    constexpr static auto index_of_v = index_of<to_find, pack_type>::value;

    template <typename T, typename... Ts>
    using contains = std::disjunction<std::is_same<T, Ts>...>;
    template <typename T, typename... Ts>
    static constexpr inline auto contains_v = contains<T, Ts...>::value;

    template <typename T, template <typename> typename trait>
    struct filters;
    template <template <typename...> typename T, template <typename> typename trait, typename... Ts>
    struct filters<T<Ts...>, trait> {
        template <typename Type>
        using impl = std::conditional_t<trait<Type>::value, std::tuple<Type>, std::tuple<>>;

      public:
        using type = pack_arguments_t<decltype(std::tuple_cat(impl<Ts>{}...)), T>;
    };
    template <typename T, template <typename> typename trait>
    using filters_t = typename filters<T, trait>::type;
}
namespace gcl::mp
{
    template <typename T, typename = std::enable_if_t<gcl::mp::type_traits::is_template_v<T>>>
    struct pack_traits;
    template <template <typename...> typename T, typename... Ts>
    struct pack_traits<T<Ts...>> {
        using type = T<Ts...>;
        using arguments = type_traits::pack_arguments_t<type>;
        template <template <class...> class template_type>
        using unpack_as = type_traits::pack_arguments_t<type, template_type>;
        template <size_t N>
        using type_at = type_traits::type_at_t<N, Ts...>; // typename std::tuple_element<N, arguments>::type;

        template <typename U>
        static constexpr inline auto index_of_v = gcl::mp::type_traits::index_of_v<U, arguments>;

        static constexpr inline auto size = std::tuple_size_v<arguments>;
        template <typename U>
        static constexpr inline auto contains = type_traits::contains_v<U, Ts...>;
        template <template <class...> class template_type>
        static inline constexpr auto is_instance_of_v = type_traits::is_instance_of_v<type, template_type>;

        template <template <typename> typename trait>
        using satisfy_trait_t = std::conjunction<trait<Ts>...>;
        template <template <typename> typename trait>
        constexpr static inline bool satisfy_trait_v = satisfy_trait_t<trait>::value; //(trait<Ts>::value && ...)

        template <template <typename> typename trait>
        using filters = type_traits::filters_t<T<Ts...>, trait>;
    };
    template <typename... Ts>
    struct pack_type { // empty type that has variadic template-type parameters
                       // use this instead of std::tuple to pack template-type parameters,
                       // if your optimization level does not skip unused variables for some reasons
    };
    template <typename... Ts>
    struct super : Ts... {};
    template <template <typename...> class base_type, typename... Ts>
    struct partial {
        // differs type instanciation with partial template-type parameters
        template <typename... Us, typename = std::enable_if_t<sizeof...(Us) >= 1>>
        using type = base_type<Ts..., Us...>;
    };
}

namespace gcl::mp::type_traits::tests
{
    static_assert(std::is_same_v<gcl::mp::type_traits::type_at_t<2, char, bool, int, float>, int>);
    static_assert(gcl::mp::type_traits::contains_v<int, char, bool, int, float>);

    static_assert(gcl::mp::partial<std::is_same, int>::type<int>::value);
    static_assert(gcl::mp::partial<std::is_same>::type<int, int>::value);

    namespace pack_arguments
    {
        template <typename... Ts>
        struct pack_type {};

        using toto = typename gcl::mp::type_traits::pack_arguments_t<pack_type<int, double, float>, std::tuple>;
        using titi = typename gcl::mp::type_traits::pack_arguments_t<pack_type<int, double, float>>;
        static_assert(std::is_same_v<titi, toto>);
        static_assert(std::is_same_v<titi, std::tuple<int, double, float>>);
        static_assert(
            std::is_same_v<pack_type<int, double, float>, gcl::mp::type_traits::pack_arguments_t<titi, pack_type>>);
    }
    namespace concatenate
    {
        template <typename... Ts>
        struct pack {};
        using T1 = pack<int, double>;
        using T2 = pack<char, float>;
        static_assert(std::is_same_v<concatenate_t<T1, T2>, pack<int, double, char, float>>);
    }
    namespace filters
    {
        template <typename... Ts>
        struct pack {};
        using T1 = pack<int, int*,char, char*, float>;
        static_assert(std::is_same_v<filters_t<T1, std::is_pointer>, pack<int*, char*>>);
    }
    namespace index_of
    {
        template <typename... Ts>
        struct pack {};

        using type_pack = pack<int, double, char, float>;
        static_assert(gcl::mp::type_traits::index_of_v<char, type_pack> == 2);
    }
}
namespace gcl::mp::tests::pack_traits
{
    template <typename... Ts>
    struct pack_type {};

    using base_type = pack_type<int, char, float>;
    using pack_traits_type = gcl::mp::pack_traits<base_type>;

    static_assert(std::is_same_v<pack_traits_type::type, base_type>);
    static_assert(pack_traits_type::size == 3);
    static_assert(pack_traits_type::size == std::tuple_size_v<pack_traits_type::arguments>);
    static_assert(std::is_same_v<pack_traits_type::arguments, std::tuple<int, char, float>>);
    static_assert(std::is_same_v<base_type, pack_traits_type::unpack_as<pack_type>>);

    static_assert(pack_traits_type::is_instance_of_v<pack_type>);

    static_assert(std::is_same_v<pack_traits_type::type_at<1>, char>);
    static_assert(pack_traits_type::contains<char>);

    static_assert(pack_traits_type::satisfy_trait_v<std::is_standard_layout>);
    static_assert(not pack_traits_type::satisfy_trait_v<std::is_pointer>);

    static_assert(pack_traits_type::index_of_v<char> == 1);

    namespace filters
    {
        using T1 = pack_type<int, int*, char, char*, float>;
        using T1_pack_trait = gcl::mp::pack_traits<T1>;
        static_assert(std::is_same_v<pack_type<int*, char*>, T1_pack_trait::filters<std::is_pointer>>);
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2016 The Bitcoin developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
// MVF-BU common objects and functions

#include "mvf-bu.h"
#include "init.h"
#include "util.h"
#include "chainparams.h"

#include <iostream>
#include <fstream>
#include <boost/filesystem.hpp>

using namespace std;

// actual fork height, taking into account user configuration parameters (MVHF-BU-DES-TRIG-4)
int FinalActivateForkHeight = 0;

// actual fork id, taking into account user configuration parameters (MVHF-BU-DES-CSIG-1)
int FinalForkId = 0;

// track whether HF has been activated before in previous run (MVHF-BU-DES-TRIG-5)
// is set at startup based on btcfork.conf presence
bool wasMVFHardForkPreviouslyActivated = false;

// track whether HF is active (MVHF-BU-DES-TRIG-5)
bool isMVFHardForkActive = false;

// track whether auto wallet backup might still need to be done
// this is set to true at startup if client detects fork already triggered
// otherwise when the backup is made. (MVHF-BU-DES-WABU-1)
bool fAutoBackupDone = false;

// default suffix to append to wallet filename for auto backup (MVHF-BU-DES-WABU-1)
std::string autoWalletBackupSuffix = "auto.@.bak";

/** Add MVF-specific command line options (MVHF-BU-DES-TRIG-8) */
std::string ForkCmdLineHelp()
{
    std::string strUsage;
    strUsage += HelpMessageGroup(_("Bitcoin MVF-BU Options:"));

    // automatic wallet backup parameters (MVHF-BU-DES-WABU-1)
    strUsage += HelpMessageOpt("-autobackupwalletpath=<path>", _("Automatically backup the wallet to the autobackupwalletfile path after the block specified becomes the best block (-autobackupblock). Default: Enabled"));
    strUsage += HelpMessageOpt("-autobackupblock=<n>", _("Specify the block number that triggers the automatic wallet backup. Default: forkheight-1"));

    // fork height parameter (MVHF-BU-DES-TRIG-1)
    strUsage += HelpMessageOpt("-forkheight=<n>", strprintf(_("Block height at which to fork on active network (integer). Defaults (also minimums): mainnet:%u,testnet=%u,nolnet=%u,regtest=%u"), (unsigned)HARDFORK_HEIGHT_MAINNET, (unsigned)HARDFORK_HEIGHT_TESTNET, (unsigned)HARDFORK_HEIGHT_NOLNET, (unsigned)HARDFORK_HEIGHT_REGTEST));

    // fork id (MVHF-BU-DES-CSIG-1)
    strUsage += HelpMessageOpt("-forkid=<n>", strprintf(_("Fork id to use for signature change. Value must be between 0 and %d. Default is 0x%06x (%u)"), (unsigned)MAX_HARDFORK_SIGHASH_ID, (unsigned)HARDFORK_SIGHASH_ID, (unsigned)HARDFORK_SIGHASH_ID));

    return strUsage;
}

/** Performs fork-related setup / validation actions when the program starts */
void ForkSetup(const CChainParams& chainparams)
{
    int minForkHeightForNetwork = 0;
    std:string activeNetworkID = chainparams.NetworkIDString();

    LogPrintf("%s: MVF: doing setup\n", __func__);
    LogPrintf("%s: MVF: active network = %s\n", __func__, activeNetworkID);

    // determine minimum fork height according to network
    // (these are set to the same as the default fork heights for now, but could be made different)
    if (activeNetworkID == CBaseChainParams::MAIN)
        minForkHeightForNetwork = HARDFORK_HEIGHT_MAINNET;
    else if (activeNetworkID == CBaseChainParams::TESTNET)
        minForkHeightForNetwork = HARDFORK_HEIGHT_TESTNET;
    else if (activeNetworkID == CBaseChainParams::REGTEST)
        minForkHeightForNetwork = HARDFORK_HEIGHT_REGTEST;
    else if (activeNetworkID == CBaseChainParams::UNL)
        minForkHeightForNetwork = HARDFORK_HEIGHT_NOLNET;
    else
        throw std::runtime_error(strprintf("%s: Unknown chain %s.", __func__, activeNetworkID));

    FinalActivateForkHeight = GetArg("-forkheight", minForkHeightForNetwork);

    // shut down immediately if specified fork height is invalid
    if (FinalActivateForkHeight < minForkHeightForNetwork)
    {
        LogPrintf("MVF: Error: specified fork height (%d) is less than minimum for '%s' network (%d)\n", FinalActivateForkHeight, activeNetworkID, minForkHeightForNetwork);
        StartShutdown();
    }

    FinalForkId = GetArg("-forkid", HARDFORK_SIGHASH_ID);
    // check fork id for validity (MVHF-BU-DES-CSIG-2)
    if (FinalForkId == 0) {
        LogPrintf("MVF: Warning: fork id = 0 will result in vulnerability to replay attacks\n");
    }
    else {
        if (FinalForkId < 0 || FinalForkId > MAX_HARDFORK_SIGHASH_ID) {
            LogPrintf("MVF: Error: specified fork id (%d) is not in range 0..%u\n", FinalForkId, (unsigned)MAX_HARDFORK_SIGHASH_ID);
            StartShutdown();
        }
    }

    LogPrintf("%s: MVF: active fork height = %d\n", __func__, FinalActivateForkHeight);
    LogPrintf("%s: MVF: active fork id = 0x%06x (%d)\n", __func__, FinalForkId, FinalForkId);
    LogPrintf("%s: MVF: auto backup block = %d\n", __func__, GetArg("-autobackupblock", FinalForkId - 1));

    // check if btcfork.conf exists (MVHF-BU-DES-TRIG-10)
    boost::filesystem::path pathBTCforkConfigFile(BTCFORK_CONF_FILENAME);
    if (!pathBTCforkConfigFile.is_complete())
        pathBTCforkConfigFile = GetDataDir(false) / pathBTCforkConfigFile;
    if (boost::filesystem::exists(pathBTCforkConfigFile)) {
        LogPrintf("%s: MVF: found marker config file at %s - client has already forked before\n", __func__, pathBTCforkConfigFile.string().c_str());
        wasMVFHardForkPreviouslyActivated = true;
    }
    else {
        LogPrintf("%s: MVF: no marker config file at %s - client has not forked yet\n", __func__, pathBTCforkConfigFile.string().c_str());
        wasMVFHardForkPreviouslyActivated = false;
    }

    // we should always set the activation flag to false during setup
    isMVFHardForkActive = false;
}

/** Actions when the fork triggers (MVHF-BU-DES-TRIG-6) */
void ActivateFork(void)
{
    LogPrintf("%s: MVF: checking whether to perform fork activation\n", __func__);
    if (!isMVFHardForkActive && !wasMVFHardForkPreviouslyActivated)  // sanity check to protect the one-off actions
    {
        LogPrintf("%s: MVF: performing fork activation actions\n", __func__);

        boost::filesystem::path pathBTCforkConfigFile(BTCFORK_CONF_FILENAME);
        if (!pathBTCforkConfigFile.is_complete())
            pathBTCforkConfigFile = GetDataDir(false) / pathBTCforkConfigFile;

        LogPrintf("%s: MVF: checking for existence of %s\n", __func__, pathBTCforkConfigFile.string().c_str());

        // remove btcfork.conf if it already exists - it shall be overwritten
        if (boost::filesystem::exists(pathBTCforkConfigFile)) {
            LogPrintf("%s: MVF: removing %s\n", __func__, pathBTCforkConfigFile.string().c_str());
            try {
                boost::filesystem::remove(pathBTCforkConfigFile);
            } catch (const boost::filesystem::filesystem_error& e) {
                LogPrintf("%s: Unable to remove pidfile: %s\n", __func__, e.what());
            }
        }
        // try to write the btcfork.conf (MVHF-BU-DES-TRIG-10)
        LogPrintf("%s: MVF: writing %s\n", __func__, pathBTCforkConfigFile.string().c_str());
        std::ofstream  btcforkfile(pathBTCforkConfigFile.string().c_str(), std::ios::out);
        btcforkfile << "forkheight=" << FinalActivateForkHeight << "\n";
        btcforkfile << "forkid=" << FinalForkId << "\n";
        btcforkfile << "autobackupblock=" << GetArg("-autobackupblock", FinalActivateForkHeight - 1) << "\n";
        btcforkfile.close();

        LogPrintf("%s: MVF: active fork height = %d\n", __func__, FinalActivateForkHeight);
        LogPrintf("%s: MVF: active fork id = 0x%06x (%d)\n", __func__, FinalForkId, FinalForkId);
        LogPrintf("%s: MVF: auto backup block = %d\n", __func__, GetArg("-autobackupblock", FinalForkId - 1));
    }
    // set the flag so that other code knows HF is active
    LogPrintf("%s: MVF: enabling isMVFHardForkActive\n", __func__);
    isMVFHardForkActive = true;
}

/** Actions when the fork is deactivated in reorg (MVHF-BU-DES-TRIG-7) */
void DeactivateFork(void)
{
    LogPrintf("%s: MVF: checking whether to perform fork deactivation\n", __func__);
    if (isMVFHardForkActive)
    {
        LogPrintf("%s: MVF: performing fork deactivation actions\n", __func__);
    }
    LogPrintf("%s: MVF: disabling isMVFHardForkActive\n", __func__);
    isMVFHardForkActive = false;
}
<commit_msg>Update FinalForkId to FinalActiveForkHeight.<commit_after>// Copyright (c) 2016 The Bitcoin developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
// MVF-BU common objects and functions

#include "mvf-bu.h"
#include "init.h"
#include "util.h"
#include "chainparams.h"

#include <iostream>
#include <fstream>
#include <boost/filesystem.hpp>

using namespace std;

// actual fork height, taking into account user configuration parameters (MVHF-BU-DES-TRIG-4)
int FinalActivateForkHeight = 0;

// actual fork id, taking into account user configuration parameters (MVHF-BU-DES-CSIG-1)
int FinalForkId = 0;

// track whether HF has been activated before in previous run (MVHF-BU-DES-TRIG-5)
// is set at startup based on btcfork.conf presence
bool wasMVFHardForkPreviouslyActivated = false;

// track whether HF is active (MVHF-BU-DES-TRIG-5)
bool isMVFHardForkActive = false;

// track whether auto wallet backup might still need to be done
// this is set to true at startup if client detects fork already triggered
// otherwise when the backup is made. (MVHF-BU-DES-WABU-1)
bool fAutoBackupDone = false;

// default suffix to append to wallet filename for auto backup (MVHF-BU-DES-WABU-1)
std::string autoWalletBackupSuffix = "auto.@.bak";

/** Add MVF-specific command line options (MVHF-BU-DES-TRIG-8) */
std::string ForkCmdLineHelp()
{
    std::string strUsage;
    strUsage += HelpMessageGroup(_("Bitcoin MVF-BU Options:"));

    // automatic wallet backup parameters (MVHF-BU-DES-WABU-1)
    strUsage += HelpMessageOpt("-autobackupwalletpath=<path>", _("Automatically backup the wallet to the autobackupwalletfile path after the block specified becomes the best block (-autobackupblock). Default: Enabled"));
    strUsage += HelpMessageOpt("-autobackupblock=<n>", _("Specify the block number that triggers the automatic wallet backup. Default: forkheight-1"));

    // fork height parameter (MVHF-BU-DES-TRIG-1)
    strUsage += HelpMessageOpt("-forkheight=<n>", strprintf(_("Block height at which to fork on active network (integer). Defaults (also minimums): mainnet:%u,testnet=%u,nolnet=%u,regtest=%u"), (unsigned)HARDFORK_HEIGHT_MAINNET, (unsigned)HARDFORK_HEIGHT_TESTNET, (unsigned)HARDFORK_HEIGHT_NOLNET, (unsigned)HARDFORK_HEIGHT_REGTEST));

    // fork id (MVHF-BU-DES-CSIG-1)
    strUsage += HelpMessageOpt("-forkid=<n>", strprintf(_("Fork id to use for signature change. Value must be between 0 and %d. Default is 0x%06x (%u)"), (unsigned)MAX_HARDFORK_SIGHASH_ID, (unsigned)HARDFORK_SIGHASH_ID, (unsigned)HARDFORK_SIGHASH_ID));

    return strUsage;
}

/** Performs fork-related setup / validation actions when the program starts */
void ForkSetup(const CChainParams& chainparams)
{
    int minForkHeightForNetwork = 0;
    std:string activeNetworkID = chainparams.NetworkIDString();

    LogPrintf("%s: MVF: doing setup\n", __func__);
    LogPrintf("%s: MVF: active network = %s\n", __func__, activeNetworkID);

    // determine minimum fork height according to network
    // (these are set to the same as the default fork heights for now, but could be made different)
    if (activeNetworkID == CBaseChainParams::MAIN)
        minForkHeightForNetwork = HARDFORK_HEIGHT_MAINNET;
    else if (activeNetworkID == CBaseChainParams::TESTNET)
        minForkHeightForNetwork = HARDFORK_HEIGHT_TESTNET;
    else if (activeNetworkID == CBaseChainParams::REGTEST)
        minForkHeightForNetwork = HARDFORK_HEIGHT_REGTEST;
    else if (activeNetworkID == CBaseChainParams::UNL)
        minForkHeightForNetwork = HARDFORK_HEIGHT_NOLNET;
    else
        throw std::runtime_error(strprintf("%s: Unknown chain %s.", __func__, activeNetworkID));

    FinalActivateForkHeight = GetArg("-forkheight", minForkHeightForNetwork);

    // shut down immediately if specified fork height is invalid
    if (FinalActivateForkHeight < minForkHeightForNetwork)
    {
        LogPrintf("MVF: Error: specified fork height (%d) is less than minimum for '%s' network (%d)\n", FinalActivateForkHeight, activeNetworkID, minForkHeightForNetwork);
        StartShutdown();
    }

    FinalForkId = GetArg("-forkid", HARDFORK_SIGHASH_ID);
    // check fork id for validity (MVHF-BU-DES-CSIG-2)
    if (FinalForkId == 0) {
        LogPrintf("MVF: Warning: fork id = 0 will result in vulnerability to replay attacks\n");
    }
    else {
        if (FinalForkId < 0 || FinalForkId > MAX_HARDFORK_SIGHASH_ID) {
            LogPrintf("MVF: Error: specified fork id (%d) is not in range 0..%u\n", FinalForkId, (unsigned)MAX_HARDFORK_SIGHASH_ID);
            StartShutdown();
        }
    }

    LogPrintf("%s: MVF: active fork height = %d\n", __func__, FinalActivateForkHeight);
    LogPrintf("%s: MVF: active fork id = 0x%06x (%d)\n", __func__, FinalForkId, FinalForkId);
    LogPrintf("%s: MVF: auto backup block = %d\n", __func__, GetArg("-autobackupblock", FinalActivateForkHeight - 1));

    // check if btcfork.conf exists (MVHF-BU-DES-TRIG-10)
    boost::filesystem::path pathBTCforkConfigFile(BTCFORK_CONF_FILENAME);
    if (!pathBTCforkConfigFile.is_complete())
        pathBTCforkConfigFile = GetDataDir(false) / pathBTCforkConfigFile;
    if (boost::filesystem::exists(pathBTCforkConfigFile)) {
        LogPrintf("%s: MVF: found marker config file at %s - client has already forked before\n", __func__, pathBTCforkConfigFile.string().c_str());
        wasMVFHardForkPreviouslyActivated = true;
    }
    else {
        LogPrintf("%s: MVF: no marker config file at %s - client has not forked yet\n", __func__, pathBTCforkConfigFile.string().c_str());
        wasMVFHardForkPreviouslyActivated = false;
    }

    // we should always set the activation flag to false during setup
    isMVFHardForkActive = false;
}

/** Actions when the fork triggers (MVHF-BU-DES-TRIG-6) */
void ActivateFork(void)
{
    LogPrintf("%s: MVF: checking whether to perform fork activation\n", __func__);
    if (!isMVFHardForkActive && !wasMVFHardForkPreviouslyActivated)  // sanity check to protect the one-off actions
    {
        LogPrintf("%s: MVF: performing fork activation actions\n", __func__);

        boost::filesystem::path pathBTCforkConfigFile(BTCFORK_CONF_FILENAME);
        if (!pathBTCforkConfigFile.is_complete())
            pathBTCforkConfigFile = GetDataDir(false) / pathBTCforkConfigFile;

        LogPrintf("%s: MVF: checking for existence of %s\n", __func__, pathBTCforkConfigFile.string().c_str());

        // remove btcfork.conf if it already exists - it shall be overwritten
        if (boost::filesystem::exists(pathBTCforkConfigFile)) {
            LogPrintf("%s: MVF: removing %s\n", __func__, pathBTCforkConfigFile.string().c_str());
            try {
                boost::filesystem::remove(pathBTCforkConfigFile);
            } catch (const boost::filesystem::filesystem_error& e) {
                LogPrintf("%s: Unable to remove pidfile: %s\n", __func__, e.what());
            }
        }
        // try to write the btcfork.conf (MVHF-BU-DES-TRIG-10)
        LogPrintf("%s: MVF: writing %s\n", __func__, pathBTCforkConfigFile.string().c_str());
        std::ofstream  btcforkfile(pathBTCforkConfigFile.string().c_str(), std::ios::out);
        btcforkfile << "forkheight=" << FinalActivateForkHeight << "\n";
        btcforkfile << "forkid=" << FinalForkId << "\n";
        btcforkfile << "autobackupblock=" << GetArg("-autobackupblock", FinalActivateForkHeight - 1) << "\n";
        btcforkfile.close();

        LogPrintf("%s: MVF: active fork height = %d\n", __func__, FinalActivateForkHeight);
        LogPrintf("%s: MVF: active fork id = 0x%06x (%d)\n", __func__, FinalForkId, FinalForkId);
        LogPrintf("%s: MVF: auto backup block = %d\n", __func__, GetArg("-autobackupblock", FinalActivateForkHeight - 1));
    }
    // set the flag so that other code knows HF is active
    LogPrintf("%s: MVF: enabling isMVFHardForkActive\n", __func__);
    isMVFHardForkActive = true;
}

/** Actions when the fork is deactivated in reorg (MVHF-BU-DES-TRIG-7) */
void DeactivateFork(void)
{
    LogPrintf("%s: MVF: checking whether to perform fork deactivation\n", __func__);
    if (isMVFHardForkActive)
    {
        LogPrintf("%s: MVF: performing fork deactivation actions\n", __func__);
    }
    LogPrintf("%s: MVF: disabling isMVFHardForkActive\n", __func__);
    isMVFHardForkActive = false;
}
<|endoftext|>