Сode weight reduction from 4kb to 1kb.

Go To Last Post
30 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Please help me reduce weight the code from 4kb to 1kb.

I have attiny 13a and only 1kb memory. So bottom the code. 

#define F_CPU 1200000UL
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <stdlib.h>

#define T_POLL 136
#define TRANSON   _BV(2)
#define TRANSOFF   _BV(4)
#define LED_R   _BV(3)
#define BTN      _BV(1)

char mod = 0; // vatiable for 0 to 1
volatile uint8_t amount; //vatiable for 0 to 12 need for 12 reps ot one side and back
volatile uint8_t i; //vatiable for 0 to 10 need fo timer
volatile uint16_t Sec; //variable for count the number of second
volatile uint16_t SecF=0;// variable for make 5 second delay working mode, and than off.
int rantime; // variable for make random number.

ISR(TIM0_OVF_vect){ //timer
   TCNT0 = T_POLL;
   i++;

   if (i>=10) //period 1s
   {
      Sec++;
     i=0;
   }
}

static void pulcesDREAMon(void){
	for ( amount = 0; amount < 12; amount++ ) //this function make 11 times on/off ransistor of number 1
	 {
      PORTB |= TRANSON;
      _delay_ms(500);
      PORTB &= ~TRANSON;
	  _delay_ms(1000);
	}
}

static void pulcesDREAMoff(void){
	for ( amount = 0; amount < 12; amount++ ) //this function make 11 times on/off ransistor of number 2
	 {
      PORTB |= TRANSOFF;
      _delay_ms(500);
      PORTB &= ~TRANSOFF;
	  _delay_ms(1000);
	}
}

static void pulce_led(void){
    PORTB |= LED_R;
    _delay_ms(10);
    PORTB &= ~LED_R;
}

static void povtor_per(void){ //repeating a piece of text repeat
   	SecF=5; //this variable need for check how much time passed
	Sec = 0;
}

static void povtor_per2(void){ //repeating a piece of text repeat
   	SecF=3000; //this variable need for disable funtion which off the mode
	Sec = 0;
}

int main(void){

   PRR = (1<<PRADC); // shut down ADC

   TIMSK0 = (1<<TOIE0);  // timer0 overflow interrupt enable
   TCCR0B = (1<<CS02) | (1<<CS00); // prescaler 1/1024

   sei();

   DDRB = TRANSON | TRANSOFF | LED_R; //work for the exit

   rantime = 1800 + random() % 5400; //make random number between 30 min and 2 hours.

while (1){
  if (mod==0){
     if (Sec>=1800){
        pulcesDREAMon(); //on the need mode and give them to work 5 sek.
		povtor_per();
     }

	 if (Sec>=SecF){ //check how much time passed
        pulcesDREAMoff();
		povtor_per2();
     }

  }

  if (mod==1){
     if (Sec>=rantime){
        pulcesDREAMon(); //on the need mode and give them to work 5 sek.
		povtor_per();
		rantime = 1800 + random() % 5400;
     }

	 if (Sec>=SecF){
        pulcesDREAMoff(); //check how much time passed
		povtor_per2();
     }

     }

  if (PINB & BTN){ //just a function button processing
     cli();
     Sec = 0;
     if (mod==0){
        mod = 1;
        pulce_led();
    } else {
       mod = 0;
       pulce_led();
       _delay_ms(100);
       pulce_led();
	   SecF=5400;
    }
     _delay_ms(1000);
     sei();
  }
}
}

 

This topic has a solution.
Last Edited: Thu. Feb 9, 2017 - 06:22 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I would get rid of the delay calls, you've got a timer ISR, use it to write your own delay function.

How does the random number work out? Seems to me that you'll probably get the same number every time at startup, although I could be wrong. Anyhow, I'm guessing the random function could eat some memory. Think about doing it another way. Just using % 5400 probably adds a fair amount of code.

 

If it's still too big, you might need to write it in assembler.

Four legs good, two legs bad, three legs stable.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Your code takes 1168 bytes i.e. 114% full

 

If I eliminate the greedy library function.

#define random() 12345   //.kbv

then the code goes down to 790 bytes.   So it just comes down to writing a smaller random() function.   Quite honestly,   simple math on a long and truncating the result might be "good enough".

 

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Program Memory Usage     :    982 bytes   95.9 % Full
Data Memory Usage         :    9 bytes   14.1 % Full

 

Code fits in when all variables are not global scope. only 2(?) variables actually needed to be global.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I check hex file, which i get after building code in the avr studio. His current weight is 3.23kb. What i should check really?
How can i writing random() a smaller?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Strog wrote:

I check hex file, which i get after building code in the avr studio. His current weight is 3.23kb. What i should check really?
How can i writing random() a smaller?

 

use atleast -O1 optimisation level, right now you are using -O0 which makes the code huge.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

now i change optimization level to -O1 and have the same result in .hex file.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

AS7 reports the number of bytes.   The size of the HEX file is irrelevant.

 

Just look at Jonis's report in #4.

 

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

if you have a spare unconnected pin, use the ADC to read it, makes a fairly good random number generator! 

If all else fails, get a tiny85, same pinout as your t13, but has 8 times the flash space! 

 

Jim

 

 

Keys to wealth:

Invest for cash flow, not capital gains!

Wealth is attracted, not chased! 

Income is proportional to how many you serve!

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Please post you questions on the correct forum, this is for Studio bugs ONLY. I'll move the thread.

John Samperi

Ampertronics Pty. Ltd.

https://www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Just for fun, I built the app with CodeVision, fixing up as needed.  Came up with 816 bytes "Speed"; 760 bytes "Size".  .HEX is 2.1KB.

 

I'd expect a GGC build to be very close in size to CV.  Perhaps this one is worse but often/usually GCC is a few percent smaller on a real (i.e. full) app.  This one is borderline trivial...

 

Strog wrote:
ISR(TIM0_OVF_vect){ //timer TCNT0 = T_POLL; ...

 

That timer has a CTC mode -- use it.

 

 

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

To replace the random number generator, you can use a 16 bit "linear feedback shift register", it will generate a pseudo-random sequence of all 16 bit numbers except zero, and is a very simple algorithm.

 

edit:

Also, this line has a modulus, which is a kind of division. This will probably generate quite a lot of code, you can replace the modulus by a successive subtraction, it may be slower but saves bytes.

   rantime = 1800 + random() % 5400; //make random number between 30 min and 2 hours.

 

uint16_t temp_random;

temp_random = random();
while (temp_random >= 5400) temp_random -= 5400;
rantime = 1800 + temp_random;

 

Last Edited: Tue. Feb 7, 2017 - 11:16 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

El Tangas wrote:
To replace the random number generator,...

 

I'll rebuild with GCC.  But I wouldn't focus on that random too much.  A)  The app fits;  B) CV's rand() takes 29 words so not really a killer.

 

I verified the results above with a default build in Studio7 and GCC -- ~115%.  Now, my build used the standard rand() with is small.  I need to start digging to see what random() is...

 

Function random()

long random(void)

The random() function computes a sequence of pseudo-random integers in the range of 0 to RANDOM_MAX (as defined by the header file <stdlib.h>).

The srandom() function sets its argument seed as the seed for a new sequence of pseudo-random numbers to be returned by rand(). These sequences are repeatable by calling srandom() with the same seed value.

If no seed value is provided, the functions are automatically seeded with a value of 1.

And rand()...

Function rand()

int rand(void)

The rand() function computes a sequence of pseudo-random integers in the range of 0 to RAND_MAX (as defined by the header file <stdlib.h>).

The srand() function sets its argument seed as the seed for a new sequence of pseudo-random numbers to be returned by rand(). These sequences are repeatable by calling srand() with the same seed value.

If no seed value is provided, the functions are automatically seeded with a value of 1.

In compliance with the C standard, these functions operate on int arguments. Since the underlying algorithm already uses 32-bit calculations, this causes a loss of precision. See random() for an alternate set of functions that retains full 32-bit precision.

 

 

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

Last Edited: Tue. Feb 7, 2017 - 11:06 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

lol -- changing to rand() >>increases<< the code size in GCC.  Not what I expected.

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

