OSDN Git Service

M系列信号による乱数発生器を追加。
[bluetank/bluetank.git] / firm / bare_metal / common / tinyrand.c
1 /**
2  * @file tinyrand.c
3  * @author Shinichiro Nakamura
4  * @brief NTMが使用する乱数生成器の実装。
5  */
6
7 /*
8  * ===============================================================
9  *  Natural Tiny Monitor (NT-Monitor)
10  * ===============================================================
11  * Copyright (c) 2011-2012 Shinichiro Nakamura
12  * Inspired by M, Murakami
13  *
14  * Permission is hereby granted, free of charge, to any person
15  * obtaining a copy of this software and associated documentation
16  * files (the "Software"), to deal in the Software without
17  * restriction, including without limitation the rights to use,
18  * copy, modify, merge, publish, distribute, sublicense, and/or
19  * sell copies of the Software, and to permit persons to whom the
20  * Software is furnished to do so, subject to the following
21  * conditions:
22  *
23  * The above copyright notice and this permission notice shall be
24  * included in all copies or substantial portions of the Software.
25  *
26  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
27  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
28  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
29  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
30  * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
31  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
32  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
33  * OTHER DEALINGS IN THE SOFTWARE.
34  * ===============================================================
35  */
36
37 #include "tinyrand.h"
38
39 /**
40  * @brief ビットポジションを得る。
41  *
42  * @param N ビット。
43  *
44  * @return ビットポジション。
45  */
46 #define BP(N)   (1 << ((N) - 1))
47
48 /**
49  * @brief 乱数生成モジュールを初期化する。
50  * @details
51  * この乱数生成モジュールは24ビットM系列信号によって乱数を生成する。
52  *
53  * @param p 乱数生成用ハンドラ。
54  * @param seed 乱数の種。(0以外の値を指定しなければならない)
55  *
56  * @return 0 成功。
57  * @return !0 失敗。
58  */
59 int tinyrand_init(tinyrand_t *p, const uint32_t seed)
60 {
61     if (seed == 0) {
62         return -1;
63     }
64
65     p->seed = seed;
66     p->reg = seed;
67     return 0;
68 }
69
70 /**
71  * @brief 乱数生成モジュールから1ビットの乱数を取り出す。
72  * @details
73  * この関数が乱数生成モジュールの心臓部分である。
74  * 24ビットM系列信号を発生させるモジュールである。
75  *
76  * @param p 乱数生成用ハンドラ。
77  *
78  * @return 1ビットの乱数。
79  */
80 static int tinyrand_update(tinyrand_t *p)
81 {
82     const uint32_t mask = BP(1) | BP(3) | BP(4);
83     const uint32_t bits = BP(24);
84     if ((p->reg & bits) == bits) {
85         p->reg = ((p->reg ^ mask) << 1) | 1;
86         return 1;
87     } else {
88         p->reg = p->reg << 1;
89         return 0;
90     }
91 }
92
93 /**
94  * @brief 乱数を取り出す。
95  * @details
96  * このインターフェースは、指定したビット幅に収まる値を返す。
97  *
98  * @param p 乱数生成用ハンドラ。
99  * @param nbits 生成する乱数のビット幅。
100  * @param value 値格納先。
101  *
102  * @return 0 成功。
103  * @return !0 失敗。
104  */
105 int tinyrand_pop(tinyrand_t *p, const uint8_t nbits, uint32_t *value)
106 {
107     int i;
108
109     /*
110      * 値を初期化する。
111      */
112     *value = 0;
113
114     /*
115      * 不正なパラメータの場合、何もしない。
116      */
117     if (nbits == 0) {
118         return -1;
119     }
120
121     /*
122      * nbitsの幅を持つ値を生成する。
123      */
124     for (i = 0; i < nbits; i++) {
125         *value |= tinyrand_update(p) ? (1 << i) : 0;
126     }
127     return 0;
128 }
129