Carrier mixer amplitude limit

D
dwp@md1tech.co.uk
Wed, Jan 24, 2024 4:22 PM

Hi,

I want to use the carrier_mixer_us in ocpi.comp.sdr.dsp component to down convert a signal.

Ideally I would want the input wave to have the same amplitude as the output wave however this does not seem to be possible due to the carrier_amplitude property having a maximum allowed value of 14,060.

Since the property is scaled by 1.646760258, this brings the amplitude of the mixer wave to 23170.475 or roughly sqrt(2) * 2^15. I would understand if the amplitude was limited to 2^15 to prevent overflow but what is the reason for this sqrt(2) factor?

Before outputting, the result of each multiplication is shifted right by 15 (both I and Q) i.e scaled by 1 / 2^15. Therefore with the maximum mixer amplitude, the resulting wave’s amplitude will be roughly 1/sqrt(2) that of the input wave.

It is also quite counterintuitive that the input amplitude of the carrier wave is being scaled this way. Would it not be possible to provide the true amplitude to the carrier_amplitude property and have the worker do the necessary scaling? If not, renaming the property to indicate that it is not the actual amplitude would be useful.

Thanks,
Dan

Hi, I want to use the carrier_mixer_us in `ocpi.comp.sdr.dsp` component to down convert a signal. Ideally I would want the input wave to have the same amplitude as the output wave however this does not seem to be possible due to the `carrier_amplitude` property having a maximum allowed value of 14,060. Since the property is scaled by 1.646760258, this brings the amplitude of the mixer wave to 23170.475 or roughly sqrt(2) \* 2^15. I would understand if the amplitude was limited to 2^15 to prevent overflow but what is the reason for this sqrt(2) factor? Before outputting, the result of each multiplication is shifted right by 15 (both I and Q) i.e scaled by 1 / 2^15. Therefore with the maximum mixer amplitude, the resulting wave’s amplitude will be roughly 1/sqrt(2) that of the input wave. It is also quite counterintuitive that the input amplitude of the carrier wave is being scaled this way. Would it not be possible to provide the true amplitude to the `carrier_amplitude` property and have the worker do the necessary scaling? If not, renaming the property to indicate that it is not the actual amplitude would be useful. Thanks,\ Dan
DW
Dominic Walters
Tue, Jan 30, 2024 9:35 PM

Hi,

Apologies for the delayed response to this.
I asked this question to several people who were / are involved with the
creation and maintenance of this worker / component.

These are their responses, which I have slightly edited to fix formatting
and remove names, etc.

I hope the formatting is retained or this might be quite hard to read :D

--- First Response ---

This is explained in the documentation:

https://opencpi.gitlab.io/releases/develop/rst/comp_sdr/components/dsp/carrier_mixer_xs.comp/carrier_mixer_xs-index.html

However, the term carrier_amplitude may be misleading, carrier_gain would
be better.

In (9) we are looking to define the gain A for some given complex sample -
the gain is relative to the input so we consider the input on a unit
circle, i.e. x and y are in the range -1 to 1.

Substituting in (9) for the point where the term multiplying A is maximal
(x = x_max and y = -x_max):

A ( x_max * cos (theta) – (-x_max) * sin( theta) )

-----------------------------------------------------------------  < x_max

                            2^15

As x_max is 1 and the largest value of cos(theta) + sin(theta) is sqrt(2)
we then get:

A * sqrt(2)

--------------  < 1

2^15

Solving for A:

A * sqrt(2)

-------------- = 1

2^15

A * sqrt(2) = 1 * 2^15 = 2^15

A = 2^15 / sqrt(2) = 23170.475….

A is scaled by 1.64…. and so carrier_amplitude should be set to 14070 for a
gain of 1 through the component.

However, the underlying cordic can over/under-shoot so we recommend using
the value 14,060.

