Let's say the sender and the receiver got a 16 size buffer with a 7 size window.
In other words, each side has a buffer, an array, where they can store 16 frames. Each frame has an id that fits in the 16 frames buffer (index in the array). The receiver got a window that only allow 7 frames in any order to be accepted at any given time. The window will slide by one when it got the oldest frame in the buffer filled.
My problem now is, let's say if a frame get lost on the way, but somehow make it back way too late. The receiver got it so late it actually fills the next circle of the frame's buffer.
The sender send the frames: 0, 1, 2, 3, 4, 5, 6, 7.
The receiver gets the frames and sends an ACK back for having got all up to 7 (or for each one).
The sender gets a timeout on frame 0, and re-sends it.
The sender gets ACK on all up to 7, so it sends the next frames: 8, 9, 10, 11, 12, 13, 14
The receiver gets the following packets: 8, 9, 10, 11, 12, 13, 14. It sends an ACK for having got them and open ups the buffer for: 15, 0, 1, 2, 3, 4, 5, 6.
The receiver gets the old frame 0 that was sent by the sender due to a timeout. The receiver think the packet is legit and stores it.
How to avoid what happened at step 6?
Should I send a CRC of the entire window? CRC is not perfect, so there may still be issues.
I'm currently doing this over an UDP socket in C, hence the C tag.
Related
I'm a newbie and I'm playing with ESP32 and IR receiver to capture signal from AC IR remote.
Currently, I refer to example code for capturing IR signal as follows:
static void nec_rx_init()
{
rmt_config_t rmt_rx;
rmt_rx.channel = RMT_RX_CHANNEL;
rmt_rx.gpio_num = RMT_RX_GPIO_NUM;
rmt_rx.clk_div = RMT_CLK_DIV;
rmt_rx.mem_block_num = 1;
rmt_rx.rmt_mode = RMT_MODE_RX;
rmt_rx.rx_config.filter_en = true;
rmt_rx.rx_config.filter_ticks_thresh = 100;
rmt_rx.rx_config.idle_threshold = rmt_item32_tIMEOUT_US / 10 * (RMT_TICK_10_US);
rmt_config(&rmt_rx);
rmt_driver_install(rmt_rx.channel, 3000, 0);
}
//get RMT RX ringbuffer
RingbufHandle_t rb = NULL;
rmt_get_ringbuf_handle(RMT_RX_CHANNEL, &rb);
// rmt_rx_start(channel, rx_idx_rst) - Set true to reset memory index for receiver
rmt_rx_start(RMT_RX_CHANNEL, 1);
while(rb) {
uint32_t rx_size = 0;
//try to receive data from ringbuffer.
//RMT driver will push all the data it receives to its ringbuffer.
//We just need to parse the value and return the spaces of ringbuffer.
rmt_item32_t* item = (rmt_item32_t*) xRingbufferReceive(rb, &rx_size, 1000);
...
}
Although IR signal is emitted from an AC IR remote is about 100 items but I always see that rx_size is only 256 (64 items). So it is problem, how can I capture total signals from AC IR remote?. Note that I set the buffer size from 3000 to 10000.
I appreciate any suggestion for me in order to deal with this problem.
I had this same issue this past week. I was receiving a serial packet that was 128 bits, but only ever got the first 64. After digging into it a bit deeper I found that the hardware buffer on the RMT interface defaults to a 64x32-bit RAM block per channel. You can set the channel up to use the memory blocks normally assigned to subsequent channels if you need to receive more data at once.
For my project I used the following function to give 4 RAM blocks to channel 0, thus increasing the maximum receive size to 256 bits, which is more than enough for my application. I also had to move the receive to channel 4 since channel 0 was now using the memory block for channel 1.
rmt_set_mem_block_num((rmt_channel_t) 0, 4);
Documentation for this function can be found here:
https://docs.espressif.com/projects/esp-idf/en/stable/api-reference/peripherals/rmt.html#_CPPv421rmt_set_mem_block_num13rmt_channel_t7uint8_t
It's also worth noting that it did throw an error in the serial monitor while the issue was occurring, which did help find the cause of the issue.
E (33323) rmt: RMT[0] ERR
E (33323) rmt: status: 0x14000100
E (33373) rmt: RMT RX BUFFER FULL
With the default amount of RAM I was getting an error code of 0x14000040, and when I increased it to 2 blocks I got a status code of 0x13000040. After increasing to 4 blocks of RAM the error message stopped appearing.
I have these packets saved in pcap file (shown in wireshark)
Iam parsing these packets using DPDK and for some reason i cannot use mbufs. To parse them iam using struct ipv4_hdr and struct ether_hdr as following:
eth_hdr = (struct ether_hdr *) pckt;
ip_hdr = (struct ipv4_hdr *)((unsigned char *) pckt + sizeof(struct ether_hdr));
The total_length in ipv4_hdr is size of ipv4 header + size of data. With size of etherhet header it should be the total length of packet, right?
size = rte_bswap16(ip_hdr->total_length) + sizeof(struct ether_hdr);
which gives me for these 6 packets output:
54, 54, 54, 54, 54, 54
For first, third and fifth packets its correct, but for the others its 6 bytes less than it should be.
Iam asking what these 6 bytes in packets are and how to find out the correct sizes using ipv4 and ether headers:
54, 60, 54, 60, 54, 60
In wireshark all of these packets has total_length 40 bytes and sizeof(ether_hdr) is 14 bytes -> it should be 54.
I guess the root cause is the minimum Ethernet frame length. As Wikipedia says, the minimum frame length is 64 bytes.
At the end of each Ethernet frame we add Frame Check Sequence (FCS, 4 octets), so it makes minimum 60 octets for Ethernet header and payload.
Now answering your questions:
I am asking what these 6 bytes in packets
Those are zero paddings to make ethernet frame (with FCS) at least 64 octets.
For outgoing packets, there are no paddings yet, they will be added later by the driver or NIC itself. So Wireshark shows unpadded frames, i.e. 40 bytes of IP + 14 bytes of Ethernet header (without FCS) makes 54 bytes.
For incoming packets, there are already paddings added by the sending part. So Wireshark shows frames with padding, i.e. 64 octets - 4 octets FCS = 60 octets.
how to find out the correct sizes using ipv4 and ether headers
Your method is completely correct. Those zeros at the end of the frame are just padding and should be ignored. If we really need a correct length, we should take into account the minimum frame length as described above.
I have 500 frames for which I have stored the length of each frame in an array as the frames are in ascending order.
const char header_length = {23,34, 45, 12, 23,56,......,2,4};
Here frame 1 is of length 23 bytes, frame 2 is of length 34 bytes.
Now when I am requested frame with header 4 I would have to reply with frame with header 7, frame with header 8 would require a reply frame with header 60. The co-relation is a constant, header 4 frame will always reply header 7 frame. So I need a look up table sort of implementation here. I plan to implement this using a multidimensional array. Although is there a better way to implement this?
I am answering based on OP's comment above, otherwise OP's question just does not make any sense.
Assuming that the maximum frame size is limited by a considerably small N, then it may be better to just keep another array as the following,
const char header_length[] = {23,34, 45, 12, 23,56,......,2,4};
const int to_be_replied[N+1] = {...,0,...,2,...,0,...,4,...}; /* fill remaining */
/* here are their positions #12 #23 #34 #45 */
and use the following during the reply.
int frame_num, reply_frame_num;
frame_num = get_frame_number(); /* some function */
reply_frame_num = to_be_replied[header_length[frame_num]];
the problem is, I want to open order when my indicator gives signal. How can I do that?
I have been trying to do with iCustom() but it is not satisfying.
I tried to use GlobalVariableSet() in indicator and GlobalVariableGet() method in EA but it is not properly worked.
Please help.
The syntax is:
double iCustom(
string symbol, // symbol
int timeframe, // timeframe
string name, // path/name of the custom indicator compiled program
... // custom indicator input parameters (if necessary)
int mode, // line index
int shift // shift
);
Here is the example using custom Alligator indicator (which should be available by default as Alligator.mq4 in MT platform).
double Alligator[3];
Alligator[0] = iCustom(NULL, 0, "Alligator", 13, 8, 8, 5, 5, 3, 0, 0);
Alligator[1] = iCustom(NULL, 0, "Alligator", 13, 8, 8, 5, 5, 3, 1, 0);
Alligator[2] = iCustom(NULL, 0, "Alligator", 13, 8, 8, 5, 5, 3, 2, 0);
where 13, 8, 8, 5, 5, 3 are corresponding input parameters of custom Alligator as defined in indicator it-self:
//---- input parameters
input int InpJawsPeriod=13; // Jaws Period
input int InpJawsShift=8; // Jaws Shift
input int InpTeethPeriod=8; // Teeth Period
input int InpTeethShift=5; // Teeth Shift
input int InpLipsPeriod=5; // Lips Period
input int InpLipsShift=3; // Lips Shift
and mode is the corresponding line index as defined in the indicator by:
SetIndexBuffer(0, ExtBlueBuffer);
SetIndexBuffer(1, ExtRedBuffer);
SetIndexBuffer(2, ExtLimeBuffer);
The syntax is:
int signal = iCustom(NULL, 0, "MyCustomIndicatorName",
...parameters it takes in...,
...the buffer index you want from the custom indicator...,
...shift in bars);
Let's say you wrote a custom moving average indicator called "myMA" and it takes in a period only as one of its extern variables. This indicator calculates a simple moving average based on the period that the user supplies and on the close of each bar. This indicator stores its calculated values in an array MAValues[] that gets assigned to an index like this: SetIndexBuffer(0, MAValues);
To get the moving average of the current bar with period 200 then, you would write:
double ma_current_bar = iCustom(NULL, 0, "myMA", 200, 0, 0);
Then once you have this value you can check it against some trading criteria you determine, and open an order when it is met. For example if you wanted to open a long position if the moving average of the current bar equals the current Ask price, you would write:
if (ma_current_bar == Ask){
OrderSend(Symbol(), OP_BUY, 1, Ask, *max slippage*, *sl*, *tp*, NULL, 0, 0, GREEN);
}
This is just example code, do NOT use this in a live EA.
Below is the a sample C Program which provides the output followed after the program
#include<stdio.h>
void newfunc(int n);
int main(void)
{
newfunc(2);
return 0;
}
void newfunc(int n)
{
printf("\n%d",n);
if(n<50)
{
newfunc(2*n);
printf("\n%d",n);
}
}
produces output
2
4
8
16
32
64
32
16
8
4
2
But according to the code, it seems that after the function call in line 13, the next printf is not called. And the output seems unnatural. I searched the internet and found something about stacks. Can someone elaborate why this happens?
This is a basic recursive call.
First, notice that for values of n less than 50 your function will print n twice, and for other values of n it will print only once. That agrees with your output,so the only thing to figure out here is the order...
Second notice that the output for n*2 should come between the first and second line of output from n (for n < 50), because you make the recursive call in between the two printfs. Well, that also agrees with your output.
This is as expected.
The part you found on the internet about stacks is referring to the call stack. In order to return from a function the program has to keep track of where it was when the function was called. This information is written to 'end' of a special part of memory called the "call stack" or "execution stack"; and it is taken off of the stack (meaning that the 'end' is moved when the function returns). Call parameters are also recorded on the stack.
This kind of stacking is essential to recursion.
So, when you call newfunc(2) the program records that it was on line 5, then jumps to the beginning of newfunc on line 8. The stack looks (notionally) like:
line 5, n=2
When it gets to line 13, it calls new function again, making the stack
line 5, n=2; line 13, n=4
This goes on several times until the stack looks like
line 5, n=2; line 13, n=4; line 13, n=8; line 13, n=16; line 13, n=32; line 13, n=64
when the if fails and newfunc returns poping the stack and resuming execution after line 13 (because that is what we got off the stack) making the stack
line 5, n=2; line 13, n=4; line 13, n=8; line 13, n=16; line 13, n=32
when we run printf and pop the stack as we return to line 13 (what we got when we popped, right>) so that the stack is
line 5, n=2; line 13, n=4; line 13, n=8; line 13, n=16;
and so on while it unwinds the whole call stack.
A couple of final details: the stack notionally grows "up" so we often write it as
line 13, n=32
line 13, n=16
line 13, n=8
line 13, n=4
line 5, n=2
and the exact format of the stuff of the stack depends on the architecture of the chip and some decisions made by the OS programmers.
BTW--a c program doesn't typically use line numbers to denote "where" it was because lines are not good measures in c (I can write the whole program one one line if I'm silly enough), rather it uses the value of a register on the chip, but that doesn't really affect the explanation here.
What actually happens is, when you call the function in line 13 the code after the function cannot execute at that time, so they are stored in a special place in memory called stacks and they are filled up from bottom so newer codes fill in the top of the stacks. So at the first function call the printf("\n%d",2) is added to the stack at the bottom and printf("\n%d",4); i.e, 2 * n = 2 * 2 = 4 is added to top of the previous stack and when the recursive execution stops. the stack program from top is executed producing the above complex type of output not predictable to simple analysis.
Lets take it for small value say 10
1st call from main ////returned from newfunc(2)
newfunc(2)
//inside newfunc(2)
print 2
2<10 (correct)
newfunc(4) --> on stack print 2 //returned from newfunc(4)
-------------------------------
//inside newfunc(4)
print 4
4<10
newfunc(8) --> on stack print 4 //returned from newfunc(8)
---------------------------------
//inside newfunc(8)
print 8
8<10
newfunc(16) --> on stack print 8 //returned from newfunc(16)
---------------------------
//inside newfunc(16)
print 16
16<10 failed
so it will return to its previous function whichever has called it so it will go on --> symbol which is top of stack here for this example and print is used to show the result on screen
Function sequence is top to down ... I tried to show this in diagram. hope you get it.
here --> statement will be executed from bottom to top so the result will be
2
4
8
16
8
4
2