V850のタイマー割り込み

組み込み勉強中です!下記のプログラムに間違いがあればアドバイス願います!
INTTP0CC0は、1msのタイマー割り込み要求でいいのかな?
どこかでインターバルの設定をするのかな?

volatileは、レジスタを参照する変数や割り込みハンドラ(interrupt handler)と通常の関数(normal function)で共有される変数(下記の例では、counter_10msやcounter_20ms)などを修飾するために用いられ、コンパイル時に最適化を抑止するそうです。

timer_interrupt.h

#ifndef TIMER_INTERRUPT_H
#define TIMER_INTERRUPT_H

//extern volatile unsigned int counter_10ms;
//extern volatile unsigned int counter_20ms;
extern void function_10ms(void);
extern void function_20ms(void);

#endif

timer_interrupt.c

/* V850 */

static volatile unsigned int counter_10ms;
static volatile unsigned int counter_20ms;

//1msのタイマー割り込み要求(INTTP0CC0)で割り込みハンドラ(handler_1ms)を呼び出す設定
#pragma interrupt INTTP0CC0 handler_1ms

//1ms毎に呼び出される割り込みハンドラ
__interrupt void handler_1ms(void) {
  counter_10ms++;
  counter_20ms++;
}

//10ms毎に実行される通常の関数
void function_10ms(void) {
  if (counter_10ms >= 10) {
    //procedure_10ms();
    counter_10ms = 0;
  }
}

//20ms毎に実行される通常の関数
void function_20ms(void) {
  if (counter_20ms >= 20) {
    //procedure_20ms();
    counter_20ms = 0;
  }
}

main.c

#include "timer_interrupt.h"

void main(void) {
  for (;;) {
    function_10ms();
    function_20ms();
  }
}


参考サイト

1.V850 ファミリ
2.タイマ機能を使ったプログラミング
3.V850ES/Jx3 サンプルプログラム(割り込み)
4.V850 割り込みサンプルプログラム
5.V850 サンプルプログラム1
6.V850 サンプルプログラム2
7.Google:V850 割り込み

Bitwise Operator and Logical Operator

・Bitwise AND Operator & と Logical AND Operator &&

C/C++の論理演算(logical operation)では、0は偽(false)、0以外は真(true)です!

and.c

#include <math.h>
#include <stdio.h>

int main(void) {
  printf("%d\n", 0&1);
  printf("%d\n", 2&3);
  printf("%d\n", 0&&1);
  printf("%d\n", 2&&3);
  printf("%d\n", 'a'&&"abc");

  int i = 3;
  int n = 7;
  if ((int)pow(2, i - 1) & n) {
    printf("The %d-th bit in the binary representation of the decimal number %d is 1!\n", i, n);
  }
  else {
    printf("The %d-th bit in the binary representation of the decimal number %d is 0!\n", i, n);
  }
}

〈実行結果〉

0
2
0
1
1
The 3-th bit in the binary representation of the decimal number 7 is 1!


参考サイト

1.Google:Bitwise Operator and Logical Operator
2.2進数、8進数、10進数、16進数相互変換ツール

C/C++における条件コンパイル

条件コンパイル(conditional compilation)のやり方です。日本語では、コンパイラスウィッチとかコンパイルスウィッチと呼ばれることがあります。

conditional_compilation1.c

#include <stdio.h>
#define DEBUG 1

int main(void) {
#if DEBUG
  printf("Debug Mode!\n");
#endif
}

conditional_compilation2.c

#include <stdio.h>
#define DEBUG

int main(void) {
#ifdef DEBUG
  printf("Debug Mode!\n");
#endif
}


参考サイト

1.#ifディレクティブを使った条件コンパイル
2.#ifdefディレクティブを使った条件コンパイル

FLTK による GUI アプリケーションの開発(Windows)

FLTK は軽量クロスプラットフォームのGUIライブラリです。ライブラリが静的にリンクされるので FLTK がインストールされていない Windows PC でも実行できます。その上、生成される実行ファイルのサイズが小さいので容易に配布できます。また、プログラムを比較的簡単に作成できるのもメリットの一つです。
ということで、私はとても気に入っています!
以下では、Windows環境での FLTK による GUI アプリケーションの作成手順について説明します。


1.MinGW と MSYS のインストール

