Revert "Cchange random() to use libc srand()/rand()"
This reverts commit db5227872a
.
return to using our own random implementation.
This commit is contained in:
parent
db5227872a
commit
5333729644

@ 90,6 +90,7 @@ class MicroBit


private:




void seedRandom();


uint32_t randomValue;




public:





@ 213,9 +214,8 @@ class MicroBit




/**


* Generate a random number in the given range.


* We use libc's rand() which is sufficient for our applications and much


* more lightweight than the hardware random number generator built into


* the processor, which takes a long time and uses a lot of energy.


* We use the NRF51822 in built random number generator here


* TODO: Determine if we want to, given its relatively high power consumption!


*


* @param max the upper range to generate a number for. This number cannot be negative


* @return A random, natural number between 0 and the max1. Or MICROBIT_INVALID_PARAMETER if max is <= 0.





@ 1,5 +1,4 @@


#include "MicroBit.h"


#include <stdlib.h> /* rand(),srand() */




char MICROBIT_BLE_DEVICE_NAME[] = "BBC micro:bit [xxxxx]";





@ 284,11 +283,13 @@ int MicroBit::sleep(int milliseconds)




/**


* Generate a random number in the given range.


* We use libc's rand() which is sufficient for our applications and much


* more lightweight than the hardware random number generator built into


* the processor, which takes a long time and uses a lot of energy.


* We use a simple Galois LFSR random number generator here,


* as a Galois LFSR is sufficient for our applications, and much more lightweight


* than the hardware random number generator built int the processor, which takes


* a long time and uses a lot of energy.


*


* KIDS: You shouldn't use this is the real world to generate cryptographic keys though...


* KIDS: You shouldn't use this is the real world to generte cryptographic keys though...


* have a think why not. :)


*


* @param max the upper range to generate a number for. This number cannot be negative


* @return A random, natural number between 0 and the max1. Or MICROBIT_INVALID_VALUE (defined in ErrorNo.h) if max is <= 0.



@ 300,38 +301,60 @@ int MicroBit::sleep(int milliseconds)


*/


int MicroBit::random(int max)


{


unsigned long num_bins, num_rand, bin_size, defect;


int result;


uint32_t m, result;




//return MICROBIT_INVALID_VALUE if max is <= 0...


if(max <= 0)


return MICROBIT_INVALID_PARAMETER;




num_bins = (unsigned long) max;


num_rand = (unsigned long) RAND_MAX + 1;


bin_size = num_rand / num_bins;


defect = num_rand % num_bins;


// Our maximum return value is actually one less than passed


max;




do {


result = rand();


} while ((num_rand  defect) <= (unsigned long)result); // CARE: avoid overflow


m = (uint32_t)max;


result = 0;


while(m >>= 1) {


// Cycle the LFSR (Linear Feedback Shift Register).


// We use an optimal sequence with a period of 2^321, as defined by Bruce Schneider here (a true legend in the field!),


// For those interested, it's documented in his paper:


// "PseudoRandom Sequence Generator for 32Bit CPUs: A fast, machineindependent generator for 32bit Microprocessors"


// https://www.schneier.com/paperpseudorandomsequence.html


// Avoid interupts (and hence fibre context switch) while we are doing this




__disable_irq();




randomValue = ((((randomValue >> 31)


^ (randomValue >> 6)


^ (randomValue >> 4)


^ (randomValue >> 2)


^ (randomValue >> 1)


^ randomValue)


& 0x0000001)


<< 31 )


 (randomValue >> 1);




__enable_irq();




result = ((result << 1)  (randomValue & 0x00000001));


}


} while (result > (uint32_t)max);






return result/bin_size;


return result;


}






/**


* Seed our a random number generator (RNG).


* We use the NRF51822 in built cryptographic random number generator to seed rand().


* We use the NRF51822 in built cryptographic random number generator to seed a Galois LFSR.


* We do this as the hardware RNG is relatively high power, and use the the BLE stack internally,


* with a less than optimal application interface. rand() is sufficient for our


* with a less than optimal application interface. A Galois LFSR is sufficient for our


* applications, and much more lightweight.


*/


void MicroBit::seedRandom()


{


unsigned int seed = 0;




randomValue = 0;




// Start the Random number generator. No need to leave it running... I hope. :)


NRF_RNG>TASKS_START = 1;





@ 343,13 +366,11 @@ void MicroBit::seedRandom()


// Wait for a number ot be generated.


while ( NRF_RNG>EVENTS_VALRDY == 0);




seed = (seed << 8)  ((int) NRF_RNG>VALUE);


randomValue = (randomValue << 8)  ((int) NRF_RNG>VALUE);


}




// Disable the generator to save power.


NRF_RNG>TASKS_STOP = 1;




srand(seed);


}








Loading…
Reference in a new issue