<commit_before>// Copyright (c) 2012 Intel Corp
// Copyright (c) 2012 The Chromium Authors
//
// 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 co
// pies 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 al
// l copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IM
// PLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNES
// S FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
//  OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WH
// ETHER 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 "content/nw/src/api/dispatcher_host.h"

#include "base/logging.h"
#include "base/threading/thread_restrictions.h"
#include "base/values.h"
#include "content/browser/child_process_security_policy_impl.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/nw/src/api/api_messages.h"
#include "content/nw/src/api/app/app.h"
#include "content/nw/src/api/base/base.h"
#include "content/nw/src/api/clipboard/clipboard.h"
#include "content/nw/src/api/menu/menu.h"
#include "content/nw/src/api/menuitem/menuitem.h"
#include "content/nw/src/api/shell/shell.h"
#include "content/nw/src/api/tray/tray.h"
#include "content/nw/src/api/window/window.h"
#include "content/nw/src/common/shell_switches.h"
#include "content/nw/src/shell_browser_context.h"
#include "content/nw/src/nw_shell.h"
#include "content/public/browser/render_process_host.h"

using content::WebContents;
using content::ShellBrowserContext;
using content::Shell;

namespace nwapi {

IDMap<Base, IDMapOwnPointer> nwapi::DispatcherHost::objects_registry_;
int nwapi::DispatcherHost::next_object_id_ = 1;
static std::map<content::RenderViewHost*, DispatcherHost*> g_dispatcher_host_map;

DispatcherHost::DispatcherHost(content::RenderViewHost* render_view_host)
    : content::RenderViewHostObserver(render_view_host) {
  g_dispatcher_host_map[render_view_host] = this;
}

DispatcherHost::~DispatcherHost() {
  g_dispatcher_host_map.erase(render_view_host());
}

DispatcherHost*
FindDispatcherHost(content::RenderViewHost* render_view_host) {
  std::map<content::RenderViewHost*, DispatcherHost*>::iterator it
    = g_dispatcher_host_map.find(render_view_host);
  if (it == g_dispatcher_host_map.end())
    return NULL;
  return it->second;
}

void DispatcherHost::ClearObjectRegistry() {
  objects_registry_.Clear();
}

Base* DispatcherHost::GetApiObject(int id) {
  return objects_registry_.Lookup(id);
}

int DispatcherHost::AllocateId() {
  return next_object_id_++;
}

void DispatcherHost::SendEvent(Base* object,
                               const std::string& event,
                               const base::ListValue& arguments) {
  Send(new ShellViewMsg_Object_On_Event(
       routing_id(), object->id(), event, arguments));
}

bool DispatcherHost::Send(IPC::Message* message) {
  return content::RenderViewHostObserver::Send(message);
}

bool DispatcherHost::OnMessageReceived(const IPC::Message& message) {
  bool handled = true;
  base::ThreadRestrictions::ScopedAllowIO allow_io;
  base::ThreadRestrictions::ScopedAllowWait allow_wait;
  IPC_BEGIN_MESSAGE_MAP(DispatcherHost, message)
    IPC_MESSAGE_HANDLER(ShellViewHostMsg_Allocate_Object, OnAllocateObject)
    IPC_MESSAGE_HANDLER(ShellViewHostMsg_Deallocate_Object, OnDeallocateObject)
    IPC_MESSAGE_HANDLER(ShellViewHostMsg_Call_Object_Method, OnCallObjectMethod)
    IPC_MESSAGE_HANDLER(ShellViewHostMsg_Call_Object_Method_Sync,
                        OnCallObjectMethodSync)
    IPC_MESSAGE_HANDLER(ShellViewHostMsg_Call_Static_Method, OnCallStaticMethod)
    IPC_MESSAGE_HANDLER(ShellViewHostMsg_Call_Static_Method_Sync,
                        OnCallStaticMethodSync)
    IPC_MESSAGE_HANDLER(ShellViewHostMsg_UncaughtException,
                        OnUncaughtException);
    IPC_MESSAGE_HANDLER(ShellViewHostMsg_GetShellId, OnGetShellId);
    IPC_MESSAGE_HANDLER(ShellViewHostMsg_CreateShell, OnCreateShell);
    IPC_MESSAGE_HANDLER(ShellViewHostMsg_GrantUniversalPermissions, OnGrantUniversalPermissions);
    IPC_MESSAGE_HANDLER(ShellViewHostMsg_AllocateId, OnAllocateId);
    IPC_MESSAGE_UNHANDLED(handled = false)
  IPC_END_MESSAGE_MAP()

  return handled;
}

void DispatcherHost::OnAllocateObject(int object_id,
                                      const std::string& type,
                                      const base::DictionaryValue& option) {
  DVLOG(1) << "OnAllocateObject: object_id:" << object_id
             << " type:" << type
             << " option:" << option;

  if (type == "Menu") {
    objects_registry_.AddWithID(new Menu(object_id, this, option), object_id);
  } else if (type == "MenuItem") {
    objects_registry_.AddWithID(
        new MenuItem(object_id, this, option), object_id);
  } else if (type == "Tray") {
    objects_registry_.AddWithID(new Tray(object_id, this, option), object_id);
  } else if (type == "Clipboard") {
    objects_registry_.AddWithID(
        new Clipboard(object_id, this, option), object_id);
  } else if (type == "Window") {
    objects_registry_.AddWithID(new Window(object_id, this, option), object_id);
  } else {
    LOG(ERROR) << "Allocate an object of unknown type: " << type;
    objects_registry_.AddWithID(new Base(object_id, this, option), object_id);
  }
}

void DispatcherHost::OnDeallocateObject(int object_id) {
  DLOG(INFO) << "OnDeallocateObject: object_id:" << object_id;
  objects_registry_.Remove(object_id);
}

void DispatcherHost::OnCallObjectMethod(
    int object_id,
    const std::string& type,
    const std::string& method,
    const base::ListValue& arguments) {
  DLOG(INFO) << "OnCallObjectMethod: object_id:" << object_id
             << " type:" << type
             << " method:" << method
             << " arguments:" << arguments;

  Base* object = GetApiObject(object_id);
  if (object)
    object->Call(method, arguments);
  else
    DLOG(WARNING) << "Unknown object: " << object_id
             << " type:" << type
             << " method:" << method
             << " arguments:" << arguments;
}

void DispatcherHost::OnCallObjectMethodSync(
    int object_id,
    const std::string& type,
    const std::string& method,
    const base::ListValue& arguments,
    base::ListValue* result) {
  DLOG(INFO) << "OnCallObjectMethodSync: object_id:" << object_id
             << " type:" << type
             << " method:" << method
             << " arguments:" << arguments;

  Base* object = GetApiObject(object_id);
  LOG(WARNING) << "Unknown object: " << object_id
             << " type:" << type
             << " method:" << method
             << " arguments:" << arguments;
  if (object)
    object->CallSync(method, arguments, result);
}

void DispatcherHost::OnCallStaticMethod(
    const std::string& type,
    const std::string& method,
    const base::ListValue& arguments) {
  DLOG(INFO) << "OnCallStaticMethod: "
             << " type:" << type
             << " method:" << method
             << " arguments:" << arguments;

  if (type == "Shell") {
    nwapi::Shell::Call(method, arguments);
    return;
  } else if (type == "App") {
    nwapi::App::Call(method, arguments);
    return;
  }

  NOTREACHED() << "Calling unknown method " << method << " of class " << type;
}

void DispatcherHost::OnCallStaticMethodSync(
    const std::string& type,
    const std::string& method,
    const base::ListValue& arguments,
    base::ListValue* result) {
  DLOG(INFO) << "OnCallStaticMethodSync: "
             << " type:" << type
             << " method:" << method
             << " arguments:" << arguments;

  if (type == "App") {
    content::Shell* shell =
        content::Shell::FromRenderViewHost(render_view_host());
    nwapi::App::Call(shell, method, arguments, result);
    return;
  }

  NOTREACHED() << "Calling unknown method " << method << " of class " << type;
}

void DispatcherHost::OnUncaughtException(const std::string& err) {
  content::Shell* shell =
      content::Shell::FromRenderViewHost(render_view_host());
  shell->PrintCriticalError("Uncaught node.js Error", err);
}

void DispatcherHost::OnGetShellId(int* id) {
  content::Shell* shell =
      content::Shell::FromRenderViewHost(render_view_host());
  *id = shell->id();
}

void DispatcherHost::OnCreateShell(const std::string& url,
                                   const base::DictionaryValue& manifest,
                                   int* routing_id) {
  WebContents* base_web_contents =
      content::Shell::FromRenderViewHost(render_view_host())->web_contents();
  ShellBrowserContext* browser_context =
      static_cast<ShellBrowserContext*>(base_web_contents->GetBrowserContext());
  scoped_ptr<base::DictionaryValue> new_manifest(manifest.DeepCopy());
  bool new_renderer = false;
  if (new_manifest->GetBoolean(switches::kmNewInstance,
                               &new_renderer) && new_renderer)
    browser_context->set_pinning_renderer(false);

  WebContents::CreateParams create_params(browser_context,
                                          new_renderer ? NULL : base_web_contents->GetSiteInstance());

  WebContents* web_contents = content::WebContentsImpl::CreateWithOpener(
      create_params,
      static_cast<content::WebContentsImpl*>(base_web_contents));
  content::Shell::Create(base_web_contents,
                         GURL(url),
                         new_manifest.get(),
                         web_contents);

  if (new_renderer)
    browser_context->set_pinning_renderer(true);

  *routing_id = web_contents->GetRoutingID();

  int object_id = 0;
  if (new_manifest->GetInteger("object_id", &object_id)) {
    DispatcherHost* dhost = FindDispatcherHost(web_contents->GetRenderViewHost());
    dhost->OnAllocateObject(object_id, "Window", *new_manifest.get());
  }
}

void DispatcherHost::OnGrantUniversalPermissions(int *ret) {
  content::Shell* shell =
      content::Shell::FromRenderViewHost(render_view_host());
  if (shell->nodejs()) {
    content::ChildProcessSecurityPolicy::GetInstance()->GrantUniversalAccess(shell->web_contents()->GetRenderProcessHost()->GetID());
    *ret = 1;
  }else
    *ret = 0;
}

void DispatcherHost::OnAllocateId(int * ret) {
  *ret = AllocateId();
}

}  // namespace nwapi
<commit_msg>Force close the new-instance window<commit_after>// Copyright (c) 2012 Intel Corp
// Copyright (c) 2012 The Chromium Authors
//
// 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 co
// pies 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 al
// l copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IM
// PLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNES
// S FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
//  OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WH
// ETHER 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 "content/nw/src/api/dispatcher_host.h"

#include "base/logging.h"
#include "base/threading/thread_restrictions.h"
#include "base/values.h"
#include "content/browser/child_process_security_policy_impl.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/nw/src/api/api_messages.h"
#include "content/nw/src/api/app/app.h"
#include "content/nw/src/api/base/base.h"
#include "content/nw/src/api/clipboard/clipboard.h"
#include "content/nw/src/api/menu/menu.h"
#include "content/nw/src/api/menuitem/menuitem.h"
#include "content/nw/src/api/shell/shell.h"
#include "content/nw/src/api/tray/tray.h"
#include "content/nw/src/api/window/window.h"
#include "content/nw/src/common/shell_switches.h"
#include "content/nw/src/shell_browser_context.h"
#include "content/nw/src/nw_shell.h"
#include "content/public/browser/render_process_host.h"

using content::WebContents;
using content::ShellBrowserContext;
using content::Shell;

