Recognize MD-2017 radio.

This commit is contained in:
Serge Vakulenko 2018-08-29 17:44:46 -07:00
parent 1fa524e2f9
commit 7c8c7148a5
4 changed files with 71 additions and 47 deletions

24
md380.c
View File

@ -243,7 +243,7 @@ static const char *SIGNALING_SYSTEM[] = { "-", "DTMF-1", "DTMF-2", "DTMF-3", "DT
// //
// Print a generic information about the device. // Print a generic information about the device.
// //
static void md380_print_version(FILE *out) static void md380_print_version(radio_device_t *radio, FILE *out)
{ {
// Nothing to print. // Nothing to print.
} }
@ -251,7 +251,7 @@ static void md380_print_version(FILE *out)
// //
// Read memory image from the device. // Read memory image from the device.
// //
static void md380_download() static void md380_download(radio_device_t *radio)
{ {
int bno; int bno;
@ -269,7 +269,7 @@ static void md380_download()
// //
// Write memory image to the device. // Write memory image to the device.
// //
static void md380_upload(int cont_flag) static void md380_upload(radio_device_t *radio, int cont_flag)
{ {
int bno; int bno;
@ -291,7 +291,7 @@ static void md380_upload(int cont_flag)
// //
// Check whether the memory image is compatible with this device. // Check whether the memory image is compatible with this device.
// //
static int md380_is_compatible() static int md380_is_compatible(radio_device_t *radio)
{ {
return 1; return 1;
} }
@ -504,7 +504,6 @@ static void print_id(FILE *out)
{ {
const unsigned char *data = &radio_mem[OFFSET_VERSION]; const unsigned char *data = &radio_mem[OFFSET_VERSION];
fprintf(out, "Radio: TYT MD-380\n");
fprintf(out, "Name: "); fprintf(out, "Name: ");
if (radio_mem[OFFSET_NAME] != 0 && *(uint16_t*)&radio_mem[OFFSET_NAME] != 0xffff) { if (radio_mem[OFFSET_NAME] != 0 && *(uint16_t*)&radio_mem[OFFSET_NAME] != 0xffff) {
print_unicode(out, (uint16_t*) &radio_mem[OFFSET_NAME], 16, 0); print_unicode(out, (uint16_t*) &radio_mem[OFFSET_NAME], 16, 0);
@ -828,10 +827,11 @@ static int have_messages()
// //
// Print full information about the device configuration. // Print full information about the device configuration.
// //
static void md380_print_config(FILE *out, int verbose) static void md380_print_config(radio_device_t *radio, FILE *out, int verbose)
{ {
int i; int i;
fprintf(out, "Radio: %s\n", radio->name);
print_id(out); print_id(out);
// //
@ -1033,7 +1033,7 @@ static void md380_print_config(FILE *out, int verbose)
// //
// Read memory image from the binary file. // Read memory image from the binary file.
// //
static void md380_read_image(FILE *img) static void md380_read_image(radio_device_t *radio, FILE *img)
{ {
struct stat st; struct stat st;
@ -1068,7 +1068,7 @@ static void md380_read_image(FILE *img)
// //
// Save memory image to the binary file. // Save memory image to the binary file.
// //
static void md380_save_image(FILE *img) static void md380_save_image(radio_device_t *radio, FILE *img)
{ {
fwrite(&radio_mem[0], 1, MEMSZ, img); fwrite(&radio_mem[0], 1, MEMSZ, img);
} }
@ -1076,10 +1076,10 @@ static void md380_save_image(FILE *img)
// //
// Parse the scalar parameter. // Parse the scalar parameter.
// //
static void md380_parse_parameter(char *param, char *value) static void md380_parse_parameter(radio_device_t *radio, char *param, char *value)
{ {
if (strcasecmp("Radio", param) == 0) { if (strcasecmp("Radio", param) == 0) {
if (strcasecmp("TYT MD-380", value) != 0) { if (strcasecmp(radio->name, value) != 0) {
fprintf(stderr, "Bad value for %s: %s\n", param, value); fprintf(stderr, "Bad value for %s: %s\n", param, value);
exit(-1); exit(-1);
} }
@ -1300,7 +1300,7 @@ static int parse_grouplist(int first_row, char *line)
// Parse table header. // Parse table header.
// Return table id, or 0 in case of error. // Return table id, or 0 in case of error.
// //
static int md380_parse_header(char *line) static int md380_parse_header(radio_device_t *radio, char *line)
{ {
if (strncasecmp(line, "Digital", 7) == 0) if (strncasecmp(line, "Digital", 7) == 0)
return 'D'; return 'D';
@ -1321,7 +1321,7 @@ static int md380_parse_header(char *line)
// Parse one line of table data. // Parse one line of table data.
// Return 0 on failure. // Return 0 on failure.
// //
static int md380_parse_row(int table_id, int first_row, char *line) static int md380_parse_row(radio_device_t *radio, int table_id, int first_row, char *line)
{ {
switch (table_id) { switch (table_id) {
case 'D': return parse_digital_channel(first_row, line); case 'D': return parse_digital_channel(first_row, line);

23
radio.c
View File

@ -59,7 +59,7 @@ void radio_disconnect()
// //
void radio_print_version(FILE *out) void radio_print_version(FILE *out)
{ {
device->print_version(out); device->print_version(device, out);
} }
// //
@ -74,6 +74,9 @@ void radio_connect()
if (strcasecmp(ident, "MD380") == 0) { if (strcasecmp(ident, "MD380") == 0) {
device = &radio_md380; device = &radio_md380;
} else } else
if (strcasecmp(ident, "MD-2017") == 0) {
device = &radio_md2017;
} else
if (strcasecmp(ident, "MD-UV380") == 0) { if (strcasecmp(ident, "MD-UV380") == 0) {
device = &radio_uv380; device = &radio_uv380;
} else { } else {
@ -92,7 +95,7 @@ void radio_download()
if (! serial_verbose) if (! serial_verbose)
fprintf(stderr, "Read device: "); fprintf(stderr, "Read device: ");
device->download(); device->download(device);
if (! serial_verbose) if (! serial_verbose)
fprintf(stderr, " done.\n"); fprintf(stderr, " done.\n");
@ -104,7 +107,7 @@ void radio_download()
void radio_upload(int cont_flag) void radio_upload(int cont_flag)
{ {
// Check for compatibility. // Check for compatibility.
if (! device->is_compatible()) { if (! device->is_compatible(device)) {
fprintf(stderr, "Incompatible image - cannot upload.\n"); fprintf(stderr, "Incompatible image - cannot upload.\n");
exit(-1); exit(-1);
} }
@ -113,7 +116,7 @@ void radio_upload(int cont_flag)
fprintf(stderr, "Write device: "); fprintf(stderr, "Write device: ");
fflush(stderr); fflush(stderr);
} }
device->upload(cont_flag); device->upload(device, cont_flag);
if (! serial_verbose) if (! serial_verbose)
fprintf(stderr, " done.\n"); fprintf(stderr, " done.\n");
@ -154,7 +157,7 @@ void radio_read_image(char *filename)
perror(filename); perror(filename);
exit(-1); exit(-1);
} }
device->read_image(img); device->read_image(device, img);
fclose(img); fclose(img);
} }
@ -171,7 +174,7 @@ void radio_save_image(char *filename)
perror(filename); perror(filename);
exit(-1); exit(-1);
} }
device->save_image(img); device->save_image(device, img);
fclose(img); fclose(img);
} }
@ -217,7 +220,7 @@ void radio_parse_config(char *filename)
v = strchr(p, ':'); v = strchr(p, ':');
if (! v) { if (! v) {
// Table header: get table type. // Table header: get table type.
table_id = device->parse_header(p); table_id = device->parse_header(device, p);
if (! table_id) { if (! table_id) {
badline: fprintf(stderr, "Invalid line: '%s'\n", line); badline: fprintf(stderr, "Invalid line: '%s'\n", line);
exit(-1); exit(-1);
@ -233,7 +236,7 @@ badline: fprintf(stderr, "Invalid line: '%s'\n", line);
while (*v == ' ' || *v == '\t') while (*v == ' ' || *v == '\t')
v++; v++;
device->parse_parameter(p, v); device->parse_parameter(device, p, v);
} else { } else {
// Table row or comment. // Table row or comment.
@ -247,7 +250,7 @@ badline: fprintf(stderr, "Invalid line: '%s'\n", line);
goto badline; goto badline;
} }
if (! device->parse_row(table_id, ! table_dirty, p)) { if (! device->parse_row(device, table_id, ! table_dirty, p)) {
goto badline; goto badline;
} }
table_dirty = 1; table_dirty = 1;
@ -275,5 +278,5 @@ void radio_print_config(FILE *out, int verbose)
fprintf(out, "# Version %s, %s\n", version, copyright); fprintf(out, "# Version %s, %s\n", version, copyright);
fprintf(out, "#\n"); fprintf(out, "#\n");
} }
device->print_config(out, verbose); device->print_config(device, out, verbose);
} }

26
radio.h
View File

@ -75,21 +75,23 @@ void radio_parse_config(char *filename);
// //
// Device-dependent interface to the radio. // Device-dependent interface to the radio.
// //
typedef struct { typedef struct _radio_device_t radio_device_t;
struct _radio_device_t {
const char *name; const char *name;
void (*download)(void); void (*download)(radio_device_t *radio);
void (*upload)(int cont_flag); void (*upload)(radio_device_t *radio, int cont_flag);
int (*is_compatible)(void); int (*is_compatible)(radio_device_t *radio);
void (*read_image)(FILE *img); void (*read_image)(radio_device_t *radio, FILE *img);
void (*save_image)(FILE *img); void (*save_image)(radio_device_t *radio, FILE *img);
void (*print_version)(FILE *out); void (*print_version)(radio_device_t *radio, FILE *out);
void (*print_config)(FILE *out, int verbose); void (*print_config)(radio_device_t *radio, FILE *out, int verbose);
void (*parse_parameter)(char *param, char *value); void (*parse_parameter)(radio_device_t *radio, char *param, char *value);
int (*parse_header)(char *line); int (*parse_header)(radio_device_t *radio, char *line);
int (*parse_row)(int table_id, int first_row, char *line); int (*parse_row)(radio_device_t *radio, int table_id, int first_row, char *line);
} radio_device_t; };
extern radio_device_t radio_md380; // TYT MD-380 extern radio_device_t radio_md380; // TYT MD-380
extern radio_device_t radio_md2017; // TYT MD-2017
extern radio_device_t radio_uv380; // TYT MD-UV380 extern radio_device_t radio_uv380; // TYT MD-UV380
// //

45
uv380.c
View File

@ -1,5 +1,5 @@
/* /*
* Interface to TYT MD-UV380. * Interface to TYT MD-UV380 and MD-2017.
* *
* Copyright (C) 2018 Serge Vakulenko, KK6ABQ * Copyright (C) 2018 Serge Vakulenko, KK6ABQ
* *
@ -261,7 +261,7 @@ static const char *TURNOFF_FREQ[] = { "259.2", "55.2", "???", "-" };
// //
// Print a generic information about the device. // Print a generic information about the device.
// //
static void uv380_print_version(FILE *out) static void uv380_print_version(radio_device_t *radio, FILE *out)
{ {
// Nothing to print. // Nothing to print.
} }
@ -269,7 +269,7 @@ static void uv380_print_version(FILE *out)
// //
// Read memory image from the device. // Read memory image from the device.
// //
static void uv380_download() static void uv380_download(radio_device_t *radio)
{ {
int bno; int bno;
@ -287,7 +287,7 @@ static void uv380_download()
// //
// Write memory image to the device. // Write memory image to the device.
// //
static void uv380_upload(int cont_flag) static void uv380_upload(radio_device_t *radio, int cont_flag)
{ {
int bno; int bno;
@ -307,7 +307,7 @@ static void uv380_upload(int cont_flag)
// //
// Check whether the memory image is compatible with this device. // Check whether the memory image is compatible with this device.
// //
static int uv380_is_compatible() static int uv380_is_compatible(radio_device_t *radio)
{ {
return 1; return 1;
} }
@ -520,7 +520,6 @@ static void print_id(FILE *out)
{ {
const unsigned char *data = &radio_mem[OFFSET_VERSION]; const unsigned char *data = &radio_mem[OFFSET_VERSION];
fprintf(out, "Radio: TYT MD-UV380\n");
fprintf(out, "Name: "); fprintf(out, "Name: ");
if (radio_mem[OFFSET_NAME] != 0 && *(uint16_t*)&radio_mem[OFFSET_NAME] != 0xffff) { if (radio_mem[OFFSET_NAME] != 0 && *(uint16_t*)&radio_mem[OFFSET_NAME] != 0xffff) {
print_unicode(out, (uint16_t*) &radio_mem[OFFSET_NAME], 16, 0); print_unicode(out, (uint16_t*) &radio_mem[OFFSET_NAME], 16, 0);
@ -851,10 +850,11 @@ static int have_messages()
// //
// Print full information about the device configuration. // Print full information about the device configuration.
// //
static void uv380_print_config(FILE *out, int verbose) static void uv380_print_config(radio_device_t *radio, FILE *out, int verbose)
{ {
int i; int i;
fprintf(out, "Radio: %s\n", radio->name);
print_id(out); print_id(out);
// //
@ -1069,7 +1069,7 @@ static void uv380_print_config(FILE *out, int verbose)
// //
// Read memory image from the binary file. // Read memory image from the binary file.
// //
static void uv380_read_image(FILE *img) static void uv380_read_image(radio_device_t *radio, FILE *img)
{ {
struct stat st; struct stat st;
@ -1109,7 +1109,7 @@ static void uv380_read_image(FILE *img)
// //
// Save memory image to the binary file. // Save memory image to the binary file.
// //
static void uv380_save_image(FILE *img) static void uv380_save_image(radio_device_t *radio, FILE *img)
{ {
fwrite(&radio_mem[0], 1, MEMSZ, img); fwrite(&radio_mem[0], 1, MEMSZ, img);
} }
@ -1117,10 +1117,12 @@ static void uv380_save_image(FILE *img)
// //
// Parse the scalar parameter. // Parse the scalar parameter.
// //
static void uv380_parse_parameter(char *param, char *value) static void uv380_parse_parameter(radio_device_t *radio, char *param, char *value)
{ {
if (strcasecmp("Radio", param) == 0) { if (strcasecmp("Radio", param) == 0) {
if (strcasecmp("TYT MD-UV380", value) != 0) { // Accept either MD-2017 or MD-UV380.
if (strcasecmp("TYT MD-2017", value) != 0 &&
strcasecmp("TYT MD-UV380", value) != 0) {
fprintf(stderr, "Bad value for %s: %s\n", param, value); fprintf(stderr, "Bad value for %s: %s\n", param, value);
exit(-1); exit(-1);
} }
@ -1341,7 +1343,7 @@ static int parse_grouplist(int first_row, char *line)
// Parse table header. // Parse table header.
// Return table id, or 0 in case of error. // Return table id, or 0 in case of error.
// //
static int uv380_parse_header(char *line) static int uv380_parse_header(radio_device_t *radio, char *line)
{ {
if (strncasecmp(line, "Digital", 7) == 0) if (strncasecmp(line, "Digital", 7) == 0)
return 'D'; return 'D';
@ -1362,7 +1364,7 @@ static int uv380_parse_header(char *line)
// Parse one line of table data. // Parse one line of table data.
// Return 0 on failure. // Return 0 on failure.
// //
static int uv380_parse_row(int table_id, int first_row, char *line) static int uv380_parse_row(radio_device_t *radio, int table_id, int first_row, char *line)
{ {
switch (table_id) { switch (table_id) {
case 'D': return parse_digital_channel(first_row, line); case 'D': return parse_digital_channel(first_row, line);
@ -1391,3 +1393,20 @@ radio_device_t radio_uv380 = {
uv380_parse_header, uv380_parse_header,
uv380_parse_row, uv380_parse_row,
}; };
//
// TYT MD-2017
//
radio_device_t radio_md2017 = {
"TYT MD-2017",
uv380_download,
uv380_upload,
uv380_is_compatible,
uv380_read_image,
uv380_save_image,
uv380_print_version,
uv380_print_config,
uv380_parse_parameter,
uv380_parse_header,
uv380_parse_row,
};