aboutsummaryrefslogtreecommitdiffstats
path: root/homescreen/src/mastervolume.h
AgeCommit message (Expand)AuthorFilesLines
2017-05-22Add master volume control sliderMatt Porter1-0/+49
f='#n97'>97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184
FM configuration improvements

Changes include:
- Add command-line option for selecting FM band plan.  The default
  band plan is US / Canada.
- Add command-line options for setting FM scanning valid SNR and RSSI
  thresholds to allow tweaking sensitivity in poor radio environments.
- Increased seeking scan timeout to 3 seconds, which seems to improve
  behavior in poor radio environments where powerful stations may be
  far apart.
- Removed explicit setting of FM_SOFTMUTE_SNR_LIMITS, as it seemed
  like it might be resulting in odd muting behavior when scanning.
- Changed initial FM frequency if not specified to the minimum of the
  band plan.

Signed-off-by: Scott Murray <scott.murray@konsulko.com>

diff --git a/si46xx.h b/si46xx.h
index 172ea8b..c32fca4 100644
--- a/si46xx.h
+++ b/si46xx.h
@@ -83,6 +83,7 @@
 #define SI46XX_PIN_CONFIG_ENABLE 0x0800
 #define SI46XX_FM_SEEK_BAND_BOTTOM 0x3100
 #define SI46XX_FM_SEEK_BAND_TOP 0x3101
+#define SI46XX_FM_SEEK_FREQUENCY_SPACING 0x3102
 #define SI46XX_FM_VALID_MAX_TUNE_ERROR 0x3200
 #define SI46XX_FM_VALID_RSSI_TIME 0x3201
 #define SI46XX_FM_VALID_RSSI_THRESHOLD 0x3202
@@ -150,7 +151,7 @@
 #define MAX_SERVICES 32
 #define MAX_COMPONENTS 15
 
