add bit counter program
This commit is contained in:
parent
045a1e20d5
commit
ad08d857d1
6
Makefile
6
Makefile
@ -29,7 +29,11 @@ ifeq ($(shell test -d $(name) && echo "ok"),)
|
||||
@false
|
||||
endif
|
||||
|
||||
project: .check-name
|
||||
project:
|
||||
ifeq ($(strip $(name)), "")
|
||||
@echo "error: project name must be set, ex: name=<project_name>"
|
||||
@false
|
||||
endif
|
||||
@./scripts/scaffold_project.bash $(name) $(SDK_VERSION)
|
||||
|
||||
format: .check-name
|
||||
|
||||
38
bit_counter/CMakeLists.txt
Normal file
38
bit_counter/CMakeLists.txt
Normal file
@ -0,0 +1,38 @@
|
||||
# Generated Cmake Pico project file
|
||||
|
||||
cmake_minimum_required(VERSION 3.13)
|
||||
|
||||
set(CMAKE_C_STANDARD 11)
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||
|
||||
# Pull in Raspberry Pi Pico SDK (must be before project)
|
||||
include($ENV{PICO_SDK_PATH}/external/pico_sdk_import.cmake)
|
||||
|
||||
project(bit_counter C CXX ASM)
|
||||
|
||||
# Initialise the Raspberry Pi Pico SDK
|
||||
pico_sdk_init()
|
||||
|
||||
# Add executable. Default name is the project name, version 0.1
|
||||
|
||||
add_executable(bit_counter main.c )
|
||||
|
||||
pico_set_program_name(bit_counter "bit_counter")
|
||||
pico_set_program_version(bit_counter "0.1")
|
||||
|
||||
# Modify the below lines to enable/disable output over UART/USB
|
||||
pico_enable_stdio_uart(bit_counter 0)
|
||||
pico_enable_stdio_usb(bit_counter 1)
|
||||
|
||||
# Add the standard library to the build
|
||||
target_link_libraries(bit_counter
|
||||
pico_stdlib)
|
||||
|
||||
# Add the standard include files to the build
|
||||
target_include_directories(bit_counter PRIVATE
|
||||
${CMAKE_CURRENT_LIST_DIR}
|
||||
)
|
||||
|
||||
pico_add_extra_outputs(bit_counter)
|
||||
|
||||
187
bit_counter/main.c
Normal file
187
bit_counter/main.c
Normal file
@ -0,0 +1,187 @@
|
||||
#include <pico/printf.h>
|
||||
#include <pico/stdlib.h>
|
||||
#include <pico/malloc.h>
|
||||
#include <string.h>
|
||||
|
||||
#define NB_LED_BAR_GPIO 10
|
||||
|
||||
static const int LED_BAR_GPIO[NB_LED_BAR_GPIO] = {28, 27, 26, 22, 21, 20, 19, 18, 17, 16};
|
||||
|
||||
typedef int led_state;
|
||||
enum LED_STATE { OFF, ON };
|
||||
|
||||
typedef struct led led;
|
||||
struct led {
|
||||
int gpio;
|
||||
led_state state;
|
||||
};
|
||||
|
||||
void set_led_state(led *l, int state) {
|
||||
if (l != NULL) {
|
||||
l->state = state;
|
||||
gpio_put(l->gpio, l->state);
|
||||
}
|
||||
}
|
||||
|
||||
char* state_into_str(led_state state) {
|
||||
switch (state) {
|
||||
case ON:
|
||||
return "ON";
|
||||
case OFF:
|
||||
return "OFF";
|
||||
default:
|
||||
return "OFF";
|
||||
}
|
||||
}
|
||||
|
||||
void init_led_bar(led leds[]) {
|
||||
for (int i = 0; i < NB_LED_BAR_GPIO; i++, leds++) {
|
||||
*leds = (led) {
|
||||
.gpio = LED_BAR_GPIO[i], .state = OFF
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void print_led_bar_state(led leds[]) {
|
||||
for (int i = 0; i < NB_LED_BAR_GPIO; i++, leds++) {
|
||||
char *state = state_into_str(leds->state);
|
||||
char led_state[12];
|
||||
sprintf(led_state, "%3s (%d)", state, leds->gpio);
|
||||
if (i != NB_LED_BAR_GPIO - 1) {
|
||||
strcat(led_state, " | ");
|
||||
}
|
||||
printf(led_state);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert an integer into a 10 bits array (corresponding to the number of LED).
|
||||
*
|
||||
* It loops over the less to the most significant bit and for each bit, masks it with
|
||||
* the value to find if the value bit is 0 or 1 and then store it in the bits array.
|
||||
*
|
||||
* Example:
|
||||
* - value = 10 <=> 1010, i = 0
|
||||
* - left shift one: 1 << i <=> 0001 << 0 = 1
|
||||
* - mask the value with the shifted one: 1010 & 0001 = 0000
|
||||
* - find the result by right shifting the masked value by i: 0 >> 0 <=> 0000 >> 0 = 0
|
||||
* - i++
|
||||
*/
|
||||
int *int_into_bits(int value) {
|
||||
int *bits = malloc(NB_LED_BAR_GPIO * sizeof(int));
|
||||
for (int i = 0; i < NB_LED_BAR_GPIO; i++) {
|
||||
int mask = 1 << i;
|
||||
int masked_value = value & mask;
|
||||
// the first led is the rightmost, so we start feeding the bit array by the end
|
||||
bits[NB_LED_BAR_GPIO - 1 - i] = masked_value >> i;
|
||||
}
|
||||
return bits;
|
||||
}
|
||||
|
||||
void blink_failed(uint gpio, uint32_t delay_ms) {
|
||||
for (;;) {
|
||||
gpio_put(gpio, false);
|
||||
sleep_ms(delay_ms);
|
||||
|
||||
gpio_put(gpio, true);
|
||||
sleep_ms(delay_ms);
|
||||
}
|
||||
}
|
||||
|
||||
void set_default_led_state(led_state state) {
|
||||
gpio_put(PICO_DEFAULT_LED_PIN, state == ON);
|
||||
}
|
||||
|
||||
void run_bit_counter(led leds[], uint nb_bit, uint32_t delay_ms) {
|
||||
// nothing to do with 0 bit, entering in failed mode.
|
||||
if (nb_bit <= 0) {
|
||||
blink_failed(PICO_DEFAULT_LED_PIN, 500);
|
||||
return;
|
||||
}
|
||||
|
||||
// healthcheck
|
||||
set_default_led_state(ON);
|
||||
|
||||
// `nb_bit` can't be greater than the number of leds
|
||||
if (nb_bit > NB_LED_BAR_GPIO) {
|
||||
nb_bit = NB_LED_BAR_GPIO;
|
||||
}
|
||||
|
||||
// compute the maximum value
|
||||
int const max_value = 2 << nb_bit - 1;
|
||||
int current_value = 1;
|
||||
|
||||
for (;;) {
|
||||
if (current_value == max_value) {
|
||||
current_value = 1;
|
||||
led *p_leds = leds;
|
||||
|
||||
for (int i = 0; i < NB_LED_BAR_GPIO; i++, p_leds++) {
|
||||
set_led_state(p_leds, OFF);
|
||||
}
|
||||
|
||||
set_default_led_state(OFF);
|
||||
sleep_ms(delay_ms);
|
||||
set_default_led_state(ON);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
led *p_leds = leds;
|
||||
int *bits = int_into_bits(current_value);
|
||||
|
||||
int *p_bits = bits;
|
||||
for (int i = 0; i < NB_LED_BAR_GPIO; i++, p_leds++, p_bits++) {
|
||||
set_led_state(p_leds, *p_bits ? ON : OFF);
|
||||
}
|
||||
free(bits);
|
||||
|
||||
print_led_bar_state(leds);
|
||||
current_value++;
|
||||
|
||||
sleep_ms(delay_ms);
|
||||
}
|
||||
}
|
||||
|
||||
/* Initialize needed GPIO. */
|
||||
void init_gpio(void) {
|
||||
#ifdef PICO_DEFAULT_LED_PIN
|
||||
gpio_init(PICO_DEFAULT_LED_PIN);
|
||||
gpio_set_dir(PICO_DEFAULT_LED_PIN, GPIO_OUT);
|
||||
#endif
|
||||
|
||||
for (int i = 0; i < NB_LED_BAR_GPIO; i++) {
|
||||
gpio_init(LED_BAR_GPIO[i]);
|
||||
gpio_set_dir(LED_BAR_GPIO[i], GPIO_OUT);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Bit counter program with a LED bar.
|
||||
*
|
||||
* Increment a value, convert it in bit and display the value
|
||||
* on the LED bar (1: led on, 0 led OFF) until it reaches max value.
|
||||
*
|
||||
* BA-SIC. But it's fun to see the result.
|
||||
*
|
||||
* When the max value is reached, the program restarts.
|
||||
*
|
||||
* You can customize the incrementation speed and the number of bit to display
|
||||
* (max = number of led on the bar available) by changing the `run_bit_counter`
|
||||
* arguments.
|
||||
*
|
||||
* Ex: display only 4 bits (4 leds) with increment speed of 50 ms:
|
||||
* run_bit_counter(leds, 4, 50);
|
||||
*/
|
||||
int main() {
|
||||
stdio_init_all();
|
||||
init_gpio();
|
||||
|
||||
led leds[NB_LED_BAR_GPIO] = {};
|
||||
init_led_bar(leds);
|
||||
print_led_bar_state(leds);
|
||||
|
||||
run_bit_counter(leds, 11, 50);
|
||||
}
|
||||
@ -1,4 +1,4 @@
|
||||
#include <stdio.h>
|
||||
#include <pico/printf.h>
|
||||
#include <pico/stdlib.h>
|
||||
|
||||
int main()
|
||||
@ -6,7 +6,7 @@ int main()
|
||||
stdio_init_all();
|
||||
|
||||
while (true) {
|
||||
printf("<prog_name> is running...\n");
|
||||
stdio_printf("<prog_name> is running...\n");
|
||||
sleep_ms(1000);
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user