How to find out carrier signal strength programmatically - iphone

Here is the code that I have used to find out carrier signal strength:
int getSignalStrength()
{
void *libHandle = dlopen("/System/Library/Frameworks/CoreTelephony.framework/CoreTelephony", RTLD_LAZY);
int (*CTGetSignalStrength)();
CTGetSignalStrength = dlsym(libHandle, "CTGetSignalStrength");
if( CTGetSignalStrength == NULL) NSLog(#"Could not find CTGetSignalStrength");
int result = CTGetSignalStrength();
dlclose(libHandle);
return result;
}
It is giving me values between 60 to 100, but when I test the signal strength in device by calling to this *3001#12345#* number it showed me as -65. Below I have attached the screenshot. Is the value coming from getSignalStrength() accurate? Then why is it returning positive values always?

getSignalStrength() is showing negated dB attenuation, e.g. -(-60) == 60. The call in is displaying it more conventionally as a measurement less than zero. Yes, these kinds of variations are typical. Even in strictly controlled conditions you can get +/- 20 decibels. One way you can fix it is to take a series of measurements over time, say every second, and keep a running list of the last 10 or so measurements. Then report the mean or median or some other statistic. In my experience this cuts down the variation a lot. You can also do standard deviation to provide a measure of reliability.

My observation on CTGetSignalStrength() in CoreTelephony is that, it returns the
RSSI(Received Signal Strength Indication) value of carrier's signal strength. My experiments with this returns values between the range 0 - 100, which I believe is the "percent signal strength" of the carrier according to this .
Also iOS does not measure signal strength in a linear manner according to this
I also noticed that, even when we have 5 bars in status bar, RSSI value may not be 100.

getSignalStrength() provides the result in negative scale. The difference can be controlled using high pass filter.
You should gather the results of last 10 observations. At the time of adding new observation, take the average of last 10 observations. Multiply it by 0.1. Take the current reading and multiply it by 0.9. Add both. If total observations are greater than 10, remove the oldest observation for next calculation.
It will make your result more reliable and you can also handle sudden changes in the signal strength effectively.

I would recommend reading up on decibel measure. The following link should help.
How to Read Signal Strength

As for many signals getSignalStrength() should be used cojointly with a high-pass filter algorithm.
Also make sure to have an average measurement over some time (10-15 successive measurements).
And it's normal that it gives negative result, dB signals for telephony are like that ;-)

Related

Negative option prices for certain input values in MATLAB?

In the course of testing an algorithm I computed option prices for random input values using the standard pricing function blsprice implemented in MATLAB's Financial Toolbox.
Surprisingly ( at least for me ) ,
the function seems to return negative option prices for certain combinations of input values.
As an example take the following:
> [Call,Put]=blsprice(67.6201,170.3190,0.0129,0.80,0.1277)
Call =-7.2942e-15
Put = 100.9502
If I change time to expiration to 0.79 or 0.81, the value becomes non-negative as I would expect.
Did anyone of you ever experience something similar and can come up with a short explanation why that happens?
I don't know which version of the Financial Toolbox you are using but for me (TB 2007b) it works fine.
When running:
[Call,Put]=blsprice(67.6201,170.3190,0.0129,0.80,0.1277)
I get the following:
Call = 9.3930e-016
Put = 100.9502
Which is indeed positive
Bit late but I have come across things like this before. The small negative value can be attributed to numerical rounding error and / or truncation error within the routine used to compute the cumulative normal distribution.
As you know computers are not perfect and small numerical error always persists in all calculations, in my view therefore the question one should must ask instead is - what is the accuracy of the input parameters being used and therefore what is the error tolerance for outputs.
The way I thought about it when I encountered it before was that, in finance, typical annual stock price return variance are of the order of 30% which means the mean returns are typically sampled with standard error of roughly 30% / sqrt(N) which is roughly of the order of +/- 1% assuming 2 years worth of data (so N = 260 x 2 = 520, any more data you have the other problem of stationarity assumption). Therefore on that basis the answer you got above could have been interpreted as zero given the error tolerance.
Also we typically work to penny / cent accuracy and again on that basis the answer you had could be interpreted as zero.
Just thought I'd give my 2c hope this is helpful in some ways if you are still checking for answers!

Finding where data levels off and rise times

My data looks like this:
I am trying to find the following info about my data:
Rate of rise on the "transient" portion
time to steady state and steady state average
I think that stepinfo is my best bet to do this, but it seems to want take the final value as the steady state value which isn't giving me the best result. And I cannot find the average value of the steady time until I know when it is.... Is there a way to set some bounds on the steady state search? On the picture i linked it could be data within +/- 0.25 for 50 data points is steady state?
What you can do is:
Decide what the slope of the curve should be in the intersection between transient and steady state
Smoothen you signal
Find the difference between each point on the graph
Find the first place where the difference between points is lower then the value you selected in
To do this, keep in mind:
The difference in the beginning is on average zero, thus you have to skip these values.
One way to do this is simply: x(x < 0.1 * max(x)) = []; That way you remove the entire start of the curve. You won't need it for this part anyway. Remember to keep a backup of x.
A simple way to smoothen the signal is: smooth_x = arrayfun(#(t) mean(x(t:t+k)), 1:numel(x-k)). You need to find an appropriate value for k.
Even a smoothed curve will have "bumps", thus you might want to compare points that are not adjacent, for instance check diff(x(k),x(k+10)). If the average incline between those two points are lower than the value you selected in 1, you're happy. A combination of find and diff should do the trick here.
Once you have smoothed it, you can use diff to find the average inclination for both the transient and the stable part.
There is no way for me to tell where the curve goes from transient to stable. That's a decision you need to make. It could for instance be less than 0.2 l/min per 10 seconds.

What is AVAudioPlayer's averagePowerForChannel averaging?

The docs for AVAudioPlayer say averagePowerForChannel: "Returns the average power for a given channel, in decibels, for the sound being played." But it doesn't say what "average" means, or how/if that average is weighted. I'm particularly interested in what the range of samples is, specifically the time interval and whether it goes forward into the future at all.
AVAudioRecorder: peak and average power says that the formula used to calculate power is RMS (root mean square) over a number of samples, but also doesn't say how many samples are used.
Optional bonus question: if I want to calculate what the average power will be in, say, 100 msec -- enough time for an animation to begin now and reach an appropriate level soon -- what frameworks should I be looking into? Confusion with meters in AVAudioRecorder says I can get ahold of the raw sample data with AudioQueue or RemoteIO, and then I can use something like this: Android version of AVAudioPlayer's averagePowerForChannel -- but I haven't found sample code (pardon the pun).

Sine LUT VHDL wont simulate below 800 hz

I made a sine LUT for VHDL, using 256 elements.
Im using MIDI input, so values range 8.17Hz (note #0) to 12543.85z (note #127).
I have another LUT that calculates how many value must be sent to my 48 kHz codec in order to play the sound (the 8.17Hz frequency will need 48000/8.17 = 5870 values).
I have another LUT that contains an index factor, which is 256/num_Values, which is used to call values from the sin table (ex: 100*256/5870 = 4 (with integer rounding)).
I send this index factor to another VHDL file, which is used to calculate which value should be sent back. (ex: index = index_factor*step_counter)
When I get this index, I divide it by 100, and call sineLUT[index] to get the value that I need to generate a sine wave at the desired frequency.
The problem is, only the last 51 notes seem to work for me, and I do not know why. It seems to get stuck on a constant note at anything below that frequency (<650 hz) , and just decrease in volume every time I try to lower the note.
If you need parts of my code, let me know.
Just guessing, I suspect your step_counter isn't going through enough cycles, so your index (into the sine lut) doesn't go through a full 360 degrees for the lower frequencies.
For anything more helpful, you'll probably have to post code.
As an aside, why aren't you using something more like a conventional DDS? Analog Devices has a nice write-up on the basics: DDS Tutorial

Measuring Frequency of Square wave in MATLAB using USB 1024HLS

I'm trying to measure the frequency of a square wave which is read through a USB 1024 HLS Daq module through MATLAB. What I've done is create a loop which reads 100 values from the digitial input and that gives me vector of 0's and 1's. There is also a timer in this loop which measures the duration for which the loop runs.
After getting the vector, I then count the number of 1's and then use frequency = num_transitions/time to give me the frequency. However, this doesn't seem to work well :( I keep getting different frequencies for different number of iterations of the loop. Any suggestions?
I would suggest trying the following code:
vec = ...(the 100-element vector of digital values)...
dur = ...(the time required to collect the above vector)...
edges = find(diff(vec)); % Finds the indices of transitions between 0 and 1
period = 2*mean(diff(edges)); % Finds the mean period, in number of samples
frequency = 100/(dur*period);
First, the code finds the indices of the transitions from 0 to 1 or 1 to 0. Next, the differences between these indices are computed and averaged, giving the average duration (in number of samples) for the lengths of zeroes and ones. Multiplying this number by two then gives the average period (in number of samples) of the square wave. This number is then multiplied by dur/100 to get the period in whatever the time units of dur are (i.e. seconds, milliseconds, etc.). Taking the reciprocal then gives the average frequency.
One additional caveat: in order to get a good estimate of the frequency, you might have to make sure the 100 samples you collect contain at least a few repeated periods.
Functions of interest used above: DIFF, FIND, MEAN
First of all, you have to make sure that your 100 samples contain at least one full period of the signal, otherwise you'll get false results. You need a good compromise of sample rate (i.e. the more samples per period you have the better the measurement is) and and number of samples.
To be really precise, you should either have a timestamp associated with every measurement (as you usually can't be sure that you get equidistant time spacing in the for loop) or perhaps it's possible to switch your USB module in some "running" mode which doesn't only get one sample at a time but a complete waveform with fixed samplerate.
Concerning the calculation of the frequency, gnovice already pointed out the right way. If you have individual timestamps (in seconds), the following changes are necessary:
tst = ...(the timestamps associated with every sample)...
period = 2*mean(diff(tst(edges)));
frequency = 1/period;
I can't figure out the problem, but if the boolean vector were v then,
frequency = sum(v)/time_to_give_me_the_frequency
Based on your description, it doesn't sound like a problem with the software, UNLESS you are using the Windows system timer, which is notoriously inaccurate (it is only accurate to about 15 milliseconds).
There are high-resolution timers available in Windows, but I don't know how to use them in Matlab. If you have access to the .NET framework, the Stopwatch class has 1 microsecond accuracy (or better), as does the QueryPerformanceCounter API in Win32.
Other than that, you might have some jitter. There could be something in your signal chain that is causing false triggers, etc.
UPDATE: The following CodeProject article should solve the timing problem, if there is one. You should check the Matlab documentation of your version of Matlab to see if it has a native high-resolution timer. Otherwise, you can use this:
C++/Mex wrapper adds microsecond resolution timer to Matlab under WinXP
http://www.codeproject.com/KB/cpp/Matlab_Microsecond_Timer.aspx
mersenne31:
Thanks everyone for your responses. I have tried the solutions that gnovice and groovingandi mentioned and I'm sure they will work as soon as the timing issue is solved.
The code I've used is shown below:
for i=1:100 tic; value = getvalue(portCH); vector(i) = value(1); tst(i) = toc; % gets an individual time sample end
% to get the total time I put total_time = toc after the for loop
totaltime = sum(tst); edges = find(diff(vec)); % Finds the indices of transitions between 0 and 1 period = 2*mean(diff(edges)); % Finds the mean period, in number of samples frequency = 100/(totaltime*period);
The problem is that measuring the time for one sample doesn't really help because it is nearly the same for all samples. What is needed is, as groovingandi mentioned, some "running" mode which reads 100 samples for 3 seconds.
So something like for(3 seconds) and then we do the data capture. But I can't find anything like this. Is there any function in MATLAB that could do this?
This won't answer your question, but it's what I thought of after reading you question. square waves have infinite frequency. The FFT of a square wave it sin(x)/x, which goes from -inf to +inf.
Also try counting only the rising edges in matlab. You can quantize the signal to just +1 and 0, and then only increment the count when you see [0 1] slice of your vector.
OR
You can quantize, decimate, then just sum. This will only work if the each square pulse is the same length and your sampling frequency is constant. I think this one would be harder to do.