There is (in my opinion) an unnecessary limitation in the C++
implementation which sets an upper bound of the carrier_amplitude value to
14,060 – it is perfectly reasonable to use this component as a gain block –
i.e. setting the value to 28,000 would double the output amplitude relative
to the input.

(if you consider the input to be half scale (x = 0.5, y = 0.5, x_max = 1)
and substitute in (9) you get 28,140).

I did test the RCC implementation and the above holds, I believe the RCC
and HDL implementations are both tested against the same Python based model
– so have no reason to expect the HDL version is any different.

*--- *Second Response ---

I have been doing some thinking on this also and I think I see what Dan is
getting at…but also understand why it is designed as is.

The issue Dan is bringing up is specifically with this bit -> “A is maximal
(x = x_max and y = -x_max)”. If the carrier mixer input is a “perfect” iq
tone, as it is in Dan case, with sin and cos waveforms 90 degrees apart the
condition “x = x_max and y = -x_max” never occurs (see below that there is
never a point in time where x is 1 and y is 1 (or -1)).

[image: cid:image003.png@01DA5377.D1D769A0]

Euler’s formula is the easiest way to understand this (I reckon…):

When frequency shifting, Dan wants to realise the below formula, where  is
the input signal and  is the generated signal.

However, what is currently done is an acknowledgment that the input
waveform might not be a “perfect” since wave and therefore is accounting
for the “x = x_max and y = -x_max)” condition occurring.

So the  term is reduced to , since the magnitude of  gives 1, which ensures
whatever the input is there is no overflow. To be clear, the  is  and  (the
amplitude of the generated waveform).

In summary, I think how we have it implemented now is correct since it
ensures a messy input waveform never overflows on the output when it is
mixed. But a good compromise to allow for Dan’s “perfect” input waveform
use case is as the first reply says: adding the ability to set the
carrier_amplitude to a value such that an amplitude of 32767 instead of
23170 is achieved for the generated waveform.

I will relay this information onto the ocpi.comp.sdr developers to add to
their backlog.


I hope this was helpful.

Kind Regards,
Dom Walters

On Wed, Jan 24, 2024 at 4:22 PM dwp@md1tech.co.uk wrote:

Hi,

I want to use the carrier_mixer_us in ocpi.comp.sdr.dsp component to down
convert a signal.

Ideally I would want the input wave to have the same amplitude as the
output wave however this does not seem to be possible due to the
carrier_amplitude property having a maximum allowed value of 14,060.

Since the property is scaled by 1.646760258, this brings the amplitude of
the mixer wave to 23170.475 or roughly sqrt(2) * 2^15. I would understand
if the amplitude was limited to 2^15 to prevent overflow but what is the
reason for this sqrt(2) factor?

Before outputting, the result of each multiplication is shifted right by
15 (both I and Q) i.e scaled by 1 / 2^15. Therefore with the maximum mixer
amplitude, the resulting wave’s amplitude will be roughly 1/sqrt(2) that of
the input wave.

It is also quite counterintuitive that the input amplitude of the carrier
wave is being scaled this way. Would it not be possible to provide the true
amplitude to the carrier_amplitude property and have the worker do the
necessary scaling? If not, renaming the property to indicate that it is not
the actual amplitude would be useful.

Thanks,
Dan


discuss mailing list -- discuss@lists.opencpi.org
To unsubscribe send an email to discuss-leave@lists.opencpi.org

