Need help with pin mapping, 328 to 644

Hi gang,
I am designing what is basically an oversized duemilanove, using an surface mount atmega644p in place of the atmega328p, and adding extra board area for some other parts. (644P for the 2nd serial port and more memory)

Is there a way to make this compatible with existing shields?

(and where is the Eagle symbol for the 644A/PA in TQFP? Am not finding it )
(Oops, Never mind, I found it)

One connector look straight forward

  • bring the 6 power/reset signals to a connector

while the other 3 not so much:

  • the 6 analog signals, they originate at different port pins:
    atmega328P atmega644P
    J2, pins 1-6
    adc0/PC0 adc0/PA0
    adc1/PC1 adc1/PA1
    adc2/PC2 adc2/PA2
    adc3/PC3 adc3/PA3
    adc4/PC4 adc4/PA4
    adc5/PC5 adc5/PA5

  • the J3 pins originate at different port pins:
    J3, pins 1-8
    atmega328P atmega644P
    OC1/PB1 OC1A/PD5
    SS/PB2 SS/PB4
    Gnd GND
    ARef ARef

  • the J1 pins originate at different port pins:
    J1, pins 1-8
    atmega328P atmega644P
    RX/PD0 RX0/PD0
    TX/PD1 TX0/PD1
    INT0/PD2 INT0/PD2
    INT1/PD3 INT1/PD3
    T0/PD4 T0/PB0 ??
    T1/PD5 T1/PB1 ??
    AIN0/PD6 AIN0/PB2 ??
    AIN1/PD7 AIN1/PB3 ??

How do I handle this to ensure shield compatibility?


Is there a way to make this compatible with existing shields?

We studied this for our Gator board and here are the pin mappings we came up with for best compatibility:

The Quick Shield: breakout all 28 pins to quick-connect terminals

I guess you have to try and ensure any hardware features like SPI match, which you seem to have done. All GPIO can presumably be mapped as any with other variant.

One thing that looks like a problem is the i2c, that's on PC0,1 but these pins are not ADC inputs on the 644. So that conflict cannot be resolved.

What I've done on a board I'm working on (and I've seen this done on another Mega clone) is provide solder bridges to allow either the A4,5 or the i2c onto the shield header. But you can't do both at the same time unless you just connect PC0,1 to PA4,5 and hope nobody write code that causes them to clash :), ie they decide to use AN4 as an output while also using i2c.

Thinks: You could do the same with the two extra ADCs but you'd still have the same problem of potential clashes.

Thinks again: A low value resistor between the pins would at least stop people from killing the pin hardware and have no real affect on other functions. Maybe 220R or something that won't stuff up the i2c. WRONG, you'd need a high value to preserve the i2c but that would affect other functions


Here’s what I did for my Mega clone, any suggestions for a better way welcome.


I'm liking that solution, maybe with 3 pins & 2 jumpers to set to one side or the other vs solder pads to make it a little more user friendly- or, easier to screw up, depending on how one looks at it 8)

Yeah, triple jumpers would be a lot easier for the user. I don't really have the room.


@RuggedCircuits, you only have 29 pins shown on the gator circuit, not sure where the others went.

Okay Rob, here's what I'm thinking then.

The data from the sanguino pins.c file is shown also, that's what was used for the original Hacking the Uno prototype.

I'm thinking a pinout assigment like this, keeping arduino functionality based on name commonality, other names based on sanguino usage, and backfilling the rest.
I'm not in love with any particular name assignment, there's only the few functions that are fixed by hardware,
so if it makes to call them otherwise & make a pins.c match I'll have no issue with that.

Analog inputs
I2C pins
SPI pins
RX/TX pins (2 sets)
INT2 pin
PWMs (PB3,4, PD4,5,6,7)

PA0 - A0/D14
PA1 - A1/D15
PA2 - A2/D16
PA3 - A3/D17
PA4 - A4/D18
PA5 - A5/D19
PA6 - A6/D25 (S)
PA7 - A7/D24 (S)

PB0 - D4
PB1 - D5
PB2 - D6 - (INT2 on 644)
PB3 - D7
PB4 - D10 - SS (SPI)
PB5 - D11 - MOSI (SPI)
PB6 - D12 - MISO (SPI)
PB7 - D13 - SCK (SPI)

