Find source address from multicast message in esp8266? - ip

I'm using non-OS SDK v2.0 for esp8266.
I join a multicast group.
I then receive a message (that was sent to multicast).
I want to respond to the sender, but in struct espconn, udp.remote_ip is the address of the multicast group, not sender.
How do I get the ip address of the sender?
Edit:
Receive function has an void* arg argument that is casted to struct espconn.

The old method doesn't do the job anymore, but I found a way to find remote ip and port.
New code:
struct espconn* udp_ch;
remot_info *premot = NULL;
udp_ch = arg;
if (espconn_get_connection_info(udp_ch,&premot,0) == ESPCONN_OK){
os_printf("%d.%d.%d.%d:%d\n", premot->remote_ip[0], premot->remote_ip[1], premot->remote_ip[2], premot->remote_ip[3], premot->remote_port);
}
else{
os_printf("Get info fail\n");
}
This is exactly what I was searching for before. For now, as far as I can see, it works well.
OLD:
I found a way to find the ip, but I don't think it should be done this way. Until I find better, I will use this.
The first thing I did was print first 256 hex values, from void* arg.
I noticed that my address was occurring before a bunch of zeros.
On unicast, the starting position of 0s was 128.
I'm currently using this function:
uint32_t udp_get_addr(void* arg){
uint32_t adr = 0;
uint16_t pos;
uint8_t* data = (uint8_t*) arg;
//unicast?
for(pos = 128; pos<144; pos++){
if(data[pos] != 0){
adr = 1;
break;
}
}
//multicast
if(adr == 1)
pos = 172;
else
pos = 124;
adr = data[pos]<<24 | data[pos+1]<<16 | data[pos+2]<<8 | data[pos+3];
return adr;
}
I know this method is bad, and there is a number of things that can be changed for the better, but for now, this will do.
Edit2:
I needed the source port also. It is located 4 bytes before address. New functions that I currently use:
#define SRC_ADDR_U 120
#define SRC_ADDR_M 168
uint32_t udp_src_addr(void* arg, uint8_t isMulticast){
uint32_t res;
uint8_t* tmp = (uint8_t*) arg;
uint16_t pos;
if(isMulticast) pos = SRC_ADDR_M+4;
else pos = SRC_ADDR_U+4;
res = (tmp[pos+3] << 24) | (tmp[pos+2] << 16) | (tmp[pos+1] << 8) | tmp[pos];
return res;
}
uint16_t udp_src_port(void* arg, uint8_t isMulticast){
uint32_t res;
uint8_t* tmp = (uint8_t*) arg;
uint16_t pos;
if(isMulticast) pos = SRC_ADDR_M;
else pos = SRC_ADDR_U;
res = (tmp[pos+1] << 8) | tmp[pos];
return res;
}

Related

Float variable to HEX in Arduino

I want to convert my float variables into HEX value like 0x00466 or etc. but when I try all the things that I saw in the internet my Serial Console just turns out crazy :D like "' #gA".
I tried this code below
float gyrox, gyroy, gyroz, accelx, accely, accelz, enlem, boylam, sicaklik, yukseklik, basinc;
byte ByteArray[11];
void setup() {
Serial.begin(9600);
gyrox = 1.5;
gyroy = 2.5;
gyroz = 2.0;
accelx = 5.3;
accely = 3.2;
accelz = 6.1;
enlem = 39.9250506;
boylam = 32.8369756;
sicaklik = 35.0;
yukseklik = 103.0;
basinc = 65.31455;
ByteArray[0]=(gyrox,HEX);
ByteArray[1]=(gyroy,HEX);
ByteArray[2]=(gyroz,HEX);
ByteArray[3]=(accelx,HEX);
ByteArray[4]=(accely,HEX);
ByteArray[5]=(accelz,HEX);
ByteArray[6]=(enlem,HEX);
ByteArray[7]=(boylam,HEX);
ByteArray[8]=(sicaklik,HEX);
ByteArray[9]=(yukseklik,HEX);
ByteArray[10]=(basinc,HEX);
}
void loop() {
Serial.println((char*)ByteArray);
}
and the result is ""(:D) I want the result like "0x000466 or anything likte HEX value" so what should I do?
You can cast the float to an array of bytes to get its internal representation. Then you can loop over all of the bytes and print each of them individually.
void printFloat(float const f)
{
// cast the float to an array of bytes
uint8_t const * const byteArray = (uint8_t const *)&f;
// print the start
Serial.print("0x");
// loop over the bytes, sizeof(f) tells us how many bytes make up the float
for (size_t idx = 0; idx != sizeof(f); ++idx)
{
// get the byte for this position
uint8_t const b = byteArray[idx];
// print a zero if b < 16,
// https://stackoverflow.com/questions/19127945/how-to-serial-print-full-hexadecimal-bytes
Serial.print(b>>4, HEX);
Serial.print(b&0x0F,HEX);
}
}
A float is 32 bits long (4 bytes). You can try this:
float f;
Serial.print("0x"); Serial.print(*(uint32_t*)&f, HEX);
If you really need leading zeroes, try this:
void hex_print(uint32_t x)
{
Serial.print("0x");
for (uint32_t mask = 0x0FFFFFFFul; mask && mask > x; mask >>= 4)
Serial.print('0');
Serial.print(x, HEX);
}
// calling as:
float f = 123.456f;
hex_print(*(uint32_t*)&f);

