add new rotator grbltrk

Changes to be committed:
	modified:   Android.mk
	modified:   configure.ac
	modified:   include/hamlib/rotlist.h
	new file:   rotators/grbltrk/Android.mk
	new file:   rotators/grbltrk/Makefile.am
	new file:   rotators/grbltrk/grbltrk.c
	modified:   src/rot_reg.c
pull/1032/head
wuxx 2022-05-17 13:23:44 +08:00
rodzic 17539bb68a
commit e9fb733dae
7 zmienionych plików z 600 dodań i 1 usunięć

Wyświetl plik

@ -34,6 +34,7 @@ include $(TOP_PATH)/rotators/amsat/Android.mk
include $(TOP_PATH)/rotators/ars/Android.mk include $(TOP_PATH)/rotators/ars/Android.mk
include $(TOP_PATH)/rotators/celestron/Android.mk include $(TOP_PATH)/rotators/celestron/Android.mk
include $(TOP_PATH)/rotators/cnctrk/Android.mk include $(TOP_PATH)/rotators/cnctrk/Android.mk
include $(TOP_PATH)/rotators/grbltrk/Android.mk
include $(TOP_PATH)/rotators/easycomm/Android.mk include $(TOP_PATH)/rotators/easycomm/Android.mk
include $(TOP_PATH)/rotators/ether6/Android.mk include $(TOP_PATH)/rotators/ether6/Android.mk
include $(TOP_PATH)/rotators/fodtrack/Android.mk include $(TOP_PATH)/rotators/fodtrack/Android.mk

Wyświetl plik

@ -48,7 +48,7 @@ dnl Beware of duplication should a backend directory include both rig and
dnl rotor definitions, e.g. "dummy". Optional backends will not be listed dnl rotor definitions, e.g. "dummy". Optional backends will not be listed
dnl here but will be added later, e.g. "winradio". dnl here but will be added later, e.g. "winradio".
RIG_BACKEND_LIST="rigs/adat rigs/alinco rigs/aor rigs/barrett rigs/codan rigs/dorji rigs/drake rigs/dummy rigs/elad rigs/flexradio rigs/icom rigs/icmarine rigs/jrc rigs/kachina rigs/kenwood rigs/kit rigs/lowe rigs/pcr rigs/prm80 rigs/racal rigs/rft rigs/rs rigs/skanti rigs/tapr rigs/tentec rigs/tuner rigs/uniden rigs/winradio rigs/wj rigs/yaesu rigs/gomspace" RIG_BACKEND_LIST="rigs/adat rigs/alinco rigs/aor rigs/barrett rigs/codan rigs/dorji rigs/drake rigs/dummy rigs/elad rigs/flexradio rigs/icom rigs/icmarine rigs/jrc rigs/kachina rigs/kenwood rigs/kit rigs/lowe rigs/pcr rigs/prm80 rigs/racal rigs/rft rigs/rs rigs/skanti rigs/tapr rigs/tentec rigs/tuner rigs/uniden rigs/winradio rigs/wj rigs/yaesu rigs/gomspace"
ROT_BACKEND_LIST="rotators/amsat rotators/ars rotators/celestron rotators/cnctrk rotators/easycomm rotators/ether6 rotators/fodtrack rotators/gs232a rotators/heathkit rotators/m2 rotators/meade rotators/rotorez rotators/sartek rotators/spid rotators/ts7400 rotators/prosistel rotators/ioptron rotators/satel rotators/radant" ROT_BACKEND_LIST="rotators/amsat rotators/ars rotators/celestron rotators/cnctrk rotators/grbltrk rotators/easycomm rotators/ether6 rotators/fodtrack rotators/gs232a rotators/heathkit rotators/m2 rotators/meade rotators/rotorez rotators/sartek rotators/spid rotators/ts7400 rotators/prosistel rotators/ioptron rotators/satel rotators/radant"
# Amplifiers are all in the amplifiers directory # Amplifiers are all in the amplifiers directory
AMP_BACKEND_LIST="amplifiers/elecraft" AMP_BACKEND_LIST="amplifiers/elecraft"
@ -831,6 +831,7 @@ rotators/amsat/Makefile
rotators/ars/Makefile rotators/ars/Makefile
rotators/celestron/Makefile rotators/celestron/Makefile
rotators/cnctrk/Makefile rotators/cnctrk/Makefile
rotators/grbltrk/Makefile
rotators/easycomm/Makefile rotators/easycomm/Makefile
rotators/ether6/Makefile rotators/ether6/Makefile
rotators/fodtrack/Makefile rotators/fodtrack/Makefile

