Hi im trying to repeat this wifi baby monitor project based on esp8266:
baby monitor project
But instead of receiving data on another esp8266, I want to receive data on pc.
I'm a c # programmer and I've encountered an problem of understanding c/c++ pointers how arrays works here and receive udp.
this is esp8266 receiver source code which works without any problems, but data that it receives, passes them to DAC. And i cant figure out where i can read just values one by one which was readed by esp8266 transmiter from ADC. Also readed data from ADC is 12 bit and author of original code use all 16 bit with some compression to transfer more data, and this compression part is what i have difficulty to uderstand it
#include <Wire.h>
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <WiFiUdp.h>
#include "ESP8266mDNS.h"
#include <ArduinoOTA.h>
//#include "wifi_params.h"
const int mySDA = D7;
const int mySCL = D6;
const int AMPLI_MUTE_PIN = D2;
const int AMPLI_SHUTDOWN_PIN = D1;
const int RIGHT_BTN = D3;
const int LEFT_BTN = D4;
const int LED1 = D8;
const int udp_recv_port = 45990;
WiFiUDP udp;
TwoWire i2c;
#define NB_DATA_BUFS 5
uint16_t data_buf[NB_DATA_BUFS][700]; // data buffer, N buffered
unsigned int current_play_data_buf; // current data buf being played
unsigned int play_data_buf_pos; // position in the ADC data buffer
unsigned int current_recv_data_buf; // current data buf being received
bool play_waiting = true;
bool amplifier_stopped = false;
long play_waiting_at;
bool left_btn_pressed;
bool right_btn_pressed;
#define ICACHE_RAM_ATTR __attribute__((section(".iram.text")))
#define twi_sda mySDA
#define twi_scl mySCL
#define twi_dcount 0
#define twi_clockStretchLimit 10
#define SDA_LOW() (GPES = (1 << twi_sda)) //Enable SDA (becomes output and since GPO is 0 for the pin, it will pull the line low)
#define SDA_HIGH() (GPEC = (1 << twi_sda)) //Disable SDA (becomes input and since it has pullup it will go high)
#define SDA_READ() ((GPI & (1 << twi_sda)) != 0)
#define SCL_LOW() (GPES = (1 << twi_scl))
#define SCL_HIGH() (GPEC = (1 << twi_scl))
#define SCL_READ() ((GPI & (1 << twi_scl)) != 0)
static void twi_delay(unsigned char v) {
unsigned int i;
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
unsigned int reg;
for (i = 0; i<v; i++) reg = GPI;
#pragma GCC diagnostic pop
}
static inline ICACHE_RAM_ATTR bool twi_write_start(void) {
SCL_HIGH();
SDA_HIGH();
if (SDA_READ() == 0) return false;
SDA_LOW();
return true;
}
static inline ICACHE_RAM_ATTR bool twi_write_stop(void) {
uint32_t i = 0;
SCL_LOW();
SDA_LOW();
SCL_HIGH();
while (SCL_READ() == 0 && (i++) < twi_clockStretchLimit); // Clock stretching
SDA_HIGH();
return true;
}
static inline ICACHE_RAM_ATTR bool twi_write_bit(bool bit) {
uint32_t i = 0;
SCL_LOW();
if (bit) SDA_HIGH();
else SDA_LOW();
twi_delay(twi_dcount + 1);
SCL_HIGH();
while (SCL_READ() == 0 && (i++) < twi_clockStretchLimit);// Clock stretching
return true;
}
static inline ICACHE_RAM_ATTR bool twi_read_bit(void) {
uint32_t i = 0;
SCL_LOW();
SDA_HIGH();
twi_delay(twi_dcount + 2);
SCL_HIGH();
while (SCL_READ() == 0 && (i++) < twi_clockStretchLimit);// Clock stretching
bool bit = SDA_READ();
return bit;
}
static inline ICACHE_RAM_ATTR bool twi_write_byte(unsigned char byte) {
unsigned char bit;
for (bit = 0; bit < 8; bit++) {
twi_write_bit(byte & 0x80);
byte <<= 1;
}
return !twi_read_bit();//NACK/ACK
}
static inline ICACHE_RAM_ATTR unsigned char twi_read_byte(bool nack) {
unsigned char byte = 0;
unsigned char bit;
for (bit = 0; bit < 8; bit++) byte = (byte << 1) | twi_read_bit();
twi_write_bit(nack);
return byte;
}
unsigned char inline ICACHE_RAM_ATTR mytwi_writeTo(unsigned char address, unsigned char * buf, unsigned int len, unsigned char sendStop) {
unsigned int i;
if (!twi_write_start()) return 4;//line busy
if (!twi_write_byte(((address << 1) | 0) & 0xFF)) {
if (sendStop) twi_write_stop();
return 2; //received NACK on transmit of address
}
for (i = 0; i<len; i++) {
if (!twi_write_byte(buf[i])) {
if (sendStop) twi_write_stop();
return 3;//received NACK on transmit of data
}
}
if (sendStop) twi_write_stop();
i = 0;
while (SDA_READ() == 0 && (i++) < 10) {
SCL_LOW();
SCL_HIGH();
}
return 0;
}
static inline ICACHE_RAM_ATTR uint8_t DAC(uint16_t value)
{
/* value is 76543210 XXXXBA98
per the datasheet for fast write:
1 1 0 0 A2 A1 A0 0 <ACK> 0 0 PD1 PD0 D11 D10 D9 D8 <ACK> D7 D6 D5 D4 D3 D2 D1 D0 <ACK>
*/
uint8_t buf[2] = { (value >> 8) & 0x0F, (value & 0xFF) };
int ret = mytwi_writeTo(0x60, buf, 2, true);
Serial.println(value);
return ret;
}
void ICACHE_RAM_ATTR playsample_isr(void)
{
if (play_waiting) {
return;
}
DAC(data_buf[current_play_data_buf][play_data_buf_pos]);
play_data_buf_pos++;
if (play_data_buf_pos >= sizeof(data_buf[0]) / sizeof(data_buf[0][0])) {
play_data_buf_pos = 0;
current_play_data_buf++;
if (current_play_data_buf == NB_DATA_BUFS) {
current_play_data_buf = 0;
}
if (current_play_data_buf == current_recv_data_buf) {
play_waiting = true;
play_waiting_at = micros();
}
}
}
void ota_onstart(void)
{
// Disable timer when an OTA happens
timer1_detachInterrupt();
timer1_disable();
}
void ota_onprogress(unsigned int sz, unsigned int total)
{
Serial.print("OTA: "); Serial.print(sz); Serial.print("/"); Serial.print(total);
Serial.print("="); Serial.print(100 * sz / total); Serial.println("%");
}
void ota_onerror(ota_error_t err)
{
Serial.print("OTA ERROR:"); Serial.println((int)err);
}
void left_btn_intr()
{
left_btn_pressed = 1;
}
void right_btn_intr()
{
right_btn_pressed = 1;
}
void setup(void)
{
Serial.begin(115200);
Serial.println("I was built on " __DATE__ " at " __TIME__ "");
i2c.begin(mySDA, mySCL);
i2c.setClock(400000);
WiFi.mode(WIFI_STA);
WiFi.begin("valik 2", "299745buhlo");
WiFi.setSleepMode(WIFI_MODEM_SLEEP);
Serial.print("Connecting to wifi");
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.print("Cnnectd to ");
Serial.println("valik 2");
Serial.print("IP ");
Serial.println(WiFi.localIP());
ArduinoOTA.onStart(ota_onstart);
ArduinoOTA.onError(ota_onerror);
ArduinoOTA.onProgress(ota_onprogress);
ArduinoOTA.setHostname("bb-recv");
ArduinoOTA.begin();
timer1_isr_init();
timer1_attachInterrupt(playsample_isr);
timer1_enable(TIM_DIV16, TIM_EDGE, TIM_LOOP);
timer1_write(clockCyclesPerMicrosecond() / 16 * 50); //50us = 20 kHz sampling freq
udp.begin(udp_recv_port);
pinMode(AMPLI_MUTE_PIN, OUTPUT);
pinMode(AMPLI_SHUTDOWN_PIN, OUTPUT);
digitalWrite(AMPLI_SHUTDOWN_PIN, 0);
digitalWrite(AMPLI_MUTE_PIN, 0);
pinMode(LEFT_BTN, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(LEFT_BTN), left_btn_intr, FALLING);
pinMode(RIGHT_BTN, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(RIGHT_BTN), right_btn_intr, FALLING);
pinMode(LED1, OUTPUT);
digitalWrite(LED1, 0);
}
int do_undelta7(const uint8_t *val, int sz, uint16_t *out)
{
// Implement delta 7 decompression.
// First bit = 0 <=> uncompressed 15 bits following
// First bit = 1 <=> 7 bits follow representing delta
// must switch to big endian...
uint16_t last = 0;
uint8_t *ptr = (uint8_t *)&out[0];
const uint8_t *start = ptr;
for (int i = 0; i < sz; i++) {
uint16_t *ptr16 = (uint16_t *)ptr;
const int8_t firstbyte = val[i];
if (firstbyte & 0x80) {
// Delta7 compressed
// byte is CSMMMMMM
int8_t delta = firstbyte & 0x3F;
if (firstbyte & 0x40) {
delta = -delta;
}
const uint16_t value = last + delta;
*ptr16 = value;
ptr += 2;
last = value;
}
else {
// uncompressed -- switch bytes back to LE
*ptr++ = val[i + 1];
*ptr++ = val[i];
last = val[i + 1] | val[i] << 8;
i++;
}
}
return ptr - start;
}
void loop(void)
{
ArduinoOTA.handle();
int sz = udp.parsePacket();
//Serial.println(current_play_data_buf);
if (sz) {
uint8_t buf[sz];
udp.read(&buf[0], sz);
current_recv_data_buf++;
if (current_recv_data_buf == NB_DATA_BUFS) {
current_recv_data_buf = 0;
if (current_recv_data_buf == current_play_data_buf && !play_waiting) {
Serial.println("buffer overflow when receiving");
}
}
do_undelta7(buf, sz, &data_buf[current_recv_data_buf][0]);
if (play_waiting) {
Serial.print("Restarting play, was waiting (us)"); Serial.println(micros() - play_waiting_at);
// Re-enable *then* unmute in that order to avoid pops
digitalWrite(AMPLI_SHUTDOWN_PIN, 1);
digitalWrite(AMPLI_MUTE_PIN, 1);
play_waiting = false;
amplifier_stopped = false;
digitalWrite(LED1, 1);
}
Serial.println("");
}
// If not playing anything, but amplifier is still up
if (!amplifier_stopped && play_waiting) {
if ((micros() - play_waiting_at) > 2000 * 1000) {
// If nothing has been played for two seconds, shut down the amplifier
Serial.println("Shutting down amplifier!");
digitalWrite(AMPLI_SHUTDOWN_PIN, 0);
digitalWrite(AMPLI_MUTE_PIN, 0);
amplifier_stopped = true;
digitalWrite(LED1, 0);
}
}
if (left_btn_pressed) {
left_btn_pressed = 0;
digitalWrite(AMPLI_MUTE_PIN, 0);
digitalWrite(AMPLI_SHUTDOWN_PIN, 0);
}
if (right_btn_pressed) {
digitalWrite(AMPLI_SHUTDOWN_PIN, 1);
digitalWrite(AMPLI_MUTE_PIN, 1);
udp.beginPacket(udp.remoteIP(), 45990);
udp.write("sendnow");
udp.endPacket();
right_btn_pressed = 0;
}
// If the amplifier is stopped, add a delay for power saving
if (amplifier_stopped) {
delay(10);
}
}
This is my attempt to translate code to c++ for windows. But i encountered problem where programm just freeze without any errors and without closing.
#include "stdafx.h"
#include <winsock2.h>
#include <stdio.h>
#include <cstdint>
#include <ctime>
#pragma comment (lib, "ws2_32.lib")
#define NB_DATA_BUFS 5
uint16_t data_buf[NB_DATA_BUFS][700]; // data buffer, N buffered
unsigned int current_play_data_buf; // current data buf being played
unsigned int play_data_buf_pos; // position in the ADC data buffer
unsigned int current_recv_data_buf; // current data buf being received
bool play_waiting = true;
bool amplifier_stopped = false;
long play_waiting_at;
bool left_btn_pressed;
bool right_btn_pressed;
void InitWinsock()
{
WSADATA wsaData;
WSAStartup(MAKEWORD(2, 2), &wsaData);
}
int do_undelta7(const uint8_t *val, int sz, uint16_t *out)
{
// Implement delta 7 decompression.
// First bit = 0 <=> uncompressed 15 bits following
// First bit = 1 <=> 7 bits follow representing delta
// must switch to big endian...
uint16_t last = 0;
uint8_t *ptr = (uint8_t *)&out[0];
const uint8_t *start = ptr;
for (int i = 0; i < sz; i++) {
uint16_t *ptr16 = (uint16_t *)ptr;
const int8_t firstbyte = val[i];
if (firstbyte & 0x80) {
// Delta7 compressed
// byte is CSMMMMMM
int8_t delta = firstbyte & 0x3F;
if (firstbyte & 0x40) {
delta = -delta;
}
const uint16_t value = last + delta;
*ptr16 = value;
ptr += 2;
last = value;
}
else {
// uncompressed -- switch bytes back to LE
*ptr++ = val[i + 1];
*ptr++ = val[i];
last = val[i + 1] | val[i] << 8;
i++;
}
}
return ptr - start;
}
void DAC(uint16_t value)
{
/* value is 76543210 XXXXBA98
per the datasheet for fast write:
1 1 0 0 A2 A1 A0 0 <ACK> 0 0 PD1 PD0 D11 D10 D9 D8 <ACK> D7 D6 D5 D4 D3 D2 D1 D0 <ACK>
*/
uint8_t buf[2] = { (value >> 8) & 0x0F, (value & 0xFF) };
printf("%u\n", value & 0xFFF);
}
int _tmain(int argc, _TCHAR* argv[])
{
SOCKET socketC;
InitWinsock();
struct sockaddr_in serverInfo;
int len = 2000;
serverInfo.sin_family = AF_INET;
serverInfo.sin_port = htons(45990);
serverInfo.sin_addr.s_addr = inet_addr("192.168.1.105");
socketC = socket(AF_INET, SOCK_DGRAM, 0);
char buffers[16];
ZeroMemory(buffers, sizeof(buffers));
sendto(socketC, buffers, sizeof(IReleaseMarshalBuffers), 0, (sockaddr*)&serverInfo, len);
while (1)
{
sockaddr_in from;
const int paketSize = sizeof(from);
int r = paketSize;
char buffer[paketSize];
sprintf(buffer, "%.7s", "sendnow");
if (strcmp(buffer, "exit") == 0)
break;
recvfrom(socketC, buffer, sizeof(buffer), 0, (sockaddr*)&serverInfo, &len);
uint8_t buf[sizeof(buffer)];
uint8_t * bufeerPntr = (uint8_t*)buffer;
uint8_t * bufPntr = (uint8_t*)buffer;
for(int i=0;i<sizeof(buffer);i++)
{
buf[i] = buffer[i];
}
//udp.read(&buf[0], sizeof(buffer));
current_recv_data_buf++;
if (current_recv_data_buf == NB_DATA_BUFS) {
current_recv_data_buf = 0;
if (current_recv_data_buf == current_play_data_buf && !play_waiting) {
printf("buffer overflow when receiving\n");
}
}
do_undelta7(buf, sizeof(buffer), &data_buf[current_recv_data_buf][0]);
}
closesocket(socketC);
return 0;
}
This is my attempt to translate decoding part to c# (c# is much easier for me to understand) but i forced to use pointers and strange * and & things which i have difficulty to understand:
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
public class UDPListener
{
private const int listenPort = 45990;
public static int Main()
{
bool done = false;
UdpClient listener = new UdpClient(listenPort);
IPEndPoint groupEP = new IPEndPoint(IPAddress.Parse("192.168.1.3"), listenPort);
string received_data;
int BUFSIZE = 700;
byte[] receive_byte_array;
uint current_recv_data_buf = 1;
while (!done)
{
Console.WriteLine("Waiting for broadcast");
receive_byte_array = listener.Receive(ref groupEP);
Console.WriteLine("Received a broadcast from {0}", groupEP.ToString());
received_data = Encoding.ASCII.GetString(receive_byte_array, 0, receive_byte_array.Length);
unsafe
{
UInt16*[,] data_buf = new UInt16*[5, 700];
int sz = receive_byte_array.Length;
if (sz > 0)
{
byte[] buf = new byte[receive_byte_array.Length];
UInt16* f = stackalloc UInt16[2000];
//udp.read(&buf[0], sz);
buf = receive_byte_array;
current_recv_data_buf++;
UInt16 last = 0;
UInt16* #out1 = stackalloc UInt16[800];
for (int i = 0; i < 800; i++)
{
#out1[i] = (char)i;
}
//UIntPtr* ptr = (UIntPtr*)&#out[0];
UIntPtr* ptr = (UIntPtr*)&#out1[0];
UIntPtr* start = ptr;
for (int i = 0; i < sz; i++)
{
UIntPtr* ptr16 = ptr;
byte firstbyte = buf[i];
if ((firstbyte & 0x80) != 0)
{
// Delta7 compressed
// byte is CSMMMMMM
byte delta = (byte)(firstbyte & 0x3F);
if ((firstbyte & 0x40) != 0)
{
delta = (byte)(0 - delta);
}
UInt16 value = (UInt16)(last + delta);
*ptr16 = (UIntPtr)value;
ptr += 2;
last = value;
}
else
{
*ptr++ = (UIntPtr)buf[i + 1];
*ptr++ = (UIntPtr)buf[i];
last = (UInt16)(buf[i + 1] | buf[i] << 8);
i++;
}
}
for (int i = 0; i < 91; i++)
{
System.Console.WriteLine(#out1[i]);
}
string b = "";
}
}
}
listener.Close();
return 0;
}
} // end of class UDPListener
udp.read(&buf[0], sz); copies the received UDP packet into buffer buf. The function do_undelta7 then makes a decompression of the data in the input buffer to output buffer data_buf[current_recv_data_buf]. data_buf is array of buffers. The interrupt playsample_isr plays the content of the buffers in data_buf.
i missed an unsigned byte in do_undelta7
so now it's decoding well
c#
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Media;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using NAudio.Wave;
public class UDPListener
{
uint current_recv_data_buf;
static int NB_DATA_BUFS = 5;
static UInt16[] data_buf = new UInt16[700];
uint current_play_data_buf; // current data buf being played
uint play_data_buf_pos; // position in the ADC data buffer
private const int listenPort = 45990;
public static unsafe int Main()
{
bool done = false;
UdpClient listener = new UdpClient(listenPort);
IPEndPoint groupEP = new IPEndPoint(IPAddress.Parse("192.168.1.3"), listenPort);
int BUFSIZE = 700;
byte[] receive_byte_array;
uint current_recv_data_buf = 1;
List<byte> tenBuffsToPlay = new List<byte>();
int iterBuffsToPLay = 0;
byte[] byteArrToPlay = new byte[data_buf.Length * 2];
byte[] byte10ArrToPlay;
int pktcount = 0;
var sampleRate = 20000;
var frequency = 500;
var amplitude = 0.2;
var seconds = 5;
while (!done)
{
receive_byte_array = listener.Receive(ref groupEP);
if (receive_byte_array.Length > 0)
{
Console.WriteLine("received !"+pktcount++);
int sz = receive_byte_array.Length;
unsafe
{
byte[] buf = new byte[sz];
buf = receive_byte_array;
fixed (UInt16* data_bufPtr = &data_buf[0])
fixed (byte* ptrbuf = buf)
do_undelta7(ptrbuf, sz, data_bufPtr);
//string firstPart = "";
//string secondPart = "";
for (int i =0;i<data_buf.Length;i++)
{
//Console.WriteLine("Hex: {0:X}", data_buf[i]);
byteArrToPlay[i*2] = (byte)((data_buf[i] >> 8)&0x0f);
byteArrToPlay[(i*2)+1] = (byte)(data_buf[i] & 0xff);
//firstPart = Convert.ToString(byteArrToPlay[i], 2).PadLeft(4, '0');
//Console.Write(firstPart);
//secondPart = Convert.ToString(byteArrToPlay[i+1], 2).PadLeft(4, '0');
//Console.Write(secondPart+"\n");
}
//byteArrToPlay = data_buf.SelectMany(BitConverter.GetBytes).ToArray();
//foreach (var Arr in byteArrToPlay)
// {
// Console.WriteLine("Hex: {0:X}", Arr);
// }
tenBuffsToPlay.AddRange(byteArrToPlay);
iterBuffsToPLay++;
if (iterBuffsToPLay == 3)
{
byte10ArrToPlay = tenBuffsToPlay.ToArray();
/*var raw = new byte[sampleRate * seconds * 2];
var multiple = 2.0 * frequency / sampleRate;
for (int n = 0; n < sampleRate * seconds; n++)
{
var sampleSaw = ((n * multiple) % 2) - 1;
var sampleValue = sampleSaw > 0 ? amplitude : -amplitude;
var sample = (short)(sampleValue * Int16.MaxValue);
var bytes = BitConverter.GetBytes(sample);
raw[n * 2] = bytes[0];
raw[n * 2 + 1] = bytes[1];
}*/
var ms = new MemoryStream(byte10ArrToPlay);
var rs = new RawSourceWaveStream(ms, new WaveFormat(sampleRate, 16, 1));
var wo = new WaveOutEvent();
wo.Init(rs);
wo.Play();
/*while (wo.PlaybackState == PlaybackState.Playing)
{
Thread.Sleep(1);
}*/
//wo.Dispose();
/*using (MemoryStream ms = new MemoryStream())
{
WriteWavHeader(ms, false, 1, 16, 20000, (byte10ArrToPlay.Length / 2 - 45));
// Construct the sound player
ms.Write(byte10ArrToPlay, 0, byte10ArrToPlay.Length);
ms.Position = 0;
SoundPlayer player = new SoundPlayer(ms);
player.Play();
}*/
tenBuffsToPlay.Clear();
iterBuffsToPLay = 0;
}
}
}
}
listener.Close();
return 0;
}
static unsafe long do_undelta7(byte* val, int sz, UInt16* outArray)
{
// Implement delta 7 decompression.
// First bit = 0 <=> uncompressed 15 bits following
// First bit = 1 <=> 7 bits follow representing delta
// must switch to big endian...
UInt16 last = 0;
byte* ptr = (byte*)&outArray[0];
byte* start = ptr;
for (int i = 0; i < sz; i++)
{
UInt16* ptr16 = (UInt16*)ptr;
byte firstbyte = val[i];
var bit = (firstbyte & (1 << 8 - 1)) != 0;
if (bit == true)
{
// Delta7 compressed
// byte is CSMMMMMM
sbyte delta = (sbyte)(firstbyte & 0x3f);
bit = (firstbyte & (1 << 7 - 1)) != 0;
if (bit == true)
{
delta = (sbyte)(0x0 - delta);
}
UInt16 value = (UInt16)(last + delta);
*ptr16 = value;
ptr += 2;
last = value;
}
else
{
// uncompressed -- switch bytes back to LE
*ptr++ = val[i + 1];
*ptr++ = val[i];
last = (UInt16)(val[i + 1] | val[i] << 8);
i++;
}
}
return ptr - start;
}
private static void WriteWavHeader(MemoryStream stream, bool isFloatingPoint, ushort channelCount, ushort bitDepth, int sampleRate, int totalSampleCount)
{
stream.Position = 0;
stream.Write(Encoding.ASCII.GetBytes("RIFF"), 0, 4);
stream.Write(BitConverter.GetBytes((2* totalSampleCount) + 36), 0, 4);
stream.Write(Encoding.ASCII.GetBytes("WAVE"), 0, 4);
stream.Write(Encoding.ASCII.GetBytes("fmt "), 0, 4);
stream.Write(BitConverter.GetBytes(16), 0, 4);
stream.Write(BitConverter.GetBytes((ushort)(isFloatingPoint ? 3 : 1)), 0, 2);
stream.Write(BitConverter.GetBytes(channelCount), 0, 2);
stream.Write(BitConverter.GetBytes(sampleRate), 0, 4);
stream.Write(BitConverter.GetBytes(sampleRate * 2), 0, 4);
stream.Write(BitConverter.GetBytes((ushort)2), 0, 2);
stream.Write(BitConverter.GetBytes(16), 0, 2);
stream.Write(Encoding.ASCII.GetBytes("data"), 0, 4);
stream.Write(BitConverter.GetBytes(2 * totalSampleCount), 0, 4);
}
} // end of class UDPListener
How do you convert between hexadecimal numbers and decimal numbers in C#?
To convert from decimal to hex do...
string hexValue = decValue.ToString("X");
To convert from hex to decimal do either...
int decValue = int.Parse(hexValue, System.Globalization.NumberStyles.HexNumber);
or
int decValue = Convert.ToInt32(hexValue, 16);
Hex -> decimal:
Convert.ToInt64(hexString, 16);
Decimal -> Hex
string.Format("{0:x}", intValue);
It looks like you can say
Convert.ToInt64(value, 16)
to get the decimal from hexdecimal.
The other way around is:
otherVar.ToString("X");
If you want maximum performance when doing conversion from hex to decimal number, you can use the approach with pre-populated table of hex-to-decimal values.
Here is the code that illustrates that idea. My performance tests showed that it can be 20%-40% faster than Convert.ToInt32(...):
class TableConvert
{
static sbyte[] unhex_table =
{ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,-1,-1,-1,-1,-1,-1
,-1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1
,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
,-1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1
,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
};
public static int Convert(string hexNumber)
{
int decValue = unhex_table[(byte)hexNumber[0]];
for (int i = 1; i < hexNumber.Length; i++)
{
decValue *= 16;
decValue += unhex_table[(byte)hexNumber[i]];
}
return decValue;
}
}
From Geekpedia:
// Store integer 182
int decValue = 182;
// Convert integer 182 as a hex in a string variable
string hexValue = decValue.ToString("X");
// Convert the hex string back to the number
int decAgain = int.Parse(hexValue, System.Globalization.NumberStyles.HexNumber);
String stringrep = myintvar.ToString("X");
int num = int.Parse("FF", System.Globalization.NumberStyles.HexNumber);
If it's a really big hex string beyond the capacity of the normal integer:
For .NET 3.5, we can use BouncyCastle's BigInteger class:
String hex = "68c7b05d0000000002f8";
// results in "494809724602834812404472"
String decimal = new Org.BouncyCastle.Math.BigInteger(hex, 16).ToString();
.NET 4.0 has the BigInteger class.
Hex to Decimal Conversion
Convert.ToInt32(number, 16);
Decimal to Hex Conversion
int.Parse(number, System.Globalization.NumberStyles.HexNumber)
For more details Check this article
Try using BigNumber in C# - Represents an arbitrarily large signed integer.
Program
using System.Numerics;
...
var bigNumber = BigInteger.Parse("837593454735734579347547357233757342857087879423437472347757234945743");
Console.WriteLine(bigNumber.ToString("X"));
Output
4F30DC39A5B10A824134D5B18EEA3707AC854EE565414ED2E498DCFDE1A15DA5FEB6074AE248458435BD417F06F674EB29A2CFECF
Possible Exceptions,
ArgumentNullException - value is null.
FormatException - value is not in the correct format.
Conclusion
You can convert string and store a value in BigNumber without constraints about the size of the number unless the string is empty and non-analphabets
static string chex(byte e) // Convert a byte to a string representing that byte in hexadecimal
{
string r = "";
string chars = "0123456789ABCDEF";
r += chars[e >> 4];
return r += chars[e &= 0x0F];
} // Easy enough...
static byte CRAZY_BYTE(string t, int i) // Take a byte, if zero return zero, else throw exception (i=0 means false, i>0 means true)
{
if (i == 0) return 0;
throw new Exception(t);
}
static byte hbyte(string e) // Take 2 characters: these are hex chars, convert it to a byte
{ // WARNING: This code will make small children cry. Rated R.
e = e.ToUpper(); //
string msg = "INVALID CHARS"; // The message that will be thrown if the hex str is invalid
byte[] t = new byte[] // Gets the 2 characters and puts them in seperate entries in a byte array.
{ // This will throw an exception if (e.Length != 2).
(byte)e[CRAZY_BYTE("INVALID LENGTH", e.Length ^ 0x02)],
(byte)e[0x01]
};
for (byte i = 0x00; i < 0x02; i++) // Convert those [ascii] characters to [hexadecimal] characters. Error out if either character is invalid.
{
t[i] -= (byte)((t[i] >= 0x30) ? 0x30 : CRAZY_BYTE(msg, 0x01)); // Check for 0-9
t[i] -= (byte)((!(t[i] < 0x0A)) ? (t[i] >= 0x11 ? 0x07 : CRAZY_BYTE(msg, 0x01)) : 0x00); // Check for A-F
}
return t[0x01] |= t[0x00] <<= 0x04; // The moment of truth.
}
This is not really easiest way but this source code enable you to right any types of octal number i.e 23.214, 23 and 0.512 and so on. Hope this will help you..
public string octal_to_decimal(string m_value)
{
double i, j, x = 0;
Int64 main_value;
int k = 0;
bool pw = true, ch;
int position_pt = m_value.IndexOf(".");
if (position_pt == -1)
{
main_value = Convert.ToInt64(m_value);
ch = false;
}
else
{
main_value = Convert.ToInt64(m_value.Remove(position_pt, m_value.Length - position_pt));
ch = true;
}
while (k <= 1)
{
do
{
i = main_value % 10; // Return Remainder
i = i * Convert.ToDouble(Math.Pow(8, x)); // calculate power
if (pw)
x++;
else
x--;
o_to_d = o_to_d + i; // Saving Required calculated value in main variable
main_value = main_value / 10; // Dividing the main value
}
while (main_value >= 1);
if (ch)
{
k++;
main_value = Convert.ToInt64(Reversestring(m_value.Remove(0, position_pt + 1)));
}
else
k = 2;
pw = false;
x = -1;
}
return (Convert.ToString(o_to_d));
}
This one worked for me:
public static decimal HexToDec(string hex)
{
if (hex.Length % 2 == 1)
hex = "0" + hex;
byte[] raw = new byte[hex.Length / 2];
decimal d = 0;
for (int i = 0; i < raw.Length; i++)
{
raw[i] = Convert.ToByte(hex.Substring(i * 2, 2), 16);
d += Math.Pow(256, (raw.Length - 1 - i)) * raw[i];
}
return d.ToString();
return d;
}
Decimal - Hexa
var decValue = int.Parse(Console.ReadLine());
string hex = string.Format("{0:x}", decValue);
Console.WriteLine(hex);
Hexa - Decimal (use namespace: using System.Globalization;)
var hexval = Console.ReadLine();
int decValue = int.Parse(hexval, NumberStyles.HexNumber);
Console.WriteLine(decValue);
FOUR C# native ways to convert Hex to Dec and back:
using System;
namespace Hexadecimal_and_Decimal
{
internal class Program
{
private static void Main(string[] args)
{
string hex = "4DEAD";
int dec;
// hex to dec:
dec = int.Parse(hex, System.Globalization.NumberStyles.HexNumber);
// or:
dec = Convert.ToInt32(hex, 16);
// dec to hex:
hex = dec.ToString("X"); // lowcase: x, uppercase: X
// or:
hex = string.Format("{0:X}", dec); // lowcase: x, uppercase: X
Console.WriteLine("Hexadecimal number: " + hex);
Console.WriteLine("Decimal number: " + dec);
}
}
}
My version is I think a little more understandable because my C# knowledge is not so high.
I'm using this algorithm: http://easyguyevo.hubpages.com/hub/Convert-Hex-to-Decimal (The Example 2)
using System;
using System.Collections.Generic;
static class Tool
{
public static string DecToHex(int x)
{
string result = "";
while (x != 0)
{
if ((x % 16) < 10)
result = x % 16 + result;
else
{
string temp = "";
switch (x % 16)
{
case 10: temp = "A"; break;
case 11: temp = "B"; break;
case 12: temp = "C"; break;
case 13: temp = "D"; break;
case 14: temp = "E"; break;
case 15: temp = "F"; break;
}
result = temp + result;
}
x /= 16;
}
return result;
}
public static int HexToDec(string x)
{
int result = 0;
int count = x.Length - 1;
for (int i = 0; i < x.Length; i++)
{
int temp = 0;
switch (x[i])
{
case 'A': temp = 10; break;
case 'B': temp = 11; break;
case 'C': temp = 12; break;
case 'D': temp = 13; break;
case 'E': temp = 14; break;
case 'F': temp = 15; break;
default: temp = -48 + (int)x[i]; break; // -48 because of ASCII
}
result += temp * (int)(Math.Pow(16, count));
count--;
}
return result;
}
}
class Program
{
static void Main(string[] args)
{
Console.Write("Enter Decimal value: ");
int decNum = int.Parse(Console.ReadLine());
Console.WriteLine("Dec {0} is hex {1}", decNum, Tool.DecToHex(decNum));
Console.Write("\nEnter Hexadecimal value: ");
string hexNum = Console.ReadLine().ToUpper();
Console.WriteLine("Hex {0} is dec {1}", hexNum, Tool.HexToDec(hexNum));
Console.ReadKey();
}
}
Convert binary to Hex
Convert.ToString(Convert.ToUInt32(binary1, 2), 16).ToUpper()
You can use this code and possible set Hex length and part's:
const int decimal_places = 4;
const int int_places = 4;
static readonly string decimal_places_format = $"X{decimal_places}";
static readonly string int_places_format = $"X{int_places}";
public static string DecimaltoHex(decimal number)
{
var n = (int)Math.Truncate(number);
var f = (int)Math.Truncate((number - n) * ((decimal)Math.Pow(10, decimal_places)));
return $"{string.Format($"{{0:{int_places_format}}}", n)}{string.Format($"{{0:{decimal_places_format}}}", f)}";
}
public static decimal HextoDecimal(string number)
{
var n = number.Substring(0, number.Length - decimal_places);
var f = number.Substring(number.Length - decimal_places);
return decimal.Parse($"{int.Parse(n, System.Globalization.NumberStyles.HexNumber)}.{int.Parse(f, System.Globalization.NumberStyles.HexNumber)}");
}
An extension method for converting a byte array into a hex representation. This pads each byte with leading zeros.
/// <summary>
/// Turns the byte array into its Hex representation.
/// </summary>
public static string ToHex(this byte[] y)
{
StringBuilder sb = new StringBuilder();
foreach (byte b in y)
{
sb.Append(b.ToString("X").PadLeft(2, "0"[0]));
}
return sb.ToString();
}
Here is my function:
using System;
using System.Collections.Generic;
class HexadecimalToDecimal
{
static Dictionary<char, int> hexdecval = new Dictionary<char, int>{
{'0', 0},
{'1', 1},
{'2', 2},
{'3', 3},
{'4', 4},
{'5', 5},
{'6', 6},
{'7', 7},
{'8', 8},
{'9', 9},
{'a', 10},
{'b', 11},
{'c', 12},
{'d', 13},
{'e', 14},
{'f', 15},
};
static decimal HexToDec(string hex)
{
decimal result = 0;
hex = hex.ToLower();
for (int i = 0; i < hex.Length; i++)
{
char valAt = hex[hex.Length - 1 - i];
result += hexdecval[valAt] * (int)Math.Pow(16, i);
}
return result;
}
static void Main()
{
Console.WriteLine("Enter Hexadecimal value");
string hex = Console.ReadLine().Trim();
//string hex = "29A";
Console.WriteLine("Hex {0} is dec {1}", hex, HexToDec(hex));
Console.ReadKey();
}
}
My solution is a bit like back to basics, but it works without using any built-in functions to convert between number systems.
public static string DecToHex(long a)
{
int n = 1;
long b = a;
while (b > 15)
{
b /= 16;
n++;
}
string[] t = new string[n];
int i = 0, j = n - 1;
do
{
if (a % 16 == 10) t[i] = "A";
else if (a % 16 == 11) t[i] = "B";
else if (a % 16 == 12) t[i] = "C";
else if (a % 16 == 13) t[i] = "D";
else if (a % 16 == 14) t[i] = "E";
else if (a % 16 == 15) t[i] = "F";
else t[i] = (a % 16).ToString();
a /= 16;
i++;
}
while ((a * 16) > 15);
string[] r = new string[n];
for (i = 0; i < n; i++)
{
r[i] = t[j];
j--;
}
string res = string.Concat(r);
return res;
}