#include "stm32f4xx.h"


__attribute__((always_inline)) inline void bitCopy( uint32_t *dest, const uint8_t dstBit, const uint32_t src, const uint8_t srcBit )
{
	register uint32_t temp;
	__asm__ __volatile__ (
			"UBFX	%[tmp], %[src], %[sbit], #1	\n\t"
			"BFI	%[dst], %[tmp], %[dbit], #1	\n\t"
			: [dst]"=r"(*dest), [tmp]"=&r"(temp)
			: [src]"r"(src), [dbit]"I"(dstBit), [sbit]"I"(srcBit), "0"(*dest) );
}


uint32_t rand()
{
	uint32_t rand = RNG->DR;
	// ohne folgende Zeile kommt häufig mehrmals die selbe Zahl aus der Schüttelbox... What ever...
	while( rand == RNG->DR );
	return rand;
}


int main(void)
{
	SystemInit();

	// Enable the RNG
	RCC_AHB2PeriphClockCmd(RCC_AHB2Periph_RNG, ENABLE);
	RNG->CR |= RNG_CR_RNGEN;
	while ( !(RNG->SR & RNG_FLAG_DRDY) )
		;

	uint8_t data[16];
	uint16_t buffer[8];

	// random init data[]
	for( uint8_t i=0; i<16; i++ )
		data[i] = rand();

	__asm("NOP");
	__asm("NOP");
	__asm("NOP");	// zum wieder finden des Codes 3x NOP

	uint32_t out0;	// Arrays kann er wohl nicht in register optimieren...
	uint32_t out1;	//  Daher 4 einzelne Variablen
	uint32_t out2;
	uint32_t out3;

	for (int dataCnt = 0; dataCnt < 16; dataCnt++)
	{
		uint8_t tmp = data[dataCnt];

		bitCopy( &out0, 0, tmp, 7 );
		bitCopy( &out0, 16, tmp, 6 );
		bitCopy( &out1, 0, tmp, 5 );
		bitCopy( &out1, 16, tmp, 4 );
		bitCopy( &out2, 0, tmp, 3 );
		bitCopy( &out2, 16, tmp, 2 );
		bitCopy( &out3, 0, tmp, 1 );
		bitCopy( &out3, 16, tmp, 0 );

		out0 <<= 1;
		out1 <<= 1;
		out2 <<= 1;
		out3 <<= 1;
	}

	buffer[0] = out0 & 0xFFFF;
	buffer[1] = out0 >> 16;
	buffer[2] = out1 & 0xFFFF;
	buffer[3] = out1 >> 16;
	buffer[4] = out2 & 0xFFFF;
	buffer[5] = out2 >> 16;
	buffer[6] = out3 & 0xFFFF;
	buffer[7] = out3 >> 16;


	__asm__( "NOP" );

    while(1)
    {
    	for( int i=0; i<8; i++ )
    		GPIOE->ODR = ((volatile uint16_t*)(buffer))[i];	// Bitte nix wegopimieren!
    }
    return 0;
}
