Commit 449f699d authored by Xavier Piroux's avatar Xavier Piroux

converter from GPS data to raw data to store in a file on the SD

converter reverse (from raw data from file to GPS data)
converter from GPS data to GPX format
parent 65b989dc
SRCS=test_convert_files.c
OBJS=$(SRCS:.c=.o)
BIN=test_convert_files
PREREQ_SRC.1=../watch_format/watch_file_format.c
PREREQ_OBJ.1=$(notdir $(PREREQ_SRC.1:.c=.o))
PREREQ_SRC.2=../watch_format/watch_file_gpx.c
PREREQ_OBJ.2=$(notdir $(PREREQ_SRC.2:.c=.o))
PREREQ_SRCS=$(PREREQ_SRC.1) $(PREREQ_SRC.2)
PREREQ_OBJS=$(PREREQ_OBJ.1) $(PREREQ_OBJ.2)
INCLUDES=-I../watch_format
CFLAGS=-g
LIBS=
LDFLAGS=
COMPILER=gcc
ifdef VERBOSE
CFLAGS+= -DVERBOSE=1
endif
.PHONY: all clean
all: prerequis $(BIN)
clean:
rm -rf $(BINS) $(OBJS)
prerequis:
$(COMPILER) $(CFLAGS) $(INCLUDES) -o $(PREREQ_OBJ.1) -c $(PREREQ_SRC.1)
$(COMPILER) $(CFLAGS) $(INCLUDES) -o $(PREREQ_OBJ.2) -c $(PREREQ_SRC.2)
$(BIN): $(OBJS)
$(COMPILER) $(LDFLAGS) $(LIBS) -o $@ $^ $(PREREQ_OBJS)
%.o: %.c
$(COMPILER) $(CFLAGS) $(INCLUDES) -o $@ -c $^
printxavier:
@echo "SRCS = $(SRCS)"
@echo "OBJS = $(OBJS)"
@echo "BIN = $(BIN)"
@echo "PREREQ_SRCS = $(PREREQ_SRCS)"
@echo "PREREQ_OBJS = $(PREREQ_OBJS)"
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <watch_file_format.h>
#ifndef VERBOSE
#define VERBOSE 0
#endif
#define IS_VERBOSE() (VERBOSE)
static uint32_t bufferStatic[1000];
#define CHECK_DATA_BIT_PRINT(data, bit, COMMONSTRING, IFBIT, IFNOTBIT) \
printf(COMMONSTRING); \
if (data->fields_mask & (1 << bit)) { \
printf IFBIT; \
} else { \
printf IFNOTBIT; \
}
void printData(watch_format_data* data) {
printf(" time %10lu", (unsigned long) data->time_sec);
CHECK_DATA_BIT_PRINT(data, WATCH_PRESENCE_TIME_MILLIS, "", (".%03lu", (unsigned long) data->time_ms), (".---"))
CHECK_DATA_BIT_PRINT(data, WATCH_PRESENCE_LAT_GPS, " - lat ", ("% 9.4lf", data->lat_gps), ("----.----"))
CHECK_DATA_BIT_PRINT(data, WATCH_PRESENCE_LON_GPS, " - lon ", ("% 9.4lf", data->lon_gps), ("----.----"))
CHECK_DATA_BIT_PRINT(data, WATCH_PRESENCE_ALT_GPS, " - alt ", ("% 9.4lf", data->alt_gps), ("----.----"))
CHECK_DATA_BIT_PRINT(data, WATCH_PRESENCE_ALT_FROM_PRESSURE, " - alt(pres) ", ("% 9.4lf", data->alt_from_pressure), ("----.----"))
CHECK_DATA_BIT_PRINT(data, WATCH_PRESENCE_PRESSURE, " - pressure ", ("% 9.4lf", data->pressure), ("----.----"))
}
void constructData(watch_format_data* data) {
static int iFirstTime = 1;
static watch_format_data staticdata = {0};
if (iFirstTime) {
iFirstTime = 0;
staticdata.fields_mask = -1;
}
*data = staticdata;
staticdata.time_sec++;
staticdata.time_ms+=2;
staticdata.lat_gps+=1.0101;
staticdata.lon_gps+=0.0202;
staticdata.alt_gps-=1.0101;
staticdata.pressure+=1;
if (staticdata.fields_mask & (1 << WATCH_PRESENCE_PRESSURE)) {
staticdata.fields_mask ^= (1 << WATCH_PRESENCE_PRESSURE);
} else {
staticdata.fields_mask |= (1 << WATCH_PRESENCE_PRESSURE);
}
}
static uint8_t* pointer_to_save;
static uint8_t* pointer_to_read;
static uint8_t size_of_data;
void saveData(watch_format_data* data) {
uint8_t buff[size_of_data + 1];
uint32_t bytes_written;
buff[0] = WATCH_NEXT_DATA_DATA;
bytes_written = convert_data_to_file(data, &buff[1]);
{
int i;
for (i = 0 ; i < bytes_written + 1 ; i++) pointer_to_save[i] = buff[i];
}
pointer_to_save += (bytes_written + 1);
}
watch_next_data_type readNextDataType(void) {
watch_next_data_type data_type = *pointer_to_read;
pointer_to_read++;
return data_type;
}
void readData(watch_format_data* data) {
uint32_t bytes_read = convert_file_to_data(pointer_to_read, data);
pointer_to_read += bytes_read;
}
int main() {
size_of_data = watch_get_size_of_data_type(WATCH_NEXT_DATA_DATA);
printf("main() : starting. Constructing false set of data and saving it...\n");
{
//be sure the buffer is empty
uint32_t i = (sizeof(bufferStatic) / sizeof(bufferStatic[0]));
for (; i > 0 ; i--) bufferStatic[i-1] = 0;
}
{
//save the data
int i;
printf("\n\nSaving data...\n");
pointer_to_save = (uint8_t*) &bufferStatic[0];
//save preliminary info : we start a new file
*pointer_to_save = WATCH_NEXT_DATA_BEGIN;
pointer_to_save++;
for (i = 0 ; i < 20 ; i++) {
watch_format_data data;
constructData(&data);
saveData(&data);
if (IS_VERBOSE()) {
printData(&data);
printf("\n");
}
if (i % 6 == 0) {
//new lap sometimes
*pointer_to_save = WATCH_NEXT_DATA_NEWLAP;
pointer_to_save++;
if (IS_VERBOSE()) {
printf("new lap \n");
}
}
}
//save sentinel info : we finished saving data
*pointer_to_save = WATCH_NEXT_DATA_END;
pointer_to_save++;
}
{
//check we can retrieve the data
char bufferGpx[10000] = {0};
int continue_reading = 1;
int begin_happened = 0;
watch_format_data data;
uint8_t* pointer_gpx = (uint8_t*) &bufferGpx[0];
uint32_t bytes_written_gpx;
printf("\n\nRetrieving data...\n");
pointer_to_read = (uint8_t*) &bufferStatic[0];
while (continue_reading) {
watch_next_data_type data_type = readNextDataType();
switch (data_type) {
case WATCH_NEXT_DATA_BEGIN:
printf("BEGIN detected\n");
bytes_written_gpx = watch_gpx_write_header(pointer_gpx);
pointer_gpx += bytes_written_gpx;
bytes_written_gpx = watch_gpx_write_track_segment_begin(pointer_gpx);
pointer_gpx += bytes_written_gpx;
if (begin_happened) {
continue_reading = 0;
printf(" ==> already happened, this is an error !\n");
}
begin_happened = 1;
break;
case WATCH_NEXT_DATA_END:
printf("END detected\n");
bytes_written_gpx = watch_gpx_write_track_segment_end(pointer_gpx);
pointer_gpx += bytes_written_gpx;
bytes_written_gpx = watch_gpx_write_footer(pointer_gpx);
pointer_gpx += bytes_written_gpx;
continue_reading = 0;
break;
case WATCH_NEXT_DATA_DATA:
//printf("DATA detected\n");
readData(&data);
if (IS_VERBOSE()) {
printData(&data);
printf("\n");
}
bytes_written_gpx = watch_gpx_write_data(&data, pointer_gpx);
pointer_gpx += bytes_written_gpx;
break;
case WATCH_NEXT_DATA_NEWLAP:
printf("NEWLAP detected\n");
bytes_written_gpx = watch_gpx_write_track_segment_end(pointer_gpx);
pointer_gpx += bytes_written_gpx;
bytes_written_gpx = watch_gpx_write_track_segment_begin(pointer_gpx);
pointer_gpx += bytes_written_gpx;
break;
default:
printf("UNKNOWN data type, exiting...\n");
continue_reading = 0;
break;
}
if ((unsigned long) pointer_to_read > (unsigned long) (((char*) bufferStatic) + sizeof(bufferStatic))) {
printf("STOPPING : we are no more in the bufferStatic\n");
printf("pointer_to_read = %p ; &bufferStatic[0] = %p ; sizeof(bufferStatic) = %lu\n",
pointer_to_read, bufferStatic, (unsigned long) sizeof(bufferStatic));
continue_reading = 0;
}
}
printf("\n\n GPX output :\n\n%s\n", bufferGpx);
}
return 0;
}
#include <stdint.h>
#include "watch_file_format.h"
double gps_raw_to_double(uint32_t raw) {
double latitude = (raw / 8388608.0) - 180.0;
return latitude;
}
uint32_t gps_double_to_raw(double latitude) {
uint32_t raw = (latitude + 180) * 8388608;
return raw;
}
/** How watch data is saved into files */
typedef struct watch_file_format_data_private
{
uint16_t fields_mask; /*!< bit mask to know what are the available data */
uint32_t time_sec; /*!< time in seconds since epoch (from GPS or not) */
uint16_t time_ms; /*!< milliseconds time */
uint32_t raw_lat_gps; /*!< latitude in degrees */
uint32_t raw_lon_gps; /*!< longitude in degrees */
int32_t raw_alt_gps; /*!< altitude in millimeters, can be negative */
uint32_t raw_alt_from_pressure;
uint32_t raw_pressure;
//uint8_t heart_rate; /*!< we don't have such thing in the freewatch project */
} watch_file_format_data_private;
uint8_t watch_get_size_of_data_type(watch_next_data_type data_type) {
switch (data_type) {
case WATCH_NEXT_DATA_DATA:
return (sizeof(watch_file_format_data_private) / sizeof(uint8_t));
default:
return 0;
}
}
#define IS_FIELD_PRESENT(mask, pos) (mask & (1 << pos))
uint32_t convert_data_to_file(watch_format_data* data, uint8_t* dest) {
watch_file_format_data_private* raw_data = (watch_file_format_data_private*) dest;
uint16_t mask = data->fields_mask;
raw_data->fields_mask = mask;
raw_data->time_sec = data->time_sec;
raw_data->time_ms = (IS_FIELD_PRESENT(mask, WATCH_PRESENCE_TIME_MILLIS) ? data->time_ms : 0);
raw_data->raw_lat_gps = (IS_FIELD_PRESENT(mask, WATCH_PRESENCE_LAT_GPS) ? gps_double_to_raw(data->lat_gps) : 0);
raw_data->raw_lon_gps = (IS_FIELD_PRESENT(mask, WATCH_PRESENCE_LON_GPS) ? gps_double_to_raw(data->lon_gps) : 0);
raw_data->raw_alt_gps = (IS_FIELD_PRESENT(mask, WATCH_PRESENCE_ALT_GPS) ? gps_double_to_raw(data->alt_gps) : 0);
raw_data->raw_alt_from_pressure = (IS_FIELD_PRESENT(mask, WATCH_PRESENCE_ALT_FROM_PRESSURE) ? gps_double_to_raw(data->alt_from_pressure) : 0);
raw_data->raw_pressure = (IS_FIELD_PRESENT(mask, WATCH_PRESENCE_PRESSURE) ? gps_double_to_raw(data->pressure) : 0);
return watch_get_size_of_data_type(WATCH_NEXT_DATA_DATA);
}
uint32_t convert_file_to_data(uint8_t* src, watch_format_data* data) {
watch_file_format_data_private* raw_data = (watch_file_format_data_private*) src;
uint16_t mask = raw_data->fields_mask;
data->fields_mask = mask;
data->time_sec = raw_data->time_sec;
data->time_ms = (IS_FIELD_PRESENT(mask, WATCH_PRESENCE_TIME_MILLIS) ? raw_data->time_ms : 0);
data->lat_gps = (IS_FIELD_PRESENT(mask, WATCH_PRESENCE_LAT_GPS) ? gps_raw_to_double(raw_data->raw_lat_gps) : 0);
data->lon_gps = (IS_FIELD_PRESENT(mask, WATCH_PRESENCE_LON_GPS) ? gps_raw_to_double(raw_data->raw_lon_gps) : 0);
data->alt_gps = (IS_FIELD_PRESENT(mask, WATCH_PRESENCE_ALT_GPS) ? gps_raw_to_double(raw_data->raw_alt_gps) : 0);
data->alt_from_pressure = (IS_FIELD_PRESENT(mask, WATCH_PRESENCE_ALT_FROM_PRESSURE) ? gps_raw_to_double(raw_data->raw_alt_from_pressure) : 0);
data->pressure = (IS_FIELD_PRESENT(mask, WATCH_PRESENCE_PRESSURE) ? gps_raw_to_double(raw_data->raw_pressure) : 0);
return watch_get_size_of_data_type(WATCH_NEXT_DATA_DATA);
}
/*
* Copyright (C) 2014 Julian Lewis
* @author Xavier Piroux <xavierpiroux@gmail.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#ifndef __WATCH_FILE_FORMAT_H
#define __WATCH_FILE_FORMAT_H
/**
* @brief headers to read, write and interpret data stored in files
*/
#define GPS_FILE_FORMAT_VERSION 1
double gps_raw_to_double(uint32_t raw);
uint32_t gps_double_to_raw(double latitude);
typedef enum watch_next_data_type
{
WATCH_NEXT_DATA_BEGIN = 0,
WATCH_NEXT_DATA_END,
WATCH_NEXT_DATA_DATA,
WATCH_NEXT_DATA_NEWLAP
} watch_next_data_type;
uint8_t watch_get_size_of_data_type(watch_next_data_type data_type);
typedef enum watch_presence_fields_mask
{
//WATCH_PRESENCE_TIME_SEC = -1, /*!< the most basic data : is always set */
WATCH_PRESENCE_TIME_MILLIS = 0, /*!< bit set if milliseconds is available */
WATCH_PRESENCE_LAT_GPS,
WATCH_PRESENCE_LON_GPS,
WATCH_PRESENCE_ALT_GPS,
WATCH_PRESENCE_ALT_FROM_PRESSURE,
WATCH_PRESENCE_PRESSURE,
} watch_presence_fields_mask;
/** Structure used to save data of the watch */
typedef struct watch_format_data
{
uint16_t fields_mask; /*!< bit mask to know what are the available data ( from enum watch_format_fields_mask ) */
uint32_t time_sec; /*!< time in seconds since epoch (from GPS or not) */
uint16_t time_ms; /*!< milliseconds time */
double lat_gps; /*!< latitude in degrees */
double lon_gps; /*!< longitude in degrees */
double alt_gps; /*!< altitude in meters, can be negative */
double alt_from_pressure;
double pressure;
//uint8_t heart_rate; /*!< we don't have such thing in the freewatch project */
} watch_format_data;
/**
* @brief write into dest the data converted into format used in the files stored in the SD
* @param data data to convert
* @param dest buffer to store converted data
* @return number of written bytes
*/
uint32_t convert_data_to_file(watch_format_data* data, uint8_t* dest);
uint32_t watch_gpx_write_header(uint8_t* dest);
uint32_t watch_gpx_write_track_segment_begin(uint8_t* dest);
uint32_t watch_gpx_write_track_segment_end(uint8_t* dest);
uint32_t watch_gpx_write_data(watch_format_data* data, uint8_t* dest);
uint32_t watch_gpx_write_footer(uint8_t* dest);
#endif /* __WATCH_FILE_FORMAT_H */
#include <stdint.h>
#include <stdio.h>
#include <time.h>
#include "watch_file_format.h"
static const char* string_xml_header = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\" ?>\n";
static const char* string_gpx_header = "<gpx xmlns=\"http://www.topografix.com/GPX/1/1\" creator=\"freewatch\" version=\"1.1\"\n" \
" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n" \
" xsi:schemaLocation=\"http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd\">";
static const char* string_track_tag = "trk";
uint32_t watch_gpx_write_header(uint8_t* dest) {
char* str_dest = (char*) dest;
int n = sprintf(str_dest, "%s\n%s\n <%s>\n", string_xml_header, string_gpx_header, string_track_tag);
return (uint32_t) n;
}
static const char* string_track_segment_tag = "trkseg";
uint32_t watch_gpx_write_track_segment_begin(uint8_t* dest) {
char* str_dest = (char*) dest;
int n = sprintf(str_dest, "<%s>\n", string_track_segment_tag);
return (uint32_t) n;
}
uint32_t watch_gpx_write_track_segment_end(uint8_t* dest) {
char* str_dest = (char*) dest;
int n = sprintf(str_dest, "</%s>\n", string_track_segment_tag);
return (uint32_t) n;
}
static const char* string_trackpoint_tag = "trkpt";
static const char* string_elevation_tag = "ele";
static const char* string_time_tag = "time";
static const char* string_extensions_tag = "extensions";
static const char* string_extaltgps_tag = "fwtch:alt_gps";
static const char* string_extaltfrompressure_tag = "fwtch:alt_from_pressure";
static const char* string_extpressure_tag = "fwtch:pressure";
uint32_t watch_gpx_write_data(watch_format_data* data, uint8_t* dest) {
int n = 0;
n += sprintf(((char*) dest + n), "<%s lon=\"%lf\" lat=\"%lf\">\n", string_trackpoint_tag,
(data->fields_mask & (1 << WATCH_PRESENCE_LAT_GPS) ? data->lon_gps : 0),
(data->fields_mask & (1 << WATCH_PRESENCE_LON_GPS) ? data->lat_gps : 0));
if ( (data->fields_mask & (
(1 << WATCH_PRESENCE_ALT_GPS) ||
(1 << WATCH_PRESENCE_ALT_FROM_PRESSURE))) ) {
double altitude = (data->fields_mask & (1 << WATCH_PRESENCE_ALT_FROM_PRESSURE) ?
data->alt_from_pressure : data->alt_gps);//pressure more prioritar
n += sprintf(((char*) dest + n), " <%s>%ld<%s>\n", string_elevation_tag, (long) altitude, string_elevation_tag);
}
n += sprintf(((char*) dest + n), " <%s>", string_time_tag);
{
struct tm date_and_time;
time_t seconds = data->time_sec;
localtime_r(&seconds, &date_and_time);
strftime(((char*) dest + n), 22, "%Y-%m-%dT%H:%M:%S ", &date_and_time);
n += 19;//added manually because strftime returns 0
}
n += sprintf(((char*) dest + n), "</%s>\n", string_time_tag);
if ( (data->fields_mask & (
(1 << WATCH_PRESENCE_ALT_GPS) ||
(1 << WATCH_PRESENCE_ALT_FROM_PRESSURE) ||
(1 << WATCH_PRESENCE_PRESSURE))) ) {
n += sprintf(((char*) dest + n), " <%s>\n", string_extensions_tag);
if (data->fields_mask & (1 << WATCH_PRESENCE_ALT_GPS)) {
n += sprintf(((char*) dest + n), " <%s>%ld<%s>\n", string_extaltgps_tag, (long) data->alt_gps, string_extaltgps_tag);
}
if (data->fields_mask & (1 << WATCH_PRESENCE_ALT_FROM_PRESSURE)) {
n += sprintf(((char*) dest + n), " <%s>%ld<%s>\n", string_extaltfrompressure_tag, (long) data->alt_gps, string_extaltfrompressure_tag);
}
if (data->fields_mask & (1 << WATCH_PRESENCE_PRESSURE)) {
n += sprintf(((char*) dest + n), " <%s>%ld<%s>\n", string_extpressure_tag, (long) data->pressure, string_extpressure_tag);
}
n += sprintf(((char*) dest + n), " </%s>\n", string_extensions_tag);
}
n += sprintf(((char*) dest + n), "</%s>\n", string_trackpoint_tag);
return (uint32_t) n;
}
static const char* string_gpx_footer = "</gpx>";
uint32_t watch_gpx_write_footer(uint8_t* dest) {
char* str_dest = (char*) dest;
int n = sprintf(str_dest, " <%s>\n%s", string_track_tag, string_gpx_footer);
return (uint32_t) n;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment