1
0
mirror of https://github.com/f4exb/sdrangel.git synced 2025-11-17 05:33:33 -05:00

LoRa: optimize non LoRa modes. Improve preamble detection. GUI updates

This commit is contained in:
f4exb 2020-03-05 07:12:41 +01:00
parent bedf682ef2
commit 22a668394e
13 changed files with 180 additions and 174 deletions

View File

@ -239,7 +239,7 @@ void ChirpChatDemodGUI::on_clear_clicked(bool checked)
{
(void) checked;
ui->messageText->clear();
ui->hexText->clear();
ui->messageText->clear();
}
void ChirpChatDemodGUI::on_eomSquelch_valueChanged(int value)
@ -410,8 +410,7 @@ ChirpChatDemodGUI::ChirpChatDemodGUI(PluginAPI* pluginAPI, DeviceUISet *deviceUI
ui->deltaFrequency->setValueRange(false, 7, -9999999, 9999999);
ui->messageText->setReadOnly(true);
ui->syncWord->setReadOnly(true);
ui->hexText->setReadOnly(true);
ui->messageText->setReadOnly(true);
m_channelMarker.setMovable(true);
m_channelMarker.setVisible(true);
@ -602,7 +601,6 @@ void ChirpChatDemodGUI::showLoRaMessage(const Message& message)
QByteArray bytes = msg.getBytes();
QString syncWordStr((tr("%1").arg(msg.getSyncWord(), 2, 16, QChar('0'))));
ui->syncWord->setText(tr("%1").arg(syncWordStr));
ui->sText->setText(tr("%1").arg(msg.getSingalDb(), 0, 'f', 1));
ui->snrText->setText(tr("%1").arg(msg.getSingalDb() - msg.getNoiseDb(), 0, 'f', 1));
unsigned int packetLength;
@ -650,7 +648,8 @@ void ChirpChatDemodGUI::showLoRaMessage(const Message& message)
.arg(getParityStr(msg.getPayloadParityStatus()))
.arg(msg.getPayloadCRCStatus() ? "ok" : "err");
displayBytes(loRaHeader, bytes);
displayStatus(loRaHeader);
displayBytes(bytes);
QByteArray bytesCopy(bytes);
bytesCopy.truncate(packetLength);
@ -658,7 +657,7 @@ void ChirpChatDemodGUI::showLoRaMessage(const Message& message)
QString str = QString(bytesCopy.toStdString().c_str());
QString textHeader(tr("%1 (%2)").arg(dateStr).arg(syncWordStr));
displayText(textHeader, str);
displayText(str);
displayLoRaStatus(msg.getHeaderParityStatus(), msg.getHeaderCRCStatus(), msg.getPayloadParityStatus(), msg.getPayloadCRCStatus());
}
@ -672,10 +671,6 @@ void ChirpChatDemodGUI::showTextMessage(const Message& message)
QDateTime dt = QDateTime::currentDateTime();
QString dateStr = dt.toString("HH:mm:ss");
QString syncWordStr((tr("%1").arg(msg.getSyncWord(), 2, 16, QChar('0'))));
QString textHeader(tr("%1 (%2)").arg(dateStr).arg(syncWordStr));
displayText(textHeader, msg.getString());
ui->syncWord->setText(syncWordStr);
ui->sText->setText(tr("%1").arg(msg.getSingalDb(), 0, 'f', 1));
ui->snrText->setText(tr("%1").arg(msg.getSingalDb() - msg.getNoiseDb(), 0, 'f', 1));
@ -683,30 +678,31 @@ void ChirpChatDemodGUI::showTextMessage(const Message& message)
.arg(dateStr)
.arg(msg.getSingalDb(), 0, 'f', 1)
.arg(msg.getSingalDb() - msg.getNoiseDb(), 0, 'f', 1);
displayStatus(status);
displayText(msg.getString());
}
void ChirpChatDemodGUI::displayText(const QString& header, const QString& text)
void ChirpChatDemodGUI::displayText(const QString& text)
{
QTextCursor cursor = ui->messageText->textCursor();
cursor.movePosition(QTextCursor::End, QTextCursor::MoveAnchor);
if (!ui->messageText->document()->isEmpty()) {
cursor.insertText("\n");
}
cursor.insertText(tr("%1 %2").arg(header).arg(text));
cursor.insertText(tr("TXT|%1").arg(text));
ui->messageText->verticalScrollBar()->setValue(ui->messageText->verticalScrollBar()->maximum());
}
void ChirpChatDemodGUI::displayBytes(const QString& header, const QByteArray& bytes)
void ChirpChatDemodGUI::displayBytes(const QByteArray& bytes)
{
QTextCursor cursor = ui->hexText->textCursor();
QTextCursor cursor = ui->messageText->textCursor();
cursor.movePosition(QTextCursor::End, QTextCursor::MoveAnchor);
if (!ui->hexText->document()->isEmpty()) {
if (!ui->messageText->document()->isEmpty()) {
cursor.insertText("\n");
}
cursor.insertText(tr(">%1\n").arg(header));
QByteArray::const_iterator it = bytes.begin();
unsigned int i = 0;
@ -729,20 +725,20 @@ void ChirpChatDemodGUI::displayBytes(const QString& header, const QByteArray& by
}
}
ui->hexText->verticalScrollBar()->setValue(ui->hexText->verticalScrollBar()->maximum());
ui->messageText->verticalScrollBar()->setValue(ui->messageText->verticalScrollBar()->maximum());
}
void ChirpChatDemodGUI::displayStatus(const QString& status)
{
QTextCursor cursor = ui->hexText->textCursor();
QTextCursor cursor = ui->messageText->textCursor();
cursor.movePosition(QTextCursor::End, QTextCursor::MoveAnchor);
if (!ui->hexText->document()->isEmpty()) {
if (!ui->messageText->document()->isEmpty()) {
cursor.insertText("\n");
}
cursor.insertText(tr(">%1").arg(status));
ui->hexText->verticalScrollBar()->setValue(ui->hexText->verticalScrollBar()->maximum());
ui->messageText->verticalScrollBar()->setValue(ui->messageText->verticalScrollBar()->maximum());
}
QString ChirpChatDemodGUI::getParityStr(int parityStatus)

View File

@ -112,8 +112,8 @@ private:
void setBandwidths();
void showLoRaMessage(const Message& message);
void showTextMessage(const Message& message); //!< For TTY and ASCII
void displayText(const QString& header, const QString& text);
void displayBytes(const QString& header, const QByteArray& bytes);
void displayText(const QString& text);
void displayBytes(const QByteArray& bytes);
void displayStatus(const QString& status);
void displayLoRaStatus(int headerParityStatus, bool headerCRCStatus, int payloadParityStatus, bool payloadCRCStatus);
QString getParityStr(int parityStatus);

View File

@ -6,7 +6,7 @@
<rect>
<x>0</x>
<y>0</y>
<width>552</width>
<width>532</width>
<height>680</height>
</rect>
</property>
@ -562,28 +562,20 @@
<string>Msg</string>
</property>
</widget>
<widget class="QLabel" name="hexLabel">
<property name="geometry">
<rect>
<x>2</x>
<y>145</y>
<width>32</width>
<height>16</height>
</rect>
</property>
<property name="text">
<string>Hex</string>
</property>
</widget>
<widget class="QPlainTextEdit" name="messageText">
<property name="geometry">
<rect>
<x>30</x>
<y>60</y>
<width>490</width>
<height>80</height>
<height>161</height>
</rect>
</property>
<property name="font">
<font>
<family>Liberation Mono</family>
</font>
</property>
</widget>
<widget class="QLabel" name="schemeLabel">
<property name="geometry">
@ -784,28 +776,6 @@
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
<widget class="QLineEdit" name="syncWord">
<property name="geometry">
<rect>
<x>492</x>
<y>10</y>
<width>25</width>
<height>20</height>
</rect>
</property>
<property name="focusPolicy">
<enum>Qt::ClickFocus</enum>
</property>
<property name="toolTip">
<string>Sync word (1 byte hex)</string>
</property>
<property name="inputMask">
<string>HH</string>
</property>
<property name="text">
<string>00</string>
</property>
</widget>
<widget class="QLabel" name="loraLabel">
<property name="geometry">
<rect>
@ -902,22 +872,6 @@
<string>FEC</string>
</property>
</widget>
<widget class="QPlainTextEdit" name="hexText">
<property name="geometry">
<rect>
<x>30</x>
<y>145</y>
<width>490</width>
<height>75</height>
</rect>
</property>
<property name="font">
<font>
<family>Liberation Mono</family>
<pointsize>9</pointsize>
</font>
</property>
</widget>
<widget class="QLabel" name="packetLengthLabel">
<property name="geometry">
<rect>
@ -969,19 +923,6 @@
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
<widget class="QLabel" name="syncWordLabel">
<property name="geometry">
<rect>
<x>456</x>
<y>10</y>
<width>30</width>
<height>19</height>
</rect>
</property>
<property name="text">
<string>Sync</string>
</property>
</widget>
<widget class="QLabel" name="headerHammingStatus">
<property name="geometry">
<rect>

View File

@ -202,3 +202,19 @@ bool ChirpChatDemodSettings::deserialize(const QByteArray& data)
return false;
}
}
unsigned int ChirpChatDemodSettings::getNbSFDFourths() const
{
switch (m_codingScheme)
{
case CodingLoRa:
return 9;
default:
return 8;
}
}
bool ChirpChatDemodSettings::hasSyncWord() const
{
return m_codingScheme == CodingLoRa;
}