Wyświetl plik

@ -623,6 +623,20 @@
#define ROT_BACKEND_ANDROIDSENSOR "androidsensor" #define ROT_BACKEND_ANDROIDSENSOR "androidsensor"
#define ROT_MODEL_ANDROIDSENSOR ROT_MAKE_MODEL(ROT_ANDROIDSENSOR, 1) #define ROT_MODEL_ANDROIDSENSOR ROT_MAKE_MODEL(ROT_ANDROIDSENSOR, 1)
/**
* \brief A macro that returns the model number of the GRBLTRK backend.
*
* \def ROT_MODEL_GRBLTRK
*
* The GRBLTRK backend can be used with rotators that support the GRBL
* protocol.
*/
//! @cond Doxygen_Suppress
#define ROT_GRBLTRK 24
#define ROT_BACKEND_GRBLTRK "grbltrk"
//! @endcond
#define ROT_MODEL_GRBLTRK_SER ROT_MAKE_MODEL(ROT_GRBLTRK, 1)
#define ROT_MODEL_GRBLTRK_NET ROT_MAKE_MODEL(ROT_GRBLTRK, 2)
/** /**
* \brief Convenience type definition for a rotator model. * \brief Convenience type definition for a rotator model.

Wyświetl plik

@ -0,0 +1,12 @@
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := grbltrk.c
LOCAL_MODULE := grbltrk
LOCAL_CFLAGS := -DHAVE_CONFIG_H
LOCAL_C_INCLUDES := android include src
LOCAL_LDLIBS := -lhamlib -Lobj/local/armeabi
include $(BUILD_STATIC_LIBRARY)

Wyświetl plik

@ -0,0 +1,5 @@
noinst_LTLIBRARIES = libhamlib-grbltrk.la
libhamlib_grbltrk_la_SOURCES = grbltrk.c
EXTRA_DIST = Android.mk

Wyświetl plik

@ -0,0 +1,564 @@
/*
* Hamlib Rotator backend - LinuxCNC no hardware port
* Copyright (c) 2015 by Robert Freeman
* Adapted from AMSAT code by Stephane Fillod
*
* 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 Street, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <math.h>
#include <stdlib.h>
#include <string.h> /* String function definitions */
#include <unistd.h> /* UNIX standard function definitions */
#ifdef HAVE_SYS_IOCTL_H
#include <sys/ioctl.h>
#endif
#include "hamlib/rotator.h"
#include "hamlib/rig.h"
#include "misc.h"
#include "serial.h"
#include "token.h"
#include "network.h"
#include "register.h"
#define RSIZE (1024)
#define XDEGREE2MM(d) ((d)/9.0)
// 42-gear-22
#define YDEGREE2MM(d) ((d)/9.0)
//#define YDEGREE2MM(d) ((d) * ((1710) / (77*9)))
//#define YDEGREE2MM(d) ((d) * ((190) / (77)))
/*
$0=10 (step pulse, usec)
$1=25 (step idle delay, msec)
$2=0 (step port invert mask:00000000)
$3=0 (dir port invert mask:00000000)
$4=0 (step enable invert, bool)
$5=0 (limit pins invert, bool)
$6=0 (probe pin invert, bool)
$10=3 (status report mask:00000011)
$11=0.010 (junction deviation, mm)
$12=0.002 (arc tolerance, mm)
$13=0 (report inches, bool)
$20=0 (soft limits, bool)
$21=0 (hard limits, bool)
$22=0 (homing cycle, bool)
$23=0 (homing dir invert mask:00000000)
$24=25.000 (homing feed, mm/min)
$25=500.000 (homing seek, mm/min)
$26=250 (homing debounce, msec)
$27=1.000 (homing pull-off, mm)
$30=1000. (rpm max)
$31=0. (rpm min)
$32=0 (motor lock bool)
$33=7 (motor mode mask:00000111)
$100=80.000 (x, step/mm)
$101=80.000 (y, step/mm)
$102=80.000 (z, step/mm)
$110=10000.000 (x max rate, mm/min)
$111=10000.000 (y max rate, mm/min)
$112=10000.000 (z max rate, mm/min)
$120=250.000 (x accel, mm/sec^2)
$121=250.000 (y accel, mm/sec^2)
$122=250.000 (z accel, mm/sec^2)
$130=500.000 (x max travel, mm)
$131=500.000 (y max travel, mm)
$132=500.000 (z max travel, mm)
*/
char *grbl_get_config = "$$\r\n";
char *grbl_get_pos = "?\r\n";
char *grbl_init_list[] =
{
"$1=255\r\n", /* lock motors */
"$3=3\r\n", /* invert X and Y direction */
//"$100=80\r\n", /* axis-x a4988 16 microstep */
"$100=1776\r\n", /* axis-x a4988 16 microstep 42-gear-motor-22-(1710/77) (80*1710)/77 */
//"$101=160\n", /* axis-y drv8825 32 microstep */
//"$101=80\n", /* axis-y a4988 16 microstep */
"$101=1776\r\n", /* axis-y a4988 16 microstep 42-gear-motor-22-(1710/77) (80*1710)/77 */
"$110=50\r\n",
"$111=50\r\n",
"$120=25\r\n",
"$121=25\r\n",
"G90\r\n",
"G0 X0 Y0\r\n",
};
static int
grbl_request(ROT *rot, char *request, uint32_t req_size, char *response, uint32_t *resp_size)
{
int retval;
static int fail_count = 0;
rot_debug(RIG_DEBUG_ERR, "req: [%s][%d]\n", request, fail_count);
if (rot->caps->rot_model == ROT_MODEL_GRBLTRK_SER
|| rot->caps->rot_model == ROT_MODEL_GRBLTRK_NET) {
//fprintf(stderr, "ctrl by serial/network\n");
if ((retval = write_block(&rot->state.rotport, (unsigned char *)request, req_size)) != RIG_OK) {
rot_debug(RIG_DEBUG_ERR, "%s write_block fail!\n", __func__);
//exit(-1);
fail_count++;
//return RIG_EIO;
} else {
fail_count = 0;
}
rig_flush(&rot->state.rotport);
usleep(300000);
if ((retval = read_string(&rot->state.rotport, (unsigned char *)response, 1024, "\n", 1, 0, 1)) < 0) {
rot_debug(RIG_DEBUG_ERR, "%s read_string fail! (%d) \n", __func__, retval);
//exit(-1);
fail_count++;
//return RIG_EIO;
} else {
fail_count = 0;
}
if (fail_count >= 10) {
rot_debug(RIG_DEBUG_ERR, "%s too much xfer fail! exit\n", __func__);
exit(-1);
}
rig_flush(&rot->state.rotport);
rot_debug(RIG_DEBUG_ERR, "rsp: [%s]\n", response);
//fprintf(stderr, "rsp: [%s]\n", response);
*resp_size = retval;
}
return RIG_OK;
}
static int
grbl_init(ROT *rot)
{
int i, retval;
uint32_t init_count;
char rsp[RSIZE];
uint32_t resp_size;
/* get total config */
grbl_request(rot, grbl_get_config, strlen(grbl_get_config), rsp, &resp_size);
if (strstr(rsp, grbl_init_list[0]) != NULL) {
rot_debug(RIG_DEBUG_ERR, "%s: grbl already configured\n", __func__);
return RIG_OK;
}
init_count = sizeof(grbl_init_list) / sizeof(grbl_init_list[0]);
for(i = 0; i < init_count; i++) {
rot_debug(RIG_DEBUG_ERR, "grbl_request [%s] ", grbl_init_list[i]);
retval = grbl_request(rot, grbl_init_list[i], strlen(grbl_init_list[i]), rsp, &resp_size);
//fprintf(stderr, "done\n");
if (retval != RIG_OK) {
rot_debug(RIG_DEBUG_ERR, "grbl_request [%s] fail\n", grbl_init_list[i]);
return RIG_EIO;
}
}
return RIG_OK;
}
static int
grbltrk_rot_set_position(ROT *rot, azimuth_t curr_az, elevation_t curr_el)
{
int i;
int retval;
static float prev_az, prev_el;
static float prev_x, curr_x;
float x[3], delta[3];
float y;
char req[RSIZE] = {0};
char rsp[RSIZE] = {0};
uint32_t rsp_size;
float min_value;
int min_index;
/* az:x: 0 - 360 */
/* el:y: 0 - 90 */
rot_debug(RIG_DEBUG_ERR,
"%s: (prev_x) = (%.3f); (prev_az) = (%.3f); (prev_el) = (%.3f); (curr_az, curr_el) = (%.3f, %.3f)\n", __func__,
prev_x, prev_az, prev_el, curr_az, curr_el);
/* convert degree to mm, 360 degree = 40mm, 1 degree = 0.111mm */
//x = az * 0.111;
//y = el * 0.111;
/* 360 -> 0 */
if ((prev_az > 270 && prev_az < 360) &&
(curr_az > 0 && curr_az < 90 )) {
rot_debug(RIG_DEBUG_ERR, "%s:%d\n", __func__, __LINE__);
if (prev_x >= XDEGREE2MM(270)) {
curr_x = XDEGREE2MM(curr_az) + XDEGREE2MM(360);
} else {
curr_x = XDEGREE2MM(curr_az);
}
/* 0 -> 360 */
} else if ((prev_az > 0 && prev_az < 90 ) &&
(curr_az > 270 && curr_az < 360)) {
rot_debug(RIG_DEBUG_ERR, "%s:%d\n", __func__, __LINE__);
if (prev_x >= XDEGREE2MM(360)) {
curr_x = XDEGREE2MM(curr_az);
} else {
curr_x = XDEGREE2MM(curr_az) - XDEGREE2MM(360);
}
/* reset */
} else if (curr_az == 0 && curr_el == 0) {
rot_debug(RIG_DEBUG_ERR, "%s: reset\n", __func__);
curr_x = 0;
} else {
rot_debug(RIG_DEBUG_ERR, "%s:%d prev_x: %.3f\n", __func__, __LINE__, prev_x);
x[0] = XDEGREE2MM(curr_az) - XDEGREE2MM(360);
x[1] = XDEGREE2MM(curr_az);
x[2] = XDEGREE2MM(curr_az) + XDEGREE2MM(360);
delta[0] = prev_x - x[0];
delta[1] = prev_x - x[1];
delta[2] = prev_x - x[2];
if (delta[0] < 0) { delta[0] = -1 * delta[0]; }
if (delta[1] < 0) { delta[1] = -1 * delta[1]; }
if (delta[2] < 0) { delta[2] = -1 * delta[2]; }
min_value = delta[0];
min_index = 0;
for(i = 0; i < 3; i++) {
if (delta[i] <= min_value) {
min_value = delta[i];
min_index = i;
}
}
curr_x = x[min_index];
rot_debug(RIG_DEBUG_ERR, "min_index: %d; curr_x: %.3f\n", min_index, curr_x);
}
y = YDEGREE2MM(curr_el);
/**/
snprintf(req, sizeof(req), "G0 X%.3f Y%.3f\n", curr_x, y);
retval = grbl_request(rot, req, strlen(req), rsp, &rsp_size);
if (retval != RIG_OK)
{
return retval;
}
prev_az = curr_az;
prev_el = curr_el;
prev_x = curr_x;
return RIG_OK;
}
static int
grbltrk_rot_get_position(ROT *rot, azimuth_t *az, elevation_t *el)
{
//static char req[RSIZE];
static char rsp[RSIZE];
uint32_t rsp_size;
float mpos[3];
char dummy0[256];
char dummy1[256];
int retval;
int i;
rot_debug(RIG_DEBUG_ERR, "%s called\n", __func__);
//snprintf(req, sizeof(req), "?\r\n");
for(i = 0; i < 5; i++) {
retval = grbl_request(rot, grbl_get_pos, strlen(grbl_get_pos), rsp, &rsp_size);
/*FIXME: X Y safe check */
if (retval != RIG_OK)
{
return retval;
}
if (strstr(rsp, "MPos") == NULL) {
rot_debug(RIG_DEBUG_ERR, "%s no MPos found, continue\n", __func__);
continue;
}
/* grbl 0.9 mega328p */
/* <Idle,MPos:0.000,0.000,0.000,WPos:0.000,0.000,0.000,SC:0> */
//sscanf(rsp, "%[^','],MPos:%f,%f,%f,WPos:%f,%f,%f,%s", &dummy[0], &mpos[0], &mpos[1], &mpos[2], &wpos[0], &wpos[1], &wpos[2], &dummy[1]);
/* grbl 1.3a esp32 */
//<Idle|MPos:0.000,0.000,0.000|FS:0,0|Pn:P|WCO:5.000,0.000,0.000>
sscanf(rsp, "%[^'|']|MPos:%f,%f,%s", dummy0, &mpos[0], &mpos[1], dummy1);
//rot_debug(RIG_DEBUG_ERR, "%s: (%.3f, %.3f) (%.3f, %.3f)\n", __func__, mpos[0], mpos[1], wpos[0], wpos[1]);
//*az = (azimuth_t) mpos[0] / 0.111;
//*el = (elevation_t) mpos[1] / 0.111;
*az = (azimuth_t) mpos[0] * 9;
*el = (elevation_t) mpos[1] * 9;
if ((*az) < 0) {
(*az) = (*az) + 360;
}
//rot_debug(RIG_DEBUG_ERR, "%s: (az, el) = (%.3f, %.3f)\n", __func__, *az, *el);
rot_debug(RIG_DEBUG_ERR, "%s: (az, el) = (%.3f, %.3f)\n", __func__, *az, *el);
return RIG_OK;
}
*az = (azimuth_t) 0;
*el = (elevation_t) 0;
return RIG_OK;
}
static int
grbltrk_rot_set_conf(ROT *rot, token_t token, const char *val)
{
int i, retval;
char req[RSIZE] = {0};
char rsp[RSIZE];
uint32_t resp_size, len;
rot_debug(RIG_DEBUG_ERR, "token: %ld; value: [%s]\n", token, val);
len = strlen(val);
if ((len != 0) && (val[0] == 'G')) {
for(i = 0; i < len; i++) {
if (val[i] == '@') {
req[i] = ' ';
} else {
req[i] = val[i];
}
}
req[i] = '\n';
len = strlen(req);
rot_debug(RIG_DEBUG_ERR, "send gcode [%s]\n", req);
retval = grbl_request(rot, req, len, rsp, &resp_size);
if (retval < 0) {
rot_debug(RIG_DEBUG_ERR, "grbl_request [%s] fail\n", val);
return RIG_EIO;
}
}
return RIG_OK;
}
static int
grbltrk_rot_init(ROT *rot)
{
int r = RIG_OK;
rot_debug(RIG_DEBUG_ERR, "%s:%d rot->caps->rot_model: %d\n", __func__, __LINE__, rot->caps->rot_model);
return r;
}
static int
grbl_net_open(ROT *rot, int port)
{
//network_open(&rot->state.rotport, port);
//rot_debug(RIG_DEBUG_ERR, "%s:%d network_fd: %d\n", __func__, __LINE__, (&rot->state.rotport)->fd);
rot_debug(RIG_DEBUG_ERR, "%s:%d \n", __func__, __LINE__);
return 0;
}
static int
grbltrk_rot_open(ROT *rot)
{
int r = RIG_OK;
char host[128] = {0};
//char ip[32];
//int port;
//rot_debug(RIG_DEBUG_ERR, "%s:%d rot->caps->rot_model: %d\n", __func__, __LINE__, rot->caps->rot_model);
if (rot->caps->rot_model == ROT_MODEL_GRBLTRK_SER) {
rot_debug(RIG_DEBUG_ERR, "%s:%d ctrl via serial\n", __func__, __LINE__);
} else if (rot->caps->rot_model == ROT_MODEL_GRBLTRK_NET) {
rot_get_conf(rot, TOK_PATHNAME, host);
rot_debug(RIG_DEBUG_ERR, "%s:%d ctrl via net, host [%s]\n", __func__, __LINE__, host);
grbl_net_open(rot, 23);
#if 0
if (sscanf(host, "%[^:]:%d", ip, &port) == 2) {
grbl_net_open(rot, ip, port);
} else {
grbl_net_open(rot, NULL, 0); /* use default ip & port */
}
#endif
}
grbl_init(rot);
//rot_debug(RIG_DEBUG_ERR, "%s:%d\n", __func__, __LINE__);
return r;
}
static void
grbl_net_close(ROT *rot)
{
port_close(&rot->state.rotport, RIG_PORT_NETWORK);
}
static int
grbltrk_rot_close(ROT *rot)
{
int r = RIG_OK;
if (rot->caps->rot_model == ROT_MODEL_GRBLTRK_SER) {
rot_debug(RIG_DEBUG_ERR, "%s:%d\n", __func__, __LINE__);
} else if (rot->caps->rot_model == ROT_MODEL_GRBLTRK_NET) {
rot_debug(RIG_DEBUG_ERR, "%s:%d\n", __func__, __LINE__);
grbl_net_close(rot);
}
rot_debug(RIG_DEBUG_ERR, "%s:%d\n", __func__, __LINE__);
return r;
}
/** CNCTRK implements essentially only the set position function.
it assumes there is a LinuxCNC running with the Axis GUI */
const struct rot_caps grbltrk_serial_rot_caps =
{
ROT_MODEL(ROT_MODEL_GRBLTRK_SER),
.model_name = "GRBLTRK via Serial",
.mfg_name = "BG5DIW",
.version = "20220515.0",
.copyright = "LGPL",
.status = RIG_STATUS_BETA,
.rot_type = ROT_TYPE_OTHER,
.port_type = RIG_PORT_SERIAL,
.serial_rate_min = 9600,
.serial_rate_max = 115200,
.serial_data_bits = 8,
.serial_stop_bits = 1,
.serial_parity = RIG_PARITY_NONE,
.serial_handshake = RIG_HANDSHAKE_NONE,
.write_delay = 0,
.post_write_delay = 0,
.timeout = 400,
.retry = 0,
.min_az = 0,
.max_az = 360,
.min_el = 0,
.max_el = 90,
.rot_init = grbltrk_rot_init,
.rot_open = grbltrk_rot_open,
.set_position = grbltrk_rot_set_position,
.get_position = grbltrk_rot_get_position,
.set_conf = grbltrk_rot_set_conf,
};
const struct rot_caps grbltrk_net_rot_caps =
{
ROT_MODEL(ROT_MODEL_GRBLTRK_NET),
.model_name = "GRBLTRK via Net",
.mfg_name = "BG5DIW",
.version = "20220515.0",
.copyright = "LGPL",
.status = RIG_STATUS_BETA,
.rot_type = ROT_TYPE_OTHER,
.port_type = RIG_PORT_NETWORK, /* RIG_PORT_NONE */
//.port_type = RIG_PORT_NONE, /* RIG_PORT_NONE */
.write_delay = 0,
.post_write_delay = 0,
.timeout = 300,
.retry = 0,
//.retry = 3,
.min_az = 0,
.max_az = 360,
.min_el = 0,
.max_el = 90,
.rot_init = grbltrk_rot_init,
.rot_open = grbltrk_rot_open,
.rot_close = grbltrk_rot_close,
.set_position = grbltrk_rot_set_position,
.get_position = grbltrk_rot_get_position,
.set_conf = grbltrk_rot_set_conf,
};
/* ************************************************************************* */
DECLARE_INITROT_BACKEND(grbltrk)
{
rig_debug(RIG_DEBUG_VERBOSE, "%s: _init called\n", __func__);
//rot_debug(RIG_DEBUG_ERR, "%s: _init called\n", __func__);
rot_register(&grbltrk_serial_rot_caps);
rot_register(&grbltrk_net_rot_caps);
return RIG_OK;
}

Wyświetl plik

@ -90,6 +90,7 @@ DEFINE_INITROT_BACKEND(indi);
#if defined(ANDROID) || defined(__ANDROID__) #if defined(ANDROID) || defined(__ANDROID__)
DEFINE_INITROT_BACKEND(androidsensor); DEFINE_INITROT_BACKEND(androidsensor);
#endif #endif
DEFINE_INITROT_BACKEND(grbltrk);
//! @endcond //! @endcond
/** /**
@ -137,6 +138,7 @@ static struct
#if defined(ANDROID) || defined(__ANDROID__) #if defined(ANDROID) || defined(__ANDROID__)
{ ROT_ANDROIDSENSOR, ROT_BACKEND_ANDROIDSENSOR, ROT_FUNCNAMA(androidsensor) }, { ROT_ANDROIDSENSOR, ROT_BACKEND_ANDROIDSENSOR, ROT_FUNCNAMA(androidsensor) },
#endif #endif
{ ROT_GRBLTRK, ROT_BACKEND_GRBLTRK, ROT_FUNCNAMA(grbltrk) },
{ 0, NULL }, /* end */ { 0, NULL }, /* end */
}; };