<commit_before>/* ---------------------------------------------------------------------
 * Numenta Platform for Intelligent Computing (NuPIC)
 * Copyright (C) 2015-2016, Numenta, Inc.  Unless you have an agreement
 * with Numenta, Inc., for a separate license for this software code, the
 * following terms and conditions apply:
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero Public License version 3 as
 * published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero Public License for more details.
 *
 * You should have received a copy of the GNU Affero Public License
 * along with this program.  If not, see http://www.gnu.org/licenses.
 *
 * http://numenta.org/licenses/
 * ---------------------------------------------------------------------
 */

#include "gtest/gtest.h"

/** @file
 * Implementation of performance tests for Connections
 */

#include <fstream>
#include <iostream>

#include <nupic/algorithms/SpatialPooler.hpp>
#include <nupic/algorithms/TemporalMemory.hpp>
#include <nupic/utils/Random.hpp>
#include <nupic/os/Timer.hpp>
#include <nupic/types/Types.hpp> // macro "UNUSED"

namespace testing {

using namespace std;
using namespace nupic;
using ::nupic::algorithms::spatial_pooler::SpatialPooler;
using ::nupic::algorithms::temporal_memory::TemporalMemory;

#define SEED 42

Random rng(SEED);

std::vector<UInt32> _randomSDR(UInt n, UInt w);
void _feedTM(TemporalMemory &tm, vector<CellIdx> sdr, bool learn = true);

float runTemporalMemoryTest(UInt numColumns, UInt w,   int numSequences,
                                                       int numElements,
                                                       string label) {
  Timer timer(true);

  // Initialize

  TemporalMemory tm;
  vector<UInt> columnDim;
  columnDim.push_back(numColumns);
  tm.initialize(columnDim);

  cout << (float)timer.getElapsed() << " in " << label << ": initialize"  << endl;

  // Learn

  vector<vector<vector<CellIdx>>> sequences;
  vector<vector<CellIdx>> sequence;
  vector<CellIdx> sdr;

  for (int i = 0; i < numSequences; i++) {
    for (int j = 0; j < numElements; j++) {
      sdr = _randomSDR(numColumns, w);
      sequence.push_back(sdr);
    }

    sequences.push_back(sequence);
  }

  for (int i = 0; i < 5; i++) {
    for (auto sequence : sequences) {
      for (auto sdr : sequence) {
        _feedTM(tm, sdr);
        tm.reset();
      }
    }
  }

  cout << (float)timer.getElapsed() << " in " << label << ": initialize + learn"  << endl;

  // Test

  for (auto sequence : sequences) {
    for (auto sdr : sequence) {
      _feedTM(tm, sdr, false);
      tm.reset();
    }
  }

  cout << (float)timer.getElapsed() << " in " << label << ": initialize + learn + test"  << endl;
  timer.stop();
  return timer.getElapsed();
}

float runSpatialPoolerTest(
                  UInt   numInputs,
                  Real   inputSparsity,
                  UInt   numColumns,
                  Real   columnSparsity,
                  string label)
{
#ifdef NDEBUG
  const auto trainTime = 1000u;
  const auto testTime  =  500u;
#else
  const auto trainTime = 10u;
  const auto testTime  =  5u;
#endif

  Timer timer;
  timer.start();

  // Initialize
  SpatialPooler sp(
    /* inputDimensions */               { numInputs },
    /* columnDimensions */              { numColumns },
    /* potentialRadius */               (numInputs + numColumns),
    /* potentialPct */                  0.5f,
    /* globalInhibition */              true,
    /* localAreaDensity */              columnSparsity,
    /* numActiveColumnsPerInhArea */    -1,
    /* stimulusThreshold */             6u,
    /* synPermInactiveDec */            0.01f,
    /* synPermActiveInc */              0.03f,
    /* synPermConnected */              0.4f,
    /* minPctOverlapDutyCycles */       0.001f,
    /* dutyCyclePeriod */               1000u,
    /* boostStrength */                 1.0f,
    /* seed */                          rng(),
    /* spVerbosity */                   0u,
    /* wrapAround */                    true);
  SDR input( sp.getInputDimensions() );
  SDR columns( sp.getColumnDimensions() );
  cout << (float)timer.getElapsed() << " in " << label << ": initialize"  << endl;

  // Learn
  for (auto i = 0u; i < trainTime; i++) {
    input.randomize( inputSparsity, rng );
    sp.compute( input, true, columns );
  }
  cout << (float)timer.getElapsed() << " in " << label << ": initialize + learn"  << endl;

  // Test
  for (auto i = 0u; i < testTime; i++) {
    input.randomize( inputSparsity, rng );
    sp.compute( input, false, columns );
  }
  cout << (float)timer.getElapsed() << " in " << label << ": initialize + learn + test"  << endl;
  timer.stop();
  return timer.getElapsed();
}

vector<CellIdx> _randomSDR(UInt n, UInt w) {
  set<UInt> sdrSet = set<UInt>();
  vector<CellIdx> sdr;

  for (UInt i = 0; i < w; i++) {
    sdrSet.insert(rng.getUInt32(n));
  }

  for (UInt c : sdrSet) {
    sdr.push_back(c);
  }

  return sdr;
}

void _feedTM(TemporalMemory &tm, vector<CellIdx> sdr, bool learn) {
  vector<UInt> activeColumns;

  for (auto c : sdr) {
    activeColumns.push_back(c);
  }

  tm.compute(activeColumns.size(), activeColumns.data(), learn);
}

// TESTS
#ifdef NDEBUG
  const UInt COLS = 2048; //standard num of columns in SP/TM
  const UInt SEQ = 50; //number of sequences ran in tests
  const UInt EPOCHS = 20; //tests run for epochs times
#else
  const UInt COLS = 20; //standard num of columns in SP/TM
  const UInt SEQ = 25; //number of sequences ran in tests
  const UInt EPOCHS = 4; //only short in debug; is epochs/2 in some tests, that's why 4
#endif

/**
 * Tests typical usage of Connections with Temporal Memory.
 * format is: COLS, W(bits), EPOCHS, SEQUENCES
 */
TEST(ConnectionsPerformanceTest, testTM) {
	auto tim = runTemporalMemoryTest(COLS, 40, EPOCHS, SEQ, "temporal memory");
	ASSERT_LE(tim, 1.0*Timer::getSpeed()); //there are times, we must be better. Bit underestimated for slow CI
}

/**
 * Tests typical usage of Connections with a large Temporal Memory.
 */
TEST(ConnectionsPerformanceTest, testTMLarge) {
  auto tim = runTemporalMemoryTest(2*COLS, 328, EPOCHS/2, SEQ, "temporal memory (large)");
  ASSERT_LE(tim, 1.9*Timer::getSpeed());
}

/**
 * Tests typical usage of Connections with Spatial Pooler.
 */
TEST(ConnectionsPerformanceTest, testSP) {
  auto tim = runSpatialPoolerTest(
    /* numInputs */          COLS,
    /* inputSparsity */      0.15f,
    /* numColumns */         COLS,
    /* columnSparsity */     0.05f,
    /* label */              "spatial pooler");

#ifdef NDEBUG
  ASSERT_LE(tim, 4.0f * Timer::getSpeed());
#endif
  UNUSED(tim);
}

/**
 * Tests typical usage of Connections with Temporal Pooler.
 */
TEST(ConnectionsPerformanceTest, testTP) {
  auto tim = runSpatialPoolerTest(
    /* numInputs */          2 * COLS,
    /* inputSparsity */      0.02f,
    /* numColumns */         COLS / 2,
    /* columnSparsity */     0.05f,
    /* label */              "temporal pooler");

#ifdef NDEBUG
  ASSERT_LE(tim, 4.0f * Timer::getSpeed());
#endif
  UNUSED(tim);
}

} // end namespace
<commit_msg>ConnectionsPerformanceTest: fix params so Debug check passes<commit_after>/* ---------------------------------------------------------------------
 * Numenta Platform for Intelligent Computing (NuPIC)
 * Copyright (C) 2015-2016, Numenta, Inc.  Unless you have an agreement
 * with Numenta, Inc., for a separate license for this software code, the
 * following terms and conditions apply:
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero Public License version 3 as
 * published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero Public License for more details.
 *
 * You should have received a copy of the GNU Affero Public License
 * along with this program.  If not, see http://www.gnu.org/licenses.
 *
 * http://numenta.org/licenses/
 * ---------------------------------------------------------------------
 */

#include "gtest/gtest.h"

/** @file
 * Implementation of performance tests for Connections
 */

#include <fstream>
#include <iostream>

#include <nupic/algorithms/SpatialPooler.hpp>
#include <nupic/algorithms/TemporalMemory.hpp>
#include <nupic/utils/Random.hpp>
#include <nupic/os/Timer.hpp>
#include <nupic/types/Types.hpp> // macro "UNUSED"

