1
0
mirror of https://github.com/peterantypas/maiana.git synced 2025-05-18 16:30:08 -07:00

More API features

This commit is contained in:
Peter Antypas 2016-07-03 20:00:05 -07:00
parent 7b276a21e3
commit e243ad615f
12 changed files with 268 additions and 103 deletions

View File

@ -0,0 +1,163 @@
eclipse.preferences.version=1
org.eclipse.cdt.core.formatter.alignment_for_arguments_in_method_invocation=18
org.eclipse.cdt.core.formatter.alignment_for_assignment=16
org.eclipse.cdt.core.formatter.alignment_for_base_clause_in_type_declaration=80
org.eclipse.cdt.core.formatter.alignment_for_binary_expression=16
org.eclipse.cdt.core.formatter.alignment_for_compact_if=16
org.eclipse.cdt.core.formatter.alignment_for_conditional_expression=34
org.eclipse.cdt.core.formatter.alignment_for_conditional_expression_chain=18
org.eclipse.cdt.core.formatter.alignment_for_constructor_initializer_list=0
org.eclipse.cdt.core.formatter.alignment_for_declarator_list=16
org.eclipse.cdt.core.formatter.alignment_for_enumerator_list=48
org.eclipse.cdt.core.formatter.alignment_for_expression_list=0
org.eclipse.cdt.core.formatter.alignment_for_expressions_in_array_initializer=16
org.eclipse.cdt.core.formatter.alignment_for_member_access=0
org.eclipse.cdt.core.formatter.alignment_for_overloaded_left_shift_chain=16
org.eclipse.cdt.core.formatter.alignment_for_parameters_in_method_declaration=18
org.eclipse.cdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16
org.eclipse.cdt.core.formatter.brace_position_for_array_initializer=end_of_line
org.eclipse.cdt.core.formatter.brace_position_for_block=end_of_line
org.eclipse.cdt.core.formatter.brace_position_for_block_in_case=end_of_line
org.eclipse.cdt.core.formatter.brace_position_for_method_declaration=next_line
org.eclipse.cdt.core.formatter.brace_position_for_namespace_declaration=next_line
org.eclipse.cdt.core.formatter.brace_position_for_switch=end_of_line
org.eclipse.cdt.core.formatter.brace_position_for_type_declaration=next_line
org.eclipse.cdt.core.formatter.comment.min_distance_between_code_and_line_comment=1
org.eclipse.cdt.core.formatter.comment.never_indent_line_comments_on_first_column=true
org.eclipse.cdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments=true
org.eclipse.cdt.core.formatter.compact_else_if=true
org.eclipse.cdt.core.formatter.continuation_indentation=2
org.eclipse.cdt.core.formatter.continuation_indentation_for_array_initializer=2
org.eclipse.cdt.core.formatter.format_guardian_clause_on_one_line=false
org.eclipse.cdt.core.formatter.indent_access_specifier_compare_to_type_header=false
org.eclipse.cdt.core.formatter.indent_access_specifier_extra_spaces=0
org.eclipse.cdt.core.formatter.indent_body_declarations_compare_to_access_specifier=true
org.eclipse.cdt.core.formatter.indent_body_declarations_compare_to_namespace_header=true
org.eclipse.cdt.core.formatter.indent_breaks_compare_to_cases=true
org.eclipse.cdt.core.formatter.indent_declaration_compare_to_template_header=true
org.eclipse.cdt.core.formatter.indent_empty_lines=false
org.eclipse.cdt.core.formatter.indent_statements_compare_to_block=true
org.eclipse.cdt.core.formatter.indent_statements_compare_to_body=true
org.eclipse.cdt.core.formatter.indent_switchstatements_compare_to_cases=true
org.eclipse.cdt.core.formatter.indent_switchstatements_compare_to_switch=true
org.eclipse.cdt.core.formatter.indentation.size=4
org.eclipse.cdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert
org.eclipse.cdt.core.formatter.insert_new_line_after_template_declaration=insert
org.eclipse.cdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert
org.eclipse.cdt.core.formatter.insert_new_line_before_catch_in_try_statement=insert
org.eclipse.cdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert
org.eclipse.cdt.core.formatter.insert_new_line_before_colon_in_constructor_initializer_list=insert
org.eclipse.cdt.core.formatter.insert_new_line_before_else_in_if_statement=insert
org.eclipse.cdt.core.formatter.insert_new_line_before_identifier_in_function_declaration=insert
org.eclipse.cdt.core.formatter.insert_new_line_before_while_in_do_statement=insert
org.eclipse.cdt.core.formatter.insert_new_line_in_empty_block=insert
org.eclipse.cdt.core.formatter.insert_space_after_assignment_operator=insert
org.eclipse.cdt.core.formatter.insert_space_after_binary_operator=insert
org.eclipse.cdt.core.formatter.insert_space_after_closing_angle_bracket_in_template_arguments=insert
org.eclipse.cdt.core.formatter.insert_space_after_closing_angle_bracket_in_template_parameters=insert
org.eclipse.cdt.core.formatter.insert_space_after_closing_brace_in_block=insert
org.eclipse.cdt.core.formatter.insert_space_after_closing_paren_in_cast=insert
org.eclipse.cdt.core.formatter.insert_space_after_colon_in_base_clause=insert
org.eclipse.cdt.core.formatter.insert_space_after_colon_in_case=insert
org.eclipse.cdt.core.formatter.insert_space_after_colon_in_conditional=insert
org.eclipse.cdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert
org.eclipse.cdt.core.formatter.insert_space_after_comma_in_array_initializer=insert
org.eclipse.cdt.core.formatter.insert_space_after_comma_in_base_types=insert
org.eclipse.cdt.core.formatter.insert_space_after_comma_in_declarator_list=insert
org.eclipse.cdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert
org.eclipse.cdt.core.formatter.insert_space_after_comma_in_expression_list=insert
org.eclipse.cdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert
org.eclipse.cdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert
org.eclipse.cdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert
org.eclipse.cdt.core.formatter.insert_space_after_comma_in_template_arguments=insert
org.eclipse.cdt.core.formatter.insert_space_after_comma_in_template_parameters=insert
org.eclipse.cdt.core.formatter.insert_space_after_opening_angle_bracket_in_template_arguments=do not insert
org.eclipse.cdt.core.formatter.insert_space_after_opening_angle_bracket_in_template_parameters=do not insert
org.eclipse.cdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert
org.eclipse.cdt.core.formatter.insert_space_after_opening_bracket=do not insert
org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert
org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert
org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_exception_specification=do not insert
org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert
org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert
org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert
org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert
org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert
org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert
org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert
org.eclipse.cdt.core.formatter.insert_space_after_postfix_operator=do not insert
org.eclipse.cdt.core.formatter.insert_space_after_prefix_operator=do not insert
org.eclipse.cdt.core.formatter.insert_space_after_question_in_conditional=insert
org.eclipse.cdt.core.formatter.insert_space_after_semicolon_in_for=insert
org.eclipse.cdt.core.formatter.insert_space_after_unary_operator=do not insert
org.eclipse.cdt.core.formatter.insert_space_before_assignment_operator=insert
org.eclipse.cdt.core.formatter.insert_space_before_binary_operator=insert
org.eclipse.cdt.core.formatter.insert_space_before_closing_angle_bracket_in_template_arguments=do not insert
org.eclipse.cdt.core.formatter.insert_space_before_closing_angle_bracket_in_template_parameters=do not insert
org.eclipse.cdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert
org.eclipse.cdt.core.formatter.insert_space_before_closing_bracket=do not insert
org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert
org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert
org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_exception_specification=do not insert
org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert
org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert
org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert
org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert
org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert
org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert
org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert
org.eclipse.cdt.core.formatter.insert_space_before_colon_in_base_clause=insert
org.eclipse.cdt.core.formatter.insert_space_before_colon_in_case=do not insert
org.eclipse.cdt.core.formatter.insert_space_before_colon_in_conditional=insert
org.eclipse.cdt.core.formatter.insert_space_before_colon_in_default=do not insert
org.eclipse.cdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert
org.eclipse.cdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert
org.eclipse.cdt.core.formatter.insert_space_before_comma_in_base_types=do not insert
org.eclipse.cdt.core.formatter.insert_space_before_comma_in_declarator_list=do not insert
org.eclipse.cdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert
org.eclipse.cdt.core.formatter.insert_space_before_comma_in_expression_list=do not insert
org.eclipse.cdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert
org.eclipse.cdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert
org.eclipse.cdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert
org.eclipse.cdt.core.formatter.insert_space_before_comma_in_template_arguments=do not insert
org.eclipse.cdt.core.formatter.insert_space_before_comma_in_template_parameters=do not insert
org.eclipse.cdt.core.formatter.insert_space_before_opening_angle_bracket_in_template_arguments=do not insert
org.eclipse.cdt.core.formatter.insert_space_before_opening_angle_bracket_in_template_parameters=do not insert
org.eclipse.cdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert
org.eclipse.cdt.core.formatter.insert_space_before_opening_brace_in_block=insert
org.eclipse.cdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert
org.eclipse.cdt.core.formatter.insert_space_before_opening_brace_in_namespace_declaration=insert
org.eclipse.cdt.core.formatter.insert_space_before_opening_brace_in_switch=insert
org.eclipse.cdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert
org.eclipse.cdt.core.formatter.insert_space_before_opening_bracket=do not insert
org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_catch=insert
org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_exception_specification=insert
org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_for=insert
org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_if=insert
org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert
org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=insert
org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert
org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_switch=insert
org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_while=insert
org.eclipse.cdt.core.formatter.insert_space_before_postfix_operator=do not insert
org.eclipse.cdt.core.formatter.insert_space_before_prefix_operator=do not insert
org.eclipse.cdt.core.formatter.insert_space_before_question_in_conditional=insert
org.eclipse.cdt.core.formatter.insert_space_before_semicolon=do not insert
org.eclipse.cdt.core.formatter.insert_space_before_semicolon_in_for=do not insert
org.eclipse.cdt.core.formatter.insert_space_before_unary_operator=do not insert
org.eclipse.cdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert
org.eclipse.cdt.core.formatter.insert_space_between_empty_brackets=do not insert
org.eclipse.cdt.core.formatter.insert_space_between_empty_parens_in_exception_specification=do not insert
org.eclipse.cdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert
org.eclipse.cdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert
org.eclipse.cdt.core.formatter.join_wrapped_lines=true
org.eclipse.cdt.core.formatter.keep_else_statement_on_same_line=false
org.eclipse.cdt.core.formatter.keep_empty_array_initializer_on_one_line=false
org.eclipse.cdt.core.formatter.keep_imple_if_on_one_line=false
org.eclipse.cdt.core.formatter.keep_then_statement_on_same_line=false
org.eclipse.cdt.core.formatter.lineSplit=80
org.eclipse.cdt.core.formatter.number_of_empty_lines_to_preserve=1
org.eclipse.cdt.core.formatter.put_empty_statement_on_new_line=true
org.eclipse.cdt.core.formatter.tabulation.char=space
org.eclipse.cdt.core.formatter.tabulation.size=4
org.eclipse.cdt.core.formatter.use_tabs_only_for_leading_indentations=false