namespace nwapi {

IDMap<Base, IDMapOwnPointer> nwapi::DispatcherHost::objects_registry_;
int nwapi::DispatcherHost::next_object_id_ = 1;
static std::map<content::RenderViewHost*, DispatcherHost*> g_dispatcher_host_map;

DispatcherHost::DispatcherHost(content::RenderViewHost* render_view_host)
    : content::RenderViewHostObserver(render_view_host) {
  g_dispatcher_host_map[render_view_host] = this;
}

DispatcherHost::~DispatcherHost() {
  g_dispatcher_host_map.erase(render_view_host());
}

DispatcherHost*
FindDispatcherHost(content::RenderViewHost* render_view_host) {
  std::map<content::RenderViewHost*, DispatcherHost*>::iterator it
    = g_dispatcher_host_map.find(render_view_host);
  if (it == g_dispatcher_host_map.end())
    return NULL;
  return it->second;
}

void DispatcherHost::ClearObjectRegistry() {
  objects_registry_.Clear();
}

Base* DispatcherHost::GetApiObject(int id) {
  return objects_registry_.Lookup(id);
}

int DispatcherHost::AllocateId() {
  return next_object_id_++;
}

void DispatcherHost::SendEvent(Base* object,
                               const std::string& event,
                               const base::ListValue& arguments) {
  Send(new ShellViewMsg_Object_On_Event(
       routing_id(), object->id(), event, arguments));
}

bool DispatcherHost::Send(IPC::Message* message) {
  return content::RenderViewHostObserver::Send(message);
}

bool DispatcherHost::OnMessageReceived(const IPC::Message& message) {
  bool handled = true;
  base::ThreadRestrictions::ScopedAllowIO allow_io;
  base::ThreadRestrictions::ScopedAllowWait allow_wait;
  IPC_BEGIN_MESSAGE_MAP(DispatcherHost, message)
    IPC_MESSAGE_HANDLER(ShellViewHostMsg_Allocate_Object, OnAllocateObject)
    IPC_MESSAGE_HANDLER(ShellViewHostMsg_Deallocate_Object, OnDeallocateObject)
    IPC_MESSAGE_HANDLER(ShellViewHostMsg_Call_Object_Method, OnCallObjectMethod)
    IPC_MESSAGE_HANDLER(ShellViewHostMsg_Call_Object_Method_Sync,
                        OnCallObjectMethodSync)
    IPC_MESSAGE_HANDLER(ShellViewHostMsg_Call_Static_Method, OnCallStaticMethod)
    IPC_MESSAGE_HANDLER(ShellViewHostMsg_Call_Static_Method_Sync,
                        OnCallStaticMethodSync)
    IPC_MESSAGE_HANDLER(ShellViewHostMsg_UncaughtException,
                        OnUncaughtException);
    IPC_MESSAGE_HANDLER(ShellViewHostMsg_GetShellId, OnGetShellId);
    IPC_MESSAGE_HANDLER(ShellViewHostMsg_CreateShell, OnCreateShell);
    IPC_MESSAGE_HANDLER(ShellViewHostMsg_GrantUniversalPermissions, OnGrantUniversalPermissions);
    IPC_MESSAGE_HANDLER(ShellViewHostMsg_AllocateId, OnAllocateId);
    IPC_MESSAGE_UNHANDLED(handled = false)
  IPC_END_MESSAGE_MAP()

  return handled;
}

void DispatcherHost::OnAllocateObject(int object_id,
                                      const std::string& type,
                                      const base::DictionaryValue& option) {
  DVLOG(1) << "OnAllocateObject: object_id:" << object_id
             << " type:" << type
             << " option:" << option;

  if (type == "Menu") {
    objects_registry_.AddWithID(new Menu(object_id, this, option), object_id);
  } else if (type == "MenuItem") {
    objects_registry_.AddWithID(
        new MenuItem(object_id, this, option), object_id);
  } else if (type == "Tray") {
    objects_registry_.AddWithID(new Tray(object_id, this, option), object_id);
  } else if (type == "Clipboard") {
    objects_registry_.AddWithID(
        new Clipboard(object_id, this, option), object_id);
  } else if (type == "Window") {
    objects_registry_.AddWithID(new Window(object_id, this, option), object_id);
  } else {
    LOG(ERROR) << "Allocate an object of unknown type: " << type;
    objects_registry_.AddWithID(new Base(object_id, this, option), object_id);
  }
}

void DispatcherHost::OnDeallocateObject(int object_id) {
  DLOG(INFO) << "OnDeallocateObject: object_id:" << object_id;
  objects_registry_.Remove(object_id);
}

void DispatcherHost::OnCallObjectMethod(
    int object_id,
    const std::string& type,
    const std::string& method,
    const base::ListValue& arguments) {
  DLOG(INFO) << "OnCallObjectMethod: object_id:" << object_id
             << " type:" << type
             << " method:" << method
             << " arguments:" << arguments;

  Base* object = GetApiObject(object_id);
  if (object)
    object->Call(method, arguments);
  else
    DLOG(WARNING) << "Unknown object: " << object_id
             << " type:" << type
             << " method:" << method
             << " arguments:" << arguments;
}

void DispatcherHost::OnCallObjectMethodSync(
    int object_id,
    const std::string& type,
    const std::string& method,
    const base::ListValue& arguments,
    base::ListValue* result) {
  DLOG(INFO) << "OnCallObjectMethodSync: object_id:" << object_id
             << " type:" << type
             << " method:" << method
             << " arguments:" << arguments;

  Base* object = GetApiObject(object_id);
  LOG(WARNING) << "Unknown object: " << object_id
             << " type:" << type
             << " method:" << method
             << " arguments:" << arguments;
  if (object)
    object->CallSync(method, arguments, result);
}

void DispatcherHost::OnCallStaticMethod(
    const std::string& type,
    const std::string& method,
    const base::ListValue& arguments) {
  DLOG(INFO) << "OnCallStaticMethod: "
             << " type:" << type
             << " method:" << method
             << " arguments:" << arguments;

  if (type == "Shell") {
    nwapi::Shell::Call(method, arguments);
    return;
  } else if (type == "App") {
    nwapi::App::Call(method, arguments);
    return;
  }

  NOTREACHED() << "Calling unknown method " << method << " of class " << type;
}

void DispatcherHost::OnCallStaticMethodSync(
    const std::string& type,
    const std::string& method,
    const base::ListValue& arguments,
    base::ListValue* result) {
  DLOG(INFO) << "OnCallStaticMethodSync: "
             << " type:" << type
             << " method:" << method
             << " arguments:" << arguments;

  if (type == "App") {
    content::Shell* shell =
        content::Shell::FromRenderViewHost(render_view_host());
    nwapi::App::Call(shell, method, arguments, result);
    return;
  }

  NOTREACHED() << "Calling unknown method " << method << " of class " << type;
}

void DispatcherHost::OnUncaughtException(const std::string& err) {
  content::Shell* shell =
      content::Shell::FromRenderViewHost(render_view_host());
  shell->PrintCriticalError("Uncaught node.js Error", err);
}

void DispatcherHost::OnGetShellId(int* id) {
  content::Shell* shell =
      content::Shell::FromRenderViewHost(render_view_host());
  *id = shell->id();
}

void DispatcherHost::OnCreateShell(const std::string& url,
                                   const base::DictionaryValue& manifest,
                                   int* routing_id) {
  WebContents* base_web_contents =
      content::Shell::FromRenderViewHost(render_view_host())->web_contents();
  ShellBrowserContext* browser_context =
      static_cast<ShellBrowserContext*>(base_web_contents->GetBrowserContext());
  scoped_ptr<base::DictionaryValue> new_manifest(manifest.DeepCopy());
  bool new_renderer = false;
  if (new_manifest->GetBoolean(switches::kmNewInstance,
                               &new_renderer) && new_renderer)
    browser_context->set_pinning_renderer(false);

  WebContents::CreateParams create_params(browser_context,
                                          new_renderer ? NULL : base_web_contents->GetSiteInstance());

  WebContents* web_contents = content::WebContentsImpl::CreateWithOpener(
      create_params,
      static_cast<content::WebContentsImpl*>(base_web_contents));
  content::Shell* new_shell =
    content::Shell::Create(base_web_contents,
                           GURL(url),
                           new_manifest.get(),
                           web_contents);

  if (new_renderer) {
    browser_context->set_pinning_renderer(true);
    // since the new-instance shell is always bound
    // there would be 'Close' event cannot reach dest
    new_shell->set_force_close(true);
  }

  *routing_id = web_contents->GetRoutingID();

  int object_id = 0;
  if (new_manifest->GetInteger("object_id", &object_id)) {
    DispatcherHost* dhost = FindDispatcherHost(web_contents->GetRenderViewHost());
    dhost->OnAllocateObject(object_id, "Window", *new_manifest.get());
  }
}

void DispatcherHost::OnGrantUniversalPermissions(int *ret) {
  content::Shell* shell =
      content::Shell::FromRenderViewHost(render_view_host());
  if (shell->nodejs()) {
    content::ChildProcessSecurityPolicy::GetInstance()->GrantUniversalAccess(shell->web_contents()->GetRenderProcessHost()->GetID());
    *ret = 1;
  }else
    *ret = 0;
}

void DispatcherHost::OnAllocateId(int * ret) {
  *ret = AllocateId();
}

}  // namespace nwapi
<|endoftext|>


<commit_before>/* dtkMath.tpp ---
 *
 * Author: Julien Wintz
 * Copyright (C) 2008 - Julien Wintz, Inria.
 * Created: Wed Mar  9 11:05:40 2011 (+0100)
 * Version: $Id$
 * Last-Updated: Tue Apr 24 20:19:17 2012 (+0200)
 *           By: Julien Wintz
 *     Update #: 88
 */

/* Commentary:
 *
 */

/* Change log:
 *
 */

#ifndef DTKMATH_TPP
#define DTKMATH_TPP

#include "dtkMatrixSquared.h"
#include "dtkQuaternion.h"
#include "dtkVector3D.h"

static double dtkDeg2Rad(double v)
{
    return v*M_PI/180.0;
}

static double dtkRad2Deg(double v)
{
    return v*180.0/M_PI;
}

template <class T> dtkVector3D<T> dtkRotate(const dtkQuaternion<T>& quaternion, const dtkVector3D<T>& vector)
{
    dtkQuaternion<T> q(quaternion*dtkQuaternion<T>(vector[0], vector[1], vector[2], 0)*dtkInverse<T>(quaternion));
    return dtkVector3D<T>(q[0], q[1], q[2]);
}

//! dtkMixedProduct(const dtkVector3D &v0, const dtkVector3D &v1, const dtkVector3D &v2)
/*!
 * This function calculates the mixed product (also called triple scalar product)
 * formed by three dtkVector3D.
 */
template <class T>  T dtkMixedProduct(const dtkVector3D<T> &v0,
                                      const dtkVector3D<T> &v1,
                                      const dtkVector3D<T> &v2)
{
    dtkVector3D<T> v;
    v.storeOuterProduct(v1, v2);
    return (v0*v);
}

//! dtkQuaternionFromEulerAxisAndAngle(const dtkVector3D<T> &dtkVecEulerAxis, const T &rotateEulerAngle)
/*!
 * This function returns a quaternion representing a rigid body's
 * attitude from its Euler axis and angle.
 * NOTE: Argument vector dtkVecEulerAxis MUST be a unit vector.
 */
template <class T> dtkQuaternion<T> dtkQuaternionFromAxisAngle(const dtkVector3D<T> &axis, const T &angle)
{
    dtkVector3D<T> v = axis.unit();

    return dtkQuaternion<T>(1.0, dtkVector3D<T>(axis[0], axis[1], axis[2]), dtkDeg2Rad(angle/(T)2));
}

