Skip to content

Commit 7e5403c

Browse files
authored
Merge pull request drowe67#206 from drowe67/ms-stm32-700e
Add 700E support to the SM1000.
2 parents d1ae6b4 + ff8c33e commit 7e5403c

File tree

13 files changed

+319
-42
lines changed

13 files changed

+319
-42
lines changed

src/freedv_700.c

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ void freedv_ofdm_voice_open(struct freedv *f, char *mode) {
110110
ofdm_config = ofdm_get_config_param(f->ofdm);
111111
f->ofdm_bitsperpacket = ofdm_get_bits_per_packet(f->ofdm);
112112
f->ofdm_bitsperframe = ofdm_get_bits_per_frame(f->ofdm);
113-
f->ofdm_nuwbits = (ofdm_config->ns - 1) * ofdm_config->bps - ofdm_config->txtbits;
113+
f->ofdm_nuwbits = ofdm_config->nuwbits;
114114
f->ofdm_ntxtbits = ofdm_config->txtbits;
115115

116116
f->ldpc = (struct LDPC*)MALLOC(sizeof(struct LDPC));
@@ -140,11 +140,6 @@ void freedv_ofdm_voice_open(struct freedv *f, char *mode) {
140140

141141
f->tx_bits = NULL; /* not used for 700D */
142142

143-
/* tx BPF off on embedded platforms, as it consumes significant CPU */
144-
#ifdef __EMBEDDED__
145-
ofdm_set_tx_bpf(f->ofdm, 0);
146-
#endif
147-
148143
f->speech_sample_rate = FREEDV_FS_8000;
149144
f->codec2 = codec2_create(CODEC2_MODE_700C); assert(f->codec2 != NULL);
150145
/* should be exactly an integer number of Codec 2 frames in a OFDM modem frame */
@@ -162,6 +157,10 @@ void freedv_ofdm_voice_open(struct freedv *f, char *mode) {
162157

163158
/* attenuate audio 12dB as channel noise isn't that pleasant */
164159
f->passthrough_gain = 0.25;
160+
161+
/* should all add up to a complete frame */
162+
assert((ofdm_config->ns - 1) * ofdm_config->nc * ofdm_config->bps ==
163+
f->ldpc->coded_bits_per_frame + ofdm_config->txtbits + f->ofdm_nuwbits);
165164
}
166165

167166
// open function for OFDM data modes, TODO consider moving to a new

src/ldpc_codes.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@ struct LDPC ldpc_codes[] = {
3939
(uint16_t *)HRA_112_112_H_rows,
4040
(uint16_t *)HRA_112_112_H_cols
4141
}
42-
#ifndef __EMBEDDED__
4342
,
4443
/* short rate 1/2 code for FreeDV 700E */
4544
{
@@ -56,6 +55,7 @@ struct LDPC ldpc_codes[] = {
5655
(uint16_t *)HRA_56_56_H_rows,
5756
(uint16_t *)HRA_56_56_H_cols
5857
},
58+
#ifndef __EMBEDDED__
5959

6060
/* default Wenet High Alitiude Balloon rate 0.8 code */
6161
{

src/ofdm.c

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,7 @@ struct OFDM *ofdm_create(const struct OFDM_CONFIG *config) {
223223
} else {
224224
/* Use the users values */
225225

226+
226227
strcpy(ofdm->mode, config->mode);
227228
ofdm->nc = config->nc; /* Number of carriers */
228229
ofdm->np = config->np; /* Number of modem Frames per Packet */
@@ -251,6 +252,7 @@ struct OFDM *ofdm_create(const struct OFDM_CONFIG *config) {
251252
ofdm->clip_en = config->clip_en;
252253
memcpy(ofdm->tx_uw, config->tx_uw, ofdm->nuwbits);
253254
ofdm->data_mode = config->data_mode;
255+
254256
}
255257

256258
ofdm->rs = (1.0f / ofdm->ts); /* Modulation Symbol Rate */
@@ -1918,17 +1920,15 @@ void ofdm_sync_state_machine_data_streaming(struct OFDM *ofdm, uint8_t *rx_uw) {
19181920
}
19191921

19201922
if (ofdm->sync_state == trial) {
1921-
if (ofdm->sync_state == trial) {
1922-
if (ofdm->uw_errors < ofdm->bad_uw_errors) {
1923-
next_state = synced;
1924-
ofdm->packet_count = 0;
1925-
ofdm->modem_frame = ofdm->nuwframes;
1926-
} else {
1927-
ofdm->sync_counter++;
1923+
if (ofdm->uw_errors < ofdm->bad_uw_errors) {
1924+
next_state = synced;
1925+
ofdm->packet_count = 0;
1926+
ofdm->modem_frame = ofdm->nuwframes;
1927+
} else {
1928+
ofdm->sync_counter++;
19281929

1929-
if (ofdm->sync_counter > ofdm->np) {
1930-
next_state = search;
1931-
}
1930+
if (ofdm->sync_counter > ofdm->np) {
1931+
next_state = search;
19321932
}
19331933
}
19341934
}

stm32/CMakeLists.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ endif()
6767
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -std=gnu11 -mlittle-endian -mthumb -mthumb-interwork --specs=nano.specs -u_printf_float -mcpu=cortex-m4 -ffunction-sections -fdata-sections -O3")
6868

6969
add_definitions(-DSTM32F40_41xxx -DCORTEX_M4 -D__EMBEDDED__)
70-
add_definitions(-DFREEDV_MODE_EN_DEFAULT=0 -DFREEDV_MODE_1600_EN=1 -DFREEDV_MODE_700D_EN=1 -DCODEC2_MODE_EN_DEFAULT=0 -DCODEC2_MODE_1300_EN=1 -DCODEC2_MODE_700C_EN=1)
70+
add_definitions(-DFREEDV_MODE_EN_DEFAULT=0 -DFREEDV_MODE_1600_EN=1 -DFREEDV_MODE_700D_EN=1 -DFREEDV_MODE_700E_EN=1 -DCODEC2_MODE_EN_DEFAULT=0 -DCODEC2_MODE_1300_EN=1 -DCODEC2_MODE_700C_EN=1)
7171

7272
if(FLOAT_TYPE STREQUAL "hard")
7373
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsingle-precision-constant -Wdouble-promotion -mfpu=fpv4-sp-d16 -mfloat-abi=hard -D__FPU_PRESENT=1 -D__FPU_USED=1")
@@ -203,6 +203,7 @@ ${CODEC2_SRC}/freedv_data_channel.c
203203
${CODEC2_SRC}/newamp1.c
204204
${CODEC2_SRC}/mbest.c
205205
${CODEC2_SRC}/HRA_112_112.c
206+
${CODEC2_SRC}/HRA_56_56.c
206207
${CODEC2_SRC}/linreg.c
207208
${CODEC2_SRC}/mpdecode_core.c
208209
${CODEC2_SRC}/ldpc_codes.c

stm32/doc/sm1000_manual.md

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@
99
1. The SELECT button steps through the mode:
1010
+ Analog pass through (ANA)
1111
+ FreeDV 1600 (1600)
12-
+ FreeDV 700D (700D)
12+
+ FreeDV 700D (700D)
13+
+ FreeDV 700E (700E)
1314

1415
1. Select 1600 mode.
1516

@@ -78,7 +79,8 @@ The menu structure looks like this:
7879
|---> "MODE": Boot-up Operating mode
7980
| |---> "ANA": Analogue mode
8081
| |---> "1600": FreeDV 1600
81-
| '---> "700D": FreeDV 700D
82+
| |---> "700D": FreeDV 700D
83+
| '---> "700E": FreeDV 700E
8284
|
8385
|---> "TOT": Time-out timer
8486
| |---> "TIME": Total time-out period (0 == disabled)
@@ -106,7 +108,7 @@ You can program the flash memory on your SM1000 via USB using a Windows or Linux
106108
2 | July 2019 | [sm1000v2.bin](http://www.rowetel.com/downloads/codec2/smartmic/sm1000v2.bin) | [sm1000v2.dfu](http://www.rowetel.com/downloads/codec2/smartmic/sm1000v2.dfu) | FreeDV 700D and morse menus
107109
3 | March 2020 | [sm1000v3.bin](http://www.rowetel.com/downloads/codec2/smartmic/sm1000v3.bin) | [sm1000v3.dfu](http://www.rowetel.com/downloads/codec2/smartmic/sm1000v3.dfu) | Menu bug fixes, 700D modem improvements & automatic Mic EQ
108110
4 | May 2020 | [sm1000v4.bin](http://www.rowetel.com/downloads/codec2/smartmic/sm1000v4.bin) | [sm1000v4.dfu](http://www.rowetel.com/downloads/codec2/smartmic/sm1000v4.dfu) | 700D sync logic to reduce stop burbling with no signal
109-
5 | August 2021 | [sm1000v5.bin](http://www.rowetel.com/downloads/codec2/smartmic/sm1000v5.bin) | [sm1000v5.dfu](http://www.rowetel.com/downloads/codec2/smartmic/sm1000v5.dfu) | maintenance release due to FreeDV API refactoring, no changes to SM1000 behaivour
111+
5 | August 2021 | [sm1000v5.bin](http://www.rowetel.com/downloads/codec2/smartmic/sm1000v5.bin) | [sm1000v5.dfu](http://www.rowetel.com/downloads/codec2/smartmic/sm1000v5.dfu) | FreeDV 700E and Tx band pass filter for 700D & E
110112

111113
## Windows
112114

@@ -176,7 +178,7 @@ To perform a factory reset, hold down BACK whilst powering the device on. A loud
176178

177179
The SM1000 hardware was developed by David Rowe VK5DGR and Rick Barnich KA8BMA. It is being manufactured, tested and shipped by our good friend Edwin at Dragino in Shenzhen, China.
178180

179-
Steve (K5OKC) helped develop the fine OFDM modem used for FreeDV 700D. Don (W7DMR), spearheaded the port of FreeDV 700D to the SM1000, including code optimisation and a comprehensive unit test system. Don, Danilo (DB4PLE), and Richard (KF5OIM) have done some fantastic work on the cmake build and test system for the stm32 port of 700D. Stuart VK4MSL developed the morse menu system for the SM1000.
181+
Steve (K5OKC) helped develop the fine OFDM modem used for FreeDV 700D. Don (W7DMR), spearheaded the port of FreeDV 700D to the SM1000, including code optimisation and a comprehensive unit test system. Don, Danilo (DB4PLE), and Richard (KF5OIM) have done some fantastic work on the cmake build and test system for the stm32 port of 700D. Stuart VK4MSL developed the morse menu system for the SM1000. Mooneer, K6AQ, ported FreeDV 700E to the SM1000.
180182

181183
Thanks also to the many Hams who kindly helped out with testing new firmware releases.
182184

stm32/src/sm1000_main.c

Lines changed: 64 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -133,10 +133,11 @@
133133
*/
134134
uint8_t core_state = STATE_RX;
135135

136-
#define MAX_MODES 3
136+
#define MAX_MODES 4
137137
#define ANALOG 0
138138
#define DV1600 1
139139
#define DV700D 2
140+
#define DV700E 3
140141

141142
struct switch_t sw_select; /*!< Switch driver for SELECT button */
142143
struct switch_t sw_back; /*!< Switch driver for BACK button */
@@ -304,6 +305,25 @@ struct freedv *set_freedv_mode(int op_mode, int *n_samples) {
304305
freedv_set_snr_squelch_thresh(f, -2.0); /* squelch at -2.0 dB */
305306
freedv_set_squelch_en(f, 1);
306307
freedv_set_eq(f, 1); /* equaliser on by default */
308+
309+
/* Clipping and TXBPF nice to have for 700D. */
310+
freedv_set_clip(f, 1);
311+
freedv_set_tx_bpf(f, 1);
312+
313+
*n_samples = freedv_get_n_speech_samples(f);
314+
break;
315+
case DV700E:
316+
usart_printf("FreeDV 700E\n");
317+
f = freedv_open(FREEDV_MODE_700E);
318+
assert(f != NULL);
319+
freedv_set_snr_squelch_thresh(f, 0.0); /* squelch at 0.0 dB */
320+
freedv_set_squelch_en(f, 1);
321+
freedv_set_eq(f, 1); /* equaliser on by default */
322+
323+
/* Clipping and TXBPF needed for 700E. */
324+
freedv_set_clip(f, 1);
325+
freedv_set_tx_bpf(f, 1);
326+
307327
*n_samples = freedv_get_n_speech_samples(f);
308328
break;
309329
}
@@ -468,6 +488,8 @@ int main(void) {
468488
snprintf(startup_announcement, 16, VERSION " 1600");
469489
else if (op_mode == DV700D)
470490
snprintf(startup_announcement, 16, VERSION " 700D");
491+
else if (op_mode == DV700E)
492+
snprintf(startup_announcement, 16, VERSION " 700E");
471493
morse_play(&morse_player, startup_announcement);
472494

473495
usart_printf("entering main loop...\n");
@@ -512,7 +534,7 @@ int main(void) {
512534
}
513535

514536
/* if we have moved from tx to rx reset sync state of rx so we re-start acquisition */
515-
if ((op_mode == DV1600) || (op_mode == DV700D))
537+
if ((op_mode == DV1600) || (op_mode == DV700D) || (op_mode == DV700E))
516538
if ((prev_core_state == STATE_TX) && (core_state == STATE_RX))
517539
freedv_set_sync(f, FREEDV_SYNC_UNSYNC);
518540

@@ -591,7 +613,7 @@ int main(void) {
591613
lastms = ms;
592614
}
593615

594-
/* 1600 or 700D DV mode */
616+
/* 1600 or 700D/E DV mode */
595617

596618
nin = freedv_nin(f);
597619
nout = nin;
@@ -733,7 +755,12 @@ int process_core_state_machine(int core_state, struct menu_t *menu, int *op_mode
733755
mode_changed = 1;
734756
} else if (switch_released(&sw_back)) {
735757
/* Shortcut: change current mode */
736-
*op_mode = (*op_mode - 1) % MAX_MODES;
758+
*op_mode = *op_mode - 1;
759+
if (*op_mode < 0)
760+
{
761+
// Loop back around to the end of the mode list if we reach 0.
762+
*op_mode = MAX_MODES - 1;
763+
}
737764
mode_changed = 1;
738765
}
739766

@@ -745,6 +772,8 @@ int process_core_state_machine(int core_state, struct menu_t *menu, int *op_mode
745772
morse_play(&morse_player, "1600");
746773
else if (*op_mode == DV700D)
747774
morse_play(&morse_player, "700D");
775+
else if (*op_mode == DV700E)
776+
morse_play(&morse_player, "700E");
748777
sfx_play(&sfx_player, sound_click);
749778
}
750779
}
@@ -867,6 +896,7 @@ int process_core_state_machine(int core_state, struct menu_t *menu, int *op_mode
867896
* | |- "ANA" - Analog
868897
* | |- "DV1600" - FreeDV 1600
869898
* | |- "DV700D" - FreeDV 700D
899+
* | |- "DV700E" - FreeDV 700E
870900
* |
871901
* |- "TOT" Timer Out Timer options
872902
* | |- "TIME" - Set timeout time (a sub menu)
@@ -915,7 +945,14 @@ static void menu_default_cb(struct menu_t* const menu, uint32_t event)
915945
break;
916946
case MENU_EVT_PREV:
917947
sfx_play(&sfx_player, sound_click);
918-
menu->current = (menu->current - 1) % item->num_children;
948+
if (menu->current == 0)
949+
{
950+
menu->current = item->num_children - 1;
951+
}
952+
else
953+
{
954+
menu->current = menu->current - 1;
955+
}
919956
announce = 1;
920957
break;
921958
case MENU_EVT_SELECT:
@@ -968,7 +1005,7 @@ static const struct menu_item_t menu_op_mode = {
9681005
.label = "MODE",
9691006
.event_cb = menu_op_mode_cb,
9701007
.children = menu_op_mode_children,
971-
.num_children = 3,
1008+
.num_children = 4,
9721009
};
9731010
/* Children */
9741011
static const struct menu_item_t menu_op_mode_analog = {
@@ -998,10 +1035,20 @@ static const struct menu_item_t menu_op_mode_dv700D = {
9981035
.ui = DV700D,
9991036
},
10001037
};
1038+
static const struct menu_item_t menu_op_mode_dv700E = {
1039+
.label = "700E",
1040+
.event_cb = NULL,
1041+
.children = NULL,
1042+
.num_children = 0,
1043+
.data = {
1044+
.ui = DV700E,
1045+
},
1046+
};
10011047
static struct menu_item_t const* menu_op_mode_children[] = {
10021048
&menu_op_mode_analog,
10031049
&menu_op_mode_dv1600,
10041050
&menu_op_mode_dv700D,
1051+
&menu_op_mode_dv700E,
10051052
};
10061053
/* Callback function */
10071054
static void menu_op_mode_cb(struct menu_t* const menu, uint32_t event)
@@ -1020,6 +1067,9 @@ static void menu_op_mode_cb(struct menu_t* const menu, uint32_t event)
10201067
case DV700D:
10211068
menu->current = 2;
10221069
break;
1070+
case DV700E:
1071+
menu->current = 3;
1072+
break;
10231073
default:
10241074
menu->current = 0;
10251075
}
@@ -1034,7 +1084,14 @@ static void menu_op_mode_cb(struct menu_t* const menu, uint32_t event)
10341084
break;
10351085
case MENU_EVT_PREV:
10361086
sfx_play(&sfx_player, sound_click);
1037-
menu->current = (menu->current - 1) % item->num_children;
1087+
if (menu->current == 0)
1088+
{
1089+
menu->current = item->num_children - 1;
1090+
}
1091+
else
1092+
{
1093+
menu->current = menu->current - 1;
1094+
}
10381095
announce = 1;
10391096
break;
10401097
case MENU_EVT_SELECT:

0 commit comments

Comments
 (0)