Compare commits

...

62 Commits

Author SHA1 Message Date
Ben Lye
d5885d96b9 Bump action versions 2023-06-14 12:46:28 +01:00
Ben Lye
f1ede37f6d Used a fixed version of Arduino CLI 2023-06-14 12:46:10 +01:00
Ben Lye
c814cc1bd4 Switch back to non-devel boards for CI/CD (#863) 2023-06-14 13:29:34 +02:00
pascallanger
4e7c1502ff Update Protocols_Details.md 2023-06-04 13:48:04 +02:00
pascallanger
8ddee12de5 Update _Config.h 2023-06-04 12:50:39 +02:00
pascallanger
692bcc1fbb Update Scorpio_cyrf6936.ino 2023-06-04 12:38:09 +02:00
pascallanger
0bb345e3fc J6Pro save some flash space 2023-06-04 12:20:10 +02:00
pascallanger
c193d0b9dd Update Multiprotocol.ino 2023-06-04 12:12:22 +02:00
pascallanger
410ce5cc4c Fixed SX1276 protocol 2023-06-04 12:07:27 +02:00
pascallanger
cefe69a692 Fix SPORT when using FRSKYX (V1) protocol set to EU LBT 2023-06-04 12:03:43 +02:00
pascallanger
daa4ded390 New protocol Scorpio
Model Falco 300
2023-06-04 12:02:37 +02:00
pascallanger
5949fca990 Update Protocols_Details.md (#856) 2023-05-15 08:26:13 +02:00
pascallanger
ed2e2e4f32 Update Protocols_Details.md 2023-05-15 08:17:19 +02:00
Frankie Arzu
b2f8f482bb V0.54 Enhacements (#846)
* #751 DSM Enhancements

 #751 DSM Forward Programming Enhancements (New GUI, etc)

* Make both work on EdgeTx and OpenTX

* #751 Turn OFF simulation by default

Distribution code with RX simulation OFF
Simulation should be only for Development

* #751 Update Readme Documentation

Updated the Readme.txt documentation
and removed compiled luac file that was check in by mistake

* #751 Fix problems With Reset RX

1. Fix problem when trying to Factory Reset. Enter Bind Mode. Save backup, Restore Backup

2. Found a way to advance on the Gyro initial Setup menus.. a bit of a hack, but works.

3. Handle RX resets properly. It needed after initial setup

* #751 Cosmetic and Show Orientation Images

#751
1. Fix problems when text contradictions between Menu/Line Headers and List Values
2. Show Images of RX orientations
3. Able to Hack getting into Initial Setup and other menus who was failing before
4. Custumize the way Flight Mode reports the Value on Screen

* #751 add check for required libraries

Add check that the required files in DSMLIB exist

* #751

Write documentation about the protocol so that we don't forget later what we know, and enable others to understand the logs and maybe help solve problems.

* #766

Change the way to detect that the files exist. now works on both ETX and OTX

* #766 Strange Flickering in OTX

Strange Flickering happening on OTX. Refreshing the screen on every cycle fixed the problem

* #766 Change way of dectecting EdgeTX

Change way of detecting OTX in multiple versions: OTX 2.3.14 and 2.3.15

* #766  make editable Gain Values

Gains and other settings should be editable even when they are VALUE_NOCHANGING. Flight Mode is an exception that is handled properly. Right align numbers.

* #766 More enhacements

Added AR630
Make numbers right justified
Cleanup some log messages and line types.
Updated DSM FWD prog documentation

* #751 more cosmetic things

1. Added AR10360T,
2. Simplify way to configured the hack for more receivers.
3. Change some texts on menus to march spektrum
4. Background color in Spektrum theme to match

* #751 A few final changes

1. Update channel names to include channel number. i.e: Ch5 (Gear)
2,  Fix flight mode display for Heli Receiver
3. i think the unknown lines are to request info about the TX settings

* #751

1. Added Warning Screen
2. Correct handling of Unknown lines in Gyro Settings->Initial Setup

* #751

New v0.51 version.
- Added new menus to configure Model/Wing type.  Without it, the initial setup will not work properly.

* #751 More fixes on mixers and servo reverse

-- Fix problem reversing servos when using vtail/delta mix
-- Properly detect ch order of multimodule

* #751 Updated channel naming and docs

Updated readme documentation
Consistent naming of Ch across the code.

* #751 Fix message displaying data path

* #751  More improvements

1. Much easier to select channels > Ch6 for FMode, Gain and Panic channels
2. B&W version for smaller screens (128x64).. Memory footprint still a problem.
3. Fix a lot typos/misspell/grammar in the documentation

* Create DSM_AR636_TextGen.lua

Script to show Telemetry TextGen screens
for AR636 Receiver.
Really useful for BLADE helis using the AR636

Could replace dsmPID.lua

Still needs to be ported to smaller screens.

* #751 Enhancements for Lua Script tools

Enhancements

* Delete DSM_AR636_TextGen.lua

The TextGen functionality is included in DSM_AR636_Tel.lua. No longer needed

* Version 0.54

1. Fix problem with "Attitude Trim" Menu
2. New "MINimalistic" version for radios with very low memory
3. Externalized menu messages shared by all versions. the idea is to allow to translate it into other languages.
4. Correction of TextGen tools to work on black&white radios (some Lua functional differences). TextGen will be working on EdgeTx 2,8.3

---------

Co-authored-by: pascallanger <pascal_langer@yahoo.fr>
2023-04-16 21:42:31 +02:00
Frankie Arzu
89023d4b55 Remove DSM_AR636_TextGen.lua (#837)
* #751 DSM Enhancements

 #751 DSM Forward Programming Enhancements (New GUI, etc)

* Make both work on EdgeTx and OpenTX

* #751 Turn OFF simulation by default

Distribution code with RX simulation OFF
Simulation should be only for Development

* #751 Update Readme Documentation

Updated the Readme.txt documentation
and removed compiled luac file that was check in by mistake

* #751 Fix problems With Reset RX

1. Fix problem when trying to Factory Reset. Enter Bind Mode. Save backup, Restore Backup

2. Found a way to advance on the Gyro initial Setup menus.. a bit of a hack, but works.

3. Handle RX resets properly. It needed after initial setup

* #751 Cosmetic and Show Orientation Images

#751
1. Fix problems when text contradictions between Menu/Line Headers and List Values
2. Show Images of RX orientations
3. Able to Hack getting into Initial Setup and other menus who was failing before
4. Custumize the way Flight Mode reports the Value on Screen

* #751 add check for required libraries

Add check that the required files in DSMLIB exist

* #751

Write documentation about the protocol so that we don't forget later what we know, and enable others to understand the logs and maybe help solve problems.

* #766

Change the way to detect that the files exist. now works on both ETX and OTX

* #766 Strange Flickering in OTX

Strange Flickering happening on OTX. Refreshing the screen on every cycle fixed the problem

* #766 Change way of dectecting EdgeTX

Change way of detecting OTX in multiple versions: OTX 2.3.14 and 2.3.15

* #766  make editable Gain Values

Gains and other settings should be editable even when they are VALUE_NOCHANGING. Flight Mode is an exception that is handled properly. Right align numbers.

* #766 More enhacements

Added AR630
Make numbers right justified
Cleanup some log messages and line types.
Updated DSM FWD prog documentation

* #751 more cosmetic things

1. Added AR10360T,
2. Simplify way to configured the hack for more receivers.
3. Change some texts on menus to march spektrum
4. Background color in Spektrum theme to match

* #751 A few final changes

1. Update channel names to include channel number. i.e: Ch5 (Gear)
2,  Fix flight mode display for Heli Receiver
3. i think the unknown lines are to request info about the TX settings

* #751

1. Added Warning Screen
2. Correct handling of Unknown lines in Gyro Settings->Initial Setup

* #751

New v0.51 version.
- Added new menus to configure Model/Wing type.  Without it, the initial setup will not work properly.

* #751 More fixes on mixers and servo reverse

-- Fix problem reversing servos when using vtail/delta mix
-- Properly detect ch order of multimodule

* #751 Updated channel naming and docs

Updated readme documentation
Consistent naming of Ch across the code.

* #751 Fix message displaying data path

* #751  More improvements

1. Much easier to select channels > Ch6 for FMode, Gain and Panic channels
2. B&W version for smaller screens (128x64).. Memory footprint still a problem.
3. Fix a lot typos/misspell/grammar in the documentation

* Create DSM_AR636_TextGen.lua

Script to show Telemetry TextGen screens
for AR636 Receiver.
Really useful for BLADE helis using the AR636

Could replace dsmPID.lua

Still needs to be ported to smaller screens.

* #751 Enhancements for Lua Script tools

Enhancements

* Delete DSM_AR636_TextGen.lua

The TextGen functionality is included in DSM_AR636_Tel.lua. No longer needed

---------

Co-authored-by: pascallanger <pascal_langer@yahoo.fr>
2023-03-19 06:19:35 +01:00
Frankie Arzu
66ac007d4c Frankie dsm telemetry lua scripts enhancements (#835)
* #751 DSM Enhancements

 #751 DSM Forward Programming Enhancements (New GUI, etc)

* Make both work on EdgeTx and OpenTX

* #751 Turn OFF simulation by default

Distribution code with RX simulation OFF
Simulation should be only for Development

* #751 Update Readme Documentation

Updated the Readme.txt documentation
and removed compiled luac file that was check in by mistake

* #751 Fix problems With Reset RX

1. Fix problem when trying to Factory Reset. Enter Bind Mode. Save backup, Restore Backup

2. Found a way to advance on the Gyro initial Setup menus.. a bit of a hack, but works.

3. Handle RX resets properly. It needed after initial setup

* #751 Cosmetic and Show Orientation Images

#751
1. Fix problems when text contradictions between Menu/Line Headers and List Values
2. Show Images of RX orientations
3. Able to Hack getting into Initial Setup and other menus who was failing before
4. Custumize the way Flight Mode reports the Value on Screen

* #751 add check for required libraries

Add check that the required files in DSMLIB exist

* #751

Write documentation about the protocol so that we don't forget later what we know, and enable others to understand the logs and maybe help solve problems.

* #766

Change the way to detect that the files exist. now works on both ETX and OTX

* #766 Strange Flickering in OTX

Strange Flickering happening on OTX. Refreshing the screen on every cycle fixed the problem

* #766 Change way of dectecting EdgeTX

Change way of detecting OTX in multiple versions: OTX 2.3.14 and 2.3.15

* #766  make editable Gain Values

Gains and other settings should be editable even when they are VALUE_NOCHANGING. Flight Mode is an exception that is handled properly. Right align numbers.

* #766 More enhacements

Added AR630
Make numbers right justified
Cleanup some log messages and line types.
Updated DSM FWD prog documentation

* #751 more cosmetic things

1. Added AR10360T,
2. Simplify way to configured the hack for more receivers.
3. Change some texts on menus to march spektrum
4. Background color in Spektrum theme to match

* #751 A few final changes

1. Update channel names to include channel number. i.e: Ch5 (Gear)
2,  Fix flight mode display for Heli Receiver
3. i think the unknown lines are to request info about the TX settings

* #751

1. Added Warning Screen
2. Correct handling of Unknown lines in Gyro Settings->Initial Setup

* #751

New v0.51 version.
- Added new menus to configure Model/Wing type.  Without it, the initial setup will not work properly.

* #751 More fixes on mixers and servo reverse

-- Fix problem reversing servos when using vtail/delta mix
-- Properly detect ch order of multimodule

* #751 Updated channel naming and docs

Updated readme documentation
Consistent naming of Ch across the code.

* #751 Fix message displaying data path

* #751  More improvements

1. Much easier to select channels > Ch6 for FMode, Gain and Panic channels
2. B&W version for smaller screens (128x64).. Memory footprint still a problem.
3. Fix a lot typos/misspell/grammar in the documentation

* Create DSM_AR636_TextGen.lua

Script to show Telemetry TextGen screens
for AR636 Receiver.
Really useful for BLADE helis using the AR636

Could replace dsmPID.lua

Still needs to be ported to smaller screens.

* #751 Enhancements for Lua Script tools

Enhancements

---------

Co-authored-by: pascallanger <pascal_langer@yahoo.fr>
2023-03-18 19:31:48 +01:00
Frankie Arzu
139cd4c583 Telemetry TextGen/Screens for BLADE Helis with AR636 (#813)
* #751 DSM Enhancements

 #751 DSM Forward Programming Enhancements (New GUI, etc)

* Make both work on EdgeTx and OpenTX

* #751 Turn OFF simulation by default

Distribution code with RX simulation OFF
Simulation should be only for Development

* #751 Update Readme Documentation

Updated the Readme.txt documentation
and removed compiled luac file that was check in by mistake

* #751 Fix problems With Reset RX

1. Fix problem when trying to Factory Reset. Enter Bind Mode. Save backup, Restore Backup

2. Found a way to advance on the Gyro initial Setup menus.. a bit of a hack, but works.

3. Handle RX resets properly. It needed after initial setup

* #751 Cosmetic and Show Orientation Images

#751
1. Fix problems when text contradictions between Menu/Line Headers and List Values
2. Show Images of RX orientations
3. Able to Hack getting into Initial Setup and other menus who was failing before
4. Custumize the way Flight Mode reports the Value on Screen

* #751 add check for required libraries

Add check that the required files in DSMLIB exist

* #751

Write documentation about the protocol so that we don't forget later what we know, and enable others to understand the logs and maybe help solve problems.

* #766

Change the way to detect that the files exist. now works on both ETX and OTX

* #766 Strange Flickering in OTX

Strange Flickering happening on OTX. Refreshing the screen on every cycle fixed the problem

* #766 Change way of dectecting EdgeTX

Change way of detecting OTX in multiple versions: OTX 2.3.14 and 2.3.15

* #766  make editable Gain Values

Gains and other settings should be editable even when they are VALUE_NOCHANGING. Flight Mode is an exception that is handled properly. Right align numbers.

* #766 More enhacements

Added AR630
Make numbers right justified
Cleanup some log messages and line types.
Updated DSM FWD prog documentation

* #751 more cosmetic things

1. Added AR10360T,
2. Simplify way to configured the hack for more receivers.
3. Change some texts on menus to march spektrum
4. Background color in Spektrum theme to match

* #751 A few final changes

1. Update channel names to include channel number. i.e: Ch5 (Gear)
2,  Fix flight mode display for Heli Receiver
3. i think the unknown lines are to request info about the TX settings

* #751

1. Added Warning Screen
2. Correct handling of Unknown lines in Gyro Settings->Initial Setup

* #751

New v0.51 version.
- Added new menus to configure Model/Wing type.  Without it, the initial setup will not work properly.

* #751 More fixes on mixers and servo reverse

-- Fix problem reversing servos when using vtail/delta mix
-- Properly detect ch order of multimodule

* #751 Updated channel naming and docs

Updated readme documentation
Consistent naming of Ch across the code.

* #751 Fix message displaying data path

* #751  More improvements

1. Much easier to select channels > Ch6 for FMode, Gain and Panic channels
2. B&W version for smaller screens (128x64).. Memory footprint still a problem.
3. Fix a lot typos/misspell/grammar in the documentation

* Create DSM_AR636_TextGen.lua

Script to show Telemetry TextGen screens
for AR636 Receiver.
Really useful for BLADE helis using the AR636

Could replace dsmPID.lua

Still needs to be ported to smaller screens.

---------

Co-authored-by: pascallanger <pascal_langer@yahoo.fr>
2023-02-07 10:48:46 +01:00
richardclli
0fed2486f5 FX9630 protocol support, resolves #801 (#805)
New protocol FX9630
2023-01-16 20:06:27 +01:00
Filip Kotoucek
11c01004bf KF606: subprotocol ZC-Z50v2 Cessna (#797)
Maybe newer iteration of Z50. My plane does not have front propeller.
But if there is one, its just for design. This model does not have front motor.

Thanks @pascallanger for support and reviews.
2023-01-15 21:26:35 +01:00
Frankie Arzu
f49f03d7da Frankie dsm fwrd prg enhancements (#806)
* #751 DSM Enhancements

 #751 DSM Forward Programming Enhancements (New GUI, etc)

* Make both work on EdgeTx and OpenTX

* #751 Turn OFF simulation by default

Distribution code with RX simulation OFF
Simulation should be only for Development

* #751 Update Readme Documentation

Updated the Readme.txt documentation
and removed compiled luac file that was check in by mistake

* #751 Fix problems With Reset RX

1. Fix problem when trying to Factory Reset. Enter Bind Mode. Save backup, Restore Backup

2. Found a way to advance on the Gyro initial Setup menus.. a bit of a hack, but works.

3. Handle RX resets properly. It needed after initial setup

* #751 Cosmetic and Show Orientation Images

#751
1. Fix problems when text contradictions between Menu/Line Headers and List Values
2. Show Images of RX orientations
3. Able to Hack getting into Initial Setup and other menus who was failing before
4. Custumize the way Flight Mode reports the Value on Screen

* #751 add check for required libraries

Add check that the required files in DSMLIB exist

* #751

Write documentation about the protocol so that we don't forget later what we know, and enable others to understand the logs and maybe help solve problems.

* #766

Change the way to detect that the files exist. now works on both ETX and OTX

* #766 Strange Flickering in OTX

Strange Flickering happening on OTX. Refreshing the screen on every cycle fixed the problem

* #766 Change way of dectecting EdgeTX

Change way of detecting OTX in multiple versions: OTX 2.3.14 and 2.3.15

* #766  make editable Gain Values

Gains and other settings should be editable even when they are VALUE_NOCHANGING. Flight Mode is an exception that is handled properly. Right align numbers.

* #766 More enhacements

Added AR630
Make numbers right justified
Cleanup some log messages and line types.
Updated DSM FWD prog documentation

* #751 more cosmetic things

1. Added AR10360T,
2. Simplify way to configured the hack for more receivers.
3. Change some texts on menus to march spektrum
4. Background color in Spektrum theme to match

* #751 A few final changes

1. Update channel names to include channel number. i.e: Ch5 (Gear)
2,  Fix flight mode display for Heli Receiver
3. i think the unknown lines are to request info about the TX settings

* #751

1. Added Warning Screen
2. Correct handling of Unknown lines in Gyro Settings->Initial Setup

* #751

New v0.51 version.
- Added new menus to configure Model/Wing type.  Without it, the initial setup will not work properly.

* #751 More fixes on mixers and servo reverse

-- Fix problem reversing servos when using vtail/delta mix
-- Properly detect ch order of multimodule

* #751 Updated channel naming and docs

Updated readme documentation
Consistent naming of Ch across the code.

* #751 Fix message displaying data path

* #751  More improvements

1. Much easier to select channels > Ch6 for FMode, Gain and Panic channels
2. B&W version for smaller screens (128x64).. Memory footprint still a problem.
3. Fix a lot typos/misspell/grammar in the documentation

Co-authored-by: pascallanger <pascal_langer@yahoo.fr>
2023-01-15 11:27:34 +01:00
Louis Botha
90bb5f8871 Update Protocols_Details.md (#796)
Fixed spelling mistake
2023-01-12 10:59:20 +01:00
Frankie Arzu
401cc76f20 Fix message displaying the DataPath after saving (#787)
* #751 DSM Enhancements

 #751 DSM Forward Programming Enhancements (New GUI, etc)

* Make both work on EdgeTx and OpenTX

* #751 Turn OFF simulation by default

Distribution code with RX simulation OFF
Simulation should be only for Development

* #751 Update Readme Documentation

Updated the Readme.txt documentation
and removed compiled luac file that was check in by mistake

* #751 Fix problems With Reset RX

1. Fix problem when trying to Factory Reset. Enter Bind Mode. Save backup, Restore Backup

2. Found a way to advance on the Gyro initial Setup menus.. a bit of a hack, but works.

3. Handle RX resets properly. It needed after initial setup

* #751 Cosmetic and Show Orientation Images

#751
1. Fix problems when text contradictions between Menu/Line Headers and List Values
2. Show Images of RX orientations
3. Able to Hack getting into Initial Setup and other menus who was failing before
4. Custumize the way Flight Mode reports the Value on Screen

* #751 add check for required libraries

Add check that the required files in DSMLIB exist

* #751

Write documentation about the protocol so that we don't forget later what we know, and enable others to understand the logs and maybe help solve problems.

* #766

Change the way to detect that the files exist. now works on both ETX and OTX

* #766 Strange Flickering in OTX

Strange Flickering happening on OTX. Refreshing the screen on every cycle fixed the problem

* #766 Change way of dectecting EdgeTX

Change way of detecting OTX in multiple versions: OTX 2.3.14 and 2.3.15

* #766  make editable Gain Values

Gains and other settings should be editable even when they are VALUE_NOCHANGING. Flight Mode is an exception that is handled properly. Right align numbers.

* #766 More enhacements

Added AR630
Make numbers right justified
Cleanup some log messages and line types.
Updated DSM FWD prog documentation

* #751 more cosmetic things

1. Added AR10360T,
2. Simplify way to configured the hack for more receivers.
3. Change some texts on menus to march spektrum
4. Background color in Spektrum theme to match

* #751 A few final changes

1. Update channel names to include channel number. i.e: Ch5 (Gear)
2,  Fix flight mode display for Heli Receiver
3. i think the unknown lines are to request info about the TX settings

* #751

1. Added Warning Screen
2. Correct handling of Unknown lines in Gyro Settings->Initial Setup

* #751

New v0.51 version.
- Added new menus to configure Model/Wing type.  Without it, the initial setup will not work properly.

* #751 More fixes on mixers and servo reverse

-- Fix problem reversing servos when using vtail/delta mix
-- Properly detect ch order of multimodule

* #751 Updated channel naming and docs

Updated readme documentation
Consistent naming of Ch across the code.

* #751 Fix message displaying data path

Co-authored-by: pascallanger <pascal_langer@yahoo.fr>
2022-12-20 23:48:23 +01:00
Frankie Arzu
6297810edc Updated Ch naming across all display, and updated Docs (#786)
* #751 DSM Enhancements

 #751 DSM Forward Programming Enhancements (New GUI, etc)

* Make both work on EdgeTx and OpenTX

* #751 Turn OFF simulation by default

Distribution code with RX simulation OFF
Simulation should be only for Development

* #751 Update Readme Documentation

Updated the Readme.txt documentation
and removed compiled luac file that was check in by mistake

* #751 Fix problems With Reset RX

1. Fix problem when trying to Factory Reset. Enter Bind Mode. Save backup, Restore Backup

2. Found a way to advance on the Gyro initial Setup menus.. a bit of a hack, but works.

3. Handle RX resets properly. It needed after initial setup

* #751 Cosmetic and Show Orientation Images

#751
1. Fix problems when text contradictions between Menu/Line Headers and List Values
2. Show Images of RX orientations
3. Able to Hack getting into Initial Setup and other menus who was failing before
4. Custumize the way Flight Mode reports the Value on Screen

* #751 add check for required libraries

Add check that the required files in DSMLIB exist

* #751

Write documentation about the protocol so that we don't forget later what we know, and enable others to understand the logs and maybe help solve problems.

* #766

Change the way to detect that the files exist. now works on both ETX and OTX

* #766 Strange Flickering in OTX

Strange Flickering happening on OTX. Refreshing the screen on every cycle fixed the problem

* #766 Change way of dectecting EdgeTX

Change way of detecting OTX in multiple versions: OTX 2.3.14 and 2.3.15

* #766  make editable Gain Values

Gains and other settings should be editable even when they are VALUE_NOCHANGING. Flight Mode is an exception that is handled properly. Right align numbers.

* #766 More enhacements

Added AR630
Make numbers right justified
Cleanup some log messages and line types.
Updated DSM FWD prog documentation

* #751 more cosmetic things

1. Added AR10360T,
2. Simplify way to configured the hack for more receivers.
3. Change some texts on menus to march spektrum
4. Background color in Spektrum theme to match

* #751 A few final changes

1. Update channel names to include channel number. i.e: Ch5 (Gear)
2,  Fix flight mode display for Heli Receiver
3. i think the unknown lines are to request info about the TX settings

* #751

1. Added Warning Screen
2. Correct handling of Unknown lines in Gyro Settings->Initial Setup

* #751

New v0.51 version.
- Added new menus to configure Model/Wing type.  Without it, the initial setup will not work properly.

* #751 More fixes on mixers and servo reverse

-- Fix problem reversing servos when using vtail/delta mix
-- Properly detect ch order of multimodule

* #751 Updated channel naming and docs

Updated readme documentation
Consistent naming of Ch across the code.

Co-authored-by: pascallanger <pascal_langer@yahoo.fr>
2022-12-20 22:58:38 +01:00
Frankie Arzu
01aef0a822 Frankie dsm fwrd prg enhancements (#785)
* #751 DSM Enhancements

 #751 DSM Forward Programming Enhancements (New GUI, etc)

* Make both work on EdgeTx and OpenTX

* #751 Turn OFF simulation by default

Distribution code with RX simulation OFF
Simulation should be only for Development

* #751 Update Readme Documentation

Updated the Readme.txt documentation
and removed compiled luac file that was check in by mistake

* #751 Fix problems With Reset RX

1. Fix problem when trying to Factory Reset. Enter Bind Mode. Save backup, Restore Backup

2. Found a way to advance on the Gyro initial Setup menus.. a bit of a hack, but works.

3. Handle RX resets properly. It needed after initial setup

* #751 Cosmetic and Show Orientation Images

#751
1. Fix problems when text contradictions between Menu/Line Headers and List Values
2. Show Images of RX orientations
3. Able to Hack getting into Initial Setup and other menus who was failing before
4. Custumize the way Flight Mode reports the Value on Screen

* #751 add check for required libraries

Add check that the required files in DSMLIB exist

* #751

Write documentation about the protocol so that we don't forget later what we know, and enable others to understand the logs and maybe help solve problems.

* #766

Change the way to detect that the files exist. now works on both ETX and OTX

* #766 Strange Flickering in OTX

Strange Flickering happening on OTX. Refreshing the screen on every cycle fixed the problem

* #766 Change way of dectecting EdgeTX

Change way of detecting OTX in multiple versions: OTX 2.3.14 and 2.3.15

* #766  make editable Gain Values

Gains and other settings should be editable even when they are VALUE_NOCHANGING. Flight Mode is an exception that is handled properly. Right align numbers.

* #766 More enhacements

Added AR630
Make numbers right justified
Cleanup some log messages and line types.
Updated DSM FWD prog documentation

* #751 more cosmetic things

1. Added AR10360T,
2. Simplify way to configured the hack for more receivers.
3. Change some texts on menus to march spektrum
4. Background color in Spektrum theme to match

* #751 A few final changes

1. Update channel names to include channel number. i.e: Ch5 (Gear)
2,  Fix flight mode display for Heli Receiver
3. i think the unknown lines are to request info about the TX settings

* #751

1. Added Warning Screen
2. Correct handling of Unknown lines in Gyro Settings->Initial Setup

* #751

New v0.51 version.
- Added new menus to configure Model/Wing type.  Without it, the initial setup will not work properly.

* #751 More fixes on mixers and servo reverse

-- Fix problem reversing servos when using vtail/delta mix
-- Properly detect ch order of multimodule

Co-authored-by: pascallanger <pascal_langer@yahoo.fr>
2022-12-20 10:12:34 +01:00
Frankie Arzu
186730231e Fwrd Programming New Model/Wingtype Setup Menus (#784)
* #751 DSM Enhancements

 #751 DSM Forward Programming Enhancements (New GUI, etc)

* Make both work on EdgeTx and OpenTX

* #751 Turn OFF simulation by default

Distribution code with RX simulation OFF
Simulation should be only for Development

* #751 Update Readme Documentation

Updated the Readme.txt documentation
and removed compiled luac file that was check in by mistake

* #751 Fix problems With Reset RX

1. Fix problem when trying to Factory Reset. Enter Bind Mode. Save backup, Restore Backup

2. Found a way to advance on the Gyro initial Setup menus.. a bit of a hack, but works.

3. Handle RX resets properly. It needed after initial setup

* #751 Cosmetic and Show Orientation Images

#751
1. Fix problems when text contradictions between Menu/Line Headers and List Values
2. Show Images of RX orientations
3. Able to Hack getting into Initial Setup and other menus who was failing before
4. Custumize the way Flight Mode reports the Value on Screen

* #751 add check for required libraries

Add check that the required files in DSMLIB exist

* #751

Write documentation about the protocol so that we don't forget later what we know, and enable others to understand the logs and maybe help solve problems.

* #766

Change the way to detect that the files exist. now works on both ETX and OTX

* #766 Strange Flickering in OTX

Strange Flickering happening on OTX. Refreshing the screen on every cycle fixed the problem

* #766 Change way of dectecting EdgeTX

Change way of detecting OTX in multiple versions: OTX 2.3.14 and 2.3.15

* #766  make editable Gain Values

Gains and other settings should be editable even when they are VALUE_NOCHANGING. Flight Mode is an exception that is handled properly. Right align numbers.

* #766 More enhacements

Added AR630
Make numbers right justified
Cleanup some log messages and line types.
Updated DSM FWD prog documentation

* #751 more cosmetic things

1. Added AR10360T,
2. Simplify way to configured the hack for more receivers.
3. Change some texts on menus to march spektrum
4. Background color in Spektrum theme to match

* #751 A few final changes

1. Update channel names to include channel number. i.e: Ch5 (Gear)
2,  Fix flight mode display for Heli Receiver
3. i think the unknown lines are to request info about the TX settings

* #751

1. Added Warning Screen
2. Correct handling of Unknown lines in Gyro Settings->Initial Setup

* #751

New v0.51 version.
- Added new menus to configure Model/Wing type.  Without it, the initial setup will not work properly.

Co-authored-by: pascallanger <pascal_langer@yahoo.fr>
2022-12-18 19:45:50 +01:00
pascallanger
770a12ffdf EU 2022-12-08 08:28:45 +01:00
pascallanger
40fa242012 Update Protocols_Details.md 2022-12-06 15:53:42 +01:00
Frankie Arzu
c4e70ab4fd Frankie dsm fwrd prg enhancements (#776)
* #751 DSM Enhancements

 #751 DSM Forward Programming Enhancements (New GUI, etc)

* Make both work on EdgeTx and OpenTX

* #751 Turn OFF simulation by default

Distribution code with RX simulation OFF
Simulation should be only for Development

* #751 Update Readme Documentation

Updated the Readme.txt documentation
and removed compiled luac file that was check in by mistake

* #751 Fix problems With Reset RX

1. Fix problem when trying to Factory Reset. Enter Bind Mode. Save backup, Restore Backup

2. Found a way to advance on the Gyro initial Setup menus.. a bit of a hack, but works.

3. Handle RX resets properly. It needed after initial setup

* #751 Cosmetic and Show Orientation Images

#751
1. Fix problems when text contradictions between Menu/Line Headers and List Values
2. Show Images of RX orientations
3. Able to Hack getting into Initial Setup and other menus who was failing before
4. Custumize the way Flight Mode reports the Value on Screen

* #751 add check for required libraries

Add check that the required files in DSMLIB exist

* #751

Write documentation about the protocol so that we don't forget later what we know, and enable others to understand the logs and maybe help solve problems.

* #766

Change the way to detect that the files exist. now works on both ETX and OTX

* #766 Strange Flickering in OTX

Strange Flickering happening on OTX. Refreshing the screen on every cycle fixed the problem

* #766 Change way of dectecting EdgeTX

Change way of detecting OTX in multiple versions: OTX 2.3.14 and 2.3.15

* #766  make editable Gain Values

Gains and other settings should be editable even when they are VALUE_NOCHANGING. Flight Mode is an exception that is handled properly. Right align numbers.

* #766 More enhacements

Added AR630
Make numbers right justified
Cleanup some log messages and line types.
Updated DSM FWD prog documentation

* #751 more cosmetic things

1. Added AR10360T,
2. Simplify way to configured the hack for more receivers.
3. Change some texts on menus to march spektrum
4. Background color in Spektrum theme to match

* #751 A few final changes

1. Update channel names to include channel number. i.e: Ch5 (Gear)
2,  Fix flight mode display for Heli Receiver
3. i think the unknown lines are to request info about the TX settings

* #751

1. Added Warning Screen
2. Correct handling of Unknown lines in Gyro Settings->Initial Setup

Co-authored-by: pascallanger <pascal_langer@yahoo.fr>
2022-12-02 08:53:13 +01:00
Frankie Arzu
2da8b3c42a Frankie dsm fwrd prg enhancements (#773)
* #751 DSM Enhancements

 #751 DSM Forward Programming Enhancements (New GUI, etc)

* Make both work on EdgeTx and OpenTX

* #751 Turn OFF simulation by default

Distribution code with RX simulation OFF
Simulation should be only for Development

* #751 Update Readme Documentation

Updated the Readme.txt documentation
and removed compiled luac file that was check in by mistake

* #751 Fix problems With Reset RX

1. Fix problem when trying to Factory Reset. Enter Bind Mode. Save backup, Restore Backup

2. Found a way to advance on the Gyro initial Setup menus.. a bit of a hack, but works.

3. Handle RX resets properly. It needed after initial setup

* #751 Cosmetic and Show Orientation Images

#751
1. Fix problems when text contradictions between Menu/Line Headers and List Values
2. Show Images of RX orientations
3. Able to Hack getting into Initial Setup and other menus who was failing before
4. Custumize the way Flight Mode reports the Value on Screen

* #751 add check for required libraries

Add check that the required files in DSMLIB exist

* #751

Write documentation about the protocol so that we don't forget later what we know, and enable others to understand the logs and maybe help solve problems.

* #766

Change the way to detect that the files exist. now works on both ETX and OTX

* #766 Strange Flickering in OTX

Strange Flickering happening on OTX. Refreshing the screen on every cycle fixed the problem

* #766 Change way of dectecting EdgeTX

Change way of detecting OTX in multiple versions: OTX 2.3.14 and 2.3.15

* #766  make editable Gain Values

Gains and other settings should be editable even when they are VALUE_NOCHANGING. Flight Mode is an exception that is handled properly. Right align numbers.

* #766 More enhacements

Added AR630
Make numbers right justified
Cleanup some log messages and line types.
Updated DSM FWD prog documentation

* #751 more cosmetic things

1. Added AR10360T,
2. Simplify way to configured the hack for more receivers.
3. Change some texts on menus to march spektrum
4. Background color in Spektrum theme to match

* #751 A few final changes

1. Update channel names to include channel number. i.e: Ch5 (Gear)
2,  Fix flight mode display for Heli Receiver
3. i think the unknown lines are to request info about the TX settings

Co-authored-by: pascallanger <pascal_langer@yahoo.fr>
2022-12-01 08:57:33 +01:00
Frankie Arzu
38a79c816a Frankie dsm fwrd prg enhancements (#772)
* #751 DSM Enhancements

 #751 DSM Forward Programming Enhancements (New GUI, etc)

* Make both work on EdgeTx and OpenTX

* #751 Turn OFF simulation by default

Distribution code with RX simulation OFF
Simulation should be only for Development

* #751 Update Readme Documentation

Updated the Readme.txt documentation
and removed compiled luac file that was check in by mistake

* #751 Fix problems With Reset RX

1. Fix problem when trying to Factory Reset. Enter Bind Mode. Save backup, Restore Backup

2. Found a way to advance on the Gyro initial Setup menus.. a bit of a hack, but works.

3. Handle RX resets properly. It needed after initial setup

* #751 Cosmetic and Show Orientation Images

#751
1. Fix problems when text contradictions between Menu/Line Headers and List Values
2. Show Images of RX orientations
3. Able to Hack getting into Initial Setup and other menus who was failing before
4. Custumize the way Flight Mode reports the Value on Screen

* #751 add check for required libraries

Add check that the required files in DSMLIB exist

* #751

Write documentation about the protocol so that we don't forget later what we know, and enable others to understand the logs and maybe help solve problems.

* #766

Change the way to detect that the files exist. now works on both ETX and OTX

* #766 Strange Flickering in OTX

Strange Flickering happening on OTX. Refreshing the screen on every cycle fixed the problem

* #766 Change way of dectecting EdgeTX

Change way of detecting OTX in multiple versions: OTX 2.3.14 and 2.3.15

* #766  make editable Gain Values

Gains and other settings should be editable even when they are VALUE_NOCHANGING. Flight Mode is an exception that is handled properly. Right align numbers.

* #766 More enhacements

Added AR630
Make numbers right justified
Cleanup some log messages and line types.
Updated DSM FWD prog documentation

* #751 more cosmetic things

1. Added AR10360T,
2. Simplify way to configured the hack for more receivers.
3. Change some texts on menus to march spektrum
4. Background color in Spektrum theme to match

Co-authored-by: pascallanger <pascal_langer@yahoo.fr>
2022-11-29 23:23:10 +01:00
Frankie Arzu
1d8f1a0857 Frankie dsm fwrd prg enhancements (#771)
* #751 DSM Enhancements

 #751 DSM Forward Programming Enhancements (New GUI, etc)

* Make both work on EdgeTx and OpenTX

* #751 Turn OFF simulation by default

Distribution code with RX simulation OFF
Simulation should be only for Development

* #751 Update Readme Documentation

Updated the Readme.txt documentation
and removed compiled luac file that was check in by mistake

* #751 Fix problems With Reset RX

1. Fix problem when trying to Factory Reset. Enter Bind Mode. Save backup, Restore Backup

2. Found a way to advance on the Gyro initial Setup menus.. a bit of a hack, but works.

3. Handle RX resets properly. It needed after initial setup

* #751 Cosmetic and Show Orientation Images

#751
1. Fix problems when text contradictions between Menu/Line Headers and List Values
2. Show Images of RX orientations
3. Able to Hack getting into Initial Setup and other menus who was failing before
4. Custumize the way Flight Mode reports the Value on Screen

* #751 add check for required libraries

Add check that the required files in DSMLIB exist

* #751

Write documentation about the protocol so that we don't forget later what we know, and enable others to understand the logs and maybe help solve problems.

* #766

Change the way to detect that the files exist. now works on both ETX and OTX

* #766 Strange Flickering in OTX

Strange Flickering happening on OTX. Refreshing the screen on every cycle fixed the problem

* #766 Change way of dectecting EdgeTX

Change way of detecting OTX in multiple versions: OTX 2.3.14 and 2.3.15

* #766  make editable Gain Values

Gains and other settings should be editable even when they are VALUE_NOCHANGING. Flight Mode is an exception that is handled properly. Right align numbers.

* #766 More enhacements

Added AR630
Make numbers right justified
Cleanup some log messages and line types.
Updated DSM FWD prog documentation

Co-authored-by: pascallanger <pascal_langer@yahoo.fr>
2022-11-29 07:46:40 +01:00
Frankie Arzu
5901bac374 #766 Fix for editable Gains + Number formatting (#770)
* #751 DSM Enhancements

 #751 DSM Forward Programming Enhancements (New GUI, etc)

* Make both work on EdgeTx and OpenTX

* #751 Turn OFF simulation by default

Distribution code with RX simulation OFF
Simulation should be only for Development

* #751 Update Readme Documentation

Updated the Readme.txt documentation
and removed compiled luac file that was check in by mistake

* #751 Fix problems With Reset RX

1. Fix problem when trying to Factory Reset. Enter Bind Mode. Save backup, Restore Backup

2. Found a way to advance on the Gyro initial Setup menus.. a bit of a hack, but works.

3. Handle RX resets properly. It needed after initial setup

* #751 Cosmetic and Show Orientation Images

#751
1. Fix problems when text contradictions between Menu/Line Headers and List Values
2. Show Images of RX orientations
3. Able to Hack getting into Initial Setup and other menus who was failing before
4. Custumize the way Flight Mode reports the Value on Screen

* #751 add check for required libraries

Add check that the required files in DSMLIB exist

* #751

Write documentation about the protocol so that we don't forget later what we know, and enable others to understand the logs and maybe help solve problems.

* #766

Change the way to detect that the files exist. now works on both ETX and OTX

* #766 Strange Flickering in OTX

Strange Flickering happening on OTX. Refreshing the screen on every cycle fixed the problem

* #766 Change way of dectecting EdgeTX

Change way of detecting OTX in multiple versions: OTX 2.3.14 and 2.3.15

* #766  make editable Gain Values

Gains and other settings should be editable even when they are VALUE_NOCHANGING. Flight Mode is an exception that is handled properly. Right align numbers.

Co-authored-by: pascallanger <pascal_langer@yahoo.fr>
2022-11-28 20:00:16 +01:00
Frankie Arzu
2e7b1dc904 #766 change validation of required files (#768)
* #751 DSM Enhancements

 #751 DSM Forward Programming Enhancements (New GUI, etc)

* Make both work on EdgeTx and OpenTX

* #751 Turn OFF simulation by default

Distribution code with RX simulation OFF
Simulation should be only for Development

* #751 Update Readme Documentation

Updated the Readme.txt documentation
and removed compiled luac file that was check in by mistake

* #751 Fix problems With Reset RX

1. Fix problem when trying to Factory Reset. Enter Bind Mode. Save backup, Restore Backup

2. Found a way to advance on the Gyro initial Setup menus.. a bit of a hack, but works.

3. Handle RX resets properly. It needed after initial setup

* #751 Cosmetic and Show Orientation Images

#751
1. Fix problems when text contradictions between Menu/Line Headers and List Values
2. Show Images of RX orientations
3. Able to Hack getting into Initial Setup and other menus who was failing before
4. Custumize the way Flight Mode reports the Value on Screen

* #751 add check for required libraries

Add check that the required files in DSMLIB exist

* #751

Write documentation about the protocol so that we don't forget later what we know, and enable others to understand the logs and maybe help solve problems.

* #766

Change the way to detect that the files exist. now works on both ETX and OTX

* #766 Strange Flickering in OTX

Strange Flickering happening on OTX. Refreshing the screen on every cycle fixed the problem

* #766 Change way of dectecting EdgeTX

Change way of detecting OTX in multiple versions: OTX 2.3.14 and 2.3.15

Co-authored-by: pascallanger <pascal_langer@yahoo.fr>
2022-11-27 15:10:02 +01:00
Frankie Arzu
7052751261 Frankie dsm fwrd prg enhancements (#763)
* #751 DSM Enhancements

 #751 DSM Forward Programming Enhancements (New GUI, etc)

* Make both work on EdgeTx and OpenTX

* #751 Turn OFF simulation by default

Distribution code with RX simulation OFF
Simulation should be only for Development

* #751 Update Readme Documentation

Updated the Readme.txt documentation
and removed compiled luac file that was check in by mistake

* #751 Fix problems With Reset RX

1. Fix problem when trying to Factory Reset. Enter Bind Mode. Save backup, Restore Backup

2. Found a way to advance on the Gyro initial Setup menus.. a bit of a hack, but works.

3. Handle RX resets properly. It needed after initial setup

* #751 Cosmetic and Show Orientation Images

#751
1. Fix problems when text contradictions between Menu/Line Headers and List Values
2. Show Images of RX orientations
3. Able to Hack getting into Initial Setup and other menus who was failing before
4. Custumize the way Flight Mode reports the Value on Screen

* #751 add check for required libraries

Add check that the required files in DSMLIB exist

* #751

Write documentation about the protocol so that we don't forget later what we know, and enable others to understand the logs and maybe help solve problems.

Co-authored-by: pascallanger <pascal_langer@yahoo.fr>
2022-11-21 09:52:15 +01:00
Frankie Arzu
60047e2c73 Frankie dsm fwrd prg enhancements (#762)
* #751 DSM Enhancements

 #751 DSM Forward Programming Enhancements (New GUI, etc)

* Make both work on EdgeTx and OpenTX

* #751 Turn OFF simulation by default

Distribution code with RX simulation OFF
Simulation should be only for Development

* #751 Update Readme Documentation

Updated the Readme.txt documentation
and removed compiled luac file that was check in by mistake

* #751 Fix problems With Reset RX

1. Fix problem when trying to Factory Reset. Enter Bind Mode. Save backup, Restore Backup

2. Found a way to advance on the Gyro initial Setup menus.. a bit of a hack, but works.

3. Handle RX resets properly. It needed after initial setup

* #751 Cosmetic and Show Orientation Images

#751
1. Fix problems when text contradictions between Menu/Line Headers and List Values
2. Show Images of RX orientations
3. Able to Hack getting into Initial Setup and other menus who was failing before
4. Custumize the way Flight Mode reports the Value on Screen

* #751 add check for required libraries

Add check that the required files in DSMLIB exist

Co-authored-by: pascallanger <pascal_langer@yahoo.fr>
2022-11-20 18:24:47 +01:00
Frankie Arzu
40b393ac4a Frankie DSM fwrd Prog (more improvements) (#760)
* #751 DSM Enhancements

 #751 DSM Forward Programming Enhancements (New GUI, etc)

* Make both work on EdgeTx and OpenTX

* #751 Turn OFF simulation by default

Distribution code with RX simulation OFF
Simulation should be only for Development

* #751 Update Readme Documentation

Updated the Readme.txt documentation
and removed compiled luac file that was check in by mistake

* #751 Fix problems With Reset RX

1. Fix problem when trying to Factory Reset. Enter Bind Mode. Save backup, Restore Backup

2. Found a way to advance on the Gyro initial Setup menus.. a bit of a hack, but works.

3. Handle RX resets properly. It needed after initial setup

* #751 Cosmetic and Show Orientation Images

#751
1. Fix problems when text contradictions between Menu/Line Headers and List Values
2. Show Images of RX orientations
3. Able to Hack getting into Initial Setup and other menus who was failing before
4. Custumize the way Flight Mode reports the Value on Screen

Co-authored-by: pascallanger <pascal_langer@yahoo.fr>
2022-11-20 18:01:16 +01:00
Frankie Arzu
1c6dc01959 Frankie dsm fwrd prg enhancements (#757)
* #751 DSM Enhancements

 #751 DSM Forward Programming Enhancements (New GUI, etc)

* Make both work on EdgeTx and OpenTX

* #751 Turn OFF simulation by default

Distribution code with RX simulation OFF
Simulation should be only for Development

* #751 Update Readme Documentation

Updated the Readme.txt documentation
and removed compiled luac file that was check in by mistake

* #751 Fix problems With Reset RX

1. Fix problem when trying to Factory Reset. Enter Bind Mode. Save backup, Restore Backup

2. Found a way to advance on the Gyro initial Setup menus.. a bit of a hack, but works.

3. Handle RX resets properly. It needed after initial setup

Co-authored-by: pascallanger <pascal_langer@yahoo.fr>
2022-11-18 10:41:59 +01:00
pascallanger
5148449066 FS2A: Turning on/off the LNA during bind. 2022-11-17 20:08:56 +01:00
Frankie Arzu
fcc4d19430 Frankie dsm fwrd prg enhancements (#755)
* #751 DSM Enhancements

 #751 DSM Forward Programming Enhancements (New GUI, etc)

* Make both work on EdgeTx and OpenTX

* #751 Turn OFF simulation by default

Distribution code with RX simulation OFF
Simulation should be only for Development

* #751 Update Readme Documentation

Updated the Readme.txt documentation
and removed compiled luac file that was check in by mistake

Co-authored-by: pascallanger <pascal_langer@yahoo.fr>
2022-11-17 17:50:36 +01:00
richardclli
c80f705fa2 Added MPM for Flysky PL18 PCB and casing design. (#754) 2022-11-17 11:37:11 +01:00
pascallanger
c95db35b41 Update Protocols_Details.md 2022-11-17 10:58:38 +01:00
pascallanger
35f3548992 Compilation option 2022-11-17 10:29:53 +01:00
pascallanger
58f6716035 Update README.md 2022-11-17 09:49:30 +01:00
pascallanger
2b15de0f90 Update README.md 2022-11-17 09:47:22 +01:00
pascallanger
be91409df9 Delete DSM FwdPrg.lua 2022-11-17 09:44:18 +01:00
Frankie Arzu
4d8e440965 Frankie dsm fwrd prg enhancements (#753)
DSM Forward Programming Enhancements (New GUI for Color+Touch and BW, etc). Work on EdgeTx and OpenTX.
2022-11-17 09:42:04 +01:00
pascallanger
2d469d074e Merge branch 'master' of https://github.com/pascallanger/DIY-Multiprotocol-TX-Module 2022-10-30 11:40:11 +01:00
pascallanger
96405d27b5 Extend Kyosho KT-17 bind time 2022-10-30 11:40:07 +01:00
yakulis
75c9fb40a7 Update DSM FwdPrg.lua (#735)
Panic Text Updates - The following strings were updated:
Text[0x00D2]="Panic Channel"
Text[0x008E]="Panic Delay"
Text[0x01FC]="Panic Flight Mode"
2022-10-12 11:35:09 +02:00
Pieter du Preez
cd1c15a45a Added documentation for using dfu-util for flashing STM32 targets. (#727)
This patch adds documentation, explaining how to flash firmware to DFU
capable multimodules.

A dfu-util command was taken and adapted from:
https://github.com/benlye/flash-multi/blob/master/doc/Troubleshooting.md

Using dfu-util is straight forward, easy and very safe.
2022-10-12 11:34:32 +02:00
pascallanger
2bd50f4c8c V761/TOPRC: new sub protocol
Top RC Hobby mini planes
2022-09-26 12:02:38 +02:00
yakulis
4c2ddcbe48 Update DSM FwdPrg.lua (#733)
Reversing 'Off' and 'On' text values in lines #555 and #556.  They are used in the SAFE and AS3X menu items in the DSM Forward Programming section, and they are functioning backwards. This will correct the issue. This is the fix for Issue #728
2022-09-11 06:01:02 -04:00
Ben Lye
d7f9ef6967 Use devel boards in CI workflow (#709) 2022-07-21 10:20:16 +02:00
pascallanger
bfc8c2f9fd Kyosho2/KT-17: only 1 ID 2022-07-20 17:20:27 +02:00
pascallanger
ce6243d6e3 FX/620: IDs 2022-07-17 09:07:28 +02:00
pascallanger
80f9ff4163 Update FX_nrf24l01.ino 2022-07-15 15:44:10 +02:00
pascallanger
d9f8a3989a FX/FX620: only 1 ID 2022-07-15 15:43:04 +02:00
pascallanger
416f7d5c19 FX/FX620 another try 2022-07-12 08:05:41 +02:00
pascallanger
eb24dd5549 FX/FX620
I messed up the hopping, I must have looked at the wrong file.
2022-07-11 11:12:20 +02:00
pascallanger
ba19592973 FX/FX620 debug off 2022-07-11 09:11:11 +02:00
pascallanger
98d8d7fb5f FX/FX620 new protocol 2022-07-11 09:03:31 +02:00
pascallanger
ad0947b0b7 Updated MT99xx/PA18: need someone to test... 2022-07-09 00:43:28 +02:00
89 changed files with 111578 additions and 1059 deletions

View File

@@ -55,10 +55,12 @@ jobs:
BOARD: ${{ matrix.board }}
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- name: Install Arduino CLI
uses: arduino/setup-arduino-cli@v1.1.1
uses: arduino/setup-arduino-cli@v1.1.2
with:
version: "0.32.2"
- name: Prepare build environment
run: |
@@ -67,15 +69,22 @@ jobs:
echo "Event action: ${{ github.event.action }}"
echo "Tag name: ${{ github.event.release.tag_name }}"
arduino-cli config init --additional-urls https://raw.githubusercontent.com/pascallanger/DIY-Multiprotocol-TX-Module-Boards/master/package_multi_4in1_board_index.json
arduino-cli config init --additional-urls https://raw.githubusercontent.com/pascallanger/DIY-Multiprotocol-TX-Module-Boards/master/package_multi_4in1_board_index.json,https://raw.githubusercontent.com/pascallanger/DIY-Multiprotocol-TX-Module-Boards/devel/source/package_multi_4in1_board_devel_index.json
arduino-cli core update-index
if [[ "$BOARD" =~ "multi4in1:avr:" ]]; then
if [[ "$BOARD" =~ ":avr:" ]]; then
arduino-cli core install arduino:avr;
fi
if [[ "$BOARD" =~ "multi4in1-devel:avr" ]]; then
arduino-cli core install multi4in1-devel:avr
elif [[ "$BOARD" =~ "multi4in1:avr" ]]; then
arduino-cli core install multi4in1:avr
fi
if [[ "$BOARD" =~ "multi4in1:STM32F1:" ]]; then
if [[ "$BOARD" =~ "multi4in1-devel:STM32F1:" ]]; then
arduino-cli core install multi4in1-devel:STM32F1
elif [[ "$BOARD" =~ "multi4in1:STM32F1:" ]]; then
arduino-cli core install multi4in1:STM32F1
fi
@@ -109,18 +118,18 @@ jobs:
echo "ALL_RFMODULES=$(echo $ALL_RFMODULES)" >> $GITHUB_ENV
# Disable CHECK_FOR_BOOTLOADER when not needed
if [[ "$BOARD" == "multi4in1:avr:multiatmega328p:bootloader=none" ]]; then
if [[ "$BOARD" =~ ":avr:multiatmega328p:bootloader=none" ]]; then
opt_disable CHECK_FOR_BOOTLOADER;
fi
# Trim the build down for the Atmega328p board
if [[ "$BOARD" =~ "multi4in1:avr:multiatmega328p:" ]]; then
if [[ "$BOARD" =~ ":avr:multiatmega328p:" ]]; then
opt_disable $ALL_PROTOCOLS
opt_enable FRSKYX_CC2500_INO AFHDS2A_A7105_INO MJXQ_NRF24L01_INO DSM_CYRF6936_INO;
fi
# Trim the enabled protocols down for the STM32F103CB board with debugging or the STM32F103C8 board in general
if [[ "$BOARD" == "multi4in1:STM32F1:multistm32f103cb:debug_option=ftdi" ]] || [[ "$BOARD" == "multi4in1:STM32F1:multistm32f103cb:debug_option=native" ]] || [[ "$BOARD" =~ "multi4in1:STM32F1:multistm32f103c8" ]]; then
if [[ "$BOARD" =~ ":STM32F1:multistm32f103cb:debug_option=ftdi" ]] || [[ "$BOARD" =~ ":STM32F1:multistm32f103cb:debug_option=native" ]] || [[ "$BOARD" =~ ":STM32F1:multistm32f103c8" ]]; then
opt_disable $ALL_PROTOCOLS;
opt_enable FRSKYX_CC2500_INO AFHDS2A_A7105_INO MJXQ_NRF24L01_INO DSM_CYRF6936_INO;
fi
@@ -133,7 +142,7 @@ jobs:
- name: Build default configuration
run: |
# Skip the default build for boards where it's too large now
if [[ "$BOARD" == "multi4in1:STM32F1:multistm32f103cb:debug_option=none" ]] || [[ "$BOARD" == "multi4in1:STM32F1:multi5in1t18int" ]]; then
if [[ "$BOARD" =~ ":STM32F1:multistm32f103cb:debug_option=none" ]] || [[ "$BOARD" =~ ":STM32F1:multi5in1t18int" ]]; then
printf "Not testing default build for $BOARD.";
else
source ./buildroot/bin/buildFunctions;
@@ -189,7 +198,7 @@ jobs:
- name: 'Upload Artifacts'
if: env.HAVE_FILES == 'true'
uses: actions/upload-artifact@v2
uses: actions/upload-artifact@v3
with:
name: multi-test-build
path: ./binaries/

View File

@@ -1,768 +0,0 @@
local toolName = "TNS|DSM Forward Programming v0.2|TNE"
---- #########################################################################
---- # #
---- # Copyright (C) OpenTX #
-----# #
---- # License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html #
---- # #
---- # This program is free software; you can redistribute it and/or modify #
---- # it under the terms of the GNU General Public License version 2 as #
---- # published by the Free Software Foundation. #
---- # #
---- # This program is distributed in the hope that it will be useful #
---- # but WITHOUT ANY WARRANTY; without even the implied warranty of #
---- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
---- # GNU General Public License for more details. #
---- # #
---- #########################################################################
--###############################################################################
-- Multi buffer for DSM description
-- Multi_Buffer[0..2]=="DSM" -> Lua script is running
-- Multi_Buffer[3]==0x70+len -> TX to RX data ready to be sent
-- Multi_Buffer[4..9]=6 bytes of TX to RX data
-- Multi_Buffer[10..25]=16 bytes of RX to TX data
--
-- To start operation:
-- Write 0x00 at address 3
-- Write 0x00 at address 10
-- Write "DSM" at address 0..2
--###############################################################################
local RX_VERSION, WAIT_CMD, MENU_TITLE, MENU_LINES, MENU_VALUES, VALUE_CHANGING, VALUE_CHANGING_WAIT, VALUE_CHANGED, EXIT, EXIT_DONE = 0, 1, 2, 3, 4, 5, 6, 7, 8, 9
local MENU, LIST_MENU_NOCHANGING, LIST_MENU1, LIST_MENU2, VALUE_NOCHANGING = 0x1C, 0x6C, 0x0C, 0x4C, 0x60
local Phase = RX_VERSION
local Waiting_RX = 0
local Text = {}
local RxName = {}
local Retry=100
local Blink = 0
local Value_Changed=0
local Menu = { Cur=nil, Id=nil, Title="", Prev=nil, PrevId=nil, Next=nil, NextId=nil, Back=nil, BackId=nil, CurLine=nil, SelLine=nil, EditLine=nil }
local Line = {}
local RX = { Name="", Version="" }
-- used for debug
local rxAnswer = ""
local debugLine = 0
------------------------------------------------------------------------------------------------------------
local function GetDebugInfo(lineNr) -- used for debug
local i
debugLine = lineNr
rxAnswer = "RX:"
for i=10, 25 do
rxAnswer = rxAnswer.." "..string.format("%02X", multiBuffer(i))
end
end
------------------------------------------------------------------------------------------------------------
local function conv_int16(number)
if number >= 0x8000 then
return number - 0x10000
end
return number
end
------------------------------------------------------------------------------------------------------------
local function Get_Text(index)
out = Text[index]
if out == nil then -- unknown...
out = "Unknown_"..string.format("%X",index)
end
return out
end
------------------------------------------------------------------------------------------------------------
local function Get_RxName(index)
out = RxName[index]
if out == nil then -- unknown...
out = "Unknown_"..string.format("%X",index)
end
return out
end
------------------------------------------------------------------------------------------------------------
local function DSM_Release()
multiBuffer( 0, 0 )
Phase = EXIT_DONE
end
------------------------------------------------------------------------------------------------------------
local function DSM_Send(...)
local arg = {...}
for i = 1 , #arg do
multiBuffer( 3+i, arg[i])
end
multiBuffer( 3, 0x70+#arg)
end
------------------------------------------------------------------------------------------------------------
local function Value_Add(dir)
local line=Line[Menu.SelLine]
Speed = getRotEncSpeed()
if Speed == ROTENC_MIDSPEED then
line.Val = line.Val + (5 * dir)
elseif Speed == ROTENC_HIGHSPEED then
line.Val = line.Val + (15 * dir)
else
line.Val = line.Val + dir
end
if line.Val > line.Max then
line.Val = line.Max
elseif line.Val < line.Min then
line.Val = line.Min
end
if Line[Menu.SelLine].Type ~= LIST_MENU_NOCHANGING then
Phase = VALUE_CHANGING
Waiting_RX = 0
end
end
------------------------------------------------------------------------------------------------------------
local function DSM_Menu(event)
local Speed = 0
if event == EVT_VIRTUAL_EXIT then
if Phase == RX_VERSION then
DSM_Release()
else
Phase = EXIT
Waiting_RX = 0
end
elseif event == EVT_VIRTUAL_NEXT then
if Menu.EditLine == nil then
-- not changing a value
if Menu.SelLine ~= nil then
if Menu.SelLine < 7 then
local num = Menu.SelLine
for i = Menu.SelLine + 1, 6, 1 do
if Line[i].Type ~= nil and Line[i].Next ~= nil and Line[i].Type ~= VALUE_NOCHANGING then
Menu.SelLine=i
break
end
end
if num == Menu.SelLine then
if Menu.Next ~= 0 then -- Next
Menu.SelLine = 7
elseif Menu.Prev ~= 0 then -- Prev
Menu.SelLine = 8
end
end
elseif Menu.Prev ~= 0 then -- Prev
Menu.SelLine = 8
end
end
else -- need to inc the value
Value_Add(1)
end
elseif event == EVT_VIRTUAL_PREV then
if Menu.EditLine == nil then
if Menu.SelLine ~= nil then
if Menu.SelLine == 8 and Menu.Next ~= 0 then
Menu.SelLine = 7
elseif Menu.SelLine > 0 then
if Menu.SelLine > 6 then
Menu.SelLine = 7
end
local num = Menu.SelLine
for i = Menu.SelLine-1, 0, -1 do
if Line[i].Type ~= nil and Line[i].Next ~= nil and Line[i].Type ~= VALUE_NOCHANGING then
Menu.SelLine=i
break
end
end
if num == Menu.SelLine then -- Back
Menu.SelLine = -1
end
else
Menu.SelLine = -1 -- Back
end
end
else -- need to dec the value
Value_Add(-1)
end
elseif event == EVT_VIRTUAL_ENTER_LONG then
if Menu.EditLine ~= nil then
-- reset the value to default
if Line[Menu.SelLine].Type ~= LIST_MENU_NOCHANGING then
Line[Menu.SelLine].Val = Line[Menu.SelLine].Def
Phase = VALUE_CHANGING
Waiting_RX = 0
end
end
elseif event == EVT_VIRTUAL_ENTER then
if Menu.SelLine == -1 then -- Back
Menu.Cur = Menu.Back
Menu.Id = Menu.BackId
Menu.SelLine = 0
Phase = MENU_TITLE
Waiting_RX = 0
elseif Menu.SelLine == 7 then -- Next
Menu.Cur = Menu.Next
Menu.Id = Menu.NextId
Menu.SelLine = 0
Phase = MENU_TITLE
Waiting_RX = 0
elseif Menu.SelLine == 8 then -- Prev
Menu.Cur = Menu.Prev
Menu.Id = Menu.PrevId
Menu.SelLine = 0
Phase = MENU_TITLE
Waiting_RX = 0
elseif Menu.SelLine ~= nil and Line[Menu.SelLine].Next ~= nil then
if Line[Menu.SelLine].Type == MENU then -- Next menu exist
Menu.Cur = Line[Menu.SelLine].Next
Menu.Id = Line[Menu.SelLine].NextId
Phase = MENU_TITLE
Waiting_RX = 0
else
-- value entry
if Menu.EditLine == Menu.SelLine then
Menu.EditLine = nil
Value_Changed = 0
Phase = VALUE_CHANGED
Waiting_RX = 0
else
Menu.EditLine = Menu.SelLine
end
end
end
end
end
------------------------------------------------------------------------------------------------------------
local function DSM_Send_Receive()
if Waiting_RX == 0 then
Waiting_RX = 1
-- Need to send a request
if Phase == RX_VERSION then -- request RX version
DSM_Send(0x11,0x06,0x00,0x14,0x00,0x00)
elseif Phase == WAIT_CMD then -- keep connection open
DSM_Send(0x00,0x04,0x00,0x00)
elseif Phase == MENU_TITLE then -- request menu title
if Menu.Cur == nil then
DSM_Send(0x12,0x06,0x00,0x14,0x00,0x00) -- first menu only
Menu.Cur = 0
else
DSM_Send(0x16,0x06,Menu.Id,Menu.Cur,0x00,Menu.SelLine)
end
elseif Phase == MENU_LINES then -- request menu lines
if Menu.CurLine == nil then
DSM_Send(0x13,0x04,Menu.Id,Menu.Cur) -- line 0
elseif Menu.CurLine >= 0x80 then
local last_byte={0x40,0x01,0x02,0x04,0x00,0x00} -- unknown...
DSM_Send(0x20,0x06,Menu.CurLine-0x80,Menu.CurLine-0x80,0x00,last_byte[Menu.CurLine-0x80+1]) -- line X
else
DSM_Send(0x14,0x06,Menu.Id,Menu.Cur,0x00,Menu.CurLine) -- line X
end
elseif Phase == MENU_VALUES then -- request menu values
DSM_Send(0x15,0x06,Menu.Id,Menu.Cur,Line[Menu.CurLine].ValId,Line[Menu.CurLine].Next) -- line X
elseif Phase == VALUE_CHANGING then -- send value
local value=Line[Menu.SelLine].Val
if value < 0 then
value = 0x10000 + value
end
DSM_Send(0x18,0x06,Line[Menu.SelLine].ValId,Line[Menu.SelLine].Next,bit32.rshift(value,8),bit32.band(value,0xFF)) -- send current value
Phase = VALUE_CHANGING_WAIT
elseif Phase == VALUE_CHANGED then -- send value
if Value_Changed == 0 then
local value=Line[Menu.SelLine].Val
if value < 0 then
value = 0x10000 + value
end
DSM_Send(0x18,0x06,Line[Menu.SelLine].ValId,Line[Menu.SelLine].Next,bit32.rshift(value,8),bit32.band(value,0xFF)) -- send current value
Value_Changed = Value_Changed + 1
Waiting_RX = 0
elseif Value_Changed == 1 then
DSM_Send(0x19,0x06,Line[Menu.SelLine].ValId,Line[Menu.SelLine].Next) -- validate
-- Value_Changed = Value_Changed + 1
-- Waiting_RX = 0
--elseif Value_Changed == 2 then
-- DSM_Send(0x1B,0x06,0x10,Menu.SelLine) -- validate again?
-- Value_Changed = Value_Changed + 1
end
elseif Phase == VALUE_CHANGING_WAIT then
DSM_Send(0x1A,0x06,Line[Menu.SelLine].ValId,Line[Menu.SelLine].Next)
elseif Phase == EXIT then
DSM_Send(0x1F,0x02,0xAA)
end
multiBuffer(10,0x00);
Retry = 50
-- -- -- -- -- -- -- -- -- -- -- -- receive part -- -- -- -- -- -- -- -- -- -- -- -- --
elseif multiBuffer(10) == 0x09 then
-- Answer received
-- GetDebugInfo(292) -- used for debug
--if multiBuffer(11) == 0x00 then -- waiting for commands?
if multiBuffer(11) == 0x01 then -- read version
--ex: 0x09 0x01 0x00 0x15 0x02 0x22 0x01 0x00 0x14 0x00 0x00 0x00 0x00 0x00 0x00 0x00
RX.Name = Get_RxName(multiBuffer(13))
RX.Version = multiBuffer(14).."."..multiBuffer(15).."."..multiBuffer(16)
Phase = MENU_TITLE
elseif multiBuffer(11) == 0x02 then -- read menu title
--ex: 0x09 0x02 0x4F 0x10 0xA5 0x00 0x00 0x00 0x50 0x10 0x10 0x10 0x00 0x00 0x00 0x00
Menu.Cur = multiBuffer(12)
Menu.Id = multiBuffer(13)
Menu.Title = Get_Text(multiBuffer(14)+multiBuffer(15)*256)
Menu.Prev = multiBuffer(16)
Menu.PrevId = multiBuffer(17)
Menu.Next = multiBuffer(18)
Menu.NextId = multiBuffer(19)
Menu.Back = multiBuffer(20)
Menu.BackId = multiBuffer(21)
for i = 0, 6 do -- clear menu
Line[i] = { Menu = nil, Id = nil, Type = nil, Text="", Next = nil, NextId = nil, ValLine = nil, ValId = nil, Min, Max, Def, Val, Unit, Step }
end
Menu.CurLine = nil
if Menu.Next ~= 0 then
Menu.SelLine = 7 -- highlight Next
else
Menu.SelLine = -1 -- highlight Back
end
Blink = 0
Phase = MENU_LINES
elseif multiBuffer(11) == 0x03 then -- read menu lines
--ex: 0x09 0x03 0x00 0x10 0x00 0x1C 0xF9 0x00 0x10 0x10 0x00 0x00 0x00 0x00 0x03 0x00
-- Menu Id line Type Text_idx Next V_Id Val_Min Val_Max Val_Def
--ex: 0x09 0x03 0x61 0x10 0x00 0x6C 0x50 0x00 0x00 0x10 0x36 0x00 0x49 0x00 0x36 0x00
Menu.CurLine = multiBuffer(14)
local line = Line[Menu.CurLine]
line.Menu = multiBuffer(12)
line.Id = multiBuffer(13) -- not quite sure yet
line.Type = multiBuffer(15) -- not quite sure yet: 1C is text menu only, 4C/6C is text followed by text list, C0 is text followed by percentage value, 0C new list type
line.Text = Get_Text(multiBuffer(16)+multiBuffer(17)*256)
--if multiBuffer(18) == Menu.Cur then
-- line.Next = nil
--else
line.Next = multiBuffer(18) -- not quite sure yet: 1C=text menu=>next menu, others=>identifier of line number of the value
--end
if Menu.SelLine == -1 and line.Next ~= nil then -- Auto select first line of the menu
Menu.SelLine = Menu.CurLine
end
line.NextId = multiBuffer(19) -- not quite sure yet
line.ValLine = multiBuffer(18) -- not quite sure yet
line.ValId = multiBuffer(19) -- not quite sure yet
line.Min = conv_int16(multiBuffer(20)+multiBuffer(21)*256)
line.Max = conv_int16(multiBuffer(22)+multiBuffer(23)*256)
line.Def = conv_int16(multiBuffer(24)+multiBuffer(25)*256)
if line.Type == MENU then
-- nothing to do on menu entries
elseif line.Type == LIST_MENU_NOCHANGING or line.Type == LIST_MENU1 or line.Type == LIST_MENU2 then
line.Val = nil --line.Def - line.Min -- use default value not sure if needed
line.Def = line.Min -- pointer to the start of the list in Text
line.Max = line.Max - line.Min -- max index
line.Min = 0 -- min index
else -- default to numerical value
line.Val = nil --line.Def -- use default value not sure if needed
end
if line.Type ~= MENU and line.Type ~= VALUE_NOCHANGING then -- updatable value to follow
line.Text = line.Text..":"
end
Phase = MENU_LINES
elseif multiBuffer(11) == 0x04 then -- read menu values
--ex: 0x09 0x04 0x53 0x10 0x00 0x10 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
-- Menu MeId line VaId Value
--ex: 0x09 0x04 0x61 0x10 0x02 0x10 0x01 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
-- Identify the line and update the value
for i = 0, 6 do
if Line[i] ~= nil and Line[i].Type ~= nil then
if Line[i].Type ~= MENU and Line[i].Next == multiBuffer(14) then -- identifier of line number stored in .Next
Line[i].Val = conv_int16(multiBuffer(16)+multiBuffer(17)*256)
Menu.CurLine = i
break
end
end
end
Phase = MENU_VALUES
elseif multiBuffer(11) == 0x05 then -- unknown... need to get through the lines...
Menu.CurLine = 0x80 + multiBuffer(12)
Phase = MENU_LINES
elseif multiBuffer(11) == 0xA7 then -- answer to EXIT command
DSM_Release()
elseif multiBuffer(11) == 0x00 and Phase == VALUE_CHANGING then
Phase = VALUE_CHANGING_WAIT
end
-- Data processed
Waiting_RX = 0
multiBuffer(10,0x00)
Retry = 50
else
Retry = Retry - 1
if Retry <= 0 then
-- Retry the RX request
Retry = 50
Waiting_RX = 0
if Phase == EXIT then
DSM_Release()
end
if Phase ~= RX_VERSION and Phase ~= VALUE_CHANGING_WAIT then
Phase = WAIT_CMD
end
end
end
end
------------------------------------------------------------------------------------------------------------
local function DSM_Display()
lcd.clear()
if LCD_W == 480 then
--lcd.drawText(10,55,debugLine.." "..rxAnswer) -- draw debug info
--Draw title
lcd.drawFilledRectangle(0, 0, LCD_W, 30, TITLE_BGCOLOR)
lcd.drawText(1, 5, "DSM Forward Programming", MENU_TITLE_COLOR)
--Draw RX Menu
if Phase == RX_VERSION then
lcd.drawText(10,50,"No compatible DSM RX...", BLINK)
else
if Menu.Title ~= nil then
local attrib=0;
lcd.drawText(80,32,Menu.Title,MIDSIZE)
for i = 0, 6 do
if i == Menu.SelLine then
attrib = INVERS
else
attrib = 0
end
if Line[i] ~= nil and Line[i].Type ~= nil then
if Line[i].Type ~= MENU then -- list/value
if Line[i].Val ~= nil then
local text=""
if Line[i].Type == LIST_MENU_NOCHANGING or Line[i].Type == LIST_MENU1 or Line[i].Type == LIST_MENU2 then
text = Get_Text(Line[i].Val+Line[i].Def)
elseif ( Line[i].Min == 0 and Line[i].Max == 100) or ( Line[i].Min == -100 and Line[i].Max == 100) or ( Line[i].Min == 0 and Line[i].Max == 150) or ( Line[i].Min == -150 and Line[i].Max == 150) then
text = Line[i].Val.." %"
else
--text = Line[i].Val .." T="..Line[i].Type -- used for debug
text = Line[i].Val
end
if Menu.EditLine == Menu.SelLine then -- blink edited entry
Blink = Blink + 1
if Blink > 25 then
attrib = 0
if Blink > 50 then
Blink = 0
end
end
end
lcd.drawText(240,32+20*(i+2), text, attrib) -- display value
end
attrib = 0
end
lcd.drawText(10,32+20*(i+2), Line[i].Text, attrib) -- display text
end
end
if Menu.SelLine == -1 then
lcd.drawText(437,32, "Back", INVERS)
else
lcd.drawText(437,32, "Back", 0)
end
lcd.drawRectangle(437-5, 32-2, 47, 25)
if Menu.Next ~= 0 then
if Menu.SelLine == 7 then
lcd.drawText(437,220, "Next",INVERS)
else
lcd.drawText(437,220, "Next")
end
lcd.drawRectangle(437-5, 220-2, 47, 25)
end
if Menu.Prev ~= 0 then
if Menu.SelLine == 8 then
lcd.drawText(5,220, "Prev",INVERS)
else
lcd.drawText(5,220, "Prev")
end
lcd.drawRectangle(5-5, 220-2, 47, 25)
end
end
lcd.drawText(170,252, "RX "..RX.Name.." v"..RX.Version) -- display RX info
end
else
-- --Draw RX Menu on LCD_W=128
-- if multiBuffer( 4 ) == 0xFF then
-- lcd.drawText(2,17,"No compatible DSM RX...",SMLSIZE)
-- else
-- if Retry_128 ~= 0 then
-- --Intro page
-- Retry_128 = Retry_128 - 1
-- lcd.drawScreenTitle("DSM Forward Programming",0,0)
-- lcd.drawText(2,17,"Press Prev Page for previous Menu" ,SMLSIZE)
-- else
-- --Menu page
-- for line = 0, 7, 1 do
-- for i = 0, 21-1, 1 do
-- value=multiBuffer( line*21+6+i )
-- if value > 0x80 then
-- value = value - 0x80
-- lcd.drawText(2+i*6,1+8*line,string.char(value).." ",SMLSIZE+INVERS)
-- else
-- lcd.drawText(2+i*6,1+8*line,string.char(value),SMLSIZE)
-- end
-- end
-- end
-- end
-- end
end
end
------------------------------------------------------------------------------------------------------------
-- Init
local function DSM_Init()
--Set protocol to talk to
multiBuffer( 0, string.byte('D') )
--test if value has been written
if multiBuffer( 0 ) ~= string.byte('D') then
error("Not enough memory!")
return 2
end
--Init TX buffer
multiBuffer( 3, 0x00 )
--Init RX buffer
multiBuffer( 10, 0x00 )
--Init telemetry
multiBuffer( 0, string.byte('D') )
multiBuffer( 1, string.byte('S') )
multiBuffer( 2, string.byte('M') )
--RX names--
RxName[0x0001]="AR636B"
RxName[0x0014]="SPM4651T"
RxName[0x0015]="AR637T"
RxName[0x0016]="AR637TA"
RxName[0x0018]="FC6250HX"
RxName[0x001A]="AR8360T"
RxName[0x001E]="AR631"
--Text to be displayed -> need to use a file instead?
Text[0x0001]="On"
Text[0x0002]="Off"
Text[0x0003]="Inh"
Text[0x0004]="Act"
Text[0x000C]="Inhibit?" --?
Text[0x000D]="Gear"
--Lists--
Text[0x002E]="11ms"
Text[0x002F]="22ms"
Text[0x0032]="1 X"
Text[0x0033]="2 X"
Text[0x0034]="4 X"
Text[0x0035]="Inhibit?" --?
Text[0x0036]="Throttle"
Text[0x0037]="Aileron"
Text[0x0038]="Elevator"
Text[0x0039]="Rudder"
Text[0x003A]="Gear"
--******
--This part is strange since the AR637T needs
for i=1,7 do -- 3B..41
Text[0x003A+i]="Aux"..i
end
for i=1,8 do -- 41..49
Text[0x0041+i]="XPlus-"..i
end
--But FOTO-PETE reports that it should be:
Text[0x0040]="Roll"
Text[0x0041]="Pitch"
Text[0x0042]="Yaw"
Text[0x0043]="Gain" -- FC6250HX
Text[0x0045]="Differential"
Text[0x0046]="Priority"
Text[0x0049]="Output Setup" -- FC6250HX
--******
Text[0x004A]="Failsafe"
Text[0x004B]="Main Menu"
Text[0x004E]="Position"
Text[0x0050]="Outputs"
Text[0x0051]="Output Channel 1"
Text[0x0052]="Output Channel 2"
Text[0x0053]="Output Channel 3"
Text[0x0054]="Output Channel 4"
Text[0x0055]="Output Channel 5"
Text[0x0056]="Output Channel 6"
--Text[0x005E]="Inhibit"
Text[0x005F]="Hold Last"
Text[0x0060]="Preset"
--Text[0x0061]="Custom"
--Messages--
Text[0x0071]="Proportional"
Text[0x0072]="Integral"
Text[0x0073]="Derivate"
Text[0x0078]="FM Channel"
Text[0x0080]="Orientation"
Text[0x0082]="Heading"
Text[0x0085]="Frame Rate"
Text[0x0086]="System Setup"
Text[0x0087]="F-Mode Setup"
Text[0x0088]="Enabled F-Modes"
Text[0x0089]="Gain Channel"
Text[0x008A]="Gain Sensitivity"
Text[0x008B]="Panic"
Text[0x0090]="Apply"
Text[0x0092]="Start"
Text[0x0093]="Complete"
Text[0x0094]="Done"
Text[0x0097]="Factory Reset"
Text[0x0099]="Advanced Setup"
Text[0x009A]="Capture Failsafe Positions"
Text[0x009C]="Custom Failsafe"
Text[0x00A5]="First Time Setup"
Text[0x00AA]="Capture Gyro Gains"
Text[0x00AD]="Gain Channel Select"
Text[0x00B0]="Self-Level/Angle Dem"
Text[0x00B1]="Envelope"
Text[0x00B5]="Inhibit"
Text[0x00B6]="FM1"
Text[0x00B7]="FM2"
Text[0x00B8]="FM3"
Text[0x00B9]="FM4"
Text[0x00BA]="FM5"
Text[0x00BB]="FM6"
Text[0x00BC]="FM7"
Text[0x00BD]="FM8"
Text[0x00BE]="FM9"
Text[0x00BF]="FM10"
Text[0x00C7]="Calibrate Sensor"
Text[0x00CA]="SAFE/Panic Mode Setup"
Text[0x00D3]="Swashplate"
Text[0x00D5]="Agility"
Text[0x00D8]="Stop"
Text[0x00DA]="SAFE"
Text[0x00DB]="Stability"
Text[0x00DC]="@ per sec"
Text[0x00DD]="Tail rotor"
Text[0x00DE]="Setup"
Text[0x00DF]="AFR"
Text[0x00E0]="Collective"
Text[0x00E1]="Subtrim"
Text[0x00E2]="Phasing"
Text[0x00E4]="E-Ring"
Text[0x00E7]="Left"
Text[0x00E8]="Right"
Text[0x00F2]="Fixed"
Text[0x00F3]="Adjustable"
Text[0x00F9]="Gyro settings"
Text[0x00FE]="Stick Priority"
Text[0x0100]="Make sure the model has been"
Text[0x0101]="configured, including wing type,"
Text[0x0102]="reversing, travel, trimmed, etc."
Text[0x0103]="before continuing setup."
Text[0x0106]="Any wing type, channel assignment,"
Text[0x0107]="subtrim, or servo reversing changes"
Text[0x0108]="require running through initial"
Text[0x0109]="setup again."
Text[0x0190]="Relearn Servo Settings"
Text[0x019C]="Enter Receiver Bind Mode"
Text[0x01D7]="SAFE Select Channel"
Text[0x01DC]="AS3X"
Text[0x01DD]="AS3X Settings"
Text[0x01DE]="AS3X Gains"
Text[0x01E0]="Rate Gains"
Text[0x01E2]="SAFE Settings"
Text[0x01E3]="SAFE Gains"
Text[0x01E6]="Attitude Trim"
Text[0x01E7]="Envelope"
Text[0x01E9]="Roll Right"
Text[0x01EA]="Roll Left"
Text[0x01EB]="Pitch Down"
Text[0x01EC]="Pitch Up"
Text[0x01EE]="Throttle to Pitch"
Text[0x01EF]="Low Thr to Pitch"
Text[0x01F0]="High Thr to Pitch"
Text[0x01F3]="Threshold"
Text[0x01F4]="Angle"
Text[0x01F6]="Failsafe Angles"
Text[0x01F8]="Safe Mode"
Text[0x01F9]="SAFE Select"
Text[0x01FD]="SAFE Failsafe FMode"
Text[0x0208]="Decay"
Text[0x0209]="Save to Backup"
Text[0x020A]="Restore from Backup"
Text[0x020D]="First Time SAFE Setup"
Text[0x021A]="Set the model level,"
Text[0x021B]="and press Continue."
Text[0x021C]="" -- empty??
Text[0x021D]="" -- empty??
Text[0x021F]="Set the model on its nose,"
Text[0x0220]="and press Continue. If the"
Text[0x0221]="orientation on the next"
Text[0x0222]="screen is wrong go back"
Text[0x0223]="and try again."
Text[0x0224]="Continue"
Text[0x0226]="Angle Limits"
Text[0x0227]="Other settings"
Text[0x0229]="Set Orientation Manually"
Text[0x022B]="WARNING!"
Text[0x022C]="This will reset the"
Text[0x022D]="configuration to factory"
Text[0x022E]="defaults. This does not"
Text[0x022F]="affect the backup config."
Text[0x0230]="" -- empty??
Text[0x0231]="This will overwrite the"
Text[0x0232]="backup memory with your"
Text[0x0233]="current configuartion."
Text[0x0234]="" -- blank line
Text[0x0235]="" -- blank line
Text[0x0236]="This will overwrite the"
Text[0x0237]="current config with"
Text[0x0238]="that which is in"
Text[0x0239]="the backup memory."
Text[0x023A]="" -- blank line
Text[0x023D]="Copy Flight Mode Settings"
Text[0x0240]="Utilities"
Text[0x024C]="Gains will be captured on"
Text[0x024D]="Captured gains will be"
Text[0x024E]="Gains on"
Text[0x024F]="were captured and changed"
Text[0x0250]="from Adjustable to Fixed"
Text[0x0254]="Postive = Up, Negative = Down"
Text[0x0263]="Fixed/Adjustable Gains"
Text[0x0266]="Heading Gain"
Text[0x0267]="Positive = Nose Up/Roll Right"
Text[0x0268]="Negative = Nose Down/Roll Left"
Text[0x0269]="SAFE - Throttle to Pitch"
Text[0x026A]="Use CAUTION for Yaw gain!"
Text[0x8000]="FLIGHT MODE"
Text[0x8001]="Flight Mode 1"
Text[0x8002]="Flight Mode 2"
Text[0x8003]="Flight Mode 3"
end
------------------------------------------------------------------------------------------------------------
-- Main
local function DSM_Run(event)
if event == nil then
error("Cannot be run as a model script!")
return 2
else
DSM_Menu(event)
DSM_Send_Receive()
DSM_Display()
end
if Phase == EXIT_DONE then
return 2
else
return 0
end
end
return { init=DSM_Init, run=DSM_Run }

View File

@@ -0,0 +1,549 @@
local toolName = "TNS|DSM Forward Prog v0.54 (Text B&W) |TNE"
local VERSION = "v0.54"
---- #########################################################################
---- # #
---- # Copyright (C) OpenTX #
-----# #
---- # License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html #
---- # #
---- # This program is free software; you can redistribute it and/or modify #
---- # it under the terms of the GNU General Public License version 2 as #
---- # published by the Free Software Foundation. #
---- # #
---- # This program is distributed in the hope that it will be useful #
---- # but WITHOUT ANY WARRANTY; without even the implied warranty of #
---- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
---- # GNU General Public License for more details. #
---- # #
---- #########################################################################
------------------------------------------------------------------------------
-- This script library is a rewrite of the original DSM forward programming Lua
-- Script. The goal is to make it easier to understand, mantain, and to
-- separate the GUI from the DSM Forward programming engine/logic
-- in this way, GUIs can evolve independent. OpenTX Gui, EdgeTx GUI, Small Radios, etc.
-- Code is based on the code/work by: Pascal Langer (Author of the Multi-Module)
-- Rewrite/Enhancements By: Francisco Arzu
------------------------------------------------------------------------------
local SIMULATION_ON = false -- FALSE: don't show simulation menu (DEFAULT), TRUE: show simulation menu
local DEBUG_ON = 1 -- 0=NO DEBUG, 1=HIGH LEVEL 2=LOW LEVEL (Debug logged into the /LOGS/dsm.log)
local DEBUG_ON_LCD = false -- Interactive Information on LCD of Menu data from RX
local DSMLIB_PATH = "/SCRIPTS/TOOLS/DSMLIB/"
local dsmLib = assert(loadScript(DSMLIB_PATH.."DsmSetupLib.lua"), "Not-Found: DSMLIB/DsmSetupLib.lua")(DEBUG_ON,SIMULATION_ON)
local PHASE = dsmLib.PHASE
local LINE_TYPE = dsmLib.LINE_TYPE
local DISP_ATTR = dsmLib.DISP_ATTR
local DSM_Context = dsmLib.DSM_Context
local IS_EDGETX = false -- DEFAULT until Init changed it
local LCD_W_USABLE = LCD_W-10
-- X for Menu Lines
local LCD_X_LINE_MENU = 10
-- X offsets for (Title: [Value] debugInfo) lines
local LCD_X_LINE_TITLE = 10
local LCD_X_LINE_VALUE = 230
local LCD_X_LINE_DEBUG = 390
-- Line Height: make it smaller debugging info tp LCD (some space buttom)
local LCD_Y_LINE_HEIGHT = (DEBUG_ON_LCD and 23) or 27 -- if DEBUG 23 else 27
-- Y offsets
local LCD_Y_MENU_TITLE = 20
-- Y offet
local LCD_Y_LINE_FIRST = LCD_Y_MENU_TITLE + 30
local LCD_Y_LOWER_BUTTONS = LCD_Y_LINE_FIRST + 7 * LCD_Y_LINE_HEIGHT
local LCD_W_BUTTONS = 47
local LCD_H_BUTTONS = 25
local LCD_X_RIGHT_BUTTONS = LCD_W - LCD_W_BUTTONS - 5
local TEXT_SIZE = 0 -- NORMAL
local lastRefresh=0 -- Last time the screen was refreshed
local REFRESH_GUI_MS = 500/10 -- 500ms.. Screen Refresh Rate.. to not use unneded CPU time (in 10ms units to be compatible with getTime())
local originalValue = nil
local warningScreenON = true
------------------------------------------------------------------------------------------------------------
local function GUI_SwitchToRX()
-- Force to refresh DSM Info in MODEL (dsmLib pointing to the setup Script)
local dsmChannelInfo, description = dsmLib.CreateDSMPortChannelInfo()
dsmLib.ReleaseConnection()
dsmLib.LOG_close()
SIMULATION_ON = false
dsmLib = assert(loadScript(DSMLIB_PATH.."DsmFwPrgLib.lua"),"Not-Found: DSMLIB/DsmFwPrgLib.lua")(DEBUG_ON)
DSM_Context = dsmLib.DSM_Context
dsmLib.Init(toolName) -- Initialize Library
dsmLib.SetDSMChannelInfo(dsmChannelInfo, description) -- send the dsmChannelInfo to new instance library
dsmLib.StartConnection()
DSM_Context.Refresh_Display = true
end
local function GUI_SwitchToSIM()
dsmLib.ReleaseConnection()
dsmLib.LOG_close()
SIMULATION_ON = true
dsmLib = assert(loadScript(DSMLIB_PATH.."DsmFwPrgSIMLib.lua"), "Not-Found: DSMLIB/DsmFwPrgSIMLib.lua")(DEBUG_ON)
DSM_Context = dsmLib.DSM_Context
dsmLib.Init(toolName) -- Initialize Library
dsmLib.StartConnection()
DSM_Context.Refresh_Display = true
end
local function openTx_lcd_sizeText(s)
return string.len(s)*5
end
local function GUI_Diplay_Button(x,y,w,h,text,selected)
local attr = (selected) and INVERS or 0 -- INVERS if line Selected
if (TEXT_SIZE~=SMLSIZE) then
lcd.drawText(x+5,y+2, text, attr + TEXT_SIZE)
lcd.drawRectangle(x, y, w, h, LINE_COLOR)
else -- SMALL Screen
lcd.drawText(x,y, text, attr + TEXT_SIZE)
end
end
local function GUI_Display_Menu(menu)
local ctx = DSM_Context
local w= LCD_W_USABLE - LCD_W_BUTTONS - 10 -- usable Width for the Menu/Lines
-- Center Header
local tw = openTx_lcd_sizeText(menu.Text)
local x = w/2 - tw/2 -- Center of Screen - Center of Text
if (x < 0) then x=0 end -- in case text is too wide
local bold = BOLD
lcd.drawText(x,LCD_Y_MENU_TITLE,menu.Text,bold + TEXT_SIZE)
-- Back
if menu.BackId ~= 0 then
GUI_Diplay_Button(LCD_X_RIGHT_BUTTONS,LCD_Y_MENU_TITLE,LCD_W_BUTTONS,LCD_H_BUTTONS,"Back",ctx.SelLine == dsmLib.BACK_BUTTON)
end
-- Next ?
if menu.NextId ~= 0 then
GUI_Diplay_Button(LCD_X_RIGHT_BUTTONS,LCD_Y_LOWER_BUTTONS,LCD_W_BUTTONS,LCD_H_BUTTONS,"Next",ctx.SelLine == dsmLib.NEXT_BUTTON)
end
-- Prev?
if menu.PrevId ~= 0 then
GUI_Diplay_Button(0,LCD_Y_LOWER_BUTTONS,LCD_W_BUTTONS,LCD_H_BUTTONS,"Prev",ctx.SelLine == dsmLib.PREV_BUTTON)
end
-- Debug into LCD
if (DEBUG_ON_LCD) then lcd.drawText(0,LCD_Y_MENU_TITLE,dsmLib.phase2String(ctx.Phase),TEXT_SIZE + WARNING_COLOR) end -- Phase we are in
if (DEBUG_ON_LCD) then lcd.drawText(LCD_X_LINE_MENU,240,dsmLib.menu2String(menu),TEXT_SIZE + WARNING_COLOR) end -- Menu Info
end
local function GUI_Display_Line_Menu(x,y,w,h,line,selected)
local attr = (selected and INVERS) or 0 -- INVERS if line Selected
local bold = 0
local text = line.Text
if dsmLib.isSelectableLine(line) then
-- Menu Line
text = text .. " >"
else -- SubHeaders and plain text lines
bold = (dsmLib.isDisplayAttr(line.TextAttr,DISP_ATTR._BOLD) and BOLD) or 0
if dsmLib.isDisplayAttr(line.TextAttr,DISP_ATTR._RIGHT) then -- Right Align???
local tw = openTx_lcd_sizeText(line.Text)+4
x = LCD_X_LINE_VALUE - tw -- Right
elseif dsmLib.isDisplayAttr(line.TextAttr,DISP_ATTR._CENTER) then -- Center??
local tw = openTx_lcd_sizeText(line.Text)
x = x + (LCD_X_LINE_VALUE - LCD_X_LINE_MENU)/2 - tw/2 -- Center - 1/2 Text
end
if (x < 0) then x=0 end -- in case text is too wide
end
lcd.drawText(x,y, text, attr + bold + TEXT_SIZE)
end
------------------------------------------------------------------------------------------------------------
local function GUI_Display_Line_Value(lineNum, line, value, selected, editing)
local bold = 0
local y = LCD_Y_LINE_FIRST+(LCD_Y_LINE_HEIGHT*lineNum)
local x = LCD_X_LINE_TITLE
---------- NAME Part
local header = line.Text
-- ONLY do this for Flight Mode (Right Align or Centered)
if (dsmLib.isFlightModeLine(line)) then
-- Display Header + Value together
header = dsmLib.GetFlightModeValue(line)
-- Flight mode display attributes
bold = (dsmLib.isDisplayAttr(line.TextAttr,DISP_ATTR._BOLD) and BOLD) or 0
if dsmLib.isDisplayAttr(line.TextAttr,DISP_ATTR._RIGHT) then -- Right Align
local tw = openTx_lcd_sizeText(header)+4
x = LCD_X_LINE_VALUE - tw -- Right
elseif dsmLib.isDisplayAttr(line.TextAttr,DISP_ATTR._CENTER) then -- Centered
local tw = openTx_lcd_sizeText(header)
x = x + (LCD_X_LINE_VALUE - LCD_X_LINE_TITLE)/2 - tw/2 -- Center - 1/2 Text
end
if (x < 0) then x=0 end -- in case text is too wide
else
-- No Flight Mode, no effects here
header = header .. ":"
end
lcd.drawText(x, y, header, bold + TEXT_SIZE) -- display Line Header
--------- VALUE PART, Skip for Flight Mode since already show the value
if not dsmLib.isFlightModeLine(line) then
local attrib = 0
if selected then
attrib = INVERS
if editing then -- blink editing entry
attrib = attrib + BLINK
value = "[" .. value .. "]"
end
end
value = value .. " " .. (line.Format or "") -- Append % if needed
lcd.drawText(LCD_X_LINE_VALUE,y, value, attrib + TEXT_SIZE) -- display value
end
if (DEBUG_ON_LCD) then lcd.drawText(LCD_X_LINE_DEBUG,y, line.MinMaxDebug or "", TEXT_SIZE + WARNING_COLOR) end -- display debug
end
------------------------------------------------------------------------------------------------------------
local function GUI_ShowBitmap(x,y,imgData)
-- imgData format "bitmap.png|alt message"
local f = string.gmatch(imgData, '([^%|]+)') -- Iterator over values split by '|'
local imgName, imgMsg = f(), f()
if (LCD_W > 128) then
lcd.drawText(x, y, imgMsg or "", TEXT_SIZE) -- Alternate Image MSG
else
local f = string.gmatch(imgMsg, '([^%:]+)') -- Iterator over values split by ':'
local msg1,msg2 = f(), f()
lcd.drawText(x, y, (msg1 or "")..":", TEXT_SIZE) -- Alternate Image MSG
lcd.drawText(x, y+10, msg2 or "", TEXT_SIZE) -- Alternate Image MSG
end
-- NO IMAGES in Text B&W
--local imgPath = IMAGE_PATH .. (imgName or "")
--local bitmap = Bitmap.open(imgPath)
--if (bitmap~=nil) then
-- lcd.drawBitmap(bitmap, x,y+20)
--end
end
------------------------------------------------------------------------------------------------------------
local function GUI_Display()
local ctx = DSM_Context
lcd.clear()
local header = "DSM Fwrd Programming "
if (TEXT_SIZE==SMLSIZE) then -- Small Screen no title
header = ""
end
if ctx.Phase ~= PHASE.RX_VERSION then
header = header .. ctx.RX.Name.." v"..ctx.RX.Version
end
--Draw title
if (TEXT_SIZE~=SMLSIZE) then -- ignore tool title small size screens
lcd.drawFilledRectangle(0, 0, LCD_W, 20, TITLE_BGCOLOR)
lcd.drawText(5, 0, header, MENU_TITLE_COLOR + TEXT_SIZE)
else -- Small Screen
lcd.drawText(20, LCD_Y_LOWER_BUTTONS+1, header, TEXT_SIZE)
end
--Draw RX Menu
if ctx.Phase == PHASE.RX_VERSION then
if (ctx.isReset) then
lcd.drawText(LCD_X_LINE_TITLE,50,dsmLib.Get_Text(0x301), BLINK + TEXT_SIZE) -- Resetting
else
lcd.drawText(LCD_X_LINE_TITLE,50,dsmLib.Get_Text(0x300), BLINK + TEXT_SIZE) -- Waiting for RX Version
end
else
local menu = ctx.Menu
if menu.Text ~= nil then
GUI_Display_Menu(menu)
for i = 0, dsmLib.MAX_MENU_LINES do
local line = ctx.MenuLines[i]
if i == ctx.SelLine then
-- DEBUG: Display Selected Line info for ON SCREEN Debugging
if (DEBUG_ON_LCD) then lcd.drawText(LCD_X_LINE_TITLE,255,dsmLib.menuLine2String(line),TEXT_SIZE + WARNING_COLOR) end
end
if line ~= nil and line.Type ~= 0 then
if line.Type == LINE_TYPE.MENU then
-- Menu Line
GUI_Display_Line_Menu(LCD_X_LINE_MENU,LCD_Y_LINE_FIRST+(LCD_Y_LINE_HEIGHT*i), 350, LCD_Y_LINE_HEIGHT, line, i == ctx.SelLine)
else
-- list/value line
local value = line.Val
if line.Val ~= nil then
if dsmLib.isListLine(line) then -- for Lists of Strings, get the text
value = dsmLib.Get_List_Text(line.Val + line.TextStart) -- TextStart is the initial offset for text
local imgData = dsmLib.Get_List_Text_Img(line.Val + line.TextStart) -- Complentary IMAGE for this value to Display??
if (imgData and i == ctx.SelLine) then -- Optional Image and Msg for selected value
GUI_ShowBitmap(LCD_X_LINE_TITLE,LCD_Y_LINE_FIRST+LCD_Y_LINE_HEIGHT, imgData)
end
end
GUI_Display_Line_Value(i, line, value, i == ctx.SelLine, i == ctx.EditLine)
end
end -- if ~MENU
end -- if Line[i]~=nil
end -- for
end
end
end
-------------------------------------------------------------------------------------------------------------
local function GUI_RotEncVal(dir) -- return encoder speed to inc or dec values
local inc = 0
local Speed = getRotEncSpeed()
if Speed == ROTENC_MIDSPEED then
inc = (5 * dir)
elseif Speed == ROTENC_HIGHSPEED then
inc = (15 * dir)
else
inc = dir
end
return inc
end
------------------------------------------------------------------------------------------------------------
local function GUI_HandleEvent(event, touchState)
local ctx = DSM_Context
local menu = ctx.Menu
local menuLines = ctx.MenuLines
if event == EVT_VIRTUAL_EXIT then
ctx.Refresh_Display=true
if (DEBUG_ON) then dsmLib.LOG_write("%s: EVT_VIRTUAL_EXIT\n",dsmLib.phase2String(ctx.Phase)) end
if ctx.Phase == PHASE.RX_VERSION then
dsmLib.ReleaseConnection()
else
if ctx.isEditing() then -- Editing a Line, need to restore original value
ctx.MenuLines[ctx.EditLine].Val = originalValue
dsmLib.Value_Write_Validate(menuLines[ctx.EditLine])
else
dsmLib.ChangePhase(PHASE.EXIT) -- Exit
end
end
return
end
if event == EVT_VIRTUAL_NEXT then
ctx.Refresh_Display=true
if (DEBUG_ON) then dsmLib.LOG_write("%s: EVT_VIRTUAL_NEXT\n",dsmLib.phase2String(ctx.Phase)) end
if ctx.isEditing() then -- Editing a Line, need to inc the value
local line=ctx.MenuLines[ctx.EditLine]
dsmLib.Value_Add(line, GUI_RotEncVal(1))
else -- not editing, move selected line to NEXT
dsmLib.MoveSelectionLine(1)
end
return
end
if event == EVT_VIRTUAL_PREV then
ctx.Refresh_Display=true
if (DEBUG_ON) then dsmLib.LOG_write("%s: EVT_VIRTUAL_PREV\n",dsmLib.phase2String(ctx.Phase)) end
if ctx.isEditing() then -- Editiing a line, need to dec the value
local line=ctx.MenuLines[ctx.EditLine]
dsmLib.Value_Add(line, GUI_RotEncVal(-1))
else -- not editing, move selected line to PREV
dsmLib.MoveSelectionLine(-1)
end
return
end
if event == EVT_VIRTUAL_ENTER_LONG then
ctx.Refresh_Display=true
if (DEBUG_ON) then dsmLib.LOG_write("%s: EVT_VIRTUAL_ENTER_LONG\n",dsmLib.phase2String(ctx.Phase)) end
if ctx.isEditing() then
-- reset the value to default
dsmLib.Value_Default( menuLines[ctx.EditLine]) -- Update RX value as needed
end
return
end
if event == EVT_VIRTUAL_ENTER then
ctx.Refresh_Display=true
if (DEBUG_ON) then dsmLib.LOG_write("%s: EVT_VIRTUAL_ENTER\n",dsmLib.phase2String(ctx.Phase)) end
if ctx.SelLine == dsmLib.BACK_BUTTON then -- Back
dsmLib.GotoMenu(menu.BackId,0x80)
elseif ctx.SelLine == dsmLib.NEXT_BUTTON then -- Next
dsmLib.GotoMenu(menu.NextId,0x82)
elseif ctx.SelLine == dsmLib.PREV_BUTTON then -- Prev
dsmLib.GotoMenu(menu.PrevId,0x81)
elseif menuLines[ctx.SelLine].ValId ~= 0 then
if menuLines[ctx.SelLine].Type == LINE_TYPE.MENU then -- Next menu exist
if (menuLines[ctx.SelLine].ValId==0xFFF1) then
-- SPECIAL Simulation menu to Simulator
GUI_SwitchToSIM()
elseif (menuLines[ctx.SelLine].ValId==0xFFF2) then
-- SPECIAL Simulation menu to go to RX
GUI_SwitchToRX()
else
dsmLib.GotoMenu(menuLines[ctx.SelLine].ValId, ctx.SelLine) -- ValId is the MenuId to navigate to
end
else
-- Editing a Line????
if ctx.isEditing() then
-- Change the Value and exit edit
dsmLib.Value_Write_Validate(menuLines[ctx.SelLine])
else
-- enter Edit the current line
ctx.EditLine = ctx.SelLine
originalValue = menuLines[ctx.SelLine].Val
dsmLib.ChangePhase(PHASE.VALUE_CHANGING_WAIT)
end
end
end
end
end
local function init_screen_pos()
-- osName in OpenTX is nil, otherwise is EDGETX
local ver, radio, maj, minor, rev, osname = getVersion()
if (osname==nil) then osname = "OpenTX" end -- OTX 2.3.14 and below returns nil
IS_EDGETX = string.sub(osname,1,1) =='E'
if LCD_W == 480 then -- TX16
-- use defaults in the script header
elseif LCD_W == 128 then --TX12 (128x64) -- Still needs some work on the vertical
DEBUG_ON_LCD = false -- no space for this
TEXT_SIZE = SMLSIZE
LCD_W_USABLE = 128
LCD_W_BUTTONS = 16
LCD_H_BUTTONS = 10
LCD_X_RIGHT_BUTTONS = 128 - LCD_W_BUTTONS - 3
LCD_X_LINE_MENU = 0
-- X offsets for (Title: [Value] debugInfo) lines
LCD_X_LINE_TITLE = 0
LCD_X_LINE_VALUE = 75
LCD_X_LINE_DEBUG = 110
LCD_Y_LINE_HEIGHT = 7
LCD_Y_MENU_TITLE = 0
LCD_Y_LINE_FIRST = LCD_Y_MENU_TITLE + 8
LCD_Y_LOWER_BUTTONS = LCD_Y_LINE_FIRST + (7 * LCD_Y_LINE_HEIGHT)
end
end
local function GUI_Warning(event)
lcd.clear()
local header = "DSM Forward Programming "..VERSION.." "
--Draw title
if (LCD_W > 128) then
lcd.drawFilledRectangle(0, 0, LCD_W, 17, TITLE_BGCOLOR)
lcd.drawText(5, 0, header, MENU_TITLE_COLOR + TEXT_SIZE)
lcd.drawText(100,20,"INFO", BOLD)
lcd.drawText(5,40,"DSM Forward programing shares TX Servo/Output settings", TEXT_SIZE)
lcd.drawText(5,60,"with the RX. Make sure you setup your plane first in ", TEXT_SIZE)
lcd.drawText(5,80,"the TX before your start programming your RX.", TEXT_SIZE)
lcd.drawText(5,100,"Wing & Tail type can be configured using this tool.", TEXT_SIZE)
lcd.drawText(5,150,"TX Servo settings are sent to the RX during 'Initial Setup'", TEXT_SIZE)
lcd.drawText(5,170,"as well as when using RX menu 'Relearn Servo Settings'", TEXT_SIZE)
lcd.drawText(5,200,"ALWAYS TEST Gyro reactions after this conditions before flying.", BOLD+TEXT_SIZE)
lcd.drawText(100,250," OK ", INVERS + BOLD + TEXT_SIZE)
else
lcd.drawText(0,15,"Make sure you setup your plane", TEXT_SIZE)
lcd.drawText(0,22,"first. Wing and Tail type.", TEXT_SIZE)
lcd.drawText(0,30,"TX Servo settings are sent to ", TEXT_SIZE)
lcd.drawText(0,37,"the RX during 'Initial Setup' and ", TEXT_SIZE)
lcd.drawText(0,45,"ALWAYS TEST Gyro reactions", TEXT_SIZE)
lcd.drawText(0,52,"before flying!!!", TEXT_SIZE)
lcd.drawText(10,0," OK ", INVERS + BOLD + TEXT_SIZE)
end
if event == EVT_VIRTUAL_EXIT or event == EVT_VIRTUAL_ENTER then
warningScreenON = false
end
return 0
end
------------------------------------------------------------------------------------------------------------
-- Init
local function DSM_Init()
init_screen_pos()
dsmLib.Init(toolName) -- Initialize Library
return dsmLib.StartConnection()
end
------------------------------------------------------------------------------------------------------------
-- Main
local function DSM_Run(event)
local ctx = DSM_Context
if event == nil then
error("Cannot be run as a model script!")
dsmLib.LOG_close()
return 2
end
if (warningScreenON) then
return GUI_Warning(event)
end
GUI_HandleEvent(event)
dsmLib.Send_Receive() -- Handle Send and Receive DSM Forward Programming Messages
local refreshInterval = REFRESH_GUI_MS
-- When using LCD BLINK attribute, we need faster refresh for BLINK to SHOW on LCD
if (ctx.EditLine or (ctx.Phase == PHASE.RX_VERSION)) then -- Editing or Requesting RX Version?
ctx.Refresh_Display=true
refreshInterval = 20 -- 200ms
end
if (not IS_EDGETX) then -- OPENTX NEEDS REFRESH ON EVERY CYCLE
GUI_Display()
-- Refresh display only if needed and no faster than 500ms, utilize more CPU to speedup DSM communications
elseif (ctx.Refresh_Display and (getTime()-lastRefresh) > refreshInterval) then --300ms from last refresh
GUI_Display()
ctx.Refresh_Display=false
lastRefresh=getTime()
end
if ctx.Phase == PHASE.EXIT_DONE then
dsmLib.LOG_close()
return 2
else
return 0
end
end
return { init=DSM_Init, run=DSM_Run }

View File

@@ -0,0 +1,708 @@
local toolName = "TNS|DSM Forward Prog v0.54 (Color+Touch) |TNE"
local VERSION = "v0.54"
---- #########################################################################
---- # #
---- # Copyright (C) OpenTX #
-----# #
---- # License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html #
---- # #
---- # This program is free software; you can redistribute it and/or modify #
---- # it under the terms of the GNU General Public License version 2 as #
---- # published by the Free Software Foundation. #
---- # #
---- # This program is distributed in the hope that it will be useful #
---- # but WITHOUT ANY WARRANTY; without even the implied warranty of #
---- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
---- # GNU General Public License for more details. #
---- # #
---- #########################################################################
------------------------------------------------------------------------------
-- This script library is a rewrite of the original DSM forward programming Lua
-- Script. The goal is to make it easier to understand, mantain, and to
-- separate the GUI from the DSM Forward programming engine/logic
-- in this way, GUIs can evolve independent. OpenTX Gui, EdgeTx GUI, Small Radios, etc.
-- Code is based on the code/work by: Pascal Langer (Author of the Multi-Module)
-- Rewrite/Enhancements By: Francisco Arzu
------------------------------------------------------------------------------
local SIMULATION_ON = false -- FALSE:don't show simulation memu (DEFAULT), TRUE: show simulation menu
local DEBUG_ON = 1 -- 0=NO DEBUG, 1=HIGH LEVEL 2=LOW LEVEL (Debug logged into the /LOGS/dsm.log)
local DEBUG_ON_LCD = false -- Interactive Information on LCD of Menu data from RX
local USE_SPECKTRUM_COLORS = true -- true: Use spectrum colors, false: use theme colors (default on OpenTX)
local DSMLIB_PATH = "/SCRIPTS/TOOLS/DSMLIB/"
local IMAGE_PATH = DSMLIB_PATH .. "img/"
local dsmLib = assert(loadScript(DSMLIB_PATH.."DsmSetupLib.lua"), "Not-Found: DSMLIB/DsmSetupLib.lua")(DEBUG_ON,SIMULATION_ON)
local PHASE = dsmLib.PHASE
local LINE_TYPE = dsmLib.LINE_TYPE
local DISP_ATTR = dsmLib.DISP_ATTR
local DSM_Context = dsmLib.DSM_Context
local lastRefresh=0 -- Last time the screen was refreshed
local REFRESH_GUI_MS = 300/10 -- 300ms.. Screen Refresh Rate.. to not waste CPU time (in 10ms units to be compatible with getTime())
local originalValue = nil
local touchButtonArea = {}
local EDIT_BUTTON = { DEFAULT=1001, DEC_10=1002, DEC_1=1003, INC_1=1004, INC_10=5, OK=1006, ESC=1007 }
local IS_EDGETX = false -- DEFAULT until Init changed it
local LCD_Y_MENU_TITLE = 20
local LCD_W_MENU_TITLE = LCD_W-100
local LCD_X_LINE_MENU = 30
local LCD_W_LINE_MENU = 350
local LCD_X_LINE_TITLE = 30
local LCD_X_LINE_VALUE = 230
local LCD_X_LINE_DEBUG = 390
local LCD_Y_LINE_START = LCD_Y_MENU_TITLE + 30
local LCD_Y_LINE_HEIGHT = (DEBUG_ON_LCD and 23) or 27 -- if DEBUG 23 else 27
local LCD_Y_LOWER_BUTTONS = LCD_Y_LINE_START + 3 + (7 * LCD_Y_LINE_HEIGHT)
-- TOOL BG COLOR
local LCD_TOOL_BGCOLOR = TEXT_BGCOLOR
-- TOOL HEADER
local LCD_TOOL_HDR_COLOR = MENU_TITLE_COLOR
local LCD_TOOL_HDR_BGCOLOR = TITLE_BGCOLOR
-- MENU HEADER
local LCD_MENU_COLOR = MENU_TITLE_COLOR
local LCD_MENU_BGCOLOR = MENU_TITLE_BGCOLOR
-- LINE SELECTED
local LCD_SELECTED_COLOR = TEXT_INVERTED_COLOR
local LCD_SELECTED_BGCOLOR = TEXT_INVERTED_BGCOLOR
local LCD_EDIT_BGCOLOR = MENU_TITLE_BGCOLOR -- WARNING_COLOR
-- NORMAL TEXT
local LCD_NORMAL_COLOR = TEXT_COLOR
local LCD_DISABLE_COLOR = TEXT_DISABLE_COLOR
local LCD_DEBUG_COLOR = LINE_COLOR
-- NORMAL BOX FRAME COLOR
local LCD_BOX_COLOR = TEXT_DISABLE_COLOR
local warningScreenON = true
--------------------- lcd.sizeText replacement -------------------------------------------------
-- EdgeTx dont have lcd.sizeText, so we do an equivalent one using the string length and 5px per character
local function my_lcd_sizeText(s)
-- return: If IS_EDGETX then lcd.sizeText() else string.len()
return (IS_EDGETX and lcd.sizeText(s)) or (string.len(s)*10)
end
local function GUI_SwitchToRX()
-- Force to refresh DSM Info in MODEL (dsmLib pointing to the setup Script)
local dsmChannelInfo, description = dsmLib.CreateDSMPortChannelInfo()
dsmLib.ReleaseConnection()
dsmLib.LOG_close()
SIMULATION_ON = false
dsmLib = assert(loadScript(DSMLIB_PATH.."DsmFwPrgLib.lua"),"Not-Found: DSMLIB/DsmFwPrgLib.lua")(DEBUG_ON)
DSM_Context = dsmLib.DSM_Context
dsmLib.Init(toolName) -- Initialize Library
dsmLib.SetDSMChannelInfo(dsmChannelInfo, description) -- send the dsmChannelInfo to new instance library
dsmLib.StartConnection()
DSM_Context.Refresh_Display = true
end
local function GUI_SwitchToSIM()
dsmLib.ReleaseConnection()
dsmLib.LOG_close()
SIMULATION_ON = true
dsmLib = assert(loadScript(DSMLIB_PATH.."DsmFwPrgSIMLib.lua"), "Not-Found: DSMLIB/DsmFwPrgSIMLib.lua")(DEBUG_ON)
DSM_Context = dsmLib.DSM_Context
dsmLib.Init(toolName) -- Initialize Library
dsmLib.StartConnection()
DSM_Context.Refresh_Display = true
end
--------------------- Toucch Button Helpers ------------------------------------------------------------
local function GUI_addTouchButton(x,y,w,h,line)
-- Add new button info to end of the array
touchButtonArea[#touchButtonArea+1] = {x=x, y=y, w=w, h=h, line=line}
end
local function GUI_getTouchButton(x,y)
for i = 1, #touchButtonArea do
local button = touchButtonArea[i]
-- is the coordinate inside the button area??
if (x >= button.x and x <= (button.x+button.w) and y >= button.y and (y <= button.y+button.h)) then
return button.line
end
end
return nil
end
local function GUI_clearTouchButtons()
touchButtonArea = {}
end
---------- Return Color to display Menu Lines ----------------------------------------------------------------
local function GUI_GetTextColor(lineNum)
local ctx = DSM_Context
local txtColor = LCD_NORMAL_COLOR
-- Gray Out any other line except the one been edited
if (ctx.isEditing() and ctx.EditLine~=lineNum) then txtColor=LCD_DISABLE_COLOR end
return txtColor
end
local function GUI_GetFrameColor(lineNum) -- Frame Color for Value/Menu Boxes
local ctx = DSM_Context
local txtColor = LCD_BOX_COLOR
-- Gray Out any other line except the one been edited
if (ctx.EditLine~=lineNum) then txtColor=LCD_DISABLE_COLOR end
return txtColor
end
--------------------------------------------------------------------------------------------------------
-- Display Text inside a Rectangle. Inv: true means solid rectangle, false=only perimeter
local function GUI_Display_Boxed_Text(lineNum,x,y,w,h,text,inv, isNumber)
local ctx = DSM_Context
local txtColor = GUI_GetTextColor(lineNum)
local frameColor = GUI_GetFrameColor(lineNum)
-- If editing this lineNum, chose EDIT Color, else SELECTED Color
local selectedBGColor = (ctx.EditLine==lineNum and LCD_EDIT_BGCOLOR) or LCD_SELECTED_BGCOLOR
if (inv) then
txtColor = LCD_SELECTED_COLOR
lcd.drawFilledRectangle(x-5, y-2, w, h, selectedBGColor)
else
lcd.drawRectangle(x-5, y-2, w, h, frameColor)
end
if (isNumber) then
lcd.drawNumber(x+w-10 , y, text, txtColor + RIGHT)
else
lcd.drawText(x , y, text, txtColor)
end
end
------ Display Pre/Next/Back buttons
local function GUI_Diplay_Button(x,y,w,h,text,selected)
GUI_Display_Boxed_Text(-1,x,y,w,h,text,selected, false)
end
------ Display MENU type of lines (Navigation, SubHeaders, and plain text comments)
local function GUI_Display_Line_Menu(lineNum,line,selected)
-- Menu Lines can be navidation to other Menus (if Selectable)
-- Or SubHeaders or Messages
local txtColor = GUI_GetTextColor(lineNum)
local y = LCD_Y_LINE_START+(LCD_Y_LINE_HEIGHT*lineNum)
local x = LCD_X_LINE_MENU
if dsmLib.isSelectableLine(line) then -- Draw Selectable Menus in Boxes
GUI_Display_Boxed_Text(lineNum,x, y, LCD_W_LINE_MENU, LCD_Y_LINE_HEIGHT, line.Text,selected, false)
GUI_addTouchButton(x, y, LCD_W_LINE_MENU, LCD_Y_LINE_HEIGHT,lineNum)
else
-- Non Selectable Menu Lines, plain text
-- Can be use for sub headers or just regular text lines (like warnings)
local bold = (dsmLib.isDisplayAttr(line.TextAttr,DISP_ATTR._BOLD) and BOLD) or 0
if dsmLib.isDisplayAttr(line.TextAttr,DISP_ATTR._RIGHT) then -- Right Align???
local tw = my_lcd_sizeText(line.Text)+4
x = LCD_X_LINE_VALUE - tw -- Right
elseif dsmLib.isDisplayAttr(line.TextAttr,DISP_ATTR._CENTER) then -- Center??
local tw = my_lcd_sizeText(line.Text)
x = x + (LCD_X_LINE_VALUE - LCD_X_LINE_MENU)/2 - tw/2 -- Center - 1/2 Text
end
lcd.drawText(x, y, line.Text, txtColor + bold)
end
end
------ Display NAME : VALUES type of lines
local function GUI_Display_Line_Value(lineNum, line, value, selected, editing)
-- This Displays Name and Value Pairs
local txtColor = GUI_GetTextColor(lineNum)
local bold = 0
local y = LCD_Y_LINE_START+(LCD_Y_LINE_HEIGHT*lineNum)
local x = LCD_X_LINE_TITLE
---------- NAME Part
local header = line.Text
-- ONLY do this for Flight Mode (Right Align or Centered)
if (dsmLib.isFlightModeLine(line)) then
-- Display Header + Value together
header = dsmLib.GetFlightModeValue(line)
-- Bold Text???
bold = (dsmLib.isDisplayAttr(line.TextAttr,DISP_ATTR._BOLD) and BOLD) or 0
if dsmLib.isDisplayAttr(line.TextAttr,DISP_ATTR._RIGHT) then -- Right Align
local tw = my_lcd_sizeText(header)+4
x = LCD_X_LINE_VALUE - tw -- Right
elseif dsmLib.isDisplayAttr(line.TextAttr,DISP_ATTR._CENTER) then -- Centered
local tw = my_lcd_sizeText(header)
x = x + (LCD_X_LINE_VALUE - LCD_X_LINE_TITLE)/2 - tw/2 -- Center - 1/2 Text
end
else
-- No Flight Mode, no effects here
header = header .. ":"
end
lcd.drawText(x, y, header, txtColor + bold) -- display Line Header
--------- VALUE PART, Skip for Flight Mode since already show the value
if not dsmLib.isFlightModeLine(line) then
if dsmLib.isSelectableLine(line) then
--if (editing) then -- Any Special color/effect when editing??
-- value = "["..value .. "]"
--end
-- Can select/edit value, Box it
local tw = math.max(my_lcd_sizeText(value)+10,45) -- Width of the Text in the lcd
GUI_Display_Boxed_Text(lineNum,LCD_X_LINE_VALUE,y,tw,LCD_Y_LINE_HEIGHT,value,selected, not dsmLib.isListLine(line))
GUI_addTouchButton(LCD_X_LINE_VALUE,y,tw,LCD_Y_LINE_HEIGHT,lineNum)
lcd.drawText(LCD_X_LINE_VALUE+tw+5, y, (line.Format or ""), txtColor + bold)
else -- Not Editable, Plain Text
lcd.drawText(LCD_X_LINE_VALUE, y, value, txtColor)
end
end
-- Debug info for line Value RANGE when Debug on LCD
if (DEBUG_ON_LCD) then lcd.drawText(LCD_X_LINE_DEBUG, y, line.MinMaxDebug or "", SMLSIZE + LCD_DEBUG_COLOR) end -- display debug Min/Max
end
local function GUI_Display_Menu(menu)
local ctx = DSM_Context
local w= LCD_W_MENU_TITLE
-- Center Header
local tw = my_lcd_sizeText(menu.Text)
local x = w/2 - tw/2 -- Center of Screen - Center of Text
lcd.drawFilledRectangle(0, LCD_Y_MENU_TITLE-2, w, LCD_Y_LINE_HEIGHT-2, LCD_MENU_BGCOLOR)
lcd.drawText(x,LCD_Y_MENU_TITLE,menu.Text, LCD_MENU_COLOR + BOLD)
-- Back Button
if menu.BackId ~= 0 then
GUI_Diplay_Button(437-5,LCD_Y_MENU_TITLE+3,47,LCD_Y_LINE_HEIGHT,"Back",ctx.SelLine == dsmLib.BACK_BUTTON)
GUI_addTouchButton(437-5,LCD_Y_MENU_TITLE+3,47,LCD_Y_LINE_HEIGHT,dsmLib.BACK_BUTTON)
end
-- Next Button
if menu.NextId ~= 0 then
GUI_Diplay_Button(437-5,LCD_Y_LOWER_BUTTONS,47,LCD_Y_LINE_HEIGHT,"Next",ctx.SelLine == dsmLib.NEXT_BUTTON)
GUI_addTouchButton(437-5,LCD_Y_LOWER_BUTTONS,47,LCD_Y_LINE_HEIGHT,dsmLib.NEXT_BUTTON)
end
-- Prev Button
if menu.PrevId ~= 0 then
GUI_Diplay_Button(10,LCD_Y_LOWER_BUTTONS,47,LCD_Y_LINE_HEIGHT,"Prev",ctx.SelLine == dsmLib.PREV_BUTTON)
GUI_addTouchButton(10,LCD_Y_LOWER_BUTTONS,47,LCD_Y_LINE_HEIGHT,dsmLib.PREV_BUTTON)
end
-- Debug on LCD, Show the menu Indo and Phase we are on
if (DEBUG_ON_LCD) then lcd.drawText(0,LCD_Y_MENU_TITLE,dsmLib.phase2String(ctx.Phase),SMLSIZE+LCD_DEBUG_COLOR) end -- Phase we are in
if (DEBUG_ON_LCD) then lcd.drawText(0,240,dsmLib.menu2String(menu),SMLSIZE+LCD_DEBUG_COLOR) end -- Menu Info
end
------------------------------------------------------------------------------------------------------------
-- Display the EDIT mode buttons when editing a value
local function GUI_Display_Edit_Buttons(line)
GUI_clearTouchButtons() -- Only this buttons can be touched
local x = 15 -- Inittial X position
local w = 55 -- Width of the buttons
local showPrev = line.Val > line.Min
local showNext = line.Val < line.Max
GUI_Diplay_Button(x,LCD_Y_LOWER_BUTTONS,w,LCD_Y_LINE_HEIGHT,"ESC",true)
GUI_addTouchButton(x,LCD_Y_LOWER_BUTTONS,w,LCD_Y_LINE_HEIGHT,EDIT_BUTTON.ESC)
x=x+w+10
GUI_Diplay_Button(x,LCD_Y_LOWER_BUTTONS,w,LCD_Y_LINE_HEIGHT," Def",true)
GUI_addTouchButton(x,LCD_Y_LOWER_BUTTONS,w,LCD_Y_LINE_HEIGHT,EDIT_BUTTON.DEFAULT)
x=x+w+10
if (not dsmLib.isListLine(line)) then
GUI_Diplay_Button(x,LCD_Y_LOWER_BUTTONS,w,LCD_Y_LINE_HEIGHT," << ",showPrev)
GUI_addTouchButton(x,LCD_Y_LOWER_BUTTONS,w,LCD_Y_LINE_HEIGHT,EDIT_BUTTON.DEC_10)
end
x=x+w+10
GUI_Diplay_Button(x,LCD_Y_LOWER_BUTTONS,w,LCD_Y_LINE_HEIGHT," <",showPrev)
GUI_addTouchButton(x,LCD_Y_LOWER_BUTTONS,w,LCD_Y_LINE_HEIGHT,EDIT_BUTTON.DEC_1)
x=x+w+10
GUI_Diplay_Button(x,LCD_Y_LOWER_BUTTONS,w,LCD_Y_LINE_HEIGHT," >",showNext)
GUI_addTouchButton(x,LCD_Y_LOWER_BUTTONS,w,LCD_Y_LINE_HEIGHT,EDIT_BUTTON.INC_1)
x=x+w+10
if (not dsmLib.isListLine(line)) then
GUI_Diplay_Button(x,LCD_Y_LOWER_BUTTONS,w,LCD_Y_LINE_HEIGHT," >>",showNext)
GUI_addTouchButton(x,LCD_Y_LOWER_BUTTONS,w,LCD_Y_LINE_HEIGHT,EDIT_BUTTON.INC_10)
end
x=x+w+10
GUI_Diplay_Button(x,LCD_Y_LOWER_BUTTONS,w,LCD_Y_LINE_HEIGHT," OK",true)
GUI_addTouchButton(x,LCD_Y_LOWER_BUTTONS,w,LCD_Y_LINE_HEIGHT,EDIT_BUTTON.OK)
end
local function GUI_ShowBitmap(x,y,imgData)
-- imgData format "bitmap.png|alt message"
local f = string.gmatch(imgData, '([^%|]+)') -- Iterator over values split by '|'
local imgName, imgMsg = f(), f()
lcd.drawText(x, y, imgMsg or "") -- Alternate Image MSG
local imgPath = IMAGE_PATH .. (imgName or "")
local bitmap = Bitmap.open(imgPath)
if (bitmap~=nil) then
lcd.drawBitmap(bitmap, x,y+20)
end
end
------------------------------------------------------------------------------------------------------------
local function GUI_Display()
local ctx = DSM_Context
lcd.clear(LCD_TOOL_BGCOLOR)
GUI_clearTouchButtons()
if LCD_W == 480 then
local header = "DSM Forward Programming "..VERSION.." "
if ctx.Phase ~= PHASE.RX_VERSION then
header = header .. "RX "..ctx.RX.Name.." v"..ctx.RX.Version
end
--Draw title
lcd.drawFilledRectangle(0, 0, LCD_W, 17, LCD_TOOL_HDR_BGCOLOR)
lcd.drawText(5, 0, header, LCD_TOOL_HDR_COLOR + SMLSIZE)
--Draw RX Menu
if ctx.Phase == PHASE.RX_VERSION then
if (ctx.isReset) then
lcd.drawText(LCD_X_LINE_TITLE,100,dsmLib.Get_Text(0x301), BLINK) -- Waiting for Restart
else
lcd.drawText(LCD_X_LINE_TITLE,100,dsmLib.Get_Text(0x300), BLINK) -- Waiting for RX
end
else
local menu = ctx.Menu
if menu.Text ~= nil then
GUI_Display_Menu(menu)
for i = 0, dsmLib.MAX_MENU_LINES do
local line = ctx.MenuLines[i]
if i == ctx.SelLine then
-- DEBUG: Display Selected Line info for ON SCREEN Debugging
if (DEBUG_ON_LCD) then lcd.drawText(0,255,dsmLib.menuLine2String(line),SMLSIZE + LCD_DEBUG_COLOR) end
end
if line ~= nil and line.Type ~= 0 then
if line.Type == LINE_TYPE.MENU then
GUI_Display_Line_Menu(i, line, i == ctx.SelLine)
else
if line.Val ~= nil then
local value = line.Val
if dsmLib.isListLine(line) then -- for Lists of Strings, get the text
value = dsmLib.Get_List_Text(line.Val + line.TextStart) -- TextStart is the initial offset for text
local imgData = dsmLib.Get_List_Text_Img(line.Val + line.TextStart) -- Complentary IMAGE for this value to Display??
if (imgData and i == ctx.SelLine) then -- Optional Image and Msg for selected value
GUI_ShowBitmap(LCD_X_LINE_TITLE,LCD_Y_LINE_START, imgData)
end
end
GUI_Display_Line_Value(i, line, value, i == ctx.SelLine, i == ctx.EditLine)
end
end -- if ~MENU
end -- if Line[i]~=nil
end -- for
if IS_EDGETX and ctx.isEditing() then
-- Display Touch button for Editing values
GUI_Display_Edit_Buttons(ctx.MenuLines[ctx.EditLine])
end
end
end
else
-- Different Resolution.. Maybe just adjusting some of the constants will work, adjust it in DSM_Init??
-- LCD_X_LINE_TITLE, LCD_Y_LINE_START, etc
lcd.drawText(LCD_X_LINE_TITLE,100,"Only supported in Color Radios of 480 resolution", BLINK)
end
end
-------------------------------------------------------------------------------------------------------------
local function GUI_RotEncVal(dir) -- return encoder speed to inc or dec values
local inc = 0
local Speed = getRotEncSpeed()
if Speed == ROTENC_MIDSPEED then inc = (5 * dir)
elseif Speed == ROTENC_HIGHSPEED then inc = (15 * dir)
else inc = dir end
return inc
end
------------------------------------------------------------------------------------
-- Translate Tap/Touch of EDIT buttons to equivalent Key events
local function GUI_Translate_Edit_Buttons(button)
local event = EVT_TOUCH_TAP
local editInc = nil
if (button==EDIT_BUTTON.ESC) then -- ESC
event = EVT_VIRTUAL_EXIT
elseif (button==EDIT_BUTTON.DEFAULT) then -- Default
event = EVT_VIRTUAL_ENTER_LONG
elseif (button==EDIT_BUTTON.DEC_10) then -- -10
event = EVT_VIRTUAL_PREV
editInc = -10
elseif (button==EDIT_BUTTON.DEC_1) then -- -1
event = EVT_VIRTUAL_PREV
editInc = -1
elseif (button==EDIT_BUTTON.INC_1) then -- +1
event = EVT_VIRTUAL_NEXT
editInc = 1
elseif (button==EDIT_BUTTON.INC_10) then -- + 10
event = EVT_VIRTUAL_NEXT
editInc = 10
elseif (button==EDIT_BUTTON.OK) then -- OK
event = EVT_VIRTUAL_ENTER
else
end
return event, editInc
end
------------------------------------------------------------------------------------------------------------
-- Handle Events comming from the GUI
local function GUI_HandleEvent(event, touchState)
local ctx = DSM_Context
local menu = ctx.Menu
local menuLines = ctx.MenuLines
local editInc = nil
if (IS_EDGETX) then
if (event == EVT_TOUCH_TAP and ctx.isEditing()) then -- Touch and Editing
local button = GUI_getTouchButton(touchState.x, touchState.y)
if (button) then
event, editInc = GUI_Translate_Edit_Buttons(button)
end
end
if (event == EVT_TOUCH_TAP or event == EVT_TOUCH_FIRST) and not ctx.isEditing() then -- Touch and NOT editing
if (DEBUG_ON) then dsmLib.LOG_write("%s: EVT_TOUCH_TAP %d,%d\n",dsmLib.phase2String(ctx.Phase),touchState.x, touchState.y) end
local button = GUI_getTouchButton(touchState.x, touchState.y)
if button then
-- Found a valid line
ctx.SelLine = button
ctx.Refresh_Display=true
if event == EVT_TOUCH_TAP then -- EVT_TOUCH_FIRST only move focus
event = EVT_VIRTUAL_ENTER
end
end
end
end -- IS_EDGETX
if event == EVT_VIRTUAL_EXIT then
ctx.Refresh_Display=true
if (DEBUG_ON) then dsmLib.LOG_write("%s: EVT_VIRTUAL_EXIT\n",dsmLib.phase2String(ctx.Phase)) end
if ctx.Phase == PHASE.RX_VERSION then
dsmLib.ReleaseConnection() -- Just Exit the Script
else
if ctx.isEditing() then -- Editing a Line, need to restore original value
local line = ctx.MenuLines[ctx.EditLine]
line.Val = originalValue
dsmLib.Value_Write_Validate(line)
else
dsmLib.ChangePhase(PHASE.EXIT)
end
end
return
end
if event == EVT_VIRTUAL_NEXT then
ctx.Refresh_Display=true
if (DEBUG_ON) then dsmLib.LOG_write("%s: EVT_VIRTUAL_NEXT\n",dsmLib.phase2String(ctx.Phase)) end
if ctx.isEditing() then -- Editing a Line, need to inc the value
local line=ctx.MenuLines[ctx.EditLine]
dsmLib.Value_Add(line, editInc or GUI_RotEncVal(1))
else -- not editing, move selected line to NEXT
dsmLib.MoveSelectionLine(1)
end
return
end
if event == EVT_VIRTUAL_PREV then
ctx.Refresh_Display=true
if (DEBUG_ON) then dsmLib.LOG_write("%s: EVT_VIRTUAL_PREV\n",dsmLib.phase2String(ctx.Phase)) end
if ctx.isEditing() then -- Editiing a line, need to dec the value
local line=ctx.MenuLines[ctx.EditLine]
dsmLib.Value_Add(line, editInc or GUI_RotEncVal(-1))
else -- not editing, move selected line to PREV
dsmLib.MoveSelectionLine(-1)
end
return
end
if event == EVT_VIRTUAL_ENTER_LONG then
ctx.Refresh_Display=true
if (DEBUG_ON) then dsmLib.LOG_write("%s: EVT_VIRTUAL_ENTER_LONG\n",dsmLib.phase2String(ctx.Phase)) end
if ctx.isEditing() then
-- reset the value to default
dsmLib.Value_Default(menuLines[ctx.EditLine]) -- Update value in RX if needed
end
return
end
if event == EVT_VIRTUAL_ENTER then
ctx.Refresh_Display=true
if (DEBUG_ON) then dsmLib.LOG_write("%s: EVT_VIRTUAL_ENTER, SelLine=%d\n",dsmLib.phase2String(ctx.Phase), ctx.SelLine) end
if ctx.SelLine == dsmLib.BACK_BUTTON then -- Back
dsmLib.GotoMenu(menu.BackId,0x80)
elseif ctx.SelLine == dsmLib.NEXT_BUTTON then -- Next
dsmLib.GotoMenu(menu.NextId,0x82)
elseif ctx.SelLine == dsmLib.PREV_BUTTON then -- Prev
dsmLib.GotoMenu(menu.PrevId,0x81)
elseif menuLines[ctx.SelLine].ValId ~= 0 then -- Menu or Value
if menuLines[ctx.SelLine].Type == LINE_TYPE.MENU then -- Navigate to Menu
if (menuLines[ctx.SelLine].ValId==0xFFF1) then
-- SPECIAL Simulation menu to Simulator
GUI_SwitchToSIM()
elseif (menuLines[ctx.SelLine].ValId==0xFFF2) then
-- SPECIAL Simulation menu to go to RX
GUI_SwitchToRX()
else
dsmLib.GotoMenu(menuLines[ctx.SelLine].ValId, ctx.SelLine) -- ValId is the MenuId to navigate to
end
else -- Enter on a Value
if ctx.isEditing() then -- already editing a Line????
dsmLib.Value_Write_Validate(menuLines[ctx.SelLine])
else -- Edit the current value
ctx.EditLine = ctx.SelLine
originalValue = menuLines[ctx.SelLine].Val
dsmLib.ChangePhase(PHASE.VALUE_CHANGING_WAIT)
end
end
end
end
end
local function init_colors()
-- osName in OpenTX is nil, otherwise is EDGETX
local ver, radio, maj, minor, rev, osname = getVersion()
if (osname==nil) then osname = "OpenTX" end -- OTX 2.3.14 and below returns nil
IS_EDGETX = string.sub(osname,1,1) == 'E'
if (IS_EDGETX and USE_SPECKTRUM_COLORS) then
-- SPECKTRUM COLORS (only works on EDGETX)
LCD_TOOL_BGCOLOR = LIGHTWHITE
-- TOOL HEADER
LCD_TOOL_HDR_COLOR = WHITE
LCD_TOOL_HDR_BGCOLOR = DARKBLUE
-- MENU HEADER
LCD_MENU_COLOR = WHITE
LCD_MENU_BGCOLOR = DARKGREY
-- LINE SELECTED
LCD_SELECTED_COLOR = WHITE
LCD_SELECTED_BGCOLOR = ORANGE
LCD_EDIT_BGCOLOR = RED
-- NORMAL TEXT
LCD_NORMAL_COLOR = BLACK
LCD_DISABLE_COLOR = LIGHTGREY
LCD_DEBUG_COLOR = BLUE
-- NORMAL BOX FRAME COLOR
LCD_BOX_COLOR = LIGHTGREY
end
end
local function GUI_Warning(event,touchState)
lcd.clear(LCD_TOOL_BGCOLOR)
local header = "DSM Forward Programming "..VERSION.." "
--Draw title
lcd.drawFilledRectangle(0, 0, LCD_W, 17, LCD_TOOL_HDR_BGCOLOR)
lcd.drawText(5, 0, header, LCD_TOOL_HDR_COLOR + SMLSIZE)
lcd.drawText(100,20,"INFO", BOLD)
lcd.drawText(5,40,"DSM Forward programing shares TX Servo/Output settings", 0)
lcd.drawText(5,60,"with the RX. Make sure you setup your plane first in ", 0)
lcd.drawText(5,80,"the TX before your start Fwrd programming your RX.", 0)
lcd.drawText(5,100,"Wing & Tail type can be configured using this tool.", 0)
lcd.drawText(5,150,"TX Gyro Servo settings are sent to the RX during 'Initial Setup'", 0)
lcd.drawText(5,170,"as well as when using RX 'Relearn Servo Settings'", 0)
lcd.drawText(5,200,"ALWAYS TEST Gyro reactions after this conditions before flying.", BOLD)
lcd.drawText(100,250," OK ", INVERS + BOLD)
if event == EVT_VIRTUAL_EXIT or event == EVT_VIRTUAL_ENTER or event == EVT_TOUCH_TAP then
warningScreenON = false
end
return 0
end
------------------------------------------------------------------------------------------------------------
-- Init
local function DSM_Init()
init_colors()
dsmLib.Init(toolName) -- Initialize Library
return dsmLib.StartConnection()
end
------------------------------------------------------------------------------------------------------------
-- Main
local function DSM_Run(event,touchState)
local ctx = DSM_Context
if event == nil then
error("Cannot be run as a model script!")
dsmLib.LOG_close()
return 2
end
if (warningScreenON) then
return GUI_Warning(event,touchState)
end
GUI_HandleEvent(event,touchState)
dsmLib.Send_Receive() -- Handle Send and Receive DSM Forward Programming Messages
local refreshInterval = REFRESH_GUI_MS
-- When using LCD BLINK attribute, we need faster refresh for BLINK to SHOW on LCD
if (ctx.Phase == PHASE.RX_VERSION) then -- Requesting RX Message Version usea BLINK?
ctx.Refresh_Display=true
refreshInterval = 20 -- 200ms
end
if (not IS_EDGETX) then -- OPENTX NEEDS REFRESH ON EVERY CYCLE
GUI_Display()
-- Refresh display only if needed and no faster than 300ms, utilize more CPU to speedup DSM communications
elseif (ctx.Refresh_Display and (getTime()-lastRefresh) > refreshInterval) then --300ms from last refresh
GUI_Display()
ctx.Refresh_Display=false
lastRefresh=getTime()
end
if ctx.Phase == PHASE.EXIT_DONE then
dsmLib.LOG_close()
return 2
else
return 0
end
end
return { init=DSM_Init, run=DSM_Run }

View File

@@ -0,0 +1,932 @@
local toolName = "TNS|DSM Frwd Prog v0.54-beta (MIN)|TNE"
--local ModelParam = ...
---- #########################################################################
---- # #
---- # Copyright (C) OpenTX #
-----# #
---- # License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html #
---- # #
---- # This program is free software; you can redistribute it and/or modify #
---- # it under the terms of the GNU General Public License version 2 as #
---- # published by the Free Software Foundation. #
---- # #
---- # This program is distributed in the hope that it will be useful #
---- # but WITHOUT ANY WARRANTY; without even the implied warranty of #
---- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
---- # GNU General Public License for more details. #
---- # #
---- #########################################################################
--###############################################################################
-- Multi buffer for DSM description
-- Multi_Buffer[0..2]=="DSM" -> Lua script is running
-- Multi_Buffer[3]==0x70+len -> TX to RX data ready to be sent
-- Multi_Buffer[4..9]=6 bytes of TX to RX data
-- Multi_Buffer[10..25]=16 bytes of RX to TX data
--
-- To start operation:
-- Write 0x00 at address 3
-- Write 0x00 at address 10
-- Write "DSM" at address 0..2
--###############################################################################
local VERSION = "v0.54-MIN"
local LANGUAGE = "en"
local DSMLIB_PATH = "/SCRIPTS/TOOLS/DSMLIB/"
local LOG_FILE = "/LOGS/dsm_min_log.txt"
local MSG_FILE = DSMLIB_PATH.."msg_fwdp_" .. LANGUAGE .. ".txt"
local MSG_FILE_MIN = DSMLIB_PATH.."MIN_msg_fwdp_" .. LANGUAGE .. ".txt"
-- Phase
local PH_RX_VER, PH_TITLE, PH_TX_INFO, PH_LINES, PH_VALUES = 1, 2, 3, 4, 5
local PH_VAL_CHANGING, PH_VAL_WAIT, PH_VAL_CHNG_END = 6, 7, 8
local PH_WAIT_CMD, PH_EXIT_REQ, PH_EXIT_DONE = 9, 10, 11
-- Line Types
local LT_MENU = 0x1C
local LT_LIST, LT_LIST_VALIDATE, LT_LIST_TOG = 0x6C, 0x0C, 0x4C
local LT_VALUE_NOCHANGING = 0x60
local LT_VALUE_PERCENT, LT_VALUE_DEGREES = 0xC0, 0xE0
local Phase = PH_RX_VER
local Waiting_RX = 0
local Text = {}
local List_Text = {}
local List_Text_Img = {}
local Flight_Mode = { [0] = "Flight Mode" }
local RxName = {}
local InactivityTime = 0
local Value_Change_Step = 0
local TX_Info_Step = 0
local TX_Info_Type = 0
local originalValue = 0
local ctx = {
SelLine = 0, -- Current Selected Line
EditLine = nil, -- Current Editing Line
CurLine = -1, -- Current Line Requested/Parsed via h message protocol
isReset = false -- false when starting from scracts, true when starting from Reset
}
local MODEL = {
modelName = "", -- The name of the model comming from OTX/ETX
modelOutputChannel = {}, -- Output information from OTX/ETX
AirWingTailDesc = "",
--TX_CH_TEXT = {},
--PORT_TEXT = {},
DSM_ChannelInfo = {} -- Data Created by DSM Configuration Script
}
local Menu = { MenuId = 0, Text = "", TextId = 0, PrevId = 0, NextId = 0, BackId = 0 }
local MenuLines = {}
local RX = { Name = "", Version = "" }
local logFile = nil
local logCount = 0
local LCD_X_LINE_TITLE = 0
local LCD_X_LINE_VALUE = 75
local LCD_W_BUTTONS = 19
local LCD_H_BUTTONS = 10
local LCD_X_MAX = 128
local LCD_X_RIGHT_BUTTONS = LCD_X_MAX - LCD_W_BUTTONS - 1
local LCD_Y_LINE_HEIGHT = 7
local LCD_Y_LOWER_BUTTONS = (8 * LCD_Y_LINE_HEIGHT) + 2
local TEXT_ATTR = SMLSIZE
local function LOG_open()
logFile = io.open(LOG_FILE, "w") -- Truncate Log File
end
local function LOG_write(...)
if (logFile == nil) then LOG_open() end
local str = string.format(...)
io.write(logFile, str)
end
local function LOG_close()
if (logFile ~= nil) then io.close(logFile) end
end
---------------- DSM Values <-> Int16 Manipulation --------------------------------------------------------
local function int16_LSB(number) -- Less Significat byte
local r, x = bit32.band(number, 0xFF)
return r
end
local function int16_MSB(number) -- Most signifcant byte
return bit32.rshift(number, 8)
end
local function Dsm_to_Int16(lsb, msb) -- Componse an Int16 value
return bit32.lshift(msb, 8) + lsb
end
local function Dsm_to_SInt16(lsb, msb) -- Componse a SIGNED Int16 value
local value = bit32.lshift(msb, 8) + lsb
if value >= 0x8000 then -- Negative value??
return value - 0x10000
end
return value
end
local function sInt16ToDsm(value) -- Convent to SIGNED DSM Value
if value < 0 then
value = 0x10000 + value
end
return value
end
------------------------------------------------------------------------------------------------------------
local function Get_Text(index)
local out = Text[index] or string.format("Unknown_%X", index)
if (index >= 0x8000) then
out = Flight_Mode[0]
end
return out
end
local function Get_Text_Value(index)
local out = List_Text[index] or Get_Text(index)
return out
end
------------------------------------------------------------------------------------------------------------
local function Get_RxName(index)
local out = RxName[index] or string.format("Unknown_%X", index)
return out
end
------------------------------------------------------------------------------------------------------------
local function DSM_Release()
multiBuffer(0, 0)
Phase = PH_EXIT_DONE
end
------------------------------------------------------------------------------------------------------------
local function DSM_Send(...)
local arg = { ... }
for i = 1, #arg do
multiBuffer(3 + i, arg[i])
end
multiBuffer(3, 0x70 + #arg)
end
------------------------------------------------------------------------------------------------------------
function ChangePhase(newPhase)
Phase = newPhase
Waiting_RX = 0
end
local function Value_Add(dir)
local line = MenuLines[ctx.SelLine]
Speed = getRotEncSpeed()
if Speed == ROTENC_MIDSPEED then
line.Val = line.Val + (5 * dir)
elseif Speed == ROTENC_HIGHSPEED then
line.Val = line.Val + (15 * dir)
else
line.Val = line.Val + dir
end
if line.Val > line.Max then
line.Val = line.Max
elseif line.Val < line.Min then
line.Val = line.Min
end
ChangePhase(PH_VAL_CHANGING)
Value_Change_Step = 0
end
------------------------------------------------------------------------------------------------------------
local function GotoMenu(menuId, lastSelectedLine)
Menu.MenuId = menuId
ctx.SelLine = lastSelectedLine
-- Request to load the menu Again
ChangePhase(PH_TITLE)
end
local function isSelectable(line)
if (line.TextId == 0x00CD) then return true end -- Exceptiom: Level model and capture attitude
if (line.Type == LT_MENU and line.ValId == line.MenuId) then return false end -- Menu to same page
if (line.Type ~= LT_MENU and line.Max == 0) then return false end -- Read only data line
if (line.Type ~= 0 and line.TextId < 0x8000) then return true end -- Not Flight Mode
return false;
end
local function isListLine(line)
return line.Type==LT_LIST or line.Type == LT_LIST_VALIDATE or line.Type == LT_LIST_TOG
end
local function DSM_Menu(event)
if event == EVT_VIRTUAL_EXIT then
if Phase == PH_RX_VER then
DSM_Release() -- Exit program
else
if ctx.EditLine ~= nil then -- Editing a Line, need to restore original value
MenuLines[ctx.EditLine].Val = originalValue
event = EVT_VIRTUAL_ENTER
else
ChangePhase(PH_EXIT_REQ)
end
end
end
if Phase == PH_RX_VER then return end -- nothing else to do
if event == EVT_VIRTUAL_NEXT then
if ctx.EditLine ~= nil then
Value_Add(1)
else
-- not changing a value
if ctx.SelLine < 7 then -- On a regular line
local num = ctx.SelLine -- Find the prev selectable
for i = ctx.SelLine + 1, 6, 1 do
local line = MenuLines[i]
if isSelectable(line) then
ctx.SelLine = i
break
end
end
if num == ctx.SelLine then -- No Selectable Line
if Menu.NextId ~= 0 then
ctx.SelLine = 7 -- Next
elseif Menu.PrevId ~= 0 then
ctx.SelLine = 8 -- Prev
end
end
elseif Menu.PrevId ~= 0 then
ctx.SelLine = 8 -- Prev
end
end
elseif event == EVT_VIRTUAL_PREV then
if ctx.EditLine ~= nil then -- In Edit Mode
Value_Add(-1)
else
if ctx.SelLine == 8 and Menu.NextId ~= 0 then
ctx.SelLine = 7 -- Next
elseif ctx.SelLine > 0 then
if ctx.SelLine > 6 then
ctx.SelLine = 7 --NEXT
end
local num = ctx.SelLine -- Find Prev Selectable line
for i = ctx.SelLine - 1, 0, -1 do
local line = MenuLines[i]
if isSelectable(line) then
ctx.SelLine = i
break
end
end
if num == ctx.SelLine then -- No Selectable Line
if (Menu.BackId > 0) then
ctx.SelLine = -1 -- Back
end
end
else
ctx.SelLine = -1 -- Back
end
end
elseif event == EVT_VIRTUAL_ENTER_LONG then
if ctx.EditLine ~= nil then
-- reset the value to default
--if MenuLines[ctx.SelLine].Type ~= LIST_MENU_NOCHANGING then
MenuLines[ctx.SelLine].Val = MenuLines[ctx.SelLine].Def
ChangePhase(PH_VAL_CHANGING)
Value_Change_Step = 0
--end
end
elseif event == EVT_VIRTUAL_ENTER then
if ctx.SelLine == -1 then -- Back
GotoMenu(Menu.BackId, 0x80)
elseif ctx.SelLine == 7 then -- Next
GotoMenu(Menu.NextId, 0x82)
elseif ctx.SelLine == 8 then -- Prev
GotoMenu(Menu.PrevId, 0x81)
elseif ctx.SelLine >= 0 and MenuLines[ctx.SelLine].Type == LT_MENU then
GotoMenu(MenuLines[ctx.SelLine].ValId, ctx.SelLine) -- ValId is the next menu
else
-- value entry
if ctx.EditLine ~= nil then
ctx.EditLine = nil -- Done Editting
Value_Change_Step = 0
ChangePhase(PH_VAL_CHNG_END)
else -- Start Editing
ctx.EditLine = ctx.SelLine
originalValue = MenuLines[ctx.SelLine].Val
ChangePhase(PH_VAL_WAIT)
end
end
end
end
------------------------------------------------------------------------------------------------------------
local function SendTxInfo(portNo)
-- TxInfo_Type=0 : AR636 Main Menu (Send port/Channel info + SubTrim + Travel)
-- TxInfo_Type=1 : AR630-637 Famly Main Menu (Only Send Port/Channel usage Msg 0x20)
-- TxInfo_Type=1F : AR630-637 Initial Setup/Relearn Servo Settings (Send port/Channel info + SubTrim + Travel +0x24/Unknown)
if (TX_Info_Step == 0) then
-- AR630 family: Both TxInfo_Type (ManinMenu=0x1, Other First Time Configuration = 0x1F)
local info = MODEL.DSM_ChannelInfo[portNo]
DSM_Send(0x20, 0x06, portNo, portNo, info[0],info[1])
LOG_write("DSM_TxInfo_20(Port=#%d, Port Use)\n", portNo)
if (TX_Info_Type == 0x1F) then
TX_Info_Step = 1
elseif (TX_Info_Type == 0x00) then
TX_Info_Step = 2
end
elseif (TX_Info_Step == 1) then
local info = MODEL.modelOutputChannel[portNo]
local leftTravel = math.abs(math.floor(info.min/10))
local rightTravel = math.abs(math.floor(info.max/10))
DSM_Send(0x23, 0x06, 0x00, leftTravel, 0x00, rightTravel)
LOG_write("DSM_TxInfo_23(Port=#%d,ServoTravel(L=%d - R=%d))\n", portNo,leftTravel,rightTravel)
TX_Info_Step = 2
elseif (TX_Info_Step == 2) then
local data = {[0]= -- Start at 0
{[0]= 0x0, 0x00, 0x07, 0xFF }, -- Ch1 Thr: 0 00 07 FF Subtrim ??
{[0]= 0x0, 0x8E, 0x07, 0x72 }, -- Ch2 Ail: 0 8E 07 72 Subtrim 0
{[0]= 0x0, 0x8E, 0x07, 0x72 }, -- Ch3 Elev: 0 8E 07 72 Subtrim 0
{[0]= 0x0, 0x8E, 0x07, 0x72 }, -- Ch4 Rud: 0 8E 07 72 Subtrim 0
{[0]= 0x0, 0x8E, 0x07, 0x72 }, -- Ch5 Gear: 0 8E 07 72 Subtrim 0
{[0]= 0x0, 0x8E, 0x07, 0x72 }, -- Ch6 Aux1: 0 8E 07 72 Subtrim 0
{[0]= 0x0, 0x8E, 0x07, 0x72 }, -- Ch7 Aux2: 0 8E 07 72 Subtrim 0
{[0]= 0x0, 0x8E, 0x07, 0x72 }, -- Ch8 Aux3: 0 8E 07 72 Subtrim 0
{[0]= 0x0, 0x8E, 0x07, 0x72 }, -- Ch9 Aux4: 0 8E 07 72 Subtrim 0
{[0]= 0x0, 0x8E, 0x07, 0x72 }, -- Ch10 Aux5: 0 8E 07 72 Subtrim 0
}
local info = data[portNo]
local b1,b2,b3,b4 = info[0], info[1], info[2], info[3]
DSM_Send(0x21, 0x06, b1,b2,b3,b4) -- Port is not send anywhere, since the previous 0x20 type message have it.
LOG_write("DSM_TxInfo_21(Port=#%d, SubTrim)\n", portNo)
if (TX_Info_Type == 0x00) then
TX_Info_Step = 5 -- End Step
else
TX_Info_Step = 3
end
elseif (TX_Info_Step == 3) then
LOG_write("DSM_TxInfo_24?(Port=#%d)\n", portNo)
DSM_Send(0x24, 0x06, 0x00, 0x83, 0x5A, 0xB5) -- Still Uknown
TX_Info_Step = 4
elseif (TX_Info_Step == 4) then
LOG_write("DSM_TxInfo_24?(Port=#%d)\n", portNo)
DSM_Send(0x24, 0x06, 0x06, 0x80, 0x25, 0x4B) -- Still Uknown
TX_Info_Step = 5
elseif (TX_Info_Step == 5) then
LOG_write("DSM_TxInfo_22(Port=#%d, END of Data)\n", portNo)
DSM_Send(0x22, 0x04, 0x00, 0x00)
TX_Info_Step = 0 -- Done!!
end
if (TX_Info_Step > 0) then
Waiting_RX = 0 -- keep Transmitig
end
end
local function DSM_SendRequest()
--LOG_write("DSM_SendRequest Phase=%d\n",Phase)
-- Need to send a request
if Phase == PH_RX_VER then -- request RX version
DSM_Send(0x11, 0x06, 0x00, 0x14, 0x00, 0x00)
LOG_write("GetVersion()\n")
elseif Phase == PH_WAIT_CMD then -- keep connection open
DSM_Send(0x00, 0x04, 0x00, 0x00)
elseif Phase == PH_TITLE then -- request menu title
local menuId = Menu.MenuId
if menuId == 0 then
DSM_Send(0x12, 0x06, 0x00, 0x14, 0x00, 0x00) -- first menu only
else
DSM_Send(0x16, 0x06, int16_MSB(menuId), int16_LSB(menuId), 0x00, ctx.SelLine)
if (menuId == 0x0001) then -- Executed Save&Reset menu
Phase = PH_RX_VER
ctx.isReset = true
end
end
LOG_write("GetMenu(M=0x%04X,L=%d)\n", menuId, ctx.SelLine)
elseif Phase == PH_TX_INFO then -- TX Info
SendTxInfo(ctx.CurLine)
elseif Phase == PH_LINES then -- request menu lines
local menuId = Menu.MenuId
if ctx.CurLine == -1 then
DSM_Send(0x13, 0x04, int16_MSB(menuId), int16_LSB(menuId)) -- GetFirstLine
else
DSM_Send(0x14, 0x06, int16_MSB(menuId), int16_LSB(menuId), 0x00, ctx.CurLine) -- line X
end
LOG_write("GetLines(LastLine=%d)\n", ctx.CurLine)
elseif Phase == PH_VALUES then -- request menu values
local menuId = Menu.MenuId
local valId = MenuLines[ctx.CurLine].ValId
DSM_Send(0x15, 0x06,
int16_MSB(menuId), int16_LSB(menuId),
int16_MSB(valId), int16_LSB(valId))
LOG_write("GetValues(LastVId=0x%04X)\n", valId)
elseif Phase == PH_VAL_CHANGING then -- send new value: Two steps, Update & Validate
local line = MenuLines[ctx.SelLine]
local valId = line.ValId
if Value_Change_Step == 0 then
local value = sInt16ToDsm(line.Val)
DSM_Send(0x18, 0x06,
int16_MSB(valId), int16_LSB(valId),
int16_MSB(value), int16_LSB(value)) -- send current values
LOG_write("ChangeValue(VId=0x%04X,Val=%d)\n", valId, value)
if line.Type == LT_LIST_VALIDATE then -- Incremental Validation??
Value_Change_Step = 1
Waiting_RX = 0 -- Do SEND in the next step
end
else
-- Validate Value
DSM_Send(0x19, 0x04, int16_MSB(valId), int16_LSB(valId))
Value_Change_Step = 0
Phase = PH_VAL_WAIT
LOG_write("ValidateValue(VId=0x%04X)\n", valId)
end
elseif Phase == PH_VAL_CHNG_END then
DSM_Send(0x1B, 0x04, 0x00, int16_LSB(ctx.SelLine))
Value_Change_Step = 0
Phase = PH_WAIT_CMD
LOG_write("ValueChangeEnd(L=%d)\n", ctx.SelLine)
elseif Phase == PH_VAL_WAIT then
-- Value Changing Wait
DSM_Send(0x1A, 0x04, 0x00, int16_LSB(ctx.SelLine))
LOG_write("ValueChangeWait(L=%d)\n", ctx.SelLine)
elseif Phase == PH_EXIT_REQ then -- EXIT Request
DSM_Send(0x1F, 0x02, 0xAA)
end
end
local function DSM_ProcessResponse()
local cmd = multiBuffer(11)
-- LOG_write("DSM_ProcessResponse BEGIN: Cmd=%x\n",cmd)
if cmd == 0x01 then -- read version
RX.Name = Get_RxName(multiBuffer(13))
RX.Version = multiBuffer(14) .. "." .. multiBuffer(15) .. "." .. multiBuffer(16)
--ctx.isReset = false -- no longer resetting
Menu.MenuId = 0
Phase = PH_TITLE
LOG_write("Version: %s %s\n", RX.Name, RX.Version)
elseif cmd == 0x02 then -- read menu title
local menu = Menu
menu.MenuId = Dsm_to_Int16(multiBuffer(12), multiBuffer(13))
menu.TextId = Dsm_to_Int16(multiBuffer(14), multiBuffer(15))
menu.Text = Get_Text(menu.TextId)
menu.PrevId = Dsm_to_Int16(multiBuffer(16), multiBuffer(17))
menu.NextId = Dsm_to_Int16(multiBuffer(18), multiBuffer(19))
menu.BackId = Dsm_to_Int16(multiBuffer(20), multiBuffer(21))
for i = 0, 6 do -- clear menu
MenuLines[i] = { MenuId = 0, Type = 0, TextId = 0, ValId = 0, Min = 0, Max = 0, Def = 0, Val = nil, Unit, Step }
end
ctx.CurLine = -1
ctx.SelLine = -1 -- highlight Back
LOG_write("Menu: Mid=0x%04X \"%s\"\n", menu.MenuId, menu.Text)
if (menu.MenuId == 0x0001) then -- Still in RESETTING MENU???
--menu.MenuId = 0
Phase = PH_RX_VER
else
Phase = PH_LINES
end
elseif cmd == 0x03 then -- read menu lines
local i = multiBuffer(14)
local type = multiBuffer(15)
local line = MenuLines[i]
ctx.CurLine = i
line.lineNum = i
line.MenuId = Dsm_to_Int16(multiBuffer(12), multiBuffer(13))
line.Type = type
line.TextId = Dsm_to_Int16(multiBuffer(16), multiBuffer(17))
line.Text = Get_Text(line.TextId)
line.ValId = Dsm_to_Int16(multiBuffer(18), multiBuffer(19))
-- Singed int values
line.Min = Dsm_to_SInt16(multiBuffer(20), multiBuffer(21))
line.Max = Dsm_to_SInt16(multiBuffer(22), multiBuffer(23))
line.Def = Dsm_to_SInt16(multiBuffer(24), multiBuffer(25))
if line.Type == LT_MENU then
-- nothing to do on menu entries
elseif isListLine(line) then
line.Val = nil --line.Def - line.Min -- use default value not sure if needed
line.Def = line.Min -- pointer to the start of the list in Text
line.Max = line.Max - line.Min -- max index
line.Min = 0 -- min index
else -- default to numerical value
line.Val = nil --line.Def -- use default value not sure if needed
if (line.Min == 0 and line.Max == 100) or (line.Min == -100 and line.Max == 100) or
(line.Min == 0 and line.Max == 150) or (line.Min == -150 and line.Max == 150) then
line.Type = LT_VALUE_PERCENT -- Override to Value Percent
end
end
if ctx.SelLine == -1 and isSelectable(line) then -- Auto select first selectable line of the menu
ctx.SelLine = ctx.CurLine
end
LOG_write("Line: #%d Vid=0x%04X T=0x%02X \"%s\"\n", i, line.ValId, type, line.Text)
Phase = PH_LINES
elseif cmd == 0x04 then -- read menu values
-- Identify the line and update the value
local valId = Dsm_to_Int16(multiBuffer(14), multiBuffer(15))
local value = Dsm_to_SInt16(multiBuffer(16), multiBuffer(17)) --Signed int
local updatedLine = nil
for i = 0, 6 do -- Find the menu line for this value
local line = MenuLines[i]
if line.Type ~= 0 then
if line.Type ~= LT_MENU and line.ValId == valId then -- identifier of ValueId stored in the line
line.Val = value
ctx.CurLine = i
updatedLine = line
local valueTxt = value
if isListLine(line) then
valueTxt = Get_Text_Value(line.Def + value) .. " [" .. value .. "]"
end
LOG_write("Update Value: #%d VId=0x%04X Value=%s\n", i, valId, valueTxt)
break
end
end
end
if (updatedLine == nil) then
LOG_write("Cannot Find Line for ValueId=%x\n", valId)
end
Phase = PH_VALUES
elseif cmd == 0x05 then -- Request TX info
ctx.CurLine = multiBuffer(12)
TX_Info_Type = multiBuffer(13)
TX_Info_Step = 0
Phase = PH_TX_INFO
LOG_write("TXInfoReq: Port=%d T=0x%02X\n", ctx.CurLine, TX_Info_Type)
elseif cmd == 0xA7 then -- answer to EXIT command
DSM_Release()
elseif cmd == 0x00 and Phase == PH_VAL_CHANGING then
Phase = PH_VAL_WAIT
end
--LOG_write("DSM_ProcessResponse END: Cmd=%x\n",cmd)
return cmd
end
local function DSM_Send_Receive()
if Waiting_RX == 0 then
Waiting_RX = 1
DSM_SendRequest()
multiBuffer(10, 0x00);
InactivityTime = getTime() + 200 -- Reset Inactivity timeout
-- -- -- -- -- -- -- -- -- -- -- -- receive part -- -- -- -- -- -- -- -- -- -- -- -- --
elseif multiBuffer(10) == 0x09 then
local cmd = DSM_ProcessResponse()
-- Data processed
multiBuffer(10, 0x00)
if (cmd > 0x00) then -- Any non NULL response
-- Only change to SEND mode if we received a valid response (Ignore NULL Responses, that are really heartbeat i most cases)
Waiting_RX = 0
InactivityTime = getTime() + 200 -- Reset Inactivity timeout
end
else -- No Send or Receive,
-- Check if enouth time has passed from last transmit/receive activity
if getTime() > InactivityTime then
InactivityTime = getTime() + 200
Waiting_RX = 0 -- Switch to Send mode to send heartbeat
if Phase == PH_EXIT_REQ then
DSM_Release()
end
if Phase ~= PH_RX_VER and Phase ~= PH_VAL_WAIT then
Phase = PH_WAIT_CMD
end
end
end
end
------------------------------------------------------------------------------------------------------------
local function showBitmap(x, y, imgDesc)
local f = string.gmatch(imgDesc, '([^%|]+)') -- Iterator over values split by '|'
local imgName, imgMsg = f(), f()
f = string.gmatch(imgMsg or "", '([^%:]+)') -- Iterator over values split by ':'
local p1, p2 = f(), f()
lcd.drawText(x, y, p1 or "", TEXT_ATTR) -- Alternate Image MSG
lcd.drawText(x, y + LCD_Y_LINE_HEIGHT, p2 or "", TEXT_ATTR) -- Alternate Image MSG
end
local function drawButton(x, y, text, active)
local attr = TEXT_ATTR
if (active) then attr = attr + INVERS end
lcd.drawText(x, y, text, attr)
end
local ver_rx_count = 0
local function DSM_Display()
lcd.clear()
--Draw RX Menu
if Phase == PH_RX_VER then
lcd.drawText(1, 0, "DSM Frwd Prog "..VERSION, INVERS)
local msgId = 0x300 -- Waiting for RX
if (ctx.isReset) then msgId=0x301 end -- Waiting for Reset
lcd.drawText(0, 3 * LCD_Y_LINE_HEIGHT, Get_Text(msgId), BLINK)
return
end
-- display Program version or RX version
local msg = RX.Name .. " v" .. RX.Version
if (ver_rx_count < 100) then
msg = RX.Name .. " v" .. RX.Version
ver_rx_count = ver_rx_count + 1
else
msg = "Frwd Prog "..VERSION
ver_rx_count = ver_rx_count + 1
if (ver_rx_count > 200) then ver_rx_count=0 end
end
lcd.drawText(30, LCD_Y_LOWER_BUTTONS, msg, TEXT_ATTR)
if Menu.MenuId == 0 then return end; -- No Title yet
-- Got a Menu
lcd.drawText(1, 0, Menu.Text, TEXT_ATTR + INVERS)
local y = LCD_Y_LINE_HEIGHT + 2
for i = 0, 6 do
local attrib = TEXT_ATTR
if (i == ctx.SelLine) then attrib = attrib + INVERS end -- Selected Line
local line = MenuLines[i]
if line ~= nil and line.Type ~= 0 then
local heading = Get_Text(line.TextId)
if (line.TextId >= 0x8000) then -- Flight mode
heading = " " .. Flight_Mode[0] .. " "
if (line.Val==nil) then heading = heading .. "--" else heading = heading .. ((line.Val or 0) + 1) end
else
local text = "-"
if line.Type ~= LT_MENU then -- list/value
if line.Val ~= nil then
if isListLine(line) then
local textId = line.Val + line.Def
text = Get_Text_Value(textId)
local imgDesc = List_Text_Img[textId]
if (imgDesc and i == ctx.SelLine) then -- Optional Image and Msg for selected value
showBitmap(0, 20, imgDesc)
end
elseif (line.Type == LT_VALUE_PERCENT) then
text = line.Val .. " %"
elseif (line.Type == LT_VALUE_DEGREES) then
text = line.Val .. " @"
else
text = line.Val
end
end -- if is Value
if (ctx.EditLine == i) then -- Editing a Line
attrib = BLINK + INVERS + TEXT_ATTR
end
lcd.drawText(LCD_X_MAX, y, text, attrib + RIGHT) -- display value
attrib = TEXT_ATTR
end
end -- Flight mode
lcd.drawText(0, y, heading, attrib) -- display text
end
y = y + LCD_Y_LINE_HEIGHT
end -- for
if Menu.BackId ~= 0 then
drawButton(LCD_X_RIGHT_BUTTONS, 0, "Back", ctx.SelLine == -1)
end
if Menu.NextId ~= 0 then
drawButton(LCD_X_RIGHT_BUTTONS, LCD_Y_LOWER_BUTTONS, "Next", ctx.SelLine == 7)
end
if Menu.PrevId ~= 0 then
drawButton(0, LCD_Y_LOWER_BUTTONS, "Prev", ctx.SelLine == 8)
end
end
local function load_msg_from_file(fileName, mem, Text, List_Text, List_Text_Img, RxName, Flight_Mode)
local function rtrim(s)
local n = string.len(s)
while n > 0 and string.find(s, "^%s", n) do n = n - 1 end
return string.sub(s, 1, n)
end
--print(string.format("Loading messages from [%s]",fileName))
local dataFile = io.open(fileName, "r") -- read File
-- cannot read file???
assert(dataFile, "Cannot load Message file:" .. fileName)
local data = io.read(dataFile, mem * 1024) -- read up to 10k characters (newline char also counts!)
io.close(dataFile)
collectgarbage("collect")
local lineNo = 0
for line in string.gmatch(data, "[^\r\n]+") do
lineNo = lineNo + 1
--print(string.format("Line [%d]: %s",lineNo,line))
-- Remove Comments
local s = string.find(line, "--", 1, true)
if (s ~= nil) then
line = string.sub(line, 1, s - 1)
end
line = rtrim(line)
if (string.len(line) > 0) then
local a, b, c = string.match(line, "%s*(%a*)%s*|%s*(%w*)%s*|(.*)%s*")
--print(string.format("[%s] [%s] [%s]",a,b,c))
if (a ~= nil) then
local index = tonumber(b)
if (index == nil) then
assert(false, string.format("%s:%d: Invalid Hex num [%s]", fileName, lineNo, b))
elseif (a == "T") then
Text[index] = c
elseif (a == "LT") then
List_Text[index] = c
elseif (a == "LI") then
List_Text_Img[index] = c
elseif (a == "FM") then
Flight_Mode[0] = c
elseif (a == "RX") then
RxName[index] = c
else
assert(false, string.format("%s:%d: Invalid Line Type [%s]", fileName, lineNo, a))
end
end
end
if (lineNo % 50 == 0) then
collectgarbage("collect")
end
end -- For
--print(string.format("Loaded [%d] messages",lineNo))
data = nil
end
local function clean_msg(Text, Flight_Mode)
local function clean_line(c)
if (c==nil) then return c end
local pos
c, pos = string.gsub(c, "/b$", "")
c, pos = string.gsub(c, "/c$", "")
c, pos = string.gsub(c, "/r$", "")
c, pos = string.gsub(c, "/p$", "")
c, pos = string.gsub(c, "/m$", "")
return c
end
-- Clean the line of special markers that are only used in color vesion
for i = 0, 0x0300 do
Text[i] = clean_line(Text[i])
collectgarbage("collect")
end
for i = 0, #Flight_Mode do
-- Clean the line of special markers that are only used in color vesion
Flight_Mode[i] = clean_line(Flight_Mode[i])
end
end
local function DSM_Init_Model()
MODEL.DSM_ChannelInfo= {[0]= -- Start array at position 0
{[0]= 0x00, 0x40}, -- Ch1 Thr (0x40)
{[0]= 0x00, 0x01}, -- Ch2 Ail (0x01)
{[0]= 0x00, 0x02}, -- Ch2 ElE (0x02)
{[0]= 0x00, 0x04}, -- Ch4 Rud (0x04)
{[0]= 0x00, 0x00}, -- Ch5 Gear (0x00)
{[0]= 0x00, 0x00}, -- Ch6 Aux1 (0x00)
{[0]= 0x00, 0x00}, -- Ch7 Aux2 (0x00)
{[0]= 0x00, 0x00}, -- Ch8 Aux3 (0x00)
{[0]= 0x00, 0x00}, -- Ch9 Aux4 (0x00)
{[0]= 0x00, 0x00} -- Ch10 Aux5 (0x00)
}
MODEL.modelOutputChannel = {[0]=
{min=1000, max=1000}, -- Ch1
{min=1000, max=1000}, -- Ch2
{min=1000, max=1000}, -- Ch3
{min=1000, max=1000}, -- Ch4
{min=1000, max=1000}, -- Ch5
{min=1000, max=1000}, -- Ch6
{min=1000, max=1000}, -- Ch7
{min=1000, max=1000}, -- Ch8
{min=1000, max=1000}, -- Ch9
{min=1000, max=1000} -- Ch10
}
end
------------------------------------------------------------------------------------------------------------
-- Init
local function DSM_Init()
LOG_open()
LOG_write("-------- NEW SESSION --------------------\n")
DSM_Init_Model()
--[[
if (ModelParam~=nil) then
LOG_write("Got MODEL PARAMETER... copying\n")
MODEL.DSM_ChannelInfo = ModelParam.DSM_ChannelInfo
else
LOG_write("NO-PARMETER --- Create DEFAULT")
end
--]]
collectgarbage("collect")
LOG_write("Mem before msg =%d\n",collectgarbage("count"))
load_msg_from_file(MSG_FILE, 10, Text, List_Text, List_Text_Img, RxName, Flight_Mode)
collectgarbage("collect")
LOG_write("Mem after msg =%d\n",collectgarbage("count"))
load_msg_from_file(MSG_FILE_MIN, 4, Text, List_Text, List_Text_Img, RxName, Flight_Mode)
collectgarbage("collect")
LOG_write("Mem after msg2 =%d\n",collectgarbage("count"))
clean_msg(Text,Flight_Mode)
collectgarbage("collect")
--Set protocol to talk to
multiBuffer(0, string.byte('D'))
--test if value has been written
if multiBuffer(0) ~= string.byte('D') then
error("Not enough memory!")
return 2
end
--Init TX buffer
multiBuffer(3, 0x00)
--Init RX buffer
multiBuffer(10, 0x00)
--Init telemetry
multiBuffer(0, string.byte('D'))
multiBuffer(1, string.byte('S'))
multiBuffer(2, string.byte('M'))
if (LCD_W > 128) then
TEXT_ATTR = 0
LCD_Y_LINE_HEIGHT = 25
LCD_X_MAX = 300
LCD_X_RIGHT_BUTTONS = LCD_X_MAX - 30
LCD_Y_LOWER_BUTTONS = (8 * LCD_Y_LINE_HEIGHT) + 2
end
end
------------------------------------------------------------------------------------------------------------
-- Main
local function DSM_Run(event)
if event == nil then
error("Cannot be run as a model script!")
return 2
else
DSM_Display()
DSM_Menu(event)
DSM_Send_Receive()
end
if Phase == PH_EXIT_DONE then
LOG_close()
return 2
else
return 0
end
end
return { init = DSM_Init, run = DSM_Run }

View File

@@ -0,0 +1,467 @@
# Forward Programing Protocol
## Introduction
DSM, DSMX and DSM Forward Programming are propietary protocol from the **Spektrum** radio brand. Since they don't make this information public, we have to reverse engineer it by analyzing the data exchanged between the RX and TX.
This document descrives what we know so far.
Thanks to **Pascal Langer** (Author of the Multi-Module) for the initial reverse engineering of the protocol and first version of the code that has been used for a while (Version 0.2)
Thanks to **Francisco Arzu** for taking the time to continue the work on reverse engineering, documenting and making the code more understandable.
New Capabilities in Version 0.5
- Log files of the conversation between RX/TX
- Improve the GUI (EdgeTX touch screen)
- Reversed engineer other things to make it work completly.
# Menu Title and Lines
The menu to be displayed is stored at the RX, the GUI only renders the menu title and menu lines received. The tipical conversation with the RX will be to ask for a menu (using the menuId number), and then wait for the data to come. The first thing will be the Menu (header) data, later we request the next 6 lines (one at a time), and optionally the values for each line.
A typical exchange will look like this in the log:
SEND DSM_getMenu(MenuId=0x1010 LastSelectedLine=0)
RESPONSE Menu: M[Id=0x1010 P=0x0 N=0x0 B=0x1000 Text="Gyro settings"[0xF9]]
SEND DSM_getFirstMenuLine(MenuId=0x1010)
RESPONSE MenuLine: L[#0 T=M VId=0x1011 Text="AS3X Settings"[0x1DD] MId=0x1010 ]
SEND DSM_getNextLine(MenuId=0x1010,LastLine=0)
RESPONSE MenuLine: L[#1 T=M VId=0x1019 Text="SAFE Settings"[0x1E2] MId=0x1010 ]
SEND DSM_getNextLine(MenuId=0x1010,LastLine=1)
RESPONSE MenuLine: L[#2 T=M VId=0x1021 Text="F-Mode Setup"[0x87] MId=0x1010 ]
SEND DSM_getNextLine(MenuId=0x1010,LastLine=2)
RESPONSE MenuLine: L[#3 T=M VId=0x1022 Text="System Setup"[0x86] MId=0x1010 ]
## Menu
The menu has the following information:
Menu: M[Id=0x1010 P=0x0 N=0x0 B=0x1000 Text="Gyro settings"[0xF9]]
- `MenuId`: The menu ID number of the menu (hex, 16 bit number)
- `PrevId`: The menu ID of the previous menu (for navigation), Log show as `"P="`
- `NextId`: The menu ID of the next menu (for navigation), Log shows as `"N="`
- `BackId`: The menu ID of the back menu (for navigation), Log shows as `"B="`
- `TextId`: The message number to display (16 bits, Hex). Log shows as [`0xXX`] after the message.
- `Text`: Retrived using the `TextId` from the script message `Text` array.
## Menu Lines
The menu lines has the following information:
L[#0 T=V_nc VId=0x1000 Text="Flight Mode"[0x8001] Val=1 [0->10,0] MId=0x1021 ]
L[#1 T=M VId=0x7CA6 Text="FM Channel"[0x78] MId=0x1021 ]
L[#2 T=LM VId=0x1002 Text="AS3X"[0x1DC] Val=1|"Act" NL=(0->1,0,S=3) [3->4,3] MId=0x1021 ]
- `MenuId`: of the menu they beling to. Log show as `"MId="` at the end.
- `LineNum`: Line number (0..5). The line number in the screen. Log show as # in the beginning
- `Type`: Type of Line, Log shows as `"T="` (explanation later)
- `TextId`: The message number to display (16 bits, Hex). Log shows as [`0xXXXX`] after the message.
- `Text`: Retrived using the `TextId` from the script message `Text` array.
- `ValueId`: The value or menu ID of the line. Log shows as `"VId="` (16 bits, Hex).
- `Value Range`: Shows as [`Min`->`Max`, `Default`]. This is the RAW data comming from the RX
- `NL`: Computed Normalized LIST (0 reference) for List Values. Source is the RAW range. For example, for lines of list of values. `[3->4,3]` is tranlated to `NL=(0->1,0,S=3)` since the value is also normalize to 0. `"S="` means the initial entry in the `List_Text` array
- `Val`: Current value for line who hold data. Relative to 0 for List Values. For List Values, the log will show the translation of the value to display text. example: `Val=1|"Act"` that is coming from `List_Value[4]`
## Type of Menu Lines
- `LINE_TYPE.MENU (Log: "T=M")`: This could be regular text or a navigation to another menu. if `ValueId` is the same as the current MenuId (`MId=`), is a plain text line (navigation to itself). If the `ValueId` is not the current menuId, then `ValueId` is the MenuId to navigate to.
We have found only one exception to the plain text rule, a true navigation to itself, in that case, in the text of the menu, you can use the "/M" flag at the end of the text to force it to be a menu button.
Example, FM_Channel is a navigation to menuId=0x7CA6.
L[#1 T=M VId=0x7CA6 Text="FM Channel"[0x78] MId=0x1021 ]
- `LINE_TYPE.LIST_MENU_NC (Log T=LM_nc)`: This is a line that shows as text in the GUI. The numeric value is translated to the proper text. The range is important, since it descrives the range of posible values. No incremental RX changes, only at the end.
Example: List of Values, List_Text[] starts at 53, ends at 85, with a default of 85. When normalized to 0, is a range from 0->32 for the numeric value. The Display value `Aux1` is retrive from `List_Text[6+53]`.
L[#0 T=LM_nc VId=0x1000 Text="FM Channel"[0x78] Val=6|"Aux1" NL=(0->32,0,S=53) [53->85,53] MId=0x7CA6 ]
- `LINE_TYPE.LIST_MENU_TOG (Log T=L_tog)`: Mostly the same as LIST_MENU_NC, but is just 2 values. (ON/OFF, Ihn/Act, etc). Should be a toggle in the GUI.
L[#2 T=LM_tog VId=0x1002 Text="AS3X"[0x1DC] Val=1|"Act" NL=(0->1,0,S=3) [3->4,3] MId=0x1021 ]
- `LINE_TYPE.LIST_MENU (Log T=LM)`: Mostly the same as LIST_MENU_NC, but incremental changes to the RX. Some times, it comes with a strange range `[0->244,Default]`. Usually this means that the values are not contiguos range; usually Ihn + Range. Still haven't found where in the data the correct range comes from.
Example: Valid Values: 3, 176->177 (Inh, Self-Level/Angle Dem, Envelope)
L[#3 T=LM VId=0x1003 Text="Safe Mode"[0x1F8] Val=176|"Self-Level/Angle Dem" NL=(0->244,3,S=0) [0->244,3] MId=0x1021 ]
- `LINE_TYPE.VALUE_NUM_I8_NC (Log: "T=V_nc")`: This line is editable, but is not updated to the RX incrementally, but only at the end. The Flight Mode line is of this type, so we have to check the TextId to differenciate between Flight mode and an Editable Value.
Fligh Mode TextId is between 0x8000 and 0x8003
Example, Flight mode comes from Variable ValId=0x1000, with current value of 1. Range of the Value is 0..10.
L[#0 T=V_nc VId=0x1000 Text="Flight Mode"[0x8001] Val=1 [0->10,0] MId=0x1021 ]
- `LINE_TYPE.VALUE_NUM_I8 (Log T=V_i8)`: 8 bit number (1 byte)
- `LINE_TYPE.VALUE_NUM_I16' (Log T=V_i16)`: 16 Bit number (2 bytes)
- `LINE_TYPE.VALUE_NUM_SI16 (Log T=V_si16)`: Signed 16 bit number (2 bytes)
- `LINE_TYPE.VALUE_PERCENT (Log T=L_%)`: Shows a Percent Value. 1 Byte value.
- `LINE_TYPE.VALUE_DEGREES (Log T=L_de)`: Shows a Degrees VAlue. 1 Byte value.
## LIST_TYPE Bitmap
TYPE|Sum|Hex|7 Signed|6 Valid Min/Max??|5 No-Inc-Changing|4 Menu|3 List-Menu|2 text / number|1|0 - 16 bits
|-|-|-|-|-|-|-|-|-|-|-
|MENU|Text|0x1C|0|0|0|1|1|1|0|0
|LIST_MENU|Text|0x0C|0|0|0|0|1|1|0|0
|LIST_MENU_TOG|Text|0x4C|0|1|0|0|1|1|0|0
|LIST_MENU_NC|Text, NC|0x6C|0|1|1|0|1|1|0|0
|VALUE_NUM_I8_NC|I8, NC|0x60|0|1|1|0|0|0|0|0
|VALUE_PERCENT|S8|0xC0|1|1|0|0|0|0|0|0
|VALUE_DEGREES|S8 NC|0xE0|1|1|1|0|0|0|0|0
|VALUE_NUM_I8|I8|0x40|0|1|0|0|0|0|0|0
|VALUE_NUM_I16|I16|0x41|0|1|0|0|0|0|0|1
|VALUE_NUM_SI16|S16|0xC1|1|1|0|0|0|0|0|1
## Important Behavioral differences when updating values
Values who are editable, are updated to RX as they change. For example, when changing attitude trims, the servo moves as we change the value in real-time.
LIST_MENU_NC, VALUE_NUM_I8_NC don't update the RX as it changes. It changes only in the GUI, and only update the RX at the end when confirmed the value. (NO-INC-CHANGES Bit)
After finishing updating a value, a validation command is sent. RX can reject the current value, and will change it to the nearest valid value.
## Special Menus
Seems like menuId=0x0001 is special. When you navigate to this menu, the RX reboots.
When this happens, we need to start from the beginning as if it was a new connection.
# Send and Receive messages
To comunicate with the Multi-Module, Lua scripts in OpenTx/EdgeTx has access to the `Multi_Buffer`. Writting to it will send data to RX, received data will be read from it.
For our specific case, this is how the Multi_Buffer is used:
|0..2|3|4..9|10..25
|--|--|--|--
|DSM|0x70+len|TX->RX data|RX->TX Data
To write a new DSM Fwd Programing command, write the data to address 4..9, and later set the address 3 with the length.
When receiving data, address 10 will have the message type we are receiving, or 0 if nothing has been received.
## Starting a new DSM Forward programming Connection
- Write 0x00 at address 3
- Write 0x00 at address 10
- Write "DSM" at address 0..2
## Disconnect
- Write 0x00 at address 0
# Request Messages (TX->RX)
## DSM_sendHeartbeat()
keep connection open.. We need to send it every 2-3 seconds, otherwise the RX will force close the connection by sending the TX an Exit_Confirm message.
|4|5|6|7|8|9|10
|--|--|--|--|--|--|--
Msg| Len? | ?? | ??
0x00|0x04|0x00|0x00
SEND DSM_sendHeartbeat()
DSM_SEND: [00 04 00 00 ]
## DSM_getRxVersion()
Request the RX information
|4|5|6|7|8|9|10
|--|--|--|--|--|--|--
Msg| Len? | ?? | ?? |??|??
0x11|0x06|0x00|0x14|0x00|0x00
SEND DSM_getRxVersion()
DSM_SEND: [11 06 00 14 00 00 ]
## DSM_getMainMenu()
Request data for the main menu of the RX
|4|5|6|7|8|9|10
|--|--|--|--|--|--|--
Msg| Len? | ?? | ?? |??|??
0x12|0x06|0x00|0x14|0x00|0x00
SEND DSM_getMainMenu()
DSM_SEND: [12 06 00 14 00 00 ]
## DSM_getMenu(menuId, lastSelLine)
Request data for Menu with ID=`menuId`. lastSelLine is the line that was selected to navigate to that menu. Most menus works with 0, but for some special "Enter Bind Mode", "Factory Reset", "Save to Backup" they will not work if we send 0, has to be the line who was selected in the confirmation menu line "Apply".
|4|5|6|7|8|9|10
|--|--|--|--|--|--|--
Msg|Len? | MSB (menuId) | LSB (MenuId) | MSB (line#)??| LSB (line#)
0x16|0x06|0x10|0x60|0x00|0x01
SEND DSM_getMenu(MenuId=0x1060 LastSelectedLine=1)
DSM_SEND: [16 06 10 60 00 01 ]
## DSM_getFirstMenuLine(menuId)
Request the first line of a menu identified as `menuId`. The response will be the first line of the menu. Some times, it return lines shown as `'MenuUknownLine_0x05'` that we still are trying to understand what they are for.
|4|5|6|7|8|9|10
|--|--|--|--|--|--|--
Msg|Len? | MSB (menuId) | LSB (MenuId)
0x13|0x04|0x10|0x60
SEND DSM_getFirstMenuLine(MenuId=0x1000)
DSM_SEND: [13 04 10 00 ]
## DSM_getNextMenuLine(menuId, curLine)
Request the retrival of the next line following the current line. Response is either the next line, or the next value, or nothing.
|4|5|6|7|8|9|10
|--|--|--|--|--|--|--
Msg|Len? | MSB (menuId) | LSB (MenuId) | MSB (line#)??| LSB (line#)
0x14|0x06|0x10|0x60|0x00|0x01
SEND DSM_getNextLine(MenuId=0x1000,LastLine=1)
DSM_SEND: [14 06 10 00 00 01 ]
## DSM_getNextMenuValue(menuId, valId, text)
Retrive the next value after the last `ValId` of the current `menuId`. text is just for debugging purposes to show the header of the value been retrived.
The Response is a Menu Value or nothing if no more data.
|4|5|6|7|8|9|10
|--|--|--|--|--|--|--
Msg|Len? | MSB (menuId) | LSB (MenuId) | MSB (ValId)| LSB (ValId)
0x15|0x06|0x10|0x61|0x10|0x00
SEND DSM_getNextMenuValue(MenuId=0x1061, LastValueId=0x1000) Extra: Text="Outputs"
DSM_SEND: [15 06 10 61 10 00 ]
## DSM_updateMenuValue(valId, val, text, line)
Updates the value identified as `valId` with the numeric value `val`. `text` and `line` are there to add debugging info. No response is expected.
If the value is negative, it has to be translated to the proper DSM negative representaion.
|4|5|6|7|8|9|10
|--|--|--|--|--|--|--
Msg|Len? | MSB (ValId) | LSB (ValId) | MSB (Value)| LSB (Value)
0x18|0x06|0x??|0x??|0x??|0x??
DSM_updateMenuValue(valId, val, text, line)
-->DSM_send(0x18, 0x06, int16_MSB(valId), int16_LSB(valId), int16_MSB(value), int16_LSB(value))
## DSM_validateMenuValue(valId, text, line)
Validates the value identified as `valId`. `text` and `line` are there to add debugging info. The RX can response an Update value if the value is not valid and needs to be corrected.
|4|5|6|7|8|9|10
|--|--|--|--|--|--|--
Msg|Len? | MSB (ValId) | LSB (ValId)
0x19|0x06|0x??|0x??
DSM_validateMenuValue(valId, text, line)
-> DSM_send(0x19, 0x06, int16_MSB(valId), int16_LSB(valId))
## DSM_menuValueChangingWait(valId, text, line)
Durin editing, this serves as a heartbeat that we are editing the value. The value identified as `valId`. `text` and `line` are there to add debugging info. The RX can response an Update value or a NUL response.
|4|5|6|7|8|9|10
|--|--|--|--|--|--|--
Msg|Len?? | MSB (ValId) | LSB (ValId)
0x1A|0x06|0x??|0x??
DSM_menuValueChangingWait(valId, text, line)
->DSM_send(0x1A, 0x06, int16_MSB(valId), int16_LSB(valId))
## DSM_exitRequest()
Request to end the DSM Frd Prog connection. Will reponse with an exit confirmation.
|4|5|6|7|8|9|10
|--|--|--|--|--|--|--
Msg|Len?? | ??
0x1F|0x02|0xAA
CALL DSM_exitRequest()
DSM_SEND: [1F 02 AA ]
# Response Messages (RX->TX)
All responses will have the a response byte in Multi_Buffer[10]=0x09, and the type of message in Multi_Buffer[11].
## RX Version Response
Returns the information about the current RX.
The Display text of name name of the RX is retrive from the `RX_Name` array.
|10|11|12|13|14|15|16
|--|--|--|--|--|--|--
|Resp|Msg|?? |RxId|Major|Minor|Patch
|0x09|0x01|0x00|0x1E|0x02|0x26|0x05
RESPONSE RX: 09 01 00 1E 02 26 05
RESPONSE Receiver=AR631 Version 2.38.5
## Menu Response
Returns the menu information to display and navigation.
The Display text for the menu is retrive from the `Text` array.
|10|11|12|13|14|15|16|17|18|19|20|21
|--|--|--|--|--|--|--|--|--|--|--|--
|Resp|Msg|LSB (menuId)|MSB (menuId)|LSB (TextId)|MSB (TextId)|LSB (PrevId)|MSB (PrevId)|LSB (NextId)|MSB (NextId)|LSB (BackId)|MSB (BackId)
|0x09|0x02|0x5E|0x10|0x27|0x02|0x00|0x00|0x00|0x00|0x00|0x10
RESPONSE RX: 09 02 5E 10 27 02 00 00 00 00 00 10 00 00 00 00
RESPONSE Menu: M[Id=0x105E P=0x0 N=0x0 B=0x1000 Text="Other settings"[0x227]]
## Menu Line Response
Returns the menu line information.
The Display text for the menu line is retrive from the `Text` array.
`Min`,`Max` and `Default` can be signed numbers.
|10|11|12|13|14|15|16|17|18|19|20|21|22|23|24|25
|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--
|Resp|Msg|LSB (menuId)|MSB (menuId)|Line#|Line Type|LSB (TextId)|MSB (TextId)|LSB (ValId)|MSB (ValId)|LSB (Min)|MSB (Min)|LSB (Max)|MSB (Max)|LSB (Def)|MSB (Def)
|0x09|0x03|0x61|0x10|0x00|0x6C|0x50|0x00|0x00|0x10|0x36|0x00|0x49|0x00|0x36|0x00
RESPONSE RX: 09 03 61 10 00 6C 50 00 00 10 36 00 49 00 36 00
RESPONSE MenuLine: L[#0 T=LM_nc VId=0x1000 Text="Outputs"[0x50] Val=nil NL=(0->19,0,S=54) [54->73,54] MId=0x1061 ]
## Menu Line Value Response
Returns the Value for a line.
The response updates the Value in the line identified by `ValId`.
The Display text for the Value, when it is a list, is retrive from the `List_Text` array.
|10|11|12|13|14|15|16|17
|--|--|--|--|--|--|--|--
|Resp|Msg|LSB (menuId)|MSB (menuId)|LSB (ValId)|MSB (ValId)|LSB (Value)|MSB (Value)
|0x09|0x04|0x61|0x10|0x00|0x10|0x00|0x00
RESPONSE RX: 09 04 61 10 00 10 00 00
RESPONSE MenuValue: UPDATED: L[#0 T=L_m0 VId=0x1000 Text="Outputs"[0x50] Val=0|"Throttle" NL=(0->19,0,S=54) [54->73,54] MId=0x1061 ]
## Exit Response
Response from a Exit Request.
|10|11
|--|--
|Resp|Msg
|0x09|0x07
RESPONSE RX: 09 A7
RESPONSE Exit Confirm
## NULL Response
Can be use as a response, or heartbeat from the RX to keep the connection open.
|10|11
|--|--
|Resp|Msg
|0x09|0x00
RESPONSE RX: 09 00
RESPONSE NULL
# Unknown Lines
TOTALLY UNKNOWN WHAT THIS ARE FOR.. but only works for the Main Menu..
Other menus they just loop on line=0 forever.
## DSM_getNextUknownLine_0x05(menuId, curLine)
Request the retrival of the next Unknown line following the current line. Response is either the next unknow line, next menu line, or the next value, or nothing.
|4|5|6|7|8|9| Comment
|--|--|--|--|--|--|--
Msg|Len? | Line# | Line# | 0x00 | Formula(line#)??
0x20|0x06|0x00|0x00|0x00|0x40 | LastLineLine=0 retrieval
0x20|0x06|0x01|0x01|0x00|0x01| LastLineLine=1 retrieval
0x20|0x06|0x02|0x02|0x00|0x02| LastLineLine=2 retrieval
0x20|0x06|0x03|0x03|0x00|0x04| LastLineLine=3 retrieval
0x20|0x06|0x04|0x04|0x00|0x00| LastLineLine=4 retrieval
0x20|0x06|0x05|0x05|0x00|0x00| LastLineLine=5 retrieval
## Unknown Line Response
We still don't know what is this for, but we have to retrive them and skip then. Works for main menu, but when it happens in another menus, usually we stay in an infinite loop retrieving line=0
|10|11|12|13|14|15|16|17
|--|--|--|--|--|--|--|--
|Resp|Msg|LSB (line#)
|0x09|0x05|0x00|0x01|0x00|0x00|0x00|0x07
|0x09|0x05|0x01|0x01|0x00|0x00|0x00|0x07
## Interaction on Main Menu
This is the normal interaction for the main menu. As you can see, it iterates on the 6 Unknow lines (0..5), and afterwards, it starts sending normal menu lines.
SEND DSM_getFirstMenuLine(MenuId=0x1000)
RESPONSE MenuUknownLine_0x05: LineNum=0 DATA=RX: 09 05 00 01 00 00 00 07 00 00 00 00 00 00 00 00
CALL DSM_getNextUknownLine_0x05(LastLine=0)
RESPONSE MenuUknownLine_0x05: LineNum=1 DATA=RX: 09 05 01 01 00 00 00 07 00 00 00 00 00 00 00 00
CALL DSM_getNextUknownLine_0x05(LastLine=1)
RESPONSE MenuUknownLine_0x05: LineNum=2 DATA=RX: 09 05 02 01 00 00 00 07 00 00 00 00 00 00 00 00
CALL DSM_getNextUknownLine_0x05(LastLine=2)
RESPONSE MenuUknownLine_0x05: LineNum=3 DATA=RX: 09 05 03 01 00 00 00 07 00 00 00 00 00 00 00 00
CALL DSM_getNextUknownLine_0x05(LastLine=3)
RESPONSE MenuUknownLine_0x05: LineNum=4 DATA=RX: 09 05 04 01 00 00 00 07 00 00 00 00 00 00 00 00
CALL DSM_getNextUknownLine_0x05(LastLine=4)
RESPONSE MenuUknownLine_0x05: LineNum=5 DATA=RX: 09 05 05 01 00 00 00 07 00 00 00 00 00 00 00 00
CALL DSM_getNextUknownLine_0x05(LastLine=5)
RESPONSE MenuLine: L[#0 T=M VId=0x1010 Text="Gyro settings"[0xF9] MId=0x1000 ]
## Other menus
If it hapen on other menus. Usualy stays in an infinite loop until it crash/exits.
The screen will show **"Error: Cannot Load Menu Lines from RX"**
The log will look like:
DSM_getMenu(MenuId=0x104F LastSelectedLine=1)
RESPONSE Menu: M[Id=0x104F P=0x0 N=0x0 B=0x1000 Text="First Time Setup"[0x4A]]
SEND DSM_getFirstMenuLine(MenuId=0x104F)
RESPONSE MenuUknownLine_0x05: LineNum=0 DATA=RX: 09 05 00 01 00 00 00 07 00 00 00 00 00 00 00 00
CALL DSM_getNextUknownLine_0x05(LastLine=0)
RESPONSE MenuUknownLine_0x05: LineNum=0 DATA=RX: 09 05 00 01 00 00 00 07 00 00 00 00 00 00 00 00
ERROR: Received Same menu line
CALL DSM_getNextUknownLine_0x05(LastLine=0)
RESPONSE MenuUknownLine_0x05: LineNum=0 DATA=RX: 09 05 00 01 00 00 00 07 00 00 00 00 00 00 00 00
ERROR: Received Same menu line
We found that sometimes, Overriding LastSelectedLine to 0 solves the problem for some specific menus. Not for all (for other, is the oposite (0->1)). But at least no unknown lines are returned with this hack for AR631/AR637. Maybe others also needed.
**Overriding to Zero is not a good solution for every menu. Some menus needs the LastLine to know the behaviour (for example, Factory Reset the RX, Save Backup, Restore Backup, Enter Bind Mode, Some sensor Calibration). Thats why we cannot do it blindly.**
Here is the current code to fix some of this problems in AR631/AR637.
Function `DSM_SelLine_HACK()`
if (ctx.RX.Id == RX.AR637T or ctx.RX.Id == RX.AR637TA or ctx.RX.Id == RX.AR631) then
-- AR631/AR637 Hack for "First time Setup" or
-- "First Time AS3X Setup", use 0 instead of the ctx.SelLine=5
if (ctx.Menu.MenuId == 0x104F or ctx.Menu.MenuId==0x1055) then
LOG_write("First time Setup Menu HACK: Overrideing LastSelectedLine to ZERO\n")
ctx.SelLine = 0
end
-- DID NOT WORK: AR631/AR637 Hack for "Relearn Servo Settings", use 1 instead
-- of the ctx.SelLine=0
--if (ctx.Menu.MenuId == 0x1023) then
-- LOG_write("Relearn Servo Settings HACK: Overrideing LastSelectedLine to 1\n")
-- ctx.SelLine = 1
--end
Now it retrives properly the menu:
Log shows:
First time Setup Menu HACK: Overrideing LastSelectedLine to ZERO
DSM_getMenu(MenuId=0x104F LastSelectedLine=0)
RESPONSE Menu: M[Id=0x104F P=0x0 N=0x0 B=0x105E Text="First Time Setup"[0x4A]]
SEND DSM_getFirstMenuLine(MenuId=0x104F)
.. Good menu data

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,15 @@
-- OVERRIDES Messges for MIN 128x64 screns
-- FORMAT <LineType>|<Msg#>|<Text>
-- Line Type: Text for Menus (T), List_Text Options (LT), List_Text_Image (LI), Flight Mode (FM), RX Name (RX)
-- IMPORTANT: NO EMPTY LINES
--
T |0x0097|DONT USE: Factory Reset
T |0x0098|DONT USE: Factory Reset
T |0x00A5|DONT USE: First Time Setup
T |0x00B0|Self-Lev/Ang Dem
T |0x00CD|Level model & capt attitude
T |0x0190|DONT USE: Relearn Servo Settings
T |0x020D|DONT USE: First Time SAFE Setup
T |0x0254|Pos = Up, Neg = Down
T |0x0267|Pos = Nose Up/Roll Right
T |0x0268|Neg = Nose Down/Roll Left

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 728 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 721 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 803 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 679 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 755 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 817 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 679 B

View File

@@ -0,0 +1,375 @@
-- FORMAT <LineType>|<Msg#>|<Text>
-- Line Type: Text for Menus (T), List_Text Options (LT), List_Text_Image (LI), Flight Mode (FM), RX Name (RX)
-- NO EMPTY LINES
-- Formmatting at end of line: /c=Center, /r=Right, /b=Bold, /m=menu
LT|0x0001|Off
LT|0x0002|On
-- Ihn/Act List Options
LT|0x0003|Inh
LT|0x0004|Act
--
-- Channel selection for SAFE MODE and GAINS on FC6250HX
LT|0x000C|Inhibit?
LT|0x000D|Ch5
LT|0x000E|Ch6
LT|0x000F|Ch7
LT|0x0010|Ch8
LT|0x0011|Ch9
LT|0x0012|Ch10
LT|0x0013|Ch11
LT|0x0014|Ch12
--
-- Servo Output values
LT|0x002D|5.5ms
LT|0x002E|11ms
LT|0x002F|22ms
--
-- Gain Multiplier Values
LT|0x0032|1 X
LT|0x0033|2 X
LT|0x0034|4 X
--
LT|0x0035|Inh?
LT|0x0036|Thr
LT|0x0037|Ail
LT|0x0038|Ele
LT|0x0039|Rud
LT|0x003A|Ch5
LT|0x003B|Ch6
LT|0x003C|Ch7
LT|0x003D|Ch8
LT|0x003E|Ch9
LT|0x003F|Ch10
LT|0x0040|Ch11
LT|0x0041|Ch12
LT|0x0042|Ch13
LT|0x0043|Ch14
LT|0x0044|Ch15
LT|0x0045|Ch16
LT|0x0046|Ch17
LT|0x0047|Ch18
LT|0x0048|Ch19
LT|0x0049|Ch20
--
T |0x0040|Roll
T |0x0041|Pitch
T |0x0042|Yaw
T |0x0043|Gain/c/b
T |0x0045|Differential
T |0x0046|Priority
T |0x0049|Output Setup
T |0x004A|Failsafe
T |0x004B|Main Menu
T |0x004E|Position
--
T |0x0050|Outputs
T |0x0051|Output Channel 1
T |0x0052|Output Channel 2
T |0x0053|Output Channel 3
T |0x0054|Output Channel 4
T |0x0055|Output Channel 5
T |0x0056|Output Channel 6
--
-- FailSafe Options
--LT|0x005E|Inhibit
LT|0x005F|Hold Last
LT|0x0060|Preset
--LT|0x0061|Custom
--
T |0x0071|Proportional
T |0x0072|Integral
T |0x0073|Derivate
--
T |0x0078|FM Channel
--
T |0x0080|Orientation
T |0x0082|Heading
T |0x0085|Frame Rate
T |0x0086|System Setup
T |0x0087|F-Mode Setup
T |0x0088|Enabled F-Modes
T |0x0089|Gain Channel
T |0x008A|Gain Sensitivity/r -- Right Align
T |0x008B|Panic
T |0x008E|Panic Delay
--
LT|0x008D|560hz
--
-- FC6250HX: Callibration Menu -> Begin..Start, Complete, Done
T |0x0091|Begin
T |0x0090|Apply
T |0x0092|Start
T |0x0093|Complete
T |0x0094|Done
--
T |0x0097|Factory Reset
T |0x0098|Factory Reset
--
T |0x0099|Advanced Setup
T |0x009A|Capture Failsafe Positions
T |0x009C|Custom Failsafe
--
T |0x009F|Save Settings -- Save & Reboot RX
--
T |0x00A5|First Time Setup
T |0x00AA|Capture Gyro Gains
T |0x00AD|Gain Channel Select
T |0x00AF|Dynamic
T |0x00B0|Self-Level/Angle Dem
T |0x00B1|Envelope
--
-- Flight Modes List Options
LT|0x00B5|Inhibit
LT|0x00B6|FM1
LT|0x00B7|FM2
LT|0x00B8|FM3
LT|0x00B9|FM4
LT|0x00BA|FM5
LT|0x00BB|FM6
LT|0x00BC|FM7
LT|0x00BD|FM8
LT|0x00BE|FM9
LT|0x00BF|FM10
--
T |0x00BE|Unknown_BE -- Used in Reset menu (0x0001) while the RX is rebooting
--
T |0x00C7|Calibrate Sensor
T |0x00CA|SAFE/Panic Mode Setup
--
T |0x00CD|Level model and capture attitude/m -- SPECIAL MENU to itself who is not a comment
--
-- RX Orientations for AR631/AR637, Optionally attach an Image + Alt Text to display
LT|0x00CB|Pos 1
LI|0x00CB|rx_pos_1.png|Pilot View: RX Label Up, Pins Back
LT|0x00CC|Pos 2
LI|0x00CC|rx_pos_2.png|Pilot View: RX Label Left, Pins Back
LT|0x00CD|Pos 3
LI|0x00CD|rx_pos_3.png|Pilot View: RX Label Down, Pins Back
LT|0x00CE|Pos 4
LI|0x00CE|rx_pos_4.png|Pilot View: RX Label Right, Pins Back
LT|0x00CF|Pos 5
LI|0x00CF|rx_pos_5.png|Pilot View: RX Label UP, Pins to Front
LT|0x00D0|Pos 6
LI|0x00D0|rx_pos_6.png|Pilot View: RX Label Left, Pins Front
LT|0x00D1|Pos 7
LI|0x00D1|rx_pos_7.png|Pilot View: RX Label Down, Pins Front
LT|0x00D2|Pos 8
LI|0x00D2|rx_pos_8.png|Pilot View: RX Label Right, Pins Front
LT|0x00D3|Pos 9
LI|0x00D3|rx_pos_9.png|Pilot View: RX Label Up, Pins Left
LT|0x00D4|Pos 10
LI|0x00D4|rx_pos_10.png|Pilot View: RX Label Back, Pins Left
LT|0x00D5|Pos 11
LI|0x00D5|rx_pos_11.png|Pilot View: RX Label Down, Pins Left
LT|0x00D6|Pos 12
LI|0x00D6|rx_pos_12.png|Pilot View: RX Label Front, Pins Left
LT|0x00D7|Pos 13
LI|0x00D7|rx_pos_13.png|Pilot View: RX Label Up, Pins Right
LT|0x00D8|Pos 14
LI|0x00D8|rx_pos_14.png|Pilot View: RX Label Back, Pins Right
LT|0x00D9|Pos 15
LI|0x00D9|rx_pos_15.png|Pilot View: RX Label Down, Pins Right
LT|0x00DA|Pos 16
LI|0x00DA|rx_pos_16.png|Pilot View: RX Label Front, Pins Right
LT|0x00DB|Pos 17
LI|0x00DB|rx_pos_17.png|Pilot View: RX Label Back, Pins Down
LT|0x00DC|Pos 18
LI|0x00DC|rx_pos_18.png|Pilot View: RX Label Left, Pins Down
LT|0x00DD|Pos 19
LI|0x00DD|rx_pos_19.png|Pilot View: RX Label Front, Pins Down
LT|0x00DE|Pos 20
LI|0x00DE|rx_pos_20.png|Pilot View: RX Label Right, Pins Down
LT|0x00DF|Pos 21
LI|0x00DF|rx_pos_21.png|Pilot View: RX Label Back, Pins Up
LT|0x00E0|Pos 22
LI|0x00E0|rx_pos_22.png|Pilot View: RX Label Left, Pins Up
LT|0x00E1|Pos 23
LI|0x00E1|rx_pos_23.png|Pilot View: RX Label Front, Pins Up
LT|0x00E2|Pos 24
LI|0x00E2|rx_pos_24.png|Pilot View: RX Label Right, Pins Up
LT|0x00E3|Pos Invalid
LI|0x00E3|rx_pos_25.png|Cannot detect orientation of RX
--
T |0x00D1|Receiver will Reboot/b
T |0x00D2|Panic Channel
T |0x00D3|Swashplate
T |0x00D5|Agility
T |0x00D8|Stop
T |0x00DA|SAFE/c/b -- Center + Bold
T |0x00DB|Stability
T |0x00DC|@ per sec
T |0x00DD|Tail rotor
T |0x00DE|Setup
T |0x00DF|AFR
T |0x00E0|Collective
T |0x00E1|Subtrim
T |0x00E2|Phasing
T |0x00E4|E-Ring
T |0x00E5|Swash Type
T |0x00E6|Travel
T |0x00E7|Left
T |0x00E8|Right
--
LT|0x00F2|Fixed
LT|0x00F3|Adjustable
--
T |0x00F6|Direction
T |0x00F8|Settings -- ?? validate on a Spektrum radio
T |0x00F9|Gyro settings
T |0x00FE|Stick Priority/c/b
--
T |0x0100|Make sure the model has been
T |0x0101|configured, including wing type,
T |0x0102|reversing, travel, trimmed, etc.
T |0x0103|before continuing setup.
T |0x0104| -- Blank
--
T |0x0106|Any wing type, channel assignment,
T |0x0107|subtrim, or servo reversing changes
T |0x0108|require running through initial
T |0x0109|setup again.
T |0x010A| -- Blank
--
T |0x0190|Relearn Servo Settings
T |0x019C|Enter Receiver Bind Mode
T |0x01AA|Offset
T |0x01D7|SAFE Select Channel
T |0x01DC|AS3X/c/b -- Center + Bold
T |0x01DD|AS3X Settings
T |0x01DE|AS3X Gains
T |0x01E0|Rate Gains/c/b
T |0x01E2|SAFE Settings
T |0x01E3|SAFE Gains
T |0x01E6|Attitude Trim/c/b
T |0x01E7|Envelope
T |0x01E9|Roll Right
T |0x01EA|Roll Left
T |0x01EB|Pitch Down
T |0x01EC|Pitch Up
T |0x01EE|Thr to Pitch
T |0x01EF|Low Thr to Pitch/c/b
T |0x01F0|High Thr to Pitch/c/b
T |0x01F3|Threshold
T |0x01F4|Angle
T |0x01F6|Failsafe Angles/c/b
T |0x01F8|Safe Mode
T |0x01F9|SAFE Select
T |0x01FC|Panic F-Mode
T |0x01FD|FailSafe Flight Mode -- Safe Flight Mode
T |0x0201|Throttle
T |0x0204|Hover
T |0x0208|Decay
T |0x0209|Save to Backup
T |0x020A|Restore from Backup
T |0x020D|First Time SAFE Setup
--
-- First time safe setup Page 3 :
T |0x020E|AS3X gains must be tuned
T |0x020F|and active in SAFE Flight Modes
T |0x0210|to help reduce wobble.
T |0x0211| -- Blank
T |0x0212| -- Blank
T |0x0213| -- Blank
--
-- AS3X orientation Setting menu (Level)
T |0x021A|Set the model level,
T |0x021B|and press Continue.
T |0x021C| -- Blank
T |0x021D| -- Blank
--
-- AS3X orientation Setting menu (Nose down)
T |0x021F|Set the model on its nose,
T |0x0220|and press Continue. If the
T |0x0221|orientation on the next
T |0x0222|screen is wrong go back
T |0x0223|and try again.
--
T |0x0224|Continue
T |0x0226|Angle Limits/c/b
T |0x0227|Other settings
T |0x0229|Set Orientation Manually
--
-- Factory Default Warning
T |0x022B|WARNING!
T |0x022C|This will reset the
T |0x022D|configuration to factory
T |0x022E|defaults. This does not
T |0x022F|affect the backup config.
T |0x0230| -- Blank
--
-- Backup Warning
T |0x0231|This will overwrite the
T |0x0232|backup memory with your
T |0x0233|current configuartion.
T |0x0234| -- Blank
T |0x0235| -- Blank
--
-- Restore from Backup Warning
T |0x0236|This will overwrite the
T |0x0237|current config with
T |0x0238|that which is in
T |0x0239|the backup memory.
T |0x023A| -- blank line
--
-- Utilities Copy flight modes
T |0x023D|Copy F-Mode Settings
T |0x023E|Source F-Mode
T |0x023F|Target F-Mode
--
T |0x0240|Utilities
--
-- Gain Capture Page
T |0x024C|Gains will be captured on
T |0x024D|Captured gains will be
T |0x024E|Gains on
T |0x024F|were captured and changed
T |0x0250|from Adjustable to Fixed
--
-- Utilities, Copy flight mode (Copy Confirmation, oveerriding FM)
T |0x0251|Are you sure you want to ovewrite the "Target"
T |0x0252|with the "Source" ?
T |0x0253| -- Blank
--
T |0x0254|Postive = Up, Negative = Down
--
-- First time safe setup Page 1 (maybe ask to select Flight Mode cannel)
T |0x0255|Before setting up SAFE
T |0x0256|a Flight Mode channel
T |0x0257|most be configured.
--
-- First time safe setup Page 2 (something related for flight mode)
T |0x025A|Select the desired flight mode
T |0x025B|switch position to adjust settings
T |0x025C|for each flight mode
T |0x025D| -- Blank
T |0x025E| -- Blank
--
-- Utilities, Copy flight mode (Confirm)
T |0x0259|YES
T |0x0260|WARNING: "Target"
T |0x0261|F-Mode will be overwritten
T |0x0262|by "Source"
--
T |0x0263|Fixed/Adjustable Gains/c/b
T |0x0266|Heading Gain/c/b
T |0x0267|Positive = Nose Up/Roll Right
T |0x0268|Negative = Nose Down/Roll Left
T |0x0269|SAFE - Thr to Pitch
T |0x026A|Use CAUTION for Yaw gain!/b
--
T |0x0300|No compatible DSM RX...
T |0x0301|Waiting for RX to Restart
--
FM|0x8000|Flight Mode/c/b
--
RX|0x0001|AR636
RX|0x0014|SPM4651T
RX|0x0015|AR637T
RX|0x0016|AR637TA
RX|0x0018|FC6250HX
RX|0x0019|AR630
RX|0x001A|AR8360T
RX|0x001B|AR8020T
RX|0x001C|AR10360T
RX|0x001E|AR631

View File

@@ -0,0 +1,227 @@
# Credits
Code is based on the code/work by: Pascal Langer (Author of the Multi-Module)
Rewrite/Enhancements by: Francisco Arzu
Thanks to all the people volunteered to test it.
# Introduction (v0.54)
This script library enhances the original DSM Forward Programming tool. DSM Forward Programming is needed to setup many of the new Spektrum Receivers with Gyro AS3X/SAFE features. For the Gyro (/Safe) to correct the plane in flight, it needs to move the right surfaces therefore the RX needs to know the configuration of the plane (Wing Type, Tail Type, Mixers, Servo Assignments, Servo Reverse). That info tells the RX where the aileron(s) are (one or two), where the elevator(s) are (one or two), V-Tail, Delta Wing, etc.
Since EdgeTx/OpenTx doesnt have an equivalent setup that is stored in the radio, we have to create our own version. This info is stored inside the `/MODELS/DSMDATA` directory/folder (which needs to be created by manually).
During `"Gyro Settings->initial setup"`, the RX asks the TX for model information behind the scenes. After setup, `"Gyro Settings->System Tools-> Relearn Servo Settings"` requests the TX configuration and stores it in the RX.
# Deployment
Make sure to manually create `/MODELS/DSMDATA` . The script will complain at startup if it does not exist. Here the script saves the Spektrun settings for each of your models.
Uncompress the Zip file (ZIP version) into your local computer.
In another window, open your TX SDCard and go to /SCRIPTS/TOOLS.
When upgrading from a previous version of this tool, delete your /SCRIPTS/TOOLS/DSMLIB before copying the new one (if you customized your images, inside "DSMLIB/img" do a backup first)
Copy the entire DSMLIB folder.
Copy the main script you want to use (Color or B&W).
Your TX SDCard should looks like this:
/SCRIPTS/TOOLS
DSM FwdPrg_05_BW.lua -- black/white text only
DSM FwdPrg_05_Color.lua -- Color and touch radios
DSM FwdPrg_05_MIN.lua -- `NEW!` Minimalistic version for radios with LOW memory (cannot setup new planes)
/SCRIPTS/TOOLS/DSMLIB/ -- (ALL CAPITALS) Libraries ane extra files
DsmFwPrgLib.lua -- DSM Protocol Message and Menu engine
DsmFwPrgSIMLib.lua -- Simulation of AR631, FC6250HX (For GUI development)
SetupLib.lua -- Model Setup Screens
msg_fwdp_en.txt -- `NEW!` Messages for forward programing externalized. To support other langs
/SCRIPTS/TOOLS/DSMLIB/img -- Images for RX orientations
Other Directories
/MODELS/DSMDATA --(ALL CAPITALS) Data of model config (Wing Type, Servo Assignments)
/LOGS/dsm_log.txt --Readable log of the last RX/TX session, usefull for debugging problems
When upgrading from a previous version of this tool, delete your /SCRIPTS/TOOLS/DSMLIB before copying the new one (if you customized your images, inside "DSMLIB/img" do a backup first)
# Common Questions
1. `RX not accepting channels higher than Ch6 for Flight-mode o Gains:`
V0.53 and newer: The RX is listening to channel changes for this options. Configure the Switch to the channel, togling once the switch will select the channel on the menu field.
2. `Why Ch1 says Ch1 (TX:Ch3/Thr)?`:
Radios with Multi-Module are usually configured to work the standard AETR convention. Spektrum uses TAER. The multi-module does the conversion when transmitting the signals. So `Spektrum Ch1 (Throttle)` really comes from the `TX Ch3`. We show both information (+name from the TX output). If your multi-module/radio is setup as TAER, the script will not do the re-arrangement.
3. `If i change the model name, the original model settings are lost.` This is correct, the model name is used to generate the file name (inside /MODEL/DSMDATA) who stores the model configuration. Currently EdgeTx and OpenTX has differt features where i could get either the Model Name or the YAML file where the EdgeTX model configuration is stored.. to keep the code compatible, the model name is used.
4. `Reversing a channel in my TX do not reverse the AS3X/SAFE reaction.` Correct, the channel stick direction and the Gyro direction are two separate things.
4.1: First, you have setup your model so that the sticks and switches moves the surfaces in the right direction.
4.2: Go to the script, `Model Setup` and setup your wing type, tail type, and select the channel assigment for each surface. Leave the servo settings the same as the values in the TX to start.
4.3: AR63X family: Go to `Forward programming->Gyro Setting->Initial Setup` (New/factory reset), or `Forward programming->Gyro Setting->System Setup->Relearn Servo Settings` (not new RX). This will load your current Gyro servo settings into the plane's RX.
4.4: Verify that the AS3X and SAFE reacts in the proper direction. You can use the Flight mode confugured as "Safe Mode: Auto-Level" to see if it moves the surfaces in the right direction.
4.5: If a surface don't move in the right direction, go to the `Model Setup->Gyro Channel Reverse` to reverse the Gyro on the channels needed, and do again the `Forward programming->Gyro Setting->System Setup->Relearn Servo Settings` to tranfer the new settings to the RX.
4.6: Specktrum TX always passes the TX servo reverse as the Gyro Reverse, but on many OpenTX/EdgeTX radios, the Rud/Ail are usually reversed by default compared to Specktrum. So far i don't think that i can use this as a rule, that is why the `Gyro Channel Reverse` page exist.
---
---
# Changes and fixes
V0.54:
1. Fix a problem in the Attitude Trim page (`Gyro Settings->System Setup->SAFE/Panic Setup->Attitude Trim`). It was not saving the values after exiting the menu. This is to change what SAFE considers "Level" flying.
2. Wings 2-Ail 2-Flaps had a bug on the 2nd flap.
3. New Minimalistic script (`DsmFwdPrg_05_MIN.lua`): For radios with very low memory (FrSky QX7, RM Zorro, others). It can only change existing settings, but does not have the Plane Setup menus to setup a completly new plane. In some radios, the very first time it runs (compile + run), it might give you a `not enouth memory` error.. try to run it again.
4. External menu message file (DSMLIB/msg_en.txt and msg_MIN_es.txt). Intial work to do localization and different languages.
V0.53:
1. Improved channel selection (Flight mode, Panic Channel, Gains Channel). Now during editing a channel, you can select any channel (>Ch4). Also, of you toggle the switch/channel it will populate the screen.
2. Support for smaller screens (128x64) in B&W. The problem with this older radios is memory. In some, it does not have enouth memory to load the additional DSMLIB libraries.
3. Fix formatting problem with some TX channel names who could affect the screen.. for example, rud channel should show "Ch4/rud", but shows "Ch4ud" because /r is for right justify formatting on messages. Now the formatting is only if it appears at the end of the message.
V0.52:
1. Menus to be able to configure Plane in a similar way as Spektrum Radio (v0.52)
2. Make "Gyro Settings"->"Initial Setup" works (Tested on AR631,AR637xx with PLANE type of aircraft)
3. Properly reset and restart after initial configuration and SAFE changes.
4. Write Log of the conversation between RX/TX. To be used for debugging a problem is reported.
5. Provide a simulation of RX to do GUI development in Companion, and understand patterns of how the data is organized.
# Tested Hardware
- AR631/AR637xx
- FC6250HX (Blade 230S V2 Helicopter)
- AR636 (Blade 230S V1 Heli firmware 4.40)
- Radiomaster TX16S (All versions)
- FrSky QX7, Radimaster Boxter (Minimalistic version)
Please report if you have tested it with other receivers to allow us to update the documentation. Code should work up to 10 channels for the main surfaces (Ail/Ele/etc). All Spektrum RX are internally 20 channels, so you can use Ch7 for Flight Mode even if your RX is only 6 channels (See common Questions)
# Messages Displayed in the GUI
If in a screen you get text that looks like `Unknown_XX` (ex: Unknown_D3), that message has not been setup in the script in english. If you can determine what the proper message is, you can send us a message to be added to the library.
The `XX` represents a Hex Number (0..9,A..F) message ID.
### Version 0.53 and older:
If you want to fix it in your local copy, all messages are towards the end in the file `SCRIPT\TOOS\DSMLIB\DsmFwPrgLib.lua`. Messages for Headers are stored in `Text` and messages for Options are stored in `List_Text`. Lua scripts are text files, and can be edited with Notepad or equivalent.
Portion of DsmFwPrgLib.lua:
Text[0x0097] = "Factory Reset"
Text[0x0098] = "Factory Reset" -- FC6250HX: Title
Text[0x0099] = "Advanced Setup"
Text[0x009A] = "Capture Failsafe Positions"
Text[0x009C] = "Custom Failsafe"
Text[0x009F] = "Save & Reset RX" -- TODO: Find the Proper Spektrum Value ??
Text[0x00A5] = "First Time Setup"
Text[0x00AA] = "Capture Gyro Gains"
Text[0x00AD] = "Gain Channel Select"
-- Safe mode options, Inhibit + the values
local safeModeOptions = {0x0003,0x00B0,0x00B1} -- inh (gap), "Self-Level/Angle Dem, Envelope
List_Text[0x00B0] = "Self-Level/Angle Dem"
List_Text[0x00B1] = "Envelope"
For example, if you get `Unknown_9D` in the GUI and your now that it should say **NEW Text**, you can edit the lua script to look like this:
Text[0x009A] = "Capture Failsafe Positions"
Text[0x009C] = "Custom Failsafe"
Text[0x009D] = "NEW Text" -- NEW Text added for AR98xx
Text[0x009F] = "Save & Reset RX" -- TODO: Find the proper Spektrum text
### Version 0.54 and newer:
The menu messages are stored in DSMLIB/msg_fwdp_en.txt (For english). Just add the message there. MIN_msg_fwdp_en.txt has shorter messages overrides for screens who are smaller (for minimalistic 128x64 version). The reference to the message file is at the file `/DSMLIB/DsmFwPrgLib.lua` if you want to change to use another language.
T |0x0097|Factory Reset
LT|0x00B0|Self-Level/Angle Dem
LT|0x00B1|Envelope
# LOG File
The log file of the last use of the script is located at `/LOGS/dsm_log.txt`. **It is overridden on every start to avoid filling up the SD card**. So if you want to keep it, copy or rename it before starting the script again. (it can be renamed in the TX by browsing the SD card)
The log is human readable. The first number is the number of seconds since the start, and then what is the current state of the Library, and what has been sent and received. The info in the log can be easily used to create a new simulation for that RX in the future.
Example Log:
5.340 WAIT_CMD: DSM_GotoMenu(0x1010,LastSelectedLine=0)
5.350 MENU_TITLE: SEND DSM_getMenu(MenuId=0x1010 LastSelectedLine=0)
5.440 MENU_TITLE: RESPONSE Menu: M[Id=0x1010 P=0x0 N=0x0 B=0x1000 Text="Gyro settings"[0xF9]]
5.490 MENU_LINES: SEND DSM_getFirstMenuLine(MenuId=0x1010)
5.590 MENU_LINES: RESPONSE MenuLine: L[#0 T=M VId=0x1011 Text="AS3X Settings"[0x1DD] MId=0x1010 ]
5.640 MENU_LINES: SEND DSM_getNextLine(MenuId=0x1010,LastLine=0)
5.740 MENU_LINES: RESPONSE MenuLine: L[#1 T=M VId=0x1019 Text="SAFE Settings"[0x1E2] MId=0x1010 ]
5.790 MENU_LINES: SEND DSM_getNextLine(MenuId=0x1010,LastLine=1)
5.850 MENU_LINES: RESPONSE MenuLine: L[#2 T=M VId=0x1021 Text="F-Mode Setup"[0x87] MId=0x1010 ]
5.910 MENU_LINES: SEND DSM_getNextLine(MenuId=0x1010,LastLine=2)
5.970 MENU_LINES: RESPONSE MenuLine: L[#3 T=M VId=0x1022 Text="System Setup"[0x86] MId=0x1010 ]
6.020 MENU_LINES: SEND DSM_getNextLine(MenuId=0x1010,LastLine=3
# Validation of data by the RX
The RX validates the data. if you change to an invalid channel or do a invalid number range, the RX will change it at the end of editing the field.
---
# Version 0.53
- Improve Channel selection in menus
- Support smaller screens 128x64 in the black/white mode.
# Version 0.52
- Fix Reversing of Servos
- Properly detect Multimodule Ch settings AETR
---
# Version 0.51 (volunteer testing version, not for production)
- New Screens to Configure Model (Wing Type/Tail Tail, etc)
- Finally got understanding that the previous unknown 0x05 lines are to send Model/Servo data to RX.
- Fix use of AR636B (Firmware version 4.40.0 for Blade 230 heli, is the only one with Forward Programming)
- Aircraft types: Tested With Plane type only.. Glider and other in progress
### Known Problems:
- 4-Servo Wing type (Dual Ail/Tail) in planes give conflicting servo assignments by defaults.. Solution choose your own Ch.
- Glider, Heli, Drone: Still in development. In glider, only a few wing type works.. needs to restrict menu options for the only valid one.
# Version 0.5
- Make the code more readable and understandable
- Separate the DSM Forwards Programming logic from the GUI
- Log the communication with the RX on a /LOGS/dsm_log.txt to allow to debug it easier
and see the exchange of data between the RX/TX
- Created a black/white Text only version with only Key/Roller Inputs
- Created a nicer GUI for EdgeTX touch screen color Radios
- RX simulation for GUI development: turn on `SIMULATION_ON=true` in the beginning of the lua file
- Test it on AR631, AR637xx, FC6250HX (Helicopter)
### Some settings that can change (top of Lua file):
SIMULATION_ON = false -- FALSE: hide similation menu (DEFAULT), TRUE: show RX simulation menu
DEBUG_ON = 1 -- 0=NO DEBUG, 1=HIGH LEVEL 2=LOW LEVEL (Debug logged into the /LOGS/dsm_log.txt)
USE_SPECKTRUM_COLORS = true -- true: Use spectrum colors, false: use theme colors (default on OpenTX, OpenTX handle colors different)
### Known Problems:
1. **Incorrect List Value Options:** Some Menu List line (`LINE_TYPE.LIST_MENU1` or `L_m1` in logs), the range (min/max) of valid values seems to be incorrect, but the RX corrects the values.
in the MINimalistic version, the RX is doing all the range validation, and will show invalid options temporarilly. In an Spektrum radio, it happens so fast, that you don't notice it, but in LUA scripts who are slower, you can see it in the screen.
In the COLOR version, The code has hardcoded the valid ranges to avoid this problem.
2. Glider/Heli/Drone wing types not ready.
For Helicopter, use airplane normal wing and normal tail
# Version 0.2
Original Version from Pascal Langer

View File

@@ -0,0 +1,683 @@
local toolName = "TNS|DSM AR636 Telemetry|TNE"
---- ######################################################################### #
---- # License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html #
---- # #
---- # This program is free software; you can redistribute it and/or modify #
---- # it under the terms of the GNU General Public License version 2 as #
---- # published by the Free Software Foundation. #
---- # #
---- # This program is distributed in the hope that it will be useful #
---- # but WITHOUT ANY WARRANTY; without even the implied warranty of #
---- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
---- # GNU General Public License for more details. #
---- # #
---- #########################################################################
------------------------------------------------------------------------------
-- Developer: Francisco Arzu
-- Original idea taken from DsmPID.lua.. don't know who is the author
--
local DEBUG_ON = false
--
local TEXT_SIZE = 0 -- NORMAL
local X_COL1_HEADER = 6
local X_COL1_DATA = 60
local X_COL2_HEADER = 170
local X_COL2_DATA = 220
local Y_LINE_HEIGHT = 20
local Y_HEADER = 0
local Y_DATA = Y_HEADER + Y_LINE_HEIGHT*2
local X_DATA_LEN = 80
local X_DATA_SPACE = 5
local function getPage(iParam)
-- get page from 0-based index
-- {0,1,2,3}: cyclic (1), {4,5,6,7}: tail (2)
local res = (math.floor(iParam/4)==0) and 0 or 1
return res
end
local function round(v)
-- round float
local factor = 100
return math.floor(v * factor + 0.5) / factor
end
local function readValue(sensor)
-- read from sensor, round and return
local v = getValue(sensor)
--v = round(v)
return v
end
local function readValueById(sensor)
local i = getFieldInfo(sensor)
if (i==nil) then return nil end
local v = getValue(i.id)
return v
end
local function readBatValue(sensor)
-- read from sensor, round and return
local v = getValue(sensor)
if (v==nil) then return "--" end
return string.format("%2.2f",v)
end
local function readActiveParamValue(sensor)
-- read and return a validated active parameter value
local v = getValue(sensor)
if (v<1 or v>8) then
return -1
end
return v
end
local function drawPIDScreen()
-- draw labels and params on screen
local pageId = getValue("FLss")
lcd.clear()
-- if active gain does not validate then assume
-- Gain Adjustment Mode is disabled
if not (pageId==4401 or pageId==4402) then
lcd.drawText(0,0,"BLADE Gain Adjustment", TEXT_SIZE +INVERS)
lcd.drawText(X_COL1_HEADER,Y_LINE_HEIGHT*1,"Enter Gain Adjustment Mode",TEXT_SIZE)
lcd.drawText(X_COL1_HEADER,Y_LINE_HEIGHT*2,"Stk: Low/R + Low/R + Panic (3 sec)",TEXT_SIZE)
lcd.drawText(X_COL1_HEADER,Y_LINE_HEIGHT*4,"Op: Right Stk: Up/Down to select, Left/Right change value",TEXT_SIZE)
lcd.drawText(X_COL1_HEADER,Y_LINE_HEIGHT*5,"Panic to exit",TEXT_SIZE)
return
end
local activePage = (pageId % 100)-1 --Last 2 digits, make it zero base
lcd.drawText (X_COL1_HEADER, Y_HEADER, "Cyclic (0-200)", TEXT_SIZE + INVERS)
lcd.drawText (X_COL2_HEADER, Y_HEADER, "Tail (0-200)", TEXT_SIZE + INVERS)
local p = readValue("FdeA")
local i = readValue("FdeB")
local d = readValue("FdeL")
local r = readValue("FdeR")
local titles = {[0]="P:", "I:", "D:", "Resp:", "P:","I:","D:", "Filt:"}
local values = {[0]=p,i,d,r,p,i,d,r}
local activeParam = readActiveParamValue("Hold")-1
for iParam=0,7 do
-- highlight selected parameter
local attr = (activeParam==iParam) and INVERS or 0
-- circular index (per page)
local perPageIndx = (iParam % 4)
-- set y draw coord
local y = (perPageIndx+1)*Y_LINE_HEIGHT+Y_DATA
-- check if displaying cyclic params.
local isCyclicPage = (getPage(iParam)==0)
-- labels
local x = isCyclicPage and X_COL1_HEADER or X_COL2_HEADER
-- labels are P,I,D for both pages except for last param
local val = titles[iParam]
lcd.drawText (x, y, val, TEXT_SIZE)
-- gains
-- set all params for non-active page to '--' rather than 'last value'
val = (getPage(iParam)==activePage) and values[iParam] or '--'
x = isCyclicPage and X_COL1_DATA or X_COL2_DATA
if (val~=16384) then -- Active value
lcd.drawText (x, y, val, attr + TEXT_SIZE)
end
end
end
local function drawFlightLogScreen()
-- draw labels and params on screen
local h = getValue("Hold")
local activeParam = h-1 -- H
lcd.clear()
lcd.drawText (X_COL1_HEADER, Y_HEADER, "Flight Log", TEXT_SIZE + INVERS)
-- read and return parameters
local a = getValue("FdeA")
local b = getValue("FdeB")
local l = getValue("FdeL")
local r = getValue("FdeR")
local f = getValue("FLss")
local titles = {[0]="A:", "B:", "L:", "R:", "F:", "H:"}
local values = {[0]=a,b,l,r,f,h}
local y = Y_LINE_HEIGHT+Y_DATA
for iParam=0,3 do -- A,B,L,R
-- highlight selected parameter (rund)
local attr = ((activeParam%4)==iParam) and INVERS or 0
-- labels
local x = X_COL1_HEADER
local val = titles[iParam]
lcd.drawText (x, y, val, TEXT_SIZE)
-- Values
val = values[iParam]
x = X_COL1_DATA + X_DATA_LEN
if (val~=16384) then -- Active value
lcd.drawText (x, y, val, attr + TEXT_SIZE + RIGHT)
end
y = y + Y_LINE_HEIGHT
end
y = Y_LINE_HEIGHT+Y_DATA
for iParam=4,5 do -- F, H
-- labels
local x = X_COL2_HEADER
local val = titles[iParam]
lcd.drawText (x, y, val, TEXT_SIZE + BOLD)
-- Values
val = values[iParam]
x = X_COL2_DATA + X_DATA_LEN
lcd.drawText (x, y, val, TEXT_SIZE + RIGHT + BOLD)
y = y + Y_LINE_HEIGHT
end
-- Bat
y = y + Y_LINE_HEIGHT
local bat = readBatValue("A2") or "--"
lcd.drawText (X_COL2_HEADER, y, "Bat:", TEXT_SIZE)
lcd.drawText (X_COL2_DATA + X_DATA_LEN, y, bat, TEXT_SIZE + RIGHT)
lcd.drawText (X_COL2_DATA + X_DATA_LEN + X_DATA_SPACE, y, "v", TEXT_SIZE)
end
local function servoAdjustScreen()
-- draw labels and params on screen
local pageId = getValue("FLss") -- FLss
local activeParam = getValue("Hold")-1 -- Hold
lcd.clear()
lcd.drawText (0, Y_HEADER, "BLADE Servo SubTrim", TEXT_SIZE + INVERS)
if pageId~=1234 then
lcd.drawText(X_COL1_HEADER,Y_LINE_HEIGHT*1,"Enter Servo Adjustment Mode",TEXT_SIZE)
lcd.drawText(X_COL1_HEADER,Y_LINE_HEIGHT*2,"Stk: Low/L + Low/R + Panic (3 sec)",TEXT_SIZE)
lcd.drawText(X_COL1_HEADER,Y_LINE_HEIGHT*4,"Op: R Stk: Up/Down to select, Left/Right change value",TEXT_SIZE)
lcd.drawText(X_COL1_HEADER,Y_LINE_HEIGHT*5,"Panic to exit",TEXT_SIZE)
return
end
local a = getValue("FdeA")
local b = getValue("FdeB")
local l = getValue("FdeL")
local titles = {[0]="Servo1:", "Servo2:", "Servo3:"}
local values = {[0]=a,b,l}
for iParam=0,#values do -- S1,S2,S3
-- highlight selected parameter
local attr = (activeParam==iParam) and INVERS or 0
-- set y draw coord
local y = (iParam+1)*Y_LINE_HEIGHT+Y_HEADER
-- labels
local x = X_COL1_HEADER
local val = titles[iParam]
lcd.drawText (x, y, val, TEXT_SIZE)
val = values[iParam]
x = X_COL1_DATA
if (val~=16384) then -- Active value
lcd.drawText (x, y, val, attr + TEXT_SIZE)
end
end
end
local function Unsigned_to_SInt16(value)
if value >= 0x8000 then -- Negative value??
return value - 0x10000
end
return value
end
local function getDegreesValue(sensor)
local i = getFieldInfo(sensor)
if (i==nil) then return "-unk-" end
local v = getValue(i.id)
if v==nil then return "---" end
local vs = Unsigned_to_SInt16(v)
return string.format("%0.1f o",vs/10)
end
local function getDecHexValue(sensor)
local i = getFieldInfo(sensor)
if (i==nil) then return "-unk-" end
local v = getValue(i.id)
if v==nil then return "---" end
local vs = Unsigned_to_SInt16(v)
return string.format("%d (0x%04X)",vs,v)
end
local function drawVersionScreen()
local paramV = getValue("FdeA")
local B = getValue("FdeB")
local rxId = getValue("FdeL")
local firmware = getValue("FLss")
local prodId = getValue("Hold")
local bat = readBatValue("A2")
lcd.clear()
lcd.drawText (0, Y_HEADER, "BLADE Version", TEXT_SIZE + INVERS)
--Product ID
local val = "ID_".. prodId
if (prodId==243) then val = "Blade 230 V1"
elseif (prodId==250) then val = "Blade 230 V2 (not Smart)"
elseif (prodId==149) then val = "Blade 250 CFX"
end
local y = Y_DATA
local x_data1 = X_COL1_DATA+X_DATA_LEN
lcd.drawText (X_COL1_HEADER, y, "Prod:", TEXT_SIZE)
lcd.drawText (x_data1, y, val, TEXT_SIZE)
-- RX
val = "ID_"..rxId
if (rxId==1) then val = "AR636"
end
y = y + Y_LINE_HEIGHT
lcd.drawText (X_COL1_HEADER, y, "RX:", TEXT_SIZE)
lcd.drawText (x_data1, y, val, TEXT_SIZE)
-- Firmware
val = string.format("%0.2f",firmware/100)
y = y + Y_LINE_HEIGHT
lcd.drawText (X_COL1_HEADER, y, "Firmware:", TEXT_SIZE)
lcd.drawText (x_data1, y, val, TEXT_SIZE)
-- ParamV
y = y + Y_LINE_HEIGHT
lcd.drawText (X_COL1_HEADER, y, "Params:", TEXT_SIZE)
lcd.drawText (x_data1, y, paramV, TEXT_SIZE)
-- Bat
y = y + Y_LINE_HEIGHT
lcd.drawText (X_COL1_HEADER, y, "Bat:", TEXT_SIZE)
lcd.drawText (x_data1, y, bat, TEXT_SIZE)
y = y + Y_LINE_HEIGHT
lcd.drawText(X_COL1_HEADER,y,"Press Panic for 3s",TEXT_SIZE)
y = y + Y_LINE_HEIGHT
lcd.drawText(X_COL1_HEADER,y,"Usually Panic is Ch7 on a switch and Revesed",TEXT_SIZE)
end
local function parseFlightMode(v)
-- FlightMode (Hex: MMSGG) MM=Flight Mode, S=Status (0= off, 1=init, 2=Hold, 3=Running) GG=???
if v==nil then return "---" end
local fm = bit32.rshift(v, 12)
local status = bit32.band(bit32.rshift(v, 8),0xF)
local res = " "..fm.." "
if (fm==0) then res = res .. " NORMAL"
elseif (fm==1) then res = res .. " INTERMEDIATE"
elseif (fm==2) then res = res .. " ADVANCED"
elseif (fm==5) then res = res .. " PANIC"
end
if (status==2) then res=res .. " HOLD" end
if (DEBUG_ON) then
res = res .. string.format(" (0x%04X)",v)
end
return res
end
local function drawAlpha6Monitor()
lcd.clear()
local RxStatus = readValueById("2402") -- FlightMode (Hex: MMSGG) MM=Flight Mode, S=Status (0=init, 2=Ready, 3=Sensor Fault) GG=???
local ARoll = getDegreesValue("2406") --Att Roll
local APitch = getDegreesValue("2408") --Att Pitch
local AYaw = getDegreesValue("240B") --Att Yaw
lcd.drawText (0,0, "BLADE Alpha6 Monitor", TEXT_SIZE+INVERS)
local y = Y_DATA
local x_data1 = X_COL1_DATA+X_DATA_LEN
local x_data2 = X_COL1_DATA+X_DATA_LEN*2
local x_data3 = X_COL1_DATA+X_DATA_LEN*3
-- Flight Mode
lcd.drawText (0,y, "F-Mode:"..parseFlightMode(RxStatus), TEXT_SIZE)
y = y + Y_LINE_HEIGHT
lcd.drawText (x_data1,y, "Attitude", TEXT_SIZE+BOLD + RIGHT)
lcd.drawText (x_data2,y, "Gyro", TEXT_SIZE+BOLD + RIGHT)
lcd.drawText (x_data3,y, "Gain", TEXT_SIZE+BOLD + RIGHT)
y = y + Y_LINE_HEIGHT
lcd.drawText (X_COL1_HEADER,y, "Rol:", TEXT_SIZE)
lcd.drawText (x_data1,y, ARoll, TEXT_SIZE + RIGHT)
lcd.drawText (x_data2,y, "-", TEXT_SIZE + RIGHT)
lcd.drawText (x_data3,y, "-", TEXT_SIZE + RIGHT)
y = y + Y_LINE_HEIGHT
lcd.drawText (X_COL1_HEADER,y, "Pitch:", TEXT_SIZE)
lcd.drawText (x_data1,y, APitch, TEXT_SIZE + RIGHT)
lcd.drawText (x_data2,y, "-", TEXT_SIZE + RIGHT)
lcd.drawText (x_data3,y, "-", TEXT_SIZE + RIGHT)
y = y + Y_LINE_HEIGHT
lcd.drawText (X_COL1_HEADER,y, "Yaw:", TEXT_SIZE)
lcd.drawText (x_data1,y, AYaw, TEXT_SIZE + RIGHT)
lcd.drawText (x_data2,y, "-", TEXT_SIZE + RIGHT)
lcd.drawText (x_data3,y, "-", TEXT_SIZE + RIGHT)
y = y + Y_LINE_HEIGHT + Y_LINE_HEIGHT
lcd.drawText (0,y, "Bat: "..readBatValue("A2").." v", TEXT_SIZE)
-- Debug Values
if (DEBUG_ON) then
local s2400 = getDecHexValue("2400")
local s2402 = getDecHexValue("2402")
local s2404 = getDecHexValue("2404")
local s240D = getDecHexValue("240D")
local s1G00 = getDecHexValue("1G00")
local s1G02 = getDecHexValue("1G02")
local s1G04 = getDecHexValue("1G04")
local s1G06 = getDecHexValue("1G06")
local s1G08 = getDecHexValue("1G08")
local s1G0B = getDecHexValue("1G0B")
local s1G0D = getDecHexValue("1G0D")
local titles = {[0]=
"2400","2402/FM-S-?",
"2404","240D",
"1G00","1G02","1G04",
"1G06","1G08","1G0B","1G0D"}
local values = {[0]=
s2400,s2402,s2404,s240D,
s1G00,s1G02,s1G04,
s1G06,s1G08,s1G0B,s1G0D}
-- draw labels and params on screen
y = Y_LINE_HEIGHT*2 + Y_HEADER
for iParam=0,#titles do -- ??
-- labels
local x = X_COL1_HEADER+220
local val = titles[iParam]
lcd.drawText (x, y, val, TEXT_SIZE)
val = values[iParam]
x = X_COL1_DATA+250
lcd.drawText (x, y, val, TEXT_SIZE)
y = y + Y_LINE_HEIGHT
end
end
end
local function readAlpha3arameters()
end
local function drawAS3XMonitor()
lcd.clear()
local s1G00 = getDecHexValue("1G00")
local s1G02 = getDecHexValue("1G02")
local s1G04 = getDecHexValue("1G04")
local s1G06 = getDecHexValue("1G06")
local s1G08 = getDecHexValue("1G08")
local s1G0B = getDecHexValue("1G0B")
local s1G0D = getDecHexValue("1G0D")
local s6C00 = getDecHexValue("6C00")
local s6C02 = getDecHexValue("6C02")
local s6C04 = getDecHexValue("6C04")
local RRoll = bit32.rshift(getValue("1G00") or 0,8)
local RPitch = bit32.band(getValue("1G00") or 0,0xFF)
local RYaw = bit32.rshift(getValue("1G02") or 0,8)
local HRoll = bit32.band(getValue("1G02") or 0,0xFF)
local HPitch = bit32.rshift(getValue("1G04") or 0,8)
local HYaw = bit32.band(getValue("1G04") or 0,0xFF)
local ARoll = bit32.rshift(getValue("1G06") or 0,8)
local APitch = bit32.band(getValue("1G06") or 0,0xFF)
local AYaw = bit32.rshift(getValue("1G08") or 0,8)
lcd.drawText (0,0, "Plane AR636 AS3X Gains", TEXT_SIZE+INVERS)
local y = Y_DATA
local x_data1 = X_COL1_DATA+X_DATA_LEN
local x_data2 = X_COL1_DATA+X_DATA_LEN*2
local x_data3 = X_COL1_DATA+X_DATA_LEN*3.1
-- Flight Mode
--lcd.drawText (0,y, "F-Mode: "..(nil or "--"), TEXT_SIZE)
y = y + Y_LINE_HEIGHT
lcd.drawText (x_data1,y, "Rate", TEXT_SIZE+BOLD + RIGHT)
lcd.drawText (x_data2,y, "Head", TEXT_SIZE+BOLD + RIGHT)
lcd.drawText (x_data3+X_DATA_SPACE*3,y, "Actual", TEXT_SIZE+BOLD + RIGHT)
y = y + Y_LINE_HEIGHT
lcd.drawText (X_COL1_HEADER,y, "Roll %:", TEXT_SIZE)
lcd.drawText (x_data1,y, RRoll, TEXT_SIZE + RIGHT)
lcd.drawText (x_data2,y, HRoll, TEXT_SIZE + RIGHT)
lcd.drawText (x_data3,y, ARoll, TEXT_SIZE + RIGHT)
y = y + Y_LINE_HEIGHT
lcd.drawText (X_COL1_HEADER,y, "Pitch %:", TEXT_SIZE)
lcd.drawText (x_data1,y, RPitch, TEXT_SIZE + RIGHT)
lcd.drawText (x_data2,y, HPitch, TEXT_SIZE + RIGHT)
lcd.drawText (x_data3,y, APitch, TEXT_SIZE + RIGHT)
y = y + Y_LINE_HEIGHT
lcd.drawText (X_COL1_HEADER,y, "Yaw %:", TEXT_SIZE)
lcd.drawText (x_data1,y, RYaw, TEXT_SIZE + RIGHT)
lcd.drawText (x_data2,y, HYaw, TEXT_SIZE + RIGHT)
lcd.drawText (x_data3,y, AYaw, TEXT_SIZE + RIGHT)
-- Debug Values
if (DEBUG_ON) then
local Alpha3Tags = {[0]=
"1G00/RA+RE","1G02/RY+HA","1G04R HP+HY","1G06/AR+AP","1G08/AY+?","1G0B","1G0D","6C00","6C02","6C04"}
local params = {[0]=
s1G00,s1G02,s1G04,s1G06,s1G08,s1G0B,s1G0D,s6C00,s6C02,s6C04 }
y = Y_LINE_HEIGHT*2 + Y_HEADER
for iParam=0,#Alpha3Tags do -- ??
-- labels
local x = X_COL1_HEADER+220
local val = Alpha3Tags[iParam]
lcd.drawText (x, y, val, TEXT_SIZE)
val = params[iParam]
x = X_COL1_DATA+250
lcd.drawText (x, y, val, TEXT_SIZE)
y = y + Y_LINE_HEIGHT
end
end
end
local function openTelemetryRaw(i2cId)
--Init telemetry (Spectrun Telemetry Raw STR)
multiBuffer( 0, string.byte('S') )
multiBuffer( 1, string.byte('T') )
multiBuffer( 2, string.byte('R') )
multiBuffer( 3, i2cId ) -- Monitor this teemetry data
multiBuffer( 4, 0 ) -- Allow to get Data
end
local function closeTelemetryRaw()
multiBuffer(0, 0) -- Destroy the STR header
multiBuffer(3, 0) -- Not requesting any Telementry ID
end
local lineText = {nil}
local I2C_TEXT_GEN = 0x0C
local function drawTextGen(event)
if (multiBuffer(0)~=string.byte('S')) then -- First time run???
openTelemetryRaw(I2C_TEXT_GEN) -- I2C_ID for TEXT_GEN
lineText = {nil}
end
-- Proces TEXT GEN Telementry message
if multiBuffer( 4 ) == I2C_TEXT_GEN then -- Specktrum Telemetry ID of data received
local instanceNo = multiBuffer( 5 )
local lineNo = multiBuffer( 6 )
local line = ""
for i=0,13 do
line = line .. string.char(multiBuffer( 7 + i ))
end
multiBuffer( 4, 0 ) -- Clear Semaphore, to notify that we fully process the current message
lineText[lineNo]=line
end
lcd.clear()
-- Header
if (lineText[0]) then
lcd.drawText (X_COL1_HEADER,0, " "..lineText[0].." ", TEXT_SIZE + BOLD + INVERS)
else
lcd.drawText (X_COL1_HEADER,0, "TextGen", TEXT_SIZE+INVERS)
end
-- Menu lines
local y = Y_DATA
for i=1,8 do
if (lineText[i]) then
lcd.drawText (X_COL1_HEADER,y, lineText[i], TEXT_SIZE)
end
y = y + Y_LINE_HEIGHT
end
if event == EVT_VIRTUAL_EXIT then -- Exit?? Clear menu data
closeTelemetryRaw()
end
end
local telPage = 1
local telPageSelected = 0
local pageTitle = {[0]="Main", "Blade Version", "Blade Servo Adjust","Blade Gyro Adjust", "Blade Alpha6 Monitor", "Plane AS3X Monitor", "TextGen", "Flight Log"}
local function drawMainScreen(event)
lcd.clear()
lcd.drawText (X_COL1_HEADER, Y_HEADER, "Main Telemetry (AR636)", TEXT_SIZE + INVERS)
for iParam=1,#pageTitle do
-- highlight selected parameter
local attr = (telPage==iParam) and INVERS or 0
-- set y draw coord
local y = (iParam-1)*Y_LINE_HEIGHT+Y_DATA
-- labels
local x = X_COL1_HEADER
local val = pageTitle[iParam]
lcd.drawText (x, y, val, attr + TEXT_SIZE)
end
if event == EVT_VIRTUAL_PREV then
if (telPage>1) then telPage = telPage - 1 end
elseif event == EVT_VIRTUAL_NEXT then
if (telPage<#pageTitle) then telPage = telPage + 1 end
elseif event == EVT_VIRTUAL_ENTER then
telPageSelected = telPage
end
end
local pageDraw = {[0]=drawMainScreen, drawVersionScreen, servoAdjustScreen,drawPIDScreen, drawAlpha6Monitor, drawAS3XMonitor, drawTextGen, drawFlightLogScreen}
local function run_func(event)
if event == nil then
error("Cannot be run as a model script!")
return 2
end
-- draw specific page
pageDraw[telPageSelected](event)
if event == EVT_VIRTUAL_EXIT then
if (telPageSelected==0) then return 1 end -- on Main?? Exit Script
telPageSelected = 0 -- any page, return to Main
end
return 0
end
local function init_func()
if (LCD_W <= 128 or LCD_H <=64) then -- Smaller Screens
TEXT_SIZE = SMLSIZE
X_COL1_HEADER = 0
X_COL1_DATA = 20
X_COL2_HEADER = 60
X_COL2_DATA = 90
X_DATA_LEN = 28
X_DATA_SPACE = 1
Y_LINE_HEIGHT = 8
Y_DATA = Y_HEADER + Y_LINE_HEIGHT
end
end
return { run=run_func, init=init_func }

View File

@@ -0,0 +1,603 @@
local toolName = "TNS|DSM Smart RX Telemetry|TNE"
---- ######################################################################### #
---- # License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html #
---- # #
---- # This program is free software; you can redistribute it and/or modify #
---- # it under the terms of the GNU General Public License version 2 as #
---- # published by the Free Software Foundation. #
---- # #
---- # This program is distributed in the hope that it will be useful #
---- # but WITHOUT ANY WARRANTY; without even the implied warranty of #
---- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
---- # GNU General Public License for more details. #
---- # #
---- #########################################################################
------------------------------------------------------------------------------
-- Developer: Francisco Arzu
local DEBUG_ON = false
--
local TEXT_SIZE = 0 -- NORMAL
local X_COL1_HEADER = 6
local X_COL1_DATA = 60
local X_COL2_HEADER = 170
local X_COL2_DATA = 220
local Y_LINE_HEIGHT = 20
local Y_HEADER = 0
local Y_DATA = Y_HEADER + Y_LINE_HEIGHT*2
local X_DATA_LEN = 80
local X_DATA_SPACE = 5
local function getPage(iParam)
-- get page from 0-based index
-- {0,1,2,3}: cyclic (1), {4,5,6,7}: tail (2)
local res = (math.floor(iParam/4)==0) and 0 or 1
return res
end
local function round(v)
-- round float
local factor = 100
return math.floor(v * factor + 0.5) / factor
end
local function readValue(sensor)
-- read from sensor, round and return
local v = getValue(sensor)
--v = round(v)
return v
end
local function readValueById(sensor)
local i = getFieldInfo(sensor)
if (i==nil) then return nil end
local v = getValue(i.id)
return v
end
local function readBatValue(sensor)
-- read from sensor, round and return
local v = getValue(sensor)
if (v==nil) then return v end
return string.format("%2.2f",v)
end
local function readActiveParamValue(sensor)
-- read and return a validated active parameter value
local v = getValue(sensor)
if (v<1 or v>8) then
return -1
end
return v
end
local function drawFlightLogScreen(event)
-- draw labels and params on screen
local h = getValue("Hold")
local activeParam = h-1 -- H
lcd.clear()
lcd.drawText (X_COL1_HEADER, Y_HEADER, "Flight Log", TEXT_SIZE + INVERS)
-- read and return parameters
local a = getValue("FdeA")
local b = getValue("FdeB")
local l = getValue("FdeL")
local r = getValue("FdeR")
local f = getValue("FLss")
local titles = {[0]="A:", "B:", "L:", "R:", "F:", "H:"}
local values = {[0]=a,b,l,r,f,h}
local y = Y_LINE_HEIGHT+Y_DATA
for iParam=0,3 do -- A,B,L,R
-- highlight selected parameter (rund)
local attr = ((activeParam%4)==iParam) and INVERS or 0
-- labels
local x = X_COL1_HEADER
local val = titles[iParam]
lcd.drawText (x, y, val, TEXT_SIZE)
-- Values
val = values[iParam]
x = X_COL1_DATA + X_DATA_LEN
if (val~=16384) then -- Active value
lcd.drawText (x, y, val, attr + TEXT_SIZE + RIGHT)
end
y = y + Y_LINE_HEIGHT
end
y = Y_LINE_HEIGHT+Y_DATA
for iParam=4,5 do -- F, H
-- labels
local x = X_COL2_HEADER
local val = titles[iParam]
lcd.drawText (x, y, val, TEXT_SIZE + BOLD)
-- Values
val = values[iParam]
x = X_COL2_DATA + X_DATA_LEN
lcd.drawText (x, y, val, TEXT_SIZE + RIGHT + BOLD)
y = y + Y_LINE_HEIGHT
end
-- Bat
y = y + Y_LINE_HEIGHT
local bat = readBatValue("A2") or "--"
lcd.drawText (X_COL2_HEADER, y, "Bat:", TEXT_SIZE)
lcd.drawText (X_COL2_DATA + X_DATA_LEN, y, bat, TEXT_SIZE + RIGHT)
lcd.drawText (X_COL2_DATA + X_DATA_LEN + X_DATA_SPACE, y, "v", TEXT_SIZE)
end
local function Unsigned_to_SInt16(value)
if value >= 0x8000 then -- Negative value??
return value - 0x10000
end
return value
end
local function getDegreesValue(sensor)
local i = getFieldInfo(sensor)
if (i==nil) then return "-unk-" end
local v = getValue(i.id)
if v==nil then return "---" end
local vs = Unsigned_to_SInt16(v)
return string.format("%0.1f o",vs/10)
end
local function getDecHexValue(sensor)
local i = getFieldInfo(sensor)
if (i==nil) then return "-unk-" end
local v = getValue(i.id)
if v==nil then return "---" end
local vs = Unsigned_to_SInt16(v)
return string.format("%d (0x%04X)",vs,v)
end
local as3xData = {[0]=0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}
local function drawAS3XSettings(event, page)
local s0500 = getDecHexValue("0500")
local s0502 = getDecHexValue("0502")
local s0504 = getDecHexValue("0504")
local s0506 = getDecHexValue("0506")
local s0508 = getDecHexValue("0508")
local s050B = getDecHexValue("050B")
local s050D = getDecHexValue("050D")
local d0500 = readValueById("0500") or 0
local flags = bit32.rshift(d0500,8)
local state = bit32.band(d0500,0xFF)
local flagsMsg=""
-- flags bits: Safe Envelop, ?, Angle Demand, Stab
if (bit32.band(flags,0x1)~=0) then flagsMsg=flagsMsg.."AS3X Stab" end
-- This one, only one should show
if (bit32.band(flags,0x2)~=0) then flagsMsg=flagsMsg..", Angle Demand"
elseif (bit32.band(flags,0x8)~=0) then flagsMsg=flagsMsg..", Safe Envelope"
elseif (bit32.band(flags,0x4)~=0) then flagsMsg=flagsMsg..", AS3X Heading" end
local d0502 = readValueById("0502") or 0 -- 0x?F?S
local fm = bit32.band(bit32.rshift(d0502,8),0xF) -- 0,1,2
local axis = bit32.band(d0502,0xF) -- 0=Gains,1=Headings,2=Angle Limits (cointinus iterating to provide all values)
local d0504 = readValueById("0504") or 0
local d0506 = readValueById("0506") or 0
local d0508 = readValueById("0508") or 0
local d0 = bit32.rshift(d0504,8)
local d1 = bit32.band(d0504,0xFF)
local d2 = bit32.rshift(d0506,8)
local d3 = bit32.band(d0506,0xFF)
local d4 = bit32.rshift(d0508,8)
local d5 = bit32.band(d0508,0xFF)
--axis: 0=Gains+Headings (RG,PG,YG,RH,PH,YH), 1=Safe Gains (R,P,Y),2=Angle Limits(L,R,U,D)
--Constantly changing from 0..2 to represent different data, thats why we have to store the values
--in a script/global variable, and not local to the function
local s = axis*6
as3xData[s+0] = d0
as3xData[s+1] = d1
as3xData[s+2] = d2
as3xData[s+3] = d3
as3xData[s+4] = d4
as3xData[s+5] = d5
lcd.clear()
lcd.drawText (0,0, "AS3X/SAFE Settings", TEXT_SIZE + INVERS)
local y = Y_DATA
-- Flight Mode
lcd.drawText (X_COL1_HEADER,y, "FM: "..(fm+1), TEXT_SIZE)
lcd.drawText (X_COL1_DATA+X_DATA_LEN*0.3,y, "Flags: "..flags, TEXT_SIZE)
lcd.drawText (X_COL2_HEADER+X_DATA_LEN*0.3,y, "State: "..state, TEXT_SIZE)
y = y + Y_LINE_HEIGHT
lcd.drawText (X_COL1_HEADER,y, flagsMsg, TEXT_SIZE)
y = y + Y_LINE_HEIGHT
if (page==1) then
lcd.drawText (X_COL1_HEADER+X_DATA_LEN*0.3,y, "AS3X Gains", TEXT_SIZE+BOLD)
lcd.drawText (X_COL2_HEADER+X_DATA_LEN*0.3,y, "AS3X Headings", TEXT_SIZE+BOLD)
y = y + Y_LINE_HEIGHT
lcd.drawText (X_COL1_HEADER,y, "Roll:", TEXT_SIZE)
lcd.drawText (X_COL1_DATA+X_DATA_LEN,y, as3xData[0], TEXT_SIZE + RIGHT) -- Roll G
lcd.drawText (X_COL2_DATA+X_DATA_LEN,y, as3xData[3], TEXT_SIZE + RIGHT) -- Roll H
y = y + Y_LINE_HEIGHT
lcd.drawText (X_COL1_HEADER,y, "Pitch:", TEXT_SIZE)
lcd.drawText (X_COL1_DATA+X_DATA_LEN,y,as3xData[1], TEXT_SIZE + RIGHT) -- Pitch G
lcd.drawText (X_COL2_DATA+X_DATA_LEN,y, as3xData[4], TEXT_SIZE + RIGHT) -- Pitch H
y = y + Y_LINE_HEIGHT
lcd.drawText (X_COL1_HEADER,y, "Yaw:", TEXT_SIZE)
lcd.drawText (X_COL1_DATA+X_DATA_LEN,y, as3xData[2], TEXT_SIZE + RIGHT) -- Yaw G
lcd.drawText (X_COL2_DATA+X_DATA_LEN,y, as3xData[5], TEXT_SIZE + RIGHT) -- Yaw H
end
if (page==2) then
local x_data1 = X_COL1_DATA+X_DATA_LEN
local x_data2 = X_COL2_HEADER+X_DATA_LEN*1.6
lcd.drawText (X_COL1_HEADER+X_DATA_LEN*0.3,y, "SAFE Gains", TEXT_SIZE+BOLD)
lcd.drawText (X_COL2_HEADER+X_DATA_LEN*0.1,y, "Angle Limits", TEXT_SIZE+BOLD)
y = y + Y_LINE_HEIGHT
lcd.drawText (X_COL1_HEADER,y, "Roll:", TEXT_SIZE)
lcd.drawText (x_data1,y, as3xData[6], TEXT_SIZE + RIGHT)
lcd.drawText (X_COL2_HEADER,y, "Roll R:", TEXT_SIZE)
lcd.drawText (x_data2,y, as3xData[12], TEXT_SIZE + RIGHT)
y = y + Y_LINE_HEIGHT
lcd.drawText (X_COL1_HEADER,y, "Pitch:", TEXT_SIZE)
lcd.drawText (x_data1,y,as3xData[7], TEXT_SIZE + RIGHT)
lcd.drawText (X_COL2_HEADER,y, "Roll L:", TEXT_SIZE)
lcd.drawText (x_data2,y,as3xData[13], TEXT_SIZE + RIGHT)
y = y + Y_LINE_HEIGHT
lcd.drawText (X_COL1_HEADER,y, "Yaw:", TEXT_SIZE)
lcd.drawText (x_data1,y, as3xData[8], TEXT_SIZE + RIGHT)
lcd.drawText (X_COL2_HEADER,y, "Pitch U:", TEXT_SIZE)
lcd.drawText (x_data2,y, as3xData[14], TEXT_SIZE + RIGHT)
y = y + Y_LINE_HEIGHT
lcd.drawText (X_COL2_HEADER,y, "Pitch D:", TEXT_SIZE)
lcd.drawText (x_data2,y, as3xData[15], TEXT_SIZE + RIGHT)
end
-- Debug Values
if (DEBUG_ON) then
local titles = {[0]=
"0500","0502","0504","0506","0508","050B","050D"}
local values = {[0]=
s0500,s0502,s0504,s0506,s0508,s050B,s050D }
y = Y_LINE_HEIGHT*2 + Y_HEADER
for iParam=0,#titles do -- ??
-- labels
local x = X_COL1_HEADER+250
local val = titles[iParam]
lcd.drawText (x, y, val, TEXT_SIZE)
val = values[iParam] or "--"
x = X_COL1_DATA+250
lcd.drawText (x, y, val, TEXT_SIZE)
y = y + Y_LINE_HEIGHT
end
end
end
local function drawAS3XSettingsP1(event)
drawAS3XSettings(event, 1)
end
local function drawAS3XSettingsP2(event)
drawAS3XSettings(event, 2)
end
local function doFloat(v)
if v==nil then return 0.0 end
local vs = string.format("%1.2f",v)
return vs + 0.0
end
local ESC_Title={[0]="","RPM:","Volts:","Motor:","Mot Out:","Throttle:","FET Temp:", "BEC V:", "BEC T:", "BEC A:"}
local ESC_uom={[0]="","","V","A","%","%","C", "V","C","A"}
local ESC_Status={[0]=0,0,0,0,0,0,0,0,0,0,0}
local ESC_Min={[0]=0,0,0,0,0,0,0,0,0,0,0}
local ESC_Max={[0]=0,0,0,0,0,0,0,0,0,0,0}
local function drawESCStatus(event)
lcd.clear()
ESC_Status[1] = getValue("Erpm") -- RPM
ESC_Status[2] = doFloat(getValue("EVIN")) -- Volts
ESC_Status[3] = doFloat(getValue("ECUR")) -- Current
ESC_Status[4] = doFloat(getValue("EOUT")) -- % Output
ESC_Status[5] = doFloat(getValue("ETHR")) -- Throttle % (EOUT)
ESC_Status[6] = getValue("TFET") -- Temp FET
ESC_Status[7] = doFloat(getValue("VBEC")) -- Volts BEC
ESC_Status[8] = getValue("TBEC") -- Temp BEC
ESC_Status[9] = doFloat(getValue("CBEC")) -- Current BEC
for i=1,9 do
if (ESC_Status~=nil) then
if (ESC_Min[i]==0) then
ESC_Min[i]=ESC_Status[i]
else
ESC_Min[i] = math.min(ESC_Min[i],ESC_Status[i])
end
ESC_Max[i] = math.max(ESC_Max[i],ESC_Status[i])
end
end
lcd.drawText (0,0, "ESC", TEXT_SIZE+INVERS)
local y = 0
local x_data = X_COL1_DATA+X_DATA_LEN*1.5
local x_data2 = X_COL2_DATA+X_DATA_LEN*0.5
local x_data3 = x_data2 + X_DATA_LEN*0.8
lcd.drawText (x_data,y , "Status", TEXT_SIZE+BOLD+RIGHT)
lcd.drawText (x_data2,y, "Min", TEXT_SIZE+BOLD+RIGHT)
lcd.drawText (x_data3,y, "Max", TEXT_SIZE+BOLD+RIGHT)
y = Y_DATA
for i=1,9 do
lcd.drawText (X_COL1_HEADER,y, ESC_Title[i], TEXT_SIZE + BOLD)
lcd.drawText (x_data,y, ESC_Status[i] or "--", TEXT_SIZE + RIGHT)
lcd.drawText (x_data + X_DATA_SPACE,y, ESC_uom[i], TEXT_SIZE)
lcd.drawText (x_data2,y, ESC_Min[i] or "--", TEXT_SIZE + RIGHT)
lcd.drawText (x_data3,y, ESC_Max[i] or "--", TEXT_SIZE + RIGHT)
y = y + Y_LINE_HEIGHT
end
end
local function drawBATStatus(event)
local Title={[0]="","Bat:","Temp:","Rem :","Curr:","Used:","Imbal:","Cycles:", "RX:", "BCpT?:"}
local uom={[0]="","V","C","%","mAh","mAh","mV","", "V",""}
local Values={[0]=0,0,0,0,0,0,0,0,0,0,0}
local CellValues={[0]=0,0,0,0,0,0,0,0,0,0,0}
lcd.clear()
local ESC_Volts = getValue("EVIN") or 0 -- Volts
local ESC_Current = getValue("ECUR") or 0 -- Current
Values[1] = 0 -- compute later
Values[2] = getValue("BTmp") -- Current (C)
Values[3] = nil -- Remaining???
Values[4] = getValue("BCur") -- Current (mAh)
Values[5] = getValue("BUse") -- Current Used (mAh)
Values[6] = getValue("CLMa") -- 0.0 (mV) Imbalance
Values[7] = getValue("Cycl") -- Cycles
Values[8] = readBatValue("A2") -- v
Values[9] = getValue("BCpT") -- Current (mAh) ????
--- Total Voltange Calculation
local VTotal=0
for i=1,10 do
CellValues[i] = getValue("Cel"..i)
VTotal = VTotal + CellValues[i]
end
if (VTotal==0) then -- No Inteligent Battery,use intelligent ESC if any
VTotal = ESC_Volts
Values[4] = string.format("%d",ESC_Current * 1000)
end
Values[1] = string.format("%2.2f",VTotal)
--- SCREEN
lcd.drawText (X_COL1_HEADER,0, "Battery Stats", TEXT_SIZE+INVERS)
local y = Y_DATA
local x_data = X_COL1_DATA+X_DATA_LEN+X_DATA_SPACE*3
for i=2,9 do
lcd.drawText (X_COL1_HEADER, y, Title[i], TEXT_SIZE + BOLD)
lcd.drawText (x_data, y, Values[i] or "--", TEXT_SIZE + RIGHT)
lcd.drawText (x_data+X_DATA_SPACE, y, uom[i], TEXT_SIZE)
y = y + Y_LINE_HEIGHT
end
y = Y_DATA
x_data = X_COL2_DATA+X_DATA_LEN+X_DATA_SPACE*5
for i=1,8 do
if ((CellValues[i] or 0) > 0) then
lcd.drawText (X_COL2_HEADER+X_DATA_LEN/2,y, "Cel "..i..":", TEXT_SIZE + BOLD)
lcd.drawText (x_data,y, string.format("%2.2f",CellValues[i] or 0), TEXT_SIZE + RIGHT)
lcd.drawText (x_data+X_DATA_SPACE,y, "v", TEXT_SIZE)
end
y = y + Y_LINE_HEIGHT
end
lcd.drawText (X_COL2_HEADER+X_DATA_LEN/2,0, Title[1], TEXT_SIZE + INVERS + BOLD)
lcd.drawText (x_data,0, string.format("%2.2f",Values[1] or 0), TEXT_SIZE + INVERS+ RIGHT)
lcd.drawText (x_data+X_DATA_SPACE, 0, uom[1], TEXT_SIZE + INVERS)
end
local function openTelemetryRaw(i2cId)
--Init telemetry (Spectrun Telemetry Raw STR)
multiBuffer( 0, string.byte('S') )
multiBuffer( 1, string.byte('T') )
multiBuffer( 2, string.byte('R') )
multiBuffer( 3, i2cId ) -- Monitor this teemetry data
multiBuffer( 4, 0 ) -- Allow to get Data
end
local function closeTelemetryRaw()
multiBuffer(0, 0) -- Destroy the STR header
multiBuffer(3, 0) -- Not requesting any Telementry ID
end
local lineText = {nil}
local I2C_TEXT_GEN = 0x0C
local function drawTextGen(event)
if (multiBuffer(0)~=string.byte('S')) then -- First time run???
openTelemetryRaw(I2C_TEXT_GEN) -- I2C_ID for TEXT_GEN
lineText = {nil}
end
-- Proces TEXT GEN Telementry message
if multiBuffer( 4 ) == I2C_TEXT_GEN then -- Specktrum Telemetry ID of data received
local instanceNo = multiBuffer( 5 )
local lineNo = multiBuffer( 6 )
local line = ""
for i=0,13 do
line = line .. string.char(multiBuffer( 7 + i ))
end
multiBuffer( 4, 0 ) -- Clear Semaphore, to notify that we fully process the current message
lineText[lineNo]=line
end
lcd.clear()
-- Header
if (lineText[0]) then
lcd.drawText (X_COL1_HEADER,0, " "..lineText[0].." ", TEXT_SIZE + BOLD + INVERS)
else
lcd.drawText (X_COL1_HEADER,0, "TextGen", TEXT_SIZE+INVERS)
end
-- Menu lines
local y = Y_DATA
for i=1,8 do
if (lineText[i]) then
lcd.drawText (X_COL1_HEADER,y, lineText[i], TEXT_SIZE)
end
y = y + Y_LINE_HEIGHT
end
if event == EVT_VIRTUAL_EXIT then -- Exit?? Clear menu data
closeTelemetryRaw()
end
end
local telPage = 1
local telPageSelected = 0
local pageTitle = {[0]="Main", "AS3X Settings", "SAFE Settings", "ESC Status", "Battery Status","TextGen","Flight Log"}
local function drawMainScreen(event)
lcd.clear()
lcd.drawText (X_COL1_HEADER, Y_HEADER, "Main Telemetry (Smart RXs)", TEXT_SIZE + INVERS)
for iParam=1,#pageTitle do
-- highlight selected parameter
local attr = (telPage==iParam) and INVERS or 0
-- set y draw coord
local y = (iParam)*Y_LINE_HEIGHT+Y_DATA
-- labels
local x = X_COL1_HEADER
local val = pageTitle[iParam]
lcd.drawText (x, y, val, attr + TEXT_SIZE)
end
if event == EVT_VIRTUAL_PREV then
if (telPage>1) then telPage = telPage - 1 end
elseif event == EVT_VIRTUAL_NEXT then
if (telPage<#pageTitle) then telPage = telPage + 1 end
elseif event == EVT_VIRTUAL_ENTER then
telPageSelected = telPage
end
end
local pageDraw = {[0]=drawMainScreen, drawAS3XSettingsP1, drawAS3XSettingsP2, drawESCStatus, drawBATStatus, drawTextGen, drawFlightLogScreen}
local function run_func(event)
if event == nil then
error("Cannot be run as a model script!")
return 2
end
-- draw specific page
pageDraw[telPageSelected](event)
if event == EVT_VIRTUAL_EXIT then
if (telPageSelected==0) then return 1 end -- on Main?? Exit Script
telPageSelected = 0 -- any page, return to Main
end
return 0
end
local function init_func()
if (LCD_W <= 128 or LCD_H <=64) then -- Smaller Screens
TEXT_SIZE = SMLSIZE
X_COL1_HEADER = 0
X_COL1_DATA = 20
X_COL2_HEADER = 60
X_COL2_DATA = 90
X_DATA_LEN = 28
X_DATA_SPACE = 1
Y_LINE_HEIGHT = 8
Y_DATA = Y_HEADER + Y_LINE_HEIGHT
end
end
return { run=run_func, init=init_func }

View File

@@ -86,7 +86,8 @@
55,1,FrSkyRX,CloneTX,0
55,2,FrSkyRX,EraseTX,0
55,3,FrSkyRX,CPPM,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
58,0,FX816,Std,1
58,0,FX,816,1
58,1,FX,620,1
20,0,FY326,FY326,1,Flip,RTH,HLess,Expert,Calib
20,1,FY326,FY319,1,Flip,RTH,HLess,Expert,Calib
23,0,FY326,FY326,1,Flip,RTH,HLess,Expert
@@ -116,6 +117,7 @@
71,1,JJRC345,SkyTmblr,1,Flip,HLess,RTH,LED,UNK1,UNK2,UNK3
49,0,KF606,KF606,1,Trim
49,1,KF606,MIG320,1,Trim,LED
49,2,KF606,ZCZ50,1,Trim,UNK
9,0,KN,WLToys,0,DRate,THold,IdleUp,Gyro,Ttrim,Atrim,Etrim
9,1,KN,Feilun,0,DRate,THold,IdleUp,Gyro,Ttrim,Atrim,Etrim
73,0,Kyosho,Std,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14
@@ -171,6 +173,7 @@
5,1,V2x2,JXD506,1,Flip,Light,Pict,Video,HLess,StaSto,Emerg,Cam_UD
48,0,V761,3CH,0,Gyro,Calib,Flip,RtnAct,Rtn
48,1,V761,4CH,0,Gyro,Calib,Flip,RtnAct,Rtn
48,2,V761,TOPRC,0,Gyro,Calib,Flip,RtnAct,Rtn
46,0,V911s,V911s,1,Calib,Rate
46,1,V911s,E119,1,Calib,Rate,6G_3D
22,0,WFLY,WFR0xS,0,CH5,CH6,CH7,CH8,CH9
@@ -203,3 +206,5 @@
90,1,MouldKg,Digit,0
91,0,Xerall,Tank,0,FlTa,TakLan,Rate,HLess,Photo,Video,TrimR,TrimE,TrimA
92,0,MT99xx2,PA18,0,MODE,FLIP,RTH
93,0,Kyosho2,KT-17,0
94,0,Scorpio

View File

@@ -60,16 +60,14 @@ The OpenTX sensor "RSSI" is populated by the individual OpenTX telemetry protoco
## DSM Forward Programming
Navigation is mainly done using the scroll wheel and ENT. Short press on ENT will edit a value. When editing a value a long ENT press will restore the value to its default. To exit the script and terminate all current operations correctly short press RTN (if you don't do this the RX might not store the changes).
This is a work in progress. It's available for color(+touch) and B&W screens.
This is a work in progress. It's only available for color screens (Horus, TX16S, T16, T18...).
If some text appears as Unknown_xxx, please report xxx and what the exact text display should be.
Need OpenTX 2.3.10 nightly or above. Located on the radio SD card under \SCRIPTS\TOOLS.
Work on OpenTX and EdgeTX. Located on the radio SD card under \SCRIPTS\TOOLS, make sure to copy the DSMLIB folder along with DSM FwdPrg_05_Color.lua or DSM FwdPrg_05_BW.lua.
[![DSM Forward Programming](https://img.youtube.com/vi/sjIaDw5j9nE/0.jpg)](https://www.youtube.com/watch?v=sjIaDw5j9nE)
If some text appears as Unknown_xxx, please report xxx and what the exact text display should be.
## DSM PID Flight log gain parameters for Blade micros
Lua telemetry script from [feathering on RCGroups](https://www.rcgroups.com/forums/showpost.php?p=46033341&postcount=20728) to facilitate setting the Gain Parameters on the Blade 150S FBL. It doesn't use Forward Programming but instead it just reads telemetry data from the Multi-module and displays it on a telemetry display.

View File

@@ -292,10 +292,17 @@ uint16_t AFHDS2A_callback()
case AFHDS2A_BIND2:
case AFHDS2A_BIND3:
AFHDS2A_build_bind_packet();
data_rx=A7105_ReadReg(A7105_00_MODE); // Check if something has been received...
A7105_WriteData(AFHDS2A_TXPACKET_SIZE, packet_count%2 ? 0x0d : 0x8c);
if(!(A7105_ReadReg(A7105_00_MODE) & (1<<5))) // removed FECF check due to issues with fs-x6b -> & (1<<5 | 1<<6)
{ // CRCF Ok
if(!(A7105_ReadReg(A7105_00_MODE) & (1<<5)) && !(data_rx & 1)) // removed FECF check due to issues with fs-x6b -> & (1<<5 | 1<<6)
{ // RX+CRCF Ok
A7105_ReadData(AFHDS2A_RXPACKET_SIZE);
#if 0
debug("RX");
for(uint8_t i=0; i<AFHDS2A_RXPACKET_SIZE ; i++)
debug(" %02X", packet[i]);
debugln("");
#endif
if(packet[0] == 0xbc && packet[9] == 0x01)
{
uint16_t addr;
@@ -330,7 +337,7 @@ uint16_t AFHDS2A_callback()
if(!(A7105_ReadReg(A7105_00_MODE) & 0x01))
break;
A7105_SetPower();
A7105_SetTxRxMode(TXRX_OFF); // Turn LNA off since we are in near range and we want to prevent swamping
A7105_SetTxRxMode((packet_count & 0x40) ? TXRX_OFF : RX_EN); // Turn LNA off time to time since we are in near range and we want to prevent swamping
A7105_Strobe(A7105_RX);
phase &= ~AFHDS2A_WAIT_WRITE;
phase++;

View File

@@ -249,6 +249,10 @@ static uint8_t __attribute__((unused)) DSM_Check_RX_packet()
uint16_t DSM_callback()
{
#if defined MULTI_EU
if(sub_protocol == DSM2_1F || sub_protocol == DSM2_2F)
return 11000;
#endif
#define DSM_CH1_CH2_DELAY 4010 // Time between write of channel 1 and channel 2
#ifdef STM32_BOARD
#define DSM_WRITE_DELAY 1600 // Time after write to verify write complete

View File

@@ -1,100 +0,0 @@
/*
This project is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Multiprotocol is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Multiprotocol. If not, see <http://www.gnu.org/licenses/>.
*/
// Compatible with FEI XIONG P38 plane.
#if defined(FX816_NRF24L01_INO)
#include "iface_xn297.h"
#define FX816_INITIAL_WAIT 500
#define FX816_PACKET_PERIOD 10000
#define FX816_RF_BIND_CHANNEL 0x28 //40
#define FX816_RF_NUM_CHANNELS 4
#define FX816_PAYLOAD_SIZE 6
#define FX816_BIND_COUNT 300 //3sec
static void __attribute__((unused)) FX816_send_packet()
{
if(IS_BIND_IN_PROGRESS)
packet[0] = 0x55;
else
{
XN297_Hopping(hopping_frequency_no++);
hopping_frequency_no%=FX816_RF_NUM_CHANNELS;
packet[0] = 0xAA;
}
packet[1] = rx_tx_addr[0];
packet[2] = rx_tx_addr[1];
uint8_t val=convert_channel_8b(AILERON);
#define FX816_SWITCH 20
if(val>127+FX816_SWITCH)
packet[3] = 1;
else if(val<127-FX816_SWITCH)
packet[3] = 2;
else
packet[3] = 0;
packet[4] = convert_channel_16b_limit(THROTTLE,0,100);
val=0;
for(uint8_t i=0;i<FX816_PAYLOAD_SIZE-1;i++)
val+=packet[i];
packet[5]=val;
// Send
XN297_SetPower();
XN297_SetTxRxMode(TX_EN);
XN297_WritePayload(packet, FX816_PAYLOAD_SIZE);
}
static void __attribute__((unused)) FX816_RF_init()
{
XN297_Configure(XN297_CRCEN, XN297_SCRAMBLED, XN297_1M);
XN297_SetTXAddr((uint8_t *)"\xcc\xcc\xcc\xcc\xcc", 5);
//XN297_HoppingCalib(FX816_RF_NUM_CHANNELS);
XN297_RFChannel(FX816_RF_BIND_CHANNEL);
}
static void __attribute__((unused)) FX816_initialize_txid()
{
//Only 8 IDs: the RX led does not indicate frame loss.
//I didn't open the plane to find out if I could connect there so this is the best I came up with with few trial and errors...
rx_tx_addr[0]=0x35+(rx_tx_addr[3]&0x07); //Original dump=0x35
rx_tx_addr[1]=0x09; //Original dump=0x09
memcpy(hopping_frequency,"\x09\x1B\x30\x42",FX816_RF_NUM_CHANNELS); //Original dump=9=0x09,27=0x1B,48=0x30,66=0x42
for(uint8_t i=0;i<FX816_RF_NUM_CHANNELS;i++)
hopping_frequency[i]+=rx_tx_addr[3]&0x07;
}
uint16_t FX816_callback()
{
#ifdef MULTI_SYNC
telemetry_set_input_sync(FX816_PACKET_PERIOD);
#endif
if(bind_counter)
if(--bind_counter==0)
BIND_DONE;
FX816_send_packet();
return FX816_PACKET_PERIOD;
}
void FX816_init()
{
BIND_IN_PROGRESS; // autobind protocol
FX816_initialize_txid();
FX816_RF_init();
hopping_frequency_no = 0;
bind_counter=FX816_BIND_COUNT;
}
#endif

View File

@@ -0,0 +1,240 @@
/*
This project is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Multiprotocol is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Multiprotocol. If not, see <http://www.gnu.org/licenses/>.
*/
// Compatible with FEI XIONG P38 plane.
#if defined(FX_NRF24L01_INO)
#include "iface_xn297.h"
#define FX_BIND_COUNT 300 //3sec
#define FX_SWITCH 20
#define FX_NUM_CHANNELS 4
#define FX816_PACKET_PERIOD 10000
#define FX816_BIND_CHANNEL 40
#define FX816_PAYLOAD_SIZE 6
#define FX816_CH_OFFSET 3
#define FX620_PACKET_PERIOD 3250
#define FX620_BIND_PACKET_PERIOD 4500
#define FX620_BIND_CHANNEL 18
#define FX620_PAYLOAD_SIZE 7
#define FX620_CH_OFFSET 1
#define FX9630_PACKET_PERIOD 8124
#define FX9630_BIND_PACKET_PERIOD 8124
#define FX9630_BIND_CHANNEL 51
#define FX9630_PAYLOAD_SIZE 8
#define FX9630_NUM_CHANNELS 3
//#define FORCE_FX620_ID
//#define FORCE_FX9630_ID
static void __attribute__((unused)) FX_send_packet()
{
//Hopp
if(IS_BIND_DONE)
{
XN297_Hopping(hopping_frequency_no++);
if(sub_protocol == FX9630)
{
XN297_SetTXAddr(rx_tx_addr, 4);
if (hopping_frequency_no > FX9630_NUM_CHANNELS)
hopping_frequency_no = 0;
}
else // FX816 and FX620
{
hopping_frequency_no &= 0x03;
}
}
memset(packet,0x00,packet_length);
//Channels
uint8_t val;
if (sub_protocol == FX9630)
{
packet[0] = convert_channel_8b(THROTTLE);
packet[1] = convert_channel_8b(AILERON);
packet[2] = 0xFF - convert_channel_8b(ELEVATOR);
packet[3] = convert_channel_8b(RUDDER);
packet[4] = 0x20;
packet[5] = GET_FLAG(CH5_SW, 0x01); // DR toggle swich: 0 small throw, 1 large throw
packet[5] |= (Channel_data[CH6] < CHANNEL_MIN_COMMAND ? 0x00 : (Channel_data[CH6] > CHANNEL_MAX_COMMAND ? 0x02 : 0x01)) << 1; // Mode A(0) : 6D small throw, B(1) : 6D large throw, C(2) : 3D
}
else // FX816 and FX620
{
uint8_t offset=sub_protocol == FX816 ? FX816_CH_OFFSET:FX620_CH_OFFSET;
val=convert_channel_8b(AILERON);
if(val>127+FX_SWITCH)
packet[offset] = sub_protocol == FX816 ? 1:0xFF;
else if(val<127-FX_SWITCH)
packet[offset] = sub_protocol == FX816 ? 2:0x00;
else
packet[offset] = sub_protocol == FX816 ? 0:0x7F;
packet[offset+1] = convert_channel_16b_limit(THROTTLE,0,100); //FX816:0x00..0x63, FX620:0x00..0x5E but that should work
}
//Bind and specifics
if(sub_protocol == FX816)
{
if(IS_BIND_IN_PROGRESS)
packet[0] = 0x55;
else
packet[0] = 0xAA;
packet[1] = rx_tx_addr[0];
packet[2] = rx_tx_addr[1];
}
else if(sub_protocol == FX620)
{
if(IS_BIND_IN_PROGRESS)
{
memcpy(packet,rx_tx_addr,3);
packet[3] = hopping_frequency[0];
if(bind_counter > (FX_BIND_COUNT >> 1))
packet[5] = 0x78;
}
else
{
packet[0] = 0x1F; // Is it based on ID??
packet[5] = 0xAB; // Is it based on ID??
}
}
else // FX9630
{
if(IS_BIND_IN_PROGRESS)
{
memcpy(packet,rx_tx_addr, 4);
packet[4] = hopping_frequency[1];
packet[5] = hopping_frequency[2];
packet[7] = 0x55;
}
}
//Check
uint8_t last_packet_idx = packet_length-1;
if (sub_protocol == FX9630 && IS_BIND_IN_PROGRESS)
last_packet_idx--;
val=0;
for(uint8_t i=0;i<last_packet_idx;i++)
val+=packet[i];
if (sub_protocol == FX9630)
val = val ^ 0xFF;
packet[last_packet_idx]=val;
//Debug
#if 0
for(uint8_t i=0;i<packet_length;i++)
debug("%02X ",packet[i]);
debugln("");
#endif
// Send
XN297_SetPower();
XN297_SetTxRxMode(TX_EN);
XN297_WritePayload(packet, packet_length);
}
static void __attribute__((unused)) FX_RF_init()
{
XN297_Configure(XN297_CRCEN, XN297_SCRAMBLED, XN297_1M);
if(sub_protocol == FX816)
{
XN297_SetTXAddr((uint8_t *)"\xcc\xcc\xcc\xcc\xcc", 5);
XN297_RFChannel(FX816_BIND_CHANNEL);
packet_period = FX816_PACKET_PERIOD;
packet_length = FX816_PAYLOAD_SIZE;
}
else if(sub_protocol == FX620)
{
XN297_SetTXAddr((uint8_t *)"\xaa\xbb\xcc", 3);
XN297_RFChannel(FX620_BIND_CHANNEL);
packet_period = FX620_BIND_PACKET_PERIOD;
packet_length = FX620_PAYLOAD_SIZE;
}
else // FX9630
{
XN297_SetTXAddr((uint8_t *)"\x56\x78\x90\x12", 4);
XN297_RFChannel(FX9630_BIND_CHANNEL);
packet_period = FX9630_BIND_PACKET_PERIOD;
packet_length = FX9630_PAYLOAD_SIZE;
}
}
static void __attribute__((unused)) FX_initialize_txid()
{
if(sub_protocol == FX816)
{
//Only 8 IDs: the RX led does not indicate frame loss.
//I didn't open the plane to find out if I could connect there so this is the best I came up with with few trial and errors...
rx_tx_addr[0]=0x35+(rx_tx_addr[3]&0x07); //Original dump=0x35
rx_tx_addr[1]=0x09; //Original dump=0x09
memcpy(hopping_frequency,"\x09\x1B\x30\x42",FX_NUM_CHANNELS); //Original dump=9=0x09,27=0x1B,48=0x30,66=0x42
for(uint8_t i=0;i<FX_NUM_CHANNELS;i++)
hopping_frequency[i]+=rx_tx_addr[3]&0x07;
}
else if(sub_protocol == FX620)
{
rx_tx_addr[0] = rx_tx_addr[3];
hopping_frequency[0] = 0x18 + rx_tx_addr[3]&0x07; // just to try something
#ifdef FORCE_FX620_ID
memcpy(rx_tx_addr,(uint8_t*)"\x34\xA9\x32",3);
hopping_frequency[0] = 0x18; //on dump: 24 34 44 54
#endif
for(uint8_t i=1;i<FX_NUM_CHANNELS;i++)
hopping_frequency[i] = i*10 + hopping_frequency[0];
}
else // FX9630
{
#ifdef FORCE_FX9630_ID
memcpy(rx_tx_addr,(uint8_t*)"\xCE\x31\x9B\x73", 4);
memcpy(hopping_frequency,"\x13\x1A\x38", FX9630_NUM_CHANNELS); //Original dump=19=0x13,26=0x1A,56=0x38
#else
hopping_frequency[0] = 0x13; // constant
hopping_frequency[1] = RX_num & 0x0F + 0x1A;
hopping_frequency[2] = rx_tx_addr[3] & 0x0F + 0x38;
#endif
}
}
uint16_t FX_callback()
{
#ifdef MULTI_SYNC
telemetry_set_input_sync(packet_period);
#endif
if(bind_counter)
if(--bind_counter==0)
{
BIND_DONE;
if(sub_protocol == FX620)
{
XN297_SetTXAddr(rx_tx_addr, 3);
packet_period = FX620_PACKET_PERIOD;
}
}
FX_send_packet();
return packet_period;
}
void FX_init()
{
BIND_IN_PROGRESS; // autobind protocol
FX_initialize_txid();
FX_RF_init();
hopping_frequency_no = 0;
bind_counter=FX_BIND_COUNT;
}
#endif

View File

@@ -100,7 +100,7 @@ static void __attribute__((unused)) FrSkyX_build_packet()
FrSkyX_channels(7); // Set packet[7]=failsafe, packet[8]=0?? and packet[9..20]=channels data
//Sequence and send SPort
FrSkyX_seq_sport(21,packet_length-2); //21=RX|TXseq, 22=bytes count, 23..packet_length-2=data
FrSkyX_seq_sport(21,packet_length-(protocol==PROTO_FRSKYX && (FrSkyFormat & 2 )) ? 4 : 2); //21=RX|TXseq, 22=bytes count, 23..packet_length-2=data
//CRC
uint16_t lcrc = FrSkyX_crc(&packet[3], packet_length-4);
@@ -116,6 +116,10 @@ static void __attribute__((unused)) FrSkyX_build_packet()
uint16_t FRSKYX_callback()
{
#if defined MULTI_EU
if(sub_protocol == CH_16 || sub_protocol == CH_8)
return 9000;
#endif
switch(state)
{
default:

View File

@@ -36,7 +36,7 @@ enum PktState {
};
const uint8_t PROGMEM j6pro_bind_sop_code[] = {0x62, 0xdf, 0xc1, 0x49, 0xdf, 0xb1, 0xc0, 0x49};
const uint8_t j6pro_data_code[] = {0x02, 0xf9, 0x93, 0x97, 0x02, 0xfa, 0x5c, 0xe3, 0x01, 0x2b, 0xf1, 0xdb, 0x01, 0x32, 0xbe, 0x6f};
//const uint8_t j6pro_data_code[] = {0x02, 0xf9, 0x93, 0x97, 0x02, 0xfa, 0x5c, 0xe3, 0x01, 0x2b, 0xf1, 0xdb, 0x01, 0x32, 0xbe, 0x6f}; // unneeded since this is the default table after a reset
static void __attribute__((unused)) j6pro_build_bind_packet()
{
@@ -84,7 +84,7 @@ static void __attribute__((unused)) j6pro_cyrf_init()
CYRF_WriteRegister(CYRF_10_FRAMING_CFG, 0xee);
CYRF_WriteRegister(CYRF_1F_TX_OVERRIDE, 0x00);
CYRF_WriteRegister(CYRF_1E_RX_OVERRIDE, 0x00);
CYRF_ConfigDataCode(j6pro_data_code, 16);
//CYRF_ConfigDataCode(j6pro_data_code, 16);
CYRF_WritePreamble(0x333302);
CYRF_GetMfgData(cyrfmfg_id);

View File

@@ -20,6 +20,7 @@ Multiprotocol is distributed in the hope that it will be useful,
//#define FORCE_KF606_ORIGINAL_ID
//#define FORCE_MIG320_ORIGINAL_ID
//#define FORCE_ZCZ50_ORIGINAL_ID
#define KF606_INITIAL_WAIT 500
#define KF606_PACKET_PERIOD 3000
@@ -30,10 +31,16 @@ Multiprotocol is distributed in the hope that it will be useful,
static void __attribute__((unused)) KF606_send_packet()
{
uint8_t len = KF606_PAYLOAD_SIZE;
if(IS_BIND_IN_PROGRESS)
{
packet[0] = 0xAA;
memcpy(&packet[1],rx_tx_addr,3);
if(sub_protocol != KF606_ZCZ50)
{
packet[0] = 0xAA;
memcpy(&packet[1],rx_tx_addr,3);
}
else
memcpy(packet,rx_tx_addr,4);
}
else
{
@@ -43,25 +50,32 @@ static void __attribute__((unused)) KF606_send_packet()
packet[0] = 0x55;
packet[1] = convert_channel_8b(THROTTLE); // 0..255
// Deadband is needed on aileron, 40 gives +-6%
if(sub_protocol == KF606_KF606)
switch(sub_protocol)
{
packet[2] = convert_channel_8b_limit_deadband(AILERON,0x20,0x80,0xE0,40); // Aileron: Max values:20..80..E0, Low rates:50..80..AF, High rates:3E..80..C1
packet[3] = convert_channel_16b_limit(CH5,0xC1,0xDF); // Aileron trim must be on a separated channel C1..D0..DF
}
else
{
packet[2] = convert_channel_8b_limit_deadband(AILERON,0x00,0x80,0xFF,40); // Aileron: High rate:2B..80..DA
packet[3] = convert_channel_16b_limit(CH5,0x01,0x1F); // Aileron trim must be on a separated channel 01..10..1F
packet[3] += (packet[2]-0x80)>>3; // Drive trims for more aileron authority
if(packet[3] > 0x80)
packet[3] = 0x01;
else if(packet[3] > 0x1F)
packet[3] = 0x1F;
packet[3] |= GET_FLAG(CH6_SW, 0xC0); // 0xC0 and 0xE0 are both turning the LED off, not sure if there is another hidden feature
case KF606_KF606:
packet[2] = convert_channel_8b_limit_deadband(AILERON,0x20,0x80,0xE0,40); // Aileron: Max values:20..80..E0, Low rates:50..80..AF, High rates:3E..80..C1
packet[3] = convert_channel_16b_limit(CH5,0xC1,0xDF); // Aileron trim must be on a separated channel C1..D0..DF
break;
case KF606_MIG320:
packet[2] = convert_channel_8b_limit_deadband(AILERON,0x00,0x80,0xFF,40); // Aileron: High rate:2B..80..DA
packet[3] = convert_channel_16b_limit(CH5,0x01,0x1F); // Aileron trim must be on a separated channel 01..10..1F
packet[3] += (packet[2]-0x80)>>3; // Drive trims for more aileron authority
if(packet[3] > 0x80)
packet[3] = 0x01;
else if(packet[3] > 0x1F)
packet[3] = 0x1F;
packet[3] |= GET_FLAG(CH6_SW, 0xC0); // 0xC0 and 0xE0 are both turning the LED off, not sure if there is another hidden feature
break;
case KF606_ZCZ50:
len--; // uses only 3 bytes of payload
packet[0] = packet[1]; // Throttle: 0x00..0xFF
packet[1] = convert_channel_8b_limit_deadband(AILERON,0x20,0x80,0xE0,40); // Aileron: Max values:20..80..E0, low rate 0x52..0x80..0xB1, high rate: 0x41..0x80..0xC3.
packet[2] = convert_channel_16b_limit(CH5,0x01,0x1F); // Trim: 0x01..0x10..0x1F
packet[2] |= GET_FLAG(CH6_SW, 0xC0); // Unknown: 0x00 or 0xC0. Left top switch on original TX changes nothing on my plane. Maybe ON/OFF for main motor?
break;
}
}
uint8_t len = KF606_PAYLOAD_SIZE;
if(sub_protocol == KF606_MIG320)
{
len++;
@@ -107,6 +121,19 @@ static void __attribute__((unused)) KF606_initialize_txid()
hopping_frequency[0]=68;
hopping_frequency[1]=71;
#endif
if(sub_protocol == KF606_ZCZ50)
{
rx_tx_addr[1] = rx_tx_addr[0];
rx_tx_addr[0]=0xAA;
}
#ifdef FORCE_ZCZ50_ORIGINAL_ID
rx_tx_addr[0]=0xAA;
rx_tx_addr[1]=0x67;
rx_tx_addr[2]=0x64;
rx_tx_addr[3]=0x01;
hopping_frequency[0]=48;
hopping_frequency[1]=51;
#endif
}
static void __attribute__((unused)) KF606_RF_init()
@@ -126,7 +153,7 @@ uint16_t KF606_callback()
if(--bind_counter==0)
{
BIND_DONE;
XN297_SetTXAddr(rx_tx_addr, 3);
XN297_SetTXAddr(rx_tx_addr, sub_protocol != KF606_ZCZ50 ? 3 : 4);
}
KF606_send_packet();
return KF606_PACKET_PERIOD;
@@ -153,3 +180,14 @@ void KF606_init()
// P[2] = AIL 2B..80..DA
// P[3] = TRIM 01..10..1F
// channels 68=BB&3F+9 and 71
// ZCZ50v2 protocol (with fake front propeller)
// Bind
// 250K C=7 S=Y A= E7 E7 E7 E7 E7 P(4)= AA 67 64 01
// 3ms on ch7
// Normal
// 250K C=48 S=Y A= AA 67 64 01 P(3)= 00 80 10
// P[0] = THR 0x00..0xFF
// P[1] = AIL low rate 0x52..0x80..0xB1, high rate: 0x41..0x80..0xC3
// P[2] = TRIM 0x01..0x10..0x1F + UNKNOWN 0x00 or 0xC0

View File

@@ -0,0 +1,141 @@
/*
This project is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Multiprotocol is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Multiprotocol. If not, see <http://www.gnu.org/licenses/>.
*/
#if defined(KYOSHO2_NRF24L01_INO)
#include "iface_nrf24l01.h"
#define KYOSHO2_PACKET_PERIOD 1120
#define KYOSHO2_BIND_PACKET_PERIOD 1600
#define KYOSHO2_BIND_COUNT 6000 // about 9sec
#define KYOSHO2_BIND_CHANNEL 0x50
#define KYOSHO2_PAYLOAD_SIZE 28
#define KYOSHO2_RF_CHANNELS 15
#define KYOSHO2_START_RF_CHANNEL 0x13 // No idea where it comes from... ID or unknown bytes during the bind?
#define KYOSHO2_NUM_CHANNEL 10 // Only 4 on the dumps but there is space for 10 channels in the payload...
#define FORCE_KYOSHO2_ID
bool KYOSHO2_resend;
//
static void __attribute__((unused)) KYOSHO2_send_packet()
{
if(KYOSHO2_resend == true)
{
NRF24L01_Strobe(NRF24L01_E3_REUSE_TX_PL);
if(IS_BIND_DONE)
KYOSHO2_resend = false;
return;
}
memset(packet,0x00,KYOSHO2_PAYLOAD_SIZE);
if(IS_BIND_IN_PROGRESS)
{
memcpy(packet, (uint8_t*)"\x01\x02\x05\x08\x1A\x2B\x3C\x4D", 8); // unknown bytes, parameters on how to build the rf channels?
memcpy(&packet[8], rx_tx_addr, 4);
}
else
{
memcpy(packet, rx_tx_addr, 4);
//Hopp
packet[6] = hopping_frequency_no + KYOSHO2_START_RF_CHANNEL;
packet[7] = hopping_frequency[hopping_frequency_no];
NRF24L01_WriteReg(NRF24L01_05_RF_CH, packet[6+(rf_ch_num&0x01)]);
rf_ch_num++;
//Channels
uint16_t temp;
for (uint8_t i = 0; i< KYOSHO2_NUM_CHANNEL; i++)
{
temp=convert_channel_16b_limit(i,0,0x3FF);
packet[8+i*2] = temp >> 8;
packet[9+i*2] = temp;
}
}
//Send
NRF24L01_WriteReg(NRF24L01_07_STATUS, (_BV(NRF24L01_07_TX_DS) | _BV(NRF24L01_07_MAX_RT))); // Reset flags
NRF24L01_FlushTx();
NRF24L01_WritePayload(packet,KYOSHO2_PAYLOAD_SIZE);
NRF24L01_SetPower();
KYOSHO2_resend = true;
#if 0
for(uint8_t i=0;i<KYOSHO2_PAYLOAD_SIZE;i++)
debug("%02X ", packet[i]);
debugln("");
#endif
}
static void __attribute__((unused)) KYOSHO2_RF_init()
{
NRF24L01_Initialize();
NRF24L01_WriteReg(NRF24L01_05_RF_CH, KYOSHO2_BIND_CHANNEL);
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, (uint8_t*)"\x69\x53\x10\xAC\xEF", 5);
}
static void __attribute__((unused)) KYOSHO2_initialize_tx_id()
{
hopping_frequency_no = rx_tx_addr[3]%KYOSHO2_RF_CHANNELS;
hopping_frequency[0] = 0x4A;
#ifdef FORCE_KYOSHO2_ID
memcpy(rx_tx_addr, (uint8_t*)"\x0A\xBD\x31\xDF", 4);
hopping_frequency[0] = 0x4A; // No idea where it comes from... ID or unknown bytes during the bind?
#endif
for(uint8_t i=1;i<KYOSHO2_RF_CHANNELS;i++)
{
if(hopping_frequency[i-1]+5 < 0x50)
hopping_frequency[i] = hopping_frequency[i-1]+5;
else
hopping_frequency[i] = hopping_frequency[i-1]-0x21;
}
#if 0
for(uint8_t i=0;i<KYOSHO2_RF_CHANNELS;i++)
debugln("1:%02X, 2: %02X", i + KYOSHO2_START_RF_CHANNEL, hopping_frequency[i]);
debugln("Selected 1:%02X, 2: %02X", hopping_frequency_no + KYOSHO2_START_RF_CHANNEL, hopping_frequency[hopping_frequency_no]);
#endif
}
uint16_t KYOSHO2_callback()
{
#ifdef MULTI_SYNC
telemetry_set_input_sync(KYOSHO2_PACKET_PERIOD);
#endif
KYOSHO2_send_packet();
if(bind_counter)
{
if(--bind_counter==0)
{
BIND_DONE;
KYOSHO2_resend = false;
}
return KYOSHO2_BIND_PACKET_PERIOD;
}
return KYOSHO2_PACKET_PERIOD;
}
void KYOSHO2_init()
{
KYOSHO2_initialize_tx_id();
KYOSHO2_RF_init();
rf_ch_num = 0;
if(IS_BIND_IN_PROGRESS)
bind_counter = KYOSHO2_BIND_COUNT;
else
bind_counter = 0;
KYOSHO2_resend = false;
}
#endif

View File

@@ -27,15 +27,15 @@
#define MT99XX_PACKET_PERIOD_DRAGON 1038 // there is a pause of 2x1038 between two packets, no idea why and how since it is not even stable on a same dump...
#define MT99XX_PACKET_PERIOD_DRAGON_TELEM 10265 // long pause to receive the telemetry packets, 3 are sent by the RX one after the other
#define MT99XX_PACKET_PERIOD_F949G 3450
#define MT99XX_PACKET_PERIOD_PA18 1160
#define MT99XX_PA18_CRC 0x89 // Is it a constant???
#define MT99XX_PACKET_PERIOD_PA18 1338
#define MT99XX_INITIAL_WAIT 500
#define MT99XX_PACKET_SIZE 9
//#define FORCE_A180_ID
//#define FORCE_DRAGON_ID
//#define FORCE_F949G_ID
#define FORCE_PA18_ID
#define FORCE_PA18_ID1
//#define FORCE_PA18_ID2
enum {
MT99XX_DATA,
@@ -115,10 +115,10 @@ static void __attribute__((unused)) MT99XX_send_packet()
//Set RF freq
if(sub_protocol == LS)
XN297_RFChannel(0x2D); // LS always transmits on the same channel
XN297_RFChannel(0x2D); // LS always transmits on the same channel
else
if(sub_protocol==FY805)
XN297_RFChannel(0x4B); // FY805 always transmits on the same channel
XN297_RFChannel(0x4B); // FY805 always transmits on the same channel
else // MT99 & H7 & YZ & A180 & DRAGON & F949G & PA18
XN297_Hopping(hopping_frequency_no);
@@ -154,7 +154,7 @@ static void __attribute__((unused)) MT99XX_send_packet()
packet[6] = rx_tx_addr[2];
if(sub_protocol == PA18+8)
{
packet[7] = MT99XX_PA18_CRC; // checksum offset
packet[7] = num_ch; // checksum offset
packet[8] = 0x55; // fixed
}
else
@@ -255,10 +255,10 @@ static void __attribute__((unused)) MT99XX_send_packet()
break;
case PA18+8:
if(Channel_data[CH5] > CHANNEL_MAX_COMMAND) // Expert mode
packet[5] += 0xA0;
packet[5] = 0xA0;
else
if(Channel_data[CH5] > CHANNEL_MIN_COMMAND) // Intermediate mode
packet[5] += 0x60;
packet[5] = 0x60;
packet[6] = GET_FLAG( CH6_SW, FLAG_PA18_FLIP ) // Flip
| GET_FLAG( CH7_SW, FLAG_PA18_RTH ); // RTH
if(hopping_frequency_no == 0)
@@ -269,7 +269,7 @@ static void __attribute__((unused)) MT99XX_send_packet()
for(uint8_t i=0; i<8; i++)
result += packet[i];
if(sub_protocol == PA18+8)
result += MT99XX_PA18_CRC;
result += num_ch;
packet[8] = result;
}
else
@@ -337,8 +337,8 @@ static void __attribute__((unused)) MT99XX_RF_init()
static void __attribute__((unused)) MT99XX_initialize_txid()
{
rx_tx_addr[1] = rx_tx_addr[3]; // RX_Num
num_ch = rx_tx_addr[1]; // PA18
rx_tx_addr[1] = rx_tx_addr[3]; // RX_Num
switch(sub_protocol)
{
case YZ:
@@ -381,20 +381,35 @@ static void __attribute__((unused)) MT99XX_initialize_txid()
//channel_offset = 0x03
break;
#endif
#ifdef FORCE_PA18_ID
#ifdef FORCE_PA18_ID1
case PA18+8:
rx_tx_addr[0] = 0xC9; // zebble ID
rx_tx_addr[1] = 0x02;
rx_tx_addr[2] = 0x13;
num_ch = 0x89; // additional crc init. How is this calculated? or could it be random?
//crc8 = 0xDE
// additional crc init of 0x89, how is this calculated???
//channel_offset = 0x03
//1Mb C=5 S=Y A= C9 02 13 CC CC P(9)= E1 70 70 70 20 20 00 20 1A
//1Mb C=5 S=Y A= C9 02 13 CC CC P(9)= E1 70 70 70 20 20 00 20 1A -> 0x91 + 0x89 => 0x1A
// S=Y A= C9 02 13 CC CC P(9)= E1 70 70 70 20 A0 00 20 9A -> 0x11 + 0x89 => 0x9A
//bind S=Y A= CC CC CC CC CC P(9)= 20 14 03 25 C9 02 13 89 55
break;
#endif
default: //MT99 & H7 & A180 & DRAGON & F949G
#ifdef FORCE_PA18_ID2
case PA18+8:
rx_tx_addr[0] = 0x0E;
rx_tx_addr[1] = 0x05;
rx_tx_addr[2] = 0x13;
num_ch = 0xD1; // additional crc init. How is this calculated? or could it be random?
//crc8 = 0x28
//channel_offset = 0x00
//1Mb C=2 S=Y A= 0E 05 13 CC CC P(9)= E1 70 70 70 20 60 00 60 E2 -> 0x11 + 0xD1 => 0xE2
//bind S=Y A= CC CC CC CC CC P(9)= 20 14 03 25 0E 05 13 D1 55
break;
#endif
default: //MT99 & H7 & A180 & DRAGON & F949G & PA18
rx_tx_addr[2] = 0x00;
if(sub_protocol == PA18+8)
rx_tx_addr[2] = 0x13;
break;
}

View File

@@ -45,8 +45,8 @@
45,E01X,E012,E015
46,V911S,V911S,E119
47,GD00x,GD_V1,GD_V2
48,V761,3CH,4CH
49,KF606,KF606,MIG320
48,V761,3CH,4CH,TOPRC
49,KF606,KF606,MIG320,ZCZ50
50,Redpine,Fast,Slow
51,Potensic,A20
52,ZSX,280
@@ -55,7 +55,7 @@
55,Frsky_RX,Multi,CloneTX,EraseTX,CPPM
56,AFHDS2A_RX,Multi,CPPM
57,HoTT,Sync,No_Sync
58,FX816
58,FX,816,620,9630
59,Bayang_RX,Multi,CPPM
60,Pelikan,Pro,Lite,SCX24
61,Tiger
@@ -88,4 +88,6 @@
89,Losi
90,MouldKg,Analog,Digit
91,Xerall
92,MT99xx,PA18
92,MT99xx,PA18
93,Kyosho2,KT-17
94,Scorpio

View File

@@ -78,7 +78,7 @@ const char STR_SCANNER[] ="Scanner";
const char STR_FRSKY_RX[] ="FrSkyRX";
const char STR_AFHDS2A_RX[] ="FS2A_RX";
const char STR_HOTT[] ="HoTT";
const char STR_FX816[] ="FX816";
const char STR_FX[] ="FX";
const char STR_BAYANG_RX[] ="BayanRX";
const char STR_PELIKAN[] ="Pelikan";
const char STR_TIGER[] ="Tiger";
@@ -88,6 +88,7 @@ const char STR_FRSKYR9[] ="FrSkyR9";
const char STR_PROPEL[] ="Propel";
const char STR_SKYARTEC[] ="Skyartc";
const char STR_KYOSHO[] ="Kyosho";
const char STR_KYOSHO2[] ="Kyosho2";
const char STR_RLINK[] ="RadLink";
const char STR_REALACC[] ="Realacc";
const char STR_OMP[] ="OMP";
@@ -104,14 +105,23 @@ const char STR_CONFIG[] ="Config";
const char STR_LOSI[] ="Losi";
const char STR_MOULDKG[] ="MouldKg";
const char STR_XERALL[] ="Xerall";
const char STR_SCORPIO[] ="Scorpio";
const char STR_SUBTYPE_FLYSKY[] = "\x04""Std\0""V9x9""V6x6""V912""CX20";
const char STR_SUBTYPE_HUBSAN[] = "\x04""H107""H301""H501";
const char STR_SUBTYPE_FRSKYD[] = "\x06""D8\0 ""Cloned";
const char STR_SUBTYPE_FRSKYX[] = "\x07""D16\0 ""D16 8ch""LBT(EU)""LBT 8ch""Cloned\0""Clo 8ch";
#ifndef MULTI_EU
const char STR_SUBTYPE_FRSKYX[] = "\x07""D16\0 ""D16 8ch""LBT(EU)""LBT 8ch""Cloned\0""Clo 8ch";
#else
const char STR_SUBTYPE_FRSKYX[] = "\x07""--->\0 ""--->\0 ""LBT(EU)""LBT 8ch""Cloned\0""Clo 8ch";
#endif
const char STR_SUBTYPE_HISKY[] = "\x05""Std\0 ""HK310";
const char STR_SUBTYPE_V2X2[] = "\x06""Std\0 ""JXD506""MR101\0";
const char STR_SUBTYPE_DSM[] = "\x04""2 1F""2 2F""X 1F""X 2F""Auto""R 1F";
#ifndef MULTI_EU
const char STR_SUBTYPE_DSM[] = "\x04""2 1F""2 2F""X 1F""X 2F""Auto""R 1F";
#else
const char STR_SUBTYPE_DSM[] = "\x04""--->""--->""X 1F""X 2F""Auto""R 1F";
#endif
const char STR_SUBTYPE_DEVO[] = "\x04""8ch\0""10ch""12ch""6ch\0""7ch\0";
const char STR_SUBTYPE_YD717[] = "\x07""Std\0 ""SkyWlkr""Syma X4""XINXUN\0""NIHUI\0 ";
const char STR_SUBTYPE_KN[] = "\x06""WLtoys""FeiLun";
@@ -154,16 +164,17 @@ const char STR_SUBTYPE_WFLY[] = "\x05""WFR0x";
const char STR_SUBTYPE_WFLY2[] = "\x05""RF20x";
const char STR_SUBTYPE_HOTT[] = "\x07""Sync\0 ""No_Sync";
const char STR_SUBTYPE_PELIKAN[] = "\x05""Pro\0 ""Lite\0""SCX24";
const char STR_SUBTYPE_V761[] = "\x03""3ch""4ch";
const char STR_SUBTYPE_V761[] = "\x05""3ch\0 ""4ch\0 ""TOPRC";
const char STR_SUBTYPE_RLINK[] = "\x07""Surface""Air\0 ""DumboRC";
const char STR_SUBTYPE_REALACC[] = "\x03""R11";
const char STR_SUBTYPE_KYOSHO[] = "\x04""FHSS""Hype";
const char STR_SUBTYPE_KYOSHO2[] = "\x05""KT-17";
const char STR_SUBTYPE_FUTABA[] = "\x05""SFHSS";
const char STR_SUBTYPE_JJRC345[] = "\x08""JJRC345\0""SkyTmblr";
const char STR_SUBTYPE_MOULKG[] = "\x06""Analog""Digit\0";
const char STR_SUBTYPE_KF606[] = "\x06""KF606\0""MIG320";
const char STR_SUBTYPE_KF606[] = "\x06""KF606\0""MIG320""ZCZ50\0";
const char STR_SUBTYPE_E129[] = "\x04""E129""C186";
const char STR_SUBTYPE_FX[] = "\x04""816\0""620\0""9630";
#define NO_SUBTYPE nullptr
#ifdef SEND_CPPM
@@ -304,8 +315,8 @@ const mm_protocol_definition multi_protocols[] = {
#if defined(FUTABA_CC2500_INO)
{PROTO_FUTABA, STR_FUTABA, STR_SUBTYPE_FUTABA, 1, OPTION_RFTUNE, 1, 1, SW_CC2500, SFHSS_init, SFHSS_callback },
#endif
#if defined(FX816_NRF24L01_INO)
{PROTO_FX816, STR_FX816, NO_SUBTYPE, 0, OPTION_NONE, 0, 0, SW_NRF, FX816_init, FX816_callback },
#if defined(FX_NRF24L01_INO)
{PROTO_FX, STR_FX, STR_SUBTYPE_FX, 3, OPTION_NONE, 0, 0, SW_NRF, FX_init, FX_callback },
#endif
#if defined(FY326_NRF24L01_INO)
{PROTO_FY326, STR_FY326, STR_SUBTYPE_FY326, 2, OPTION_NONE, 0, 0, SW_NRF, FY326_init, FY326_callback },
@@ -350,7 +361,7 @@ const mm_protocol_definition multi_protocols[] = {
{PROTO_JOYSWAY, STR_JOYSWAY, NO_SUBTYPE, 0, OPTION_NONE, 0, 0, SW_A7105, JOYSWAY_init, JOYSWAY_callback },
#endif
#if defined(KF606_CCNRF_INO)
{PROTO_KF606, STR_KF606, STR_SUBTYPE_KF606, 2, OPTION_RFTUNE, 0, 0, SW_NRF, KF606_init, KF606_callback },
{PROTO_KF606, STR_KF606, STR_SUBTYPE_KF606, 3, OPTION_RFTUNE, 0, 0, SW_NRF, KF606_init, KF606_callback },
#endif
#if defined(KN_NRF24L01_INO)
{PROTO_KN, STR_KN, STR_SUBTYPE_KN, 2, OPTION_NONE, 0, 0, SW_NRF, KN_init, KN_callback },
@@ -358,6 +369,9 @@ const mm_protocol_definition multi_protocols[] = {
#if defined(KYOSHO_A7105_INO)
{PROTO_KYOSHO, STR_KYOSHO, STR_SUBTYPE_KYOSHO, 2, OPTION_NONE, 0, 1, SW_A7105, KYOSHO_init, KYOSHO_callback },
#endif
#if defined(KYOSHO2_NRF24L01_INO)
{PROTO_KYOSHO2, STR_KYOSHO2, STR_SUBTYPE_KYOSHO2, 1, OPTION_NONE, 0, 0, SW_NRF, KYOSHO2_init, KYOSHO2_callback },
#endif
#if defined(LOLI_NRF24L01_INO)
{PROTO_LOLI, STR_LOLI, NO_SUBTYPE, 0, OPTION_NONE, 1, 0, SW_NRF, LOLI_init, LOLI_callback },
#endif
@@ -415,6 +429,9 @@ const mm_protocol_definition multi_protocols[] = {
#if defined(SCANNER_CC2500_INO)
{PROTO_SCANNER, STR_SCANNER, NO_SUBTYPE, 0, OPTION_NONE, 0, 0, SW_CC2500, SCANNER_init, SCANNER_callback },
#endif
#if defined(SCORPIO_CYRF6936_INO)
{PROTO_SCORPIO, STR_SCORPIO, NO_SUBTYPE, 0, OPTION_NONE, 0, 0, SW_CYRF, SCORPIO_init, SCORPIO_callback },
#endif
#if defined(SHENQI_NRF24L01_INO)
{PROTO_SHENQI, STR_SHENQI, NO_SUBTYPE, 0, OPTION_NONE, 0, 0, SW_NRF, SHENQI_init, SHENQI_callback },
#endif
@@ -437,7 +454,7 @@ const mm_protocol_definition multi_protocols[] = {
{PROTO_V2X2, STR_V2X2, STR_SUBTYPE_V2X2, 3, OPTION_NONE, 0, 0, SW_NRF, V2X2_init, V2X2_callback },
#endif
#if defined(V761_NRF24L01_INO)
{PROTO_V761, STR_V761, STR_SUBTYPE_V761, 2, OPTION_NONE, 0, 0, SW_NRF, V761_init, V761_callback },
{PROTO_V761, STR_V761, STR_SUBTYPE_V761, 3, OPTION_NONE, 0, 0, SW_NRF, V761_init, V761_callback },
#endif
#if defined(V911S_CCNRF_INO)
{PROTO_V911S, STR_V911S, STR_SUBTYPE_V911S, 2, OPTION_RFTUNE, 0, 0, SW_NRF, V911S_init, V911S_callback },

View File

@@ -19,7 +19,7 @@
#define VERSION_MAJOR 1
#define VERSION_MINOR 3
#define VERSION_REVISION 3
#define VERSION_PATCH_LEVEL 14
#define VERSION_PATCH_LEVEL 27
#define MODE_SERIAL 0
@@ -86,7 +86,7 @@ enum PROTOCOLS
PROTO_FRSKY_RX = 55, // =>CC2500
PROTO_AFHDS2A_RX= 56, // =>A7105
PROTO_HOTT = 57, // =>CC2500
PROTO_FX816 = 58, // =>NRF24L01
PROTO_FX = 58, // =>NRF24L01
PROTO_BAYANG_RX = 59, // =>NRF24L01
PROTO_PELIKAN = 60, // =>A7105
PROTO_TIGER = 61, // =>NRF24L01
@@ -120,7 +120,9 @@ enum PROTOCOLS
PROTO_MOULDKG = 90, // =>NRF24L01
PROTO_XERALL = 91, // =>NRF24L01
PROTO_MT99XX2 = 92, // =>NRF24L01, extension of MT99XX protocol
PROTO_KYOSHO2 = 93, // =>NRF24L01
PROTO_SCORPIO = 94, // =>CYRF6936
PROTO_NANORF = 126, // =>NRF24L01
PROTO_TEST = 127, // =>CC2500
};
@@ -390,7 +392,6 @@ enum ESKY
ESKY_STD = 0,
ESKY_ET4 = 1,
};
enum FRSKY_RX
{
FRSKY_RX = 0,
@@ -398,74 +399,71 @@ enum FRSKY_RX
FRSKY_ERASE = 2,
FRSKY_CPPM = 3,
};
enum FRSKYL
{
LR12 = 0,
LR12_6CH = 1,
};
enum HOTT
{
HOTT_SYNC = 0,
HOTT_NO_SYNC= 1,
};
enum PELIKAN
{
PELIKAN_PRO = 0,
PELIKAN_LITE= 1,
PELIKAN_SCX24=2,
};
enum V761
{
V761_3CH = 0,
V761_4CH = 1,
V761_TOPRC = 2,
};
enum HEIGHT
{
HEIGHT_5CH = 0,
HEIGHT_8CH = 1,
};
enum KYOSHO
{
KYOSHO_FHSS = 0,
KYOSHO_HYPE = 1,
};
enum JJRC345
{
JJRC345 = 0,
SKYTMBLR = 1,
};
enum RLINK
{
RLINK_SURFACE = 0,
RLINK_AIR = 1,
RLINK_DUMBORC = 2,
};
enum MOULDKG
{
MOULDKG_ANALOG = 0,
MOULDKG_DIGIT = 1,
};
enum KF606
{
KF606_KF606 = 0,
KF606_MIG320 = 1,
KF606_ZCZ50 = 2,
};
enum E129
{
E129_E129 = 0,
E129_C186 = 1,
};
enum FX
{
FX816 = 0,
FX620 = 1,
FX9630 = 2,
};
#define NONE 0
#define P_HIGH 1
@@ -911,7 +909,7 @@ Serial: 100000 Baud 8e2 _ xxxx xxxx p --
FRSKY_RX 55
AFHDS2A_RX 56
HOTT 57
FX816 58
FX 58
BAYANG_RX 59
PELIKAN 60
TIGER 61

View File

@@ -1199,9 +1199,9 @@ static void protocol_init()
modules_reset();
uint8_t index=0;
#if defined(FRSKYX_CC2500_INO) && defined(EU_MODULE)
if( ! ( (protocol == PROTO_FRSKYX || protocol == PROTO_FRSKYX2) && sub_protocol < 2 ) )
#endif
//#if defined(FRSKYX_CC2500_INO) && defined(MULTI_EU)
// if( ! ( (protocol == PROTO_FRSKYX || protocol == PROTO_FRSKYX2) && sub_protocol < 2 ) )
//#endif
while(multi_protocols[index].protocol != 0xFF)
{
if(multi_protocols[index].protocol==protocol)

View File

@@ -0,0 +1,123 @@
/*
This project is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Multiprotocol is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Multiprotocol. If not, see <http://www.gnu.org/licenses/>.
*/
#if defined(SCORPIO_CYRF6936_INO)
#include "iface_cyrf6936.h"
//#define SCORPIO_FORCE_ID
#define SCORPIO_PACKET_PERIOD 12000
#define SCORPIO_PACKETCH_PERIOD 2580
#define SCORPIO_BINDPAYLOAD_SIZE 8
#define SCORPIO_PAYLOAD_SIZE 10
#define SCORPIO_BIND_COUNT 1000
#define SCORPIO_RF_NUM_CHANNELS 3
static uint16_t __attribute__((unused)) SCORPIO_send_packet()
{
if(IS_BIND_IN_PROGRESS)
{
packet[0] = 0x88; //FIXME: What is this?
packet[1] = 0x55; //FIXME: What is this?
packet[2] = crc; //CRC_low for normal packets
packet[3] = crc >> 8; //CRC_high for normal packets
packet[4] = hopping_frequency[0]; //RF freq 0
packet[5] = hopping_frequency[1]; //RF freq 1
packet[6] = hopping_frequency[2]; //RF freq 2
packet[7] = 0x80; //FIXME: What is this?
//SendPacket
CYRF_WriteDataPacketLen(packet, SCORPIO_BINDPAYLOAD_SIZE);
return SCORPIO_PACKET_PERIOD;
}
CYRF_ConfigRFChannel(hopping_frequency[hopping_frequency_no]);
CYRF_SetPower(0x28); //Update power
delayMicroseconds(180); //Frequency settle time
packet[0] = hopping_frequency[0];
packet[1] = hopping_frequency[1];
packet[2] = hopping_frequency[2];
packet[3] = convert_channel_8b(THROTTLE);
packet[4] = 0xFF - convert_channel_8b(RUDDER);
packet[5] = convert_channel_8b(ELEVATOR);
packet[6] = convert_channel_8b(AILERON);
packet[7] = 0x55; //FIXME: What is this?
packet[8] = 0x00; //FIXME: What is this?
packet[9] = 0x00; //FIXME: What is this?
CYRF_WriteDataPacketLen(packet, SCORPIO_PAYLOAD_SIZE);
hopping_frequency_no++;
if(hopping_frequency_no >= SCORPIO_RF_NUM_CHANNELS)
{
hopping_frequency_no = 0;
return SCORPIO_PACKET_PERIOD - 2*SCORPIO_PACKETCH_PERIOD;
}
return SCORPIO_PACKETCH_PERIOD;
}
static void __attribute__((unused)) SCORPIO_RF_init()
{
/* Initialise CYRF chip */
CYRF_WriteRegister(CYRF_32_AUTO_CAL_TIME, 0x3C);
CYRF_WriteRegister(CYRF_35_AUTOCAL_OFFSET, 0x14);
CYRF_WriteRegister(CYRF_1B_TX_OFFSET_LSB, 0x55);
CYRF_WriteRegister(CYRF_1C_TX_OFFSET_MSB, 0x05);
CYRF_WriteRegister(CYRF_10_FRAMING_CFG, 0xE8);
CYRF_SetPower(0x28);
CYRF_SetTxRxMode(TX_EN);
}
static void __attribute__((unused)) SCORPIO_TX_init()
{
calc_fh_channels(3); // select 3 frequencies between 2 and 77. FIXME: Could they be choosen on the spot finding empty frequencies?
crc = (rx_tx_addr[0] ^ rx_tx_addr[1] ^ RX_num) + ((rx_tx_addr[2] ^ rx_tx_addr[3] ^ RX_num) << 8);
#ifdef SCORPIO_FORCE_ID
crc = 0x689C;
hopping_frequency[0] = 0x26;
hopping_frequency[1] = 0x49;
hopping_frequency[2] = 0x2E;
#endif
//debugln("C0:%02X, C1:%02X, C2:%02X, CRC:%04X", hopping_frequency[0], hopping_frequency[1], hopping_frequency[2], crc);
CYRF_ConfigRFChannel(hopping_frequency[0]); // Use first RF channel for bind
}
uint16_t SCORPIO_callback()
{
#ifdef MULTI_SYNC
telemetry_set_input_sync(SCORPIO_PACKET_PERIOD);
#endif
if(bind_counter)
if(--bind_counter==0)
{
CYRF_ConfigCRCSeed(crc);
BIND_DONE;
}
return SCORPIO_send_packet();
}
void SCORPIO_init()
{
SCORPIO_RF_init();
SCORPIO_TX_init();
if(IS_BIND_IN_PROGRESS)
{
bind_counter = SCORPIO_BIND_COUNT;
CYRF_ConfigCRCSeed(0x0001);
}
else
bind_counter = 1;
hopping_frequency_no = 0;
}
#endif

View File

@@ -25,13 +25,15 @@ Multiprotocol is distributed in the hope that it will be useful,
#define V761_BIND_COUNT 200
#define V761_BIND_FREQ 0x28
#define V761_RF_NUM_CHANNELS 3
#define TOPRC_BIND_FREQ 0x2A
#define TOPRC_PACKET_PERIOD 14120 // Timeout for callback in uSec
enum
{
{
V761_BIND1 = 0,
V761_BIND2,
V761_DATA
};
};
static void __attribute__((unused)) V761_set_checksum()
{
@@ -56,14 +58,11 @@ static void __attribute__((unused)) V761_send_packet()
if(phase != V761_DATA)
{
packet[0] = rx_tx_addr[0];
packet[1] = rx_tx_addr[1];
packet[2] = rx_tx_addr[2];
packet[3] = rx_tx_addr[3];
memcpy(packet, rx_tx_addr, 4);
packet[4] = hopping_frequency[1];
packet[5] = hopping_frequency[2];
if(phase == V761_BIND2)
packet[6] = 0xf0; // ?
packet[6] = 0xF0; // ?
}
else
{
@@ -72,23 +71,22 @@ static void __attribute__((unused)) V761_send_packet()
{
hopping_frequency_no = 0;
packet_count++;
if(packet_count >= 4)
packet_count = 0;
packet_count &= 0x03;
}
packet[0] = convert_channel_8b(THROTTLE); // Throttle
packet[2] = convert_channel_8b(ELEVATOR)>>1; // Elevator
if(sub_protocol==V761_3CH)
{
packet[1] = convert_channel_8b(RUDDER)>>1; // Rudder
packet[3] = convert_channel_8b(AILERON)>>1; // Aileron
}
else
if(sub_protocol == V761_4CH || sub_protocol == V761_TOPRC)
{
packet[1] = convert_channel_8b(AILERON)>>1; // Aileron
packet[3] = convert_channel_8b(RUDDER)>>1; // Rudder
}
else
{
packet[1] = convert_channel_8b(RUDDER)>>1; // Rudder
packet[3] = convert_channel_8b(AILERON)>>1; // Aileron
}
packet[5] = packet_count<<6; // 0X, 4X, 8X, CX
packet[4] = 0x20; // Trims 00..20..40, 0X->20 4X->TrAil 8X->TrEle CX->TrRud
@@ -112,7 +110,7 @@ static void __attribute__((unused)) V761_send_packet()
packet[6] = GET_FLAG(CH7_SW, 0x20) // Flip
|GET_FLAG(CH8_SW, 0x08) // RTH activation
|GET_FLAG(CH9_SW, 0x10); // RTH on/off
if(sub_protocol==V761_3CH)
if(sub_protocol == V761_3CH)
packet[6] |= 0x80; // Unknown, set on original V761-1 dump but not on eachine dumps, keeping for compatibility
}
V761_set_checksum();
@@ -137,28 +135,36 @@ static void __attribute__((unused)) V761_RF_init()
static void __attribute__((unused)) V761_initialize_txid()
{
#ifdef V761_FORCE_ID
switch(RX_num%5)
if(sub_protocol == V761_TOPRC)
{ //Dump from air on TopRCHobby TX
memcpy(rx_tx_addr,(uint8_t *)"\xD5\x01\x00\x00",4);
memcpy(hopping_frequency,(uint8_t *)"\x2E\x41",2);
}
else
{
case 1: //Dump from air on Protonus TX
memcpy(rx_tx_addr,(uint8_t *)"\xE8\xE4\x45\x09",4);
memcpy(hopping_frequency,(uint8_t *)"\x0D\x21",2);
break;
case 2: //Dump from air on mshagg2 TX
memcpy(rx_tx_addr,(uint8_t *)"\xAE\xD1\x45\x09",4);
memcpy(hopping_frequency,(uint8_t *)"\x13\x1D",2);
break;
case 3: //Dump from air on MikeHRC Eachine TX
memcpy(rx_tx_addr,(uint8_t *)"\x08\x03\x00\xA0",4);
memcpy(hopping_frequency,(uint8_t *)"\x0D\x21",2);
break;
case 4: //Dump from air on Crashanium Eachine TX
memcpy(rx_tx_addr,(uint8_t *)"\x58\x08\x00\xA0",4);
memcpy(hopping_frequency,(uint8_t *)"\x0D\x31",2);
break;
default: //Dump from SPI
memcpy(rx_tx_addr,(uint8_t *)"\x6f\x2c\xb1\x93",4);
memcpy(hopping_frequency,(uint8_t *)"\x14\x1e",2);
break;
switch(RX_num%5)
{
case 1: //Dump from air on Protonus TX
memcpy(rx_tx_addr,(uint8_t *)"\xE8\xE4\x45\x09",4);
memcpy(hopping_frequency,(uint8_t *)"\x0D\x21",2);
break;
case 2: //Dump from air on mshagg2 TX
memcpy(rx_tx_addr,(uint8_t *)"\xAE\xD1\x45\x09",4);
memcpy(hopping_frequency,(uint8_t *)"\x13\x1D",2);
break;
case 3: //Dump from air on MikeHRC Eachine TX
memcpy(rx_tx_addr,(uint8_t *)"\x08\x03\x00\xA0",4);
memcpy(hopping_frequency,(uint8_t *)"\x0D\x21",2);
break;
case 4: //Dump from air on Crashanium Eachine TX
memcpy(rx_tx_addr,(uint8_t *)"\x58\x08\x00\xA0",4);
memcpy(hopping_frequency,(uint8_t *)"\x0D\x31",2);
break;
default: //Dump from SPI
memcpy(rx_tx_addr,(uint8_t *)"\x6f\x2c\xb1\x93",4);
memcpy(hopping_frequency,(uint8_t *)"\x14\x1e",2);
break;
}
}
#else
//Tested with Eachine RX
@@ -180,8 +186,8 @@ uint16_t V761_callback()
if(bind_counter)
bind_counter--;
packet_count ++;
XN297_RFChannel(V761_BIND_FREQ);
XN297_SetTXAddr((uint8_t*)"\x34\x43\x10\x10", 4);
XN297_RFChannel(sub_protocol == V761_TOPRC ? TOPRC_BIND_FREQ : V761_BIND_FREQ);
XN297_SetTXAddr(rx_id, 4);
V761_send_packet();
if(packet_count >= 20)
{
@@ -210,17 +216,28 @@ uint16_t V761_callback()
return 15730;
case V761_DATA:
#ifdef MULTI_SYNC
telemetry_set_input_sync(V761_PACKET_PERIOD);
telemetry_set_input_sync(packet_period);
#endif
V761_send_packet();
break;
}
return V761_PACKET_PERIOD;
return packet_period;
}
void V761_init(void)
{
V761_initialize_txid();
if(sub_protocol == V761_TOPRC)
{
memcpy(rx_id,(uint8_t*)"\x20\x21\x05\x0A",4);
packet_period = TOPRC_PACKET_PERIOD;
}
else
{
memcpy(rx_id,(uint8_t*)"\x34\x43\x10\x10",4);
packet_period = V761_PACKET_PERIOD;
}
if(IS_BIND_IN_PROGRESS)
{
bind_counter = V761_BIND_COUNT;
@@ -231,7 +248,7 @@ void V761_init(void)
XN297_SetTXAddr(rx_tx_addr, 4);
phase = V761_DATA;
}
V761_RF_init();
hopping_frequency_no = 0;
packet_count = 0;

View File

@@ -241,22 +241,27 @@
#endif
//Make sure protocols are selected correctly
#ifndef A7105_INSTALLED
#undef AFHDS2A_A7105_INO
#undef AFHDS2A_RX_A7105_INO
#undef BUGS_A7105_INO
#undef FLYSKY_A7105_INO
#undef HEIGHT_A7105_INO
#undef HUBSAN_A7105_INO
#undef JOYSWAY_A7105_INO
#undef KYOSHO_A7105_INO
#undef PELIKAN_A7105_INO
#undef WFLY2_A7105_INO
#if not defined(A7105_INSTALLED) || defined MULTI_EU
#undef AFHDS2A_A7105_INO
#if not defined(A7105_INSTALLED)
#undef AFHDS2A_RX_A7105_INO
#endif
#undef BUGS_A7105_INO
#undef FLYSKY_A7105_INO
#undef HEIGHT_A7105_INO
#undef HUBSAN_A7105_INO
#undef JOYSWAY_A7105_INO
#undef KYOSHO_A7105_INO
#undef PELIKAN_A7105_INO
#undef WFLY2_A7105_INO
#endif
#ifndef CYRF6936_INSTALLED
#if not defined(CYRF6936_INSTALLED) || defined MULTI_EU
#undef DEVO_CYRF6936_INO
#undef DSM_CYRF6936_INO
#undef DSM_RX_CYRF6936_INO
#if not defined(CYRF6936_INSTALLED)
#undef DSM_CYRF6936_INO
#undef DSM_RX_CYRF6936_INO
#endif
#undef E010R5_CYRF6936_INO
#undef E01X_CYRF6936_INO
#undef E129_CYRF6936_INO
@@ -264,31 +269,42 @@
#undef LOSI_CYRF6936_INO
#undef MLINK_CYRF6936_INO
#undef TRAXXAS_CYRF6936_INO
#undef SCORPIO_CYRF6936_INO
#undef WFLY_CYRF6936_INO
#undef WK2x01_CYRF6936_INO
#endif
#ifndef CC2500_INSTALLED
#if not defined(CC2500_INSTALLED) || defined MULTI_EU
#undef CORONA_CC2500_INO
#undef E016HV2_CC2500_INO
#undef ESKY150V2_CC2500_INO
#undef FRSKYD_CC2500_INO
#undef FRSKYL_CC2500_INO
#undef FRSKYV_CC2500_INO
#undef FRSKYX_CC2500_INO
#undef FRSKY_RX_CC2500_INO
#if not defined(CC2500_INSTALLED)
#undef FRSKYX_CC2500_INO
#undef FRSKY_RX_CC2500_INO
#endif
#undef HITEC_CC2500_INO
#undef HOTT_CC2500_INO
#if not defined(CC2500_INSTALLED)
#undef HOTT_CC2500_INO
#endif
#undef IKEAANSLUTA_CC2500_INO
#undef REDPINE_CC2500_INO
#undef RLINK_CC2500_INO
#undef SCANNER_CC2500_INO
#if not defined(CC2500_INSTALLED)
#undef SCANNER_CC2500_INO
#endif
#undef FUTABA_CC2500_INO
#undef SKYARTEC_CC2500_INO
#endif
#ifndef NRF24L01_INSTALLED
#if not defined(NRF24L01_INSTALLED) || defined MULTI_EU
#undef ASSAN_NRF24L01_INO
#undef BAYANG_NRF24L01_INO
#undef BAYANG_RX_NRF24L01_INO
#if not defined(NRF24L01_INSTALLED)
#undef BAYANG_RX_NRF24L01_INO
#endif
#undef BUGSMINI_NRF24L01_INO
#undef CABELL_NRF24L01_INO
#undef CFLIE_NRF24L01_INO
@@ -299,7 +315,7 @@
#undef ESKY_NRF24L01_INO
#undef ESKY150_NRF24L01_INO
#undef FQ777_NRF24L01_INO
#undef FX816_NRF24L01_INO
#undef FX_NRF24L01_INO
#undef FY326_NRF24L01_INO
#undef GW008_NRF24L01_INO
#undef H8_3D_NRF24L01_INO
@@ -307,6 +323,7 @@
#undef HONTAI_NRF24L01_INO
#undef JJRC345_NRF24L01_INO
#undef KN_NRF24L01_INO
#undef KYOSHO2_NRF24L01_INO
#undef LOLI_NRF24L01_INO
#undef MOULDKG_NRF24L01_INO
#undef NCC1701_NRF24L01_INO
@@ -322,7 +339,7 @@
#undef YD717_NRF24L01_INO
#undef ZSX_NRF24L01_INO
#endif
#if not defined(CC2500_INSTALLED) && not defined(NRF24L01_INSTALLED)
#if ( not defined(CC2500_INSTALLED) && not defined(NRF24L01_INSTALLED) ) || defined MULTI_EU
#undef GD00X_CCNRF_INO
#undef KF606_CCNRF_INO
#undef MJXQ_CCNRF_INO
@@ -342,7 +359,7 @@
#if not defined(STM32_BOARD)
#undef SX1276_INSTALLED
#endif
#ifndef SX1276_INSTALLED
#if not defined(SX1276_INSTALLED) || defined MULTI_EU
#undef FRSKYR9_SX1276_INO
#endif

View File

@@ -191,8 +191,9 @@
#define E01X_CYRF6936_INO
#define E129_CYRF6936_INO
#define J6PRO_CYRF6936_INO
#define LOSI_CYRF6936_INO
//#define LOSI_CYRF6936_INO
#define MLINK_CYRF6936_INO
#define SCORPIO_CYRF6936_INO
#define TRAXXAS_CYRF6936_INO
#define WFLY_CYRF6936_INO
#define WK2x01_CYRF6936_INO
@@ -229,7 +230,7 @@
#define ESKY_NRF24L01_INO
#define ESKY150_NRF24L01_INO
#define FQ777_NRF24L01_INO
#define FX816_NRF24L01_INO
#define FX_NRF24L01_INO
#define FY326_NRF24L01_INO
#define GW008_NRF24L01_INO
#define HISKY_NRF24L01_INO
@@ -237,6 +238,7 @@
#define H8_3D_NRF24L01_INO
#define JJRC345_NRF24L01_INO
#define KN_NRF24L01_INO
#define KYOSHO2_NRF24L01_INO
#define LOLI_NRF24L01_INO
//#define MOULDKG_NRF24L01_INO
#define NCC1701_NRF24L01_INO
@@ -666,8 +668,12 @@ const PPM_Parameters PPM_prot[14*NBR_BANKS]= {
PROTO_FRSKY_RX
FRSKY_RX
FRSKY_CLONE
PROTO_FX816
PROTO_FUTABA
NONE
PROTO_FX
FX816
FX620
FX9630
PROTO_FY326
FY326
FY319
@@ -715,12 +721,15 @@ const PPM_Parameters PPM_prot[14*NBR_BANKS]= {
PROTO_KF606
KF606_KF606
KF606_MIG320
KF606_ZCZ50
PROTO_KN
WLTOYS
FEILUN
PROTO_KYOSHO
KYOSHO_FHSS
KYOSHO_HYPE
PROTO_KYOSHO2
NONE
PROTO_LOLI
NONE
PROTO_LOSI
@@ -783,7 +792,7 @@ const PPM_Parameters PPM_prot[14*NBR_BANKS]= {
RLINK_DUMBORC
PROTO_SCANNER
NONE
PROTO_FUTABA
PROTO_SCORPIO
NONE
PROTO_SHENQI
NONE

View File

@@ -96,7 +96,7 @@ CFlie|38|CFlie||||||||NRF24L01|
[FrskyX2](Protocols_Details.md#FRSKYX2---64)|64|CH_16|CH_8|EU_16|EU_8|Cloned|Cloned_8|||CC2500|
[Frsky_RX](Protocols_Details.md#FRSKY_RX---55)|55|Multi|CloneTX|EraseTX|CPPM|||||CC2500|
[Futaba/SFHSS](Protocols_Details.md#Futaba---21)|21|SFHSS||||||||CC2500|
[FX816](Protocols_Details.md#FX816---58)|28|FX816||||||||NRF24L01|
[FX](Protocols_Details.md#FX---58)|28|816|620|||||||NRF24L01|
[FY326](Protocols_Details.md#FY326---20)|20|FY326|FY319|||||||NRF24L01|
[GD00X](Protocols_Details.md#GD00X---47)|47|GD_V1*|GD_V2*|||||||NRF24L01|XN297L
[GW008](Protocols_Details.md#GW008---32)|32|||||||||NRF24L01|XN297
@@ -110,9 +110,10 @@ CFlie|38|CFlie||||||||NRF24L01|
[J6Pro](Protocols_Details.md#J6Pro---22)|22|||||||||CYRF6936|
[JJRC345](Protocols_Details.md#JJRC345---71)|71|JJRC345|SkyTmblr|||||||NRF24L01|XN297
[JOYSWAY](Protocols_Details.md#JOYSWAY---84)|84|||||||||NRF24L01|XN297
[KF606](Protocols_Details.md#KF606---49)|49|KF606|MIG320|||||||NRF24L01|XN297
[KF606](Protocols_Details.md#KF606---49)|49|KF606|MIG320|ZCZ50||||||NRF24L01|XN297
[KN](Protocols_Details.md#KN---9)|9|WLTOYS|FEILUN|||||||NRF24L01|
[Kyosho](Protocols_Details.md#Kyosho---73)|73|FHSS|Hype|||||||A7105|
[Kyosho2](Protocols_Details.md#Kyosho2---93)|93|KT-17||||||||NRF24L01|
[LOLI](Protocols_Details.md#LOLI---82)|82|||||||||NRF24L01|
[Losi](Protocols_Details.md#Losi---89)|89|||||||||CYRF6936|
[MJXq](Protocols_Details.md#MJXQ---18)|18|WLH08|X600|X800|H26D|E010*|H26WH|PHOENIX*||NRF24L01|XN297
@@ -133,6 +134,7 @@ CFlie|38|CFlie||||||||NRF24L01|
[Realacc](Protocols_Details.md#Realacc---76)|76|R11||||||||NRF24L01|
[Redpine](Protocols_Details.md#Redpine---50)|50|FAST|SLOW|||||||NRF24L01|XN297
[Scanner](Protocols_Details.md#Scanner---54)|54|||||||||CC2500|
[Scorpio](Protocols_Details.md#Scorpio---94)|94|||||||||CYRF6936|
[Shenqi](Protocols_Details.md#Shenqi---19)|19|Shenqi||||||||NRF24L01|LT8900
[Skyartec](Protocols_Details.md#Skyartec---68)|68|||||||||CC2500|CC2500
[SLT](Protocols_Details.md#SLT---11)|11|SLT_V1|SLT_V2|Q100|Q200|MR100||||NRF24L01|CC2500
@@ -140,7 +142,7 @@ CFlie|38|CFlie||||||||NRF24L01|
[Tiger](Protocols_Details.md#Tiger---61)|61|||||||||NRF24L01|XN297
[Traxxas](Protocols_Details.md#Traxxas---43)|43|6519 RX||||||||CYRF6936|
[V2x2](Protocols_Details.md#V2X2---5)|5|V2x2|JXD506|MR101||||||NRF24L01|
[V761](Protocols_Details.md#V761---48)|48|3CH|4CH|||||||NRF24L01|XN297
[V761](Protocols_Details.md#V761---48)|48|3CH|4CH|TOPRC||||||NRF24L01|XN297
[V911S](Protocols_Details.md#V911S---46)|46|V911S*|E119*|||||||NRF24L01|XN297
[WFLY](Protocols_Details.md#WFLY---40)|40|WFR0x||||||||CYRF6936|
[WFLY2](Protocols_Details.md#WFLY2---79)|79|RF20x||||||||A7105|
@@ -519,18 +521,18 @@ Here is a table detailling the different RX output ranges based on the radio set
![Image](/docs/images/DSM_RX_Output.JPG)
### Sub_protocol DSM2_1F - *0*
DSM2, Resolution 1024, servo refresh rate can only be 22ms
Air DSM2, Resolution 1024, servo refresh rate can only be 22ms
### Sub_protocol DSM2_2F - *1*
DSM2, Resolution 2048, servo refresh rate can be 22 or 11ms. 11ms won't be available on all servo outputs when more than 7 channels are used.
Air DSM2, Resolution 2048, servo refresh rate can be 22 or 11ms. 11ms won't be available on all servo outputs when more than 7 channels are used.
### Sub_protocol DSMX_1F - *2*
DSMX, Resolution 2048, servo refresh rate can only be 22ms
Air DSMX, Resolution 2048, servo refresh rate can only be 22ms
### Sub_protocol DSMX_2F - *3*
DSMX, Resolution 2048, servo refresh rate can be 22 or 11ms. 11ms won't be available on all servo outputs when more than 7 channels are used.
Air DSMX, Resolution 2048, servo refresh rate can be 22 or 11ms. 11ms won't be available on all servo outputs when more than 7 channels are used.
### Sub_protocol AUTO - *4*
"AUTO" is recommended to automatically select the best settings for your DSM RX.
"AUTO" is recommended to automatically select the best settings for your air DSM2 and DSMX RXs.
### Sub_protocol DSMR_1F - *5*
DSMR receivers
Surface DSMR receivers
**Only 22 IDs available**, use RX num to cycle through them.
@@ -614,7 +616,7 @@ Calib is the same as the original radio with both sticks down and to the left in
Models: Eachine E129/E130 and Twister Ninja 250
### Sub_protocol C186 - *1*
Models: C186/E120, C127/E110, K127
Models: C186/E120, C127/E110, K127, C159
The FC of the heli seems to store the trims Trim A/E/R=CH7..9. If you use these trims, make sure to center them after powering off the heli or they will be added to the previous trims and over correct.
@@ -650,6 +652,13 @@ CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12|CH13|CH14|CH15|CH16
---|---|---|---|---|---|---|---|---|----|----|----|----|----|----|----
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12|CH13|CH14|CH15|CH16
## Scorpio - *94*
Model Scorpio Falco 300, TX:Nine Eagles 4CH-TX, RX:Nine Eagles 4CH-RX
CH1|CH2|CH3|CH4
---|---|---|---
A|E|T|R
## Traxxas - *43*
Receiver 6519
@@ -1048,6 +1057,15 @@ CH1|CH2|CH3|CH4|CH5|CH6
---|---|---|---|---|---
A||T||TRIM|LED
### Sub_protocol ZCZ50v2 - *2*
Model: ZC-Z50 Cessna
This might be newer version of the model. My plane does not have front propeller, but its just fake anyway (no motor in the front).
CH1|CH2|CH3|CH4|CH5|CH6
---|---|---|---|---|---
A||T||TRIM|UNKNOWN
## MJXQ - *18*
Autobind protocol
@@ -1129,13 +1147,18 @@ CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9
A|E|T|R|FLIP||||HEADLESS
### Sub_protocol A180 - *5*
Model: XK A180, F949S, F959
Model: XK A180, A120, F949S, F959
A180:
CH1|CH2|CH3|CH4|CH5|CH6
---|---|---|---|---|---
A|E|T|R|3D6G|RATE
A120:
CH1|CH2|CH3|CH4|CH5|CH6
---|---|---|---|---|---
A|E|T|R|RATE|LED
F949S:
CH1|CH2|CH3|CH4|CH5|CH6|CH7
---|---|---|---|---|---|---
@@ -1600,15 +1623,21 @@ A|E|T|R|FMODE|AUX6|AUX7
FMODE and AUX7 have 4 positions: -100%..-50%=>0, -50%..5%=>1, 5%..50%=>2, 50%..100%=>3
## FX816 - *58*
Model: FEI XIONG FX P38, B17
Only 8 TX IDs available
## FX - *58*
FEI XIONG
CH1|CH2|CH3|CH4
---|---|---|---
A|-|T|-
### Sub_protocol 816 - *0*
Model: FX816 P38, B17
Only 8 TX IDs available
### Sub_protocol 620 - *1*
Model: FX620 SU35
## FY326 - *20*
### Sub_protocol FY326 - *0*
@@ -1725,6 +1754,13 @@ Model: DF-Models SkyTumbler
RTH not supported
## KYOSHO2 - *93*
Model: TX KT-17, Minium Edge 540, Minium Citabria
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10
---|---|---|---|---|---|---|---|---|----
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10
## LOLI - *82*
LOLI3 receivers: https://github.com/wooddoor/Loli3
@@ -1764,7 +1800,7 @@ Option field | Value
3|The module will control the brick number RX_num, RX_num+1 and RX_num+2
4|The module will control the brick number RX_num, RX_num+1, RX_num+2 and RX_num+3
To associate a brick to a RX number (RX_num above), set this RX number under the protocol, set option to 1, launch a bind and power on the brick you want to control. Repeat this for every brick using a different RX number each time and then indicate the number of bricks to be comtrolled using the Option field.
To associate a brick to a RX number (RX_num above), set this RX number under the protocol, set option to 1, launch a bind and power on the brick you want to control. Repeat this for every brick using a different RX number each time and then indicate the number of bricks to be controlled using the Option field.
Example: I want to control 2 bricks. I select RX number 1, set option to 1 and launch a bind on the first brick. I select RX number 2, set option to 1 and launch a bind on the second brick. Now to control both bricks I set RX number to 1 and option to 2. Therefore brick1 will react to channels CH1 to CH4 and brick2 to channel CH5 to CH8.
On another model I can control 4 other bricks, bind each brick to RX number 3 to 6 and then finaly set RX number to 3 and option to 4 to contol the 4 bricks with CH1 to CH16.
@@ -1937,14 +1973,21 @@ Flip: momentary switch: hold flip(+100%), indicate flip direction with Ele or Ai
RTN_ACT and RTN: -100% disable, +100% enable
### Sub_protocol 3CH - *0*
Model: Volantex V761-1, V761-3 and may be others
Models: Volantex V761-1, V761-3 and may be others
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9
---|---|---|---|---|---|---|---|---
-|E|T|R|GYRO|CALIB|FLIP|RTN_ACT|RTN
### Sub_protocol 4CH - *1*
Model: Volantex V761-4+ and Eachine P51-D, F4U, F22 and may be others
Models: Volantex V761-4+ and Eachine P51-D, F4U, F22 and may be others
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9
---|---|---|---|---|---|---|---|---
A|E|T|R|GYRO|CALIB|FLIP|RTN_ACT|RTN
### Sub_protocol TOPRC - *2*
Models: Top RC Hobby Spitfire, P51D, BF-109
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9
---|---|---|---|---|---|---|---|---

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,130 @@
(kicad_symbol_lib (version 20211014) (generator kicad_symbol_editor)
(symbol "MULTIRF4IN1SMT" (in_bom yes) (on_board yes)
(property "Reference" "M" (id 0) (at -12.7 21.59 0)
(effects (font (size 1.27 1.0795)) (justify left bottom))
)
(property "Value" "MULTIRF4IN1SMT" (id 1) (at -12.7 -16.51 0)
(effects (font (size 1.778 1.5113)) (justify left top))
)
(property "Footprint" "Multi:MULTIRF4IN1-SMT" (id 2) (at 0 0 0)
(effects (font (size 1.27 1.27)) hide)
)
(property "Datasheet" "" (id 3) (at 0 0 0)
(effects (font (size 1.27 1.27)) hide)
)
(symbol "MULTIRF4IN1SMT_1_0"
(polyline
(pts
(xy -12.7 -15.24)
(xy 12.7 -15.24)
)
(stroke (width 0.254) (type default) (color 0 0 0 0))
(fill (type none))
)
(polyline
(pts
(xy -12.7 20.32)
(xy -12.7 -15.24)
)
(stroke (width 0.254) (type default) (color 0 0 0 0))
(fill (type none))
)
(polyline
(pts
(xy 12.7 -15.24)
(xy 12.7 20.32)
)
(stroke (width 0.254) (type default) (color 0 0 0 0))
(fill (type none))
)
(polyline
(pts
(xy 12.7 20.32)
(xy -12.7 20.32)
)
(stroke (width 0.254) (type default) (color 0 0 0 0))
(fill (type none))
)
(pin bidirectional line (at 15.24 17.78 180) (length 2.54)
(name "CE_2401" (effects (font (size 1.27 1.27))))
(number "CE_2401" (effects (font (size 0 0))))
)
(pin bidirectional line (at 15.24 2.54 180) (length 2.54)
(name "CS_2401" (effects (font (size 1.27 1.27))))
(number "CS_2401" (effects (font (size 0 0))))
)
(pin bidirectional line (at 15.24 0 180) (length 2.54)
(name "CS_2500" (effects (font (size 1.27 1.27))))
(number "CS_2500" (effects (font (size 0 0))))
)
(pin bidirectional line (at 15.24 5.08 180) (length 2.54)
(name "CS_6936" (effects (font (size 1.27 1.27))))
(number "CS_6936" (effects (font (size 0 0))))
)
(pin bidirectional line (at 15.24 -2.54 180) (length 2.54)
(name "CS_7105" (effects (font (size 1.27 1.27))))
(number "CS_7105" (effects (font (size 0 0))))
)
(pin power_in line (at 15.24 -10.16 180) (length 2.54)
(name "GND" (effects (font (size 1.27 1.27))))
(number "GND" (effects (font (size 0 0))))
)
(pin power_in line (at -15.24 17.78 0) (length 2.54)
(name "GND@1" (effects (font (size 1.27 1.27))))
(number "GND@1" (effects (font (size 0 0))))
)
(pin power_in line (at -15.24 15.24 0) (length 2.54)
(name "GND@2" (effects (font (size 1.27 1.27))))
(number "GND@2" (effects (font (size 0 0))))
)
(pin power_in line (at -15.24 5.08 0) (length 2.54)
(name "GND@3" (effects (font (size 1.27 1.27))))
(number "GND@3" (effects (font (size 0 0))))
)
(pin power_in line (at -15.24 0 0) (length 2.54)
(name "GND@4" (effects (font (size 1.27 1.27))))
(number "GND@4" (effects (font (size 0 0))))
)
(pin power_in line (at -15.24 -10.16 0) (length 2.54)
(name "GND@5" (effects (font (size 1.27 1.27))))
(number "GND@5" (effects (font (size 0 0))))
)
(pin power_in line (at -15.24 -12.7 0) (length 2.54)
(name "GND@6" (effects (font (size 1.27 1.27))))
(number "GND@6" (effects (font (size 0 0))))
)
(pin bidirectional line (at 15.24 12.7 180) (length 2.54)
(name "MISO" (effects (font (size 1.27 1.27))))
(number "MISO" (effects (font (size 0 0))))
)
(pin bidirectional line (at 15.24 10.16 180) (length 2.54)
(name "MOSI" (effects (font (size 1.27 1.27))))
(number "MOSI" (effects (font (size 0 0))))
)
(pin bidirectional line (at 15.24 -7.62 180) (length 2.54)
(name "PE1" (effects (font (size 1.27 1.27))))
(number "PE1" (effects (font (size 0 0))))
)
(pin bidirectional line (at 15.24 -5.08 180) (length 2.54)
(name "PE2" (effects (font (size 1.27 1.27))))
(number "PE2" (effects (font (size 0 0))))
)
(pin output line (at -15.24 2.54 0) (length 2.54)
(name "RF" (effects (font (size 1.27 1.27))))
(number "RF" (effects (font (size 0 0))))
)
(pin bidirectional line (at 15.24 15.24 180) (length 2.54)
(name "RST_CYFR" (effects (font (size 1.27 1.27))))
(number "RST_CYFR" (effects (font (size 0 0))))
)
(pin bidirectional line (at 15.24 7.62 180) (length 2.54)
(name "SCK" (effects (font (size 1.27 1.27))))
(number "SCK" (effects (font (size 0 0))))
)
(pin power_in line (at 15.24 -12.7 180) (length 2.54)
(name "VCC" (effects (font (size 1.27 1.27))))
(number "VCC" (effects (font (size 0 0))))
)
)
)
)

View File

@@ -0,0 +1,42 @@
(footprint "DS-B01F-A-S2" (version 20211014) (generator pcbnew)
(layer "F.Cu")
(tedit 59FED5CC)
(descr "Through hole straight pin header, 1x05, 2.54mm pitch, single row")
(tags "Through hole pin header THT 1x05 2.54mm single row")
(attr through_hole)
(fp_text reference "REF**" (at -0.25 -4.75) (layer "F.SilkS")
(effects (font (size 1 1) (thickness 0.15)))
(tstamp d518c7db-9a4d-4905-902c-7b6d95f659cb)
)
(fp_text value "DS-B01F-A-S2" (at 0 12.49) (layer "F.Fab")
(effects (font (size 1 1) (thickness 0.15)))
(tstamp 614f538e-5f2b-401d-b0ab-3346d3ff44e4)
)
(fp_text user "${REFERENCE}" (at 0 5.08 90) (layer "F.Fab")
(effects (font (size 1 1) (thickness 0.15)))
(tstamp 9586cda1-48da-45c7-86f7-751657e7c25a)
)
(fp_line (start -4.5 13.5) (end 1.25 13.5) (layer "F.SilkS") (width 0.12) (tstamp 05393a00-de07-40a8-8064-67c0a8a1e9ef))
(fp_line (start 1.25 -3.5) (end 1.25 13.5) (layer "F.SilkS") (width 0.12) (tstamp 09bf1fa9-9ec6-4d5c-bed9-fcd1fe76bd8e))
(fp_line (start -4.5 -3.5) (end 1.25 -3.5) (layer "F.SilkS") (width 0.12) (tstamp 2f1dd441-3cdc-4eed-9839-dc1fa6a931ba))
(fp_line (start -4.5 -3.5) (end -4.5 13.5) (layer "F.SilkS") (width 0.12) (tstamp 35bb1bb5-998b-4ce9-a139-e009425d4e40))
(fp_line (start -4.5 -3.5) (end -4.5 13.5) (layer "F.CrtYd") (width 0.05) (tstamp 346ee0d3-e13a-49f6-8f6c-eb860777d6c4))
(fp_line (start 1.25 13.5) (end 1.25 -3.5) (layer "F.CrtYd") (width 0.05) (tstamp 93808e54-10fb-4c6c-984b-3a91c36dbafa))
(fp_line (start 1.25 -3.5) (end -4.5 -3.5) (layer "F.CrtYd") (width 0.05) (tstamp d7a0888c-6be2-4a97-ac01-de345dcd2919))
(fp_line (start -4.5 13.5) (end 1.25 13.5) (layer "F.CrtYd") (width 0.05) (tstamp ee85719d-9f71-411e-a024-43105a50c262))
(fp_line (start -1.27 11.43) (end -1.27 -0.635) (layer "F.Fab") (width 0.1) (tstamp 085f4818-84f1-415f-823e-e6076d0e732d))
(fp_line (start -1.27 -0.635) (end -0.635 -1.27) (layer "F.Fab") (width 0.1) (tstamp 602c4495-9f5f-4ae3-9800-df18526e3c50))
(fp_line (start 1.27 -1.27) (end 1.27 11.43) (layer "F.Fab") (width 0.1) (tstamp 73eb4832-b804-463c-ae2b-563755d89978))
(fp_line (start -0.635 -1.27) (end 1.27 -1.27) (layer "F.Fab") (width 0.1) (tstamp aed66e63-a453-441e-94eb-3442ef294c72))
(fp_line (start 1.27 11.43) (end -1.27 11.43) (layer "F.Fab") (width 0.1) (tstamp dde86203-069d-47dc-8693-34fe614da099))
(pad "1" thru_hole rect (at 0 0) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask) (tstamp 174ecd2f-6484-485c-a83d-71d6a1dc733a))
(pad "2" thru_hole oval (at 0 2.5) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask) (tstamp 997a59d1-7e2b-4400-b74b-3cb21ad33038))
(pad "3" thru_hole oval (at 0 5) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask) (tstamp 7aa5c04b-5bd3-4c72-bbaf-9ec87c5447e0))
(pad "4" thru_hole oval (at 0 7.5) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask) (tstamp 8a6c42bd-bf44-40be-9e58-41dc76d10644))
(pad "5" thru_hole oval (at 0 10) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask) (tstamp c1741286-ba0e-4f33-8f37-5fd51504bac5))
(model "${KICAD6_3DMODEL_DIR}/Connector_PinHeader_2.54mm.3dshapes/PinHeader_1x05_P2.54mm_Vertical.wrl"
(offset (xyz 0 0 0))
(scale (xyz 1 1 1))
(rotate (xyz 0 0 0))
)
)

View File

@@ -0,0 +1,60 @@
(footprint "MULTIRF4IN1-SMT" (version 20211014) (generator pcbnew)
(layer "F.Cu")
(tedit 0)
(fp_text reference "REF**" (at 0 -0.75) (layer "F.SilkS")
(effects (font (size 1.27 1.27) (thickness 0.15)))
(tstamp c70c9e03-6ffa-4ea8-9291-15d2673122a0)
)
(fp_text value "Val**" (at 0 1) (layer "F.Fab")
(effects (font (size 1.27 1.27) (thickness 0.15)))
(tstamp c3246ecf-81bc-4b14-94a2-7b86227cabaf)
)
(fp_line (start -13 11.9) (end -13 17) (layer "F.SilkS") (width 0.12) (tstamp 21d8aff3-5b17-43c7-9d08-4e33edbcbeb9))
(fp_line (start -13 3.4) (end -13 8.1) (layer "F.SilkS") (width 0.12) (tstamp 4a2c9e01-3f0b-4116-a39b-baa7e7b94b8a))
(fp_line (start -13 -8.1) (end -13 -2.4) (layer "F.SilkS") (width 0.12) (tstamp 960baeae-d7ca-4f76-ac15-6cd68f041702))
(fp_line (start 13 -17) (end 13 -13.9) (layer "F.SilkS") (width 0.12) (tstamp a22c44ee-0c9a-42e0-81e0-94f90a0da388))
(fp_line (start 13 11.9) (end 13 17) (layer "F.SilkS") (width 0.12) (tstamp a8050edb-a9eb-479e-abea-105077de87b8))
(fp_line (start -13 -17) (end -13 -11.9) (layer "F.SilkS") (width 0.12) (tstamp dbeb96d9-bbc7-4dae-ba00-6746209bdc43))
(fp_line (start 13 -17) (end -13 -17) (layer "F.SilkS") (width 0.12) (tstamp de173627-aedf-48e0-8674-66cfe17b969a))
(fp_line (start 13 17) (end -13 17) (layer "F.SilkS") (width 0.12) (tstamp edb180b5-b35e-4fa4-8440-d021574908ae))
(pad "CE_2401" smd rect (at 12.49 -13) (size 1.52 1.27) (layers "F.Cu" "F.Paste" "F.Mask")
(solder_mask_margin 0.1) (tstamp 177c8408-9b8a-453c-871a-7a335239833a))
(pad "CS_2401" smd rect (at 12.49 -1) (size 1.52 1.27) (layers "F.Cu" "F.Paste" "F.Mask")
(solder_mask_margin 0.1) (tstamp deb3cbb7-c404-4161-b154-3014395e2a30))
(pad "CS_2500" smd rect (at 12.49 1) (size 1.52 1.27) (layers "F.Cu" "F.Paste" "F.Mask")
(solder_mask_margin 0.1) (tstamp e8ecba2d-0746-43bc-b641-9cc180ff9253))
(pad "CS_6936" smd rect (at 12.49 -3) (size 1.52 1.27) (layers "F.Cu" "F.Paste" "F.Mask")
(solder_mask_margin 0.1) (tstamp 90314976-271d-4f34-b2f0-dff6de6b86e7))
(pad "CS_7105" smd rect (at 12.49 3) (size 1.52 1.27) (layers "F.Cu" "F.Paste" "F.Mask")
(solder_mask_margin 0.1) (tstamp 1f154bf6-42ea-456f-89ac-fed01ff7208b))
(pad "GND" smd rect (at 12.49 9) (size 1.52 1.27) (layers "F.Cu" "F.Paste" "F.Mask")
(solder_mask_margin 0.1) (tstamp 14373cb3-8424-453e-b0d3-1a6022ea35b1))
(pad "GND@1" smd rect (at -12.49 -11) (size 1.52 1.27) (layers "F.Cu" "F.Paste" "F.Mask")
(solder_mask_margin 0.1) (tstamp b15a1378-3e57-41cb-96b2-030f4848402c))
(pad "GND@2" smd rect (at -12.49 -9) (size 1.52 1.27) (layers "F.Cu" "F.Paste" "F.Mask")
(solder_mask_margin 0.1) (tstamp 71e83330-d2fe-4680-bbc4-fbbb511ecf3d))
(pad "GND@3" smd rect (at -12.49 -1.5) (size 1.52 1.27) (layers "F.Cu" "F.Paste" "F.Mask")
(solder_mask_margin 0.1) (tstamp 27f29ad7-d4f7-416a-bc00-7c36c9ffbaca))
(pad "GND@4" smd rect (at -12.49 2.5) (size 1.52 1.27) (layers "F.Cu" "F.Paste" "F.Mask")
(solder_mask_margin 0.1) (tstamp 6b446947-9739-4960-abfc-ef89034a0437))
(pad "GND@5" smd rect (at -12.49 9) (size 1.52 1.27) (layers "F.Cu" "F.Paste" "F.Mask")
(solder_mask_margin 0.1) (tstamp 589b3137-9b71-4e00-93fe-63222c56ecc3))
(pad "GND@6" smd rect (at -12.49 11) (size 1.52 1.27) (layers "F.Cu" "F.Paste" "F.Mask")
(solder_mask_margin 0.1) (tstamp 371c3d69-e48f-46fb-a1b6-b681b17bacb1))
(pad "MISO" smd rect (at 12.49 -9) (size 1.52 1.27) (layers "F.Cu" "F.Paste" "F.Mask")
(solder_mask_margin 0.1) (tstamp a1ef8d67-bdf4-443e-88f7-406670c2aef9))
(pad "MOSI" smd rect (at 12.49 -7) (size 1.52 1.27) (layers "F.Cu" "F.Paste" "F.Mask")
(solder_mask_margin 0.1) (tstamp d9f5d5e2-2571-4cc2-800c-f5758bd5695f))
(pad "PE1" smd rect (at 12.49 7) (size 1.52 1.27) (layers "F.Cu" "F.Paste" "F.Mask")
(solder_mask_margin 0.1) (tstamp 06684ce2-c9de-48bf-9621-ada44ca8a12c))
(pad "PE2" smd rect (at 12.49 5) (size 1.52 1.27) (layers "F.Cu" "F.Paste" "F.Mask")
(solder_mask_margin 0.1) (tstamp bd470244-7da3-4d59-894b-19e4071da146))
(pad "RF" smd rect (at -12.49 0.5) (size 1.52 1.27) (layers "F.Cu" "F.Paste" "F.Mask")
(solder_mask_margin 0.1) (tstamp e91e6b83-902b-42be-92fa-6ac19487af54))
(pad "RST_CYFR" smd rect (at 12.49 -11) (size 1.52 1.27) (layers "F.Cu" "F.Paste" "F.Mask")
(solder_mask_margin 0.1) (tstamp dc86e8ca-1f6b-4f0d-9576-5c57346768bf))
(pad "SCK" smd rect (at 12.49 -5) (size 1.52 1.27) (layers "F.Cu" "F.Paste" "F.Mask")
(solder_mask_margin 0.1) (tstamp 483e384c-d6af-490d-b4f9-371490f0e46f))
(pad "VCC" smd rect (at 12.49 11) (size 1.52 1.27) (layers "F.Cu" "F.Paste" "F.Mask")
(solder_mask_margin 0.1) (tstamp 8796d68c-81fa-42ef-ace9-9d8c76827e59))
)

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,75 @@
{
"board": {
"active_layer": 0,
"active_layer_preset": "All Layers",
"auto_track_width": false,
"hidden_nets": [],
"high_contrast_mode": 0,
"net_color_mode": 1,
"opacity": {
"pads": 1.0,
"tracks": 1.0,
"vias": 1.0,
"zones": 0.6
},
"ratsnest_display_mode": 0,
"selection_filter": {
"dimensions": true,
"footprints": true,
"graphics": true,
"keepouts": true,
"lockedItems": true,
"otherItems": true,
"pads": true,
"text": true,
"tracks": true,
"vias": true,
"zones": true
},
"visible_items": [
0,
1,
2,
3,
4,
5,
8,
9,
10,
11,
12,
13,
14,
15,
16,
17,
18,
19,
20,
21,
22,
23,
24,
25,
26,
27,
28,
29,
30,
32,
33,
34,
35,
36
],
"visible_layers": "fffffff_ffffffff",
"zone_display_mode": 0
},
"meta": {
"filename": "PL18_multiprotocol.kicad_prl",
"version": 3
},
"project": {
"files": []
}
}

View File

@@ -0,0 +1,462 @@
{
"board": {
"design_settings": {
"defaults": {
"board_outline_line_width": 0.09999999999999999,
"copper_line_width": 0.19999999999999998,
"copper_text_italic": false,
"copper_text_size_h": 1.5,
"copper_text_size_v": 1.5,
"copper_text_thickness": 0.3,
"copper_text_upright": false,
"courtyard_line_width": 0.049999999999999996,
"dimension_precision": 4,
"dimension_units": 3,
"dimensions": {
"arrow_length": 1270000,
"extension_offset": 500000,
"keep_text_aligned": true,
"suppress_zeroes": false,
"text_position": 0,
"units_format": 1
},
"fab_line_width": 0.09999999999999999,
"fab_text_italic": false,
"fab_text_size_h": 1.0,
"fab_text_size_v": 1.0,
"fab_text_thickness": 0.15,
"fab_text_upright": false,
"other_line_width": 0.15,
"other_text_italic": false,
"other_text_size_h": 1.0,
"other_text_size_v": 1.0,
"other_text_thickness": 0.15,
"other_text_upright": false,
"pads": {
"drill": 0.762,
"height": 1.524,
"width": 1.524
},
"silk_line_width": 0.15,
"silk_text_italic": false,
"silk_text_size_h": 1.0,
"silk_text_size_v": 1.0,
"silk_text_thickness": 0.15,
"silk_text_upright": false,
"zones": {
"45_degree_only": false,
"min_clearance": 0.19999999999999998
}
},
"diff_pair_dimensions": [
{
"gap": 0.0,
"via_gap": 0.0,
"width": 0.0
}
],
"drc_exclusions": [
"copper_edge_clearance|34900000|34735000|785ef911-e457-413e-ac63-cf1535b242cb|be0d3c71-0f5b-45b9-9c9b-72866af0f7a2",
"copper_edge_clearance|34900000|36735000|785ef911-e457-413e-ac63-cf1535b242cb|e7b16a25-ec09-4bb5-aa09-fe00038c1f1f",
"copper_edge_clearance|34900000|38735000|785ef911-e457-413e-ac63-cf1535b242cb|e65ad8dc-91cb-4c5d-b0fe-169b84ac0b55",
"copper_edge_clearance|34900000|40735000|785ef911-e457-413e-ac63-cf1535b242cb|95287391-9e27-4475-a375-0f63337ce67a",
"copper_edge_clearance|34900000|42735000|785ef911-e457-413e-ac63-cf1535b242cb|c29c966c-91b2-4b36-b1bc-6673192d38fe",
"copper_edge_clearance|34900000|44735000|785ef911-e457-413e-ac63-cf1535b242cb|4f24c66e-64cb-408b-9295-97d993d96225",
"copper_edge_clearance|34900000|46735000|785ef911-e457-413e-ac63-cf1535b242cb|0ddbf31e-bbeb-43d6-ae3b-cab85e65b36d",
"copper_edge_clearance|34900000|48735000|785ef911-e457-413e-ac63-cf1535b242cb|4dcf731f-2949-4865-b539-ff1e637244c5",
"copper_edge_clearance|34900000|50735000|785ef911-e457-413e-ac63-cf1535b242cb|34e18046-0932-48eb-854b-3707688a2215",
"copper_edge_clearance|34900000|52735000|785ef911-e457-413e-ac63-cf1535b242cb|5c40c44b-70c5-4c30-aafc-a4724555cbb1",
"copper_edge_clearance|34900000|54735000|785ef911-e457-413e-ac63-cf1535b242cb|bb59f967-af06-40a4-adc7-d38dcc40fc54",
"copper_edge_clearance|34900000|56735000|785ef911-e457-413e-ac63-cf1535b242cb|27057d15-87f3-4a5e-bab7-6c1fa0d1954f",
"copper_edge_clearance|34900000|58735000|785ef911-e457-413e-ac63-cf1535b242cb|13a669d2-833b-4c54-a87d-44fb38d91e82",
"copper_edge_clearance|61100000|36735000|b1556ea3-f1cc-4201-b942-480142bd0c54|5bd3edee-4a1d-4d5f-8aae-d7afd4bced8c",
"copper_edge_clearance|61100000|38735000|b1556ea3-f1cc-4201-b942-480142bd0c54|2bcfc76b-5219-4cb8-b24e-4fb83ce73dfb",
"copper_edge_clearance|61100000|46235000|b1556ea3-f1cc-4201-b942-480142bd0c54|ad1d31a9-5733-4b73-be03-a80ca4f16773",
"copper_edge_clearance|61100000|48235000|b1556ea3-f1cc-4201-b942-480142bd0c54|0967fce8-8cdb-4026-bedd-d620a9cd0bad",
"copper_edge_clearance|61100000|50235000|b1556ea3-f1cc-4201-b942-480142bd0c54|7aa764ba-7abe-485a-b859-ce8f0595e5cd",
"copper_edge_clearance|61100000|56735000|b1556ea3-f1cc-4201-b942-480142bd0c54|7dbb4403-9304-4fc0-8912-17af08ce6248",
"copper_edge_clearance|61100000|58735000|b1556ea3-f1cc-4201-b942-480142bd0c54|425646f1-4301-496a-bd77-d52b64168923"
],
"meta": {
"version": 2
},
"rule_severities": {
"annular_width": "error",
"clearance": "error",
"copper_edge_clearance": "error",
"courtyards_overlap": "error",
"diff_pair_gap_out_of_range": "error",
"diff_pair_uncoupled_length_too_long": "error",
"drill_out_of_range": "error",
"duplicate_footprints": "warning",
"extra_footprint": "warning",
"footprint_type_mismatch": "error",
"hole_clearance": "error",
"hole_near_hole": "error",
"invalid_outline": "error",
"item_on_disabled_layer": "error",
"items_not_allowed": "error",
"length_out_of_range": "error",
"malformed_courtyard": "error",
"microvia_drill_out_of_range": "error",
"missing_courtyard": "ignore",
"missing_footprint": "warning",
"net_conflict": "warning",
"npth_inside_courtyard": "ignore",
"padstack": "error",
"pth_inside_courtyard": "ignore",
"shorting_items": "error",
"silk_over_copper": "warning",
"silk_overlap": "warning",
"skew_out_of_range": "error",
"through_hole_pad_without_hole": "error",
"too_many_vias": "error",
"track_dangling": "warning",
"track_width": "error",
"tracks_crossing": "error",
"unconnected_items": "error",
"unresolved_variable": "error",
"via_dangling": "warning",
"zone_has_empty_net": "error",
"zones_intersect": "error"
},
"rules": {
"allow_blind_buried_vias": false,
"allow_microvias": false,
"max_error": 0.005,
"min_clearance": 0.0,
"min_copper_edge_clearance": 0.0,
"min_hole_clearance": 0.25,
"min_hole_to_hole": 0.25,
"min_microvia_diameter": 0.19999999999999998,
"min_microvia_drill": 0.09999999999999999,
"min_silk_clearance": 0.0,
"min_through_hole_diameter": 0.3,
"min_track_width": 0.19999999999999998,
"min_via_annular_width": 0.049999999999999996,
"min_via_diameter": 0.39999999999999997,
"solder_mask_clearance": 0.0,
"solder_mask_min_width": 0.0,
"use_height_for_length_calcs": true
},
"track_widths": [
0.0,
0.4,
0.6,
0.603595,
1.0
],
"via_dimensions": [
{
"diameter": 0.0,
"drill": 0.0
},
{
"diameter": 1.2,
"drill": 0.6
}
],
"zones_allow_external_fillets": false,
"zones_use_no_outline": true
},
"layer_presets": []
},
"boards": [],
"cvpcb": {
"equivalence_files": []
},
"erc": {
"erc_exclusions": [],
"meta": {
"version": 0
},
"pin_map": [
[
0,
0,
0,
0,
0,
0,
1,
0,
0,
0,
0,
2
],
[
0,
2,
0,
1,
0,
0,
1,
0,
2,
2,
2,
2
],
[
0,
0,
0,
0,
0,
0,
1,
0,
1,
0,
1,
2
],
[
0,
1,
0,
0,
0,
0,
1,
1,
2,
1,
1,
2
],
[
0,
0,
0,
0,
0,
0,
1,
0,
0,
0,
0,
2
],
[
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
2
],
[
1,
1,
1,
1,
1,
0,
1,
1,
1,
1,
1,
2
],
[
0,
0,
0,
1,
0,
0,
1,
0,
0,
0,
0,
2
],
[
0,
2,
1,
2,
0,
0,
1,
0,
2,
2,
2,
2
],
[
0,
2,
0,
1,
0,
0,
1,
0,
2,
0,
0,
2
],
[
0,
2,
1,
1,
0,
0,
1,
0,
2,
0,
0,
2
],
[
2,
2,
2,
2,
2,
2,
2,
2,
2,
2,
2,
2
]
],
"rule_severities": {
"bus_definition_conflict": "error",
"bus_entry_needed": "error",
"bus_label_syntax": "error",
"bus_to_bus_conflict": "error",
"bus_to_net_conflict": "error",
"different_unit_footprint": "error",
"different_unit_net": "error",
"duplicate_reference": "error",
"duplicate_sheet_names": "error",
"extra_units": "error",
"global_label_dangling": "warning",
"hier_label_mismatch": "error",
"label_dangling": "error",
"lib_symbol_issues": "warning",
"multiple_net_names": "warning",
"net_not_bus_member": "warning",
"no_connect_connected": "warning",
"no_connect_dangling": "warning",
"pin_not_connected": "error",
"pin_not_driven": "error",
"pin_to_pin": "warning",
"power_pin_not_driven": "error",
"similar_labels": "warning",
"unannotated": "error",
"unit_value_mismatch": "error",
"unresolved_variable": "error",
"wire_dangling": "error"
}
},
"libraries": {
"pinned_footprint_libs": [],
"pinned_symbol_libs": []
},
"meta": {
"filename": "PL18_multiprotocol.kicad_pro",
"version": 1
},
"net_settings": {
"classes": [
{
"bus_width": 12.0,
"clearance": 0.2,
"diff_pair_gap": 0.25,
"diff_pair_via_gap": 0.25,
"diff_pair_width": 0.2,
"line_style": 0,
"microvia_diameter": 0.3,
"microvia_drill": 0.1,
"name": "Default",
"pcb_color": "rgba(0, 0, 0, 0.000)",
"schematic_color": "rgba(0, 0, 0, 0.000)",
"track_width": 0.25,
"via_diameter": 0.8,
"via_drill": 0.4,
"wire_width": 6.0
}
],
"meta": {
"version": 2
},
"net_colors": null
},
"pcbnew": {
"last_paths": {
"gencad": "",
"idf": "",
"netlist": "",
"specctra_dsn": "",
"step": "",
"vrml": ""
},
"page_layout_descr_file": ""
},
"schematic": {
"annotate_start_num": 0,
"drawing": {
"default_line_thickness": 6.0,
"default_text_size": 50.0,
"field_names": [],
"intersheets_ref_own_page": false,
"intersheets_ref_prefix": "",
"intersheets_ref_short": false,
"intersheets_ref_show": false,
"intersheets_ref_suffix": "",
"junction_size_choice": 3,
"label_size_ratio": 0.375,
"pin_symbol_size": 25.0,
"text_offset_ratio": 0.15
},
"legacy_lib_dir": "",
"legacy_lib_list": [],
"meta": {
"version": 1
},
"net_format_name": "",
"ngspice": {
"fix_include_paths": true,
"fix_passive_vals": false,
"meta": {
"version": 0
},
"model_mode": 0,
"workbook_filename": ""
},
"page_layout_descr_file": "",
"plot_directory": "",
"spice_adjust_passive_values": false,
"spice_external_command": "spice \"%I\"",
"subpart_first_id": 65,
"subpart_id_separator": 0
},
"sheets": [
[
"e6b36db3-d652-4d66-bbfe-8c61f998d4b2",
""
]
],
"text_variables": {}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,3 @@
(fp_lib_table
(lib (name "Multi")(type "KiCad")(uri "${KIPRJMOD}/Multi.pretty")(options "")(descr ""))
)

View File

@@ -0,0 +1,3 @@
(sym_lib_table
(lib (name "Multi")(type "KiCad")(uri "${KIPRJMOD}/Multi.kicad_sym")(options "")(descr ""))
)

View File

@@ -0,0 +1,5 @@
# MPM for Flysky PL18
The PCB design is located in PL18_multiprotocol folder and is designed using KiCad 6.0.
The casing is located in Casing folder and is designed using Blender 3.3.1. The model included 2 pieces, T is the top piece and B is the bottom pieces. These 2 pieces is cloned into TF and BF respectively to apply all modifiers and make manifold for 3D printing. I have included the stl files generated for simplity.

View File

@@ -9,11 +9,11 @@ getMultiVersion() {
}
getAllRFModules() {
if [[ "$BOARD" =~ "multi4in1:avr:multixmega32d4" ]]; then
if [[ "$BOARD" =~ ":avr:multixmega32d4" ]]; then
ALL_RFMODULES=$(echo CYRF6936_INSTALLED);
elif [[ "$BOARD" =~ "multi4in1:avr:multiatmega328p:" ]]; then
elif [[ "$BOARD" =~ ":avr:multiatmega328p:" ]]; then
ALL_RFMODULES=$(echo A7105_INSTALLED CYRF6936_INSTALLED CC2500_INSTALLED NRF24L01_INSTALLED);
elif [[ "$BOARD" =~ "multi4in1:STM32F1:" ]]; then
elif [[ "$BOARD" =~ ":STM32F1:" ]]; then
ALL_RFMODULES=$(echo A7105_INSTALLED CYRF6936_INSTALLED CC2500_INSTALLED NRF24L01_INSTALLED SX1276_INSTALLED);
fi
}
@@ -26,11 +26,11 @@ getAllProtocols() {
CCNRF_PROTOCOLS=$(sed -n 's/[\/\/]*[[:blank:]]*#define[[:blank:]]*\([[:alnum:]_]*_CCNRF_INO\)\(.*\)/\1/p' Multiprotocol/_Config.h)
SX1276_PROTOCOLS=$(sed -n 's/[\/\/]*[[:blank:]]*#define[[:blank:]]*\([[:alnum:]_]*_SX1276_INO\)\(.*\)/\1/p' Multiprotocol/_Config.h)
if [[ "$BOARD" =~ "multi4in1:avr:multixmega32d4" ]]; then
if [[ "$BOARD" =~ ":avr:multixmega32d4" ]]; then
ALL_PROTOCOLS=$(echo $CYRF6936_PROTOCOLS);
elif [[ "$BOARD" =~ "multi4in1:avr:multiatmega328p:" ]]; then
elif [[ "$BOARD" =~ ":avr:multiatmega328p:" ]]; then
ALL_PROTOCOLS=$(echo $A7105_PROTOCOLS $CC2500_PROTOCOLS $CYRF6936_PROTOCOLS $NRF24L01_PROTOCOLS $CCNRF_PROTOCOLS);
elif [[ "$BOARD" =~ "multi4in1:STM32F1:" ]]; then
elif [[ "$BOARD" =~ ":STM32F1:" ]]; then
ALL_PROTOCOLS=$(echo $A7105_PROTOCOLS $CC2500_PROTOCOLS $CYRF6936_PROTOCOLS $NRF24L01_PROTOCOLS $CCNRF_PROTOCOLS $SX1276_PROTOCOLS);
fi
}
@@ -84,21 +84,21 @@ buildEachRFModule() {
}
buildReleaseFiles(){
if [[ "$BOARD" == "multi4in1:avr:multixmega32d4" ]]; then
if [[ "$BOARD" =~ ":avr:multixmega32d4" ]]; then
build_release_orx;
elif [[ "$BOARD" == "multi4in1:avr:multiatmega328p:bootloader=none" ]]; then
elif [[ "$BOARD" =~ ":avr:multiatmega328p:bootloader=none" ]]; then
build_release_avr_noboot;
elif [[ "$BOARD" == "multi4in1:avr:multiatmega328p:bootloader=optiboot" ]]; then
elif [[ "$BOARD" =~ ":avr:multiatmega328p:bootloader=optiboot" ]]; then
build_release_avr_optiboot;
elif [[ "$BOARD" == "multi4in1:STM32F1:multistm32f103cb:debug_option=none" ]]; then
elif [[ "$BOARD" =~ ":STM32F1:multistm32f103cb:debug_option=none" ]]; then
build_release_stm32f1_no_debug;
elif [[ "$BOARD" == "multi4in1:STM32F1:multistm32f103cb:debug_option=native" ]]; then
elif [[ "$BOARD" =~ ":STM32F1:multistm32f103cb:debug_option=native" ]]; then
build_release_stm32f1_native_debug;
elif [[ "$BOARD" == "multi4in1:STM32F1:multistm32f103cb:debug_option=ftdi" ]]; then
elif [[ "$BOARD" =~ ":STM32F1:multistm32f103cb:debug_option=ftdi" ]]; then
build_release_stm32f1_serial_debug;
elif [[ "$BOARD" == "multi4in1:STM32F1:multi5in1t18int" ]]; then
elif [[ "$BOARD" =~ ":STM32F1:multi5in1t18int" ]]; then
build_release_stm32f1_t18int;
elif [[ "$BOARD" == "multi4in1:STM32F1:multistm32f103c8:debug_option=none" ]]; then
elif [[ "$BOARD" =~ ":STM32F1:multistm32f103c8:debug_option=none" ]]; then
build_release_stm32f1_64k;
else
printf "No release files for this board.";

View File

@@ -20,6 +20,7 @@ Multiprotocol modules can be flashed with a precompiled firmware file (Option 1
1. [USB Port](#usb-port)
1. [USB-to-Serial adapter](#usb-to-serial-adapter)
1. [Upload the firmware](#upload-the-firmware)
1. [Option 4 - Flash via USB, using dfu-util (on Linux)](#option-4---flash-via-usb-using-dfu-util-on-linux)
1. [Troubleshooting](#troubleshooting)
## Tools required
@@ -172,6 +173,98 @@ In order to flash the bootloader the **BOOT0** jumper must be installed connecti
### Upload the firmware
1. In the Arduino IDE click **Sketch -> Upload**, or press **Ctrl+U**
## Option 4 - Flash via USB, using dfu-util (on Linux)
This upgrade method is only for modules that have USB connectors and
that have the ability to enter DFU mode when plugged into a Linux
machine.
[dfu-util](http://dfu-util.sourceforge.net/) is a command line tool that
can be used to write firmware to a processor that is in the DFU
state. Pre-built dfu-util packages are available for almost any Linux
distribution, so simply install the dfu-util package via your system's
package manager.
You now need to get your multimodule connected to your Linux machine
and make sure that it is in DFU mode. Usually the multimodule should
enter the DFU mode if you remove it from your radio and simply connect
it to your Linux machine via a _proper_ USB cable. Note: Some cheap,
loading USB cables sometimes have no data lines connected, and these
will no work.
Once your multimodule is connected, run the following command in order
to see if the DFU interface had been discovered:
```shell
# dfu-util -l -v
dfu-util 0.11
Copyright 2005-2009 Weston Schmidt, Harald Welte and OpenMoko Inc.
Copyright 2010-2021 Tormod Volden and Stefan Schmidt
This program is Free Software and has ABSOLUTELY NO WARRANTY
Please report bugs to http://sourceforge.net/p/dfu-util/tickets/
libusb version 1.0.26 (11724)
Found DFU: [1eaf:0003] ver=0201, devnum=69, cfg=1, intf=0, path="1-4", alt=2, name="STM32duino bootloader v1.0 Upload to Flash 0x8002000", serial="LLM 003"
Found DFU: [1eaf:0003] ver=0201, devnum=69, cfg=1, intf=0, path="1-4", alt=1, name="STM32duino bootloader v1.0 Upload to Flash 0x8005000", serial="LLM 003"
Found DFU: [1eaf:0003] ver=0201, devnum=69, cfg=1, intf=0, path="1-4", alt=0, name="STM32duino bootloader v1.0 ERROR. Upload to RAM not supported.", serial="LLM 003"
```
If you the above didn't succeed, your module is not in DFU mode and it
would not make any sense to continue.
Now that your Linux machine discovered the device with id, 1eaf:0003,
you can can start the update process, which will take around 8 to 10
seconds. Once done, your multimodule will be updated and you can
simply unplug it and start using it.
The example below, uses a pre-compiled binary available from
[here](https://github.com/pascallanger/DIY-Multiprotocol-TX-Module/releases).
```shell
# dfu-util -v -R -a 2 -d 1EAF:0003 -D mm-stm-serial-aetr-v1.3.3.14.bin
dfu-util 0.11
Copyright 2005-2009 Weston Schmidt, Harald Welte and OpenMoko Inc.
Copyright 2010-2021 Tormod Volden and Stefan Schmidt
This program is Free Software and has ABSOLUTELY NO WARRANTY
Please report bugs to http://sourceforge.net/p/dfu-util/tickets/
libusb version 1.0.26 (11724)
dfu-util: Warning: Invalid DFU suffix signature
dfu-util: A valid DFU suffix will be required in a future dfu-util release
Opening DFU capable USB device...
Device ID 1eaf:0003
Device DFU version 0110
DFU attributes: (0x03) bitCanDnload bitCanUpload
Detach timeout 255 ms
Claiming USB DFU Interface...
Setting Alternate Interface #2 ...
Determining device status...
DFU state(2) = dfuIDLE, status(0) = No error condition is present
DFU mode device DFU version 0110
Device returned transfer size 1024
Copying data from PC to DFU device
Download [=========================] 100% 118668 bytes
Download done.
Sent a total of 118668 bytes
DFU state(8) = dfuMANIFEST-WAIT-RESET, status(0) = No error condition is present
Resetting USB to switch back to runtime mode
Done!
```
NOTE: The above command was taken and adapted from
[here](https://github.com/benlye/flash-multi/blob/master/doc/Troubleshooting.md).
As you can see, the above process is really extremely straight
forward. You basically only need to have dfu-util installed and you need to
run one single command for updating your multimodule.
As a bonus, the dfu-util method could also be used under Mac or
Windows, as dfu-util binaries also exist for those operating systems.
# Troubleshooting
You can report your problem using the [GitHub issue](https://github.com/midelic/DIY-Multiprotocol-TX-Module/issues) system or go to the [Main thread on RCGROUPS](http://www.rcgroups.com/forums/showthread.php?t=2165676) to ask your question.
Please provide the following information: