diff --git a/MyCity/app/src/main/java/gq/yigit/mycity/CrashMapFragment.java b/MyCity/app/src/main/java/gq/yigit/mycity/CrashMapFragment.java new file mode 100644 index 0000000..2d684f5 --- /dev/null +++ b/MyCity/app/src/main/java/gq/yigit/mycity/CrashMapFragment.java @@ -0,0 +1,118 @@ +package gq.yigit.mycity; + +import android.content.Context; +import android.net.Uri; +import android.os.Bundle; +import android.support.v4.app.Fragment; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import com.google.android.gms.maps.MapView; +import com.google.android.gms.maps.model.LatLng; + +import java.util.ArrayList; + +/** + * A simple {@link Fragment} subclass. + * Activities that contain this fragment must implement the + * {@link CrashMapFragment.OnFragmentInteractionListener} interface + * to handle interaction events. + * Use the {@link CrashMapFragment#newInstance} factory method to + * create an instance of this fragment. + */ + +public class CrashMapFragment extends Fragment { + // TODO: Rename parameter arguments, choose names that match + // the fragment initialization parameters, e.g. ARG_ITEM_NUMBER + private static final String ARG_PARAM1 = "param1"; + private static final String ARG_PARAM2 = "param2"; + + // TODO: Rename and change types of parameters + private String mParam1; + private String mParam2; + + MapView mMapView; + private GoogleMap googleMap; + + ArrayList markerPoints; + + private const String API_KEY = "AIzaSyCe3xvqc_FyrPDvu7MptJ3h2GyR1-EpCLw"; + + private OnFragmentInteractionListener mListener; + + public CrashMapFragment() { + } + + /** + * Use this factory method to create a new instance of + * this fragment using the provided parameters. + * + * @param param1 Parameter 1. + * @param param2 Parameter 2. + * @return A new instance of fragment CrashMapFragment. + */ + // TODO: Rename and change types and number of parameters + public static CrashMapFragment newInstance(String param1, String param2) { + CrashMapFragment fragment = new CrashMapFragment(); + Bundle args = new Bundle(); + args.putString(ARG_PARAM1, param1); + args.putString(ARG_PARAM2, param2); + fragment.setArguments(args); + return fragment; + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + if (getArguments() != null) { + mParam1 = getArguments().getString(ARG_PARAM1); + mParam2 = getArguments().getString(ARG_PARAM2); + } + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + // Inflate the layout for this fragment + return inflater.inflate(R.layout.fragment_crash_map, container, false); + } + + // TODO: Rename method, update argument and hook method into UI event + public void onButtonPressed(Uri uri) { + if (mListener != null) { + mListener.onFragmentInteraction(uri); + } + } + + @Override + public void onAttach(Context context) { + super.onAttach(context); + if (context instanceof OnFragmentInteractionListener) { + mListener = (OnFragmentInteractionListener) context; + } else { + throw new RuntimeException(context.toString() + + " must implement OnFragmentInteractionListener"); + } + } + + @Override + public void onDetach() { + super.onDetach(); + mListener = null; + } + + /** + * This interface must be implemented by activities that contain this + * fragment to allow an interaction in this fragment to be communicated + * to the activity and potentially other fragments contained in that + * activity. + *

+ * See the Android Training lesson Communicating with Other Fragments for more information. + */ + public interface OnFragmentInteractionListener { + // TODO: Update argument type and name + void onFragmentInteraction(Uri uri); + } +} diff --git a/MyCity/app/src/main/java/gq/yigit/mycity/MainActivity.java b/MyCity/app/src/main/java/gq/yigit/mycity/MainActivity.java index 3ed3595..8b8419c 100644 --- a/MyCity/app/src/main/java/gq/yigit/mycity/MainActivity.java +++ b/MyCity/app/src/main/java/gq/yigit/mycity/MainActivity.java @@ -69,6 +69,7 @@ public class MainActivity extends AppCompatActivity ComplaintsFragment.OnListFragmentInteractionListener, ComplaintViewFragment.OnFragmentInteractionListener, CrashFragment.OnFragmentInteractionListener, + CrashMapFragment.OnFragmentInteractionListener, responseListener, imageListener { @@ -281,6 +282,10 @@ public class MainActivity extends AppCompatActivity CrashFragment fragment= new CrashFragment(); fragmentTransaction.replace(R.id.app_bar_main, fragment); fragmentTransaction.commit(); + }else if (id == R.id.crash_map){ + CrashMapFragment fragment = new CrashMapFragment(); + fragmentTransaction.replace(R.id.app_bar_main, fragment); + fragmentTransaction.commit(); } diff --git a/MyCity/app/src/main/res/drawable-v24/crash_map.xml b/MyCity/app/src/main/res/drawable-v24/crash_map.xml new file mode 100644 index 0000000..799c218 --- /dev/null +++ b/MyCity/app/src/main/res/drawable-v24/crash_map.xml @@ -0,0 +1,14 @@ + + + + + + \ No newline at end of file diff --git a/MyCity/app/src/main/res/layout/fragment_crash_map.xml b/MyCity/app/src/main/res/layout/fragment_crash_map.xml new file mode 100644 index 0000000..7ca8cc7 --- /dev/null +++ b/MyCity/app/src/main/res/layout/fragment_crash_map.xml @@ -0,0 +1,10 @@ + + + + + \ No newline at end of file diff --git a/MyCity/app/src/main/res/menu/activity_main_drawer.xml b/MyCity/app/src/main/res/menu/activity_main_drawer.xml index 6579012..42253d5 100644 --- a/MyCity/app/src/main/res/menu/activity_main_drawer.xml +++ b/MyCity/app/src/main/res/menu/activity_main_drawer.xml @@ -24,6 +24,10 @@ android:icon="@drawable/crash" android:title="Car Crash"/> + + diff --git a/MyCity/classes/production/main/me/yigitcolakoglu/master_app/fan.png b/MyCity/classes/production/main/me/yigitcolakoglu/master_app/fan.png deleted file mode 100644 index 994a115..0000000 Binary files a/MyCity/classes/production/main/me/yigitcolakoglu/master_app/fan.png and /dev/null differ diff --git a/MyCity/classes/production/main/me/yigitcolakoglu/master_app/ips.json b/MyCity/classes/production/main/me/yigitcolakoglu/master_app/ips.json deleted file mode 100644 index be4ac40..0000000 --- a/MyCity/classes/production/main/me/yigitcolakoglu/master_app/ips.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "qr": "127.0.0.3", - "intersection": "127.0.0.1", - "ambulance": "127.0.0.1" -} \ No newline at end of file diff --git a/MyCity/classes/production/main/me/yigitcolakoglu/master_app/userinfo.json b/MyCity/classes/production/main/me/yigitcolakoglu/master_app/userinfo.json deleted file mode 100644 index 19c4e71..0000000 --- a/MyCity/classes/production/main/me/yigitcolakoglu/master_app/userinfo.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "usernames": { - "qr": "admin", - "ambulance": "yigit", - "intersection": "admin" - }, - "passwords": { - "qr": "admin", - "ambulance": "Ygtclksbl1", - "intersection": "admin" - } -} \ No newline at end of file diff --git a/bus_stop/bus_stop.iml b/bus_stop/bus_stop.iml index 88ad541..4940f2e 100644 --- a/bus_stop/bus_stop.iml +++ b/bus_stop/bus_stop.iml @@ -3,7 +3,7 @@ - + \ No newline at end of file diff --git a/client_side/client_side.iml b/client_side/client_side.iml index 88ad541..4940f2e 100644 --- a/client_side/client_side.iml +++ b/client_side/client_side.iml @@ -3,7 +3,7 @@ - + \ No newline at end of file diff --git a/master_app/target/classes/me/yigitcolakoglu/master_app/Main.class b/master_app/target/classes/me/yigitcolakoglu/master_app/Main.class deleted file mode 100644 index 5f50643..0000000 Binary files a/master_app/target/classes/me/yigitcolakoglu/master_app/Main.class and /dev/null differ diff --git a/master_app/target/classes/me/yigitcolakoglu/master_app/cameraForm$1.class b/master_app/target/classes/me/yigitcolakoglu/master_app/cameraForm$1.class deleted file mode 100644 index 70b2de1..0000000 Binary files a/master_app/target/classes/me/yigitcolakoglu/master_app/cameraForm$1.class and /dev/null differ diff --git a/master_app/target/classes/me/yigitcolakoglu/master_app/cameraForm$2.class b/master_app/target/classes/me/yigitcolakoglu/master_app/cameraForm$2.class deleted file mode 100644 index 4f6c378..0000000 Binary files a/master_app/target/classes/me/yigitcolakoglu/master_app/cameraForm$2.class and /dev/null differ diff --git a/master_app/target/classes/me/yigitcolakoglu/master_app/cameraForm$3.class b/master_app/target/classes/me/yigitcolakoglu/master_app/cameraForm$3.class deleted file mode 100644 index 7a1d4e3..0000000 Binary files a/master_app/target/classes/me/yigitcolakoglu/master_app/cameraForm$3.class and /dev/null differ diff --git a/master_app/target/classes/me/yigitcolakoglu/master_app/cameraForm$4.class b/master_app/target/classes/me/yigitcolakoglu/master_app/cameraForm$4.class deleted file mode 100644 index bc5b5d0..0000000 Binary files a/master_app/target/classes/me/yigitcolakoglu/master_app/cameraForm$4.class and /dev/null differ diff --git a/master_app/target/classes/me/yigitcolakoglu/master_app/cameraForm$5.class b/master_app/target/classes/me/yigitcolakoglu/master_app/cameraForm$5.class deleted file mode 100644 index 0f8b631..0000000 Binary files a/master_app/target/classes/me/yigitcolakoglu/master_app/cameraForm$5.class and /dev/null differ diff --git a/master_app/target/classes/me/yigitcolakoglu/master_app/cameraForm$6.class b/master_app/target/classes/me/yigitcolakoglu/master_app/cameraForm$6.class deleted file mode 100644 index 94ff0ca..0000000 Binary files a/master_app/target/classes/me/yigitcolakoglu/master_app/cameraForm$6.class and /dev/null differ diff --git a/master_app/target/classes/me/yigitcolakoglu/master_app/cameraForm.class b/master_app/target/classes/me/yigitcolakoglu/master_app/cameraForm.class deleted file mode 100644 index 834bc06..0000000 Binary files a/master_app/target/classes/me/yigitcolakoglu/master_app/cameraForm.class and /dev/null differ diff --git a/master_app/target/classes/me/yigitcolakoglu/master_app/managementForm$1.class b/master_app/target/classes/me/yigitcolakoglu/master_app/managementForm$1.class deleted file mode 100644 index f1aa674..0000000 Binary files a/master_app/target/classes/me/yigitcolakoglu/master_app/managementForm$1.class and /dev/null differ diff --git a/master_app/target/classes/me/yigitcolakoglu/master_app/managementForm$2.class b/master_app/target/classes/me/yigitcolakoglu/master_app/managementForm$2.class deleted file mode 100644 index 5c6e97e..0000000 Binary files a/master_app/target/classes/me/yigitcolakoglu/master_app/managementForm$2.class and /dev/null differ diff --git a/master_app/target/classes/me/yigitcolakoglu/master_app/managementForm$3.class b/master_app/target/classes/me/yigitcolakoglu/master_app/managementForm$3.class deleted file mode 100644 index fbd4df3..0000000 Binary files a/master_app/target/classes/me/yigitcolakoglu/master_app/managementForm$3.class and /dev/null differ diff --git a/master_app/target/classes/me/yigitcolakoglu/master_app/managementForm$4.class b/master_app/target/classes/me/yigitcolakoglu/master_app/managementForm$4.class deleted file mode 100644 index ea4e612..0000000 Binary files a/master_app/target/classes/me/yigitcolakoglu/master_app/managementForm$4.class and /dev/null differ diff --git a/master_app/target/classes/me/yigitcolakoglu/master_app/managementForm$5.class b/master_app/target/classes/me/yigitcolakoglu/master_app/managementForm$5.class deleted file mode 100644 index 3387011..0000000 Binary files a/master_app/target/classes/me/yigitcolakoglu/master_app/managementForm$5.class and /dev/null differ diff --git a/master_app/target/classes/me/yigitcolakoglu/master_app/managementForm$6.class b/master_app/target/classes/me/yigitcolakoglu/master_app/managementForm$6.class deleted file mode 100644 index 8ef68c3..0000000 Binary files a/master_app/target/classes/me/yigitcolakoglu/master_app/managementForm$6.class and /dev/null differ diff --git a/master_app/target/classes/me/yigitcolakoglu/master_app/managementForm$7.class b/master_app/target/classes/me/yigitcolakoglu/master_app/managementForm$7.class deleted file mode 100644 index 5c699ac..0000000 Binary files a/master_app/target/classes/me/yigitcolakoglu/master_app/managementForm$7.class and /dev/null differ diff --git a/master_app/target/classes/me/yigitcolakoglu/master_app/managementForm$8.class b/master_app/target/classes/me/yigitcolakoglu/master_app/managementForm$8.class deleted file mode 100644 index ff5972c..0000000 Binary files a/master_app/target/classes/me/yigitcolakoglu/master_app/managementForm$8.class and /dev/null differ diff --git a/master_app/target/classes/me/yigitcolakoglu/master_app/managementForm$9.class b/master_app/target/classes/me/yigitcolakoglu/master_app/managementForm$9.class deleted file mode 100644 index 8b1cd3e..0000000 Binary files a/master_app/target/classes/me/yigitcolakoglu/master_app/managementForm$9.class and /dev/null differ diff --git a/master_app/target/classes/me/yigitcolakoglu/master_app/managementForm.class b/master_app/target/classes/me/yigitcolakoglu/master_app/managementForm.class deleted file mode 100644 index 0989692..0000000 Binary files a/master_app/target/classes/me/yigitcolakoglu/master_app/managementForm.class and /dev/null differ diff --git a/traffic_analyzer/CMakeLists.2.txt/.idea/serialmonitor_settings.xml b/traffic_analyzer/CMakeLists.2.txt/.idea/serialmonitor_settings.xml new file mode 100644 index 0000000..b45564e --- /dev/null +++ b/traffic_analyzer/CMakeLists.2.txt/.idea/serialmonitor_settings.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/traffic_analyzer/CMakeLists.2.txt/.idea/vcs.xml b/traffic_analyzer/CMakeLists.2.txt/.idea/vcs.xml new file mode 100644 index 0000000..b2bdec2 --- /dev/null +++ b/traffic_analyzer/CMakeLists.2.txt/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/traffic_analyzer/CMakeLists.txt b/traffic_analyzer/CMakeLists.txt new file mode 100644 index 0000000..928ba94 --- /dev/null +++ b/traffic_analyzer/CMakeLists.txt @@ -0,0 +1,15 @@ +cmake_minimum_required(VERSION 2.8.4) +set(CMAKE_TOOLCHAIN_FILE ${CMAKE_SOURCE_DIR}/cmake/ArduinoToolchain.cmake) +set(PROJECT_NAME light_control) +project(${PROJECT_NAME}) + +set(${CMAKE_PROJECT_NAME}_SKETCH light_control.ino) + +#### Uncomment below additional settings as needed. +# set(${CMAKE_PROJECT_NAME}_BOARD mega) +# set(${CMAKE_PROJECT_NAME}_PORT /dev/ttyACM0) +# set(mega.build.mcu atmega2560) +# set(mega.upload.protocol wiring) +# set(mega.upload.speed 115200) + +generate_arduino_firmware(${CMAKE_PROJECT_NAME}) diff --git a/traffic_analyzer/cmake/ArduinoToolchain.cmake b/traffic_analyzer/cmake/ArduinoToolchain.cmake new file mode 100644 index 0000000..acda9cf --- /dev/null +++ b/traffic_analyzer/cmake/ArduinoToolchain.cmake @@ -0,0 +1,89 @@ +#=============================================================================# +# Author: Tomasz Bogdal (QueezyTheGreat) +# Home: https://github.com/queezythegreat/arduino-cmake +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this file, +# You can obtain one at http://mozilla.org/MPL/2.0/. +#=============================================================================# +set(CMAKE_SYSTEM_NAME Arduino) + +set(CMAKE_C_COMPILER avr-gcc) +set(CMAKE_CXX_COMPILER avr-g++) + +# Add current directory to CMake Module path automatically +if(EXISTS ${CMAKE_CURRENT_LIST_DIR}/Platform/Arduino.cmake) + set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_LIST_DIR}) +endif() + +#=============================================================================# +# System Paths # +#=============================================================================# +if(UNIX) + include(Platform/UnixPaths) + if(APPLE) + list(APPEND CMAKE_SYSTEM_PREFIX_PATH ~/Applications + /Applications + /Developer/Applications + /sw # Fink + /opt/local) # MacPorts + endif() +elseif(WIN32) + include(Platform/WindowsPaths) +endif() + + +#=============================================================================# +# Detect Arduino SDK # +#=============================================================================# +if(NOT ARDUINO_SDK_PATH) + set(ARDUINO_PATHS) + + foreach(DETECT_VERSION_MAJOR 1) + foreach(DETECT_VERSION_MINOR RANGE 5 0) + list(APPEND ARDUINO_PATHS arduino-${DETECT_VERSION_MAJOR}.${DETECT_VERSION_MINOR}) + foreach(DETECT_VERSION_PATCH RANGE 3 0) + list(APPEND ARDUINO_PATHS arduino-${DETECT_VERSION_MAJOR}.${DETECT_VERSION_MINOR}.${DETECT_VERSION_PATCH}) + endforeach() + endforeach() + endforeach() + + foreach(VERSION RANGE 23 19) + list(APPEND ARDUINO_PATHS arduino-00${VERSION}) + endforeach() + + if(UNIX) + file(GLOB SDK_PATH_HINTS /usr/share/arduino* + /opt/local/arduino* + /opt/arduino* + /usr/local/share/arduino*) + elseif(WIN32) + set(SDK_PATH_HINTS "C:\\Program Files\\Arduino" + "C:\\Program Files (x86)\\Arduino" + ) + endif() + list(SORT SDK_PATH_HINTS) + list(REVERSE SDK_PATH_HINTS) +endif() + +find_path(ARDUINO_SDK_PATH + NAMES lib/version.txt + PATH_SUFFIXES share/arduino + Arduino.app/Contents/Resources/Java/ + Arduino.app/Contents/Java/ + ${ARDUINO_PATHS} + HINTS ${SDK_PATH_HINTS} + DOC "Arduino SDK path.") + +if(ARDUINO_SDK_PATH) + list(APPEND CMAKE_SYSTEM_PREFIX_PATH ${ARDUINO_SDK_PATH}/hardware/tools/avr) + list(APPEND CMAKE_SYSTEM_PREFIX_PATH ${ARDUINO_SDK_PATH}/hardware/tools/avr/utils) +else() + message(FATAL_ERROR "Could not find Arduino SDK (set ARDUINO_SDK_PATH)!") +endif() + +set(ARDUINO_CPUMENU) +if(ARDUINO_CPU) + set(ARDUINO_CPUMENU ".menu.cpu.${ARDUINO_CPU}") +endif(ARDUINO_CPU) + diff --git a/traffic_analyzer/cmake/Platform/Arduino.cmake b/traffic_analyzer/cmake/Platform/Arduino.cmake new file mode 100644 index 0000000..42c6cbf --- /dev/null +++ b/traffic_analyzer/cmake/Platform/Arduino.cmake @@ -0,0 +1,2340 @@ +#=============================================================================# +# generate_arduino_firmware(name +# [BOARD board_id] +# [SKETCH sketch_path | +# SRCS src1 src2 ... srcN] +# [HDRS hdr1 hdr2 ... hdrN] +# [LIBS lib1 lib2 ... libN] +# [PORT port] +# [SERIAL serial_cmd] +# [PROGRAMMER programmer_id] +# [AFLAGS flags] +# [NO_AUTOLIBS] +# [MANUAL]) +# +#=============================================================================# +# +# generaters firmware and libraries for Arduino devices +# +# The arguments are as follows: +# +# name # The name of the firmware target [REQUIRED] +# BOARD # Board name (such as uno, mega2560, ...) [REQUIRED] +# SKETCH # Arduino sketch [must have SRCS or SKETCH] +# SRCS # Sources [must have SRCS or SKETCH] +# HDRS # Headers +# LIBS # Libraries to link +# ARDLIBS # Arduino libraries to link (Wire, Servo, SPI, etc) +# PORT # Serial port (enables upload support) +# SERIAL # Serial command for serial target +# PROGRAMMER # Programmer id (enables programmer support) +# AFLAGS # Avrdude flags for target +# NO_AUTOLIBS # Disables Arduino library detection +# MANUAL # (Advanced) Only use AVR Libc/Includes +# +# Here is a short example for a target named test: +# +# generate_arduino_firmware( +# NAME test +# SRCS test.cpp +# test2.cpp +# HDRS test.h test2.h +# BOARD uno) +# +# Alternatively you can specify the option by variables: +# +# set(test_SRCS test.cpp test2.cpp) +# set(test_HDRS test.h test2.h +# set(test_BOARD uno) +# +# generate_arduino_firmware(test) +# +# All variables need to be prefixed with the target name (${TARGET_NAME}_${OPTION}). +# +#=============================================================================# +# generate_avr_firmware(name +# [BOARD board_id] +# SRCS src1 src2 ... srcN] +# [HDRS hdr1 hdr2 ... hdrN] +# [LIBS lib1 lib2 ... libN] +# [PORT port] +# [SERIAL serial_cmd] +# [PROGRAMMER programmer_id] +# [AFLAGS flags]) +#=============================================================================# +# +# generaters firmware and libraries for AVR devices +# it simply calls generate_arduino_firmware() with NO_AUTOLIBS and MANUAL +# +# The arguments are as follows: +# +# name # The name of the firmware target [REQUIRED] +# BOARD # Board name (such as uno, mega2560, ...) [REQUIRED] +# SRCS # Sources [REQUIRED] +# HDRS # Headers +# LIBS # Libraries to link +# PORT # Serial port (enables upload support) +# SERIAL # Serial command for serial target +# PROGRAMMER # Programmer id (enables programmer support) +# AFLAGS # Avrdude flags for target +# +# Here is a short example for a target named test: +# +# generate_avr_firmware( +# NAME test +# SRCS test.cpp +# test2.cpp +# HDRS test.h test2.h +# BOARD uno) +# +# Alternatively you can specify the option by variables: +# +# set(test_SRCS test.cpp test2.cpp) +# set(test_HDRS test.h test2.h +# set(test_BOARD uno) +# +# generate_avr_firmware(test) +# +# All variables need to be prefixed with the target name (${TARGET_NAME}_${OPTION}). +# +#=============================================================================# +# generate_arduino_library(name +# [BOARD board_id] +# [SRCS src1 src2 ... srcN] +# [HDRS hdr1 hdr2 ... hdrN] +# [LIBS lib1 lib2 ... libN] +# [NO_AUTOLIBS] +# [MANUAL]) +#=============================================================================# +# generaters firmware and libraries for Arduino devices +# +# The arguments are as follows: +# +# name # The name of the firmware target [REQUIRED] +# BOARD # Board name (such as uno, mega2560, ...) [REQUIRED] +# SRCS # Sources [REQUIRED] +# HDRS # Headers +# LIBS # Libraries to link +# NO_AUTOLIBS # Disables Arduino library detection +# MANUAL # (Advanced) Only use AVR Libc/Includes +# +# Here is a short example for a target named test: +# +# generate_arduino_library( +# NAME test +# SRCS test.cpp +# test2.cpp +# HDRS test.h test2.h +# BOARD uno) +# +# Alternatively you can specify the option by variables: +# +# set(test_SRCS test.cpp test2.cpp) +# set(test_HDRS test.h test2.h +# set(test_BOARD uno) +# +# generate_arduino_library(test) +# +# All variables need to be prefixed with the target name (${TARGET_NAME}_${OPTION}). +# +#=============================================================================# +# generate_avr_library(name +# [BOARD board_id] +# [SRCS src1 src2 ... srcN] +# [HDRS hdr1 hdr2 ... hdrN] +# [LIBS lib1 lib2 ... libN]) +#=============================================================================# +# generaters firmware and libraries for AVR devices +# it simply calls generate_arduino_library() with NO_AUTOLIBS and MANUAL +# +# The arguments are as follows: +# +# name # The name of the firmware target [REQUIRED] +# BOARD # Board name (such as uno, mega2560, ...) [REQUIRED] +# SRCS # Sources [REQUIRED] +# HDRS # Headers +# LIBS # Libraries to link +# +# Here is a short example for a target named test: +# +# generate_avr_library( +# NAME test +# SRCS test.cpp +# test2.cpp +# HDRS test.h test2.h +# BOARD uno) +# +# Alternatively you can specify the option by variables: +# +# set(test_SRCS test.cpp test2.cpp) +# set(test_HDRS test.h test2.h +# set(test_BOARD uno) +# +# generate_avr_library(test) +# +# All variables need to be prefixed with the target name (${TARGET_NAME}_${OPTION}). +# +#=============================================================================# +# generate_arduino_example(name +# LIBRARY library_name +# EXAMPLE example_name +# [BOARD board_id] +# [PORT port] +# [SERIAL serial command] +# [PORGRAMMER programmer_id] +# [AFLAGS avrdude_flags]) +#=============================================================================# +# +# name - The name of the library example [REQUIRED] +# LIBRARY - Library name [REQUIRED] +# EXAMPLE - Example name [REQUIRED] +# BOARD - Board ID +# PORT - Serial port [optional] +# SERIAL - Serial command [optional] +# PROGRAMMER - Programmer id (enables programmer support) +# AFLAGS - Avrdude flags for target +# +# Creates a example from the specified library. +# +# +#=============================================================================# +# print_board_list() +#=============================================================================# +# +# Print list of detected Arduino Boards. +# +#=============================================================================# +# print_programmer_list() +#=============================================================================# +# +# Print list of detected Programmers. +# +#=============================================================================# +# print_programmer_settings(PROGRAMMER) +#=============================================================================# +# +# PROGRAMMER - programmer id +# +# Print the detected Programmer settings. +# +#=============================================================================# +# print_board_settings(ARDUINO_BOARD) +#=============================================================================# +# +# ARDUINO_BOARD - Board id +# +# Print the detected Arduino board settings. +# +#=============================================================================# +# register_hardware_platform(HARDWARE_PLATFORM_PATH) +#=============================================================================# +# +# HARDWARE_PLATFORM_PATH - Hardware platform path +# +# Registers a Hardware Platform path. +# See: http://code.google.com/p/arduino/wiki/Platforms +# +# This enables you to register new types of hardware platforms such as the +# Sagnuino, without having to copy the files into your Arduion SDK. +# +# A Hardware Platform is a directory containing the following: +# +# HARDWARE_PLATFORM_PATH/ +# |-- bootloaders/ +# |-- cores/ +# |-- variants/ +# |-- boards.txt +# `-- programmers.txt +# +# The board.txt describes the target boards and bootloaders. While +# programmers.txt the programmer defintions. +# +# A good example of a Hardware Platform is in the Arduino SDK: +# +# ${ARDUINO_SDK_PATH}/hardware/arduino/ +# +#=============================================================================# +# Configuration Options +#=============================================================================# +# +# ARDUINO_SDK_PATH - Arduino SDK Path +# ARDUINO_AVRDUDE_PROGRAM - Full path to avrdude programmer +# ARDUINO_AVRDUDE_CONFIG_PATH - Full path to avrdude configuration file +# +# ARDUINO_C_FLAGS - C compiler flags +# ARDUINO_CXX_FLAGS - C++ compiler flags +# ARDUINO_LINKER_FLAGS - Linker flags +# +# ARDUINO_DEFAULT_BOARD - Default Arduino Board ID when not specified. +# ARDUINO_DEFAULT_PORT - Default Arduino port when not specified. +# ARDUINO_DEFAULT_SERIAL - Default Arduino Serial command when not specified. +# ARDUINO_DEFAULT_PROGRAMMER - Default Arduino Programmer ID when not specified. +# +# +# ARDUINO_FOUND - Set to True when the Arduino SDK is detected and configured. +# ARDUINO_SDK_VERSION - Set to the version of the detected Arduino SDK (ex: 1.0) + +#=============================================================================# +# Author: Tomasz Bogdal (QueezyTheGreat) +# Home: https://github.com/queezythegreat/arduino-cmake +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this file, +# You can obtain one at http://mozilla.org/MPL/2.0/. +#=============================================================================# +cmake_minimum_required(VERSION 2.8.5) +include(CMakeParseArguments) + + + + + + +#=============================================================================# +# User Functions +#=============================================================================# + +#=============================================================================# +# [PUBLIC/USER] +# +# print_board_list() +# +# see documentation at top +#=============================================================================# +function(PRINT_BOARD_LIST) + foreach(PLATFORM ${ARDUINO_PLATFORMS}) + if(${PLATFORM}_BOARDS) + message(STATUS "${PLATFORM} Boards:") + print_list(${PLATFORM}_BOARDS) + message(STATUS "") + endif() + endforeach() +endfunction() + +#=============================================================================# +# [PUBLIC/USER] +# +# print_programmer_list() +# +# see documentation at top +#=============================================================================# +function(PRINT_PROGRAMMER_LIST) + foreach(PLATFORM ${ARDUINO_PLATFORMS}) + if(${PLATFORM}_PROGRAMMERS) + message(STATUS "${PLATFORM} Programmers:") + print_list(${PLATFORM}_PROGRAMMERS) + endif() + message(STATUS "") + endforeach() +endfunction() + +#=============================================================================# +# [PUBLIC/USER] +# +# print_programmer_settings(PROGRAMMER) +# +# see documentation at top +#=============================================================================# +function(PRINT_PROGRAMMER_SETTINGS PROGRAMMER) + if(${PROGRAMMER}.SETTINGS) + message(STATUS "Programmer ${PROGRAMMER} Settings:") + print_settings(${PROGRAMMER}) + endif() +endfunction() + +# [PUBLIC/USER] +# +# print_board_settings(ARDUINO_BOARD) +# +# see documentation at top +function(PRINT_BOARD_SETTINGS ARDUINO_BOARD) + if(${ARDUINO_BOARD}.SETTINGS) + message(STATUS "Arduino ${ARDUINO_BOARD} Board:") + print_settings(${ARDUINO_BOARD}) + endif() +endfunction() + +#=============================================================================# +# [PUBLIC/USER] +# see documentation at top +#=============================================================================# +function(GENERATE_ARDUINO_LIBRARY INPUT_NAME) + message(STATUS "Generating ${INPUT_NAME}") + parse_generator_arguments(${INPUT_NAME} INPUT + "NO_AUTOLIBS;MANUAL" # Options + "BOARD" # One Value Keywords + "SRCS;HDRS;LIBS" # Multi Value Keywords + ${ARGN}) + + if(NOT INPUT_BOARD) + set(INPUT_BOARD ${ARDUINO_DEFAULT_BOARD}) + endif() + if(NOT INPUT_MANUAL) + set(INPUT_MANUAL FALSE) + endif() + required_variables(VARS INPUT_SRCS INPUT_BOARD MSG "must define for target ${INPUT_NAME}") + + set(ALL_LIBS) + set(ALL_SRCS ${INPUT_SRCS} ${INPUT_HDRS}) + + if(NOT INPUT_MANUAL) + setup_arduino_core(CORE_LIB ${INPUT_BOARD}) + endif() + + find_arduino_libraries(TARGET_LIBS "${ALL_SRCS}" "") + set(LIB_DEP_INCLUDES) + foreach(LIB_DEP ${TARGET_LIBS}) + set(LIB_DEP_INCLUDES "${LIB_DEP_INCLUDES} -I\"${LIB_DEP}\"") + endforeach() + + if(NOT ${INPUT_NO_AUTOLIBS}) + setup_arduino_libraries(ALL_LIBS ${INPUT_BOARD} "${ALL_SRCS}" "" "${LIB_DEP_INCLUDES}" "") + endif() + + list(APPEND ALL_LIBS ${CORE_LIB} ${INPUT_LIBS}) + + add_library(${INPUT_NAME} ${ALL_SRCS}) + + get_arduino_flags(ARDUINO_COMPILE_FLAGS ARDUINO_LINK_FLAGS ${INPUT_BOARD} ${INPUT_MANUAL}) + + set_target_properties(${INPUT_NAME} PROPERTIES + COMPILE_FLAGS "${ARDUINO_COMPILE_FLAGS} ${COMPILE_FLAGS} ${LIB_DEP_INCLUDES}" + LINK_FLAGS "${ARDUINO_LINK_FLAGS} ${LINK_FLAGS}") + + target_link_libraries(${INPUT_NAME} ${ALL_LIBS} "-lc -lm") +endfunction() + +#=============================================================================# +# [PUBLIC/USER] +# see documentation at top +#=============================================================================# +function(GENERATE_AVR_LIBRARY INPUT_NAME) + message(STATUS "Generating ${INPUT_NAME}") + parse_generator_arguments(${INPUT_NAME} INPUT + "NO_AUTOLIBS;MANUAL" # Options + "BOARD" # One Value Keywords + "SRCS;HDRS;LIBS" # Multi Value Keywords + ${ARGN}) + + if(NOT INPUT_BOARD) + set(INPUT_BOARD ${ARDUINO_DEFAULT_BOARD}) + endif() + + required_variables(VARS INPUT_SRCS INPUT_BOARD MSG "must define for target ${INPUT_NAME}") + + if(INPUT_HDRS) + set( INPUT_HDRS "SRCS ${INPUT_HDRS}" ) + endif() + if(INPUT_LIBS) + set( INPUT_LIBS "LIBS ${INPUT_LIBS}" ) + endif() + + if(INPUT_HDRS) + list(INSERT INPUT_HDRS 0 "HDRS") + endif() + if(INPUT_LIBS) + list(INSERT INPUT_LIBS 0 "LIBS") + endif() + + + generate_arduino_library( ${INPUT_NAME} + NO_AUTOLIBS + MANUAL + BOARD ${INPUT_BOARD} + SRCS ${INPUT_SRCS} + ${INPUT_HDRS} + ${INPUT_LIBS} ) + +endfunction() + +#=============================================================================# +# [PUBLIC/USER] +# see documentation at top +#=============================================================================# +function(GENERATE_ARDUINO_FIRMWARE INPUT_NAME) + message(STATUS "Generating ${INPUT_NAME}") + parse_generator_arguments(${INPUT_NAME} INPUT + "NO_AUTOLIBS;MANUAL" # Options + "BOARD;PORT;SKETCH;PROGRAMMER" # One Value Keywords + "SERIAL;SRCS;HDRS;LIBS;ARDLIBS;AFLAGS" # Multi Value Keywords + ${ARGN}) + + if(NOT INPUT_BOARD) + set(INPUT_BOARD ${ARDUINO_DEFAULT_BOARD}) + endif() + if(NOT INPUT_PORT) + set(INPUT_PORT ${ARDUINO_DEFAULT_PORT}) + endif() + if(NOT INPUT_SERIAL) + set(INPUT_SERIAL ${ARDUINO_DEFAULT_SERIAL}) + endif() + if(NOT INPUT_PROGRAMMER) + set(INPUT_PROGRAMMER ${ARDUINO_DEFAULT_PROGRAMMER}) + endif() + if(NOT INPUT_MANUAL) + set(INPUT_MANUAL FALSE) + endif() + required_variables(VARS INPUT_BOARD MSG "must define for target ${INPUT_NAME}") + + set(ALL_LIBS) + set(ALL_SRCS ${INPUT_SRCS} ${INPUT_HDRS}) + set(LIB_DEP_INCLUDES) + + if(NOT INPUT_MANUAL) + setup_arduino_core(CORE_LIB ${INPUT_BOARD}) + endif() + + if(NOT "${INPUT_SKETCH}" STREQUAL "") + get_filename_component(INPUT_SKETCH "${INPUT_SKETCH}" ABSOLUTE) + setup_arduino_sketch(${INPUT_NAME} ${INPUT_SKETCH} ALL_SRCS) + if (IS_DIRECTORY "${INPUT_SKETCH}") + set(LIB_DEP_INCLUDES "${LIB_DEP_INCLUDES} -I\"${INPUT_SKETCH}\"") + else() + get_filename_component(INPUT_SKETCH_PATH "${INPUT_SKETCH}" PATH) + set(LIB_DEP_INCLUDES "${LIB_DEP_INCLUDES} -I\"${INPUT_SKETCH_PATH}\"") + endif() + endif() + + required_variables(VARS ALL_SRCS MSG "must define SRCS or SKETCH for target ${INPUT_NAME}") + + find_arduino_libraries(TARGET_LIBS "${ALL_SRCS}" "${INPUT_ARDLIBS}") + foreach(LIB_DEP ${TARGET_LIBS}) + arduino_debug_msg("Arduino Library: ${LIB_DEP}") + set(LIB_DEP_INCLUDES "${LIB_DEP_INCLUDES} -I\"${LIB_DEP}\" -I\"${LIB_DEP}/src\"") + endforeach() + + if(NOT INPUT_NO_AUTOLIBS) + setup_arduino_libraries(ALL_LIBS ${INPUT_BOARD} "${ALL_SRCS}" "${INPUT_ARDLIBS}" "${LIB_DEP_INCLUDES}" "") + foreach(LIB_INCLUDES ${ALL_LIBS_INCLUDES}) + arduino_debug_msg("Arduino Library Includes: ${LIB_INCLUDES}") + set(LIB_DEP_INCLUDES "${LIB_DEP_INCLUDES} ${LIB_INCLUDES}") + endforeach() + endif() + + list(APPEND ALL_LIBS ${CORE_LIB} ${INPUT_LIBS}) + + setup_arduino_target(${INPUT_NAME} ${INPUT_BOARD} "${ALL_SRCS}" "${ALL_LIBS}" "${LIB_DEP_INCLUDES}" "" "${INPUT_MANUAL}") + + if(INPUT_PORT) + setup_arduino_upload(${INPUT_BOARD} ${INPUT_NAME} ${INPUT_PORT} "${INPUT_PROGRAMMER}" "${INPUT_AFLAGS}") + endif() + + if(INPUT_SERIAL) + setup_serial_target(${INPUT_NAME} "${INPUT_SERIAL}" "${INPUT_PORT}") + endif() + +endfunction() + +#=============================================================================# +# [PUBLIC/USER] +# see documentation at top +#=============================================================================# +function(GENERATE_AVR_FIRMWARE INPUT_NAME) + # TODO: This is not optimal!!!! + message(STATUS "Generating ${INPUT_NAME}") + parse_generator_arguments(${INPUT_NAME} INPUT + "NO_AUTOLIBS;MANUAL" # Options + "BOARD;PORT;PROGRAMMER" # One Value Keywords + "SERIAL;SRCS;HDRS;LIBS;AFLAGS" # Multi Value Keywords + ${ARGN}) + + if(NOT INPUT_BOARD) + set(INPUT_BOARD ${ARDUINO_DEFAULT_BOARD}) + endif() + if(NOT INPUT_PORT) + set(INPUT_PORT ${ARDUINO_DEFAULT_PORT}) + endif() + if(NOT INPUT_SERIAL) + set(INPUT_SERIAL ${ARDUINO_DEFAULT_SERIAL}) + endif() + if(NOT INPUT_PROGRAMMER) + set(INPUT_PROGRAMMER ${ARDUINO_DEFAULT_PROGRAMMER}) + endif() + + required_variables(VARS INPUT_BOARD INPUT_SRCS MSG "must define for target ${INPUT_NAME}") + + if(INPUT_HDRS) + list(INSERT INPUT_HDRS 0 "HDRS") + endif() + if(INPUT_LIBS) + list(INSERT INPUT_LIBS 0 "LIBS") + endif() + if(INPUT_AFLAGS) + list(INSERT INPUT_AFLAGS 0 "AFLAGS") + endif() + + generate_arduino_firmware( ${INPUT_NAME} + NO_AUTOLIBS + MANUAL + BOARD ${INPUT_BOARD} + PORT ${INPUT_PORT} + PROGRAMMER ${INPUT_PROGRAMMER} + SERIAL ${INPUT_SERIAL} + SRCS ${INPUT_SRCS} + ${INPUT_HDRS} + ${INPUT_LIBS} + ${INPUT_AFLAGS} ) + +endfunction() + +#=============================================================================# +# [PUBLIC/USER] +# see documentation at top +#=============================================================================# +function(GENERATE_ARDUINO_EXAMPLE INPUT_NAME) + parse_generator_arguments(${INPUT_NAME} INPUT + "" # Options + "LIBRARY;EXAMPLE;BOARD;PORT;PROGRAMMER" # One Value Keywords + "SERIAL;AFLAGS" # Multi Value Keywords + ${ARGN}) + + + if(NOT INPUT_BOARD) + set(INPUT_BOARD ${ARDUINO_DEFAULT_BOARD}) + endif() + if(NOT INPUT_PORT) + set(INPUT_PORT ${ARDUINO_DEFAULT_PORT}) + endif() + if(NOT INPUT_SERIAL) + set(INPUT_SERIAL ${ARDUINO_DEFAULT_SERIAL}) + endif() + if(NOT INPUT_PROGRAMMER) + set(INPUT_PROGRAMMER ${ARDUINO_DEFAULT_PROGRAMMER}) + endif() + required_variables(VARS INPUT_LIBRARY INPUT_EXAMPLE INPUT_BOARD + MSG "must define for target ${INPUT_NAME}") + + message(STATUS "Generating ${INPUT_NAME}") + + set(ALL_LIBS) + set(ALL_SRCS) + + setup_arduino_core(CORE_LIB ${INPUT_BOARD}) + + setup_arduino_example("${INPUT_NAME}" "${INPUT_LIBRARY}" "${INPUT_EXAMPLE}" ALL_SRCS) + + if(NOT ALL_SRCS) + message(FATAL_ERROR "Missing sources for example, aborting!") + endif() + + find_arduino_libraries(TARGET_LIBS "${ALL_SRCS}" "") + set(LIB_DEP_INCLUDES) + foreach(LIB_DEP ${TARGET_LIBS}) + set(LIB_DEP_INCLUDES "${LIB_DEP_INCLUDES} -I\"${LIB_DEP}\"") + endforeach() + + setup_arduino_libraries(ALL_LIBS ${INPUT_BOARD} "${ALL_SRCS}" "" "${LIB_DEP_INCLUDES}" "") + + list(APPEND ALL_LIBS ${CORE_LIB} ${INPUT_LIBS}) + + setup_arduino_target(${INPUT_NAME} ${INPUT_BOARD} "${ALL_SRCS}" "${ALL_LIBS}" "${LIB_DEP_INCLUDES}" "" FALSE) + + if(INPUT_PORT) + setup_arduino_upload(${INPUT_BOARD} ${INPUT_NAME} ${INPUT_PORT} "${INPUT_PROGRAMMER}" "${INPUT_AFLAGS}") + endif() + + if(INPUT_SERIAL) + setup_serial_target(${INPUT_NAME} "${INPUT_SERIAL}" "${INPUT_PORT}") + endif() +endfunction() + +#=============================================================================# +# [PUBLIC/USER] +# see documentation at top +#=============================================================================# +function(REGISTER_HARDWARE_PLATFORM PLATFORM_PATH) + string(REGEX REPLACE "/$" "" PLATFORM_PATH ${PLATFORM_PATH}) + GET_FILENAME_COMPONENT(PLATFORM ${PLATFORM_PATH} NAME) + + if(PLATFORM) + string(TOUPPER ${PLATFORM} PLATFORM) + list(FIND ARDUINO_PLATFORMS ${PLATFORM} platform_exists) + + if (platform_exists EQUAL -1) + set(${PLATFORM}_PLATFORM_PATH ${PLATFORM_PATH} CACHE INTERNAL "The path to ${PLATFORM}") + set(ARDUINO_PLATFORMS ${ARDUINO_PLATFORMS} ${PLATFORM} CACHE INTERNAL "A list of registered platforms") + + find_file(${PLATFORM}_CORES_PATH + NAMES cores + PATHS ${PLATFORM_PATH} + DOC "Path to directory containing the Arduino core sources." + NO_SYSTEM_ENVIRONMENT_PATH) + + find_file(${PLATFORM}_VARIANTS_PATH + NAMES variants + PATHS ${PLATFORM_PATH} + DOC "Path to directory containing the Arduino variant sources." + NO_SYSTEM_ENVIRONMENT_PATH) + + find_file(${PLATFORM}_BOOTLOADERS_PATH + NAMES bootloaders + PATHS ${PLATFORM_PATH} + DOC "Path to directory containing the Arduino bootloader images and sources." + NO_SYSTEM_ENVIRONMENT_PATH) + + find_file(${PLATFORM}_LIBRARIES_PATH + NAMES libraries + PATHS ${PLATFORM_PATH} + DOC "Path to directory containing the Arduino hardware libraries sources." + NO_SYSTEM_ENVIRONMENT_PATH) + + find_file(${PLATFORM}_PROGRAMMERS_PATH + NAMES programmers.txt + PATHS ${PLATFORM_PATH} + DOC "Path to Arduino programmers definition file." + NO_SYSTEM_ENVIRONMENT_PATH) + + find_file(${PLATFORM}_BOARDS_PATH + NAMES boards.txt + PATHS ${PLATFORM_PATH} + DOC "Path to Arduino boards definition file." + NO_SYSTEM_ENVIRONMENT_PATH) + + if(${PLATFORM}_BOARDS_PATH) + load_arduino_style_settings(${PLATFORM}_BOARDS "${PLATFORM_PATH}/boards.txt") + endif() + + if(${PLATFORM}_PROGRAMMERS_PATH) + load_arduino_style_settings(${PLATFORM}_PROGRAMMERS "${ARDUINO_PROGRAMMERS_PATH}") + endif() + + if(${PLATFORM}_VARIANTS_PATH) + file(GLOB sub-dir ${${PLATFORM}_VARIANTS_PATH}/*) + foreach(dir ${sub-dir}) + if(IS_DIRECTORY ${dir}) + get_filename_component(variant ${dir} NAME) + set(VARIANTS ${VARIANTS} ${variant} CACHE INTERNAL "A list of registered variant boards") + set(${variant}.path ${dir} CACHE INTERNAL "The path to the variant ${variant}") + endif() + endforeach() + endif() + + if(${PLATFORM}_CORES_PATH) + file(GLOB sub-dir ${${PLATFORM}_CORES_PATH}/*) + foreach(dir ${sub-dir}) + if(IS_DIRECTORY ${dir}) + get_filename_component(core ${dir} NAME) + set(CORES ${CORES} ${core} CACHE INTERNAL "A list of registered cores") + set(${core}.path ${dir} CACHE INTERNAL "The path to the core ${core}") + endif() + endforeach() + endif() + + endif() + endif() + +endfunction() + +#=============================================================================# +# Internal Functions +#=============================================================================# + +#=============================================================================# +# [PRIVATE/INTERNAL] +# +# parse_generator_arguments(TARGET_NAME PREFIX OPTIONS ARGS MULTI_ARGS [ARG1 ARG2 .. ARGN]) +# +# PREFIX - Parsed options prefix +# OPTIONS - List of options +# ARGS - List of one value keyword arguments +# MULTI_ARGS - List of multi value keyword arguments +# [ARG1 ARG2 .. ARGN] - command arguments [optional] +# +# Parses generator options from either variables or command arguments +# +#=============================================================================# +macro(PARSE_GENERATOR_ARGUMENTS TARGET_NAME PREFIX OPTIONS ARGS MULTI_ARGS) + cmake_parse_arguments(${PREFIX} "${OPTIONS}" "${ARGS}" "${MULTI_ARGS}" ${ARGN}) + error_for_unparsed(${PREFIX}) + load_generator_settings(${TARGET_NAME} ${PREFIX} ${OPTIONS} ${ARGS} ${MULTI_ARGS}) +endmacro() + +#=============================================================================# +# [PRIVATE/INTERNAL] +# +# load_generator_settings(TARGET_NAME PREFIX [SUFFIX_1 SUFFIX_2 .. SUFFIX_N]) +# +# TARGET_NAME - The base name of the user settings +# PREFIX - The prefix name used for generator settings +# SUFFIX_XX - List of suffixes to load +# +# Loads a list of user settings into the generators scope. User settings have +# the following syntax: +# +# ${BASE_NAME}${SUFFIX} +# +# The BASE_NAME is the target name and the suffix is a specific generator settings. +# +# For every user setting found a generator setting is created of the follwoing fromat: +# +# ${PREFIX}${SUFFIX} +# +# The purpose of loading the settings into the generator is to not modify user settings +# and to have a generic naming of the settings within the generator. +# +#=============================================================================# +function(LOAD_GENERATOR_SETTINGS TARGET_NAME PREFIX) + foreach(GEN_SUFFIX ${ARGN}) + if(${TARGET_NAME}_${GEN_SUFFIX} AND NOT ${PREFIX}_${GEN_SUFFIX}) + set(${PREFIX}_${GEN_SUFFIX} ${${TARGET_NAME}_${GEN_SUFFIX}} PARENT_SCOPE) + endif() + endforeach() +endfunction() + +#=============================================================================# +# [PRIVATE/INTERNAL] +# +# get_arduino_flags(COMPILE_FLAGS LINK_FLAGS BOARD_ID MANUAL) +# +# COMPILE_FLAGS_VAR -Variable holding compiler flags +# LINK_FLAGS_VAR - Variable holding linker flags +# BOARD_ID - The board id name +# MANUAL - (Advanced) Only use AVR Libc/Includes +# +# Configures the the build settings for the specified Arduino Board. +# +#=============================================================================# +function(get_arduino_flags COMPILE_FLAGS_VAR LINK_FLAGS_VAR BOARD_ID MANUAL) + + set(BOARD_CORE ${${BOARD_ID}.build.core}) + if(BOARD_CORE) + if(ARDUINO_SDK_VERSION MATCHES "([0-9]+)[.]([0-9]+)[.]([0-9]+)") + string(REPLACE "." "" ARDUINO_VERSION_DEFINE "${ARDUINO_SDK_VERSION}") # Normalize version (remove all periods) + set(ARDUINO_VERSION_DEFINE "") + if(CMAKE_MATCH_1 GREATER 0) + set(ARDUINO_VERSION_DEFINE "${CMAKE_MATCH_1}") + endif() + if(CMAKE_MATCH_2 GREATER 10) + set(ARDUINO_VERSION_DEFINE "${ARDUINO_VERSION_DEFINE}${CMAKE_MATCH_2}") + else() + set(ARDUINO_VERSION_DEFINE "${ARDUINO_VERSION_DEFINE}0${CMAKE_MATCH_2}") + endif() + if(CMAKE_MATCH_3 GREATER 10) + set(ARDUINO_VERSION_DEFINE "${ARDUINO_VERSION_DEFINE}${CMAKE_MATCH_3}") + else() + set(ARDUINO_VERSION_DEFINE "${ARDUINO_VERSION_DEFINE}0${CMAKE_MATCH_3}") + endif() + else() + message("Invalid Arduino SDK Version (${ARDUINO_SDK_VERSION})") + endif() + + # output + set(COMPILE_FLAGS "") + + if(${BOARD_ID}${ARDUINO_CPUMENU}.build.f_cpu) + set(COMPILE_FLAGS "${COMPILE_FLAGS} -DF_CPU=${${BOARD_ID}${ARDUINO_CPUMENU}.build.f_cpu}") + else() + if(${BOARD_ID}.build.f_cpu) + set(COMPILE_FLAGS "${COMPILE_FLAGS} -DF_CPU=${${BOARD_ID}.build.f_cpu}") + else() + message(FATAL_ERROR "Can not find f_cpu in boards.txt for Arduino board ID (${BOARD_ID}), aborting.") + endif() + endif() + + set(COMPILE_FLAGS "${COMPILE_FLAGS} -DARDUINO=${ARDUINO_VERSION_DEFINE} -DARDUINO_${${BOARD_ID}.build.board} -DARDUINO_ARCH_AVR -mmcu=${${BOARD_ID}${ARDUINO_CPUMENU}.build.mcu}") + + if(DEFINED ${BOARD_ID}.build.vid) + set(COMPILE_FLAGS "${COMPILE_FLAGS} -DUSB_VID=${${BOARD_ID}.build.vid}") + endif() + if(DEFINED ${BOARD_ID}.build.pid) + set(COMPILE_FLAGS "${COMPILE_FLAGS} -DUSB_PID=${${BOARD_ID}.build.pid}") + endif() + if(NOT MANUAL) + set(COMPILE_FLAGS "${COMPILE_FLAGS} -I\"${${BOARD_CORE}.path}\" -I\"${ARDUINO_LIBRARIES_PATH}\"") + endif() + set(LINK_FLAGS "-mmcu=${${BOARD_ID}${ARDUINO_CPUMENU}.build.mcu}") + if(ARDUINO_SDK_VERSION VERSION_GREATER 1.0 OR ARDUINO_SDK_VERSION VERSION_EQUAL 1.0) + if(NOT MANUAL) + set(PIN_HEADER ${${${BOARD_ID}.build.variant}.path}) + if(PIN_HEADER) + set(COMPILE_FLAGS "${COMPILE_FLAGS} -I\"${PIN_HEADER}\"") + endif() + endif() + endif() + + # output + set(${COMPILE_FLAGS_VAR} "${COMPILE_FLAGS}" PARENT_SCOPE) + set(${LINK_FLAGS_VAR} "${LINK_FLAGS}" PARENT_SCOPE) + + else() + message(FATAL_ERROR "Invalid Arduino board ID (${BOARD_ID}), aborting.") + endif() +endfunction() + +#=============================================================================# +# [PRIVATE/INTERNAL] +# +# setup_arduino_core(VAR_NAME BOARD_ID) +# +# VAR_NAME - Variable name that will hold the generated library name +# BOARD_ID - Arduino board id +# +# Creates the Arduino Core library for the specified board, +# each board gets it's own version of the library. +# +#=============================================================================# +function(setup_arduino_core VAR_NAME BOARD_ID) + set(CORE_LIB_NAME ${BOARD_ID}_CORE) + set(BOARD_CORE ${${BOARD_ID}.build.core}) + if(BOARD_CORE) + if(NOT TARGET ${CORE_LIB_NAME}) + set(BOARD_CORE_PATH ${${BOARD_CORE}.path}) + find_sources(CORE_SRCS ${BOARD_CORE_PATH} True) + # Debian/Ubuntu fix + list(REMOVE_ITEM CORE_SRCS "${BOARD_CORE_PATH}/main.cxx") + add_library(${CORE_LIB_NAME} ${CORE_SRCS}) + get_arduino_flags(ARDUINO_COMPILE_FLAGS ARDUINO_LINK_FLAGS ${BOARD_ID} FALSE) + set_target_properties(${CORE_LIB_NAME} PROPERTIES + COMPILE_FLAGS "${ARDUINO_COMPILE_FLAGS}" + LINK_FLAGS "${ARDUINO_LINK_FLAGS}") + endif() + set(${VAR_NAME} ${CORE_LIB_NAME} PARENT_SCOPE) + endif() +endfunction() + +#=============================================================================# +# [PRIVATE/INTERNAL] +# +# find_arduino_libraries(VAR_NAME SRCS ARDLIBS) +# +# VAR_NAME - Variable name which will hold the results +# SRCS - Sources that will be analized +# ARDLIBS - Arduino libraries identified by name (e.g., Wire, SPI, Servo) +# +# returns a list of paths to libraries found. +# +# Finds all Arduino type libraries included in sources. Available libraries +# are ${ARDUINO_SDK_PATH}/libraries and ${CMAKE_CURRENT_SOURCE_DIR}. +# +# Also adds Arduino libraries specifically names in ALIBS. We add ".h" to the +# names and then process them just like the Arduino libraries found in the sources. +# +# A Arduino library is a folder that has the same name as the include header. +# For example, if we have a include "#include " then the following +# directory structure is considered a Arduino library: +# +# LibraryName/ +# |- LibraryName.h +# `- LibraryName.c +# +# If such a directory is found then all sources within that directory are considred +# to be part of that Arduino library. +# +#=============================================================================# +function(find_arduino_libraries VAR_NAME SRCS ARDLIBS) + get_property(include_dirs DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY INCLUDE_DIRECTORIES) + + set(ARDUINO_LIBS ) + foreach(SRC ${SRCS}) + + # Skipping generated files. They are, probably, not exist yet. + # TODO: Maybe it's possible to skip only really nonexisting files, + # but then it wiil be less deterministic. + get_source_file_property(_srcfile_generated ${SRC} GENERATED) + # Workaround for sketches, which are marked as generated + get_source_file_property(_sketch_generated ${SRC} GENERATED_SKETCH) + + if(NOT ${_srcfile_generated} OR ${_sketch_generated}) + if(NOT (EXISTS ${SRC} OR + EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${SRC} OR + EXISTS ${CMAKE_CURRENT_BINARY_DIR}/${SRC})) + message(FATAL_ERROR "Invalid source file: ${SRC}") + endif() + file(STRINGS ${SRC} SRC_CONTENTS) + + foreach(LIBNAME ${ARDLIBS}) + list(APPEND SRC_CONTENTS "#include <${LIBNAME}.h>") + endforeach() + + foreach(SRC_LINE ${SRC_CONTENTS}) + if("#${SRC_LINE}#" MATCHES "^#[ \t]*#[ \t]*include[ \t]*[<\"]([^>\"]*)[>\"]#") + get_filename_component(INCLUDE_NAME ${CMAKE_MATCH_1} NAME_WE) + get_property(LIBRARY_SEARCH_PATH + DIRECTORY # Property Scope + PROPERTY LINK_DIRECTORIES) + foreach(LIB_SEARCH_PATH ${include_dirs} ${LIBRARY_SEARCH_PATH} ${ARDUINO_LIBRARIES_PATH} ${${ARDUINO_PLATFORM}_LIBRARIES_PATH} ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/libraries ${ARDUINO_EXTRA_LIBRARIES_PATH}) + if(EXISTS ${LIB_SEARCH_PATH}/${INCLUDE_NAME}/${CMAKE_MATCH_1}) + list(APPEND ARDUINO_LIBS ${LIB_SEARCH_PATH}/${INCLUDE_NAME}) + break() + endif() + if(EXISTS ${LIB_SEARCH_PATH}/${INCLUDE_NAME}/src/${CMAKE_MATCH_1}) + list(APPEND ARDUINO_LIBS ${LIB_SEARCH_PATH}/${INCLUDE_NAME}) + break() + endif() + get_source_file_property(_header_generated ${LIB_SEARCH_PATH}/${CMAKE_MATCH_1} GENERATED) + if((EXISTS ${LIB_SEARCH_PATH}/${CMAKE_MATCH_1}) OR ${_header_generated}) + list(APPEND ARDUINO_LIBS ${LIB_SEARCH_PATH}/${INCLUDE_NAME}) + break() + endif() + endforeach() + endif() + endforeach() + endif() + endforeach() + if(ARDUINO_LIBS) + list(REMOVE_DUPLICATES ARDUINO_LIBS) + endif() + set(${VAR_NAME} ${ARDUINO_LIBS} PARENT_SCOPE) +endfunction() + +#=============================================================================# +# [PRIVATE/INTERNAL] +# +# setup_arduino_library(VAR_NAME BOARD_ID LIB_PATH COMPILE_FLAGS LINK_FLAGS) +# +# VAR_NAME - Vairable wich will hold the generated library names +# BOARD_ID - Board ID +# LIB_PATH - Path of the library +# COMPILE_FLAGS - Compile flags +# LINK_FLAGS - Link flags +# +# Creates an Arduino library, with all it's library dependencies. +# +# ${LIB_NAME}_RECURSE controls if the library will recurse +# when looking for source files. +# +#=============================================================================# + +# For known libraries can list recurse here +set(Wire_RECURSE True) +set(Ethernet_RECURSE True) +set(SD_RECURSE True) +set(Servo_RECURSE True) +set(SPI_RECURSE True) +set(SoftwareSerial_RECURSE True) +set(EEPROM_RECURSE True) +set(LiquidCrystal_RECURSE True) +set(TFT_RECURSE True) +set(WiFi_RECURSE True) +set(Robot_Control_RECURSE True) +function(setup_arduino_library VAR_NAME BOARD_ID LIB_PATH COMPILE_FLAGS LINK_FLAGS) + set(LIB_TARGETS) + set(LIB_INCLUDES) + + get_filename_component(LIB_NAME ${LIB_PATH} NAME) + set(TARGET_LIB_NAME ${BOARD_ID}_${LIB_NAME}) + if(NOT TARGET ${TARGET_LIB_NAME}) + string(REGEX REPLACE ".*/" "" LIB_SHORT_NAME ${LIB_NAME}) + + # Detect if recursion is needed + if (NOT DEFINED ${LIB_SHORT_NAME}_RECURSE) + set(${LIB_SHORT_NAME}_RECURSE False) + endif() + + find_sources(LIB_SRCS ${LIB_PATH} ${${LIB_SHORT_NAME}_RECURSE}) + if(LIB_SRCS) + message(STATUS "Generating ${TARGET_LIB_NAME} for library ${LIB_NAME}") + arduino_debug_msg("Generating Arduino ${LIB_NAME} library") + add_library(${TARGET_LIB_NAME} STATIC ${LIB_SRCS}) + include_directories(${LIB_PATH}) + include_directories(${LIB_PATH}/src) + include_directories(${LIB_PATH}/utility) + + get_arduino_flags(ARDUINO_COMPILE_FLAGS ARDUINO_LINK_FLAGS ${BOARD_ID} FALSE) + + find_arduino_libraries(LIB_DEPS "${LIB_SRCS}" "") + + foreach(LIB_DEP ${LIB_DEPS}) + if(NOT DEP_LIB_SRCS STREQUAL TARGET_LIB_NAME AND DEP_LIB_SRCS) + message(STATUS "Found library ${LIB_NAME} needs ${DEP_LIB_SRCS}") + endif() + + setup_arduino_library(DEP_LIB_SRCS ${BOARD_ID} ${LIB_DEP} "${COMPILE_FLAGS}" "${LINK_FLAGS}") + # Do not link to this library. DEP_LIB_SRCS will always be only one entry + # if we are looking at the same library. + if(NOT DEP_LIB_SRCS STREQUAL TARGET_LIB_NAME) + list(APPEND LIB_TARGETS ${DEP_LIB_SRCS}) + list(APPEND LIB_INCLUDES ${DEP_LIB_SRCS_INCLUDES}) + endif() + endforeach() + + if (LIB_INCLUDES) + string(REPLACE ";" " " LIB_INCLUDES "${LIB_INCLUDES}") + endif() + + set_target_properties(${TARGET_LIB_NAME} PROPERTIES + COMPILE_FLAGS "${ARDUINO_COMPILE_FLAGS} ${LIB_INCLUDES} -I\"${LIB_PATH}\" -I\"${LIB_PATH}/src\" -I\"${LIB_PATH}/utility\" ${COMPILE_FLAGS}" + LINK_FLAGS "${ARDUINO_LINK_FLAGS} ${LINK_FLAGS}") + list(APPEND LIB_INCLUDES "-I\"${LIB_PATH}\" -I\"${LIB_PATH}/src\" -I\"${LIB_PATH}/utility\"") + + target_link_libraries(${TARGET_LIB_NAME} ${BOARD_ID}_CORE) + list(APPEND LIB_TARGETS ${TARGET_LIB_NAME}) + + endif() + else() + # Target already exists, skiping creating + list(APPEND LIB_TARGETS ${TARGET_LIB_NAME}) + endif() + if(LIB_TARGETS) + list(REMOVE_DUPLICATES LIB_TARGETS) + endif() + set(${VAR_NAME} ${LIB_TARGETS} PARENT_SCOPE) + set(${VAR_NAME}_INCLUDES ${LIB_INCLUDES} PARENT_SCOPE) +endfunction() + +#=============================================================================# +# [PRIVATE/INTERNAL] +# +# setup_arduino_libraries(VAR_NAME BOARD_ID SRCS COMPILE_FLAGS LINK_FLAGS) +# +# VAR_NAME - Vairable wich will hold the generated library names +# BOARD_ID - Board ID +# SRCS - source files +# COMPILE_FLAGS - Compile flags +# LINK_FLAGS - Linker flags +# +# Finds and creates all dependency libraries based on sources. +# +#=============================================================================# +function(setup_arduino_libraries VAR_NAME BOARD_ID SRCS ARDLIBS COMPILE_FLAGS LINK_FLAGS) + set(LIB_TARGETS) + set(LIB_INCLUDES) + + find_arduino_libraries(TARGET_LIBS "${SRCS}" ARDLIBS) + foreach(TARGET_LIB ${TARGET_LIBS}) + # Create static library instead of returning sources + setup_arduino_library(LIB_DEPS ${BOARD_ID} ${TARGET_LIB} "${COMPILE_FLAGS}" "${LINK_FLAGS}") + list(APPEND LIB_TARGETS ${LIB_DEPS}) + list(APPEND LIB_INCLUDES ${LIB_DEPS_INCLUDES}) + endforeach() + + set(${VAR_NAME} ${LIB_TARGETS} PARENT_SCOPE) + set(${VAR_NAME}_INCLUDES ${LIB_INCLUDES} PARENT_SCOPE) +endfunction() + + +#=============================================================================# +# [PRIVATE/INTERNAL] +# +# setup_arduino_target(TARGET_NAME ALL_SRCS ALL_LIBS COMPILE_FLAGS LINK_FLAGS MANUAL) +# +# TARGET_NAME - Target name +# BOARD_ID - Arduino board ID +# ALL_SRCS - All sources +# ALL_LIBS - All libraries +# COMPILE_FLAGS - Compile flags +# LINK_FLAGS - Linker flags +# MANUAL - (Advanced) Only use AVR Libc/Includes +# +# Creates an Arduino firmware target. +# +#=============================================================================# +function(setup_arduino_target TARGET_NAME BOARD_ID ALL_SRCS ALL_LIBS COMPILE_FLAGS LINK_FLAGS MANUAL) + + add_executable(${TARGET_NAME} ${ALL_SRCS}) + set_target_properties(${TARGET_NAME} PROPERTIES SUFFIX ".elf") + + get_arduino_flags(ARDUINO_COMPILE_FLAGS ARDUINO_LINK_FLAGS ${BOARD_ID} ${MANUAL}) + + set_target_properties(${TARGET_NAME} PROPERTIES + COMPILE_FLAGS "${ARDUINO_COMPILE_FLAGS} ${COMPILE_FLAGS}" + LINK_FLAGS "${ARDUINO_LINK_FLAGS} ${LINK_FLAGS}") + target_link_libraries(${TARGET_NAME} ${ALL_LIBS} "-lc -lm") + + if(NOT EXECUTABLE_OUTPUT_PATH) + set(EXECUTABLE_OUTPUT_PATH ${CMAKE_CURRENT_BINARY_DIR}) + endif() + set(TARGET_PATH ${EXECUTABLE_OUTPUT_PATH}/${TARGET_NAME}) + + message(STATUS "Using ${CMAKE_OBJCOPY} for converting firmware image to hex") + add_custom_command(TARGET ${TARGET_NAME} POST_BUILD + COMMAND ${CMAKE_OBJCOPY} + ARGS ${ARDUINO_OBJCOPY_EEP_FLAGS} + ${TARGET_PATH}.elf + ${TARGET_PATH}.eep + COMMENT "Generating EEP image" + VERBATIM) + + # Convert firmware image to ASCII HEX format + add_custom_command(TARGET ${TARGET_NAME} POST_BUILD + COMMAND ${CMAKE_OBJCOPY} + ARGS ${ARDUINO_OBJCOPY_HEX_FLAGS} + ${TARGET_PATH}.elf + ${TARGET_PATH}.hex + COMMENT "Generating HEX image" + VERBATIM) + + # Display target size + add_custom_command(TARGET ${TARGET_NAME} POST_BUILD + COMMAND ${CMAKE_COMMAND} + ARGS -DFIRMWARE_IMAGE=${TARGET_PATH}.elf + -DMCU=${${BOARD_ID}${ARDUINO_CPUMENU}.build.mcu} + -DEEPROM_IMAGE=${TARGET_PATH}.eep + -P ${ARDUINO_SIZE_SCRIPT} + COMMENT "Calculating image size" + VERBATIM) + + # Create ${TARGET_NAME}-size target + add_custom_target(${TARGET_NAME}-size + COMMAND ${CMAKE_COMMAND} + -DFIRMWARE_IMAGE=${TARGET_PATH}.elf + -DMCU=${${BOARD_ID}${ARDUINO_CPUMENU}.build.mcu} + -DEEPROM_IMAGE=${TARGET_PATH}.eep + -P ${ARDUINO_SIZE_SCRIPT} + DEPENDS ${TARGET_NAME} + COMMENT "Calculating ${TARGET_NAME} image size") + +endfunction() + +#=============================================================================# +# [PRIVATE/INTERNAL] +# +# setup_arduino_upload(BOARD_ID TARGET_NAME PORT) +# +# BOARD_ID - Arduino board id +# TARGET_NAME - Target name +# PORT - Serial port for upload +# PROGRAMMER_ID - Programmer ID +# AVRDUDE_FLAGS - avrdude flags +# +# Create an upload target (${TARGET_NAME}-upload) for the specified Arduino target. +# +#=============================================================================# +function(setup_arduino_upload BOARD_ID TARGET_NAME PORT PROGRAMMER_ID AVRDUDE_FLAGS) + setup_arduino_bootloader_upload(${TARGET_NAME} ${BOARD_ID} ${PORT} "${AVRDUDE_FLAGS}") + + # Add programmer support if defined + if(PROGRAMMER_ID AND ${PROGRAMMER_ID}.protocol) + setup_arduino_programmer_burn(${TARGET_NAME} ${BOARD_ID} ${PROGRAMMER_ID} ${PORT} "${AVRDUDE_FLAGS}") + setup_arduino_bootloader_burn(${TARGET_NAME} ${BOARD_ID} ${PROGRAMMER_ID} ${PORT} "${AVRDUDE_FLAGS}") + endif() +endfunction() + + +#=============================================================================# +# [PRIVATE/INTERNAL] +# +# setup_arduino_bootloader_upload(TARGET_NAME BOARD_ID PORT) +# +# TARGET_NAME - target name +# BOARD_ID - board id +# PORT - serial port +# AVRDUDE_FLAGS - avrdude flags (override) +# +# Set up target for upload firmware via the bootloader. +# +# The target for uploading the firmware is ${TARGET_NAME}-upload . +# +#=============================================================================# +function(setup_arduino_bootloader_upload TARGET_NAME BOARD_ID PORT AVRDUDE_FLAGS) + set(UPLOAD_TARGET ${TARGET_NAME}-upload) + set(AVRDUDE_ARGS) + + setup_arduino_bootloader_args(${BOARD_ID} ${TARGET_NAME} ${PORT} "${AVRDUDE_FLAGS}" AVRDUDE_ARGS) + + if(NOT AVRDUDE_ARGS) + message("Could not generate default avrdude bootloader args, aborting!") + return() + endif() + + if(NOT EXECUTABLE_OUTPUT_PATH) + set(EXECUTABLE_OUTPUT_PATH ${CMAKE_CURRENT_BINARY_DIR}) + endif() + set(TARGET_PATH ${EXECUTABLE_OUTPUT_PATH}/${TARGET_NAME}) + + list(APPEND AVRDUDE_ARGS "-Uflash:w:${TARGET_PATH}.hex:i") + list(APPEND AVRDUDE_ARGS "-Ueeprom:w:${TARGET_PATH}.eep:i") + add_custom_target(${UPLOAD_TARGET} + ${ARDUINO_AVRDUDE_PROGRAM} + ${AVRDUDE_ARGS} + DEPENDS ${TARGET_NAME}) + + # Global upload target + if(NOT TARGET upload) + add_custom_target(upload) + endif() + + add_dependencies(upload ${UPLOAD_TARGET}) +endfunction() + +#=============================================================================# +# [PRIVATE/INTERNAL] +# +# setup_arduino_programmer_burn(TARGET_NAME BOARD_ID PROGRAMMER PORT AVRDUDE_FLAGS) +# +# TARGET_NAME - name of target to burn +# BOARD_ID - board id +# PROGRAMMER - programmer id +# PORT - serial port +# AVRDUDE_FLAGS - avrdude flags (override) +# +# Sets up target for burning firmware via a programmer. +# +# The target for burning the firmware is ${TARGET_NAME}-burn . +# +#=============================================================================# +function(setup_arduino_programmer_burn TARGET_NAME BOARD_ID PROGRAMMER PORT AVRDUDE_FLAGS) + set(PROGRAMMER_TARGET ${TARGET_NAME}-burn) + + set(AVRDUDE_ARGS) + + setup_arduino_programmer_args(${BOARD_ID} ${PROGRAMMER} ${TARGET_NAME} ${PORT} "${AVRDUDE_FLAGS}" AVRDUDE_ARGS) + + if(NOT AVRDUDE_ARGS) + message("Could not generate default avrdude programmer args, aborting!") + return() + endif() + + if(NOT EXECUTABLE_OUTPUT_PATH) + set(EXECUTABLE_OUTPUT_PATH ${CMAKE_CURRENT_BINARY_DIR}) + endif() + set(TARGET_PATH ${EXECUTABLE_OUTPUT_PATH}/${TARGET_NAME}) + + list(APPEND AVRDUDE_ARGS "-Uflash:w:${TARGET_PATH}.hex") + + add_custom_target(${PROGRAMMER_TARGET} + ${ARDUINO_AVRDUDE_PROGRAM} + ${AVRDUDE_ARGS} + DEPENDS ${TARGET_NAME}) +endfunction() + +#=============================================================================# +# [PRIVATE/INTERNAL] +# +# setup_arduino_bootloader_burn(TARGET_NAME BOARD_ID PROGRAMMER PORT AVRDUDE_FLAGS) +# +# TARGET_NAME - name of target to burn +# BOARD_ID - board id +# PROGRAMMER - programmer id +# PORT - serial port +# AVRDUDE_FLAGS - avrdude flags (override) +# +# Create a target for burning a bootloader via a programmer. +# +# The target for burning the bootloader is ${TARGET_NAME}-burn-bootloader +# +#=============================================================================# +function(setup_arduino_bootloader_burn TARGET_NAME BOARD_ID PROGRAMMER PORT AVRDUDE_FLAGS) + set(BOOTLOADER_TARGET ${TARGET_NAME}-burn-bootloader) + + set(AVRDUDE_ARGS) + + setup_arduino_programmer_args(${BOARD_ID} ${PROGRAMMER} ${TARGET_NAME} ${PORT} "${AVRDUDE_FLAGS}" AVRDUDE_ARGS) + + if(NOT AVRDUDE_ARGS) + message("Could not generate default avrdude programmer args, aborting!") + return() + endif() + + foreach( ITEM unlock_bits high_fuses low_fuses path file) + if(NOT ${BOARD_ID}.bootloader.${ITEM}) + message("Missing ${BOARD_ID}.bootloader.${ITEM}, not creating bootloader burn target ${BOOTLOADER_TARGET}.") + return() + endif() + endforeach() + + if(NOT EXISTS "${ARDUINO_BOOTLOADERS_PATH}/${${BOARD_ID}.bootloader.path}/${${BOARD_ID}${ARDUINO_CPUMENU}.bootloader.file}") + message("${ARDUINO_BOOTLOADERS_PATH}/${${BOARD_ID}.bootloader.path}/${${BOARD_ID}${ARDUINO_CPUMENU}.bootloader.file}") + message("Missing bootloader image, not creating bootloader burn target ${BOOTLOADER_TARGET}.") + return() + endif() + + # Erase the chip + list(APPEND AVRDUDE_ARGS "-e") + + # Set unlock bits and fuses (because chip is going to be erased) + list(APPEND AVRDUDE_ARGS "-Ulock:w:${${BOARD_ID}.bootloader.unlock_bits}:m") + if(${BOARD_ID}.bootloader.extended_fuses) + list(APPEND AVRDUDE_ARGS "-Uefuse:w:${${BOARD_ID}${ARDUINO_CPUMENU}.bootloader.extended_fuses}:m") + endif() + list(APPEND AVRDUDE_ARGS + "-Uhfuse:w:${${BOARD_ID}${ARDUINO_CPUMENU}.bootloader.high_fuses}:m" + "-Ulfuse:w:${${BOARD_ID}.bootloader.low_fuses}:m") + + # Set bootloader image + list(APPEND AVRDUDE_ARGS "-Uflash:w:${${BOARD_ID}${ARDUINO_CPUMENU}.bootloader.file}:i") + + # Set lockbits + list(APPEND AVRDUDE_ARGS "-Ulock:w:${${BOARD_ID}.bootloader.lock_bits}:m") + + # Create burn bootloader target + add_custom_target(${BOOTLOADER_TARGET} + ${ARDUINO_AVRDUDE_PROGRAM} + ${AVRDUDE_ARGS} + WORKING_DIRECTORY ${ARDUINO_BOOTLOADERS_PATH}/${${BOARD_ID}.bootloader.path} + DEPENDS ${TARGET_NAME}) +endfunction() + +#=============================================================================# +# [PRIVATE/INTERNAL] +# +# setup_arduino_programmer_args(BOARD_ID PROGRAMMER TARGET_NAME PORT AVRDUDE_FLAGS OUTPUT_VAR) +# +# BOARD_ID - board id +# PROGRAMMER - programmer id +# TARGET_NAME - target name +# PORT - serial port +# AVRDUDE_FLAGS - avrdude flags (override) +# OUTPUT_VAR - name of output variable for result +# +# Sets up default avrdude settings for burning firmware via a programmer. +#=============================================================================# +function(setup_arduino_programmer_args BOARD_ID PROGRAMMER TARGET_NAME PORT AVRDUDE_FLAGS OUTPUT_VAR) + set(AVRDUDE_ARGS ${${OUTPUT_VAR}}) + + if(NOT AVRDUDE_FLAGS) + set(AVRDUDE_FLAGS ${ARDUINO_AVRDUDE_FLAGS}) + endif() + + list(APPEND AVRDUDE_ARGS "-C${ARDUINO_AVRDUDE_CONFIG_PATH}") + + #TODO: Check mandatory settings before continuing + if(NOT ${PROGRAMMER}.protocol) + message(FATAL_ERROR "Missing ${PROGRAMMER}.protocol, aborting!") + endif() + + list(APPEND AVRDUDE_ARGS "-c${${PROGRAMMER}.protocol}") # Set programmer + + if(${PROGRAMMER}.communication STREQUAL "usb") + list(APPEND AVRDUDE_ARGS "-Pusb") # Set USB as port + elseif(${PROGRAMMER}.communication STREQUAL "serial") + list(APPEND AVRDUDE_ARGS "-P${PORT}") # Set port + if(${PROGRAMMER}.speed) + list(APPEND AVRDUDE_ARGS "-b${${PROGRAMMER}.speed}") # Set baud rate + endif() + endif() + + if(${PROGRAMMER}.force) + list(APPEND AVRDUDE_ARGS "-F") # Set force + endif() + + if(${PROGRAMMER}.delay) + list(APPEND AVRDUDE_ARGS "-i${${PROGRAMMER}.delay}") # Set delay + endif() + + list(APPEND AVRDUDE_ARGS "-p${${BOARD_ID}${ARDUINO_CPUMENU}.build.mcu}") # MCU Type + + list(APPEND AVRDUDE_ARGS ${AVRDUDE_FLAGS}) + + set(${OUTPUT_VAR} ${AVRDUDE_ARGS} PARENT_SCOPE) +endfunction() + +#=============================================================================# +# [PRIVATE/INTERNAL] +# +# setup_arduino_bootloader_args(BOARD_ID TARGET_NAME PORT AVRDUDE_FLAGS OUTPUT_VAR) +# +# BOARD_ID - board id +# TARGET_NAME - target name +# PORT - serial port +# AVRDUDE_FLAGS - avrdude flags (override) +# OUTPUT_VAR - name of output variable for result +# +# Sets up default avrdude settings for uploading firmware via the bootloader. +#=============================================================================# +function(setup_arduino_bootloader_args BOARD_ID TARGET_NAME PORT AVRDUDE_FLAGS OUTPUT_VAR) + set(AVRDUDE_ARGS ${${OUTPUT_VAR}}) + + if(NOT AVRDUDE_FLAGS) + set(AVRDUDE_FLAGS ${ARDUINO_AVRDUDE_FLAGS}) + endif() + + list(APPEND AVRDUDE_ARGS + "-C${ARDUINO_AVRDUDE_CONFIG_PATH}" # avrdude config + "-p${${BOARD_ID}${ARDUINO_CPUMENU}.build.mcu}" # MCU Type + ) + + # Programmer + if(NOT ${BOARD_ID}${ARDUINO_CPUMENU}.upload.protocol OR ${BOARD_ID}${ARDUINO_CPUMENU}.upload.protocol STREQUAL "stk500") + if(NOT ${BOARD_ID}.upload.protocol OR ${BOARD_ID}.upload.protocol STREQUAL "stk500") + list(APPEND AVRDUDE_ARGS "-cstk500v1") + else() + list(APPEND AVRDUDE_ARGS "-c${${BOARD_ID}.upload.protocol}") + endif() + else() + list(APPEND AVRDUDE_ARGS "-c${${BOARD_ID}${ARDUINO_CPUMENU}.upload.protocol}") + endif() + + set(UPLOAD_SPEED "19200") + if(${BOARD_ID}${ARDUINO_CPUMENU}.upload.speed) + set(UPLOAD_SPEED ${${BOARD_ID}${ARDUINO_CPUMENU}.upload.speed}) + endif() + + list(APPEND AVRDUDE_ARGS + "-b${UPLOAD_SPEED}" # Baud rate + "-P${PORT}" # Serial port + "-D" # Dont erase + ) + + list(APPEND AVRDUDE_ARGS ${AVRDUDE_FLAGS}) + + set(${OUTPUT_VAR} ${AVRDUDE_ARGS} PARENT_SCOPE) +endfunction() + +#=============================================================================# +# [PRIVATE/INTERNAL] +# +# find_sources(VAR_NAME LIB_PATH RECURSE) +# +# VAR_NAME - Variable name that will hold the detected sources +# LIB_PATH - The base path +# RECURSE - Whether or not to recurse +# +# Finds all C/C++ sources located at the specified path. +# +#=============================================================================# +function(find_sources VAR_NAME LIB_PATH RECURSE) + set(FILE_SEARCH_LIST + ${LIB_PATH}/*.cpp + ${LIB_PATH}/*.c + ${LIB_PATH}/*.cc + ${LIB_PATH}/*.cxx + ${LIB_PATH}/*.h + ${LIB_PATH}/*.hh + ${LIB_PATH}/*.hxx) + + if(RECURSE) + file(GLOB_RECURSE LIB_FILES ${FILE_SEARCH_LIST}) + else() + file(GLOB LIB_FILES ${FILE_SEARCH_LIST}) + endif() + + if(LIB_FILES) + set(${VAR_NAME} ${LIB_FILES} PARENT_SCOPE) + endif() +endfunction() + +#=============================================================================# +# [PRIVATE/INTERNAL] +# +# setup_serial_target(TARGET_NAME CMD) +# +# TARGET_NAME - Target name +# CMD - Serial terminal command +# +# Creates a target (${TARGET_NAME}-serial) for launching the serial termnial. +# +#=============================================================================# +function(setup_serial_target TARGET_NAME CMD SERIAL_PORT) + string(CONFIGURE "${CMD}" FULL_CMD @ONLY) + add_custom_target(${TARGET_NAME}-serial + COMMAND ${FULL_CMD}) +endfunction() + + +#=============================================================================# +# [PRIVATE/INTERNAL] +# +# detect_arduino_version(VAR_NAME) +# +# VAR_NAME - Variable name where the detected version will be saved +# +# Detects the Arduino SDK Version based on the lib/versions.txt file. The +# following variables will be generated: +# +# ${VAR_NAME} -> the full version (major.minor.patch) +# ${VAR_NAME}_MAJOR -> the major version +# ${VAR_NAME}_MINOR -> the minor version +# ${VAR_NAME}_PATCH -> the patch version +# +#=============================================================================# +function(detect_arduino_version VAR_NAME) + if(ARDUINO_VERSION_PATH) + file(READ ${ARDUINO_VERSION_PATH} RAW_VERSION) + if("${RAW_VERSION}" MATCHES " *[0]+([0-9]+)") + set(PARSED_VERSION 0.${CMAKE_MATCH_1}.0) + elseif("${RAW_VERSION}" MATCHES "[ ]*([0-9]+[.][0-9]+[.][0-9]+)") + set(PARSED_VERSION ${CMAKE_MATCH_1}) + elseif("${RAW_VERSION}" MATCHES "[ ]*([0-9]+[.][0-9]+)") + set(PARSED_VERSION ${CMAKE_MATCH_1}.0) + endif() + + if(NOT PARSED_VERSION STREQUAL "") + string(REPLACE "." ";" SPLIT_VERSION ${PARSED_VERSION}) + list(GET SPLIT_VERSION 0 SPLIT_VERSION_MAJOR) + list(GET SPLIT_VERSION 1 SPLIT_VERSION_MINOR) + list(GET SPLIT_VERSION 2 SPLIT_VERSION_PATCH) + + set(${VAR_NAME} "${PARSED_VERSION}" PARENT_SCOPE) + set(${VAR_NAME}_MAJOR "${SPLIT_VERSION_MAJOR}" PARENT_SCOPE) + set(${VAR_NAME}_MINOR "${SPLIT_VERSION_MINOR}" PARENT_SCOPE) + set(${VAR_NAME}_PATCH "${SPLIT_VERSION_PATCH}" PARENT_SCOPE) + endif() + endif() +endfunction() + + +#=============================================================================# +# [PRIVATE/INTERNAL] +# +# load_arduino_style_settings(SETTINGS_LIST SETTINGS_PATH) +# +# SETTINGS_LIST - Variable name of settings list +# SETTINGS_PATH - File path of settings file to load. +# +# Load a Arduino style settings file into the cache. +# +# Examples of this type of settings file is the boards.txt and +# programmers.txt files located in ${ARDUINO_SDK}/hardware/arduino. +# +# Settings have to following format: +# +# entry.setting[.subsetting] = value +# +# where [.subsetting] is optional +# +# For example, the following settings: +# +# uno.name=Arduino Uno +# uno.upload.protocol=stk500 +# uno.upload.maximum_size=32256 +# uno.build.mcu=atmega328p +# uno.build.core=arduino +# +# will generate the follwoing equivalent CMake variables: +# +# set(uno.name "Arduino Uno") +# set(uno.upload.protocol "stk500") +# set(uno.upload.maximum_size "32256") +# set(uno.build.mcu "atmega328p") +# set(uno.build.core "arduino") +# +# set(uno.SETTINGS name upload build) # List of settings for uno +# set(uno.upload.SUBSETTINGS protocol maximum_size) # List of sub-settings for uno.upload +# set(uno.build.SUBSETTINGS mcu core) # List of sub-settings for uno.build +# +# The ${ENTRY_NAME}.SETTINGS variable lists all settings for the entry, while +# ${ENTRY_NAME}.SUBSETTINGS variables lists all settings for a sub-setting of +# a entry setting pair. +# +# These variables are generated in order to be able to programatically traverse +# all settings (for a example see print_board_settings() function). +# +#=============================================================================# +function(LOAD_ARDUINO_STYLE_SETTINGS SETTINGS_LIST SETTINGS_PATH) + + if(NOT ${SETTINGS_LIST} AND EXISTS ${SETTINGS_PATH}) + file(STRINGS ${SETTINGS_PATH} FILE_ENTRIES) # Settings file split into lines + + foreach(FILE_ENTRY ${FILE_ENTRIES}) + if("${FILE_ENTRY}" MATCHES "^[^#]+=.*") + string(REGEX MATCH "^[^=]+" SETTING_NAME ${FILE_ENTRY}) + string(REGEX MATCH "[^=]+$" SETTING_VALUE ${FILE_ENTRY}) + string(REPLACE "." ";" ENTRY_NAME_TOKENS ${SETTING_NAME}) + string(STRIP "${SETTING_VALUE}" SETTING_VALUE) + + list(LENGTH ENTRY_NAME_TOKENS ENTRY_NAME_TOKENS_LEN) + + # Add entry to settings list if it does not exist + list(GET ENTRY_NAME_TOKENS 0 ENTRY_NAME) + list(FIND ${SETTINGS_LIST} ${ENTRY_NAME} ENTRY_NAME_INDEX) + if(ENTRY_NAME_INDEX LESS 0) + # Add entry to main list + list(APPEND ${SETTINGS_LIST} ${ENTRY_NAME}) + endif() + + # Add entry setting to entry settings list if it does not exist + set(ENTRY_SETTING_LIST ${ENTRY_NAME}.SETTINGS) + list(GET ENTRY_NAME_TOKENS 1 ENTRY_SETTING) + set(PARAMETERS 2) + if(ENTRY_SETTING STREQUAL "menu") + list(GET ENTRY_NAME_TOKENS 3 CPUNAME) + if(ENTRY_NAME_TOKENS_LEN GREATER 4) + list(GET ENTRY_NAME_TOKENS 4 PROPERTYNAME) + set(ENTRY_SETTING "menu.cpu.${CPUNAME}.${PROPERTYNAME}") + set(PARAMETERS 5) + else() + set(ENTRY_SETTING "menu.cpu.${CPUNAME}") + set(PARAMETERS 4) + endif() + list(APPEND ${ENTRY_SETTING_LIST} "${ENTRY_SETTING}") + else() + list(FIND ${ENTRY_SETTING_LIST} ${ENTRY_SETTING} ENTRY_SETTING_INDEX) + if(ENTRY_SETTING_INDEX LESS 0) + # Add setting to entry + list(APPEND ${ENTRY_SETTING_LIST} ${ENTRY_SETTING}) + set(${ENTRY_SETTING_LIST} ${${ENTRY_SETTING_LIST}} + CACHE INTERNAL "Arduino ${ENTRY_NAME} Board settings list") + endif() + endif() + + set(FULL_SETTING_NAME ${ENTRY_NAME}.${ENTRY_SETTING}) + + # Add entry sub-setting to entry sub-settings list if it does not exists + if(ENTRY_NAME_TOKENS_LEN GREATER ${PARAMETERS}) + set(ENTRY_SUBSETTING_LIST ${ENTRY_NAME}.${ENTRY_SETTING}.SUBSETTINGS) + list(GET ENTRY_NAME_TOKENS ${PARAMETERS} ENTRY_SUBSETTING) + list(FIND ${ENTRY_SUBSETTING_LIST} ${ENTRY_SUBSETTING} ENTRY_SUBSETTING_INDEX) + if(ENTRY_SUBSETTING_INDEX LESS 0) + list(APPEND ${ENTRY_SUBSETTING_LIST} ${ENTRY_SUBSETTING}) + set(${ENTRY_SUBSETTING_LIST} ${${ENTRY_SUBSETTING_LIST}} + CACHE INTERNAL "Arduino ${ENTRY_NAME} Board sub-settings list") + endif() + set(FULL_SETTING_NAME ${FULL_SETTING_NAME}.${ENTRY_SUBSETTING}) + endif() + + # Save setting value + set(${FULL_SETTING_NAME} ${SETTING_VALUE} + CACHE INTERNAL "Arduino ${ENTRY_NAME} Board setting") + + + endif() + endforeach() + set(${SETTINGS_LIST} ${${SETTINGS_LIST}} + CACHE STRING "List of detected Arduino Board configurations") + mark_as_advanced(${SETTINGS_LIST}) + endif() +endfunction() + +#=============================================================================# +# print_settings(ENTRY_NAME) +# +# ENTRY_NAME - name of entry +# +# Print the entry settings (see load_arduino_syle_settings()). +# +#=============================================================================# +function(PRINT_SETTINGS ENTRY_NAME) + if(${ENTRY_NAME}.SETTINGS) + + foreach(ENTRY_SETTING ${${ENTRY_NAME}.SETTINGS}) + if(${ENTRY_NAME}.${ENTRY_SETTING}) + message(STATUS " ${ENTRY_NAME}.${ENTRY_SETTING}=${${ENTRY_NAME}.${ENTRY_SETTING}}") + endif() + if(${ENTRY_NAME}.${ENTRY_SETTING}.SUBSETTINGS) + foreach(ENTRY_SUBSETTING ${${ENTRY_NAME}.${ENTRY_SETTING}.SUBSETTINGS}) + if(${ENTRY_NAME}.${ENTRY_SETTING}.${ENTRY_SUBSETTING}) + message(STATUS " ${ENTRY_NAME}.${ENTRY_SETTING}.${ENTRY_SUBSETTING}=${${ENTRY_NAME}.${ENTRY_SETTING}.${ENTRY_SUBSETTING}}") + endif() + endforeach() + endif() + message(STATUS "") + endforeach() + endif() +endfunction() + +#=============================================================================# +# [PRIVATE/INTERNAL] +# +# print_list(SETTINGS_LIST) +# +# SETTINGS_LIST - Variables name of settings list +# +# Print list settings and names (see load_arduino_syle_settings()). +#=============================================================================# +function(PRINT_LIST SETTINGS_LIST) + if(${SETTINGS_LIST}) + set(MAX_LENGTH 0) + foreach(ENTRY_NAME ${${SETTINGS_LIST}}) + string(LENGTH "${ENTRY_NAME}" CURRENT_LENGTH) + if(CURRENT_LENGTH GREATER MAX_LENGTH) + set(MAX_LENGTH ${CURRENT_LENGTH}) + endif() + endforeach() + foreach(ENTRY_NAME ${${SETTINGS_LIST}}) + string(LENGTH "${ENTRY_NAME}" CURRENT_LENGTH) + math(EXPR PADDING_LENGTH "${MAX_LENGTH}-${CURRENT_LENGTH}") + set(PADDING "") + foreach(X RANGE ${PADDING_LENGTH}) + set(PADDING "${PADDING} ") + endforeach() + message(STATUS " ${PADDING}${ENTRY_NAME}: ${${ENTRY_NAME}.name}") + endforeach() + endif() +endfunction() + +#=============================================================================# +# [PRIVATE/INTERNAL] +# +# setup_arduino_example(TARGET_NAME LIBRARY_NAME EXAMPLE_NAME OUTPUT_VAR) +# +# TARGET_NAME - Target name +# LIBRARY_NAME - Library name +# EXAMPLE_NAME - Example name +# OUTPUT_VAR - Variable name to save sketch path. +# +# Creates a Arduino example from a the specified library. +#=============================================================================# +function(SETUP_ARDUINO_EXAMPLE TARGET_NAME LIBRARY_NAME EXAMPLE_NAME OUTPUT_VAR) + set(EXAMPLE_SKETCH_PATH ) + + get_property(LIBRARY_SEARCH_PATH + DIRECTORY # Property Scope + PROPERTY LINK_DIRECTORIES) + foreach(LIB_SEARCH_PATH ${LIBRARY_SEARCH_PATH} ${ARDUINO_LIBRARIES_PATH} ${${ARDUINO_PLATFORM}_LIBRARIES_PATH} ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/libraries) + message(STATUS "Search ${LIBRARY_NAME} example directory in ${LIB_SEARCH_PATH}") + if(EXISTS "${LIB_SEARCH_PATH}/${LIBRARY_NAME}/examples/${EXAMPLE_NAME}") + set(EXAMPLE_SKETCH_PATH "${LIB_SEARCH_PATH}/${LIBRARY_NAME}/examples/${EXAMPLE_NAME}") + break() + endif() + endforeach() + + if(EXAMPLE_SKETCH_PATH) + setup_arduino_sketch(${TARGET_NAME} ${EXAMPLE_SKETCH_PATH} SKETCH_CPP) + set("${OUTPUT_VAR}" ${${OUTPUT_VAR}} ${SKETCH_CPP} PARENT_SCOPE) + else() + message(FATAL_ERROR "Could not find example ${EXAMPLE_NAME} from library ${LIBRARY_NAME}") + endif() +endfunction() + +#=============================================================================# +# [PRIVATE/INTERNAL] +# +# setup_arduino_sketch(TARGET_NAME SKETCH_PATH OUTPUT_VAR) +# +# TARGET_NAME - Target name +# SKETCH_PATH - Path to sketch directory +# OUTPUT_VAR - Variable name where to save generated sketch source +# +# Generates C++ sources from Arduino Sketch. +#=============================================================================# +function(SETUP_ARDUINO_SKETCH TARGET_NAME SKETCH_PATH OUTPUT_VAR) + get_filename_component(SKETCH_NAME "${SKETCH_PATH}" NAME) + get_filename_component(SKETCH_PATH "${SKETCH_PATH}" ABSOLUTE) + + if(EXISTS "${SKETCH_PATH}") + set(SKETCH_CPP ${CMAKE_CURRENT_BINARY_DIR}/${TARGET_NAME}_${SKETCH_NAME}.cpp) + + if (IS_DIRECTORY "${SKETCH_PATH}") + # Sketch directory specified, try to find main sketch... + set(MAIN_SKETCH ${SKETCH_PATH}/${SKETCH_NAME}) + + if(EXISTS "${MAIN_SKETCH}.pde") + set(MAIN_SKETCH "${MAIN_SKETCH}.pde") + elseif(EXISTS "${MAIN_SKETCH}.ino") + set(MAIN_SKETCH "${MAIN_SKETCH}.ino") + else() + message(FATAL_ERROR "Could not find main sketch (${SKETCH_NAME}.pde or ${SKETCH_NAME}.ino) at ${SKETCH_PATH}! Please specify the main sketch file path instead of directory.") + endif() + else() + # Sektch file specified, assuming parent directory as sketch directory + set(MAIN_SKETCH ${SKETCH_PATH}) + get_filename_component(SKETCH_PATH "${SKETCH_PATH}" PATH) + endif() + arduino_debug_msg("sketch: ${MAIN_SKETCH}") + + # Find all sketch files + file(GLOB SKETCH_SOURCES ${SKETCH_PATH}/*.pde ${SKETCH_PATH}/*.ino) + set(ALL_SRCS ${SKETCH_SOURCES}) + + list(REMOVE_ITEM SKETCH_SOURCES ${MAIN_SKETCH}) + list(SORT SKETCH_SOURCES) + + + + generate_cpp_from_sketch("${MAIN_SKETCH}" "${SKETCH_SOURCES}" "${SKETCH_CPP}") + + # Regenerate build system if sketch changes + add_custom_command(OUTPUT ${SKETCH_CPP} + COMMAND ${CMAKE_COMMAND} ${CMAKE_SOURCE_DIR} + WORKING_DIRECTORY ${CMAKE_BINARY_DIR} + DEPENDS ${MAIN_SKETCH} ${SKETCH_SOURCES} + COMMENT "Regnerating ${SKETCH_NAME} Sketch") + set_source_files_properties(${SKETCH_CPP} PROPERTIES GENERATED TRUE) + # Mark file that it exists for find_file + set_source_files_properties(${SKETCH_CPP} PROPERTIES GENERATED_SKETCH TRUE) + + set("${OUTPUT_VAR}" ${${OUTPUT_VAR}} ${SKETCH_CPP} PARENT_SCOPE) + else() + message(FATAL_ERROR "Sketch does not exist: ${SKETCH_PATH}") + endif() +endfunction() + + +#=============================================================================# +# [PRIVATE/INTERNAL] +# +# generate_cpp_from_sketch(MAIN_SKETCH_PATH SKETCH_SOURCES SKETCH_CPP) +# +# MAIN_SKETCH_PATH - Main sketch file path +# SKETCH_SOURCES - Setch source paths +# SKETCH_CPP - Name of file to generate +# +# Generate C++ source file from Arduino sketch files. +#=============================================================================# +function(GENERATE_CPP_FROM_SKETCH MAIN_SKETCH_PATH SKETCH_SOURCES SKETCH_CPP) + file(WRITE ${SKETCH_CPP} "// automatically generated by arduino-cmake\n") + file(READ ${MAIN_SKETCH_PATH} MAIN_SKETCH) + + # remove comments + remove_comments(MAIN_SKETCH MAIN_SKETCH_NO_COMMENTS) + + # find first statement + string(REGEX MATCH "[\n][_a-zA-Z0-9]+[^\n]*" FIRST_STATEMENT "${MAIN_SKETCH_NO_COMMENTS}") + string(FIND "${MAIN_SKETCH}" "${FIRST_STATEMENT}" HEAD_LENGTH) + if ("${HEAD_LENGTH}" STREQUAL "-1") + set(HEAD_LENGTH 0) + endif() + #message(STATUS "FIRST STATEMENT: ${FIRST_STATEMENT}") + #message(STATUS "FIRST STATEMENT POSITION: ${HEAD_LENGTH}") + string(LENGTH "${MAIN_SKETCH}" MAIN_SKETCH_LENGTH) + + string(SUBSTRING "${MAIN_SKETCH}" 0 ${HEAD_LENGTH} SKETCH_HEAD) + #arduino_debug_msg("SKETCH_HEAD:\n${SKETCH_HEAD}") + + # find the body of the main pde + math(EXPR BODY_LENGTH "${MAIN_SKETCH_LENGTH}-${HEAD_LENGTH}") + string(SUBSTRING "${MAIN_SKETCH}" "${HEAD_LENGTH}+1" "${BODY_LENGTH}-1" SKETCH_BODY) + #arduino_debug_msg("BODY:\n${SKETCH_BODY}") + + # write the file head + file(APPEND ${SKETCH_CPP} "#line 1 \"${MAIN_SKETCH_PATH}\"\n${SKETCH_HEAD}") + + # Count head line offset (for GCC error reporting) + file(STRINGS ${SKETCH_CPP} SKETCH_HEAD_LINES) + list(LENGTH SKETCH_HEAD_LINES SKETCH_HEAD_LINES_COUNT) + math(EXPR SKETCH_HEAD_OFFSET "${SKETCH_HEAD_LINES_COUNT}+2") + + # add arduino include header + #file(APPEND ${SKETCH_CPP} "\n#line 1 \"autogenerated\"\n") + file(APPEND ${SKETCH_CPP} "\n#line ${SKETCH_HEAD_OFFSET} \"${SKETCH_CPP}\"\n") + if(ARDUINO_SDK_VERSION VERSION_LESS 1.0) + file(APPEND ${SKETCH_CPP} "#include \"WProgram.h\"\n") + else() + file(APPEND ${SKETCH_CPP} "#include \"Arduino.h\"\n") + endif() + + # add function prototypes + foreach(SKETCH_SOURCE_PATH ${SKETCH_SOURCES} ${MAIN_SKETCH_PATH}) + arduino_debug_msg("Sketch: ${SKETCH_SOURCE_PATH}") + file(READ ${SKETCH_SOURCE_PATH} SKETCH_SOURCE) + remove_comments(SKETCH_SOURCE SKETCH_SOURCE) + + set(ALPHA "a-zA-Z") + set(NUM "0-9") + set(ALPHANUM "${ALPHA}${NUM}") + set(WORD "_${ALPHANUM}") + set(LINE_START "(^|[\n])") + set(QUALIFIERS "[ \t]*([${ALPHA}]+[ ])*") + set(TYPE "[${WORD}]+([ ]*[\n][\t]*|[ ])+") + set(FNAME "[${WORD}]+[ ]?[\n]?[\t]*[ ]*") + set(FARGS "[(]([\t]*[ ]*[*&]?[ ]?[${WORD}](\\[([${NUM}]+)?\\])*[,]?[ ]*[\n]?)*([,]?[ ]*[\n]?)?[)]") + set(BODY_START "([ ]*[\n][\t]*|[ ]|[\n])*{") + set(PROTOTYPE_PATTERN "${LINE_START}${QUALIFIERS}${TYPE}${FNAME}${FARGS}${BODY_START}") + + string(REGEX MATCHALL "${PROTOTYPE_PATTERN}" SKETCH_PROTOTYPES "${SKETCH_SOURCE}") + + # Write function prototypes + file(APPEND ${SKETCH_CPP} "\n//=== START Forward: ${SKETCH_SOURCE_PATH}\n") + foreach(SKETCH_PROTOTYPE ${SKETCH_PROTOTYPES}) + string(REPLACE "\n" " " SKETCH_PROTOTYPE "${SKETCH_PROTOTYPE}") + string(REPLACE "{" "" SKETCH_PROTOTYPE "${SKETCH_PROTOTYPE}") + arduino_debug_msg("\tprototype: ${SKETCH_PROTOTYPE};") + # " else if(var == other) {" shoudn't be listed as prototype + if(NOT SKETCH_PROTOTYPE MATCHES "(if[ ]?[\n]?[\t]*[ ]*[)])") + file(APPEND ${SKETCH_CPP} "${SKETCH_PROTOTYPE};\n") + else() + arduino_debug_msg("\trejected prototype: ${SKETCH_PROTOTYPE};") + endif() + file(APPEND ${SKETCH_CPP} "${SKETCH_PROTOTYPE};\n") + endforeach() + file(APPEND ${SKETCH_CPP} "//=== END Forward: ${SKETCH_SOURCE_PATH}\n") + endforeach() + + # Write Sketch CPP source + get_num_lines("${SKETCH_HEAD}" HEAD_NUM_LINES) + file(APPEND ${SKETCH_CPP} "#line ${HEAD_NUM_LINES} \"${MAIN_SKETCH_PATH}\"\n") + file(APPEND ${SKETCH_CPP} "\n${SKETCH_BODY}") + foreach (SKETCH_SOURCE_PATH ${SKETCH_SOURCES}) + file(READ ${SKETCH_SOURCE_PATH} SKETCH_SOURCE) + file(APPEND ${SKETCH_CPP} "\n//=== START : ${SKETCH_SOURCE_PATH}\n") + file(APPEND ${SKETCH_CPP} "#line 1 \"${SKETCH_SOURCE_PATH}\"\n") + file(APPEND ${SKETCH_CPP} "${SKETCH_SOURCE}") + file(APPEND ${SKETCH_CPP} "\n//=== END : ${SKETCH_SOURCE_PATH}\n") + endforeach() +endfunction() + +#=============================================================================# +# [PRIVATE/INTERNAL] +# +# setup_arduino_size_script(OUTPUT_VAR) +# +# OUTPUT_VAR - Output variable that will contain the script path +# +# Generates script used to display the firmware size. +#=============================================================================# +function(SETUP_ARDUINO_SIZE_SCRIPT OUTPUT_VAR) + set(ARDUINO_SIZE_SCRIPT_PATH ${CMAKE_BINARY_DIR}/CMakeFiles/FirmwareSize.cmake) + + file(WRITE ${ARDUINO_SIZE_SCRIPT_PATH} " + set(AVRSIZE_PROGRAM \"${AVRSIZE_PROGRAM}\") + set(AVRSIZE_FLAGS -C --mcu=\${MCU}) + + execute_process(COMMAND \${AVRSIZE_PROGRAM} \${AVRSIZE_FLAGS} \${FIRMWARE_IMAGE} \${EEPROM_IMAGE} + OUTPUT_VARIABLE SIZE_OUTPUT) + + + string(STRIP \"\${SIZE_OUTPUT}\" RAW_SIZE_OUTPUT) + + # Convert lines into a list + string(REPLACE \"\\n\" \";\" SIZE_OUTPUT_LIST \"\${SIZE_OUTPUT}\") + + set(SIZE_OUTPUT_LINES) + foreach(LINE \${SIZE_OUTPUT_LIST}) + if(NOT \"\${LINE}\" STREQUAL \"\") + list(APPEND SIZE_OUTPUT_LINES \"\${LINE}\") + endif() + endforeach() + + function(EXTRACT LIST_NAME INDEX VARIABLE) + list(GET \"\${LIST_NAME}\" \${INDEX} RAW_VALUE) + string(STRIP \"\${RAW_VALUE}\" VALUE) + + set(\${VARIABLE} \"\${VALUE}\" PARENT_SCOPE) + endfunction() + function(PARSE INPUT VARIABLE_PREFIX) + if(\${INPUT} MATCHES \"([^:]+):[ \\t]*([0-9]+)[ \\t]*([^ \\t]+)[ \\t]*[(]([0-9.]+)%.*\") + set(ENTRY_NAME \${CMAKE_MATCH_1}) + set(ENTRY_SIZE \${CMAKE_MATCH_2}) + set(ENTRY_SIZE_TYPE \${CMAKE_MATCH_3}) + set(ENTRY_PERCENT \${CMAKE_MATCH_4}) + endif() + + set(\${VARIABLE_PREFIX}_NAME \${ENTRY_NAME} PARENT_SCOPE) + set(\${VARIABLE_PREFIX}_SIZE \${ENTRY_SIZE} PARENT_SCOPE) + set(\${VARIABLE_PREFIX}_SIZE_TYPE \${ENTRY_SIZE_TYPE} PARENT_SCOPE) + set(\${VARIABLE_PREFIX}_PERCENT \${ENTRY_PERCENT} PARENT_SCOPE) + endfunction() + + list(LENGTH SIZE_OUTPUT_LINES SIZE_OUTPUT_LENGTH) + #message(\"\${SIZE_OUTPUT_LINES}\") + #message(\"\${SIZE_OUTPUT_LENGTH}\") + if (\${SIZE_OUTPUT_LENGTH} STREQUAL 14) + EXTRACT(SIZE_OUTPUT_LINES 3 FIRMWARE_PROGRAM_SIZE_ROW) + EXTRACT(SIZE_OUTPUT_LINES 5 FIRMWARE_DATA_SIZE_ROW) + PARSE(FIRMWARE_PROGRAM_SIZE_ROW FIRMWARE_PROGRAM) + PARSE(FIRMWARE_DATA_SIZE_ROW FIRMWARE_DATA) + + set(FIRMWARE_STATUS \"Firmware Size: \") + set(FIRMWARE_STATUS \"\${FIRMWARE_STATUS} [\${FIRMWARE_PROGRAM_NAME}: \${FIRMWARE_PROGRAM_SIZE} \${FIRMWARE_PROGRAM_SIZE_TYPE} (\${FIRMWARE_PROGRAM_PERCENT}%)] \") + set(FIRMWARE_STATUS \"\${FIRMWARE_STATUS} [\${FIRMWARE_DATA_NAME}: \${FIRMWARE_DATA_SIZE} \${FIRMWARE_DATA_SIZE_TYPE} (\${FIRMWARE_DATA_PERCENT}%)]\") + set(FIRMWARE_STATUS \"\${FIRMWARE_STATUS} on \${MCU}\") + + EXTRACT(SIZE_OUTPUT_LINES 10 EEPROM_PROGRAM_SIZE_ROW) + EXTRACT(SIZE_OUTPUT_LINES 12 EEPROM_DATA_SIZE_ROW) + PARSE(EEPROM_PROGRAM_SIZE_ROW EEPROM_PROGRAM) + PARSE(EEPROM_DATA_SIZE_ROW EEPROM_DATA) + + set(EEPROM_STATUS \"EEPROM Size: \") + set(EEPROM_STATUS \"\${EEPROM_STATUS} [\${EEPROM_PROGRAM_NAME}: \${EEPROM_PROGRAM_SIZE} \${EEPROM_PROGRAM_SIZE_TYPE} (\${EEPROM_PROGRAM_PERCENT}%)] \") + set(EEPROM_STATUS \"\${EEPROM_STATUS} [\${EEPROM_DATA_NAME}: \${EEPROM_DATA_SIZE} \${EEPROM_DATA_SIZE_TYPE} (\${EEPROM_DATA_PERCENT}%)]\") + set(EEPROM_STATUS \"\${EEPROM_STATUS} on \${MCU}\") + + message(\"\${FIRMWARE_STATUS}\") + message(\"\${EEPROM_STATUS}\\n\") + + if(\$ENV{VERBOSE}) + message(\"\${RAW_SIZE_OUTPUT}\\n\") + elseif(\$ENV{VERBOSE_SIZE}) + message(\"\${RAW_SIZE_OUTPUT}\\n\") + endif() + else() + message(\"\${RAW_SIZE_OUTPUT}\") + endif() + ") + + set(${OUTPUT_VAR} ${ARDUINO_SIZE_SCRIPT_PATH} PARENT_SCOPE) +endfunction() + + +#=============================================================================# +# [PRIVATE/INTERNAL] +# +# arduino_debug_on() +# +# Enables Arduino module debugging. +#=============================================================================# +function(ARDUINO_DEBUG_ON) + set(ARDUINO_DEBUG True PARENT_SCOPE) +endfunction() + + +#=============================================================================# +# [PRIVATE/INTERNAL] +# +# arduino_debug_off() +# +# Disables Arduino module debugging. +#=============================================================================# +function(ARDUINO_DEBUG_OFF) + set(ARDUINO_DEBUG False PARENT_SCOPE) +endfunction() + + +#=============================================================================# +# [PRIVATE/INTERNAL] +# +# arduino_debug_msg(MSG) +# +# MSG - Message to print +# +# Print Arduino debugging information. In order to enable printing +# use arduino_debug_on() and to disable use arduino_debug_off(). +#=============================================================================# +function(ARDUINO_DEBUG_MSG MSG) + if(ARDUINO_DEBUG) + message("## ${MSG}") + endif() +endfunction() + +#=============================================================================# +# [PRIVATE/INTERNAL] +# +# remove_comments(SRC_VAR OUT_VAR) +# +# SRC_VAR - variable holding sources +# OUT_VAR - variable holding sources with no comments +# +# Removes all comments from the source code. +#=============================================================================# +function(REMOVE_COMMENTS SRC_VAR OUT_VAR) + string(REGEX REPLACE "[\\./\\\\]" "_" FILE "${NAME}") + + set(SRC ${${SRC_VAR}}) + + #message(STATUS "removing comments from: ${FILE}") + #file(WRITE "${CMAKE_BINARY_DIR}/${FILE}_pre_remove_comments.txt" ${SRC}) + #message(STATUS "\n${SRC}") + + # remove all comments + string(REGEX REPLACE "([/][/][^\n]*)|([/][\\*]([^\\*]|([\\*]+[^/\\*]))*[\\*]+[/])" "" OUT "${SRC}") + + #file(WRITE "${CMAKE_BINARY_DIR}/${FILE}_post_remove_comments.txt" ${SRC}) + #message(STATUS "\n${SRC}") + + set(${OUT_VAR} ${OUT} PARENT_SCOPE) + +endfunction() + +#=============================================================================# +# [PRIVATE/INTERNAL] +# +# get_num_lines(DOCUMENT OUTPUT_VAR) +# +# DOCUMENT - Document contents +# OUTPUT_VAR - Variable which will hold the line number count +# +# Counts the line number of the document. +#=============================================================================# +function(GET_NUM_LINES DOCUMENT OUTPUT_VAR) + string(REGEX MATCHALL "[\n]" MATCH_LIST "${DOCUMENT}") + list(LENGTH MATCH_LIST NUM) + set(${OUTPUT_VAR} ${NUM} PARENT_SCOPE) +endfunction() + +#=============================================================================# +# [PRIVATE/INTERNAL] +# +# required_variables(MSG msg VARS var1 var2 .. varN) +# +# MSG - Message to be displayed in case of error +# VARS - List of variables names to check +# +# Ensure the specified variables are not empty, otherwise a fatal error is emmited. +#=============================================================================# +function(REQUIRED_VARIABLES) + cmake_parse_arguments(INPUT "" "MSG" "VARS" ${ARGN}) + error_for_unparsed(INPUT) + foreach(VAR ${INPUT_VARS}) + if ("${${VAR}}" STREQUAL "") + message(FATAL_ERROR "${VAR} not set: ${INPUT_MSG}") + endif() + endforeach() +endfunction() + +#=============================================================================# +# [PRIVATE/INTERNAL] +# +# error_for_unparsed(PREFIX) +# +# PREFIX - Prefix name +# +# Emit fatal error if there are unparsed argument from cmake_parse_arguments(). +#=============================================================================# +function(ERROR_FOR_UNPARSED PREFIX) + set(ARGS "${${PREFIX}_UNPARSED_ARGUMENTS}") + if (NOT ( "${ARGS}" STREQUAL "") ) + message(FATAL_ERROR "unparsed argument: ${ARGS}") + endif() +endfunction() + + + + + + +#=============================================================================# +# C Flags +#=============================================================================# +if (NOT DEFINED ARDUINO_C_FLAGS) + set(ARDUINO_C_FLAGS "-g -Os -w -ffunction-sections -fdata-sections -MMD") +endif (NOT DEFINED ARDUINO_C_FLAGS) +set(CMAKE_C_FLAGS "${ARDUINO_C_FLAGS}" CACHE STRING "") +set(CMAKE_C_FLAGS_DEBUG "${ARDUINO_C_FLAGS}" CACHE STRING "") +set(CMAKE_C_FLAGS_MINSIZEREL "${ARDUINO_C_FLAGS}" CACHE STRING "") +set(CMAKE_C_FLAGS_RELEASE "${ARDUINO_C_FLAGS}" CACHE STRING "") +set(CMAKE_C_FLAGS_RELWITHDEBINFO "${ARDUINO_C_FLAGS}" CACHE STRING "") + +#=============================================================================# +# C++ Flags +#=============================================================================# +if (NOT DEFINED ARDUINO_CXX_FLAGS) + set(ARDUINO_CXX_FLAGS "-g -Os -w -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -MMD") +endif (NOT DEFINED ARDUINO_CXX_FLAGS) +set(CMAKE_CXX_FLAGS "${ARDUINO_CXX_FLAGS}" CACHE STRING "") +set(CMAKE_CXX_FLAGS_DEBUG "${ARDUINO_CXX_FLAGS}" CACHE STRING "") +set(CMAKE_CXX_FLAGS_MINSIZEREL "${ARDUINO_CXX_FLAGS}" CACHE STRING "") +set(CMAKE_CXX_FLAGS_RELEASE "${ARDUINO_CXX_FLAGS}" CACHE STRING "") +set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${ARDUINO_CXX_FLAGS}" CACHE STRING "") + +#=============================================================================# +# Executable Linker Flags # +#=============================================================================# +set(ARDUINO_LINKER_FLAGS "-w -Os -Wl,--gc-sections") +set(CMAKE_EXE_LINKER_FLAGS "${ARDUINO_LINKER_FLAGS}" CACHE STRING "") +set(CMAKE_EXE_LINKER_FLAGS_DEBUG "${ARDUINO_LINKER_FLAGS}" CACHE STRING "") +set(CMAKE_EXE_LINKER_FLAGS_MINSIZEREL "${ARDUINO_LINKER_FLAGS}" CACHE STRING "") +set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${ARDUINO_LINKER_FLAGS}" CACHE STRING "") +set(CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO "${ARDUINO_LINKER_FLAGS}" CACHE STRING "") + +#=============================================================================# +#=============================================================================# +# Shared Lbrary Linker Flags # +#=============================================================================# +set(CMAKE_SHARED_LINKER_FLAGS "${ARDUINO_LINKER_FLAGS}" CACHE STRING "") +set(CMAKE_SHARED_LINKER_FLAGS_DEBUG "${ARDUINO_LINKER_FLAGS}" CACHE STRING "") +set(CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL "${ARDUINO_LINKER_FLAGS}" CACHE STRING "") +set(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${ARDUINO_LINKER_FLAGS}" CACHE STRING "") +set(CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO "${ARDUINO_LINKER_FLAGS}" CACHE STRING "") + +set(CMAKE_MODULE_LINKER_FLAGS "${ARDUINO_LINKER_FLAGS}" CACHE STRING "") +set(CMAKE_MODULE_LINKER_FLAGS_DEBUG "${ARDUINO_LINKER_FLAGS}" CACHE STRING "") +set(CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL "${ARDUINO_LINKER_FLAGS}" CACHE STRING "") +set(CMAKE_MODULE_LINKER_FLAGS_RELEASE "${ARDUINO_LINKER_FLAGS}" CACHE STRING "") +set(CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO "${ARDUINO_LINKER_FLAGS}" CACHE STRING "") + + +#=============================================================================# +# Arduino Settings +#=============================================================================# +set(ARDUINO_OBJCOPY_EEP_FLAGS -O ihex -j .eeprom --set-section-flags=.eeprom=alloc,load + --no-change-warnings --change-section-lma .eeprom=0 CACHE STRING "") +set(ARDUINO_OBJCOPY_HEX_FLAGS -O ihex -R .eeprom CACHE STRING "") +set(ARDUINO_AVRDUDE_FLAGS -V CACHE STRING "") + +#=============================================================================# +# Initialization +#=============================================================================# +if(NOT ARDUINO_FOUND AND ARDUINO_SDK_PATH) + register_hardware_platform(${ARDUINO_SDK_PATH}/hardware/arduino/) + + find_file(ARDUINO_LIBRARIES_PATH + NAMES libraries + PATHS ${ARDUINO_SDK_PATH} + DOC "Path to directory containing the Arduino libraries." + NO_SYSTEM_ENVIRONMENT_PATH) + + find_file(ARDUINO_VERSION_PATH + NAMES lib/version.txt + PATHS ${ARDUINO_SDK_PATH} + DOC "Path to Arduino version file." + NO_SYSTEM_ENVIRONMENT_PATH) + + find_program(ARDUINO_AVRDUDE_PROGRAM + NAMES avrdude + PATHS ${ARDUINO_SDK_PATH} + PATH_SUFFIXES hardware/tools hardware/tools/avr/bin + NO_DEFAULT_PATH) + + find_program(ARDUINO_AVRDUDE_PROGRAM + NAMES avrdude + DOC "Path to avrdude programmer binary.") + + find_program(AVRSIZE_PROGRAM + NAMES avr-size) + + find_file(ARDUINO_AVRDUDE_CONFIG_PATH + NAMES avrdude.conf + PATHS ${ARDUINO_SDK_PATH} /etc/avrdude /etc + PATH_SUFFIXES hardware/tools + hardware/tools/avr/etc + DOC "Path to avrdude programmer configuration file." + NO_SYSTEM_ENVIRONMENT_PATH) + + if(NOT CMAKE_OBJCOPY) + find_program(AVROBJCOPY_PROGRAM + avr-objcopy) + set(ADDITIONAL_REQUIRED_VARS AVROBJCOPY_PROGRAM) + set(CMAKE_OBJCOPY ${AVROBJCOPY_PROGRAM} CACHE PATH "OBJCOPY Program for firmware convertion in hex") + endif(NOT CMAKE_OBJCOPY) + + set(ARDUINO_DEFAULT_BOARD uno CACHE STRING "Default Arduino Board ID when not specified.") + set(ARDUINO_DEFAULT_PORT CACHE STRING "Default Arduino port when not specified.") + set(ARDUINO_DEFAULT_SERIAL CACHE STRING "Default Arduino Serial command when not specified.") + set(ARDUINO_DEFAULT_PROGRAMMER CACHE STRING "Default Arduino Programmer ID when not specified.") + + # Ensure that all required paths are found + required_variables(VARS + ARDUINO_PLATFORMS + ARDUINO_CORES_PATH + ARDUINO_BOOTLOADERS_PATH + ARDUINO_LIBRARIES_PATH + ARDUINO_BOARDS_PATH + ARDUINO_PROGRAMMERS_PATH + ARDUINO_VERSION_PATH + ARDUINO_AVRDUDE_FLAGS + ARDUINO_AVRDUDE_PROGRAM + ARDUINO_AVRDUDE_CONFIG_PATH + AVRSIZE_PROGRAM + ${ADDITIONAL_REQUIRED_VARS} + MSG "Invalid Arduino SDK path (${ARDUINO_SDK_PATH}).\n") + + detect_arduino_version(ARDUINO_SDK_VERSION) + set(ARDUINO_SDK_VERSION ${ARDUINO_SDK_VERSION} CACHE STRING "Arduino SDK Version") + set(ARDUINO_SDK_VERSION_MAJOR ${ARDUINO_SDK_VERSION_MAJOR} CACHE STRING "Arduino SDK Major Version") + set(ARDUINO_SDK_VERSION_MINOR ${ARDUINO_SDK_VERSION_MINOR} CACHE STRING "Arduino SDK Minor Version") + set(ARDUINO_SDK_VERSION_PATCH ${ARDUINO_SDK_VERSION_PATCH} CACHE STRING "Arduino SDK Patch Version") + + if(ARDUINO_SDK_VERSION VERSION_LESS 0.19) + message(FATAL_ERROR "Unsupported Arduino SDK (require version 0.19 or higher)") + endif() + + message(STATUS "Arduino SDK version ${ARDUINO_SDK_VERSION}: ${ARDUINO_SDK_PATH}") + + setup_arduino_size_script(ARDUINO_SIZE_SCRIPT) + set(ARDUINO_SIZE_SCRIPT ${ARDUINO_SIZE_SCRIPT} CACHE INTERNAL "Arduino Size Script") + + #print_board_list() + #print_programmer_list() + + set(ARDUINO_FOUND True CACHE INTERNAL "Arduino Found") + mark_as_advanced( + ARDUINO_CORES_PATH + ARDUINO_VARIANTS_PATH + ARDUINO_BOOTLOADERS_PATH + ARDUINO_LIBRARIES_PATH + ARDUINO_BOARDS_PATH + ARDUINO_PROGRAMMERS_PATH + ARDUINO_VERSION_PATH + ARDUINO_AVRDUDE_FLAGS + ARDUINO_AVRDUDE_PROGRAM + ARDUINO_AVRDUDE_CONFIG_PATH + ARDUINO_OBJCOPY_EEP_FLAGS + ARDUINO_OBJCOPY_HEX_FLAGS + AVRSIZE_PROGRAM) +endif() + +if(ARDUINO_SDK_VERSION VERSION_LESS 1.5) + set(ARDUINO_PLATFORM "AVR") +else() + if(NOT ARDUINO_PLATFORM) + register_hardware_platform(${ARDUINO_SDK_PATH}/hardware/arduino/avr) + set(ARDUINO_PLATFORM "AVR") + else() + string(TOLOWER ${ARDUINO_PLATFORM} _platform) + register_hardware_platform(${ARDUINO_SDK_PATH}/hardware/arduino/${_platform}) + endif() +endif() + +if(ARDUINO_SDK_VERSION VERSION_LESS 1.5) + set(ARDUINO_PLATFORM "AVR") +else() + if(NOT ARDUINO_PLATFORM) + register_hardware_platform(${ARDUINO_SDK_PATH}/hardware/arduino/avr) + set(ARDUINO_PLATFORM "AVR") + else() + string(TOLOWER ${ARDUINO_PLATFORM} _platform) + register_hardware_platform(${ARDUINO_SDK_PATH}/hardware/arduino/${_platform}) + endif() +endif() + diff --git a/traffic_analyzer/light_control.ino b/traffic_analyzer/light_control.ino new file mode 100644 index 0000000..14262c3 --- /dev/null +++ b/traffic_analyzer/light_control.ino @@ -0,0 +1,211 @@ +#include + +/* + WiFiTelnetToSerial - Example Transparent UART to Telnet Server for esp8266 + + Copyright (c) 2015 Hristo Gochkov. All rights reserved. + This file is part of the ESP8266WiFi library for Arduino environment. + + 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ +#include + +#include // std::min + +#ifndef STASSID +#define STASSID "ZyXEL5500bT5" +#define STAPSK "eBusgxczl5" +#endif + +/* + SWAP_PINS: + 0: use Serial1 for logging (legacy example) + 1: configure Hardware Serial port on RX:GPIO13 TX:GPIO15 + and use SoftwareSerial for logging on + standard Serial pins RX:GPIO3 and TX:GPIO1 +*/ + +#define SWAP_PINS 0 + +/* + SERIAL_LOOPBACK + 0: normal serial operations + 1: RX-TX are internally connected (loopback) +*/ + +#define SERIAL_LOOPBACK 0 + +#define BAUD_SERIAL 115200 +#define BAUD_LOGGER 115200 +#define RXBUFFERSIZE 1024 + +//////////////////////////////////////////////////////////// + +#if SERIAL_LOOPBACK +#undef BAUD_SERIAL +#define BAUD_SERIAL 3000000 +#include +#endif + +#if SWAP_PINS +#include +SoftwareSerial* logger = nullptr; +#else +#define logger (&Serial1) +#endif + +#define STACK_PROTECTOR 512 // bytes + +//how many clients should be able to telnet to this ESP8266 +#define MAX_SRV_CLIENTS 2 +const char* ssid = STASSID; +const char* password = STAPSK; + +const int port = 23; + +WiFiServer server(port); +WiFiClient serverClients[MAX_SRV_CLIENTS]; + +void setup() { + + Serial.begin(BAUD_SERIAL); + Serial.setRxBufferSize(RXBUFFERSIZE); + +#if SWAP_PINS + Serial.swap(); + // Hardware serial is now on RX:GPIO13 TX:GPIO15 + // use SoftwareSerial on regular RX(3)/TX(1) for logging + logger = new SoftwareSerial(3, 1); + logger->begin(BAUD_LOGGER); + logger->println("\n\nUsing SoftwareSerial for logging"); +#else + logger->begin(BAUD_LOGGER); + logger->println("\n\nUsing Serial1 for logging"); +#endif + logger->println(ESP.getFullVersion()); + logger->printf("Serial baud: %d (8n1: %d KB/s)\n", BAUD_SERIAL, BAUD_SERIAL * 8 / 10 / 1024); + logger->printf("Serial receive buffer size: %d bytes\n", RXBUFFERSIZE); + +#if SERIAL_LOOPBACK + USC0(0) |= (1 << UCLBE); // incomplete HardwareSerial API + logger->println("Serial Internal Loopback enabled"); +#endif + + WiFi.mode(WIFI_STA); + WiFi.begin(ssid, password); + logger->print("\nConnecting to "); + logger->println(ssid); + while (WiFi.status() != WL_CONNECTED) { + logger->print('.'); + delay(500); + } + logger->println(); + logger->print("connected, address="); + logger->println(WiFi.localIP()); + + //start server + server.begin(); + server.setNoDelay(true); + + logger->print("Ready! Use 'telnet "); + logger->print(WiFi.localIP()); + logger->printf(" %d' to connect\n", port); +} + +void loop() { + //check if there are any new clients + if (server.hasClient()) { + //find free/disconnected spot + int i; + for (i = 0; i < MAX_SRV_CLIENTS; i++) + if (!serverClients[i]) { // equivalent to !serverClients[i].connected() + serverClients[i] = server.available(); + logger->print("New client: index "); + logger->print(i); + break; + } + + //no free/disconnected spot so reject + if (i == MAX_SRV_CLIENTS) { + server.available().println("busy"); + // hints: server.available() is a WiFiClient with short-term scope + // when out of scope, a WiFiClient will + // - flush() - all data will be sent + // - stop() - automatically too + logger->printf("server is busy with %d active connections\n", MAX_SRV_CLIENTS); + } + } + + //check TCP clients for data +#if 1 + // Incredibly, this code is faster than the bufferred one below - #4620 is needed + // loopback/3000000baud average 348KB/s + for (int i = 0; i < MAX_SRV_CLIENTS; i++) + while (serverClients[i].available() && Serial.availableForWrite() > 0) { + // working char by char is not very efficient + Serial.write(serverClients[i].read()); + } +#else + // loopback/3000000baud average: 312KB/s + for (int i = 0; i < MAX_SRV_CLIENTS; i++) + while (serverClients[i].available() && Serial.availableForWrite() > 0) { + size_t maxToSerial = std::min(serverClients[i].available(), Serial.availableForWrite()); + maxToSerial = std::min(maxToSerial, (size_t)STACK_PROTECTOR); + uint8_t buf[maxToSerial]; + size_t tcp_got = serverClients[i].read(buf, maxToSerial); + size_t serial_sent = Serial.write(buf, tcp_got); + if (serial_sent != maxToSerial) { + logger->printf("len mismatch: available:%zd tcp-read:%zd serial-write:%zd\n", maxToSerial, tcp_got, serial_sent); + } + } +#endif + + // determine maximum output size "fair TCP use" + // client.availableForWrite() returns 0 when !client.connected() + size_t maxToTcp = 0; + for (int i = 0; i < MAX_SRV_CLIENTS; i++) + if (serverClients[i]) { + size_t afw = serverClients[i].availableForWrite(); + if (afw) { + if (!maxToTcp) { + maxToTcp = afw; + } else { + maxToTcp = std::min(maxToTcp, afw); + } + } else { + // warn but ignore congested clients + logger->println("one client is congested"); + } + } + + //check UART for data + size_t len = std::min((size_t)Serial.available(), maxToTcp); + len = std::min(len, (size_t)STACK_PROTECTOR); + if (len) { + uint8_t sbuf[len]; + size_t serial_got = Serial.readBytes(sbuf, len); + // push UART data to all connected telnet clients + for (int i = 0; i < MAX_SRV_CLIENTS; i++) + // if client.availableForWrite() was 0 (congested) + // and increased since then, + // ensure write space is sufficient: + if (serverClients[i].availableForWrite() >= serial_got) { + size_t tcp_sent = serverClients[i].write(sbuf, serial_got); + if (tcp_sent != len) { + logger->printf("len mismatch: available:%zd serial-read:%zd tcp-write:%zd\n", len, serial_got, tcp_sent); + } + } + } +} \ No newline at end of file diff --git a/traffic_analyzer/traffic_analyzer.iml b/traffic_analyzer/traffic_analyzer.iml index 798190b..6c15359 100644 --- a/traffic_analyzer/traffic_analyzer.iml +++ b/traffic_analyzer/traffic_analyzer.iml @@ -3,7 +3,7 @@ - +