Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement the message reception loop #4

Merged
merged 9 commits into from
Feb 3, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/workflows/documentation.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ jobs:

steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Setup Python
uses: actions/setup-python@v4.5.0
with:
Expand Down
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ CPPFLAGS += $(shell pkg-config --cflags-only-I *.pc)
CPPFLAGS += -MMD
CPPFLAGS += -DVERSION="$(VERSION)"
CPPFLAGS += -DLOG_USE_COLOR
# _DEFAULT_SOURCE is needed for cfmakeraw
CPPFLAGS += -D_DEFAULT_SOURCE

LDFLAGS += -L .
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@
### As an executable

- Display the current serial port configuration in the YAML format
- Output the ublox messages read on the serial port in the JSON format

### As a C library

- Iterate over all ublox messages read on the serial port
- Verbose alternatives to termios
- Extensive documentation

Expand Down
16 changes: 15 additions & 1 deletion include/serial.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@

#include "serial_options.h"

#include <ft_deque.h>

#include <sys/types.h> // ssize_t

#include <stdbool.h>
#include <stdint.h> // uint*_t

Expand All @@ -18,8 +22,9 @@ typedef struct serial_port serial_port_t;
*/
struct serial_port
{
int file_descriptor; /**< Underlying file */
serial_options_t options; /**< Terminal options */
t_deque buffer; /**< Circular buffer */
int file_descriptor; /**< Underlying file */
uint8_t opened :1; /**< Is this file still open ? */
uint8_t got_options :1; /**< Is @ref options filled ? */
};
Expand All @@ -34,6 +39,9 @@ speed_t serial_encode_baudrate(int64_t speed_in_bps);

bool serial_print_config(serial_port_t* port);

ssize_t serial_single_read(serial_port_t* port);
bool serial_accumulate(serial_port_t* port, size_t n);

/**
* Use the RAII with serial ports.
*
Expand All @@ -57,3 +65,9 @@ bool serial_print_config(serial_port_t* port);
*/
#define serial_ensure_options(PORT) \
do { if (!(PORT)->got_options) serial_get_options(PORT); } while (0)

/**
@var serial_port::buffer
Good complexity for push_bash and pop_front.
No need to memmove remaining data to the front.
*/
8 changes: 6 additions & 2 deletions include/serial_options.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ struct serial_input_modes
uint32_t enable_start_stop_in :1; /**< Enable start/stop input control */
uint32_t ring_bell_when_full :1; /**< Ring bell when input queue is full */
uint32_t is_utf8 :1; /**< Input is UTF8 */
uint32_t _unused :16;
uint32_t _dont_modify_speed :1; /* Used when setting speed */
};

/**
Expand Down Expand Up @@ -69,7 +71,7 @@ struct serial_output_modes
*/
struct serial_control_modes
{
uint32_t _unused :4;
uint32_t _speed_4lsb :4; /* Least significant 4-bits of the line speed */
uint32_t character_size :2; /**< Number of bits used by a single character */
uint32_t two_stop_bits :1; /**< Set two stop bits, rather than one */
uint32_t read :1; /**< Enable receiver */
Expand All @@ -80,6 +82,7 @@ struct serial_control_modes
/** Lower modem control lines after last process closes the device (hang up). */
uint32_t hang_up :1;
uint32_t is_local :1; /**< Ignore modem control lines */
uint32_t _speed_is_extra:1; /* For non-posix baud rates */
};

/**
Expand All @@ -102,7 +105,8 @@ struct serial_local_modes
/** Send SIGTOU to background jobs attempting to write to the terminal. */
uint32_t tostop :1;
uint32_t _echo_control :1; /* Escape control characters */
uint32_t _misc :5;
uint32_t _echo_print :1; /* Print chars when erased, if ICANON and ECHO */
uint32_t _misc :4;
uint32_t enable_processing :1; /* implementation-defined input processing */
};

Expand Down
38 changes: 31 additions & 7 deletions include/ublox.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,17 @@
* This code assumes a Little Endian host.
*/

#include "serial.h"

#include <ft_prepro/enum.h>
#include <ft_string.h>

#include <sys/types.h> // size_t

#include <stdint.h> // uint*_t

extern const uint8_t sync_chars[2];
extern const uint8_t ublox_sync_chars[2];
extern const size_t ublox_smallest_message_size;

/**
* All ublox messages inherit from that type.
Expand Down Expand Up @@ -76,8 +80,10 @@ DECLARE_ENUM_WITH_VALUES(ublox_constellation,
(SBAS /**< Satellite-based augmentation systems */, 1),
(Galileo /**< From Europe */, 2),
(BeiDou /**< BeiDou Navigation Satellite System, from China */, 3),
(IMES /**< Indoor MEssaging System, from Japan */, 4),
(QZSS /**< Quasi-Zenith Satellite System, from Japan */, 5),
(GLONASS /**< Global Navigation Satellite System, from Russia */, 6)
(GLONASS /**< Global Navigation Satellite System, from Russia */, 6),
(NavIC /**< Navigation Indian Constellation */, 7)
);

