<commit_before>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/memory/p9_mss_draminit_mc.C $ */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2015,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* Licensed under the Apache License, Version 2.0 (the "License");        */
/* you may not use this file except in compliance with the License.       */
/* You may obtain a copy of the License at                                */
/*                                                                        */
/*     http://www.apache.org/licenses/LICENSE-2.0                         */
/*                                                                        */
/* Unless required by applicable law or agreed to in writing, software    */
/* distributed under the License is distributed on an "AS IS" BASIS,      */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or        */
/* implied. See the License for the specific language governing           */
/* permissions and limitations under the License.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */

///
/// @file p9_mss_draminit_mc.C
/// @brief Initialize the memory controller to take over the DRAM
///
// *HWP HWP Owner: Brian Silver <bsilver@us.ibm.com>
// *HWP HWP Backup: Andre Marin <aamarin@us.ibm.com>
// *HWP Team: Memory
// *HWP Level: 2
// *HWP Consumed by: FSP:HB

#include <fapi2.H>
#include <mss.H>

#include <p9_mss_draminit_mc.H>

using fapi2::TARGET_TYPE_MCBIST;
using fapi2::TARGET_TYPE_MCA;
using fapi2::TARGET_TYPE_MCS;

extern "C"
{
///
/// @brief Initialize the MC now that DRAM is up
/// @param[in] i_target, the McBIST of the ports
/// @return FAPI2_RC_SUCCESS iff ok
///
    fapi2::ReturnCode p9_mss_draminit_mc( const fapi2::Target<TARGET_TYPE_MCBIST>& i_target )
    {
        auto l_mca = i_target.getChildren<TARGET_TYPE_MCA>();

        FAPI_INF("Start draminit MC");

        // If we don't have any ports, lets go.
        if (l_mca.size() == 0)
        {
            FAPI_INF("No ports? %s", mss::c_str(i_target));
            return fapi2::FAPI2_RC_SUCCESS;
        }

        // While we're doing the scominit in here, lets do it for all ports before we dump the MCS regs.
        for (auto p : i_target.getChildren<TARGET_TYPE_MCA>())
        {
            mss::mc<TARGET_TYPE_MCS> l_mc;

            // Don't do this yet - leverage the sim inits for the moment
#if 0
            // All the scominit for this MCA
            l_mc.scominit(p);
#endif
            // Setup the MC port/dimm address translation registers
            FAPI_TRY( l_mc.setup_xlate_map(p) );
        }

        for (auto p : l_mca)
        {

            // Setup the read_pointer_delay
            // TK: Do we need to do this in general or is this a place holder until the
            // init file gets here?
            {
                fapi2::buffer<uint64_t> l_data;
                FAPI_TRY( mss::getScom(p, MCA_RECR, l_data) );
                l_data.insertFromRight<MCA_RECR_MBSECCQ_READ_POINTER_DELAY, MCA_RECR_MBSECCQ_READ_POINTER_DELAY_LEN>(0x1);
                FAPI_DBG("writing read pointer delay 0x%016lx %s", l_data, mss::c_str(p));
                FAPI_TRY( mss::putScom(p, MCA_RECR, l_data) );
            }

            // Set the IML Complete bit MBSSQ(3) (SCOM Addr: 0x02011417) to indicate that IML has completed
            // Can't find MBSSQ or the iml_complete bit - asked Steve. Gary VH created this bit as a scratch
            // 'you are hre bit' and it was removed for Nimbus. Gary VH asked for it to be put back in. Not
            // sure if that happened yet. BRS (2/16).

            // Reset addr_mux_sel to “0” to allow the MCA to take control of the DDR interface over from CCS.
            // (Note: this step must remain in this procedure to ensure that data path is placed into mainline
            // mode prior to running memory diagnostics. This step maybe superfluous but not harmful.)
            // Note: addr_mux_sel is set low in p9_mss_draminit(), however that might be a work-around so we
            // set it low here kind of like belt-and-suspenders. BRS
            FAPI_TRY( mss::change_addr_mux_sel(p, mss::LOW) );

            // Re-enable port fails. Turned off in draminit_training
            FAPI_TRY( mss::change_port_fail_disable(p, mss::OFF ) );

            // Step Two.1: Check RCD protect time on RDIMM and LRDIMM
            // Step Two.2: Enable address inversion on each MBA for ALL CARDS

            // Start the refresh engines by setting MBAREF0Q(0) = “1”. Note that the remaining bits in
            // MBAREF0Q should retain their initialization values.
            FAPI_TRY( mss::change_refresh_enable(p, mss::HIGH) );

            // Power management is handled in the init file. (or should be BRS)

            // Enabling periodic calibration
            FAPI_TRY( mss::enable_periodic_cal(p) );

            // Step Six: Setup Control Bit ECC
            FAPI_TRY( mss::enable_read_ecc(p) );

            // At this point the DDR interface must be monitored for memory errors. Memory related FIRs should be unmasked.

            // Cram a fast write, followed by a read in here for giggles
            {
                mss::mcbist::program<TARGET_TYPE_MCBIST> l_program;
                uint64_t l_start = 0;
                uint64_t l_end = 0;
                uint64_t l_pattern = 0;

                // Write
                {
                    // Uses address register set 0
                    mss::mcbist::subtest_t<TARGET_TYPE_MCBIST> l_fw_subtest =
                        mss::mcbist::write_subtest<TARGET_TYPE_MCBIST>();
                    l_fw_subtest.enable_port(mss::relative_pos<TARGET_TYPE_MCBIST>(p));

                    // Run in ECC mode

                    // HACK: We only need to worry about the DIMM in slot 0 right now
                    l_fw_subtest.enable_dimm(0);
                    l_program.iv_subtests.push_back(l_fw_subtest);
                }

                // Read
                {
                    // Uses address register set 0
                    mss::mcbist::subtest_t<TARGET_TYPE_MCBIST> l_fr_subtest =
                        mss::mcbist::read_subtest<TARGET_TYPE_MCBIST>();
                    l_fr_subtest.enable_port(mss::relative_pos<TARGET_TYPE_MCBIST>(p));

                    // Run in ECC mode

                    // HACK: We only need to worry about the DIMM in slot 0 right now
                    l_fr_subtest.enable_dimm(0);
                    l_program.iv_subtests.push_back(l_fr_subtest);
                }

                FAPI_TRY( mss::mcbist_start_addr(p, l_start) );
                FAPI_TRY( mss::mcbist_end_addr(p, l_end) );

                // TK: calculate proper polling based on address range

                // Setup a nice pattern for writing
                FAPI_TRY( mss::mcbist_write_data(i_target, l_pattern) );
                FAPI_TRY( mss::putScom(i_target, MCBIST_MCBFD0Q, l_pattern) );
                FAPI_TRY( mss::putScom(i_target, MCBIST_MCBFD1Q, l_pattern) );
                FAPI_TRY( mss::putScom(i_target, MCBIST_MCBFD2Q, l_pattern) );
                FAPI_TRY( mss::putScom(i_target, MCBIST_MCBFD3Q, l_pattern) );
                FAPI_TRY( mss::putScom(i_target, MCBIST_MCBFD4Q, l_pattern) );
                FAPI_TRY( mss::putScom(i_target, MCBIST_MCBFD5Q, l_pattern) );
                FAPI_TRY( mss::putScom(i_target, MCBIST_MCBFD6Q, l_pattern) );
                FAPI_TRY( mss::putScom(i_target, MCBIST_MCBFD7Q, l_pattern) );

                // Sanity check - can't do much if end is before start.
                // This is either a programming error or a mistake in attribute settings. So we'll just assert.
                if (l_end < l_start)
                {
                    FAPI_ERR("mcbist end address is less than mcbist starting address. s: 0x%x e: 0x%x", l_start, l_end);
                    fapi2::Assert(false);
                }

                // By default we're in maint address mode so we do a start + len and the 'BIST increments for us.
                // By default, the write subtest uses the 0'th address start/end registers.
                mss::mcbist::config_address_range0(i_target, l_start, l_end - l_start);

                // Setup the polling based on a heuristic <cough>guess</cough>
                // Looks like 20ns per address for a write/read program, and add a long number of polls
                l_program.iv_poll.iv_initial_delay = (l_end - l_start) * 2 * mss::DELAY_10NS;
                l_program.iv_poll.iv_initial_sim_delay =
                    mss::cycles_to_simcycles(mss::ns_to_cycles(i_target, l_program.iv_poll.iv_initial_delay));
                l_program.iv_poll.iv_poll_count = 100;

                // Just one port for now. Per Shelton we need to set this in maint adress mode
                // even tho we specify the port/dimm in the subtest.
                fapi2::buffer<uint8_t> l_port;
                l_port.setBit(mss::relative_pos<TARGET_TYPE_MCBIST>(p));
                l_program.select_ports(l_port >> 4);

                // Kick it off, wait for a result
                FAPI_TRY( mss::mcbist::execute(i_target, l_program) );
            }
        }

    fapi_try_exit:
        FAPI_INF("End draminit MC");
        return fapi2::current_err;
    }
}
<commit_msg>Add L2 p9_mss_scrub<commit_after>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/memory/p9_mss_draminit_mc.C $ */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2015,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* Licensed under the Apache License, Version 2.0 (the "License");        */
/* you may not use this file except in compliance with the License.       */
/* You may obtain a copy of the License at                                */
/*                                                                        */
/*     http://www.apache.org/licenses/LICENSE-2.0                         */
/*                                                                        */
/* Unless required by applicable law or agreed to in writing, software    */
/* distributed under the License is distributed on an "AS IS" BASIS,      */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or        */
/* implied. See the License for the specific language governing           */
/* permissions and limitations under the License.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */

///
/// @file p9_mss_draminit_mc.C
/// @brief Initialize the memory controller to take over the DRAM
///
// *HWP HWP Owner: Brian Silver <bsilver@us.ibm.com>
// *HWP HWP Backup: Andre Marin <aamarin@us.ibm.com>
// *HWP Team: Memory
// *HWP Level: 2
// *HWP Consumed by: FSP:HB

#include <fapi2.H>
#include <mss.H>

#include <p9_mss_draminit_mc.H>

using fapi2::TARGET_TYPE_MCBIST;
using fapi2::TARGET_TYPE_MCA;
using fapi2::TARGET_TYPE_MCS;

