From af61f326b51b22ccb2bf6c4d3f477d972260ee60 Mon Sep 17 00:00:00 2001 From: SkorP Date: Wed, 17 Jul 2024 18:16:13 +0400 Subject: [PATCH] FlipTDI: refactoring --- flip_tdi/helpers/ftdi.c | 2 +- flip_tdi/helpers/ftdi_bitbang.c | 538 ++++++++++++++++++----------- flip_tdi/helpers/ftdi_bitbang.h | 3 +- flip_tdi/helpers/ftdi_gpio.c | 131 +++++++ flip_tdi/helpers/ftdi_gpio.h | 126 +++++++ flip_tdi/helpers/ftdi_mpsse.c | 336 ++++++++++++++++++ flip_tdi/helpers/ftdi_mpsse.h | 6 + flip_tdi/helpers/ftdi_usb_define.h | 52 +++ 8 files changed, 989 insertions(+), 205 deletions(-) create mode 100644 flip_tdi/helpers/ftdi_gpio.c create mode 100644 flip_tdi/helpers/ftdi_gpio.h create mode 100644 flip_tdi/helpers/ftdi_mpsse.c create mode 100644 flip_tdi/helpers/ftdi_mpsse.h diff --git a/flip_tdi/helpers/ftdi.c b/flip_tdi/helpers/ftdi.c index a443bbea..2467e178 100644 --- a/flip_tdi/helpers/ftdi.c +++ b/flip_tdi/helpers/ftdi.c @@ -230,7 +230,7 @@ void ftdi_set_flow_ctrl(Ftdi* ftdi, uint16_t index) { } uint16_t flow_ctrl = index & 0xFF00; if(flow_ctrl != FtdiFlowControlDisable) { - //ToDo: implement FtdiFlowControl + //ToDo: no implement FtdiFlowControl } } diff --git a/flip_tdi/helpers/ftdi_bitbang.c b/flip_tdi/helpers/ftdi_bitbang.c index a501b447..3f676188 100644 --- a/flip_tdi/helpers/ftdi_bitbang.c +++ b/flip_tdi/helpers/ftdi_bitbang.c @@ -3,28 +3,33 @@ #include #include #include +#include "ftdi_gpio.h" #define TAG "FTDI_BITBANG" -#define gpio_b0 (gpio_ext_pa7) -#define gpio_b1 (gpio_ext_pa6) -#define gpio_b2 (gpio_ext_pa4) -#define gpio_b3 (gpio_ext_pb3) -#define gpio_b4 (gpio_ext_pb2) -#define gpio_b5 (gpio_ext_pc3) -#define gpio_b6 (gpio_ext_pc1) -#define gpio_b7 (gpio_ext_pc0) - -struct FtdiBitbang { - FuriThread* worker_thread; - Ftdi* ftdi; +// #define gpio_b0 (gpio_ext_pa7) +// #define gpio_b1 (gpio_ext_pa6) +// #define gpio_b2 (gpio_ext_pa4) +// #define gpio_b3 (gpio_ext_pb3) +// #define gpio_b4 (gpio_ext_pb2) +// #define gpio_b5 (gpio_ext_pc3) +// #define gpio_b6 (gpio_ext_pc1) +// #define gpio_b7 (gpio_ext_pc0) +typedef uint8_t (*FtdiBitbangGpioIO)(uint8_t state); +struct FtdiBitbang +{ + FuriThread *worker_thread; + Ftdi *ftdi; uint32_t speed; bool enable; uint8_t gpio_mask; bool async; + FtdiBitbangGpioIO gpio_io[8]; + uint8_t gpio_data; }; -typedef enum { +typedef enum +{ WorkerEventReserved = (1 << 0), // Reserved for StreamBuffer internal event WorkerEventStop = (1 << 1), WorkerEventTimerUpdate = (1 << 2), @@ -32,208 +37,320 @@ typedef enum { #define WORKER_EVENTS_MASK (WorkerEventStop | WorkerEventTimerUpdate) -static void ftdi_bitbang_gpio_init(FtdiBitbang* ftdi_bitbang); -static void ftdi_bitbang_gpio_deinit(FtdiBitbang* ftdi_bitbang); -static void ftdi_bitbang_gpio_set(FtdiBitbang* ftdi_bitbang, uint8_t gpio_data); -static void ftdi_bitbang_tim_init(FtdiBitbang* ftdi_bitbang); -static void ftdi_bitbang_tim_deinit(FtdiBitbang* ftdi_bitbang); - -static int32_t ftdi_bitbang_worker(void* context) { - furi_assert(context); - FtdiBitbang* ftdi_bitbang = context; - - uint8_t buffer[64]; - - FURI_LOG_I(TAG, "Worker started"); - ftdi_bitbang_tim_init(ftdi_bitbang); - while(1) { - uint32_t events = - furi_thread_flags_wait(WORKER_EVENTS_MASK, FuriFlagWaitAny, FuriWaitForever); - furi_check((events & FuriFlagError) == 0); - - if(events & WorkerEventStop) break; - if(events & WorkerEventTimerUpdate) { - size_t length = ftdi_get_rx_buf(ftdi_bitbang->ftdi, buffer, 1); - if(length > 0) { - ftdi_bitbang_gpio_set(ftdi_bitbang, buffer[0]); - if(!ftdi_bitbang->async) { - buffer[0] = ftdi_bitbang_gpio_get(ftdi_bitbang); - ftdi_set_tx_buf(ftdi_bitbang->ftdi, buffer, 1); - } - } - if(ftdi_bitbang->enable && ftdi_bitbang->async) { - buffer[0] = ftdi_bitbang_gpio_get(ftdi_bitbang); - ftdi_set_tx_buf(ftdi_bitbang->ftdi, buffer, 1); - } - } +// static void ftdi_bitbang_gpio_init(FtdiBitbang* ftdi_bitbang); +// static void ftdi_bitbang_gpio_deinit(FtdiBitbang* ftdi_bitbang); +// static void ftdi_bitbang_gpio_set(FtdiBitbang* ftdi_bitbang, uint8_t gpio_data); +static void ftdi_bitbang_tim_init(FtdiBitbang *ftdi_bitbang); +static void ftdi_bitbang_tim_deinit(FtdiBitbang *ftdi_bitbang); + +void ftdi_bitbang_gpio_set_direction(FtdiBitbang *ftdi_bitbang) +{ + ftdi_gpio_set_direction(ftdi_bitbang->gpio_mask); + if (ftdi_bitbang->gpio_mask & 0b00000001) + { + ftdi_bitbang->gpio_io[0] = ftdi_gpio_set_b0; + } + else + { + ftdi_bitbang->gpio_io[0] = ftdi_gpio_get_b0; } - ftdi_bitbang_tim_deinit(ftdi_bitbang); - ftdi_bitbang_gpio_deinit(ftdi_bitbang); - FURI_LOG_I(TAG, "Worker stopped"); - return 0; -} - -#pragma GCC push_options -#pragma GCC optimize("Ofast,unroll-loops") -// #pragma GCC optimize("O3") -// #pragma GCC optimize("-funroll-all-loops") -static void ftdi_bitbang_gpio_init(FtdiBitbang* ftdi_bitbang) { - if(ftdi_bitbang->gpio_mask & 0b00000001) { - furi_hal_gpio_init(&gpio_b0, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh); - } else { - furi_hal_gpio_init(&gpio_b0, GpioModeInput, GpioPullNo, GpioSpeedVeryHigh); + if (ftdi_bitbang->gpio_mask & 0b00000010) + { + ftdi_bitbang->gpio_io[1] = ftdi_gpio_set_b1; } - if(ftdi_bitbang->gpio_mask & 0b00000010) { - furi_hal_gpio_init(&gpio_b1, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh); - } else { - furi_hal_gpio_init(&gpio_b1, GpioModeInput, GpioPullNo, GpioSpeedVeryHigh); + else + { + ftdi_bitbang->gpio_io[1] = ftdi_gpio_get_b1; } - if(ftdi_bitbang->gpio_mask & 0b00000100) { - furi_hal_gpio_init(&gpio_b2, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh); - } else { - furi_hal_gpio_init(&gpio_b2, GpioModeInput, GpioPullNo, GpioSpeedVeryHigh); + + if (ftdi_bitbang->gpio_mask & 0b00000100) + { + ftdi_bitbang->gpio_io[2] = ftdi_gpio_set_b2; } - if(ftdi_bitbang->gpio_mask & 0b00001000) { - furi_hal_gpio_init(&gpio_b3, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh); - } else { - furi_hal_gpio_init(&gpio_b3, GpioModeInput, GpioPullNo, GpioSpeedVeryHigh); + else + { + ftdi_bitbang->gpio_io[2] = ftdi_gpio_get_b2; } - if(ftdi_bitbang->gpio_mask & 0b00010000) { - furi_hal_gpio_init(&gpio_b4, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh); - } else { - furi_hal_gpio_init(&gpio_b4, GpioModeInput, GpioPullNo, GpioSpeedVeryHigh); + + if (ftdi_bitbang->gpio_mask & 0b00001000) + { + ftdi_bitbang->gpio_io[3] = ftdi_gpio_set_b3; } - if(ftdi_bitbang->gpio_mask & 0b00100000) { - furi_hal_gpio_init(&gpio_b5, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh); - } else { - furi_hal_gpio_init(&gpio_b5, GpioModeInput, GpioPullNo, GpioSpeedVeryHigh); + else + { + ftdi_bitbang->gpio_io[3] = ftdi_gpio_get_b3; } - if(ftdi_bitbang->gpio_mask & 0b01000000) { - furi_hal_gpio_init(&gpio_b6, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh); - } else { - furi_hal_gpio_init(&gpio_b6, GpioModeInput, GpioPullNo, GpioSpeedVeryHigh); + + if (ftdi_bitbang->gpio_mask & 0b00010000) + { + ftdi_bitbang->gpio_io[4] = ftdi_gpio_set_b4; } - if(ftdi_bitbang->gpio_mask & 0b10000000) { - furi_hal_gpio_init(&gpio_b7, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh); - } else { - furi_hal_gpio_init(&gpio_b7, GpioModeInput, GpioPullNo, GpioSpeedVeryHigh); + else + { + ftdi_bitbang->gpio_io[4] = ftdi_gpio_get_b4; } -} - -static void ftdi_bitbang_gpio_deinit(FtdiBitbang* ftdi_bitbang) { - UNUSED(ftdi_bitbang); - furi_hal_gpio_init(&gpio_b0, GpioModeAnalog, GpioPullNo, GpioSpeedLow); - furi_hal_gpio_init(&gpio_b1, GpioModeAnalog, GpioPullNo, GpioSpeedLow); - furi_hal_gpio_init(&gpio_b2, GpioModeAnalog, GpioPullNo, GpioSpeedLow); - furi_hal_gpio_init(&gpio_b3, GpioModeAnalog, GpioPullNo, GpioSpeedLow); - furi_hal_gpio_init(&gpio_b4, GpioModeAnalog, GpioPullNo, GpioSpeedLow); - furi_hal_gpio_init(&gpio_b5, GpioModeAnalog, GpioPullNo, GpioSpeedLow); - furi_hal_gpio_init(&gpio_b6, GpioModeAnalog, GpioPullNo, GpioSpeedLow); - furi_hal_gpio_init(&gpio_b7, GpioModeAnalog, GpioPullNo, GpioSpeedLow); -} -static void ftdi_bitbang_gpio_set(FtdiBitbang* ftdi_bitbang, uint8_t gpio_data) { - if(ftdi_bitbang->gpio_mask & 0b00000001) { - if(gpio_data & 0b00000001) { - furi_hal_gpio_write(&gpio_b0, 1); - } else { - furi_hal_gpio_write(&gpio_b0, 0); - } + if (ftdi_bitbang->gpio_mask & 0b00100000) + { + ftdi_bitbang->gpio_io[5] = ftdi_gpio_set_b5; } - - if(ftdi_bitbang->gpio_mask & 0b00000010) { - if(gpio_data & 0b00000010) { - furi_hal_gpio_write(&gpio_b1, 1); - } else { - furi_hal_gpio_write(&gpio_b1, 0); - } + else + { + ftdi_bitbang->gpio_io[5] = ftdi_gpio_get_b5; } - if(ftdi_bitbang->gpio_mask & 0b00000100) { - if(gpio_data & 0b00000100) { - furi_hal_gpio_write(&gpio_b2, 1); - } else { - furi_hal_gpio_write(&gpio_b2, 0); - } + if (ftdi_bitbang->gpio_mask & 0b01000000) + { + ftdi_bitbang->gpio_io[6] = ftdi_gpio_set_b6; } - - if(ftdi_bitbang->gpio_mask & 0b00001000) { - if(gpio_data & 0b00001000) { - furi_hal_gpio_write(&gpio_b3, 1); - } else { - furi_hal_gpio_write(&gpio_b3, 0); - } + else + { + ftdi_bitbang->gpio_io[6] = ftdi_gpio_get_b6; } - if(ftdi_bitbang->gpio_mask & 0b00010000) { - if(gpio_data & 0b00010000) { - furi_hal_gpio_write(&gpio_b4, 1); - } else { - furi_hal_gpio_write(&gpio_b4, 0); - } + if (ftdi_bitbang->gpio_mask & 0b10000000) + { + ftdi_bitbang->gpio_io[7] = ftdi_gpio_set_b7; } - - if(ftdi_bitbang->gpio_mask & 0b00100000) { - if(gpio_data & 0b00100000) { - furi_hal_gpio_write(&gpio_b5, 1); - } else { - furi_hal_gpio_write(&gpio_b5, 0); - } + else + { + ftdi_bitbang->gpio_io[7] = ftdi_gpio_get_b7; } +} - if(ftdi_bitbang->gpio_mask & 0b01000000) { - if(gpio_data & 0b01000000) { - furi_hal_gpio_write(&gpio_b6, 1); - } else { - furi_hal_gpio_write(&gpio_b6, 0); - } - } +void ftdi_bitbang_gpio_init(FtdiBitbang *ftdi_bitbang) +{ + ftdi_gpio_init(ftdi_bitbang->gpio_mask); + ftdi_bitbang_gpio_set_direction(ftdi_bitbang); +} - if(ftdi_bitbang->gpio_mask & 0b10000000) { - if(gpio_data & 0b10000000) { - furi_hal_gpio_write(&gpio_b7, 1); - } else { - furi_hal_gpio_write(&gpio_b7, 0); - } - } +uint8_t ftdi_bitbang_gpio_io(FtdiBitbang *ftdi_bitbang, uint8_t gpio_data_out) +{ + uint8_t gpio_data_in = 0; + gpio_data_in |= ftdi_bitbang->gpio_io[0](gpio_data_out & 0b00000001); + gpio_data_in |= ftdi_bitbang->gpio_io[1](gpio_data_out & 0b00000010); + gpio_data_in |= ftdi_bitbang->gpio_io[2](gpio_data_out & 0b00000100); + gpio_data_in |= ftdi_bitbang->gpio_io[3](gpio_data_out & 0b00001000); + gpio_data_in |= ftdi_bitbang->gpio_io[4](gpio_data_out & 0b00010000); + gpio_data_in |= ftdi_bitbang->gpio_io[5](gpio_data_out & 0b00100000); + gpio_data_in |= ftdi_bitbang->gpio_io[6](gpio_data_out & 0b01000000); + gpio_data_in |= ftdi_bitbang->gpio_io[7](gpio_data_out & 0b10000000); + return gpio_data_in; } -uint8_t ftdi_bitbang_gpio_get(FtdiBitbang* ftdi_bitbang) { - UNUSED(ftdi_bitbang); - uint8_t gpio_data = 0; - if(furi_hal_gpio_read(&gpio_b0)) { - gpio_data |= 0b00000001; - } - if(furi_hal_gpio_read(&gpio_b1)) { - gpio_data |= 0b00000010; - } - if(furi_hal_gpio_read(&gpio_b2)) { - gpio_data |= 0b00000100; - } - if(furi_hal_gpio_read(&gpio_b3)) { - gpio_data |= 0b00001000; - } - if(furi_hal_gpio_read(&gpio_b4)) { - gpio_data |= 0b00010000; - } - if(furi_hal_gpio_read(&gpio_b5)) { - gpio_data |= 0b00100000; - } - if(furi_hal_gpio_read(&gpio_b6)) { - gpio_data |= 0b01000000; - } - if(furi_hal_gpio_read(&gpio_b7)) { - gpio_data |= 0b10000000; - } +static int32_t ftdi_bitbang_worker(void *context) +{ + furi_assert(context); + FtdiBitbang *ftdi_bitbang = context; + + uint8_t buffer[64]; + + FURI_LOG_I(TAG, "Worker started"); + ftdi_bitbang_tim_init(ftdi_bitbang); + // uint8_t gpio_data[1] = {0}; + while (1) + { + uint32_t events = + furi_thread_flags_wait(WORKER_EVENTS_MASK, FuriFlagWaitAny, FuriWaitForever); + furi_check((events & FuriFlagError) == 0); - return gpio_data; + if (events & WorkerEventStop) + break; + if (events & WorkerEventTimerUpdate) + { + size_t length = ftdi_get_rx_buf(ftdi_bitbang->ftdi, buffer, 1); + if (length > 0) + { + // ftdi_bitbang_gpio_set(ftdi_bitbang, buffer[0]); + ftdi_bitbang->gpio_data = ftdi_bitbang_gpio_io(ftdi_bitbang, buffer[0]); + if (!ftdi_bitbang->async) + { + // buffer[0] = ftdi_bitbang_gpio_get(ftdi_bitbang); + ftdi_set_tx_buf(ftdi_bitbang->ftdi, &ftdi_bitbang->gpio_data, 1); + } + } + if (ftdi_bitbang->enable && ftdi_bitbang->async) + { + ftdi_bitbang->gpio_data = ftdi_bitbang_gpio_io(ftdi_bitbang, ftdi_bitbang->gpio_data); + ftdi_set_tx_buf(ftdi_bitbang->ftdi, &ftdi_bitbang->gpio_data, 1); + } + } + } + ftdi_bitbang_tim_deinit(ftdi_bitbang); + // ftdi_bitbang_gpio_deinit(ftdi_bitbang); + // ftdi_gpio_deinit(); + FURI_LOG_I(TAG, "Worker stopped"); + return 0; } -#pragma GCC pop_options +// #pragma GCC push_options +// #pragma GCC optimize("Ofast,unroll-loops") +// // #pragma GCC optimize("O3") +// // #pragma GCC optimize("-funroll-all-loops") + +// static void ftdi_bitbang_gpio_init(FtdiBitbang* ftdi_bitbang) { +// if(ftdi_bitbang->gpio_mask & 0b00000001) { +// furi_hal_gpio_init(&gpio_b0, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh); +// } else { +// furi_hal_gpio_init(&gpio_b0, GpioModeInput, GpioPullNo, GpioSpeedVeryHigh); +// } +// if(ftdi_bitbang->gpio_mask & 0b00000010) { +// furi_hal_gpio_init(&gpio_b1, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh); +// } else { +// furi_hal_gpio_init(&gpio_b1, GpioModeInput, GpioPullNo, GpioSpeedVeryHigh); +// } +// if(ftdi_bitbang->gpio_mask & 0b00000100) { +// furi_hal_gpio_init(&gpio_b2, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh); +// } else { +// furi_hal_gpio_init(&gpio_b2, GpioModeInput, GpioPullNo, GpioSpeedVeryHigh); +// } +// if(ftdi_bitbang->gpio_mask & 0b00001000) { +// furi_hal_gpio_init(&gpio_b3, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh); +// } else { +// furi_hal_gpio_init(&gpio_b3, GpioModeInput, GpioPullNo, GpioSpeedVeryHigh); +// } +// if(ftdi_bitbang->gpio_mask & 0b00010000) { +// furi_hal_gpio_init(&gpio_b4, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh); +// } else { +// furi_hal_gpio_init(&gpio_b4, GpioModeInput, GpioPullNo, GpioSpeedVeryHigh); +// } +// if(ftdi_bitbang->gpio_mask & 0b00100000) { +// furi_hal_gpio_init(&gpio_b5, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh); +// } else { +// furi_hal_gpio_init(&gpio_b5, GpioModeInput, GpioPullNo, GpioSpeedVeryHigh); +// } +// if(ftdi_bitbang->gpio_mask & 0b01000000) { +// furi_hal_gpio_init(&gpio_b6, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh); +// } else { +// furi_hal_gpio_init(&gpio_b6, GpioModeInput, GpioPullNo, GpioSpeedVeryHigh); +// } +// if(ftdi_bitbang->gpio_mask & 0b10000000) { +// furi_hal_gpio_init(&gpio_b7, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh); +// } else { +// furi_hal_gpio_init(&gpio_b7, GpioModeInput, GpioPullNo, GpioSpeedVeryHigh); +// } +// } + +// static void ftdi_bitbang_gpio_deinit(FtdiBitbang* ftdi_bitbang) { +// UNUSED(ftdi_bitbang); +// furi_hal_gpio_init(&gpio_b0, GpioModeAnalog, GpioPullNo, GpioSpeedLow); +// furi_hal_gpio_init(&gpio_b1, GpioModeAnalog, GpioPullNo, GpioSpeedLow); +// furi_hal_gpio_init(&gpio_b2, GpioModeAnalog, GpioPullNo, GpioSpeedLow); +// furi_hal_gpio_init(&gpio_b3, GpioModeAnalog, GpioPullNo, GpioSpeedLow); +// furi_hal_gpio_init(&gpio_b4, GpioModeAnalog, GpioPullNo, GpioSpeedLow); +// furi_hal_gpio_init(&gpio_b5, GpioModeAnalog, GpioPullNo, GpioSpeedLow); +// furi_hal_gpio_init(&gpio_b6, GpioModeAnalog, GpioPullNo, GpioSpeedLow); +// furi_hal_gpio_init(&gpio_b7, GpioModeAnalog, GpioPullNo, GpioSpeedLow); +// } + +// static void ftdi_bitbang_gpio_set(FtdiBitbang* ftdi_bitbang, uint8_t gpio_data) { +// if(ftdi_bitbang->gpio_mask & 0b00000001) { +// if(gpio_data & 0b00000001) { +// furi_hal_gpio_write(&gpio_b0, 1); +// } else { +// furi_hal_gpio_write(&gpio_b0, 0); +// } +// } + +// if(ftdi_bitbang->gpio_mask & 0b00000010) { +// if(gpio_data & 0b00000010) { +// furi_hal_gpio_write(&gpio_b1, 1); +// } else { +// furi_hal_gpio_write(&gpio_b1, 0); +// } +// } + +// if(ftdi_bitbang->gpio_mask & 0b00000100) { +// if(gpio_data & 0b00000100) { +// furi_hal_gpio_write(&gpio_b2, 1); +// } else { +// furi_hal_gpio_write(&gpio_b2, 0); +// } +// } + +// if(ftdi_bitbang->gpio_mask & 0b00001000) { +// if(gpio_data & 0b00001000) { +// furi_hal_gpio_write(&gpio_b3, 1); +// } else { +// furi_hal_gpio_write(&gpio_b3, 0); +// } +// } + +// if(ftdi_bitbang->gpio_mask & 0b00010000) { +// if(gpio_data & 0b00010000) { +// furi_hal_gpio_write(&gpio_b4, 1); +// } else { +// furi_hal_gpio_write(&gpio_b4, 0); +// } +// } + +// if(ftdi_bitbang->gpio_mask & 0b00100000) { +// if(gpio_data & 0b00100000) { +// furi_hal_gpio_write(&gpio_b5, 1); +// } else { +// furi_hal_gpio_write(&gpio_b5, 0); +// } +// } + +// if(ftdi_bitbang->gpio_mask & 0b01000000) { +// if(gpio_data & 0b01000000) { +// furi_hal_gpio_write(&gpio_b6, 1); +// } else { +// furi_hal_gpio_write(&gpio_b6, 0); +// } +// } + +// if(ftdi_bitbang->gpio_mask & 0b10000000) { +// if(gpio_data & 0b10000000) { +// furi_hal_gpio_write(&gpio_b7, 1); +// } else { +// furi_hal_gpio_write(&gpio_b7, 0); +// } +// } +// } + +// uint8_t ftdi_bitbang_gpio_get(FtdiBitbang* ftdi_bitbang) { +// UNUSED(ftdi_bitbang); +// uint8_t gpio_data = 0; +// if(furi_hal_gpio_read(&gpio_b0)) { +// gpio_data |= 0b00000001; +// } +// if(furi_hal_gpio_read(&gpio_b1)) { +// gpio_data |= 0b00000010; +// } +// if(furi_hal_gpio_read(&gpio_b2)) { +// gpio_data |= 0b00000100; +// } +// if(furi_hal_gpio_read(&gpio_b3)) { +// gpio_data |= 0b00001000; +// } +// if(furi_hal_gpio_read(&gpio_b4)) { +// gpio_data |= 0b00010000; +// } +// if(furi_hal_gpio_read(&gpio_b5)) { +// gpio_data |= 0b00100000; +// } +// if(furi_hal_gpio_read(&gpio_b6)) { +// gpio_data |= 0b01000000; +// } +// if(furi_hal_gpio_read(&gpio_b7)) { +// gpio_data |= 0b10000000; +// } + +// return gpio_data; +// } + +// #pragma GCC pop_options + +uint8_t ftdi_bitbang_gpio_get(FtdiBitbang *ftdi_bitbang) +{ + return ftdi_bitbang_gpio_io(ftdi_bitbang, ftdi_bitbang->gpio_data); +} -FtdiBitbang* ftdi_bitbang_alloc(Ftdi* ftdi) { - FtdiBitbang* ftdi_bitbang = malloc(sizeof(FtdiBitbang)); +FtdiBitbang *ftdi_bitbang_alloc(Ftdi *ftdi) +{ + FtdiBitbang *ftdi_bitbang = malloc(sizeof(FtdiBitbang)); ftdi_bitbang->ftdi = ftdi; ftdi_bitbang->enable = false; ftdi_bitbang->gpio_mask = 0; @@ -245,35 +362,46 @@ FtdiBitbang* ftdi_bitbang_alloc(Ftdi* ftdi) { return ftdi_bitbang; } -void ftdi_bitbang_free(FtdiBitbang* ftdi_bitbang) { - if(!ftdi_bitbang) return; +void ftdi_bitbang_free(FtdiBitbang *ftdi_bitbang) +{ + if (!ftdi_bitbang) + return; + ftdi_bitbang->enable = false; furi_thread_flags_set(ftdi_bitbang->worker_thread, WorkerEventStop); furi_thread_join(ftdi_bitbang->worker_thread); furi_thread_free(ftdi_bitbang->worker_thread); + ftdi_gpio_deinit(); + free(ftdi_bitbang); ftdi_bitbang = NULL; } -void ftdi_bitbang_set_gpio(FtdiBitbang* ftdi_bitbang, uint8_t gpio_mask) { +void ftdi_bitbang_set_gpio(FtdiBitbang *ftdi_bitbang, uint8_t gpio_mask) +{ ftdi_bitbang->gpio_mask = gpio_mask; - ftdi_bitbang_gpio_init(ftdi_bitbang); + ftdi_bitbang_gpio_set_direction(ftdi_bitbang); } -void ftdi_bitbang_enable(FtdiBitbang* ftdi_bitbang, bool enable, bool async) { +void ftdi_bitbang_enable(FtdiBitbang *ftdi_bitbang, bool enable, bool async) +{ ftdi_bitbang->enable = enable; ftdi_bitbang->async = async; - if(enable) { + if (enable) + { LL_TIM_SetCounter(TIM17, 0); LL_TIM_EnableCounter(TIM17); - } else { + } + else + { LL_TIM_DisableCounter(TIM17); } } -void ftdi_bitbang_set_speed(FtdiBitbang* ftdi_bitbang, uint32_t speed) { +void ftdi_bitbang_set_speed(FtdiBitbang *ftdi_bitbang, uint32_t speed) +{ UNUSED(ftdi_bitbang); UNUSED(speed); @@ -284,23 +412,26 @@ void ftdi_bitbang_set_speed(FtdiBitbang* ftdi_bitbang, uint32_t speed) { LL_TIM_SetAutoReload(TIM17, period - 1); } -static void ftdi_bitbang_tim_isr(void* context) { - FtdiBitbang* ftdi_bitbang = context; +static void ftdi_bitbang_tim_isr(void *context) +{ + FtdiBitbang *ftdi_bitbang = context; UNUSED(ftdi_bitbang); - if(LL_TIM_IsActiveFlag_UPDATE(TIM17)) { + if (LL_TIM_IsActiveFlag_UPDATE(TIM17)) + { LL_TIM_ClearFlag_UPDATE(TIM17); furi_thread_flags_set( furi_thread_get_id(ftdi_bitbang->worker_thread), WorkerEventTimerUpdate); } } -static void ftdi_bitbang_tim_init(FtdiBitbang* ftdi_bitbang) { +static void ftdi_bitbang_tim_init(FtdiBitbang *ftdi_bitbang) +{ furi_hal_bus_enable(FuriHalBusTIM17); LL_TIM_SetCounterMode(TIM17, LL_TIM_COUNTERMODE_UP); LL_TIM_SetClockDivision(TIM17, LL_TIM_CLOCKDIVISION_DIV1); - LL_TIM_SetAutoReload(TIM17, 6400-1); - LL_TIM_SetPrescaler(TIM17, 0); //10kHz + LL_TIM_SetAutoReload(TIM17, 6400 - 1); + LL_TIM_SetPrescaler(TIM17, 0); // 10kHz LL_TIM_SetClockSource(TIM17, LL_TIM_CLOCKSOURCE_INTERNAL); LL_TIM_DisableARRPreload(TIM17); @@ -310,7 +441,8 @@ static void ftdi_bitbang_tim_init(FtdiBitbang* ftdi_bitbang) { LL_TIM_EnableIT_UPDATE(TIM17); } -static void ftdi_bitbang_tim_deinit(FtdiBitbang* ftdi_bitbang) { +static void ftdi_bitbang_tim_deinit(FtdiBitbang *ftdi_bitbang) +{ UNUSED(ftdi_bitbang); LL_TIM_DisableCounter(TIM17); furi_hal_bus_disable(FuriHalBusTIM17); diff --git a/flip_tdi/helpers/ftdi_bitbang.h b/flip_tdi/helpers/ftdi_bitbang.h index a9e364e7..067e81d1 100644 --- a/flip_tdi/helpers/ftdi_bitbang.h +++ b/flip_tdi/helpers/ftdi_bitbang.h @@ -9,4 +9,5 @@ void ftdi_bitbang_free(FtdiBitbang* ftdi_bitbang); void ftdi_bitbang_set_gpio(FtdiBitbang* ftdi_bitbang, uint8_t gpio_mask); void ftdi_bitbang_enable(FtdiBitbang* ftdi_bitbang, bool enable, bool async); void ftdi_bitbang_set_speed(FtdiBitbang* ftdi_bitbang, uint32_t speed); -uint8_t ftdi_bitbang_gpio_get(FtdiBitbang* ftdi_bitbang); \ No newline at end of file +uint8_t ftdi_bitbang_gpio_get(FtdiBitbang* ftdi_bitbang); +uint8_t ftdi_bitbang_gpio_io(FtdiBitbang* ftdi_bitbang, uint8_t gpio_data); \ No newline at end of file diff --git a/flip_tdi/helpers/ftdi_gpio.c b/flip_tdi/helpers/ftdi_gpio.c new file mode 100644 index 00000000..7712a4ed --- /dev/null +++ b/flip_tdi/helpers/ftdi_gpio.c @@ -0,0 +1,131 @@ +#include "ftdi_latency_timer.h" +#include "furi.h" +#include + +#include + +#define TAG "FTDI_GPIO" + +#define gpio_b0 (gpio_ext_pa7) +#define gpio_b1 (gpio_ext_pa6) +#define gpio_b2 (gpio_ext_pa4) +#define gpio_b3 (gpio_ext_pb3) +#define gpio_b4 (gpio_ext_pb2) +#define gpio_b5 (gpio_ext_pc3) +#define gpio_b6 (gpio_ext_pc1) +#define gpio_b7 (gpio_ext_pc0) + +void ftdi_gpio_set_direction(uint8_t gpio_mask) { + // gpio_ext_pa7 + if(gpio_mask & 0b00000001) { + LL_GPIO_SetPinMode(GPIOA, LL_GPIO_PIN_7, LL_GPIO_MODE_OUTPUT); + } else { + LL_GPIO_SetPinMode(GPIOA, LL_GPIO_PIN_7, LL_GPIO_MODE_INPUT); + } + // gpio_ext_pa6 + if(gpio_mask & 0b00000010) { + LL_GPIO_SetPinMode(GPIOA, LL_GPIO_PIN_6, LL_GPIO_MODE_OUTPUT); + } else { + LL_GPIO_SetPinMode(GPIOA, LL_GPIO_PIN_6, LL_GPIO_MODE_INPUT); + } + // gpio_ext_pa4 + if(gpio_mask & 0b00000100) { + LL_GPIO_SetPinMode(GPIOA, LL_GPIO_PIN_4, LL_GPIO_MODE_OUTPUT); + } else { + LL_GPIO_SetPinMode(GPIOA, LL_GPIO_PIN_4, LL_GPIO_MODE_INPUT); + } + // gpio_ext_pb3 + if(gpio_mask & 0b00001000) { + LL_GPIO_SetPinMode(GPIOB, LL_GPIO_PIN_3, LL_GPIO_MODE_OUTPUT); + } else { + LL_GPIO_SetPinMode(GPIOB, LL_GPIO_PIN_3, LL_GPIO_MODE_INPUT); + } + // gpio_ext_pb2 + if(gpio_mask & 0b00010000) { + LL_GPIO_SetPinMode(GPIOB, LL_GPIO_PIN_2, LL_GPIO_MODE_OUTPUT); + } else { + LL_GPIO_SetPinMode(GPIOB, LL_GPIO_PIN_2, LL_GPIO_MODE_INPUT); + } + // gpio_ext_pc3 + if(gpio_mask & 0b00100000) { + LL_GPIO_SetPinMode(GPIOC, LL_GPIO_PIN_3, LL_GPIO_MODE_OUTPUT); + } else { + LL_GPIO_SetPinMode(GPIOC, LL_GPIO_PIN_3, LL_GPIO_MODE_INPUT); + } + // gpio_ext_pc1 + if(gpio_mask & 0b01000000) { + LL_GPIO_SetPinMode(GPIOC, LL_GPIO_PIN_1, LL_GPIO_MODE_OUTPUT); + } else { + LL_GPIO_SetPinMode(GPIOC, LL_GPIO_PIN_1, LL_GPIO_MODE_INPUT); + } + // gpio_ext_pc0 + if(gpio_mask & 0b10000000) { + LL_GPIO_SetPinMode(GPIOC, LL_GPIO_PIN_0, LL_GPIO_MODE_OUTPUT); + } else { + LL_GPIO_SetPinMode(GPIOC, LL_GPIO_PIN_0, LL_GPIO_MODE_INPUT); + } +} + +void ftdi_gpio_init(uint8_t gpio_mask) { + // // gpio_ext_pa7 + // LL_GPIO_SetPinSpeed(GPIOA, LL_GPIO_PIN_7, LL_GPIO_SPEED_FREQ_VERY_HIGH); + // LL_GPIO_SetPinOutputType(GPIOA, LL_GPIO_PIN_7, LL_GPIO_OUTPUT_PUSHPULL); + // LL_GPIO_SetPinPull(GPIOA, LL_GPIO_PIN_7, LL_GPIO_PULL_NO); + + // // gpio_ext_pa6 + // LL_GPIO_SetPinSpeed(GPIOA, LL_GPIO_PIN_6, LL_GPIO_SPEED_FREQ_VERY_HIGH); + // LL_GPIO_SetPinOutputType(GPIOA, LL_GPIO_PIN_6, LL_GPIO_OUTPUT_PUSHPULL); + // LL_GPIO_SetPinPull(GPIOA, LL_GPIO_PIN_6, LL_GPIO_PULL_NO); + + // // gpio_ext_pa4 + // LL_GPIO_SetPinSpeed(GPIOA, LL_GPIO_PIN_4, LL_GPIO_SPEED_FREQ_VERY_HIGH); + // LL_GPIO_SetPinOutputType(GPIOA, LL_GPIO_PIN_4, LL_GPIO_OUTPUT_PUSHPULL); + // LL_GPIO_SetPinPull(GPIOA, LL_GPIO_PIN_4, LL_GPIO_PULL_NO); + + // // gpio_ext_pb3 + // LL_GPIO_SetPinSpeed(GPIOB, LL_GPIO_PIN_3, LL_GPIO_SPEED_FREQ_VERY_HIGH); + // LL_GPIO_SetPinOutputType(GPIOB, LL_GPIO_PIN_3, LL_GPIO_OUTPUT_PUSHPULL); + // LL_GPIO_SetPinPull(GPIOB, LL_GPIO_PIN_3, LL_GPIO_PULL_NO); + + // // gpio_ext_pb2 + // LL_GPIO_SetPinSpeed(GPIOB, LL_GPIO_PIN_2, LL_GPIO_SPEED_FREQ_VERY_HIGH); + // LL_GPIO_SetPinOutputType(GPIOB, LL_GPIO_PIN_2, LL_GPIO_OUTPUT_PUSHPULL); + // LL_GPIO_SetPinPull(GPIOB, LL_GPIO_PIN_2, LL_GPIO_PULL_NO); + + // // gpio_ext_pc3 + // LL_GPIO_SetPinSpeed(GPIOC, LL_GPIO_PIN_3, LL_GPIO_SPEED_FREQ_VERY_HIGH); + // LL_GPIO_SetPinOutputType(GPIOC, LL_GPIO_PIN_3, LL_GPIO_OUTPUT_PUSHPULL); + // LL_GPIO_SetPinPull(GPIOC, LL_GPIO_PIN_3, LL_GPIO_PULL_NO); + + // // gpio_ext_pc1 + // LL_GPIO_SetPinSpeed(GPIOC, LL_GPIO_PIN_1, LL_GPIO_SPEED_FREQ_VERY_HIGH); + // LL_GPIO_SetPinOutputType(GPIOC, LL_GPIO_PIN_1, LL_GPIO_OUTPUT_PUSHPULL); + // LL_GPIO_SetPinPull(GPIOC, LL_GPIO_PIN_1, LL_GPIO_PULL_NO); + + // // gpio_ext_pc0 + // LL_GPIO_SetPinSpeed(GPIOC, LL_GPIO_PIN_0, LL_GPIO_SPEED_FREQ_VERY_HIGH); + // LL_GPIO_SetPinOutputType(GPIOC, LL_GPIO_PIN_0, LL_GPIO_OUTPUT_PUSHPULL); + // LL_GPIO_SetPinPull(GPIOC, LL_GPIO_PIN_0, LL_GPIO_PULL_NO); + furi_hal_gpio_init(&gpio_b0, GpioModeInput, GpioPullNo, GpioSpeedVeryHigh); + furi_hal_gpio_init(&gpio_b1, GpioModeInput, GpioPullNo, GpioSpeedVeryHigh); + furi_hal_gpio_init(&gpio_b2, GpioModeInput, GpioPullNo, GpioSpeedVeryHigh); + furi_hal_gpio_init(&gpio_b3, GpioModeInput, GpioPullNo, GpioSpeedVeryHigh); + //furi_hal_gpio_init(&gpio_b4, GpioModeInput, GpioPullNo, GpioSpeedVeryHigh); + furi_hal_gpio_init(&gpio_b4, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh); + furi_hal_gpio_init(&gpio_b5, GpioModeInput, GpioPullNo, GpioSpeedVeryHigh); + furi_hal_gpio_init(&gpio_b6, GpioModeInput, GpioPullNo, GpioSpeedVeryHigh); + furi_hal_gpio_init(&gpio_b7, GpioModeInput, GpioPullNo, GpioSpeedVeryHigh); + + ftdi_gpio_set_direction(gpio_mask); +} + +void ftdi_gpio_deinit() { + furi_hal_gpio_init(&gpio_b0, GpioModeAnalog, GpioPullNo, GpioSpeedLow); + furi_hal_gpio_init(&gpio_b1, GpioModeAnalog, GpioPullNo, GpioSpeedLow); + furi_hal_gpio_init(&gpio_b2, GpioModeAnalog, GpioPullNo, GpioSpeedLow); + furi_hal_gpio_init(&gpio_b3, GpioModeAnalog, GpioPullNo, GpioSpeedLow); + furi_hal_gpio_init(&gpio_b4, GpioModeAnalog, GpioPullNo, GpioSpeedLow); + furi_hal_gpio_init(&gpio_b5, GpioModeAnalog, GpioPullNo, GpioSpeedLow); + furi_hal_gpio_init(&gpio_b6, GpioModeAnalog, GpioPullNo, GpioSpeedLow); + furi_hal_gpio_init(&gpio_b7, GpioModeAnalog, GpioPullNo, GpioSpeedLow); +} diff --git a/flip_tdi/helpers/ftdi_gpio.h b/flip_tdi/helpers/ftdi_gpio.h new file mode 100644 index 00000000..1982c90b --- /dev/null +++ b/flip_tdi/helpers/ftdi_gpio.h @@ -0,0 +1,126 @@ +#pragma once +#include "ftdi.h" + +void ftdi_gpio_set_direction(uint8_t gpio_mask); +void ftdi_gpio_init(uint8_t gpio_mask); +void ftdi_gpio_deinit(); + +static inline uint8_t ftdi_gpio_get_b0(uint8_t state) { // gpio_ext_pa7 + UNUSED(state); + return (GPIOA->IDR & LL_GPIO_PIN_7) ? 0b00000001 : 0; +} + +static inline uint8_t ftdi_gpio_get_b1(uint8_t state) { // gpio_ext_pa6 + UNUSED(state); + return (GPIOA->IDR & LL_GPIO_PIN_6) ? 0b00000010 : 0; +} + +static inline uint8_t ftdi_gpio_get_b2(uint8_t state) { // gpio_ext_pa4 + UNUSED(state); + return (GPIOA->IDR & LL_GPIO_PIN_4) ? 0b00000100 : 0; +} + +static inline uint8_t ftdi_gpio_get_b3(uint8_t state) { // gpio_ext_pb3 + UNUSED(state); + return (GPIOB->IDR & LL_GPIO_PIN_3) ? 0b00001000 : 0; +} + +static inline uint8_t ftdi_gpio_get_b4(uint8_t state) { // gpio_ext_pb2 + UNUSED(state); + return (GPIOB->IDR & LL_GPIO_PIN_2) ? 0b00010000 : 0; +} + +static inline uint8_t ftdi_gpio_get_b5(uint8_t state) { // gpio_ext_pc3 + UNUSED(state); + return (GPIOC->IDR & LL_GPIO_PIN_3) ? 0b00100000 : 0; +} + +static inline uint8_t ftdi_gpio_get_b6(uint8_t state) { // gpio_ext_pc1 + UNUSED(state); + return (GPIOC->IDR & LL_GPIO_PIN_1) ? 0b01000000 : 0; +} + +static inline uint8_t ftdi_gpio_get_b7(uint8_t state) { // gpio_ext_pc0 + UNUSED(state); + return (GPIOC->IDR & LL_GPIO_PIN_0) ? 0b10000000 : 0; +} + +static inline uint8_t ftdi_gpio_set_b0(uint8_t state) { // gpio_ext_pa7 + if(state) { + GPIOA->BSRR = LL_GPIO_PIN_7; + return 0b00000001; + } else { + GPIOA->BRR = LL_GPIO_PIN_7; + return 0; + } +} + +static inline uint8_t ftdi_gpio_set_b1(uint8_t state) { // gpio_ext_pa6 + if(state) { + GPIOA->BSRR = LL_GPIO_PIN_6; + return 0b00000010; + } else { + GPIOA->BRR = LL_GPIO_PIN_6; + return 0; + } +} + +static inline uint8_t ftdi_gpio_set_b2(uint8_t state) { // gpio_ext_pa4 + if(state) { + GPIOA->BSRR = LL_GPIO_PIN_4; + return 0b00000100; + } else { + GPIOA->BRR = LL_GPIO_PIN_4; + return 0; + } +} + +static inline uint8_t ftdi_gpio_set_b3(uint8_t state) { // gpio_ext_pb3 + if(state) { + GPIOB->BSRR = LL_GPIO_PIN_3; + return 0b00001000; + } else { + GPIOB->BRR = LL_GPIO_PIN_3; + return 0; + } +} + +static inline uint8_t ftdi_gpio_set_b4(uint8_t state) { // gpio_ext_pb2 + if(state) { + GPIOB->BSRR = LL_GPIO_PIN_2; + return 0b00010000; + } else { + GPIOB->BRR = LL_GPIO_PIN_2; + return 0; + } +} + +static inline uint8_t ftdi_gpio_set_b5(uint8_t state) { // gpio_ext_pc3 + if(state) { + GPIOC->BSRR = LL_GPIO_PIN_3; + return 0b00100000; + } else { + GPIOC->BRR = LL_GPIO_PIN_3; + return 0; + } +} + +static inline uint8_t ftdi_gpio_set_b6(uint8_t state) { // gpio_ext_pc1 + if(state) { + GPIOC->BSRR = LL_GPIO_PIN_1; + return 0b01000000; + } else { + GPIOC->BRR = LL_GPIO_PIN_1; + return 0; + } +} + +static inline uint8_t ftdi_gpio_set_b7(uint8_t state) { // gpio_ext_pc0 + if(state) { + GPIOC->BSRR = LL_GPIO_PIN_0; + return 0b10000000; + } else { + GPIOC->BRR = LL_GPIO_PIN_0; + return 0; + } +} diff --git a/flip_tdi/helpers/ftdi_mpsse.c b/flip_tdi/helpers/ftdi_mpsse.c new file mode 100644 index 00000000..55eb4bbd --- /dev/null +++ b/flip_tdi/helpers/ftdi_mpsse.c @@ -0,0 +1,336 @@ +#include "ftdi_mpsse.h" +#include "furi.h" +#include + +#define TAG "FTDI_MPSSE" + +struct FtdiMpsse { + Ftdi* ftdi; + uint8_t gpio_state; + uint8_t gpio_mask; + uint16_t data_size; + bool is_loopback; + bool is_div5; + bool is_clk3phase; + bool is_adaptive; +}; + +FtdiMpsse* ftdi_mpsse_alloc(Ftdi* ftdi) { + FtdiMpsse* ftdi_mpsse = malloc(sizeof(FtdiMpsse)); + ftdi_mpsse->ftdi = ftdi; + ftdi_mpsse->gpio_state = 0; + ftdi_mpsse->gpio_mask = 0; + ftdi_mpsse->data_size = 0; + ftdi_mpsse->is_loopback = false; + ftdi_mpsse->is_div5 = false; + ftdi_mpsse->is_clk3phase = false; + ftdi_mpsse->is_adaptive = false; + return ftdi_mpsse; +} + +void ftdi_mpsse_free(FtdiMpsse* ftdi_mpsse) { + if(!ftdi_mpsse) return; + free(ftdi_mpsse); + ftdi_mpsse = NULL; +} + +uint8_t ftdi_mpsse_get_data_stream(FtdiMpsse* ftdi_mpsse) { + uint8_t data = 0; + //Todo add timeout + ftdi_get_rx_buf(ftdi_mpsse->ftdi, &data, 1); + return data; +} + +void ftdi_mpssse_set_data_stream(FtdiMpsse* ftdi_mpsse, uint8_t* data, uint16_t size) { + ftdi_set_tx_buf(ftdi_mpsse->ftdi, data, size); +} + +void ftdi_mpsse_get_data(FtdiMpsse* ftdi_mpsse) { + //todo add support for tx buffer, data_size_max = 0xFF00 + ftdi_mpsse->data_size++; + while(ftdi_mpsse->data_size--) { + ftdi_mpsse_get_data_stream(ftdi_mpsse); + } +} + +static uint16_t ftdi_mpsse_get_data_size(FtdiMpsse* ftdi_mpsse) { + return (uint16_t)ftdi_mpsse_get_data_stream(ftdi_mpsse) << 8 | + ftdi_mpsse_get_data_stream(ftdi_mpsse); +} + +static inline void ftdi_mpsse_skeep_data(FtdiMpsse* ftdi_mpsse) { + ftdi_mpsse->data_size++; + while(ftdi_mpsse->data_size--) { + ftdi_mpsse_get_data_stream(ftdi_mpsse); + } +} + +void ftdi_mpsse_state_machine(FtdiMpsse* ftdi_mpsse) { + uint8_t data = ftdi_mpsse_get_data_stream(ftdi_mpsse); + switch(data) { + case FtdiMpsseCommandsSetBitsLow: // 0x80 Change LSB GPIO output */ + ftdi_mpsse->gpio_state = ftdi_mpsse_get_data_stream(ftdi_mpsse); + ftdi_mpsse->gpio_state = ftdi_mpsse_get_data_stream(ftdi_mpsse); + //Write to GPIO + break; + case FtdiMpsseCommandsSetBitsHigh: // 0x82 Change MSB GPIO output */ + //Todo not supported + ftdi_mpsse_get_data_stream(ftdi_mpsse); + ftdi_mpsse_get_data_stream(ftdi_mpsse); + break; + case FtdiMpsseCommandsGetBitsLow: // 0x81 Get LSB GPIO output */ + //Read GPIO + //add to buffer + //read Gpio + ftdi_mpssse_set_data_stream(ftdi_mpsse, &ftdi_mpsse->gpio_state, 1); + break; + case FtdiMpsseCommandsGetBitsHigh: // 0x83 Get MSB GPIO output */ + //Todo not supported + //add to buffer FF + uint8_t gpio = 0xFF; + ftdi_mpssse_set_data_stream(ftdi_mpsse, &gpio, 1); + break; + case FtdiMpsseCommandsSendImmediate: // 0x87 Send immediate */ + //tx data to host add callback + break; + case FtdiMpsseCommandsWriteBytesPveMsb: // 0x10 Write bytes with positive edge clock, MSB first */ + //spi mode 1,3 + ftdi_mpsse->data_size = ftdi_mpsse_get_data_size(ftdi_mpsse); + //read data + ftdi_mpsse_get_data(ftdi_mpsse); + break; + case FtdiMpsseCommandsWriteBytesNveMsb: // 0x11 Write bytes with negative edge clock, MSB first */ + //spi mode 0,2 + ftdi_mpsse->data_size = ftdi_mpsse_get_data_size(ftdi_mpsse); + //read data + ftdi_mpsse_get_data(ftdi_mpsse); + break; + case FtdiMpsseCommandsWriteBitsPveMsb: // 0x12 Write bits with positive edge clock, MSB first */ + //not supported + ftdi_mpsse->data_size = ftdi_mpsse_get_data_size(ftdi_mpsse); + //read data + ftdi_mpsse_skeep_data(ftdi_mpsse); + break; + case FtdiMpsseCommandsWriteBitsNveMsb: // 0x13 Write bits with negative edge clock, MSB first */ + //not supported + ftdi_mpsse->data_size = ftdi_mpsse_get_data_size(ftdi_mpsse); + //read data + ftdi_mpsse_skeep_data(ftdi_mpsse); + break; + case FtdiMpsseCommandsWriteBytesPveLsb: // 0x18 Write bytes with positive edge clock, LSB first */ + //spi mode 1,3 + ftdi_mpsse->data_size = ftdi_mpsse_get_data_size(ftdi_mpsse); + //read data + ftdi_mpsse_get_data(ftdi_mpsse); + break; + case FtdiMpsseCommandsWriteBytesNveLsb: // 0x19 Write bytes with negative edge clock, LSB first */ + //spi mode 0,2 + ftdi_mpsse->data_size = ftdi_mpsse_get_data_size(ftdi_mpsse); + //read data + ftdi_mpsse_get_data(ftdi_mpsse); + break; + case FtdiMpsseCommandsWriteBitsPveLsb: // 0x1a Write bits with positive edge clock, LSB first */ + //not supported + ftdi_mpsse->data_size = ftdi_mpsse_get_data_size(ftdi_mpsse); + //read data + ftdi_mpsse_skeep_data(ftdi_mpsse); + break; + case FtdiMpsseCommandsWriteBitsNveLsb: // 0x1b Write bits with negative edge clock, LSB first */ + //not supported + ftdi_mpsse->data_size = ftdi_mpsse_get_data_size(ftdi_mpsse); + //read data + ftdi_mpsse_skeep_data(ftdi_mpsse); + break; + case FtdiMpsseCommandsReadBytesPveMsb: // 0x20 Read bytes with positive edge clock, MSB first */ + //spi mode 1,3 + ftdi_mpsse->data_size = ftdi_mpsse_get_data_size(ftdi_mpsse); + //write data + //ftdi_mpssse_set_data_stream(ftdi_mpsse, 0xFF, ftdi_mpsse->data_size); + break; + case FtdiMpsseCommandsReadBytesNveMsb: // 0x24 Read bytes with negative edge clock, MSB first */ + //spi mode 0,2 + ftdi_mpsse->data_size = ftdi_mpsse_get_data_size(ftdi_mpsse); + //write data + //ftdi_mpssse_set_data_stream(ftdi_mpsse, 0xFF, ftdi_mpsse->data_size); + break; + case FtdiMpsseCommandsReadBitsPveMsb: // 0x22 Read bits with positive edge clock, MSB first */ + //not supported + ftdi_mpsse->data_size = ftdi_mpsse_get_data_size(ftdi_mpsse); + //write data + //ftdi_mpssse_set_data_stream(ftdi_mpsse, 0xFF, ftdi_mpsse->data_size); + break; + case FtdiMpsseCommandsReadBitsNveMsb: // 0x26 Read bits with negative edge clock, MSB first */ + //not supported + ftdi_mpsse->data_size = ftdi_mpsse_get_data_size(ftdi_mpsse); + //write data + //ftdi_mpssse_set_data_stream(ftdi_mpsse, 0xFF, ftdi_mpsse->data_size); + break; + case FtdiMpsseCommandsReadBytesPveLsb: // 0x28 Read bytes with positive edge clock, LSB first */ + //spi mode 1,3 + ftdi_mpsse->data_size = ftdi_mpsse_get_data_size(ftdi_mpsse); + //write data + //ftdi_mpssse_set_data_stream(ftdi_mpsse, 0xFF, ftdi_mpsse->data_size); + break; + case FtdiMpsseCommandsReadBytesNveLsb: // 0x2c Read bytes with negative edge clock, LSB first */ + //spi mode 0,2 + ftdi_mpsse->data_size = ftdi_mpsse_get_data_size(ftdi_mpsse); + //write data + //ftdi_mpssse_set_data_stream(ftdi_mpsse, 0xFF, ftdi_mpsse->data_size); + break; + case FtdiMpsseCommandsReadBitsPveLsb: // 0x2a Read bits with positive edge clock, LSB first */ + //not supported + ftdi_mpsse->data_size = ftdi_mpsse_get_data_size(ftdi_mpsse); + //write data + //ftdi_mpssse_set_data_stream(ftdi_mpsse, 0xFF, ftdi_mpsse->data_size); + break; + case FtdiMpsseCommandsReadBitsNveLsb: // 0x2e Read bits with negative edge clock, LSB first */ + //not supported + ftdi_mpsse->data_size = ftdi_mpsse_get_data_size(ftdi_mpsse); + //write data + //ftdi_mpssse_set_data_stream(ftdi_mpsse, 0xFF, ftdi_mpsse->data_size); + break; + case FtdiMpsseCommandsRwBytesPveNveMsb: // 0x31 Read/Write bytes with positive edge clock, MSB first */ + //spi mode 1,3 + ftdi_mpsse->data_size = ftdi_mpsse_get_data_size(ftdi_mpsse); + //read data + //ftdi_mpsse_get_data(ftdi_mpsse); + //ftdi_mpssse_set_data_stream(ftdi_mpsse, 0xFF, ftdi_mpsse->data_size); + break; + case FtdiMpsseCommandsRwBytesNvePveMsb: // 0x34 Read/Write bytes with negative edge clock, MSB first */ + //spi mode 0,2 + ftdi_mpsse->data_size = ftdi_mpsse_get_data_size(ftdi_mpsse); + //read data + //ftdi_mpsse_get_data(ftdi_mpsse); + //ftdi_mpssse_set_data_stream(ftdi_mpsse, 0xFF, ftdi_mpsse->data_size); + break; + case FtdiMpsseCommandsRwBitsPveNveMsb: // 0x33 Read/Write bits with positive edge clock, MSB first */ + //not supported + ftdi_mpsse->data_size = ftdi_mpsse_get_data_size(ftdi_mpsse); + //read data + //ftdi_mpsse_skeep_data(ftdi_mpsse); + //ftdi_mpssse_set_data_stream(ftdi_mpsse, 0xFF, ftdi_mpsse->data_size); + break; + case FtdiMpsseCommandsRwBitsNvePveMsb: // 0x36 Read/Write bits with negative edge clock, MSB first */ + //not supported + ftdi_mpsse->data_size = ftdi_mpsse_get_data_size(ftdi_mpsse); + //read data + //ftdi_mpsse_skeep_data(ftdi_mpsse); + //ftdi_mpssse_set_data_stream(ftdi_mpsse, 0xFF, ftdi_mpsse->data_size); + break; + case FtdiMpsseCommandsRwBytesPveNveLsb: // 0x39 Read/Write bytes with positive edge clock, LSB first */ + //spi mode 1,3 + ftdi_mpsse->data_size = ftdi_mpsse_get_data_size(ftdi_mpsse); + //read data + //ftdi_mpsse_get_data(ftdi_mpsse); + //ftdi_mpssse_set_data_stream(ftdi_mpsse, 0xFF, ftdi_mpsse->data_size); + break; + case FtdiMpsseCommandsRwBytesNvePveLsb: // 0x3c Read/Write bytes with negative edge clock, LSB first */ + //spi mode 0,2 + ftdi_mpsse->data_size = ftdi_mpsse_get_data_size(ftdi_mpsse); + //read data + //ftdi_mpsse_get_data(ftdi_mpsse); + //ftdi_mpssse_set_data_stream(ftdi_mpsse, 0xFF, ftdi_mpsse->data_size); + break; + case FtdiMpsseCommandsRwBitsPveNveLsb: // 0x3b Read/Write bits with positive edge clock, LSB first */ + //not supported + ftdi_mpsse->data_size = ftdi_mpsse_get_data_size(ftdi_mpsse); + //read data + //ftdi_mpsse_skeep_data(ftdi_mpsse); + //ftdi_mpssse_set_data_stream(ftdi_mpsse, 0xFF, ftdi_mpsse->data_size); + break; + case FtdiMpsseCommandsRwBitsNvePveLsb: // 0x3e Read/Write bits with negative edge clock, LSB first */ + //not supported + ftdi_mpsse->data_size = ftdi_mpsse_get_data_size(ftdi_mpsse); + //read data + //ftdi_mpsse_skeep_data(ftdi_mpsse); + //ftdi_mpssse_set_data_stream(ftdi_mpsse, 0xFF, ftdi_mpsse->data_size); + break; + case FtdiMpsseCommandsWriteBitsTmsPve: // 0x4a Write bits with TMS, positive edge clock */ + //not supported + break; + case FtdiMpsseCommandsWriteBitsTmsNve: // 0x4b Write bits with TMS, negative edge clock */ + //not supported + break; + case FtdiMpsseCommandsRwBitsTmsPvePve: // 0x6a Read/Write bits with TMS, positive edge clock, MSB first */ + //not supported + break; + case FtdiMpsseCommandsRwBitsTmsPveNve: // 0x6b Read/Write bits with TMS, positive edge clock, MSB first */ + //not supported + break; + case FtdiMpsseCommandsRwBitsTmsNvePve: // 0x6e Read/Write bits with TMS, negative edge clock, MSB first */ + //not supported + break; + case FtdiMpsseCommandsRwBitsTmsNveNve: // 0x6f Read/Write bits with TMS, negative edge clock, MSB first */ + //not supported + break; + case FtdiMpsseCommandsLoopbackStart: // 0x84 Enable loopback */ + ftdi_mpsse->is_loopback = true; + break; + case FtdiMpsseCommandsLoopbackEnd: // 0x85 Disable loopback */ + ftdi_mpsse->is_loopback = false; + break; + case FtdiMpsseCommandsSetTckDivisor: // 0x86 Set clock */ + + break; + case FtdiMpsseCommandsDisDiv5: // 0x8a Disable divide by 5 */ + ftdi_mpsse->is_div5 = false; + break; + case FtdiMpsseCommandsEnDiv5: // 0x8b Enable divide by 5 */ + ftdi_mpsse->is_div5 = true; + break; + case FtdiMpsseCommandsEnableClk3Phase: // 0x8c Enable 3-phase data clocking (I2C) */ + ftdi_mpsse->is_clk3phase = true; + break; + case FtdiMpsseCommandsDisableClk3Phase: // 0x8d Disable 3-phase data clocking */ + ftdi_mpsse->is_clk3phase = false; + break; + case FtdiMpsseCommandsClkBitsNoData: // 0x8e Allows JTAG clock to be output w/o data */ + //not supported + break; + case FtdiMpsseCommandsClkBytesNoData: // 0x8f Allows JTAG clock to be output w/o data */ + //not supported + break; + case FtdiMpsseCommandsClkWaitOnHigh: // 0x94 Clock until GPIOL1 is high */ + //not supported + break; + case FtdiMpsseCommandsClkWaitOnLow: // 0x95 Clock until GPIOL1 is low */ + //not supported + break; + case FtdiMpsseCommandsEnableClkAdaptive: // 0x96 Enable JTAG adaptive clock for ARM */ + ftdi_mpsse->is_adaptive = true; + break; + case FtdiMpsseCommandsDisableClkAdaptive: // 0x97 Disable JTAG adaptive clock */ + ftdi_mpsse->is_adaptive = false; + break; + case FtdiMpsseCommandsClkCountWaitOnHigh: // 0x9c Clock byte cycles until GPIOL1 is high */ + //not supported + break; + case FtdiMpsseCommandsClkCountWaitOnLow: // 0x9d Clock byte cycles until GPIOL1 is low */ + //not supported + break; + case FtdiMpsseCommandsDriveZero: // 0x9e Drive-zero mode */ + //not supported + break; + case FtdiMpsseCommandsWaitOnHigh: // 0x88 Wait until GPIOL1 is high */ + //not supported + break; + case FtdiMpsseCommandsWaitOnLow: // 0x89 Wait until GPIOL1 is low */ + //not supported + break; + case FtdiMpsseCommandsReadShort: // 0x90 Read short */ + //not supported + break; + case FtdiMpsseCommandsReadExtended: // 0x91 Read extended */ + //not supported + break; + case FtdiMpsseCommandsWriteShort: // 0x92 Write short */ + //not supported + break; + case FtdiMpsseCommandsWriteExtended: // 0x93 Write extended */ + //not supported + break; + + default: + break; + } +} diff --git a/flip_tdi/helpers/ftdi_mpsse.h b/flip_tdi/helpers/ftdi_mpsse.h new file mode 100644 index 00000000..094e7024 --- /dev/null +++ b/flip_tdi/helpers/ftdi_mpsse.h @@ -0,0 +1,6 @@ +#pragma once +#include "ftdi.h" + +typedef struct FtdiMpsse FtdiMpsse; + + diff --git a/flip_tdi/helpers/ftdi_usb_define.h b/flip_tdi/helpers/ftdi_usb_define.h index 4c93d152..fe2d959f 100644 --- a/flip_tdi/helpers/ftdi_usb_define.h +++ b/flip_tdi/helpers/ftdi_usb_define.h @@ -97,6 +97,48 @@ static_assert(sizeof(FtdiBitMode) == sizeof(uint8_t), "Wrong FtdiBitMode"); /* FTDI MPSSE commands */ typedef enum { + // /* Shifting commands IN MPSSE Mode*/ + // #define MPSSE_WRITE_NEG 0x01 /* Write TDI/DO on negative TCK/SK edge*/ + // #define MPSSE_BITMODE 0x02 /* Write bits, not bytes */ + // #define MPSSE_READ_NEG 0x04 /* Sample TDO/DI on negative TCK/SK edge */ + // #define MPSSE_LSB 0x08 /* LSB first */ + // #define MPSSE_DO_WRITE 0x10 /* Write TDI/DO */ + // #define MPSSE_DO_READ 0x20 /* Read TDO/DI */ + // #define MPSSE_WRITE_TMS 0x40 /* Write TMS/CS */ + + /*MPSSE Commands*/ + FtdiMpsseCommandsWriteBytesPveMsb = 0x10, /**< Write bytes with positive edge clock, MSB first */ + FtdiMpsseCommandsWriteBytesNveMsb = 0x11, /**< Write bytes with negative edge clock, MSB first */ + FtdiMpsseCommandsWriteBitsPveMsb = 0x12, /**< Write bits with positive edge clock, MSB first */ + FtdiMpsseCommandsWriteBitsNveMsb = 0x13, /**< Write bits with negative edge clock, MSB first */ + FtdiMpsseCommandsWriteBytesPveLsb = 0x18, /**< Write bytes with positive edge clock, LSB first */ + FtdiMpsseCommandsWriteBytesNveLsb = 0x19, /**< Write bytes with negative edge clock, LSB first */ + FtdiMpsseCommandsWriteBitsPveLsb = 0x1a, /**< Write bits with positive edge clock, LSB first */ + FtdiMpsseCommandsWriteBitsNveLsb = 0x1b, /**< Write bits with negative edge clock, LSB first */ + FtdiMpsseCommandsReadBytesPveMsb = 0x20, /**< Read bytes with positive edge clock, MSB first */ + FtdiMpsseCommandsReadBytesNveMsb = 0x24, /**< Read bytes with negative edge clock, MSB first */ + FtdiMpsseCommandsReadBitsPveMsb = 0x22, /**< Read bits with positive edge clock, MSB first */ + FtdiMpsseCommandsReadBitsNveMsb = 0x26, /**< Read bits with negative edge clock, MSB first */ + FtdiMpsseCommandsReadBytesPveLsb = 0x28, /**< Read bytes with positive edge clock, LSB first */ + FtdiMpsseCommandsReadBytesNveLsb = 0x2c, /**< Read bytes with negative edge clock, LSB first */ + FtdiMpsseCommandsReadBitsPveLsb = 0x2a, /**< Read bits with positive edge clock, LSB first */ + FtdiMpsseCommandsReadBitsNveLsb = 0x2e, /**< Read bits with negative edge clock, LSB first */ + FtdiMpsseCommandsRwBytesPveNveMsb = 0x31, /**< Read/Write bytes with positive edge clock, MSB first */ + FtdiMpsseCommandsRwBytesNvePveMsb = 0x34, /**< Read/Write bytes with negative edge clock, MSB first */ + FtdiMpsseCommandsRwBitsPveNveMsb = 0x33, /**< Read/Write bits with positive edge clock, MSB first */ + FtdiMpsseCommandsRwBitsNvePveMsb = 0x36, /**< Read/Write bits with negative edge clock, MSB first */ + FtdiMpsseCommandsRwBytesPveNveLsb = 0x39, /**< Read/Write bytes with positive edge clock, LSB first */ + FtdiMpsseCommandsRwBytesNvePveLsb = 0x3c, /**< Read/Write bytes with negative edge clock, LSB first */ + FtdiMpsseCommandsRwBitsPveNveLsb = 0x3b, /**< Read/Write bits with positive edge clock, LSB first */ + FtdiMpsseCommandsRwBitsNvePveLsb = 0x3e, /**< Read/Write bits with negative edge clock, LSB first */ + FtdiMpsseCommandsWriteBitsTmsPve = 0x4a, /**< Write bits with TMS, positive edge clock */ + FtdiMpsseCommandsWriteBitsTmsNve = 0x4b, /**< Write bits with TMS, negative edge clock */ + FtdiMpsseCommandsRwBitsTmsPvePve = 0x6a, /**< Read/Write bits with TMS, positive edge clock, MSB first */ + FtdiMpsseCommandsRwBitsTmsPveNve = 0x6b, /**< Read/Write bits with TMS, positive edge clock, MSB first */ + FtdiMpsseCommandsRwBitsTmsNvePve = 0x6e, /**< Read/Write bits with TMS, negative edge clock, MSB first */ + FtdiMpsseCommandsRwBitsTmsNveNve = 0x6f, /**< Read/Write bits with TMS, negative edge clock, MSB first */ + + FtdiMpsseCommandsSetBitsLow = 0x80, /**< Change LSB GPIO output */ /*BYTE DATA*/ /*BYTE Direction*/ @@ -123,6 +165,16 @@ typedef enum { FtdiMpsseCommandsClkCountWaitOnLow = 0x9d, /**< Clock byte cycles until GPIOL1 is low */ //FT232H only FtdiMpsseCommandsDriveZero = 0x9e, /**< Drive-zero mode */ + /* Commands in MPSSE and Host Emulation Mode */ + FtdiMpsseCommandsSendImmediate = 0x87, /**< Send immediate */ + FtdiMpsseCommandsWaitOnHigh = 0x88, /**< Wait until GPIOL1 is high */ + FtdiMpsseCommandsWaitOnLow = 0x89, /**< Wait until GPIOL1 is low */ + /* Commands in Host Emulation Mode */ + FtdiMpsseCommandsReadShort = 0x90, /**< Read short */ + FtdiMpsseCommandsReadExtended = 0x91, /**< Read extended */ + FtdiMpsseCommandsWriteShort = 0x92, /**< Write short */ + FtdiMpsseCommandsWriteExtended = 0x93, /**< Write extended */ + } FtdiMpsseCommands; /* USB control requests */