linux-media.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [RFC PATCHv2 0/3] libv4l2rds: add support for RDS-EON and TMC-tuning decoding
@ 2013-06-04 19:15 Konke Radlow
  2013-06-04 19:15 ` [RFC PATCHv2 1/3] libv4l2rds: support RDS-EON and TMC-tuning info Konke Radlow
  2013-06-07  8:27 ` [RFC PATCHv2 0/3] libv4l2rds: add support for RDS-EON and TMC-tuning decoding Hans Verkuil
  0 siblings, 2 replies; 5+ messages in thread
From: Konke Radlow @ 2013-06-04 19:15 UTC (permalink / raw)
  To: linux-media; +Cc: hverkuil, hdegoede

This patch series is based on the commments to:

[RFC PATCH 0/4] libv4l2rds: support for decoding RDS tuning information
[RFC PATCH 1/4] libv4l2rds: added support to decode RDS-EON information
[RFC PATCH 2/4] rds-ctl.cpp: added functionality to print RDS-EON information
[RFC PATCH 3/4] libv4l2rds: added support to decode RDS-TMC tuning information
[RFC PATCH 4/4] rds-ctl.cpp: added functionality to print RDS-TMC tuning information

The proposed changes have been integrated and the patches (1, 3) and (2, 4) have been merged
into one unit.


^ permalink raw reply	[flat|nested] 5+ messages in thread

* [RFC PATCHv2 1/3] libv4l2rds: support RDS-EON and TMC-tuning info
  2013-06-04 19:15 [RFC PATCHv2 0/3] libv4l2rds: add support for RDS-EON and TMC-tuning decoding Konke Radlow
@ 2013-06-04 19:15 ` Konke Radlow
  2013-06-04 19:15   ` [RFC PATCHv2 2/3] rds-ctl: " Konke Radlow
  2013-06-04 19:15   ` [RFC PATCHv2 3/3] libv4l2rds.c: moving functions to get rid of declarations Signed-off-by: Konke Radlow <koradlow@gmail.com> Konke Radlow
  2013-06-07  8:27 ` [RFC PATCHv2 0/3] libv4l2rds: add support for RDS-EON and TMC-tuning decoding Hans Verkuil
  1 sibling, 2 replies; 5+ messages in thread
From: Konke Radlow @ 2013-06-04 19:15 UTC (permalink / raw)
  To: linux-media; +Cc: hverkuil, hdegoede

Signed-off-by: Konke Radlow <koradlow@gmail.com>

libv4l2rds: added support to decode RDS-EON information

Signed-off-by: Konke Radlow <koradlow@gmail.com>

libv4l2rds: added support to decode RDS-TMC tuning information

Signed-off-by: Konke Radlow <koradlow@gmail.com>

libv4l2rds.c: fixing compiler warnings due to missing pointer dereferencing
and implementing changes proposed in RFC replies (RDS-EON patch)

Signed-off-by: Konke Radlow <koradlow@gmail.com>

libv4l2rds: implementing changes proposed in RFC replies (TMC-Tuning patch)

Signed-off-by: Konke Radlow <koradlow@gmail.com>
---
 lib/include/libv4l2rds.h    |   79 +++++++++-
 lib/libv4l2rds/libv4l2rds.c |  363 ++++++++++++++++++++++++++++++++++++++++---
 2 files changed, 417 insertions(+), 25 deletions(-)

