###################################################
-all: libstm32f4.a codec2_profile.elf fft_test.elf dac_ut.elf dac_play.elf adc_rec.elf pwm_ut.elf fdmdv_profile.elf sm1000_leds_switches_ut.elf sm1000.elf adcdac_ut.elf freedv_tx_profile.elf freedv_rx_profile.elf adc_sd.elf usb_vcp_ut.elf tuner_ut.elf fast_dac_ut.elf
+all: libstm32f4.a codec2_profile.elf fft_test.elf dac_ut.elf dac_play.elf adc_rec.elf pwm_ut.elf fdmdv_profile.elf sm1000_leds_switches_ut.elf sm1000.elf adcdac_ut.elf freedv_tx_profile.elf freedv_rx_profile.elf adc_sd.elf usb_vcp_ut.elf tuner_ut.elf fast_dac_ut.elf adc_sfdr_ut.elf
dl/$(PERIPHLIBZIP):
mkdir -p dl
$(CC) $(CFLAGS) -O3 $^ -o $@ $(LIBPATHS) $(LIBS)
$(OBJCOPY) -O binary tuner_ut.elf tuner_ut.bin
+# ---------------------------------------------------------------------------
+
+ADC_SFDR_UT_SRCS=\
+src/adc_sfdr_ut.c \
+gdb_stdio.c \
+../src/fifo.c \
+src/sm1000_leds_switches.c \
+src/debugblinky.c \
+src/system_stm32f4xx.c \
+src/startup_stm32f4xx.s \
+src/init.c \
+
+# this needs to be compiled without the optimiser or ugly things happen
+# would be nice to work out why as ISRs need to run fast
+
+src/stm32f4_adc_tuner.o: src/stm32f4_adc_tuner.c
+ $(CC) $(CFLAGS) $^ -c -o $@
+
+adc_sfdr_ut.elf: $(TUNER_UT_SRCS) src/stm32f4_adc_tuner.o
+ $(CC) $(CFLAGS) -O3 $^ -o $@ $(LIBPATHS) $(LIBS)
+ $(OBJCOPY) -O binary adc_sfdr_ut.elf adc_sfdr_ut.bin
+
# ---------------------------------------------------------------------------------
clean:
README.txt
codec2 support for the stm32f4
-David Rowe May 2013
+David Rowe August 2015
-Introduction
-------------
+Quickstart
+==========
-The Makefile generates several unit tests, stm32f4_codec2.elf is the
-most important. It's is equivalent to c2demo.c and runs the encoder
-and decoder on raw speech files. It also gathers and prints profiling
-information and can dump the codec states to compare changes.
+The Makefile generates several programs used in Codec 2 development on
+the STM32F4, including sm1000.bin, the firmware for the SM1000.
+
+1. Find stm32f4_dsp_stdperiph_lib.zip on the InterWebs and place in in
+ dl. (st.com was down when I last looked for it)
+
+2. Install the toolchain, on Ubuntu 14 this is:
+
+ $ sudo apt-get install gcc-arm-none-eabi
+
+3. $ make (and cross your fingers)
+
+You may need to mess about with the Makefile to get it to work,
+e.g. BINPATH, PERIPHLIBURL. A better build system is hopefully on
+it's way. Contact me if you can help.
+
+Not quite so Quickstart
+=======================
+
+Note: This section needs some editing. It deals with the running the
+semi-hosting used for development system.
gdb_stdio system
----------------
void adc_open(int fifo_sz);
int adc1_read(short buf[], int n); /* ADC1 Pin PA1 */
+void adc_set_tuner_en(short flag); /* disable tuner to get raw ADC samples written to fifo */
#endif
--- /dev/null
+/*---------------------------------------------------------------------------*\\r
+\r
+ FILE........: adc_sfdr_ut.c\r
+ AUTHOR......: David Rowe\r
+ DATE CREATED: August 2015\r
+\r
+ Unit test for high speed ADC SFDR testing. Samples ADC1 from in PA1 at \r
+ Fs=2 MHz and write raw samples to a file, in discontinuus blocks of \r
+ ADC_TUNER_BUF_SZ/2 samples. The blocks are discontinuous as we \r
+ don'thave the bandwitdh back to the host to support continuous sampling.\r
+\r
+ To process the blocks, fread() ADC_TUNER_BUF_SZ/2 samples at a time,\r
+ abs(fft) and sum results from next block.\r
+\r
+\*---------------------------------------------------------------------------*/\r
+\r
+/*\r
+ Copyright (C) 2015 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 <stdlib.h>\r
+#include "gdb_stdio.h"\r
+#include "stm32f4_dac.h"\r
+#include "stm32f4_adc_tuner.h"\r
+#include "iir_tuner.h"\r
+#include "sm1000_leds_switches.h"\r
+#include "../src/codec2_fm.h"\r
+#include "stm32f4xx.h"\r
+\r
+#define REC_TIME_SECS 1\r
+#define FS 2E6\r
+#define N (ADC_TUNER_BUF_SZ/2)\r
+\r
+extern int adc_overflow1;\r
+\r
+int main(void) {\r
+ short buf[N];\r
+ int bufs, i;\r
+ FILE *fadc;\r
+\r
+ ftuner = fopen("adc.raw", "wb");\r
+ if (ftuner == NULL) {\r
+ printf("Error opening output file: adc.raw\n\nTerminating....\n");\r
+ exit(1);\r
+ }\r
+ bufs = FS*REC_TIME_SECS/N;\r
+ fifo_sz = ADC_TUNER_N;\r
+ printf("Starting! bufs: %d %d\n", bufs, fifo_sz);\r
+ \r
+ adc_open(fifo_sz);\r
+ adc_set_tuner_en(0); /* dump raw samples, no tuner */\r
+\r
+ sm1000_leds_switches_init();\r
+\r
+ for (i=0; i<bufs; i++) {\r
+ while(adc1_read(buf, N) == -1);\r
+\r
+ /* most of the time will be spent here */\r
+\r
+ GPIOE->ODR |= (1 << 3);\r
+ fwrite(buf, sizeof(short), N, fadc);\r
+ GPIOE->ODR &= ~(1 << 3);\r
+ }\r
+ fclose(fadc);\r
+\r
+ printf("Finsihed!\n");\r
+}\r
+\r
unsigned short adc_buf[ADC_TUNER_BUF_SZ];
int adc_overflow1;
int half,full;
+static short tuner_en = 1;
#define ADCx_DR_ADDRESS ((uint32_t)0x4001204C)
#define DMA_CHANNELx DMA_Channel_0
}
+void adc_set_tuner_en(short flag)
+{
+ tuner_en = flag;
+}
+
static void tim2_config(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
if(DMA_GetITStatus(DMA2_Stream0, DMA_IT_HTIF0) != RESET) {
half++;
- iir_tuner(dec_buf, adc_buf);
+ if (tuner_en) {
+ iir_tuner(dec_buf, adc_buf);
- /* write first half to fifo */
+ /* write first half to fifo */
- if (fifo_write(adc1_fifo, (short*)dec_buf, ADC_TUNER_N) == -1) {
- adc_overflow1++;
+ if (fifo_write(adc1_fifo, (short*)dec_buf, ADC_TUNER_N) == -1) {
+ adc_overflow1++;
+ }
}
-
+ else
+ fifo_write(adc1_fifo, (short*)adc_buf, ADC_TUNER_BUF_SZ/2);
+
/* Clear DMA Stream Transfer Complete interrupt pending bit */
DMA_ClearITPendingBit(DMA2_Stream0, DMA_IT_HTIF0);
if(DMA_GetITStatus(DMA2_Stream0, DMA_IT_TCIF0) != RESET) {
full++;
- iir_tuner(dec_buf, &adc_buf[ADC_TUNER_BUF_SZ/2]);
+ if (tuner_en) {
+ iir_tuner(dec_buf, &adc_buf[ADC_TUNER_BUF_SZ/2]);
- /* write second half to fifo */
+ /* write second half to fifo */
- if (fifo_write(adc1_fifo, (short*)dec_buf, ADC_TUNER_N) == -1) {
- adc_overflow1++;
+ if (fifo_write(adc1_fifo, (short*)dec_buf, ADC_TUNER_N) == -1) {
+ adc_overflow1++;
+ }
}
-
+ else
+ fifo_write(adc1_fifo, (short*)&adc_buf[ADC_TUNER_BUF_SZ/2], ADC_TUNER_BUF_SZ/2);
+
/* Clear DMA Stream Transfer Complete interrupt pending bit */
DMA_ClearITPendingBit(DMA2_Stream0, DMA_IT_TCIF0);