mirror of
https://github.com/f4exb/sdrangel.git
synced 2025-03-22 20:28:58 -04:00
ChirpChat modulator: added FT protocol
This commit is contained in:
parent
aa95a5bd53
commit
2a39ef5d6d
@ -1,5 +1,10 @@
|
||||
project(modchirpchat)
|
||||
|
||||
if (FT8_SUPPORT)
|
||||
set(chirpchatmod_FT8_LIB ft8)
|
||||
set(chirpchatmod_FT8_INCLUDE ${CMAKE_SOURCE_DIR}/ft8)
|
||||
endif()
|
||||
|
||||
set(modchirpchat_SOURCES
|
||||
chirpchatmod.cpp
|
||||
chirpchatmodsettings.cpp
|
||||
@ -10,6 +15,7 @@ set(modchirpchat_SOURCES
|
||||
chirpchatmodencodertty.cpp
|
||||
chirpchatmodencoderascii.cpp
|
||||
chirpchatmodencoderlora.cpp
|
||||
chirpchatmodencoderft.cpp
|
||||
chirpchatmodwebapiadapter.cpp
|
||||
)
|
||||
|
||||
@ -23,11 +29,13 @@ set(modchirpchat_HEADERS
|
||||
chirpchatmodencodertty.h
|
||||
chirpchatmodencoderascii.h
|
||||
chirpchatmodencoderlora.h
|
||||
chirpchatmodencoderft.h
|
||||
chirpchatmodwebapiadapter.h
|
||||
)
|
||||
|
||||
include_directories(
|
||||
${CMAKE_SOURCE_DIR}/swagger/sdrangel/code/qt5/client
|
||||
${chirpchatmod_FT8_INCLUDE}
|
||||
)
|
||||
|
||||
if(NOT SERVER_MODE)
|
||||
@ -38,7 +46,7 @@ if(NOT SERVER_MODE)
|
||||
)
|
||||
set(modchirpchat_HEADERS
|
||||
${modchirpchat_HEADERS}
|
||||
chirpchatmodgui.h
|
||||
chirpchatmodgui.h
|
||||
)
|
||||
|
||||
set(TARGET_NAME modchirpchat)
|
||||
@ -62,6 +70,7 @@ target_link_libraries(${TARGET_NAME}
|
||||
sdrbase
|
||||
${TARGET_LIB_GUI}
|
||||
swagger
|
||||
${chirpchatmod_FT8_LIB}
|
||||
)
|
||||
|
||||
install(TARGETS ${TARGET_NAME} DESTINATION ${INSTALL_FOLDER})
|
||||
|
@ -284,74 +284,19 @@ void ChirpChatMod::applySettings(const ChirpChatModSettings& settings, bool forc
|
||||
{
|
||||
payloadMsg = ChirpChatModBaseband::MsgConfigureChirpChatModPayload::create();
|
||||
}
|
||||
else if ((settings.m_messageType == ChirpChatModSettings::MessageBeacon)
|
||||
&& ((settings.m_messageType != m_settings.m_messageType)
|
||||
|| (settings.m_beaconMessage != m_settings.m_beaconMessage) || force))
|
||||
else if ((settings.m_messageType != m_settings.m_messageType)
|
||||
|| (settings.m_beaconMessage != m_settings.m_beaconMessage)
|
||||
|| (settings.m_cqMessage != m_settings.m_cqMessage)
|
||||
|| (settings.m_replyMessage != m_settings.m_replyMessage)
|
||||
|| (settings.m_reportMessage != m_settings.m_reportMessage)
|
||||
|| (settings.m_replyReportMessage != m_settings.m_replyReportMessage)
|
||||
|| (settings.m_rrrMessage != m_settings.m_rrrMessage)
|
||||
|| (settings.m_73Message != m_settings.m_73Message)
|
||||
|| (settings.m_qsoTextMessage != m_settings.m_qsoTextMessage)
|
||||
|| (settings.m_textMessage != m_settings.m_textMessage)
|
||||
|| (settings.m_bytesMessage != m_settings.m_bytesMessage) || force)
|
||||
{
|
||||
m_encoder.encodeString(settings.m_beaconMessage, symbols);
|
||||
payloadMsg = ChirpChatModBaseband::MsgConfigureChirpChatModPayload::create(symbols);
|
||||
}
|
||||
else if ((settings.m_messageType == ChirpChatModSettings::MessageCQ)
|
||||
&& ((settings.m_messageType != m_settings.m_messageType)
|
||||
|| (settings.m_cqMessage != m_settings.m_cqMessage) || force))
|
||||
{
|
||||
m_encoder.encodeString(settings.m_cqMessage, symbols);
|
||||
payloadMsg = ChirpChatModBaseband::MsgConfigureChirpChatModPayload::create(symbols);
|
||||
}
|
||||
else if ((settings.m_messageType == ChirpChatModSettings::MessageReply)
|
||||
&& ((settings.m_messageType != m_settings.m_messageType)
|
||||
|| (settings.m_replyMessage != m_settings.m_replyMessage) || force))
|
||||
{
|
||||
m_encoder.encodeString(settings.m_replyMessage, symbols);
|
||||
payloadMsg = ChirpChatModBaseband::MsgConfigureChirpChatModPayload::create(symbols);
|
||||
}
|
||||
else if ((settings.m_messageType == ChirpChatModSettings::MessageReport)
|
||||
&& ((settings.m_messageType != m_settings.m_messageType)
|
||||
|| (settings.m_reportMessage != m_settings.m_reportMessage) || force))
|
||||
{
|
||||
m_encoder.encodeString(settings.m_reportMessage, symbols);
|
||||
payloadMsg = ChirpChatModBaseband::MsgConfigureChirpChatModPayload::create(symbols);
|
||||
}
|
||||
else if ((settings.m_messageType == ChirpChatModSettings::MessageReplyReport)
|
||||
&& ((settings.m_messageType != m_settings.m_messageType)
|
||||
|| (settings.m_replyReportMessage != m_settings.m_replyReportMessage) || force))
|
||||
{
|
||||
m_encoder.encodeString(settings.m_replyReportMessage, symbols);
|
||||
payloadMsg = ChirpChatModBaseband::MsgConfigureChirpChatModPayload::create(symbols);
|
||||
}
|
||||
else if ((settings.m_messageType == ChirpChatModSettings::MessageRRR)
|
||||
&& ((settings.m_messageType != m_settings.m_messageType)
|
||||
|| (settings.m_rrrMessage != m_settings.m_rrrMessage) || force))
|
||||
{
|
||||
m_encoder.encodeString(settings.m_rrrMessage, symbols);
|
||||
payloadMsg = ChirpChatModBaseband::MsgConfigureChirpChatModPayload::create(symbols);
|
||||
}
|
||||
else if ((settings.m_messageType == ChirpChatModSettings::Message73)
|
||||
&& ((settings.m_messageType != m_settings.m_messageType)
|
||||
|| (settings.m_73Message != m_settings.m_73Message) || force))
|
||||
{
|
||||
m_encoder.encodeString(settings.m_73Message, symbols);
|
||||
payloadMsg = ChirpChatModBaseband::MsgConfigureChirpChatModPayload::create(symbols);
|
||||
}
|
||||
else if ((settings.m_messageType == ChirpChatModSettings::MessageQSOText)
|
||||
&& ((settings.m_messageType != m_settings.m_messageType)
|
||||
|| (settings.m_qsoTextMessage != m_settings.m_qsoTextMessage) || force))
|
||||
{
|
||||
m_encoder.encodeString(settings.m_qsoTextMessage, symbols);
|
||||
payloadMsg = ChirpChatModBaseband::MsgConfigureChirpChatModPayload::create(symbols);
|
||||
}
|
||||
else if ((settings.m_messageType == ChirpChatModSettings::MessageText)
|
||||
&& ((settings.m_messageType != m_settings.m_messageType)
|
||||
|| (settings.m_textMessage != m_settings.m_textMessage) || force))
|
||||
{
|
||||
m_encoder.encodeString(settings.m_textMessage, symbols);
|
||||
payloadMsg = ChirpChatModBaseband::MsgConfigureChirpChatModPayload::create(symbols);
|
||||
}
|
||||
else if ((settings.m_messageType == ChirpChatModSettings::MessageBytes)
|
||||
&& ((settings.m_messageType != m_settings.m_messageType)
|
||||
|| (settings.m_bytesMessage != m_settings.m_bytesMessage) || force))
|
||||
{
|
||||
m_encoder.encodeBytes(settings.m_bytesMessage, symbols);
|
||||
m_encoder.encode(settings, symbols);
|
||||
payloadMsg = ChirpChatModBaseband::MsgConfigureChirpChatModPayload::create(symbols);
|
||||
}
|
||||
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "chirpchatmodencodertty.h"
|
||||
#include "chirpchatmodencoderascii.h"
|
||||
#include "chirpchatmodencoderlora.h"
|
||||
#include "chirpchatmodencoderft.h"
|
||||
|
||||
ChirpChatModEncoder::ChirpChatModEncoder() :
|
||||
m_codingScheme(ChirpChatModSettings::CodingTTY),
|
||||
@ -44,6 +45,47 @@ void ChirpChatModEncoder::setNbSymbolBits(unsigned int spreadFactor, unsigned in
|
||||
m_nbSymbolBits = m_spreadFactor - m_deBits;
|
||||
}
|
||||
|
||||
void ChirpChatModEncoder::encode(ChirpChatModSettings settings, std::vector<unsigned short>& symbols)
|
||||
{
|
||||
if (settings.m_codingScheme == ChirpChatModSettings::CodingFT)
|
||||
{
|
||||
ChirpChatModEncoderFT::encodeMsg(
|
||||
settings.m_myCall,
|
||||
settings.m_urCall,
|
||||
settings.m_myLoc,
|
||||
settings.m_myRpt,
|
||||
settings.m_textMessage,
|
||||
settings.m_messageType,
|
||||
m_nbSymbolBits,
|
||||
symbols
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (settings.m_messageType == ChirpChatModSettings::MessageBytes) {
|
||||
encodeBytes(settings.m_bytesMessage, symbols);
|
||||
} else if (settings.m_messageType == ChirpChatModSettings::MessageBeacon) {
|
||||
encodeString(settings.m_beaconMessage, symbols);
|
||||
} else if (settings.m_messageType == ChirpChatModSettings::MessageCQ) {
|
||||
encodeString(settings.m_cqMessage, symbols);
|
||||
} else if (settings.m_messageType == ChirpChatModSettings::MessageReply) {
|
||||
encodeString(settings.m_replyMessage, symbols);
|
||||
} else if (settings.m_messageType == ChirpChatModSettings::MessageReport) {
|
||||
encodeString(settings.m_reportMessage, symbols);
|
||||
} else if (settings.m_messageType == ChirpChatModSettings::MessageReplyReport) {
|
||||
encodeString(settings.m_replyReportMessage, symbols);
|
||||
} else if (settings.m_messageType == ChirpChatModSettings::MessageRRR) {
|
||||
encodeString(settings.m_rrrMessage, symbols);
|
||||
} else if (settings.m_messageType == ChirpChatModSettings::Message73) {
|
||||
encodeString(settings.m_73Message, symbols);
|
||||
} else if (settings.m_messageType == ChirpChatModSettings::MessageQSOText) {
|
||||
encodeString(settings.m_qsoTextMessage, symbols);
|
||||
} else if (settings.m_messageType == ChirpChatModSettings::MessageText) {
|
||||
encodeString(settings.m_textMessage, symbols);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ChirpChatModEncoder::encodeString(const QString& str, std::vector<unsigned short>& symbols)
|
||||
{
|
||||
switch (m_codingScheme)
|
||||
|
@ -34,10 +34,11 @@ public:
|
||||
void setLoRaParityBits(unsigned int parityBits) { m_nbParityBits = parityBits; }
|
||||
void setLoRaHasHeader(bool hasHeader) { m_hasHeader = hasHeader; }
|
||||
void setLoRaHasCRC(bool hasCRC) { m_hasCRC = hasCRC; }
|
||||
void encodeString(const QString& str, std::vector<unsigned short>& symbols);
|
||||
void encodeBytes(const QByteArray& bytes, std::vector<unsigned short>& symbols);
|
||||
void encode(ChirpChatModSettings settings, std::vector<unsigned short>& symbols);
|
||||
|
||||
private:
|
||||
void encodeString(const QString& str, std::vector<unsigned short>& symbols);
|
||||
// LoRa functions
|
||||
void encodeBytesLoRa(const QByteArray& bytes, std::vector<unsigned short>& symbols);
|
||||
|
||||
|
220
plugins/channeltx/modchirpchat/chirpchatmodencoderft.cpp
Normal file
220
plugins/channeltx/modchirpchat/chirpchatmodencoderft.cpp
Normal file
@ -0,0 +1,220 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright (C) 2024 Edouard Griffiths, F4EXB <f4exb06@gmail.com> //
|
||||
// //
|
||||
// This program is free software; you can redistribute it and/or modify //
|
||||
// it under the terms of the GNU General Public License as published by //
|
||||
// the Free Software Foundation as version 3 of the License, or //
|
||||
// (at your option) any later version. //
|
||||
// //
|
||||
// This program is distributed in the hope that it will be useful, //
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
|
||||
// GNU General Public License V3 for more details. //
|
||||
// //
|
||||
// You should have received a copy of the GNU General Public License //
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "chirpchatmodencoderft.h"
|
||||
|
||||
#ifndef HAS_FT8
|
||||
void ChirpChatModEncoderFT::encodeMsg(
|
||||
const QString& myCall,
|
||||
const QString& urCall,
|
||||
const QString& myLocator,
|
||||
const QString& myReport,
|
||||
const QString& textMessage,
|
||||
ChirpChatModSettings::MessageType messageType,
|
||||
unsigned int nbSymbolBits,
|
||||
std::vector<unsigned short>& symbols
|
||||
)
|
||||
{
|
||||
qDebug("ChirpChatModEncoderFT::encodeMsg: not implemented");
|
||||
}
|
||||
#else
|
||||
|
||||
#include "ft8.h"
|
||||
#include "packing.h"
|
||||
|
||||
|
||||
void ChirpChatModEncoderFT::encodeMsg(
|
||||
const QString& myCall,
|
||||
const QString& urCall,
|
||||
const QString& myLocator,
|
||||
const QString& myReport,
|
||||
const QString& textMessage,
|
||||
ChirpChatModSettings::MessageType messageType,
|
||||
unsigned int nbSymbolBits,
|
||||
std::vector<unsigned short>& symbols
|
||||
)
|
||||
{
|
||||
int a174[174]; // FT payload is 174 bits
|
||||
|
||||
if (messageType == ChirpChatModSettings::MessageNone) {
|
||||
return; // do nothing
|
||||
} else if (messageType == ChirpChatModSettings::MessageBeacon) {
|
||||
encodeMsgBeaconOrCQ(myCall, myLocator, "DE", a174);
|
||||
} else if (messageType == ChirpChatModSettings::MessageCQ) {
|
||||
encodeMsgBeaconOrCQ(myCall, myLocator, "CQ", a174);
|
||||
} else if (messageType == ChirpChatModSettings::MessageReply) {
|
||||
encodeMsgReply(myCall, urCall, myLocator, a174);
|
||||
} else if (messageType == ChirpChatModSettings::MessageReport) {
|
||||
encodeMsgReport(myCall, urCall, myReport, 0, a174);
|
||||
} else if (messageType == ChirpChatModSettings::MessageReplyReport) {
|
||||
encodeMsgReport(myCall, urCall, myReport, 1, a174);
|
||||
} else if (messageType == ChirpChatModSettings::MessageRRR) {
|
||||
encodeMsgReport(myCall, urCall, "RRR", 1, a174);
|
||||
} else if (messageType == ChirpChatModSettings::Message73) {
|
||||
encodeMsgReport(myCall, urCall, "73", 1, a174);
|
||||
} else {
|
||||
encodeTextMsg(textMessage, a174);
|
||||
}
|
||||
|
||||
int allBits = ((174 / nbSymbolBits) + (174 % nbSymbolBits == 0 ? 0 : 1))*nbSymbolBits; // ensures zero bits padding
|
||||
int iBit;
|
||||
int symbol = 0;
|
||||
|
||||
for (int i = 0; i < allBits; i++)
|
||||
{
|
||||
iBit = nbSymbolBits - (i % nbSymbolBits) - 1; // MSB first
|
||||
|
||||
if (i < 174) {
|
||||
symbol += a174[i] * (1<<iBit);
|
||||
}
|
||||
|
||||
if ((i % nbSymbolBits) == (nbSymbolBits - 1))
|
||||
{
|
||||
symbols.push_back(symbol);
|
||||
symbol = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ChirpChatModEncoderFT::encodeTextMsg(const QString& text, int a174[])
|
||||
{
|
||||
int a77[77];
|
||||
std::fill(a77, a77 + 77, 0);
|
||||
QString sentMsg = text.rightJustified(13, ' ', true);
|
||||
|
||||
if (!FT8::Packing::packfree(a77, sentMsg.toStdString()))
|
||||
{
|
||||
qDebug("ChirpChatModEncoderFT::encodeTextMsg: failed to encode free text message (%s)", qPrintable(sentMsg));
|
||||
return;
|
||||
}
|
||||
|
||||
FT8::FT8::encode(a174, a77);
|
||||
}
|
||||
|
||||
void ChirpChatModEncoderFT::encodeMsgBeaconOrCQ(const QString& myCall, const QString& myLocator, const QString& shorthand, int a174[])
|
||||
{
|
||||
int c28_1, c28_2, g15;
|
||||
|
||||
if (!FT8::Packing::packcall_std(c28_1, shorthand.toStdString())) //
|
||||
{
|
||||
qDebug("ChirpChatModEncoderFT::encodeMsgBeacon: failed to encode call1 (%s)", qPrintable(shorthand));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!FT8::Packing::packcall_std(c28_2, myCall.toStdString()))
|
||||
{
|
||||
qDebug("ChirpChatModEncoderFT::encodeMsgBeacon: failed to encode call2 (%s)", qPrintable(myCall));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!FT8::Packing::packgrid(g15, myLocator.toStdString()))
|
||||
{
|
||||
qDebug("ChirpChatModEncoderFT::encodeMsgBeacon: failed to encode locator (%s)", qPrintable(myLocator));
|
||||
return;
|
||||
}
|
||||
|
||||
int a77[77];
|
||||
std::fill(a77, a77 + 77, 0);
|
||||
FT8::Packing::pack1(a77, c28_1, c28_2, g15, 0);
|
||||
FT8::FT8::encode(a174, a77);
|
||||
}
|
||||
|
||||
void ChirpChatModEncoderFT::encodeMsgReply(const QString& myCall, const QString& urCall, const QString& myLocator, int a174[])
|
||||
{
|
||||
int c28_1, c28_2, g15;
|
||||
|
||||
if (!FT8::Packing::packcall_std(c28_1, urCall.toStdString())) //
|
||||
{
|
||||
qDebug("ChirpChatModEncoderFT::encodeMsgBeacon: failed to encode call1 (%s)", qPrintable(urCall));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!FT8::Packing::packcall_std(c28_2, myCall.toStdString()))
|
||||
{
|
||||
qDebug("ChirpChatModEncoderFT::encodeMsgBeacon: failed to encode call2 (%s)", qPrintable(myCall));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!FT8::Packing::packgrid(g15, myLocator.toStdString()))
|
||||
{
|
||||
qDebug("ChirpChatModEncoderFT::encodeMsgBeacon: failed to encode locator (%s)", qPrintable(myLocator));
|
||||
return;
|
||||
}
|
||||
|
||||
int a77[77];
|
||||
std::fill(a77, a77 + 77, 0);
|
||||
FT8::Packing::pack1(a77, c28_1, c28_2, g15, 0);
|
||||
FT8::FT8::encode(a174, a77);
|
||||
}
|
||||
|
||||
void ChirpChatModEncoderFT::encodeMsgReport(const QString& myCall, const QString& urCall, const QString& myReport, int reply, int a174[])
|
||||
{
|
||||
int c28_1, c28_2, g15;
|
||||
|
||||
if (!FT8::Packing::packcall_std(c28_1, urCall.toStdString())) //
|
||||
{
|
||||
qDebug("ChirpChatModEncoderFT::encodeMsgBeacon: failed to encode call1 (%s)", qPrintable(urCall));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!FT8::Packing::packcall_std(c28_2, myCall.toStdString()))
|
||||
{
|
||||
qDebug("ChirpChatModEncoderFT::encodeMsgBeacon: failed to encode call2 (%s)", qPrintable(myCall));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!FT8::Packing::packgrid(g15, myReport.toStdString()))
|
||||
{
|
||||
qDebug("ChirpChatModEncoderFT::encodeMsgBeacon: failed to encode report (%s)", qPrintable(myReport));
|
||||
return;
|
||||
}
|
||||
|
||||
int a77[77];
|
||||
std::fill(a77, a77 + 77, 0);
|
||||
FT8::Packing::pack1(a77, c28_1, c28_2, g15, reply);
|
||||
FT8::FT8::encode(a174, a77);
|
||||
}
|
||||
|
||||
void ChirpChatModEncoderFT::encodeMsgFinish(const QString& myCall, const QString& urCall, const QString& shorthand, int a174[])
|
||||
{
|
||||
int c28_1, c28_2, g15;
|
||||
|
||||
if (!FT8::Packing::packcall_std(c28_1, urCall.toStdString())) //
|
||||
{
|
||||
qDebug("ChirpChatModEncoderFT::encodeMsgBeacon: failed to encode call1 (%s)", qPrintable(urCall));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!FT8::Packing::packcall_std(c28_2, myCall.toStdString()))
|
||||
{
|
||||
qDebug("ChirpChatModEncoderFT::encodeMsgBeacon: failed to encode call2 (%s)", qPrintable(myCall));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!FT8::Packing::packgrid(g15, shorthand.toStdString()))
|
||||
{
|
||||
qDebug("ChirpChatModEncoderFT::encodeMsgBeacon: failed to encode shorthand (%s)", qPrintable(shorthand));
|
||||
return;
|
||||
}
|
||||
|
||||
int a77[77];
|
||||
std::fill(a77, a77 + 77, 0);
|
||||
FT8::Packing::pack1(a77, c28_1, c28_2, g15, 0);
|
||||
FT8::FT8::encode(a174, a77);
|
||||
}
|
||||
|
||||
#endif // HAS_FT8
|
48
plugins/channeltx/modchirpchat/chirpchatmodencoderft.h
Normal file
48
plugins/channeltx/modchirpchat/chirpchatmodencoderft.h
Normal file
@ -0,0 +1,48 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright (C) 2024 Edouard Griffiths, F4EXB <f4exb06@gmail.com> //
|
||||
// //
|
||||
// This program is free software; you can redistribute it and/or modify //
|
||||
// it under the terms of the GNU General Public License as published by //
|
||||
// the Free Software Foundation as version 3 of the License, or //
|
||||
// (at your option) any later version. //
|
||||
// //
|
||||
// This program is distributed in the hope that it will be useful, //
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
|
||||
// GNU General Public License V3 for more details. //
|
||||
// //
|
||||
// You should have received a copy of the GNU General Public License //
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef PLUGINS_CHANNELTX_MODCHIRPCHAT_CHIRPCHATMODENCODEFT_H_
|
||||
#define PLUGINS_CHANNELTX_MODCHIRPCHAT_CHIRPCHATMODENCODEFT_H_
|
||||
|
||||
#include <vector>
|
||||
#include <QString>
|
||||
|
||||
#include "chirpchatmodsettings.h"
|
||||
|
||||
class ChirpChatModEncoderFT
|
||||
{
|
||||
public:
|
||||
static void encodeMsg(
|
||||
const QString& myCall,
|
||||
const QString& urCall,
|
||||
const QString& myLocator,
|
||||
const QString& myReport,
|
||||
const QString& textMessage,
|
||||
ChirpChatModSettings::MessageType messageType,
|
||||
unsigned int nbSymbolBits,
|
||||
std::vector<unsigned short>& symbols
|
||||
);
|
||||
|
||||
private:
|
||||
static void encodeTextMsg(const QString& text, int a174[]);
|
||||
static void encodeMsgBeaconOrCQ(const QString& myCall, const QString& myLocator, const QString& shorthand, int a174[]);
|
||||
static void encodeMsgReply(const QString& myCall, const QString& urCall, const QString& myLocator, int a174[]);
|
||||
static void encodeMsgReport(const QString& myCall, const QString& urCall, const QString& myReport, int reply, int a174[]);
|
||||
static void encodeMsgFinish(const QString& myCall, const QString& urCall, const QString& shorthand, int a174[]);
|
||||
};
|
||||
|
||||
#endif // PLUGINS_CHANNELTX_MODCHIRPCHAT_CHIRPCHATMODENCODEFT_H_
|
@ -551,6 +551,11 @@
|
||||
<string>TTY</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>FT</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
|
@ -34,7 +34,8 @@ struct ChirpChatModSettings
|
||||
{
|
||||
CodingLoRa, //!< Standard LoRa
|
||||
CodingASCII, //!< plain ASCII (7 bits)
|
||||
CodingTTY //!< plain TTY (5 bits)
|
||||
CodingTTY, //!< plain TTY (5 bits)
|
||||
CodingFT //!< FT8/4 scheme (payload 174 bits LDPC)
|
||||
};
|
||||
|
||||
enum MessageType
|
||||
|
@ -13,9 +13,7 @@ LoRa is a property of Semtech and the details of the protocol are not made publi
|
||||
|
||||
This LoRa encoder is designed for experimentation. For production grade applications it is recommended to use dedicated hardware instead.
|
||||
|
||||
Modulation characteristics from LoRa have been augmented with more bandwidths and FFT bin collations (DE factor). Plain TTY and ASCII have also been added and there are plans to add some more complex typically amateur radio MFSK based modes like JT65.
|
||||
|
||||
Note: this plugin is officially supported since version 6.
|
||||
Modulation characteristics from LoRa have been augmented with more bandwidths and FFT bin collations (DE factor). Plain TTY and ASCII have also been added that match character value to symbols directly. The FT protocol used in FT8 and FT4 is introduced packing the 174 bits payload into (SF -DE) bits symbols. There are plans to add some more of these typically amateur radio MFSK based modes like JT65.
|
||||
|
||||
<h2>Interface</h2>
|
||||
|
||||
@ -106,6 +104,7 @@ To populate messages you can specify your callsign (10.5), the other party calls
|
||||
- **LoRa**: LoRa compatible
|
||||
- **ASCII**: 7 bit plain ASCII without FEC and CRC. Requires exactly 7 bit effective samples thus SF-DE = 7 where SF is the spreading factor (5) and DE the distance enhancement factor (6)
|
||||
- **TTY**: 5 bit Baudot (Teletype) without FEC and CRC. Requires exactly 5 bit effective samples thus SF-DE = 5 where SF is the spreading factor (5) and DE the distance enhancement factor (6)
|
||||
- **FT**: FT8/FT4 coding is applied using data in (10.5) to (10.8) to encode the 174 bit message payload with CRC and FEC as per FT8/FT4 protocol using a type 1 (standard) type of message. Note that the report (10.8) must comply with the FT rule (coded "-35" to "+99" with a leading 0 for the number) and would usually represent the integer part of the S/N ratio in the ChirpChat demodulator receiver. Calls should not be prefixed nor suffixed and the first 4 characters of the locator must represent a valid 4 character grid square. Plain text messages (13 characters) are also supported with the 0.0 type of message using the text entered in the message box (11). These 174 bits are packed into (SF - DE) bits symbols padded with zero bits if necessary. For the details of the FT protocol see: https://wsjt.sourceforge.io/FT4_FT8_QEX.pdf
|
||||
|
||||
<h4>10.2: Number of FEC parity bits (LoRa)</h4>
|
||||
|
||||
@ -157,6 +156,19 @@ This lets you choose which pre-formatted message to send:
|
||||
- **Text**: plain text
|
||||
- **Bytes**: binary message in the form of a string of bytes. Use the hex window (12) to specify the message
|
||||
|
||||
In FT mode standard FT type messages are generated regardless of placeholders based on MyCall, YourCall, MyLoc, Report and Msg data (entered while in "Text" format). Locators are 4 character grids i.e. only the 4 first characters are taken. Reports must be valid FT reports from -35 to 99 coded as < sign>< zero padded value> (e.g -12, -04, +00, +04, +12) :
|
||||
|
||||
- **Beacon**: DE < MyCall > < MyLoc >
|
||||
- **CQ**: CQ < MyCall> < MyLoc >
|
||||
- **Reply**: < YourCall > < MyCall > < MyLoc >
|
||||
- **Report**: < YourCall > < MyCall > < Report >
|
||||
- **R-Report**: < YourCall > < MyCall > R< Report >
|
||||
- **RRR**: < YourCall > < MyCall > RRR
|
||||
- **73**: < YourCall > < MyCall > 73
|
||||
- **QSO text**: < Msg >
|
||||
- **Text**: < Msg >
|
||||
- **Bytes**: < Msg >
|
||||
|
||||
<h4>10.10: Revert to standard messages</h4>
|
||||
|
||||
Reformat all predefined messages in standard messages with placeholders. The Generate button (13) replaces the placeholders with the given QSO elements (10.5 to 10.8)
|
||||
|
@ -98,16 +98,16 @@ void TestFT8Protocols::testMsg1(const QStringList& argElements, bool runLDPC)
|
||||
|
||||
|
||||
std::string locstr;
|
||||
int report;
|
||||
int reply;
|
||||
|
||||
if (argElements[3].startsWith("R+") || argElements[3].startsWith("R-"))
|
||||
{
|
||||
report = 1;
|
||||
reply = 1;
|
||||
locstr = argElements[3].mid(1).toStdString();
|
||||
}
|
||||
else
|
||||
{
|
||||
report = 0;
|
||||
reply = 0;
|
||||
locstr = argElements[3].toStdString();
|
||||
}
|
||||
|
||||
@ -121,14 +121,13 @@ void TestFT8Protocols::testMsg1(const QStringList& argElements, bool runLDPC)
|
||||
|
||||
int a77[77];
|
||||
std::fill(a77, a77 + 77, 0);
|
||||
FT8::Packing::pack1(a77, c28_1, c28_2, g15, report);
|
||||
FT8::Packing::pack1(a77, c28_1, c28_2, g15, reply);
|
||||
FT8::Packing packing;
|
||||
|
||||
std::string call1, call2, loc;
|
||||
std::string msg = packing.unpack_1(a77, call1, call2, loc);
|
||||
qInfo("TestFT8Protocols::testMsg1: msg: %s, call1: %s, call2: %s, loc: %s", msg.c_str(), call1.c_str(), call2.c_str(), loc.c_str());
|
||||
|
||||
|
||||
if (runLDPC)
|
||||
{
|
||||
if (testLDPC(a77)) {
|
||||
|
Loading…
Reference in New Issue
Block a user