diff --git a/CMakeLists.txt b/CMakeLists.txt index 832bab1..88c8b50 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -37,6 +37,8 @@ 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_uart2.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/tool78/tool78_hw_78k0_uart2_extclk.c ${CMAKE_CURRENT_SOURCE_DIR}/src/test/piotest.c ) diff --git a/src/tool78/.gitignore b/src/tool78/.gitignore new file mode 100644 index 0000000..99ed0d4 --- /dev/null +++ b/src/tool78/.gitignore @@ -0,0 +1 @@ +notes.txt diff --git a/src/tool78/tool78_defs.h b/src/tool78/tool78_defs.h index 73fb365..1d5b879 100644 --- a/src/tool78/tool78_defs.h +++ b/src/tool78/tool78_defs.h @@ -22,20 +22,20 @@ #define PINOUT_TOOL78_RL78_RX 19 enum tool78_target { - tool78k0_kx2_uart2 = 0x12, - tool78k0_kx2_spi = 0x13, - tool78k0_kx2_uart2_extclk = 0x14, + tool78k0_uart2 = 0x12, + tool78k0_spi = 0x13, + tool78k0_uart2_extclk = 0x14, - tool78k0r_kx3l_uart1 = 0x21, + tool78k0r_uart1 = 0x21, tool78rl_uart1 = 0x31, tool78rl_uart2 = 0x32, tool78rl_ocd = 0x38, // FIXME: do this in a better way - tool78_mcu_mask = 0xf0, - tool78_mcu_78k0_kx2 = 0x10, - tool78_mcu_78k0r_kx3l = 0x20, - tool78_mcu_rl78 = 0x30, + tool78_mcu_mask = 0xf0, + tool78_mcu_78k0 = 0x10, + tool78_mcu_78k0r = 0x20, + tool78_mcu_rl78 = 0x30, tool78_phy_mask = 0x0f, tool78_phy_uart1 = 0x01, diff --git a/src/tool78/tool78_hw_78k0_uart2.c b/src/tool78/tool78_hw_78k0_uart2.c new file mode 100644 index 0000000..c3aa3e4 --- /dev/null +++ b/src/tool78/tool78_hw_78k0_uart2.c @@ -0,0 +1,89 @@ + +#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; + +int t78k0_uart2_send(int len, const uint8_t* data, int32_t timeout_us); +void t78k0_uart2_deinit(void); +int t78k0_uart2_has_available(void); +int t78k0_uart2_recv(int len, uint8_t* data, int32_t timeout_us); +int t78k0_uart2_send(int len, const uint8_t* data, int32_t timeout_us); + + +static bool t78k0_uart2_init(void) { + if (!tool78_hw_init_help(&tool78_uart_tx_program, &tool78_uart_rx_program, + &vars)) return false; + + vars.exclusive = false; + + // extclk between 2 and 20 MHz + tool78_entryseq_78k0(tool78k0_uart2); + + tool78_uart_tx_program_init(PINOUT_TOOL78_PIO, vars.smtx, vars.txoff, + PINOUT_TOOL78_78K0_TXMOSI, 9600, true); + tool78_uart_rx_program_init(PINOUT_TOOL78_PIO, vars.smrx, vars.rxoff, + PINOUT_TOOL78_78K0_RXMISO, 9600, true); + + // magic initial not-really-commands + // wait tCOM or tR1 (unclear) (>445k/8M s + (2^16)/2M s) + // send 0x00 + // wait t12 (>15k/8M s) + // send 0x00 + // wait t2C (>15k/8M s) + + busy_wait_us_32(477768); // tCOM or tR1 + + uint8_t byte = 0x00; + t78k0_uart2_send(1, &byte, -1); + + busy_wait_us_32(1900); // t12 + + t78k0_uart2_send(1, &byte, -1); + + busy_wait_us_32(1900); // t2C + + // 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! +} +void t78k0_uart2_deinit(void) { + tool78_hw_deinit_help(&tool78_uart_tx_program, &tool78_uart_rx_program, + &vars); + + tool78_deinit_78k0(); +} + +int t78k0_uart2_has_available(void) { + return tool78_hw_has_available_help(&vars); +} + +int t78k0_uart2_recv(int len, uint8_t* data, int32_t timeout_us) { + return tool78_hw_help_recv(&vars, len, data, timeout_us); +} +int t78k0_uart2_send(int len, const uint8_t* data, int32_t timeout_us) { + return tool78_hw_help_send(&vars, 12/*inter-byte delay (us) tDR = 90/8M s */, + len, data, timeout_us); +} + +struct tool78_hw tool78_hw_78k0_uart2 = { + .target = tool78k0_uart2, + + .init = t78k0_uart2_init, + .deinit = t78k0_uart2_deinit, + + .has_available = t78k0_uart2_has_available, + + .recv = t78k0_uart2_recv, + .send = t78k0_uart2_send +}; + diff --git a/src/tool78/tool78_hw_78k0_uart2_extclk.c b/src/tool78/tool78_hw_78k0_uart2_extclk.c new file mode 100644 index 0000000..7005343 --- /dev/null +++ b/src/tool78/tool78_hw_78k0_uart2_extclk.c @@ -0,0 +1,81 @@ + +#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; + +int t78k0_uart2_send(int len, const uint8_t* data, int32_t timeout_us); +void t78k0_uart2_deinit(void); +int t78k0_uart2_has_available(void); +int t78k0_uart2_recv(int len, uint8_t* data, int32_t timeout_us); +int t78k0_uart2_send(int len, const uint8_t* data, int32_t timeout_us); + +static bool t78k0_uart2_extclk_init(void) { + if (!tool78_hw_init_help(&tool78_uart_tx_program, &tool78_uart_rx_program, + &vars)) return false; + + vars.exclusive = false; + + // extclk between 2 and 20 MHz, let's do 8 MHz + pwm_config pc = pwm_get_default_config(); + pwm_config_set_clkdiv(&pc, (float)clock_get_hz(clk_sys) / 8e6); + pwm_init(pwm_gpio_to_slice_num(PINOUT_TOOL78_78K0_CLOCK), &pc, true); + gpio_set_function(PINOUT_TOOL78_78K0_CLOCK, GPIO_FUNC_PWM); + + tool78_entryseq_78k0(tool78k0_uart2_extclk); + + tool78_uart_tx_program_init(PINOUT_TOOL78_PIO, vars.smtx, vars.txoff, + PINOUT_TOOL78_78K0_TXMOSI, 9600, true); + tool78_uart_rx_program_init(PINOUT_TOOL78_PIO, vars.smrx, vars.rxoff, + PINOUT_TOOL78_78K0_RXMISO, 9600, true); + + // magic initial not-really-commands + // wait tCOM or tR1 (unclear) (>445k/8M s + (2^16)/2M s) + // send 0x00 + // wait t12 (>15k/8M s) + // send 0x00 + // wait t2C (>15k/8M s) + + busy_wait_us_32(477768); // tCOM or tR1 + + uint8_t byte = 0x00; + t78k0_uart2_send(1, &byte, -1); + + busy_wait_us_32(1900); // t12 + + t78k0_uart2_send(1, &byte, -1); + + busy_wait_us_32(1900); // t2C + + // 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_uart2_extclk_deinit(void) { + t78k0_uart2_deinit(); // sets extclk to no func + + pwm_set_enabled(pwm_gpio_to_slice_num(PINOUT_TOOL78_78K0_CLOCK), false); +} + +struct tool78_hw tool78_hw_78k0_uart2_extclk = { + .target = tool78k0_uart2_extclk, + + .init = t78k0_uart2_extclk_init, + .deinit = t78k0_uart2_extclk_deinit, + + .has_available = t78k0_uart2_has_available, + + .recv = t78k0_uart2_recv, + .send = t78k0_uart2_send +}; + diff --git a/src/tool78/tool78_hw_helpers.c b/src/tool78/tool78_hw_helpers.c index 9933b95..ab972d6 100644 --- a/src/tool78/tool78_hw_helpers.c +++ b/src/tool78/tool78_hw_helpers.c @@ -145,6 +145,7 @@ int tool78_hw_help_send(const struct tool78_pio_vars* vars, uint32_t sleep_us_be *(volatile uint8_t*)&PINOUT_TOOL78_PIO->txf[vars->smtx] = bitswap(data[i]); + // FIXME: THIS IS NOT HOW TO WAIT BETWEEN TWO BYTES YOU DOOFUS if (sleep_us_between_bytes) busy_wait_us_32(sleep_us_between_bytes); } @@ -153,7 +154,7 @@ end: // wait until everything is sent before reenabling the RX SM again while (!pio_sm_is_tx_fifo_empty(PINOUT_TOOL78_PIO, vars->smtx)) ; // wait until FIFO is clear - while (!(PINOUT_TOOL78_PIO->fdebug & ((1u << vars.smtx) << PIO_FDEBUG_TXSTALL_LSB))) + while (!(PINOUT_TOOL78_PIO->fdebug & ((1u << vars->smtx) << PIO_FDEBUG_TXSTALL_LSB))) ; // now wait for the SM to hang on the next 'pull' pio_sm_set_enabled(PINOUT_TOOL78_PIO, vars->smrx, true); @@ -162,3 +163,70 @@ end: return i; } + +// ------ + + +void tool78_entryseq_78k0(enum tool78_entry typ) { + // set TX, RX (and MISO MOSI nSCK) pullup, not driven + // set nRESET, FLMD0 low ;; set pindir to out ;; set GPIO func to SIO + // wait some time (tDP: >1ms and tRST for reset low >2ms) + // FLMD0 high + // wait some time (tPR: >2ms) + // nRESET high + // wait some time (tRP: 60k/8M s) + // FLMD0 pulses (period/2 = 10us) + // wait some time (end happens 239k/8M s after nRESET high) + // NOTE: datasheet tells to start doing pulses in the middle of the 60k..239k interval + + gpio_pull_up(PINOUT_TOOL78_78K0_TXMOSI); + gpio_pull_up(PINOUT_TOOL78_78K0_RXMISO); + gpio_pull_up(PINOUT_TOOL78_78K0_CLOCK ); + gpio_set_function(PINOUT_TOOL78_78K0_TXMOSI, GPIO_FUNC_NULL); + gpio_set_function(PINOUT_TOOL78_78K0_RXMISO, GPIO_FUNC_NULL); + gpio_set_function(PINOUT_TOOL78_78K0_CLOCK , GPIO_FUNC_NULL); + + gpio_put_masked((1u<