Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions doc/documentation.md
Original file line number Diff line number Diff line change
Expand Up @@ -526,6 +526,20 @@ Here the ```dot_position``` option is an index starting at the most right positi
| ------| -------------- | -------------- | -------------- |
| 12345 | 12345. | 1234.5 | 123.45 |

### Display Value Truncation
#### Overview
When displaying values on hardware panels with limited character capacity, XPanel automatically handles cases where the data exceeds the available display space.

#### Truncation Behavior
If a display value is wider than the available characters on the hardware display, XPanel will truncate the value and append a period (`.`) character at the end to indicate that the value has been shortened.

**Example:**
- **Full value**: `120.375` (8.33kHz radio frequency)
- **Saitek Radio Panel display** (5 characters): `12037.`
- The period at the end indicates that the complete value cannot be displayed

#### Configuration
The truncation behavior is automatically applied and does not require any configuration. The feature ensures that users are always aware when displayed values are incomplete due to hardware limitations.

### Multipurpose displays
The display value can be a conditional display which means the value to display depends on the position of a switch. A display that contains conditions called multi-purpose display (multi_display).
Expand Down
28 changes: 20 additions & 8 deletions src/core/GenericDisplay.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -161,17 +161,29 @@ bool GenericDisplay::get_decimal_components(int number, unsigned char* buffer, i
negative = true;
}

if (number > pow(10, nr_of_bytes))
return false;
for (int i = 0; i < nr_of_bytes; i++)
buffer[i] = ZERO_CHAR;

int remain = number;
for (int dec_pos = nr_of_bytes - 1; dec_pos >= 0; dec_pos--)
if (number != 0)
{
buffer[nr_of_bytes - 1 - dec_pos] = remain / (int)pow(10, dec_pos);
if (dec_pos == _dot_position)
buffer[nr_of_bytes - 1 - dec_pos] += PERIOD_CHAR; // turn on period dot
// how many decimal positions do we need?
const int base_10_of_number = (int)log10(number);

int remain = number;
int buffer_index = nr_of_bytes > (base_10_of_number + 1) ? nr_of_bytes - (base_10_of_number+1) : 0;

for (int dec_pos = base_10_of_number; dec_pos >= 0 && buffer_index < nr_of_bytes; dec_pos--)
{
buffer[buffer_index] = remain / (int)pow(10, dec_pos);
if (dec_pos == _dot_position)
buffer[buffer_index] += PERIOD_CHAR; // turn on period dot

remain = remain % (int)pow(10, dec_pos);
buffer_index++;
}

remain = remain % (int)pow(10, dec_pos);
if (remain != 0)
buffer[nr_of_bytes - 1] += PERIOD_CHAR; // a dot at the end of display indicates the truncated line
}

if (blank_leading_zeros)
Expand Down
3 changes: 2 additions & 1 deletion test/test-radio-panel-config.ini
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,12 @@ pid="d05"

[multi_display:id="RADIO_DISPLAY_ACTIVE_UP"]
line="on_select:SW_UP_COM1,dataref:sim/cockpit2/radios/actuators/com1_frequency_hz"
line="on_select:SW_UP_COM2,dataref:sim/cockpit/radios/com1_stdby_freq_hz"
line="on_select:SW_UP_COM2,dataref:sim/cockpit2/radios/actuators/com1_frequency_hz_833"
line="on_select:SW_UP_NAV1,dataref:sim/cockpit2/radios/actuators/nav1_frequency_hz"
line="on_select:SW_UP_NAV2,dataref:sim/cockpit2/radios/actuators/nav2_frequency_hz"
line="on_select:SW_UP_ADF,const:12345"
line="on_select:SW_UP_DME,lua:get_display_value()"
line="on_select:SW_UP_IDT,dataref:sim/cockpit2/radios/actuators/transponder_code"