diff --git a/lib/include/libv4l2rds.h b/lib/include/libv4l2rds.h
index 6a6c7f3..e1078de 100644
--- a/lib/include/libv4l2rds.h
+++ b/lib/include/libv4l2rds.h
@@ -37,7 +37,7 @@ extern "C" {
 #endif
 
 /* used to define the current version (version field) of the v4l2_rds struct */
-#define V4L2_RDS_VERSION (1)
+#define V4L2_RDS_VERSION (2)
 
 /* Constants used to define the size of arrays used to store RDS information */
 #define MAX_ODA_CNT 18 	/* there are 16 groups each with type a or b. Of these
@@ -50,6 +50,16 @@ extern "C" {
 			* Additional data is limited to 112 bit, and the smallest
 			* optional tuple has a size of 4 bit (4 bit identifier +
 			* 0 bits of data) */
+#define MAX_TMC_ALT_STATIONS 32 /* defined by ISO 14819-1:2003, 7.5.3.3  */
+#define MAX_TMC_AF_CNT 4	/* limit for the numbers of AFs stored per alternative TMC
+			* station. This value is not defined by the standard, but based on observation
+			* of real-world RDS-TMC streams. The maximum encountered number of AFs per
+			* station during testing was 2 */
+#define MAX_EON_CNT 20	/* Maximal number of entries in the EON table (for storing
+			* information about other radio stations, broadcasted by the current station). 
+			* This value is not defined by the standard, but based on observation
+			* of real-world RDS-TMC streams. EON doesn't seem to be a widely used feature
+			* and the maximum number of EON encountered during testing was 8 */
 
 /* Define Constants for the possible types of RDS information
  * used to address the relevant bit in the valid_fields bitmask */
@@ -69,7 +79,10 @@ extern "C" {
 #define V4L2_RDS_LC		0x2000	/* Language Code */
 #define V4L2_RDS_TMC_SG		0x4000	/* RDS-TMC single group */
 #define V4L2_RDS_TMC_MG		0x8000	/* RDS-TMC multi group */
-#define V4L2_RDS_TMC_SYS	0x10000 /* RDS-TMC system information */
+#define V4L2_RDS_TMC_SYS	0x10000	/* RDS-TMC system information */
+#define V4L2_RDS_EON		0x20000	/* Enhanced Other Network Info */
+#define V4L2_RDS_LSF		0x40000	/* Linkage information */
+#define V4L2_RDS_TMC_TUNING	0x80000	/* RDS-TMC tuning information */
 
 /* Define Constants for the state of the RDS decoding process
  * used to address the relevant bit in the decode_information bitmask */
@@ -84,9 +97,10 @@ extern "C" {
 #define V4L2_RDS_FLAG_STATIC_PTY	0x08
 
 /* TMC related codes
- * used to extract TMC fields from RDS groups */
-#define V4L2_TMC_TUNING_INFO	0x08
-#define V4L2_TMC_SINGLE_GROUP	0x04
+ * used to extract TMC fields from RDS-TMC groups
+ * see ISO 14819-1:2003, Figure 2 - RDS-TMC single-grp full message structure */
+#define V4L2_TMC_TUNING_INFO	0x10	/* Bit 4 indicates Tuning Info / User msg */
+#define V4L2_TMC_SINGLE_GROUP	0x08	/* Bit 3 indicates Single / Multi-group msg */
 
 /* struct to encapsulate one complete RDS group */
 /* This structure is used internally to store data until a complete RDS
@@ -149,6 +163,57 @@ struct v4l2_rds_af_set {
 	uint32_t af[MAX_AF_CNT];	/* AFs defined in Hz */
 };
 
+/* struct to encapsulate one entry in the EON table (Enhanced Other Network) */
+struct v4l2_rds_eon {
+	uint32_t valid_fields;
+	uint16_t pi;
+	uint8_t ps[9];
+	uint8_t pty;
+	bool ta;
+	bool tp;
+	uint16_t lsf;		/* Linkage Set Number */
+	struct v4l2_rds_af_set af;
+};
+
+/* struct to encapsulate a table of EON information */
+struct v4l2_rds_eon_set {
+	uint8_t size;		/* size of the table */
+	uint8_t index;		/* current position in the table */
+	struct v4l2_rds_eon eon[MAX_EON_CNT];	/* Information about other
+						 * radio channels */
+};
+
+/* struct to encapsulate alternative frequencies (AFs) for RDS-TMC stations.
+ * AFs listed in af[] can be used unconditionally. 
+ * AFs listed in mapped_af[n] should only be used if the current 
+ * tuner frequency matches the value in mapped_af_tuning[n] */
+struct v4l2_tmc_alt_freq {
+	uint8_t af_size;		/* number of known AFs */
+	uint8_t af_index;
+	uint8_t mapped_af_size;		/* number of mapped AFs */
+	uint8_t mapped_af_index;
+	uint32_t af[MAX_TMC_AF_CNT];		/* AFs defined in Hz */
+	uint32_t mapped_af[MAX_TMC_AF_CNT];		/* mapped AFs defined in Hz */
+	uint32_t mapped_af_tuning[MAX_TMC_AF_CNT];	/* mapped AFs defined in Hz */
+};
+
+/* struct to encapsulate information about stations carrying RDS-TMC services */
+struct v4l2_tmc_station {
+	uint16_t pi;
+	uint8_t ltn;	/* database-ID of ON */
+	uint8_t msg;	/* msg parameters of ON */
+	uint8_t sid;	/* service-ID of ON */
+	struct v4l2_tmc_alt_freq afi;
+};
+
+/* struct to encapsulate tuning information for TMC */
+struct v4l2_tmc_tuning {
+	uint8_t station_cnt;	/* number of announced alternative stations */
+	uint8_t index;
+	struct v4l2_tmc_station station[MAX_TMC_ALT_STATIONS];	/* information
+							* about other stations carrying the same RDS-TMC service */
+};
+
 /* struct to encapsulate an additional data field in a TMC message */
 struct v4l2_tmc_additional {
 	uint8_t label;
@@ -199,6 +264,9 @@ struct v4l2_rds_tmc {
 	uint8_t t_d;		/* delay time (only if mode = enhanced */
 	uint8_t spn[9];		/* service provider name */
 	struct v4l2_rds_tmc_msg tmc_msg;
+
+	/* tuning information for alternative service providers */
+	struct v4l2_tmc_tuning tuning;
 };
 
 /* struct to encapsulate state and RDS information for current decoding process */
@@ -236,6 +304,7 @@ struct v4l2_rds {
 	struct v4l2_rds_statistics rds_statistics;
 	struct v4l2_rds_oda_set rds_oda;	/* Open Data Services */
 	struct v4l2_rds_af_set rds_af; 		/* Alternative Frequencies */
+	struct v4l2_rds_eon_set rds_eon;	/* EON information */
 	struct v4l2_rds_tmc tmc;		/* TMC information */
 };
 
diff --git a/lib/libv4l2rds/libv4l2rds.c b/lib/libv4l2rds/libv4l2rds.c
index 2918061..28b78ce 100644
--- a/lib/libv4l2rds/libv4l2rds.c
+++ b/lib/libv4l2rds/libv4l2rds.c
@@ -92,6 +92,11 @@ enum rds_state {
 	RDS_C_RECEIVED,
 };
 
+/* function declarations to prevent the need to move large code blocks */
+static int rds_add_tmc_station(struct rds_private_state *priv_state, uint16_t pi);
+static uint32_t rds_decode_af(uint8_t af, bool is_vhf);
+static bool rds_add_tmc_af(struct rds_private_state *priv_state);
+
 static inline uint8_t set_bit(uint8_t input, uint8_t bitmask, bool bitvalue)
 {
 	return bitvalue ? input | bitmask : input & ~bitmask;
@@ -368,7 +373,7 @@ static uint32_t rds_decode_tmc_multi_group(struct rds_private_state *priv_state)
 	/* bit 15 of block 3 is the first group indicator */
 	if (grp->data_c_msb & 0x80) {
 		/* begine decoding of new message */
-		memset(msg, 0, sizeof(msg));
+		memset(msg, 0, sizeof(*msg));
 		memset(priv_state->optional_tmc, 0, 112*sizeof(bool)); 
 		/* bits 0-3 of block 2 contain continuity index */
 		priv_state->continuity_id = grp->data_b_lsb & 0x07;
@@ -434,6 +439,60 @@ static uint32_t rds_decode_tmc_multi_group(struct rds_private_state *priv_state)
 	return V4L2_RDS_TMC_MG;
 }
 
+/* decode the RDS-TMC tuning information that is contained in type 8A groups
+ * (variants 4 to 9) that announce the presence alternative transmitters 
+ * providing the same RDS-TMC service */
+static uint32_t rds_decode_tmc_tuning(struct rds_private_state *priv_state)
+{
+	struct v4l2_rds_group *group = &priv_state->rds_group;
+	struct v4l2_rds_tmc *tmc = &priv_state->handle.tmc;
+	uint8_t variant_code = group->data_b_lsb & 0x0f;
+	uint16_t pi_on = (group->data_d_msb << 8) | group->data_d_lsb;
+	uint8_t index;
+
+	/* variants 4 and 5 carry the service provider name */
+	if (variant_code >= 4 && variant_code <= 5) {
+		int offset = 4 * (variant_code - 4);
+		tmc->spn[0 + offset] = group->data_c_msb;
+		tmc->spn[1 + offset] = group->data_c_lsb;
+		tmc->spn[2 + offset] = group->data_d_msb;
+		tmc->spn[3 + offset] = group->data_d_lsb;
+
+	/* variant 6 provides specific frequencies for the same RDS-TMC service
+	 * on a network with a different PI code */
+	/* variant 7 provides mapped frequency pair information which should only
+	 * be used if the terminal is tuned to the tuning frequency */
+	} else if (variant_code == 6 || variant_code == 7) {
+		rds_add_tmc_af(priv_state);
+
+	/* variant 8 indicates up to 2 PI codes of adjacent networks carrying 
+	 * the same RDS-TMC service on all transmitters of the network */ 
+	} else if (variant_code == 8) {
+		uint16_t pi_on_2 = (group->data_c_msb << 8) | group->data_c_lsb;
+
+		/* try to add both transmitted PI codes to the table */
+		rds_add_tmc_station(priv_state, pi_on);
+		/* PI = 0 is used as a filler code */
+		if (pi_on_2 != 0)
+			rds_add_tmc_station(priv_state, pi_on_2);
+
+	/* variant 9 provides PI codes of other networks with different system 
+	 * parameters */
+	} else if (variant_code == 9) {
+		index = rds_add_tmc_station(priv_state, pi_on);
+
+		/* bits 0 - 5 contain the service-ID of the ON */
+		tmc->tuning.station[index].sid = group->data_c_lsb & 0x3F;
+		/* bits 6-10 contain the msg parameters of the ON */
+		tmc->tuning.station[index].msg = (group->data_c_msb & 0x03) << 2;
+		tmc->tuning.station[index].msg |= (group->data_c_lsb >> 6) & 0x03;
+		/* bits 11-15 contain the database-ID of the ON */
+		tmc->tuning.station[index].ltn = group->data_c_msb >> 2;
+	}
+
+	return V4L2_RDS_TMC_TUNING;
+}
+
 static bool rds_add_oda(struct rds_private_state *priv_state, struct v4l2_rds_oda oda)
 {
 	struct v4l2_rds *handle = &priv_state->handle;
@@ -455,20 +514,11 @@ static bool rds_add_oda(struct rds_private_state *priv_state, struct v4l2_rds_od
 /* add a new AF to the list, if it doesn't exist yet */
 static bool rds_add_af_to_list(struct v4l2_rds_af_set *af_set, uint8_t af, bool is_vhf)
 {
-	uint32_t freq = 0;
-
-	/* AF0 -> "Not to be used" */
-	if (af == 0)
+	/* convert the frequency to Hz, skip on errors */
+	uint32_t freq = rds_decode_af(af, is_vhf);
+	if (freq == 0) 
 		return false;
 
-	/* calculate the AF values in HZ */
-	if (is_vhf)
-		freq = 87500000 + af * 100000;
-	else if (freq <= 15)
-		freq = 152000 + af * 9000;
-	else
-		freq = 531000 + af * 9000;
-
 	/* prevent buffer overflows */
 	if (af_set->size >= MAX_AF_CNT || af_set->size >= af_set->announced_af)
 		return false;
@@ -505,7 +555,7 @@ static bool rds_add_af(struct rds_private_state *priv_state)
 			updated_af = true;
 		c_lsb = 0; /* invalidate */
 	}
-	/* 224..249: announcement of AF count (224=0, 249=25)*/
+	/* 224..249: announcement of AF count (224=0, 249=25) */
 	if (c_msb >= 224 && c_msb <= 249)
 		af_set->announced_af = c_msb - 224;
 	/* check if the data represents an AF (for 1 =< val <= 204 the
@@ -522,6 +572,103 @@ static bool rds_add_af(struct rds_private_state *priv_state)
 	return updated_af;
 }
 
+/* checks if an entry for the given PI already exists and returns the index
+ * of that entry if so. Else it adds a new entry to the TMC-Tuning table and returns
+ * the index of the new field */
+static int rds_add_tmc_station(struct rds_private_state *priv_state, uint16_t pi)
+{
+	struct v4l2_tmc_tuning *tuning = &priv_state->handle.tmc.tuning;
+	uint8_t index = tuning->index;
+	uint8_t size = tuning->station_cnt;
+	
+	/* check if there's an entry for the given PI key */
+	for (int i = 0; i < tuning->station_cnt; i++) {
+		if (tuning->station[i].pi == pi) {
+			return i;
+		}
+	}
+	/* if the the maximum table size is reached, overwrite old
+	 * entries, starting at the oldest one = 0 */
+	tuning->station[index].pi = pi;
+	tuning->index = (index+1 < MAX_TMC_ALT_STATIONS) ? (index+1) : 0;
+	tuning->station_cnt = (size+1 <= MAX_TMC_ALT_STATIONS) ? (size+1) : MAX_TMC_ALT_STATIONS;
+	return index;
+}
+
+/* tries to add new AFs to the relevant entry in the list of RDS-TMC providers */
+static bool rds_add_tmc_af(struct rds_private_state *priv_state)
+{
+	struct v4l2_rds_group *grp = &priv_state->rds_group;
+	struct v4l2_tmc_alt_freq *afi;
+	uint16_t pi_on = grp->data_d_msb << 8 | grp->data_d_lsb;
+	uint8_t variant = grp->data_b_lsb & 0x0f;
+	uint8_t station_index = rds_add_tmc_station(priv_state, pi_on);
+	uint8_t af_index;
+	uint8_t mapped_af_index;
+	uint32_t freq_a = rds_decode_af(grp->data_c_msb, true);
+	uint32_t freq_b = rds_decode_af(grp->data_c_lsb, true);
+	
+	afi = &priv_state->handle.tmc.tuning.station[station_index].afi;
+	af_index = afi->af_index;
+	mapped_af_index = afi->mapped_af_index;
+
+	/* specific frequencies */
+	if (variant == 6) {
+		/* compare the new AFs to the stored ones, reset them to 0 if the AFs are
+		 * already known */
+		for (int i = 0; i < afi->af_size; i++) {
+			freq_a = (freq_a == afi->af[i]) ? 0 : freq_a;
+			freq_b = (freq_b == afi->af[i]) ? 0 : freq_b;
+		}
+		/* return early if there is nothing to do */
+		if (freq_a == 0 && freq_b == 0)
+			return false;
+
+		/* add the new AFs if they were previously unknown */
+		if (freq_a != 0) {
+			afi->af[af_index] = freq_a;
+			af_index = (af_index+1 < MAX_TMC_AF_CNT) ? af_index+1 : 0;
+			afi->af_size++; 
+		}
+		if (freq_b != 0) {
+			afi->af[af_index] = freq_b;
+			af_index = (af_index+1 < MAX_TMC_AF_CNT) ? af_index+1 : 0;
+			afi->af_size++; 
+		}
+		/* update the information in the handle */
+		afi->af_index = af_index;
+		if (afi->af_size >= MAX_TMC_AF_CNT) 
+			afi->af_size = MAX_TMC_AF_CNT;
+
+		return true;
+	}
+
+	/* mapped frequency pair */
+	else if (variant == 7) {
+		/* check the if there's already a frequency mapped to the new tuning
+		 * frequency, update the mapped frequency in this case */
+		for (int i = 0; i < afi->mapped_af_size; i++) {
+			if (freq_a == afi->mapped_af_tuning[i])
+				afi->mapped_af[i] = freq_b;
+				return true;
+		}
+		/* new pair is unknown, add it to the list */
+		if (freq_a != 0 && freq_b != 0) {
+			mapped_af_index = (mapped_af_index+1 >= MAX_TMC_AF_CNT) ? 0 : mapped_af_index + 1;
+			afi->mapped_af[mapped_af_index] = freq_b;
+			afi->mapped_af_tuning[mapped_af_index] = freq_a;
+			afi->mapped_af_size++; 
+		}
+		/* update the information in the handle */
+		afi->mapped_af_index = mapped_af_index;
+		if (afi->mapped_af_size >= MAX_TMC_AF_CNT) 
+			afi->mapped_af_size = MAX_TMC_AF_CNT;
+
+		return true;
+	}
+	return false;
+}
+
 /* adds one char of the ps name to temporal storage, the value is validated
  * if it is received twice in a row
  * @pos:	position of the char within the PS name (0..7)
@@ -543,6 +690,44 @@ static bool rds_add_ps(struct rds_private_state *priv_state, uint8_t pos, uint8_
 	return true;
 }
 
+/* checks if an entry for the given PI already exists and returns the index
+ * of that entry if so. Else it adds a new entry to the EON table and returns
+ * the index of the new field */
+static uint8_t rds_add_eon_entry(struct rds_private_state *priv_state, uint16_t pi)
+{
+	struct v4l2_rds *handle = &priv_state->handle;
+	uint8_t index = handle->rds_eon.index;
+	uint8_t size = handle->rds_eon.size;
+
+	/* check if there's an entry for the given PI key */
+	for (int i = 0; i < handle->rds_eon.size; i++) {
+		if (handle->rds_eon.eon[i].pi == pi) {
+			return i;
+		}
+	}
+	/* if the the maximum table size is reached, overwrite old
+	 * entries, starting at the oldest one = 0 */
+	handle->rds_eon.eon[index].pi = pi;
+	handle->rds_eon.eon[index].valid_fields |= V4L2_RDS_PI;
+	handle->rds_eon.index = (index+1 < MAX_EON_CNT) ? (index+1) : 0;
+	handle->rds_eon.size = (size+1 <= MAX_EON_CNT) ? (size+1) : MAX_EON_CNT;
+	return index;
+}
+
+/* checks if an entry for the given PI already exists */
+static bool rds_check_eon_entry(struct rds_private_state *priv_state, uint16_t pi)
+{
+	struct v4l2_rds *handle = &priv_state->handle;
+
+	/* check if there's an entry for the given PI key */
+	for (int i = 0; i <= handle->rds_eon.size; i++) {
+		if (handle->rds_eon.eon[i].pi == pi) {
+			return true;
+		}
+	}
+	return false;
+}
+
 /* group of functions to decode successfully received RDS groups into
  * easily accessible data fields
  *
@@ -790,6 +975,29 @@ static uint32_t rds_decode_group3(struct rds_private_state *priv_state)
 	return updated_fields;
 }
 
+/* decodes the RDS radio frequency representation into Hz
+ * @af: 8-bit AF value as transmitted in RDS groups
+ * @is_vhf: boolean value defining  which conversion table to use
+ * @return: frequency in Hz, 0 in case of wrong input values */
+static uint32_t rds_decode_af(uint8_t af, bool is_vhf) {
+	uint32_t freq = 0;
+
+	/* AF = 0 => "not to be used"
+	 * AF >= 205 => special meanings */
+	if (af == 0 || af >= 205)
+		return 0;
+
+	/* calculate the AF values in HZ */
+	if (is_vhf)
+		freq = 87500000 + af * 100000;
+	else if (freq <= 15)
+		freq = 152000 + af * 9000;
+	else
+		freq = 531000 + af * 9000;
+
+	return freq;
+}
+
 /* decodes the RDS date/time representation into a standard c representation
  * that can be used with c-library functions */
 static time_t rds_decode_mjd(const struct rds_private_state *priv_state)
@@ -880,7 +1088,6 @@ static uint32_t rds_decode_group4(struct rds_private_state *priv_state)
 	handle->time = rds_decode_mjd(priv_state);
 	updated_fields |= V4L2_RDS_TIME;
 	handle->valid_fields |= V4L2_RDS_TIME;
-	printf("\nLIB: time_t: %ld", handle->time);
 	return updated_fields;
 }
 
@@ -916,13 +1123,13 @@ static uint32_t rds_decode_group8(struct rds_private_state *priv_state)
 		!(grp->data_b_lsb & V4L2_TMC_TUNING_INFO)) {
 		return rds_decode_tmc_multi_group(priv_state);
 	}
-	/* -> tuning information message, defined for variants 4..9, submitted
-	 * in bits 0-3 of block 2 */
+	/* -> tuning information message, defined for variants 4..9,
+	 * submitted in bits 0-3 of block 2 */
 	tuning_variant = grp->data_b_lsb & 0x0f;
 	if ((grp->data_b_lsb & V4L2_TMC_TUNING_INFO) && tuning_variant >= 4 &&
 		tuning_variant <= 9) {
-		/* TODO: Implement tuning information decoding */
-		return 0;
+		priv_state->handle.valid_fields |= V4L2_RDS_TMC_TUNING;
+		return rds_decode_tmc_tuning(priv_state);
 	}
 
 	return 0;
@@ -981,6 +1188,121 @@ static uint32_t rds_decode_group10(struct rds_private_state *priv_state)
 	return updated_fields;
 }
 
+/* group 14: EON (Enhanced Other Network) information */
+static uint32_t rds_decode_group14(struct rds_private_state* priv_state)
+{
+	struct v4l2_rds *handle = &priv_state->handle;
+	struct v4l2_rds_group *grp = &priv_state->rds_group;
+	struct v4l2_rds_eon *eon_entry;
+	uint32_t updated_fields = 0;
+	uint16_t pi_on;
+	uint16_t lsf_on;
+	uint8_t variant_code;
+	uint8_t eon_index;
+	uint8_t pty_on;
+	bool tp_on, ta_on;
+	bool new_a = false, new_b = false;
+
+	if (grp->group_version != 'A')
+		return 0;
+
+	/* bits 0-3 of group b contain the variant code */
+	variant_code = grp->data_b_lsb & 0x0f;
+
+	/* group d contains the PI code of the ON (Other Network) */
+	pi_on = (grp->data_d_msb << 8) | grp->data_d_lsb;
+
+	/* bit 4 of group b contains the TP status of the ON*/
+	tp_on = grp->data_b_lsb & 0x10;
+	if (rds_check_eon_entry(priv_state, pi_on)) {
+		/* if there's an entry for this PI(ON) update the TP field */
+		eon_index = rds_add_eon_entry(priv_state, pi_on);
+		eon_entry = &handle->rds_eon.eon[eon_index];
+		eon_entry->tp = tp_on;
+		eon_entry->valid_fields |= V4L2_RDS_TP;
+		updated_fields |= V4L2_RDS_EON;
+	}
+
+	/* perform group variant dependent decoding */
+	if ((variant_code >=5 && variant_code <= 11) || variant_code >= 14) {
+		/* 5-9 = mapped FM frequencies -> unsupported
+		 * 10-11 = unallocated
+		 * 14 = PIN(ON) -> unsupported (unused RDS feature)
+		 * 15 = reserved for broadcasters use */
+		return updated_fields;
+	}
+	
+	/* retrieve the EON entry corresponding to the PI(ON) code or add a new
+	 * entry to the table if no entry exists */
+	eon_index = rds_add_eon_entry(priv_state, pi_on);
+	eon_entry = &handle->rds_eon.eon[eon_index];
+
+	/* PS Name */
+	if (variant_code < 4) {
+		eon_entry->ps[variant_code*2] = grp->data_c_msb;
+		eon_entry->ps[variant_code*2+1] = grp->data_c_lsb;
+		eon_entry->valid_fields |= V4L2_RDS_PS;
+		updated_fields |= V4L2_RDS_EON;
+	}
+	/* Alternative frequencies */
+	else if (variant_code == 4) {
+		uint8_t c_msb = grp->data_c_msb;
+		uint8_t c_lsb = grp->data_c_lsb;
+
+		/* 224..249: announcement of AF count (224=0, 249=25) */
+		if (c_msb >= 224 && c_msb <= 249)
+			eon_entry->af.announced_af = c_msb - 224;
+		/* check if the data represents an AF (for 1 =< val <= 204 the
+		 * value represents an AF) */
+		if (c_msb < 205)
+			new_a = rds_add_af_to_list(&eon_entry->af,
+					grp->data_c_msb, true);
+		if (c_lsb < 205)
+			new_b = rds_add_af_to_list(&eon_entry->af,
+					grp->data_c_lsb, true);
+		/* check if one of the frequencies was previously unknown */
+		if (new_a || new_b) {
+			eon_entry->valid_fields |= V4L2_RDS_AF;
+			updated_fields |= V4L2_RDS_EON;
+		}
+	}
+	/* Linkage information */
+	else if (variant_code == 12) {
+		/* group c contains the lsf code */
+		lsf_on = (grp->data_c_msb << 8) | grp->data_c_lsb;
+		/* check if the lsf code is already known */
+		new_a = (eon_entry->lsf == lsf_on);
+		if (new_a) {
+			eon_entry->lsf = lsf_on;
+			eon_entry->valid_fields |= V4L2_RDS_LSF;
+			updated_fields |= V4L2_RDS_EON;
+		}
+	}
+	/* PTY(ON) and TA(ON) */
+	else if (variant_code == 13) {
+		/* bits 15-10 of group c contain the PTY(ON) */
+		pty_on = grp->data_c_msb >> 3;
+		/* bit 0 of group c contains the TA code */
+		ta_on = grp->data_c_lsb & 0x01;
+		/* check if the data is new */
+		new_a = (eon_entry->pty == pty_on);
+		if (new_a) {
+			eon_entry->pty = pty_on;
+			eon_entry->valid_fields |= V4L2_RDS_PTY;
+		}
+		new_b = (eon_entry->ta == ta_on);
+		eon_entry->ta = ta_on;
+		eon_entry->valid_fields |= V4L2_RDS_TA;
+		if (new_a || new_b)
+			updated_fields |= V4L2_RDS_EON;
+	}
+	/* set valid field for EON data, if EON table contains entries */
+	if (handle->rds_eon.size > 0)
+		handle->valid_fields |= V4L2_RDS_EON;
+
+	return updated_fields;
+}
+
 typedef uint32_t (*decode_group_func)(struct rds_private_state *);
 
 /* array of function pointers to contain all group specific decoding functions */
@@ -992,6 +1314,7 @@ static const decode_group_func decode_group[16] = {
 	[4] = rds_decode_group4,
 	[8] = rds_decode_group8,
 	[10] = rds_decode_group10,
+	[14] = rds_decode_group14
 };
 
 static uint32_t rds_decode_group(struct rds_private_state *priv_state)
@@ -1068,7 +1391,7 @@ uint32_t v4l2_rds_add(struct v4l2_rds *handle, struct v4l2_rds_data *rds_data)
 		if (block_id == 0) {
 			*decode_state = RDS_A_RECEIVED;
 			/* begin reception of a new data group, reset raw buffer to 0 */
-			memset(rds_data_raw, 0, sizeof(rds_data_raw));
+			memset(rds_data_raw, 0, sizeof(*rds_data_raw));
 			rds_data_raw[0] = *rds_data;
 		} else {
 			/* ignore block if it is not the first block of a group */
-- 
1.7.10.4


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [RFC PATCHv2 2/3] rds-ctl: support RDS-EON and TMC-tuning info
  2013-06-04 19:15 ` [RFC PATCHv2 1/3] libv4l2rds: support RDS-EON and TMC-tuning info Konke Radlow
@ 2013-06-04 19:15   ` Konke Radlow
  2013-06-04 19:15   ` [RFC PATCHv2 3/3] libv4l2rds.c: moving functions to get rid of declarations Signed-off-by: Konke Radlow <koradlow@gmail.com> Konke Radlow
  1 sibling, 0 replies; 5+ messages in thread
From: Konke Radlow @ 2013-06-04 19:15 UTC (permalink / raw)
  To: linux-media; +Cc: hverkuil, hdegoede

Signed-off-by: Konke Radlow <koradlow@gmail.com>

rds-ctl.cpp: added functionality to print RDS-EON information

Signed-off-by: Konke Radlow <koradlow@gmail.com>

rds-ctl.cpp: added functionality to print RDS-TMC tuning information

Signed-off-by: Konke Radlow <koradlow@gmail.com>

rds-ctl.cpp: clarify option description, change
trigger condition for printing TMC Tuning information

Signed-off-by: Konke Radlow <koradlow@gmail.com>
---
 utils/rds-ctl/rds-ctl.cpp |   59 +++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 57 insertions(+), 2 deletions(-)

diff --git a/utils/rds-ctl/rds-ctl.cpp b/utils/rds-ctl/rds-ctl.cpp
index 191cfee..d894ec1 100644
--- a/utils/rds-ctl/rds-ctl.cpp
+++ b/utils/rds-ctl/rds-ctl.cpp
@@ -130,7 +130,7 @@ static void usage_hint(void)
 static void usage_common(void)
 {
 	printf("\nGeneral/Common options:\n"
-	       "  --all              display all information available\n"
+	       "  --all              display all device information available\n"
 	       "  -D, --info         show driver info [VIDIOC_QUERYCAP]\n"
 	       "  -d, --device=<dev> use device <dev>\n"
 	       "                     if <dev> is a single digit, then /dev/radio<dev> is used\n"
@@ -172,7 +172,7 @@ static void usage_rds(void)
 	       "                     <default>: 5000 ms\n"
 	       "  --print-block      prints all valid RDS fields, whenever a value is updated\n"
 	       "                     instead of printing only updated values\n"
-	       "  --tmc              enables decoding of TMC (Traffic Message Channel) data\n"
+	       "  --tmc              print information about TMC (Traffic Message Channel) messages\n"
 	       "  --silent           only set the result code, do not print any messages\n"
 	       "  --verbose          turn on verbose mode - every received RDS group\n"
 	       "                     will be printed\n"
@@ -517,6 +517,30 @@ static void print_rds_tmc(const struct v4l2_rds *handle, uint32_t updated_fields
 	}
 }
 
+static void print_rds_tmc_tuning(const struct v4l2_rds *handle, uint32_t updated_fields)
+{
+	const struct v4l2_tmc_tuning *tuning = &handle->tmc.tuning;
+	const struct v4l2_tmc_station *station;
+	
+	if (updated_fields & V4L2_RDS_TMC_TUNING) {
+		printf("\nTMC Service provider: %s, %u alternative stations\n", handle->tmc.spn, tuning->station_cnt);
+		for (int i = 0; i < tuning->station_cnt; i++) {
+			station = &tuning->station[i];
+			printf("PI(ON %02u) = %04x, AFs: %u, mapped AFs: %u \n", i, station->pi,
+					station->afi.af_size, station->afi.mapped_af_size);
+			for (int j = 0; j < station->afi.af_size; j++)
+				printf("        AF%02d: %.1fMHz\n", j, station->afi.af[j] / 1000000.0);
+			for (int k = 0; k < station->afi.mapped_af_size; k++)
+				printf("        m_AF%02d: %.1fMHz => %.1fMHz\n", k,
+						station->afi.mapped_af_tuning[k] / 1000000.0,
+						station->afi.mapped_af[k] / 1000000.0);
+			if (station->ltn != 0 || station->msg != 0 || station-> sid != 0)
+				printf("        ltn: %02x, msg: %02x, sid: %02x\n", station->ltn,
+						station->msg, station->sid);
+		}
+	}
+}
+
 static void print_rds_statistics(const struct v4l2_rds_statistics *statistics)
 {
 	printf("\n\nRDS Statistics: \n");
@@ -557,6 +581,33 @@ static void print_rds_af(const struct v4l2_rds_af_set *af_set)
 	}
 }
 
+static void print_rds_eon(const struct v4l2_rds_eon_set *eon_set)
+{
+	int counter = 0;
+
+	printf("\n\nEnhanced Other Network information: %u channels", eon_set->size);
+	for (int i = 0; i < eon_set->size; i++, counter++) {
+		if (eon_set->eon[i].valid_fields & V4L2_RDS_PI)
+			printf("\nPI(ON %02i) =  %04x", i, eon_set->eon[i].pi);
+		if (eon_set->eon[i].valid_fields & V4L2_RDS_PS)
+			printf("\nPS(ON %02i) =  %s", i, eon_set->eon[i].ps);
+		if (eon_set->eon[i].valid_fields & V4L2_RDS_PTY)
+			printf("\nPTY(ON %02i) =  %0u", i, eon_set->eon[i].pty);
+		if (eon_set->eon[i].valid_fields & V4L2_RDS_LSF)
+			printf("\nLSF(ON %02i) =  %0u", i, eon_set->eon[i].lsf);
+		if (eon_set->eon[i].valid_fields & V4L2_RDS_AF)
+			printf("\nPTY(ON %02i) =  %0u", i, eon_set->eon[i].pty);
+		if (eon_set->eon[i].valid_fields & V4L2_RDS_TP)
+			printf("\nTP(ON %02i): %s", i, eon_set->eon[i].tp? "yes":"no");
+		if (eon_set->eon[i].valid_fields & V4L2_RDS_TA)
+			printf("\nTA(ON %02i): %s", i, eon_set->eon[i].tp? "yes":"no");
+		if (eon_set->eon[i].valid_fields & V4L2_RDS_AF) {
+			printf("\nAF(ON %02i): size=%i", i, eon_set->eon[i].af.size);
+			print_rds_af(&(eon_set->eon[i].af));
+		}
+	}
+}
+
 static void print_rds_pi(const struct v4l2_rds *handle)
 {
 	printf("\nArea Coverage: %s", v4l2_rds_get_coverage_str(handle));
@@ -614,6 +665,8 @@ static void print_rds_data(const struct v4l2_rds *handle, uint32_t updated_field
 	}
 	if (updated_fields & V4L2_RDS_AF && handle->valid_fields & V4L2_RDS_AF)
 		print_rds_af(&handle->rds_af);
+	if (updated_fields & V4L2_RDS_TMC_TUNING && handle->valid_fields & V4L2_RDS_TMC_TUNING);
+		print_rds_tmc_tuning(handle, updated_fields);
 	if (params.options[OptPrintBlock])
 		printf("\n");
 	if (params.options[OptTMC])
@@ -669,6 +722,8 @@ static void read_rds_from_fd(const int fd)
 
 	/* try to receive and decode RDS data */
 	read_rds(rds_handle, fd, params.wait_limit);
+	if (rds_handle->valid_fields & V4L2_RDS_EON)
+		print_rds_eon(&rds_handle->rds_eon);
 	print_rds_statistics(&rds_handle->rds_statistics);
 
 	v4l2_rds_destroy(rds_handle);
-- 
1.7.10.4


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [RFC PATCHv2 3/3] libv4l2rds.c: moving functions to get rid of declarations Signed-off-by: Konke Radlow <koradlow@gmail.com>
  2013-06-04 19:15 ` [RFC PATCHv2 1/3] libv4l2rds: support RDS-EON and TMC-tuning info Konke Radlow
  2013-06-04 19:15   ` [RFC PATCHv2 2/3] rds-ctl: " Konke Radlow
@ 2013-06-04 19:15   ` Konke Radlow
  1 sibling, 0 replies; 5+ messages in thread
From: Konke Radlow @ 2013-06-04 19:15 UTC (permalink / raw)
  To: linux-media; +Cc: hverkuil, hdegoede

Signed-off-by: Konke Radlow <koradlow@gmail.com>
---
 lib/libv4l2rds/libv4l2rds.c |  243 +++++++++++++++++++++----------------------
 1 file changed, 120 insertions(+), 123 deletions(-)

diff --git a/lib/libv4l2rds/libv4l2rds.c b/lib/libv4l2rds/libv4l2rds.c
index 28b78ce..333bf95 100644
--- a/lib/libv4l2rds/libv4l2rds.c
+++ b/lib/libv4l2rds/libv4l2rds.c
@@ -92,11 +92,6 @@ enum rds_state {
 	RDS_C_RECEIVED,
 };
 
-/* function declarations to prevent the need to move large code blocks */
-static int rds_add_tmc_station(struct rds_private_state *priv_state, uint16_t pi);
-static uint32_t rds_decode_af(uint8_t af, bool is_vhf);
-static bool rds_add_tmc_af(struct rds_private_state *priv_state);
-
 static inline uint8_t set_bit(uint8_t input, uint8_t bitmask, bool bitvalue)
 {
 	return bitvalue ? input | bitmask : input & ~bitmask;
@@ -201,6 +196,29 @@ static void rds_decode_d(struct rds_private_state *priv_state, struct v4l2_rds_d
 	grp->data_d_lsb = rds_data->lsb;
 }
 
+/* decodes the RDS radio frequency representation into Hz
+ * @af: 8-bit AF value as transmitted in RDS groups
+ * @is_vhf: boolean value defining  which conversion table to use
+ * @return: frequency in Hz, 0 in case of wrong input values */
+static uint32_t rds_decode_af(uint8_t af, bool is_vhf) {
+	uint32_t freq = 0;
+
+	/* AF = 0 => "not to be used"
+	 * AF >= 205 => special meanings */
+	if (af == 0 || af >= 205)
+		return 0;
+
+	/* calculate the AF values in HZ */
+	if (is_vhf)
+		freq = 87500000 + af * 100000;
+	else if (freq <= 15)
+		freq = 152000 + af * 9000;
+	else
+		freq = 531000 + af * 9000;
+
+	return freq;
+}
+
 /* compare two rds-groups for equality */
 /* used for decoding RDS-TMC, which has the requirement that the same group
  * is at least received twice before it is accepted */
@@ -224,6 +242,103 @@ static bool rds_compare_group(const struct v4l2_rds_group *a,
 	return true;
 }
 
+/* checks if an entry for the given PI already exists and returns the index
+ * of that entry if so. Else it adds a new entry to the TMC-Tuning table and returns
+ * the index of the new field */
+static int rds_add_tmc_station(struct rds_private_state *priv_state, uint16_t pi)
+{
+	struct v4l2_tmc_tuning *tuning = &priv_state->handle.tmc.tuning;
+	uint8_t index = tuning->index;
+	uint8_t size = tuning->station_cnt;
+
+	/* check if there's an entry for the given PI key */
+	for (int i = 0; i < tuning->station_cnt; i++) {
+		if (tuning->station[i].pi == pi) {
+			return i;
+		}
+	}
+	/* if the the maximum table size is reached, overwrite old
+	 * entries, starting at the oldest one = 0 */
+	tuning->station[index].pi = pi;
+	tuning->index = (index+1 < MAX_TMC_ALT_STATIONS) ? (index+1) : 0;
+	tuning->station_cnt = (size+1 <= MAX_TMC_ALT_STATIONS) ? (size+1) : MAX_TMC_ALT_STATIONS;
+	return index;
+}
+
+/* tries to add new AFs to the relevant entry in the list of RDS-TMC providers */
+static bool rds_add_tmc_af(struct rds_private_state *priv_state)
+{
+	struct v4l2_rds_group *grp = &priv_state->rds_group;
+	struct v4l2_tmc_alt_freq *afi;
+	uint16_t pi_on = grp->data_d_msb << 8 | grp->data_d_lsb;
+	uint8_t variant = grp->data_b_lsb & 0x0f;
+	uint8_t station_index = rds_add_tmc_station(priv_state, pi_on);
+	uint8_t af_index;
+	uint8_t mapped_af_index;
+	uint32_t freq_a = rds_decode_af(grp->data_c_msb, true);
+	uint32_t freq_b = rds_decode_af(grp->data_c_lsb, true);
+
+	afi = &priv_state->handle.tmc.tuning.station[station_index].afi;
+	af_index = afi->af_index;
+	mapped_af_index = afi->mapped_af_index;
+
+	/* specific frequencies */
+	if (variant == 6) {
+		/* compare the new AFs to the stored ones, reset them to 0 if the AFs are
+		 * already known */
+		for (int i = 0; i < afi->af_size; i++) {
+			freq_a = (freq_a == afi->af[i]) ? 0 : freq_a;
+			freq_b = (freq_b == afi->af[i]) ? 0 : freq_b;
+		}
+		/* return early if there is nothing to do */
+		if (freq_a == 0 && freq_b == 0)
+			return false;
+
+		/* add the new AFs if they were previously unknown */
+		if (freq_a != 0) {
+			afi->af[af_index] = freq_a;
+			af_index = (af_index+1 < MAX_TMC_AF_CNT) ? af_index+1 : 0;
+			afi->af_size++;
+		}
+		if (freq_b != 0) {
+			afi->af[af_index] = freq_b;
+			af_index = (af_index+1 < MAX_TMC_AF_CNT) ? af_index+1 : 0;
+			afi->af_size++;
+		}
+		/* update the information in the handle */
+		afi->af_index = af_index;
+		if (afi->af_size >= MAX_TMC_AF_CNT)
+			afi->af_size = MAX_TMC_AF_CNT;
+
+		return true;
+	}
+
+	/* mapped frequency pair */
+	else if (variant == 7) {
+		/* check the if there's already a frequency mapped to the new tuning
+		 * frequency, update the mapped frequency in this case */
+		for (int i = 0; i < afi->mapped_af_size; i++) {
+			if (freq_a == afi->mapped_af_tuning[i])
+				afi->mapped_af[i] = freq_b;
+				return true;
+		}
+		/* new pair is unknown, add it to the list */
+		if (freq_a != 0 && freq_b != 0) {
+			mapped_af_index = (mapped_af_index+1 >= MAX_TMC_AF_CNT) ? 0 : mapped_af_index + 1;
+			afi->mapped_af[mapped_af_index] = freq_b;
+			afi->mapped_af_tuning[mapped_af_index] = freq_a;
+			afi->mapped_af_size++;
+		}
+		/* update the information in the handle */
+		afi->mapped_af_index = mapped_af_index;
+		if (afi->mapped_af_size >= MAX_TMC_AF_CNT)
+			afi->mapped_af_size = MAX_TMC_AF_CNT;
+
+		return true;
+	}
+	return false;
+}
+
 /* decode additional information of a TMC message into handy representation */
 /* the additional information of TMC messages is submitted in (up to) 4 blocks of
  * 28 bits each, which are to be treated as a consecutive bit-array. This data
@@ -572,102 +687,7 @@ static bool rds_add_af(struct rds_private_state *priv_state)
 	return updated_af;
 }
 
-/* checks if an entry for the given PI already exists and returns the index
- * of that entry if so. Else it adds a new entry to the TMC-Tuning table and returns
- * the index of the new field */
-static int rds_add_tmc_station(struct rds_private_state *priv_state, uint16_t pi)
-{
-	struct v4l2_tmc_tuning *tuning = &priv_state->handle.tmc.tuning;
-	uint8_t index = tuning->index;
-	uint8_t size = tuning->station_cnt;
-	
-	/* check if there's an entry for the given PI key */
-	for (int i = 0; i < tuning->station_cnt; i++) {
-		if (tuning->station[i].pi == pi) {
-			return i;
-		}
-	}
-	/* if the the maximum table size is reached, overwrite old
-	 * entries, starting at the oldest one = 0 */
-	tuning->station[index].pi = pi;
-	tuning->index = (index+1 < MAX_TMC_ALT_STATIONS) ? (index+1) : 0;
-	tuning->station_cnt = (size+1 <= MAX_TMC_ALT_STATIONS) ? (size+1) : MAX_TMC_ALT_STATIONS;
-	return index;
-}
-
-/* tries to add new AFs to the relevant entry in the list of RDS-TMC providers */
-static bool rds_add_tmc_af(struct rds_private_state *priv_state)
-{
-	struct v4l2_rds_group *grp = &priv_state->rds_group;
-	struct v4l2_tmc_alt_freq *afi;
-	uint16_t pi_on = grp->data_d_msb << 8 | grp->data_d_lsb;
-	uint8_t variant = grp->data_b_lsb & 0x0f;
-	uint8_t station_index = rds_add_tmc_station(priv_state, pi_on);
-	uint8_t af_index;
-	uint8_t mapped_af_index;
-	uint32_t freq_a = rds_decode_af(grp->data_c_msb, true);
-	uint32_t freq_b = rds_decode_af(grp->data_c_lsb, true);
-	
-	afi = &priv_state->handle.tmc.tuning.station[station_index].afi;
-	af_index = afi->af_index;
-	mapped_af_index = afi->mapped_af_index;
-
-	/* specific frequencies */
-	if (variant == 6) {
-		/* compare the new AFs to the stored ones, reset them to 0 if the AFs are
-		 * already known */
-		for (int i = 0; i < afi->af_size; i++) {
-			freq_a = (freq_a == afi->af[i]) ? 0 : freq_a;
-			freq_b = (freq_b == afi->af[i]) ? 0 : freq_b;
-		}
-		/* return early if there is nothing to do */
-		if (freq_a == 0 && freq_b == 0)
-			return false;
-
-		/* add the new AFs if they were previously unknown */
-		if (freq_a != 0) {
-			afi->af[af_index] = freq_a;
-			af_index = (af_index+1 < MAX_TMC_AF_CNT) ? af_index+1 : 0;
-			afi->af_size++; 
-		}
-		if (freq_b != 0) {
-			afi->af[af_index] = freq_b;
-			af_index = (af_index+1 < MAX_TMC_AF_CNT) ? af_index+1 : 0;
-			afi->af_size++; 
-		}
-		/* update the information in the handle */
-		afi->af_index = af_index;
-		if (afi->af_size >= MAX_TMC_AF_CNT) 
-			afi->af_size = MAX_TMC_AF_CNT;
-
-		return true;
-	}
 
-	/* mapped frequency pair */
-	else if (variant == 7) {
-		/* check the if there's already a frequency mapped to the new tuning
-		 * frequency, update the mapped frequency in this case */
-		for (int i = 0; i < afi->mapped_af_size; i++) {
-			if (freq_a == afi->mapped_af_tuning[i])
-				afi->mapped_af[i] = freq_b;
-				return true;
-		}
-		/* new pair is unknown, add it to the list */
-		if (freq_a != 0 && freq_b != 0) {
-			mapped_af_index = (mapped_af_index+1 >= MAX_TMC_AF_CNT) ? 0 : mapped_af_index + 1;
-			afi->mapped_af[mapped_af_index] = freq_b;
-			afi->mapped_af_tuning[mapped_af_index] = freq_a;
-			afi->mapped_af_size++; 
-		}
-		/* update the information in the handle */
-		afi->mapped_af_index = mapped_af_index;
-		if (afi->mapped_af_size >= MAX_TMC_AF_CNT) 
-			afi->mapped_af_size = MAX_TMC_AF_CNT;
-
-		return true;
-	}
-	return false;
-}
 
 /* adds one char of the ps name to temporal storage, the value is validated
  * if it is received twice in a row
@@ -975,29 +995,6 @@ static uint32_t rds_decode_group3(struct rds_private_state *priv_state)
 	return updated_fields;
 }
 
-/* decodes the RDS radio frequency representation into Hz
- * @af: 8-bit AF value as transmitted in RDS groups
- * @is_vhf: boolean value defining  which conversion table to use
- * @return: frequency in Hz, 0 in case of wrong input values */
-static uint32_t rds_decode_af(uint8_t af, bool is_vhf) {
-	uint32_t freq = 0;
-
-	/* AF = 0 => "not to be used"
-	 * AF >= 205 => special meanings */
-	if (af == 0 || af >= 205)
-		return 0;
-
-	/* calculate the AF values in HZ */
-	if (is_vhf)
-		freq = 87500000 + af * 100000;
-	else if (freq <= 15)
-		freq = 152000 + af * 9000;
-	else
-		freq = 531000 + af * 9000;
-
-	return freq;
-}
-
 /* decodes the RDS date/time representation into a standard c representation
  * that can be used with c-library functions */
 static time_t rds_decode_mjd(const struct rds_private_state *priv_state)
-- 
1.7.10.4


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [RFC PATCHv2 0/3] libv4l2rds: add support for RDS-EON and TMC-tuning decoding
  2013-06-04 19:15 [RFC PATCHv2 0/3] libv4l2rds: add support for RDS-EON and TMC-tuning decoding Konke Radlow
  2013-06-04 19:15 ` [RFC PATCHv2 1/3] libv4l2rds: support RDS-EON and TMC-tuning info Konke Radlow
@ 2013-06-07  8:27 ` Hans Verkuil
  1 sibling, 0 replies; 5+ messages in thread
From: Hans Verkuil @ 2013-06-07  8:27 UTC (permalink / raw)
  To: Konke Radlow; +Cc: linux-media, hdegoede

Hi Konke,

On Tue June 4 2013 21:15:00 Konke Radlow wrote:
> This patch series is based on the commments to:
> 
> [RFC PATCH 0/4] libv4l2rds: support for decoding RDS tuning information
> [RFC PATCH 1/4] libv4l2rds: added support to decode RDS-EON information
> [RFC PATCH 2/4] rds-ctl.cpp: added functionality to print RDS-EON information
> [RFC PATCH 3/4] libv4l2rds: added support to decode RDS-TMC tuning information
> [RFC PATCH 4/4] rds-ctl.cpp: added functionality to print RDS-TMC tuning information
> 
> The proposed changes have been integrated and the patches (1, 3) and (2, 4) have been merged
> into one unit.

Thank you for working on this. I've committed these patches. It's really nice
to have full support for this.

Regards,

	Hans

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2013-06-07  8:27 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-06-04 19:15 [RFC PATCHv2 0/3] libv4l2rds: add support for RDS-EON and TMC-tuning decoding Konke Radlow
2013-06-04 19:15 ` [RFC PATCHv2 1/3] libv4l2rds: support RDS-EON and TMC-tuning info Konke Radlow
2013-06-04 19:15   ` [RFC PATCHv2 2/3] rds-ctl: " Konke Radlow
2013-06-04 19:15   ` [RFC PATCHv2 3/3] libv4l2rds.c: moving functions to get rid of declarations Signed-off-by: Konke Radlow <koradlow@gmail.com> Konke Radlow
2013-06-07  8:27 ` [RFC PATCHv2 0/3] libv4l2rds: add support for RDS-EON and TMC-tuning decoding Hans Verkuil

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).