freedv-gui/codec2-1.2.0/octave/ofdm_state.m

272 lines
8.0 KiB
Matlab

% 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