Skip to content

Commit

Permalink
Merge pull request #196 from pimoroni/patch-pico-unicorn-soft-reset
Browse files Browse the repository at this point in the history
Pico Unicorn: fix MP soft reset & cleanup
  • Loading branch information
Gadgetoid committed Aug 27, 2021
2 parents d1ca596 + 90c01f6 commit c117d34
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 19 deletions.
43 changes: 26 additions & 17 deletions libraries/pico_unicorn/pico_unicorn.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -101,10 +101,6 @@ namespace pimoroni {
dma_hw->ints0 = (1u << dma_channel); // clear irq flag
dma_channel_set_trans_count(dma_channel, BITSTREAM_LENGTH / 4, false);
dma_channel_set_read_addr(dma_channel, bitstream, true);

static bool hilo = false;
gpio_put(2, hilo);
hilo = !hilo;
}
}

Expand All @@ -125,14 +121,16 @@ namespace pimoroni {
}

void PicoUnicorn::init() {
// todo: shouldn't need to do this if things were cleaned up properly but without
// this any attempt to run a micropython script twice will fail
static bool already_init = false;

// setup pins
gpio_init(pin::LED_DATA); gpio_set_dir(pin::LED_DATA, GPIO_OUT);
gpio_init(pin::LED_CLOCK); gpio_set_dir(pin::LED_CLOCK, GPIO_OUT);
gpio_init(pin::LED_LATCH); gpio_set_dir(pin::LED_LATCH, GPIO_OUT);
gpio_init(pin::LED_BLANK); gpio_set_dir(pin::LED_BLANK, GPIO_OUT);

gpio_init(2); gpio_set_dir(2, GPIO_OUT);

gpio_init(pin::ROW_0); gpio_set_dir(pin::ROW_0, GPIO_OUT);
gpio_init(pin::ROW_1); gpio_set_dir(pin::ROW_1, GPIO_OUT);
gpio_init(pin::ROW_2); gpio_set_dir(pin::ROW_2, GPIO_OUT);
Expand Down Expand Up @@ -186,26 +184,37 @@ namespace pimoroni {
}
}

// setup the pio
bitstream_pio = pio0;
bitstream_sm = pio_claim_unused_sm(pio0, true);
uint offset = pio_add_program(bitstream_pio, &unicorn_program);
unicorn_jetpack_program_init(bitstream_pio, bitstream_sm, offset);

// setup button inputs
gpio_set_function(pin::A, GPIO_FUNC_SIO); gpio_set_dir(pin::A, GPIO_IN); gpio_pull_up(pin::A);
gpio_set_function(pin::B, GPIO_FUNC_SIO); gpio_set_dir(pin::B, GPIO_IN); gpio_pull_up(pin::B);
gpio_set_function(pin::X, GPIO_FUNC_SIO); gpio_set_dir(pin::X, GPIO_IN); gpio_pull_up(pin::X);
gpio_set_function(pin::Y, GPIO_FUNC_SIO); gpio_set_dir(pin::Y, GPIO_IN); gpio_pull_up(pin::Y);

// todo: shouldn't need to do this if things were cleaned up properly but without
// this any attempt to run a micropython script twice will fail
static bool already_init = false;

if(already_init) {
return;
// stop and release the dma channel
irq_set_enabled(DMA_IRQ_0, false);
dma_channel_abort(dma_channel);
dma_channel_wait_for_finish_blocking(dma_channel);

dma_channel_set_irq0_enabled(dma_channel, false);
irq_set_enabled(pio_get_dreq(bitstream_pio, bitstream_sm, true), false);
irq_remove_handler(DMA_IRQ_0, dma_complete);

dma_channel_unclaim(dma_channel);

// release the pio and sm
pio_sm_unclaim(bitstream_pio, bitstream_sm);
pio_clear_instruction_memory(bitstream_pio);
pio_sm_restart(bitstream_pio, bitstream_sm);
//return;
}

// setup the pio
bitstream_pio = pio0;
bitstream_sm = pio_claim_unused_sm(pio0, true);
sm_offset = pio_add_program(bitstream_pio, &unicorn_program);
unicorn_jetpack_program_init(bitstream_pio, bitstream_sm, sm_offset);

// setup dma transfer for pixel data to the pio
dma_channel = dma_claim_unused_channel(true);
dma_channel_config config = dma_channel_get_default_config(dma_channel);
Expand Down
3 changes: 1 addition & 2 deletions libraries/pico_unicorn/pico_unicorn.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,9 @@ namespace pimoroni {
static const uint8_t X = 14;
static const uint8_t Y = 15;
private:
uint32_t __fb[WIDTH * HEIGHT];
PIO bitstream_pio = pio0;
uint bitstream_sm = 0;

uint sm_offset = 0;
public:
~PicoUnicorn();

Expand Down
40 changes: 40 additions & 0 deletions micropython/examples/pico_unicorn/rainbow.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import picounicorn
import time

picounicorn.init()


# From CPython Lib/colorsys.py
def hsv_to_rgb(h, s, v):
if s == 0.0:
return v, v, v
i = int(h * 6.0)
f = (h * 6.0) - i
p = v * (1.0 - s)
q = v * (1.0 - s * f)
t = v * (1.0 - s * (1.0 - f))
i = i % 6
if i == 0:
return v, t, p
if i == 1:
return q, v, p
if i == 2:
return p, v, t
if i == 3:
return p, q, v
if i == 4:
return t, p, v
if i == 5:
return v, p, q


w = picounicorn.get_width()
h = picounicorn.get_height()

while True:
t = time.ticks_ms() / 3600
for x in range(w):
for y in range(h):
r, g, b = [int(c * 255) for c in hsv_to_rgb(t + ((x + y) / w / 4), 1.0, 1.0)]
picounicorn.set_pixel(x, y, r, g, b)
time.sleep(1.0 / 60)

0 comments on commit c117d34

Please sign in to comment.