So apart from the fact that I already mentioned the random and modulo functions being worth investigation, I still reckon that the first random, which is near the beginning of main(), will simply return the same number every time the program is run. Maybe I'm missing something.

 

Four legs good, two legs bad, three legs stable.

This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

david.prentice wrote:

Your code takes 1168 bytes i.e. 114% full

 

If I eliminate the greedy library function.

#define random() 12345   //.kbv

then the code goes down to 790 bytes.   So it just comes down to writing a smaller random() function.   Quite honestly,   simple math on a long and truncating the result might be "good enough".

 

David.

 

When I did that, I got 590 bytes. No doubt, random() has to go away.

 

Edit: So I after reading a bit I wrote a pseudo random generator to replace random(), just comment out  the #include <stdlib.h> line and paste this, I hereby release it into public domain:

 

#define random() rnd()
uint16_t rnd_seed = 0xC042;
uint16_t rnd() {
	union {
		uint16_t full;
		struct as_bytes {
			uint8_t low;
			uint8_t high;
		} byte;
		struct as_bits {
			uint8_t _0: 1;
			uint8_t _1: 1;
			uint8_t _2: 1;
			uint8_t _3: 1;
			uint8_t _4: 1;
			uint8_t _5: 1;
			uint8_t _6: 1;
			uint8_t _7: 1;
			uint8_t _8: 1;
			uint8_t _9: 1;
			uint8_t _10: 1;
			uint8_t _11: 1;
			uint8_t _12: 1;
			uint8_t _13: 1;
			uint8_t _14: 1;
			uint8_t _15: 1;
		} bit;
	} random;
	
	random.full = rnd_seed;
	random.bit._7 = random.bit._1;
	random.byte.low = random.byte.high ^ random.byte.low;
	random.byte.high = random.byte.low ^ (random.byte.low << 1);
	
	rnd_seed <<=1;
	if (random.bit._15 == 1) rnd_seed++;
	
	return rnd_seed;
}

 

Yeah, this was written in a convoluted way because I think in terms of assembly an not C. My bad. The randomness seems ok on visual inspection:

 

 

Using this, the code is 736 bytes.

Last Edited: Wed. Feb 8, 2017 - 03:32 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Yes, but your code will still produce exactly the same number the first time your random function is called. It will also, unless I've missed something, return exactly the same sequence thereafter. Maybe that's not important for your application, but if, for example, you were designing a network of some sort, and wanted a random back-off in the event of a collision, you might have a big problem.

 

Four legs good, two legs bad, three legs stable.

Last Edited: Wed. Feb 8, 2017 - 09:32 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Ok I checked the org code and compiled from studio4 (2010 winAVR compiler), and got this result:

 

-O2  1168 Byte 

-Os  1120 Byte

 

 

It's only Sec that need's to be volatile,  (i should be static in the ISR)

so remove volatile for all the other variables , and move to register variables (and init in main for those that need it).

the code is down to 1022 byte ;)

 

Comments to OP for the future:

don't use delay when you have ISR's they become inaccurate (and especially not when you have a timer ISR where you easy can make a counter for them)

don't change the timer in the ISR, run the timer in CTC mode with a top that fit your code (something like 256-T_POLL for your code perhaps +-1 ;) )

i only change in the ISR, so place it as a static inside the ISR. (produce same code)

I checked the code size for  % 5400 and it didn't go down by much , that surprised me but I guess it's because random probably use div routines as well.

 

And if a more optimal code for random and better selections for the delay numbers this code could fit into 512 byte even in C  ;)

 

perhaps theusch can check it with CV that is normally better to small stuff like this.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

John_A_Brown wrote:

Yes, but your code will still produce exactly the same number the first time your random function is called. It will also, unless I've missed something, return exactly the same sequence thereafter. Maybe that's not important for your application, but if, for example, you were designing a network of some sort, and wanted a random back-off in the event of a collision, you might have a big problem.

 

 

You mean for the OP's application, I don't know what it is, so I just suggested this method.

And yes, it's a pseudorandom sequence, it has 65535 terms (all 16 bit numbers except zero), you could at least start at a random place with an ADC read, or as was suggested before, even create a random number generator entirely based on the ADC.

 

For example, read the ADC 16 times and concatenate the LSBs of each reading into a 16 bit random number.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

or lower n bits of the WD timer.

 

Ups forget it you can't read the WD

Last Edited: Wed. Feb 8, 2017 - 03:31 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

El Tangas wrote:

John_A_Brown wrote:

Yes, but your code will still produce exactly the same number the first time your random function is called. It will also, unless I've missed something, return exactly the same sequence thereafter. Maybe that's not important for your application, but if, for example, you were designing a network of some sort, and wanted a random back-off in the event of a collision, you might have a big problem.

 

 

You mean for the OP's application, I don't know what it is, so I just suggested this method.

And yes, it's a pseudorandom sequence, it has 65535 terms (all 16 bit numbers except zero), you could at least start at a random place with an ADC read, or as was suggested before, even create a random number generator entirely based on the ADC.

 

For example, read the ADC 16 times and concatenate the LSBs of each reading into a 16 bit random number.

 

Sorry, my bad. I was assuming you were the OP.  I should have checked.

 

Four legs good, two legs bad, three legs stable.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Edit: So I after reading a bit I wrote a pseudo random generator to replace random(), just comment out  the #include <stdlib.h> line and paste this, I hereby release it into public domain:

 Thanks man. But i have a stupid question. Which variables are responsible for the nomination of the minimum and maximum boundary values. I mean if i need a range numbers between 0 and 5400, what should i do. Or a just need wrote something like 

if(rnd_seed>5400) rnd_seed=0;

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

it don't

but since 5400 is so big just sub 5400 until <5400 and use that number. (as your number but the org number as that next input)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

 

have the same result in .hex file.

The .hex file is an ascii representation of the binary, and is always much bigger than the actual code.  Use "avr-size" on the .elf file (or the .hex file, probably) to see the actual size.

 

 avr-gcc -mmcu=attiny13 -Os dream.c

 avr-size a.out
   text       data        bss        dec        hex    filename
   1160          4          9       1173        495    a.out

 

Ok; just a little bit over; this is probably doable...

 

 avr-nm --size-sort -S a.out
 :
000000cc 00000012 t pulce_led
00000382 00000012 T srandom
0000002c 00000016 T __do_copy_data

00000278 00000028 T __divmodsi4
000003fc 0000002c T __epilogue_restores__
000003ce 0000002e T __prologue_saves__

00000398 00000036 T __umulsidi3
0000008a 00000042 t pulcesDREAMoff
00000048 00000042 t pulcesDREAMon

000002b0 00000044 T __udivmodsi4
000000de 00000048 T __vector_3
00000428 0000005c T __muldi3

000002f4 00000082 t do_random
00000126 00000152 T main

 

So the "big" functions in your program are the random number generator, and the modulus operator (that ends up calling various division functions.)  Replace those with more space-efficient code and you should be OK.   (Other people have already suggested this; I added this message to show one way to figure that out...)

 

After that...   You have some "volatile" variables that don't need to be volatile, and I'd note that  pulcesDREAMon and pulcesDREAMoff are almost identical, and _delay_ms() is a macro that expands to more code than, say, "delay10ms(100);" (Where delay10ms() is a function that uses _delay_ms() inside a small loop.)

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

As said in #18 if you remove the unneeded volatile and place the variables in registers then the code fit (at least with the old compiler and I guess the version in studio7 can do it aswell .) 

 

declare variables:

register uint8_t amount asm("r3");
register uint16_t SecF asm("r4");
register char mod asm("r2");
register int rantime asm("r6");
register uint8_t i asm("r8");

 

volatile uint16_t Sec; //variable for count the number of second

 

add init code in main:

   mod=0;
   SecF=0;

 

 

Add

I just looked at the code again and realized that you have an atomic problem with Sec.

You have disabled ISR when you change the it so there it's fine

 

But this code