extern "C"
{
///
/// @brief Initialize the MC now that DRAM is up
/// @param[in] i_target, the McBIST of the ports
/// @return FAPI2_RC_SUCCESS iff ok
///
    fapi2::ReturnCode p9_mss_draminit_mc( const fapi2::Target<TARGET_TYPE_MCBIST>& i_target )
    {
        FAPI_INF("Start draminit MC");

        // No need to check to see if we have ports - this loop will just be skipped
        for (const auto& p : i_target.getChildren<TARGET_TYPE_MCA>())
        {
            mss::mc<TARGET_TYPE_MCS> l_mc;

            // Don't do this yet - leverage the sim inits for the moment
#if 0
            // All the scominit for this MCA
            l_mc.scominit(p);
#endif
            // Setup the MC port/dimm address translation registers
            FAPI_TRY( l_mc.setup_xlate_map(p) );

            // Setup the read_pointer_delay
            // TK: Do we need to do this in general or is this a place holder until the
            // init file gets here?
            {
                fapi2::buffer<uint64_t> l_data;
                FAPI_TRY( mss::getScom(p, MCA_RECR, l_data) );
                l_data.insertFromRight<MCA_RECR_MBSECCQ_READ_POINTER_DELAY, MCA_RECR_MBSECCQ_READ_POINTER_DELAY_LEN>(0x1);
                FAPI_DBG("writing read pointer delay 0x%016lx %s", l_data, mss::c_str(p));
                FAPI_TRY( mss::putScom(p, MCA_RECR, l_data) );
            }

            // Set the IML Complete bit MBSSQ(3) (SCOM Addr: 0x02011417) to indicate that IML has completed
            // Can't find MBSSQ or the iml_complete bit - asked Steve. Gary VH created this bit as a scratch
            // 'you are hre bit' and it was removed for Nimbus. Gary VH asked for it to be put back in. Not
            // sure if that happened yet. BRS (2/16).

            // Reset addr_mux_sel to “0” to allow the MCA to take control of the DDR interface over from CCS.
            // (Note: this step must remain in this procedure to ensure that data path is placed into mainline
            // mode prior to running memory diagnostics. This step maybe superfluous but not harmful.)
            // Note: addr_mux_sel is set low in p9_mss_draminit(), however that might be a work-around so we
            // set it low here kind of like belt-and-suspenders. BRS
            FAPI_TRY( mss::change_addr_mux_sel(p, mss::LOW) );

            // Re-enable port fails. Turned off in draminit_training
            FAPI_TRY( mss::change_port_fail_disable(p, mss::OFF ) );

            // Step Two.1: Check RCD protect time on RDIMM and LRDIMM
            // Step Two.2: Enable address inversion on each MBA for ALL CARDS

            // Start the refresh engines by setting MBAREF0Q(0) = “1”. Note that the remaining bits in
            // MBAREF0Q should retain their initialization values.
            FAPI_TRY( mss::change_refresh_enable(p, mss::HIGH) );

            // Power management is handled in the init file. (or should be BRS)

            // Enabling periodic calibration
            FAPI_TRY( mss::enable_periodic_cal(p) );

            // Step Six: Setup Control Bit ECC
            FAPI_TRY( mss::enable_read_ecc(p) );

            // At this point the DDR interface must be monitored for memory errors. Memory related FIRs should be unmasked.
        }

    fapi_try_exit:
        FAPI_INF("End draminit MC");
        return fapi2::current_err;
    }
}
<|endoftext|>


<commit_before>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: chips/p9/procedures/hwp/perv/p9_set_fsi_gp_shadow.H $         */
/*                                                                        */
/* IBM CONFIDENTIAL                                                       */
/*                                                                        */
/* EKB Project                                                            */
/*                                                                        */
/* COPYRIGHT 2015,2016                                                    */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* The source code for this program is not published or otherwise         */
/* divested of its trade secrets, irrespective of what has been           */
/* deposited with the U.S. Copyright Office.                              */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */
//------------------------------------------------------------------------------
/// @file  p9_set_fsi_gp_shadow.H
///
/// @brief --IPL step 0.8 proc_prep_ipl
//------------------------------------------------------------------------------
// *HWP HW Owner        : Anusha Reddy Rangareddygari <anusrang@in.ibm.com>
// *HWP HW Backup Owner : Srinivas V Naga <srinivan@in.ibm.com>
// *HWP FW Owner        : Brian Silver <bsilver@us.ibm.com>
// *HWP Team            : Perv
// *HWP Level           : 2
// *HWP Consumed by     : SBE
//------------------------------------------------------------------------------

#ifndef _P9_SET_FSI_GP_SHADOW_H_
#define _P9_SET_FSI_GP_SHADOW_H_

#include <fapi2.H>

namespace p9SetFsiGpShadow
{
enum P9_SET_FSI_GP_SHADOW_Public_Constants
{
    PERV_CTRL0_FLUSHVALUE = 0x7C0E2000,
    PERV_CTRL1_FLUSHVALUE = 0x63C00000,
    ROOT_CTRL1_FLUSHVALUE = 0x00180000,
    ROOT_CTRL2_FLUSHVALUE = 0x0000E000,
    ROOT_CTRL7_FLUSHVALUE = 0x0,
    ROOT_CTRL8_FLUSHVALUE = 0xEEECF300,
    ROOT_CTRL0_FLUSHVALUE = 0x80FF4003,
    ROOT_CTRL3_FLUSHVALUE = 0x0080C000,
    ROOT_CTRL4_FLUSHVALUE = 0x0,
    ROOT_CTRL5_FLUSHVALUE = 0x0,
    ROOT_CTRL6_FLUSHVALUE = 0x00800000
};
}

typedef fapi2::ReturnCode (*p9_set_fsi_gp_shadow_FP_t)(const
        fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>&);

/// @brief --update ROOT CTRL shadows if needed
///
/// @param[in]     i_target_chip   Reference to TARGET_TYPE_PROC_CHIP target
/// @return  FAPI2_RC_SUCCESS if success, else error code.
extern "C"
{
    fapi2::ReturnCode p9_set_fsi_gp_shadow(const
                                           fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>& i_target_chip);
}

#endif
<commit_msg>p9_set_fsi_gp_shadow - updates RC init values<commit_after>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: chips/p9/procedures/hwp/perv/p9_set_fsi_gp_shadow.H $         */
/*                                                                        */
/* IBM CONFIDENTIAL                                                       */
/*                                                                        */
/* EKB Project                                                            */
/*                                                                        */
/* COPYRIGHT 2015,2016                                                    */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* The source code for this program is not published or otherwise         */
/* divested of its trade secrets, irrespective of what has been           */
/* deposited with the U.S. Copyright Office.                              */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */
//------------------------------------------------------------------------------
/// @file  p9_set_fsi_gp_shadow.H
///
/// @brief --IPL step 0.8 proc_prep_ipl
//------------------------------------------------------------------------------
// *HWP HW Owner        : Anusha Reddy Rangareddygari <anusrang@in.ibm.com>
// *HWP HW Backup Owner : Srinivas V Naga <srinivan@in.ibm.com>
// *HWP FW Owner        : Brian Silver <bsilver@us.ibm.com>
// *HWP Team            : Perv
// *HWP Level           : 2
// *HWP Consumed by     : SBE
//------------------------------------------------------------------------------

#ifndef _P9_SET_FSI_GP_SHADOW_H_
#define _P9_SET_FSI_GP_SHADOW_H_

#include <fapi2.H>

namespace p9SetFsiGpShadow
{
enum P9_SET_FSI_GP_SHADOW_Public_Constants
{
    PERV_CTRL0_FLUSHVALUE = 0x7C0E2000,
    PERV_CTRL1_FLUSHVALUE = 0x63C00000,
    ROOT_CTRL1_FLUSHVALUE = 0x00180000,
    ROOT_CTRL2_FLUSHVALUE = 0x0400E000,
    ROOT_CTRL7_FLUSHVALUE = 0x0,
    ROOT_CTRL8_FLUSHVALUE = 0xEEEEF300,
    ROOT_CTRL0_FLUSHVALUE = 0x80FF4003,
    ROOT_CTRL3_FLUSHVALUE = 0x0080C000,
    ROOT_CTRL4_FLUSHVALUE = 0x0,
    ROOT_CTRL5_FLUSHVALUE = 0x0,
    ROOT_CTRL6_FLUSHVALUE = 0x00800000
};
}

typedef fapi2::ReturnCode (*p9_set_fsi_gp_shadow_FP_t)(const
        fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>&);

/// @brief --update ROOT CTRL shadows if needed
///
/// @param[in]     i_target_chip   Reference to TARGET_TYPE_PROC_CHIP target
/// @return  FAPI2_RC_SUCCESS if success, else error code.
extern "C"
{
    fapi2::ReturnCode p9_set_fsi_gp_shadow(const
                                           fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>& i_target_chip);
}

#endif
<|endoftext|>


<commit_before>#include <ros/ros.h>
#include <cv_bridge/cv_bridge.h>
#include <geometry_msgs/Point.h>
#include <geometry_msgs/PointStamped.h>
#include <image_transport/image_transport.h>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/video/video.hpp>
#include <sensor_msgs/image_encodings.h>

class ShowImage {
public:
  ShowImage()
    : m_gamma(2048),
      RGB_WINDOW_NAME {"RGB image"},
      DEPTH_WINDOW_NAME {"Depth image"},
      BINARY_WINDOW_NAME {"Binary image"}
  {
    for(int i = 0; i < 2048; i++) {
      float v = i / 2048.0;
      v = std::pow(v, 3) * 6;
      m_gamma[i] = v * 6 * 256;
    }

    cv::namedWindow(RGB_WINDOW_NAME);
    cv::namedWindow(DEPTH_WINDOW_NAME);
    cv::namedWindow(BINARY_WINDOW_NAME);
  }

  ~ShowImage() {
    cv::destroyWindow(RGB_WINDOW_NAME);
    cv::destroyWindow(DEPTH_WINDOW_NAME);
    cv::destroyWindow(BINARY_WINDOW_NAME);
  }

  void showRGB(const cv::Mat& rgb) {
    imshow(RGB_WINDOW_NAME, rgb);
  }

  void showBinary(const cv::Mat& binary) {
    imshow(BINARY_WINDOW_NAME, binary);
  }