template <class T> dtkQuaternion<T> dtkQuaternionFromHPR(T h, T p, T r)
{
    T  cosH, sinH, cosP, sinP, cosR, sinR;
    T  half_r, half_p, half_h;

   /* put angles into radians and divide by two, since all angles in formula
    *  are (angle/2)
    */

   half_h = dtkDeg2Rad(h / 2.0);
   half_p = dtkDeg2Rad(p / 2.0);
   half_r = dtkDeg2Rad(r / 2.0);

   cosH = cos(half_h);
   sinH = sin(half_h);

   cosP = cos(half_p);
   sinP = sin(half_p);

   cosR = cos(half_r);
   sinR = sin(half_r);

   return dtkQuaternion<T>(
        sinR * cosP * cosH - cosR * sinP * sinH,
        cosR * sinP * cosH + sinR * cosP * sinH,
        cosR * cosP * sinH - sinR * sinP * cosH,
        cosR * cosP * cosH + sinR * sinP * sinH);
}

//! dtkEulerAxisFromQuaternion(const dtkQuaternion<T> &qtn)
/*!
 * This function returns Euler axis from a quaternion representing a rigid body's
 * attitude.
 */
template <class T> dtkVector3D<T> dtkAxisFromQuaternion(const dtkQuaternion<T> &qtn)
{
    dtkVector3D<T> axis(qtn[0], qtn[1], qtn[2]);

    return axis.unit();
}

//! dtkQuaternionFromMatSquared(const dtkMatrixSquared<T> &mat)
/*!
 * This function returns the quaternion corresponding to a
 * transformation matrix.
*/
template <class T> dtkQuaternion<T> dtkQuaternionFromMatSquared(const dtkMatrixSquared<T> &mat)
{
    T sclrTmp = dtkTrace(mat);

    dtkQuaternion<T> qtn;

    if(sclrTmp > 0) {
	sclrTmp = 0.5*sqrt(1 + sclrTmp);
	qtn[0] = 0.25*(mat[1][2] - mat[2][1])/sclrTmp;
	qtn[1] = 0.25*(mat[2][0] - mat[0][2])/sclrTmp;
	qtn[2] = 0.25*(mat[0][1] - mat[1][0])/sclrTmp;
	qtn[3] = sclrTmp;
    } else {
	// We could be in trouble, so we have to take
	// precautions. NOTE: Parts of this piece of code were taken
	// from the example in the article "Rotating Objects Using
	// Quaternions" in Game Developer Magazine written by Nick
	// Bobick, july 3, 1998, vol. 2, issue 26.
	int i = 0;
	if (mat[1][1] > mat[0][0]) i = 1;
	if (mat[2][2] > mat[i][i]) i = 2;

	switch (i) {
        case 0:
	    sclrTmp = 0.5*sqrt(1 + mat[0][0] - mat[1][1] - mat[2][2]);
	    qtn[0] = sclrTmp;
	    qtn[1] = 0.25*(mat[0][1] + mat[1][0])/sclrTmp;
	    qtn[2] = 0.25*(mat[0][2] + mat[2][0])/sclrTmp;
	    qtn[3] = 0.25*(mat[1][2] - mat[2][1])/sclrTmp;
	    break;

        case 1:
	    sclrTmp = 0.5*sqrt(1 - mat[0][0] + mat[1][1] - mat[2][2]);
	    qtn[0] = 0.25*(mat[1][0] + mat[0][1])/sclrTmp;
	    qtn[1] = sclrTmp;
	    qtn[2] = 0.25*(mat[1][2] + mat[2][1])/sclrTmp;
	    qtn[3] = 0.25*(mat[2][0] - mat[0][2])/sclrTmp;
	    break;

        case 2:
	    sclrTmp = 0.5*sqrt(1 - mat[0][0] - mat[1][1] + mat[2][2]);
	    qtn[0] = 0.25*(mat[2][0] + mat[0][2])/sclrTmp;
	    qtn[1] = 0.25*(mat[2][1] + mat[1][2])/sclrTmp;
	    qtn[2] = sclrTmp;
	    qtn[3] = 0.25*(mat[0][1] - mat[1][0])/sclrTmp;
	    break;
        }
    }

    return qtn;
}

//! dtkEulerAngleFromQuaternion(const dtkQuaternion<T> &qtn)
/*!
 * This function returns Euler angle from a quaternion representing a rigid body's
 * attitude.
 */
template <class T> T dtkAngleFromQuaternion(const dtkQuaternion<T> &qtn)
{
    return 2*dtkRad2Deg(acos(qtn[3]));
}

//! dtkChangeOfBasis(dtkVector3D< dtkVector3D<T> >&from, dtkVector3D< dtkVector3D<T> >&to)
/*!
 * This is a "change of basis" from the "from" frame to the "to"
 * frame.  the "to" frame is typically the "Standard basis" frame.
 * The "from" is a frame that represents the current orientation
 * of the object in the shape of an orthonormal tripod.
*/
template <class T> dtkMatrixSquared<T> dtkChangeOfBasis(dtkVector3D< dtkVector3D<T> >&from,
                                                        dtkVector3D< dtkVector3D<T> >&to)
{
    dtkMatrixSquared<T> A( 3 );
    enum { x , y , z };

    // _X,_Y,_Z is typically the standard basis frame.

    //  | x^_X , y^_X , z^_X |
    //  | x^_Y , y^_Y , z^_Y |
    //  | x^_Z , y^_Z , z^_Z |

    A[0][0] = from[x]*to[x];
    A[0][1] = from[y]*to[x];
    A[0][2] = from[z]*to[x];

    A[1][0] = from[x]*to[y];
    A[1][1] = from[y]*to[y];
    A[1][2] = from[z]*to[y];

    A[2][0] = from[x]*to[z];
    A[2][1] = from[y]*to[z];
    A[2][2] = from[z]*to[z];

    // This is simply the transpose done manually which would save
    // and inverse call.
    //	| x ^ _X , x ^ _Y , x ^ _Z |
    //	| y ^ _X , y ^ _Y , y ^ _Z |
    //	| z ^ _X , z ^ _Y , z ^ _Z |

    // And finally we return the matrix that takes the "from" frame
    // to the "to"/"Standard basis" frame.
    return A;
}

#endif

// /////////////////////////////////////////////////////////////////
// Credits
// /////////////////////////////////////////////////////////////////

// $Id: coordsys.h 165 2008-01-19 19:53:19Z hkuiper $

// CwMtx matrix and vector math library
// Copyright (C) 1999-2001  Harry Kuiper
// Copyright (C) 2000  Will DeVore (template conversion)

// 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 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307
// USA
<commit_msg>Fixing matrix trace call in math layer.<commit_after>/* dtkMath.tpp ---
 *
 * Author: Julien Wintz
 * Copyright (C) 2008 - Julien Wintz, Inria.
 * Created: Wed Mar  9 11:05:40 2011 (+0100)
 * Version: $Id$
 * Last-Updated: Tue Apr 24 21:10:02 2012 (+0200)
 *           By: Julien Wintz
 *     Update #: 89
 */

/* Commentary:
 *
 */

/* Change log:
 *
 */

#ifndef DTKMATH_TPP
#define DTKMATH_TPP

#include "dtkMatrixSquared.h"
#include "dtkQuaternion.h"
#include "dtkVector3D.h"

static double dtkDeg2Rad(double v)
{
    return v*M_PI/180.0;
}

static double dtkRad2Deg(double v)
{
    return v*180.0/M_PI;
}

template <class T> dtkVector3D<T> dtkRotate(const dtkQuaternion<T>& quaternion, const dtkVector3D<T>& vector)
{
    dtkQuaternion<T> q(quaternion*dtkQuaternion<T>(vector[0], vector[1], vector[2], 0)*dtkInverse<T>(quaternion));
    return dtkVector3D<T>(q[0], q[1], q[2]);
}

//! dtkMixedProduct(const dtkVector3D &v0, const dtkVector3D &v1, const dtkVector3D &v2)
/*!
 * This function calculates the mixed product (also called triple scalar product)
 * formed by three dtkVector3D.
 */
template <class T>  T dtkMixedProduct(const dtkVector3D<T> &v0,
                                      const dtkVector3D<T> &v1,
                                      const dtkVector3D<T> &v2)
{
    dtkVector3D<T> v;
    v.storeOuterProduct(v1, v2);
    return (v0*v);
}

//! dtkQuaternionFromEulerAxisAndAngle(const dtkVector3D<T> &dtkVecEulerAxis, const T &rotateEulerAngle)
/*!
 * This function returns a quaternion representing a rigid body's
 * attitude from its Euler axis and angle.
 * NOTE: Argument vector dtkVecEulerAxis MUST be a unit vector.
 */
template <class T> dtkQuaternion<T> dtkQuaternionFromAxisAngle(const dtkVector3D<T> &axis, const T &angle)
{
    dtkVector3D<T> v = axis.unit();

    return dtkQuaternion<T>(1.0, dtkVector3D<T>(axis[0], axis[1], axis[2]), dtkDeg2Rad(angle/(T)2));
}

template <class T> dtkQuaternion<T> dtkQuaternionFromHPR(T h, T p, T r)
{
    T  cosH, sinH, cosP, sinP, cosR, sinR;
    T  half_r, half_p, half_h;

   /* put angles into radians and divide by two, since all angles in formula
    *  are (angle/2)
    */

   half_h = dtkDeg2Rad(h / 2.0);
   half_p = dtkDeg2Rad(p / 2.0);
   half_r = dtkDeg2Rad(r / 2.0);

   cosH = cos(half_h);
   sinH = sin(half_h);

   cosP = cos(half_p);
   sinP = sin(half_p);

   cosR = cos(half_r);
   sinR = sin(half_r);

   return dtkQuaternion<T>(
        sinR * cosP * cosH - cosR * sinP * sinH,
        cosR * sinP * cosH + sinR * cosP * sinH,
        cosR * cosP * sinH - sinR * sinP * cosH,
        cosR * cosP * cosH + sinR * sinP * sinH);
}

//! dtkEulerAxisFromQuaternion(const dtkQuaternion<T> &qtn)
/*!
 * This function returns Euler axis from a quaternion representing a rigid body's
 * attitude.
 */
template <class T> dtkVector3D<T> dtkAxisFromQuaternion(const dtkQuaternion<T> &qtn)
{
    dtkVector3D<T> axis(qtn[0], qtn[1], qtn[2]);

    return axis.unit();
}

//! dtkQuaternionFromMatSquared(const dtkMatrixSquared<T> &mat)
/*!
 * This function returns the quaternion corresponding to a
 * transformation matrix.
*/
template <class T> dtkQuaternion<T> dtkQuaternionFromMatSquared(const dtkMatrixSquared<T> &mat)
{
    T sclrTmp = dtkMatrixSquaredTrace(mat);

    dtkQuaternion<T> qtn;

    if(sclrTmp > 0) {
	sclrTmp = 0.5*sqrt(1 + sclrTmp);
	qtn[0] = 0.25*(mat[1][2] - mat[2][1])/sclrTmp;
	qtn[1] = 0.25*(mat[2][0] - mat[0][2])/sclrTmp;
	qtn[2] = 0.25*(mat[0][1] - mat[1][0])/sclrTmp;
	qtn[3] = sclrTmp;
    } else {
	// We could be in trouble, so we have to take
	// precautions. NOTE: Parts of this piece of code were taken
	// from the example in the article "Rotating Objects Using
	// Quaternions" in Game Developer Magazine written by Nick
	// Bobick, july 3, 1998, vol. 2, issue 26.
	int i = 0;
	if (mat[1][1] > mat[0][0]) i = 1;
	if (mat[2][2] > mat[i][i]) i = 2;

	switch (i) {
        case 0:
	    sclrTmp = 0.5*sqrt(1 + mat[0][0] - mat[1][1] - mat[2][2]);
	    qtn[0] = sclrTmp;
	    qtn[1] = 0.25*(mat[0][1] + mat[1][0])/sclrTmp;
	    qtn[2] = 0.25*(mat[0][2] + mat[2][0])/sclrTmp;
	    qtn[3] = 0.25*(mat[1][2] - mat[2][1])/sclrTmp;
	    break;

        case 1:
	    sclrTmp = 0.5*sqrt(1 - mat[0][0] + mat[1][1] - mat[2][2]);
	    qtn[0] = 0.25*(mat[1][0] + mat[0][1])/sclrTmp;
	    qtn[1] = sclrTmp;
	    qtn[2] = 0.25*(mat[1][2] + mat[2][1])/sclrTmp;
	    qtn[3] = 0.25*(mat[2][0] - mat[0][2])/sclrTmp;
	    break;

        case 2:
	    sclrTmp = 0.5*sqrt(1 - mat[0][0] - mat[1][1] + mat[2][2]);
	    qtn[0] = 0.25*(mat[2][0] + mat[0][2])/sclrTmp;
	    qtn[1] = 0.25*(mat[2][1] + mat[1][2])/sclrTmp;
	    qtn[2] = sclrTmp;
	    qtn[3] = 0.25*(mat[0][1] - mat[1][0])/sclrTmp;
	    break;
        }
    }

    return qtn;
}

