linux-media.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 1/2] vivid: SDR cap: add control for FM deviation
@ 2015-09-01 23:04 Antti Palosaari
  2015-09-01 23:04 ` [PATCH 2/2] vivid: sdr cap: few enhancements Antti Palosaari
  0 siblings, 1 reply; 2+ messages in thread
From: Antti Palosaari @ 2015-09-01 23:04 UTC (permalink / raw)
  To: linux-media; +Cc: Hans Verkuil, Antti Palosaari

Add user control to adjust generated FM deviation.
Default it to 75kHz like public FM radio broadcast.

Signed-off-by: Antti Palosaari <crope@iki.fi>
---
 drivers/media/platform/vivid/vivid-core.h    |  1 +
 drivers/media/platform/vivid/vivid-ctrls.c   | 37 +++++++++++++++++++++++++++-
 drivers/media/platform/vivid/vivid-sdr-cap.c |  6 ++++-
 3 files changed, 42 insertions(+), 2 deletions(-)

diff --git a/drivers/media/platform/vivid/vivid-core.h b/drivers/media/platform/vivid/vivid-core.h
index c72349c..289640c 100644
--- a/drivers/media/platform/vivid/vivid-core.h
+++ b/drivers/media/platform/vivid/vivid-core.h
@@ -451,6 +451,7 @@ struct vivid_dev {
 	unsigned			sdr_buffersize;
 	unsigned			sdr_adc_freq;
 	unsigned			sdr_fm_freq;
+	unsigned			sdr_fm_deviation;
 	int				sdr_fixp_src_phase;
 	int				sdr_fixp_mod_phase;
 
diff --git a/drivers/media/platform/vivid/vivid-ctrls.c b/drivers/media/platform/vivid/vivid-ctrls.c
index 339c8b7..29834fa 100644
--- a/drivers/media/platform/vivid/vivid-ctrls.c
+++ b/drivers/media/platform/vivid/vivid-ctrls.c
@@ -99,6 +99,7 @@
 
 #define VIVID_CID_RADIO_TX_RDS_BLOCKIO	(VIVID_CID_VIVID_BASE + 94)
 
+#define VIVID_CID_SDR_CAP_FM_DEVIATION	(VIVID_CID_VIVID_BASE + 110)
 
 /* General User Controls */
 
@@ -1257,6 +1258,36 @@ static const struct v4l2_ctrl_config vivid_ctrl_radio_tx_rds_blockio = {
 };
 
 
+/* SDR Capture Controls */
+
+static int vivid_sdr_cap_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct vivid_dev *dev = container_of(ctrl->handler, struct vivid_dev, ctrl_hdl_sdr_cap);
+
+	switch (ctrl->id) {
+	case VIVID_CID_SDR_CAP_FM_DEVIATION:
+		dev->sdr_fm_deviation = ctrl->val;
+		break;
+	}
+	return 0;
+}
+
+static const struct v4l2_ctrl_ops vivid_sdr_cap_ctrl_ops = {
+	.s_ctrl = vivid_sdr_cap_s_ctrl,
+};
+
+static const struct v4l2_ctrl_config vivid_ctrl_sdr_cap_fm_deviation = {
+	.ops = &vivid_sdr_cap_ctrl_ops,
+	.id = VIVID_CID_SDR_CAP_FM_DEVIATION,
+	.name = "FM Deviation",
+	.type = V4L2_CTRL_TYPE_INTEGER,
+	.min =    100,
+	.max = 200000,
+	.def =  75000,
+	.step =     1,
+};
+
+
 static const struct v4l2_ctrl_config vivid_ctrl_class = {
 	.ops = &vivid_user_gen_ctrl_ops,
 	.flags = V4L2_CTRL_FLAG_READ_ONLY | V4L2_CTRL_FLAG_WRITE_ONLY,
@@ -1314,7 +1345,7 @@ int vivid_create_controls(struct vivid_dev *dev, bool show_ccs_cap,
 	v4l2_ctrl_new_custom(hdl_radio_rx, &vivid_ctrl_class, NULL);
 	v4l2_ctrl_handler_init(hdl_radio_tx, 17);
 	v4l2_ctrl_new_custom(hdl_radio_tx, &vivid_ctrl_class, NULL);
-	v4l2_ctrl_handler_init(hdl_sdr_cap, 18);
+	v4l2_ctrl_handler_init(hdl_sdr_cap, 19);
 	v4l2_ctrl_new_custom(hdl_sdr_cap, &vivid_ctrl_class, NULL);
 
 	/* User Controls */
@@ -1545,6 +1576,10 @@ int vivid_create_controls(struct vivid_dev *dev, bool show_ccs_cap,
 			&vivid_radio_tx_ctrl_ops,
 			V4L2_CID_RDS_TX_MUSIC_SPEECH, 0, 1, 1, 1);
 	}
+	if (dev->has_sdr_cap) {
+		v4l2_ctrl_new_custom(hdl_sdr_cap,
+			&vivid_ctrl_sdr_cap_fm_deviation, NULL);
+	}
 	if (hdl_user_gen->error)
 		return hdl_user_gen->error;
 	if (hdl_user_vid->error)
diff --git a/drivers/media/platform/vivid/vivid-sdr-cap.c b/drivers/media/platform/vivid/vivid-sdr-cap.c
index d2f2188..c36b3f5 100644
--- a/drivers/media/platform/vivid/vivid-sdr-cap.c
+++ b/drivers/media/platform/vivid/vivid-sdr-cap.c
@@ -22,6 +22,7 @@
 #include <linux/delay.h>
 #include <linux/kthread.h>
 #include <linux/freezer.h>
+#include <linux/math64.h>
 #include <linux/videodev2.h>
 #include <linux/v4l2-dv-timings.h>
 #include <media/v4l2-common.h>
@@ -488,12 +489,14 @@ int vidioc_try_fmt_sdr_cap(struct file *file, void *fh, struct v4l2_format *f)
 #define FIXP_N    (15)
 #define FIXP_FRAC (1 << FIXP_N)
 #define FIXP_2PI  ((int)(2 * 3.141592653589 * FIXP_FRAC))
+#define M_100000PI (3.14159 * 100000)
 
 void vivid_sdr_cap_process(struct vivid_dev *dev, struct vivid_buffer *buf)
 {
 	u8 *vbuf = vb2_plane_vaddr(&buf->vb, 0);
 	unsigned long i;
 	unsigned long plane_size = vb2_plane_size(&buf->vb, 0);
+	s64 s64tmp;
 	s32 src_phase_step;
 	s32 mod_phase_step;
 	s32 fixp_i;
@@ -515,7 +518,8 @@ void vivid_sdr_cap_process(struct vivid_dev *dev, struct vivid_buffer *buf)
 						FIXP_2PI) >> (31 - FIXP_N);
 
 		dev->sdr_fixp_src_phase += src_phase_step;
-		dev->sdr_fixp_mod_phase += mod_phase_step / 4;
+		s64tmp = (s64) mod_phase_step * dev->sdr_fm_deviation;
+		dev->sdr_fixp_mod_phase += div_s64(s64tmp, M_100000PI);
 
 		/*
 		 * Transfer phases to [0 / 2xPI] in order to avoid variable
-- 
http://palosaari.fi/


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

* [PATCH 2/2] vivid: sdr cap: few enhancements
  2015-09-01 23:04 [PATCH 1/2] vivid: SDR cap: add control for FM deviation Antti Palosaari
@ 2015-09-01 23:04 ` Antti Palosaari
  0 siblings, 0 replies; 2+ messages in thread
