Skip to content

Commit

Permalink
Merge branch 'main' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
grymmy authored Oct 22, 2024
2 parents 4d92aeb + 4fe88e9 commit a3f18ba
Show file tree
Hide file tree
Showing 51 changed files with 5,290 additions and 1,961 deletions.
13 changes: 12 additions & 1 deletion .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,15 @@ GRAPHITE_HOST=
STUCK_AIRTABLE_BASE=
SENDGRID_API_KEY=
LOOPS_API_KEY=
DEV_CODE=
DEV_CODE=

PUBLIC_SPRIG_LLM_API=
EMAIL_FROM=
EMAIL_REPLY_TO=
PUBLIC_SIGNALING_SERVER_HOST=
GITHUB_CLIENT_SECRET=
PUBLIC_GITHUB_CLIENT_ID=
PUBLIC_GITHUB_REDIRECT_URI=
PUBLIC_GALLERY_API=
MAX_ATTEMPTS=
LOCKOUT_DURATION_MS=
1 change: 1 addition & 0 deletions firmware/c_scaffold/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
build
48 changes: 48 additions & 0 deletions firmware/c_scaffold/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
cmake_minimum_required(VERSION 3.24)
set(CMAKE_C_STANDARD 11)
set(CMAKE_CXX_STANDARD 17)

if (NOT PICO_SDK_PATH)
set(PICO_SDK_PATH "~/raspberrypi/pico-sdk")
endif ()

if (NOT PICO_EXTRAS_PATH)
set(PICO_EXTRAS_PATH "~/raspberrypi/pico-extras")
endif ()

include(cmake/pico_sdk_import.cmake)
include(cmake/pico_extras_import.cmake)

project(c_scaffold C CXX)

set(CMAKE_BUILD_TYPE Release)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-void-pointer-to-int-cast -Wno-int-to-void-pointer-cast -Wno-pointer-sign -Werror=implicit-function-declaration")

add_executable(${PROJECT_NAME} "src/main.c")

target_include_directories(${PROJECT_NAME} PRIVATE "src/")

pico_sdk_init()
add_definitions(
-DSAMPLES_PER_BUFFER=\(256*6\)
-DBUFFER_COUNT=3
)

pico_enable_stdio_usb(${PROJECT_NAME} 1)
pico_enable_stdio_uart(${PROJECT_NAME} 1)

add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/../sprig_hal sprig_hal)

target_link_libraries(${PROJECT_NAME} PRIVATE
pico_stdlib
pico_multicore
hardware_spi
hardware_timer
hardware_pwm
hardware_adc
sprig_hal
)

# create map/bin/hex file etc.
pico_add_extra_outputs(${PROJECT_NAME})

1 change: 1 addition & 0 deletions firmware/c_scaffold/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Sprig C Firmware Scaffold
62 changes: 62 additions & 0 deletions firmware/c_scaffold/cmake/pico_extras_import.cmake
Original file line number Diff line number Diff line change
@@ -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)
73 changes: 73 additions & 0 deletions firmware/c_scaffold/cmake/pico_sdk_import.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
# This is a copy of <PICO_SDK_PATH>/external/pico_sdk_import.cmake

# This can be dropped into an external project to help locate this SDK
# It should be include()ed prior to project()

if (DEFINED ENV{PICO_SDK_PATH} AND (NOT PICO_SDK_PATH))
set(PICO_SDK_PATH $ENV{PICO_SDK_PATH})
message("Using PICO_SDK_PATH from environment ('${PICO_SDK_PATH}')")
endif ()

if (DEFINED ENV{PICO_SDK_FETCH_FROM_GIT} AND (NOT PICO_SDK_FETCH_FROM_GIT))
set(PICO_SDK_FETCH_FROM_GIT $ENV{PICO_SDK_FETCH_FROM_GIT})
message("Using PICO_SDK_FETCH_FROM_GIT from environment ('${PICO_SDK_FETCH_FROM_GIT}')")
endif ()

if (DEFINED ENV{PICO_SDK_FETCH_FROM_GIT_PATH} AND (NOT PICO_SDK_FETCH_FROM_GIT_PATH))
set(PICO_SDK_FETCH_FROM_GIT_PATH $ENV{PICO_SDK_FETCH_FROM_GIT_PATH})
message("Using PICO_SDK_FETCH_FROM_GIT_PATH from environment ('${PICO_SDK_FETCH_FROM_GIT_PATH}')")
endif ()

