add basic state machine

This commit is contained in:
Laila van Reenen 2025-01-13 19:28:52 +01:00
parent 85f6f53f34
commit ef76d8e35f
Signed by: LailaTheElf
GPG Key ID: 8A3EF0226518C12D
7 changed files with 151 additions and 85 deletions

3
.gitmodules vendored
View File

@ -1,3 +1,6 @@
[submodule "libs/pico-sdk"]
path = libs/pico-sdk
url = https://github.com/raspberrypi/pico-sdk.git
[submodule "libs/pico-extra"]
path = libs/pico-extra
url = https://github.com/raspberrypi/pico-extras.git

View File

@ -1,8 +1,11 @@
cmake_minimum_required(VERSION 3.13)
set(PICO_EXTRAS_PATH ${CMAKE_CURRENT_LIST_DIR}/libs/pico-extra)
# initialize the SDK based on PICO_SDK_PATH
# note: this must happen before project()
include(libs/pico-sdk/pico_sdk_init.cmake)
include(pico_extras_import.cmake)
project(stofzuiger CXX C ASM)
@ -14,10 +17,10 @@ pico_sdk_init()
add_executable(stofzuiger src/main.c)
# pico_generate_pio_header(stofzuiger ${CMAKE_CURRENT_LIST_DIR}/src/ws2812.pio)
pico_generate_pio_header(stofzuiger ${CMAKE_CURRENT_LIST_DIR}/src/ws2812.pio OUTPUT_DIR ${CMAKE_CURRENT_LIST_DIR}/src/generated)
target_link_libraries(stofzuiger pico_stdlib hardware_pio)
target_link_libraries(stofzuiger
pico_stdlib
hardware_sleep
)
pico_enable_stdio_uart(stofzuiger 0)
pico_enable_stdio_usb(stofzuiger 1)

1
libs/pico-extra Submodule

@ -0,0 +1 @@
Subproject commit f05d4f7371802440cadd36744789a26944d950ac

62
pico_extras_import.cmake Normal file
View File

@ -0,0 +1,62 @@
# This is a copy of <PICO_EXTRAS_PATH>/external/pico_extras_import.cmake
# This can be dropped into an external project to help locate pico-extras
# It should be include()ed prior to project()
if (DEFINED ENV{PICO_EXTRAS_PATH} AND (NOT PICO_EXTRAS_PATH))
set(PICO_EXTRAS_PATH $ENV{PICO_EXTRAS_PATH})
message("Using PICO_EXTRAS_PATH from environment ('${PICO_EXTRAS_PATH}')")
endif ()
if (DEFINED ENV{PICO_EXTRAS_FETCH_FROM_GIT} AND (NOT PICO_EXTRAS_FETCH_FROM_GIT))
set(PICO_EXTRAS_FETCH_FROM_GIT $ENV{PICO_EXTRAS_FETCH_FROM_GIT})
message("Using PICO_EXTRAS_FETCH_FROM_GIT from environment ('${PICO_EXTRAS_FETCH_FROM_GIT}')")
endif ()
if (DEFINED ENV{PICO_EXTRAS_FETCH_FROM_GIT_PATH} AND (NOT PICO_EXTRAS_FETCH_FROM_GIT_PATH))
set(PICO_EXTRAS_FETCH_FROM_GIT_PATH $ENV{PICO_EXTRAS_FETCH_FROM_GIT_PATH})
message("Using PICO_EXTRAS_FETCH_FROM_GIT_PATH from environment ('${PICO_EXTRAS_FETCH_FROM_GIT_PATH}')")
endif ()
if (NOT PICO_EXTRAS_PATH)
if (PICO_EXTRAS_FETCH_FROM_GIT)
include(FetchContent)
set(FETCHCONTENT_BASE_DIR_SAVE ${FETCHCONTENT_BASE_DIR})
if (PICO_EXTRAS_FETCH_FROM_GIT_PATH)
get_filename_component(FETCHCONTENT_BASE_DIR "${PICO_EXTRAS_FETCH_FROM_GIT_PATH}" REALPATH BASE_DIR "${CMAKE_SOURCE_DIR}")
endif ()
FetchContent_Declare(
pico_extras
GIT_REPOSITORY https://github.com/raspberrypi/pico-extras
GIT_TAG master
)
if (NOT pico_extras)
message("Downloading PICO EXTRAS")
FetchContent_Populate(pico_extras)
set(PICO_EXTRAS_PATH ${pico_extras_SOURCE_DIR})
endif ()
set(FETCHCONTENT_BASE_DIR ${FETCHCONTENT_BASE_DIR_SAVE})
else ()
if (PICO_SDK_PATH AND EXISTS "${PICO_SDK_PATH}/../pico-extras")
set(PICO_EXTRAS_PATH ${PICO_SDK_PATH}/../pico-extras)
message("Defaulting PICO_EXTRAS_PATH as sibling of PICO_SDK_PATH: ${PICO_EXTRAS_PATH}")
else()
message(FATAL_ERROR
"PICO EXTRAS location was not specified. Please set PICO_EXTRAS_PATH or set PICO_EXTRAS_FETCH_FROM_GIT to on to fetch from git."
)
endif()
endif ()
endif ()
set(PICO_EXTRAS_PATH "${PICO_EXTRAS_PATH}" CACHE PATH "Path to the PICO EXTRAS")
set(PICO_EXTRAS_FETCH_FROM_GIT "${PICO_EXTRAS_FETCH_FROM_GIT}" CACHE BOOL "Set to ON to fetch copy of PICO EXTRAS from git if not otherwise locatable")
set(PICO_EXTRAS_FETCH_FROM_GIT_PATH "${PICO_EXTRAS_FETCH_FROM_GIT_PATH}" CACHE FILEPATH "location to download EXTRAS")
get_filename_component(PICO_EXTRAS_PATH "${PICO_EXTRAS_PATH}" REALPATH BASE_DIR "${CMAKE_BINARY_DIR}")
if (NOT EXISTS ${PICO_EXTRAS_PATH})
message(FATAL_ERROR "Directory '${PICO_EXTRAS_PATH}' not found")
endif ()
set(PICO_EXTRAS_PATH ${PICO_EXTRAS_PATH} CACHE PATH "Path to the PICO EXTRAS" FORCE)
add_subdirectory(${PICO_EXTRAS_PATH} pico_extras)