namespace testing {

using namespace std;
using namespace nupic;
using ::nupic::algorithms::spatial_pooler::SpatialPooler;
using ::nupic::algorithms::temporal_memory::TemporalMemory;

#define SEED 42

Random rng(SEED);

std::vector<UInt32> _randomSDR(UInt n, UInt w);
void _feedTM(TemporalMemory &tm, vector<CellIdx> sdr, bool learn = true);

float runTemporalMemoryTest(UInt numColumns, UInt w,   int numSequences,
                                                       int numElements,
                                                       string label) {
  Timer timer(true);

  // Initialize

  TemporalMemory tm;
  vector<UInt> columnDim;
  columnDim.push_back(numColumns);
  tm.initialize(columnDim);

  cout << (float)timer.getElapsed() << " in " << label << ": initialize"  << endl;

  // Learn

  vector<vector<vector<CellIdx>>> sequences;
  vector<vector<CellIdx>> sequence;
  vector<CellIdx> sdr;

  for (int i = 0; i < numSequences; i++) {
    for (int j = 0; j < numElements; j++) {
      sdr = _randomSDR(numColumns, w);
      sequence.push_back(sdr);
    }

    sequences.push_back(sequence);
  }

  for (int i = 0; i < 5; i++) {
    for (auto sequence : sequences) {
      for (auto sdr : sequence) {
        _feedTM(tm, sdr);
        tm.reset();
      }
    }
  }

  cout << (float)timer.getElapsed() << " in " << label << ": initialize + learn"  << endl;

  // Test

  for (auto sequence : sequences) {
    for (auto sdr : sequence) {
      _feedTM(tm, sdr, false);
      tm.reset();
    }
  }

  cout << (float)timer.getElapsed() << " in " << label << ": initialize + learn + test"  << endl;
  timer.stop();
  return timer.getElapsed();
}

float runSpatialPoolerTest(
                  UInt   numInputs,
                  Real   inputSparsity,
                  UInt   numColumns,
                  Real   columnSparsity,
                  string label)
{
#ifdef NDEBUG
  const auto trainTime = 1000u;
  const auto testTime  =  500u;
#else
  const auto trainTime = 10u;
  const auto testTime  =  5u;
#endif

  Timer timer;
  timer.start();

  // Initialize
  SpatialPooler sp(
    /* inputDimensions */               { numInputs },
    /* columnDimensions */              { numColumns },
    /* potentialRadius */               (numInputs + numColumns),
    /* potentialPct */                  0.5f,
    /* globalInhibition */              true,
    /* localAreaDensity */              columnSparsity,
    /* numActiveColumnsPerInhArea */    -1,
    /* stimulusThreshold */             6u,
    /* synPermInactiveDec */            0.01f,
    /* synPermActiveInc */              0.03f,
    /* synPermConnected */              0.4f,
    /* minPctOverlapDutyCycles */       0.001f,
    /* dutyCyclePeriod */               1000u,
    /* boostStrength */                 1.0f,
    /* seed */                          rng(),
    /* spVerbosity */                   0u,
    /* wrapAround */                    true);
  SDR input( sp.getInputDimensions() );
  SDR columns( sp.getColumnDimensions() );
  cout << (float)timer.getElapsed() << " in " << label << ": initialize"  << endl;

  // Learn
  for (auto i = 0u; i < trainTime; i++) {
    input.randomize( inputSparsity, rng );
    sp.compute( input, true, columns );
  }
  cout << (float)timer.getElapsed() << " in " << label << ": initialize + learn"  << endl;

  // Test
  for (auto i = 0u; i < testTime; i++) {
    input.randomize( inputSparsity, rng );
    sp.compute( input, false, columns );
  }
  cout << (float)timer.getElapsed() << " in " << label << ": initialize + learn + test"  << endl;
  timer.stop();
  return timer.getElapsed();
}

vector<CellIdx> _randomSDR(UInt n, UInt w) {
  set<UInt> sdrSet = set<UInt>();
  vector<CellIdx> sdr;

  for (UInt i = 0; i < w; i++) {
    sdrSet.insert(rng.getUInt32(n));
  }

  for (UInt c : sdrSet) {
    sdr.push_back(c);
  }

  return sdr;
}

void _feedTM(TemporalMemory &tm, vector<CellIdx> sdr, bool learn) {
  vector<UInt> activeColumns;

  for (auto c : sdr) {
    activeColumns.push_back(c);
  }

  tm.compute(activeColumns.size(), activeColumns.data(), learn);
}

// TESTS
#ifdef NDEBUG
  const UInt COLS = 2048; //standard num of columns in SP/TM
  const UInt SEQ = 50; //number of sequences ran in tests
  const UInt EPOCHS = 20; //tests run for epochs times
#else
  const UInt COLS = 20; //standard num of columns in SP/TM
  const UInt SEQ = 25; //number of sequences ran in tests
  const UInt EPOCHS = 4; //only short in debug; is epochs/2 in some tests, that's why 4
#endif

/**
 * Tests typical usage of Connections with Temporal Memory.
 * format is: COLS, W(bits), EPOCHS, SEQUENCES
 */
TEST(ConnectionsPerformanceTest, testTM) {
	auto tim = runTemporalMemoryTest(COLS, 40, EPOCHS, SEQ, "temporal memory");
	ASSERT_LE(tim, 1.0*Timer::getSpeed()); //there are times, we must be better. Bit underestimated for slow CI
}

/**
 * Tests typical usage of Connections with a large Temporal Memory.
 */
TEST(ConnectionsPerformanceTest, testTMLarge) {
  auto tim = runTemporalMemoryTest(2*COLS, 328, EPOCHS/2, SEQ, "temporal memory (large)");
  ASSERT_LE(tim, 1.9*Timer::getSpeed());
}

/**
 * Tests typical usage of Connections with Spatial Pooler.
 */
TEST(ConnectionsPerformanceTest, testSP) {
  auto tim = runSpatialPoolerTest(
    /* numInputs */          COLS,
    /* inputSparsity */      0.15f,
    /* numColumns */         COLS,
    /* columnSparsity */     0.05f,
    /* label */              "spatial pooler");

#ifdef NDEBUG
  ASSERT_LE(tim, 4.0f * Timer::getSpeed());
#endif
  UNUSED(tim);
}

/**
 * Tests typical usage of Connections with Temporal Pooler.
 */
TEST(ConnectionsPerformanceTest, testTP) {
  auto tim = runSpatialPoolerTest(
    /* numInputs */          2 * COLS,
    /* inputSparsity */      0.02f,
    /* numColumns */         COLS / 2,
    /* columnSparsity */     0.1f,
    /* label */              "temporal pooler");

#ifdef NDEBUG
  ASSERT_LE(tim, 4.0f * Timer::getSpeed());
#endif
  UNUSED(tim);
}

} // end namespace
<|endoftext|>


<commit_before>//===- TGLexer.cpp - Lexer for TableGen -----------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Implement the Lexer for TableGen.
//
//===----------------------------------------------------------------------===//

#include "TGLexer.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Config/config.h"
#include <cctype>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cerrno>
using namespace llvm;

TGLexer::TGLexer(SourceMgr &SM) : SrcMgr(SM) {
  CurBuffer = 0;
  CurBuf = SrcMgr.getMemoryBuffer(CurBuffer);
  CurPtr = CurBuf->getBufferStart();
  TokStart = 0;
}

SMLoc TGLexer::getLoc() const {
  return SMLoc::getFromPointer(TokStart);
}

/// ReturnError - Set the error to the specified string at the specified
/// location.  This is defined to always return tgtok::Error.
tgtok::TokKind TGLexer::ReturnError(const char *Loc, const Twine &Msg) {
  PrintError(Loc, Msg);
  return tgtok::Error;
}

void TGLexer::PrintError(const char *Loc, const Twine &Msg) const {
  SrcMgr.PrintMessage(SMLoc::getFromPointer(Loc), Msg, "error");
}

void TGLexer::PrintError(SMLoc Loc, const Twine &Msg) const {
  SrcMgr.PrintMessage(Loc, Msg, "error");
}

int TGLexer::getNextChar() {
  char CurChar = *CurPtr++;
  switch (CurChar) {
  default:
    return (unsigned char)CurChar;
  case 0: {
    // A nul character in the stream is either the end of the current buffer or
    // a random nul in the file.  Disambiguate that here.
    if (CurPtr-1 != CurBuf->getBufferEnd())
      return 0;  // Just whitespace.

    // If this is the end of an included file, pop the parent file off the
    // include stack.
    SMLoc ParentIncludeLoc = SrcMgr.getParentIncludeLoc(CurBuffer);
    if (ParentIncludeLoc != SMLoc()) {
      CurBuffer = SrcMgr.FindBufferContainingLoc(ParentIncludeLoc);
      CurBuf = SrcMgr.getMemoryBuffer(CurBuffer);
      CurPtr = ParentIncludeLoc.getPointer();
      return getNextChar();
    }

    // Otherwise, return end of file.
    --CurPtr;  // Another call to lex will return EOF again.
    return EOF;
  }
  case '\n':
  case '\r':
    // Handle the newline character by ignoring it and incrementing the line
    // count.  However, be careful about 'dos style' files with \n\r in them.
    // Only treat a \n\r or \r\n as a single line.
    if ((*CurPtr == '\n' || (*CurPtr == '\r')) &&
        *CurPtr != CurChar)
      ++CurPtr;  // Eat the two char newline sequence.
    return '\n';
  }
}

tgtok::TokKind TGLexer::LexToken() {
  TokStart = CurPtr;
  // This always consumes at least one character.
  int CurChar = getNextChar();

  switch (CurChar) {
  default:
    // Handle letters: [a-zA-Z_#]
    if (isalpha(CurChar) || CurChar == '_' || CurChar == '#')
      return LexIdentifier();

    // Unknown character, emit an error.
    return ReturnError(TokStart, "Unexpected character");
  case EOF: return tgtok::Eof;
  case ':': return tgtok::colon;
  case ';': return tgtok::semi;
  case '.': return tgtok::period;
  case ',': return tgtok::comma;
  case '<': return tgtok::less;
  case '>': return tgtok::greater;
  case ']': return tgtok::r_square;
  case '{': return tgtok::l_brace;
  case '}': return tgtok::r_brace;
  case '(': return tgtok::l_paren;
  case ')': return tgtok::r_paren;
  case '=': return tgtok::equal;
  case '?': return tgtok::question;

  case 0:
  case ' ':
  case '\t':
  case '\n':
  case '\r':
    // Ignore whitespace.
    return LexToken();
  case '/':
    // If this is the start of a // comment, skip until the end of the line or
    // the end of the buffer.
    if (*CurPtr == '/')
      SkipBCPLComment();
    else if (*CurPtr == '*') {
      if (SkipCComment())
        return tgtok::Error;
    } else // Otherwise, this is an error.
      return ReturnError(TokStart, "Unexpected character");
    return LexToken();
  case '-': case '+':
  case '0': case '1': case '2': case '3': case '4': case '5': case '6':
  case '7': case '8': case '9':
    return LexNumber();
  case '"': return LexString();
  case '$': return LexVarName();
  case '[': return LexBracket();
  case '!': return LexExclaim();
  }
}

/// LexString - Lex "[^"]*"
tgtok::TokKind TGLexer::LexString() {
  const char *StrStart = CurPtr;

  CurStrVal = "";

  while (*CurPtr != '"') {
    // If we hit the end of the buffer, report an error.
    if (*CurPtr == 0 && CurPtr == CurBuf->getBufferEnd())
      return ReturnError(StrStart, "End of file in string literal");

    if (*CurPtr == '\n' || *CurPtr == '\r')
      return ReturnError(StrStart, "End of line in string literal");

    if (*CurPtr != '\\') {
      CurStrVal += *CurPtr++;
      continue;
    }

    ++CurPtr;

    switch (*CurPtr) {
    case '\\': case '\'': case '"':
      // These turn into their literal character.
      CurStrVal += *CurPtr++;
      break;
    case 't':
      CurStrVal += '\t';
      ++CurPtr;
      break;
    case 'n':
      CurStrVal += '\n';
      ++CurPtr;
      break;

    case '\n':
    case '\r':
      return ReturnError(CurPtr, "escaped newlines not supported in tblgen");

    // If we hit the end of the buffer, report an error.
    case '\0':
      if (CurPtr == CurBuf->getBufferEnd())
        return ReturnError(StrStart, "End of file in string literal");
      // FALL THROUGH
    default:
      return ReturnError(CurPtr, "invalid escape in string literal");
    }
  }

  ++CurPtr;
  return tgtok::StrVal;
}

tgtok::TokKind TGLexer::LexVarName() {
  if (!isalpha(CurPtr[0]) && CurPtr[0] != '_')
    return ReturnError(TokStart, "Invalid variable name");

  // Otherwise, we're ok, consume the rest of the characters.
  const char *VarNameStart = CurPtr++;

  while (isalpha(*CurPtr) || isdigit(*CurPtr) || *CurPtr == '_')
    ++CurPtr;

  CurStrVal.assign(VarNameStart, CurPtr);
  return tgtok::VarName;
}

tgtok::TokKind TGLexer::LexIdentifier() {
  // The first letter is [a-zA-Z_#].
  const char *IdentStart = TokStart;

  // Match the rest of the identifier regex: [0-9a-zA-Z_#]*
  while (isalpha(*CurPtr) || isdigit(*CurPtr) || *CurPtr == '_' ||
         *CurPtr == '#')
    ++CurPtr;

  // Check to see if this identifier is a keyword.
  unsigned Len = CurPtr-IdentStart;

  if (Len == 3 && !memcmp(IdentStart, "int", 3)) return tgtok::Int;
  if (Len == 3 && !memcmp(IdentStart, "bit", 3)) return tgtok::Bit;
  if (Len == 4 && !memcmp(IdentStart, "bits", 4)) return tgtok::Bits;
  if (Len == 6 && !memcmp(IdentStart, "string", 6)) return tgtok::String;
  if (Len == 4 && !memcmp(IdentStart, "list", 4)) return tgtok::List;
  if (Len == 4 && !memcmp(IdentStart, "code", 4)) return tgtok::Code;
  if (Len == 3 && !memcmp(IdentStart, "dag", 3)) return tgtok::Dag;

  if (Len == 5 && !memcmp(IdentStart, "class", 5)) return tgtok::Class;
  if (Len == 3 && !memcmp(IdentStart, "def", 3)) return tgtok::Def;
  if (Len == 4 && !memcmp(IdentStart, "defm", 4)) return tgtok::Defm;
  if (Len == 10 && !memcmp(IdentStart, "multiclass", 10))
    return tgtok::MultiClass;
  if (Len == 5 && !memcmp(IdentStart, "field", 5)) return tgtok::Field;
  if (Len == 3 && !memcmp(IdentStart, "let", 3)) return tgtok::Let;
  if (Len == 2 && !memcmp(IdentStart, "in", 2)) return tgtok::In;

  if (Len == 7 && !memcmp(IdentStart, "include", 7)) {
    if (LexInclude()) return tgtok::Error;
    return Lex();
  }

  CurStrVal.assign(IdentStart, CurPtr);
  return tgtok::Id;
}

