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
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
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
|