AutoResearch a specific chipset timing configuration Creates channels, runs tests, destroys channels
| 1009 | // AutoResearch a specific chipset timing configuration |
| 1010 | // Creates channels, runs tests, destroys channels |
| 1011 | void autoResearchChipsetTiming(fl::AutoResearchConfig& config, |
| 1012 | int& driver_total, int& driver_passed, |
| 1013 | uint32_t& out_show_duration_ms, |
| 1014 | fl::vector<fl::RunResult>* out_results, |
| 1015 | int num_runs_per_pattern) { |
| 1016 | fl::sstream ss; |
| 1017 | ss << "\n========================================\n"; |
| 1018 | ss << "Testing: " << config.timing_name << "\n"; |
| 1019 | bool has_spi_config = config.tx_configs.size() > 0 && config.tx_configs[0].isSpi(); |
| 1020 | if (has_spi_config) { |
| 1021 | const auto* spi_cfg = config.tx_configs[0].getSpiChipset(); |
| 1022 | ss << " Protocol: SPI (APA102)\n"; |
| 1023 | ss << " Clock: " << (spi_cfg ? spi_cfg->timing.clock_hz : 0) << " Hz\n"; |
| 1024 | } else { |
| 1025 | ss << " T0H: " << config.timing.t1_ns << "ns\n"; |
| 1026 | ss << " T1H: " << (config.timing.t1_ns + config.timing.t2_ns) << "ns\n"; |
| 1027 | ss << " T0L: " << config.timing.t3_ns << "ns\n"; |
| 1028 | ss << " RESET: " << config.timing.reset_us << "us\n"; |
| 1029 | } |
| 1030 | ss << " Channels: " << config.tx_configs.size() << "\n"; |
| 1031 | ss << "========================================"; |
| 1032 | FL_WARN(ss.str()); |
| 1033 | |
| 1034 | // Create ALL channels from tx_configs (multi-channel support) |
| 1035 | fl::vector<fl::shared_ptr<fl::Channel>> channels; |
| 1036 | for (size_t i = 0; i < config.tx_configs.size(); i++) { |
| 1037 | fl::shared_ptr<fl::Channel> channel; |
| 1038 | if (config.tx_configs[i].isSpi()) { |
| 1039 | // SPI chipset: pass through the SPI config directly |
| 1040 | channel = FastLED.add(config.tx_configs[i]); |
| 1041 | } else { |
| 1042 | // Clockless chipset: re-create with runtime timing |
| 1043 | fl::ChannelConfig channel_config(config.tx_configs[i].getDataPin(), config.timing, config.tx_configs[i].mLeds, config.tx_configs[i].rgb_order); |
| 1044 | channel = FastLED.add(channel_config); |
| 1045 | } |
| 1046 | if (!channel) { |
| 1047 | FL_ERROR("Failed to create channel " << i << " (pin " << config.tx_configs[i].getDataPin() << ") - platform not supported"); |
| 1048 | // Clean up previously created channels |
| 1049 | for (auto& ch : channels) { |
| 1050 | ch.reset(); |
| 1051 | } |
| 1052 | return; |
| 1053 | } |
| 1054 | channels.push_back(channel); |
| 1055 | } |
| 1056 | |
| 1057 | FastLED.setBrightness(255); |
| 1058 | |
| 1059 | // Pre-initialize the TX engine to avoid first-call setup delays |
| 1060 | for (size_t i = 0; i < config.tx_configs.size(); i++) { |
| 1061 | fill_solid(config.tx_configs[i].mLeds.data(), config.tx_configs[i].mLeds.size(), CRGB::Black); |
| 1062 | } |
| 1063 | FastLED.show(); |
| 1064 | if (!FastLED.wait(1000)) { // 1s timeout - driver stall guard |
| 1065 | FL_ERROR("[PREINIT] TX wait timeout - driver may be stalled on this platform"); |
| 1066 | FastLED.clear(ClearFlags::CHANNELS); |
| 1067 | return; |
| 1068 | } |
no test coverage detected