FLTK をビルドするために、MinGW をDドライブの直下にインストールします。インストールの際に MinGW Installation Manager で mingw32-gcc-g++msys-base を指定すると MSYS も一緒にインストールできます。MinGW のインストールについては、“clang++ による DLL のビルド” の記事の MinGW の箇所を参考にして下さい。
インストールが終わったら、D:\MinGW\msys\1.0\msys.bat をダブルクリックして MSYS を起動し、下記のコマンドを実行するとパスを設定できます。
注)exit で一旦終了して MSYS を再起動した後にパスが有効になるので、exit するのを忘れないで下さい。

<MSYS>

$ echo "PATH=\$PATH:/D/MinGW/bin" > .profile
$ exit


2.FLTK のビルドとインストール

まず、FLTK のソールファイル fltk-1.3.3-source.tar.gz をダウンロードし、
“D:\MinGW\msys\1.0\home\ユーザ名”の直下に置きます。
続いて、D:\MinGW\msys\1.0\msys.bat をダブルクリックして MSYS を起動し、ソースファイルのあるディレクトリで以下のコマンドを実行すれば、解凍 → ビルド → インストール が行えます。

<MSYS>

$ tar -xvf fltk-1.3.3-source.tar.gz
$ cd fltk-1.3.3
$ ./configure
$ make
$ make install


3.C++によるプログラムの作成

以下は、FLTK を使ったサンプルプログラムです。

fltk1.cpp

#include <FL/Fl.H>
#include <FL/Fl_Button.H>
#include <FL/Fl_Input.H>
#include <FL/Fl_Output.H>
#include <FL/Fl_Window.H>

auto copy(Fl_Widget* widget, void* v) -> void {
  const char* input = ((Fl_Input*)((void**)v)[0])->value();
  ((Fl_Output*)((void**)v)[1])->value(input);
}

auto main() -> int {
  Fl_Window* window = new Fl_Window(500, 200, "^o^");
  window->begin();
  Fl_Button* button = new Fl_Button(0, 0, 50, 25, "copy");
  Fl_Input* input = new Fl_Input(50, 50, 250, 25, "input:");
  Fl_Output* output = new Fl_Output(50, 100, 250, 25, "output:");
  window->end();
  void* v[] = {input, output};
  button->callback(copy, v);
  window->show();
  return Fl::run();
}

fltk2.cpp

#include <FL/Fl.H>
#include <FL/Fl_Button.H>
#include <FL/Fl_Input.H>
#include <FL/Fl_Output.H>
#include <FL/Fl_Window.H>

auto copy(Fl_Widget* widget, void* v) -> void {
  const char* input = ((Fl_Input*)(widget->parent()->child(1)))->value();
  ((Fl_Output*)(widget->parent()->child(2)))->value(input);
}

auto main() -> int {
  Fl_Window* window = new Fl_Window(500, 200, "^o^");
  window->begin();
  Fl_Button* button = new Fl_Button(0, 0, 50, 25, "copy");
  Fl_Input* input = new Fl_Input(50, 50, 250, 25, "input:");
  Fl_Output* output = new Fl_Output(50, 100, 250, 25, "output:");
  window->end();
  button->callback(copy);
  window->show();
  return Fl::run();
}

fltk3.cpp

#include <FL/Fl.H>
#include <FL/Fl_Button.H>
#include <FL/Fl_Input.H>
#include <FL/Fl_Output.H>
#include <FL/Fl_Window.H>

class CopyWindow : Fl_Window {
  Fl_Button* button;
  Fl_Input* input;
  Fl_Output* output;
public:
  CopyWindow(int, int, const char*);
private:
  static auto copy(Fl_Widget*, void*) -> void;
};

CopyWindow::CopyWindow(int width, int height, const char* title) : Fl_Window(width, height, title) {
  begin();
  button = new Fl_Button(0, 0, 50, 25, "copy");
  input = new Fl_Input(50, 50, 250, 25, "input:");
  output = new Fl_Output(50, 100, 250, 25, "output:");
  end();
  button->callback(copy, this);
  show();
}

auto CopyWindow::copy(Fl_Widget* widget, void* v) -> void {
  ((CopyWindow*)v)->output->value(((CopyWindow*)v)->input->value());
}

auto main() -> int {
  CopyWindow copyWindow(500, 200, "^o^");
  return Fl::run();
}

drag and drop.cpp

#include <fstream>
#include <iostream>
#include <sstream>
#include <vector>
#include <FL/Fl.H>
#include <FL/Fl_Box.H>
#include <FL/Fl_Window.H>

auto split(const std::string& input, char delimiter) -> std::vector<std::string> {
  std::istringstream istringstream(input);
  std::string buffer;
  std::vector<std::string> output;
  while (std::getline(istringstream, buffer, delimiter)) {
    output.push_back(buffer);
  }
  return output;
}

