瀏覽代碼

Add support for the GAT562 Mesh Tracker Pro device

MGJ 5 月之前
父節點
當前提交
dc48126baf

+ 57 - 0
variants/gat562_mesh_tracker_pro/GAT562MeshTrackerProBoard.cpp

@@ -0,0 +1,57 @@
+#include <Arduino.h>
+#include <Wire.h>
+
+#include "GAT562MeshTrackerProBoard.h"
+
+
+#ifdef NRF52_POWER_MANAGEMENT
+// Static configuration for power management
+// Values set in variant.h defines
+const PowerMgtConfig power_config = {
+  .lpcomp_ain_channel = PWRMGT_LPCOMP_AIN,
+  .lpcomp_refsel = PWRMGT_LPCOMP_REFSEL,
+  .voltage_bootlock = PWRMGT_VOLTAGE_BOOTLOCK
+};
+
+
+void GAT562MeshTrackerProBoard::initiateShutdown(uint8_t reason) {
+  // Disable LoRa module power before shutdown
+  digitalWrite(SX126X_POWER_EN, LOW);
+
+  if (reason == SHUTDOWN_REASON_LOW_VOLTAGE ||
+      reason == SHUTDOWN_REASON_BOOT_PROTECT) {
+    configureVoltageWake(power_config.lpcomp_ain_channel, power_config.lpcomp_refsel);
+  }
+
+  enterSystemOff(reason);
+}
+#endif // NRF52_POWER_MANAGEMENT
+
+
+void GAT562MeshTrackerProBoard::begin() {
+  NRF52BoardDCDC::begin();
+  pinMode(PIN_VBAT_READ, INPUT);
+
+  // Set all button pins to INPUT_PULLUP
+  pinMode(PIN_BUTTON1, INPUT_PULLUP);
+  pinMode(PIN_BUTTON2, INPUT_PULLUP);
+  pinMode(PIN_BUTTON3, INPUT_PULLUP);
+  pinMode(PIN_BUTTON4, INPUT_PULLUP);
+  pinMode(PIN_BUTTON5, INPUT_PULLUP);
+  pinMode(PIN_BUTTON6, INPUT_PULLUP);
+
+#if defined(PIN_BOARD_SDA) && defined(PIN_BOARD_SCL)
+  Wire.setPins(PIN_BOARD_SDA, PIN_BOARD_SCL);
+#endif
+
+  Wire.begin();
+
+  pinMode(SX126X_POWER_EN, OUTPUT);
+#ifdef NRF52_POWER_MANAGEMENT
+  // Boot voltage protection check (may not return if voltage too low)
+  // We need to call this after we configure SX126X_POWER_EN as output but before we pull high
+  checkBootVoltage(&power_config);
+#endif
+  digitalWrite(SX126X_POWER_EN, HIGH);
+  delay(10);   // give sx1268 some time to power up
+}

+ 55 - 0
variants/gat562_mesh_tracker_pro/GAT562MeshTrackerProBoard.h

@@ -0,0 +1,55 @@
+#pragma once
+
+#include <MeshCore.h>
+#include <Arduino.h>
+#include <helpers/NRF52Board.h>
+
+
+class GAT562MeshTrackerProBoard : public NRF52BoardDCDC {
+protected:
+#ifdef NRF52_POWER_MANAGEMENT
+  void initiateShutdown(uint8_t reason) override;
+#endif
+
+public:
+  GAT562MeshTrackerProBoard() : NRF52Board("GAT562_OTA") {}
+  void begin();
+
+  #define BATTERY_SAMPLES 8
+
+  uint16_t getBattMilliVolts() override {
+    analogReadResolution(12);
+
+    uint32_t raw = 0;
+    for (int i = 0; i < BATTERY_SAMPLES; i++) {
+      raw += analogRead(PIN_VBAT_READ);
+    }
+    raw = raw / BATTERY_SAMPLES;
+
+    return (ADC_MULTIPLIER * raw) / 4096;
+  }
+
+  const char* getManufacturerName() const override {
+    return "GAT562 Mesh Tracker Pro";
+  }
+
+#if defined(P_LORA_TX_LED)
+  void onBeforeTransmit() override {
+    //nothing
+  }
+
+  void onAfterTransmit() override {
+    digitalWrite(P_LORA_TX_LED, HIGH);   // turn TX LED on
+    delay(10);
+    digitalWrite(P_LORA_TX_LED, LOW);   // turn TX LED off
+  }
+#endif
+
+  void powerOff() override {
+    uint32_t button_pin = PIN_BUTTON1;
+    nrf_gpio_cfg_input(button_pin, NRF_GPIO_PIN_PULLUP);
+    nrf_gpio_cfg_sense_set(button_pin, NRF_GPIO_PIN_SENSE_LOW);
+    sd_power_system_off(); 
+  }
+
+};