Hi, Apologies for the delayed response to this. I asked this question to several people who were / are involved with the creation and maintenance of this worker / component. These are their responses, which I have slightly edited to fix formatting and remove names, etc. I hope the formatting is retained or this might be quite hard to read :D *--- First Response ---* This is explained in the documentation: https://opencpi.gitlab.io/releases/develop/rst/comp_sdr/components/dsp/carrier_mixer_xs.comp/carrier_mixer_xs-index.html However, the term carrier_amplitude may be misleading, carrier_gain would be better. In (9) we are looking to define the gain A for some given complex sample - the gain is relative to the input so we consider the input on a unit circle, i.e. x and y are in the range -1 to 1. Substituting in (9) for the point where the term multiplying A is maximal (x = x_max and y = -x_max): A ( x_max * cos (theta) – (-x_max) * sin( theta) ) ----------------------------------------------------------------- < x_max 2^15 As x_max is 1 and the largest value of cos(theta) + sin(theta) is sqrt(2) we then get: A * sqrt(2) -------------- < 1 2^15 Solving for A: A * sqrt(2) -------------- = 1 2^15 A * sqrt(2) = 1 * 2^15 = 2^15 A = 2^15 / sqrt(2) = 23170.475…. A is scaled by 1.64…. and so carrier_amplitude should be set to 14070 for a gain of 1 through the component. However, the underlying cordic can over/under-shoot so we recommend using the value 14,060. There is (in my opinion) an unnecessary limitation in the C++ implementation which sets an upper bound of the carrier_amplitude value to 14,060 – it is perfectly reasonable to use this component as a gain block – i.e. setting the value to 28,000 would double the output amplitude relative to the input. (if you consider the input to be half scale (x = 0.5, y = 0.5, x_max = 1) and substitute in (9) you get 28,140). I did test the RCC implementation and the above holds, I believe the RCC and HDL implementations are both tested against the same Python based model – so have no reason to expect the HDL version is any different. *--- **Second Response ---* I have been doing some thinking on this also and I think I see what Dan is getting at…but also understand why it is designed as is. The issue Dan is bringing up is specifically with this bit -> “A is maximal (x = x_max and y = -x_max)”. If the carrier mixer input is a “perfect” iq tone, as it is in Dan case, with sin and cos waveforms 90 degrees apart the condition “x = x_max and y = -x_max” never occurs (see below that there is never a point in time where x is 1 and y is 1 (or -1)). [image: cid:image003.png@01DA5377.D1D769A0] Euler’s formula is the easiest way to understand this (I reckon…): When frequency shifting, Dan wants to realise the below formula, where is the input signal and is the generated signal. However, what is currently done is an acknowledgment that the input waveform might not be a “perfect” since wave and therefore is accounting for the “x = x_max and y = -x_max)” condition occurring. So the term is reduced to , since the magnitude of gives 1, which ensures whatever the input is there is no overflow. To be clear, the is and (the amplitude of the generated waveform). In summary, I think how we have it implemented now is correct since it ensures a messy input waveform never overflows on the output when it is mixed. But a good compromise to allow for Dan’s “perfect” input waveform use case is as the first reply says: adding the ability to set the carrier_amplitude to a value such that an amplitude of 32767 instead of 23170 is achieved for the generated waveform. I will relay this information onto the ocpi.comp.sdr developers to add to their backlog. --- I hope this was helpful. Kind Regards, Dom Walters On Wed, Jan 24, 2024 at 4:22 PM <dwp@md1tech.co.uk> wrote: > Hi, > > I want to use the carrier_mixer_us in ocpi.comp.sdr.dsp component to down > convert a signal. > > Ideally I would want the input wave to have the same amplitude as the > output wave however this does not seem to be possible due to the > carrier_amplitude property having a maximum allowed value of 14,060. > > Since the property is scaled by 1.646760258, this brings the amplitude of > the mixer wave to 23170.475 or roughly sqrt(2) * 2^15. I would understand > if the amplitude was limited to 2^15 to prevent overflow but what is the > reason for this sqrt(2) factor? > > Before outputting, the result of each multiplication is shifted right by > 15 (both I and Q) i.e scaled by 1 / 2^15. Therefore with the maximum mixer > amplitude, the resulting wave’s amplitude will be roughly 1/sqrt(2) that of > the input wave. > > It is also quite counterintuitive that the input amplitude of the carrier > wave is being scaled this way. Would it not be possible to provide the true > amplitude to the carrier_amplitude property and have the worker do the > necessary scaling? If not, renaming the property to indicate that it is not > the actual amplitude would be useful. > > Thanks, > Dan > _______________________________________________ > discuss mailing list -- discuss@lists.opencpi.org > To unsubscribe send an email to discuss-leave@lists.opencpi.org >
DW
Dominic Walters
Tue, Jan 30, 2024 9:38 PM

