Pin mapping file tutorial ?

Hi, I have been looking around for a tutorial or explanation of the arduino pin mapping file.... Ie what all the various sections do and how to go about editing it for a custom MCU pin arrangement?

Anyone know of anything out there in the wild ... Or a quick run down of the anatomy of the pin map file would be great . Thanks for any help.

What do you mean by "pin map file", please?

Are you talking about pins_arduino.h?

Because I think the comments do a good job of showing what ports on the AVR chip map to what pins on the Arduino board.

It is probably helpful to go look at analogRead, digitalWrite, etc to see how the arrays are used.

Hi, pins_arduino.h - that's the one :-)

I can see how bits of the file work but some of it remains a mystery. Let's say I wanted to swap analog pin 0 and analog pin 5.... what would I need to change?

Let's say I wanted to swap analog pin 0 and analog pin 5.... what would I need to change?

Let's say I wouldn't do it in the library, I'd do it in my sketch.

I can see how bits of the file work but some of it remains a mystery.

We don't know what bits remain a mystery or why.

point5: Let's say I wanted to swap analog pin 0 and analog pin 5.... what would I need to change?

What do you mean, swap them? To what purpose?

"Are you talking about pins_arduino.h?

Because I think the comments do a good job of showing what ports on the AVR chip map to what pins on the Arduino board."

These comments? These are all the comments in the "standard" pins_arduino.h

I didn't find them very helpful at all.

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

// ATMEL ATMEGA8 & 168 / ARDUINO
//
//                  +-\/-+
//            PC6  1|    |28  PC5 (AI 5)
//      (D 0) PD0  2|    |27  PC4 (AI 4)
//      (D 1) PD1  3|    |26  PC3 (AI 3)
//      (D 2) PD2  4|    |25  PC2 (AI 2)
// PWM+ (D 3) PD3  5|    |24  PC1 (AI 1)
//      (D 4) PD4  6|    |23  PC0 (AI 0)
//            VCC  7|    |22  GND
//            GND  8|    |21  AREF
//            PB6  9|    |20  AVCC
//            PB7 10|    |19  PB5 (D 13)
// PWM+ (D 5) PD5 11|    |18  PB4 (D 12)
// PWM+ (D 6) PD6 12|    |17  PB3 (D 11) PWM
//      (D 7) PD7 13|    |16  PB2 (D 10) PWM
//      (D 8) PB0 14|    |15  PB1 (D 9) PWM
//                  +----+
//
// (PWM+ indicates the additional PWM pins on the ATmega168.)

// ATMEL ATMEGA1280 / ARDUINO
//
// 0-7 PE0-PE7   works
// 8-13 PB0-PB5  works
// 14-21 PA0-PA7 works 
// 22-29 PH0-PH7 works
// 30-35 PG5-PG0 works
// 36-43 PC7-PC0 works
// 44-51 PJ7-PJ0 works
// 52-59 PL7-PL0 works
// 60-67 PD7-PD0 works
// A0-A7 PF0-PF7
// A8-A15 PK0-PK7

// these arrays map port names (e.g. port B) to the
// appropriate addresses for various functions (e.g. reading
// and writing)

    // on the ATmega168, digital pin 3 has hardware pwm

    // on the ATmega168, digital pins 5 and 6 have hardware pwm

Hi,

What I’m hoping to do is edit the pins_arduino.h file so that I can correctly map the pins of an Atmega 1284p project I’m tinkering with. At the moment some of my pins are mapped correctly for my setup but I need to make some changes to the pins_arduino.h file to reflect some differences. The swapping of A5 & A0 is just an example for the purposes of illustration. There are several sections to the pins_arduino.h, I guess I’m looking for an explanation of the file contents or an example of what to change if pins need swapping. Perhaps I will post a copy of pins_arduino.h commented with questions later. Thanks again.

point5: Hi,

What I'm hoping to do is edit the pins_arduino.h file so that I can correctly map the pins of an Atmega 1284p project I'm tinkering with. At the moment some of my pins are mapped correctly for my setup but I need to make some changes to the pins_arduino.h file to reflect some differences. The swapping of A5 & A0 is just an example for the purposes of illustration. There are several sections to the pins_arduino.h, I guess I'm looking for an explanation of the file contents or an example of what to change if pins need swapping. Perhaps I will post a copy of pins_arduino.h commented with questions later. Thanks again.

Tutorials and simple examples don't exist for many, many things. I suggest trial and error, staring at the comments and variable names for a while, or looking at the arduino source code.