View File

@ -1,2 +0,0 @@
*
!.gitignore

View File

@ -4,47 +4,99 @@
#include <stdbool.h>
#include <pico/stdlib.h>
#include <hardware/pio.h>
#include <hardware/clocks.h>
#include "generated/ws2812.pio.h"
#include <pico/sleep.h>
#define IS_RGBW false
#define NUM_PIXELS 1
#define WS2812_PIN 16
static inline void put_pixel(PIO pio, uint sm, uint32_t pixel_grb) {
pio_sm_put_blocking(pio, sm, pixel_grb << 8u);
}
#define PIN_LED_MODE_RED 0
#define PIN_LED_MODE_GREEN 1
#define PIN_LED_BATT1 2
#define PIN_LED_BATT2 3
#define PIN_LED_BATT3 4
#define PIN_BTN 5
#define PIN_MOTOR_IO1 6
#define PIN_MOTOR_IO2 7
#define PIN_MOTOR_PWM 8
static inline uint32_t urgb_u32(uint8_t r, uint8_t g, uint8_t b) {
return ((uint32_t) (r) << 8) | ((uint32_t) (g) << 16) | (uint32_t) (b);
typedef enum {
STATE_OFF,
STATE_HIGE,
STATE_LOW
} mainState_t;
mainState_t mainState;
void update_state(mainState_t state)
{
switch (state)
{
case STATE_OFF:
gpio_put(PIN_MOTOR_IO1, 0);
gpio_put(PIN_MOTOR_IO2, 0);
break;
case STATE_HIGE:
gpio_put(PIN_MOTOR_IO1, 1);
gpio_put(PIN_MOTOR_IO2, 0);
break;
case STATE_LOW:
gpio_put(PIN_MOTOR_IO1, 0);
gpio_put(PIN_MOTOR_IO2, 1);
break;
}
}
int main() {
//set_sys_clock_48();
stdio_init_all();
printf("WS2812 test %d\n", WS2812_PIN);
// todo get free sm
PIO pio;
uint sm;
uint offset;
mainState = STATE_OFF;
// This will find a free pio and state machine for our program and load it for us
// We use pio_claim_free_sm_and_add_program_for_gpio_range (for_gpio_range variant)
// so we will get a PIO instance suitable for addressing gpios >= 32 if needed and supported by the hardware
bool success = pio_claim_free_sm_and_add_program_for_gpio_range(&ws2812_program, &pio, &sm, &offset, WS2812_PIN, 1, false);
if (success == false)
// init gpio outputs
gpio_init(PIN_LED_MODE_RED);
gpio_set_dir(PIN_LED_MODE_RED, GPIO_OUT);
gpio_put(PIN_LED_MODE_RED, 0);
gpio_init(PIN_LED_MODE_GREEN);
gpio_set_dir(PIN_LED_MODE_GREEN, GPIO_OUT);
gpio_put(PIN_LED_MODE_GREEN, 0);
gpio_init(PIN_LED_BATT1);
gpio_set_dir(PIN_LED_BATT1, GPIO_OUT);
gpio_put(PIN_LED_BATT1, 0);
gpio_init(PIN_LED_BATT2);
gpio_set_dir(PIN_LED_BATT2, GPIO_OUT);
gpio_put(PIN_LED_BATT2, 0);
gpio_init(PIN_LED_BATT3);
gpio_set_dir(PIN_LED_BATT3, GPIO_OUT);
gpio_put(PIN_LED_BATT3, 0);
gpio_set_dir(PIN_MOTOR_IO1, GPIO_OUT);
gpio_put(PIN_MOTOR_IO1, 0);
gpio_set_dir(PIN_MOTOR_IO2, GPIO_OUT);
gpio_put(PIN_MOTOR_IO2, 0);
// init gpio inputs
gpio_init(PIN_BTN);
gpio_set_dir(PIN_BTN, GPIO_IN);
while (true)
{
printf("Faild to claim PIO or SM");
return -1;
mainState = STATE_OFF;
update_state(STATE_OFF);
sleep_goto_dormant_until_edge_high(PIN_BTN);
mainState = STATE_HIGE;
while (mainState != STATE_OFF)
{
switch (mainState) {
case STATE_HIGE:
mainState = STATE_LOW;
break;
case STATE_LOW:
mainState = STATE_OFF;
break;
}
update_state(mainState);
}
}
ws2812_program_init(pio, sm, offset, WS2812_PIN, 800000, false);
put_pixel(pio, sm, urgb_u32(50, 50, 50));
// This will free resources and unload our program
pio_remove_program_and_unclaim_sm(&ws2812_program, pio, sm, offset);
return 0;
}

View File

@ -1,53 +0,0 @@
;
; Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
;
; SPDX-License-Identifier: BSD-3-Clause
;
.pio_version 0 // only requires PIO version 0
.program ws2812
.side_set 1
; The following constants are selected for broad compatibility with WS2812,
; WS2812B, and SK6812 LEDs. Other constants may support higher bandwidths for
; specific LEDs, such as (7,10,8) for WS2812B LEDs.
.define public T1 3
.define public T2 3
.define public T3 4
.lang_opt python sideset_init = pico.PIO.OUT_HIGH
.lang_opt python out_init = pico.PIO.OUT_HIGH
.lang_opt python out_shiftdir = 1
.wrap_target
bitloop:
out x, 1 side 0 [T3 - 1] ; Side-set still takes place when instruction stalls
jmp !x do_zero side 1 [T1 - 1] ; Branch on the bit we shifted out. Positive pulse
do_one:
jmp bitloop side 1 [T2 - 1] ; Continue driving high, for a long pulse
do_zero:
nop side 0 [T2 - 1] ; Or drive low, for a short pulse
.wrap
% c-sdk {
#include "hardware/clocks.h"
static inline void ws2812_program_init(PIO pio, uint sm, uint offset, uint pin, float freq, bool rgbw) {
pio_gpio_init(pio, pin);
pio_sm_set_consecutive_pindirs(pio, sm, pin, 1, true);
pio_sm_config c = ws2812_program_get_default_config(offset);
sm_config_set_sideset_pins(&c, pin);
sm_config_set_out_shift(&c, false, true, rgbw ? 32 : 24);
sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_TX);
int cycles_per_bit = ws2812_T1 + ws2812_T2 + ws2812_T3;
float div = clock_get_hz(clk_sys) / (freq * cycles_per_bit);
sm_config_set_clkdiv(&c, div);
pio_sm_init(pio, sm, offset, &c);
pio_sm_set_enabled(pio, sm, true);
}
%}