wangrong
2026-08-24 beef6536e7c8dd3f5cbe8f73585611479910bea7
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
#pragma once
 
#include <vector>
#include <deque>
#include <string>
#include <memory>
#include <optional>
#include <cmath>
#include "wifi_manager.h"
#include "application.h"
 
// Audio signal processing constants for WiFi configuration via audio
const size_t kAudioSampleRate = 6400;
const size_t kMarkFrequency = 1800;
const size_t kSpaceFrequency = 1500;
const size_t kBitRate = 100;
const size_t kWindowSize = 64;
 
namespace audio_wifi_config
{
    // Main function to receive WiFi credentials through audio signal
    void ReceiveWifiCredentialsFromAudio(Application *app, WifiManager *wifi_manager, Display *display, 
                                         size_t input_channels = 1);
 
    /**
     * Goertzel algorithm implementation for single frequency detection
     * Used to detect specific audio frequencies in the AFSK demodulation process
     */
    class FrequencyDetector
    {
    private:
        float frequency_;              // Target frequency (normalized, i.e., f / fs)
        size_t window_size_;           // Window size for analysis
        float frequency_bin_;          // Frequency bin
        float angular_frequency_;      // Angular frequency
        float cos_coefficient_;        // cos(w)
        float sin_coefficient_;        // sin(w)
        float filter_coefficient_;     // 2 * cos(w)
        std::deque<float> state_buffer_;  // Circular buffer for storing S[-1] and S[-2]
 
    public:
        /**
         * Constructor
         * @param frequency Normalized frequency (f / fs)
         * @param window_size Window size for analysis
         */
        FrequencyDetector(float frequency, size_t window_size);
 
        /**
         * Reset the detector state
         */
        void Reset();
 
        /**
         * Process one audio sample
         * @param sample Input audio sample
         */
        void ProcessSample(float sample);
 
        /**
         * Calculate current amplitude
         * @return Amplitude value
         */
        float GetAmplitude() const;
    };
 
    /**
     * Audio signal processor for Mark/Space frequency pair detection
     * Processes audio signals to extract digital data using AFSK demodulation
     */
    class AudioSignalProcessor
    {
    private:
        std::deque<float> input_buffer_;             // Input sample buffer
        size_t input_buffer_size_;                   // Input buffer size = window size
        size_t output_sample_count_;                 // Output sample counter
        size_t samples_per_bit_;                     // Samples per bit threshold
        std::unique_ptr<FrequencyDetector> mark_detector_;   // Mark frequency detector
        std::unique_ptr<FrequencyDetector> space_detector_;  // Space frequency detector
 
    public:
        /**
         * Constructor
         * @param sample_rate Audio sampling rate
         * @param mark_frequency Mark frequency for digital '1'
         * @param space_frequency Space frequency for digital '0'
         * @param bit_rate Data transmission bit rate
         * @param window_size Analysis window size
         */
        AudioSignalProcessor(size_t sample_rate, size_t mark_frequency, size_t space_frequency,
                           size_t bit_rate, size_t window_size);
 
        /**
         * Process input audio samples
         * @param samples Input audio sample vector
         * @return Vector of Mark probability values (0.0 to 1.0)
         */
        std::vector<float> ProcessAudioSamples(const std::vector<float> &samples);
    };
 
    /**
     * Data reception state machine states
     */
    enum class DataReceptionState
    {
        kInactive,  // Waiting for start signal
        kWaiting,   // Detected potential start, waiting for confirmation
        kReceiving  // Actively receiving data
    };
 
    /**
     * Data buffer for managing audio-to-digital data conversion
     * Handles the complete process from audio signal to decoded text data
     */
    class AudioDataBuffer
    {
    private:
        DataReceptionState current_state_;       // Current reception state
        std::deque<uint8_t> identifier_buffer_;  // Buffer for start/end identifier detection
        size_t identifier_buffer_size_;          // Identifier buffer size
        std::vector<uint8_t> bit_buffer_;        // Buffer for storing bit stream
        size_t max_bit_buffer_size_;             // Maximum bit buffer size
        const std::vector<uint8_t> start_of_transmission_;  // Start-of-transmission identifier
        const std::vector<uint8_t> end_of_transmission_;    // End-of-transmission identifier
        bool enable_checksum_validation_;       // Whether to validate checksum
 
    public:
        std::optional<std::string> decoded_text; // Successfully decoded text data
 
        /**
         * Default constructor using predefined start and end identifiers
         */
        AudioDataBuffer();
 
        /**
         * Constructor with custom parameters
         * @param max_byte_size Expected maximum data size in bytes
         * @param start_identifier Start-of-transmission identifier
         * @param end_identifier End-of-transmission identifier
         * @param enable_checksum Whether to enable checksum validation
         */
        AudioDataBuffer(size_t max_byte_size, const std::vector<uint8_t> &start_identifier,
                      const std::vector<uint8_t> &end_identifier, bool enable_checksum = false);
 
        /**
         * Process probability data and attempt to decode
         * @param probabilities Vector of Mark probabilities
         * @param threshold Decision threshold for bit detection
         * @return true if complete data was successfully received and decoded
         */
        bool ProcessProbabilityData(const std::vector<float> &probabilities, float threshold = 0.5f);
 
        /**
         * Calculate checksum for ASCII text
         * @param text Input text string
         * @return Checksum value (0-255)
         */
        static uint8_t CalculateChecksum(const std::string &text);
 
    private:
        /**
         * Convert bit vector to byte vector
         * @param bits Input bit vector
         * @return Converted byte vector
         */
        std::vector<uint8_t> ConvertBitsToBytes(const std::vector<uint8_t> &bits) const;
 
        /**
         * Clear all buffers and reset state
         */
        void ClearBuffers();
    };
 
    // Default start and end transmission identifiers
    extern const std::vector<uint8_t> kDefaultStartTransmissionPattern;
    extern const std::vector<uint8_t> kDefaultEndTransmissionPattern;
}