to freedv interface added the ability to determine demod sync and bit errors, better...
authordrowe67 <drowe67@01035d8c-6547-0410-b346-abe4f91aad63>
Tue, 5 Aug 2014 04:08:41 +0000 (04:08 +0000)
committerdrowe67 <drowe67@01035d8c-6547-0410-b346-abe4f91aad63>
Tue, 5 Aug 2014 04:08:41 +0000 (04:08 +0000)
git-svn-id: https://svn.code.sf.net/p/freetel/code@1786 01035d8c-6547-0410-b346-abe4f91aad63

codec2-dev/README
codec2-dev/src/freedv_api.c
codec2-dev/src/freedv_api.h
codec2-dev/src/freedv_rx.c
codec2-dev/stm32/Makefile
codec2-dev/stm32/inc/leds_switches.h [deleted file]
codec2-dev/stm32/inc/sm1000_leds_switches.h [new file with mode: 0644]
codec2-dev/stm32/src/leds_switches.c [deleted file]
codec2-dev/stm32/src/sm1000_leds_switches.c [new file with mode: 0644]
codec2-dev/stm32/src/sm1000_leds_switches_ut.c [new file with mode: 0644]
codec2-dev/stm32/src/sm1000_main.c [new file with mode: 0644]

index 0f236e513c69bd8009dedf52e329a0b85fc5204f..97f3c1e635eb8b0c3549291190728af80ff9f6de 100644 (file)
@@ -7,12 +7,15 @@ and below.  For more information please see:
     http://rowetel.com/codec2.html
 
 Also included is a FDMDV modem (README_fdmdv.txt), and an API for
-embeddeding FreeDV in other programs (see example below).  For more
+embedding FreeDV in other programs (see example below).  For more
 information on building Codec 2 see READE.cmake
 
 Quickstart
 ----------
 
+NOTE: Use the "codec2" or "codec2-dev" depending on which repository
+      you are working with
+
 1/ Listen to Codec 2:
    $ cd codec2
    $ mkdir build_linux
@@ -36,11 +39,16 @@ Embedded FreeDV API
 See freedv_api.h and freedv_api.c, and the demo programs freedv_tx &
 freedv_rx.  Quickstart:
 
-  $ ./freedv_tx ../../raw/hts1.raw - | ./freedv_rx - - | play -t raw -r 8000 -s -2 -
+  $ ./freedv_tx ../../raw/hts1.raw - | ./freedv_rx - - | play -t raw -r 8000 -s -2 -q -
 
 Or with a simulated 2 dB SNR channel:
 
-  $ ./freedv_tx ../../raw/hts1.raw - | ./fdmdv_channel - - 2 | ./freedv_rx - - | play -t raw -r 8000 -s -2 
+  $ ./freedv_tx ../../raw/hts1.raw - | ./fdmdv_channel - - 2 | ./freedv_rx - - | play -t raw -r 8000 -s -2 -q -
+
+To log the demod state information and received text msg characters to a text file:
+
+  $ ./freedv_tx ../../raw/hts1.raw - | ./fdmdv_channel - - 2 | ./freedv_rx - - log.txt | play -t raw -r 8000 -s -2 -q -
+  $ cat log.txt
 
 Programs
 --------
@@ -61,25 +69,34 @@ switching phase modelling or LSP quantisation on and off.
 Debugging
 ---------
 
-1/ For dump file support:
+1/ To compile with debug symbols for using gdb:
 
-  $ cd codec2
-  $ CFLAGS=-DDUMP ./configure
-  $ make clean && make
+  $ cd ~/codec2
+  $ rm -Rf build_linux && mkdir build_linux
+  $ cd build_linux
+  $ CFLAGS=-g cmake ..
+  $ make
 
-2/ To use gdb:
+2/ For dump file support:
 
-  $ libtool --mode=execute gdb c2sim
+  $ cd ~/codec2
+  $ rm -Rf build_linux && mkdir build_linux
+  $ CFLAGS=-DDUMP cmake ..
+  $ cd build_linux
+  $ make
 
 Directories
 -----------
 
