RD-5R: implement valid bits for scanlists.

This commit is contained in:
Serge Vakulenko 2018-09-20 20:26:40 -07:00
parent 88f968787e
commit 77459dedd8

178
rd5r.c
View File

@ -51,20 +51,19 @@
#define OFFSET_INTRO 0x07540 #define OFFSET_INTRO 0x07540
#define OFFSET_ZONETAB 0x08010 #define OFFSET_ZONETAB 0x08010
#define OFFSET_BANK_1 0x0b1b0 // Channels 129-1024 #define OFFSET_BANK_1 0x0b1b0 // Channels 129-1024
#define OFFSET_SCANL 0x17720 #define OFFSET_SCANTAB 0x17620
#define OFFSET_GLISTS 0x1d6a0 #define OFFSET_GLISTS 0x1d6a0
#define GET_TIMESTAMP() (&radio_mem[OFFSET_TIMESTMP]) #define GET_TIMESTAMP() (&radio_mem[OFFSET_TIMESTMP])
#define GET_SETTINGS() ((general_settings_t*) &radio_mem[OFFSET_SETTINGS]) #define GET_SETTINGS() ((general_settings_t*) &radio_mem[OFFSET_SETTINGS])
#define GET_INTRO() ((intro_text_t*) &radio_mem[OFFSET_INTRO]) #define GET_INTRO() ((intro_text_t*) &radio_mem[OFFSET_INTRO])
#define GET_ZONETAB() ((zonetab_t*) &radio_mem[OFFSET_ZONETAB]) #define GET_ZONETAB() ((zonetab_t*) &radio_mem[OFFSET_ZONETAB])
#define GET_SCANLIST(i) ((scanlist_t*) &radio_mem[OFFSET_SCANL + (i)*88]) #define GET_SCANTAB(i) ((scantab_t*) &radio_mem[OFFSET_SCANTAB])
#define GET_CONTACT(i) ((contact_t*) &radio_mem[OFFSET_CONTACTS + (i)*24]) #define GET_CONTACT(i) ((contact_t*) &radio_mem[OFFSET_CONTACTS + (i)*24])
#define GET_GROUPLIST(i) ((grouplist_t*) &radio_mem[OFFSET_GLISTS + (i)*48]) #define GET_GROUPLIST(i) ((grouplist_t*) &radio_mem[OFFSET_GLISTS + (i)*48])
#define GET_MSGTAB() ((msgtab_t*) &radio_mem[OFFSET_MSGTAB]) #define GET_MSGTAB() ((msgtab_t*) &radio_mem[OFFSET_MSGTAB])
#define VALID_TEXT(txt) (*(txt) != 0 && *(txt) != 0xff) #define VALID_TEXT(txt) (*(txt) != 0 && *(txt) != 0xff)
#define VALID_SCANLIST(sl) VALID_TEXT((sl)->name)
#define VALID_GROUPLIST(gl) VALID_TEXT((gl)->name) #define VALID_GROUPLIST(gl) VALID_TEXT((gl)->name)
#define VALID_CONTACT(ct) VALID_TEXT((ct)->name) #define VALID_CONTACT(ct) VALID_TEXT((ct)->name)
@ -267,6 +266,14 @@ typedef struct {
} scanlist_t; } scanlist_t;
//
// Table of scanlists.
//
typedef struct {
uint8_t valid[256]; // byte=1 when scanlist valid
scanlist_t scanlist[NSCANL];
} scantab_t;
// //
// General settings. // General settings.
// //
@ -436,6 +443,20 @@ static void setup_zone(int index, const char *name)
zt->bitmap[index / 8] |= 1 << (index & 7); zt->bitmap[index / 8] |= 1 << (index & 7);
} }
//
// Get zone by index.
// Return 0 when zone is disabled.
//
static zone_t *get_zone(int index)
{
zonetab_t *zt = GET_ZONETAB();
if (zt->bitmap[index / 8] >> (index & 7) & 1)
return &zt->zone[index];
else
return 0;
}
// //
// Add channel to a zone. // Add channel to a zone.
// Return 0 on failure. // Return 0 on failure.
@ -469,47 +490,55 @@ static void erase_zone(int index)
zt->bitmap[index / 8] &= ~(1 << (index & 7)); zt->bitmap[index / 8] &= ~(1 << (index & 7));
} }
//
// Is zone valid?
//
static int valid_zone(int i)
{
zonetab_t *zt = GET_ZONETAB();
return (zt->bitmap[i / 8] >> (i & 7)) & 1;
}
// //
// Set parameters for a given scan list. // Set parameters for a given scan list.
// //
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 = GET_SCANLIST(index); scantab_t *st = GET_SCANTAB();
scanlist_t *sl = &st->scanlist[index];
int len = strlen(name); int len = strlen(name);
// Bytes 0-31 memset(sl, 0, 88);
memset(sl->name, 0xff, sizeof(sl->name)); memset(sl->name, 0xff, sizeof(sl->name));
memcpy(sl->name, name, len < sizeof(sl->name) ? len : sizeof(sl->name)); memcpy(sl->name, name, len < sizeof(sl->name) ? len : sizeof(sl->name));
// Bytes 32-37
sl->priority_ch1 = prio1; sl->priority_ch1 = prio1;
sl->priority_ch2 = prio2; sl->priority_ch2 = prio2;
sl->tx_designated_ch = txchan; sl->tx_designated_ch = txchan;
sl->talkback = 1;
sl->channel_mark = 1;
sl->pl_type = PL_PRI_NONPRI;
sl->sign_hold_time = 1000 / 25; // 1 sec
sl->prio_sample_time = 2000 / 250; // 2 sec
// Set valid bit.
st->valid[index] = 1;
} }
static void erase_scanlist(int index) static void erase_scanlist(int index)
{ {
scanlist_t *sl = GET_SCANLIST(index); scantab_t *st = GET_SCANTAB();
memset(sl, 0, 88); memset(&st->scanlist[index], 0xff, sizeof(scanlist_t));
memset(sl->name, 0xff, sizeof(sl->name));
sl->talkback = 1; // Clear valid bit.
sl->channel_mark = 1; st->valid[index] = 0;
sl->pl_type = PL_PRI_NONPRI; }
sl->sign_hold_time = 0xff;
sl->prio_sample_time = 2000 / 250; // 2 sec //
// Get scanlist by index.
// Return 0 when scanlist is disabled.
//
static scanlist_t *get_scanlist(int index)
{
scantab_t *st = GET_SCANTAB();
if (st->valid[index])
return &st->scanlist[index];
else
return 0;
} }
// //
@ -518,9 +547,12 @@ static void erase_scanlist(int index)
// //
static int scanlist_append(int index, int cnum) static int scanlist_append(int index, int cnum)
{ {
scanlist_t *sl = GET_SCANLIST(index); scanlist_t *sl = get_scanlist(index);
int i; int i;
if (!sl)
return 0;
// First element is always Selected. // First element is always Selected.
if (sl->member[0] == 0) if (sl->member[0] == 0)
sl->member[0] = CHAN_SELECTED; sl->member[0] = CHAN_SELECTED;
@ -646,17 +678,10 @@ static channel_t *get_channel(int i)
{ {
bank_t *b = get_bank(i >> 7); bank_t *b = get_bank(i >> 7);
return &b->chan[i % 128]; if ((b->bitmap[i % 128 / 8] >> (i & 7)) & 1)
} return &b->chan[i % 128];
else
// return 0;
// Is channel valid?
//
static int valid_channel(int i)
{
bank_t *b = get_bank(i >> 7);
return (b->bitmap[i % 128 / 8] >> (i & 7)) & 1;
} }
// //
@ -667,7 +692,8 @@ static void setup_channel(int i, int mode, char *name, double rx_mhz, double tx_
int admit, int colorcode, int timeslot, int grouplist, int contact, int admit, int colorcode, int timeslot, int grouplist, int contact,
int rxtone, int txtone, int width) int rxtone, int txtone, int width)
{ {
channel_t *ch = get_channel(i); bank_t *b = get_bank(i >> 7);
channel_t *ch = &b->chan[i % 128];
ch->channel_mode = mode; ch->channel_mode = mode;
ch->bandwidth = width; ch->bandwidth = width;
@ -692,7 +718,6 @@ static void setup_channel(int i, int mode, char *name, double rx_mhz, double tx_
memcpy(ch->name, name, (len < sizeof(ch->name)) ? len : sizeof(ch->name)); memcpy(ch->name, name, (len < sizeof(ch->name)) ? len : sizeof(ch->name));
// Set valid bit. // Set valid bit.
bank_t *b = get_bank(i >> 7);
b->bitmap[i % 128 / 8] |= 1 << (i & 7); b->bitmap[i % 128 / 8] |= 1 << (i & 7);
} }
@ -701,7 +726,8 @@ 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 = get_channel(i); bank_t *b = get_bank(i >> 7);
channel_t *ch = &b->chan[i % 128];
// Bytes 0-15 // Bytes 0-15
memset(ch->name, 0xff, sizeof(ch->name)); memset(ch->name, 0xff, sizeof(ch->name));
@ -784,7 +810,6 @@ static void erase_channel(int i)
ch->squelch = 5; ch->squelch = 5;
// Clear valid bit. // Clear valid bit.
bank_t *b = get_bank(i >> 7);
b->bitmap[i % 128 / 8] &= ~(1 << (i & 7)); b->bitmap[i % 128 / 8] &= ~(1 << (i & 7));
} }
@ -867,12 +892,10 @@ static int have_channels(int mode)
int i; int i;
for (i=0; i<NCHAN; i++) { for (i=0; i<NCHAN; i++) {
if (valid_channel(i)) { channel_t *ch = get_channel(i);
channel_t *ch = get_channel(i);
if (ch->channel_mode == mode) if (ch && ch->channel_mode == mode)
return 1; return 1;
}
} }
return 0; return 0;
} }
@ -958,11 +981,11 @@ 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++) {
if (!valid_channel(i)) { channel_t *ch = get_channel(i);
if (!ch) {
continue; continue;
} }
channel_t *ch = get_channel(i);
if (ch->channel_mode != MODE_DIGITAL) { if (ch->channel_mode != MODE_DIGITAL) {
// Select digital channels // Select digital channels
continue; continue;
@ -1053,11 +1076,11 @@ 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++) {
if (!valid_channel(i)) { channel_t *ch = get_channel(i);
if (!ch) {
continue; continue;
} }
channel_t *ch = get_channel(i);
if (ch->channel_mode != MODE_ANALOG) { if (ch->channel_mode != MODE_ANALOG) {
// Select analog channels // Select analog channels
continue; continue;
@ -1102,9 +1125,14 @@ static int have_zones()
static int have_scanlists() static int have_scanlists()
{ {
scanlist_t *sl = GET_SCANLIST(0); scantab_t *st = GET_SCANTAB();
int i;
return VALID_SCANLIST(sl); for (i=0; i<NSCANL; i++) {
if (st->valid[i])
return 1;
}
return 0;
} }
static int have_contacts() static int have_contacts()
@ -1155,8 +1183,6 @@ static void rd5r_print_config(radio_device_t *radio, FILE *out, int verbose)
// Zones. // Zones.
// //
if (have_zones()) { if (have_zones()) {
zonetab_t *zt = GET_ZONETAB();
fprintf(out, "\n"); fprintf(out, "\n");
if (verbose) { if (verbose) {
fprintf(out, "# Table of channel zones.\n"); fprintf(out, "# Table of channel zones.\n");
@ -1167,12 +1193,12 @@ static void rd5r_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++) {
if (!valid_zone(i)) { zone_t *z = get_zone(i);
if (!z) {
// Zone is disabled. // Zone is disabled.
continue; continue;
} }
zone_t *z = &zt->zone[i];
fprintf(out, "%4d ", i + 1); fprintf(out, "%4d ", i + 1);
print_ascii(out, z->name, 16, 1); print_ascii(out, z->name, 16, 1);
fprintf(out, " "); fprintf(out, " ");
@ -1206,13 +1232,12 @@ static void rd5r_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 = GET_SCANLIST(i); scanlist_t *sl = get_scanlist(i);
if (!VALID_SCANLIST(sl)) { if (!sl) {
// Scan list is disabled. // Scan list is disabled.
break; continue;
} }
fprintf(out, "%5d ", i + 1); fprintf(out, "%5d ", i + 1);
print_ascii(out, sl->name, 15, 1); print_ascii(out, sl->name, 15, 1);
if (sl->priority_ch1 == 0) { if (sl->priority_ch1 == 0) {
@ -2159,19 +2184,18 @@ static int rd5r_verify_config(radio_device_t *radio)
{ {
int i, k, nchannels = 0, nzones = 0, nscanlists = 0, ngrouplists = 0; int i, k, nchannels = 0, nzones = 0, nscanlists = 0, ngrouplists = 0;
int ncontacts = 0, nerrors = 0; int ncontacts = 0, nerrors = 0;
zonetab_t *zt = GET_ZONETAB();
// Channels: check references to scanlists, contacts and grouplists. // Channels: check references to scanlists, contacts and grouplists.
for (i=0; i<NCHAN; i++) { for (i=0; i<NCHAN; i++) {
if (!valid_channel(i))
continue;
channel_t *ch = get_channel(i); channel_t *ch = get_channel(i);
if (!ch)
continue;
nchannels++; nchannels++;
if (ch->scan_list_index != 0) { if (ch->scan_list_index != 0) {
scanlist_t *sl = GET_SCANLIST(ch->scan_list_index - 1); scanlist_t *sl = get_scanlist(ch->scan_list_index - 1);
if (!VALID_SCANLIST(sl)) { if (!sl) {
fprintf(stderr, "Channel %d '", i+1); fprintf(stderr, "Channel %d '", i+1);
print_ascii(stderr, ch->name, 16, 0); print_ascii(stderr, ch->name, 16, 0);
fprintf(stderr, "': scanlist %d not found.\n", ch->scan_list_index); fprintf(stderr, "': scanlist %d not found.\n", ch->scan_list_index);
@ -2202,16 +2226,16 @@ static int rd5r_verify_config(radio_device_t *radio)
// Zones: check references to channels. // Zones: check references to channels.
for (i=0; i<NZONES; i++) { for (i=0; i<NZONES; i++) {
if (!valid_zone(i)) zone_t *z = get_zone(i);
continue;
zone_t *z = &zt->zone[i]; if (!z)
continue;
nzones++; nzones++;
for (k=0; k<16; k++) { for (k=0; k<16; k++) {
int cnum = z->member[k]; int cnum = z->member[k];
if (cnum != 0 && !valid_channel(cnum - 1)) { if (cnum != 0 && !get_channel(cnum - 1)) {
fprintf(stderr, "Zone %d '", i+1); fprintf(stderr, "Zone %d '", i+1);
print_ascii(stderr, z->name, 16, 0); print_ascii(stderr, z->name, 16, 0);
fprintf(stderr, "': channel %d not found.\n", cnum); fprintf(stderr, "': channel %d not found.\n", cnum);
@ -2222,16 +2246,16 @@ static int rd5r_verify_config(radio_device_t *radio)
// Scanlists: check references to channels. // Scanlists: check references to channels.
for (i=0; i<NSCANL; i++) { for (i=0; i<NSCANL; i++) {
scanlist_t *sl = GET_SCANLIST(i); scanlist_t *sl = get_scanlist(i);
if (!VALID_SCANLIST(sl)) if (!sl)
break; continue;
nscanlists++; nscanlists++;
for (k=0; k<32; k++) { for (k=0; k<32; k++) {
int cnum = sl->member[k]; int cnum = sl->member[k] - 1;
if (cnum != 0 && !valid_channel(cnum - 1)) { if (cnum > 0 && !get_channel(cnum - 1)) {
fprintf(stderr, "Scanlist %d '", i+1); fprintf(stderr, "Scanlist %d '", i+1);
print_ascii(stderr, sl->name, 15, 0); print_ascii(stderr, sl->name, 15, 0);
fprintf(stderr, "': channel %d not found.\n", cnum); fprintf(stderr, "': channel %d not found.\n", cnum);