Skip to content

Commit fac1fd3

Browse files
committed
Hack for ATmega 644.
1 parent 2d6448c commit fac1fd3

11 files changed

+112
-48
lines changed

.github/workflows/LibraryBuild.yml

+11-11
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,8 @@ jobs:
4242
- arduino:avr:leonardo
4343
- arduino:avr:mega
4444
- digistump:avr:digispark-pro
45-
# - ATTinyCore:avr:attinyx5:chip=85,clock=1internal
46-
# - ATTinyCore:avr:attinyx7micr:sketchclock=1external16
45+
- ATTinyCore:avr:attinyx5:chip=85,clock=1internal
46+
- ATTinyCore:avr:attinyx7micr:sketchclock=1external16
4747

4848
# Choose the right platform for the boards we want to test. (maybe in the future Arduino will automatically do this for you)
4949
# With sketches-exclude you may exclude specific examples for a board. Use a comma separated list.
@@ -52,15 +52,15 @@ jobs:
5252
- arduino-boards-fqbn: digistump:avr:digispark-pro
5353
platform-url: https://raw.githubusercontent.com/ArminJo/DigistumpArduino/master/package_digistump_index.json
5454

55-
# - arduino-boards-fqbn: ATTinyCore:avr:attinyx5:chip=85,clock=1internal # ATtiny85 board @1 MHz / Digispark
56-
# platform-url: http://drazzy.com/package_drazzy.com_index.json
57-
# build-properties:
58-
# TwoButtons: -DTX_PIN=PB0
55+
- arduino-boards-fqbn: ATTinyCore:avr:attinyx5:chip=85,clock=1internal # ATtiny85 board @1 MHz / Digispark
56+
platform-url: http://drazzy.com/package_drazzy.com_index.json
57+
build-properties:
58+
TwoButtons: -DTX_PIN=PB0
5959

60-
# - arduino-boards-fqbn: ATTinyCore:avr:attinyx7micr:sketchclock=1external16 # Digispark pro
61-
# platform-url: http://drazzy.com/package_drazzy.com_index.json
62-
# build-properties:
63-
# TwoButtons: -DTX_PIN=PB0
60+
- arduino-boards-fqbn: ATTinyCore:avr:attinyx7micr:sketchclock=1external16 # Digispark pro
61+
platform-url: http://drazzy.com/package_drazzy.com_index.json
62+
build-properties:
63+
TwoButtons: -DTX_PIN=PB0
6464

6565

6666
# Do not cancel all jobs / architectures if one job fails
@@ -77,4 +77,4 @@ jobs:
7777
platform-url: ${{ matrix.platform-url }}
7878
# sketches-exclude: ${{ matrix.sketches-exclude }}
7979
build-properties: ${{ toJson(matrix.build-properties) }}
80-
cli-version: 0.33.0 # to avoid errors for ATTinyCore
80+
# cli-version: 0.33.0 # to avoid errors for ATTinyCore

README.md

