-
Notifications
You must be signed in to change notification settings - Fork 948
add pio example for 7_segment display #375
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
mjcross
wants to merge
4
commits into
raspberrypi:develop
Choose a base branch
from
mjcross:add-pio-7_segment
base: develop
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 1 commit
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
/** | ||
* Copyright (c) 2023 mjcross | ||
* | ||
* SPDX-License-Identifier: BSD-3-Clause | ||
**/ | ||
|
||
#include <stdio.h> | ||
#include "pico/stdlib.h" | ||
#include "7_segment_lib.h" | ||
|
||
|
||
const PIO pio = pio0; | ||
const uint first_segment_pin = 8; // gpio 15-8 = segments E,D,B,G,A,C,F,dp | ||
const uint first_digit_pin = 16; // gpio 19-16 = common anodes 4,3,2,1 | ||
|
||
// EDBGACF. bit ordering depends on your display and wiring | ||
const uint32_t Pico = 0b10111010 << 24 | // 'P' | ||
0b10000000 << 16 | // 'i' | ||
0b11010000 << 8 | // 'c' | ||
0b11010100; // 'o' | ||
|
||
int main() { | ||
uint sm; | ||
stdio_init_all(); | ||
|
||
if (seven_segment_init (pio, &sm, first_segment_pin, first_digit_pin)) { | ||
puts ("running"); | ||
|
||
// display scrolling 'Pico' | ||
for (int shift = 24; shift >= 0; shift -= 8) { | ||
pio_sm_put (pio, sm, Pico >> shift); | ||
sleep_ms (1000); | ||
} | ||
|
||
// count to 9999 | ||
for (int i = 0; i < 10000; i += 1) { | ||
sleep_ms (100); | ||
pio_sm_put (pio, sm, int_to_seven_segment (i)); | ||
} | ||
} | ||
|
||
puts ("done"); | ||
while (true); | ||
} |
Binary file not shown.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
add_executable(pio_7_segment) | ||
|
||
target_sources(pio_7_segment PRIVATE 7_segment.c) | ||
|
||
add_subdirectory(pio_7_segment_library) | ||
|
||
target_link_libraries(pio_7_segment PRIVATE | ||
pico_stdlib | ||
hardware_pio | ||
pio_7_segment_library) | ||
|
||
pico_add_extra_outputs(pio_7_segment) | ||
|
||
example_auto_set_url(pio_7_segment) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
= Driving a 7 segment LED display with the PIO | ||
|
||
This example demonstrates how the RP2040 PIO can be used to control a four digit multiplexed 7-segment display. | ||
|
||
Multiplexed displays work by rapidly displaying each digit in turn. The PIO is a good way to relieve the CPU of this repetitive task. | ||
|
||
The code uses four `side-set` pins to control the digit multiplex lines and displays the segment patterns received on the FIFO. A non-blocking PULL is used to keep showing the same segments until the CPU sends new data. | ||
|
||
The provided example spells out the word **Pico** then counts from 0 to 9999. | ||
|
||
== Wiring information | ||
|
||
Miniature _('bubble')_ displays can sometimes be driven directly from the GPIO pins but full sized ones usually need an external drive circuit like the example shown. | ||
|
||
|
||
Connect the circuit to an external 5V supply or power it via USB (in which case you may prefer to take the _+5V_ rail from _VBUS_). | ||
|
||
TIP: make any changes required for your display and transistors: this is for a _common anode_ display that takes about 15mA per segment. | ||
|
||
[[pio_7_segment_wiring]] | ||
[pdfwidth=75%] | ||
.Wiring diagram | ||
image::7_segment_wiring.png[] | ||
|
||
[[pio_7_segment_schematic]] | ||
[pdfwidth=50%] | ||
.Schematic (common anode driver) | ||
image::7_segment_schematic.png[] | ||
|
||
|
||
[[pio_7_segment_connections-table]] | ||
.Connections table | ||
[options="header,footer"] | ||
|================================================== | ||
|RP2040 |Pico pin |Display driver | ||
|GP8 |11 |segment dp | ||
|GP9 |12 |segment F | ||
|GP10 |14 |segment C | ||
|GP11 |15 |segment A | ||
|GP12 |16 |segment G | ||
|GP13 |17 |segment B | ||
|GP14 |19 |segment D | ||
|GP15 |20 |segment E | ||
|GP16 |21 |digit 1 (thousands) | ||
|GP17 |22 |digit 2 (hundreds) | ||
|GP18 |24 |digit 3 (tens) | ||
|GP19 |25 |digit 4 (units) | ||
|================================================== | ||
|
||
== Bill of materials | ||
|
||
.A list of materials for the example circuit | ||
[[pio_onewire_bom-table]] | ||
[cols=3] | ||
|=== | ||
| *Item* | *Quantity* | *Details* | ||
| Breadboard | 1 | generic part | ||
| Raspberry Pi Pico | 1 | https://www.raspberrypi.com/products/raspberry-pi-pico/ | ||
| 4 digit 7 segment display (common anode) | 1 | e.g. https://shop.pimoroni.com/products/4-digit-7-segment-display | ||
| NPN bipolar transistor | 12 | e.g. https://thepihut.com/products/npn-bipolar-transistors-pn2222-10-pack (10-pack) | ||
| PNP bipolar transistor | 4 | e.g. https://thepihut.com/products/bipolar-transistor-kit-5-x-pn2222-npn-and-5-x-pn2907-pnp (5-PNP + 5-NPN) | ||
| 180 ohm resistor | 8 | generic part | ||
| 220 ohm resistor | 4 | generic part | ||
| M/M jumper wire | 22 | generic part | ||
| M/F jumper wire | 12 | generic part | ||
|=== |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
/** | ||
* Copyright (c) 2023 mjcross | ||
* | ||
* SPDX-License-Identifier: BSD-3-Clause | ||
**/ | ||
|
||
#include <stdio.h> | ||
#include "hardware/gpio.h" | ||
|
||
#include "7_segment_lib.h" | ||
|
||
|
||
// define which segments to illuminate for the digits 0-9 | ||
// | ||
static const uint8_t segments[] = { | ||
// EDBGACF. the bit ordering depends on the display used | ||
0b11101110, // 0 | ||
0b00100100, // 1 | ||
0b11111000, // 2 | ||
0b01111100, // 3 | ||
0b00110110, // 4 | ||
0b01011110, // 5 | ||
0b11011110, // 6 | ||
0b00101100, // 7 | ||
0b11111110, // 8 | ||
0b01111110 // 9 | ||
}; | ||
|
||
|
||
// convert an integer into a 32-bit word representing up to four 7-segment digits | ||
// | ||
uint32_t int_to_seven_segment (int num) { | ||
uint32_t word = 0; | ||
if (num == 0) { | ||
word = segments[0]; | ||
} else { | ||
for (int bitshift = 0; bitshift < 32 && num > 0; bitshift += 8) { | ||
word |= segments[num % 10] << bitshift; | ||
num /= 10; | ||
} | ||
} | ||
return word; | ||
} | ||
|
||
|
||
// configure and initialise a PIO state machine | ||
// | ||
bool seven_segment_init (PIO pio, uint *p_sm, uint segment_pinbase, uint digit_pinbase) { | ||
// add the program to the PIO shared instruction memory | ||
if (pio_can_add_program (pio, &seven_segment_program) == false) { | ||
puts ("could not add the pio program"); | ||
return false; | ||
} | ||
uint offset = pio_add_program (pio, &seven_segment_program); | ||
|
||
// claim a free state machine | ||
int sm = pio_claim_unused_sm (pio, false); | ||
if (sm == -1) { | ||
puts ("could not claim a state machine"); | ||
return false; | ||
} else { | ||
*p_sm = (uint)sm; | ||
} | ||
|
||
// set segment pins to PIO output | ||
for (int pin = 0; pin < 8; pin += 1) { | ||
pio_gpio_init (pio, segment_pinbase + pin); | ||
} | ||
pio_sm_set_consecutive_pindirs (pio, *p_sm, segment_pinbase, 8, true); | ||
|
||
// set digit mux pins to PIO output | ||
for (int pin = 0; pin < 4; pin += 1) { | ||
pio_gpio_init (pio, digit_pinbase + pin); | ||
} | ||
pio_sm_set_consecutive_pindirs (pio, *p_sm, digit_pinbase, 4, true); | ||
|
||
// initialise X register to zero | ||
pio_sm_exec_wait_blocking (pio, *p_sm, pio_encode_mov (pio_x, pio_null)); | ||
|
||
// configure and enable the state machine | ||
seven_segment_sm_init (pio, *p_sm, offset, segment_pinbase, digit_pinbase); | ||
|
||
return true; | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
#include "hardware/pio.h" | ||
#include "hardware/clocks.h" // for clock_get_hz() in generated header | ||
#include "7_segment_lib.pio.h" // generated by pioasm | ||
|
||
uint32_t int_to_seven_segment (int num); | ||
bool seven_segment_init (PIO pio, uint *p_sm, uint segment_pinbase, uint digit_pinbase); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
;; | ||
;; Copyright (c) 2023 mjcross | ||
;; | ||
;; SPDX-License-Identifier: BSD-3-Clause | ||
;; | ||
|
||
.program seven_segment | ||
|
||
;; SIDE pins: digit enable lines | ||
;; OUT pins: segments (multiplexed) | ||
|
||
.side_set 4 ; leaves one `delay` bit | ||
|
||
; note: for the digits to look the same brightness it's | ||
; important to show them for the same amount of time | ||
.wrap_target | ||
pull noblock side 0b0001 ; TX FIFO (or X) -> OSR keep showing 1000's for 1 tick | ||
; if the FIFO is empty then the OSR is loaded from X | ||
public entry_point: | ||
mov x, osr side 0b0000 ; save the segments in X and show no digits for 1 tick | ||
|
||
out pins, 8 side 0b1000 [1] ; OSR[07..00] -> segments and show 1's digit for 2 ticks | ||
out pins, 8 side 0b0100 [1] ; OSR[15..08] -> segments and show 10's digit for 2 ticks | ||
out pins, 8 side 0b0010 [1] ; OSR[23..16] -> segments and show 100's digit for 2 ticks | ||
out pins, 8 side 0b0001 ; OSR[31..24] -> segments and show 1000's digit for 1 tick | ||
.wrap | ||
;; 6 instructions | ||
|
||
|
||
% c-sdk { | ||
static inline void seven_segment_sm_init (PIO pio, uint sm, uint offset, | ||
uint segment_pinbase, uint digit_pinbase) { | ||
// create new sm config | ||
pio_sm_config config = seven_segment_program_get_default_config (offset); | ||
|
||
// configure the common cathodes and segment pin groups | ||
sm_config_set_out_pins (&config, segment_pinbase, 8); | ||
sm_config_set_sideset_pins (&config, digit_pinbase); | ||
|
||
// configure the clock divider | ||
float div = clock_get_hz (clk_sys) * 10e-3; | ||
sm_config_set_clkdiv (&config, div); | ||
|
||
// apply the configuration to the state machine initialise the program counter | ||
pio_sm_init (pio, sm, offset + seven_segment_offset_entry_point, &config); | ||
|
||
// enable the state machine | ||
pio_sm_set_enabled (pio, sm, true); | ||
} | ||
%} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
add_library(pio_7_segment_library INTERFACE) | ||
|
||
target_sources(pio_7_segment_library INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/7_segment_lib.c) | ||
|
||
# invoke pio_asm to assemble the state machine programs | ||
# | ||
pico_generate_pio_header(pio_7_segment_library ${CMAKE_CURRENT_LIST_DIR}/7_segment_lib.pio) | ||
|
||
target_link_libraries(pio_7_segment_library INTERFACE | ||
pico_stdlib | ||
hardware_pio | ||
) | ||
|
||
# add the `binary` directory so that the generated headers are included in the project | ||
# | ||
target_include_directories(pio_7_segment_library INTERFACE | ||
${CMAKE_CURRENT_SOURCE_DIR} | ||
${CMAKE_CURRENT_BINARY_DIR} | ||
) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.