[button:id="KNOB_UP_BIG_PLUS"]
on_push="on_select:SW_UP_COM1,dataref:sim/cockpit2/radios/actuators/com1_frequency_hz:100:0:99999"
Expand Down
47 changes: 47 additions & 0 deletions test/test_radio_panel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,15 @@ namespace test
std::string nav2_freq_dataref_str = "sim/cockpit2/radios/actuators/nav2_frequency_hz";
std::string com1_freq_dataref_str = "sim/cockpit2/radios/actuators/com1_frequency_hz";
std::string com2_freq_dataref_str = "sim/cockpit/radios/com1_stdby_freq_hz";
std::string com1_freq_833khz_dataref_str = "sim/cockpit2/radios/actuators/com1_frequency_hz_833";
std::string transponder_code_str = "sim/cockpit2/radios/actuators/transponder_code";

XPLMDataRef nav1_freq_dataref;
XPLMDataRef nav2_freq_dataref;
XPLMDataRef com1_freq_dataref;
XPLMDataRef com2_freq_dataref;
XPLMDataRef com1_freq_833khz_dataref;
XPLMDataRef transponder_code_dataref;

public:
TEST_METHOD_INITIALIZE(TestMultiPanelInit)
Expand All @@ -66,11 +70,15 @@ namespace test
nav2_freq_dataref = XPLMFindDataRef(nav2_freq_dataref_str.c_str());
com1_freq_dataref = XPLMFindDataRef(com1_freq_dataref_str.c_str());
com2_freq_dataref = XPLMFindDataRef(com2_freq_dataref_str.c_str());
com1_freq_833khz_dataref = XPLMFindDataRef(com1_freq_833khz_dataref_str.c_str());
transponder_code_dataref = XPLMFindDataRef(transponder_code_str.c_str());

XPLMSetDatai(nav1_freq_dataref, 11111);
XPLMSetDatai(nav2_freq_dataref, 22222);
XPLMSetDatai(com1_freq_dataref, 33333);
XPLMSetDatai(com2_freq_dataref, 44444);
XPLMSetDatai(com1_freq_833khz_dataref, 120375); // 120.375 Mhz is a 8.33kHz channel
XPLMSetDatai(transponder_code_dataref, 7001);
}

TEST_METHOD(Test_VID_PID)
Expand Down Expand Up @@ -98,6 +106,45 @@ namespace test
Assert::AreEqual(1, (int)write_buffer[5]);
}

TEST_METHOD(Test_Display_833kHz)
{
// set rotation switch to SW_COM_2 position
unsigned char buffer[4] = { 0x02,0,0,0 };
test_hid_set_read_data(buffer, sizeof(buffer));
std::this_thread::sleep_for(150ms);

test_flight_loop(device);
std::this_thread::sleep_for(150ms);

unsigned char write_buffer[23];
test_hid_get_write_data(write_buffer, sizeof(write_buffer));
Assert::AreEqual(1, (int)write_buffer[1]);
Assert::AreEqual(2, (int)write_buffer[2]);
Assert::AreEqual(0, (int)write_buffer[3]);
Assert::AreEqual(3, (int)write_buffer[4]);
Assert::AreEqual(7, (int)write_buffer[5] & 0x0F); // the digit at last position
Assert::AreEqual(0xD0, (int)write_buffer[5] & 0xF0); // the period after the last digit
}

TEST_METHOD(Test_4_digit_display)
{
// set rotation switch to XPDR position
unsigned char buffer[4] = { 0x40,0,0,0 };
test_hid_set_read_data(buffer, sizeof(buffer));
std::this_thread::sleep_for(150ms);

test_flight_loop(device);
std::this_thread::sleep_for(150ms);

unsigned char write_buffer[23];
test_hid_get_write_data(write_buffer, sizeof(write_buffer));
Assert::AreEqual(255, (int)write_buffer[1]);
Assert::AreEqual(7, (int)write_buffer[2]);
Assert::AreEqual(0, (int)write_buffer[3]);
Assert::AreEqual(0, (int)write_buffer[4]);
Assert::AreEqual(1, (int)write_buffer[5]);
}

TEST_METHOD(Test_Const_Value)
{
// set rotation switch to SW_UP_ADF position
Expand Down
Loading