seeeduino mega : 16 extra digital i/o

Hi Steve;

I’ve been testing out my new Seeeduino Mega sense it arrived earlier this week. I too was not real clear on the extra I/O pins Vs the Ardunio Mega. What I’ve come to understand is that Arduino mega digital pins 0 to 69 are the same as for the Seeduino and that digital pins 54-69 are the same pins as analog pins 0-15. The extra I/O pins that the Seeeduino Mega brings out are not mapped out with pin aliases in the Arduino core libraries. So the only way to access these additional I/O pins is via direct port access using direction ports and masks to set or reset or read the actual pins. The schematic that Seeeduino published in my other thread on the mega shows the port/bit number of the additional pins.

Bottom line, it’s nice that the Seeeduino folks brought out those additional I/O pins, however the Arduino library does not support those pins directly using the standard digitalwrite/read functions.

At least that is my take on the topic to date.

Lefty

Ok, sounds tedious, but wouldn’t it be possible to write a function to take out the tedium? I have no idea how to do what you just said, but it seems like if it’s possible it should be possible to make it a bit more user friendly through a library extension, yeah?

I guess you could write a conversion function that would convert new higher digital pin numbers and mimic what the arduino digitalwrite() and digitalread() functions due. You could call them extendedwrite() and extendedread() :laughing:

Anyway below is a write up from the Arduino site on how direct port access works to give you an idea of what is involved. I’m more of a hardware guy then software so I can’t just whip you out the functions :wink:

It would be a pretty unusual application that would require the extra I/O pins I suspect, but it’s nice to know they are available. I decided not to solder header connectors to those extra pins at this time.

arduino.cc/en/Reference/PortManipulation

Lefty

Hello,
Can use the GPIO register to config the extern 16 IOs at this moment.
And we may modify the internal file(Pin_arduino.c) to match the IOs, if possible.
PH2 -->70;
PH7 -->71;
.
.
.
PE2 -->85.
Thanks
Albert

Can someone from seeedstudio post some example code for how I could read and write to these extra GPIO pins? This will absolutely decide it for me and I’ll order up a seeeduino mega immediately after. My project is super hungry for more i/o :slight_smile: flickr.com/photos/stevecoole … 158437796/

i should say “I will order one mega immediately and can require them for my project when I start selling them.”

Steve;

Here is a simple example of turning on and off the first and last I/O bits of the extended bits that the Seeeduino Mega makes avalible.

[code]/*

  • Toggle extended I/O bits 70 and 86 on and off for Seeeduino Mega board
  • Also added an example of a digital input reading the state of digital pin 71
    */

int switchstate; // variable to hold value of digital input pin 70

void setup() // run once, when the sketch starts
{

DDRH |= 0x04; // sets the digital pin 70 to output, pin 70 is bit 2 of port H
DDRE |= 0x04; // sets the digital pin 86 to output, pin 86 is bit 2 of port E

DDRH &= 0x7f; // sets the digital pin 71 to input, pin 71 is bit 7 of port H
}

void loop() // run over and over again
{

PORTH |= 0x04; // sets pin 70 high
PORTE |= 0x04; // sets pin 86 high
delay(1000); // waits for a second

PORTH &= 0xfb; // sets pin 70 low
PORTE &= 0xfb; // sets pin 86 low
delay(1000); // waits for a second

switchstate = PINH & 0x80; // switchstate is non zero if digital input 71 is high, else it’s zero if input 71 is low
}
[/code]

Lefty

I was researching the Arduino Mega while searching for a microcontroller board on which I’d like to base a project, and came upon the Seeeduino Mega. Then I got all excited because of the extra digital ports without any futzing about with matrices or multiplexing. Then I saw this thread. Hopefully someone can answer some questions I have re: the Seeduino Mega’s extra digital ins and outs.

So, this is what I have gotten out of this discussion:

1: The Seeeduino Mega has 16 extra digi i/o pins, but these pins are difficult to use, and surely won’t be supported by the stantard Firmata sketch (which isn’t functional for the normal Arduino Mega, anyhow, according to info on the Arduino forum).

2: These extra 16 digi i/o’s cannot be used simultaneously with the 16 analog pins that they share traces/microcontroller pins with. Or can they?

