diff --git a/Makefile.pseudomodules b/Makefile.pseudomodules index 86aca801eb73ae249b07af49bbc342fd647acc2a..7567b1a78300ceab6231aa6cef4356ed5bfbab7c 100644 --- a/Makefile.pseudomodules +++ b/Makefile.pseudomodules @@ -23,3 +23,6 @@ PSEUDOMODULES += netif # include variants of the AT86RF2xx drivers as pseudo modules PSEUDOMODULES += at86rf23% PSEUDOMODULES += at86rf21% + +# add all pseudo random number generator variants as pseudomodules +PSEUDOMODULES += prng_% diff --git a/sys/include/div.h b/sys/include/div.h index 816f05cb87023bf356e5749ed0cbae73ddf2779a..d55a81ac223b3a6e8787d4db2e8fa71be7f166f7 100644 --- a/sys/include/div.h +++ b/sys/include/div.h @@ -77,6 +77,28 @@ static inline uint32_t div_u32_by_15625div512(uint32_t val) return ((uint64_t)(val) * 0x431bde83ul) >> (12 + 32 - 9); } +/** + * @brief Integer divide val by 44488 + * + * @param[in] val dividend + * @return (val / 44488) + */ +static inline uint32_t div_u32_by_44488(uint32_t val) +{ + return ((uint64_t)val * 0xBC8F1391UL) >> (15 + 32); +} + +/** + * @brief Modulo 44488 + * + * @param[in] val dividend + * @return (val % 44488) + */ +static inline uint32_t div_u32_mod_44488(uint32_t val) +{ + return val - (div_u32_by_44488(val)*44488); +} + #ifdef __cplusplus } #endif diff --git a/sys/random/Makefile b/sys/random/Makefile index 48422e909a47d7cd428d10fa73825060ccc8d8c2..7e79cc14ab81ef8b2302902aaf0043e082555d0d 100644 --- a/sys/random/Makefile +++ b/sys/random/Makefile @@ -1 +1,14 @@ +ifeq (,$(filter prng_%,$(USEMODULE))) + USEMODULE += prng_mersenne +endif +ifneq (,$(filter prng_mersenne,$(USEMODULE))) + SRC += mersenne.c +endif +ifneq (,$(filter prng_minstd,$(USEMODULE))) + SRC += minstd.c +endif +ifneq (,$(filter prng_musl_lcg,$(USEMODULE))) + SRC += musl_lcg.c +endif + include $(RIOTBASE)/Makefile.base diff --git a/sys/random/minstd.c b/sys/random/minstd.c new file mode 100644 index 0000000000000000000000000000000000000000..038b81c4c53627bedb5d148a74a6f9f5e4c0888f --- /dev/null +++ b/sys/random/minstd.c @@ -0,0 +1,73 @@ +/** + * Copyright (C) 2015 Kaspar Schleiser <kaspar@schleiser.de> + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + * + * Code taken from C FAQ (http://c-faq.com/lib/rand.html). + */ + + /** + * @ingroup sys_random + * @{ + * @file + * + * @brief Simple Park & Miller "minimal standard" PRNG + * + * This file contains a simple Park-Miller pseudo random number generator. + * + * While not very random when considering crypto requirements, this is probably + * random enough anywhere where pseudo-randomness is sufficient, e.g., when + * provided with a sensible seed source, for MAC algorithms. + * + * The implementation is taken from the C FAQ, but modified to use magic number + * division and adapted to RIOT's coding conventions.. + * + * @author Kaspar Schleiser <kaspar@schleiser.de> + * @} + */ + +#include <stdint.h> + +#include "div.h" + +#define a 48271 +#define m 2147483647 +#define q (m / a) /* 44488 */ +#define r (m % a) /* 3399 */ + +static uint32_t _seed = 1; + +int rand_minstd(void) +{ + uint32_t hi = div_u32_by_44488(_seed); + uint32_t lo = div_u32_mod_44488(_seed); + uint32_t test = (a * lo) - (r * hi); + + if(test > 0) { + _seed = test; + } + else { + _seed = test + m; + } + + return _seed; +} + +uint32_t genrand_uint32(void) +{ + /* minstd as implemented returns only values from 1 to 2147483647, + * so run it two times to get 32bits */ + uint16_t A = (rand_minstd() >> 15); + uint16_t B = (rand_minstd() >> 15); + return (((uint32_t)A) << 16) | B; +} + +void genrand_init(uint32_t val) +{ + if (!val) { + val = 1; + } + _seed = val; +} diff --git a/sys/random/musl_lcg.c b/sys/random/musl_lcg.c new file mode 100644 index 0000000000000000000000000000000000000000..6e10a21ffb6da004e6295c483846fbd54600a580 --- /dev/null +++ b/sys/random/musl_lcg.c @@ -0,0 +1,45 @@ +/** + * Copyright (C) 2015 Kaspar Schleiser <kaspar@schleiser.de> + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + * + * Code taken from Musl C library. Original copyright notice: + * + * Copyright © 2005-2014 Rich Felker, et al. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include <stdint.h> + +static uint64_t _seed; + +void genrand_init(uint32_t s) +{ + _seed = s-1; +} + +uint32_t genrand_uint32(void) +{ + _seed = 6364136223846793005ULL*_seed + 1; + return _seed>>32; +} diff --git a/sys/shell/commands/Makefile b/sys/shell/commands/Makefile index aa91aeed7c7d4a259882d22d4d2f8ef978f614c5..d9ed78e449cb46d8dfc440abac17de52ec3087e2 100644 --- a/sys/shell/commands/Makefile +++ b/sys/shell/commands/Makefile @@ -21,7 +21,7 @@ ifneq (,$(filter lpc2387,$(USEMODULE))) SRC += sc_heap.c endif ifneq (,$(filter random,$(USEMODULE))) - SRC += sc_mersenne.c + SRC += sc_random.c endif ifeq ($(CPU),x86) SRC += sc_x86_lspci.c diff --git a/sys/shell/commands/sc_mersenne.c b/sys/shell/commands/sc_random.c similarity index 89% rename from sys/shell/commands/sc_mersenne.c rename to sys/shell/commands/sc_random.c index 73c96cba6be64e277dfdf1eb7a889d7cb1c524fb..a15b4421ced74d3ed6b71709757c326bb06c90fa 100644 --- a/sys/shell/commands/sc_mersenne.c +++ b/sys/shell/commands/sc_random.c @@ -12,7 +12,7 @@ * @{ * * @file - * @brief Shell commands for mersenne twister + * @brief Shell commands for random generators * * @author Christian Mehlis <mehlis@inf.fu-berlin.de> * @author Kaspar Schleiser <kaspar@schleiser.de> @@ -30,7 +30,7 @@ #include "random.h" -int _mersenne_init(int argc, char **argv) +int _random_init(int argc, char **argv) { int initval; @@ -53,7 +53,7 @@ int _mersenne_init(int argc, char **argv) return 0; } -int _mersenne_get(int argc, char **argv) +int _random_get(int argc, char **argv) { (void) argc; (void) argv; diff --git a/sys/shell/commands/shell_commands.c b/sys/shell/commands/shell_commands.c index 05d908a6281b36e3f911667d1c645a6fb98b56d7..ba8efa334dead1fbcd326744c19093b3aad9a2ea 100644 --- a/sys/shell/commands/shell_commands.c +++ b/sys/shell/commands/shell_commands.c @@ -96,8 +96,8 @@ extern int _icmpv6_ping(int argc, char **argv); #endif #ifdef MODULE_RANDOM -extern int _mersenne_init(int argc, char **argv); -extern int _mersenne_get(int argc, char **argv); +extern int _random_init(int argc, char **argv); +extern int _random_get(int argc, char **argv); #endif #ifdef MODULE_GNRC_NETIF @@ -187,8 +187,8 @@ const shell_command_t _shell_command_list[] = { #endif #endif #ifdef MODULE_RANDOM - { "mersenne_init", "initializes the PRNG", _mersenne_init }, - { "mersenne_get", "returns 32 bit of pseudo randomness", _mersenne_get }, + { "random_init", "initializes the PRNG", _random_init }, + { "random_get", "returns 32 bit of pseudo randomness", _random_get }, #endif #if FEATURE_PERIPH_RTC {"rtc", "control RTC peripheral interface", _rtc_handler},