Convert two 16 Bit Registers to 32 Bit real value flutter - flutter

I am using a Modbus flutter lib, reading 2 registers I obtain:
[22136, 4660]
This means: 0x12345678 I need a function to convert it to a 32 bit real value: 305419896, in easymodbustcp library I found:
/**
* Convert two 16 Bit Registers to 32 Bit real value
* #param registers 16 Bit Registers
* #return 32 bit real value
*/
public static float ConvertRegistersToFloat(int[] registers) throws IllegalArgumentException
{
if (registers.length != 2)
throw new IllegalArgumentException("Input Array length invalid");
int highRegister = registers[1];
int lowRegister = registers[0];
byte[] highRegisterBytes = toByteArray(highRegister);
byte[] lowRegisterBytes = toByteArray(lowRegister);
byte[] floatBytes = {
highRegisterBytes[1],
highRegisterBytes[0],
lowRegisterBytes[1],
lowRegisterBytes[0]
};
return ByteBuffer.wrap(floatBytes).getFloat();
}
Any help to do it in flutter / dart?

This can be done with bit shifts and a bitwise or. You need to shift the 2 higher bytes by 16 bits, then or it to get the value you want.
void main() {
List<int> vals = [22136, 4660];
int result = vals[1] << 16 | vals[0];
print(result);//305419896
}
You could also achieve the same result in this case by replacing the bitwise or with addition.
void main() {
List<int> vals = [22136, 4660];
int result = (vals[1] << 16) + vals[0];
print(result);//305419896
}

Related

STM32 Read event from remoteControlEvent_t and parse data. Values are wrong with passing

I have small problem with adding and reading values.
Define variables
#define ADC_BIT_MASK 0x0FFF
static TaskHandle_t remoteControlTaskHandle = NULL;
typedef enum
{
...
rcEvent_FreshADC = 0x80000000,
...
}
Code for notify task. adc12bitVal_pedal value is for example 100 and adc12bitVal_lr value for example 1000. I am shifting adc12bitVal_lr to the left that I can pass params ...
static void remoteControl_FreshADC(uint16_t adc12bitVal_pedal, uint16_t adc12bitVal_lr)
{
if(remoteControlTaskHandle != NULL)
{
xTaskNotify(remoteControlTaskHandle,
(rcEvent_FreshADC | (adc12bitVal_pedal & ADC_BIT_MASK) | (adc12bitVal_lr & ADC_BIT_MASK)<<12),
eSetValueWithOverwrite);
}
}
and then remoteControlHandleEvent which handle an event. Here I have problem with adcVal_lr which should be 1000 but is for example 52123. I need to shift 12 to the left that I get correct value. Or this is wrong?
returnCode_t remoteControlHandleEvent(remoteControlEvent_t event)
{
if(event & rcEvent_motorControlACK)
{
uint8_t ackNum = (uint8_t) ( ((event >> MOTOR_CONTROL_ACK_BIT_POS) & MOTOR_CONTROL_ACK_BIT_MASK));
printf("CONF: %u\n", (unsigned int)ackNum);
}
if(event & rcEvent_FreshADC)
{
...
// Value is 100
uint16_t adcVal_pedal = (uint16_t)(event & ADC_BIT_MASK);
// DOESN'T WORK VALUE IS 52123 instead of 1000
uint16_t adcVal_lr = (uint16_t)((event & ADC_BIT_MASK)<<12);
...
}
}
I don't understand and know why wrong value for
uint16_t adcVal_lr = (uint16_t)((event & ADC_BIT_MASK)<<12);
Thnak you for all comments and help.
You are shifting left (up) twice. To extract a value that you shifted left you need to shift right (down). You also apply the mask before shifting, when it should be after.
uint16_t adcVal_lr = (uint16_t)((event >> 12) & ADC_BIT_MASK);

Xilinx Echo Server Data Variable

