how the ping implementation calculating the round trip time? - c

I was learning about the ping implementation.
In that I had one doubt. The doubt is, how they calculating the round trip time.
They done some calculation to calculate the round trip time. I am not able to understand that calculation.
Here is the code for the round trip time calculation.
tsum += triptime;
tsum2 += (long long)triptime * (long long)triptime;
if (triptime < tmin)
tmin = triptime;
if (triptime > tmax)
tmax = triptime;
if (!rtt)
rtt = triptime*8;
else
rtt += triptime-rtt/8;
The tsum, tsum2, triptime, tmax variables are initially 0.
The tmin contains the value as 2147483647 as initially.
The triptime is calculated by the before the packet sending, noted one time. In destination the packet is received, before it send replay it note one time and it fill that in reply packet and it sends the reply.
The two times are subtracted and convert that subtracted time into micro seconds. The triptime variable contains that micro seconds.
For example, take the below output for calculating the rtt.
The trip time for the first packet is 42573, and second packet 43707, third packet 48047, and fourth packet 42559.
Using this how they calculate the round trip time. Why they multiply with 8 in the starting and after that they divide with 8 and subtract with the first rtt. I am not able to find why they calculating the rtt like that.
Can any one please explain me why they multiply with 8 in starting and after that why they divide with 8 and subtract with the before calculated rtt.
The below link contains the full code for the ping implementation.
ping_common.c
ping.c
Thanks in advance.

rtt is Modified Moving Average of triptime values, multiplied by 8 for easy calculations, with N==8.

rtt in the program variable name is not necessarily rtt in the output - And here it isn't.
The 'average round trip delay' in the implementation you show is in tsum / count of packets. When you look at rtt, you are actually looking at something different. That is only displayed when you use pingin adaptive mode.

Because you are dealing with bits. Bit rate and transmission time are not the same thing, so you need to do a tiny bit of arithmetic to convert. The formula is:
Packet transmission time = Packet size / Bit rate
So assuming 100 Mbit/s and a packet size of 1526 bytes, you get:
1526 bytes x 8 bits / (100 x 106 bits/second)) = 116 microseconds
The bit unit cancels out and you are left with seconds.
Now here's another example. Say you have a round trip time of 225 milliseconds and your throughput is 32 kilobytes. You get:
32,000 bytes * 8 bits / 0.255 = 1,003,921 bits per second

Related

Storing a Timestamp as a Binary Fraction in C

I'm working on an implementation of an obscure network protocol, and one of the requirements is that each packet header should contain a 56-bit timestamp, with the first 4 bytes containing an integer number of seconds since the epoch, and the remaining 3 bytes used to contain a binary fraction of the current second. In other words, the last 3 bytes should represent the number of 2^-24 seconds since the previous second. The first part of the timestamp is trivial, but I'm struggling to implement the C code that would store the fractional part of the timestamp. Can anyone shed some light on how to do this?
For completeness' sake, here's the timestamp code I have so far. primaryHeader is a char* that I'm using to store the header data for the packet. You can assume that the first 6 bytes in primaryHeader contain valid, unrelated data, and that primaryHeader is large enough to contain everything that needs to be stored in it.
int secs = (int)time(NULL);
memcpy(&primaryHeader[7], &secs, sizeof(int));
// TODO: Compute fractional portion of the timestamp and memcpy to primaryHeader[11]
The time() function will only give you seconds. You a higher resolution timer.
struct timespec t;
timespec_get(&ts, TIME_UTC);
int secs = t.tv_sec; // Whole seconds
int frac = ((int64_t)t.tv_nsec << 24) / 1000000000; // Fractional part.
If this is not available you can use clock_gettime, but clock_gettime is not found on Windows.

Effective way to calc without float, C

I need to do a math to convert a 16-bit value received from sensor to real relative humidity value. It's calculated with following formula:
Given this in floating point math that would be:
uint16_t buf = 0x7C80; // Example
float rh = ((float)buf*125 / 65536)-6;
But I want to avoid floating point math as my platform are "FPUless".
What are the most effective way to calculate & store RH in integer math here? Considering it's humidity the actual value should be between 0 and 100% but sometimes approximation could lead that rh could be slightly less than 0 or higher than 100 (if I would leave that float, I could just do something like if (rh<0) rh=0; else if (rh>100) rh=100;) and I care only about last 2 digits after decimal point (%.2f).
Currently I've solved this like this:
int16_t rhint = ((uint32_t)buf*12500 / 65536)-600;
And working with rhint / 100; rhint % 100. But probably there are more effective way?
You could avoid the large intermediate term by writing the right hand side as
-6 + (128 - 4 + 1) * S / 65536
Which becomes
-6 + S / 512 - S / 16384 + S / 65536
You might be able to drop the last term, and possibly the penultimate one too depending on how precise you want the basis point truncation to be.

math function as binary operations