class EventBox : Fl_Box {
public:
  EventBox(int x, int y, int width, int height);
private:
  auto handle(int event) -> int;
};

EventBox::EventBox(int x, int y, int width, int height) : Fl_Box(FL_UP_BOX, x, y, width, height, "") {
  label("Hello!");
  labelcolor(FL_BLUE);
  labelfont(FL_ITALIC);
  labelsize(50);
}

auto EventBox::handle(int event) -> int {
  std::ofstream ofstream;
  switch (event) {
    case FL_DND_DRAG:
    case FL_DND_ENTER:
    case FL_DND_RELEASE:
      return 1;
    case FL_PASTE:
      label("Goodbye!");
      labelcolor(FL_RED);
      ofstream.open("fout.txt");
      ofstream << split(Fl::event_text(), '\n')[0];
      ofstream << std::flush;
      ofstream.close();
      return 1;
    default:
      return Fl_Box::handle(event);
  }
}

auto main() -> int {
  Fl_Window window(250, 100, "^o^");
  EventBox eventBox(0, 0, 250, 100);
  window.show();
  return Fl::run();
}


4.プログラムのビルド

MSYSで以下のコマンドを実行するとプログラムをビルドできます。
注)-static を外すと、実行する際に libstdc++-6.dll と libgcc_s_dw2-1.dll が必要になります。

<MSYS>

$ g++ -std=c++11 -static `fltk-config --cxxflags` fltk.cpp `fltk-config --ldflags` -o fltk.exe
$ strip fltk.exe


参考サイト

1.FLTK
2.FLTKとは
3.Beginner FLTK Tutorial
4.Compile FLTK with g++
5.Erco’s FLTK Cheat Page
6.3-Common Widgets and Attributes
7.C++ FLTK BUTTONS TUTORIAL
8.Simple Inherited Window
9.Complex FLTK Window
10.FLTK で GUI を使ってみる
11.C/C++のGUIライブラリ比較
12.MinGW+MSYSのインストール
13.MinGW (64bit) + MSYS 環境の構築(1)
14.tarのオプションをまとめる
15.FOX toolkit のメモ

C++におけるクラス内配列

クラス内配列を添字演算子[](index operator, subscript operator)のオーバーロードを利用して記述します。


1.クラス内で配列を静的に確保する

C/C++では配列そのものを関数の引数や戻り値にすることはできませんが、以下のArrayクラスではそれが可能です。これを使えば複数の値の値渡しや値戻しができます。関数の引数や戻り値がベクトルである場合に使うと便利です。もちろん、配列長が大きい場合は参照渡しや参照戻しを使うこともできます。

array1.cpp

#include <cassert>
#include <iostream>

template <int LENGTH> class Array {
  double array[LENGTH];
public:
  const int length = LENGTH;
  Array() {
    if (length > 0) {
      for (int i = 0; i < length; i++) {
        array[i] = 0;
      }
    }
  }
  Array& operator=(const Array& object) {
    if (length > 0) {
      for (int i = 0; i < length; i++) {
        array[i] = object.array[i];
      }
    }
    return *this;
  }
  double& operator[](int index) {
    assert(0 <= index && index < length);
    return array[index];
  }
  const double& operator[](int index) const {
    assert(0 <= index && index < length);
    return array[index];
  }
};

Array<10> echo1(Array<10> array) {
  return array;
}

const Array<10>& echo2(const Array<10>& array) {
  return array;
}

int main() {
  const int length = 10;
  //Array<length> array;
  auto array = Array<length>();
  for (int i = 0; i < array.length; i++) {
    array[i] = i;
  }
  auto array1 = Array<length>();
  array1 = array;
  for (int i = 0; i < array1.length; i++) {
    std::cout << array1[i] << std::endl;
  }
  for (int i = 0; i < echo1(array).length; i++) {
    std::cout << echo1(array)[i] << std::endl;
  }
  for (int i = 0; i < echo2(array).length; i++) {
    std::cout << echo2(array)[i] << std::endl;
  }
}

array2.cpp

#include <cassert>
#include <iostream>

template <int LENGTH> class Array {
  double array[LENGTH];
public:
  const int length = LENGTH;
  Array();
  Array& operator=(const Array&);
  double& operator[](int);
  const double& operator[](int) const;
};

