scr-deck.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781
  1. /*
  2. * Copyright (C) 2023 Daniele Lacamera <root@danielinux.net>
  3. *
  4. * This program is free software: you can redistribute it and/or modify
  5. * it under the terms of the GNU Lesser General Public License as published by
  6. * the Free Software Foundation, either version 3 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU Lesser General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU Lesser General Public License
  15. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  16. */
  17. #include <stdint.h>
  18. #include <stddef.h>
  19. #include "ui.h"
  20. #include "button.h"
  21. #include <stdio.h>
  22. #include <string.h>
  23. #include <stdint.h>
  24. #include "ksp-serial.h"
  25. #include "led.h"
  26. #include "adc.h"
  27. #include <math.h>
  28. #include "arm_math.h"
  29. #include "ui.h"
  30. #include "trig.h"
  31. #define ROLL_CALIB (30)
  32. #define PITCH_CALIB (0)
  33. #define M_PI_INT 3
  34. const char main_deck_name[] = "Main Deck";
  35. static void main_deck_draw(void);
  36. static void main_deck_run(uint32_t ev, void *arg);
  37. static char _soi_target[20];
  38. static int vdata_valid = 0;
  39. static int show_pitch_roll_yaw = 0;
  40. static char *soi_target(uint8_t SOI)
  41. {
  42. switch (SOI) {
  43. case 100:
  44. strcpy(_soi_target, "Kerbol");
  45. break;
  46. case 110:
  47. strcpy(_soi_target, "Moho");
  48. break;
  49. case 120:
  50. strcpy(_soi_target, "Eve");
  51. break;
  52. case 121:
  53. strcpy(_soi_target, "Gilly");
  54. break;
  55. case 130:
  56. strcpy(_soi_target, "Kerbin");
  57. break;
  58. case 131:
  59. strcpy(_soi_target, "Mun");
  60. break;
  61. case 132:
  62. strcpy(_soi_target, "Minmus");
  63. break;
  64. case 140:
  65. strcpy(_soi_target, "Duna");
  66. break;
  67. case 141:
  68. strcpy(_soi_target, "Ike");
  69. break;
  70. case 150:
  71. strcpy(_soi_target, "Dres");
  72. break;
  73. case 160:
  74. strcpy(_soi_target, "Jool");
  75. break;
  76. case 161:
  77. strcpy(_soi_target, "Laythe");
  78. break;
  79. case 162:
  80. strcpy(_soi_target, "Vall");
  81. break;
  82. case 163:
  83. strcpy(_soi_target, "Tylo");
  84. break;
  85. case 164:
  86. strcpy(_soi_target, "Bop");
  87. break;
  88. case 165:
  89. strcpy(_soi_target, "Pol");
  90. break;
  91. case 170:
  92. strcpy(_soi_target, "Eloo");
  93. break;
  94. default:
  95. strcpy(_soi_target, "Unknown");
  96. }
  97. return _soi_target;
  98. }
  99. static void main_deck_init(void)
  100. {
  101. }
  102. struct screen main_deck_screen = {
  103. .draw = main_deck_draw,
  104. .name = main_deck_name
  105. };
  106. struct task main_deck_task = {
  107. .init = main_deck_init,
  108. .run = main_deck_run,
  109. .events = EV_BUTTON | EV_HEARTBEAT | EV_VESSELDATA,
  110. .screen = &main_deck_screen,
  111. .name = main_deck_name
  112. };
  113. static char * _float_to_str(float x, char *p) {
  114. char *s = p + 20; // go to end of buffer
  115. uint16_t decimals; // variable to store the decimals
  116. int units; // variable to store the units (part to left of decimal place)
  117. memset(p, ' ', 20);
  118. if (x < 0.0) { // take care of negative numbers
  119. decimals = (int)(x * -100) % 100; // make 1000 for 3 decimals etc.
  120. units = (int)(-1 * x);
  121. } else { // positive numbers
  122. decimals = (int)(x * 100) % 100;
  123. units = (int)x;
  124. }
  125. *--s = (decimals % 10) + '0';
  126. decimals /= 10; // repeat for as many decimal places as you need
  127. *--s = (decimals % 10) + '0';
  128. *--s = '.';
  129. while (units > 0) {
  130. *--s = (units % 10) + '0';
  131. units /= 10;
  132. }
  133. if (x < 0) *--s = '-'; // unary minus sign for negative numbers
  134. return s;
  135. }
  136. float approx_sqrt(float x) {
  137. float guess = x / 2.0;
  138. float prev_guess;
  139. float error = 1e-3; // set desired level of accuracy here
  140. do {
  141. prev_guess = guess;
  142. guess = (guess + x / guess) / 2.0;
  143. } while (fabs(guess - prev_guess) > error);
  144. return guess;
  145. }
  146. #ifndef PI
  147. #define PI 3.14159265
  148. #endif
  149. void draw_circle(int x, int y, int radius, uint8_t color)
  150. {
  151. int i, j;
  152. uint8_t *screen = ui_get_screen(0);
  153. int x0 = x - 10;
  154. for (i = x - radius; i <= x + radius; i++) {
  155. for (j = y - radius; j <= y + radius; j++) {
  156. if ((i - x) * (i - x) + (j - y) * (j - y) <= radius * radius) {
  157. ui_draw_h_segment(0, color, i, j, 1);
  158. }
  159. }
  160. }
  161. }
  162. void ui_draw_circle_slice(uint32_t x, uint32_t y, uint32_t r, int alpha, int beta, uint8_t color) {
  163. int i, j;
  164. uint32_t start, end;
  165. int cx = x;
  166. int cy = y;
  167. alpha += 90;
  168. beta += 90;
  169. if (alpha >= 360)
  170. alpha-=360;
  171. if (beta >= 360)
  172. beta -= 360;
  173. if (alpha < 0)
  174. alpha += 360;
  175. if (beta < 0)
  176. beta += 360;
  177. ui_draw_h_segment(0, color, x-1, y, 3);
  178. if (alpha < beta) {
  179. for (j = 0; j < r; j++) {
  180. for (i = alpha; i < beta; i++) {
  181. int px = cx + (int)(j * pcos(i));
  182. int py = cy + (int)(j * psin(i));
  183. if (px != cx || py != cy) {
  184. ui_draw_h_segment(0, color, px, py, 1);
  185. }
  186. }
  187. }
  188. } else {
  189. for (j = 0; j < r; j++) {
  190. for (i = alpha; i < 360; i++) {
  191. int px = cx + (int)(j * pcos(i));
  192. int py = cy + (int)(j * psin(i));
  193. if (px != cx || py != cy) {
  194. ui_draw_h_segment(0, color, px, py, 1);
  195. }
  196. }
  197. for (i = 0; i < beta; i++) {
  198. int px = cx + (int)(j * pcos(i));
  199. int py = cy + (int)(j * psin(i));
  200. if (px != cx || py != cy) {
  201. ui_draw_h_segment(0, color, px, py, 1);
  202. }
  203. }
  204. }
  205. }
  206. }
  207. #define ptan(a) psin(a)/pcos(a)
  208. void ui_draw_circle_sector(int x, int y, int r, int px, int py, int rho, int include_center) {
  209. int rho_norm = (0 - rho) + 90;
  210. int i, j;
  211. float m,q;
  212. uint8_t upc, downc;
  213. while (rho_norm < 0)
  214. rho_norm+=360;
  215. while (rho_norm >= 360)
  216. rho_norm -= 360;
  217. if ((rho == 0) || (rho == 180)) {
  218. upc = BROWN;
  219. downc = CYAN;
  220. if (rho == 180){
  221. upc = CYAN;
  222. downc = BROWN;
  223. }
  224. for (i = x - r; i <= x + r; i++) {
  225. for (j = y - r; j <= y + r; j++) {
  226. if ((i - x) * (i - x) + (j - y) * (j - y) <= r * r) {
  227. if (i > px)
  228. ui_draw_h_segment(0, upc, i, j, 1);
  229. else
  230. ui_draw_h_segment(0, downc, i, j, 1);
  231. }
  232. }
  233. }
  234. return;
  235. }
  236. if (rho > 0) {
  237. upc = CYAN;
  238. downc = BROWN;
  239. }else {
  240. upc = BROWN;
  241. downc = CYAN;
  242. }
  243. m = ptan(rho_norm);
  244. q = py - (m * px);
  245. for (i = x - r; i <= x + r; i++) {
  246. for (j = y - r; j <= y + r; j++) {
  247. if ((i - x) * (i - x) + (j - y) * (j - y) <= r * r) {
  248. if (j > (m * i + q))
  249. ui_draw_h_segment(0, upc, i, j, 1);
  250. else
  251. ui_draw_h_segment(0, downc, i, j, 1);
  252. }
  253. }
  254. }
  255. }
  256. void draw_navball(int x, int y, int pitch, int roll) {
  257. static int last_p_navball = -400;
  258. static int last_r_navball = - 400;
  259. if ((last_p_navball == pitch) && (last_r_navball == roll))
  260. return;
  261. ui_fill_area(0, BLACK, 150, 120, 320, 200);
  262. last_p_navball = pitch;
  263. last_r_navball = roll;
  264. if (pitch > 45 && pitch < 135) {
  265. draw_circle(x,y, 40, CYAN);
  266. } else if (pitch < -45 && pitch > -135) {
  267. draw_circle(x,y, 40, BROWN);
  268. } else if (pitch == 0) {
  269. int a = 0 - roll;
  270. int b = a + 180;
  271. ui_draw_circle_slice(x,y, 40, a, b, CYAN);
  272. ui_draw_circle_slice(x,y, 40, b, a, BROWN);
  273. } else {
  274. uint32_t px, py;
  275. px = x + 40 * psin(pitch) * pcos(roll);
  276. py = y - 40 * psin(pitch) * psin(roll);
  277. ui_draw_circle_sector(x, y, 40, px, py, roll, 1);
  278. }
  279. ui_draw_h_segment(0, ORANGE, x, y - 6, 5);
  280. ui_draw_h_segment(0, ORANGE, x, y + 1, 5);
  281. ui_draw_h_segment(0, ORANGE, x + 1, y - 2, 3);
  282. ui_draw_h_segment(0, ORANGE, x + 1, y + 1, 3);
  283. ui_draw_h_segment(0, ORANGE, x + 2, y, 1);
  284. }
  285. static void fuel_display(unsigned x, unsigned y, unsigned fuel, unsigned fuel_tot, char *label, int col)
  286. {
  287. unsigned tx = x;
  288. unsigned ty = y;
  289. unsigned i;
  290. unsigned pct;
  291. if (!vdata_valid)
  292. return;
  293. pct = fuel * 100 / fuel_tot;
  294. ui_fill_area(0, BLACK, tx - 10, ty + 100, tx + 8, ty + 110);
  295. ui_fill_area(0, BLACK, tx, ty, tx + 8, ty + 100);
  296. ui_text_at(0, col, tx - 10, ty + 100, label);
  297. for (i = 0; i < 100; i++) {
  298. if (pct < 10)
  299. col = RED;
  300. if (pct > i) {
  301. ui_fill_area(0, col, tx, ty + 100 - i, tx + 8, ty + 101 - i);
  302. }
  303. }
  304. }
  305. void avionics_display(controlPacket_t *cp)
  306. {
  307. uint32_t throttle, potr;
  308. int32_t pitch, yaw, roll;
  309. int i;
  310. int tx = 322;
  311. int ty = 150;
  312. /* Throttle display */
  313. pot_read(NULL, &potr);
  314. throttle = ((potr * 100) / 4096);
  315. ui_fill_area(0, BLACK, 245, 250, 332, 270);
  316. ui_fill_area(0, BLACK, tx, ty, tx + 10, ty + 100);
  317. ui_text_at(0, YELLOW, 245, 250, "Throttle:");
  318. ui_text_at(0, YELLOW, 265, 260, ui_printn((potr * 100) / 4096));
  319. for (i = 0; i < 100; i++) {
  320. int col = YELLOW;
  321. if (i > 90)
  322. col = RED;
  323. if (throttle > i) {
  324. ui_fill_area(0, col, tx, ty + 100 - i, tx + 10, ty + 101 - i);
  325. }
  326. }
  327. cp->Throttle = (potr * 1000) / 4096;
  328. if (show_pitch_roll_yaw) {
  329. unsigned px, py, rx,ry, yx, yy;
  330. int col = GREEN;
  331. int labelcol = GREEN;
  332. char label[15];
  333. px = 55;
  334. py = 70;
  335. rx = 2;
  336. ry = 75;
  337. yx = 2;
  338. yy = 110;
  339. ui_fill_area(0, 238, 2, 52, 103, 138);
  340. /* Pitch display */
  341. pitch = 0 - (cp->Pitch / 50);
  342. snprintf(label, 15, "P %d", pitch);
  343. ui_text_at(0, labelcol, px + 10, py + 20, label);
  344. ui_fill_area(0, 235, px, py, px + 10, py + 40);
  345. for (i = -20; i < 0; i++) {
  346. if (pitch < i) {
  347. ui_fill_area(0, col, px, py + 20 + i, px + 10, py + 21 + i);
  348. }
  349. }
  350. for (i = 0; i < 20; i++) {
  351. if (pitch > i) {
  352. ui_fill_area(0, col, px, py + 20 + i, px + 10, py + 21 + i);
  353. }
  354. }
  355. ui_fill_area(0, RED, px - 2, py + 20, px + 12, py + 21);
  356. /* Roll display */
  357. roll = (cp->Roll / 50);
  358. snprintf(label, 15, "R %d", roll);
  359. ui_text_at(0, labelcol, rx, ry - 10, label);
  360. ui_fill_area(0, 235, rx, ry, rx + 40, ry + 10);
  361. for (i = -20; i < 0; i++) {
  362. if (roll < i) {
  363. ui_fill_area(0, col, rx + 20 + i, ry, rx + 21 + i, ry + 10);
  364. }
  365. }
  366. for (i = 0; i < 20; i++) {
  367. if (roll > i) {
  368. ui_fill_area(0, col, rx + 20 + i, ry, rx + 21 + i, ry + 10);
  369. }
  370. }
  371. ui_fill_area(0, RED, rx + 20, ry - 2, rx + 21, ry + 12);
  372. /* Yaw display */
  373. yaw = (cp->Yaw / 50);
  374. snprintf(label, 15, "Y %d", yaw);
  375. ui_text_at(0, labelcol, yx, yy - 10, label);
  376. ui_fill_area(0, 235, yx, yy, yx + 40, yy + 10);
  377. for (i = -20; i < 0; i++) {
  378. if (yaw < i) {
  379. ui_fill_area(0, col, yx + 20 + i, yy, yx + 21 + i, yy + 10);
  380. }
  381. }
  382. for (i = 0; i < 20; i++) {
  383. if (yaw > i) {
  384. ui_fill_area(0, col, yx + 20 + i, yy, yx + 21 + i, yy + 10);
  385. }
  386. }
  387. ui_fill_area(0, RED, yx + 20, yy - 2, yx + 21, yy + 12);
  388. } else
  389. ui_fill_area(0, 235, 1, 51, 104, 138);
  390. }
  391. static void navi_display(void)
  392. {
  393. char Status[100] = "";
  394. char Points[100] = "";
  395. int ralt = (int)cur_vdata->RAlt;
  396. int i = 0;
  397. char hdg_bar[30] = "";
  398. int hdg_dec, hdg_ref;
  399. unsigned x_alt, y_alt;
  400. int vvi;
  401. uint8_t pointcolor;
  402. if (((int)cur_vdata->VVI == 0) && ((int)cur_vdata->RAlt < 10)) {
  403. strcpy(Status, "Landed at ");
  404. } else if ((int)cur_vdata->e != 0) {
  405. strcpy(Status, "Escaping from ");
  406. } else if ((int) cur_vdata->PE < 0) {
  407. strcpy(Status, "In flight over ");
  408. } else {
  409. strcpy(Status, "Orbiting ");
  410. }
  411. strcat(Status, soi_target(cur_vdata->SOINumber));
  412. if ((int)(cur_vdata->PE < 0)){
  413. snprintf(Points, 100, "Apo: %d, Peri: Negative", (int)(cur_vdata->AP));
  414. pointcolor = PURPLE;
  415. } else {
  416. snprintf(Points, 100, "Apo: %d, Peri: %d",
  417. (int)(cur_vdata->AP),
  418. (int)(cur_vdata->PE));
  419. pointcolor = CYAN;
  420. }
  421. ui_fill_area(0, BLACK, 140, 20, 380, 60);
  422. ui_text_at(0, WHITE, 150, 20, Status);
  423. ui_text_at(0, pointcolor, 150, 30, Points);
  424. /* Navball */
  425. draw_navball(160, 233, (int)cur_vdata->Pitch, (int)cur_vdata->Roll);
  426. /* Altimeter */
  427. x_alt = 105;
  428. y_alt = 99;
  429. ui_fill_area(0, DARKGREY, x_alt, y_alt, x_alt + 45, y_alt + 101);
  430. if (ralt < 100000) {
  431. ui_fill_area(0, BLACK, x_alt+45, y_alt, x_alt + 55, y_alt + 101);
  432. for (i = 0; i < 100; i+=10)
  433. ui_fill_area(0, DARKGREY, x_alt + 46, (y_alt + 99 - i), x_alt + 54, (y_alt + 101) - i);
  434. i = ralt / 1000;
  435. ui_fill_area(0, GREEN, x_alt + 45, (y_alt + 101) - i, x_alt + 55, (y_alt + 101));
  436. ui_fill_area(0, BLACK, x_alt, (y_alt + 90) - i, x_alt + 50, (y_alt + 100) - i);
  437. ui_text_at(0, WHITE, x_alt, (y_alt + 90) - i, ui_printn(ralt));
  438. ui_text_at(0, WHITE, x_alt + 40, (y_alt + 90) - i, "m");
  439. ui_fill_area(0, BRIGHT(GREEN), x_alt + 20, (y_alt + 101) - i, x_alt + 55, (y_alt + 102) - i);
  440. }
  441. ui_fill_area(0, WHITE, x_alt + 55, y_alt + 60, x_alt + 70, y_alt + 61);
  442. vvi = (int)(cur_vdata->VVI);
  443. if (vvi > 100)
  444. vvi = 100;
  445. if (vvi < -100)
  446. vvi = -100;
  447. if (vvi > 0) {
  448. ui_fill_area(0, BRIGHT(GREEN), x_alt+56, y_alt + 60 - (vvi / 4), x_alt +60, y_alt + 61);
  449. } else {
  450. ui_fill_area(0, BRIGHT(RED), x_alt+56, y_alt + 60, x_alt +60, (y_alt + 60) - (vvi / 4));
  451. }
  452. /* Flight Data */
  453. char pitch_s[6], roll_s[6], hdg_s[4] = "000";
  454. ui_fill_area(0, BLACK, 155, 100, 320, 120);
  455. ui_fill_area(0, BLACK, 222, 140, 246, 148);
  456. snprintf(hdg_s, 4, "%03d", (int)(cur_vdata->Heading));
  457. ui_text_at(0, WHITE, 222, 140, hdg_s);
  458. ui_text_at(0, GREEN, 205, 110, "SPD");
  459. ui_text_at(0, WHITE, 235, 110, ui_printn((int)(cur_vdata->IAS)));
  460. /* Heading bar */
  461. ui_fill_area(0, BLACK, 150, 200, 320, 220);
  462. hdg_ref = ((int)cur_vdata->Heading) - 10;
  463. if (hdg_ref < 0)
  464. hdg_ref += 360;
  465. for (i = 0; i < 20; i++) {
  466. if (((i + hdg_ref) % 10) == 9) {
  467. int hdg_pr = (hdg_ref + 1 + i) / 10 * 10;
  468. if (hdg_pr >= 360)
  469. hdg_pr -= 360;
  470. snprintf(hdg_bar + i, 4,"%03d", hdg_pr);
  471. i += 2;
  472. continue;
  473. }
  474. else if (((i + hdg_ref) % 5) == 0) {
  475. hdg_bar[i] = '|';
  476. } else {
  477. hdg_bar[i] = '.';
  478. }
  479. }
  480. hdg_bar[21] = '\0';
  481. ui_text_at(0, WHITE, 150, 200, " |");
  482. ui_text_at(0, WHITE, 150, 210, hdg_bar);
  483. }
  484. static int button = -1;
  485. #define BUTTON_THRESHOLD 2
  486. static void main_deck_run(uint32_t event, void *arg)
  487. {
  488. int32_t x, y;
  489. uint32_t torque;
  490. struct sample *s;
  491. int ts;
  492. int throttle = 0;
  493. int pitch = 0, roll = 0, yaw = 0;
  494. int main_ctrl = 0;
  495. static int sas = 0;
  496. static int rcs = 0;
  497. static int brk = 0;
  498. static int gear = 0;
  499. static int light = 0;
  500. static uint8_t navmode = 0;
  501. int i;
  502. char btn_str[6];
  503. int staging = 0;
  504. controlPacket_t cp = {};
  505. if (screen_get_focus() != &main_deck_screen)
  506. return;
  507. if (ui_menu_is_on()) {
  508. if (event & EV_BUTTON)
  509. ui_redraw(EV_BUTTON);
  510. return;
  511. }
  512. ts = input_detect_touch();
  513. if (ts == TS_TOUCH_NONE) {
  514. } else {
  515. event |= EV_BUTTON;
  516. button = 12;
  517. }
  518. if (event & EV_VESSELDATA) {
  519. static int ev_data_ctr = 0;
  520. if ((++ev_data_ctr == 10) || (vdata_valid == 0)) {
  521. brk = (cur_vdata->ActionGroups & (1 << 4)) >> 4;
  522. gear = (cur_vdata->ActionGroups & (1 << 3)) >> 3;
  523. light = (cur_vdata->ActionGroups & (1 << 2)) >> 2;
  524. rcs = (cur_vdata->ActionGroups & (1 << 6)) >> 6;
  525. sas = (cur_vdata->ActionGroups & (1 << 7)) >> 7;
  526. navmode = cur_vdata->NavballSASMode;
  527. ev_data_ctr = 0;
  528. }
  529. vdata_valid = 1;
  530. navi_display();
  531. clear_event(EV_VESSELDATA);
  532. }
  533. if (event & EV_BUTTON) {
  534. if (button < 0)
  535. button = ui_process_button_pressed();
  536. switch(button) {
  537. case 12: /* TS */
  538. show_pitch_roll_yaw = !!!show_pitch_roll_yaw;
  539. break;
  540. case BUTTON_DPADU:
  541. cp.Pitch = -1000;
  542. break;
  543. case BUTTON_DPADD:
  544. cp.Pitch = 1000;
  545. break;
  546. case BUTTON_DPADL:
  547. cp.Yaw = -1000;
  548. break;
  549. case BUTTON_DPADR:
  550. cp.Yaw = 1000;
  551. break;
  552. case 7:
  553. ui_menu(1);
  554. ui_redraw(EV_NONE);
  555. break;
  556. case 10:
  557. if (sas)
  558. navmode++;
  559. if ((navmode & 0xF) > 10) {
  560. navmode &= 0xF0;
  561. navmode |= 0x01;
  562. }
  563. break;
  564. case 8:
  565. if (vdata_valid)
  566. gear = !(((cur_vdata->ActionGroups & (1 << 3)) >> 3));
  567. break;
  568. case 9:
  569. if (vdata_valid)
  570. light = !light;
  571. break;
  572. case 5:
  573. if (vdata_valid)
  574. brk = !(((cur_vdata->ActionGroups & (1 << 4)) >> 4));
  575. break;
  576. case 4:
  577. staging++;
  578. break;
  579. }
  580. button = -1;
  581. clear_event(EV_BUTTON);
  582. }
  583. /* Sample joystick */
  584. joy_read(&x, &y);
  585. pot_read(&torque, NULL);
  586. x-=2048 + ROLL_CALIB;
  587. y-=2048 + PITCH_CALIB;
  588. x*=2000 * torque / 4096;
  589. y*=2000 * torque / 4096;
  590. x/=4096;
  591. y/=4096;
  592. if ((x > 20) || (x < -20))
  593. cp.Roll = x;
  594. else
  595. cp.Roll = 0;
  596. if ((y > 20) || (y < -20))
  597. cp.Pitch = y;
  598. else
  599. cp.Pitch = 0;
  600. avionics_display(&cp);
  601. if (vdata_valid) {
  602. fuel_display(370, 100, (int)(cur_vdata->LiquidFuel), (int)(cur_vdata->LiquidFuelTot), "LF", YELLOW );
  603. fuel_display(388, 100, (int)(cur_vdata->Oxidizer), (int)(cur_vdata->OxidizerTot), "Ox", CYAN);
  604. fuel_display(406, 100, (int)(cur_vdata->SolidFuel), (int)(cur_vdata->SolidFuelTot), "SF", GREY);
  605. fuel_display(424, 100, (int)(cur_vdata->ECharge), (int)(cur_vdata->EChargeTot), "el" , BRIGHT(GREEN));
  606. fuel_display(442, 100, (int)(cur_vdata->XenonGas), (int)(cur_vdata->XenonGasTot), "Xe" , PINK);
  607. if ((cur_vdata->ActionGroups & (1 << 1)) == (1 << 1))
  608. fuel_display(32, 150, (int)(cur_vdata->MonoProp), (int)(cur_vdata->MonoPropTot), "MP", BRIGHT(YELLOW));
  609. else
  610. ui_fill_area(0, DARKGREY, 20, 150, 50, 280);
  611. if ((cur_vdata->Density > 0)) {
  612. int dens = (int)(cur_vdata->Density * 100);
  613. if (dens > 100)
  614. dens = 100;
  615. fuel_display (50, 150, dens, 100, "At", 87);
  616. fuel_display (68, 150, (int)(cur_vdata->IntakeAir),(int)(cur_vdata->IntakeAirTot), "Ai", CYAN);
  617. }
  618. }
  619. /* Lamps */
  620. ui_fill_area(0, 242, 35, 0, 64, 27);
  621. ui_fill_area(0, light?58:233, 38, 0, 64, 24);
  622. ui_text_at (0, (light?BLACK:238), 38, 8, "LIG");
  623. ui_fill_area(0, 242, 65, 0, 94, 27);
  624. ui_fill_area(0, gear?28:233, 68, 0, 94, 24);
  625. ui_text_at (0, (gear?BLACK:238), 68, 8, "GEA");
  626. ui_fill_area(0, 242, 95, 0, 124, 27);
  627. ui_fill_area(0, brk?BLOOD:233, 98, 0, 124, 24);
  628. ui_text_at (0, (brk?WHITE:238), 98, 8, "(!)");
  629. /* Switches */
  630. sas = input_get_swr()?1:0;
  631. rcs = input_get_swl()?1:0;
  632. if (sas == 0) {
  633. navmode &= 0xF0;
  634. }
  635. ui_fill_area(0, 242, 447, 0, 474, 28);
  636. ui_fill_area(0, sas?122:233, 450, 0, 474, 24);
  637. ui_text_at (0, (sas?BLUE:238), 450, 8, "SAS");
  638. ui_fill_area(0, 242, 3, 0, 30, 28);
  639. ui_fill_area(0, rcs?GREEN:235, 6, 0, 30, 24);
  640. ui_text_at (0, rcs?BRIGHT(GREEN):238, 6, 8, "RCS");
  641. cp.id = 101;
  642. cp.NavBallSASMode = navmode;
  643. if (!rcs)
  644. staging = 0;
  645. if (vdata_valid) {
  646. cp.MainControls = ((sas << 7) | (rcs << 6) | (light << 5) | (gear << 4) | (brk << 3) | (staging << 0));
  647. ksp_serial_send(&cp, sizeof(cp));
  648. }
  649. if (sas)
  650. uled_on(4);
  651. else
  652. uled_off(4);
  653. if (rcs)
  654. uled_on(5);
  655. else
  656. uled_off(5);
  657. if(light)
  658. uled_on(0);
  659. else
  660. uled_off(0);
  661. if (gear)
  662. uled_on(1);
  663. else
  664. uled_off(1);
  665. if (brk)
  666. uled_on(2);
  667. else
  668. uled_off(2);
  669. }
  670. static void main_deck_draw(void)
  671. {
  672. int i;
  673. char btn_str[4] = "";
  674. /* background to foreground */
  675. ui_fill_area(0, DARKGREY, 0, 0, xres, yres);
  676. ui_fill_area(0, WHITE, 0, 50, 105, 140); /* Pitch panel */
  677. /* Logo & appname */
  678. //image_at(0, logo, 5, 4, logox, logoy);
  679. }
  680. void main_deck_setup(void)
  681. {
  682. register_task(&main_deck_task);
  683. register_screen(&main_deck_task, &main_deck_screen);
  684. }