Arduino variant, how do I add more pins

I've made a custom board based on the Arduino Mega 2560. I've used pins on my board that is not used on the Arduino board (for example all the pins on PORT J)

How do I add the PORT J pins to the Arduino code?

I looked at the pins_arduino.h file but is not 100% sure if this is the correct place. I'm not sure what to do.

Any help will be appreciated.

Thank you

#ifdef ARDUINO_MAIN

const uint16_t PROGMEM port_to_mode_PGM[] = {
	NOT_A_PORT,
	(uint16_t) &DDRA,
	(uint16_t) &DDRB,
	(uint16_t) &DDRC,
	(uint16_t) &DDRD,
	(uint16_t) &DDRE,
	(uint16_t) &DDRF,
	(uint16_t) &DDRG,
	(uint16_t) &DDRH,
	 NOT_A_PORT;
	(uint16_t) &DDRJ, // ddr J is already defined
	(uint16_t) &DDRK,
	(uint16_t) &DDRL,
};

const uint16_t PROGMEM port_to_output_PGM[] = {
	NOT_A_PORT,
	(uint16_t) &PORTA,
	(uint16_t) &PORTB,
	(uint16_t) &PORTC,
	(uint16_t) &PORTD,
	(uint16_t) &PORTE,
	(uint16_t) &PORTF,
	(uint16_t) &PORTG,
	(uint16_t) &PORTH,
	NOT_A_PORT,
	(uint16_t) &PORTJ, // port J is already defined
	(uint16_t) &PORTK,
	(uint16_t) &PORTL,
};

const uint16_t PROGMEM port_to_input_PGM[] = {
	NOT_A_PIN,
	(uint16_t) &PINA,
	(uint16_t) &PINB,
	(uint16_t) &PINC,
	(uint16_t) &PIND,
	(uint16_t) &PINE,
	(uint16_t) &PINF,
	(uint16_t) &PING,
	(uint16_t) &PINH,
	NOT_A_PIN,
	(uint16_t) &PINJ, // pin J is already defined
	(uint16_t) &PINK,
	(uint16_t) &PINL,
};

Say you wanted J2 to J7 to be digital 70 to digital 75, you would change the following:

#define NUM_DIGITAL_PINS            76

...
...

const uint8_t PROGMEM digital_pin_to_port_PGM[] = {
	// PORTLIST		
	// -------------------------------------------		
...	
	PK	, // PK 6 ** 68 ** A14	
	PK	, // PK 7 ** 69 ** A15	
	PJ	, // PJ 2 ** 70 ** D70	
	PJ	, // PJ 3 ** 71 ** D71	
	PJ	, // PJ 4 ** 72 ** D72	
	PJ	, // PJ 5 ** 73 ** D73	
	PJ	, // PJ 6 ** 74 ** D74	
	PJ	, // PJ 7 ** 75 ** D75	
};

const uint8_t PROGMEM digital_pin_to_bit_mask_PGM[] = {
	// PIN IN PORT		
	// -------------------------------------------		
...
	_BV( 5 )	, // PK 5 ** 67 ** A13	
	_BV( 6 )	, // PK 6 ** 68 ** A14	
	_BV( 7 )	, // PK 7 ** 69 ** A15	
	_BV( 2 )	, // PJ 2 ** 70 ** D70	
	_BV( 3 )	, // PJ 3 ** 71 ** D71	
	_BV( 4 )	, // PJ 4 ** 72 ** D72	
	_BV( 5 )	, // PJ 5 ** 73 ** D73	
	_BV( 6 )	, // PJ 6 ** 74 ** D74	
	_BV( 7 )	, // PJ 7 ** 75 ** D75	
};

const uint8_t PROGMEM digital_pin_to_timer_PGM[] = {
	// TIMERS		
	// -------------------------------------------		
...
	NOT_ON_TIMER	, // PK 4 ** 66 ** A12	
	NOT_ON_TIMER	, // PK 5 ** 67 ** A13	
	NOT_ON_TIMER	, // PK 6 ** 68 ** A14	
	NOT_ON_TIMER	, // PK 7 ** 69 ** A15	
	NOT_ON_TIMER	, // PJ 2 ** 70 ** D70	
	NOT_ON_TIMER	, // PJ 3 ** 71 ** D71	
	NOT_ON_TIMER	, // PJ 4 ** 72 ** D72	
	NOT_ON_TIMER	, // PJ 5 ** 73 ** D73	
	NOT_ON_TIMER	, // PJ 6 ** 74 ** D74	
	NOT_ON_TIMER	, // PJ 7 ** 75 ** D75		
};

Take a look at the overallstructure, and create yourself a new Variant.
Copy the 2560 files there.
In pins_arduino.h, there are several arrays where the pins are defined.
One array lists the ports used, these will be the pins, listed in what ends up as D0 to Dxx.
Next is the pins within the ports.
Next is whether the pins have timers associated with them.

There might be more. I haven't dug into the 1.0 format in a while, and then maniacbug was able to get the files finished up for a 1284 chip.

