Compare commits
2385 Commits
v1.0.0
...
pascallang
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bf1a842955 | ||
|
|
11ae26a431 | ||
|
|
cdabde5d67 | ||
|
|
ce75dd3355 | ||
|
|
69484b5278 | ||
|
|
a90e1f2d3a | ||
|
|
5af246bba0 | ||
|
|
75a46858da | ||
|
|
8ac53657ec | ||
|
|
2888d3e937 | ||
|
|
3d989a47db | ||
|
|
a7d6d12679 | ||
|
|
457703b881 | ||
|
|
8e663f2531 | ||
|
|
8c2fe5f65e | ||
|
|
7549783741 | ||
|
|
e6bafaabb7 | ||
|
|
9286ac84f6 | ||
|
|
ede40ac598 | ||
|
|
88fad2dc9f | ||
|
|
549d3ad653 | ||
|
|
62aa58d32d | ||
|
|
21a06c2925 | ||
|
|
9acb3b0e2c | ||
|
|
785edde659 | ||
|
|
7da6d52a84 | ||
|
|
61cbe45ce2 | ||
|
|
23af33e214 | ||
|
|
11db967b8a | ||
|
|
d419e2b344 | ||
|
|
2b69c1184e | ||
|
|
1ceed87298 | ||
|
|
a1737eab46 | ||
|
|
9cbcafe6cf | ||
|
|
495706314f | ||
|
|
595511979b | ||
|
|
b8d30f47be | ||
|
|
b7097bdfb7 | ||
|
|
a682b0e604 | ||
|
|
7e7b555809 | ||
|
|
62ecaa8412 | ||
|
|
5ae052317d | ||
|
|
f3331ca397 | ||
|
|
ffcfd44127 | ||
|
|
5ef944241a | ||
|
|
ab5f75b1b3 | ||
|
|
10ec4dd735 | ||
|
|
a62d1dcd2e | ||
|
|
2c9e98e341 | ||
|
|
0bf94e96b5 | ||
|
|
8d84386c7a | ||
|
|
cd721e31d8 | ||
|
|
1294ad21cf | ||
|
|
01bc08575f | ||
|
|
ecfe17915f | ||
|
|
f97aa3597d | ||
|
|
2e1d763d54 | ||
|
|
93a2cc8b7f | ||
|
|
abfebb3da4 | ||
|
|
ce5f4ec264 | ||
|
|
a41123deb2 | ||
|
|
fabb65a2bb | ||
|
|
eae1329dfe | ||
|
|
a8ae0a2bd1 | ||
|
|
c814cc1bd4 | ||
|
|
4e7c1502ff | ||
|
|
8ddee12de5 | ||
|
|
692bcc1fbb | ||
|
|
0bb345e3fc | ||
|
|
c193d0b9dd | ||
|
|
410ce5cc4c | ||
|
|
cefe69a692 | ||
|
|
daa4ded390 | ||
|
|
5949fca990 | ||
|
|
ed2e2e4f32 | ||
|
|
b2f8f482bb | ||
|
|
89023d4b55 | ||
|
|
66ac007d4c | ||
|
|
139cd4c583 | ||
|
|
0fed2486f5 | ||
|
|
11c01004bf | ||
|
|
f49f03d7da | ||
|
|
90bb5f8871 | ||
|
|
401cc76f20 | ||
|
|
6297810edc | ||
|
|
01aef0a822 | ||
|
|
186730231e | ||
|
|
770a12ffdf | ||
|
|
40fa242012 | ||
|
|
c4e70ab4fd | ||
|
|
2da8b3c42a | ||
|
|
38a79c816a | ||
|
|
1d8f1a0857 | ||
|
|
5901bac374 | ||
|
|
2e7b1dc904 | ||
|
|
7052751261 | ||
|
|
60047e2c73 | ||
|
|
40b393ac4a | ||
|
|
1c6dc01959 | ||
|
|
5148449066 | ||
|
|
fcc4d19430 | ||
|
|
c80f705fa2 | ||
|
|
c95db35b41 | ||
|
|
35f3548992 | ||
|
|
58f6716035 | ||
|
|
2b15de0f90 | ||
|
|
be91409df9 | ||
|
|
4d8e440965 | ||
|
|
2d469d074e | ||
|
|
96405d27b5 | ||
|
|
75c9fb40a7 | ||
|
|
cd1c15a45a | ||
|
|
2bd50f4c8c | ||
|
|
4c2ddcbe48 | ||
|
|
d7f9ef6967 | ||
|
|
bfc8c2f9fd | ||
|
|
ce6243d6e3 | ||
|
|
80f9ff4163 | ||
|
|
d9f8a3989a | ||
|
|
416f7d5c19 | ||
|
|
eb24dd5549 | ||
|
|
ba19592973 | ||
|
|
98d8d7fb5f | ||
|
|
ad0947b0b7 | ||
|
|
c093f21b31 | ||
|
|
c5a3e305f9 | ||
|
|
e085602a6c | ||
|
|
dee25215cf | ||
|
|
ef1bb1ead7 | ||
|
|
90170493c0 | ||
|
|
00a9057186 | ||
|
|
05c300e979 | ||
|
|
6730ed6246 | ||
|
|
0a0463652b | ||
|
|
4f580a4286 | ||
|
|
0616cab386 | ||
|
|
175cfa5e93 | ||
|
|
dbfccad568 | ||
|
|
3fe6dc64fa | ||
|
|
49068af59f | ||
|
|
fbd81c6e26 | ||
|
|
9cac96d6a7 | ||
|
|
5987aa40a6 | ||
|
|
30cb812549 | ||
|
|
0fd2e36046 | ||
|
|
8b05e55ebd | ||
|
|
af71a208fd | ||
|
|
7e5cb8e884 | ||
|
|
8c669ea015 | ||
|
|
acd8379077 | ||
|
|
97c6088715 | ||
|
|
db017c73b6 | ||
|
|
24aaa0dd0c | ||
|
|
da33df4346 | ||
|
|
22590ed4f7 | ||
|
|
c0bc64c2aa | ||
|
|
694d968e8c | ||
|
|
fff3b8830e | ||
|
|
b740f4cd24 | ||
|
|
e247b8b9c1 | ||
|
|
4f7af553d1 | ||
|
|
570e6f8c64 | ||
|
|
b6e665b567 | ||
|
|
48e82304a0 | ||
|
|
7b58b9aca0 | ||
|
|
dfcf3f533c | ||
|
|
4c14925b4f | ||
|
|
4c74bc869d | ||
|
|
45edfa1ec0 | ||
|
|
88343b7424 | ||
|
|
13197840c2 | ||
|
|
ffe4ac68fd | ||
|
|
5bab5f03db | ||
|
|
ae748e25f8 | ||
|
|
e9c7959ecb | ||
|
|
bf09855014 | ||
|
|
32bd39f209 | ||
|
|
940f241b9d | ||
|
|
5c00ce6b88 | ||
|
|
016b282246 | ||
|
|
d6ecac1302 | ||
|
|
901f8ca6b0 | ||
|
|
9c3b6ba9f6 | ||
|
|
53ec484028 | ||
|
|
246e808cb4 | ||
|
|
a7b68dc2aa | ||
|
|
08404f9223 | ||
|
|
149554e61c | ||
|
|
7b71425db2 | ||
|
|
f9cfb7f20f | ||
|
|
506ee43d41 | ||
|
|
ebde0915cd | ||
|
|
2501656bf4 | ||
|
|
9356e7654e | ||
|
|
4f1e5d2452 | ||
|
|
64c75414d8 | ||
|
|
5147833487 | ||
|
|
324419241f | ||
|
|
1a921b1cdb | ||
|
|
25c052c0a3 | ||
|
|
a02586cca9 | ||
|
|
226e082c5a | ||
|
|
5afdff8477 | ||
|
|
c52ac2cefc | ||
|
|
09f39ea60f | ||
|
|
41e31eae6d | ||
|
|
dcf20951ba | ||
|
|
6e9ebfd695 | ||
|
|
c36b112437 | ||
|
|
24fbd44f5b | ||
|
|
d0db7829e5 | ||
|
|
58ed8ca60f | ||
|
|
4d2c8ef04e | ||
|
|
438e85c551 | ||
|
|
06b336ee59 | ||
|
|
a93adeb75e | ||
|
|
802e69563e | ||
|
|
a8897df3f2 | ||
|
|
7157d3d906 | ||
|
|
96b8a500b4 | ||
|
|
51a3ef8ee9 | ||
|
|
652d6604e7 | ||
|
|
b9028ab4b4 | ||
|
|
62c509b03c | ||
|
|
1648a0780a | ||
|
|
3b1af68ed6 | ||
|
|
aeed7bac57 | ||
|
|
2bb76a40f3 | ||
|
|
0c129a45aa | ||
|
|
2a383c7285 | ||
|
|
34f16b0b66 | ||
|
|
a9d9c4cdfa | ||
|
|
4a1c986dd0 | ||
|
|
756e9b3213 | ||
|
|
61a284863e | ||
|
|
39410c290b | ||
|
|
9e0684b6cb | ||
|
|
13add5b9f2 | ||
|
|
475cd1af98 | ||
|
|
04d08c6d67 | ||
|
|
6295bb1bbc | ||
|
|
931ba2bd68 | ||
|
|
769fb4ff94 | ||
|
|
aa7c18a2bd | ||
|
|
f95cfa1261 | ||
|
|
8c12aaf2c1 | ||
|
|
94f73bd54f | ||
|
|
9b3549d4a9 | ||
|
|
7bc05cb63c | ||
|
|
84780a9d90 | ||
|
|
37e029c612 | ||
|
|
c47ed8aca8 | ||
|
|
5bb0752d5e | ||
|
|
4a626eaf14 | ||
|
|
47de19c8a5 | ||
|
|
3d4cfa30ac | ||
|
|
d658bee05a | ||
|
|
820c181394 | ||
|
|
c9774f557e | ||
|
|
b17618a5a8 | ||
|
|
03d0adbd74 | ||
|
|
905ee4b1ed | ||
|
|
dbc33951a4 | ||
|
|
732e66cab2 | ||
|
|
0dab92552a | ||
|
|
047952537a | ||
|
|
d4bf1fb36e | ||
|
|
ff817cd098 | ||
|
|
04ea44ed4b | ||
|
|
e23c8e2216 | ||
|
|
afb4802a2c | ||
|
|
3a5d341514 | ||
|
|
b6bcab1604 | ||
|
|
0a998d2dc5 | ||
|
|
7927bc601e | ||
|
|
f8cc913898 | ||
|
|
a5428bc180 | ||
|
|
c0285f81f0 | ||
|
|
600049898a | ||
|
|
0e1db8f06b | ||
|
|
ec83f1e5a3 | ||
|
|
f8f7769d9c | ||
|
|
4dacac29c6 | ||
|
|
593f3b87f1 | ||
|
|
bb70116df0 | ||
|
|
d7c24d62ed | ||
|
|
07df1a8959 | ||
|
|
ca9e2870ab | ||
|
|
99ca6fa36c | ||
|
|
3d82560f71 | ||
|
|
44d362aeb4 | ||
|
|
3d4ed5ad11 | ||
|
|
ca3c2bbdc8 | ||
|
|
90c226c748 | ||
|
|
b757283f41 | ||
|
|
b3132c7bf1 | ||
|
|
9ba56f040a | ||
|
|
ac71b4d981 | ||
|
|
6bb2c06cf6 | ||
|
|
2ad3c727fd | ||
|
|
d36af55b84 | ||
|
|
f19bb05c7a | ||
|
|
08ea8818fb | ||
|
|
59c541d013 | ||
|
|
37e2b5f41c | ||
|
|
614a330cf2 | ||
|
|
9106548859 | ||
|
|
2f07e79e50 | ||
|
|
2233f6f862 | ||
|
|
ae842f0bdc | ||
|
|
4b36656246 | ||
|
|
ea282489f9 | ||
|
|
6f2d9430d0 | ||
|
|
bccd9dc0d9 | ||
|
|
af919fb940 | ||
|
|
7dab0de3c5 | ||
|
|
2c0525421a | ||
|
|
0844ec2efd | ||
|
|
49c3af12f9 | ||
|
|
96d335f458 | ||
|
|
eae412fe41 | ||
|
|
0270420531 | ||
|
|
93bb117961 | ||
|
|
29d1fb00b1 | ||
|
|
5a49d99c4f | ||
|
|
d66bf1a5b3 | ||
|
|
b41dccef67 | ||
|
|
addf2c5143 | ||
|
|
ff829f1f7b | ||
|
|
7ee72976c4 | ||
|
|
dc18e8e5b2 | ||
|
|
97de2aaf3d | ||
|
|
3b8b2ef376 | ||
|
|
d496f62719 | ||
|
|
fc978f95ef | ||
|
|
596e8c9b55 | ||
|
|
0cf58c2990 | ||
|
|
6ba1c8b118 | ||
|
|
b949ac0fed | ||
|
|
510f892d2f | ||
|
|
17750e774a | ||
|
|
be1591c489 | ||
|
|
3b22705166 | ||
|
|
c05c0a5693 | ||
|
|
d6fc6a3517 | ||
|
|
7bfaee8b4f | ||
|
|
89c00e8f17 | ||
|
|
447a58966f | ||
|
|
74162aa972 | ||
|
|
78a1e61f7a | ||
|
|
a917227ddc | ||
|
|
c866d07743 | ||
|
|
43d969f962 | ||
|
|
3973b42f81 | ||
|
|
6046ad81db | ||
|
|
63a9874aea | ||
|
|
89420fe2d4 | ||
|
|
9769354989 | ||
|
|
580b996215 | ||
|
|
8f5fb5083f | ||
|
|
821076ce95 | ||
|
|
0bfe1f8e63 | ||
|
|
9c35f6f73c | ||
|
|
983debe6ce | ||
|
|
66704b5a13 | ||
|
|
f11da0c1de | ||
|
|
7676398aab | ||
|
|
9c6c55fa00 | ||
|
|
5b9ca3ba06 | ||
|
|
23141b6087 | ||
|
|
6d4b4bd2c0 | ||
|
|
5cec22a757 | ||
|
|
153ba2e090 | ||
|
|
21e8bed52b | ||
|
|
ecfc5b0313 | ||
|
|
2bcebbda45 | ||
|
|
52e8d87ab1 | ||
|
|
b613345da4 | ||
|
|
f2665ca786 | ||
|
|
e3189d3aed | ||
|
|
c829e1c86f | ||
|
|
8499a508f5 | ||
|
|
50dec0e55d | ||
|
|
6f419adb7f | ||
|
|
502e8beafb | ||
|
|
5aae065dc0 | ||
|
|
152dbed3fa | ||
|
|
b516bb8d20 | ||
|
|
30e3e84066 | ||
|
|
8338104266 | ||
|
|
00c6aa52b9 | ||
|
|
e5689d2f1b | ||
|
|
b51dedcea1 | ||
|
|
49f004e53f | ||
|
|
062fc05eac | ||
|
|
6d080d5d5f | ||
|
|
0955340a93 | ||
|
|
9b2318cc7e | ||
|
|
2098cdc5e0 | ||
|
|
d19b5187c5 | ||
|
|
2a78b1d6b7 | ||
|
|
84ae6366eb | ||
|
|
e5b235ac83 | ||
|
|
0195384592 | ||
|
|
0937f832fc | ||
|
|
c77b4af2a0 | ||
|
|
b943bae8dd | ||
|
|
4955978eb6 | ||
|
|
df409fddf5 | ||
|
|
0330c596e4 | ||
|
|
8c6c58f12f | ||
|
|
4bc08d22b8 | ||
|
|
96fb3b20b7 | ||
|
|
47f713c6c8 | ||
|
|
443c7a6b99 | ||
|
|
e79ca9b7d7 | ||
|
|
b94f774f80 | ||
|
|
5614e8bef6 | ||
|
|
4ce3a5d298 | ||
|
|
f6de3de78c | ||
|
|
8099018132 | ||
|
|
360dde2e1b | ||
|
|
cc7b7638d3 | ||
|
|
321e4aee34 | ||
|
|
f18847df57 | ||
|
|
a2559a65d3 | ||
|
|
5ac41fdd15 | ||
|
|
6d38dd2d7a | ||
|
|
667058269c | ||
|
|
ad6f934892 | ||
|
|
714220c349 | ||
|
|
4887fca873 | ||
|
|
cfe80edcb6 | ||
|
|
484588ff6b | ||
|
|
1bb059c2a2 | ||
|
|
ef5d9cb6b3 | ||
|
|
37a06c050d | ||
|
|
5f0ed395ba | ||
|
|
ae27c8b671 | ||
|
|
088bfb9c2f | ||
|
|
b01462e36b | ||
|
|
abd36dc6a4 | ||
|
|
ebb8a33c1a | ||
|
|
2b0f663482 | ||
|
|
956e632392 | ||
|
|
90b6bb8f7d | ||
|
|
6153e84abf | ||
|
|
16357f29e9 | ||
|
|
0b8a5a7539 | ||
|
|
6874e3a6a7 | ||
|
|
96263ed8a6 | ||
|
|
7bb1cb9ae3 | ||
|
|
20e32c4cb0 | ||
|
|
b4421306c0 | ||
|
|
e53f723fdb | ||
|
|
832a331437 | ||
|
|
12e66bd84f | ||
|
|
d290cc519f | ||
|
|
f4b19fe33e | ||
|
|
767d2c079a | ||
|
|
7750310be5 | ||
|
|
6de4e1e1dd | ||
|
|
627d47f139 | ||
|
|
36675cf729 | ||
|
|
33d8234eb3 | ||
|
|
347eb11328 | ||
|
|
5ed61f30e1 | ||
|
|
a633f46f4f | ||
|
|
baf9a0f978 | ||
|
|
c98b8fc8bf | ||
|
|
2fae0a35b8 | ||
|
|
b04f38ed3d | ||
|
|
60d5dd4101 | ||
|
|
75b7dd1dd7 | ||
|
|
aa2717d6ab | ||
|
|
4058f04b39 | ||
|
|
25ebd55c85 | ||
|
|
d00b58c8ed | ||
|
|
e7eb07a5a4 | ||
|
|
a4cac50261 | ||
|
|
4f8da64822 | ||
|
|
4f89721cd0 | ||
|
|
43c2843490 | ||
|
|
c152265284 | ||
|
|
b591b92b4e | ||
|
|
090388aa1b | ||
|
|
c6ab696949 | ||
|
|
df45a3ff83 | ||
|
|
fedd04b724 | ||
|
|
d8630da09d | ||
|
|
6192f7287e | ||
|
|
5b8a08ab22 | ||
|
|
313b03fb84 | ||
|
|
5639def6fb | ||
|
|
15a254879c | ||
|
|
5baa9bd256 | ||
|
|
d5346c0eaf | ||
|
|
a2213fd6dc | ||
|
|
9b07f12f90 | ||
|
|
c9b49483e0 | ||
|
|
e2972a5823 | ||
|
|
d5b3ed832d | ||
|
|
9fcc030c15 | ||
|
|
fc81b7ee5a | ||
|
|
f168abc2bb | ||
|
|
fe6778635e | ||
|
|
65a6c19d02 | ||
|
|
a32b5561a1 | ||
|
|
4b4393952e | ||
|
|
ea205b1e69 | ||
|
|
748140cdee | ||
|
|
e8037c857f | ||
|
|
15e37cefee | ||
|
|
b1e4daf1c2 | ||
|
|
4e0fccfc63 | ||
|
|
48b90029c4 | ||
|
|
8b189af2f9 | ||
|
|
030cdd35a2 | ||
|
|
3789998ba9 | ||
|
|
ea24ab6032 | ||
|
|
1408431649 | ||
|
|
6810372064 | ||
|
|
708e2ac5f6 | ||
|
|
2178f6761d | ||
|
|
aa5fd82004 | ||
|
|
660282db2e | ||
|
|
fdd357619b | ||
|
|
5f12f99761 | ||
|
|
3d98abb6d4 | ||
|
|
e35879a5d0 | ||
|
|
37138f03ae | ||
|
|
51d39bbd8c | ||
|
|
0932a1c93f | ||
|
|
19164521e4 | ||
|
|
df28cfe3cc | ||
|
|
354878d542 | ||
|
|
695264d59a | ||
|
|
de190f3349 | ||
|
|
b049385094 | ||
|
|
75dc616130 | ||
|
|
b542f5e7cd | ||
|
|
f3bee3cded | ||
|
|
a9b7ab9a06 | ||
|
|
ed019e954e | ||
|
|
65186b4356 | ||
|
|
e1d4f9a270 | ||
|
|
69c95ca153 | ||
|
|
e6976fb08d | ||
|
|
f502ba3659 | ||
|
|
e6ccc7e7cc | ||
|
|
da9d8851c2 | ||
|
|
ad48291d2a | ||
|
|
d6da230369 | ||
|
|
f8ac406a94 | ||
|
|
e691ecd167 | ||
|
|
930c26a111 | ||
|
|
64419a6cf4 | ||
|
|
5c59cddc7a | ||
|
|
4c7a51be46 | ||
|
|
7dad0fb89f | ||
|
|
adebb3fc5c | ||
|
|
5ab00b9d18 | ||
|
|
fbd5d7cf48 | ||
|
|
84132678cc | ||
|
|
78421748ba | ||
|
|
7112f58dae | ||
|
|
e56f737b34 | ||
|
|
49d993f613 | ||
|
|
63dd8a9215 | ||
|
|
d5f819dd59 | ||
|
|
a68787f16e | ||
|
|
858ef5801c | ||
|
|
9e0bd29cee | ||
|
|
15395de579 | ||
|
|
db4aad04a7 | ||
|
|
466e4cf227 | ||
|
|
05a3780c38 | ||
|
|
85ea91cdbb | ||
|
|
985d7a6fd9 | ||
|
|
2a19b8dd45 | ||
|
|
b2b3078861 | ||
|
|
2ac92f5725 | ||
|
|
e2f5afd71e | ||
|
|
e094ee036d | ||
|
|
2ad7f3e9f2 | ||
|
|
8e1f2258f8 | ||
|
|
5c01bbf284 | ||
|
|
647425fc1a | ||
|
|
7286049d07 | ||
|
|
ce67a065cd | ||
|
|
8948cb6287 | ||
|
|
4daa5fa2bb | ||
|
|
c49a7dae0a | ||
|
|
890a042a43 | ||
|
|
c95e576ef3 | ||
|
|
2aa96dd129 | ||
|
|
908634474b | ||
|
|
79b525ee71 | ||
|
|
872b8259ab | ||
|
|
a14c82708f | ||
|
|
7e53778680 | ||
|
|
210fbe3b9e | ||
|
|
0a5fd72bdc | ||
|
|
6e1701ecc5 | ||
|
|
a5f627a2d6 | ||
|
|
b4a1f175c6 | ||
|
|
e0690fa661 | ||
|
|
bd962eff35 | ||
|
|
b515355249 | ||
|
|
d1feef97be | ||
|
|
f52f96d44e | ||
|
|
944ec62f49 | ||
|
|
30905014d2 | ||
|
|
32dbdfc6e3 | ||
|
|
b2e312b41e | ||
|
|
52f4096197 | ||
|
|
c547ea0c0f | ||
|
|
c73ee61128 | ||
|
|
90b287f1f4 | ||
|
|
0316c9eea9 | ||
|
|
374b46966c | ||
|
|
3705415927 | ||
|
|
bff68f482e | ||
|
|
32ed758072 | ||
|
|
5ce99ee419 | ||
|
|
ceea384a36 | ||
|
|
fd3b026e12 | ||
|
|
7e451c13a8 | ||
|
|
3dcf74c2e4 | ||
|
|
50f1eca4be | ||
|
|
0d97af5ae2 | ||
|
|
aeb8d67219 | ||
|
|
1f65025036 | ||
|
|
8df3687684 | ||
|
|
adf59a9d0d | ||
|
|
b9f00bdbc5 | ||
|
|
a10e169573 | ||
|
|
317b9a8156 | ||
|
|
1c632d462f | ||
|
|
c46b49ccf1 | ||
|
|
e70708b133 | ||
|
|
62486c2220 | ||
|
|
cffe66747a | ||
|
|
b31bbfa04f | ||
|
|
48e4cad3ad | ||
|
|
53f58ce2e1 | ||
|
|
eb8b5eac01 | ||
|
|
02008a8b2e | ||
|
|
5b82599eb9 | ||
|
|
a5e4b2c6fa | ||
|
|
987753ff73 | ||
|
|
ee080839b1 | ||
|
|
4290c75478 | ||
|
|
cc6be6027d | ||
|
|
4cfde0a80a | ||
|
|
a77aee0e1a | ||
|
|
6f36473975 | ||
|
|
f5720d38bb | ||
|
|
23478d3d21 | ||
|
|
ba72b6dedd | ||
|
|
103f595891 | ||
|
|
957d623b4b | ||
|
|
2be757e609 | ||
|
|
c4be660a05 | ||
|
|
c1c5f9fe3a | ||
|
|
53c0637a85 | ||
|
|
4ae30dc3b0 | ||
|
|
fc5fbc9899 | ||
|
|
2397bf365b | ||
|
|
42cd17d5f2 | ||
|
|
a35e01bbeb | ||
|
|
b21e8030b3 | ||
|
|
0984a42fe5 | ||
|
|
ed50d60108 | ||
|
|
a7f72a73e5 | ||
|
|
1c02cb46f5 | ||
|
|
da8fd21177 | ||
|
|
7e5cd9819a | ||
|
|
00aecb3ab1 | ||
|
|
cde77a88fd | ||
|
|
08a555f187 | ||
|
|
4039cbf8af | ||
|
|
3f652fa06c | ||
|
|
272d2be3ae | ||
|
|
7e461344a8 | ||
|
|
8af985a2cb | ||
|
|
08eee34446 | ||
|
|
0a5b97a177 | ||
|
|
cab782b38e | ||
|
|
d1518d763b | ||
|
|
44a676b809 | ||
|
|
d66709ea87 | ||
|
|
358a77cf7c | ||
|
|
1a631908f4 | ||
|
|
9f32a1f22b | ||
|
|
dfd3386319 | ||
|
|
3df836e6b8 | ||
|
|
2b8ed25843 | ||
|
|
62250d2f25 | ||
|
|
a4e9082f53 | ||
|
|
7217e8c41d | ||
|
|
a7ac093753 | ||
|
|
5503502bad | ||
|
|
5124c2a96d | ||
|
|
73d7728e08 | ||
|
|
8b7bd00a48 | ||
|
|
68a6af0eb5 | ||
|
|
693f9f58eb | ||
|
|
4a01e2d472 | ||
|
|
e4fd1f4399 | ||
|
|
0d5fcb0849 | ||
|
|
2236c256ba | ||
|
|
945ad2e7bd | ||
|
|
6f9740f03f | ||
|
|
f9fa4dff73 | ||
|
|
77bf17967d | ||
|
|
7281c0b5bf | ||
|
|
e6cab65560 | ||
|
|
cc115323e1 | ||
|
|
58665ea7a7 | ||
|
|
3920644caf | ||
|
|
25aecbf15e | ||
|
|
e18d8868d2 | ||
|
|
c6e5d00a2b | ||
|
|
7a5b4dea1a | ||
|
|
5df877f32c | ||
|
|
c5c7dda2e0 | ||
|
|
492b9e5ed4 | ||
|
|
9f721c528d | ||
|
|
7f3c80c2a9 | ||
|
|
8f789607e4 | ||
|
|
6a9b6ed4be | ||
|
|
953a97dae4 | ||
|
|
86778c5997 | ||
|
|
8c32cdf5fd | ||
|
|
d092593e5c | ||
|
|
edbf4b6908 | ||
|
|
43f688d011 | ||
|
|
054c3088c3 | ||
|
|
0cedd5bb66 | ||
|
|
1961579fe4 | ||
|
|
6906f1652e | ||
|
|
e2bbe8a422 | ||
|
|
8ea4e00d31 | ||
|
|
917e27280f | ||
|
|
ec92edfc85 | ||
|
|
afd2be6c59 | ||
|
|
a23d50bf0d | ||
|
|
cace1144db | ||
|
|
0d646ed1a6 | ||
|
|
e9b09ffecd | ||
|
|
0008633d6e | ||
|
|
396c005b0a | ||
|
|
d3c3fac4f7 | ||
|
|
cf4acc1d4c | ||
|
|
5bd95f8414 | ||
|
|
a31d9a83a3 | ||
|
|
9b24589897 | ||
|
|
8f3d634132 | ||
|
|
5ef1ccb99b | ||
|
|
e7d91bc76a | ||
|
|
e4309824c2 | ||
|
|
cc6a35ac8a | ||
|
|
1f13a6c281 | ||
|
|
69519bdf14 | ||
|
|
2e5a8f384a | ||
|
|
c803eeb26a | ||
|
|
6a7497cdf8 | ||
|
|
3067ea3a5c | ||
|
|
9a5309d84b | ||
|
|
fff18f825a | ||
|
|
e70bdd4152 | ||
|
|
cf77a1981f | ||
|
|
10e33f5d5c | ||
|
|
db442d81dd | ||
|
|
f800b4f90b | ||
|
|
712f297d86 | ||
|
|
0afed7d3a4 | ||
|
|
6a03972ff3 | ||
|
|
0e40f64c6b | ||
|
|
c83b769f28 | ||
|
|
dad3282bbb | ||
|
|
1621263fb0 | ||
|
|
2686cd0c48 | ||
|
|
b07b081a15 | ||
|
|
c5d4e8c191 | ||
|
|
928641f535 | ||
|
|
c4c5ffec4f | ||
|
|
c048e97d3a | ||
|
|
00f0719659 | ||
|
|
0482627512 | ||
|
|
5856442e0f | ||
|
|
7b281e47d6 | ||
|
|
6ef2934c18 | ||
|
|
19b931223b | ||
|
|
ca15d7108f | ||
|
|
e6e4d33847 | ||
|
|
815cf4fd99 | ||
|
|
5cf2bf2cf5 | ||
|
|
6632da0276 | ||
|
|
9b499ab7d1 | ||
|
|
d29461607b | ||
|
|
243bdf2240 | ||
|
|
cde185901a | ||
|
|
a9f35f8095 | ||
|
|
63d7e32e06 | ||
|
|
400fdb3cc6 | ||
|
|
9f1bdc901c | ||
|
|
61970b028e | ||
|
|
aee92737ca | ||
|
|
0fddd9c119 | ||
|
|
b156f66146 | ||
|
|
63e6590b65 | ||
|
|
103be7f6e0 | ||
|
|
2154b75499 | ||
|
|
6a83cb5577 | ||
|
|
70ce8e9a1f | ||
|
|
fdd0a00d5a | ||
|
|
a8cad1e70a | ||
|
|
40afd67fc6 | ||
|
|
f3b9206d67 | ||
|
|
b76dd4c8ac | ||
|
|
3eb507ebe6 | ||
|
|
fe0a1f0f94 | ||
|
|
fab3339b8d | ||
|
|
10604cf820 | ||
|
|
e297310a25 | ||
|
|
d71006f2ae | ||
|
|
7a8e099a79 | ||
|
|
822aa84fa2 | ||
|
|
948ce9e8b8 | ||
|
|
caf145c38a | ||
|
|
f964cdec98 | ||
|
|
6848fab873 | ||
|
|
72d57cae71 | ||
|
|
a23178e20e | ||
|
|
5ae4f0288b | ||
|
|
e0e51eb187 | ||
|
|
840944ea94 | ||
|
|
31ff27b1d3 | ||
|
|
a234ccbd05 | ||
|
|
6dfd54b8be | ||
|
|
edb7729b35 | ||
|
|
d434e63c22 | ||
|
|
cd7ede006c | ||
|
|
d4d0dc3dbc | ||
|
|
5c7f997e7a | ||
|
|
1623a007a4 | ||
|
|
0b19fa0bdf | ||
|
|
897c8b6ec5 | ||
|
|
d427a7fec1 | ||
|
|
b0749a1bee | ||
|
|
2406080515 | ||
|
|
ff96146b04 | ||
|
|
e3a5b2825d | ||
|
|
9fd72b5ad5 | ||
|
|
c2bf63991f | ||
|
|
a75ae7b65a | ||
|
|
507e4cb07b | ||
|
|
0f250bb04b | ||
|
|
4a315057a2 | ||
|
|
c8f44a0c4b | ||
|
|
382d853fe2 | ||
|
|
a5996c488e | ||
|
|
760642ecb3 | ||
|
|
c7a3548df0 | ||
|
|
d8acc6a5e8 | ||
|
|
431808286b | ||
|
|
747fa19259 | ||
|
|
bf61295b76 | ||
|
|
49a1ecea00 | ||
|
|
11f0e55bb1 | ||
|
|
331da37840 | ||
|
|
032e0641a5 | ||
|
|
f3d2ab61e4 | ||
|
|
e8b5f071fe | ||
|
|
ada72d6113 | ||
|
|
c2404d4f0d | ||
|
|
821732bba9 | ||
|
|
b6df650f50 | ||
|
|
e783ce5788 | ||
|
|
18af4a0724 | ||
|
|
7e6ec1dc8d | ||
|
|
4fbe0859e0 | ||
|
|
b89c23fe7c | ||
|
|
e038c49ae9 | ||
|
|
bed02c9384 | ||
|
|
96bc4f7cdf | ||
|
|
6503469ddd | ||
|
|
61a1c3742c | ||
|
|
1fb2a38bc1 | ||
|
|
22a0d79315 | ||
|
|
0cc72772a3 | ||
|
|
11f4e636e3 | ||
|
|
fef1a2e041 | ||
|
|
41a9c8e013 | ||
|
|
c1ad02b792 | ||
|
|
ab2315c951 | ||
|
|
7948e33cbc | ||
|
|
2be2dce584 | ||
|
|
69bdfe3dba | ||
|
|
d73d163a58 | ||
|
|
48a52ae5b2 | ||
|
|
078dc2ab17 | ||
|
|
6f4522caa6 | ||
|
|
3c76ce9f39 | ||
|
|
8601149051 | ||
|
|
d7ef15d435 | ||
|
|
27e3645b56 | ||
|
|
95eb4e1a22 | ||
|
|
32ea07bf5a | ||
|
|
06272575c5 | ||
|
|
edd6432d4c | ||
|
|
303c4615e9 | ||
|
|
7d327c1622 | ||
|
|
6a74b83f98 | ||
|
|
c601c2dd98 | ||
|
|
c27b60749f | ||
|
|
b3cb286088 | ||
|
|
361903e8ec | ||
|
|
d72c69242d | ||
|
|
539819fa0c | ||
|
|
d80c218744 | ||
|
|
0603d220a9 | ||
|
|
e13fe56f47 | ||
|
|
acd7694485 | ||
|
|
7f50edacc8 | ||
|
|
5a4906c5b5 | ||
|
|
4e906757b9 | ||
|
|
1f0b21e351 | ||
|
|
2f3ea323c7 | ||
|
|
d4e77c6499 | ||
|
|
ffc56b049d | ||
|
|
ddac89d732 | ||
|
|
fecf2805c7 | ||
|
|
4dcc88ba32 | ||
|
|
084308d8a4 | ||
|
|
1ffb5c405b | ||
|
|
ad29409407 | ||
|
|
6f33abb25e | ||
|
|
2c9693389e | ||
|
|
d3c82c4da4 | ||
|
|
541a96e7b4 | ||
|
|
5b234a9cbc | ||
|
|
24c3a62f3a | ||
|
|
23756a387a | ||
|
|
efbd350dfd | ||
|
|
072e95c84e | ||
|
|
4be26e7202 | ||
|
|
a616cbb95c | ||
|
|
8aea9aa3dd | ||
|
|
e4992bc917 | ||
|
|
000b3e97c7 | ||
|
|
cb91e19413 | ||
|
|
c72e690085 | ||
|
|
f1a4e659e7 | ||
|
|
0d56d17d52 | ||
|
|
96c89c8c97 | ||
|
|
7df5a1f211 | ||
|
|
8ae8e028c7 | ||
|
|
581ad5f8f4 | ||
|
|
977bae3750 | ||
|
|
8a0161607e | ||
|
|
cd6a7bfc3a | ||
|
|
4671700b7d | ||
|
|
840ca74407 | ||
|
|
0d8a7e46de | ||
|
|
8b9940b0f0 | ||
|
|
521b819b8a | ||
|
|
208e9ef64b | ||
|
|
a7ea8e012e | ||
|
|
d940a7e49a | ||
|
|
9d50171034 | ||
|
|
701a5b9e28 | ||
|
|
d11785ef2d | ||
|
|
f4a4d91ef8 | ||
|
|
9514e47ed3 | ||
|
|
9461f2d632 | ||
|
|
f6064d03e1 | ||
|
|
0d917e0dc5 | ||
|
|
9408af8d08 | ||
|
|
862ab48bbc | ||
|
|
f498347c53 | ||
|
|
3f77f59c8a | ||
|
|
e96186015d | ||
|
|
1fa6e4526b | ||
|
|
3853d585a0 | ||
|
|
e8c6225ef0 | ||
|
|
17c67cc780 | ||
|
|
dcc4236833 | ||
|
|
6a7c735924 | ||
|
|
3c40cd853e | ||
|
|
5357660b68 | ||
|
|
a15a911f8e | ||
|
|
ded0487ce6 | ||
|
|
e7b079ece7 | ||
|
|
0cbe4de920 | ||
|
|
5c3bf30fe7 | ||
|
|
56b8694fd5 | ||
|
|
c9fecafada | ||
|
|
f3ca7ad644 | ||
|
|
c3b48c78af | ||
|
|
18dcc29a0d | ||
|
|
c3a5c263d3 | ||
|
|
ccdf60d525 | ||
|
|
443e1cec75 | ||
|
|
aa540514b8 | ||
|
|
fda7e2e5b6 | ||
|
|
fb4d5cf437 | ||
|
|
9fc2898a56 | ||
|
|
2e24323adf | ||
|
|
77abc1ed7c | ||
|
|
259d550d04 | ||
|
|
1a8f9c5a12 | ||
|
|
1916eb3095 | ||
|
|
fc3eec7ae1 | ||
|
|
8d10c9b004 | ||
|
|
511f77f5e7 | ||
|
|
a58d7a4d79 | ||
|
|
6748f6ce78 | ||
|
|
2dcb6b1987 | ||
|
|
2b4ac41142 | ||
|
|
2b47958207 | ||
|
|
5538d4d1c4 | ||
|
|
467756df48 | ||
|
|
534ebb26c0 | ||
|
|
21790a9725 | ||
|
|
6bc22c8ac4 | ||
|
|
ac1c422f14 | ||
|
|
efa1860104 | ||
|
|
c673b4254f | ||
|
|
96db173694 | ||
|
|
1d5be624fe | ||
|
|
56f9672896 | ||
|
|
303b3f08b8 | ||
|
|
150e3fd92e | ||
|
|
840b01273c | ||
|
|
8a7beda339 | ||
|
|
65606f7083 | ||
|
|
0095071ebf | ||
|
|
ae4ee9061d | ||
|
|
6ba06bc006 | ||
|
|
00f247eae1 | ||
|
|
c250c91ab4 | ||
|
|
b1ac10a4c4 | ||
|
|
af4185fbea | ||
|
|
aa85d4d797 | ||
|
|
74cc63e6dd | ||
|
|
04ed613ca3 | ||
|
|
9ea157b9b6 | ||
|
|
536d7f6124 | ||
|
|
869a01b57f | ||
|
|
ea982b23c2 | ||
|
|
15dfe8cead | ||
|
|
b50027150e | ||
|
|
103acb8294 | ||
|
|
aca23b8bca | ||
|
|
aaffbbc5be | ||
|
|
e0002c9488 | ||
|
|
687d6d914c | ||
|
|
9a61b2701e | ||
|
|
d8224ebefe | ||
|
|
cc2af73a05 | ||
|
|
aecd44ada6 | ||
|
|
72593c4d99 | ||
|
|
52ca258616 | ||
|
|
04412667ff | ||
|
|
4124ec80ec | ||
|
|
693ea75e95 | ||
|
|
9e3c1ab059 | ||
|
|
5fc860702f | ||
|
|
6ad2ee5a47 | ||
|
|
b0f64297cb | ||
|
|
f99a63dbc0 | ||
|
|
9261e8fe94 | ||
|
|
52bb116e24 | ||
|
|
7006c36101 | ||
|
|
f7d452e3f1 | ||
|
|
598e50a40f | ||
|
|
eadfa26c3b | ||
|
|
b03491fdf7 | ||
|
|
42911c63b3 | ||
|
|
43462757ed | ||
|
|
0eee1c5d15 | ||
|
|
3a21bf69f1 | ||
|
|
7d4c8f7f07 | ||
|
|
866d19d649 | ||
|
|
c27ec2475c | ||
|
|
1d64cbfaa0 | ||
|
|
5d1baa89e4 | ||
|
|
e846ce7e98 | ||
|
|
300b3582a6 | ||
|
|
3a7ffe62b0 | ||
|
|
d990ebe49e | ||
|
|
bd78739217 | ||
|
|
6c7312a09c | ||
|
|
1525e564cb | ||
|
|
7fb4bbbf3c | ||
|
|
2553d44d32 | ||
|
|
dc902b7a61 | ||
|
|
b992cbd92e | ||
|
|
22711fad28 | ||
|
|
a9df0abed3 | ||
|
|
fd65550f8d | ||
|
|
b910ad3386 | ||
|
|
fb9f094365 | ||
|
|
05470446a0 | ||
|
|
903982afb7 | ||
|
|
8bea5b125b | ||
|
|
c658a892f2 | ||
|
|
3f0d6cfcf1 | ||
|
|
c6657c199c | ||
|
|
cf6d980b8b | ||
|
|
c3ff49e86e | ||
|
|
e51f91f041 | ||
|
|
2589c67f6c | ||
|
|
2f4f19b52b | ||
|
|
b3ed7563dc | ||
|
|
ea96c328fc | ||
|
|
f42da14413 | ||
|
|
2149149723 | ||
|
|
f1916b3d0b | ||
|
|
10788976b6 | ||
|
|
567d26a385 | ||
|
|
220eb8f6f4 | ||
|
|
b40e7d6e97 | ||
|
|
97dd90a718 | ||
|
|
75ba6401a4 | ||
|
|
5cf8d8d263 | ||
|
|
058e09c413 | ||
|
|
63fb1b1f36 | ||
|
|
7c0b9ce3c6 | ||
|
|
c153d236f2 | ||
|
|
3b3a3c275c | ||
|
|
f4691d08cc | ||
|
|
e5d9471b33 | ||
|
|
ab9525c507 | ||
|
|
b1fb3a5470 | ||
|
|
b2194790eb | ||
|
|
8901310ed4 | ||
|
|
09c6adaa95 | ||
|
|
5fe1e9674e | ||
|
|
601116bd59 | ||
|
|
27dc02fdec | ||
|
|
03f417546e | ||
|
|
3b9aa79201 | ||
|
|
5aa4936c0e | ||
|
|
1e65d58113 | ||
|
|
e2a66bdd1f | ||
|
|
4f9c30505a | ||
|
|
1ec817c96c | ||
|
|
41528ae7b6 | ||
|
|
77d248df0b | ||
|
|
c6cb13b332 | ||
|
|
d67108fa8b | ||
|
|
b7447f055a | ||
|
|
3902ed19b7 | ||
|
|
51ba7cf75c | ||
|
|
82fb5dd0da | ||
|
|
2ac20cb575 | ||
|
|
3f33e5b2a8 | ||
|
|
655ea98bf1 | ||
|
|
238260612c | ||
|
|
cd26c2d8e6 | ||
|
|
814e28b86a | ||
|
|
f515ba79af | ||
|
|
e6f16700e4 | ||
|
|
f38e7c35da | ||
|
|
b3576b7162 | ||
|
|
d9914e95d9 | ||
|
|
64c79626b4 | ||
|
|
e047a76855 | ||
|
|
e7449897f9 | ||
|
|
db093cf25b | ||
|
|
4bb4bd9792 | ||
|
|
c16654c8cf | ||
|
|
817ff7e239 | ||
|
|
685de52538 | ||
|
|
1dc52773f4 | ||
|
|
fbb04ea88a | ||
|
|
23da318645 | ||
|
|
30b77931d7 | ||
|
|
39327b2b27 | ||
|
|
13c3af96a6 | ||
|
|
4411732022 | ||
|
|
0c08b8b93b | ||
|
|
838755aabf | ||
|
|
2bca104e33 | ||
|
|
cf857f3256 | ||
|
|
1647d3d841 | ||
|
|
2f5252ab88 | ||
|
|
eb89b5be1b | ||
|
|
e80fe29dba | ||
|
|
74ab2a4bd7 | ||
|
|
edd4f740e0 | ||
|
|
d0c9bc801b | ||
|
|
73dd63caa1 | ||
|
|
cc4703ea40 | ||
|
|
f105d7c7eb | ||
|
|
e85ad00a46 | ||
|
|
658dfa4290 | ||
|
|
df75036501 | ||
|
|
9ab5353122 | ||
|
|
5345ece322 | ||
|
|
9f09c81ef4 | ||
|
|
c8dea20865 | ||
|
|
bf09177916 | ||
|
|
d71640ad7e | ||
|
|
68afcc0c44 | ||
|
|
9b30a3d72a | ||
|
|
789cd21618 | ||
|
|
d9f343e20b | ||
|
|
0b8ff15133 | ||
|
|
27a4748111 | ||
|
|
18efaef38c | ||
|
|
35137b87ed | ||
|
|
9019c46102 | ||
|
|
52d0869c50 | ||
|
|
236b375669 | ||
|
|
9502b5a12a | ||
|
|
ad18856f7a | ||
|
|
9015b78aaf | ||
|
|
8cc7a4f693 | ||
|
|
ac298fee61 | ||
|
|
457fc5296e | ||
|
|
b8f3cd1ad8 | ||
|
|
f9f265271a | ||
|
|
dde5f6e119 | ||
|
|
add3fb13ef | ||
|
|
51c1936c24 | ||
|
|
07adeaf60d | ||
|
|
811913bf89 | ||
|
|
8906c85d06 | ||
|
|
7df5894ca4 | ||
|
|
fa9e559195 | ||
|
|
81f408ee77 | ||
|
|
aa8a059553 | ||
|
|
8c7918577d | ||
|
|
7219885196 | ||
|
|
9f8915239f | ||
|
|
83401f6e1a | ||
|
|
dd686ad9d1 | ||
|
|
7d04005c72 | ||
|
|
cdbaeb1c6c | ||
|
|
6bf432a112 | ||
|
|
f6ef136502 | ||
|
|
4a9d295f1a | ||
|
|
105e0bb7a4 | ||
|
|
ab27ee50b0 | ||
|
|
f4a4f67453 | ||
|
|
fb88eebc2f | ||
|
|
6fea0c2a93 | ||
|
|
301c8da9eb | ||
|
|
4facdf0932 | ||
|
|
ce489887db | ||
|
|
55e30bd4aa | ||
|
|
eb0d03d420 | ||
|
|
db1da2d9cf | ||
|
|
6fa3b8597f | ||
|
|
c8da89f0d3 | ||
|
|
c3c89801e9 | ||
|
|
eb3f8b0d91 | ||
|
|
d3285f002e | ||
|
|
e81ee38fa5 | ||
|
|
499e854275 | ||
|
|
cd235bbcde | ||
|
|
984aa3f413 | ||
|
|
11287cb9c0 | ||
|
|
5cc49a8862 | ||
|
|
fabda76e98 | ||
|
|
70db505dd9 | ||
|
|
29fd1c800b | ||
|
|
d70d8f62a4 | ||
|
|
bef562964d | ||
|
|
fc5495b6d1 | ||
|
|
f3838ae4b0 | ||
|
|
b3eccf55ba | ||
|
|
835cc3d0a2 | ||
|
|
b49584ec16 | ||
|
|
334e49c4ca | ||
|
|
3fc5be111b | ||
|
|
1bc2dd2964 | ||
|
|
68dcc75949 | ||
|
|
dc9f738f30 | ||
|
|
4171d2f93b | ||
|
|
64fb90960b | ||
|
|
93e277bb0f | ||
|
|
337216efac | ||
|
|
f1f5b68821 | ||
|
|
8f941e6d12 | ||
|
|
6a4dcbd6e1 | ||
|
|
7e773dfe1b | ||
|
|
465ae75ffc | ||
|
|
8da03940e8 | ||
|
|
f280779528 | ||
|
|
5c568da125 | ||
|
|
f46b8366b0 | ||
|
|
1d9c052c01 | ||
|
|
544927b9b7 | ||
|
|
8b5bb0d358 | ||
|
|
6031f1e3b8 | ||
|
|
c297df76ef | ||
|
|
122e9f4fca | ||
|
|
748ed01252 | ||
|
|
56188328fb | ||
|
|
880e463b01 | ||
|
|
a53046bf12 | ||
|
|
a8050fd8a1 | ||
|
|
6ae819e8d5 | ||
|
|
79c73444ab | ||
|
|
8cc1b07456 | ||
|
|
0d43614ac3 | ||
|
|
19f879da7f | ||
|
|
ed42bf311f | ||
|
|
fd4346cb64 | ||
|
|
6e458ebd4a | ||
|
|
0f0be60245 | ||
|
|
27783677c2 | ||
|
|
4418cab3a5 | ||
|
|
b3cddfe2d4 | ||
|
|
a19ac87a04 | ||
|
|
3ba951fd91 | ||
|
|
824f23c3d6 | ||
|
|
fc49a32008 | ||
|
|
5ca0d31606 | ||
|
|
ebd44d9628 | ||
|
|
329fa1c2a5 | ||
|
|
9a5bf7999b | ||
|
|
7debad6c67 | ||
|
|
dc9b84ea8b | ||
|
|
199c254838 | ||
|
|
7ff482dafe | ||
|
|
9376019198 | ||
|
|
cec654a75b | ||
|
|
3e004d01ec | ||
|
|
21266d0a17 | ||
|
|
2b62b8dab3 | ||
|
|
b24564ffe9 | ||
|
|
f57d436640 | ||
|
|
762613bd7f | ||
|
|
e2ed752b51 | ||
|
|
2610926f47 | ||
|
|
cf1a74e532 | ||
|
|
f55b451d9b | ||
|
|
ae51e389ca | ||
|
|
6f71ef1d03 | ||
|
|
94a9e4db05 | ||
|
|
82dc0c4f32 | ||
|
|
bb5827629e | ||
|
|
76f7cb7126 | ||
|
|
d5005323d4 | ||
|
|
9bc1a9963f | ||
|
|
cefbf2ee70 | ||
|
|
e10dc6dcec | ||
|
|
e4f4d278a8 | ||
|
|
3dd9df558e | ||
|
|
87c2216d0f | ||
|
|
8cd5ff6bd6 | ||
|
|
28868e4c78 | ||
|
|
01bef23ac9 | ||
|
|
9379bd1792 | ||
|
|
63a479b6b6 | ||
|
|
49b0d92c75 | ||
|
|
277402a25d | ||
|
|
cc83177542 | ||
|
|
5a342cf8e6 | ||
|
|
7d5dabde82 | ||
|
|
e3917226cc | ||
|
|
4e3c1edd52 | ||
|
|
e52b7ea7ff | ||
|
|
6f60d87f85 | ||
|
|
049db615e3 | ||
|
|
e557155b17 | ||
|
|
9bf5b0c9a7 | ||
|
|
ea860f24a1 | ||
|
|
5e89d49bd9 | ||
|
|
cb1ba0e00c | ||
|
|
0f965b6800 | ||
|
|
486c2170cd | ||
|
|
83641a4f54 | ||
|
|
5cb2326ea7 | ||
|
|
84d7986353 | ||
|
|
a3c2628359 | ||
|
|
8ae34bdd9d | ||
|
|
4a9374936d | ||
|
|
110378e3b4 | ||
|
|
bd60feff60 | ||
|
|
2181d0b33c | ||
|
|
2afa7ea691 | ||
|
|
d0f76117cd | ||
|
|
e25060a16e | ||
|
|
5e6da326f6 | ||
|
|
981a8f8d2c | ||
|
|
5c7e592e1e | ||
|
|
2a25f76b56 | ||
|
|
41d579dc23 | ||
|
|
7d41017850 | ||
|
|
daeba0d43a | ||
|
|
24fd5ba361 | ||
|
|
3353637c8f | ||
|
|
9601e6942d | ||
|
|
4b32a93f27 | ||
|
|
9e8978166e | ||
|
|
6bf873f4db | ||
|
|
1318f1a29b | ||
|
|
d9282ac750 | ||
|
|
205d728798 | ||
|
|
bd9c772a52 | ||
|
|
76e9002995 | ||
|
|
e990d44bb6 | ||
|
|
2ffa2d7b73 | ||
|
|
0e4583f8e2 | ||
|
|
3802722bb1 | ||
|
|
41f0a712fd | ||
|
|
4633c37380 | ||
|
|
b779becf8c | ||
|
|
35089febab | ||
|
|
a95fd1e1d8 | ||
|
|
6535f64699 | ||
|
|
b15a5d4a45 | ||
|
|
65a5c37ffb | ||
|
|
6cf58c032c | ||
|
|
e0365df6dd | ||
|
|
40ae0c7257 | ||
|
|
aecd4c5266 | ||
|
|
113caf4970 | ||
|
|
da2d57c8e9 | ||
|
|
3aed8b8479 | ||
|
|
ff58a826b1 | ||
|
|
9a0873e404 | ||
|
|
7d9133793c | ||
|
|
f43d9883cf | ||
|
|
067842818e | ||
|
|
8ea70a1b77 | ||
|
|
47207dcead | ||
|
|
235876a4d8 | ||
|
|
af88abb13f | ||
|
|
f13701b120 | ||
|
|
5f7c598a34 | ||
|
|
defd354286 | ||
|
|
f9e6b30550 | ||
|
|
d451af365a | ||
|
|
57a78535f2 | ||
|
|
f824ecb7f9 | ||
|
|
98f848138d | ||
|
|
200a1dc3da | ||
|
|
507e1d2b50 | ||
|
|
0f752e2571 | ||
|
|
ca6cd65d46 | ||
|
|
ddc287a84e | ||
|
|
c92ec031ae | ||
|
|
ef2d4d6b12 | ||
|
|
2753f6c4e5 | ||
|
|
021577d638 | ||
|
|
dd3f8b4717 | ||
|
|
a1fb4a0ac5 | ||
|
|
ebf0c4fae6 | ||
|
|
44a086a27b | ||
|
|
4624075112 | ||
|
|
97a3c8dca1 | ||
|
|
c50b5d93d7 | ||
|
|
08f9176f3f | ||
|
|
f95ca6eac6 | ||
|
|
34165c0d90 | ||
|
|
1f87cf09d7 | ||
|
|
005c7b9cb0 | ||
|
|
2b265bd1de | ||
|
|
3e83216384 | ||
|
|
a9889b5b79 | ||
|
|
2aa5b7917f | ||
|
|
040354501c | ||
|
|
bd46f6d25f | ||
|
|
7e801269af | ||
|
|
2586e2e661 | ||
|
|
fb2a5c2378 | ||
|
|
f490fa6e7d | ||
|
|
df347be672 | ||
|
|
4e518bf70c | ||
|
|
29e90246d2 | ||
|
|
1e62c0d836 | ||
|
|
278ebf4ff2 | ||
|
|
edc58a3496 | ||
|
|
7c96862b19 | ||
|
|
11b18f7468 | ||
|
|
86787b6099 | ||
|
|
12645c19aa | ||
|
|
7e06a57fd9 | ||
|
|
4d7c31cfa1 | ||
|
|
f5e4fc5a3d | ||
|
|
1c4174431e | ||
|
|
60d4f2d6c7 | ||
|
|
5a30a96c0c | ||
|
|
09b454ba6a | ||
|
|
8ea06e84a6 | ||
|
|
ebaf56d964 | ||
|
|
517d2bb1ec | ||
|
|
706d43ee41 | ||
|
|
e537d27e28 | ||
|
|
948f28b0af | ||
|
|
70f7c6a25e | ||
|
|
a0a0cd4f57 | ||
|
|
dfa120339c | ||
|
|
36f194b9bd | ||
|
|
12dd851fc3 | ||
|
|
cc9a5893de | ||
|
|
9d2ac3f2c4 | ||
|
|
9cda61de3d | ||
|
|
060d93d68b | ||
|
|
8d1e8c6699 | ||
|
|
f4865c5206 | ||
|
|
2d44c89149 | ||
|
|
c2050d4314 | ||
|
|
7991605106 | ||
|
|
adeea85c9a | ||
|
|
c32e390184 | ||
|
|
154f61fb11 | ||
|
|
b08bcf041b | ||
|
|
e51f6e1e86 | ||
|
|
62e2a0211f | ||
|
|
5286e7f89c | ||
|
|
e81ba55967 | ||
|
|
25a2689bd0 | ||
|
|
c949eb5491 | ||
|
|
709c5cbd71 | ||
|
|
3ac59a5bc0 | ||
|
|
6894228a63 | ||
|
|
a7b914b84e | ||
|
|
84922e84a3 | ||
|
|
7ee0b2b0a3 | ||
|
|
5c06a241ac | ||
|
|
0cb0128caf | ||
|
|
8661b8074c | ||
|
|
fa52a1a81e | ||
|
|
680fa7a350 | ||
|
|
3850ce88d3 | ||
|
|
a800f1efc7 | ||
|
|
514bbbe8a3 | ||
|
|
700b922350 | ||
|
|
bdfeeb9a41 | ||
|
|
2b80d1a6d8 | ||
|
|
fa6f2061e7 | ||
|
|
ff5f12e4d2 | ||
|
|
9ad6e8142d | ||
|
|
49e3534738 | ||
|
|
4cb7ba83e9 | ||
|
|
9282828ffc | ||
|
|
2f2a2d4bee | ||
|
|
b904e6a889 | ||
|
|
804d5723c2 | ||
|
|
681e3a6865 | ||
|
|
dd75c56404 | ||
|
|
86cee1e339 | ||
|
|
063edc032a | ||
|
|
32c59cb583 | ||
|
|
0242f88d26 | ||
|
|
940a89fa38 | ||
|
|
364a66ad0b | ||
|
|
f714315b0d | ||
|
|
ed83471a13 | ||
|
|
1263aa7884 | ||
|
|
c21afc3f8a | ||
|
|
59af0594dc | ||
|
|
8cf6d4f7d8 | ||
|
|
61ceeb44fb | ||
|
|
995bb921c1 | ||
|
|
e7cab78aad | ||
|
|
1c06bd45ef | ||
|
|
85a3e112e0 | ||
|
|
9c5e054dda | ||
|
|
86932e6da4 | ||
|
|
5f94fdfc93 | ||
|
|
74584dd39e | ||
|
|
18ed5d51a9 | ||
|
|
d7076f5295 | ||
|
|
29a5397491 | ||
|
|
47a4261631 | ||
|
|
a3927218a6 | ||
|
|
7d846a3d0d | ||
|
|
8db1f6d1e2 | ||
|
|
9cb679d545 | ||
|
|
006d705cbd | ||
|
|
a19a14665f | ||
|
|
55bc6f9a00 | ||
|
|
997d31addd | ||
|
|
548390b0d7 | ||
|
|
bd64bdedc3 | ||
|
|
846e09c7cb | ||
|
|
2ba3552578 | ||
|
|
943bb6d15b | ||
|
|
af53e75ae4 | ||
|
|
14ca63571d | ||
|
|
10c5ce68f5 | ||
|
|
d9fb856eb8 | ||
|
|
f5c08158cb | ||
|
|
9ee0311ea9 | ||
|
|
69ed2d2428 | ||
|
|
0c5fae01b5 | ||
|
|
72052925a6 | ||
|
|
dc2d02bf32 | ||
|
|
ee267ea086 | ||
|
|
1e730f3376 | ||
|
|
c230c52af6 | ||
|
|
219beb4a0e | ||
|
|
c4807c44f3 | ||
|
|
7dafd14644 | ||
|
|
57c3e8c51d | ||
|
|
da71eca978 | ||
|
|
7a47af14be | ||
|
|
f67adc53ab | ||
|
|
68e9948493 | ||
|
|
894416c719 | ||
|
|
11650450c8 | ||
|
|
6973d85b10 | ||
|
|
bf5598515e | ||
|
|
cc03c27d17 | ||
|
|
9cd729df71 | ||
|
|
d6ee9fbfac | ||
|
|
b6999f5c67 | ||
|
|
c02f273d57 | ||
|
|
8d87bfb4a3 | ||
|
|
0a7cd3d6e9 | ||
|
|
235699b3b9 | ||
|
|
1aebfbecc1 | ||
|
|
00e47b9afb | ||
|
|
68b94cfcaa | ||
|
|
0068f21a2d | ||
|
|
7a7e639490 | ||
|
|
81bae1441e | ||
|
|
3516e5ae8a | ||
|
|
04bbe3187f | ||
|
|
877cdec4ea | ||
|
|
21ab94c512 | ||
|
|
70f52afb3d | ||
|
|
85f4dbd670 | ||
|
|
bee70e67bc | ||
|
|
7e137f17a5 | ||
|
|
c576f62ca3 | ||
|
|
9c8499e6cd | ||
|
|
f81e7cb78a | ||
|
|
773f3048f7 | ||
|
|
40faaea7f8 | ||
|
|
47b4409f3e | ||
|
|
9ce23c3d61 | ||
|
|
f40ffed069 | ||
|
|
0b223170d9 | ||
|
|
e61f8a512c | ||
|
|
65b43c39ed | ||
|
|
131645f31e | ||
|
|
ca8fc14d36 | ||
|
|
efe693c0c0 | ||
|
|
4eb2d073ac | ||
|
|
fd49c02e18 | ||
|
|
f0e3d492d3 | ||
|
|
3f8ba6be9d | ||
|
|
df4563379d | ||
|
|
f0f9d8faa7 | ||
|
|
031b4b637a | ||
|
|
e206ae3403 | ||
|
|
021c463d80 | ||
|
|
41d75da33f | ||
|
|
c7e7a559a6 | ||
|
|
4f5dfcc65b | ||
|
|
e85208110f | ||
|
|
17bb2f11e4 | ||
|
|
124db5f11f | ||
|
|
6b099d7298 | ||
|
|
7ac2e227b1 | ||
|
|
868c1aa251 | ||
|
|
7283fc89a5 | ||
|
|
f933560934 | ||
|
|
7ee918ad49 | ||
|
|
e30ebd39fd | ||
|
|
7ac6ff828c | ||
|
|
017f5f8e74 | ||
|
|
2c46feb8f8 | ||
|
|
f5171f3f47 | ||
|
|
1a2c28435a | ||
|
|
7221fc2060 | ||
|
|
e17e7ab4ec | ||
|
|
46eb0bc474 | ||
|
|
b03227ea9f | ||
|
|
a1de5e15c5 | ||
|
|
7f2322ba60 | ||
|
|
5c04844461 | ||
|
|
591a185fc2 | ||
|
|
fbc0b60b68 | ||
|
|
325ce8824e | ||
|
|
d54e25bb44 | ||
|
|
740943aee2 | ||
|
|
73ee93335b | ||
|
|
c69c3361ac | ||
|
|
a91d019738 | ||
|
|
dc272a472d | ||
|
|
b265108322 | ||
|
|
6cab6a9646 | ||
|
|
3baf237fa8 | ||
|
|
fa8503546e | ||
|
|
b9d988c712 | ||
|
|
2bbf672094 | ||
|
|
a6f8fe4c95 | ||
|
|
6d7415880a | ||
|
|
479e4588f3 | ||
|
|
821f1bdc2b | ||
|
|
5cdd672e84 | ||
|
|
48fb8d0b92 | ||
|
|
52fae655ba | ||
|
|
3ab6e84275 | ||
|
|
2b5ab6db11 | ||
|
|
a0f6d47153 | ||
|
|
787901ba73 | ||
|
|
37c7167128 | ||
|
|
35e1ddc578 | ||
|
|
d61e7b8729 | ||
|
|
8ef73f9dd2 | ||
|
|
f7448cc2e4 | ||
|
|
6af35b5ec5 | ||
|
|
8f4e5c6064 | ||
|
|
2d76775e40 | ||
|
|
8eb71cbe74 | ||
|
|
9146a8bb21 | ||
|
|
445bca7333 | ||
|
|
6286551ef5 | ||
|
|
1ae6a69c7a | ||
|
|
34851b772f | ||
|
|
4823aa378e | ||
|
|
40a42e86ee | ||
|
|
c518b52243 | ||
|
|
abccc3c3cd | ||
|
|
9786b7139e | ||
|
|
28e8e3434e | ||
|
|
cdf59fba10 | ||
|
|
be8571cb56 | ||
|
|
857715e55c | ||
|
|
5ccc815a47 | ||
|
|
d77c04109b | ||
|
|
1ba8b8b1b1 | ||
|
|
caa349b59b | ||
|
|
9a7350149d | ||
|
|
7f435363f7 | ||
|
|
832cb79f88 | ||
|
|
ba7290fdda | ||
|
|
85ee4a95ec | ||
|
|
eb164c511f | ||
|
|
26e3119ef3 | ||
|
|
6c38b54f7d | ||
|
|
7e6badaf5d | ||
|
|
c104e8e1f0 | ||
|
|
c8d04f3373 | ||
|
|
f64f417711 | ||
|
|
92fe975e3d | ||
|
|
e00731ef8f | ||
|
|
0d7d0664f6 | ||
|
|
b59b0ef041 | ||
|
|
964aa0ecce | ||
|
|
a9ecf06cd4 | ||
|
|
76da6857e7 | ||
|
|
9eef60c93d | ||
|
|
df412bbef7 | ||
|
|
b4c6632162 | ||
|
|
5f2eb6bd32 | ||
|
|
ea532b15fc | ||
|
|
01bd1fde39 | ||
|
|
c6c1c61ff6 | ||
|
|
bbd33c70c1 | ||
|
|
a2592342fe | ||
|
|
db06e12337 | ||
|
|
22139c9650 | ||
|
|
3b1e2e38fb | ||
|
|
6f6da47ebe | ||
|
|
f3237172f3 | ||
|
|
45dc64af5a | ||
|
|
4df71bff7f | ||
|
|
f5003d3505 | ||
|
|
f2f3fab3e2 | ||
|
|
2357e139f0 | ||
|
|
c74eaa47a3 | ||
|
|
591f9fa4c2 | ||
|
|
766ffa3e65 | ||
|
|
78d2c7beaa | ||
|
|
f11c38238a | ||
|
|
6d388d50ee | ||
|
|
9479254562 | ||
|
|
9c9fdaf35d | ||
|
|
a4767591ae | ||
|
|
ecbc50b990 | ||
|
|
dde9cc27d0 | ||
|
|
703c03e84b | ||
|
|
2f831b3e6f | ||
|
|
d54eec0b87 | ||
|
|
bc80554cd3 | ||
|
|
a696d330e5 | ||
|
|
b1479ab3c5 | ||
|
|
e51fb06ceb | ||
|
|
dc0f2bde6b | ||
|
|
eb13f267fe | ||
|
|
8677e73d75 | ||
|
|
fbb919d767 | ||
|
|
1f0f9a2eae | ||
|
|
282b2a0a43 | ||
|
|
6d0e4d5a38 | ||
|
|
43956bbf2c | ||
|
|
18e31b3821 | ||
|
|
0d0acb9d10 | ||
|
|
6a792ce6a0 | ||
|
|
917cea5052 | ||
|
|
c98f0d3c81 | ||
|
|
88d650e638 | ||
|
|
72ebe937fb | ||
|
|
8efa5bc1dc | ||
|
|
9b6d2bce58 | ||
|
|
7bb26a7f07 | ||
|
|
9585b3919a | ||
|
|
f56c9deb00 | ||
|
|
c6221fc60f | ||
|
|
acfe3e912e | ||
|
|
50be0ebe3c | ||
|
|
704dc803b8 | ||
|
|
e2d64e9140 | ||
|
|
bdef0612f7 | ||
|
|
a196b71d36 | ||
|
|
fff8116430 | ||
|
|
2be6fb13d2 | ||
|
|
faa6d7f148 | ||
|
|
982fc2838d | ||
|
|
a8351319f8 | ||
|
|
5b1901708c | ||
|
|
fa8d4f511f | ||
|
|
b4215afe82 | ||
|
|
2ad25e8fbc | ||
|
|
67d0e9d2c2 | ||
|
|
f69aae550f | ||
|
|
2d26acd991 | ||
|
|
8dec1453c4 | ||
|
|
241d1e181f | ||
|
|
f267c597e0 | ||
|
|
192437896d | ||
|
|
d59ae7fce1 | ||
|
|
18b21005f1 | ||
|
|
94ac91cce3 | ||
|
|
46e255bccc | ||
|
|
87de5b5305 | ||
|
|
1ddc923631 | ||
|
|
03f65606fd | ||
|
|
148cf9552b | ||
|
|
bf230322d0 | ||
|
|
758779a8f5 | ||
|
|
55eb39c51d | ||
|
|
13b8475c54 | ||
|
|
d3d52b44ee | ||
|
|
d2886432b7 | ||
|
|
7bb8737ff9 | ||
|
|
3904c36a6e | ||
|
|
c2577df6f7 | ||
|
|
36cb0fb4cd | ||
|
|
ec79793f3d | ||
|
|
188bf76ed1 | ||
|
|
e4e909737c | ||
|
|
d32421c583 | ||
|
|
63cbcdc3ea | ||
|
|
dfd8d0fa3d | ||
|
|
7d7ca11c81 | ||
|
|
ee50a31bba | ||
|
|
179930ad80 | ||
|
|
fdb02da5ed | ||
|
|
5499beb510 | ||
|
|
96046d2ee2 | ||
|
|
a35a209066 | ||
|
|
8139c33b86 | ||
|
|
da40562ee3 | ||
|
|
ce478583ab | ||
|
|
6215af0e5a | ||
|
|
8f0ecac842 | ||
|
|
54dd562d88 | ||
|
|
c24f7a86d4 | ||
|
|
d6b4437664 | ||
|
|
68e74b9830 | ||
|
|
3fa40b2303 | ||
|
|
5feb73c65b | ||
|
|
33d676e1fe | ||
|
|
afb7af287b | ||
|
|
d6291a4c47 | ||
|
|
7228b84bf8 | ||
|
|
2dbf8ebb65 | ||
|
|
2d90844239 | ||
|
|
bf6e66ea47 | ||
|
|
5edaa6ec29 | ||
|
|
881ca67f80 | ||
|
|
1c0ed2a2c1 | ||
|
|
245d27ea71 | ||
|
|
f14d4b8ac3 | ||
|
|
fdc867b9d5 | ||
|
|
8e876d6a99 | ||
|
|
c9de0b4cf2 | ||
|
|
27b3a86155 | ||
|
|
683bdc838d | ||
|
|
4f9f10ddf2 | ||
|
|
6fe3f90a26 | ||
|
|
5bdb7eee85 | ||
|
|
34262a45ca | ||
|
|
7c22110c96 | ||
|
|
6ad9fb8f27 | ||
|
|
4348f4b0d4 | ||
|
|
22529e28d8 | ||
|
|
aa52bcee8c | ||
|
|
d731ab3682 | ||
|
|
7840438bfc | ||
|
|
455a2dba8a | ||
|
|
01c310c913 | ||
|
|
a679d6f2e1 | ||
|
|
e8af56bdbe | ||
|
|
efa099ac5b | ||
|
|
81181aa7e6 | ||
|
|
1ab6640983 | ||
|
|
e5636cde05 | ||
|
|
0a0d00b26e | ||
|
|
6c9afcff81 | ||
|
|
b7933b282b | ||
|
|
653c34758b | ||
|
|
9d18ab795e | ||
|
|
a5c06c67bc | ||
|
|
db2f790bf7 | ||
|
|
5cbc6b5f6a | ||
|
|
f7ecf40633 | ||
|
|
6cd83c60ef | ||
|
|
90ffce63e5 | ||
|
|
2910ebc0fd | ||
|
|
02fab95637 | ||
|
|
22d2209a1b | ||
|
|
e2bea81c64 | ||
|
|
466b8bd1cc | ||
|
|
c5287d2869 | ||
|
|
010502ed9d | ||
|
|
be06e74d94 | ||
|
|
199d2cf851 | ||
|
|
deab1b4962 | ||
|
|
d04411e4a8 | ||
|
|
ce52b57a52 | ||
|
|
c760c19056 | ||
|
|
6b5e469b19 | ||
|
|
8663489ae4 | ||
|
|
877ef1d7ed | ||
|
|
6a81035f10 | ||
|
|
1f7276bbfd | ||
|
|
90e8490a85 | ||
|
|
38d51988d9 | ||
|
|
b8fccd1bac | ||
|
|
ded8e7b916 | ||
|
|
f56ca6318a | ||
|
|
5bd6ba4f36 | ||
|
|
909fb2eb2b | ||
|
|
b2209eaad0 | ||
|
|
dcae3c4acb | ||
|
|
3a3a2ec76d | ||
|
|
5e2ba192c1 | ||
|
|
6d4452bf94 | ||
|
|
998f9491f6 | ||
|
|
fa7efeb283 | ||
|
|
22206b6a99 | ||
|
|
34036ee355 | ||
|
|
2eb2d555ad | ||
|
|
722abf9cab | ||
|
|
357d3b8140 | ||
|
|
01ef79ac33 | ||
|
|
8d2456f238 | ||
|
|
bb164edb55 | ||
|
|
21117eaa17 | ||
|
|
573f823f48 | ||
|
|
47ca3b5d33 | ||
|
|
7334134b45 | ||
|
|
e6be594395 | ||
|
|
e2b6697362 | ||
|
|
f78e11057d | ||
|
|
314ee96525 | ||
|
|
efc1223d45 | ||
|
|
38d9aa4997 | ||
|
|
42c7431416 | ||
|
|
d1e40ee71c | ||
|
|
43169d8bab | ||
|
|
8cbbb52b95 | ||
|
|
807a55fcdc | ||
|
|
8c5351445b | ||
|
|
999c630c5a | ||
|
|
a0186ce8e4 | ||
|
|
9fe336d564 | ||
|
|
34a1d4e6b9 | ||
|
|
bafa548f2f | ||
|
|
fa709a9bdc | ||
|
|
2a1cc7e3ea | ||
|
|
68648b9920 | ||
|
|
b9f297935b | ||
|
|
eb6fc4f8cf | ||
|
|
8a177c34fa | ||
|
|
22a5f411d0 | ||
|
|
f557609e9e | ||
|
|
cde8deaf4b | ||
|
|
48eb1c6d67 | ||
|
|
4db741a87c | ||
|
|
3188ca6884 | ||
|
|
bb9cd171bf | ||
|
|
7a81638258 | ||
|
|
6519db1fe8 | ||
|
|
f313d319d4 | ||
|
|
a8c4e6fedc | ||
|
|
db16458cf5 | ||
|
|
38a9562eaf | ||
|
|
b2327e8bf7 | ||
|
|
aafef107ec | ||
|
|
4b442e75f7 | ||
|
|
e8f103799b | ||
|
|
618685dc05 | ||
|
|
f0d50e53fa | ||
|
|
1b4828f4fa | ||
|
|
56730d67a2 | ||
|
|
b02516b0b3 | ||
|
|
1eb32f86bd | ||
|
|
3b669e64e2 | ||
|
|
fbccd70f7d | ||
|
|
61e5231d99 | ||
|
|
5c101c5a85 | ||
|
|
a6e991923e | ||
|
|
f0c494ecea | ||
|
|
40dfdf9bb1 | ||
|
|
770e0f01f1 | ||
|
|
8448d3e516 | ||
|
|
292a11f942 | ||
|
|
6099986f5b | ||
|
|
53d18d8947 | ||
|
|
f77bdd233b | ||
|
|
dc25a1294c | ||
|
|
8f4bffa950 | ||
|
|
96195fa16a | ||
|
|
4e8a59ad4e | ||
|
|
e42ee6d6be | ||
|
|
f6a04a8b36 | ||
|
|
36b94b81ce | ||
|
|
d66e782152 | ||
|
|
d122d39d3a | ||
|
|
7c3053e8cd | ||
|
|
ecdfa61755 | ||
|
|
7321117c99 | ||
|
|
b50560eadf | ||
|
|
60841e6312 | ||
|
|
66cc61f967 | ||
|
|
1933f4bcc8 | ||
|
|
977f5ca9ce | ||
|
|
e5e529d3d2 | ||
|
|
e1f9d6091c | ||
|
|
a83d8064f2 | ||
|
|
9afb5e7272 | ||
|
|
4c7c2ccc74 | ||
|
|
a6d5686c1c | ||
|
|
8fa1b92deb | ||
|
|
f06e3643b6 | ||
|
|
cd8e59bc9c | ||
|
|
b6eeeea1ea | ||
|
|
aea642fcde | ||
|
|
27bec7ad05 | ||
|
|
80cb3458de | ||
|
|
615048df04 | ||
|
|
4e07b56f3e | ||
|
|
7d18da13a1 | ||
|
|
a49e9e346f | ||
|
|
87fd267183 | ||
|
|
c61fefb55f | ||
|
|
c644031041 | ||
|
|
79f0f52825 | ||
|
|
03ac62044b | ||
|
|
531bc0f887 | ||
|
|
af8b60ca29 | ||
|
|
80c14e9ebd | ||
|
|
3d658eff29 | ||
|
|
8a8a75aa79 | ||
|
|
ea3fe06613 | ||
|
|
92e7f6bd68 | ||
|
|
96b22a00ff | ||
|
|
cfddbc5b3f | ||
|
|
725009d719 | ||
|
|
7f7370f6db | ||
|
|
0fcc1316b2 | ||
|
|
e9933bebe7 | ||
|
|
9810081b11 | ||
|
|
6522d252cb | ||
|
|
a2867cffb7 | ||
|
|
e92c1b53a1 | ||
|
|
52aecb47e7 | ||
|
|
c4652d39fa | ||
|
|
c7b155ccac | ||
|
|
96d18535f8 | ||
|
|
98471e39e1 | ||
|
|
f55fc5776e | ||
|
|
f9a8d1cc40 | ||
|
|
e55a210cf9 | ||
|
|
d19d4406f6 | ||
|
|
9697331abb | ||
|
|
91db02f2da | ||
|
|
b933b30e0a | ||
|
|
2cb9a7c199 | ||
|
|
06ff17ebb2 | ||
|
|
44a573ecd5 | ||
|
|
ffa7952fc1 | ||
|
|
701514a168 | ||
|
|
1565bc9e1a | ||
|
|
0681bad8e6 | ||
|
|
23a21bb39f | ||
|
|
9aabb575c1 | ||
|
|
cf607e892b | ||
|
|
6bf906f2a7 | ||
|
|
7e897d604c | ||
|
|
39887df3ec | ||
|
|
fbb7a684bf | ||
|
|
449ad6cd0d | ||
|
|
cfcd6e5f93 | ||
|
|
73aab88109 | ||
|
|
beb692a3c4 | ||
|
|
fe8385e759 | ||
|
|
58fb331019 | ||
|
|
e4986a6a47 | ||
|
|
fcd47ecec6 | ||
|
|
174e6ad637 | ||
|
|
2ac4097e32 | ||
|
|
dd13ac5cbb | ||
|
|
9c55a898f7 | ||
|
|
bb9018c094 | ||
|
|
b09b4183bb | ||
|
|
3d7bc6583d | ||
|
|
99e8be227e | ||
|
|
b1c38cc793 | ||
|
|
26e4e70fc8 | ||
|
|
04bdf3f26a | ||
|
|
cafeacf69f | ||
|
|
4c2d6d78ea | ||
|
|
ea7d0cdef5 | ||
|
|
47bae63548 | ||
|
|
8470f4f7fb | ||
|
|
242f9d55ed | ||
|
|
236ac52925 | ||
|
|
baab9a9c89 | ||
|
|
3d26e6e340 | ||
|
|
c34ab48972 | ||
|
|
cf0abf21db | ||
|
|
7918b392e8 | ||
|
|
f0ced15e6a | ||
|
|
c0204cb725 | ||
|
|
eb3905447f | ||
|
|
16c7459906 | ||
|
|
eae5f87eed | ||
|
|
d4b85e3b1c | ||
|
|
a989c3b7d0 | ||
|
|
d96ba9fa46 | ||
|
|
2261d655ea | ||
|
|
8b67049863 | ||
|
|
48258dd9dd | ||
|
|
e04c573726 | ||
|
|
4daec3794e | ||
|
|
f0646dde32 | ||
|
|
ec2086e0f7 | ||
|
|
2ac704178c | ||
|
|
7c43c38e28 | ||
|
|
043a8336e5 | ||
|
|
ee27535b82 | ||
|
|
89e6ae2475 | ||
|
|
e51615f520 | ||
|
|
6e59897587 | ||
|
|
bd0644a261 | ||
|
|
d7825e1bf8 | ||
|
|
97956b6c5e | ||
|
|
8150504ea0 | ||
|
|
942dec81c7 | ||
|
|
dcbc377c62 | ||
|
|
7b65233699 | ||
|
|
eabfd8b5c4 | ||
|
|
b7b2799611 | ||
|
|
ece59ac374 | ||
|
|
83cc8b772c | ||
|
|
8b5bc18142 | ||
|
|
e1413baa9a | ||
|
|
03640e6d37 | ||
|
|
2588011524 | ||
|
|
0c16a6804a | ||
|
|
e2021fdf5d | ||
|
|
33b5694d35 | ||
|
|
af7d04fef6 | ||
|
|
14e3419e4c | ||
|
|
f6c5252376 | ||
|
|
78ee77444f | ||
|
|
fb022970b5 | ||
|
|
e5d378dc93 | ||
|
|
5969902263 | ||
|
|
d5894de142 | ||
|
|
059c6baa4e | ||
|
|
bbf9331baf | ||
|
|
a5b084f506 | ||
|
|
3b5471b97c | ||
|
|
fae37fe67d | ||
|
|
1f975efda1 | ||
|
|
3b3b61f52c | ||
|
|
1c1f6e21c5 | ||
|
|
8b60c7cc09 | ||
|
|
d4f9752cd4 | ||
|
|
6332a37f5b | ||
|
|
840a583a0b | ||
|
|
e7ed80d3e0 | ||
|
|
c2b9376313 | ||
|
|
7a8b291189 | ||
|
|
e63f71d3a7 | ||
|
|
061c97caca | ||
|
|
988d28f2fd | ||
|
|
af8a0ea9c0 | ||
|
|
c78e8d8358 | ||
|
|
392f7098bc | ||
|
|
195f918543 | ||
|
|
b2579538fa | ||
|
|
35b97c4f45 | ||
|
|
adaa89a963 | ||
|
|
fc1429fae5 | ||
|
|
4090f95098 | ||
|
|
3189d8d43e | ||
|
|
cd6d10e428 | ||
|
|
7d37236d78 | ||
|
|
7c127acf17 | ||
|
|
0a4ce2350a | ||
|
|
181a70cb1f | ||
|
|
7438545a16 | ||
|
|
9e902a5dd4 | ||
|
|
91e395884f | ||
|
|
7107c68a41 | ||
|
|
86728b79e3 | ||
|
|
e04f901590 | ||
|
|
47ad2b5cfa | ||
|
|
cea0f1766f | ||
|
|
407e57d334 | ||
|
|
c4e66d0c9c | ||
|
|
c54f1ca9b0 | ||
|
|
f9fdc36d0d | ||
|
|
6d546094ef | ||
|
|
8dc5ae4f86 | ||
|
|
fd7b81af10 | ||
|
|
3abd859664 | ||
|
|
6134ce39d4 | ||
|
|
8ea42ea432 | ||
|
|
fd4ff00ee2 | ||
|
|
9d981b09ca | ||
|
|
ed807e0fe5 | ||
|
|
32b962b036 | ||
|
|
8ac476b6bd | ||
|
|
9ab8b84d81 | ||
|
|
05cc4b4bd1 | ||
|
|
b28cf30f47 | ||
|
|
5bf8b0a2b6 | ||
|
|
d2891a49fc | ||
|
|
bec8ba6c2f | ||
|
|
9e097be657 | ||
|
|
b008f55847 | ||
|
|
487d90f260 | ||
|
|
671a745acc | ||
|
|
80880f4d2a | ||
|
|
109fba828b | ||
|
|
0a845fdfa6 | ||
|
|
5a5b8464fc | ||
|
|
86d0b92a66 | ||
|
|
9f75234dac | ||
|
|
a58b129503 | ||
|
|
6d752acb28 | ||
|
|
4486582006 | ||
|
|
ed027fd3ce | ||
|
|
a92cb848c0 | ||
|
|
e573e36aa6 | ||
|
|
fc61753953 | ||
|
|
9b74e19a99 | ||
|
|
e9e39cb985 | ||
|
|
d938f2ea50 | ||
|
|
6c3535951f | ||
|
|
cee78b4ae3 | ||
|
|
1ee646e1ce | ||
|
|
6199dec82f | ||
|
|
59f307bdb3 | ||
|
|
24747355ce | ||
|
|
3d287a2827 | ||
|
|
def28df4dd | ||
|
|
d90e698a15 | ||
|
|
f4d6f88e5c | ||
|
|
799dce4b13 | ||
|
|
a025d028d4 | ||
|
|
8cfa9a891d | ||
|
|
5b44439dd2 | ||
|
|
44fb7dcdaa | ||
|
|
4f5d1ba26b | ||
|
|
0a08b09d70 | ||
|
|
35eedda352 | ||
|
|
05fb8bc742 | ||
|
|
795df2937e | ||
|
|
5607740e77 | ||
|
|
d4287d3046 | ||
|
|
71ef72bae3 | ||
|
|
c310d698ca | ||
|
|
13ce3d1c92 | ||
|
|
122ed79a98 | ||
|
|
6d655242a6 | ||
|
|
09cab9d825 | ||
|
|
d8bd38c124 | ||
|
|
abc8bf0e62 | ||
|
|
24106ac3d2 | ||
|
|
bf506d382f | ||
|
|
84b1a9bbec | ||
|
|
d67afd4396 | ||
|
|
9f2f7eff5b | ||
|
|
c863d5976b | ||
|
|
d6338e9daf | ||
|
|
b393d2666d | ||
|
|
c5b1e73312 | ||
|
|
fa65222228 | ||
|
|
38e57ccd71 | ||
|
|
86d3d26273 | ||
|
|
db8e4a03a8 | ||
|
|
c90db8594a | ||
|
|
855ca77194 | ||
|
|
4f23af070e | ||
|
|
626613b545 | ||
|
|
c26de3bd67 | ||
|
|
c059915bd3 | ||
|
|
d2d70dcb38 | ||
|
|
846292442c | ||
|
|
11283a2199 | ||
|
|
4c8a0b9a63 | ||
|
|
54accbf21f | ||
|
|
08dc0db2e2 | ||
|
|
38c6330a2a | ||
|
|
2f983f42fe | ||
|
|
b9e45c4bb0 | ||
|
|
9d3b1d75d1 | ||
|
|
ac78ddcc82 | ||
|
|
f912d84ab6 | ||
|
|
85548d6e8e | ||
|
|
c74de12ceb | ||
|
|
017a21c17f | ||
|
|
9a63038a5f | ||
|
|
304fc2536b | ||
|
|
365169a9fb | ||
|
|
4b82ead18b | ||
|
|
141d7cc268 | ||
|
|
ee8e94cfb0 | ||
|
|
b50bedef39 | ||
|
|
a689ce4de9 | ||
|
|
ae0478a7e9 | ||
|
|
ee6eed5ac5 | ||
|
|
9140c426c4 | ||
|
|
a41bfabede | ||
|
|
5d26357025 | ||
|
|
644c10e994 | ||
|
|
b3ca0beead | ||
|
|
93300c6821 | ||
|
|
2bd8d7ee32 | ||
|
|
95c339ef74 | ||
|
|
76ad1d5ef7 | ||
|
|
151e82a2c3 | ||
|
|
3fcaf93788 | ||
|
|
b8927d66e9 | ||
|
|
9273f364fc | ||
|
|
bc42dbf88a | ||
|
|
481d4c15d6 | ||
|
|
563030e732 | ||
|
|
4f9137d009 | ||
|
|
ed1b4d1885 | ||
|
|
6bbcd9020e | ||
|
|
0ba916a7d6 | ||
|
|
cf498462eb | ||
|
|
e8b8b861a4 | ||
|
|
4afb045234 | ||
|
|
ef5c876085 | ||
|
|
7fbcfeec9c | ||
|
|
2981a8ef83 | ||
|
|
b1e8bfe2ab | ||
|
|
623d568eb9 | ||
|
|
3625834be3 | ||
|
|
925a4f4a57 | ||
|
|
0729b21e67 | ||
|
|
393d37a8c6 | ||
|
|
c1454e4414 | ||
|
|
282c48ec63 | ||
|
|
c02a5d7f19 | ||
|
|
8a06230aab | ||
|
|
d01d6f8fd6 | ||
|
|
fdf6cc9912 | ||
|
|
00a93233ad | ||
|
|
30dcf40e48 |
12
.github/FUNDING.yml
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
# These are supported funding model platforms
|
||||
|
||||
github: [pascallanger]
|
||||
patreon: # Replace with a single Patreon username
|
||||
open_collective: # Replace with a single Open Collective username
|
||||
ko_fi: # Replace with a single Ko-fi username
|
||||
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
|
||||
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
|
||||
liberapay: # Replace with a single Liberapay username
|
||||
issuehunt: # Replace with a single IssueHunt username
|
||||
otechie: # Replace with a single Otechie username
|
||||
custom: https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=VF2K9T23DRY56&lc=US&item_name=DIY%20Multiprotocol¤cy_code=EUR&bn=PP%2dDonationsBF%3abtn_donate_SM%2egif%3aNonHosted
|
||||
214
.github/workflows/main.yml
vendored
Normal file
@@ -0,0 +1,214 @@
|
||||
# Workflow for testing MULTI-Module firmware builds
|
||||
|
||||
name: CI
|
||||
|
||||
on:
|
||||
# Trigger the workflow on pushes, except those that are tagged (avoids double-testing releases)
|
||||
push:
|
||||
branches:
|
||||
- '**'
|
||||
tags-ignore:
|
||||
- '**'
|
||||
paths:
|
||||
- '.github/workflows/**'
|
||||
- 'buildroot/bin/**'
|
||||
- 'Multiprotocol/**'
|
||||
|
||||
# Trigger the workflow on pull requests to the master branch
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
paths:
|
||||
- '.github/workflows/**'
|
||||
- 'buildroot/bin/**'
|
||||
- 'Multiprotocol/**'
|
||||
|
||||
# Triggers the workflow on release creation
|
||||
release:
|
||||
types:
|
||||
- created
|
||||
|
||||
# Allows the workflow to be triggered manually from the Actions tab
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
# Configure the board matrix
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- board: "multi4in1:avr:multiatmega328p:bootloader=none"
|
||||
name: "ATmega328p"
|
||||
- board: "multi4in1:avr:multiatmega328p:bootloader=optiboot"
|
||||
name: "ATmega328p (Optiboot)"
|
||||
- board: "multi4in1:avr:multixmega32d4"
|
||||
name: "OrangeRX"
|
||||
- board: "multi4in1:STM32F1:multistm32f103c8:debug_option=none"
|
||||
name: "STM32F103 (64KB)"
|
||||
- board: "multi4in1:STM32F1:multistm32f103cb:debug_option=none"
|
||||
name: "STM32F103 (128KB)"
|
||||
- board: "multi4in1:STM32F1:multistm32f103cb:debug_option=native"
|
||||
name: "STM32F103 (128KB, USB Debugging)"
|
||||
- board: "multi4in1:STM32F1:multistm32f103cb:debug_option=ftdi"
|
||||
name: "STM32F103 (128KB, Serial Debugging)"
|
||||
- board: "multi4in1:STM32F1:multi5in1t18int"
|
||||
name: "T18 5-in-1 (128KB)"
|
||||
|
||||
# Set the build name using the friendly board name
|
||||
name: ${{ matrix.name }}
|
||||
|
||||
# Set the environment variables
|
||||
env:
|
||||
BOARD: ${{ matrix.board }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Install Arduino CLI
|
||||
uses: arduino/setup-arduino-cli@v1.1.2
|
||||
with:
|
||||
version: "0.32.2"
|
||||
|
||||
- name: Prepare build environment
|
||||
run: |
|
||||
echo "Github Ref: $GITHUB_REF"
|
||||
echo "Event name: ${{ github.event_name }}"
|
||||
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,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" =~ ":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-devel:STM32F1:" ]]; then
|
||||
arduino-cli core install multi4in1-devel:STM32F1
|
||||
elif [[ "$BOARD" =~ "multi4in1:STM32F1:" ]]; then
|
||||
arduino-cli core install multi4in1:STM32F1
|
||||
fi
|
||||
|
||||
chmod +x ${GITHUB_WORKSPACE}/buildroot/bin/*
|
||||
echo "${GITHUB_WORKSPACE}/buildroot/bin" >> $GITHUB_PATH
|
||||
|
||||
mkdir ./build
|
||||
mkdir ./binaries
|
||||
|
||||
- name: Configure MULTI-Module firmware options
|
||||
run: |
|
||||
# Load the build functions
|
||||
source ./buildroot/bin/buildFunctions;
|
||||
|
||||
# Get the version
|
||||
getMultiVersion
|
||||
echo "MULTI_VERSION=$(echo $MULTI_VERSION)" >> $GITHUB_ENV
|
||||
|
||||
# Get all the protocols for this board
|
||||
getAllProtocols
|
||||
echo "A7105_PROTOCOLS=$(echo $A7105_PROTOCOLS)" >> $GITHUB_ENV
|
||||
echo "CC2500_PROTOCOLS=$(echo $CC2500_PROTOCOLS)" >> $GITHUB_ENV
|
||||
echo "CYRF6936_PROTOCOLS=$(echo $CYRF6936_PROTOCOLS)" >> $GITHUB_ENV
|
||||
echo "NRF24L01_PROTOCOLS=$(echo $NRF24L01_PROTOCOLS)" >> $GITHUB_ENV
|
||||
echo "SX1276_PROTOCOLS=$(echo $SX1276_PROTOCOLS)" >> $GITHUB_ENV
|
||||
echo "CCNRF_INO_PROTOCOLS=$(echo $CCNRF_INO_PROTOCOLS)" >> $GITHUB_ENV
|
||||
echo "ALL_PROTOCOLS=$(echo $ALL_PROTOCOLS)" >> $GITHUB_ENV
|
||||
|
||||
# Get all the RF modules for this board
|
||||
getAllRFModules
|
||||
echo "ALL_RFMODULES=$(echo $ALL_RFMODULES)" >> $GITHUB_ENV
|
||||
|
||||
# Disable CHECK_FOR_BOOTLOADER when not needed
|
||||
if [[ "$BOARD" =~ ":avr:multiatmega328p:bootloader=none" ]]; then
|
||||
opt_disable CHECK_FOR_BOOTLOADER;
|
||||
fi
|
||||
|
||||
# Trim the build down for the Atmega328p board
|
||||
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" =~ ":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
|
||||
|
||||
- name: Save default firmware configuration
|
||||
run: |
|
||||
cat Multiprotocol/_Config.h
|
||||
cp Multiprotocol/_Config.h ./_Config.h.bak
|
||||
|
||||
- name: Build default configuration
|
||||
run: |
|
||||
# Skip the default build for boards where it's too large now
|
||||
if [[ "$BOARD" =~ ":STM32F1:multistm32f103cb:debug_option=none" ]] || [[ "$BOARD" =~ ":STM32F1:multi5in1t18int" ]]; then
|
||||
printf "Not testing default build for $BOARD.";
|
||||
else
|
||||
source ./buildroot/bin/buildFunctions;
|
||||
buildMulti
|
||||
fi
|
||||
|
||||
- name: Build serial only
|
||||
run: |
|
||||
source ./buildroot/bin/buildFunctions;
|
||||
cp ./_Config.h.bak Multiprotocol/_Config.h
|
||||
opt_disable ENABLE_PPM;
|
||||
buildMulti;
|
||||
|
||||
- name: Build PPM only
|
||||
run: |
|
||||
source ./buildroot/bin/buildFunctions;
|
||||
cp ./_Config.h.bak Multiprotocol/_Config.h
|
||||
opt_disable ENABLE_SERIAL;
|
||||
buildMulti;
|
||||
|
||||
- name: Build each RF module individually
|
||||
run: |
|
||||
source ./buildroot/bin/buildFunctions;
|
||||
cp ./_Config.h.bak Multiprotocol/_Config.h;
|
||||
buildEachRFModule;
|
||||
|
||||
- name: Build each protocol individually
|
||||
run: |
|
||||
source ./buildroot/bin/buildFunctions;
|
||||
cp ./_Config.h.bak Multiprotocol/_Config.h;
|
||||
buildEachProtocol;
|
||||
|
||||
- name: Build release files
|
||||
run: |
|
||||
source ./buildroot/bin/buildFunctions;
|
||||
cp ./_Config.h.bak Multiprotocol/_Config.h;
|
||||
buildReleaseFiles;
|
||||
ls -al ./binaries;
|
||||
|
||||
NUM_FILES=$(ls -l ./binaries | grep ^- | wc -l);
|
||||
if [ $NUM_FILES -gt 0 ]; then
|
||||
echo "HAVE_FILES=true" >> $GITHUB_ENV
|
||||
else
|
||||
echo "HAVE_FILES=false" >> $GITHUB_ENV
|
||||
fi
|
||||
|
||||
- name: Deploy files to release
|
||||
if: github.event_name == 'release' && github.event.action == 'created' && env.HAVE_FILES == 'true'
|
||||
uses: AButler/upload-release-assets@v2.0
|
||||
with:
|
||||
files: './binaries/*'
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: 'Upload Artifacts'
|
||||
if: env.HAVE_FILES == 'true'
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: multi-test-build
|
||||
path: ./binaries/
|
||||
@@ -1,16 +0,0 @@
|
||||
# DIY-Multiprotocol-TX-Module - Latest binaries version
|
||||
|
||||
##Multiprotocol using the latest provided source files
|
||||
**Multiprotocol_16ch_%date%.hex** -> build using the unmodified available source files
|
||||
|
||||
##ER9X using the latest available next branch
|
||||
**er9x_next_9X_NOFRSKY_16ch_%date%.hex** -> 9X without telemetry using these parameters: TEMPLATES=NO PHASES=YES
|
||||
|
||||
**er9x_next_9X_FRSKY_16ch_%date%.hex** -> 9X with telemetry using these parameters: EXT=FRSKY TEMPLATES=NO PHASES=YES
|
||||
|
||||
**er9x_next_9XR_16ch_%date%.hex** -> 9XR using these parameters: CPU=128 EXT=FRSKY PHASES=YES
|
||||
|
||||
##ERSKY9X using the latest available next branch
|
||||
**ersky9xr_next_9XRPRO_16ch_%date%.bin** -> 9XR PRO using these parameters: REVB=1 DEBUG=1 STAMP=1 PHASES=1 REVX=1
|
||||
|
||||
**ersky9x9XT_next_9XTREME_16ch_%date%.bin** -> 9XTREME using these parameters: PCB=9XT DEBUG=1 STAMP=1
|
||||
2
BootLoaders/AtmegaEmptyBoot/AtmegaMultiEmpty.hex
Normal file
@@ -0,0 +1,2 @@
|
||||
:02000000FFFF00
|
||||
:00000001FF
|
||||
34
BootLoaders/AtmegaMultiBoot/AtmegaMultiBoot.hex
Normal file
@@ -0,0 +1,34 @@
|
||||
:107E0000112484B714BE9FEF9BB99CE395B991E010
|
||||
:107E100098B98370A9F08AEF80938500109284004E
|
||||
:107E200085E08093810096BBB09BFECF10928100CD
|
||||
:107E300093B186B181709C73892B8D3109F0B3D0D9
|
||||
:107E400082E08093C00088E18093C10086E0809347
|
||||
:107E5000C20081E28093C400259AC0E0D0E093E0A4
|
||||
:107E6000F92EEE24E39425E0D22E31E1C32EA9D0E1
|
||||
:107E7000813481F4A6D08EBBABD08EB3823811F49E
|
||||
:107E800085E006C08EB3813811F484E001C083E040
|
||||
:107E900091D086C0823411F484E103C0853419F492
|
||||
:107EA00085E09DD07DC0853541F48BD0C82F89D029
|
||||
:107EB000D0E0D82BCC0FDD1F72C0863521F484E0D2
|
||||
:107EC0008ED080E0E5CF843609F03DC07AD079D0FD
|
||||
:107ED000B82E77D0C11520E7D20718F000E011E0E6
|
||||
:107EE00004C0FE01F7BEE895F9CF6BD0F80181938D
|
||||
:107EF0008F01BE12FACFCE01905781159E4018F423
|
||||
:107F0000FE01F7BEE89564D0C115FEE7DF0708F073
|
||||
:107F100047C007B600FCFDCFFE01A0E0B1E08D91A7
|
||||
:107F20009D910C01E7BEE89511243296A03821E01E
|
||||
:107F3000B207A9F7FE01D7BEE89507B600FCFDCF52
|
||||
:107F4000C7BEE8952DC08437B1F43BD03AD0B82EE7
|
||||
:107F500038D03ED0FE01AC2EAB0C8F010F5F1F4F0F
|
||||
:107F6000849128D0A01205C02196BA94CB0DD11DC2
|
||||
:107F700017C0F801F2CF853739F42AD08EE11AD034
|
||||
:107F800085E918D08FE084CF813549F421D080E194
|
||||
:107F900011D08091C00086FFFCCF05D001C018D061
|
||||
:107FA00080E108D064CFE0E0F0E084918F3F09F0F9
|
||||
:107FB000099408959091C00095FFFCCF8093C6006E
|
||||
:107FC00008958091C00087FFFCCF8091C60008957E
|
||||
:107FD000F8DF803211F085E1EDDF84E1EBCFCF9364
|
||||
:107FE000C82FEFDFC150E9F7CF91F2CFA8950895E0
|
||||
:0C7FF000E0E6F0E098E1908380830895C3
|
||||
:0400000300007E007B
|
||||
:00000001FF
|
||||
504
BootLoaders/AtmegaMultiBoot/Source/Makefile
Normal file
@@ -0,0 +1,504 @@
|
||||
# Makefile for ATmegaBOOT
|
||||
# E.Lins, 18.7.2005
|
||||
# $Id$
|
||||
#
|
||||
# Instructions
|
||||
#
|
||||
# To make bootloader .hex file:
|
||||
# make diecimila
|
||||
# make lilypad
|
||||
# make ng
|
||||
# etc...
|
||||
#
|
||||
# To burn bootloader .hex file:
|
||||
# make diecimila_isp
|
||||
# make lilypad_isp
|
||||
# make ng_isp
|
||||
# etc...
|
||||
|
||||
# program name should not be changed...
|
||||
PROGRAM = optiboot
|
||||
|
||||
# The default behavior is to build using tools that are in the users
|
||||
# current path variables, but we can also build using an installed
|
||||
# Arduino user IDE setup, or the Arduino source tree.
|
||||
# Uncomment this next lines to build within the arduino environment,
|
||||
# using the arduino-included avrgcc toolset (mac and pc)
|
||||
# ENV ?= arduino
|
||||
# ENV ?= arduinodev
|
||||
# OS ?= macosx
|
||||
# OS ?= windows
|
||||
|
||||
|
||||
# enter the parameters for the avrdude isp tool -b19200
|
||||
#
|
||||
# These are the parameters for a usb-based STK500v2 programmer.
|
||||
# Exact type unknown. (historical Makefile values.)
|
||||
ISPTOOL = stk500v2
|
||||
ISPPORT = usb
|
||||
ISPSPEED = -b 57600
|
||||
#
|
||||
#
|
||||
# These are parameters for using an Arduino with the ArduinoISP sketch
|
||||
# as the programmer. On a mac, for a particular Uno as programmer.
|
||||
#ISPTOOL = stk500v1 -C /Applications/arduino/arduino-0022/hardware/tools/avr/etc/avrdude.conf
|
||||
#ISPPORT = /dev/tty.usbmodemfd3141
|
||||
#ISPSPEED = -b19200
|
||||
|
||||
MCU_TARGET = atmega168
|
||||
LDSECTIONS = -Wl,--section-start=.text=0x3e00 -Wl,--section-start=.version=0x3ffe
|
||||
|
||||
# Build environments
|
||||
# Start of some ugly makefile-isms to allow optiboot to be built
|
||||
# in several different environments. See the README.TXT file for
|
||||
# details.
|
||||
|
||||
# default
|
||||
fixpath = $(1)
|
||||
|
||||
ifeq ($(ENV), arduino)
|
||||
# For Arduino, we assume that we're connected to the optiboot directory
|
||||
# included with the arduino distribution, which means that the full set
|
||||
# of avr-tools are "right up there" in standard places.
|
||||
TOOLROOT = ../../../tools
|
||||
GCCROOT = $(TOOLROOT)/avr/bin/
|
||||
AVRDUDE_CONF = -C$(TOOLROOT)/avr/etc/avrdude.conf
|
||||
|
||||
ifeq ($(OS), windows)
|
||||
# On windows, SOME of the tool paths will need to have backslashes instead
|
||||
# of forward slashes (because they use windows cmd.exe for execution instead
|
||||
# of a unix/mingw shell?) We also have to ensure that a consistent shell
|
||||
# is used even if a unix shell is installed (ie as part of WINAVR)
|
||||
fixpath = $(subst /,\,$1)
|
||||
SHELL = cmd.exe
|
||||
endif
|
||||
|
||||
else ifeq ($(ENV), arduinodev)
|
||||
# Arduino IDE source code environment. Use the unpacked compilers created
|
||||
# by the build (you'll need to do "ant build" first.)
|
||||
ifeq ($(OS), macosx)
|
||||
TOOLROOT = ../../../../build/macosx/work/Arduino.app/Contents/Resources/Java/hardware/tools
|
||||
endif
|
||||
ifeq ($(OS), windows)
|
||||
TOOLROOT = ../../../../build/windows/work/hardware/tools
|
||||
endif
|
||||
|
||||
GCCROOT = $(TOOLROOT)/avr/bin/
|
||||
AVRDUDE_CONF = -C$(TOOLROOT)/avr/etc/avrdude.conf
|
||||
|
||||
else
|
||||
GCCROOT =
|
||||
AVRDUDE_CONF =
|
||||
endif
|
||||
#
|
||||
# End of build environment code.
|
||||
|
||||
|
||||
# the efuse should really be 0xf8; since, however, only the lower
|
||||
# three bits of that byte are used on the atmega168, avrdude gets
|
||||
# confused if you specify 1's for the higher bits, see:
|
||||
# http://tinker.it/now/2007/02/24/the-tale-of-avrdude-atmega168-and-extended-bits-fuses/
|
||||
#
|
||||
# similarly, the lock bits should be 0xff instead of 0x3f (to
|
||||
# unlock the bootloader section) and 0xcf instead of 0x2f (to
|
||||
# lock it), but since the high two bits of the lock byte are
|
||||
# unused, avrdude would get confused.
|
||||
|
||||
ISPFUSES = $(GCCROOT)avrdude $(AVRDUDE_CONF) -c $(ISPTOOL) \
|
||||
-p $(MCU_TARGET) -P $(ISPPORT) $(ISPSPEED) \
|
||||
-e -u -U lock:w:0x3f:m -U efuse:w:0x$(EFUSE):m \
|
||||
-U hfuse:w:0x$(HFUSE):m -U lfuse:w:0x$(LFUSE):m
|
||||
ISPFLASH = $(GCCROOT)avrdude $(AVRDUDE_CONF) -c $(ISPTOOL) \
|
||||
-p $(MCU_TARGET) -P $(ISPPORT) $(ISPSPEED) \
|
||||
-U flash:w:$(PROGRAM)_$(TARGET).hex -U lock:w:0x2f:m
|
||||
|
||||
STK500 = "C:\Program Files\Atmel\AVR Tools\STK500\Stk500.exe"
|
||||
STK500-1 = $(STK500) -e -d$(MCU_TARGET) -pf -vf -if$(PROGRAM)_$(TARGET).hex \
|
||||
-lFF -LFF -f$(HFUSE)$(LFUSE) -EF8 -ms -q -cUSB -I200kHz -s -wt
|
||||
STK500-2 = $(STK500) -d$(MCU_TARGET) -ms -q -lCF -LCF -cUSB -I200kHz -s -wt
|
||||
|
||||
OBJ = $(PROGRAM).o
|
||||
OPTIMIZE = -Os -fno-inline-small-functions -fno-split-wide-types
|
||||
# -mshort-calls
|
||||
|
||||
DEFS =
|
||||
LIBS =
|
||||
|
||||
CC = $(GCCROOT)avr-gcc
|
||||
|
||||
# Override is only needed by avr-lib build system.
|
||||
|
||||
override CFLAGS = -g -Wall $(OPTIMIZE) -mmcu=$(MCU_TARGET) -DF_CPU=$(AVR_FREQ) $(DEFS)
|
||||
override LDFLAGS = $(LDSECTIONS) -Wl,--relax -Wl,--gc-sections -nostartfiles -nostdlib
|
||||
|
||||
OBJCOPY = $(GCCROOT)avr-objcopy
|
||||
OBJDUMP = $(call fixpath,$(GCCROOT)avr-objdump)
|
||||
|
||||
SIZE = $(GCCROOT)avr-size
|
||||
|
||||
|
||||
|
||||
#Voice board test
|
||||
# ATmega328
|
||||
#
|
||||
#atmega328: TARGET = atmega328p
|
||||
#atmega328: MCU_TARGET = atmega328p
|
||||
#atmega328: CFLAGS += '-DLED_START_FLASHES=0' '-DBAUD_RATE=38400'
|
||||
#atmega328: AVR_FREQ = 12000000L
|
||||
#atmega328: LDSECTIONS = -Wl,--section-start=.text=0x7e00 -Wl,--section-start=.version=0x7ffe
|
||||
#atmega328: $(PROGRAM)_atmega328.hex
|
||||
#atmega328: $(PROGRAM)_atmega328.lst
|
||||
|
||||
atmega328: TARGET = atmega328
|
||||
atmega328: MCU_TARGET = atmega328p
|
||||
atmega328: CFLAGS += '-DLED_START_FLASHES=0' '-DBAUD_RATE=57600'
|
||||
atmega328: AVR_FREQ = 16000000L
|
||||
atmega328: LDSECTIONS = -Wl,--section-start=.text=0x7e00 -Wl,--section-start=.version=0x7ffe
|
||||
atmega328: $(PROGRAM)_atmega328_16.hex
|
||||
atmega328: $(PROGRAM)_atmega328_16.lst
|
||||
|
||||
|
||||
xmega32D4: TARGET = atxmega32d4
|
||||
xmega32D4: MCU_TARGET = atxmega32d4
|
||||
xmega32D4: CFLAGS += '-DLED_START_FLASHES=0' '-DBAUD_RATE=57600'
|
||||
xmega32D4: AVR_FREQ = 32000000L
|
||||
xmega32D4: LDSECTIONS = -Wl,--section-start=.text=0x8000
|
||||
xmega32D4: $(PROGRAM)_xmega32d4.hex
|
||||
xmega32D4: $(PROGRAM)_xmega32d4.lst
|
||||
|
||||
|
||||
# Test platforms
|
||||
# Virtual boot block test
|
||||
virboot328: TARGET = atmega328
|
||||
virboot328: MCU_TARGET = atmega328p
|
||||
virboot328: CFLAGS += '-DLED_START_FLASHES=3' '-DBAUD_RATE=38400' '-DVIRTUAL_BOOT'
|
||||
virboot328: AVR_FREQ = 16000000L
|
||||
virboot328: LDSECTIONS = -Wl,--section-start=.text=0x7e00 -Wl,--section-start=.version=0x7ffe
|
||||
virboot328: $(PROGRAM)_atmega328.hex
|
||||
virboot328: $(PROGRAM)_atmega328.lst
|
||||
|
||||
# 20MHz clocked platforms
|
||||
#
|
||||
# These are capable of 230400 baud, or 38400 baud on PC (Arduino Avrdude issue)
|
||||
#
|
||||
|
||||
pro20: TARGET = pro_20mhz
|
||||
pro20: MCU_TARGET = atmega168
|
||||
pro20: CFLAGS += '-DLED_START_FLASHES=3' '-DBAUD_RATE=38400'
|
||||
pro20: AVR_FREQ = 20000000L
|
||||
pro20: $(PROGRAM)_pro_20mhz.hex
|
||||
pro20: $(PROGRAM)_pro_20mhz.lst
|
||||
|
||||
pro20_isp: pro20
|
||||
pro20_isp: TARGET = pro_20mhz
|
||||
# 2.7V brownout
|
||||
pro20_isp: HFUSE = DD
|
||||
# Full swing xtal (20MHz) 258CK/14CK+4.1ms
|
||||
pro20_isp: LFUSE = C6
|
||||
# 512 byte boot
|
||||
pro20_isp: EFUSE = 04
|
||||
pro20_isp: isp
|
||||
|
||||
# 16MHz clocked platforms
|
||||
#
|
||||
# These are capable of 230400 baud, or 38400 baud on PC (Arduino Avrdude issue)
|
||||
#
|
||||
|
||||
pro16: TARGET = pro_16MHz
|
||||
pro16: MCU_TARGET = atmega168
|
||||
pro16: CFLAGS += '-DLED_START_FLASHES=3' '-DBAUD_RATE=38400'
|
||||
pro16: AVR_FREQ = 16000000L
|
||||
pro16: $(PROGRAM)_pro_16MHz.hex
|
||||
pro16: $(PROGRAM)_pro_16MHz.lst
|
||||
|
||||
pro16_isp: pro16
|
||||
pro16_isp: TARGET = pro_16MHz
|
||||
# 2.7V brownout
|
||||
pro16_isp: HFUSE = DD
|
||||
# Full swing xtal (20MHz) 258CK/14CK+4.1ms
|
||||
pro16_isp: LFUSE = C6
|
||||
# 512 byte boot
|
||||
pro16_isp: EFUSE = 04
|
||||
pro16_isp: isp
|
||||
|
||||
# Diecimila, Duemilanove with m168, and NG use identical bootloaders
|
||||
# Call it "atmega168" for generality and clarity, keep "diecimila" for
|
||||
# backward compatibility of makefile
|
||||
#
|
||||
atmega168: TARGET = atmega168
|
||||
atmega168: MCU_TARGET = atmega168
|
||||
atmega168: CFLAGS += '-DLED_START_FLASHES=0' '-DBAUD_RATE=38400'
|
||||
atmega168: AVR_FREQ = 12000000L
|
||||
atmega168: $(PROGRAM)_atmega168.hex
|
||||
atmega168: $(PROGRAM)_atmega168.lst
|
||||
|
||||
atmega168_isp: atmega168
|
||||
atmega168_isp: TARGET = atmega168
|
||||
# 2.7V brownout
|
||||
atmega168_isp: HFUSE = DD
|
||||
# Low power xtal (16MHz) 16KCK/14CK+65ms
|
||||
atmega168_isp: LFUSE = FF
|
||||
# 512 byte boot
|
||||
atmega168_isp: EFUSE = 04
|
||||
atmega168_isp: isp
|
||||
|
||||
diecimila: TARGET = diecimila
|
||||
diecimila: MCU_TARGET = atmega168
|
||||
diecimila: CFLAGS += '-DLED_START_FLASHES=3' '-DBAUD_RATE=38400'
|
||||
diecimila: AVR_FREQ = 16000000L
|
||||
diecimila: $(PROGRAM)_diecimila.hex
|
||||
diecimila: $(PROGRAM)_diecimila.lst
|
||||
|
||||
diecimila_isp: diecimila
|
||||
diecimila_isp: TARGET = diecimila
|
||||
# 2.7V brownout
|
||||
diecimila_isp: HFUSE = DD
|
||||
# Low power xtal (16MHz) 16KCK/14CK+65ms
|
||||
diecimila_isp: LFUSE = FF
|
||||
# 512 byte boot
|
||||
diecimila_isp: EFUSE = 04
|
||||
diecimila_isp: isp
|
||||
|
||||
atmega328_isp: atmega328
|
||||
atmega328_isp: TARGET = atmega328
|
||||
atmega328_isp: MCU_TARGET = atmega328p
|
||||
# 512 byte boot, SPIEN
|
||||
atmega328_isp: HFUSE = DE
|
||||
# Low power xtal (16MHz) 16KCK/14CK+65ms
|
||||
atmega328_isp: LFUSE = FF
|
||||
# 2.7V brownout
|
||||
atmega328_isp: EFUSE = FD
|
||||
atmega328_isp: isp
|
||||
|
||||
atmega1284: TARGET = atmega1284p
|
||||
atmega1284: MCU_TARGET = atmega1284p
|
||||
atmega1284: CFLAGS += '-DLED_START_FLASHES=3' '-DBAUD_RATE=38400' '-DBIGBOOT'
|
||||
atmega1284: AVR_FREQ = 16000000L
|
||||
atmega1284: LDSECTIONS = -Wl,--section-start=.text=0x1fc00 -Wl,--section-start=.version=0x1fffe
|
||||
atmega1284: $(PROGRAM)_atmega1284p.hex
|
||||
atmega1284: $(PROGRAM)_atmega1284p.lst
|
||||
|
||||
atmega1284_isp: atmega1284
|
||||
atmega1284_isp: TARGET = atmega1284p
|
||||
atmega1284_isp: MCU_TARGET = atmega1284p
|
||||
# 1024 byte boot
|
||||
atmega1284_isp: HFUSE = DE
|
||||
# Low power xtal (16MHz) 16KCK/14CK+65ms
|
||||
atmega1284_isp: LFUSE = FF
|
||||
# 2.7V brownout
|
||||
atmega1284_isp: EFUSE = FD
|
||||
atmega1284_isp: isp
|
||||
|
||||
# Sanguino has a minimum boot size of 1024 bytes, so enable extra functions
|
||||
#
|
||||
sanguino: TARGET = atmega644p
|
||||
sanguino: MCU_TARGET = atmega644p
|
||||
sanguino: CFLAGS += '-DLED_START_FLASHES=3' '-DBAUD_RATE=38400' '-DBIGBOOT'
|
||||
sanguino: AVR_FREQ = 16000000L
|
||||
sanguino: LDSECTIONS = -Wl,--section-start=.text=0xfc00 -Wl,--section-start=.version=0xfffe
|
||||
sanguino: $(PROGRAM)_atmega644p.hex
|
||||
sanguino: $(PROGRAM)_atmega644p.lst
|
||||
|
||||
sanguino_isp: sanguino
|
||||
sanguino_isp: TARGET = atmega644p
|
||||
sanguino_isp: MCU_TARGET = atmega644p
|
||||
# 1024 byte boot
|
||||
sanguino_isp: HFUSE = DE
|
||||
# Low power xtal (16MHz) 16KCK/14CK+65ms
|
||||
sanguino_isp: LFUSE = FF
|
||||
# 2.7V brownout
|
||||
sanguino_isp: EFUSE = FD
|
||||
sanguino_isp: isp
|
||||
|
||||
# Mega has a minimum boot size of 1024 bytes, so enable extra functions
|
||||
#mega: TARGET = atmega1280
|
||||
mega1280: MCU_TARGET = atmega1280
|
||||
mega1280: CFLAGS += '-DLED_START_FLASHES=3' '-DBAUD_RATE=38400' '-DBIGBOOT'
|
||||
mega1280: AVR_FREQ = 16000000L
|
||||
mega1280: LDSECTIONS = -Wl,--section-start=.text=0x1fc00 -Wl,--section-start=.version=0x1fffe
|
||||
mega1280: $(PROGRAM)_atmega1280.hex
|
||||
mega1280: $(PROGRAM)_atmega1280.lst
|
||||
|
||||
mega1280_isp: mega
|
||||
mega1280_isp: TARGET = atmega1280
|
||||
mega1280_isp: MCU_TARGET = atmega1280
|
||||
# 1024 byte boot
|
||||
mega1280_isp: HFUSE = DE
|
||||
# Low power xtal (16MHz) 16KCK/14CK+65ms
|
||||
mega1280_isp: LFUSE = FF
|
||||
# 2.7V brownout
|
||||
mega1280_isp: EFUSE = FD
|
||||
mega1280_isp: isp
|
||||
|
||||
# ATmega8
|
||||
#
|
||||
atmega8: TARGET = atmega8
|
||||
atmega8: MCU_TARGET = atmega8
|
||||
atmega8: CFLAGS += '-DLED_START_FLASHES=3' '-DBAUD_RATE=38400'
|
||||
atmega8: AVR_FREQ = 16000000L
|
||||
atmega8: LDSECTIONS = -Wl,--section-start=.text=0x1e00 -Wl,--section-start=.version=0x1ffe
|
||||
atmega8: $(PROGRAM)_atmega8.hex
|
||||
atmega8: $(PROGRAM)_atmega8.lst
|
||||
|
||||
atmega8_isp: atmega8
|
||||
atmega8_isp: TARGET = atmega8
|
||||
atmega8_isp: MCU_TARGET = atmega8
|
||||
# SPIEN, CKOPT, Bootsize=512B
|
||||
atmega8_isp: HFUSE = CC
|
||||
# 2.7V brownout, Low power xtal (16MHz) 16KCK/14CK+65ms
|
||||
atmega8_isp: LFUSE = BF
|
||||
atmega8_isp: isp
|
||||
|
||||
# ATmega88
|
||||
#
|
||||
atmega88: TARGET = atmega88
|
||||
atmega88: MCU_TARGET = atmega88
|
||||
atmega88: CFLAGS += '-DLED_START_FLASHES=0' '-DBAUD_RATE=38400'
|
||||
atmega88: AVR_FREQ = 12000000L
|
||||
atmega88: LDSECTIONS = -Wl,--section-start=.text=0x1e00 -Wl,--section-start=.version=0x1ffe
|
||||
atmega88: $(PROGRAM)_atmega88.hex
|
||||
atmega88: $(PROGRAM)_atmega88.lst
|
||||
|
||||
atmega88_isp: atmega88
|
||||
atmega88_isp: TARGET = atmega88
|
||||
atmega88_isp: MCU_TARGET = atmega88
|
||||
# 2.7V brownout
|
||||
atmega88_isp: HFUSE = DD
|
||||
# Low power xtal (16MHz) 16KCK/14CK+65ms
|
||||
atemga88_isp: LFUSE = FF
|
||||
# 512 byte boot
|
||||
atmega88_isp: EFUSE = 04
|
||||
atmega88_isp: isp
|
||||
|
||||
|
||||
# 8MHz clocked platforms
|
||||
#
|
||||
# These are capable of 38400 baud
|
||||
#
|
||||
|
||||
lilypad: TARGET = lilypad
|
||||
lilypad: MCU_TARGET = atmega168
|
||||
lilypad: CFLAGS += '-DLED_START_FLASHES=3' '-DBAUD_RATE=38400'
|
||||
lilypad: AVR_FREQ = 8000000L
|
||||
lilypad: $(PROGRAM)_lilypad.hex
|
||||
lilypad: $(PROGRAM)_lilypad.lst
|
||||
|
||||
lilypad_isp: lilypad
|
||||
lilypad_isp: TARGET = lilypad
|
||||
# 2.7V brownout
|
||||
lilypad_isp: HFUSE = DD
|
||||
# Internal 8MHz osc (8MHz) Slow rising power
|
||||
lilypad_isp: LFUSE = E2
|
||||
# 512 byte boot
|
||||
lilypad_isp: EFUSE = 04
|
||||
lilypad_isp: isp
|
||||
|
||||
lilypad_resonator: TARGET = lilypad_resonator
|
||||
lilypad_resonator: MCU_TARGET = atmega168
|
||||
lilypad_resonator: CFLAGS += '-DLED_START_FLASHES=3' '-DBAUD_RATE=38400'
|
||||
lilypad_resonator: AVR_FREQ = 8000000L
|
||||
lilypad_resonator: $(PROGRAM)_lilypad_resonator.hex
|
||||
lilypad_resonator: $(PROGRAM)_lilypad_resonator.lst
|
||||
|
||||
lilypad_resonator_isp: lilypad_resonator
|
||||
lilypad_resonator_isp: TARGET = lilypad_resonator
|
||||
# 2.7V brownout
|
||||
lilypad_resonator_isp: HFUSE = DD
|
||||
# Full swing xtal (20MHz) 258CK/14CK+4.1ms
|
||||
lilypad_resonator_isp: LFUSE = C6
|
||||
# 512 byte boot
|
||||
lilypad_resonator_isp: EFUSE = 04
|
||||
lilypad_resonator_isp: isp
|
||||
|
||||
pro8: TARGET = pro_8MHz
|
||||
pro8: MCU_TARGET = atmega168
|
||||
pro8: CFLAGS += '-DLED_START_FLASHES=3' '-DBAUD_RATE=38400'
|
||||
pro8: AVR_FREQ = 8000000L
|
||||
pro8: $(PROGRAM)_pro_8MHz.hex
|
||||
pro8: $(PROGRAM)_pro_8MHz.lst
|
||||
|
||||
pro8_isp: pro8
|
||||
pro8_isp: TARGET = pro_8MHz
|
||||
# 2.7V brownout
|
||||
pro8_isp: HFUSE = DD
|
||||
# Full swing xtal (20MHz) 258CK/14CK+4.1ms
|
||||
pro8_isp: LFUSE = C6
|
||||
# 512 byte boot
|
||||
pro8_isp: EFUSE = 04
|
||||
pro8_isp: isp
|
||||
|
||||
atmega328_pro8: TARGET = atmega328_pro_8MHz
|
||||
atmega328_pro8: MCU_TARGET = atmega328p
|
||||
atmega328_pro8: CFLAGS += '-DLED_START_FLASHES=3' '-DBAUD_RATE=38400'
|
||||
atmega328_pro8: AVR_FREQ = 8000000L
|
||||
atmega328_pro8: LDSECTIONS = -Wl,--section-start=.text=0x7e00 -Wl,--section-start=.version=0x7ffe
|
||||
atmega328_pro8: $(PROGRAM)_atmega328_pro_8MHz.hex
|
||||
atmega328_pro8: $(PROGRAM)_atmega328_pro_8MHz.lst
|
||||
|
||||
atmega328_pro8_isp: atmega328_pro8
|
||||
atmega328_pro8_isp: TARGET = atmega328_pro_8MHz
|
||||
atmega328_pro8_isp: MCU_TARGET = atmega328p
|
||||
# 512 byte boot, SPIEN
|
||||
atmega328_pro8_isp: HFUSE = DE
|
||||
# Low power xtal (16MHz) 16KCK/14CK+65ms
|
||||
atmega328_pro8_isp: LFUSE = FF
|
||||
# 2.7V brownout
|
||||
atmega328_pro8_isp: EFUSE = DE
|
||||
atmega328_pro8_isp: isp
|
||||
|
||||
# 1MHz clocked platforms
|
||||
#
|
||||
# These are capable of 9600 baud
|
||||
#
|
||||
|
||||
luminet: TARGET = luminet
|
||||
luminet: MCU_TARGET = attiny84
|
||||
luminet: CFLAGS += '-DLED_START_FLASHES=3' '-DSOFT_UART' '-DBAUD_RATE=9600'
|
||||
luminet: CFLAGS += '-DVIRTUAL_BOOT_PARTITION'
|
||||
luminet: AVR_FREQ = 1000000L
|
||||
luminet: LDSECTIONS = -Wl,--section-start=.text=0x1d00 -Wl,--section-start=.version=0x1efe
|
||||
luminet: $(PROGRAM)_luminet.hex
|
||||
luminet: $(PROGRAM)_luminet.lst
|
||||
|
||||
luminet_isp: luminet
|
||||
luminet_isp: TARGET = luminet
|
||||
luminet_isp: MCU_TARGET = attiny84
|
||||
# Brownout disabled
|
||||
luminet_isp: HFUSE = DF
|
||||
# 1MHz internal oscillator, slowly rising power
|
||||
luminet_isp: LFUSE = 62
|
||||
# Self-programming enable
|
||||
luminet_isp: EFUSE = FE
|
||||
luminet_isp: isp
|
||||
|
||||
#
|
||||
# Generic build instructions
|
||||
#
|
||||
#
|
||||
|
||||
isp: $(TARGET)
|
||||
$(ISPFUSES)
|
||||
$(ISPFLASH)
|
||||
|
||||
isp-stk500: $(PROGRAM)_$(TARGET).hex
|
||||
$(STK500-1)
|
||||
$(STK500-2)
|
||||
|
||||
%.elf: $(OBJ)
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(LIBS)
|
||||
$(SIZE) $@
|
||||
|
||||
clean:
|
||||
rm -rf *.o *.elf *.lst *.map *.sym *.lss *.eep *.srec *.bin *.hex
|
||||
|
||||
%.lst: %.elf
|
||||
$(OBJDUMP) -h -S $< > $@
|
||||
|
||||
%.hex: %.elf
|
||||
$(OBJCOPY) -j .text -j .data -j .version --set-section-flags .version=alloc,load -O ihex $< $@
|
||||
|
||||
%.srec: %.elf
|
||||
$(OBJCOPY) -j .text -j .data -j .version --set-section-flags .version=alloc,load -O srec $< $@
|
||||
|
||||
%.bin: %.elf
|
||||
$(OBJCOPY) -j .text -j .data -j .version --set-section-flags .version=alloc,load -O binary $< $@
|
||||
848
BootLoaders/AtmegaMultiBoot/Source/boot.h
Normal file
@@ -0,0 +1,848 @@
|
||||
/* Modified to use out for SPM access
|
||||
** Peter Knight, Optiboot project http://optiboot.googlecode.com
|
||||
**
|
||||
** Todo: Tidy up
|
||||
**
|
||||
** "_short" routines execute 1 cycle faster and use 1 less word of flash
|
||||
** by using "out" instruction instead of "sts".
|
||||
**
|
||||
** Additional elpm variants that trust the value of RAMPZ
|
||||
*/
|
||||
|
||||
/* Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 Eric B. Weddington
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
* Neither the name of the copyright holders nor the names of
|
||||
contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE. */
|
||||
|
||||
/* $Id: boot.h,v 1.27.2.3 2008/09/30 13:58:48 arcanum Exp $ */
|
||||
|
||||
#ifndef _AVR_BOOT_H_
|
||||
#define _AVR_BOOT_H_ 1
|
||||
|
||||
/** \file */
|
||||
/** \defgroup avr_boot <avr/boot.h>: Bootloader Support Utilities
|
||||
\code
|
||||
#include <avr/io.h>
|
||||
#include <avr/boot.h>
|
||||
\endcode
|
||||
|
||||
The macros in this module provide a C language interface to the
|
||||
bootloader support functionality of certain AVR processors. These
|
||||
macros are designed to work with all sizes of flash memory.
|
||||
|
||||
Global interrupts are not automatically disabled for these macros. It
|
||||
is left up to the programmer to do this. See the code example below.
|
||||
Also see the processor datasheet for caveats on having global interrupts
|
||||
enabled during writing of the Flash.
|
||||
|
||||
\note Not all AVR processors provide bootloader support. See your
|
||||
processor datasheet to see if it provides bootloader support.
|
||||
|
||||
\todo From email with Marek: On smaller devices (all except ATmega64/128),
|
||||
__SPM_REG is in the I/O space, accessible with the shorter "in" and "out"
|
||||
instructions - since the boot loader has a limited size, this could be an
|
||||
important optimization.
|
||||
|
||||
\par API Usage Example
|
||||
The following code shows typical usage of the boot API.
|
||||
|
||||
\code
|
||||
#include <inttypes.h>
|
||||
#include <avr/interrupt.h>
|
||||
#include <avr/pgmspace.h>
|
||||
|
||||
void boot_program_page (uint32_t page, uint8_t *buf)
|
||||
{
|
||||
uint16_t i;
|
||||
uint8_t sreg;
|
||||
|
||||
// Disable interrupts.
|
||||
|
||||
sreg = SREG;
|
||||
cli();
|
||||
|
||||
eeprom_busy_wait ();
|
||||
|
||||
boot_page_erase (page);
|
||||
boot_spm_busy_wait (); // Wait until the memory is erased.
|
||||
|
||||
for (i=0; i<SPM_PAGESIZE; i+=2)
|
||||
{
|
||||
// Set up little-endian word.
|
||||
|
||||
uint16_t w = *buf++;
|
||||
w += (*buf++) << 8;
|
||||
|
||||
boot_page_fill (page + i, w);
|
||||
}
|
||||
|
||||
boot_page_write (page); // Store buffer in flash page.
|
||||
boot_spm_busy_wait(); // Wait until the memory is written.
|
||||
|
||||
// Reenable RWW-section again. We need this if we want to jump back
|
||||
// to the application after bootloading.
|
||||
|
||||
boot_rww_enable ();
|
||||
|
||||
// Re-enable interrupts (if they were ever enabled).
|
||||
|
||||
SREG = sreg;
|
||||
}\endcode */
|
||||
|
||||
#include <avr/eeprom.h>
|
||||
#include <avr/io.h>
|
||||
#include <inttypes.h>
|
||||
#include <limits.h>
|
||||
|
||||
/* Check for SPM Control Register in processor. */
|
||||
#if defined (SPMCSR)
|
||||
# define __SPM_REG SPMCSR
|
||||
#elif defined (SPMCR)
|
||||
# define __SPM_REG SPMCR
|
||||
#else
|
||||
# error AVR processor does not provide bootloader support!
|
||||
#endif
|
||||
|
||||
|
||||
/* Check for SPM Enable bit. */
|
||||
#if defined(SPMEN)
|
||||
# define __SPM_ENABLE SPMEN
|
||||
#elif defined(SELFPRGEN)
|
||||
# define __SPM_ENABLE SELFPRGEN
|
||||
#else
|
||||
# error Cannot find SPM Enable bit definition!
|
||||
#endif
|
||||
|
||||
/** \ingroup avr_boot
|
||||
\def BOOTLOADER_SECTION
|
||||
|
||||
Used to declare a function or variable to be placed into a
|
||||
new section called .bootloader. This section and its contents
|
||||
can then be relocated to any address (such as the bootloader
|
||||
NRWW area) at link-time. */
|
||||
|
||||
#define BOOTLOADER_SECTION __attribute__ ((section (".bootloader")))
|
||||
|
||||
/* Create common bit definitions. */
|
||||
#ifdef ASB
|
||||
#define __COMMON_ASB ASB
|
||||
#else
|
||||
#define __COMMON_ASB RWWSB
|
||||
#endif
|
||||
|
||||
#ifdef ASRE
|
||||
#define __COMMON_ASRE ASRE
|
||||
#else
|
||||
#define __COMMON_ASRE RWWSRE
|
||||
#endif
|
||||
|
||||
/* Define the bit positions of the Boot Lock Bits. */
|
||||
|
||||
#define BLB12 5
|
||||
#define BLB11 4
|
||||
#define BLB02 3
|
||||
#define BLB01 2
|
||||
|
||||
/** \ingroup avr_boot
|
||||
\def boot_spm_interrupt_enable()
|
||||
Enable the SPM interrupt. */
|
||||
|
||||
#define boot_spm_interrupt_enable() (__SPM_REG |= (uint8_t)_BV(SPMIE))
|
||||
|
||||
/** \ingroup avr_boot
|
||||
\def boot_spm_interrupt_disable()
|
||||
Disable the SPM interrupt. */
|
||||
|
||||
#define boot_spm_interrupt_disable() (__SPM_REG &= (uint8_t)~_BV(SPMIE))
|
||||
|
||||
/** \ingroup avr_boot
|
||||
\def boot_is_spm_interrupt()
|
||||
Check if the SPM interrupt is enabled. */
|
||||
|
||||
#define boot_is_spm_interrupt() (__SPM_REG & (uint8_t)_BV(SPMIE))
|
||||
|
||||
/** \ingroup avr_boot
|
||||
\def boot_rww_busy()
|
||||
Check if the RWW section is busy. */
|
||||
|
||||
#define boot_rww_busy() (__SPM_REG & (uint8_t)_BV(__COMMON_ASB))
|
||||
|
||||
/** \ingroup avr_boot
|
||||
\def boot_spm_busy()
|
||||
Check if the SPM instruction is busy. */
|
||||
|
||||
#define boot_spm_busy() (__SPM_REG & (uint8_t)_BV(__SPM_ENABLE))
|
||||
|
||||
/** \ingroup avr_boot
|
||||
\def boot_spm_busy_wait()
|
||||
Wait while the SPM instruction is busy. */
|
||||
|
||||
#define boot_spm_busy_wait() do{}while(boot_spm_busy())
|
||||
|
||||
#define __BOOT_PAGE_ERASE (_BV(__SPM_ENABLE) | _BV(PGERS))
|
||||
#define __BOOT_PAGE_WRITE (_BV(__SPM_ENABLE) | _BV(PGWRT))
|
||||
#define __BOOT_PAGE_FILL _BV(__SPM_ENABLE)
|
||||
#define __BOOT_RWW_ENABLE (_BV(__SPM_ENABLE) | _BV(__COMMON_ASRE))
|
||||
#define __BOOT_LOCK_BITS_SET (_BV(__SPM_ENABLE) | _BV(BLBSET))
|
||||
|
||||
#define __boot_page_fill_short(address, data) \
|
||||
(__extension__({ \
|
||||
__asm__ __volatile__ \
|
||||
( \
|
||||
"movw r0, %3\n\t" \
|
||||
"out %0, %1\n\t" \
|
||||
"spm\n\t" \
|
||||
"clr r1\n\t" \
|
||||
: \
|
||||
: "i" (_SFR_IO_ADDR(__SPM_REG)), \
|
||||
"r" ((uint8_t)__BOOT_PAGE_FILL), \
|
||||
"z" ((uint16_t)address), \
|
||||
"r" ((uint16_t)data) \
|
||||
: "r0" \
|
||||
); \
|
||||
}))
|
||||
|
||||
#define __boot_page_fill_normal(address, data) \
|
||||
(__extension__({ \
|
||||
__asm__ __volatile__ \
|
||||
( \
|
||||
"movw r0, %3\n\t" \
|
||||
"sts %0, %1\n\t" \
|
||||
"spm\n\t" \
|
||||
"clr r1\n\t" \
|
||||
: \
|
||||
: "i" (_SFR_MEM_ADDR(__SPM_REG)), \
|
||||
"r" ((uint8_t)__BOOT_PAGE_FILL), \
|
||||
"z" ((uint16_t)address), \
|
||||
"r" ((uint16_t)data) \
|
||||
: "r0" \
|
||||
); \
|
||||
}))
|
||||
|
||||
#define __boot_page_fill_alternate(address, data)\
|
||||
(__extension__({ \
|
||||
__asm__ __volatile__ \
|
||||
( \
|
||||
"movw r0, %3\n\t" \
|
||||
"sts %0, %1\n\t" \
|
||||
"spm\n\t" \
|
||||
".word 0xffff\n\t" \
|
||||
"nop\n\t" \
|
||||
"clr r1\n\t" \
|
||||
: \
|
||||
: "i" (_SFR_MEM_ADDR(__SPM_REG)), \
|
||||
"r" ((uint8_t)__BOOT_PAGE_FILL), \
|
||||
"z" ((uint16_t)address), \
|
||||
"r" ((uint16_t)data) \
|
||||
: "r0" \
|
||||
); \
|
||||
}))
|
||||
|
||||
#define __boot_page_fill_extended(address, data) \
|
||||
(__extension__({ \
|
||||
__asm__ __volatile__ \
|
||||
( \
|
||||
"movw r0, %4\n\t" \
|
||||
"movw r30, %A3\n\t" \
|
||||
"sts %1, %C3\n\t" \
|
||||
"sts %0, %2\n\t" \
|
||||
"spm\n\t" \
|
||||
"clr r1\n\t" \
|
||||
: \
|
||||
: "i" (_SFR_MEM_ADDR(__SPM_REG)), \
|
||||
"i" (_SFR_MEM_ADDR(RAMPZ)), \
|
||||
"r" ((uint8_t)__BOOT_PAGE_FILL), \
|
||||
"r" ((uint32_t)address), \
|
||||
"r" ((uint16_t)data) \
|
||||
: "r0", "r30", "r31" \
|
||||
); \
|
||||
}))
|
||||
|
||||
#define __boot_page_fill_extended_short(address, data) \
|
||||
(__extension__({ \
|
||||
__asm__ __volatile__ \
|
||||
( \
|
||||
"movw r0, %4\n\t" \
|
||||
"movw r30, %A3\n\t" \
|
||||
"out %1, %C3\n\t" \
|
||||
"out %0, %2\n\t" \
|
||||
"spm\n\t" \
|
||||
"clr r1\n\t" \
|
||||
: \
|
||||
: "i" (_SFR_IO_ADDR(__SPM_REG)), \
|
||||
"i" (_SFR_IO_ADDR(RAMPZ)), \
|
||||
"r" ((uint8_t)__BOOT_PAGE_FILL), \
|
||||
"r" ((uint32_t)address), \
|
||||
"r" ((uint16_t)data) \
|
||||
: "r0", "r30", "r31" \
|
||||
); \
|
||||
}))
|
||||
|
||||
#define __boot_page_erase_short(address) \
|
||||
(__extension__({ \
|
||||
__asm__ __volatile__ \
|
||||
( \
|
||||
"out %0, %1\n\t" \
|
||||
"spm\n\t" \
|
||||
: \
|
||||
: "i" (_SFR_IO_ADDR(__SPM_REG)), \
|
||||
"r" ((uint8_t)__BOOT_PAGE_ERASE), \
|
||||
"z" ((uint16_t)address) \
|
||||
); \
|
||||
}))
|
||||
|
||||
|
||||
#define __boot_page_erase_normal(address) \
|
||||
(__extension__({ \
|
||||
__asm__ __volatile__ \
|
||||
( \
|
||||
"sts %0, %1\n\t" \
|
||||
"spm\n\t" \
|
||||
: \
|
||||
: "i" (_SFR_MEM_ADDR(__SPM_REG)), \
|
||||
"r" ((uint8_t)__BOOT_PAGE_ERASE), \
|
||||
"z" ((uint16_t)address) \
|
||||
); \
|
||||
}))
|
||||
|
||||
#define __boot_page_erase_alternate(address) \
|
||||
(__extension__({ \
|
||||
__asm__ __volatile__ \
|
||||
( \
|
||||
"sts %0, %1\n\t" \
|
||||
"spm\n\t" \
|
||||
".word 0xffff\n\t" \
|
||||
"nop\n\t" \
|
||||
: \
|
||||
: "i" (_SFR_MEM_ADDR(__SPM_REG)), \
|
||||
"r" ((uint8_t)__BOOT_PAGE_ERASE), \
|
||||
"z" ((uint16_t)address) \
|
||||
); \
|
||||
}))
|
||||
|
||||
#define __boot_page_erase_extended(address) \
|
||||
(__extension__({ \
|
||||
__asm__ __volatile__ \
|
||||
( \
|
||||
"movw r30, %A3\n\t" \
|
||||
"sts %1, %C3\n\t" \
|
||||
"sts %0, %2\n\t" \
|
||||
"spm\n\t" \
|
||||
: \
|
||||
: "i" (_SFR_MEM_ADDR(__SPM_REG)), \
|
||||
"i" (_SFR_MEM_ADDR(RAMPZ)), \
|
||||
"r" ((uint8_t)__BOOT_PAGE_ERASE), \
|
||||
"r" ((uint32_t)address) \
|
||||
: "r30", "r31" \
|
||||
); \
|
||||
}))
|
||||
#define __boot_page_erase_extended_short(address) \
|
||||
(__extension__({ \
|
||||
__asm__ __volatile__ \
|
||||
( \
|
||||
"movw r30, %A3\n\t" \
|
||||
"out %1, %C3\n\t" \
|
||||
"out %0, %2\n\t" \
|
||||
"spm\n\t" \
|
||||
: \
|
||||
: "i" (_SFR_IO_ADDR(__SPM_REG)), \
|
||||
"i" (_SFR_IO_ADDR(RAMPZ)), \
|
||||
"r" ((uint8_t)__BOOT_PAGE_ERASE), \
|
||||
"r" ((uint32_t)address) \
|
||||
: "r30", "r31" \
|
||||
); \
|
||||
}))
|
||||
|
||||
#define __boot_page_write_short(address) \
|
||||
(__extension__({ \
|
||||
__asm__ __volatile__ \
|
||||
( \
|
||||
"out %0, %1\n\t" \
|
||||
"spm\n\t" \
|
||||
: \
|
||||
: "i" (_SFR_IO_ADDR(__SPM_REG)), \
|
||||
"r" ((uint8_t)__BOOT_PAGE_WRITE), \
|
||||
"z" ((uint16_t)address) \
|
||||
); \
|
||||
}))
|
||||
|
||||
#define __boot_page_write_normal(address) \
|
||||
(__extension__({ \
|
||||
__asm__ __volatile__ \
|
||||
( \
|
||||
"sts %0, %1\n\t" \
|
||||
"spm\n\t" \
|
||||
: \
|
||||
: "i" (_SFR_MEM_ADDR(__SPM_REG)), \
|
||||
"r" ((uint8_t)__BOOT_PAGE_WRITE), \
|
||||
"z" ((uint16_t)address) \
|
||||
); \
|
||||
}))
|
||||
|
||||
#define __boot_page_write_alternate(address) \
|
||||
(__extension__({ \
|
||||
__asm__ __volatile__ \
|
||||
( \
|
||||
"sts %0, %1\n\t" \
|
||||
"spm\n\t" \
|
||||
".word 0xffff\n\t" \
|
||||
"nop\n\t" \
|
||||
: \
|
||||
: "i" (_SFR_MEM_ADDR(__SPM_REG)), \
|
||||
"r" ((uint8_t)__BOOT_PAGE_WRITE), \
|
||||
"z" ((uint16_t)address) \
|
||||
); \
|
||||
}))
|
||||
|
||||
#define __boot_page_write_extended(address) \
|
||||
(__extension__({ \
|
||||
__asm__ __volatile__ \
|
||||
( \
|
||||
"movw r30, %A3\n\t" \
|
||||
"sts %1, %C3\n\t" \
|
||||
"sts %0, %2\n\t" \
|
||||
"spm\n\t" \
|
||||
: \
|
||||
: "i" (_SFR_MEM_ADDR(__SPM_REG)), \
|
||||
"i" (_SFR_MEM_ADDR(RAMPZ)), \
|
||||
"r" ((uint8_t)__BOOT_PAGE_WRITE), \
|
||||
"r" ((uint32_t)address) \
|
||||
: "r30", "r31" \
|
||||
); \
|
||||
}))
|
||||
#define __boot_page_write_extended_short(address) \
|
||||
(__extension__({ \
|
||||
__asm__ __volatile__ \
|
||||
( \
|
||||
"movw r30, %A3\n\t" \
|
||||
"out %1, %C3\n\t" \
|
||||
"out %0, %2\n\t" \
|
||||
"spm\n\t" \
|
||||
: \
|
||||
: "i" (_SFR_IO_ADDR(__SPM_REG)), \
|
||||
"i" (_SFR_IO_ADDR(RAMPZ)), \
|
||||
"r" ((uint8_t)__BOOT_PAGE_WRITE), \
|
||||
"r" ((uint32_t)address) \
|
||||
: "r30", "r31" \
|
||||
); \
|
||||
}))
|
||||
|
||||
#define __boot_rww_enable_short() \
|
||||
(__extension__({ \
|
||||
__asm__ __volatile__ \
|
||||
( \
|
||||
"out %0, %1\n\t" \
|
||||
"spm\n\t" \
|
||||
: \
|
||||
: "i" (_SFR_IO_ADDR(__SPM_REG)), \
|
||||
"r" ((uint8_t)__BOOT_RWW_ENABLE) \
|
||||
); \
|
||||
}))
|
||||
|
||||
#define __boot_rww_enable() \
|
||||
(__extension__({ \
|
||||
__asm__ __volatile__ \
|
||||
( \
|
||||
"sts %0, %1\n\t" \
|
||||
"spm\n\t" \
|
||||
: \
|
||||
: "i" (_SFR_MEM_ADDR(__SPM_REG)), \
|
||||
"r" ((uint8_t)__BOOT_RWW_ENABLE) \
|
||||
); \
|
||||
}))
|
||||
|
||||
#define __boot_rww_enable_alternate() \
|
||||
(__extension__({ \
|
||||
__asm__ __volatile__ \
|
||||
( \
|
||||
"sts %0, %1\n\t" \
|
||||
"spm\n\t" \
|
||||
".word 0xffff\n\t" \
|
||||
"nop\n\t" \
|
||||
: \
|
||||
: "i" (_SFR_MEM_ADDR(__SPM_REG)), \
|
||||
"r" ((uint8_t)__BOOT_RWW_ENABLE) \
|
||||
); \
|
||||
}))
|
||||
|
||||
/* From the mega16/mega128 data sheets (maybe others):
|
||||
|
||||
Bits by SPM To set the Boot Loader Lock bits, write the desired data to
|
||||
R0, write "X0001001" to SPMCR and execute SPM within four clock cycles
|
||||
after writing SPMCR. The only accessible Lock bits are the Boot Lock bits
|
||||
that may prevent the Application and Boot Loader section from any
|
||||
software update by the MCU.
|
||||
|
||||
If bits 5..2 in R0 are cleared (zero), the corresponding Boot Lock bit
|
||||
will be programmed if an SPM instruction is executed within four cycles
|
||||
after BLBSET and SPMEN (or SELFPRGEN) are set in SPMCR. The Z-pointer is
|
||||
don't care during this operation, but for future compatibility it is
|
||||
recommended to load the Z-pointer with $0001 (same as used for reading the
|
||||
Lock bits). For future compatibility It is also recommended to set bits 7,
|
||||
6, 1, and 0 in R0 to 1 when writing the Lock bits. When programming the
|
||||
Lock bits the entire Flash can be read during the operation. */
|
||||
|
||||
#define __boot_lock_bits_set_short(lock_bits) \
|
||||
(__extension__({ \
|
||||
uint8_t value = (uint8_t)(~(lock_bits)); \
|
||||
__asm__ __volatile__ \
|
||||
( \
|
||||
"ldi r30, 1\n\t" \
|
||||
"ldi r31, 0\n\t" \
|
||||
"mov r0, %2\n\t" \
|
||||
"out %0, %1\n\t" \
|
||||
"spm\n\t" \
|
||||
: \
|
||||
: "i" (_SFR_IO_ADDR(__SPM_REG)), \
|
||||
"r" ((uint8_t)__BOOT_LOCK_BITS_SET), \
|
||||
"r" (value) \
|
||||
: "r0", "r30", "r31" \
|
||||
); \
|
||||
}))
|
||||
|
||||
#define __boot_lock_bits_set(lock_bits) \
|
||||
(__extension__({ \
|
||||
uint8_t value = (uint8_t)(~(lock_bits)); \
|
||||
__asm__ __volatile__ \
|
||||
( \
|
||||
"ldi r30, 1\n\t" \
|
||||
"ldi r31, 0\n\t" \
|
||||
"mov r0, %2\n\t" \
|
||||
"sts %0, %1\n\t" \
|
||||
"spm\n\t" \
|
||||
: \
|
||||
: "i" (_SFR_MEM_ADDR(__SPM_REG)), \
|
||||
"r" ((uint8_t)__BOOT_LOCK_BITS_SET), \
|
||||
"r" (value) \
|
||||
: "r0", "r30", "r31" \
|
||||
); \
|
||||
}))
|
||||
|
||||
#define __boot_lock_bits_set_alternate(lock_bits) \
|
||||
(__extension__({ \
|
||||
uint8_t value = (uint8_t)(~(lock_bits)); \
|
||||
__asm__ __volatile__ \
|
||||
( \
|
||||
"ldi r30, 1\n\t" \
|
||||
"ldi r31, 0\n\t" \
|
||||
"mov r0, %2\n\t" \
|
||||
"sts %0, %1\n\t" \
|
||||
"spm\n\t" \
|
||||
".word 0xffff\n\t" \
|
||||
"nop\n\t" \
|
||||
: \
|
||||
: "i" (_SFR_MEM_ADDR(__SPM_REG)), \
|
||||
"r" ((uint8_t)__BOOT_LOCK_BITS_SET), \
|
||||
"r" (value) \
|
||||
: "r0", "r30", "r31" \
|
||||
); \
|
||||
}))
|
||||
|
||||
/*
|
||||
Reading lock and fuse bits:
|
||||
|
||||
Similarly to writing the lock bits above, set BLBSET and SPMEN (or
|
||||
SELFPRGEN) bits in __SPMREG, and then (within four clock cycles) issue an
|
||||
LPM instruction.
|
||||
|
||||
Z address: contents:
|
||||
0x0000 low fuse bits
|
||||
0x0001 lock bits
|
||||
0x0002 extended fuse bits
|
||||
0x0003 high fuse bits
|
||||
|
||||
Sounds confusing, doesn't it?
|
||||
|
||||
Unlike the macros in pgmspace.h, no need to care for non-enhanced
|
||||
cores here as these old cores do not provide SPM support anyway.
|
||||
*/
|
||||
|
||||
/** \ingroup avr_boot
|
||||
\def GET_LOW_FUSE_BITS
|
||||
address to read the low fuse bits, using boot_lock_fuse_bits_get
|
||||
*/
|
||||
#define GET_LOW_FUSE_BITS (0x0000)
|
||||
/** \ingroup avr_boot
|
||||
\def GET_LOCK_BITS
|
||||
address to read the lock bits, using boot_lock_fuse_bits_get
|
||||
*/
|
||||
#define GET_LOCK_BITS (0x0001)
|
||||
/** \ingroup avr_boot
|
||||
\def GET_EXTENDED_FUSE_BITS
|
||||
address to read the extended fuse bits, using boot_lock_fuse_bits_get
|
||||
*/
|
||||
#define GET_EXTENDED_FUSE_BITS (0x0002)
|
||||
/** \ingroup avr_boot
|
||||
\def GET_HIGH_FUSE_BITS
|
||||
address to read the high fuse bits, using boot_lock_fuse_bits_get
|
||||
*/
|
||||
#define GET_HIGH_FUSE_BITS (0x0003)
|
||||
|
||||
/** \ingroup avr_boot
|
||||
\def boot_lock_fuse_bits_get(address)
|
||||
|
||||
Read the lock or fuse bits at \c address.
|
||||
|
||||
Parameter \c address can be any of GET_LOW_FUSE_BITS,
|
||||
GET_LOCK_BITS, GET_EXTENDED_FUSE_BITS, or GET_HIGH_FUSE_BITS.
|
||||
|
||||
\note The lock and fuse bits returned are the physical values,
|
||||
i.e. a bit returned as 0 means the corresponding fuse or lock bit
|
||||
is programmed.
|
||||
*/
|
||||
#define boot_lock_fuse_bits_get_short(address) \
|
||||
(__extension__({ \
|
||||
uint8_t __result; \
|
||||
__asm__ __volatile__ \
|
||||
( \
|
||||
"ldi r30, %3\n\t" \
|
||||
"ldi r31, 0\n\t" \
|
||||
"out %1, %2\n\t" \
|
||||
"lpm %0, Z\n\t" \
|
||||
: "=r" (__result) \
|
||||
: "i" (_SFR_IO_ADDR(__SPM_REG)), \
|
||||
"r" ((uint8_t)__BOOT_LOCK_BITS_SET), \
|
||||
"M" (address) \
|
||||
: "r0", "r30", "r31" \
|
||||
); \
|
||||
__result; \
|
||||
}))
|
||||
|
||||
#define boot_lock_fuse_bits_get(address) \
|
||||
(__extension__({ \
|
||||
uint8_t __result; \
|
||||
__asm__ __volatile__ \
|
||||
( \
|
||||
"ldi r30, %3\n\t" \
|
||||
"ldi r31, 0\n\t" \
|
||||
"sts %1, %2\n\t" \
|
||||
"lpm %0, Z\n\t" \
|
||||
: "=r" (__result) \
|
||||
: "i" (_SFR_MEM_ADDR(__SPM_REG)), \
|
||||
"r" ((uint8_t)__BOOT_LOCK_BITS_SET), \
|
||||
"M" (address) \
|
||||
: "r0", "r30", "r31" \
|
||||
); \
|
||||
__result; \
|
||||
}))
|
||||
|
||||
/** \ingroup avr_boot
|
||||
\def boot_signature_byte_get(address)
|
||||
|
||||
Read the Signature Row byte at \c address. For some MCU types,
|
||||
this function can also retrieve the factory-stored oscillator
|
||||
calibration bytes.
|
||||
|
||||
Parameter \c address can be 0-0x1f as documented by the datasheet.
|
||||
\note The values are MCU type dependent.
|
||||
*/
|
||||
|
||||
#define __BOOT_SIGROW_READ (_BV(__SPM_ENABLE) | _BV(SIGRD))
|
||||
|
||||
#define boot_signature_byte_get_short(addr) \
|
||||
(__extension__({ \
|
||||
uint16_t __addr16 = (uint16_t)(addr); \
|
||||
uint8_t __result; \
|
||||
__asm__ __volatile__ \
|
||||
( \
|
||||
"out %1, %2\n\t" \
|
||||
"lpm %0, Z" "\n\t" \
|
||||
: "=r" (__result) \
|
||||
: "i" (_SFR_IO_ADDR(__SPM_REG)), \
|
||||
"r" ((uint8_t) __BOOT_SIGROW_READ), \
|
||||
"z" (__addr16) \
|
||||
); \
|
||||
__result; \
|
||||
}))
|
||||
|
||||
#define boot_signature_byte_get(addr) \
|
||||
(__extension__({ \
|
||||
uint16_t __addr16 = (uint16_t)(addr); \
|
||||
uint8_t __result; \
|
||||
__asm__ __volatile__ \
|
||||
( \
|
||||
"sts %1, %2\n\t" \
|
||||
"lpm %0, Z" "\n\t" \
|
||||
: "=r" (__result) \
|
||||
: "i" (_SFR_MEM_ADDR(__SPM_REG)), \
|
||||
"r" ((uint8_t) __BOOT_SIGROW_READ), \
|
||||
"z" (__addr16) \
|
||||
); \
|
||||
__result; \
|
||||
}))
|
||||
|
||||
/** \ingroup avr_boot
|
||||
\def boot_page_fill(address, data)
|
||||
|
||||
Fill the bootloader temporary page buffer for flash
|
||||
address with data word.
|
||||
|
||||
\note The address is a byte address. The data is a word. The AVR
|
||||
writes data to the buffer a word at a time, but addresses the buffer
|
||||
per byte! So, increment your address by 2 between calls, and send 2
|
||||
data bytes in a word format! The LSB of the data is written to the lower
|
||||
address; the MSB of the data is written to the higher address.*/
|
||||
|
||||
/** \ingroup avr_boot
|
||||
\def boot_page_erase(address)
|
||||
|
||||
Erase the flash page that contains address.
|
||||
|
||||
\note address is a byte address in flash, not a word address. */
|
||||
|
||||
/** \ingroup avr_boot
|
||||
\def boot_page_write(address)
|
||||
|
||||
Write the bootloader temporary page buffer
|
||||
to flash page that contains address.
|
||||
|
||||
\note address is a byte address in flash, not a word address. */
|
||||
|
||||
/** \ingroup avr_boot
|
||||
\def boot_rww_enable()
|
||||
|
||||
Enable the Read-While-Write memory section. */
|
||||
|
||||
/** \ingroup avr_boot
|
||||
\def boot_lock_bits_set(lock_bits)
|
||||
|
||||
Set the bootloader lock bits.
|
||||
|
||||
\param lock_bits A mask of which Boot Loader Lock Bits to set.
|
||||
|
||||
\note In this context, a 'set bit' will be written to a zero value.
|
||||
Note also that only BLBxx bits can be programmed by this command.
|
||||
|
||||
For example, to disallow the SPM instruction from writing to the Boot
|
||||
Loader memory section of flash, you would use this macro as such:
|
||||
|
||||
\code
|
||||
boot_lock_bits_set (_BV (BLB11));
|
||||
\endcode
|
||||
|
||||
\note Like any lock bits, the Boot Loader Lock Bits, once set,
|
||||
cannot be cleared again except by a chip erase which will in turn
|
||||
also erase the boot loader itself. */
|
||||
|
||||
/* Normal versions of the macros use 16-bit addresses.
|
||||
Extended versions of the macros use 32-bit addresses.
|
||||
Alternate versions of the macros use 16-bit addresses and require special
|
||||
instruction sequences after LPM.
|
||||
|
||||
FLASHEND is defined in the ioXXXX.h file.
|
||||
USHRT_MAX is defined in <limits.h>. */
|
||||
|
||||
#if defined(__AVR_ATmega161__) || defined(__AVR_ATmega163__) \
|
||||
|| defined(__AVR_ATmega323__)
|
||||
|
||||
/* Alternate: ATmega161/163/323 and 16 bit address */
|
||||
#define boot_page_fill(address, data) __boot_page_fill_alternate(address, data)
|
||||
#define boot_page_erase(address) __boot_page_erase_alternate(address)
|
||||
#define boot_page_write(address) __boot_page_write_alternate(address)
|
||||
#define boot_rww_enable() __boot_rww_enable_alternate()
|
||||
#define boot_lock_bits_set(lock_bits) __boot_lock_bits_set_alternate(lock_bits)
|
||||
|
||||
#elif (FLASHEND > USHRT_MAX)
|
||||
|
||||
/* Extended: >16 bit address */
|
||||
#define boot_page_fill(address, data) __boot_page_fill_extended_short(address, data)
|
||||
#define boot_page_erase(address) __boot_page_erase_extended_short(address)
|
||||
#define boot_page_write(address) __boot_page_write_extended_short(address)
|
||||
#define boot_rww_enable() __boot_rww_enable_short()
|
||||
#define boot_lock_bits_set(lock_bits) __boot_lock_bits_set_short(lock_bits)
|
||||
|
||||
#else
|
||||
|
||||
/* Normal: 16 bit address */
|
||||
#define boot_page_fill(address, data) __boot_page_fill_short(address, data)
|
||||
#define boot_page_erase(address) __boot_page_erase_short(address)
|
||||
#define boot_page_write(address) __boot_page_write_short(address)
|
||||
#define boot_rww_enable() __boot_rww_enable_short()
|
||||
#define boot_lock_bits_set(lock_bits) __boot_lock_bits_set_short(lock_bits)
|
||||
|
||||
#endif
|
||||
|
||||
/** \ingroup avr_boot
|
||||
|
||||
Same as boot_page_fill() except it waits for eeprom and spm operations to
|
||||
complete before filling the page. */
|
||||
|
||||
#define boot_page_fill_safe(address, data) \
|
||||
do { \
|
||||
boot_spm_busy_wait(); \
|
||||
eeprom_busy_wait(); \
|
||||
boot_page_fill(address, data); \
|
||||
} while (0)
|
||||
|
||||
/** \ingroup avr_boot
|
||||
|
||||
Same as boot_page_erase() except it waits for eeprom and spm operations to
|
||||
complete before erasing the page. */
|
||||
|
||||
#define boot_page_erase_safe(address) \
|
||||
do { \
|
||||
boot_spm_busy_wait(); \
|
||||
eeprom_busy_wait(); \
|
||||
boot_page_erase (address); \
|
||||
} while (0)
|
||||
|
||||
/** \ingroup avr_boot
|
||||
|
||||
Same as boot_page_write() except it waits for eeprom and spm operations to
|
||||
complete before writing the page. */
|
||||
|
||||
#define boot_page_write_safe(address) \
|
||||
do { \
|
||||
boot_spm_busy_wait(); \
|
||||
eeprom_busy_wait(); \
|
||||
boot_page_write (address); \
|
||||
} while (0)
|
||||
|
||||
/** \ingroup avr_boot
|
||||
|
||||
Same as boot_rww_enable() except waits for eeprom and spm operations to
|
||||
complete before enabling the RWW mameory. */
|
||||
|
||||
#define boot_rww_enable_safe() \
|
||||
do { \
|
||||
boot_spm_busy_wait(); \
|
||||
eeprom_busy_wait(); \
|
||||
boot_rww_enable(); \
|
||||
} while (0)
|
||||
|
||||
/** \ingroup avr_boot
|
||||
|
||||
Same as boot_lock_bits_set() except waits for eeprom and spm operations to
|
||||
complete before setting the lock bits. */
|
||||
|
||||
#define boot_lock_bits_set_safe(lock_bits) \
|
||||
do { \
|
||||
boot_spm_busy_wait(); \
|
||||
eeprom_busy_wait(); \
|
||||
boot_lock_bits_set (lock_bits); \
|
||||
} while (0)
|
||||
|
||||
#endif /* _AVR_BOOT_H_ */
|
||||
891
BootLoaders/AtmegaMultiBoot/Source/optiboot.c
Normal file
@@ -0,0 +1,891 @@
|
||||
/**********************************************************/
|
||||
/* Optiboot bootloader for Arduino */
|
||||
/* */
|
||||
/* http://optiboot.googlecode.com */
|
||||
/* */
|
||||
/* Arduino-maintained version : See README.TXT */
|
||||
/* http://code.google.com/p/arduino/ */
|
||||
/* It is the intent that changes not relevant to the */
|
||||
/* Arduino production envionment get moved from the */
|
||||
/* optiboot project to the arduino project in "lumps." */
|
||||
/* */
|
||||
/* Heavily optimised bootloader that is faster and */
|
||||
/* smaller than the Arduino standard bootloader */
|
||||
/* */
|
||||
/* Enhancements: */
|
||||
/* Fits in 512 bytes, saving 1.5K of code space */
|
||||
/* Background page erasing speeds up programming */
|
||||
/* Higher baud rate speeds up programming */
|
||||
/* Written almost entirely in C */
|
||||
/* Customisable timeout with accurate timeconstant */
|
||||
/* Optional virtual UART. No hardware UART required. */
|
||||
/* Optional virtual boot partition for devices without. */
|
||||
/* */
|
||||
/* What you lose: */
|
||||
/* Implements a skeleton STK500 protocol which is */
|
||||
/* missing several features including EEPROM */
|
||||
/* programming and non-page-aligned writes */
|
||||
/* High baud rate breaks compatibility with standard */
|
||||
/* Arduino flash settings */
|
||||
/* */
|
||||
/* Fully supported: */
|
||||
/* ATmega168 based devices (Diecimila etc) */
|
||||
/* ATmega328P based devices (Duemilanove etc) */
|
||||
/* */
|
||||
/* Beta test (believed working.) */
|
||||
/* ATmega8 based devices (Arduino legacy) */
|
||||
/* ATmega328 non-picopower devices */
|
||||
/* ATmega644P based devices (Sanguino) */
|
||||
/* ATmega1284P based devices */
|
||||
/* */
|
||||
/* Alpha test */
|
||||
/* ATmega1280 based devices (Arduino Mega) */
|
||||
/* */
|
||||
/* Work in progress: */
|
||||
/* ATtiny84 based devices (Luminet) */
|
||||
/* */
|
||||
/* Does not support: */
|
||||
/* USB based devices (eg. Teensy) */
|
||||
/* */
|
||||
/* Assumptions: */
|
||||
/* The code makes several assumptions that reduce the */
|
||||
/* code size. They are all true after a hardware reset, */
|
||||
/* but may not be true if the bootloader is called by */
|
||||
/* other means or on other hardware. */
|
||||
/* No interrupts can occur */
|
||||
/* UART and Timer 1 are set to their reset state */
|
||||
/* SP points to RAMEND */
|
||||
/* */
|
||||
/* Code builds on code, libraries and optimisations from: */
|
||||
/* stk500boot.c by Jason P. Kyle */
|
||||
/* Arduino bootloader http://arduino.cc */
|
||||
/* Spiff's 1K bootloader http://spiffie.org/know/arduino_1k_bootloader/bootloader.shtml */
|
||||
/* avr-libc project http://nongnu.org/avr-libc */
|
||||
/* Adaboot http://www.ladyada.net/library/arduino/bootloader.html */
|
||||
/* AVR305 Atmel Application Note */
|
||||
/* */
|
||||
/* This program 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 2 of the License, or */
|
||||
/* (at your option) any later version. */
|
||||
/* */
|
||||
/* 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. */
|
||||
/* */
|
||||
/* You should have received a copy of the GNU General */
|
||||
/* Public License along with this program; if not, write */
|
||||
/* to the Free Software Foundation, Inc., */
|
||||
/* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
/* */
|
||||
/* Licence can be viewed at */
|
||||
/* http://www.fsf.org/licenses/gpl.txt */
|
||||
/* */
|
||||
/**********************************************************/
|
||||
|
||||
|
||||
/**********************************************************/
|
||||
/* */
|
||||
/* Optional defines: */
|
||||
/* */
|
||||
/**********************************************************/
|
||||
/* */
|
||||
/* BIG_BOOT: */
|
||||
/* Build a 1k bootloader, not 512 bytes. This turns on */
|
||||
/* extra functionality. */
|
||||
/* */
|
||||
/* BAUD_RATE: */
|
||||
/* Set bootloader baud rate. */
|
||||
/* */
|
||||
/* LUDICROUS_SPEED: */
|
||||
/* 230400 baud :-) */
|
||||
/* */
|
||||
/* SOFT_UART: */
|
||||
/* Use AVR305 soft-UART instead of hardware UART. */
|
||||
/* */
|
||||
/* LED_START_FLASHES: */
|
||||
/* Number of LED flashes on bootup. */
|
||||
/* */
|
||||
/* LED_DATA_FLASH: */
|
||||
/* Flash LED when transferring data. For boards without */
|
||||
/* TX or RX LEDs, or for people who like blinky lights. */
|
||||
/* */
|
||||
/* SUPPORT_EEPROM: */
|
||||
/* Support reading and writing from EEPROM. This is not */
|
||||
/* used by Arduino, so off by default. */
|
||||
/* */
|
||||
/* TIMEOUT_MS: */
|
||||
/* Bootloader timeout period, in milliseconds. */
|
||||
/* 500,1000,2000,4000,8000 supported. */
|
||||
/* */
|
||||
/* UART: */
|
||||
/* UART number (0..n) for devices with more than */
|
||||
/* one hardware uart (644P, 1284P, etc) */
|
||||
/* */
|
||||
/**********************************************************/
|
||||
|
||||
/**********************************************************/
|
||||
/* Version Numbers! */
|
||||
/* */
|
||||
/* Arduino Optiboot now includes this Version number in */
|
||||
/* the source and object code. */
|
||||
/* */
|
||||
/* Version 3 was released as zip from the optiboot */
|
||||
/* repository and was distributed with Arduino 0022. */
|
||||
/* Version 4 starts with the arduino repository commit */
|
||||
/* that brought the arduino repository up-to-date with */
|
||||
/* the optiboot source tree changes since v3. */
|
||||
/* */
|
||||
/**********************************************************/
|
||||
|
||||
/**********************************************************/
|
||||
/* Edit History: */
|
||||
/* */
|
||||
/* Nov 2012 */
|
||||
/* Specific version for 9x voice module */
|
||||
/* by Mike Blandford */
|
||||
/* Mar 2012 */
|
||||
/* 4.5 WestfW: add infrastructure for non-zero UARTS. */
|
||||
/* 4.5 WestfW: fix SIGNATURE_2 for m644 (bad in avr-libc) */
|
||||
/* Jan 2012: */
|
||||
/* 4.5 WestfW: fix NRWW value for m1284. */
|
||||
/* 4.4 WestfW: use attribute OS_main instead of naked for */
|
||||
/* main(). This allows optimizations that we */
|
||||
/* count on, which are prohibited in naked */
|
||||
/* functions due to PR42240. (keeps us less */
|
||||
/* than 512 bytes when compiler is gcc4.5 */
|
||||
/* (code from 4.3.2 remains the same.) */
|
||||
/* 4.4 WestfW and Maniacbug: Add m1284 support. This */
|
||||
/* does not change the 328 binary, so the */
|
||||
/* version number didn't change either. (?) */
|
||||
/* June 2011: */
|
||||
/* 4.4 WestfW: remove automatic soft_uart detect (didn't */
|
||||
/* know what it was doing or why.) Added a */
|
||||
/* check of the calculated BRG value instead. */
|
||||
/* Version stays 4.4; existing binaries are */
|
||||
/* not changed. */
|
||||
/* 4.4 WestfW: add initialization of address to keep */
|
||||
/* the compiler happy. Change SC'ed targets. */
|
||||
/* Return the SW version via READ PARAM */
|
||||
/* 4.3 WestfW: catch framing errors in getch(), so that */
|
||||
/* AVRISP works without HW kludges. */
|
||||
/* http://code.google.com/p/arduino/issues/detail?id=368n*/
|
||||
/* 4.2 WestfW: reduce code size, fix timeouts, change */
|
||||
/* verifySpace to use WDT instead of appstart */
|
||||
/* 4.1 WestfW: put version number in binary. */
|
||||
/**********************************************************/
|
||||
|
||||
#define OPTIBOOT_MAJVER 4
|
||||
#define OPTIBOOT_MINVER 5
|
||||
|
||||
#define MULTI_CALLED 1
|
||||
|
||||
#define MAKESTR(a) #a
|
||||
#define MAKEVER(a, b) MAKESTR(a*256+b)
|
||||
|
||||
//asm(" .section .version\n"
|
||||
// "optiboot_version: .word " MAKEVER(OPTIBOOT_MAJVER, OPTIBOOT_MINVER) "\n"
|
||||
// " .section .text\n");
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <avr/io.h>
|
||||
#include <avr/pgmspace.h>
|
||||
|
||||
// <avr/boot.h> uses sts instructions, but this version uses out instructions
|
||||
// This saves cycles and program memory.
|
||||
#include "boot.h"
|
||||
|
||||
|
||||
// We don't use <avr/wdt.h> as those routines have interrupt overhead we don't need.
|
||||
|
||||
#include "pin_defs.h"
|
||||
#include "stk500.h"
|
||||
|
||||
#ifndef LED_START_FLASHES
|
||||
#define LED_START_FLASHES 0
|
||||
#endif
|
||||
|
||||
#ifdef LUDICROUS_SPEED
|
||||
#define BAUD_RATE 230400L
|
||||
#endif
|
||||
|
||||
/* set the UART baud rate defaults */
|
||||
#ifndef BAUD_RATE
|
||||
#if F_CPU >= 8000000L
|
||||
#define BAUD_RATE 38400L // Highest rate Avrdude win32 will support
|
||||
#elsif F_CPU >= 1000000L
|
||||
#define BAUD_RATE 9600L // 19200 also supported, but with significant error
|
||||
#elsif F_CPU >= 128000L
|
||||
#define BAUD_RATE 4800L // Good for 128kHz internal RC
|
||||
#else
|
||||
#define BAUD_RATE 1200L // Good even at 32768Hz
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef UART
|
||||
#define UART 0
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
/* Switch in soft UART for hard baud rates */
|
||||
/*
|
||||
* I don't understand what this was supposed to accomplish, where the
|
||||
* constant "280" came from, or why automatically (and perhaps unexpectedly)
|
||||
* switching to a soft uart is a good thing, so I'm undoing this in favor
|
||||
* of a range check using the same calc used to config the BRG...
|
||||
*/
|
||||
#if (F_CPU/BAUD_RATE) > 280 // > 57600 for 16MHz
|
||||
#ifndef SOFT_UART
|
||||
#define SOFT_UART
|
||||
#endif
|
||||
#endif
|
||||
#else // 0
|
||||
#if (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 > 250
|
||||
#error Unachievable baud rate (too slow) BAUD_RATE
|
||||
#endif // baud rate slow check
|
||||
#if (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 < 3
|
||||
#error Unachievable baud rate (too fast) BAUD_RATE
|
||||
#endif // baud rate fastn check
|
||||
#endif
|
||||
|
||||
/* Watchdog settings */
|
||||
#define WATCHDOG_OFF (0)
|
||||
#define WATCHDOG_16MS (_BV(WDE))
|
||||
#define WATCHDOG_32MS (_BV(WDP0) | _BV(WDE))
|
||||
#define WATCHDOG_64MS (_BV(WDP1) | _BV(WDE))
|
||||
#define WATCHDOG_125MS (_BV(WDP1) | _BV(WDP0) | _BV(WDE))
|
||||
#define WATCHDOG_250MS (_BV(WDP2) | _BV(WDE))
|
||||
#define WATCHDOG_500MS (_BV(WDP2) | _BV(WDP0) | _BV(WDE))
|
||||
#define WATCHDOG_1S (_BV(WDP2) | _BV(WDP1) | _BV(WDE))
|
||||
#define WATCHDOG_2S (_BV(WDP2) | _BV(WDP1) | _BV(WDP0) | _BV(WDE))
|
||||
#ifndef __AVR_ATmega8__
|
||||
#define WATCHDOG_4S (_BV(WDP3) | _BV(WDE))
|
||||
#define WATCHDOG_8S (_BV(WDP3) | _BV(WDP0) | _BV(WDE))
|
||||
#endif
|
||||
|
||||
/* Function Prototypes */
|
||||
/* The main function is in init9, which removes the interrupt vector table */
|
||||
/* we don't need. It is also 'naked', which means the compiler does not */
|
||||
/* generate any entry or exit code itself. */
|
||||
int main(void) __attribute__ ((OS_main)) __attribute__ ((noreturn)) __attribute__ ((section (".init9")));
|
||||
void putch(char);
|
||||
uint8_t getch(void);
|
||||
static inline void getNch(uint8_t); /* "static inline" is a compiler hint to reduce code size */
|
||||
void verifySpace();
|
||||
#if LED_START_FLASHES > 0
|
||||
static inline void flash_led(uint8_t);
|
||||
#endif
|
||||
uint8_t getLen();
|
||||
//static inline void watchdogReset();
|
||||
void watchdogConfig(uint8_t x);
|
||||
#ifdef SOFT_UART
|
||||
void uartDelay() __attribute__ ((naked));
|
||||
#endif
|
||||
static void appStart() ; // __attribute__ ((naked));
|
||||
|
||||
/*
|
||||
* NRWW memory
|
||||
* Addresses below NRWW (Non-Read-While-Write) can be programmed while
|
||||
* continuing to run code from flash, slightly speeding up programming
|
||||
* time. Beware that Atmel data sheets specify this as a WORD address,
|
||||
* while optiboot will be comparing against a 16-bit byte address. This
|
||||
* means that on a part with 128kB of memory, the upper part of the lower
|
||||
* 64k will get NRWW processing as well, even though it doesn't need it.
|
||||
* That's OK. In fact, you can disable the overlapping processing for
|
||||
* a part entirely by setting NRWWSTART to zero. This reduces code
|
||||
* space a bit, at the expense of being slightly slower, overall.
|
||||
*
|
||||
* RAMSTART should be self-explanatory. It's bigger on parts with a
|
||||
* lot of peripheral registers.
|
||||
*/
|
||||
#if defined(__AVR_ATmega168__)
|
||||
#define RAMSTART (0x100)
|
||||
#define NRWWSTART (0x3800)
|
||||
#elif defined(__AVR_ATmega328P__)
|
||||
#define RAMSTART (0x100)
|
||||
#define NRWWSTART (0x7000)
|
||||
#elif defined(__AVR_ATmega328__)
|
||||
#define RAMSTART (0x100)
|
||||
#define NRWWSTART (0x7000)
|
||||
#elif defined (__AVR_ATmega644P__)
|
||||
#define RAMSTART (0x100)
|
||||
#define NRWWSTART (0xE000)
|
||||
// correct for a bug in avr-libc
|
||||
#undef SIGNATURE_2
|
||||
#define SIGNATURE_2 0x0A
|
||||
#elif defined (__AVR_ATmega1284P__)
|
||||
#define RAMSTART (0x100)
|
||||
#define NRWWSTART (0xE000)
|
||||
#elif defined(__AVR_ATtiny84__)
|
||||
#define RAMSTART (0x100)
|
||||
#define NRWWSTART (0x0000)
|
||||
#elif defined(__AVR_ATmega1280__)
|
||||
#define RAMSTART (0x200)
|
||||
#define NRWWSTART (0xE000)
|
||||
#elif defined(__AVR_ATmega8__) || defined(__AVR_ATmega88__)
|
||||
#define RAMSTART (0x100)
|
||||
#define NRWWSTART (0x1800)
|
||||
#endif
|
||||
|
||||
/* C zero initialises all global variables. However, that requires */
|
||||
/* These definitions are NOT zero initialised, but that doesn't matter */
|
||||
/* This allows us to drop the zero init code, saving us memory */
|
||||
#define buff ((uint8_t*)(RAMSTART))
|
||||
#ifdef VIRTUAL_BOOT_PARTITION
|
||||
#define rstVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+4))
|
||||
#define wdtVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+6))
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Handle devices with up to 4 uarts (eg m1280.) Rather inelegantly.
|
||||
* Note that mega8 still needs special handling, because ubrr is handled
|
||||
* differently.
|
||||
*/
|
||||
#if UART == 0
|
||||
# define UART_SRA UCSR0A
|
||||
# define UART_SRB UCSR0B
|
||||
# define UART_SRC UCSR0C
|
||||
# define UART_SRL UBRR0L
|
||||
# define UART_UDR UDR0
|
||||
#elif UART == 1
|
||||
# define UART_SRA UCSR1A
|
||||
# define UART_SRB UCSR1B
|
||||
# define UART_SRC UCSR1C
|
||||
# define UART_SRL UBRR1L
|
||||
# define UART_UDR UDR1
|
||||
#elif UART == 2
|
||||
# define UART_SRA UCSR2A
|
||||
# define UART_SRB UCSR2B
|
||||
# define UART_SRC UCSR2C
|
||||
# define UART_SRL UBRR2L
|
||||
# define UART_UDR UDR2
|
||||
#elif UART == 3
|
||||
# define UART_SRA UCSR3A
|
||||
# define UART_SRB UCSR3B
|
||||
# define UART_SRC UCSR3C
|
||||
# define UART_SRL UBRR3L
|
||||
# define UART_UDR UDR3
|
||||
#endif
|
||||
|
||||
/* main program starts here */
|
||||
int main(void) {
|
||||
uint8_t ch;
|
||||
|
||||
/*
|
||||
* Making these local and in registers prevents the need for initializing
|
||||
* them, and also saves space because code no longer stores to memory.
|
||||
* (initializing address keeps the compiler happy, but isn't really
|
||||
* necessary, and uses 4 bytes of flash.)
|
||||
*/
|
||||
register uint16_t address = 0;
|
||||
|
||||
// After the zero init loop, this is the first code to run.
|
||||
//
|
||||
// This code makes the following assumptions:
|
||||
// No interrupts will execute
|
||||
// SP points to RAMEND
|
||||
// r1 contains zero
|
||||
//
|
||||
// If not, uncomment the following instructions:
|
||||
// cli();
|
||||
asm volatile ("clr __zero_reg__");
|
||||
#ifdef __AVR_ATmega8__
|
||||
SP=RAMEND; // This is done by hardware reset
|
||||
#endif
|
||||
|
||||
// Adaboot no-wait mod
|
||||
ch = MCUSR;
|
||||
MCUSR = 0;
|
||||
|
||||
// Here, if power on, wait 0.5 secs, then check for
|
||||
// serial Rx signal low, if so, stay in bootloader
|
||||
// else go to application
|
||||
|
||||
PORTD = 0xFF ;
|
||||
PORTB = 0x3C ;
|
||||
PORTC = 1 ;
|
||||
|
||||
if (ch & (_BV(PORF) | (_BV(EXTRF)) ) )
|
||||
{
|
||||
#ifdef MULTI_CALLED
|
||||
#if F_CPU == 12000000L
|
||||
TCNT1H = 256 - 8 ;
|
||||
#else
|
||||
#if F_CPU == 16000000L
|
||||
TCNT1H = 256 - 6 ;
|
||||
#else
|
||||
TCNT1H = 256 - 127 ;
|
||||
#endif
|
||||
TCNT1L = 0 ;
|
||||
#endif
|
||||
#else
|
||||
#if F_CPU == 12000000L
|
||||
TCNT1 = 65535-5859 ;
|
||||
#else
|
||||
#if F_CPU == 16000000L
|
||||
TCNT1 = 65535-7813 ;
|
||||
#else
|
||||
TCNT1 = 65535-32767 ;
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
TCCR1B = _BV(CS12) | _BV(CS10); // div 1024
|
||||
TIFR1 = _BV(TOV1);
|
||||
while(!(TIFR1 & _BV(TOV1)))
|
||||
;
|
||||
TCCR1B = 0 ; // Stop timer
|
||||
uint8_t x ;
|
||||
x = PINB & 0x3C ;
|
||||
x |= PINC & 1 ;
|
||||
if ( x != 0x1D )
|
||||
{
|
||||
appStart() ; // Power on, go to voice application
|
||||
// if loaded
|
||||
}
|
||||
}
|
||||
|
||||
#if LED_START_FLASHES > 0
|
||||
// Set up Timer 1 for timeout counter
|
||||
TCCR1B = _BV(CS12) | _BV(CS10); // div 1024
|
||||
#endif
|
||||
|
||||
#ifndef SOFT_UART
|
||||
UART_SRA = _BV(U2X0); //Double speed mode USART0
|
||||
UART_SRB = _BV(RXEN0) | _BV(TXEN0);
|
||||
UART_SRC = _BV(UCSZ00) | _BV(UCSZ01);
|
||||
// UART_SRL = (uint8_t)( (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 );
|
||||
// Baudrate of 57600
|
||||
#if F_CPU == 12000000L
|
||||
UART_SRL = 25 ;
|
||||
#else
|
||||
#if F_CPU == 16000000L
|
||||
UART_SRL = 33 ;
|
||||
#else
|
||||
#ERROR Baud rate not available
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
// Set up watchdog to trigger after 500ms
|
||||
|
||||
|
||||
// watchdogConfig(WATCHDOG_1S);
|
||||
|
||||
/* Set LED pin as output */
|
||||
LED_DDR |= _BV(LED);
|
||||
|
||||
#ifdef SOFT_UART
|
||||
/* Set TX pin as output */
|
||||
UART_DDR |= _BV(UART_TX_BIT);
|
||||
#endif
|
||||
|
||||
#if LED_START_FLASHES > 0
|
||||
/* Flash onboard LED to signal entering of bootloader */
|
||||
flash_led(LED_START_FLASHES * 2);
|
||||
#endif
|
||||
|
||||
/* Forever loop */
|
||||
for (;;)
|
||||
{
|
||||
/* get character from UART */
|
||||
ch = getch();
|
||||
|
||||
if(ch == STK_GET_PARAMETER)
|
||||
{
|
||||
GPIOR0 = getch();
|
||||
verifySpace();
|
||||
if (GPIOR0 == 0x82)
|
||||
{
|
||||
/*
|
||||
* Send optiboot version as "minor SW version"
|
||||
*/
|
||||
putch(OPTIBOOT_MINVER);
|
||||
}
|
||||
else if (GPIOR0 == 0x81)
|
||||
{
|
||||
putch(OPTIBOOT_MAJVER);
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* GET PARAMETER returns a generic 0x03 reply for
|
||||
* other parameters - enough to keep Avrdude happy
|
||||
*/
|
||||
putch(0x03);
|
||||
}
|
||||
}
|
||||
else if(ch == STK_SET_DEVICE) {
|
||||
// SET DEVICE is ignored
|
||||
getNch(20);
|
||||
}
|
||||
else if(ch == STK_SET_DEVICE_EXT)
|
||||
{
|
||||
// SET DEVICE EXT is ignored
|
||||
getNch(5);
|
||||
}
|
||||
else if(ch == STK_LOAD_ADDRESS)
|
||||
{
|
||||
// LOAD ADDRESS
|
||||
uint16_t newAddress;
|
||||
newAddress = getch() ;
|
||||
newAddress = (newAddress & 0xff) | (getch() << 8);
|
||||
#ifdef RAMPZ
|
||||
// Transfer top bit to RAMPZ
|
||||
RAMPZ = (newAddress & 0x8000) ? 1 : 0;
|
||||
#endif
|
||||
newAddress += newAddress; // Convert from word address to byte address
|
||||
address = newAddress;
|
||||
verifySpace();
|
||||
}
|
||||
else if(ch == STK_UNIVERSAL)
|
||||
{
|
||||
// UNIVERSAL command is ignored
|
||||
getNch(4);
|
||||
putch(0x00);
|
||||
}
|
||||
/* Write memory, length is big endian and is in bytes */
|
||||
else if(ch == STK_PROG_PAGE)
|
||||
{
|
||||
// PROGRAM PAGE - we support flash programming only, not EEPROM
|
||||
uint8_t *bufPtr;
|
||||
uint16_t addrPtr;
|
||||
register uint8_t length;
|
||||
|
||||
getch(); /* getlen() */
|
||||
length = getch();
|
||||
getch();
|
||||
|
||||
// If we are in RWW section, immediately start page erase
|
||||
if (address < NRWWSTART) __boot_page_erase_short((uint16_t)(void*)address);
|
||||
|
||||
// While that is going on, read in page contents
|
||||
bufPtr = buff;
|
||||
do *bufPtr++ = getch();
|
||||
while (--length);
|
||||
|
||||
// If we are in NRWW section, page erase has to be delayed until now.
|
||||
// Todo: Take RAMPZ into account
|
||||
#ifdef MULTI_CALLED
|
||||
if (address < 0x7E00)
|
||||
#endif
|
||||
{
|
||||
if (address >= NRWWSTART) __boot_page_erase_short((uint16_t)(void*)address);
|
||||
}
|
||||
// Read command terminator, start reply
|
||||
verifySpace();
|
||||
|
||||
// If only a partial page is to be programmed, the erase might not be complete.
|
||||
// So check that here
|
||||
#ifdef MULTI_CALLED
|
||||
if (address < 0x7E00)
|
||||
#endif
|
||||
{
|
||||
boot_spm_busy_wait();
|
||||
|
||||
#ifdef VIRTUAL_BOOT_PARTITION
|
||||
if ((uint16_t)(void*)address == 0) {
|
||||
// This is the reset vector page. We need to live-patch the code so the
|
||||
// bootloader runs.
|
||||
//
|
||||
// Move RESET vector to WDT vector
|
||||
uint16_t vect = buff[0] | (buff[1]<<8);
|
||||
rstVect = vect;
|
||||
wdtVect = buff[8] | (buff[9]<<8);
|
||||
vect -= 4; // Instruction is a relative jump (rjmp), so recalculate.
|
||||
buff[8] = vect & 0xff;
|
||||
buff[9] = vect >> 8;
|
||||
|
||||
// Add jump to bootloader at RESET vector
|
||||
buff[0] = 0x7f;
|
||||
buff[1] = 0xce; // rjmp 0x1d00 instruction
|
||||
}
|
||||
#endif
|
||||
|
||||
// Copy buffer into programming buffer
|
||||
bufPtr = buff;
|
||||
addrPtr = (uint16_t)(void*)address;
|
||||
ch = SPM_PAGESIZE / 2;
|
||||
do {
|
||||
uint16_t a;
|
||||
// a = *bufPtr++;
|
||||
// a |= (*bufPtr++) << 8;
|
||||
|
||||
a = *((uint16_t *)bufPtr) ;
|
||||
bufPtr += 2 ;
|
||||
|
||||
__boot_page_fill_short((uint16_t)(void*)addrPtr,a);
|
||||
addrPtr += 2;
|
||||
} while (--ch);
|
||||
|
||||
// Write from programming buffer
|
||||
__boot_page_write_short((uint16_t)(void*)address);
|
||||
boot_spm_busy_wait();
|
||||
|
||||
#if defined(RWWSRE)
|
||||
// Reenable read access to flash
|
||||
boot_rww_enable();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
/* Read memory block mode, length is big endian. */
|
||||
else if(ch == STK_READ_PAGE)
|
||||
{
|
||||
register uint8_t length;
|
||||
// READ PAGE - we only read flash
|
||||
getch(); /* getlen() */
|
||||
length = getch();
|
||||
getch();
|
||||
|
||||
verifySpace();
|
||||
#ifdef VIRTUAL_BOOT_PARTITION
|
||||
do {
|
||||
// Undo vector patch in bottom page so verify passes
|
||||
if (address == 0) ch=rstVect & 0xff;
|
||||
else if (address == 1) ch=rstVect >> 8;
|
||||
else if (address == 8) ch=wdtVect & 0xff;
|
||||
else if (address == 9) ch=wdtVect >> 8;
|
||||
else ch = pgm_read_byte_near(address);
|
||||
address++;
|
||||
putch(ch);
|
||||
} while (--length);
|
||||
#else
|
||||
#ifdef RAMPZ
|
||||
// Since RAMPZ should already be set, we need to use EPLM directly.
|
||||
// do putch(pgm_read_byte_near(address++));
|
||||
// while (--length);
|
||||
do {
|
||||
uint8_t result;
|
||||
__asm__ ("elpm %0,Z\n":"=r"(result):"z"(address));
|
||||
putch(result);
|
||||
address++;
|
||||
}
|
||||
while (--length);
|
||||
#else
|
||||
do putch(pgm_read_byte_near(address++));
|
||||
while (--length);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Get device signature bytes */
|
||||
else if(ch == STK_READ_SIGN)
|
||||
{
|
||||
// READ SIGN - return what Avrdude wants to hear
|
||||
verifySpace();
|
||||
putch(SIGNATURE_0);
|
||||
putch(SIGNATURE_1);
|
||||
putch(SIGNATURE_2);
|
||||
}
|
||||
else if (ch == STK_LEAVE_PROGMODE) { /* 'Q' */
|
||||
// Adaboot no-wait mod
|
||||
|
||||
// watchdogConfig(WATCHDOG_16MS);
|
||||
|
||||
verifySpace();
|
||||
#ifdef MULTI_CALLED
|
||||
putch(STK_OK);
|
||||
while (!(UART_SRA & _BV(TXC0)));
|
||||
appStart() ;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
// This covers the response to commands like STK_ENTER_PROGMODE
|
||||
verifySpace();
|
||||
}
|
||||
putch(STK_OK);
|
||||
}
|
||||
}
|
||||
|
||||
void putch(char ch) {
|
||||
#ifndef SOFT_UART
|
||||
while (!(UART_SRA & _BV(UDRE0)));
|
||||
UART_UDR = ch;
|
||||
#else
|
||||
__asm__ __volatile__ (
|
||||
" com %[ch]\n" // ones complement, carry set
|
||||
" sec\n"
|
||||
"1: brcc 2f\n"
|
||||
" cbi %[uartPort],%[uartBit]\n"
|
||||
" rjmp 3f\n"
|
||||
"2: sbi %[uartPort],%[uartBit]\n"
|
||||
" nop\n"
|
||||
"3: rcall uartDelay\n"
|
||||
" rcall uartDelay\n"
|
||||
" lsr %[ch]\n"
|
||||
" dec %[bitcnt]\n"
|
||||
" brne 1b\n"
|
||||
:
|
||||
:
|
||||
[bitcnt] "d" (10),
|
||||
[ch] "r" (ch),
|
||||
[uartPort] "I" (_SFR_IO_ADDR(UART_PORT)),
|
||||
[uartBit] "I" (UART_TX_BIT)
|
||||
:
|
||||
"r25"
|
||||
);
|
||||
#endif
|
||||
}
|
||||
|
||||
uint8_t getch(void) {
|
||||
uint8_t ch;
|
||||
|
||||
#ifdef LED_DATA_FLASH
|
||||
#ifdef __AVR_ATmega8__
|
||||
LED_PORT ^= _BV(LED);
|
||||
#else
|
||||
LED_PIN |= _BV(LED);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef SOFT_UART
|
||||
__asm__ __volatile__ (
|
||||
"1: sbic %[uartPin],%[uartBit]\n" // Wait for start edge
|
||||
" rjmp 1b\n"
|
||||
" rcall uartDelay\n" // Get to middle of start bit
|
||||
"2: rcall uartDelay\n" // Wait 1 bit period
|
||||
" rcall uartDelay\n" // Wait 1 bit period
|
||||
" clc\n"
|
||||
" sbic %[uartPin],%[uartBit]\n"
|
||||
" sec\n"
|
||||
" dec %[bitCnt]\n"
|
||||
" breq 3f\n"
|
||||
" ror %[ch]\n"
|
||||
" rjmp 2b\n"
|
||||
"3:\n"
|
||||
:
|
||||
[ch] "=r" (ch)
|
||||
:
|
||||
[bitCnt] "d" (9),
|
||||
[uartPin] "I" (_SFR_IO_ADDR(UART_PIN)),
|
||||
[uartBit] "I" (UART_RX_BIT)
|
||||
:
|
||||
"r25"
|
||||
);
|
||||
#else
|
||||
while(!(UART_SRA & _BV(RXC0)))
|
||||
|
||||
// watchdogReset()
|
||||
|
||||
;
|
||||
// if (!(UART_SRA & _BV(FE0))) {
|
||||
/*
|
||||
* A Framing Error indicates (probably) that something is talking
|
||||
* to us at the wrong bit rate. Assume that this is because it
|
||||
* expects to be talking to the application, and DON'T reset the
|
||||
* watchdog. This should cause the bootloader to abort and run
|
||||
* the application "soon", if it keeps happening. (Note that we
|
||||
* don't care that an invalid char is returned...)
|
||||
*/
|
||||
// watchdogReset();
|
||||
// }
|
||||
|
||||
ch = UART_UDR;
|
||||
#endif
|
||||
|
||||
#ifdef LED_DATA_FLASH
|
||||
#ifdef __AVR_ATmega8__
|
||||
LED_PORT ^= _BV(LED);
|
||||
#else
|
||||
LED_PIN |= _BV(LED);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
return ch;
|
||||
}
|
||||
|
||||
#ifdef SOFT_UART
|
||||
// AVR305 equation: #define UART_B_VALUE (((F_CPU/BAUD_RATE)-23)/6)
|
||||
// Adding 3 to numerator simulates nearest rounding for more accurate baud rates
|
||||
#define UART_B_VALUE (((F_CPU/BAUD_RATE)-20)/6)
|
||||
#if UART_B_VALUE > 255
|
||||
#error Baud rate too slow for soft UART
|
||||
#endif
|
||||
|
||||
void uartDelay() {
|
||||
__asm__ __volatile__ (
|
||||
"ldi r25,%[count]\n"
|
||||
"1:dec r25\n"
|
||||
"brne 1b\n"
|
||||
"ret\n"
|
||||
::[count] "M" (UART_B_VALUE)
|
||||
);
|
||||
}
|
||||
#endif
|
||||
|
||||
void getNch(uint8_t count) {
|
||||
do getch(); while (--count);
|
||||
verifySpace();
|
||||
}
|
||||
|
||||
void verifySpace()
|
||||
{
|
||||
if ( getch() != CRC_EOP) {
|
||||
|
||||
putch(STK_NOSYNC);
|
||||
// watchdogConfig(WATCHDOG_16MS); // shorten WD timeout
|
||||
//
|
||||
// while (1) // and busy-loop so that WD causes
|
||||
// ; // a reset and app start.
|
||||
}
|
||||
putch(STK_INSYNC);
|
||||
}
|
||||
|
||||
#if LED_START_FLASHES > 0
|
||||
void flash_led(uint8_t count) {
|
||||
do {
|
||||
TCNT1 = -(F_CPU/(1024*16));
|
||||
TIFR1 = _BV(TOV1);
|
||||
while(!(TIFR1 & _BV(TOV1)));
|
||||
//#ifdef __AVR_ATmega8__
|
||||
LED_PORT ^= _BV(LED);
|
||||
//#else
|
||||
// LED_PIN |= _BV(LED);
|
||||
//#endif
|
||||
watchdogReset();
|
||||
} while (--count);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Watchdog functions. These are only safe with interrupts turned off.
|
||||
void watchdogReset() {
|
||||
__asm__ __volatile__ (
|
||||
"wdr\n"
|
||||
);
|
||||
}
|
||||
|
||||
void watchdogConfig(uint8_t x) {
|
||||
WDTCSR = _BV(WDCE) | _BV(WDE);
|
||||
WDTCSR = x;
|
||||
}
|
||||
|
||||
void appStart()
|
||||
{
|
||||
// watchdogConfig(WATCHDOG_OFF);
|
||||
// __asm__ __volatile__ (
|
||||
//#ifdef VIRTUAL_BOOT_PARTITION
|
||||
// // Jump to WDT vector
|
||||
// "ldi r30,4\n"
|
||||
// "clr r31\n"
|
||||
//#else
|
||||
// // Jump to RST vector
|
||||
// "clr r30\n"
|
||||
// "clr r31\n"
|
||||
//#endif
|
||||
// "ijmp\n"
|
||||
// );
|
||||
|
||||
register void (*p)() ;
|
||||
p = 0 ;
|
||||
|
||||
if ( pgm_read_byte( (uint16_t)p ) != 0xFF )
|
||||
{
|
||||
(*p)() ;
|
||||
}
|
||||
}
|
||||
|
||||
80
BootLoaders/AtmegaMultiBoot/Source/pin_defs.h
Normal file
@@ -0,0 +1,80 @@
|
||||
#if defined(__AVR_ATmega168__) || defined(__AVR_ATmega328P__) || defined(__AVR_ATmega328__) || defined(__AVR_ATmega88) || defined(__AVR_ATmega8__) || defined(__AVR_ATmega88__)
|
||||
/* Onboard LED is connected to pin PB5 in Arduino NG, Diecimila, and Duemilanove */
|
||||
#define LED_DDR DDRB
|
||||
#define LED_PORT PORTB
|
||||
#define LED_PIN PINB
|
||||
#define LED PINB5
|
||||
|
||||
/* Ports for soft UART */
|
||||
#ifdef SOFT_UART
|
||||
#define UART_PORT PORTD
|
||||
#define UART_PIN PIND
|
||||
#define UART_DDR DDRD
|
||||
#define UART_TX_BIT 1
|
||||
#define UART_RX_BIT 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(__AVR_ATmega8__)
|
||||
//Name conversion R.Wiersma
|
||||
#define UCSR0A UCSRA
|
||||
#define UDR0 UDR
|
||||
#define UDRE0 UDRE
|
||||
#define RXC0 RXC
|
||||
#define FE0 FE
|
||||
#define TIFR1 TIFR
|
||||
#define WDTCSR WDTCR
|
||||
#endif
|
||||
|
||||
/* Luminet support */
|
||||
#if defined(__AVR_ATtiny84__)
|
||||
/* Red LED is connected to pin PA4 */
|
||||
#define LED_DDR DDRA
|
||||
#define LED_PORT PORTA
|
||||
#define LED_PIN PINA
|
||||
#define LED PINA4
|
||||
/* Ports for soft UART - left port only for now. TX/RX on PA2/PA3 */
|
||||
#ifdef SOFT_UART
|
||||
#define UART_PORT PORTA
|
||||
#define UART_PIN PINA
|
||||
#define UART_DDR DDRA
|
||||
#define UART_TX_BIT 2
|
||||
#define UART_RX_BIT 3
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Sanguino support */
|
||||
#if defined(__AVR_ATmega644P__) || defined(__AVR_ATmega1284P__)
|
||||
/* Onboard LED is connected to pin PB0 on Sanguino */
|
||||
#define LED_DDR DDRB
|
||||
#define LED_PORT PORTB
|
||||
#define LED_PIN PINB
|
||||
#define LED PINB0
|
||||
|
||||
/* Ports for soft UART */
|
||||
#ifdef SOFT_UART
|
||||
#define UART_PORT PORTD
|
||||
#define UART_PIN PIND
|
||||
#define UART_DDR DDRD
|
||||
#define UART_TX_BIT 1
|
||||
#define UART_RX_BIT 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Mega support */
|
||||
#if defined(__AVR_ATmega1280__)
|
||||
/* Onboard LED is connected to pin PB7 on Arduino Mega */
|
||||
#define LED_DDR DDRB
|
||||
#define LED_PORT PORTB
|
||||
#define LED_PIN PINB
|
||||
#define LED PINB7
|
||||
|
||||
/* Ports for soft UART */
|
||||
#ifdef SOFT_UART
|
||||
#define UART_PORT PORTE
|
||||
#define UART_PIN PINE
|
||||
#define UART_DDR DDRE
|
||||
#define UART_TX_BIT 1
|
||||
#define UART_RX_BIT 0
|
||||
#endif
|
||||
#endif
|
||||
39
BootLoaders/AtmegaMultiBoot/Source/stk500.h
Normal file
@@ -0,0 +1,39 @@
|
||||
/* STK500 constants list, from AVRDUDE */
|
||||
#define STK_OK 0x10
|
||||
#define STK_FAILED 0x11 // Not used
|
||||
#define STK_UNKNOWN 0x12 // Not used
|
||||
#define STK_NODEVICE 0x13 // Not used
|
||||
#define STK_INSYNC 0x14 // ' '
|
||||
#define STK_NOSYNC 0x15 // Not used
|
||||
#define ADC_CHANNEL_ERROR 0x16 // Not used
|
||||
#define ADC_MEASURE_OK 0x17 // Not used
|
||||
#define PWM_CHANNEL_ERROR 0x18 // Not used
|
||||
#define PWM_ADJUST_OK 0x19 // Not used
|
||||
#define CRC_EOP 0x20 // 'SPACE'
|
||||
#define STK_GET_SYNC 0x30 // '0'
|
||||
#define STK_GET_SIGN_ON 0x31 // '1'
|
||||
#define STK_SET_PARAMETER 0x40 // '@'
|
||||
#define STK_GET_PARAMETER 0x41 // 'A'
|
||||
#define STK_SET_DEVICE 0x42 // 'B'
|
||||
#define STK_SET_DEVICE_EXT 0x45 // 'E'
|
||||
#define STK_ENTER_PROGMODE 0x50 // 'P'
|
||||
#define STK_LEAVE_PROGMODE 0x51 // 'Q'
|
||||
#define STK_CHIP_ERASE 0x52 // 'R'
|
||||
#define STK_CHECK_AUTOINC 0x53 // 'S'
|
||||
#define STK_LOAD_ADDRESS 0x55 // 'U'
|
||||
#define STK_UNIVERSAL 0x56 // 'V'
|
||||
#define STK_PROG_FLASH 0x60 // '`'
|
||||
#define STK_PROG_DATA 0x61 // 'a'
|
||||
#define STK_PROG_FUSE 0x62 // 'b'
|
||||
#define STK_PROG_LOCK 0x63 // 'c'
|
||||
#define STK_PROG_PAGE 0x64 // 'd'
|
||||
#define STK_PROG_FUSE_EXT 0x65 // 'e'
|
||||
#define STK_READ_FLASH 0x70 // 'p'
|
||||
#define STK_READ_DATA 0x71 // 'q'
|
||||
#define STK_READ_FUSE 0x72 // 'r'
|
||||
#define STK_READ_LOCK 0x73 // 's'
|
||||
#define STK_READ_PAGE 0x74 // 't'
|
||||
#define STK_READ_SIGN 0x75 // 'u'
|
||||
#define STK_READ_OSCCAL 0x76 // 'v'
|
||||
#define STK_READ_FUSE_EXT 0x77 // 'w'
|
||||
#define STK_READ_OSCCAL_EXT 0x78 // 'x'
|
||||
5
BootLoaders/Boards/Linux/45-maple.rules
Normal file
@@ -0,0 +1,5 @@
|
||||
ATTRS{idProduct}=="1001", ATTRS{idVendor}=="0110", MODE="664", GROUP="plugdev"
|
||||
ATTRS{idProduct}=="1002", ATTRS{idVendor}=="0110", MODE="664", GROUP="plugdev"
|
||||
ATTRS{idProduct}=="0003", ATTRS{idVendor}=="1eaf", MODE="664", GROUP="plugdev" SYMLINK+="maple", ENV{ID_MM_DEVICE_IGNORE}="1"
|
||||
ATTRS{idProduct}=="0004", ATTRS{idVendor}=="1eaf", MODE="664", GROUP="plugdev" SYMLINK+="maple", ENV{ID_MM_DEVICE_IGNORE}="1"
|
||||
|
||||
11
BootLoaders/Boards/Windows/install_drivers.bat
Normal file
@@ -0,0 +1,11 @@
|
||||
@echo off
|
||||
|
||||
echo Installing MULTI-Module DFU Bootloader Driver...
|
||||
"%~dp0wdi-simple" --vid 0x1EAF --pid 0x0003 --type 2 --name "MULTI-Module DFU Bootloader" --dest "%~dp0MULTI-DFU-Bootloader" -b
|
||||
echo.
|
||||
|
||||
echo Installing MULTI-Module USB Serial Driver...
|
||||
"%~dp0wdi-simple" --vid 0x1EAF --pid 0x0004 --type 3 --name "MULTI-Module USB Serial" --dest "%~dp0MULTI-USB-Serial" -b
|
||||
echo.
|
||||
|
||||
pause
|
||||
BIN
BootLoaders/Boards/Windows/wdi-simple.exe
Normal file
47
BootLoaders/OrangeMultiBoot/OrangeMultiBoot.hex
Normal file
@@ -0,0 +1,47 @@
|
||||
:108000001F92CDB7DEB7CFD01124809178009FEFBB
|
||||
:1080100090937800837099F088EA91E680936808DD
|
||||
:108020009093690880E180934C0880914C0884FF0C
|
||||
:10803000FCCF109240088091680682FD8FD082E0CC
|
||||
:1080400080936106C12CD12C97D0813479F494D0DF
|
||||
:10805000898399D08981823811F485E005C08138FF
|
||||
:1080600011F484E001C083E080D075C0823411F443
|
||||
:1080700084E103C0853419F485E08CD06CC085356B
|
||||
:1080800059F47AD0C82E78D0D12CD82A8D2D881FBB
|
||||
:108090008827881F8BBF5EC0863521F484E07AD0A4
|
||||
:1080A00080E0E2CF843641F567D066D0F82E64D008
|
||||
:1080B000C601DCD000E010E25FD0F80181938F01AF
|
||||
:1080C000FE12FACF60D0D7FC46C0CBD0C601DAD0C2
|
||||
:1080D000760100E010E2F801619171918F01C70112
|
||||
:1080E000DBD0F2E0EF0EF11C011581E2180799F7E1
|
||||
:1080F000C601E0D0B6D02FC08437C1F43DD03CD00B
|
||||
:10810000F82E3AD040D0F601EC2CEF0C8F010F5F27
|
||||
:108110001F4F84912AD0E01207C0EFEFCE1ADE0A7B
|
||||
:10812000FA94CF0CD11C17C0F801F0CF853739F481
|
||||
:108130002AD08EE11AD085E918D082E495CF813516
|
||||
:1081400049F421D080E111D08091A10886FFFCCFB5
|
||||
:1081500005D001C018D080E108D076CFE0E0F0E093
|
||||
:1081600084918F3F09F0099408959091A10895FF9B
|
||||
:10817000FCCF8093A00808958091A10887FFFCCFD1
|
||||
:108180008091A0080895F8DF803211F085E1EDDFDD
|
||||
:1081900084E1EBCFCF93C82FEFDFC150E9F7CF9148
|
||||
:1081A000F2CFA895089583EC8093520080915000FF
|
||||
:1081B0008860809350008091510083FFFCCF82EC57
|
||||
:1081C0008093550080915000806180935000809191
|
||||
:1081D000510084FFFCCF88ED84BF1092400084BF23
|
||||
:1081E00024E02093400087E08093A20087E88093FA
|
||||
:1081F0008301109241081092420810924308109295
|
||||
:10820000440810924608109247088FEF9FEF809322
|
||||
:1082100066089093670810926008109261088BE0DE
|
||||
:1082200080934008209365062093620688E180933E
|
||||
:10823000720698E0909345069093410692E29093DF
|
||||
:10824000A6081092A7088093A4088091A3088F7CA9
|
||||
:1082500080618093A30883E08093A5088091A008A3
|
||||
:1082600008958091CF0187FDFCCF08958F939F9350
|
||||
:1082700082E2E0ECF1E08287FF91EF918DE984BF2B
|
||||
:10828000E8950895FC0186E28093CA0188ED84BFD9
|
||||
:1082900081E08093CB0108950F921F92FC01062E7E
|
||||
:1082A000172E83E28093CA018DE984BFE8951F9061
|
||||
:1082B0000F900895FC018EE28093CA018DE984BF7E
|
||||
:0482C000E8950895A0
|
||||
:040000030000800079
|
||||
:00000001FF
|
||||
503
BootLoaders/OrangeMultiBoot/Source/Makefile
Normal file
@@ -0,0 +1,503 @@
|
||||
# Makefile for ATmegaBOOT
|
||||
# E.Lins, 18.7.2005
|
||||
# $Id$
|
||||
#
|
||||
# Instructions
|
||||
#
|
||||
# To make bootloader .hex file:
|
||||
# make diecimila
|
||||
# make lilypad
|
||||
# make ng
|
||||
# etc...
|
||||
#
|
||||
# To burn bootloader .hex file:
|
||||
# make diecimila_isp
|
||||
# make lilypad_isp
|
||||
# make ng_isp
|
||||
# etc...
|
||||
|
||||
# program name should not be changed...
|
||||
PROGRAM = optiboot
|
||||
|
||||
# The default behavior is to build using tools that are in the users
|
||||
# current path variables, but we can also build using an installed
|
||||
# Arduino user IDE setup, or the Arduino source tree.
|
||||
# Uncomment this next lines to build within the arduino environment,
|
||||
# using the arduino-included avrgcc toolset (mac and pc)
|
||||
# ENV ?= arduino
|
||||
# ENV ?= arduinodev
|
||||
# OS ?= macosx
|
||||
# OS ?= windows
|
||||
|
||||
|
||||
# enter the parameters for the avrdude isp tool -b19200
|
||||
#
|
||||
# These are the parameters for a usb-based STK500v2 programmer.
|
||||
# Exact type unknown. (historical Makefile values.)
|
||||
ISPTOOL = stk500v2
|
||||
ISPPORT = usb
|
||||
ISPSPEED = -b 57600
|
||||
#
|
||||
#
|
||||
# These are parameters for using an Arduino with the ArduinoISP sketch
|
||||
# as the programmer. On a mac, for a particular Uno as programmer.
|
||||
#ISPTOOL = stk500v1 -C /Applications/arduino/arduino-0022/hardware/tools/avr/etc/avrdude.conf
|
||||
#ISPPORT = /dev/tty.usbmodemfd3141
|
||||
#ISPSPEED = -b19200
|
||||
|
||||
MCU_TARGET = atmega168
|
||||
LDSECTIONS = -Wl,--section-start=.text=0x3e00 -Wl,--section-start=.version=0x3ffe
|
||||
|
||||
# Build environments
|
||||
# Start of some ugly makefile-isms to allow optiboot to be built
|
||||
# in several different environments. See the README.TXT file for
|
||||
# details.
|
||||
|
||||
# default
|
||||
fixpath = $(1)
|
||||
|
||||
ifeq ($(ENV), arduino)
|
||||
# For Arduino, we assume that we're connected to the optiboot directory
|
||||
# included with the arduino distribution, which means that the full set
|
||||
# of avr-tools are "right up there" in standard places.
|
||||
TOOLROOT = ../../../tools
|
||||
GCCROOT = $(TOOLROOT)/avr/bin/
|
||||
AVRDUDE_CONF = -C$(TOOLROOT)/avr/etc/avrdude.conf
|
||||
|
||||
ifeq ($(OS), windows)
|
||||
# On windows, SOME of the tool paths will need to have backslashes instead
|
||||
# of forward slashes (because they use windows cmd.exe for execution instead
|
||||
# of a unix/mingw shell?) We also have to ensure that a consistent shell
|
||||
# is used even if a unix shell is installed (ie as part of WINAVR)
|
||||
fixpath = $(subst /,\,$1)
|
||||
SHELL = cmd.exe
|
||||
endif
|
||||
|
||||
else ifeq ($(ENV), arduinodev)
|
||||
# Arduino IDE source code environment. Use the unpacked compilers created
|
||||
# by the build (you'll need to do "ant build" first.)
|
||||
ifeq ($(OS), macosx)
|
||||
TOOLROOT = ../../../../build/macosx/work/Arduino.app/Contents/Resources/Java/hardware/tools
|
||||
endif
|
||||
ifeq ($(OS), windows)
|
||||
TOOLROOT = ../../../../build/windows/work/hardware/tools
|
||||
endif
|
||||
|
||||
GCCROOT = $(TOOLROOT)/avr/bin/
|
||||
AVRDUDE_CONF = -C$(TOOLROOT)/avr/etc/avrdude.conf
|
||||
|
||||
else
|
||||
GCCROOT =
|
||||
AVRDUDE_CONF =
|
||||
endif
|
||||
#
|
||||
# End of build environment code.
|
||||
|
||||
|
||||
# the efuse should really be 0xf8; since, however, only the lower
|
||||
# three bits of that byte are used on the atmega168, avrdude gets
|
||||
# confused if you specify 1's for the higher bits, see:
|
||||
# http://tinker.it/now/2007/02/24/the-tale-of-avrdude-atmega168-and-extended-bits-fuses/
|
||||
#
|
||||
# similarly, the lock bits should be 0xff instead of 0x3f (to
|
||||
# unlock the bootloader section) and 0xcf instead of 0x2f (to
|
||||
# lock it), but since the high two bits of the lock byte are
|
||||
# unused, avrdude would get confused.
|
||||
|
||||
ISPFUSES = $(GCCROOT)avrdude $(AVRDUDE_CONF) -c $(ISPTOOL) \
|
||||
-p $(MCU_TARGET) -P $(ISPPORT) $(ISPSPEED) \
|
||||
-e -u -U lock:w:0x3f:m -U efuse:w:0x$(EFUSE):m \
|
||||
-U hfuse:w:0x$(HFUSE):m -U lfuse:w:0x$(LFUSE):m
|
||||
ISPFLASH = $(GCCROOT)avrdude $(AVRDUDE_CONF) -c $(ISPTOOL) \
|
||||
-p $(MCU_TARGET) -P $(ISPPORT) $(ISPSPEED) \
|
||||
-U flash:w:$(PROGRAM)_$(TARGET).hex -U lock:w:0x2f:m
|
||||
|
||||
STK500 = "C:\Program Files\Atmel\AVR Tools\STK500\Stk500.exe"
|
||||
STK500-1 = $(STK500) -e -d$(MCU_TARGET) -pf -vf -if$(PROGRAM)_$(TARGET).hex \
|
||||
-lFF -LFF -f$(HFUSE)$(LFUSE) -EF8 -ms -q -cUSB -I200kHz -s -wt
|
||||
STK500-2 = $(STK500) -d$(MCU_TARGET) -ms -q -lCF -LCF -cUSB -I200kHz -s -wt
|
||||
|
||||
OBJ = $(PROGRAM).o
|
||||
OPTIMIZE = -Os -fno-inline-small-functions -fno-split-wide-types
|
||||
# -mshort-calls
|
||||
|
||||
DEFS =
|
||||
LIBS =
|
||||
|
||||
CC = $(GCCROOT)avr-gcc
|
||||
|
||||
# Override is only needed by avr-lib build system.
|
||||
|
||||
override CFLAGS = -g -Wall $(OPTIMIZE) -mmcu=$(MCU_TARGET) -DF_CPU=$(AVR_FREQ) $(DEFS)
|
||||
override LDFLAGS = $(LDSECTIONS) -Wl,--relax -Wl,--gc-sections -nostartfiles -nostdlib
|
||||
|
||||
OBJCOPY = $(GCCROOT)avr-objcopy
|
||||
OBJDUMP = $(call fixpath,$(GCCROOT)avr-objdump)
|
||||
|
||||
SIZE = $(GCCROOT)avr-size
|
||||
|
||||
|
||||
|
||||
#Voice board test
|
||||
# ATmega328
|
||||
#
|
||||
#atmega328: TARGET = atmega328p
|
||||
#atmega328: MCU_TARGET = atmega328p
|
||||
#atmega328: CFLAGS += '-DLED_START_FLASHES=0' '-DBAUD_RATE=38400'
|
||||
#atmega328: AVR_FREQ = 12000000L
|
||||
#atmega328: LDSECTIONS = -Wl,--section-start=.text=0x7e00 -Wl,--section-start=.version=0x7ffe
|
||||
#atmega328: $(PROGRAM)_atmega328.hex
|
||||
#atmega328: $(PROGRAM)_atmega328.lst
|
||||
|
||||
xmega32D4: TARGET = atxmega32d4
|
||||
xmega32D4: MCU_TARGET = atxmega32d4
|
||||
xmega32D4: CFLAGS += '-DLED_START_FLASHES=0' '-DBAUD_RATE=57600'
|
||||
xmega32D4: AVR_FREQ = 32000000L
|
||||
xmega32D4: LDSECTIONS = -Wl,--section-start=.text=0x8000
|
||||
xmega32D4: $(PROGRAM)_xmega32d4.hex
|
||||
xmega32D4: $(PROGRAM)_xmega32d4.lst
|
||||
|
||||
atmega328: TARGET = atmega328
|
||||
atmega328: MCU_TARGET = atmega328p
|
||||
atmega328: CFLAGS += '-DLED_START_FLASHES=0' '-DBAUD_RATE=57600'
|
||||
atmega328: AVR_FREQ = 16000000L
|
||||
atmega328: LDSECTIONS = -Wl,--section-start=.text=0x7e00 -Wl,--section-start=.version=0x7ffe
|
||||
atmega328: $(PROGRAM)_atmega328_16.hex
|
||||
atmega328: $(PROGRAM)_atmega328_16.lst
|
||||
|
||||
|
||||
# Test platforms
|
||||
# Virtual boot block test
|
||||
virboot328: TARGET = atmega328
|
||||
virboot328: MCU_TARGET = atmega328p
|
||||
virboot328: CFLAGS += '-DLED_START_FLASHES=3' '-DBAUD_RATE=38400' '-DVIRTUAL_BOOT'
|
||||
virboot328: AVR_FREQ = 16000000L
|
||||
virboot328: LDSECTIONS = -Wl,--section-start=.text=0x7e00 -Wl,--section-start=.version=0x7ffe
|
||||
virboot328: $(PROGRAM)_atmega328.hex
|
||||
virboot328: $(PROGRAM)_atmega328.lst
|
||||
|
||||
# 20MHz clocked platforms
|
||||
#
|
||||
# These are capable of 230400 baud, or 38400 baud on PC (Arduino Avrdude issue)
|
||||
#
|
||||
|
||||
pro20: TARGET = pro_20mhz
|
||||
pro20: MCU_TARGET = atmega168
|
||||
pro20: CFLAGS += '-DLED_START_FLASHES=3' '-DBAUD_RATE=38400'
|
||||
pro20: AVR_FREQ = 20000000L
|
||||
pro20: $(PROGRAM)_pro_20mhz.hex
|
||||
pro20: $(PROGRAM)_pro_20mhz.lst
|
||||
|
||||
pro20_isp: pro20
|
||||
pro20_isp: TARGET = pro_20mhz
|
||||
# 2.7V brownout
|
||||
pro20_isp: HFUSE = DD
|
||||
# Full swing xtal (20MHz) 258CK/14CK+4.1ms
|
||||
pro20_isp: LFUSE = C6
|
||||
# 512 byte boot
|
||||
pro20_isp: EFUSE = 04
|
||||
pro20_isp: isp
|
||||
|
||||
# 16MHz clocked platforms
|
||||
#
|
||||
# These are capable of 230400 baud, or 38400 baud on PC (Arduino Avrdude issue)
|
||||
#
|
||||
|
||||
pro16: TARGET = pro_16MHz
|
||||
pro16: MCU_TARGET = atmega168
|
||||
pro16: CFLAGS += '-DLED_START_FLASHES=3' '-DBAUD_RATE=38400'
|
||||
pro16: AVR_FREQ = 16000000L
|
||||
pro16: $(PROGRAM)_pro_16MHz.hex
|
||||
pro16: $(PROGRAM)_pro_16MHz.lst
|
||||
|
||||
pro16_isp: pro16
|
||||
pro16_isp: TARGET = pro_16MHz
|
||||
# 2.7V brownout
|
||||
pro16_isp: HFUSE = DD
|
||||
# Full swing xtal (20MHz) 258CK/14CK+4.1ms
|
||||
pro16_isp: LFUSE = C6
|
||||
# 512 byte boot
|
||||
pro16_isp: EFUSE = 04
|
||||
pro16_isp: isp
|
||||
|
||||
# Diecimila, Duemilanove with m168, and NG use identical bootloaders
|
||||
# Call it "atmega168" for generality and clarity, keep "diecimila" for
|
||||
# backward compatibility of makefile
|
||||
#
|
||||
atmega168: TARGET = atmega168
|
||||
atmega168: MCU_TARGET = atmega168
|
||||
atmega168: CFLAGS += '-DLED_START_FLASHES=0' '-DBAUD_RATE=38400'
|
||||
atmega168: AVR_FREQ = 12000000L
|
||||
atmega168: $(PROGRAM)_atmega168.hex
|
||||
atmega168: $(PROGRAM)_atmega168.lst
|
||||
|
||||
atmega168_isp: atmega168
|
||||
atmega168_isp: TARGET = atmega168
|
||||
# 2.7V brownout
|
||||
atmega168_isp: HFUSE = DD
|
||||
# Low power xtal (16MHz) 16KCK/14CK+65ms
|
||||
atmega168_isp: LFUSE = FF
|
||||
# 512 byte boot
|
||||
atmega168_isp: EFUSE = 04
|
||||
atmega168_isp: isp
|
||||
|
||||
diecimila: TARGET = diecimila
|
||||
diecimila: MCU_TARGET = atmega168
|
||||
diecimila: CFLAGS += '-DLED_START_FLASHES=3' '-DBAUD_RATE=38400'
|
||||
diecimila: AVR_FREQ = 16000000L
|
||||
diecimila: $(PROGRAM)_diecimila.hex
|
||||
diecimila: $(PROGRAM)_diecimila.lst
|
||||
|
||||
diecimila_isp: diecimila
|
||||
diecimila_isp: TARGET = diecimila
|
||||
# 2.7V brownout
|
||||
diecimila_isp: HFUSE = DD
|
||||
# Low power xtal (16MHz) 16KCK/14CK+65ms
|
||||
diecimila_isp: LFUSE = FF
|
||||
# 512 byte boot
|
||||
diecimila_isp: EFUSE = 04
|
||||
diecimila_isp: isp
|
||||
|
||||
atmega328_isp: atmega328
|
||||
atmega328_isp: TARGET = atmega328
|
||||
atmega328_isp: MCU_TARGET = atmega328p
|
||||
# 512 byte boot, SPIEN
|
||||
atmega328_isp: HFUSE = DE
|
||||
# Low power xtal (16MHz) 16KCK/14CK+65ms
|
||||
atmega328_isp: LFUSE = FF
|
||||
# 2.7V brownout
|
||||
atmega328_isp: EFUSE = FD
|
||||
atmega328_isp: isp
|
||||
|
||||
atmega1284: TARGET = atmega1284p
|
||||
atmega1284: MCU_TARGET = atmega1284p
|
||||
atmega1284: CFLAGS += '-DLED_START_FLASHES=3' '-DBAUD_RATE=38400' '-DBIGBOOT'
|
||||
atmega1284: AVR_FREQ = 16000000L
|
||||
atmega1284: LDSECTIONS = -Wl,--section-start=.text=0x1fc00 -Wl,--section-start=.version=0x1fffe
|
||||
atmega1284: $(PROGRAM)_atmega1284p.hex
|
||||
atmega1284: $(PROGRAM)_atmega1284p.lst
|
||||
|
||||
atmega1284_isp: atmega1284
|
||||
atmega1284_isp: TARGET = atmega1284p
|
||||
atmega1284_isp: MCU_TARGET = atmega1284p
|
||||
# 1024 byte boot
|
||||
atmega1284_isp: HFUSE = DE
|
||||
# Low power xtal (16MHz) 16KCK/14CK+65ms
|
||||
atmega1284_isp: LFUSE = FF
|
||||
# 2.7V brownout
|
||||
atmega1284_isp: EFUSE = FD
|
||||
atmega1284_isp: isp
|
||||
|
||||
# Sanguino has a minimum boot size of 1024 bytes, so enable extra functions
|
||||
#
|
||||
sanguino: TARGET = atmega644p
|
||||
sanguino: MCU_TARGET = atmega644p
|
||||
sanguino: CFLAGS += '-DLED_START_FLASHES=3' '-DBAUD_RATE=38400' '-DBIGBOOT'
|
||||
sanguino: AVR_FREQ = 16000000L
|
||||
sanguino: LDSECTIONS = -Wl,--section-start=.text=0xfc00 -Wl,--section-start=.version=0xfffe
|
||||
sanguino: $(PROGRAM)_atmega644p.hex
|
||||
sanguino: $(PROGRAM)_atmega644p.lst
|
||||
|
||||
sanguino_isp: sanguino
|
||||
sanguino_isp: TARGET = atmega644p
|
||||
sanguino_isp: MCU_TARGET = atmega644p
|
||||
# 1024 byte boot
|
||||
sanguino_isp: HFUSE = DE
|
||||
# Low power xtal (16MHz) 16KCK/14CK+65ms
|
||||
sanguino_isp: LFUSE = FF
|
||||
# 2.7V brownout
|
||||
sanguino_isp: EFUSE = FD
|
||||
sanguino_isp: isp
|
||||
|
||||
# Mega has a minimum boot size of 1024 bytes, so enable extra functions
|
||||
#mega: TARGET = atmega1280
|
||||
mega1280: MCU_TARGET = atmega1280
|
||||
mega1280: CFLAGS += '-DLED_START_FLASHES=3' '-DBAUD_RATE=38400' '-DBIGBOOT'
|
||||
mega1280: AVR_FREQ = 16000000L
|
||||
mega1280: LDSECTIONS = -Wl,--section-start=.text=0x1fc00 -Wl,--section-start=.version=0x1fffe
|
||||
mega1280: $(PROGRAM)_atmega1280.hex
|
||||
mega1280: $(PROGRAM)_atmega1280.lst
|
||||
|
||||
mega1280_isp: mega
|
||||
mega1280_isp: TARGET = atmega1280
|
||||
mega1280_isp: MCU_TARGET = atmega1280
|
||||
# 1024 byte boot
|
||||
mega1280_isp: HFUSE = DE
|
||||
# Low power xtal (16MHz) 16KCK/14CK+65ms
|
||||
mega1280_isp: LFUSE = FF
|
||||
# 2.7V brownout
|
||||
mega1280_isp: EFUSE = FD
|
||||
mega1280_isp: isp
|
||||
|
||||
# ATmega8
|
||||
#
|
||||
atmega8: TARGET = atmega8
|
||||
atmega8: MCU_TARGET = atmega8
|
||||
atmega8: CFLAGS += '-DLED_START_FLASHES=3' '-DBAUD_RATE=38400'
|
||||
atmega8: AVR_FREQ = 16000000L
|
||||
atmega8: LDSECTIONS = -Wl,--section-start=.text=0x1e00 -Wl,--section-start=.version=0x1ffe
|
||||
atmega8: $(PROGRAM)_atmega8.hex
|
||||
atmega8: $(PROGRAM)_atmega8.lst
|
||||
|
||||
atmega8_isp: atmega8
|
||||
atmega8_isp: TARGET = atmega8
|
||||
atmega8_isp: MCU_TARGET = atmega8
|
||||
# SPIEN, CKOPT, Bootsize=512B
|
||||
atmega8_isp: HFUSE = CC
|
||||
# 2.7V brownout, Low power xtal (16MHz) 16KCK/14CK+65ms
|
||||
atmega8_isp: LFUSE = BF
|
||||
atmega8_isp: isp
|
||||
|
||||
# ATmega88
|
||||
#
|
||||
atmega88: TARGET = atmega88
|
||||
atmega88: MCU_TARGET = atmega88
|
||||
atmega88: CFLAGS += '-DLED_START_FLASHES=0' '-DBAUD_RATE=38400'
|
||||
atmega88: AVR_FREQ = 12000000L
|
||||
atmega88: LDSECTIONS = -Wl,--section-start=.text=0x1e00 -Wl,--section-start=.version=0x1ffe
|
||||
atmega88: $(PROGRAM)_atmega88.hex
|
||||
atmega88: $(PROGRAM)_atmega88.lst
|
||||
|
||||
atmega88_isp: atmega88
|
||||
atmega88_isp: TARGET = atmega88
|
||||
atmega88_isp: MCU_TARGET = atmega88
|
||||
# 2.7V brownout
|
||||
atmega88_isp: HFUSE = DD
|
||||
# Low power xtal (16MHz) 16KCK/14CK+65ms
|
||||
atemga88_isp: LFUSE = FF
|
||||
# 512 byte boot
|
||||
atmega88_isp: EFUSE = 04
|
||||
atmega88_isp: isp
|
||||
|
||||
|
||||
# 8MHz clocked platforms
|
||||
#
|
||||
# These are capable of 38400 baud
|
||||
#
|
||||
|
||||
lilypad: TARGET = lilypad
|
||||
lilypad: MCU_TARGET = atmega168
|
||||
lilypad: CFLAGS += '-DLED_START_FLASHES=3' '-DBAUD_RATE=38400'
|
||||
lilypad: AVR_FREQ = 8000000L
|
||||
lilypad: $(PROGRAM)_lilypad.hex
|
||||
lilypad: $(PROGRAM)_lilypad.lst
|
||||
|
||||
lilypad_isp: lilypad
|
||||
lilypad_isp: TARGET = lilypad
|
||||
# 2.7V brownout
|
||||
lilypad_isp: HFUSE = DD
|
||||
# Internal 8MHz osc (8MHz) Slow rising power
|
||||
lilypad_isp: LFUSE = E2
|
||||
# 512 byte boot
|
||||
lilypad_isp: EFUSE = 04
|
||||
lilypad_isp: isp
|
||||
|
||||
lilypad_resonator: TARGET = lilypad_resonator
|
||||
lilypad_resonator: MCU_TARGET = atmega168
|
||||
lilypad_resonator: CFLAGS += '-DLED_START_FLASHES=3' '-DBAUD_RATE=38400'
|
||||
lilypad_resonator: AVR_FREQ = 8000000L
|
||||
lilypad_resonator: $(PROGRAM)_lilypad_resonator.hex
|
||||
lilypad_resonator: $(PROGRAM)_lilypad_resonator.lst
|
||||
|
||||
lilypad_resonator_isp: lilypad_resonator
|
||||
lilypad_resonator_isp: TARGET = lilypad_resonator
|
||||
# 2.7V brownout
|
||||
lilypad_resonator_isp: HFUSE = DD
|
||||
# Full swing xtal (20MHz) 258CK/14CK+4.1ms
|
||||
lilypad_resonator_isp: LFUSE = C6
|
||||
# 512 byte boot
|
||||
lilypad_resonator_isp: EFUSE = 04
|
||||
lilypad_resonator_isp: isp
|
||||
|
||||
pro8: TARGET = pro_8MHz
|
||||
pro8: MCU_TARGET = atmega168
|
||||
pro8: CFLAGS += '-DLED_START_FLASHES=3' '-DBAUD_RATE=38400'
|
||||
pro8: AVR_FREQ = 8000000L
|
||||
pro8: $(PROGRAM)_pro_8MHz.hex
|
||||
pro8: $(PROGRAM)_pro_8MHz.lst
|
||||
|
||||
pro8_isp: pro8
|
||||
pro8_isp: TARGET = pro_8MHz
|
||||
# 2.7V brownout
|
||||
pro8_isp: HFUSE = DD
|
||||
# Full swing xtal (20MHz) 258CK/14CK+4.1ms
|
||||
pro8_isp: LFUSE = C6
|
||||
# 512 byte boot
|
||||
pro8_isp: EFUSE = 04
|
||||
pro8_isp: isp
|
||||
|
||||
atmega328_pro8: TARGET = atmega328_pro_8MHz
|
||||
atmega328_pro8: MCU_TARGET = atmega328p
|
||||
atmega328_pro8: CFLAGS += '-DLED_START_FLASHES=3' '-DBAUD_RATE=38400'
|
||||
atmega328_pro8: AVR_FREQ = 8000000L
|
||||
atmega328_pro8: LDSECTIONS = -Wl,--section-start=.text=0x7e00 -Wl,--section-start=.version=0x7ffe
|
||||
atmega328_pro8: $(PROGRAM)_atmega328_pro_8MHz.hex
|
||||
atmega328_pro8: $(PROGRAM)_atmega328_pro_8MHz.lst
|
||||
|
||||
atmega328_pro8_isp: atmega328_pro8
|
||||
atmega328_pro8_isp: TARGET = atmega328_pro_8MHz
|
||||
atmega328_pro8_isp: MCU_TARGET = atmega328p
|
||||
# 512 byte boot, SPIEN
|
||||
atmega328_pro8_isp: HFUSE = DE
|
||||
# Low power xtal (16MHz) 16KCK/14CK+65ms
|
||||
atmega328_pro8_isp: LFUSE = FF
|
||||
# 2.7V brownout
|
||||
atmega328_pro8_isp: EFUSE = DE
|
||||
atmega328_pro8_isp: isp
|
||||
|
||||
# 1MHz clocked platforms
|
||||
#
|
||||
# These are capable of 9600 baud
|
||||
#
|
||||
|
||||
luminet: TARGET = luminet
|
||||
luminet: MCU_TARGET = attiny84
|
||||
luminet: CFLAGS += '-DLED_START_FLASHES=3' '-DSOFT_UART' '-DBAUD_RATE=9600'
|
||||
luminet: CFLAGS += '-DVIRTUAL_BOOT_PARTITION'
|
||||
luminet: AVR_FREQ = 1000000L
|
||||
luminet: LDSECTIONS = -Wl,--section-start=.text=0x1d00 -Wl,--section-start=.version=0x1efe
|
||||
luminet: $(PROGRAM)_luminet.hex
|
||||
luminet: $(PROGRAM)_luminet.lst
|
||||
|
||||
luminet_isp: luminet
|
||||
luminet_isp: TARGET = luminet
|
||||
luminet_isp: MCU_TARGET = attiny84
|
||||
# Brownout disabled
|
||||
luminet_isp: HFUSE = DF
|
||||
# 1MHz internal oscillator, slowly rising power
|
||||
luminet_isp: LFUSE = 62
|
||||
# Self-programming enable
|
||||
luminet_isp: EFUSE = FE
|
||||
luminet_isp: isp
|
||||
|
||||
#
|
||||
# Generic build instructions
|
||||
#
|
||||
#
|
||||
|
||||
isp: $(TARGET)
|
||||
$(ISPFUSES)
|
||||
$(ISPFLASH)
|
||||
|
||||
isp-stk500: $(PROGRAM)_$(TARGET).hex
|
||||
$(STK500-1)
|
||||
$(STK500-2)
|
||||
|
||||
%.elf: $(OBJ)
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(LIBS)
|
||||
$(SIZE) $@
|
||||
|
||||
clean:
|
||||
rm -rf *.o *.elf *.lst *.map *.sym *.lss *.eep *.srec *.bin *.hex
|
||||
|
||||
%.lst: %.elf
|
||||
$(OBJDUMP) -h -S $< > $@
|
||||
|
||||
%.hex: %.elf
|
||||
$(OBJCOPY) -j .text -j .data -j .version --set-section-flags .version=alloc,load -O ihex $< $@
|
||||
|
||||
%.srec: %.elf
|
||||
$(OBJCOPY) -j .text -j .data -j .version --set-section-flags .version=alloc,load -O srec $< $@
|
||||
|
||||
%.bin: %.elf
|
||||
$(OBJCOPY) -j .text -j .data -j .version --set-section-flags .version=alloc,load -O binary $< $@
|
||||
980
BootLoaders/OrangeMultiBoot/Source/optiboot.c
Normal file
@@ -0,0 +1,980 @@
|
||||
/**********************************************************/
|
||||
/* Optiboot bootloader for Xmega */
|
||||
/* */
|
||||
/* http://optiboot.googlecode.com */
|
||||
/* */
|
||||
/* Arduino-maintained version : See README.TXT */
|
||||
/* http://code.google.com/p/arduino/ */
|
||||
/* It is the intent that changes not relevant to the */
|
||||
/* Arduino production envionment get moved from the */
|
||||
/* optiboot project to the arduino project in "lumps." */
|
||||
/* */
|
||||
/* Heavily optimised bootloader that is faster and */
|
||||
/* smaller than the Arduino standard bootloader */
|
||||
/* */
|
||||
/* Enhancements: */
|
||||
/* Fits in 512 bytes, saving 1.5K of code space */
|
||||
/* Background page erasing speeds up programming */
|
||||
/* Higher baud rate speeds up programming */
|
||||
/* Written almost entirely in C */
|
||||
/* Customisable timeout with accurate timeconstant */
|
||||
/* Optional virtual UART. No hardware UART required. */
|
||||
/* Optional virtual boot partition for devices without. */
|
||||
/* */
|
||||
/* What you lose: */
|
||||
/* Implements a skeleton STK500 protocol which is */
|
||||
/* missing several features including EEPROM */
|
||||
/* programming and non-page-aligned writes */
|
||||
/* High baud rate breaks compatibility with standard */
|
||||
/* Arduino flash settings */
|
||||
/* */
|
||||
/* Fully supported: */
|
||||
/* ATmega168 based devices (Diecimila etc) */
|
||||
/* ATmega328P based devices (Duemilanove etc) */
|
||||
/* */
|
||||
/* Beta test (believed working.) */
|
||||
/* ATmega8 based devices (Arduino legacy) */
|
||||
/* ATmega328 non-picopower devices */
|
||||
/* ATmega644P based devices (Sanguino) */
|
||||
/* ATmega1284P based devices */
|
||||
/* */
|
||||
/* Alpha test */
|
||||
/* ATmega1280 based devices (Arduino Mega) */
|
||||
/* */
|
||||
/* Work in progress: */
|
||||
/* ATtiny84 based devices (Luminet) */
|
||||
/* */
|
||||
/* Does not support: */
|
||||
/* USB based devices (eg. Teensy) */
|
||||
/* */
|
||||
/* Assumptions: */
|
||||
/* The code makes several assumptions that reduce the */
|
||||
/* code size. They are all true after a hardware reset, */
|
||||
/* but may not be true if the bootloader is called by */
|
||||
/* other means or on other hardware. */
|
||||
/* No interrupts can occur */
|
||||
/* UART and Timer 1 are set to their reset state */
|
||||
/* SP points to RAMEND */
|
||||
/* */
|
||||
/* Code builds on code, libraries and optimisations from: */
|
||||
/* stk500boot.c by Jason P. Kyle */
|
||||
/* Arduino bootloader http://arduino.cc */
|
||||
/* Spiff's 1K bootloader http://spiffie.org/know/arduino_1k_bootloader/bootloader.shtml */
|
||||
/* avr-libc project http://nongnu.org/avr-libc */
|
||||
/* Adaboot http://www.ladyada.net/library/arduino/bootloader.html */
|
||||
/* AVR305 Atmel Application Note */
|
||||
/* */
|
||||
/* This program 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 2 of the License, or */
|
||||
/* (at your option) any later version. */
|
||||
/* */
|
||||
/* 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. */
|
||||
/* */
|
||||
/* You should have received a copy of the GNU General */
|
||||
/* Public License along with this program; if not, write */
|
||||
/* to the Free Software Foundation, Inc., */
|
||||
/* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
/* */
|
||||
/* Licence can be viewed at */
|
||||
/* http://www.fsf.org/licenses/gpl.txt */
|
||||
/* */
|
||||
/**********************************************************/
|
||||
|
||||
|
||||
/**********************************************************/
|
||||
/* */
|
||||
/* Optional defines: */
|
||||
/* */
|
||||
/**********************************************************/
|
||||
/* */
|
||||
/* BIG_BOOT: */
|
||||
/* Build a 1k bootloader, not 512 bytes. This turns on */
|
||||
/* extra functionality. */
|
||||
/* */
|
||||
/* BAUD_RATE: */
|
||||
/* Set bootloader baud rate. */
|
||||
/* */
|
||||
/* LUDICROUS_SPEED: */
|
||||
/* 230400 baud :-) */
|
||||
/* */
|
||||
/* SOFT_UART: */
|
||||
/* Use AVR305 soft-UART instead of hardware UART. */
|
||||
/* */
|
||||
/* LED_START_FLASHES: */
|
||||
/* Number of LED flashes on bootup. */
|
||||
/* */
|
||||
/* LED_DATA_FLASH: */
|
||||
/* Flash LED when transferring data. For boards without */
|
||||
/* TX or RX LEDs, or for people who like blinky lights. */
|
||||
/* */
|
||||
/* SUPPORT_EEPROM: */
|
||||
/* Support reading and writing from EEPROM. This is not */
|
||||
/* used by Arduino, so off by default. */
|
||||
/* */
|
||||
/* TIMEOUT_MS: */
|
||||
/* Bootloader timeout period, in milliseconds. */
|
||||
/* 500,1000,2000,4000,8000 supported. */
|
||||
/* */
|
||||
/* UART: */
|
||||
/* UART number (0..n) for devices with more than */
|
||||
/* one hardware uart (644P, 1284P, etc) */
|
||||
/* */
|
||||
/**********************************************************/
|
||||
|
||||
/**********************************************************/
|
||||
/* Version Numbers! */
|
||||
/* */
|
||||
/* Arduino Optiboot now includes this Version number in */
|
||||
/* the source and object code. */
|
||||
/* */
|
||||
/* Version 3 was released as zip from the optiboot */
|
||||
/* repository and was distributed with Arduino 0022. */
|
||||
/* Version 4 starts with the arduino repository commit */
|
||||
/* that brought the arduino repository up-to-date with */
|
||||
/* the optiboot source tree changes since v3. */
|
||||
/* */
|
||||
/**********************************************************/
|
||||
|
||||
/**********************************************************/
|
||||
/* Edit History: */
|
||||
/* */
|
||||
/* Nov 2012 */
|
||||
/* Specific version for 9x voice module */
|
||||
/* by Mike Blandford */
|
||||
/* Mar 2012 */
|
||||
/* 4.5 WestfW: add infrastructure for non-zero UARTS. */
|
||||
/* 4.5 WestfW: fix SIGNATURE_2 for m644 (bad in avr-libc) */
|
||||
/* Jan 2012: */
|
||||
/* 4.5 WestfW: fix NRWW value for m1284. */
|
||||
/* 4.4 WestfW: use attribute OS_main instead of naked for */
|
||||
/* main(). This allows optimizations that we */
|
||||
/* count on, which are prohibited in naked */
|
||||
/* functions due to PR42240. (keeps us less */
|
||||
/* than 512 bytes when compiler is gcc4.5 */
|
||||
/* (code from 4.3.2 remains the same.) */
|
||||
/* 4.4 WestfW and Maniacbug: Add m1284 support. This */
|
||||
/* does not change the 328 binary, so the */
|
||||
/* version number didn't change either. (?) */
|
||||
/* June 2011: */
|
||||
/* 4.4 WestfW: remove automatic soft_uart detect (didn't */
|
||||
/* know what it was doing or why.) Added a */
|
||||
/* check of the calculated BRG value instead. */
|
||||
/* Version stays 4.4; existing binaries are */
|
||||
/* not changed. */
|
||||
/* 4.4 WestfW: add initialization of address to keep */
|
||||
/* the compiler happy. Change SC'ed targets. */
|
||||
/* Return the SW version via READ PARAM */
|
||||
/* 4.3 WestfW: catch framing errors in getch(), so that */
|
||||
/* AVRISP works without HW kludges. */
|
||||
/* http://code.google.com/p/arduino/issues/detail?id=368n*/
|
||||
/* 4.2 WestfW: reduce code size, fix timeouts, change */
|
||||
/* verifySpace to use WDT instead of appstart */
|
||||
/* 4.1 WestfW: put version number in binary. */
|
||||
/**********************************************************/
|
||||
|
||||
#define OPTIBOOT_MAJVER 4
|
||||
#define OPTIBOOT_MINVER 5
|
||||
|
||||
#define MULTI_CALLED 1
|
||||
|
||||
#define MAKESTR(a) #a
|
||||
#define MAKEVER(a, b) MAKESTR(a*256+b)
|
||||
|
||||
// Page Size is 128 words (256 bytes)
|
||||
|
||||
//asm(" .section .version\n"
|
||||
// "optiboot_version: .word " MAKEVER(OPTIBOOT_MAJVER, OPTIBOOT_MINVER) "\n"
|
||||
// " .section .text\n");
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <avr/io.h>
|
||||
#include <avr/pgmspace.h>
|
||||
|
||||
// <avr/boot.h> uses sts instructions, but this version uses out instructions
|
||||
// This saves cycles and program memory.
|
||||
//#include "boot.h"
|
||||
|
||||
|
||||
// We don't use <avr/wdt.h> as those routines have interrupt overhead we don't need.
|
||||
|
||||
#include "pin_defs.h"
|
||||
#include "stk500.h"
|
||||
|
||||
#define BIND_pin 2 //PD2
|
||||
#define BIND_port PORTD
|
||||
#define IS_BIND_BUTTON_on ( (BIND_port.IN & _BV(BIND_pin)) == 0x00 )
|
||||
|
||||
#ifndef LED_START_FLASHES
|
||||
#define LED_START_FLASHES 0
|
||||
#endif
|
||||
|
||||
#ifdef LUDICROUS_SPEED
|
||||
#define BAUD_RATE 230400L
|
||||
#endif
|
||||
|
||||
/* set the UART baud rate defaults */
|
||||
#ifndef BAUD_RATE
|
||||
#if F_CPU >= 8000000L
|
||||
#define BAUD_RATE 38400L // Highest rate Avrdude win32 will support
|
||||
#elsif F_CPU >= 1000000L
|
||||
#define BAUD_RATE 9600L // 19200 also supported, but with significant error
|
||||
#elsif F_CPU >= 128000L
|
||||
#define BAUD_RATE 4800L // Good for 128kHz internal RC
|
||||
#else
|
||||
#define BAUD_RATE 1200L // Good even at 32768Hz
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef UART
|
||||
#define UART 0
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
/* Switch in soft UART for hard baud rates */
|
||||
/*
|
||||
* I don't understand what this was supposed to accomplish, where the
|
||||
* constant "280" came from, or why automatically (and perhaps unexpectedly)
|
||||
* switching to a soft uart is a good thing, so I'm undoing this in favor
|
||||
* of a range check using the same calc used to config the BRG...
|
||||
*/
|
||||
#if (F_CPU/BAUD_RATE) > 280 // > 57600 for 16MHz
|
||||
#ifndef SOFT_UART
|
||||
#define SOFT_UART
|
||||
#endif
|
||||
#endif
|
||||
#else // 0
|
||||
#if (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 > 250
|
||||
#error Unachievable baud rate (too slow) BAUD_RATE
|
||||
#endif // baud rate slow check
|
||||
#if (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 < 3
|
||||
#error Unachievable baud rate (too fast) BAUD_RATE
|
||||
#endif // baud rate fastn check
|
||||
#endif
|
||||
|
||||
/* Watchdog settings */
|
||||
#define WATCHDOG_OFF (0)
|
||||
#define WATCHDOG_16MS (_BV(WDE))
|
||||
#define WATCHDOG_32MS (_BV(WDP0) | _BV(WDE))
|
||||
#define WATCHDOG_64MS (_BV(WDP1) | _BV(WDE))
|
||||
#define WATCHDOG_125MS (_BV(WDP1) | _BV(WDP0) | _BV(WDE))
|
||||
#define WATCHDOG_250MS (_BV(WDP2) | _BV(WDE))
|
||||
#define WATCHDOG_500MS (_BV(WDP2) | _BV(WDP0) | _BV(WDE))
|
||||
#define WATCHDOG_1S (_BV(WDP2) | _BV(WDP1) | _BV(WDE))
|
||||
#define WATCHDOG_2S (_BV(WDP2) | _BV(WDP1) | _BV(WDP0) | _BV(WDE))
|
||||
#ifndef __AVR_ATmega8__
|
||||
#define WATCHDOG_4S (_BV(WDP3) | _BV(WDE))
|
||||
#define WATCHDOG_8S (_BV(WDP3) | _BV(WDP0) | _BV(WDE))
|
||||
#endif
|
||||
|
||||
/* Function Prototypes */
|
||||
/* The main function is in init9, which removes the interrupt vector table */
|
||||
/* we don't need. It is also 'naked', which means the compiler does not */
|
||||
/* generate any entry or exit code itself. */
|
||||
int main(void) __attribute__ ((OS_main)) __attribute__ ((noreturn)) __attribute__ ((section (".init9")));
|
||||
void putch(char);
|
||||
uint8_t getch(void);
|
||||
static inline void getNch(uint8_t); /* "static inline" is a compiler hint to reduce code size */
|
||||
void verifySpace();
|
||||
#if LED_START_FLASHES > 0
|
||||
static inline void flash_led(uint8_t);
|
||||
#endif
|
||||
uint8_t getLen();
|
||||
//static inline void watchdogReset();
|
||||
void watchdogConfig(uint8_t x);
|
||||
#ifdef SOFT_UART
|
||||
void uartDelay() __attribute__ ((naked));
|
||||
#endif
|
||||
static void appStart() ; // __attribute__ ((naked));
|
||||
void boot_spm_busy_wait() ;
|
||||
void __boot_page_erase_short( uint16_t address ) ;
|
||||
void __boot_page_fill_short( uint16_t address, uint16_t data) ;
|
||||
void __boot_page_write_short( uint16_t address) ;
|
||||
void __boot_erase_flash_buffer( uint16_t address ) ;
|
||||
void init() ;
|
||||
|
||||
/*
|
||||
* NRWW memory
|
||||
* Addresses below NRWW (Non-Read-While-Write) can be programmed while
|
||||
* continuing to run code from flash, slightly speeding up programming
|
||||
* time. Beware that Atmel data sheets specify this as a WORD address,
|
||||
* while optiboot will be comparing against a 16-bit byte address. This
|
||||
* means that on a part with 128kB of memory, the upper part of the lower
|
||||
* 64k will get NRWW processing as well, even though it doesn't need it.
|
||||
* That's OK. In fact, you can disable the overlapping processing for
|
||||
* a part entirely by setting NRWWSTART to zero. This reduces code
|
||||
* space a bit, at the expense of being slightly slower, overall.
|
||||
*
|
||||
* RAMSTART should be self-explanatory. It's bigger on parts with a
|
||||
* lot of peripheral registers.
|
||||
*/
|
||||
#if defined(__AVR_ATmega168__)
|
||||
#define RAMSTART (0x100)
|
||||
#define NRWWSTART (0x3800)
|
||||
#elif defined(__AVR_ATmega328P__)
|
||||
#define RAMSTART (0x100)
|
||||
#define NRWWSTART (0x7000)
|
||||
#elif defined(__AVR_ATmega328__)
|
||||
#define RAMSTART (0x100)
|
||||
#define NRWWSTART (0x7000)
|
||||
#elif defined (__AVR_ATmega644P__)
|
||||
#define RAMSTART (0x100)
|
||||
#define NRWWSTART (0xE000)
|
||||
// correct for a bug in avr-libc
|
||||
#undef SIGNATURE_2
|
||||
#define SIGNATURE_2 0x0A
|
||||
#elif defined (__AVR_ATmega1284P__)
|
||||
#define RAMSTART (0x100)
|
||||
#define NRWWSTART (0xE000)
|
||||
#elif defined(__AVR_ATtiny84__)
|
||||
#define RAMSTART (0x100)
|
||||
#define NRWWSTART (0x0000)
|
||||
#elif defined(__AVR_ATmega1280__)
|
||||
#define RAMSTART (0x200)
|
||||
#define NRWWSTART (0xE000)
|
||||
#elif defined(__AVR_ATmega8__) || defined(__AVR_ATmega88__)
|
||||
#define RAMSTART (0x100)
|
||||
#define NRWWSTART (0x1800)
|
||||
#endif
|
||||
|
||||
/* C zero initialises all global variables. However, that requires */
|
||||
/* These definitions are NOT zero initialised, but that doesn't matter */
|
||||
/* This allows us to drop the zero init code, saving us memory */
|
||||
#define buff ((uint8_t*)(RAMSTART))
|
||||
#ifdef VIRTUAL_BOOT_PARTITION
|
||||
#define rstVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+4))
|
||||
#define wdtVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+6))
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Handle devices with up to 4 uarts (eg m1280.) Rather inelegantly.
|
||||
* Note that mega8 still needs special handling, because ubrr is handled
|
||||
* differently.
|
||||
*/
|
||||
#if UART == 0
|
||||
# define UART_SRA UCSR0A
|
||||
# define UART_SRB UCSR0B
|
||||
# define UART_SRC UCSR0C
|
||||
# define UART_SRL UBRR0L
|
||||
# define UART_UDR UDR0
|
||||
#elif UART == 1
|
||||
# define UART_SRA UCSR1A
|
||||
# define UART_SRB UCSR1B
|
||||
# define UART_SRC UCSR1C
|
||||
# define UART_SRL UBRR1L
|
||||
# define UART_UDR UDR1
|
||||
#elif UART == 2
|
||||
# define UART_SRA UCSR2A
|
||||
# define UART_SRB UCSR2B
|
||||
# define UART_SRC UCSR2C
|
||||
# define UART_SRL UBRR2L
|
||||
# define UART_UDR UDR2
|
||||
#elif UART == 3
|
||||
# define UART_SRA UCSR3A
|
||||
# define UART_SRB UCSR3B
|
||||
# define UART_SRC UCSR3C
|
||||
# define UART_SRL UBRR3L
|
||||
# define UART_UDR UDR3
|
||||
#endif
|
||||
|
||||
|
||||
/* main program starts here */
|
||||
int main(void)
|
||||
{
|
||||
uint8_t ch;
|
||||
uint8_t byte ;
|
||||
|
||||
/*
|
||||
* Making these local and in registers prevents the need for initializing
|
||||
* them, and also saves space because code no longer stores to memory.
|
||||
* (initializing address keeps the compiler happy, but isn't really
|
||||
* necessary, and uses 4 bytes of flash.)
|
||||
*/
|
||||
register uint16_t address = 0;
|
||||
init() ;
|
||||
|
||||
// After the zero init loop, this is the first code to run.
|
||||
//
|
||||
// This code makes the following assumptions:
|
||||
// No interrupts will execute
|
||||
// SP points to RAMEND
|
||||
// r1 contains zero
|
||||
//
|
||||
// If not, uncomment the following instructions:
|
||||
// cli();
|
||||
asm volatile ("clr __zero_reg__");
|
||||
|
||||
ch = RST.STATUS ;
|
||||
RST.STATUS = 0xFF ; // Clear all flags
|
||||
|
||||
// Here, if power on, wait 0.1 secs, then check for
|
||||
// serial Rx signal low, if so, stay in bootloader
|
||||
// else go to application
|
||||
|
||||
if (ch & (RST_EXTRF_bm | RST_PORF_bm ) )
|
||||
{
|
||||
TCC1.CCA = 25000 ;
|
||||
TCC1.INTFLAGS = TC1_CCAIF_bm ;
|
||||
|
||||
while(!(TCC1.INTFLAGS & TC1_CCAIF_bm))
|
||||
;
|
||||
TCC1.CTRLA = 0 ; // Stop timer
|
||||
|
||||
uint8_t x ;
|
||||
x = PORTD.IN & 0x04 ;
|
||||
if ( x != 0 )
|
||||
{
|
||||
appStart() ; // Power on, go to app if loaded
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//#ifndef SOFT_UART
|
||||
// UART_SRA = _BV(U2X0); //Double speed mode USART0
|
||||
// UART_SRB = _BV(RXEN0) | _BV(TXEN0);
|
||||
// UART_SRC = _BV(UCSZ00) | _BV(UCSZ01);
|
||||
//// UART_SRL = (uint8_t)( (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 );
|
||||
//// Baudrate of 57600
|
||||
//#if F_CPU == 12000000L
|
||||
// UART_SRL = 25 ;
|
||||
//#else
|
||||
//#if F_CPU == 16000000L
|
||||
// UART_SRL = 33 ;
|
||||
//#else
|
||||
//#ERROR Baud rate not available
|
||||
//#endif
|
||||
//#endif
|
||||
|
||||
//#endif
|
||||
|
||||
// Set up watchdog to trigger after 500ms
|
||||
|
||||
|
||||
// watchdogConfig(WATCHDOG_1S);
|
||||
|
||||
/* Set LED pin as output */
|
||||
#define LED_pin 1 //PD1
|
||||
#define LED_port PORTD
|
||||
LED_port.DIRSET = _BV(LED_pin) ;
|
||||
|
||||
//#ifdef SOFT_UART
|
||||
// /* Set TX pin as output */
|
||||
// UART_DDR |= _BV(UART_TX_BIT);
|
||||
//#endif
|
||||
|
||||
//#if LED_START_FLASHES > 0
|
||||
// /* Flash onboard LED to signal entering of bootloader */
|
||||
// flash_led(LED_START_FLASHES * 2);
|
||||
//#endif
|
||||
|
||||
/* Forever loop */
|
||||
for (;;)
|
||||
{
|
||||
/* get character from UART */
|
||||
ch = getch();
|
||||
|
||||
if(ch == STK_GET_PARAMETER)
|
||||
{
|
||||
byte = getch();
|
||||
verifySpace();
|
||||
if ( byte == 0x82)
|
||||
{
|
||||
/*
|
||||
* Send optiboot version as "minor SW version"
|
||||
*/
|
||||
putch(OPTIBOOT_MINVER);
|
||||
}
|
||||
else if ( byte == 0x81)
|
||||
{
|
||||
putch(OPTIBOOT_MAJVER);
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* GET PARAMETER returns a generic 0x03 reply for
|
||||
* other parameters - enough to keep Avrdude happy
|
||||
*/
|
||||
putch(0x03);
|
||||
}
|
||||
}
|
||||
else if(ch == STK_SET_DEVICE) {
|
||||
// SET DEVICE is ignored
|
||||
getNch(20);
|
||||
}
|
||||
else if(ch == STK_SET_DEVICE_EXT)
|
||||
{
|
||||
// SET DEVICE EXT is ignored
|
||||
getNch(5);
|
||||
}
|
||||
else if(ch == STK_LOAD_ADDRESS)
|
||||
{
|
||||
// LOAD ADDRESS
|
||||
uint16_t newAddress;
|
||||
newAddress = getch() ;
|
||||
newAddress = (newAddress & 0xff) | (getch() << 8);
|
||||
#ifdef RAMPZ
|
||||
// Transfer top bit to RAMPZ
|
||||
RAMPZ = (newAddress & 0x8000) ? 1 : 0;
|
||||
#endif
|
||||
// newAddress += newAddress; // Convert from word address to byte address
|
||||
address = newAddress;
|
||||
verifySpace();
|
||||
}
|
||||
else if(ch == STK_UNIVERSAL)
|
||||
{
|
||||
// UNIVERSAL command is ignored
|
||||
getNch(4);
|
||||
putch(0x00);
|
||||
}
|
||||
/* Write memory, length is big endian and is in bytes */
|
||||
else if(ch == STK_PROG_PAGE)
|
||||
{
|
||||
// PROGRAM PAGE - we support flash programming only, not EEPROM
|
||||
uint8_t *bufPtr;
|
||||
uint16_t addrPtr;
|
||||
register uint8_t length;
|
||||
|
||||
getch(); /* getlen() */
|
||||
length = getch();
|
||||
getch();
|
||||
|
||||
// If we are in RWW section, immediately start page erase
|
||||
// if (address < NRWWSTART) __boot_page_erase_short((uint16_t)(void*)address);
|
||||
__boot_page_erase_short((uint16_t)(void*)address);
|
||||
|
||||
// While that is going on, read in page contents
|
||||
bufPtr = buff;
|
||||
do *bufPtr++ = getch();
|
||||
while (--length);
|
||||
|
||||
// If we are in NRWW section, page erase has to be delayed until now.
|
||||
// Todo: Take RAMPZ into account
|
||||
//#ifdef MULTI_CALLED
|
||||
// if (address < 0x7E00)
|
||||
//#endif
|
||||
// {
|
||||
// if (address >= NRWWSTART) __boot_page_erase_short((uint16_t)(void*)address);
|
||||
// }
|
||||
// Read command terminator, start reply
|
||||
verifySpace();
|
||||
|
||||
// If only a partial page is to be programmed, the erase might not be complete.
|
||||
// So check that here
|
||||
#ifdef MULTI_CALLED
|
||||
if (address < 0x8000)
|
||||
#endif
|
||||
{
|
||||
boot_spm_busy_wait();
|
||||
|
||||
#ifdef VIRTUAL_BOOT_PARTITION
|
||||
if ((uint16_t)(void*)address == 0) {
|
||||
// This is the reset vector page. We need to live-patch the code so the
|
||||
// bootloader runs.
|
||||
//
|
||||
// Move RESET vector to WDT vector
|
||||
uint16_t vect = buff[0] | (buff[1]<<8);
|
||||
rstVect = vect;
|
||||
wdtVect = buff[8] | (buff[9]<<8);
|
||||
vect -= 4; // Instruction is a relative jump (rjmp), so recalculate.
|
||||
buff[8] = vect & 0xff;
|
||||
buff[9] = vect >> 8;
|
||||
|
||||
// Add jump to bootloader at RESET vector
|
||||
buff[0] = 0x7f;
|
||||
buff[1] = 0xce; // rjmp 0x1d00 instruction
|
||||
}
|
||||
#endif
|
||||
|
||||
// Copy buffer into programming buffer
|
||||
bufPtr = buff;
|
||||
addrPtr = (uint16_t)(void*)address;
|
||||
ch = SPM_PAGESIZE / 2;
|
||||
__boot_erase_flash_buffer((uint16_t)(void*)addrPtr ) ;
|
||||
do {
|
||||
uint16_t a;
|
||||
// a = *bufPtr++;
|
||||
// a |= (*bufPtr++) << 8;
|
||||
|
||||
a = *((uint16_t *)bufPtr) ;
|
||||
bufPtr += 2 ;
|
||||
|
||||
__boot_page_fill_short((uint16_t)(void*)addrPtr,a);
|
||||
addrPtr += 2;
|
||||
} while (--ch);
|
||||
|
||||
// Write from programming buffer
|
||||
__boot_page_write_short((uint16_t)(void*)address);
|
||||
boot_spm_busy_wait();
|
||||
|
||||
#if defined(RWWSRE)
|
||||
// Reenable read access to flash
|
||||
boot_rww_enable();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
/* Read memory block mode, length is big endian. */
|
||||
else if(ch == STK_READ_PAGE)
|
||||
{
|
||||
register uint8_t length;
|
||||
// READ PAGE - we only read flash
|
||||
getch(); /* getlen() */
|
||||
length = getch();
|
||||
getch();
|
||||
|
||||
verifySpace();
|
||||
//#ifdef VIRTUAL_BOOT_PARTITION
|
||||
// do {
|
||||
// // Undo vector patch in bottom page so verify passes
|
||||
// if (address == 0) ch=rstVect & 0xff;
|
||||
// else if (address == 1) ch=rstVect >> 8;
|
||||
// else if (address == 8) ch=wdtVect & 0xff;
|
||||
// else if (address == 9) ch=wdtVect >> 8;
|
||||
// else ch = pgm_read_byte_near(address);
|
||||
// address++;
|
||||
// putch(ch);
|
||||
// } while (--length);
|
||||
//#else
|
||||
//#ifdef RAMPZ
|
||||
//// Since RAMPZ should already be set, we need to use EPLM directly.
|
||||
//// do putch(pgm_read_byte_near(address++));
|
||||
//// while (--length);
|
||||
// do {
|
||||
// uint8_t result;
|
||||
// __asm__ ("elpm %0,Z\n":"=r"(result):"z"(address));
|
||||
// putch(result);
|
||||
// address++;
|
||||
// }
|
||||
// while (--length);
|
||||
//#else
|
||||
do putch(pgm_read_byte_near(address++));
|
||||
while (--length);
|
||||
//#endif
|
||||
//#endif
|
||||
}
|
||||
|
||||
/* Get device signature bytes */
|
||||
else if(ch == STK_READ_SIGN)
|
||||
{
|
||||
// READ SIGN - return what Avrdude wants to hear
|
||||
verifySpace();
|
||||
putch(SIGNATURE_0);
|
||||
putch(SIGNATURE_1);
|
||||
putch(SIGNATURE_2);
|
||||
}
|
||||
else if (ch == STK_LEAVE_PROGMODE) { /* 'Q' */
|
||||
// Adaboot no-wait mod
|
||||
|
||||
// watchdogConfig(WATCHDOG_16MS);
|
||||
|
||||
verifySpace();
|
||||
#ifdef MULTI_CALLED
|
||||
putch(STK_OK);
|
||||
while(!(USARTC0.STATUS & USART_TXCIF_bm))
|
||||
;
|
||||
appStart() ;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
// This covers the response to commands like STK_ENTER_PROGMODE
|
||||
verifySpace();
|
||||
}
|
||||
putch(STK_OK);
|
||||
}
|
||||
}
|
||||
|
||||
void putch(char ch)
|
||||
{
|
||||
//#ifndef SOFT_UART
|
||||
while(!(USARTC0.STATUS & USART_DREIF_bm))
|
||||
;
|
||||
USARTC0.DATA = ch ;
|
||||
//#else
|
||||
// __asm__ __volatile__ (
|
||||
// " com %[ch]\n" // ones complement, carry set
|
||||
// " sec\n"
|
||||
// "1: brcc 2f\n"
|
||||
// " cbi %[uartPort],%[uartBit]\n"
|
||||
// " rjmp 3f\n"
|
||||
// "2: sbi %[uartPort],%[uartBit]\n"
|
||||
// " nop\n"
|
||||
// "3: rcall uartDelay\n"
|
||||
// " rcall uartDelay\n"
|
||||
// " lsr %[ch]\n"
|
||||
// " dec %[bitcnt]\n"
|
||||
// " brne 1b\n"
|
||||
// :
|
||||
// :
|
||||
// [bitcnt] "d" (10),
|
||||
// [ch] "r" (ch),
|
||||
// [uartPort] "I" (_SFR_IO_ADDR(UART_PORT)),
|
||||
// [uartBit] "I" (UART_TX_BIT)
|
||||
// :
|
||||
// "r25"
|
||||
// );
|
||||
//#endif
|
||||
}
|
||||
|
||||
uint8_t getch(void)
|
||||
{
|
||||
uint8_t ch;
|
||||
|
||||
//#ifdef LED_DATA_FLASH
|
||||
//#ifdef __AVR_ATmega8__
|
||||
// LED_PORT ^= _BV(LED);
|
||||
//#else
|
||||
// LED_PIN |= _BV(LED);
|
||||
//#endif
|
||||
//#endif
|
||||
|
||||
//#ifdef SOFT_UART
|
||||
// __asm__ __volatile__ (
|
||||
// "1: sbic %[uartPin],%[uartBit]\n" // Wait for start edge
|
||||
// " rjmp 1b\n"
|
||||
// " rcall uartDelay\n" // Get to middle of start bit
|
||||
// "2: rcall uartDelay\n" // Wait 1 bit period
|
||||
// " rcall uartDelay\n" // Wait 1 bit period
|
||||
// " clc\n"
|
||||
// " sbic %[uartPin],%[uartBit]\n"
|
||||
// " sec\n"
|
||||
// " dec %[bitCnt]\n"
|
||||
// " breq 3f\n"
|
||||
// " ror %[ch]\n"
|
||||
// " rjmp 2b\n"
|
||||
// "3:\n"
|
||||
// :
|
||||
// [ch] "=r" (ch)
|
||||
// :
|
||||
// [bitCnt] "d" (9),
|
||||
// [uartPin] "I" (_SFR_IO_ADDR(UART_PIN)),
|
||||
// [uartBit] "I" (UART_RX_BIT)
|
||||
// :
|
||||
// "r25"
|
||||
//);
|
||||
//#else
|
||||
while(!(USARTC0.STATUS & USART_RXCIF_bm))
|
||||
|
||||
// watchdogReset()
|
||||
|
||||
;
|
||||
// if (!(UART_SRA & _BV(FE0))) {
|
||||
/*
|
||||
* A Framing Error indicates (probably) that something is talking
|
||||
* to us at the wrong bit rate. Assume that this is because it
|
||||
* expects to be talking to the application, and DON'T reset the
|
||||
* watchdog. This should cause the bootloader to abort and run
|
||||
* the application "soon", if it keeps happening. (Note that we
|
||||
* don't care that an invalid char is returned...)
|
||||
*/
|
||||
// watchdogReset();
|
||||
// }
|
||||
|
||||
ch = USARTC0.DATA ;
|
||||
//#endif
|
||||
|
||||
//#ifdef LED_DATA_FLASH
|
||||
//#ifdef __AVR_ATmega8__
|
||||
// LED_PORT ^= _BV(LED);
|
||||
//#else
|
||||
// LED_PIN |= _BV(LED);
|
||||
//#endif
|
||||
//#endif
|
||||
|
||||
return ch;
|
||||
}
|
||||
|
||||
#ifdef SOFT_UART
|
||||
// AVR305 equation: #define UART_B_VALUE (((F_CPU/BAUD_RATE)-23)/6)
|
||||
// Adding 3 to numerator simulates nearest rounding for more accurate baud rates
|
||||
#define UART_B_VALUE (((F_CPU/BAUD_RATE)-20)/6)
|
||||
#if UART_B_VALUE > 255
|
||||
#error Baud rate too slow for soft UART
|
||||
#endif
|
||||
|
||||
void uartDelay() {
|
||||
__asm__ __volatile__ (
|
||||
"ldi r25,%[count]\n"
|
||||
"1:dec r25\n"
|
||||
"brne 1b\n"
|
||||
"ret\n"
|
||||
::[count] "M" (UART_B_VALUE)
|
||||
);
|
||||
}
|
||||
#endif
|
||||
|
||||
void getNch(uint8_t count) {
|
||||
do getch(); while (--count);
|
||||
verifySpace();
|
||||
}
|
||||
|
||||
void verifySpace()
|
||||
{
|
||||
if ( getch() != CRC_EOP) {
|
||||
|
||||
putch(STK_NOSYNC);
|
||||
// watchdogConfig(WATCHDOG_16MS); // shorten WD timeout
|
||||
//
|
||||
// while (1) // and busy-loop so that WD causes
|
||||
// ; // a reset and app start.
|
||||
}
|
||||
putch(STK_INSYNC);
|
||||
}
|
||||
|
||||
#if LED_START_FLASHES > 0
|
||||
void flash_led(uint8_t count) {
|
||||
do {
|
||||
TCNT1 = -(F_CPU/(1024*16));
|
||||
TIFR1 = _BV(TOV1);
|
||||
while(!(TIFR1 & _BV(TOV1)));
|
||||
//#ifdef __AVR_ATmega8__
|
||||
LED_PORT ^= _BV(LED);
|
||||
//#else
|
||||
// LED_PIN |= _BV(LED);
|
||||
//#endif
|
||||
watchdogReset();
|
||||
} while (--count);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Watchdog functions. These are only safe with interrupts turned off.
|
||||
void watchdogReset() {
|
||||
__asm__ __volatile__ (
|
||||
"wdr\n"
|
||||
);
|
||||
}
|
||||
|
||||
//void watchdogConfig(uint8_t x) {
|
||||
// WDTCSR = _BV(WDCE) | _BV(WDE);
|
||||
// WDTCSR = x;
|
||||
//}
|
||||
|
||||
void init()
|
||||
{
|
||||
// Enable external oscillator (16MHz)
|
||||
OSC.XOSCCTRL = OSC_FRQRANGE_12TO16_gc | OSC_XOSCSEL_XTAL_256CLK_gc ;
|
||||
OSC.CTRL |= OSC_XOSCEN_bm ;
|
||||
while( ( OSC.STATUS & OSC_XOSCRDY_bm ) == 0 )
|
||||
/* wait */ ;
|
||||
// Enable PLL (*2 = 32MHz)
|
||||
OSC.PLLCTRL = OSC_PLLSRC_XOSC_gc | 2 ;
|
||||
OSC.CTRL |= OSC_PLLEN_bm ;
|
||||
while( ( OSC.STATUS & OSC_PLLRDY_bm ) == 0 )
|
||||
/* wait */ ;
|
||||
// Switch to PLL clock
|
||||
CPU_CCP = 0xD8 ;
|
||||
CLK.CTRL = CLK_SCLKSEL_RC2M_gc ;
|
||||
CPU_CCP = 0xD8 ;
|
||||
CLK.CTRL = CLK_SCLKSEL_PLL_gc ;
|
||||
|
||||
PMIC.CTRL = 7 ; // Enable all interrupt levels
|
||||
|
||||
|
||||
// Timer1 config
|
||||
// TCC1 16-bit timer, clocked at 0.5uS
|
||||
EVSYS.CH3MUX = 0x80 + 0x07 ; // Prescaler of 128
|
||||
TCC1.CTRLB = 0; TCC1.CTRLC = 0; TCC1.CTRLD = 0; TCC1.CTRLE = 0;
|
||||
TCC1.INTCTRLA = 0 ;
|
||||
TCC1.INTCTRLB = 0 ;
|
||||
TCC1.PER = 0xFFFF ;
|
||||
TCC1.CNT = 0 ;
|
||||
TCC1.CTRLA = 0x0B ; // Event3 (prescale of 16)
|
||||
|
||||
PORTD.OUTSET = 0x04 ;
|
||||
PORTD.DIRCLR = 0x04 ;
|
||||
PORTD.PIN2CTRL = 0x18 ; // Pullup
|
||||
|
||||
PORTC.OUTSET = 0x08 ;
|
||||
PORTC.DIRSET = 0x08 ;
|
||||
|
||||
USARTC0.BAUDCTRLA = 34 ; // 57600
|
||||
USARTC0.BAUDCTRLB = 0 ;
|
||||
|
||||
USARTC0.CTRLB = 0x18 ; // Enable Tx and Rx
|
||||
USARTC0.CTRLA = (USARTC0.CTRLA & 0xCF) ;
|
||||
USARTC0.CTRLC = 0x03 ; // 8 bit, no parity, 1 stop
|
||||
USARTC0.DATA ;
|
||||
}
|
||||
|
||||
void boot_spm_busy_wait()
|
||||
{
|
||||
while(NVM.STATUS & NVM_NVMBUSY_bm)
|
||||
;
|
||||
}
|
||||
|
||||
#define A_NVM_CMD 0x1CA
|
||||
|
||||
void __boot_page_erase_short( uint16_t address )
|
||||
{
|
||||
asm( "push r24" ) ;
|
||||
asm( "push r25" ) ;
|
||||
NVM.CMD = NVM_CMD_ERASE_APP_PAGE_gc ;
|
||||
asm( "pop r31" ) ;
|
||||
asm( "pop r30" ) ;
|
||||
CCP = CCP_SPM_gc ;
|
||||
asm( "spm" ) ;
|
||||
}
|
||||
|
||||
void __boot_erase_flash_buffer( uint16_t address )
|
||||
{
|
||||
asm( "movw r30,r24" ) ;
|
||||
asm( "ldi r24,0x26" ) ;
|
||||
asm("sts 0x1CA,r24");
|
||||
CCP = CCP_IOREG_gc ;
|
||||
asm( "ldi r24,1" ) ;
|
||||
asm("sts 0x1CB,r24");
|
||||
}
|
||||
|
||||
void __boot_page_fill_short( uint16_t address, uint16_t data)
|
||||
{
|
||||
asm( "push r0" ) ;
|
||||
asm( "push r1" ) ;
|
||||
asm( "movw r30,r24" ) ;
|
||||
asm( "mov r0,r22" ) ;
|
||||
asm( "mov r1,r23" ) ;
|
||||
asm( "ldi r24,0x23" ) ;
|
||||
asm("sts 0x1CA,r24");
|
||||
CCP = CCP_SPM_gc ;
|
||||
asm( "spm" ) ;
|
||||
asm( "pop r1" ) ;
|
||||
asm( "pop r0" ) ;
|
||||
}
|
||||
|
||||
void __boot_page_write_short( uint16_t address)
|
||||
{
|
||||
asm( "movw r30,r24" ) ;
|
||||
asm( "ldi r24,0x2E" ) ;
|
||||
asm("sts 0x1CA,r24");
|
||||
CCP = CCP_SPM_gc ;
|
||||
asm( "spm" ) ;
|
||||
}
|
||||
|
||||
void appStart()
|
||||
{
|
||||
// watchdogConfig(WATCHDOG_OFF);
|
||||
// __asm__ __volatile__ (
|
||||
//#ifdef VIRTUAL_BOOT_PARTITION
|
||||
// // Jump to WDT vector
|
||||
// "ldi r30,4\n"
|
||||
// "clr r31\n"
|
||||
//#else
|
||||
// // Jump to RST vector
|
||||
// "clr r30\n"
|
||||
// "clr r31\n"
|
||||
//#endif
|
||||
// "ijmp\n"
|
||||
// );
|
||||
|
||||
register void (*p)() ;
|
||||
p = 0 ;
|
||||
|
||||
if ( pgm_read_byte( (uint16_t)p ) != 0xFF )
|
||||
{
|
||||
(*p)() ;
|
||||
}
|
||||
}
|
||||
|
||||
80
BootLoaders/OrangeMultiBoot/Source/pin_defs.h
Normal file
@@ -0,0 +1,80 @@
|
||||
#if defined(__AVR_ATmega168__) || defined(__AVR_ATmega328P__) || defined(__AVR_ATmega328__) || defined(__AVR_ATmega88) || defined(__AVR_ATmega8__) || defined(__AVR_ATmega88__)
|
||||
/* Onboard LED is connected to pin PB5 in Arduino NG, Diecimila, and Duemilanove */
|
||||
#define LED_DDR DDRB
|
||||
#define LED_PORT PORTB
|
||||
#define LED_PIN PINB
|
||||
#define LED PINB5
|
||||
|
||||
/* Ports for soft UART */
|
||||
#ifdef SOFT_UART
|
||||
#define UART_PORT PORTD
|
||||
#define UART_PIN PIND
|
||||
#define UART_DDR DDRD
|
||||
#define UART_TX_BIT 1
|
||||
#define UART_RX_BIT 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(__AVR_ATmega8__)
|
||||
//Name conversion R.Wiersma
|
||||
#define UCSR0A UCSRA
|
||||
#define UDR0 UDR
|
||||
#define UDRE0 UDRE
|
||||
#define RXC0 RXC
|
||||
#define FE0 FE
|
||||
#define TIFR1 TIFR
|
||||
#define WDTCSR WDTCR
|
||||
#endif
|
||||
|
||||
/* Luminet support */
|
||||
#if defined(__AVR_ATtiny84__)
|
||||
/* Red LED is connected to pin PA4 */
|
||||
#define LED_DDR DDRA
|
||||
#define LED_PORT PORTA
|
||||
#define LED_PIN PINA
|
||||
#define LED PINA4
|
||||
/* Ports for soft UART - left port only for now. TX/RX on PA2/PA3 */
|
||||
#ifdef SOFT_UART
|
||||
#define UART_PORT PORTA
|
||||
#define UART_PIN PINA
|
||||
#define UART_DDR DDRA
|
||||
#define UART_TX_BIT 2
|
||||
#define UART_RX_BIT 3
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Sanguino support */
|
||||
#if defined(__AVR_ATmega644P__) || defined(__AVR_ATmega1284P__)
|
||||
/* Onboard LED is connected to pin PB0 on Sanguino */
|
||||
#define LED_DDR DDRB
|
||||
#define LED_PORT PORTB
|
||||
#define LED_PIN PINB
|
||||
#define LED PINB0
|
||||
|
||||
/* Ports for soft UART */
|
||||
#ifdef SOFT_UART
|
||||
#define UART_PORT PORTD
|
||||
#define UART_PIN PIND
|
||||
#define UART_DDR DDRD
|
||||
#define UART_TX_BIT 1
|
||||
#define UART_RX_BIT 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Mega support */
|
||||
#if defined(__AVR_ATmega1280__)
|
||||
/* Onboard LED is connected to pin PB7 on Arduino Mega */
|
||||
#define LED_DDR DDRB
|
||||
#define LED_PORT PORTB
|
||||
#define LED_PIN PINB
|
||||
#define LED PINB7
|
||||
|
||||
/* Ports for soft UART */
|
||||
#ifdef SOFT_UART
|
||||
#define UART_PORT PORTE
|
||||
#define UART_PIN PINE
|
||||
#define UART_DDR DDRE
|
||||
#define UART_TX_BIT 1
|
||||
#define UART_RX_BIT 0
|
||||
#endif
|
||||
#endif
|
||||
39
BootLoaders/OrangeMultiBoot/Source/stk500.h
Normal file
@@ -0,0 +1,39 @@
|
||||
/* STK500 constants list, from AVRDUDE */
|
||||
#define STK_OK 0x10
|
||||
#define STK_FAILED 0x11 // Not used
|
||||
#define STK_UNKNOWN 0x12 // Not used
|
||||
#define STK_NODEVICE 0x13 // Not used
|
||||
#define STK_INSYNC 0x14 // ' '
|
||||
#define STK_NOSYNC 0x15 // Not used
|
||||
#define ADC_CHANNEL_ERROR 0x16 // Not used
|
||||
#define ADC_MEASURE_OK 0x17 // Not used
|
||||
#define PWM_CHANNEL_ERROR 0x18 // Not used
|
||||
#define PWM_ADJUST_OK 0x19 // Not used
|
||||
#define CRC_EOP 0x20 // 'SPACE'
|
||||
#define STK_GET_SYNC 0x30 // '0'
|
||||
#define STK_GET_SIGN_ON 0x31 // '1'
|
||||
#define STK_SET_PARAMETER 0x40 // '@'
|
||||
#define STK_GET_PARAMETER 0x41 // 'A'
|
||||
#define STK_SET_DEVICE 0x42 // 'B'
|
||||
#define STK_SET_DEVICE_EXT 0x45 // 'E'
|
||||
#define STK_ENTER_PROGMODE 0x50 // 'P'
|
||||
#define STK_LEAVE_PROGMODE 0x51 // 'Q'
|
||||
#define STK_CHIP_ERASE 0x52 // 'R'
|
||||
#define STK_CHECK_AUTOINC 0x53 // 'S'
|
||||
#define STK_LOAD_ADDRESS 0x55 // 'U'
|
||||
#define STK_UNIVERSAL 0x56 // 'V'
|
||||
#define STK_PROG_FLASH 0x60 // '`'
|
||||
#define STK_PROG_DATA 0x61 // 'a'
|
||||
#define STK_PROG_FUSE 0x62 // 'b'
|
||||
#define STK_PROG_LOCK 0x63 // 'c'
|
||||
#define STK_PROG_PAGE 0x64 // 'd'
|
||||
#define STK_PROG_FUSE_EXT 0x65 // 'e'
|
||||
#define STK_READ_FLASH 0x70 // 'p'
|
||||
#define STK_READ_DATA 0x71 // 'q'
|
||||
#define STK_READ_FUSE 0x72 // 'r'
|
||||
#define STK_READ_LOCK 0x73 // 's'
|
||||
#define STK_READ_PAGE 0x74 // 't'
|
||||
#define STK_READ_SIGN 0x75 // 'u'
|
||||
#define STK_READ_OSCCAL 0x76 // 'v'
|
||||
#define STK_READ_FUSE_EXT 0x77 // 'w'
|
||||
#define STK_READ_OSCCAL_EXT 0x78 // 'x'
|
||||
2
BootLoaders/README.md
Normal file
@@ -0,0 +1,2 @@
|
||||
## Page Moved
|
||||
Moved to [/docs/Arduino_IDE_Boards.md](/docs/Arduino_IDE_Boards.md).
|
||||
1
BootLoaders/StmMultiBoot/README.md
Normal file
@@ -0,0 +1 @@
|
||||
[Source for the StmMultiBooloader](https://github.com/MikeBland/StmMultiBoot)
|
||||
BIN
BootLoaders/StmMultiBoot/StmMultiBoot.bin
Normal file
2
BootLoaders/StmMultiUSB/README.md
Normal file
@@ -0,0 +1,2 @@
|
||||
[Source for the StmMultiUSB=STM32duino-bootloader](https://github.com/rogerclarkmelbourne/STM32duino-bootloader)
|
||||
If you want the latest version, you should look for the file generic_boot20_pa1.bin.
|
||||
BIN
BootLoaders/StmMultiUSB/StmMultiUSB.bin
Normal file
657
BootLoaders/package_multi_4in1_board_index.json
Normal file
@@ -0,0 +1,657 @@
|
||||
{
|
||||
"packages": [{
|
||||
"name": "multi4in1",
|
||||
"maintainer": "Pascal Langer",
|
||||
"websiteURL": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module",
|
||||
"email": "pascal_langer@yahoo.fr",
|
||||
"help": {
|
||||
"online": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module"
|
||||
},
|
||||
"platforms": [
|
||||
{
|
||||
"name": "Multi 4-in-1 AVR Boards",
|
||||
"architecture": "avr",
|
||||
"version": "1.0.2",
|
||||
"category": "Contributed",
|
||||
"help": {
|
||||
"online": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module"
|
||||
},
|
||||
"url": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module-Boards/raw/master/archives/package_multi_4in1_avr_board_v1.0.2.tar.gz",
|
||||
"archiveFileName": "package_multi_4in1_avr_board_v1.0.2.tar.gz",
|
||||
"checksum": "SHA-256:b7e2fda37186bf696b7a769b12317737d513181096b33d9ad321ec2fd47f3f80",
|
||||
"size": "164467",
|
||||
"boards": [
|
||||
{"name": "Multi 4-in-1 (Atmega328p, 3.3V, 16MHz)"},
|
||||
{"name": "Multi 4-in-1 (OrangeRX)"}
|
||||
],
|
||||
"toolsDependencies": []
|
||||
},
|
||||
{
|
||||
"name": "Multi 4-in-1 AVR Boards",
|
||||
"architecture": "avr",
|
||||
"version": "1.0.3",
|
||||
"category": "Contributed",
|
||||
"help": {
|
||||
"online": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module"
|
||||
},
|
||||
"url": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module-Boards/raw/master/archives/package_multi_4in1_avr_board_v1.0.3.tar.gz",
|
||||
"archiveFileName": "package_multi_4in1_avr_board_v1.0.3.tar.gz",
|
||||
"checksum": "SHA-256:7d4561eebe0d7f6422f06d5719a417e15fcc0aa9cdbfc1c48a57066ce768e33c",
|
||||
"size": "164483",
|
||||
"boards": [
|
||||
{"name": "Multi 4-in-1 (Atmega328p, 3.3V, 16MHz)"},
|
||||
{"name": "Multi 4-in-1 (OrangeRX)"}
|
||||
],
|
||||
"toolsDependencies": []
|
||||
},
|
||||
{
|
||||
"name": "Multi 4-in-1 AVR Boards",
|
||||
"architecture": "avr",
|
||||
"version": "1.0.4",
|
||||
"category": "Contributed",
|
||||
"help": {
|
||||
"online": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module"
|
||||
},
|
||||
"url": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module-Boards/raw/master/archives/package_multi_4in1_avr_board_v1.0.4.tar.gz",
|
||||
"archiveFileName": "package_multi_4in1_avr_board_v1.0.4.tar.gz",
|
||||
"checksum": "SHA-256:6c51a4eb09bcd074cc651dab3f2356ea3afd358f6330aba0d8bdfaa75f718dbb",
|
||||
"size": "167975",
|
||||
"boards": [
|
||||
{"name": "Multi 4-in-1 (Atmega328p, 3.3V, 16MHz)"},
|
||||
{"name": "Multi 4-in-1 (OrangeRX)"}
|
||||
],
|
||||
"toolsDependencies": []
|
||||
},
|
||||
{
|
||||
"name": "Multi 4-in-1 AVR Boards",
|
||||
"architecture": "avr",
|
||||
"version": "1.0.5",
|
||||
"category": "Contributed",
|
||||
"help": {
|
||||
"online": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module"
|
||||
},
|
||||
"url": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module-Boards/raw/master/archives/package_multi_4in1_avr_board_v1.0.5.tar.gz",
|
||||
"archiveFileName": "package_multi_4in1_avr_board_v1.0.5.tar.gz",
|
||||
"checksum": "SHA-256:0a4754d47cdbb49ca194b15835686331530ed9d36c0db093a29ae5f865e75421",
|
||||
"size": "169830",
|
||||
"boards": [
|
||||
{"name": "Multi 4-in-1 (Atmega328p, 3.3V, 16MHz)"},
|
||||
{"name": "Multi 4-in-1 (OrangeRX)"}
|
||||
],
|
||||
"toolsDependencies": []
|
||||
},
|
||||
{
|
||||
"name": "Multi 4-in-1 AVR Boards",
|
||||
"architecture": "avr",
|
||||
"version": "1.0.6",
|
||||
"category": "Contributed",
|
||||
"help": {
|
||||
"online": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module"
|
||||
},
|
||||
"url": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module-Boards/raw/master/archives/package_multi_4in1_avr_board_v1.0.6.tar.gz",
|
||||
"archiveFileName": "package_multi_4in1_avr_board_v1.0.6.tar.gz",
|
||||
"checksum": "SHA-256:4f4cf8820e30bf6c88f280514c67ee67b9dc6649f439597cfb8d0be3a5b13bf5",
|
||||
"size": "169819",
|
||||
"boards": [
|
||||
{"name": "Multi 4-in-1 (Atmega328p, 3.3V, 16MHz)"},
|
||||
{"name": "Multi 4-in-1 (OrangeRX)"}
|
||||
],
|
||||
"toolsDependencies": []
|
||||
},
|
||||
{
|
||||
"name": "Multi 4-in-1 AVR Boards",
|
||||
"architecture": "avr",
|
||||
"version": "1.0.7",
|
||||
"category": "Contributed",
|
||||
"help": {
|
||||
"online": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module"
|
||||
},
|
||||
"url": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module-Boards/raw/master/archives/package_multi_4in1_avr_board_v1.0.7.tar.gz",
|
||||
"archiveFileName": "package_multi_4in1_avr_board_v1.0.7.tar.gz",
|
||||
"checksum": "SHA-256:453c9999e433ed1bdda2ba2b12cb7cbba7b547591db969dc6b7efb941b61cf76",
|
||||
"size": "169825",
|
||||
"boards": [
|
||||
{"name": "Multi 4-in-1 (Atmega328p, 3.3V, 16MHz)"},
|
||||
{"name": "Multi 4-in-1 (OrangeRX)"}
|
||||
],
|
||||
"toolsDependencies": []
|
||||
},
|
||||
{
|
||||
"name": "Multi 4-in-1 AVR Boards",
|
||||
"architecture": "avr",
|
||||
"version": "1.0.8",
|
||||
"category": "Contributed",
|
||||
"help": {
|
||||
"online": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module"
|
||||
},
|
||||
"url": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module-Boards/raw/master/archives/package_multi_4in1_avr_board_v1.0.8.tar.gz",
|
||||
"archiveFileName": "package_multi_4in1_avr_board_v1.0.8.tar.gz",
|
||||
"checksum": "SHA-256:8e58b8733220d56155e10bf5bec0bfe6bf96f8460b3fd49a4b45c7f9fad776cb",
|
||||
"size": "293388",
|
||||
"boards": [
|
||||
{"name": "Multi 4-in-1 (Atmega328p, 3.3V, 16MHz)"},
|
||||
{"name": "Multi 4-in-1 (OrangeRX)"}
|
||||
],
|
||||
"toolsDependencies": []
|
||||
},
|
||||
{
|
||||
"name": "Multi 4-in-1 AVR Boards",
|
||||
"architecture": "avr",
|
||||
"version": "1.0.9",
|
||||
"category": "Contributed",
|
||||
"help": {
|
||||
"online": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module"
|
||||
},
|
||||
"url": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module-Boards/raw/master/archives/package_multi_4in1_avr_board_v1.0.9.tar.gz",
|
||||
"archiveFileName": "package_multi_4in1_avr_board_v1.0.9.tar.gz",
|
||||
"checksum": "SHA-256:269c4ddcb8018be2b31f5c9e9f0814d120af492e894b8d5098a814486d56faa5",
|
||||
"size": "318437",
|
||||
"boards": [
|
||||
{"name": "Multi 4-in-1 (Atmega328p, 3.3V, 16MHz)"},
|
||||
{"name": "Multi 4-in-1 (OrangeRX)"}
|
||||
],
|
||||
"toolsDependencies": []
|
||||
},
|
||||
{
|
||||
"name": "Multi 4-in-1 AVR Boards",
|
||||
"architecture": "avr",
|
||||
"version": "1.1.0",
|
||||
"category": "Contributed",
|
||||
"help": {
|
||||
"online": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module"
|
||||
},
|
||||
"url": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module-Boards/raw/master/archives/package_multi_4in1_avr_board_v1.1.0.tar.gz",
|
||||
"archiveFileName": "package_multi_4in1_avr_board_v1.1.0.tar.gz",
|
||||
"checksum": "SHA-256:7bacf2db754ceb890a203de5ce89d97aa787a9e6462debeb44cf04830859687a",
|
||||
"size": "326431",
|
||||
"boards": [
|
||||
{"name": "Multi 4-in-1 (Atmega328p, 3.3V, 16MHz)"},
|
||||
{"name": "Multi 4-in-1 (OrangeRX)"}
|
||||
],
|
||||
"toolsDependencies": []
|
||||
},
|
||||
{
|
||||
"name": "MULTI-Module AVR Boards",
|
||||
"architecture": "avr",
|
||||
"version": "1.1.1",
|
||||
"category": "Contributed",
|
||||
"help": {
|
||||
"online": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module"
|
||||
},
|
||||
"url": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module-Boards/raw/master/archives/package_multi_4in1_avr_board_v1.1.1.tar.gz",
|
||||
"archiveFileName": "package_multi_4in1_avr_board_v1.1.1.tar.gz",
|
||||
"checksum": "SHA-256:02158258b4dbaca61bedbb6933336200d13b02ad0db981e2dda253682c482e99",
|
||||
"size": "324512",
|
||||
"boards": [
|
||||
{"name": "Multi 4-in-1 (Atmega328p, 3.3V, 16MHz)"},
|
||||
{"name": "Multi 4-in-1 (OrangeRX)"}
|
||||
],
|
||||
"toolsDependencies": []
|
||||
},
|
||||
{
|
||||
"name": "Multi 4-in-1 STM32 Board",
|
||||
"architecture": "STM32F1",
|
||||
"version": "1.0.1",
|
||||
"category": "Contributed",
|
||||
"help": {
|
||||
"online": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module"
|
||||
},
|
||||
"url": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module-Boards/raw/master/archives/package_multi_4in1_stm32_board_v1.0.1.tar.gz",
|
||||
"archiveFileName": "package_multi_4in1_stm32_board_v1.0.1.tar.gz",
|
||||
"checksum": "SHA-256:b522b5d3474308768c197a6897cad037fb54d6fac26c75678415a0908793bae3",
|
||||
"size": "10332875",
|
||||
"boards": [{
|
||||
"name": "Multi 4-in-1 (STM32F103C)"
|
||||
}],
|
||||
"toolsDependencies": [{
|
||||
"packager": "arduino",
|
||||
"name": "arm-none-eabi-gcc",
|
||||
"version": "4.8.3-2014q1"
|
||||
}]
|
||||
},
|
||||
{
|
||||
"name": "Multi 4-in-1 STM32 Board",
|
||||
"architecture": "STM32F1",
|
||||
"version": "1.0.2",
|
||||
"category": "Contributed",
|
||||
"help": {
|
||||
"online": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module"
|
||||
},
|
||||
"url": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module-Boards/raw/master/archives/package_multi_4in1_stm32_board_v1.0.2.tar.gz",
|
||||
"archiveFileName": "package_multi_4in1_stm32_board_v1.0.2.tar.gz",
|
||||
"checksum": "SHA-256:26d21dbd2fe80680ac523b8bca24b3ecf2c2016bac626826d20b651e11278287",
|
||||
"size": "10318646",
|
||||
"boards": [{
|
||||
"name": "Multi 4-in-1 (STM32F103C)"
|
||||
}],
|
||||
"toolsDependencies": [{
|
||||
"packager": "arduino",
|
||||
"name": "arm-none-eabi-gcc",
|
||||
"version": "4.8.3-2014q1"
|
||||
}]
|
||||
},
|
||||
{
|
||||
"name": "Multi 4-in-1 STM32 Board",
|
||||
"architecture": "STM32F1",
|
||||
"version": "1.0.3",
|
||||
"category": "Contributed",
|
||||
"help": {
|
||||
"online": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module"
|
||||
},
|
||||
"url": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module-Boards/raw/master/archives/package_multi_4in1_stm32_board_v1.0.3.tar.gz",
|
||||
"archiveFileName": "package_multi_4in1_stm32_board_v1.0.3.tar.gz",
|
||||
"checksum": "SHA-256:e48f1f30948b3f7be83e8b1fe2bb5c6b41be7c4d5da02503a0b4827c60926541",
|
||||
"size": "10309833",
|
||||
"boards": [{
|
||||
"name": "Multi 4-in-1 (STM32F103C)"
|
||||
}],
|
||||
"toolsDependencies": [{
|
||||
"packager": "arduino",
|
||||
"name": "arm-none-eabi-gcc",
|
||||
"version": "4.8.3-2014q1"
|
||||
}]
|
||||
},
|
||||
{
|
||||
"name": "Multi 4-in-1 STM32 Board",
|
||||
"architecture": "STM32F1",
|
||||
"version": "1.0.4",
|
||||
"category": "Contributed",
|
||||
"help": {
|
||||
"online": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module"
|
||||
},
|
||||
"url": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module-Boards/raw/master/archives/package_multi_4in1_stm32_board_v1.0.4.tar.gz",
|
||||
"archiveFileName": "package_multi_4in1_stm32_board_v1.0.4.tar.gz",
|
||||
"checksum": "SHA-256:388a4dbcd567f9d41b82955e12e8a640d9696217081c0ee6ab8c58a25aedf70f",
|
||||
"size": "10307581",
|
||||
"boards": [{
|
||||
"name": "Multi 4-in-1 (STM32F103C)"
|
||||
}],
|
||||
"toolsDependencies": [{
|
||||
"packager": "arduino",
|
||||
"name": "arm-none-eabi-gcc",
|
||||
"version": "4.8.3-2014q1"
|
||||
}]
|
||||
},
|
||||
{
|
||||
"name": "Multi 4-in-1 STM32 Board",
|
||||
"architecture": "STM32F1",
|
||||
"version": "1.0.5",
|
||||
"category": "Contributed",
|
||||
"help": {
|
||||
"online": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module"
|
||||
},
|
||||
"url": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module-Boards/raw/master/archives/package_multi_4in1_stm32_board_v1.0.5.tar.gz",
|
||||
"archiveFileName": "package_multi_4in1_stm32_board_v1.0.5.tar.gz",
|
||||
"checksum": "SHA-256:46d3b4e62fc46e6b8ca4f429974ffd2ee8cde9e29a6e0cda58f85044991a9c2b",
|
||||
"size": "10313436",
|
||||
"boards": [{
|
||||
"name": "Multi 4-in-1 (STM32F103C)"
|
||||
}],
|
||||
"toolsDependencies": [{
|
||||
"packager": "arduino",
|
||||
"name": "arm-none-eabi-gcc",
|
||||
"version": "4.8.3-2014q1"
|
||||
}]
|
||||
},
|
||||
{
|
||||
"name": "Multi 4-in-1 STM32 Board",
|
||||
"architecture": "STM32F1",
|
||||
"version": "1.0.6",
|
||||
"category": "Contributed",
|
||||
"help": {
|
||||
"online": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module"
|
||||
},
|
||||
"url": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module-Boards/raw/master/archives/package_multi_4in1_stm32_board_v1.0.6.tar.gz",
|
||||
"archiveFileName": "package_multi_4in1_stm32_board_v1.0.6.tar.gz",
|
||||
"checksum": "SHA-256:ad7a330326069a5ffb2908495b288933f68517b1247cc6636b160eb483a58284",
|
||||
"size": "10319669",
|
||||
"boards": [{
|
||||
"name": "Multi 4-in-1 (STM32F103C)"
|
||||
}],
|
||||
"toolsDependencies": [{
|
||||
"packager": "arduino",
|
||||
"name": "arm-none-eabi-gcc",
|
||||
"version": "4.8.3-2014q1"
|
||||
}]
|
||||
},
|
||||
{
|
||||
"name": "Multi 4-in-1 STM32 Board",
|
||||
"architecture": "STM32F1",
|
||||
"version": "1.0.7",
|
||||
"category": "Contributed",
|
||||
"help": {
|
||||
"online": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module"
|
||||
},
|
||||
"url": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module-Boards/raw/master/archives/package_multi_4in1_stm32_board_v1.0.7.tar.gz",
|
||||
"archiveFileName": "package_multi_4in1_stm32_board_v1.0.7.tar.gz",
|
||||
"checksum": "SHA-256:f73fded48beaee55e646a3cf36d24beeedc336873c7824683a4912f2aee9e350",
|
||||
"size": "10322111",
|
||||
"boards": [{
|
||||
"name": "Multi 4-in-1 (STM32F103C)"
|
||||
}],
|
||||
"toolsDependencies": [{
|
||||
"packager": "arduino",
|
||||
"name": "arm-none-eabi-gcc",
|
||||
"version": "4.8.3-2014q1"
|
||||
}]
|
||||
},
|
||||
{
|
||||
"name": "Multi 4-in-1 STM32 Board",
|
||||
"architecture": "STM32F1",
|
||||
"version": "1.0.8",
|
||||
"category": "Contributed",
|
||||
"help": {
|
||||
"online": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module"
|
||||
},
|
||||
"url": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module-Boards/raw/master/archives/package_multi_4in1_stm32_board_v1.0.8.tar.gz",
|
||||
"archiveFileName": "package_multi_4in1_stm32_board_v1.0.8.tar.gz",
|
||||
"checksum": "SHA-256:f8100272ec615074cf7962c2c8331014ebda78f3e4c17172b88b6dd3d83c4331",
|
||||
"size": "10319134",
|
||||
"boards": [{
|
||||
"name": "Multi 4-in-1 (STM32F103C)"
|
||||
}],
|
||||
"toolsDependencies": [{
|
||||
"packager": "arduino",
|
||||
"name": "arm-none-eabi-gcc",
|
||||
"version": "4.8.3-2014q1"
|
||||
}]
|
||||
},
|
||||
{
|
||||
"name": "Multi 4-in-1 STM32 Board",
|
||||
"architecture": "STM32F1",
|
||||
"version": "1.0.9",
|
||||
"category": "Contributed",
|
||||
"help": {
|
||||
"online": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module"
|
||||
},
|
||||
"url": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module-Boards/raw/master/archives/package_multi_4in1_stm32_board_v1.0.9.tar.gz",
|
||||
"archiveFileName": "package_multi_4in1_stm32_board_v1.0.9.tar.gz",
|
||||
"checksum": "SHA-256:c3621d1cf6580ca5c943a67dc14dc15a60e2797a4b985548abe1919486bf4a8b",
|
||||
"size": "10324251",
|
||||
"boards": [{
|
||||
"name": "Multi 4-in-1 (STM32F103C)"
|
||||
}],
|
||||
"toolsDependencies": [{
|
||||
"packager": "arduino",
|
||||
"name": "arm-none-eabi-gcc",
|
||||
"version": "4.8.3-2014q1"
|
||||
}]
|
||||
},
|
||||
{
|
||||
"name": "Multi 4-in-1 STM32 Board",
|
||||
"architecture": "STM32F1",
|
||||
"version": "1.1.0",
|
||||
"category": "Contributed",
|
||||
"help": {
|
||||
"online": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module"
|
||||
},
|
||||
"url": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module-Boards/raw/master/archives/package_multi_4in1_stm32_board_v1.1.0.tar.gz",
|
||||
"archiveFileName": "package_multi_4in1_stm32_board_v1.1.0.tar.gz",
|
||||
"checksum": "SHA-256:919ece2021757686e6892679956dcb8a01c9308a152167d61d9204656b4ed7ee",
|
||||
"size": "10333612",
|
||||
"boards": [{
|
||||
"name": "Multi 4-in-1 (STM32F103C)"
|
||||
}],
|
||||
"toolsDependencies": [{
|
||||
"packager": "arduino",
|
||||
"name": "arm-none-eabi-gcc",
|
||||
"version": "4.8.3-2014q1"
|
||||
}]
|
||||
},
|
||||
{
|
||||
"name": "Multi 4-in-1 STM32 Board",
|
||||
"architecture": "STM32F1",
|
||||
"version": "1.1.1",
|
||||
"category": "Contributed",
|
||||
"help": {
|
||||
"online": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module"
|
||||
},
|
||||
"url": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module-Boards/raw/master/archives/package_multi_4in1_stm32_board_v1.1.1.tar.gz",
|
||||
"archiveFileName": "package_multi_4in1_stm32_board_v1.1.1.tar.gz",
|
||||
"checksum": "SHA-256:549dbfa0f48f3e519a9efa96d03e8933cc72989c618826b2b570980d9c382979",
|
||||
"size": "10331547",
|
||||
"boards": [{
|
||||
"name": "Multi 4-in-1 (STM32F103C)"
|
||||
}],
|
||||
"toolsDependencies": [{
|
||||
"packager": "arduino",
|
||||
"name": "arm-none-eabi-gcc",
|
||||
"version": "4.8.3-2014q1"
|
||||
}]
|
||||
},
|
||||
{
|
||||
"name": "Multi 4-in-1 STM32 Board",
|
||||
"architecture": "STM32F1",
|
||||
"version": "1.1.2",
|
||||
"category": "Contributed",
|
||||
"help": {
|
||||
"online": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module"
|
||||
},
|
||||
"url": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module-Boards/raw/master/archives/package_multi_4in1_stm32_board_v1.1.2.tar.gz",
|
||||
"archiveFileName": "package_multi_4in1_stm32_board_v1.1.2.tar.gz",
|
||||
"checksum": "SHA-256:debfdc14df3023045a2297bc99daf7104be75f21572fc5a4f57192ffae4028f0",
|
||||
"size": "10322776",
|
||||
"boards": [{
|
||||
"name": "Multi 4-in-1 (STM32F103C)"
|
||||
}],
|
||||
"toolsDependencies": [{
|
||||
"packager": "arduino",
|
||||
"name": "arm-none-eabi-gcc",
|
||||
"version": "4.8.3-2014q1"
|
||||
}]
|
||||
},
|
||||
{
|
||||
"name": "Multi 4-in-1 STM32 Board",
|
||||
"architecture": "STM32F1",
|
||||
"version": "1.1.3",
|
||||
"category": "Contributed",
|
||||
"help": {
|
||||
"online": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module"
|
||||
},
|
||||
"url": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module-Boards/raw/master/archives/package_multi_4in1_stm32_board_v1.1.3.tar.gz",
|
||||
"archiveFileName": "package_multi_4in1_stm32_board_v1.1.3.tar.gz",
|
||||
"checksum": "SHA-256:6b9dceb033ccc31f37cebc4f025ddb862cd24a733e7c356ca2fa5719d595af89",
|
||||
"size": "10322145",
|
||||
"boards": [{
|
||||
"name": "Multi 4-in-1 (STM32F103C)"
|
||||
}],
|
||||
"toolsDependencies": [{
|
||||
"packager": "arduino",
|
||||
"name": "arm-none-eabi-gcc",
|
||||
"version": "4.8.3-2014q1"
|
||||
}]
|
||||
},
|
||||
{
|
||||
"name": "Multi 4-in-1 STM32 Board",
|
||||
"architecture": "STM32F1",
|
||||
"version": "1.1.4",
|
||||
"category": "Contributed",
|
||||
"help": {
|
||||
"online": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module"
|
||||
},
|
||||
"url": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module-Boards/raw/master/archives/package_multi_4in1_stm32_board_v1.1.4.tar.gz",
|
||||
"archiveFileName": "package_multi_4in1_stm32_board_v1.1.4.tar.gz",
|
||||
"checksum": "SHA-256:16a83a3b4409cb55aead6593396979483996080634d214ae07c8a956db2480fb",
|
||||
"size": "10322152",
|
||||
"boards": [{
|
||||
"name": "Multi 4-in-1 (STM32F103C)"
|
||||
}],
|
||||
"toolsDependencies": [{
|
||||
"packager": "arduino",
|
||||
"name": "arm-none-eabi-gcc",
|
||||
"version": "4.8.3-2014q1"
|
||||
}]
|
||||
},
|
||||
{
|
||||
"name": "Multi 4-in-1 STM32 Board",
|
||||
"architecture": "STM32F1",
|
||||
"version": "1.1.5",
|
||||
"category": "Contributed",
|
||||
"help": {
|
||||
"online": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module"
|
||||
},
|
||||
"url": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module-Boards/raw/master/archives/package_multi_4in1_stm32_board_v1.1.5.tar.gz",
|
||||
"archiveFileName": "package_multi_4in1_stm32_board_v1.1.5.tar.gz",
|
||||
"checksum": "SHA-256:2d45c95f59b4fb9fc7f7bf8caca2dd8c13b4258141c20db6169e0c7faf72e5e4",
|
||||
"size": "7930904",
|
||||
"boards": [{
|
||||
"name": "Multi 4-in-1 (STM32F103C)"
|
||||
}],
|
||||
"toolsDependencies": [{
|
||||
"packager": "arduino",
|
||||
"name": "arm-none-eabi-gcc",
|
||||
"version": "4.8.3-2014q1"
|
||||
}]
|
||||
},
|
||||
{
|
||||
"name": "Multi 4-in-1 STM32 Board",
|
||||
"architecture": "STM32F1",
|
||||
"version": "1.1.6",
|
||||
"category": "Contributed",
|
||||
"help": {
|
||||
"online": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module"
|
||||
},
|
||||
"url": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module-Boards/raw/master/archives/package_multi_4in1_stm32_board_v1.1.6.tar.gz",
|
||||
"archiveFileName": "package_multi_4in1_stm32_board_v1.1.6.tar.gz",
|
||||
"checksum": "SHA-256:d2d1ef721bbcdc3c680c6f98b4b8ab394478ac0f82d67af2f6c389a4a30789f4",
|
||||
"size": "7962942",
|
||||
"boards": [{
|
||||
"name": "Multi 4-in-1 (STM32F103C)"
|
||||
}],
|
||||
"toolsDependencies": [{
|
||||
"packager": "arduino",
|
||||
"name": "arm-none-eabi-gcc",
|
||||
"version": "4.8.3-2014q1"
|
||||
}]
|
||||
},
|
||||
{
|
||||
"name": "Multi 4-in-1 STM32 Board",
|
||||
"architecture": "STM32F1",
|
||||
"version": "1.1.7",
|
||||
"category": "Contributed",
|
||||
"help": {
|
||||
"online": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module"
|
||||
},
|
||||
"url": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module-Boards/raw/master/archives/package_multi_4in1_stm32_board_v1.1.7.tar.gz",
|
||||
"archiveFileName": "package_multi_4in1_stm32_board_v1.1.7.tar.gz",
|
||||
"checksum": "SHA-256:37cccde7eafad3d0587d28d13d5f8b2b3244bf7c83e6819b6cb08f4f468815e2",
|
||||
"size": "7966348",
|
||||
"boards": [{
|
||||
"name": "Multi 4-in-1 (STM32F103C)"
|
||||
}],
|
||||
"toolsDependencies": [{
|
||||
"packager": "arduino",
|
||||
"name": "arm-none-eabi-gcc",
|
||||
"version": "4.8.3-2014q1"
|
||||
}]
|
||||
},
|
||||
{
|
||||
"name": "Multi X-in-1 STM32 Boards",
|
||||
"architecture": "STM32F1",
|
||||
"version": "1.1.8",
|
||||
"category": "Contributed",
|
||||
"help": {
|
||||
"online": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module"
|
||||
},
|
||||
"url": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module-Boards/raw/master/archives/package_multi_4in1_stm32_board_v1.1.8.tar.gz",
|
||||
"archiveFileName": "package_multi_4in1_stm32_board_v1.1.8.tar.gz",
|
||||
"checksum": "SHA-256:e9ed8055ebf72abf37e60e1b8d1c6ee5472132ea7c0a3c4a63fbb8442613e4c2",
|
||||
"size": "7481800",
|
||||
"boards": [
|
||||
{"name": "Multi 4-in-1 (STM32F103C)"},
|
||||
{"name": "Multi 5-in-1 (Jumper T18 Internal)"}
|
||||
],
|
||||
"toolsDependencies": [{
|
||||
"packager": "arduino",
|
||||
"name": "arm-none-eabi-gcc",
|
||||
"version": "4.8.3-2014q1"
|
||||
}]
|
||||
},
|
||||
{
|
||||
"name": "Multi X-in-1 STM32 Boards",
|
||||
"architecture": "STM32F1",
|
||||
"version": "1.2.0",
|
||||
"category": "Contributed",
|
||||
"help": {
|
||||
"online": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module"
|
||||
},
|
||||
"url": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module-Boards/raw/master/archives/package_multi_4in1_stm32_board_v1.2.0.tar.gz",
|
||||
"archiveFileName": "package_multi_4in1_stm32_board_v1.2.0.tar.gz",
|
||||
"checksum": "SHA-256:754f08ca2a553701cc9112b645c079b6041107f1bf863648305e560c136a6ac5",
|
||||
"size": "7496214",
|
||||
"boards": [
|
||||
{"name": "Multi 4-in-1 (STM32F103C)"},
|
||||
{"name": "Multi 5-in-1 (Jumper T18 Internal)"}
|
||||
],
|
||||
"toolsDependencies": [{
|
||||
"packager": "arduino",
|
||||
"name": "arm-none-eabi-gcc",
|
||||
"version": "4.8.3-2014q1"
|
||||
}]
|
||||
},
|
||||
{
|
||||
"name": "Multi X-in-1 STM32 Boards",
|
||||
"architecture": "STM32F1",
|
||||
"version": "1.2.1",
|
||||
"category": "Contributed",
|
||||
"help": {
|
||||
"online": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module"
|
||||
},
|
||||
"url": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module-Boards/raw/master/archives/package_multi_4in1_stm32_board_v1.2.1.tar.gz",
|
||||
"archiveFileName": "package_multi_4in1_stm32_board_v1.2.1.tar.gz",
|
||||
"checksum": "SHA-256:c66d34afadc5b21e9e28c4d477fa03a6d55db0b74b59ff2dcb07b4d6ef06da1a",
|
||||
"size": "7496448",
|
||||
"boards": [
|
||||
{"name": "Multi 4-in-1 (STM32F103C)"},
|
||||
{"name": "Multi 5-in-1 (Jumper T18 Internal)"}
|
||||
],
|
||||
"toolsDependencies": [{
|
||||
"packager": "arduino",
|
||||
"name": "arm-none-eabi-gcc",
|
||||
"version": "4.8.3-2014q1"
|
||||
}]
|
||||
},
|
||||
{
|
||||
"name": "MULTI-Module STM32 Boards",
|
||||
"architecture": "STM32F1",
|
||||
"version": "1.2.2",
|
||||
"category": "Contributed",
|
||||
"help": {
|
||||
"online": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module"
|
||||
},
|
||||
"url": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module-Boards/raw/master/archives/package_multi_4in1_stm32_board_v1.2.2.tar.gz",
|
||||
"archiveFileName": "package_multi_4in1_stm32_board_v1.2.2.tar.gz",
|
||||
"checksum": "SHA-256:0fe4a8899438bbc31dc37714acca13968e43d75a47e59143343d83b634d2e47d",
|
||||
"size": "7485662",
|
||||
"boards": [
|
||||
{"name": "Multi X-in-1 STM32F103CB (128KB)"},
|
||||
{"name": "Multi X-in-1 STM32F103C8 (64KB)"},
|
||||
{"name": "Multi 5-in-1 (Jumper T18 Internal)"}
|
||||
],
|
||||
"toolsDependencies": [{
|
||||
"packager": "arduino",
|
||||
"name": "arm-none-eabi-gcc",
|
||||
"version": "4.8.3-2014q1"
|
||||
}]
|
||||
},
|
||||
{
|
||||
"name": "Multi 4-in-1 OrangeRX Board - DEPRECATED, USE MULTI 4-IN-1 AVR BOARDS PACKAGE INSTEAD",
|
||||
"architecture": "orangerx",
|
||||
"version": "1.0.1",
|
||||
"category": "Contributed",
|
||||
"help": {
|
||||
"online": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module"
|
||||
},
|
||||
"url": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module-Boards/raw/master/archives/package_multi_4in1_orangerx_board_v1.0.1.tar.gz",
|
||||
"archiveFileName": "package_multi_4in1_orangerx_board_v1.0.1.tar.gz",
|
||||
"checksum": "SHA-256:7287ce61028b754bb8ff947317dd15773fc7eeecd752826c707fa356b9b36dc6",
|
||||
"size": "161615",
|
||||
"boards": [{
|
||||
"name": "Multi 4-in-1 (OrangeRX)"
|
||||
}],
|
||||
"toolsDependencies": []
|
||||
}
|
||||
],
|
||||
"tools": []
|
||||
}]
|
||||
}
|
||||
1046
Lua_scripts/DSM FwdPrg_55_MIN.lua
Normal file
790
Lua_scripts/DSM FwdPrg_56_Color.lua
Normal file
@@ -0,0 +1,790 @@
|
||||
local toolName = "TNS|DSM Forward Prog v0.56 (Color) |TNE"
|
||||
local VERSION = "v0.56"
|
||||
|
||||
---- #########################################################################
|
||||
---- # #
|
||||
---- # 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 = true -- false: dont show simulation menu, 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 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 Log = assert(loadScript(DSMLIB_PATH.."DsmLogLib.lua"), "Not-Found: DSMLIB/DsmLogLib.lua")()
|
||||
local menuLib = assert(loadScript(DSMLIB_PATH.."DsmMenuLib.lua"), "Not-Found: DSMLIB/DsmMenuLib.lua")(Log, DEBUG_ON)
|
||||
local modelLib = assert(loadScript(DSMLIB_PATH.."DsmModelLib.lua"), "Not-Found: DSMLIB/DsmModelLib.lua")(Log, DEBUG_ON)
|
||||
local menuProcessor = assert(loadScript(DSMLIB_PATH.."DsmMainMenuLib.lua"), "Not-Found: DSMLIB/DsmMainMenuLib.lua")(Log, menuLib, modelLib, DEBUG_ON, SIMULATION_ON)
|
||||
|
||||
local PHASE = menuLib.PHASE
|
||||
local LINE_TYPE = menuLib.LINE_TYPE
|
||||
local DISP_ATTR = menuLib.DISP_ATTR
|
||||
local DSM_Context = menuLib.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 = 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)
|
||||
if (s==nil) then return 20 end
|
||||
-- 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 = modelLib.CreateDSMPortChannelInfo()
|
||||
|
||||
menuProcessor.done()
|
||||
Log.LOG_close() -- Reset the log
|
||||
Log.LOG_open()
|
||||
|
||||
menuProcessor = nil
|
||||
collectgarbage("collect")
|
||||
|
||||
modelLib.ReadTxModelData()
|
||||
modelLib.ST_LoadFileData()
|
||||
modelLib.CreateDSMPortChannelInfo()
|
||||
|
||||
local dsmLib = assert(loadScript(DSMLIB_PATH.."DsmFwPrgLib.lua"),"Not-Found: DSMLIB/DsmFwPrgLib.lua")
|
||||
menuProcessor = dsmLib(Log, menuLib, modelLib, DEBUG_ON)
|
||||
|
||||
dsmLib = nil
|
||||
collectgarbage("collect")
|
||||
|
||||
menuProcessor.init(toolName) -- Initialize Library
|
||||
DSM_Context.Refresh_Display = true
|
||||
end
|
||||
|
||||
local function GUI_SwitchToSIM()
|
||||
menuProcessor.done()
|
||||
Log.LOG_close()
|
||||
|
||||
menuProcessor = nil
|
||||
collectgarbage("collect")
|
||||
|
||||
local simLib = assert(loadScript(DSMLIB_PATH.."DsmSimMenuLib.lua"), "Not-Found: DSMLIB/DsmSimMenuLib.lua")
|
||||
menuProcessor = simLib(Log, menuLib, modelLib, DEBUG_ON)
|
||||
|
||||
simLib = nil
|
||||
collectgarbage("collect")
|
||||
|
||||
menuProcessor.init(toolName) -- Initialize Library
|
||||
DSM_Context.Refresh_Display = true
|
||||
end
|
||||
|
||||
local function GUI_SwitchToSetupMenu()
|
||||
menuProcessor.done()
|
||||
|
||||
menuProcessor = nil
|
||||
collectgarbage("collect")
|
||||
|
||||
local setupLib = assert(loadScript(DSMLIB_PATH.."DsmSetupMenuLib.lua"), "Not-Found: DSMLIB/DsmSetupMenuLib.lua")
|
||||
menuProcessor = setupLib(Log, menuLib, modelLib, DEBUG_ON, SIMULATION_ON)
|
||||
|
||||
setupLib = nil
|
||||
collectgarbage("collect")
|
||||
|
||||
menuProcessor.init(toolName) -- Initialize Library
|
||||
DSM_Context.Refresh_Display = true
|
||||
end
|
||||
|
||||
local function GUI_SwitchToMainMenu()
|
||||
print("SWITCHING TO MAIN MENU")
|
||||
menuProcessor.done()
|
||||
|
||||
menuProcessor = nil
|
||||
collectgarbage("collect")
|
||||
|
||||
local mainMenuLib = assert(loadScript(DSMLIB_PATH.."DsmMainMenuLib.lua"), "Not-Found: DSMLIB/DsmMainMenuLib.lua")
|
||||
menuProcessor = mainMenuLib(Log, menuLib, modelLib, DEBUG_ON, SIMULATION_ON)
|
||||
|
||||
mainMenuLib = nil
|
||||
collectgarbage("collect")
|
||||
|
||||
menuProcessor.init(toolName) -- Initialize Library
|
||||
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 menuLib.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 = (menuLib.isDisplayAttr(line.TextAttr,DISP_ATTR._BOLD) and BOLD) or 0
|
||||
|
||||
if menuLib.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 menuLib.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 (menuLib.isFlightModeLine(line)) then
|
||||
-- Display Header + Value together
|
||||
header = menuLib.GetFlightModeValue(line)
|
||||
|
||||
-- Bold Text???
|
||||
bold = (menuLib.isDisplayAttr(line.TextAttr,DISP_ATTR._BOLD) and BOLD) or 0
|
||||
|
||||
if menuLib.isDisplayAttr(line.TextAttr,DISP_ATTR._RIGHT) then -- Right Align
|
||||
local tw = my_lcd_sizeText(header)+4
|
||||
x = LCD_X_LINE_VALUE - tw -- Right
|
||||
elseif menuLib.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 (value==nil) then return end
|
||||
|
||||
if not menuLib.isFlightModeLine(line) then
|
||||
if menuLib.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 menuLib.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
|
||||
|
||||
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 == menuLib.BACK_BUTTON)
|
||||
GUI_addTouchButton(437-5,LCD_Y_MENU_TITLE+3,47,LCD_Y_LINE_HEIGHT,menuLib.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 == menuLib.NEXT_BUTTON)
|
||||
GUI_addTouchButton(437-5,LCD_Y_LOWER_BUTTONS,47,LCD_Y_LINE_HEIGHT,menuLib.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 == menuLib.PREV_BUTTON)
|
||||
GUI_addTouchButton(10,LCD_Y_LOWER_BUTTONS,47,LCD_Y_LINE_HEIGHT,menuLib.PREV_BUTTON)
|
||||
end
|
||||
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 menuLib.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 menuLib.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
|
||||
-- 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)
|
||||
return
|
||||
end
|
||||
|
||||
local header = "DSM Forward Programming "..VERSION.." "
|
||||
if ctx.Phase ~= PHASE.RX_VERSION then
|
||||
header = header .. 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)
|
||||
|
||||
-- Getting RX Version
|
||||
if ctx.Phase == PHASE.RX_VERSION then
|
||||
if (ctx.isReset) then
|
||||
lcd.drawText(LCD_X_LINE_TITLE,100, menuLib.Get_Text(0x301), BLINK) -- Resetting...
|
||||
else
|
||||
lcd.drawText(LCD_X_LINE_TITLE,100,menuLib.Get_Text(0x300), BLINK) -- Not valid RX
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
|
||||
local menu = ctx.Menu
|
||||
if menu.Text == nil then return end
|
||||
|
||||
----- Draw RX Menu ---------
|
||||
GUI_Display_Menu(menu)
|
||||
|
||||
-- Sending TX Information???
|
||||
if (ctx.Phase==PHASE.MENU_REQ_TX_INFO) then
|
||||
--lcd.drawFilledRectangle(x-5, y-2, w, h, selectedBGColor)
|
||||
--lcd.drawRectangle(x-5, y-2, w, h, frameColor)
|
||||
lcd.drawText(LCD_X_LINE_TITLE,100, "Sending CH"..(ctx.CurLine+1)) -- Channel Info
|
||||
return
|
||||
end
|
||||
|
||||
for i = 0, menuLib.MAX_MENU_LINES do
|
||||
local line = ctx.MenuLines[i]
|
||||
|
||||
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
|
||||
local value = nil
|
||||
if line.Val ~= nil then
|
||||
value = line.Val
|
||||
if menuLib.isListLine(line) then -- for Lists of Strings, get the text
|
||||
value = menuLib.Get_List_Text(line.Val + line.TextStart) -- TextStart is the initial offset for text
|
||||
-- Complentary IMAGE for this value to Display??
|
||||
local offset = 0
|
||||
if (line.Type==LINE_TYPE.LIST_MENU_ORI) then offset = offset + 0x100 end --FH6250 hack
|
||||
|
||||
local imgData = menuLib.Get_List_Text_Img(line.Val + line.TextStart + offset)
|
||||
|
||||
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
|
||||
end -- if Line[i]~=nil
|
||||
GUI_Display_Line_Value(i, line, value, i == ctx.SelLine, i == ctx.EditLine)
|
||||
end
|
||||
end -- if ~MENU
|
||||
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
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
local function GUI_RotEncVal(line, dir) -- return encoder speed to inc or dec values
|
||||
|
||||
if menuLib.isListLine(line) then return dir end
|
||||
|
||||
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 Log.LOG_write("%s: EVT_TOUCH_TAP %d,%d\n",menuLib.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 Log.LOG_write("%s: EVT_VIRTUAL_EXIT\n",menuLib.phase2String(ctx.Phase)) end
|
||||
if ctx.Phase == PHASE.RX_VERSION then
|
||||
menuLib.ChangePhase(PHASE.EXIT_DONE) -- 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
|
||||
menuLib.Value_Write_Validate(line)
|
||||
elseif (menu.BackId > 0 ) then -- Back??
|
||||
ctx.SelLine = menuLib.BACK_BUTTON
|
||||
event = EVT_VIRTUAL_ENTER
|
||||
else
|
||||
menuLib.ChangePhase(PHASE.EXIT)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if ctx.Phase == PHASE.RX_VERSION then return end
|
||||
|
||||
if event == EVT_VIRTUAL_NEXT then
|
||||
ctx.Refresh_Display=true
|
||||
if (DEBUG_ON) then Log.LOG_write("%s: EVT_VIRTUAL_NEXT\n",menuLib.phase2String(ctx.Phase)) end
|
||||
if ctx.isEditing() then -- Editing a Line, need to inc the value
|
||||
local line=ctx.MenuLines[ctx.EditLine]
|
||||
menuLib.Value_Add(line, editInc or GUI_RotEncVal(line, 1))
|
||||
else -- not editing, move selected line to NEXT
|
||||
menuLib.MoveSelectionLine(1)
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
if event == EVT_VIRTUAL_PREV then
|
||||
ctx.Refresh_Display=true
|
||||
if (DEBUG_ON) then Log.LOG_write("%s: EVT_VIRTUAL_PREV\n",menuLib.phase2String(ctx.Phase)) end
|
||||
if ctx.isEditing() then -- Editiing a line, need to dec the value
|
||||
local line=ctx.MenuLines[ctx.EditLine]
|
||||
menuLib.Value_Add(line, editInc or GUI_RotEncVal(line, -1))
|
||||
else -- not editing, move selected line to PREV
|
||||
menuLib.MoveSelectionLine(-1)
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
if event == EVT_VIRTUAL_ENTER_LONG then
|
||||
ctx.Refresh_Display=true
|
||||
if (DEBUG_ON) then Log.LOG_write("%s: EVT_VIRTUAL_ENTER_LONG\n",menuLib.phase2String(ctx.Phase)) end
|
||||
if ctx.isEditing() then
|
||||
-- reset the value to default
|
||||
menuLib.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 Log.LOG_write("%s: EVT_VIRTUAL_ENTER, SelLine=%d\n",menuLib.phase2String(ctx.Phase), ctx.SelLine) end
|
||||
if ctx.SelLine == menuLib.BACK_BUTTON then -- Back
|
||||
if (menu.BackId==0xFFF9) then
|
||||
-- SPECIAL Main Menu
|
||||
GUI_SwitchToMainMenu()
|
||||
else
|
||||
menuLib.GotoMenu(menu.BackId,0x80)
|
||||
end
|
||||
elseif ctx.SelLine == menuLib.NEXT_BUTTON then -- Next
|
||||
menuLib.GotoMenu(menu.NextId,0x82)
|
||||
elseif ctx.SelLine == menuLib.PREV_BUTTON then -- Prev
|
||||
menuLib.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()
|
||||
elseif (menuLines[ctx.SelLine].ValId==0xFFF3) then
|
||||
-- SPECIAL Settup Menu
|
||||
GUI_SwitchToSetupMenu()
|
||||
elseif (menuLines[ctx.SelLine].ValId==0xFFF9) then
|
||||
-- SPECIAL Settup Menu
|
||||
GUI_SwitchToMainMenu()
|
||||
else
|
||||
menuLib.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????
|
||||
menuLib.Value_Write_Validate(menuLines[ctx.SelLine])
|
||||
else -- Edit the current value
|
||||
ctx.EditLine = ctx.SelLine
|
||||
originalValue = menuLines[ctx.SelLine].Val
|
||||
menuLib.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()
|
||||
Log.LOG_open()
|
||||
|
||||
init_colors()
|
||||
modelLib.ReadTxModelData()
|
||||
modelLib.ST_LoadFileData()
|
||||
modelLib.CreateDSMPortChannelInfo()
|
||||
|
||||
menuLib.Init()
|
||||
menuProcessor.init()
|
||||
return 0
|
||||
end
|
||||
|
||||
------------------------------------------------------------------------------------------------------------
|
||||
-- Main
|
||||
local function DSM_Run(event,touchState)
|
||||
local ctx = DSM_Context
|
||||
|
||||
if event == nil then
|
||||
error("Cannot be run as a model script!")
|
||||
Log.LOG_close()
|
||||
return 2
|
||||
end
|
||||
|
||||
if (warningScreenON) then
|
||||
return GUI_Warning(event,touchState)
|
||||
end
|
||||
|
||||
GUI_HandleEvent(event,touchState)
|
||||
|
||||
local ret = menuProcessor.run() -- Handle Send and Receive DSM Forward Programming Messages
|
||||
|
||||
if ctx.Phase == PHASE.INIT then return 0 end
|
||||
|
||||
|
||||
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 or ctx.Phase==PHASE.MENU_REQ_TX_INFO) 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
|
||||
Log.LOG_close()
|
||||
return 2
|
||||
else
|
||||
return 0
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
return { init=DSM_Init, run=DSM_Run }
|
||||
1088
Lua_scripts/DSM FwdPrg_56_MIN.lua
Normal file
951
Lua_scripts/DSM FwdPrg_56_STUP.lua
Normal file
@@ -0,0 +1,951 @@
|
||||
local toolName = "TNS|DSM Frwd Prog v0.56a (MIN-SETUP)|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. #
|
||||
---- # #
|
||||
---- #########################################################################
|
||||
|
||||
|
||||
local VERSION = "v0.56"
|
||||
local DSMLIB_PATH = "/SCRIPTS/TOOLS/DSMLIB/"
|
||||
local DATA_PATH = "/MODELS/DSMDATA"
|
||||
|
||||
local LOG_FILE = "/LOGS/dsm_min_log.txt"
|
||||
|
||||
-- Phase
|
||||
local PH_INIT = 0
|
||||
local PH_RX_VER, PH_TITLE = 1, 2
|
||||
local PH_VAL_CHANGING, PH_VAL_EDITING, PH_VAL_EDIT_END = 6, 7, 8
|
||||
local PH_WAIT_CMD, PH_EXIT_REQ, PH_EXIT_DONE = 9, 10, 11
|
||||
|
||||
-- Line Types
|
||||
local LT_MENU, LT_LIST_NC = 0x1C, 0x6C
|
||||
|
||||
local Phase = PH_INIT
|
||||
|
||||
local Text = {}
|
||||
local List_Text = {}
|
||||
local List_Text_Img = {}
|
||||
|
||||
local originalValue = 0
|
||||
|
||||
local ctx_SelLine = 0 -- Current Selected Line
|
||||
local ctx_EditLine = nil -- Current Editing Line
|
||||
|
||||
local Menu = { MenuId = 0, Text = "", TextId = 0, PrevId = 0, NextId = 0, BackId = 0 }
|
||||
local MenuLines = {}
|
||||
|
||||
local logFile = nil
|
||||
|
||||
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 TX_CHANNELS = 12
|
||||
|
||||
local AT_PLANE = 0
|
||||
|
||||
local aircraft_type_text = {[0]="Plane","Heli","Glider","Drone"}
|
||||
|
||||
local WT_A1 = 0
|
||||
local WT_A2 = 1
|
||||
local WT_FLPR = 2
|
||||
local WT_A1_F1 = 3
|
||||
local WT_A2_F1 = 4
|
||||
local WT_A2_F2 = 5
|
||||
local WT_ELEVON_A = 6
|
||||
local WT_ELEVON_B = 7
|
||||
|
||||
local wing_type_text = {[0]="Normal","Dual Ail","Flapperon", "Ail + Flp","Dual Ail + Flp","Dual Ail/Flp","Elevon A","Elevon B"}
|
||||
|
||||
local TT_R1 = 0
|
||||
local TT_R1_E1 = 1
|
||||
local TT_R1_E2 = 2
|
||||
local TT_R2_E1 = 3
|
||||
local TT_R2_E2 = 4
|
||||
local TT_VT_A = 5
|
||||
local TT_VT_B = 6
|
||||
local TT_TLRN_A = 7
|
||||
local TT_TLRN_B = 8
|
||||
local TT_TLRN_A_R2 = 9
|
||||
local TT_TLRN_B_R2 = 10
|
||||
|
||||
local tail_type_text = {[0]="Rud Only","Normal","Rud + Dual Ele","Dual Rud + Elv","Dual Rud/Ele",
|
||||
"VTail A","VTail B","Taileron A","Taileron B",
|
||||
"Taileron A + Dual Rud","Taileron B + Dual Rud"
|
||||
}
|
||||
|
||||
local MT_NORMAL = 0
|
||||
local MT_REVERSE = 1
|
||||
|
||||
local P1 = 0
|
||||
local P2 = 1
|
||||
local P3 = 2
|
||||
local P4 = 3
|
||||
local P5 = 4
|
||||
local P6 = 5
|
||||
local P7 = 6
|
||||
local P8 = 7
|
||||
--local P9 = 8
|
||||
--local P10 = 9
|
||||
|
||||
local MV_AIRCRAFT_TYPE = 1001
|
||||
local MV_WING_TYPE = 1002
|
||||
local MV_TAIL_TYPE = 1003
|
||||
|
||||
local MV_CH_BASE = 1010
|
||||
local MV_CH_THR = 1010
|
||||
|
||||
local MV_CH_L_AIL = 1011
|
||||
local MV_CH_R_AIL = 1012
|
||||
local MV_CH_L_FLP = 1013
|
||||
local MV_CH_R_FLP = 1014
|
||||
|
||||
local MV_CH_L_RUD = 1015
|
||||
local MV_CH_R_RUD = 1016
|
||||
local MV_CH_L_ELE = 1017
|
||||
local MV_CH_R_ELE = 1018
|
||||
|
||||
local MV_PORT_BASE = 1020
|
||||
local MV_P1_MODE = 1020
|
||||
--local MV_P2_MODE = 1021
|
||||
--local MV_P3_MODE = 1022
|
||||
--local MV_P4_MODE = 1023
|
||||
--local MV_P5_MODE = 1024
|
||||
local MV_P6_MODE = 1025
|
||||
--local MV_P7_MODE = 1026
|
||||
--local MV_P8_MODE = 1027
|
||||
--local MV_P9_MODE = 1028
|
||||
--local MV_P10_MODE = 1029
|
||||
|
||||
local MV_DATA_END = 1040
|
||||
|
||||
-- MENU DATA Management
|
||||
local M_DB = {} -- Store the variables used in the Menus.
|
||||
|
||||
local lastGoodMenu=0
|
||||
|
||||
local currATyp = -1
|
||||
local currTTyp = -1
|
||||
local currWTyp = -1
|
||||
|
||||
local menuDataChanged = false
|
||||
|
||||
local MODEL = {
|
||||
modelName = "", -- The name of the model comming from OTX/ETX
|
||||
hashName = nil,
|
||||
modelOutputChannel = {}, -- Output information from OTX/ETX
|
||||
|
||||
TX_CH_TEXT= { },
|
||||
PORT_TEXT = { },
|
||||
|
||||
DSM_ChannelInfo = {} -- Data Created by DSM Configuration Script
|
||||
}
|
||||
|
||||
local function gc()
|
||||
collectgarbage("collect")
|
||||
end
|
||||
|
||||
--[[
|
||||
local function gcTable(t)
|
||||
if type(t)=="table" then
|
||||
for i,v in pairs(t) do
|
||||
if type(v) == "table" then
|
||||
gcTable(v)
|
||||
end
|
||||
t[i] = nil
|
||||
end
|
||||
end
|
||||
gc()
|
||||
return t
|
||||
end
|
||||
--]]
|
||||
|
||||
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
|
||||
|
||||
-- Saves MENU_DATA to a file
|
||||
local function ST_SaveFileData()
|
||||
local fname = MODEL.hashName
|
||||
|
||||
print("Saving File:"..fname)
|
||||
local dataFile = assert(io.open(DATA_PATH .. "/" .. fname, "w"),"Please create "..DATA_PATH.." folder") -- write File
|
||||
|
||||
-- Foreach MENU_DATA with a value write Var_Id:Value into file
|
||||
for i = 0, MV_DATA_END do
|
||||
if (M_DB[i]~=nil) then
|
||||
io.write(dataFile,string.format("%s:%s\n",i,M_DB[i]))
|
||||
end
|
||||
end
|
||||
io.close(dataFile)
|
||||
end
|
||||
|
||||
local function tailTypeCompatible(a,b)
|
||||
|
||||
local function normalize(tt)
|
||||
if (tt==TT_TLRN_A or tt==TT_TLRN_B) then
|
||||
return TT_TLRN_A
|
||||
elseif (tt==TT_TLRN_A_R2 or tt==TT_TLRN_B_R2) then
|
||||
return TT_TLRN_A_R2
|
||||
elseif (tt==TT_VT_A or tt==TT_VT_B) then
|
||||
return TT_VT_A
|
||||
else
|
||||
return tt
|
||||
end
|
||||
end
|
||||
|
||||
return (normalize(a)==normalize(b))
|
||||
end
|
||||
|
||||
local function ST_PlaneWingInit(wingType)
|
||||
--print("Change Plane WingType:"..wing_type_text[wingType])
|
||||
|
||||
M_DB[MV_WING_TYPE] = wingType
|
||||
|
||||
-- Clear all Wing Data
|
||||
M_DB[MV_CH_L_AIL] = nil
|
||||
M_DB[MV_CH_R_AIL] = nil
|
||||
M_DB[MV_CH_L_FLP] = nil
|
||||
M_DB[MV_CH_R_FLP] = nil
|
||||
|
||||
M_DB[MV_CH_THR] = P1
|
||||
|
||||
-- Default Channel Assisgments for each Wing type
|
||||
|
||||
if (wingType==WT_A1) then
|
||||
M_DB[MV_CH_L_AIL] = P2
|
||||
elseif (wingType==WT_A2 or wingType==WT_FLPR) then
|
||||
M_DB[MV_CH_L_AIL] = P6
|
||||
M_DB[MV_CH_R_AIL] = P2
|
||||
elseif (wingType==WT_A1_F1) then
|
||||
M_DB[MV_CH_L_AIL] = P2
|
||||
M_DB[MV_CH_L_FLP] = P6
|
||||
elseif (wingType==WT_A2_F1) then
|
||||
M_DB[MV_CH_L_AIL] = P6
|
||||
M_DB[MV_CH_R_AIL] = P2
|
||||
M_DB[MV_CH_L_FLP] = P5
|
||||
elseif (wingType==WT_A2_F2) then
|
||||
M_DB[MV_CH_L_AIL] = P6
|
||||
M_DB[MV_CH_R_AIL] = P2
|
||||
M_DB[MV_CH_R_FLP] = P5
|
||||
M_DB[MV_CH_L_FLP] = P7
|
||||
elseif (wingType==WT_ELEVON_A) then
|
||||
M_DB[MV_CH_L_AIL] = P2
|
||||
M_DB[MV_CH_R_AIL] = P3
|
||||
elseif (wingType==WT_ELEVON_B) then
|
||||
M_DB[MV_CH_L_AIL] = P3
|
||||
M_DB[MV_CH_R_AIL] = P2
|
||||
else -- Assume normal
|
||||
print("ERROR: Invalid Wing Type")
|
||||
end
|
||||
end
|
||||
|
||||
local function ST_PlaneTailInit(tailType)
|
||||
if (M_DB[MV_WING_TYPE]==WT_ELEVON_A or
|
||||
M_DB[MV_WING_TYPE]==WT_ELEVON_B) then
|
||||
tailType = TT_R1 -- Delta only have ruder
|
||||
end
|
||||
|
||||
--print("Change Plane Tail Type:"..tail_type_text[tailType])
|
||||
|
||||
-- Clear all data for Tail
|
||||
M_DB[MV_TAIL_TYPE] = tailType
|
||||
M_DB[MV_CH_L_ELE] = nil
|
||||
M_DB[MV_CH_R_ELE] = nil
|
||||
M_DB[MV_CH_L_RUD] = nil
|
||||
M_DB[MV_CH_R_RUD] = nil
|
||||
|
||||
-- Setup Channels for different Tail types
|
||||
if (tailType == TT_R1) then
|
||||
M_DB[MV_CH_L_RUD] = P4
|
||||
elseif (tailType == TT_R1_E1) then
|
||||
M_DB[MV_CH_L_ELE] = P3
|
||||
M_DB[MV_CH_L_RUD] = P4
|
||||
elseif (tailType == TT_R1_E2) then
|
||||
M_DB[MV_CH_L_ELE] = P5
|
||||
M_DB[MV_CH_R_ELE] = P3
|
||||
M_DB[MV_CH_L_RUD] = P4
|
||||
elseif (tailType == TT_R2_E1) then
|
||||
M_DB[MV_CH_L_ELE] = P3
|
||||
M_DB[MV_CH_L_RUD] = P4
|
||||
M_DB[MV_CH_R_RUD] = P5
|
||||
elseif (tailType == TT_R2_E2) then
|
||||
M_DB[MV_CH_L_ELE] = P5
|
||||
M_DB[MV_CH_R_ELE] = P3
|
||||
M_DB[MV_CH_L_RUD] = P4
|
||||
M_DB[MV_CH_R_RUD] = P6
|
||||
elseif (tailType == TT_VT_A or tailType == TT_VT_B) then
|
||||
M_DB[MV_CH_L_ELE] = P3
|
||||
M_DB[MV_CH_R_ELE] = P4
|
||||
elseif (tailType == TT_TLRN_A or tailType == TT_TLRN_B or
|
||||
tailType == TT_TLRN_A_R2 or tailType == TT_TLRN_B_R2) then
|
||||
M_DB[MV_CH_L_RUD] = P4
|
||||
M_DB[MV_CH_L_ELE] = P5
|
||||
M_DB[MV_CH_R_ELE] = P3
|
||||
else -- Assume Normal
|
||||
print("ERROR:invalid Tail Type")
|
||||
end
|
||||
|
||||
if (tailType == TT_TLRN_A_R2 or tailType == TT_TLRN_B_R2) then
|
||||
M_DB[MV_CH_R_RUD] = P8
|
||||
end
|
||||
end
|
||||
|
||||
local function ST_AircraftInit(aircraftType)
|
||||
M_DB[MV_AIRCRAFT_TYPE] = aircraftType
|
||||
ST_PlaneWingInit(WT_A1)
|
||||
ST_PlaneTailInit(TT_R1_E1)
|
||||
end
|
||||
|
||||
|
||||
-- Setup Initial Default Data for the Menus
|
||||
local function ST_Default_Data()
|
||||
ST_AircraftInit(AT_PLANE)
|
||||
|
||||
for i=0,9 do
|
||||
M_DB[MV_P1_MODE+i] = MT_NORMAL + MODEL.modelOutputChannel[P1+i].revert
|
||||
end
|
||||
end
|
||||
|
||||
local function MenuLinePostProcessing(line)
|
||||
line.MenuId = Menu.MenuId
|
||||
|
||||
if line.Type == LT_MENU then
|
||||
-- nothing to do on menu entries
|
||||
line.Val=nil
|
||||
elseif line.Type == LT_LIST_NC then
|
||||
-- Normalize Min/Max to be relative to Zero
|
||||
line.TextStart = line.Min
|
||||
line.Def = line.Def - line.Min -- normalize default value
|
||||
line.Max = line.Max - line.Min -- normalize max index
|
||||
line.Min = 0 -- min index
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
local function portUse(p)
|
||||
local out = nil
|
||||
if p==M_DB[MV_CH_THR] then out = "Thr"
|
||||
elseif p == M_DB[MV_CH_L_AIL] then
|
||||
out=(M_DB[MV_CH_R_AIL] and "Ail_L") or "Ail"
|
||||
elseif p == M_DB[MV_CH_R_AIL] then out="Ail_R"
|
||||
elseif p == M_DB[MV_CH_L_ELE] then
|
||||
out=(M_DB[MV_CH_R_ELE] and "Ele_L") or "Ele"
|
||||
elseif p == M_DB[MV_CH_R_ELE] then out="Ele_R"
|
||||
elseif p == M_DB[MV_CH_L_RUD] then
|
||||
out=(M_DB[MV_CH_R_RUD] and "Rud_L") or "Rud"
|
||||
elseif p == M_DB[MV_CH_R_RUD] then out="Rud-R"
|
||||
elseif p == M_DB[MV_CH_L_FLP] then
|
||||
out=(M_DB[MV_CH_R_FLP] and "Flp_L") or "Flp"
|
||||
elseif p == M_DB[MV_CH_R_FLP] then out="Flp_R"
|
||||
else
|
||||
out = ""
|
||||
end
|
||||
return out
|
||||
end
|
||||
|
||||
-- Creates the menus to Render with the GUI
|
||||
local function ST_LoadMenu(menuId)
|
||||
|
||||
local function Header(p)
|
||||
return MODEL.PORT_TEXT[p].." "..portUse(p)
|
||||
end
|
||||
|
||||
local function generateGyroReverse(menuId, P_BASE, V_BASE)
|
||||
for i=0,4 do
|
||||
MenuLines[i] = { Type = LT_LIST_NC, Text=Header(P_BASE+i), TextId = 0, ValId = V_BASE+i, Min=45, Max=46, Def=45, Val=M_DB[V_BASE+i] }
|
||||
end
|
||||
|
||||
MenuLines[5] = { Type = LT_MENU, Text="Only TAER affects AS3X/SAFE react dir", TextId = 0, ValId = menuId }
|
||||
MenuLines[6] = { Type = LT_MENU, Text="If changes, RX 'Relearn Servo'", TextId = 0, ValId = menuId }
|
||||
|
||||
ctx_SelLine = 0
|
||||
end
|
||||
|
||||
-- Begin
|
||||
for i = 0, 6 do -- clear menu
|
||||
MenuLines[i] = { MenuId = 0, lineNum = 0, Type = 0 }
|
||||
end
|
||||
|
||||
|
||||
if (menuId==0x1000) then -- MAIN MENU
|
||||
Menu = { MenuId = 0x1000, Text = "Save-Exit ("..MODEL.modelName..")", PrevId = 0, NextId = 0, BackId = 0, TextId=0 }
|
||||
|
||||
if (true) then
|
||||
MenuLines[4] = { Type = LT_MENU, Text="Save Changes", TextId = 0, ValId = 0x1005 }
|
||||
MenuLines[5] = { Type = LT_MENU, Text="Discard Changes", TextId = 0, ValId = 0xFFF9 }
|
||||
ctx_SelLine = 4
|
||||
end
|
||||
lastGoodMenu = menuId
|
||||
elseif (menuId==0x1001) then -- MODEL SETUP
|
||||
local backId = 0xFFF9 -- No changes, just exit
|
||||
local title = "Setup ("..MODEL.modelName..")"
|
||||
if (menuDataChanged) then
|
||||
backId = 0x1000 -- Go to Save menu
|
||||
title = title.." *"
|
||||
end
|
||||
Menu = { MenuId = 0x1001, Text = title, PrevId = 0, NextId = 0, BackId = backId, TextId=0 }
|
||||
MenuLines[0] = { Type = LT_MENU, Text = "Aircraft Setup", ValId = 0x1010,TextId=0 }
|
||||
MenuLines[1] = { Type = LT_MENU, Text = "Wing & Tail Channels ", ValId = 0x1020, TextId=0 }
|
||||
MenuLines[3] = { Type = LT_MENU, Text = "Gyro Channel Reverse", ValId = 0x1030, TextId=0 }
|
||||
MenuLines[5] = { Type = LT_MENU, Text = "WARNING: Changing of Aircraft", ValId = 0x1001, TextId=0 }
|
||||
MenuLines[6] = { Type = LT_MENU, Text = "deletes prev Ch/Port assgmt.", ValId = 0x1001, TextId=0 }
|
||||
|
||||
ctx_SelLine = 0
|
||||
lastGoodMenu = menuId
|
||||
elseif (menuId==0x1005) then
|
||||
ST_SaveFileData()
|
||||
menuDataChanged = false
|
||||
|
||||
local msg1 = "Data saved to: "
|
||||
local msg2 = " ../DSMLIB/"..MODEL.hashName
|
||||
|
||||
Menu = { MenuId = 0x1005, Text = "Config Saved", PrevId = 0, NextId = 0, BackId = 0, TextId=0 }
|
||||
MenuLines[2] = { Type = LT_MENU, Text=msg1, TextId = 0, ValId = 0x1005 }
|
||||
MenuLines[3] = { Type = LT_MENU, Text=msg2, TextId = 0, ValId = 0x1005 }
|
||||
MenuLines[6] = { Type = LT_MENU, Text="Complete", TextId = 0, ValId = 0xFFF9 }
|
||||
ctx_SelLine = 6
|
||||
lastGoodMenu = menuId
|
||||
elseif (menuId==0x1010) then
|
||||
Menu = { MenuId = 0x1010, Text = "Aircraft", PrevId = 0, NextId = 0x1011, BackId = 0x1001, TextId=0 }
|
||||
MenuLines[5] = { Type = LT_LIST_NC, Text="Aircraft Type", TextId = 0, ValId = MV_AIRCRAFT_TYPE, Min=15, Max=15, Def=15, Val=M_DB[MV_AIRCRAFT_TYPE] }
|
||||
ctx_SelLine = 5
|
||||
lastGoodMenu = menuId
|
||||
elseif (menuId==0x1011) then
|
||||
Menu = { MenuId = 0x1011, Text = "Model Type: "..aircraft_type_text[currATyp], PrevId = 0, NextId = 0x1020, BackId = 0x1010, TextId=0 }
|
||||
MenuLines[5] = { Type = LT_LIST_NC, Text="Wing Type", TextId = 0, ValId = MV_WING_TYPE, Min=20, Max=27, Def=20, Val=M_DB[MV_WING_TYPE] }
|
||||
MenuLines[6] = { Type = LT_LIST_NC, Text="Tail Type", TextId = 0, ValId = MV_TAIL_TYPE, Min=30, Max=40, Def=30, Val=M_DB[MV_TAIL_TYPE] }
|
||||
ctx_SelLine = 5
|
||||
lastGoodMenu = menuId
|
||||
elseif (menuId==0x1020) then
|
||||
------ WING SETUP -------
|
||||
local thr = M_DB[MV_CH_THR]
|
||||
local leftAil = M_DB[MV_CH_L_AIL]
|
||||
local rightAil = M_DB[MV_CH_R_AIL]
|
||||
local leftFlap = M_DB[MV_CH_L_FLP]
|
||||
local rightFlap = M_DB[MV_CH_R_FLP]
|
||||
|
||||
local thrText = "Thr"
|
||||
local leftAilText = "Left Ail"
|
||||
local rightAilText = "Right Ail"
|
||||
local leftFlapText = "Left Flap"
|
||||
local rightFlapText = "Right Flap"
|
||||
|
||||
if (rightAil==nil) then leftAilText = "Aileron" end
|
||||
if (rightFlap==nil) then leftFlapText = "Flap" end
|
||||
|
||||
local title = aircraft_type_text[currATyp].." Wing:"..wing_type_text[currWTyp]
|
||||
|
||||
Menu = { MenuId = 0x1020, Text = title, PrevId = 0, NextId = 0x1021, BackId = 0x1011, TextId=0 }
|
||||
|
||||
MenuLines[0] = { Type = LT_LIST_NC, Text=thrText, TextId = 0, ValId = MV_CH_THR, Min=0, Max=10, Def=0, Val= thr }
|
||||
|
||||
MenuLines[2] = { Type = LT_LIST_NC, Text=leftAilText, TextId = 0, ValId = MV_CH_L_AIL, Min=0, Max=9, Def=0, Val= leftAil }
|
||||
|
||||
if (rightAil) then
|
||||
MenuLines[3] = { Type = LT_LIST_NC, Text=rightAilText, TextId = 0, ValId = MV_CH_R_AIL, Min=0, Max=9, Def=0, Val= rightAil }
|
||||
end
|
||||
|
||||
if (leftFlap) then
|
||||
MenuLines[4] = { Type = LT_LIST_NC, Text=leftFlapText, TextId = 0, ValId = MV_CH_L_FLP, Min=0, Max=9, Def=0, Val= leftFlap }
|
||||
end
|
||||
if (rightFlap) then
|
||||
MenuLines[5] = { Type = LT_LIST_NC, Text=rightFlapText, TextId = 0, ValId = MV_CH_R_FLP, Min=0, Max=9, Def=0, Val= rightFlap }
|
||||
end
|
||||
|
||||
ctx_SelLine = 0
|
||||
lastGoodMenu = menuId
|
||||
|
||||
elseif (menuId==0x1021) then
|
||||
------ TAIL SETUP -------
|
||||
local leftRud = M_DB[MV_CH_L_RUD]
|
||||
local rightRud = M_DB[MV_CH_R_RUD]
|
||||
local leftEle = M_DB[MV_CH_L_ELE]
|
||||
local rightEle = M_DB[MV_CH_R_ELE]
|
||||
|
||||
local leftRudText = "Left Rud"
|
||||
local rightRudText = "Right Rud"
|
||||
|
||||
local leftElvText = "Left Ele"
|
||||
local rightElvText = "Right Ele"
|
||||
|
||||
if (rightRud==nil) then leftRudText = "Rud" end
|
||||
if (rightEle==nil) then leftElvText = "Ele" end
|
||||
|
||||
local title = aircraft_type_text[currATyp].." Tail:"..tail_type_text[currTTyp]
|
||||
|
||||
Menu = { MenuId = 0x1021, Text = title, PrevId = 0, NextId = 0x1001, BackId = 0x1020, TextId=0 }
|
||||
if (leftRud) then
|
||||
MenuLines[1] = { Type = LT_LIST_NC, Text=leftRudText, TextId = 0, ValId = MV_CH_L_RUD, Min=0, Max=9, Def=0, Val= leftRud}
|
||||
end
|
||||
|
||||
if (rightRud) then
|
||||
MenuLines[2] = { Type = LT_LIST_NC, Text=rightRudText, TextId = 0, ValId = MV_CH_R_RUD, Min=0, Max=9, Def=0, Val=rightRud }
|
||||
end
|
||||
|
||||
if (leftEle) then
|
||||
MenuLines[4] = { Type = LT_LIST_NC, Text=leftElvText, TextId = 0, ValId = MV_CH_L_ELE, Min=0, Max=9, Def=0, Val=leftEle }
|
||||
end
|
||||
|
||||
if (rightEle) then
|
||||
MenuLines[5] = { Type = LT_LIST_NC, Text=rightElvText, TextId = 0, ValId = MV_CH_R_ELE, Min=0, Max=9, Def=0, Val=rightEle }
|
||||
end
|
||||
|
||||
ctx_SelLine = 1
|
||||
lastGoodMenu = menuId
|
||||
|
||||
elseif (menuId==0x1030) then
|
||||
Menu = { MenuId = 0x1030, Text = "Gyro Reverse (Port 1-5)", PrevId = 0, NextId = 0x1031, BackId = 0x1001, TextId=0 }
|
||||
generateGyroReverse(menuId,P1,MV_P1_MODE)
|
||||
lastGoodMenu = menuId
|
||||
elseif (menuId==0x1031) then
|
||||
Menu = { MenuId = 0x1031, Text = "Gyro Reverse (Port 6-10)", PrevId = 0x1030, NextId = 0, BackId = 0x1001, TextId=0 }
|
||||
generateGyroReverse(menuId,P6,MV_P6_MODE)
|
||||
lastGoodMenu = menuId
|
||||
elseif (menuId==0xFFF9) then
|
||||
ChangePhase(PH_EXIT_DONE)
|
||||
return
|
||||
else
|
||||
Menu = { MenuId = 0x0002, Text = "NOT IMPLEMENTED", TextId = 0, PrevId = 0, NextId = 0, BackId = lastGoodMenu }
|
||||
ctx_SelLine = -1 -- BACK BUTTON
|
||||
end
|
||||
|
||||
for i = 0, 6 do
|
||||
if (MenuLines[i].Type > 0) then
|
||||
MenuLinePostProcessing(MenuLines[i])
|
||||
end
|
||||
end
|
||||
gc()
|
||||
end
|
||||
|
||||
-- Inital List and Image Text for this menus
|
||||
local function ST_Init_Text(rxId)
|
||||
-- Channel Names use the Port Text Retrived from OTX/ETX
|
||||
local p = 0
|
||||
|
||||
for i = 0, 9 do List_Text[i] = MODEL.PORT_TEXT[i] end
|
||||
List_Text[10] = "--"
|
||||
|
||||
-- Aircraft Type
|
||||
List_Text[15+AT_PLANE] = "Airplane";
|
||||
|
||||
-- Wing Types
|
||||
p = 20+WT_A1; List_Text[p] = "Single Ail"; --List_Text_Img[p] = "x.png|Single Aileron"
|
||||
p = 20+WT_A2; List_Text[p] = "Dual Ail"; --List_Text_Img[p] = "x.png|Dual Aileron"
|
||||
p = 20+WT_FLPR; List_Text[p] = "Flaperon"; --List_Text_Img[p] = "x.png|Flaperon"
|
||||
p = 20+WT_A1_F1; List_Text[p] = "Ail + Flap"; --List_Text_Img[p] = "x.png|Aileron + Flap"
|
||||
p = 20+WT_A2_F1; List_Text[p] = "Dual Ail + Flap"; --List_Text_Img[p] = "x.png|Dual Aileron + Flap"
|
||||
p = 20+WT_A2_F2; List_Text[p] = "Dual Ail + Dual Flap"; --List_Text_Img[p] = "x.png|Dual Aileron + Dual Flap"
|
||||
p = 20+WT_ELEVON_A; List_Text[p] = "Delta A"; --List_Text_Img[p] = "x.png|Delta/Elevon A"
|
||||
p = 20+WT_ELEVON_B; List_Text[p] = "Delta B"; --List_Text_Img[p] = "x.png|Delta/Elevon B"
|
||||
|
||||
-- Tail Types
|
||||
p = 30+TT_R1; List_Text[p] = "Rudder Only"; --List_Text_Img[p] = "x.png|Rudder Only"
|
||||
p = 30+TT_R1_E1; List_Text[p] = "Rud + Ele"; --List_Text_Img[p] = "x.png|Tail Normal"
|
||||
p = 30+TT_R1_E2; List_Text[p] = "Rud + Dual Ele"; --List_Text_Img[p] = "x.png|Rud + Dual Ele"
|
||||
p = 30+TT_R2_E1; List_Text[p] = "Dual Rud + Ele"; --List_Text_Img[p] = "x.png|Dual Rud + Ele"
|
||||
p = 30+TT_R2_E2; List_Text[p] = "Dual Rud + Dual Ele"; --List_Text_Img[p] = "x.png|Dual Rud + Dual Elev"
|
||||
p = 30+TT_VT_A; List_Text[p] = "V-Tail A"; --List_Text_Img[p] = "x.png|V-Tail A"
|
||||
p = 30+TT_VT_B; List_Text[p] = "V-Tail B"; --List_Text_Img[p] = "x.png|V-Tail B"
|
||||
p = 30+TT_TLRN_A; List_Text[p] = "Taileron A"; --List_Text_Img[p] = "x.png|Taileron A"
|
||||
p = 30+TT_TLRN_B; List_Text[p] = "Taileron B"; --List_Text_Img[p] = "x.png|Taileron B"
|
||||
p = 30+TT_TLRN_A_R2; List_Text[p] = "Taileron A + 2x Rud"; --List_Text_Img[p] = "x.png|Taileron A + Dual Rud"
|
||||
p = 30+TT_TLRN_B_R2; List_Text[p] = "Taileron B + 2x Rud"; --List_Text_Img[p] = "x.png|Taileron B + Dual Rud"
|
||||
|
||||
-- Servo Reverse
|
||||
List_Text[45+MT_NORMAL] = "Normal"
|
||||
List_Text[45+MT_REVERSE] = "Reverse"
|
||||
end
|
||||
|
||||
-- Initial Setup
|
||||
local function ST_Init()
|
||||
ST_Init_Text(0)
|
||||
gc()
|
||||
|
||||
-- Setup default Data if no data loaded
|
||||
menuDataChanged = false
|
||||
if (M_DB[MV_AIRCRAFT_TYPE]==nil) then
|
||||
ST_Default_Data()
|
||||
menuDataChanged = true
|
||||
end
|
||||
|
||||
currATyp = M_DB[MV_AIRCRAFT_TYPE]
|
||||
currWTyp = M_DB[MV_WING_TYPE]
|
||||
currTTyp = M_DB[MV_TAIL_TYPE]
|
||||
|
||||
Phase = PH_RX_VER
|
||||
end
|
||||
|
||||
----- Line Type
|
||||
|
||||
local function isSelectable(line)
|
||||
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_NC
|
||||
end
|
||||
|
||||
local function isEditing()
|
||||
return ctx_EditLine ~= nil
|
||||
end
|
||||
|
||||
-----------------------
|
||||
local function Get_Text(index)
|
||||
local out = Text[index] or string.format("Unknown_%X", index)
|
||||
return out
|
||||
end
|
||||
|
||||
local function Get_Text_Value(index)
|
||||
local out = List_Text[index] or Get_Text(index)
|
||||
return out
|
||||
end
|
||||
|
||||
function ChangePhase(newPhase)
|
||||
Phase = newPhase
|
||||
end
|
||||
|
||||
local function Value_Add(dir)
|
||||
local line = MenuLines[ctx_SelLine]
|
||||
local inc = dir
|
||||
|
||||
line.Val = line.Val + inc
|
||||
|
||||
if line.Val > line.Max then
|
||||
line.Val = line.Max
|
||||
elseif line.Val < line.Min then
|
||||
line.Val = line.Min
|
||||
end
|
||||
end
|
||||
--------------
|
||||
|
||||
local function GotoMenu(menuId, lastSelectedLine)
|
||||
Menu.MenuId = menuId
|
||||
ctx_SelLine = lastSelectedLine
|
||||
ChangePhase(PH_TITLE)
|
||||
end
|
||||
|
||||
local function DSM_HandleEvent(event)
|
||||
if event == EVT_VIRTUAL_EXIT then
|
||||
if Phase == PH_RX_VER then
|
||||
Phase = PH_EXIT_DONE -- Exit program
|
||||
else
|
||||
if isEditing() then -- Editing a Line, need to restore original value
|
||||
MenuLines[ctx_EditLine].Val = originalValue
|
||||
event = EVT_VIRTUAL_ENTER
|
||||
else
|
||||
if (Menu.BackId > 0 ) then -- Back??
|
||||
ctx_SelLine = -1 --Back Button
|
||||
event = EVT_VIRTUAL_ENTER
|
||||
else
|
||||
ChangePhase(PH_EXIT_REQ)
|
||||
end
|
||||
end
|
||||
end
|
||||
end -- Exit
|
||||
|
||||
if Phase == PH_RX_VER then return end -- nothing else to do
|
||||
|
||||
if event == EVT_VIRTUAL_NEXT then
|
||||
if isEditing() then -- Editting?
|
||||
Value_Add(1)
|
||||
else
|
||||
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
|
||||
return
|
||||
end
|
||||
|
||||
if event == EVT_VIRTUAL_PREV then
|
||||
if isEditing() 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
|
||||
return
|
||||
end
|
||||
|
||||
|
||||
if 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 isEditing() then
|
||||
ctx_EditLine = nil -- Done Editting
|
||||
ChangePhase(PH_VAL_EDIT_END)
|
||||
else -- Start Editing
|
||||
ctx_EditLine = ctx_SelLine
|
||||
originalValue = MenuLines[ctx_SelLine].Val
|
||||
ChangePhase(PH_VAL_EDITING)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function DSM_Send_Receive()
|
||||
|
||||
if Phase == PH_RX_VER then -- request RX version
|
||||
Phase = PH_TITLE
|
||||
Menu.MenuId = 0x01001
|
||||
Refresh_Display = true
|
||||
elseif Phase == PH_WAIT_CMD then
|
||||
|
||||
elseif Phase == PH_TITLE then -- request menu title
|
||||
ST_LoadMenu(Menu.MenuId)
|
||||
if (Phase~=PH_EXIT_DONE) then
|
||||
Phase = PH_WAIT_CMD
|
||||
end
|
||||
Refresh_Display = true
|
||||
elseif Phase == PH_VAL_EDIT_END then -- send value
|
||||
local line = MenuLines[ctx_SelLine] -- Updated Value of SELECTED line
|
||||
|
||||
-- Update the menu data from the line
|
||||
if (M_DB[line.ValId] ~= line.Val ) then
|
||||
M_DB[line.ValId] = line.Val
|
||||
print(string.format("MENU_DATA[%d/%s]=%d",line.ValId,line.Text, line.Val))
|
||||
menuDataChanged=true
|
||||
end
|
||||
|
||||
-- Did the Wing type change?
|
||||
local wt = M_DB[MV_WING_TYPE]
|
||||
if (currWTyp ~= wt) then
|
||||
currWTyp = wt
|
||||
ST_PlaneWingInit(currWTyp)
|
||||
|
||||
-- DELTA has only RUDER
|
||||
if (currWTyp==WT_ELEVON_A or currWTyp==WT_ELEVON_B) then
|
||||
M_DB[MV_TAIL_TYPE] = TT_R1
|
||||
end
|
||||
end
|
||||
|
||||
--- Did the tail changed?
|
||||
local tt = M_DB[MV_TAIL_TYPE]
|
||||
if (currTTyp ~= tt) then
|
||||
if (not tailTypeCompatible(currTTyp,tt)) then
|
||||
ST_PlaneTailInit(tt)
|
||||
end
|
||||
currTTyp = tt
|
||||
end
|
||||
|
||||
Phase = PH_WAIT_CMD
|
||||
elseif Phase == PH_EXIT_REQ then
|
||||
Phase=PH_EXIT_DONE
|
||||
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
|
||||
gc()
|
||||
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 function DSM_Display()
|
||||
lcd.clear()
|
||||
--Draw RX Menu
|
||||
if Phase == PH_RX_VER then
|
||||
return
|
||||
end
|
||||
|
||||
-- display Program version or RX version
|
||||
local msg = "FProg "..VERSION
|
||||
lcd.drawText(40, 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 = line.Text
|
||||
|
||||
local text = nil
|
||||
if line.Type ~= LT_MENU then -- list/value
|
||||
if line.Val ~= nil then
|
||||
if isListLine(line) then
|
||||
local textId = line.Val + line.TextStart
|
||||
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(1, 20, imgDesc)
|
||||
--end
|
||||
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 or "--", attrib + RIGHT) -- display value
|
||||
--lcd.drawText(LCD_X_MAX, y, line.Format or "", TEXT_ATTR + RIGHT) -- display Format
|
||||
attrib = TEXT_ATTR
|
||||
end
|
||||
|
||||
lcd.drawText(1, 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(1, LCD_Y_LOWER_BUTTONS, "Prev", ctx_SelLine == 8)
|
||||
end
|
||||
end
|
||||
|
||||
------------------------------------------------------------------------------------------------------------
|
||||
-- Init
|
||||
local function DSM_Init()
|
||||
--LOG_open()
|
||||
ST_Init()
|
||||
gc()
|
||||
|
||||
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
|
||||
|
||||
Phase = PH_RX_VER
|
||||
end
|
||||
|
||||
-- Main
|
||||
|
||||
local function DSM_Run(event)
|
||||
if event == nil then
|
||||
error("Cannot be run as a model script!")
|
||||
return 2
|
||||
end
|
||||
|
||||
DSM_Display()
|
||||
DSM_HandleEvent(event)
|
||||
DSM_Send_Receive()
|
||||
gc()
|
||||
|
||||
if Phase == PH_EXIT_DONE then
|
||||
LOG_close()
|
||||
return 2
|
||||
else
|
||||
return 0
|
||||
end
|
||||
end
|
||||
|
||||
---
|
||||
-- Load Model Config
|
||||
gc()
|
||||
local r = assert(loadScript(DSMLIB_PATH.."DsmMIN_P1.lua"), "Not-Found: DSMLIB/DsmMIN_P1.lua")
|
||||
(MODEL,M_DB, LOG_write)
|
||||
gc()
|
||||
----
|
||||
return { init = DSM_Init, run = DSM_Run }
|
||||
813
Lua_scripts/DSMLIB/DsmFwPrgLib.lua
Normal file
@@ -0,0 +1,813 @@
|
||||
---- #########################################################################
|
||||
---- # #
|
||||
---- # Copyright (C) OpenTX/EdgeTx #
|
||||
-----# #
|
||||
---- # 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
|
||||
--
|
||||
------------------------------------------------------------------------------
|
||||
--###############################################################################
|
||||
-- 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 Log, menuLib, modelLib, DEBUG_ON = ... -- Get Debug_ON from parameters. -- 0=NO DEBUG, 1=HIGH LEVEL 2=MORE DETAILS
|
||||
local LIB_VERSION = "0.55"
|
||||
local MSG_FILE = "/SCRIPTS/TOOLS/DSMLIB/msg_fwdp_en.txt"
|
||||
|
||||
local PHASE = menuLib.PHASE
|
||||
local LINE_TYPE = menuLib.LINE_TYPE
|
||||
|
||||
local CH_TYPE = modelLib.CH_TYPE
|
||||
local CH_MIX_TYPE = modelLib.CH_MIX_TYPE
|
||||
|
||||
local DISP_ATTR = menuLib.DISP_ATTR
|
||||
local DSM_Context = menuLib.DSM_Context
|
||||
local MODEL = modelLib.MODEL
|
||||
|
||||
local MAX_MENU_LINES = menuLib.MAX_MENU_LINES
|
||||
local BACK_BUTTON = menuLib.BACK_BUTTON
|
||||
local NEXT_BUTTON = menuLib.NEXT_BUTTON
|
||||
local PREV_BUTTON = menuLib.PREV_BUTTON
|
||||
|
||||
|
||||
local SEND_TIMEOUT = 2000 / 10 -- Home many 10ms intervals to wait on sending data to tx to keep connection open (2s)
|
||||
local TXInactivityTime = 0 -- Next time to do heartbeat after inactivity
|
||||
local RXInactivityTime = 0 -- To check RX disconnection
|
||||
|
||||
|
||||
local TxInfo_Type = 0
|
||||
local TxInfo_Step = 0
|
||||
local Change_Step = 0
|
||||
|
||||
local IS_EDGETX = false
|
||||
|
||||
------------------------------------------------------------------------------------------------------------
|
||||
|
||||
local function multiBuffer2String() -- used for debug
|
||||
local i
|
||||
local rxAnswer = "RX:"
|
||||
for i = 10, 25 do
|
||||
rxAnswer = rxAnswer .. string.format(" %02X", multiBuffer(i))
|
||||
end
|
||||
return rxAnswer
|
||||
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 DSM_send(...)
|
||||
local arg = { ... }
|
||||
|
||||
for i = 1, #arg do
|
||||
multiBuffer(3 + i, arg[i])
|
||||
end
|
||||
multiBuffer(3, 0x70 + #arg)
|
||||
|
||||
|
||||
if (DEBUG_ON > 1) then
|
||||
local str = ""
|
||||
for i = 1, #arg do
|
||||
str = str .. string.format("%02X ", arg[i])
|
||||
end
|
||||
LOG_write("DSM_SEND: [%s]\n", str)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
-------------------------------------------------------------------------------------------------
|
||||
local function DSM_StartConnection()
|
||||
if (DEBUG_ON) then Log.LOG_write("DSM_StartConnection()\n") end
|
||||
|
||||
--Set protocol to talk to
|
||||
multiBuffer( 0, string.byte('D') )
|
||||
--test if value has been written
|
||||
if multiBuffer( 0 ) ~= string.byte('D') then
|
||||
if (DEBUG_ON) then Log.LOG_write("Not Enouth memory\n") end
|
||||
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') )
|
||||
|
||||
return 0
|
||||
end
|
||||
|
||||
local function DSM_ReleaseConnection()
|
||||
if (DEBUG_ON) then Log.LOG_write("DSM_ReleaseConnection()\n") end
|
||||
multiBuffer(0, 0)
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------------------------------
|
||||
-- REEQUEST Messages to RX
|
||||
|
||||
local function DSM_sendHeartbeat()
|
||||
-- keep connection open
|
||||
if (DEBUG_ON) then Log.LOG_write("SEND DSM_sendHeartbeat()\n") end
|
||||
DSM_send(0x00, 0x04, 0x00, 0x00)
|
||||
end
|
||||
|
||||
local function DSM_getRxVerson()
|
||||
local TX_CAP=0x14 -- Capabilities??
|
||||
local TX_MAX_CH = modelLib.TX_CHANNELS - 6 --number of channels after 6 (6Ch=0, 10ch=4, etc)
|
||||
|
||||
if (DEBUG_ON) then Log.LOG_write("SEND DSM_getRxVersion(Ch:0x%X,Cap:0x%X)\n",TX_MAX_CH,TX_CAP) end
|
||||
DSM_send(0x11, 0x06, TX_MAX_CH, TX_CAP, 0x00, 0x00)
|
||||
end
|
||||
|
||||
local function DSM_getMainMenu()
|
||||
local TX_CAP=0x14 -- Capabilities??
|
||||
local TX_MAX_CH = modelLib.TX_CHANNELS - 6 --number of channels after 6 (6Ch=0, 10ch=4, etc)
|
||||
|
||||
if (DEBUG_ON) then Log.LOG_write("SEND DSM_getMainMenu(Ch:0x%X,Cap:0x%X) -- TX_Channels=%d\n",TX_MAX_CH,TX_CAP,TX_MAX_CH+6) end
|
||||
DSM_send(0x12, 0x06, TX_MAX_CH, TX_CAP, 0x00, 0x00) -- first menu only
|
||||
end
|
||||
|
||||
local function DSM_getMenu(menuId, latSelLine)
|
||||
if (DEBUG_ON) then Log.LOG_write("SEND DSM_getMenu(MenuId=0x%X LastSelectedLine=%s)\n", menuId, latSelLine) end
|
||||
DSM_send(0x16, 0x06, int16_MSB(menuId), int16_LSB(menuId), 0x00, latSelLine)
|
||||
end
|
||||
|
||||
local function DSM_getFirstMenuLine(menuId)
|
||||
if (DEBUG_ON) then Log.LOG_write("SEND DSM_getFirstMenuLine(MenuId=0x%X)\n", menuId) end
|
||||
DSM_send(0x13, 0x04, int16_MSB(menuId), int16_LSB(menuId)) -- line 0
|
||||
end
|
||||
|
||||
local function DSM_getNextMenuLine(menuId, curLine)
|
||||
if (DEBUG_ON) then Log.LOG_write("SEND DSM_getNextLine(MenuId=0x%X,LastLine=%s)\n", menuId, curLine) end
|
||||
DSM_send(0x14, 0x06, int16_MSB(menuId), int16_LSB(menuId), 0x00, curLine) -- line X
|
||||
end
|
||||
|
||||
local function DSM_getNextMenuValue(menuId, valId, text)
|
||||
if (DEBUG_ON) then Log.LOG_write("SEND DSM_getNextMenuValue(MenuId=0x%X, LastValueId=0x%X) Extra: Text=\"%s\"\n", menuId, valId,
|
||||
text)
|
||||
end
|
||||
DSM_send(0x15, 0x06, int16_MSB(menuId), int16_LSB(menuId), int16_MSB(valId), int16_LSB(valId)) -- line X
|
||||
end
|
||||
|
||||
local function DSM_updateMenuValue(valId, val, text, line)
|
||||
local value = sInt16ToDsm(val)
|
||||
if (DEBUG_ON) then Log.LOG_write("SEND DSM_updateValue(ValueId=0x%X,val=%d) Extra: Text=\"%s\" Value=%s\n", valId, val, text, menuLib.lineValue2String(line)) end
|
||||
DSM_send(0x18, 0x06, int16_MSB(valId), int16_LSB(valId), int16_MSB(value), int16_LSB(value)) -- send current value
|
||||
end
|
||||
|
||||
local function DSM_validateMenuValue(valId, text, line)
|
||||
if (DEBUG_ON) then Log.LOG_write("SEND DSM_validateValue(ValueId=0x%X) Extra: Text=\"%s\" Value=%s\n", valId, text, menuLib.lineValue2String(line)) end
|
||||
DSM_send(0x19, 0x04, int16_MSB(valId), int16_LSB(valId))
|
||||
end
|
||||
|
||||
local function DSM_editingValue(lineNum, text, line)
|
||||
if (DEBUG_ON) then Log.LOG_write("SEND DSM_editingValue(lineNo=0x%X) Extra: Text=\"%s\" Val=%s\n", lineNum, text, menuLib.lineValue2String(line)) end
|
||||
DSM_send(0x1A, 0x04, int16_MSB(lineNum), int16_LSB(lineNum))
|
||||
end
|
||||
|
||||
local function DSM_editingValueEnd(lineNum, text, line)
|
||||
if (DEBUG_ON) then Log.LOG_write("SEND DSM_editingValueEnd(lineNo=0x%X) Extra: Text=\"%s\" Value=%s\n", lineNum, text, menuLib.lineValue2String(line)) end
|
||||
DSM_send(0x1B, 0x04, int16_MSB(lineNum), int16_LSB(lineNum))
|
||||
end
|
||||
|
||||
-- Send the functionality of the RX channel Port (channel)
|
||||
local function DSM_sendTxChInfo_20(portNo)
|
||||
local b1,b2 = MODEL.DSM_ChannelInfo[portNo][0] or 0, MODEL.DSM_ChannelInfo[portNo][1] or 0
|
||||
|
||||
if (DEBUG_ON) then Log.LOG_write("CALL DSM_TxChInfo(#%d DATA= %02X %02X %02X %02X) %s\n", portNo,
|
||||
portNo, portNo, b1, b2, modelLib.channelType2String(b1,b2)) -- DATA part
|
||||
end
|
||||
DSM_send(0x20, 0x06, portNo, portNo, b1, b2)
|
||||
end
|
||||
|
||||
local function DSM_sendTxSubtrim_21(portNo)
|
||||
local usage = MODEL.DSM_ChannelInfo[portNo][1] or 0
|
||||
local leftTravel = math.abs(math.floor(MODEL.modelOutputChannel[portNo].min/10))
|
||||
local rightTravel = math.abs(math.floor(MODEL.modelOutputChannel[portNo].max/10))
|
||||
local subTrim = math.floor(MODEL.modelOutputChannel[portNo].offset/10)
|
||||
|
||||
-- Center at 100%: 142-1906 (0 8E 07 72)
|
||||
local left = 142
|
||||
local right = 1906
|
||||
|
||||
if (bit32.band(usage,CH_TYPE.THR)>0) then
|
||||
left = 0
|
||||
right = 2047
|
||||
end
|
||||
|
||||
left = math.floor (left - (leftTravel -100) *8.8 + subTrim*2)
|
||||
right = math.floor (right + (rightTravel -100) *8.8 + subTrim*2)
|
||||
|
||||
if (left<0) then left=0 end
|
||||
if (right>2027) then right=2047 end
|
||||
|
||||
local b1,b2,b3,b4 = int16_MSB(left), int16_LSB(left), int16_MSB(right), int16_LSB(right)
|
||||
|
||||
if (DEBUG_ON) then Log.LOG_write("CALL DSM_TxSubtrim(#%d DATA=%02X %02X %02X %02X) Range(%d - %d) ER L/R:(%d - %d)x8 ST:(%d)x2\n", portNo,
|
||||
b1,b2,b3,b4, left, right, leftTravel-100, rightTravel-100, subTrim) -- DATA part
|
||||
end
|
||||
DSM_send(0x21, 0x06, b1,b2,b3,b4) -- Port is not send anywhere, since the previous 0x20 type message have it.
|
||||
end
|
||||
|
||||
local function DSM_sendTxServoTravel_23(portNo)
|
||||
local leftTravel = math.abs(math.floor(MODEL.modelOutputChannel[portNo].min/10))
|
||||
local rightTravel = math.abs(math.floor(MODEL.modelOutputChannel[portNo].max/10))
|
||||
local debugInfo = string.format("Travel L/R (%d - %d)",leftTravel,rightTravel)
|
||||
|
||||
if (DEBUG_ON) then Log.LOG_write("CALL DSM_TxServoTravel(#%d DATA= %02X %02X %02X %02X) %s\n", portNo,
|
||||
0x00, leftTravel, 0x00, rightTravel, debugInfo) -- DATA part
|
||||
end
|
||||
DSM_send(0x23, 0x06, 0x00, leftTravel, 0x00, rightTravel)
|
||||
end
|
||||
|
||||
local function DSM_sentTxInfo(menuId,portNo)
|
||||
-- TxInfo_Type=0 : AR636B 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 (TxInfo_Step == 0) then
|
||||
-- AR630 family: Both TxInfo_Type (ManinMenu=0x1, Other First Time Configuration = 0x1F)
|
||||
DSM_sendTxChInfo_20(portNo)
|
||||
|
||||
if (TxInfo_Type == 0x1F) then
|
||||
TxInfo_Step = 1
|
||||
end
|
||||
if (TxInfo_Type == 0x00) then
|
||||
TxInfo_Step = 2
|
||||
end
|
||||
elseif (TxInfo_Step == 1) then
|
||||
DSM_sendTxServoTravel_23(portNo)
|
||||
TxInfo_Step = 2
|
||||
elseif (TxInfo_Step == 2) then
|
||||
DSM_sendTxSubtrim_21(portNo)
|
||||
|
||||
if (TxInfo_Type == 0x00) then
|
||||
TxInfo_Step = 5 -- End Step
|
||||
else
|
||||
TxInfo_Step = 3
|
||||
end
|
||||
elseif (TxInfo_Step == 3) then
|
||||
-- 24,6: 0 83 5A B5
|
||||
if (DEBUG_ON) then Log.LOG_write("CALL DSM_TxInfo24(#%d DATA=0x24 0x06 %02X %02X %02X %02X)\n", portNo,
|
||||
0x00, 0x83, 0x5A, 0xB5) -- DATA part
|
||||
end
|
||||
DSM_send(0x24, 0x06, 0x00, 0x83, 0x5A, 0xB5) -- Still Uknown
|
||||
TxInfo_Step = 4
|
||||
|
||||
elseif (TxInfo_Step == 4) then
|
||||
-- 24,6: 6 80 25 4B
|
||||
if (DEBUG_ON) then Log.LOG_write("CALL DSM_TxInfo24(#%d DATA=0x24 0x06 %02X %02X %02X %02X)\n", portNo,
|
||||
0x06, 0x80, 0x25, 0x4B) -- DATA part
|
||||
end
|
||||
DSM_send(0x24, 0x06, 0x06, 0x80, 0x25, 0x4B) -- Still Uknown
|
||||
TxInfo_Step = 5
|
||||
elseif (TxInfo_Step == 5) then
|
||||
-- 22,4: 0 0
|
||||
if (DEBUG_ON) then Log.LOG_write("CALL DSM_TxInfo_End(#%d)\n", portNo)
|
||||
end
|
||||
DSM_send(0x22, 0x04, 0x00, 0x00)
|
||||
TxInfo_Step = 0
|
||||
end
|
||||
|
||||
if (TxInfo_Step > 0) then
|
||||
DSM_Context.SendDataToRX = 1 -- keep Transmitig
|
||||
end
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------------------------------------
|
||||
|
||||
local function DSM_sendRequest()
|
||||
-- Send the proper Request message depending on the Phase
|
||||
|
||||
local ctx = DSM_Context
|
||||
if (DEBUG_ON) then Log.LOG_write("%3.3f %s: ", menuLib.getElapsedTime(), menuLib.phase2String(ctx.Phase)) end
|
||||
|
||||
if ctx.Phase == PHASE.RX_VERSION then -- request RX version
|
||||
DSM_getRxVerson()
|
||||
|
||||
elseif ctx.Phase == PHASE.WAIT_CMD then -- keep connection open
|
||||
DSM_sendHeartbeat()
|
||||
|
||||
elseif ctx.Phase == PHASE.MENU_TITLE then -- request menu title
|
||||
if ctx.Menu.MenuId == 0 then -- First time loading a menu ?
|
||||
DSM_getMainMenu()
|
||||
else
|
||||
DSM_getMenu(ctx.Menu.MenuId, ctx.SelLine)
|
||||
|
||||
if (ctx.Menu.MenuId == 0x0001) then -- Executed the Reset Menu??
|
||||
if (DEBUG_ON) then Log.LOG_write("RX Reset!!!\n") end
|
||||
-- Start again retriving RX info
|
||||
ctx.Menu.MenuId = 0
|
||||
ctx.isReset = true
|
||||
ctx.Phase = PHASE.RX_VERSION
|
||||
end
|
||||
end
|
||||
|
||||
elseif ctx.Phase == PHASE.MENU_REQ_TX_INFO then
|
||||
DSM_sentTxInfo(ctx.Menu.MenuId, ctx.CurLine)
|
||||
|
||||
elseif ctx.Phase == PHASE.MENU_LINES then -- request next menu lines
|
||||
if ctx.CurLine == -1 then -- No previous menu line loaded ?
|
||||
DSM_getFirstMenuLine(ctx.Menu.MenuId)
|
||||
else
|
||||
DSM_getNextMenuLine(ctx.Menu.MenuId, ctx.CurLine)
|
||||
end
|
||||
|
||||
elseif ctx.Phase == PHASE.MENU_VALUES then -- request menu values
|
||||
local line = ctx.MenuLines[ctx.CurLine]
|
||||
DSM_getNextMenuValue(ctx.Menu.MenuId, line.ValId, line.Text)
|
||||
|
||||
elseif ctx.Phase == PHASE.VALUE_CHANGING then -- send value
|
||||
local line = ctx.MenuLines[ctx.SelLine] -- Updated Value of SELECTED line
|
||||
|
||||
if (Change_Step==0) then
|
||||
DSM_updateMenuValue(line.ValId, line.Val, line.Text, line)
|
||||
|
||||
if line.Type == menuLib.LINE_TYPE.LIST_MENU then -- Validation on every Step??
|
||||
Change_Step=1; ctx.SendDataToRX=1 -- Send inmediatly after
|
||||
else
|
||||
ctx.Phase = PHASE.VALUE_CHANGING_WAIT
|
||||
end
|
||||
else
|
||||
DSM_validateMenuValue(line.ValId, line.Text, line)
|
||||
Change_Step=0
|
||||
ctx.Phase = PHASE.VALUE_CHANGING_WAIT
|
||||
end
|
||||
|
||||
elseif ctx.Phase == PHASE.VALUE_CHANGING_WAIT then
|
||||
local line = ctx.MenuLines[ctx.SelLine]
|
||||
DSM_editingValue(line.lineNum, line.Text, line)
|
||||
elseif ctx.Phase == PHASE.VALUE_CHANGE_END then -- send value
|
||||
local line = ctx.MenuLines[ctx.SelLine] -- Update Value of SELECTED line
|
||||
|
||||
if (Change_Step==0) then
|
||||
DSM_updateMenuValue(line.ValId, line.Val, line.Text, line)
|
||||
Change_Step=1; ctx.SendDataToRX=1 -- Send inmediatly after
|
||||
elseif (Change_Step==1) then
|
||||
DSM_validateMenuValue(line.ValId, line.Text, line)
|
||||
Change_Step=2; ctx.SendDataToRX=1 -- Send inmediatly after
|
||||
else
|
||||
DSM_editingValueEnd(line.lineNum, line.Text, line)
|
||||
Change_Step=0
|
||||
ctx.Phase = PHASE.WAIT_CMD
|
||||
end
|
||||
elseif ctx.Phase == PHASE.EXIT then
|
||||
if (DEBUG_ON) then Log.LOG_write("CALL DSM_TX_Exit()\n") end
|
||||
DSM_send(0x1F, 0x02, 0xFF, 0xFF) -- 0xAA
|
||||
end
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------------------------------------
|
||||
-- Parsing Responses
|
||||
|
||||
local function DSM_parseRxVersion()
|
||||
--ex: 0x09 0x01 0x00 0x15 0x02 0x22 0x01 0x00 0x14 v2.22.1 00 14?? 8ch SAFE
|
||||
-- 0x09 0x01 0x00 0x18 0x05 0x06 0x34 0x00 0x12 v5.6.52 00 12??? 6ch FC6250
|
||||
local rxId = multiBuffer(13)
|
||||
DSM_Context.RX.Id = rxId
|
||||
DSM_Context.RX.Name = menuLib.Get_RxName(rxId)
|
||||
DSM_Context.RX.Version = multiBuffer(14) .. "." .. multiBuffer(15) .. "." .. multiBuffer(16)
|
||||
if (DEBUG_ON) then Log.LOG_write("RESPONSE Receiver=%s Version %s Cap:0x%02X\n",
|
||||
DSM_Context.RX.Name, DSM_Context.RX.Version, multiBuffer(18)) end
|
||||
end
|
||||
|
||||
local function DSM_parseMenu()
|
||||
--ex: 0x09 0x02 0x4F 0x10 0xA5 0x00 0x00 0x00 0x50 0x10 0x10 0x10 0x00 0x00 0x00 0x00
|
||||
-- MenuID TextID PrevID NextID BackID
|
||||
local ctx = DSM_Context
|
||||
local menu = ctx.Menu
|
||||
menu.MenuId = Dsm_to_Int16(multiBuffer(12), multiBuffer(13))
|
||||
menu.TextId = Dsm_to_Int16(multiBuffer(14), multiBuffer(15))
|
||||
menu.Text = menuLib.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, MAX_MENU_LINES do -- clear menu
|
||||
ctx.MenuLines[i] = { MenuId = 0, lineNum = 0, Type = 0, Text = "", TextId = 0, ValId = 0, Min=0, Max=0, Def=0, Val=nil }
|
||||
end
|
||||
ctx.CurLine = -1
|
||||
|
||||
menuLib.MenuPostProcessing(menu)
|
||||
|
||||
if (DEBUG_ON) then Log.LOG_write("RESPONSE Menu: %s\n", menuLib.menu2String(menu)) end
|
||||
return menu
|
||||
end
|
||||
|
||||
|
||||
local function DSM_parseMenuLine()
|
||||
--ex: 0x09 0x03 0x00 0x10 0x00 0x1C 0xF9 0x00 0x10 0x10 0x00 0x00 0x00 0x00 0x03 0x00
|
||||
--ex: 0x09 0x03 0x61 0x10 0x00 0x6C 0x50 0x00 0x00 0x10 0x36 0x00 0x49 0x00 0x36 0x00
|
||||
--ex: 0x09 0x03 0x65 0x10 0x00 0x0C 0x51 0x00 0x00 0x10 0x00 0x00 0xF4 0x00 0x2E 0x00
|
||||
-- MenuLSB MenuMSB line Type TextID NextLSB NextMSB Val_Min Val_Max Val_Def
|
||||
|
||||
local ctx = DSM_Context
|
||||
local i = multiBuffer(14)
|
||||
local type = multiBuffer(15)
|
||||
local line = ctx.MenuLines[i]
|
||||
|
||||
-- are we trying to override existing line
|
||||
if (line.Type > 0 and type == 0) then
|
||||
if (DEBUG_ON) then Log.LOG_write("RESPONSE MenuLine: ERROR. Trying to ZERO Override: %s\n", menuLib.menuLine2String(line)) end
|
||||
return ctx.MenuLines[ctx.CurLine]
|
||||
end
|
||||
|
||||
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 = nil -- Fill at Post processing
|
||||
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))
|
||||
|
||||
line.Val=nil
|
||||
|
||||
menuLib.MenuLinePostProcessing(line)
|
||||
|
||||
if (DEBUG_ON) then Log.LOG_write("RESPONSE MenuLine: %s\n", menuLib.menuLine2String(line)) end
|
||||
|
||||
if (line.MenuId~=ctx.Menu.MenuId) then
|
||||
-- Going Back too fast: Stil receiving lines from previous menu
|
||||
ctx.Menu.MenuId = line.MenuId
|
||||
Log.LOG_write("WARNING: Overriding current Menu from Line\n")
|
||||
end
|
||||
|
||||
return line
|
||||
end
|
||||
|
||||
local function DSM_parseMenuValue()
|
||||
--ex: 0x09 0x04 0x53 0x10 0x00 0x10 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
|
||||
--ex: 0x09 0x04 0x61 0x10 0x02 0x10 0x01 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
|
||||
-- MenuLSB MenuMSB ValLSB ValMSB V_LSB V_MSB
|
||||
|
||||
-- Identify the line and update the value
|
||||
local ctx = DSM_Context
|
||||
local menuId = Dsm_to_Int16(multiBuffer(12), multiBuffer(13))
|
||||
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, MAX_MENU_LINES do -- Find the menu line for this value
|
||||
local line = ctx.MenuLines[i]
|
||||
if line ~= nil and line.Type ~= 0 then
|
||||
if line.Type ~= LINE_TYPE.MENU and line.ValId == valId then -- identifier of ValueId stored in the line
|
||||
line.Val = value
|
||||
ctx.CurLine = i
|
||||
updatedLine = line
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if (updatedLine == nil) then
|
||||
if (DEBUG_ON) then Log.LOG_write("RESPONSE MenuValue: ERROR, Cant find Menu Line with MenuId=%X, ValID=%X to update\n", menuId, valId) end
|
||||
else
|
||||
if (DEBUG_ON) then Log.LOG_write("RESPONSE MenuValue: UPDATED: %s\n", menuLib.menuLine2String(updatedLine))
|
||||
end
|
||||
end
|
||||
return updatedLine ~= nil
|
||||
end
|
||||
|
||||
local function DSM_parseReqTxInfo()
|
||||
local portNo = multiBuffer(12)
|
||||
TxInfo_Type = multiBuffer(13)
|
||||
if (DEBUG_ON) then Log.LOG_write("RESPONSE ReqTXChannelInfo(#%d %s InfoType=0x%0X)\n",
|
||||
portNo, MODEL.PORT_TEXT[portNo], TxInfo_Type) end
|
||||
|
||||
TxInfo_Step = 0
|
||||
|
||||
return portNo
|
||||
end
|
||||
|
||||
------------------------------------------------------------------------------------------------------------
|
||||
local function DSM_processResponse()
|
||||
local ctx = DSM_Context
|
||||
local cmd = multiBuffer(11) -- Response Command
|
||||
|
||||
if (DEBUG_ON > 1) then Log.LOG_write("%s: RESPONSE %s \n", menuLib.phase2String(ctx.Phase), multiBuffer2String()) end
|
||||
if (DEBUG_ON and cmd > 0x00) then Log.LOG_write("%3.3f %s: ", menuLib.getElapsedTime(), menuLib.phase2String(ctx.Phase)) end
|
||||
|
||||
if cmd == 0x01 then -- read version
|
||||
DSM_parseRxVersion()
|
||||
--Lib.Init_Text(DSM_Context.RX.Id)
|
||||
ctx.isReset = false -- no longer resetting
|
||||
ctx.Phase = PHASE.MENU_TITLE
|
||||
ctx.Menu.MenuId = 0
|
||||
|
||||
elseif cmd == 0x02 then -- read menu title
|
||||
local menu = DSM_parseMenu()
|
||||
|
||||
-- Update Selected Line navigation
|
||||
if menu.NextId ~= 0 then
|
||||
ctx.SelLine = NEXT_BUTTON -- highlight Next
|
||||
else
|
||||
ctx.SelLine = BACK_BUTTON -- highlight Back
|
||||
end
|
||||
|
||||
if (ctx.Menu.MenuId == 0x0001) then -- Still in RESETTING MENU???
|
||||
-- Star from Start
|
||||
if (DEBUG_ON) then Log.LOG_write("RX Reset: Still not done, restart again!!!\n") end
|
||||
ctx.Menu.MenuId = 0
|
||||
ctx.Phase = PHASE.RX_VERSION
|
||||
else
|
||||
ctx.Phase = PHASE.MENU_LINES
|
||||
end
|
||||
|
||||
|
||||
elseif cmd == 0x03 then -- menu lines
|
||||
local line = DSM_parseMenuLine()
|
||||
|
||||
-- Update Selected line navigation
|
||||
if (ctx.SelLine == BACK_BUTTON or ctx.SelLine == NEXT_BUTTON or ctx.SelLine == PREV_BUTTON)
|
||||
and menuLib.isSelectableLine(line) then -- Auto select the current line
|
||||
ctx.SelLine = line.lineNum
|
||||
end
|
||||
|
||||
ctx.Phase = PHASE.MENU_LINES
|
||||
|
||||
elseif cmd == 0x04 then -- read menu values
|
||||
if DSM_parseMenuValue() then
|
||||
ctx.Phase = PHASE.MENU_VALUES
|
||||
else
|
||||
ctx.Phase = PHASE.WAIT_CMD
|
||||
end
|
||||
|
||||
elseif cmd == 0x05 then -- Request TX Info
|
||||
local portNo = DSM_parseReqTxInfo()
|
||||
ctx.CurLine = portNo
|
||||
ctx.Phase = PHASE.MENU_REQ_TX_INFO
|
||||
|
||||
elseif cmd == 0xA7 then -- answer to EXIT command
|
||||
if (DEBUG_ON) then Log.LOG_write("RESPONSE RX Exit\n") end
|
||||
if (ctx.Phase==PHASE.EXIT) then -- Expected RX Exit
|
||||
ctx.Phase = PHASE.EXIT_DONE
|
||||
else -- UnExpected RX Exit
|
||||
DSM_ReleaseConnection()
|
||||
error("RX Connection Drop")
|
||||
end
|
||||
|
||||
elseif cmd == 0x00 then -- NULL response (or RX heartbeat)
|
||||
-- 09 00 01 00 00 00 00 00 00 00 00 00 00 00 00
|
||||
-- 09 00 7E 00 20 9E 28 00 20 9E 28 00 20 8D 7E : After TX Heartbeat one of this (FC6250)
|
||||
-- 09 00 18 00 20 08 00 00 00 08 00 00 00 98 AE AR8360T
|
||||
if (DEBUG_ON) then Log.LOG_write("%3.3f %s: RESPONSE RX Heartbeat --Context: 0x%02X\n",
|
||||
menuLib.getElapsedTime(), menuLib.phase2String(ctx.Phase), multiBuffer(12)) end
|
||||
else
|
||||
if (DEBUG_ON) then Log.LOG_write("RESPONSE Unknown Command (0x%X) DATA=%s\n", cmd, multiBuffer2String()) end
|
||||
end
|
||||
|
||||
return cmd
|
||||
end
|
||||
|
||||
------------------------------------------------------------------------------------------------------------
|
||||
local function DSM_Send_Receive()
|
||||
local ctx = DSM_Context
|
||||
|
||||
-- Receive part: Process incoming messages if there is nothing to send
|
||||
if ctx.SendDataToRX == 0 and multiBuffer(10) == 0x09 then
|
||||
local cmd = DSM_processResponse()
|
||||
|
||||
multiBuffer(10, 0x00) -- Clear Response Buffer to know that we are done with the response
|
||||
RXInactivityTime = getTime() + SEND_TIMEOUT*4 -- Reset RX Inactivity timeout
|
||||
|
||||
if (cmd > 0x00) then -- RX HeartBeat ??
|
||||
-- Only change to SEND mode if we received a valid response (Ignore heartbeat)
|
||||
ctx.SendDataToRX = 1
|
||||
ctx.Refresh_Display = true
|
||||
end
|
||||
else
|
||||
if (getTime() > RXInactivityTime and ctx.Phase ~= PHASE.RX_VERSION and ctx.Phase ~= PHASE.EXIT_DONE) then
|
||||
if (ctx.isEditing()) then -- If Editing, Extend Timeout
|
||||
RXInactivityTime = getTime() + SEND_TIMEOUT*4
|
||||
else
|
||||
if (DEBUG_ON) then Log.LOG_write("%3.3f %s: RX INACTIVITY TIMEOUT\n", menuLib.getElapsedTime(), menuLib.phase2String(ctx.Phase)) end
|
||||
DSM_ReleaseConnection()
|
||||
error("RX Disconnected")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-----TX Part --------------------------------------
|
||||
if ctx.SendDataToRX == 1 then -- Need to send a request
|
||||
ctx.SendDataToRX = 0
|
||||
DSM_sendRequest()
|
||||
TXInactivityTime = getTime() + SEND_TIMEOUT -- Reset Inactivity timeout
|
||||
else
|
||||
-- Check if enouth time has passed from last transmit/receive activity
|
||||
if getTime() > TXInactivityTime then
|
||||
ctx.SendDataToRX = 1 -- Switch to Send mode to send heartbeat
|
||||
ctx.Refresh_Display = true
|
||||
|
||||
-- Only change to WAIT_CMD if we are NOT wating for RX version
|
||||
if ctx.Phase ~= PHASE.RX_VERSION then
|
||||
-- Phase = If IsEditing then VALUE_CHANGING_WAIT else WAIT_CMD
|
||||
ctx.Phase = (ctx.isEditing() and PHASE.VALUE_CHANGING_WAIT) or PHASE.WAIT_CMD
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Init
|
||||
local function DSM_Init(toolName)
|
||||
local dateTime = getDateTime()
|
||||
local dateStr = dateTime.year.."-"..dateTime.mon.."-"..dateTime.day.." "..dateTime.hour..":"..dateTime.min
|
||||
|
||||
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 (DEBUG_ON) then
|
||||
Log.LOG_write("---------------DSM New Session %s ----------------\n", toolName, dateStr)
|
||||
Log.LOG_write("Radio Info: %s\n", radio .. " " .. (osname or "OpenTx") .. " " .. ver)
|
||||
Log.LOG_write("Date : %s\n", dateStr)
|
||||
Log.LOG_write("DsmLib Version : %s\n", LIB_VERSION)
|
||||
end
|
||||
end
|
||||
|
||||
local function DSM_Init_Text_Exceptions()
|
||||
-- Apply special restrictions to some Values
|
||||
|
||||
local function getTxChText(ch)
|
||||
return " ("..(MODEL.TX_CH_TEXT[ch] or "--")..")"
|
||||
end
|
||||
|
||||
local List_Values = menuLib.List_Values
|
||||
local List_Text = menuLib.List_Text
|
||||
local Text = menuLib.Text
|
||||
|
||||
Log.LOG_write("Initializing TEXT Exception\n")
|
||||
|
||||
-- Channel selection for SAFE MODE and GAINS on FC6250HX
|
||||
--List_Text[0x000C] = "Inhibit?" --?
|
||||
for i = 0, 7 do
|
||||
List_Text[0x000D + i] = "Ch"..(i+5) ..getTxChText(i+4)
|
||||
end -- Aux channels (Ch5 and Greater)
|
||||
|
||||
-- Servo Output values..
|
||||
local servoOutputValues = {0x0003,0x002D,0x002E,0x002F} --Inh (GAP), 5.5ms, 11ms, 22ms. Fixing L_m1 with 0..244 range!
|
||||
--List_Text[0x002D] = "5.5ms"
|
||||
--[0x002E] = "11ms"
|
||||
--List_Text[0x002F] = "22ms"
|
||||
|
||||
-- Gain Values
|
||||
local gainValues = {0x0032,0x0033,0x0034} -- 1X, 2X, 4X -- Fixing L_m1 with 0..244 range!
|
||||
--List_Text[0x0032] = "1 X"
|
||||
--[0x0033] = "2 X"
|
||||
-- List_Text[0x0034] = "4 X"
|
||||
|
||||
-- List of Channels for Safe, Gains, Panic, except FC6250HX that uses other range (0x00C..0x015)
|
||||
-- the valid range Starts with GEAR if enabled (Thr,Ail,Ele,Rud are not valid, the RX reject them )
|
||||
-- Valid Values: Inhibit? (GAP), Gear,Aux1..Aux7,X-Plus-1..XPlus-8
|
||||
local channelValues = {0x0035,0x0036,0x0037,0x0038,0x0039,0x003A,0x003B,0x003C,0x003D,0x003E,0x003F,
|
||||
0x0040,0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047,0x0048,0x0049}
|
||||
|
||||
--List_Text[0x0035] = "Inhibit?"
|
||||
for i = 0, 11 do
|
||||
List_Text[0x0036 + i] = "Ch"..(i+1) .. getTxChText(i)
|
||||
end -- Channels on AR637T
|
||||
|
||||
for i = 1, 8 do -- 41..49
|
||||
List_Text[0x0041 + i] = "Ch"..(i+12)
|
||||
end
|
||||
|
||||
-- Flight mode channel selection
|
||||
--Text[0x0078] = "FM Channel"
|
||||
List_Values[0x0078]=channelValues
|
||||
|
||||
-- Gain channel selection
|
||||
--Text[0x0089] = "Gain Channel"
|
||||
List_Values[0x0089]=channelValues
|
||||
|
||||
-- Gain Sensitivity selection
|
||||
--Text[0x008A] = "Gain Sensitivity/r";
|
||||
List_Values[0x008A]=gainValues -- Right Alight, (L_M1 was wide open range 0->244)
|
||||
|
||||
-- Safe mode options, Ihnibit + this values
|
||||
local safeModeOptions = {0x0003,0x00B0,0x00B1} -- inh (gap), "Self-Level/Angle Dem, Envelope
|
||||
--List_Text[0x00B0] = "Self-Level/Angle Dem"
|
||||
--List_Text[0x00B1] = "Envelope"
|
||||
|
||||
--Text[0x00D2] = "Panic Channel"
|
||||
List_Values[0x00D2]=channelValues
|
||||
|
||||
--Inh, Self-Level/Angle Dem, Envelope -- (L_M was wide open range 0->244)
|
||||
--Text[0x01F8] = "Safe Mode";
|
||||
List_Values[0x01F8]=safeModeOptions
|
||||
end
|
||||
|
||||
-- Initial Setup
|
||||
local function FP_Init(toolname)
|
||||
DSM_Context.Phase = PHASE.INIT
|
||||
|
||||
DSM_Init(toolname)
|
||||
menuLib.clearAllText()
|
||||
end
|
||||
|
||||
local initStep=0
|
||||
local FileState = {}
|
||||
|
||||
local function Message_Init()
|
||||
lcd.clear()
|
||||
if (initStep == 0) then
|
||||
if (IS_EDGETX) then
|
||||
-- Load all messages at once
|
||||
menuLib.LoadTextFromFile(MSG_FILE,13)
|
||||
initStep=1
|
||||
|
||||
else
|
||||
-- load messages incrementally to avoid "CPU Limit"
|
||||
lcd.drawText(30, 50, "Loading Msg file: "..(FileState.lineNo or 0))
|
||||
if (menuLib.INC_LoadTextFromFile(MSG_FILE, FileState)==1) then
|
||||
initStep=1
|
||||
end
|
||||
end
|
||||
elseif (initStep == 1) then
|
||||
DSM_Init_Text_Exceptions()
|
||||
|
||||
DSM_Context.Phase = PHASE.RX_VERSION
|
||||
DSM_StartConnection()
|
||||
end
|
||||
end
|
||||
|
||||
local function FP_Run()
|
||||
if (DSM_Context.Phase==PHASE.INIT) then
|
||||
Message_Init()
|
||||
return 0
|
||||
end
|
||||
|
||||
return DSM_Send_Receive()
|
||||
end
|
||||
|
||||
local function FP_Done()
|
||||
local ctx = menuLib.DSM_Context
|
||||
ctx.Phase = PHASE.EXIT_DONE
|
||||
DSM_ReleaseConnection()
|
||||
end
|
||||
|
||||
return { init=FP_Init, run=FP_Run, done=FP_Done }
|
||||
33
Lua_scripts/DSMLIB/DsmLogLib.lua
Normal file
@@ -0,0 +1,33 @@
|
||||
local LogLib = { }
|
||||
|
||||
local LOG_FILE = "/LOGS/dsm_log.txt"
|
||||
local logFile = nil
|
||||
local logCount=0
|
||||
|
||||
function LogLib.LOG_open()
|
||||
logFile = io.open(LOG_FILE, "w") -- Truncate Log File
|
||||
end
|
||||
|
||||
function LogLib.LOG_write(...)
|
||||
if (logFile==nil) then LogLib.LOG_open() end
|
||||
local str = string.format(...)
|
||||
|
||||
if (str==nil) then return end
|
||||
|
||||
io.write(logFile, str)
|
||||
|
||||
str = string.gsub(str,"\n"," ") -- Elimitate return from line, since print will do it
|
||||
print(str)
|
||||
|
||||
if (logCount > 10) then -- Close an re-open the file
|
||||
io.close(logFile)
|
||||
logFile = io.open(LOG_FILE, "a")
|
||||
logCount =0
|
||||
end
|
||||
end
|
||||
|
||||
function LogLib.LOG_close()
|
||||
if (logFile~=nil) then io.close(logFile) end
|
||||
end
|
||||
|
||||
return LogLib
|
||||
167
Lua_scripts/DSMLIB/DsmMIN_P1.lua
Normal file
@@ -0,0 +1,167 @@
|
||||
local MODEL, M_DATA, LOG_write = ...
|
||||
|
||||
--[[
|
||||
local MODEL = {
|
||||
modelName = "", -- The name of the model comming from OTX/ETX
|
||||
hashName = "",
|
||||
modelOutputChannel = {}, -- Output information from OTX/ETX
|
||||
|
||||
TX_CH_TEXT= { [0]=""},
|
||||
PORT_TEXT = { [0]=""},
|
||||
|
||||
DSM_ChannelInfo = {} -- Data Created by DSM Configuration Script
|
||||
}
|
||||
|
||||
-- MENU DATA Management
|
||||
local M_DATA = {} -- Store the variables used in the Menus.
|
||||
|
||||
--]]
|
||||
|
||||
local DATA_PATH = "/MODELS/DSMDATA"
|
||||
local TX_CHANNELS = 12
|
||||
|
||||
local MV_DATA_END = 1040
|
||||
|
||||
|
||||
local function hashName(mName)
|
||||
local c=10000;
|
||||
|
||||
local prefix = string.gsub(mName,"%.","_") -- Change any "." to "_"
|
||||
prefix = string.gsub(prefix,"% ","_") -- Change any space to "_"
|
||||
prefix = string.sub(prefix,1,5) -- Take the first 5 characters
|
||||
|
||||
-- Simple Hash of the Model Name adding each character
|
||||
for i = 1, #mName do
|
||||
local ch = string.byte(mName,i,i)
|
||||
c=c+ch
|
||||
end
|
||||
|
||||
return (prefix .. c) -- Return Prefix + Hash
|
||||
end
|
||||
|
||||
-- Load Menu Data from a file
|
||||
local function ST_LoadFileData()
|
||||
local fname = hashName(MODEL.modelName)..".txt"
|
||||
MODEL.hashName = fname
|
||||
|
||||
-- Clear Menu Data
|
||||
for i = 0, MV_DATA_END do
|
||||
M_DATA[i]=nil
|
||||
end
|
||||
|
||||
print("Loading File:"..fname)
|
||||
|
||||
local dataFile = io.open(DATA_PATH .. "/".. fname, "r") -- read File
|
||||
-- cannot read file???
|
||||
if (dataFile==nil) then return 0 end
|
||||
|
||||
local line = io.read(dataFile, 5000)
|
||||
io.close(dataFile)
|
||||
|
||||
if #line == 0 then return 0 end -- No data??
|
||||
|
||||
-- Process the input, each line is "Var_Id : Value" format
|
||||
-- Store it into MANU_DATA
|
||||
local i=0
|
||||
for k, v in string.gmatch(line, "(%d+):(%d+)") do
|
||||
M_DATA[k+0]=v+0 -- do aritmentic to convert string to number
|
||||
i=i+1
|
||||
end
|
||||
|
||||
-- Return 0 if no lines processed, 1 otherwise
|
||||
if (i > 0) then return 1 else return 0 end
|
||||
end
|
||||
|
||||
local function getModuleChannelOrder(num)
|
||||
--Determine fist 4 channels order
|
||||
local ch_n={}
|
||||
local st_n = {[0]= "R", "E", "T", "A" }
|
||||
local c_ord=num -- ch order
|
||||
if (c_ord == -1) then
|
||||
ch_n[0] = st_n[3]
|
||||
ch_n[1] = st_n[1]
|
||||
ch_n[2] = st_n[2]
|
||||
ch_n[3] = st_n[0]
|
||||
else
|
||||
ch_n[bit32.band(c_ord,3)] = st_n[3]
|
||||
c_ord = math.floor(c_ord/4)
|
||||
ch_n[bit32.band(c_ord,3)] = st_n[1]
|
||||
c_ord = math.floor(c_ord/4)
|
||||
ch_n[bit32.band(c_ord,3)] = st_n[2]
|
||||
c_ord = math.floor(c_ord/4)
|
||||
ch_n[bit32.band(c_ord,3)] = st_n[0]
|
||||
end
|
||||
|
||||
local s = ""
|
||||
for i=0,3 do
|
||||
s=s..ch_n[i]
|
||||
end
|
||||
return s
|
||||
end
|
||||
|
||||
local function ReadTxModelData()
|
||||
local TRANSLATE_AETR_TO_TAER=false
|
||||
local table = model.getInfo() -- Get the model name
|
||||
MODEL.modelName = table.name
|
||||
|
||||
local module = model.getModule(0) -- Internal
|
||||
if (module==nil or module.Type~=6) then module = model.getModule(1) end -- External
|
||||
if (module~=nil) then
|
||||
if (module.Type==6 ) then -- MULTI-MODULE
|
||||
local chOrder = module.channelsOrder
|
||||
local s = getModuleChannelOrder(chOrder)
|
||||
LOG_write("MultiChannel Ch Order: [%s] %s\n",chOrder,s)
|
||||
|
||||
if (s=="AETR") then TRANSLATE_AETR_TO_TAER=true
|
||||
else TRANSLATE_AETR_TO_TAER=false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Read Ch1 to Ch10
|
||||
local i= 0
|
||||
for i = 0, TX_CHANNELS-1 do
|
||||
local ch = model.getOutput(i) -- Zero base
|
||||
if (ch~=nil) then
|
||||
MODEL.modelOutputChannel[i] = ch
|
||||
if (string.len(ch.name)==0) then
|
||||
ch.formatCh = string.format("TX:Ch%i",i+1)
|
||||
else
|
||||
ch.formatCh = string.format("TX:Ch%i/%s",i+1,ch.name or "--")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Translate AETR to TAER
|
||||
|
||||
if (TRANSLATE_AETR_TO_TAER) then
|
||||
LOG_write("Applying AETR -> TAER translation\n")
|
||||
local ail = MODEL.modelOutputChannel[0]
|
||||
local elv = MODEL.modelOutputChannel[1]
|
||||
local thr = MODEL.modelOutputChannel[2]
|
||||
|
||||
MODEL.modelOutputChannel[0] = thr
|
||||
MODEL.modelOutputChannel[1] = ail
|
||||
MODEL.modelOutputChannel[2] = elv
|
||||
end
|
||||
|
||||
-- Create the Port Text to be used
|
||||
LOG_write("Ports/Channels:\n")
|
||||
for i = 0, TX_CHANNELS-1 do
|
||||
local ch = MODEL.modelOutputChannel[i]
|
||||
if (ch~=nil) then
|
||||
MODEL.TX_CH_TEXT[i] = ch.formatCh
|
||||
MODEL.PORT_TEXT[i] = string.format("P%i (%s) ",i+1,MODEL.TX_CH_TEXT[i])
|
||||
LOG_write("Port%d %s [%d,%d] Rev=%d, Off=%d, ppmC=%d, syn=%d\n",i+1,MODEL.TX_CH_TEXT[i],math.floor(ch.min/10),math.floor(ch.max/10), ch.revert, ch.offset, ch.ppmCenter, ch.symetrical)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Main Program
|
||||
|
||||
LOG_write("Reading Model Info\n")
|
||||
ReadTxModelData()
|
||||
local r = ST_LoadFileData()
|
||||
return r
|
||||
|
||||
|
||||
282
Lua_scripts/DSMLIB/DsmMIN_P2.lua
Normal file
@@ -0,0 +1,282 @@
|
||||
local MODEL, M_DATA, LOG_write = ...
|
||||
|
||||
--[[
|
||||
local MODEL = {
|
||||
modelName = "", -- The name of the model comming from OTX/ETX
|
||||
hashName = "",
|
||||
modelOutputChannel = {}, -- Output information from OTX/ETX
|
||||
|
||||
TX_CH_TEXT= { [0]=""},
|
||||
PORT_TEXT = { [0]=""},
|
||||
|
||||
DSM_ChannelInfo = {} -- Data Created by DSM Configuration Script
|
||||
}
|
||||
|
||||
-- MENU DATA Management
|
||||
local M_DATA = {} -- Store the variables used in the Menus.
|
||||
|
||||
--]]
|
||||
|
||||
|
||||
local TX_CHANNELS = 12
|
||||
|
||||
local AT_PLANE = 0
|
||||
|
||||
local aircraft_type_text = {[0]="Plane","Heli","Glider","Drone"}
|
||||
|
||||
--[[
|
||||
local WT_A1 = 0
|
||||
local WT_A2 = 1
|
||||
local WT_FLPR = 2
|
||||
local WT_A1_F1 = 3
|
||||
local WT_A2_F1 = 4
|
||||
local WT_A2_F2 = 5
|
||||
--]]
|
||||
local WT_ELEVON_A = 6
|
||||
local WT_ELEVON_B = 7
|
||||
|
||||
local wing_type_text = {[0]="Normal","Dual Ail","Flapperon", "Ail + Flp","Dual Ail + Flp","Dual Ail/Flp","Elevon A","Elevon B"}
|
||||
|
||||
--[[
|
||||
local TT_R1 = 0
|
||||
local TT_R1_E1 = 1
|
||||
local TT_R1_E2 = 2
|
||||
local TT_R2_E1 = 3
|
||||
local TT_R2_E2 = 4
|
||||
--]]
|
||||
|
||||
local TT_VT_A = 5
|
||||
local TT_VT_B = 6
|
||||
local TT_TLRN_A = 7
|
||||
local TT_TLRN_B = 8
|
||||
local TT_TLRN_A_R2 = 9
|
||||
local TT_TLRN_B_R2 = 10
|
||||
|
||||
local tail_type_text = {[0]="Rud Only","Normal","Rud + Dual Ele","Dual Rud + Elv","Dual Rud/Ele",
|
||||
"VTail A","VTail B","Taileron A","Taileron B","Taileron A + Dual Rud","Taileron B + Dual Rud"}
|
||||
|
||||
|
||||
local MV_AIRCRAFT_TYPE = 1001
|
||||
local MV_WING_TYPE = 1002
|
||||
local MV_TAIL_TYPE = 1003
|
||||
|
||||
local MV_CH_BASE = 1010
|
||||
local MV_CH_THR = 1010
|
||||
local MV_CH_L_AIL = 1011
|
||||
local MV_CH_R_AIL = 1012
|
||||
local MV_CH_L_FLP = 1013
|
||||
local MV_CH_R_FLP = 1014
|
||||
|
||||
local MV_CH_L_RUD = 1015
|
||||
local MV_CH_R_RUD = 1016
|
||||
local MV_CH_L_ELE = 1017
|
||||
local MV_CH_R_ELE = 1018
|
||||
|
||||
local MV_PORT_BASE = 1020
|
||||
|
||||
local MV_DATA_END = 1040
|
||||
|
||||
--Channel Types --
|
||||
local CT_NONE = 0x00
|
||||
local CT_AIL = 0x01
|
||||
local CT_ELE = 0x02
|
||||
local CT_RUD = 0x04
|
||||
local CT_REVERSE = 0x20
|
||||
local CT_THR = 0x40
|
||||
local CT_SLAVE = 0x80
|
||||
|
||||
-- Seems like Reverse Mix is complement of the 3 bits
|
||||
local CMT_NORM = 0x00 -- 0000
|
||||
local CMT_AIL = 0x10 -- 0001 Taileron
|
||||
local CMT_ELE = 0x20 -- 0010 For VTIAL and Delta-ELEVON
|
||||
local CMT_RUD = 0x30 -- 0011 For VTIAL
|
||||
local CMT_RUD_REV = 0x40 -- 0100 For VTIAL
|
||||
local CMT_ELE_REV = 0x50 -- 0101 For VTIAL and Delta-ELEVON A
|
||||
local CMT_AIL_REV = 0x60 -- 0110 Taileron
|
||||
local CMT_NORM_REV = 0x70 -- 0111
|
||||
|
||||
local MT_NORMAL = 0
|
||||
local MT_REVERSE = 1
|
||||
|
||||
local function channelType2String(byte1, byte2)
|
||||
local s = ""
|
||||
|
||||
if (byte2==0) then return s end;
|
||||
|
||||
if (bit32.band(byte2,CT_AIL)>0) then s=s.."Ail" end
|
||||
if (bit32.band(byte2,CT_ELE)>0) then s=s.."Ele" end
|
||||
if (bit32.band(byte2,CT_RUD)>0) then s=s.."Rud" end
|
||||
if (bit32.band(byte2,CT_THR)>0) then s=s.."Thr" end
|
||||
|
||||
if (bit32.band(byte2,CT_REVERSE)>0) then s=s.."-" end
|
||||
|
||||
if (bit32.band(byte2,CT_SLAVE)>0) then s=s.." Slv" end
|
||||
|
||||
if (byte1==CMT_NORM) then s=s.." "
|
||||
elseif (byte1==CMT_AIL) then s=s.." M_Ail"
|
||||
elseif (byte1==CMT_ELE) then s=s.." M_Ele"
|
||||
elseif (byte1==CMT_RUD) then s=s.." M_Rud"
|
||||
elseif (byte1==CMT_RUD_REV) then s=s.." M_Rud-"
|
||||
elseif (byte1==CMT_ELE_REV) then s=s.." M_Ele-"
|
||||
elseif (byte1==CMT_AIL_REV) then s=s.." M_Ail-"
|
||||
elseif (byte1==CMT_NORM_REV) then s=s.." M-"
|
||||
end
|
||||
|
||||
return s;
|
||||
end
|
||||
|
||||
-- This Creates the Servo Settings that will be used to pass to
|
||||
-- Forward programming
|
||||
local function CreateDSMPortChannelInfo()
|
||||
local function ApplyWingMixA(b2)
|
||||
-- ELEVON
|
||||
if (b2==CT_AIL+CT_ELE) then return CMT_ELE end; -- 0x03
|
||||
if (b2==CT_AIL+CT_ELE+CT_SLAVE) then return CMT_NORM end; -- 0x83
|
||||
end
|
||||
|
||||
local function ApplyWingMixB(b2)
|
||||
-- ELEVON
|
||||
if (b2==CT_AIL+CT_ELE) then return CMT_NORM end; -- 0x03
|
||||
if (b2==CT_AIL+CT_ELE+CT_SLAVE) then return CMT_ELE end; -- 0x83
|
||||
end
|
||||
|
||||
local function ApplyTailMixA(b2)
|
||||
-- VTAIL
|
||||
-- Default normal/reverse behaviour
|
||||
if (b2==CT_RUD+CT_ELE) then return CMT_NORM end; -- 0x06
|
||||
if (b2==CT_RUD+CT_ELE+CT_SLAVE) then return CMT_ELE end; -- 0x86
|
||||
|
||||
--TAILERON
|
||||
-- Default normal/reverse behaviour
|
||||
if (b2==CT_AIL+CT_ELE) then return CMT_NORM end; -- 0x03
|
||||
if (b2==CT_AIL+CT_ELE+CT_SLAVE) then return CMT_AIL end; -- 0x83
|
||||
end
|
||||
|
||||
local function ApplyTailMixB(b2)
|
||||
-- VTAIL
|
||||
-- Default normal/reverse behaviour
|
||||
if (b2==CT_RUD+CT_ELE) then return CMT_NORM end; -- 0x06
|
||||
if (b2==CT_RUD+CT_ELE+CT_SLAVE) then return CMT_RUD end; -- 0x86
|
||||
|
||||
--TAILERON
|
||||
if (b2==CT_AIL+CT_ELE) then return CMT_AIL end; -- 0x03
|
||||
if (b2==CT_AIL+CT_ELE+CT_SLAVE) then return CMT_NORM end; -- 0x83
|
||||
end
|
||||
|
||||
local function reverseMix(b)
|
||||
if (b==CMT_NORM) then return CMT_NORM_REV end;
|
||||
if (b==CMT_AIL) then return CMT_AIL_REV end;
|
||||
if (b==CMT_ELE) then return CMT_ELE_REV end;
|
||||
if (b==CMT_RUD) then return CMT_RUD_REV end;
|
||||
return b
|
||||
end
|
||||
|
||||
local DSM_Ch = MODEL.DSM_ChannelInfo
|
||||
|
||||
for i=0, TX_CHANNELS-1 do
|
||||
DSM_Ch[i] = {[0]= CMT_NORM, CT_NONE, nil} -- Initialize with no special function
|
||||
end
|
||||
|
||||
--local aircraftType = M_DATA[MV_AIRCRAFT_TYPE]
|
||||
local wingType = M_DATA[MV_WING_TYPE]
|
||||
local tailType = M_DATA[MV_TAIL_TYPE]
|
||||
|
||||
local thrCh = M_DATA[MV_CH_THR]
|
||||
local lAilCh = M_DATA[MV_CH_L_AIL]
|
||||
local rAilCh = M_DATA[MV_CH_R_AIL]
|
||||
|
||||
local lElevCh = M_DATA[MV_CH_L_ELE]
|
||||
local rElevCh = M_DATA[MV_CH_R_ELE]
|
||||
|
||||
local lRudCh = M_DATA[MV_CH_L_RUD]
|
||||
local rRudCh = M_DATA[MV_CH_R_RUD]
|
||||
|
||||
-- Channels in menu vars are Zero base, Channel info is 1 based
|
||||
|
||||
-- THR
|
||||
if (thrCh~=nil and thrCh < 10) then DSM_Ch[thrCh][1]= CT_THR end
|
||||
|
||||
-- AIL (Left and Right)
|
||||
if (lAilCh~=nil) then DSM_Ch[lAilCh][1] = CT_AIL end
|
||||
if (rAilCh~=nil) then DSM_Ch[rAilCh][1] = CT_AIL+CT_SLAVE end
|
||||
-- ELE (Left and Right)
|
||||
if (lElevCh~=nil) then DSM_Ch[lElevCh][1] = CT_ELE end
|
||||
if (rElevCh~=nil) then DSM_Ch[rElevCh][1] = CT_ELE+CT_SLAVE end
|
||||
-- RUD (Left and Right)
|
||||
if (lRudCh~=nil) then DSM_Ch[lRudCh][1] = CT_RUD end
|
||||
if (rRudCh~=nil) then DSM_Ch[rRudCh][1] = CT_RUD+CT_SLAVE end
|
||||
|
||||
-- VTAIL: RUD + ELE
|
||||
if (tailType==TT_VT_A) then
|
||||
DSM_Ch[lElevCh][1] = CT_RUD+CT_ELE
|
||||
DSM_Ch[rElevCh][1] = CT_RUD+CT_ELE+CT_SLAVE
|
||||
elseif (tailType==TT_VT_B) then
|
||||
DSM_Ch[lElevCh][1] = CT_RUD+CT_ELE+CT_SLAVE
|
||||
DSM_Ch[rElevCh][1] = CT_RUD+CT_ELE
|
||||
end
|
||||
|
||||
-- TAILERRON: 2-ELE + AIL
|
||||
if (tailType==TT_TLRN_A or tailType==TT_TLRN_A_R2) then
|
||||
DSM_Ch[lElevCh][1] = CT_AIL+CT_ELE
|
||||
DSM_Ch[rElevCh][1] = CT_AIL+CT_ELE+CT_SLAVE
|
||||
elseif (tailType==TT_TLRN_B or tailType==TT_TLRN_B_R2) then
|
||||
DSM_Ch[lElevCh][1] = CT_AIL+CT_ELE+CT_SLAVE
|
||||
DSM_Ch[rElevCh][1] = CT_AIL+CT_ELE
|
||||
end
|
||||
|
||||
---- ELEVON : AIL + ELE
|
||||
if (wingType==WT_ELEVON_A) then
|
||||
DSM_Ch[lAilCh][1] = CT_AIL+CT_ELE
|
||||
DSM_Ch[rAilCh][1] = CT_AIL+CT_ELE+CT_SLAVE
|
||||
elseif (wingType==WT_ELEVON_B) then
|
||||
DSM_Ch[lAilCh][1] = CT_AIL+CT_ELE+CT_SLAVE
|
||||
DSM_Ch[rAilCh][1] = CT_AIL+CT_ELE
|
||||
end
|
||||
|
||||
------MIXES ---------
|
||||
|
||||
-- TAIL Mixes (Elevator and VTail)
|
||||
if (tailType==TT_VT_A or tailType==TT_TLRN_A or tailType==TT_TLRN_A_R2) then
|
||||
DSM_Ch[lElevCh][0] = ApplyTailMixA(DSM_Ch[lElevCh][1])
|
||||
DSM_Ch[rElevCh][0] = ApplyTailMixA(DSM_Ch[rElevCh][1])
|
||||
elseif (tailType==TT_VT_B or tailType==TT_TLRN_B or tailType==TT_TLRN_B_R2) then
|
||||
DSM_Ch[lElevCh][0] = ApplyTailMixB(DSM_Ch[lElevCh][1])
|
||||
DSM_Ch[rElevCh][0] = ApplyTailMixB(DSM_Ch[rElevCh][1])
|
||||
end
|
||||
|
||||
---- ELEVON : AIL + ELE
|
||||
if (wingType==WT_ELEVON_A) then
|
||||
DSM_Ch[lAilCh][0] = ApplyWingMixA(DSM_Ch[lAilCh][1])
|
||||
DSM_Ch[rAilCh][0] = ApplyWingMixA(DSM_Ch[rAilCh][1])
|
||||
elseif (wingType==WT_ELEVON_B) then
|
||||
DSM_Ch[lAilCh][0] = ApplyWingMixB(DSM_Ch[lAilCh][1])
|
||||
DSM_Ch[rAilCh][0] = ApplyWingMixB(DSM_Ch[rAilCh][1])
|
||||
end
|
||||
|
||||
-- Apply Gyro Reverse as needed for each channel as long as it is used
|
||||
for i=0, TX_CHANNELS-1 do
|
||||
if (M_DATA[MV_PORT_BASE+i]==MT_REVERSE and DSM_Ch[i][1]>0) then
|
||||
DSM_Ch[i][0]=reverseMix(DSM_Ch[i][0])
|
||||
DSM_Ch[i][1]=DSM_Ch[i][1]+CT_REVERSE
|
||||
end
|
||||
end
|
||||
|
||||
-- Show how it looks
|
||||
for i=0, 9 do
|
||||
local b1,b2 = DSM_Ch[i][0], DSM_Ch[i][1]
|
||||
local s1 = channelType2String(b1,b2)
|
||||
local s = string.format("%s (%02X %02X) %s\n", MODEL.PORT_TEXT[i],
|
||||
b1, b2,s1)
|
||||
DSM_Ch[i][2]=s1
|
||||
LOG_write(s)
|
||||
end
|
||||
|
||||
--MODEL.AirWingTailDesc = string.format("Aircraft(%s) Wing(%s) Tail(%s)",aircraft_type_text[aircraftType],wing_type_text[wingType],tail_type_text[tailType])
|
||||
end
|
||||
|
||||
-- Main Program
|
||||
|
||||
LOG_write("Creating DSMPort Info\n")
|
||||
CreateDSMPortChannelInfo()
|
||||
|
||||
|
||||
90
Lua_scripts/DSMLIB/DsmMainMenuLib.lua
Normal file
@@ -0,0 +1,90 @@
|
||||
local Log, menuLib, modelLib, DEBUG_ON, SIMULATION_ON = ... -- Get DebugON from parameters
|
||||
local MAIN_MENU_LIB_VERSION = "0.56"
|
||||
local MODEL = modelLib.MODEL
|
||||
|
||||
local PHASE = menuLib.PHASE
|
||||
local LINE_TYPE = menuLib.LINE_TYPE
|
||||
|
||||
local lastGoodMenu=0
|
||||
|
||||
-- Creates the menus to Render with the GUI
|
||||
local function ST_LoadMenu(menuId)
|
||||
local ctx = menuLib.DSM_Context
|
||||
menuLib.clearMenuLines()
|
||||
|
||||
if (menuId==0x1000) then -- MAIN MENU
|
||||
ctx.Menu = { MenuId = 0x1000, Text = "Main Menu ("..MODEL.modelName..")", PrevId = 0, NextId = 0, BackId = 0, TextId=0 }
|
||||
ctx.MenuLines[0] = { Type = LINE_TYPE.MENU, Text = "Model Setup", ValId = 0xFFF3,TextId=0 }
|
||||
|
||||
if (SIMULATION_ON) then
|
||||
ctx.MenuLines[4] = { Type = LINE_TYPE.MENU, Text = "RX Simulator (GUI dev only)", ValId = 0xFFF1, TextId=0 } -- Menu 0xFFF2 to SIMULATOR
|
||||
end
|
||||
ctx.MenuLines[6] = { Type = LINE_TYPE.MENU, Text = "Forward Programming RX", ValId = 0xFFF2, TextId=0 } -- Menu 0xFFF2 to Real RX
|
||||
ctx.SelLine = 6
|
||||
|
||||
lastGoodMenu = menuId
|
||||
else
|
||||
--print("NOT IMPLEMENTED")
|
||||
ctx.Menu = { MenuId = 0x0002, Text = "NOT IMPLEMENTED", TextId = 0, PrevId = 0, NextId = 0, BackId = lastGoodMenu }
|
||||
ctx.SelLine = menuLib.BACK_BUTTON
|
||||
end
|
||||
|
||||
menuLib.PostProcessMenu()
|
||||
end
|
||||
|
||||
local function Main_Send_Receive()
|
||||
local ctx = menuLib.DSM_Context
|
||||
|
||||
if ctx.Phase == PHASE.RX_VERSION then -- Just Init RX Version
|
||||
ctx.RX.Name = "Main Menu"
|
||||
ctx.RX.Version = MAIN_MENU_LIB_VERSION
|
||||
ctx.Phase = PHASE.MENU_TITLE
|
||||
ctx.Menu.MenuId = 0
|
||||
|
||||
ctx.Refresh_Display = true
|
||||
elseif ctx.Phase == PHASE.WAIT_CMD then
|
||||
|
||||
elseif ctx.Phase == PHASE.MENU_TITLE then -- request menu title
|
||||
if ctx.Menu.MenuId == 0 then -- First time loading a menu ?
|
||||
ST_LoadMenu(0x01000)
|
||||
else
|
||||
ST_LoadMenu(ctx.Menu.MenuId)
|
||||
end
|
||||
ctx.Phase = PHASE.WAIT_CMD
|
||||
ctx.Refresh_Display = true
|
||||
|
||||
elseif ctx.Phase == PHASE.VALUE_CHANGING then -- send value
|
||||
local line = ctx.MenuLines[ctx.SelLine] -- Updated Value of SELECTED line
|
||||
--if (DEBUG_ON) then Log.LOG_write("%3.3f %s: ", menuLib.getElapsedTime(), menuLib.phase2String(ctx.Phase)) end
|
||||
--if (DEBUG_ON) then Log.LOG_write("SEND SIM_updateMenuValue(ValueId=0x%X Text=\"%s\" Value=%s)\n", line.ValId, line.Text, menuLib.lineValue2String(line)) end
|
||||
ctx.Phase = PHASE.VALUE_CHANGING_WAIT
|
||||
|
||||
elseif ctx.Phase == PHASE.VALUE_CHANGING_WAIT then
|
||||
local line = ctx.MenuLines[ctx.SelLine]
|
||||
|
||||
elseif ctx.Phase == PHASE.VALUE_CHANGE_END then -- send value
|
||||
local line = ctx.MenuLines[ctx.SelLine] -- Updated Value of SELECTED line
|
||||
--if (DEBUG_ON) then Log.LOG_write("%3.3f %s: ", menuLib.getElapsedTime(), menuLib.phase2String(ctx.Phase)) end
|
||||
--if (DEBUG_ON) then Log.LOG_write("SEND SIM_updateMenuValue(ValueId=0x%X Text=\"%s\" Value=%s)\n", line.ValId, line.Text, menuLib.lineValue2String(line)) end
|
||||
--if (DEBUG_ON) then Log.LOG_write("SEND SIM_validateMenuValue(ValueId=0x%X Text=\"%s\" Value=%s)\n", line.ValId, line.Text, menuLib.lineValue2String(line)) end
|
||||
ctx.Phase = PHASE.WAIT_CMD
|
||||
|
||||
elseif ctx.Phase == PHASE.EXIT then
|
||||
ctx.Phase=PHASE.EXIT_DONE
|
||||
return 1
|
||||
end
|
||||
|
||||
return 0
|
||||
end
|
||||
|
||||
local function Main_Init()
|
||||
local ctx = menuLib.DSM_Context
|
||||
ctx.Phase = PHASE.RX_VERSION
|
||||
end
|
||||
|
||||
local function Main_Done()
|
||||
local ctx = menuLib.DSM_Context
|
||||
ctx.Phase = PHASE.EXIT_DONE
|
||||
end
|
||||
|
||||
return { init=Main_Init, run=Main_Send_Receive, done=Main_Done }
|
||||
788
Lua_scripts/DSMLIB/DsmMenuLib.lua
Normal file
@@ -0,0 +1,788 @@
|
||||
--- #########################################################################
|
||||
---- # #
|
||||
---- # Copyright (C) OpenTX/EdgeTx #
|
||||
-----# #
|
||||
---- # 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 Log, DEBUG_ON = ... -- Parameters
|
||||
|
||||
|
||||
local MenuLib = { }
|
||||
|
||||
local PHASE = {
|
||||
INIT = 0,
|
||||
RX_VERSION = 1,
|
||||
WAIT_CMD = 2,
|
||||
MENU_TITLE = 3,
|
||||
MENU_REQ_TX_INFO = 4,
|
||||
MENU_LINES = 5,
|
||||
MENU_VALUES = 6,
|
||||
VALUE_CHANGING = 7,
|
||||
VALUE_CHANGING_WAIT = 8,
|
||||
VALUE_CHANGE_END = 9,
|
||||
EXIT = 10,
|
||||
EXIT_DONE = 11
|
||||
}
|
||||
|
||||
local LINE_TYPE = {
|
||||
MENU = 0x1C,
|
||||
LIST_MENU = 0x0C, -- List: INC Change + Validate
|
||||
LIST_MENU_NC = 0x6C, -- List: No Incremental Change
|
||||
LIST_MENU_NC2 = 0x6D, -- List: No Incremental Change (Frame Rate Herz)
|
||||
LIST_MENU_TOG = 0x4C, -- List: Incremental Change, sometimes bolean/Toggle menu (if only 2 values)
|
||||
LIST_MENU_ORI = 0xCC, -- List: Incremental Change, Orientation Heli
|
||||
|
||||
VALUE_NUM_I8_NC = 0x60, -- 8 bit number, no incremental change
|
||||
VALUE_PERCENT = 0xC0, -- 8 bit number, Signed, percent
|
||||
VALUE_DEGREES = 0xE0, -- 8 bit number, Signed, Degress
|
||||
VALUE_NUM_I8 = 0x40, -- 8 bit number
|
||||
VALUE_NUM_I16 = 0x41, -- 16 Bit number
|
||||
VALUE_NUM_SI16 = 0xC1, -- 16 bit number, Signed
|
||||
|
||||
LT_EMPTY = 0x00
|
||||
}
|
||||
|
||||
-- Bug in Lua compiler, confusing with global BOLD and RIGHT
|
||||
local DISP_ATTR = {
|
||||
_BOLD = 0x01, _RIGHT=0x02, _CENTER=0x04, PERCENT = 0x10, DEGREES=0x20, FORCED_MENU = 0x40
|
||||
}
|
||||
|
||||
--RX IDs--
|
||||
local RX = {
|
||||
AR636B = 0x0001,
|
||||
SPM4651T = 0x0014,
|
||||
AR637T = 0x0015,
|
||||
AR637TA = 0x0016,
|
||||
FC6250HX = 0x0018,
|
||||
AR630 = 0x0019,
|
||||
AR8360T = 0x001A,
|
||||
AR10360T = 0x001C,
|
||||
AR631 = 0x001E
|
||||
}
|
||||
|
||||
local DSM_Context = {
|
||||
Phase = PHASE.INIT,
|
||||
Menu = { MenuId = 0, Text = "", TextId = 0, PrevId = 0, NextId = 0, BackId = 0 },
|
||||
MenuLines = {},
|
||||
RX = { Id=0, Name = "", Version = "" },
|
||||
Refresh_Display = true,
|
||||
SendDataToRX = 1,
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
function DSM_Context.isEditing() return DSM_Context.EditLine~=nil end
|
||||
|
||||
local MAX_MENU_LINES = 6
|
||||
local BACK_BUTTON = -1 -- Tread it as a display line #-1
|
||||
local NEXT_BUTTON = MAX_MENU_LINES + 1 -- Tread it as a display line #7
|
||||
local PREV_BUTTON = MAX_MENU_LINES + 2 -- Tread it as a display line #7
|
||||
|
||||
-- Text Arrays for Display Text and Debuging
|
||||
local PhaseText = {}
|
||||
local LineTypeText = {}
|
||||
|
||||
local Text = {} -- Text for Menu and Menu Lines (Headers only)
|
||||
local List_Text = {} -- Messages for List Options (values only)
|
||||
local List_Text_Img = {} -- If the Text has Attached Images
|
||||
local List_Values = {} -- Additiona restrictions on List Values when non contiguos (L_M1 lines has this problem)
|
||||
local Flight_Mode = {[0]="Fligh Mode"}
|
||||
local RxName = {}
|
||||
|
||||
local StartTime = 0
|
||||
|
||||
------------------------------------------------------------------------------------------------------------
|
||||
-- Get Elapsed Time since we started running the Script. Return a float in format: Seconds.Milliseconds
|
||||
function MenuLib.getElapsedTime()
|
||||
local t = getTime()
|
||||
if (StartTime == 0) then StartTime = t end
|
||||
|
||||
return ((t - StartTime) * 10) / 1000
|
||||
end
|
||||
|
||||
------------- Line Type helper functions ------------------------------------------------------------------
|
||||
|
||||
-- Check if the text are Flight modes, who will be treated different for Display
|
||||
function MenuLib.isFlightModeLine(line)
|
||||
return (line.TextId >= 0x8000 and line.TextId <= 0x8003)
|
||||
end
|
||||
|
||||
function MenuLib.isSelectableLine(line) -- is the display line Selectable??
|
||||
-- values who are not selectable
|
||||
if (line.Type == 0) then return false end -- Empty Line
|
||||
if (line.Type == LINE_TYPE.MENU and line.ValId == line.MenuId and bit32.band(line.TextAttr, DISP_ATTR.FORCED_MENU)==0) then return false end -- Menu that navigates to Itself?
|
||||
if (line.Min==0 and line.Max==0 and line.Def==0) then return false end -- Values with no Range are only for display
|
||||
if (line.Type == LINE_TYPE.VALUE_NUM_I8_NC and MenuLib.isFlightModeLine(line)) then return false end -- Flight mode is not Selectable
|
||||
return true
|
||||
end
|
||||
|
||||
function MenuLib.isEditableLine(line) -- is the display line editable??
|
||||
-- values who are not editable
|
||||
if (line.Type == 0 or line.Type == LINE_TYPE.MENU) then return false end -- Menus are not editable
|
||||
if (line.Min==0 and line.Max==0 and line.Def==0) then return false end -- Values with no Range are only for display
|
||||
if (line.Type == LINE_TYPE.VALUE_NUM_I8_NC and MenuLib.isFlightModeLine(line)) then return false end -- Flight mode is not Editable
|
||||
-- any other is Editable
|
||||
return true
|
||||
end
|
||||
|
||||
function MenuLib.isListLine(line) -- is it a List of options??
|
||||
if (line.Type == LINE_TYPE.LIST_MENU_NC or line.Type == LINE_TYPE.LIST_MENU or
|
||||
line.Type == LINE_TYPE.LIST_MENU_TOG or line.Type == LINE_TYPE.LIST_MENU_NC2 or
|
||||
line.Type == LINE_TYPE.LIST_MENU_ORI) then return true end
|
||||
return false
|
||||
end
|
||||
|
||||
function MenuLib.isPercentValueLineByMinMax(line)
|
||||
return
|
||||
(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)
|
||||
end
|
||||
|
||||
function MenuLib.isPercentValueLine(line) -- is it a Percent value??
|
||||
if (line.Type == LINE_TYPE.VALUE_PERCENT) then return true end
|
||||
return false
|
||||
end
|
||||
|
||||
function MenuLib.isNumberValueLine(line) -- is it a number ??
|
||||
if (MenuLib.isListLine(line) or line.Type == LINE_TYPE.MENU or line.Type == 0) then return false
|
||||
else return true end
|
||||
end
|
||||
|
||||
function MenuLib.isIncrementalValueUpdate(line)
|
||||
if (line.Type == LINE_TYPE.LIST_MENU_NC or line.Type == LINE_TYPE.LIST_MENU_NC2 or
|
||||
line.Type == LINE_TYPE.VALUE_NUM_I8_NC or line.Type == LINE_TYPE.VALUE_DEGREES) then return false end
|
||||
return true
|
||||
end
|
||||
|
||||
------------------------------------------------------------------------------------------------------------
|
||||
function MenuLib.Get_Text(index)
|
||||
if (index >= 0x8000) then
|
||||
return Flight_Mode[0]
|
||||
end
|
||||
|
||||
local out = Text[index] -- Find in regular header first
|
||||
if out== nil then
|
||||
out = List_Text[index] -- Try list values, don't think is necesary, but just playing Safe
|
||||
end
|
||||
if out == nil then -- unknown...
|
||||
out = "Unknown_" .. string.format("%X", index)
|
||||
end
|
||||
return out
|
||||
end
|
||||
|
||||
function MenuLib.Get_List_Text(index)
|
||||
local out = List_Text[index] -- Try to find the message in List_Text
|
||||
if out == nil then
|
||||
out = Text[index] -- Try list headers, don't think is necesary, but just playing Safe
|
||||
end
|
||||
if out == nil then -- unknown...
|
||||
out = "UnknownLT_" .. string.format("%X", index)
|
||||
end
|
||||
return out
|
||||
end
|
||||
|
||||
function MenuLib.Get_List_Text_Img(index)
|
||||
local out = List_Text_Img[index]
|
||||
return out
|
||||
end
|
||||
|
||||
function MenuLib.Get_List_Values(index)
|
||||
local out = List_Values[index]
|
||||
return out
|
||||
end
|
||||
|
||||
function MenuLib.Get_RxName(index)
|
||||
local out = RxName[index]
|
||||
return out or ("RX_" .. string.format("%X", index))
|
||||
end
|
||||
|
||||
----------- Debugging 2-String functions -------------------------------------------------------------------
|
||||
|
||||
function MenuLib.phase2String(index)
|
||||
local out = PhaseText[index]
|
||||
return out or ("Phase_" .. string.format("%X", index))
|
||||
end
|
||||
|
||||
function MenuLib.lineType2String(index)
|
||||
local out = LineTypeText[index]
|
||||
return out or ("LT_" .. string.format("%X", index or 0xFF))
|
||||
end
|
||||
|
||||
function MenuLib.lineValue2String(l)
|
||||
if (DEBUG_ON == 0) then
|
||||
return ""
|
||||
end
|
||||
if (l ~= nil and l.Val ~= nil) then
|
||||
local value = l.Val
|
||||
if MenuLib.isListLine(l) then
|
||||
value = value .. "|\"" .. MenuLib.Get_List_Text(l.Val + l.TextStart) .. "\""
|
||||
else
|
||||
value = value..(l.Format or "")
|
||||
end
|
||||
return value
|
||||
end
|
||||
return "nil"
|
||||
end
|
||||
|
||||
function MenuLib.menu2String(m)
|
||||
local txt = "Menu[]"
|
||||
if (m ~= nil) then
|
||||
txt = string.format("M[Id=0x%X P=0x%X N=0x%X B=0x%X Text=\"%s\"[0x%X]]",
|
||||
m.MenuId, m.PrevId, m.NextId, m.BackId, m.Text, m.TextId)
|
||||
end
|
||||
return txt
|
||||
end
|
||||
|
||||
function MenuLib.menuLine2String(l)
|
||||
local txt = "Line[]"
|
||||
if (l ~= nil) then
|
||||
local value = ""
|
||||
local range = ""
|
||||
if l.Type~=LINE_TYPE.MENU then
|
||||
value = "Val="..MenuLib.lineValue2String(l)
|
||||
if MenuLib.isListLine(l) then
|
||||
range = string.format("NL=(%s->%s,%s,S=%s) ",l.Min, l.Max, l.Def, l.TextStart )
|
||||
range = range .. (l.MinMaxOrig or "")
|
||||
else
|
||||
range = string.format("[%s->%s,%s]",l.Min, l.Max, l.Def)
|
||||
end
|
||||
end
|
||||
|
||||
txt = string.format("L[#%s T=%s VId=0x%X Text=\"%s\"[0x%X] %s %s MId=0x%X A=0x%X]",
|
||||
l.lineNum, MenuLib.lineType2String(l.Type), l.ValId,
|
||||
l.Text, l.TextId,
|
||||
value,
|
||||
range,
|
||||
l.MenuId,
|
||||
l.TextAttr
|
||||
)
|
||||
end
|
||||
return txt
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------------------------------------
|
||||
-- Post Procssing Line from Raw values receive by RX or Simulation
|
||||
|
||||
function MenuLib.isDisplayAttr(attr, bit)
|
||||
return (bit32.band(attr,bit)>0)
|
||||
end
|
||||
|
||||
function MenuLib.ExtractDisplayAttr(text1, attr)
|
||||
local text = text1, pos;
|
||||
|
||||
for i=1,2 do
|
||||
text, pos = string.gsub(text, "/c$", "")
|
||||
if (pos>0) then -- CENTER
|
||||
attr = bit32.bor(attr, DISP_ATTR._CENTER)
|
||||
end
|
||||
|
||||
text, pos = string.gsub(text, "/r$", "")
|
||||
if (pos>0) then -- RIGHT
|
||||
attr = bit32.bor(attr, DISP_ATTR._RIGHT)
|
||||
end
|
||||
|
||||
text, pos = string.gsub(text, "/p$", "")
|
||||
if (pos>0) then -- Percent TEXT
|
||||
attr = bit32.bor(attr, DISP_ATTR.PERCENT)
|
||||
end
|
||||
|
||||
text, pos = string.gsub(text, "/b$", "")
|
||||
if (pos>0) then -- BOLD TEXT
|
||||
attr = bit32.bor(attr, DISP_ATTR._BOLD)
|
||||
end
|
||||
|
||||
text, pos = string.gsub(text, "/m$", "")
|
||||
if (pos>0) then -- FORCED MENU Button
|
||||
attr = bit32.bor(attr, DISP_ATTR.FORCED_MENU)
|
||||
end
|
||||
end
|
||||
|
||||
return text, attr
|
||||
end
|
||||
|
||||
function MenuLib.MenuPostProcessing(menu)
|
||||
menu.Text, menu.TextAttr = MenuLib.ExtractDisplayAttr(menu.Text,menu.TextAttr or 0)
|
||||
end
|
||||
|
||||
function MenuLib.MenuLinePostProcessing(line)
|
||||
if (line.Text==nil) then
|
||||
line.Text = MenuLib.Get_Text(line.TextId) -- Get Textual Line headeing text
|
||||
end
|
||||
|
||||
-- Text formatting options
|
||||
line.Text, line.TextAttr = MenuLib.ExtractDisplayAttr(line.Text,line.TextAttr or 0)
|
||||
|
||||
if line.Type == LINE_TYPE.MENU then
|
||||
-- nothing to do on menu entries
|
||||
line.Val=nil
|
||||
elseif MenuLib.isListLine(line) then
|
||||
-- Original Range for Debugging
|
||||
line.MinMaxOrig = "[" .. line.Min .. "->" .. line.Max .. "," .. line.Def .. "]"
|
||||
|
||||
-- Normalize Min/Max to be relative to Zero
|
||||
line.TextStart = line.Min
|
||||
line.Def = line.Def - line.Min -- normalize default value
|
||||
line.Max = line.Max - line.Min -- normalize max index
|
||||
line.Min = 0 -- min index
|
||||
else -- default to numerical value
|
||||
if MenuLib.isPercentValueLine(line) or MenuLib.isPercentValueLineByMinMax(line) then
|
||||
-- either explicit Percent or NO-Change value, but range is %Percent
|
||||
line.Format ="%"
|
||||
line.TextAttr = bit32.bor(line.TextAttr,DISP_ATTR.PERCENT)
|
||||
elseif (line.Type == LINE_TYPE.VALUE_DEGREES) then
|
||||
line.Format ="o"
|
||||
line.TextAttr = bit32.bor(line.TextAttr,DISP_ATTR.DEGREES)
|
||||
end
|
||||
end
|
||||
|
||||
line.MinMaxDebug = MenuLib.lineType2String(line.Type).." "..(line.MinMaxOrig or "")
|
||||
end
|
||||
|
||||
|
||||
function MenuLib.ChangePhase(newPhase)
|
||||
DSM_Context.Phase = newPhase
|
||||
DSM_Context.SendDataToRX = 1
|
||||
end
|
||||
|
||||
function MenuLib.Value_Add(line, inc)
|
||||
if (DEBUG_ON) then Log.LOG_write("%3.3f %s: DSM_Value_Add(%s,%s)\n",
|
||||
MenuLib.getElapsedTime(), MenuLib.phase2String(DSM_Context.Phase), inc, MenuLib.menuLine2String(line)) end
|
||||
|
||||
local skipIncrement = false
|
||||
local values = nil
|
||||
local origVal = line.Val
|
||||
|
||||
-- Use local validation for LIST_MENU1 when the range is wide open
|
||||
-- Also use if for some LIST_MENU0 that the Range seems incorrect
|
||||
if (MenuLib.isListLine(line)) then -- and line.Type==LINE_TYPE.LIST_MENU1 and line.Min==0 and line.Max==244) then
|
||||
values = MenuLib.Get_List_Values(line.TextId)
|
||||
end
|
||||
|
||||
|
||||
if (values~=nil) then -- Inc/Dec based on a list of predefined Values Local to Script (values not contiguous),
|
||||
-- locate current value in values array
|
||||
-- Values are Zero normalized to the Start of the List (line.TextStart)
|
||||
for i = 1, #values do
|
||||
if ((values[i]-line.TextStart)==origVal) then
|
||||
skipIncrement = true
|
||||
if (inc==-1 and i > 1) then -- PREV
|
||||
line.Val = values[i-1]-line.TextStart
|
||||
elseif (inc==1 and i < #values) then -- NEXT
|
||||
line.Val = values[i+1]-line.TextStart
|
||||
end
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if not skipIncrement then
|
||||
-- Do it Sequentially
|
||||
line.Val = line.Val + inc
|
||||
|
||||
if line.Val > line.Max then
|
||||
line.Val = line.Max
|
||||
elseif line.Val < line.Min then
|
||||
line.Val = line.Min
|
||||
end
|
||||
end
|
||||
|
||||
if (origVal~=line.Val and MenuLib.isIncrementalValueUpdate(line)) then
|
||||
-- Update RX value on every change
|
||||
MenuLib.ChangePhase(PHASE.VALUE_CHANGING)
|
||||
end
|
||||
end
|
||||
|
||||
function MenuLib.Value_Default(line)
|
||||
local origVal = line.Val
|
||||
if (DEBUG_ON) then Log.LOG_write("%3.3f %s: DSM_Value_Default(%s)\n",
|
||||
MenuLib.getElapsedTime(), MenuLib.phase2String(DSM_Context.Phase), MenuLib.menuLine2String(line)) end
|
||||
|
||||
line.Val = line.Def
|
||||
if (origVal~=line.Val and MenuLib.isIncrementalValueUpdate(line)) then
|
||||
-- Update RX value on every change
|
||||
MenuLib.ChangePhase(PHASE.VALUE_CHANGING)
|
||||
end
|
||||
end
|
||||
|
||||
function MenuLib.Value_Write_Validate(line)
|
||||
if (DEBUG_ON) then Log.LOG_write("%3.3f %s: DSM_Value_Write_Validate(%s)\n",
|
||||
MenuLib.getElapsedTime(), MenuLib.phase2String(DSM_Context.Phase), MenuLib.menuLine2String(line)) end
|
||||
|
||||
MenuLib.ChangePhase(PHASE.VALUE_CHANGE_END) -- Update + Validate value in RX
|
||||
DSM_Context.EditLine = nil -- Exit Edit Mode (By clearing the line editing)
|
||||
end
|
||||
|
||||
function MenuLib.GotoMenu(menuId, lastSelectedLine)
|
||||
if (DEBUG_ON) then Log.LOG_write("%3.3f %s: DSM_GotoMenu(0x%X,LastSelectedLine=%d)\n",
|
||||
MenuLib.getElapsedTime(), MenuLib.phase2String(DSM_Context.Phase), menuId, lastSelectedLine) end
|
||||
|
||||
DSM_Context.Menu.MenuId = menuId
|
||||
DSM_Context.SelLine = lastSelectedLine
|
||||
-- Request to load the menu Again
|
||||
MenuLib.ChangePhase(PHASE.MENU_TITLE)
|
||||
end
|
||||
|
||||
function MenuLib.MoveSelectionLine(dir)
|
||||
local ctx = DSM_Context
|
||||
local menu = ctx.Menu
|
||||
local menuLines = ctx.MenuLines
|
||||
|
||||
if (dir == 1) then -- NEXT
|
||||
if ctx.SelLine <= MAX_MENU_LINES then
|
||||
local num = ctx.SelLine
|
||||
for i = ctx.SelLine + 1, MAX_MENU_LINES, 1 do
|
||||
if MenuLib.isSelectableLine(menuLines[i]) then
|
||||
ctx.SelLine = i
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
if num == ctx.SelLine then
|
||||
if menu.NextId ~= 0 then -- Next
|
||||
ctx.SelLine = NEXT_BUTTON
|
||||
elseif menu.PrevId ~= 0 then -- Prev
|
||||
ctx.SelLine = PREV_BUTTON
|
||||
end
|
||||
end
|
||||
elseif menu.PrevId ~= 0 then -- Prev
|
||||
ctx.SelLine = PREV_BUTTON
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
if (dir == -1) then -- PREV
|
||||
if ctx.SelLine == PREV_BUTTON and menu.NextId ~= 0 then
|
||||
ctx.SelLine = NEXT_BUTTON
|
||||
elseif ctx.SelLine > 0 then
|
||||
if ctx.SelLine > MAX_MENU_LINES then
|
||||
ctx.SelLine = NEXT_BUTTON
|
||||
end
|
||||
local num = ctx.SelLine
|
||||
for i = ctx.SelLine - 1, 0, -1 do
|
||||
if MenuLib.isSelectableLine(menuLines[i]) then
|
||||
ctx.SelLine = i
|
||||
break
|
||||
end
|
||||
end
|
||||
if num == ctx.SelLine then -- can't find previous selectable line, then SELECT Back
|
||||
if (menu.BackId ~= 0) then ctx.SelLine = BACK_BUTTON end
|
||||
end
|
||||
else
|
||||
if (menu.BackId ~= 0) then ctx.SelLine = BACK_BUTTON end -- Back
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
-- Clear each line of the menu
|
||||
function MenuLib.clearMenuLines()
|
||||
local ctx = DSM_Context
|
||||
for i = 0, MAX_MENU_LINES do -- clear menu
|
||||
ctx.MenuLines[i] = { MenuId = 0, lineNum = 0, Type = 0, Text = "", TextId = 0, ValId = 0, Min=0, Max=0, Def=0, TextStart=0, Val=nil }
|
||||
end
|
||||
end
|
||||
|
||||
-- Post processing needed for each menu
|
||||
function MenuLib.PostProcessMenu()
|
||||
local ctx = DSM_Context
|
||||
|
||||
if (ctx.Menu.Text==nil) then
|
||||
ctx.Menu.Text = MenuLib.Get_Text(ctx.Menu.TextId)
|
||||
MenuLib.MenuPostProcessing (ctx.Menu)
|
||||
end
|
||||
|
||||
--if (DEBUG_ON) then Log.LOG_write("SIM RESPONSE Menu: %s\n", MenuLib.menu2String(ctx.Menu)) end
|
||||
|
||||
for i = 0, MenuLib.MAX_MENU_LINES do -- clear menu
|
||||
local line = ctx.MenuLines[i]
|
||||
if (line.Type~=0) then
|
||||
line.MenuId = ctx.Menu.MenuId
|
||||
line.lineNum = i
|
||||
MenuLib.MenuLinePostProcessing(line) -- Do the same post processing as if they come from the RX
|
||||
--if (DEBUG_ON) then Log.LOG_write("SIM RESPONSE MenuLine: %s\n", MenuLib.menuLine2String(line)) end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
function MenuLib.GetFlightModeValue(line)
|
||||
local ret = line.Text.." "
|
||||
local val = line.Val
|
||||
|
||||
if (val==nil) then return ret.."--" end
|
||||
|
||||
-- Adjust the displayed value for Flight mode line as needed
|
||||
if (DSM_Context.RX.Id == RX.FC6250HX) then
|
||||
-- Helicopter Flights modes
|
||||
if (val==0) then ret = ret .. "1 / HOLD"
|
||||
elseif (val==1) then ret = ret .. "2 / Normal"
|
||||
elseif (val==2) then ret = ret .. "3 / Stunt 1"
|
||||
elseif (val==3) then ret = ret .. "4 / Stunt 2"
|
||||
elseif (val==4) then ret = ret .. "5 / Panic"
|
||||
else
|
||||
ret = ret .. " " .. (val + 1)
|
||||
end
|
||||
else
|
||||
-- No adjustment needed
|
||||
if (val==190) then
|
||||
ret=ret.."Err:Out of Range"
|
||||
else
|
||||
ret=ret..(val + 1)
|
||||
end
|
||||
|
||||
end
|
||||
return ret
|
||||
end
|
||||
|
||||
function MenuLib.Init()
|
||||
print("MenuLib.Init()")
|
||||
-- Phase Names
|
||||
PhaseText[PHASE.INIT] = "INIT"
|
||||
PhaseText[PHASE.RX_VERSION] = "RX_VERSION"
|
||||
PhaseText[PHASE.WAIT_CMD] = "WAIT_CMD"
|
||||
PhaseText[PHASE.MENU_TITLE] = "MENU_TITLE"
|
||||
PhaseText[PHASE.MENU_REQ_TX_INFO] = "MENU_REQ_TX_INFO"
|
||||
PhaseText[PHASE.MENU_LINES] = "MENU_LINES"
|
||||
PhaseText[PHASE.MENU_VALUES] = "MENU_VALUES"
|
||||
PhaseText[PHASE.VALUE_CHANGING] = "VALUE_CHANGING"
|
||||
PhaseText[PHASE.VALUE_CHANGING_WAIT] = "VALUE_EDITING"
|
||||
PhaseText[PHASE.VALUE_CHANGE_END] = "VALUE_CHANGE_END"
|
||||
PhaseText[PHASE.EXIT] = "EXIT"
|
||||
PhaseText[PHASE.EXIT_DONE] = "EXIT_DONE"
|
||||
|
||||
|
||||
-- Line Types
|
||||
LineTypeText[LINE_TYPE.MENU] = "M"
|
||||
LineTypeText[LINE_TYPE.LIST_MENU_NC] = "LM_nc"
|
||||
LineTypeText[LINE_TYPE.LIST_MENU] = "LM"
|
||||
LineTypeText[LINE_TYPE.LIST_MENU_TOG] = "LM_tog"
|
||||
LineTypeText[LINE_TYPE.LIST_MENU_NC2] = "LM_nc2"
|
||||
LineTypeText[LINE_TYPE.LIST_MENU_ORI] = "LM_ori"
|
||||
LineTypeText[LINE_TYPE.VALUE_NUM_I8_NC] = "V_nc"
|
||||
LineTypeText[LINE_TYPE.VALUE_PERCENT] = "V_%"
|
||||
LineTypeText[LINE_TYPE.VALUE_DEGREES] = "V_de"
|
||||
LineTypeText[LINE_TYPE.VALUE_NUM_I8] = "V_i8"
|
||||
LineTypeText[LINE_TYPE.VALUE_NUM_I16] = "V_i16"
|
||||
LineTypeText[LINE_TYPE.VALUE_NUM_SI16] = "V_s16"
|
||||
LineTypeText[LINE_TYPE.LT_EMPTY] = "Z"
|
||||
|
||||
DSM_Context.Phase = PHASE.RX_VERSION
|
||||
end
|
||||
|
||||
function MenuLib.clearAllText()
|
||||
local function clearTable(t)
|
||||
for i, v in ipairs(t) do t[i] = nil end
|
||||
end
|
||||
|
||||
clearTable(Text)
|
||||
clearTable(List_Text)
|
||||
clearTable(List_Text_Img)
|
||||
clearTable(List_Values)
|
||||
end
|
||||
|
||||
function MenuLib.LoadTextFromFile(fileName, mem)
|
||||
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
|
||||
|
||||
function MenuLib.INC_LoadTextFromFile(fileName, FileState)
|
||||
-----------------------
|
||||
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
|
||||
|
||||
local function GetTextInfoFromFile(pos)
|
||||
local dataFile = io.open(fileName, "r")
|
||||
io.seek(dataFile,pos)
|
||||
local buff = io.read(dataFile, 100)
|
||||
io.close(dataFile)
|
||||
|
||||
local line=""
|
||||
local index=""
|
||||
local type=""
|
||||
|
||||
local pipe=0
|
||||
local comment=0
|
||||
local newPos = pos
|
||||
|
||||
-- Parse the line:
|
||||
-- Format: TT|0x999|Text -- Comment
|
||||
for i=1,#buff do
|
||||
newPos=newPos+1
|
||||
local ch = string.sub(buff,i,i)
|
||||
|
||||
if (pipe < 2 and ch=="|") then pipe=pipe+1 -- Count pipes pos (Type | Index | .....)
|
||||
elseif (ch=="\r") then -- Ignore CR
|
||||
elseif (ch=="\n") then break -- LF, end of line
|
||||
elseif (ch=="-") then -- March comments
|
||||
comment=comment+1
|
||||
if (comment==2) then pipe=6 end -- Comment part of line
|
||||
else
|
||||
-- regular char
|
||||
comment=0
|
||||
if (pipe==0) then type=type..ch -- in TT (Type)
|
||||
elseif (pipe==1) then index=index..ch -- in Index
|
||||
elseif (pipe<6) then line=line..ch end -- in Text
|
||||
end -- Regular char
|
||||
end -- For
|
||||
|
||||
return type, index, rtrim(line), newPos
|
||||
end
|
||||
|
||||
-----------------------------------------------------------
|
||||
|
||||
if (FileState.state==nil) then -- Initial State
|
||||
FileState.state=1
|
||||
FileState.lineNo=0
|
||||
FileState.filePos=0
|
||||
end
|
||||
|
||||
if FileState.state==1 then
|
||||
for l=1,10 do -- do 10 lines at a time
|
||||
local type, sIndex, text
|
||||
local lineStart = FileState.filePos
|
||||
|
||||
type, sIndex, text, FileState.filePos = GetTextInfoFromFile(FileState.filePos)
|
||||
|
||||
--print(string.format("T=%s, I=%s, T=%s LS=%d, FP=%d",type,sIndex,text,lineStart, FileState.filePos))
|
||||
|
||||
if (lineStart==FileState.filePos) then -- EOF
|
||||
FileState.state=2 --EOF State
|
||||
return 1
|
||||
end
|
||||
FileState.lineNo = FileState.lineNo + 1
|
||||
|
||||
type = rtrim(type)
|
||||
|
||||
if (string.len(type) > 0 and string.len(sIndex) > 0) then
|
||||
local index = tonumber(sIndex)
|
||||
|
||||
if (index == nil) then
|
||||
assert(false, string.format("%s:%d: Invalid Hex num [%s]", fileName, FileState.lineNo, sIndex))
|
||||
elseif (type == "T") then
|
||||
Text[index] = text
|
||||
elseif (type == "LT") then
|
||||
List_Text[index] = text
|
||||
elseif (type == "LI") then
|
||||
List_Text_Img[index] = text
|
||||
elseif (type == "FM") then
|
||||
Flight_Mode[0] = text
|
||||
elseif (type == "RX") then
|
||||
RxName[index] = text
|
||||
else
|
||||
assert(false, string.format("%s:%d: Invalid Line Type [%s]", fileName, FileState.lineNo, type))
|
||||
end
|
||||
end
|
||||
end -- for
|
||||
end -- if
|
||||
|
||||
return 0
|
||||
end
|
||||
|
||||
|
||||
-- Export some Constants and Variables
|
||||
MenuLib.PHASE = PHASE
|
||||
MenuLib.LINE_TYPE = LINE_TYPE
|
||||
MenuLib.DISP_ATTR = DISP_ATTR
|
||||
MenuLib.RX = RX
|
||||
|
||||
MenuLib.MAX_MENU_LINES = MAX_MENU_LINES
|
||||
MenuLib.BACK_BUTTON = BACK_BUTTON
|
||||
MenuLib.NEXT_BUTTON = NEXT_BUTTON
|
||||
MenuLib.PREV_BUTTON = PREV_BUTTON
|
||||
|
||||
MenuLib.DSM_Context = DSM_Context
|
||||
|
||||
MenuLib.Text = Text
|
||||
MenuLib.List_Text = List_Text
|
||||
MenuLib.List_Text_Img = List_Text_Img
|
||||
MenuLib.List_Values = List_Values
|
||||
|
||||
MenuLib.LOG_open = Log.LOG_open
|
||||
MenuLib.LOG_write = Log.LOG_write
|
||||
MenuLib.LOG_Close = Log.LOG_close
|
||||
|
||||
|
||||
return MenuLib
|
||||
789
Lua_scripts/DSMLIB/DsmModelLib.lua
Normal file
@@ -0,0 +1,789 @@
|
||||
|
||||
local Log, DEBUG_ON = ...
|
||||
|
||||
local DATA_PATH = "/MODELS/DSMDATA" -- Path to store model settings files
|
||||
local TX_CHANNELS = 12
|
||||
|
||||
-- MODEL information from ETX/OTX
|
||||
local ModelLib = {}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
--Channel Types --
|
||||
local CH_TYPE = {
|
||||
NONE = 0x00,
|
||||
AIL = 0x01,
|
||||
ELE = 0x02,
|
||||
RUD = 0x04,
|
||||
|
||||
REVERSE = 0x20,
|
||||
THR = 0x40,
|
||||
SLAVE = 0x80,
|
||||
}
|
||||
|
||||
-- Seems like Reverse Mix is complement of the 3 bits
|
||||
local CH_MIX_TYPE = {
|
||||
MIX_NORM = 0x00, -- 0000
|
||||
MIX_AIL = 0x10, -- 0001 Taileron
|
||||
MIX_ELE = 0x20, -- 0010 For VTIAL and Delta-ELEVON
|
||||
MIX_RUD = 0x30, -- 0011 For VTIAL
|
||||
|
||||
MIX_RUD_REV = 0x40, -- 0100 For VTIAL
|
||||
MIX_ELE_REV = 0x50, -- 0101 For VTIAL and Delta-ELEVON A
|
||||
MIX_AIL_REV = 0x60, -- 0110 Taileron
|
||||
MIX_NORM_REV = 0x70 -- 0111
|
||||
}
|
||||
|
||||
local AIRCRAFT_TYPE = {
|
||||
PLANE = 0,
|
||||
HELI = 1,
|
||||
GLIDER = 2,
|
||||
DRONE = 3
|
||||
}
|
||||
local aircraft_type_text = {[0]="Plane","Heli","Glider","Drone"}
|
||||
|
||||
local WING_TYPE = {
|
||||
AIL_1 = 0, --1
|
||||
AIL_2 = 1, --2
|
||||
FLAPERON = 2, --2
|
||||
AIL_1_FLP_1 = 3, --2
|
||||
AIL_2_FLP_1 = 4, --3
|
||||
AIL_2_FLP_2 = 5, --4
|
||||
ELEVON_A = 6, --2
|
||||
ELEVON_B = 7 --2
|
||||
}
|
||||
|
||||
local wing_type_text = {[0]="Normal","Dual Ail","Flapperon", "Ail + Flp","Dual Ail + Flp","Dual Ail/Flp","Elevon A","Elevon B"}
|
||||
|
||||
local TAIL_TYPE = {
|
||||
RUD_1 = 0, -- 1
|
||||
RUD_1_ELEV_1 = 1, -- 2
|
||||
RUD_1_ELEV_2 = 2, -- 3
|
||||
RUD_2_ELEV_1 = 3, -- 3
|
||||
RUD_2_ELEV_2 = 4, -- 4
|
||||
VTAIL_A = 5, -- 2
|
||||
VTAIL_B = 6, -- 2
|
||||
TRAILERON_A = 7, -- 3
|
||||
TRAILERON_B = 8, -- 3
|
||||
TRAILERON_A_R2 = 9, -- 3
|
||||
TRAILERON_B_R2 = 10 -- 3
|
||||
}
|
||||
local tail_type_text = {[0]="Rud Only","Normal","Rud + Dual Ele","Dual Rud + Elv","Dual Rud/Ele",
|
||||
"VTail A","VTail B","Taileron A","Taileron B","Taileron A + 2x Rud","Taileron B + 2x Rud"}
|
||||
|
||||
local CH_MODE_TYPE = {
|
||||
NORMAL = 0,
|
||||
REVERSE = 1,
|
||||
USE_TX = 3
|
||||
}
|
||||
|
||||
local PORT = {
|
||||
PORT1 = 0,
|
||||
PORT2 = 1,
|
||||
PORT3 = 2,
|
||||
PORT4 = 3,
|
||||
PORT5 = 4,
|
||||
PORT6 = 5,
|
||||
PORT7 = 6,
|
||||
PORT8 = 7,
|
||||
PORT9 = 8,
|
||||
PORT10 = 9,
|
||||
PORT11 = 10,
|
||||
PORT12 = 11
|
||||
}
|
||||
|
||||
local MEMU_VAR = {
|
||||
AIRCRAFT_TYPE = 1001,
|
||||
WING_TYPE = 1002,
|
||||
TAIL_TYPE = 1003,
|
||||
|
||||
CH_BASE = 1010,
|
||||
CH_THR = 1010,
|
||||
|
||||
CH_L_AIL = 1011,
|
||||
CH_R_AIL = 1012,
|
||||
CH_L_FLP = 1013,
|
||||
CH_R_FLP = 1014,
|
||||
|
||||
CH_L_RUD = 1015,
|
||||
CH_R_RUD = 1016,
|
||||
CH_L_ELE = 1017,
|
||||
CH_R_ELE = 1018,
|
||||
|
||||
PORT_BASE = 1020,
|
||||
PORT1_MODE = 1020,
|
||||
PORT2_MODE = 1021,
|
||||
PORT3_MODE = 1022,
|
||||
PORT4_MODE = 1023,
|
||||
PORT5_MODE = 1024,
|
||||
PORT6_MODE = 1025,
|
||||
PORT7_MODE = 1026,
|
||||
PORT8_MODE = 1027,
|
||||
PORT9_MODE = 1028,
|
||||
PORT10_MODE = 1029,
|
||||
PORT11_MODE = 1030,
|
||||
PORT12_MODE = 1031,
|
||||
|
||||
DATA_END = 1040
|
||||
}
|
||||
|
||||
|
||||
-- MENU DATA Management
|
||||
local MENU_DATA = {} -- Store the variables used in the Menus.
|
||||
|
||||
|
||||
---- DSM_ChannelInfo ---------------------------------
|
||||
-- First byte describe Special Mixing (Vtail/Elevon = 0x20)
|
||||
--VTAIL
|
||||
--(0x00 0x06) CH_TYPE.ELE+CH_TYPE.RUD (0x02+0x04 = 0x06)
|
||||
--(0x20 0x86) CH_TYPE.ELE+CH_TYPE.RUD+CH_TYPE.SLAVE (0x02+0x04+0x80 = 0x86)
|
||||
|
||||
-- The 2nd byte describes the functionality of the port
|
||||
--
|
||||
-- Single Example: CH_TYPE.AIL (0x01) Aileron
|
||||
-- Reverse Example: CH_TYPE.AIL+CH_TYPE.REVERSE (0x01+0x20=0x21) Reverse Aileron
|
||||
-- Slave Example: CH_TYPE.AIL+CH_TYPE.SLAVE (0x01+0x80) -- 2nd servo Aileron
|
||||
|
||||
-- Elevon Example: CH_TYPE.AIL+CH_TYPE.ELE (0x01+0x02 = 0x03) -- Elevon
|
||||
-- Elevon Example: CH_TYPE.AIL+CH_TYPE.ELE+CH_TYPE.SLAVE (0x01+0x02+0x80 = 0x83) -- Slave Elevon
|
||||
|
||||
-- RudElv (VTail) Example: CH_TYPE.ELE+CH_TYPE.RUD (0x02+0x04 = 0x06) -- Rudevator
|
||||
-- RudElv (VTail) Example: CH_TYPE.ELE+CH_TYPE.RUD+CH_TYPE.SLAVE (0x02+0x04+0x80 = 0x86) -- Rudevator Slave
|
||||
|
||||
-- DEFAULT Simple Plane Port configuration (The Configuration tool will overrride this)
|
||||
MODEL.DSM_ChannelInfo= {[0]= -- Start array at position 0
|
||||
{[0]= CH_MIX_TYPE.MIX_NORM, CH_TYPE.THR}, -- Ch1 Thr (0x40)
|
||||
{[0]= CH_MIX_TYPE.MIX_NORM, CH_TYPE.AIL}, -- Ch2 Ail (0x01)
|
||||
{[0]= CH_MIX_TYPE.MIX_NORM, CH_TYPE.ELE}, -- Ch2 ElE (0x02)
|
||||
{[0]= CH_MIX_TYPE.MIX_NORM, CH_TYPE.RUD}, -- Ch4 Rud (0x04)
|
||||
{[0]= CH_MIX_TYPE.MIX_NORM, CH_TYPE.NONE}, -- Ch5 Gear (0x00)
|
||||
{[0]= CH_MIX_TYPE.MIX_NORM, CH_TYPE.NONE}, -- Ch6 Aux1 (0x00)
|
||||
{[0]= CH_MIX_TYPE.MIX_NORM, CH_TYPE.NONE}, -- Ch7 Aux2 (0x00)
|
||||
{[0]= CH_MIX_TYPE.MIX_NORM, CH_TYPE.NONE}, -- Ch8 Aux3 (0x00)
|
||||
{[0]= CH_MIX_TYPE.MIX_NORM, CH_TYPE.NONE}, -- Ch9 Aux4 (0x00)
|
||||
{[0]= CH_MIX_TYPE.MIX_NORM, CH_TYPE.NONE}, -- Ch10 Aux5 (0x00)
|
||||
{[0]= CH_MIX_TYPE.MIX_NORM, CH_TYPE.NONE}, -- Ch11 Aux6 (0x00)
|
||||
{[0]= CH_MIX_TYPE.MIX_NORM, CH_TYPE.NONE} -- Ch12 Aux7 (0x00)
|
||||
}
|
||||
|
||||
function ModelLib.printChannelSummary(a,w,t)
|
||||
-- Summary
|
||||
print("CHANNEL INFORMATION")
|
||||
print("Aircraft:".. (aircraft_type_text[MENU_DATA[MEMU_VAR.AIRCRAFT_TYPE]] or "--"))
|
||||
print("Wing Type:".. (wing_type_text[MENU_DATA[MEMU_VAR.WING_TYPE]] or "--"))
|
||||
print("Tail Type:".. (tail_type_text[MENU_DATA[MEMU_VAR.TAIL_TYPE]] or "--"))
|
||||
print("Thr:".. (MODEL.PORT_TEXT[(MENU_DATA[MEMU_VAR.CH_THR] or 30)] or "--")) -- use fake ch30 for non existing channels
|
||||
print("LAil:".. (MODEL.PORT_TEXT[(MENU_DATA[MEMU_VAR.CH_L_AIL] or 30)] or "--"))
|
||||
print("RAil:".. (MODEL.PORT_TEXT[(MENU_DATA[MEMU_VAR.CH_R_AIL] or 30)] or "--"))
|
||||
print("LFlp:".. (MODEL.PORT_TEXT[(MENU_DATA[MEMU_VAR.CH_L_FLP] or 30)] or "--"))
|
||||
print("RFlp:".. (MODEL.PORT_TEXT[(MENU_DATA[MEMU_VAR.CH_R_FLP] or 30)] or "--"))
|
||||
print("LEle:".. (MODEL.PORT_TEXT[(MENU_DATA[MEMU_VAR.CH_L_ELE] or 30)] or "--"))
|
||||
print("REle:".. (MODEL.PORT_TEXT[(MENU_DATA[MEMU_VAR.CH_R_ELE] or 30)] or "--"))
|
||||
print("LRud:".. (MODEL.PORT_TEXT[(MENU_DATA[MEMU_VAR.CH_L_RUD] or 30)] or "--"))
|
||||
print("RRud:".. (MODEL.PORT_TEXT[(MENU_DATA[MEMU_VAR.CH_R_RUD] or 30)] or "--"))
|
||||
end
|
||||
|
||||
function ModelLib.printServoReverseInfo()
|
||||
print("SERVO Normal/Reverse INFORMATION")
|
||||
for i=0, TX_CHANNELS-1 do
|
||||
local s="--"
|
||||
if (MENU_DATA[MEMU_VAR.PORT1_MODE+i] or 0) == 0 then s="NORMAL" else s="REVERSE" end
|
||||
print(string.format("Port%d: %s", i+1, s))
|
||||
end
|
||||
end
|
||||
|
||||
function ModelLib.channelType2String(byte1, byte2)
|
||||
local s = ""
|
||||
|
||||
if (byte2==0) then return s end;
|
||||
|
||||
if (bit32.band(byte2,CH_TYPE.AIL)>0) then s=s.."Ail" end
|
||||
if (bit32.band(byte2,CH_TYPE.ELE)>0) then s=s.."Ele" end
|
||||
if (bit32.band(byte2,CH_TYPE.RUD)>0) then s=s.."Rud" end
|
||||
if (bit32.band(byte2,CH_TYPE.THR)>0) then s=s.."Thr" end
|
||||
|
||||
if (bit32.band(byte2,CH_TYPE.REVERSE)>0) then s=s.."-" end
|
||||
|
||||
if (bit32.band(byte2,CH_TYPE.SLAVE)>0) then s=s.." Slv" end
|
||||
|
||||
if (byte1==CH_MIX_TYPE.MIX_NORM) then s=s.." "
|
||||
elseif (byte1==CH_MIX_TYPE.MIX_AIL) then s=s.." M_Ail"
|
||||
elseif (byte1==CH_MIX_TYPE.MIX_ELE) then s=s.." M_Ele"
|
||||
elseif (byte1==CH_MIX_TYPE.MIX_RUD) then s=s.." M_Rud"
|
||||
elseif (byte1==CH_MIX_TYPE.MIX_RUD_REV) then s=s.." M_Rud-"
|
||||
elseif (byte1==CH_MIX_TYPE.MIX_ELE_REV) then s=s.." M_Ele-"
|
||||
elseif (byte1==CH_MIX_TYPE.MIX_AIL_REV) then s=s.." M_Ail-"
|
||||
elseif (byte1==CH_MIX_TYPE.MIX_NORM_REV) then s=s.." M-"
|
||||
end
|
||||
|
||||
return s;
|
||||
end
|
||||
|
||||
|
||||
-------------------------------------------------------------------------------------------------
|
||||
-- Read the model information from OTX/ETX
|
||||
|
||||
local function getModuleChannelOrder(num)
|
||||
--Determine fist 4 channels order
|
||||
local channel_names={}
|
||||
local stick_names = {[0]= "R", "E", "T", "A" }
|
||||
local ch_order=num
|
||||
if (ch_order == -1) then
|
||||
channel_names[0] = stick_names[3]
|
||||
channel_names[1] = stick_names[1]
|
||||
channel_names[2] = stick_names[2]
|
||||
channel_names[3] = stick_names[0]
|
||||
else
|
||||
channel_names[bit32.band(ch_order,3)] = stick_names[3]
|
||||
ch_order = math.floor(ch_order/4)
|
||||
channel_names[bit32.band(ch_order,3)] = stick_names[1]
|
||||
ch_order = math.floor(ch_order/4)
|
||||
channel_names[bit32.band(ch_order,3)] = stick_names[2]
|
||||
ch_order = math.floor(ch_order/4)
|
||||
channel_names[bit32.band(ch_order,3)] = stick_names[0]
|
||||
end
|
||||
|
||||
local s = ""
|
||||
for i=0,3 do
|
||||
s=s..channel_names[i]
|
||||
end
|
||||
return s
|
||||
end
|
||||
|
||||
function ModelLib.ReadTxModelData()
|
||||
local TRANSLATE_AETR_TO_TAER=false
|
||||
local table = model.getInfo() -- Get the model name
|
||||
MODEL.modelName = table.name
|
||||
|
||||
local module = model.getModule(0) -- Internal
|
||||
if (module==nil or module.Type~=6) then module = model.getModule(1) end -- External
|
||||
if (module~=nil) then
|
||||
if (module.Type==6 ) then -- MULTI-MODULE
|
||||
local chOrder = module.channelsOrder
|
||||
local s = getModuleChannelOrder(chOrder)
|
||||
Log.LOG_write("MultiChannel Ch Order: [%s] %s\n",chOrder,s)
|
||||
|
||||
if (s=="AETR") then TRANSLATE_AETR_TO_TAER=true
|
||||
else TRANSLATE_AETR_TO_TAER=false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Log.LOG_write("MODEL NAME = %s\n",MODEL.modelName)
|
||||
|
||||
-- Read Ch1 to Ch10
|
||||
local i= 0
|
||||
for i = 0, TX_CHANNELS-1 do
|
||||
local ch = model.getOutput(i) -- Zero base
|
||||
if (ch~=nil) then
|
||||
MODEL.modelOutputChannel[i] = ch
|
||||
if (string.len(ch.name)==0) then
|
||||
ch.formatCh = string.format("TX:Ch%i",i+1)
|
||||
else
|
||||
ch.formatCh = string.format("TX:Ch%i/%s",i+1,ch.name or "--")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Translate AETR to TAER
|
||||
-- TODO: Check if there is a way to know how to the TX is configured, since if it is
|
||||
-- already TAER, is not needed
|
||||
|
||||
if (TRANSLATE_AETR_TO_TAER) then
|
||||
Log.LOG_write("Applying AETR -> TAER translation\n")
|
||||
local ail = MODEL.modelOutputChannel[0]
|
||||
local elv = MODEL.modelOutputChannel[1]
|
||||
local thr = MODEL.modelOutputChannel[2]
|
||||
|
||||
MODEL.modelOutputChannel[0] = thr
|
||||
MODEL.modelOutputChannel[1] = ail
|
||||
MODEL.modelOutputChannel[2] = elv
|
||||
end
|
||||
|
||||
-- Create the Port Text to be used
|
||||
Log.LOG_write("Ports/Channels:\n")
|
||||
for i = 0, TX_CHANNELS-1 do
|
||||
local ch = MODEL.modelOutputChannel[i]
|
||||
if (ch~=nil) then
|
||||
MODEL.TX_CH_TEXT[i] = ch.formatCh
|
||||
MODEL.PORT_TEXT[i] = string.format("P%i (%s) ",i+1,MODEL.TX_CH_TEXT[i])
|
||||
|
||||
Log.LOG_write("Port%d %s [%d,%d] Rev=%d, Off=%d, ppmC=%d, syn=%d\n",i+1,MODEL.TX_CH_TEXT[i],math.floor(ch.min/10),math.floor(ch.max/10), ch.revert, ch.offset, ch.ppmCenter, ch.symetrical)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
----------------------- FILE MANAGEMENT ---------------------------------------------
|
||||
-- Create a fairly unique name for a model..combination of name and a hash
|
||||
-- TODO: Check with ETX why we can't get the filename used to store the model info
|
||||
-- Improvement request??
|
||||
|
||||
function ModelLib.hashName(mName)
|
||||
local c=10000;
|
||||
|
||||
local prefix = string.gsub(mName,"%.","_") -- Change any "." to "_"
|
||||
prefix = string.gsub(prefix,"% ","_") -- Change any space to "_"
|
||||
prefix = string.sub(prefix,1,5) -- Take the first 5 characters
|
||||
|
||||
-- Simple Hash of the Model Name adding each character
|
||||
for i = 1, #mName do
|
||||
local ch = string.byte(mName,i,i)
|
||||
c=c+ch
|
||||
end
|
||||
|
||||
return (prefix .. c) -- Return Prefix + Hash
|
||||
end
|
||||
|
||||
-- Load Menu Data from a file
|
||||
function ModelLib.ST_LoadFileData()
|
||||
local fname = ModelLib.hashName(MODEL.modelName)..".txt"
|
||||
|
||||
-- Clear Menu Data
|
||||
for i = 0, MEMU_VAR.DATA_END do
|
||||
MENU_DATA[i]=nil
|
||||
end
|
||||
|
||||
print("Loading File:"..fname)
|
||||
|
||||
local dataFile = io.open(DATA_PATH .. "/".. fname, "r") -- read File
|
||||
-- cannot read file???
|
||||
if (dataFile==nil) then return 0 end
|
||||
|
||||
local line = io.read(dataFile, 5000)
|
||||
io.close(dataFile)
|
||||
|
||||
if #line == 0 then return 0 end -- No data??
|
||||
|
||||
-- Process the input, each line is "Var_Id : Value" format
|
||||
-- Store it into MANU_DATA
|
||||
local i=0
|
||||
for k, v in string.gmatch(line, "(%d+):(%d+)") do
|
||||
--print(string.format("Read MENU_DATA[%d]:[%d]",k, v))
|
||||
MENU_DATA[k+0]=v+0 -- do aritmentic to convert string to number
|
||||
i=i+1
|
||||
end
|
||||
|
||||
local currAircraftType = MENU_DATA[MEMU_VAR.AIRCRAFT_TYPE]
|
||||
local currWingType = MENU_DATA[MEMU_VAR.WING_TYPE]
|
||||
local currTailType = MENU_DATA[MEMU_VAR.TAIL_TYPE]
|
||||
|
||||
print("Validation")
|
||||
print(string.format("AIRCRAFT_TYPE(%d)=%s", MEMU_VAR.AIRCRAFT_TYPE,aircraft_type_text[currAircraftType]))
|
||||
print(string.format("WING_TYPE(%d)=%s", MEMU_VAR.WING_TYPE, wing_type_text[currWingType]))
|
||||
print(string.format("TAIL_TYPE(%d)=%s", MEMU_VAR.TAIL_TYPE, tail_type_text[currTailType]))
|
||||
|
||||
ModelLib.printChannelSummary()
|
||||
ModelLib.printServoReverseInfo()
|
||||
|
||||
-- Return 0 if no lines processed, 1 otherwise
|
||||
if (i > 0) then return 1 else return 0 end
|
||||
end
|
||||
|
||||
-- Saves MENU_DATA to a file
|
||||
function ModelLib.ST_SaveFileData()
|
||||
local fname = ModelLib.hashName(MODEL.modelName)..".txt"
|
||||
|
||||
print("Saving File:"..fname)
|
||||
local dataFile = assert(io.open(DATA_PATH .. "/" .. fname, "w"),"Please create "..DATA_PATH.." folder") -- write File
|
||||
|
||||
-- Foreach MENU_DATA with a value write Var_Id:Value into file
|
||||
for i = 0, MEMU_VAR.DATA_END do
|
||||
if (MENU_DATA[i]~=nil) then
|
||||
--print(string.format("Write MENU_DATA[%s] : %s",i,MENU_DATA[i]))
|
||||
io.write(dataFile,string.format("%s:%s\n",i,MENU_DATA[i]))
|
||||
end
|
||||
end
|
||||
io.close(dataFile)
|
||||
end
|
||||
|
||||
-- This Creates the Servo Settings that will be used to pass to
|
||||
-- Forward programming
|
||||
function ModelLib.CreateDSMPortChannelInfo()
|
||||
local function ApplyWingMixA(b2)
|
||||
-- ELEVON
|
||||
if (b2==CH_TYPE.AIL+CH_TYPE.ELE) then return CH_MIX_TYPE.MIX_ELE end; -- 0x03
|
||||
if (b2==CH_TYPE.AIL+CH_TYPE.ELE+CH_TYPE.SLAVE) then return CH_MIX_TYPE.MIX_NORM end; -- 0x83
|
||||
end
|
||||
|
||||
local function ApplyWingMixB(b2)
|
||||
-- ELEVON
|
||||
if (b2==CH_TYPE.AIL+CH_TYPE.ELE) then return CH_MIX_TYPE.MIX_NORM end; -- 0x03
|
||||
if (b2==CH_TYPE.AIL+CH_TYPE.ELE+CH_TYPE.SLAVE) then return CH_MIX_TYPE.MIX_ELE end; -- 0x83
|
||||
end
|
||||
|
||||
local function ApplyTailMixA(b2)
|
||||
-- VTAIL
|
||||
-- Default normal/reverse behaviour
|
||||
if (b2==CH_TYPE.RUD+CH_TYPE.ELE) then return CH_MIX_TYPE.MIX_NORM end; -- 0x06
|
||||
if (b2==CH_TYPE.RUD+CH_TYPE.ELE+CH_TYPE.SLAVE) then return CH_MIX_TYPE.MIX_ELE end; -- 0x86
|
||||
|
||||
--TAILERON
|
||||
-- Default normal/reverse behaviour
|
||||
if (b2==CH_TYPE.AIL+CH_TYPE.ELE) then return CH_MIX_TYPE.MIX_NORM end; -- 0x03
|
||||
if (b2==CH_TYPE.AIL+CH_TYPE.ELE+CH_TYPE.SLAVE) then return CH_MIX_TYPE.MIX_AIL end; -- 0x83
|
||||
end
|
||||
|
||||
local function ApplyTailMixB(b2)
|
||||
-- VTAIL
|
||||
-- Default normal/reverse behaviour
|
||||
if (b2==CH_TYPE.RUD+CH_TYPE.ELE) then return CH_MIX_TYPE.MIX_NORM end; -- 0x06
|
||||
if (b2==CH_TYPE.RUD+CH_TYPE.ELE+CH_TYPE.SLAVE) then return CH_MIX_TYPE.MIX_RUD end; -- 0x86
|
||||
|
||||
--TAILERON
|
||||
if (b2==CH_TYPE.AIL+CH_TYPE.ELE) then return CH_MIX_TYPE.MIX_AIL end; -- 0x03
|
||||
if (b2==CH_TYPE.AIL+CH_TYPE.ELE+CH_TYPE.SLAVE) then return CH_MIX_TYPE.MIX_NORM end; -- 0x83
|
||||
end
|
||||
|
||||
local function reverseMix(b)
|
||||
if (b==CH_MIX_TYPE.MIX_NORM) then return CH_MIX_TYPE.MIX_NORM_REV end;
|
||||
if (b==CH_MIX_TYPE.MIX_AIL) then return CH_MIX_TYPE.MIX_AIL_REV end;
|
||||
if (b==CH_MIX_TYPE.MIX_ELE) then return CH_MIX_TYPE.MIX_ELE_REV end;
|
||||
if (b==CH_MIX_TYPE.MIX_RUD) then return CH_MIX_TYPE.MIX_RUD_REV end;
|
||||
return b
|
||||
end
|
||||
|
||||
|
||||
|
||||
local DSM_ChannelInfo = MODEL.DSM_ChannelInfo
|
||||
|
||||
for i=0, TX_CHANNELS-1 do
|
||||
DSM_ChannelInfo[i] = {[0]= CH_MIX_TYPE.MIX_NORM, CH_TYPE.NONE} -- Initialize with no special function
|
||||
end
|
||||
|
||||
local aircraftType = MENU_DATA[MEMU_VAR.AIRCRAFT_TYPE]
|
||||
local wingType = MENU_DATA[MEMU_VAR.WING_TYPE]
|
||||
local tailType = MENU_DATA[MEMU_VAR.TAIL_TYPE]
|
||||
|
||||
local thrCh = MENU_DATA[MEMU_VAR.CH_THR]
|
||||
local lAilCh = MENU_DATA[MEMU_VAR.CH_L_AIL]
|
||||
local rAilCh = MENU_DATA[MEMU_VAR.CH_R_AIL]
|
||||
local lflapCh = MENU_DATA[MEMU_VAR.CH_L_FLP]
|
||||
local rflapCh = MENU_DATA[MEMU_VAR.CH_R_FLP]
|
||||
|
||||
local lElevCh = MENU_DATA[MEMU_VAR.CH_L_ELE]
|
||||
local rElevCh = MENU_DATA[MEMU_VAR.CH_R_ELE]
|
||||
|
||||
local lRudCh = MENU_DATA[MEMU_VAR.CH_L_RUD]
|
||||
local rRudCh = MENU_DATA[MEMU_VAR.CH_R_RUD]
|
||||
|
||||
-- Channels in menu vars are Zero base, Channel info is 1 based
|
||||
|
||||
-- THR
|
||||
if (thrCh~=nil and thrCh < 10) then DSM_ChannelInfo[thrCh][1]= CH_TYPE.THR end
|
||||
|
||||
-- AIL (Left and Right)
|
||||
if (lAilCh~=nil) then DSM_ChannelInfo[lAilCh][1] = CH_TYPE.AIL end
|
||||
if (rAilCh~=nil) then DSM_ChannelInfo[rAilCh][1] = CH_TYPE.AIL+CH_TYPE.SLAVE end
|
||||
-- ELE (Left and Right)
|
||||
if (lElevCh~=nil) then DSM_ChannelInfo[lElevCh][1] = CH_TYPE.ELE end
|
||||
if (rElevCh~=nil) then DSM_ChannelInfo[rElevCh][1] = CH_TYPE.ELE+CH_TYPE.SLAVE end
|
||||
-- RUD (Left and Right)
|
||||
if (lRudCh~=nil) then DSM_ChannelInfo[lRudCh][1] = CH_TYPE.RUD end
|
||||
if (rRudCh~=nil) then DSM_ChannelInfo[rRudCh][1] = CH_TYPE.RUD+CH_TYPE.SLAVE end
|
||||
|
||||
-- VTAIL: RUD + ELE
|
||||
if (tailType==TAIL_TYPE.VTAIL_A or tailType==TAIL_TYPE.VTAIL_B) then
|
||||
DSM_ChannelInfo[lElevCh][1] = CH_TYPE.RUD+CH_TYPE.ELE
|
||||
DSM_ChannelInfo[rElevCh][1] = CH_TYPE.RUD+CH_TYPE.ELE+CH_TYPE.SLAVE
|
||||
end
|
||||
|
||||
-- TAILERRON: 2-ELE + AIL
|
||||
if (tailType==TAIL_TYPE.TRAILERON_A or tailType==TAIL_TYPE.TRAILERON_A_R2 or
|
||||
tailType==TAIL_TYPE.TRAILERON_B or tailType==TAIL_TYPE.TRAILERON_B_R2) then
|
||||
DSM_ChannelInfo[lElevCh][1] = CH_TYPE.AIL+CH_TYPE.ELE
|
||||
DSM_ChannelInfo[rElevCh][1] = CH_TYPE.AIL+CH_TYPE.ELE+CH_TYPE.SLAVE
|
||||
end
|
||||
|
||||
---- ELEVON : AIL + ELE
|
||||
if (wingType==WING_TYPE.ELEVON_A or wingType==WING_TYPE.ELEVON_B) then
|
||||
DSM_ChannelInfo[lAilCh][1] = CH_TYPE.AIL+CH_TYPE.ELE
|
||||
DSM_ChannelInfo[rAilCh][1] = CH_TYPE.AIL+CH_TYPE.ELE+CH_TYPE.SLAVE
|
||||
end
|
||||
|
||||
------MIXES ---------
|
||||
|
||||
-- TAIL Mixes (Elevator and VTail)
|
||||
if (tailType==TAIL_TYPE.VTAIL_A or tailType==TAIL_TYPE.TRAILERON_A or tailType==TAIL_TYPE.TRAILERON_A_R2) then
|
||||
DSM_ChannelInfo[lElevCh][0] = ApplyTailMixA(DSM_ChannelInfo[lElevCh][1])
|
||||
DSM_ChannelInfo[rElevCh][0] = ApplyTailMixA(DSM_ChannelInfo[rElevCh][1])
|
||||
elseif (tailType==TAIL_TYPE.VTAIL_B or tailType==TAIL_TYPE.TRAILERON_B or tailType==TAIL_TYPE.TRAILERON_B_R2) then
|
||||
DSM_ChannelInfo[lElevCh][0] = ApplyTailMixA(DSM_ChannelInfo[lElevCh][1])
|
||||
DSM_ChannelInfo[rElevCh][0] = ApplyTailMixA(DSM_ChannelInfo[rElevCh][1])
|
||||
end
|
||||
|
||||
---- Wing Mixes
|
||||
if (wingType==WING_TYPE.ELEVON_A) then
|
||||
DSM_ChannelInfo[lAilCh][0] = ApplyWingMixA(DSM_ChannelInfo[lAilCh][1])
|
||||
DSM_ChannelInfo[rAilCh][0] = ApplyWingMixA(DSM_ChannelInfo[rAilCh][1])
|
||||
elseif (wingType==WING_TYPE.ELEVON_B) then
|
||||
DSM_ChannelInfo[lAilCh][0] = ApplyWingMixB(DSM_ChannelInfo[lAilCh][1])
|
||||
DSM_ChannelInfo[rAilCh][0] = ApplyWingMixB(DSM_ChannelInfo[rAilCh][1])
|
||||
end
|
||||
|
||||
-- Apply Gyro Reverse as needed for each channel as long as it is used
|
||||
for i=0, TX_CHANNELS-1 do
|
||||
if (MENU_DATA[MEMU_VAR.PORT_BASE+i]==CH_MODE_TYPE.REVERSE and DSM_ChannelInfo[i][1]>0) then
|
||||
DSM_ChannelInfo[i][0]=reverseMix(DSM_ChannelInfo[i][0])
|
||||
DSM_ChannelInfo[i][1]=DSM_ChannelInfo[i][1]+CH_TYPE.REVERSE
|
||||
end
|
||||
end
|
||||
|
||||
-- Show how it looks
|
||||
for i=0, 9 do
|
||||
local b1,b2 = DSM_ChannelInfo[i][0], DSM_ChannelInfo[i][1]
|
||||
print(string.format("%s (%02X %02X) %s", MODEL.PORT_TEXT[i],
|
||||
b1, b2, ModelLib.channelType2String(b1,b2)))
|
||||
end
|
||||
|
||||
MODEL.AirWingTailDesc = string.format("Aircraft(%s) Wing(%s) Tail(%s)",aircraft_type_text[aircraftType],wing_type_text[wingType],tail_type_text[tailType])
|
||||
end
|
||||
|
||||
function ModelLib.ST_PlaneWingInit(wingType)
|
||||
print("Change Plane WingType:"..wing_type_text[wingType])
|
||||
|
||||
MENU_DATA[MEMU_VAR.WING_TYPE] = wingType
|
||||
|
||||
-- Clear all Wing Data
|
||||
MENU_DATA[MEMU_VAR.CH_L_AIL] = nil
|
||||
MENU_DATA[MEMU_VAR.CH_R_AIL] = nil
|
||||
MENU_DATA[MEMU_VAR.CH_L_FLP] = nil
|
||||
MENU_DATA[MEMU_VAR.CH_R_FLP] = nil
|
||||
|
||||
MENU_DATA[MEMU_VAR.CH_THR] = PORT.PORT1
|
||||
|
||||
-- Default Channel Assisgments for each Wing type
|
||||
|
||||
if (wingType==WING_TYPE.AIL_1) then
|
||||
MENU_DATA[MEMU_VAR.CH_L_AIL] = PORT.PORT2
|
||||
elseif (wingType==WING_TYPE.AIL_2) then
|
||||
MENU_DATA[MEMU_VAR.CH_L_AIL] = PORT.PORT6
|
||||
MENU_DATA[MEMU_VAR.CH_R_AIL] = PORT.PORT2
|
||||
elseif (wingType==WING_TYPE.FLAPERON) then
|
||||
MENU_DATA[MEMU_VAR.CH_L_AIL] = PORT.PORT6
|
||||
MENU_DATA[MEMU_VAR.CH_R_AIL] = PORT.PORT2
|
||||
elseif (wingType==WING_TYPE.AIL_1_FLP_1) then
|
||||
MENU_DATA[MEMU_VAR.CH_L_AIL] = PORT.PORT2
|
||||
MENU_DATA[MEMU_VAR.CH_L_FLP] = PORT.PORT6
|
||||
elseif (wingType==WING_TYPE.AIL_2_FLP_1) then
|
||||
MENU_DATA[MEMU_VAR.CH_L_AIL] = PORT.PORT6
|
||||
MENU_DATA[MEMU_VAR.CH_R_AIL] = PORT.PORT2
|
||||
MENU_DATA[MEMU_VAR.CH_L_FLP] = PORT.PORT5
|
||||
elseif (wingType==WING_TYPE.AIL_2_FLP_2) then
|
||||
MENU_DATA[MEMU_VAR.CH_L_AIL] = PORT.PORT6
|
||||
MENU_DATA[MEMU_VAR.CH_R_AIL] = PORT.PORT2
|
||||
MENU_DATA[MEMU_VAR.CH_R_FLP] = PORT.PORT5
|
||||
MENU_DATA[MEMU_VAR.CH_L_FLP] = PORT.PORT7
|
||||
elseif (wingType==WING_TYPE.ELEVON_A) then
|
||||
MENU_DATA[MEMU_VAR.CH_L_AIL] = PORT.PORT2
|
||||
MENU_DATA[MEMU_VAR.CH_R_AIL] = PORT.PORT3
|
||||
elseif (wingType==WING_TYPE.ELEVON_B) then
|
||||
MENU_DATA[MEMU_VAR.CH_L_AIL] = PORT.PORT3
|
||||
MENU_DATA[MEMU_VAR.CH_R_AIL] = PORT.PORT2
|
||||
else -- Assume normal
|
||||
print("ERROR: Invalid Wing Type")
|
||||
end
|
||||
|
||||
|
||||
ModelLib.printChannelSummary()
|
||||
end
|
||||
|
||||
function ModelLib.ST_PlaneTailInit(tailType)
|
||||
if (MENU_DATA[MEMU_VAR.WING_TYPE]==WING_TYPE.ELEVON_A or
|
||||
MENU_DATA[MEMU_VAR.WING_TYPE]==WING_TYPE.ELEVON_B) then
|
||||
tailType = TAIL_TYPE.RUD_1 -- Delta only have ruder
|
||||
end
|
||||
|
||||
print("Change Plane Tail Type:"..tail_type_text[tailType])
|
||||
|
||||
-- Clear all data for Tail
|
||||
MENU_DATA[MEMU_VAR.TAIL_TYPE] = tailType
|
||||
MENU_DATA[MEMU_VAR.CH_L_ELE] = nil
|
||||
MENU_DATA[MEMU_VAR.CH_R_ELE] = nil
|
||||
MENU_DATA[MEMU_VAR.CH_L_RUD] = nil
|
||||
MENU_DATA[MEMU_VAR.CH_R_RUD] = nil
|
||||
|
||||
-- Setup Channels for different Tail types
|
||||
if (tailType == TAIL_TYPE.RUD_1) then
|
||||
MENU_DATA[MEMU_VAR.CH_L_RUD] = PORT.PORT4
|
||||
elseif (tailType == TAIL_TYPE.RUD_1_ELEV_1) then
|
||||
MENU_DATA[MEMU_VAR.CH_L_ELE] = PORT.PORT3
|
||||
MENU_DATA[MEMU_VAR.CH_L_RUD] = PORT.PORT4
|
||||
elseif (tailType == TAIL_TYPE.RUD_1_ELEV_2) then
|
||||
MENU_DATA[MEMU_VAR.CH_L_ELE] = PORT.PORT5
|
||||
MENU_DATA[MEMU_VAR.CH_R_ELE] = PORT.PORT3
|
||||
MENU_DATA[MEMU_VAR.CH_L_RUD] = PORT.PORT4
|
||||
elseif (tailType == TAIL_TYPE.RUD_2_ELEV_1) then
|
||||
MENU_DATA[MEMU_VAR.CH_L_ELE] = PORT.PORT3
|
||||
MENU_DATA[MEMU_VAR.CH_L_RUD] = PORT.PORT4
|
||||
MENU_DATA[MEMU_VAR.CH_R_RUD] = PORT.PORT5
|
||||
elseif (tailType == TAIL_TYPE.RUD_2_ELEV_2) then
|
||||
MENU_DATA[MEMU_VAR.CH_L_ELE] = PORT.PORT5
|
||||
MENU_DATA[MEMU_VAR.CH_R_ELE] = PORT.PORT3
|
||||
MENU_DATA[MEMU_VAR.CH_L_RUD] = PORT.PORT4
|
||||
MENU_DATA[MEMU_VAR.CH_R_RUD] = PORT.PORT6
|
||||
elseif (tailType == TAIL_TYPE.VTAIL_A or tailType == TAIL_TYPE.VTAIL_B) then
|
||||
MENU_DATA[MEMU_VAR.CH_L_ELE] = PORT.PORT4
|
||||
MENU_DATA[MEMU_VAR.CH_R_ELE] = PORT.PORT3
|
||||
elseif (tailType == TAIL_TYPE.TRAILERON_A or tailType==TAIL_TYPE.TRAILERON_A_R2 or
|
||||
tailType == TAIL_TYPE.TRAILERON_B or tailType==TAIL_TYPE.TRAILERON_B_R2) then
|
||||
MENU_DATA[MEMU_VAR.CH_L_RUD] = PORT.PORT4
|
||||
MENU_DATA[MEMU_VAR.CH_L_ELE] = PORT.PORT5
|
||||
MENU_DATA[MEMU_VAR.CH_R_ELE] = PORT.PORT3
|
||||
else -- Assume Normal
|
||||
print("ERROR:invalid Tail Type")
|
||||
end
|
||||
|
||||
if (tailType == TAIL_TYPE.TRAILERON_A_R2 or tailType==TAIL_TYPE.TRAILERON_B_R2) then
|
||||
MENU_DATA[MEMU_VAR.CH_R_RUD] = PORT.PORT7
|
||||
end
|
||||
|
||||
ModelLib.printChannelSummary()
|
||||
end
|
||||
|
||||
function ModelLib.ST_GliderWingInit(wingType)
|
||||
print("Change Glider WingType:"..wing_type_text[wingType])
|
||||
|
||||
MENU_DATA[MEMU_VAR.WING_TYPE] = wingType
|
||||
|
||||
-- Clear all Wing Data
|
||||
MENU_DATA[MEMU_VAR.CH_L_AIL] = nil
|
||||
MENU_DATA[MEMU_VAR.CH_R_AIL] = nil
|
||||
MENU_DATA[MEMU_VAR.CH_L_FLP] = nil
|
||||
MENU_DATA[MEMU_VAR.CH_R_FLP] = nil
|
||||
MENU_DATA[MEMU_VAR.CH_THR] = PORT.PORT6
|
||||
|
||||
-- Default Channel Assisgments for each Wing type
|
||||
|
||||
if (wingType==WING_TYPE.AIL_1) then
|
||||
MENU_DATA[MEMU_VAR.CH_L_AIL] = PORT.PORT1
|
||||
elseif (wingType==WING_TYPE.AIL_2) then
|
||||
MENU_DATA[MEMU_VAR.CH_L_AIL] = PORT.PORT1
|
||||
MENU_DATA[MEMU_VAR.CH_R_AIL] = PORT.PORT2
|
||||
elseif (wingType==WING_TYPE.AIL_2_FLP_1) then
|
||||
MENU_DATA[MEMU_VAR.CH_L_AIL] = PORT.PORT1
|
||||
MENU_DATA[MEMU_VAR.CH_R_AIL] = PORT.PORT2
|
||||
MENU_DATA[MEMU_VAR.CH_L_FLP] = PORT.PORT5
|
||||
elseif (wingType==WING_TYPE.AIL_2_FLP_2) then
|
||||
MENU_DATA[MEMU_VAR.CH_L_AIL] = PORT.PORT1
|
||||
MENU_DATA[MEMU_VAR.CH_R_AIL] = PORT.PORT2
|
||||
MENU_DATA[MEMU_VAR.CH_L_FLP] = PORT.PORT5
|
||||
MENU_DATA[MEMU_VAR.CH_R_FLP] = PORT.PORT6
|
||||
MENU_DATA[MEMU_VAR.CH_THR] = PORT.PORT7
|
||||
elseif (wingType==WING_TYPE.ELEVON_A) then
|
||||
MENU_DATA[MEMU_VAR.CH_L_AIL] = PORT.PORT1
|
||||
MENU_DATA[MEMU_VAR.CH_R_AIL] = PORT.PORT2
|
||||
elseif (wingType==WING_TYPE.ELEVON_B) then
|
||||
MENU_DATA[MEMU_VAR.CH_L_AIL] = PORT.PORT2
|
||||
MENU_DATA[MEMU_VAR.CH_R_AIL] = PORT.PORT1
|
||||
else -- Assume normal
|
||||
print("ERROR: Invalid Wing Type")
|
||||
end
|
||||
|
||||
ModelLib.printChannelSummary()
|
||||
end
|
||||
|
||||
function ModelLib.ST_GliderTailInit(tailType)
|
||||
if (MENU_DATA[MEMU_VAR.WING_TYPE]==WING_TYPE.ELEVON_A) then
|
||||
tailType = TAIL_TYPE.RUD_1 -- Delta only have ruder
|
||||
end
|
||||
|
||||
print("Change Glider Tail Type:"..tail_type_text[tailType])
|
||||
|
||||
-- Clear all data for Tail
|
||||
MENU_DATA[MEMU_VAR.TAIL_TYPE] = tailType
|
||||
MENU_DATA[MEMU_VAR.CH_L_ELE] = nil
|
||||
MENU_DATA[MEMU_VAR.CH_R_ELE] = nil
|
||||
MENU_DATA[MEMU_VAR.CH_L_RUD] = nil
|
||||
MENU_DATA[MEMU_VAR.CH_R_RUD] = nil
|
||||
|
||||
-- Setup Channels for different Tail types
|
||||
if (tailType == TAIL_TYPE.RUD_1) then
|
||||
MENU_DATA[MEMU_VAR.CH_L_RUD] = PORT.PORT4
|
||||
elseif (tailType == TAIL_TYPE.RUD_1_ELEV_1) then
|
||||
MENU_DATA[MEMU_VAR.CH_L_ELE] = PORT.PORT3
|
||||
MENU_DATA[MEMU_VAR.CH_L_RUD] = PORT.PORT4
|
||||
elseif (tailType == TAIL_TYPE.VTAIL_A) then
|
||||
MENU_DATA[MEMU_VAR.CH_L_ELE] = PORT.PORT4
|
||||
MENU_DATA[MEMU_VAR.CH_R_ELE] = PORT.PORT3
|
||||
elseif (tailType == TAIL_TYPE.VTAIL_B) then
|
||||
MENU_DATA[MEMU_VAR.CH_L_ELE] = PORT.PORT3
|
||||
MENU_DATA[MEMU_VAR.CH_R_ELE] = PORT.PORT4
|
||||
else -- Assume Normal
|
||||
print("ERROR: Invalid Tail Type")
|
||||
end
|
||||
|
||||
ModelLib.printChannelSummary()
|
||||
end
|
||||
|
||||
|
||||
function ModelLib.ST_AircraftInit(aircraftType)
|
||||
MENU_DATA[MEMU_VAR.AIRCRAFT_TYPE] = aircraftType
|
||||
|
||||
print("Change Aircraft:".. aircraft_type_text[aircraftType])
|
||||
|
||||
-- Setup Default Aircraft Wing/Tail
|
||||
if (aircraftType==AIRCRAFT_TYPE.PLANE) then
|
||||
ModelLib.ST_PlaneWingInit(WING_TYPE.AIL_1)
|
||||
ModelLib.ST_PlaneTailInit(TAIL_TYPE.RUD_1_ELEV_1)
|
||||
elseif (aircraftType==AIRCRAFT_TYPE.GLIDER) then
|
||||
ModelLib.ST_GliderWingInit(WING_TYPE.AIL_1)
|
||||
ModelLib.ST_GliderTailInit(TAIL_TYPE.RUD_1_ELEV_1)
|
||||
else
|
||||
ModelLib.ST_PlaneWingInit(WING_TYPE.AIL_1)
|
||||
ModelLib.ST_PlaneTailInit(TAIL_TYPE.RUD_1_ELEV_1)
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
||||
|
||||
-- Setup Initial Default Data for the Menus
|
||||
function ModelLib.ST_Default_Data()
|
||||
print("Initializing Menu DATA")
|
||||
ModelLib.ST_AircraftInit(AIRCRAFT_TYPE.PLANE)
|
||||
|
||||
print("Initializing Servo Reverse from TX output settings")
|
||||
|
||||
MENU_DATA[MEMU_VAR.PORT1_MODE] = CH_MODE_TYPE.NORMAL + MODEL.modelOutputChannel[PORT.PORT1].revert
|
||||
MENU_DATA[MEMU_VAR.PORT2_MODE] = CH_MODE_TYPE.NORMAL + MODEL.modelOutputChannel[PORT.PORT2].revert
|
||||
MENU_DATA[MEMU_VAR.PORT3_MODE] = CH_MODE_TYPE.NORMAL + MODEL.modelOutputChannel[PORT.PORT3].revert
|
||||
MENU_DATA[MEMU_VAR.PORT4_MODE] = CH_MODE_TYPE.NORMAL + MODEL.modelOutputChannel[PORT.PORT4].revert
|
||||
MENU_DATA[MEMU_VAR.PORT5_MODE] = CH_MODE_TYPE.NORMAL + MODEL.modelOutputChannel[PORT.PORT5].revert
|
||||
MENU_DATA[MEMU_VAR.PORT6_MODE] = CH_MODE_TYPE.NORMAL + MODEL.modelOutputChannel[PORT.PORT6].revert
|
||||
MENU_DATA[MEMU_VAR.PORT7_MODE] = CH_MODE_TYPE.NORMAL + MODEL.modelOutputChannel[PORT.PORT7].revert
|
||||
MENU_DATA[MEMU_VAR.PORT8_MODE] = CH_MODE_TYPE.NORMAL + MODEL.modelOutputChannel[PORT.PORT8].revert
|
||||
MENU_DATA[MEMU_VAR.PORT9_MODE] = CH_MODE_TYPE.NORMAL + MODEL.modelOutputChannel[PORT.PORT9].revert
|
||||
MENU_DATA[MEMU_VAR.PORT10_MODE] = CH_MODE_TYPE.NORMAL + MODEL.modelOutputChannel[PORT.PORT10].revert
|
||||
|
||||
ModelLib.printServoReverseInfo()
|
||||
|
||||
end
|
||||
|
||||
|
||||
ModelLib.TX_CHANNELS = TX_CHANNELS
|
||||
ModelLib.MODEL = MODEL
|
||||
ModelLib.CH_TYPE = CH_TYPE
|
||||
ModelLib.CH_MODE_TYPE = CH_MODE_TYPE
|
||||
ModelLib.AIRCRAFT_TYPE = AIRCRAFT_TYPE
|
||||
ModelLib.WING_TYPE = WING_TYPE
|
||||
ModelLib.TAIL_TYPE = TAIL_TYPE
|
||||
ModelLib.MENU_DATA = MENU_DATA
|
||||
ModelLib.MEMU_VAR = MEMU_VAR
|
||||
ModelLib.PORT = PORT
|
||||
ModelLib.DATA_PATH = DATA_PATH
|
||||
|
||||
ModelLib.aircraft_type_text = aircraft_type_text
|
||||
ModelLib.wing_type_text = wing_type_text
|
||||
ModelLib.tail_type_text = tail_type_text
|
||||
|
||||
|
||||
return ModelLib
|
||||
|
||||
467
Lua_scripts/DSMLIB/DsmSetupMenuLib.lua
Normal file
@@ -0,0 +1,467 @@
|
||||
---- #########################################################################
|
||||
---- # #
|
||||
---- # 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 scrip does the airplane Setup similar to how a a Spektrum radio does
|
||||
-- it. You can select the plane type, the Wing type, etc.
|
||||
-- This settings are needed for ForwardProgramming to send the TX aircraft
|
||||
-- configuration to the RX when in Initial Setup
|
||||
-- Author: Francisco Arzu
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
local Log, menuLib, modelLib, DEBUG_ON, SIMULATION_ON = ... -- Get DebugON from parameters
|
||||
local SETUP_LIB_VERSION = "0.56"
|
||||
|
||||
local DATA_PATH = modelLib.DATA_PATH
|
||||
|
||||
local PHASE = menuLib.PHASE
|
||||
local LINE_TYPE = menuLib.LINE_TYPE
|
||||
|
||||
local MODEL = modelLib.MODEL
|
||||
|
||||
local AIRCRAFT_TYPE = modelLib.AIRCRAFT_TYPE
|
||||
local WING_TYPE = modelLib.WING_TYPE
|
||||
local TAIL_TYPE = modelLib.TAIL_TYPE
|
||||
local CH_MODE_TYPE = modelLib.CH_MODE_TYPE
|
||||
local PORT = modelLib.PORT
|
||||
local MEMU_VAR = modelLib.MEMU_VAR
|
||||
local MENU_DATA = modelLib.MENU_DATA
|
||||
|
||||
local SetupLib = {}
|
||||
|
||||
local lastGoodMenu=0
|
||||
|
||||
------------------- Model Setup Helper functions ----------------------
|
||||
local currAircraftType = -1 -- Current AircraftType selected, and to detect change
|
||||
local currTailType = -1 -- Current WingType selected, and to detect change
|
||||
local currWingType = -1 -- Current TailType selected, and to detect change
|
||||
|
||||
local menuDataChanged = false -- Flag to notify if any data has changed
|
||||
|
||||
|
||||
local function tailTypeCompatible(a,b)
|
||||
|
||||
local function normalize(tt)
|
||||
if (tt==TAIL_TYPE.TRAILERON_A or tt==TAIL_TYPE.TRAILERON_B) then
|
||||
return TAIL_TYPE.TRAILERON_A
|
||||
elseif (tt==TAIL_TYPE.TRAILERON_A_R2 or tt==TAIL_TYPE.TRAILERON_B_R2) then
|
||||
return TAIL_TYPE.TRAILERON_A_R2
|
||||
elseif (tt==TAIL_TYPE.VTAIL_A or tt==TAIL_TYPE.VTAIL_B) then
|
||||
return TAIL_TYPE.VTAIL_A
|
||||
else
|
||||
return tt
|
||||
end
|
||||
end
|
||||
|
||||
return (normalize(a)==normalize(b))
|
||||
end
|
||||
|
||||
|
||||
-- Creates the menus to Render with the GUI
|
||||
local function ST_LoadMenu(menuId)
|
||||
local ctx = menuLib.DSM_Context
|
||||
|
||||
local function portUse(p)
|
||||
local out = ""
|
||||
if p==MENU_DATA[MEMU_VAR.CH_THR] then out = "Thr"
|
||||
elseif p == MENU_DATA[MEMU_VAR.CH_L_AIL] then
|
||||
out=(MENU_DATA[MEMU_VAR.CH_R_AIL] and "Ail_L") or "Ail"
|
||||
elseif p == MENU_DATA[MEMU_VAR.CH_R_AIL] then out="Ail_R"
|
||||
elseif p == MENU_DATA[MEMU_VAR.CH_L_ELE] then
|
||||
out=(MENU_DATA[MEMU_VAR.CH_R_ELE] and "Ele_L") or "Ele"
|
||||
elseif p == MENU_DATA[MEMU_VAR.CH_R_ELE] then out="Ele_R"
|
||||
elseif p == MENU_DATA[MEMU_VAR.CH_L_RUD] then
|
||||
out=(MENU_DATA[MEMU_VAR.CH_R_RUD] and "Rud_L") or "Rud"
|
||||
elseif p == MENU_DATA[MEMU_VAR.CH_R_RUD] then out="Rud_R"
|
||||
elseif p == MENU_DATA[MEMU_VAR.CH_L_FLP] then
|
||||
out=(MENU_DATA[MEMU_VAR.CH_R_FLP] and "Flp_L") or "Flp"
|
||||
elseif p == MENU_DATA[MEMU_VAR.CH_R_FLP] then out="Flp_R"
|
||||
end
|
||||
return out
|
||||
end
|
||||
|
||||
local function formatTXRevert(port)
|
||||
local out = " " .. modelLib.channelType2String(MODEL.DSM_ChannelInfo[port][0], MODEL.DSM_ChannelInfo[port][1]);
|
||||
return out
|
||||
end
|
||||
|
||||
local function Header(p)
|
||||
return MODEL.PORT_TEXT[p].." "..portUse(p)
|
||||
end
|
||||
|
||||
menuLib.clearMenuLines()
|
||||
|
||||
|
||||
if (menuId==0x1000) then -- MAIN MENU
|
||||
ctx.Menu = { MenuId = 0x1000, Text = "Save-Exit ("..MODEL.modelName..")", PrevId = 0, NextId = 0, BackId = 0, TextId=0 }
|
||||
|
||||
if (true) then
|
||||
ctx.MenuLines[4] = { Type = LINE_TYPE.MENU, Text="Save Changes", TextId = 0, ValId = 0x1005 }
|
||||
ctx.MenuLines[5] = { Type = LINE_TYPE.MENU, Text="Discard Changes", TextId = 0, ValId = 0x1006 }
|
||||
ctx.SelLine = 4
|
||||
end
|
||||
lastGoodMenu = menuId
|
||||
elseif (menuId==0x1001) then -- MODEL SETUP
|
||||
local backId = 0xFFF9 -- No changes, just exit
|
||||
local title = "Model Setup ("..MODEL.modelName..")"
|
||||
if (menuDataChanged) then
|
||||
backId = 0x1000 -- Go to Save menu
|
||||
title = title.." *"
|
||||
end
|
||||
ctx.Menu = { MenuId = 0x1001, Text = title, PrevId = 0, NextId = 0, BackId = backId, TextId=0 }
|
||||
ctx.MenuLines[0] = { Type = LINE_TYPE.MENU, Text = "Aircraft Type Setup", ValId = 0x1010,TextId=0 }
|
||||
ctx.MenuLines[1] = { Type = LINE_TYPE.MENU, Text = "Wing & Tail Channels ", ValId = 0x1020, TextId=0 }
|
||||
ctx.MenuLines[3] = { Type = LINE_TYPE.MENU, Text = "Gyro Channel Reverse", ValId = 0x1030, TextId=0 }
|
||||
ctx.MenuLines[5] = { Type = LINE_TYPE.MENU, Text = "WARNING: Changing of Aircraft or Wing will", ValId = 0x1001, TextId=0 }
|
||||
ctx.MenuLines[6] = { Type = LINE_TYPE.MENU, Text = "delete previous Channel/Port assigments.", ValId = 0x1001, TextId=0 }
|
||||
|
||||
ctx.SelLine = 0
|
||||
lastGoodMenu = menuId
|
||||
elseif (menuId==0x1005) then
|
||||
modelLib.printChannelSummary()
|
||||
modelLib.ST_SaveFileData()
|
||||
menuDataChanged = false
|
||||
|
||||
|
||||
local msg1 = "Data saved to: "
|
||||
local msg2 = " "..DATA_PATH.."/"..modelLib.hashName(MODEL.modelName)..".txt"
|
||||
|
||||
ctx.Menu = { MenuId = 0x1005, Text = "Config Saved", PrevId = 0, NextId = 0, BackId = 0, TextId=0 }
|
||||
ctx.MenuLines[2] = { Type = LINE_TYPE.MENU, Text=msg1, TextId = 0, ValId = 0x1005 }
|
||||
ctx.MenuLines[3] = { Type = LINE_TYPE.MENU, Text=msg2, TextId = 0, ValId = 0x1005 }
|
||||
ctx.MenuLines[6] = { Type = LINE_TYPE.MENU, Text="Complete", TextId = 0, ValId = 0xFFF9 }
|
||||
ctx.SelLine = 6
|
||||
lastGoodMenu = menuId
|
||||
elseif (menuId==0x1006) then
|
||||
modelLib.ST_LoadFileData()
|
||||
menuDataChanged = false
|
||||
currAircraftType = MENU_DATA[MEMU_VAR.AIRCRAFT_TYPE]
|
||||
currWingType = MENU_DATA[MEMU_VAR.WING_TYPE]
|
||||
currTailType = MENU_DATA[MEMU_VAR.TAIL_TYPE]
|
||||
|
||||
local msg1 = "Data restored from: "
|
||||
local msg2 = " "..DATA_PATH.."/"..modelLib.hashName(MODEL.modelName)..".txt"
|
||||
|
||||
ctx.Menu = { MenuId = 0x1006, Text = "Discart Changes", PrevId = 0, NextId = 0, BackId = 0, TextId=0 }
|
||||
ctx.MenuLines[2] = { Type = LINE_TYPE.MENU, Text=msg1, TextId = 0, ValId = 0x1006 }
|
||||
ctx.MenuLines[3] = { Type = LINE_TYPE.MENU, Text=msg2, TextId = 0, ValId = 0x1006 }
|
||||
ctx.MenuLines[6] = { Type = LINE_TYPE.MENU, Text="Complete", TextId = 0, ValId = 0xFFF9 }
|
||||
ctx.SelLine = 6
|
||||
lastGoodMenu = menuId
|
||||
elseif (menuId==0x1010) then
|
||||
modelLib.printChannelSummary()
|
||||
ctx.Menu = { MenuId = 0x1010, Text = "Aircraft Type", PrevId = 0, NextId = 0x1011, BackId = 0x1001, TextId=0 }
|
||||
ctx.MenuLines[5] = { Type = LINE_TYPE.LIST_MENU_NC, Text="Aircraft Type", TextId = 0, ValId = MEMU_VAR.AIRCRAFT_TYPE, Min=50, Max=53, Def=50, Val=MENU_DATA[MEMU_VAR.AIRCRAFT_TYPE] }
|
||||
ctx.SelLine = 5
|
||||
lastGoodMenu = menuId
|
||||
elseif (menuId==0x1011) then
|
||||
ctx.Menu = { MenuId = 0x1011, Text = "Model Type:"..modelLib.aircraft_type_text[currAircraftType], PrevId = 0, NextId = 0x1020, BackId = 0x1010, TextId=0 }
|
||||
ctx.MenuLines[5] = { Type = LINE_TYPE.LIST_MENU_NC, Text="Wing Type", TextId = 0, ValId = MEMU_VAR.WING_TYPE, Min=100, Max=107, Def=100, Val=MENU_DATA[MEMU_VAR.WING_TYPE] }
|
||||
ctx.MenuLines[6] = { Type = LINE_TYPE.LIST_MENU_NC, Text="Tail Type", TextId = 0, ValId = MEMU_VAR.TAIL_TYPE, Min=200, Max=210, Def=200, Val=MENU_DATA[MEMU_VAR.TAIL_TYPE] }
|
||||
ctx.SelLine = 5
|
||||
lastGoodMenu = menuId
|
||||
elseif (menuId==0x1020) then
|
||||
------ WING SETUP -------
|
||||
local thr = MENU_DATA[MEMU_VAR.CH_THR]
|
||||
local leftAil = MENU_DATA[MEMU_VAR.CH_L_AIL]
|
||||
local rightAil = MENU_DATA[MEMU_VAR.CH_R_AIL]
|
||||
local leftFlap = MENU_DATA[MEMU_VAR.CH_L_FLP]
|
||||
local rightFlap = MENU_DATA[MEMU_VAR.CH_R_FLP]
|
||||
|
||||
local thrText = "Thr"
|
||||
local leftAilText = "Left Aileron"
|
||||
local rightAilText = "Right Aileron"
|
||||
local leftFlapText = "Left Flap"
|
||||
local rightFlapText = "Right Flap"
|
||||
|
||||
if (rightAil==nil) then leftAilText = "Aileron" end
|
||||
if (rightFlap==nil) then leftFlapText = "Flap" end
|
||||
|
||||
local title = modelLib.aircraft_type_text[currAircraftType].." Wing:"..modelLib.wing_type_text[currWingType]
|
||||
|
||||
ctx.Menu = { MenuId = 0x1020, Text = title, PrevId = 0, NextId = 0x1021, BackId = 0x1011, TextId=0 }
|
||||
|
||||
ctx.MenuLines[0] = { Type = LINE_TYPE.LIST_MENU_NC, Text=thrText, TextId = 0, ValId = MEMU_VAR.CH_THR, Min=0, Max=10, Def=0, Val= thr }
|
||||
|
||||
ctx.MenuLines[2] = { Type = LINE_TYPE.LIST_MENU_NC, Text=leftAilText, TextId = 0, ValId = MEMU_VAR.CH_L_AIL, Min=0, Max=9, Def=0, Val= leftAil }
|
||||
|
||||
if (rightAil~=nil) then
|
||||
ctx.MenuLines[3] = { Type = LINE_TYPE.LIST_MENU_NC, Text=rightAilText, TextId = 0, ValId = MEMU_VAR.CH_R_AIL, Min=0, Max=9, Def=0, Val= rightAil }
|
||||
end
|
||||
|
||||
if (leftFlap~=nil) then
|
||||
ctx.MenuLines[4] = { Type = LINE_TYPE.LIST_MENU_NC, Text=leftFlapText, TextId = 0, ValId = MEMU_VAR.CH_L_FLP, Min=0, Max=9, Def=0, Val= leftFlap }
|
||||
end
|
||||
if (rightFlap~=nil) then
|
||||
ctx.MenuLines[5] = { Type = LINE_TYPE.LIST_MENU_NC, Text=rightFlapText, TextId = 0, ValId = MEMU_VAR.CH_R_FLP, Min=0, Max=9, Def=0, Val= rightFlap }
|
||||
end
|
||||
|
||||
ctx.SelLine = 0
|
||||
lastGoodMenu = menuId
|
||||
|
||||
elseif (menuId==0x1021) then
|
||||
------ TAIL SETUP -------
|
||||
local leftRud = MENU_DATA[MEMU_VAR.CH_L_RUD]
|
||||
local rightRud = MENU_DATA[MEMU_VAR.CH_R_RUD]
|
||||
local leftEle = MENU_DATA[MEMU_VAR.CH_L_ELE]
|
||||
local rightEle = MENU_DATA[MEMU_VAR.CH_R_ELE]
|
||||
|
||||
local leftRudText = "Left Rudder"
|
||||
local rightRudText = "Right Rudder"
|
||||
|
||||
local leftElvText = "Left Elevator"
|
||||
local rightElvText = "Right Elevator"
|
||||
|
||||
if (rightRud==nil) then leftRudText = "Rudder" end
|
||||
if (rightEle==nil) then leftElvText = "Elevator" end
|
||||
|
||||
local title = modelLib.aircraft_type_text[currAircraftType].." Tail:"..modelLib.tail_type_text[currTailType]
|
||||
|
||||
ctx.Menu = { MenuId = 0x1021, Text = title, PrevId = 0, NextId = 0x1001, BackId = 0x1020, TextId=0 }
|
||||
if (leftRud~=nil) then
|
||||
ctx.MenuLines[1] = { Type = LINE_TYPE.LIST_MENU_NC, Text=leftRudText, TextId = 0, ValId = MEMU_VAR.CH_L_RUD, Min=0, Max=9, Def=0, Val= leftRud}
|
||||
end
|
||||
|
||||
if (rightRud~=nil) then
|
||||
ctx.MenuLines[2] = { Type = LINE_TYPE.LIST_MENU_NC, Text=rightRudText, TextId = 0, ValId = MEMU_VAR.CH_R_RUD, Min=0, Max=9, Def=0, Val=rightRud }
|
||||
end
|
||||
|
||||
if (leftEle~=nil) then
|
||||
ctx.MenuLines[4] = { Type = LINE_TYPE.LIST_MENU_NC, Text=leftElvText, TextId = 0, ValId = MEMU_VAR.CH_L_ELE, Min=0, Max=9, Def=0, Val=leftEle }
|
||||
end
|
||||
|
||||
if (rightEle~=nil) then
|
||||
ctx.MenuLines[5] = { Type = LINE_TYPE.LIST_MENU_NC, Text=rightElvText, TextId = 0, ValId = MEMU_VAR.CH_R_ELE, Min=0, Max=9, Def=0, Val=rightEle }
|
||||
end
|
||||
|
||||
ctx.SelLine = 1
|
||||
lastGoodMenu = menuId
|
||||
|
||||
elseif (menuId==0x1030) then
|
||||
modelLib.CreateDSMPortChannelInfo()
|
||||
modelLib.printChannelSummary()
|
||||
|
||||
ctx.Menu = { MenuId = 0x1030, Text = "Gyro Channel Reverse (Port 1-5)", PrevId = 0, NextId = 0x1031, BackId = 0x1001, TextId=0 }
|
||||
ctx.MenuLines[0] = { Type = LINE_TYPE.LIST_MENU_NC, Text=Header(PORT.PORT1), TextId = 0, ValId = MEMU_VAR.PORT1_MODE, Min=300, Max=301, Def=300, Val=MENU_DATA[MEMU_VAR.PORT1_MODE], Format = formatTXRevert(PORT.PORT1) }
|
||||
ctx.MenuLines[1] = { Type = LINE_TYPE.LIST_MENU_NC, Text=Header(PORT.PORT2), TextId = 0, ValId = MEMU_VAR.PORT2_MODE, Min=300, Max=301, Def=300, Val=MENU_DATA[MEMU_VAR.PORT2_MODE], Format = formatTXRevert(PORT.PORT2) }
|
||||
ctx.MenuLines[2] = { Type = LINE_TYPE.LIST_MENU_NC, Text=Header(PORT.PORT3), TextId = 0, ValId = MEMU_VAR.PORT3_MODE, Min=300, Max=301, Def=300, Val=MENU_DATA[MEMU_VAR.PORT3_MODE], Format = formatTXRevert(PORT.PORT3) }
|
||||
ctx.MenuLines[3] = { Type = LINE_TYPE.LIST_MENU_NC, Text=Header(PORT.PORT4), TextId = 0, ValId = MEMU_VAR.PORT4_MODE, Min=300, Max=301, Def=300, Val=MENU_DATA[MEMU_VAR.PORT4_MODE], Format = formatTXRevert(PORT.PORT4) }
|
||||
ctx.MenuLines[4] = { Type = LINE_TYPE.LIST_MENU_NC, Text=Header(PORT.PORT5), TextId = 0, ValId = MEMU_VAR.PORT5_MODE, Min=300, Max=301, Def=300, Val=MENU_DATA[MEMU_VAR.PORT5_MODE], Format = formatTXRevert(PORT.PORT5) }
|
||||
|
||||
ctx.MenuLines[5] = { Type = LINE_TYPE.MENU, Text="Only Thr/Ail/Rud/Ele. This affects AS3X/SAFE reaction dir./b", TextId = 0, ValId = 0x1030 }
|
||||
ctx.MenuLines[6] = { Type = LINE_TYPE.MENU, Text="Any changes, use RX 'Relearn Servo Settings'/b", TextId = 0, ValId = 0x1030 }
|
||||
|
||||
ctx.SelLine = 0
|
||||
lastGoodMenu = menuId
|
||||
elseif (menuId==0x1031) then
|
||||
modelLib.CreateDSMPortChannelInfo()
|
||||
modelLib.printChannelSummary()
|
||||
ctx.Menu = { MenuId = 0x1031, Text = "Gyro Channel Reverse (Port 6-10)", PrevId = 0x1030, NextId = 0, BackId = 0x1001, TextId=0 }
|
||||
ctx.MenuLines[0] = { Type = LINE_TYPE.LIST_MENU_NC, Text=Header(PORT.PORT6), TextId = 0, ValId = MEMU_VAR.PORT6_MODE, Min=300, Max=301, Def=300, Val=MENU_DATA[MEMU_VAR.PORT6_MODE], Format = formatTXRevert(PORT.PORT6) }
|
||||
ctx.MenuLines[1] = { Type = LINE_TYPE.LIST_MENU_NC, Text=Header(PORT.PORT7), TextId = 0, ValId = MEMU_VAR.PORT7_MODE, Min=300, Max=301, Def=300, Val=MENU_DATA[MEMU_VAR.PORT7_MODE], Format = formatTXRevert(PORT.PORT7) }
|
||||
ctx.MenuLines[2] = { Type = LINE_TYPE.LIST_MENU_NC, Text=Header(PORT.PORT8), TextId = 0, ValId = MEMU_VAR.PORT8_MODE, Min=300, Max=301, Def=300, Val=MENU_DATA[MEMU_VAR.PORT8_MODE], Format = formatTXRevert(PORT.PORT8) }
|
||||
ctx.MenuLines[3] = { Type = LINE_TYPE.LIST_MENU_NC, Text=Header(PORT.PORT9), TextId = 0, ValId = MEMU_VAR.PORT9_MODE, Min=300, Max=301, Def=300, Val=MENU_DATA[MEMU_VAR.PORT9_MODE], Format = formatTXRevert(PORT.PORT9) }
|
||||
ctx.MenuLines[4] = { Type = LINE_TYPE.LIST_MENU_NC, Text=Header(PORT.PORT10), TextId = 0, ValId = MEMU_VAR.PORT10_MODE, Min=300, Max=301, Def=300, Val=MENU_DATA[MEMU_VAR.PORT10_MODE], Format = formatTXRevert(PORT.PORT10) }
|
||||
|
||||
ctx.MenuLines[5] = { Type = LINE_TYPE.MENU, Text="Only Thr/Ail/Rud/Ele. This affects AS3X/SAFE reaction dir./b", TextId = 0, ValId = 0x1031 }
|
||||
ctx.MenuLines[6] = { Type = LINE_TYPE.MENU, Text="Any changes, use RX 'Relearn Servo Settings'/b", TextId = 0, ValId = 0x1031 }
|
||||
|
||||
ctx.SelLine = 0
|
||||
lastGoodMenu = menuId
|
||||
else
|
||||
print("NOT IMPLEMENTED")
|
||||
ctx.Menu = { MenuId = 0x0002, Text = "NOT IMPLEMENTED", TextId = 0, PrevId = 0, NextId = 0, BackId = lastGoodMenu }
|
||||
ctx.SelLine = menuLib.BACK_BUTTON
|
||||
end
|
||||
|
||||
menuLib.PostProcessMenu()
|
||||
end
|
||||
|
||||
-- ST_SendReceive
|
||||
-- Main state machine for the Setup menu
|
||||
|
||||
local function ST_SendReceive()
|
||||
local ctx = menuLib.DSM_Context
|
||||
--if (DEBUG_ON>1) then Log.LOG_write("%3.3f %s: ", menuLib.getElapsedTime(), menuLib.phase2String(ctx.Phase)) end
|
||||
|
||||
if ctx.Phase == PHASE.RX_VERSION then -- request RX version
|
||||
ctx.RX.Name = "MODEL SETUP"
|
||||
ctx.RX.Version = SETUP_LIB_VERSION
|
||||
ctx.Phase = PHASE.MENU_TITLE
|
||||
ctx.Menu.MenuId = 0x01001
|
||||
|
||||
ctx.Refresh_Display = true
|
||||
|
||||
|
||||
elseif ctx.Phase == PHASE.WAIT_CMD then
|
||||
|
||||
elseif ctx.Phase == PHASE.MENU_TITLE then -- request menu title
|
||||
ST_LoadMenu(ctx.Menu.MenuId)
|
||||
ctx.Phase = PHASE.WAIT_CMD
|
||||
ctx.Refresh_Display = true
|
||||
|
||||
elseif ctx.Phase == PHASE.VALUE_CHANGING then -- send value
|
||||
local line = ctx.MenuLines[ctx.SelLine] -- Updated Value of SELECTED line
|
||||
|
||||
if (MENU_DATA[line.ValId] ~= line.Val ) then
|
||||
MENU_DATA[line.ValId] = line.Val
|
||||
print(string.format("MENU_DATA[%d/%s]=%d",line.ValId,line.Text, line.Val))
|
||||
menuDataChanged=true
|
||||
end
|
||||
|
||||
ctx.Phase = PHASE.VALUE_CHANGING_WAIT
|
||||
|
||||
elseif ctx.Phase == PHASE.VALUE_CHANGING_WAIT then
|
||||
local line = ctx.MenuLines[ctx.SelLine]
|
||||
|
||||
elseif ctx.Phase == PHASE.VALUE_CHANGE_END then -- send value
|
||||
local line = ctx.MenuLines[ctx.SelLine] -- Updated Value of SELECTED line
|
||||
|
||||
-- Update the menu data from the line
|
||||
if (MENU_DATA[line.ValId] ~= line.Val ) then
|
||||
MENU_DATA[line.ValId] = line.Val
|
||||
print(string.format("MENU_DATA[%d/%s]=%d",line.ValId,line.Text, line.Val))
|
||||
menuDataChanged=true
|
||||
end
|
||||
|
||||
-- Did the aircraft type change?
|
||||
if (currAircraftType ~= MENU_DATA[MEMU_VAR.AIRCRAFT_TYPE]) then
|
||||
currAircraftType = MENU_DATA[MEMU_VAR.AIRCRAFT_TYPE]
|
||||
modelLib.ST_AircraftInit(currAircraftType)
|
||||
currWingType = MENU_DATA[MEMU_VAR.WING_TYPE]
|
||||
currTailType = MENU_DATA[MEMU_VAR.TAIL_TYPE]
|
||||
end
|
||||
|
||||
-- Did the Wing type change?
|
||||
if (currWingType ~= MENU_DATA[MEMU_VAR.WING_TYPE]) then
|
||||
if (currAircraftType==AIRCRAFT_TYPE.GLIDER) then
|
||||
currWingType = MENU_DATA[MEMU_VAR.WING_TYPE]
|
||||
modelLib.ST_GliderWingInit(currWingType)
|
||||
else
|
||||
currWingType = MENU_DATA[MEMU_VAR.WING_TYPE]
|
||||
modelLib.ST_PlaneWingInit(currWingType)
|
||||
|
||||
end
|
||||
|
||||
-- DELTA has only RUDER
|
||||
if ((currWingType==WING_TYPE.ELEVON_A or currWingType==WING_TYPE.ELEVON_B) and TAIL_TYPE~=TAIL_TYPE.RUD_1) then
|
||||
MENU_DATA[MEMU_VAR.TAIL_TYPE] = TAIL_TYPE.RUD_1
|
||||
end
|
||||
end
|
||||
|
||||
--- Did the tail changed?
|
||||
local ntt = MENU_DATA[MEMU_VAR.TAIL_TYPE]
|
||||
if (currTailType ~= ntt) then
|
||||
if (currAircraftType==AIRCRAFT_TYPE.GLIDER) then
|
||||
currTailType = ntt
|
||||
modelLib.ST_GliderTailInit(currTailType)
|
||||
else
|
||||
if (not tailTypeCompatible(currTailType,ntt)) then
|
||||
modelLib.ST_PlaneTailInit(ntt)
|
||||
end
|
||||
currTailType = ntt
|
||||
end
|
||||
end
|
||||
|
||||
ctx.Phase = PHASE.WAIT_CMD
|
||||
elseif ctx.Phase == PHASE.EXIT then
|
||||
ctx.Phase=PHASE.EXIT_DONE
|
||||
end
|
||||
end
|
||||
|
||||
------------------------------------------------------------------------------------------------------------
|
||||
|
||||
-- Inital List and Image Text for this menus
|
||||
local function ST_Init_Text(rxId)
|
||||
menuLib.clearAllText()
|
||||
|
||||
local List_Values = menuLib.List_Values
|
||||
local List_Text = menuLib.List_Text
|
||||
local Text = menuLib.Text
|
||||
local List_Text_Img = menuLib.List_Text_Img
|
||||
|
||||
-- Channel Names use the Port Text Retrived from OTX/ETX
|
||||
for i = 0, 9 do List_Text[i] = MODEL.PORT_TEXT[i] end
|
||||
List_Text[10]="--"
|
||||
|
||||
-- Aircraft Type
|
||||
List_Text[50+AIRCRAFT_TYPE.PLANE] = "Airplane"; --List_Text_Img[50+AIRCRAFT_TYPE.PLANE] = "at_plane.png|Airplane"
|
||||
List_Text[50+AIRCRAFT_TYPE.GLIDER] = "Glider (Partial work)"; --List_Text_Img[50+AIRCRAFT_TYPE.GLIDER] = "at_glider.png|Glider"
|
||||
List_Text[50+AIRCRAFT_TYPE.HELI] = "Helicopter (Not done)"; --List_Text_Img[50+AIRCRAFT_TYPE.HELI] = "at_heli.png|Helicopter"
|
||||
List_Text[50+AIRCRAFT_TYPE.DRONE] = "Drone (not done)"; --List_Text_Img[50+AIRCRAFT_TYPE.DRONE] = "at_drone.png|Drone"
|
||||
|
||||
-- Wing Types
|
||||
List_Text[100+WING_TYPE.AIL_1] = "Single Ail"; List_Text_Img[100+WING_TYPE.AIL_1] = "wt_1ail.png|Single Aileron"
|
||||
List_Text[100+WING_TYPE.AIL_2] = "Dual Ail"; List_Text_Img[100+WING_TYPE.AIL_2] = "wt_2ail.png|Dual Aileron"
|
||||
List_Text[100+WING_TYPE.FLAPERON] = "Flaperon"; List_Text_Img[100+WING_TYPE.FLAPERON] = "wt_flaperon.png|Flaperon"
|
||||
List_Text[100+WING_TYPE.AIL_1_FLP_1] = "Ail + Flap"; List_Text_Img[100+WING_TYPE.AIL_1_FLP_1] = "wt_1ail_1flp.png|Aileron + Flap"
|
||||
List_Text[100+WING_TYPE.AIL_2_FLP_1] = "Dual Ail + Flap"; List_Text_Img[100+WING_TYPE.AIL_2_FLP_1] = "wt_2ail_1flp.png|Dual Aileron + Flap"
|
||||
List_Text[100+WING_TYPE.AIL_2_FLP_2] = "Dual Ail + Dual Flap"; List_Text_Img[100+WING_TYPE.AIL_2_FLP_2] = "wt_2ail_2flp.png|Dual Aileron + Dual Flap"
|
||||
List_Text[100+WING_TYPE.ELEVON_A] = "Delta/Elevon A"; List_Text_Img[100+WING_TYPE.ELEVON_A] = "wt_elevon.png|Delta/Elevon A"
|
||||
List_Text[100+WING_TYPE.ELEVON_B] = "Delta/Elevon B"; List_Text_Img[100+WING_TYPE.ELEVON_B] = "wt_elevon.png|Delta/Elevon B"
|
||||
|
||||
-- Tail Types
|
||||
List_Text[200+TAIL_TYPE.RUD_1] = "Rudder Only"; List_Text_Img[200+TAIL_TYPE.RUD_1] = "tt_1rud.png|Rudder Only"
|
||||
List_Text[200+TAIL_TYPE.RUD_1_ELEV_1] = "Rud + Ele"; List_Text_Img[200+TAIL_TYPE.RUD_1_ELEV_1] = "tt_1rud_1ele.png|Tail Normal"
|
||||
List_Text[200+TAIL_TYPE.RUD_1_ELEV_2] = "Rud + Dual Ele"; List_Text_Img[200+TAIL_TYPE.RUD_1_ELEV_2] = "tt_1rud_2ele.png|Rud + Dual Elev"
|
||||
List_Text[200+TAIL_TYPE.RUD_2_ELEV_1] = "Dual Rud + Ele"; List_Text_Img[200+TAIL_TYPE.RUD_2_ELEV_1] = "tt_2rud_1ele.png|Dual Rud + Elev"
|
||||
List_Text[200+TAIL_TYPE.RUD_2_ELEV_2] = "Dual Rud + Dual Ele"; List_Text_Img[200+TAIL_TYPE.RUD_2_ELEV_2] = "tt_2rud_2ele.png|Dual Rud + Dual Elev"
|
||||
List_Text[200+TAIL_TYPE.VTAIL_A] = "V-Tail A"; List_Text_Img[200+TAIL_TYPE.VTAIL_A] = "tt_vtail.png|V-Tail A"
|
||||
List_Text[200+TAIL_TYPE.VTAIL_B] = "V-Tail B"; List_Text_Img[200+TAIL_TYPE.VTAIL_B] = "tt_vtail.png|V-Tail B"
|
||||
List_Text[200+TAIL_TYPE.TRAILERON_A] = "Taileron A"; List_Text_Img[200+TAIL_TYPE.TRAILERON_A] = "tt_taileron.png|Taileron A"
|
||||
List_Text[200+TAIL_TYPE.TRAILERON_B] = "Taileron B"; List_Text_Img[200+TAIL_TYPE.TRAILERON_B] = "tt_taileron.png|Taileron B"
|
||||
List_Text[200+TAIL_TYPE.TRAILERON_A_R2] = "Taileron A + 2x Rud"; List_Text_Img[200+TAIL_TYPE.TRAILERON_A_R2] = "tt_taileron2.png|Taileron A + Dual Rud"
|
||||
List_Text[200+TAIL_TYPE.TRAILERON_B_R2] = "Taileron B + 2x Rud"; List_Text_Img[200+TAIL_TYPE.TRAILERON_B_R2] = "tt_taileron2.png|Taileron B + Dual Rud"
|
||||
|
||||
|
||||
-- Servo Reverse
|
||||
if (LCD_W > 128) then
|
||||
List_Text[300+CH_MODE_TYPE.NORMAL] = "Normal "
|
||||
List_Text[300+CH_MODE_TYPE.REVERSE] = "Reverse"
|
||||
else
|
||||
List_Text[300+CH_MODE_TYPE.NORMAL] = "Nor"
|
||||
List_Text[300+CH_MODE_TYPE.REVERSE] = "Rev"
|
||||
end
|
||||
end
|
||||
|
||||
-- Initial Setup
|
||||
local function ST_Init()
|
||||
-- Initialize text (use RX_ID 0)
|
||||
ST_Init_Text(0)
|
||||
|
||||
-- Setup default Data, and load a file if exist
|
||||
--modelLib.ST_Default_Data()
|
||||
if (modelLib.ST_LoadFileData()==0) then -- Did not load a file
|
||||
modelLib.ST_Default_Data()
|
||||
modelLib.ST_SaveFileData() -- Save Defaults
|
||||
end
|
||||
menuDataChanged = false
|
||||
currAircraftType = MENU_DATA[MEMU_VAR.AIRCRAFT_TYPE]
|
||||
currWingType = MENU_DATA[MEMU_VAR.WING_TYPE]
|
||||
currTailType = MENU_DATA[MEMU_VAR.TAIL_TYPE]
|
||||
|
||||
local ctx = menuLib.DSM_Context
|
||||
ctx.Phase = PHASE.RX_VERSION
|
||||
end
|
||||
|
||||
local function ST_Done()
|
||||
local ctx = menuLib.DSM_Context
|
||||
ctx.Phase = PHASE.EXIT_DONE
|
||||
end
|
||||
|
||||
|
||||
return { init=ST_Init, run=ST_SendReceive, done=ST_Done }
|
||||
1596
Lua_scripts/DSMLIB/DsmSimMenuLib.lua
Normal file
10
Lua_scripts/DSMLIB/MIN_msg_fwdp_en.txt
Normal file
@@ -0,0 +1,10 @@
|
||||
-- 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 |0x0190|DONT USE: Relearn Servo Settings
|
||||
T |0x020D|DONT USE: First Time SAFE Setup
|
||||
BIN
Lua_scripts/DSMLIB/img/h_rx_pos_1.png
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
BIN
Lua_scripts/DSMLIB/img/h_rx_pos_2.png
Normal file
|
After Width: | Height: | Size: 862 B |
BIN
Lua_scripts/DSMLIB/img/h_rx_pos_3.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
Lua_scripts/DSMLIB/img/h_rx_pos_4.png
Normal file
|
After Width: | Height: | Size: 866 B |
BIN
Lua_scripts/DSMLIB/img/h_rx_pos_5.png
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
BIN
Lua_scripts/DSMLIB/img/h_rx_pos_6.png
Normal file
|
After Width: | Height: | Size: 880 B |
BIN
Lua_scripts/DSMLIB/img/h_rx_pos_7.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
Lua_scripts/DSMLIB/img/h_rx_pos_8.png
Normal file
|
After Width: | Height: | Size: 863 B |
BIN
Lua_scripts/DSMLIB/img/h_swp_3_120.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
Lua_scripts/DSMLIB/img/h_swp_3_120inv.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
Lua_scripts/DSMLIB/img/h_swp_3_135.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
Lua_scripts/DSMLIB/img/h_swp_3_135inv.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
Lua_scripts/DSMLIB/img/h_swp_3_140.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
Lua_scripts/DSMLIB/img/h_swp_3_140inv.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
Lua_scripts/DSMLIB/img/h_swp_3_90.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
Lua_scripts/DSMLIB/img/h_swp_3_90inv.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
Lua_scripts/DSMLIB/img/h_swp_norm.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
Lua_scripts/DSMLIB/img/rx_pos_1.png
Normal file
|
After Width: | Height: | Size: 2.7 KiB |
BIN
Lua_scripts/DSMLIB/img/rx_pos_10.png
Normal file
|
After Width: | Height: | Size: 2.7 KiB |
BIN
Lua_scripts/DSMLIB/img/rx_pos_11.png
Normal file
|
After Width: | Height: | Size: 3.0 KiB |
BIN
Lua_scripts/DSMLIB/img/rx_pos_12.png
Normal file
|
After Width: | Height: | Size: 2.7 KiB |
BIN
Lua_scripts/DSMLIB/img/rx_pos_13.png
Normal file
|
After Width: | Height: | Size: 2.6 KiB |
BIN
Lua_scripts/DSMLIB/img/rx_pos_14.png
Normal file
|
After Width: | Height: | Size: 2.7 KiB |
BIN
Lua_scripts/DSMLIB/img/rx_pos_15.png
Normal file
|
After Width: | Height: | Size: 2.9 KiB |
BIN
Lua_scripts/DSMLIB/img/rx_pos_16.png
Normal file
|
After Width: | Height: | Size: 2.7 KiB |
BIN
Lua_scripts/DSMLIB/img/rx_pos_17.png
Normal file
|
After Width: | Height: | Size: 2.6 KiB |
BIN
Lua_scripts/DSMLIB/img/rx_pos_18.png
Normal file
|
After Width: | Height: | Size: 2.6 KiB |
BIN
Lua_scripts/DSMLIB/img/rx_pos_19.png
Normal file
|
After Width: | Height: | Size: 2.6 KiB |
BIN
Lua_scripts/DSMLIB/img/rx_pos_2.png
Normal file
|
After Width: | Height: | Size: 2.5 KiB |
BIN
Lua_scripts/DSMLIB/img/rx_pos_20.png
Normal file
|
After Width: | Height: | Size: 2.6 KiB |
BIN
Lua_scripts/DSMLIB/img/rx_pos_21.png
Normal file
|
After Width: | Height: | Size: 2.7 KiB |
BIN
Lua_scripts/DSMLIB/img/rx_pos_22.png
Normal file
|
After Width: | Height: | Size: 2.6 KiB |
BIN
Lua_scripts/DSMLIB/img/rx_pos_23.png
Normal file
|
After Width: | Height: | Size: 2.7 KiB |
BIN
Lua_scripts/DSMLIB/img/rx_pos_24.png
Normal file
|
After Width: | Height: | Size: 2.7 KiB |
BIN
Lua_scripts/DSMLIB/img/rx_pos_25.png
Normal file
|
After Width: | Height: | Size: 2.6 KiB |
BIN
Lua_scripts/DSMLIB/img/rx_pos_3.png
Normal file
|
After Width: | Height: | Size: 2.9 KiB |
BIN
Lua_scripts/DSMLIB/img/rx_pos_4.png
Normal file
|
After Width: | Height: | Size: 2.5 KiB |
BIN
Lua_scripts/DSMLIB/img/rx_pos_5.png
Normal file
|
After Width: | Height: | Size: 2.5 KiB |
BIN
Lua_scripts/DSMLIB/img/rx_pos_6.png
Normal file
|
After Width: | Height: | Size: 2.5 KiB |
BIN
Lua_scripts/DSMLIB/img/rx_pos_7.png
Normal file
|
After Width: | Height: | Size: 2.9 KiB |
BIN
Lua_scripts/DSMLIB/img/rx_pos_8.png
Normal file
|
After Width: | Height: | Size: 2.5 KiB |
BIN
Lua_scripts/DSMLIB/img/rx_pos_9.png
Normal file
|
After Width: | Height: | Size: 2.8 KiB |
BIN
Lua_scripts/DSMLIB/img/tt_1rud.png
Normal file
|
After Width: | Height: | Size: 728 B |
BIN
Lua_scripts/DSMLIB/img/tt_1rud_1ele.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
Lua_scripts/DSMLIB/img/tt_1rud_2ele.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
Lua_scripts/DSMLIB/img/tt_2rud_1ele.png
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
BIN
Lua_scripts/DSMLIB/img/tt_2rud_2ele.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
Lua_scripts/DSMLIB/img/tt_taileron.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
Lua_scripts/DSMLIB/img/tt_taileron2.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
Lua_scripts/DSMLIB/img/tt_vtail.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
Lua_scripts/DSMLIB/img/wt_1ail.png
Normal file
|
After Width: | Height: | Size: 721 B |
BIN
Lua_scripts/DSMLIB/img/wt_1ail_1flp.png
Normal file
|
After Width: | Height: | Size: 803 B |
BIN
Lua_scripts/DSMLIB/img/wt_2ail.png
Normal file
|
After Width: | Height: | Size: 679 B |
BIN
Lua_scripts/DSMLIB/img/wt_2ail_1flp.png
Normal file
|
After Width: | Height: | Size: 755 B |
BIN
Lua_scripts/DSMLIB/img/wt_2ail_2flp.png
Normal file
|
After Width: | Height: | Size: 817 B |
BIN
Lua_scripts/DSMLIB/img/wt_elevon.png
Normal file
|
After Width: | Height: | Size: 1.0 KiB |