help

Do you think using port manipulation would be faster? Or would it end up being slower after dealing with getting the bits into their respective places in a byte?

it would be faster, but there is a ton of optimization left in that code

Osgeld:
it would be faster, but there is a ton of optimization left in that code

Really?

war_spigot:
Do you think using port manipulation would be faster? Or would it end up being slower after dealing with getting the bits into their respective places in a byte?

It would be a great exercise for sure, but in this particular case it will only serve to obfuscate what you are trying to do. As far as counting down from 9 to 0 in seconds, nothing will be gained. The code I offered may not be the most absolutely optimized as is possible (although it's not as far off as others might suggest), but it is easy to follow and will be as accurate as the crystal on your Arduino

I got it from 1086 bytes to 650 bytes with port manipulation(I don't know if it's faster or if it even works, I don't have my arduino, not any flipflops).

const byte pin0 = 4;
const byte pin1 = 5;
const byte pin2 = 6;
const byte pin3= 7;
byte count = 9;
long baseT = 0;
long period = 1000;
unsigned long currentT;

void setup() {
DDRD = DDRD | B11110000;
}

void loop(){
  display(count);
  currentT = millis();
  if((currentT - baseT) > period) {
    baseT = currentT;
    count--;  
    if (count == 255) count = 9;
  }
}

void display(int digit) {
  digit = digit << 4;
  PORTD = PORTD | digit;
}

There you go. Nice!

Speed is not a consideration here. The next step is only triggered once every second. Space savings are for real though. Cool. Hope tbear will test it out. Maybe Osgeld can get it down to 326 bytes. :wink:

BillO:
There you go. Nice!

Speed is not a consideration here. The next step is only triggered once every second. Space savings are for real though. Cool. Hope bear will test it out. Maybe Osgeld can get it down to 326 bytes.

I would be very impressed. One thing I found interesting was that changing "count" from an int to a byte made it 26 bytes smaller.

It would be a great exercise for sure, but in this particular case it will only serve to obfuscate what you are trying to do. As far as counting down from 9 to 0 in seconds, nothing will be gained.

I agree, see below for a grand example

The code I offered may not be the most absolutely optimized as is possible (although it's not as far off as others might suggest)

I did not mean to offend, "ton" is an exaggeration looking back

One thing I found interesting was that changing "count" from an int to a byte made it 26 bytes smaller.

Yes, get in the habit of using byte (or its C version uint8_t) if your value is < 255, you would not believe how many bytes you can save in for loops and dumb variables by not wasting 16 bits of space on nothing (especially in ram, storage is nothing, ram is the problem). Also something to keep an eye out for if your hitting the wall is value format, IE whats the difference tween

if count == 255);

and

if(count == 0xFFFF);

about 10 bytes, but of course if your program is 1k out of 32 or your using 650 bytes out of 2048, why bother? (and it does not really do squat for small values, play around)

Maybe Osgeld can get it down to 326 bytes. smiley-wink

Challenge ... (wait for it)... (wait for it)... FAILED

byte count = 9;

void setup() 
{
  DDRD = DDRD | 0xFF00;
  noInterrupts();      
  TCCR1A = 0;
  TCCR1B = 0;
  TCNT1  = 0;
  OCR1A  = 62500;            
  TCCR1B |= (1 << WGM12)|(1 << CS12);   
  TIMSK1 |= (1 << OCIE1A);  
  interrupts();          
}

ISR(TIMER1_COMPA_vect)
{
  count = count << 4;
  PORTD = PORTD | count;
  if(count == 0xFFFF) count = 9;
  count--;
}

void loop(){}

Binary sketch size: 570 bytes (of a 32256 byte maximum)

BTW: this is based on BillO's code so we dont know if it works, I am not at the bench, but hey it compiles ...

It could get smaller without the arduino overhead, and if we are REALLY pinching for bits one could always go direct to assembly. I also opted for a timer interrupt, which is a tad more piggy than using the arduino functions (cause they already set up 1 out of 3 timers that we are not using, I set up a second). But heck this aint avr freaks, and for a new person thread I went a little off the deep end.

The only advantage here is you could delay the main loop by an hour, and write an AI script that would make the arduino have nightmares for a decade and still keep 99.99999999% perfect time, if you want to know more visit http://letsmakerobots.com/node/28278

Personally, for new people I tend to forget it exist's, arduino already sets up some great time functions for you that only require simple 4 function math to use, and it gets you in the mindset of what you are doing, actions have effects on desired outputs. Yea you COULD use an interrupt every time you want to write a willy-nilly whatever main loop, but what happens when that timer (Timer 1 in this case) is already being used, like by the servo library?

Well you could use timer 0, oops there goes all your delays! Ok I will use timer 2, and crap there goes another batch of functions you may want to use. I dont want to call them crutches, they are valuable parts of the CPU's design, and for a reason, but on the other hand ... if you never learn to walk then you really have no need to run, right?

Great discussion!!

@ Osgeld and war-spigot

A few questions though.

count = count << 4; This effectively multiples count by 16, no? I'll test it later, but I'm pretty sure that would break things. We could move output to pins 8-11 and use port B to avoid the need for a shift. Otherwise we'd need something like:

x = count << 4;

Also, PORTD = PORTD | count;, the item above notwithstanding, would this not mean that the 4 MSB of PORTD would eventually end up all high? How about something like:

PORTD = x; where x is as suggested.

Finally, you are doing the test before the decrement, I think this is also going to create a problem.

I'll test your code above later today, but i suggest the following:

byte count = 9;
byte x;

void setup() 
{
  DDRD = DDRD | 0xFF00;
  noInterrupts();      
  TCCR1A = 0;
  TCCR1B = 0;
  TCNT1  = 0;
  OCR1A  = 62500;            
  TCCR1B |= (1 << WGM12)|(1 << CS12);   
  TIMSK1 |= (1 << OCIE1A);  
  interrupts();          
}

ISR(TIMER1_COMPA_vect)
{
  x = count << 4;
  PORTD = x;
  count--;
  if(count == 0xFFFF) count = 9;
}

void loop(){}

I'll test both and fiddle, and try port B. Later.

Okay, so I got 2 scenarios working.

My suspicions were right, the code Osgeld gave us needed some changing. This what worked:

//compiles to 566 bytes in V.22
byte count = 9;
byte x;

void setup() 
{
  DDRD = 0xFFF0;
  noInterrupts();      
  TCCR1A = 0;
  TCCR1B = 0;
  TCNT1  = 0;
  OCR1A  = 62500;            
  TCCR1B |= (1 << WGM12)|(1 << CS12);   
  TIMSK1 |= (1 << OCIE1A);  
  interrupts();          
}

ISR(TIMER1_COMPA_vect)
{
  x = count << 4;
  PORTD = x;
  count--;
  if(count == 0x00FF) count = 9;
}

void loop(){}

In IDE v0.22 it compiles to 566 bytes. Strange thing though, changing if(count == 0x00FF) count = 9; to if(count == 0xFFFF) count = 9; reduces the code by 12 bytes, but it doesn't trigger the condition.

Using port B this worked:

byte count = 9;

void setup() 
{
  DDRB = 0xFF0F;
  noInterrupts();      
  TCCR1A = 0;
  TCCR1B = 0;
  TCNT1  = 0;
  OCR1A  = 62500;            
  TCCR1B |= (1 << WGM12)|(1 << CS12);   
  TIMSK1 |= (1 << OCIE1A);  
  interrupts();          
}

ISR(TIMER1_COMPA_vect)
{
  PORTB = count;
  count--;
  if(count == 0xFF) count = 9;
}

void loop(){}

And compiles to 552 bytes. Again in IDE v0.22.

BTW Osgeld, your code compiles to 554 bytes in v0.22, so version 1 seems to add a little pork.

So, can any one explain why using OxFFFF is 12 bytes more compact than Ox00FF (or OxFF)?

You guys definitely helped and I did try Osgeld's code and it worked. Hope you guys had fun helping. Thanks!!