  void showDepth(const cv::Mat& depth) {
    cv::Mat buf = cv::Mat::zeros(depth.size(), CV_16UC1);
    cv::Mat output = cv::Mat::zeros(depth.size(), CV_8UC3);
    cv::normalize(depth, buf, 0, 2013, cv::NORM_MINMAX);

    for (int i = 0; i < depth.rows * depth.cols; i++) {
      int y = (int)(i / depth.cols);
      int x = (int)(i % depth.cols);
      int pval = m_gamma[buf.at<uint16_t>(i)];
      int lb = pval & 0xff;

      switch(pval >> 8) {
      case 0:
        output.at<cv::Vec3b>(y,x)[2] = 255;
        output.at<cv::Vec3b>(y,x)[1] = 255-lb;
        output.at<cv::Vec3b>(y,x)[0] = 255-lb;
        break;
      case 1:
        output.at<cv::Vec3b>(y,x)[2] = 255;
        output.at<cv::Vec3b>(y,x)[1] = lb;
        output.at<cv::Vec3b>(y,x)[0] = 0;
        break;
      case 2:
        output.at<cv::Vec3b>(y,x)[2] = 255-lb;
        output.at<cv::Vec3b>(y,x)[1] = 255;
        output.at<cv::Vec3b>(y,x)[0] = 0;
        break;
      case 3:
        output.at<cv::Vec3b>(y,x)[2] = 0;
        output.at<cv::Vec3b>(y,x)[1] = 255;
        output.at<cv::Vec3b>(y,x)[0] = lb;
        break;
      case 4:
        output.at<cv::Vec3b>(y,x)[2] = 0;
        output.at<cv::Vec3b>(y,x)[1] = 255-lb;
        output.at<cv::Vec3b>(y,x)[0] = 255;
        break;
      case 5:
        output.at<cv::Vec3b>(y,x)[2] = 0;
        output.at<cv::Vec3b>(y,x)[1] = 0;
        output.at<cv::Vec3b>(y,x)[0] = 255-lb;
        break;
      default:
        output.at<cv::Vec3b>(y,x)[2] = 0;
        output.at<cv::Vec3b>(y,x)[1] = 0;
        output.at<cv::Vec3b>(y,x)[0] = 0;
        break;
      }
    }
    imshow(DEPTH_WINDOW_NAME, output);
  }

private:
  std::vector<uint16_t> m_gamma;
  const std::string RGB_WINDOW_NAME;
  const std::string DEPTH_WINDOW_NAME;
  const std::string BINARY_WINDOW_NAME;
};

class SearchTomato {
public:
  SearchTomato()
    : tomato_contours {},
      siObj {}
  {
  }

  void update(const cv::Mat& capture_rgb) {
    siObj.showRGB(capture_rgb);
    cv::Mat binary_mat = cv::Mat::zeros(capture_rgb.size(), CV_8UC1);
    imageProsessing(capture_rgb, binary_mat);
    siObj.showBinary(binary_mat);
    searchTomatoContours(binary_mat, tomato_contours);
  }

  bool searchTomato(const cv::Mat& capture_depth, geometry_msgs::Point& tomato_point) {
    siObj.showDepth(capture_depth);
    cv::Mat maskedDepth = cv::Mat::zeros(capture_depth.size(), CV_16UC1);
    cv::Mat mask = cv::Mat::zeros(capture_depth.size(), CV_8UC1);
    cv::drawContours(mask, tomato_contours, -1, cv::Scalar(255), CV_FILLED, 8);
    siObj.showBinary(mask);

    capture_depth.copyTo(maskedDepth, mask);
    return findClosePoint(maskedDepth, tomato_point);
  }

private:
  void imageProsessing(const cv::Mat& rgb, cv::Mat& binary) {
    cv::Mat blur, hsv;
    cv::GaussianBlur(rgb, blur, cv::Size(5, 5), 4.0, 4.0);
    cv::cvtColor(blur, hsv, CV_BGR2HSV);
    redFilter(hsv, binary);
    cv::dilate(binary, binary, cv::Mat(), cv::Point(-1, -1), 2);
    cv::erode(binary, binary, cv::Mat(), cv::Point(-1, -1), 4);
    cv::dilate(binary, binary, cv::Mat(), cv::Point(-1, -1), 1);
  }

  void searchTomatoContours(const cv::Mat& binary, std::vector<std::vector<cv::Point> >& tomato_contours) {
    std::vector<std::vector<cv::Point> > contours;
    std::vector<cv::Point> contour;
    cv::Rect bounding_box;
    float ratio_balance;

    cv::findContours(binary, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);

    tomato_contours.clear();
    while (!contours.empty()) {
      contour = contours.back();
      contours.pop_back();

      bounding_box = cv::boundingRect(contour);
      ratio_balance = (float)bounding_box.width / (float)bounding_box.height;
      if (ratio_balance > 1.0f) ratio_balance = 1.0f / ratio_balance;

      // delete mismach. that is smaller or spier or empty
      if (bounding_box.area() >= 400 && bounding_box.area() < cv::contourArea(contour)*2 && ratio_balance > 0.4f)
        tomato_contours.push_back(contour);
    }
  }

  void redFilter(const cv::Mat& hsv, cv::Mat& binary) {
    int a, x, y;
    for(y = 0; y < hsv.rows; y++) {
      for(x = 0; x < hsv.cols; x++) {
        a = hsv.step*y+(x*3);
        if((hsv.data[a] <= 15 || hsv.data[a] >= 300) && hsv.data[a+1] >= 30 && hsv.data[a+2] >= 50)
          binary.at<unsigned char>(y,x) = 255;
        else
          binary.at<unsigned char>(y,x) = 0;
      }
    }
  }

  bool findClosePoint(const cv::Mat& maskedDepth, geometry_msgs::Point& tomato_point) {
    uint16_t depth;
    constexpr uint16_t OVER_RANGE = 3000;
    uint16_t close_depth = OVER_RANGE;

    for (int y = 0; y < maskedDepth.rows; y++) {
      const uint16_t* line_point = maskedDepth.ptr<uint16_t>(y);
      for (int x = 0; x < maskedDepth.cols; x++) {
        depth = line_point[x];
        if (512 < depth && depth <  close_depth) {
          tomato_point.x = depth; // for ros coordinate system
          tomato_point.y = x - maskedDepth.cols / 2; // for ros coordinate system
          tomato_point.z = -(y - maskedDepth.rows / 2); // for ros coordinate system
          close_depth = depth;
        }
      }
    }
    return (close_depth != OVER_RANGE ? true : false);
  }

  std::vector<std::vector<cv::Point> > tomato_contours;
  ShowImage siObj;
};

class ImageConverter {
private:
  ros::NodeHandle nh;
  ros::NodeHandle tomapo_nh;
  ros::Publisher point_pub;
  geometry_msgs::Point pub_msg;
  image_transport::ImageTransport it;
  image_transport::Subscriber rgb_sub;
  image_transport::Subscriber depth_sub;
  cv_bridge::CvImageConstPtr rgb_ptr;
  cv_bridge::CvImageConstPtr depth_ptr;
  SearchTomato stObj;
  const std::size_t height_;
  const double angle_x_per_piccell_;
  const double angle_y_per_piccell_;
  static constexpr double PI {3.141592653589793};

public:
  ImageConverter(const std::size_t width, const std::size_t height, const double angle_of_view_x, const double angle_of_view_y)
    : nh {},
      tomapo_nh {nh, "tomato_point"},
      point_pub {tomapo_nh.advertise<geometry_msgs::PointStamped>("raw", 1)},
      it {nh},
      rgb_sub {it.subscribe("rgb", 1, &ImageConverter::rgbCb, this)},
      depth_sub {it.subscribe("depth", 1, &ImageConverter::depthCb, this)},
      stObj {},
      height_ {height},
      angle_x_per_piccell_ {(angle_of_view_x * PI / 180.0) / width},
      angle_y_per_piccell_ {(angle_of_view_y * PI / 180.0) / height}
  {
  }

  /**
   * search tomato function.
   * get rgb image, and search tomato.
   * will tomato_point have data.
   *
   * @author Yusuke Doi
   */
  void rgbCb(const sensor_msgs::ImageConstPtr& msg) {
    // get rgb image on kinect
    try {
      rgb_ptr = cv_bridge::toCvShare(msg, "bgr8");
    } catch (cv_bridge::Exception& e) {
      ROS_ERROR("cv_bridge exception by rgb: %s", e.what());
    }

    stObj.update(rgb_ptr->image);

    cv::waitKey(100);
  }

  void depthCb(const sensor_msgs::ImageConstPtr& msg) {
    try {
      depth_ptr = cv_bridge::toCvShare(msg, sensor_msgs::image_encodings::TYPE_16UC1);
    } catch (cv_bridge::Exception& e) {
      ROS_ERROR("cv_bridge exception by depth: %s", e.what());
    }

    if (stObj.searchTomato(depth_ptr->image, pub_msg)) {
      pub_msg.y = pub_msg.x * tan(angle_x_per_piccell_ * pub_msg.y) / 1000.0; // convert to m
      pub_msg.z = pub_msg.x * tan(angle_y_per_piccell_ * pub_msg.z) / 1000.0; // convert to m
      pub_msg.x = pub_msg.x / 1000.0; // convert to m
      geometry_msgs::PointStamped stamped_msg; // FIXME: rename to pub_msg
      stamped_msg.header.stamp = ros::Time::now();
      stamped_msg.header.frame_id = "kinect";
      stamped_msg.point = pub_msg;
      point_pub.publish(stamped_msg);
    }

    cv::waitKey(100);
  }
};

int main(int argc, char** argv) {
  ros::init(argc, argv, "kinect_tomato_searcher_node");
  ImageConverter ic {512, 424, 70, 60};
  ros::spin();
  return 0;
}
<commit_msg>Update for PoseArray message<commit_after>#include <ros/ros.h>
#include <cv_bridge/cv_bridge.h>
#include <geometry_msgs/Point.h>
#include <geometry_msgs/PointStamped.h>
#include <geometry_msgs/Pose.h>
#include <geometry_msgs/PoseArray.h>
#include <image_transport/image_transport.h>
#include <sensor_msgs/image_encodings.h>

#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/video/video.hpp>

class ShowImage {
public:
  ShowImage()
    : m_gamma(2048),
      RGB_WINDOW_NAME {"RGB image"},
      DEPTH_WINDOW_NAME {"Depth image"},
      BINARY_WINDOW_NAME {"Binary image"}
  {
    for(int i = 0; i < 2048; i++) {
      float v = i / 2048.0;
      v = std::pow(v, 3) * 6;
      m_gamma[i] = v * 6 * 256;
    }

    cv::namedWindow(RGB_WINDOW_NAME);
    cv::namedWindow(DEPTH_WINDOW_NAME);
    cv::namedWindow(BINARY_WINDOW_NAME);
  }

  ~ShowImage() {
    cv::destroyWindow(RGB_WINDOW_NAME);
    cv::destroyWindow(DEPTH_WINDOW_NAME);
    cv::destroyWindow(BINARY_WINDOW_NAME);
  }

  void showRGB(const cv::Mat& rgb) {
    imshow(RGB_WINDOW_NAME, rgb);
  }