You'll probably need a new entry for boards.txt also to call out your new variant to map in your new pins_arduino.h. And possiby a new entry on avrdude.conf, altho maybe not if boards.txt calls out the same chip type.

Cool! Thanks guys!

1.) I've added the new pins in a custom header file "..\hardware\arduino\variants\custom\pins_arduino.h"
2.) I copied the board settings for the Arduino Mega 2560 and created a custom board entry
3.) I've updated the pin numbers in my sketch

##############################################################

custom2560.name=Custom 2560

custom2560.upload.protocol=stk500v2
custom2560.upload.maximum_size=258048
custom2560.upload.speed=115200

custom2560.bootloader.low_fuses=0xFF
custom2560.bootloader.high_fuses=0xD8
custom2560.bootloader.extended_fuses=0xFD
custom2560.bootloader.path=stk500v2
custom2560.bootloader.file=stk500boot_v2_mega2560.hex
custom2560.bootloader.unlock_bits=0x3F
custom2560.bootloader.lock_bits=0x0F

custom2560.build.mcu=atmega2560
custom2560.build.f_cpu=16000000L
custom2560.build.core=arduino
custom2560.build.variant=custom

But when I compile my sketch I get the following errors for each new pin:

error: 'DIO76_DDR' was not declared in this scope
error: 'DIO76_PIN' was not declared in this scope
error: 'DIO76_WPORT' was not declared in this scope

etc.

So somewhere there is a mapping from the arduino pins to the actual avr pins but I dont know where.

Any ideas?

Ok, the mapping is located in fastio.h.

I had to add the following for each extra pin used on my device:

#if defined (__AVR_ATmega1280__) || defined (__AVR_ATmega2560__)
.
.
.
#define DIO70_PIN		PINJ2
#define DIO70_RPORT	        PINJ2
#define DIO70_WPORT	        PORTJ
#define DIO70_DDR		DDRJ
#define DIO70_PWM		NULL
.
.
.

yet another file.
I wonder if there is a writeup somewhere explaining this whole variant's thing so its not so hit & miss.

Here is the link to maniacbug's files for the 1284 variant. You can use his files as a basis of how many and what files you will need for your board.

I think that could be a good start.

I don't see a fastio.h anywhere. Might be some other subtleties involved too.

Hello, I have related question. I use ATtiny 44/45/84/85 variants from http://hlt.media.mit.edu/?p=1695 - all works as expected. Although I would like to use SPI library. These chips have USI instead of SPI, by reading specs it is slightly different. I think I will be able to make version of SPI library working on these chips. My question is - where should I put files? It would be nice if standard Arduinos will use standard SPI and ATtiny USI variant of SPI.

I have ~/Arduino/hardware/attiny folder with "variants" and "boards.txt". I think I can redefine cores/standard/* to modify basic functionality. Is it possible to override extra libraries (as SPI) this way? In the system installation, libraries are above the "hardware" folder and offer no hint about hardware variants.

Other idea about how to achieve this is to create ~/Arduino/libraries/SPI version of the library, hoping it overrides system installation. And #ifdef it to oblivion.

What is the best, or most compatible way to do it?

Looks like the ATTiny25/45/85 hardware will support SPI:

Port B, Bit 2 – SCK/ADC1/T0/USCK/SCL/INT0/PCINT2
• SCK: Master Clock output, Slave Clock input pin for SPI channel. When the SPI is enabled as
a Slave, this pin is configured as an input regardless of the setting of DDB2. When the SPI is
enabled as a Master, the data direction of this pin is controlled by DDPB2. When the pin is
forced by the SPI to be an input, the pull-up can still be controlled by the PORTB2 bit.

Port B, Bit 1 – MISO/AIN1/OC0B/OC1A/DO/PCINT1
• MISO: Master Data input, Slave Data output pin for SPI channel. When the SPI is enabled as
a Master, this pin is configured as an input regardless of the setting of DDB1. When the SPI
is enabled as a Slave, the data direction of this pin is controlled by DDB1. When the pin is
forced by the SPI to be an input, the pull-up can still be controlled by the PORTB1 bit.

Port B, Bit 0 – MOSI/AIN0/OC0A/OC1A/DI/SDA/AREF/PCINT0
• MOSI: SPI Master Data output, Slave Data input for SPI channel. When the SPI is enabled as
a Slave, this pin is configured as an input regardless of the setting of DDB0. When the SPI is
enabled as a Master, the data direction of this pin is controlled by DDB0. When the pin is
forced by the SPI to be an input, the pull-up can still be controlled by the PORTB0 bit.

CrossRoads:
Looks like the ATTiny25/45/85 hardware will support SPI:

Yes it does, but the hardware is different. ATmega 328 has dedicated SPI hardware, ATtiny have USI, which can be configured as SPI (without !SS pin) or i2c. So 328's code for SPI will not work on these.

To code it should not be a problem. Just different port names and setup. My question is how to make the code most portable, so other can use it.