ardupilot/libraries/AP_HAL_QURT/mainapp/mainapp.cpp

166 lines
3.9 KiB
C++

/*
main program for HAL_QURT port
*/
#include <stdio.h>
#include <stdint.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <errno.h>
#include <AP_HAL/utility/Socket.h>
#include <qurt_dsp.h>
static SocketAPM sock{true};
static bool connected;
static uint32_t last_get_storage_us;
static uint64_t start_time;
// location of virtual eeprom in Linux filesystem
#define STORAGE_DIR "/var/APM"
#define STORAGE_FILE STORAGE_DIR "/" SKETCHNAME ".stg"
extern const char *get_ipv4_broadcast(void);
// time since startup in microseconds
static uint64_t micros64()
{
struct timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts);
uint64_t ret = ts.tv_sec*1000*1000ULL + ts.tv_nsec/1000U;
if (start_time == 0) {
start_time = ret;
}
ret -= start_time;
return ret;
}
/*
send storage file to DSPs
*/
static void send_storage(void)
{
int fd = open(STORAGE_FILE, O_RDWR|O_CREAT, 0644);
if (fd == -1) {
printf("Unable to open %s", STORAGE_FILE);
exit(1);
}
uint8_t buf[16384];
memset(buf, 0, sizeof(buf));
read(fd, buf, sizeof(buf));
if (ardupilot_set_storage(buf, sizeof(buf)) != 0) {
printf("Failed to send initial storage");
exit(1);
}
close(fd);
}
/*
get updated storage file from DSPs
*/
static void get_storage(void)
{
uint8_t buf[16384];
if (ardupilot_get_storage(buf, sizeof(buf)) != 0) {
return;
}
int fd = open(STORAGE_FILE ".new", O_WRONLY|O_CREAT|O_TRUNC, 0644);
if (fd == -1) {
printf("Unable to open %s - %s\n", STORAGE_FILE ".new", strerror(errno));
}
write(fd, buf, sizeof(buf));
close(fd);
// atomic rename
if (rename(STORAGE_FILE ".new", STORAGE_FILE) != 0) {
printf("Unable to rename to %s - %s\n", STORAGE_FILE, strerror(errno));
}
}
/*
handle any incoming or outgoing UDP socket data on behalf of the DSPs
*/
static void socket_check(void)
{
static const char *bcast = nullptr;
uint8_t buf[300];
ssize_t ret = sock.recv(buf, sizeof(buf), 0);
if (ret > 0) {
uint32_t nbytes;
ardupilot_socket_input(buf, ret, &nbytes);
if (!connected) {
const char *ip;
uint16_t port;
sock.last_recv_address(ip, port);
connected = sock.connect(ip, port);
if (connected) {
printf("Connected to UDP %s:%u\n", ip, (unsigned)port);
}
sock.set_blocking(false);
}
}
uint32_t nbytes;
if (bcast == nullptr) {
bcast = get_ipv4_broadcast();
if (bcast == nullptr) {
bcast = "255.255.255.255";
}
printf("Broadcasting to %s\n", bcast);
}
if (ardupilot_socket_check(buf, sizeof(buf), &nbytes) == 0) {
if (!connected) {
sock.sendto(buf, nbytes, bcast, 14550);
} else {
sock.send(buf, nbytes);
}
}
}
/*
encode argv/argv as a sequence separated by \n
*/
static char *encode_argv(int argc, const char *argv[])
{
uint32_t len = 0;
for (int i=0; i<argc; i++) {
len += strlen(argv[i]) + 1;
}
char *ret = (char *)malloc(len+1);
char *p = ret;
for (int i=0; i<argc; i++) {
size_t slen = strlen(argv[i]);
strcpy(p, argv[i]);
p[slen] = '\n';
p += slen + 1;
}
*p = 0;
return ret;
}
/*
main program
*/
int main(int argc, const char *argv[])
{
sock.set_broadcast();
printf("Starting DSP code\n");
send_storage();
char *cmdline = encode_argv(argc, argv);
ardupilot_start(cmdline, strlen(cmdline));
free(cmdline);
while (true) {
uint64_t now = micros64();
if (now - last_get_storage_us > 1000*1000) {
printf("tick t=%.6f\n", now*1.0e-6f);
ardupilot_heartbeat();
get_storage();
last_get_storage_us = now;
}
socket_check();
usleep(5000);
}
}