#ifndef COMMON_H_6J30YQFP #define COMMON_H_6J30YQFP #include #include #include #include #include #include "ftd3xx.h" using namespace std; static bool do_exit; static atomic_int tx_count; static atomic_int rx_count; static uint8_t in_ch_cnt; static uint8_t out_ch_cnt; static void sig_hdlr(int signum) { switch (signum) { case SIGINT: do_exit = true; break; } } static void register_signals(void) { signal(SIGINT, sig_hdlr); } static void get_version(void) { DWORD dwVersion; FT_GetDriverVersion(NULL, &dwVersion); printf("Driver version:%d.%d.%d\r\n", dwVersion >> 24, (uint8_t)(dwVersion >> 16), dwVersion & 0xFFFF); FT_GetLibraryVersion(&dwVersion); printf("Library version:%d.%d.%d\r\n", dwVersion >> 24, (uint8_t)(dwVersion >> 16), dwVersion & 0xFFFF); } #if defined(_WIN32) || defined(_WIN64) #define turn_off_thread_safe() #else /* _WIN32 || _WIN64 */ static void turn_off_thread_safe(void) { FT_TRANSFER_CONF conf; memset(&conf, 0, sizeof(FT_TRANSFER_CONF)); conf.wStructSize = sizeof(FT_TRANSFER_CONF); conf.pipe[FT_PIPE_DIR_IN].fNonThreadSafeTransfer = true; conf.pipe[FT_PIPE_DIR_OUT].fNonThreadSafeTransfer = true; for (DWORD i = 0; i < 4; i++) FT_SetTransferParams(&conf, i); } #endif /* !_WIN32 && !_WIN64 */ static bool get_device_lists(int timeout_ms) { DWORD count; FT_DEVICE_LIST_INFO_NODE nodes[16]; chrono::steady_clock::time_point const timeout = chrono::steady_clock::now() + chrono::milliseconds(timeout_ms); do { if (FT_OK == FT_CreateDeviceInfoList(&count)) break; this_thread::sleep_for(chrono::microseconds(10)); } while (chrono::steady_clock::now() < timeout); printf("Total %u device(s)\r\n", count); if (!count) return false; if (FT_OK != FT_GetDeviceInfoList(nodes, &count)) return false; return true; } static void show_throughput(FT_HANDLE handle) { auto next = chrono::steady_clock::now() + chrono::seconds(1);; (void)handle; while (!do_exit) { this_thread::sleep_until(next); next += chrono::seconds(1); int tx = tx_count.exchange(0); int rx = rx_count.exchange(0); printf("TX:%.2fMiB/s RX:%.2fMiB/s, total:%.2fMiB\r\n", (float)tx/1000/1000, (float)rx/1000/1000, (float)(tx+ rx)/1000/1000); } } static void set_ft600_optional_features(USHORT *features) { USHORT flag; flag = CONFIGURATION_OPTIONAL_FEATURE_ENABLENOTIFICATIONMESSAGE_INCHALL; if (flag & *features) { *features &= ~flag; printf("Notification feature is not supported\r\n"); } flag = CONFIGURATION_OPTIONAL_FEATURE_DISABLECANCELSESSIONUNDERRUN; if (!(flag & *features)) { *features |= flag; printf("Cancel session on underrun is not supported\r\n"); } flag = CONFIGURATION_OPTIONAL_FEATURE_DISABLEUNDERRUN_INCHALL; if (!(flag & *features)) { *features |= flag; printf("Set 'disable underrun' to get better performance\r\n"); } } static void set_ft600_channels(UCHAR *channels, bool is_600_mode) { if (in_ch_cnt == 1 && out_ch_cnt == 0) { *channels = CONFIGURATION_CHANNEL_CONFIG_1_INPIPE; } else if (in_ch_cnt == 0 && out_ch_cnt == 1) *channels = CONFIGURATION_CHANNEL_CONFIG_1_OUTPIPE; else { UCHAR total = in_ch_cnt < out_ch_cnt ? out_ch_cnt : in_ch_cnt; if (total == 4) *channels = CONFIGURATION_CHANNEL_CONFIG_4; else if (total == 2) *channels = CONFIGURATION_CHANNEL_CONFIG_2; else *channels = CONFIGURATION_CHANNEL_CONFIG_1; if (!is_600_mode && total > 1) { printf("245 mode only support single channel\r\n"); exit (-1); } } } static void set_ft600_channel_config(FT_60XCONFIGURATION *cfg, CONFIGURATION_FIFO_CLK clock, bool is_600_mode) { cfg->FIFOClock = clock; cfg->FIFOMode = is_600_mode ? CONFIGURATION_FIFO_MODE_600 : CONFIGURATION_FIFO_MODE_245; set_ft600_optional_features(&cfg->OptionalFeatureSupport); set_ft600_channels(&cfg->ChannelConfig, is_600_mode); const char *const CH_STR[] = { "4CH", "2CH", "1CH", "1CH OUT", "1CH IN", }; const char *const FIFO_STR[] = { "FT245", "FT600", }; printf("%s %s @ 100MHz\r\n", CH_STR[cfg->ChannelConfig], FIFO_STR[cfg->FIFOMode]); } static bool set_channel_config(bool is_600_mode, CONFIGURATION_FIFO_CLK clock) { FT_HANDLE handle = NULL; DWORD dwType = FT_DEVICE_UNKNOWN; FT_Create(0, FT_OPEN_BY_INDEX, &handle); if (!handle) return false; FT_GetDeviceInfoDetail(0, NULL, &dwType, NULL, NULL, NULL, NULL, NULL); union CHIP_CONFIGURATION { FT_60XCONFIGURATION ft600; } old_cfg, new_cfg; if (FT_OK != FT_GetChipConfiguration(handle, &old_cfg)) { printf("Failed to get chip conf\r\n"); return false; } memcpy(&new_cfg, &old_cfg, sizeof(union CHIP_CONFIGURATION)); if (dwType == FT_DEVICE_600 || dwType == FT_DEVICE_601) set_ft600_channel_config(&new_cfg.ft600, clock, is_600_mode); else return false; if (memcmp(&new_cfg, &old_cfg, sizeof(union CHIP_CONFIGURATION))) { if (FT_OK != FT_SetChipConfiguration(handle, &new_cfg)) { printf("Failed to set chip conf\r\n"); exit(-1); } else { printf("Configuration changed\r\n"); this_thread::sleep_for(chrono::seconds(1)); get_device_lists(6000); } } FT_Close(handle); return true; } #endif /* end of include guard: COMMON_H_6J30YQFP */