//! dtkEulerAngleFromQuaternion(const dtkQuaternion<T> &qtn)
/*!
 * This function returns Euler angle from a quaternion representing a rigid body's
 * attitude.
 */
template <class T> T dtkAngleFromQuaternion(const dtkQuaternion<T> &qtn)
{
    return 2*dtkRad2Deg(acos(qtn[3]));
}

//! dtkChangeOfBasis(dtkVector3D< dtkVector3D<T> >&from, dtkVector3D< dtkVector3D<T> >&to)
/*!
 * This is a "change of basis" from the "from" frame to the "to"
 * frame.  the "to" frame is typically the "Standard basis" frame.
 * The "from" is a frame that represents the current orientation
 * of the object in the shape of an orthonormal tripod.
*/
template <class T> dtkMatrixSquared<T> dtkChangeOfBasis(dtkVector3D< dtkVector3D<T> >&from,
                                                        dtkVector3D< dtkVector3D<T> >&to)
{
    dtkMatrixSquared<T> A( 3 );
    enum { x , y , z };

    // _X,_Y,_Z is typically the standard basis frame.

    //  | x^_X , y^_X , z^_X |
    //  | x^_Y , y^_Y , z^_Y |
    //  | x^_Z , y^_Z , z^_Z |

    A[0][0] = from[x]*to[x];
    A[0][1] = from[y]*to[x];
    A[0][2] = from[z]*to[x];

    A[1][0] = from[x]*to[y];
    A[1][1] = from[y]*to[y];
    A[1][2] = from[z]*to[y];

    A[2][0] = from[x]*to[z];
    A[2][1] = from[y]*to[z];
    A[2][2] = from[z]*to[z];

    // This is simply the transpose done manually which would save
    // and inverse call.
    //	| x ^ _X , x ^ _Y , x ^ _Z |
    //	| y ^ _X , y ^ _Y , y ^ _Z |
    //	| z ^ _X , z ^ _Y , z ^ _Z |

    // And finally we return the matrix that takes the "from" frame
    // to the "to"/"Standard basis" frame.
    return A;
}

#endif

// /////////////////////////////////////////////////////////////////
// Credits
// /////////////////////////////////////////////////////////////////

// $Id: coordsys.h 165 2008-01-19 19:53:19Z hkuiper $

// CwMtx matrix and vector math library
// Copyright (C) 1999-2001  Harry Kuiper
// Copyright (C) 2000  Will DeVore (template conversion)

// 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 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307
// USA
<|endoftext|>


<commit_before>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2014.  All rights reserved
 */
#ifndef _Stroika_Foundation_Execution_Sleep_inl_
#define _Stroika_Foundation_Execution_Sleep_inl_    1

/*
 ********************************************************************************
 ***************************** Implementation Details ***************************
 ********************************************************************************
 */

#if     qPlatform_Windows
#include    <windows.h>
#elif   qPlatform_POSIX
#include    <time.h>
#include    <unistd.h>
#endif

#include    "../Debug/Assertions.h"

namespace   Stroika {
    namespace   Foundation {
        namespace   Execution {

            //redeclare to avoid having to include Thread code
            void    CheckForThreadAborting ();

            /*
            ********************************************************************************
            ******************************** Execution::Sleep ******************************
            ********************************************************************************
            */
            inline  void    Sleep (Time::DurationSecondsType seconds2Wait, Time::DurationSecondsType* remainingInSleep)
            {
                Require (seconds2Wait >= 0.0);
                RequireNotNull (remainingInSleep);  // else call the over overload
                CheckForThreadAborting ();
#if     qPlatform_Windows
                Time::DurationSecondsType   tc  =   Time::GetTickCount ();
                if (::SleepEx (static_cast<int> (seconds2Wait * 1000), true) == 0) {
                    *remainingInSleep = 0;
                }
                else {
                    Time::DurationSecondsType   remaining   = (tc + seconds2Wait) - Time::GetTickCount ();
                    if (remaining < 0) {
                        remaining = 0;
                    }
                    *remainingInSleep = remaining;
                }
#elif       qPlatform_POSIX
                const   long    kNanoSecondsPerSecond   =   1000L * 1000L * 1000L;
                timespec    ts;
                ts.tv_sec = static_cast<time_t> (seconds2Wait);
                ts.tv_nsec = static_cast<long> (kNanoSecondsPerSecond * (seconds2Wait - ts.tv_sec));
                Assert (0 <= ts.tv_nsec and ts.tv_nsec < kNanoSecondsPerSecond);
                timespec    nextTS;
                if (::nanosleep (&ts, &nextTS) == 0) {
                    *remainingInSleep = 0;
                }
                else {
                    *remainingInSleep = nextTS.tv_sec + static_cast<Time::DurationSecondsType> (ts.tv_nsec) / kNanoSecondsPerSecond;
                }
#else
                AssertNotImplemented ();
#endif
                CheckForThreadAborting ();
            }

            /*
            ********************************************************************************
            *************************** Execution::SleepUntil ******************************
            ********************************************************************************
            */
            void    SleepUntil (Time::DurationSecondsType untilTickCount)
            {
                Time::DurationSecondsType waitMoreSeconds  = untilTickCount - Time::GetTickCount ();
                if (waitMoreSeconds <= 0) {
                    CheckForThreadAborting ();
                }
                else {
                    Sleep (waitMoreSeconds);
                }
            }

        }
    }
}
#endif  /*_Stroika_Foundation_Execution_Sleep_inl_*/
<commit_msg>fixed SleepUnil<commit_after>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2014.  All rights reserved
 */
#ifndef _Stroika_Foundation_Execution_Sleep_inl_
#define _Stroika_Foundation_Execution_Sleep_inl_    1

/*
 ********************************************************************************
 ***************************** Implementation Details ***************************
 ********************************************************************************
 */

#if     qPlatform_Windows
#include    <windows.h>
#elif   qPlatform_POSIX
#include    <time.h>
#include    <unistd.h>
#endif

#include    "../Debug/Assertions.h"

namespace   Stroika {
    namespace   Foundation {
        namespace   Execution {

            //redeclare to avoid having to include Thread code
            void    CheckForThreadAborting ();

            /*
            ********************************************************************************
            ******************************** Execution::Sleep ******************************
            ********************************************************************************
            */
            inline  void    Sleep (Time::DurationSecondsType seconds2Wait, Time::DurationSecondsType* remainingInSleep)
            {
                Require (seconds2Wait >= 0.0);
                RequireNotNull (remainingInSleep);  // else call the over overload
                CheckForThreadAborting ();
#if     qPlatform_Windows
                Time::DurationSecondsType   tc  =   Time::GetTickCount ();
                if (::SleepEx (static_cast<int> (seconds2Wait * 1000), true) == 0) {
                    *remainingInSleep = 0;
                }
                else {
                    Time::DurationSecondsType   remaining   = (tc + seconds2Wait) - Time::GetTickCount ();
                    if (remaining < 0) {
                        remaining = 0;
                    }
                    *remainingInSleep = remaining;
                }
#elif       qPlatform_POSIX
                const   long    kNanoSecondsPerSecond   =   1000L * 1000L * 1000L;
                timespec    ts;
                ts.tv_sec = static_cast<time_t> (seconds2Wait);
                ts.tv_nsec = static_cast<long> (kNanoSecondsPerSecond * (seconds2Wait - ts.tv_sec));
                Assert (0 <= ts.tv_nsec and ts.tv_nsec < kNanoSecondsPerSecond);
                timespec    nextTS;
                if (::nanosleep (&ts, &nextTS) == 0) {
                    *remainingInSleep = 0;
                }
                else {
                    *remainingInSleep = nextTS.tv_sec + static_cast<Time::DurationSecondsType> (ts.tv_nsec) / kNanoSecondsPerSecond;
                }
#else
                AssertNotImplemented ();
#endif
                CheckForThreadAborting ();
            }

            /*
            ********************************************************************************
            *************************** Execution::SleepUntil ******************************
            ********************************************************************************
            */
            inline  void    SleepUntil (Time::DurationSecondsType untilTickCount)
            {
                Time::DurationSecondsType waitMoreSeconds  = untilTickCount - Time::GetTickCount ();
                if (waitMoreSeconds <= 0) {
                    CheckForThreadAborting ();
                }
                else {
                    Sleep (waitMoreSeconds);
                }
            }

        }
    }
}
#endif  /*_Stroika_Foundation_Execution_Sleep_inl_*/
<|endoftext|>


<commit_before>/**
 * \file
 * \brief SignalsCatcherControlBlock class header
 *
 * \author Copyright (C) 2015 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
 *
 * \par License
 * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
 * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * \date 2015-05-17
 */

#ifndef INCLUDE_DISTORTOS_SYNCHRONIZATION_SIGNALSCATCHERCONTROLBLOCK_HPP_
#define INCLUDE_DISTORTOS_SYNCHRONIZATION_SIGNALSCATCHERCONTROLBLOCK_HPP_

#include "distortos/SignalAction.hpp"

namespace distortos
{

namespace scheduler
{

class ThreadControlBlock;

}	// namespace scheduler

namespace synchronization
{

class SignalsReceiverControlBlock;

/// SignalsCatcherControlBlock class is a structure required by threads for "catching" and "handling" of signals
class SignalsCatcherControlBlock
{
public:

	/// association of signal numbers (as SignalSet) with SignalAction
	using Association = std::pair<SignalSet, SignalAction>;

	/// type of uninitialized storage for Association objects
	using Storage = std::aligned_storage<sizeof(Association), alignof(Association)>::type;

	/**
	 * \brief SignalsCatcherControlBlock's constructor
	 *
	 * \param [in] storageBegin is a pointer to first element of storage for Association objects
	 * \param [in] storageEnd is a pointer to "one past the last" element of storage for Association objects
	 */

	constexpr SignalsCatcherControlBlock(Storage* const storageBegin, Storage* const storageEnd) :
			signalMask_{SignalSet::empty},
			associationsBegin_{reinterpret_cast<decltype(associationsBegin_)>(storageBegin)},
			storageBegin_{storageBegin},
			storageEnd_{storageEnd},
			deliveryIsPending_{}
	{

	}

	/**
	 * \brief Gets SignalAction associated with given signal number.
	 *
	 * \param [in] signalNumber is the signal for which the association is requested, [0; 31]
	 *
	 * \return pair with return code (0 on success, error code otherwise) and SignalAction that is associated with
	 * \a signalNumber, default-constructed object if no association was found;
	 * error codes:
	 * - EINVAL - \a signalNumber value is invalid;
	 */

	std::pair<int, SignalAction> getAssociation(uint8_t signalNumber) const;

	/**
	 * \return SignalSet with signal mask for associated thread
	 */

	SignalSet getSignalMask() const
	{
		return signalMask_;
	}

	/**
	 * \brief Part of SignalsReceiverControlBlock::postGenerate() specific to catching unmasked signals.
	 *
	 * Requests delivery of signals to associated thread if there is some non-default signal handler for the signal.
	 *
	 * \param [in] signalNumber is the unmasked signal that was generated, [0; 31]
	 * \param [in] threadControlBlock is a reference to associated ThreadControlBlock
	 *
	 * \return 0 on success, error code otherwise:
	 * - EINVAL - \a signalNumber value is invalid;
	 */

