Skip to content

#ifdef by properties, not by chip names: improve support for uncommon chips. #197

@Traumflug

Description

@Traumflug

Two years ago I started Generation 7 Electronics, which is pretty close to an Arduino from the programmers view. Back then there was no support for 20 MHz chips, ATmega644 (without P) and ATmega644P, so I had to tweak the library fork made for the Sanguino. Today, things have changed, thanks a lot. I just rebased my derivate to Arduino 1.0.3 and I think the patch has become small enough to deserve incorporation into the general Arduino library.

My strategy is to check not for chip names, but for their features. This way you become compatible to virtually all ATmegas and ATtinys existing, even the rare ones, and without long chains of #if defined().

For the result, please see this patch against the 1.0.3 tag:

From faeb76ed6443dd0422a98e003d824fc5a7b835ab Mon Sep 17 00:00:00 2001
From: Markus Hitter <[email protected]>
Date: Wed, 30 Jan 2013 21:01:07 +0100
Subject: [PATCH] All changes for ATmega644, 644P and 1284P in one commit.

---
 hardware/arduino/cores/arduino/Arduino.h        |   11 +++++++++--
 hardware/arduino/cores/arduino/Tone.cpp         |    5 +++--
 hardware/arduino/cores/arduino/wiring.c         |    2 +-
 hardware/arduino/cores/arduino/wiring_analog.c  |    4 ++--
 hardware/arduino/cores/arduino/wiring_private.h |    4 ++--
 5 files changed, 17 insertions(+), 9 deletions(-)
 mode change 100755 => 100644 hardware/arduino/cores/arduino/Print.cpp
 mode change 100755 => 100644 hardware/arduino/cores/arduino/Print.h
 mode change 100755 => 100644 hardware/arduino/cores/arduino/Tone.cpp
 mode change 100755 => 100644 hardware/arduino/cores/arduino/wiring_private.h
 mode change 100755 => 100644 hardware/arduino/cores/arduino/wiring_pulse.c
 mode change 100755 => 100644 hardware/arduino/cores/arduino/wiring_shift.c

