ATTiny85 and MIT core not running at 8Mhz?

I searched around and didn't see any mention of this anywhere, so I thought I'd ask. Has anyone used the MIT Tiny cores from Index of /, burned the 8Mhz Internal Oscillator bootloader (i.e. set the fuse bits) and then had it still run at 1Mhz? I was totally baffled by debugging some timing+interrupt heavy based code that I've been working with (GitHub - mchr3k/arduino-libs-manchester for 433mhz RF) and then I realized that my Tiny was running at 1Mhz. Reburned the bootloader, still no love. Hooked up my oscillator and just sent a pulse in my loop, nothing more than

digitalWrite(4, HIGH);
digitalWrite(4, LOW);

and it spikes once per uS, which is, unless I'm delusional, 1Mhz. Anyone else run into this?

joshuajnoble:

digitalWrite(4, HIGH);

digitalWrite(4, LOW);




and it spikes once per uS, which is, unless I'm delusional, 1Mhz. Anyone else run into this?

You're making an awful lot of assumptions there.

digitalWrite() takes more than one clock cycle to execute. You're doing two digitalWrites per pulse so it will take twice as long as that for one cycle (I'm very amazed you got 1MHz - the Tiny85 library must be quite well optimized!)

Try something like this:

const char p = 0x10;
while (true) {
  PINB=p;   PINB=p;  // One pulse...
  PINB=p;   PINB=p;
  PINB=p;   PINB=p;
  PINB=p;   PINB=p;
  PINB=p;   PINB=p;
  PINB=p;   PINB=p;
  PINB=p;   PINB=p;
  PINB=p;   PINB=p;  // Eight pulses
}

That will flip the output pin once per clock cycle (apart from when it goes back to the start of the loop). Two flips makes one complete pulse so you should see a 4mHz signal if you're running at 8mHz.

You're making an awful lot of assumptions there

Had I thought a little bit more, I would have put 2Mhz. That's what I get for trying to multi-task.

You're definitely right about the number of cycles per instruction, many thanks for reminding me about that! I've got the following code showing me 4 spikes per uS, hence 8Mhz if my math is right?

void setup()
{
  DDRB |= 0x1;	// setup pin 1 in data direction register as output
}

void loop()
{
  while(true) {
    PORTB |= 0x1;	// set pin 1 so that it is at vcc
    PORTB &= 0xFE;	// clear pin 1 so that it is grounded
    PORTB |= 0x1;	// set pin 1 so that it is at vcc
    PORTB &= 0xFE;	// clear pin 1 so that it is grounded
    PORTB |= 0x1;	// set pin 1 so that it is at vcc
    PORTB &= 0xFE;	// clear pin 1 so that it is grounded
    PORTB |= 0x1;	// set pin 1 so that it is at vcc
    PORTB &= 0xFE;	// clear pin 1 so that it is grounded
  }
}

