From 2b236d794e6a4f6b842c4639cd9a64435aae4901 Mon Sep 17 00:00:00 2001
From: Brent Petit <bjpetit@users.noreply.github.com>
Date: Thu, 29 Jun 2023 23:29:44 -0500
Subject: [PATCH] Add support for full CTCSS and DCS beacon options

---
 src/beacon.c      |  6 +++---
 src/config.c      | 14 +++++++++++++-
 src/config.h      |  1 +
 src/direwolf.c    |  2 +-
 src/encode_aprs.c | 49 +++++++++++++++++++++++++++++------------------
 src/encode_aprs.h |  4 ++--
 src/tt_user.c     |  2 +-
 src/walk96.c      |  2 +-
 8 files changed, 52 insertions(+), 28 deletions(-)

diff --git a/src/beacon.c b/src/beacon.c
index 69a72701..de3d90d0 100644
--- a/src/beacon.c
+++ b/src/beacon.c
@@ -892,7 +892,7 @@ static void beacon_send (int j, dwgps_info_t *gpsinfo)
 			bp->symtab, bp->symbol,
 			bp->power, bp->height, bp->gain, bp->dir,
 			G_UNKNOWN, G_UNKNOWN, /* course, speed */
-			bp->freq, bp->tone, bp->offset,
+			bp->freq, bp->tone_type, bp->tone, bp->offset,
 			super_comment,
 			info, sizeof(info));
 		  strlcat (beacon_text, info, sizeof(beacon_text));
@@ -904,7 +904,7 @@ static void beacon_send (int j, dwgps_info_t *gpsinfo)
 			bp->symtab, bp->symbol,
 			bp->power, bp->height, bp->gain, bp->dir,
 			G_UNKNOWN, G_UNKNOWN, /* course, speed */
-			bp->freq, bp->tone, bp->offset, super_comment,
+			bp->freq, bp-> tone_type, bp->tone, bp->offset, super_comment,
 			info, sizeof(info));
 		  strlcat (beacon_text, info, sizeof(beacon_text));
 		  break;
@@ -935,7 +935,7 @@ static void beacon_send (int j, dwgps_info_t *gpsinfo)
 			bp->symtab, bp->symbol,
 			bp->power, bp->height, bp->gain, bp->dir,
 			coarse, (int)roundf(gpsinfo->speed_knots),
-			bp->freq, bp->tone, bp->offset,
+			bp->freq, bp->tone_type, bp->tone, bp->offset,
 			super_comment,
 			info, sizeof(info));
 		    strlcat (beacon_text, info, sizeof(beacon_text));