ili9341 Not Working on STM32f4 discovery

I am testing IlI9341 3.2 TFT LCD on stm32F4-discovery. I wired based on Discovery datasheet. I also read ILI9341 datasheet and went through all registers.
However I get nothing. Also, the LD7, LD5 and LD6 keep on indicating overflow of current. Compiled using Coocox IDE.
The functions SETCURSORPOSITION and FILL are further down.
Here is my code if someone can help me. Thank you.
#include "stm32f4xx.h"
#include "stm32f4xx_rcc.h"
#include "stm32f4xx_gpio.h"
#include "stm32f4xx_fsmc.h"
#include "LCD.h"
#define LCD_REG (*((volatile unsigned short *) 0x60000000))//address
#define LCD_RAM (*((volatile unsigned short *) 0x60020000))//data
#define MAX_X 320//landscape mode
#define MAX_Y 240//landscape mode
#define ILI9341_PIXEL 76800
#define Green 0x07E0
void LCD_PinsConfiguration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD,ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOD,&GPIO_InitStructure);
GPIO_ResetBits(GPIOD,GPIO_Pin_7);
RCC_AHB3PeriphClockCmd(RCC_AHB3Periph_FSMC,ENABLE);
GPIO_PinAFConfig(GPIOD,GPIO_PinSource0,GPIO_AF_FSMC);
GPIO_PinAFConfig(GPIOD,GPIO_PinSource1,GPIO_AF_FSMC);
GPIO_PinAFConfig(GPIOD,GPIO_PinSource4,GPIO_AF_FSMC);
GPIO_PinAFConfig(GPIOD,GPIO_PinSource5,GPIO_AF_FSMC);
GPIO_PinAFConfig(GPIOD,GPIO_PinSource8,GPIO_AF_FSMC);
GPIO_PinAFConfig(GPIOD,GPIO_PinSource9,GPIO_AF_FSMC);
GPIO_PinAFConfig(GPIOD,GPIO_PinSource10,GPIO_AF_FSMC);
GPIO_PinAFConfig(GPIOD,GPIO_PinSource11,GPIO_AF_FSMC);
GPIO_PinAFConfig(GPIOD,GPIO_PinSource14,GPIO_AF_FSMC);
GPIO_PinAFConfig(GPIOD,GPIO_PinSource15,GPIO_AF_FSMC);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_8|GPIO_Pin_9|GPIO_Pin_10|GPIO_Pin_11|GPIO_Pin_14|GPIO_Pin_15;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(GPIOD,&GPIO_InitStructure);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE,ENABLE);
GPIO_PinAFConfig(GPIOE,GPIO_PinSource2,GPIO_AF_FSMC);
GPIO_PinAFConfig(GPIOE,GPIO_PinSource7,GPIO_AF_FSMC);
GPIO_PinAFConfig(GPIOE,GPIO_PinSource8,GPIO_AF_FSMC);
GPIO_PinAFConfig(GPIOE,GPIO_PinSource9,GPIO_AF_FSMC);
GPIO_PinAFConfig(GPIOE,GPIO_PinSource10,GPIO_AF_FSMC);
GPIO_PinAFConfig(GPIOE,GPIO_PinSource11,GPIO_AF_FSMC);
GPIO_PinAFConfig(GPIOE,GPIO_PinSource12,GPIO_AF_FSMC);
GPIO_PinAFConfig(GPIOE,GPIO_PinSource13,GPIO_AF_FSMC);
GPIO_PinAFConfig(GPIOE,GPIO_PinSource14,GPIO_AF_FSMC);
GPIO_PinAFConfig(GPIOE,GPIO_PinSource15,GPIO_AF_FSMC);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2|GPIO_Pin_7|GPIO_Pin_8|GPIO_Pin_9|GPIO_Pin_10|GPIO_Pin_11|GPIO_Pin_12|GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(GPIOD,&GPIO_InitStructure);
Delay(5000);
RCC_AHB3PeriphClockCmd(RCC_AHB3Periph_FSMC,ENABLE);
FSMC_NORSRAMInitTypeDef FSMC_NORSRAMInitStructure;
FSMC_NORSRAMTimingInitTypeDef FSMC_NORSRAMTimingInitStructure;
FSMC_NORSRAMTimingInitStructure.FSMC_AddressSetupTime = 0x0F;
FSMC_NORSRAMTimingInitStructure.FSMC_AddressHoldTime = 0;
FSMC_NORSRAMTimingInitStructure.FSMC_AddressSetupTime = 5;
FSMC_NORSRAMTimingInitStructure.FSMC_BusTurnAroundDuration =0;
FSMC_NORSRAMTimingInitStructure.FSMC_CLKDivision = 0;
FSMC_NORSRAMTimingInitStructure.FSMC_DataLatency =0;
FSMC_NORSRAMTimingInitStructure.FSMC_AccessMode = FSMC_AccessMode_A;
FSMC_NORSRAMInitStructure.FSMC_Bank = FSMC_Bank1_NORSRAM1;
FSMC_NORSRAMInitStructure.FSMC_DataAddressMux = FSMC_DataAddressMux_Disable;
FSMC_NORSRAMInitStructure.FSMC_MemoryType = FSMC_MemoryType_SRAM;
FSMC_NORSRAMInitStructure.FSMC_MemoryDataWidth = FSMC_MemoryDataWidth_16b;
FSMC_NORSRAMInitStructure.FSMC_BurstAccessMode = FSMC_BurstAccessMode_Disable;
FSMC_NORSRAMInitStructure.FSMC_WaitSignalPolarity = FSMC_WaitSignalPolarity_Low;
FSMC_NORSRAMInitStructure.FSMC_WrapMode = FSMC_WrapMode_Disable;
FSMC_NORSRAMInitStructure.FSMC_WaitSignalActive = FSMC_WaitSignalActive_BeforeWaitState;
FSMC_NORSRAMInitStructure.FSMC_WriteOperation = FSMC_WriteOperation_Enable;
FSMC_NORSRAMInitStructure.FSMC_AsynchronousWait = FSMC_AsynchronousWait_Disable;
FSMC_NORSRAMInitStructure.FSMC_ExtendedMode = FSMC_ExtendedMode_Disable;
FSMC_NORSRAMInitStructure.FSMC_WriteBurst = FSMC_WriteBurst_Disable;
FSMC_NORSRAMInitStructure.FSMC_ReadWriteTimingStruct = &FSMC_NORSRAMTimingInitStructure;
FSMC_NORSRAMInit(&FSMC_NORSRAMInitStructure);
FSMC_NORSRAMCmd(FSMC_Bank1_NORSRAM1,ENABLE);
}
void LCD_Initialization(void)
{
LCD_PinsConfiguration();
LCD_ILI9341_SendCommand(0x01);
Delay(50000);
LCD_ILI9341_SendCommand(0xcb);
LCD_ILI9341_SendData(0x39);
LCD_ILI9341_SendData(0x2C);
LCD_ILI9341_SendData(0x00);
LCD_ILI9341_SendData(0x34);
LCD_ILI9341_SendData(0x02);
LCD_ILI9341_SendCommand(0xcf);
LCD_ILI9341_SendData(0x00);
LCD_ILI9341_SendData(0xC1);
LCD_ILI9341_SendData(0x30);
LCD_ILI9341_SendCommand(0xe8);
LCD_ILI9341_SendData(0x85);
LCD_ILI9341_SendData(0x00);
LCD_ILI9341_SendData(0x78);
LCD_ILI9341_SendCommand(0xea);
LCD_ILI9341_SendData(0x00);
LCD_ILI9341_SendData(0x00);
LCD_ILI9341_SendCommand(0xed);
LCD_ILI9341_SendData(0x64);
LCD_ILI9341_SendData(0x03);
LCD_ILI9341_SendData(0x12);
LCD_ILI9341_SendData(0x81);
LCD_ILI9341_SendCommand(0xf7);
LCD_ILI9341_SendData(0x20);
LCD_ILI9341_SendCommand(0xc0);
LCD_ILI9341_SendData(0x23);
LCD_ILI9341_SendCommand(0xc1);
LCD_ILI9341_SendData(0x10);
LCD_ILI9341_SendCommand(0xc5);
LCD_ILI9341_SendData(0x3E);
LCD_ILI9341_SendData(0x28);
LCD_ILI9341_SendCommand(0xc7);
LCD_ILI9341_SendData(0x86);
LCD_ILI9341_SendCommand(0x36);
LCD_ILI9341_SendData(0x48);
LCD_ILI9341_SendCommand(0x3a);
LCD_ILI9341_SendData(0x55);
LCD_ILI9341_SendCommand(0xb1);
LCD_ILI9341_SendData(0x00);
LCD_ILI9341_SendData(0x18);
LCD_ILI9341_SendCommand(0xb6);
LCD_ILI9341_SendData(0x08);
LCD_ILI9341_SendData(0x82);
LCD_ILI9341_SendData(0x27);
LCD_ILI9341_SendCommand(0xf2);
LCD_ILI9341_SendData(0x00);
LCD_ILI9341_SendCommand(0x2a);
LCD_ILI9341_SendData(0x00);
LCD_ILI9341_SendData(0x00);
LCD_ILI9341_SendData(0x00);
LCD_ILI9341_SendData(0xEF);
LCD_ILI9341_SendCommand(0x2b);
LCD_ILI9341_SendData(0x00);
LCD_ILI9341_SendData(0x00);
LCD_ILI9341_SendData(0x01);
LCD_ILI9341_SendData(0x3F);
LCD_ILI9341_SendCommand(0x26);
LCD_ILI9341_SendData(0x01);
LCD_ILI9341_SendCommand(0xe0);
LCD_ILI9341_SendData(0x0F);
LCD_ILI9341_SendData(0x31);
LCD_ILI9341_SendData(0x2B);
LCD_ILI9341_SendData(0x0C);
LCD_ILI9341_SendData(0x0E);
LCD_ILI9341_SendData(0x08);
LCD_ILI9341_SendData(0x4E);
LCD_ILI9341_SendData(0xF1);
LCD_ILI9341_SendData(0x37);
LCD_ILI9341_SendData(0x07);
LCD_ILI9341_SendData(0x10);
LCD_ILI9341_SendData(0x03);
LCD_ILI9341_SendData(0x0E);
LCD_ILI9341_SendData(0x09);
LCD_ILI9341_SendData(0x00);
LCD_ILI9341_SendCommand(0xe1);
LCD_ILI9341_SendData(0x00);
LCD_ILI9341_SendData(0x0E);
LCD_ILI9341_SendData(0x14);
LCD_ILI9341_SendData(0x03);
LCD_ILI9341_SendData(0x11);
LCD_ILI9341_SendData(0x07);
LCD_ILI9341_SendData(0x31);
LCD_ILI9341_SendData(0xC1);
LCD_ILI9341_SendData(0x48);
LCD_ILI9341_SendData(0x08);
LCD_ILI9341_SendData(0x0F);
LCD_ILI9341_SendData(0x0C);
LCD_ILI9341_SendData(0x31);
LCD_ILI9341_SendData(0x36);
LCD_ILI9341_SendData(0x0F);
LCD_ILI9341_SendCommand(0x11);
Delay(50000);
LCD_ILI9341_SendCommand(0x29);
LCD_ILI9341_SendCommand(0x22);
}
void LCD_ILI9341_SendCommand(uint16_t index)
{
LCD_REG = index;
}
void LCD_ILI9341_SendData(uint16_t data)
{
LCD_RAM = data;
}
void LCD_ILI9341_SetCursorPosition(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2) {
LCD_ILI9341_SendCommand(0x2A);
LCD_ILI9341_SendData(x1 >> 8);
LCD_ILI9341_SendData(x1 & 0xFF);
LCD_ILI9341_SendData(x2 >> 8);
LCD_ILI9341_SendData(x2 & 0xFF);
LCD_ILI9341_SendCommand(0x2B);
LCD_ILI9341_SendData(y1 >> 8);
LCD_ILI9341_SendData(y1 & 0xFF);
LCD_ILI9341_SendData(y2 >> 8);
LCD_ILI9341_SendData(y2 & 0xFF);
}
void LCD_ILI9341_Fill(uint16_t color) {
unsigned int n, i, j;
i = color >> 8;
j = color & 0xFF;
LCD_ILI9341_SetCursorPosition(0, 0, MAX_Y - 1, MAX_X - 1);
LCD_ILI9341_SendCommand(0x0022);
for (n = 0; n < ILI9341_PIXEL; n++) {
LCD_ILI9341_SendData(i);
LCD_ILI9341_SendData(j);
}
}
void Delay(__IO uint32_t nCount)
{
while(nCount--)
{
}
}
I am going to answer my own question to make it clear things got solved. But I want to thank the community.
Actually I did few things: I removed GPIOE 2 from configuration block, because it was not being used. I replaced GPIOD to GPIOE in the same block. Inside "LCD_ILI9341_Fill" I changed "LCD_ILI9341_SendCommand(0x0022)" to "LCD_ILI9341_SendCommand(0x002C)". 0x002C is the actual Memory Write address to where you write the data on ili9341. I also connected the LCD RESET pin to the stm32f4 NRST pin. 3V power was connected to LCD LED_A.
Now everything works, I still get wrong colors but I need to make few changes on registers, such as register 36h.
There is a typo there, you're not configuring GPIOE at all.
change the last GPIO_Init() call to
GPIO_Init(GPIOE,&GPIO_InitStructure);
instead of configuring the wrong pins of GPIOD again.
I wired based on Discovery datasheet.
Do you mean the extension board datasheet? Because the Discovery datasheet says nothing about LCD controllers.
LD7, LD5 and LD6 keep on indicating overflow of current
Are you sure? The overcurrent indicator is LD8 (red). You should expect some random lighting up or flickering of LD5, LD6, and LD8, because they are connected to the LCD data lines, but not on LD7.

Update UDP checksum in fragmented packets

I'm building a network appliance. I need to support NAT and IP packet fragmentation. When I change the source or destination address of a UDP packet, I have to correct the UDP checksum (and the IP checksum too, but that's trivial). When the packet is fragmented, I'd have to collect all the fragments to recalculate the checksum. I know the old address and the new address. I'd like to:
Un-negate the checksum
Subtract the old address
Add the new address
Re-reduce the sum and negate
This process doesn't always work. Is there any way to update the checksum versus having to recalculate it from scratch?
I've tried:
long CalcCheckSumAdd(unsigned char *pbHeader, int iSize, long lInitial){
long lSum = lInitial;
while (iSize > 1){
lSum += *((unsigned short*)pbHeader);
pbHeader += 2;
iSize -= 2;
}
if (iSize > 0) lSum += *pbHeader;
return lSum;
}
long CalcCheckSumSubract(unsigned char *pbHeader, int iSize, long lInitial){
long lSum = lInitial;
while (iSize > 1){
lSum -= *((unsigned short*)pbHeader);
pbHeader += 2;
iSize -= 2;
}
if (iSize > 0) lSum -= *pbHeader;
return lSum;
}
unsigned short CalcCheckSumFinish(long lSum){
while (lSum >> 16){
lSum = (lSum & 0xFFFF) + (lSum >> 16);
}
return (unsigned short)(~lSum);
}
long CalcCheckSumUnfinish(unsigned short usSum){
// Can't totally undo lossy finish logic
return ~usSum;
}
unsigned short CalcCheckSumUpdateAddress(unsigned short usOldSum, unsigned long ulOldAddress, unsigned long ulNewAddress){
long lSumFixed = CalcCheckSumUnfinish(usOldSum);
lSumFixed = CalcCheckSumSubract((unsigned char*)&ulOldAddress,sizeof(ulOldAddress),lSumFixed);
lSumFixed = CalcCheckSumAdd((unsigned char*)&ulNewAddress,sizeof(ulNewAddress),lSumFixed);
return CalcCheckSumFinish(lSumFixed);
}
Thanks!
EDIT: Added unit test code below
#include <time.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
long CalcCheckSumAdd(unsigned char *pbHeader, int iSize, long lInitial){
long lSum = lInitial;
while (iSize > 1){
lSum += *((unsigned short*)pbHeader);
pbHeader += 2;
iSize -= 2;
}
if (iSize > 0) lSum += *pbHeader;
return lSum;
}
unsigned short CalcCheckSumFinish(long lSum){
while (lSum >> 16){
lSum = (lSum & 0xFFFF) + (lSum >> 16);
}
return (unsigned short)(~lSum);
}
void Randomize(unsigned char *pucPacket, unsigned long ulSize){
for (unsigned long ulByte = 0; ulByte < ulSize; ulByte++){
pucPacket[ulByte] = (unsigned char)(255 * rand() / RAND_MAX);
}
}
unsigned short Calc(unsigned char *pucPacket, unsigned long ulSize){
long lSum = CalcCheckSumAdd(pucPacket,ulSize,0);
return CalcCheckSumFinish(lSum);
}
unsigned short Fix(unsigned short usOrig, unsigned int uiOld, unsigned int uiNew){
// TODO: Replace this with something that makes main never fail
usOrig -= uiOld & 0xffff;
usOrig -= uiOld >> 16 & 0xffff;
usOrig += uiNew & 0xffff;
usOrig += uiNew >>16 & 0xffff;
return usOrig;
}
void Break(unsigned char *pucPacket, unsigned int *puiOld, unsigned int *puiNew){
unsigned int *puiChange = (unsigned int*)pucPacket;
*puiOld = *puiChange;
Randomize((unsigned char*)puiNew,sizeof(unsigned int));
*puiChange = *puiNew;
}
void PrintBuffer(const char *szName, unsigned char *pucBuff, unsigned int uiSize){
printf("%s: ",szName);
for (unsigned int uiByte = 0; uiByte < uiSize; uiByte++){
printf("%02X",(unsigned int)pucBuff[uiByte]);
}
printf("\n");
}
void PrintTestCase(unsigned char *pucOrig, unsigned char *pucChanged, unsigned int uiSize, unsigned short usOrig, unsigned short usChanged, unsigned short usFixed){
PrintBuffer("Original Buffer",pucOrig,uiSize);
PrintBuffer("Changed Buffer ",pucChanged,uiSize);
printf("Orig checksum: %04X\n",(unsigned int)usOrig);
printf("Changed checksum: %04X\n",(unsigned int)usChanged);
printf("Fixed checksum: %04X\n",(unsigned int)usFixed);
}
int main(){
srand((unsigned int)time(nullptr));
unsigned char pucDataOrig[100];
unsigned char pucDataChanged[100];
bool bTestFailed = false;
while (!bTestFailed){
Randomize(pucDataOrig,sizeof(pucDataOrig));
memcpy(pucDataChanged,pucDataOrig,sizeof(pucDataOrig));
unsigned short usOrig = Calc(pucDataOrig,sizeof(pucDataOrig));
unsigned int uiOld = 0,
uiNew = 0;
Break(pucDataChanged,&uiOld,&uiNew);
unsigned short usFixed = Fix(usOrig,uiOld,uiNew);
unsigned short usChanged = Calc(pucDataChanged,sizeof(pucDataChanged));
if (usChanged == usFixed){
printf(".");
}else{
printf("\nTest case failed\n");
PrintTestCase(pucDataOrig,pucDataChanged,sizeof(pucDataOrig),usOrig,usChanged,usFixed);
bTestFailed = true;
}
}
return 0;
}
You are right, the solution above works only on some cases, but I have a new implem that works for all kind of packet (fragmented or not, UDP, TCP, IP). Here is the implem:
/* incremental checksum update */
static inline void
cksum_update(uint16_t *csum, uint32_t from, uint32_t to)
{
uint32_t sum, csum_c, from_c, res, res2, ret, ret2;
csum_c = ~((uint32_t)*csum);
from_c = ~from;
res = csum_c + from_c;
ret = res + (res < from_c);
res2 = ret + to;
ret2 = res2 + (res2 < to);
sum = ret2;
sum = (sum & 0xffff) + (sum >> 16);
sum = (sum & 0xffff) + (sum >> 16);
*csum = (uint16_t)~sum;
}
You can now use this function when you translated you packet address and before sending:
/* Update L4 checksums on all packet a part from [2nd, n] fragment */
switch (IS_FRAG(ipv4_hdr) ? 0 : ipv4_hdr->next_proto_id) {
case IPPROTO_TCP:
{
struct tcp_hdr *tcp_hdr = tcp_header(pkt);
/* Compute TCP checksum using incremental update */
cksum_update(&tcp_hdr->cksum, old_ip_addr, *address);
break;
}
case IPPROTO_UDPLITE:
case IPPROTO_UDP:
{
struct udp_hdr *udp_hdr = udp_header(pkt);
/* Compute UDP checksum using incremental update */
cksum_update(&udp_hdr->dgram_cksum, old_ip_addr, *address);
break;
}
default:
break;
}
You have to substract the old ip address and add the new one on the udp checksum, here is the pseudo code:
udp_hdr->dgram_cksum -= old_ipv4_addr & 0xffff;
udp_hdr->dgram_cksum -= old_ipv4_addr >> 16 & 0xffff;
udp_hdr->dgram_cksum += new_ipv4_addr & 0xffff;
udp_hdr->dgram_cksum += new_ipv4_addr >>16 & 0xffff;
That should handle UDP checksum on IP fragments.

