Skip to content

Commit

Permalink
Implemented message templates for radioddity devices. Addresses #413.
Browse files Browse the repository at this point in the history
  • Loading branch information
hmatuschek committed May 20, 2024
1 parent ca1ad78 commit d630070
Show file tree
Hide file tree
Showing 15 changed files with 199 additions and 19 deletions.
8 changes: 8 additions & 0 deletions lib/gd77_codeplug.cc
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,14 @@ void
GD77Codeplug::clearMessages() {
MessageBankElement(data(ADDR_MESSAGE_BANK)).clear();
}
bool
GD77Codeplug::encodeMessages(Context &ctx, const Flags &flags, const ErrorStack &err) {
return MessageBankElement(data(Offset::messages())).encode(ctx, flags, err);
}
bool
GD77Codeplug::decodeMessages(Context &ctx, const ErrorStack &err) {
return MessageBankElement(data(Offset::messages())).decode(ctx, err);
}

void
GD77Codeplug::clearScanLists() {
Expand Down
3 changes: 3 additions & 0 deletions lib/gd77_codeplug.hh
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,8 @@ public:
bool decodeButtonSettings(Context &ctx, const ErrorStack &err=ErrorStack());

void clearMessages();
bool encodeMessages(Context &ctx, const Flags &flags, const ErrorStack &err=ErrorStack());
bool decodeMessages(Context &ctx, const ErrorStack &err=ErrorStack());

void clearScanLists();
bool encodeScanLists(Config *config, const Flags &flags, Context &ctx, const ErrorStack &err=ErrorStack());
Expand Down Expand Up @@ -310,6 +312,7 @@ protected:
struct Offset {
/// @cond DO_NOT_DOCUMENT
static constexpr unsigned int buttonSettings() { return 0x000108; }
static constexpr unsigned int messages() { return 0x000128; }
/// @endcond
};
};
Expand Down
5 changes: 0 additions & 5 deletions lib/opengd77_codeplug.cc
Original file line number Diff line number Diff line change
Expand Up @@ -540,11 +540,6 @@ OpenGD77Codeplug::clearButtonSettings() {
/// @bug Find button settings within OpenGD77 codeplug.
}

void
OpenGD77Codeplug::clearMessages() {
MessageBankElement(data(ADDR_MESSAGE_BANK, IMAGE_MESSAGE_BANK)).clear();
}