Have you seen http://maniacbug.wordpress.com/2011/11/27/arduino-on-atmega1284p-4/ ? There are ready prepared pins files available.

Ah yes, maniacbug is the inspiration to this project - I just need to tweak his pins_arduino.h pin map file and keen to understand what I am doing :-)

Okidoki… there is actually quite a lot in the pins_arduino.h file that I don’t understand how to change to achieve a modified pin map… the first lot of code below is what I am trying to achieve and the second lot is the pins_arduino.h file I am starting with - I am hoping to find out what do I need to tinker with to achieve the end result and why? I figured there is so much info out there about Arduino that hacking the pins_arduino.h file would be explained somewhere but perhaps its not?

Pin map that I am hoping to implement:

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

Starting point:

#ifndef Pins_Arduino_h
#define Pins_Arduino_h

#include <avr/pgmspace.h>

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

/*
   PCINT15-8: D7-0  : bit 1
   PCINT31-24: D15-8  : bit 3
   PCINT23-16: D23-16 : bit 2
   PCINT7-0: D31-24   : bit 0
   */

#define NUM_DIGITAL_PINS            31
#define NUM_ANALOG_INPUTS           8
//#define analogInputToDigitalPin(p)  ((p < NUM_ANALOG_INPUTS) ? (p) + 24 : -1)
#define analogInputToDigitalPin(p)  ((p < NUM_ANALOG_INPUTS) ? (p) + 24 : -1)

#define digitalPinToAnalogPin(p)    ( (p) >= 24 && (p) <= 31 ? ((p) < 30 ? 5-((p)-24) : ((p) - 24)) : (((p)<=5) ? 5-(p) : (((p)<=7) ? (p) : -1 )) )
#define digitalPinHasPWM(p)         ((p) == 4 || (p) == 5 || (p) == 6 || (p) == 7 || (p) == 10 || (p) == 12 || (p) == 13 || (p) == 15)

static const uint8_t SS   = 10;
static const uint8_t MOSI = 11;
static const uint8_t MISO = 12;
static const uint8_t SCK  = 13;

static const uint8_t SDA = 17;
static const uint8_t SCL = 16;
static const uint8_t LED = 23;

static const uint8_t A0 = 24;
static const uint8_t A1 = 25;
static const uint8_t A2 = 26;
static const uint8_t A3 = 27;
static const uint8_t A4 = 28;
static const uint8_t A5 = 29;
static const uint8_t A6 = 30;
static const uint8_t A7 = 31;

#define digitalPinToPCICR(p)    ifpin(p,&PCICR,(uint8_t *)0)
#define digitalPinToPCICRbit(p) ifpin(p,digital_pin_to_pcint[p] >> 3,(uint8_t *)0)
#define digitalPinToPCMSK(p)    ifpin(p,__pcmsk[digital_pin_to_pcint[]],(uint8_t *)0)
#define digitalPinToPCMSKbit(p) ifpin(p,digital_pin_to_pcint[p] & 0x7,(uint8_t *)0)

#ifdef ARDUINO_MAIN

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

const uint8_t digital_pin_to_pcint[NUM_DIGITAL_PINS] =
{
  24, // D0 PD0
  25, // D1 PD1
  26, // D2 PD2
  27, // D3 PD3
  28, // D4 PD4
  29, // D5 PD5
  30, // D6 PD6
  31, // D7 PD7
  8, // D8 PB0
  9, // D9 PB1
  12, // D10 PB4
  13, // D11 PB5
  14, // D12 PB6
  15, // D13 PB7
  10, // D14 PB2
  11, // D15 PB3
  16, // D16 PC0
  17, // D17 PC1
  18, // D18 PC2
  19, // D19 PC3
  20, // D20 PC4
  21, // D21 PC5
  22, // D22 PD6
  23, // D23 PC7

  5, // D31 PA7
  4, // D30 PA6
  3, // D24 PA5
  2, // D25 PA4
  1, // D26 PA3
  0, // D27 PA2
  6, // D28 PA1
  7, // D29 PA0

//  7, // D31 PA7
//  6, // D30 PA6
//  0, // D24 PA5
//  1, // D25 PA4
//  2, // D26 PA3
//  3, // D27 PA2
//  4, // D28 PA1
//  5, // D29 PA0
};

const uint16_t __pcmsk[] = 
{
  (uint16_t)&PCMSK0, 
  (uint16_t)&PCMSK1, 
  (uint16_t)&PCMSK2, 
  (uint16_t)&PCMSK3
};

// these arrays map port names (e.g. port B) to the
// appropriate addresses for various functions (e.g. reading
// and writing)
const uint16_t PROGMEM port_to_mode_PGM[] =
{
	NOT_A_PORT,
	(uint16_t) &DDRA,
	(uint16_t) &DDRB,
	(uint16_t) &DDRC,
	(uint16_t) &DDRD,
};

const uint16_t PROGMEM port_to_output_PGM[] =
{
	NOT_A_PORT,
	(uint16_t) &PORTA,
	(uint16_t) &PORTB,
	(uint16_t) &PORTC,
	(uint16_t) &PORTD,
};

const uint16_t PROGMEM port_to_input_PGM[] =
{
	NOT_A_PORT,
	(uint16_t) &PINA,
	(uint16_t) &PINB,
	(uint16_t) &PINC,
	(uint16_t) &PIND,
};

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

const uint8_t PROGMEM digital_pin_to_bit_mask_PGM[] =
{
	_BV(0), /* 0, port D */
	_BV(1),
	_BV(2),
	_BV(3),
	_BV(4),
	_BV(5),
	_BV(6),
	_BV(7),
	_BV(0), /* 8, port B */
	_BV(1),
	_BV(4),
	_BV(5),
	_BV(6),
	_BV(7),
	_BV(2),
	_BV(3),
	_BV(0), /* 16, port C */
	_BV(1),
	_BV(2),
	_BV(3),
	_BV(4),
	_BV(5),
	_BV(6),
	_BV(7),
	_BV(5), /* 24, port A */
	_BV(4),
	_BV(3),
	_BV(2),
	_BV(1),
	_BV(0),
	_BV(6),
	_BV(7)
};

const uint8_t PROGMEM digital_pin_to_timer_PGM[] =
{
	NOT_ON_TIMER, 	/* 1 - PD0 */
	NOT_ON_TIMER, 	/* 2 - PD1 */
	NOT_ON_TIMER, 	/* 3 - PD2 */
	NOT_ON_TIMER, 	/* 4 - PD3 */
	TIMER1B,     	/* 5 - PD4 */
	TIMER1A,     	/* 6 - PD5 */
	TIMER2B,     	/* 7 - PD6 */
	TIMER2A,     	/* 8 - PD7 */

	NOT_ON_TIMER, 	/* 8  - PB0 */
	NOT_ON_TIMER, 	/* 9  - PB1 */
	TIMER0B, 	/* 10 - PB4 */
	NOT_ON_TIMER, 	/* 11 - PB5 */
	TIMER3A, 	/* 12 - PB6 */
	TIMER3B,	/* 13 - PB7 */
	NOT_ON_TIMER, 	/* 14 - PB2 */
	TIMER0A,     	/* 15 - PB3 */

	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 */
};

#endif // ARDUINO_MAIN

#endif // Pins_Arduino_h
// vim:ai:cin:sts=2 sw=2 ft=cpp

Hi, just wondering if anyone has any pointers to help me head off in the rict direction on this :-) Thanks & Cheers.

See if the diffs attached to http://code.google.com/p/arduino/issues/detail?id=1055 help any...

this post has been read 4500 times. has anyone found a tutorial?

Nope. It's supposed to be obvious. If you want to use an existing core, you need to implement all of the "digitalPinTo" and similar macros that are annoyingly split between variants/*/pins_arduino.h and cores/Arduino.h Exactly how you do it is up to you. Currently, some are algorithmic:

#define digitalPinHasPWM(p)         ((p) == 9 || (p) == 10 || (p) == 11)

And some are table driven:

// From Arduino.h:
#define digitalPinToBitMask(P) ( pgm_read_byte( digital_pin_to_bit_mask_PGM + (P) ) )

//From pins_arduino.h:
const uint8_t PROGMEM digital_pin_to_bit_mask_PGM[] = {
    _BV(0), /* 0, port D */
    _BV(1),
    _BV(2),
  :
    _BV(0), /* 8, port B */
    _BV(1),
    :
    _BV(0), /* 14, port C */
    _BV(1),
  :
};

Other platforms are more consistently table-driven (HUGE tables. Sigh.)

Some of the macros are used by third-party libraries are are thus globally "important", while others only need to be consistent between the definitions and the particular core functions that use them. For now. You can probably assume that the macros defined in Arduino.h are more important than the ones only used in pins_arduino.h. For now. Again.

Swapping some pins means switching the values in any table and fixing or re-writing any of the algorithm definitions that involve that pin.