MSP430 Random Number Generator (RNG)

10000_RNG_sFür mein nächstes Projekt bzw. Programm, brauchte ich einen RNG (Random Number Generator) oder auch Zufallsgenerator genannt. Auf einen normalen Desktop-Rechner ist das kein Problem, da C und z.B. Java fertige Random-Funktionen besitzen. Diese Funktionen generieren die Zufallszahlen auf Basis der Uhrzeit (meistens). Bei einem Microcontroller bzw. speziell dem MSP430 musste ich mir also etwas anderes einfallen lassen. Vor ein paar Monaten bin ich auf diese Idee durch Zufall gestoßen. Ich habe einen falschen ADC-Port initialisiert und habe ein nettes Rauschen (offener ADC-Port) bekommen. Der umgewandelte Wert ist also dauerhaft in einem bestimmten Bereich hin und her gesprungen. Perfekt für einen RNG! Display: ILI9341 TFT-Display

Video

Ein kurzes Video, welches den RNG in Action zeigt. Ein klassischer Starfield Effect, Pseudo-Code von Hugo Elias.

Source-Code & Bilder

Um den den RNG zu testen, habe ich auf einem Display einfach zufällig Pixel gesetzt. Das wird wohl der beste Test sein, um die Zufälligkeit zu bewerten. Ein wirkliches Muster lässt sich nicht erkennen. Die eigentliche Zufallszahl wird durch einen offenen Port am ADC realisiert. Bei der Erzeugung der Zufallszahl wird ein Wert eingelesen und das LSB von diesem Wert in eine Variable geshiftet. Dies passiert x-mal (je nach Wunsch). Das LSB wird also immer eine Position weiter (LSB -> MSB) in die Variable (Word) abgespeichert. DIe Wahrscheinlichkeit, dass sich das LSB ändert, ist höher als alle anderen Bits. Somit kann ein sehr guter Zufallswert erzeugt werden.

10000 draw_pixel Aufrufe:

10000_RNG_s

20000 draw_pixel Aufrufe:

20000_RNG_s

30000 draw_pixel Aufrufe:

30000_RNG_s

lib_RNG.c

  1. /*******************************
  2.  *          __                   
  3.  *         /\ \                  
  4.  *  __  _  \_\ \     __    ___   
  5.  * /\ \/'\ /'_' \  /'__'\ /'___\
  6.  * \/>  <//\ \ \ \/\  __//\ \__/
  7.  *  /\_/\_\ \___,_\ \____\ \____\
  8.  *  \//\/_/\/__,_ /\/____/\/____/
  9.  *
  10.  *  Author: declis (xdec.de)
  11.  ********************************/
  12.  
  13. #include <msp430g2553.h>
  14. #include "lib_RNG.h"
  15.  
  16. unsigned char max_bits=12;  // max. number
  17.  
  18. /*********************************************************************************
  19.  * Name:        get_rand
  20.  * Description: - generates a random number between min and max
  21.  *              - function is based on a linear equation y=mx+b
  22.  *              - the maximum value can be set via max_bits
  23.  *              - if you need a number between 0-255, max_bits need to be set to
  24.  *                  8 (2^8), number between 0-4095 -> 12 (2^12) etc.
  25.  * Input:       minimum (min), maximum (max)
  26.  * Return:      random number
  27.  *********************************************************************************/
  28.  
  29. signed int get_rand(signed int min, signed int max)
  30. {
  31.     return min+(((signed long)(max-min+1)*get_seed(max_bits))>>max_bits);
  32. }
  33.  
  34. /*********************************************************************************
  35.  * Name:        get_seed
  36.  * Description: - generates a random number between 0 to a max. of (2^16)-1
  37.  *              - RNG is based on ADC10 and a floating port (noise)
  38.  *              - maximum value can be set via bit_count
  39.  *              - if bit_count is set to 16, ADC conversion will be started 16x times
  40.  *                  and the LSB of ADC10MEM will be shifted into a word 16x
  41.  * Input:       bit_count (maximum number)
  42.  * Return:      random number
  43.  *********************************************************************************/
  44.  
  45. unsigned int get_seed(unsigned char bit_count)
  46. {
  47.     unsigned int mix_up=0;unsigned char index=0;
  48.     while(index<bit_count)
  49.     {
  50.         ADC_start();
  51.         // LSB of ADC10MEM will be shifted into a word
  52.         mix_up+=(ADC10MEM&1)<<index++;
  53.     }
  54.     // xor old with new value or something else maybe
  55.     return mix_up;
  56. }
  57.  
  58. /*********************************************************************************
  59.  * Name:        init_ADC
  60.  * Description: - initialize ADC10
  61.  * Input:       ADC channel, analog port
  62.  * Return:      nothing
  63.  *********************************************************************************/
  64.  
  65. void init_ADC(unsigned char channel, unsigned char port)
  66. {
  67.     ADC10CTL0&=~ENC;    // conversion disabled
  68.     //Channel 2; ADC10 CLK divider = /8; CLK=ADC10OSC
  69.     ADC10CTL1=(unsigned int)(channel<<12)+ADC10DIV_7+ADC10SSEL_0;
  70.     //Vref+=Vcc (3.3V)&Vss=Vr- ; S&H time 16x; ADC10 on        
  71.     ADC10CTL0=SREF_0+ADC10SHT_3+ADC10ON;  
  72.     // P1.2 is analog input (floating port)
  73.     ADC10AE0|=port;                        
  74. }
  75.  
  76. /*********************************************************************************
  77.  * Name:        ADC_start
  78.  * Description: - converted value will be in ADC10MEM
  79.  * Input:       nothing
  80.  * Return:      nothing
  81.  *********************************************************************************/
  82.  
  83. void ADC_start(void)
  84. {
  85.     ADC10CTL0|=ENC+ADC10SC;         // start & enable conversion       
  86.     while(ADC10CTL0&ADC10BUSY);     // ADC busy?
  87. }