/// LexInclude - We just read the "include" token.  Get the string token that
/// comes next and enter the include.
bool TGLexer::LexInclude() {
  // The token after the include must be a string.
  tgtok::TokKind Tok = LexToken();
  if (Tok == tgtok::Error) return true;
  if (Tok != tgtok::StrVal) {
    PrintError(getLoc(), "Expected filename after include");
    return true;
  }

  // Get the string.
  std::string Filename = CurStrVal;

  CurBuffer = SrcMgr.AddIncludeFile(Filename, SMLoc::getFromPointer(CurPtr));
  if (CurBuffer == -1) {
    PrintError(getLoc(), "Could not find include file '" + Filename + "'");
    return true;
  }

  // Save the line number and lex buffer of the includer.
  CurBuf = SrcMgr.getMemoryBuffer(CurBuffer);
  CurPtr = CurBuf->getBufferStart();
  return false;
}

void TGLexer::SkipBCPLComment() {
  ++CurPtr;  // skip the second slash.
  while (1) {
    switch (*CurPtr) {
    case '\n':
    case '\r':
      return;  // Newline is end of comment.
    case 0:
      // If this is the end of the buffer, end the comment.
      if (CurPtr == CurBuf->getBufferEnd())
        return;
      break;
    }
    // Otherwise, skip the character.
    ++CurPtr;
  }
}

/// SkipCComment - This skips C-style /**/ comments.  The only difference from C
/// is that we allow nesting.
bool TGLexer::SkipCComment() {
  ++CurPtr;  // skip the star.
  unsigned CommentDepth = 1;

  while (1) {
    int CurChar = getNextChar();
    switch (CurChar) {
    case EOF:
      PrintError(TokStart, "Unterminated comment!");
      return true;
    case '*':
      // End of the comment?
      if (CurPtr[0] != '/') break;

      ++CurPtr;   // End the */.
      if (--CommentDepth == 0)
        return false;
      break;
    case '/':
      // Start of a nested comment?
      if (CurPtr[0] != '*') break;
      ++CurPtr;
      ++CommentDepth;
      break;
    }
  }
}

/// LexNumber - Lex:
///    [-+]?[0-9]+
///    0x[0-9a-fA-F]+
///    0b[01]+
tgtok::TokKind TGLexer::LexNumber() {
  if (CurPtr[-1] == '0') {
    if (CurPtr[0] == 'x') {
      ++CurPtr;
      const char *NumStart = CurPtr;
      while (isxdigit(CurPtr[0]))
        ++CurPtr;

      // Requires at least one hex digit.
      if (CurPtr == NumStart)
        return ReturnError(TokStart, "Invalid hexadecimal number");

      errno = 0;
      CurIntVal = strtoll(NumStart, 0, 16);
      if (errno == EINVAL)
        return ReturnError(TokStart, "Invalid hexadecimal number");
      if (errno == ERANGE) {
        errno = 0;
        CurIntVal = (int64_t)strtoull(NumStart, 0, 16);
        if (errno == EINVAL)
          return ReturnError(TokStart, "Invalid hexadecimal number");
        if (errno == ERANGE)
          return ReturnError(TokStart, "Hexadecimal number out of range");
      }
      return tgtok::IntVal;
    } else if (CurPtr[0] == 'b') {
      ++CurPtr;
      const char *NumStart = CurPtr;
      while (CurPtr[0] == '0' || CurPtr[0] == '1')
        ++CurPtr;

      // Requires at least one binary digit.
      if (CurPtr == NumStart)
        return ReturnError(CurPtr-2, "Invalid binary number");
      CurIntVal = strtoll(NumStart, 0, 2);
      return tgtok::IntVal;
    }
  }

  // Check for a sign without a digit.
  if (!isdigit(CurPtr[0])) {
    if (CurPtr[-1] == '-')
      return tgtok::minus;
    else if (CurPtr[-1] == '+')
      return tgtok::plus;
  }

  while (isdigit(CurPtr[0]))
    ++CurPtr;
  CurIntVal = strtoll(TokStart, 0, 10);
  return tgtok::IntVal;
}

/// LexBracket - We just read '['.  If this is a code block, return it,
/// otherwise return the bracket.  Match: '[' and '[{ ( [^}]+ | }[^]] )* }]'
tgtok::TokKind TGLexer::LexBracket() {
  if (CurPtr[0] != '{')
    return tgtok::l_square;
  ++CurPtr;
  const char *CodeStart = CurPtr;
  while (1) {
    int Char = getNextChar();
    if (Char == EOF) break;

    if (Char != '}') continue;

    Char = getNextChar();
    if (Char == EOF) break;
    if (Char == ']') {
      CurStrVal.assign(CodeStart, CurPtr-2);
      return tgtok::CodeFragment;
    }
  }

  return ReturnError(CodeStart-2, "Unterminated Code Block");
}

/// LexExclaim - Lex '!' and '![a-zA-Z]+'.
tgtok::TokKind TGLexer::LexExclaim() {
  if (!isalpha(*CurPtr))
    return ReturnError(CurPtr-1, "Invalid \"!operator\"");

  const char *Start = CurPtr++;
  while (isalpha(*CurPtr))
    ++CurPtr;

  // Check to see which operator this is.
  unsigned Len = CurPtr-Start;

  if (Len == 3  && !memcmp(Start, "con", 3)) return tgtok::XConcat;
  if (Len == 3  && !memcmp(Start, "sra", 3)) return tgtok::XSRA;
  if (Len == 3  && !memcmp(Start, "srl", 3)) return tgtok::XSRL;
  if (Len == 3  && !memcmp(Start, "shl", 3)) return tgtok::XSHL;
  if (Len == 2  && !memcmp(Start, "eq", 2)) return tgtok::XEq;
  if (Len == 9  && !memcmp(Start, "strconcat", 9))   return tgtok::XStrConcat;
  if (Len == 5 && !memcmp(Start, "subst", 5)) return tgtok::XSubst;
  if (Len == 7 && !memcmp(Start, "foreach", 7)) return tgtok::XForEach;
  if (Len == 4 && !memcmp(Start, "cast", 4)) return tgtok::XCast;
  if (Len == 3 && !memcmp(Start, "car", 3)) return tgtok::XCar;
  if (Len == 3 && !memcmp(Start, "cdr", 3)) return tgtok::XCdr;
  if (Len == 4 && !memcmp(Start, "null", 4)) return tgtok::XNull;
  if (Len == 2 && !memcmp(Start, "if", 2)) return tgtok::XIf;

  return ReturnError(Start-1, "Unknown operator");
}

<commit_msg>Cleanup table a bit.<commit_after>//===- TGLexer.cpp - Lexer for TableGen -----------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Implement the Lexer for TableGen.
//
//===----------------------------------------------------------------------===//

#include "TGLexer.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Config/config.h"
#include <cctype>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cerrno>
using namespace llvm;

TGLexer::TGLexer(SourceMgr &SM) : SrcMgr(SM) {
  CurBuffer = 0;
  CurBuf = SrcMgr.getMemoryBuffer(CurBuffer);
  CurPtr = CurBuf->getBufferStart();
  TokStart = 0;
}

SMLoc TGLexer::getLoc() const {
  return SMLoc::getFromPointer(TokStart);
}

/// ReturnError - Set the error to the specified string at the specified
/// location.  This is defined to always return tgtok::Error.
tgtok::TokKind TGLexer::ReturnError(const char *Loc, const Twine &Msg) {
  PrintError(Loc, Msg);
  return tgtok::Error;
}

void TGLexer::PrintError(const char *Loc, const Twine &Msg) const {
  SrcMgr.PrintMessage(SMLoc::getFromPointer(Loc), Msg, "error");
}

void TGLexer::PrintError(SMLoc Loc, const Twine &Msg) const {
  SrcMgr.PrintMessage(Loc, Msg, "error");
}

int TGLexer::getNextChar() {
  char CurChar = *CurPtr++;
  switch (CurChar) {
  default:
    return (unsigned char)CurChar;
  case 0: {
    // A nul character in the stream is either the end of the current buffer or
    // a random nul in the file.  Disambiguate that here.
    if (CurPtr-1 != CurBuf->getBufferEnd())
      return 0;  // Just whitespace.

    // If this is the end of an included file, pop the parent file off the
    // include stack.
    SMLoc ParentIncludeLoc = SrcMgr.getParentIncludeLoc(CurBuffer);
    if (ParentIncludeLoc != SMLoc()) {
      CurBuffer = SrcMgr.FindBufferContainingLoc(ParentIncludeLoc);
      CurBuf = SrcMgr.getMemoryBuffer(CurBuffer);
      CurPtr = ParentIncludeLoc.getPointer();
      return getNextChar();
    }

    // Otherwise, return end of file.
    --CurPtr;  // Another call to lex will return EOF again.
    return EOF;
  }
  case '\n':
  case '\r':
    // Handle the newline character by ignoring it and incrementing the line
    // count.  However, be careful about 'dos style' files with \n\r in them.
    // Only treat a \n\r or \r\n as a single line.
    if ((*CurPtr == '\n' || (*CurPtr == '\r')) &&
        *CurPtr != CurChar)
      ++CurPtr;  // Eat the two char newline sequence.
    return '\n';
  }
}

tgtok::TokKind TGLexer::LexToken() {
  TokStart = CurPtr;
  // This always consumes at least one character.
  int CurChar = getNextChar();

  switch (CurChar) {
  default:
    // Handle letters: [a-zA-Z_#]
    if (isalpha(CurChar) || CurChar == '_' || CurChar == '#')
      return LexIdentifier();

    // Unknown character, emit an error.
    return ReturnError(TokStart, "Unexpected character");
  case EOF: return tgtok::Eof;
  case ':': return tgtok::colon;
  case ';': return tgtok::semi;
  case '.': return tgtok::period;
  case ',': return tgtok::comma;
  case '<': return tgtok::less;
  case '>': return tgtok::greater;
  case ']': return tgtok::r_square;
  case '{': return tgtok::l_brace;
  case '}': return tgtok::r_brace;
  case '(': return tgtok::l_paren;
  case ')': return tgtok::r_paren;
  case '=': return tgtok::equal;
  case '?': return tgtok::question;

  case 0:
  case ' ':
  case '\t':
  case '\n':
  case '\r':
    // Ignore whitespace.
    return LexToken();
  case '/':
    // If this is the start of a // comment, skip until the end of the line or
    // the end of the buffer.
    if (*CurPtr == '/')
      SkipBCPLComment();
    else if (*CurPtr == '*') {
      if (SkipCComment())
        return tgtok::Error;
    } else // Otherwise, this is an error.
      return ReturnError(TokStart, "Unexpected character");
    return LexToken();
  case '-': case '+':
  case '0': case '1': case '2': case '3': case '4': case '5': case '6':
  case '7': case '8': case '9':
    return LexNumber();
  case '"': return LexString();
  case '$': return LexVarName();
  case '[': return LexBracket();
  case '!': return LexExclaim();
  }
}

/// LexString - Lex "[^"]*"
tgtok::TokKind TGLexer::LexString() {
  const char *StrStart = CurPtr;

  CurStrVal = "";

  while (*CurPtr != '"') {
    // If we hit the end of the buffer, report an error.
    if (*CurPtr == 0 && CurPtr == CurBuf->getBufferEnd())
      return ReturnError(StrStart, "End of file in string literal");

    if (*CurPtr == '\n' || *CurPtr == '\r')
      return ReturnError(StrStart, "End of line in string literal");

    if (*CurPtr != '\\') {
      CurStrVal += *CurPtr++;
      continue;
    }

    ++CurPtr;

    switch (*CurPtr) {
    case '\\': case '\'': case '"':
      // These turn into their literal character.
      CurStrVal += *CurPtr++;
      break;
    case 't':
      CurStrVal += '\t';
      ++CurPtr;
      break;
    case 'n':
      CurStrVal += '\n';
      ++CurPtr;
      break;

    case '\n':
    case '\r':
      return ReturnError(CurPtr, "escaped newlines not supported in tblgen");

    // If we hit the end of the buffer, report an error.
    case '\0':
      if (CurPtr == CurBuf->getBufferEnd())
        return ReturnError(StrStart, "End of file in string literal");
      // FALL THROUGH
    default:
      return ReturnError(CurPtr, "invalid escape in string literal");
    }
  }

  ++CurPtr;
  return tgtok::StrVal;
}

