afsk_demod.cc 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411
  1. #include "afsk_demod.h"
  2. #include <cstring>
  3. #include <algorithm>
  4. #include "esp_log.h"
  5. #ifndef M_PI
  6. #define M_PI 3.14159265358979323846
  7. #endif
  8. namespace audio_wifi_config
  9. {
  10. static const char *kLogTag = "AUDIO_WIFI_CONFIG";
  11. void ReceiveWifiCredentialsFromAudio(Application *app,
  12. WifiConfigurationAp *wifi_ap)
  13. {
  14. const int kInputSampleRate = 16000; // Input sampling rate
  15. const float kDownsampleStep = static_cast<float>(kInputSampleRate) / static_cast<float>(kAudioSampleRate); // Downsampling step
  16. std::vector<int16_t> audio_data;
  17. AudioSignalProcessor signal_processor(kAudioSampleRate, kMarkFrequency, kSpaceFrequency, kBitRate, kWindowSize);
  18. AudioDataBuffer data_buffer;
  19. while (true)
  20. {
  21. // 检查Application状态,只有在WiFi配置模式下才处理音频
  22. if (app->GetDeviceState() != kDeviceStateWifiConfiguring) {
  23. // 不在WiFi配置状态,休眠100ms后再检查
  24. vTaskDelay(pdMS_TO_TICKS(100));
  25. continue;
  26. }
  27. if (!app->GetAudioService().ReadAudioData(audio_data, 16000, 480)) { // 16kHz, 480 samples corresponds to 30ms data
  28. // 读取音频失败,短暂延迟后重试
  29. ESP_LOGI(kLogTag, "Failed to read audio data, retrying.");
  30. vTaskDelay(pdMS_TO_TICKS(10));
  31. continue;
  32. }
  33. // Downsample the audio data
  34. std::vector<float> downsampled_data;
  35. size_t last_index = 0;
  36. if (kDownsampleStep > 1.0f)
  37. {
  38. downsampled_data.reserve(audio_data.size() / static_cast<size_t>(kDownsampleStep));
  39. for (size_t i = 0; i < audio_data.size(); ++i)
  40. {
  41. size_t sample_index = static_cast<size_t>(i / kDownsampleStep);
  42. if ((sample_index + 1) > last_index)
  43. {
  44. downsampled_data.push_back(static_cast<float>(audio_data[i]));
  45. last_index = sample_index + 1;
  46. }
  47. }
  48. }
  49. else
  50. {
  51. downsampled_data.reserve(audio_data.size());
  52. for (int16_t sample : audio_data)
  53. {
  54. downsampled_data.push_back(static_cast<float>(sample));
  55. }
  56. }
  57. // Process audio samples to get probability data
  58. auto probabilities = signal_processor.ProcessAudioSamples(downsampled_data);
  59. // Feed probability data to the data buffer
  60. if (data_buffer.ProcessProbabilityData(probabilities, 0.5f))
  61. {
  62. // If complete data was received, extract WiFi credentials
  63. if (data_buffer.decoded_text.has_value())
  64. {
  65. ESP_LOGI(kLogTag, "Received text data: %s", data_buffer.decoded_text->c_str());
  66. // Split SSID and password by newline character
  67. std::string wifi_ssid, wifi_password;
  68. size_t newline_position = data_buffer.decoded_text->find('\n');
  69. if (newline_position != std::string::npos)
  70. {
  71. wifi_ssid = data_buffer.decoded_text->substr(0, newline_position);
  72. wifi_password = data_buffer.decoded_text->substr(newline_position + 1);
  73. ESP_LOGI(kLogTag, "WiFi SSID: %s, Password: %s", wifi_ssid.c_str(), wifi_password.c_str());
  74. }
  75. else
  76. {
  77. ESP_LOGE(kLogTag, "Invalid data format, no newline character found");
  78. continue;
  79. }
  80. if (wifi_ap->ConnectToWifi(wifi_ssid, wifi_password))
  81. {
  82. wifi_ap->Save(wifi_ssid, wifi_password); // Save WiFi credentials
  83. esp_restart(); // Restart device to apply new WiFi configuration
  84. }
  85. else
  86. {
  87. ESP_LOGE(kLogTag, "Failed to connect to WiFi with received credentials");
  88. }
  89. data_buffer.decoded_text.reset(); // Clear processed data
  90. }
  91. }
  92. vTaskDelay(pdMS_TO_TICKS(1)); // 1ms delay
  93. }
  94. }
  95. // Default start and end transmission identifiers
  96. // \x01\x02 = 00000001 00000010
  97. const std::vector<uint8_t> kDefaultStartTransmissionPattern = {
  98. 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0};
  99. // \x03\x04 = 00000011 00000100
  100. const std::vector<uint8_t> kDefaultEndTransmissionPattern = {
  101. 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0};
  102. // FrequencyDetector implementation
  103. FrequencyDetector::FrequencyDetector(float frequency, size_t window_size)
  104. : frequency_(frequency), window_size_(window_size)
  105. {
  106. frequency_bin_ = std::floor(frequency_ * static_cast<float>(window_size_));
  107. angular_frequency_ = 2.0f * M_PI * frequency_;
  108. cos_coefficient_ = std::cos(angular_frequency_);
  109. sin_coefficient_ = std::sin(angular_frequency_);
  110. filter_coefficient_ = 2.0f * cos_coefficient_;
  111. // Initialize state buffer
  112. state_buffer_.push_back(0.0f);
  113. state_buffer_.push_back(0.0f);
  114. }
  115. void FrequencyDetector::Reset()
  116. {
  117. state_buffer_.clear();
  118. state_buffer_.push_back(0.0f);
  119. state_buffer_.push_back(0.0f);
  120. }
  121. void FrequencyDetector::ProcessSample(float sample)
  122. {
  123. if (state_buffer_.size() < 2)
  124. {
  125. return;
  126. }
  127. float s_minus_2 = state_buffer_.front(); // S[-2]
  128. state_buffer_.pop_front();
  129. float s_minus_1 = state_buffer_.front(); // S[-1]
  130. state_buffer_.pop_front();
  131. float s_current = sample + filter_coefficient_ * s_minus_1 - s_minus_2;
  132. state_buffer_.push_back(s_minus_1); // Put S[-1] back
  133. state_buffer_.push_back(s_current); // Add new S[0]
  134. }
  135. float FrequencyDetector::GetAmplitude() const
  136. {
  137. if (state_buffer_.size() < 2)
  138. {
  139. return 0.0f;
  140. }
  141. float s_minus_1 = state_buffer_[1]; // S[-1]
  142. float s_minus_2 = state_buffer_[0]; // S[-2]
  143. float real_part = cos_coefficient_ * s_minus_1 - s_minus_2; // Real part
  144. float imaginary_part = sin_coefficient_ * s_minus_1; // Imaginary part
  145. return std::sqrt(real_part * real_part + imaginary_part * imaginary_part) /
  146. (static_cast<float>(window_size_) / 2.0f);
  147. }
  148. // AudioSignalProcessor implementation
  149. AudioSignalProcessor::AudioSignalProcessor(size_t sample_rate, size_t mark_frequency, size_t space_frequency,
  150. size_t bit_rate, size_t window_size)
  151. : input_buffer_size_(window_size), output_sample_count_(0)
  152. {
  153. if (sample_rate % bit_rate != 0)
  154. {
  155. // On ESP32 we can continue execution, but log the error
  156. ESP_LOGW(kLogTag, "Sample rate %zu is not divisible by bit rate %zu", sample_rate, bit_rate);
  157. }
  158. float normalized_mark_freq = static_cast<float>(mark_frequency) / static_cast<float>(sample_rate);
  159. float normalized_space_freq = static_cast<float>(space_frequency) / static_cast<float>(sample_rate);
  160. mark_detector_ = std::make_unique<FrequencyDetector>(normalized_mark_freq, window_size);
  161. space_detector_ = std::make_unique<FrequencyDetector>(normalized_space_freq, window_size);
  162. samples_per_bit_ = sample_rate / bit_rate; // Number of samples per bit
  163. }
  164. std::vector<float> AudioSignalProcessor::ProcessAudioSamples(const std::vector<float> &samples)
  165. {
  166. std::vector<float> result;
  167. for (float sample : samples)
  168. {
  169. if (input_buffer_.size() < input_buffer_size_)
  170. {
  171. input_buffer_.push_back(sample); // Just add, don't process yet
  172. }
  173. else
  174. {
  175. // Input buffer is full, process the data
  176. input_buffer_.pop_front(); // Remove oldest sample
  177. input_buffer_.push_back(sample); // Add new sample
  178. output_sample_count_++;
  179. if (output_sample_count_ >= samples_per_bit_)
  180. {
  181. // Process all samples in the window using Goertzel algorithm
  182. for (float window_sample : input_buffer_)
  183. {
  184. mark_detector_->ProcessSample(window_sample);
  185. space_detector_->ProcessSample(window_sample);
  186. }
  187. float mark_amplitude = mark_detector_->GetAmplitude(); // Mark amplitude
  188. float space_amplitude = space_detector_->GetAmplitude(); // Space amplitude
  189. // Avoid division by zero
  190. float mark_probability = mark_amplitude /
  191. (space_amplitude + mark_amplitude + std::numeric_limits<float>::epsilon());
  192. result.push_back(mark_probability);
  193. // Reset detector windows
  194. mark_detector_->Reset();
  195. space_detector_->Reset();
  196. output_sample_count_ = 0; // Reset output counter
  197. }
  198. }
  199. }
  200. return result;
  201. }
  202. // AudioDataBuffer implementation
  203. AudioDataBuffer::AudioDataBuffer()
  204. : current_state_(DataReceptionState::kInactive),
  205. start_of_transmission_(kDefaultStartTransmissionPattern),
  206. end_of_transmission_(kDefaultEndTransmissionPattern),
  207. enable_checksum_validation_(true)
  208. {
  209. identifier_buffer_size_ = std::max(start_of_transmission_.size(), end_of_transmission_.size());
  210. max_bit_buffer_size_ = 776; // Preset bit buffer size, 776 bits = (32 + 1 + 63 + 1) * 8 = 776
  211. bit_buffer_.reserve(max_bit_buffer_size_);
  212. }
  213. AudioDataBuffer::AudioDataBuffer(size_t max_byte_size, const std::vector<uint8_t> &start_identifier,
  214. const std::vector<uint8_t> &end_identifier, bool enable_checksum)
  215. : current_state_(DataReceptionState::kInactive),
  216. start_of_transmission_(start_identifier),
  217. end_of_transmission_(end_identifier),
  218. enable_checksum_validation_(enable_checksum)
  219. {
  220. identifier_buffer_size_ = std::max(start_of_transmission_.size(), end_of_transmission_.size());
  221. max_bit_buffer_size_ = max_byte_size * 8; // Bit buffer size in bytes
  222. bit_buffer_.reserve(max_bit_buffer_size_);
  223. }
  224. uint8_t AudioDataBuffer::CalculateChecksum(const std::string &text)
  225. {
  226. uint8_t checksum = 0;
  227. for (char character : text)
  228. {
  229. checksum += static_cast<uint8_t>(character);
  230. }
  231. return checksum;
  232. }
  233. void AudioDataBuffer::ClearBuffers()
  234. {
  235. identifier_buffer_.clear();
  236. bit_buffer_.clear();
  237. }
  238. bool AudioDataBuffer::ProcessProbabilityData(const std::vector<float> &probabilities, float threshold)
  239. {
  240. for (float probability : probabilities)
  241. {
  242. uint8_t bit = (probability > threshold) ? 1 : 0;
  243. if (identifier_buffer_.size() >= identifier_buffer_size_)
  244. {
  245. identifier_buffer_.pop_front(); // Maintain buffer size
  246. }
  247. identifier_buffer_.push_back(bit);
  248. // Process received bit based on state machine
  249. switch (current_state_)
  250. {
  251. case DataReceptionState::kInactive:
  252. if (identifier_buffer_.size() >= start_of_transmission_.size())
  253. {
  254. current_state_ = DataReceptionState::kWaiting; // Enter waiting state
  255. ESP_LOGI(kLogTag, "Entering Waiting state");
  256. }
  257. break;
  258. case DataReceptionState::kWaiting:
  259. // Waiting state, possibly waiting for transmission end
  260. if (identifier_buffer_.size() >= start_of_transmission_.size())
  261. {
  262. std::vector<uint8_t> identifier_snapshot(identifier_buffer_.begin(), identifier_buffer_.end());
  263. if (identifier_snapshot == start_of_transmission_)
  264. {
  265. ClearBuffers(); // Clear buffers
  266. current_state_ = DataReceptionState::kReceiving; // Enter receiving state
  267. ESP_LOGI(kLogTag, "Entering Receiving state");
  268. }
  269. }
  270. break;
  271. case DataReceptionState::kReceiving:
  272. bit_buffer_.push_back(bit);
  273. if (identifier_buffer_.size() >= end_of_transmission_.size())
  274. {
  275. std::vector<uint8_t> identifier_snapshot(identifier_buffer_.begin(), identifier_buffer_.end());
  276. if (identifier_snapshot == end_of_transmission_)
  277. {
  278. current_state_ = DataReceptionState::kInactive; // Enter inactive state
  279. // Convert bits to bytes
  280. std::vector<uint8_t> bytes = ConvertBitsToBytes(bit_buffer_);
  281. uint8_t received_checksum = 0;
  282. size_t minimum_length = 0;
  283. if (enable_checksum_validation_)
  284. {
  285. // If checksum is required, last byte is checksum
  286. minimum_length = 1 + start_of_transmission_.size() / 8;
  287. if (bytes.size() >= minimum_length)
  288. {
  289. received_checksum = bytes[bytes.size() - start_of_transmission_.size() / 8 - 1];
  290. }
  291. }
  292. else
  293. {
  294. minimum_length = start_of_transmission_.size() / 8;
  295. }
  296. if (bytes.size() < minimum_length)
  297. {
  298. ClearBuffers();
  299. ESP_LOGW(kLogTag, "Data too short, clearing buffer");
  300. return false; // Data too short, return failure
  301. }
  302. // Extract text data (remove trailing identifier part)
  303. std::vector<uint8_t> text_bytes(
  304. bytes.begin(), bytes.begin() + bytes.size() - minimum_length);
  305. std::string result(text_bytes.begin(), text_bytes.end());
  306. // Validate checksum if required
  307. if (enable_checksum_validation_)
  308. {
  309. uint8_t calculated_checksum = CalculateChecksum(result);
  310. if (calculated_checksum != received_checksum)
  311. {
  312. // Checksum mismatch
  313. ESP_LOGW(kLogTag, "Checksum mismatch: expected %d, got %d",
  314. received_checksum, calculated_checksum);
  315. ClearBuffers();
  316. return false;
  317. }
  318. }
  319. ClearBuffers();
  320. decoded_text = result;
  321. return true; // Return success
  322. }
  323. else if (bit_buffer_.size() >= max_bit_buffer_size_)
  324. {
  325. // If not end identifier and bit buffer is full, reset
  326. ClearBuffers();
  327. ESP_LOGW(kLogTag, "Buffer overflow, clearing buffer");
  328. current_state_ = DataReceptionState::kInactive; // Reset state machine
  329. }
  330. }
  331. break;
  332. }
  333. }
  334. return false;
  335. }
  336. std::vector<uint8_t> AudioDataBuffer::ConvertBitsToBytes(const std::vector<uint8_t> &bits) const
  337. {
  338. std::vector<uint8_t> bytes;
  339. // Ensure number of bits is a multiple of 8
  340. size_t complete_bytes_count = bits.size() / 8;
  341. bytes.reserve(complete_bytes_count);
  342. for (size_t i = 0; i < complete_bytes_count; ++i)
  343. {
  344. uint8_t byte_value = 0;
  345. for (size_t j = 0; j < 8; ++j)
  346. {
  347. byte_value |= bits[i * 8 + j] << (7 - j);
  348. }
  349. bytes.push_back(byte_value);
  350. }
  351. return bytes;
  352. }
  353. }