core13: An Arduino core for the Attiny13 *testers wanted*

Yes the 1.1V reference works. But make sure you use the latest version because it was not supported in old versions

Tested this ok, I have a slight different folder structure (just addapted a bit there for my sketches/hardware folder), i'm running the attiny13a @ 5V 9.6MHz (lfuse: 7A hfuse: FF), F_CPU = 12MHz, still the delay is not accurate, guess i could do a calibration here.
Programming it with an usbasp programmer (guess my raspi would program it too)
burned fuses with avrdude:
avrdude -pt13 -cusbasp -Pusb -U lfuse:w:0x7A:m -U hfuse:w:0xFF:m
or avrdude -pt13 -cusbasp -Pusb -U lfuse:w:0x7A:m -U hfuse:w:0xFF:m
depending on how the board was called on the avrdude.conf file (avrdude -p? for a list of boards)
some might change -P and -c if using another programmer

I had to edit my avrdude.conf and changed the "t13" to "attiny13a" because thats how the IDE was refering it (use verbose mode for details) so after the change i had to refer to the board as attiny13a when using avrdude from command line

here is my 208 bytes blink program:

#define LED 2

void setup() {
DDRB=DDRB&~(1<<LED)|(1<<LED);//set LED as output
}

void loop() {
PORTB^=(1<<LED);//blink LED
delay(500);
}

i have to add an Arduino.h file (using IDE 1.0.5)
also on my linux (ubuntu 14.04) system i had to create a link for

/usr/lib/avr/lib/avr25/tiny-stack/crttn13a.o -> /usr/lib/avr/lib/avr25/crttn13a.o

thanks for the core :smiley:

dwhacks:
Is there a way to have 8 mhz?

8mhz is very easy by simply adjusting the osccal register. i do this on all my t13 projects to compensate for the oddball clock. now the same code works for nearly all my avr projects.

Hello i am trying to fit a weather station transmitter code into a attiny13 and its working as it is but i need a bit more space to get the sleep code in, to make it usable with batteries. This is the code as of now any tip on where/how i can make the code smaller??

//WH2 transmitter weather station

#define rf_ut 0    //433 transmitter on pin 0


#define  onee 470      //Timings for transmitting
#define  zero 1430
#define  space 930

byte wh2_packet[5];      //Packets to send
//byte wh2_calculated_crc;






int main(void){
init();
{
 


  
  
  wh2_packet[0]=75;      //First 12 bits transmitter id and stuff (8 bits here and 4 in next packet)
  wh2_packet[1]=80;      // 4 bits id and rest temperature bit 3 set bit for -+ and 0-2 highest bits in 11 bit temp 260=26,0 C
//  wh2_packet[2]=138;   //last 8 bits in temp
  wh2_packet[3]=255;    //humidity set no senstor for it so set to 255
  
  
   analogReference(INTERNAL);      //internal ADC
 
 /*
  
  wh2_packet[0]=B01001011 ;
  wh2_packet[1]=B01010000 ;
  wh2_packet[2]=B10001010 ;
  wh2_packet[3]=B11111111  ;
  //wh2_packet[4]=B01010111;
  
  
 */ 
  
  /*
  wh2_packet[0]=B01000011;
  wh2_packet[1]=B10010001;
  wh2_packet[2]=B11111111;
  wh2_packet[3]=B00000000;
  wh2_packet[4]=B00111000;
  */
  

  pinMode(rf_ut, OUTPUT);
  
   //setup
}



while(1) {
  
  
  

  unsigned int temp=analogRead(A1);    //read temp tmp 36 sensor
  
   if(temp<467)          //trying to map the temperature/voltage without long or float not perfect but -+1 or 2 deg ok for now
 {                                    //1023 adc to 1100 mv, 500-1100 positive temp in c, 500-0 negative temp in c
  temp=(temp*107)/100; 
  temp=500-temp;
 //temp=temp*(-1);
 bitSet(wh2_packet[1], 3);        //bit for negative temp 1=neg 0=+
 }
 
 else
 {
 bitClear(wh2_packet[1], 3);
 
 
 
 temp=temp-467;                           //467 is the adc of 500 mv-+
 temp=(temp*107)/100;
 }
  
  
  
 //moving temperature into the right bits 
 //3 lowest bits in  wh2_packet[1] and all bits in wh2_packet[2]
int counter=2;

 while(counter>(-1))
 {
  
  bitWrite(wh2_packet[1], counter, bitRead(temp, counter+8));
  counter--; 
   
 }
  
  counter=7;
   while(counter>(-1))
 {
  
  bitWrite(wh2_packet[2], counter, bitRead(temp, counter));
  counter--; 
   
 }
 
 //wh2_packet[3]=temp;
 
 
  

  //crc over the first 4 bits stolen from resciever end
  
  wh2_packet[4] = crc8(wh2_packet, 4);
 
 
 //Sending first 8 bits B11111111 to initinate resciever
 
    sendd(255);
   sendd(wh2_packet[0]);
   sendd(wh2_packet[1]);
   sendd(wh2_packet[2]);
   sendd(wh2_packet[3]);
   sendd(wh2_packet[4]);
  delay(1000);
  
  
  
  
  
  
//code
                                 
}
}