I have an MP3 board attached to a ATmega microcontroller which is additionally connected to a potentiometer. The MP3 board plays MP3 data directly through its onboard speaker and therefore I am also able to set the volume of the output.
So, as you might guess, I read the value from the poti and forward it to the microcontroller. Unfortunately, the microcontroller does not increase the volume in a linear way. So, from values 0 to 128 you nearly hear nothing, and from 128 to 255 (max) the volume increases rapidly.
I found out, that the following function could solve this problem:
vol = 1 - (1 - x)^4
but x must be between 0 and 1 and the result is also between 0 and 1.
Since I am on a microcontroller, I would like to
transform this formula, so that I can use it with unsigned integers
optimize it (maybe use some cheap binary functions), because I read the poti value multiple times per second. So this function has to be calculated multiple times per second and I want to use the microcontroller for other stuff too ;-)
Maybe some of you have an idea? Would be great!
uint8_t linearize_volume(uint8_t value) {
// ideas?
// please don't use bigger data types than uint16_t
}
You can "pay" with memory for CPU cycles. If you have 256 bytes of ROM available to you, the cheapest way of computing such function would be building a lookup table.
Make a program that prints a list of 256 8-bit numbers with the values of your non-linear function. It does not matter how fast the program is, because you are going to run it only once. Copy the numbers the program prints into your C program as an array initializer, and perform the lookup instead of calculating the function.
You can get a decent estimate by treating the values as 8.8 fixed-point and raising to the power of four by squaring twice.
uint8_t linearize_volume(uint8_t value) {
// Approximate 255 * (1 - (1 - x/255)^4)
uint16_t x = 0xff - value;
x = (x * x) >> 8;
x = (x * x) >> 8;
return 0xff - x;
}
First, be sure you're using a linear pot, not an audio-taper pot.
This is typical of audio outputs. The data is a sine wave, and therefore negative values are necessary. You can certainly convert negatives to positives for the sole purpose of accessing their power level, but you can't alter the sample without hearing a completely different sound.
Depending upon the output device, lower values may not pack enough power to energize your speaker much at all.
The "MP3 board" should include an ability to control the volume without your having to alter samples.
You state you read the pot and forward it to the micro. Aren't you reading the pot with the micro's ADC?

How to Calculate FAT

I am learning about FAT file system and how to calculate FAT size. Now, I have this question:
Consider a disk size is 32 MB and the block size is 1 KB. Calculate the size of FAT16.
Now, I know that to calculate it, we would multiply the number of bits per entry with the number of blocks.
So first step would be to calculate the number of blocks = (32MB)/(1KB) = 2^15 = 32 KB blocks.
Then, we would put that into the first equation to get = 2^16 * 2^15 = 2^19
Now, up to here I understand and I had thought that that is the answer (and that is how I found it to be calculated in http://pcnineoneone.com/howto/fat1.html).
However, the answer I was given goes one step further to divide 2^19 by (8*1024) , which would basically give an answer of 64KB. Why is that? I have searched for hours, but could find nothing.
Can someone explain why we would perform the extra step of dividing 2^19 by (8*1024)?
oh, and the other question stated that the block size is 2KB and so it divided the end result by(8*1024*1024) ... where is the 8 and 1024 coming from?
please help
you are using FAT16. Clusters are represented with 16 bits which means 16/8=2 bytes. To get size in bytes the result should be divided by 8.to get result in kilobytes you should divide your result by 8*1024

adding/subtracting floats/ints linux C

(can skip this part just an explanation of the code below. my problems are under the code block.)
hi. i'm trying to algro for throttling loop cycles based on how much bandwidth the linux computer is using. i'm reading /proc/net/dev once a second and keeping track of the bytes transmitted in 2 variables. one is the last time it was checked the other is the recent time. from there subtracts the recent one from the last one to calculate how many bytes has been sent in 1 second.
from there i have the variables max_throttle, throttle, max_speed, and sleepp.
the idea is to increase or decrease sleepp depending on bandwidth being used. the less bandwidth the lower the delay and the higher the longer.
i am currently having to problems dealing with floats and ints. if i set all my variables to ints max_throttle becomes 0 always no matter what i set the others to and even if i initialize them.
also even though my if statement says "if sleepp is less then 0 return it to 0" it keeps going deeper and deeper into the negatives then levels out at aroung -540 with 0 bandwidth being used.
and the if(ii & 0x40) is for speed and usage control. in my application there will be no 1 second sleep so this code allows me to limit the sleepp from changing about once every 20-30 iterations. although im also having a problem with it where after the 2X iterations when it does trigger it continues to trigger every iteration after instead of only being true once and then being true again after 20-30 more iterations.
edit:: simpler test cast for my variable problem.
#include <stdio.h>
int main()
{
int max_t, max_s, throttle;
max_s = 400;
throttle = 90;
max_t = max_s * (throttle / 100);
printf("max throttle:%d\n", max_t);
return 0;
}
In C, operator / is an integer division when used with integers only. Therefore, 90/100 = 0. In order to do floating-point division with integers, first convert them to floats (or double or other fp types).
max_t = max_s * (int)(((float)throttle / 100.0)+0.5);
The +0.5 is rounding before converting to int. You might want to consider some standard flooring functions, I don't know your use case.
Also note that the 100.0 is a float literal, whereas 100 would be an intger literal. So, although they seem identical, they are not.
As kralyk pointed out, C’s integer division of 90/100 is 0. But rather than using floats you can work with ints… Just do the division after the multiplication (note the omission of parentheses):
max_t = max_s * throttle / 100;
This gives you the general idea. For example if you want the kind of rounding kralyk mentions, add 50 before doing the division:
max_t = (max_s * throttle + 50) / 100;

Resources