template <int LENGTH> Array<LENGTH>::Array() {
  if (length > 0) {
    for (int i = 0; i < length; i++) {
      array[i] = 0;
    }
  }
}

template <int LENGTH> Array<LENGTH>& Array<LENGTH>::operator=(const Array& object) {
  if (length > 0) {
    for (int i = 0; i < length; i++) {
      array[i] = object.array[i];
    }
  }
  return *this;
}

template <int LENGTH> double& Array<LENGTH>::operator[](int index) {
  assert(0 <= index && index < length);
  return array[index];
}

template <int LENGTH> const double& Array<LENGTH>::operator[](int index) const {
  assert(0 <= index && index < length);
  return array[index];
}

Array<10> echo1(Array<10> array) {
  return array;
}

const Array<10>& echo2(const Array<10>& array) {
  return array;
}

int main() {
  const int length = 10;
  //Array<length> array;
  auto array = Array<length>();
  for (int i = 0; i < array.length; i++) {
    array[i] = i;
  }
  auto array1 = Array<length>();
  array1 = array;
  for (int i = 0; i < array1.length; i++) {
    std::cout << array1[i] << std::endl;
  }
  for (int i = 0; i < echo1(array).length; i++) {
    std::cout << echo1(array)[i] << std::endl;
  }
  for (int i = 0; i < echo2(array).length; i++) {
    std::cout << echo2(array)[i] << std::endl;
  }
}


2.クラス内で配列を動的に確保する

スタックに格納できないサイズの配列を扱う際に使うと便利です。また、ディストラクタが自動で動的に確保した配列の後始末をしてくれます。

注)オブジェクトの値渡しでは、値渡しの際にコピーコンストラクタが呼び出され、関数を抜ける時にディストラクタが呼び出されます。

注)メンバ変数にポインタがあるオブジェクトの値渡しでは、関数を抜ける時に呼び出されるディストラクタがコピー元の実体を解放するので、値渡しの際に実体がコピーされるようにコピーコンストラクタを定義しておきます。

array3.cpp

#include <cassert>
#include <iostream>

class Array {
  double* array;
public:
  int length;
  Array(int length) : array(NULL), length(length) {
    if (length > 0) {
      array = new double[length];
      for (int i = 0; i < length; i++) {
        array[i] = 0;
      }
    }
  }
  Array(const Array& object) : array(NULL), length(object.length) {
    if (length > 0) {
      array = new double[length];
      for (int i = 0; i < length; i++) {
        array[i] = object.array[i];
      }
    }
  }
  Array& operator=(const Array& object) {
    array = NULL;
    length = object.length;
    if (length > 0) {
      array = new double[length];
      for (int i = 0; i < length; i++) {
        array[i] = object.array[i];
      }
    }
    return *this;
  }
  ~Array() {
    if (array != NULL) {
      delete[] array;
      array = NULL;
    }
  }
  double& operator[](int index) {
    assert(0 <= index && index < length);
    return array[index];
  }
  const double& operator[](int index) const {
    assert(0 <= index && index < length);
    return array[index];
  }
};

Array echo1(Array array) {
  return array;
}

const Array& echo2(const Array& array) {
  return array;
}

int main() {
  int length = 10;
  //Array array(length);
  auto array = Array(length);
  for (int i = 0; i < array.length; i++) {
    array[i] = i;
  }
  auto array1 = Array(length);
  array1 = array;
  for (int i = 0; i < array1.length; i++) {
    std::cout << array1[i] << std::endl;
  }
  for (int i = 0; i < echo1(array).length; i++) {
    std::cout << echo1(array)[i] << std::endl;
  }
  for (int i = 0; i < echo2(array).length; i++) {
    std::cout << echo2(array)[i] << std::endl;
  }
}

array4.cpp

#include <cassert>
#include <iostream>

class Array {
  double* array;
public:
  int length;
  Array(int);
  Array(const Array&);
  Array& operator=(const Array&);
  ~Array();
  double& operator[](int);
  const double& operator[](int) const;
};

Array::Array(int length) : array(NULL), length(length) {
  if (length > 0) {
    array = new double[length];
    for (int i = 0; i < length; i++) {
      array[i] = 0;
    }
  }
}

Array::Array(const Array& object) : array(NULL), length(object.length) {
  if (length > 0) {
    array = new double[length];
    for (int i = 0; i < length; i++) {
      array[i] = object.array[i];
    }
  }
}

Array& Array::operator=(const Array& object) {
  array = NULL;
  length = object.length;
  if (length > 0) {
    array = new double[length];
    for (int i = 0; i < length; i++) {
      array[i] = object.array[i];
    }
  }
  return *this;
}

