@ -2,6 +2,10 @@
@@ -2,6 +2,10 @@
# include <AP_HAL.h>
# include "DataFlash.h"
# include <stdlib.h>
# include <AP_Param.h>
extern const AP_HAL : : HAL & hal ;
// This function determines the number of whole or partial log files in the DataFlash
// Wholly overwritten files are (of course) lost.
@ -53,6 +57,7 @@ uint16_t DataFlash_Block::start_new_log(void)
@@ -53,6 +57,7 @@ uint16_t DataFlash_Block::start_new_log(void)
SetFileNumber ( 1 ) ;
StartWrite ( 1 ) ;
//Serial.println("start log from 0");
Log_Write_Parameters ( ) ;
return 1 ;
}
@ -73,6 +78,7 @@ uint16_t DataFlash_Block::start_new_log(void)
@@ -73,6 +78,7 @@ uint16_t DataFlash_Block::start_new_log(void)
SetFileNumber ( new_log_num ) ;
StartWrite ( last_page + 1 ) ;
}
Log_Write_Parameters ( ) ;
return new_log_num ;
}
@ -240,13 +246,221 @@ uint16_t DataFlash_Block::find_last_page_of_log(uint16_t log_number)
@@ -240,13 +246,221 @@ uint16_t DataFlash_Block::find_last_page_of_log(uint16_t log_number)
return - 1 ;
}
# define PGM_UINT8(addr) pgm_read_byte((const prog_char *)addr)
/*
Read the DataFlash log memory
Call the callback ( ) function on each log message found in the page
range . Return the number of log messages found
print the log column names
*/
void DataFlash_Class : : _print_format_headers ( uint8_t num_types ,
const struct LogStructure * structure ,
AP_HAL : : BetterStream * port )
{
uint8_t i ;
for ( i = 0 ; i < num_types ; i + + ) {
port - > printf_P ( PSTR ( " FMT, %S, %u, %S, %S \n " ) ,
structure [ i ] . name ,
( unsigned ) PGM_UINT8 ( & structure [ i ] . msg_type ) ,
structure [ i ] . format ,
structure [ i ] . labels ) ;
}
}
Note that for the block oriented backend the log_num is ignored
/*
read and print a log entry using the format strings from the given structure
*/
void DataFlash_Class : : _print_log_entry ( uint8_t msg_type ,
uint8_t num_types ,
const struct LogStructure * structure ,
AP_HAL : : BetterStream * port )
{
uint8_t i ;
for ( i = 0 ; i < num_types ; i + + ) {
if ( msg_type = = PGM_UINT8 ( & structure [ i ] . msg_type ) ) {
break ;
}
}
if ( i = = num_types ) {
port - > printf_P ( PSTR ( " UNKN, %u \n " ) , ( unsigned ) msg_type ) ;
return ;
}
uint8_t msg_len = PGM_UINT8 ( & structure [ i ] . msg_len ) ;
uint8_t pkt [ msg_len ] ;
ReadPacket ( pkt , msg_len ) ;
port - > printf_P ( PSTR ( " %S, " ) , structure [ i ] . name ) ;
for ( uint8_t ofs = 3 , fmt_ofs = 0 ; ofs < msg_len ; fmt_ofs + + ) {
char fmt = PGM_UINT8 ( & structure [ i ] . format [ fmt_ofs ] ) ;
switch ( fmt ) {
case ' b ' : {
port - > printf_P ( PSTR ( " %d " ) , ( int ) pkt [ ofs ] ) ;
ofs + = 1 ;
break ;
}
case ' B ' : {
port - > printf_P ( PSTR ( " %u " ) , ( unsigned ) pkt [ ofs ] ) ;
ofs + = 1 ;
break ;
}
case ' h ' : {
int16_t v ;
memcpy ( & v , & pkt [ ofs ] , sizeof ( v ) ) ;
port - > printf_P ( PSTR ( " %d " ) , ( int ) v ) ;
ofs + = sizeof ( v ) ;
break ;
}
case ' H ' : {
uint16_t v ;
memcpy ( & v , & pkt [ ofs ] , sizeof ( v ) ) ;
port - > printf_P ( PSTR ( " %u " ) , ( unsigned ) v ) ;
ofs + = sizeof ( v ) ;
break ;
}
case ' i ' : {
int32_t v ;
memcpy ( & v , & pkt [ ofs ] , sizeof ( v ) ) ;
port - > printf_P ( PSTR ( " %ld " ) , ( long ) v ) ;
ofs + = sizeof ( v ) ;
break ;
}
case ' I ' : {
uint32_t v ;
memcpy ( & v , & pkt [ ofs ] , sizeof ( v ) ) ;
port - > printf_P ( PSTR ( " %lu " ) , ( unsigned long ) v ) ;
ofs + = sizeof ( v ) ;
break ;
}
case ' f ' : {
float v ;
memcpy ( & v , & pkt [ ofs ] , sizeof ( v ) ) ;
port - > printf_P ( PSTR ( " %f " ) , v ) ;
ofs + = sizeof ( v ) ;
break ;
}
case ' c ' : {
int16_t v ;
memcpy ( & v , & pkt [ ofs ] , sizeof ( v ) ) ;
port - > printf_P ( PSTR ( " %.2f " ) , 0.01f * v ) ;
ofs + = sizeof ( v ) ;
break ;
}
case ' C ' : {
uint16_t v ;
memcpy ( & v , & pkt [ ofs ] , sizeof ( v ) ) ;
port - > printf_P ( PSTR ( " %.2f " ) , 0.01f * v ) ;
ofs + = sizeof ( v ) ;
break ;
}
case ' e ' : {
int32_t v ;
memcpy ( & v , & pkt [ ofs ] , sizeof ( v ) ) ;
port - > printf_P ( PSTR ( " %.2f " ) , 0.01f * v ) ;
ofs + = sizeof ( v ) ;
break ;
}
case ' E ' : {
uint32_t v ;
memcpy ( & v , & pkt [ ofs ] , sizeof ( v ) ) ;
port - > printf_P ( PSTR ( " %.2f " ) , 0.01f * v ) ;
ofs + = sizeof ( v ) ;
break ;
}
case ' L ' : {
int32_t v ;
memcpy ( & v , & pkt [ ofs ] , sizeof ( v ) ) ;
int32_t dec_portion , frac_portion ;
int32_t abs_lat_or_lon = labs ( v ) ;
// extract decimal portion (special handling of negative numbers to ensure we round towards zero)
dec_portion = abs_lat_or_lon / 10000000UL ;
// extract fractional portion
frac_portion = abs_lat_or_lon - dec_portion * 10000000UL ;
// print output including the minus sign
if ( v < 0 ) {
port - > printf_P ( PSTR ( " - " ) ) ;
}
port - > printf_P ( PSTR ( " %ld.%07ld " ) , ( long ) dec_portion , ( long ) frac_portion ) ;
ofs + = sizeof ( v ) ;
break ;
}
case ' N ' : {
char v [ 17 ] ;
memcpy ( & v , & pkt [ ofs ] , sizeof ( v ) ) ;
v [ 16 ] = 0 ;
port - > printf_P ( PSTR ( " %s " ) , v ) ;
ofs + = 16 ;
break ;
}
default :
ofs = msg_len ;
break ;
}
if ( ofs < msg_len ) {
port - > printf_P ( PSTR ( " , " ) ) ;
}
}
port - > println ( ) ;
}
/*
Read the log and print it on port
*/
void DataFlash_Block : : LogReadProcess ( uint16_t log_num ,
uint16_t start_page , uint16_t end_page ,
uint8_t num_types ,
const struct LogStructure * structure ,
AP_HAL : : BetterStream * port )
{
uint8_t log_step = 0 ;
uint16_t page = start_page ;
if ( df_BufferIdx ! = 0 ) {
FinishWrite ( ) ;
}
_print_format_headers ( num_types , structure , port ) ;
StartRead ( start_page ) ;
while ( true ) {
uint8_t data ;
ReadBlock ( & data , 1 ) ;
// This is a state machine to read the packets
switch ( log_step ) {
case 0 :
if ( data = = HEAD_BYTE1 ) {
log_step + + ;
}
break ;
case 1 :
if ( data = = HEAD_BYTE2 ) {
log_step + + ;
} else {
log_step = 0 ;
}
break ;
case 2 :
log_step = 0 ;
_print_log_entry ( data , num_types , structure , port ) ;
break ;
}
uint16_t new_page = GetPage ( ) ;
if ( new_page ! = page ) {
if ( new_page = = end_page | | new_page = = start_page ) {
return ;
}
page = new_page ;
}
}
}
/*
Read the DataFlash log memory
This is obsolete and will be removed when plane and copter are
converted to LogReadProcess ( )
*/
void DataFlash_Block : : log_read_process ( uint16_t log_num ,
uint16_t start_page , uint16_t end_page ,
@ -358,3 +572,89 @@ void DataFlash_Block::ListAvailableLogs(AP_HAL::BetterStream *port)
@@ -358,3 +572,89 @@ void DataFlash_Block::ListAvailableLogs(AP_HAL::BetterStream *port)
}
port - > println ( ) ;
}
/*
write a parameter to the log
*/
void DataFlash_Class : : Log_Write_Parameter ( const char * name , float value )
{
struct log_Parameter pkt = {
LOG_PACKET_HEADER_INIT ( LOG_PARAMETER_MSG ) ,
name : { } ,
value : value
} ;
strncpy ( pkt . name , name , sizeof ( pkt . name ) ) ;
WriteBlock ( & pkt , sizeof ( pkt ) ) ;
}
/*
write a parameter to the log
*/
void DataFlash_Class : : Log_Write_Parameter ( const AP_Param * ap ,
const AP_Param : : ParamToken & token ,
enum ap_var_type type )
{
char name [ 16 ] ;
ap - > copy_name_token ( token , & name [ 0 ] , sizeof ( name ) , true ) ;
Log_Write_Parameter ( name , ap - > cast_to_float ( type ) ) ;
}
/*
write all parameters to the log - used when starting a new log so
the log file has a full record of the parameters
*/
void DataFlash_Class : : Log_Write_Parameters ( void )
{
AP_Param : : ParamToken token ;
AP_Param * ap ;
enum ap_var_type type ;
for ( ap = AP_Param : : first ( & token , & type ) ;
ap ;
ap = AP_Param : : next_scalar ( & token , & type ) ) {
Log_Write_Parameter ( ap , token , type ) ;
// slow down the parameter dump to prevent saturating
// the dataflash write bandwidth
hal . scheduler - > delay ( 1 ) ;
}
}
// Write an GPS packet
void DataFlash_Class : : Log_Write_GPS ( const GPS * gps , int32_t relative_alt )
{
struct log_GPS pkt = {
LOG_PACKET_HEADER_INIT ( LOG_GPS_MSG ) ,
status : ( uint8_t ) gps - > status ( ) ,
gps_time : gps - > time ,
num_sats : gps - > num_sats ,
hdop : gps - > hdop ,
latitude : gps - > latitude ,
longitude : gps - > longitude ,
rel_altitude : relative_alt ,
altitude : gps - > altitude ,
ground_speed : gps - > ground_speed ,
ground_course : gps - > ground_course
} ;
WriteBlock ( & pkt , sizeof ( pkt ) ) ;
}
// Write an raw accel/gyro data packet
void DataFlash_Class : : Log_Write_IMU ( const AP_InertialSensor * ins )
{
Vector3f gyro = ins - > get_gyro ( ) ;
Vector3f accel = ins - > get_accel ( ) ;
struct log_IMU pkt = {
LOG_PACKET_HEADER_INIT ( LOG_IMU_MSG ) ,
gyro_x : gyro . x ,
gyro_y : gyro . y ,
gyro_z : gyro . z ,
accel_x : accel . x ,
accel_y : accel . y ,
accel_z : accel . z
} ;
WriteBlock ( & pkt , sizeof ( pkt ) ) ;
}