Archive for May, 2011

Generating Random Numbers

I was looking for example code for RF2500 last night and came across some TI code for using the ADC as a random number generator. The function was in assembly, so I rewrote it in C:

bool getRandomBit(){
  ADC10CTL1 |= INCH_5;
  ADC10CTL0 |= SREF_1 + ADC10SHT_1 + REFON + ADC10ON;
  ADC10CTL0 |= ENC + ADC10SC;
  while(ADC10CTL1 & ADC10BUSY);
  return ADC10MEM & 0x01;
}

Pin 1.5 is floating unconnected, and is measured by the adc. The LSB is used as the random bit. There’s a twist though. Pin 1.4 is also floating unconnected, and is used as Vref+, so the top end of the range is floating as well. I thought that was pretty clever. Nice, TI!

I wrote a few console programs to help me visualize the randomness. It turned out the generator was biased toward producing 0′s. This function used with the previous function seemed to remove the bias:

EDIT: it was just dumb luck that the following function removed the bias. I did the math afterward, and this 0′s the bias when getRandomBit() returns a 1 30% of the time. I guess that means the ’0′ to ’1′ ratio of getRandomBit() is close to 7 to 3. Not great. I’m mulling over the idea of using laser speckle as a cheap way to generate the randomness.

bool get0BiasRandomBit(){
  if(getRandomBit()){
    if(getRandomBit())
      return 0;
    else
      return 1;
  }
  else{
    if(getRandomBit())
      return 1;
    else
      return 0;
  }
}

The following examples require the Full-duplex software UART for launchpad library, which was assembled by Rickta59.

To test for bias, I displayed a meandering line in a serial console. If I get more 0′s than 1′s, the line should slowly skew to the left or right:

#include "msp430g2231.h"
#include "config.h"
#include "softserial.h"
#include <stdbool.h>

#define CONSOLE_WIDTH          80

bool getRandomBit();
bool get0BiasRandomBit();

void main(){
  int linePositon = CONSOLE_WIDTH / 2;
  char cursorPosition;
  
  
  DCOCTL = CALDCO_16MHZ;
  BCSCTL1 = CALBC1_16MHZ;
  
  WDTCTL = WDTPW + WDTHOLD;          // Stop WDT
  
  SoftSerial_init();
  _enable_interrupts();
  
  while(1){
    for(cursorPosition = 0; cursorPosition < linePositon; cursorPosition++)
      SoftSerial_xmit('8');
    
    SoftSerial_xmit(' ');
    cursorPosition++;
    while(cursorPosition < CONSOLE_WIDTH){
      SoftSerial_xmit('8');
      cursorPosition++;
    }
    
    if(get0BiasRandomBit())
      linePositon++;
    else
      linePositon--;
    
    if(linePositon < 0)
      linePositon = CONSOLE_WIDTH + linePositon;
    else if(linePositon >= CONSOLE_WIDTH - 1)
      linePositon = linePositon - CONSOLE_WIDTH;
  }
}

bool get0BiasRandomBit(){
  if(getRandomBit()){
    if(getRandomBit())
      return 0;
    else
      return 1;
  }
  else{
    if(getRandomBit())
      return 1;
    else
      return 0;
  }
}

bool getRandomBit(){
  ADC10CTL1 |= INCH_5;
  ADC10CTL0 |= SREF_1 + ADC10SHT_1 + REFON + ADC10ON;
  ADC10CTL0 |= ENC + ADC10SC;
  while(ADC10CTL1 & ADC10BUSY);
  return ADC10MEM & 0x01;
}

and some example output from this code:

This sends a comma-separated list of random ints to the console:

#include "msp430g2231.h"
#include "config.h"
#include "softserial.h"
#include <string.h>

int adcGenRand16();
void reverse(char s[]);
void itoa(int n, char s[]);
void txString(char string[]);

void main(){
  int random;
  char string[7];
  
  DCOCTL = CALDCO_16MHZ;
  BCSCTL1 = CALBC1_16MHZ;
  
  WDTCTL = WDTPW + WDTHOLD;          // Stop WDT
  
  SoftSerial_init();
  _enable_interrupts();
  
  while(1){
    random = adcGenRand16();
    itoa(random, string);
    txString(string);
  }
}

void txString(char string[]){
  int iString = 0;
  while(string[iString] != 0){
    SoftSerial_xmit(string[iString]);
    iString++;
  }
  SoftSerial_xmit(',');
  SoftSerial_xmit(' ');
}

int adcGenRand16(){
  char bit;
  unsigned int random;
  
  for(bit = 0; bit < 16; bit++){
    ADC10CTL1 |= INCH_5;
    ADC10CTL0 |= SREF_1 + ADC10SHT_1 + REFON + ADC10ON;
    ADC10CTL0 |= ENC + ADC10SC;
    while(ADC10CTL1 & ADC10BUSY);
    random <<= 1;
    random |= (ADC10MEM & 0x01);
  }
  return random;
}

 /* itoa:  convert n to characters in s */
 void itoa(int n, char s[])
 {
     int i, sign;
 
     if ((sign = n) < 0)  /* record sign */
         n = -n;          /* make n positive */
     i = 0;
     do {       /* generate digits in reverse order */
         s[i++] = n % 10 + '0';   /* get next digit */
     } while ((n /= 10) > 0);     /* delete it */
     if (sign < 0)
         s[i++] = '-';
     s[i] = '\0';
     reverse(s);
 }
 
 /* reverse:  reverse string s in place */
 void reverse(char s[])
 {
     int i, j;
     char c;
 
     for (i = 0, j = strlen(s)-1; i<j; i++, j--) {
         c = s[i];
         s[i] = s[j];
         s[j] = c;
     }
 }

I guess I got a little sidetracked from my original purpose of getting started with the RF2500, but I had fun.

MIDI Synth is polyphonic

I did some work on the MIDI synth to make it polyphonic. With the help of George Lucas and John Williams, I was able to win the 43oh.com April 2011 Project of the Month Contest. Check out my thread on the 43oh forums for the details and to find out what this has to do with George Lucas.

It uses a cheap DAC breakout from Sparkfun and an LM386.

If you use MSP430 for fun or profit, the 43oh forums are a great resource with helpful people, so check them out!

MSP430 TV output update

Just a quick update. With the new MSP430G’s and their bigger flash space, I was able to increase the resolution of my TV output program. The resolution is now 192×240. When the new 16K MSP430G’s arrive, I plan on increasing this to 384×240, which will finally approach the native aspect ratio.

I just had to change a couple lines of code to get this going, and include the larger image file. I used an MSP430G2452 with 8K flash.

NOTE: This should be compiled in CCS under debug mode. Using release mode or different compilers will likely require adjustment of the software delay toward the bottom of the code.

Here’s the code.

The example images seen below:
miss_nature_close.h
miss_nature_wide.h

If you want to make your own images to use, first create a 192×240 monochrome bitmap. To convert the bitmap into a header.h file, I used a program called Image2Code from CrystalFontz. Use this setting to get the proper image format:

Return top