Initial commit
Signed-off-by: fly <merspieler@alwaysdata.net>
This commit is contained in:
commit
0e7415296c
5 changed files with 868 additions and 0 deletions
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
*.swp
|
||||
*.swo
|
477
WinWingFCU.xml
Normal file
477
WinWingFCU.xml
Normal file
|
@ -0,0 +1,477 @@
|
|||
<?xml version="1.0"?>
|
||||
|
||||
<PropertyList>
|
||||
<name type="string">Winwing WINWING FCU-320</name>
|
||||
<debug-events type="bool">true</debug-events>
|
||||
<nasal>
|
||||
<open>
|
||||
<![CDATA[
|
||||
setprop("/winwing/spd", "100");
|
||||
setprop("/winwing/hdg", "360");
|
||||
setprop("/winwing/alt", "10000");
|
||||
setprop("/winwing/vs", "----");
|
||||
|
||||
var updateWinwingFCUDisplay = func() {
|
||||
if (getprop("/it-autoflight/input/spd-managed")) {
|
||||
setprop("/winwing/spd", "---");
|
||||
} else if (getprop("/controls/switches/annun-test")) {
|
||||
setprop("/winwing/spd", "888");
|
||||
} else if (getprop("/it-autoflight/input/kts-mach")) {
|
||||
setprop("/winwing/spd", getprop("/it-autoflight/input/mach") * 1000);
|
||||
} else {
|
||||
setprop("/winwing/spd", getprop("/it-autoflight/input/kts"));
|
||||
}
|
||||
|
||||
if (getprop("/it-autoflight/custom/show-hdg") != true and getprop("/it-autoflight/output/lat") != 0) {
|
||||
setprop("/winwing/hdg", "---");
|
||||
} else if (getprop("/controls/switches/annun-test")) {
|
||||
setprop("/winwing/hdg", "888");
|
||||
} else {
|
||||
setprop("/winwing/hdg", sprintf("%03.0f", getprop("/it-autoflight/input/hdg")));
|
||||
}
|
||||
|
||||
if (getprop("/controls/switches/annun-test")) {
|
||||
setprop("/winwing/alt", "88888");
|
||||
} else {
|
||||
setprop("/winwing/alt", sprintf("%05.0f", getprop("/it-autoflight/input/alt")));
|
||||
}
|
||||
|
||||
if (getprop("/controls/switches/annun-test")) {
|
||||
setprop("/winwing/vs", "8888");
|
||||
} else if (getprop("/it-autoflight/output/vert") != 1 and getprop("/it-autoflight/output/vert") != 5) {
|
||||
setprop("/winwing/vs", "----");
|
||||
} else {
|
||||
if (getprop("/it-autoflight/input/trk")) {
|
||||
setprop("/winwing/vs", sprintf("%02.0f", math.abs(getprop("/it-autoflight/input/fpa")) * 10));
|
||||
} else {
|
||||
setprop("/winwing/vs", sprintf("%04.0f", getprop("/it-autoflight/input/vs-abs")));
|
||||
}
|
||||
}
|
||||
|
||||
var flags = "";
|
||||
if (getprop("/controls/switches/annun-test") or getprop("/it-autoflight/input/kts-mach") == false) {
|
||||
flags = flags ~ ",spd";
|
||||
}
|
||||
if (getprop("/controls/switches/annun-test") or getprop("/it-autoflight/input/kts-mach")) {
|
||||
flags = flags ~ ",mach";
|
||||
}
|
||||
if (getprop("/controls/switches/annun-test") or getprop("/it-autoflight/input/spd-managed")) {
|
||||
flags = flags ~ ",spd-mgt";
|
||||
}
|
||||
|
||||
if (getprop("/controls/switches/annun-test") or getprop("/it-autoflight/output/lat") == 1 or getprop("/it-autoflight/output/lnav-armed")) {
|
||||
flags = flags ~ ",lat";
|
||||
}
|
||||
|
||||
if (getprop("/controls/switches/annun-test") or getprop("/it-autoflight/custom/trk-fpa") == false) {
|
||||
flags = flags ~ ",hdg-vs";
|
||||
}
|
||||
if (getprop("/controls/switches/annun-test") or getprop("/it-autoflight/custom/trk-fpa")) {
|
||||
flags = flags ~ ",trk-fpa";
|
||||
}
|
||||
|
||||
if (getprop("/controls/switches/annun-test") or (((getprop("/it-autoflight/input/vs") >= 0 and getprop("/it-autoflight/custom/trk-fpa") == false) or (getprop("/it-autoflight/input/fpa") >= 0 and getprop("/it-autoflight/custom/trk-fpa"))) and (getprop("/it-autoflight/output/vert") == 1 or getprop("/it-autoflight/output/vert") == 5))) {
|
||||
flags = flags ~ ",plus";
|
||||
}
|
||||
|
||||
if (getprop("/controls/switches/annun-test") or getprop("/it-autoflight/output/ap1")) {
|
||||
flags = flags ~ ",ap1";
|
||||
}
|
||||
if (getprop("/controls/switches/annun-test") or getprop("/it-autoflight/output/ap2")) {
|
||||
flags = flags ~ ",ap2";
|
||||
}
|
||||
if (getprop("/controls/switches/annun-test") or getprop("/it-autoflight/output/athr")) {
|
||||
flags = flags ~ ",athr";
|
||||
}
|
||||
if (getprop("/controls/switches/annun-test") or ((getprop("/it-autoflight/output/lat") == 2 or getprop("/it-autoflight/output/loc-arm") == 1) and getprop("/it-autoflight/output/gs-arm") == false and getprop("/it-autoflight/output/vert") != 2 and getprop("/it-autoflight/output/vert") != 6)) {
|
||||
flags = flags ~ ",loc";
|
||||
}
|
||||
if (getprop("/controls/switches/annun-test") or getprop("/it-autoflight/output/gs-arm") or getprop("/it-autoflight/output/vert") == 2 or getprop("/it-autoflight/output/vert") == 6) {
|
||||
flags = flags ~ ",appr";
|
||||
}
|
||||
|
||||
setprop("/winwing/flags", flags);
|
||||
return [0x00]; # dummy return so log doesn't get spammed anymore
|
||||
|
||||
};
|
||||
|
||||
var getButtonBrightnessReport = func(item, value) {
|
||||
var r = [0x10, 0xBB, 0x00, 0x00, 0x00, 0x49, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00];
|
||||
r[6] = item;
|
||||
r[7] = int(value);
|
||||
return r;
|
||||
};
|
||||
var updateWinwingFCUIntegLT = func() {
|
||||
var value = getprop("/controls/lighting/fcu-panel-norm") * 255;
|
||||
# debug.dump(getButtonBrightnessReport(0x00, value));
|
||||
return getButtonBrightnessReport(0x00, value);
|
||||
};
|
||||
]]>
|
||||
</open>
|
||||
</nasal>
|
||||
<hid-descriptor>
|
||||
<report>
|
||||
<type>input</type>
|
||||
<id>1</id>
|
||||
<button-1>
|
||||
<size type="int">1</size>
|
||||
<count type="int">128</count>
|
||||
</button-1>
|
||||
<unused-bits><size type="int">176</size></unused-bits>
|
||||
</report>
|
||||
<report>
|
||||
<type>input</type>
|
||||
<id>2</id>
|
||||
<dummy-1>
|
||||
<size type="int">8</size>
|
||||
<count type="int">13</count>
|
||||
</dummy-1>
|
||||
<unused-bits><size type="int">0</size></unused-bits>
|
||||
</report>
|
||||
<report>
|
||||
<type>output</type>
|
||||
<id>2</id>
|
||||
<display-0>
|
||||
<size type="int">104</size>
|
||||
<count type="int">1</count>
|
||||
</display-0>
|
||||
<unused-bits><size type="int">0</size></unused-bits>
|
||||
</report>
|
||||
<report>
|
||||
<type>input</type>
|
||||
<id>240</id>
|
||||
<dummy2-1>
|
||||
<size type="int">8</size>
|
||||
<count type="int">63</count>
|
||||
</dummy2-1>
|
||||
<unused-bits><size type="int">0</size></unused-bits>
|
||||
</report>
|
||||
<report>
|
||||
<type>output</type>
|
||||
<id>240</id>
|
||||
<display2-0>
|
||||
<size type="int">8</size>
|
||||
<count type="int">63</count>
|
||||
</display2-0>
|
||||
<unused-bits><size type="int">0</size></unused-bits>
|
||||
</report>
|
||||
</hid-descriptor>
|
||||
<report>
|
||||
<report-id type="int">2</report-id>
|
||||
<type>output</type>
|
||||
<watch>/controls/lighting/fcu-panel-norm</watch>
|
||||
<nasal-function>updateWinwingFCUIntegLT</nasal-function>
|
||||
</report>
|
||||
<report>
|
||||
<report-id type="int">2</report-id>
|
||||
<type>output</type>
|
||||
<watch>/it-autoflight/input/kts-mach</watch>
|
||||
<watch>/it-autoflight/input/kts</watch>
|
||||
<watch>/it-autoflight/input/mach</watch>
|
||||
<watch>/it-autoflight/input/hdg</watch>
|
||||
<watch>/it-autoflight/input/alt</watch>
|
||||
<watch>/it-autoflight/output/vs-fcu-display</watch>
|
||||
<watch>/controls/switches/annun-test</watch>
|
||||
<nasal-function>updateWinwingFCUDisplay</nasal-function>
|
||||
</report>
|
||||
<!--report>
|
||||
<type>feature</type>
|
||||
<watch>/controls/lighting/fcu-digit-norm</watch>
|
||||
<nasal-function>updateWinwingFCUDisplayBrightness</nasal-function>
|
||||
</report-->
|
||||
<event>
|
||||
<name>button-1</name>
|
||||
<desc type="string">IAS/Mach</desc>
|
||||
<repeatable type="string">false</repeatable>
|
||||
<binding>
|
||||
<command type="string">nasal</command>
|
||||
<script>
|
||||
fcu.FCUController.IASMach();
|
||||
</script>
|
||||
</binding>
|
||||
</event>
|
||||
<event>
|
||||
<name>button-2</name>
|
||||
<desc type="string">LOC</desc>
|
||||
<repeatable type="string">false</repeatable>
|
||||
<binding>
|
||||
<command type="string">nasal</command>
|
||||
<script>
|
||||
fcu.FCUController.LOCButton();
|
||||
</script>
|
||||
</binding>
|
||||
</event>
|
||||
<event>
|
||||
<name>button-3</name>
|
||||
<desc type="string">Track/Fligtht Path Angle</desc>
|
||||
<repeatable type="string">false</repeatable>
|
||||
<binding>
|
||||
<command type="string">nasal</command>
|
||||
<script>
|
||||
fcu.FCUController.TRKFPA();
|
||||
</script>
|
||||
</binding>
|
||||
</event>
|
||||
<event>
|
||||
<name>button-4</name>
|
||||
<desc type="string">Autopilot 1</desc>
|
||||
<repeatable type="string">false</repeatable>
|
||||
<binding>
|
||||
<command type="string">nasal</command>
|
||||
<script>
|
||||
fcu.FCUController.AP1();
|
||||
</script>
|
||||
</binding>
|
||||
</event>
|
||||
<event>
|
||||
<name>button-5</name>
|
||||
<desc type="string">Autopilot 2</desc>
|
||||
<repeatable type="string">false</repeatable>
|
||||
<binding>
|
||||
<command type="string">nasal</command>
|
||||
<script>
|
||||
fcu.FCUController.AP2();
|
||||
</script>
|
||||
</binding>
|
||||
</event>
|
||||
<event>
|
||||
<name>button-6</name>
|
||||
<desc type="string">Autothrust</desc>
|
||||
<repeatable type="string">false</repeatable>
|
||||
<binding>
|
||||
<command type="string">nasal</command>
|
||||
<script>
|
||||
fcu.FCUController.ATHR();
|
||||
</script>
|
||||
</binding>
|
||||
</event>
|
||||
<event>
|
||||
<name>button-7</name>
|
||||
<desc type="string">Expedite</desc>
|
||||
<repeatable type="string">false</repeatable>
|
||||
<binding>
|
||||
<command type="string">nasal</command>
|
||||
<script>
|
||||
|
||||
</script>
|
||||
</binding>
|
||||
</event>
|
||||
<event>
|
||||
<name>button-8</name>
|
||||
<desc type="string">Metric ALT</desc>
|
||||
<repeatable type="string">false</repeatable>
|
||||
<binding>
|
||||
<command type="string">nasal</command>
|
||||
<script>
|
||||
fcu.FCUController.MetricAlt();
|
||||
</script>
|
||||
</binding>
|
||||
</event>
|
||||
<event>
|
||||
<name>button-9</name>
|
||||
<desc type="string">Approach</desc>
|
||||
<repeatable type="string">false</repeatable>
|
||||
<binding>
|
||||
<command type="string">nasal</command>
|
||||
<script>
|
||||
fcu.FCUController.APPRButton();
|
||||
</script>
|
||||
</binding>
|
||||
</event>
|
||||
<event>
|
||||
<name>button-10</name>
|
||||
<desc type="string">Speed decrease</desc>
|
||||
<repeatable type="string">false</repeatable>
|
||||
<binding>
|
||||
<command type="string">nasal</command>
|
||||
<script>
|
||||
fcu.FCUController.SPDAdjust(-1);
|
||||
</script>
|
||||
</binding>
|
||||
</event>
|
||||
<event>
|
||||
<name>button-11</name>
|
||||
<desc type="string">Speed increase</desc>
|
||||
<repeatable type="string">false</repeatable>
|
||||
<binding>
|
||||
<command type="string">nasal</command>
|
||||
<script>
|
||||
fcu.FCUController.SPDAdjust(1);
|
||||
</script>
|
||||
</binding>
|
||||
</event>
|
||||
<event>
|
||||
<name>button-12</name>
|
||||
<desc type="string">Speed Push</desc>
|
||||
<repeatable type="string">false</repeatable>
|
||||
<binding>
|
||||
<command type="string">nasal</command>
|
||||
<script>
|
||||
fcu.FCUController.SPDPush();
|
||||
</script>
|
||||
</binding>
|
||||
</event>
|
||||
<event>
|
||||
<name>button-13</name>
|
||||
<desc type="string">Speed Pull</desc>
|
||||
<repeatable type="string">false</repeatable>
|
||||
<binding>
|
||||
<command type="string">nasal</command>
|
||||
<script>
|
||||
fcu.FCUController.SPDPull();
|
||||
</script>
|
||||
</binding>
|
||||
</event>
|
||||
<event>
|
||||
<name>button-14</name>
|
||||
<desc type="string">Heading decrease</desc>
|
||||
<repeatable type="string">false</repeatable>
|
||||
<binding>
|
||||
<command type="string">nasal</command>
|
||||
<script>
|
||||
fcu.FCUController.HDGAdjust(-1);
|
||||
</script>
|
||||
</binding>
|
||||
</event>
|
||||
<event>
|
||||
<name>button-15</name>
|
||||
<desc type="string">Heading increase</desc>
|
||||
<repeatable type="string">false</repeatable>
|
||||
<binding>
|
||||
<command type="string">nasal</command>
|
||||
<script>
|
||||
fcu.FCUController.HDGAdjust(1);
|
||||
</script>
|
||||
</binding>
|
||||
</event>
|
||||
<event>
|
||||
<name>button-16</name>
|
||||
<desc type="string">Heading push</desc>
|
||||
<repeatable type="string">false</repeatable>
|
||||
<binding>
|
||||
<command type="string">nasal</command>
|
||||
<script>
|
||||
fcu.FCUController.HDGPush();
|
||||
</script>
|
||||
</binding>
|
||||
</event>
|
||||
<event>
|
||||
<name>button-17</name>
|
||||
<desc type="string">Heading pull</desc>
|
||||
<repeatable type="string">false</repeatable>
|
||||
<binding>
|
||||
<command type="string">nasal</command>
|
||||
<script>
|
||||
fcu.FCUController.HDGPull();
|
||||
</script>
|
||||
</binding>
|
||||
</event>
|
||||
<event>
|
||||
<name>button-18</name>
|
||||
<desc type="string">Altitude decrease</desc>
|
||||
<repeatable type="string">false</repeatable>
|
||||
<binding>
|
||||
<command type="string">nasal</command>
|
||||
<script>
|
||||
fcu.FCUController.ALTAdjust(-1);
|
||||
</script>
|
||||
</binding>
|
||||
</event>
|
||||
<event>
|
||||
<name>button-19</name>
|
||||
<desc type="string">Altitude increase</desc>
|
||||
<repeatable type="string">false</repeatable>
|
||||
<binding>
|
||||
<command type="string">nasal</command>
|
||||
<script>
|
||||
fcu.FCUController.ALTAdjust(1);
|
||||
</script>
|
||||
</binding>
|
||||
</event>
|
||||
<event>
|
||||
<name>button-20</name>
|
||||
<desc type="string">Altitude Push</desc>
|
||||
<repeatable type="string">false</repeatable>
|
||||
<binding>
|
||||
<command type="string">nasal</command>
|
||||
<script>
|
||||
fcu.FCUController.ALTPush();
|
||||
</script>
|
||||
</binding>
|
||||
</event>
|
||||
<event>
|
||||
<name>button-21</name>
|
||||
<desc type="string">Altitude pull</desc>
|
||||
<repeatable type="string">false</repeatable>
|
||||
<binding>
|
||||
<command type="string">nasal</command>
|
||||
<script>
|
||||
fcu.FCUController.ALTPull();
|
||||
</script>
|
||||
</binding>
|
||||
</event>
|
||||
<event>
|
||||
<name>button-22</name>
|
||||
<desc type="string">Vertical Speed decrease</desc>
|
||||
<repeatable type="string">false</repeatable>
|
||||
<binding>
|
||||
<command type="string">nasal</command>
|
||||
<script>
|
||||
fcu.FCUController.VSAdjust(-1);
|
||||
</script>
|
||||
</binding>
|
||||
</event>
|
||||
<event>
|
||||
<name>button-23</name>
|
||||
<desc type="string">Vertical Speed increase</desc>
|
||||
<repeatable type="string">false</repeatable>
|
||||
<binding>
|
||||
<command type="string">nasal</command>
|
||||
<script>
|
||||
fcu.FCUController.VSAdjust(1);
|
||||
</script>
|
||||
</binding>
|
||||
</event>
|
||||
<event>
|
||||
<name>button-24</name>
|
||||
<desc type="string">Vertical Speed push</desc>
|
||||
<repeatable type="string">false</repeatable>
|
||||
<binding>
|
||||
<command type="string">nasal</command>
|
||||
<script>
|
||||
fcu.FCUController.VSPush();
|
||||
</script>
|
||||
</binding>
|
||||
</event>
|
||||
<event>
|
||||
<name>button-25</name>
|
||||
<desc type="string">Vertical Speed pull</desc>
|
||||
<repeatable type="string">false</repeatable>
|
||||
<binding>
|
||||
<command type="string">nasal</command>
|
||||
<script>
|
||||
fcu.FCUController.VSPull();
|
||||
</script>
|
||||
</binding>
|
||||
</event>
|
||||
<event>
|
||||
<name>button-26</name>
|
||||
<desc type="string">Altitude mode 100</desc>
|
||||
<repeatable type="string">false</repeatable>
|
||||
<binding>
|
||||
<command>property-assign</command>
|
||||
<property>it-autoflight/config/altitude-dial-mode</property>
|
||||
<value>0</value>
|
||||
</binding>
|
||||
</event>
|
||||
<event>
|
||||
<name>button-27</name>
|
||||
<desc type="string">Altitude mode 1000</desc>
|
||||
<repeatable type="string">false</repeatable>
|
||||
<binding>
|
||||
<command>property-assign</command>
|
||||
<property>it-autoflight/config/altitude-dial-mode</property>
|
||||
<value>1</value>
|
||||
</binding>
|
||||
</event>
|
||||
</PropertyList>
|
50
displayProtocol.xml
Normal file
50
displayProtocol.xml
Normal file
|
@ -0,0 +1,50 @@
|
|||
<?xml version="1.0"?>
|
||||
<PropertyList>
|
||||
<generic>
|
||||
<output>
|
||||
<binary_mode>false</binary_mode>
|
||||
<var_separator>,</var_separator>
|
||||
<chunk>
|
||||
<format>d</format>
|
||||
</chunk>
|
||||
<chunk>
|
||||
<node>/winwing/spd</node>
|
||||
<type>string</type>
|
||||
<format>%s</format>
|
||||
</chunk>
|
||||
<chunk>
|
||||
<node>/winwing/hdg</node>
|
||||
<type>string</type>
|
||||
<format>%s</format>
|
||||
</chunk>
|
||||
<chunk>
|
||||
<node>/winwing/alt</node>
|
||||
<type>string</type>
|
||||
<format>%s</format>
|
||||
</chunk>
|
||||
<chunk>
|
||||
<node>/winwing/vs</node>
|
||||
<type>string</type>
|
||||
<format>%s</format>
|
||||
</chunk>
|
||||
<chunk>
|
||||
<node>/controls/lighting/fcu-panel-norm</node>
|
||||
<type>float</type>
|
||||
<format>%01.2f</format>
|
||||
</chunk>
|
||||
<chunk>
|
||||
<node>/controls/lighting/fcu-digit-norm</node>
|
||||
<type>float</type>
|
||||
<format>%01.2f</format>
|
||||
</chunk>
|
||||
<chunk>
|
||||
<node>/winwing/flags</node>
|
||||
<type>string</type>
|
||||
<format>%s</format>
|
||||
</chunk>
|
||||
<chunk>
|
||||
<format>d</format>
|
||||
</chunk>
|
||||
</output>
|
||||
</generic>
|
||||
</PropertyList>
|
337
fcuSync.py
Executable file
337
fcuSync.py
Executable file
|
@ -0,0 +1,337 @@
|
|||
#! /usr/bin/env python3
|
||||
|
||||
from dataclasses import dataclass
|
||||
import time
|
||||
import os
|
||||
import sys
|
||||
import socket
|
||||
|
||||
from enum import Enum
|
||||
|
||||
import hid
|
||||
|
||||
hidraw_path = ""
|
||||
for device in hid.enumerate():
|
||||
if device["vendor_id"] == 0x4098 and device["product_id"] == 0xbb10:
|
||||
hidraw_path = device["path"]
|
||||
|
||||
if hidraw_path == "":
|
||||
print("Unable to find FCU device")
|
||||
sys.exit(1)
|
||||
|
||||
class Leds(Enum):
|
||||
BACKLIGHT = 0 # 0 .. 255
|
||||
SCREEN_BACKLIGHT = 1 # 0 .. 255
|
||||
LOC_GREEN = 3 # all on/off
|
||||
AP1_GREEN = 5
|
||||
AP2_GREEN = 7
|
||||
ATHR_GREEN = 9
|
||||
EXPED_GREEN = 11
|
||||
APPR_GREEN = 13
|
||||
FLAG_GREEN = 17 # 0 .. 255
|
||||
EXPED_YELLOW = 30 # 0 .. 255
|
||||
|
||||
# A
|
||||
# ---
|
||||
# F | G | B
|
||||
# ---
|
||||
# E | | C
|
||||
# ---
|
||||
# D
|
||||
# A=0x80, B=0x40, C=0x20, D=0x10, E=0x02, F=0x08, G=0x04
|
||||
# Bits are valid for Speed display only, all other share bits in 2 databyte per lcd 7-segment display.
|
||||
# Use function data_from_string_swapped to recalculate values
|
||||
representations = {
|
||||
'0' : 0xfa,
|
||||
'1' : 0x60,
|
||||
'2' : 0xd6,
|
||||
'3' : 0xf4,
|
||||
'4' : 0x6c,
|
||||
'5' : 0xbc,
|
||||
'6' : 0xbe,
|
||||
'7' : 0xe0,
|
||||
'8' : 0xfe,
|
||||
'9' : 0xfc,
|
||||
'A' : 0xee,
|
||||
'B' : 0xfe,
|
||||
'C' : 0x9a,
|
||||
'D' : 0x76,
|
||||
'E' : 0x9e,
|
||||
'F' : 0x8e,
|
||||
'G' : 0xbe,
|
||||
'H' : 0x6e,
|
||||
'I' : 0x60,
|
||||
'J' : 0x70,
|
||||
'K' : 0x0e,
|
||||
'L' : 0x1a,
|
||||
'M' : 0xa6,
|
||||
'N' : 0x26,
|
||||
'O' : 0xfa,
|
||||
'P' : 0xce,
|
||||
'Q' : 0xec,
|
||||
'R' : 0x06,
|
||||
'S' : 0xbc,
|
||||
'T' : 0x1e,
|
||||
'U' : 0x7a,
|
||||
'V' : 0x32,
|
||||
'W' : 0x58,
|
||||
'X' : 0x6e,
|
||||
'Y' : 0x7c,
|
||||
'Z' : 0xd6,
|
||||
'-' : 0x04,
|
||||
'#' : 0x36,
|
||||
'/' : 0x60,
|
||||
'\\' : 0xa0,
|
||||
' ' : 0x00,
|
||||
}
|
||||
|
||||
class Byte(Enum):
|
||||
H0 = 0
|
||||
H3 = 1
|
||||
A0 = 2
|
||||
A1 = 3
|
||||
A2 = 4
|
||||
A3 = 5
|
||||
A4 = 6
|
||||
A5 = 7
|
||||
V2 = 8
|
||||
V3 = 9
|
||||
V0 = 10
|
||||
V1 = 11
|
||||
S1 = 12
|
||||
|
||||
|
||||
|
||||
@dataclass
|
||||
class Flag:
|
||||
name : str
|
||||
byte : Byte
|
||||
mask : int
|
||||
value : bool = False
|
||||
|
||||
|
||||
flags = dict([("spd", Flag('spd-mach_spd', Byte.H3, 0x08, True)),
|
||||
("mach", Flag('spd-mach_mach', Byte.H3, 0x04)),
|
||||
("hdg", Flag('hdg-trk-lat_hdg', Byte.H0, 0x80)),
|
||||
("trk", Flag('hdg-trk-lat_trk', Byte.H0, 0x40)),
|
||||
("lat", Flag('hdg-trk-lat_lat', Byte.H0, 0x20, True)),
|
||||
("vshdg", Flag('hdg-v/s_hdg', Byte.A5, 0x08, True)),
|
||||
("vs", Flag('hdg-v/s_v/s', Byte.A5, 0x04, True)),
|
||||
("ftrk", Flag('trk-fpa_trk', Byte.A5, 0x02)),
|
||||
("ffpa", Flag('trk-fpa_fpa', Byte.A5, 0x01)),
|
||||
("alt", Flag('alt', Byte.A4, 0x10, True)),
|
||||
("hdg_managed", Flag('hdg managed', Byte.H0, 0x10)),
|
||||
("spd_managed", Flag('spd managed', Byte.H3, 0x02)),
|
||||
("alt_managed", Flag('alt_managed', Byte.V1, 0x10)),
|
||||
("vs_horz", Flag('v/s plus horizontal', Byte.A0, 0x10, True)),
|
||||
("vs_vert", Flag('v/s plus vertical', Byte.V2, 0x10)),
|
||||
("lvl", Flag('lvl change', Byte.A2, 0x10, True)),
|
||||
("lvl_left", Flag('lvl change left', Byte.A3, 0x10, True)),
|
||||
("lvl_right", Flag('lvl change right', Byte.A1, 0x10, True)),
|
||||
("fvs", Flag('v/s-fpa_v/s', Byte.V0, 0x40, True)),
|
||||
("ffpa2", Flag('v/s-fpa_fpa', Byte.V0, 0x80)),
|
||||
("fpa_comma", Flag('fpa_comma', Byte.V3, 0x10)),
|
||||
("mach_comma", Flag('mach_comma', Byte.S1, 0x01)),
|
||||
])
|
||||
|
||||
|
||||
def swap_nibbles(x):
|
||||
return ( (x & 0x0F)<<4 | (x & 0xF0)>>4 )
|
||||
|
||||
|
||||
def winwing_fcu_set_led(led, brightness):
|
||||
data = [0x02, 0x10, 0xbb, 0, 0, 3, 0x49, led.value, brightness, 0,0,0,0,0]
|
||||
cmd = bytes(data)
|
||||
send_data_to_hidraw(cmd)
|
||||
|
||||
|
||||
def lcd_init():
|
||||
data = [0xf0, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0] # init packet
|
||||
cmd = bytes(data)
|
||||
send_data_to_hidraw(cmd)
|
||||
|
||||
|
||||
def data_from_string(num_7segments, string):
|
||||
|
||||
l = num_7segments
|
||||
d = [0] * (l)
|
||||
for i in range(min(l, len(string))):
|
||||
r = representations.get(string.upper()[i])
|
||||
if r == None:
|
||||
r = 0xef
|
||||
print("ERROR: char '{string.upper()[i]}' not found")
|
||||
d[l-1-i] = r
|
||||
return d
|
||||
|
||||
|
||||
def data_from_string_swapped(num_7segments, string): # some 7-segemnts have wired mapping, correct ist here
|
||||
# return array with one byte more than lcd chars
|
||||
|
||||
l = num_7segments
|
||||
|
||||
d = data_from_string(l, string)
|
||||
d.append(0)
|
||||
|
||||
# fix wired segment mapping special elements such at the bars at the LVL/CH
|
||||
for i in range(len(d)):
|
||||
d[i] = swap_nibbles(d[i])
|
||||
for i in range(0, len(d) - 1):
|
||||
d[l-i] = (d[l-i] & 0x0f) | (d[l-1-i] & 0xf0)
|
||||
d[l-1-i] = d[l-1-i] & 0x0f
|
||||
|
||||
return d
|
||||
|
||||
|
||||
def winwing_fcu_lcd_set(speed, heading, alt,vs, new):
|
||||
s = data_from_string( 3, str(speed))
|
||||
h = data_from_string_swapped(3, str(heading))
|
||||
a = data_from_string_swapped(5, str(alt))
|
||||
v = data_from_string_swapped(4, str(vs))
|
||||
|
||||
bl = [0] * len(Byte)
|
||||
for f in flags:
|
||||
bl[flags[f].byte.value] |= (flags[f].mask * flags[f].value)
|
||||
|
||||
pkg_nr = 1
|
||||
data = [0xf0, 0x0, pkg_nr, 0x31, 0x10, 0xbb, 0x0, 0x0, 0x2, 0x1, 0x0, 0x0, 0xff, 0xff, 0x2, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, s[2], s[1], s[0], h[3] | bl[Byte.H3.value], h[2], h[1], h[0] | bl[Byte.H0.value], a[5] | bl[Byte.A5.value], a[4] | bl[Byte.A4.value], a[3] | bl[Byte.A3.value], a[2] | bl[Byte.A2.value], a[1] | bl[Byte.A1.value], a[0] | v[4] | bl[Byte.A0.value], v[3] | bl[Byte.V3.value], v[2] | bl[Byte.V2.value], v[1] | bl[Byte.V1.value], v[0] | bl[Byte.V0.value], 0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0]
|
||||
cmd = bytes(data)
|
||||
send_data_to_hidraw(cmd)
|
||||
|
||||
data = [0xf0, 0x0, pkg_nr, 0x11, 0x10, 0xbb, 0x0, 0x0, 0x3, 0x1, 0x0, 0x0, 0xff, 0xff, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0]
|
||||
cmd = bytes(data)
|
||||
send_data_to_hidraw(cmd)
|
||||
|
||||
def send_data_to_hidraw(data):
|
||||
global hidraw_path
|
||||
try:
|
||||
# Open the HIDRAW device
|
||||
hidraw = os.open(hidraw_path, os.O_RDWR | os.O_NONBLOCK)
|
||||
|
||||
# Write data to the HIDRAW device
|
||||
os.write(hidraw, bytes(data))
|
||||
|
||||
# print("Data sent successfully to HIDRAW device.")
|
||||
|
||||
# Close the HIDRAW device
|
||||
os.close(hidraw)
|
||||
except Exception as e:
|
||||
print("Error:", e)
|
||||
|
||||
|
||||
lcd_init()
|
||||
|
||||
speed = 100
|
||||
heading = 360
|
||||
alt = 10000
|
||||
vs = '----'
|
||||
|
||||
|
||||
winwing_fcu_set_led(Leds.BACKLIGHT, 70)
|
||||
winwing_fcu_set_led(Leds.EXPED_YELLOW, 70)
|
||||
winwing_fcu_set_led(Leds.SCREEN_BACKLIGHT, 200)
|
||||
winwing_fcu_lcd_set(speed, heading, alt, vs, 0x0)
|
||||
|
||||
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||
s.bind(('', 12000))
|
||||
try:
|
||||
while True:
|
||||
message, address = s.recvfrom(1024)
|
||||
print(message)
|
||||
items = str(message).split(",")
|
||||
winwing_fcu_lcd_set(items[1], items[2], items[3], items[4], 0x0)
|
||||
winwing_fcu_set_led(Leds.BACKLIGHT, int(float(items[5]) * 255))
|
||||
winwing_fcu_set_led(Leds.EXPED_YELLOW, int(float(items[5]) * 255))
|
||||
winwing_fcu_set_led(Leds.SCREEN_BACKLIGHT, int(float(items[6]) * 255))
|
||||
|
||||
if "spd" in items:
|
||||
flags["spd"].value = True
|
||||
else:
|
||||
flags["spd"].value = False
|
||||
if "mach" in items:
|
||||
flags["mach"].value = True
|
||||
flags["mach_comma"].value = True
|
||||
else:
|
||||
flags["mach"].value = False
|
||||
flags["mach_comma"].value = False
|
||||
if "spd-mgt" in items:
|
||||
flags["spd_managed"].value = True
|
||||
else:
|
||||
flags["spd_managed"].value = False
|
||||
|
||||
if "lat" in items:
|
||||
flags["lat"].value = True
|
||||
flags["hdg_managed"].value = True
|
||||
else:
|
||||
flags["lat"].value = False
|
||||
flags["hdg_managed"].value = False
|
||||
|
||||
if "hdg-vs" in items:
|
||||
flags["hdg"].value = True
|
||||
flags["vshdg"].value = True
|
||||
flags["vs"].value = True
|
||||
flags["fvs"].value = True
|
||||
else:
|
||||
flags["hdg"].value = False
|
||||
flags["vshdg"].value = False
|
||||
flags["vs"].value = False
|
||||
flags["fvs"].value = False
|
||||
if "trk-fpa" in items:
|
||||
flags["trk"].value = True
|
||||
flags["ftrk"].value = True
|
||||
flags["ffpa"].value = True
|
||||
flags["ffpa2"].value = True
|
||||
if items[4] != "----":
|
||||
flags["fpa_comma"].value = True
|
||||
else:
|
||||
flags["fpa_comma"].value = False
|
||||
else:
|
||||
flags["trk"].value = False
|
||||
flags["ftrk"].value = False
|
||||
flags["ffpa"].value = False
|
||||
flags["ffpa2"].value = False
|
||||
flags["fpa_comma"].value = False
|
||||
|
||||
if "plus" in items:
|
||||
flags["vs_vert"].value = True
|
||||
else:
|
||||
flags["vs_vert"].value = False
|
||||
|
||||
if "ap1" in items:
|
||||
winwing_fcu_set_led(Leds.AP1_GREEN, 1)
|
||||
else:
|
||||
winwing_fcu_set_led(Leds.AP1_GREEN, 0)
|
||||
if "ap2" in items:
|
||||
winwing_fcu_set_led(Leds.AP2_GREEN, 1)
|
||||
else:
|
||||
winwing_fcu_set_led(Leds.AP2_GREEN, 0)
|
||||
if "athr" in items:
|
||||
winwing_fcu_set_led(Leds.ATHR_GREEN, 1)
|
||||
else:
|
||||
winwing_fcu_set_led(Leds.ATHR_GREEN, 0)
|
||||
if "loc" in items:
|
||||
winwing_fcu_set_led(Leds.LOC_GREEN, 1)
|
||||
else:
|
||||
winwing_fcu_set_led(Leds.LOC_GREEN, 0)
|
||||
if "appr" in items:
|
||||
winwing_fcu_set_led(Leds.APPR_GREEN, 1)
|
||||
else:
|
||||
winwing_fcu_set_led(Leds.APPR_GREEN, 0)
|
||||
|
||||
|
||||
except KeyboardInterrupt:
|
||||
s.close()
|
||||
|
||||
#while True:
|
||||
# buf_in = [None] * 7
|
||||
# winwing_fcu_set_led(Leds.AP1_GREEN, 1)
|
||||
# winwing_fcu_set_led(Leds.AP2_GREEN, 0)
|
||||
# winwing_fcu_lcd_set(speed, heading, alt, vs, 0x0)
|
||||
# speed = speed + 1
|
||||
# heading = heading + 3
|
||||
# if heading > 360:
|
||||
# heading = 0
|
||||
# time.sleep(0.5)
|
||||
# winwing_fcu_set_led(Leds.AP1_GREEN, 0)
|
||||
# winwing_fcu_set_led(Leds.AP2_GREEN, 1)
|
||||
# winwing_fcu_lcd_set(speed, heading, alt, vs, 0xff)
|
||||
# time.sleep(0.5)
|
2
nix-shell.sh
Executable file
2
nix-shell.sh
Executable file
|
@ -0,0 +1,2 @@
|
|||
#! /usr/bin/env bash
|
||||
nix-shell -p "python311.withPackages (ps: with ps; [ hidapi ])"
|
Loading…
Reference in a new issue