3: The standard Arduino Mega may be able to do the same thing as the Seeeduino Mega and produce 16 more usable digital i/o’s; it would just require a firmware revision and some extra off-board wiring? Or is there more work which would have to be done to access these pins? …Or is this completely impossible on the original Mega? The way the posts above are worded, it seems the analog pins 0-15 share circuit board traces with the digital pins 54-69. which means that those digital pins are just duplicates, as you would get from stacked headers sprouting off of a shield on an Arduino. This theory would further confirm my suspicion that you can’t use the extra 16 digital pins at the same time as the analog pins.

So anyhow, could someone with experience confirm or deny any of this? I really want to purchase a Seeeduino to base a prototype of a production piece off of, but I can’t until I have this stuff figured out.

Cheers,
Scott

Thanks for the run-down, Leftyretro! You are right, I was confusing the pins you were discussing above. I was aware that the analog pins could be used as digital as well, so talking about those in the same thread as the 16 extra digital i/o’s on the Seeeduino Mega crossed my wires a bit :blush:

…but it is crystal clear now!

Cheers!

-Scott

Has anyone hacked a version of pins_arduino as Albert suggested they might to make those pins easier, or done a seeeduino expansion library that exposes an extended interface with an extended functions to do this. If no one has I may start asking questions to figure it out, but it seems that if it is this straight forward, from Albert’s post at least he implies it is. I figure someone must have done this. I can see the argument going either way, but given the unfortunate choice by the arduino folks to not expose the pins and concatenate the analog ports after the digital ports, maybe a separate library that allow access to the extra pins at the end of the name space. (Or figuring out there mapping scheme and adding them after the analog ports so that compatibility is not completely lost. The software does not scare me, but I don’t fully understand the low levels of the libraries and this chip so I am not going spite out changes quickly. It also seems like it ought to be a team effort if the information can become clear enough.

Okay a quick scan of the pins_arduino.c file indicates to me that at a minimum I would need to modify
These three list

digital_pin_to_port_PGM
digital_pin_to_bit_mask_PGM
digital_pin_to_timer_PGM

So the last one is easy, add 16 NOT_ON_TIMER entries.

I am not understanding the format of the digital_to_bitmask_PGM I am guessing it is the bit in the port
register associated with the pin. I am guessing that the register is defined in digital_pin_to_port data structure. If that is the case this is any easy extension if someone can tell me the 16 correct port registers for the 16 unmapped signals. Then I can add the P*, to the first, the correct bits for the second, and declare no timers in the third. Is this all there is to it, or am I missing something. Also can someone more schooled in the Arduino doctrine suggest which term I should ifdef this on and which file I need to declare the existence of this new option in I would appreciate it. Then I will push at the Arduino folks to consider adding it.

If I am missing something please tell me what it is, but it seem like it ought to be very straight forward.
From my limited reading of the board file it would appear that I need to add

PH,
PH,
PJ,
PJ,
PJ,
PJ,
PJ,
PJ,
PD,
PD,
PD,
PG,
PG,
PE,
PE,
PE

and for the bit values
_BV(2),
_BV(7),
_BV(2),
_BV(3),
_BV(4),
_BV(5),
_BV(6),
_BV(7),
_BV(4),
_BV(5),
_BV(6),
_BV(4),
_BV(3),
_BV(7),
_BV(6),
_BV(2)

Albert, or some one else who is more of a hardware type than me, is this correct? Should I be adding a timer to some of these pins for pwm? Any other things to consider?

Rich;

I don’t believe anyone has taken on the task of mapping the additional 16 digital pins into the Arduino IDE core library. It would be really cool if you can, I know the task is a little more software intensive then I felt I could handle when I looked at those library files after first getting my Seeeduino Mega. I’m more comfortable with the hardware side of these things. I did review your posted lists and I do think you correctly listed the correct ports and their bit positions for the additional 16 pins.

I think a few of the extra pins do have timers associated with them, but it’s probably something you would have to research better with the AVR 1280 datasheet: atmel.com/dyn/resources/prod … oc2549.pdf

So while I’m not up to the task of writing the code, I would be more then happy to test any changed IDE core files you want and report back.

I thought about this issues back whenever, and decided that if I really ever needed to access these extra pins I could write simple functions that would utilize the direct port statements to get to them.

Last point would be don’t be too disappointed that if you get it all working that the ‘official’ Arduino core team does not see fit to include it into an official IDE release, they may feel it’s a too vendor specific change :unamused:

Lefty

I read the chip spec, but I did not find any PWM timer settings associate with the 16 additional Digital outs. I am going to add them after the analog outs for the moment, but I will entertain arguments that they should precede them. This way a code for a arduino mega will be compatable at the bit lvl with this change.

When I get a free moment or two I will test the changes, unless someone shows up with a problem or issue before I get to it. If someone wants to help test it send me a note on the bbs and i will forward the file.

I have a working pins_arduino.c with the additional pins added after the analog in the order I transcribed them from the drawing. My test work, although I am not sure I didn’t reverse the order from what I intended in starting. At this point I am unsure if it is forward or backward. I am also uncertain if I should have placed them before the analog entries or not. I now think I understand the files well enough to do it either way. Anyway if there is a place to put such things please tell me.
I would attach it, but the bbs has an issue with .c files so I can’t

Why don’t you just rename them as .txt files and try attaching?

Lefty

Okay why not, cause I can’t post .txt files either. No idea why, but I get the same "The extension txt is not allowed.

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

Copyright © 2005 David A. Mellis
Modified by Rich Hyde 2009 to add support Seeedmega’s other pins

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
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
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 602 2009-06-01 08:32:11Z dmellis $
*/

#include <avr/io.h>
#include “wiring_private.h”
#include “pins_arduino.h”

// 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

#define PA 1
#define PB 2
#define PC 3
#define PD 4
#define PE 5
#define PF 6
#define PG 7
#define PH 8
#define PJ 10
#define PK 11
#define PL 12

#define REPEAT8(x) x, x, x, x, x, x, x, x
#define BV0TO7 _BV(0), _BV(1), _BV(2), _BV(3), _BV(4), _BV(5), _BV(6), _BV(7)
#define BV7TO0 _BV(7), _BV(6), _BV(5), _BV(4), _BV(3), _BV(2), _BV(1), _BV(0)

#if defined(AVR_ATmega1280)
const uint16_t PROGMEM port_to_mode_PGM[] = {
NOT_A_PORT,
&DDRA,
&DDRB,
&DDRC,
&DDRD,
&DDRE,
&DDRF,
&DDRG,
&DDRH,
NOT_A_PORT,
&DDRJ,
&DDRK,
&DDRL,
};

const uint16_t PROGMEM port_to_output_PGM[] = {
NOT_A_PORT,
&PORTA,
&PORTB,
&PORTC,
&PORTD,
&PORTE,
&PORTF,
&PORTG,
&PORTH,
NOT_A_PORT,
&PORTJ,
&PORTK,
&PORTL,
};

const uint16_t PROGMEM port_to_input_PGM[] = {
NOT_A_PIN,
&PINA,
&PINB,
&PINC,
&PIND,
&PINE,
&PINF,
&PING,
&PINH,
NOT_A_PIN,
&PINJ,
&PINK,
&PINL,
};

const uint8_t PROGMEM digital_pin_to_port_PGM[] = {
// PORTLIST
// -------------------------------------------
PE , // PE 0 ** 0 ** USART0_RX
PE , // PE 1 ** 1 ** USART0_TX
PE , // PE 4 ** 2 ** PWM2
PE , // PE 5 ** 3 ** PWM3
PG , // PG 5 ** 4 ** PWM4
PE , // PE 3 ** 5 ** PWM5
PH , // PH 3 ** 6 ** PWM6
PH , // PH 4 ** 7 ** PWM7
PH , // PH 5 ** 8 ** PWM8
PH , // PH 6 ** 9 ** PWM9
PB , // PB 4 ** 10 ** PWM10
PB , // PB 5 ** 11 ** PWM11
PB , // PB 6 ** 12 ** PWM12
PB , // PB 7 ** 13 ** PWM13
PJ , // PJ 1 ** 14 ** USART3_TX
PJ , // PJ 0 ** 15 ** USART3_RX
PH , // PH 1 ** 16 ** USART2_TX
PH , // PH 0 ** 17 ** USART2_RX
PD , // PD 3 ** 18 ** USART1_TX
PD , // PD 2 ** 19 ** USART1_RX
PD , // PD 1 ** 20 ** I2C_SDA
PD , // PD 0 ** 21 ** I2C_SCL
PA , // PA 0 ** 22 ** D22
PA , // PA 1 ** 23 ** D23
PA , // PA 2 ** 24 ** D24
PA , // PA 3 ** 25 ** D25
PA , // PA 4 ** 26 ** D26
PA , // PA 5 ** 27 ** D27
PA , // PA 6 ** 28 ** D28
PA , // PA 7 ** 29 ** D29
PC , // PC 7 ** 30 ** D30
PC , // PC 6 ** 31 ** D31
PC , // PC 5 ** 32 ** D32
PC , // PC 4 ** 33 ** D33
PC , // PC 3 ** 34 ** D34
PC , // PC 2 ** 35 ** D35
PC , // PC 1 ** 36 ** D36
PC , // PC 0 ** 37 ** D37
PD , // PD 7 ** 38 ** D38
PG , // PG 2 ** 39 ** D39
PG , // PG 1 ** 40 ** D40
PG , // PG 0 ** 41 ** D41
PL , // PL 7 ** 42 ** D42
PL , // PL 6 ** 43 ** D43
PL , // PL 5 ** 44 ** D44
PL , // PL 4 ** 45 ** D45
PL , // PL 3 ** 46 ** D46
PL , // PL 2 ** 47 ** D47
PL , // PL 1 ** 48 ** D48
PL , // PL 0 ** 49 ** D49
PB , // PB 3 ** 50 ** SPI_MISO
PB , // PB 2 ** 51 ** SPI_MOSI
PB , // PB 1 ** 52 ** SPI_SCK
PB , // PB 0 ** 53 ** SPI_SS
PF , // PF 0 ** 54 ** A0
PF , // PF 1 ** 55 ** A1
PF , // PF 2 ** 56 ** A2
PF , // PF 3 ** 57 ** A3
PF , // PF 4 ** 58 ** A4
PF , // PF 5 ** 59 ** A5
PF , // PF 6 ** 60 ** A6
PF , // PF 7 ** 61 ** A7
PK , // PK 0 ** 62 ** A8
PK , // PK 1 ** 63 ** A9
PK , // PK 2 ** 64 ** A10
PK , // PK 3 ** 65 ** A11
PK , // PK 4 ** 66 ** A12
PK , // PK 5 ** 67 ** A13
PK , // PK 6 ** 68 ** A14
PK , // PK 7 ** 69 ** A15
PH , // PH 2 ** 70 **
PH , // PH 7 ** 71 **
PJ , // PJ 2 ** 72 **
PJ , // PJ 3 ** 73 **
PJ , // PJ 4 ** 74 **
PJ , // PJ 5 ** 75 **
PJ , // PJ 6 ** 76 **
PJ , // PJ 7 ** 77 **
PD , // PD 4 ** 78 **
PD , // PD 5 ** 79 **
PD , // PD 6 ** 80 **
PG , // PG 4 ** 81 **
PG , // PG 3 ** 82 **
PE , // PE 7 ** 83 **
PE , // PE 6 ** 84 **
PE // PE 2 ** 85 **
};

const uint8_t PROGMEM digital_pin_to_bit_mask_PGM[] = {
// PIN IN PORT
// -------------------------------------------
_BV( 0 ) , // PE 0 ** 0 ** USART0_RX
_BV( 1 ) , // PE 1 ** 1 ** USART0_TX
_BV( 4 ) , // PE 4 ** 2 ** PWM2
_BV( 5 ) , // PE 5 ** 3 ** PWM3
_BV( 5 ) , // PG 5 ** 4 ** PWM4
_BV( 3 ) , // PE 3 ** 5 ** PWM5
_BV( 3 ) , // PH 3 ** 6 ** PWM6
_BV( 4 ) , // PH 4 ** 7 ** PWM7
_BV( 5 ) , // PH 5 ** 8 ** PWM8
_BV( 6 ) , // PH 6 ** 9 ** PWM9
_BV( 4 ) , // PB 4 ** 10 ** PWM10
_BV( 5 ) , // PB 5 ** 11 ** PWM11
_BV( 6 ) , // PB 6 ** 12 ** PWM12
_BV( 7 ) , // PB 7 ** 13 ** PWM13
_BV( 1 ) , // PJ 1 ** 14 ** USART3_TX
_BV( 0 ) , // PJ 0 ** 15 ** USART3_RX
_BV( 1 ) , // PH 1 ** 16 ** USART2_TX
_BV( 0 ) , // PH 0 ** 17 ** USART2_RX
_BV( 3 ) , // PD 3 ** 18 ** USART1_TX
_BV( 2 ) , // PD 2 ** 19 ** USART1_RX
_BV( 1 ) , // PD 1 ** 20 ** I2C_SDA
_BV( 0 ) , // PD 0 ** 21 ** I2C_SCL
_BV( 0 ) , // PA 0 ** 22 ** D22
_BV( 1 ) , // PA 1 ** 23 ** D23
_BV( 2 ) , // PA 2 ** 24 ** D24
_BV( 3 ) , // PA 3 ** 25 ** D25
_BV( 4 ) , // PA 4 ** 26 ** D26
_BV( 5 ) , // PA 5 ** 27 ** D27
_BV( 6 ) , // PA 6 ** 28 ** D28
_BV( 7 ) , // PA 7 ** 29 ** D29
_BV( 7 ) , // PC 7 ** 30 ** D30
_BV( 6 ) , // PC 6 ** 31 ** D31
_BV( 5 ) , // PC 5 ** 32 ** D32
_BV( 4 ) , // PC 4 ** 33 ** D33
_BV( 3 ) , // PC 3 ** 34 ** D34
_BV( 2 ) , // PC 2 ** 35 ** D35
_BV( 1 ) , // PC 1 ** 36 ** D36
_BV( 0 ) , // PC 0 ** 37 ** D37
_BV( 7 ) , // PD 7 ** 38 ** D38
_BV( 2 ) , // PG 2 ** 39 ** D39
_BV( 1 ) , // PG 1 ** 40 ** D40
_BV( 0 ) , // PG 0 ** 41 ** D41
_BV( 7 ) , // PL 7 ** 42 ** D42
_BV( 6 ) , // PL 6 ** 43 ** D43
_BV( 5 ) , // PL 5 ** 44 ** D44
_BV( 4 ) , // PL 4 ** 45 ** D45
_BV( 3 ) , // PL 3 ** 46 ** D46
_BV( 2 ) , // PL 2 ** 47 ** D47
_BV( 1 ) , // PL 1 ** 48 ** D48
_BV( 0 ) , // PL 0 ** 49 ** D49
_BV( 3 ) , // PB 3 ** 50 ** SPI_MISO
_BV( 2 ) , // PB 2 ** 51 ** SPI_MOSI
_BV( 1 ) , // PB 1 ** 52 ** SPI_SCK
_BV( 0 ) , // PB 0 ** 53 ** SPI_SS
_BV( 0 ) , // PF 0 ** 54 ** A0
_BV( 1 ) , // PF 1 ** 55 ** A1
_BV( 2 ) , // PF 2 ** 56 ** A2
_BV( 3 ) , // PF 3 ** 57 ** A3
_BV( 4 ) , // PF 4 ** 58 ** A4
_BV( 5 ) , // PF 5 ** 59 ** A5
_BV( 6 ) , // PF 6 ** 60 ** A6
_BV( 7 ) , // PF 7 ** 61 ** A7
_BV( 0 ) , // PK 0 ** 62 ** A8
_BV( 1 ) , // PK 1 ** 63 ** A9
_BV( 2 ) , // PK 2 ** 64 ** A10
_BV( 3 ) , // PK 3 ** 65 ** A11
_BV( 4 ) , // PK 4 ** 66 ** A12
_BV( 5 ) , // PK 5 ** 67 ** A13
_BV( 6 ) , // PK 6 ** 68 ** A14
_BV( 7 ) , // PK 7 ** 69 ** A15
_BV(2) , // PH 2 ** 70 **
_BV(7) , // PH 7 ** 71 **
_BV(2) , // PJ 2 ** 72 **
_BV(3) , // PJ 3 ** 73 **
_BV(4) , // PJ 4 ** 74 **
_BV(5) , // PJ 5 ** 75 **
_BV(6) , // PJ 6 ** 76 **
_BV(7) , // PJ 7 ** 77 **
_BV(4) , // PD 4 ** 78 **
_BV(5) , // PD 5 ** 79 **
_BV(6) , // PD 6 ** 80 **
_BV(4) , // PG 4 ** 81 **
_BV(3) , // PG 3 ** 82 **
_BV(7) , // PE 7 ** 83 **
_BV(6) , // PE 6 ** 84 **
_BV(2) , // PE 2 ** 85 **
};

const uint8_t PROGMEM digital_pin_to_timer_PGM[] = {
// TIMERS
// -------------------------------------------
NOT_ON_TIMER , // PE 0 ** 0 ** USART0_RX
NOT_ON_TIMER , // PE 1 ** 1 ** USART0_TX
TIMER3B , // PE 4 ** 2 ** PWM2
TIMER3C , // PE 5 ** 3 ** PWM3
TIMER0B , // PG 5 ** 4 ** PWM4
TIMER3A , // PE 3 ** 5 ** PWM5
TIMER4A , // PH 3 ** 6 ** PWM6
TIMER4B , // PH 4 ** 7 ** PWM7
TIMER4C , // PH 5 ** 8 ** PWM8
TIMER2B , // PH 6 ** 9 ** PWM9
TIMER2A , // PB 4 ** 10 ** PWM10
TIMER1A , // PB 5 ** 11 ** PWM11
TIMER1B , // PB 6 ** 12 ** PWM12
TIMER0A , // PB 7 ** 13 ** PWM13
NOT_ON_TIMER , // PJ 1 ** 14 ** USART3_TX
NOT_ON_TIMER , // PJ 0 ** 15 ** USART3_RX
NOT_ON_TIMER , // PH 1 ** 16 ** USART2_TX
NOT_ON_TIMER , // PH 0 ** 17 ** USART2_RX
NOT_ON_TIMER , // PD 3 ** 18 ** USART1_TX
NOT_ON_TIMER , // PD 2 ** 19 ** USART1_RX
NOT_ON_TIMER , // PD 1 ** 20 ** I2C_SDA
NOT_ON_TIMER , // PD 0 ** 21 ** I2C_SCL
NOT_ON_TIMER , // PA 0 ** 22 ** D22
NOT_ON_TIMER , // PA 1 ** 23 ** D23
NOT_ON_TIMER , // PA 2 ** 24 ** D24
NOT_ON_TIMER , // PA 3 ** 25 ** D25
NOT_ON_TIMER , // PA 4 ** 26 ** D26
NOT_ON_TIMER , // PA 5 ** 27 ** D27
NOT_ON_TIMER , // PA 6 ** 28 ** D28
NOT_ON_TIMER , // PA 7 ** 29 ** D29
NOT_ON_TIMER , // PC 7 ** 30 ** D30
NOT_ON_TIMER , // PC 6 ** 31 ** D31
NOT_ON_TIMER , // PC 5 ** 32 ** D32
NOT_ON_TIMER , // PC 4 ** 33 ** D33
NOT_ON_TIMER , // PC 3 ** 34 ** D34
NOT_ON_TIMER , // PC 2 ** 35 ** D35
NOT_ON_TIMER , // PC 1 ** 36 ** D36
NOT_ON_TIMER , // PC 0 ** 37 ** D37
NOT_ON_TIMER , // PD 7 ** 38 ** D38
NOT_ON_TIMER , // PG 2 ** 39 ** D39
NOT_ON_TIMER , // PG 1 ** 40 ** D40
NOT_ON_TIMER , // PG 0 ** 41 ** D41
NOT_ON_TIMER , // PL 7 ** 42 ** D42
NOT_ON_TIMER , // PL 6 ** 43 ** D43
TIMER5C , // PL 5 ** 44 ** D44
TIMER5B , // PL 4 ** 45 ** D45
TIMER5A , // PL 3 ** 46 ** D46
NOT_ON_TIMER , // PL 2 ** 47 ** D47
NOT_ON_TIMER , // PL 1 ** 48 ** D48
NOT_ON_TIMER , // PL 0 ** 49 ** D49
NOT_ON_TIMER , // PB 3 ** 50 ** SPI_MISO
NOT_ON_TIMER , // PB 2 ** 51 ** SPI_MOSI
NOT_ON_TIMER , // PB 1 ** 52 ** SPI_SCK
NOT_ON_TIMER , // PB 0 ** 53 ** SPI_SS
NOT_ON_TIMER , // PF 0 ** 54 ** A0
NOT_ON_TIMER , // PF 1 ** 55 ** A1
NOT_ON_TIMER , // PF 2 ** 56 ** A2
NOT_ON_TIMER , // PF 3 ** 57 ** A3
NOT_ON_TIMER , // PF 4 ** 58 ** A4
NOT_ON_TIMER , // PF 5 ** 59 ** A5
NOT_ON_TIMER , // PF 6 ** 60 ** A6
NOT_ON_TIMER , // PF 7 ** 61 ** A7
NOT_ON_TIMER , // PK 0 ** 62 ** A8
NOT_ON_TIMER , // PK 1 ** 63 ** A9
NOT_ON_TIMER , // PK 2 ** 64 ** A10
NOT_ON_TIMER , // PK 3 ** 65 ** A11
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 , // PH 2 ** 70 **
NOT_ON_TIMER , // PH 7 ** 71 **
NOT_ON_TIMER , // PJ 2 ** 72 **
NOT_ON_TIMER , // PJ 3 ** 73 **
NOT_ON_TIMER , // PJ 4 ** 74 **
NOT_ON_TIMER , // PJ 5 ** 75 **
NOT_ON_TIMER , // PJ 6 ** 76 **
NOT_ON_TIMER , // PJ 7 ** 77 **
NOT_ON_TIMER , // PD 4 ** 78 **
NOT_ON_TIMER , // PD 5 ** 79 **
NOT_ON_TIMER , // PD 6 ** 80 **
NOT_ON_TIMER , // PG 4 ** 81 **
NOT_ON_TIMER , // PG 3 ** 82 **
NOT_ON_TIMER , // PE 7 ** 83 **
NOT_ON_TIMER , // PE 6 ** 84 **
NOT_ON_TIMER , // PE 2 ** 85 **

};
#else
// 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,
NOT_A_PORT,
&DDRB,
&DDRC,
&DDRD,
};

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