View File

@ -0,0 +1,3 @@
eclipse.preferences.version=1
formatter_profile=_GNU Variant
formatter_settings_version=1

View File

@ -225,9 +225,17 @@ void CommandProcessor::setLength(uint8_t len)
sendEmptyReply(true); sendEmptyReply(true);
} }
void CommandProcessor::setVesselData(const char *data) void CommandProcessor::setVesselData(const char *s)
{ {
sendEmptyReply(true); StationData data;
EEPROM::instance().readStationData(data);
int items = sscanf(s, "%lu,%s,%s,%cu,%cu", &data.mmsi, data.name, data.callsign, &data.beam, &data.len);
if ( items < 5 )
sendEmptyReply(false);
else {
EEPROM::instance().writeStationData(data);
sendEmptyReply(true);
}
} }
void CommandProcessor::setMode(const char *mode) void CommandProcessor::setMode(const char *mode)
@ -259,6 +267,20 @@ void CommandProcessor::setMode(const char *mode)
Event *e = EventPool::instance().newEvent(RESET_EVENT); Event *e = EventPool::instance().newEvent(RESET_EVENT);
EventQueue::instance().push(e); EventQueue::instance().push(e);
} }
else if ( strcmp(mode, "rx") == 0 ) {
StationData data;
EEPROM::instance().readStationData(data);
data.flags |= STATION_RX_ONLY;
EEPROM::instance().writeStationData(data);
sendEmptyReply(true);
}
else if ( strcmp(mode, "trx") == 0 ) {
StationData data;
EEPROM::instance().readStationData(data);
data.flags &= ~(STATION_RX_ONLY);
EEPROM::instance().writeStationData(data);
sendEmptyReply(true);
}
else else
sendError("Unrecognized mode"); sendError("Unrecognized mode");
} }