uint8_t crc8( uint8_t *addr, uint8_t len)
{
  uint8_t crc = 0;

  // Indicated changes are from reference CRC-8 function in OneWire library
  while (len--) {
    uint8_t inbyte = *addr++;
    for (uint8_t i = 8; i; i--) {
      uint8_t mix = (crc ^ inbyte) & 0x80; // changed from & 0x01
      crc <<= 1; // changed from right shift
      if (mix) crc ^= 0x31;// changed from 0x8C;
      inbyte <<= 1; // changed from right shift
    }
  }
  return crc;
}


void sendd(byte number)

{
int counter1=7;



  //-----preamble---------------------------------
  
    while(counter1>-1)
    {
    
    if((bitRead(number, (counter1)))==1 )
    {
    digitalWrite(rf_ut,HIGH);
    delayMicroseconds(onee);
    
    }
      else
      {
          digitalWrite(rf_ut,HIGH);
          delayMicroseconds(zero);
      }
      digitalWrite(rf_ut,LOW);
      delayMicroseconds(space);
      counter1--;
    }


}

recompiling with winavr using "naked" directive will save about 30%. rewriting in asm about half. all tools to these are included in arduino.

You can call _delay_ms() yourself instead of delay since you don't need a variable argument
which might save a few bites. A word of warning though:

The internal clock in the '13 is marginally accurate at best and is voltage and temperature dependent
Things that need tight timing like generating rf signal pulses might not work as you expect

Thank you both for the tips, i have managed to get the sleeping function in now, so its sleeping at 3uA now.

Ye i know the clock are temperamental lol, but i am lucky the receiver side of things are very forgiving with the timing. I have the transmitter in the freezer now its -27 C in there and it is still sending out OK signals so i think it will do.

Thank you again for this Core as of now i have 4 projects running with it and more to come.

First release (minor update) of 2014

Thank you for the update, i will give it a test over the weekend.

This is brilliant !! Good work SmeezeKitty, I have been looking for a way to use 13's from my IDE and this is perfect

Ideally I want to run at 8mhz, I guess others have commented on this too, but I havent read all 16 pages of posts yet

Are the cores stable ? on page 1 you mentioned that alot is untested, is this still the case ?

Regards Bob

mcnobby:
This is brilliant !! Good work SmeezeKitty, I have been looking for a way to use 13's from my IDE and this is perfect

Ideally I want to run at 8mhz, I guess others have commented on this too, but I havent read all 16 pages of posts yet

Are the cores stable ? on page 1 you mentioned that alot is untested, is this still the case ?

Regards Bob

It runs fine on 8MHz but you need to use an external oscillator (which uses up an I/O pin)
The internal clock options are 128KHz, 600KHz, 1.2MHz, 4.8MHz, 9.6MHz
None of which are particularly accurate :stuck_out_tongue:
But they are R/C oscillators

It is pretty stable now. At first I had a lot of problems with hanging especially during I/O
but I think I have that problem more or less solved. There are still some functions I have not thoroughly tested.
Partly because it isn't that easy to test without UART. And partly because I haven't had much time lately.

thats ok, I can work with 9.6mhz..

for comms have you considered making a few timing adjustments to tinydebug ? or would that take up too much flash ?

for comms have you considered making a few timing adjustments to tinydebug ?

Regarding smeezekitty's core and TinyDebug see this

http://forum.arduino.cc/index.php?PHPSESSID=ugfk8b6of564ohs1btn2lpfb10&topic=123388.75