set(PICO_SDK_PATH "${PICO_SDK_PATH}" CACHE PATH "Path to the Raspberry Pi Pico SDK")
set(PICO_SDK_FETCH_FROM_GIT "${PICO_SDK_FETCH_FROM_GIT}" CACHE BOOL "Set to ON to fetch copy of SDK from git if not otherwise locatable")
set(PICO_SDK_FETCH_FROM_GIT_PATH "${PICO_SDK_FETCH_FROM_GIT_PATH}" CACHE FILEPATH "location to download SDK")

if (NOT PICO_SDK_PATH)
if (PICO_SDK_FETCH_FROM_GIT)
include(FetchContent)
set(FETCHCONTENT_BASE_DIR_SAVE ${FETCHCONTENT_BASE_DIR})
if (PICO_SDK_FETCH_FROM_GIT_PATH)
get_filename_component(FETCHCONTENT_BASE_DIR "${PICO_SDK_FETCH_FROM_GIT_PATH}" REALPATH BASE_DIR "${CMAKE_SOURCE_DIR}")
endif ()
# GIT_SUBMODULES_RECURSE was added in 3.17
if (${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.17.0")
FetchContent_Declare(
pico_sdk
GIT_REPOSITORY https://github.com/raspberrypi/pico-sdk
GIT_TAG master
GIT_SUBMODULES_RECURSE FALSE
)
else ()
FetchContent_Declare(
pico_sdk
GIT_REPOSITORY https://github.com/raspberrypi/pico-sdk
GIT_TAG master
)
endif ()

if (NOT pico_sdk)
message("Downloading Raspberry Pi Pico SDK")
FetchContent_Populate(pico_sdk)
set(PICO_SDK_PATH ${pico_sdk_SOURCE_DIR})
endif ()
set(FETCHCONTENT_BASE_DIR ${FETCHCONTENT_BASE_DIR_SAVE})
else ()
message(FATAL_ERROR
"SDK location was not specified. Please set PICO_SDK_PATH or set PICO_SDK_FETCH_FROM_GIT to on to fetch from git."
)
endif ()
endif ()

get_filename_component(PICO_SDK_PATH "${PICO_SDK_PATH}" REALPATH BASE_DIR "${CMAKE_BINARY_DIR}")
if (NOT EXISTS ${PICO_SDK_PATH})
message(FATAL_ERROR "Directory '${PICO_SDK_PATH}' not found")
endif ()

set(PICO_SDK_INIT_CMAKE_FILE ${PICO_SDK_PATH}/pico_sdk_init.cmake)
if (NOT EXISTS ${PICO_SDK_INIT_CMAKE_FILE})
message(FATAL_ERROR "Directory '${PICO_SDK_PATH}' does not appear to contain the Raspberry Pi Pico SDK")
endif ()

set(PICO_SDK_PATH ${PICO_SDK_PATH} CACHE PATH "Path to the Raspberry Pi Pico SDK" FORCE)

include(${PICO_SDK_INIT_CMAKE_FILE})
39 changes: 39 additions & 0 deletions firmware/c_scaffold/src/audio.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#ifndef C_SCAFFOLD_AUDIO_H
#define C_SCAFFOLD_AUDIO_H

#include <math.h>
#include "HAL.h"

#define SINE_WAVE_TABLE_LEN 2048

int16_t sine_wave_table[SINE_WAVE_TABLE_LEN];

// precalculate a sine wave and store it in sine_wave_table
void init_sine_wave_table() {
for (int i = 0; i < SINE_WAVE_TABLE_LEN; i++) {
sine_wave_table[i] = 32767 * cosf(i * 2 * (float) (M_PI / SINE_WAVE_TABLE_LEN));
}
}

void play_sine_wave(uint32_t step, uint32_t volume) {
// get a free audio buffer from the pool
struct audio_buffer *buffer = get_audio_buffer(false);
if (buffer == NULL) return; // if there aren't free buffers, return early

uint32_t pos_max = 0x10000 * SINE_WAVE_TABLE_LEN;
uint32_t pos = 0;

int16_t *samples = (int16_t *) buffer->buffer->bytes; // reference to buffer bytes
for (uint i = 0; i < buffer->max_sample_count; i++) {
// sample the sine wave at position pos, and write to buffer
samples[i] = (volume * sine_wave_table[pos >> 16u]) >> 8u;

// increment pos; if step is larger, it'll move faster thru the sine wave, and pitch is higher
pos += step;
if (pos >= pos_max) pos -= pos_max; // wrap back around if past end of wave
}
buffer->sample_count = buffer->max_sample_count;
push_audio_buffer(buffer); // push filled buffer into the pool
}

#endif //C_SCAFFOLD_AUDIO_H
85 changes: 85 additions & 0 deletions firmware/c_scaffold/src/buttons.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
#ifndef C_SCAFFOLD_BUTTONS_H
#define C_SCAFFOLD_BUTTONS_H

/**
* We store a 64-boolean ringbuffer of polled button states for a primitive
* sort of debouncing. The button counts as pressed if more than 5/6th of
* the ringbuffer is true.
*
* (gpio_set_input_hysteresis_enabled was too slow.)
*/
#include "HAL.h"
#include "pico/util/queue.h"
#include "pico/multicore.h"

#define HISTORY_LEN (64)

typedef struct {
uint8_t history[HISTORY_LEN / 8];
uint8_t last_state;
uint8_t ring_i;
} ButtonState;

ButtonState button_states[8] = {0};

bool button_history_read(ButtonState *bs, int i) {
// We want to store bools compactly so we have to do some bit twiddling.
int q = 1 << (i % 8);
return !!(bs->history[i / 8] & q);
}

void button_history_write(ButtonState *bs, int i, bool value) {
if (value)
bs->history[i / 8] |= 1 << (i % 8);
else
bs->history[i / 8] &= ~(1 << (i % 8));
}

/**
* Poll the buttons and push any keypresses to the main core.
*
* (Should be run in a loop on a non-primary core.)
*/
void button_poll(void) {
for (;;) {
for (int i = 0; i < 8; i++) {
ButtonState *bs = button_states + i;

bs->ring_i = (bs->ring_i + 1) % HISTORY_LEN; // Incrememnt ringbuffer index
button_history_write(bs, bs->ring_i, get_button( (Sprig_Button) i));

// up is true if more than 5/6 are true
int up = 0;
for (int i = 0; i < HISTORY_LEN; i++) {
up += button_history_read(bs, i);
}
up = up > ((HISTORY_LEN * 5) / 6); // Here we convert to a bool

if (up != bs->last_state) {
bs->last_state = up;
if (!up) {
// Send the keypress to the main core
multicore_fifo_push_blocking(i);
}
}
}
}
}

Sprig_Button get_button_press() {
if (!multicore_fifo_rvalid()) return Button_None;
return (Sprig_Button) multicore_fifo_pop_blocking();
}

void init_button_handler() {
// Start a core to listen for keypresses.
multicore_reset_core1();
multicore_launch_core1(button_poll);

/* We get a bunch of fake keypresses at startup, so we need to
* drain them from the FIFO queue. */
sleep_ms(50);
while (multicore_fifo_rvalid()) multicore_fifo_pop_blocking();
}

#endif //C_SCAFFOLD_BUTTONS_H
28 changes: 28 additions & 0 deletions firmware/c_scaffold/src/common.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#ifndef C_SCAFFOLD_COMMON_H
#define C_SCAFFOLD_COMMON_H

#define SCREEN_SIZE_X (160)
#define SCREEN_SIZE_Y (128)

#define TEXT_CHARS_MAX_X (20)
#define TEXT_CHARS_MAX_Y (16)

#define ARR_LEN(arr) (sizeof(arr) / sizeof(arr[0]))

uint8_t flip_endianness(uint8_t in) {
in = ((in & 0x0F) << 4) | ((in & 0xF0) >> 4);
in = ((in & 0b00110011) << 2) | ((in & 0b11001100) >> 2);
in = ((in & 0b01010101) << 1) | ((in & 0b10101010) >> 1);
return in;
}

uint16_t color16(uint8_t r, uint8_t g, uint8_t b) {
// arrange bits in 5-6-5 (BBBBBGGG GGGRRRRR)
uint16_t result = ((b & 0b11111000) << 8) | ((g & 0b11111100) << 3) | (r >> 3);

// swap bytes to conform to display endianness
return ((result & 0x00FF) << 8) | ((result & 0xFF00) >> 8);
}


#endif //C_SCAFFOLD_COMMON_H
Loading

0 comments on commit a3f18ba

Please sign in to comment.