// -------------------------------------------------- //
// This file is autogenerated by pioasm; do not edit! //
// -------------------------------------------------- //

#pragma once

#if !PICO_NO_HARDWARE
#include "hardware/pio.h"
#endif

// --- //
// tft //
// --- //

#define tft_wrap_target 0
#define tft_wrap 1

static const uint16_t tft_program_instructions[] = {
            //     .wrap_target
    0x6001, //  0: out    pins, 1         side 0     
    0xb042, //  1: nop                    side 1     
            //     .wrap
};

#if !PICO_NO_HARDWARE
static const struct pio_program tft_program = {
    .instructions = tft_program_instructions,
    .length = 2,
    .origin = -1,
};

static inline pio_sm_config tft_program_get_default_config(uint offset) {
    pio_sm_config c = pio_get_default_sm_config();
    sm_config_set_wrap(&c, offset + tft_wrap_target, offset + tft_wrap);
    sm_config_set_sideset(&c, 1, false, false);
    return c;
}

// For optimal use of DMA bandwidth we would use an autopull threshold of 32,
// but we are using a threshold of 8 here (consume 1 byte from each FIFO entry
// and discard the remainder) to make things easier for software on the other side
#include <stdlib.h>
static inline void tft_program_init(PIO pio, uint sm, uint offset, uint data_pin, uint clk_pin, float clk_div) {
    pio_gpio_init(pio, data_pin);
    pio_gpio_init(pio, clk_pin);
    pio_sm_set_consecutive_pindirs(pio, sm, data_pin, 1, true);
    pio_sm_set_consecutive_pindirs(pio, sm, clk_pin, 1, true);
    pio_sm_config c = tft_program_get_default_config(offset);
    sm_config_set_sideset_pins(&c, clk_pin);
    sm_config_set_out_pins(&c, data_pin, 1);
    sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_TX);
    sm_config_set_clkdiv(&c, clk_div);
    sm_config_set_out_shift(&c, false, true, 32);
    pio_sm_init(pio, sm, offset, &c);
    pio_sm_set_enabled(pio, sm, true);
}
// Making use of the narrow store replication behaviour on RP2040 to get the
// data left-justified (as we are using shift-to-left to get MSB-first serial)
static inline void tft_put(PIO pio, uint sm, uint8_t x) {
    while (pio_sm_is_tx_fifo_full(pio, sm))
        ;
    *(volatile uint8_t*)&pio->txf[sm] = x;
}
static inline void tft_push(PIO pio, uint sm, int dma_chan, uint16_t* pixels, size_t size) {
    size_t new_size = size / 2;
    uint32_t* x = malloc(new_size * sizeof(uint32_t));
    for (size_t i = 0, j = 0; i < size; i += 2, j++) {
        uint32_t combinedValue = ((uint32_t)pixels[i] << 16) | pixels[i + 1];
        x[j] = combinedValue;
    }
    dma_channel_set_read_addr(dma_chan, x, true);
    sleep_ms(100);
    free(x);
}
// SM is done when it stalls on an empty FIFO
static inline void tft_wait_idle(PIO pio, uint sm) {
    uint32_t sm_stall_mask = 1u << (sm + PIO_FDEBUG_TXSTALL_LSB);
    pio->fdebug = sm_stall_mask;
    while (!(pio->fdebug & sm_stall_mask))
        ;
}

#endif