void
OpenGD77Codeplug::clearScanLists() {
// Scan lists are not touched with OpenGD77 codeplug
Expand Down
1 change: 0 additions & 1 deletion lib/opengd77_codeplug.hh
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,6 @@ public:
bool decodeGeneralSettings(Config *config, Context &ctx, const ErrorStack &err=ErrorStack());

void clearButtonSettings();
void clearMessages();

void clearScanLists();
bool encodeScanLists(Config *config, const Flags &flags, Context &ctx, const ErrorStack &err=ErrorStack());
Expand Down
55 changes: 45 additions & 10 deletions lib/radioddity_codeplug.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2518,35 +2518,60 @@ RadioddityCodeplug::MessageBankElement::~MessageBankElement() {

void
RadioddityCodeplug::MessageBankElement::clear() {
setUInt8(0x0000, 0); // set count to 0
setUInt8(Offset::messageConut(), 0); // set count to 0
memset(_data+0x0001, 0x00, 7); // Fill unused
memset(_data+0x0008, 0x00, 32); // Set message lengths to 0
memset(_data+Offset::messageLengths(), 0x00, Limit::messages()); // Set message lengths to 0
memset(_data+0x0028, 0x00, 32); // Fill unused
memset(_data+0x0048, 0xff, 32*144); // Clear all messages
memset(_data+Offset::messages(), 0xff, Limit::messages()*Limit::messageLength()); // Clear all messages
}

unsigned
RadioddityCodeplug::MessageBankElement::numMessages() const {
return getUInt8(0x0000);
return getUInt8(Offset::messageConut());
}
QString
RadioddityCodeplug::MessageBankElement::message(unsigned n) const {
if (n >= numMessages())
return QString();
return readASCII(0x0048+n*144, 144, 0xff);
return readASCII(Offset::messages()+n*Offset::betweenMessages(), Limit::messageLength(), 0xff);
}
void
RadioddityCodeplug::MessageBankElement::appendMessage(const QString msg) {
unsigned idx = numMessages();
if (idx >= 32)
if (idx >= Limit::messages())
return;
unsigned len = std::min(msg.size(), 144);
unsigned int len = std::min((unsigned int)msg.size(), Limit::messageLength());
// increment counter
setUInt8(0x0000, idx+1);
setUInt8(Offset::messageConut(), idx+1);
// store length
setUInt8(0x0008+idx, len);
setUInt8(Offset::messageLengths()+idx, len);
// store string
writeASCII(0x0048+144*len, msg, 144, 0xff);
writeASCII(Offset::messages()+Offset::betweenMessages()*idx, msg, Limit::messageLength(), 0xff);
}

bool
RadioddityCodeplug::MessageBankElement::encode(Context &ctx, const Flags &flags, const ErrorStack &err) {
Q_UNUSED(flags); Q_UNUSED(err)
clear();
unsigned int count = std::min(
Limit::messages(), (unsigned int)ctx.config()->smsExtension()->smsTemplates()->count());
for (unsigned int i=0; i<count; i++)
appendMessage(ctx.config()->smsExtension()->smsTemplates()->message(i)->message());
return true;
}

bool
RadioddityCodeplug::MessageBankElement::decode(Context &ctx, const ErrorStack &err) {
Q_UNUSED(err);

for (unsigned int i=0; i<numMessages(); i++) {
SMSTemplate *sms = new SMSTemplate();
sms->setName(QString("Message %1").arg(i+1));
sms->setMessage(message(i));
ctx.config()->smsExtension()->smsTemplates()->add(sms);
}

return true;
}


Expand Down Expand Up @@ -2819,6 +2844,11 @@ RadioddityCodeplug::encodeElements(const Flags &flags, Context &ctx, const Error
return false;
}

if (! this->encodeMessages(ctx, flags, err)) {
errMsg(err) << "Cannot encode preset messages.";
return false;
}

// Define Contacts
if (! this->encodeContacts(ctx.config(), flags, ctx, err)) {
errMsg(err) << "Cannot encode contacts.";
Expand Down Expand Up @@ -2903,6 +2933,11 @@ RadioddityCodeplug::decodeElements(Context &ctx, const ErrorStack &err) {
return false;
}

if (! this->decodeMessages(ctx, err)) {
errMsg(err) << "Cannot decode preset messages.";
return false;
}

if (! this->createContacts(ctx.config(), ctx, err)) {
errMsg(err) << "Cannot create contacts.";
return false;
Expand Down
29 changes: 29 additions & 0 deletions lib/radioddity_codeplug.hh
Original file line number Diff line number Diff line change
Expand Up @@ -1321,6 +1321,8 @@ public:
/** Destructor. */
virtual ~MessageBankElement();

/** Returns the size of the message bank. */
static constexpr unsigned int size() { return 0x1248; }
/** Resets all messages. */
void clear();

Expand All @@ -1330,6 +1332,29 @@ public:
virtual QString message(unsigned n) const;
/** Appends a message to the list. */
virtual void appendMessage(const QString msg);

/** Encodes all preset messages. */
virtual bool encode(Context &ctx, const Flags &flags, const ErrorStack &err=ErrorStack());
/** Decodes all preset messages. */
virtual bool decode(Context &ctx, const ErrorStack &err=ErrorStack());

public:
/** Some limits. */
struct Limit {
static constexpr unsigned int messages() { return 32; } ///< Maximum number of messages.
static constexpr unsigned int messageLength() { return 144; } ///< Maximum length of each message.
};

protected:
/** Some internal used offset. */
struct Offset {
/// @cond DO_NOT_DOCUMENT
static constexpr unsigned int messageConut() { return 0x0000; }
static constexpr unsigned int messageLengths() { return 0x0008; }
static constexpr unsigned int messages() { return 0x0048; }
static constexpr unsigned int betweenMessages() { return Limit::messageLength(); }
/// @endcond
};
};


Expand Down Expand Up @@ -1424,6 +1449,10 @@ public:

/** Clears the messages. */
virtual void clearMessages() = 0;
/** Encodes preset messages. */
virtual bool encodeMessages(Context &ctx, const Flags &flags, const ErrorStack &err=ErrorStack()) = 0;
/** Decodes preset messages. */
virtual bool decodeMessages(Context &ctx, const ErrorStack &err=ErrorStack()) = 0;

/** Clears all contacts in the codeplug. */
virtual void clearContacts() = 0;
Expand Down
17 changes: 17 additions & 0 deletions lib/rd5r_codeplug.cc
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,23 @@ void
RD5RCodeplug::clearMessages() {
MessageBankElement(data(Offset::messages())).clear();
}
bool
RD5RCodeplug::encodeMessages(Context &ctx, const Flags &flags, const ErrorStack &err) {
if (! MessageBankElement(data(Offset::messages())).encode(ctx, flags, err)) {
errMsg(err) << "Cannot encode preset messages.";
return false;
}
return true;
}
bool
RD5RCodeplug::decodeMessages(Context &ctx, const ErrorStack &err) {
if (! MessageBankElement(data(Offset::messages())).decode(ctx, err)) {
errMsg(err) << "Cannot decode preset messages.";
return false;
}
return true;
}


void
RD5RCodeplug::clearContacts() {
Expand Down
2 changes: 2 additions & 0 deletions lib/rd5r_codeplug.hh
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,8 @@ public:
bool decodeButtonSettings(Context &ctx, const ErrorStack &err=ErrorStack());

void clearMessages();
bool encodeMessages(Context &ctx, const Flags &flags, const ErrorStack &err=ErrorStack());
bool decodeMessages(Context &ctx, const ErrorStack &err=ErrorStack());

void clearContacts();
bool encodeContacts(Config *config, const Flags &flags, Context &ctx, const ErrorStack &err=ErrorStack());
Expand Down
29 changes: 29 additions & 0 deletions test/gd77_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -62,5 +62,34 @@ GD77Test::testChannelFrequency() {
Frequency::fromHz(999999990ULL));
}

void
GD77Test::testSMSTemplates() {
Config config;
config.radioIDs()->add(new DMRRadioID("ID", 1234567));
SMSTemplate *sms0 = new SMSTemplate(); sms0->setName("SMS0"); sms0->setMessage("ABC");
SMSTemplate *sms1 = new SMSTemplate(); sms1->setName("SMS1"); sms1->setMessage("XYZ");
config.smsExtension()->smsTemplates()->add(sms0);
config.smsExtension()->smsTemplates()->add(sms1);

ErrorStack err;
GD77Codeplug codeplug;
if (! codeplug.encode(&config, Codeplug::Flags(), err)) {
QFAIL(QString("Cannot encode codeplug for Radioddity GD77: %1")
.arg(err.format()).toStdString().c_str());
}

Config decoded;
if (! codeplug.decode(&decoded, err)) {
QFAIL(QString("Cannot decode codeplug for Radioddity GD77: %1")
.arg(err.format()).toStdString().c_str());
}

QCOMPARE(decoded.smsExtension()->smsTemplates()->count(), 2);
//QCOMPARE_NE(decoded.smsExtension()->smsTemplates()->message(0)->name(), "SMS0");
QCOMPARE(decoded.smsExtension()->smsTemplates()->message(0)->message(), "ABC");
//QCOMPARE_NE(decoded.smsExtension()->smsTemplates()->message(1)->name(), "SMS1");
QCOMPARE(decoded.smsExtension()->smsTemplates()->message(1)->message(), "XYZ");
}

QTEST_GUILESS_MAIN(GD77Test)

1 change: 1 addition & 0 deletions test/gd77_test.hh
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ private slots:
void testBasicConfigEncoding();
void testBasicConfigDecoding();
void testChannelFrequency();
void testSMSTemplates();
};

#endif // GD77TEST_HH
31 changes: 31 additions & 0 deletions test/opengd77_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -64,5 +64,36 @@ OpenGD77Test::testChannelFrequency() {
Frequency::fromHz(999999990ULL));
}

void
OpenGD77Test::testSMSTemplates() {
Config config;
config.radioIDs()->add(new DMRRadioID("ID", 1234567));
SMSTemplate *sms0 = new SMSTemplate(); sms0->setName("SMS0"); sms0->setMessage("ABC");
SMSTemplate *sms1 = new SMSTemplate(); sms1->setName("SMS1"); sms1->setMessage("XYZ");
config.smsExtension()->smsTemplates()->add(sms0);
config.smsExtension()->smsTemplates()->add(sms1);

ErrorStack err;
OpenGD77Codeplug codeplug;
if (! codeplug.encode(&config, Codeplug::Flags(), err)) {
QFAIL(QString("Cannot encode codeplug for OpenGD77: %1")
.arg(err.format()).toStdString().c_str());
}

Config decoded;
if (! codeplug.decode(&decoded, err)) {
QFAIL(QString("Cannot decode codeplug for OpenGD77: %1")
.arg(err.format()).toStdString().c_str());
}

// For now, messages are not encoded
QCOMPARE(decoded.smsExtension()->smsTemplates()->count(), 2);
//QCOMPARE_NE(decoded.smsExtension()->smsTemplates()->message(0)->name(), "SMS0");
QCOMPARE(decoded.smsExtension()->smsTemplates()->message(0)->message(), "ABC");
//QCOMPARE_NE(decoded.smsExtension()->smsTemplates()->message(1)->name(), "SMS1");
QCOMPARE(decoded.smsExtension()->smsTemplates()->message(1)->message(), "XYZ");
}


QTEST_GUILESS_MAIN(OpenGD77Test)

1 change: 1 addition & 0 deletions test/opengd77_test.hh
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ private slots:
void testBasicConfigEncoding();
void testBasicConfigDecoding();
void testChannelFrequency();
void testSMSTemplates();

protected:
QTextStream _stderr;
Expand Down
30 changes: 30 additions & 0 deletions test/rd5r_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -62,5 +62,35 @@ RD5RTest::testChannelFrequency() {
1234567890ULL);*/
}