tgtok::TokKind TGLexer::LexVarName() {
  if (!isalpha(CurPtr[0]) && CurPtr[0] != '_')
    return ReturnError(TokStart, "Invalid variable name");

  // Otherwise, we're ok, consume the rest of the characters.
  const char *VarNameStart = CurPtr++;

  while (isalpha(*CurPtr) || isdigit(*CurPtr) || *CurPtr == '_')
    ++CurPtr;

  CurStrVal.assign(VarNameStart, CurPtr);
  return tgtok::VarName;
}

tgtok::TokKind TGLexer::LexIdentifier() {
  // The first letter is [a-zA-Z_#].
  const char *IdentStart = TokStart;

  // Match the rest of the identifier regex: [0-9a-zA-Z_#]*
  while (isalpha(*CurPtr) || isdigit(*CurPtr) || *CurPtr == '_' ||
         *CurPtr == '#')
    ++CurPtr;

  // Check to see if this identifier is a keyword.
  unsigned Len = CurPtr-IdentStart;

  if (Len == 3 && !memcmp(IdentStart, "int", 3)) return tgtok::Int;
  if (Len == 3 && !memcmp(IdentStart, "bit", 3)) return tgtok::Bit;
  if (Len == 4 && !memcmp(IdentStart, "bits", 4)) return tgtok::Bits;
  if (Len == 6 && !memcmp(IdentStart, "string", 6)) return tgtok::String;
  if (Len == 4 && !memcmp(IdentStart, "list", 4)) return tgtok::List;
  if (Len == 4 && !memcmp(IdentStart, "code", 4)) return tgtok::Code;
  if (Len == 3 && !memcmp(IdentStart, "dag", 3)) return tgtok::Dag;

  if (Len == 5 && !memcmp(IdentStart, "class", 5)) return tgtok::Class;
  if (Len == 3 && !memcmp(IdentStart, "def", 3)) return tgtok::Def;
  if (Len == 4 && !memcmp(IdentStart, "defm", 4)) return tgtok::Defm;
  if (Len == 10 && !memcmp(IdentStart, "multiclass", 10))
    return tgtok::MultiClass;
  if (Len == 5 && !memcmp(IdentStart, "field", 5)) return tgtok::Field;
  if (Len == 3 && !memcmp(IdentStart, "let", 3)) return tgtok::Let;
  if (Len == 2 && !memcmp(IdentStart, "in", 2)) return tgtok::In;

  if (Len == 7 && !memcmp(IdentStart, "include", 7)) {
    if (LexInclude()) return tgtok::Error;
    return Lex();
  }

  CurStrVal.assign(IdentStart, CurPtr);
  return tgtok::Id;
}

/// LexInclude - We just read the "include" token.  Get the string token that
/// comes next and enter the include.
bool TGLexer::LexInclude() {
  // The token after the include must be a string.
  tgtok::TokKind Tok = LexToken();
  if (Tok == tgtok::Error) return true;
  if (Tok != tgtok::StrVal) {
    PrintError(getLoc(), "Expected filename after include");
    return true;
  }

  // Get the string.
  std::string Filename = CurStrVal;

  CurBuffer = SrcMgr.AddIncludeFile(Filename, SMLoc::getFromPointer(CurPtr));
  if (CurBuffer == -1) {
    PrintError(getLoc(), "Could not find include file '" + Filename + "'");
    return true;
  }

  // Save the line number and lex buffer of the includer.
  CurBuf = SrcMgr.getMemoryBuffer(CurBuffer);
  CurPtr = CurBuf->getBufferStart();
  return false;
}

void TGLexer::SkipBCPLComment() {
  ++CurPtr;  // skip the second slash.
  while (1) {
    switch (*CurPtr) {
    case '\n':
    case '\r':
      return;  // Newline is end of comment.
    case 0:
      // If this is the end of the buffer, end the comment.
      if (CurPtr == CurBuf->getBufferEnd())
        return;
      break;
    }
    // Otherwise, skip the character.
    ++CurPtr;
  }
}

/// SkipCComment - This skips C-style /**/ comments.  The only difference from C
/// is that we allow nesting.
bool TGLexer::SkipCComment() {
  ++CurPtr;  // skip the star.
  unsigned CommentDepth = 1;

  while (1) {
    int CurChar = getNextChar();
    switch (CurChar) {
    case EOF:
      PrintError(TokStart, "Unterminated comment!");
      return true;
    case '*':
      // End of the comment?
      if (CurPtr[0] != '/') break;

      ++CurPtr;   // End the */.
      if (--CommentDepth == 0)
        return false;
      break;
    case '/':
      // Start of a nested comment?
      if (CurPtr[0] != '*') break;
      ++CurPtr;
      ++CommentDepth;
      break;
    }
  }
}

/// LexNumber - Lex:
///    [-+]?[0-9]+
///    0x[0-9a-fA-F]+
///    0b[01]+
tgtok::TokKind TGLexer::LexNumber() {
  if (CurPtr[-1] == '0') {
    if (CurPtr[0] == 'x') {
      ++CurPtr;
      const char *NumStart = CurPtr;
      while (isxdigit(CurPtr[0]))
        ++CurPtr;

      // Requires at least one hex digit.
      if (CurPtr == NumStart)
        return ReturnError(TokStart, "Invalid hexadecimal number");

      errno = 0;
      CurIntVal = strtoll(NumStart, 0, 16);
      if (errno == EINVAL)
        return ReturnError(TokStart, "Invalid hexadecimal number");
      if (errno == ERANGE) {
        errno = 0;
        CurIntVal = (int64_t)strtoull(NumStart, 0, 16);
        if (errno == EINVAL)
          return ReturnError(TokStart, "Invalid hexadecimal number");
        if (errno == ERANGE)
          return ReturnError(TokStart, "Hexadecimal number out of range");
      }
      return tgtok::IntVal;
    } else if (CurPtr[0] == 'b') {
      ++CurPtr;
      const char *NumStart = CurPtr;
      while (CurPtr[0] == '0' || CurPtr[0] == '1')
        ++CurPtr;

      // Requires at least one binary digit.
      if (CurPtr == NumStart)
        return ReturnError(CurPtr-2, "Invalid binary number");
      CurIntVal = strtoll(NumStart, 0, 2);
      return tgtok::IntVal;
    }
  }

  // Check for a sign without a digit.
  if (!isdigit(CurPtr[0])) {
    if (CurPtr[-1] == '-')
      return tgtok::minus;
    else if (CurPtr[-1] == '+')
      return tgtok::plus;
  }

  while (isdigit(CurPtr[0]))
    ++CurPtr;
  CurIntVal = strtoll(TokStart, 0, 10);
  return tgtok::IntVal;
}

/// LexBracket - We just read '['.  If this is a code block, return it,
/// otherwise return the bracket.  Match: '[' and '[{ ( [^}]+ | }[^]] )* }]'
tgtok::TokKind TGLexer::LexBracket() {
  if (CurPtr[0] != '{')
    return tgtok::l_square;
  ++CurPtr;
  const char *CodeStart = CurPtr;
  while (1) {
    int Char = getNextChar();
    if (Char == EOF) break;

    if (Char != '}') continue;

    Char = getNextChar();
    if (Char == EOF) break;
    if (Char == ']') {
      CurStrVal.assign(CodeStart, CurPtr-2);
      return tgtok::CodeFragment;
    }
  }

  return ReturnError(CodeStart-2, "Unterminated Code Block");
}

/// LexExclaim - Lex '!' and '![a-zA-Z]+'.
tgtok::TokKind TGLexer::LexExclaim() {
  if (!isalpha(*CurPtr))
    return ReturnError(CurPtr - 1, "Invalid \"!operator\"");

  const char *Start = CurPtr++;
  while (isalpha(*CurPtr))
    ++CurPtr;

  // Check to see which operator this is.
  switch (CurPtr - Start) {
  default:
    break;
  case 2:
    if (!memcmp(Start, "eq", 2)) return tgtok::XEq;
    if (!memcmp(Start, "if", 2)) return tgtok::XIf;
    break;
  case 3:
    if (!memcmp(Start, "car", 3)) return tgtok::XCar;
    if (!memcmp(Start, "cdr", 3)) return tgtok::XCdr;
    if (!memcmp(Start, "con", 3)) return tgtok::XConcat;
    if (!memcmp(Start, "shl", 3)) return tgtok::XSHL;
    if (!memcmp(Start, "sra", 3)) return tgtok::XSRA;
    if (!memcmp(Start, "srl", 3)) return tgtok::XSRL;
    break;
  case 4:
    if (!memcmp(Start, "cast", 4)) return tgtok::XCast;
    if (!memcmp(Start, "null", 4)) return tgtok::XNull;
    break;
  case 5:
    if (!memcmp(Start, "subst", 5)) return tgtok::XSubst;
    break;
  case 7:
    if (!memcmp(Start, "foreach", 7)) return tgtok::XForEach;
    break;
  case 9:
    if (!memcmp(Start, "strconcat", 9)) return tgtok::XStrConcat;
    break;
  }

  return ReturnError(Start - 1, "Unknown operator");
}

<|endoftext|>


<commit_before>/**
  ******************************************************************************
  * @file    main.cpp
  * @author  Michal Prevratil
  * @version V1.0
  * @date    01-December-2013
  * @brief   Default main function.
  ******************************************************************************
*/

#include "PWM_Generator.h"
#include "ESP.h"
#include "MS5611.h"
#include "MPU6050.h"
#include "LEDs.h"
#include "NEO_M8N.h"
#include "PID.h"
#include "Logger.h"
#include "Timer.h"
#include "ESP_Connection.h"

using namespace flyhero;

#ifdef LOG
extern "C" void initialise_monitor_handles(void);
#endif

ESP& esp = ESP::Create_Instance(ESP8266);
PWM_Generator& pwm = PWM_Generator::Instance();
MPU6050& mpu = MPU6050::Instance();
MS5611& ms5611 = MS5611::Instance();
NEO_M8N& neo = NEO_M8N::Instance();
Logger& logger = Logger::Instance();
Motors_Controller& motors_controller = Motors_Controller::Instance();

void Arm_Callback();
void IPD_Callback(uint8_t link_ID, uint8_t *data, uint16_t length);
void IMU_Data_Ready_Callback();
void IMU_Data_Read_Callback();

bool connected = false;
bool start = false;
bool inverse_yaw = false;
IWDG_HandleTypeDef hiwdg;

volatile bool data_received = false;
volatile bool log_flag = false;

int main(void)
{
	HAL_Init();
#ifdef LOG
	initialise_monitor_handles();
#endif

	uint32_t timestamp;

	LEDs::Init();

	hiwdg.Instance = IWDG;
	hiwdg.Init.Prescaler = IWDG_PRESCALER_32;
	hiwdg.Init.Reload = 480;
	// timeout after 2 s

	// reset gyro
	if (mpu.Init()) {
		LEDs::TurnOn(LEDs::Yellow);
		while (true);
	}

	logger.Init();
	esp.Init(&IPD_Callback);

	timestamp = HAL_GetTick();

	while (!connected) {
		if (HAL_GetTick() - timestamp >= 750) {
			LEDs::Toggle(LEDs::Green);

			timestamp = HAL_GetTick();
		}
		esp.Process_Data();
	}
	LEDs::TurnOff(LEDs::Green);

	pwm.Init();
	pwm.Arm(&Arm_Callback);

	if (mpu.Calibrate() != HAL_OK) {
		LEDs::TurnOn(LEDs::Yellow);
		while (true);
	}

	pwm.SetPulse(1100, 1);
	pwm.SetPulse(1100, 2);
	pwm.SetPulse(1100, 3);
	pwm.SetPulse(1100, 4);

	Timer::Delay_ms(250);

	pwm.SetPulse(940, 4);
	pwm.SetPulse(940, 1);
	pwm.SetPulse(940, 3);
	pwm.SetPulse(940, 2);

	while (!start) {
		if (HAL_GetTick() - timestamp >= 750) {
			LEDs::Toggle(LEDs::Green);

			timestamp = HAL_GetTick();
		}
		esp.Process_Data();
	}

	LEDs::TurnOn(LEDs::Green);

#ifndef LOG
	HAL_IWDG_Init(&hiwdg);
#endif

	mpu.Data_Ready_Callback = &IMU_Data_Ready_Callback;
	mpu.Data_Read_Callback = &IMU_Data_Read_Callback;

	while (true) {
		if (log_flag) {
			log_flag = false;

			// 200 us
			logger.Send_Data();
		}
		esp.Get_Connection('4')->Connection_Send_Continue();
	}
}

