/* BlueDataDistributor - data distribution module from ethernet to 32 serial ports
 * version 0.1.1 date 2006-10-07
 * Copyright (C) 2006 Stefan Schuermans <stefan@blinkenarea.org>
 * a BlinkenArea project - http://www.blinkenarea.org/
 */

#include <stdlib.h>

#include "random.h"

// number of complete bytes a call to random( ) returns
#if RANDOM_MAX < 0xFF
#error random number generator is not able to return a random byte
#elif RANDOM_MAX < 0xFFFF
#define RANDOM_BYTES 1
#elif RANDOM_MAX < 0xFFFFFF
#define RANDOM_BYTES 2
#elif RANDOM_MAX < 0xFFFFFFFF
#define RANDOM_BYTES 3
#else
#define RANDOM_BYTES 4
#endif

// entropy collected so far
unsigned long RandomEntropy = 0; // the entropy itself
unsigned char RandomEntropyCnt // number of times entropy was collected so far
              = sizeof( unsigned long ) * 8 - 1; // use first entropy collected as initial random seed (better than no seed at all)

// provide some entropy
void RandomProvideEntropy( unsigned char Entropy ) // (extern)
{
  // collect entropy
  RandomEntropy = RandomEntropy << 1 ^ (unsigned int)Entropy;
  RandomEntropyCnt++;
}

// task function to do the work - call from main loop
void RandomTask( void ) // (extern)
{
  // enough entropy was collected
  if( RandomEntropyCnt >= sizeof( unsigned long ) * 8 ) // one time entropy for every bit of RandomEntropy
  {
    RandomEntropyCnt = 0;
    // re-seed random number generator
    srandom( RandomEntropy );
  }
}

// get random data
void RandomGetData( unsigned char * pData, unsigned char Length ) // (extern)
{
  unsigned long r;
  unsigned char i;

  // return random data
  for( ; Length >= RANDOM_BYTES; Length -= RANDOM_BYTES )
  {
    r = random( );
    for( i = 0; i < RANDOM_BYTES; i++ )
    {
      *pData = (unsigned char)r;
      pData++;
      r >>= 8;
    }
  }
  if( Length > 0 )
  {
    r = random( );
    for( i = 0; i < Length; i++ )
    {
      *pData = (unsigned char)r;
      pData++;
      r >>= 8;
    }
  }
}

