attiny84 Core

I've been working with attiny84s over christmas and I have a satisfactory setup going based on arduino-0017 and the attiny84 originally put up by R.Wiersma here http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1236434254/94#94

The results are pretty good with the 14 pin chip running at 8mhz. It doesn't have a hardware UART but it's fast enough that the original Software Serial library works fine at 9600 bps. The attiny84 has only 8k of flash and 512 bytes of ram but that's ok for my application. It only has one external interrupt but Bohne and others have made me less scared of the pin change interrupts so that's ok. I have hopes of getting a bootloader working sometime but at the moment i'm just loading the .hex file with an avr dragon.

The original poster did the heavy lifting of figuring out the core files and setting up timers but in order to get it working I've had to make a change to the source that I don't understand. I've PMd him but no joy there so I'm throwing the mystery out here for anyone who's interested. The problem shows up in the arduino functions pinMode and digitalWrite. As originally supplied these would work for the pins mapped to port B but not those on the attiny's portA.

The definition of pinMode is in wiring_digital.c and depends on definitions in pins_arduino.h and pins_arduino.c as follows:

 **FROM WIRING_DIGITAL.C**
void orig_pinMode(uint8_t pin, uint8_t mode)
{
      uint8_t bit = digitalPinToBitMask(pin);
      uint8_t port = digitalPinToPort(pin);
      volatile uint8_t *reg;

      if (port == NOT_A_PIN) return;

      // JWS: can I let the optimizer do this?
      reg = portModeRegister(port);

      if (mode == INPUT) *reg &= ~bit;
      else *reg |= bit;
}

**FROM PINS_ARDUINO.H**
#define digitalPinToPort(P) ( pgm_read_byte( digital_pin_to_port_PGM + (P) ) )
#define digitalPinToBitMask(P) ( pgm_read_byte( digital_pin_to_bit_mask_PGM + (P) ) )

**FROM PINS_ARDUINO.C**

#define PA 2
#define PB 3

const uint8_t PROGMEM port_to_mode_PGM[] = {
      NOT_A_PORT,
      NOT_A_PORT,
      &DDRA,
      &DDRB,
};
const uint8_t PROGMEM digital_pin_to_port_PGM[] = {
      PB, /* 0 */
      PB,
      PB,
      PA,
      PA,
      PA,
      PA,
      PA,
      PA, /* 8 */
      PA,
};

As I say, these work fine on the portB defined pins(digital 0-2) but not on the PortA pins(digital 3-9).

Trying to diagnose it I moved some port definitions into pinMode directly as follows:

void pinMode(uint8_t pin, uint8_t mode) //changes by bill rowe - not obvious why they're needed
{
      uint8_t bit = digitalPinToBitMask(pin);
      uint8_t port = digitalPinToPort(pin);
      volatile uint8_t *reg;
      uint8_t port_to_mode[] = { //wjr port mode mapping changed to local definition, 
                                 //macro/progmem stuff wasn't working.
        NOT_A_PORT,
        NOT_A_PORT,
        &DDRA,
        &DDRB,};
      if (port == NOT_A_PIN) return;

      reg = (volatile uint8_t *)(port_to_mode[port]);

      if (mode == INPUT) *reg &= ~bit;
      else *reg |= bit;

}

When it worked, I could only say "huh". The same problem exisisted for digitalWrite but seemingly not digitalRead. I haven't had to try the analogRead or Write yet.

Here are the pin definitions by the way:

//Modified 28-08-2009 for attiny84 R.Wiersma
// ATMEL ATTINY84 / ARDUINO
//
//                  +-\/-+
//            VCC  1|    |14  GND
//      (D 0) PB0  2|    |13  AREF
//      (D 1) PB1  3|    |12  PA1 (D 9) 
//              PB3  4|    |11  PA2 (D 8) 
//  PWM (D 2) PB2  5|    |10  PA3 (D 7) 
//  PWM (D 3) PA7  6|    |9   PA4 (D 6) 
//  PWM (D 4) PA6  7|    |8   PA5 (D 5) PWM
//                  +----+

The bug is in pins_arduino.h.

The following changes (to the original source files) seem to fix the problem...

#define portOutputRegister(P) ( (volatile uint8_t *)( [glow]pgm_read_byte[/glow]( port_to_output_PGM + (P))) )
#define portInputRegister(P) ( (volatile uint8_t *)( [glow]pgm_read_byte[/glow]( port_to_input_PGM + (P))) )
#define portModeRegister(P) ( (volatile uint8_t *)( [glow]pgm_read_byte[/glow]( port_to_mode_PGM + (P))) )

Hey great - thx for that.

You are welcome!

Have you done any more with the ATtiny84?

I've just about finished adding tone / noTone to bring it up-to-date with Arduino 0018.

Not really, i actually squeezed my application down to an 8 pin attiny85.

I'm delighted to know the tiny84 will work when i pick it up again.