I want to have my Zedboard return a numeric value using the Xilinx lwIP example as a base but no matter what I do I can't figure out what stores the data received or transmitted.
I have found the void type payload but I don't know what to do with it.
Snapshot of one instance of payload and a list of lwIP files
Below is the closest function to my goal:
err_t recv_callback(void *arg, struct tcp_pcb *tpcb,
struct pbuf *p, err_t err){
/* do not read the packet if we are not in ESTABLISHED state */
if (!p) {
tcp_close(tpcb);
tcp_recv(tpcb, NULL);
return ERR_OK;
}
/* indicate that the packet has been received */
tcp_recved(tpcb, p->len);
/* echo back the payload */
/* in this case, we assume that the payload is < TCP_SND_BUF */
if (tcp_sndbuf(tpcb) > p->len) {
err = tcp_write(tpcb, p->payload, p->len, 1);
//I need to change p->paylod but IDK where it is given a value.
} else
xil_printf("no space in tcp_sndbuf\n\r");
/* free the received pbuf */
pbuf_free(p);
return ERR_OK;
}
Any guidance is appreciated.
Thanks,
Turtlemii
-I cheated and just made sure that the function has access to Global_tpcb from echo.c
-tcp_write() reads in an address and displays each char it seems.
void Print_Code()
{
/* Prepare for TRANSMISSION */
char header[] = "\rSwitch: 1 2 3 4 5 6 7 8\n\r"; //header text
char data_t[] = " \n\r\r"; //area for storing the
data
unsigned char mask = 10000000; //mask to decode switches
swc_value = XGpio_DiscreteRead(&SWCInst, 1); //Save switch values
/* Write switch values to the LEDs for visual. */
XGpio_DiscreteWrite(&LEDInst, LED_CHANNEL, swc_value);
for (int i =0; i<=7; i++) //load data_t with switch values (0/1)
{
data_t[8+2*i] = '0' + ((swc_value & mask)/mask); //convert one bit to 0/1
mask = mask >> 1;//move to next bit
}
int len_header = *(&header + 1) - header; //find the length of the
header string
int len_data = *(&data_t + 1) - data_t; //find the length of the data string
tcp_write(Global_tpcb, &header, len_header, 1); //print the header
tcp_write(Global_tpcb, &data_t, len_data, 1); //print the data
}

How to convert 2 bytes to Int16 in dart?

There is a method in bitconverter class in java which has a method called toInt16
But in dart i am unable to cast short as Int16
public static short toInt16( byte[] bytes, int index )
throws Exception {
if ( bytes.length != 8 )
throw new Exception( "The length of the byte array must be at least 8 bytes long." );
return (short) ( ( 0xff & bytes[index] ) << 8 | ( 0xff & bytes[index + 1] ) << 0 );
}
can someone help me with this conversion to dart language ?
Here is the updated dart version of answer that i followed using the ByteData class suggested by emerssso and this works for me
int toInt16(Uint8List byteArray, int index)
{
ByteBuffer buffer = byteArray.buffer;
ByteData data = new ByteData.view(buffer);
int short = data.getInt16(index, Endian.little);
return short;
}
I had to specifically set Endian.little because originally getInt16 method is set to BigEndian but my byte data was in former order
I think you are looking for one of the methods on the ByteData class available in dart:typed_data. Wrap your byte array in a ByteData via ByteData.view() and then you can arbitrarily access bytes as a specified type. You could then do i.e. byteData.getInt16(index);.
https://api.dart.dev/stable/2.7.1/dart-typed_data/ByteData-class.html

UEFI TGC2's sendCommand always returns error 21

I'm developing an UEFI app using the TPM2. getCapabilities works, but everything else is shoved onto this submitCommand() function. everything I try there returns EFI_ABORTED as status.
I tried several commands, like read_PCR and get_random_number, but it appears to occur for all commands (TPM2 spec part 3). I chose the random number command because it's a simple command without authorization or encryption that should always return when executed correctly.
struct TPM2_ {
EFI_HANDLE image;
EFI_BOOT_SERVICES *BS;
EFI_TCG2_PROTOCOL *prot;
UINT32 activePCRbanks;
};
struct TPM2_Rand_Read_Command {
TPMI_ST_COMMAND_TAG tag;
UINT32 commandSize;
TPM_CC commandCode;
UINT16 bytesRequested;
};
struct TPM2_Rand_Read_Response {
TPM_ST tag;
UINT32 responseSize;
TPM_RC responseCode;
TPM2B_DIGEST randomBytes;
};
UINTN tpm_get_random(TPM2 * tpm) {
struct TPM2_Rand_Read_Command cmd;
struct TPM2_Rand_Read_Response resp;
cmd.tag = __builtin_bswap16(TPM_ST_NO_SESSIONS); //x86 is little endian, TPM2 is big-endian, use bswap to convert!)
cmd.commandCode = __builtin_bswap32(TPM_CC_GetRandom);
cmd.commandSize = __builtin_bswap32(sizeof(struct TPM2_Rand_Read_Command));
cmd.bytesRequested = __builtin_bswap16(4);
EFI_STATUS stat = tpm->prot->SubmitCommand(tpm->prot,sizeof(struct TPM2_Rand_Read_Command), (UINT8*)&cmd,sizeof(struct TPM2_Rand_Read_Response),(UINT8*)&resp); //responds 0x15 || 21
Print(L"statreadrand: %x \t %d \r\n", stat, *((UINT32*)resp.randomBytes.buffer));
CHECK_STATUS(stat, L"SubmitReadCommand");
return 0;
}
TPM2* tpm_create(EFI_BOOT_SERVICES *BS, EFI_HANDLE image) {
TPM2* tpm = calloc(1, sizeof(TPM2));
EFI_GUID prot_guid = (EFI_GUID)EFI_TCG2_PROTOCOL_GUID;
tpm->BS = BS;
tpm->image = image;
EFI_STATUS stat = tpm->BS->LocateProtocol(&prot_guid, NULL, (void **)&tpm->prot);
CHECK_STATUS(stat, L"LocateTPMProtocol");
return tpm;
}
I expect the SubmitCommand function to return EFI_SUCCESS (0) and fill the response struct with 4 random bytes. But the function returns EFI_ABORTED (21)
Does anyone know how to solve this?
EDIT: tried different toolchains (GNU-EFI/ plain GCC / EDK2) all give the same behaviour.
The particular PC had this exact problem. probably the TPM was locked.
When using a different PC With a TPM2 the problem didn' t occur and instead, I just got a random number back.

convert array<uchar>^ to std::vector<char> data;

I'm working with managed and unmanaged code and I need to convert
convert array<uchar>^ image to std::vector<char> data.
I've started doing this:
array<uchar> ^image = gcnew array<uchar>(tam);
reader2->GetBytes(0, 0, image, 0, tam);
vector<uchar> data;
for (int idxImage = 0; idxImage < tam; idxImage++)
{
data.push_back(image[idxImage]);
}
It looks like it is working but it is very slow. Any idea about how can be done faster?
A first optimization you could do is to reserve the needed space in the vector, so it doesn't have to resize itself as you insert data into it.
This is as easy as:
data.reserve(tam);
This will improve performance, but not by that much. You can do better, you could use memcpy, which, as cppreference says:
std::memcpy is the fastest library routine for memory-to-memory copy.
So let's use that.
First, you need to resize (not reserve) the vector, so it knows the number of used bytes. Then, you can get a pointer to the raw data it holds with the data() function.
As for the array, it's a managed object, which means you need to pin it so the GC won't move it around. In C++/CLI this is done with pin_ptr.
Together, here's the final code:
data.resize(tam);
pin_ptr<uchar> pinned = &image[0];
std::memcpy(data.data(), pinned, tam);
I've tested it, and it's much faster. Here's a full test program:
#include "stdafx.h"
#include <vector>
typedef unsigned char uchar;
void test1(array<uchar>^ image)
{
std::vector<uchar> data;
int tam = image->Length;
auto sw = System::Diagnostics::Stopwatch::StartNew();
for (int idxImage = 0; idxImage < tam; idxImage++)
{
data.push_back(image[idxImage]);
}
sw->Stop();
System::Console::WriteLine("OP: {0} ms", sw->ElapsedMilliseconds);
}
void test2(array<uchar>^ image)
{
std::vector<uchar> data;
int tam = image->Length;
auto sw = System::Diagnostics::Stopwatch::StartNew();
data.reserve(tam);
for (int idxImage = 0; idxImage < tam; idxImage++)
{
data.push_back(image[idxImage]);
}
sw->Stop();
System::Console::WriteLine("reserve: {0} ms", sw->ElapsedMilliseconds);
}
void test3(array<uchar>^ image)
{
std::vector<uchar> data;
int tam = image->Length;
auto sw = System::Diagnostics::Stopwatch::StartNew();
data.resize(tam);
pin_ptr<uchar> pinned = &image[0];
std::memcpy(data.data(), pinned, tam);
sw->Stop();
System::Console::WriteLine("memcpy: {0} ms", sw->ElapsedMilliseconds);
}
int main(array<System::String ^> ^args)
{
size_t tam = 20 * 1024 * 1024;
array<uchar>^ image = gcnew array<uchar>(tam);
(gcnew System::Random)->NextBytes(image);
test1(image);
test2(image);
test3(image);
return 0;
}
My results are:
OP: 123 ms
reserve: 95 ms
memcpy: 8 ms