PC0 - D26 (X) - SCL - (I2C) jumper to A4/A5 (check which)
PC1 - D27 (X) - SDA - (I2C) jumper to A5/A4 (check which)
PC2 - D28 (X)
PC3 - D29 (X)
PC4 - D20 (S)
PC5 - D21 (S)
PC6 - D22 (S)
PC7 - D23 (S)

PD0 - D0 (RX0)
PD1 - D1 (TX0)
PD2 - D2 (INT0 - RX1)
PD3 - D3 (INT1 - TX1)
PD4 - D30 (X)
PD5 - D8
PD6 - D9
PD7 - D31 (X)

I may have D8/D9 swapped, going by the OC1/IPB names.

Don't tell me you've crossed over to the dark side and started using Eagle, or is that just a grab from the Sanguino site?

What do (S) and (X) stand for?


Well, I was using it to get the footprints for an SMD layout, otherwise I wouldn't. Got another fulltime job few weeks ago, reaally sucked up all my free time with the longer drive to & from, had to find a way to save some time & not reinvent all the footprints in expresspcb, especially when the plan is to hand off to someone esle to assemble 25-30 units.

(S) is the pin assignment from the Sanguino pins.c file, (X) is a pin that needs to change because it was needed elsewhere to be shield compatible.

Looks like they can be arbitrarily assigned in here to suit one’s needs, in this case to be compatible and also for differences for the surface mount part.

  pins_arduino.c - pin definitions for the Arduino board
  Part of Arduino / Wiring Lite

  Copyright (c) 2005 David A. Mellis

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.

  This library is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  Lesser General Public License for more details.

  You should have received a copy of the GNU Lesser General
  Public License along with this library; if not, write to the
  Free Software Foundation, Inc., 59 Temple Place, Suite 330,
  Boston, MA  02111-1307  USA

  $Id: pins_arduino.c 254 2007-04-20 23:17:38Z mellis $

#include <avr/io.h>
#include "wiring_private.h"
#include "pins_arduino.h"

// On the Sanguino board, digital pins are also used
// for the analog output (software PWM).  Analog input
// pins are a separate set.

//                   +---\/---+
//  INT0 (D 0) PB0  1|        |40  PA0 (AI 0 / D31)
//  INT1 (D 1) PB1  2|        |39  PA1 (AI 1 / D30)
//  INT2 (D 2) PB2  3|        |38  PA2 (AI 2 / D29)
//   PWM (D 3) PB3  4|        |37  PA3 (AI 3 / D28)
//   PWM (D 4) PB4  5|        |36  PA4 (AI 4 / D27)
//  MOSI (D 5) PB5  6|        |35  PA5 (AI 5 / D26)
//  MISO (D 6) PB6  7|        |34  PA6 (AI 6 / D25)
//   SCK (D 7) PB7  8|        |33  PA7 (AI 7 / D24)
//             RST  9|        |32  AREF
//             VCC 10|        |31  GND 
//             GND 11|        |30  AVCC
//           XTAL2 12|        |29  PC7 (D 23)
//           XTAL1 13|        |28  PC6 (D 22)
//  RX0 (D 8)  PD0 14|        |27  PC5 (D 21) TDI
//  TX0 (D 9)  PD1 15|        |26  PC4 (D 20) TDO
//  RX1 (D 10) PD2 16|        |25  PC3 (D 19) TMS
//  TX1 (D 11) PD3 17|        |24  PC2 (D 18) TCK
//  PWM (D 12) PD4 18|        |23  PC1 (D 17) SDA
//  PWM (D 13) PD5 19|        |22  PC0 (D 16) SCL
//  PWM (D 14) PD6 20|        |21  PD7 (D 15) PWM
//                   +--------+

#define PA 1
#define PB 2
#define PC 3
#define PD 4

// these arrays map port names (e.g. port B) to the
// appropriate addresses for various functions (e.g. reading
// and writing)
const uint8_t PROGMEM port_to_mode_PGM[] =

const uint8_t PROGMEM port_to_output_PGM[] =

const uint8_t PROGMEM port_to_input_PGM[] =

const uint8_t PROGMEM digital_pin_to_port_PGM[] =
	PB, /* 0 */
	PD, /* 8 */
	PC, /* 16 */
	PA, /* 24 */
	PA  /* 31 */

const uint8_t PROGMEM digital_pin_to_bit_mask_PGM[] =
	_BV(0), /* 0, port B */
	_BV(0), /* 8, port D */
	_BV(0), /* 16, port C */
	_BV(7), /* 24, port A */

const uint8_t PROGMEM digital_pin_to_timer_PGM[] =
	NOT_ON_TIMER, 	/* 0  - PB0 */
	NOT_ON_TIMER, 	/* 1  - PB1 */
	NOT_ON_TIMER, 	/* 2  - PB2 */
	TIMER0A,     	/* 3  - PB3 */
	TIMER0B, 		/* 4  - PB4 */
	NOT_ON_TIMER, 	/* 5  - PB5 */
	NOT_ON_TIMER, 	/* 6  - PB6 */
	NOT_ON_TIMER,	/* 7  - PB7 */
	NOT_ON_TIMER, 	/* 8  - PD0 */
	NOT_ON_TIMER, 	/* 9  - PD1 */
	NOT_ON_TIMER, 	/* 10 - PD2 */
	NOT_ON_TIMER, 	/* 11 - PD3 */
	TIMER1B,     	/* 12 - PD4 */
	TIMER1A,     	/* 13 - PD5 */
	TIMER2B,     	/* 14 - PD6 */
	TIMER2A,     	/* 15 - PD7 */
	NOT_ON_TIMER, 	/* 16 - PC0 */
	NOT_ON_TIMER,   /* 17 - PC1 */
	NOT_ON_TIMER,   /* 18 - PC2 */
	NOT_ON_TIMER,   /* 19 - PC3 */
	NOT_ON_TIMER,   /* 20 - PC4 */
	NOT_ON_TIMER,   /* 21 - PC5 */
	NOT_ON_TIMER,   /* 22 - PC6 */
	NOT_ON_TIMER,   /* 23 - PC7 */
	NOT_ON_TIMER,   /* 24 - PA0 */
	NOT_ON_TIMER,   /* 25 - PA1 */
	NOT_ON_TIMER,   /* 26 - PA2 */
	NOT_ON_TIMER,   /* 27 - PA3 */
	NOT_ON_TIMER,   /* 28 - PA4 */
	NOT_ON_TIMER,   /* 29 - PA5 */
	NOT_ON_TIMER,   /* 30 - PA6 */
	NOT_ON_TIMER   /* 31 - PA7 */

plan is to hand off to someone esle to assemble 25-30 units.

Please let me know how you go with that, I'm interested in doing something similar.

I've never really looked at a pins file before, it looks like a simple set of lookup tables for mapping so that would be easy to replicate.

I'm not sure what the digital_pin_to_timer_PGM table is for, presumably analogueWrite needs to know if a pin is on a hardware PWM or something.

Now as I read those tables D0 is on PORTB:0, yet your table (and the schematic) shows it on PORTD:0. Is that correct?


DO on PB:0 - yes, I read it that way also.
I don't know if the pins can be arbitrarily assigned or not. Not fully understanding what I am looking at yet.
Well, I guess not so arbitrary as I would want D0 = Rx to be on the actual hardware pin, which is PD:0, so some things are set in stone.

Build plan - local company about an hour south of here to make the PWB and do the assembly, preferring all SMD if possible, trying to make that happen. Need to consider programming blanks uCs on board too to get get bootloader in. Lots of little things to consider.

Anyway, off to bed, more tomorrow night ...

I don't know if the pins can be arbitrarily assigned or not.

That seems to be the case. The Arduino pin # is used to index into various tables that give the port address and bit number, so any valid port/pin should be OK.

So as long as your docs and PCB make it clear what physical pin is what Arduino logical pin you should be right.


I am designing what is basically an oversized duemilanove, using an surface mount atmega644p in place of the atmega328p, and adding extra board area for some other parts. (644P for the 2nd serial port and more memory)
Is there a way to make this compatible with existing shields?

Like this?

They seem to have ignored the i2c pins WRT the shield and taken them to another header.


Exactly! Looks like I was on the right track for assigning pins.
Will borrow some of that, some of the duemilanove, getting some unique stuff added, and ending up with a board that is larger, somewhere near the eagele 80x100mm size limit.

@GrayNomad - I2C, indeed. I plan to have pin fields as discussed last night to accomodate that.