Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ATmega128 support #30

Merged
merged 5 commits into from
Oct 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions ATmega/vendor/libraries/TimerOne/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#TimerOne Library

Paul Stoffregen's modified TimerOne. This version provides 2 main benefits:

1: Optimized inline functions - much faster for the most common usage
2: Support for more boards (including ATTiny85 except for the PWM functionality)

http://www.pjrc.com/teensy/td_libs_TimerOne.html

https://github.com/PaulStoffregen/TimerOne

Original code

http://playground.arduino.cc/Code/Timer1

Open Source License

TimerOne is free software. You can redistribute it and/or modify it under
the terms of Creative Commons Attribution 3.0 United States License.
To view a copy of this license, visit

http://creativecommons.org/licenses/by/3.0/us/

Paul Stoffregen forked this version from an early copy of TimerOne/TimerThree
which was licensed "Creative Commons Attribution 3.0" and has maintained
the original "CC BY 3.0 US" license terms.

Other, separately developed updates to TimerOne have been released by other
authors under the GNU GPLv2 license. Multiple copies of this library, bearing
the same name but distributed under different license terms, is unfortunately
confusing. This copy, with nearly all the code redesigned as inline functions,
is provided under the "CC BY 3.0 US" license terms.

44 changes: 22 additions & 22 deletions ATmega/vendor/libraries/TimerOne/TimerOne.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,12 @@
* Modified April 2012 by Paul Stoffregen - portable to other AVR chips, use inline functions
* Modified again, June 2014 by Paul Stoffregen - support Teensy 3.x & even more AVR chips
* Modified July 2017 by Stoyko Dimitrov - added support for ATTiny85 except for the PWM functionality
*
* Modified August 2024 by Nathan Cheek - added support for ATmega128
*
*
* This is free software. You can redistribute it and/or modify it under
* the terms of Creative Commons Attribution 3.0 United States License.
* To view a copy of this license, visit http://creativecommons.org/licenses/by/3.0/us/
* the terms of Creative Commons Attribution 3.0 United States License.
* To view a copy of this license, visit http://creativecommons.org/licenses/by/3.0/us/
* or send a letter to Creative Commons, 171 Second Street, Suite 300, San Francisco, California, 94105, USA.
*
*/
Expand Down Expand Up @@ -52,7 +53,7 @@ class TimerOne
TIMSK |= _BV(OCIE1A); //enable interrupt when OCR1A matches the timer value
setPeriod(microseconds);
}
void setPeriod(unsigned long microseconds) __attribute__((always_inline)) {
void setPeriod(unsigned long microseconds) __attribute__((always_inline)) {
const unsigned long cycles = microseconds * ratio;
if (cycles < TIMER1_RESOLUTION) {
clockSelectBits = _BV(CS10);
Expand Down Expand Up @@ -121,13 +122,13 @@ class TimerOne
OCR1C = pwmPeriod;
TCCR1 = _BV(CTC1) | clockSelectBits;
}

//****************************
// Run Control
//****************************
//****************************
void start() __attribute__((always_inline)) {
TCCR1 = 0;
TCNT1 = 0;
TCNT1 = 0;
resume();
}
void stop() __attribute__((always_inline)) {
Expand All @@ -139,13 +140,13 @@ class TimerOne
void resume() __attribute__((always_inline)) {
TCCR1 = _BV(CTC1) | clockSelectBits;
}

//****************************
// PWM outputs
//****************************
//Not implemented yet for ATTiny85
//TO DO

//****************************
// Interrupt Function
//****************************
Expand All @@ -168,21 +169,21 @@ class TimerOne
static unsigned short pwmPeriod;
static unsigned char clockSelectBits;
static const byte ratio = (F_CPU)/ ( 1000000 );

#elif defined(__AVR__)

#if defined (__AVR_ATmega8__) || defined (__AVR_ATmega128__)
//in some io definitions for older microcontrollers TIMSK is used instead of TIMSK1
#define TIMSK1 TIMSK
#endif

public:
//****************************
// Configuration
//****************************
void initialize(unsigned long microseconds=1000000) __attribute__((always_inline)) {
TCCR1B = _BV(WGM13); // set mode as phase and frequency correct pwm, stop the timer
TCCR1A = 0; // clear control register A
TCCR1A = 0; // clear control register A
setPeriod(microseconds);
}
void setPeriod(unsigned long microseconds) __attribute__((always_inline)) {
Expand Down Expand Up @@ -275,26 +276,25 @@ class TimerOne
//****************************
// Interrupt Function
//****************************

void attachInterrupt(void (*isr)()) __attribute__((always_inline)) {
isrCallback = isr;

#if defined(__AVR_ATmega128__)
TIMSK1 |= _BV(TOIE1);
TIMSK1 &= ~(_BV(TICIE1) | _BV(OCIE1A) | _BV(OCIE1B));
TIMSK1 |= _BV(TOIE1);
TIMSK1 &= ~(_BV(TICIE1) | _BV(OCIE1A) | _BV(OCIE1B));
#else
TIMSK1 = _BV(TOIE1);
TIMSK1 = _BV(TOIE1);
#endif
}
void attachInterrupt(void (*isr)(), unsigned long microseconds) __attribute__((always_inline)) {
if(microseconds > 0) setPeriod(microseconds);
attachInterrupt(isr);
}
void detachInterrupt() __attribute__((always_inline)) {
#if defined(__AVR_ATmega128__)
TIMSK1 &= ~(_BV(TOIE1) | _BV(TICIE1) | _BV(OCIE1A) | _BV(OCIE1B));
#if defined(__AVR_ATmega128__)
TIMSK1 &= ~(_BV(TOIE1) | _BV(TICIE1) | _BV(OCIE1A) | _BV(OCIE1B));
#else
TIMSK1 = 0;
TIMSK1 = 0;
#endif
}
static void (*isrCallback)();
Expand Down Expand Up @@ -339,10 +339,10 @@ class TimerOne
// This is like a binary serch tree and no more than 3 conditions are evaluated.
// I haven't checked if this becomes significantly longer ASM than the simple ladder.
// It looks very similar to the ladder tho: same # of if's and else's

/*
// This code does not work properly in all cases :(
// https://github.com/PaulStoffregen/TimerOne/issues/17
// https://github.com/PaulStoffregen/TimerOne/issues/17
if (cycles < TIMER1_RESOLUTION * 16) {
if (cycles < TIMER1_RESOLUTION * 4) {
if (cycles < TIMER1_RESOLUTION) {
Expand Down
13 changes: 10 additions & 3 deletions ATmega/vendor/libraries/TimerOne/config/known_16bit_timers.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@
#define TIMER3_A_PIN 32
#define TIMER3_B_PIN 25
#define TIMER3_ICP_PIN 32

// Teensy 3.5 / Teensy 3.6
//
#elif defined(__MK64FX512__) || defined(__MK66FX1M0__)
Expand All @@ -58,7 +58,7 @@
#define TIMER3_A_PIN 29
#define TIMER3_B_PIN 30
#define TIMER3_ICP_PIN 29

// Teensy-LC
//
#elif defined(__MKL26Z64__)
Expand Down Expand Up @@ -121,7 +121,7 @@
#define TIMER1_B_PIN 10
#define TIMER1_ICP_PIN 8
#define TIMER1_CLK_PIN 5
#elif defined(__AVR_ATmega328PB__)
#elif defined(__AVR_ATmega328PB__)
#define TIMER1_A_PIN 9
#define TIMER1_B_PIN 10
#define TIMER1_ICP_PIN 8
Expand All @@ -142,6 +142,13 @@
#define TIMER1_B_PIN 11
//#define TIMER1_ICP_PIN 8
//#define TIMER1_CLK_PIN 5

#elif defined (__AVR_ATmega128__)
#define TIMER1_A_PIN 13 // PB5
#define TIMER1_B_PIN 14 // PB6
#define TIMER1_C_PIN 15 // PB7
#define TIMER1_ICP_PIN 22 // PD4
#define TIMER1_CLK_PIN 24 // PD6

// Sanguino
//
Expand Down
4 changes: 2 additions & 2 deletions ATmega/vendor/libraries/TimerOne/library.properties
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name=TimerOne
version=1.1
author=Stoyko Dimitrov, Jesse Tane, Jérôme Despatis, Michael Polli, Dan Clemens, Paul Stoffregen
version=1.1.1
author=Stoyko Dimitrov, Jesse Tane, Jérôme Despatis, Michael Polli, Dan Clemens, Nathan Cheek, Paul Stoffregen
maintainer=Paul Stoffregen
sentence=Use hardware Timer1 for finer PWM control and/or running an periodic interrupt function
paragraph=
Expand Down
2 changes: 1 addition & 1 deletion Arduino/Drv/HardwareRateDriver/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ elseif (IS_TEENSY)
target_use_arduino_libraries("IntervalTimer")
list(APPEND SOURCE_FILES "${CMAKE_CURRENT_LIST_DIR}/HardwareRateDriverTeensy.cpp")
elseif (IS_ATMEGA)
target_use_arduino_libraries("TimerOne")
list(APPEND SOURCE_FILES "${CMAKE_CURRENT_LIST_DIR}/../../../ATmega/vendor/libraries/TimerOne/TimerOne.cpp")
list(APPEND SOURCE_FILES "${CMAKE_CURRENT_LIST_DIR}/HardwareRateDriverAvr.cpp")
else()
list(APPEND SOURCE_FILES "${CMAKE_CURRENT_LIST_DIR}/HardwareRateDriverBasic.cpp")
Expand Down
4 changes: 2 additions & 2 deletions Arduino/Drv/HardwareRateDriver/HardwareRateDriver.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,13 @@ namespace Arduino {
public:
/**
* Construct the rate driver. Takes in a name (if configured) and a
* rate at witch to drive.
* rate at which to drive.
* \param const char* compName: name of the component (only supply if configured)
*/
HardwareRateDriver(const char* compName);

/**
* Configure theis component with the interval time in milliseconds.
* Configure this component with the interval time in milliseconds.
* \param U32 intervalMs: interval to ping in milliseconds
*/
void configure(U32 intervalMs);
Expand Down
2 changes: 1 addition & 1 deletion Arduino/Drv/HardwareRateDriver/HardwareRateDriverAvr.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#include <Fw/Types/BasicTypes.hpp>
#include <ATmega/Drv/HardwareRateDriver/HardwareRateDriver.hpp>
#include <Arduino.h>
#include <TimerOne.h>
#include <ATmega/vendor/libraries/TimerOne/TimerOne.h>

namespace Arduino {

Expand Down
10 changes: 6 additions & 4 deletions cmake/toolchain/ATmega128.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# ATmega128.cmake:
#
# Arduino MegaCore ATmega128 support file. This file ensures that the
# ATmega128 can be useds as a target for the CMake system's output. This
# ATmega128 can be used as a target for the CMake system's output. This
# sets the Arduino target to be the MegaCore ATmega128.
####

Expand All @@ -13,11 +13,13 @@ set(CMAKE_SYSTEM_PROCESSOR "avr")
set(CMAKE_CROSSCOMPILING 1)
set(FPRIME_PLATFORM "ArduinoFw")
set(FPRIME_USE_BAREMETAL_SCHEDULER ON)
# set(ARDUINO_LIBRARIES "SPI.h" "Wire.h" "TimerOne.h")
# set(ARDUINO_BUILD_PROPERTIES "build.extra_flags=-DTIMER1_A_PIN=13 -DTIMSK1=TIMSK")
set(ARDUINO_BUILD_PROPERTIES "build.extra_flags=-flto -mrelax -mcall-prologues")
set(ARDUINO_BOARD_OPTIONS "clock=7_3728MHz_external")
set(ARDUINO_LINKER_FLAGS "-Wl,--section-start,.data=0x801100,--defsym=__heap_end=0x80ffff")

set(ARDUINO_FQBN "MegaCore:avr:128")
add_compile_options(-DATMEGA)
# Run the base arduino setup which should detect settings!
include("${CMAKE_CURRENT_LIST_DIR}/support/arduino-support.cmake")
# include_directories("${CMAKE_CURRENT_LIST_DIR}/../../ATmega/vendor/libraries/TimerOne")
# Use the ranlib wrapper which adds the appropriate --plugin option for the compiler
SET(CMAKE_RANLIB "${CMAKE_CXX_COMPILER_RANLIB}")
13 changes: 10 additions & 3 deletions cmake/toolchain/support/arduino-support.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ function(set_arduino_build_settings)
# If it was not found, generate it
if (NOT FOUND_LOCATION)
set(FOUND_LOCATION "${ARDUINO_WRAPPER_JSON_OUTPUT}")
run_arduino_wrapper("-b" "${ARDUINO_FQBN}" "--properties" ${ARDUINO_BUILD_PROPERTIES} -j "${FOUND_LOCATION}")
run_arduino_wrapper("-b" "${ARDUINO_FQBN}" "--properties" ${ARDUINO_BUILD_PROPERTIES} "--board-options" ${ARDUINO_BOARD_OPTIONS} -j "${FOUND_LOCATION}")
endif()
file(READ "${FOUND_LOCATION}" WRAPPER_OUTPUT)
# Compilers detection
Expand All @@ -64,6 +64,11 @@ function(set_arduino_build_settings)
string(REPLACE ";" " " "${LIST_VARIABLE}" "${${LIST_VARIABLE}}")
endforeach()

# Add additional linker flags if provided
if (ARDUINO_LINKER_FLAGS)
string(APPEND CMAKE_EXE_LINKER_FLAGS_INIT " ${ARDUINO_LINKER_FLAGS}")
endif()

read_json(INCLUDES "${WRAPPER_OUTPUT}" includes CXX)
include_directories(${INCLUDES})
if (NOT TARGET fprime_arduino_libraries)
Expand Down Expand Up @@ -116,7 +121,9 @@ function(setup_arduino_libraries)
prevent_prescan(${ARDUINO_LIBRARY_LIST_LOCAL} fprime_arduino_patcher fprime_arduino_loose_object_library)
run_arduino_wrapper(
-b "${ARDUINO_FQBN}"
--properties ${ARDUINO_BUILD_PROPERTIES} -j "${ARDUINO_WRAPPER_JSON_OUTPUT}"
--properties ${ARDUINO_BUILD_PROPERTIES}
--board-options ${ARDUINO_BOARD_OPTIONS}
-j "${ARDUINO_WRAPPER_JSON_OUTPUT}"
--generate-code
--libraries ${ARDUINO_LIBRARY_LIST_LOCAL}
)
Expand All @@ -134,7 +141,7 @@ function(setup_arduino_libraries)
set_property(TARGET fprime_arduino_patcher PROPERTY LINK_LIBRARIES ${TARGET_LIBRARIES})
endif()

# Setup library to capture loose object files from arduino-cli compile
# Setup library to capture loose object files from arduino-cli compile
if (NOT TARGET fprime_arduino_loose_object_library)
add_library(fprime_arduino_loose_object_library OBJECT IMPORTED GLOBAL)
set_target_properties(fprime_arduino_loose_object_library PROPERTIES IMPORTED_OBJECTS "${OBJECTS}")
Expand Down
2 changes: 1 addition & 1 deletion cmake/toolchain/support/arduino-wrapper.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ endfunction(run_arduino_wrapper)
###
# Function `read_json`:
#
# A wrapper to help read JOSN data as native-cmake types.
# A wrapper to help read JSON data as native-cmake types.
#
# Args:
# VARIABLE_NAME: variable to set
Expand Down