diff --git a/hardware/arduino/cores/arduino/Arduino.h b/hardware/arduino/cores/arduino/Arduino.h
index b265825..349b9a4 100755
--- a/hardware/arduino/cores/arduino/Arduino.h
+++ b/hardware/arduino/cores/arduino/Arduino.h
@@ -41,12 +41,16 @@ extern "C"{
 #define FALLING 2
 #define RISING 3

-#if defined(__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__) || defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
+// analog voltage references
+#if defined(REFS2) // ATtiny of some sort
 #define DEFAULT 0
 #define EXTERNAL 1
 #define INTERNAL 2
 #else  
-#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(__AVR_ATmega1284P__) || defined(__AVR_ATmega644P__)
+// Looks like the SFIOR register exists only on those chips without
+// 1.1V internal reference voltage. This is an educated guess inspired
+// by AppNote AVR097, page 5 bottom.
+#if !defined(SFIOR)
 #define INTERNAL1V1 2
 #define INTERNAL2V56 3
 #else
@@ -65,7 +69,10 @@ extern "C"{
 #define max(a,b) ((a)>(b)?(a):(b))
 #define abs(x) ((x)>0?(x):-(x))
 #define constrain(amt,low,high) ((amt)<(low)?(low):((amt)>(high)?(high):(amt)))
+#if __GNUC__ <= 4 && __GNUC_MINOR__ < 5
+// this conflicts with avr-gcc's built in headers as of avr-gcc 4.5.3
 #define round(x)     ((x)>=0?(long)((x)+0.5):(long)((x)-0.5))
+#endif
 #define radians(deg) ((deg)*DEG_TO_RAD)
 #define degrees(rad) ((rad)*RAD_TO_DEG)
 #define sq(x) ((x)*(x))
diff --git a/hardware/arduino/cores/arduino/Tone.cpp b/hardware/arduino/cores/arduino/Tone.cpp
index 9bb6fe7..964f2ec
--- a/hardware/arduino/cores/arduino/Tone.cpp
+++ b/hardware/arduino/cores/arduino/Tone.cpp
@@ -37,7 +37,7 @@ Version Modified By Date     Comments
 #include "Arduino.h"
 #include "pins_arduino.h"

-#if defined(__AVR_ATmega8__) || defined(__AVR_ATmega128__)
+#if defined(TCCR2) // ATmega8, ATmega128 or similar
 #define TCCR2A TCCR2
 #define TCCR2B TCCR2
 #define COM2A1 COM21
@@ -54,7 +54,7 @@ Version Modified By Date     Comments
 //  = 0 - stopped
 //  < 0 - infinitely (until stop() method called, or new play() called)

-#if !defined(__AVR_ATmega8__)
+#if defined(TIMSK0)
 volatile long timer0_toggle_count;
 volatile uint8_t *timer0_pin_port;
 volatile uint8_t timer0_pin_mask;
@@ -86,6 +86,7 @@ volatile uint8_t timer5_pin_mask;
 #endif


+// Don't distinguish by chip type, but by register presence
 #if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)

 #define AVAILABLE_TONE_PINS 1
diff --git a/hardware/arduino/cores/arduino/wiring.c b/hardware/arduino/cores/arduino/wiring.c
index ac8bb6f..8407849 100644
--- a/hardware/arduino/cores/arduino/wiring.c
+++ b/hardware/arduino/cores/arduino/wiring.c
@@ -41,7 +41,7 @@ volatile unsigned long timer0_overflow_count = 0;
 volatile unsigned long timer0_millis = 0;
 static unsigned char timer0_fract = 0;

-#if defined(__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__)
+#if defined (TIM0_OVF_vect)
 SIGNAL(TIM0_OVF_vect)
 #else
 SIGNAL(TIMER0_OVF_vect)
diff --git a/hardware/arduino/cores/arduino/wiring_analog.c b/hardware/arduino/cores/arduino/wiring_analog.c
index 23b01c6..38c8e39 100644
--- a/hardware/arduino/cores/arduino/wiring_analog.c
+++ b/hardware/arduino/cores/arduino/wiring_analog.c
@@ -41,11 +41,11 @@ int analogRead(uint8_t pin)
 {
    uint8_t low, high;

-#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
+#if defined(PORTL) // 100 pin chips
    if (pin >= 54) pin -= 54; // allow for channel or pin numbers
 #elif defined(__AVR_ATmega32U4__)
    if (pin >= 18) pin -= 18; // allow for channel or pin numbers
-#elif defined(__AVR_ATmega1284P__) || defined(__AVR_ATmega644P__)
+#elif defined(PORTA) // 40/44 pin chips
    if (pin >= 24) pin -= 24; // allow for channel or pin numbers
 #else
    if (pin >= 14) pin -= 14; // allow for channel or pin numbers
diff --git a/hardware/arduino/cores/arduino/wiring_private.h b/hardware/arduino/cores/arduino/wiring_private.h
index f678265..c91289e
--- a/hardware/arduino/cores/arduino/wiring_private.h
+++ b/hardware/arduino/cores/arduino/wiring_private.h
@@ -52,9 +52,9 @@ extern "C"{
 #define EXTERNAL_INT_6 6
 #define EXTERNAL_INT_7 7

-#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
+#if defined (SIG_INTERRUPT7)
 #define EXTERNAL_NUM_INTERRUPTS 8
-#elif defined(__AVR_ATmega1284P__) || defined(__AVR_ATmega644P__)
+#elif defined (SIG_INTERRUPT2)
 #define EXTERNAL_NUM_INTERRUPTS 3
 #elif defined(__AVR_ATmega32U4__)
 #define EXTERNAL_NUM_INTERRUPTS 4
-- 
1.7.10.4

What do you think? Given this could go into this repo I could give up my derivate, making things for many users much easier. Not only Gen7 users, but any user of a rare AVR.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions