flipper-zero-tutorials/gpio/gpio_7segment
2023-06-11 17:03:26 -05:00
..
application.fam appid must be lowercase in latest firmware 2023-06-11 17:03:26 -05:00
gpio_7segment_app.c Control 7-segment display with Flipper Zero 2023-02-21 11:45:07 -05:00
gpio_7segment.png Control 7-segment display with Flipper Zero 2023-02-21 11:45:07 -05:00
README.md Control 7-segment display with Flipper Zero 2023-02-21 11:45:07 -05:00

GPIO 7-Segment Output

Introduction

This is a GPIO push-pull output demo application for driving a 7-segment display on the Flipper Zero. The goal of this project is to show application developers how GPIO works for push-pull output. This project was derived from the \plugins\basic tutorial.

Installation Directions

This project is intended to be overlayed on top of an existing firmware repo.

  • Clone, Build & Deploy an existing flipper zero firmware repo. See this tutorial for updating firmware.
  • Copy the "gpio_7segment" folder to the \applications\plugins\gpio_7segment folder in your firmware.
  • Build & deploy the firmware. See this tutorial for updating firmware.
  • NOTE: You can also extract the gpio_output_demo.FAP from resources.tar file and use qFlipper to copy the file to the SD Card/apps/Misc folder.

Running the updated firmware

These directions assume you are starting at the flipper desktop. If not, please press the back button until you are at the desktop.

  • Press the OK button on the flipper to pull up the main menu.

  • Choose "Applications" from the menu.

  • Choose "Gpio" from the sub-menu.

  • Choose "GPIO 7-Segment Output"

  • The flipper should say "GPIO 7-Segment".

  • Click the "OK" button to display a random number from 1-6.

  • Press the BACK button to exit.

How it works

  • application.fam

    • specifies the settings for our application.
    • adds "gpio" to requires.
  • gpio_7segment.png

    • The icon for our application that shows up in the "Misc" folder.
  • gpio_7segment_app.c

    • Similar to the plugin\basic tutorial.
    • bool digits[70] is defined to store the segments to glow for different digits.
      • each group of 7 booleans represents a number.
      • note: in production code you could replace with a single byte [8-bits] to represent the segments to turn on/off. Like bit 0 is middle LED, bit 1 is bottom right, etc.
    • gpio_7segment_render_callback(...) callback paints the canvas.
      • Title of application
      • two boxes (looks like a 7-segment display)
      • index is set to the first index with our LED information
        • for example to draw a 2 we index at 7*2 = 14 (which is the 15th bool, since it starts at a count of 0.)
        • digits[index++] ? "A7" : "a7"
          • digits[index] is the bool (true/false) from our digits table.
          • if it is true we will use the text "A7" (CAPS to show on)
          • if it is false we will use the text "a7" (lowercase)
          • index++ will increment index to the next number.
      • data->invert ? "GND" : "3.3v"
        • if invert is set to true we show the text "GND" (pins will GND to glow.)
        • if invert is set to false we show the text "3.3v" (pins will 3.3 to glow.)
      • We show the number we are displaying on the 7-segment display.
    • gpio_7segment_show(...) displays a number.
      • index is set to the first index with our LED information
        • for example to draw a 2 we index at 7*2 = 14 (which is the 15th bool, since it starts at a count of 0.)
      • furi_hal_gpio_write(&gpio_ext_pa7, digits[index++] ^ invert);
        • THIS IS THE CODE THAT CHANGES THE STATE OF THE PIN!
        • gpio_ext_pa7 is the pin (a7). You can see all pin names at \firmware\targets\f7\furi_hal\furi_hal_resources.c
        • digits[index++] ^ invert
          • digits[index] is the bool (true/false) from our digits table.
          • if invert is false, (digits[index++] ^ false) == digits[index++] (so same as table.)
          • if invert it true, (digits[index++] ^ true) == !digits[index++] (so inverted from table value. This is needed for common anode 7-segment LEDs.)
    • gpio_7segment_disconnect_pin(...) disconnects a pin.
      • GpioModeOutputOpenDrain means that when the value is false the pin will be GND, but when the value is true the pin will be disconnected.
      • GpioPullNo means there is no pull-up resistor between 3.3v and pin & there is no pull-down resistor between GND and pin.
      • we write a true, so pin is disconnected.
      • Some people use Input with Push/Pull-No to disconnect pins while others use OutputOpenDrain. I'm not sure if the pins are really disconnected just because you aren't reading, so I think I would prefer to use OutputOpenDrain.
    • gpio_7segment_app(...) is our entry point
      • furi_hal_gpio_init_simple(&gpio_ext_pa7, GpioModeOutputPushPull);
        • this sets the A7 pin to be OutputPushPull.
          • PushPull means pin will either be GND or 3.3volts.
          • (As opposed to OutputOpenDrain when pin is GND or disconnected.)
          • We use "init_simple" instead of "init", because other params aren't needed.
      • context->data->digit = (furi_hal_random_get() % 6) + 1;
        • when OK button is pressed we use furi_hal_random_get() to get a random number (I think from the secure random number generator).
        • (x % 6) will return the remainder from dividing x by 6. Which should be a number between 0 and 5. We then add 1 to the value so we get a value between 1 and 6.
      • gpio_7segment_disconnect_pin(&gpio_ext_pa7);
        • when our app exits, we disconnect the pins. If we didn't the number would still show.