Guest User

Untitled

a guest
Jul 16th, 2018
58
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 9.27 KB | None | 0 0
  1. // ex_counter.nxc
  2. // Simulation of a digital counter odometer-like display. The
  3. // counter digits are displayed in seven-segment form such as
  4. // used in many electronic instrument displays.
  5.  
  6. // Right button increments count.
  7. // Left button decrements count.
  8. // Center button zeros count.
  9. // Gray button halts and exits program.
  10.  
  11. // Buttons must be bumped (pressed and released) for operations to
  12. // execute.
  13.  
  14. // DIGITS determines how many digits the counter maintains and
  15. // displays. It should no bigger than 5. If not set at compile
  16. // time, it will default to 3.
  17. #ifndef DIGITS
  18. #define DIGITS 3
  19. #endif
  20.  
  21. // Counter globals
  22. mutex counter_mutex;
  23. bool counter_changed;
  24. int counter[DIGITS];
  25.  
  26. // Section defining 7-segment display functions
  27.  
  28. // Dimensions of the segments of a 7-segment digit
  29. #define HRZ_W 8
  30. #define HRZ_H 2
  31. #define VRT_W 2
  32. #define VRT_H 8
  33.  
  34. // Dimensions of the spaces occupied by the segments.
  35. #define HRZ_CELL_W (HRZ_W + 1)
  36. #define HRZ_CELL_H (HRZ_H + 1)
  37. #define VRT_CELL_W (VRT_W + 1)
  38. #define VRT_CELL_H (VRT_H + 1)
  39.  
  40. // Constants used to position digits on the display.
  41. #define DIGIT_WIDTH (HRZ_CELL_W + 2 * VRT_CELL_W + 2)
  42. #define COUNTER_WIDTH (DIGIT_WIDTH * DIGITS)
  43. #define X_OFFSET ((100 - COUNTER_WIDTH) / 2)
  44. #define DIGIT_HEIGHT (3 * HRZ_CELL_H + 2 * VRT_CELL_H)
  45. #define Y_OFFSET ((64 - DIGIT_HEIGHT) / 2)
  46.  
  47. // Draw a horizontal segment at screen location (x, y), which is at
  48. // the lower-left corner of the segment.
  49. inline void hrz_segment_out(int x, int y)
  50. {
  51. RectOut(x, y, HRZ_W, HRZ_H, DRAW_OPT_FILL_SHAPE);
  52. }
  53.  
  54. // Draw a vertical segment at screen location (x, y), which is at
  55. // the lower-left corner of the segment.
  56. inline void vrt_segment_out(int x, int y)
  57. {
  58. RectOut(x, y, VRT_W, VRT_H, DRAW_OPT_FILL_SHAPE);
  59. }
  60.  
  61. /*
  62. aaa
  63. e b
  64. e b
  65. e b
  66. ggg the segments of a 7-segment display
  67. f c
  68. f c
  69. f c
  70. ddd
  71.  
  72. The reference point (ref_x, ref_y) for positioning a 7-segment
  73. digit on the NXT screen is at its lower right corner.
  74. */
  75.  
  76. // Draw segment aaa at its proper offset from the reference point
  77. // (ref_x, ref_y).
  78. inline void seg_a_out(int ref_x, int ref_y)
  79. {
  80. const int dx = VRT_CELL_W;
  81. const int dy = 2 * HRZ_CELL_H + 2 * VRT_CELL_H;
  82. hrz_segment_out(ref_x + dx, ref_y + dy);
  83. }
  84.  
  85. // Draw segment bbb at its proper offset from the reference point
  86. // (ref_x, ref_y).
  87. inline void seg_b_out(int ref_x, int ref_y)
  88. {
  89. const int dx = VRT_CELL_W + HRZ_CELL_W;
  90. const int dy = 2 * HRZ_CELL_H + VRT_CELL_H;
  91. vrt_segment_out(ref_x + dx, ref_y + dy);
  92. }
  93.  
  94. // Draw segment ccc at its proper offset from the reference point
  95. // (ref_x, ref_y).
  96. inline void seg_c_out(int ref_x, int ref_y)
  97. {
  98. const int dx = VRT_CELL_W + HRZ_CELL_W;
  99. const int dy = HRZ_CELL_H;
  100. vrt_segment_out(ref_x + dx, ref_y + dy);
  101. }
  102.  
  103. // Draw segment ddd at its proper offset from the reference point
  104. // (ref_x, ref_y).
  105. inline void seg_d_out(int ref_x, int ref_y)
  106. {
  107. const int dx = VRT_CELL_W;
  108. const int dy = 0;
  109. hrz_segment_out(ref_x + dx, ref_y + dy);
  110. }
  111.  
  112. // Draw segment eee at its proper offset from the reference point
  113. // (ref_x, ref_y).
  114. inline void seg_e_out(int ref_x, int ref_y)
  115. {
  116. const int dx = 0;
  117. const int dy = 2 * HRZ_CELL_H + VRT_CELL_H;
  118. vrt_segment_out(ref_x + dx, ref_y + dy);
  119. }
  120.  
  121. // Draw segment fff at its proper offset from the reference point
  122. // (ref_x, ref_y).
  123. inline void seg_f_out(int ref_x, int ref_y)
  124. {
  125. const int dx = 0;
  126. const int dy = HRZ_CELL_H;
  127. vrt_segment_out(ref_x + dx, ref_y + dy);
  128. }
  129.  
  130. // Draw segment ggg at its proper offset from the reference point
  131. // (ref_x, ref_y).
  132. inline void seg_g_out(int ref_x, int ref_y)
  133. {
  134. const int dx = VRT_CELL_W;
  135. const int dy = HRZ_CELL_H + VRT_CELL_H;
  136. hrz_segment_out(ref_x + dx, ref_y + dy);
  137. }
  138.  
  139. // 7-segment numbers on the display are built up from various
  140. // combinations of horizontal and vertical segments.
  141.  
  142. // Draw zero at reference point (x, Y_OFFSET).
  143. void digit_0(int x)
  144. {
  145. seg_a_out(x, Y_OFFSET);
  146. seg_b_out(x, Y_OFFSET);
  147. seg_c_out(x, Y_OFFSET);
  148. seg_d_out(x, Y_OFFSET);
  149. seg_e_out(x, Y_OFFSET);
  150. seg_f_out(x, Y_OFFSET);
  151. }
  152.  
  153. // Draw one at reference point (x, Y_OFFSET).
  154. void digit_1(int x)
  155. {
  156. seg_b_out(x, Y_OFFSET);
  157. seg_c_out(x, Y_OFFSET);
  158. }
  159.  
  160. // Draw twp at reference point (x, Y_OFFSET).
  161. void digit_2(int x)
  162. {
  163. seg_a_out(x, Y_OFFSET);
  164. seg_b_out(x, Y_OFFSET);
  165. seg_d_out(x, Y_OFFSET);
  166. seg_f_out(x, Y_OFFSET);
  167. seg_g_out(x, Y_OFFSET);
  168. }
  169.  
  170. // Draw three at reference point (x, Y_OFFSET).
  171. void digit_3(int x)
  172. {
  173. seg_a_out(x, Y_OFFSET);
  174. seg_b_out(x, Y_OFFSET);
  175. seg_c_out(x, Y_OFFSET);
  176. seg_d_out(x, Y_OFFSET);
  177. seg_g_out(x, Y_OFFSET);
  178. }
  179.  
  180. // Draw four at reference point (x, Y_OFFSET).
  181. void digit_4(int x)
  182. {
  183. seg_b_out(x, Y_OFFSET);
  184. seg_c_out(x, Y_OFFSET);
  185. seg_e_out(x, Y_OFFSET);
  186. seg_g_out(x, Y_OFFSET);
  187. }
  188.  
  189. // Draw five at reference point (x, Y_OFFSET).
  190. void digit_5(int x)
  191. {
  192. seg_a_out(x, Y_OFFSET);
  193. seg_c_out(x, Y_OFFSET);
  194. seg_d_out(x, Y_OFFSET);
  195. seg_e_out(x, Y_OFFSET);
  196. seg_g_out(x, Y_OFFSET);
  197. }
  198.  
  199. // Draw six at reference point (x, Y_OFFSET).
  200. void digit_6(int x)
  201. {
  202. seg_a_out(x, Y_OFFSET);
  203. seg_c_out(x, Y_OFFSET);
  204. seg_d_out(x, Y_OFFSET);
  205. seg_e_out(x, Y_OFFSET);
  206. seg_f_out(x, Y_OFFSET);
  207. seg_g_out(x, Y_OFFSET);
  208. }
  209.  
  210. // Draw seven at reference point (x, Y_OFFSET).
  211. void digit_7(int x)
  212. {
  213. seg_a_out(x, Y_OFFSET);
  214. seg_b_out(x, Y_OFFSET);
  215. seg_c_out(x, Y_OFFSET);
  216. seg_e_out(x, Y_OFFSET);
  217. }
  218.  
  219. // Draw eight at reference point (x, Y_OFFSET).
  220. void digit_8(int x)
  221. {
  222. seg_a_out(x, Y_OFFSET);
  223. seg_b_out(x, Y_OFFSET);
  224. seg_c_out(x, Y_OFFSET);
  225. seg_d_out(x, Y_OFFSET);
  226. seg_e_out(x, Y_OFFSET);
  227. seg_f_out(x, Y_OFFSET);
  228. seg_g_out(x, Y_OFFSET);
  229. }
  230.  
  231. // Draw nine at reference point (x, Y_OFFSET).
  232. void digit_9(int x)
  233. {
  234. seg_a_out(x, Y_OFFSET);
  235. seg_b_out(x, Y_OFFSET);
  236. seg_c_out(x, Y_OFFSET);
  237. seg_d_out(x, Y_OFFSET);
  238. seg_e_out(x, Y_OFFSET);
  239. seg_g_out(x, Y_OFFSET);
  240. }
  241.  
  242. // Given the digit place of digit, return its horizontal offset on
  243. // the NXT screen. The place of a digit is its index in the counter
  244. // array.
  245. int offset(int place)
  246. {
  247. return X_OFFSET + (DIGITS - place - 1) * DIGIT_WIDTH;
  248. }
  249.  
  250. // Section defining counter control tasks
  251.  
  252. // Given a button's ID number, return true if that button has been
  253. // bumped. Otherwise return false.
  254. bool button_bumped(const byte btn)
  255. {
  256. bool result = false;
  257. if (ButtonPressed(btn, false))
  258. {
  259. while (ButtonPressed(btn, true));
  260. PlayFile("! Click.rso");
  261. result = true;
  262. }
  263. return result;
  264. }
  265.  
  266. // When the right button is bumped, increment the counter. The
  267. // for-loop performs carry propagation.
  268. task increment()
  269. {
  270. byte carry;
  271. while(true)
  272. {
  273. Acquire(counter_mutex);
  274. if ((! counter_changed) && button_bumped(BTNRIGHT))
  275. {
  276. carry = 1;
  277. for (int i = 0; (carry == 1) && (i < DIGITS); ++i)
  278. {
  279. int d = counter[i] + carry;
  280. if (d > 9)
  281. {
  282. d = 0;
  283. carry = 1;
  284. }
  285. else carry = 0;
  286. counter[i] = d;
  287. }
  288. counter_changed = true;
  289. }
  290. Release(counter_mutex);
  291. Yield();
  292. }
  293. }
  294.  
  295. // When the left button is bumped, decrement the counter. The
  296. // for-loop performs borrow propagation.
  297. task decrement()
  298. {
  299. byte borrow;
  300. while(true)
  301. {
  302. Acquire(counter_mutex);
  303. if ((! counter_changed) && button_bumped(BTNLEFT))
  304. {
  305. borrow = 1;
  306. for (int i = 0; (borrow == 1) && (i < DIGITS); ++i)
  307. {
  308. int d = counter[i] - borrow;
  309. if (d < 0)
  310. {
  311. d = 9;
  312. borrow = 1;
  313. }
  314. else borrow = 0;
  315. counter[i] = d;
  316. }
  317. counter_changed = true;
  318. }
  319. Release(counter_mutex);
  320. Yield();
  321. }
  322. }
  323.  
  324. // When the center button is bumped, zero the counter.
  325. task zero()
  326. {
  327. while(true)
  328. {
  329. Acquire(counter_mutex);
  330. if ((! counter_changed) && button_bumped(BTNCENTER))
  331. {
  332. ArrayInit(counter, 0, DIGITS);
  333. counter_changed = true;
  334. }
  335. Release(counter_mutex);
  336. Yield();
  337. }
  338. }
  339.  
  340. // When the count has changed, update the NXT screen with the new
  341. // count.
  342. task show_count()
  343. {
  344. while(true)
  345. {
  346. Acquire(counter_mutex);
  347. if (counter_changed)
  348. {
  349. ClearScreen();
  350. for (int i = 0; i < DIGITS; ++i)
  351. {
  352. switch (counter[i])
  353. {
  354. case 0:
  355. digit_0(offset(i));
  356. break;
  357. case 1:
  358. digit_1(offset(i));
  359. break;
  360. case 2:
  361. digit_2(offset(i));
  362. break;
  363. case 3:
  364. digit_3(offset(i));
  365. break;
  366. case 4:
  367. digit_4(offset(i));
  368. break;
  369. case 5:
  370. digit_5(offset(i));
  371. break;
  372. case 6:
  373. digit_6(offset(i));
  374. break;
  375. case 7:
  376. digit_7(offset(i));
  377. break;
  378. case 8:
  379. digit_8(offset(i));
  380. break;
  381. case 9:
  382. digit_9(offset(i));
  383. break;
  384. }
  385. }
  386. counter_changed = false;
  387. }
  388. Release(counter_mutex);
  389. Yield();
  390. }
  391. }
  392.  
  393. // Section defining start-up code.
  394.  
  395. task main()
  396. {
  397. Precedes(show_count, zero, increment, decrement);
  398. counter = 0;
  399. counter_changed = true;
  400. }
Add Comment
Please, Sign In to add comment