Verify configuration before writing it into the radio.
This commit is contained in:
parent
5a842d8770
commit
a9a6d691b1
5
dfu.c
5
dfu.c
@ -284,6 +284,9 @@ static void erase_block(uint32_t address)
|
|||||||
}
|
}
|
||||||
get_status();
|
get_status();
|
||||||
wait_dfu_idle();
|
wait_dfu_idle();
|
||||||
|
|
||||||
|
fprintf(stderr, "#");
|
||||||
|
fflush(stderr);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *identify()
|
static const char *identify()
|
||||||
@ -369,6 +372,8 @@ void dfu_close()
|
|||||||
void dfu_erase(int nbytes)
|
void dfu_erase(int nbytes)
|
||||||
{
|
{
|
||||||
// Enter Programming Mode.
|
// Enter Programming Mode.
|
||||||
|
get_status();
|
||||||
|
wait_dfu_idle();
|
||||||
md380_command(0x91, 0x01);
|
md380_command(0x91, 0x01);
|
||||||
usleep(100000);
|
usleep(100000);
|
||||||
|
|
||||||
|
2
main.c
2
main.c
@ -120,6 +120,7 @@ int main(int argc, char **argv)
|
|||||||
radio_read_image(argv[0]);
|
radio_read_image(argv[0]);
|
||||||
radio_print_version(stdout);
|
radio_print_version(stdout);
|
||||||
radio_parse_config(argv[1]);
|
radio_parse_config(argv[1]);
|
||||||
|
radio_verify_config();
|
||||||
radio_save_image("device.img");
|
radio_save_image("device.img");
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
@ -129,6 +130,7 @@ int main(int argc, char **argv)
|
|||||||
radio_print_version(stdout);
|
radio_print_version(stdout);
|
||||||
radio_save_image("backup.img");
|
radio_save_image("backup.img");
|
||||||
radio_parse_config(argv[0]);
|
radio_parse_config(argv[0]);
|
||||||
|
radio_verify_config();
|
||||||
radio_upload(1);
|
radio_upload(1);
|
||||||
radio_disconnect();
|
radio_disconnect();
|
||||||
}
|
}
|
||||||
|
260
md380.c
260
md380.c
@ -51,6 +51,16 @@
|
|||||||
#define OFFSET_SCANL 0x18860
|
#define OFFSET_SCANL 0x18860
|
||||||
#define OFFSET_CHANNELS 0x1ee00
|
#define OFFSET_CHANNELS 0x1ee00
|
||||||
|
|
||||||
|
#define GET_TIMESTAMP() (&radio_mem[OFFSET_TIMESTMP])
|
||||||
|
#define GET_SETTINGS() ((general_settings_t*) &radio_mem[OFFSET_SETTINGS])
|
||||||
|
#define GET_CHANNEL(i) ((channel_t*) &radio_mem[OFFSET_CHANNELS + (i)*64])
|
||||||
|
#define GET_ZONE(i) ((zone_t*) &radio_mem[OFFSET_ZONES + (i)*64])
|
||||||
|
#define GET_ZONEXT(i) ((zone_ext_t*) &radio_mem[OFFSET_ZONEXT + (i)*224])
|
||||||
|
#define GET_SCANLIST(i) ((scanlist_t*) &radio_mem[OFFSET_SCANL + (i)*104])
|
||||||
|
#define GET_CONTACT(i) ((contact_t*) &radio_mem[OFFSET_CONTACTS + (i)*36])
|
||||||
|
#define GET_GROUPLIST(i) ((grouplist_t*) &radio_mem[OFFSET_GLISTS + (i)*96])
|
||||||
|
#define GET_MESSAGE(i) ((uint16_t*) &radio_mem[OFFSET_MSG + (i)*288])
|
||||||
|
|
||||||
//
|
//
|
||||||
// Channel data.
|
// Channel data.
|
||||||
//
|
//
|
||||||
@ -325,7 +335,7 @@ static const char *SIGNALING_SYSTEM[] = { "-", "DTMF-1", "DTMF-2", "DTMF-3", "DT
|
|||||||
//
|
//
|
||||||
static void md380_print_version(radio_device_t *radio, FILE *out)
|
static void md380_print_version(radio_device_t *radio, FILE *out)
|
||||||
{
|
{
|
||||||
unsigned char *timestamp = &radio_mem[OFFSET_TIMESTMP];
|
unsigned char *timestamp = GET_TIMESTAMP();
|
||||||
static const char charmap[16] = "0123456789:;<=>?";
|
static const char charmap[16] = "0123456789:;<=>?";
|
||||||
|
|
||||||
if (*timestamp != 0xff) {
|
if (*timestamp != 0xff) {
|
||||||
@ -368,8 +378,6 @@ static void md380_upload(radio_device_t *radio, int cont_flag)
|
|||||||
|
|
||||||
dfu_erase(MEMSZ);
|
dfu_erase(MEMSZ);
|
||||||
|
|
||||||
fprintf(stderr, "Sending data... ");
|
|
||||||
fflush(stderr);
|
|
||||||
for (bno=0; bno<MEMSZ/1024; bno++) {
|
for (bno=0; bno<MEMSZ/1024; bno++) {
|
||||||
dfu_write_block(bno, &radio_mem[bno*1024], 1024);
|
dfu_write_block(bno, &radio_mem[bno*1024], 1024);
|
||||||
|
|
||||||
@ -394,7 +402,7 @@ static int md380_is_compatible(radio_device_t *radio)
|
|||||||
//
|
//
|
||||||
static void setup_zone(int index, const char *name)
|
static void setup_zone(int index, const char *name)
|
||||||
{
|
{
|
||||||
zone_t *z = (zone_t*) &radio_mem[OFFSET_ZONES + index*64];
|
zone_t *z = GET_ZONE(index);
|
||||||
|
|
||||||
utf8_decode(z->name, name, 16);
|
utf8_decode(z->name, name, 16);
|
||||||
}
|
}
|
||||||
@ -403,9 +411,9 @@ static void setup_zone(int index, const char *name)
|
|||||||
// Add channel to a zone.
|
// Add channel to a zone.
|
||||||
// Return 0 on failure.
|
// Return 0 on failure.
|
||||||
//
|
//
|
||||||
static int zone_append(int zone_index, int cnum)
|
static int zone_append(int index, int cnum)
|
||||||
{
|
{
|
||||||
zone_t *z = (zone_t*) &radio_mem[OFFSET_ZONES + zone_index*64];
|
zone_t *z = GET_ZONE(index);
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i=0; i<16; i++) {
|
for (i=0; i<16; i++) {
|
||||||
@ -419,9 +427,9 @@ static int zone_append(int zone_index, int cnum)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void erase_zone(int zone_index)
|
static void erase_zone(int index)
|
||||||
{
|
{
|
||||||
zone_t *z = (zone_t*) &radio_mem[OFFSET_ZONES + zone_index*64];
|
zone_t *z = GET_ZONE(index);
|
||||||
|
|
||||||
memset(z, 0, 64);
|
memset(z, 0, 64);
|
||||||
}
|
}
|
||||||
@ -432,7 +440,7 @@ static void erase_zone(int zone_index)
|
|||||||
static void setup_scanlist(int index, const char *name,
|
static void setup_scanlist(int index, const char *name,
|
||||||
int prio1, int prio2, int txchan)
|
int prio1, int prio2, int txchan)
|
||||||
{
|
{
|
||||||
scanlist_t *sl = (scanlist_t*) &radio_mem[OFFSET_SCANL + index*104];
|
scanlist_t *sl = GET_SCANLIST(index);
|
||||||
|
|
||||||
// Bytes 0-31
|
// Bytes 0-31
|
||||||
utf8_decode(sl->name, name, 16);
|
utf8_decode(sl->name, name, 16);
|
||||||
@ -445,7 +453,7 @@ static void setup_scanlist(int index, const char *name,
|
|||||||
|
|
||||||
static void erase_scanlist(int index)
|
static void erase_scanlist(int index)
|
||||||
{
|
{
|
||||||
scanlist_t *sl = (scanlist_t*) &radio_mem[OFFSET_SCANL + index*104];
|
scanlist_t *sl = GET_SCANLIST(index);
|
||||||
|
|
||||||
memset(sl, 0, 104);
|
memset(sl, 0, 104);
|
||||||
|
|
||||||
@ -465,9 +473,9 @@ static void erase_scanlist(int index)
|
|||||||
// Add channel to a zone.
|
// Add channel to a zone.
|
||||||
// Return 0 on failure.
|
// Return 0 on failure.
|
||||||
//
|
//
|
||||||
static int scanlist_append(int list_index, int cnum)
|
static int scanlist_append(int index, int cnum)
|
||||||
{
|
{
|
||||||
scanlist_t *sl = (scanlist_t*) &radio_mem[OFFSET_SCANL + list_index*104];
|
scanlist_t *sl = GET_SCANLIST(index);
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i=0; i<31; i++) {
|
for (i=0; i<31; i++) {
|
||||||
@ -483,7 +491,7 @@ static int scanlist_append(int list_index, int cnum)
|
|||||||
|
|
||||||
static void erase_contact(int index)
|
static void erase_contact(int index)
|
||||||
{
|
{
|
||||||
contact_t *ct = (contact_t*) &radio_mem[OFFSET_CONTACTS + index*36];
|
contact_t *ct = GET_CONTACT(index);
|
||||||
|
|
||||||
memset(ct, 0, 36);
|
memset(ct, 0, 36);
|
||||||
*(uint32_t*)ct = 0xffffffff;
|
*(uint32_t*)ct = 0xffffffff;
|
||||||
@ -491,7 +499,7 @@ static void erase_contact(int index)
|
|||||||
|
|
||||||
static void setup_contact(int index, const char *name, int type, int id, int rxtone)
|
static void setup_contact(int index, const char *name, int type, int id, int rxtone)
|
||||||
{
|
{
|
||||||
contact_t *ct = (contact_t*) &radio_mem[OFFSET_CONTACTS + index*36];
|
contact_t *ct = GET_CONTACT(index);
|
||||||
|
|
||||||
ct->id = id;
|
ct->id = id;
|
||||||
ct->type = type;
|
ct->type = type;
|
||||||
@ -502,7 +510,7 @@ static void setup_contact(int index, const char *name, int type, int id, int rxt
|
|||||||
|
|
||||||
static void setup_grouplist(int index, const char *name)
|
static void setup_grouplist(int index, const char *name)
|
||||||
{
|
{
|
||||||
grouplist_t *gl = (grouplist_t*) &radio_mem[OFFSET_GLISTS + index*96];
|
grouplist_t *gl = GET_GROUPLIST(index);
|
||||||
|
|
||||||
utf8_decode(gl->name, name, 16);
|
utf8_decode(gl->name, name, 16);
|
||||||
}
|
}
|
||||||
@ -513,7 +521,7 @@ static void setup_grouplist(int index, const char *name)
|
|||||||
//
|
//
|
||||||
static int grouplist_append(int index, int cnum)
|
static int grouplist_append(int index, int cnum)
|
||||||
{
|
{
|
||||||
grouplist_t *gl = (grouplist_t*) &radio_mem[OFFSET_GLISTS + index*96];
|
grouplist_t *gl = GET_GROUPLIST(index);
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i=0; i<32; i++) {
|
for (i=0; i<32; i++) {
|
||||||
@ -532,7 +540,7 @@ static int grouplist_append(int index, int cnum)
|
|||||||
//
|
//
|
||||||
static void setup_message(int index, const char *text)
|
static void setup_message(int index, const char *text)
|
||||||
{
|
{
|
||||||
uint16_t *msg = (uint16_t*) &radio_mem[OFFSET_MSG + index*288];
|
uint16_t *msg = GET_MESSAGE(index);
|
||||||
|
|
||||||
// Skip spaces and tabs.
|
// Skip spaces and tabs.
|
||||||
while (*text == ' ' || *text == '\t')
|
while (*text == ' ' || *text == '\t')
|
||||||
@ -560,7 +568,7 @@ static void setup_channel(int i, int mode, char *name, double rx_mhz, double tx_
|
|||||||
int admit, int colorcode, int timeslot, int incall, int grouplist, int contact,
|
int admit, int colorcode, int timeslot, int incall, int grouplist, int contact,
|
||||||
int rxtone, int txtone, int width)
|
int rxtone, int txtone, int width)
|
||||||
{
|
{
|
||||||
channel_t *ch = (channel_t*) &radio_mem[OFFSET_CHANNELS + i*64];
|
channel_t *ch = GET_CHANNEL(i);
|
||||||
|
|
||||||
ch->channel_mode = mode;
|
ch->channel_mode = mode;
|
||||||
ch->bandwidth = width;
|
ch->bandwidth = width;
|
||||||
@ -590,7 +598,7 @@ static void setup_channel(int i, int mode, char *name, double rx_mhz, double tx_
|
|||||||
//
|
//
|
||||||
static void erase_channel(int i)
|
static void erase_channel(int i)
|
||||||
{
|
{
|
||||||
channel_t *ch = (channel_t*) &radio_mem[OFFSET_CHANNELS + i*64];
|
channel_t *ch = GET_CHANNEL(i);
|
||||||
|
|
||||||
// Byte 0
|
// Byte 0
|
||||||
ch->channel_mode = MODE_ANALOG;
|
ch->channel_mode = MODE_ANALOG;
|
||||||
@ -706,7 +714,7 @@ static void print_chanlist(FILE *out, uint16_t *unsorted, int nchan)
|
|||||||
|
|
||||||
static void print_id(FILE *out, int verbose)
|
static void print_id(FILE *out, int verbose)
|
||||||
{
|
{
|
||||||
general_settings_t *gs = (general_settings_t*) &radio_mem[OFFSET_SETTINGS];
|
general_settings_t *gs = GET_SETTINGS();
|
||||||
unsigned id = gs->radio_id[0] | (gs->radio_id[1] << 8) | (gs->radio_id[2] << 16);
|
unsigned id = gs->radio_id[0] | (gs->radio_id[1] << 8) | (gs->radio_id[2] << 16);
|
||||||
|
|
||||||
if (verbose)
|
if (verbose)
|
||||||
@ -722,7 +730,7 @@ static void print_id(FILE *out, int verbose)
|
|||||||
|
|
||||||
static void print_intro(FILE *out, int verbose)
|
static void print_intro(FILE *out, int verbose)
|
||||||
{
|
{
|
||||||
general_settings_t *gs = (general_settings_t*) &radio_mem[OFFSET_SETTINGS];
|
general_settings_t *gs = GET_SETTINGS();
|
||||||
|
|
||||||
if (verbose)
|
if (verbose)
|
||||||
fprintf(out, "\n# Text displayed when the radio powers up.\n");
|
fprintf(out, "\n# Text displayed when the radio powers up.\n");
|
||||||
@ -749,7 +757,7 @@ static int have_channels(int mode)
|
|||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i=0; i<NCHAN; i++) {
|
for (i=0; i<NCHAN; i++) {
|
||||||
channel_t *ch = (channel_t*) &radio_mem[OFFSET_CHANNELS + i*64];
|
channel_t *ch = GET_CHANNEL(i);
|
||||||
|
|
||||||
if (ch->name[0] != 0 && ch->channel_mode == mode)
|
if (ch->name[0] != 0 && ch->channel_mode == mode)
|
||||||
return 1;
|
return 1;
|
||||||
@ -850,7 +858,7 @@ static void print_digital_channels(FILE *out, int verbose)
|
|||||||
#endif
|
#endif
|
||||||
fprintf(out, "\n");
|
fprintf(out, "\n");
|
||||||
for (i=0; i<NCHAN; i++) {
|
for (i=0; i<NCHAN; i++) {
|
||||||
channel_t *ch = (channel_t*) &radio_mem[OFFSET_CHANNELS + i*64];
|
channel_t *ch = GET_CHANNEL(i);
|
||||||
|
|
||||||
if (ch->name[0] == 0 || ch->channel_mode != MODE_DIGITAL) {
|
if (ch->name[0] == 0 || ch->channel_mode != MODE_DIGITAL) {
|
||||||
// Select digital channels
|
// Select digital channels
|
||||||
@ -939,7 +947,7 @@ static void print_analog_channels(FILE *out, int verbose)
|
|||||||
#endif
|
#endif
|
||||||
fprintf(out, "\n");
|
fprintf(out, "\n");
|
||||||
for (i=0; i<NCHAN; i++) {
|
for (i=0; i<NCHAN; i++) {
|
||||||
channel_t *ch = (channel_t*) &radio_mem[OFFSET_CHANNELS + i*64];
|
channel_t *ch = GET_CHANNEL(i);
|
||||||
|
|
||||||
if (ch->name[0] == 0 || ch->channel_mode != MODE_ANALOG) {
|
if (ch->name[0] == 0 || ch->channel_mode != MODE_ANALOG) {
|
||||||
// Select analog channels
|
// Select analog channels
|
||||||
@ -975,37 +983,66 @@ static void print_analog_channels(FILE *out, int verbose)
|
|||||||
|
|
||||||
static int have_zones()
|
static int have_zones()
|
||||||
{
|
{
|
||||||
zone_t *z = (zone_t*) &radio_mem[OFFSET_ZONES];
|
int i;
|
||||||
|
|
||||||
return z->name[0] != 0 && z->name[0] != 0xffff;
|
for (i=0; i<NZONES; i++) {
|
||||||
|
zone_t *z = GET_ZONE(i);
|
||||||
|
if (z->name[0] != 0 && z->name[0] != 0xffff)
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int have_scanlists()
|
static int have_scanlists()
|
||||||
{
|
{
|
||||||
scanlist_t *sl = (scanlist_t*) &radio_mem[OFFSET_SCANL];
|
int i;
|
||||||
|
|
||||||
return sl->name[0] != 0 && sl->name[0] != 0xffff;
|
for (i=0; i<NSCANL; i++) {
|
||||||
|
scanlist_t *sl = GET_SCANLIST(i);
|
||||||
|
|
||||||
|
if (sl->name[0] != 0 && sl->name[0] != 0xffff)
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int have_contacts()
|
static int have_contacts()
|
||||||
{
|
{
|
||||||
contact_t *ct = (contact_t*) &radio_mem[OFFSET_CONTACTS];
|
int i;
|
||||||
|
|
||||||
return ct->name[0] != 0 && ct->name[0] != 0xffff;
|
for (i=0; i<NCONTACTS; i++) {
|
||||||
|
contact_t *ct = GET_CONTACT(i);
|
||||||
|
|
||||||
|
if (ct->name[0] != 0 && ct->name[0] != 0xffff)
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int have_grouplists()
|
static int have_grouplists()
|
||||||
{
|
{
|
||||||
grouplist_t *gl = (grouplist_t*) &radio_mem[OFFSET_GLISTS];
|
int i;
|
||||||
|
|
||||||
return gl->name[0] != 0 && gl->name[0] != 0xffff;
|
for (i=0; i<NGLISTS; i++) {
|
||||||
|
grouplist_t *gl = GET_GROUPLIST(i);
|
||||||
|
|
||||||
|
if (gl->name[0] != 0 && gl->name[0] != 0xffff)
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int have_messages()
|
static int have_messages()
|
||||||
{
|
{
|
||||||
uint16_t *msg = (uint16_t*) &radio_mem[OFFSET_MSG];
|
int i;
|
||||||
|
|
||||||
return msg[0] != 0 && msg[0] != 0xffff;
|
for (i=0; i<NMESSAGES; i++) {
|
||||||
|
uint16_t *msg = GET_MESSAGE(i);
|
||||||
|
|
||||||
|
if (msg[0] != 0 && msg[0] != 0xffff)
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -1045,7 +1082,7 @@ static void md380_print_config(radio_device_t *radio, FILE *out, int verbose)
|
|||||||
}
|
}
|
||||||
fprintf(out, "Zone Name Channels\n");
|
fprintf(out, "Zone Name Channels\n");
|
||||||
for (i=0; i<NZONES; i++) {
|
for (i=0; i<NZONES; i++) {
|
||||||
zone_t *z = (zone_t*) &radio_mem[OFFSET_ZONES + i*64];
|
zone_t *z = GET_ZONE(i);
|
||||||
|
|
||||||
if (z->name[0] == 0 || z->name[0] == 0xffff) {
|
if (z->name[0] == 0 || z->name[0] == 0xffff) {
|
||||||
// Zone is disabled.
|
// Zone is disabled.
|
||||||
@ -1085,7 +1122,7 @@ static void md380_print_config(radio_device_t *radio, FILE *out, int verbose)
|
|||||||
#endif
|
#endif
|
||||||
fprintf(out, "Channels\n");
|
fprintf(out, "Channels\n");
|
||||||
for (i=0; i<NSCANL; i++) {
|
for (i=0; i<NSCANL; i++) {
|
||||||
scanlist_t *sl = (scanlist_t*) &radio_mem[OFFSET_SCANL + i*104];
|
scanlist_t *sl = GET_SCANLIST(i);
|
||||||
|
|
||||||
if (sl->name[0] == 0 || sl->name[0] == 0xffff) {
|
if (sl->name[0] == 0 || sl->name[0] == 0xffff) {
|
||||||
// Scan list is disabled.
|
// Scan list is disabled.
|
||||||
@ -1144,7 +1181,7 @@ static void md380_print_config(radio_device_t *radio, FILE *out, int verbose)
|
|||||||
}
|
}
|
||||||
fprintf(out, "Contact Name Type ID RxTone\n");
|
fprintf(out, "Contact Name Type ID RxTone\n");
|
||||||
for (i=0; i<NCONTACTS; i++) {
|
for (i=0; i<NCONTACTS; i++) {
|
||||||
contact_t *ct = (contact_t*) &radio_mem[OFFSET_CONTACTS + i*36];
|
contact_t *ct = GET_CONTACT(i);
|
||||||
|
|
||||||
if (ct->name[0] == 0 || ct->name[0] == 0xffff) {
|
if (ct->name[0] == 0 || ct->name[0] == 0xffff) {
|
||||||
// Contact is disabled
|
// Contact is disabled
|
||||||
@ -1172,7 +1209,7 @@ static void md380_print_config(radio_device_t *radio, FILE *out, int verbose)
|
|||||||
}
|
}
|
||||||
fprintf(out, "Grouplist Name Contacts\n");
|
fprintf(out, "Grouplist Name Contacts\n");
|
||||||
for (i=0; i<NGLISTS; i++) {
|
for (i=0; i<NGLISTS; i++) {
|
||||||
grouplist_t *gl = (grouplist_t*) &radio_mem[OFFSET_GLISTS + i*96];
|
grouplist_t *gl = GET_GROUPLIST(i);
|
||||||
|
|
||||||
if (gl->name[0] == 0 || gl->name[0] == 0xffff) {
|
if (gl->name[0] == 0 || gl->name[0] == 0xffff) {
|
||||||
// Group list is disabled.
|
// Group list is disabled.
|
||||||
@ -1204,7 +1241,7 @@ static void md380_print_config(radio_device_t *radio, FILE *out, int verbose)
|
|||||||
}
|
}
|
||||||
fprintf(out, "Message Text\n");
|
fprintf(out, "Message Text\n");
|
||||||
for (i=0; i<NMESSAGES; i++) {
|
for (i=0; i<NMESSAGES; i++) {
|
||||||
uint16_t *msg = (uint16_t*) &radio_mem[OFFSET_MSG + i*288];
|
uint16_t *msg = GET_MESSAGE(i);
|
||||||
|
|
||||||
if (msg[0] == 0 || msg[0] == 0xffff) {
|
if (msg[0] == 0 || msg[0] == 0xffff) {
|
||||||
// Message is disabled
|
// Message is disabled
|
||||||
@ -1318,7 +1355,7 @@ static void erase_contacts()
|
|||||||
//
|
//
|
||||||
static void md380_parse_parameter(radio_device_t *radio, char *param, char *value)
|
static void md380_parse_parameter(radio_device_t *radio, char *param, char *value)
|
||||||
{
|
{
|
||||||
general_settings_t *gs = (general_settings_t*) &radio_mem[OFFSET_SETTINGS];
|
general_settings_t *gs = GET_SETTINGS();
|
||||||
|
|
||||||
if (strcasecmp("Radio", param) == 0) {
|
if (strcasecmp("Radio", param) == 0) {
|
||||||
if (strcasecmp(radio->name, value) != 0) {
|
if (strcasecmp(radio->name, value) != 0) {
|
||||||
@ -2057,7 +2094,7 @@ static int md380_parse_row(radio_device_t *radio, int table_id, int first_row, c
|
|||||||
//
|
//
|
||||||
static void md380_update_timestamp(radio_device_t *radio)
|
static void md380_update_timestamp(radio_device_t *radio)
|
||||||
{
|
{
|
||||||
unsigned char *timestamp = &radio_mem[OFFSET_TIMESTMP];
|
unsigned char *timestamp = GET_TIMESTAMP();
|
||||||
char p[16];
|
char p[16];
|
||||||
|
|
||||||
// Last Programmed Date
|
// Last Programmed Date
|
||||||
@ -2085,6 +2122,146 @@ static void md380_update_timestamp(radio_device_t *radio)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Check that configuration is correct.
|
||||||
|
// Return 0 on error.
|
||||||
|
//
|
||||||
|
static int md380_verify_config(radio_device_t *radio)
|
||||||
|
{
|
||||||
|
int i, k, nchannels = 0, nzones = 0, nscanlists = 0, ngrouplists = 0;
|
||||||
|
int ncontacts = 0, nerrors = 0;
|
||||||
|
|
||||||
|
// Channels: check references to scanlists, contacts and grouplists.
|
||||||
|
for (i=0; i<NCHAN; i++) {
|
||||||
|
channel_t *ch = GET_CHANNEL(i);
|
||||||
|
|
||||||
|
if (ch->name[0] == 0 || ch->name[0] == 0xffff)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
nchannels++;
|
||||||
|
if (ch->scan_list_index != 0) {
|
||||||
|
scanlist_t *sl = GET_SCANLIST(ch->scan_list_index - 1);
|
||||||
|
|
||||||
|
if (sl->name[0] == 0 || sl->name[0] == 0xffff) {
|
||||||
|
fprintf(stderr, "Channel %d '", i+1);
|
||||||
|
print_unicode(stderr, ch->name, 16, 0);
|
||||||
|
fprintf(stderr, "': scanlist %d not found.\n", ch->scan_list_index);
|
||||||
|
nerrors++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ch->contact_name_index != 0) {
|
||||||
|
contact_t *ct = GET_CONTACT(ch->contact_name_index - 1);
|
||||||
|
|
||||||
|
if (ct->name[0] == 0 || ct->name[0] == 0xffff) {
|
||||||
|
fprintf(stderr, "Channel %d '", i+1);
|
||||||
|
print_unicode(stderr, ch->name, 16, 0);
|
||||||
|
fprintf(stderr, "': contact %d not found.\n", ch->contact_name_index);
|
||||||
|
nerrors++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ch->group_list_index != 0) {
|
||||||
|
grouplist_t *gl = GET_GROUPLIST(ch->group_list_index - 1);
|
||||||
|
|
||||||
|
if (gl->name[0] == 0 || gl->name[0] == 0xffff) {
|
||||||
|
fprintf(stderr, "Channel %d '", i+1);
|
||||||
|
print_unicode(stderr, ch->name, 16, 0);
|
||||||
|
fprintf(stderr, "': grouplist %d not found.\n", ch->group_list_index);
|
||||||
|
nerrors++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Zones: check references to channels.
|
||||||
|
for (i=0; i<NZONES; i++) {
|
||||||
|
zone_t *z = GET_ZONE(i);
|
||||||
|
|
||||||
|
if (z->name[0] == 0 || z->name[0] == 0xffff)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
nzones++;
|
||||||
|
for (k=0; k<16; k++) {
|
||||||
|
int cnum = z->member[k];
|
||||||
|
|
||||||
|
if (cnum != 0) {
|
||||||
|
channel_t *ch = GET_CHANNEL(cnum - 1);
|
||||||
|
|
||||||
|
if (ch->name[0] == 0 || ch->name[0] == 0xffff) {
|
||||||
|
fprintf(stderr, "Zone %da '", i+1);
|
||||||
|
print_unicode(stderr, z->name, 16, 0);
|
||||||
|
fprintf(stderr, "': channel %d not found.\n", cnum);
|
||||||
|
nerrors++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Scanlists: check references to channels.
|
||||||
|
for (i=0; i<NSCANL; i++) {
|
||||||
|
scanlist_t *sl = GET_SCANLIST(i);
|
||||||
|
|
||||||
|
if (sl->name[0] == 0 || sl->name[0] == 0xffff)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
nscanlists++;
|
||||||
|
for (k=0; k<31; k++) {
|
||||||
|
int cnum = sl->member[k];
|
||||||
|
|
||||||
|
if (cnum != 0) {
|
||||||
|
channel_t *ch = GET_CHANNEL(cnum - 1);
|
||||||
|
|
||||||
|
if (ch->name[0] == 0 || ch->name[0] == 0xffff) {
|
||||||
|
fprintf(stderr, "Scanlist %d '", i+1);
|
||||||
|
print_unicode(stderr, sl->name, 16, 0);
|
||||||
|
fprintf(stderr, "': channel %d not found.\n", cnum);
|
||||||
|
nerrors++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Grouplists: check references to contacts.
|
||||||
|
for (i=0; i<NGLISTS; i++) {
|
||||||
|
grouplist_t *gl = GET_GROUPLIST(i);
|
||||||
|
|
||||||
|
if (gl->name[0] == 0 || gl->name[0] == 0xffff)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
ngrouplists++;
|
||||||
|
for (k=0; k<32; k++) {
|
||||||
|
int cnum = gl->member[k];
|
||||||
|
|
||||||
|
if (cnum != 0) {
|
||||||
|
contact_t *ct = GET_CONTACT(cnum - 1);
|
||||||
|
|
||||||
|
if (ct->name[0] == 0 || ct->name[0] == 0xffff) {
|
||||||
|
fprintf(stderr, "Grouplist %d '", i+1);
|
||||||
|
print_unicode(stderr, gl->name, 16, 0);
|
||||||
|
fprintf(stderr, "': contact %d not found.\n", cnum);
|
||||||
|
nerrors++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Count contacts.
|
||||||
|
for (i=0; i<NCONTACTS; i++) {
|
||||||
|
contact_t *ct = GET_CONTACT(i);
|
||||||
|
|
||||||
|
if (ct->name[0] == 0 || ct->name[0] == 0xffff)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
ncontacts++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nerrors > 0) {
|
||||||
|
fprintf(stderr, "Total %d errors.\n", nerrors);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
fprintf(stderr, "Total %d channels, %d zones, %d scanlists, %d contacts, %d grouplists.\n",
|
||||||
|
nchannels, nzones, nscanlists, ncontacts, ngrouplists);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// TYT MD-380
|
// TYT MD-380
|
||||||
//
|
//
|
||||||
@ -2097,6 +2274,7 @@ radio_device_t radio_md380 = {
|
|||||||
md380_save_image,
|
md380_save_image,
|
||||||
md380_print_version,
|
md380_print_version,
|
||||||
md380_print_config,
|
md380_print_config,
|
||||||
|
md380_verify_config,
|
||||||
md380_parse_parameter,
|
md380_parse_parameter,
|
||||||
md380_parse_header,
|
md380_parse_header,
|
||||||
md380_parse_row,
|
md380_parse_row,
|
||||||
|
11
radio.c
11
radio.c
@ -282,3 +282,14 @@ void radio_print_config(FILE *out, int verbose)
|
|||||||
}
|
}
|
||||||
device->print_config(device, out, verbose);
|
device->print_config(device, out, verbose);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Check the configuration is correct.
|
||||||
|
//
|
||||||
|
void radio_verify_config()
|
||||||
|
{
|
||||||
|
if (!device->verify_config(device)) {
|
||||||
|
// Message should be already printed.
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
6
radio.h
6
radio.h
@ -72,6 +72,11 @@ void radio_save_image(char *filename);
|
|||||||
//
|
//
|
||||||
void radio_parse_config(char *filename);
|
void radio_parse_config(char *filename);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Check the configuration.
|
||||||
|
//
|
||||||
|
void radio_verify_config();
|
||||||
|
|
||||||
//
|
//
|
||||||
// Device-dependent interface to the radio.
|
// Device-dependent interface to the radio.
|
||||||
//
|
//
|
||||||
@ -85,6 +90,7 @@ struct _radio_device_t {
|
|||||||
void (*save_image)(radio_device_t *radio, FILE *img);
|
void (*save_image)(radio_device_t *radio, FILE *img);
|
||||||
void (*print_version)(radio_device_t *radio, FILE *out);
|
void (*print_version)(radio_device_t *radio, FILE *out);
|
||||||
void (*print_config)(radio_device_t *radio, FILE *out, int verbose);
|
void (*print_config)(radio_device_t *radio, FILE *out, int verbose);
|
||||||
|
int (*verify_config)(radio_device_t *radio);
|
||||||
void (*parse_parameter)(radio_device_t *radio, char *param, char *value);
|
void (*parse_parameter)(radio_device_t *radio, char *param, char *value);
|
||||||
int (*parse_header)(radio_device_t *radio, char *line);
|
int (*parse_header)(radio_device_t *radio, char *line);
|
||||||
int (*parse_row)(radio_device_t *radio, int table_id, int first_row, char *line);
|
int (*parse_row)(radio_device_t *radio, int table_id, int first_row, char *line);
|
||||||
|
298
uv380.c
298
uv380.c
@ -52,6 +52,16 @@
|
|||||||
#define OFFSET_CHANNELS 0x40000
|
#define OFFSET_CHANNELS 0x40000
|
||||||
#define OFFSET_CONTACTS 0x70000
|
#define OFFSET_CONTACTS 0x70000
|
||||||
|
|
||||||
|
#define GET_TIMESTAMP() (&radio_mem[OFFSET_TIMESTMP])
|
||||||
|
#define GET_SETTINGS() ((general_settings_t*) &radio_mem[OFFSET_SETTINGS])
|
||||||
|
#define GET_CHANNEL(i) ((channel_t*) &radio_mem[OFFSET_CHANNELS + (i)*64])
|
||||||
|
#define GET_ZONE(i) ((zone_t*) &radio_mem[OFFSET_ZONES + (i)*64])
|
||||||
|
#define GET_ZONEXT(i) ((zone_ext_t*) &radio_mem[OFFSET_ZONEXT + (i)*224])
|
||||||
|
#define GET_SCANLIST(i) ((scanlist_t*) &radio_mem[OFFSET_SCANL + (i)*104])
|
||||||
|
#define GET_CONTACT(i) ((contact_t*) &radio_mem[OFFSET_CONTACTS + (i)*36])
|
||||||
|
#define GET_GROUPLIST(i) ((grouplist_t*) &radio_mem[OFFSET_GLISTS + (i)*96])
|
||||||
|
#define GET_MESSAGE(i) ((uint16_t*) &radio_mem[OFFSET_MSG + (i)*288])
|
||||||
|
|
||||||
//
|
//
|
||||||
// Channel data.
|
// Channel data.
|
||||||
//
|
//
|
||||||
@ -343,7 +353,7 @@ static const char *TURNOFF_FREQ[] = { "259.2", "55.2", "???", "-" };
|
|||||||
//
|
//
|
||||||
static void uv380_print_version(radio_device_t *radio, FILE *out)
|
static void uv380_print_version(radio_device_t *radio, FILE *out)
|
||||||
{
|
{
|
||||||
unsigned char *timestamp = &radio_mem[OFFSET_TIMESTMP];
|
unsigned char *timestamp = GET_TIMESTAMP();
|
||||||
static const char charmap[16] = "0123456789:;<=>?";
|
static const char charmap[16] = "0123456789:;<=>?";
|
||||||
|
|
||||||
if (*timestamp != 0xff) {
|
if (*timestamp != 0xff) {
|
||||||
@ -410,7 +420,7 @@ static int uv380_is_compatible(radio_device_t *radio)
|
|||||||
//
|
//
|
||||||
static void setup_zone(int index, const char *name)
|
static void setup_zone(int index, const char *name)
|
||||||
{
|
{
|
||||||
zone_t *z = (zone_t*) &radio_mem[OFFSET_ZONES + index*64];
|
zone_t *z = GET_ZONE(index);
|
||||||
|
|
||||||
utf8_decode(z->name, name, 16);
|
utf8_decode(z->name, name, 16);
|
||||||
}
|
}
|
||||||
@ -419,10 +429,10 @@ static void setup_zone(int index, const char *name)
|
|||||||
// Add channel to a zone.
|
// Add channel to a zone.
|
||||||
// Return 0 on failure.
|
// Return 0 on failure.
|
||||||
//
|
//
|
||||||
static int zone_append(int zone_index, int b_flag, int cnum)
|
static int zone_append(int index, int b_flag, int cnum)
|
||||||
{
|
{
|
||||||
zone_t *z = (zone_t*) &radio_mem[OFFSET_ZONES + zone_index*64];
|
zone_t *z = GET_ZONE(index);
|
||||||
zone_ext_t *zext = (zone_ext_t*) &radio_mem[OFFSET_ZONEXT + zone_index*224];
|
zone_ext_t *zext = GET_ZONEXT(index);
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (b_flag) {
|
if (b_flag) {
|
||||||
@ -455,10 +465,10 @@ static int zone_append(int zone_index, int b_flag, int cnum)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void erase_zone(int zone_index)
|
static void erase_zone(int index)
|
||||||
{
|
{
|
||||||
zone_t *z = (zone_t*) &radio_mem[OFFSET_ZONES + zone_index*64];
|
zone_t *z = GET_ZONE(index);
|
||||||
zone_ext_t *zext = (zone_ext_t*) &radio_mem[OFFSET_ZONEXT + zone_index*224];
|
zone_ext_t *zext = GET_ZONEXT(index);
|
||||||
|
|
||||||
memset(z, 0, 64);
|
memset(z, 0, 64);
|
||||||
memset(zext, 0, 224);
|
memset(zext, 0, 224);
|
||||||
@ -470,7 +480,7 @@ static void erase_zone(int zone_index)
|
|||||||
static void setup_scanlist(int index, const char *name,
|
static void setup_scanlist(int index, const char *name,
|
||||||
int prio1, int prio2, int txchan)
|
int prio1, int prio2, int txchan)
|
||||||
{
|
{
|
||||||
scanlist_t *sl = (scanlist_t*) &radio_mem[OFFSET_SCANL + index*104];
|
scanlist_t *sl = GET_SCANLIST(index);
|
||||||
|
|
||||||
// Bytes 0-31
|
// Bytes 0-31
|
||||||
utf8_decode(sl->name, name, 16);
|
utf8_decode(sl->name, name, 16);
|
||||||
@ -483,7 +493,7 @@ static void setup_scanlist(int index, const char *name,
|
|||||||
|
|
||||||
static void erase_scanlist(int index)
|
static void erase_scanlist(int index)
|
||||||
{
|
{
|
||||||
scanlist_t *sl = (scanlist_t*) &radio_mem[OFFSET_SCANL + index*104];
|
scanlist_t *sl = GET_SCANLIST(index);
|
||||||
|
|
||||||
memset(sl, 0, 104);
|
memset(sl, 0, 104);
|
||||||
|
|
||||||
@ -503,9 +513,9 @@ static void erase_scanlist(int index)
|
|||||||
// Add channel to a zone.
|
// Add channel to a zone.
|
||||||
// Return 0 on failure.
|
// Return 0 on failure.
|
||||||
//
|
//
|
||||||
static int scanlist_append(int list_index, int cnum)
|
static int scanlist_append(int index, int cnum)
|
||||||
{
|
{
|
||||||
scanlist_t *sl = (scanlist_t*) &radio_mem[OFFSET_SCANL + list_index*104];
|
scanlist_t *sl = GET_SCANLIST(index);
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i=0; i<31; i++) {
|
for (i=0; i<31; i++) {
|
||||||
@ -521,7 +531,7 @@ static int scanlist_append(int list_index, int cnum)
|
|||||||
|
|
||||||
static void erase_contact(int index)
|
static void erase_contact(int index)
|
||||||
{
|
{
|
||||||
contact_t *ct = (contact_t*) &radio_mem[OFFSET_CONTACTS + index*36];
|
contact_t *ct = GET_CONTACT(index);
|
||||||
|
|
||||||
memset(ct, 0, 36);
|
memset(ct, 0, 36);
|
||||||
*(uint32_t*)ct = 0xffffffff;
|
*(uint32_t*)ct = 0xffffffff;
|
||||||
@ -529,7 +539,7 @@ static void erase_contact(int index)
|
|||||||
|
|
||||||
static void setup_contact(int index, const char *name, int type, int id, int rxtone)
|
static void setup_contact(int index, const char *name, int type, int id, int rxtone)
|
||||||
{
|
{
|
||||||
contact_t *ct = (contact_t*) &radio_mem[OFFSET_CONTACTS + index*36];
|
contact_t *ct = GET_CONTACT(index);
|
||||||
|
|
||||||
ct->id = id;
|
ct->id = id;
|
||||||
ct->type = type;
|
ct->type = type;
|
||||||
@ -540,7 +550,7 @@ static void setup_contact(int index, const char *name, int type, int id, int rxt
|
|||||||
|
|
||||||
static void setup_grouplist(int index, const char *name)
|
static void setup_grouplist(int index, const char *name)
|
||||||
{
|
{
|
||||||
grouplist_t *gl = (grouplist_t*) &radio_mem[OFFSET_GLISTS + index*96];
|
grouplist_t *gl = GET_GROUPLIST(index);
|
||||||
|
|
||||||
utf8_decode(gl->name, name, 16);
|
utf8_decode(gl->name, name, 16);
|
||||||
}
|
}
|
||||||
@ -551,7 +561,7 @@ static void setup_grouplist(int index, const char *name)
|
|||||||
//
|
//
|
||||||
static int grouplist_append(int index, int cnum)
|
static int grouplist_append(int index, int cnum)
|
||||||
{
|
{
|
||||||
grouplist_t *gl = (grouplist_t*) &radio_mem[OFFSET_GLISTS + index*96];
|
grouplist_t *gl = GET_GROUPLIST(index);
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i=0; i<32; i++) {
|
for (i=0; i<32; i++) {
|
||||||
@ -570,7 +580,7 @@ static int grouplist_append(int index, int cnum)
|
|||||||
//
|
//
|
||||||
static void setup_message(int index, const char *text)
|
static void setup_message(int index, const char *text)
|
||||||
{
|
{
|
||||||
uint16_t *msg = (uint16_t*) &radio_mem[OFFSET_MSG + index*288];
|
uint16_t *msg = GET_MESSAGE(index);
|
||||||
|
|
||||||
// Skip spaces and tabs.
|
// Skip spaces and tabs.
|
||||||
while (*text == ' ' || *text == '\t')
|
while (*text == ' ' || *text == '\t')
|
||||||
@ -598,7 +608,7 @@ static void setup_channel(int i, int mode, char *name, double rx_mhz, double tx_
|
|||||||
int admit, int colorcode, int timeslot, int incall, int grouplist, int contact,
|
int admit, int colorcode, int timeslot, int incall, int grouplist, int contact,
|
||||||
int rxtone, int txtone, int width)
|
int rxtone, int txtone, int width)
|
||||||
{
|
{
|
||||||
channel_t *ch = (channel_t*) &radio_mem[OFFSET_CHANNELS + i*64];
|
channel_t *ch = GET_CHANNEL(i);
|
||||||
|
|
||||||
ch->channel_mode = mode;
|
ch->channel_mode = mode;
|
||||||
ch->bandwidth = width;
|
ch->bandwidth = width;
|
||||||
@ -628,7 +638,7 @@ static void setup_channel(int i, int mode, char *name, double rx_mhz, double tx_
|
|||||||
//
|
//
|
||||||
static void erase_channel(int i)
|
static void erase_channel(int i)
|
||||||
{
|
{
|
||||||
channel_t *ch = (channel_t*) &radio_mem[OFFSET_CHANNELS + i*64];
|
channel_t *ch = GET_CHANNEL(i);
|
||||||
|
|
||||||
// Byte 0
|
// Byte 0
|
||||||
ch->channel_mode = MODE_ANALOG;
|
ch->channel_mode = MODE_ANALOG;
|
||||||
@ -748,7 +758,7 @@ static void print_chanlist(FILE *out, uint16_t *unsorted, int nchan)
|
|||||||
|
|
||||||
static void print_id(FILE *out, int verbose)
|
static void print_id(FILE *out, int verbose)
|
||||||
{
|
{
|
||||||
general_settings_t *gs = (general_settings_t*) &radio_mem[OFFSET_SETTINGS];
|
general_settings_t *gs = GET_SETTINGS();
|
||||||
unsigned id = gs->radio_id[0] | (gs->radio_id[1] << 8) | (gs->radio_id[2] << 16);
|
unsigned id = gs->radio_id[0] | (gs->radio_id[1] << 8) | (gs->radio_id[2] << 16);
|
||||||
|
|
||||||
if (verbose)
|
if (verbose)
|
||||||
@ -764,7 +774,7 @@ static void print_id(FILE *out, int verbose)
|
|||||||
|
|
||||||
static void print_intro(FILE *out, int verbose)
|
static void print_intro(FILE *out, int verbose)
|
||||||
{
|
{
|
||||||
general_settings_t *gs = (general_settings_t*) &radio_mem[OFFSET_SETTINGS];
|
general_settings_t *gs = GET_SETTINGS();
|
||||||
|
|
||||||
if (verbose)
|
if (verbose)
|
||||||
fprintf(out, "\n# Text displayed when the radio powers up.\n");
|
fprintf(out, "\n# Text displayed when the radio powers up.\n");
|
||||||
@ -791,7 +801,7 @@ static int have_channels(int mode)
|
|||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i=0; i<NCHAN; i++) {
|
for (i=0; i<NCHAN; i++) {
|
||||||
channel_t *ch = (channel_t*) &radio_mem[OFFSET_CHANNELS + i*64];
|
channel_t *ch = GET_CHANNEL(i);
|
||||||
|
|
||||||
if (ch->name[0] != 0 && ch->channel_mode == mode)
|
if (ch->name[0] != 0 && ch->channel_mode == mode)
|
||||||
return 1;
|
return 1;
|
||||||
@ -894,7 +904,7 @@ static void print_digital_channels(FILE *out, int verbose)
|
|||||||
#endif
|
#endif
|
||||||
fprintf(out, "\n");
|
fprintf(out, "\n");
|
||||||
for (i=0; i<NCHAN; i++) {
|
for (i=0; i<NCHAN; i++) {
|
||||||
channel_t *ch = (channel_t*) &radio_mem[OFFSET_CHANNELS + i*64];
|
channel_t *ch = GET_CHANNEL(i);
|
||||||
|
|
||||||
if (ch->name[0] == 0 || ch->channel_mode != MODE_DIGITAL) {
|
if (ch->name[0] == 0 || ch->channel_mode != MODE_DIGITAL) {
|
||||||
// Select digital channels
|
// Select digital channels
|
||||||
@ -987,7 +997,7 @@ static void print_analog_channels(FILE *out, int verbose)
|
|||||||
#endif
|
#endif
|
||||||
fprintf(out, "\n");
|
fprintf(out, "\n");
|
||||||
for (i=0; i<NCHAN; i++) {
|
for (i=0; i<NCHAN; i++) {
|
||||||
channel_t *ch = (channel_t*) &radio_mem[OFFSET_CHANNELS + i*64];
|
channel_t *ch = GET_CHANNEL(i);
|
||||||
|
|
||||||
if (ch->name[0] == 0 || ch->channel_mode != MODE_ANALOG) {
|
if (ch->name[0] == 0 || ch->channel_mode != MODE_ANALOG) {
|
||||||
// Select analog channels
|
// Select analog channels
|
||||||
@ -1024,37 +1034,66 @@ static void print_analog_channels(FILE *out, int verbose)
|
|||||||
|
|
||||||
static int have_zones()
|
static int have_zones()
|
||||||
{
|
{
|
||||||
zone_t *z = (zone_t*) &radio_mem[OFFSET_ZONES];
|
int i;
|
||||||
|
|
||||||
return z->name[0] != 0 && z->name[0] != 0xffff;
|
for (i=0; i<NZONES; i++) {
|
||||||
|
zone_t *z = GET_ZONE(i);
|
||||||
|
if (z->name[0] != 0 && z->name[0] != 0xffff)
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int have_scanlists()
|
static int have_scanlists()
|
||||||
{
|
{
|
||||||
scanlist_t *sl = (scanlist_t*) &radio_mem[OFFSET_SCANL];
|
int i;
|
||||||
|
|
||||||
return sl->name[0] != 0 && sl->name[0] != 0xffff;
|
for (i=0; i<NSCANL; i++) {
|
||||||
|
scanlist_t *sl = GET_SCANLIST(i);
|
||||||
|
|
||||||
|
if (sl->name[0] != 0 && sl->name[0] != 0xffff)
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int have_contacts()
|
static int have_contacts()
|
||||||
{
|
{
|
||||||
contact_t *ct = (contact_t*) &radio_mem[OFFSET_CONTACTS];
|
int i;
|
||||||
|
|
||||||
return ct->name[0] != 0 && ct->name[0] != 0xffff;
|
for (i=0; i<NCONTACTS; i++) {
|
||||||
|
contact_t *ct = GET_CONTACT(i);
|
||||||
|
|
||||||
|
if (ct->name[0] != 0 && ct->name[0] != 0xffff)
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int have_grouplists()
|
static int have_grouplists()
|
||||||
{
|
{
|
||||||
grouplist_t *gl = (grouplist_t*) &radio_mem[OFFSET_GLISTS];
|
int i;
|
||||||
|
|
||||||
return gl->name[0] != 0 && gl->name[0] != 0xffff;
|
for (i=0; i<NGLISTS; i++) {
|
||||||
|
grouplist_t *gl = GET_GROUPLIST(i);
|
||||||
|
|
||||||
|
if (gl->name[0] != 0 && gl->name[0] != 0xffff)
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int have_messages()
|
static int have_messages()
|
||||||
{
|
{
|
||||||
uint16_t *msg = (uint16_t*) &radio_mem[OFFSET_MSG];
|
int i;
|
||||||
|
|
||||||
return msg[0] != 0 && msg[0] != 0xffff;
|
for (i=0; i<NMESSAGES; i++) {
|
||||||
|
uint16_t *msg = GET_MESSAGE(i);
|
||||||
|
|
||||||
|
if (msg[0] != 0 && msg[0] != 0xffff)
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -1094,8 +1133,8 @@ static void uv380_print_config(radio_device_t *radio, FILE *out, int verbose)
|
|||||||
}
|
}
|
||||||
fprintf(out, "Zone Name Channels\n");
|
fprintf(out, "Zone Name Channels\n");
|
||||||
for (i=0; i<NZONES; i++) {
|
for (i=0; i<NZONES; i++) {
|
||||||
zone_t *z = (zone_t*) &radio_mem[OFFSET_ZONES + i*64];
|
zone_t *z = GET_ZONE(i);
|
||||||
zone_ext_t *zext = (zone_ext_t*) &radio_mem[OFFSET_ZONEXT + i*224];
|
zone_ext_t *zext = GET_ZONEXT(i);
|
||||||
|
|
||||||
if (z->name[0] == 0 || z->name[0] == 0xffff) {
|
if (z->name[0] == 0 || z->name[0] == 0xffff) {
|
||||||
// Zone is disabled.
|
// Zone is disabled.
|
||||||
@ -1147,7 +1186,7 @@ static void uv380_print_config(radio_device_t *radio, FILE *out, int verbose)
|
|||||||
#endif
|
#endif
|
||||||
fprintf(out, "Channels\n");
|
fprintf(out, "Channels\n");
|
||||||
for (i=0; i<NSCANL; i++) {
|
for (i=0; i<NSCANL; i++) {
|
||||||
scanlist_t *sl = (scanlist_t*) &radio_mem[OFFSET_SCANL + i*104];
|
scanlist_t *sl = GET_SCANLIST(i);
|
||||||
|
|
||||||
if (sl->name[0] == 0 || sl->name[0] == 0xffff) {
|
if (sl->name[0] == 0 || sl->name[0] == 0xffff) {
|
||||||
// Scan list is disabled.
|
// Scan list is disabled.
|
||||||
@ -1206,7 +1245,7 @@ static void uv380_print_config(radio_device_t *radio, FILE *out, int verbose)
|
|||||||
}
|
}
|
||||||
fprintf(out, "Contact Name Type ID RxTone\n");
|
fprintf(out, "Contact Name Type ID RxTone\n");
|
||||||
for (i=0; i<NCONTACTS; i++) {
|
for (i=0; i<NCONTACTS; i++) {
|
||||||
contact_t *ct = (contact_t*) &radio_mem[OFFSET_CONTACTS + i*36];
|
contact_t *ct = GET_CONTACT(i);
|
||||||
|
|
||||||
if (ct->name[0] == 0 || ct->name[0] == 0xffff) {
|
if (ct->name[0] == 0 || ct->name[0] == 0xffff) {
|
||||||
// Contact is disabled
|
// Contact is disabled
|
||||||
@ -1234,7 +1273,7 @@ static void uv380_print_config(radio_device_t *radio, FILE *out, int verbose)
|
|||||||
}
|
}
|
||||||
fprintf(out, "Grouplist Name Contacts\n");
|
fprintf(out, "Grouplist Name Contacts\n");
|
||||||
for (i=0; i<NGLISTS; i++) {
|
for (i=0; i<NGLISTS; i++) {
|
||||||
grouplist_t *gl = (grouplist_t*) &radio_mem[OFFSET_GLISTS + i*96];
|
grouplist_t *gl = GET_GROUPLIST(i);
|
||||||
|
|
||||||
if (gl->name[0] == 0 || gl->name[0] == 0xffff) {
|
if (gl->name[0] == 0 || gl->name[0] == 0xffff) {
|
||||||
// Group list is disabled.
|
// Group list is disabled.
|
||||||
@ -1266,7 +1305,7 @@ static void uv380_print_config(radio_device_t *radio, FILE *out, int verbose)
|
|||||||
}
|
}
|
||||||
fprintf(out, "Message Text\n");
|
fprintf(out, "Message Text\n");
|
||||||
for (i=0; i<NMESSAGES; i++) {
|
for (i=0; i<NMESSAGES; i++) {
|
||||||
uint16_t *msg = (uint16_t*) &radio_mem[OFFSET_MSG + i*288];
|
uint16_t *msg = GET_MESSAGE(i);
|
||||||
|
|
||||||
if (msg[0] == 0 || msg[0] == 0xffff) {
|
if (msg[0] == 0 || msg[0] == 0xffff) {
|
||||||
// Message is disabled
|
// Message is disabled
|
||||||
@ -1385,7 +1424,7 @@ static void erase_contacts()
|
|||||||
//
|
//
|
||||||
static void uv380_parse_parameter(radio_device_t *radio, char *param, char *value)
|
static void uv380_parse_parameter(radio_device_t *radio, char *param, char *value)
|
||||||
{
|
{
|
||||||
general_settings_t *gs = (general_settings_t*) &radio_mem[OFFSET_SETTINGS];
|
general_settings_t *gs = GET_SETTINGS();
|
||||||
|
|
||||||
if (strcasecmp("Radio", param) == 0) {
|
if (strcasecmp("Radio", param) == 0) {
|
||||||
// Accept either MD-2017 or MD-UV380.
|
// Accept either MD-2017 or MD-UV380.
|
||||||
@ -2128,7 +2167,7 @@ static int uv380_parse_row(radio_device_t *radio, int table_id, int first_row, c
|
|||||||
//
|
//
|
||||||
static void uv380_update_timestamp(radio_device_t *radio)
|
static void uv380_update_timestamp(radio_device_t *radio)
|
||||||
{
|
{
|
||||||
unsigned char *timestamp = &radio_mem[OFFSET_TIMESTMP];
|
unsigned char *timestamp = GET_TIMESTAMP();
|
||||||
char p[16];
|
char p[16];
|
||||||
|
|
||||||
// Last Programmed Date
|
// Last Programmed Date
|
||||||
@ -2156,6 +2195,179 @@ static void uv380_update_timestamp(radio_device_t *radio)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Check that configuration is correct.
|
||||||
|
// Return 0 on error.
|
||||||
|
//
|
||||||
|
static int uv380_verify_config(radio_device_t *radio)
|
||||||
|
{
|
||||||
|
int i, k, nchannels = 0, nzones = 0, nscanlists = 0, ngrouplists = 0;
|
||||||
|
int ncontacts = 0, nerrors = 0;
|
||||||
|
|
||||||
|
// Channels: check references to scanlists, contacts and grouplists.
|
||||||
|
for (i=0; i<NCHAN; i++) {
|
||||||
|
channel_t *ch = GET_CHANNEL(i);
|
||||||
|
|
||||||
|
if (ch->name[0] == 0 || ch->name[0] == 0xffff)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
nchannels++;
|
||||||
|
if (ch->scan_list_index != 0) {
|
||||||
|
scanlist_t *sl = GET_SCANLIST(ch->scan_list_index - 1);
|
||||||
|
|
||||||
|
if (sl->name[0] == 0 || sl->name[0] == 0xffff) {
|
||||||
|
fprintf(stderr, "Channel %d '", i+1);
|
||||||
|
print_unicode(stderr, ch->name, 16, 0);
|
||||||
|
fprintf(stderr, "': scanlist %d not found.\n", ch->scan_list_index);
|
||||||
|
nerrors++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ch->contact_name_index != 0) {
|
||||||
|
contact_t *ct = GET_CONTACT(ch->contact_name_index - 1);
|
||||||
|
|
||||||
|
if (ct->name[0] == 0 || ct->name[0] == 0xffff) {
|
||||||
|
fprintf(stderr, "Channel %d '", i+1);
|
||||||
|
print_unicode(stderr, ch->name, 16, 0);
|
||||||
|
fprintf(stderr, "': contact %d not found.\n", ch->contact_name_index);
|
||||||
|
nerrors++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ch->group_list_index != 0) {
|
||||||
|
grouplist_t *gl = GET_GROUPLIST(ch->group_list_index - 1);
|
||||||
|
|
||||||
|
if (gl->name[0] == 0 || gl->name[0] == 0xffff) {
|
||||||
|
fprintf(stderr, "Channel %d '", i+1);
|
||||||
|
print_unicode(stderr, ch->name, 16, 0);
|
||||||
|
fprintf(stderr, "': grouplist %d not found.\n", ch->group_list_index);
|
||||||
|
nerrors++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Zones: check references to channels.
|
||||||
|
for (i=0; i<NZONES; i++) {
|
||||||
|
zone_t *z = GET_ZONE(i);
|
||||||
|
zone_ext_t *zext = GET_ZONEXT(i);
|
||||||
|
|
||||||
|
if (z->name[0] == 0 || z->name[0] == 0xffff)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
nzones++;
|
||||||
|
|
||||||
|
// Zone A
|
||||||
|
for (k=0; k<16; k++) {
|
||||||
|
int cnum = z->member_a[k];
|
||||||
|
|
||||||
|
if (cnum != 0) {
|
||||||
|
channel_t *ch = GET_CHANNEL(cnum - 1);
|
||||||
|
|
||||||
|
if (ch->name[0] == 0 || ch->name[0] == 0xffff) {
|
||||||
|
fprintf(stderr, "Zone %da '", i+1);
|
||||||
|
print_unicode(stderr, z->name, 16, 0);
|
||||||
|
fprintf(stderr, "': channel %d not found.\n", cnum);
|
||||||
|
nerrors++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (k=0; k<48; k++) {
|
||||||
|
int cnum = zext->ext_a[k];
|
||||||
|
|
||||||
|
if (cnum != 0) {
|
||||||
|
channel_t *ch = GET_CHANNEL(cnum - 1);
|
||||||
|
|
||||||
|
if (ch->name[0] == 0 || ch->name[0] == 0xffff) {
|
||||||
|
fprintf(stderr, "Zone %da '", i+1);
|
||||||
|
print_unicode(stderr, z->name, 16, 0);
|
||||||
|
fprintf(stderr, "': channel %d not found.\n", cnum);
|
||||||
|
nerrors++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Zone B
|
||||||
|
for (k=0; k<64; k++) {
|
||||||
|
int cnum = zext->member_b[k];
|
||||||
|
|
||||||
|
if (cnum != 0) {
|
||||||
|
channel_t *ch = GET_CHANNEL(cnum - 1);
|
||||||
|
|
||||||
|
if (ch->name[0] == 0 || ch->name[0] == 0xffff) {
|
||||||
|
fprintf(stderr, "Zone %db '", i+1);
|
||||||
|
print_unicode(stderr, z->name, 16, 0);
|
||||||
|
fprintf(stderr, "': channel %d not found.\n", cnum);
|
||||||
|
nerrors++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Scanlists: check references to channels.
|
||||||
|
for (i=0; i<NSCANL; i++) {
|
||||||
|
scanlist_t *sl = GET_SCANLIST(i);
|
||||||
|
|
||||||
|
if (sl->name[0] == 0 || sl->name[0] == 0xffff)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
nscanlists++;
|
||||||
|
for (k=0; k<31; k++) {
|
||||||
|
int cnum = sl->member[k];
|
||||||
|
|
||||||
|
if (cnum != 0) {
|
||||||
|
channel_t *ch = GET_CHANNEL(cnum - 1);
|
||||||
|
|
||||||
|
if (ch->name[0] == 0 || ch->name[0] == 0xffff) {
|
||||||
|
fprintf(stderr, "Scanlist %d '", i+1);
|
||||||
|
print_unicode(stderr, sl->name, 16, 0);
|
||||||
|
fprintf(stderr, "': channel %d not found.\n", cnum);
|
||||||
|
nerrors++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Grouplists: check references to contacts.
|
||||||
|
for (i=0; i<NGLISTS; i++) {
|
||||||
|
grouplist_t *gl = GET_GROUPLIST(i);
|
||||||
|
|
||||||
|
if (gl->name[0] == 0 || gl->name[0] == 0xffff)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
ngrouplists++;
|
||||||
|
for (k=0; k<32; k++) {
|
||||||
|
int cnum = gl->member[k];
|
||||||
|
|
||||||
|
if (cnum != 0) {
|
||||||
|
contact_t *ct = GET_CONTACT(cnum - 1);
|
||||||
|
|
||||||
|
if (ct->name[0] == 0 || ct->name[0] == 0xffff) {
|
||||||
|
fprintf(stderr, "Grouplist %d '", i+1);
|
||||||
|
print_unicode(stderr, gl->name, 16, 0);
|
||||||
|
fprintf(stderr, "': contact %d not found.\n", cnum);
|
||||||
|
nerrors++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Count contacts.
|
||||||
|
for (i=0; i<NCONTACTS; i++) {
|
||||||
|
contact_t *ct = GET_CONTACT(i);
|
||||||
|
|
||||||
|
if (ct->name[0] == 0 || ct->name[0] == 0xffff)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
ncontacts++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nerrors > 0) {
|
||||||
|
fprintf(stderr, "Total %d errors.\n", nerrors);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
fprintf(stderr, "Total %d channels, %d zones, %d scanlists, %d contacts, %d grouplists.\n",
|
||||||
|
nchannels, nzones, nscanlists, ncontacts, ngrouplists);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// TYT MD-UV380
|
// TYT MD-UV380
|
||||||
//
|
//
|
||||||
@ -2168,6 +2380,7 @@ radio_device_t radio_uv380 = {
|
|||||||
uv380_save_image,
|
uv380_save_image,
|
||||||
uv380_print_version,
|
uv380_print_version,
|
||||||
uv380_print_config,
|
uv380_print_config,
|
||||||
|
uv380_verify_config,
|
||||||
uv380_parse_parameter,
|
uv380_parse_parameter,
|
||||||
uv380_parse_header,
|
uv380_parse_header,
|
||||||
uv380_parse_row,
|
uv380_parse_row,
|
||||||
@ -2186,6 +2399,7 @@ radio_device_t radio_md2017 = {
|
|||||||
uv380_save_image,
|
uv380_save_image,
|
||||||
uv380_print_version,
|
uv380_print_version,
|
||||||
uv380_print_config,
|
uv380_print_config,
|
||||||
|
uv380_verify_config,
|
||||||
uv380_parse_parameter,
|
uv380_parse_parameter,
|
||||||
uv380_parse_header,
|
uv380_parse_header,
|
||||||
uv380_parse_row,
|
uv380_parse_row,
|
||||||
|
Loading…
Reference in New Issue
Block a user