1
0
mirror of https://github.com/peterantypas/maiana.git synced 2025-05-18 08:20: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);
}
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");
}

View File

@ -9,6 +9,7 @@
#include "printf2.h"
#include <stm32f30x_i2c.h>
#include "Utils.hpp"
#include <cstring>
#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;
}
*/
}

View File

@ -26,6 +26,7 @@ public:
private:
EEPROM();
StationData mData;
};
#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);
//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<string> &fields = sentence.fields();
// This is the time that corresponds to the previous PPS
const vector<string> &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 &timestr = 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 &timestr = 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);
}

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_
#include <inttypes.h>
#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<RXPacket> *mPool;
};
#endif
#endif /* RXPACKET_HPP_ */

View File

@ -13,11 +13,14 @@
#include <time.h>
#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

View File

@ -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<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
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<ClockEvent*>(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;

View File

@ -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_ */

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 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.