+3-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ Available as [Arduino library "EasyButtonAtInt01"](https://www.arduinolibraries.
2020

2121
[![Button Install](https://img.shields.io/badge/Install-brightgreen?logoColor=white&logo=GitBook)](https://www.ardu-badge.com/EasyButtonAtInt01)
2222
   
23-
[![Button Changelog](https://img.shields.io/badge/Changelog-blue?logoColor=white&logo=AzureArtifacts)](https://github.com/ArminJo/EasyButtonAtInt01#revision-history)
23+
[![Button Changelog](https://img.shields.io/badge/Changelog-blue?logoColor=white&logo=AzureArtifacts)](https://github.com/ArminJo/EasyButtonAtInt01?tab=readme-ov-file#revision-history)
2424

2525
</div>
2626

@@ -211,6 +211,7 @@ Modify them by enabling / disabling them, or change the values if applicable.
211211
| `BUTTON_LED_FEEDBACK` | disabled | This activates LED_BUILTIN as long as button is pressed. |
212212
| `BUTTON_LED_FEEDBACK_PIN` | disabled | The pin to use for button LED feedback. |
213213
| `INTENTIONALLY_USE_PCI0_FOR_BUTTON1` | disabled | Activate it to suppress the warning: "Using PCINT0 interrupt for button 1". |
214+
| `USE_INT2_FOR_BUTTON_0` | disabled | Hack, especially for ATmega644 etc, where INT0 and INT1 are occupied by 2. USART. |
214215

215216
The exact pin numbers of the buttons used internally are available by the macros INT0_PIN and INT1_PIN, which are set after the include.
216217

@@ -240,6 +241,7 @@ bool checkForForButtonNotPressedTime(uint16_t aTimeoutMillis);
240241
# Revision History
241242
### Version 3.4.1 - work in progress
242243
- Avoid wrong double press detection if calling checkForDoublePress() after release of button.
244+
- Hack for ATmega 644.
243245
244246
### Version 3.4.0
245247
- Added `NO_INITIALIZE_IN_CONSTRUCTOR` macro to enable late initializing.

examples/Callback/Callback.ino

+2-1
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,8 @@ void setup() {
4949
pinMode(LED_BUILTIN, OUTPUT);
5050

5151
Serial.begin(115200);
52-
#if defined(__AVR_ATmega32U4__) || defined(SERIAL_PORT_USBVIRTUAL) || defined(SERIAL_USB) /*stm32duino*/|| defined(USBCON) /*STM32_stm32*/|| defined(SERIALUSB_PID) || defined(ARDUINO_attiny3217)
52+
#if defined(__AVR_ATmega32U4__) || defined(SERIAL_PORT_USBVIRTUAL) || defined(SERIAL_USB) /*stm32duino*/|| defined(USBCON) /*STM32_stm32*/ \
53+
|| defined(SERIALUSB_PID) || defined(ARDUINO_ARCH_RP2040) || defined(ARDUINO_attiny3217)
5354
delay(4000); // To be able to connect Serial monitor after reset or power up and before first print out. Do not wait for an attached Serial Monitor!
5455
#endif
5556
// Just to know which program is running on my Arduino

examples/DebounceTest/DebounceTest.ino

+2-1
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,8 @@ void setup() {
5353
pinMode(LED_BUILTIN, OUTPUT);
5454

5555
Serial.begin(115200);
56-
#if defined(__AVR_ATmega32U4__) || defined(SERIAL_PORT_USBVIRTUAL) || defined(SERIAL_USB) /*stm32duino*/|| defined(USBCON) /*STM32_stm32*/|| defined(SERIALUSB_PID) || defined(ARDUINO_attiny3217)
56+
#if defined(__AVR_ATmega32U4__) || defined(SERIAL_PORT_USBVIRTUAL) || defined(SERIAL_USB) /*stm32duino*/|| defined(USBCON) /*STM32_stm32*/ \
57+
|| defined(SERIALUSB_PID) || defined(ARDUINO_ARCH_RP2040) || defined(ARDUINO_attiny3217)
5758
delay(4000); // To be able to connect Serial monitor after reset or power up and before first print out. Do not wait for an attached Serial Monitor!
5859
#endif
5960
// Just to know which program is running on my Arduino

examples/OneButton/OneButton.ino

+2-1
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,8 @@ void setup() {
4646
pinMode(LED_BUILTIN, OUTPUT);
4747

4848
Serial.begin(115200);
49-
#if defined(__AVR_ATmega32U4__) || defined(SERIAL_PORT_USBVIRTUAL) || defined(SERIAL_USB) /*stm32duino*/|| defined(USBCON) /*STM32_stm32*/|| defined(SERIALUSB_PID) || defined(ARDUINO_attiny3217)
49+
#if defined(__AVR_ATmega32U4__) || defined(SERIAL_PORT_USBVIRTUAL) || defined(SERIAL_USB) /*stm32duino*/|| defined(USBCON) /*STM32_stm32*/ \
50+
|| defined(SERIALUSB_PID) || defined(ARDUINO_ARCH_RP2040) || defined(ARDUINO_attiny3217)
5051
delay(4000); // To be able to connect Serial monitor after reset or power up and before first print out. Do not wait for an attached Serial Monitor!
5152
#endif
5253
// Just to know which program is running on my Arduino

examples/TwoButtons/ATtinySerialOut.h

+6-6
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*
22
* ATtinySerialOut.h
33
*
4-
* Copyright (C) 2015-2023 Armin Joachimsmeyer
4+
* Copyright (C) 2015-2024 Armin Joachimsmeyer
55
66
*
77
* This file is part of TinySerialOut https://github.com/ArminJo/ATtinySerialOut.
@@ -70,16 +70,16 @@
7070
#ifndef _ATTINY_SERIAL_OUT_H
7171
#define _ATTINY_SERIAL_OUT_H
7272

73-
#if defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) \
73+
#if defined(__AVR_ATtiny13__) || defined(__AVR_ATtiny13A__) || defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) \
7474
|| defined(__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__) \
7575
|| defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__) \
7676
|| defined(__AVR_ATtiny88__)
7777
#include <Arduino.h>
7878

79-
#define VERSION_ATTINY_SERIAL_OUT "2.2.0"
79+
#define VERSION_ATTINY_SERIAL_OUT "2.3.1"
8080
#define VERSION_ATTINY_SERIAL_OUT_MAJOR 2
81-
#define VERSION_ATTINY_SERIAL_OUT_MINOR 2
82-
#define VERSION_ATTINY_SERIAL_OUT_PATCH 0
81+
#define VERSION_ATTINY_SERIAL_OUT_MINOR 3
82+
#define VERSION_ATTINY_SERIAL_OUT_PATCH 1
8383
// The change log is at the bottom of the file
8484

8585
/*
@@ -195,7 +195,7 @@ class TinySerialOut
195195

196196
// virtual functions of Print class
197197
size_t write(uint8_t aByte);
198-
operator bool(); // To support "while (!Serial); // wait for serial port to connect. Required for Leonardo only
198+
operator bool() { return true; } // To support "while (!Serial); // wait for serial port to connect. Required for Leonardo only
199199

200200
#if !defined(TINY_SERIAL_INHERIT_FROM_PRINT)
201201
void print(const __FlashStringHelper *aStringPtr);

examples/TwoButtons/ATtinySerialOut.hpp

+24-8
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
* Using the Serial.print commands needs 4 bytes extra for each call.
1414
*
1515
*
16-
* Copyright (C) 2015-2023 Armin Joachimsmeyer
16+
* Copyright (C) 2015-2024 Armin Joachimsmeyer
1717
1818
*
1919
* This file is part of TinySerialOut https://github.com/ArminJo/ATtinySerialOut.
@@ -36,7 +36,7 @@
3636
#ifndef _ATTINY_SERIAL_OUT_HPP
3737
#define _ATTINY_SERIAL_OUT_HPP
3838

39-
#if defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) \
39+
#if defined(__AVR_ATtiny13__) || defined(__AVR_ATtiny13A__) || defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) \
4040
|| defined(__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__) \
4141
|| defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__) \
4242
|| defined(__AVR_ATtiny88__)
@@ -52,24 +52,40 @@
5252
#endif
5353

5454
#if defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__) // For use with ATTinyCore
55-
# if !defined(TX_PORT)
56-
# if TX_PIN == PIN_PA0 || TX_PIN == PIN_PA1 || TX_PIN == PIN_PA2 || TX_PIN == PIN_PA3 \
55+
# if TX_PIN == PIN_PA0 || TX_PIN == PIN_PA1 || TX_PIN == PIN_PA2 || TX_PIN == PIN_PA3 \
5756
|| TX_PIN == PIN_PA4 || TX_PIN == PIN_PA5 || TX_PIN == PIN_PA6 || TX_PIN == PIN_PA7
5857
#define TX_PORT PORTA
5958
#define TX_PORT_ADDR 0x02 // from #define PORTA _SFR_IO8(0x02)
6059
#define TX_DDR DDRA
61-
# else
60+
# else
6261
#define TX_PORT PORTB
6362
#define TX_PORT_ADDR 0x05 // from #define PORTB _SFR_IO8(0x05)
6463
#define TX_DDR DDRB
65-
# endif
6664
# endif
6765

6866
#elif defined(__AVR_ATtiny88__)
6967
// MH-ET LIVE Tiny88(16.0MHz) board
68+
# if TX_PIN <= 7
7069
#define TX_PORT PORTD
71-
#define TX_PORT_ADDR 0x0B // PORTD
70+
#define TX_PORT_ADDR 0x0B // from #define PORTD _SFR_IO8(0x0B)
7271
#define TX_DDR DDRD
72+
# elif TX_PIN <= 15
73+
#define TX_PORT PORTB
74+
#define TX_PORT_ADDR 0x05
75+
#define TX_DDR DDRB
76+
# elif TX_PIN <= 22
77+
#define TX_PORT PORTC
78+
#define TX_PORT_ADDR 0x08
79+
#define TX_DDR DDRC
80+
# elif TX_PIN <= 26
81+
#define TX_PORT PORTA
82+
#define TX_PORT_ADDR 0x0E
83+
#define TX_DDR DDRA
84+
# else
85+
#define TX_PORT PORTC
86+
#define TX_PORT_ADDR 0x08
87+
#define TX_DDR DDRC
88+
# endif
7389

7490
#elif defined(__AVR_ATtiny84__) // For use with ATTinyCore
7591
# if TX_PIN == PIN_PA0 || TX_PIN == PIN_PA1 || TX_PIN == PIN_PA2 || TX_PIN == PIN_PA3 \
@@ -550,7 +566,7 @@ inline void delay4CyclesExact(uint16_t a4Microseconds) {
550566
);
551567
}
552568

553-
#if (F_CPU == 1000000) && defined(_USE_115200BAUD) // else smaller code, but only 38400 baud at 1 MHz
569+
#if (F_CPU == 1000000) && defined(_USE_115200BAUD) // else around 120 bytes smaller code, but only 38400 baud at 1 MHz
554570
/*
555571
* 115200 baud - 8,680 cycles per bit, 86,8 per byte at 1 MHz
556572
*

examples/TwoButtons/TwoButtons.ino

+2-1
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,8 @@ void setup() {
7474
pinMode(LED_BUILTIN, OUTPUT);
7575

7676
Serial.begin(115200);
77-
#if defined(__AVR_ATmega32U4__) || defined(SERIAL_PORT_USBVIRTUAL) || defined(SERIAL_USB) /*stm32duino*/|| defined(USBCON) /*STM32_stm32*/|| defined(SERIALUSB_PID) || defined(ARDUINO_attiny3217)
77+
#if defined(__AVR_ATmega32U4__) || defined(SERIAL_PORT_USBVIRTUAL) || defined(SERIAL_USB) /*stm32duino*/|| defined(USBCON) /*STM32_stm32*/ \
78+
|| defined(SERIALUSB_PID) || defined(ARDUINO_ARCH_RP2040) || defined(ARDUINO_attiny3217)
7879
delay(4000); // To be able to connect Serial monitor after reset or power up and before first print out. Do not wait for an attached Serial Monitor!
7980
#endif
8081
// Just to know which program is running on my Arduino

src/EasyButtonAtInt01.h

+17-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* EasyButtonAtInt01.hpp
2+
* EasyButtonAtInt01.h
33
*
44
* Arduino library for handling push buttons connected between ground and INT0 and / or INT1 pin.
55
* INT0 and INT1 are connected to Pin 2 / 3 on most Arduinos (ATmega328), to PB6 / PA3 on ATtiny167 and on ATtinyX5 we have only INT0 at PB2.
@@ -13,7 +13,7 @@
1313
* EasyButton Button0AtPin2(true);
1414
* The macros INT0_PIN and INT1_PIN are set after the include.
1515
*
16-
* Copyright (C) 2018-2022 Armin Joachimsmeyer
16+
* Copyright (C) 2018-2024 Armin Joachimsmeyer
1717
1818
*
1919
* This file is part of EasyButtonAtInt01 https://github.com/ArminJo/EasyButtonAtInt01.
@@ -63,6 +63,10 @@
6363
*
6464
*/
6565

66+
// Return values for button state
67+
#define BUTTON_IS_ACTIVE true
68+
#define BUTTON_IS_INACTIVE false
69+
6670
/*
6771
* Enable this if you buttons are active high.
6872
*/
@@ -166,6 +170,16 @@
166170
#define INT1_OUT_PORT (PORTB)
167171
# endif // defined(USE_BUTTON_1)
168172

173+
#elif defined(USE_INT2_FOR_BUTTON_0) // Hack for ATmega 644
174+
# if defined(USE_BUTTON_1)
175+
#error If USE_INT2_FOR_BUTTON_0 is defined, only USE_BUTTON_0 is allowed, USE_BUTTON_1 must be disabled!
176+
# endif
177+
// dirty hack, but INT0 and INT1 are occupied by second USART
178+
#define INT0_PIN 2 // PB2 / INT2
179+
#define INT0_DDR_PORT (DDRB)
180+
#define INT0_IN_PORT (PINB)
181+
#define INT0_OUT_PORT (PORTB)
182+
169183
#elif defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__)
170184
// from here we use only ATtinyCore / PAx / PBx numbers, since on Digispark board and core library there is used a strange enumeration of pins
171185
#define INT0_PIN 14 // PB6 / INT0 is connected to USB+ on DigisparkPro boards and labeled with 3 (D3)
@@ -379,6 +393,7 @@ void __attribute__ ((weak)) handleINT1Interrupt();
379393

380394
/* Version 3.4.1 - 12/2023
381395
* - Avoid wrong double press detection if calling checkForDoublePress() after release of button.
396+
* - Hack for ATmega 644.
382397
*
383398
* Version 3.4.0 - 10/2023
384399
* - Added NO_INITIALIZE_IN_CONSTRUCTOR macro to enable late initializing.

src/EasyButtonAtInt01.hpp

+34-10
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
* #include "EasyButtonAtInt01.hpp"
1616
* EasyButton Button0AtPin2(true);
1717
*
18-
* Copyright (C) 2018-2022 Armin Joachimsmeyer
18+
* Copyright (C) 2018-2024 Armin Joachimsmeyer
1919
2020
*
2121
* This file is part of EasyButtonAtInt01 https://github.com/ArminJo/EasyButtonAtInt01.
@@ -222,6 +222,12 @@ void EasyButton::init(bool aIsButtonAtINT0) {
222222
sPointerToButton0ForISR = this;
223223
# if defined(USE_ATTACH_INTERRUPT)
224224
attachInterrupt(digitalPinToInterrupt(INT0_PIN), &handleINT0Interrupt, CHANGE);
225+
226+
# elif defined(USE_INT2_FOR_BUTTON_0)
227+
EICRA |= _BV(ISC20); // interrupt on any logical change
228+
EIFR |= _BV(INTF2);// clear interrupt bit
229+
EIMSK |= _BV(INT2);// enable interrupt on next change
230+
225231
# else
226232
EICRA |= _BV(ISC00); // interrupt on any logical change
227233
EIFR |= _BV(INTF0);// clear interrupt bit
@@ -340,7 +346,9 @@ void EasyButton::init(bool aIsButtonAtINT0) {
340346
}
341347

342348
/*
343-
* Negative logic for readButtonState() true means button pin is LOW, if button is active low (default)
349+
* if NOT defined BUTTON_IS_ACTIVE_HIGH we have negative logic for readButtonState()!
350+
* In this case BUTTON_IS_ACTIVE (true) means button pin is LOW
351+
* @return BUTTON_IS_ACTIVE (true) or BUTTON_IS_INACTIVE (false)
344352
*/
345353
bool EasyButton::readButtonState() {
346354
#if defined(USE_BUTTON_0) && not defined(USE_BUTTON_1)
@@ -384,11 +392,14 @@ bool EasyButton::getButtonStateIsActive() {
384392
}
385393
/*
386394
* Returns stored state if in debouncing period otherwise current state of button
395+
* If button is in bouncing period, we do not know button state, so it is only save to return BUTTON_IS_INACTIVE
396+
* @return BUTTON_IS_ACTIVE (true) or BUTTON_IS_INACTIVE (false)
387397
*/
388398
bool EasyButton::readDebouncedButtonState() {
389-
// Check for bouncing period
399+
// Check if we are in bouncing period
390400
if (millis() - ButtonLastChangeMillis <= BUTTON_DEBOUNCING_MILLIS) {
391-
return ButtonStateIsActive;
401+
// If button is in bouncing period, we do not know button state, so it is only save to return BUTTON_IS_INACTIVE
402+
return BUTTON_IS_INACTIVE;
392403
}
393404
return readButtonState();
394405
}
@@ -445,14 +456,15 @@ uint16_t EasyButton::updateButtonPressDuration() {
445456
*/
446457
uint8_t EasyButton::checkForLongPress(uint16_t aLongPressThresholdMillis) {
447458
uint8_t tRetvale = EASY_BUTTON_LONG_PRESS_ABORT;
448-
if (readDebouncedButtonState()) {
459+
// noInterrupts() is required, since otherwise we may get wrong results if interrupted during processing by button ISR
460+
noInterrupts();
461+
if (readDebouncedButtonState() != BUTTON_IS_INACTIVE) {
449462
// Button still active -> update current ButtonPressDurationMillis
450-
// noInterrupts() is required, since otherwise we may get wrong results if interrupted during load of long value by button ISR
451-
noInterrupts();
463+
452464
ButtonPressDurationMillis = millis() - ButtonLastChangeMillis;
453-
interrupts();
454465
tRetvale = EASY_BUTTON_LONG_PRESS_STILL_POSSIBLE; // if not detected, you may try again
455466
}
467+
interrupts();
456468
if (ButtonPressDurationMillis >= aLongPressThresholdMillis) {
457469
// long press detected
458470
return EASY_BUTTON_LONG_PRESS_DETECTED;
@@ -716,8 +728,8 @@ void __attribute__ ((weak)) handleINT1Interrupt() {
716728
// ISR for PIN PD2
717729
// Cannot make the vector itself weak, since the vector table is already filled by weak vectors resulting in ignoring my weak one:-(
718730
//ISR(INT0_vect, __attribute__ ((weak))) {
719-
# if defined(USE_BUTTON_0)
720-
ISR(INT0_vect) {
731+
# if defined(USE_INT2_FOR_BUTTON_0)
732+
ISR(INT2_vect) {
721733
# if defined(MEASURE_EASY_BUTTON_INTERRUPT_TIMING)
722734
digitalWriteFast(INTERRUPT_TIMING_OUTPUT_PIN, HIGH);
723735
# endif
@@ -726,6 +738,18 @@ ISR(INT0_vect) {
726738
digitalWriteFast(INTERRUPT_TIMING_OUTPUT_PIN, LOW);
727739
# endif
728740
}
741+
# else
742+
# if defined(USE_BUTTON_0)
743+
ISR(INT0_vect) {
744+
# if defined(MEASURE_EASY_BUTTON_INTERRUPT_TIMING)
745+
digitalWriteFast(INTERRUPT_TIMING_OUTPUT_PIN, HIGH);
746+
# endif
747+
handleINT0Interrupt();
748+
# if defined(MEASURE_EASY_BUTTON_INTERRUPT_TIMING)
749+
digitalWriteFast(INTERRUPT_TIMING_OUTPUT_PIN, LOW);
750+
# endif
751+
}
752+
# endif
729753
# endif
730754

731755
# if defined(USE_BUTTON_1)

0 commit comments

Comments
 (0)