diff --git a/src/config.c b/src/config.c
index de8d74d4..c1b09499 100644
--- a/src/config.c
+++ b/src/config.c
@@ -5663,6 +5663,7 @@ static int beacon_options(char *cmd, struct beacon_s *b, int line, struct audio_
 	b->symtab = '/';
 	b->symbol = '-';	/* house */
 	b->freq = G_UNKNOWN;
+	b->tone_type = 'T';
 	b->tone = G_UNKNOWN;
 	b->offset = G_UNKNOWN;
 	b->source = NULL;
@@ -5913,7 +5914,18 @@ static int beacon_options(char *cmd, struct beacon_s *b, int line, struct audio_
 	    b->freq = atof(value);
 	  }
 	  else if (strcasecmp(keyword, "TONE") == 0) {
-	    b->tone = atof(value);
+	    b->tone_type = 'T';
+	    /* Try the legacy tone config, just a number */
+	    if((b->tone = atof(value)) == 0) {
+	      /* Legacy parsing failed, try with leading type char */
+	      if(sscanf(value, "%c%f", &b->tone_type, &b->tone) != 2) {
+	        /* That failed. Bad tone format, set to no tone */
+	        b->tone_type = 'T';
+	        b->tone = 0;
+	        text_color_set(DW_COLOR_ERROR);
+	        dw_printf ("Config file, line %d: Bad tone format, %s.\n", line, value);
+	      }
+	    }
 	  }
 	  else if (strcasecmp(keyword, "OFFSET") == 0 || strcasecmp(keyword, "OFF") == 0) {
 	    b->offset = atof(value);
diff --git a/src/config.h b/src/config.h
index 360ac492..a92a7e82 100644
--- a/src/config.h
+++ b/src/config.h
@@ -221,6 +221,7 @@ struct misc_config_s {
 	  char dir[3];		/* 1 or 2 of N,E,W,S, or empty for omni. */
 
 	  float freq;		/* MHz. */
+	  char  tone_type;	/* Tone(T), Tone Squelch(C) or DCS(D) */
 	  float tone;		/* Hz. */
 	  float offset;		/* MHz. */
 	
diff --git a/src/direwolf.c b/src/direwolf.c
index 2dfa58d3..a8cddd82 100644
--- a/src/direwolf.c
+++ b/src/direwolf.c
@@ -1495,7 +1495,7 @@ void app_process_rec_packet (int chan, int subchan, int slice, packet_t pp, alev
 	        // Unknown not handled properly.
 		// Should encode_object take floating point here?
 		(int)(A.g_course+0.5), (int)(DW_MPH_TO_KNOTS(A.g_speed_mph)+0.5),
-		0, 0, 0, A.g_comment,	// freq, tone, offset
+		0, 'T', 0, 0, A.g_comment,	// freq, tone_type, tone, offset
 		ais_obj_info, sizeof(ais_obj_info));
 
 	      snprintf (ais_obj_packet, sizeof(ais_obj_packet), "%s>%s%1d%1d:%s", A.g_src, APP_TOCALL, MAJOR_VERSION, MINOR_VERSION, ais_obj_info);
diff --git a/src/encode_aprs.c b/src/encode_aprs.c
index 20992bf7..e1eaa2b9 100644
--- a/src/encode_aprs.c
+++ b/src/encode_aprs.c
@@ -405,6 +405,7 @@ static int cse_spd_data_extension (int course, int speed, char *presult)
  * Purpose:     Put frequency specification in beginning of comment field.
  *
  * Inputs: 	freq	- MHz.
+ *		tone_type - T/Tone, C/Tone Squelch, D/DCS
  *		tone	- Hz.
  *		offset	- MHz.
  *
@@ -430,7 +431,7 @@ static int cse_spd_data_extension (int course, int speed, char *presult)
  *----------------------------------------------------------------*/
 
 
-static int frequency_spec (float freq, float tone, float offset, char *presult)
+static int frequency_spec (float freq, char tone_type, float tone, float offset, char *presult)
 {
 	int result_size = 24;		// TODO: add as parameter.
 
@@ -456,7 +457,15 @@ static int frequency_spec (float freq, float tone, float offset, char *presult)
 	    strlcpy (stemp, "Toff ", sizeof (stemp));
 	  }
 	  else {
-	    snprintf (stemp, sizeof(stemp), "T%03d ", (int)tone);
+	    /* Tone enabled */
+	    if (tone_type == 'T' || tone_type == 'C' || tone_type == 'D') {
+	      /* CTCSS Tone or DCS Code*/
+	      snprintf(stemp, sizeof(stemp), "%c%03d ", tone_type, (int)tone);
+	    } else {
+	      /* Error */
+	      text_color_set(DW_COLOR_ERROR);
+	      dw_printf("Invalid tone type\n");
+	    }
 	  }
 
 	  strlcat (presult, stemp, result_size);
@@ -499,6 +508,7 @@ static int frequency_spec (float freq, float tone, float offset, char *presult)
  *		speed	- knots.		// TODO:  should distinguish unknown(not revevant) vs. known zero.
  *
  * 	 	freq	- MHz.
+ * 	 	tone_type - T/C/D
  *		tone	- Hz.
  *		offset	- MHz.
  *
@@ -544,7 +554,7 @@ int encode_position (int messaging, int compressed, double lat, double lon, int
 		char symtab, char symbol, 
 		int power, int height, int gain, char *dir,
 		int course, int speed,
-		float freq, float tone, float offset,
+		float freq, char tone_type, float tone, float offset,
 		char *comment,
 		char *presult, size_t result_size)
 {
@@ -590,7 +600,7 @@ int encode_position (int messaging, int compressed, double lat, double lon, int
 /* Optional frequency spec. */
 
 	if (freq != 0 || tone != 0 || offset != 0) {
-	  result_len += frequency_spec (freq, tone, offset, presult + result_len);
+	  result_len += frequency_spec (freq, tone_type, tone, offset, presult + result_len);
 	}
 
 	presult[result_len] = '\0';
@@ -650,6 +660,7 @@ int encode_position (int messaging, int compressed, double lat, double lon, int
  *		speed	- knots.
  *
  * 	 	freq	- MHz.
+ * 	 	tone_type - T/C/D 
  *		tone	- Hz.
  *		offset	- MHz.
  *
@@ -687,7 +698,7 @@ int encode_object (char *name, int compressed, time_t thyme, double lat, double
 		char symtab, char symbol, 
 		int power, int height, int gain, char *dir,
 		int course, int speed,
-		float freq, float tone, float offset, char *comment,
+		float freq, char tone_type, float tone, float offset, char *comment,
 		char *presult, size_t result_size)
 {
 	aprs_object_t *p = (aprs_object_t *) presult;
@@ -753,7 +764,7 @@ int encode_object (char *name, int compressed, time_t thyme, double lat, double
 /* Optional frequency spec. */
 
 	if (freq != 0 || tone != 0 || offset != 0) {
-	  result_len += frequency_spec (freq, tone, offset, presult + result_len);
+	  result_len += frequency_spec (freq, tone_type, tone, offset, presult + result_len);
 	}
 
 	presult[result_len] = '\0';
@@ -857,7 +868,7 @@ int main (int argc, char *argv[])
 /***********  Position  ***********/
 
 	encode_position (0, 0, 42+34.61/60, -(71+26.47/60), 0, G_UNKNOWN, 'D', '&',
-		0, 0, 0, NULL, G_UNKNOWN, 0, 0, 0, 0, NULL, result, sizeof(result));
+		0, 0, 0, NULL, G_UNKNOWN, 0, 0, 'T', 0, 0, NULL, result, sizeof(result));
 	dw_printf ("%s\n", result);
 	if (strcmp(result, "!4234.61ND07126.47W&") != 0) { dw_printf ("ERROR!  line %d\n", __LINE__); errors++; }
 
@@ -865,50 +876,50 @@ int main (int argc, char *argv[])
 // TODO:  Need to test specifying some but not all.
 
 	encode_position (0, 0, 42+34.61/60, -(71+26.47/60), 0, G_UNKNOWN, 'D', '&',
-		50, 100, 6, "N", G_UNKNOWN, 0, 0, 0, 0, NULL, result, sizeof(result));
+		50, 100, 6, "N", G_UNKNOWN, 0, 0, 'T', 0, 0, NULL, result, sizeof(result));
 	dw_printf ("%s\n", result);
 	if (strcmp(result, "!4234.61ND07126.47W&PHG7368") != 0) { dw_printf ("ERROR!  line %d\n", __LINE__); errors++; }
 
 /* with freq & tone.  minus offset, no offset, explicit simplex. */
 
 	encode_position (0, 0, 42+34.61/60, -(71+26.47/60), 0, G_UNKNOWN, 'D', '&',
-		0, 0, 0, NULL, G_UNKNOWN, 0, 146.955, 74.4, -0.6, NULL, result, sizeof(result));
+		0, 0, 0, NULL, G_UNKNOWN, 0, 146.955, 'T', 74.4, -0.6, NULL, result, sizeof(result));
 	dw_printf ("%s\n", result);
 	if (strcmp(result, "!4234.61ND07126.47W&146.955MHz T074 -060 ") != 0) { dw_printf ("ERROR!  line %d\n", __LINE__); errors++; }
 
 	encode_position (0, 0, 42+34.61/60, -(71+26.47/60), 0, G_UNKNOWN, 'D', '&',
-		0, 0, 0, NULL, G_UNKNOWN, 0, 146.955, 74.4, G_UNKNOWN, NULL, result, sizeof(result));
+		0, 0, 0, NULL, G_UNKNOWN, 0, 146.955, 'T', 74.4, G_UNKNOWN, NULL, result, sizeof(result));
 	dw_printf ("%s\n", result);
 	if (strcmp(result, "!4234.61ND07126.47W&146.955MHz T074 ") != 0) { dw_printf ("ERROR!  line %d\n", __LINE__); errors++; }
 
 	encode_position (0, 0, 42+34.61/60, -(71+26.47/60), 0, G_UNKNOWN, 'D', '&',
-		0, 0, 0, NULL, G_UNKNOWN, 0, 146.955, 74.4, 0, NULL, result, sizeof(result));
+		0, 0, 0, NULL, G_UNKNOWN, 0, 146.955, 'T', 74.4, 0, NULL, result, sizeof(result));
 	dw_printf ("%s\n", result);
 	if (strcmp(result, "!4234.61ND07126.47W&146.955MHz T074 +000 ") != 0) { dw_printf ("ERROR!  line %d\n", __LINE__); errors++; }
 
 /* with course/speed, freq, and comment! */
 
 	encode_position (0, 0, 42+34.61/60, -(71+26.47/60), 0, G_UNKNOWN, 'D', '&',
-		0, 0, 0, NULL, 180, 55, 146.955, 74.4, -0.6, "River flooding", result, sizeof(result));
+		0, 0, 0, NULL, 180, 55, 146.955, 'T', 74.4, -0.6, "River flooding", result, sizeof(result));
 	dw_printf ("%s\n", result);
 	if (strcmp(result, "!4234.61ND07126.47W&180/055146.955MHz T074 -060 River flooding") != 0) { dw_printf ("ERROR!  line %d\n", __LINE__); errors++; }
 
 /* Course speed, no tone, + offset */
 
 	encode_position (0, 0, 42+34.61/60, -(71+26.47/60), 0, G_UNKNOWN, 'D', '&',
-		0, 0, 0, NULL, 180, 55, 146.955, G_UNKNOWN, 0.6, "River flooding", result, sizeof(result));
+		0, 0, 0, NULL, 180, 55, 146.955, 'T', G_UNKNOWN, 0.6, "River flooding", result, sizeof(result));
 	dw_printf ("%s\n", result);
 	if (strcmp(result, "!4234.61ND07126.47W&180/055146.955MHz +060 River flooding") != 0) { dw_printf ("ERROR!  line %d\n", __LINE__); errors++; }
 
 /* Course speed, no tone, + offset + altitude */
 
 	encode_position (0, 0, 42+34.61/60, -(71+26.47/60), 0, 12345, 'D', '&',
-		0, 0, 0, NULL, 180, 55, 146.955, G_UNKNOWN, 0.6, "River flooding", result, sizeof(result));
+		0, 0, 0, NULL, 180, 55, 146.955, 'T', G_UNKNOWN, 0.6, "River flooding", result, sizeof(result));
 	dw_printf ("%s\n", result);
 	if (strcmp(result, "!4234.61ND07126.47W&180/055146.955MHz +060 /A=012345River flooding") != 0) { dw_printf ("ERROR!  line %d\n", __LINE__); errors++; }
 
 	encode_position (0, 0, 42+34.61/60, -(71+26.47/60), 0, 12345, 'D', '&',
-		0, 0, 0, NULL, 180, 55, 146.955, 0, 0.6, "River flooding", result, sizeof(result));
+		0, 0, 0, NULL, 180, 55, 146.955, 'T', 0, 0.6, "River flooding", result, sizeof(result));
 	dw_printf ("%s\n", result);
 	if (strcmp(result, "!4234.61ND07126.47W&180/055146.955MHz Toff +060 /A=012345River flooding") != 0) { dw_printf ("ERROR!  line %d\n", __LINE__); errors++; }
 
@@ -917,7 +928,7 @@ int main (int argc, char *argv[])
 /*********** Compressed position. ***********/
 
 	encode_position (0, 1, 42+34.61/60, -(71+26.47/60), 0, G_UNKNOWN, 'D', '&',
-		0, 0, 0, NULL, G_UNKNOWN, 0, 0, 0, 0, NULL, result, sizeof(result));
+		0, 0, 0, NULL, G_UNKNOWN, 0, 0, 'T', 0, 0, NULL, result, sizeof(result));
 	dw_printf ("%s\n", result);
 	if (strcmp(result, "!D8yKC<Hn[&  !") != 0) { dw_printf ("ERROR!  line %d\n", __LINE__); errors++; }
 
@@ -925,14 +936,14 @@ int main (int argc, char *argv[])
 /* with PHG. In this case it is converted to precomputed radio range.  TODO: check on this.  Is 27.4 correct? */
 
 	encode_position (0, 1, 42+34.61/60, -(71+26.47/60), 0, G_UNKNOWN, 'D', '&',
-		50, 100, 6, "N", G_UNKNOWN, 0, 0, 0, 0, NULL, result, sizeof(result));
+		50, 100, 6, "N", G_UNKNOWN, 0, 0, 'T', 0, 0, NULL, result, sizeof(result));
 	dw_printf ("%s\n", result);
 	if (strcmp(result, "!D8yKC<Hn[&{CG") != 0) { dw_printf ("ERROR!  line %d\n", __LINE__); errors++; }
 
 /* with course/speed, freq, and comment!  Roundoff. 55 knots should be 63 MPH.  we get 62. */
 
 	encode_position (0, 1, 42+34.61/60, -(71+26.47/60), 0, G_UNKNOWN, 'D', '&',
-		0, 0, 0, NULL, 180, 55, 146.955, 74.4, -0.6, "River flooding", result, sizeof(result));
+		0, 0, 0, NULL, 180, 55, 146.955, 'T', 74.4, -0.6, "River flooding", result, sizeof(result));
 	dw_printf ("%s\n", result);
 	if (strcmp(result, "!D8yKC<Hn[&NUG146.955MHz T074 -060 River flooding") != 0) { dw_printf ("ERROR!  line %d\n", __LINE__); errors++; }
 
@@ -942,7 +953,7 @@ int main (int argc, char *argv[])
 /*********** Object. ***********/
 
 	encode_object ("WB1GOF-C", 0, 0, 42+34.61/60, -(71+26.47/60), 0, 'D', '&',
-		0, 0, 0, NULL, G_UNKNOWN, 0, 0, 0, 0, NULL, result, sizeof(result));
+		0, 0, 0, NULL, G_UNKNOWN, 0, 0, 'T', 0, 0, NULL, result, sizeof(result));
 	dw_printf ("%s\n", result);
 	if (strcmp(result, ";WB1GOF-C *111111z4234.61ND07126.47W&") != 0) { dw_printf ("ERROR!  line %d\n", __LINE__); errors++; }
 
diff --git a/src/encode_aprs.h b/src/encode_aprs.h
index dc7b8bdf..9a6a0965 100644
--- a/src/encode_aprs.h
+++ b/src/encode_aprs.h
@@ -3,7 +3,7 @@ int encode_position (int messaging, int compressed, double lat, double lon, int
 		char symtab, char symbol, 
 		int power, int height, int gain, char *dir,
 		int course, int speed_knots,
-		float freq, float tone, float offset,
+		float freq, char tone_type, float tone, float offset,
 		char *comment,
 		char *presult, size_t result_size);
 