if (Sec>=1800){

is not good (don't feel bad you aren't the only one that have made that mistake, and for you it only means that your random delay is a tad wrong).

(the problem is that it's a 8 bit micro so between it reads low byte and high byte there can come an ISR that change Sec so in a odd time between 1791 and 1792 you can get a reading of 2047 )

 

there are many ways to avoid this,

1:the fast and ugly safe way is to use ATOMIC_BLOCK (include <util/atomic.h> ) every time you use Sec.

2:make a atomic copy of Sec in the top of the while loop (in PLC's it's normal to read all inputs at the top, then do all the logic with those (even if they change in the real world), and then write back at the end. )

3:do the check in the ISR and set a flag you use in main

4:scale Sec so it can fit in 8 bit 

5:in ASM (and I know that CV can do it, but no warranty, place it in register and use movw for the copy) 

6:set a flag in main, and wait until it's cleared in ISR, now you know that that the ISR don't come for a while. (only good for timer ISR  that run all the time like here). 

Add

7: Or don't use timer ISR, (let the timer set it's ISR flag, but have ISR disabled ), then in the while loop see if the flag is set, then clear it and do what the ISR did. This way you know when everything happens. (or use ISR but just set a flag when Sec should get updated, and then do the update in main ) 

 

Add I just tried to add this:

register volatile uint16_t Sec asm("r10"); //variable for count the number of second

 

still the atomic problem , but it compiles it (I didn't think register and volatile would work) and the ASM output code looks fine, and what more are the code go down to 936 byte.

 

And now I guess that we need an GCC expert to tell how to make sure that the compiler don't overwrite the register variables!

 

Last Edited: Thu. Feb 9, 2017 - 01:37 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Well, I decided to do the OP work for him, by following all (well, most) the advice in the thread, including my own advice, of course cheeky

 

- Put variables in registers (variables in ISR are volatile register, whatever that means...)

- Merge pulcesDREAMon and pulcesDREAMoff into a single function

- custom random function

- replace modulus by successive subtraction

 

Obtaining:

 

#define F_CPU 1200000UL
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
//#include <stdlib.h>


#define T_POLL 136
#define TRANSON   _BV(2)
#define TRANSOFF   _BV(4)
#define LED_R   _BV(3)
#define BTN      _BV(1)

register uint8_t mod asm("r2"); // vatiable for 0 to 1
register uint8_t amount asm("r3"); //vatiable for 0 to 12 need for 12 reps ot one side and back
volatile register uint8_t i asm("r4"); //vatiable for 0 to 10 need fo timer
volatile register uint16_t Sec asm("r10"); //variable for count the number of second
register uint16_t SecF asm ("r12");// variable for make 5 second delay working mode, and than off.
register uint16_t rantime asm("r6"); // variable for make random number.

#define random() rnd()
register uint16_t rnd_seed asm("r8");
uint16_t rnd() {
	union {
		uint16_t full;
		struct as_bytes {
			uint8_t low;
			uint8_t high;
		} byte;
		struct as_bits {
			uint8_t _0: 1;
			uint8_t _1: 1;
			uint8_t _2: 1;
			uint8_t _3: 1;
			uint8_t _4: 1;
			uint8_t _5: 1;
			uint8_t _6: 1;
			uint8_t _7: 1;
			uint8_t _8: 1;
			uint8_t _9: 1;
			uint8_t _10: 1;
			uint8_t _11: 1;
			uint8_t _12: 1;
			uint8_t _13: 1;
			uint8_t _14: 1;
			uint8_t _15: 1;
		} bit;
	} random;
	
	random.full = rnd_seed;
	random.bit._7 = random.bit._1;
	random.byte.low = random.byte.high ^ random.byte.low;
	random.byte.high = random.byte.low ^ (random.byte.low << 1);
	
	rnd_seed <<=1;
	if (random.bit._15 == 1) rnd_seed++;
	
	return rnd_seed;
}

ISR(TIM0_OVF_vect){ //timer
	TCNT0 = T_POLL;
	i++;

	if (i>=10) //period 1s
	{
		Sec++;
		i=0;
	}
}

void randomize_rantime (void) {
	rantime = random();
	while (rantime > 5400) rantime -= 5400;
	rantime += 1800;
}

static void pulcesDREAM(uint8_t state){
	for ( amount = 0; amount < 12; amount++ ) //this function make 11 times on/off ransistor of number 1
	{
		PORTB |= state;
		_delay_ms(500);
		PORTB &= ~state;
		_delay_ms(1000);
	}
}


static void pulce_led(void){
	PORTB |= LED_R;
	_delay_ms(10);
	PORTB &= ~LED_R;
}

static void povtor_per(void){ //repeating a piece of text repeat
	SecF=5; //this variable need for check how much time passed
	Sec = 0;
}

static void povtor_per2(void){ //repeating a piece of text repeat
	SecF=3000; //this variable need for disable funtion which off the mode
	Sec = 0;
}

int main(void){
	mod = 0;
	SecF=0;
	rnd_seed = 0xC042;

	PRR = (1<<PRADC); // shut down ADC

	TIMSK0 = (1<<TOIE0);  // timer0 overflow interrupt enable
	TCCR0B = (1<<CS02) | (1<<CS00); // prescaler 1/1024

	sei();

	DDRB = TRANSON | TRANSOFF | LED_R; //work for the exit

	randomize_rantime(); //make random number between 30 min and 2 hours.

	while (1){
		if (mod==0){
			if (Sec>=1800){
				pulcesDREAM(TRANSON); //on the need mode and give them to work 5 sek.
				povtor_per();
			}

			if (Sec>=SecF){ //check how much time passed
				pulcesDREAM(TRANSOFF);
				povtor_per2();
			}

		}

		if (mod==1){
			if (Sec>=rantime){
				pulcesDREAM(TRANSON); //on the need mode and give them to work 5 sek.
				povtor_per();
				randomize_rantime();
			}

			if (Sec>=SecF){
				pulcesDREAM(TRANSOFF); //check how much time passed
				povtor_per2();
			}

		}

		if (PINB & BTN){ //just a function button processing
			cli();
			Sec = 0;
			if (mod==0){
				mod = 1;
				pulce_led();
				} else {
				mod = 0;
				pulce_led();
				_delay_ms(100);
				pulce_led();
				SecF=5400;
			}
			_delay_ms(1000);
			sei();
		}
	}
}

 

This compiles to 442 bytes! It's Under 512 bytes, as sparrow2 had predicted in post #18.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

but it don't solve OP's atomic problem :)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

El Tangas, thx very much. But i still can't understand.

1. What about range this code (from 0 to 60000?) I can't use range from 0 to 5400?

#define random() rnd()

2. About this 

void randomize_rantime (void) {
    rantime = random();
    while (rantime > 5400) rantime -= 5400; // Why i can't write rantime -=3600; ?
    rantime += 1800;
}

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

sparrow2 wrote:

but it don't solve OP's atomic problem :)

 