Will this work as is with a 10 pin attiny13?

I noticed that you commented out:
/#define EXTERNAL_INT_6 6
#define EXTERNAL_INT_7 7
/

But I don't understand what it means.

I'm looking to create a very small single rgb led controller while being able to check the input of 2 pins and supporting i2c so I can communicate to other controllers.

fusionstream:
Will this work as is with a 10 pin attiny13?

Huh? Do you mean the 10-pin QFN package? This still has only 6 usable pins. PB0 - PB5.

The attiny13 only has two PWM output pins so you wouldn't be able to properly control an RGB LED.

You will need to go with an attiny85 which does have 3 PWM output pins.

The attiny13 only has two PWM output pins so you wouldn't be able to properly control an RGB LED.

Unless you use a WS2812 rgb LED, I have just finished writing my code to convert DMX (250kbps) to WS2812 (800khz), it is currently only 950 bytes and runs on an ATTiny85 @ 8mhz perfectly, when my ATTiny13's arrive this will be my first project

Its written in C and assembler, but once I get confident enough I will convert it over to all assembly

I have just 90 bytes left to squeeze in an up/down button input to set the DMX receive channel :slight_smile:

That is very interesting. Adafruits NeoPixel code does not currently support the attiny13 due to internal clock rate differences and the minimum flash size need to be at least 2.5K.

So you have custom code that can support the attiny13 clock rates and flash size? Can you share your code?

Its a bit knife and fork, but it works, I intend to use it on the ATTiny13 (1k flash / 60 bytes ram)
just need a few defines, and set your port, and DDR... WS2812 routine is left for you to include/adjust how you like

code modified from here -> http://www.instructables.com/id/Bitbanging-step-by-step-Arduino-control-of-WS2811-/#step0

#define DIGITAL_PIN   (2)         // Digital port number
#define PORT          (PORTB)     // Digital pin's port
#define PORT_PIN      (PORTB2)    // Digital pin's bit position

unsigned long  latch50us;

void setup(void) {
// setups and DDR
}

void loop(void) {
WS2812();
delay(10);
}

void WS2812(void) {
    while((micros() - latch50us) < 50L);  // 50us data latch
    cli(); 
    volatile uint8_t green = 50; // choose your values for RGB
    volatile uint8_t red = 191; 
    volatile uint8_t blue = 45; 
    asm volatile(
      "rcall dobits\n\t"    // do green
      "mov %5, %6\n\t"
      "rcall dobits\n\t"    // do red
      "mov %5, %7\n\t"
      "rcall dobits\n\t"    // do bloo
      "rjmp out\n\t"
    "dobits:\n\t"           // label
      "ldi  %4, 8\n\t"      // reset number of bits
    "nextbit:\n\t"          // label                       
      "sbi  %0, %1\n\t"     // SET OUTPUT HIGH
      "sbrc %5, 7\n\t"      // Skip if HiBit in value is clear  
      "rjmp bitset\n\t"     // jump if HiBit is set 
      "cbi %0, %1\n\t"      // SET OUTPUT LOW
      "rol  %5\n\t"         // shift value left to get to next bit
      "dec  %4\n\t"         // decrement nBits
      "brne nextbit\n\t"    // branch if bits not finished
      "ret\n\t"
    "bitset:\n\t"           // label
      "rol  %5\n\t"         // shift value left to get to next bit
      "cbi %0, %1\n\t"      // SET OUTPUT LOW
      "dec  %4\n\t"         // decrement nBits
      "brne nextbit\n\t"    // branch back if bits not finished
    "ret\n\t"               // return from sub
    "out:\n\t"              // exit
      ::
      // Input operands         Operand Id (w/ constraint)
      "I" (_SFR_IO_ADDR(PORT)), // %0
      "I" (PORT_PIN),           // %1
      "e" (&PORT),              // %a2
      "w" (NULL),              // %3
      "r" (8),                // %4
      "r" (green),              // %5
      "r" (red),                // %6
      "r" (blue)                // %7
    );
  sei();                       
  latch50us = micros();                 
}

I forgot to mention, I am just writing to a single WS2812 at the moment, but i guess the code can be adjusted to write to more

I have just 90 bytes left to squeeze in an up/down button input to set the DMX receive channel

Well that isn't necessarily true. When you switch to a different core the compiled code size may go up or down