I don’t know about you, but I quickly got bored of always starting the ball in the same place. I’ve added some code to make that position random. The PSoC 6 device has an on-board true random number generator but, I’ll be honest, I’ve not looked up how to use it yet! So I shall use the poor-man’s option – read the noise on a pin with the ADC. Maybe I’ll circle back to this in the future and do it right!

The ADC on the PSoC 6 connects to port 10 and, after a quick scan of the kit silk screen I found that P10.7 has nothing connected to it (other than a solder hole). OK, that’s a lie. It was not quick and I did not find it. It’s been years since I could read a silk screen with my clapped-out old peepers. I had to go find a teenager and bribe him to read it for me. Why am I so honest with you on this blog???

Anyway, this pin will have enough noise to be a good random number seed. Note that I will not use the noise itself as the random number because it does not have a wide range of values. I’d just get a varying number in a small area of the screen. Instead I am going to use a pair of C stdlib run-time library functions. Start by including the header file.

#include <stdlib.h>

Write this simple function to get a random number from the library rand() function and constrain it to a desired range.

uint32_t getRandomInRange( uint32_t lo, uint32_t hi )

{

    uint32_t num = rand();

 

    num %= ( hi - lo );

    num += lo;

 

    return num;

}

Then change the bounce() function to call this function instead of hard-coding the values.

    uint16_t xPos = getRandomInRange( BOX_LEFT + radius, BOX_RIGHT  - radius );

    uint16_t yPos = getRandomInRange( BOX_TOP  + radius, BOX_BOTTOM - radius );

The last job is to get the random number and use it as a seed. I did this in a function with a pin as argument so I could experiment with different pins and verify that P10.7 is a good choice. The function initializes the ADC and selects a channel for the desired pin, then it reads the voltage at the pin and passes that value to srand() as the seed argument. Then it dutifully deinitializes the ADC like a good function should.

void initRandomNumber( cyhal_gpio_t noisy_pin )

{

    cyhal_adc_t adc;

    cyhal_adc_channel_t channel;

    uint16_t seed;

 

    /* Turn on the ADC for the specified pin */

    cyhal_adc_init( &adc, noisy_pin, (cyhal_clock_divider_t*)NULL );

    cyhal_adc_channel_init( &channel, &adc, noisy_pin );

 

    /* Read the noise (random) and use it as the seed */

    seed = cyhal_adc_read_u16( &channel );

    srand( seed );

 

    /* Turn off the ADC */

    cyhal_adc_channel_free( &channel );

    cyhal_adc_free( &adc );

}

Call this function from main(), with the argument “P10_7”, which is defined in the BSP, before you call bounce().

    initRandomNumber( P10_7 );

Program the kit with the new program and you’ll see that it (probably) does not start the ball in the center of the box. Good eh? Try resetting the kit a few times and the start point should change every time.

bounce_random_1.jpg     bounce_random_3.jpg

As before I have attached a copy of the main.c source file for your reference. I think we have had as much fun as you can have with just one ball now. Next time, I am going to add an RTOS to my project and spawn multiple ball-bouncing tasks…