1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114
|
#include "md390.hh"
#include "md390_limits.hh"
#include "logger.hh"
#include "utils.hh"
#define NUM_CHANNELS 1000
#define ADDR_CHANNELS 0x01ee00
#define CHANNEL_SIZE 0x000040
#define BLOCK_SIZE 1024
MD390::MD390(TyTInterface *device, const ErrorStack &err, QObject *parent)
: TyTRadio(device, parent), _name("TyT MD-390"), _limits(nullptr)
{
// Read channels and identify device variance based on the channel frequencies. This may block
// the GUI for some time.
unsigned addr_start = align_addr(ADDR_CHANNELS, BLOCK_SIZE);
unsigned channel_offset = ADDR_CHANNELS-addr_start;
uint total_size = align_size(addr_start+NUM_CHANNELS*CHANNEL_SIZE, BLOCK_SIZE)-addr_start;
QByteArray buffer(total_size, 0xff);
if (! _dev->read_start(0, addr_start, err)) {
errMsg(err) << "Cannot read channels from MD-390, cannot determine variant.";
return;
}
for (unsigned i=0; i<(total_size/BLOCK_SIZE); i++){
if (! _dev->read(0, ADDR_CHANNELS, (uint8_t *)buffer.data()+i*BLOCK_SIZE, BLOCK_SIZE, err)) {
errMsg(err) << "Cannot read channels from MD-390, cannot determine variant.";
return;
}
}
_dev->read_finish(err);
// Determine frequency range of channels
unsigned channelCount = 0;
QPair<double, double> range(std::numeric_limits<double>::max(),0);
for (unsigned i=0; i<NUM_CHANNELS; i++) {
MD390Codeplug::ChannelElement channel(
((uint8_t *)buffer.data()) + channel_offset + i*CHANNEL_SIZE);
if (! channel.isValid())
continue;
if (channel.rxFrequency().inHz()) {
range.first = std::min(range.first, channel.rxFrequency().inMHz());
range.second = std::max(range.second, channel.rxFrequency().inMHz());
}
if (channel.txFrequency().inHz()) {
range.first = std::min(range.first, channel.txFrequency().inMHz());
range.second = std::max(range.second, channel.txFrequency().inMHz());
}
channelCount++;
}
logDebug() << "Got frequency range " << range.first << "MHz - " << range.second
<< "MHz from " << channelCount << " channels.";
if ((137<=range.first) && (174>=range.second)) {
_limits = new MD390Limits({{Frequency::fromMHz(136.), Frequency::fromMHz(174.)}}, this);
_name += "V";
} else if ((350<=range.first) && (400>=range.second)) {
_limits = new MD390Limits({{Frequency::fromMHz(350.), Frequency::fromMHz(400.)}}, this);
_name += "U";
} else if ((400<=range.first) && (450>=range.second)) {
_limits = new MD390Limits({{Frequency::fromMHz(400.), Frequency::fromMHz(480.)}}, this);
_name += "U";
} else if ((450<=range.first) && (520>=range.second)) {
_limits = new MD390Limits({{Frequency::fromMHz(450.), Frequency::fromMHz(520.)}}, this);
_name += "U";
} else {
// Invalid frequency range, needs "Ignore frequency limits" in settings to write any codeplug.
_limits = new MD390Limits({}, this);
errMsg(err) << "Cannot determine frequency range from channel frequencies between "
<< range.first << "MHz and " << range.second
<< "MHz. Will not check frequency ranges.";
}
}
const QString &
MD390::name() const {
return _name;
}
const RadioLimits &
MD390::limits() const {
return *_limits;
}
const Codeplug &
MD390::codeplug() const {
return _codeplug;
}
Codeplug &
MD390::codeplug() {
return _codeplug;
}
const CallsignDB *
MD390::callsignDB() const {
return nullptr;
}
CallsignDB *
MD390::callsignDB() {
return nullptr;
}
RadioInfo
MD390::defaultRadioInfo() {
return RadioInfo(RadioInfo::MD390, "md390", "MD-390", "TyT", {TyTInterface::interfaceInfo()},
QList<RadioInfo>{
RadioInfo(RadioInfo::RT8, "rt8", "RT8", "Retevis", {TyTInterface::interfaceInfo()})
});
}
|