Looks like a lot of the embedded images got stripped out or added as
attachments, which is unfortunate.

If you struggle to read the second part of this, I can try screen grab it
and upload the image somewhere. Or something like that.

On Tue, Jan 30, 2024 at 9:35 PM Dominic Walters waltersdom@googlemail.com
wrote:

Hi,

Apologies for the delayed response to this.
I asked this question to several people who were / are involved with the
creation and maintenance of this worker / component.

These are their responses, which I have slightly edited to fix formatting
and remove names, etc.

I hope the formatting is retained or this might be quite hard to read :D

--- First Response ---

This is explained in the documentation:

https://opencpi.gitlab.io/releases/develop/rst/comp_sdr/components/dsp/carrier_mixer_xs.comp/carrier_mixer_xs-index.html

However, the term carrier_amplitude may be misleading, carrier_gain would
be better.

In (9) we are looking to define the gain A for some given complex sample -
the gain is relative to the input so we consider the input on a unit
circle, i.e. x and y are in the range -1 to 1.

Substituting in (9) for the point where the term multiplying A is maximal
(x = x_max and y = -x_max):

A ( x_max * cos (theta) – (-x_max) * sin( theta) )

-----------------------------------------------------------------  < x_max

                             2^15

As x_max is 1 and the largest value of cos(theta) + sin(theta) is sqrt(2)
we then get:

A * sqrt(2)

--------------  < 1

2^15

Solving for A:

A * sqrt(2)

-------------- = 1

 2^15

A * sqrt(2) = 1 * 2^15 = 2^15

A = 2^15 / sqrt(2) = 23170.475….

A is scaled by 1.64…. and so carrier_amplitude should be set to 14070 for
a gain of 1 through the component.

However, the underlying cordic can over/under-shoot so we recommend using
the value 14,060.

There is (in my opinion) an unnecessary limitation in the C++
implementation which sets an upper bound of the carrier_amplitude value to
14,060 – it is perfectly reasonable to use this component as a gain block –
i.e. setting the value to 28,000 would double the output amplitude relative
to the input.

(if you consider the input to be half scale (x = 0.5, y = 0.5, x_max = 1)
and substitute in (9) you get 28,140).

I did test the RCC implementation and the above holds, I believe the RCC
and HDL implementations are both tested against the same Python based model
– so have no reason to expect the HDL version is any different.

*--- *Second Response ---

I have been doing some thinking on this also and I think I see what Dan is
getting at…but also understand why it is designed as is.

The issue Dan is bringing up is specifically with this bit -> “A is
maximal (x = x_max and y = -x_max)”. If the carrier mixer input is a
“perfect” iq tone, as it is in Dan case, with sin and cos waveforms 90
degrees apart the condition “x = x_max and y = -x_max” never occurs (see
below that there is never a point in time where x is 1 and y is 1 (or -1)).

[image: cid:image003.png@01DA5377.D1D769A0]

Euler’s formula is the easiest way to understand this (I reckon…):

When frequency shifting, Dan wants to realise the below formula, where  is
the input signal and  is the generated signal.

However, what is currently done is an acknowledgment that the input
waveform might not be a “perfect” since wave and therefore is accounting
for the “x = x_max and y = -x_max)” condition occurring.

So the  term is reduced to , since the magnitude of  gives 1, which
ensures whatever the input is there is no overflow. To be clear, the  is
and  (the amplitude of the generated waveform).

In summary, I think how we have it implemented now is correct since it
ensures a messy input waveform never overflows on the output when it is
mixed. But a good compromise to allow for Dan’s “perfect” input waveform
use case is as the first reply says: adding the ability to set the
carrier_amplitude to a value such that an amplitude of 32767 instead of
23170 is achieved for the generated waveform.

