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:
parent
bedf682ef2
commit
22a668394e
@ -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)
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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;
|
||||
}
|
||||
@ -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);
|
||||
};
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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)));
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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>
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user