Created
November 4, 2024 21:49
-
-
Save Lukelectro/bcded0cc4e09df868421af01b088456b to your computer and use it in GitHub Desktop.
Playlogic - play logic patterns on raspberry pi pico pins using the pio, as a proof of concept pattern generator
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
to name gist |
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
cmake_minimum_required(VERSION 3.13) | |
# Pull in SDK (must be before project) | |
include(pico_sdk_import.cmake) | |
project(playlogic C CXX ASM) | |
set(CMAKE_C_STANDARD 11) | |
set(CMAKE_CXX_STANDARD 17) | |
set(PICO_BOARD pico_w) #compile for pico_w board | |
if (PICO_SDK_VERSION_STRING VERSION_LESS "1.3.0") | |
message(FATAL_ERROR "Raspberry Pi Pico SDK version 1.3.0 (or later) required. Your version is ${PICO_SDK_VERSION_STRING}") | |
endif() | |
# Initialize the SDK | |
pico_sdk_init() | |
add_executable(playlogic) | |
target_sources(playlogic PUBLIC playlogic.c) | |
pico_generate_pio_header(playlogic ${CMAKE_CURRENT_LIST_DIR}/playlogic.pio) | |
#target_include_directories(playlogic PUBLIC folder1 folder2) | |
target_link_libraries(playlogic pico_stdlib hardware_pio) | |
pico_enable_stdio_usb(playlogic 1) | |
pico_enable_stdio_uart(playlogic 0) | |
pico_add_extra_outputs(playlogic) |
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
#include <stdio.h> | |
#include "pico/stdlib.h" | |
#include "hardware/gpio.h" | |
#include "pico/binary_info.h" | |
#include "playlogic.pio.h" | |
/* | |
* Bitpattern in the form of "output bits, delay, output bits, delay etc.". | |
* Can be changed in RAM in running debuger to quickly test external hardware. | |
* Like an osiloscope and signal generator can be used for analogue circuits, this pattern generator and a logic analyser can be used to test digital circuits. | |
* | |
* The example displays HELLO in the logic analyser window and uses the upper 8 bits. But it can be change it at runtime in a debugger. | |
* (Or, with an adition to this program, over (usb) serial port... That would be less cumbersome) | |
* | |
* Note: In case you change this to use other pins and need some 'regular' IO too: | |
* It is possible to assign pins to regular GPIO (SIO) even when they are in the OUT pingroup of PIO. | |
* Being in the OUT group but not assigned to PIO they can be assigned to other peripherals, like SIO. | |
*/ | |
#define SIZE 1234 | |
uint32_t pattern[SIZE] = | |
{0xFFFF, 5, 0x0000, 25, | |
0xFF, 2, 0x18, 3, 0xFF, 2, //H | |
0x00, 3, | |
0xFF, 1, 0x99, 3, // E | |
0x00, 3, | |
0xFF, 1, 0x80, 3, // L | |
0x00, 3, | |
0xff, 1, 0x80, 3, // L | |
0x00, 3, | |
0xff, 1, 0x81, 2, 0xff, 1, // O | |
0x00, 20, | |
0x7F, 1, 0x80, 1, 0xC0, 1, 0x80, 1, 0x7F, 1, // W | |
0x00, 3, | |
0xff, 1, 0x81, 2, 0xff, 1, // O | |
0x00, 3, | |
0xFF, 1, 0x09,1, 0x29,1 ,0x87,1, 0x80,1, // R | |
0x00, 3, | |
0xff, 1, 0x80, 3, // L | |
0x00, 3, | |
0xf0, 1, 0x90, 2, 0xff, 1, // d | |
0x00, 40, | |
}; | |
uint size = SIZE; // size is a variable so size can be changed with debugger also. | |
#define STARTPIN 0 // it uses all pins, starting from this one, wrapping around at 32 | |
int main() | |
{ | |
bi_decl(bi_program_description("This is a test binary. PlayLogic: a logic pattern generator that plays from RAM in a debugger")); | |
stdio_init_all(); | |
pio_sm_claim(pio0, 0); | |
PIO pio = pio0; | |
uint offset = pio_add_program(pio, &playlogic_program); | |
uint sm = pio_claim_unused_sm(pio, true); | |
playlogic_program_init(pio, sm, offset, STARTPIN, 25000000); | |
while (1) | |
{ | |
for (uint i = 0; i < size; i++) | |
{ | |
pio_sm_put_blocking(pio, sm, pattern[i]); // write pattern to PIO, wait if FIFO Full (else there would be data loss). | |
} | |
} | |
} |
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
.program playlogic | |
; | |
; // some sort of waveform generator // logic 'stimulator' / waveform player / pattern generator etc. | |
; | |
; // this can play waveforms stored in the format "[bits] [delay] [bits] [delay] repeat as long as needed" where both bits and delay are 32 bits | |
; // these waveforms can then be autopulled | |
; // it could be a simple way to control basicly any external hardware that needs IO toggling, without wasting a lot of pio instructions on the waveforms for it, as these | |
; // waveforms can then be stored in an array that gets send to the PIO, potentially even by DMA (Not nescesairy, especially if pattern size is under FIFO size). | |
.wrap_target | |
out pins 32 | |
out x 32 | |
waitlbl: | |
jmp x-- waitlbl | |
.wrap | |
% c-sdk { | |
#include "hardware/clocks.h" | |
static inline void playlogic_program_init(PIO pio, uint sm, uint offset, uint pinbase, uint clockspeed) | |
{ | |
pio_sm_config c = playlogic_program_get_default_config(offset); | |
// set ALL pins for use with OUT | |
sm_config_set_out_pins(&c, pinbase, 32); | |
// Set this pin's GPIO function (connect PIO to the pad) | |
for (uint i = 0; i < 32; i++) | |
{ | |
pio_gpio_init(pio, pinbase + i); | |
} | |
// Set the pin direction to output at the PIO | |
pio_sm_set_consecutive_pindirs(pio, sm, pinbase, 32, true); | |
float div = clock_get_hz(clk_sys) / clockspeed; // set clockspeed | |
sm_config_set_clkdiv(&c, div); | |
// join both 4-level fifo's into one output fifo (8 levels), as there is no input to CPU from this statemachine | |
sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_TX); | |
sm_config_set_out_shift(&c, true, true, 32); // autopull when 32 bits have been shifted out, right | |
// Load our configuration, and jump to the start of the program | |
pio_sm_init(pio, sm, offset, &c); | |
// Set the state machine running | |
pio_sm_set_enabled(pio, sm, true); | |
} | |
static inline void playlogic_blinkaled(PIO pio, uint sm) | |
{ | |
#define DATALENGTH 8 | |
uint data[DATALENGTH] = {0x11111111, 200, 0x22222222, 200, 0x44444444, 0x200, 0x88888888, 300}; // blink LED's on all pins alternating, with 200 and 300 cycles of delay | |
for (uint i = 0; i < DATALENGTH; i++) | |
{ | |
pio_sm_put(pio, sm, data[i]); | |
} | |
} | |
%} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment