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

/*******************************
 *          __                   
 *         /\ \                  
 *  __  _  \_\ \     __    ___   
 * /\ \/'\ /'_' \  /'__'\ /'___\ 
 * \/>  <//\ \ \ \/\  __//\ \__/ 
 *  /\_/\_\ \___,_\ \____\ \____\
 *  \//\/_/\/__,_ /\/____/\/____/
 * 
 *  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

/*******************************
 *          __                   
 *         /\ \                  
 *  __  _  \_\ \     __    ___   
 * /\ \/'\ /'_' \  /'__'\ /'___\ 
 * \/>  <//\ \ \ \/\  __//\ \__/ 
 *  /\_/\_\ \___,_\ \____\ \____\
 *  \//\/_/\/__,_ /\/____/\/____/
 * 
 *  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 *

This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

This site uses Akismet to reduce spam. Learn how your comment data is processed.