Array::~Array() {
  if (array != NULL) {
    delete[] array;
    array = NULL;
  }
}

double& Array::operator[](int index) {
  assert(0 <= index && index < length);
  return array[index];
}

const double& Array::operator[](int index) const {
  assert(0 <= index && index < length);
  return array[index];
}

Array echo1(Array array) {
  return array;
}

const Array& echo2(const Array& array) {
  return array;
}

int main() {
  int length = 10;
  //Array array(length);
  auto array = Array(length);
  for (int i = 0; i < array.length; i++) {
    array[i] = i;
  }
  auto array1 = Array(length);
  array1 = array;
  for (int i = 0; i < array1.length; i++) {
    std::cout << array1[i] << std::endl;
  }
  for (int i = 0; i < echo1(array).length; i++) {
    std::cout << echo1(array)[i] << std::endl;
  }
  for (int i = 0; i < echo2(array).length; i++) {
    std::cout << echo2(array)[i] << std::endl;
  }
}


参考サイト

1.演算子のオーバーロード
2.subscript operator overloading
3.Overloading the C++ indexing subscript operator []
4.Overloading the Subscript Operator [] the Right Way
5.クラス内での配列の動的確保
6.関数とオブジェクト
7.オブジェクト利用時の注意点
8.迷信:new に失敗すると NULL が返る?
9.コピーコンストラクタ、代入演算子、デストラクタ(The Law of The Big Three)
10.コピー操作と参照

C++におけるオブジェクトの値渡し・値戻し

1.オブジェクトの値渡し

関数の引数にオブジェクトを値渡しすると、オブジェクトのコピーの際にコピーコンストラクタが呼び出され、関数を抜ける時にディストラクタが呼び出されます。

passA.cpp

#include <iostream>

class A {
public:
  A() {
    std::cout << "Constructor!" << std::endl;
  }
  A(const A& object) {
    std::cout << "Copy Constructor!" << std::endl;
  }
  ~A() {
    std::cout << "Destructor!" << std::endl;
  }
};

void passA(A a) {
  std::cout << "Pass A!" << std::endl;
}

int main() {
  auto a = A();
  passA(a);
}

〈実行結果〉

Constructor!
Copy Constructor!
Pass A!
Destructor!
Destructor!


2.オブジェクトの値戻し

オブジェクトが値戻しされる時も、最後にディストラクタが呼び出されます。

returnA.cpp

#include <iostream>

class A {
public:
  A() {
    std::cout << "Constructor!" << std::endl;
  }
  A(const A& object) {
    std::cout << "Copy Constructor!" << std::endl;
  }
  ~A() {
    std::cout << "Destructor!" << std::endl;
  }
};

A returnA() {
  std::cout << "Return A!" << std::endl;
  return A();
}

int main() {
  returnA();
}

〈実行結果〉

Return A!
Constructor!
Destructor!


参考サイト

1.C++ クラス設計に関するノート
2.関数とオブジェクト
3.オブジェクト利用時の注意点
4.参照の復習とコピーコンストラクタ
5.コピーコンストラクタ、代入演算子、デストラクタ(The Law of the Big Three)
6.コピー

C++によるテンプレートメタプログラミング

テンプレートメタプログラミング

template1.cpp

#include <iostream>

template <typename T = int> T add(T x, T y) {
  return x + y;
}

int main() {
  std::cout << add<>(1, 1) << std::endl;
  std::cout << add<int>(1, 1) << std::endl;
}

template2.cpp

#include <iostream>

template <typename T = int, int LENGTH = 10> class Array {
  T array[LENGTH];
public:
  const int length = LENGTH;
  T& operator[](int);
  T sum();
};

template <typename T, int LENGTH> T& Array<T, LENGTH>::operator[](int index) {
  return array[index];
}

template <typename T, int LENGTH> T Array<T, LENGTH>::sum() {
  T s = 0;
  for (int i = 0; i < LENGTH; i++) {
    s += array[i];
  }
  return s;
}

int main() {
  //Array<> array;
  const int length = 10;
  //Array<int, length> array;
  auto array = Array<int, length>();
  for (int i = 0; i < array.length; i++) {
    array[i] = i;
    std::cout << array[i] << std::endl;
  }
  std::cout << array.sum() << std::endl;
}


参考サイト

1.Google:C++ template
2.Google:C++ template meta programming
3.C++テンプレートメタプログラミング超入門