diff options
| author | Marin Ivanov <[email protected]> | 2025-07-25 10:17:14 +0300 |
|---|---|---|
| committer | Marin Ivanov <[email protected]> | 2026-01-18 20:09:26 +0200 |
| commit | 0168586485e6310c598713c911b1dec5618d61a1 (patch) | |
| tree | 6aabc2a12ef8fef70683f5389bea00f948015f77 /octave/ofdm_state.m | |
* codec2 cut-down version 1.2.0
* Remove codebook and generation of sources
* remove c2dec c2enc binaries
* prepare for emscripten
Diffstat (limited to 'octave/ofdm_state.m')
| -rw-r--r-- | octave/ofdm_state.m | 271 |
1 files changed, 271 insertions, 0 deletions
diff --git a/octave/ofdm_state.m b/octave/ofdm_state.m new file mode 100644 index 0000000..a2eca26 --- /dev/null +++ b/octave/ofdm_state.m @@ -0,0 +1,271 @@ +% ofdm_state.m +% +% Library of state machine functions for the OFDM modem + +1; + +%------------------------------------------------------------------- +% sync_state_machine - calls mode-specific sync state state_machine +%------------------------------------------------------------------- + +function states = sync_state_machine(states, rx_uw) + if strcmp(states.state_machine, "voice1") + states = sync_state_machine_voice1(states, rx_uw); + elseif strcmp(states.state_machine, "data") + if strcmp(states.data_mode, "streaming") + states = sync_state_machine_data_streaming(states, rx_uw); + else + states = sync_state_machine_data_burst(states, rx_uw); + end + elseif strcmp(states.state_machine, "voice2") + states = sync_state_machine_voice2(states, rx_uw); + else + assert(0); + endif +endfunction + +%-------------------------------------------------------------------- +% Due to the low pilot symbol insertion rate and acquisition issues +% the earlier OFDM modem waveforms (700D and 2020) need a complex +% state machine to help them avoid false sync. +%-------------------------------------------------------------------- + +function states = sync_state_machine_voice1(states, rx_uw) + ofdm_load_const; + next_state = states.sync_state; + states.sync_start = states.sync_end = 0; + + if strcmp(states.sync_state,'search') + + if states.timing_valid + states.frame_count = 0; + states.sync_counter = 0; + states.modem_frame = 0; + states.sync_start = 1; + next_state = 'trial'; + end + end + + if strcmp(states.sync_state,'synced') || strcmp(states.sync_state,'trial') + + states.frame_count++; + + % UW occurs at the start of a packet + if states.modem_frame == 0 + states.uw_errors = sum(xor(tx_uw,rx_uw)); + + if strcmp(states.sync_state,'trial') + if states.uw_errors >= states.bad_uw_errors + states.sync_counter++; + states.frame_count = 0; + end + if states.sync_counter == 2 + next_state = "search"; + states.phase_est_bandwidth = "high"; + end + if states.frame_count == 4 + next_state = "synced"; + % change to low bandwidth, but more accurate phase estimation + states.phase_est_bandwidth = "low"; + end + if states.uw_errors < 2 + next_state = "synced"; + % change to low bandwidth, but more accurate phase estimation + states.phase_est_bandwidth = "low"; + else + next_state = "search"; + end + end + + if strcmp(states.sync_state,'synced') + if states.uw_errors > 2 + states.sync_counter++; + else + states.sync_counter = 0; + end + + if states.sync_counter == 6 + next_state = "search"; + states.phase_est_bandwidth = "high"; + end + end + end % if modem_frame == 0 .... + + % keep track of where we are up to in packet + states.modem_frame++; + if (states.modem_frame >= states.Np) states.modem_frame = 0; end + end + + states.last_sync_state = states.sync_state; + states.sync_state = next_state; +endfunction + + +%------------------------------------------------------- +% data (streaming mode) state machine +%------------------------------------------------------- + +function states = sync_state_machine_data_streaming(states, rx_uw) + ofdm_load_const; + next_state = states.sync_state; + states.sync_start = states.sync_end = 0; + + if strcmp(states.sync_state,'search') + if states.timing_valid + states.sync_start = 1; + states.sync_counter = 0; + next_state = 'trial'; + end + end + + states.uw_errors = sum(xor(tx_uw,rx_uw)); + + if strcmp(states.sync_state,'trial') + if states.uw_errors < states.bad_uw_errors; + next_state = "synced"; + states.packet_count = 0; + states.modem_frame = Nuwframes; + else + states.sync_counter++; + if states.sync_counter > Np + next_state = "search"; + end + end + end + + % Note packetsperburst==0 we don't ever lose sync, which is useful for + % stream based testing or external control of state machine + + if strcmp(states.sync_state,'synced') + states.modem_frame++; + if (states.modem_frame >= states.Np) + states.modem_frame = 0; + states.packet_count++; + if (states.packetsperburst) + if (states.packet_count >= states.packetsperburst) + next_state = "search"; + end + end + end + end + + states.last_sync_state = states.sync_state; + states.sync_state = next_state; +endfunction + +%------------------------------------------------------- +% data (burst mode) state machine +%------------------------------------------------------- + +function states = sync_state_machine_data_burst(states, rx_uw) + ofdm_load_const; + next_state = states.sync_state; + states.sync_start = states.sync_end = 0; + + if strcmp(states.sync_state,'search') + if states.timing_valid + states.sync_start = 1; + states.sync_counter = 0; + next_state = 'trial'; + end + end + + states.uw_errors = sum(xor(tx_uw,rx_uw)); + + % pre or post-amble has told us this is the start of the packet. Confirm we + % have a valid frame by checking the UW after the modem frames containing + % the UW have been received + if strcmp(states.sync_state,'trial') + states.sync_counter++; + if states.sync_counter == Nuwframes + if states.uw_errors < states.bad_uw_errors; + next_state = "synced"; + states.packet_count = 0; % number of packets in this burst + states.modem_frame = Nuwframes; % which modem frame we are up to in packet + else + next_state = "search"; + % reset rxbuf to make sure we only ever do a postamble loop once through same samples + states.rxbufst = states.Nrxbufhistory; + states.rxbuf = zeros(1, states.Nrxbuf); + end + end + end + + if strcmp(states.sync_state,'synced') + states.modem_frame++; + if (states.modem_frame >= states.Np) + states.modem_frame = 0; % start of new packet + states.packet_count++; + if (states.packetsperburst) + if (states.packet_count >= states.packetsperburst) + next_state = "search"; % we've finished this burst + % reset rxbuf to make sure we only ever do a postamble loop once through same samples + states.rxbufst = states.Nrxbufhistory; + states.rxbuf = zeros(1, states.Nrxbuf); + end + end + end + end + + states.last_sync_state = states.sync_state; + states.sync_state = next_state; +endfunction + +%------------------------------------------------------- +% fast sync voice state state_machine +%------------------------------------------------------- + +function states = sync_state_machine_voice2(states, rx_uw) + ofdm_load_const; + next_state = states.sync_state; + states.sync_start = states.sync_end = 0; + + if strcmp(states.sync_state,'search') + + if states.timing_valid + states.frame_count = 0; + states.sync_counter = 0; + states.modem_frame = 0; + states.sync_start = 1; + next_state = 'trial'; + end + end + + if strcmp(states.sync_state,'synced') || strcmp(states.sync_state,'trial') + + states.frame_count++; + + % UW occurs at the start of a packet + if states.modem_frame == 0 + states.uw_errors = sum(xor(tx_uw,rx_uw)); + + if strcmp(states.sync_state,'trial') + if states.uw_errors <= states.bad_uw_errors + next_state = "synced"; + else + next_state = "search"; + end + end + + if strcmp(states.sync_state,'synced') + if states.uw_errors > states.bad_uw_errors + states.sync_counter++; + else + states.sync_counter = 0; + end + + if states.sync_counter == 6 + next_state = "search"; + end + end + end + + % keep track of where we are up to in packet + states.modem_frame++; + if (states.modem_frame >= states.Np) states.modem_frame = 0; end + end + + states.last_sync_state = states.sync_state; + states.sync_state = next_state; +endfunction + |