  void showBinary(const cv::Mat& binary) {
    imshow(BINARY_WINDOW_NAME, binary);
  }

  void showDepth(const cv::Mat& depth) {
    cv::Mat buf = cv::Mat::zeros(depth.size(), CV_16UC1);
    cv::Mat output = cv::Mat::zeros(depth.size(), CV_8UC3);
    cv::normalize(depth, buf, 0, 2013, cv::NORM_MINMAX);

    for (int i = 0; i < depth.rows * depth.cols; i++) {
      int y = (int)(i / depth.cols);
      int x = (int)(i % depth.cols);
      int pval = m_gamma[buf.at<uint16_t>(i)];
      int lb = pval & 0xff;

      switch(pval >> 8) {
      case 0:
        output.at<cv::Vec3b>(y,x)[2] = 255;
        output.at<cv::Vec3b>(y,x)[1] = 255-lb;
        output.at<cv::Vec3b>(y,x)[0] = 255-lb;
        break;
      case 1:
        output.at<cv::Vec3b>(y,x)[2] = 255;
        output.at<cv::Vec3b>(y,x)[1] = lb;
        output.at<cv::Vec3b>(y,x)[0] = 0;
        break;
      case 2:
        output.at<cv::Vec3b>(y,x)[2] = 255-lb;
        output.at<cv::Vec3b>(y,x)[1] = 255;
        output.at<cv::Vec3b>(y,x)[0] = 0;
        break;
      case 3:
        output.at<cv::Vec3b>(y,x)[2] = 0;
        output.at<cv::Vec3b>(y,x)[1] = 255;
        output.at<cv::Vec3b>(y,x)[0] = lb;
        break;
      case 4:
        output.at<cv::Vec3b>(y,x)[2] = 0;
        output.at<cv::Vec3b>(y,x)[1] = 255-lb;
        output.at<cv::Vec3b>(y,x)[0] = 255;
        break;
      case 5:
        output.at<cv::Vec3b>(y,x)[2] = 0;
        output.at<cv::Vec3b>(y,x)[1] = 0;
        output.at<cv::Vec3b>(y,x)[0] = 255-lb;
        break;
      default:
        output.at<cv::Vec3b>(y,x)[2] = 0;
        output.at<cv::Vec3b>(y,x)[1] = 0;
        output.at<cv::Vec3b>(y,x)[0] = 0;
        break;
      }
    }
    imshow(DEPTH_WINDOW_NAME, output);
  }

private:
  std::vector<uint16_t> m_gamma;
  const std::string RGB_WINDOW_NAME;
  const std::string DEPTH_WINDOW_NAME;
  const std::string BINARY_WINDOW_NAME;
};

class SearchTomato {
public:
  SearchTomato()
    : tomato_contours {},
      siObj {}
  {
  }

  void update(const cv::Mat& capture_rgb) {
    siObj.showRGB(capture_rgb);
    cv::Mat binary_mat = cv::Mat::zeros(capture_rgb.size(), CV_8UC1);
    imageProsessing(capture_rgb, binary_mat);
    siObj.showBinary(binary_mat);
    searchTomatoContours(binary_mat, tomato_contours);
  }

  bool searchTomato(const cv::Mat& capture_depth, geometry_msgs::Point& tomato_point) {
    siObj.showDepth(capture_depth);
    cv::Mat maskedDepth = cv::Mat::zeros(capture_depth.size(), CV_16UC1);
    cv::Mat mask = cv::Mat::zeros(capture_depth.size(), CV_8UC1);
    cv::drawContours(mask, tomato_contours, -1, cv::Scalar(255), CV_FILLED, 8);
    siObj.showBinary(mask);

    capture_depth.copyTo(maskedDepth, mask);
    return findClosePoint(maskedDepth, tomato_point);
  }

  bool searchTomato(const cv::Mat& capture_depth, geometry_msgs::PoseArray& tomato_poses) {
    tomato_poses.poses.clear();
    siObj.showDepth(capture_depth);
    cv::Mat maskedDepth = cv::Mat::zeros(capture_depth.size(), CV_16UC1);
    cv::Mat mask = cv::Mat::zeros(capture_depth.size(), CV_8UC1);
    for (std::size_t i {0}; i < tomato_contours.size(); ++i) {
      cv::drawContours(mask, tomato_contours, i, cv::Scalar(255), CV_FILLED, 8);
      siObj.showBinary(mask);

      capture_depth.copyTo(maskedDepth, mask);
      return findClosePoint(maskedDepth, tomato_poses);
    }
  }

private:
  void imageProsessing(const cv::Mat& rgb, cv::Mat& binary) {
    cv::Mat blur, hsv;
    cv::GaussianBlur(rgb, blur, cv::Size(5, 5), 4.0, 4.0);
    cv::cvtColor(blur, hsv, CV_BGR2HSV);
    redFilter(hsv, binary);
    cv::dilate(binary, binary, cv::Mat(), cv::Point(-1, -1), 2);
    cv::erode(binary, binary, cv::Mat(), cv::Point(-1, -1), 4);
    cv::dilate(binary, binary, cv::Mat(), cv::Point(-1, -1), 1);
  }

  void searchTomatoContours(const cv::Mat& binary, std::vector<std::vector<cv::Point> >& tomato_contours) {
    std::vector<std::vector<cv::Point> > contours;
    std::vector<cv::Point> contour;
    cv::Rect bounding_box;
    float ratio_balance;

    cv::findContours(binary, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);

    tomato_contours.clear();
    while (!contours.empty()) {
      contour = contours.back();
      contours.pop_back();

      bounding_box = cv::boundingRect(contour);
      ratio_balance = (float)bounding_box.width / (float)bounding_box.height;
      if (ratio_balance > 1.0f) ratio_balance = 1.0f / ratio_balance;

      // delete mismach. that is smaller or spier or empty
      if (bounding_box.area() >= 400 && bounding_box.area() < cv::contourArea(contour)*2 && ratio_balance > 0.4f)
        tomato_contours.push_back(contour);
    }
  }

  void redFilter(const cv::Mat& hsv, cv::Mat& binary) {
    int a, x, y;
    for(y = 0; y < hsv.rows; y++) {
      for(x = 0; x < hsv.cols; x++) {
        a = hsv.step*y+(x*3);
        if((hsv.data[a] <= 15 || hsv.data[a] >= 300) && hsv.data[a+1] >= 30 && hsv.data[a+2] >= 50)
          binary.at<unsigned char>(y,x) = 255;
        else
          binary.at<unsigned char>(y,x) = 0;
      }
    }
  }

  bool findClosePoint(const cv::Mat& maskedDepth, geometry_msgs::Point& tomato_point) {
    uint16_t depth;
    constexpr uint16_t OVER_RANGE = 3000;
    uint16_t close_depth = OVER_RANGE;

    for (int y = 0; y < maskedDepth.rows; y++) {
      const uint16_t* line_point = maskedDepth.ptr<uint16_t>(y);
      for (int x = 0; x < maskedDepth.cols; x++) {
        depth = line_point[x];
        if (512 < depth && depth <  close_depth) {
          tomato_point.x = depth; // for ros coordinate system
          tomato_point.y = x - maskedDepth.cols / 2; // for ros coordinate system
          tomato_point.z = -(y - maskedDepth.rows / 2); // for ros coordinate system
          close_depth = depth;
        }
      }
    }
    return (close_depth != OVER_RANGE ? true : false);
  }

  bool findClosePoint(const cv::Mat& maskedDepth, geometry_msgs::PoseArray& tomato_poses) {
    geometry_msgs::Point tomato_point {};
    if (findClosePoint(maskedDepth, tomato_point)) {
      geometry_msgs::Pose tomato_pose {};
      tomato_pose.position = tomato_point;
      tomato_pose.orientation.w = 1.0;
      tomato_poses.poses.push_back(tomato_pose);
    }
    return tomato_poses.poses.empty() ? false : true;
  }

  std::vector<std::vector<cv::Point> > tomato_contours;
  ShowImage siObj;
};

class ImageConverter {
private:
  ros::NodeHandle nh;
  ros::NodeHandle tomapo_nh;
  ros::Publisher poses_pub;
  geometry_msgs::PoseArray pub_msg;
  image_transport::ImageTransport it;
  image_transport::Subscriber rgb_sub;
  image_transport::Subscriber depth_sub;
  cv_bridge::CvImageConstPtr rgb_ptr;
  cv_bridge::CvImageConstPtr depth_ptr;
  SearchTomato stObj;
  const std::size_t height_;
  const double angle_x_per_piccell_;
  const double angle_y_per_piccell_;
  static constexpr double PI {3.141592653589793};

public:
  ImageConverter(const std::size_t width, const std::size_t height, const double angle_of_view_x, const double angle_of_view_y)
    : nh {},
      tomapo_nh {nh, "tomato_point"},
      poses_pub {tomapo_nh.advertise<geometry_msgs::PoseArray>("raw", 1)},
      it {nh},
      rgb_sub {it.subscribe("rgb", 1, &ImageConverter::rgbCb, this)},
      depth_sub {it.subscribe("depth", 1, &ImageConverter::depthCb, this)},
      stObj {},
      height_ {height},
      angle_x_per_piccell_ {(angle_of_view_x * PI / 180.0) / width},
      angle_y_per_piccell_ {(angle_of_view_y * PI / 180.0) / height}
  {
  }

  /**
   * search tomato function.
   * get rgb image, and search tomato.
   * will tomato_point have data.
   *
   * @author Yusuke Doi
   */
  void rgbCb(const sensor_msgs::ImageConstPtr& msg) {
    // get rgb image on kinect
    try {
      rgb_ptr = cv_bridge::toCvShare(msg, "bgr8");
    } catch (cv_bridge::Exception& e) {
      ROS_ERROR("cv_bridge exception by rgb: %s", e.what());
    }

    stObj.update(rgb_ptr->image);

    cv::waitKey(100);
  }

  void depthCb(const sensor_msgs::ImageConstPtr& msg) {
    try {
      depth_ptr = cv_bridge::toCvShare(msg, sensor_msgs::image_encodings::TYPE_16UC1);
    } catch (cv_bridge::Exception& e) {
      ROS_ERROR("cv_bridge exception by depth: %s", e.what());
    }

    if (stObj.searchTomato(depth_ptr->image, pub_msg)) {
      for (auto tomato_pose : pub_msg.poses) {
        tomato_pose.position.y = tomato_pose.position.x * tan(angle_x_per_piccell_ * tomato_pose.position.y) / 1000.0; // convert to m
        tomato_pose.position.z = tomato_pose.position.x * tan(angle_y_per_piccell_ * tomato_pose.position.z) / 1000.0; // convert to m
        tomato_pose.position.x = tomato_pose.position.x / 1000.0; // convert to m
        poses_pub.publish(pub_msg);
      }
    }

    cv::waitKey(100);
  }
};

