From aa602437afaef7a55199711136fbfeec3208cca0 Mon Sep 17 00:00:00 2001 From: Hannes Matuschek Date: Sat, 24 Jun 2023 14:04:48 +0200 Subject: [PATCH] Merged FM and DMR APRS settings. Fixed frequency issue. Addresses #349. --- lib/d878uv_codeplug.cc | 415 +++++++++++++++++++++------------------ lib/d878uv_codeplug.hh | 185 ++++++++--------- lib/dmr6x2uv_codeplug.cc | 23 +-- 3 files changed, 323 insertions(+), 300 deletions(-) diff --git a/lib/d878uv_codeplug.cc b/lib/d878uv_codeplug.cc index 923e0200..bf134fa1 100644 --- a/lib/d878uv_codeplug.cc +++ b/lib/d878uv_codeplug.cc @@ -2613,16 +2613,160 @@ D878UVCodeplug::APRSSettingsElement::setPower(Channel::Power power) { } Interval -D878UVCodeplug::APRSSettingsElement::preWaveDelay() const { +D878UVCodeplug::APRSSettingsElement::fmPreWaveDelay() const { return Interval::fromMilliseconds(((unsigned)getUInt8(Offset::fmPrewaveDelay()))*10); } void -D878UVCodeplug::APRSSettingsElement::setPreWaveDelay(Interval ms) { +D878UVCodeplug::APRSSettingsElement::setFMPreWaveDelay(Interval ms) { setUInt8(Offset::fmPrewaveDelay(), ms.milliseconds()/10); } bool -D878UVCodeplug::APRSSettingsElement::fromAPRSSystem(const APRSSystem *sys, Context &ctx, const ErrorStack &err) { +D878UVCodeplug::APRSSettingsElement::dmrChannelIsSelected(unsigned n) const { + return 0xfa2 == dmrChannelIndex(n); +} +unsigned +D878UVCodeplug::APRSSettingsElement::dmrChannelIndex(unsigned n) const { + return getUInt16_le(Offset::dmrChannelIndices() + n*Offset::betweenDMRChannelIndices()); +} +void +D878UVCodeplug::APRSSettingsElement::setDMRChannelIndex(unsigned n, unsigned idx) { + setUInt16_le(Offset::dmrChannelIndices() + n*Offset::betweenDMRChannelIndices(), idx); +} +void +D878UVCodeplug::APRSSettingsElement::setDMRChannelSelected(unsigned n) { + setDMRChannelIndex(n, 0xfa2); +} + +unsigned +D878UVCodeplug::APRSSettingsElement::dmrDestination(unsigned n) const { + return getBCD8_be(Offset::dmrDestinations() + n*Offset::betweenDMRDestinations()); +} +void +D878UVCodeplug::APRSSettingsElement::setDMRDestination(unsigned n, unsigned idx) { + setBCD8_be(Offset::dmrDestinations() + n*Offset::betweenDMRDestinations(), idx); +} + +DMRContact::Type +D878UVCodeplug::APRSSettingsElement::dmrCallType(unsigned n) const { + switch(getUInt8(Offset::dmrCallTypes() + n*Offset::betweenDMRCallTypes())) { + case 0: return DMRContact::PrivateCall; + case 1: return DMRContact::GroupCall; + case 2: return DMRContact::AllCall; + } + return DMRContact::PrivateCall; +} +void +D878UVCodeplug::APRSSettingsElement::setDMRCallType(unsigned n, DMRContact::Type type) { + switch(type) { + case DMRContact::PrivateCall: setUInt8(Offset::dmrCallTypes() + n*Offset::betweenDMRCallTypes(), 0x00); break; + case DMRContact::GroupCall: setUInt8(Offset::dmrCallTypes() + n*Offset::betweenDMRCallTypes(), 0x01); break; + case DMRContact::AllCall: setUInt8(Offset::dmrCallTypes() + n*Offset::betweenDMRCallTypes(), 0x02); break; + } +} + +bool +D878UVCodeplug::APRSSettingsElement::dmrTimeSlotOverride(unsigned n) { + return 0x00 != getUInt8(Offset::dmrTimeSlots() + n*Offset::betweenDMRTimeSlots()); +} +DMRChannel::TimeSlot +D878UVCodeplug::APRSSettingsElement::dmrTimeSlot(unsigned n) const { + switch (getUInt8(Offset::dmrTimeSlots() + n*Offset::betweenDMRTimeSlots())) { + case 1: return DMRChannel::TimeSlot::TS1; + case 2: return DMRChannel::TimeSlot::TS2; + } + return DMRChannel::TimeSlot::TS1; +} +void +D878UVCodeplug::APRSSettingsElement::setDMRTimeSlot(unsigned n, DMRChannel::TimeSlot ts) { + switch (ts) { + case DMRChannel::TimeSlot::TS1: setUInt8(Offset::dmrTimeSlots() + n*Offset::betweenDMRTimeSlots(), 0x01); break; + case DMRChannel::TimeSlot::TS2: setUInt8(Offset::dmrTimeSlots() + n*Offset::betweenDMRTimeSlots(), 0x02); break; + } +} +void +D878UVCodeplug::APRSSettingsElement::clearDMRTimeSlotOverride(unsigned n) { + setUInt8(Offset::dmrTimeSlots() + n*Offset::betweenDMRTimeSlots(), 0); +} + +bool +D878UVCodeplug::APRSSettingsElement::dmrRoaming() const { + return getUInt8(Offset::roamingSupport()); +} +void +D878UVCodeplug::APRSSettingsElement::enableDMRRoaming(bool enable) { + setUInt8(Offset::roamingSupport(), (enable ? 0x01 : 0x00)); +} + +Interval +D878UVCodeplug::APRSSettingsElement::dmrPreWaveDelay() const { + return Interval::fromMilliseconds(((unsigned)getUInt8(Offset::dmrPrewaveDelay()))*100); +} +void +D878UVCodeplug::APRSSettingsElement::setDMRPreWaveDelay(Interval ms) { + setUInt8(Offset::dmrPrewaveDelay(), ms.milliseconds()/100); +} + +bool +D878UVCodeplug::APRSSettingsElement::infiniteDisplayTime() const { + return 13 == getUInt8(Offset::displayInterval()); +} +Interval +D878UVCodeplug::APRSSettingsElement::displayTime() const { + return Interval::fromSeconds(3 + getUInt8(Offset::displayInterval())); +} +void +D878UVCodeplug::APRSSettingsElement::setDisplayTime(Interval dur) { + unsigned int sec = dur.seconds(); + sec = std::min(16U, std::max(3U, sec)); + setUInt8(Offset::displayInterval(), sec-3); +} +void +D878UVCodeplug::APRSSettingsElement::setDisplayTimeInifinite() { + setUInt8(Offset::displayInterval(), 13); +} + +D878UVCodeplug::APRSSettingsElement::ChannelWidth +D878UVCodeplug::APRSSettingsElement::fmChannelWidth() const { + return (ChannelWidth)getUInt8(Offset::fmWidth()); +} +void +D878UVCodeplug::APRSSettingsElement::setFMChannelWidth(ChannelWidth width) { + setUInt8(Offset::fmWidth(), (uint8_t)width); +} + +bool +D878UVCodeplug::APRSSettingsElement::passAll() const { + return 0x00 != getUInt8(Offset::passAll()); +} +void +D878UVCodeplug::APRSSettingsElement::enablePassAll(bool enable) { + setUInt8(Offset::passAll(), enable ? 0x01 : 0x00); +} + +bool +D878UVCodeplug::APRSSettingsElement::fmFrequencySet(unsigned int n) const { + n = std::min(Limit::fmFrequencies()-1, n); + return 0 != getBCD8_be(Offset::fmFrequencies() + n*Offset::betweenFMFrequencies()); +} +Frequency +D878UVCodeplug::APRSSettingsElement::fmFrequency(unsigned int n) const { + n = std::min(Limit::fmFrequencies()-1, n); + return Frequency::fromHz(getBCD8_be(Offset::fmFrequencies() + n*Offset::betweenFMFrequencies())*10); +} +void +D878UVCodeplug::APRSSettingsElement::setFMFrequency(unsigned int n, Frequency f) { + n = std::min(Limit::fmFrequencies()-1, n); + setBCD8_be(Offset::fmFrequencies() + n*Offset::betweenFMFrequencies(), f.inHz()/10); +} +void +D878UVCodeplug::APRSSettingsElement::clearFMFrequency(unsigned int n) { + n = std::min(Limit::fmFrequencies()-1, n); + setBCD8_be(Offset::fmFrequencies() + n*Offset::betweenFMFrequencies(), 0); +} + +bool +D878UVCodeplug::APRSSettingsElement::fromFMAPRSSystem(const APRSSystem *sys, Context &ctx, const ErrorStack &err) { Q_UNUSED(ctx) clear(); if (! sys->revertChannel()) { @@ -2630,41 +2774,44 @@ D878UVCodeplug::APRSSettingsElement::fromAPRSSystem(const APRSSystem *sys, Conte << "No revert channel defined for APRS system '" << sys->name() <<"'."; return false; } - setFrequency(sys->revertChannel()->txFrequency()*1e6); + setFMFrequency(0, Frequency::fromHz(sys->revertChannel()->txFrequency()*1e6)); setTXTone(sys->revertChannel()->txTone()); setPower(sys->revertChannel()->power()); + setFMChannelWidth(FMChannel::Bandwidth::Wide == sys->revertChannel()->bandwidth() ? + ChannelWidth::Wide : ChannelWidth::Narrow); setManualTXInterval(Interval::fromSeconds(sys->period())); setAutoTXInterval(Interval::fromSeconds(sys->period())); setDestination(sys->destination(), sys->destSSID()); setSource(sys->source(), sys->srcSSID()); setPath(sys->path()); setIcon(sys->icon()); - setPreWaveDelay(0); + setFMPreWaveDelay(Interval()); return true; } APRSSystem * -D878UVCodeplug::APRSSettingsElement::toAPRSSystem() { +D878UVCodeplug::APRSSettingsElement::toFMAPRSSystem() { return new APRSSystem( tr("APRS %1").arg(destination()), nullptr, destination(), destinationSSID(), source(), sourceSSID(), - path(), icon(), "", autoTXInterval()); + path(), icon(), "", autoTXInterval().seconds()); } bool -D878UVCodeplug::APRSSettingsElement::linkAPRSSystem(APRSSystem *sys, Context &ctx) { +D878UVCodeplug::APRSSettingsElement::linkFMAPRSSystem(APRSSystem *sys, Context &ctx) { // First, try to find a matching analog channel in list - FMChannel *ch = ctx.config()->channelList()->findFMChannelByTxFreq(frequency()/1e6); + FMChannel *ch = ctx.config()->channelList()->findFMChannelByTxFreq(double(fmFrequency(0).inHz())/1e6); if (! ch) { // If no channel is found, create one with the settings from APRS channel: ch = new FMChannel(); ch->setName("APRS Channel"); - ch->setRXFrequency(frequency()/1e6); - ch->setTXFrequency(frequency()/1e6); + ch->setRXFrequency(double(fmFrequency(0).inHz())/1e6); + ch->setTXFrequency(double(fmFrequency(0).inHz())/1e6); ch->setPower(power()); ch->setTXTone(txTone()); - ch->setBandwidth(FMChannel::Bandwidth::Wide); - logInfo() << "No matching APRS channel found for TX frequency " << frequency()/1e6 + ch->setBandwidth(ChannelWidth::Wide == fmChannelWidth() ? + FMChannel::Bandwidth::Wide : FMChannel::Bandwidth::Narrow); + logInfo() << "No matching APRS channel found for TX frequency " << double(fmFrequency(0).inHz())/1e6 << "MHz, create one as 'APRS Channel'"; ctx.config()->channelList()->add(ch); } @@ -2672,6 +2819,61 @@ D878UVCodeplug::APRSSettingsElement::linkAPRSSystem(APRSSystem *sys, Context &ct return true; } +bool +D878UVCodeplug::APRSSettingsElement::fromDMRAPRSSystems(Context &ctx) { + unsigned int n = std::min(ctx.count(), Limit::dmrSystems()); + for (unsigned int idx=0; idx(idx), ctx); + return true; +} + +bool +D878UVCodeplug::APRSSettingsElement::fromDMRAPRSSystemObj(unsigned int idx, GPSSystem *sys, Context &ctx) { + if (sys->hasContact()) { + setDMRDestination(idx, sys->contactObj()->number()); + setDMRCallType(idx, sys->contactObj()->type()); + } + if (sys->hasRevertChannel() && (SelectedChannel::get() != (Channel *)sys->revertChannel())) { + setDMRChannelIndex(idx, ctx.index(sys->revertChannel())); + clearDMRTimeSlotOverride(idx); + } else { // no revert channel specified or "selected channel": + setDMRChannelSelected(idx); + } + return true; +} + +GPSSystem * +D878UVCodeplug::APRSSettingsElement::toDMRAPRSSystemObj(int idx) const { + if (0 == dmrDestination(idx)) + return nullptr; + return new GPSSystem(tr("GPS Sys #%1").arg(idx+1)); +} + +bool +D878UVCodeplug::APRSSettingsElement::linkDMRAPRSSystem(int idx, GPSSystem *sys, Context &ctx) const { + // Clear revert channel from GPS system + sys->setRevertChannel(nullptr); + + // if a revert channel is defined -> link to it + if (dmrChannelIsSelected(idx)) + sys->setRevertChannel(nullptr); + else if (ctx.has(dmrChannelIndex(idx)) && ctx.get(dmrChannelIndex(idx))->is()) + sys->setRevertChannel(ctx.get(dmrChannelIndex(idx))->as()); + + // Search for a matching contact in contacts + DMRContact *cont = ctx.config()->contacts()->findDigitalContact(dmrDestination(idx)); + // If no matching contact is found, create one + if (nullptr == cont) { + cont = new DMRContact(dmrCallType(idx), tr("GPS #%1 Contact").arg(idx+1), + dmrDestination(idx), false); + ctx.config()->contacts()->add(cont); + } + // link contact to GPS system. + sys->setContactObj(cont); + + return true; +} + /* ******************************************************************************************** * * Implementation of D878UVCodeplug::AnalogAPRSSettingsExtensionElement @@ -2856,168 +3058,6 @@ D878UVCodeplug::AnalogAPRSRXEntryElement::setCall(const QString &call, unsigned } -/* ******************************************************************************************** * - * Implementation of D878UVCodeplug::DMRAPRSSystemsElement - * ******************************************************************************************** */ -D878UVCodeplug::DMRAPRSSettingsElement::DMRAPRSSettingsElement(uint8_t *ptr, unsigned size) - : Element(ptr, size) -{ - // pass... -} - -D878UVCodeplug::DMRAPRSSettingsElement::DMRAPRSSettingsElement(uint8_t *ptr) - : Element(ptr, DMRAPRSSettingsElement::size()) -{ - // pass... -} - -void -D878UVCodeplug::DMRAPRSSettingsElement::clear() { - memset(_data, 0x00, _size); -} - -bool -D878UVCodeplug::DMRAPRSSettingsElement::channelIsSelected(unsigned n) const { - return 0xfa2 == channelIndex(n); -} -unsigned -D878UVCodeplug::DMRAPRSSettingsElement::channelIndex(unsigned n) const { - return getUInt16_le(Offset::channels() + n*Offset::betweenChannels()); -} -void -D878UVCodeplug::DMRAPRSSettingsElement::setChannelIndex(unsigned n, unsigned idx) { - setUInt16_le(Offset::channels() + n*Offset::betweenChannels(), idx); -} -void -D878UVCodeplug::DMRAPRSSettingsElement::setChannelSelected(unsigned n) { - setChannelIndex(n, 0xfa2); -} - -unsigned -D878UVCodeplug::DMRAPRSSettingsElement::destination(unsigned n) const { - return getBCD8_be(Offset::destinations() + n*Offset::betweenDestinations()); -} -void -D878UVCodeplug::DMRAPRSSettingsElement::setDestination(unsigned n, unsigned idx) { - setBCD8_be(Offset::destinations() + n*Offset::betweenDestinations(), idx); -} - -DMRContact::Type -D878UVCodeplug::DMRAPRSSettingsElement::callType(unsigned n) const { - switch(getUInt8(Offset::callTypes() + n*Offset::betweenCallTypes())) { - case 0: return DMRContact::PrivateCall; - case 1: return DMRContact::GroupCall; - case 2: return DMRContact::AllCall; - } - return DMRContact::PrivateCall; -} -void -D878UVCodeplug::DMRAPRSSettingsElement::setCallType(unsigned n, DMRContact::Type type) { - switch(type) { - case DMRContact::PrivateCall: setUInt8(Offset::callTypes() + n*Offset::betweenCallTypes(), 0x00); break; - case DMRContact::GroupCall: setUInt8(Offset::callTypes() + n*Offset::betweenCallTypes(), 0x01); break; - case DMRContact::AllCall: setUInt8(Offset::callTypes() + n*Offset::betweenCallTypes(), 0x02); break; - } -} - -bool -D878UVCodeplug::DMRAPRSSettingsElement::timeSlotOverride(unsigned n) { - return 0x00 != getUInt8(Offset::timeSlots() + n*Offset::betweenTimeSlots()); -} -DMRChannel::TimeSlot -D878UVCodeplug::DMRAPRSSettingsElement::timeSlot(unsigned n) const { - switch (getUInt8(Offset::timeSlots() + n*Offset::betweenTimeSlots())) { - case 1: return DMRChannel::TimeSlot::TS1; - case 2: return DMRChannel::TimeSlot::TS2; - } - return DMRChannel::TimeSlot::TS1; -} -void -D878UVCodeplug::DMRAPRSSettingsElement::setTimeSlot(unsigned n, DMRChannel::TimeSlot ts) { - switch (ts) { - case DMRChannel::TimeSlot::TS1: setUInt8(Offset::timeSlots() + n*Offset::betweenTimeSlots(), 0x01); break; - case DMRChannel::TimeSlot::TS2: setUInt8(Offset::timeSlots() + n*Offset::betweenTimeSlots(), 0x02); break; - } -} -void -D878UVCodeplug::DMRAPRSSettingsElement::clearTimeSlotOverride(unsigned n) { - setUInt8(Offset::timeSlots() + n*Offset::betweenTimeSlots(), 0); -} - -bool -D878UVCodeplug::DMRAPRSSettingsElement::roaming() const { - return getUInt8(Offset::roaming()); -} -void -D878UVCodeplug::DMRAPRSSettingsElement::enableRoaming(bool enable) { - setUInt8(Offset::roaming(), (enable ? 0x01 : 0x00)); -} - -Interval -D878UVCodeplug::DMRAPRSSettingsElement::repeaterActivationDelay() const { - return Interval::fromMilliseconds(((unsigned)getUInt8(Offset::repeaterActivationDelay()))*100); -} -void -D878UVCodeplug::DMRAPRSSettingsElement::setRepeaterActivationDelay(Interval ms) { - setUInt8(Offset::repeaterActivationDelay(), ms.milliseconds()/100); -} - -bool -D878UVCodeplug::DMRAPRSSettingsElement::fromGPSSystems(Context &ctx) { - unsigned int n = std::min(ctx.count(), Limit::systemCount()); - for (unsigned int idx=0; idx(idx), ctx); - return true; -} - -bool -D878UVCodeplug::DMRAPRSSettingsElement::fromGPSSystemObj(unsigned int idx, GPSSystem *sys, Context &ctx) { - if (sys->hasContact()) { - setDestination(idx, sys->contactObj()->number()); - setCallType(idx, sys->contactObj()->type()); - } - if (sys->hasRevertChannel() && (SelectedChannel::get() != (Channel *)sys->revertChannel())) { - setChannelIndex(idx, ctx.index(sys->revertChannel())); - clearTimeSlotOverride(idx); - } else { // no revert channel specified or "selected channel": - setChannelSelected(idx); - } - return true; -} - -GPSSystem * -D878UVCodeplug::DMRAPRSSettingsElement::toGPSSystemObj(int idx) const { - if (0 == destination(idx)) - return nullptr; - return new GPSSystem(tr("GPS Sys #%1").arg(idx+1)); -} - -bool -D878UVCodeplug::DMRAPRSSettingsElement::linkGPSSystem(int idx, GPSSystem *sys, Context &ctx) const { - // Clear revert channel from GPS system - sys->setRevertChannel(nullptr); - - // if a revert channel is defined -> link to it - if (channelIsSelected(idx)) - sys->setRevertChannel(nullptr); - else if (ctx.has(channelIndex(idx)) && ctx.get(channelIndex(idx))->is()) - sys->setRevertChannel(ctx.get(channelIndex(idx))->as()); - - // Search for a matching contact in contacts - DMRContact *cont = ctx.config()->contacts()->findDigitalContact(destination(idx)); - // If no matching contact is found, create one - if (nullptr == cont) { - cont = new DMRContact(callType(idx), tr("GPS #%1 Contact").arg(idx+1), - destination(idx), false); - ctx.config()->contacts()->add(cont); - } - // link contact to GPS system. - sys->setContactObj(cont); - - return true; -} - - /* ******************************************************************************************** * * Implementation of D878UVCodeplug::AESEncryptionKeyElement * ******************************************************************************************** */ @@ -3489,23 +3529,22 @@ D878UVCodeplug::encodeGPSSystems(const Flags &flags, Context &ctx, const ErrorSt Q_UNUSED(flags); Q_UNUSED(err) // replaces D868UVCodeplug::encodeGPSSystems + APRSSettingsElement aprs(data(Offset::analogAPRSSettings())); // Encode APRS system (there can only be one) if (0 < ctx.config()->posSystems()->aprsCount()) { - APRSSettingsElement(data(Offset::analogAPRSSettings())) - .fromAPRSSystem(ctx.config()->posSystems()->aprsSystem(0), ctx); + aprs.fromFMAPRSSystem(ctx.config()->posSystems()->aprsSystem(0), ctx); AnalogAPRSMessageElement(data(Offset::analogAPRSMessage())) .setMessage(ctx.config()->posSystems()->aprsSystem(0)->message()); } // Encode GPS systems - DMRAPRSSettingsElement gps(data(Offset::dmrAPRSSettings())); - if (! gps.fromGPSSystems(ctx)) + if (! aprs.fromDMRAPRSSystems(ctx)) return false; if (0 < ctx.config()->posSystems()->gpsCount()) { // If there is at least one GPS system defined -> set auto TX interval. // This setting might be overridden by any analog APRS system below APRSSettingsElement aprs(data(Offset::analogAPRSSettings())); - aprs.setAutoTXInterval(ctx.config()->posSystems()->gpsSystem(0)->period()); + aprs.setAutoTXInterval(Interval::fromSeconds(ctx.config()->posSystems()->gpsSystem(0)->period())); aprs.setManualTXInterval(Interval::fromSeconds(ctx.config()->posSystems()->gpsSystem(0)->period())); } return true; @@ -3520,22 +3559,21 @@ D878UVCodeplug::createGPSSystems(Context &ctx, const ErrorStack &err) { // Before creating any GPS/APRS systems, get global auto TX interval APRSSettingsElement aprs(data(Offset::analogAPRSSettings())); AnalogAPRSMessageElement aprsMessage(data(Offset::analogAPRSMessage())); - unsigned pos_intervall = aprs.autoTXInterval(); + unsigned pos_intervall = aprs.autoTXInterval().seconds(); // Create APRS system (if enabled) if (aprs.isValid()) { - APRSSystem *sys = aprs.toAPRSSystem(); + APRSSystem *sys = aprs.toFMAPRSSystem(); sys->setPeriod(pos_intervall); sys->setMessage(aprsMessage.message()); ctx.config()->posSystems()->add(sys); ctx.add(sys,0); } // Create GPS systems - DMRAPRSSettingsElement gps_systems(data(Offset::dmrAPRSSettings())); for (unsigned int i=0; iname() << "' at idx " << i << "."; sys->setPeriod(pos_intervall); ctx.config()->posSystems()->add(sys); ctx.add(sys, i); @@ -3554,15 +3592,14 @@ D878UVCodeplug::linkGPSSystems(Context &ctx, const ErrorStack &err) { // Link APRS system APRSSettingsElement aprs(data(Offset::analogAPRSSettings())); if (aprs.isValid()) { - aprs.linkAPRSSystem(ctx.config()->posSystems()->aprsSystem(0), ctx); + aprs.linkFMAPRSSystem(ctx.config()->posSystems()->aprsSystem(0), ctx); } // Link GPS systems - DMRAPRSSettingsElement gps_systems(data(Offset::dmrAPRSSettings())); for (unsigned int i=0; i(i), ctx); + aprs.linkDMRAPRSSystem(i, ctx.get(i), ctx); } return true; diff --git a/lib/d878uv_codeplug.hh b/lib/d878uv_codeplug.hh index 29e320fd..5339d962 100644 --- a/lib/d878uv_codeplug.hh +++ b/lib/d878uv_codeplug.hh @@ -1165,6 +1165,12 @@ public: Off=0, CTCSS=1, DCS=2 }; + public: + /** Possible FM APRS channel widths. */ + enum class ChannelWidth { + Narrow = 0, Wide = 1 + }; + public: /** Constructor. */ explicit APRSSettingsElement(uint8_t *ptr); @@ -1238,18 +1244,93 @@ public: virtual void setPower(Channel::Power power); /** Returns the pre-wave delay in ms. */ - virtual Interval preWaveDelay() const; + virtual Interval fmPreWaveDelay() const; /** Sets the pre-wave delay in ms. */ - virtual void setPreWaveDelay(Interval ms); + virtual void setFMPreWaveDelay(Interval ms); + + /** Returns @c true if the channel points to the current/selected channel. */ + virtual bool dmrChannelIsSelected(unsigned n) const; + /** Returns the digital channel index for the n-th system. */ + virtual unsigned dmrChannelIndex(unsigned n) const; + /** Sets the digital channel index for the n-th system. */ + virtual void setDMRChannelIndex(unsigned n, unsigned idx); + /** Sets the channel to the current/selected channel. */ + virtual void setDMRChannelSelected(unsigned n); + + /** Returns the destination contact for the n-th system. */ + virtual unsigned dmrDestination(unsigned n) const; + /** Sets the destination contact for the n-th system. */ + virtual void setDMRDestination(unsigned n, unsigned idx); + + /** Returns the call type for the n-th system. */ + virtual DMRContact::Type dmrCallType(unsigned n) const; + /** Sets the call type for the n-th system. */ + virtual void setDMRCallType(unsigned n, DMRContact::Type type); + + /** Returns @c true if the n-th system overrides the channel time-slot. */ + virtual bool dmrTimeSlotOverride(unsigned n); + /** Returns the time slot if overridden (only valid if @c timeSlot returns true). */ + virtual DMRChannel::TimeSlot dmrTimeSlot(unsigned n) const; + /** Overrides the time slot of the n-th selected channel. */ + virtual void setDMRTimeSlot(unsigned n, DMRChannel::TimeSlot ts); + /** Clears the time-slot override. */ + virtual void clearDMRTimeSlotOverride(unsigned n); + + /** Returns @c true if the roaming is enabled. */ + virtual bool dmrRoaming() const; + /** Enables/disables roaming. */ + virtual void enableDMRRoaming(bool enable); + + /** Returns the the repeater activation delay in ms. */ + virtual Interval dmrPreWaveDelay() const; + /** Sets the repeater activation delay in ms. */ + virtual void setDMRPreWaveDelay(Interval ms); + + /** Returns @c true if a received APRS message is shown indefinitely. */ + virtual bool infiniteDisplayTime() const; + /** Returns the time, a received APRS message is shown. */ + virtual Interval displayTime() const; + /** Sets the time, a received APRS is shown. */ + virtual void setDisplayTime(Interval dur); + /** Sets the APRS display time to infinite. */ + virtual void setDisplayTimeInifinite(); + + /** Returns the FM APRS channel width. */ + virtual ChannelWidth fmChannelWidth() const; + /** Sets the FM APRS channel width. */ + virtual void setFMChannelWidth(ChannelWidth width); + + /** Retruns @c true if "pass all" is enabled, whatever that means. */ + virtual bool passAll() const; + /** Enables/disables "pass all". */ + virtual void enablePassAll(bool enable); + + /** Retruns @c true if the n-th of 8 FM APRS frequencies is set. */ + virtual bool fmFrequencySet(unsigned int n) const; + /** Returns the n-th of 8 FM APRS frequencies. */ + virtual Frequency fmFrequency(unsigned int n) const; + /** Sets the n-th of 8 FM APRS frequencies. */ + virtual void setFMFrequency(unsigned int n, Frequency f); + /** Clears the n-th of 8 FM APRS frequencies. */ + virtual void clearFMFrequency(unsigned int n); /** Configures this APRS system from the given generic config. */ - virtual bool fromAPRSSystem(const APRSSystem *sys, Context &ctx, - const ErrorStack &err=ErrorStack()); + virtual bool fromFMAPRSSystem(const APRSSystem *sys, Context &ctx, + const ErrorStack &err=ErrorStack()); /** Constructs a generic APRS system configuration from this APRS system. */ - virtual APRSSystem *toAPRSSystem(); + virtual APRSSystem *toFMAPRSSystem(); /** Links the transmit channel within the generic APRS system based on the transmit frequency * defined within this APRS system. */ - virtual bool linkAPRSSystem(APRSSystem *sys, Context &ctx); + virtual bool linkFMAPRSSystem(APRSSystem *sys, Context &ctx); + + /** Constructs all GPS system from the generic configuration. */ + virtual bool fromDMRAPRSSystems(Context &ctx); + /** Encodes the given GPS system. */ + virtual bool fromDMRAPRSSystemObj(unsigned int idx, GPSSystem *sys, Context &ctx); + /** Constructs a generic GPS system from the idx-th encoded GPS system. */ + virtual GPSSystem *toDMRAPRSSystemObj(int idx) const; + /** Links the specified generic GPS system. */ + virtual bool linkDMRAPRSSystem(int idx, GPSSystem *sys, Context &ctx) const; public: /** Some static limits for this element. */ @@ -1435,98 +1516,6 @@ public: virtual void setCall(const QString &call, unsigned ssid); }; - /** Represents the 8 DMR-APRS systems within the binary codeplug. - * - * Memory layout of encoded DMR-APRS systems (size 0x0060 bytes): - * @verbinclude d878uv_dmraprssettings.txt */ - class DMRAPRSSettingsElement: public Element - { - protected: - /** Hidden constructor. */ - DMRAPRSSettingsElement(uint8_t *ptr, unsigned size); - - public: - /** Constructor. */ - DMRAPRSSettingsElement(uint8_t *ptr); - - /** The size of the element. */ - static constexpr unsigned int size() { return 0x0060; } - - /** Resets the systems. */ - void clear(); - - /** Returns @c true if the channel points to the current/selected channel. */ - virtual bool channelIsSelected(unsigned n) const; - /** Returns the digital channel index for the n-th system. */ - virtual unsigned channelIndex(unsigned n) const; - /** Sets the digital channel index for the n-th system. */ - virtual void setChannelIndex(unsigned n, unsigned idx); - /** Sets the channel to the current/selected channel. */ - virtual void setChannelSelected(unsigned n); - - /** Returns the destination contact for the n-th system. */ - virtual unsigned destination(unsigned n) const; - /** Sets the destination contact for the n-th system. */ - virtual void setDestination(unsigned n, unsigned idx); - - /** Returns the call type for the n-th system. */ - virtual DMRContact::Type callType(unsigned n) const; - /** Sets the call type for the n-th system. */ - virtual void setCallType(unsigned n, DMRContact::Type type); - - /** Returns @c true if the n-th system overrides the channel time-slot. */ - virtual bool timeSlotOverride(unsigned n); - /** Returns the time slot if overridden (only valid if @c timeSlot returns true). */ - virtual DMRChannel::TimeSlot timeSlot(unsigned n) const; - /** Overrides the time slot of the n-th selected channel. */ - virtual void setTimeSlot(unsigned n, DMRChannel::TimeSlot ts); - /** Clears the time-slot override. */ - virtual void clearTimeSlotOverride(unsigned n); - - /** Returns @c true if the roaming is enabled. */ - virtual bool roaming() const; - /** Enables/disables roaming. */ - virtual void enableRoaming(bool enable); - - /** Returns the the repeater activation delay in ms. */ - virtual Interval repeaterActivationDelay() const; - /** Sets the repeater activation delay in ms. */ - virtual void setRepeaterActivationDelay(Interval ms); - - /** Constructs all GPS system from the generic configuration. */ - virtual bool fromGPSSystems(Context &ctx); - /** Encodes the given GPS system. */ - virtual bool fromGPSSystemObj(unsigned int idx, GPSSystem *sys, Context &ctx); - /** Constructs a generic GPS system from the idx-th encoded GPS system. */ - virtual GPSSystem *toGPSSystemObj(int idx) const; - /** Links the specified generic GPS system. */ - virtual bool linkGPSSystem(int idx, GPSSystem *sys, Context &ctx) const; - - public: - /** Some limits. */ - struct Limit { - /// Maximum number of channels, destinations, call types and time slots. - static constexpr unsigned int systemCount() { return 8; } - }; - - protected: - /** Internal used offsets within the element. */ - struct Offset { - /// @cond DO_NOT_DOCUMENT - static constexpr unsigned int channels() { return 0x0000; } - static constexpr unsigned int betweenChannels() { return 0x0002; } - static constexpr unsigned int destinations() { return 0x0010; } - static constexpr unsigned int betweenDestinations() { return 0x0004; } - static constexpr unsigned int callTypes() { return 0x0030; } - static constexpr unsigned int betweenCallTypes() { return 0x0001; } - static constexpr unsigned int timeSlots() { return 0x0039; } - static constexpr unsigned int betweenTimeSlots() { return 0x0001; } - static constexpr unsigned int roaming() { return 0x0038; } - static constexpr unsigned int repeaterActivationDelay() { return 0x0041; } - /// @endcond - }; - }; - /** Implements the binary representation of a roaming channel within the codeplug. * * Memory layout of roaming channel (size 0x0020 bytes): diff --git a/lib/dmr6x2uv_codeplug.cc b/lib/dmr6x2uv_codeplug.cc index d5cee2e4..019007d3 100644 --- a/lib/dmr6x2uv_codeplug.cc +++ b/lib/dmr6x2uv_codeplug.cc @@ -1769,22 +1769,21 @@ DMR6X2UVCodeplug::encodeGPSSystems(const Flags &flags, Context &ctx, const Error Q_UNUSED(flags); Q_UNUSED(err) // replaces D868UVCodeplug::encodeGPSSystems + D878UVCodeplug::APRSSettingsElement aprs(data(ADDR_APRS_SETTINGS)); + // Encode APRS system (there can only be one) if (0 < ctx.config()->posSystems()->aprsCount()) { - D878UVCodeplug::APRSSettingsElement(data(ADDR_APRS_SETTINGS)) - .fromAPRSSystem(ctx.config()->posSystems()->aprsSystem(0), ctx); + aprs.fromFMAPRSSystem(ctx.config()->posSystems()->aprsSystem(0), ctx); uint8_t *aprsmsg = (uint8_t *)data(ADDR_APRS_MESSAGE); encode_ascii(aprsmsg, ctx.config()->posSystems()->aprsSystem(0)->message(), 60, 0x00); } // Encode GPS systems - D878UVCodeplug::DMRAPRSSettingsElement gps(data(ADDR_DMRAPRS_SETTINGS)); - if (! gps.fromGPSSystems(ctx)) + if (! aprs.fromDMRAPRSSystems(ctx)) return false; if (0 < ctx.config()->posSystems()->gpsCount()) { // If there is at least one GPS system defined -> set auto TX interval. // This setting might be overridden by any analog APRS system below - D878UVCodeplug::APRSSettingsElement aprs(data(ADDR_APRS_SETTINGS)); aprs.setAutoTXInterval(Interval::fromSeconds(ctx.config()->posSystems()->gpsSystem(0)->period())); aprs.setManualTXInterval(Interval::fromSeconds(ctx.config()->posSystems()->gpsSystem(0)->period())); } @@ -1804,18 +1803,17 @@ DMR6X2UVCodeplug::createGPSSystems(Context &ctx, const ErrorStack &err) { // Create APRS system (if enabled) uint8_t *aprsmsg = (uint8_t *)data(ADDR_APRS_MESSAGE); if (aprs.isValid()) { - APRSSystem *sys = aprs.toAPRSSystem(); + APRSSystem *sys = aprs.toFMAPRSSystem(); sys->setPeriod(pos_intervall); sys->setMessage(decode_ascii(aprsmsg, 60, 0x00)); ctx.config()->posSystems()->add(sys); ctx.add(sys,0); } // Create GPS systems - D878UVCodeplug::DMRAPRSSettingsElement gps_systems(data(ADDR_DMRAPRS_SETTINGS)); for (int i=0; isetPeriod(pos_intervall); ctx.config()->posSystems()->add(sys); ctx.add(sys, i); } else { @@ -1833,15 +1831,14 @@ DMR6X2UVCodeplug::linkGPSSystems(Context &ctx, const ErrorStack &err) { // Link APRS system D878UVCodeplug::APRSSettingsElement aprs(data(ADDR_APRS_SETTINGS)); if (aprs.isValid()) { - aprs.linkAPRSSystem(ctx.config()->posSystems()->aprsSystem(0), ctx); + aprs.linkFMAPRSSystem(ctx.config()->posSystems()->aprsSystem(0), ctx); } // Link GPS systems - D878UVCodeplug::DMRAPRSSettingsElement gps_systems(data(ADDR_DMRAPRS_SETTINGS)); for (int i=0; i(i), ctx); + aprs.linkDMRAPRSSystem(i, ctx.get(i), ctx); } return true;