View File

@ -9,6 +9,7 @@
#include "printf2.h" #include "printf2.h"
#include <stm32f30x_i2c.h> #include <stm32f30x_i2c.h>
#include "Utils.hpp" #include "Utils.hpp"
#include <cstring>
#define EEPROM_STATION_ADDR 0x00 // A StationData structure starts here #define EEPROM_STATION_ADDR 0x00 // A StationData structure starts here
#define EEPROM_REGION_CNT_ADDR 0x24 // Number of active special regions goes here (single byte) #define EEPROM_REGION_CNT_ADDR 0x24 // Number of active special regions goes here (single byte)
@ -76,6 +77,7 @@ void EEPROM::init()
I2C_Init(I2C1, &i2c); I2C_Init(I2C1, &i2c);
I2C_Cmd(I2C1, ENABLE); I2C_Cmd(I2C1, ENABLE);
readStationData(mData);
} }
uint8_t EEPROM::readByte(uint8_t addr) uint8_t EEPROM::readByte(uint8_t addr)
@ -133,6 +135,8 @@ void EEPROM::writeByte(uint8_t address, uint8_t byte)
void EEPROM::writeStationData(const StationData &data) void EEPROM::writeStationData(const StationData &data)
{ {
memcpy(&mData, &data, sizeof data);
uint8_t addr = EEPROM_STATION_ADDR; uint8_t addr = EEPROM_STATION_ADDR;
const uint8_t *p = (uint8_t*)&data; const uint8_t *p = (uint8_t*)&data;
for ( size_t i = 0; i < sizeof data; ++i ) for ( size_t i = 0; i < sizeof data; ++i )
@ -141,12 +145,15 @@ void EEPROM::writeStationData(const StationData &data)
void EEPROM::readStationData(StationData &data) void EEPROM::readStationData(StationData &data)
{ {
memcpy(&data, &mData, sizeof mData);
/*
uint8_t addr = EEPROM_STATION_ADDR; uint8_t addr = EEPROM_STATION_ADDR;
uint8_t *p = (uint8_t*)&data; uint8_t *p = (uint8_t*)&data;
for ( size_t i = 0; i < sizeof data; ++i ) { for ( size_t i = 0; i < sizeof data; ++i ) {
uint8_t byte = readByte(addr++); uint8_t byte = readByte(addr++);
*p++ = byte; *p++ = byte;
} }
*/
} }

View File

@ -26,6 +26,7 @@ public:
private: private:
EEPROM(); EEPROM();
StationData mData;
}; };
#endif /* EEPROM_HPP_ */ #endif /* EEPROM_HPP_ */

