1395 lines
41 KiB
C
1395 lines
41 KiB
C
// SPDX-License-Identifier: LGPL-2.0-only
|
|
// SPDX-FileCopyrightText: 2024 Oleksij Rempel <linux@rempel-privat.de>
|
|
|
|
#ifndef _J1939_VEHICLE_POSITION_H_
|
|
#define _J1939_VEHICLE_POSITION_H_
|
|
|
|
#include <stdint.h>
|
|
#include <endian.h>
|
|
#include <stdbool.h>
|
|
#include <sys/epoll.h>
|
|
|
|
#include <linux/can.h>
|
|
#include <linux/kernel.h>
|
|
#include "../libj1939.h"
|
|
#include "../lib.h"
|
|
|
|
#define J1939_PGN_REQUEST_PGN 0x0ea00 /* 59904 */
|
|
|
|
/* ISO 11783-3:2018 - 5.4.5 Acknowledgment */
|
|
#define ISOBUS_PGN_ACK 0x0e800 /* 59392 */
|
|
|
|
#define J1939_MAX_TRANSFER_LENGH 1024
|
|
|
|
struct j1939_vp_stats {
|
|
int err;
|
|
uint32_t tskey_sch;
|
|
uint32_t tskey_ack;
|
|
uint32_t send;
|
|
};
|
|
|
|
struct j1939_vp_msg {
|
|
uint8_t buf[J1939_MAX_TRANSFER_LENGH];
|
|
size_t buf_size;
|
|
size_t len; /* length of received message */
|
|
struct sockaddr_can peername;
|
|
socklen_t peer_addr_len;
|
|
int sock;
|
|
};
|
|
|
|
struct j1939_vp_err_msg {
|
|
struct sock_extended_err *serr;
|
|
struct scm_timestamping *tss;
|
|
struct j1939_vp_stats *stats;
|
|
};
|
|
|
|
/* SAE J1939 specific definitions */
|
|
|
|
/* SAE J1939-71:2002 - 5.3 pgn65267 - Vehicle Position 1 - VP1 - */
|
|
#define J1939_PGN_VP1 0x0fef3 /* 65267 */
|
|
|
|
#define J1939_VP1_PRIO_DEFAULT 6
|
|
#define J1939_VP1_MAX_TRANSFER_LENGH \
|
|
sizeof(struct j1939_vp1_packet)
|
|
#define J1939_VP1_REPETITION_RATE_MS 5000
|
|
#define J1939_VP1_JITTER_MS 500
|
|
|
|
/**
|
|
* struct j1939_vp1_packet - Represents the PGN 65267 Vehicle
|
|
* Position packet
|
|
*
|
|
* @latitude: Raw latitude position of the vehicle
|
|
* - SPN: 584
|
|
* - Data Length: 4 bytes
|
|
* - Resolution: 10^-7 deg/bit
|
|
* - Offset: -210 degrees
|
|
* - Range: -210 to +211.1008122 degrees
|
|
* - Operating Range: -210 degrees (SOUTH) to +211.108122 degrees
|
|
* (NORTH)
|
|
*
|
|
* @longitude: Raw longitude position of the vehicle
|
|
* - SPN: 585
|
|
* - Data Length: 4 bytes
|
|
* - Resolution: 10^-7 deg/bit
|
|
* - Offset: -210 degrees
|
|
* - Range: -210 to +211.1008122 degrees
|
|
* - Operating Range: -210 degrees (WEST) to +211.108122 degrees
|
|
* (EAST)
|
|
*
|
|
* This structure defines each component of the Vehicle Position as described in
|
|
* PGN 65267.
|
|
*/
|
|
struct j1939_vp1_packet {
|
|
__le32 latitude; /* SPN 584 */
|
|
__le32 longitude; /* SPN 585 */
|
|
} __attribute__((__packed__));
|
|
|
|
/**
|
|
* j1939_vp1_get_latitude - Get the latitude from the packet
|
|
* @packet: Pointer to the J1939 VP1 packet
|
|
*
|
|
* Return: Latitude in degrees as a signed 32-bit integer
|
|
*/
|
|
static inline int32_t
|
|
j1939_vp1_get_latitude(const struct j1939_vp1_packet *packet)
|
|
{
|
|
return le32toh(packet->latitude);
|
|
}
|
|
|
|
/**
|
|
* j1939_vp1_set_latitude - Set the latitude in the packet
|
|
* @packet: Pointer to the J1939 VP1 packet
|
|
* @latitude: Latitude in degrees as a signed 32-bit integer
|
|
*/
|
|
static inline void
|
|
j1939_vp1_set_latitude(struct j1939_vp1_packet *packet, int32_t latitude)
|
|
{
|
|
packet->latitude = htole32(latitude);
|
|
}
|
|
|
|
/**
|
|
* j1939_vp1_get_longitude - Get the longitude from the packet
|
|
* @packet: Pointer to the J1939 VP1 packet
|
|
*
|
|
* Return: Longitude in degrees as a signed 32-bit integer
|
|
*/
|
|
static inline int32_t
|
|
j1939_vp1_get_longitude(const struct j1939_vp1_packet *packet)
|
|
{
|
|
return le32toh(packet->longitude);
|
|
}
|
|
|
|
/**
|
|
* j1939_vp1_set_longitude - Set the longitude in the packet
|
|
* @packet: Pointer to the J1939 VP1 packet
|
|
* @longitude: Longitude in degrees as a signed 32-bit integer
|
|
*/
|
|
static inline void
|
|
j1939_vp1_set_longitude(struct j1939_vp1_packet *packet, int32_t longitude)
|
|
{
|
|
packet->longitude = htole32(longitude);
|
|
}
|
|
|
|
/* SAE J1939xxxxxxxx - xxx pgn64502 - Vehicle Position 2 - VP2 - */
|
|
#define J1939_PGN_VP2 0x0fbf6 /* 64502 */
|
|
|
|
#define J1939_VP2_PRIO_DEFAULT 6
|
|
#define J1939_VP2_MAX_TRANSFER_LENGH \
|
|
sizeof(struct j1939_vp2_packet)
|
|
#define J1939_VP2_REPETITION_RATE_MS 5000
|
|
#define J1939_VP2_JITTER_MS 500
|
|
|
|
/**
|
|
* struct j1939_vp2_packet - Represents the PGN 64502 Vehicle
|
|
* Position 2 packet
|
|
* FIXME: current packet layout is guessed based on limited information:
|
|
* https://www.isobus.net/isobus/pGNAndSPN/10801?type=PGN
|
|
*
|
|
* @total_satellites: Total number of satellites in view
|
|
* - SPN: 8128
|
|
* - Data Length: 1 byte
|
|
*
|
|
* @hdop: Horizontal dilution of precision
|
|
* - SPN: 8129
|
|
* - Data Length: 1 byte
|
|
* - Resolution: 0.1
|
|
*
|
|
* @vdop: Vertical dilution of precision
|
|
* - SPN: 8130
|
|
* - Data Length: 1 byte
|
|
* - Resolution: 0.1
|
|
*
|
|
* @pdop: Position dilution of precision
|
|
* - SPN: 8131
|
|
* - Data Length: 1 byte
|
|
* - Resolution: 0.1
|
|
*
|
|
* @tdop: Time dilution of precision
|
|
* - SPN: 8132
|
|
* - Data Length: 1 byte
|
|
* - Resolution: 0.1
|
|
*
|
|
* This structure defines each component of the Vehicle Position 2 as described
|
|
* in PGN 64502.
|
|
*/
|
|
struct j1939_vp2_packet {
|
|
uint8_t total_satellites; /* SPN 8128 */
|
|
uint8_t hdop; /* SPN 8129 */
|
|
uint8_t vdop; /* SPN 8130 */
|
|
uint8_t pdop; /* SPN 8131 */
|
|
uint8_t tdop; /* SPN 8132 */
|
|
} __attribute__((__packed__));
|
|
|
|
/**
|
|
* j1939_vp2_get_total_satellites - Get the total number of satellites
|
|
* @packet: Pointer to the J1939 VP2 packet
|
|
*
|
|
* Return: Total number of satellites as an 8-bit integer
|
|
*/
|
|
static inline uint8_t j1939_vp2_get_total_satellites(const struct j1939_vp2_packet *packet)
|
|
{
|
|
return packet->total_satellites;
|
|
}
|
|
|
|
/**
|
|
* j1939_vp2_set_total_satellites - Set the total number of satellites
|
|
* @packet: Pointer to the J1939 VP2 packet
|
|
* @total_satellites: Total number of satellites as an 8-bit integer
|
|
*/
|
|
static inline void j1939_vp2_set_total_satellites(struct j1939_vp2_packet *packet,
|
|
uint8_t total_satellites)
|
|
{
|
|
packet->total_satellites = total_satellites;
|
|
}
|
|
|
|
/**
|
|
* j1939_vp2_get_hdop - Get the horizontal dilution of precision (HDOP)
|
|
* @packet: Pointer to the J1939 VP2 packet
|
|
*
|
|
* Return: HDOP as an 8-bit integer
|
|
*/
|
|
static inline uint8_t j1939_vp2_get_hdop(const struct j1939_vp2_packet *packet)
|
|
{
|
|
return packet->hdop;
|
|
}
|
|
|
|
/**
|
|
* j1939_vp2_set_hdop - Set the horizontal dilution of precision (HDOP)
|
|
* @packet: Pointer to the J1939 VP2 packet
|
|
* @hdop: HDOP as an 8-bit integer
|
|
*/
|
|
static inline void j1939_vp2_set_hdop(struct j1939_vp2_packet *packet,
|
|
uint8_t hdop)
|
|
{
|
|
packet->hdop = hdop;
|
|
}
|
|
|
|
/**
|
|
* j1939_vp2_get_vdop - Get the vertical dilution of precision (VDOP)
|
|
* @packet: Pointer to the J1939 VP2 packet
|
|
*
|
|
* Return: VDOP as an 8-bit integer
|
|
*/
|
|
static inline uint8_t j1939_vp2_get_vdop(const struct j1939_vp2_packet *packet)
|
|
{
|
|
return packet->vdop;
|
|
}
|
|
|
|
/**
|
|
* j1939_vp2_set_vdop - Set the vertical dilution of precision (VDOP)
|
|
* @packet: Pointer to the J1939 VP2 packet
|
|
* @vdop: VDOP as an 8-bit integer
|
|
*/
|
|
static inline void j1939_vp2_set_vdop(struct j1939_vp2_packet *packet,
|
|
uint8_t vdop)
|
|
{
|
|
packet->vdop = vdop;
|
|
}
|
|
|
|
/**
|
|
* j1939_vp2_get_pdop - Get the positional dilution of precision (PDOP)
|
|
* @packet: Pointer to the J1939 VP2 packet
|
|
*
|
|
* Return: PDOP as an 8-bit integer
|
|
*/
|
|
static inline uint8_t j1939_vp2_get_pdop(const struct j1939_vp2_packet *packet)
|
|
{
|
|
return packet->pdop;
|
|
}
|
|
|
|
/**
|
|
* j1939_vp2_set_pdop - Set the positional dilution of precision (PDOP)
|
|
* @packet: Pointer to the J1939 VP2 packet
|
|
* @pdop: PDOP as an 8-bit integer
|
|
*/
|
|
static inline void j1939_vp2_set_pdop(struct j1939_vp2_packet *packet,
|
|
uint8_t pdop)
|
|
{
|
|
packet->pdop = pdop;
|
|
}
|
|
|
|
/**
|
|
* j1939_vp2_get_tdop - Get the time dilution of precision (TDOP)
|
|
* @packet: Pointer to the J1939 VP2 packet
|
|
*
|
|
* Return: TDOP as an 8-bit integer
|
|
*/
|
|
static inline uint8_t j1939_vp2_get_tdop(const struct j1939_vp2_packet *packet)
|
|
{
|
|
return packet->tdop;
|
|
}
|
|
|
|
/**
|
|
* j1939_vp2_set_tdop - Set the time dilution of precision (TDOP)
|
|
* @packet: Pointer to the J1939 VP2 packet
|
|
* @tdop: TDOP as an 8-bit integer
|
|
*/
|
|
static inline void j1939_vp2_set_tdop(struct j1939_vp2_packet *packet,
|
|
uint8_t tdop)
|
|
{
|
|
packet->tdop = tdop;
|
|
}
|
|
|
|
/* NMEA 2000 specific definitions */
|
|
|
|
/* NMEA 2000 - PGN 126992 - System Time */
|
|
#define NMEA2000_PGN_SYS_TIME 0x1F010 /* 126992 */
|
|
|
|
#define NMEA2000_SYS_TIME_PRIO_DEFAULT 6
|
|
#define NMEA2000_SYS_TIME_MAX_TRANSFER_LENGTH \
|
|
sizeof(struct nmea2000_sys_time_packet)
|
|
#define NMEA2000_SYS_TIME_REPETITION_RATE_MS 1000
|
|
#define NMEA2000_SYS_TIME_JITTER_MS 100
|
|
|
|
/* Bit masks for the source_and_reserved field */
|
|
#define NMEA2000_SYS_TIME_SOURCE_MASK GENMASK(3, 0)
|
|
/**
|
|
* enum nmea2000_sys_time_source - Source of time information
|
|
* @NMEA2000_SYS_TIME_SOURCE_GPS: GPS
|
|
* @NMEA2000_SYS_TIME_SOURCE_GLONASS: GLONASS
|
|
* @NMEA2000_SYS_TIME_SOURCE_RADIO_STATION: Radio Station
|
|
* @NMEA2000_SYS_TIME_SOURCE_LOCAL_CESIUM: Local Cesium clock
|
|
* @NMEA2000_SYS_TIME_SOURCE_LOCAL_RUBIDIUM: Local Rubidium clock
|
|
* @NMEA2000_SYS_TIME_SOURCE_LOCAL_CRYSTAL: Local Crystal clock
|
|
*/
|
|
enum nmea2000_sys_time_source {
|
|
NMEA2000_SYS_TIME_SOURCE_GPS = 0,
|
|
NMEA2000_SYS_TIME_SOURCE_GLONASS = 1,
|
|
NMEA2000_SYS_TIME_SOURCE_RADIO_STATION = 2,
|
|
NMEA2000_SYS_TIME_SOURCE_LOCAL_CESIUM = 3,
|
|
NMEA2000_SYS_TIME_SOURCE_LOCAL_RUBIDIUM = 4,
|
|
NMEA2000_SYS_TIME_SOURCE_LOCAL_CRYSTAL = 5,
|
|
};
|
|
|
|
#define NMEA2000_SYS_TIME_RESERVED_MASK GENMASK(7, 4)
|
|
|
|
/**
|
|
* struct nmea2000_sys_time_packet - Represents the PGN 126992 System Time packet
|
|
*
|
|
* @sid: Sequence identifier for correlating related PGNs.
|
|
* @source: Source of the time information. Possible values are:
|
|
* 0 = GPS, 1 = GLONASS, 2 = Radio Station, 3 = Local Cesium clock,
|
|
* 4 = Local Rubidium clock, 5 = Local Crystal clock).
|
|
* @reserved: Reserved field, set to 0xF.
|
|
* @date: UTC Date in days since January 1, 1970.
|
|
* @time: UTC Time in 0.0001 seconds since midnight.
|
|
*/
|
|
struct nmea2000_sys_time_packet {
|
|
uint8_t sid;
|
|
uint8_t source_reserved;
|
|
__le16 date;
|
|
__le32 time;
|
|
} __attribute__((__packed__));
|
|
|
|
/**
|
|
* nmea2000_sys_time_get_sid - Get the sequence identifier (SID)
|
|
* @packet: Pointer to the NMEA2000 system time packet
|
|
*
|
|
* Return: Sequence identifier (8 bits)
|
|
*/
|
|
static inline uint8_t
|
|
nmea2000_sys_time_get_sid(const struct nmea2000_sys_time_packet *packet)
|
|
{
|
|
return packet->sid;
|
|
}
|
|
|
|
/**
|
|
* nmea2000_sys_time_set_sid - Set the sequence identifier (SID)
|
|
* @packet: Pointer to the NMEA2000 system time packet
|
|
* @sid: Sequence identifier to set (8 bits)
|
|
*/
|
|
static inline void
|
|
nmea2000_sys_time_set_sid(struct nmea2000_sys_time_packet *packet, uint8_t sid)
|
|
{
|
|
packet->sid = sid;
|
|
}
|
|
|
|
/**
|
|
* nmea2000_sys_time_get_source - Extract the source of time information
|
|
* @packet: Pointer to the NMEA2000 system time packet
|
|
*
|
|
* Return: Source of time information (4 bits)
|
|
*/
|
|
static inline uint8_t
|
|
nmea2000_sys_time_get_source(const struct nmea2000_sys_time_packet *packet)
|
|
{
|
|
return FIELD_GET(NMEA2000_SYS_TIME_SOURCE_MASK, packet->source_reserved);
|
|
}
|
|
|
|
/**
|
|
* nmea2000_sys_time_get_reserved - Extract the reserved field
|
|
* @packet: Pointer to the NMEA2000 system time packet
|
|
*
|
|
* Return: Reserved field (4 bits)
|
|
*/
|
|
static inline uint8_t
|
|
nmea2000_sys_time_get_reserved(const struct nmea2000_sys_time_packet *packet)
|
|
{
|
|
return FIELD_GET(NMEA2000_SYS_TIME_RESERVED_MASK, packet->source_reserved);
|
|
}
|
|
|
|
/**
|
|
* nmea2000_sys_time_set_source_reserved - Set the source and reserved fields
|
|
* @packet: Pointer to the NMEA2000 system time packet
|
|
* @source: Source of time information (4 bits)
|
|
* @reserved: Reserved field value (4 bits)
|
|
*/
|
|
static inline void
|
|
nmea2000_sys_time_set_source_reserved(struct nmea2000_sys_time_packet *packet,
|
|
enum nmea2000_sys_time_source source,
|
|
uint8_t reserved)
|
|
{
|
|
packet->source_reserved = FIELD_PREP(NMEA2000_SYS_TIME_SOURCE_MASK,
|
|
source) |
|
|
FIELD_PREP(NMEA2000_SYS_TIME_RESERVED_MASK,
|
|
reserved);
|
|
}
|
|
|
|
/**
|
|
* nmea2000_sys_time_get_date - Get the UTC date
|
|
* @packet: Pointer to the NMEA2000 system time packet
|
|
*
|
|
* Return: UTC date in days since January 1, 1970
|
|
*/
|
|
static inline uint16_t
|
|
nmea2000_sys_time_get_date(const struct nmea2000_sys_time_packet *packet)
|
|
{
|
|
return le16toh(packet->date);
|
|
}
|
|
|
|
/**
|
|
* nmea2000_sys_time_set_date - Set the UTC date
|
|
* @packet: Pointer to the NMEA2000 system time packet
|
|
* @date: UTC date in days since January 1, 1970
|
|
*/
|
|
static inline void
|
|
nmea2000_sys_time_set_date(struct nmea2000_sys_time_packet *packet,
|
|
uint16_t date)
|
|
{
|
|
packet->date = htole16(date);
|
|
}
|
|
|
|
/**
|
|
* nmea2000_sys_time_get_time - Get the UTC time
|
|
* @packet: Pointer to the NMEA2000 system time packet
|
|
*
|
|
* Return: UTC time in 0.0001 seconds since midnight
|
|
*/
|
|
static inline uint32_t
|
|
nmea2000_sys_time_get_time(const struct nmea2000_sys_time_packet *packet)
|
|
{
|
|
return le32toh(packet->time);
|
|
}
|
|
|
|
/**
|
|
* nmea2000_sys_time_set_time - Set the UTC time
|
|
* @packet: Pointer to the NMEA2000 system time packet
|
|
* @time: UTC time in 0.0001 seconds since midnight
|
|
*/
|
|
static inline void
|
|
nmea2000_sys_time_set_time(struct nmea2000_sys_time_packet *packet,
|
|
uint32_t time)
|
|
{
|
|
packet->time = htole32(time);
|
|
}
|
|
|
|
/* NMEA 2000 - PGN 127258 - Magnetic Variation */
|
|
#define NMEA2000_PGN_MAG_VAR 0x1F11A /* 127258 */
|
|
|
|
#define NMEA2000_MAG_VAR_PRIO_DEFAULT 6
|
|
#define NMEA2000_MAG_VAR_MAX_TRANSFER_LENGTH \
|
|
sizeof(struct nmea2000_mag_var_packet)
|
|
#define NMEA2000_MAG_VAR_REPETITION_RATE_MS 1000
|
|
#define NMEA2000_MAG_VAR_JITTER_MS 100
|
|
|
|
#define NMEA2000_MAG_VAR_SOURCE_MASK GENMASK(3, 0)
|
|
/**
|
|
* enum magnetic_variation_source - Source of magnetic variation
|
|
* @MAGNETIC_VARIATION_MANUAL: Manual entry
|
|
* @MAGNETIC_VARIATION_AUTOMATIC_CHART: Automatic from chart
|
|
* @MAGNETIC_VARIATION_AUTOMATIC_TABLE: Automatic from table
|
|
* @MAGNETIC_VARIATION_AUTOMATIC_CALCULATION: Automatic calculation
|
|
* @MAGNETIC_VARIATION_WMM_2000: WMM 2000
|
|
* @MAGNETIC_VARIATION_WMM_2005: WMM 2005
|
|
* @MAGNETIC_VARIATION_WMM_2010: WMM 2010
|
|
* @MAGNETIC_VARIATION_WMM_2015: WMM 2015
|
|
* @MAGNETIC_VARIATION_WMM_2020: WMM 2020
|
|
*/
|
|
enum magnetic_variation_source {
|
|
MAGNETIC_VARIATION_MANUAL = 0,
|
|
MAGNETIC_VARIATION_AUTOMATIC_CHART = 1,
|
|
MAGNETIC_VARIATION_AUTOMATIC_TABLE = 2,
|
|
MAGNETIC_VARIATION_AUTOMATIC_CALCULATION = 3,
|
|
MAGNETIC_VARIATION_WMM_2000 = 4,
|
|
MAGNETIC_VARIATION_WMM_2005 = 5,
|
|
MAGNETIC_VARIATION_WMM_2010 = 6,
|
|
MAGNETIC_VARIATION_WMM_2015 = 7,
|
|
MAGNETIC_VARIATION_WMM_2020 = 8,
|
|
};
|
|
|
|
#define NMEA2000_MAG_VAR_RESERVED_MASK GENMASK(7, 4)
|
|
|
|
/**
|
|
* struct nmea2000_mag_var_packet - Represents the PGN 127258 Magnetic Variation
|
|
* packet
|
|
*
|
|
* @sid: Sequence identifier for correlating related PGNs.
|
|
* @source_reserved: Encodes the source of magnetic variation and reserved bits.
|
|
* - Bits 0-3: Source of magnetic variation (4 bits).
|
|
* - For example, 5 = WMM2005.
|
|
* - Bits 4-7: Reserved field (4 bits).
|
|
* - Reserved for future use, typically set to 0xF.
|
|
* @age_of_service: UTC Date in days since January 1, 1970
|
|
* @variation: Magnetic variation (positive = Easterly, negative = Westerly)
|
|
*
|
|
* This structure defines the fields for the Magnetic Variation packet.
|
|
*/
|
|
struct nmea2000_mag_var_packet {
|
|
uint8_t sid;
|
|
uint8_t source_reserved;
|
|
__le32 age_of_service;
|
|
__le16 variation;
|
|
} __attribute__((__packed__));
|
|
|
|
/**
|
|
* nmea2000_mag_var_get_sid - Get the sequence identifier (SID)
|
|
* @packet: Pointer to the NMEA2000 magnetic variation packet
|
|
*
|
|
* Return: Sequence identifier (8 bits)
|
|
*/
|
|
static inline uint8_t
|
|
nmea2000_mag_var_get_sid(const struct nmea2000_mag_var_packet *packet)
|
|
{
|
|
return packet->sid;
|
|
}
|
|
|
|
/**
|
|
* nmea2000_mag_var_set_sid - Set the sequence identifier (SID)
|
|
* @packet: Pointer to the NMEA2000 magnetic variation packet
|
|
* @sid: Sequence identifier to set (8 bits)
|
|
*/
|
|
static inline void
|
|
nmea2000_mag_var_set_sid(struct nmea2000_mag_var_packet *packet, uint8_t sid)
|
|
{
|
|
packet->sid = sid;
|
|
}
|
|
|
|
/**
|
|
* nmea2000_mag_var_get_source - Extract the source of magnetic variation
|
|
* @packet: Pointer to the NMEA2000 magnetic variation packet
|
|
*
|
|
* Return: Source of magnetic variation (4 bits)
|
|
*/
|
|
static inline uint8_t
|
|
nmea2000_mag_var_get_source(const struct nmea2000_mag_var_packet *packet)
|
|
{
|
|
return FIELD_GET(NMEA2000_MAG_VAR_SOURCE_MASK, packet->source_reserved);
|
|
}
|
|
|
|
/**
|
|
* nmea2000_mag_var_set_source_reserved - Set the source and reserved fields
|
|
* @packet: Pointer to the NMEA2000 magnetic variation packet
|
|
* @source: Source of magnetic variation (4 bits)
|
|
* @reserved: Reserved field value (4 bits)
|
|
*/
|
|
|
|
static inline void
|
|
nmea2000_mag_var_set_source_reserved(struct nmea2000_mag_var_packet *packet,
|
|
enum magnetic_variation_source source,
|
|
uint8_t reserved)
|
|
{
|
|
packet->source_reserved = FIELD_PREP(NMEA2000_MAG_VAR_SOURCE_MASK,
|
|
source) |
|
|
FIELD_PREP(NMEA2000_MAG_VAR_RESERVED_MASK,
|
|
reserved);
|
|
}
|
|
|
|
/**
|
|
* nmea2000_mag_var_get_age_of_service - Get the age of service
|
|
* @packet: Pointer to the NMEA2000 magnetic variation packet
|
|
*
|
|
* Return: UTC date in days since January 1, 1970
|
|
*/
|
|
static inline uint32_t
|
|
nmea2000_mag_var_get_age_of_service(const struct nmea2000_mag_var_packet *packet)
|
|
{
|
|
return le32toh(packet->age_of_service);
|
|
}
|
|
|
|
/**
|
|
* nmea2000_mag_var_set_age_of_service - Set the age of service
|
|
* @packet: Pointer to the NMEA2000 magnetic variation packet
|
|
* @age: UTC date in days since January 1, 1970
|
|
*/
|
|
static inline void
|
|
nmea2000_mag_var_set_age_of_service(struct nmea2000_mag_var_packet *packet,
|
|
uint32_t age)
|
|
{
|
|
packet->age_of_service = htole32(age);
|
|
}
|
|
|
|
/**
|
|
* nmea2000_mag_var_get_variation - Get the magnetic variation
|
|
* @packet: Pointer to the NMEA2000 magnetic variation packet
|
|
*
|
|
* Return: Magnetic variation in tenths of degrees (positive = Easterly,
|
|
* negative = Westerly)
|
|
*/
|
|
static inline uint16_t
|
|
nmea2000_mag_var_get_variation(const struct nmea2000_mag_var_packet *packet)
|
|
{
|
|
return le16toh(packet->variation);
|
|
}
|
|
|
|
/**
|
|
* nmea2000_mag_var_set_variation - Set the magnetic variation
|
|
* @packet: Pointer to the NMEA2000 magnetic variation packet
|
|
* @variation: Magnetic variation in tenths of degrees (positive = Easterly,
|
|
* negative = Westerly)
|
|
*/
|
|
static inline void
|
|
nmea2000_mag_var_set_variation(struct nmea2000_mag_var_packet *packet,
|
|
uint16_t variation)
|
|
{
|
|
packet->variation = htole16(variation);
|
|
}
|
|
|
|
/* NMEA 2000 - PGN 129025 - Position, Rapid Update */
|
|
#define NMEA2000_PGN_POSITION_RAPID 0x1F801 /* 129025 */
|
|
|
|
#define NMEA2000_POSITION_RAPID_PRIO_DEFAULT 6
|
|
#define NMEA2000_POSITION_RAPID_MAX_TRANSFER_LENGTH \
|
|
sizeof(struct nmea2000_position_rapid_packet)
|
|
#define NMEA2000_POSITION_RAPID_REPETITION_RATE_MS 200
|
|
#define NMEA2000_POSITION_RAPID_JITTER_MS 50
|
|
|
|
/**
|
|
* struct nmea2000_position_rapid_packet - Represents the PGN 129025 Position,
|
|
* Rapid Update packet
|
|
*
|
|
* @latitude: Latitude in 1e-7 degrees ("-" = south, "+" = north)
|
|
* @longitude: Longitude in 1e-7 degrees ("-" = west, "+" = east)
|
|
*
|
|
* This structure defines the fields for the Position, Rapid Update packet.
|
|
*/
|
|
struct nmea2000_position_rapid_packet {
|
|
__le32 latitude; /* SPN 263 */
|
|
__le32 longitude; /* SPN 264 */
|
|
} __attribute__((__packed__));
|
|
|
|
/**
|
|
* nmea2000_position_get_latitude - Get the latitude from the packet
|
|
* @packet: Pointer to the NMEA2000 position rapid update packet
|
|
*
|
|
* Return: Latitude in degrees as a signed 32-bit integer
|
|
*/
|
|
static inline int32_t
|
|
nmea2000_position_get_latitude(const struct nmea2000_position_rapid_packet *packet)
|
|
{
|
|
return le32toh(packet->latitude);
|
|
}
|
|
|
|
/**
|
|
* nmea2000_position_set_latitude - Set the latitude in the packet
|
|
* @packet: Pointer to the NMEA2000 position rapid update packet
|
|
* @latitude: Latitude in degrees as a signed 32-bit integer
|
|
*/
|
|
static inline void
|
|
nmea2000_position_set_latitude(struct nmea2000_position_rapid_packet *packet,
|
|
int32_t latitude)
|
|
{
|
|
packet->latitude = htole32(latitude);
|
|
}
|
|
|
|
/**
|
|
* nmea2000_position_get_longitude - Get the longitude from the packet
|
|
* @packet: Pointer to the NMEA2000 position rapid update packet
|
|
*
|
|
* Return: Longitude in degrees as a signed 32-bit integer
|
|
*/
|
|
static inline int32_t
|
|
nmea2000_position_get_longitude(const struct nmea2000_position_rapid_packet *packet)
|
|
{
|
|
return le32toh(packet->longitude);
|
|
}
|
|
|
|
/**
|
|
* nmea2000_position_set_longitude - Set the longitude in the packet
|
|
* @packet: Pointer to the NMEA2000 position rapid update packet
|
|
* @longitude: Longitude in degrees as a signed 32-bit integer
|
|
*/
|
|
static inline void
|
|
nmea2000_position_set_longitude(struct nmea2000_position_rapid_packet *packet,
|
|
int32_t longitude)
|
|
{
|
|
packet->longitude = htole32(longitude);
|
|
}
|
|
|
|
/* NMEA 2000 - PGN 129026 - COG and SOG, Rapid Update */
|
|
#define NMEA2000_PGN_COG_SOG_RAPID 0x1F802 /* 129026 */
|
|
|
|
#define NMEA2000_COG_SOG_RAPID_PRIO_DEFAULT 6
|
|
#define NMEA2000_COG_SOG_RAPID_MAX_TRANSFER_LENGTH \
|
|
sizeof(struct nmea2000_cog_sog_rapid_packet)
|
|
#define NMEA2000_COG_SOG_RAPID_REPETITION_RATE_MS 250
|
|
#define NMEA2000_COG_SOG_RAPID_JITTER_MS 50
|
|
|
|
#define NMEA2000_COG_SOG_REF_MASK GENMASK(1, 0)
|
|
/**
|
|
* enum nmea2000_cog_reference - Reference for Course Over Ground (COG)
|
|
* @NMEA2000_COG_REFERENCE_TRUE: True reference
|
|
* @NMEA2000_COG_REFERENCE_MAGNETIC: Magnetic reference
|
|
* @NMEA2000_COG_REFERENCE_ERROR: Error
|
|
*/
|
|
enum nmea2000_cog_reference {
|
|
NMEA2000_COG_REFERENCE_TRUE = 0,
|
|
NMEA2000_COG_REFERENCE_MAGNETIC = 1,
|
|
NMEA2000_COG_REFERENCE_ERROR = 2,
|
|
};
|
|
|
|
#define NMEA2000_COG_SOG_RES1_MASK GENMASK(7, 2)
|
|
|
|
/**
|
|
* struct nmea2000_cog_sog_rapid_packet - Represents the PGN 129026 COG and SOG,
|
|
* Rapid Update packet
|
|
*
|
|
* @sid: Sequence identifier for correlating related PGNs.
|
|
* @cog_ref_res1: Encodes the COG reference and reserved1 fields (8 bits).
|
|
* - Bits 0-1: COG reference (2 bits).
|
|
* - 0: True
|
|
* - 1: Magnetic
|
|
* - 2: Error
|
|
* - Bits 2-7: Reserved1 field (6 bits).
|
|
* - Reserved for future use, typically set to 0xFF.
|
|
* @cog: Course Over Ground in 1e-4 radians
|
|
* @sog: Speed Over Ground in 1e-2 m/s
|
|
* @reserved2: Reserved field, set to 0xFFFF.
|
|
*
|
|
* This structure defines the fields for the COG and SOG, Rapid Update packet.
|
|
*/
|
|
struct nmea2000_cog_sog_rapid_packet {
|
|
uint8_t sid;
|
|
uint8_t cog_ref_res1;
|
|
__le16 cog;
|
|
__le16 sog;
|
|
uint16_t reserved2;
|
|
} __attribute__((__packed__));
|
|
|
|
/**
|
|
* nmea2000_cog_sog_get_sid - Get the sequence identifier (SID)
|
|
* @packet: Pointer to the NMEA2000 COG and SOG rapid update packet
|
|
*
|
|
* Return: Sequence identifier (8 bits)
|
|
*/
|
|
static inline uint8_t
|
|
nmea2000_cog_sog_get_sid(const struct nmea2000_cog_sog_rapid_packet *packet)
|
|
{
|
|
return packet->sid;
|
|
}
|
|
|
|
/**
|
|
* nmea2000_cog_sog_set_sid - Set the sequence identifier (SID)
|
|
* @packet: Pointer to the NMEA2000 COG and SOG rapid update packet
|
|
* @sid: Sequence identifier to set (8 bits)
|
|
*/
|
|
static inline void
|
|
nmea2000_cog_sog_set_sid(struct nmea2000_cog_sog_rapid_packet *packet,
|
|
uint8_t sid)
|
|
{
|
|
packet->sid = sid;
|
|
}
|
|
|
|
/**
|
|
* nmea2000_cog_sog_get_cog_reference - Extract the COG reference
|
|
* @packet: Pointer to the NMEA2000 COG and SOG rapid update packet
|
|
*
|
|
* Return: COG reference (2 bits)
|
|
*/
|
|
static inline uint8_t
|
|
nmea2000_cog_sog_get_cog_reference(const struct nmea2000_cog_sog_rapid_packet *packet)
|
|
{
|
|
return FIELD_GET(NMEA2000_COG_SOG_REF_MASK, packet->cog_ref_res1);
|
|
}
|
|
|
|
/**
|
|
* nmea2000_cog_sog_set_cog_ref_res1 - Set the COG reference and reserved1 fields
|
|
* @packet: Pointer to the NMEA2000 COG and SOG rapid update packet
|
|
* @cog_reference: COG reference value (2 bits)
|
|
* @reserved1: Reserved1 value (6 bits)
|
|
*/
|
|
static inline void
|
|
nmea2000_cog_sog_set_cog_ref_res1(struct nmea2000_cog_sog_rapid_packet *packet,
|
|
enum nmea2000_cog_reference cog_reference,
|
|
uint8_t reserved1)
|
|
{
|
|
packet->cog_ref_res1 = FIELD_PREP(NMEA2000_COG_SOG_REF_MASK,
|
|
cog_reference) |
|
|
FIELD_PREP(NMEA2000_COG_SOG_RES1_MASK,
|
|
reserved1);
|
|
}
|
|
|
|
/**
|
|
* nmea2000_cog_sog_get_cog - Get the Course Over Ground (COG)
|
|
* @packet: Pointer to the NMEA2000 COG and SOG rapid update packet
|
|
*
|
|
* Return: COG in 1e-4 radians
|
|
*/
|
|
static inline uint16_t
|
|
nmea2000_cog_sog_get_cog(const struct nmea2000_cog_sog_rapid_packet *packet)
|
|
{
|
|
return le16toh(packet->cog);
|
|
}
|
|
|
|
/**
|
|
* nmea2000_cog_sog_set_cog - Set the Course Over Ground (COG)
|
|
* @packet: Pointer to the NMEA2000 COG and SOG rapid update packet
|
|
* @cog: COG value in 1e-4 radians
|
|
*/
|
|
static inline void
|
|
nmea2000_cog_sog_set_cog(struct nmea2000_cog_sog_rapid_packet *packet,
|
|
uint16_t cog)
|
|
{
|
|
packet->cog = htole16(cog);
|
|
}
|
|
|
|
/**
|
|
* nmea2000_cog_sog_get_sog - Get the Speed Over Ground (SOG)
|
|
* @packet: Pointer to the NMEA2000 COG and SOG rapid update packet
|
|
*
|
|
* Return: SOG in 1e-2 m/s
|
|
*/
|
|
static inline uint16_t
|
|
nmea2000_cog_sog_get_sog(const struct nmea2000_cog_sog_rapid_packet *packet)
|
|
{
|
|
return le16toh(packet->sog);
|
|
}
|
|
|
|
/**
|
|
* nmea2000_cog_sog_set_sog - Set the Speed Over Ground (SOG)
|
|
* @packet: Pointer to the NMEA2000 COG and SOG rapid update packet
|
|
* @sog: SOG value in 1e-2 m/s
|
|
*/
|
|
static inline void
|
|
nmea2000_cog_sog_set_sog(struct nmea2000_cog_sog_rapid_packet *packet,
|
|
uint16_t sog)
|
|
{
|
|
packet->sog = htole16(sog);
|
|
}
|
|
|
|
/* NMEA 2000 - PGN 129029 - GNSS Position Data */
|
|
#define NMEA2000_PGN_GNSS_POSITION_DATA 0x1F805 /* 129029 */
|
|
|
|
#define NMEA2000_GNSS_POSITION_DATA_PRIO_DEFAULT 6
|
|
#define NMEA2000_GNSS_POSITION_DATA_MAX_TRANSFER_LENGTH \
|
|
sizeof(struct nmea2000_gnss_position_data_packet)
|
|
#define NMEA2000_GNSS_POSITION_DATA_REPETITION_RATE_MS 1000
|
|
#define NMEA2000_GNSS_POSITION_DATA_JITTER_MS 100
|
|
|
|
#define NMEA2000_GNSS_TYPE_MASK GENMASK(3, 0)
|
|
/**
|
|
* enum nmea2000_gnss_type - Types of GNSS systems
|
|
* @GNSS_TYPE_GPS: GPS
|
|
* @GNSS_TYPE_GLONASS: GLONASS
|
|
* @GNSS_TYPE_GPS_GLONASS: Combined GPS and GLONASS
|
|
* @GNSS_TYPE_GPS_SBAS_WAAS: GPS with SBAS/WAAS
|
|
* @GNSS_TYPE_GPS_SBAS_WAAS_GLONASS: Combined GPS, SBAS/WAAS, and GLONASS
|
|
* @GNSS_TYPE_CHAYKA: Chayka navigation system
|
|
* @GNSS_TYPE_INTEGRATED: Integrated navigation
|
|
* @GNSS_TYPE_SURVEYED: Surveyed position
|
|
* @GNSS_TYPE_GALILEO: Galileo navigation system
|
|
*/
|
|
enum nmea2000_gnss_type {
|
|
GNSS_TYPE_GPS = 0,
|
|
GNSS_TYPE_GLONASS = 1,
|
|
GNSS_TYPE_GPS_GLONASS = 2,
|
|
GNSS_TYPE_GPS_SBAS_WAAS = 3,
|
|
GNSS_TYPE_GPS_SBAS_WAAS_GLONASS = 4,
|
|
GNSS_TYPE_CHAYKA = 5,
|
|
GNSS_TYPE_INTEGRATED = 6,
|
|
GNSS_TYPE_SURVEYED = 7,
|
|
GNSS_TYPE_GALILEO = 8,
|
|
};
|
|
|
|
#define NMEA2000_GNSS_METHOD_MASK GENMASK(7, 4)
|
|
/**
|
|
* enum nmea2000_gnss_method - GNSS methods
|
|
* @GNSS_METHOD_NO_GNSS: No GNSS
|
|
* @GNSS_METHOD_GNSS_FIX: GNSS fix
|
|
* @GNSS_METHOD_DGNSS_FIX: Differential GNSS (DGNSS) fix
|
|
* @GNSS_METHOD_PRECISE_GNSS: Precise GNSS fix
|
|
* @GNSS_METHOD_RTK_FIXED_INT: RTK fixed integer solution
|
|
* @GNSS_METHOD_RTK_FLOAT: RTK float solution
|
|
* @GNSS_METHOD_ESTIMATED: Estimated (Dead Reckoning) mode
|
|
* @GNSS_METHOD_MANUAL_INPUT: Manual input mode
|
|
* @GNSS_METHOD_SIMULATE_MODE: Simulated GNSS mode
|
|
*/
|
|
enum nmea2000_gnss_method {
|
|
GNSS_METHOD_NO_GNSS = 0,
|
|
GNSS_METHOD_GNSS_FIX = 1,
|
|
GNSS_METHOD_DGNSS_FIX = 2,
|
|
GNSS_METHOD_PRECISE_GNSS = 3,
|
|
GNSS_METHOD_RTK_FIXED_INT = 4,
|
|
GNSS_METHOD_RTK_FLOAT = 5,
|
|
GNSS_METHOD_ESTIMATED = 6,
|
|
GNSS_METHOD_MANUAL_INPUT = 7,
|
|
GNSS_METHOD_SIMULATE_MODE = 8,
|
|
};
|
|
|
|
#define NMEA2000_INTEGRITY_MASK GENMASK(1, 0)
|
|
/**
|
|
* enum nmea2000_integrity_status - Integrity status values
|
|
* @NMEA2000_INTEGRITY_NO_CHECKING: No integrity checking
|
|
* @NMEA2000_INTEGRITY_SAFE: Safe integrity status
|
|
* @NMEA2000_INTEGRITY_CAUTION: Caution integrity status
|
|
*/
|
|
enum nmea2000_integrity_status {
|
|
NMEA2000_INTEGRITY_NO_CHECKING = 0,
|
|
NMEA2000_INTEGRITY_SAFE = 1,
|
|
NMEA2000_INTEGRITY_CAUTION = 2,
|
|
};
|
|
|
|
#define NMEA2000_RESERVED_MASK GENMASK(7, 2)
|
|
|
|
/**
|
|
* struct nmea2000_gnss_position_data_packet - Represents the PGN 129029 GNSS
|
|
* Position Data packet
|
|
*
|
|
* @sid: Sequence identifier for correlating related PGNs (8 bits).
|
|
* @date: UTC Date in days since January 1, 1970 (16 bits).
|
|
* @time: UTC Time in 0.0001 seconds since midnight (32 bits).
|
|
* @latitude: Latitude in 1e-16 degrees ("-" = south, "+" = north) (64 bits).
|
|
* @longitude: Longitude in 1e-16 degrees ("-" = west, "+" = east) (64 bits).
|
|
* @altitude: Altitude in 1e-6 meters above WGS-84 (64 bits).
|
|
* @gnss_info: Encodes GNSS system type and GNSS method in a single byte.
|
|
* - Bits 0-3: GNSS system type. Possible values:
|
|
* - 0: GPS
|
|
* - 1: GLONASS
|
|
* - 2: GPS+GLONASS
|
|
* - 3: GPS+SBAS/WAAS
|
|
* - 4: GPS+SBAS/WAAS+GLONASS
|
|
* - 5: Chayka
|
|
* - 6: Integrated
|
|
* - 7: Surveyed
|
|
* - 8: Galileo
|
|
* - Bits 4-7: GNSS method. Possible values:
|
|
* - 0: No GNSS
|
|
* - 1: GNSS fix
|
|
* - 2: DGNSS fix
|
|
* - 3: Precise GNSS
|
|
* - 4: RTK Fixed Integer
|
|
* - 5: RTK float
|
|
* - 6: Estimated (DR) mode
|
|
* - 7: Manual Input
|
|
* - 8: Simulate mode
|
|
*
|
|
* @status: Encodes integrity status and reserved bits in a single byte.
|
|
* - Bits 0-1: Integrity status. Possible values:
|
|
* - 0: No integrity checking
|
|
* - 1: Safe
|
|
* - 2: Caution
|
|
* - Bits 2-7: Reserved field.
|
|
* @num_svs: Number of satellites used in the solution (8 bits).
|
|
* @hdop: Horizontal Dilution of Precision (1e-2) (16 bits).
|
|
* @pdop: Positional Dilution of Precision (1e-2) (16 bits).
|
|
* @geoidal_separation: Geoidal Separation in 0.01 meters (32 bits).
|
|
* @num_ref_stations: Number of reference stations (8 bits).
|
|
*
|
|
* This structure defines the fields for the GNSS Position Data packet.
|
|
*/
|
|
struct nmea2000_gnss_position_data_packet {
|
|
uint8_t sid;
|
|
__le16 date;
|
|
__le32 time;
|
|
__le64 latitude;
|
|
__le64 longitude;
|
|
__le64 altitude;
|
|
uint8_t gnss_info;
|
|
uint8_t status;
|
|
uint8_t num_svs;
|
|
__le16 hdop;
|
|
__le16 pdop;
|
|
__le32 geoidal_separation;
|
|
uint8_t num_ref_stations;
|
|
} __attribute__((__packed__));
|
|
|
|
/**
|
|
* nmea2000_gnss_get_sid - Get the sequence identifier
|
|
* @packet: Pointer to the NMEA2000 GNSS position data packet
|
|
*
|
|
* Return: Sequence identifier (8 bits)
|
|
*/
|
|
static inline uint8_t
|
|
nmea2000_gnss_get_sid(const struct nmea2000_gnss_position_data_packet *packet)
|
|
{
|
|
return packet->sid;
|
|
}
|
|
|
|
/**
|
|
* nmea2000_gnss_set_sid - Set the sequence identifier
|
|
* @packet: Pointer to the NMEA2000 GNSS position data packet
|
|
* @sid: Sequence identifier to set
|
|
*/
|
|
static inline void
|
|
nmea2000_gnss_set_sid(struct nmea2000_gnss_position_data_packet *packet,
|
|
uint8_t sid)
|
|
{
|
|
packet->sid = sid;
|
|
}
|
|
|
|
/**
|
|
* nmea2000_gnss_get_date - Get the UTC date
|
|
* @packet: Pointer to the NMEA2000 GNSS position data packet
|
|
*
|
|
* Return: UTC date in days since January 1, 1970
|
|
*/
|
|
static inline uint16_t
|
|
nmea2000_gnss_get_date(const struct nmea2000_gnss_position_data_packet *packet)
|
|
{
|
|
return le16toh(packet->date);
|
|
}
|
|
|
|
/**
|
|
* nmea2000_gnss_set_date - Set the UTC date
|
|
* @packet: Pointer to the NMEA2000 GNSS position data packet
|
|
* @date: UTC date in days since January 1, 1970
|
|
*/
|
|
static inline void
|
|
nmea2000_gnss_set_date(struct nmea2000_gnss_position_data_packet *packet,
|
|
uint16_t date)
|
|
{
|
|
packet->date = htole16(date);
|
|
}
|
|
|
|
/**
|
|
* nmea2000_gnss_get_time - Get the UTC time
|
|
* @packet: Pointer to the NMEA2000 GNSS position data packet
|
|
*
|
|
* Return: UTC time in 0.0001 seconds since midnight
|
|
*/
|
|
static inline uint32_t
|
|
nmea2000_gnss_get_time(const struct nmea2000_gnss_position_data_packet *packet)
|
|
{
|
|
return le32toh(packet->time);
|
|
}
|
|
|
|
/**
|
|
* nmea2000_gnss_set_time - Set the UTC time
|
|
* @packet: Pointer to the NMEA2000 GNSS position data packet
|
|
* @time: UTC time in 0.0001 seconds since midnight
|
|
*/
|
|
static inline void
|
|
nmea2000_gnss_set_time(struct nmea2000_gnss_position_data_packet *packet,
|
|
uint32_t time)
|
|
{
|
|
packet->time = htole32(time);
|
|
}
|
|
|
|
/**
|
|
* nmea2000_gnss_get_latitude - Get the latitude
|
|
* @packet: Pointer to the NMEA2000 GNSS position data packet
|
|
*
|
|
* Return: Latitude in 1e-16 degrees (int64_t)
|
|
*/
|
|
static inline int64_t
|
|
nmea2000_gnss_get_latitude(const struct nmea2000_gnss_position_data_packet *packet)
|
|
{
|
|
return le64toh(packet->latitude);
|
|
}
|
|
|
|
/**
|
|
* nmea2000_gnss_set_latitude - Set the latitude
|
|
* @packet: Pointer to the NMEA2000 GNSS position data packet
|
|
* @latitude: Latitude in 1e-16 degrees (int64_t)
|
|
*/
|
|
static inline void
|
|
nmea2000_gnss_set_latitude(struct nmea2000_gnss_position_data_packet *packet,
|
|
int64_t latitude)
|
|
{
|
|
packet->latitude = htole64(latitude);
|
|
}
|
|
|
|
/**
|
|
* nmea2000_gnss_get_longitude - Get the longitude
|
|
* @packet: Pointer to the NMEA2000 GNSS position data packet
|
|
*
|
|
* Return: Longitude in 1e-16 degrees (int64_t)
|
|
*/
|
|
static inline int64_t
|
|
nmea2000_gnss_get_longitude(const struct nmea2000_gnss_position_data_packet *packet)
|
|
{
|
|
return le64toh(packet->longitude);
|
|
}
|
|
|
|
/**
|
|
* nmea2000_gnss_set_longitude - Set the longitude
|
|
* @packet: Pointer to the NMEA2000 GNSS position data packet
|
|
* @longitude: Longitude in 1e-16 degrees (int64_t)
|
|
*/
|
|
static inline void
|
|
nmea2000_gnss_set_longitude(struct nmea2000_gnss_position_data_packet *packet,
|
|
int64_t longitude)
|
|
{
|
|
packet->longitude = htole64(longitude);
|
|
}
|
|
|
|
/**
|
|
* nmea2000_gnss_get_altitude - Get the altitude
|
|
* @packet: Pointer to the NMEA2000 GNSS position data packet
|
|
*
|
|
* Return: Altitude in 1e-6 meters above WGS-84 (int64_t)
|
|
*/
|
|
static inline int64_t
|
|
nmea2000_gnss_get_altitude(const struct nmea2000_gnss_position_data_packet *packet)
|
|
{
|
|
return le64toh(packet->altitude);
|
|
}
|
|
|
|
/**
|
|
* nmea2000_gnss_set_altitude - Set the altitude
|
|
* @packet: Pointer to the NMEA2000 GNSS position data packet
|
|
* @altitude: Altitude in 1e-6 meters above WGS-84 (int64_t)
|
|
*/
|
|
static inline void
|
|
nmea2000_gnss_set_altitude(struct nmea2000_gnss_position_data_packet *packet,
|
|
int64_t altitude)
|
|
{
|
|
packet->altitude = htole64(altitude);
|
|
}
|
|
|
|
/**
|
|
* nmea2000_get_gnss_type - Extract GNSS type from the packet
|
|
* @packet: Pointer to the NMEA2000 GNSS position data packet
|
|
*
|
|
* Return: GNSS type (lower 4 bits of gnss_info field)
|
|
*/
|
|
static inline uint8_t
|
|
nmea2000_get_gnss_type(const struct nmea2000_gnss_position_data_packet *packet)
|
|
{
|
|
return FIELD_GET(NMEA2000_GNSS_TYPE_MASK, packet->gnss_info);
|
|
}
|
|
|
|
/**
|
|
* nmea2000_get_gnss_method - Extract GNSS method from the packet
|
|
* @packet: Pointer to the NMEA2000 GNSS position data packet
|
|
*
|
|
* Return: GNSS method (upper 4 bits of gnss_info field)
|
|
*/
|
|
static inline uint8_t
|
|
nmea2000_get_gnss_method(const struct nmea2000_gnss_position_data_packet *packet)
|
|
{
|
|
return FIELD_GET(NMEA2000_GNSS_METHOD_MASK, packet->gnss_info);
|
|
}
|
|
|
|
/**
|
|
* nmea2000_set_gnss_info - Set GNSS type and method in the packet
|
|
* @packet: Pointer to the NMEA2000 GNSS position data packet
|
|
* @gnss_type: GNSS type to set
|
|
* @gnss_method: GNSS method to set
|
|
*/
|
|
static inline void
|
|
nmea2000_set_gnss_info(struct nmea2000_gnss_position_data_packet *packet,
|
|
enum nmea2000_gnss_type gnss_type,
|
|
enum nmea2000_gnss_method gnss_method)
|
|
{
|
|
packet->gnss_info = FIELD_PREP(NMEA2000_GNSS_TYPE_MASK, gnss_type) |
|
|
FIELD_PREP(NMEA2000_GNSS_METHOD_MASK, gnss_method);
|
|
}
|
|
|
|
/**
|
|
* nmea2000_get_integrity - Extract integrity status from the packet
|
|
* @packet: Pointer to the NMEA2000 GNSS position data packet
|
|
*
|
|
* Return: Integrity status (lower 2 bits of status field)
|
|
*/
|
|
static inline uint8_t
|
|
nmea2000_get_integrity(const struct nmea2000_gnss_position_data_packet *packet)
|
|
{
|
|
return FIELD_GET(NMEA2000_INTEGRITY_MASK, packet->status);
|
|
}
|
|
|
|
/**
|
|
* nmea2000_set_status - Set integrity and reserved fields in the packet
|
|
* @packet: Pointer to the NMEA2000 GNSS position data packet
|
|
* @integrity: Integrity status to set
|
|
* @reserved: Reserved value to set
|
|
*/
|
|
static inline void
|
|
nmea2000_set_status(struct nmea2000_gnss_position_data_packet *packet,
|
|
enum nmea2000_integrity_status integrity, uint8_t reserved)
|
|
{
|
|
packet->status = FIELD_PREP(NMEA2000_INTEGRITY_MASK, integrity) |
|
|
FIELD_PREP(NMEA2000_RESERVED_MASK, reserved);
|
|
}
|
|
|
|
/**
|
|
* nmea2000_gnss_get_num_svs - Get the number of satellites used in the solution
|
|
* @packet: Pointer to the NMEA2000 GNSS position data packet
|
|
*
|
|
* Return: Number of satellites used (8 bits)
|
|
*/
|
|
static inline uint8_t
|
|
nmea2000_gnss_get_num_svs(const struct nmea2000_gnss_position_data_packet *packet)
|
|
{
|
|
return packet->num_svs;
|
|
}
|
|
|
|
/**
|
|
* nmea2000_gnss_set_num_svs - Set the number of satellites used in the solution
|
|
* @packet: Pointer to the NMEA2000 GNSS position data packet
|
|
* @num_svs: Number of satellites used (8 bits)
|
|
*/
|
|
static inline void
|
|
nmea2000_gnss_set_num_svs(struct nmea2000_gnss_position_data_packet *packet,
|
|
uint8_t num_svs)
|
|
{
|
|
packet->num_svs = num_svs;
|
|
}
|
|
|
|
/**
|
|
* nmea2000_gnss_get_hdop - Get the Horizontal Dilution of Precision (HDOP)
|
|
* @packet: Pointer to the NMEA2000 GNSS position data packet
|
|
*
|
|
* Return: HDOP in 1e-2 units (uint16_t)
|
|
*/
|
|
static inline uint16_t
|
|
nmea2000_gnss_get_hdop(const struct nmea2000_gnss_position_data_packet *packet)
|
|
{
|
|
return le16toh(packet->hdop);
|
|
}
|
|
|
|
/**
|
|
* nmea2000_gnss_set_hdop - Set the Horizontal Dilution of Precision (HDOP)
|
|
* @packet: Pointer to the NMEA2000 GNSS position data packet
|
|
* @hdop: HDOP in 1e-2 units (uint16_t)
|
|
*/
|
|
static inline void
|
|
nmea2000_gnss_set_hdop(struct nmea2000_gnss_position_data_packet *packet,
|
|
uint16_t hdop)
|
|
{
|
|
packet->hdop = htole16(hdop);
|
|
}
|
|
|
|
/**
|
|
* nmea2000_gnss_get_pdop - Get the Positional Dilution of Precision (PDOP)
|
|
* @packet: Pointer to the NMEA2000 GNSS position data packet
|
|
*
|
|
* Return: PDOP in 1e-2 units (uint16_t)
|
|
*/
|
|
static inline uint16_t
|
|
nmea2000_gnss_get_pdop(const struct nmea2000_gnss_position_data_packet *packet)
|
|
{
|
|
return le16toh(packet->pdop);
|
|
}
|
|
|
|
/**
|
|
* nmea2000_gnss_set_pdop - Set the Positional Dilution of Precision (PDOP)
|
|
* @packet: Pointer to the NMEA2000 GNSS position data packet
|
|
* @pdop: PDOP in 1e-2 units (uint16_t)
|
|
*/
|
|
static inline void
|
|
nmea2000_gnss_set_pdop(struct nmea2000_gnss_position_data_packet *packet,
|
|
uint16_t pdop)
|
|
{
|
|
packet->pdop = htole16(pdop);
|
|
}
|
|
|
|
/**
|
|
* nmea2000_gnss_get_geoidal_separation - Get the Geoidal Separation
|
|
* @packet: Pointer to the NMEA2000 GNSS position data packet
|
|
*
|
|
* Return: Geoidal Separation in 0.01 meters (uint32_t)
|
|
*/
|
|
static inline uint32_t
|
|
nmea2000_gnss_get_geoidal_separation(const struct nmea2000_gnss_position_data_packet *packet)
|
|
{
|
|
return le32toh(packet->geoidal_separation);
|
|
}
|
|
|
|
/**
|
|
* nmea2000_gnss_set_geoidal_separation - Set the Geoidal Separation
|
|
* @packet: Pointer to the NMEA2000 GNSS position data packet
|
|
* @geoidal_separation: Geoidal Separation in 0.01 meters (uint32_t)
|
|
*/
|
|
static inline void
|
|
nmea2000_gnss_set_geoidal_separation(struct nmea2000_gnss_position_data_packet *packet,
|
|
uint32_t geoidal_separation)
|
|
{
|
|
packet->geoidal_separation = htole32(geoidal_separation);
|
|
}
|
|
|
|
/**
|
|
* nmea2000_gnss_get_num_ref_stations - Get the number of reference stations
|
|
* @packet: Pointer to the NMEA2000 GNSS position data packet
|
|
*
|
|
* Return: Number of reference stations (8 bits)
|
|
*/
|
|
static inline uint8_t
|
|
nmea2000_gnss_get_num_ref_stations(const struct nmea2000_gnss_position_data_packet *packet)
|
|
{
|
|
return packet->num_ref_stations;
|
|
}
|
|
|
|
/**
|
|
* nmea2000_gnss_set_num_ref_stations - Set the number of reference stations
|
|
* @packet: Pointer to the NMEA2000 GNSS position data packet
|
|
* @num_ref_stations: Number of reference stations (8 bits)
|
|
*/
|
|
static inline void
|
|
nmea2000_gnss_set_num_ref_stations(struct nmea2000_gnss_position_data_packet *packet,
|
|
uint8_t num_ref_stations)
|
|
{
|
|
packet->num_ref_stations = num_ref_stations;
|
|
}
|
|
|
|
#define NMEA2000_REF_STATION_TYPE_MASK GENMASK(3, 0)
|
|
#define NMEA2000_REF_STATION_ID_MASK GENMASK(15, 4)
|
|
|
|
/**
|
|
* struct nmea2000_reference_station - Represents the reference station fields
|
|
* in PGN 129029
|
|
*
|
|
* @type_id: Encodes the type and ID of the reference station (16 bits).
|
|
* - Bits 0-3: Type of reference station (4 bits).
|
|
* - Values range from 0 to 13, indicating different types of reference
|
|
* stations.
|
|
* - Bits 4-15: Reference Station ID (12 bits).
|
|
* - Unique identifier for the reference station.
|
|
* @dgnss_age: Age of DGNSS corrections in 0.01 seconds (16 bits).
|
|
* - Indicates the age of the differential GNSS corrections.
|
|
*
|
|
* This structure defines the optional repeating fields for reference stations
|
|
* in the GNSS Position Data packet. Bitfield operations on the type and ID
|
|
* are handled using FIELD_GET and FIELD_PREP macros for clarity and safety.
|
|
*/
|
|
struct nmea2000_reference_station {
|
|
__le16 type_id;
|
|
__le16 dgnss_age;
|
|
} __attribute__((__packed__));
|
|
|
|
/**
|
|
* nmea2000_ref_station_get_type - Extract the type of reference station
|
|
* @station: Pointer to the NMEA2000 reference station structure
|
|
*
|
|
* Return: Type of the reference station (4 bits)
|
|
*/
|
|
static inline uint8_t
|
|
nmea2000_ref_station_get_type(const struct nmea2000_reference_station *station)
|
|
{
|
|
return FIELD_GET(NMEA2000_REF_STATION_TYPE_MASK,
|
|
le16toh(station->type_id));
|
|
}
|
|
|
|
/**
|
|
* nmea2000_ref_station_get_id - Extract the reference station ID
|
|
* @station: Pointer to the NMEA2000 reference station structure
|
|
*
|
|
* Return: Reference station ID (12 bits)
|
|
*/
|
|
static inline uint16_t
|
|
nmea2000_ref_station_get_id(const struct nmea2000_reference_station *station)
|
|
{
|
|
return FIELD_GET(NMEA2000_REF_STATION_ID_MASK,
|
|
le16toh(station->type_id));
|
|
}
|
|
|
|
/**
|
|
* nmea2000_ref_station_set_type_id - Set type and ID of reference station
|
|
* @station: Pointer to the NMEA2000 reference station structure
|
|
* @type: Type of the reference station (4 bits)
|
|
* @id: Reference station ID (12 bits)
|
|
*/
|
|
static inline void
|
|
nmea2000_ref_station_set_type_id(struct nmea2000_reference_station *station,
|
|
uint8_t type, uint16_t id)
|
|
{
|
|
station->type_id =
|
|
htole16(FIELD_PREP(NMEA2000_REF_STATION_TYPE_MASK, type) |
|
|
FIELD_PREP(NMEA2000_REF_STATION_ID_MASK, id));
|
|
}
|
|
|
|
/**
|
|
* nmea2000_ref_station_get_dgnss_age - Get the age of DGNSS corrections
|
|
* @station: Pointer to the NMEA2000 reference station structure
|
|
*
|
|
* Return: Age of DGNSS corrections in 0.01 seconds (16 bits)
|
|
*/
|
|
static inline uint16_t
|
|
nmea2000_ref_station_get_dgnss_age(const struct nmea2000_reference_station *station)
|
|
{
|
|
return le16toh(station->dgnss_age);
|
|
}
|
|
|
|
/**
|
|
* nmea2000_ref_station_set_dgnss_age - Set the age of DGNSS corrections
|
|
* @station: Pointer to the NMEA2000 reference station structure
|
|
* @dgnss_age: Age of DGNSS corrections in 0.01 seconds (16 bits)
|
|
*/
|
|
static inline void
|
|
nmea2000_ref_station_set_dgnss_age(struct nmea2000_reference_station *station,
|
|
uint16_t dgnss_age)
|
|
{
|
|
station->dgnss_age = htole16(dgnss_age);
|
|
}
|
|
|
|
#endif /* !_J1939_VEHICLE_POSITION_H_ */
|