const uint16_t PROGMEM port_to_input_PGM[] = {
NOT_A_PORT,
NOT_A_PORT,
&PINB,
&PINC,
&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,
PC, /
14 */
PC,
PC,
PC,
PC,
PC,
};

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(2),
_BV(3),
_BV(4),
_BV(5),
_BV(0), /
14, port C */
_BV(1),
_BV(2),
_BV(3),
_BV(4),
_BV(5),
};

const uint8_t PROGMEM digital_pin_to_timer_PGM[] = {
NOT_ON_TIMER, /* 0 - port D /
NOT_ON_TIMER,
NOT_ON_TIMER,
// on the ATmega168, digital pin 3 has hardware pwm
#if defined(AVR_ATmega8)
NOT_ON_TIMER,
#else
TIMER2B,
#endif
NOT_ON_TIMER,
// on the ATmega168, digital pins 5 and 6 have hardware pwm
#if defined(AVR_ATmega8)
NOT_ON_TIMER,
NOT_ON_TIMER,
#else
TIMER0B,
TIMER0A,
#endif
NOT_ON_TIMER,
NOT_ON_TIMER, /
8 - port B /
TIMER1A,
TIMER1B,
#if defined(AVR_ATmega8)
TIMER2,
#else
TIMER2A,
#endif
NOT_ON_TIMER,
NOT_ON_TIMER,
NOT_ON_TIMER,
NOT_ON_TIMER, /
14 - port C */
NOT_ON_TIMER,
NOT_ON_TIMER,
NOT_ON_TIMER,
NOT_ON_TIMER,
};
#endif

Kinda silly but that seems to be the only way for me to upload it.

Rich;

I’ll give it a try sometime this weekend.

Thanks;

Lefty