int main(int argc, char** argv) {
  ros::init(argc, argv, "kinect_tomato_searcher_node");
  ImageConverter ic {512, 424, 70, 60};
  ros::spin();
  return 0;
}
<|endoftext|>


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

#include <numeric>

#include "group_conv.hpp"

#include "ngraph/op/convolution.hpp"
#include "ngraph/op/get_output_element.hpp"
#include "ngraph/util.hpp"

using namespace std;
using namespace ngraph;

op::GroupConvolution::GroupConvolution(const shared_ptr<Node>& data_batch,
                                       const shared_ptr<Node>& filters,
                                       const Strides& window_movement_strides,
                                       const Strides& window_dilation_strides,
                                       const CoordinateDiff& padding_below,
                                       const CoordinateDiff& padding_above,
                                       const Strides& data_dilation_strides,
                                       size_t groups,
                                       const Shape& output_shape)
    : RequiresTensorViewArgs("GroupConvolution", {data_batch, filters})
    , m_window_movement_strides(window_movement_strides)
    , m_window_dilation_strides(window_dilation_strides)
    , m_padding_below(padding_below)
    , m_padding_above(padding_above)
    , m_data_dilation_strides(data_dilation_strides)
    , m_groups(groups)
{
    auto& data_batch_et = data_batch->get_element_type();
    auto& filters_et = filters->get_element_type();

    //
    // Make sure data batch and filter element types match.
    //
    if (data_batch_et != filters_et)
    {
        throw ngraph_error("Convolution data batch and filter element types do not match");
    }

    set_value_type_checked(data_batch_et, output_shape);
}

Shape op::GroupConvolution::get_weights_dimensions() const
{
    //reshape weights into 5d tensors that includes groups
    const size_t OC = 0;
    const size_t IC = 1;
    Shape weights_shape_groups{get_inputs().at(1).get_shape()};
    //adjust output and channel given a number of groups

    weights_shape_groups.at(OC) /= get_groups();
    weights_shape_groups.at(IC) = get_inputs().at(0).get_shape().at(IC) / get_groups();
    //push_front the number of groups
    weights_shape_groups.insert(weights_shape_groups.begin(), get_groups());
    return weights_shape_groups;
}

shared_ptr<Node> op::GroupConvolution::copy_with_new_args(const NodeVector& new_args) const
{
    if (new_args.size() != 2)
    {
        throw ngraph_error("Incorrect number of new arguments");
    }

    return make_shared<op::GroupConvolution>(new_args.at(0),
                                             new_args.at(1),
                                             get_window_movement_strides(),
                                             get_window_dilation_strides(),
                                             get_padding_below(),
                                             get_padding_above(),
                                             get_data_dilation_strides(),
                                             get_groups(),
                                             this->get_shape());
}

void op::GroupConvolution::generate_adjoints(autodiff::Adjoints& adjoints, const NodeVector& deltas)
{
    throw ngraph_error("NYI");
}
<commit_msg>Properly setting OC for Group Convolution (#1161)<commit_after>/*******************************************************************************
* Copyright 2017-2018 Intel Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************/

#include <numeric>

#include "group_conv.hpp"

#include "ngraph/op/convolution.hpp"
#include "ngraph/op/get_output_element.hpp"
#include "ngraph/util.hpp"

using namespace std;
using namespace ngraph;

op::GroupConvolution::GroupConvolution(const shared_ptr<Node>& data_batch,
                                       const shared_ptr<Node>& filters,
                                       const Strides& window_movement_strides,
                                       const Strides& window_dilation_strides,
                                       const CoordinateDiff& padding_below,
                                       const CoordinateDiff& padding_above,
                                       const Strides& data_dilation_strides,
                                       size_t groups,
                                       const Shape& output_shape)
    : RequiresTensorViewArgs("GroupConvolution", {data_batch, filters})
    , m_window_movement_strides(window_movement_strides)
    , m_window_dilation_strides(window_dilation_strides)
    , m_padding_below(padding_below)
    , m_padding_above(padding_above)
    , m_data_dilation_strides(data_dilation_strides)
    , m_groups(groups)
{
    auto& data_batch_et = data_batch->get_element_type();
    auto& filters_et = filters->get_element_type();

    //
    // Make sure data batch and filter element types match.
    //
    if (data_batch_et != filters_et)
    {
        throw ngraph_error("Convolution data batch and filter element types do not match");
    }

    set_value_type_checked(data_batch_et, output_shape);
}

Shape op::GroupConvolution::get_weights_dimensions() const
{
    //reshape weights into 5d tensors that includes groups
    const size_t OC = 0;
    const size_t OC_IN_OUTPUT = 1;
    const size_t IC = 1;
    Shape weights_shape_groups{get_inputs().at(1).get_shape()};
    //adjust output and channel given a number of groups

    weights_shape_groups.at(OC) = get_shape().at(OC_IN_OUTPUT) / get_groups();
    weights_shape_groups.at(IC) = get_inputs().at(0).get_shape().at(IC) / get_groups();
    //push_front the number of groups
    weights_shape_groups.insert(weights_shape_groups.begin(), get_groups());
    return weights_shape_groups;
}

shared_ptr<Node> op::GroupConvolution::copy_with_new_args(const NodeVector& new_args) const
{
    if (new_args.size() != 2)
    {
        throw ngraph_error("Incorrect number of new arguments");
    }

    return make_shared<op::GroupConvolution>(new_args.at(0),
                                             new_args.at(1),
                                             get_window_movement_strides(),
                                             get_window_dilation_strides(),
                                             get_padding_below(),
                                             get_padding_above(),
                                             get_data_dilation_strides(),
                                             get_groups(),
                                             this->get_shape());
}

void op::GroupConvolution::generate_adjoints(autodiff::Adjoints& adjoints, const NodeVector& deltas)
{
    throw ngraph_error("NYI");
}
<|endoftext|>


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

  Program:   Visualization Toolkit
  Module:    PacketFileSender.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/
// .NAME PacketFileSender -
// .SECTION Description
// This program reads a pcap file and sends the packets using UDP.

#include "vtkPacketFileReader.h"
#include "vvPacketSender.h"

#include <string>
#include <cstdlib>
#include <iostream>

#include <boost/thread/thread.hpp>

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

  /*if (argc < 2) {
    std::cout << "Usage: " << argv[0] << " <packet file> [loop] [ip] [dataPort] [position Port]" << std::endl;
    return 1;
  }*/
  //std::string filename(argv[1]);

  int loop = 1;
  std::string destinationIp = "10.33.0.20";
  int dataPort=2368;
  int positionPort=8308;
  if(argc > 2)
    {
    loop = atoi(argv[2]);
    }
  if(argc > 3)
    {
    destinationIp = argv[3];
    }
  if(argc>5)
    {
      dataPort=atoi(argv[4]);
      positionPort=atoi(argv[5]);
    }

  try
    {
    do
      {
      vvPacketSender sender("D:\NMEA 2dot3 compliant GPRMC.pcap", destinationIp, dataPort, positionPort);
      //socket.connect(destinationEndpoint);

      while (!sender.done())
        {
        sender.pumpPacket();
        if ((sender.packetCount() % 500) == 0)
          {
          printf("total sent packets: %lu\n", sender.packetCount());
          }

        boost::this_thread::sleep(boost::posix_time::microseconds(200));
        }
      } while(loop);
    }
  catch( std::exception & e )
    {
    std::cout << "Caught Exception: " << e.what() << std::endl;
    return 1;
    }

  return 0;
}
<commit_msg>Restore PacketFileSender<commit_after>// Copyright 2013 Velodyne Acoustics, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/*=========================================================================

  Program:   Visualization Toolkit
  Module:    PacketFileSender.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/
// .NAME PacketFileSender -
// .SECTION Description
// This program reads a pcap file and sends the packets using UDP.

#include "vtkPacketFileReader.h"
#include "vvPacketSender.h"

#include <string>
#include <cstdlib>
#include <iostream>

#include <boost/thread/thread.hpp>

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

  if (argc < 2) {
    std::cout << "Usage: " << argv[0] << " <packet file> [loop] [ip] [dataPort] [position Port]" << std::endl;
    return 1;
  }
  std::string filename(argv[1]);

  int loop = 0;
  std::string destinationIp = "127.0.0.1";
  int dataPort=2368;
  int positionPort=8308;
  if(argc > 2)
    {
    loop = atoi(argv[2]);
    }
  if(argc > 3)
    {
    destinationIp = argv[3];
    }
  if(argc>5)
    {
      dataPort=atoi(argv[4]);
      positionPort=atoi(argv[5]);
    }

  try
    {
    do
      {
      vvPacketSender sender(filename, destinationIp, dataPort, positionPort);

      while (!sender.done())
        {
        sender.pumpPacket();
        if ((sender.packetCount() % 500) == 0)
          {
          printf("total sent packets: %lu\n", sender.packetCount());
          }

        boost::this_thread::sleep(boost::posix_time::microseconds(200));
        }
      } while(loop);
    }
  catch( std::exception & e )
    {
    std::cout << "Caught Exception: " << e.what() << std::endl;
    return 1;
    }

  return 0;
}
<|endoftext|>


<commit_before>// Source : https://oj.leetcode.com/problems/pascals-triangle-ii/
// Author : Hao Chen
// Date   : 2014-06-18

/**********************************************************************************
*
* Given an index k, return the kth row of the Pascal's triangle.
*
* For example, given k = 3,
* Return [1,3,3,1].
*
* Note:
* Could you optimize your algorithm to use only O(k) extra space?
*
*
**********************************************************************************/

#include <stdlib.h>
#include <vector>
#include <iostream>
using namespace std;

vector<int> getRow(int rowIndex) {
    vector<int> v;
    v.push_back(1);
    for(int i=0; i<rowIndex; i++){
        v.push_back(0);
    }

    for (int i=0; i<rowIndex; i++){
        for(int j=i+1; j>0; j--){
           v[j] += v[j-1];
        }
    }
    return v;

}

void printVector( vector<int>  pt)
{
    cout << "{ ";
    for(int j=0; j<pt.size(); j++){
        cout << pt[j] << ", ";
    }
    cout << "} " << endl;
}

int main(int argc, char** argv)
{
    int n = atoi(argv[1]);
    printVector(getRow(n));
}
<commit_msg>simplify the code<commit_after>// Source : https://oj.leetcode.com/problems/pascals-triangle-ii/
// Author : Hao Chen
// Date   : 2014-06-18

