Introduction
In this post I want to take things further beyond what has been established in the last post ‘Raspberry Pico development environment’. To ‘Refactor’1 ‘nibble.c’ such that it provides a basis upon which to:
- Understand the means by which to have re-usable components of code that can then be used in other projects.
- Understand how to have more than one source file in a project and make the build system work. Thus with the last two points, understand how ‘CMake’2 supports what I want to to achieve.
- Use ‘C++’ instead of ‘C’ as a means of relearning the past.
Being the ‘objectives’.
Refactoring itself is not the main focus of this post. It is the change in the structure that forms a basis, foundation and design concept upon which to create organised complex programs with reusable components.
Disclaimers
If replicating what I’ve done then be sure of what you’re doing, as information presented in this article is written according to my own understanding, there could be inaccuracies, so please do undertake your own research. All sources of information that are not my own have been cited / referenced. All screen shots taken on the ‘Pi 5’3. Images / video are my own.
Research
With what I want to achieve in mind, the objectives, I set about finding out how they could be done. Often what you want to do has already been solved by somebody else. It’s just a matter of finding it.
The section title of ‘2.2’ in the SDK4 is ‘Every Library is an INTERFACE Library’. Thus this is a basis of thinking about how to implement the third objective which will then be an enablier for the other two. Given this and through a process of changing the code such that the ‘LED’ display functionality was separate to that of the main program, I found the following the most useful:
- Raspberry Pico and CMake - create your own C lib or subdirectory with header files5.
- PicoLED library6.
- Building Libraries7.
- pico_rand8.
As with all things, you can find yourself discovering other things you thought you didn’t need but actually would be a good idea!
- Embedded Binary Information, chapter 10 of the SDK4.
- ‘project’ CMake command9 additional parameters. Which also references a newer version of CMake. This I determined by running ‘
cmake --version’ on the Pi to understand what is currently being used.
So I’ve added them to the list of objectives that I wanted to achieve.
Result
The result of understanding what I wanted to achieve is evident in the code that was produced. This process is akin to both understanding the new and what I already knew, combined with the skills I have developed over the years. I feel that I want to describe the step by step process, but it in this case its tricky as I ‘danced’ around different solutions to see if they would work before coming up with this result - informed trial and error. To have understood what the result would turn out to be beforehand would lead to a concise explanation. Thus I don’t want to make this long winded, but rather a summary of what works and why.
Nibble
The code is now broken down into three files (per C and a C++ version).
C version
The main file has been refactored to take out the ‘show LED’ functionality:
nibble.c
1/*
2 * Copyright (c) 2026 G J Barnard.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6#include <stdint.h>
7#include "pico/stdlib.h"
8/* #include "hardware/gpio.h" - Included in pico/stdlib.h. */
9#include "pico/printf.h"
10#include "pico/binary_info.h"
11#include "gj/led.h"
12
13/* Constants */
14const uint16_t FLASH_PAUSE = 1024;
15const uint8_t FLASH_INTERMISSION = 255;
16const uint8_t FLASH_FLASH = 128;
17const uint8_t FLASH_INC = 1;
18const uint8_t FIFTEEN = 15;
19
20/**
21 * Initialise.
22 */
23void init() {
24 bi_decl(bi_program_name("Nibble"));
25 bi_decl(bi_program_description("Demonstrate binary counting with a nibble"));
26 bi_decl(bi_program_version_string("V1.1.0"));
27
28 stdio_uart_init();
29 stdio_usb_init();
30
31 gj_led_init();
32}
33
34/**
35 * Intermission.
36 */
37void intermission() {
38 const uint8_t sequence[] = {1, 2, 4, 8, 4, 2, 1};
39 uint8_t display;
40
41 for (display = 0; display < 7; display++) {
42 gj_led_show(sequence[display]);
43 sleep_ms(FLASH_INTERMISSION);
44 }
45
46 for (display = 0; display < 2; display++) {
47 gj_led_show(0);
48 sleep_ms(FLASH_FLASH);
49 gj_led_show(FIFTEEN);
50 sleep_ms(FLASH_FLASH);
51 }
52}
53
54/**
55 * Run.
56 */
57void run() {
58 uint8_t flashCount = 0;
59 uint8_t showing = 0;
60
61 sleep_ms(FLASH_PAUSE * 2);
62
63 printf("run()\n");
64
65 while (true) {
66 printf("Count was %d", flashCount);
67 flashCount += FLASH_INC;
68 showing = flashCount << 4;
69 showing = showing >> 4;
70 printf(", and is now %d, showing %d.\n", flashCount, showing);
71
72 gj_led_show(showing);
73
74 sleep_ms(FLASH_PAUSE);
75
76 if ((flashCount & FIFTEEN) == FIFTEEN) {
77 intermission();
78 }
79 }
80}
81
82/**
83 * Main.
84 */
85void main() {
86 init();
87 run();
88}
which it then imports as a header file, being ‘led.h’ in the folder ‘gj’. It is:
led.h
1/*
2 * Copyright (c) 2026 G J Barnard.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6#ifndef _GJ_LED_H
7#define _GJ_LED_H
8
9#include <stdint.h>
10
11#ifdef __cplusplus
12extern "C" {
13#endif
14
15void gj_led_init();
16void gj_led_show(uint8_t show);
17
18#ifdef __cplusplus
19}
20#endif
21
22#endif
That defines two functions ‘gj_led_init()’ and ‘gj_led_show(uint8_t show)’ to initialise and set the LEDs respectively. Note that there is use of:
1#ifdef __cplusplus
2extern "C" {
3#endif
to allow the header to be used with a C++ file, even though I won’t be.
The functions defined in the header file are implemented in ‘led.c’:
led.c
1/*
2 * Copyright (c) 2026 G J Barnard.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6#include "pico/stdlib.h"
7#include "pico/binary_info.h"
8
9/* GPs / Pins common for both Pico, Pico W, Pico 2 and Pico 2 W. */
10const uint8_t LED_8_PIN = 21; /* GP21 / Pin 27 */
11const uint8_t LED_4_PIN = 20; /* GP20 / Pin 26 */
12const uint8_t LED_2_PIN = 19; /* GP19 / Pin 25 */
13const uint8_t LED_1_PIN = 18; /* GP18 / Pin 24 */
14
15const uint8_t EIGHT = 8;
16const uint8_t FOUR = 4;
17const uint8_t TWO = 2;
18const uint8_t ONE = 1;
19
20/**
21 * Initialise.
22 */
23void gj_led_init() {
24 bi_decl(bi_4pins_with_names(
25 LED_1_PIN, "LED One",
26 LED_2_PIN, "LED Two",
27 LED_4_PIN, "LED Three",
28 LED_8_PIN, "LED Four")
29 );
30
31 gpio_init(LED_8_PIN);
32 gpio_set_dir(LED_8_PIN, GPIO_OUT);
33 gpio_init(LED_4_PIN);
34 gpio_set_dir(LED_4_PIN, GPIO_OUT);
35 gpio_init(LED_2_PIN);
36 gpio_set_dir(LED_2_PIN, GPIO_OUT);
37 gpio_init(LED_1_PIN);
38 gpio_set_dir(LED_1_PIN, GPIO_OUT);
39}
40
41/**
42 * Show.
43 */
44void gj_led_show(uint8_t show) {
45 gpio_put(LED_8_PIN, (show & EIGHT));
46 gpio_put(LED_4_PIN, (show & FOUR));
47 gpio_put(LED_2_PIN, (show & TWO));
48 gpio_put(LED_1_PIN, (show & ONE));
49}
Which originate (migrated) from the code that was there before. ‘nibble.c’ has then been changed to call them.
I’ve replaced ‘stdio_init_all’ with ‘stdio_uart_init’ and ‘stdio_usb_init’ to be more specific to the implementation.
There is a new import of ‘binary_info.h’ in both ‘C’ files that defines the macros we want to use:
1 bi_decl(bi_program_name("Nibble"));
2 bi_decl(bi_program_description("Demonstrate binary counting with a nibble"));
3 bi_decl(bi_program_version_string("V1.1.0"));
See chapter 10 of the SDK4. Resulting in:
1File nibble.elf:
2
3Program Information
4 name: Nibble
5 version: V1.1.0
6 description: Demonstrate binary counting with a nibble, C version.
7 features: UART stdin / stdout
8 USB stdin / stdout
9 binary start: 0x10000000
10 binary end: 0x10009360
11
12Fixed Pin Information
13 0: UART0 TX
14 1: UART0 RX
15 18: LED One
16 19: LED Two
17 20: LED Three
18 21: LED Four
19
20Build Information
21 sdk version: 2.2.0
22 pico_board: pico
23 boot2_name: boot2_w25q080
24 build date: Jun 10 2026
25 build attributes: Debug
26
27Metadata Blocks
28 none
when we use ‘picotool’ with ‘picotool info -a nibble.elf’.
All of this means that we have now separated out the functionality of showing four LED’s which could then conceptually be used in other programs.
To understand ‘headers’, one source of information is ‘26.4 Header Files’10 in the ‘GNU C Language Manual’11.
Build structure
The code files have been re-organised into the structure:
1.
2├── build
3├── CMakeLists.txt
4├── gj_led
5│ ├── CMakeLists.txt
6│ ├── include
7│ │ └── gj
8│ │ ├── led.h
9│ │ └── led.hpp
10│ └── src
11│ ├── led.c
12│ └── led.cpp
13└── src
14 ├── nibble.c
15 └── nibble.cpp
Which mirrors what has been stated in the code with the ‘#include "gj/led.h"’ statement.
We now have two ‘CMakeLists.txt’ files, one for ‘nibble.c’ and the other for ‘led.c’. The top level ‘CMakeLists.txt’ file:
1cmake_minimum_required(VERSION 3.31)
2
3# Use below when using the Pico VS Code Extension. Seems to copy 'pico_sdk_import.cmake' when importing the folder.
4include(pico_sdk_import.cmake)
5# Uncomment below for 'Manual' and comment out above:
6#include($ENV{PICO_SDK_PATH}/external/pico_sdk_import.cmake)
7
8set(CMAKE_C_STANDARD 17)
9set(CMAKE_CXX_STANDARD 14)
10set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
11
12pico_sdk_init()
13
14project(nibble
15 LANGUAGES C CXX ASM
16 VERSION 1.1.0
17)
18
19add_subdirectory(gj_led)
20
21add_executable(${PROJECT_NAME}
22 ${CMAKE_CURRENT_LIST_DIR}/src/nibble.c
23 #${CMAKE_CURRENT_LIST_DIR}/src/nibble.cpp
24)
25
26pico_enable_stdio_usb(${PROJECT_NAME} 1)
27pico_enable_stdio_uart(${PROJECT_NAME} 1)
28
29pico_add_uf2_output(${PROJECT_NAME})
30# Have if debugging.
31pico_add_dis_output(${PROJECT_NAME})
32
33target_link_libraries(${PROJECT_NAME} pico_stdlib gj_led)
still compliles ‘nibble.c’ but also calls ‘led.c’s ‘CMakeLists.txt’ file in its subdirectory using the ‘add_subdirectory’12 command:
1add_library(gj_led INTERFACE)
2
3target_sources(gj_led INTERFACE
4 ${CMAKE_CURRENT_LIST_DIR}/src/led.c
5 #${CMAKE_CURRENT_LIST_DIR}/src/led.cpp
6)
7
8target_include_directories(gj_led INTERFACE ${CMAKE_CURRENT_LIST_DIR}/include)
9target_link_libraries(gj_led INTERFACE pico_stdlib)
Which will complile ‘led.c’ for us producing ’led.o’ but no more as it is being used as a ‘INTERFACE’13. The ‘target_include_directories’14 command is there so that when compiling ‘nibble.c’ that ‘#include "gj/led.h"’ can be found. The command ‘target_link_libraries’15 is not really required in this case as the top level call pulls in the same libraries that the program requires, but I’ve left it there for completeness. In the top level ‘CMakeLists.txt’ file though you will see the addition of ‘gj_led’ so that its linked into the program.
Note that the C++ versions have been commented out, so that only this ‘C’ version is created.
In the top level ‘CMakeLists.txt’ file you’ll see use of the ‘VERSION’ parameter on the ‘project’9 command. Here I’m using ‘Semantic Versioning’16 for versioning.
C++ version
This is where things get a bit more interesting! With the files:
led.hpp
1/*
2 * Copyright (c) 2026 G J Barnard.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6#ifndef _GJ_TOOLBOX_LED_H
7#define _GJ_TOOLBOX_LED_H
8
9#include <stdint.h>
10
11namespace GJ_Toolbox {
12 class Led {
13 public:
14 void init();
15 void show(uint8_t show);
16
17 private:
18 static const uint8_t LED_8_PIN;
19 static const uint8_t LED_4_PIN;
20 static const uint8_t LED_2_PIN;
21 static const uint8_t LED_1_PIN;
22
23 static const uint8_t EIGHT;
24 static const uint8_t FOUR;
25 static const uint8_t TWO;
26 static const uint8_t ONE;
27 };
28};
29
30#endif
led.cpp
1/*
2 * Copyright (c) 2026 G J Barnard.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6#include "pico/stdlib.h"
7#include "pico/binary_info.h"
8#include "gj/led.hpp"
9
10/* GPs / Pins common for both Pico, Pico W, Pico 2 and Pico 2 W. */
11const uint8_t GJ_Toolbox::Led::LED_8_PIN = 21; /* GP21 / Pin 27 */
12const uint8_t GJ_Toolbox::Led::LED_4_PIN = 20; /* GP20 / Pin 26 */
13const uint8_t GJ_Toolbox::Led::LED_2_PIN = 19; /* GP19 / Pin 25 */
14const uint8_t GJ_Toolbox::Led::LED_1_PIN = 18; /* GP18 / Pin 24 */
15
16const uint8_t GJ_Toolbox::Led::EIGHT = 8;
17const uint8_t GJ_Toolbox::Led::FOUR = 4;
18const uint8_t GJ_Toolbox::Led::TWO = 2;
19const uint8_t GJ_Toolbox::Led::ONE = 1;
20
21/**
22 * Initialise.
23 */
24void GJ_Toolbox::Led::init() {
25 bi_decl(bi_4pins_with_names(
26 LED_1_PIN, "LED One",
27 LED_2_PIN, "LED Two",
28 LED_4_PIN, "LED Three",
29 LED_8_PIN, "LED Four")
30 );
31
32 gpio_init(LED_8_PIN);
33 gpio_set_dir(LED_8_PIN, GPIO_OUT);
34 gpio_init(LED_4_PIN);
35 gpio_set_dir(LED_4_PIN, GPIO_OUT);
36 gpio_init(LED_2_PIN);
37 gpio_set_dir(LED_2_PIN, GPIO_OUT);
38 gpio_init(LED_1_PIN);
39 gpio_set_dir(LED_1_PIN, GPIO_OUT);
40}
41
42/**
43 * Show.
44 */
45void GJ_Toolbox::Led::show(uint8_t show) {
46 gpio_put(LED_8_PIN, (show & EIGHT));
47 gpio_put(LED_4_PIN, (show & FOUR));
48 gpio_put(LED_2_PIN, (show & TWO));
49 gpio_put(LED_1_PIN, (show & ONE));
50}
Where I’ve now included ‘#include "gj/led.hpp"’ to get the ‘Led’ ‘namespace’17 and ‘class’18 definition that makes the implementation scope make sense.
nibble.cpp
1/*
2 * Copyright (c) 2026 G J Barnard.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#include <stdint.h>
8#include "pico/stdlib.h"
9/* #include "hardware/gpio.h" - Included in pico/stdlib.h. */
10#include "pico/printf.h"
11#include "pico/binary_info.h"
12#include "gj/led.hpp"
13
14class Nibble {
15 public:
16 /**
17 * Initialise.
18 */
19 void init() {
20 bi_decl(bi_program_name("Nibble"));
21 bi_decl(bi_program_description("Demonstrate binary counting with a nibble, C++ version."));
22 bi_decl(bi_program_version_string("V1.1.0"));
23
24 stdio_uart_init();
25 stdio_usb_init();
26
27 leds.init(); // Initialise the Led's.
28 }
29
30 /**
31 * Intermission.
32 */
33 void intermission() {
34 const uint8_t sequence[] = {1, 2, 4, 8, 4, 2, 1};
35 uint8_t display;
36
37 for (display = 0; display < 7; display++) {
38 leds.show(sequence[display]);
39 sleep_ms(FLASH_INTERMISSION);
40 }
41
42 for (display = 0; display < 2; display++) {
43 leds.show(0);
44 sleep_ms(FLASH_FLASH);
45 leds.show(FIFTEEN);
46 sleep_ms(FLASH_FLASH);
47 }
48 }
49
50 /**
51 * Run.
52 */
53 void run() {
54 uint8_t flashCount = 0;
55 uint8_t showing = 0;
56
57 sleep_ms(FLASH_PAUSE * 2);
58
59 printf("run()\n");
60
61 while (true) {
62 printf("Count was %d", flashCount);
63 flashCount += FLASH_INC;
64 showing = flashCount << 4;
65 showing = showing >> 4;
66 printf(", and is now %d, showing %d.\n", flashCount, showing);
67
68 leds.show(showing);
69
70 sleep_ms(FLASH_PAUSE);
71
72 if ((flashCount & FIFTEEN) == FIFTEEN) {
73 intermission();
74 }
75 }
76 }
77
78 private:
79 // Constants.
80 const uint16_t FLASH_PAUSE = 1024;
81 const uint8_t FLASH_INTERMISSION = 255;
82 const uint8_t FLASH_FLASH = 128;
83 const uint8_t FLASH_INC = 1;
84 const uint8_t FIFTEEN = 15;
85
86 // Led.
87 GJ_Toolbox::Led leds; // Instantiate and instance of the 'Led' class.
88};
89
90/**
91 * Main.
92 */
93int main() {
94 Nibble nibble; // Instantiate an instance of the 'Nibble' class.
95 nibble.init();
96 nibble.run();
97
98 return 1;
99}
That encapuslates the functionality within a ‘Nibble’ class18. Which in itself containts a single instance of the ‘Led’ class. I need not have put that in a ‘namespace’17 but wanted to re-learn about them in the C++ context.
Note that ‘main()’ now returns an ‘int’ because the compiler told me so! Even though the ‘return’ is never reached.
Going further with the C++ version
In the process of writing this post, it has hit me that I should really be using ‘Constructors’19 instead of having separate ‘init()’ methods! That I can make things even tidier with using constant initialisation20 on the constuctor itself in the ‘Led’ class as its broken apart between the header and implementation files. Thus improved versions:
led.hpp
1/**
2 * @file led.hpp
3 * @defgroup Led
4 * @copyright (c) 2026 G J Barnard.
5 *
6 * @par License
7 * SPDX-License-Identifier: BSD-3-Clause
8 *
9 * @version V1.1.0
10 */
11#ifndef _GJ_TOOLBOX_LED_H
12#define _GJ_TOOLBOX_LED_H
13
14#include <stdint.h>
15
16/**
17 * @namespace GJ_Toolbox
18 * @brief A toolbox containing generic 'components' for re-use.
19 */
20namespace GJ_Toolbox {
21 /**
22 * @class Led led.hpp gj/led.hpp
23 * @brief Led class.
24 * @details Class ecapsulating the functionality to show the value of a nibble on four led's.
25 */
26 class Led {
27 public:
28 /**
29 * @brief Constructor.
30 */
31 Led();
32
33 /**
34 * @brief Show the Led's using the bit's in the lower nibble of the byte.
35 */
36 void show(uint8_t show);
37
38 private:
39 /** Pin representing the 8'ths column in the byte. */
40 const uint8_t LED_8_PIN;
41 /** Pin representing the 4's column in the byte. */
42 const uint8_t LED_4_PIN;
43 /** Pin representing the 2's column in the byte. */
44 const uint8_t LED_2_PIN;
45 /** Pin representing the 1's column in the byte. */
46 const uint8_t LED_1_PIN;
47
48 /** Byte representing the decimal value 8. */
49 const uint8_t EIGHT;
50 /** Byte representing the decimal value 4. */
51 const uint8_t FOUR;
52 /** Byte representing the decimal value 2. */
53 const uint8_t TWO;
54 /** Byte representing the decimal value 1. */
55 const uint8_t ONE;
56 };
57};
58
59#endif
led.cpp
1/**
2 * @file led.cpp
3 * @defgroup Led
4 * @copyright (c) 2026 G J Barnard.
5 *
6 * @par License
7 * SPDX-License-Identifier: BSD-3-Clause
8 *
9 * @version V1.1.0
10 */
11#include "pico/stdlib.h"
12#include "pico/binary_info.h"
13#include "gj/led.hpp"
14
15/**
16 * @class Led
17 * @brief Constructor.
18 */
19GJ_Toolbox::Led::Led():
20 /* GPs / Pins common for both Pico, Pico W, Pico 2 and Pico 2 W. */
21 LED_8_PIN(21), /* GP21 / Pin 27 */
22 LED_4_PIN(20), /* GP20 / Pin 26 */
23 LED_2_PIN(19), /* GP19 / Pin 25 */
24 LED_1_PIN(18), /* GP18 / Pin 24 */
25 EIGHT(8),
26 FOUR(4),
27 TWO(2),
28 ONE(1)
29 {
30 bi_decl(bi_4pins_with_names(
31 LED_1_PIN, "LED One",
32 LED_2_PIN, "LED Two",
33 LED_4_PIN, "LED Three",
34 LED_8_PIN, "LED Four")
35 );
36
37 gpio_init(LED_8_PIN);
38 gpio_set_dir(LED_8_PIN, GPIO_OUT);
39 gpio_init(LED_4_PIN);
40 gpio_set_dir(LED_4_PIN, GPIO_OUT);
41 gpio_init(LED_2_PIN);
42 gpio_set_dir(LED_2_PIN, GPIO_OUT);
43 gpio_init(LED_1_PIN);
44 gpio_set_dir(LED_1_PIN, GPIO_OUT);
45}
46
47/**
48 * @brief Show the Led's using the bit's in the lower nibble of the byte.
49 *
50 * @param uint8_t show Byte having the state of the leds in the lower nibble.
51 */
52void GJ_Toolbox::Led::show(uint8_t show) {
53 gpio_put(LED_8_PIN, (show & EIGHT));
54 gpio_put(LED_4_PIN, (show & FOUR));
55 gpio_put(LED_2_PIN, (show & TWO));
56 gpio_put(LED_1_PIN, (show & ONE));
57}
nibble.cpp
1/**
2 * @file nibble.cpp
3 * @copyright (c) 2026 G J Barnard.
4 *
5 * @par License
6 * SPDX-License-Identifier: BSD-3-Clause
7 *
8 * @version V1.1.0
9 */
10#include <stdint.h>
11#include "pico/stdlib.h"
12/* #include "hardware/gpio.h" - Included in pico/stdlib.h. */
13#include "pico/printf.h"
14#include "pico/binary_info.h"
15#include "gj/led.hpp"
16
17/**
18 * @class Nibble.
19 * @brief Demonstrate binary counting with a nibble.
20 */
21class Nibble {
22 public:
23 /**
24 * @brief Constructor.
25 */
26 Nibble() {
27 bi_decl(bi_program_name("Nibble"));
28 bi_decl(bi_program_description("Demonstrate binary counting with a nibble, C++ version."));
29 bi_decl(bi_program_version_string("V1.1.0"));
30
31 stdio_uart_init();
32 stdio_usb_init();
33 }
34
35 /**
36 * @brief Intermission.
37 * @details Signify a break between successive incremental overflows of the nibble.
38 */
39 void intermission() {
40 static const uint8_t sequence[] = {1, 2, 4, 8, 4, 2, 1};
41 uint8_t display;
42
43 for (display = 0; display < 7; display++) {
44 leds.show(sequence[display]);
45 sleep_ms(FLASH_INTERMISSION);
46 }
47
48 for (display = 0; display < 2; display++) {
49 leds.show(0);
50 sleep_ms(FLASH_FLASH);
51 leds.show(FIFTEEN);
52 sleep_ms(FLASH_FLASH);
53 }
54 }
55
56 /**
57 * @brief Run.
58 */
59 void run() {
60 uint8_t flashCount = 0;
61 uint8_t showing = 0;
62
63 sleep_ms(FLASH_PAUSE * 2);
64
65 while (true) {
66 printf("Count was %d", flashCount);
67 flashCount += FLASH_INC;
68 showing = flashCount << 4;
69 showing = showing >> 4;
70 printf(", and is now %d, showing %d.\n", flashCount, showing);
71
72 leds.show(showing);
73
74 sleep_ms(FLASH_PAUSE);
75
76 if ((flashCount & FIFTEEN) == FIFTEEN) {
77 intermission();
78 }
79 }
80 }
81
82 private:
83 /** Milliseconds to pause during the intermisson */
84 const uint16_t FLASH_PAUSE = 1024;
85 /** Milliseconds to pause during the intermisson */
86 const uint8_t FLASH_INTERMISSION = 255;
87 /** The flash timing during the intermisson, in milliseconds */
88 const uint8_t FLASH_FLASH = 128;
89 /** Increment the byte by */
90 const uint8_t FLASH_INC = 1;
91 /** Byte representing the decimal value 15. */
92 const uint8_t FIFTEEN = 15;
93
94 /**
95 * @var GJ_Toolbox::Led leds.
96 * @brief Instantiate and instance of the 'Led' class.
97 */
98 GJ_Toolbox::Led leds;
99};
100
101/**
102 * Main.
103 */
104int main() {
105 Nibble nibble; // Instantiate an instance of the 'Nibble' class.
106 nibble.run();
107
108 return 1;
109}
I’ve also added ‘Doxygen’2122 annotations to document the code. These can then be used to generate the documentation, with a helpful wizard23, including graphically2425. To install use ‘sudo apt install doxygen doxygen-gui graphviz’, then in a folder run the wizard, ‘doxywizard’. I’ve not used it much, so can’t state detailed instructions on how to use it yet.
To build the C++ version, change the appropriate ‘add_executable’ and ‘target_sources’ commands in the ‘CMakeLists.txt’ files where hash symbol is being used to denote that a line is a comment.
Conclusion
Though no new functionality has been added, all of the objectives have been achieved.