samples/96b_argonkey: divided test into sensor and microphone

We have now two code samples available for ArgonKey board:

    1. sensors sample, fetching data from accel/gyro/mag,
       barometer, humidity and proximity sensors

    2. microphone sample, acquiring 5s audio @16KHz from the
       on-board microphone.

Signed-off-by: Armando Visconti <armando.visconti@st.com>
This commit is contained in:
Armando Visconti 2018-11-13 10:17:45 +01:00 committed by Maureen Helm
parent c4b3583afd
commit 69a3566868
10 changed files with 390 additions and 16 deletions

View file

@ -0,0 +1,10 @@
# Copyright (c) 2018 STMicroelectronics
#
# SPDX-License-Identifier: Apache-2.0
#
cmake_minimum_required(VERSION 3.13.1)
include($ENV{ZEPHYR_BASE}/cmake/app/boilerplate.cmake NO_POLICY_SCOPE)
project(NONE)
target_sources(app PRIVATE src/main.c)

View file

@ -0,0 +1,129 @@
.. _ArgonKey_Microphone:
ArgonKey Board Microphone
#########################
Overview
********
This sample provides an example of how to acquire audio through
the on-board MP34DT05 microphone. The microphone generates a PDM
stream which is acquired through I2S. The PDM stream is then
converted to PCM using the OpenPDMFilter library, which is available
in source code in this sample.
Requirements
************
This sample requires the ArgonKey board plus a USB to TTL 1V8 serial
cable to get the output audio stream. The board can be powered
in either one of the following two ways:
- mezzanine mode, plugging the ArgonKey to HiKey board thru its 96Board
low-speed connector
- standalone mode, supplying 5V directly on P1 connector
References
**********
- :ref:`96b_argonkey`
Building and Running
********************
.. zephyr-app-commands::
:zephyr-app: samples/boards/96b_argonkey/microphone
:host-os: unix
:board: 96b_argonkey
:goals: run
:compact:
Sample Output
=============
The example acquires 5s of audio and prints out the PCM stream on COM port.
A USB to TTL 1V8 serial cable may be attached to the low speed connector on
the back of the board on P3.5 (TX) and P3.7 (RX).
As soon as the acquisition starts the green LED glows. At the end of the
acquisition both the green and red LEDs go on and the PCM stream is sent
on COM port. When the output is completed the green LED goes off and the red
LED stays on. The process can be reiterated by pressing the RST button.
- audio acquisition starts: GRN on - RED off
- audio acquisition ends: GRN on - RED on
- audio output ends: GRN off - RED on
The characteristics of the PCM audio are hardcoded in the example:
- 16KHz sample rate
- 16 bits per sample
- 1 channel (mono), as only 1 microphone is available
Five seconds of acquisition at a 16KHz sampling rate yields 80,000 16-bit samples.
The microphone PDM requested clock should lead the MP34DT05 driver to select an
oversampling/decimation factor equal to 128, resulting in a 2.048MHz bit clock.
See pcm and pdm configuration in file :file:`samples/boards/96b_argonkey/microphone/src/main.c`.
.. note:: It is possible to change the AUDIO_FREQ to 32000 acquiring only 2500 ms. In this
case the oversampling/decimation factor will be 64.
At the end of the acquisition the PCM data will be printed on the terminal
emulator in either binary or ASCII format. The output is controlled by
following macro, off by default, in :file:`samples/boards/96b_argonkey/microphone/src/main.c`:
* :c:macro:`PCM_OUTPUT_IN_ASCII`
Binary PCM Output
-----------------
The ttyUSB0 port must be configured in raw mode to avoid having
characters 'cooked' out.
.. code-block:: console
stty -F /dev/ttyUSB0 115200 raw
cat /dev/ttyUSB0 > /tmp/sound.raw
.. note:: In case the character 0x0a is interpreted as NL and an 0x0d (CR) is added,
you may need to remove it::
dos2unix -f /tmp/sound.raw
ASCII PCM Output
----------------
It is also possible to recompile and to have PCM output in ASCII, which needs
to be converted to binary later on. The output format is the following:
.. code-block:: console
ArgonKey test!!
-- start
0xfbe0,
0xfbf0,
0xfc0c,
0xfc24,
0xfc3c,
0xfc4c,
0xfc68,
0xfc48,
[...]
0xfb98,
0xfb98,
0xfbb8,
0xfbac,
0xfbc4,
0xfbe8,
0xfbf4,
-- end
Play PCM Audio
--------------
Now that we have a binary PCM file (say sound.raw), you can use,
for example, the audicity open source editor/player to load and play it.
Use the 'Import->Raw Data' menu to load the sound.raw file as
signed 16 bit PCM, Little Endian, mono format @16KHz.