View File

@ -72,6 +72,8 @@ struct ChirpChatDemodSettings
void resetToDefaults();
void setChannelMarker(Serializable *channelMarker) { m_channelMarker = channelMarker; }
void setSpectrumGUI(Serializable *spectrumGUI) { m_spectrumGUI = spectrumGUI; }
unsigned int getNbSFDFourths() const; //!< Get the number of SFD period fourths (depends on coding scheme)
bool hasSyncWord() const; //!< Only LoRa has a syncword (for the moment)
QByteArray serialize() const;
bool deserialize(const QByteArray& data);
};

View File

@ -82,9 +82,12 @@ void ChirpChatDemodSink::initSF(unsigned int sf, unsigned int deBits)
m_nbSymbols = 1 << sf;
m_nbSymbolsEff = 1 << (sf - deBits);
m_deLength = 1 << deBits;
m_fftLength = m_nbSymbols;
m_fft->configure(m_fftInterpolation*m_fftLength, false);
m_fftSFD->configure(m_fftInterpolation*m_fftLength, false);
m_interpolatedFFTLength = m_fftInterpolation*m_fftLength;
m_preambleTolerance = (m_deLength*m_fftInterpolation)/2;
m_fft->configure(m_interpolatedFFTLength, false);
m_fftSFD->configure(m_interpolatedFFTLength, false);
m_state = ChirpChatStateReset;
m_sfdSkip = m_fftLength / 4;
m_fftWindow.create(FFTWindow::Function::Kaiser, m_fftLength);
@ -146,7 +149,7 @@ void ChirpChatDemodSink::processSample(const Complex& ci)
if (m_fftCounter == m_fftLength)
{
m_fftWindow.apply(m_fft->in());
std::fill(m_fft->in()+m_fftLength, m_fft->in()+m_fftInterpolation*m_fftLength, Complex{0.0, 0.0});
std::fill(m_fft->in()+m_fftLength, m_fft->in()+m_interpolatedFFTLength, Complex{0.0, 0.0});
m_fft->transform();
m_fftCounter = 0;
double magsq, magsqTotal;
@ -176,11 +179,20 @@ void ChirpChatDemodSink::processSample(const Complex& ci)
for (int i = 1; i < m_requiredPreambleChirps; i++)
{
if (m_argMaxHistory[0] != m_argMaxHistory[i])
int delta = m_argMaxHistory[i] - m_argMaxHistory[i-1];
// qDebug("ChirpChatDemodSink::processSample: search: delta: %d / %d", delta, m_deLength);
if ((delta < -m_preambleTolerance) || (delta > m_preambleTolerance))
{
preambleFound = false;
break;
}
// if (m_argMaxHistory[0] != m_argMaxHistory[i])
// {
// preambleFound = false;
// break;
// }
}
if ((preambleFound) && (magsq > 1e-9))
@ -227,11 +239,11 @@ void ChirpChatDemodSink::processSample(const Complex& ci)
if (m_fftCounter == m_fftLength)
{
m_fftWindow.apply(m_fft->in());
std::fill(m_fft->in()+m_fftLength, m_fft->in()+m_fftInterpolation*m_fftLength, Complex{0.0, 0.0});
std::fill(m_fft->in()+m_fftLength, m_fft->in()+m_interpolatedFFTLength, Complex{0.0, 0.0});
m_fft->transform();
m_fftWindow.apply(m_fftSFD->in());
std::fill(m_fftSFD->in()+m_fftLength, m_fftSFD->in()+m_fftInterpolation*m_fftLength, Complex{0.0, 0.0});
std::fill(m_fftSFD->in()+m_fftLength, m_fftSFD->in()+m_interpolatedFFTLength, Complex{0.0, 0.0});
m_fftSFD->transform();
m_fftCounter = 0;
@ -265,23 +277,30 @@ void ChirpChatDemodSink::processSample(const Complex& ci)
{
m_magsqTotalAvg(magsqSFDTotal);
if (m_chirpCount < 3) // too early
if (m_chirpCount < 1 + (m_settings.hasSyncWord() ? 2 : 0)) // too early
{
m_state = ChirpChatStateReset;
qDebug("ChirpChatDemodSink::processSample: SFD search: signal drop is too early");
}
else
{
m_syncWord = round(m_preambleHistory[m_chirpCount-2] / 8.0);
m_syncWord += 16 * round(m_preambleHistory[m_chirpCount-3] / 8.0);
qDebug("ChirpChatDemodSink::processSample: SFD found: up: %4u|%11.6f - down: %4u|%11.6f sync: %x", imax, magsq, imaxSFD, magsqSFD, m_syncWord);
if (m_settings.hasSyncWord())
{
m_syncWord = round(m_preambleHistory[m_chirpCount-2] / 8.0);
m_syncWord += 16 * round(m_preambleHistory[m_chirpCount-3] / 8.0);
qDebug("ChirpChatDemodSink::processSample: SFD found: up: %4u|%11.6f - down: %4u|%11.6f sync: %x", imax, magsq, imaxSFD, magsqSFD, m_syncWord);
}
else
{
qDebug("ChirpChatDemodSink::processSample: SFD found: up: %4u|%11.6f - down: %4u|%11.6f", imax, magsq, imaxSFD, magsqSFD);
}
int sadj = 0;
int nadj = 0;
int zadj;
int sfdSkip = m_sfdSkip;
for (int i = 0; i < m_chirpCount-3; i++)
for (int i = 0; i < m_chirpCount - 1 - (m_settings.hasSyncWord() ? 2 : 0); i++)
{
sadj += m_preambleHistory[i] > m_nbSymbols/2 ? m_preambleHistory[i] - m_nbSymbols : m_preambleHistory[i];
nadj++;
@ -315,7 +334,7 @@ void ChirpChatDemodSink::processSample(const Complex& ci)
}
}
}
else if (m_state == ChirpChatStateSkipSFD) // Just skip SFD
else if (m_state == ChirpChatStateSkipSFD) // Just skip the rest of SFD
{
m_fftCounter++;
@ -324,13 +343,12 @@ void ChirpChatDemodSink::processSample(const Complex& ci)
m_fftCounter = m_fftLength - m_sfdSkip;
m_sfdSkipCounter++;
if (m_sfdSkipCounter == m_sfdFourths) // 1.25 SFD chips left
if (m_sfdSkipCounter == m_settings.getNbSFDFourths() - 4U) // SFD chips fourths less one full period
{
qDebug("ChirpChatDemodSink::processSample: SFD skipped");
m_chirp = m_chirp0;
m_fftCounter = 0;
m_chirpCount = 0;
int correction = 0;
m_magsqMax = 0.0;
m_decodeMsg = ChirpChatDemodMsg::MsgDecodeSymbols::create();
m_decodeMsg->setSyncWord(m_syncWord);
@ -346,7 +364,7 @@ void ChirpChatDemodSink::processSample(const Complex& ci)
if (m_fftCounter == m_fftLength)
{
m_fftWindow.apply(m_fft->in());
std::fill(m_fft->in()+m_fftLength, m_fft->in()+m_fftInterpolation*m_fftLength, Complex{0.0, 0.0});
std::fill(m_fft->in()+m_fftLength, m_fft->in()+m_interpolatedFFTLength, Complex{0.0, 0.0});
m_fft->transform();
m_fftCounter = 0;
double magsq, magsqTotal;

View File

@ -77,7 +77,6 @@ private:
static const unsigned int m_requiredPreambleChirps = 4; //!< Number of chirps required to estimate preamble
static const unsigned int m_maxSFDSearchChirps = 8; //!< Maximum number of chirps when looking for SFD after preamble detection
static const unsigned int m_sfdFourths = 5; //!< Number of SFD chip period fourths to skip until payload
static const unsigned int m_fftInterpolation = 2; //!< FFT interpolation factor (usually a power of 2)
FFTEngine *m_fft;
@ -87,7 +86,7 @@ private:
Complex *m_upChirps;
Complex *m_spectrumLine;
unsigned int m_fftCounter;
unsigned int m_argMaxHistory[m_requiredPreambleChirps];
int m_argMaxHistory[m_requiredPreambleChirps];
unsigned int m_argMaxHistoryCounter;
unsigned int m_preambleHistory[m_maxSFDSearchChirps];
unsigned int m_syncWord;
@ -108,9 +107,12 @@ private:
BasebandSampleSink* m_spectrumSink;
Complex *m_spectrumBuffer;
unsigned int m_nbSymbols;
unsigned int m_nbSymbolsEff; //!< effective symbols considering DE bits
unsigned int m_fftLength;
unsigned int m_nbSymbols; //!< Number of symbols = length of base FFT
unsigned int m_nbSymbolsEff; //!< effective symbols considering DE bits
unsigned int m_fftLength; //!< Length of base FFT
unsigned int m_interpolatedFFTLength; //!< Length of interpolated FFT
int m_deLength; //!< Number of FFT bins collated to represent one symbol
int m_preambleTolerance; //!< Number of FFT bins to collate when looking for preamble
void processSample(const Complex& ci);
void initSF(unsigned int sf, unsigned int deBits); //!< Init tables, FFTs, depending on spread factor

View File

@ -109,7 +109,10 @@ bool ChirpChatModGUI::handleMessage(const Message& message)
{
const ChirpChatMod::MsgReportPayloadTime& rpt = (ChirpChatMod::MsgReportPayloadTime&) message;
float fourthsMs = ((1<<m_settings.m_spreadFactor) * 250.0) / ChirpChatModSettings::bandwidths[m_settings.m_bandwidthIndex];
float controlMs = (4*m_settings.m_preambleChirps + 8 + 9) * fourthsMs; // preamble + sync word + SFD
int fourthsChirps = 4*m_settings.m_preambleChirps;
fourthsChirps += m_settings.hasSyncWord() ? 8 : 0;
fourthsChirps += m_settings.getNbSFDFourths();
float controlMs = fourthsChirps * fourthsMs; // preamble + sync word + SFD
ui->timePayloadText->setText(tr("%1 ms").arg(QString::number(rpt.getPayloadTimeMs(), 'f', 0)));
ui->timeTotalText->setText(tr("%1 ms").arg(QString::number(rpt.getPayloadTimeMs() + controlMs, 'f', 0)));
ui->timeSymbolText->setText(tr("%1 ms").arg(QString::number(4.0*fourthsMs, 'f', 1)));

View File

@ -6,7 +6,7 @@
<rect>
<x>0</x>
<y>0</y>
<width>392</width>
<width>402</width>
<height>373</height>
</rect>
</property>
@ -30,7 +30,7 @@
<rect>
<x>1</x>
<y>20</y>
<width>390</width>
<width>400</width>
<height>125</height>
</rect>
</property>
@ -74,7 +74,7 @@
<rect>
<x>40</x>
<y>50</y>
<width>251</width>
<width>261</width>
<height>16</height>
</rect>
</property>
@ -102,7 +102,7 @@
<rect>
<x>40</x>
<y>70</y>
<width>81</width>
<width>101</width>
<height>16</height>
</rect>
</property>
@ -131,7 +131,7 @@
<widget class="QLabel" name="spreadText">
<property name="geometry">
<rect>
<x>130</x>
<x>150</x>
<y>70</y>
<width>30</width>
<height>16</height>
@ -153,7 +153,7 @@
<widget class="QLabel" name="bwText">
<property name="geometry">
<rect>
<x>300</x>
<x>310</x>
<y>50</y>
<width>80</width>
<height>16</height>
@ -175,7 +175,7 @@
<widget class="QLabel" name="deBitsLabel">
<property name="geometry">
<rect>
<x>180</x>
<x>200</x>
<y>70</y>
<width>32</width>
<height>16</height>
@ -188,7 +188,7 @@
<widget class="QLabel" name="deBitsText">
<property name="geometry">
<rect>
<x>280</x>
<x>370</x>
<y>70</y>
<width>10</width>
<height>16</height>
@ -210,9 +210,9 @@
<widget class="QSlider" name="deBits">
<property name="geometry">
<rect>
<x>210</x>
<x>240</x>
<y>70</y>
<width>61</width>
<width>91</width>
<height>16</height>
</rect>
</property>
@ -243,7 +243,7 @@
<rect>
<x>10</x>
<y>10</y>
<width>371</width>
<width>381</width>
<height>26</height>
</rect>
</property>
@ -366,7 +366,7 @@
<rect>
<x>40</x>
<y>90</y>
<width>81</width>
<width>101</width>
<height>16</height>
</rect>
</property>
@ -408,7 +408,7 @@
<widget class="QLabel" name="preambleChirpsText">
<property name="geometry">
<rect>
<x>130</x>
<x>150</x>
<y>90</y>
<width>30</width>
<height>16</height>
@ -430,7 +430,7 @@
<widget class="QLabel" name="idleTimeLabel">
<property name="geometry">
<rect>
<x>180</x>
<x>200</x>
<y>90</y>
<width>32</width>
<height>16</height>
@ -443,9 +443,9 @@
<widget class="QSlider" name="idleTime">
<property name="geometry">
<rect>
<x>220</x>
<x>240</x>
<y>90</y>
<width>81</width>
<width>91</width>
<height>16</height>
</rect>
</property>
@ -474,7 +474,7 @@
<widget class="QLabel" name="idleTimeText">
<property name="geometry">
<rect>
<x>320</x>
<x>350</x>
<y>90</y>
<width>30</width>
<height>16</height>
@ -493,48 +493,13 @@
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
<widget class="QLabel" name="syncLabel">
<property name="geometry">
<rect>
<x>310</x>
<y>70</y>
<width>32</width>
<height>16</height>
</rect>
</property>
<property name="text">
<string>Sync</string>
</property>
</widget>
<widget class="QLineEdit" name="syncWord">
<property name="geometry">
<rect>
<x>350</x>
<y>68</y>
<width>30</width>
<height>20</height>
</rect>
</property>
<property name="focusPolicy">
<enum>Qt::ClickFocus</enum>
</property>
<property name="toolTip">
<string>Sync word (1 byte hex)</string>
</property>
<property name="inputMask">
<string>HH</string>
</property>
<property name="text">
<string>00</string>
</property>
</widget>
</widget>
<widget class="QWidget" name="messageContainer" native="true">
<property name="geometry">
<rect>
<x>1</x>
<y>150</y>
<width>390</width>
<width>400</width>
<height>221</height>
</rect>
</property>
@ -807,7 +772,7 @@
<rect>
<x>40</x>
<y>110</y>
<width>341</width>
<width>355</width>
<height>60</height>
</rect>
</property>
@ -830,7 +795,7 @@
<rect>
<x>40</x>
<y>175</y>
<width>341</width>
<width>355</width>
<height>20</height>
</rect>
</property>
@ -964,7 +929,7 @@
<widget class="QLabel" name="timeTotalLabel">
<property name="geometry">
<rect>
<x>290</x>
<x>300</x>
<y>200</y>
<width>25</width>
<height>16</height>
@ -980,7 +945,7 @@
<widget class="QLabel" name="timeTotalText">
<property name="geometry">
<rect>
<x>320</x>
<x>330</x>
<y>200</y>
<width>60</width>
<height>16</height>
@ -1037,7 +1002,7 @@
<widget class="QCheckBox" name="header">
<property name="geometry">
<rect>
<x>290</x>
<x>285</x>
<y>10</y>
<width>50</width>
<height>16</height>
@ -1053,7 +1018,7 @@
<widget class="QCheckBox" name="crc">
<property name="geometry">
<rect>
<x>230</x>
<x>226</x>
<y>10</y>
<width>50</width>
<height>16</height>
@ -1168,6 +1133,41 @@
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
<widget class="QLineEdit" name="syncWord">
<property name="geometry">
<rect>
<x>377</x>
<y>8</y>
<width>22</width>
<height>20</height>
</rect>
</property>
<property name="focusPolicy">
<enum>Qt::ClickFocus</enum>
</property>
<property name="toolTip">
<string>Sync word (1 byte hex)</string>
</property>
<property name="inputMask">
<string>HH</string>
</property>
<property name="text">
<string>00</string>
</property>
</widget>
<widget class="QLabel" name="syncLabel">
<property name="geometry">
<rect>
<x>342</x>
<y>10</y>
<width>32</width>
<height>16</height>
</rect>
</property>
<property name="text">
<string>Sync</string>
</property>
</widget>
</widget>
</widget>
<customwidgets>

View File

@ -122,6 +122,22 @@ void ChirpChatModSettings::generateMessages()
.arg(m_urCall).arg(m_myCall).arg(m_textMessage);
}
unsigned int ChirpChatModSettings::getNbSFDFourths() const
{
switch (m_codingScheme)
{
case CodingLoRa:
return 9;
default:
return 8;
}
}
bool ChirpChatModSettings::hasSyncWord() const
{
return m_codingScheme == CodingLoRa;
}
QByteArray ChirpChatModSettings::serialize() const
{
SimpleSerializer s(1);

View File

@ -96,6 +96,8 @@ struct ChirpChatModSettings
void resetToDefaults();
void setDefaultTemplates();
void generateMessages();
unsigned int getNbSFDFourths() const; //!< Get the number of SFD period fourths (depends on coding scheme)
bool hasSyncWord() const; //!< Only LoRa has a syncword (for the moment)
void setChannelMarker(Serializable *channelMarker) { m_channelMarker = channelMarker; }
QByteArray serialize() const;
bool deserialize(const QByteArray& data);

View File

@ -233,10 +233,20 @@ void ChirpChatModSource::modulateSample()
if (m_chirpCount == m_settings.m_preambleChirps)
{
m_chirpCount = 0;
m_chirp0 = ((m_settings.m_syncWord >> ((1-m_chirpCount)*4)) & 0xf)*8;
m_chirp = (m_chirp0 + m_fftLength)*ChirpChatModSettings::oversampling - 1;
m_fftCounter = 0;
m_state = ChirpChatStateSyncWord;
if (m_settings.hasSyncWord())
{
m_chirp0 = ((m_settings.m_syncWord >> ((1-m_chirpCount)*4)) & 0xf)*8;
m_chirp = (m_chirp0 + m_fftLength)*ChirpChatModSettings::oversampling - 1;
m_state = ChirpChatStateSyncWord;
}
else
{
m_sampleCounter = 0;
m_chirp0 = 0;
m_chirp = m_fftLength*ChirpChatModSettings::oversampling - 1;
m_state = ChirpChatStateSFD;
}
}
}
}
@ -286,7 +296,7 @@ void ChirpChatModSource::modulateSample()
m_sampleCounter = 0;
}
if (m_chirpCount == 9)
if (m_chirpCount == m_settings.getNbSFDFourths())
{
m_fftCounter = 0;
m_chirpCount = 0;

View File

@ -82,7 +82,7 @@ In practice it is difficult on the Rx side to make correct decodes if only one F
<h3>7: Sync word</h3>
This is the sync word (byte) to transmit entered as a 2 nibble hexadecimal number.
This is a LoRa specific feature and is the sync word (byte) to transmit entered as a 2 nibble hexadecimal number.
<h3>8: Number of preamble chirps</h3>