78k0 spi mode

This commit is contained in:
Triss 2021-11-04 22:40:36 +01:00
parent 0987d432f2
commit 42e447f3a8
2 changed files with 108 additions and 0 deletions

View File

@ -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

View File

@ -0,0 +1,107 @@
#include <hardware/gpio.h>
#include <hardware/pio.h>
#include <pico/time.h>
#include <pico/timeout_helper.h>
#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
};