From efdfa2b8b4aa5ef6fb81a237cf8a79276bb4e382 Mon Sep 17 00:00:00 2001 From: Simon Wilks Date: Wed, 14 Nov 2012 00:33:26 +0100 Subject: [PATCH 01/19] Setup skeleton code (basic daemon). --- apps/hott_telemetry/Makefile | 42 +++++++ apps/hott_telemetry/hott_telemetry_main.c | 140 ++++++++++++++++++++++ nuttx/configs/px4fmu/nsh/appconfig | 1 + 3 files changed, 183 insertions(+) create mode 100644 apps/hott_telemetry/Makefile create mode 100644 apps/hott_telemetry/hott_telemetry_main.c diff --git a/apps/hott_telemetry/Makefile b/apps/hott_telemetry/Makefile new file mode 100644 index 0000000000..06336d4511 --- /dev/null +++ b/apps/hott_telemetry/Makefile @@ -0,0 +1,42 @@ +############################################################################ +# +# Copyright (C) 2012 PX4 Development Team. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name PX4 nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +# +# Basic example application +# + +APPNAME = hott_telemetry +PRIORITY = SCHED_PRIORITY_DEFAULT +STACKSIZE = 2048 + +include $(APPDIR)/mk/app.mk diff --git a/apps/hott_telemetry/hott_telemetry_main.c b/apps/hott_telemetry/hott_telemetry_main.c new file mode 100644 index 0000000000..0350c29df9 --- /dev/null +++ b/apps/hott_telemetry/hott_telemetry_main.c @@ -0,0 +1,140 @@ +/**************************************************************************** + * + * Copyright (C) 2012 PX4 Development Team. All rights reserved. + * Author: @author Simon Wilks + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/** + * @file hott_telemetry_main.c + * + * Graupner HoTT Telemetry implementation. + */ + +#include +#include +#include + +#include + +static bool thread_should_exit = false; /**< Deamon exit flag */ +static bool thread_running = false; /**< Deamon status flag */ +static int deamon_task; /**< Handle of deamon task / thread */ + +/** + * Deamon management function. + */ +__EXPORT int hott_telemetry_main(int argc, char *argv[]); + +/** + * Mainloop of deamon. + */ +int hott_telemetry_thread_main(int argc, char *argv[]); + +/** + * Print the correct usage. + */ +static void usage(const char *reason); + +static void +usage(const char *reason) +{ + if (reason) + fprintf(stderr, "%s\n", reason); + fprintf(stderr, "usage: deamon {start|stop|status} [-p ]\n\n"); + exit(1); +} + +/** + * The deamon app only briefly exists to start + * the background job. The stack size assigned in the + * Makefile does only apply to this management task. + * + * The actual stack size should be set in the call + * to task_create(). + */ +int hott_telemetry_main(int argc, char *argv[]) +{ + if (argc < 1) + usage("missing command"); + + if (!strcmp(argv[1], "start")) { + + if (thread_running) { + printf("deamon already running\n"); + /* this is not an error */ + exit(0); + } + + thread_should_exit = false; + deamon_task = task_spawn("hott_telemetry", + SCHED_DEFAULT, + SCHED_PRIORITY_DEFAULT, + 4096, + hott_telemetry_thread_main, + (argv) ? (const char **)&argv[2] : (const char **)NULL); + exit(0); + } + + if (!strcmp(argv[1], "stop")) { + thread_should_exit = true; + exit(0); + } + + if (!strcmp(argv[1], "status")) { + if (thread_running) { + printf("\thott_telemetry is running\n"); + } else { + printf("\thott_telemetry not started\n"); + } + exit(0); + } + + usage("unrecognized command"); + exit(1); +} + +int hott_telemetry_thread_main(int argc, char *argv[]) { + + printf("[hott_telemetry] starting\n"); + + thread_running = true; + + while (!thread_should_exit) { + printf("The HoTT telemetry deamon is here!\n"); + sleep(10); + } + + printf("[deamon] exiting.\n"); + + thread_running = false; + + return 0; +} diff --git a/nuttx/configs/px4fmu/nsh/appconfig b/nuttx/configs/px4fmu/nsh/appconfig index 798f57e93c..5659960831 100644 --- a/nuttx/configs/px4fmu/nsh/appconfig +++ b/nuttx/configs/px4fmu/nsh/appconfig @@ -80,6 +80,7 @@ CONFIGURED_APPS += fixedwing_att_control CONFIGURED_APPS += fixedwing_pos_control CONFIGURED_APPS += position_estimator CONFIGURED_APPS += attitude_estimator_ekf +CONFIGURED_APPS += hott_telemetry # Hacking tools #CONFIGURED_APPS += system/i2c From 46ab48ab942a1505d4916a2443c62d020a6cb67a Mon Sep 17 00:00:00 2001 From: Simon Wilks Date: Wed, 14 Nov 2012 00:36:01 +0100 Subject: [PATCH 02/19] Added a missing comment. --- apps/hott_telemetry/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/hott_telemetry/Makefile b/apps/hott_telemetry/Makefile index 06336d4511..4660f89a33 100644 --- a/apps/hott_telemetry/Makefile +++ b/apps/hott_telemetry/Makefile @@ -32,7 +32,7 @@ ############################################################################ # -# Basic example application +# Graupner HoTT Telemetry application. # APPNAME = hott_telemetry From aa7873dee1d8f5e24b5995f61f3cf922cd3621e9 Mon Sep 17 00:00:00 2001 From: Simon Wilks Date: Wed, 21 Nov 2012 00:16:43 +0100 Subject: [PATCH 03/19] Introducing an initial implementation of HoTT telemetry support. --- apps/hott_telemetry/Makefile | 2 + apps/hott_telemetry/hott_telemetry_main.c | 217 +++++++++++++++++++--- apps/hott_telemetry/messages.c | 75 ++++++++ apps/hott_telemetry/messages.h | 113 +++++++++++ 4 files changed, 386 insertions(+), 21 deletions(-) create mode 100644 apps/hott_telemetry/messages.c create mode 100644 apps/hott_telemetry/messages.h diff --git a/apps/hott_telemetry/Makefile b/apps/hott_telemetry/Makefile index 4660f89a33..528306dab0 100644 --- a/apps/hott_telemetry/Makefile +++ b/apps/hott_telemetry/Makefile @@ -35,6 +35,8 @@ # Graupner HoTT Telemetry application. # +INCLUDES = $(TOPDIR)/arch/arm/src/stm32 $(TOPDIR)/arch/arm/src/common + APPNAME = hott_telemetry PRIORITY = SCHED_PRIORITY_DEFAULT STACKSIZE = 2048 diff --git a/apps/hott_telemetry/hott_telemetry_main.c b/apps/hott_telemetry/hott_telemetry_main.c index 0350c29df9..c5932baeba 100644 --- a/apps/hott_telemetry/hott_telemetry_main.c +++ b/apps/hott_telemetry/hott_telemetry_main.c @@ -36,16 +36,31 @@ * @file hott_telemetry_main.c * * Graupner HoTT Telemetry implementation. + * + * The HoTT receiver polls each device at a regular interval at which point + * a data packet can be returned if necessary. */ +#include #include -#include +#include +#include #include - +#include +#include +#include #include -static bool thread_should_exit = false; /**< Deamon exit flag */ -static bool thread_running = false; /**< Deamon status flag */ +#include "messages.h" + +// The following are equired for UART direct manipulation. +#include +#include "up_arch.h" +#include "chip.h" +#include "stm32_internal.h" + +static int thread_should_exit = false; /**< Deamon exit flag */ +static int thread_running = false; /**< Deamon status flag */ static int deamon_task; /**< Handle of deamon task / thread */ /** @@ -58,10 +73,109 @@ __EXPORT int hott_telemetry_main(int argc, char *argv[]); */ int hott_telemetry_thread_main(int argc, char *argv[]); -/** - * Print the correct usage. - */ -static void usage(const char *reason); +static int read_data(int uart); +static int send_data(int uart, const struct eam_module_msg *msg); +static void uart_disable_rx(void); +static void uart_disable_tx(void); + +static int open_uart(const char *uart_name, struct termios *uart_config_original) +{ + /* baud rate */ + int speed = B19200; + int uart; + + /* open uart */ + uart = open(uart_name, O_RDWR | O_NOCTTY); + + if (uart < 0) { + fprintf(stderr, "[hott_telemetry] ERROR opening port: %s\n", uart_name); + return ERROR; + } + + /* Try to set baud rate */ + struct termios uart_config; + int termios_state; + + /* Back up the original uart configuration to restore it after exit */ + if ((termios_state = tcgetattr(uart, uart_config_original)) < 0) { + fprintf(stderr, "[hott_telemetry] ERROR getting baudrate / termios config for %s: %d\n", uart_name, termios_state); + close(uart); + return ERROR; + } + + /* Fill the struct for the new configuration */ + tcgetattr(uart, &uart_config); + + /* Clear ONLCR flag (which appends a CR for every LF) */ + uart_config.c_oflag &= ~ONLCR; + + /* Set baud rate */ + if (cfsetispeed(&uart_config, speed) < 0 || cfsetospeed(&uart_config, speed) < 0) { + fprintf(stderr, "[hott_telemetry] ERROR setting baudrate / termios config for %s: %d (cfsetispeed, cfsetospeed)\n", uart_name, termios_state); + close(uart); + return ERROR; + } + + if ((termios_state = tcsetattr(uart, TCSANOW, &uart_config)) < 0) { + fprintf(stderr, "[hott_telemetry] ERROR setting baudrate / termios config for %s (tcsetattr)\n", uart_name); + close(uart); + return ERROR; + } + + return uart; +} + +int hott_telemetry_thread_main(int argc, char *argv[]) +{ + printf("[hott_telemetry] starting\n"); + + thread_running = true; + + char *device = "/dev/ttyS2"; // UART5 + char *commandline_usage = "\tusage: hott_telemetry start|status|stop [-d device]\n"; + + /* read commandline arguments */ + for (int i = 0; i < argc && argv[i]; i++) { + if (strcmp(argv[i], "-d") == 0 || strcmp(argv[i], "--device") == 0) { //device set + if (argc > i + 1) { + device = argv[i + 1]; + + } else { + thread_running = false; + errx(1, "missing parameter to -m 1..4\n %s", commandline_usage); + } + } + } + + /* enable UART, writes potentially an empty buffer, but multiplexing is disabled */ + struct termios uart_config_original; + int uart = open_uart(device, &uart_config_original); + + if (uart < 0) { + fprintf(stderr, "[hott_telemetry] Failed opening HoTT UART, exiting.\n"); + thread_running = false; + exit(ERROR); + } + + messages_init(); + + struct eam_module_msg msg; + while (!thread_should_exit) { + build_eam_response(&msg); + if (read_data(uart) == OK) { + send_data(uart, &msg); + } + } + + printf("[hott_telemetry] exiting.\n"); + + /* close uarts */ + close(uart); + + thread_running = false; + + return 0; +} static void usage(const char *reason) @@ -96,8 +210,8 @@ int hott_telemetry_main(int argc, char *argv[]) thread_should_exit = false; deamon_task = task_spawn("hott_telemetry", SCHED_DEFAULT, - SCHED_PRIORITY_DEFAULT, - 4096, + SCHED_PRIORITY_MAX - 20, + 2048, hott_telemetry_thread_main, (argv) ? (const char **)&argv[2] : (const char **)NULL); exit(0); @@ -121,20 +235,81 @@ int hott_telemetry_main(int argc, char *argv[]) exit(1); } -int hott_telemetry_thread_main(int argc, char *argv[]) { +int read_data(int uart) +{ + uart_disable_tx(); - printf("[hott_telemetry] starting\n"); + const int timeout = 1000; + struct pollfd fds[] = { { .fd = uart, .events = POLLIN } }; - thread_running = true; + if (poll(fds, 1, timeout) > 0) { + // get the mode: binary or text + char mode; + read(uart, &mode, 1); + + // read the poll ID (device ID being targetted) + char id; + read(uart, &id, 1); - while (!thread_should_exit) { - printf("The HoTT telemetry deamon is here!\n"); - sleep(10); + //printf("Reading: mode='%x' id='%x'\n", mode, id); + + // if we have a binary mode request for our sensor ID let's run with it + if (mode != BINARY_MODE_REQUEST_ID || id != ELECTRIC_AIR_MODULE) { + return ERROR; // not really an error, rather uninteresting. + } + } else { + printf("Timeout\n"); + return ERROR; + } + return OK; +} + +int send_data(int uart, const struct eam_module_msg *msg) +{ + usleep(POST_READ_DELAY_IN_USECS); + + uart_disable_rx(); + + uint16_t checksum = 0; + int size = sizeof(*msg); + char buffer[size]; + + memcpy(buffer, msg, size); + + for(int i = 0; i < size; i++) { + if (i == size - 1) { + // Set the checksum: the first uint8_t is taken as the checksum. + buffer[i] = checksum & 0xff; + } else { + checksum += buffer[i]; + } + + //printf("%x ", buffer[i]); + write(uart, &buffer[i], 1); + + // Sleep before sending the next uint8_t. + usleep(POST_WRITE_DELAY_IN_USECS); } - printf("[deamon] exiting.\n"); - - thread_running = false; - - return 0; + return OK; } + +void uart_disable_rx() +{ + uint32_t cr; + cr = getreg32(STM32_UART5_CR1); + cr &= ~(USART_CR1_RE); // turn off RX + cr |= (USART_CR1_TE); // turn on TX + putreg32(cr, STM32_UART5_CR1); +} + +void uart_disable_tx() +{ + uint32_t cr; + cr = getreg32(STM32_UART5_CR1); + cr |= (USART_CR1_RE); // turn on RX + cr &= ~(USART_CR1_TE); // turn off TX + putreg32(cr, STM32_UART5_CR1); +} + + diff --git a/apps/hott_telemetry/messages.c b/apps/hott_telemetry/messages.c new file mode 100644 index 0000000000..eee78a01e8 --- /dev/null +++ b/apps/hott_telemetry/messages.c @@ -0,0 +1,75 @@ +/**************************************************************************** + * + * Copyright (C) 2012 PX4 Development Team. All rights reserved. + * Author: @author Simon Wilks + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/** + * @file messages.c + * + */ + +#include "messages.h" + +#include +#include +#include +#include + +static int sensor_sub = -1; + +void messages_init(void) +{ + sensor_sub = orb_subscribe(ORB_ID(sensor_combined)); +} + +void build_eam_response(struct eam_module_msg *msg) +{ + /* get a local copy of the current sensor values */ + struct sensor_combined_s raw; + memset(&raw, 0, sizeof(raw)); + orb_copy(ORB_ID(sensor_combined), sensor_sub, &raw); + + memset(msg, 0, sizeof(*msg)); + + msg->start = START_BYTE; + msg->eam_sensor_id = ELECTRIC_AIR_MODULE; + msg->sensor_id = EAM_SENSOR_ID; + msg->temperature1 = (uint8_t)(raw.baro_temp_celcius + 20); + msg->temperature2 = TEMP_ZERO_CELSIUS; + msg->main_voltage_L = (uint8_t)(raw.battery_voltage_v * 10); + + uint16_t alt = (uint16_t)(raw.baro_alt_meter + 500); + msg->altitude_L = (uint8_t)alt & 0xff; + msg->altitude_H = (uint8_t)(alt >> 8) & 0xff; + + msg->stop = STOP_BYTE; +} \ No newline at end of file diff --git a/apps/hott_telemetry/messages.h b/apps/hott_telemetry/messages.h new file mode 100644 index 0000000000..562010a06e --- /dev/null +++ b/apps/hott_telemetry/messages.h @@ -0,0 +1,113 @@ +/**************************************************************************** + * + * Copyright (C) 2012 PX4 Development Team. All rights reserved. + * Author: @author Simon Wilks + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/** + * @file messages.h + * + * Graupner HoTT Telemetry message generator. + * + */ +#ifndef MESSAGES_H_ +#define MESSAGES_H + +#include + +// The HoTT receiver demands a minimum 5ms period of silence after delivering its request. +#define POST_READ_DELAY_IN_USECS 4500 +// A pause of 3ms is required between each uint8_t sent back to the HoTT receiver. Much lower +// values can be used in practise though. +#define POST_WRITE_DELAY_IN_USECS 1500 + +// Protocol constants. +#define BINARY_MODE_REQUEST_ID 0x80 // Binary mode request. +#define START_BYTE 0x7c +#define STOP_BYTE 0x7d +#define TEMP_ZERO_CELSIUS 0x14 + +// Electric Air Module (EAM) constants. +#define ELECTRIC_AIR_MODULE 0x8e +#define EAM_SENSOR_ID 0xe0 + +struct eam_module_msg { + uint8_t start; /**< Start byte */ + uint8_t eam_sensor_id; /**< EAM sensor ID */ + uint8_t warning; + uint8_t sensor_id; /**< Sensor ID, why different? */ + uint8_t alarm_inverse1; + uint8_t alarm_inverse2; + uint8_t cell1_L; /**< Lipo cell voltages. Not supported. */ + uint8_t cell2_L; + uint8_t cell3_L; + uint8_t cell4_L; + uint8_t cell5_L; + uint8_t cell6_L; + uint8_t cell7_L; + uint8_t cell1_H; + uint8_t cell2_H; + uint8_t cell3_H; + uint8_t cell4_H; + uint8_t cell5_H; + uint8_t cell6_H; + uint8_t cell7_H; + uint8_t batt1_voltage_L; /**< Battery 1 voltage, lower 8-bits in steps of 0.02V */ + uint8_t batt1_voltage_H; + uint8_t batt2_voltage_L; /**< Battery 2 voltage, lower 8-bits in steps of 0.02V */ + uint8_t batt2_voltage_H; + uint8_t temperature1; /**< Temperature sensor 1. 20 = 0 degrees */ + uint8_t temperature2; + uint8_t altitude_L; /**< Attitude (meters) lower 8-bits. 500 = 0 meters */ + uint8_t altitude_H; + uint8_t current_L; /**< Current (mAh) lower 8-bits in steps of 0.1V */ + uint8_t current_H; + uint8_t main_voltage_L; /**< Main power voltage lower 8-bits in steps of 0.1V */ + uint8_t main_voltage_H; + uint8_t battery_capacity_L; /**< Used battery capacity in steps of 10mAh */ + uint8_t battery_capacity_H; + uint8_t climbrate_L; /**< Climb rate in 0.01m/s. 0m/s = 30000 */ + uint8_t climbrate_H; + uint8_t climbrate_3s; /**< Climb rate in m/3sec. 0m/3sec = 120 */ + uint8_t rpm_L; /**< RPM Lower 8-bits In steps of 10 U/min */ + uint8_t rpm_H; + uint8_t electric_min; /**< Flight time in minutes. */ + uint8_t electric_sec; /**< Flight time in seconds. */ + uint8_t speed_L; /**< Airspeed in km/h in steps of 1 km/h */ + uint8_t speed_H; + uint8_t stop; /**< Stop byte */ + uint8_t checksum; /**< Lower 8-bits of all bytes summed. */ +}; + +void messages_init(void); +void build_eam_response(struct eam_module_msg *msg); + +#endif /* MESSAGES_H_ */ From 6894c4d1bfaf5b8c43705b8b758788ebf31e17f9 Mon Sep 17 00:00:00 2001 From: Simon Wilks Date: Wed, 21 Nov 2012 00:19:45 +0100 Subject: [PATCH 04/19] Added a note on the inclusion of libraries for UART access in the Makefile. --- apps/hott_telemetry/Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/hott_telemetry/Makefile b/apps/hott_telemetry/Makefile index 528306dab0..8d5faa3b7f 100644 --- a/apps/hott_telemetry/Makefile +++ b/apps/hott_telemetry/Makefile @@ -35,6 +35,7 @@ # Graupner HoTT Telemetry application. # +# The following line is required for accessing UARTs directly. INCLUDES = $(TOPDIR)/arch/arm/src/stm32 $(TOPDIR)/arch/arm/src/common APPNAME = hott_telemetry From 054c65535f41c788a6db2accf1f920eaf3d05ff4 Mon Sep 17 00:00:00 2001 From: Simon Wilks Date: Wed, 21 Nov 2012 23:37:20 +0100 Subject: [PATCH 05/19] General code cleanup. --- apps/hott_telemetry/hott_telemetry_main.c | 271 ++++++++++++---------- apps/hott_telemetry/messages.h | 9 +- 2 files changed, 150 insertions(+), 130 deletions(-) diff --git a/apps/hott_telemetry/hott_telemetry_main.c b/apps/hott_telemetry/hott_telemetry_main.c index c5932baeba..00b8f8d665 100644 --- a/apps/hott_telemetry/hott_telemetry_main.c +++ b/apps/hott_telemetry/hott_telemetry_main.c @@ -39,6 +39,15 @@ * * The HoTT receiver polls each device at a regular interval at which point * a data packet can be returned if necessary. + * + * NOTE: Since HoTT telemetry works half-duplex over a single wire the wire + * is connected to both the UART TX and RX port. In order to send and receive + * we need to be able to disable one of these ports at a time. This level of + * control is currently not provided by Nuttx (yet) so we need to do this + * at the hardware level for now. + * + * TODO: Add support for at least the vario and GPS sensors. + * */ #include @@ -53,7 +62,7 @@ #include "messages.h" -// The following are equired for UART direct manipulation. +/* The following are equired for UART direct manipulation. */ #include #include "up_arch.h" #include "chip.h" @@ -62,7 +71,7 @@ static int thread_should_exit = false; /**< Deamon exit flag */ static int thread_running = false; /**< Deamon status flag */ static int deamon_task; /**< Handle of deamon task / thread */ - +static uint32_t uart_addr; /**< The regsitry address of the UART for direct access */ /** * Deamon management function. */ @@ -77,6 +86,7 @@ static int read_data(int uart); static int send_data(int uart, const struct eam_module_msg *msg); static void uart_disable_rx(void); static void uart_disable_tx(void); +static uint32_t get_uart_address(const char *device); static int open_uart(const char *uart_name, struct termios *uart_config_original) { @@ -125,116 +135,6 @@ static int open_uart(const char *uart_name, struct termios *uart_config_original return uart; } -int hott_telemetry_thread_main(int argc, char *argv[]) -{ - printf("[hott_telemetry] starting\n"); - - thread_running = true; - - char *device = "/dev/ttyS2"; // UART5 - char *commandline_usage = "\tusage: hott_telemetry start|status|stop [-d device]\n"; - - /* read commandline arguments */ - for (int i = 0; i < argc && argv[i]; i++) { - if (strcmp(argv[i], "-d") == 0 || strcmp(argv[i], "--device") == 0) { //device set - if (argc > i + 1) { - device = argv[i + 1]; - - } else { - thread_running = false; - errx(1, "missing parameter to -m 1..4\n %s", commandline_usage); - } - } - } - - /* enable UART, writes potentially an empty buffer, but multiplexing is disabled */ - struct termios uart_config_original; - int uart = open_uart(device, &uart_config_original); - - if (uart < 0) { - fprintf(stderr, "[hott_telemetry] Failed opening HoTT UART, exiting.\n"); - thread_running = false; - exit(ERROR); - } - - messages_init(); - - struct eam_module_msg msg; - while (!thread_should_exit) { - build_eam_response(&msg); - if (read_data(uart) == OK) { - send_data(uart, &msg); - } - } - - printf("[hott_telemetry] exiting.\n"); - - /* close uarts */ - close(uart); - - thread_running = false; - - return 0; -} - -static void -usage(const char *reason) -{ - if (reason) - fprintf(stderr, "%s\n", reason); - fprintf(stderr, "usage: deamon {start|stop|status} [-p ]\n\n"); - exit(1); -} - -/** - * The deamon app only briefly exists to start - * the background job. The stack size assigned in the - * Makefile does only apply to this management task. - * - * The actual stack size should be set in the call - * to task_create(). - */ -int hott_telemetry_main(int argc, char *argv[]) -{ - if (argc < 1) - usage("missing command"); - - if (!strcmp(argv[1], "start")) { - - if (thread_running) { - printf("deamon already running\n"); - /* this is not an error */ - exit(0); - } - - thread_should_exit = false; - deamon_task = task_spawn("hott_telemetry", - SCHED_DEFAULT, - SCHED_PRIORITY_MAX - 20, - 2048, - hott_telemetry_thread_main, - (argv) ? (const char **)&argv[2] : (const char **)NULL); - exit(0); - } - - if (!strcmp(argv[1], "stop")) { - thread_should_exit = true; - exit(0); - } - - if (!strcmp(argv[1], "status")) { - if (thread_running) { - printf("\thott_telemetry is running\n"); - } else { - printf("\thott_telemetry not started\n"); - } - exit(0); - } - - usage("unrecognized command"); - exit(1); -} - int read_data(int uart) { uart_disable_tx(); @@ -243,17 +143,15 @@ int read_data(int uart) struct pollfd fds[] = { { .fd = uart, .events = POLLIN } }; if (poll(fds, 1, timeout) > 0) { - // get the mode: binary or text + /* get the mode: binary or text */ char mode; read(uart, &mode, 1); - // read the poll ID (device ID being targetted) + /* read the poll ID (device ID being targetted) */ char id; read(uart, &id, 1); - //printf("Reading: mode='%x' id='%x'\n", mode, id); - - // if we have a binary mode request for our sensor ID let's run with it + /* if we have a binary mode request for our sensor ID let's run with it. */ if (mode != BINARY_MODE_REQUEST_ID || id != ELECTRIC_AIR_MODULE) { return ERROR; // not really an error, rather uninteresting. } @@ -278,38 +176,159 @@ int send_data(int uart, const struct eam_module_msg *msg) for(int i = 0; i < size; i++) { if (i == size - 1) { - // Set the checksum: the first uint8_t is taken as the checksum. + /* Set the checksum: the first uint8_t is taken as the checksum. */ buffer[i] = checksum & 0xff; } else { checksum += buffer[i]; } - //printf("%x ", buffer[i]); write(uart, &buffer[i], 1); - // Sleep before sending the next uint8_t. + /* Sleep before sending the next byte. */ usleep(POST_WRITE_DELAY_IN_USECS); } return OK; } -void uart_disable_rx() +void uart_disable_rx(void) { uint32_t cr; - cr = getreg32(STM32_UART5_CR1); + cr = getreg32(uart_addr); cr &= ~(USART_CR1_RE); // turn off RX cr |= (USART_CR1_TE); // turn on TX - putreg32(cr, STM32_UART5_CR1); + putreg32(cr, uart_addr); } -void uart_disable_tx() +void uart_disable_tx(void) { uint32_t cr; - cr = getreg32(STM32_UART5_CR1); + cr = getreg32(uart_addr); cr |= (USART_CR1_RE); // turn on RX cr &= ~(USART_CR1_TE); // turn off TX - putreg32(cr, STM32_UART5_CR1); + putreg32(cr, uart_addr); +} + +uint32_t get_uart_address(const char *device) +{ + /* Map the tty device number to the UART address */ + switch(device[strlen(device) - 1]) { + case '0': return STM32_USART1_CR1; + case '1': return STM32_USART2_CR1; + case '2': return STM32_UART5_CR1; + case '3': return STM32_USART6_CR1; + default: return STM32_UART5_CR1; + } +} + +int hott_telemetry_thread_main(int argc, char *argv[]) +{ + printf("[hott_telemetry] starting\n"); + + thread_running = true; + + char *commandline_usage = "\tusage: hott_telemetry start|status|stop [-d device]\n"; + char *device = "/dev/ttyS2"; /**< Default telemetry port: UART5 */ + + /* read commandline arguments */ + for (int i = 0; i < argc && argv[i]; i++) { + if (strcmp(argv[i], "-d") == 0 || strcmp(argv[i], "--device") == 0) { //device set + if (argc > i + 1) { + device = argv[i + 1]; + + } else { + thread_running = false; + errx(1, "missing parameter to -m 1..4\n %s", commandline_usage); + } + } + } + + /* enable UART, writes potentially an empty buffer, but multiplexing is disabled */ + struct termios uart_config_original; + int uart = open_uart(device, &uart_config_original); + + if (uart < 0) { + fprintf(stderr, "[hott_telemetry] Failed opening HoTT UART, exiting.\n"); + thread_running = false; + exit(ERROR); + } + + /* Since we need to enable/disable both TX and RX on the UART at the device level + * we need to know the register address of the UART we are working with. Making it + * global so it's easy to remove later when TX/RX control is provided by Nuttx. */ + uart_addr = get_uart_address(device); + + messages_init(); + + struct eam_module_msg msg; + while (!thread_should_exit) { + build_eam_response(&msg); + if (read_data(uart) == OK) { + send_data(uart, &msg); + } + } + + printf("[hott_telemetry] exiting.\n"); + + close(uart); + + thread_running = false; + + return 0; +} + +static void +usage(const char *reason) +{ + if (reason) + fprintf(stderr, "%s\n", reason); + fprintf(stderr, "usage: deamon {start|stop|status} [-p ]\n\n"); + exit(1); +} + +/** + * Process command line arguments and tart the daemon. + */ +int hott_telemetry_main(int argc, char *argv[]) +{ + if (argc < 1) + usage("missing command"); + + if (!strcmp(argv[1], "start")) { + + if (thread_running) { + printf("deamon already running\n"); + /* this is not an error */ + exit(0); + } + + thread_should_exit = false; + deamon_task = task_spawn("hott_telemetry", + SCHED_DEFAULT, + SCHED_PRIORITY_MAX - 40, + 2048, + hott_telemetry_thread_main, + (argv) ? (const char **)&argv[2] : (const char **)NULL); + exit(0); + } + + if (!strcmp(argv[1], "stop")) { + thread_should_exit = true; + exit(0); + } + + if (!strcmp(argv[1], "status")) { + if (thread_running) { + printf("\thott_telemetry is running\n"); + } else { + printf("\thott_telemetry not started\n"); + } + exit(0); + } + + usage("unrecognized command"); + exit(1); } + diff --git a/apps/hott_telemetry/messages.h b/apps/hott_telemetry/messages.h index 562010a06e..fb305cd8d2 100644 --- a/apps/hott_telemetry/messages.h +++ b/apps/hott_telemetry/messages.h @@ -43,10 +43,10 @@ #include -// The HoTT receiver demands a minimum 5ms period of silence after delivering its request. +/* The HoTT receiver demands a minimum 5ms period of silence after delivering its request. */ #define POST_READ_DELAY_IN_USECS 4500 -// A pause of 3ms is required between each uint8_t sent back to the HoTT receiver. Much lower -// values can be used in practise though. +/* A pause of 3ms is required between each uint8_t sent back to the HoTT receiver. Much lower + values can be used in practise though. */ #define POST_WRITE_DELAY_IN_USECS 1500 // Protocol constants. @@ -55,10 +55,11 @@ #define STOP_BYTE 0x7d #define TEMP_ZERO_CELSIUS 0x14 -// Electric Air Module (EAM) constants. +/* Electric Air Module (EAM) constants. */ #define ELECTRIC_AIR_MODULE 0x8e #define EAM_SENSOR_ID 0xe0 +/* The Electric Air Module message. */ struct eam_module_msg { uint8_t start; /**< Start byte */ uint8_t eam_sensor_id; /**< EAM sensor ID */ From bc27a495a0ff4e9e76e38ab606c291d678658e1d Mon Sep 17 00:00:00 2001 From: Simon Wilks Date: Thu, 22 Nov 2012 01:54:41 +0100 Subject: [PATCH 06/19] Make the reading and sending of data independant of the message type. This will allow us to cleanly support various sensor types by having a byte array interface for send_data() and read_data(). --- apps/hott_telemetry/hott_telemetry_main.c | 38 ++++++++++++----------- apps/hott_telemetry/messages.c | 29 ++++++++++------- apps/hott_telemetry/messages.h | 4 +-- 3 files changed, 40 insertions(+), 31 deletions(-) diff --git a/apps/hott_telemetry/hott_telemetry_main.c b/apps/hott_telemetry/hott_telemetry_main.c index 00b8f8d665..ba08aa3c5e 100644 --- a/apps/hott_telemetry/hott_telemetry_main.c +++ b/apps/hott_telemetry/hott_telemetry_main.c @@ -82,8 +82,8 @@ __EXPORT int hott_telemetry_main(int argc, char *argv[]); */ int hott_telemetry_thread_main(int argc, char *argv[]); -static int read_data(int uart); -static int send_data(int uart, const struct eam_module_msg *msg); +static int read_data(int uart, int *id); +static int send_data(int uart, char *buffer, int size); static void uart_disable_rx(void); static void uart_disable_tx(void); static uint32_t get_uart_address(const char *device); @@ -135,7 +135,7 @@ static int open_uart(const char *uart_name, struct termios *uart_config_original return uart; } -int read_data(int uart) +int read_data(int uart, int *id) { uart_disable_tx(); @@ -148,12 +148,11 @@ int read_data(int uart) read(uart, &mode, 1); /* read the poll ID (device ID being targetted) */ - char id; - read(uart, &id, 1); + read(uart, id, 1); - /* if we have a binary mode request for our sensor ID let's run with it. */ - if (mode != BINARY_MODE_REQUEST_ID || id != ELECTRIC_AIR_MODULE) { - return ERROR; // not really an error, rather uninteresting. + /* if we have a binary mode request */ + if (mode != BINARY_MODE_REQUEST_ID) { + return ERROR; } } else { printf("Timeout\n"); @@ -162,18 +161,13 @@ int read_data(int uart) return OK; } -int send_data(int uart, const struct eam_module_msg *msg) +int send_data(int uart, char *buffer, int size) { usleep(POST_READ_DELAY_IN_USECS); uart_disable_rx(); uint16_t checksum = 0; - int size = sizeof(*msg); - char buffer[size]; - - memcpy(buffer, msg, size); - for(int i = 0; i < size; i++) { if (i == size - 1) { /* Set the checksum: the first uint8_t is taken as the checksum. */ @@ -260,11 +254,19 @@ int hott_telemetry_thread_main(int argc, char *argv[]) messages_init(); - struct eam_module_msg msg; + char *buffer; + int size = 0; + int id = 0; while (!thread_should_exit) { - build_eam_response(&msg); - if (read_data(uart) == OK) { - send_data(uart, &msg); + if (read_data(uart, &id) == OK) { + switch(id) { + case ELECTRIC_AIR_MODULE: + build_eam_response(&buffer, &size); + break; + default: + continue; // Not a module we support. + } + send_data(uart, buffer, size); } } diff --git a/apps/hott_telemetry/messages.c b/apps/hott_telemetry/messages.c index eee78a01e8..1ce103b125 100644 --- a/apps/hott_telemetry/messages.c +++ b/apps/hott_telemetry/messages.c @@ -51,25 +51,32 @@ void messages_init(void) sensor_sub = orb_subscribe(ORB_ID(sensor_combined)); } -void build_eam_response(struct eam_module_msg *msg) +void build_eam_response(char **buffer, int *size) { /* get a local copy of the current sensor values */ struct sensor_combined_s raw; memset(&raw, 0, sizeof(raw)); orb_copy(ORB_ID(sensor_combined), sensor_sub, &raw); - memset(msg, 0, sizeof(*msg)); + struct eam_module_msg msg; + *size = sizeof(msg); + memset(&msg, 0, *size); - msg->start = START_BYTE; - msg->eam_sensor_id = ELECTRIC_AIR_MODULE; - msg->sensor_id = EAM_SENSOR_ID; - msg->temperature1 = (uint8_t)(raw.baro_temp_celcius + 20); - msg->temperature2 = TEMP_ZERO_CELSIUS; - msg->main_voltage_L = (uint8_t)(raw.battery_voltage_v * 10); + msg.start = START_BYTE; + msg.eam_sensor_id = ELECTRIC_AIR_MODULE; + msg.sensor_id = EAM_SENSOR_ID; + msg.temperature1 = (uint8_t)(raw.baro_temp_celcius + 20); + msg.temperature2 = TEMP_ZERO_CELSIUS; + msg.main_voltage_L = (uint8_t)(raw.battery_voltage_v * 10); uint16_t alt = (uint16_t)(raw.baro_alt_meter + 500); - msg->altitude_L = (uint8_t)alt & 0xff; - msg->altitude_H = (uint8_t)(alt >> 8) & 0xff; + msg.altitude_L = (uint8_t)alt & 0xff; + msg.altitude_H = (uint8_t)(alt >> 8) & 0xff; - msg->stop = STOP_BYTE; + msg.stop = STOP_BYTE; + + //*chunk = malloc( sizeof(char) * length); + //char tmp_buffer[*size]; + *buffer = malloc(sizeof(char) * *size); + memcpy(*buffer, &msg, *size); } \ No newline at end of file diff --git a/apps/hott_telemetry/messages.h b/apps/hott_telemetry/messages.h index fb305cd8d2..51217a23b9 100644 --- a/apps/hott_telemetry/messages.h +++ b/apps/hott_telemetry/messages.h @@ -35,7 +35,7 @@ /** * @file messages.h * - * Graupner HoTT Telemetry message generator. + * Graupner HoTT Telemetry message generation. * */ #ifndef MESSAGES_H_ @@ -109,6 +109,6 @@ struct eam_module_msg { }; void messages_init(void); -void build_eam_response(struct eam_module_msg *msg); +void build_eam_response(char **buffer, int *size); #endif /* MESSAGES_H_ */ From ae906dee980c0090135cb6928f9fed04003f5e76 Mon Sep 17 00:00:00 2001 From: Simon Wilks Date: Thu, 22 Nov 2012 02:03:50 +0100 Subject: [PATCH 07/19] Shorten the post read delay slightly. --- apps/hott_telemetry/messages.h | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/apps/hott_telemetry/messages.h b/apps/hott_telemetry/messages.h index 51217a23b9..74418fd013 100644 --- a/apps/hott_telemetry/messages.h +++ b/apps/hott_telemetry/messages.h @@ -43,8 +43,11 @@ #include -/* The HoTT receiver demands a minimum 5ms period of silence after delivering its request. */ -#define POST_READ_DELAY_IN_USECS 4500 +/* The HoTT receiver demands a minimum 5ms period of silence after delivering its request. + * Note that the value specified here is lower than 5000 (5ms) as time is lost constucting + * the message after the read which takes some milliseconds. + */ +#define POST_READ_DELAY_IN_USECS 4000 /* A pause of 3ms is required between each uint8_t sent back to the HoTT receiver. Much lower values can be used in practise though. */ #define POST_WRITE_DELAY_IN_USECS 1500 From c296ffb7083678b6760aca9f179067830669af1e Mon Sep 17 00:00:00 2001 From: Simon Wilks Date: Thu, 22 Nov 2012 11:46:23 +0100 Subject: [PATCH 08/19] Tried cleaning up console messaging a bit. --- apps/hott_telemetry/hott_telemetry_main.c | 68 ++++++++++++----------- 1 file changed, 37 insertions(+), 31 deletions(-) diff --git a/apps/hott_telemetry/hott_telemetry_main.c b/apps/hott_telemetry/hott_telemetry_main.c index ba08aa3c5e..25830f20f2 100644 --- a/apps/hott_telemetry/hott_telemetry_main.c +++ b/apps/hott_telemetry/hott_telemetry_main.c @@ -46,7 +46,7 @@ * control is currently not provided by Nuttx (yet) so we need to do this * at the hardware level for now. * - * TODO: Add support for at least the vario and GPS sensors. + * TODO: Add support for at least the vario and GPS sensor data. * */ @@ -72,6 +72,13 @@ static int thread_should_exit = false; /**< Deamon exit flag */ static int thread_running = false; /**< Deamon status flag */ static int deamon_task; /**< Handle of deamon task / thread */ static uint32_t uart_addr; /**< The regsitry address of the UART for direct access */ +static char *daemon_name = "hott_telemetry"; +static char *commandline_usage = "usage: hott_telemetry start|status|stop [-d ]"; + +/* A little console messaging experiment - console helper macro */ +#define FATAL_MSG(_msg) fprintf(stderr, "[%s] %s\n", daemon_name, _msg); exit(1); +#define ERROR_MSG(_msg) fprintf(stderr, "[%s] %s\n", daemon_name, _msg); +#define INFO_MSG(_msg) printf("[%s] %s\n", daemon_name, _msg); /** * Deamon management function. */ @@ -98,8 +105,9 @@ static int open_uart(const char *uart_name, struct termios *uart_config_original uart = open(uart_name, O_RDWR | O_NOCTTY); if (uart < 0) { - fprintf(stderr, "[hott_telemetry] ERROR opening port: %s\n", uart_name); - return ERROR; + char msg[80]; + sprintf(msg, "Error opening port: %s\n", uart_name); + FATAL_MSG(msg); } /* Try to set baud rate */ @@ -108,9 +116,10 @@ static int open_uart(const char *uart_name, struct termios *uart_config_original /* Back up the original uart configuration to restore it after exit */ if ((termios_state = tcgetattr(uart, uart_config_original)) < 0) { - fprintf(stderr, "[hott_telemetry] ERROR getting baudrate / termios config for %s: %d\n", uart_name, termios_state); + char msg[80]; + sprintf(msg, "Error getting baudrate / termios config for %s: %d\n", uart_name, termios_state); close(uart); - return ERROR; + FATAL_MSG(msg); } /* Fill the struct for the new configuration */ @@ -121,15 +130,17 @@ static int open_uart(const char *uart_name, struct termios *uart_config_original /* Set baud rate */ if (cfsetispeed(&uart_config, speed) < 0 || cfsetospeed(&uart_config, speed) < 0) { - fprintf(stderr, "[hott_telemetry] ERROR setting baudrate / termios config for %s: %d (cfsetispeed, cfsetospeed)\n", uart_name, termios_state); + char msg[80]; + sprintf(msg, "Error setting baudrate / termios config for %s: %d (cfsetispeed, cfsetospeed)\n", uart_name, termios_state); close(uart); - return ERROR; + FATAL_MSG(msg); } if ((termios_state = tcsetattr(uart, TCSANOW, &uart_config)) < 0) { - fprintf(stderr, "[hott_telemetry] ERROR setting baudrate / termios config for %s (tcsetattr)\n", uart_name); + char msg[80]; + sprintf(msg, "Error setting baudrate / termios config for %s (tcsetattr)\n", uart_name); close(uart); - return ERROR; + FATAL_MSG(msg); } return uart; @@ -155,7 +166,7 @@ int read_data(int uart, int *id) return ERROR; } } else { - printf("Timeout\n"); + ERROR_MSG("UART timeout on TX/RX port"); return ERROR; } return OK; @@ -217,11 +228,10 @@ uint32_t get_uart_address(const char *device) int hott_telemetry_thread_main(int argc, char *argv[]) { - printf("[hott_telemetry] starting\n"); + INFO_MSG("starting"); thread_running = true; - char *commandline_usage = "\tusage: hott_telemetry start|status|stop [-d device]\n"; char *device = "/dev/ttyS2"; /**< Default telemetry port: UART5 */ /* read commandline arguments */ @@ -232,7 +242,9 @@ int hott_telemetry_thread_main(int argc, char *argv[]) } else { thread_running = false; - errx(1, "missing parameter to -m 1..4\n %s", commandline_usage); + ERROR_MSG("missing parameter to -d"); + ERROR_MSG(commandline_usage); + exit(1); } } } @@ -242,7 +254,7 @@ int hott_telemetry_thread_main(int argc, char *argv[]) int uart = open_uart(device, &uart_config_original); if (uart < 0) { - fprintf(stderr, "[hott_telemetry] Failed opening HoTT UART, exiting.\n"); + ERROR_MSG("Failed opening HoTT UART, exiting."); thread_running = false; exit(ERROR); } @@ -270,7 +282,7 @@ int hott_telemetry_thread_main(int argc, char *argv[]) } } - printf("[hott_telemetry] exiting.\n"); + INFO_MSG("exiting"); close(uart); @@ -279,28 +291,21 @@ int hott_telemetry_thread_main(int argc, char *argv[]) return 0; } -static void -usage(const char *reason) -{ - if (reason) - fprintf(stderr, "%s\n", reason); - fprintf(stderr, "usage: deamon {start|stop|status} [-p ]\n\n"); - exit(1); -} - /** * Process command line arguments and tart the daemon. */ int hott_telemetry_main(int argc, char *argv[]) { - if (argc < 1) - usage("missing command"); + if (argc < 1) { + ERROR_MSG("missing command"); + ERROR_MSG(commandline_usage); + exit(1); + } if (!strcmp(argv[1], "start")) { if (thread_running) { - printf("deamon already running\n"); - /* this is not an error */ + INFO_MSG("deamon already running"); exit(0); } @@ -321,14 +326,15 @@ int hott_telemetry_main(int argc, char *argv[]) if (!strcmp(argv[1], "status")) { if (thread_running) { - printf("\thott_telemetry is running\n"); + INFO_MSG("daemon is running"); } else { - printf("\thott_telemetry not started\n"); + INFO_MSG("daemon not started"); } exit(0); } - usage("unrecognized command"); + ERROR_MSG("unrecognized command"); + ERROR_MSG(commandline_usage); exit(1); } From cc7952ea94f30b62be70486f42b47bcffee7f8eb Mon Sep 17 00:00:00 2001 From: Simon Wilks Date: Thu, 22 Nov 2012 12:48:52 +0100 Subject: [PATCH 09/19] Messaging cleanup. --- apps/hott_telemetry/hott_telemetry_main.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/apps/hott_telemetry/hott_telemetry_main.c b/apps/hott_telemetry/hott_telemetry_main.c index 25830f20f2..515779cb5f 100644 --- a/apps/hott_telemetry/hott_telemetry_main.c +++ b/apps/hott_telemetry/hott_telemetry_main.c @@ -115,8 +115,8 @@ static int open_uart(const char *uart_name, struct termios *uart_config_original int termios_state; /* Back up the original uart configuration to restore it after exit */ + char msg[80]; if ((termios_state = tcgetattr(uart, uart_config_original)) < 0) { - char msg[80]; sprintf(msg, "Error getting baudrate / termios config for %s: %d\n", uart_name, termios_state); close(uart); FATAL_MSG(msg); @@ -130,14 +130,13 @@ static int open_uart(const char *uart_name, struct termios *uart_config_original /* Set baud rate */ if (cfsetispeed(&uart_config, speed) < 0 || cfsetospeed(&uart_config, speed) < 0) { - char msg[80]; - sprintf(msg, "Error setting baudrate / termios config for %s: %d (cfsetispeed, cfsetospeed)\n", uart_name, termios_state); + sprintf(msg, "Error setting baudrate / termios config for %s: %d (cfsetispeed, cfsetospeed)\n", + uart_name, termios_state); close(uart); FATAL_MSG(msg); } if ((termios_state = tcsetattr(uart, TCSANOW, &uart_config)) < 0) { - char msg[80]; sprintf(msg, "Error setting baudrate / termios config for %s (tcsetattr)\n", uart_name); close(uart); FATAL_MSG(msg); From 14d874f4a15653fce2902f016b1e75373afadd51 Mon Sep 17 00:00:00 2001 From: Simon Wilks Date: Thu, 22 Nov 2012 16:20:48 +0100 Subject: [PATCH 10/19] Fix some memory corruption bugs. --- apps/hott_telemetry/hott_telemetry_main.c | 8 ++++---- apps/hott_telemetry/messages.c | 7 ++----- apps/hott_telemetry/messages.h | 10 ++++++++-- 3 files changed, 14 insertions(+), 11 deletions(-) diff --git a/apps/hott_telemetry/hott_telemetry_main.c b/apps/hott_telemetry/hott_telemetry_main.c index 515779cb5f..98ae30dfca 100644 --- a/apps/hott_telemetry/hott_telemetry_main.c +++ b/apps/hott_telemetry/hott_telemetry_main.c @@ -90,7 +90,7 @@ __EXPORT int hott_telemetry_main(int argc, char *argv[]); int hott_telemetry_thread_main(int argc, char *argv[]); static int read_data(int uart, int *id); -static int send_data(int uart, char *buffer, int size); +static int send_data(int uart, uint8_t *buffer, int size); static void uart_disable_rx(void); static void uart_disable_tx(void); static uint32_t get_uart_address(const char *device); @@ -171,7 +171,7 @@ int read_data(int uart, int *id) return OK; } -int send_data(int uart, char *buffer, int size) +int send_data(int uart, uint8_t *buffer, int size) { usleep(POST_READ_DELAY_IN_USECS); @@ -265,14 +265,14 @@ int hott_telemetry_thread_main(int argc, char *argv[]) messages_init(); - char *buffer; + uint8_t buffer[MESSAGE_BUFFER_SIZE]; int size = 0; int id = 0; while (!thread_should_exit) { if (read_data(uart, &id) == OK) { switch(id) { case ELECTRIC_AIR_MODULE: - build_eam_response(&buffer, &size); + build_eam_response(buffer, &size); break; default: continue; // Not a module we support. diff --git a/apps/hott_telemetry/messages.c b/apps/hott_telemetry/messages.c index 1ce103b125..83cc5348c6 100644 --- a/apps/hott_telemetry/messages.c +++ b/apps/hott_telemetry/messages.c @@ -51,7 +51,7 @@ void messages_init(void) sensor_sub = orb_subscribe(ORB_ID(sensor_combined)); } -void build_eam_response(char **buffer, int *size) +void build_eam_response(uint8_t *buffer, int *size) { /* get a local copy of the current sensor values */ struct sensor_combined_s raw; @@ -75,8 +75,5 @@ void build_eam_response(char **buffer, int *size) msg.stop = STOP_BYTE; - //*chunk = malloc( sizeof(char) * length); - //char tmp_buffer[*size]; - *buffer = malloc(sizeof(char) * *size); - memcpy(*buffer, &msg, *size); + memcpy(buffer, &msg, *size); } \ No newline at end of file diff --git a/apps/hott_telemetry/messages.h b/apps/hott_telemetry/messages.h index 74418fd013..2e0699acea 100644 --- a/apps/hott_telemetry/messages.h +++ b/apps/hott_telemetry/messages.h @@ -43,13 +43,19 @@ #include +/* The buffer size used to store messages. This must be at least as big as the number of + * fields in the largest message struct. + */ +#define MESSAGE_BUFFER_SIZE 50 + /* The HoTT receiver demands a minimum 5ms period of silence after delivering its request. * Note that the value specified here is lower than 5000 (5ms) as time is lost constucting * the message after the read which takes some milliseconds. */ #define POST_READ_DELAY_IN_USECS 4000 /* A pause of 3ms is required between each uint8_t sent back to the HoTT receiver. Much lower - values can be used in practise though. */ + * values can be used in practise though. + */ #define POST_WRITE_DELAY_IN_USECS 1500 // Protocol constants. @@ -112,6 +118,6 @@ struct eam_module_msg { }; void messages_init(void); -void build_eam_response(char **buffer, int *size); +void build_eam_response(uint8_t *buffer, int *size); #endif /* MESSAGES_H_ */ From d6e54c3ce43902a96fc33e08581421884fa94de4 Mon Sep 17 00:00:00 2001 From: Simon Wilks Date: Thu, 29 Nov 2012 02:30:46 +0100 Subject: [PATCH 11/19] Trying to get single wire working. Not quite there yet. --- apps/hott_telemetry/hott_telemetry_main.c | 91 ++++++++--------------- apps/hott_telemetry/messages.h | 2 +- 2 files changed, 34 insertions(+), 59 deletions(-) diff --git a/apps/hott_telemetry/hott_telemetry_main.c b/apps/hott_telemetry/hott_telemetry_main.c index 98ae30dfca..d16f69b88f 100644 --- a/apps/hott_telemetry/hott_telemetry_main.c +++ b/apps/hott_telemetry/hott_telemetry_main.c @@ -71,10 +71,10 @@ static int thread_should_exit = false; /**< Deamon exit flag */ static int thread_running = false; /**< Deamon status flag */ static int deamon_task; /**< Handle of deamon task / thread */ -static uint32_t uart_addr; /**< The regsitry address of the UART for direct access */ static char *daemon_name = "hott_telemetry"; static char *commandline_usage = "usage: hott_telemetry start|status|stop [-d ]"; + /* A little console messaging experiment - console helper macro */ #define FATAL_MSG(_msg) fprintf(stderr, "[%s] %s\n", daemon_name, _msg); exit(1); #define ERROR_MSG(_msg) fprintf(stderr, "[%s] %s\n", daemon_name, _msg); @@ -91,22 +91,22 @@ int hott_telemetry_thread_main(int argc, char *argv[]); static int read_data(int uart, int *id); static int send_data(int uart, uint8_t *buffer, int size); -static void uart_disable_rx(void); -static void uart_disable_tx(void); -static uint32_t get_uart_address(const char *device); -static int open_uart(const char *uart_name, struct termios *uart_config_original) +static int open_uart(const char *device, struct termios *uart_config_original) { + /* Change the TX port to be open-drain */ + stm32_configgpio(GPIO_UART5_TX | GPIO_OPENDRAIN); + /* baud rate */ int speed = B19200; int uart; /* open uart */ - uart = open(uart_name, O_RDWR | O_NOCTTY); + uart = open(device, O_RDWR | O_NOCTTY); if (uart < 0) { char msg[80]; - sprintf(msg, "Error opening port: %s\n", uart_name); + sprintf(msg, "Error opening port: %s\n", device); FATAL_MSG(msg); } @@ -117,7 +117,7 @@ static int open_uart(const char *uart_name, struct termios *uart_config_original /* Back up the original uart configuration to restore it after exit */ char msg[80]; if ((termios_state = tcgetattr(uart, uart_config_original)) < 0) { - sprintf(msg, "Error getting baudrate / termios config for %s: %d\n", uart_name, termios_state); + sprintf(msg, "Error getting baudrate / termios config for %s: %d\n", device, termios_state); close(uart); FATAL_MSG(msg); } @@ -131,43 +131,48 @@ static int open_uart(const char *uart_name, struct termios *uart_config_original /* Set baud rate */ if (cfsetispeed(&uart_config, speed) < 0 || cfsetospeed(&uart_config, speed) < 0) { sprintf(msg, "Error setting baudrate / termios config for %s: %d (cfsetispeed, cfsetospeed)\n", - uart_name, termios_state); + device, termios_state); close(uart); FATAL_MSG(msg); } if ((termios_state = tcsetattr(uart, TCSANOW, &uart_config)) < 0) { - sprintf(msg, "Error setting baudrate / termios config for %s (tcsetattr)\n", uart_name); + sprintf(msg, "Error setting baudrate / termios config for %s (tcsetattr)\n", device); close(uart); FATAL_MSG(msg); } + + uint32_t cr; + cr = getreg32(STM32_UART5_CR3); + cr |= (USART_CR3_HDSEL); + //cr &= ~(USART_CR2_LINEN|USART_CR2_CLKEN|USART_CR3_SCEN|USART_CR3_IREN); + putreg32(cr, STM32_UART5_CR3); + return uart; } int read_data(int uart, int *id) { - uart_disable_tx(); - const int timeout = 1000; struct pollfd fds[] = { { .fd = uart, .events = POLLIN } }; - if (poll(fds, 1, timeout) > 0) { + //if (poll(fds, 1, timeout) > 0) { + /* get the mode: binary or text */ char mode; read(uart, &mode, 1); - - /* read the poll ID (device ID being targetted) */ + read(uart, id, 1); /* if we have a binary mode request */ if (mode != BINARY_MODE_REQUEST_ID) { return ERROR; } - } else { - ERROR_MSG("UART timeout on TX/RX port"); - return ERROR; - } + //} else { + // ERROR_MSG("UART timeout on TX/RX port"); + // return ERROR; + //} return OK; } @@ -175,8 +180,6 @@ int send_data(int uart, uint8_t *buffer, int size) { usleep(POST_READ_DELAY_IN_USECS); - uart_disable_rx(); - uint16_t checksum = 0; for(int i = 0; i < size; i++) { if (i == size - 1) { @@ -185,9 +188,12 @@ int send_data(int uart, uint8_t *buffer, int size) } else { checksum += buffer[i]; } - write(uart, &buffer[i], 1); - + + // THIS SHOULDN'T BE NECESSARY! + char dummy; + read(uart, &dummy, 1); + /* Sleep before sending the next byte. */ usleep(POST_WRITE_DELAY_IN_USECS); } @@ -195,36 +201,6 @@ int send_data(int uart, uint8_t *buffer, int size) return OK; } -void uart_disable_rx(void) -{ - uint32_t cr; - cr = getreg32(uart_addr); - cr &= ~(USART_CR1_RE); // turn off RX - cr |= (USART_CR1_TE); // turn on TX - putreg32(cr, uart_addr); -} - -void uart_disable_tx(void) -{ - uint32_t cr; - cr = getreg32(uart_addr); - cr |= (USART_CR1_RE); // turn on RX - cr &= ~(USART_CR1_TE); // turn off TX - putreg32(cr, uart_addr); -} - -uint32_t get_uart_address(const char *device) -{ - /* Map the tty device number to the UART address */ - switch(device[strlen(device) - 1]) { - case '0': return STM32_USART1_CR1; - case '1': return STM32_USART2_CR1; - case '2': return STM32_UART5_CR1; - case '3': return STM32_USART6_CR1; - default: return STM32_UART5_CR1; - } -} - int hott_telemetry_thread_main(int argc, char *argv[]) { INFO_MSG("starting"); @@ -258,11 +234,6 @@ int hott_telemetry_thread_main(int argc, char *argv[]) exit(ERROR); } - /* Since we need to enable/disable both TX and RX on the UART at the device level - * we need to know the register address of the UART we are working with. Making it - * global so it's easy to remove later when TX/RX control is provided by Nuttx. */ - uart_addr = get_uart_address(device); - messages_init(); uint8_t buffer[MESSAGE_BUFFER_SIZE]; @@ -277,7 +248,11 @@ int hott_telemetry_thread_main(int argc, char *argv[]) default: continue; // Not a module we support. } + //printf("Write start\n"); send_data(uart, buffer, size); + //printf("Write end\n"); + } else { + printf("NOK: %x\n", id); } } diff --git a/apps/hott_telemetry/messages.h b/apps/hott_telemetry/messages.h index 2e0699acea..fbb9a2d844 100644 --- a/apps/hott_telemetry/messages.h +++ b/apps/hott_telemetry/messages.h @@ -56,7 +56,7 @@ /* A pause of 3ms is required between each uint8_t sent back to the HoTT receiver. Much lower * values can be used in practise though. */ -#define POST_WRITE_DELAY_IN_USECS 1500 +#define POST_WRITE_DELAY_IN_USECS 2000 // Protocol constants. #define BINARY_MODE_REQUEST_ID 0x80 // Binary mode request. From d82c62e95bd8d37ec2a8060f096ad4188f34bc49 Mon Sep 17 00:00:00 2001 From: Simon Wilks Date: Thu, 29 Nov 2012 16:42:13 +0100 Subject: [PATCH 12/19] Single wire now working once moving away from UART5. --- apps/hott_telemetry/hott_telemetry_main.c | 65 ++++++++++++++--------- 1 file changed, 41 insertions(+), 24 deletions(-) diff --git a/apps/hott_telemetry/hott_telemetry_main.c b/apps/hott_telemetry/hott_telemetry_main.c index d16f69b88f..455d25f889 100644 --- a/apps/hott_telemetry/hott_telemetry_main.c +++ b/apps/hott_telemetry/hott_telemetry_main.c @@ -40,12 +40,6 @@ * The HoTT receiver polls each device at a regular interval at which point * a data packet can be returned if necessary. * - * NOTE: Since HoTT telemetry works half-duplex over a single wire the wire - * is connected to both the UART TX and RX port. In order to send and receive - * we need to be able to disable one of these ports at a time. This level of - * control is currently not provided by Nuttx (yet) so we need to do this - * at the hardware level for now. - * * TODO: Add support for at least the vario and GPS sensor data. * */ @@ -94,9 +88,6 @@ static int send_data(int uart, uint8_t *buffer, int size); static int open_uart(const char *device, struct termios *uart_config_original) { - /* Change the TX port to be open-drain */ - stm32_configgpio(GPIO_UART5_TX | GPIO_OPENDRAIN); - /* baud rate */ int speed = B19200; int uart; @@ -142,12 +133,37 @@ static int open_uart(const char *device, struct termios *uart_config_original) FATAL_MSG(msg); } - + /* Get the appropriate GPIO pin and control register */ + uint32_t gpio_uart; + uint32_t uart_cr3; + switch(device[strlen(device) - 1]) { + case '0': + gpio_uart = GPIO_USART1_TX; + uart_cr3 = STM32_USART1_CR3; + break; + case '1': + gpio_uart = GPIO_USART2_TX; + uart_cr3 = STM32_USART2_CR3; + break; + case '2': + sprintf(msg, "/dev/ttyS3 is not supported.\n", device); + close(uart); + FATAL_MSG(msg); + break; + case '3': + gpio_uart = GPIO_USART6_TX; + uart_cr3 = STM32_USART6_CR3; + break; + } + + /* Change the TX port to be open-drain */ + stm32_configgpio(gpio_uart | GPIO_OPENDRAIN); + + /* Turn on half-duplex mode */ uint32_t cr; - cr = getreg32(STM32_UART5_CR3); + cr = getreg32(uart_cr3); cr |= (USART_CR3_HDSEL); - //cr &= ~(USART_CR2_LINEN|USART_CR2_CLKEN|USART_CR3_SCEN|USART_CR3_IREN); - putreg32(cr, STM32_UART5_CR3); + putreg32(cr, uart_cr3); return uart; } @@ -157,7 +173,7 @@ int read_data(int uart, int *id) const int timeout = 1000; struct pollfd fds[] = { { .fd = uart, .events = POLLIN } }; - //if (poll(fds, 1, timeout) > 0) { + if (poll(fds, 1, timeout) > 0) { /* get the mode: binary or text */ char mode; @@ -165,14 +181,15 @@ int read_data(int uart, int *id) read(uart, id, 1); + //printf("[%x %x]\n", mode, *id); /* if we have a binary mode request */ if (mode != BINARY_MODE_REQUEST_ID) { return ERROR; } - //} else { - // ERROR_MSG("UART timeout on TX/RX port"); - // return ERROR; - //} + } else { + ERROR_MSG("UART timeout on TX/RX port"); + return ERROR; + } return OK; } @@ -190,14 +207,15 @@ int send_data(int uart, uint8_t *buffer, int size) } write(uart, &buffer[i], 1); - // THIS SHOULDN'T BE NECESSARY! - char dummy; - read(uart, &dummy, 1); - /* Sleep before sending the next byte. */ usleep(POST_WRITE_DELAY_IN_USECS); } + /* A hack the reads out what was written so the next read from the receiver doesn't get it. */ + /* TODO: Fix this!! */ + uint8_t dummy[size]; + read(uart, &dummy, size); + return OK; } @@ -207,7 +225,7 @@ int hott_telemetry_thread_main(int argc, char *argv[]) thread_running = true; - char *device = "/dev/ttyS2"; /**< Default telemetry port: UART5 */ + char *device = "/dev/ttyS1"; /**< Default telemetry port: USART2 */ /* read commandline arguments */ for (int i = 0; i < argc && argv[i]; i++) { @@ -250,7 +268,6 @@ int hott_telemetry_thread_main(int argc, char *argv[]) } //printf("Write start\n"); send_data(uart, buffer, size); - //printf("Write end\n"); } else { printf("NOK: %x\n", id); } From 2eccf5ff196d3c46f95cd4a5246e37d89555f5b4 Mon Sep 17 00:00:00 2001 From: Simon Wilks Date: Thu, 29 Nov 2012 16:48:52 +0100 Subject: [PATCH 13/19] Cleanup a bit. --- apps/hott_telemetry/hott_telemetry_main.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/apps/hott_telemetry/hott_telemetry_main.c b/apps/hott_telemetry/hott_telemetry_main.c index 455d25f889..ec2ca2b411 100644 --- a/apps/hott_telemetry/hott_telemetry_main.c +++ b/apps/hott_telemetry/hott_telemetry_main.c @@ -173,15 +173,13 @@ int read_data(int uart, int *id) const int timeout = 1000; struct pollfd fds[] = { { .fd = uart, .events = POLLIN } }; + char mode; if (poll(fds, 1, timeout) > 0) { - - /* get the mode: binary or text */ - char mode; + /* Get the mode: binary or text */ read(uart, &mode, 1); - + /* Read the device ID being polled */ read(uart, id, 1); - //printf("[%x %x]\n", mode, *id); /* if we have a binary mode request */ if (mode != BINARY_MODE_REQUEST_ID) { return ERROR; @@ -266,10 +264,7 @@ int hott_telemetry_thread_main(int argc, char *argv[]) default: continue; // Not a module we support. } - //printf("Write start\n"); send_data(uart, buffer, size); - } else { - printf("NOK: %x\n", id); } } From c149b26dd44ebdd84ee3fd72cda3caea893191b2 Mon Sep 17 00:00:00 2001 From: Simon Wilks Date: Fri, 30 Nov 2012 08:06:19 +0100 Subject: [PATCH 14/19] Code formatting cleanup. Fixed code style with Tools/fix_code_style.sh --- apps/hott_telemetry/hott_telemetry_main.c | 76 ++++++++++++++--------- apps/hott_telemetry/messages.c | 8 +-- apps/hott_telemetry/messages.h | 16 ++--- 3 files changed, 58 insertions(+), 42 deletions(-) diff --git a/apps/hott_telemetry/hott_telemetry_main.c b/apps/hott_telemetry/hott_telemetry_main.c index ec2ca2b411..1eccf50a18 100644 --- a/apps/hott_telemetry/hott_telemetry_main.c +++ b/apps/hott_telemetry/hott_telemetry_main.c @@ -40,7 +40,7 @@ * The HoTT receiver polls each device at a regular interval at which point * a data packet can be returned if necessary. * - * TODO: Add support for at least the vario and GPS sensor data. + * TODO: Add support for at least the vario and GPS sensor data. * */ @@ -107,6 +107,7 @@ static int open_uart(const char *device, struct termios *uart_config_original) /* Back up the original uart configuration to restore it after exit */ char msg[80]; + if ((termios_state = tcgetattr(uart, uart_config_original)) < 0) { sprintf(msg, "Error getting baudrate / termios config for %s: %d\n", device, termios_state); close(uart); @@ -121,7 +122,7 @@ static int open_uart(const char *device, struct termios *uart_config_original) /* Set baud rate */ if (cfsetispeed(&uart_config, speed) < 0 || cfsetospeed(&uart_config, speed) < 0) { - sprintf(msg, "Error setting baudrate / termios config for %s: %d (cfsetispeed, cfsetospeed)\n", + sprintf(msg, "Error setting baudrate / termios config for %s: %d (cfsetispeed, cfsetospeed)\n", device, termios_state); close(uart); FATAL_MSG(msg); @@ -136,24 +137,28 @@ static int open_uart(const char *device, struct termios *uart_config_original) /* Get the appropriate GPIO pin and control register */ uint32_t gpio_uart; uint32_t uart_cr3; - switch(device[strlen(device) - 1]) { - case '0': - gpio_uart = GPIO_USART1_TX; - uart_cr3 = STM32_USART1_CR3; - break; - case '1': - gpio_uart = GPIO_USART2_TX; - uart_cr3 = STM32_USART2_CR3; - break; - case '2': - sprintf(msg, "/dev/ttyS3 is not supported.\n", device); - close(uart); - FATAL_MSG(msg); - break; - case '3': - gpio_uart = GPIO_USART6_TX; - uart_cr3 = STM32_USART6_CR3; - break; + + switch (device[strlen(device) - 1]) { + case '0': + gpio_uart = GPIO_USART1_TX; + uart_cr3 = STM32_USART1_CR3; + break; + + case '1': + gpio_uart = GPIO_USART2_TX; + uart_cr3 = STM32_USART2_CR3; + break; + + case '2': + sprintf(msg, "/dev/ttyS3 is not supported.\n", device); + close(uart); + FATAL_MSG(msg); + break; + + case '3': + gpio_uart = GPIO_USART6_TX; + uart_cr3 = STM32_USART6_CR3; + break; } /* Change the TX port to be open-drain */ @@ -164,7 +169,7 @@ static int open_uart(const char *device, struct termios *uart_config_original) cr = getreg32(uart_cr3); cr |= (USART_CR3_HDSEL); putreg32(cr, uart_cr3); - + return uart; } @@ -174,6 +179,7 @@ int read_data(int uart, int *id) struct pollfd fds[] = { { .fd = uart, .events = POLLIN } }; char mode; + if (poll(fds, 1, timeout) > 0) { /* Get the mode: binary or text */ read(uart, &mode, 1); @@ -184,10 +190,12 @@ int read_data(int uart, int *id) if (mode != BINARY_MODE_REQUEST_ID) { return ERROR; } + } else { ERROR_MSG("UART timeout on TX/RX port"); return ERROR; } + return OK; } @@ -196,13 +204,16 @@ int send_data(int uart, uint8_t *buffer, int size) usleep(POST_READ_DELAY_IN_USECS); uint16_t checksum = 0; - for(int i = 0; i < size; i++) { + + for (int i = 0; i < size; i++) { if (i == size - 1) { /* Set the checksum: the first uint8_t is taken as the checksum. */ buffer[i] = checksum & 0xff; + } else { checksum += buffer[i]; } + write(uart, &buffer[i], 1); /* Sleep before sending the next byte. */ @@ -213,11 +224,11 @@ int send_data(int uart, uint8_t *buffer, int size) /* TODO: Fix this!! */ uint8_t dummy[size]; read(uart, &dummy, size); - + return OK; } -int hott_telemetry_thread_main(int argc, char *argv[]) +int hott_telemetry_thread_main(int argc, char *argv[]) { INFO_MSG("starting"); @@ -255,15 +266,18 @@ int hott_telemetry_thread_main(int argc, char *argv[]) uint8_t buffer[MESSAGE_BUFFER_SIZE]; int size = 0; int id = 0; + while (!thread_should_exit) { if (read_data(uart, &id) == OK) { - switch(id) { - case ELECTRIC_AIR_MODULE: - build_eam_response(buffer, &size); - break; - default: - continue; // Not a module we support. + switch (id) { + case ELECTRIC_AIR_MODULE: + build_eam_response(buffer, &size); + break; + + default: + continue; // Not a module we support. } + send_data(uart, buffer, size); } } @@ -313,9 +327,11 @@ int hott_telemetry_main(int argc, char *argv[]) if (!strcmp(argv[1], "status")) { if (thread_running) { INFO_MSG("daemon is running"); + } else { INFO_MSG("daemon not started"); } + exit(0); } diff --git a/apps/hott_telemetry/messages.c b/apps/hott_telemetry/messages.c index 83cc5348c6..dce16f3710 100644 --- a/apps/hott_telemetry/messages.c +++ b/apps/hott_telemetry/messages.c @@ -36,7 +36,7 @@ * @file messages.c * */ - + #include "messages.h" #include @@ -57,10 +57,10 @@ void build_eam_response(uint8_t *buffer, int *size) struct sensor_combined_s raw; memset(&raw, 0, sizeof(raw)); orb_copy(ORB_ID(sensor_combined), sensor_sub, &raw); - + struct eam_module_msg msg; *size = sizeof(msg); - memset(&msg, 0, *size); + memset(&msg, 0, *size); msg.start = START_BYTE; msg.eam_sensor_id = ELECTRIC_AIR_MODULE; @@ -72,7 +72,7 @@ void build_eam_response(uint8_t *buffer, int *size) uint16_t alt = (uint16_t)(raw.baro_alt_meter + 500); msg.altitude_L = (uint8_t)alt & 0xff; msg.altitude_H = (uint8_t)(alt >> 8) & 0xff; - + msg.stop = STOP_BYTE; memcpy(buffer, &msg, *size); diff --git a/apps/hott_telemetry/messages.h b/apps/hott_telemetry/messages.h index fbb9a2d844..44001e04f0 100644 --- a/apps/hott_telemetry/messages.h +++ b/apps/hott_telemetry/messages.h @@ -44,17 +44,17 @@ #include /* The buffer size used to store messages. This must be at least as big as the number of - * fields in the largest message struct. + * fields in the largest message struct. */ #define MESSAGE_BUFFER_SIZE 50 -/* The HoTT receiver demands a minimum 5ms period of silence after delivering its request. +/* The HoTT receiver demands a minimum 5ms period of silence after delivering its request. * Note that the value specified here is lower than 5000 (5ms) as time is lost constucting - * the message after the read which takes some milliseconds. + * the message after the read which takes some milliseconds. */ -#define POST_READ_DELAY_IN_USECS 4000 +#define POST_READ_DELAY_IN_USECS 4000 /* A pause of 3ms is required between each uint8_t sent back to the HoTT receiver. Much lower - * values can be used in practise though. + * values can be used in practise though. */ #define POST_WRITE_DELAY_IN_USECS 2000 @@ -74,10 +74,10 @@ struct eam_module_msg { uint8_t eam_sensor_id; /**< EAM sensor ID */ uint8_t warning; uint8_t sensor_id; /**< Sensor ID, why different? */ - uint8_t alarm_inverse1; - uint8_t alarm_inverse2; + uint8_t alarm_inverse1; + uint8_t alarm_inverse2; uint8_t cell1_L; /**< Lipo cell voltages. Not supported. */ - uint8_t cell2_L; + uint8_t cell2_L; uint8_t cell3_L; uint8_t cell4_L; uint8_t cell5_L; From 9924c4f425bc9fc507e7d065cc373a6cd9bbfebd Mon Sep 17 00:00:00 2001 From: Simon Wilks Date: Fri, 30 Nov 2012 08:12:20 +0100 Subject: [PATCH 15/19] Addressed compiler warnings and handle non-supported devices properly. --- apps/hott_telemetry/hott_telemetry_main.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/apps/hott_telemetry/hott_telemetry_main.c b/apps/hott_telemetry/hott_telemetry_main.c index 1eccf50a18..ae6c69b99d 100644 --- a/apps/hott_telemetry/hott_telemetry_main.c +++ b/apps/hott_telemetry/hott_telemetry_main.c @@ -135,8 +135,8 @@ static int open_uart(const char *device, struct termios *uart_config_original) } /* Get the appropriate GPIO pin and control register */ - uint32_t gpio_uart; - uint32_t uart_cr3; + uint32_t gpio_uart = GPIO_USART2_TX;; + uint32_t uart_cr3 = STM32_USART2_CR3; switch (device[strlen(device) - 1]) { case '0': @@ -149,16 +149,16 @@ static int open_uart(const char *device, struct termios *uart_config_original) uart_cr3 = STM32_USART2_CR3; break; - case '2': - sprintf(msg, "/dev/ttyS3 is not supported.\n", device); - close(uart); - FATAL_MSG(msg); - break; - case '3': gpio_uart = GPIO_USART6_TX; uart_cr3 = STM32_USART6_CR3; break; + + default: + sprintf(msg, "%s is not supported.\n", device); + close(uart); + FATAL_MSG(msg); + break; } /* Change the TX port to be open-drain */ From 097aeddcadc6c0b5decf8374c05586bfff5e403d Mon Sep 17 00:00:00 2001 From: Simon Wilks Date: Thu, 6 Dec 2012 17:24:27 +0100 Subject: [PATCH 16/19] Push single wire operations into stm32_serial.c and added a test to verify HoTT telemetry setup. --- apps/px4/tests/test_hott_telemetry.c | 239 ++++++++++++++++++++++++ apps/px4/tests/tests.h | 1 + apps/px4/tests/tests_main.c | 1 + nuttx/arch/arm/src/stm32/stm32_serial.c | 21 +++ nuttx/drivers/serial/serial.c | 1 + 5 files changed, 263 insertions(+) create mode 100644 apps/px4/tests/test_hott_telemetry.c diff --git a/apps/px4/tests/test_hott_telemetry.c b/apps/px4/tests/test_hott_telemetry.c new file mode 100644 index 0000000000..dbef021e32 --- /dev/null +++ b/apps/px4/tests/test_hott_telemetry.c @@ -0,0 +1,239 @@ +/**************************************************************************** + * + * Copyright (C) 2012 PX4 Development Team. All rights reserved. + * Author: @author Simon Wilks + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/** + * @file test_hott_telemetry.c + * + * Tests the Graupner HoTT telemetry support. + * + */ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "tests.h" + + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ +static int open_uart(const char *device) +{ + /* baud rate */ + int speed = B19200; + + /* open uart */ + int uart = open(device, O_RDWR | O_NOCTTY); + + if (uart < 0) { + errx(1, "FAIL: Error opening port"); + return ERROR; + } + + /* Try to set baud rate */ + struct termios uart_config; + + /* Fill the struct for the new configuration */ + tcgetattr(uart, &uart_config); + + /* Clear ONLCR flag (which appends a CR for every LF) */ + uart_config.c_oflag &= ~ONLCR; + + /* Set baud rate */ + if (cfsetispeed(&uart_config, speed) < 0 || cfsetospeed(&uart_config, speed) < 0) { + errx(1, "FAIL: Error setting baudrate / termios config for cfsetispeed, cfsetospeed"); + return ERROR; + } + + if (tcsetattr(uart, TCSANOW, &uart_config) < 0) { + errx(1, "FAIL: Error setting baudrate / termios config for tcsetattr"); + return ERROR; + } + + return uart; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: test_hott_telemetry + ****************************************************************************/ + +int test_hott_telemetry(int argc, char *argv[]) +{ + warnx("HoTT Telemetry Test Requirements:"); + warnx("- Radio on and Electric Air. Mod on (telemetry -> sensor select)."); + warnx("- Receiver telemetry port must be in telemetry mode."); + warnx("- Connect telemetry wire to /dev/ttyS1 (USART2)."); + warnx("Testing..."); + + const char device[] = "/dev/ttyS1"; + int fd = open_uart(device); + + if (fd < 0) { + close(fd); + return ERROR; + } + + /* Activate single wire mode */ + ioctl(fd, TIOCSRS485, SER_RS485_ENABLED); + + char send = 'a'; + write(fd, &send, 1); + + /* Since TX and RX are now connected we should be able to read in what we wrote */ + const int timeout = 1000; + struct pollfd fds[] = { { .fd = fd, .events = POLLIN } }; + + if (poll(fds, 1, timeout) == 0) { + errx(1, "FAIL: Could not read sent data."); + } + + char receive; + read(fd, &receive, 1); + warnx("PASS: Single wire enabled. Sent %x and received %x", send, receive); + + + /* Attempt to read HoTT poll messages from the HoTT receiver */ + int received_count = 0; + int valid_count = 0; + const int max_polls = 5; + uint8_t byte; + + for (; received_count < 5; received_count++) { + if (poll(fds, 1, timeout) == 0) { + errx(1, "FAIL: Could not read sent data. Is your HoTT receiver plugged in on %s?", device); + break; + + } else { + read(fd, &byte, 1); + + if (byte == 0x80) { + valid_count++; + } + + /* Read the device ID being polled */ + read(fd, &byte, 1); + } + } + + if (received_count > 0 && valid_count > 0) { + if (received_count == max_polls && valid_count == max_polls) { + warnx("PASS: Received %d out of %d valid byte pairs from the HoTT receiver device.", received_count, max_polls); + + } else { + warnx("WARN: Received %d out of %d byte pairs of which %d were valid from the HoTT receiver device.", received_count, max_polls, valid_count); + } + + } else { + /* Let's work out what went wrong */ + if (received_count == 0) { + errx(1, "FAIL: Could not read any polls from HoTT receiver device."); + } + + if (valid_count == 0) { + errx(1, "FAIL: Received unexpected values from the HoTT receiver device."); + } + } + + + /* Attempt to send a HoTT response messages */ + uint8_t response[] = {0x7c, 0x8e, 0x00, 0xe0, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, \ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf4, 0x01, 0x00, 0x00, \ + 0x19, 0x00, 0x00, 0x00, 0x30, 0x75, 0x78, 0x00, 0x00, 0x00, \ + 0x00, 0x00, 0x00, 0x7d, 0x12 + }; + + usleep(5000); + + for (unsigned int i = 0; i < sizeof(response); i++) { + write(fd, &response[i], 1); + usleep(1000); + } + + warnx("PASS: Response sent to the HoTT receiver device. Voltage should now show 2.5V."); + + + /* Disable single wire */ + ioctl(fd, TIOCSRS485, ~SER_RS485_ENABLED); + + write(fd, &send, 1); + + /* We should timeout as there will be nothing to read (TX and RX no longer connected) */ + if (poll(fds, 1, timeout) == 0) { + errx(1, "FAIL: timeout expected."); + } + + warnx("PASS: Single wire disabled."); + + close(fd); + exit(0); +} diff --git a/apps/px4/tests/tests.h b/apps/px4/tests/tests.h index 46450d10bf..cc3f5493a8 100644 --- a/apps/px4/tests/tests.h +++ b/apps/px4/tests/tests.h @@ -93,6 +93,7 @@ extern int test_uart_send(int argc, char *argv[]); extern int test_sleep(int argc, char *argv[]); extern int test_time(int argc, char *argv[]); extern int test_uart_console(int argc, char *argv[]); +extern int test_hott_telemetry(int argc, char *argv[]); extern int test_jig_voltages(int argc, char *argv[]); extern int test_param(int argc, char *argv[]); extern int test_bson(int argc, char *argv[]); diff --git a/apps/px4/tests/tests_main.c b/apps/px4/tests/tests_main.c index 26f7ef96bf..906d25f9e7 100644 --- a/apps/px4/tests/tests_main.c +++ b/apps/px4/tests/tests_main.c @@ -101,6 +101,7 @@ struct { {"uart_baudchange", test_uart_baudchange, OPT_NOJIGTEST | OPT_NOALLTEST, 0}, {"uart_send", test_uart_send, OPT_NOJIGTEST | OPT_NOALLTEST, 0}, {"uart_console", test_uart_console, OPT_NOJIGTEST | OPT_NOALLTEST, 0}, + {"hott_telemetry", test_hott_telemetry, OPT_NOJIGTEST | OPT_NOALLTEST, 0}, {"tone", test_tone, 0, 0}, {"sleep", test_sleep, OPT_NOJIGTEST, 0}, {"time", test_time, OPT_NOJIGTEST, 0}, diff --git a/nuttx/arch/arm/src/stm32/stm32_serial.c b/nuttx/arch/arm/src/stm32/stm32_serial.c index 0868c3cd3d..80c4ce357c 100644 --- a/nuttx/arch/arm/src/stm32/stm32_serial.c +++ b/nuttx/arch/arm/src/stm32/stm32_serial.c @@ -1307,6 +1307,27 @@ static int up_ioctl(struct file *filep, int cmd, unsigned long arg) } break; + /* Set RS485 mode */ + case TIOCSRS485: + { + /* Change the TX port to be open-drain/push-pull */ + if (arg == SER_RS485_ENABLED) { + stm32_configgpio(priv->tx_gpio | GPIO_OPENDRAIN); + } else { + stm32_configgpio(priv->tx_gpio | GPIO_PUSHPULL); + } + + /* Enable/disable half-duplex mode */ + uint32_t cr = up_serialin(priv, STM32_USART_CR3_OFFSET); + if (arg == SER_RS485_ENABLED) { + cr |= (USART_CR3_HDSEL); + } else { + cr &= ~(USART_CR3_HDSEL); + } + up_serialout(priv, STM32_USART_CR3_OFFSET, cr); + } + break; + #ifdef CONFIG_SERIAL_TERMIOS case TCGETS: { diff --git a/nuttx/drivers/serial/serial.c b/nuttx/drivers/serial/serial.c index c650da5db3..c31d12eee1 100644 --- a/nuttx/drivers/serial/serial.c +++ b/nuttx/drivers/serial/serial.c @@ -687,6 +687,7 @@ static int uart_ioctl(FAR struct file *filep, int cmd, unsigned long arg) *(int *)arg = count; } + break; #ifdef CONFIG_SERIAL_TERMIOS case TCGETS: From ecd01dc2e88a60d71ad87968cd07234a32bf7d8d Mon Sep 17 00:00:00 2001 From: Simon Wilks Date: Mon, 21 Jan 2013 23:31:12 +0100 Subject: [PATCH 17/19] We aren't using RS485 but single wire. --- apps/px4/tests/test_hott_telemetry.c | 4 ++-- nuttx/arch/arm/src/stm32/stm32_serial.c | 8 ++++---- nuttx/include/nuttx/serial/tioctl.h | 6 ++++++ 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/apps/px4/tests/test_hott_telemetry.c b/apps/px4/tests/test_hott_telemetry.c index dbef021e32..74aa0e614f 100644 --- a/apps/px4/tests/test_hott_telemetry.c +++ b/apps/px4/tests/test_hott_telemetry.c @@ -143,7 +143,7 @@ int test_hott_telemetry(int argc, char *argv[]) } /* Activate single wire mode */ - ioctl(fd, TIOCSRS485, SER_RS485_ENABLED); + ioctl(fd, TIOCSSINGLEWIRE, SER_SINGLEWIRE_ENABLED); char send = 'a'; write(fd, &send, 1); @@ -223,7 +223,7 @@ int test_hott_telemetry(int argc, char *argv[]) /* Disable single wire */ - ioctl(fd, TIOCSRS485, ~SER_RS485_ENABLED); + ioctl(fd, TIOCSSINGLEWIRE, ~SER_SINGLEWIRE_ENABLED); write(fd, &send, 1); diff --git a/nuttx/arch/arm/src/stm32/stm32_serial.c b/nuttx/arch/arm/src/stm32/stm32_serial.c index 80c4ce357c..7e8537b2a3 100644 --- a/nuttx/arch/arm/src/stm32/stm32_serial.c +++ b/nuttx/arch/arm/src/stm32/stm32_serial.c @@ -1307,11 +1307,11 @@ static int up_ioctl(struct file *filep, int cmd, unsigned long arg) } break; - /* Set RS485 mode */ - case TIOCSRS485: + /* Set single-wire mode */ + case TIOCSSINGLEWIRE: { /* Change the TX port to be open-drain/push-pull */ - if (arg == SER_RS485_ENABLED) { + if (arg == SER_SINGLEWIRE_ENABLED) { stm32_configgpio(priv->tx_gpio | GPIO_OPENDRAIN); } else { stm32_configgpio(priv->tx_gpio | GPIO_PUSHPULL); @@ -1319,7 +1319,7 @@ static int up_ioctl(struct file *filep, int cmd, unsigned long arg) /* Enable/disable half-duplex mode */ uint32_t cr = up_serialin(priv, STM32_USART_CR3_OFFSET); - if (arg == SER_RS485_ENABLED) { + if (arg == SER_SINGLEWIRE_ENABLED) { cr |= (USART_CR3_HDSEL); } else { cr &= ~(USART_CR3_HDSEL); diff --git a/nuttx/include/nuttx/serial/tioctl.h b/nuttx/include/nuttx/serial/tioctl.h index b309ff37ce..76185a22ed 100644 --- a/nuttx/include/nuttx/serial/tioctl.h +++ b/nuttx/include/nuttx/serial/tioctl.h @@ -169,6 +169,9 @@ #define TIOCSERGSTRUCT _TIOC(0x002c) /* Get device TTY structure */ +#define TIOCSSINGLEWIRE _TIOC(0x002d) /* Set single-wire mode */ +#define TIOCGSINGLEWIRE _TIOC(0x002e) /* Get single-wire mode */ + /* Definitions used in struct serial_rs485 (Linux compatible) */ #define SER_RS485_ENABLED (1 << 0) /* Enable/disble RS-485 support */ @@ -176,6 +179,9 @@ #define SER_RS485_RTS_AFTER_SEND (1 << 2) /* Logic level for RTS pin after sent */ #define SER_RS485_RX_DURING_TX (1 << 4) +/* single-wire definitions */ +#define SER_SINGLEWIRE_ENABLED (1 << 0) /* Enable/disble single-wire support */ + /******************************************************************************************** * Public Type Definitions ********************************************************************************************/ From 0246842c8854fcb49ffa34bcf46c61f2b7da95b2 Mon Sep 17 00:00:00 2001 From: Simon Wilks Date: Fri, 25 Jan 2013 01:41:11 +0100 Subject: [PATCH 18/19] Enable single wire via ioctl calls and pull the battery voltage from the battery status topic. --- apps/hott_telemetry/hott_telemetry_main.c | 37 ++--------------------- apps/hott_telemetry/messages.c | 10 +++++- nuttx/include/nuttx/serial/tioctl.h | 2 +- 3 files changed, 12 insertions(+), 37 deletions(-) diff --git a/apps/hott_telemetry/hott_telemetry_main.c b/apps/hott_telemetry/hott_telemetry_main.c index ae6c69b99d..d67ab06a98 100644 --- a/apps/hott_telemetry/hott_telemetry_main.c +++ b/apps/hott_telemetry/hott_telemetry_main.c @@ -134,41 +134,8 @@ static int open_uart(const char *device, struct termios *uart_config_original) FATAL_MSG(msg); } - /* Get the appropriate GPIO pin and control register */ - uint32_t gpio_uart = GPIO_USART2_TX;; - uint32_t uart_cr3 = STM32_USART2_CR3; - - switch (device[strlen(device) - 1]) { - case '0': - gpio_uart = GPIO_USART1_TX; - uart_cr3 = STM32_USART1_CR3; - break; - - case '1': - gpio_uart = GPIO_USART2_TX; - uart_cr3 = STM32_USART2_CR3; - break; - - case '3': - gpio_uart = GPIO_USART6_TX; - uart_cr3 = STM32_USART6_CR3; - break; - - default: - sprintf(msg, "%s is not supported.\n", device); - close(uart); - FATAL_MSG(msg); - break; - } - - /* Change the TX port to be open-drain */ - stm32_configgpio(gpio_uart | GPIO_OPENDRAIN); - - /* Turn on half-duplex mode */ - uint32_t cr; - cr = getreg32(uart_cr3); - cr |= (USART_CR3_HDSEL); - putreg32(cr, uart_cr3); + /* Activate single wire mode */ + ioctl(uart, TIOCSSINGLEWIRE, SER_SINGLEWIRE_ENABLED); return uart; } diff --git a/apps/hott_telemetry/messages.c b/apps/hott_telemetry/messages.c index dce16f3710..8bfb997737 100644 --- a/apps/hott_telemetry/messages.c +++ b/apps/hott_telemetry/messages.c @@ -42,12 +42,15 @@ #include #include #include +#include #include +static int battery_sub = -1; static int sensor_sub = -1; void messages_init(void) { + battery_sub = orb_subscribe(ORB_ID(battery_status)); sensor_sub = orb_subscribe(ORB_ID(sensor_combined)); } @@ -58,6 +61,11 @@ void build_eam_response(uint8_t *buffer, int *size) memset(&raw, 0, sizeof(raw)); orb_copy(ORB_ID(sensor_combined), sensor_sub, &raw); + /* get a local copy of the battery data */ + struct battery_status_s battery; + memset(&battery, 0, sizeof(battery)); + orb_copy(ORB_ID(battery_status), battery_sub, &battery); + struct eam_module_msg msg; *size = sizeof(msg); memset(&msg, 0, *size); @@ -67,7 +75,7 @@ void build_eam_response(uint8_t *buffer, int *size) msg.sensor_id = EAM_SENSOR_ID; msg.temperature1 = (uint8_t)(raw.baro_temp_celcius + 20); msg.temperature2 = TEMP_ZERO_CELSIUS; - msg.main_voltage_L = (uint8_t)(raw.battery_voltage_v * 10); + msg.main_voltage_L = (uint8_t)(battery.voltage_v * 10); uint16_t alt = (uint16_t)(raw.baro_alt_meter + 500); msg.altitude_L = (uint8_t)alt & 0xff; diff --git a/nuttx/include/nuttx/serial/tioctl.h b/nuttx/include/nuttx/serial/tioctl.h index 9edc7e87f9..a98b487a66 100644 --- a/nuttx/include/nuttx/serial/tioctl.h +++ b/nuttx/include/nuttx/serial/tioctl.h @@ -177,7 +177,7 @@ #define TIOCSSINGLEWIRE _TIOC(0x002c) /* Set single-wire mode */ #define TIOCGSINGLEWIRE _TIOC(0x002d) /* Get single-wire mode */ -# define SER_SINGLEWIRE_ENABLED (1 << 0) /* Enable/disble single-wire support */ +# define SER_SINGLEWIRE_ENABLED (1 << 0) /* Enable/disable single-wire support */ /* Debugging */ From bd5887b4cae08dd378c03280e6c3ddafcec729c1 Mon Sep 17 00:00:00 2001 From: Simon Wilks Date: Fri, 25 Jan 2013 10:44:21 +0100 Subject: [PATCH 19/19] Move the config param to a more sane location (I hope). --- nuttx/configs/px4fmu/nsh/defconfig | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/nuttx/configs/px4fmu/nsh/defconfig b/nuttx/configs/px4fmu/nsh/defconfig index d669da83ab..fd783dec5d 100755 --- a/nuttx/configs/px4fmu/nsh/defconfig +++ b/nuttx/configs/px4fmu/nsh/defconfig @@ -200,6 +200,12 @@ CONFIG_STM32_TIM9=y CONFIG_STM32_TIM10=y CONFIG_STM32_TIM11=y +# +# Enable single wire support. If this is not defined, then this mode cannot +# be enabled. +# +CONFIG_STM32_USART_SINGLEWIRE=y + # # We want the flash prefetch on for max performance. # @@ -226,8 +232,6 @@ CONFIG_AT24XX_MTD_BLOCKSIZE=256 # CONFIG_SERIAL_CONSOLE_REINIT - re-initializes the console serial port # immediately after creating the /dev/console device. This is required # if the console serial port has RX DMA enabled. -# CONFIG_STM32_USART_SINGLEWIRE - Serial driver supports single wire mode. If -# this is not defined, then this mode cannot be enabled. # # CONFIG_USARTn_SERIAL_CONSOLE - selects the USARTn for the # console and ttys0 (default is the USART1). @@ -242,7 +246,6 @@ CONFIG_AT24XX_MTD_BLOCKSIZE=256 # CONFIG_SERIAL_TERMIOS=y CONFIG_SERIAL_CONSOLE_REINIT=y -CONFIG_STM32_USART_SINGLEWIRE=y CONFIG_USART1_SERIAL_CONSOLE=y CONFIG_USART2_SERIAL_CONSOLE=n