-#define TIMEOUT_SEEK	2000	/* mS = 2S */
+#define TIMEOUT_SEEK	3000	/* mS = 3S */
 #define TIMEOUT_TUNE	500	/* mS = .5S */
 
 struct dab_service_t{
diff --git a/si_ctl.c b/si_ctl.c
index 59dfaf2..f168218 100644
--- a/si_ctl.c
+++ b/si_ctl.c
@@ -101,6 +101,26 @@ uint32_t frequency_list_ch[] = {	CHAN_12A,
 					CHAN_9D,
 					CHAN_8B};
 
+// Structure to describe FM band plans, all values in Hz.
+typedef struct {
+	char *name;
+	uint32_t min;
+	uint32_t max;
+	uint32_t step;
+} fm_band_plan_t;
+
+static fm_band_plan_t known_fm_band_plans[5] = {
+	{ .name = "US", .min = 87900000, .max = 107900000, .step = 200000 },
+	{ .name = "JP", .min = 76000000, .max = 95000000, .step = 100000 },
+	{ .name = "EU", .min = 87500000, .max = 108000000, .step = 50000 },
+	{ .name = "ITU-1", .min = 87500000, .max = 108000000, .step = 50000 },
+	{ .name = "ITU-2", .min = 87900000, .max = 107900000, .step = 50000 }
+};
+
+static unsigned int fm_band_plan;
+static int fm_snr_threshold = 128;
+static int fm_rssi_threshold = 128;
+
 int init_am(int offset)
 {
 	int ret;
@@ -160,12 +180,32 @@ int init_fm(int offset)
 	 * enable I2S output
 	 */
 	si46xx_set_property(SI46XX_PIN_CONFIG_ENABLE, 0x0003);
-	//si46xx_set_property(SI46XX_FM_VALID_RSSI_THRESHOLD,0x0000);
-	//si46xx_set_property(SI46XX_FM_VALID_SNR_THRESHOLD,0x0000);
-	si46xx_set_property(SI46XX_FM_SOFTMUTE_SNR_LIMITS, 0x0000); // set the SNR limits for soft mute attenuation
+	//si46xx_set_property(SI46XX_FM_SOFTMUTE_SNR_LIMITS, 0x0000); // set the SNR limits for soft mute attenuation
 	si46xx_set_property(SI46XX_FM_TUNE_FE_CFG, 0x0000); // front end switch open
-	si46xx_set_property(SI46XX_FM_SEEK_BAND_BOTTOM, 88000 / 10);
-	si46xx_set_property(SI46XX_FM_SEEK_BAND_TOP, 108000 / 10);
+
+	//si46xx_set_property(SI46XX_FM_SEEK_BAND_BOTTOM, 88000 / 10);
+	//si46xx_set_property(SI46XX_FM_SEEK_BAND_TOP, 108000 / 10);
+	if (verbose)
+		fprintf(stderr, "Using FM Bandplan: %s\n", known_fm_band_plans[fm_band_plan].name);
+	si46xx_set_property(SI46XX_FM_SEEK_BAND_BOTTOM, known_fm_band_plans[fm_band_plan].min / 10000);
+	si46xx_set_property(SI46XX_FM_SEEK_BAND_TOP, known_fm_band_plans[fm_band_plan].max / 10000);
+	if (verbose)
+		fprintf(stderr, "Using FM band: %d - %d, %d spacing\n",
+			known_fm_band_plans[fm_band_plan].min / 10000,
+			known_fm_band_plans[fm_band_plan].max / 10000,
+			known_fm_band_plans[fm_band_plan].step / 10000);
+	si46xx_set_property(SI46XX_FM_SEEK_FREQUENCY_SPACING, known_fm_band_plans[fm_band_plan].step / 10000);
+	if (fm_snr_threshold != 128) {
+		if (verbose)
+			fprintf(stderr, "Setting FM valid SNR threshold to %d dB\n", fm_snr_threshold);
+		si46xx_set_property(SI46XX_FM_VALID_SNR_THRESHOLD, fm_snr_threshold);
+	}
+	if (fm_rssi_threshold != 128) {
+		if (verbose)
+			fprintf(stderr, "Setting FM valid RSSI threshold to %d dB\n", fm_rssi_threshold);
+		si46xx_set_property(SI46XX_FM_VALID_RSSI_THRESHOLD, fm_rssi_threshold);
+	}
+
 	/*
 	 * rate
 	 */
@@ -190,6 +230,7 @@ int init_fm(int offset)
 
 	return 0;
 }
+
 int init_dab(int offset)
 {
 	int ret;
@@ -245,6 +286,10 @@ int output_help(char *prog_name)
 	printf("  -l up|down     FM/AM seek next station\n");
 	printf("  -d             FM/AM RSQ status\n");
 	printf("  -m             FM rds status\n");
+	printf("Common FM:\n");
+	printf("  -p bandplan    FM bandplan (us, jp, eu, itu-1, itu-2\n");
+	printf("  -t SNR         FM scan valid SNR threshold (-127 to 127 dB)\n");
+	printf("  -u RSSI        FM scan valid RSSI threshold (-127 to 127 dBuV)\n");
 	printf("DAB only:\n");
 	printf("  -e             dab status\n");
 	printf("  -f service     start service of dab service list\n");
@@ -354,6 +399,7 @@ int main(int argc, char **argv)
 	int offset = - 1;
 	int mode;
 	int tmp;
+	unsigned int i;
 	struct dab_digrad_status_t dab_digrad_status;
 	bool init = false;
 	bool seek_up = false;
@@ -374,7 +420,7 @@ int main(int argc, char **argv)
 
 	optind = 0;
 	while (optind < argc) {
-		if ((c = getopt(argc, argv, "a:b:c:def:ghi:j:k:l:mnosv")) != -1) {
+		if ((c = getopt(argc, argv, "a:b:c:def:ghi:j:k:l:mnop:st:u:v")) != -1) {
 			switch(c){
 			/* init */
 			case 'a':
@@ -422,6 +468,31 @@ int main(int argc, char **argv)
 			case 'c':
 				frequency = atoi(optarg);
 				break;
+			/* FM */
+			case 'p':
+				for(i = 0;
+				    i < sizeof(known_fm_band_plans) / sizeof(fm_band_plan_t);
+				    i++) {
+					if(!strcasecmp(optarg, known_fm_band_plans[i].name)) {
+						fm_band_plan = i;
+						break;
+					}
+				}
+				if(i >= (sizeof(known_fm_band_plans) / sizeof(fm_band_plan_t))) {
+					printf("Invalid mode: %s\n", optarg);
+					return -EINVAL;
+				}
+				break;
+			case 't':
+				fm_snr_threshold = atoi(optarg);
+				if(fm_snr_threshold < -128 || fm_snr_threshold > 127)
+					fm_snr_threshold = 128; // use firmware default
+				break;
+			case 'u':
+				fm_rssi_threshold = atoi(optarg);
+				if(fm_rssi_threshold < -128 || fm_rssi_threshold > 127)
+					fm_rssi_threshold = 128; // use firmware default
+				break;
 			/* DAB stuff. TODO: rework */
 			case 'e':
 				si46xx_dab_digrad_status(&dab_digrad_status);
@@ -473,7 +544,7 @@ int main(int argc, char **argv)
 			case SI46XX_MODE_FM:
 				ret = init_fm(offset);
 				if (frequency < 0)
-					frequency = 105500;
+					frequency = known_fm_band_plans[fm_band_plan].min / 1000;
 			break;
 			case SI46XX_MODE_AM:
 				ret = init_am(offset);