+ 114 - 0
variants/gat562_mesh_tracker_pro/platformio.ini

@@ -0,0 +1,114 @@
+[GAT562_Mesh_Tracker_Pro]
+extends = nrf52_base
+board = rak4631
+board_check = true
+build_flags = ${nrf52_base.build_flags}
+  ${sensor_base.build_flags}
+  -I variants/gat562_mesh_tracker_pro
+  -D RAK_4631
+  -D RAK_BOARD
+  -D NRF52_POWER_MANAGEMENT
+  -D LORA_FREQ=475
+  -D LORA_BW=125
+  -D LORA_SF=10
+  -D LORA_CR=6
+  -D PIN_BOARD_SCL=14
+  -D PIN_BOARD_SDA=13
+  -D PIN_OLED_RESET=-1
+  -D UI_HAS_JOYSTICK=1
+  -D RADIO_CLASS=CustomSX1262
+  -D WRAPPER_CLASS=CustomSX1262Wrapper
+  -D LORA_TX_POWER=22
+  -D SX126X_CURRENT_LIMIT=140
+  -D SX126X_RX_BOOSTED_GAIN=1
+build_src_filter = ${nrf52_base.build_src_filter}
+  +<../variants/gat562_mesh_tracker_pro>
+  +<helpers/ui/SSD1306Display.cpp>
+  +<helpers/ui/MomentaryButton.cpp>
+  +<helpers/sensors>
+lib_deps =
+  ${nrf52_base.lib_deps}
+  ${sensor_base.lib_deps}
+  adafruit/Adafruit SSD1306 @ ^2.5.13
+  sparkfun/SparkFun u-blox GNSS Arduino Library@^2.2.27
+
+
+[env:GAT562_Mesh_Tracker_Pro_repeater]
+extends = GAT562_Mesh_Tracker_Pro
+build_flags =
+  ${GAT562_Mesh_Tracker_Pro.build_flags}
+  -D DISPLAY_CLASS=SSD1306Display
+  -D ADVERT_NAME='"GAT562 Family Repeater"'
+  -D ADVERT_LAT=0.0
+  -D ADVERT_LON=0.0
+  -D ADMIN_PASSWORD='"password"'
+  -D MAX_NEIGHBOURS=50
+;  -D MESH_PACKET_LOGGING=1
+;  -D MESH_DEBUG=1
+build_src_filter = ${GAT562_Mesh_Tracker_Pro.build_src_filter}
+  +<helpers/ui/SSD1306Display.cpp>
+  +<../examples/simple_repeater>
+
+
+[env:GAT562_Mesh_Tracker_Pro_room_server]
+extends = GAT562_Mesh_Tracker_Pro
+build_flags =
+  ${GAT562_Mesh_Tracker_Pro.build_flags}
+  -D DISPLAY_CLASS=SSD1306Display
+  -D ADVERT_NAME='"GAT562 Family Room"'
+  -D ADVERT_LAT=0.0
+  -D ADVERT_LON=0.0
+  -D ADMIN_PASSWORD='"password"'
+  -D ROOM_PASSWORD='"hello"'
+;  -D MESH_PACKET_LOGGING=1
+;  -D MESH_DEBUG=1
+build_src_filter = ${GAT562_Mesh_Tracker_Pro.build_src_filter}
+  +<helpers/ui/SSD1306Display.cpp>
+  +<../examples/simple_room_server>
+
+
+[env:GAT562_Mesh_Tracker_Pro_companion_radio_usb]
+extends = GAT562_Mesh_Tracker_Pro
+board_build.ldscript = boards/nrf52840_s140_v6_extrafs.ld
+board_upload.maximum_size = 712704
+build_flags =
+  ${GAT562_Mesh_Tracker_Pro.build_flags}
+  -I examples/companion_radio/ui-new
+  -D DISPLAY_CLASS=SSD1306Display
+  -D MAX_CONTACTS=350
+  -D MAX_GROUP_CHANNELS=40
+; NOTE: DO NOT ENABLE -->  -D MESH_PACKET_LOGGING=1
+; NOTE: DO NOT ENABLE -->  -D MESH_DEBUG=1
+build_src_filter = ${GAT562_Mesh_Tracker_Pro.build_src_filter}
+  +<../examples/companion_radio/*.cpp>
+  +<../examples/companion_radio/ui-new/*.cpp>
+lib_deps =
+  ${GAT562_Mesh_Tracker_Pro.lib_deps}
+  densaugeo/base64 @ ~1.4.0
+
+
+
+[env:GAT562_Mesh_Tracker_Pro_companion_radio_ble]
+extends = GAT562_Mesh_Tracker_Pro
+board_build.ldscript = boards/nrf52840_s140_v6_extrafs.ld
+board_upload.maximum_size = 712704
+build_flags =
+  ${GAT562_Mesh_Tracker_Pro.build_flags}
+  -I examples/companion_radio/ui-new
+  -D DISPLAY_CLASS=SSD1306Display
+  -D MAX_CONTACTS=350
+  -D MAX_GROUP_CHANNELS=40
+  -D BLE_PIN_CODE=123456
+  -D BLE_DEBUG_LOGGING=1
+  -D OFFLINE_QUEUE_SIZE=256
+  ; -D MESH_PACKET_LOGGING=1
+  ; -D MESH_DEBUG=1
+build_src_filter = ${GAT562_Mesh_Tracker_Pro.build_src_filter}
+  +<helpers/nrf52/SerialBLEInterface.cpp>
+  +<helpers/ui/MomentaryButton.cpp>
+  +<../examples/companion_radio/*.cpp>
+  +<../examples/companion_radio/ui-new/*.cpp>
+lib_deps =
+  ${GAT562_Mesh_Tracker_Pro.lib_deps}
+  densaugeo/base64 @ ~1.4.0
+

+ 59 - 0
variants/gat562_mesh_tracker_pro/target.cpp

@@ -0,0 +1,59 @@
+#include <Arduino.h>
+#include "target.h"
+#include <helpers/ArduinoHelpers.h>
+
+GAT562MeshTrackerProBoard board;
+
+#ifndef PIN_USER_BTN
+  #define PIN_USER_BTN (-1)
+#endif
+
+
+#ifdef DISPLAY_CLASS
+  DISPLAY_CLASS display;
+  MomentaryButton user_btn(PIN_USER_BTN, 1000, true, false, false);
+  MomentaryButton joystick_left(JOYSTICK_LEFT, 1000, true, false, false);
+  MomentaryButton joystick_right(JOYSTICK_RIGHT, 1000, true, false, false);
+  MomentaryButton back_btn(PIN_BACK_BTN, 1000, true, false, true);
+#endif
+
+
+RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY, SPI);
+
+WRAPPER_CLASS radio_driver(radio, board);
+
+VolatileRTCClock fallback_clock;
+AutoDiscoverRTCClock rtc_clock(fallback_clock);
+
+#if ENV_INCLUDE_GPS
+  #include <helpers/sensors/MicroNMEALocationProvider.h>
+  MicroNMEALocationProvider nmea = MicroNMEALocationProvider(Serial1);
+  EnvironmentSensorManager sensors = EnvironmentSensorManager(nmea);
+#else
+  EnvironmentSensorManager sensors;
+#endif
+
+bool radio_init() {
+  rtc_clock.begin(Wire);
+  return radio.std_init(&SPI);
+}
+
+uint32_t radio_get_rng_seed() {
+  return radio.random(0x7FFFFFFF);
+}
+
+void radio_set_params(float freq, float bw, uint8_t sf, uint8_t cr) {
+  radio.setFrequency(freq);
+  radio.setSpreadingFactor(sf);
+  radio.setBandwidth(bw);
+  radio.setCodingRate(cr);
+}
+
+void radio_set_tx_power(int8_t dbm) {
+  radio.setOutputPower(dbm);
+}
+
+mesh::LocalIdentity radio_new_identity() {
+  RadioNoiseListener rng(radio);
+  return mesh::LocalIdentity(&rng);  // create new random identity
+}

+ 30 - 0
variants/gat562_mesh_tracker_pro/target.h

@@ -0,0 +1,30 @@
+#pragma once
+
+#define RADIOLIB_STATIC_ONLY 1
+#include <RadioLib.h>
+#include <helpers/radiolib/RadioLibWrappers.h>
+#include <GAT562MeshTrackerProBoard.h>
+#include <helpers/radiolib/CustomSX1262Wrapper.h>
+#include <helpers/AutoDiscoverRTCClock.h>
+#include <helpers/sensors/EnvironmentSensorManager.h>
+
+#ifdef DISPLAY_CLASS
+  #include <helpers/ui/SSD1306Display.h>
+  extern DISPLAY_CLASS display;
+  #include <helpers/ui/MomentaryButton.h>
+  extern MomentaryButton user_btn;
+  extern MomentaryButton joystick_left;
+  extern MomentaryButton joystick_right;
+  extern MomentaryButton back_btn;
+#endif
+
+extern GAT562MeshTrackerProBoard board;
+extern WRAPPER_CLASS radio_driver;
+extern AutoDiscoverRTCClock rtc_clock;
+extern EnvironmentSensorManager sensors;
+
+bool radio_init();
+uint32_t radio_get_rng_seed();
+void radio_set_params(float freq, float bw, uint8_t sf, uint8_t cr);
+void radio_set_tx_power(int8_t dbm);
+mesh::LocalIdentity radio_new_identity();

+ 49 - 0
variants/gat562_mesh_tracker_pro/variant.cpp

@@ -0,0 +1,49 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+  Copyright (c) 2016 Sandeep Mistry All right reserved.
+  Copyright (c) 2018, Adafruit Industries (adafruit.com)
+
+  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 "variant.h"
+#include "wiring_constants.h"
+#include "wiring_digital.h"
+#include "nrf.h"
+
+const uint32_t g_ADigitalPinMap[] =
+{
+  // P0
+  0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 ,
+  8 , 9 , 10, 11, 12, 13, 14, 15,
+  16, 17, 18, 19, 20, 21, 22, 23,
+  24, 25, 26, 27, 28, 29, 30, 31,
+
+  // P1
+  32, 33, 34, 35, 36, 37, 38, 39,
+  40, 41, 42, 43, 44, 45, 46, 47
+};
+
+
+void initVariant()
+{
+  // LED1 & LED2
+  pinMode(PIN_LED1, OUTPUT);
+  ledOff(PIN_LED1);
+
+  // pinMode(PIN_LED2, OUTPUT);
+  // ledOff(PIN_LED2);;
+}
+

+ 226 - 0
variants/gat562_mesh_tracker_pro/variant.h

@@ -0,0 +1,226 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+  Copyright (c) 2016 Sandeep Mistry All right reserved.
+  Copyright (c) 2018, Adafruit Industries (adafruit.com)
+
+  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
+*/
+
+#ifndef _VARIANT_RAK4630_
+#define _VARIANT_RAK4630_
+
+#define RAK4630
+
+/** Master clock frequency */
+#define VARIANT_MCK (64000000ul)
+
+#define USE_LFXO // Board uses 32khz crystal for LF
+// define USE_LFRC    // Board uses RC for LF
+
+/*----------------------------------------------------------------------------
+ *        Headers
+ *----------------------------------------------------------------------------*/
+
+#include "WVariant.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif // __cplusplus
+
+	/*
+ * WisBlock Base GPIO definitions
+ */
+	static const uint8_t WB_IO1 = 17;	   // SLOT_A SLOT_B
+	static const uint8_t WB_IO2 = 34;	   // SLOT_A SLOT_B
+	static const uint8_t WB_IO3 = 21;	   // SLOT_C
+	static const uint8_t WB_IO4 = 4;	   // SLOT_C
+	static const uint8_t WB_IO5 = 9;	   // SLOT_D
+	static const uint8_t WB_IO6 = 10;	   // SLOT_D
+	static const uint8_t WB_SW1 = 33;	   // IO_SLOT
+	static const uint8_t WB_A0 = 5;		   // IO_SLOT
+	static const uint8_t WB_A1 = 31;	   // IO_SLOT
+	static const uint8_t WB_I2C1_SDA = 13; // SENSOR_SLOT IO_SLOT
+	static const uint8_t WB_I2C1_SCL = 14; // SENSOR_SLOT IO_SLOT
+	static const uint8_t WB_I2C2_SDA = 24; // IO_SLOT
+	static const uint8_t WB_I2C2_SCL = 25; // IO_SLOT
+	static const uint8_t WB_SPI_CS = 26;   // IO_SLOT
+	static const uint8_t WB_SPI_CLK = 3;   // IO_SLOT
+	static const uint8_t WB_SPI_MISO = 29; // IO_SLOT
+	static const uint8_t WB_SPI_MOSI = 30; // IO_SLOT
+
+// Number of pins defined in PinDescription array
+#define PINS_COUNT (48)
+#define NUM_DIGITAL_PINS (48)
+#define NUM_ANALOG_INPUTS (6)
+#define NUM_ANALOG_OUTPUTS (0)
+
+// LEDs
+#define PIN_LED1 (35)
+#define PIN_LED2 (36)
+
+#define LED_BUILTIN PIN_LED1
+#define LED_CONN PIN_LED2
+
+#define LED_GREEN  PIN_LED1
+#define LED_BLUE   PIN_LED2
+
+#define LED_STATE_ON 1 // State when LED is litted
+
+#define P_LORA_TX_LED LED_GREEN
+
+
+/*
+ * Buttons
+ */
+#define PIN_BUTTON1             (9) // Menu / User Button
+#define PIN_BUTTON2             (28) // Joystick Up
+#define PIN_BUTTON3             (4) // Joystick Down
+#define PIN_BUTTON4             (30) // Joystick Left
+#define PIN_BUTTON5             (31) // Joystick Right
+#define PIN_BUTTON6             (26) // Joystick Press
+#define PIN_BACK_BTN            PIN_BUTTON1
+#define JOYSTICK_UP             PIN_BUTTON2
+#define JOYSTICK_DOWN           PIN_BUTTON3
+#define JOYSTICK_LEFT           PIN_BUTTON4
+#define JOYSTICK_RIGHT          PIN_BUTTON5
+#define JOYSTICK_PRESS          PIN_BUTTON6
+#define PIN_USER_BTN            PIN_BUTTON6
+
+
+// Analog pins
+#define  PIN_VBAT_READ          (5)
+#define  ADC_MULTIPLIER         (3 * 1.75 * 1.187 * 1000)
+
+
+/*
+ * Analog pins
+ */
+#define PIN_A0 (5)	//(3)
+#define PIN_A1 (31) //(4)
+#define PIN_A2 (28)
+#define PIN_A3 (29)
+#define PIN_A4 (30)
+#define PIN_A5 (31)
+#define PIN_A6 (0xff)
+#define PIN_A7 (0xff)
+
+	static const uint8_t A0 = PIN_A0;
+	static const uint8_t A1 = PIN_A1;
+	static const uint8_t A2 = PIN_A2;
+	static const uint8_t A3 = PIN_A3;
+	static const uint8_t A4 = PIN_A4;
+	static const uint8_t A5 = PIN_A5;
+	static const uint8_t A6 = PIN_A6;
+	static const uint8_t A7 = PIN_A7;
+#define ADC_RESOLUTION 14
+
+// Power management boot protection threshold (millivolts)
+// Set to 0 to disable boot protection
+#define PWRMGT_VOLTAGE_BOOTLOCK 3300   // Won't boot below this voltage (mV)
+// LPCOMP wake configuration (voltage recovery from SYSTEMOFF)
+// AIN3 = P0.05 = PIN_A0 / PIN_VBAT_READ
+#define PWRMGT_LPCOMP_AIN 3
+#define PWRMGT_LPCOMP_REFSEL 4  // 5/8 VDD (~3.13-3.44V)
+
+// Other pins
+#define PIN_AREF (2)
+#define PIN_NFC1 (9)
+#define PIN_NFC2 (10)
+
+	static const uint8_t AREF = PIN_AREF;
+
+/*
+ * Serial interfaces
+ */
+// TXD1 RXD1 on Base Board
+#define PIN_SERIAL1_RX (15)
+#define PIN_SERIAL1_TX (16)
+
+// TXD0 RXD0 on Base Board
+#define PIN_SERIAL2_RX (19)
+#define PIN_SERIAL2_TX (20)
+
+/*
+ * SPI Interfaces
+ */
+#define SPI_INTERFACES_COUNT 1
+
+#define PIN_SPI_MISO (29)
+#define PIN_SPI_MOSI (30)
+#define PIN_SPI_SCK   (3)
+
+	static const uint8_t SS = 26;
+	static const uint8_t MOSI = PIN_SPI_MOSI;
+	static const uint8_t MISO = PIN_SPI_MISO;
+	static const uint8_t SCK = PIN_SPI_SCK;
+
+// LoRa radio module pins for RAK4631
+
+#define  SX126X_POWER_EN (37)
+#define  P_LORA_RESET    (38)
+#define  P_LORA_NSS      (42)
+#define  P_LORA_SCLK     (43)
+#define  P_LORA_MOSI     (44)
+#define  P_LORA_MISO     (45)
+#define  P_LORA_BUSY     (46)
+#define  P_LORA_DIO_1    (47)
+
+#define SX126X_DIO2_AS_RF_SWITCH  true
+#define SX126X_DIO3_TCXO_VOLTAGE   1.8
+
+/*
+ * Wire Interfaces
+ */
+#define WIRE_INTERFACES_COUNT 2
+
+#define PIN_WIRE_SDA (13)
+#define PIN_WIRE_SCL (14)
+
+#define PIN_WIRE1_SDA (24)
+#define PIN_WIRE1_SCL (25)
+
+// QSPI Pins
+// QSPI occupied by GPIO's
+#define PIN_QSPI_SCK 3	// 19
+#define PIN_QSPI_CS 26	// 17
+#define PIN_QSPI_IO0 30 // 20
+#define PIN_QSPI_IO1 29 // 21
+#define PIN_QSPI_IO2 28 // 22
+#define PIN_QSPI_IO3 2	// 23
+
+// On-board QSPI Flash
+// No onboard flash
+#define EXTERNAL_FLASH_DEVICES IS25LP080D
+#define EXTERNAL_FLASH_USE_QSPI
+
+#define GPS_ADDRESS   0x42  //i2c address for GPS
+
+
+// GPS L76KB
+#define GPS_BAUD_RATE           9600
+#define GPS_THREAD_INTERVAL     50
+#define PIN_GPS_TX              PIN_SERIAL1_RX
+#define PIN_GPS_RX              PIN_SERIAL1_TX
+#define PIN_GPS_EN              (33)
+#define PIN_GPS_PPS             (17)
+
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------
+ *        Arduino objects - C++ only
+ *----------------------------------------------------------------------------*/
+
+#endif