/**********************************************************************************
*
* Given an index k, return the kth row of the Pascal's triangle.
*
* For example, given k = 3,
* Return [1,3,3,1].
*
* Note:
* Could you optimize your algorithm to use only O(k) extra space?
*
*
**********************************************************************************/

#include <stdlib.h>
#include <vector>
#include <iostream>
using namespace std;

vector<int> getRow(int rowIndex) {
    vector<int> v(rowIndex+1, 0);
    v[0]=1;

    for (int i=0; i<rowIndex; i++){
        for(int j=i+1; j>0; j--){
           v[j] += v[j-1];
        }
    }
    return v;

}

void printVector( vector<int>  pt)
{
    cout << "{ ";
    for(int j=0; j<pt.size(); j++){
        cout << pt[j] << ", ";
    }
    cout << "} " << endl;
}

int main(int argc, char** argv)
{
    int n = 3;
    if (argc>1) {
        n = atoi(argv[1]);
    }
    printVector(getRow(n));
}
<|endoftext|>


<commit_before>/*
* Copyright (c) 2007 SlimDX Group
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/

#include "Utilities.h"

namespace SlimDX
{
	GUID Utilities::GetNativeGuidForType( Type^ type )
	{
		if( type == nullptr )
			throw gcnew ArgumentNullException( "type" );

		PropertyInfo^ nativeInterfaceProperty = type->GetProperty( "NativeInterface" );
		Guid nativeInterface = static_cast<Guid>( nativeInterfaceProperty->GetValue( nullptr, nullptr ) );

		return ConvertManagedGuid( nativeInterface );
	}

	Guid Utilities::ConvertNativeGuid( const GUID &guid )
	{
		if( guid == GUID_NULL )
			return Guid::Empty;

		Guid result( guid.Data1, guid.Data2, guid.Data3, guid.Data4[0], guid.Data4[1], guid.Data4[2],
			guid.Data4[3], guid.Data4[4], guid.Data4[5], guid.Data4[6], guid.Data4[7] );

		return result;
	}

	GUID Utilities::ConvertManagedGuid( Guid guid )
	{
		if( guid == Guid::Empty )
			return GUID_NULL;

		GUID result;
		array<Byte>^ bytes = guid.ToByteArray();
		pin_ptr<unsigned char> pinned_bytes = &bytes[0];
		memcpy( &result, pinned_bytes, sizeof(GUID) );

		return result;
	}

	bool Utilities::TestForFailure( int hr, Type^ typeToThrow )
	{
		return FAILED( hr );
	}

	/// <summary>
	/// Function to convert a standard RECT to a GDI+ rectangle.
	/// </summary>
	/// <param name="rect">RECT to convert.</param>
	/// <returns>A GDI+ rectangle structure.</returns>
	Drawing::Rectangle Utilities::ConvertRect(RECT rect)
	{
		return Drawing::Rectangle(rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top);
	}

	array<Byte>^ Utilities::ReadStream( Stream^ stream, int readLength )
	{
		if( stream == nullptr )
			throw gcnew ArgumentNullException( "stream" );
		if( !stream->CanRead )
			throw gcnew NotSupportedException();

		if( readLength == 0 )
			readLength = (int) ( stream->Length - stream->Position );
		if( readLength < 0 )
			throw gcnew ArgumentOutOfRangeException( "readLength" );
		if( readLength == 0 )
			return gcnew array<Byte>( 0 );

		array<Byte>^ buffer = gcnew array<Byte>( readLength );
		int bytesRead = 0;

		while( bytesRead < readLength )
		{
			bytesRead += stream->Read( buffer, bytesRead, readLength - bytesRead );
		}

		return buffer;
	}

	generic<typename T>
	void Utilities::CheckArrayBounds( array<T>^ data, int offset, int% count )
	{
		if( count == 0 )
			count = data->Length - offset;

		if( offset < 0 || offset >= data->Length )
			throw gcnew ArgumentOutOfRangeException( "offset" );
		if( count < 0 || count > data->Length - offset )
			throw gcnew ArgumentOutOfRangeException( "count" );
	}

	String^ Utilities::BufferToString( ID3DXBuffer *buffer )
	{
		if( buffer != NULL )
		{
			String^ string = gcnew String( reinterpret_cast<const char*>( buffer->GetBufferPointer() ) );
			buffer->Release();
			return string;
		}
		else
		{
			return String::Empty;
		}
	}
}<commit_msg>GetNativeGuidForType will actually search static properties now, so a null reference exception will no longer be thrown.<commit_after>/*
* Copyright (c) 2007 SlimDX Group
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/

#include "Utilities.h"

namespace SlimDX
{
	GUID Utilities::GetNativeGuidForType( Type^ type )
	{
		if( type == nullptr )
			throw gcnew ArgumentNullException( "type" );

		PropertyInfo^ nativeInterfaceProperty = type->GetProperty( "NativeInterface", BindingFlags::NonPublic | BindingFlags::Static );
		Guid nativeInterface = static_cast<Guid>( nativeInterfaceProperty->GetValue( nullptr, nullptr ) );

		return ConvertManagedGuid( nativeInterface );
	}

	Guid Utilities::ConvertNativeGuid( const GUID &guid )
	{
		if( guid == GUID_NULL )
			return Guid::Empty;

		Guid result( guid.Data1, guid.Data2, guid.Data3, guid.Data4[0], guid.Data4[1], guid.Data4[2],
			guid.Data4[3], guid.Data4[4], guid.Data4[5], guid.Data4[6], guid.Data4[7] );

		return result;
	}

	GUID Utilities::ConvertManagedGuid( Guid guid )
	{
		if( guid == Guid::Empty )
			return GUID_NULL;

		GUID result;
		array<Byte>^ bytes = guid.ToByteArray();
		pin_ptr<unsigned char> pinned_bytes = &bytes[0];
		memcpy( &result, pinned_bytes, sizeof(GUID) );

		return result;
	}

	bool Utilities::TestForFailure( int hr, Type^ typeToThrow )
	{
		return FAILED( hr );
	}

	/// <summary>
	/// Function to convert a standard RECT to a GDI+ rectangle.
	/// </summary>
	/// <param name="rect">RECT to convert.</param>
	/// <returns>A GDI+ rectangle structure.</returns>
	Drawing::Rectangle Utilities::ConvertRect(RECT rect)
	{
		return Drawing::Rectangle(rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top);
	}

	array<Byte>^ Utilities::ReadStream( Stream^ stream, int readLength )
	{
		if( stream == nullptr )
			throw gcnew ArgumentNullException( "stream" );
		if( !stream->CanRead )
			throw gcnew NotSupportedException();

		if( readLength == 0 )
			readLength = (int) ( stream->Length - stream->Position );
		if( readLength < 0 )
			throw gcnew ArgumentOutOfRangeException( "readLength" );
		if( readLength == 0 )
			return gcnew array<Byte>( 0 );

		array<Byte>^ buffer = gcnew array<Byte>( readLength );
		int bytesRead = 0;

		while( bytesRead < readLength )
		{
			bytesRead += stream->Read( buffer, bytesRead, readLength - bytesRead );
		}

		return buffer;
	}

	generic<typename T>
	void Utilities::CheckArrayBounds( array<T>^ data, int offset, int% count )
	{
		if( count == 0 )
			count = data->Length - offset;

		if( offset < 0 || offset >= data->Length )
			throw gcnew ArgumentOutOfRangeException( "offset" );
		if( count < 0 || count > data->Length - offset )
			throw gcnew ArgumentOutOfRangeException( "count" );
	}

	String^ Utilities::BufferToString( ID3DXBuffer *buffer )
	{
		if( buffer != NULL )
		{
			String^ string = gcnew String( reinterpret_cast<const char*>( buffer->GetBufferPointer() ) );
			buffer->Release();
			return string;
		}
		else
		{
			return String::Empty;
		}
	}
}<|endoftext|>


<commit_before>/*
 WinMute
           Copyright (c) 2022, Alexander Steinhoefer

-----------------------------------------------------------------------------
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.

    * Neither the name of the author nor the names of its contributors may
      be used to endorse or promote products derived from this software
      without specific prior written permission.

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 OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
-----------------------------------------------------------------------------
*/

#include "common.h"
#include "WinAudio.h"
#include "MMNotificationClient.h"

class WinAudio;

MMNotificationClient::MMNotificationClient(WinAudio* notifyParent) :
   ref_(1), pEnumerator_(nullptr), notifyParent_(notifyParent)
{
}

MMNotificationClient::~MMNotificationClient()
{
   SafeRelease(&pEnumerator_);
}

ULONG STDMETHODCALLTYPE MMNotificationClient::AddRef()
{
   return InterlockedIncrement(&ref_);
}

ULONG STDMETHODCALLTYPE MMNotificationClient::Release()
{
   ULONG ref = InterlockedDecrement(&ref_);
   if (ref == 0) {
      delete this;
   }
   return ref;
}

HRESULT STDMETHODCALLTYPE MMNotificationClient::QueryInterface(
   REFIID riid, VOID** ppvInterface)
{
   if (IID_IUnknown == riid) {
      AddRef();
      *ppvInterface = (IUnknown*)this;
   } else if (__uuidof(IMMNotificationClient) == riid) {
      AddRef();
      *ppvInterface = (IMMNotificationClient*)this;
   } else {
      *ppvInterface = nullptr;
      return E_NOINTERFACE;
   }
   return S_OK;
}

HRESULT STDMETHODCALLTYPE MMNotificationClient::OnDefaultDeviceChanged(
   EDataFlow, ERole, LPCWSTR)
{
   if (notifyParent_) {
      notifyParent_->ShouldReInit();
   }
   return S_OK;
}

HRESULT STDMETHODCALLTYPE MMNotificationClient::OnDeviceAdded(LPCWSTR)
{
   return S_OK;
}

HRESULT STDMETHODCALLTYPE MMNotificationClient::OnDeviceRemoved(LPCWSTR)
{
   if (notifyParent_) {
      notifyParent_->ShouldReInit();
   }
   return S_OK;
}

HRESULT STDMETHODCALLTYPE MMNotificationClient::OnDeviceStateChanged(
   LPCWSTR, DWORD)
{
   return S_OK;
}

HRESULT STDMETHODCALLTYPE MMNotificationClient::OnPropertyValueChanged(
   LPCWSTR, const PROPERTYKEY)
{
   return S_OK;
}

<commit_msg>Don't reinit when default endpoint changes. Reinit when new devices are added.<commit_after>/*
 WinMute
           Copyright (c) 2022, Alexander Steinhoefer

-----------------------------------------------------------------------------
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.

    * Neither the name of the author nor the names of its contributors may
      be used to endorse or promote products derived from this software
      without specific prior written permission.

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 OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
-----------------------------------------------------------------------------
*/

#include "common.h"
#include "WinAudio.h"
#include "MMNotificationClient.h"

class WinAudio;

MMNotificationClient::MMNotificationClient(WinAudio* notifyParent) :
   ref_(1), pEnumerator_(nullptr), notifyParent_(notifyParent)
{
}

MMNotificationClient::~MMNotificationClient()
{
   SafeRelease(&pEnumerator_);
}

ULONG STDMETHODCALLTYPE MMNotificationClient::AddRef()
{
   return InterlockedIncrement(&ref_);
}

ULONG STDMETHODCALLTYPE MMNotificationClient::Release()
{
   ULONG ref = InterlockedDecrement(&ref_);
   if (ref == 0) {
      delete this;
   }
   return ref;
}

HRESULT STDMETHODCALLTYPE MMNotificationClient::QueryInterface(
   REFIID riid, VOID** ppvInterface)
{
   if (IID_IUnknown == riid) {
      AddRef();
      *ppvInterface = (IUnknown*)this;
   } else if (__uuidof(IMMNotificationClient) == riid) {
      AddRef();
      *ppvInterface = (IMMNotificationClient*)this;
   } else {
      *ppvInterface = nullptr;
      return E_NOINTERFACE;
   }
   return S_OK;
}

HRESULT STDMETHODCALLTYPE MMNotificationClient::OnDefaultDeviceChanged(
   EDataFlow, ERole, LPCWSTR)
{
   return S_OK;
}

HRESULT STDMETHODCALLTYPE MMNotificationClient::OnDeviceAdded(LPCWSTR)
{
   if (notifyParent_) {
      notifyParent_->ShouldReInit();
   }
   return S_OK;
}

HRESULT STDMETHODCALLTYPE MMNotificationClient::OnDeviceRemoved(LPCWSTR)
{
   if (notifyParent_) {
      notifyParent_->ShouldReInit();
   }
   return S_OK;
}

HRESULT STDMETHODCALLTYPE MMNotificationClient::OnDeviceStateChanged(
   LPCWSTR, DWORD)
{
   return S_OK;
}

HRESULT STDMETHODCALLTYPE MMNotificationClient::OnPropertyValueChanged(
   LPCWSTR, const PROPERTYKEY)
{
   return S_OK;
}

<|endoftext|>


<commit_before>//
// This file is part of the Marble Virtual Globe.
//
// This program is free software licensed under the GNU LGPL. You can
// find a copy of this license in LICENSE.txt in the top directory of
// the source code.
//
// Copyright 2010 Wes Hardaker <hardaker@users.sourceforge.net>
//

#include "AprsGatherer.h"

#include <QPixmap>

#include "MarbleDirs.h"
#include "MarbleDebug.h"

using namespace Marble;

AprsGatherer::AprsGatherer( AprsSource *from,
                            QMap<QString, AprsObject *> *objects,
                            QMutex *mutex,
                            QString *filter )
    : m_source( from ),
      m_socket( 0 ),
      m_filter( filter ),
      m_running( true ),
      m_dumpOutput( false ),
      m_seenFrom( GeoAprsCoordinates::FromNowhere ),
      m_sourceName( ),
      m_mutex( mutex ),
      m_objects( objects )
{
    m_sourceName = from->sourceName();
    initMicETables();
}

AprsGatherer::AprsGatherer( QIODevice *from,
                            QMap<QString, AprsObject *> *objects,
                            QMutex *mutex,
                            QString *filter )
    : m_source( 0 ),
      m_socket( from ),
      m_filter( filter ),
      m_running( true ),
      m_dumpOutput( false ),
      m_seenFrom( GeoAprsCoordinates::FromNowhere ),
      m_sourceName( "unknown" ),
      m_mutex( mutex ),
      m_objects( objects )
{
    initMicETables();
}

void
AprsGatherer::run()
{
    char buf[4096];
    qint64 linelength;
    // one particular APRS packet sender can add data after the : ( sigh )
    QRegExp matcher( "^([0-9A-Z]+-*[0-9A-Z]*)>([^:]*):([!=@\\/])([0-9][0-9][0-9][0-9][0-9][0-9]|)([hz\\/]|)([0-9][0-9])([0-9][0-9]\\.[0-9][0-9])([NS])(.)([0-9][0-9][0-9])([0-9][0-9]\\.[0-9][0-9])([EW])(.)" );

    // mic-e formatted
    // 1: src
    // 2: dst
    // 3: routes
    // 4: longitude x 3
    // 5: speed and course x3
    // 6: symbol and symbol ID
    // 7: status text
    QRegExp mic_e_matcher( "^([0-9A-Z]+-*[0-9A-Z]*)>([^,:]*),*([^:]*):['`](...)(...)(..)(.*)" );

    // If a source can directly receive a signal (as opposed to
    // through a relay like the internet) will return true.  This
    // prevents accidentially coloring signals heard over some sources
    // as heard directly where it's never possible (such as over the
    // internet).
    bool canDoDirect = m_source->canDoDirect();

    while( m_running ) {

        if ( m_socket && !m_socket->isOpen() ) {
            // connection closed; attempt to reopen
            mDebug() << "aprs: socket closed; attempting to reopen";
            delete m_socket;
            m_socket = 0;
        }

        if ( !m_socket && m_source )
            m_socket = m_source->openSocket();

        if ( !m_socket ) {
            mDebug() << "aprs: failed to open socket from "
                     << m_sourceName.toLocal8Bit().data();
            sleep( 5 );
            continue;
        }

        // wait for data to read in
        if ( m_socket->bytesAvailable() <= 0 )
            // wait no longer than 1s
            if ( ! m_socket->waitForReadyRead( 1000 ) )
                continue; // continue to loop again on "not ready"

        // Read the line to parse
        linelength = m_socket->readLine( buf, sizeof( buf ) );

        // if we got 0 or less bytes this is probably an odd case; ask
        // the source what to do.
        m_source->checkReadReturn( linelength, &m_socket, this );

        if ( linelength <= 0 ) {
            // don't go into an infinite untimed loop of failed sockets
            sleep( 2 );
            continue;
        }

        if ( m_socket && m_filter != NULL ) {
            QMutexLocker locker( m_mutex );
            if ( m_filter->length() > 0 ) {
                m_socket->write( m_filter->toLocal8Bit().data(),
                                 m_filter->length() );
            }
        }

        // Parse the results
        QString line( buf );

        // Dump it out if we wanted it dumped
        if ( m_dumpOutput )
            mDebug() << "aprs: " << m_sourceName.toLocal8Bit().data()
                     << ": " << line;

        if ( matcher.indexIn( line ) != -1 ) {
            QString callSign  = matcher.cap( 1 );
            qreal latitude = matcher.cap( 6 ).toFloat() +
                ( matcher.cap( 7 ).toFloat()/60 );
            if ( matcher.cap( 8 ) == "S" )
                latitude = - latitude;

            qreal longitude = matcher.cap( 10 ).toFloat() +
                ( matcher.cap( 11 ).toFloat()/60 );
            if ( matcher.cap( 12 ) == "W" )
                longitude = - longitude;

            addObject( callSign, latitude, longitude, canDoDirect,
                       QString( matcher.cap( 2 ) ),
                       QChar( matcher.cap( 9 )[0] ),
                       QChar( matcher.cap( 13 )[0] ) );
        }
        else if ( mic_e_matcher.indexIn( line ) != -1 ) {
            // MIC-E formatted compressed packet
            QString myCall  = mic_e_matcher.cap( 1 );
            QString dstCall = mic_e_matcher.cap( 2 );

            qreal latitude =
                // hours
                m_dstCallDigits[dstCall[0]] * 10 +
                m_dstCallDigits[dstCall[1]] +

                // minutes
                ( qreal( m_dstCallDigits[dstCall[2]] * 10 +
                         m_dstCallDigits[dstCall[3]] ) +
                  qreal( m_dstCallDigits[dstCall[4]] ) / 10.0 +
                  qreal( m_dstCallDigits[dstCall[5]] ) / 100 ) / 60.0;

            if ( m_dstCallSouthEast[dstCall[4]] )
                latitude = - latitude;

            qreal longitude =
                calculateLongitude( QString ( mic_e_matcher.cap( 4 ) ),
                                    m_dstCallLongitudeOffset[dstCall[5]],
                                    m_dstCallSouthEast[dstCall[6]] );

//           mDebug() << "  MIC-E: " << line.toLocal8Bit().data();
//           mDebug() << "    lat: " << latitude;
//           mDebug() << "    lon: " << longitude;

            addObject( myCall, latitude, longitude, canDoDirect,
                       QString( mic_e_matcher.cap( 3 ) ),
                       QChar( mic_e_matcher.cap( 6 )[1] ),
                       QChar( mic_e_matcher.cap( 6 )[0] ) );
        }
        else {
            mDebug() << "aprs: UNPARSED: " << line;
        }

        // If the filter should be changed, send it out the socket
        if ( m_filter != NULL ) {
            QMutexLocker locker( m_mutex );
            if ( m_filter->length() > 0 ) {
                m_socket->write( m_filter->toLocal8Bit().data(),
                                 m_filter->length() );
            }
        }
    }
}

void
AprsGatherer::shutDown()
{
    m_running = false;
}

void
AprsGatherer::addObject( const QString &callSign,
                         qreal latitude, qreal longitude, bool canDoDirect,
                         const QString &routePath,
                         const QChar &symbolTable,
                         const QChar &symbolCode )
{
    QMutexLocker locker( m_mutex );

    GeoAprsCoordinates location( longitude, latitude, m_seenFrom );
    if ( canDoDirect ) {
        if ( !routePath.contains( QChar( '*' ) ) ) {
            location.addSeenFrom( GeoAprsCoordinates::Directly );
        }
    }

    if ( m_objects->contains( callSign ) ) {
        // we already have one for this callSign; just add the new
        // history item.
        ( *m_objects )[callSign]->setLocation( location );
    }
    else {
        AprsObject *foundObject = new AprsObject( location, callSign );
        foundObject->setPixmapId( m_pixmaps[QPair<QChar, QChar>( symbolTable,symbolCode )] );
        ( *m_objects )[callSign] = foundObject;
        mDebug() << "aprs:  new: " << callSign.toLocal8Bit().data();
    }
}

