Parse Name and ID.
Update timestamp.
This commit is contained in:
parent
7c8c7148a5
commit
6212fac6af
209
md380.c
209
md380.c
@ -42,9 +42,8 @@
|
||||
#define NMESSAGES 50
|
||||
|
||||
#define MEMSZ 0x40000
|
||||
#define OFFSET_VERSION 0x02001
|
||||
#define OFFSET_ID 0x02084
|
||||
#define OFFSET_NAME 0x020b0
|
||||
#define OFFSET_TIMESTMP 0x02001
|
||||
#define OFFSET_SETTINGS 0x02040
|
||||
#define OFFSET_MSG 0x02180
|
||||
#define OFFSET_CONTACTS 0x05f80
|
||||
#define OFFSET_GLISTS 0x0ec20
|
||||
@ -227,6 +226,86 @@ typedef struct {
|
||||
uint16_t member[31]; // Channels
|
||||
} scanlist_t;
|
||||
|
||||
//
|
||||
// General settings.
|
||||
// TODO: verify the general settings with CPS
|
||||
//
|
||||
typedef struct {
|
||||
|
||||
// Bytes 0-19
|
||||
uint16_t intro_screen_line1[10];
|
||||
|
||||
// Bytes 20-39
|
||||
uint16_t intro_screen_line2[10];
|
||||
|
||||
// Bytes 40-63
|
||||
uint8_t _unused40[24];
|
||||
|
||||
// Byte 64
|
||||
uint8_t _unused64_0 : 3,
|
||||
monitor_type : 1,
|
||||
_unused64_4 : 1,
|
||||
disable_all_leds : 1,
|
||||
_unused64_6 : 2;
|
||||
|
||||
// Byte 65
|
||||
uint8_t talk_permit_tone : 2,
|
||||
pw_and_lock_enable : 1,
|
||||
ch_free_indication_tone : 1,
|
||||
_unused65_4 : 1,
|
||||
disable_all_tones : 1,
|
||||
save_mode_receive : 1,
|
||||
save_preamble : 1;
|
||||
|
||||
// Byte 66
|
||||
uint8_t _unused66_0 : 2,
|
||||
keypad_tones : 1,
|
||||
intro_screen : 1,
|
||||
_unused66_4 : 4;
|
||||
|
||||
// Byte 67
|
||||
uint8_t _unused67;
|
||||
|
||||
// Bytes 68-71
|
||||
uint8_t radio_id[3];
|
||||
uint8_t _unused71;
|
||||
|
||||
// Bytes 72-84
|
||||
uint8_t tx_preamble_duration;
|
||||
uint8_t group_call_hang_time;
|
||||
uint8_t private_call_hang_time;
|
||||
uint8_t vox_sensitivity;
|
||||
uint8_t _unused76[2];
|
||||
uint8_t rx_low_battery_interval;
|
||||
uint8_t call_alert_tone_duration;
|
||||
uint8_t lone_worker_response_time;
|
||||
uint8_t lone_worker_reminder_time;
|
||||
uint8_t _unused82;
|
||||
uint8_t scan_digital_hang_time;
|
||||
uint8_t scan_analog_hang_time;
|
||||
|
||||
// Byte 85
|
||||
uint8_t _unused85_0 : 6,
|
||||
backlight_time : 2;
|
||||
|
||||
// Bytes 86-87
|
||||
uint8_t set_keypad_lock_time;
|
||||
uint8_t mode;
|
||||
|
||||
// Bytes 88-95
|
||||
uint32_t power_on_password;
|
||||
uint32_t radio_prog_password;
|
||||
|
||||
// Bytes 96-103
|
||||
uint8_t pc_prog_password[8];
|
||||
|
||||
// Bytes 104-111
|
||||
uint8_t _unused104[8];
|
||||
|
||||
// Bytes 112-143
|
||||
uint16_t radio_name[16];
|
||||
} general_settings_t;
|
||||
|
||||
static const char *POWER_NAME[] = { "Low", "High" };
|
||||
static const char *SQUELCH_NAME[] = { "Tight", "Normal" };
|
||||
static const char *BANDWIDTH[] = { "12.5", "20", "25" };
|
||||
@ -502,25 +581,27 @@ static void print_chanlist(FILE *out, uint16_t *unsorted, int nchan)
|
||||
|
||||
static void print_id(FILE *out)
|
||||
{
|
||||
const unsigned char *data = &radio_mem[OFFSET_VERSION];
|
||||
general_settings_t *gs = (general_settings_t*) &radio_mem[OFFSET_SETTINGS];
|
||||
unsigned id = gs->radio_id[0] | (gs->radio_id[1] << 8) | (gs->radio_id[2] << 16);
|
||||
unsigned char *timestamp = &radio_mem[OFFSET_TIMESTMP];
|
||||
|
||||
fprintf(out, "Name: ");
|
||||
if (radio_mem[OFFSET_NAME] != 0 && *(uint16_t*)&radio_mem[OFFSET_NAME] != 0xffff) {
|
||||
print_unicode(out, (uint16_t*) &radio_mem[OFFSET_NAME], 16, 0);
|
||||
if (gs->radio_name[0] != 0 && gs->radio_name[0] != 0xffff) {
|
||||
print_unicode(out, gs->radio_name, 16, 0);
|
||||
} else {
|
||||
fprintf(out, "-");
|
||||
}
|
||||
fprintf(out, "\nID: %u\n", *(uint32_t*) &radio_mem[OFFSET_ID] & 0xffffff);
|
||||
fprintf(out, "\nID: %u\n", id);
|
||||
|
||||
if (*data != 0xff) {
|
||||
if (*timestamp != 0xff) {
|
||||
fprintf(out, "Last Programmed Date: %d%d%d%d-%d%d-%d%d",
|
||||
data[0] >> 4, data[0] & 15, data[1] >> 4, data[1] & 15,
|
||||
data[2] >> 4, data[2] & 15, data[3] >> 4, data[3] & 15);
|
||||
timestamp[0] >> 4, timestamp[0] & 15, timestamp[1] >> 4, timestamp[1] & 15,
|
||||
timestamp[2] >> 4, timestamp[2] & 15, timestamp[3] >> 4, timestamp[3] & 15);
|
||||
fprintf(out, " %d%d:%d%d:%d%d\n",
|
||||
data[4] >> 4, data[4] & 15, data[5] >> 4, data[5] & 15,
|
||||
data[6] >> 4, data[6] & 15);
|
||||
timestamp[4] >> 4, timestamp[4] & 15, timestamp[5] >> 4, timestamp[5] & 15,
|
||||
timestamp[6] >> 4, timestamp[6] & 15);
|
||||
fprintf(out, "CPS Software Version: V%x%x.%x%x\n",
|
||||
data[7], data[8], data[9], data[10]);
|
||||
timestamp[7], timestamp[8], timestamp[9], timestamp[10]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1078,6 +1159,8 @@ static void md380_save_image(radio_device_t *radio, FILE *img)
|
||||
//
|
||||
static void md380_parse_parameter(radio_device_t *radio, char *param, char *value)
|
||||
{
|
||||
general_settings_t *gs = (general_settings_t*) &radio_mem[OFFSET_SETTINGS];
|
||||
|
||||
if (strcasecmp("Radio", param) == 0) {
|
||||
if (strcasecmp(radio->name, value) != 0) {
|
||||
fprintf(stderr, "Bad value for %s: %s\n", param, value);
|
||||
@ -1085,6 +1168,29 @@ static void md380_parse_parameter(radio_device_t *radio, char *param, char *valu
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (strcasecmp ("Name", param) == 0) {
|
||||
// Decode utf8 text to ucs2.
|
||||
utf8_decode(gs->radio_name, value, 16);
|
||||
return;
|
||||
}
|
||||
|
||||
if (strcasecmp ("ID", param) == 0) {
|
||||
uint32_t id = strtoul(value, 0, 0);
|
||||
gs->radio_id[0] = id;
|
||||
gs->radio_id[1] = id >> 8;
|
||||
gs->radio_id[2] = id >> 16;
|
||||
return;
|
||||
}
|
||||
|
||||
if (strcasecmp ("Last Programmed Date", param) == 0) {
|
||||
// Ignore.
|
||||
return;
|
||||
}
|
||||
if (strcasecmp ("CPS Software Version", param) == 0) {
|
||||
// Ignore.
|
||||
return;
|
||||
}
|
||||
fprintf(stderr, "Unknown parameter: %s = %s\n", param, value);
|
||||
exit(-1);
|
||||
}
|
||||
@ -1096,7 +1202,21 @@ static void md380_parse_parameter(radio_device_t *radio, char *param, char *valu
|
||||
//
|
||||
static int parse_digital_channel(int first_row, char *line)
|
||||
{
|
||||
//TODO: parse digital channel
|
||||
//TODO: parse digital channel Name
|
||||
//TODO: parse digital channel Receive
|
||||
//TODO: parse digital channel Transmit
|
||||
//TODO: parse digital channel Power
|
||||
//TODO: parse digital channel Scan
|
||||
//TODO: parse digital channel AS
|
||||
//TODO: parse digital channel Sq
|
||||
//TODO: parse digital channel TOT
|
||||
//TODO: parse digital channel RO
|
||||
//TODO: parse digital channel Admit
|
||||
//TODO: parse digital channel Color
|
||||
//TODO: parse digital channel Slot
|
||||
//TODO: parse digital channel InCall
|
||||
//TODO: parse digital channel RxGL
|
||||
//TODO: parse digital channel TxContact
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1108,7 +1228,19 @@ static int parse_digital_channel(int first_row, char *line)
|
||||
static int parse_analog_channel(int first_row, char *line)
|
||||
{
|
||||
#if 1
|
||||
//TODO: parse analog channel
|
||||
//TODO: parse analog channel Name
|
||||
//TODO: parse analog channel Receive
|
||||
//TODO: parse analog channel Transmit
|
||||
//TODO: parse analog channel Power
|
||||
//TODO: parse analog channel Scan
|
||||
//TODO: parse analog channel AS
|
||||
//TODO: parse analog channel Sq
|
||||
//TODO: parse analog channel TOT
|
||||
//TODO: parse analog channel RO
|
||||
//TODO: parse analog channel Admit
|
||||
//TODO: parse analog channel RxTone
|
||||
//TODO: parse analog channel TxTone
|
||||
//TODO: parse analog channel Width
|
||||
return 0;
|
||||
#else
|
||||
char num_str[256], name_str[256], rxfreq_str[256], offset_str[256];
|
||||
@ -1272,7 +1404,11 @@ static int parse_zones(int first_row, char *line)
|
||||
//
|
||||
static int parse_scanlist(int first_row, char *line)
|
||||
{
|
||||
//TODO: parse scanlist
|
||||
//TODO: parse scanlist Name
|
||||
//TODO: parse scanlist PCh1
|
||||
//TODO: parse scanlist PCh2
|
||||
//TODO: parse scanlist TxCh
|
||||
//TODO: parse scanlist Channels
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1282,7 +1418,10 @@ static int parse_scanlist(int first_row, char *line)
|
||||
//
|
||||
static int parse_contact(int first_row, char *line)
|
||||
{
|
||||
//TODO: parse contact
|
||||
//TODO: parse contact Name
|
||||
//TODO: parse contact Type
|
||||
//TODO: parse contact ID
|
||||
//TODO: parse contact RxTone
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1292,7 +1431,7 @@ static int parse_contact(int first_row, char *line)
|
||||
//
|
||||
static int parse_grouplist(int first_row, char *line)
|
||||
{
|
||||
//TODO: parse grouplist
|
||||
//TODO: parse grouplist Contacts
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1334,6 +1473,39 @@ static int md380_parse_row(radio_device_t *radio, int table_id, int first_row, c
|
||||
return 0;
|
||||
}
|
||||
|
||||
//
|
||||
// Update timestamp.
|
||||
//
|
||||
static void md380_update_timestamp(radio_device_t *radio)
|
||||
{
|
||||
unsigned char *timestamp = &radio_mem[OFFSET_TIMESTMP];
|
||||
char p[16];
|
||||
|
||||
// Last Programmed Date
|
||||
get_timestamp(p);
|
||||
timestamp[0] = ((p[0] & 0xf) << 4) | (p[1] & 0xf); // year upper
|
||||
timestamp[1] = ((p[2] & 0xf) << 4) | (p[3] & 0xf); // year lower
|
||||
timestamp[2] = ((p[4] & 0xf) << 4) | (p[5] & 0xf); // month
|
||||
timestamp[3] = ((p[6] & 0xf) << 4) | (p[7] & 0xf); // day
|
||||
timestamp[4] = ((p[8] & 0xf) << 4) | (p[9] & 0xf); // hour
|
||||
timestamp[5] = ((p[10] & 0xf) << 4) | (p[11] & 0xf); // minute
|
||||
timestamp[6] = ((p[12] & 0xf) << 4) | (p[13] & 0xf); // second
|
||||
|
||||
// CPS Software Version: Vdx.xx
|
||||
const char *dot = strchr(VERSION, '.');
|
||||
if (dot) {
|
||||
timestamp[7] = 0x0d; // D means Dmrconfig
|
||||
timestamp[8] = dot[-1] & 0x0f;
|
||||
if (dot[2] == '.') {
|
||||
timestamp[9] = 0;
|
||||
timestamp[10] = dot[1] & 0x0f;
|
||||
} else {
|
||||
timestamp[9] = dot[1] & 0x0f;
|
||||
timestamp[10] = dot[2] & 0x0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// TYT MD-380
|
||||
//
|
||||
@ -1349,4 +1521,5 @@ radio_device_t radio_md380 = {
|
||||
md380_parse_parameter,
|
||||
md380_parse_header,
|
||||
md380_parse_row,
|
||||
md380_update_timestamp,
|
||||
};
|
||||
|
1
radio.c
1
radio.c
@ -257,6 +257,7 @@ badline: fprintf(stderr, "Invalid line: '%s'\n", line);
|
||||
}
|
||||
}
|
||||
fclose(conf);
|
||||
device->update_timestamp(device);
|
||||
}
|
||||
|
||||
//
|
||||
|
1
radio.h
1
radio.h
@ -88,6 +88,7 @@ struct _radio_device_t {
|
||||
void (*parse_parameter)(radio_device_t *radio, char *param, char *value);
|
||||
int (*parse_header)(radio_device_t *radio, char *line);
|
||||
int (*parse_row)(radio_device_t *radio, int table_id, int first_row, char *line);
|
||||
void (*update_timestamp)(radio_device_t *radio);
|
||||
};
|
||||
|
||||
extern radio_device_t radio_md380; // TYT MD-380
|
||||
|
52
util.c
52
util.c
@ -30,6 +30,7 @@
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <time.h>
|
||||
#ifdef MINGW32
|
||||
# include <windows.h>
|
||||
#else
|
||||
@ -231,3 +232,54 @@ void print_unicode(FILE *out, const unsigned short *text, unsigned nchars, int f
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Get local time in format: YYYYMMDDhhmmss
|
||||
//
|
||||
void get_timestamp(char p[16])
|
||||
{
|
||||
time_t now = time(NULL);
|
||||
struct tm *local = localtime(&now);
|
||||
|
||||
if (! local) {
|
||||
perror("localtime");
|
||||
exit(-1);
|
||||
}
|
||||
if (!strftime(p, 16, "%Y%m%d%H%M%S", local)) {
|
||||
perror("strftime");
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Fetch Unicode symbol from UTF-8 string.
|
||||
// Advance string pointer.
|
||||
//
|
||||
int utf8_to_unicode(const char **p)
|
||||
{
|
||||
int c1, c2, c3;
|
||||
|
||||
c1 = (unsigned char) *(*p)++;
|
||||
if (! (c1 & 0x80))
|
||||
return c1;
|
||||
c2 = (unsigned char) *(*p)++;
|
||||
if (! (c1 & 0x20))
|
||||
return (c1 & 0x1f) << 6 | (c2 & 0x3f);
|
||||
c3 = (unsigned char) *(*p)++;
|
||||
return (c1 & 0x0f) << 12 | (c2 & 0x3f) << 6 | (c3 & 0x3f);
|
||||
}
|
||||
|
||||
//
|
||||
// Decode UTF-8 string into UCS-2 string, at most nsym characters.
|
||||
//
|
||||
void utf8_decode(unsigned short *dst, const char *src, unsigned nsym)
|
||||
{
|
||||
for (; nsym > 0; nsym--) {
|
||||
if ((*dst++ = utf8_to_unicode(&src)) == 0) {
|
||||
// Clear the remaining bytes.
|
||||
while (--nsym > 0)
|
||||
*dst++ = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
16
util.h
16
util.h
@ -129,3 +129,19 @@ void putc_utf8(unsigned short ch, FILE *out);
|
||||
// Print utf16 text as utf8.
|
||||
//
|
||||
void print_unicode(FILE *out, const unsigned short *text, unsigned nchars, int fill_flag);
|
||||
|
||||
//
|
||||
// Fetch Unicode symbol from UTF-8 string.
|
||||
// Advance string pointer.
|
||||
//
|
||||
int utf8_to_unicode(const char **p);
|
||||
|
||||
//
|
||||
// Decode UTF-8 string into UCS-2 string, at most nsym characters.
|
||||
//
|
||||
void utf8_decode(unsigned short *dst, const char *src, unsigned nsym);
|
||||
|
||||
//
|
||||
// Get local time in format: YYYYMMDDhhmmss
|
||||
//
|
||||
void get_timestamp(char p[16]);
|
||||
|
210
uv380.c
210
uv380.c
@ -42,9 +42,8 @@
|
||||
#define NMESSAGES 50
|
||||
|
||||
#define MEMSZ 0xd0000
|
||||
#define OFFSET_VERSION 0x02001
|
||||
#define OFFSET_ID 0x02084
|
||||
#define OFFSET_NAME 0x020b0
|
||||
#define OFFSET_TIMESTMP 0x02001
|
||||
#define OFFSET_SETTINGS 0x02040
|
||||
#define OFFSET_MSG 0x02180
|
||||
#define OFFSET_GLISTS 0x0ec20
|
||||
#define OFFSET_ZONES 0x149e0
|
||||
@ -245,6 +244,86 @@ typedef struct {
|
||||
uint16_t member[31]; // Channels
|
||||
} scanlist_t;
|
||||
|
||||
//
|
||||
// General settings.
|
||||
// TODO: verify the general settings with CPS
|
||||
//
|
||||
typedef struct {
|
||||
|
||||
// Bytes 0-19
|
||||
uint16_t intro_screen_line1[10];
|
||||
|
||||
// Bytes 20-39
|
||||
uint16_t intro_screen_line2[10];
|
||||
|
||||
// Bytes 40-63
|
||||
uint8_t _unused40[24];
|
||||
|
||||
// Byte 64
|
||||
uint8_t _unused64_0 : 3,
|
||||
monitor_type : 1,
|
||||
_unused64_4 : 1,
|
||||
disable_all_leds : 1,
|
||||
_unused64_6 : 2;
|
||||
|
||||
// Byte 65
|
||||
uint8_t talk_permit_tone : 2,
|
||||
pw_and_lock_enable : 1,
|
||||
ch_free_indication_tone : 1,
|
||||
_unused65_4 : 1,
|
||||
disable_all_tones : 1,
|
||||
save_mode_receive : 1,
|
||||
save_preamble : 1;
|
||||
|
||||
// Byte 66
|
||||
uint8_t _unused66_0 : 2,
|
||||
keypad_tones : 1,
|
||||
intro_screen : 1,
|
||||
_unused66_4 : 4;
|
||||
|
||||
// Byte 67
|
||||
uint8_t _unused67;
|
||||
|
||||
// Bytes 68-71
|
||||
uint8_t radio_id[3];
|
||||
uint8_t _unused71;
|
||||
|
||||
// Bytes 72-84
|
||||
uint8_t tx_preamble_duration;
|
||||
uint8_t group_call_hang_time;
|
||||
uint8_t private_call_hang_time;
|
||||
uint8_t vox_sensitivity;
|
||||
uint8_t _unused76[2];
|
||||
uint8_t rx_low_battery_interval;
|
||||
uint8_t call_alert_tone_duration;
|
||||
uint8_t lone_worker_response_time;
|
||||
uint8_t lone_worker_reminder_time;
|
||||
uint8_t _unused82;
|
||||
uint8_t scan_digital_hang_time;
|
||||
uint8_t scan_analog_hang_time;
|
||||
|
||||
// Byte 85
|
||||
uint8_t _unused85_0 : 6,
|
||||
backlight_time : 2;
|
||||
|
||||
// Bytes 86-87
|
||||
uint8_t set_keypad_lock_time;
|
||||
uint8_t mode;
|
||||
|
||||
// Bytes 88-95
|
||||
uint32_t power_on_password;
|
||||
uint32_t radio_prog_password;
|
||||
|
||||
// Bytes 96-103
|
||||
uint8_t pc_prog_password[8];
|
||||
|
||||
// Bytes 104-111
|
||||
uint8_t _unused104[8];
|
||||
|
||||
// Bytes 112-143
|
||||
uint16_t radio_name[16];
|
||||
} general_settings_t;
|
||||
|
||||
static const char *POWER_NAME[] = { "Low", "???", "Mid", "High" };
|
||||
static const char *BANDWIDTH[] = { "12.5", "20", "25" };
|
||||
static const char *CONTACT_TYPE[] = { "-", "Group", "Private", "All" };
|
||||
@ -518,25 +597,27 @@ static void print_chanlist(FILE *out, uint16_t *unsorted, int nchan)
|
||||
|
||||
static void print_id(FILE *out)
|
||||
{
|
||||
const unsigned char *data = &radio_mem[OFFSET_VERSION];
|
||||
general_settings_t *gs = (general_settings_t*) &radio_mem[OFFSET_SETTINGS];
|
||||
unsigned id = gs->radio_id[0] | (gs->radio_id[1] << 8) | (gs->radio_id[2] << 16);
|
||||
unsigned char *timestamp = &radio_mem[OFFSET_TIMESTMP];
|
||||
|
||||
fprintf(out, "Name: ");
|
||||
if (radio_mem[OFFSET_NAME] != 0 && *(uint16_t*)&radio_mem[OFFSET_NAME] != 0xffff) {
|
||||
print_unicode(out, (uint16_t*) &radio_mem[OFFSET_NAME], 16, 0);
|
||||
if (gs->radio_name[0] != 0 && gs->radio_name[0] != 0xffff) {
|
||||
print_unicode(out, gs->radio_name, 16, 0);
|
||||
} else {
|
||||
fprintf(out, "-");
|
||||
}
|
||||
fprintf(out, "\nID: %u\n", *(uint32_t*) &radio_mem[OFFSET_ID] & 0xffffff);
|
||||
fprintf(out, "\nID: %u\n", id);
|
||||
|
||||
if (*data != 0xff) {
|
||||
if (*timestamp != 0xff) {
|
||||
fprintf(out, "Last Programmed Date: %d%d%d%d-%d%d-%d%d",
|
||||
data[0] >> 4, data[0] & 15, data[1] >> 4, data[1] & 15,
|
||||
data[2] >> 4, data[2] & 15, data[3] >> 4, data[3] & 15);
|
||||
timestamp[0] >> 4, timestamp[0] & 15, timestamp[1] >> 4, timestamp[1] & 15,
|
||||
timestamp[2] >> 4, timestamp[2] & 15, timestamp[3] >> 4, timestamp[3] & 15);
|
||||
fprintf(out, " %d%d:%d%d:%d%d\n",
|
||||
data[4] >> 4, data[4] & 15, data[5] >> 4, data[5] & 15,
|
||||
data[6] >> 4, data[6] & 15);
|
||||
timestamp[4] >> 4, timestamp[4] & 15, timestamp[5] >> 4, timestamp[5] & 15,
|
||||
timestamp[6] >> 4, timestamp[6] & 15);
|
||||
fprintf(out, "CPS Software Version: V%x%x.%x%x\n",
|
||||
data[7], data[8], data[9], data[10]);
|
||||
timestamp[7], timestamp[8], timestamp[9], timestamp[10]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1119,6 +1200,8 @@ static void uv380_save_image(radio_device_t *radio, FILE *img)
|
||||
//
|
||||
static void uv380_parse_parameter(radio_device_t *radio, char *param, char *value)
|
||||
{
|
||||
general_settings_t *gs = (general_settings_t*) &radio_mem[OFFSET_SETTINGS];
|
||||
|
||||
if (strcasecmp("Radio", param) == 0) {
|
||||
// Accept either MD-2017 or MD-UV380.
|
||||
if (strcasecmp("TYT MD-2017", value) != 0 &&
|
||||
@ -1128,6 +1211,29 @@ static void uv380_parse_parameter(radio_device_t *radio, char *param, char *valu
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (strcasecmp ("Name", param) == 0) {
|
||||
// Decode utf8 text to ucs2.
|
||||
utf8_decode(gs->radio_name, value, 16);
|
||||
return;
|
||||
}
|
||||
|
||||
if (strcasecmp ("ID", param) == 0) {
|
||||
uint32_t id = strtoul(value, 0, 0);
|
||||
gs->radio_id[0] = id;
|
||||
gs->radio_id[1] = id >> 8;
|
||||
gs->radio_id[2] = id >> 16;
|
||||
return;
|
||||
}
|
||||
|
||||
if (strcasecmp ("Last Programmed Date", param) == 0) {
|
||||
// Ignore.
|
||||
return;
|
||||
}
|
||||
if (strcasecmp ("CPS Software Version", param) == 0) {
|
||||
// Ignore.
|
||||
return;
|
||||
}
|
||||
fprintf(stderr, "Unknown parameter: %s = %s\n", param, value);
|
||||
exit(-1);
|
||||
}
|
||||
@ -1139,7 +1245,21 @@ static void uv380_parse_parameter(radio_device_t *radio, char *param, char *valu
|
||||
//
|
||||
static int parse_digital_channel(int first_row, char *line)
|
||||
{
|
||||
//TODO: parse digital channel
|
||||
//TODO: parse digital channel Name
|
||||
//TODO: parse digital channel Receive
|
||||
//TODO: parse digital channel Transmit
|
||||
//TODO: parse digital channel Power
|
||||
//TODO: parse digital channel Scan
|
||||
//TODO: parse digital channel AS
|
||||
//TODO: parse digital channel Sq
|
||||
//TODO: parse digital channel TOT
|
||||
//TODO: parse digital channel RO
|
||||
//TODO: parse digital channel Admit
|
||||
//TODO: parse digital channel Color
|
||||
//TODO: parse digital channel Slot
|
||||
//TODO: parse digital channel InCall
|
||||
//TODO: parse digital channel RxGL
|
||||
//TODO: parse digital channel TxContact
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1151,7 +1271,19 @@ static int parse_digital_channel(int first_row, char *line)
|
||||
static int parse_analog_channel(int first_row, char *line)
|
||||
{
|
||||
#if 1
|
||||
//TODO: parse analog channel
|
||||
//TODO: parse analog channel Name
|
||||
//TODO: parse analog channel Receive
|
||||
//TODO: parse analog channel Transmit
|
||||
//TODO: parse analog channel Power
|
||||
//TODO: parse analog channel Scan
|
||||
//TODO: parse analog channel AS
|
||||
//TODO: parse analog channel Sq
|
||||
//TODO: parse analog channel TOT
|
||||
//TODO: parse analog channel RO
|
||||
//TODO: parse analog channel Admit
|
||||
//TODO: parse analog channel RxTone
|
||||
//TODO: parse analog channel TxTone
|
||||
//TODO: parse analog channel Width
|
||||
return 0;
|
||||
#else
|
||||
char num_str[256], name_str[256], rxfreq_str[256], offset_str[256];
|
||||
@ -1315,7 +1447,11 @@ static int parse_zones(int first_row, char *line)
|
||||
//
|
||||
static int parse_scanlist(int first_row, char *line)
|
||||
{
|
||||
//TODO: parse scanlist
|
||||
//TODO: parse scanlist Name
|
||||
//TODO: parse scanlist PCh1
|
||||
//TODO: parse scanlist PCh2
|
||||
//TODO: parse scanlist TxCh
|
||||
//TODO: parse scanlist Channels
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1325,7 +1461,10 @@ static int parse_scanlist(int first_row, char *line)
|
||||
//
|
||||
static int parse_contact(int first_row, char *line)
|
||||
{
|
||||
//TODO: parse contact
|
||||
//TODO: parse contact Name
|
||||
//TODO: parse contact Type
|
||||
//TODO: parse contact ID
|
||||
//TODO: parse contact RxTone
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1335,7 +1474,7 @@ static int parse_contact(int first_row, char *line)
|
||||
//
|
||||
static int parse_grouplist(int first_row, char *line)
|
||||
{
|
||||
//TODO: parse grouplist
|
||||
//TODO: parse grouplist Contacts
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1377,6 +1516,39 @@ static int uv380_parse_row(radio_device_t *radio, int table_id, int first_row, c
|
||||
return 0;
|
||||
}
|
||||
|
||||
//
|
||||
// Update timestamp.
|
||||
//
|
||||
static void uv380_update_timestamp(radio_device_t *radio)
|
||||
{
|
||||
unsigned char *timestamp = &radio_mem[OFFSET_TIMESTMP];
|
||||
char p[16];
|
||||
|
||||
// Last Programmed Date
|
||||
get_timestamp(p);
|
||||
timestamp[0] = ((p[0] & 0xf) << 4) | (p[1] & 0xf); // year upper
|
||||
timestamp[1] = ((p[2] & 0xf) << 4) | (p[3] & 0xf); // year lower
|
||||
timestamp[2] = ((p[4] & 0xf) << 4) | (p[5] & 0xf); // month
|
||||
timestamp[3] = ((p[6] & 0xf) << 4) | (p[7] & 0xf); // day
|
||||
timestamp[4] = ((p[8] & 0xf) << 4) | (p[9] & 0xf); // hour
|
||||
timestamp[5] = ((p[10] & 0xf) << 4) | (p[11] & 0xf); // minute
|
||||
timestamp[6] = ((p[12] & 0xf) << 4) | (p[13] & 0xf); // second
|
||||
|
||||
// CPS Software Version: Vdx.xx
|
||||
const char *dot = strchr(VERSION, '.');
|
||||
if (dot) {
|
||||
timestamp[7] = 0x0d; // D means Dmrconfig
|
||||
timestamp[8] = dot[-1] & 0x0f;
|
||||
if (dot[2] == '.') {
|
||||
timestamp[9] = 0;
|
||||
timestamp[10] = dot[1] & 0x0f;
|
||||
} else {
|
||||
timestamp[9] = dot[1] & 0x0f;
|
||||
timestamp[10] = dot[2] & 0x0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// TYT MD-UV380
|
||||
//
|
||||
@ -1392,6 +1564,7 @@ radio_device_t radio_uv380 = {
|
||||
uv380_parse_parameter,
|
||||
uv380_parse_header,
|
||||
uv380_parse_row,
|
||||
uv380_update_timestamp,
|
||||
};
|
||||
|
||||
//
|
||||
@ -1409,4 +1582,5 @@ radio_device_t radio_md2017 = {
|
||||
uv380_parse_parameter,
|
||||
uv380_parse_header,
|
||||
uv380_parse_row,
|
||||
uv380_update_timestamp,
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user