IP Camera h264 streaming using udp multicast with RTPS

I have a video conference software that works with h264 multicast streamings, now I need to make this software works with an ip camera that provides an RTPS control interface.
I requested the h264 stream and it's coming via udp multicast, the packages are in RTP format.
So, acording with some research I need to remove the RTP header from the udp payload to have my wanted data, and I need to reconstruct the I frames becouse they may be fragmented.
I'm using Qt and the class QUdpSocket
QByteArray IDR;
while(socket->hasPendingDatagrams())
{
int pendingDataSize = socket->pendingDatagramSize();
char * data = (char *) malloc(pendingDataSize);
socket->readDatagram(data, pendingDataSize);
int fragment_type = data[12] & 0x1F;
int nal_type = data[13] & 0x1F;
int start_bit = data[13] & 0x80;
int end_bit = data[13] & 0x40;
//If it is an I Frame
if (((fragment_type == 28) || (fragment_type == 29)) && (nal_type == 5))
{
if(start_bit == 128 && end_bit == 64)
{
char nalByte = (data[12] & 0xE0) | (data[13] & 0x1F);
data[13] = nalByte;
char * dataWithoutHeader = data + 13;
uint8_t* datagramToQueue = (uint8_t*) queue_malloc(pendingDataSize - 13);
memcpy(datagramToQueue, dataWithoutHeader, pendingDataSize - 13);
f << "\nI Begin + I End\n";
}
if(start_bit == 128)
{
f << "\nI Begin\n";
char nalByte = (data[12] & 0xE0) | (data[13] & 0x1F);
data[13] = nalByte;
char * dataWithoutHeader = data + 13;
IDR.append(dataWithoutHeader, pendingDataSize - 13);
}
if(end_bit == 64)
{
f << "\nI End\n";
char* dataWithoutHeader = data + 13;
IDR.append(dataWithoutHeader, pendingDataSize - 13);
datagramToQueue = (uint8_t*) queue_malloc(IDR.size());
memcpy(datagramToQueue, IDR.data(), IDR.size());
queue_enqueue(this->encodedQueue, datagramToQueue, IDR.size(),0, NULL);
IDR.clear();
}
if(start_bit != 128 && end_bit != 64)
{
char* dataWithoutHeader = data + 13;
IDR.append(dataWithoutHeader, pendingDataSize - 13);
}
f << "\nI\n";
continue;
}
f << "\nP\n";
uint8_t* datagramToQueue = (uint8_t*) queue_malloc(pendingDataSize - 12);
char* datacharMid = data + 13;
memcpy(datagramToQueue, datacharMid, pendingDataSize - 12);
queue_enqueue(this->encodedQueue, datagramToQueue, pendingDataSize - 12,0, NULL);
}
To decode the stream, My software have two implementations, the first uses FFMPEG and the second Intel Media SDK.
The both identifies the parametes of the video, FFMPEG shows as result a little strip of video where I can define some stuff that is in front of the camera and the rest of image is an entire mass with the colors of my scenario. The Intel Media SDK results in a pink screen with some gray lines moving around.
So, someone can tell me if there is some mistake in my packages parser? The order fragment_type, start_bit, end_bit are coming just don't make much sense to me.

