ATtiny13A でサイコロを回そうと思えば rand() 関数が大きいようです。ここは自分で組まねばなりません。
乱数といえば線形合同法だと思えば、Xorshift なる計算方法が流行ってるんですねえ。
高速かつ長周期、じゃあということで Xorshift へ乗り換えて作ってみました。
マシンで合成する疑似乱数ってのは「疑似」乱数なのであってパターンが決まっています。ある一定の周期を持つわけです。長ければ長いほどいい乱数です。あとは出てくる値が均一でないとなりません。
メルセンヌ・ツイスタをすすめる向きもあるようですが、ここでは Xorshift で。
あとシードが必要なんですが、タイマーを使ったりメモリを読んだり、空ピンの値を読んだりするのがベスト・プラクティスなようです。ここではスイッチでの割り込み時のカウンタの値を使ってみました。
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* 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) {} | |
} | |