I will relay this information onto the ocpi.comp.sdr developers to add to
their backlog.


I hope this was helpful.

Kind Regards,
Dom Walters

On Wed, Jan 24, 2024 at 4:22 PM dwp@md1tech.co.uk wrote:

Hi,

I want to use the carrier_mixer_us in ocpi.comp.sdr.dsp component to
down convert a signal.

Ideally I would want the input wave to have the same amplitude as the
output wave however this does not seem to be possible due to the
carrier_amplitude property having a maximum allowed value of 14,060.

Since the property is scaled by 1.646760258, this brings the amplitude of
the mixer wave to 23170.475 or roughly sqrt(2) * 2^15. I would understand
if the amplitude was limited to 2^15 to prevent overflow but what is the
reason for this sqrt(2) factor?

Before outputting, the result of each multiplication is shifted right by
15 (both I and Q) i.e scaled by 1 / 2^15. Therefore with the maximum mixer
amplitude, the resulting wave’s amplitude will be roughly 1/sqrt(2) that of
the input wave.

It is also quite counterintuitive that the input amplitude of the carrier
wave is being scaled this way. Would it not be possible to provide the true
amplitude to the carrier_amplitude property and have the worker do the
necessary scaling? If not, renaming the property to indicate that it is not
the actual amplitude would be useful.

Thanks,
Dan


discuss mailing list -- discuss@lists.opencpi.org
To unsubscribe send an email to discuss-leave@lists.opencpi.org

