火曜日, 6月 21, 2016

Arduino ISP: ATTiny13A でサイコロを回す



ATtiny13A でサイコロを回そうと思えば rand() 関数が大きいようです。ここは自分で組まねばなりません。

乱数といえば線形合同法だと思えば、Xorshift なる計算方法が流行ってるんですねえ。

高速かつ長周期、じゃあということで Xorshift へ乗り換えて作ってみました。

マシンで合成する疑似乱数ってのは「疑似」乱数なのであってパターンが決まっています。ある一定の周期を持つわけです。長ければ長いほどいい乱数です。あとは出てくる値が均一でないとなりません。

メルセンヌ・ツイスタをすすめる向きもあるようですが、ここでは Xorshift で。

あとシードが必要なんですが、タイマーを使ったりメモリを読んだり、空ピンの値を読んだりするのがベスト・プラクティスなようです。ここではスイッチでの割り込み時のカウンタの値を使ってみました。

/*
* Dice.cpp
*
* Created: 2016-06-21
* Author : easai
*/
#include <avr/io.h>
#include <avr/interrupt.h>
int digit[6] = {
0b10000,
0b01000,
0b11000,
0b01100,
0b11100,
0b01101
};
volatile unsigned long r;
volatile unsigned long timer_counter=0;
int interval=1000;
volatile unsigned int counter=0;
ISR(TIM0_OVF_vect)
{
timer_counter++;
if((timer_counter%interval)==0)
{
if(counter < 50)
{
// Xorshift
r = r ^ (r << 13);
r = r ^ (r >> 17);
r = r ^ (r << 5);
// LCG
// r=(r*109+89)%251;
PORTB = digit[r%6];
counter++;
}
else if(counter < 100)
{
PORTB = digit[r%6];
counter++;
}
else
{
PORTB = 0;
}
}
}
ISR(INT0_vect)
{
cli();
counter=0;
r=timer_counter;
sei();
}
int main(void)
{
DDRB |= 0b11101;
PORTB = 0;
TCCR0A=0;
TCCR0B=(1<<CS00);
TIMSK0|=(1<<TOIE0);
MCUCR |= (1<<ISC01);
GIMSK |= (1<<INT0);
sei();
timer_counter=0;
counter=100;
while (1) {}
}
view raw Dice.cpp hosted with ❤ by GitHub

Qt: 外部プログラムを起動する

  Qt/C++ のアプリは、外部へ直接アクセスできます。これはネットアプリでは不可能な Qt のメリットです。 外部プログラムを起動することもできます。QProcess::startDetached() を使うと独立したプロセスを立ち上げることができます。 この QProces...