Nope. But now he has plenty of room to solve any problems.

 

Strog wrote:

El Tangas, thx very much. But i still can't understand.

1. What about range this code (from 0 to 60000?) I can't use range from 0 to 5400?

#define random() rnd()

2. About this 

void randomize_rantime (void) {
    rantime = random();
    while (rantime > 5400) rantime -= 5400; // Why i can't write rantime -=3600; ?
    rantime += 1800;
}

 

 

 

My rnd() function always returns numbers in range 1 to 65535 (no zero). If you need a different range, you need to use modulus (larger code equivalent to division, but may be faster) or successive subtraction, like I did in my code. I did subtraction with 5400 because that was the number you had in your original code in the modulus, but it can be any 16 bit number.

 

edit: so, for 3600, the code would be

    while (rantime > 3600) rantime -= 3600; //successive subtraction to get remainder, equivalent to rantime = rantime % 3600

and this would leave a number in range 0 to 3599. The probability of zero would be a bit smaller than it should, because as I said, zero is missing from the sequence, but 3600, 7200, etc would also give zero, so I don't think it would be a problem.

 

Problem is, the smaller the number, the slower will be the successive subtraction method, at some point modulus will be much faster.

Last Edited: Sat. Feb 11, 2017 - 11:42 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Since I doubt this number has to be that random, could you not simply use the top 12 bits(I seem to remember that the higher bits will be "more random" than the lower ones, but that may be just for linear congruential methods...), thus deriving a number between 0 and 4095? This would make the successive subtraction faster.

 

Alternatively, the OP could find a 12 bit maximal LFSR implementation.

 

 

Four legs good, two legs bad, three legs stable.

Last Edited: Sun. Feb 12, 2017 - 12:22 PM