View file

@ -0,0 +1,17 @@
CONFIG_PRINTK=y
CONFIG_I2C=y
CONFIG_I2S=y
CONFIG_GPIO=y
CONFIG_LED=y
CONFIG_LP3943=y
CONFIG_AUDIO=y
CONFIG_AUDIO_DMIC=y
CONFIG_AUDIO_MPXXDTYY=y
# When on-board microphone is used the DMA must run w/o things
# that could slow it down. So DMA logging must be completely
# disabled and DMA interrupts must run at maximum priority.
CONFIG_DMA=y
CONFIG_DMA_LOG_LEVEL_OFF=y
CONFIG_DMA_0_IRQ_PRI=0

View file

@ -0,0 +1,9 @@
sample:
description: ArgonKey sensor testing
name: ArgonKey test
tests:
test:
harness: sensor
platform_whitelist: 96b_argonkey
tags: sensors
depends_on: i2s gpio

View file

@ -0,0 +1,189 @@
/*
* Copyright (c) 2018 STMicroelectronics
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <string.h>
#include <zephyr.h>
#include <misc/printk.h>
#include <gpio.h>
#include <led.h>
#include <audio/dmic.h>
/* uncomment if you want PCM output in ascii */
/*#define PCM_OUTPUT_IN_ASCII 1 */
#define AUDIO_FREQ 16000
#define CHAN_SIZE 16
#define PCM_BLK_SIZE_MS ((AUDIO_FREQ/1000) * sizeof(s16_t))
#define NUM_MS 5000
K_MEM_SLAB_DEFINE(rx_mem_slab, PCM_BLK_SIZE_MS, NUM_MS, 1);
struct pcm_stream_cfg mic_streams = {
.pcm_rate = AUDIO_FREQ,
.pcm_width = CHAN_SIZE,
.block_size = PCM_BLK_SIZE_MS,
.mem_slab = &rx_mem_slab,
};
struct dmic_cfg cfg = {
.io = {
/* requesting a pdm freq around 2MHz */
.min_pdm_clk_freq = 1800000,
.max_pdm_clk_freq = 2500000,
},
.streams = &mic_streams,
.channel = {
.req_num_chan = 1,
},
};
#define NUM_LEDS 12
#define DELAY_TIME K_MSEC(25)
void signal_sampling_started(void)
{
static struct device *led0, *led1;
led0 = device_get_binding(LED0_GPIO_CONTROLLER);
gpio_pin_configure(led0, LED0_GPIO_PIN, GPIO_DIR_OUT);
gpio_pin_write(led0, LED0_GPIO_PIN, 1);
led1 = device_get_binding(LED1_GPIO_CONTROLLER);
gpio_pin_configure(led1, LED1_GPIO_PIN, GPIO_DIR_OUT);
gpio_pin_write(led1, LED1_GPIO_PIN, 0);
}
void signal_sampling_stopped(void)
{
static struct device *led0, *led1;
led0 = device_get_binding(LED0_GPIO_CONTROLLER);
gpio_pin_configure(led0, LED0_GPIO_PIN, GPIO_DIR_OUT);
gpio_pin_write(led0, LED0_GPIO_PIN, 1);
led1 = device_get_binding(LED1_GPIO_CONTROLLER);
gpio_pin_configure(led1, LED1_GPIO_PIN, GPIO_DIR_OUT);
gpio_pin_write(led1, LED1_GPIO_PIN, 1);
}
void signal_print_stopped(void)
{
static struct device *led0, *led1;
led0 = device_get_binding(LED0_GPIO_CONTROLLER);
gpio_pin_configure(led0, LED0_GPIO_PIN, GPIO_DIR_OUT);
gpio_pin_write(led0, LED0_GPIO_PIN, 0);
led1 = device_get_binding(LED1_GPIO_CONTROLLER);
gpio_pin_configure(led1, LED1_GPIO_PIN, GPIO_DIR_OUT);
gpio_pin_write(led1, LED1_GPIO_PIN, 1);
}
void *rx_block[NUM_MS];
size_t rx_size = PCM_BLK_SIZE_MS;
void main(void)
{
int i;
u32_t ms;
#ifdef CONFIG_LP3943
static struct device *ledc;
ledc = device_get_binding(CONFIG_LP3943_DEV_NAME);
if (!ledc) {
printk("Could not get pointer to %s sensor\n",
CONFIG_LP3943_DEV_NAME);
return;
}
/* turn all leds on */
for (i = 0; i < NUM_LEDS; i++) {
led_on(ledc, i);
k_sleep(DELAY_TIME);
}
/* turn all leds off */
for (i = 0; i < NUM_LEDS; i++) {
led_off(ledc, i);
k_sleep(DELAY_TIME);
}
#endif
printk("ArgonKey test!!\n");
int ret;
struct device *mic_dev = device_get_binding(DT_MPXXDTYY_DEV_NAME);
if (!mic_dev) {
printk("Could not get pointer to %s device\n",
DT_MPXXDTYY_DEV_NAME);
return;
}
ret = dmic_configure(mic_dev, &cfg);
if (ret < 0) {
printk("microphone configuration error\n");
return;
}
ret = dmic_trigger(mic_dev, DMIC_TRIGGER_START);
if (ret < 0) {
printk("microphone start trigger error\n");
return;
}
signal_sampling_started();
/* Acquire microphone audio */
for (ms = 0; ms < NUM_MS; ms++) {
dmic_read(mic_dev, 0, &rx_block[ms], &rx_size, 2000);
if (ret < 0) {
printk("microphone audio read error\n");
return;
}
}
signal_sampling_stopped();
/* print PCM stream */
#ifdef PCM_OUTPUT_IN_ASCII
printk("-- start\n");
int j;
for (i = 0; i < NUM_MS; i++) {
u16_t *pcm_out = rx_block[i];
for (j = 0; j < rx_size/2; j++) {
printk("0x%04x,\n", pcm_out[j]);
}
}
printk("-- end\n");
#else
unsigned char pcm_l, pcm_h;
int j;
for (i = 0; i < NUM_MS; i++) {
u16_t *pcm_out = rx_block[i];
for (j = 0; j < rx_size/2; j++) {
pcm_l = (char)(pcm_out[j] & 0xFF);
pcm_h = (char)((pcm_out[j] >> 8) & 0xFF);
_impl_k_str_out(&pcm_l, 1);
_impl_k_str_out(&pcm_h, 1);
}
}
#endif
signal_print_stopped();
}