Looks like a lot of the embedded images got stripped out or added as attachments, which is unfortunate. If you struggle to read the second part of this, I can try screen grab it and upload the image somewhere. Or something like that. On Tue, Jan 30, 2024 at 9:35 PM Dominic Walters <waltersdom@googlemail.com> wrote: > Hi, > > Apologies for the delayed response to this. > I asked this question to several people who were / are involved with the > creation and maintenance of this worker / component. > > These are their responses, which I have slightly edited to fix formatting > and remove names, etc. > > I hope the formatting is retained or this might be quite hard to read :D > > *--- First Response ---* > > This is explained in the documentation: > > > > > https://opencpi.gitlab.io/releases/develop/rst/comp_sdr/components/dsp/carrier_mixer_xs.comp/carrier_mixer_xs-index.html > > > > However, the term carrier_amplitude may be misleading, carrier_gain would > be better. > > > > In (9) we are looking to define the gain A for some given complex sample - > the gain is relative to the input so we consider the input on a unit > circle, i.e. x and y are in the range -1 to 1. > > > > Substituting in (9) for the point where the term multiplying A is maximal > (x = x_max and y = -x_max): > > > > A ( x_max * cos (theta) – (-x_max) * sin( theta) ) > > ----------------------------------------------------------------- < x_max > > 2^15 > > > > As x_max is 1 and the largest value of cos(theta) + sin(theta) is sqrt(2) > we then get: > > > > A * sqrt(2) > > -------------- < 1 > > 2^15 > > > > Solving for A: > > > > A * sqrt(2) > > -------------- = 1 > > 2^15 > > > > A * sqrt(2) = 1 * 2^15 = 2^15 > > > > A = 2^15 / sqrt(2) = 23170.475…. > > > > A is scaled by 1.64…. and so carrier_amplitude should be set to 14070 for > a gain of 1 through the component. > > > > However, the underlying cordic can over/under-shoot so we recommend using > the value 14,060. > > > > There is (in my opinion) an unnecessary limitation in the C++ > implementation which sets an upper bound of the carrier_amplitude value to > 14,060 – it is perfectly reasonable to use this component as a gain block – > i.e. setting the value to 28,000 would double the output amplitude relative > to the input. > > > > (if you consider the input to be half scale (x = 0.5, y = 0.5, x_max = 1) > and substitute in (9) you get 28,140). > > > > I did test the RCC implementation and the above holds, I believe the RCC > and HDL implementations are both tested against the same Python based model > – so have no reason to expect the HDL version is any different. > > *--- **Second Response ---* > > I have been doing some thinking on this also and I think I see what Dan is > getting at…but also understand why it is designed as is. > > > > The issue Dan is bringing up is specifically with this bit -> “A is > maximal (x = x_max and y = -x_max)”. If the carrier mixer input is a > “perfect” iq tone, as it is in Dan case, with sin and cos waveforms 90 > degrees apart the condition “x = x_max and y = -x_max” never occurs (see > below that there is never a point in time where x is 1 and y is 1 (or -1)). > > > > [image: cid:image003.png@01DA5377.D1D769A0] > > > > Euler’s formula is the easiest way to understand this (I reckon…): > > > > > > When frequency shifting, Dan wants to realise the below formula, where is > the input signal and is the generated signal. > > > > > > However, what is currently done is an acknowledgment that the input > waveform might not be a “perfect” since wave and therefore is accounting > for the “x = x_max and y = -x_max)” condition occurring. > > > > So the term is reduced to , since the magnitude of gives 1, which > ensures whatever the input is there is no overflow. To be clear, the is > and (the amplitude of the generated waveform). > > > > In summary, I think how we have it implemented now is correct since it > ensures a messy input waveform never overflows on the output when it is > mixed. But a good compromise to allow for Dan’s “perfect” input waveform > use case is as the first reply says: adding the ability to set the > carrier_amplitude to a value such that an amplitude of 32767 instead of > 23170 is achieved for the generated waveform. > > > > I will relay this information onto the ocpi.comp.sdr developers to add to > their backlog. > > > --- > > > I hope this was helpful. > > > Kind Regards, > Dom Walters > > On Wed, Jan 24, 2024 at 4:22 PM <dwp@md1tech.co.uk> wrote: > >> Hi, >> >> I want to use the carrier_mixer_us in ocpi.comp.sdr.dsp component to >> down convert a signal. >> >> Ideally I would want the input wave to have the same amplitude as the >> output wave however this does not seem to be possible due to the >> carrier_amplitude property having a maximum allowed value of 14,060. >> >> Since the property is scaled by 1.646760258, this brings the amplitude of >> the mixer wave to 23170.475 or roughly sqrt(2) * 2^15. I would understand >> if the amplitude was limited to 2^15 to prevent overflow but what is the >> reason for this sqrt(2) factor? >> >> Before outputting, the result of each multiplication is shifted right by >> 15 (both I and Q) i.e scaled by 1 / 2^15. Therefore with the maximum mixer >> amplitude, the resulting wave’s amplitude will be roughly 1/sqrt(2) that of >> the input wave. >> >> It is also quite counterintuitive that the input amplitude of the carrier >> wave is being scaled this way. Would it not be possible to provide the true >> amplitude to the carrier_amplitude property and have the worker do the >> necessary scaling? If not, renaming the property to indicate that it is not >> the actual amplitude would be useful. >> >> Thanks, >> Dan >> _______________________________________________ >> discuss mailing list -- discuss@lists.opencpi.org >> To unsubscribe send an email to discuss-leave@lists.opencpi.org >> >
D
dwp@md1tech.co.uk
Wed, Jan 31, 2024 10:14 AM

Hi Dom,

Thankyou for looking into this and please pass on thanks to the people you had these replies from.
This has cleared things up for me.

I have been looking at the component .rst files for documentation up to now however the online documentation linked is much clearer and the equations and displayed correctly. I will make sure to refer to this in future as well as the .rst files.

Hi Dom, Thankyou for looking into this and please pass on thanks to the people you had these replies from.\ This has cleared things up for me. I have been looking at the component .rst files for documentation up to now however the online documentation linked is much clearer and the equations and displayed correctly. I will make sure to refer to this in future as well as the .rst files.