From e243ad615f55c3dec10126e8cf4d7ae1d057a29c Mon Sep 17 00:00:00 2001 From: Peter Antypas Date: Sun, 3 Jul 2016 20:00:05 -0700 Subject: [PATCH] More API features --- .../.settings/org.eclipse.cdt.core.prefs | 163 ++++++++++++++++++ .../.settings/org.eclipse.cdt.ui.prefs | 3 + application/src/CommandProcessor.cpp | 26 ++- application/src/EEPROM.cpp | 7 + application/src/EEPROM.hpp | 1 + application/src/GPS.cpp | 58 +++---- application/src/RXPacket.cpp | 29 ---- application/src/RXPacket.hpp | 19 +- application/src/StationData.h | 5 +- application/src/TXScheduler.cpp | 49 ++++-- application/src/TXScheduler.hpp | 5 +- application/src/globals.h | 6 +- 12 files changed, 268 insertions(+), 103 deletions(-) create mode 100644 application/.settings/org.eclipse.cdt.core.prefs create mode 100644 application/.settings/org.eclipse.cdt.ui.prefs diff --git a/application/.settings/org.eclipse.cdt.core.prefs b/application/.settings/org.eclipse.cdt.core.prefs new file mode 100644 index 0000000..d812e1c --- /dev/null +++ b/application/.settings/org.eclipse.cdt.core.prefs @@ -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 diff --git a/application/.settings/org.eclipse.cdt.ui.prefs b/application/.settings/org.eclipse.cdt.ui.prefs new file mode 100644 index 0000000..bb44a09 --- /dev/null +++ b/application/.settings/org.eclipse.cdt.ui.prefs @@ -0,0 +1,3 @@ +eclipse.preferences.version=1 +formatter_profile=_GNU Variant +formatter_settings_version=1 diff --git a/application/src/CommandProcessor.cpp b/application/src/CommandProcessor.cpp index 7bace03..d1120ec 100644 --- a/application/src/CommandProcessor.cpp +++ b/application/src/CommandProcessor.cpp @@ -225,9 +225,17 @@ void CommandProcessor::setLength(uint8_t len) 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) @@ -259,6 +267,20 @@ void CommandProcessor::setMode(const char *mode) Event *e = EventPool::instance().newEvent(RESET_EVENT); 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 sendError("Unrecognized mode"); } diff --git a/application/src/EEPROM.cpp b/application/src/EEPROM.cpp index 19b8b98..f7588d3 100644 --- a/application/src/EEPROM.cpp +++ b/application/src/EEPROM.cpp @@ -9,6 +9,7 @@ #include "printf2.h" #include #include "Utils.hpp" +#include #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) @@ -76,6 +77,7 @@ void EEPROM::init() I2C_Init(I2C1, &i2c); I2C_Cmd(I2C1, ENABLE); + readStationData(mData); } 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) { + memcpy(&mData, &data, sizeof data); + uint8_t addr = EEPROM_STATION_ADDR; const uint8_t *p = (uint8_t*)&data; for ( size_t i = 0; i < sizeof data; ++i ) @@ -141,12 +145,15 @@ void EEPROM::writeStationData(const StationData &data) void EEPROM::readStationData(StationData &data) { + memcpy(&data, &mData, sizeof mData); + /* uint8_t addr = EEPROM_STATION_ADDR; uint8_t *p = (uint8_t*)&data; for ( size_t i = 0; i < sizeof data; ++i ) { uint8_t byte = readByte(addr++); *p++ = byte; } + */ } diff --git a/application/src/EEPROM.hpp b/application/src/EEPROM.hpp index 8ffd513..e08b153 100644 --- a/application/src/EEPROM.hpp +++ b/application/src/EEPROM.hpp @@ -26,6 +26,7 @@ public: private: EEPROM(); + StationData mData; }; #endif /* EEPROM_HPP_ */ diff --git a/application/src/GPS.cpp b/application/src/GPS.cpp index c8dea5d..acd87e2 100644 --- a/application/src/GPS.cpp +++ b/application/src/GPS.cpp @@ -238,26 +238,27 @@ void GPS::processLine(const char* buff) } } -void GPS::parseSentence(const char *buff) +void +GPS::parseSentence(const char *buff) { //printf2(buff); //if ( strstr(buff, "RMC") != buff+3 ) - // return; + // return; - NMEASentence sentence(buff); - if ( sentence.code().find("RMC") == 2 ) { + NMEASentence sentence (buff); + if (sentence.code ().find ("RMC") == 2) { #ifdef ENABLE_TERMINAL #ifdef OUTPUT_GPS_NMEA #ifdef MULTIPLEXED_OUTPUT - DataTerminal::instance().write("NMEA", buff); + DataTerminal::instance ().write ("NMEA", buff); #else DataTerminal::instance().write(buff); #endif #endif #endif -// This is the time that corresponds to the previous PPS - const vector &fields = sentence.fields(); + // This is the time that corresponds to the previous PPS + const vector &fields = sentence.fields (); /* * 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? */ - if ( fields.size() < 10 ) + if (fields.size () < 10) return; // 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; - //printf2(buff); - //LEDManager::instance().blink(); - if ( mUTC == 0 ) { - const string ×tr = fields[1].substr(0, 6); - const string &datestr = fields[9].substr(0, 6); - mTime.tm_hour = Utils::toInt(timestr.substr(0, 2)); - mTime.tm_min = Utils::toInt(timestr.substr(2, 2)); - mTime.tm_sec = Utils::toInt(timestr.substr(4, 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_year = 100 + Utils::toInt(datestr.substr(4, 2)); // Year is 1900-based - mUTC = mktime(&mTime); - //printf2("UTC=%d\r\n", mUTC); - } + const string ×tr = fields[1].substr (0, 6); + const string &datestr = fields[9].substr (0, 6); + mTime.tm_hour = Utils::toInt (timestr.substr (0, 2)); + mTime.tm_min = Utils::toInt (timestr.substr (2, 2)); + mTime.tm_sec = Utils::toInt (timestr.substr (4, 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_year = 100 + Utils::toInt (datestr.substr (4, 2)); // Year is 1900-based + mUTC = mktime (&mTime); // Do we have a fix? - if ( mUTC && sentence.fields()[3].length() > 0 && sentence.fields()[5].length() > 0 ) { - mLat = Utils::latitudeFromNMEA(sentence.fields()[3], sentence.fields()[4]); - mLng = Utils::longitudeFromNMEA(sentence.fields()[5], sentence.fields()[6]); - mSpeed = Utils::toDouble(sentence.fields()[7]); - mCOG = Utils::toDouble(sentence.fields()[8]); - Event *event = EventPool::instance().newEvent(GPS_FIX_EVENT); - if ( event ) { + if (mUTC && sentence.fields ()[3].length () > 0 && sentence.fields ()[5].length () > 0) { + mLat = Utils::latitudeFromNMEA (sentence.fields ()[3], sentence.fields ()[4]); + mLng = Utils::longitudeFromNMEA (sentence.fields ()[5], sentence.fields ()[6]); + mSpeed = Utils::toDouble (sentence.fields ()[7]); + mCOG = Utils::toDouble (sentence.fields ()[8]); + Event *event = EventPool::instance ().newEvent (GPS_FIX_EVENT); + if (event) { event->gpsFix.utc = mUTC; event->gpsFix.lat = mLat; event->gpsFix.lng = mLng; event->gpsFix.speed = mSpeed; event->gpsFix.cog = mCOG; - EventQueue::instance().push(event); + EventQueue::instance ().push (event); } //printf2("Lat: %f, Lng: %f\r\n", mLat, mLng); } diff --git a/application/src/RXPacket.cpp b/application/src/RXPacket.cpp index 75f9f77..f9fec7e 100644 --- a/application/src/RXPacket.cpp +++ b/application/src/RXPacket.cpp @@ -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(40); -} - -RXPacket *RXPacketPool::newRXPacket() -{ - return mPool->get(); -} - -void RXPacketPool::deleteRXPacket(RXPacket *p) -{ - ASSERT(p); - mPool->put(p); -} -#endif diff --git a/application/src/RXPacket.hpp b/application/src/RXPacket.hpp index 205afca..0f9e19c 100644 --- a/application/src/RXPacket.hpp +++ b/application/src/RXPacket.hpp @@ -9,7 +9,7 @@ #define RXPACKET_HPP_ #include -#include "ObjectPool.hpp" +#include "_assert.h" #include "globals.h" #include "AISChannels.h" @@ -70,21 +70,4 @@ private: uint8_t mRSSI; }; -#if 0 -class RXPacketPool -{ -public: - static RXPacketPool &instance(); - - void init(); - - RXPacket *newRXPacket(); - void deleteRXPacket(RXPacket*); - -private: - ObjectPool *mPool; - -}; -#endif - #endif /* RXPACKET_HPP_ */ diff --git a/application/src/StationData.h b/application/src/StationData.h index 4570695..e578adb 100644 --- a/application/src/StationData.h +++ b/application/src/StationData.h @@ -13,11 +13,14 @@ #include #include "AISChannels.h" +// Station flags +#define STATION_RX_ONLY 0x01 +#define STATION_PRIVACY_MODE 0x02 struct StationData { uint32_t mmsi; // Vessel MMSI (should be 30 bit) 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 beam; // Beam in meters (default: 0) uint8_t flags; // Reserved - 0 for now diff --git a/application/src/TXScheduler.cpp b/application/src/TXScheduler.cpp index 7743ab1..7678380 100644 --- a/application/src/TXScheduler.cpp +++ b/application/src/TXScheduler.cpp @@ -25,13 +25,10 @@ TXScheduler::TXScheduler () mPositionReportChannel = CH_87; mStaticDataChannel = CH_87; mUTC = 0; + mAvgSpeed = 0.0; mTesting = false; - - EEPROM::instance().readStationData(mStationData); - 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); + mLast18Time = 0; + mLast24Time = 0; } @@ -55,18 +52,24 @@ void TXScheduler::processEvent(const Event &e) if ( mTesting ) return; - //GPSFIXEvent *gfe = static_cast (event); - - //printf2("UTC: %d\r\n", mUTC); - // We do not schedule transmissions if the ChannelManager is not sure what channels are in use yet if ( !ChannelManager::instance().channelsDetermined() ) 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. - if ( RadioManager::instance().initialized() && mUTC && (mUTC % DEFAULT_TX_INTERVAL) == 0) { + StationData stationData; + 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); if ( !p1 ) { 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.utc = e.gpsFix.utc; - msg.encode (mStationData, *p1); + msg.encode (stationData, *p1); RadioManager::instance ().scheduleTransmission (p1); // Our next position report should be on the other channel 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); if ( !p2 ) { printf2("Unable to allocate TX packet for 24A\r\n"); break; } AISMessage24A msg2; - msg2.encode(mStationData, *p2); + msg2.encode(stationData, *p2); RadioManager::instance().scheduleTransmission(p2); TXPacket *p3 = TXPacketPool::instance().newTXPacket(mStaticDataChannel, mUTC+7); @@ -105,18 +109,18 @@ void TXScheduler::processEvent(const Event &e) } AISMessage24B msg3; - msg3.encode(mStationData, *p3); + msg3.encode(stationData, *p3); RadioManager::instance().scheduleTransmission(p3); // Our next static data report should be on the other channel mStaticDataChannel = RadioManager::instance().alternateChannel(mStaticDataChannel); + mLast24Time = mUTC; } break; } case CLOCK_EVENT: { // This is reliable and independent of GPS update frequency which could change to something other than 1Hz - //ClockEvent *c = static_cast(event); mUTC = e.clock.utc; if ( RadioManager::instance().initialized() && mTesting && mUTC % 1 == 0 ) { 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() { VHFChannel channel = CH_84; diff --git a/application/src/TXScheduler.hpp b/application/src/TXScheduler.hpp index b0fa16c..7546379 100644 --- a/application/src/TXScheduler.hpp +++ b/application/src/TXScheduler.hpp @@ -26,12 +26,15 @@ public: void startTXTesting(); private: void scheduleTestPacket(); + time_t positionReportTimeInterval(); private: VHFChannel mPositionReportChannel; VHFChannel mStaticDataChannel; time_t mUTC; + time_t mLast18Time; + time_t mLast24Time; + double mAvgSpeed; bool mTesting; - StationData mStationData; }; #endif /* TXSCHEDULER_HPP_ */ diff --git a/application/src/globals.h b/application/src/globals.h index 6104e5a..669956f 100644 --- a/application/src/globals.h +++ b/application/src/globals.h @@ -64,11 +64,11 @@ // Define this to set BT=0.4 for GMSK (as per ITU spec for AIS). Default is 0.5 #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 -// Default interval for message 24 A&B (static data report) -#define MSG_24_TX_INTERVAL 180 +// Default interval for message 24 A&B (static data report) is 6 minutes +#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. // It takes the Si4463 a few bits' time to switch from RX to TX, so I arbitrarily picked the 12th bit.