View file

@ -1,8 +1,8 @@
cmake_minimum_required(VERSION 3.13.1)
# Copyright (c) 2018 STMicroelectronics # Copyright (c) 2018 STMicroelectronics
# #
# SPDX-License-Identifier: Apache-2.0 # SPDX-License-Identifier: Apache-2.0
# #
cmake_minimum_required(VERSION 3.13.1)
include($ENV{ZEPHYR_BASE}/cmake/app/boilerplate.cmake NO_POLICY_SCOPE) include($ENV{ZEPHYR_BASE}/cmake/app/boilerplate.cmake NO_POLICY_SCOPE)
project(96b_argonkey) project(96b_argonkey)

View file

@ -1,7 +1,7 @@
.. _ArgonKey: .. _ArgonKey_Sensors:
ArgonKey sensor board ArgonKey Board Sensors
##################### ######################
Overview Overview
******** ********
@ -12,15 +12,21 @@ It makes use of both the trigger and poll methods.
Requirements Requirements
************ ************
This sample just requires the ArgonKey board. This sample just requires the ArgonKey board. The board can be powered
in either one of the following two ways:
- mezzanine mode, plugging the ArgonKey to HiKey board thru its 96Board
low-speed connector
- standalone mode, supplying 5V directly on P1 connector
The user may select or unselect the sensors from The user may select or unselect the sensors from
:file:`samples/boards/96b_argonkey/prj.conf`. :file:`samples/boards/96b_argonkey/sensors/prj.conf`.
Please note that all sensor related code is conditionally compiled Please note that all sensor related code is conditionally compiled
using the `#ifdef` directive, so this sample is supposed to always using the `#ifdef` directive, so this sample is supposed to always
build correctly. Example: build correctly. Example:
.. code-block:: c .. code-block:: c
#ifdef CONFIG_HTS221 #ifdef CONFIG_HTS221
struct device *hum_dev = device_get_binding("HTS221"); struct device *hum_dev = device_get_binding("HTS221");
@ -39,8 +45,8 @@ References
Building and Running Building and Running
******************** ********************
.. zephyr-app-commands:: .. zephyr-app-commands::
:zephyr-app: samples/boards/96b_argonkey :zephyr-app: samples/boards/96b_argonkey/sensors
:host-os: unix :host-os: unix
:board: 96b_argonkey :board: 96b_argonkey
:goals: run :goals: run
@ -49,27 +55,40 @@ Building and Running
Sample Output Sample Output
============= =============
A USB to TTL 1V8 serial cable may be attached to the low speed connector on
the back of the board on P3.5 (TX) and P3.7 (RX). User may use a simple
terminal emulator, such as minicom, to capture the output.
.. code-block:: console .. code-block:: console
temp: 24.78 C; press: 101.448535 proxy: 1 ;
humidity: 43.000000 distance: 0 m -- 09 cm;
accel (4.121000 -6.859000 -5.384000) m/s2 temp: 30.35 C; press: 97.466259
gyro (-0.008000 0.270000 0.161000) dps humidity: 43.500000
magn (0.021000 -0.552000 0.271500) gauss accel (0.004000 -0.540000 9.757000) m/s2
- (6) (trig_cnt: 254) gyro (0.065000 -0.029000 -0.001000) dps
magn (0.049500 0.208500 -0.544500) gauss
- (6) (trig_cnt: 1878)
<repeats endlessly every 2s> <repeats endlessly every 2s>
In this example the output is generated polling the sensor every 2 seconds. In this example the output is generated polling the sensor every 2 seconds.
Sensor data is printed in the following order (no data is printed for Sensor data is printed in the following order (no data is printed for
sensors that are not enabled): sensors that are not enabled):
#. *VL53L0x* proximity
#. *LPS22HB* baro/temp #. *LPS22HB* baro/temp
#. *HTS221* humidity #. *HTS221* humidity
#. *LSM6DSL* accel #. *LSM6DSL* accel
#. *LSM6DSL* gyro #. *LSM6DSL* gyro
#. *LIS2MDL* magnetometer (attached to *LSM6DSL*) #. *LIS2MDL* magnetometer (attached to *LSM6DSL*)
The proximity sensor displays two lines:
- a flag (proxy) that goes on when the distance is below 10cm
- the absolute distance from the obstacle
The last line displays a counter of how many trigger interrupts The last line displays a counter of how many trigger interrupts
has been received. It is possible to display the sensor data has been received. It is possible to display the sensor data
read for each trigger by enabling the **ARGONKEY_TEST_LOG** macro. read for each trigger by enabling the **ARGONKEY_TEST_LOG** macro.

View file

@ -278,7 +278,8 @@ void main(void)
sensor_channel_get(tof_dev, SENSOR_CHAN_PROX, &prox); sensor_channel_get(tof_dev, SENSOR_CHAN_PROX, &prox);
printk("proxy: %d ;\n", prox.val1); printk("proxy: %d ;\n", prox.val1);
sensor_channel_get(tof_dev, SENSOR_CHAN_DISTANCE, &prox); sensor_channel_get(tof_dev, SENSOR_CHAN_DISTANCE, &prox);
printk("distance: %d -- %3d mm;\n", prox.val1, prox.val2); printk("distance: %d m -- %02d cm;\n", prox.val1,
prox.val2/10000);
#endif #endif
#ifdef CONFIG_LPS22HB #ifdef CONFIG_LPS22HB