	int postGenerate(uint8_t signalNumber, const scheduler::ThreadControlBlock& threadControlBlock) const;

	/**
	 * \brief Sets association for given signal number.
	 *
	 * \param [in] signalNumber is the signal for which the association will be set, [0; 31]
	 * \param [in] signalAction is a reference to SignalAction that will be associated with given signal number, object
	 * in internal storage is copy-constructed
	 *
	 * \return pair with return code (0 on success, error code otherwise) and SignalAction that was associated with
	 * \a signalNumber, default-constructed object if no association was found;
	 * error codes:
	 * - EAGAIN - no resources are available to associate \a signalNumber with \a signalAction;
	 * - EINVAL - \a signalNumber value is invalid;
	 */

	std::pair<int, SignalAction> setAssociation(uint8_t signalNumber, const SignalAction& signalAction);

	/**
	 * \brief Sets signal mask for associated thread.
	 *
	 * If any pending signal is unblocked and \a owner doesn't equal nullptr, then delivery of signals to associated
	 * thread will be requested.
	 *
	 * \param [in] signalMask is the SignalSet with new signal mask for associated thread
	 * \param [in] owner selects whether delivery of signals will be requested if any pending signal is unblocked
	 * (pointer to owner SignalsReceiverControlBlock object) or not (nullptr)
	 */

	void setSignalMask(SignalSet signalMask, const SignalsReceiverControlBlock* owner);

private:

	/**
	 * \brief Clears association for given signal number.
	 *
	 * \param [in] signalNumber is the signal for which the association will be cleared, [0; 31]
	 *
	 * \return SignalAction that was associated with \a signalNumber, default-constructed object if no association was
	 * found
	 */

	SignalAction clearAssociation(uint8_t signalNumber);

	/**
	 * \brief Clears given association for given signal number.
	 *
	 * \param [in] signalNumber is the signal for which the association will be cleared, [0; 31]
	 * \param [in] association is a reference to Association object from [associationsBegin_; associationsEnd_)
	 * range that will be removed
	 *
	 * \return SignalAction from \a association
	 */

	SignalAction clearAssociation(uint8_t signalNumber, Association& association);

	/// SignalSet with signal mask for associated thread
	SignalSet signalMask_;

	/// pointer to first element of range of Association objects
	Association* associationsBegin_;

	/// union binds \a associationsEnd_ and \a storageBegin_ - these point to the same address
	union
	{
		/// pointer to "one past the last" element of range of Association objects
		Association* associationsEnd_;

		/// pointer to first element of range of Storage objects
		Storage* storageBegin_;
	};

	/// pointer to "one past the last" element of range of Storage objects
	Storage* storageEnd_;

	/// true if signal delivery is pending, false otherwise
	bool deliveryIsPending_;
};

}	// namespace synchronization

}	// namespace distortos

#endif	// INCLUDE_DISTORTOS_SYNCHRONIZATION_SIGNALSCATCHERCONTROLBLOCK_HPP_
<commit_msg>SignalsCatcherControlBlock: add SignalsCatcherControlBlock::deliveryOfSignalsStartedHook()<commit_after>/**
 * \file
 * \brief SignalsCatcherControlBlock class header
 *
 * \author Copyright (C) 2015 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
 *
 * \par License
 * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
 * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * \date 2015-05-17
 */

#ifndef INCLUDE_DISTORTOS_SYNCHRONIZATION_SIGNALSCATCHERCONTROLBLOCK_HPP_
#define INCLUDE_DISTORTOS_SYNCHRONIZATION_SIGNALSCATCHERCONTROLBLOCK_HPP_

#include "distortos/SignalAction.hpp"

namespace distortos
{

namespace scheduler
{

class ThreadControlBlock;

}	// namespace scheduler

namespace synchronization
{

class SignalsReceiverControlBlock;

/// SignalsCatcherControlBlock class is a structure required by threads for "catching" and "handling" of signals
class SignalsCatcherControlBlock
{
public:

	/// association of signal numbers (as SignalSet) with SignalAction
	using Association = std::pair<SignalSet, SignalAction>;

	/// type of uninitialized storage for Association objects
	using Storage = std::aligned_storage<sizeof(Association), alignof(Association)>::type;

	/**
	 * \brief SignalsCatcherControlBlock's constructor
	 *
	 * \param [in] storageBegin is a pointer to first element of storage for Association objects
	 * \param [in] storageEnd is a pointer to "one past the last" element of storage for Association objects
	 */

	constexpr SignalsCatcherControlBlock(Storage* const storageBegin, Storage* const storageEnd) :
			signalMask_{SignalSet::empty},
			associationsBegin_{reinterpret_cast<decltype(associationsBegin_)>(storageBegin)},
			storageBegin_{storageBegin},
			storageEnd_{storageEnd},
			deliveryIsPending_{}
	{

	}

	/**
	 * \brief Hook function executed when delivery of signals is started.
	 *
	 * Clears "delivery pending" flag.
	 *
	 * \attention This function should be called only by SignalsReceiverControlBlock::deliveryOfSignalsFinishedHook().
	 */

	void deliveryOfSignalsStartedHook()
	{
		deliveryIsPending_ = false;
	}

	/**
	 * \brief Gets SignalAction associated with given signal number.
	 *
	 * \param [in] signalNumber is the signal for which the association is requested, [0; 31]
	 *
	 * \return pair with return code (0 on success, error code otherwise) and SignalAction that is associated with
	 * \a signalNumber, default-constructed object if no association was found;
	 * error codes:
	 * - EINVAL - \a signalNumber value is invalid;
	 */

	std::pair<int, SignalAction> getAssociation(uint8_t signalNumber) const;

	/**
	 * \return SignalSet with signal mask for associated thread
	 */

	SignalSet getSignalMask() const
	{
		return signalMask_;
	}

	/**
	 * \brief Part of SignalsReceiverControlBlock::postGenerate() specific to catching unmasked signals.
	 *
	 * Requests delivery of signals to associated thread if there is some non-default signal handler for the signal.
	 *
	 * \param [in] signalNumber is the unmasked signal that was generated, [0; 31]
	 * \param [in] threadControlBlock is a reference to associated ThreadControlBlock
	 *
	 * \return 0 on success, error code otherwise:
	 * - EINVAL - \a signalNumber value is invalid;
	 */

	int postGenerate(uint8_t signalNumber, const scheduler::ThreadControlBlock& threadControlBlock) const;

	/**
	 * \brief Sets association for given signal number.
	 *
	 * \param [in] signalNumber is the signal for which the association will be set, [0; 31]
	 * \param [in] signalAction is a reference to SignalAction that will be associated with given signal number, object
	 * in internal storage is copy-constructed
	 *
	 * \return pair with return code (0 on success, error code otherwise) and SignalAction that was associated with
	 * \a signalNumber, default-constructed object if no association was found;
	 * error codes:
	 * - EAGAIN - no resources are available to associate \a signalNumber with \a signalAction;
	 * - EINVAL - \a signalNumber value is invalid;
	 */

	std::pair<int, SignalAction> setAssociation(uint8_t signalNumber, const SignalAction& signalAction);

	/**
	 * \brief Sets signal mask for associated thread.
	 *
	 * If any pending signal is unblocked and \a owner doesn't equal nullptr, then delivery of signals to associated
	 * thread will be requested.
	 *
	 * \param [in] signalMask is the SignalSet with new signal mask for associated thread
	 * \param [in] owner selects whether delivery of signals will be requested if any pending signal is unblocked
	 * (pointer to owner SignalsReceiverControlBlock object) or not (nullptr)
	 */

	void setSignalMask(SignalSet signalMask, const SignalsReceiverControlBlock* owner);

private:

	/**
	 * \brief Clears association for given signal number.
	 *
	 * \param [in] signalNumber is the signal for which the association will be cleared, [0; 31]
	 *
	 * \return SignalAction that was associated with \a signalNumber, default-constructed object if no association was
	 * found
	 */

	SignalAction clearAssociation(uint8_t signalNumber);

	/**
	 * \brief Clears given association for given signal number.
	 *
	 * \param [in] signalNumber is the signal for which the association will be cleared, [0; 31]
	 * \param [in] association is a reference to Association object from [associationsBegin_; associationsEnd_)
	 * range that will be removed
	 *
	 * \return SignalAction from \a association
	 */

	SignalAction clearAssociation(uint8_t signalNumber, Association& association);

	/// SignalSet with signal mask for associated thread
	SignalSet signalMask_;

	/// pointer to first element of range of Association objects
	Association* associationsBegin_;

	/// union binds \a associationsEnd_ and \a storageBegin_ - these point to the same address
	union
	{
		/// pointer to "one past the last" element of range of Association objects
		Association* associationsEnd_;

		/// pointer to first element of range of Storage objects
		Storage* storageBegin_;
	};

	/// pointer to "one past the last" element of range of Storage objects
	Storage* storageEnd_;

	/// true if signal delivery is pending, false otherwise
	bool deliveryIsPending_;
};

}	// namespace synchronization

}	// namespace distortos

#endif	// INCLUDE_DISTORTOS_SYNCHRONIZATION_SIGNALSCATCHERCONTROLBLOCK_HPP_
<|endoftext|>


<commit_before>/********************************************************************
* Description: inijoint.cc
*   INI file initialization routines for joint/axis NML
*
*   Derived from a work by Fred Proctor & Will Shackleford
*
* Author:
* License: GPL Version 2
* System: Linux
*
* Copyright (c) 2004-2009 All rights reserved.
********************************************************************/

#include <unistd.h>
#include <stdio.h>		// NULL
#include <stdlib.h>		// atol(), _itoa()
#include <string.h>		// strcmp()
#include <ctype.h>		// isdigit()
#include <sys/types.h>
#include <sys/stat.h>

#include "emc.hh"
#include "rcs_print.hh"
#include "emcIniFile.hh"
#include "inijoint.hh"		// these decls
#include "emcglb.h"		// EMC_DEBUG
#include "emccfg.h"		// default values for globals

/*
  loadJoint(int joint)

  Loads ini file params for joint, joint = 0, ...

  TYPE <LINEAR ANGULAR>        type of joint
  UNITS <float>                units per mm or deg
  MAX_VELOCITY <float>         max vel for joint
  MAX_ACCELERATION <float>     max accel for joint
  BACKLASH <float>             backlash
  INPUT_SCALE <float> <float>  scale, offset
  OUTPUT_SCALE <float> <float> scale, offset
  MIN_LIMIT <float>            minimum soft position limit
  MAX_LIMIT <float>            maximum soft position limit
  FERROR <float>               maximum following error, scaled to max vel
  MIN_FERROR <float>           minimum following error
  HOME <float>                 home position (where to go after home)
  HOME_VEL <float>             speed to move from HOME_OFFSET to HOME location (at the end of homing)
  HOME_OFFSET <float>          home switch/index pulse location
  HOME_SEARCH_VEL <float>      homing speed, search phase
  HOME_LATCH_VEL <float>       homing speed, latch phase
  HOME_USE_INDEX <bool>        use index pulse when homing?
  HOME_IGNORE_LIMITS <bool>    ignore limit switches when homing?
  COMP_FILE <filename>         file of joint compensation points

  calls:

  emcJointSetJoint(int joint, unsigned char jointType);
  emcJointSetUnits(int joint, double units);
  emcJointSetBacklash(int joint, double backlash);
  emcJointSetInterpolationRate(int joint, int rate);
  emcJointSetInputScale(int joint, double scale, double offset);
  emcJointSetOutputScale(int joint, double scale, double offset);
  emcJointSetMinPositionLimit(int joint, double limit);
  emcJointSetMaxPositionLimit(int joint, double limit);
  emcJointSetFerror(int joint, double ferror);
  emcJointSetMinFerror(int joint, double ferror);
  emcJointSetHomingParams(int joint, double home, double offset,
    double search_vel, double latch_vel, int use_index, int ignore_limits );
  emcJointActivate(int joint);
  emcJointDeactivate(int joint);
  emcJointSetMaxVelocity(int joint, double vel);
  emcJointSetMaxAcceleration(int joint, double acc);
  emcJointLoadComp(int joint, const char * file);
  emcJointLoadComp(int joint, const char * file);
  */

static int loadJoint(int joint, EmcIniFile *jointIniFile)
{
    char jointString[16];
    const char *inistring;
    EmcJointType jointType;
    double units;
    double backlash;
    double offset;
    double limit;
    double home;
    double search_vel;
    double latch_vel;
    double home_vel; // moving from OFFSET to HOME
    bool use_index;
    bool ignore_limits;
    bool is_shared;
    int sequence;
    int volatile_home;
    int comp_file_type; //type for the compensation file. type==0 means nom, forw, rev.
    double maxVelocity;
    double maxAcceleration;
    double ferror;

    // compose string to match, joint = 0 -> JOINT_0, etc.
    sprintf(jointString, "JOINT_%d", joint);

    jointIniFile->EnableExceptions(EmcIniFile::ERR_CONVERSION);

    try {
        // set joint type
        jointType = EMC_LINEAR;	// default
        jointIniFile->Find(&jointType, "TYPE", jointString);
        if (0 != emcJointSetJoint(joint, jointType)) {
            return -1;
        }

        // set units
        if(jointType == EMC_LINEAR){
            units = emcTrajGetLinearUnits();
        }else{
            units = emcTrajGetAngularUnits();
        }
        if (0 != emcJointSetUnits(joint, units)) {
            return -1;
        }

        // set backlash
        backlash = 0;	                // default
        jointIniFile->Find(&backlash, "BACKLASH", jointString);
        if (0 != emcJointSetBacklash(joint, backlash)) {
            return -1;
        }

        // set min position limit
        limit = -1e99;	                // default
        jointIniFile->Find(&limit, "MIN_LIMIT", jointString);
        if (0 != emcJointSetMinPositionLimit(joint, limit)) {
             return -1;
        }

        // set max position limit
        limit = 1e99;	                // default
        jointIniFile->Find(&limit, "MAX_LIMIT", jointString);
        if (0 != emcJointSetMaxPositionLimit(joint, limit)) {
            return -1;
        }

        // set following error limit (at max speed)
        ferror = 1;	                // default
        jointIniFile->Find(&ferror, "FERROR", jointString);
        if (0 != emcJointSetFerror(joint, ferror)) {
             return -1;
        }

        // do MIN_FERROR, if it's there. If not, use value of maxFerror above
        jointIniFile->Find(&ferror, "MIN_FERROR", jointString);
        if (0 != emcJointSetMinFerror(joint, ferror)) {
            return -1;
        }

        // set homing paramsters (total of 6)
        home = 0;	                // default
        jointIniFile->Find(&home, "HOME", jointString);
        offset = 0;	                // default
        jointIniFile->Find(&offset, "HOME_OFFSET", jointString);
        search_vel = 0;	                // default
        jointIniFile->Find(&search_vel, "HOME_SEARCH_VEL", jointString);
        latch_vel = 0;	                // default
        jointIniFile->Find(&latch_vel, "HOME_LATCH_VEL", jointString);
        home_vel = -1;	                // default (rapid)
        jointIniFile->Find(&home_vel, "HOME_VEL", jointString);
        is_shared = false;	        // default
        jointIniFile->Find(&is_shared, "HOME_IS_SHARED", jointString);
        use_index = false;	        // default
        jointIniFile->Find(&use_index, "HOME_USE_INDEX", jointString);
        ignore_limits = false;	        // default
        jointIniFile->Find(&ignore_limits, "HOME_IGNORE_LIMITS", jointString);
        sequence = -1;	                // default
        jointIniFile->Find(&sequence, "HOME_SEQUENCE", jointString);
        volatile_home = 0;	        // default
        jointIniFile->Find(&volatile_home, "VOLATILE_HOME", jointString);
        // issue NML message to set all params
        if (0 != emcJointSetHomingParams(joint, home, offset, home_vel, search_vel,
                                        latch_vel, (int)use_index, (int)ignore_limits,
                                        (int)is_shared, sequence, volatile_home)) {
            return -1;
        }

        // set maximum velocity
        maxVelocity = DEFAULT_JOINT_MAX_VELOCITY;
        jointIniFile->Find(&maxVelocity, "MAX_VELOCITY", jointString);
        if (0 != emcJointSetMaxVelocity(joint, maxVelocity)) {
            return -1;
        }

        maxAcceleration = DEFAULT_JOINT_MAX_ACCELERATION;
        jointIniFile->Find(&maxAcceleration, "MAX_ACCELERATION", jointString);
        if (0 != emcJointSetMaxAcceleration(joint, maxAcceleration)) {
            return -1;
        }

        comp_file_type = 0;             // default
        jointIniFile->Find(&comp_file_type, "COMP_FILE_TYPE", jointString);
        if (NULL != (inistring = jointIniFile->Find("COMP_FILE", jointString))) {
            if (0 != emcJointLoadComp(joint, inistring, comp_file_type)) {
                return -1;
            }
        }
    }

    catch(EmcIniFile::Exception &e){
        e.Print();
        return -1;
    }

    // lastly, activate joint. Do this last so that the motion controller
    // won't flag errors midway during configuration
    emcJointActivate(joint);

    return 0;
}

/*
  iniJoint(int joint, const char *filename)

  Loads ini file parameters for specified joint, [0 .. AXES - 1]

  Looks for AXES in TRAJ section for how many to do, up to
  EMC_JOINT_MAX.
 */
int iniJoint(int joint, const char *filename)
{
    int axes;
    EmcIniFile jointIniFile(EmcIniFile::ERR_TAG_NOT_FOUND |
                           EmcIniFile::ERR_SECTION_NOT_FOUND |
                           EmcIniFile::ERR_CONVERSION);

    if (jointIniFile.Open(filename) == false) {
	return -1;
    }

    try {
        jointIniFile.Find(&axes, "AXES", "TRAJ");
    }

    catch(EmcIniFile::Exception &e){
        e.Print();
        return -1;
    }

    if (joint < 0 || joint >= axes) {
	// requested joint exceeds machine axes
	return -1;
    }

    // load its values
    if (0 != loadJoint(joint, &jointIniFile)) {
        return -1;
    }

    return 0;
}

<commit_msg>Remove limit of joint counts <= axis counts in inifile<commit_after>/********************************************************************
* Description: inijoint.cc
*   INI file initialization routines for joint/axis NML
*
*   Derived from a work by Fred Proctor & Will Shackleford
*
* Author:
* License: GPL Version 2
* System: Linux
*
* Copyright (c) 2004-2009 All rights reserved.
********************************************************************/

#include <unistd.h>
#include <stdio.h>		// NULL
#include <stdlib.h>		// atol(), _itoa()
#include <string.h>		// strcmp()
#include <ctype.h>		// isdigit()
#include <sys/types.h>
#include <sys/stat.h>

#include "emc.hh"
#include "rcs_print.hh"
#include "emcIniFile.hh"
#include "inijoint.hh"		// these decls
#include "emcglb.h"		// EMC_DEBUG
#include "emccfg.h"		// default values for globals

/*
  loadJoint(int joint)

  Loads ini file params for joint, joint = 0, ...

  TYPE <LINEAR ANGULAR>        type of joint
  UNITS <float>                units per mm or deg
  MAX_VELOCITY <float>         max vel for joint
  MAX_ACCELERATION <float>     max accel for joint
  BACKLASH <float>             backlash
  INPUT_SCALE <float> <float>  scale, offset
  OUTPUT_SCALE <float> <float> scale, offset
  MIN_LIMIT <float>            minimum soft position limit
  MAX_LIMIT <float>            maximum soft position limit
  FERROR <float>               maximum following error, scaled to max vel
  MIN_FERROR <float>           minimum following error
  HOME <float>                 home position (where to go after home)
  HOME_VEL <float>             speed to move from HOME_OFFSET to HOME location (at the end of homing)
  HOME_OFFSET <float>          home switch/index pulse location
  HOME_SEARCH_VEL <float>      homing speed, search phase
  HOME_LATCH_VEL <float>       homing speed, latch phase
  HOME_USE_INDEX <bool>        use index pulse when homing?
  HOME_IGNORE_LIMITS <bool>    ignore limit switches when homing?
  COMP_FILE <filename>         file of joint compensation points

  calls:

  emcJointSetJoint(int joint, unsigned char jointType);
  emcJointSetUnits(int joint, double units);
  emcJointSetBacklash(int joint, double backlash);
  emcJointSetInterpolationRate(int joint, int rate);
  emcJointSetInputScale(int joint, double scale, double offset);
  emcJointSetOutputScale(int joint, double scale, double offset);
  emcJointSetMinPositionLimit(int joint, double limit);
  emcJointSetMaxPositionLimit(int joint, double limit);
  emcJointSetFerror(int joint, double ferror);
  emcJointSetMinFerror(int joint, double ferror);
  emcJointSetHomingParams(int joint, double home, double offset,
    double search_vel, double latch_vel, int use_index, int ignore_limits );
  emcJointActivate(int joint);
  emcJointDeactivate(int joint);
  emcJointSetMaxVelocity(int joint, double vel);
  emcJointSetMaxAcceleration(int joint, double acc);
  emcJointLoadComp(int joint, const char * file);
  emcJointLoadComp(int joint, const char * file);
  */