qreal AprsGatherer::calculateLongitude( const QString &threeBytes, int offset,
                                         bool isEast )
{
    // otherwise known as "fun with funky encoding"
    qreal hours = threeBytes[0].toLatin1() - 28 + offset;
    if ( 180 <= hours && hours <= 189 )
        hours -= 80;
    if ( 190 <= hours && hours <= 199 )
        hours -= 190;

    hours +=
        ( qreal( (threeBytes[1].toLatin1() - 28 ) % 60 ) +
          ( qreal( threeBytes[2].toLatin1() - 28 ) ) / 100 ) / 60.0;

    if ( ! isEast )
        hours = -hours;
    return hours;
}

void
AprsGatherer::setDumpOutput( bool to )
{
    m_dumpOutput = to;
}

bool
AprsGatherer::dumpOutput() const
{
    return m_dumpOutput;
}

void
AprsGatherer::setSeenFrom( GeoAprsCoordinates::SeenFrom to )
{
    m_seenFrom = to;
}

GeoAprsCoordinates::SeenFrom
AprsGatherer::seenFrom()
{
    return m_seenFrom;
}

// gets around parent QThread protected sleep as our objects need a sleep
void
AprsGatherer::sleepFor(int seconds)
{
    sleep(seconds);
}

#include "AprsGatherer.moc"
<commit_msg>Fix wrong decoding (longitude calculation) of some MIC-E positions<commit_after>//
// This file is part of the Marble Virtual Globe.
//
// This program is free software licensed under the GNU LGPL. You can
// find a copy of this license in LICENSE.txt in the top directory of
// the source code.
//
// Copyright 2010 Wes Hardaker <hardaker@users.sourceforge.net>
//

#include "AprsGatherer.h"

#include <QPixmap>

#include "MarbleDirs.h"
#include "MarbleDebug.h"

using namespace Marble;

AprsGatherer::AprsGatherer( AprsSource *from,
                            QMap<QString, AprsObject *> *objects,
                            QMutex *mutex,
                            QString *filter )
    : m_source( from ),
      m_socket( 0 ),
      m_filter( filter ),
      m_running( true ),
      m_dumpOutput( false ),
      m_seenFrom( GeoAprsCoordinates::FromNowhere ),
      m_sourceName( ),
      m_mutex( mutex ),
      m_objects( objects )
{
    m_sourceName = from->sourceName();
    initMicETables();
}

AprsGatherer::AprsGatherer( QIODevice *from,
                            QMap<QString, AprsObject *> *objects,
                            QMutex *mutex,
                            QString *filter )
    : m_source( 0 ),
      m_socket( from ),
      m_filter( filter ),
      m_running( true ),
      m_dumpOutput( false ),
      m_seenFrom( GeoAprsCoordinates::FromNowhere ),
      m_sourceName( "unknown" ),
      m_mutex( mutex ),
      m_objects( objects )
{
    initMicETables();
}

void
AprsGatherer::run()
{
    char buf[4096];
    qint64 linelength;
    // one particular APRS packet sender can add data after the : ( sigh )
    QRegExp matcher( "^([0-9A-Z]+-*[0-9A-Z]*)>([^:]*):([!=@\\/])([0-9][0-9][0-9][0-9][0-9][0-9]|)([hz\\/]|)([0-9][0-9])([0-9][0-9]\\.[0-9][0-9])([NS])(.)([0-9][0-9][0-9])([0-9][0-9]\\.[0-9][0-9])([EW])(.)" );

    // mic-e formatted
    // 1: src
    // 2: dst
    // 3: routes
    // 4: longitude x 3
    // 5: speed and course x3
    // 6: symbol and symbol ID
    // 7: status text
    QRegExp mic_e_matcher( "^([0-9A-Z]+-*[0-9A-Z]*)>([^,:]*),*([^:]*):['`](...)(...)(..)(.*)" );

    // If a source can directly receive a signal (as opposed to
    // through a relay like the internet) will return true.  This
    // prevents accidentially coloring signals heard over some sources
    // as heard directly where it's never possible (such as over the
    // internet).
    bool canDoDirect = m_source->canDoDirect();

    while( m_running ) {

        if ( m_socket && !m_socket->isOpen() ) {
            // connection closed; attempt to reopen
            mDebug() << "aprs: socket closed; attempting to reopen";
            delete m_socket;
            m_socket = 0;
        }

        if ( !m_socket && m_source )
            m_socket = m_source->openSocket();

        if ( !m_socket ) {
            mDebug() << "aprs: failed to open socket from "
                     << m_sourceName.toLocal8Bit().data();
            sleep( 5 );
            continue;
        }

        // wait for data to read in
        if ( m_socket->bytesAvailable() <= 0 )
            // wait no longer than 1s
            if ( ! m_socket->waitForReadyRead( 1000 ) )
                continue; // continue to loop again on "not ready"

        // Read the line to parse
        linelength = m_socket->readLine( buf, sizeof( buf ) );

        // if we got 0 or less bytes this is probably an odd case; ask
        // the source what to do.
        m_source->checkReadReturn( linelength, &m_socket, this );

        if ( linelength <= 0 ) {
            // don't go into an infinite untimed loop of failed sockets
            sleep( 2 );
            continue;
        }

        if ( m_socket && m_filter != NULL ) {
            QMutexLocker locker( m_mutex );
            if ( m_filter->length() > 0 ) {
                m_socket->write( m_filter->toLocal8Bit().data(),
                                 m_filter->length() );
            }
        }

        // Parse the results
        QString line( buf );

        // Dump it out if we wanted it dumped
        if ( m_dumpOutput )
            mDebug() << "aprs: " << m_sourceName.toLocal8Bit().data()
                     << ": " << line;

        if ( matcher.indexIn( line ) != -1 ) {
            QString callSign  = matcher.cap( 1 );
            qreal latitude = matcher.cap( 6 ).toFloat() +
                ( matcher.cap( 7 ).toFloat()/60 );
            if ( matcher.cap( 8 ) == "S" )
                latitude = - latitude;

            qreal longitude = matcher.cap( 10 ).toFloat() +
                ( matcher.cap( 11 ).toFloat()/60 );
            if ( matcher.cap( 12 ) == "W" )
                longitude = - longitude;

            addObject( callSign, latitude, longitude, canDoDirect,
                       QString( matcher.cap( 2 ) ),
                       QChar( matcher.cap( 9 )[0] ),
                       QChar( matcher.cap( 13 )[0] ) );
        }
        else if ( mic_e_matcher.indexIn( line ) != -1 ) {
            // MIC-E formatted compressed packet
            QString myCall  = mic_e_matcher.cap( 1 );
            QString dstCall = mic_e_matcher.cap( 2 );

            qreal latitude =
                // hours
                m_dstCallDigits[dstCall[0]] * 10 +
                m_dstCallDigits[dstCall[1]] +

                // minutes
                ( qreal( m_dstCallDigits[dstCall[2]] * 10 +
                         m_dstCallDigits[dstCall[3]] ) +
                  qreal( m_dstCallDigits[dstCall[4]] ) / 10.0 +
                  qreal( m_dstCallDigits[dstCall[5]] ) / 100 ) / 60.0;

            if ( m_dstCallSouthEast[dstCall[4]] )
                latitude = - latitude;

            qreal longitude =
                calculateLongitude( QString ( mic_e_matcher.cap( 4 ) ),
                                    m_dstCallLongitudeOffset[dstCall[4]],
                                    m_dstCallSouthEast[dstCall[5]] );

//           mDebug() << "  MIC-E: " << line.toLocal8Bit().data();
//           mDebug() << "    lat: " << latitude;
//           mDebug() << "    lon: " << longitude;

            addObject( myCall, latitude, longitude, canDoDirect,
                       QString( mic_e_matcher.cap( 3 ) ),
                       QChar( mic_e_matcher.cap( 6 )[1] ),
                       QChar( mic_e_matcher.cap( 6 )[0] ) );
        }
        else {
            mDebug() << "aprs: UNPARSED: " << line;
        }

        // If the filter should be changed, send it out the socket
        if ( m_filter != NULL ) {
            QMutexLocker locker( m_mutex );
            if ( m_filter->length() > 0 ) {
                m_socket->write( m_filter->toLocal8Bit().data(),
                                 m_filter->length() );
            }
        }
    }
}

void
AprsGatherer::shutDown()
{
    m_running = false;
}

void
AprsGatherer::addObject( const QString &callSign,
                         qreal latitude, qreal longitude, bool canDoDirect,
                         const QString &routePath,
                         const QChar &symbolTable,
                         const QChar &symbolCode )
{
    QMutexLocker locker( m_mutex );

    GeoAprsCoordinates location( longitude, latitude, m_seenFrom );
    if ( canDoDirect ) {
        if ( !routePath.contains( QChar( '*' ) ) ) {
            location.addSeenFrom( GeoAprsCoordinates::Directly );
        }
    }

    if ( m_objects->contains( callSign ) ) {
        // we already have one for this callSign; just add the new
        // history item.
        ( *m_objects )[callSign]->setLocation( location );
    }
    else {
        AprsObject *foundObject = new AprsObject( location, callSign );
        foundObject->setPixmapId( m_pixmaps[QPair<QChar, QChar>( symbolTable,symbolCode )] );
        ( *m_objects )[callSign] = foundObject;
        mDebug() << "aprs:  new: " << callSign.toLocal8Bit().data();
    }
}

qreal AprsGatherer::calculateLongitude( const QString &threeBytes, int offset,
                                         bool isEast )
{
    // otherwise known as "fun with funky encoding"
    qreal hours = threeBytes[0].toLatin1() - 28 + offset;
    if ( 180 <= hours && hours <= 189 )
        hours -= 80;
    if ( 190 <= hours && hours <= 199 )
        hours -= 190;

    hours +=
        ( qreal( (threeBytes[1].toLatin1() - 28 ) % 60 ) +
          ( qreal( threeBytes[2].toLatin1() - 28 ) ) / 100 ) / 60.0;

    if ( ! isEast )
        hours = -hours;
    return hours;
}

void
AprsGatherer::setDumpOutput( bool to )
{
    m_dumpOutput = to;
}

bool
AprsGatherer::dumpOutput() const
{
    return m_dumpOutput;
}

void
AprsGatherer::setSeenFrom( GeoAprsCoordinates::SeenFrom to )
{
    m_seenFrom = to;
}

GeoAprsCoordinates::SeenFrom
AprsGatherer::seenFrom()
{
    return m_seenFrom;
}

// gets around parent QThread protected sleep as our objects need a sleep
void
AprsGatherer::sleepFor(int seconds)
{
    sleep(seconds);
}

#include "AprsGatherer.moc"
<|endoftext|>