Why does serial communication only work in one direction (chip->PC) with my code?

I am writing code for an Arduino Mega 2560 in C and I am trying to do bidirectional communication over the serial port. However, only sending data from the Arduino to the PC works - the other way doesn't. The RX LED on the arduino shortly lights up, but my code doesn't receive the data (the LED connected to "pin 13" doesn't light up). Does anyone know how to fix this?
Here's the code that's running on the arduino:
#define USART_BAUDRATE 500000
#define BAUD_PRESCALE (((F_CPU / (USART_BAUDRATE * 16UL))) - 1)
static void serial_init(void) {
// load upper 8 bits of the baud rate into the high byte of the UBRR register
UBRR0H = (BAUD_PRESCALE >> 8);
// load lower 8 bits of the baud rate into the low byte of the UBRR register
UBRR0L = BAUD_PRESCALE;
// 8data,1stopbit
UCSR0C = (0 << UMSEL00) | (1 << UCSZ00) | (1 << UCSZ01);
// turn on the transmission and reception circuitry
UCSR0B = (1 << RXEN0) | (1 << TXEN0) | (0 << UCSZ02);
}
static void sendbyte(uint8_t b) {
// do nothing until UDR is ready for more data to be written to it
while ((UCSR0A & (1 << UDRE0)) == 0) {};
// memory was cleared - write to it
UDR0 = b;
}
static void digi_init() {
// configure port B7 (arduino digital port 13) as output and set it low
PORTB = (0<<PB7);
DDRB = (1<<DDB7);
}
static void digi_set(int val) {
PORTB = (val<<PB7);
}
int main(void) {
serial_init();
digi_init();
while (1) {
if ((UCSR0A & (1 << RXC0)) == 1) {
// we got some data, light up the LED!
digi_set(1);
}
_delay_ms(50);
sendbyte('.');
}
}
And here's the code that's running on the PC:
int main(int argc, char *argv[]) {
char *serialdevicepath = "/dev/ttyACM0";
fprintf(stderr, "Connecting to serial device ...\n");
int serial_fd = open(serialdevicepath, O_RDWR | O_NOCTTY);
struct termios config;
if(tcgetattr(serial_fd, &config) < 0) exit(1);
config.c_iflag &= ~(IGNBRK | BRKINT | ICRNL | INLCR | PARMRK | INPCK | ISTRIP | IXON);
config.c_lflag &= ~(ECHO | ECHONL | ICANON | IEXTEN | ISIG);
config.c_cflag &= ~(CSIZE | PARENB);
config.c_cflag |= CS8;
config.c_cc[VMIN] = 1;
config.c_cc[VTIME] = 0;
if(cfsetispeed(&config, B500000) < 0 || cfsetospeed(&config, B500000) < 0) exit(1);
if(tcsetattr(serial_fd, TCSAFLUSH, &config) < 0) exit(1);
FILE *serial = fdopen(serial_fd, "r");
setbuf(stdin, NULL);
fcntl(0/*stdin*/, F_SETFL, O_NONBLOCK);
setbuf(stdout, NULL);
setbuf(stderr, NULL);
setbuf(serial, NULL);
while (1) {
char c;
while (read(0, &c, 1) == 1) {
if (c != '+' && c != '-') continue;
uint8_t val = (c == '+') ? 42 : 41;
if (write(serial_fd, &val, 1) != 1) {
assert(0);
}
}
char b = fgetc(serial))&0xe0);
fprintf(stderr, "read 0x%x\n", b);
}
return 0;
}
(And yes, I am typing <+> on the PC so that it does send data. Also, I tried turning on the LED from the code directly and it worked.)
if ((UCSR0A & (1 << RXC0)) == 1)
That test is wrong, it will never be 1. The & operator here will produce either 0 or (1 << RXC0). Favor it this way instead:
if ((UCSR0A & (1 << RXC0)) != 0)
Or in C you'd typically write it this way since any non-zero value is logically true:
if (UCSR0A & (1 << RXC0))

Resources