static int loadJoint(int joint, EmcIniFile *jointIniFile)
{
    char jointString[16];
    const char *inistring;
    EmcJointType jointType;
    double units;
    double backlash;
    double offset;
    double limit;
    double home;
    double search_vel;
    double latch_vel;
    double home_vel; // moving from OFFSET to HOME
    bool use_index;
    bool ignore_limits;
    bool is_shared;
    int sequence;
    int volatile_home;
    int comp_file_type; //type for the compensation file. type==0 means nom, forw, rev.
    double maxVelocity;
    double maxAcceleration;
    double ferror;

    // compose string to match, joint = 0 -> JOINT_0, etc.
    sprintf(jointString, "JOINT_%d", joint);

    jointIniFile->EnableExceptions(EmcIniFile::ERR_CONVERSION);

    try {
        // set joint type
        jointType = EMC_LINEAR;	// default
        jointIniFile->Find(&jointType, "TYPE", jointString);
        if (0 != emcJointSetJoint(joint, jointType)) {
            return -1;
        }

        // set units
        if(jointType == EMC_LINEAR){
            units = emcTrajGetLinearUnits();
        }else{
            units = emcTrajGetAngularUnits();
        }
        if (0 != emcJointSetUnits(joint, units)) {
            return -1;
        }

        // set backlash
        backlash = 0;	                // default
        jointIniFile->Find(&backlash, "BACKLASH", jointString);
        if (0 != emcJointSetBacklash(joint, backlash)) {
            return -1;
        }

        // set min position limit
        limit = -1e99;	                // default
        jointIniFile->Find(&limit, "MIN_LIMIT", jointString);
        if (0 != emcJointSetMinPositionLimit(joint, limit)) {
             return -1;
        }

        // set max position limit
        limit = 1e99;	                // default
        jointIniFile->Find(&limit, "MAX_LIMIT", jointString);
        if (0 != emcJointSetMaxPositionLimit(joint, limit)) {
            return -1;
        }

        // set following error limit (at max speed)
        ferror = 1;	                // default
        jointIniFile->Find(&ferror, "FERROR", jointString);
        if (0 != emcJointSetFerror(joint, ferror)) {
             return -1;
        }

        // do MIN_FERROR, if it's there. If not, use value of maxFerror above
        jointIniFile->Find(&ferror, "MIN_FERROR", jointString);
        if (0 != emcJointSetMinFerror(joint, ferror)) {
            return -1;
        }

        // set homing paramsters (total of 6)
        home = 0;	                // default
        jointIniFile->Find(&home, "HOME", jointString);
        offset = 0;	                // default
        jointIniFile->Find(&offset, "HOME_OFFSET", jointString);
        search_vel = 0;	                // default
        jointIniFile->Find(&search_vel, "HOME_SEARCH_VEL", jointString);
        latch_vel = 0;	                // default
        jointIniFile->Find(&latch_vel, "HOME_LATCH_VEL", jointString);
        home_vel = -1;	                // default (rapid)
        jointIniFile->Find(&home_vel, "HOME_VEL", jointString);
        is_shared = false;	        // default
        jointIniFile->Find(&is_shared, "HOME_IS_SHARED", jointString);
        use_index = false;	        // default
        jointIniFile->Find(&use_index, "HOME_USE_INDEX", jointString);
        ignore_limits = false;	        // default
        jointIniFile->Find(&ignore_limits, "HOME_IGNORE_LIMITS", jointString);
        sequence = -1;	                // default
        jointIniFile->Find(&sequence, "HOME_SEQUENCE", jointString);
        volatile_home = 0;	        // default
        jointIniFile->Find(&volatile_home, "VOLATILE_HOME", jointString);
        // issue NML message to set all params
        if (0 != emcJointSetHomingParams(joint, home, offset, home_vel, search_vel,
                                        latch_vel, (int)use_index, (int)ignore_limits,
                                        (int)is_shared, sequence, volatile_home)) {
            return -1;
        }

        // set maximum velocity
        maxVelocity = DEFAULT_JOINT_MAX_VELOCITY;
        jointIniFile->Find(&maxVelocity, "MAX_VELOCITY", jointString);
        if (0 != emcJointSetMaxVelocity(joint, maxVelocity)) {
            return -1;
        }

        maxAcceleration = DEFAULT_JOINT_MAX_ACCELERATION;
        jointIniFile->Find(&maxAcceleration, "MAX_ACCELERATION", jointString);
        if (0 != emcJointSetMaxAcceleration(joint, maxAcceleration)) {
            return -1;
        }

        comp_file_type = 0;             // default
        jointIniFile->Find(&comp_file_type, "COMP_FILE_TYPE", jointString);
        if (NULL != (inistring = jointIniFile->Find("COMP_FILE", jointString))) {
            if (0 != emcJointLoadComp(joint, inistring, comp_file_type)) {
                return -1;
            }
        }
    }

    catch(EmcIniFile::Exception &e){
        e.Print();
        return -1;
    }

    // lastly, activate joint. Do this last so that the motion controller
    // won't flag errors midway during configuration
    emcJointActivate(joint);

    return 0;
}

/*
  iniJoint(int joint, const char *filename)

  Loads ini file parameters for specified joint, [0 .. AXES - 1]

  Looks for AXES in TRAJ section for how many to do, up to
  EMC_JOINT_MAX.
 */
int iniJoint(int joint, const char *filename)
{
    EmcIniFile jointIniFile(EmcIniFile::ERR_TAG_NOT_FOUND |
                           EmcIniFile::ERR_SECTION_NOT_FOUND |
                           EmcIniFile::ERR_CONVERSION);

    if (jointIniFile.Open(filename) == false) {
	return -1;
    }

    // load its values
    if (0 != loadJoint(joint, &jointIniFile)) {
        return -1;
    }

    return 0;
}

<|endoftext|>


<commit_before>// Copyright 2021 Google LLC
//
// 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
//
//      https://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 "iree_tf_compiler/TFL/Passes.h"
#include "mlir/IR/BuiltinAttributes.h"
#include "mlir/IR/BuiltinOps.h"
#include "mlir/Pass/Pass.h"
#include "mlir/Support/LLVM.h"
#include "llvm/ADT/StringExtras.h"

namespace mlir {
namespace iree_integrations {
namespace TFL {

// Extract the input and output names
static void splitFunctionIONames(StringAttr namesAttr,
                                 llvm::SmallVectorImpl<std::string> &names) {
  SmallVector<StringRef, 4> namesRef;
  llvm::SplitString(namesAttr.getValue(), namesRef, ",");
  for (auto nameRef : namesRef) {
    names.push_back(nameRef.str());
  }
}

class ConvertModuleMetadataPass
    : public PassWrapper<ConvertModuleMetadataPass, OperationPass<ModuleOp>> {
 public:
  void runOnOperation() override {
    // None currently handled.
  }
};

class ConvertFunctionMetadataPass
    : public PassWrapper<ConvertFunctionMetadataPass, OperationPass<FuncOp>> {
 public:
  void runOnOperation() override {
    auto funcOp = getOperation();

    // Setup TF entry functions as an IREE entry point and preserve the
    // associated metadata. Note that TFLite uses `tf.entry_function`.
    auto entryFunctionAttr =
        funcOp->getAttrOfType<DictionaryAttr>("tf.entry_function");
    if (entryFunctionAttr) {
      setupEntryPointAttrs(funcOp, entryFunctionAttr);
    }
  }

 private:
  // TF/TFL pack their I/O names on an annoying dictionary. We want our shape
  // names to match up with those for readability so we extract them here.
  // Is this ugly? Yeah - but such is what we have to deal with here.
  void setupEntryPointAttrs(FuncOp funcOp, DictionaryAttr entryFunctionAttr) {
    auto inputsAttr =
        entryFunctionAttr.get("inputs").template dyn_cast_or_null<StringAttr>();
    auto outputsAttr = entryFunctionAttr.get("outputs")
                           .template dyn_cast_or_null<StringAttr>();
    if (!inputsAttr || !outputsAttr) {
      funcOp.emitError() << "functions with tf.entry_function must have "
                            "input and output names to be handled by IREE";
      signalPassFailure();
      return;
    }

    funcOp->setAttr("iree.module.export", UnitAttr::get(&getContext()));

    SmallVector<std::string, 4> inputNames;
    SmallVector<std::string, 4> outputNames;
    splitFunctionIONames(inputsAttr, inputNames);
    splitFunctionIONames(outputsAttr, outputNames);
    if (inputNames.size() != funcOp.getNumArguments() ||
        outputNames.size() != funcOp.getNumResults()) {
      funcOp.emitError()
          << "tf.entry_function attribute malformed: inputs/outputs don't "
             "match the function signature";
      signalPassFailure();
      return;
    }
    for (unsigned i = 0; i < inputNames.size(); ++i) {
      funcOp.setArgAttr(i, "iree.identifier",
                        StringAttr::get(&getContext(), inputNames[i]));
    }
    for (unsigned i = 0; i < outputNames.size(); ++i) {
      funcOp.setResultAttr(i, "iree.identifier",
                           StringAttr::get(&getContext(), outputNames[i]));
    }
  }
};

std::unique_ptr<OperationPass<ModuleOp>> createConvertModuleMetadataPass() {
  return std::make_unique<ConvertModuleMetadataPass>();
}

std::unique_ptr<OperationPass<FuncOp>> createConvertFunctionMetadataPass() {
  return std::make_unique<ConvertFunctionMetadataPass>();
}

static PassRegistration<ConvertModuleMetadataPass> modulePass(
    "iree-tflite-convert-module-metadata",
    "Converts TFLite attributes to IREE attributes on modules");

static PassRegistration<ConvertFunctionMetadataPass> funcPass(
    "iree-tflite-convert-function-metadata",
    "Converts TFLite attributes to IREE attributes on functions");

}  // namespace TFL
}  // namespace iree_integrations
}  // namespace mlir
<commit_msg>Fix include sort order<commit_after>// Copyright 2021 Google LLC
//
// 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
//
//      https://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 "iree_tf_compiler/TFL/Passes.h"
#include "llvm/ADT/StringExtras.h"
#include "mlir/IR/BuiltinAttributes.h"
#include "mlir/IR/BuiltinOps.h"
#include "mlir/Pass/Pass.h"
#include "mlir/Support/LLVM.h"

namespace mlir {
namespace iree_integrations {
namespace TFL {

// Extract the input and output names
static void splitFunctionIONames(StringAttr namesAttr,
                                 llvm::SmallVectorImpl<std::string> &names) {
  SmallVector<StringRef, 4> namesRef;
  llvm::SplitString(namesAttr.getValue(), namesRef, ",");
  for (auto nameRef : namesRef) {
    names.push_back(nameRef.str());
  }
}

class ConvertModuleMetadataPass
    : public PassWrapper<ConvertModuleMetadataPass, OperationPass<ModuleOp>> {
 public:
  void runOnOperation() override {
    // None currently handled.
  }
};

class ConvertFunctionMetadataPass
    : public PassWrapper<ConvertFunctionMetadataPass, OperationPass<FuncOp>> {
 public:
  void runOnOperation() override {
    auto funcOp = getOperation();

    // Setup TF entry functions as an IREE entry point and preserve the
    // associated metadata. Note that TFLite uses `tf.entry_function`.
    auto entryFunctionAttr =
        funcOp->getAttrOfType<DictionaryAttr>("tf.entry_function");
    if (entryFunctionAttr) {
      setupEntryPointAttrs(funcOp, entryFunctionAttr);
    }
  }

 private:
  // TF/TFL pack their I/O names on an annoying dictionary. We want our shape
  // names to match up with those for readability so we extract them here.
  // Is this ugly? Yeah - but such is what we have to deal with here.
  void setupEntryPointAttrs(FuncOp funcOp, DictionaryAttr entryFunctionAttr) {
    auto inputsAttr =
        entryFunctionAttr.get("inputs").template dyn_cast_or_null<StringAttr>();
    auto outputsAttr = entryFunctionAttr.get("outputs")
                           .template dyn_cast_or_null<StringAttr>();
    if (!inputsAttr || !outputsAttr) {
      funcOp.emitError() << "functions with tf.entry_function must have "
                            "input and output names to be handled by IREE";
      signalPassFailure();
      return;
    }

    funcOp->setAttr("iree.module.export", UnitAttr::get(&getContext()));

    SmallVector<std::string, 4> inputNames;
    SmallVector<std::string, 4> outputNames;
    splitFunctionIONames(inputsAttr, inputNames);
    splitFunctionIONames(outputsAttr, outputNames);
    if (inputNames.size() != funcOp.getNumArguments() ||
        outputNames.size() != funcOp.getNumResults()) {
      funcOp.emitError()
          << "tf.entry_function attribute malformed: inputs/outputs don't "
             "match the function signature";
      signalPassFailure();
      return;
    }
    for (unsigned i = 0; i < inputNames.size(); ++i) {
      funcOp.setArgAttr(i, "iree.identifier",
                        StringAttr::get(&getContext(), inputNames[i]));
    }
    for (unsigned i = 0; i < outputNames.size(); ++i) {
      funcOp.setResultAttr(i, "iree.identifier",
                           StringAttr::get(&getContext(), outputNames[i]));
    }
  }
};

std::unique_ptr<OperationPass<ModuleOp>> createConvertModuleMetadataPass() {
  return std::make_unique<ConvertModuleMetadataPass>();
}

std::unique_ptr<OperationPass<FuncOp>> createConvertFunctionMetadataPass() {
  return std::make_unique<ConvertFunctionMetadataPass>();
}

static PassRegistration<ConvertModuleMetadataPass> modulePass(
    "iree-tflite-convert-module-metadata",
    "Converts TFLite attributes to IREE attributes on modules");

static PassRegistration<ConvertFunctionMetadataPass> funcPass(
    "iree-tflite-convert-function-metadata",
    "Converts TFLite attributes to IREE attributes on functions");

}  // namespace TFL
}  // namespace iree_integrations
}  // namespace mlir
<|endoftext|>


<commit_before>/*
 * ichip_2128.cpp
 *
 * Class to interface with the ichip 2128 based wifi adapter we're using on our board
 *
 Copyright (c) 2013 Collin Kidder, Michael Neuweiler, Charles Galpin

 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 "ichip_2128.h"

//initialization of hardware and parameters
void ICHIPWIFI::setup() {
	TickHandler::getInstance()->detach(this);

	tickCounter = 0;
	ibWritePtr = 0;
	serialInterface->begin(115200);

#ifdef GEVCU3
	digitalWrite(18, HIGH);
#endif

	//for now force a specific ad-hoc network to be set up
	sendCmd("WLCH=6"); //use WIFI channel 6
	sendCmd("WLSI=!GEVCU"); //name our ADHOC network GEVCU (the ! indicates a ad-hoc network)
	sendCmd("DIP=192.168.3.10"); //IP of GEVCU is this
	sendCmd("DPSZ=10"); //serve up 10 more addresses (11 - 20)
	sendCmd("RPG=secret"); // set the configuration password for /ichip
	enableServer();

	TickHandler::getInstance()->attach(this, CFG_TICK_INTERVAL_WIFI);
}

void ICHIPWIFI::sendCmd(String cmd) {
	serialInterface->write("AT+i");
	serialInterface->print(cmd);
	serialInterface->write(13);
	delay(10); // let the ichip process the command

	//TODO: this is just a hack to keep the input buffer from overflowing
	loop();
}

//periodic processes
void ICHIPWIFI::handleTick() {
	MotorController* motorController = DeviceManager::getInstance()->getMotorController();
	if (motorController) {
		setParam("statusMillis", millis());
		setParam("statusThrottle", motorController->getThrottle());
		setParam("statusTorqueReq", motorController->getTorqueRequested() / 10.0f, 1);
		setParam("statusTorqueActual", motorController->getTorqueActual() / 10.0f, 1);
		setParam("statusSpeedRequested", motorController->getSpeedRequested());
		setParam("statusSpeedActual", motorController->getSpeedActual());
		setParam("statusDcVoltage", motorController->getDcVoltage());
		setParam("statusDcCurrent", motorController->getDcCurrent());
		setParam("statusAcCurrent", motorController->getAcCurrent());
		if (motorController->getId() == BRUSA_DMC5)
			setParam("statusMechPower", motorController->getMechanicalPower());

		if (tickCounter++ > 3) {
			setParam("statusRunning", (motorController->isRunning() ? "true" : "false"));
			setParam("statusFaulted", (motorController->isFaulted() ? "true" : "false"));
			setParam("statusWarning", (motorController->isWarning() ? "true" : "false"));
			setParam("statusTempMotor", motorController->getTemperatureMotor() / 10.0f, 1);
			setParam("statusTempInverter", motorController->getTemperatureInverter() / 10.0f, 1);
			setParam("statusTempSystem", motorController->getTemperatureInverter() / 10.0f, 1);
			setParam("statusGear", motorController->getGearSwitch());
			tickCounter = 0;
		}
	}
}

//turn on the web server
void ICHIPWIFI::enableServer() {
	sendCmd("WWW=3"); //turn on web server for three clients
	sendCmd("DOWN"); //cause a reset to allow it to come up with the settings
}

//turn off the web server
void ICHIPWIFI::disableServer() {
	sendCmd("WWW=0"); //turn off web server
	sendCmd("DOWN"); //cause a reset to allow it to come up with the settings
}

//Determine if a parameter has changed, which one, and the new value
String ICHIPWIFI::getNextParam() {
	sendCmd("WNXT"); //send command to get next changed parameter
}

//try to retrieve the value of the given parameter
String ICHIPWIFI::getParamById(String paramName) {
	serialInterface->write("AT+i");
	serialInterface->print(paramName);
	serialInterface->print("?");
	serialInterface->write(13);
	loop();
}

//set the given parameter with the given string
void ICHIPWIFI::setParam(String paramName, String value) {
	serialInterface->write("AT+i");
	serialInterface->print(paramName);
	serialInterface->write("=");
	serialInterface->print(value);
	serialInterface->write(13);
	loop();
}

//set the given parameter with the given string
void ICHIPWIFI::setParam(String paramName, int32_t value) {
	char buffer[33];
	sprintf(buffer, "%lu", value);
	setParam(paramName, buffer);
}

//set the given parameter with the given string
void ICHIPWIFI::setParam(String paramName, float value, int precision) {
	char format[10];
	char buffer[33];
	sprintf(format, "%%.%df", precision);
	sprintf(buffer, format, value);
	setParam(paramName, buffer);
}

ICHIPWIFI::ICHIPWIFI() {
#ifdef GEVCU3
	serialInterface = &Serial2;
#else
	serialInterface = &Serial3; //default is serial 3 because that should be what our shield really uses
#endif
}

ICHIPWIFI::ICHIPWIFI(USARTClass *which) {
	serialInterface = which;
}

//called in the main loop (hopefully) in order to process serial input waiting for us
//from the wifi module. It should always terminate its answers with 13 so buffer
//until we get 13 (CR) and then process it.
//But, for now just echo stuff to our serial port for debugging
void ICHIPWIFI::loop() {
	int incoming;
	while (serialInterface->available()) {
		incoming = serialInterface->read();
		if (incoming != -1) { //and there is no reason it should be -1
			if (incoming != 13 && ibWritePtr < 127) { //add to the line
				if (incoming != 10)
					incomingBuffer[ibWritePtr++] = (char) incoming;
			} else { //that's the end of the line. Try to figure out what it said.
				incomingBuffer[ibWritePtr] = 0; //null terminate the string
				ibWritePtr = 0; //reset the write pointer
				if (strcmp(incomingBuffer, "I/ERROR") == 0) { //got an error back!
				}
				Logger::debug(ICHIP2128, incomingBuffer);
			}
		} else
			return;
	}
}

DeviceType ICHIPWIFI::getType() {
	return DEVICE_WIFI;
}

DeviceId ICHIPWIFI::getId() {
	return (ICHIP2128);
}
<commit_msg>fixed enabling of webserver on ichip<commit_after>/*
 * ichip_2128.cpp
 *
 * Class to interface with the ichip 2128 based wifi adapter we're using on our board
 *
 Copyright (c) 2013 Collin Kidder, Michael Neuweiler, Charles Galpin

 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 "ichip_2128.h"

//initialization of hardware and parameters
void ICHIPWIFI::setup() {
	TickHandler::getInstance()->detach(this);

	tickCounter = 0;
	ibWritePtr = 0;
	serialInterface->begin(115200);

#ifdef GEVCU3
	digitalWrite(18, HIGH);
#endif
	//for now force a specific ad-hoc network to be set up
	sendCmd("WLCH=6"); //use WIFI channel 6
	sendCmd("WLSI=!GEVCU"); //name our ADHOC network GEVCU (the ! indicates a ad-hoc network)
	sendCmd("DIP=192.168.3.10"); //IP of GEVCU is this
	sendCmd("DPSZ=10"); //serve up 10 more addresses (11 - 20)
	sendCmd("RPG=secret"); // set the configuration password for /ichip
	enableServer();

	TickHandler::getInstance()->attach(this, CFG_TICK_INTERVAL_WIFI);
}

void ICHIPWIFI::sendCmd(String cmd) {
	serialInterface->write("AT+i");
	serialInterface->print(cmd);
	serialInterface->write(13);
	delay(10); // let the ichip process the command

	//TODO: this is just a hack to keep the input buffer from overflowing
	loop();
}

//periodic processes
void ICHIPWIFI::handleTick() {
	MotorController* motorController = DeviceManager::getInstance()->getMotorController();
	if (motorController) {
		setParam("statusMillis", millis());
		setParam("statusThrottle", motorController->getThrottle());
		setParam("statusTorqueReq", motorController->getTorqueRequested() / 10.0f, 1);
		setParam("statusTorqueActual", motorController->getTorqueActual() / 10.0f, 1);
		setParam("statusSpeedRequested", motorController->getSpeedRequested());
		setParam("statusSpeedActual", motorController->getSpeedActual());
		setParam("statusDcVoltage", motorController->getDcVoltage());
		setParam("statusDcCurrent", motorController->getDcCurrent());
		setParam("statusAcCurrent", motorController->getAcCurrent());
		if (motorController->getId() == BRUSA_DMC5)
			setParam("statusMechPower", motorController->getMechanicalPower());

		if (tickCounter++ > 3) {
			setParam("statusRunning", (motorController->isRunning() ? "true" : "false"));
			setParam("statusFaulted", (motorController->isFaulted() ? "true" : "false"));
			setParam("statusWarning", (motorController->isWarning() ? "true" : "false"));
			setParam("statusTempMotor", motorController->getTemperatureMotor() / 10.0f, 1);
			setParam("statusTempInverter", motorController->getTemperatureInverter() / 10.0f, 1);
			setParam("statusTempSystem", motorController->getTemperatureInverter() / 10.0f, 1);
			setParam("statusGear", motorController->getGearSwitch());
			tickCounter = 0;
		}
	}
}

//turn on the web server
void ICHIPWIFI::enableServer() {
	sendCmd("AWS=1"); //turn on web server for three clients
	sendCmd("DOWN"); //cause a reset to allow it to come up with the settings
}

//turn off the web server
void ICHIPWIFI::disableServer() {
	sendCmd("AWS=0"); //turn off web server
	sendCmd("DOWN"); //cause a reset to allow it to come up with the settings
}

//Determine if a parameter has changed, which one, and the new value
String ICHIPWIFI::getNextParam() {
	sendCmd("WNXT"); //send command to get next changed parameter
}

//try to retrieve the value of the given parameter
String ICHIPWIFI::getParamById(String paramName) {
	serialInterface->write("AT+i");
	serialInterface->print(paramName);
	serialInterface->print("?");
	serialInterface->write(13);
	loop();
}

//set the given parameter with the given string
void ICHIPWIFI::setParam(String paramName, String value) {
	serialInterface->write("AT+i");
	serialInterface->print(paramName);
	serialInterface->write("=");
	serialInterface->print(value);
	serialInterface->write(13);
	loop();
}

//set the given parameter with the given string
void ICHIPWIFI::setParam(String paramName, int32_t value) {
	char buffer[33];
	sprintf(buffer, "%lu", value);
	setParam(paramName, buffer);
}

//set the given parameter with the given string
void ICHIPWIFI::setParam(String paramName, float value, int precision) {
	char format[10];
	char buffer[33];
	sprintf(format, "%%.%df", precision);
	sprintf(buffer, format, value);
	setParam(paramName, buffer);
}

ICHIPWIFI::ICHIPWIFI() {
#ifdef GEVCU3
	serialInterface = &Serial2;
#else
	serialInterface = &Serial3; //default is serial 3 because that should be what our shield really uses
#endif
}

ICHIPWIFI::ICHIPWIFI(USARTClass *which) {
	serialInterface = which;
}

//called in the main loop (hopefully) in order to process serial input waiting for us
//from the wifi module. It should always terminate its answers with 13 so buffer
//until we get 13 (CR) and then process it.
//But, for now just echo stuff to our serial port for debugging
void ICHIPWIFI::loop() {
	int incoming;
	while (serialInterface->available()) {
		incoming = serialInterface->read();
		if (incoming != -1) { //and there is no reason it should be -1
			if (incoming != 13 && ibWritePtr < 127) { //add to the line
				if (incoming != 10)
					incomingBuffer[ibWritePtr++] = (char) incoming;
			} else { //that's the end of the line. Try to figure out what it said.
				incomingBuffer[ibWritePtr] = 0; //null terminate the string
				ibWritePtr = 0; //reset the write pointer
				if (strcmp(incomingBuffer, "I/ERROR") == 0) { //got an error back!
				}
				Logger::debug(ICHIP2128, incomingBuffer);
			}
		} else
			return;
	}
}

DeviceType ICHIPWIFI::getType() {
	return DEVICE_WIFI;
}

DeviceId ICHIPWIFI::getId() {
	return (ICHIP2128);
}
<|endoftext|>