From 42e447f3a85e9bbdfcb0e70e7dad631c25abd9c0 Mon Sep 17 00:00:00 2001 From: sys64738 Date: Thu, 4 Nov 2021 22:40:36 +0100 Subject: [PATCH] 78k0 spi mode --- CMakeLists.txt | 1 + src/tool78/tool78_hw_78k0_spi.c | 107 ++++++++++++++++++++++++++++++++ 2 files changed, 108 insertions(+) create mode 100644 src/tool78/tool78_hw_78k0_spi.c diff --git a/CMakeLists.txt b/CMakeLists.txt index f56b800..2e32e60 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -37,6 +37,7 @@ if(FAMILY STREQUAL "rp2040") ${CMAKE_CURRENT_SOURCE_DIR}/src/swim/swim_hw.c ${CMAKE_CURRENT_SOURCE_DIR}/src/tool78/tool78_hw_helpers.c ${CMAKE_CURRENT_SOURCE_DIR}/src/tool78/tool78_hw_test_uart2.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/tool78/tool78_hw_78k0_spi.c ${CMAKE_CURRENT_SOURCE_DIR}/src/tool78/tool78_hw_78k0_uart2.c ${CMAKE_CURRENT_SOURCE_DIR}/src/tool78/tool78_hw_78k0_uart2_extclk.c ${CMAKE_CURRENT_SOURCE_DIR}/src/tool78/tool78_hw_78k0r_uart1.c diff --git a/src/tool78/tool78_hw_78k0_spi.c b/src/tool78/tool78_hw_78k0_spi.c new file mode 100644 index 0000000..c81894e --- /dev/null +++ b/src/tool78/tool78_hw_78k0_spi.c @@ -0,0 +1,107 @@ + +#include +#include +#include +#include + +#include "tool78_defs.h" +#include "tool78_hw_helpers.h" + +#include "tool78.pio.h" + +#include "tool78_hw.h" + +static struct tool78_pio_vars vars; + +static int t78k0_spi_xfer(int len, const uint8_t* out, uint8_t* in, + int32_t timeout_us) { + if (!out && !in) return 0; + + const uint32_t tdr = 12;/*inter-byte delay (us) tDR = 90/8M s */ + + bool blockinf = timeout_us < 0; + absolute_time_t at = make_timeout_time_us(timeout_us); + timeout_state_t ts = {0}; + check_timeout_fn ct = NULL; + if (!blockinf) ct = init_single_timeout_until(&ts, at); + + int i = 0; + for (; i < len; ++i) { + while (pio_sm_is_tx_fifo_full(PINOUT_TOOL78_PIO, vars.smrx)) { + if (!blockinf && ct(&ts)) goto end; // whoops, timeout + } + + *(volatile uint8_t*)&PINOUT_TOOL78_PIO->txf[vars.smrx] = + out ? out[i] : 0xff; + + while (pio_sm_is_rx_fifo_empty(PINOUT_TOOL78_PIO, vars.smrx)) { + if (!blockinf && ct(&ts)) goto end; // whoops, timeout + } + + uint8_t v = *(volatile uint8_t*)&PINOUT_TOOL78_PIO->rxf[vars.smrx]; + if (in) in[i] = v; + + // FIXME: THIS IS NOT HOW TO WAIT BETWEEN TWO BYTES YOU DOOFUS + // (ok maybe it might work because of bad reasons, so let's fix this + // once it causes problems) + if (tdr) busy_wait_us_32(tdr); + } + +end: + return i; +} + +static bool t78k0_spi_init(void) { + if (!tool78_hw_init_help(NULL, &tool78_spi_program, &vars)) return false; + + vars.exclusive = false; + vars.bitswap = false; + + // extclk between 2 and 20 MHz + tool78_entryseq_78k0(tool78k0_spi); + + tool78_spi_program_init(PINOUT_TOOL78_PIO, vars.smrx, vars.rxoff, + PINOUT_TOOL78_78K0_CLOCK, PINOUT_TOOL78_78K0_TXMOSI, + PINOUT_TOOL78_78K0_RXMISO, 1*1000*1000, true); + + busy_wait_us_32(477768); // tCOM or tR1 + + // now a reset command needs to be sent, but we leave that to the upper + // (command processing) layer as it has to know about those timings anyway + + return true; // all is well! +} +static void t78k0_spi_deinit(void) { + tool78_hw_deinit_help(&tool78_spi_program, NULL, &vars); + + tool78_deinit_78k0(); +} + +static int t78k0_spi_has_available(void) { + int r = 1; + + if (tool78_hw_help_check_overrun(&vars)) r = -r; + + return r; +} + + +static int t78k0_spi_recv(int len, uint8_t* data, int32_t timeout_us) { + return t78k0_spi_xfer(len, NULL, data, timeout_us); +} +static int t78k0_spi_send(int len, const uint8_t* data, int32_t timeout_us) { + return t78k0_spi_xfer(len, data, NULL, timeout_us); +} + +struct tool78_hw tool78_hw_78k0_spi = { + .target = tool78k0_spi, + + .init = t78k0_spi_init, + .deinit = t78k0_spi_deinit, + + .has_available = t78k0_spi_has_available, + + .recv = t78k0_spi_recv, + .send = t78k0_spi_send +}; +