This is an automated email from the ASF dual-hosted git repository.
cdutz pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/plc4x.git
The following commit(s) were added to refs/heads/develop by this push:
new 382962b - Fixed a bug not propagating the positive or negative values
when reading fractions of a short, int or long.
382962b is described below
commit 382962b22b4dbb0b02e117c379bff9635bd7cc7d
Author: Christofer Dutz <[email protected]>
AuthorDate: Wed Jul 8 15:01:32 2020 +0200
- Fixed a bug not propagating the positive or negative values when reading
fractions of a short, int or long.
---
sandbox/plc4c/spi/src/read_buffer.c | 104 +++++++++++++++++++++++++++---
sandbox/plc4c/spi/test/read_buffer_test.c | 42 +++++++++++-
2 files changed, 137 insertions(+), 9 deletions(-)
diff --git a/sandbox/plc4c/spi/src/read_buffer.c
b/sandbox/plc4c/spi/src/read_buffer.c
index 3be5fd8..8c87f9a 100644
--- a/sandbox/plc4c/spi/src/read_buffer.c
+++ b/sandbox/plc4c/spi/src/read_buffer.c
@@ -206,17 +206,29 @@ plc4c_return_code plc4c_spi_read_unsigned_bits_internal(
}
bool plc4c_spi_read_buffer_is_negative_internal(uint8_t num_bits, int8_t
value) {
- int8_t tmp_value = value >> (num_bits - 1);
+ int8_t tmp_value = value >> num_bits;
return (tmp_value & 1) != 0;
}
-plc4c_return_code plc4c_spi_fill_sign_internal(uint8_t num_bits, int8_t*
value) {
- if(plc4c_spi_read_buffer_is_negative_internal(num_bits, *value)) {
+bool plc4c_spi_fill_sign_internal(uint8_t num_bits, int8_t* value) {
+ // Find out how many bytes the value has.
+ uint8_t num_bytes_total = (num_bits / 8) + ((num_bits % 8 != 0) ? 1 : 0);
+
+ // If this is big endian, go to the highest level byte.
+ if (!plc4c_is_bigendian()) {
+ value = value + (num_bytes_total - 1);
+ }
+
+ if(plc4c_spi_read_buffer_is_negative_internal((num_bits - 1) % 8, *value)) {
// Set all bits above {num_bits} to 1
int8_t tmp_value = *value;
- tmp_value = tmp_value | (255 & bit_matrix[num_bits][0]);
+ if(num_bits % 8 != 0) {
+ tmp_value = tmp_value | bit_matrix[7 - (num_bits % 8)][0];
+ }
*value = tmp_value;
+ return true;
}
+ return false;
}
plc4c_return_code plc4c_spi_read_buffer_create(uint8_t* data, uint16_t length,
@@ -405,24 +417,100 @@ uint8_t num_bits) { return OK;
plc4c_return_code plc4c_spi_read_signed_byte(plc4c_spi_read_buffer* buf,
uint8_t num_bits, int8_t* value) {
plc4c_return_code res = plc4c_spi_read_unsigned_byte(buf, num_bits,
(uint8_t*) value);
- plc4c_spi_fill_sign_internal(num_bits, value);
+ if(res == OK) {
+ plc4c_spi_fill_sign_internal(num_bits, value);
+ }
return res;
}
plc4c_return_code plc4c_spi_read_signed_short(plc4c_spi_read_buffer* buf,
uint8_t num_bits,
int16_t* value) {
- return plc4c_spi_read_unsigned_byte(buf, num_bits, (uint16_t*) value);
+ plc4c_return_code res = plc4c_spi_read_unsigned_short(buf, num_bits,
(uint16_t*) value);
+ if(res == OK) {
+ if(plc4c_spi_fill_sign_internal(num_bits, (int8_t*) value)) {
+ // Potentially fill all higher level bytes with 255
+ if(num_bits <= 8) {
+ *value = *value | 65280;
+ }
+ } else {
+ // Potentially fill all higher level bytes with 0
+ if(num_bits <= 8) {
+ *value = *value & 255;
+ }
+ }
+ }
+ return res;
}
plc4c_return_code plc4c_spi_read_signed_int(plc4c_spi_read_buffer* buf,
uint8_t num_bits, int32_t* value) {
- return plc4c_spi_read_unsigned_byte(buf, num_bits, (uint32_t*) value);
+ plc4c_return_code res = plc4c_spi_read_unsigned_int(buf, num_bits,
(uint32_t*) value);
+ if(res == OK) {
+ if(plc4c_spi_fill_sign_internal(num_bits, (int8_t*) value)) {
+ // Potentially fill all higher level bytes with 255
+ if(num_bits <= 8) {
+ *value = *value | 4294967040;
+ } else if(num_bits <= 16) {
+ *value = *value | 4294901760;
+ } else if(num_bits <= 24) {
+ *value = *value | 4278190080;
+ }
+ } else {
+ // Potentially fill all higher level bytes with 0
+ if(num_bits <= 8) {
+ *value = *value & 255;
+ } else if(num_bits <= 16) {
+ *value = *value & 65535;
+ } else if(num_bits <= 24) {
+ *value = *value & 16777215;
+ }
+ }
+ }
+ return res;
}
plc4c_return_code plc4c_spi_read_signed_long(plc4c_spi_read_buffer* buf,
uint8_t num_bits, int64_t* value)
{
- return plc4c_spi_read_unsigned_byte(buf, num_bits, (uint64_t*) value);
+ plc4c_return_code res = plc4c_spi_read_unsigned_long(buf, num_bits,
(uint64_t*) value);
+ if(res == OK) {
+ if(plc4c_spi_fill_sign_internal(num_bits, (int8_t*) value)) {
+ // Potentially fill all higher level bytes with 255
+ if(num_bits <= 8) {
+ *value = *value | 18446744073709551360;
+ } else if(num_bits <= 16) {
+ *value = *value | 18446744073709486080;
+ } else if(num_bits <= 24) {
+ *value = *value | 18446744073692774400;
+ } else if(num_bits <= 32) {
+ *value = *value | 18446744069414584320;
+ } else if(num_bits <= 40) {
+ *value = *value | 18446742974197923840;
+ } else if(num_bits <= 48) {
+ *value = *value | 18446462598732840960;
+ } else if(num_bits <= 56) {
+ *value = *value | 18374686479671623680;
+ }
+ } else {
+ // Potentially fill all higher level bytes with 0
+ if(num_bits <= 8) {
+ *value = *value & 255;
+ } else if(num_bits <= 16) {
+ *value = *value & 65535;
+ } else if(num_bits <= 24) {
+ *value = *value & 16777215;
+ } else if(num_bits <= 32) {
+ *value = *value & 4294967295;
+ } else if(num_bits <= 40) {
+ *value = *value & 1099511627775;
+ } else if(num_bits <= 48) {
+ *value = *value & 281474976710655;
+ } else if(num_bits <= 56) {
+ *value = *value & 72057594037927935;
+ }
+ }
+ }
+ return res;
}
// TODO: Not sure which type to use in this case ...
diff --git a/sandbox/plc4c/spi/test/read_buffer_test.c
b/sandbox/plc4c/spi/test/read_buffer_test.c
index 4d5ed64..191377c 100644
--- a/sandbox/plc4c/spi/test/read_buffer_test.c
+++ b/sandbox/plc4c/spi/test/read_buffer_test.c
@@ -441,7 +441,6 @@ void test_plc4c_spi_read_unsigned_long(void) {
test_plc4c_spi_read_unsigned_long_args("Full long starting at bit 3",
read_buffer, 61, OK, 72623859790382856);
}
-
void test_plc4c_spi_read_signed_byte_args(char* message,
plc4c_spi_read_buffer*
read_buffer, uint8_t num_bits,
plc4c_return_code
expected_return_code, int8_t expected_value) {
@@ -495,6 +494,46 @@ void test_plc4c_spi_read_signed_byte(void) {
test_plc4c_spi_read_signed_byte_args("Exceed read-buffer size (Part 2)",
read_buffer2, 10, OUT_OF_RANGE, -1);
}
+void test_plc4c_spi_read_signed_short_args(char* message,
+ plc4c_spi_read_buffer* read_buffer,
uint8_t num_bits,
+ plc4c_return_code
expected_return_code, int16_t expected_value) {
+ printf("Running read_buffer read_signed_byte test: %s", message);
+
+ int16_t value = -1;
+ plc4c_return_code result =
+ plc4c_spi_read_signed_short(read_buffer, num_bits, &value);
+
+ TEST_ASSERT_EQUAL_INT(expected_return_code, result);
+ TEST_ASSERT_EQUAL_INT(expected_value, value);
+
+ printf(" -> OK\n");
+}
+
+void test_plc4c_spi_read_signed_short(void) {
+ // Prepare input data
+ uint8_t data[] = {255, 214, 3};
+ plc4c_spi_read_buffer* read_buffer;
+ plc4c_spi_read_buffer_create(data, 3, &read_buffer);
+ // Run test
+ // Read all the full bytes
+ test_plc4c_spi_read_signed_short_args("Simple full signed short 1",
read_buffer, 16, OK, -42);
+
+ // Read the only part of a short (having to fill up 1s)
+ read_buffer->curPosByte = 0;
+ read_buffer->curPosBit = 4;
+ test_plc4c_spi_read_signed_short_args("Simple 12 bit signed short",
read_buffer, 12, OK, -42);
+
+ // Read an even shorter part of a short (having to fill up even more 1s)
+ read_buffer->curPosByte = 1;
+ read_buffer->curPosBit = 1;
+ test_plc4c_spi_read_signed_short_args("Simple 7 bit signed short",
read_buffer, 7, OK, -42);
+
+ // Read an even shorter part of a short (This time however the value should
+ // be positive and hence the higher level byte should be filled with 0s)
+ read_buffer->curPosByte = 1;
+ read_buffer->curPosBit = 2;
+ test_plc4c_spi_read_signed_short_args("Simple 6 bit signed short",
read_buffer, 6, OK, 22);
+}
void test_plc4c_spi_read_buffer(void) {
test_plc4c_spi_read_buffer_create();
@@ -508,4 +547,5 @@ void test_plc4c_spi_read_buffer(void) {
test_plc4c_spi_read_unsigned_int();
test_plc4c_spi_read_unsigned_long();
test_plc4c_spi_read_signed_byte();
+ test_plc4c_spi_read_signed_short();
}
\ No newline at end of file