You are here

Fun with the TFT - making a random start position | サイプレス セミコンダクタ

Fun with the TFT - making a random start position

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.

 

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…

Blog: 
Related Files: 

このサイトに掲示されているすべてのコンテンツと資料は、「そのままの状態」で提供されます。サイプレス セミコンダクタとその関連サプライヤは、これらの資料について、いかなる目的への適合性をも表明することはありません。また、これらの資料について、すべての保証や条件を放棄します。これには、暗示的な保証および条件、商用性、特定の目的への適合性、すべてのサードパーティの知的財産権に対する権利と非侵害などが含まれますが、これらに制限されることはありません。サイプレス セミコンダクタにより、明示または暗示にかかわらず、禁反言などによるライセンスは、付与されないものとします。このサイトに掲示されている情報の使用には、サードパーティまたはサイプレス セミコンダクタからのライセンスが必要となる場合があります。

このサイトのコンテンツには、特定のガイドラインや使用制限が含まれている場合があります。このサイトにおけるすべての掲示やコンテンツの使用は、サイトの利用規約に準じて行われるものとします。このコンテンツを使用するサードパーティは、制限やガイドラインに従い、このサイトの利用規約を遵守するものとします。サイプレス セミコンダクタとそのサプライヤは、コンテンツや資料、その製品、プログラム、サービスに対し、いつでも修正、削除、変更、改善、向上、その他の変更を加える権利を有します。また、いかなるコンテンツ、製品、プログラム、サービスを予告なく変更または閉鎖する権利を有します。