/*******************************
 *          __                   
 *         /\ \                  
 *  __  _  \_\ \     __    ___   
 * /\ \/'\ /'_' \  /'__'\ /'___\ 
 * \/>  <//\ \ \ \/\  __//\ \__/ 
 *  /\_/\_\ \___,_\ \____\ \____\
 *  \//\/_/\/__,_ /\/____/\/____/
 * 
 *  Author: declis (xdec.de)
 ********************************/ 

#include <msp430g2553.h>
#include "lib_RNG.h"

unsigned char max_bits=12;	// max. number

/*********************************************************************************
 * Name: 		get_rand
 * Description: - generates a random number between min and max
 * 				- function is based on a linear equation y=mx+b
 * 				- the maximum value can be set via max_bits
 * 				- if you need a number between 0-255, max_bits need to be set to
 * 					8 (2^8), number between 0-4095 -> 12 (2^12) etc.
 * Input:		minimum (min), maximum (max)
 * Return:		random number
 *********************************************************************************/

signed int get_rand(signed int min, signed int max)
{
	return min+(((signed long)(max-min+1)*get_seed(max_bits))>>max_bits);
}

/*********************************************************************************
 * Name: 		get_seed
 * Description: - generates a random number between 0 to a max. of (2^16)-1
 * 				- RNG is based on ADC10 and a floating port (noise)
 * 				- maximum value can be set via bit_count
 * 				- if bit_count is set to 16, ADC conversion will be started 16x times
 * 					and the LSB of ADC10MEM will be shifted into a word 16x
 * Input:		bit_count (maximum number)
 * Return:		random number
 *********************************************************************************/

unsigned int get_seed(unsigned char bit_count)
{
	unsigned int mix_up=0;unsigned char index=0;
	while(index<bit_count)
	{
		ADC_start();
		// LSB of ADC10MEM will be shifted into a word
		mix_up+=(ADC10MEM&1)<<index++;
	}
	// xor old with new value or something else maybe
	return mix_up;
}

/*********************************************************************************
 * Name: 		init_ADC
 * Description: - initialize ADC10
 * Input:		ADC channel, analog port
 * Return:		nothing
 *********************************************************************************/

void init_ADC(unsigned char channel, unsigned char port)
{
	ADC10CTL0&=~ENC;	// conversion disabled
	//Channel 2; ADC10 CLK divider = /8; CLK=ADC10OSC
  	ADC10CTL1=(unsigned int)(channel<<12)+ADC10DIV_7+ADC10SSEL_0;
  	//Vref+=Vcc (3.3V)&Vss=Vr- ; S&H time 16x; ADC10 on         
  	ADC10CTL0=SREF_0+ADC10SHT_3+ADC10ON;  
  	// P1.2 is analog input (floating port)
  	ADC10AE0|=port;                        
}

/*********************************************************************************
 * Name: 		ADC_start
 * Description: - converted value will be in ADC10MEM
 * Input:		nothing
 * Return:		nothing
 *********************************************************************************/

void ADC_start(void)
{
	ADC10CTL0|=ENC+ADC10SC;			// start & enable conversion		
	while(ADC10CTL0&ADC10BUSY);		// ADC busy? 
}

lib_RNG.h

  1. /*******************************
  2.  *          __                   
  3.  *         /\ \                  
  4.  *  __  _  \_\ \     __    ___   
  5.  * /\ \/'\ /'_' \  /'__'\ /'___\
  6.  * \/>  <//\ \ \ \/\  __//\ \__/
  7.  *  /\_/\_\ \___,_\ \____\ \____\
  8.  *  \//\/_/\/__,_ /\/____/\/____/
  9.  *
  10.  *  Author: declis (xdec.de)
  11.  ********************************/
  12.  
  13. #ifndef LIB_RNG_H_
  14. #define LIB_RNG_H_
  15.  
  16. extern unsigned char max_bits;
  17. signed int get_rand(signed int,signed int);
  18. unsigned int get_seed(unsigned char);
  19. void init_ADC(unsigned char,unsigned char);
  20. void ADC_start(void);
  21.  
  22. #endif /*LIB_RNG_H_*/
/*******************************
 *          __                   
 *         /\ \                  
 *  __  _  \_\ \     __    ___   
 * /\ \/'\ /'_' \  /'__'\ /'___\ 
 * \/>  <//\ \ \ \/\  __//\ \__/ 
 *  /\_/\_\ \___,_\ \____\ \____\
 *  \//\/_/\/__,_ /\/____/\/____/
 * 
 *  Author: declis (xdec.de)
 ********************************/ 

#ifndef LIB_RNG_H_
#define LIB_RNG_H_

extern unsigned char max_bits;
signed int get_rand(signed int,signed int);
unsigned int get_seed(unsigned char);
void init_ADC(unsigned char,unsigned char);
void ADC_start(void);

#endif /*LIB_RNG_H_*/

 

 

One thought on “MSP430 Random Number Generator (RNG)

Leave a Reply

Your email address will not be published. Required fields are marked *

Time limit is exhausted. Please reload CAPTCHA.