From: Antti Palosaari @ 2015-09-01 23:04 UTC (permalink / raw)
  To: linux-media; +Cc: Hans Verkuil, Antti Palosaari

* Constify struct

* Fix comments

* Fix alignment

* Use modulus to transfer phase angles

* Correct float [-1.0, +1.0] to s8 [-128, 127] conversion

Signed-off-by: Antti Palosaari <crope@iki.fi>
---
 drivers/media/platform/vivid/vivid-sdr-cap.c | 31 +++++++++++-----------------
 1 file changed, 12 insertions(+), 19 deletions(-)

diff --git a/drivers/media/platform/vivid/vivid-sdr-cap.c b/drivers/media/platform/vivid/vivid-sdr-cap.c
index c36b3f5..fcbf498 100644
--- a/drivers/media/platform/vivid/vivid-sdr-cap.c
+++ b/drivers/media/platform/vivid/vivid-sdr-cap.c
@@ -41,7 +41,7 @@ struct vivid_format {
 };
 
 /* format descriptions for capture and preview */
-static struct vivid_format formats[] = {
+static const struct vivid_format formats[] = {
 	{
 		.pixelformat	= V4L2_SDR_FMT_CU8,
 		.buffersize	= SDR_CAP_SAMPLES_PER_BUF * 2,
@@ -502,16 +502,10 @@ void vivid_sdr_cap_process(struct vivid_dev *dev, struct vivid_buffer *buf)
 	s32 fixp_i;
 	s32 fixp_q;
 
-	/*
-	 * TODO: Generated beep tone goes very crackly when sample rate is
-	 * increased to ~1Msps or more. That is because of huge rounding error
-	 * of phase angle caused by used cosine implementation.
-	 */
-
 	/* calculate phase step */
 	#define BEEP_FREQ 1000 /* 1kHz beep */
 	src_phase_step = DIV_ROUND_CLOSEST(FIXP_2PI * BEEP_FREQ,
-			dev->sdr_adc_freq);
+					   dev->sdr_adc_freq);
 
 	for (i = 0; i < plane_size; i += 2) {
 		mod_phase_step = fixp_cos32_rad(dev->sdr_fixp_src_phase,
@@ -522,17 +516,15 @@ void vivid_sdr_cap_process(struct vivid_dev *dev, struct vivid_buffer *buf)
 		dev->sdr_fixp_mod_phase += div_s64(s64tmp, M_100000PI);
 
 		/*
-		 * Transfer phases to [0 / 2xPI] in order to avoid variable
+		 * Transfer phase agle to [0, 2xPI] in order to avoid variable
 		 * overflow and make it suitable for cosine implementation
 		 * used, which does not support negative angles.
 		 */
-		while (dev->sdr_fixp_mod_phase < FIXP_2PI)
-			dev->sdr_fixp_mod_phase += FIXP_2PI;
-		while (dev->sdr_fixp_mod_phase > FIXP_2PI)
-			dev->sdr_fixp_mod_phase -= FIXP_2PI;
+		dev->sdr_fixp_src_phase %= FIXP_2PI;
+		dev->sdr_fixp_mod_phase %= FIXP_2PI;
 
-		while (dev->sdr_fixp_src_phase > FIXP_2PI)
-			dev->sdr_fixp_src_phase -= FIXP_2PI;
+		if (dev->sdr_fixp_mod_phase < 0)
+			dev->sdr_fixp_mod_phase += FIXP_2PI;
 
 		fixp_i = fixp_cos32_rad(dev->sdr_fixp_mod_phase, FIXP_2PI);
 		fixp_q = fixp_sin32_rad(dev->sdr_fixp_mod_phase, FIXP_2PI);
@@ -544,7 +536,7 @@ void vivid_sdr_cap_process(struct vivid_dev *dev, struct vivid_buffer *buf)
 
 		switch (dev->sdr_pixelformat) {
 		case V4L2_SDR_FMT_CU8:
-			/* convert 'fixp float' to u8 */
+			/* convert 'fixp float' to u8 [0, +255] */
 			/* u8 = X * 127.5 + 127.5; X is float [-1.0, +1.0] */
 			fixp_i = fixp_i * 1275 + FIXP_FRAC * 1275;
 			fixp_q = fixp_q * 1275 + FIXP_FRAC * 1275;
@@ -552,9 +544,10 @@ void vivid_sdr_cap_process(struct vivid_dev *dev, struct vivid_buffer *buf)
 			*vbuf++ = DIV_ROUND_CLOSEST(fixp_q, FIXP_FRAC * 10);
 			break;
 		case V4L2_SDR_FMT_CS8:
-			/* convert 'fixp float' to s8 */
-			fixp_i = fixp_i * 1275;
-			fixp_q = fixp_q * 1275;
+			/* convert 'fixp float' to s8 [-128, +127] */
+			/* s8 = X * 127.5 - 0.5; X is float [-1.0, +1.0] */
+			fixp_i = fixp_i * 1275 - FIXP_FRAC * 5;
+			fixp_q = fixp_q * 1275 - FIXP_FRAC * 5;
 			*vbuf++ = DIV_ROUND_CLOSEST(fixp_i, FIXP_FRAC * 10);
 			*vbuf++ = DIV_ROUND_CLOSEST(fixp_q, FIXP_FRAC * 10);
 			break;
-- 
http://palosaari.fi/


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

end of thread, other threads:[~2015-09-01 23:05 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-09-01 23:04 [PATCH 1/2] vivid: SDR cap: add control for FM deviation Antti Palosaari
2015-09-01 23:04 ` [PATCH 2/2] vivid: sdr cap: few enhancements Antti Palosaari

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).