View File

@ -238,26 +238,27 @@ void GPS::processLine(const char* buff)
} }
} }
void GPS::parseSentence(const char *buff) void
GPS::parseSentence(const char *buff)
{ {
//printf2(buff); //printf2(buff);
//if ( strstr(buff, "RMC") != buff+3 ) //if ( strstr(buff, "RMC") != buff+3 )
// return; // return;
NMEASentence sentence(buff); NMEASentence sentence (buff);
if ( sentence.code().find("RMC") == 2 ) { if (sentence.code ().find ("RMC") == 2) {
#ifdef ENABLE_TERMINAL #ifdef ENABLE_TERMINAL
#ifdef OUTPUT_GPS_NMEA #ifdef OUTPUT_GPS_NMEA
#ifdef MULTIPLEXED_OUTPUT #ifdef MULTIPLEXED_OUTPUT
DataTerminal::instance().write("NMEA", buff); DataTerminal::instance ().write ("NMEA", buff);
#else #else
DataTerminal::instance().write(buff); DataTerminal::instance().write(buff);
#endif #endif
#endif #endif
#endif #endif
// This is the time that corresponds to the previous PPS // This is the time that corresponds to the previous PPS
const vector<string> &fields = sentence.fields(); const vector<string> &fields = sentence.fields ();
/* /*
* Sometimes the GPS indicates errors with sentences like * Sometimes the GPS indicates errors with sentences like
@ -266,43 +267,38 @@ void GPS::parseSentence(const char *buff)
* *
* TODO: Should we consider the GPS non-functioning at this point and thus prevent transmission until it recovers? * TODO: Should we consider the GPS non-functioning at this point and thus prevent transmission until it recovers?
*/ */
if ( fields.size() < 10 ) if (fields.size () < 10)
return; return;
// GPS updates arrive even with no time or fix information // GPS updates arrive even with no time or fix information
if ( fields[1].length() < 6 || fields[9].length() < 6 ) if (fields[1].length () < 6 || fields[9].length () < 6)
return; return;
//printf2(buff);
//LEDManager::instance().blink();
if ( mUTC == 0 ) { const string &timestr = fields[1].substr (0, 6);
const string &timestr = fields[1].substr(0, 6); const string &datestr = fields[9].substr (0, 6);
const string &datestr = fields[9].substr(0, 6); mTime.tm_hour = Utils::toInt (timestr.substr (0, 2));
mTime.tm_hour = Utils::toInt(timestr.substr(0, 2)); mTime.tm_min = Utils::toInt (timestr.substr (2, 2));
mTime.tm_min = Utils::toInt(timestr.substr(2, 2)); mTime.tm_sec = Utils::toInt (timestr.substr (4, 2));
mTime.tm_sec = Utils::toInt(timestr.substr(4, 2)); mTime.tm_mday = Utils::toInt (datestr.substr (0, 2));
mTime.tm_mday = Utils::toInt(datestr.substr(0, 2)); mTime.tm_mon = Utils::toInt (datestr.substr (2, 2)) - 1; // Month is 0-based
mTime.tm_mon = Utils::toInt(datestr.substr(2, 2)) - 1; // Month is 0-based mTime.tm_year = 100 + Utils::toInt (datestr.substr (4, 2)); // Year is 1900-based
mTime.tm_year = 100 + Utils::toInt(datestr.substr(4, 2)); // Year is 1900-based mUTC = mktime (&mTime);
mUTC = mktime(&mTime);
//printf2("UTC=%d\r\n", mUTC);
}
// Do we have a fix? // Do we have a fix?
if ( mUTC && sentence.fields()[3].length() > 0 && sentence.fields()[5].length() > 0 ) { if (mUTC && sentence.fields ()[3].length () > 0 && sentence.fields ()[5].length () > 0) {
mLat = Utils::latitudeFromNMEA(sentence.fields()[3], sentence.fields()[4]); mLat = Utils::latitudeFromNMEA (sentence.fields ()[3], sentence.fields ()[4]);
mLng = Utils::longitudeFromNMEA(sentence.fields()[5], sentence.fields()[6]); mLng = Utils::longitudeFromNMEA (sentence.fields ()[5], sentence.fields ()[6]);
mSpeed = Utils::toDouble(sentence.fields()[7]); mSpeed = Utils::toDouble (sentence.fields ()[7]);
mCOG = Utils::toDouble(sentence.fields()[8]); mCOG = Utils::toDouble (sentence.fields ()[8]);
Event *event = EventPool::instance().newEvent(GPS_FIX_EVENT); Event *event = EventPool::instance ().newEvent (GPS_FIX_EVENT);
if ( event ) { if (event) {
event->gpsFix.utc = mUTC; event->gpsFix.utc = mUTC;
event->gpsFix.lat = mLat; event->gpsFix.lat = mLat;
event->gpsFix.lng = mLng; event->gpsFix.lng = mLng;
event->gpsFix.speed = mSpeed; event->gpsFix.speed = mSpeed;
event->gpsFix.cog = mCOG; event->gpsFix.cog = mCOG;
EventQueue::instance().push(event); EventQueue::instance ().push (event);
} }
//printf2("Lat: %f, Lng: %f\r\n", mLat, mLng); //printf2("Lat: %f, Lng: %f\r\n", mLat, mLng);
} }

View File

@ -247,34 +247,5 @@ uint32_t RXPacket::mmsi() const
} }
///////////////////////////////////////////////////////////////////////////////
//
// RXPacketPool
//
///////////////////////////////////////////////////////////////////////////////
#if 0
RXPacketPool &RXPacketPool::instance()
{
static RXPacketPool __instance;
return __instance;
}
void RXPacketPool::init()
{
mPool = new ObjectPool<RXPacket>(40);
}
RXPacket *RXPacketPool::newRXPacket()
{
return mPool->get();
}
void RXPacketPool::deleteRXPacket(RXPacket *p)
{
ASSERT(p);
mPool->put(p);
}
#endif

View File

@ -9,7 +9,7 @@
#define RXPACKET_HPP_ #define RXPACKET_HPP_
#include <inttypes.h> #include <inttypes.h>
#include "ObjectPool.hpp" #include "_assert.h"
#include "globals.h" #include "globals.h"
#include "AISChannels.h" #include "AISChannels.h"
@ -70,21 +70,4 @@ private:
uint8_t mRSSI; uint8_t mRSSI;
}; };
#if 0
class RXPacketPool
{
public:
static RXPacketPool &instance();
void init();
RXPacket *newRXPacket();
void deleteRXPacket(RXPacket*);
private:
ObjectPool<RXPacket> *mPool;
};
#endif
#endif /* RXPACKET_HPP_ */ #endif /* RXPACKET_HPP_ */