-  octave    - Octave scripts used for visualising internal signals 
-              during development
-  script    - shell scripts for playing and converting raw files
-  src       - C source code
-  raw       - speech files in raw format (16 bits signed linear 8 kHz)
-  unittest  - unit test source code
-  wav       - speech files in wave file format
-  stm32     - Support for the STM32F4 microcntroller
+  asterisk &  - unmaintained Asterisk support
+  asterisk-11 
+  cmake       - cmake support files
+  octave      - Octave scripts used for visualising internal signals 
+                during development
+  script      - shell scripts for playing and converting raw files
+  src         - C source code for Codec 2, FDMDV modem, FreeDV API
+  raw         - speech files in raw format (16 bits signed linear 8 kHz)
+  stm32       - Support for the STM32F4 microcontroller and SM1000 FreeDV speaker-mic
+  unittest    - unit test source code
+  wav         - speech files in wave file format
 
index 69d2eaa2233bc6fd4fc5ab00f076279a55d8fb03..4083d5979ce469fb97f5ffd6a1792bcef7423dd9 100644 (file)
@@ -9,7 +9,7 @@
       
   TODO:
     [X] speex tx/rx works
-    [ ] txt messages
+    [X] txt messages
     [ ] optional test tx framemode
                                                                        
 \*---------------------------------------------------------------------------*/
@@ -104,6 +104,7 @@ struct freedv *freedv_open(int mode) {
     f->freedv_put_next_rx_char = NULL;
 
     golay23_init();
+    f->total_bit_errors = 0;
 
     return f;
 }