void
RD5RTest::testSMSTemplates() {
Config config;
config.radioIDs()->add(new DMRRadioID("ID", 1234567));
SMSTemplate *sms0 = new SMSTemplate(); sms0->setName("SMS0"); sms0->setMessage("ABC");
SMSTemplate *sms1 = new SMSTemplate(); sms1->setName("SMS1"); sms1->setMessage("XYZ");
config.smsExtension()->smsTemplates()->add(sms0);
config.smsExtension()->smsTemplates()->add(sms1);

ErrorStack err;
RD5RCodeplug codeplug;
if (! codeplug.encode(&config, Codeplug::Flags(), err)) {
QFAIL(QString("Cannot encode codeplug for Radioddity RD5R: %1")
.arg(err.format()).toStdString().c_str());
}

Config decoded;
if (! codeplug.decode(&decoded, err)) {
QFAIL(QString("Cannot decode codeplug for Radioddity RD5R: %1")
.arg(err.format()).toStdString().c_str());
}

QCOMPARE(decoded.smsExtension()->smsTemplates()->count(), 2);
//QCOMPARE_NE(decoded.smsExtension()->smsTemplates()->message(0)->name(), "SMS0");
QCOMPARE(decoded.smsExtension()->smsTemplates()->message(0)->message(), "ABC");
//QCOMPARE_NE(decoded.smsExtension()->smsTemplates()->message(1)->name(), "SMS1");
QCOMPARE(decoded.smsExtension()->smsTemplates()->message(1)->message(), "XYZ");
}


QTEST_GUILESS_MAIN(RD5RTest)

2 changes: 1 addition & 1 deletion test/rd5r_test.hh
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ public:
private slots:
void testBasicConfigEncoding();
void testBasicConfigDecoding();

void testChannelFrequency();
void testSMSTemplates();
};

#endif // RD5RTEST_HH
4 changes: 2 additions & 2 deletions test/uv390_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -73,13 +73,13 @@ UV390Test::testSMSTemplates() {
ErrorStack err;
UV390Codeplug codeplug;
if (! codeplug.encode(&config, Codeplug::Flags(), err)) {
QFAIL(QString("Cannot encode codeplug for Radioddity GD73: %1")
QFAIL(QString("Cannot encode codeplug for TyT MD-UV390: %1")
.arg(err.format()).toStdString().c_str());
}

Config decoded;
if (! codeplug.decode(&decoded, err)) {
QFAIL(QString("Cannot decode codeplug for Radioddity GD73: %1")
QFAIL(QString("Cannot decode codeplug for TyT MD-UV390: %1")
.arg(err.format()).toStdString().c_str());
}

Expand Down

0 comments on commit d630070

Please sign in to comment.