View File

@ -13,11 +13,14 @@
#include <time.h> #include <time.h>
#include "AISChannels.h" #include "AISChannels.h"
// Station flags
#define STATION_RX_ONLY 0x01
#define STATION_PRIVACY_MODE 0x02
struct StationData { struct StationData {
uint32_t mmsi; // Vessel MMSI (should be 30 bit) uint32_t mmsi; // Vessel MMSI (should be 30 bit)
char name[21]; // Vessel name (all caps) char name[21]; // Vessel name (all caps)
char callsign[8]; // Radio station call sign assigned with MMSI char callsign[8]; // Radio station call sign assigned with MMSI (if applicable)
uint8_t len; // Length in meters (default: 0) uint8_t len; // Length in meters (default: 0)
uint8_t beam; // Beam in meters (default: 0) uint8_t beam; // Beam in meters (default: 0)
uint8_t flags; // Reserved - 0 for now uint8_t flags; // Reserved - 0 for now

View File

@ -25,13 +25,10 @@ TXScheduler::TXScheduler ()
mPositionReportChannel = CH_87; mPositionReportChannel = CH_87;
mStaticDataChannel = CH_87; mStaticDataChannel = CH_87;
mUTC = 0; mUTC = 0;
mAvgSpeed = 0.0;
mTesting = false; mTesting = false;
mLast18Time = 0;
EEPROM::instance().readStationData(mStationData); mLast24Time = 0;
printf2("Read station data from EEPROM:\r\n");
printf2("MMSI: %d\r\n", mStationData.mmsi);
printf2("CS: %s\r\n", mStationData.callsign);
printf2("Name: %s\r\n", mStationData.name);
} }
@ -55,18 +52,24 @@ void TXScheduler::processEvent(const Event &e)
if ( mTesting ) if ( mTesting )
return; return;
//GPSFIXEvent *gfe = static_cast<GPSFIXEvent*> (event);
//printf2("UTC: %d\r\n", mUTC);
// We do not schedule transmissions if the ChannelManager is not sure what channels are in use yet // We do not schedule transmissions if the ChannelManager is not sure what channels are in use yet
if ( !ChannelManager::instance().channelsDetermined() ) if ( !ChannelManager::instance().channelsDetermined() )
return; return;
// TODO: This is UGLY. Stop using modulus and start counting from previous timestamps // A class B transponder only transmits when its internal GPS is working, so we tie these to GPS updates.
if ( !RadioManager::instance().initialized() || mUTC == 0 )
return;
// A class B only transmits when its internal GPS is working, so we tie these to GPS updates. StationData stationData;
if ( RadioManager::instance().initialized() && mUTC && (mUTC % DEFAULT_TX_INTERVAL) == 0) { EEPROM::instance().readStationData(stationData);
if ( stationData.flags & STATION_RX_ONLY )
return;
// Using a moving average to determine transmission rate
double alpha = 0.2;
mAvgSpeed = mAvgSpeed * (1.0 - alpha) + e.gpsFix.speed * alpha;
if ( mUTC - mLast18Time > positionReportTimeInterval() ) {
TXPacket *p1 = TXPacketPool::instance().newTXPacket(mPositionReportChannel, mUTC); TXPacket *p1 = TXPacketPool::instance().newTXPacket(mPositionReportChannel, mUTC);
if ( !p1 ) { if ( !p1 ) {
printf2("Unable to allocate TX packet for message 18, will try again later\r\n"); printf2("Unable to allocate TX packet for message 18, will try again later\r\n");
@ -80,22 +83,23 @@ void TXScheduler::processEvent(const Event &e)
msg.cog = e.gpsFix.cog; msg.cog = e.gpsFix.cog;
msg.utc = e.gpsFix.utc; msg.utc = e.gpsFix.utc;
msg.encode (mStationData, *p1); msg.encode (stationData, *p1);
RadioManager::instance ().scheduleTransmission (p1); RadioManager::instance ().scheduleTransmission (p1);
// Our next position report should be on the other channel // Our next position report should be on the other channel
mPositionReportChannel = RadioManager::instance().alternateChannel(mPositionReportChannel); mPositionReportChannel = RadioManager::instance().alternateChannel(mPositionReportChannel);
mLast18Time = mUTC;
} }
if ( RadioManager::instance().initialized() && mUTC && (mUTC % MSG_24_TX_INTERVAL) == 0 ) { if ( mUTC - mLast24Time > MSG_24_TX_INTERVAL ) {
TXPacket *p2 = TXPacketPool::instance().newTXPacket(mStaticDataChannel, mUTC+2); TXPacket *p2 = TXPacketPool::instance().newTXPacket(mStaticDataChannel, mUTC+2);
if ( !p2 ) { if ( !p2 ) {
printf2("Unable to allocate TX packet for 24A\r\n"); printf2("Unable to allocate TX packet for 24A\r\n");
break; break;
} }
AISMessage24A msg2; AISMessage24A msg2;
msg2.encode(mStationData, *p2); msg2.encode(stationData, *p2);
RadioManager::instance().scheduleTransmission(p2); RadioManager::instance().scheduleTransmission(p2);
TXPacket *p3 = TXPacketPool::instance().newTXPacket(mStaticDataChannel, mUTC+7); TXPacket *p3 = TXPacketPool::instance().newTXPacket(mStaticDataChannel, mUTC+7);
@ -105,18 +109,18 @@ void TXScheduler::processEvent(const Event &e)
} }
AISMessage24B msg3; AISMessage24B msg3;
msg3.encode(mStationData, *p3); msg3.encode(stationData, *p3);
RadioManager::instance().scheduleTransmission(p3); RadioManager::instance().scheduleTransmission(p3);
// Our next static data report should be on the other channel // Our next static data report should be on the other channel
mStaticDataChannel = RadioManager::instance().alternateChannel(mStaticDataChannel); mStaticDataChannel = RadioManager::instance().alternateChannel(mStaticDataChannel);
mLast24Time = mUTC;
} }
break; break;
} }
case CLOCK_EVENT: { case CLOCK_EVENT: {
// This is reliable and independent of GPS update frequency which could change to something other than 1Hz // This is reliable and independent of GPS update frequency which could change to something other than 1Hz
//ClockEvent *c = static_cast<ClockEvent*>(event);
mUTC = e.clock.utc; mUTC = e.clock.utc;
if ( RadioManager::instance().initialized() && mTesting && mUTC % 1 == 0 ) { if ( RadioManager::instance().initialized() && mTesting && mUTC % 1 == 0 ) {
scheduleTestPacket(); scheduleTestPacket();
@ -130,6 +134,15 @@ void TXScheduler::processEvent(const Event &e)
} }
time_t TXScheduler::positionReportTimeInterval()
{
// As a class B "CS" transponder, we transmit every 3 minutes if speed is < 2 knots, otherwise 30 seconds.
if ( mAvgSpeed < 2.0 )
return 180;
return DEFAULT_TX_INTERVAL;
}
void TXScheduler::scheduleTestPacket() void TXScheduler::scheduleTestPacket()
{ {
VHFChannel channel = CH_84; VHFChannel channel = CH_84;

View File

@ -26,12 +26,15 @@ public:
void startTXTesting(); void startTXTesting();
private: private:
void scheduleTestPacket(); void scheduleTestPacket();
time_t positionReportTimeInterval();
private: private:
VHFChannel mPositionReportChannel; VHFChannel mPositionReportChannel;
VHFChannel mStaticDataChannel; VHFChannel mStaticDataChannel;
time_t mUTC; time_t mUTC;
time_t mLast18Time;
time_t mLast24Time;
double mAvgSpeed;
bool mTesting; bool mTesting;
StationData mStationData;
}; };
#endif /* TXSCHEDULER_HPP_ */ #endif /* TXSCHEDULER_HPP_ */

View File

@ -64,11 +64,11 @@
// Define this to set BT=0.4 for GMSK (as per ITU spec for AIS). Default is 0.5 // Define this to set BT=0.4 for GMSK (as per ITU spec for AIS). Default is 0.5
#define USE_BT_04 #define USE_BT_04
// Default interval for message 18 (position report) // Default interval for message 18 (position report) is 30 seconds when under way
#define DEFAULT_TX_INTERVAL 30 #define DEFAULT_TX_INTERVAL 30
// Default interval for message 24 A&B (static data report) // Default interval for message 24 A&B (static data report) is 6 minutes
#define MSG_24_TX_INTERVAL 180 #define MSG_24_TX_INTERVAL 360
// The spec calls for Class B transmitters to listen for the first 20 bits of each frame before transmitting. // The spec calls for Class B transmitters to listen for the first 20 bits of each frame before transmitting.
// It takes the Si4463 a few bits' time to switch from RX to TX, so I arbitrarily picked the 12th bit. // It takes the Si4463 a few bits' time to switch from RX to TX, so I arbitrarily picked the 12th bit.