So, my timing problems are of my own making, which is a consolation. If I can ask a secondary question then (and if I should set up another thread, I'd be happy to) I'm setting a timer interrupt on TIMER1, would this somehow affect the timing in my sketch (other than introducing another method to run at an interval)? The gist is below (and, I'd be happy to post more code if you'd like). I'm not sure how the Tiny core works but I didn't see any indication that it's using Timer1 and I'd assume it's using Timer0 for delay() and delayMicroseconds().

void start() {
  TCCR1 = _BV(CTC1) | _BV(CS12); 
  OCR1A = 1; // we're checking every other count
  TIMSK = _BV(OCIE1A); // Turn on interrupt
  TCNT1 = 0; // Set counter to 0
}

ISR(TIMER1_COMPA_vect) {
   // check the input pins and try to do 
   // manchester decoding.
}

Thanks much for the suggestions and the help, it's much appreciated.

joshuajnoble:
You're definitely right about the number of cycles per instruction, many thanks for reminding me about that! I've got the following code showing me 4 spikes per uS, hence 8Mhz if my math is right?

void loop()

{
 while(true) {
   PORTB |= 0x1; // set pin 1 so that it is at vcc
   PORTB &= 0xFE; // clear pin 1 so that it is grounded
 }
}

I'd say no...

"PORTB |= 0x1;" is a read of port B followed by an or and a write. That's going to be at least two clock cycles.

This is why my code used PINB - to avoid the read.

joshuajnoble:
I'm not sure how the Tiny core works but I didn't see any indication that it's using Timer1 and I'd assume it's using Timer0 for delay() and delayMicroseconds().

I believe you're right...

If I'm not, and delay() stops working, use Timer0..

“PORTB |= 0x1;” is a read of port B followed by an or and a write. That’s going to be at least two clock cycles.

This is why my code used PINB - to avoid the read.

Interesting, ok. I’ve always used PORTB for writing, guess I didn’t actually know what it was doing. Thanks for the info.

If I’m not, and delay() stops working, use Timer0…

The delay() method keeps working, but my read timing seems very inconsistent. If I’m reading the data sheet correctly page 92-92, table 12-5 says that setting the CS12 of TCCR1 pre-scales the clock to PCK/8, which should be 1Mhz, so reading on the overflow of OCR1A I should be triggering this method around 500khz. It seems to be actually reading much more slowly than that, around 100khz. I’m wondering if this is caused by what’s in my interrupt routine, which is essentially just reading from the pin my RF receiver is connected to and then comparing that to the last read to find encoded bits. The code is below if anyone is interested in taking a peruse. Please do let me know if you see something horribly wrong in there. Thanks,

ISR(TIMER1_COMPA_vect) {
  rx_sample = digitalRead(RxPin);
  boolean transition = (rx_sample != rx_last_sample);

  if(simpleRXMode == 2 || simpleRXMode == 1) {
    rx_count++;
  }

  // Receive data
  if (transition)
  {

    if(simpleRXMode == 0) {
        simpleRXMode = 1;
        return;
    }

    if((simpleRXMode == 1 && rx_sample == 1) && (rx_count >= MinCount && rx_count <= MaxCount)) {
      
      transitionCount++;
      if(transitionCount == 2) {
        simpleRXMode = 2;
        return;
      }
    }

    if(rx_count >= MinLongCount && rx_count <= MaxLongCount)  // was the previous bit a double bit?
    {
      rx_count = 0;
      AddManBit(&rx_manBits, &rx_numMB, &rx_curByte, rx_data, rx_last_sample);
      bitsRead++;
    }
    else if( rx_count >= MinCount && rx_count <= MaxCount )
    {
      rx_count = 0;
      // Add the current bit
      AddManBit(&rx_manBits, &rx_numMB, &rx_curByte, rx_data, rx_sample);
      bitsRead++;
    }

    if (bitsRead > 7) // for simplicity, only sending 8 bits at a time
    {
      rx_mode = RX_MODE_MSG; // say we're done
      simpleRXMode = 0; // go back to beginning
      rx_data = 0; // clear data
      bitsRead = 0; // no bits read
      transitionCount = 0;
    }
  } 
  else if( (simpleRXMode == 1 || simpleRXMode == 2) && rx_count > MaxLongCount)  // no transition & it's been too long
  {
    rx_count = 0; // clear data
    simpleRXMode = 0; // go back to beginning
    rx_data = 0; // clear data
    bitsRead = 0; // no bits read
    transitionCount = 0;
  }
    
  // Get ready for next loop
  rx_last_sample = rx_sample;
}

joshuajnoble:
I'm setting a timer interrupt on TIMER1, would this somehow affect the timing in my sketch (other than introducing another method to run at an interval)? ...Tiny core...

Are you using the Tiny Core?
http://code.google.com/p/arduino-tiny/

Or the core available from the MIT website?
http://hlt.media.mit.edu/?p=1695
https://github.com/damellis/attiny/zipball/Arduino1

By default, in the Tiny Core, timer 1 is used for millis (and its ilk). The MIT core always uses timer 0 for millis.

The Tiny Core has a compiler switch to use timer 0.

Hi, thanks for clarifying that. I'm actually using the MIT version from Mellis https://github.com/damellis/attiny/zipball/Arduino1 because it seems like it's being developed more actively. Hence, I was trying to work with a timer overflow interrupt on Timer1.