@@ -11,7 +11,7 @@ int encode_object (char *name, int compressed, time_t thyme, double lat, double
 		char symtab, char symbol, 
 		int power, int height, int gain, char *dir,
 		int course, int speed_knots,
-		float freq, float tone, float offset, char *comment,
+		float freq, char tone_type, float tone, float offset, char *comment,
 		char *presult, size_t result_size);
 
 int encode_message (char *addressee, char *text, char *id, char *presult, size_t result_size);
diff --git a/src/tt_user.c b/src/tt_user.c
index a73d6a46..edbc67d0 100644
--- a/src/tt_user.c
+++ b/src/tt_user.c
@@ -847,7 +847,7 @@ static void xmit_object_report (int i, int first_time)
 		0,0,0,NULL, G_UNKNOWN, G_UNKNOWN,	/* PHGD, Course/Speed */
 		strlen(tt_user[i].freq) > 0 ? atof(tt_user[i].freq) : G_UNKNOWN,
 		strlen(tt_user[i].ctcss) > 0 ? atof(tt_user[i].ctcss) : G_UNKNOWN,
-		G_UNKNOWN,	/* CTCSS */
+		'T', G_UNKNOWN,	/* CTCSS */
 		info_comment, object_info, sizeof(object_info));
 
 	strlcat (stemp, object_info, sizeof(stemp));
diff --git a/src/walk96.c b/src/walk96.c
index 9fc791f8..6438fbc1 100644
--- a/src/walk96.c
+++ b/src/walk96.c
@@ -156,7 +156,7 @@ static void walk96 (int fix, double lat, double lon, float knots, float course,
 		'/', '=',
 		G_UNKNOWN, G_UNKNOWN, G_UNKNOWN, "",	// PHGd
 		(int)roundf(course), (int)roundf(knots),
-		445.925, 0, 0,
+		445.925, 'T', 0, 0,
 		comment,
 		info, sizeof(info));