You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
165 lines
3.9 KiB
165 lines
3.9 KiB
/* |
|
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); |
|
} |
|
}
|
|
|