From 9ff48731c197f9b661972c856bf61453eb87f288 Mon Sep 17 00:00:00 2001 From: Marcus Proest Date: Mon, 9 Jan 2017 19:22:31 +0100 Subject: [PATCH] added arduino support to uavobjgenerator --- .gitignore | 1 + Makefile | 4 +- arduino/uavobjects/inc/uavobject.h.template | 84 +++++++++ .../arduino/uavobjectgeneratorarduino.cpp | 178 ++++++++++++++++++ .../arduino/uavobjectgeneratorarduino.h | 47 +++++ ground/uavobjgenerator/main.cpp | 10 +- ground/uavobjgenerator/uavobjgenerator.pro | 3 + 7 files changed, 324 insertions(+), 3 deletions(-) create mode 100644 arduino/uavobjects/inc/uavobject.h.template create mode 100644 ground/uavobjgenerator/generators/arduino/uavobjectgeneratorarduino.cpp create mode 100644 ground/uavobjgenerator/generators/arduino/uavobjectgeneratorarduino.h diff --git a/.gitignore b/.gitignore index 514d54238..51bd0bdcf 100644 --- a/.gitignore +++ b/.gitignore @@ -40,6 +40,7 @@ ground/gcs/.settings *.exe *.log *.opl +*.autosave /ground/gcs/share/translations/extract-mimetypes.xq /ground/gcs/src/experimental/tools/DocumentationHelper/ui_mainwindow.h /ground/gcs/src/libs/qextserialport/.hg diff --git a/Makefile b/Makefile index 3def30cc7..1a0336f76 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ # # Top level Makefile for the LibrePilot Project build system. -# Copyright (c) 2015, The LibrePilot Project, http://www.librepilot.org +# Copyright (c) 2015-2017, The LibrePilot Project, http://www.librepilot.org # Copyright (c) 2010-2013, The OpenPilot Team, http://www.openpilot.org # Use 'make help' for instructions. # @@ -195,7 +195,7 @@ $(UAVOBJGENERATOR): | $(UAVOBJGENERATOR_DIR) CONFIG+='$(GCS_BUILD_CONF) $(GCS_EXTRA_CONF)' ) && \ $(MAKE) --no-print-directory -w -UAVOBJ_TARGETS := gcs flight python matlab java wireshark +UAVOBJ_TARGETS := gcs flight arduino python matlab java wireshark .PHONY: uavobjects uavobjects: $(addprefix uavobjects_, $(UAVOBJ_TARGETS)) diff --git a/arduino/uavobjects/inc/uavobject.h.template b/arduino/uavobjects/inc/uavobject.h.template new file mode 100644 index 000000000..eff87a9a2 --- /dev/null +++ b/arduino/uavobjects/inc/uavobject.h.template @@ -0,0 +1,84 @@ +/** + ****************************************************************************** + * @addtogroup UAVObjects LibrePilot UAVObjects + * @{ + * @addtogroup $(NAME) $(NAME) + * @brief $(DESCRIPTION) + * + * Autogenerated files and functions for $(NAME) Object + * + * @{ + * + * @file $(NAMELC).h + * + * @author The LibrePilot Project, https://www.librepilot.org, (C) 2017. + * The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010-2013. + * + * @brief Arduino Header of the $(NAME) object. This file has been + * automatically generated by the UAVObjectGenerator. + * + * @note Object definition file: $(XMLFILE). + * This is an automatically generated file. + * DO NOT modify manually. + * + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef $(NAMEUC)_H +#define $(NAMEUC)_H +#include +/* Object constants */ +#define $(NAMEUC)_OBJID $(OBJIDHEX) +#define $(NAMEUC)_ISSINGLEINST $(ISSINGLEINST) +#define $(NAMEUC)_ISSETTINGS $(ISSETTINGS) +#define $(NAMEUC)_ISPRIORITY $(ISPRIORITY) +#define $(NAMEUC)_NUMBYTES sizeof($(NAME)Data) + +$(DATAFIELDINFO) + +$(DATASTRUCTURES) +/* + * Packed Object data (unaligned). + * Should only be used where 4 byte alignment can be guaranteed + * (eg a single instance on the heap) + */ +typedef struct { +$(DATAFIELDS) +} __attribute__((packed)) $(NAME)DataPacked; + +/* + * Packed Object data. + * Alignment is forced to 4 bytes + */ +typedef $(NAME)DataPacked __attribute__((aligned(4))) $(NAME)Data; + +/* + * Union to apply the data array to and to use as structured object data + */ +union { + $(NAME)DataPacked data; + byte arr[$(NAMEUC)_NUMBYTES]; + } $(NAME)DataUnion; + +#endif // $(NAMEUC)_H + +/** + * @} + * @} + */ diff --git a/ground/uavobjgenerator/generators/arduino/uavobjectgeneratorarduino.cpp b/ground/uavobjgenerator/generators/arduino/uavobjectgeneratorarduino.cpp new file mode 100644 index 000000000..4a19971eb --- /dev/null +++ b/ground/uavobjgenerator/generators/arduino/uavobjectgeneratorarduino.cpp @@ -0,0 +1,178 @@ +/** + ****************************************************************************** + * + * @file uavobjectgeneratorarduino.cpp + * @author The LibrePilot Project, https://www.librepilot.org, Copyright (C) 2017. + * The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief produce arduino code for uavobjects + * + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "uavobjectgeneratorarduino.h" + +using namespace std; + +bool UAVObjectGeneratorArduino::generate(UAVObjectParser *parser, QString templatepath, QString outputpath) +{ + fieldTypeStrC << "int8_t" << "int16_t" << "int32_t" << "uint8_t" + << "uint16_t" << "uint32_t" << "float" << "uint8_t"; + + arduinoCodePath = QDir(templatepath + QString(ARDUINO_CODE_DIR)); + arduinoOutputPath = QDir(outputpath); + arduinoOutputPath.mkpath(arduinoOutputPath.absolutePath()); + + arduinoIncludeTemplate = readFile(arduinoCodePath.absoluteFilePath("inc/uavobject.h.template")); + + if (arduinoIncludeTemplate.isNull()) { + cerr << "Error: Could not open arduino template files." << endl; + return false; + } + + for (int objidx = 0; objidx < parser->getNumObjects(); ++objidx) { + ObjectInfo *info = parser->getObjectByIndex(objidx); + process_object(info); + } + return true; // if we come here everything should be fine +} + + +/** + * Generate the Arduino object files + **/ +bool UAVObjectGeneratorArduino::process_object(ObjectInfo *info) +{ + if (info == NULL) { + return false; + } + + // Prepare output strings + QString outInclude = arduinoIncludeTemplate; + + // Replace common tags + replaceCommonTags(outInclude, info); + + // Use the appropriate typedef for enums where we find them. Set up + // that StringList here for use below. + QStringList typeList; + for (int n = 0; n < info->fields.length(); ++n) { + if (info->fields[n]->type == FIELDTYPE_ENUM) { + typeList << QString("%1%2Options").arg(info->name).arg(info->fields[n]->name); + } else { + typeList << fieldTypeStrC[info->fields[n]->type]; + } + } + + // Replace the $(DATAFIELDS) tag + QString fields; + QString dataStructures; + for (int n = 0; n < info->fields.length(); ++n) { + // Determine type + QString type = typeList[n]; + // Append field + // Check if it is a named set and create structures accordingly + if (info->fields[n]->numElements > 1) { + if (info->fields[n]->elementNames[0].compare("0") != 0) { + QString structTypeName = QString("%1%2Data").arg(info->name).arg(info->fields[n]->name); + QString structType = "typedef struct __attribute__ ((__packed__)) {\n"; + for (int f = 0; f < info->fields[n]->elementNames.count(); f++) { + structType.append(QString(" %1 %2;\n").arg(type).arg(info->fields[n]->elementNames[f])); + } + structType.append(QString("} %1 ;\n").arg(structTypeName)); + structType.append("typedef struct __attribute__ ((__packed__)) {\n"); + structType.append(QString(" %1 array[%2];\n").arg(type).arg(info->fields[n]->elementNames.count())); + structType.append(QString("} %1Array ;\n").arg(structTypeName)); + structType.append(QString("#define %1%2ToArray( var ) UAVObjectFieldToArray( %3, var )\n\n").arg(info->name).arg(info->fields[n]->name).arg(structTypeName)); + + dataStructures.append(structType); + + fields.append(QString(" %1 %2;\n").arg(structTypeName) + .arg(info->fields[n]->name)); + } else { + fields.append(QString(" %1 %2[%3];\n").arg(type) + .arg(info->fields[n]->name).arg(info->fields[n]->numElements)); + } + } else { + fields.append(QString(" %1 %2;\n").arg(type).arg(info->fields[n]->name)); + } + } + outInclude.replace("$(DATAFIELDS)", fields); + outInclude.replace("$(DATASTRUCTURES)", dataStructures); + // Replace the $(DATAFIELDINFO) tag + QString enums; + for (int n = 0; n < info->fields.length(); ++n) { + enums.append(QString("/* Field %1 information */\n").arg(info->fields[n]->name)); + // Only for enum types + if (info->fields[n]->type == FIELDTYPE_ENUM) { + enums.append(QString("\n// Enumeration options for field %1\n").arg(info->fields[n]->name)); + enums.append("typedef enum __attribute__ ((__packed__)) {\n"); + // Go through each option + QStringList options = info->fields[n]->options; + for (int m = 0; m < options.length(); ++m) { + QString s = (m == (options.length() - 1)) ? " %1_%2_%3=%4\n" : " %1_%2_%3=%4,\n"; + enums.append(s + .arg(info->name.toUpper()) + .arg(info->fields[n]->name.toUpper()) + .arg(options[m].toUpper().replace(QRegExp(ENUM_SPECIAL_CHARS), "")) + .arg(m)); + } + enums.append(QString("} %1%2Options;\n") + .arg(info->name) + .arg(info->fields[n]->name)); + } + // Generate element names (only if field has more than one element) + if (info->fields[n]->numElements > 1 && !info->fields[n]->defaultElementNames) { + enums.append(QString("\n// Array element names for field %1\n").arg(info->fields[n]->name)); + enums.append("typedef enum {\n"); + // Go through the element names + QStringList elemNames = info->fields[n]->elementNames; + for (int m = 0; m < elemNames.length(); ++m) { + QString s = (m != (elemNames.length() - 1)) ? " %1_%2_%3=%4,\n" : " %1_%2_%3=%4\n"; + enums.append(s + .arg(info->name.toUpper()) + .arg(info->fields[n]->name.toUpper()) + .arg(elemNames[m].toUpper()) + .arg(m)); + } + enums.append(QString("} %1%2Elem;\n") + .arg(info->name) + .arg(info->fields[n]->name)); + } + // Generate array information + if (info->fields[n]->numElements > 1) { + enums.append(QString("\n// Number of elements for field %1\n").arg(info->fields[n]->name)); + enums.append(QString("#define %1_%2_NUMELEM %3\n") + .arg(info->name.toUpper()) + .arg(info->fields[n]->name.toUpper()) + .arg(info->fields[n]->numElements)); + } + + enums.append("\n"); + } + outInclude.replace("$(DATAFIELDINFO)", enums); + + // Write the arduino code + bool res = writeFileIfDifferent(arduinoOutputPath.absolutePath() + "/" + info->namelc + ".h", outInclude); + if (!res) { + cout << "Error: Could not write arduino include files" << endl; + return false; + } + + return true; +} diff --git a/ground/uavobjgenerator/generators/arduino/uavobjectgeneratorarduino.h b/ground/uavobjgenerator/generators/arduino/uavobjectgeneratorarduino.h new file mode 100644 index 000000000..e495f92d3 --- /dev/null +++ b/ground/uavobjgenerator/generators/arduino/uavobjectgeneratorarduino.h @@ -0,0 +1,47 @@ +/** + ****************************************************************************** + * + * @file uavobjectgeneratorarduino.h + * @author The LibrePilot Project, https://www.librepilot.org Copyright (C) 2017. + * The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief produce arduino code for uavobjects + * + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef UAVOBJECTGENERATORARDUINO_H +#define UAVOBJECTGENERATORARDUINO_H + +#define ARDUINO_CODE_DIR "arduino/uavobjects" + +#include "../generator_common.h" + +class UAVObjectGeneratorArduino { +public: + bool generate(UAVObjectParser *gen, QString templatepath, QString outputpath); + QStringList fieldTypeStrC; + QString arduinoIncludeTemplate; + QDir arduinoCodePath; + QDir arduinoOutputPath; + +private: + bool process_object(ObjectInfo *info); +}; + +#endif diff --git a/ground/uavobjgenerator/main.cpp b/ground/uavobjgenerator/main.cpp index a3ec16bac..2cb2b8fbf 100644 --- a/ground/uavobjgenerator/main.cpp +++ b/ground/uavobjgenerator/main.cpp @@ -2,7 +2,7 @@ ****************************************************************************** * * @file main.cpp - * @author The LibrePilot Team http://www.librepilot.org Copyright (C) 2015. + * @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2015-2017. * The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. * @brief UAVObjectGenerator main. * @@ -32,6 +32,7 @@ #include "generators/java/uavobjectgeneratorjava.h" #include "generators/flight/uavobjectgeneratorflight.h" +#include "generators/arduino/uavobjectgeneratorarduino.h" #include "generators/gcs/uavobjectgeneratorgcs.h" #include "generators/matlab/uavobjectgeneratormatlab.h" #include "generators/python/uavobjectgeneratorpython.h" @@ -52,6 +53,7 @@ void usage() cout << "Languages: " << endl; cout << "\t-gcs build groundstation code" << endl; cout << "\t-flight build flight code" << endl; + cout << "\t-arduino build arduino code" << endl; cout << "\t-java build java code" << endl; cout << "\t-python build python code" << endl; cout << "\t-matlab build matlab code" << endl; @@ -105,6 +107,7 @@ int main(int argc, char *argv[]) bool verbose = (arguments_stringlist.removeAll("-v") > 0); bool do_gcs = (arguments_stringlist.removeAll("-gcs") > 0); bool do_flight = (arguments_stringlist.removeAll("-flight") > 0); + bool do_arduino = (arguments_stringlist.removeAll("-arduino") > 0); bool do_java = (arguments_stringlist.removeAll("-java") > 0); bool do_python = (arguments_stringlist.removeAll("-python") > 0); bool do_matlab = (arguments_stringlist.removeAll("-matlab") > 0); @@ -208,6 +211,11 @@ int main(int argc, char *argv[]) cout << "generating flight code" << endl; UAVObjectGeneratorFlight flightgen; flightgen.generate(parser, templatepath, outputpath); + } else if (do_arduino) { + // generate arduino code if wanted + cout << "generating arduino code" << endl; + UAVObjectGeneratorArduino arduinogen; + arduinogen.generate(parser, templatepath, outputpath); } else if (do_gcs) { // generate gcs code if wanted cout << "generating gcs code" << endl; diff --git a/ground/uavobjgenerator/uavobjgenerator.pro b/ground/uavobjgenerator/uavobjgenerator.pro index 1ac5d95cf..a5226d25e 100644 --- a/ground/uavobjgenerator/uavobjgenerator.pro +++ b/ground/uavobjgenerator/uavobjgenerator.pro @@ -1,5 +1,6 @@ # # Qmake project for UAVObjGenerator. +# Copyright (c) 2017, The LibrePilot Project, https://www.librepilot.org # Copyright (c) 2010-2013, The OpenPilot Team, http://www.openpilot.org # @@ -27,6 +28,7 @@ SOURCES += main.cpp \ generators/generator_io.cpp \ generators/java/uavobjectgeneratorjava.cpp \ generators/flight/uavobjectgeneratorflight.cpp \ + generators/arduino/uavobjectgeneratorarduino.cpp \ generators/gcs/uavobjectgeneratorgcs.cpp \ generators/matlab/uavobjectgeneratormatlab.cpp \ generators/python/uavobjectgeneratorpython.cpp \ @@ -36,6 +38,7 @@ HEADERS += uavobjectparser.h \ generators/generator_io.h \ generators/java/uavobjectgeneratorjava.h \ generators/gcs/uavobjectgeneratorgcs.h \ + generators/arduino/uavobjectgeneratorarduino.h \ generators/matlab/uavobjectgeneratormatlab.h \ generators/python/uavobjectgeneratorpython.h \ generators/wireshark/uavobjectgeneratorwireshark.h \