void IPD_Callback(uint8_t link_ID, uint8_t *data, uint16_t length) {
	switch (length) {
	case 22:
		// around 75 us
		if (data[0] == 0x5D) {
			uint16_t roll_Kp, pitch_Kp, yaw_Kp;
			uint16_t roll_Ki, pitch_Ki, yaw_Ki;
			uint16_t roll_Kd, pitch_Kd, yaw_Kd;
			uint16_t throttle;

			data_received = true;

			// 3 us
			throttle = data[1] << 8;
			throttle |= data[2];

			motors_controller.Set_Throttle(throttle + 1000);

			// 3 us
			roll_Kp = data[3] << 8;
			roll_Kp |= data[4];
			roll_Kp *= 0.01f;

			roll_Ki = data[5] << 8;
			roll_Ki |= data[6];
			roll_Ki *= 0.01f;

			roll_Kd = data[7] << 8;
			roll_Kd |= data[8];
			roll_Kd *= 0.01f;

			motors_controller.Set_PID_Constants(Roll, roll_Kp, roll_Ki, roll_Kd);

			pitch_Kp = data[9] << 8;
			pitch_Kp |= data[10];
			pitch_Kp *= 0.01f;

			pitch_Ki = data[11] << 8;
			pitch_Ki |= data[12];
			pitch_Ki *= 0.01f;

			pitch_Kd = data[13] << 8;
			pitch_Kd |= data[14];
			pitch_Kd *= 0.01f;

			motors_controller.Set_PID_Constants(Pitch, pitch_Kp, pitch_Ki, pitch_Kd);

			yaw_Kp = data[15] << 8;
			yaw_Kp |= data[16];
			yaw_Kp *= 0.01f;

			yaw_Ki = data[17] << 8;
			yaw_Ki |= data[18];
			yaw_Ki *= 0.01f;

			yaw_Kd = data[19] << 8;
			yaw_Kd |= data[20];
			yaw_Kd *= 0.01f;

			motors_controller.Set_PID_Constants(Yaw, yaw_Kp, yaw_Ki, yaw_Kd);
			motors_controller.Set_Invert_Yaw(data[21] == 0x01);
		}
		break;
	case 3:
		if (data[0] == 0x3D) {
			start = true;
		}
		if (data[0] == 0x5D) {
			connected = true;
			uint16_t log_options = (data[1] << 8) | data[2];

			logger.Set_Data_Type(Logger::WiFi, (Logger::Data_Type)log_options);
		}
		break;
	}
}

void Arm_Callback() {
	esp.Process_Data();
	//HAL_IWDG_Refresh(&hiwdg);
}

void IMU_Data_Ready_Callback() {
	// 160 us
	if (mpu.Start_Read() != HAL_OK)
		LEDs::TurnOn(LEDs::Orange);
}

// IMU_Data_Ready_Callback() -> 340 us -> IMU_Data_Read_Callback()

void IMU_Data_Read_Callback() {
	if (data_received)
		HAL_IWDG_Refresh(&hiwdg);
	data_received = false;
	log_flag = true;

	mpu.Complete_Read();
	mpu.Compute_Euler();

	motors_controller.Update_Motors();
}
<commit_msg>Fix setting PID parameters over wifi<commit_after>/**
  ******************************************************************************
  * @file    main.cpp
  * @author  Michal Prevratil
  * @version V1.0
  * @date    01-December-2013
  * @brief   Default main function.
  ******************************************************************************
*/

#include "PWM_Generator.h"
#include "ESP.h"
#include "MS5611.h"
#include "MPU6050.h"
#include "LEDs.h"
#include "NEO_M8N.h"
#include "PID.h"
#include "Logger.h"
#include "Timer.h"
#include "ESP_Connection.h"

using namespace flyhero;

#ifdef LOG
extern "C" void initialise_monitor_handles(void);
#endif

ESP& esp = ESP::Create_Instance(ESP8266);
PWM_Generator& pwm = PWM_Generator::Instance();
MPU6050& mpu = MPU6050::Instance();
MS5611& ms5611 = MS5611::Instance();
NEO_M8N& neo = NEO_M8N::Instance();
Logger& logger = Logger::Instance();
Motors_Controller& motors_controller = Motors_Controller::Instance();

void Arm_Callback();
void IPD_Callback(uint8_t link_ID, uint8_t *data, uint16_t length);
void IMU_Data_Ready_Callback();
void IMU_Data_Read_Callback();

bool connected = false;
bool start = false;
bool inverse_yaw = false;
IWDG_HandleTypeDef hiwdg;

volatile bool data_received = false;
volatile bool log_flag = false;

int main(void)
{
	HAL_Init();
#ifdef LOG
	initialise_monitor_handles();
#endif

	uint32_t timestamp;

	LEDs::Init();

	hiwdg.Instance = IWDG;
	hiwdg.Init.Prescaler = IWDG_PRESCALER_32;
	hiwdg.Init.Reload = 480;
	// timeout after 2 s

	// reset gyro
	if (mpu.Init()) {
		LEDs::TurnOn(LEDs::Yellow);
		while (true);
	}

	logger.Init();
	esp.Init(&IPD_Callback);

	timestamp = HAL_GetTick();

	while (!connected) {
		if (HAL_GetTick() - timestamp >= 750) {
			LEDs::Toggle(LEDs::Green);

			timestamp = HAL_GetTick();
		}
		esp.Process_Data();
	}
	LEDs::TurnOff(LEDs::Green);

	pwm.Init();
	pwm.Arm(&Arm_Callback);

	if (mpu.Calibrate() != HAL_OK) {
		LEDs::TurnOn(LEDs::Yellow);
		while (true);
	}

	pwm.SetPulse(1100, 1);
	pwm.SetPulse(1100, 2);
	pwm.SetPulse(1100, 3);
	pwm.SetPulse(1100, 4);

	Timer::Delay_ms(250);

	pwm.SetPulse(940, 4);
	pwm.SetPulse(940, 1);
	pwm.SetPulse(940, 3);
	pwm.SetPulse(940, 2);

	while (!start) {
		if (HAL_GetTick() - timestamp >= 750) {
			LEDs::Toggle(LEDs::Green);

			timestamp = HAL_GetTick();
		}
		esp.Process_Data();
	}

	LEDs::TurnOn(LEDs::Green);

#ifndef LOG
	HAL_IWDG_Init(&hiwdg);
#endif

	mpu.Data_Ready_Callback = &IMU_Data_Ready_Callback;
	mpu.Data_Read_Callback = &IMU_Data_Read_Callback;

	while (true) {
		if (log_flag) {
			log_flag = false;

			// 200 us
			logger.Send_Data();
		}
		esp.Get_Connection('4')->Connection_Send_Continue();
	}
}

void IPD_Callback(uint8_t link_ID, uint8_t *data, uint16_t length) {
	switch (length) {
	case 22:
		// around 75 us
		if (data[0] == 0x5D) {
			uint16_t roll_Kp, pitch_Kp, yaw_Kp;
			uint16_t roll_Ki, pitch_Ki, yaw_Ki;
			uint16_t roll_Kd, pitch_Kd, yaw_Kd;
			uint16_t throttle;

			data_received = true;

			// 3 us
			throttle = data[1] << 8;
			throttle |= data[2];

			motors_controller.Set_Throttle(throttle + 1000);

			// 3 us
			roll_Kp = data[3] << 8;
			roll_Kp |= data[4];

			roll_Ki = data[5] << 8;
			roll_Ki |= data[6];

			roll_Kd = data[7] << 8;
			roll_Kd |= data[8];

			motors_controller.Set_PID_Constants(Roll, roll_Kp * 0.01f, roll_Ki * 0.01f, roll_Kd * 0.01f);

			pitch_Kp = data[9] << 8;
			pitch_Kp |= data[10];

			pitch_Ki = data[11] << 8;
			pitch_Ki |= data[12];

			pitch_Kd = data[13] << 8;
			pitch_Kd |= data[14];

			motors_controller.Set_PID_Constants(Pitch, pitch_Kp * 0.01f, pitch_Ki * 0.01f, pitch_Kd * 0.01f);

			yaw_Kp = data[15] << 8;
			yaw_Kp |= data[16];

			yaw_Ki = data[17] << 8;
			yaw_Ki |= data[18];

			yaw_Kd = data[19] << 8;
			yaw_Kd |= data[20];

			motors_controller.Set_PID_Constants(Yaw, yaw_Kp * 0.01f, yaw_Ki * 0.01f, yaw_Kd * 0.01f);
			motors_controller.Set_Invert_Yaw(data[21] == 0x01);
		}
		break;
	case 3:
		if (data[0] == 0x3D) {
			start = true;
		}
		if (data[0] == 0x5D) {
			connected = true;
			uint16_t log_options = (data[1] << 8) | data[2];

			logger.Set_Data_Type(Logger::WiFi, (Logger::Data_Type)log_options);
		}
		break;
	}
}

void Arm_Callback() {
	esp.Process_Data();
	//HAL_IWDG_Refresh(&hiwdg);
}

void IMU_Data_Ready_Callback() {
	// 160 us
	if (mpu.Start_Read() != HAL_OK)
		LEDs::TurnOn(LEDs::Orange);
}

// IMU_Data_Ready_Callback() -> 340 us -> IMU_Data_Read_Callback()

void IMU_Data_Read_Callback() {
	if (data_received)
		HAL_IWDG_Refresh(&hiwdg);
	data_received = false;
	log_flag = true;

	mpu.Complete_Read();
	mpu.Compute_Euler();

	motors_controller.Update_Motors();
}
<|endoftext|>


<commit_before>/* -*- coding: utf-8; mode: c++; tab-width: 3; indent-tabs-mode: nil -*-

Copyright 2010, 2011, 2012, 2013, 2014
Raffaello D. Di Napoli

This file is part of Abaclade.

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

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

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

#ifndef _ABACLADE_APP_HXX
#define _ABACLADE_APP_HXX

#ifndef _ABACLADE_HXX
   #error Please #include <abaclade.hxx> before this file
#endif
#ifdef ABC_CXX_PRAGMA_ONCE
   #pragma once
#endif

////////////////////////////////////////////////////////////////////////////////////////////////////
// abc::app

/** DOC:1063 Application startup and abc::app

Programs using Abaclade declare their main() function by deriving a class from abc::app, overriding
its main() method, and declaring that the derived class contains the program’s entry point using
ABC_APP_CLASS().

The ABC_APP_CLASS() macro defines the actual entry point of the program, using whatever
protocol is supported by the host (e.g. int main(…) on POSIX, BOOL WinMain(…) on Windows GUI). This
is a very thin wrapper around a static method of abc::app which takes care of setting up the
outermost try/catch block to intercept uncaught exceptions (see [DOC:8503 Stack tracing]), as well
as instantiating the application-defined abc::app-derived class, invoking its main() method and
returning.
*/

namespace abc {

/** Abstract application.
*/
class ABACLADE_SYM app {
public:

   /** Constructor.
   */
   app();

   /** Destructor.
   */
   virtual ~app();

