aboutsummaryrefslogtreecommitdiff
path: root/octave/ofdm_state.m
diff options
context:
space:
mode:
Diffstat (limited to 'octave/ofdm_state.m')
-rw-r--r--octave/ofdm_state.m271
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
+