gpio_badge.c 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. #include <furi.h>
  2. #include <gui/gui.h>
  3. const GpioPin* const pin_leds[] = {
  4. &gpio_ext_pa7,
  5. &gpio_ext_pa6,
  6. &gpio_ext_pa4,
  7. &gpio_ext_pb3,
  8. &gpio_ext_pb2,
  9. &gpio_ext_pc3,
  10. &gpio_swclk,
  11. &gpio_swdio,
  12. &gpio_usart_tx,
  13. &gpio_usart_rx,
  14. &gpio_ext_pc1,
  15. &gpio_ext_pc0,
  16. &gpio_ibutton,
  17. };
  18. uint32_t speed = 50;
  19. typedef enum {
  20. EffectIdLRL,
  21. EffectIdBothLRL,
  22. EffectIdLR,
  23. EffectIdCount // Make sure this is last
  24. } EffectId;
  25. EffectId effect = EffectIdLR;
  26. bool animating = true;
  27. int lri = 0;
  28. #define MAX_EFFECT 1
  29. const GpioPin* const pin_back = &gpio_button_back;
  30. static void my_draw_callback(Canvas* canvas, void* context) {
  31. UNUSED(context);
  32. canvas_set_font(canvas, FontPrimary);
  33. canvas_draw_str(canvas, 5, 8, "GPIO BADGE");
  34. canvas_draw_str(canvas, 5, 28, "Left/Right : Speed");
  35. canvas_draw_str(canvas, 5, 38, "Up/Down : Effect");
  36. }
  37. static void my_input_callback(InputEvent* event, void* context) {
  38. UNUSED(context);
  39. if(event->type == InputTypePress) {
  40. uint32_t last_speed = speed;
  41. if(event->key == InputKeyLeft) {
  42. speed *= 0.9;
  43. if(speed < 1) {
  44. speed = 1;
  45. }
  46. } else if(event->key == InputKeyRight) {
  47. speed *= 1.1;
  48. if(speed < last_speed + 5) {
  49. speed += 5;
  50. }
  51. } else if(event->key == InputKeyUp) {
  52. if(effect-- == 0) {
  53. animating = true;
  54. effect = EffectIdCount - 1;
  55. }
  56. } else if(event->key == InputKeyDown) {
  57. animating = true;
  58. if(++effect == EffectIdCount) {
  59. effect = 0;
  60. }
  61. } else if(event->key == InputKeyOk) {
  62. animating = !animating;
  63. }
  64. }
  65. }
  66. void do_effect_lrl() {
  67. int i = 0;
  68. int d = 1;
  69. for(size_t c = 0; c < COUNT_OF(pin_leds) * 2; c++) {
  70. furi_hal_gpio_write(pin_leds[i], true);
  71. furi_delay_ms(speed);
  72. furi_hal_gpio_write(pin_leds[i], false);
  73. i += d;
  74. if(i == COUNT_OF(pin_leds) || i < 0) {
  75. if(i < 1)
  76. i++;
  77. else
  78. i--;
  79. d = d * -1;
  80. }
  81. if(furi_hal_gpio_read(pin_back) == false || effect != EffectIdLRL) {
  82. break;
  83. }
  84. }
  85. }
  86. void do_effect_both_lrl() {
  87. int i = 0;
  88. int d = 1;
  89. for(size_t c = 0; c < COUNT_OF(pin_leds) * 2; c++) {
  90. furi_hal_gpio_write(pin_leds[i], true);
  91. furi_hal_gpio_write(pin_leds[COUNT_OF(pin_leds) - (i + 1)], true);
  92. furi_delay_ms(speed);
  93. furi_hal_gpio_write(pin_leds[i], false);
  94. furi_hal_gpio_write(pin_leds[COUNT_OF(pin_leds) - (i + 1)], false);
  95. i += d;
  96. if(i == COUNT_OF(pin_leds) || i < 0) {
  97. if(i < 1)
  98. i++;
  99. else
  100. i--;
  101. d = d * -1;
  102. }
  103. if(furi_hal_gpio_read(pin_back) == false || effect != EffectIdBothLRL) {
  104. break;
  105. }
  106. }
  107. }
  108. void do_effect_lr() {
  109. for(size_t c = 0; c < COUNT_OF(pin_leds) * 2; c++) {
  110. furi_hal_gpio_write(pin_leds[lri], true);
  111. furi_delay_ms(speed);
  112. furi_hal_gpio_write(pin_leds[lri], false);
  113. if(animating) {
  114. lri++;
  115. }
  116. if(lri == COUNT_OF(pin_leds)) {
  117. lri = 0;
  118. }
  119. if(furi_hal_gpio_read(pin_back) == false || effect != EffectIdLR) {
  120. break;
  121. }
  122. }
  123. }
  124. void do_effects() {
  125. while(furi_hal_gpio_read(pin_back)) {
  126. switch(effect) {
  127. case EffectIdLRL:
  128. do_effect_lrl();
  129. break;
  130. case EffectIdBothLRL:
  131. do_effect_both_lrl();
  132. break;
  133. default:
  134. do_effect_lr();
  135. break;
  136. }
  137. }
  138. }
  139. int gpio_diag_lights_app(void* p) {
  140. UNUSED(p);
  141. Gui* gui = furi_record_open(RECORD_GUI);
  142. ViewPort* view_port = view_port_alloc();
  143. view_port_draw_callback_set(view_port, my_draw_callback, NULL);
  144. view_port_input_callback_set(view_port, my_input_callback, NULL);
  145. gui_add_view_port(gui, view_port, GuiLayerFullscreen);
  146. for(size_t i = 0; i < COUNT_OF(pin_leds); i++) {
  147. furi_hal_gpio_init_simple(pin_leds[i], GpioModeOutputPushPull);
  148. }
  149. do_effects();
  150. // Typically when a pin is no longer in use, it is set to analog mode.
  151. // but we need to use open drain for the 1Wire pin.
  152. for(size_t i = 0; i < COUNT_OF(pin_leds); i++) {
  153. furi_hal_gpio_init_simple(pin_leds[i], GpioModeAnalog);
  154. }
  155. furi_hal_gpio_init_simple(&gpio_ibutton, GpioModeOutputOpenDrain);
  156. // Remove the directions from the screen.
  157. gui_remove_view_port(gui, view_port);
  158. return 0;
  159. }