   /** C-style entry point for executables.

   cArgs
      Count of arguments.
   ppszArgs
      Arguments.
   return
      Return code of the program.
   */
   template <class TApp>
   static int entry_point_main(int cArgs, char_t ** ppszArgs) {
      // Establish this as early as possible.
      exception::async_handler_manager eahm;
      try {
         // Create and initialize the app.
         TApp app;
         // Use a smvector to avoid dynamic allocation for just a few arguments.
         smvector<istr const, 8> vsArgs;
         app._build_args(cArgs, ppszArgs, &vsArgs);
         // Invoke the program-defined main().
         return app.main(vsArgs);
      } catch (std::exception const & x) {
         exception::write_with_scope_trace(nullptr, &x);
         return 123;
      } catch (...) {
         exception::write_with_scope_trace();
         return 123;
      }
   }

#if ABC_HOST_API_WIN32

   /** Entry point for Windows executables.

   hinst
      Module’s instance handle.
   iShowCmd
      Indication on how the application’s main window should be displayed; one of SW_* flags.
   */
   template <class TApp>
   static int entry_point_win_exe(HINSTANCE hinst, int iShowCmd) {
      ABC_UNUSED_ARG(iShowCmd);

      // Establish this as early as possible.
      exception::async_handler_manager eahm;
      try {
         // Create and initialize the app.
         TApp app;
         smvector<istr const, 8> vsArgs;
//       app._build_args(&vsArgs);
         // Invoke the program-defined main().
         return app.main(vsArgs);
      } catch (std::exception const & x) {
         exception::write_with_scope_trace(nullptr, &x);
         return 123;
      } catch (...) {
         exception::write_with_scope_trace();
         return 123;
      }
   }

#endif //if ABC_HOST_API_WIN32

   /** Entry point of the application.

   vsArgs
      Command-line arguments.
   return
      Return code of the program.
   */
   virtual int main(mvector<istr const> const & vsArgs) = 0;

protected:

   /** Fills up a string vector from the command-line arguments.

   cArgs
      Number of arguments.
   ppszArgs
      Arguments.
   pvsRet
      Vector to receive unsafe istr instances containing each argument.
   */
   static void _build_args(int cArgs, char_t ** ppszArgs, mvector<istr const> * pvsRet);
#if ABC_HOST_API_WIN32
   // Overload that uses ::GetCommandLine() internally.
   static void _build_args(mvector<istr const> * pvsRet);
#endif

protected:

   /** Pointer to the one and only instance of the application-defined app class. */
   static app * sm_papp;
};

} //namespace abc

/** Declares an abc::app-derived class as being the app class for the application.

cls
   Main abc::app-derived class.
*/
#if ABC_HOST_API_POSIX
   #define ABC_APP_CLASS(cls) \
      extern "C" int main(int cArgs, char ** ppszArgs) { \
         return ::abc::app::entry_point_main<cls>(cArgs, ppszArgs); \
      }
#elif ABC_HOST_API_WIN32 //if ABC_HOST_API_POSIX
   // TODO: find a way to define ABC_HOST_API_WIN32_GUI, and maybe come up with a better name.
   #ifdef ABC_HOST_API_WIN32_GUI
      #define ABC_APP_CLASS(cls) \
         extern "C" int WINAPI wWinMain( \
            HINSTANCE hinst, HINSTANCE, wchar_t * pszCmdLine, int iShowCmd \
         ) { \
            ABC_UNUSED_ARG(pszCmdLine); \
            return ::abc::app::entry_point_win_exe<cls>(hinst, iShowCmd); \
         }
   #else
      #define ABC_APP_CLASS(cls) \
         extern "C" int ABC_STL_CALLCONV wmain(int cArgs, wchar_t ** ppszArgs) { \
            return ::abc::app::entry_point_main<cls>(cArgs, ppszArgs); \
         }
   #endif
#else //if ABC_HOST_API_POSIX … elif ABC_HOST_API_WIN32
   #error TODO-PORT: OUTPUT
#endif //if ABC_HOST_API_POSIX … elif ABC_HOST_API_WIN32 … else

////////////////////////////////////////////////////////////////////////////////////////////////////

#endif //ifndef _ABACLADE_APP_HXX

<commit_msg>Make abc::app non-copyable<commit_after>/* -*- coding: utf-8; mode: c++; tab-width: 3; indent-tabs-mode: nil -*-

Copyright 2010, 2011, 2012, 2013, 2014
Raffaello D. Di Napoli

This file is part of Abaclade.

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

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

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

#ifndef _ABACLADE_APP_HXX
#define _ABACLADE_APP_HXX

#ifndef _ABACLADE_HXX
   #error Please #include <abaclade.hxx> before this file
#endif
#ifdef ABC_CXX_PRAGMA_ONCE
   #pragma once
#endif

////////////////////////////////////////////////////////////////////////////////////////////////////
// abc::app

/** DOC:1063 Application startup and abc::app

Programs using Abaclade declare their main() function by deriving a class from abc::app, overriding
its main() method, and declaring that the derived class contains the program’s entry point using
ABC_APP_CLASS().

The ABC_APP_CLASS() macro defines the actual entry point of the program, using whatever
protocol is supported by the host (e.g. int main(…) on POSIX, BOOL WinMain(…) on Windows GUI). This
is a very thin wrapper around a static method of abc::app which takes care of setting up the
outermost try/catch block to intercept uncaught exceptions (see [DOC:8503 Stack tracing]), as well
as instantiating the application-defined abc::app-derived class, invoking its main() method and
returning.
*/

namespace abc {

/** Abstract application.
*/
class ABACLADE_SYM app :
   public noncopyable {
public:

   /** Constructor.
   */
   app();

   /** Destructor.
   */
   virtual ~app();

   /** C-style entry point for executables.

   cArgs
      Count of arguments.
   ppszArgs
      Arguments.
   return
      Return code of the program.
   */
   template <class TApp>
   static int entry_point_main(int cArgs, char_t ** ppszArgs) {
      // Establish this as early as possible.
      exception::async_handler_manager eahm;
      try {
         // Create and initialize the app.
         TApp app;
         // Use a smvector to avoid dynamic allocation for just a few arguments.
         smvector<istr const, 8> vsArgs;
         app._build_args(cArgs, ppszArgs, &vsArgs);
         // Invoke the program-defined main().
         return app.main(vsArgs);
      } catch (std::exception const & x) {
         exception::write_with_scope_trace(nullptr, &x);
         return 123;
      } catch (...) {
         exception::write_with_scope_trace();
         return 123;
      }
   }

#if ABC_HOST_API_WIN32

   /** Entry point for Windows executables.

   hinst
      Module’s instance handle.
   iShowCmd
      Indication on how the application’s main window should be displayed; one of SW_* flags.
   */
   template <class TApp>
   static int entry_point_win_exe(HINSTANCE hinst, int iShowCmd) {
      ABC_UNUSED_ARG(iShowCmd);

      // Establish this as early as possible.
      exception::async_handler_manager eahm;
      try {
         // Create and initialize the app.
         TApp app;
         smvector<istr const, 8> vsArgs;
//       app._build_args(&vsArgs);
         // Invoke the program-defined main().
         return app.main(vsArgs);
      } catch (std::exception const & x) {
         exception::write_with_scope_trace(nullptr, &x);
         return 123;
      } catch (...) {
         exception::write_with_scope_trace();
         return 123;
      }
   }

#endif //if ABC_HOST_API_WIN32

   /** Entry point of the application.

   vsArgs
      Command-line arguments.
   return
      Return code of the program.
   */
   virtual int main(mvector<istr const> const & vsArgs) = 0;

protected:

   /** Fills up a string vector from the command-line arguments.

   cArgs
      Number of arguments.
   ppszArgs
      Arguments.
   pvsRet
      Vector to receive unsafe istr instances containing each argument.
   */
   static void _build_args(int cArgs, char_t ** ppszArgs, mvector<istr const> * pvsRet);
#if ABC_HOST_API_WIN32
   // Overload that uses ::GetCommandLine() internally.
   static void _build_args(mvector<istr const> * pvsRet);
#endif

protected:

   /** Pointer to the one and only instance of the application-defined app class. */
   static app * sm_papp;
};

} //namespace abc

/** Declares an abc::app-derived class as being the app class for the application.

cls
   Main abc::app-derived class.
*/
#if ABC_HOST_API_POSIX
   #define ABC_APP_CLASS(cls) \
      extern "C" int main(int cArgs, char ** ppszArgs) { \
         return ::abc::app::entry_point_main<cls>(cArgs, ppszArgs); \
      }
#elif ABC_HOST_API_WIN32 //if ABC_HOST_API_POSIX
   // TODO: find a way to define ABC_HOST_API_WIN32_GUI, and maybe come up with a better name.
   #ifdef ABC_HOST_API_WIN32_GUI
      #define ABC_APP_CLASS(cls) \
         extern "C" int WINAPI wWinMain( \
            HINSTANCE hinst, HINSTANCE, wchar_t * pszCmdLine, int iShowCmd \
         ) { \
            ABC_UNUSED_ARG(pszCmdLine); \
            return ::abc::app::entry_point_win_exe<cls>(hinst, iShowCmd); \
         }
   #else
      #define ABC_APP_CLASS(cls) \
         extern "C" int ABC_STL_CALLCONV wmain(int cArgs, wchar_t ** ppszArgs) { \
            return ::abc::app::entry_point_main<cls>(cArgs, ppszArgs); \
         }
   #endif
#else //if ABC_HOST_API_POSIX … elif ABC_HOST_API_WIN32
   #error TODO-PORT: OUTPUT
#endif //if ABC_HOST_API_POSIX … elif ABC_HOST_API_WIN32 … else

////////////////////////////////////////////////////////////////////////////////////////////////////

#endif //ifndef _ABACLADE_APP_HXX

<|endoftext|>


<commit_before>//=============================================================================
// ■ audio.hpp
//-----------------------------------------------------------------------------
//   处理播放声音的模块。
//=============================================================================

#ifndef _AUDIO_HPP
	#define _AUDIO_HPP
	#define pa_callback(name) \
		int name( \
			const void* input_buffer, \
			void* output_buffer, \
			unsigned long frame_count, \
			const PaStreamCallbackTimeInfo* time_info, \
			PaStreamCallbackFlags status_flags, \
			void* user_data \
		)
	namespace Audio {
		class channel;
		class
		struct channel {
			enum channel_type {
				CHANNEL_TYPE_MUTE,
				CHANNEL_TYPE_TRIANGLE,
				CHANNEL_TYPE_SINE,
				CHANNEL_TYPE_VORBIS,
			} type;
			union {
				struct triangle_data {
					float value;
					float delta;
				} triangle;
				struct sine_data {
					float index;
					float index_delta;
					bool minus;
					float value; // for convenience only
				} sine;
				struct vorbis_data {
					PaStream* stream;
					FILE* file;
					OggVorbis_File vf;
					#define AUDIO_VF_BUFFER_SIZE ((size_t) 4096)
					float vf_buffer[2][AUDIO_VF_BUFFER_SIZE];
					size_t play_head;
					size_t load_head;
					bool eof;
					bool loop;
					int bitstream;
					thread* decode_thread;
				} vorbis;
			}; // data
		};
		extern PaStream* stream;
		#define AUDIO_CHANNELS_SIZE ((size_t) 16)
		extern struct channel channels[AUDIO_CHANNELS_SIZE];
		void init();
		void terminate();
		void ensure_no_error(PaError err);
		pa_callback(callback);
		void stop();
		void stop_waves();
		void play_triangle(float freq);
		void get_next_triangle_value(struct triangle_data* data);
		void play_sine(float freq);
		void get_next_sine_value(struct sine_data* data);
		void compact_active_sounds_array();
		void play_sound(const char* filename, bool loop);
		void decode_vorbis(struct active_sound* sound);
		void decode_vorbis_thread(struct active_sound* sound);
	}
<commit_msg>Audio WIP<commit_after>//=============================================================================
// ■ audio.hpp
//-----------------------------------------------------------------------------
//   处理播放声音的模块。
//=============================================================================

#ifndef _AUDIO_HPP
#define _AUDIO_HPP
#define pa_callback(name) \
	int name( \
		const void* input_buffer, \
		void* output_buffer, \
		unsigned long frame_count, \
		const PaStreamCallbackTimeInfo* time_info, \
		PaStreamCallbackFlags status_flags, \
		void* user_data \
	)
namespace Audio {
	//-------------------------------------------------------------------------
	// ● Channel
	//-------------------------------------------------------------------------
	class Channel {
	};
	class Channel_Mute : public Channel {
	};
	class Channel_Triangle : public Channel {
		float value;
		float delta;
	};
	class Channel_Sine : public Channel {
		float index;
		float index_delta;
		bool minus;
		float value; // for convenience only
	};
	class Channel_Vorbis : public Channel {
		PaStream* stream;
		FILE* file;
		OggVorbis_File vf;
		#define AUDIO_VF_BUFFER_SIZE ((size_t) 4096)
		float vf_buffer[2][AUDIO_VF_BUFFER_SIZE];
		size_t play_head;
		size_t load_head;
		bool eof;
		bool loop;
		int bitstream;
		thread* decode_thread;
	} vorbis;
	//-------------------------------------------------------------------------
	// ● 模块变量
	//-------------------------------------------------------------------------
	extern PaStream* stream;
	#define AUDIO_CHANNELS_SIZE ((size_t) 16)
	extern Channel* channels[AUDIO_CHANNELS_SIZE];
	//-------------------------------------------------------------------------
	// ● 模块级函数
	//-------------------------------------------------------------------------
	void init();
	void terminate();
	void ensure_no_error(PaError err);
	pa_callback(callback);
	void stop();
	void stop_waves();
	void play_triangle(float freq);
	void get_next_triangle_value(struct triangle_data* data);
	void play_sine(float freq);
	void get_next_sine_value(struct sine_data* data);
	void compact_active_sounds_array();
	void play_sound(const char* filename, bool loop);
	void decode_vorbis(struct active_sound* sound);
	void decode_vorbis_thread(struct active_sound* sound);
}
#endif
<|endoftext|>


<commit_before>#ifndef __AMUSE_COMMON_HPP__
#define __AMUSE_COMMON_HPP__

#include <algorithm>
#include <limits>
#include <stdio.h>
#include <stdint.h>
#include <stdarg.h>
#include <string>
#include <cstring>

#ifndef _WIN32
#include <strings.h>
#include <sys/stat.h>
#include <unistd.h>
#else
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN 1
#endif
#ifndef NOMINMAX
#define NOMINMAX
#endif
#include <Windows.h>
#endif

constexpr float NativeSampleRate = 32000.0f;

namespace amuse
{

#ifndef PRISize
#ifdef _MSC_VER
#define PRISize "Iu"
#else
#define PRISize "zu"
#endif
#endif

#ifdef _WIN32
using SystemString = std::wstring;
using SystemChar = wchar_t;
#ifndef _S
#define _S(val) L##val
#endif
typedef struct _stat Sstat;
static inline int Mkdir(const wchar_t* path, int) { return _wmkdir(path); }
static inline int Stat(const wchar_t* path, Sstat* statout) { return _wstat(path, statout); }
#else
using SystemString = std::string;
using SystemChar = char;
#ifndef _S
#define _S(val) val
#endif
typedef struct stat Sstat;
static inline int Mkdir(const char* path, mode_t mode) { return mkdir(path, mode); }
static inline int Stat(const char* path, Sstat* statout) { return stat(path, statout); }
#endif

#if _WIN32
static inline int CompareCaseInsensitive(const char* a, const char* b) { return _stricmp(a, b); }
#endif

static inline int CompareCaseInsensitive(const SystemChar* a, const SystemChar* b)
{
#if _WIN32
    return _wcsicmp(a, b);
#else
    return strcasecmp(a, b);
#endif
}

template <typename T>
static inline T clamp(T a, T val, T b)
{
    return std::max<T>(a, std::min<T>(b, val));
}

template <typename T>
inline T ClampFull(float in)
{
    if(std::is_floating_point<T>())
    {
        return std::min<T>(std::max<T>(in, -1.0), 1.0);
    }
    else
    {
        constexpr T MAX = std::numeric_limits<T>::max();
        constexpr T MIN = std::numeric_limits<T>::min();

        if(in < MIN)
            return MIN;
        else if(in > MAX)
            return MAX;
        else
            return in;
    }
}

#ifndef M_PIF
#define M_PIF 3.14159265358979323846f /* pi */
#endif

#if __GNUC__
__attribute__((__format__(__printf__, 1, 2)))
#endif
static inline void
Printf(const SystemChar* fmt, ...)
{
    va_list args;
    va_start(args, fmt);
#if _WIN32
    vwprintf(fmt, args);
#else
    vprintf(fmt, args);
#endif
    va_end(args);
}

#if __GNUC__
__attribute__((__format__(__printf__, 3, 4)))
#endif
static inline void
SNPrintf(SystemChar* str, size_t maxlen, const SystemChar* format, ...)
{
    va_list va;
    va_start(va, format);
#if _WIN32
    _vsnwprintf(str, maxlen, format, va);
#else
    vsnprintf(str, maxlen, format, va);
#endif
    va_end(va);
}

static inline const SystemChar* StrRChr(const SystemChar* str, SystemChar ch)
{
#if _WIN32
    return wcsrchr(str, ch);
#else
    return strrchr(str, ch);
#endif
}

static inline SystemChar* StrRChr(SystemChar* str, SystemChar ch)
{
#if _WIN32
    return wcsrchr(str, ch);
#else
    return strrchr(str, ch);
#endif
}

static inline int FSeek(FILE* fp, int64_t offset, int whence)
{
#if _WIN32
    return _fseeki64(fp, offset, whence);
#elif __APPLE__ || __FreeBSD__
    return fseeko(fp, offset, whence);
#else
    return fseeko64(fp, offset, whence);
#endif
}

static inline int64_t FTell(FILE* fp)
{
#if _WIN32
    return _ftelli64(fp);
#elif __APPLE__ || __FreeBSD__
    return ftello(fp);
#else
    return ftello64(fp);
#endif
}

static inline FILE* FOpen(const SystemChar* path, const SystemChar* mode)
{
#if _WIN32
    FILE* fp = _wfopen(path, mode);
    if (!fp)
        return nullptr;
#else
    FILE* fp = fopen(path, mode);
    if (!fp)
        return nullptr;
#endif
    return fp;
}

static inline void Unlink(const SystemChar* file)
{
#if _WIN32
    _wunlink(file);
#else
    unlink(file);
#endif
}

#undef bswap16
#undef bswap32
#undef bswap64

/* Type-sensitive byte swappers */
template <typename T>
static inline T bswap16(T val)
{
#if __GNUC__
    return __builtin_bswap16(val);
#elif _WIN32
    return _byteswap_ushort(val);
#else
    return (val = (val << 8) | ((val >> 8) & 0xFF));
#endif
}

template <typename T>
static inline T bswap32(T val)
{
#if __GNUC__
    return __builtin_bswap32(val);
#elif _WIN32
    return _byteswap_ulong(val);
#else
    val = (val & 0x0000FFFF) << 16 | (val & 0xFFFF0000) >> 16;
    val = (val & 0x00FF00FF) << 8 | (val & 0xFF00FF00) >> 8;
    return val;
#endif
}

template <typename T>
static inline T bswap64(T val)
{
#if __GNUC__
    return __builtin_bswap64(val);
#elif _WIN32
    return _byteswap_uint64(val);
#else
    return ((val & 0xFF00000000000000ULL) >> 56) | ((val & 0x00FF000000000000ULL) >> 40) |
           ((val & 0x0000FF0000000000ULL) >> 24) | ((val & 0x000000FF00000000ULL) >> 8) |
           ((val & 0x00000000FF000000ULL) << 8) | ((val & 0x0000000000FF0000ULL) << 24) |
           ((val & 0x000000000000FF00ULL) << 40) | ((val & 0x00000000000000FFULL) << 56);
#endif
}

#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
static inline int16_t SBig(int16_t val) { return bswap16(val); }
static inline uint16_t SBig(uint16_t val) { return bswap16(val); }
static inline int32_t SBig(int32_t val) { return bswap32(val); }
static inline uint32_t SBig(uint32_t val) { return bswap32(val); }
static inline int64_t SBig(int64_t val) { return bswap64(val); }
static inline uint64_t SBig(uint64_t val) { return bswap64(val); }
static inline float SBig(float val)
{
    int32_t ival = bswap32(*((int32_t*)(&val)));
    return *((float*)(&ival));
}
static inline double SBig(double val)
{
    int64_t ival = bswap64(*((int64_t*)(&val)));
    return *((double*)(&ival));
}
#ifndef SBIG
#define SBIG(q) (((q)&0x000000FF) << 24 | ((q)&0x0000FF00) << 8 | ((q)&0x00FF0000) >> 8 | ((q)&0xFF000000) >> 24)
#endif

static inline int16_t SLittle(int16_t val) { return val; }
static inline uint16_t SLittle(uint16_t val) { return val; }
static inline int32_t SLittle(int32_t val) { return val; }
static inline uint32_t SLittle(uint32_t val) { return val; }
static inline int64_t SLittle(int64_t val) { return val; }
static inline uint64_t SLittle(uint64_t val) { return val; }
static inline float SLittle(float val) { return val; }
static inline double SLittle(double val) { return val; }
#ifndef SLITTLE
#define SLITTLE(q) (q)
#endif
#else
static inline int16_t SLittle(int16_t val) { return bswap16(val); }
static inline uint16_t SLittle(uint16_t val) { return bswap16(val); }
static inline int32_t SLittle(int32_t val) { return bswap32(val); }
static inline uint32_t SLittle(uint32_t val) { return bswap32(val); }
static inline int64_t SLittle(int64_t val) { return bswap64(val); }
static inline uint64_t SLittle(uint64_t val) { return bswap64(val); }
static inline float SLittle(float val)
{
    int32_t ival = bswap32(*((int32_t*)(&val)));
    return *((float*)(&ival));
}
static inline double SLittle(double val)
{
    int64_t ival = bswap64(*((int64_t*)(&val)));
    return *((double*)(&ival));
}
#ifndef SLITTLE
#define SLITTLE(q) (((q)&0x000000FF) << 24 | ((q)&0x0000FF00) << 8 | ((q)&0x00FF0000) >> 8 | ((q)&0xFF000000) >> 24)
#endif

static inline int16_t SBig(int16_t val) { return val; }
static inline uint16_t SBig(uint16_t val) { return val; }
static inline int32_t SBig(int32_t val) { return val; }
static inline uint32_t SBig(uint32_t val) { return val; }
static inline int64_t SBig(int64_t val) { return val; }
static inline uint64_t SBig(uint64_t val) { return val; }
static inline float SBig(float val) { return val; }
static inline double SBig(double val) { return val; }
#ifndef SBIG
#define SBIG(q) (q)
#endif
#endif

/** Versioned data format to interpret */
enum class DataFormat
{
    GCN,
    N64,
    PC
};

/** Meta-type for selecting GameCube (MusyX 2.0) data formats */
struct GCNDataTag
{
};

/** Meta-type for selecting N64 (MusyX 1.0) data formats */
struct N64DataTag
{
};

/** Meta-type for selecting PC (MusyX 1.0) data formats */
struct PCDataTag
{
};
}

#endif // __AMUSE_COMMON_HPP__
<commit_msg>Win32 macro undef<commit_after>#ifndef __AMUSE_COMMON_HPP__
#define __AMUSE_COMMON_HPP__

#include <algorithm>
#include <limits>
#include <stdio.h>
#include <stdint.h>
#include <stdarg.h>
#include <string>
#include <cstring>

#ifndef _WIN32
#include <strings.h>
#include <sys/stat.h>
#include <unistd.h>
#else
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN 1
#endif
#include <Windows.h>
#endif

#undef min
#undef max

constexpr float NativeSampleRate = 32000.0f;

namespace amuse
{

#ifndef PRISize
#ifdef _MSC_VER
#define PRISize "Iu"
#else
#define PRISize "zu"
#endif
#endif

#ifdef _WIN32
using SystemString = std::wstring;
using SystemChar = wchar_t;
#ifndef _S
#define _S(val) L##val
#endif
typedef struct _stat Sstat;
static inline int Mkdir(const wchar_t* path, int) { return _wmkdir(path); }
static inline int Stat(const wchar_t* path, Sstat* statout) { return _wstat(path, statout); }
#else
using SystemString = std::string;
using SystemChar = char;
#ifndef _S
#define _S(val) val
#endif
typedef struct stat Sstat;
static inline int Mkdir(const char* path, mode_t mode) { return mkdir(path, mode); }
static inline int Stat(const char* path, Sstat* statout) { return stat(path, statout); }
#endif

#if _WIN32
static inline int CompareCaseInsensitive(const char* a, const char* b) { return _stricmp(a, b); }
#endif

static inline int CompareCaseInsensitive(const SystemChar* a, const SystemChar* b)
{
#if _WIN32
    return _wcsicmp(a, b);
#else
    return strcasecmp(a, b);
#endif
}

template <typename T>
static inline T clamp(T a, T val, T b)
{
    return std::max<T>(a, std::min<T>(b, val));
}

template <typename T>
inline T ClampFull(float in)
{
    if(std::is_floating_point<T>())
    {
        return std::min<T>(std::max<T>(in, -1.0), 1.0);
    }
    else
    {
        constexpr T MAX = std::numeric_limits<T>::max();
        constexpr T MIN = std::numeric_limits<T>::min();

        if(in < MIN)
            return MIN;
        else if(in > MAX)
            return MAX;
        else
            return in;
    }
}

#ifndef M_PIF
#define M_PIF 3.14159265358979323846f /* pi */
#endif

#if __GNUC__
__attribute__((__format__(__printf__, 1, 2)))
#endif
static inline void
Printf(const SystemChar* fmt, ...)
{
    va_list args;
    va_start(args, fmt);
#if _WIN32
    vwprintf(fmt, args);
#else
    vprintf(fmt, args);
#endif
    va_end(args);
}

#if __GNUC__
__attribute__((__format__(__printf__, 3, 4)))
#endif
static inline void
SNPrintf(SystemChar* str, size_t maxlen, const SystemChar* format, ...)
{
    va_list va;
    va_start(va, format);
#if _WIN32
    _vsnwprintf(str, maxlen, format, va);
#else
    vsnprintf(str, maxlen, format, va);
#endif
    va_end(va);
}

static inline const SystemChar* StrRChr(const SystemChar* str, SystemChar ch)
{
#if _WIN32
    return wcsrchr(str, ch);
#else
    return strrchr(str, ch);
#endif
}

static inline SystemChar* StrRChr(SystemChar* str, SystemChar ch)
{
#if _WIN32
    return wcsrchr(str, ch);
#else
    return strrchr(str, ch);
#endif
}

static inline int FSeek(FILE* fp, int64_t offset, int whence)
{
#if _WIN32
    return _fseeki64(fp, offset, whence);
#elif __APPLE__ || __FreeBSD__
    return fseeko(fp, offset, whence);
#else
    return fseeko64(fp, offset, whence);
#endif
}

static inline int64_t FTell(FILE* fp)
{
#if _WIN32
    return _ftelli64(fp);
#elif __APPLE__ || __FreeBSD__
    return ftello(fp);
#else
    return ftello64(fp);
#endif
}

static inline FILE* FOpen(const SystemChar* path, const SystemChar* mode)
{
#if _WIN32
    FILE* fp = _wfopen(path, mode);
    if (!fp)
        return nullptr;
#else
    FILE* fp = fopen(path, mode);
    if (!fp)
        return nullptr;
#endif
    return fp;
}

static inline void Unlink(const SystemChar* file)
{
#if _WIN32
    _wunlink(file);
#else
    unlink(file);
#endif
}

#undef bswap16
#undef bswap32
#undef bswap64

/* Type-sensitive byte swappers */
template <typename T>
static inline T bswap16(T val)
{
#if __GNUC__
    return __builtin_bswap16(val);
#elif _WIN32
    return _byteswap_ushort(val);
#else
    return (val = (val << 8) | ((val >> 8) & 0xFF));
#endif
}

template <typename T>
static inline T bswap32(T val)
{
#if __GNUC__
    return __builtin_bswap32(val);
#elif _WIN32
    return _byteswap_ulong(val);
#else
    val = (val & 0x0000FFFF) << 16 | (val & 0xFFFF0000) >> 16;
    val = (val & 0x00FF00FF) << 8 | (val & 0xFF00FF00) >> 8;
    return val;
#endif
}

template <typename T>
static inline T bswap64(T val)
{
#if __GNUC__
    return __builtin_bswap64(val);
#elif _WIN32
    return _byteswap_uint64(val);
#else
    return ((val & 0xFF00000000000000ULL) >> 56) | ((val & 0x00FF000000000000ULL) >> 40) |
           ((val & 0x0000FF0000000000ULL) >> 24) | ((val & 0x000000FF00000000ULL) >> 8) |
           ((val & 0x00000000FF000000ULL) << 8) | ((val & 0x0000000000FF0000ULL) << 24) |
           ((val & 0x000000000000FF00ULL) << 40) | ((val & 0x00000000000000FFULL) << 56);
#endif
}

#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
static inline int16_t SBig(int16_t val) { return bswap16(val); }
static inline uint16_t SBig(uint16_t val) { return bswap16(val); }
static inline int32_t SBig(int32_t val) { return bswap32(val); }
static inline uint32_t SBig(uint32_t val) { return bswap32(val); }
static inline int64_t SBig(int64_t val) { return bswap64(val); }
static inline uint64_t SBig(uint64_t val) { return bswap64(val); }
static inline float SBig(float val)
{
    int32_t ival = bswap32(*((int32_t*)(&val)));
    return *((float*)(&ival));
}
static inline double SBig(double val)
{
    int64_t ival = bswap64(*((int64_t*)(&val)));
    return *((double*)(&ival));
}
#ifndef SBIG
#define SBIG(q) (((q)&0x000000FF) << 24 | ((q)&0x0000FF00) << 8 | ((q)&0x00FF0000) >> 8 | ((q)&0xFF000000) >> 24)
#endif

static inline int16_t SLittle(int16_t val) { return val; }
static inline uint16_t SLittle(uint16_t val) { return val; }
static inline int32_t SLittle(int32_t val) { return val; }
static inline uint32_t SLittle(uint32_t val) { return val; }
static inline int64_t SLittle(int64_t val) { return val; }
static inline uint64_t SLittle(uint64_t val) { return val; }
static inline float SLittle(float val) { return val; }
static inline double SLittle(double val) { return val; }
#ifndef SLITTLE
#define SLITTLE(q) (q)
#endif
#else
static inline int16_t SLittle(int16_t val) { return bswap16(val); }
static inline uint16_t SLittle(uint16_t val) { return bswap16(val); }
static inline int32_t SLittle(int32_t val) { return bswap32(val); }
static inline uint32_t SLittle(uint32_t val) { return bswap32(val); }
static inline int64_t SLittle(int64_t val) { return bswap64(val); }
static inline uint64_t SLittle(uint64_t val) { return bswap64(val); }
static inline float SLittle(float val)
{
    int32_t ival = bswap32(*((int32_t*)(&val)));
    return *((float*)(&ival));
}
static inline double SLittle(double val)
{
    int64_t ival = bswap64(*((int64_t*)(&val)));
    return *((double*)(&ival));
}
#ifndef SLITTLE
#define SLITTLE(q) (((q)&0x000000FF) << 24 | ((q)&0x0000FF00) << 8 | ((q)&0x00FF0000) >> 8 | ((q)&0xFF000000) >> 24)
#endif

static inline int16_t SBig(int16_t val) { return val; }
static inline uint16_t SBig(uint16_t val) { return val; }
static inline int32_t SBig(int32_t val) { return val; }
static inline uint32_t SBig(uint32_t val) { return val; }
static inline int64_t SBig(int64_t val) { return val; }
static inline uint64_t SBig(uint64_t val) { return val; }
static inline float SBig(float val) { return val; }
static inline double SBig(double val) { return val; }
#ifndef SBIG
#define SBIG(q) (q)
#endif
#endif

/** Versioned data format to interpret */
enum class DataFormat
{
    GCN,
    N64,
    PC
};

/** Meta-type for selecting GameCube (MusyX 2.0) data formats */
struct GCNDataTag
{
};

/** Meta-type for selecting N64 (MusyX 1.0) data formats */
struct N64DataTag
{
};

/** Meta-type for selecting PC (MusyX 1.0) data formats */
struct PCDataTag
{
};
}

#endif // __AMUSE_COMMON_HPP__
<|endoftext|>


<commit_before>#include "PicFileReader.h"
#include <itkImageFileReader.h>

//##ModelId=3E1878400265
void mitk::PicFileReader::GenerateOutputInformation()
{
	mitk::Image::Pointer output = this->GetOutput();

	if ((output->IsInitialized()) && (this->GetMTime() <= m_ReadHeaderTime.GetMTime()))
		return;

	itkDebugMacro(<<"Reading file for GenerateOutputInformation()" << m_FileName);

	// Check to see if we can read the file given the name or prefix
	//
	if ( m_FileName == "" && m_FilePrefix == "" )
	{
		throw itk::ImageFileReaderException(__FILE__, __LINE__, "One of FileName or FilePrefix must be non-empty");
	}

	ipPicDescriptor* header=ipPicGetHeader(const_cast<char *>(m_FileName.c_str()), NULL);

	if( header == NULL)
	{
		itk::ImageFileReaderException e(__FILE__, __LINE__);
		itk::OStringStream msg;
		msg << " Could not read file "
			<< m_FileName.c_str();
		e.SetDescription(msg.str().c_str());
		throw e;
		return;
	}

	output->Initialize(header);

	m_ReadHeaderTime.Modified();
}

//##ModelId=3E187255016C
void mitk::PicFileReader::GenerateData()
{
	mitk::Image::Pointer output = this->GetOutput();

	char * c=const_cast<char *>(m_FileName.c_str());
	ipPicDescriptor* pic=ipPicGet(const_cast<char *>(m_FileName.c_str()), NULL);

	output->SetPicVolume(pic);
}

//##ModelId=3E1874D202D0
mitk::PicFileReader::PicFileReader()
{
}

//##ModelId=3E1874E50179
mitk::PicFileReader::~PicFileReader()
{
}
<commit_msg>ipPicGetHeader does not read tags => tags must be explicitly read.<commit_after>#include "PicFileReader.h"
#include <itkImageFileReader.h>

//##ModelId=3E1878400265
void mitk::PicFileReader::GenerateOutputInformation()
{
	mitk::Image::Pointer output = this->GetOutput();

	if ((output->IsInitialized()) && (this->GetMTime() <= m_ReadHeaderTime.GetMTime()))
		return;

	itkDebugMacro(<<"Reading file for GenerateOutputInformation()" << m_FileName);

	// Check to see if we can read the file given the name or prefix
	//
	if ( m_FileName == "" && m_FilePrefix == "" )
	{
		throw itk::ImageFileReaderException(__FILE__, __LINE__, "One of FileName or FilePrefix must be non-empty");
	}

	ipPicDescriptor* header=ipPicGetHeader(const_cast<char *>(m_FileName.c_str()), NULL);

    header=ipPicGetTags(const_cast<char *>(m_FileName.c_str()), header);

	if( header == NULL)
	{
		itk::ImageFileReaderException e(__FILE__, __LINE__);
		itk::OStringStream msg;
		msg << " Could not read file "
			<< m_FileName.c_str();
		e.SetDescription(msg.str().c_str());
		throw e;
		return;
	}

	output->Initialize(header);

	m_ReadHeaderTime.Modified();
}

//##ModelId=3E187255016C
void mitk::PicFileReader::GenerateData()
{
	mitk::Image::Pointer output = this->GetOutput();

	char * c=const_cast<char *>(m_FileName.c_str());
	ipPicDescriptor* pic=ipPicGet(const_cast<char *>(m_FileName.c_str()), NULL);

	output->SetPicVolume(pic);
}

//##ModelId=3E1874D202D0
mitk::PicFileReader::PicFileReader()
{
}

//##ModelId=3E1874E50179
mitk::PicFileReader::~PicFileReader()
{
}
<|endoftext|>