From 316b31c5e855c107478afd46a6d64d4d099a7f27 Mon Sep 17 00:00:00 2001 From: Lucas <10280695+Lukelectro@users.noreply.github.com> Date: Tue, 3 Feb 2026 12:21:15 +0100 Subject: [PATCH 01/11] Boards.txt and pins_arduino.h modified for atmega161. pins_arduino.h TODO: use one or both UARTS? (for now, just one) --- avr/boards.txt | 149 +++++++++++++++++++++++++++ avr/variants/standard/pins_arduino.h | 45 +++++++- 2 files changed, 193 insertions(+), 1 deletion(-) diff --git a/avr/boards.txt b/avr/boards.txt index 5ca8b884..c7a0ed0e 100644 --- a/avr/boards.txt +++ b/avr/boards.txt @@ -233,6 +233,155 @@ menu.JTAG=JTAG pins 162.menu.clock.1MHz_internal.build.clkpr= 162.menu.clock.1MHz_internal.build.f_cpu=1000000L +################### +#### ATmega161 #### +################### + +# General +161.name=ATmega161 +161.upload.tool=avrdude +161.upload.maximum_data_size=512 +161.bootloader.tool=avrdude +161.bootloader.unlock_bits=0x3f +161.bootloader.lock_bits=0x0f +161.build.core=MCUdude_corefiles +161.build.variant=standard +161.build.board=AVR_ATmega161 +161.build.mcu=atmega161 +161.build.bootloader_led=led+b0 +161.build.extra_flags={build.clkpr} + +# Upload port select +161.menu.bootloader.uart0=Yes (UART0) +161.menu.bootloader.uart0.upload.maximum_size=16000 +161.menu.bootloader.uart0.upload.protocol=urclock +161.menu.bootloader.uart0.upload.uartpins=uart0_rxd0_txd1 +161.menu.bootloader.uart0.build.export_merged_output=true +161.menu.bootloader.uart0.bootloader.file=urboot/{build.mcu}/watchdog_1_s/autobaud/{upload.uartpins}/{build.bootloader_led}/urboot_{build.mcu}_pr_ee_ce.hex + +161.menu.bootloader.uart1=Yes (UART1) +161.menu.bootloader.uart1.upload.maximum_size=16000 +161.menu.bootloader.uart1.upload.protocol=urclock +161.menu.bootloader.uart1.upload.uartpins=uart1_rxb2_txb3 +161.menu.bootloader.uart1.build.export_merged_output=true +161.menu.bootloader.uart1.bootloader.file=urboot/{build.mcu}/watchdog_1_s/autobaud/{upload.uartpins}/{build.bootloader_led}/urboot_{build.mcu}_pr_ee_ce.hex + +161.menu.bootloader.no_bootloader=No bootloader +161.menu.bootloader.no_bootloader.upload.maximum_size=16384 +#16k flash is 2^14=16384 +161.menu.bootloader.no_bootloader.build.export_merged_output=false +161.menu.bootloader.no_bootloader.bootloader.file=empty/empty.hex + +# EEPROM +# Atmega161 has no EESAVE fuse. No high fuses at all. +#161.menu.eeprom.keep=EEPROM retained +#161.menu.eeprom.keep.bootloader.high_fuses=0xd7 +#161.menu.eeprom.erase=EEPROM not retained +#161.menu.eeprom.erase.bootloader.high_fuses=0xdf + +# Baud rate +161.menu.baudrate.default=Default +161.menu.baudrate.default.upload.speed={upload.default_speed} +161.menu.baudrate.1000000=1000000 +161.menu.baudrate.1000000.upload.speed=1000000 +161.menu.baudrate.500000=500000 +161.menu.baudrate.500000.upload.speed=500000 +161.menu.baudrate.460800=460800 +161.menu.baudrate.460800.upload.speed=460800 +161.menu.baudrate.250000=250000 +161.menu.baudrate.250000.upload.speed=250000 +161.menu.baudrate.230400=230400 +161.menu.baudrate.230400.upload.speed=230400 +161.menu.baudrate.125000=125000 +161.menu.baudrate.125000.upload.speed=125000 +161.menu.baudrate.115200=115200 +161.menu.baudrate.115200.upload.speed=115200 +161.menu.baudrate.57600=57600 +161.menu.baudrate.57600.upload.speed=57600 +161.menu.baudrate.38400=38400 +161.menu.baudrate.38400.upload.speed=38400 +161.menu.baudrate.19200=19200 +161.menu.baudrate.19200.upload.speed=19200 +161.menu.baudrate.9600=9600 +161.menu.baudrate.9600.upload.speed=9600 +161.menu.baudrate.4800=4800 +161.menu.baudrate.4800.upload.speed=4800 + +# Brown out detection +#Atmega161 has no efuse / no BOD +#161.menu.BOD.2v7=BOD 2.7V +#161.menu.BOD.2v7.bootloader.extended_fuses=0xfb +#161.menu.BOD.4v3=BOD 4.3V +#161.menu.BOD.4v3.bootloader.extended_fuses=0xf9 +#161.menu.BOD.1v8=BOD 1.8V +#161.menu.BOD.1v8.bootloader.extended_fuses=0xfd +#161.menu.BOD.disabled=BOD disabled +#161.menu.BOD.disabled.bootloader.extended_fuses=0xff + +# Compiler link time optimization +161.menu.LTO.Os_flto=LTO enabled +161.menu.LTO.Os_flto.compiler.c.extra_flags=-Wextra -flto -g +161.menu.LTO.Os_flto.compiler.c.elf.extra_flags=-w -flto -g +161.menu.LTO.Os_flto.compiler.cpp.extra_flags=-Wextra -flto -g +161.menu.LTO.Os_flto.ltoarcmd=avr-gcc-ar + +161.menu.LTO.Os=LTO disabled +161.menu.LTO.Os.compiler.c.extra_flags= +161.menu.LTO.Os.compiler.c.elf.extra_flags= +161.menu.LTO.Os.compiler.cpp.extra_flags= +161.menu.LTO.Os.ltoarcmd=avr-ar + + +# Clock frequencies. Atmega161 can run at maximum 8 MHz and has no internal clock + +161.menu.clock.8MHz_external=External 8 MHz +161.menu.clock.8MHz_external.upload.default_speed=57600 +161.menu.clock.8MHz_external.bootloader.low_fuses=0x80 +161.menu.clock.8MHz_external.build.clkpr= +161.menu.clock.8MHz_external.build.f_cpu=8000000L + +161.menu.clock.7_3728MHz_external=External 7.3728 MHz +161.menu.clock.7_3728MHz_external.upload.default_speed=115200 +161.menu.clock.7_3728MHz_external.bootloader.low_fuses=0x80 +161.menu.clock.7_3728MHz_external.build.clkpr= +161.menu.clock.7_3728MHz_external.build.f_cpu=7372800L + +161.menu.clock.6MHz_external=External 6 MHz +161.menu.clock.6MHz_external.upload.default_speed=57600 +161.menu.clock.6MHz_external.bootloader.low_fuses=0x80 +161.menu.clock.6MHz_external.build.clkpr= +161.menu.clock.6MHz_external.build.f_cpu=6000000L + +161.menu.clock.4MHz_external=External 4 MHz +161.menu.clock.4MHz_external.upload.default_speed=9600 +161.menu.clock.4MHz_external.bootloader.low_fuses=0x80 +161.menu.clock.4MHz_external.build.clkpr= +161.menu.clock.4MHz_external.build.f_cpu=4000000L + +161.menu.clock.3_6864MHz_external=External 3.6864 MHz +161.menu.clock.3_6864MHz_external.upload.default_speed=115200 +161.menu.clock.3_6864MHz_external.bootloader.low_fuses=0x80 +161.menu.clock.3_6864MHz_external.build.clkpr= +161.menu.clock.3_6864MHz_external.build.f_cpu=3686400L + +161.menu.clock.2MHz_external=External 2 MHz +161.menu.clock.2MHz_external.upload.default_speed=9600 +161.menu.clock.2MHz_external.bootloader.low_fuses=0x80 +161.menu.clock.2MHz_external.build.clkpr= +161.menu.clock.2MHz_external.build.f_cpu=2000000L + +161.menu.clock.1_8432MHz_external=External 1.8432 MHz +161.menu.clock.1_8432MHz_external.upload.default_speed=115200 +161.menu.clock.1_8432MHz_external.bootloader.low_fuses=0x80 +161.menu.clock.1_8432MHz_external.build.clkpr= +161.menu.clock.1_8432MHz_external.build.f_cpu=1843200L + +161.menu.clock.1MHz_external=External 1 MHz +161.menu.clock.1MHz_external.upload.default_speed=9600 +161.menu.clock.1MHz_external.bootloader.low_fuses=0x80 +161.menu.clock.1MHz_external.build.clkpr= +161.menu.clock.1MHz_external.build.f_cpu=1000000L + #################### #### ATmega8515 #### diff --git a/avr/variants/standard/pins_arduino.h b/avr/variants/standard/pins_arduino.h index e95df347..ceb3dcdc 100755 --- a/avr/variants/standard/pins_arduino.h +++ b/avr/variants/standard/pins_arduino.h @@ -17,6 +17,8 @@ #define digitalPinHasPWM(p) ((p) == 0 || (p) == 13 || (p) == 34) #elif defined(__AVR_ATmega162__) #define digitalPinHasPWM(p) ((p) == 0 || (p) == 1 || (p) == 4 || (p) == 12 || (p) == 13 || (p) == 34) +#elif defined(__AVR_ATmega161__) +#define digitalPinHasPWM(p) ((p) == 0 || (p) == 1 || (p) == 13 || (p) == 34) #endif // Builtin LED @@ -44,7 +46,7 @@ static const uint8_t SCK = PIN_SPI_SCK; #define EXTERNAL_NUM_INTERRUPTS 3 #define digitalPinToInterrupt(p) ((p) == 10 ? 0 : ((p) == 11 ? 1 : ((p) == 32 ? 2 : NOT_AN_INTERRUPT))) -// PCINT +// PCINT (Atmega161 has no PCINT, Atmega162 does) #if defined(__AVR_ATmega162__) #define digitalPinToPCICR(p) (0) #define digitalPinToPCICRbit(p) (0) @@ -288,6 +290,47 @@ const uint8_t PROGMEM digital_pin_to_timer_PGM[] = TIMER1B /* D34 - PE2 */ }; +#elif defined(__AVR_ATmega161__) +const uint8_t PROGMEM digital_pin_to_timer_PGM[] = +{ + TIMER0, /* D0 - PB0 */ + TIMER2, /* D1 - PB1 */ + NOT_ON_TIMER, /* D2 - PB2 */ + NOT_ON_TIMER, /* D3 - PB3 */ + NOT_ON_TIMER, /* D4 - PB4 */ + NOT_ON_TIMER, /* D5 - PB5 */ + NOT_ON_TIMER, /* D6 - PB6 */ + NOT_ON_TIMER, /* D7 - PB7 */ + NOT_ON_TIMER, /* D8 - PD0 */ + NOT_ON_TIMER, /* D9 - PD1 */ + NOT_ON_TIMER, /* D10 - PD2 */ + NOT_ON_TIMER, /* D11 - PD3 */ + NOT_ON_TIMER, /* D12 - PD4 */ + TIMER1A, /* D13 - PD5 */ + NOT_ON_TIMER, /* D14 - PD6 */ + NOT_ON_TIMER, /* D15 - PD7 */ + NOT_ON_TIMER, /* D16 - PC0 */ + NOT_ON_TIMER, /* D17 - PC1 */ + NOT_ON_TIMER, /* D18 - PC2 */ + NOT_ON_TIMER, /* D19 - PC3 */ + NOT_ON_TIMER, /* D20 - PC4 */ + NOT_ON_TIMER, /* D21 - PC5 */ + NOT_ON_TIMER, /* D22 - PC6 */ + NOT_ON_TIMER, /* D23 - PC7 */ + NOT_ON_TIMER, /* D24 - PA0 */ + NOT_ON_TIMER, /* D25 - PA1 */ + NOT_ON_TIMER, /* D26 - PA2 */ + NOT_ON_TIMER, /* D27 - PA3 */ + NOT_ON_TIMER, /* D28 - PA4 */ + NOT_ON_TIMER, /* D29 - PA5 */ + NOT_ON_TIMER, /* D30 - PA6 */ + NOT_ON_TIMER, /* D31 - PA7 */ + NOT_ON_TIMER, /* D32 - PE0 */ + NOT_ON_TIMER, /* D33 - PE1 */ + TIMER1B /* D34 - PE2 */ +}; + + #endif // Timer defs #endif // ARDUINO_MAIN From 719777057398863987c2e06bfad0e6f731c60696 Mon Sep 17 00:00:00 2001 From: Lucas <10280695+Lukelectro@users.noreply.github.com> Date: Tue, 3 Feb 2026 14:16:37 +0100 Subject: [PATCH 02/11] this should get serial0 to work on atmega161. work in progress. --- avr/boards.txt | 2 +- avr/cores/MCUdude_corefiles/HardwareSerial.cpp | 6 +++++- avr/cores/MCUdude_corefiles/HardwareSerial0.cpp | 10 ++++++++-- avr/cores/MCUdude_corefiles/HardwareSerial1.cpp | 8 ++++++-- avr/cores/MCUdude_corefiles/HardwareSerial_private.h | 8 ++++++++ 5 files changed, 28 insertions(+), 6 deletions(-) diff --git a/avr/boards.txt b/avr/boards.txt index c7a0ed0e..3b78aef2 100644 --- a/avr/boards.txt +++ b/avr/boards.txt @@ -240,7 +240,7 @@ menu.JTAG=JTAG pins # General 161.name=ATmega161 161.upload.tool=avrdude -161.upload.maximum_data_size=512 +161.upload.maximum_data_size=1024 161.bootloader.tool=avrdude 161.bootloader.unlock_bits=0x3f 161.bootloader.lock_bits=0x0f diff --git a/avr/cores/MCUdude_corefiles/HardwareSerial.cpp b/avr/cores/MCUdude_corefiles/HardwareSerial.cpp index 095bd1cb..655fe8d6 100755 --- a/avr/cores/MCUdude_corefiles/HardwareSerial.cpp +++ b/avr/cores/MCUdude_corefiles/HardwareSerial.cpp @@ -143,7 +143,11 @@ void HardwareSerial::begin(unsigned long baud, byte config) || defined(__AVR_ATmega162__) config |= 0x80; // select UCSRC register (shared with UBRRH) #endif + +#if !defined(__AVR_ATmega161__) // atmega161 has no ucsrc! *_ucsrc = config; +#endif + *_ucsrb |= _BV(RXEN0) | _BV(TXEN0) | _BV(RXCIE0); *_ucsrb &= ~_BV(UDRIE0); @@ -216,7 +220,7 @@ void HardwareSerial::flush() _tx_udr_empty_irq(); } // If we get here, nothing is queued anymore (DRIE is disabled) and - // the hardware finished tranmission (TXC is set). + // the hardware finished transmission (TXC is set). } size_t HardwareSerial::write(uint8_t c) diff --git a/avr/cores/MCUdude_corefiles/HardwareSerial0.cpp b/avr/cores/MCUdude_corefiles/HardwareSerial0.cpp index f3a183e0..3b665d30 100755 --- a/avr/cores/MCUdude_corefiles/HardwareSerial0.cpp +++ b/avr/cores/MCUdude_corefiles/HardwareSerial0.cpp @@ -26,7 +26,7 @@ #include "HardwareSerial.h" #include "HardwareSerial_private.h" -// Each HardwareSerial is defined in its own file, sine the linker pulls +// Each HardwareSerial is defined in its own file, since the linker pulls // in the entire file when any element inside is used. --gc-sections can // additionally cause unused symbols to be dropped, but ISRs have the // "used" attribute so are never dropped and they keep the @@ -44,8 +44,10 @@ ISR(USART0_RX_vect) #elif defined(USART_RX_vect) ISR(USART_RX_vect) +#elif defined(UART0_RX_vect) + ISR(UART0_RX_vect) #else - #error "Don't know what the Data Received vector is called for Serial" + #error "Don't know what the Data Received vector is called for Serial" #endif { Serial._rx_complete_irq(); @@ -53,6 +55,8 @@ #if defined(UART0_UDRE_vect) ISR(UART0_UDRE_vect) +#elif defined(UART_UDRE_vect) +ISR(UART_UDRE_vect) #elif defined(USART_UDRE_vect) ISR(USART_UDRE_vect) #elif defined(USART0_UDRE_vect) @@ -66,6 +70,8 @@ ISR(USART0_UDRE_vect) #if defined(UBRRH) && defined(UBRRL) HardwareSerial Serial(&UBRRH, &UBRRL, &UCSRA, &UCSRB, &UCSRC, &UDR); +#elif defined(UBRRH) && !defined(UBRRL) // on atmega161 UBBRH is defined, for both uarts shared. UBRRL is for each one appar, so UBRRL0 and UBRRL1 + HardwareSerial Serial(&UBRRH, UBRR0, &UCSR0A, &UCSR0B, NULL, &UDR0); // only using UBRR0, so only usart0. There is no UCSRC, as it is an UART, not an USART #else HardwareSerial Serial(&UBRR0H, &UBRR0L, &UCSR0A, &UCSR0B, &UCSR0C, &UDR0); #endif diff --git a/avr/cores/MCUdude_corefiles/HardwareSerial1.cpp b/avr/cores/MCUdude_corefiles/HardwareSerial1.cpp index 25190ee5..816b1a99 100755 --- a/avr/cores/MCUdude_corefiles/HardwareSerial1.cpp +++ b/avr/cores/MCUdude_corefiles/HardwareSerial1.cpp @@ -42,6 +42,8 @@ ISR(UART1_RX_vect) ISR(USART1_RX_vect) #elif defined(USART1_RXC_vect) ISR(USART1_RXC_vect) +#elif defined(UART1_RX_vect) + ISR(UART1_RX_vect) #else #error "Don't know what the Data Register Empty vector is called for Serial1" #endif @@ -59,9 +61,11 @@ ISR(USART1_UDRE_vect) { Serial1._tx_udr_empty_irq(); } - +#if !defined(__AVR_ATmega161__) HardwareSerial Serial1(&UBRR1H, &UBRR1L, &UCSR1A, &UCSR1B, &UCSR1C, &UDR1); - +#else +HardwareSerial Serial(&UBRRH, UBRR1, &UCSR1A, &UCSR1B, NULL, &UDR1); // on ATMEGA161, UBBRH is shared... Inconvinient indeed. +#endif // Function that can be weakly referenced by serialEventRun to prevent // pulling in this file if it's not otherwise used. bool Serial1_available() { diff --git a/avr/cores/MCUdude_corefiles/HardwareSerial_private.h b/avr/cores/MCUdude_corefiles/HardwareSerial_private.h index e27c7b20..92526323 100755 --- a/avr/cores/MCUdude_corefiles/HardwareSerial_private.h +++ b/avr/cores/MCUdude_corefiles/HardwareSerial_private.h @@ -46,7 +46,9 @@ #define RXCIE0 RXCIE #define UDRIE0 UDRIE #define U2X0 U2X +#if defined UPE // because on atmega161 it does not exist #define UPE0 UPE +#endif #define UDRE0 UDRE #elif defined(TXC1) // Some devices have uart1 but no uart0 @@ -56,7 +58,9 @@ #define RXCIE0 RXCIE1 #define UDRIE0 UDRIE1 #define U2X0 U2X1 +#if defined UPE1 // because on atmega161 it does not exist #define UPE0 UPE1 +#endif #define UDRE0 UDRE1 #else #error No UART found in HardwareSerial.cpp @@ -97,7 +101,11 @@ HardwareSerial::HardwareSerial( void HardwareSerial::_rx_complete_irq(void) { +#if defined UPE || defined UPE0 // Atmega161 has no Parity Error flagbit, so don't check it if it is not defined if (bit_is_clear(*_ucsra, UPE0)) { +#else + if(1){ +#endif // No Parity error, read byte and store it in the buffer if there is // room unsigned char c = *_udr; From 2bd1056f8f5c0ef9a2234c972167bbc4863f6b5a Mon Sep 17 00:00:00 2001 From: Lucas <10280695+Lukelectro@users.noreply.github.com> Date: Tue, 3 Feb 2026 17:29:52 +0100 Subject: [PATCH 03/11] baud rate setting for UART0 corrected (UBRRH is a bit weird on m161) --- avr/cores/MCUdude_corefiles/HardwareSerial.cpp | 10 ++++++++++ avr/cores/MCUdude_corefiles/HardwareSerial.h | 3 ++- avr/cores/MCUdude_corefiles/HardwareSerial0.cpp | 6 +++--- avr/cores/MCUdude_corefiles/HardwareSerial1.cpp | 2 +- 4 files changed, 16 insertions(+), 5 deletions(-) diff --git a/avr/cores/MCUdude_corefiles/HardwareSerial.cpp b/avr/cores/MCUdude_corefiles/HardwareSerial.cpp index 655fe8d6..14d74bf8 100755 --- a/avr/cores/MCUdude_corefiles/HardwareSerial.cpp +++ b/avr/cores/MCUdude_corefiles/HardwareSerial.cpp @@ -132,7 +132,17 @@ void HardwareSerial::begin(unsigned long baud, byte config) } // assign the baud_setting, a.k.a. ubrr (USART Baud Rate Register) +#if defined(__AVR_ATmega161__) +// on atmega161, UBRR is a 12 bit register with bit 7..4 for UART 1 and 4...0 for UART0. A bit inconvienient +if(_ucsrb == &UCSR0B){ // test which UART it is (this is a bit of a workaround...) + *_ubrrh = 0x0F & (baud_setting >> 8); // for uart0, use bits 3..0 +} +else{ + *_ubrrh = 0xF0 & (baud_setting >> 4); // for UART1, use bits 7..4 +} +#else *_ubrrh = baud_setting >> 8; +#endif *_ubrrl = baud_setting; _written = false; diff --git a/avr/cores/MCUdude_corefiles/HardwareSerial.h b/avr/cores/MCUdude_corefiles/HardwareSerial.h index 17000c2c..d398f017 100755 --- a/avr/cores/MCUdude_corefiles/HardwareSerial.h +++ b/avr/cores/MCUdude_corefiles/HardwareSerial.h @@ -143,7 +143,8 @@ class HardwareSerial : public Stream extern HardwareSerial Serial; #define HAVE_HWSERIAL0 #endif -#if defined(UBRR1H) +#if defined(UBRR1H) || defined (UBRR1L) +//Atmega161 has no UBRR1H, but HAS a 2nd UART with a 2nd UBRR1L extern HardwareSerial Serial1; #define HAVE_HWSERIAL1 #endif diff --git a/avr/cores/MCUdude_corefiles/HardwareSerial0.cpp b/avr/cores/MCUdude_corefiles/HardwareSerial0.cpp index 3b665d30..4e2a0312 100755 --- a/avr/cores/MCUdude_corefiles/HardwareSerial0.cpp +++ b/avr/cores/MCUdude_corefiles/HardwareSerial0.cpp @@ -68,10 +68,10 @@ ISR(USART0_UDRE_vect) Serial._tx_udr_empty_irq(); } -#if defined(UBRRH) && defined(UBRRL) +#if defined(__AVR_ATmega161__) +HardwareSerial Serial(&UBRRH, &UBRR0, &UCSR0A, &UCSR0B, NULL, &UDR0); // on atmega161 UBBRH is defined, for both uarts shared. UBRRL is for each one appart, so UBRRL0 and UBRRL1. There is no UCSRC on m161 +#elif defined(UBRRH) && defined(UBRRL) HardwareSerial Serial(&UBRRH, &UBRRL, &UCSRA, &UCSRB, &UCSRC, &UDR); -#elif defined(UBRRH) && !defined(UBRRL) // on atmega161 UBBRH is defined, for both uarts shared. UBRRL is for each one appar, so UBRRL0 and UBRRL1 - HardwareSerial Serial(&UBRRH, UBRR0, &UCSR0A, &UCSR0B, NULL, &UDR0); // only using UBRR0, so only usart0. There is no UCSRC, as it is an UART, not an USART #else HardwareSerial Serial(&UBRR0H, &UBRR0L, &UCSR0A, &UCSR0B, &UCSR0C, &UDR0); #endif diff --git a/avr/cores/MCUdude_corefiles/HardwareSerial1.cpp b/avr/cores/MCUdude_corefiles/HardwareSerial1.cpp index 816b1a99..0a7d8992 100755 --- a/avr/cores/MCUdude_corefiles/HardwareSerial1.cpp +++ b/avr/cores/MCUdude_corefiles/HardwareSerial1.cpp @@ -64,7 +64,7 @@ ISR(USART1_UDRE_vect) #if !defined(__AVR_ATmega161__) HardwareSerial Serial1(&UBRR1H, &UBRR1L, &UCSR1A, &UCSR1B, &UCSR1C, &UDR1); #else -HardwareSerial Serial(&UBRRH, UBRR1, &UCSR1A, &UCSR1B, NULL, &UDR1); // on ATMEGA161, UBBRH is shared... Inconvinient indeed. +HardwareSerial Serial(&UBRRH, &UBRR1, &UCSR1A, &UCSR1B, NULL, &UDR1); // on ATMEGA161, UBBRH is shared... Inconvinient indeed. #endif // Function that can be weakly referenced by serialEventRun to prevent // pulling in this file if it's not otherwise used. From 74dd33509746fcddfca02480dde52e51a5e4abfe Mon Sep 17 00:00:00 2001 From: Lucas <10280695+Lukelectro@users.noreply.github.com> Date: Tue, 3 Feb 2026 17:52:16 +0100 Subject: [PATCH 04/11] 2nd uart now also works. tested with serial at 4800b and serial1 at 9600b: both indeed get set to the correct br --- avr/cores/MCUdude_corefiles/HardwareSerial.h | 4 ++-- avr/cores/MCUdude_corefiles/HardwareSerial1.cpp | 4 +--- avr/variants/standard/pins_arduino.h | 3 +++ 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/avr/cores/MCUdude_corefiles/HardwareSerial.h b/avr/cores/MCUdude_corefiles/HardwareSerial.h index d398f017..b42572ca 100755 --- a/avr/cores/MCUdude_corefiles/HardwareSerial.h +++ b/avr/cores/MCUdude_corefiles/HardwareSerial.h @@ -143,8 +143,8 @@ class HardwareSerial : public Stream extern HardwareSerial Serial; #define HAVE_HWSERIAL0 #endif -#if defined(UBRR1H) || defined (UBRR1L) -//Atmega161 has no UBRR1H, but HAS a 2nd UART with a 2nd UBRR1L +#if defined(UBRR1H) || defined (UBRR1) +//Atmega161 has no UBRR1H, but HAS a 2nd UART with a 2nd UBRR1 extern HardwareSerial Serial1; #define HAVE_HWSERIAL1 #endif diff --git a/avr/cores/MCUdude_corefiles/HardwareSerial1.cpp b/avr/cores/MCUdude_corefiles/HardwareSerial1.cpp index 0a7d8992..f5b462de 100755 --- a/avr/cores/MCUdude_corefiles/HardwareSerial1.cpp +++ b/avr/cores/MCUdude_corefiles/HardwareSerial1.cpp @@ -42,8 +42,6 @@ ISR(UART1_RX_vect) ISR(USART1_RX_vect) #elif defined(USART1_RXC_vect) ISR(USART1_RXC_vect) -#elif defined(UART1_RX_vect) - ISR(UART1_RX_vect) #else #error "Don't know what the Data Register Empty vector is called for Serial1" #endif @@ -64,7 +62,7 @@ ISR(USART1_UDRE_vect) #if !defined(__AVR_ATmega161__) HardwareSerial Serial1(&UBRR1H, &UBRR1L, &UCSR1A, &UCSR1B, &UCSR1C, &UDR1); #else -HardwareSerial Serial(&UBRRH, &UBRR1, &UCSR1A, &UCSR1B, NULL, &UDR1); // on ATMEGA161, UBBRH is shared... Inconvinient indeed. +HardwareSerial Serial1(&UBRRH, &UBRR1, &UCSR1A, &UCSR1B, NULL, &UDR1); // on ATMEGA161, UBBRH is shared... Inconvinient indeed. #endif // Function that can be weakly referenced by serialEventRun to prevent // pulling in this file if it's not otherwise used. diff --git a/avr/variants/standard/pins_arduino.h b/avr/variants/standard/pins_arduino.h index ceb3dcdc..5bb3cdf3 100755 --- a/avr/variants/standard/pins_arduino.h +++ b/avr/variants/standard/pins_arduino.h @@ -342,6 +342,9 @@ const uint8_t PROGMEM digital_pin_to_timer_PGM[] = #define SERIAL_PORT_MONITOR Serial #define SERIAL_PORT_HARDWARE Serial +#if defined(__AVR_ATmega161__) +#define SERIAL_PORT_HARDWARE1 Serial1 +#endif #if defined(__AVR_ATmega162__) #define SERIAL_PORT_HARDWARE_OPEN Serial1 From 2e0432c97c4d90456847fe7a94c644f2eb3eb902 Mon Sep 17 00:00:00 2001 From: Lucas <10280695+Lukelectro@users.noreply.github.com> Date: Fri, 13 Feb 2026 19:59:23 +0100 Subject: [PATCH 05/11] modifies boards.txt for correct fuses and bootloader path. Adds bootloader --- avr/boards.txt | 33 +++++++------------ ...tobaud_uart0_rxd0_txd1_no-led_pr_ee_ce.hex | 27 +++++++++++++++ ...tobaud_uart1_rxb2_txb3_no-led_pr_ee_ce.hex | 27 +++++++++++++++ avr/programmers.txt | 0 4 files changed, 65 insertions(+), 22 deletions(-) create mode 100644 avr/bootloaders/urboot/atmega161/watchdog_2_s/autobaud/urboot_m161_2s_autobaud_uart0_rxd0_txd1_no-led_pr_ee_ce.hex create mode 100644 avr/bootloaders/urboot/atmega161/watchdog_2_s/autobaud/urboot_m161_2s_autobaud_uart1_rxb2_txb3_no-led_pr_ee_ce.hex mode change 100755 => 100644 avr/programmers.txt diff --git a/avr/boards.txt b/avr/boards.txt index 3b78aef2..31277243 100644 --- a/avr/boards.txt +++ b/avr/boards.txt @@ -257,14 +257,14 @@ menu.JTAG=JTAG pins 161.menu.bootloader.uart0.upload.protocol=urclock 161.menu.bootloader.uart0.upload.uartpins=uart0_rxd0_txd1 161.menu.bootloader.uart0.build.export_merged_output=true -161.menu.bootloader.uart0.bootloader.file=urboot/{build.mcu}/watchdog_1_s/autobaud/{upload.uartpins}/{build.bootloader_led}/urboot_{build.mcu}_pr_ee_ce.hex +161.menu.bootloader.uart0.bootloader.file=urboot/{build.mcu}/watchdog_2_s/autobaud/urboot_m161_2s_autobaud_uart0_rxd0_txd1_no-led_pr_ee_ce 161.menu.bootloader.uart1=Yes (UART1) 161.menu.bootloader.uart1.upload.maximum_size=16000 161.menu.bootloader.uart1.upload.protocol=urclock 161.menu.bootloader.uart1.upload.uartpins=uart1_rxb2_txb3 161.menu.bootloader.uart1.build.export_merged_output=true -161.menu.bootloader.uart1.bootloader.file=urboot/{build.mcu}/watchdog_1_s/autobaud/{upload.uartpins}/{build.bootloader_led}/urboot_{build.mcu}_pr_ee_ce.hex +161.menu.bootloader.uart1.bootloader.file=urboot/{build.mcu}/watchdog_2_s/autobaud/urboot_m161_2s_autobaud_uart1_rxb2_txb3_no-led_pr_ee_ce.hex 161.menu.bootloader.no_bootloader=No bootloader 161.menu.bootloader.no_bootloader.upload.maximum_size=16384 @@ -274,10 +274,7 @@ menu.JTAG=JTAG pins # EEPROM # Atmega161 has no EESAVE fuse. No high fuses at all. -#161.menu.eeprom.keep=EEPROM retained -#161.menu.eeprom.keep.bootloader.high_fuses=0xd7 -#161.menu.eeprom.erase=EEPROM not retained -#161.menu.eeprom.erase.bootloader.high_fuses=0xdf + # Baud rate 161.menu.baudrate.default=Default @@ -309,14 +306,6 @@ menu.JTAG=JTAG pins # Brown out detection #Atmega161 has no efuse / no BOD -#161.menu.BOD.2v7=BOD 2.7V -#161.menu.BOD.2v7.bootloader.extended_fuses=0xfb -#161.menu.BOD.4v3=BOD 4.3V -#161.menu.BOD.4v3.bootloader.extended_fuses=0xf9 -#161.menu.BOD.1v8=BOD 1.8V -#161.menu.BOD.1v8.bootloader.extended_fuses=0xfd -#161.menu.BOD.disabled=BOD disabled -#161.menu.BOD.disabled.bootloader.extended_fuses=0xff # Compiler link time optimization 161.menu.LTO.Os_flto=LTO enabled @@ -336,49 +325,49 @@ menu.JTAG=JTAG pins 161.menu.clock.8MHz_external=External 8 MHz 161.menu.clock.8MHz_external.upload.default_speed=57600 -161.menu.clock.8MHz_external.bootloader.low_fuses=0x80 +161.menu.clock.8MHz_external.bootloader.low_fuses=0xCA 161.menu.clock.8MHz_external.build.clkpr= 161.menu.clock.8MHz_external.build.f_cpu=8000000L 161.menu.clock.7_3728MHz_external=External 7.3728 MHz 161.menu.clock.7_3728MHz_external.upload.default_speed=115200 -161.menu.clock.7_3728MHz_external.bootloader.low_fuses=0x80 +161.menu.clock.7_3728MHz_external.bootloader.low_fuses=0xCA 161.menu.clock.7_3728MHz_external.build.clkpr= 161.menu.clock.7_3728MHz_external.build.f_cpu=7372800L 161.menu.clock.6MHz_external=External 6 MHz 161.menu.clock.6MHz_external.upload.default_speed=57600 -161.menu.clock.6MHz_external.bootloader.low_fuses=0x80 +161.menu.clock.6MHz_external.bootloader.low_fuses=0xCA 161.menu.clock.6MHz_external.build.clkpr= 161.menu.clock.6MHz_external.build.f_cpu=6000000L 161.menu.clock.4MHz_external=External 4 MHz 161.menu.clock.4MHz_external.upload.default_speed=9600 -161.menu.clock.4MHz_external.bootloader.low_fuses=0x80 +161.menu.clock.4MHz_external.bootloader.low_fuses=0xCA 161.menu.clock.4MHz_external.build.clkpr= 161.menu.clock.4MHz_external.build.f_cpu=4000000L 161.menu.clock.3_6864MHz_external=External 3.6864 MHz 161.menu.clock.3_6864MHz_external.upload.default_speed=115200 -161.menu.clock.3_6864MHz_external.bootloader.low_fuses=0x80 +161.menu.clock.3_6864MHz_external.bootloader.low_fuses=0xCA 161.menu.clock.3_6864MHz_external.build.clkpr= 161.menu.clock.3_6864MHz_external.build.f_cpu=3686400L 161.menu.clock.2MHz_external=External 2 MHz 161.menu.clock.2MHz_external.upload.default_speed=9600 -161.menu.clock.2MHz_external.bootloader.low_fuses=0x80 +161.menu.clock.2MHz_external.bootloader.low_fuses=0xCA 161.menu.clock.2MHz_external.build.clkpr= 161.menu.clock.2MHz_external.build.f_cpu=2000000L 161.menu.clock.1_8432MHz_external=External 1.8432 MHz 161.menu.clock.1_8432MHz_external.upload.default_speed=115200 -161.menu.clock.1_8432MHz_external.bootloader.low_fuses=0x80 +161.menu.clock.1_8432MHz_external.bootloader.low_fuses=0xCA 161.menu.clock.1_8432MHz_external.build.clkpr= 161.menu.clock.1_8432MHz_external.build.f_cpu=1843200L 161.menu.clock.1MHz_external=External 1 MHz 161.menu.clock.1MHz_external.upload.default_speed=9600 -161.menu.clock.1MHz_external.bootloader.low_fuses=0x80 +161.menu.clock.1MHz_external.bootloader.low_fuses=0xCA 161.menu.clock.1MHz_external.build.clkpr= 161.menu.clock.1MHz_external.build.f_cpu=1000000L diff --git a/avr/bootloaders/urboot/atmega161/watchdog_2_s/autobaud/urboot_m161_2s_autobaud_uart0_rxd0_txd1_no-led_pr_ee_ce.hex b/avr/bootloaders/urboot/atmega161/watchdog_2_s/autobaud/urboot_m161_2s_autobaud_uart0_rxd0_txd1_no-led_pr_ee_ce.hex new file mode 100644 index 00000000..c3d1af6a --- /dev/null +++ b/avr/bootloaders/urboot/atmega161/watchdog_2_s/autobaud/urboot_m161_2s_autobaud_uart0_rxd0_txd1_no-led_pr_ee_ce.hex @@ -0,0 +1,27 @@ +:103E800011248FE594E09EBF8DBF24B614BE80E060 +:103E900077D021FEDBC08FE073D0AFE7BFEF809912 +:103EA000FECF9096809BFDCFB9B91197F1F782E0D4 +:103EB0008BB988E18AB958D0C82F8235B1F464D063 +:103EC000E0E0FEE3A8959F0170E87E0F65916F3FEB +:103ED00011F4E713FBCFF90111F083E085D0E0582E +:103EE000F10980F789E53CD0E6CF8D7FD9F443D046 +:103EF000D82FA0E0B1E038D08D93DA13FCCFA0E04A +:103F0000B1E042D0C1110CC0FFBBEEBB8D918DBBA7 +:103F1000E29AE19A3196E199FECFD150A9F7E2CF2A +:103F20003DD0E0CFC33041F426D0C82F2DD08591AD +:103F300017D0C150E1F7D6CFC13061F41CD0C82FE3 +:103F400023D0FFBBEEBBE09A8DB30AD03196C150AF +:103F5000C1F7C8CFC13511F488E012D015D0C2CF57 +:103F60005D9BFECF8CB908955F9BFECF5C990FC01F +:103F7000A8958CB10895F8DFE82FF6DFF82FF4CF7D +:103F800098E191BD81BD0895EFDF803219F088E09E +:103F9000F7DFFFCF80EAE4CFFB01DC01E07870E8D7 +:103FA0007A0F9F01E0388EE3F80728F5309629F460 +:103FB0008FE38D938FEC8C93119790E045915D91F9 +:103FC00045139160A713FACFF901A058B10990FFEA +:103FD00012C083E009D081E00D901D9005D032968B +:103FE000A713FACFF90185E087BFE895FFFF00002E +:0A3FF00017B610FCFDCF1124089550 +:063FFA000313CDCFE740E8 +:0400000300003E803B +:00000001FF diff --git a/avr/bootloaders/urboot/atmega161/watchdog_2_s/autobaud/urboot_m161_2s_autobaud_uart1_rxb2_txb3_no-led_pr_ee_ce.hex b/avr/bootloaders/urboot/atmega161/watchdog_2_s/autobaud/urboot_m161_2s_autobaud_uart1_rxb2_txb3_no-led_pr_ee_ce.hex new file mode 100644 index 00000000..9842829a --- /dev/null +++ b/avr/bootloaders/urboot/atmega161/watchdog_2_s/autobaud/urboot_m161_2s_autobaud_uart1_rxb2_txb3_no-led_pr_ee_ce.hex @@ -0,0 +1,27 @@ +:103E800011248FE594E09EBF8DBF24B614BE80E060 +:103E900077D021FEDBC08FE073D0AFE7BFEFB299E0 +:103EA000FECF9096B29BFDCFB0B91197F1F782E0AB +:103EB00082B988E181B958D0C82F8235B1F464D075 +:103EC000E0E0FEE3A8959F0170E87E0F65916F3FEB +:103ED00011F4E713FBCFF90111F083E085D0E0582E +:103EE000F10980F789E53CD0E6CF8D7FD9F443D046 +:103EF000D82FA0E0B1E038D08D93DA13FCCFA0E04A +:103F0000B1E042D0C1110CC0FFBBEEBB8D918DBBA7 +:103F1000E29AE19A3196E199FECFD150A9F7E2CF2A +:103F20003DD0E0CFC33041F426D0C82F2DD08591AD +:103F300017D0C150E1F7D6CFC13061F41CD0C82FE3 +:103F400023D0FFBBEEBBE09A8DB30AD03196C150AF +:103F5000C1F7C8CFC13511F488E012D015D0C2CF57 +:103F6000159BFECF83B90895179BFECF14990FC000 +:103F7000A89583B10895F8DFE82FF6DFF82FF4CF86 +:103F800098E191BD81BD0895EFDF803219F088E09E +:103F9000F7DFFFCF80EAE4CFFB01DC01E07870E8D7 +:103FA0007A0F9F01E0388EE3F80728F5309629F460 +:103FB0008FE38D938FEC8C93119790E045915D91F9 +:103FC00045139160A713FACFF901A058B10990FFEA +:103FD00012C083E009D081E00D901D9005D032968B +:103FE000A713FACFF90185E087BFE895FFFF00002E +:0A3FF00017B610FCFDCF1124089550 +:063FFA000313CDCFE740E8 +:0400000300003E803B +:00000001FF diff --git a/avr/programmers.txt b/avr/programmers.txt old mode 100755 new mode 100644 From 59185bf833f292ceddd4460df4d98d9ce5bb2460 Mon Sep 17 00:00:00 2001 From: Lucas <10280695+Lukelectro@users.noreply.github.com> Date: Fri, 13 Feb 2026 22:17:06 +0100 Subject: [PATCH 06/11] Add Atmega161 to suported in Readme.md It is still work in progress, PWM/tone() is untested, but at least serial.print works and the bootloader works --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 70de09e9..27ade568 100644 --- a/README.md +++ b/README.md @@ -35,6 +35,7 @@ If you already have Optiboot installed and don't want to replace it with Urboot, ## Supported microcontrollers * ATmega162 * ATmega8515 +* ATmega161 ## Supported clock frequencies From 34a49f9ea22d46a8ec0286f44130f35f9de6a78b Mon Sep 17 00:00:00 2001 From: Lucas <10280695+Lukelectro@users.noreply.github.com> Date: Sat, 14 Feb 2026 20:20:26 +0100 Subject: [PATCH 07/11] bootloader path file extention --- avr/boards.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/avr/boards.txt b/avr/boards.txt index 31277243..f87af957 100644 --- a/avr/boards.txt +++ b/avr/boards.txt @@ -257,7 +257,7 @@ menu.JTAG=JTAG pins 161.menu.bootloader.uart0.upload.protocol=urclock 161.menu.bootloader.uart0.upload.uartpins=uart0_rxd0_txd1 161.menu.bootloader.uart0.build.export_merged_output=true -161.menu.bootloader.uart0.bootloader.file=urboot/{build.mcu}/watchdog_2_s/autobaud/urboot_m161_2s_autobaud_uart0_rxd0_txd1_no-led_pr_ee_ce +161.menu.bootloader.uart0.bootloader.file=urboot/{build.mcu}/watchdog_2_s/autobaud/urboot_m161_2s_autobaud_uart0_rxd0_txd1_no-led_pr_ee_ce.hex 161.menu.bootloader.uart1=Yes (UART1) 161.menu.bootloader.uart1.upload.maximum_size=16000 From 85cdbc19e2770b64f19ba5622618e1b01c81f7a1 Mon Sep 17 00:00:00 2001 From: Lucas <10280695+Lukelectro@users.noreply.github.com> Date: Wed, 25 Feb 2026 23:49:41 +0100 Subject: [PATCH 08/11] make analogWrite work on PB1 (timer2). Not tested on others. tone() still does not work (pin stays low) --- avr/cores/MCUdude_corefiles/wiring.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/avr/cores/MCUdude_corefiles/wiring.c b/avr/cores/MCUdude_corefiles/wiring.c index 9d2bf2ec..0fd03e4e 100755 --- a/avr/cores/MCUdude_corefiles/wiring.c +++ b/avr/cores/MCUdude_corefiles/wiring.c @@ -1020,6 +1020,9 @@ void init() TCCR2 |= _BV(WGM20); #elif defined(TCCR2A) && defined(WGM20) TCCR2A |= _BV(WGM20); +#elif defined(__AVR_ATmega161__) +//atmega161 has TCCR2, but no WGM20 as it has no phase correct PWM. It has PWM though: + TCCR2 |= _BV(PWM2); //#else // Timer 2 not finished (may not be present on this CPU) #endif From 300fdc3a747b4237277dfb67083462c7e0f33b9a Mon Sep 17 00:00:00 2001 From: Lucas <10280695+Lukelectro@users.noreply.github.com> Date: Thu, 26 Feb 2026 00:03:28 +0100 Subject: [PATCH 09/11] Timer 1 analogwrite/PWM now works on pins PD5 and PE2 --- avr/cores/MCUdude_corefiles/wiring.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/avr/cores/MCUdude_corefiles/wiring.c b/avr/cores/MCUdude_corefiles/wiring.c index 0fd03e4e..d124c483 100755 --- a/avr/cores/MCUdude_corefiles/wiring.c +++ b/avr/cores/MCUdude_corefiles/wiring.c @@ -1004,6 +1004,8 @@ void init() #endif #if defined(TCCR1A) && defined(WGM10) TCCR1A |= _BV(WGM10); // Put timer 1 in 8-bit phase correct pwm mode +#elif defined(__AVR_ATmega161__) + TCCR1A |= _BV(PWM10); // Put timer 1 in 8-bit phase correct pwm mode #endif // Set timer 2 prescale factor to 64 From 653d0f08288e4228c4ccde69aaf8c160f92b2a7c Mon Sep 17 00:00:00 2001 From: Lucas <10280695+Lukelectro@users.noreply.github.com> Date: Thu, 26 Feb 2026 00:22:49 +0100 Subject: [PATCH 10/11] timer 0 analogwrite now works on PB0 and it does not even break millis(). Still no tone() --- avr/cores/MCUdude_corefiles/wiring.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/avr/cores/MCUdude_corefiles/wiring.c b/avr/cores/MCUdude_corefiles/wiring.c index d124c483..b45d4ae5 100755 --- a/avr/cores/MCUdude_corefiles/wiring.c +++ b/avr/cores/MCUdude_corefiles/wiring.c @@ -962,11 +962,15 @@ void init() // CPU specific: different values for the ATmega64/128 TCCR0 |= _BV(WGM01) | _BV(WGM00) | _BV(CS02); #elif defined(TCCR0) && defined(CS01) && defined(CS00) - // This combination is for the ATmega8535, ATmega8, ATmega16, ATmega32, ATmega8515, ATmega162 + // This combination is for the ATmega8535, ATmega8, ATmega16, ATmega32, ATmega8515, ATmega162, ATmega161 TCCR0 |= _BV(CS01) | _BV(CS00); #if defined(WGM00) && defined(WGM01) // The ATmega8 doesn't have WGM00 and WGM01 TCCR0 |= _BV(WGM01) | _BV(WGM00); #endif + #if defined(__AVR_ATmega161__) + TCCR0 |= _BV(PWM0)|_BV(CTC0); // Atmega161 has no WGM00 and WGM01, it has PWM0 and CTC. see datasheet, as function might differ. + //setting only PWM0 breaks millis(); as the counter then counts up and back down. Setting CTC also makes it count up only. + #endif #elif defined(TCCR0B) && defined(CS01) && defined(CS00) // This combination is for the standard 168/328/640/1280/1281/2560/2561 TCCR0B |= _BV(CS01) | _BV(CS00); From c92e95300ef028f5fd09723d762f2d733b133151 Mon Sep 17 00:00:00 2001 From: Lucas <10280695+Lukelectro@users.noreply.github.com> Date: Mon, 2 Mar 2026 21:20:27 +0100 Subject: [PATCH 11/11] Tone() now works on atmega161, it uses timer1 so it can be used with analogWrite on PB0 and PB1 which use timer2 and timer0 respectively, but not with the analogWrite on the pins that use timer1 (PE2 and PD5) --- avr/cores/MCUdude_corefiles/Tone.cpp | 36 +++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/avr/cores/MCUdude_corefiles/Tone.cpp b/avr/cores/MCUdude_corefiles/Tone.cpp index ed289afa..d36c0a15 100755 --- a/avr/cores/MCUdude_corefiles/Tone.cpp +++ b/avr/cores/MCUdude_corefiles/Tone.cpp @@ -95,7 +95,7 @@ volatile uint8_t timer2_pin_mask; -#if defined(__AVR_ATmega8515__) || defined(__AVR_ATmega162__) +#if defined(__AVR_ATmega8515__) || defined(__AVR_ATmega162__) || defined(__AVR_ATmega161__) #define AVAILABLE_TONE_PINS 1 #define USE_TIMER1 const uint8_t PROGMEM tone_pin_to_timer_PGM[] = { 1 /*, 0 */ }; @@ -202,6 +202,17 @@ static int8_t toneBegin(uint8_t _pin) break; #endif + #if defined(TCCR0) && defined(CTC0) // atmega161 + case 0: + // 8 bit timer + TCCR0 = 0; + bitWrite(TCCR0, CTC0, 1); + bitWrite(TCCR0, CS00, 1); + timer0_pin_port = portOutputRegister(digitalPinToPort(_pin)); + timer0_pin_mask = digitalPinToBitMask(_pin); + break; + #endif + #if defined(TCCR1A) && defined(TCCR1B) && defined(WGM12) case 1: // 16 bit timer @@ -214,6 +225,18 @@ static int8_t toneBegin(uint8_t _pin) break; #endif + #if defined(TCCR1A) && defined(TCCR1B) && defined(CTC1) // atmega161 + case 1: + // 16 bit timer + TCCR1A = 0; + TCCR1B = 0; + bitWrite(TCCR1B, CTC1, 1); + bitWrite(TCCR1B, CS10, 1); + timer1_pin_port = portOutputRegister(digitalPinToPort(_pin)); + timer1_pin_mask = digitalPinToBitMask(_pin); + break; + #endif + #if defined(TCCR2A) && defined(TCCR2B) case 2: // 8 bit timer @@ -226,6 +249,17 @@ static int8_t toneBegin(uint8_t _pin) break; #endif + #if defined(TCCR2) && defined(CTC2) // atmega161 + case 2: + // 8 bit timer + TCCR2 = 0; + bitWrite(TCCR0, CTC2, 1); + bitWrite(TCCR2, CS20, 1); + timer0_pin_port = portOutputRegister(digitalPinToPort(_pin)); + timer0_pin_mask = digitalPinToBitMask(_pin); + break; + #endif + #if defined(TCCR3A) && defined(TCCR3B) && defined(TIMSK3) case 3: // 16 bit timer