@@ -168,7 +169,6 @@ void freedv_tx(struct freedv *f, short mod_out[], short speech_in[]) {
     // bit/frame to send txt messages
 
     data_flag_index = codec2_get_spare_bit_index(f->codec2);
-    assert(data_flag_index != -1); // not supported for all rates
    
     if (f->nvaricode_bits) {
         f->codec_bits[data_flag_index] = f->tx_varicode_bits[f->varicode_bit_index++];
@@ -266,8 +266,7 @@ int freedv_rx(struct freedv *f, short speech_out[], short demod_in[]) {
     COMP                rx_fdm[FDMDV_MAX_SAMPLES_PER_FRAME];
     int                 bits_per_codec_frame, bytes_per_codec_frame, bits_per_fdmdv_frame;
     int                 reliable_sync_bit, i, j, bit, byte, nin_prev, nout;
-    int                 recd_codeword, codeword1, data_flag_index, n_ascii, valid;
-    struct FDMDV_STATS  fdmdv_stats;
+    int                 recd_codeword, codeword1, data_flag_index, n_ascii;
     short               abit[1];
     char                ascii_out;
 
@@ -282,9 +281,9 @@ int freedv_rx(struct freedv *f, short speech_out[], short demod_in[]) {
 
     nin_prev = f->nin;
     fdmdv_demod(f->fdmdv, f->fdmdv_bits, &reliable_sync_bit, rx_fdm, &f->nin);
-    fdmdv_get_demod_stats(f->fdmdv, &fdmdv_stats);
+    fdmdv_get_demod_stats(f->fdmdv, &f->fdmdv_stats);
     
-    if (fdmdv_stats.sync) {
+    if (f->fdmdv_stats.sync) {
         if (reliable_sync_bit == 0) {
             memcpy(f->rx_bits, f->fdmdv_bits, bits_per_fdmdv_frame*sizeof(int));
             nout = 0;
@@ -307,6 +306,8 @@ int freedv_rx(struct freedv *f, short speech_out[], short demod_in[]) {
                     recd_codeword |= f->rx_bits[i];
                 }
                 codeword1 = golay23_decode(recd_codeword);
+                f->total_bit_errors += golay23_count_errors(recd_codeword, codeword1);
+
                 //codeword1 = recd_codeword;
                 //fprintf(stderr, "received codeword1: 0x%x  decoded codeword1: 0x%x\n", recd_codeword, codeword1);
            
@@ -324,20 +325,16 @@ int freedv_rx(struct freedv *f, short speech_out[], short demod_in[]) {
             // extract txt msg data bit ------------------------------------------------------------
 
             data_flag_index = codec2_get_spare_bit_index(f->codec2);
-            assert(data_flag_index != -1); // not supported for all rates
-
             abit[0] = f->codec_bits[data_flag_index];
 
             n_ascii = varicode_decode(&f->varicode_dec_states, &ascii_out, abit, 1, 1);
-            assert((n_ascii == 0) || (n_asacii == 1));
             if (n_ascii && (f->freedv_put_next_rx_char != NULL)) {
                 (*f->freedv_put_next_rx_char)(f->callback_state, ascii_out);
             }
 
             // reconstruct missing bit we steal for data bit and decode speech
 
-            valid = codec2_rebuild_spare_bit(f->codec2, f->codec_bits);
-            assert(valid != -1);
+            codec2_rebuild_spare_bit(f->codec2, f->codec_bits);
 
             // pack bits, MSB received first
 
@@ -357,7 +354,7 @@ int freedv_rx(struct freedv *f, short speech_out[], short demod_in[]) {
 
             /* squelch if beneath SNR threshold */
 
-            if (fdmdv_stats.snr_est < f->snr_thresh) {
+            if (f->fdmdv_stats.snr_est < f->snr_thresh) {
                 for(i=0; i<FREEDV_NSAMPLES; i++)
                     speech_out[i] = 0;
             }
index a79b1ee78f3e0bc54486a7405cc4d57575b02d5e..065772ed47e0cd2315c9719be9b1bceaae99a53f 100644 (file)
 
 #ifndef __FREEDV__
 
-
-#define FREEDV_MODE_1600    0
-#define FREEDV_NSAMPLES   320
+#define FREEDV_MODE_1600        0
+#define FREEDV_NSAMPLES       320
 
 #include "varicode.h"
+#include "codec2_fdmdv.h"
 
 struct freedv {
     int                  mode;
+
     void                *codec2;
     struct FDMDV        *fdmdv;
+    struct FDMDV_STATS   fdmdv_stats;
+
     unsigned char       *packed_codec_bits;
     int                 *codec_bits;
     int                 *tx_bits;
     int                 *fdmdv_bits;
     int                 *rx_bits;
     int                  tx_sync_bit;
+    int                  total_bit_errors;
+
     float                snr_thresh;
     int                  nin;
+
     struct VARICODE_DEC  varicode_dec_states;
     short                tx_varicode_bits[VARICODE_MAX_BITS];
     int                  nvaricode_bits;
index aab324246814578696a088012c4648c7889f018f..1215b7a39d43e1662afa10a7eacc2e4a0b61df29 100644 (file)
 
 #include "freedv_api.h"
 
+struct my_callback_state {
+    FILE *ftxt;
+};
+
 void my_put_next_rx_char(void *callback_state, char c) {
-    fprintf(stderr, "%c", c);
+    struct my_callback_state* pstate = (struct my_callback_state*)callback_state;
+    if (pstate->ftxt != NULL) {
+        fprintf(pstate->ftxt, "text char received callback: %c\n", c);
+    }
 }
 
 int main(int argc, char *argv[]) {
-    FILE          *fin, *fout;
-    short          speech_out[FREEDV_NSAMPLES];
-    short          demod_in[FREEDV_NSAMPLES];
-    struct freedv *freedv;
-    int            nin, nout;
+    FILE                      *fin, *fout, *ftxt;
+    short                      speech_out[FREEDV_NSAMPLES];
+    short                      demod_in[FREEDV_NSAMPLES];
+    struct freedv             *freedv;
+    int                        nin, nout, frame;
+    struct my_callback_state   my_cb_state;
 
     if (argc < 3) {
-       printf("usage: %s InputModemSpeechFile OutputSpeechawFile\n", argv[0]);
-       printf("e.g    %s hts1a_fdmdv.raw hts1a_out.raw\n", argv[0]);
+       printf("usage: %s InputModemSpeechFile OutputSpeechawFile txtLogFile\n", argv[0]);
+       printf("e.g    %s hts1a_fdmdv.raw hts1a_out.raw txtLogFile\n", argv[0]);
        exit(1);
     }
 
@@ -66,9 +74,20 @@ int main(int argc, char *argv[]) {
        exit(1);
     }
     
+    ftxt = NULL;
+    if ( (argc > 3) && (strcmp(argv[3],"|") != 0) ) {
+        if ((ftxt = fopen(argv[3],"wt")) == NULL ) {
+            fprintf(stderr, "Error opening txt Log File: %s: %s.\n",
+                    argv[3], strerror(errno));
+            exit(1);
+        }
+    }
+    
     freedv = freedv_open(FREEDV_MODE_1600);
     assert(freedv != NULL);
 
+    my_cb_state.ftxt = ftxt;
+    freedv->callback_state = (void*)&my_cb_state;
     freedv->freedv_put_next_rx_char = &my_put_next_rx_char;
 
     /* Note we need to work out how many samples demod needs on each
@@ -82,6 +101,14 @@ int main(int argc, char *argv[]) {
         fwrite(speech_out, sizeof(short), nout, fout);
         nin = freedv_nin(freedv);
 
+        /* log some side info to the txt file */
+        
+        frame++;
+        if (ftxt != NULL) {
+            fprintf(ftxt, "frame: %d  demod sync: %d  demod snr: %3.2f dB  bit errors: %d\n", frame, 
+                    freedv->fdmdv_stats.sync, freedv->fdmdv_stats.snr_est, freedv->total_bit_errors);
+        }
+
        /* if this is in a pipeline, we probably don't want the usual
            buffering to occur */
 
index 89386cc54bae309d186b1e016a108111c29b9ae2..edc5427fbb72b657bc846a39a81cafc0b87d0651 100644 (file)
@@ -64,9 +64,12 @@ $(CODEC2_SRC)/codebookd.c \
 $(CODEC2_SRC)/codebookjvm.c \
 $(CODEC2_SRC)/codebookge.c \
 $(CODEC2_SRC)/dump.c \
-$(CODEC2_SRC)/fdmdv.c
+$(CODEC2_SRC)/fdmdv.c \
+$(CODEC2_SRC)/freedv_api.c \
+$(CODEC2_SRC)/varicode.c \
+$(CODEC2_SRC)/golay23.c
 
-CFLAGS += -D__EMBEDDED__ -DTIMER
+CFLAGS += -D__EMBEDDED__ 
 
 #enable this for dump files to help verify optimisation
 #CFLAGS += -DDUMP
@@ -106,7 +109,7 @@ OBJS = $(SRCS:.c=.o)
 
 ###################################################
 
-all: libstm32f4.a codec2_profile.elf fft_test.elf dac_ut.elf dac_play.elf adc_rec.elf pwm_ut.elf power_ut.elf fdmdv_profile.elf
+all: libstm32f4.a codec2_profile.elf fft_test.elf dac_ut.elf dac_play.elf adc_rec.elf pwm_ut.elf power_ut.elf fdmdv_profile.elf sm1000_leds_switches_ut.elf sm1000.elf
 
 dl/$(PERIPHLIBZIP):
        mkdir -p dl
@@ -134,7 +137,7 @@ src/system_stm32f4xx.c
 CODEC2_PROFILE_SRCS += $(CODEC2_SRCS)
 
 codec2_profile.elf: $(CODEC2_PROFILE_SRCS) 
-       $(CC) $(CFLAGS) $^ -o $@ $(LIBPATHS) $(LIBS)
+       $(CC) $(CFLAGS) -DTIMER $^ -o $@ $(LIBPATHS) $(LIBS)
 
 fft_test.elf: $(FFT_TEST_SRCS)
        $(CC) $(CFLAGS) $^ -o $@ $(LIBPATHS) $(LIBS)
@@ -211,6 +214,31 @@ src/stm32f4_timer.c
 FDMDV_PROFILE_SRCS += $(CODEC2_SRCS)
 
 fdmdv_profile.elf: $(FDMDV_PROFILE_SRCS)
+       $(CC) $(CFLAGS) -DTIMER $^ -o $@ $(LIBPATHS) $(LIBS)
+
+SM1000_LEDS_SWITCHES_UT_SRCS=\
+src/sm1000_leds_switches_ut.c \
+src/sm1000_leds_switches.c \
+src/system_stm32f4xx.c \
+src/startup_stm32f4xx.s \
+src/init.c
+
+sm1000_leds_switches_ut.elf: $(SM1000_LEDS_SWITCHES_UT_SRCS)
+       $(CC) $(CFLAGS) $^ -o $@ $(LIBPATHS) $(LIBS)
+
+SM1000_SRCS=\
+src/sm1000_main.c \
+src/sm1000_leds_switches.c \
+../src/fifo.c \
+src/stm32f4_adc.c \
+src/stm32f4_dac.c \
+src/system_stm32f4xx.c \
+src/startup_stm32f4xx.s \
+src/init.c 
+
+SM1000_SRCS += $(CODEC2_SRCS)
+
+sm1000.elf: $(SM1000_SRCS)
        $(CC) $(CFLAGS) $^ -o $@ $(LIBPATHS) $(LIBS)
 
 clean:
diff --git a/codec2-dev/stm32/inc/leds_switches.h b/codec2-dev/stm32/inc/leds_switches.h
deleted file mode 100644 (file)
index 98ddbdd..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-/*---------------------------------------------------------------------------*\
-
-  FILE........: leds_switches.h
-  AUTHOR......: David Rowe
-  DATE CREATED: 18 July 2014
-
-  Functions for controlling LEDs and reading switches on SM1000.
-
-\*---------------------------------------------------------------------------*/
-
-/*
-  Copyright (C) 2014 David Rowe
-
-  All rights reserved.
-
-  This program is free software; you can redistribute it and/or modify
-  it under the terms of the GNU Lesser General Public License version 2.1, as
-  published by the Free Software Foundation.  This program is
-  distributed in the hope that it will be useful, but WITHOUT ANY
-  WARRANTY; without even the implied warranty of MERCHANTABILITY or
-  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
-  License for more details.
-
-  You should have received a copy of the GNU Lesser General Public License
-  along with this program; if not, see <http://www.gnu.org/licenses/>.
-*/
-
-#ifndef __LEDS_SWITCHES__
-#define __LEDS_SWITCHES__
-
-void leds_switches_init(void);
-void led_pwr(int state);
-void led_ptt(int state);
-void led_rt(int state);
-void led_err(int state);
-
-#endif
diff --git a/codec2-dev/stm32/inc/sm1000_leds_switches.h b/codec2-dev/stm32/inc/sm1000_leds_switches.h
new file mode 100644 (file)
index 0000000..b6207d0
--- /dev/null
@@ -0,0 +1,42 @@
+/*---------------------------------------------------------------------------*\
+
+  FILE........: sm1000_leds_switches.h
+  AUTHOR......: David Rowe
+  DATE CREATED: 18 July 2014
+
+  Functions for controlling LEDs and reading switches on SM1000.
+
+\*---------------------------------------------------------------------------*/
+
+/*
+  Copyright (C) 2014 David Rowe
+
+  All rights reserved.
+
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of the GNU Lesser General Public License version 2.1, as
+  published by the Free Software Foundation.  This program is
+  distributed in the hope that it will be useful, but WITHOUT ANY
+  WARRANTY; without even the implied warranty of MERCHANTABILITY or
+  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+  License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with this program; if not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef __LEDS_SWITCHES__
+#define __LEDS_SWITCHES__
+
+void sm1000_leds_switches_init(void);
+
+void led_pwr(int state);
+void led_ptt(int state);
+void led_rt(int state);
+void led_err(int state);
+
+int switch_ptt(void);
+int switch_select(void);
+int switch_back(void);
+
+#endif
diff --git a/codec2-dev/stm32/src/leds_switches.c b/codec2-dev/stm32/src/leds_switches.c
deleted file mode 100644 (file)
index 3985b83..0000000
+++ /dev/null
@@ -1,72 +0,0 @@
-/*---------------------------------------------------------------------------*\
-
-  FILE........: leds_switches.c
-  AUTHOR......: David Rowe
-  DATE CREATED: 18 July 2014
-
-  Functions for controlling LEDs and reading switches on SM1000.
-
-\*---------------------------------------------------------------------------*/
-
-/*
-  Copyright (C) 2014 David Rowe
-
-  All rights reserved.
-
-  This program is free software; you can redistribute it and/or modify
-  it under the terms of the GNU Lesser General Public License version 2.1, as
-  published by the Free Software Foundation.  This program is
-  distributed in the hope that it will be useful, but WITHOUT ANY
-  WARRANTY; without even the implied warranty of MERCHANTABILITY or
-  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
-  License for more details.
-
-  You should have received a copy of the GNU Lesser General Public License
-  along with this program; if not, see <http://www.gnu.org/licenses/>.
-*/
-
-#define LED_PWR 12
-#define LED_PTT 13
-#define LED_RT  14
-#define LED_ERR 15
-
-#include "stm32f4xx_conf.h"
-#include "stm32f4xx.h"
-#include "leds_switches.h"
-
-void leds_switches_init(void) {
-    RCC->AHB1ENR |= RCC_AHB1ENR_GPIODEN; // enable the clock to GPIOD 
-
-    // Set pins as general purpose IOs
-
-    GPIOD->MODER = (2 << LED_PWR) | (2 << LED_PTT) | (2 << LED_RT) | (2 << LED_ERR);           
-}
-
-void led_pwr(int state) {
-    if (state)
-        GPIOD->ODR = (1 << LED_PWR);
-    else
-        GPIOD->ODR &= ~(1 << LED_PWR);
-}
-
-void led_ptt(int state) {
-    if (state)
-        GPIOD->ODR = (1 << LED_PTT);
-    else
-        GPIOD->ODR &= ~(1 << LED_PTT);
-}
-
-void led_rt(int state) {
-    if (state)
-        GPIOD->ODR = (1 << LED_RT);
-    else
-        GPIOD->ODR &= ~(1 << LED_RT);
-}
-
-void led_err(int state) {
-    if (state)
-        GPIOD->ODR = (1 << LED_ERR);
-    else
-        GPIOD->ODR &= ~(1 << LED_ERR);
-}
-
diff --git a/codec2-dev/stm32/src/sm1000_leds_switches.c b/codec2-dev/stm32/src/sm1000_leds_switches.c
new file mode 100644 (file)
index 0000000..b37a7a9
--- /dev/null
@@ -0,0 +1,101 @@
+/*---------------------------------------------------------------------------*\
+
+  FILE........: sm1000_leds_switches.c
+  AUTHOR......: David Rowe
+  DATE CREATED: 18 July 2014
+
+  Functions for controlling LEDs and reading switches on the SM1000.
+
+\*---------------------------------------------------------------------------*/
+
+/*
+  Copyright (C) 2014 David Rowe
+
+  All rights reserved.
+
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of the GNU Lesser General Public License version 2.1, as
+  published by the Free Software Foundation.  This program is
+  distributed in the hope that it will be useful, but WITHOUT ANY
+  WARRANTY; without even the implied warranty of MERCHANTABILITY or
+  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+  License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with this program; if not, see <http://www.gnu.org/licenses/>.
+*/
+
+#define LED_PWR       12
+#define LED_PTT       13
+#define LED_RT        14
+#define LED_ERR       15
+#define SWITCH_PTT     7
+#define SWITCH_SELECT  0
+#define SWITCH_BACK    1
+
+#include <stm32f4xx.h>
+#include <stm32f4xx_gpio.h>
+#include "sm1000_leds_switches.h"
+
+void sm1000_leds_switches_init(void) {
+    GPIO_InitTypeDef GPIO_InitStruct;
+
+    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);
+
+    /* output pins */
+
+    GPIO_InitStruct.GPIO_Pin = LED_PWR | LED_PTT | LED_RT | LED_ERR;
+    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT;                 
+    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;     
+    GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;         
+    GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;      
+    GPIO_Init(GPIOD, &GPIO_InitStruct);                
+
+    /* input pins */
+
+    GPIO_InitStruct.GPIO_Pin = SWITCH_PTT | SWITCH_SELECT | SWITCH_BACK;
+    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN;          
+    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; 
+    GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL; /* we have our own external pull ups */      
+    GPIO_Init(GPIOD, &GPIO_InitStruct);                
+ }
+
+void led_pwr(int state) {
+    if (state)
+        GPIOD->ODR = (1 << LED_PWR);
+    else
+        GPIOD->ODR &= ~(1 << LED_PWR);
+}
+
+void led_ptt(int state) {
+    if (state)
+        GPIOD->ODR = (1 << LED_PTT);
+    else
+        GPIOD->ODR &= ~(1 << LED_PTT);
+}
+
+void led_rt(int state) {
+    if (state)
+        GPIOD->ODR = (1 << LED_RT);
+    else
+        GPIOD->ODR &= ~(1 << LED_RT);
+}
+
+void led_err(int state) {
+    if (state)
+        GPIOD->ODR = (1 << LED_ERR);
+    else
+        GPIOD->ODR &= ~(1 << LED_ERR);
+}
+
+int switch_ptt(void) {
+    return GPIOA->IDR & SWITCH_PTT;
+}
+
+int switch_select(void) {
+    return GPIOA->IDR & SWITCH_SELECT;
+}
+
+int switch_back(void) {
+    return GPIOA->IDR & SWITCH_BACK;
+}
diff --git a/codec2-dev/stm32/src/sm1000_leds_switches_ut.c b/codec2-dev/stm32/src/sm1000_leds_switches_ut.c
new file mode 100644 (file)
index 0000000..32813ff
--- /dev/null
@@ -0,0 +1,40 @@
+/*---------------------------------------------------------------------------*\\r
+\r
+  FILE........: sm1000_leds_switches_ut.c\r
+  AUTHOR......: David Rowe\r
+  DATE CREATED: August 5 2014\r
+\r
+  Unit Test program for the SM1000 switches and LEDs driver.\r
+\r
+\*---------------------------------------------------------------------------*/\r
+\r
+/*\r
+  Copyright (C) 2014 David Rowe\r
+\r
+  All rights reserved.\r
+\r
+  This program is free software; you can redistribute it and/or modify\r
+  it under the terms of the GNU Lesser General Public License version 2.1, as\r
+  published by the Free Software Foundation.  This program is\r
+  distributed in the hope that it will be useful, but WITHOUT ANY\r
+  WARRANTY; without even the implied warranty of MERCHANTABILITY or\r
+  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public\r
+  License for more details.\r
+\r
+  You should have received a copy of the GNU Lesser General Public License\r
+  along with this program; if not, see <http://www.gnu.org/licenses/>.\r
+*/\r
+\r
+#include <assert.h>\r
+#include "sm1000_leds_switches.h"\r
+\r
+int main(void) {\r
+    sm1000_leds_switches_init();\r
+    while(1) {\r
+        led_pwr(switch_select());\r
+        led_ptt(switch_ptt());\r
+        led_rt(switch_back());\r
+        led_err(!switch_back());\r
+    }\r
+}\r
+\r
diff --git a/codec2-dev/stm32/src/sm1000_main.c b/codec2-dev/stm32/src/sm1000_main.c
new file mode 100644 (file)
index 0000000..90c926c
--- /dev/null
@@ -0,0 +1,93 @@
+/*---------------------------------------------------------------------------*\\r
+\r
+  FILE........: sm1000_main.c\r
+  AUTHOR......: David Rowe\r
+  DATE CREATED: August 5 2014\r
+\r
+  Main program for SM1000.\r
+\r
+\*---------------------------------------------------------------------------*/\r
+\r
+/*\r
+  Copyright (C) 2014 David Rowe\r
+\r
+  All rights reserved.\r
+\r
+  This program is free software; you can redistribute it and/or modify\r
+  it under the terms of the GNU Lesser General Public License version 2.1, as\r
+  published by the Free Software Foundation.  This program is\r
+  distributed in the hope that it will be useful, but WITHOUT ANY\r
+  WARRANTY; without even the implied warranty of MERCHANTABILITY or\r
+  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public\r
+  License for more details.\r
+\r
+  You should have received a copy of the GNU Lesser General Public License\r
+  along with this program; if not, see <http://www.gnu.org/licenses/>.\r
+*/\r
+\r
+#include "stm32f4_adc.h"\r
+#include "stm32f4_dac.h"\r
+#include "freedv_api.h"\r
+#include "sm1000_leds_switches.h"\r
+\r
+int main(void) {\r
+    struct freedv *f;\r
+    short  buf[FREEDV_NSAMPLES];\r
+    int    nin, nout;\r
+\r
+    /* init all the drivers for various peripherals */\r
+\r
+    sm1000_leds_switches_init();\r
+    dac_open();\r
+    adc_open();\r
+    f = freedv_open(FREEDV_MODE_1600);\r
+\r
+    /* LEDs into a known state */\r
+\r
+    led_pwr(1); led_ptt(0); led_rt(0); led_err(0);\r
+\r
+    /* \r
+       TODO:\r
+       [ ] UT analog interfaces from file IO\r
+       [ ] UTs for simultaneous tx & rx on analog interfaces\r
+       [ ] measure CPU load of various parts with a blinky\r
+       [ ] detect program assert type errors with a blinky\r
+       [ ] timer tick function to measure 10ms-ish type times\r
+       [ ] switch debouncing?\r
+       [ ] light led with bit errors\r
+    */\r
+\r
+    while(1) {\r
+\r
+        if(switch_ptt()) {\r
+\r
+            /* Transmit -------------------------------------------------------------------------*/\r
+\r
+            /* ADC2 is the SM1000 microphone, DAC1 is the modulator signal we send to radio tx */\r
+\r
+            if (adc2_read(buf, FREEDV_NSAMPLES) == FREEDV_NSAMPLES) {\r
+                freedv_tx(f, buf, buf);\r
+                dac1_write(buf, FREEDV_NSAMPLES);\r
+                led_ptt(1); led_rt(0); led_err(0);\r
+            }\r
+        }\r
+        else {\r
+            \r
+            /* Receive --------------------------------------------------------------------------*/\r
+\r
+            /* ADC1 is the demod in signal from the radio rx, DAC2 is the SM1000 speaker */\r
+\r
+            nin = freedv_nin(f);\r
+            f->total_bit_errors = 0;\r
+            \r
+            if (adc1_read(buf, nin) == nin) {\r
+                nout = freedv_rx(f, buf, buf);\r
+                dac2_write(buf, nout);\r
+                led_ptt(0); led_rt(f->fdmdv_stats.sync); led_err(f->total_bit_errors);\r
+            }\r
+\r
+        }\r
+        \r
+    } /* while(1) ... */\r
+}\r
+\r