// clang-format on
Expand All @@ -92,20 +98,38 @@ DECLARE_ENUM_WITH_VALUES(ublox_constellation,
struct ublox_navigation_data
{
struct ublox_header header;
uint8_t constellation; /**< GNSS identifier */
uint8_t satellite; /**< Satellite identifier */
uint8_t _reserved1;
uint8_t constellation; /**< GNSS identifier */
uint8_t satellite; /**< Satellite identifier */
uint8_t signal; /**< Signal identifier */
uint8_t glonass_frequency; /**< Only used for GLONASS */
/** The number of data words contained in this message. */
uint8_t word_count;
/** The tracking channel number the message was received on. */
uint8_t channel;
uint8_t version; /**< Message version (=2 for this version) */
uint8_t _reserved2;
/** Message version (=2 for this version). */
uint8_t version;
uint8_t _reserved;
};

struct ublox_gps_l1ca
{
struct ublox_navigation_data super;
struct
{
uint32_t parity :6;
uint32_t data :24;
} words[10];
};

bool ublox_port_config(serial_port_t* port, int64_t baudrate);

ublox_message_t* ublox_next_message(serial_port_t* port);

ublox_checksum_t ublox_compute_checksum(ublox_message_t* message, size_t size);

t_string ublox_header_tostring(struct ublox_header* message);
t_string ublox_navigation_data_tostring(struct ublox_navigation_data* message);

/**
@var ublox_header::class
A class is a group of messages that are related to each other
Expand Down
53 changes: 40 additions & 13 deletions parse_ublox.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,46 @@
#include "ublox.h"

#include <argp.h>
#include <fcntl.h>
#include <ft_prepro/tools.h>
#include <ft_printf.h>
#include <fcntl.h> // open
#include <ft_prepro/tools.h> // PP_STR
#include <log.h>
#include <termios.h>

#include <stdbool.h>
#include <stdio.h>
#include <stdio.h> // printf
#include <stdlib.h> // free

/**
* Receive, parse and display all ublox messages found on the serial port.
*
* @param passive: When passive, do not change the port config, only display it and try to read.
*/
void parse_ublox(const char* port_name, bool passive)
{
ublox_message_t* message;
Serial port = serial_open(port_name);

if (!passive)
ublox_port_config(&port, 115200);
serial_print_config(&port);

while ((message = ublox_next_message(&port)) != NULL)
{
if (message->class == RXM && message->type == 0x13)
{
RAII(t_string) str = ublox_navigation_data_tostring(
(struct ublox_navigation_data*)message);
log_info("{%s}", cstring(&str));
}
else
{
RAII(t_string) str = ublox_header_tostring(message);
log_info("{%s}", cstring(&str));
}
free(message);
}

} /* <- port will be closed at this point */

const char* argp_program_version = "ublox_parser " PP_STR(VERSION);
const char* argp_program_bug_address = "<antoine.gagniere@orolia2s.com>";
Expand All @@ -33,13 +66,7 @@ static error_t parse_opt(int key, char* arg, struct argp_state* state)
case 'p': arguments->is_passive = true; break;
case ARGP_KEY_ARG:
if (arg)
{
Serial port = serial_open(arg);
if (arguments->is_passive)
serial_print_config(&port);
else
ublox_port_config(&port);
}
parse_ublox(arg, arguments->is_passive);
return 0;
default: return ARGP_ERR_UNKNOWN;
}
Expand All @@ -48,10 +75,10 @@ static error_t parse_opt(int key, char* arg, struct argp_state* state)

static struct argp argp = { options, parse_opt, args_doc, doc, 0, 0, 0 };

int main(int ac, char** av)
int main(int arg_count, char** arg_values)
{
struct arguments arguments = { .is_passive = false };

argp_parse(&argp, ac, av, 0, 0, &arguments);
argp_parse(&argp, arg_count, arg_values, 0, 0, &arguments);
return 0;
}
2 changes: 1 addition & 1 deletion setup.sh
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ function check_program_installed()
fi
}

check_program_installed pip
check_program_installed pip python3-pip

printf "%-40s" "Checking for conan"
if command -v conan >/dev/null 2>/dev/null
Expand Down
8 changes: 7 additions & 1 deletion src/globals.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,10 @@
* - `0xb5` (181) ISO 8859-1 for µ (greek letter mu)
* - `0x62` (98) ISO 8859-1 for b
*/
const uint8_t sync_chars[2] = {0xb5, 'b'};
const uint8_t ublox_sync_chars[2] = {0xb5, 'b'};

/**
* Size in byte of the smallest message (UBX-ACK)
*/
const size_t ublox_smallest_message_size =
sizeof(struct ublox_header) + 2 + sizeof(struct ublox_footer);
30 changes: 23 additions & 7 deletions src/port_config.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,20 @@
#include <errno.h>
#include <string.h> // strerror

bool _ublox_port_set_speed(serial_port_t* port, int64_t baudrate)
{
speed_t speed = serial_encode_baudrate(baudrate);

if (speed == 0)
return false;
port->options.input_speed = speed;
port->options.output_speed = speed;
port->options.input._dont_modify_speed = false;
port->options.control._speed_4lsb = speed;
port->options.control._speed_is_extra = speed >> 12;
return true;
}

/**
* Congigure a serial port to receive messages from the u-blox receiver.
*
Expand All @@ -19,13 +33,15 @@
* - Baud rate: 38400
*
* The baud rate can be set to other powers of 2 times of 9600, up to 921600
*
* @param baudrate: line speed in bits per second
*/
bool ublox_port_config(serial_port_t* port)
bool ublox_port_config(serial_port_t* port, int64_t baudrate)
{
serial_print_config(port);
port->options.input_speed = B115200;
port->options.output_speed = B115200;
serial_make_raw(port);
serial_print_config(port);
return true;
serial_ensure_options(port);
if (!_ublox_port_set_speed(port, baudrate))
return false;
port->options.control_characters.minimum = ublox_smallest_message_size;
port->options.control_characters.timeout = 15; // 1.5 second
return serial_make_raw(port);
}
Loading