Developer World Spresense
English 中文
目次

1. Spresense SDKの概要

Spresense SDKはSony Semiconductor Solutions Corp.が提供するCXD5602用に開発されたCXD5602を制御するためのソフトウェアです。 CXD5602の内部ブロックは以下のようになります。

CXD5602 blockdiagram
図 1. CXD5602 内部フロック図

CXD5602は大きく4つのドメインと呼ばれるブロックから構成されています。

  • Application Domain

    • 主にユーザアプリケーションプログラムが制御するブロックで、この中にユーザプログラムが動作するCPU (ARM社製 Cortex®-M4F) が6個搭載されています。

  • System IOP Domain

    • システムの起動やCXD5602内部の電源ドメイン管理などを行うブロックで、ARM社製 Cortex-M0が搭載されています。

  • GNSS Domain

    • 衛星を使った位置測位を行うブロックで、ARM社製 Cortex-M4Fが搭載されています。

  • Sensor Domain

    • I2CやSPIバスに接続されたセンサーのデータをCPUの介在無しに取得するブロックで低消費電力での常時センシングを行うためのソニー独自のハードウェアになります。

CXD5602に関する詳しい情報は、 ソニーセミコンダクタソリューションズ(株) Spresenseホームページを参照してください。

Spresense SDKは上記のハードウェアを制御するためのソフトウェアになります。 Spresense SDKはOSとしてRTOSの1つであるNuttXを利用しており、このOSをベースにして、CXD5602の性能を引き出すための細かな機能を提供します。 Spresenseの各ドライバは、NuttXがもつLinuxライクなDriver Frameworkに準拠して実装されており、そのドライバレイヤの上に、Spresenseが持つ、Audio、GNSS、ASMPなどのミドルウェアのレイヤがあります。

sdk overview
図 2. SDK Overview

各ミドルウェアと特徴的なドライバの概要は以下の通りになります。

表 1. Spresense SDK Middleware Overview
Module Name Summary

Audio Middleware

Spresense SDKのAudio機能を提供します。様々なデータパスに対応し、各種フォーマットでの録音、再生に加えて音声加工処理を実現できます。

Sensor Framework

Spresense SDKの各種センサーデータの出力・加工などの処理を行う際に、センサーもしくは加工データのやり取りをPublish/Subscribeアーキテクチャにて簡便にプログラム出来るようなフレームワークになります。

Memory Utility

Spresense SDKにて、リファレンスカウンター付、固定長メモリープール機能の提供及び、インスタンスの非同期送受信するタスク同期機構を提供しています。

ASMP Framework

CXD5602が持つマルチコアに対してユーザプログラムのロードなどの管理に加えて、CXD5602のメモリ構造の特徴の一つである12枚のタイルの管理を行っています。

Power Management

省電力を実現するための機能を提供します。

GNSS Driver

CXD5602にはGNSSの測位を行うHWサブシステムが備わっています。このドライバはそのサブシステムとのやり取りを行い、ユーザにPOSIX I/FのキャラクタデバイスライクなI/FとしてGNSSに関する機能を提供しています。

各モジュールの詳細は、「Spresense SDKが提供する機能」の章を参照してください。

2. License

Spresense SDKはNuttXと同様、BSD 3項型ライセンスの元でオープンソースとして公開しています。詳しいライセンス条項は、下記の通りです。

3. システム起動シーケンス

CXD5602はリセットが解除されると、BootCPUが起動します。このBootCPUで動作するのが、loader.espkになります。loader.espkが起動すると、loader.espkに制御が移り、loader.espkはnuttx.spkをロードし、アプリケーションCPUをスタートさせます。

nuttx.spkは本SDKでビルドされたバイナリですので、nuttx.spkの実行内容自体は、ビルド時の設定やアプリケーションの動作によって変わります。

アプリケーションがGNSSの機能を使う場合、初期化のAPIをコールした段階でgnss.espkがloader.espkによってロードされるようになっています。

したがって、loader.espkとgnss.espkはSpresense基板を利用する上で、必須のバイナリコードになります。 バイナリの入手方法については、ブートローダーのインストール を参照してください。

4. ソフトウェア構成管理

この章ではSpresense SDKのソースコードについてその概要を説明します。

4.1. リポジトリ

Spresense SDKでは以下の2つのリポジトリで構成されます。

リポジトリ名 サブリポジトリ 説明

spresense

Spresense SDK のメインリポジトリで開発環境を整える場合はこちらのリポジトリをCloneします。SpresenseのBSP及びSpresenseがサポートするドライバ、各種Exampleコードが含まれ、spresense-nuttx, spresense-nuttx-appsをSubmoduleとして参照しています。

spresense-nuttx

Spresense NuttX のクローンリポジトリです。SpresenseにおけるKernelがこのリポジトリで管理されています

spresense-nuttx-apps

Spresense NuttX Apps のクローンリポジトリです (v2.0以降)。SpresenseにおけるNuttXオリジナルアプリケーションがこのリポジトリで管理されています

4.2. ソースツリー

Spresense SDKのソースツリー構成は以下のようになっています

spresense directory structure2
図 3. Spresense SDKのディレクトリ構成

各ディレクトリの内容は以下のようになっています

ディレクトリ名 説明

spresense

spresenseをCloneすると生成されるディレクトリです

examples

Spresense SDKでサポートされるドライバ、モジュールを使ったExampleコードが含まれます

externals

Spresense SDKでサポートされる外部ライブラリが含まれます

nuttx

Spresense NuttX のKernelソースコードが含まれます

sdk

Spresense SDKでサポートされるドライバ、モジュール類が含まれます

apps

Spresense NuttX オリジナルアプリケーションのソースコードが含まれます (v2.0以降)

configs

Spresense SDKで提供しているConfigurationが含まれます

modules

Spresense SDKで提供しているオーディオやセンサなどのモジュールが含まれます

system

Spresense SDKで提供しているシステムツールが含まれます

tools

Spresense SDKでの開発に必要なツールおよびスクリプトが含まれます

5. Spresense SDKが提供する機能

ここでは、Spresense SDKで提供している各機能について、説明します。

5.1. BSP

5.1.1. 概要

BSP (Board Support Package) は、ボード固有の設定や処理を行うためのソースコードが含まれています。

NuttXでは、以下のようなドライバソフトウェアアーキテクチャになっており、BSPディレクトリには Driver (Lower Half)Board specific code および Architecture specific code などのドライバソフトウェアが含まれます。

Diagram
図 4. デバイスドライバ階層図
5.1.1.1. Driver (Lower Half)

NuttX には、標準的なデバイスやバスに対してUpper Halfと呼ばれるドライバがあります。Upper Halfドライバは、アプリケーションへのインターフェースやプロトコル処理などを行いますが、それ単体で動作させることはできません。このため、BSPでLower Half ドライバを適切に実装することで、そのデバイスを使用することができるようになります。

Spresense SDKが提供しているLower Halfドライバには以下のようなものがあります。

  • I2C (cxd56_i2c.c)

  • PWM (cxd56_pwm.c)

  • RTC (cxd56_rtc_lowerhalf.c)

  • SDIO Device (cxd56_sdhci.c)

  • Serial Device (cxd56_serial.c)

  • SPI (cxd56_spi.c)

  • Timer (cxd56_timer.c)

  • USB Device (cxd56_usbdev.c)

  • Watchdog timer (cxd56_wdt.c)

NuttXのドライバに関する詳細は、NuttX Device Drivers を参照してください。

5.1.1.2. Architecture specific code

アーキテクチャ固有ドライバは、チップに搭載されている機能を使用するためのドライバ(電源管理など)が含まれます。

5.1.1.3. Board specific code

ボード固有の処理には、ボードの実装によって可変になるもの(ピン設定など)があります。これらの処理には、ある程度共通化できるものと完全にボード依存になっているものに分かれます。これらはそれぞれ、nuttx/boards/arm/cxd56xx/common および nuttx/boards/arm/cxd56xx/<board name><board name> は対応しているボード名)に格納されています。

また、ボードの初期化処理もこれに含まれます。

5.1.2. ディレクトリ構成

spresense/nuttx
|-- arch
|   `-- arm
|       |-- include
|       |   `-- cxd56xx
|       `-- src
|           `-- cxd56xx
`-- boards
    `-- arm
        `-- cxd56xx
            |-- common
            |-- drivers
            `-- spresense
                `-- scripts
ディレクトリ名 内容

nuttx/boards/arm/cxd56xx/common

ボード固有の処理だが、処理シーケンスが同じで、マクロの変更等で共通化できるルーチンが含まれます。

nuttx/boards/arm/cxd56xx/spresense

Spresense基板を動作させるための処理(ピン設定など)が含まれます。

nuttx/boards/arm/cxd56xx/spresense/scripts

リンカスクリプトが含まれます。

nuttx/boards/arm/cxd56xx/drivers

Spresense固有のドライバが含まれます。

nuttx/arch/arm/include/cxd56xx

SoCに搭載されているデバイスドライバが提供しているAPIを呼び出す場合のヘッダファイルが含まれます。

nuttx/arch/arm/src/cxd56xx

Lower Halfドライバやチップ固有のデバイスドライバなどが含まれます。

5.1.3. ボードの初期化処理

Diagram
図 5. 起動シーケンス

メインCPUが起動すると、NuttXカーネルの初期化が行われ、Userのエントリポイント関数が呼び出されます。デフォルトの設定では、spresense_main 関数が呼ばれ、そこから nsh (NuttShell) を起動します。CONFIG_USER_ENTRYPOINT を変更することでUserのエントリポイントを変更することができます。

nsh では、ボードの初期化( boardctl() )が呼び出されます。実際のボードの初期化は、NuttXのルールに従い board_app_initialize 関数に実装されています。この関数では、使用するボードの初期化を行うための処理を行います。

初期化の処理には、Spresenseを使用するための最低限の機能の初期化や、使用するデバイスドライバの初期化などがあります。

CONFIG_USER_ENTRYPOINT で起動するタスクを spresense_main から変更した場合は、ユーザーが自ら boardctl() の呼び出しを行う必要があります。

5.2. GPIO/Pin Specification

5.2.1. Software Structure

Diagram

5.2.2. GPIO Driver Interface

gpioif は、アプリケーションに対して以下の機能を提供します。

  • GPIO ピン設定

    • 機能モード

    • 入出力設定

    • ドライブ電流/スルーレート設定

    • プルアップ/プルダウン設定

  • GPIO 割り込み設定

    • レベル・エッジトリガ設定

    • ノイズフィルタ設定

  • GPIO 入出力制御

  • GPIO 状態取得

APIの詳細は、こちらを参照してください。

GPIO 割り込みは、board_gpio_intconfig 関数により登録できますが、登録可能な上限数が決まっています。 SYS GPIO と APP GPIO を合わせて最大12本まで登録することができます。

  • SYS GPIO (PIN_I2C4_BCK ~ PIN_PWM3) の中から最大6本まで

  • APP GPIO (PIN_IS_CLK ~ PIN_USB_VBUSINT) の中から最大6本まで

ピン名称やピン番号の定義については、nuttx/arch/arm/include/cxd56xx/pin.h を参照してください。

5.2.2.1. GPIO Utility tool

System tools に GPIO Command が用意されており、 CONFIG_SYSTEM_GPIO=y にすることで、NuttShell から gpio コマンドが利用可能です。

gpio コマンドの使い方

nsh> gpio
USAGE: gpio command
 stat [<from_pin>] [<end_pin>]
 conf <pin> [-m <0|1|2|3>] [-i] [-H] [-p <0|1|2|3>]
  -m: function mode
  -i: input enable
  -H: Higher drive current/slew rate
  -p: 0=float, 1=pullup, 2=pulldown, 3=buskeeper
 read <pin>
 write <pin> <0|1|-1>

CONFIG_SYSTEM_GPIO_STATUS=y にすることで、NuttShell から gpio stat 状態表示コマンドが有効になります。

nsh> gpio stat
-------------------------------------------------------------
( No)PIN NAME          : Mode I/O mA Pull Read IRQ Type NF EN
-------------------------------------------------------------
(  1)PIN_I2C4_BCK      : 1    I/  2  --   1    -1
(  2)PIN_I2C4_BDT      : 1    I/  2  --   1    -1
(  3)PIN_PMIC_INT      : 1    I/  2  --   0    -1
(  4)PIN_RTC_IRQ_OUT   : 0     /  2  --   0    -1
(  5)PIN_AP_CLK        : 0     /  2  --   0    -1
(  6)PIN_GNSS_1PPS_OUT : 0     /  2  --   0    -1
( 17)PIN_SPI0_CS_X     : 1     /  2  --   0    -1
( 18)PIN_SPI0_SCK      : 1    I/  2  --   1    -1
( 19)PIN_SPI0_MOSI     : 0     /  2  --   0    -1
( 20)PIN_SPI0_MISO     : 0     /  2  --   0    -1
  :
(101)PIN_MCLK          : 0     /  2  --   0    -1
(102)PIN_PDM_CLK       : 0     /  2  --   0    -1
(103)PIN_PDM_IN        : 0     /  2  --   0    -1
(104)PIN_PDM_OUT       : 0     /  2  --   0    -1
(105)PIN_USB_VBUSINT   : 1    I/  2  --   1    -1

5.2.3. Pin specification

ピンは複数の用途が割り当てられており、Mode(0-3) によって機能を変更することができます。 それぞれのピンはまとまった単位で Pin Group としてグルーピングされており、 Mode番号の指定によってその Group 単位で機能が切り替わります。

ここで PIN_PWM2, PIN_PWM3 のピンについての具体例を示します。

boardspec pinmode

PIN_PWM2 と PIN_PWM3 は同一 Group に属しており、上の図にあるように、 Mode の選択によって 2 つのピンの機能が連動して同時に切り替わります。

  • Mode0 の場合は、PIN_PWM2 と PIN_PWM3 の Pin は 両方とも GPIO 機能に設定されます

  • Mode1 の場合は、PIN_PWM2 と PIN_PWM3 の Pin は 両方とも PWM 機能に設定されます

  • Mode2 の場合は、PIN_PWM2 と PIN_PWM3 の Pin は 両方とも I2C 機能に設定されます

Group 単位で機能が割り当てられるため、PIN_PWM2 を GPIO として、PIN_PWM3 を PWM として個別に設定することはできません。 また、全てのピンについて、LSI の初期状態は Mode0 (GPIO) が選択されています。
5.2.3.1. Pin List
  • Pin Name: nuttx/arch/arm/include/cxd56xx/pin.h に、PIN_XXX という形式で定義されています

  • WLCSP: 100-pin package (CXD5602GF) の定義です。いくつか使用できないピンがあります。

  • FCBGA: 185-pin full package (CXD5602GG) の定義です。Spresense 基板で使用されています。

  • Mode0-3: それぞれのモードにおけるピンの機能が記述されています。

表 2. SDK が制御できるピンのリスト
Pin Name Arduino
compatible
Pin Name
WLCSP FCBGA Mode0 Mode1 Mode2 Mode3

I2C4_BCK

-

*

*

GPIO

I2C#4
(CXD5247)

I2C4_BDT

-

*

*

PMIC_INT

-

*

*

GPIO

PMIC
Interrupt

PMIC Interrupt
(OpenDrain)

RTC_IRQ_OUT

D41

*

GPIO

RTC_IRQ_OUT

RTC_IRQ_OUT
(OpenDrain)

AP_CLK

D40

*

*

GPIO

AP_CLK

PMU_WDT

PMU_WDT
(OpenDrain)

GNSS_1PPS_OUT

D44

*

GPIO

GNSS_1PPS_OUT

CPU_WDT

CPU_WDT
(OpenDrain)

SPI0_CS_X

-

*

*

GPIO

UART#1
(Console)

SPI#0

SPI0_SCK

-

*

*

SPI0_MOSI

-

*

GPIO

I2C#2

SPI0_MISO

-

*

SPI1_CS_X

-

*

*

GPIO

SPI#1
(SPI-Flash)

SPI#0

SPI1_SCK

-

*

*

SPI1_IO0

-

*

*

SPI1_IO1

-

*

*

SPI1_IO2

-

*

*

GPIO

SPI1_IO3

-

*

*

SPI2_CS_X

D42

*

*

GPIO

SPI#2
(HostIF)

UART#0
(HostIF)

I2C#3
(HostIF)

SPI2_SCK

D43

*

*

SPI2_MOSI

D04

*

*

GPIO

SPI2_MISO

D08

*

*

HIF_IRQ_OUT

D02

*

*

GPIO

HIF_IRQ_OUT

HIF_IRQ_OUT
(OpenDrain)

GNSS_1PPS_OUT

HIF_GPIO0

D39

*

GPIO

GPS_EXTLD

SEN_IRQ_IN

D22

*

*

GPIO

SEN_IRQ_IN

SPI3_CS0_X

D32

*

*

GPIO

SPI3_CS0_X

SPI3_CS1_X

D07

*

*

GPIO

SPI3_CS1_X

SPI3_CS2_X

-

*

*

GPIO

SPI3_CS2_X

SPI3_SCK

D29

*

*

GPIO

SPI#3
(Sensor)

SPI3_MOSI

D31

*

*

SPI3_MISO

D30

*

*

I2C0_BCK

D15

*

*

GPIO

I2C#0
(Sensor)

I2C0_BDT

D14

*

*

PWM0

D06

*

*

GPIO

PWM#0,1

PWM1

D05

*

*

PWM2

D09

*

*

GPIO

PWM#2,3

I2C#1
(Sensor)

PWM3

D03

*

*

IS_CLK

-

*

GPIO

CMOS Image Sensor

IS_VSYNC

-

*

IS_HSYNC

-

*

IS_DATA0

-

*

IS_DATA1

-

*

IS_DATA2

-

*

IS_DATA3

-

*

IS_DATA4

-

*

IS_DATA5

-

*

IS_DATA6

-

*

IS_DATA7

-

*

UART2_TXD

D01

*

*

GPIO

UART#2

UART2_RXD

D00

*

*

UART2_CTS

D27

*

*

UART2_RTS

D28

*

*

SPI4_CS_X

D10

*

*

GPIO

SPI#4

SPI4_SCK

D13

*

*

SPI4_MOSI

D11

*

*

SPI4_MISO

D12

*

*

EMMC_CLK

D23

*

*

GPIO

eMMC

SPI#5

EMMC_CMD

D24

*

*

EMMC_DATA0

D16

*

*

EMMC_DATA1

D17

*

*

EMMC_DATA2

D20

*

*

GPIO

EMMC_DATA3

D21

*

*

SDIO_CLK

-

*

GPIO

SDIO

SPI#5

SDIO_CMD

-

*

SDIO_DATA0

-

*

SDIO_DATA1

-

*

SDIO_DATA2

-

*

GPIO

SDIO_DATA3

-

*

SDIO_CD

D36

*

GPIO

SDIO
(Card)

SDIO_WP

D37

*

SDIO_CMDDIR

D33

*

GPIO

SDIO

SDIO_DIR0

D34

*

SDIO_DIR1_3

D35

*

SDIO_CLKI

D38

*

GPIO

SDIO
(Card)

I2S0_BCK

D26

*

*

GPIO

I2S#0

I2S0_LRCK

D25

*

*

I2S0_DATA_IN

D19

*

*

I2S0_DATA_OUT

D18

*

*

I2S1_BCK

LED0

*

GPIO

I2S#1

I2S1_LRCK

LED1

*

I2S1_DATA_IN

LED2

*

I2S1_DATA_OUT

LED3

*

MCLK

-

*

*

GPIO

MCLK
(Audio)

PDM_CLK

-

*

*

GPIO

PDM
(Audio)

PDM_IN

-

*

*

PDM_OUT

-

*

*

USB_VBUSINT

-

*

*

GPIO

USB VBUS Interrupt

5.2.3.2. Pin Configuration

Pin 設定は、pinconfigドライバで設定されます。例えば、Mode0(GPIO)以外の I2C や SPI 機能として使用する場合は、 それぞれ I2C, SPI ドライバの中で、Pin が設定されます。そのため、アプリケーションが Mode の変更などを 意識する必要はありません。

Mode0(GPIO) として使用する場合に限り、前述した gpioif を使用して設定してください。

5.2.3.2.1. Board Specific Pin Pull and Drive Current Setting

Pin のプル設定やドライブ電流のデフォルト設定は、 nuttx/arch/arm/src/cxd56xx/hardware/cxd5602_pinconfig.h に定義されています。

基本的に、プル設定は Hi-Z フローティング状態、ドライブ電流は多くが 2mA に設定されています。

基板に依存して、これらの設定を変更する場合は、CONFIG_BOARD_CUSTOM_PINCONFIG=y 有効にして、 nuttx/boards/arm/cxd56xx/spresense/include/board_pinconfig.h を参考に定義してください。

Spresense基板の例では、

/* Customize from default to the board specific pin configuration
 * The default pin configurations are defined in
 * boards/arm/cxd56xx/spresense/include/board_pinconfig.h.
 *
 *  Mode: shared pin function mode
 *  ENZI: 1=Input Enable, 0=Input Disable
 *  4mA : Drive Current 1=4mA, 0=2mA
 *  Pull: 0=HiZ floating, PINCONF_PULLUP, PINCONF_PULLDOWN
 *                                                                      M  E     P
 *                                                  P                   o  N  4  u
 *                                                  i                   d  Z  m  l
 *                                                  n                   e  I  A  l
 */

#undef PINCONF_UART2_CTS
#define PINCONF_UART2_CTS                   PINCONF(PIN_UART2_CTS,      1, 1, 0, PINCONF_PULLDOWN)

#undef PINCONF_SPI4_CS_X
#undef PINCONF_SPI4_SCK
#undef PINCONF_SPI4_MOSI
#define PINCONF_SPI4_CS_X                   PINCONF(PIN_SPI4_CS_X,      1, 0, 1, 0)
#define PINCONF_SPI4_SCK                    PINCONF(PIN_SPI4_SCK,       1, 0, 1, 0)
#define PINCONF_SPI4_MOSI                   PINCONF(PIN_SPI4_MOSI,      1, 0, 1, 0)

#undef PINCONF_PWM0
#undef PINCONF_PWM1
#undef PINCONF_PWM2
#undef PINCONF_PWM3
#define PINCONF_PWM0                        PINCONF(PIN_PWM0,           1, 0, 1, 0)
#define PINCONF_PWM1                        PINCONF(PIN_PWM1,           1, 0, 1, 0)
#define PINCONF_PWM2                        PINCONF(PIN_PWM2,           1, 0, 1, 0)
#define PINCONF_PWM3                        PINCONF(PIN_PWM3,           1, 0, 1, 0)
  • UART2_CTS ピンを Pull Down を有効

  • SPI4 のドライブ電流を 2mA から 4mA に変更

  • PWM のドライブ電流を 2mA から 4mA に変更

しています。


5.3. Audio Subsystem

5.3.1. General

CXD5602 はハイレゾリューションを扱えるオーディオ機能(オーディオ・サブシステム)が搭載されています。 オーディオ・サブシステムの機能概要を以下に示します。

  • Audio Codec ハードウェア (AD/DA, DNC, DEQ, etc.) の制御

  • Audio Recorder 及び Capture 機能

  • Audio Player 及び Renderer 機能

  • Bluetooth 関連機能(for BT-A2DP)

  • Sound Effector 機能(例えば、音声通話用のバンドパスフィルタなど)

  • Sound Sensing 機能(例えば、ノイズ計測、異常音検知など)

このドキュメントは、CXD5602 のハードウェア上で実現できるオーディオ機能を制御するためのソフトウェアが記載されています。

現在のファームウェアでは、Bluetooth 関連機能(for BT-A2DP) 及び、Sound Effector 機能(例えば、音声通話用のバンドパスフィルタなど) は、未対応です。

5.3.2. レイヤ構造について

オーディオ・サブシステムのスタックダイアグラムを以下に示します。

Audio Sub-system Stack Diagram
図 6. Audio Sub-system Stack diagram

オーディオ・サブシステムは、大きく3つのレイヤを持ちます。

Audio Manager(High Level API)

最上位のレイヤで、最上位の抽象度での制御を行うレイヤです。システム全体の整合を取りながら制御します。

Object Layer(ObjectLevel API)

各機能Objectのレイヤで、機能ブロック単位での抽象度で制御を行うレイヤです。各機能内の信号処理・DSP処理などに関して整合を取ります。

Component Layer(Low Level API)

各信号処理componetのレイヤで、信号処理ブロック単位での抽象度で制御を行うレイヤです。信号処理ブロックの組み合わせで処理を構成することで、自由度の高いオーディオ処理を実現できます。

5.3.3. High Level API

High Level API は Spresense SDK AudioAudio Manager が提供する API です。

5.3.3.1. コマンド送受信による制御ついて

High Level API は、オーディオ・サブシステムをコマンドオブジェクトで制御します。(High Level API Command System)
コマンドオブジェクトは、AS_SendAudioCommandでオーディオ・サブシステムに送信されます。
送信されるコマンドオブジェクトは、AudioCommandになります。
コマンドの詳細は コマンドフォーマット に記載します。

オーディオ・サブシステムは、送信されたコマンドに応じて処理を行い、結果を返します。
結果は、AudioResult オブジェクトで返され、AS_ReceiveAudioResult で取得することができます。
リザルトの詳細は リザルトフォーマット に記載します。

コマンドは同期コマンドになります。コマンドを発行したらリザルトが返るまで次のコマンドを発行できません。
Audio Manager を介して High Level API を使う場合は、送信・受信の手順が1コマンド単位で対になるようにプログラムしてください。
High Level API Command System
図 7. Audio High Level API Command System
5.3.3.1.1. 制御データ形式(コマンドフォーマット)について

コマンドオブジェクト AudioCommand は1 ワード(4 バイト)の AudioCommandHeader で始まり、その後に必要なだけのパラメータ領域を付加したデータ構造です。
コマンドオブジェクトは、ワード単位をベースとしているため、1 ワード(32 ビット、4バイト)の整数倍の長さで構成されています。
コマンドオブジェクトのreserved フィールドには、0 を設定してください。

typedef struct
{
  AudioCommandHeader header;
  union
  {
    Command Parameters (Payload)
    ...
    ...
  };
} AudioCommand;
コマンド・ヘッダ

全てのコマンドオブジェクトの先頭1 ワード(4 バイト)は、以下の形式です。この1 ワードをコマンドヘッダ(AudioCommandHeader)と呼びます。

typedef struct
{
  uint8_t reserved;
  uint8_t sub_code;
  uint8_t command_code;
  uint8_t packet_length;
} AudioCommandHeader;
packet_length

コマンドヘッダを含めたコマンドオブジェクトの長さを示します。
全てのコマンドオブジェクトは整数個のワード(4バイト)で構成されており、
packet_lengthで指定する値はコマンド・パケットのワード長、すなわちコマンドオブジェクトのバイト長の4分の1となります。

command_code

コマンドに固有のコードです。値0x00は使用しません。
コマンドの種類については コマンド一覧 を参照してください。

sub_code

各コマンドにおいて設定および制御を行う対象を識別するためのコードです。

5.3.3.1.2. 通知データ形式(リザルトフォーマット)

リザルトオブジェクトは1 ワード(4バイト) AudioResultHeader で始まり、その後に必要なだけのパラメータ領域が付加されたデータ構造です。
リザルトオブジェクトは、ワード単位をベースとしているため、1 ワード(32 ビット、4 バイト)の整数倍の長さで構成されています。
リザルトオブジェクトのreservedフィールドは無視してください。

typedef struct
{
  AudioResultHeader header;
  union
  {
    Result Parameters (Payload)
    ...
    ...
  };
} AudioResult;
リザルト・ヘッダ

全てのリザルトオブジェクトの先頭1ワード(4バイト)は、以下の形式です。
この1ワードをリザルト・ヘッダ(AudioResultHeader)と呼びます。

typedef struct
{
  uint8_t reserved;
  uint8_t sub_code;
  uint8_t result_code;
  uint8_t packet_length;
} AudioResultHeader;
packet_length

リザルトヘッダを含めたリザルトオブジェクトの長さを示します。
全てのリザルトオブジェクトは整数個のワード(4バイト)で構成されており、
packet_lengthで指定する値はリザルトオブジェクトのワード長、すなわちリザルトオブジェクトのバイト長の4分の1となります。

result_code

リザルトの種類を識別するためのコードです。
リザルトの種類については リザルト一覧 を参照してください。 このコードにより、パラメータ領域のデータ内容が変わります。

sub_code

実行したコマンドのsub_codeと同じ値が入ります。

5.3.3.2. 状態遷移

High Level API は、複数の状態を持ちます。 以下に、状態遷移図を示します。

Diagram

各モードの説明は以下になります。

  • PowerOff 状態

オーディオ・サブシステムのオブジェクトを生成し、起動した直後の状態です。オーディオを使用しない場合には、この状態に遷移しておくことで、オーディオブロックでの消費電力をほぼ0にします。

AUDCMD_POWERON コマンドによって、Ready状態にのみ遷移します。

  • Ready状態

オーディオブロックに電源を入れて、動作モードにオーディオ機能を動作できるように準備している状態です。この状態では、消費電力は下がっていないのですが、IO/アナログが起動している状態ですので、モード遷移が速やかに行えます。

状態の遷移は、以下になります。

AUDCMD_SETPOWEROFFSTATUS コマンドによって、PowerOff状態に遷移できます。 AUDCMD_SETPLAYERSTATUS コマンドによって、Player状態に遷移できます。 AUDCMD_SETRECORDERSTATUS コマンドによって、Recorder状態に遷移できます。 AUDCMD_SETBASEBANDSTATUS コマンドによって、Baseband状態に遷移できます。 AUDCMD_SETRECOGNIZERSTATUS コマンドによって、recognizer状態に遷移できます。

  • Player状態

SDカードなどのストレージや WiFi/LTE などのネットワークからの圧縮音声ファイルをデコードし、AnalogOutやI2Sに発音する機能を実現する状態です。状態の中にPlayerReady状態とPlayerActive状態の2つのサブ状態を持ちます。 PlayerReady状態は、音楽再生停止の状態です。AUDCMD_PLAYPLAYER によってPlayerActiveに遷移し音楽再生動作を行います。 PlayerActive状態は、音楽再生中の状態です。AUDCMD_STOPPLAYER によって音楽再生を停止しPlayerReadyに遷移します。

AUDCMD_SETREADYSTATUS コマンドによって、Ready状態にのみ遷移します。

  • Recorder状態

Micから入力された音声データを圧縮して、SDカードなどのストレージに書き出したり、WiFi/LTE などのネットワークに打ち上げて記録する機能を実現する状態です。 状態の中にRecorderReady状態とRecorderActive状態の2つのサブ状態を持ちます。 RecorderReady状態は、音声記録停止の状態です。AUDCMD_STARTREC によってRecorderActiveに遷移し音声記録動作を行います。 RecorderActive状態は、音声記録中の状態です。AUDCMD_STOPREC によって音声記録を停止しRecorderReadyに遷移します。

AUDCMD_SETREADYSTATUS コマンドによって、Ready状態にのみ遷移します。

  • Baseband状態

Micから入力された音声データを、内部でエフェクト処理を行い、AnalogOut、または、I2Sに出力する機能を実現する状態です。 状態の中にBasebandReady状態とBasebandActive状態の2つのサブ状態を持ちます。 BasebandReady状態は、音声入出力停止の状態です。AUDCMD_STARTBB によってBasebandActiveに遷移し音声入出力動作を開始します。 BaseBandActive状態は、音声入出力動作中状態です。AUDCMD_STOPBB によって音声入出力動作を停止しBasebandReadyに遷移します。

AUDCMD_SETREADYSTATUS コマンドによって、Ready状態にのみ遷移します。

  • Recognizer状態

Micから入力された音声データに対して、何からの認識処理を行う機能を実現する状態です。 状態の中にRecognizerReady状態とRecognizerActive状態の2つのサブ状態を持ちます。 RecognizerReady状態は、音声入出Recognizer力停止の状態です。AUDCMD_START_RECOGNIZER によってRecognizerActiveに遷移し音声入出力動作を開始します。 RecognizerActive状態は、音声入出力動作中状態です。AUDCMD_STOP_RECOGNIZER によって音声入出力動作を停止しRecognizerReadyに遷移します。

AUDCMD_SETREADYSTATUS コマンドによって、Ready状態にのみ遷移します。

5.3.3.3. インスタンスの生成

High Level API を実行するために、各クラスインスタンスの生成、メモリ管理、メッセージ通信用のリソース割り当て等を行う必要があります。

これらは、各レイヤーごとの機能ブロックに対する create 関数を呼ぶことで実行が可能です。以下に各レイヤごとの create 関数のリストを示します。

5.3.3.3.1. Audio Manager の生成

High Level API を使用する場合、 Audio Manager のインスタンス生成とリソース割り当てを行う必要があります。 これらを行う場合は、以下の関数を呼ぶ必要があります。

  • 関数名

  • 引数

    • 各リソース(メモリマネージャ、メッセージ)のID

      typedef struct
      {
        /*! \brief [in] MsgQueID of Application */
        uint8_t app;
      
        /*! \brief [in] MsgQueID of audio_manager */
        uint8_t mng;
      
        /*! \brief [in] MsgQueID of playerObject */
        uint8_t player_main;
      
        /*! \brief [in] MsgQueID of playerObject for Sound Effect */
        uint8_t player_sub;
      
        /*! \brief [in] MsgQueID of FrontendObject */
        uint8_t micfrontend;
      
        /*! \brief [in] MsgQueID of recorderObject */
        uint8_t recorder;
      
        /*! \brief [in] MsgQueID of mixerObject */
        uint8_t mixer;
      
        /*! \brief [in] MsgQueID of effectorObject */
        uint8_t effector;
      
        /*! \brief [in] MsgQueID of recognizerObject */
        uint8_t recognizer;
      
      } AudioSubSystemIDs;
    • リザルト受信用のcallback

      AudioAttentionCb を設定する。

      typedef void (*AudioAttentionCb)(const ErrorAttentionParam *attparam);
AS_CreateAudioManager は、起動直後か、AS_DeleteAudioManager 呼出し後にのみ呼び出し可能です。
5.3.3.3.2. Object Layer の生成

High Level API を使用する場合でも、 Object Layer で使用する各 Object の生成は必要です。各 Object ごとのインスタンス生成とリソース割り当てを行います。

これらを行う場合は、以下の関数を呼ぶ必要があります。

Mic Frontend Object の生成
  • 関数名

  • 引数

    • 各リソース(メモリマネージャ、メッセージ)のID

      /** Message queue ID parameter of activate function */
      
      typedef struct
      {
        /*! \brief [in] Message queue id of micfrontend */
      
        uint8_t micfrontend;
      
        /*! \brief [in] Message queue id of audio_manager */
      
        uint8_t mng;
      
        /*! \brief [in] Message queue id of DSP */
      
        uint8_t dsp;
      
      } AsMicFrontendMsgQueId_t;
      /** Pool ID parameter of activate function */
      
      typedef struct
      {
        /*! \brief [in] Memory pool id of input data */
      
        MemMgrLite::PoolId input;
      
        /*! \brief [in] Memory pool id of PreProc */
      
        MemMgrLite::PoolId output;
      
        /*! \brief [in] Memory pool id of dsp command data */
      
        MemMgrLite::PoolId dsp;
      
      } AsMicFrontendPoolId_t;
      typedef struct
      {
        /*! \brief [in] ID for sending messages to each function */
      
        AsMicFrontendMsgQueId_t msgq_id;
      
        /*! \brief [in] ID of memory pool for processing data */
      
        AsMicFrontendPoolId_t   pool_id;
      
      } AsCreateMicFrontendParams_t;
    • リザルト受信用のcallback

      AudioAttentionCb を設定する。

      typedef void (*AudioAttentionCb)(const ErrorAttentionParam *attparam);
AS_CreateMicFrontend は、起動直後か、AS_DeleteMicFrontend 呼出し後にのみ呼び出し可能です。
Media Recorder Object の生成
  • 関数名

  • 引数

    • 各リソース(メモリマネージャ、メッセージ)のID

      /** Message queue ID parameter of activate function */
      
      typedef struct
      {
        /*! \brief [in] Message queue id of recorder */
      
        uint8_t recorder;
      
        /*! \brief [in] Message queue id of audio_manager */
      
        uint8_t mng;
      
        /*! \brief [in] Message queue id of DSP */
      
        uint8_t dsp;
      } AsRecorderMsgQueId_t;
      /** Pool ID parameter of activate function */
      
      typedef struct
      {
        /*! \brief [in] Memory pool id of input data */
      
        MemMgrLite::PoolId input;
      
        /*! \brief [in] Memory pool id of output data */
      
        MemMgrLite::PoolId output;
      
        /*! \brief [in] Memory pool id of dsp command data */
      
        MemMgrLite::PoolId dsp;
      
      } AsRecorderPoolId_t;
      typedef struct
      {
        /*! \brief [in] ID for sending messages to each function */
      
        AsRecorderMsgQueId_t msgq_id;
      
        /*! \brief [in] ID of memory pool for processing data */
      
        AsRecorderPoolId_t   pool_id;
      
      } AsCreateRecorderParams_t;
    • リザルト受信用のcallback

      AudioAttentionCb を設定する。

      typedef void (*AudioAttentionCb)(const ErrorAttentionParam *attparam);
AS_CreateMediaRecorder は、起動直後か、AS_DeleteMediaRecorder 呼出し後にのみ呼び出し可能です。
Output Mixer Object の生成
  • 関数名

  • 引数

    • 各リソース(メモリマネージャ、メッセージ)のID

      /** Message queue ID parameter of activate function */
      
      typedef struct
      {
        /*! \brief [in] Message queue id of output mixer */
      
        uint8_t mixer;
      
        /*! \brief [in] Message queue id of audio_manager */
      
        uint8_t mng;
      
        /*! \brief [in] Message queue id of dsp
         *              Effective only when use postfilter
         */
      
        uint8_t render_path0_filter_dsp;
        uint8_t render_path1_filter_dsp;
      
      } AsOutputMixMsgQueId_t;
      /** Pool ID parameter of activate function */
      
      typedef struct
      {
        /*! \brief [in] Memory pool id of pcm data
         *              Effective only when use postfilter
         */
      
        MemMgrLite::PoolId render_path0_filter_pcm;
        MemMgrLite::PoolId render_path1_filter_pcm;
      
        /*! \brief [in] Memory pool id of dsp command data
         *              Effective only when use postfilter
         */
      
        MemMgrLite::PoolId render_path0_filter_dsp;
        MemMgrLite::PoolId render_path1_filter_dsp;
      
      } AsOutputMixPoolId_t;
      typedef struct
      {
        /*! \brief [in] ID for sending messages to each function */
      
        AsOutputMixMsgQueId_t msgq_id;
      
        /*! \brief [in] ID of memory pool for processing data */
      
        AsOutputMixPoolId_t   pool_id;
      
      } AsCreateOutputMixParams_t;
    • リザルト受信用のcallback

      AudioAttentionCb を設定する。

      typedef void (*AudioAttentionCb)(const ErrorAttentionParam *attparam);
AS_CreateOutputMixer は、起動直後か、AS_DeleteOutputMix 呼出し後にのみ呼び出し可能です。
Multi Player Object の生成
  • 関数名

  • 引数

    • Player ID
      Playerのインスタンスは2つまで生成可能です。それぞれのインスタンスのIDを指定します。

      typedef enum
      {
        AS_PLAYER_ID_0 = 0,
      
        AS_PLAYER_ID_1,
      
        AS_PLAYER_ID_NUM,
      
      } AsPlayerId;
    • 各リソース(メモリマネージャ、メッセージ)のID

      /** Message queue ID parameter of activate function */
      
      typedef struct
      {
        /*! \brief [in] Message queue id of player */
      
        uint8_t player;
      
        /*! \brief [in] Message queue id of audio_manager */
      
        uint8_t mng;
      
        /*! \brief [in] Message queue id of output mixer */
      
        uint8_t mixer;
      
        /*! \brief [in] Message queue id of DSP */
      
        uint8_t dsp;
      
      } AsPlayerMsgQueId_t;
      /** Pool ID parameter of activate function */
      
      typedef struct
      {
        /*! \brief [in] Memory pool id of es data */
      
        MemMgrLite::PoolId es;
      
        /*! \brief [in] Memory pool id of pcm data */
      
        MemMgrLite::PoolId pcm;
      
        /*! \brief [in] Memory pool id of dsp command data */
      
        MemMgrLite::PoolId dsp;
      
        /*! \brief [in] Memory pool id of src work area */
      
        MemMgrLite::PoolId src_work;
      
      } AsPlayerPoolId_t;
      typedef struct
      {
        /*! \brief [in] ID for sending messages to each function */
      
        AsPlayerMsgQueId_t msgq_id;
      
        /*! \brief [in] ID of memory pool for processing data */
      
        AsPlayerPoolId_t   pool_id;
      
      } AsCreatePlayerParams_t;
    • リザルト受信用のcallback

      AudioAttentionCb を設定する。

      typedef void (*AudioAttentionCb)(const ErrorAttentionParam *attparam);
AS_CreatePlayerMulti は、起動直後か、AS_DeletePlayer 呼出し後にのみ呼び出し可能です。
Recognizer Object の生成
  • 関数名

  • 引数

    • 各リソース(メモリマネージャ、メッセージ)のID

      /** Message queue ID parameter of activate function */
      
      typedef struct
      {
        /*! \brief [in] Message queue id of sound recognizer */
      
        uint8_t recognizer;
      
        /*! \brief [in] Message queue id of audio_manager */
      
        uint8_t mng;
      
        /*! \brief [in] Message queue id of DSP */
      
        uint8_t dsp;
      
      } AsRecognizerMsgQueId_t;
      /** Pool ID parameter of activate function */
      
      typedef struct
      {
        /*! \brief [in] Memory pool id of recognition result data */
      
        MemMgrLite::PoolId out;
      
        /*! \brief [in] Memory pool id of DSP communication Message */
      
        MemMgrLite::PoolId dsp;
      
      } AsRecognizerPoolId_t;
      typedef struct
      {
        /*! \brief [in] ID for sending messages to each function */
      
        AsRecognizerMsgQueId_t msgq_id;
      
        /*! \brief [in] ID of memory pool for processing data */
      
        AsRecognizerPoolId_t   pool_id;
      
      } AsCreateRecognizerParam_t;
    • リザルト受信用のcallback

      AudioAttentionCb を設定する。

      typedef void (*AudioAttentionCb)(const ErrorAttentionParam *attparam);
AS_CreateRecognizer は、起動直後か、AS_DeleteRecognizer 呼出し後にのみ呼び出し可能です。
Media Synthesizer Object の生成
  • 関数名
    AS_CreateMediaSynthesizer

  • 引数

    • 各リソース(メモリマネージャ、メッセージ)のID

      /** Message queue ID parameter of activate function */
      
      typedef struct
      {
        /*! \brief [in] Message queue id of synthesizer */
      
        uint8_t synthesizer;
      
        /*! \brief [in] Message queue id of audio_manager */
      
        uint8_t mng;
      
        /*! \brief [in] Message queue id of DSP */
      
        uint8_t dsp;
      
      } AsSynthesizerMsgQueId_t;
      /** Pool ID parameter of activate function */
      
      typedef struct
      {
        /*! \brief [in] Memory pool id of output data */
      
        MemMgrLite::PoolId output;
      
        /*! \brief [in] Memory pool id of dsp command data */
      
        MemMgrLite::PoolId dsp;
      
      } AsSynthesizerPoolId_t;
      /** Activate function parameter */
      
      typedef struct
      {
        /*! \brief [in] ID for sending messages to each function */
      
        AsSynthesizerMsgQueId_t msgq_id;
      
        /*! \brief [in] ID of memory pool for processing data */
      
        AsSynthesizerPoolId_t   pool_id;
      
      } AsCreateSynthesizerParam_t;
    • リザルト受信用のcallback

      AudioAttentionCb を設定する。

      typedef void (*AudioAttentionCb)(const ErrorAttentionParam *attparam);
AS_CreateMediaSynthesizer は、起動直後か、AS_DeleteMediaSynthesizer 呼出し後にのみ呼び出し可能です。
5.3.3.3.3. Component Layer の生成

High Level API および Object Level API を使用する場合でも、 Component Layer で使用する各Componentの生成は必要です。各 Component ごとのインスタンス生成とリソース割り当てを行います。

これらを行う場合は、以下の関数を呼ぶ必要があります。

Capture Component の生成
  • 関数名

  • 引数

    • 各リソース(メモリマネージャ、メッセージ)のID
      音声取得(Capture)は、マイク入力とI2Sの2系統の中から2つで選択し実行が可能です。そのため2系統分のリソースの設定を行うことが可能になっています。

1系統のみ使用する場合は、dev0 側のみ設定し、dev0 には null を設定しても問題ありません。
/** Message queue ID parameter of activate function */

typedef struct
{
  /*! \brief [in] Message queue id of capture device0 request */

  uint8_t dev0_req;

  /*! \brief [in] Message queue id of capture device0 for syncronizing */

  uint8_t dev0_sync;

  /*! \brief [in] Message queue id of capture device1 request */

  uint8_t dev1_req;

  /*! \brief [in] Message queue id of capture device1 for syncronizing */

  uint8_t dev1_sync;

} AsCaptureMsgQueId_t;
typedef struct
{
  /*! \brief [in] ID for sending messages to each channels */

  AsCaptureMsgQueId_t msgq_id;

} AsCreateCaptureParam_t;
AS_CreateCapture は、起動直後か、AS_DeleteCapture 呼出し後にのみ呼び出し可能です。
Renderer Component の生成
  • 関数名

  • 引数

    • 各リソース(メモリマネージャ、メッセージ)のID
      音声出力(Render)は、2系統をMixingして出力することが可能です。そのため2系統分のリソースの設定を行うことが可能になっています。

1系統のみ使用する場合は、dev0 側のみ設定し、dev0 には null を設定しても問題ありません。
/** Message queue ID parameter of activate function */

typedef struct
{
  /*! \brief [in] Message queue id of renderer device0 request */

  uint8_t dev0_req;

  /*! \brief [in] Message queue id of renderer device0 for syncronizing */

  uint8_t dev0_sync;

  /*! \brief [in] Message queue id of renderer device1 request */

  uint8_t dev1_req;

  /*! \brief [in] Message queue id of renderer device1 for syncronizing */

  uint8_t dev1_sync;

} AsRendererMsgQueId_t;
typedef struct
{
  /*! \brief ID for sending messages to each channels */

  AsRendererMsgQueId_t msgq_id;

} AsCreateRendererParam_t;
AS_CreateRenderer は、起動直後か、AS_DeleteRenderer 呼出し後にのみ呼び出し可能です。
5.3.3.4. インスタンスの削除

High Level API でのAudio動作が終了し、Audioで使用した様々なリソースの開放やHWの停止および電源Offなどを行うためには、 delete 関数を呼び出す必要があります。

この delete 関数もすべてのレイヤーでのリソースを確保したすべての機能ブロックのインスタンスに対して呼び出す必要があります。以下に各レイヤごとの delete 関数のリストを示します。

5.3.3.4.1. Audio Manager の削除

High Level API を使用を終了する場合、Audio Manager のインスタンス削除とリソース割り当ての解除を行う必要があります。以下の関数を呼ぶことで、これらが実行できます。

AS_DeleteAudioManager は、各種リソースや HWの使用状況によって正しくリース開放やHWの電源Offができなくなってしまうことを防ぐため、Ready状態でのみ呼び出しが可能となります。
5.3.3.4.2. Object Layer の削除

High Level API を使用する場合でも、 Object Layer のリソースの生成・削除が必要になります。Audio機能の終了時に Object Layer のリソースを解放したい場合は、以下の関数を呼ぶ必要があります。

Mic Frontend Object の削減
AS_DeleteMicFrontend は、各種リソースや HWの使用状況によって正しくリース開放やHWの電源Offができなくなってしまうことを防ぐため、High Level API の場合は、Ready状態でのみ呼び出し可能であり、Object Level API の場合は、すべての系統での音声取得動作を停止している時のみ呼び出しが可能になります。
Media Recorder Object の削除
AS_DeleteMediaRecorder は、各種リソースや HWの使用状況によって正しくリース開放やHWの電源Offができなくなってしまうことを防ぐため、High Level API の場合は、Ready状態でのみ呼び出し可能であり、Object Level API の場合は、音声録音動作を停止している時のみ呼び出しが可能になります。
Output Mixer Object の削除
AS_DeleteOutputMix は、各種リソースや HWの使用状況によって正しくリース開放やHWの電源Offができなくなってしまうことを防ぐため、High Level API の場合は、Ready状態でのみ呼び出し可能であり、Object Level API の場合は、すべての系統での音声出力動作を停止している時のみ呼び出しが可能になります。
Multi Player Object の生成
AS_DeletePlayer は、各種リソースや HWの使用状況によって正しくリース開放やHWの電源Offができなくなってしまうことを防ぐため、High Level API の場合は、Ready状態でのみ呼び出し可能であり、Object Level API の場合は、すべての系統での音声再生動作を停止している時のみ呼び出しが可能になります。
Recognizer Object の生成
AS_DeleteRecognizer は、各種リソースや HWの使用状況によって正しくリース開放やHWの電源Offができなくなってしまうことを防ぐため、High Level API の場合は、Ready状態でのみ呼び出し可能であり、Object Level API の場合は、音声認識動作を停止している時のみ呼び出しが可能になります。
Media Synthesizer Object の生成
AS_DeleteMediaSynthesizer は、各種リソースや HWの使用状況によって正しくリース開放やHWの電源Offができなくなってしまうことを防ぐため、High Level API の場合は、Ready状態でのみ呼び出し可能であり、Object Level API の場合は、音声生成動作を停止している時のみ呼び出しが可能になります。
5.3.3.4.3. Component Layer の削除

High Level API および Object Level API を使用する場合でも、 Component Layer で使用する各Componentの生成および削除が必要になります。Audio機能の終了時に Component Layer のリソースを解放したい場合は、以下の関数を呼ぶ必要があります。

Capture Component の削除
AS_DeleteCapture は、各種リソースや HWの使用状況によって正しくリース開放やHWの電源Offができなくなってしまうことを防ぐため、High Level API の場合は、Ready状態でのみ呼び出し可能であり、Object Level API の場合は、 Mic Frontend Object がすべての系統での音声取得動作を停止している時のみ呼び出しが可能になります。
Renderer Component の生成
AS_DeleteCapture は、各種リソースや HWの使用状況によって正しくリース開放やHWの電源Offができなくなってしまうことを防ぐため、High Level API の場合は、Ready状態でのみ呼び出し可能であり、Object Level API の場合は、 Output Mixer Object がすべての系統での音声出力動作を停止している時のみ呼び出しが可能になります。
5.3.3.5. コマンド一覧

各コマンドの一覧は以下になります。
コマンド・ヘッダ にこのコマンドIDを指定し送信することで機能を使用することが出来ます。

5.3.3.5.1. General or Common Command

どの状態でも共通のコマンドです。 どの状態からも呼べます。

表 3. General or common Command List
Command Name Command ID Response Result Description

GetStatus

0x01

NotifyStatus

現在の状態を取得します

詳細は、以下の、Doxygenファイルを参照してください。

5.3.3.5.2. Baseband Initialize Command

Baseband HWの初期化を行うコマンドです。 Ready状態からのみ呼べます。

表 4. Baseband Initialize Command List
Command Name Command ID Response Result Description

InitMicGain

0x53

InitMicGainCmplt

マイクゲインの設定を行います

InitI2SParam

0x54

InitI2SCmplt

I2Sの設定を行います

InitOutputSelect

0x56

InitOutputSelectCmplt

発音するデバイスの設定を行います

InitClearStereo

0x58

InitClearStereoCmplt

クリアステレオ機能の設定を行います

initRenderClk

0x5c

SetRenderingClkCmplt

HiReso設定の切り替えを行います

SetSpDrv

0x5d

SetSpDrvCmplt

スピーカーのドライブ能力の設定を行います

詳細は、以下の、Doxygenファイルを参照してください。

5.3.3.5.3. Baseband Set Command

Baseband HWの設定を行うコマンドです。 PowerOff状態以外の状態から呼べます。

表 5. Baseband Set Command List
Command Name Command ID Response Result Description

SetVolume

0x59

SetVolumeCmplt

発音時のボリュームの設定を行います

SetVolumeMute

0x5a

SetVolumeMuteCmplt

発音ボリュームのMute設定を行います

SetBeep

0x5b

SetBeepCmplt

BEEP音の設定を行います

SetMicMap

0x5e

SetMicMapCmplt

使用するマイクの選択・順番を設定します

詳細は、以下の、Doxygenファイルを参照してください。

5.3.3.5.4. Player Command

Playerの制御を行うコマンドです。 Player状態から呼べます。

表 6. Player Command List
Command Name Command ID Response Result Description

InitPlayer

0x21

InitPlayCmplt

Playerの再生情報を設定します

StartPlayer

0x22

PlayCmplt

バッファの先頭からデコードを行います

StopPlayer

0x23

StopPlayCmplt

バッファの状態に依らずPlayerを停止させます

ClkRecovery

0x24

ClkRecoveryComplete

出音時間の微調整をします

SetDecoderGain

0x25

SetDecoderGainComplete

出音レベルにL/RそれぞれGainをかけます

詳細は、以下の、Doxygenファイルを参照してください。

5.3.3.5.5. Recorder Command

Recorderの制御を行うコマンドです。 Recorder状態から呼べます。

表 7. Recorder Command List
Command Name Command ID Response Result Description

InitRecorder

0x31

InitRecCmplt

音声記録機能を初期化します

StartRecorder

0x32

RecCmplt

音声記録を開始します

StopRecorder

0x33

StopRecCmplt

音声記録を停止します

詳細は、以下の、Doxygenファイルを参照してください。

表 8. recognizer Command List
Command Name Command ID Response Result Description

InitRecognizer

0x43

InitRecognizerCmplt

認識機能を初期化します

StartRecognizer

0x41

StartRecognizerCmplt

認識機能を開始します

StopRecognizer

0x42

StopRecognizerCmplt

認識機能を停止します

詳細は、以下の、Doxygenファイルを参照してください。

5.3.3.5.6. State Transition Command
表 9. State Transition Command List
Command Name Command ID Response Result Description

PowerOn

0x71

StatusChanged

Ready状態へ遷移します

SetPowerOffStatus

0x72

StatusChanged

Power Off 状態へ遷移します

SetBaseBandStatus

0x73

StatusChanged

Baseband状態へ遷移します

SetPlayerStatus

0x74

StatusChanged

Player状態へ遷移します

SetRecorderStatus

0x75

StatusChanged

Recorder状態へ遷移します

SetReadyStartus

0x76

StatusChanged

Ready状態へ遷移します

SetThroughStartus

0x77

StatusChanged

Audio path through状態へ遷移します

SetRecognizerStatus

0x79

StatusChanged

Recognizer状態へ遷移します

詳細は、以下の、Doxygenファイルを参照してください。

5.3.3.6. リザルト一覧

オーディオサブシステムからのリザルト通知です。
リザルト・ヘッダ にこのリザルトIDを格納して応答されます。

5.3.3.6.1. General or Common Result
表 10. General or common result List
Result Name Command ID Trigger Command Description

NotifyStatus

0x01

GetStatus

現在の状態を通知します。

5.3.3.6.2. Baseband Initialize Result
表 11. Baseband Initialize Result List
Result Name Command ID Trigger Command Description

InitMicGainCmplt

0x53

InitMicGain

マイクゲインの設定が完了したことを通知します。

InitI2SCmplt

0x54

InitI2SParam

I2Sの設定が完了したことを通知します。

InitOutputSelectCmplt

0x56

InitOutputSelect

発音するデバイスの設定が完了したことを通知します。

InitClearStereoCmplt

0x58

InitClearStereo

クリアステレオ機能の設定が完了したことを通知します。

SetRenderingClkCmplt

0x5c

InitRenderClk

HiReso設定の切り替えが完了したことを通知します。

SetSpDrvCmplt

0x5d

SetSpDrv

スピーカーのドライブ能力の切り替えが完了したことを通知します。

5.3.3.6.3. Baseband Set Result
表 12. Baseband Set Result List
Result Name Command ID Trigger Command Description

SetVolumeCmplt

0x59

SetVolume

発音時のボリュームの設定が完了したことを通知します。

SetVolumeMuteCmplt

0x5a

SetVolumeMute

発音ボリュームのMute設定が完了したことを通知します。

SetBeepCmplt

0x5b

SetBeep

BEEP音の設定が完了したことを通知します。

SetMicMapCmplt

0x5e

SetMicMap

使用するマイクの選択・順番の設定が完了したことを通知します。

5.3.3.6.4. Player Result
表 13. Player Result List
Result Name Command ID Trigger Command Description

InitPlayCmplt

0x21

InitPlayer

Playerの再生情報設定が完了したことを通知します。

PlayCmplt

0x22

StartPlayer

Playerが動作を開始したことを通知します。

StopPlayCmplt

0x23

StopPlayer

Playerが動作を停止したことを通知します。

ClkRecoveryComplete

0x24

ClkRecovery

出音時間の微調整設定が完了したことを通知します。

SetDecoderGainComplete

0x25

SetDecoderGain

出音レベルL/R Gain設定が完了したことを通知します。

5.3.3.6.5. Recorder Result
表 14. Recorder Result List
Result Name Command ID Trigger Command Description

InitRecCmplt

0x31

nitRecorder

音声記録機能の初期化が完了したことを通知します。

RecCmplt

0x32

StartRecorder

音声記録が開始したことを通知します。

StopRecCmplt

0x33

StopRecorder

音声記録が停止したことを通知します。

5.3.3.6.6. Recognizer Result
表 15. Recognizer Result List
Result Name Command ID Trigger Command Description

InitRecognizerCmplt

0x43

nitRecognizer

認識処理の初期化が完了したことを通知します。

RecognizerCmplt

0x41

StartRecognizer

認識処理が開始したことを通知します。

StopRecognizerCmplt

0x42

StopRecognizer

認識処理が停止したことを通知します。

5.3.3.6.7. State Transition Result
表 16. State Transition Result List
Result Name Command ID Trigger Command Description

StatusChanged

0x71

PowerOn SetPowerOffStatus SetBaseBandStatus SetPlayerStatus SetRecorderStatus SetRecognizerStatus SetReadyStartus

状態遷移が完了したことを通知します。

5.3.3.6.8. Error Notification Result
表 17. Error Notification Result List
Result Name Command ID Trigger Command Description

ErrorResponse

0xf1

エラーが発生したことを通知します。

ErrorAttention

0xf2

内部処理エラーが発生したことを通知します。

5.3.3.7. コマンドパケット詳細
5.3.3.7.1. GetStatus

AudioSubSystem内の状態を取得します。

  • Header

AudioCommandHeader
{
  uint8_t reserved      : 0x00
  uint8_t sub_code      : 0x00
  uint8_t command_code  : 0x01
  uint8_t packet_length : 0x02
}
  • Parameters

有りません。

5.3.3.7.2. InitMicGain

マイクの入力ゲインを設定します。
各マイクのゲインを個別に設定することが出来ます。

  • Header

AudioCommandHeader
{
  uint8_t reserved      : 0x00
  uint8_t sub_code      : 0x00
  uint8_t command_code  : 0x53
  uint8_t packet_length : 0x05
}
  • Parameters

5.3.3.7.3. InitI2SParam

I2Sの入出力に関する設定をします。

  • Header

AudioCommandHeader
{
  uint8_t reserved      : 0x00
  uint8_t sub_code      : 0x00
  uint8_t command_code  : 0x54
  uint8_t packet_length : 0x03
}
  • Parameters

5.3.3.7.4. InitOutputSelect

出力先の設定をします。

  • Header

AudioCommandHeader
{
  uint8_t reserved      : 0x00
  uint8_t sub_code      : 0x00
  uint8_t command_code  : 0x56
  uint8_t packet_length : 0x02
}
  • Parameters

5.3.3.7.5. InitClearStereo

Clear Stereoの設定をします。

  • Header

AudioCommandHeader
{
  uint8_t reserved      : 0x00
  uint8_t sub_code      : 0x00
  uint8_t command_code  : 0x58
  uint8_t packet_length : 0x02
}
  • Parameters

5.3.3.7.6. initRenderClk

HiResoモードの設定を行います。

  • Header

AudioCommandHeader
{
  uint8_t reserved      : 0x00
  uint8_t sub_code      : 0x00
  uint8_t command_code  : 0x5c
  uint8_t packet_length : 0x02
}
  • Parameters

5.3.3.7.7. SetSpDrv(InitSpDrv)

音声のスピーカー出力のモードの設定を行います。

  • Header

AudioCommandHeader
{
  uint8_t reserved      : 0x00
  uint8_t sub_code      : 0x00
  uint8_t command_code  : 0x5d
  uint8_t packet_length : 0x02
}
  • Parameters

    uint8_t  mode;
    ドライブ能力のモードを設定します。
    AsSpDrvMode で定義されたenum値を指定します。
    AS_SP_DRV_MODE_LINEOUT : 拡張ボードのlinoutなど、ヘッドホンやアクティブスピーカーに繋ぐときはこれを指定してください。
    AS_SP_DRV_MODE_1DRIVER : 弱めのドライブ能力に指定します。通常使用しません。
    AS_SP_DRV_MODE_2DRIVER : 強めのドライブ能力に指定します。通常使用しません。
    AS_SP_DRV_MODE_4DRIVER : パッシブスピーカをドライブするときは、これを指定してください。
5.3.3.7.8. SetVolume
  • Header

AudioCommandHeader
{
  uint8_t reserved      : 0x00
  uint8_t sub_code      : 0x00
  uint8_t command_code  : 0x59
  uint8_t packet_length : 0x03
}
  • Parameters

5.3.3.7.9. SetVolumeMute
  • Header

AudioCommandHeader
{
  uint8_t reserved      : 0x00
  uint8_t sub_code      : 0x00
  uint8_t command_code  : 0x5a
  uint8_t packet_length : 0x02
}
  • Parameters

5.3.3.7.10. SetBeep
  • Header

AudioCommandHeader
{
  uint8_t reserved      : 0x00
  uint8_t sub_code      : 0x00
  uint8_t command_code  : 0x5b
  uint8_t packet_length : 0x03
}
  • Parameters

5.3.3.7.11. SetMicMap
  • Header

AudioCommandHeader
{
  uint8_t reserved      : 0x00
  uint8_t sub_code      : 0x00
  uint8_t command_code  : 0x5e
  uint8_t packet_length : 0x03
}
  • Parameters

MicMapの設定は、MIC channel select map の設定 を参照してください。
5.3.3.7.12. InitPlayer
  • Header

AudioCommandHeader
{
  uint8_t reserved      : 0x00
  uint8_t sub_code      : 0x00
  uint8_t command_code  : 0x21
  uint8_t packet_length : 0x09
}
  • Parameters

5.3.3.7.13. StartPlayer
  • Header

AudioCommandHeader
{
  uint8_t reserved      : 0x00
  uint8_t sub_code      : 0x00
  uint8_t command_code  : 0x22
  uint8_t packet_length : 0x02
}
  • Parameters

5.3.3.7.14. StopPlayer
  • Header

AudioCommandHeader
{
  uint8_t reserved      : 0x00
  uint8_t sub_code      : 0x00
  uint8_t command_code  : 0x23
  uint8_t packet_length : 0x02
}
  • Parameters

5.3.3.7.15. ClkRecovery
  • Header

AudioCommandHeader
{
  uint8_t reserved      : 0x00
  uint8_t sub_code      : 0x00
  uint8_t command_code  : 0x24
  uint8_t packet_length : 0x02
}
  • Parameters

5.3.3.7.16. SetDecoderGain
  • Header

AudioCommandHeader
{
  uint8_t reserved      : 0x00
  uint8_t sub_code      : 0x00
  uint8_t command_code  : 0x25
  uint8_t packet_length : 0x02
}
  • Parameters

5.3.3.7.17. InitRecorder
  • Header

AudioCommandHeader
{
  uint8_t reserved      : 0x00
  uint8_t sub_code      : 0x00
  uint8_t command_code  : 0x31
  uint8_t packet_length : 0x0a
}
  • Parameters

5.3.3.7.18. StartRecorder
  • Header

AudioCommandHeader
{
  uint8_t reserved      : 0x00
  uint8_t sub_code      : 0x00
  uint8_t command_code  : 0x32
  uint8_t packet_length : 0x02
}
  • Parameters

有りません。

5.3.3.7.19. StopRecorder
  • Header

AudioCommandHeader
{
  uint8_t reserved      : 0x00
  uint8_t sub_code      : 0x00
  uint8_t command_code  : 0x33
  uint8_t packet_length : 0x02
}
  • Parameters

有りません。

5.3.3.7.20. InitRecognizer
  • Header

AudioCommandHeader
{
  uint8_t reserved      : 0x00
  uint8_t sub_code      : 0x00
  uint8_t command_code  : 0x43
  uint8_t packet_length : 0x0a
}
  • Parameters

5.3.3.7.21. StartRecognizer
  • Header

AudioCommandHeader
{
  uint8_t reserved      : 0x00
  uint8_t sub_code      : 0x00
  uint8_t command_code  : 0x41
  uint8_t packet_length : 0x02
}
  • Parameters

有りません。

5.3.3.7.22. StopRecognizer
  • Header

AudioCommandHeader
{
  uint8_t reserved      : 0x00
  uint8_t sub_code      : 0x00
  uint8_t command_code  : 0x42
  uint8_t packet_length : 0x02
}
  • Parameters

有りません。

5.3.3.7.23. PowerOn
  • Header

AudioCommandHeader
{
  uint8_t reserved      : 0x00
  uint8_t sub_code      : 0x00
  uint8_t command_code  : 0x71
  uint8_t packet_length : 0x02
}
  • Parameters

5.3.3.7.24. SetPowerOffStatus
  • Header

AudioCommandHeader
{
  uint8_t reserved      : 0x00
  uint8_t sub_code      : 0x00
  uint8_t command_code  : 0x72
  uint8_t packet_length : 0x02
}
  • Parameters

有りません。

5.3.3.7.25. SetBaseBandStatus
  • Header

AudioCommandHeader
{
  uint8_t reserved      : 0x00
  uint8_t sub_code      : 0x00
  uint8_t command_code  : 0x73
  uint8_t packet_length : 0x09
}
  • Parameters

5.3.3.7.26. SetPlayerStatus
  • Header

AudioCommandHeader
{
  uint8_t reserved      : 0x00
  uint8_t sub_code      : 0x00
  uint8_t command_code  : 0x75
  uint8_t packet_length : 0x06
}
  • Parameters

5.3.3.7.27. SetRecorderStatus
  • Header

AudioCommandHeader
{
  uint8_t reserved      : 0x00
  uint8_t sub_code      : 0x00
  uint8_t command_code  : 0x76
  uint8_t packet_length : 0x04
}
  • Parameters

5.3.3.7.28. SetReadyStartus
  • Header

AudioCommandHeader
{
  uint8_t reserved      : 0x00
  uint8_t sub_code      : 0x00
  uint8_t command_code  : 0x77
  uint8_t packet_length : 0x02
}
  • Parameters

有りません。

5.3.3.7.29. SetThroughStatus
  • Header

AudioCommandHeader
{
  uint8_t reserved      : 0x00
  uint8_t sub_code      : 0x00
  uint8_t command_code  : 0x78
  uint8_t packet_length : 0x02
}
  • parameters

有りません。

5.3.3.7.30. SetRecognizerStatus
  • Header

AudioCommandHeader
{
  uint8_t reserved      : 0x00
  uint8_t sub_code      : 0x00
  uint8_t command_code  : 0x79
  uint8_t packet_length : 0x02
}
  • parameters

有りません。

5.3.3.8. リザルトパケット詳細
5.3.3.8.1. NotifyStatus

GetStatus を発行すると応答されます。

  • Header

AudioResultHeader
{
  uint8_t reserved      : 0x00
  uint8_t sub_code      : 0x00
  uint8_t result_code   : 0x01
  uint8_t packet_length : 0x02
}
  • Parameters

typedef struct
{
  uint8_t vad_status;
  uint8_t reserved1;
  uint8_t sub_status_info;
  uint8_t status_info;
} NotifyStatus;
vad_status

現在の音声検知状態が入ります。

sub_status_info

現在のサブ状態が入ります。

status_info

現在の状態が入ります。

5.3.3.8.2. InitMicGainCmplt

InitMicGain を発行すると応答されます。

  • Header

AudioResultHeader
{
  uint8_t reserved      : 0x00
  uint8_t sub_code      : 0x00
  uint8_t result_code   : 0x53
  uint8_t packet_length : 0x02
}
  • Parameters

有りません。

5.3.3.8.3. InitI2SCmplt
  • Header

AudioResultHeader
{
  uint8_t reserved      : 0x00
  uint8_t sub_code      : 0x00
  uint8_t result_code   : 0x54
  uint8_t packet_length : 0x02
}
  • Parameters

有りません。

5.3.3.8.4. InitOutputSelectCmplt
  • Header

AudioResultHeader
{
  uint8_t reserved      : 0x00
  uint8_t sub_code      : 0x00
  uint8_t result_code   : 0x56
  uint8_t packet_length : 0x02
}
  • Parameters

有りません。

5.3.3.8.5. InitClearStereoCmplt
  • Header

AudioResultHeader
{
  uint8_t reserved      : 0x00
  uint8_t sub_code      : 0x00
  uint8_t result_code   : 0x58
  uint8_t packet_length : 0x02
}
  • Parameters

有りません。

5.3.3.8.6. SetRenderingClkCmplt
  • Header

AudioResultHeader
{
  uint8_t reserved      : 0x00
  uint8_t sub_code      : 0x00
  uint8_t result_code   : 0x5c
  uint8_t packet_length : 0x02
}
  • Parameters

有りません。

5.3.3.8.7. SetSpDrvCmplt
  • Header

AudioResultHeader
{
  uint8_t reserved      : 0x00
  uint8_t sub_code      : 0x00
  uint8_t result_code   : 0x5d
  uint8_t packet_length : 0x02
}
  • Parameters

有りません。

5.3.3.8.8. SetVolumeCmplt
  • Header

AudioResultHeader
{
  uint8_t reserved      : 0x00
  uint8_t sub_code      : 0x00
  uint8_t result_code   : 0x59
  uint8_t packet_length : 0x02
}
  • Parameters

有りません。

5.3.3.8.9. SetVolumeMuteCmplt
  • Header

AudioResultHeader
{
  uint8_t reserved      : 0x00
  uint8_t sub_code      : 0x00
  uint8_t result_code   : 0x5a
  uint8_t packet_length : 0x02
}
  • Parameters

有りません。

5.3.3.8.10. SetBeepCmplt
  • Header

AudioResultHeader
{
  uint8_t reserved      : 0x00
  uint8_t sub_code      : 0x00
  uint8_t result_code   : 0x5b
  uint8_t packet_length : 0x02
}
  • Parameters

有りません。

5.3.3.8.11. SetMicMapCmplt
  • Header

AudioResultHeader
{
  uint8_t reserved      : 0x00
  uint8_t sub_code      : 0x00
  uint8_t result_code   : 0x5e
  uint8_t packet_length : 0x02
}
  • Parameters

有りません。

5.3.3.8.12. InitPlayCmplt
  • Header

AudioResultHeader
{
  uint8_t reserved      : 0x00
  uint8_t sub_code      : 0x00
  uint8_t result_code   : 0x21
  uint8_t packet_length : 0x02
}
  • Parameters

有りません。

5.3.3.8.13. PlayCmplt
  • Header

AudioResultHeader
{
  uint8_t reserved      : 0x00
  uint8_t sub_code      : 0x00
  uint8_t result_code   : 0x22
  uint8_t packet_length : 0x02
}
  • Parameters

有りません。

5.3.3.8.14. StopPlayCmplt
  • Header

AudioResultHeader
{
  uint8_t reserved      : 0x00
  uint8_t sub_code      : 0x00
  uint8_t result_code   : 0x23
  uint8_t packet_length : 0x02
}
  • Parameters

有りません。

5.3.3.8.15. ClkRecoveryComplete
  • Header

AudioResultHeader
{
  uint8_t reserved      : 0x00
  uint8_t sub_code      : 0x00
  uint8_t result_code   : 0x24
  uint8_t packet_length : 0x02
}
  • Parameters

有りません。

5.3.3.8.16. SetDecoderGainComplete
  • Header

AudioResultHeader
{
  uint8_t reserved      : 0x00
  uint8_t sub_code      : 0x00
  uint8_t result_code   : 0x25
  uint8_t packet_length : 0x02
}
  • Parameters

有りません。

5.3.3.8.17. InitRecCmplt
  • Header

AudioResultHeader
{
  uint8_t reserved      : 0x00
  uint8_t sub_code      : 0x00
  uint8_t result_code   : 0x31
  uint8_t packet_length : 0x02
}
  • Parameters

有りません。

5.3.3.8.18. RecCmplt
  • Header

AudioResultHeader
{
  uint8_t reserved      : 0x00
  uint8_t sub_code      : 0x00
  uint8_t result_code   : 0x32
  uint8_t packet_length : 0x02
}
  • Parameters

有りません。

5.3.3.8.19. StopRecCmplt
  • Header

AudioResultHeader
{
  uint8_t reserved      : 0x00
  uint8_t sub_code      : 0x00
  uint8_t result_code   : 0x33
  uint8_t packet_length : 0x02
}
  • Parameters

有りません。

5.3.3.8.20. StatusChanged
  • Header

AudioResultHeader
{
  uint8_t reserved      : 0x00
  uint8_t sub_code      : 0x00
  uint8_t result_code   : 0x7f
  uint8_t packet_length : 0x02
}
  • Parameters

typedef struct
{
  uint8_t changed_status;
  uint8_t reseved1;
  uint8_t reseved2;
  uint8_t reseved3;
} StatusChangedParam;
changed_status

遷移後の状態が入ります。

5.3.3.8.21. ErrorResponse

コマンド処理でエラーが発生した場合に通知されます。
エラーの詳細はパラメータ領域に格納されます。

  • Header

AudioResultHeader
{
  uint8_t reserved      : 0x00
  uint8_t sub_code      : 0x00
  uint8_t result_code   : 0xf1
  uint8_t packet_length : 0x02
}
  • Parameters

typedef struct
{
  uint32_t error_code;
  uint16_t reserved1;
  uint8_t  sub_module_id;
  uint8_t  module_id;
  uint32_t error_sub_code;
  uint32_t reserved2;
  uint32_t ErrorCommand[];
} ErrorResponseParam;
error_code

エラー内容を示す エラーコード が入ります。

module_id

エラーが発生した モジュールのID が入ります。

sub_module_id

現在使用していません。

error_sub_code

エラーのサブコードが入ります。コマンドにより異なります。

ErrorCommand[]

現在使用していません。

5.3.3.8.22. ErrorAttention

内部処理でエラーが発生した場合に通知されます。

  • Header

AudioResultHeader
{
  uint8_t reserved      : 0x00
  uint8_t sub_code      : 0x00
  uint8_t result_code   : 0xf2
  uint8_t packet_length : 0x0e
}
  • Parameters

typedef struct
{
  uint32_t reserved1;
  uint8_t  error_code;
  uint8_t  cpu_id;
  uint8_t  sub_module_id;
  uint8_t  module_id;
  uint32_t error_att_sub_code;
  uint32_t reserved2;
  uint16_t line_number;
  uint8_t  task_id;
  uint8_t  reserved3;
  uint8_t  error_filename[];
} ErrorAttentionParam;
error_code

エラーの種別を示すコードが通知されます。

module_id

エラーの発生したモジュールのIDが通知されます。

error_att_sub_code

エラーの詳細を示す コード が通知されます。

line_number

エラーの発生したLineが通知されます。

error_filename

エラーの発生したファイル名(最大32byte)が通知されます。

5.3.3.9. メモリ管理とタスク間同期について
5.3.3.9.1. Memory Manager Library

AudioSubSystemは、使用するデータ領域を特殊な管理方法で管理します。 MemoryUtilityのMemoryManagerと呼ばれるライブラリは、Memory Layout定義ファイルのLayout情報に従い、必要なメモリエリアを固定長のメモリプールとして確保します。 このLayout情報は複数定義することができ、Layout番号を指定して切り替えることで、機能ごとの必要メモリを確保することができます。 Layout情報は、Applicationのニーズに従って自由に決めてもらうものになりますが、各機能で最低限必要なリソースはありますので、ご注意ください。

詳細は、Memory Manager のライブラリ説明をご参照ください。

また、各機能に合わせた必要なLayout情報に関しては、各exampleの説明をご参照下さい。

AudioSubSystem内の、各オブジェクトは、必要なメモリエリアのセグメントを指し示すMemHandleのインスタンスを生成することで、それに紐付くメモリセグメントを確保し、そこを利用します。

Get memHandle

データパイプラインの次に位置するオブジェクトに、このMemHandleのインスタンスを渡していくことで、確保されたエリアを次のオブジェクトが使用ることができ、不要になった場合、このインスタンスを破棄することで、メモリ領域が解放されます。

インスタンスはコピーでき、必要なオブジェクトが各自メモリが必要な間インスタンスを確保し、不要になったら各自のタイミングで破棄したとしても、安全にメモリを確保・解放することができます。

Copy memHandle

セグメントの使用が不要になった際、非同期に実行されるオブジェクトは、メモリ管理を意識することなく、インスタンスを破棄することで、暗黙の裡に参照が外れます。

Use memHandle

これにより、非同期オブジェクト間でのメモリ管理を簡便に行っています。 すべての参照がなくなったら、メモリを開放します。

Release memHandle

Layout情報は、Applicationが使うためのヘッダファイル群として、あらかじめ用意する必要があります。 これらのヘッダファイルは、Memory Layout定義ファイル(mem_layout.conf)を作成し、ツールを使うことで、生成されます。

Usage
python3 mem_layout.conf [layout_header] [fence_header] [pool_header]
各引数の説明は下記の通りです。
mem_layout.conf

Memory Layout定義ファイル

layout_header

各種定数値が、C言語のマクロとして出力されるヘッダファイル。この引数を省略した場合、"mem_layout.h"という名前のファイルを生成します。

fence_header

FixedAreaのメモリフェンスアドレスが出力されるヘッダファイル。この引数を省略した場合、"fixed_fence.h"という名前のファイルを生成します。

pool_header

PoolAreaの各種定義が出力されるヘッダファイル。この引数を省略した場合、"pool_layout.h"という名前のファイルを生成します。

5.3.3.9.2. Message Library

このメモリ管理機構を使用するうえで、各タスク間でのクラスオブジェクトの送受信が必要になります。これを実現するため、タスク同期機構にクラスインスタンスの送受信を可能にしたmessageライブラリを用意しており、AudioSubSystemは、これを利用しています。

各タスクにあるオブジェクトに送受信先のIDを付加していくことで、送受信したいタスクへの送信が可能になります。

例えば、送信する場合は、送信先のIDにオブジェクトを送信し、受信側のタスクは、自分のIDの送信要求が発生したときのみ、受信されることになります。 受信するまでは、そのタスクはsleepして待ちます。

これにより、AudioSubSystemは、イベント駆動でのオブジェクト設計を行っています。

Messageに関しては、Messageを使うためのヘッダファイル群をあらかじめ用意する必要があります。 これらのヘッダファイルは、MessageQueueLayout定義ファイル(msgq_layout.conf)を作成し、ツールを使うことで、生成されます。

Usage
python3 msgq_layout.conf [start_address] [size] [id_header] [pool_header]
各引数の説明は下記の通りです。
msgq_layout.conf

Message Layout定義ファイル

start_address

Message領域のアドレス。この引数を省略した場合、"mem_layout.h"から必要なアドレスを自動的に読み込みます。

size

Message領域のサイズ。この引数を省略した場合、"mem_layout.h"から必要なアドレスを自動的に読み込みます。

id_header

MessageQueueIDマクロが出力されるファイル。この引数を省略した場合、"msgq_id.h"という名前のファイルを生成します。

pool_header

MessageQueuePoolの定義が出力されるファイル。この引数を省略した場合、"msgq_pool.h"という名前のファイルを生成します。

詳細は、Message Library のライブラリ説明をご参照ください。

5.3.3.9.3. Simple FIFO Library

AudioSubSystem とユーザアプリケーションとの間でのオーディオデータの受け渡しを行う場合、Simple FIFOを用います。このFIFOは、単純なFIFOであり、特に特筆すべきものはありません。

詳細は、Simple FIFO のライブラリ説明をご参照ください。

5.3.3.10. 各機能の詳細
5.3.3.11. Audio Player Functions

Audio Player の簡単なデータの流れを以下に示します。

Audio Player Dataflow
図 8. Audio Player Dataflow

オーディオ・サブシステムがPlayerModeで動作する場合、User Applicationは、FIFOにESデータを入力します。 一定以上たまった状態で、Playerを起動すると、発音時間に合わせて、このESデータを消費していきます。このFIFOがUnderflowしない限り、音声データは途切れることなく発音します。

Playerは、2つのインスタンスを生成することが可能です。それぞれでデコードした音声は、OutputMixerで、Mixingして発音します。

データフロー内部は、Messageで通信します。 Message通信は、各クライアントごとにIDを持ちます。 Audio Playerの場合、exampleにあるサンプルLayoutをもとに、IDを示すと以下のようになります。

User Application                        : MSGQ_AUD_APP
Audio Manager                           : MSGQ_AUD_MNG
Audio Player0                           : MSGQ_AUD_PLY0
Audio Player1                           : MSGQ_AUD_PLY1           # Set this value when you use player1, in other case, set 0xff.
Output Mixer                            : MSGQ_AUD_OUTPUT_MIX
Audio DSP                               : MSGQ_AUD_DSP
Rendering Component(Audio Player0)      : MSGQ_AUD_RND_PLY0
Rendering Component(Audio Player1)      : MSGQ_AUD_RND_PLY1       # Set this value when you use player1, in other case, set 0xff.
Rendering Component Sync(Audio Player0) : MSGQ_AUD_RND_PLY0_SYNC
Rendering Component Sync(Audio Player1) : MSGQ_AUD_RND_PLY1_SYNC  # Set this value when you use player1, in other case, set 0xff.
Post Filter (Channel0)                  : MSGQ_AUD_PFDSP0
Post Filter (Channel1)                  : MSGQ_AUD_PFDSP1
将来的には、MSGQ_AUD_RND_PLY0/PLY1_SYNCが削除され、APIが変更される可能性があります。
Audio Player Message ID
図 9. Audio Player Message ID

また、各データのデータ領域は、以下になります。

ES Data (Audio Player0)                           : S0_DEC_ES_MAIN_BUF_POOL
ES Data (Audio Player1)                           : S0_DEC_ES_SUB_BUF_POOL    # Set this value when you use player1, in other case, set S0_NULL_POOL.
PCM Data (Audio Player0)                          : S0_REND_PCM_BUF_POOL
PCM Data (Audio Player1)                          : S0_REND_PCM_SUB_BUF_POOL  # Set this value when you use player1, in other case, set S0_NULL_POOL.
Audio Decoder DSP Command                         : S0_DEC_APU_CMD_POOL
SamplingRateConverter Work Buffer (Audio Player0) : S0_SRC_WORK_BUF_POOL
SamplingRateConverter Work Buffer (Audio Player1) : S0_SRC_WORK_SUB_BUF_POOL  # Set this value when you use player1, in other case, set S0_NULL_POOL.
Post Filter PCM Data (Channel0)                   : S0_PF0_PCM_BUF_POOL
Post Filter PCM Data (Channel1)                   : S0_PF1_PCM_BUF_POOL
Post Filter DSP Command (Channel0)                : S0_PF0_APU_CMD_POOL
Post Filter DSP Command (Channel1)                : S0_PF1_APU_CMD_POOL
Audio Player Pool ID
図 10. Audio Player Pool ID

これらのIDを生成時に指定する必要があります。

5.3.3.11.1. How to use
Preparation

"AudioManager", "MediaPlayerObject", "OuputpuMixerObject", "RendererComponent" と呼ばれる
オーディオ・サブシステムを制御するために設計されたソフトウェアコンポーネントで、Audio Player を実現します。

そのため、Playerを実現するには、以下のオブジェクトの生成関数を事前に呼ぶ必要があります。

Create AudioManager

AudioManager を有効にするには、AS_CreateAudioManager(AudioSubSystemIDs, AudioAttentionCb) を呼ぶ必要があります。
AudioSubSystemIDs の中で、Message Library Configuration で定義された MsgQueID を指定する必要があります。
0xFF が指定された項目は使用しないことを意味します。
AudioAttentionCb は、非同期の通知を行うためのコールバック関数を指定します。NULLを指定した場合、通知は行われません。

static void attention_callback(const ErrorAttentionParam *attparam)
{
  ...
}

AudioSubSystemIDs ids;

ids.app         = MSGQ_AUD_APP;
ids.mng         = MSGQ_AUD_MNG;
ids.player_main = MSGQ_AUD_PLY0;
ids.player_sub  = MSGQ_AUD_PLY1;
ids.mixer       = MSGQ_AUD_OUTPUT_MIX;
ids.recorder    = 0xFF;
ids.effector    = 0xFF;
ids.recognizer  = 0xFF;

AS_CreateAudioManager(ids, attention_callback);
Create MediaPlayerObject

MediaPlayerObject を有効にするには、AS_CreatePlayerMulti(AsPlayerId, AsCreatePlayerParams_t, AudioAttentionCb) を呼ぶ必要があります。
AsPlayerId には、2つあるPlayer (AsPlayerIdAS_PLAYER_ID_0, AS_PLAYER_ID_1) のいずれかを指定します。2つのPlayerを使用する場合は、それぞれCreateして下さい。
AsCreatePlayerParams_t の中で、Message Library Configuration で定義された MsgQueID と、Memory Manager Configuration で定義された PoolId を指定する必要があります。
AudioAttentionCb は、非同期の通知を行うためのコールバック関数を指定します。AudioManagerを使用しない場合に指定して下さい。AS_CreateAudioManagerでコールバック関数を登録した場合、NULLを指定した場合は通知は行われません。

static void attention_callback_from_player0(const ErrorAttentionParam *attparam)
{
  ...
}

static void attention_callback_from_player1(const ErrorAttentionParam *attparam)
{
  ...
}

AsCreatePlayerParams_t cparam;

cparam.msgq_id.player = MSGQ_AUD_PLY0;
cparam.msgq_id.mng    = MSGQ_AUD_MNG;
cparam.msgq_id.mixer  = MSGQ_AUD_OUTPUT_MIX
cparam.msgq_id.dsp    = MSGQ_AUD_DSP;
cparam.pool_id.es     = S0_DEC_ES_MAIN_BUF_POOL;
cparam.pool_id.pcm    = S0_REND_PCM_BUF_POOL;
cparam.pool_id.dsp    = S0_DEC_APU_CMD_POOL;
cparam.pool_id.src_work = S0_SRC_WORK_BUF_POOL;

bool act_rst = AS_CreatePlayerMulti(AS_PLAYER_ID_0, &cparam, attention_callback_from_player0);

cparam.msgq_id.player = MSGQ_AUD_PLY1;
cparam.msgq_id.mng    = MSGQ_AUD_MNG;
cparam.msgq_id.mixer  = MSGQ_AUD_OUTPUT_MIX
cparam.msgq_id.dsp    = MSGQ_AUD_DSP;
cparam.pool_id.es     = S0_DEC_ES_SUB_BUF_POOL;
cparam.pool_id.pcm    = S0_REND_PCM_SUB_BUF_POOL;
cparam.pool_id.dsp    = S0_DEC_APU_CMD_POOL;
cparam.pool_id.src_work = S0_SRC_WORK_SUB_BUF_POOL;

act_rst = AS_CreatePlayerMulti(AS_PLAYER_ID_1, &cparam, attention_callback_from_player1);
Create OutputMixerObject

OutputMixerObject を有効にするには、AS_CreateOutputMixer(AsCreateOutputMixParams_t) を呼ぶ必要があります。
AsCreateOutputMixParams_t の中で、AMessage Library Configuration で定義された MsgQueID と、Memory Manager Configuration で定義された PoolId を指定する必要があります。
AudioAttentionCb は、非同期の通知を行うためのコールバック関数を指定します。AudioManagerを使用しない場合に指定して下さい。AS_CreateAudioManagerでコールバック関数を登録した場合、NULLを指定した場合は通知は行われません。

static void attention_callback_from_outputmixer(const ErrorAttentionParam *attparam)
{
  ...
}

AsCreateOutputMixParams_t cparam;

cparam.msgq_id.mixer                   = MSGQ_AUD_OUTPUT_MIX;
cparam.msgq_id.render_path0_filter_dsp = MSGQ_AUD_PFDSP0;
cparam.msgq_id.render_path1_filter_dsp = MSGQ_AUD_PFDSP1;
cparam.pool_id.render_path0_filter_pcm = S0_PF0_PCM_BUF_POOL;
cparam.pool_id.render_path1_filter_pcm = S0_PF1_PCM_BUF_POOL;
cparam.pool_id.render_path0_filter_dsp = S0_PF0_APU_CMD_POOL;
cparam.pool_id.render_path1_filter_dsp = S0_PF1_APU_CMD_POOL;

result = AS_CreateOutputMixer(&output_mix_act_param, attention_callback_from_outputmixer);
Create RendererComponent

RendererComponent を有効にするには、AS_CreateRenderer(AsCreateRendererParam_t) を呼ぶ必要があります。
AsCreateRendererParam_t の中で、Message Library Configuration で定義された MsgQueID と、Memory Manager Configuration で定義された PoolId を指定する必要があります。
もしアプリケーションがPlayerを1つしか使わない場合は、3つめと4つめの引数(dev1_req, dev1_sync)を 0xFF に設定する必要があります。

AsCreateRendererParam_t renderer_act_param;
cparam.msgq_id.dev0_req  = MSGQ_AUD_RND_PLY0;
cparam.msgq_id.dev0_sync = MSGQ_AUD_RND_PLY0_SYNC;
cparam.msgq_id.dev1_req  = MSGQ_AUD_RND_PLY1;
cparam.msgq_id.dev1_sync = MSGQ_AUD_RND_PLY1_SYNC;

result = AS_CreateRenderer(&renderer_act_param);
将来的には、HighLevelAPIでの生成関数は、AudioManagerの生成関数に統合される可能性があります。
Initialize and Status change

必要なオブジェクトが生成されたら、Player動作を行わせるためにAudioのHWの設定や電源On、動作モードの変更などの初期化処理を行います。

以下のコマンドを順に発行することで、実現が可能です。

Power on Audio SubSystem

Audioブロックに電源を入れるために、AUDCMD_POWERON, PowerOnParamコマンドを発行することで、電源を入れてAudioSubSystemの状態をReady状態に遷移します。
enable_sound_effectは、AS_DISABLE_SOUNDEFFECT固定としてください。

コマンド設定例
  AudioCommand command;
  command.header.packet_length = LENGTH_POWERON;
  command.header.command_code  = AUDCMD_POWERON;
  command.header.sub_code      = 0x00;
  command.power_on_param.enable_sound_effect = AS_DISABLE_SOUNDEFFECT;
  AS_SendAudioCommand(&command);
Initialize output device

PowerOnを行い、Ready状態に遷移したら、AUDCMD_INITOUTPUTSELECT, InitOutputSelectParam コマンドでMixerからの出力先の選択を行います。

output_device_selの設定は以下の通りです。

output_device_sel
  AS_OUT_OFF : 出力OFF
  AS_OUT_SP  : スピーカーからの出力
  AS_OUT_I2S : I2Sからの出力
コマンド設定例

下記は、スピーカー出力を行う場合の設定例です。

  AudioCommand command;
  command.header.packet_length = LENGTH_INITOUTPUTSELECT;
  command.header.command_code  = AUDCMD_INITOUTPUTSELECT;
  command.header.sub_code      = 0x00;
  command.init_output_select_param.output_device_sel = AS_OUT_SP;
  AS_SendAudioCommand(&command);
AUDCMD_INITI2SPARAMは未対応です。I2Sの設定はKconfigから変更して下さい。
Set speaker driver mode

スピーカーを駆動するデジタルアンプの駆動能力を、[AUDCMD_SETSPDRVMODE], [SetSpDrvModeParam] コマンドで設定することが出来ます。

駆動能力を示すmodeの設定は以下の通りです。

スピーカーの使用方法に関しては、ハードウェアガイドを参照してください。

mode
  AS_SP_DRV_MODE_LINEOUT : 駆動能力 弱。ライン出力用。
  AS_SP_DRV_MODE_1DRIVER : 駆動能力 中。ヘッドホン出力用。
  AS_SP_DRV_MODE_4DRIVER : 駆動能力 強。スピーカー出力用。
コマンド設定例

下記は、ライン出力を行う場合の設定例です。

  AudioCommand command;
  command.header.packet_length = LENGTH_SETSPDRVMODE;
  command.header.command_code  = AUDCMD_SETSPDRVMODE;
  command.header.sub_code      = 0x00;
  command.set_sp_drv_mode.mode = AS_SP_DRV_MODE_LINEOUT;
  AS_SendAudioCommand(&command);
Change to Player Status

AUDCMD_SETPLAYERSTATUS, SetPlayerStsParam コマンドでAudioSubSystemの状態をPlayer状態に遷移します。

各パラメータの設定は以下の通りです。

active_player
  AS_ACTPLAYER_MAIN : player0のみ再生
  AS_ACTPLAYER_SUB  : player1のみ再生
  AS_ACTPLAYER_BOTH : player0とplayer1をMixして再生
input_device
  AS_SETPLAYER_INPUTDEVICE_RAM:: RAMからの入力(固定)
ram_handler

SimpleFifoのハンドル情報のポインタを指定します。

simple_fifo_handler

CMN_SimpleFifoInitialize()で取得されたハンドラを指定します。

callback_function

PlayerObjectがSimpleFifoから読み出したイベントを通知するCallbackです。読みだしたデータのサイズが通知されます。

notification_threshold_size

PlayerObjectが何バイト読み出した時点で、callbackの通知を行うかを指定します。ここで指定したサイズ以上読みだした際に通知されます。 0を指定すると、PlayerObjectが読みだす度に通知します。

コマンド設定例

下記は、Player0, Player1とも再生するようにした場合の設定例です。 Player0, Player1はそれぞれ別のSimpleFIFOを使ってデータを投入する設定です。

  AsPlayerInputDeviceHdlrForRAM input0_ram_handler;
  input0_ram_handler.simple_fifo_handler         = &input0_handle;
  input0_ram_handler.callback_function           = input0_device_callback;
  input0_ram_handler.notification_threshold_size = 0;

  AsPlayerInputDeviceHdlrForRAM input1_ram_handler;
  input1_ram_handler.simple_fifo_handler         = &input1_handle;
  input1_ram_handler.callback_function           = input1_device_callback;
  input1_ram_handler.notification_threshold_size = 0;
  AudioCommand command;
  command.header.packet_length = LENGTH_SET_PLAYER_STATUS;
  command.header.command_code = AUDCMD_SETPLAYERSTATUS;
  command.header.sub_code = 0x00;
  command.set_player_sts_param.active_player         = AS_ACTPLAYER_BOTH;
  command.set_player_sts_param.player0.input_device  = AS_SETPLAYER_INPUTDEVICE_RAM;
  command.set_player_sts_param.player0.ram_handler   = &input0_ram_handler;
  command.set_player_sts_param.player0.output_device = 0x00;
  command.set_player_sts_param.player1.input_device  = AS_SETPLAYER_INPUTDEVICE_RAM;
  command.set_player_sts_param.player1.ram_handler   = &input1_ram_handler;
  command.set_player_sts_param.player1.output_device = 0x00;
  AS_SendAudioCommand(&command);
player1を利用する場合は、AS_CreatePlayerMulti(AsPlayerId, AsCreatePlayerParams_t, AudioAttentionCb)で、 AS_PLAYER_ID_1 を有効にしてください。
Set volume

出力にスピーカーを設定した場合、AUDCMD_SETVOLUME, SetVolumeParam で音量を設定できます。 各パラメータの設定は以下の通りです。

I2Sでは音量は変更できません。

input1_db

player0の音量。dBを10倍の整数値で設定します。設定範囲は-1020(-102.0dB)から120(+12.0dB)で、ステップ幅5(0.5dB)で設定できます。

input2_db

player1の音量。設定範囲はinput1_dbと同じです。

master_db

player0とplayer1のMix後の音量。設定範囲はinput1_dbと同じです。

コマンド設定例

下記は、Player0を0dB, Player1を0dBにしMasterボリュームは-20dBとした設定例です。

  AudioCommand command;
  command.header.packet_length = LENGTH_SETVOLUME;
  command.header.command_code  = AUDCMD_SETVOLUME;
  command.header.sub_code      = 0;
  command.set_volume_param.input1_db = 0;    /* 0.0dB */
  command.set_volume_param.input2_db = 0;    /* 0.0dB */
  command.set_volume_param.master_db = -200; /* -20.0dB */
  AS_SendAudioCommand(&command);
Diagram
図 11. Initial sequence
Initialize and Start player

音楽再生初期化及び開始シーケンスを示します。

Initialize player

AUDCMD_INITPLAYER, PlayerCommand, AsInitPlayerParam で再生の初期設定を行います。

player_id

AsPlayerIdのインスタンスのIDを設定します。インスタンスは2つあり、どちらかを設定して下さい。

インスタンス番号 設定値

0

AS_PLAYER_ID_0

1

AS_PLAYER_ID_1

codec_type

再生コンテンツのコーデックの種別を設定して下さい。MP3, WAVに対応しています。

コーデック種別 設定値

MP3

AS_CODECTYPE_MP3

WAV

AS_CODECTYPE_WAV

MP3ファイルに関して、すべてのファイルに現時点で対応できていません。現在、ID3v2 TAG(特に画像データのような大きなメタデータ)がある場合、デコーダがparseエラーになります。
MP3Tag などのツールで、タグ情報を削除してください。
bit_length

再生コンテンツの1サンプルあたりのbit長を設定します。16bitと24bitに対応しています。

bit長 設定値

16

AS_BITLENGTH_16

24

AS_BITLENGTH_24

24bitのデコードができるメモリのLayoutが必要です。
channel_number

再生コンテンツのチャンネル数を設定します。モノラル(1ch), ステレオ(2ch)に対応しています。

チャンネル数 設定値

1

AS_CHANNEL_MONO

2

AS_CHANNEL_STEREO

sampling_rate

再生コンテンツのサンプリング周波数を設定します。コーデック種別ごとに設定可能な設定値が異なります。

サンプリング周波数 設定値 対応コーデック種別

16kHz

AS_SAMPLINGRATE_16000

MP3,WAV

32kHz

AS_SAMPLINGRATE_32000

MP3,WAV

44.1kHz

AS_SAMPLINGRATE_44100

MP3,WAV

48kHz

AS_SAMPLINGRATE_48000

MP3,WAV

88.2kHz

AS_SAMPLINGRATE_88200

WAV

96kHz

AS_SAMPLINGRATE_96000

WAV

176.4kHz

AS_SAMPLINGRATE_176400

WAV

192kHz

AS_SAMPLINGRATE_192000

WAV

自動判別

AS_SAMPLINGRATE_AUTO

MP3

AS_SAMPLINGRATE_AUTO は、ストリーム上のSyntaxからサンプリング周波数を自動判定して欲しいときに 使用します。現時点では、MP3のみ対応です。
ハイレゾリューションサンプリングレート、すなわち、AS_SAMPLINGRATE_88200AS_SAMPLINGRATE_96000AS_SAMPLINGRATE_176400 の場合、DSPをDualCore使用しWorking領域も大きく使用するため、Dual Decodeを行おうとする場合、DSP領域だけで384kB必要になります。必要に応じて、SDKのConfigurationを変更しDSP領域を変更して下さい。
dsp_path

DecoderのDSPバイナリイメージを格納している絶対パスを指定します。最大24文字です。

コマンド設定例

下記は、Player0にmp3/16bit/Stereo/48kHzのコンテンツを再生するように初期化した設定例です。 また、再生に使用するデコーダの配置パスはSDカードのBINフォルダを指定しています。

  AudioCommand command;
  command.header.packet_length = LENGTH_INIT_PLAYER;
  command.header.command_code  = AUDCMD_INITPLAYER;
  command.header.sub_code      = 0x00;
  command.player.player_id                 = AS_PLAYER_ID_0;
  command.player.init_param.codec_type     = AS_CODECTYPE_MP3;
  command.player.init_param.bit_length     = AS_BITLENGTH_16;
  command.player.init_param.channel_number = AS_CHANNEL_STEREO;
  command.player.init_param.sampling_rate  = AS_SAMPLINGRATE_48000;
  command.player.init_param.dsp_path       = "/mnt/sd0/BIN";
  AS_SendAudioCommand(&command);
Initialize OutputMixer

AUDCMD_INIT_OUTPUTMIXER, AsInitMixerParam で音声出力の初期設定を行います。

player_id

AsPlayerIdのインスタンスのIDを設定します。インスタンスは2つあり、どちらかを設定して下さい。

postproc_type

PostProcessの種別を設定します。

AsPostprocTypeThrough    : Through,
AsPostprocTypeUserCustom : User Custom Process,
dsp_path

PostProcess用DSPバイナリをファイル名を含むフルパスで指定します。
postproc_type が AsPostprocTypeThrough である場合には使われません。

"/mnt/sd0/BIN/POSTPROC" : POSTPROC SDBIN
"/mnt/spif/POSTPROC"    : POSTPROC SPI-FLASH

PostprocessDSPを使用した信号処理がAudio Player Fuction内でどこに位置するかを下図に示します。

ハイライトされた箇所にあるCustomproc, UserCustomDSPで信号処理をおないます。
ユーザーはこのUserCustomDSPに信号処理を作成、組み込みます。

Audio player postprocess
図 12. Audio Player Postprocess
コマンド設定例

下記は、出力するPlayer0の音声に対して /mnt/sd0/BIN/POSTPROC のユーザーカスタムDSPで信号処理を行う設定の例です。

AudioCommand command;
command.header.packet_length = LENGTH_INIT_OUTPUTMIXER;
command.header.command_code  = AUDCMD_INIT_OUTPUTMIXER;
command.header.sub_code      = 0x00;
command.init_mixer_param.player_id     = AS_PLAYER_0;
command.init_mixer_param.postproc_type = AsPostprocTypeUserCustom;
snprintf(command.init_mixer_param.dsp_path,
         AS_POSTPROC_FILE_PATH_LEN,
         "%s", "/mnt/sd0/BIN/POSTPROC");
AS_SendAudioCommand(&command);
Init PostProcess DSP

AUDCMD_INITMPP, AsInitMediaPlayerPost でPost処理用DSPの初期化をします。

AUDCMD_INIT_OUTPUTMIXERpost_enableAsPostprocTypeThrough にしている場合はこの手順は不要です。
player_id

AsPlayerIdのインスタンスのIDを設定します。インスタンスは2つあり、どちらかを設定して下さい。

addr

初期化コマンドパケットのアドレスです。コマンドのフォーマットはPost処理用DSPに依存します。
設定したアドレス領域は、このAPIの応答まで保持しておく必要があります。

size

初期化コマンドパケットのサイズです。

コマンド設定例

下記は、 initpostcmd データをPostprocessDSPの初期化コマンドとして送信する例です。

InitParam initpostcmd;

AudioCommand command;
command.header.packet_length = LENGTH_INITMPP;
command.header.command_code  = AUDCMD_INITMPP;
command.init_mpp_param.player_id        = AS_PLAYER_ID_0;
command.init_mpp_param.initpp_param.addr = reinterpret_cast<uint8_t *>(&initpostcmd);
command.init_mpp_param.initpp_param.size = sizeof(initpostcmd);
AS_SendAudioCommand(&command);
Start Player

AUDCMD_PLAYPLAYER, PlayerCommandで再生を開始します。 音楽再生を開始するとFIFOから圧縮音声データを読み出し始めます。
このため、音楽生成開始時までに、十分な量の圧縮音声データをFIFOに入力しておくようにしてください。

開始時に、十分な量のデータをFIFOに入力していないと、開始直後にUnderflowしてしまい音声再生が停止してしまいます。
player_id

AsPlayerIdのインスタンスのIDを設定します。AUDCMD_INITPLAYERで初期設定済みのインスタンスIDを 設定して下さい。

インスタンス番号 設定値

0

AS_PLAYER_ID_0

1

AS_PLAYER_ID_1

コマンド設定例

下記は、Player0を再生開始する設定例です。

  AudioCommand command;
  command.header.packet_length = LENGTH_PLAY_PLAYER;
  command.header.command_code  = AUDCMD_PLAYPLAYER;
  command.header.sub_code      = 0x00;
  command.player.player_id     = AS_PLAYER_ID_0;
  AS_SendAudioCommand(&command);
Diagram
図 13. Player State sequence
Stop play

音声再生停止のシーケンスを示します。

Stop Player

AUDCMD_PLAYPLAYER, PlayerCommand, AsStopPlayerParamで再生を停止します。

player_id

AsPlayerIdのインスタンスのIDを設定します。AUDCMD_PLAYPLAYERで再生を停止したいインスタンスIDを指定してください。開始済みのインスタンスIDでなければいけません。

インスタンス番号 設定値

0

AS_PLAYER_ID_0

1

AS_PLAYER_ID_1

stop_mode

AsStopPlayerStopModeの停止モードを設定します。停止モードは通常停止とES終端停止、強制停止の3種類があります。
通常停止は、停止要求のタイミングでできるだけ早く停止します。すなわちFIFOの中身は残っている状態になります。
ES終端停止は、停止要求時点で、FIFOに入っているデータをすべて発音してから停止します。
強制停止は、Audio SubSystem内部でのエラー時に使用されるモードで、アプリケーションからは発行しません。

停止モード 設定値

通常停止

AS_STOPPLAYER_NORMAL

ES終端停止

AS_STOPPLAYER_ESEND

強制停止

AS_STOPPLAYER_FORCIBLY

コマンド設定例

下記は、Player0を通常停止する設定例です。

  AudioCommand command;
  command.header.packet_length = LENGTH_STOP_PLAYER;
  command.header.command_code  = AUDCMD_STOPPLAYER;
  command.header.sub_code      = 0x00;
  command.player.player_id     = AS_PLAYER_ID_0;
  command.player.stop_param.stop_mode = AS_STOPPLAYER_NORMAL;
  AS_SendAudioCommand(&command);
Diagram
図 14. Stop sequence
5.3.3.11.2. Build Configurations

AudioPlayer の機能を使用するためには

cd sdk
tools/config.py -m

でConfig menu を開き、以下のConfigを設定する必要があります。

Select options in below:

[Device Drivers]
  [MMCSD driver support]                   <= Y (If using the SD card)
  [Board specific drivers]
    [CXD56 Audio Driver]                   <= Y

[Application Configuration]
  [Spresense SDK]
    [SDK audio]                            <= Y
      [Audio Utilities]
        [Audio Player]                     <= Y
          [Playlist manager]               <= Y (If use PlayList)

    [Memory Manager]                       <= Y
      [Memory Utilities]                   <= Y

    [ASMP]                                 <= Y
5.3.3.11.3. Error Attentions and Approach

音楽再生時の警告の一覧と、対処方法は以下の通りです。詳細は オーディオサブシステムのエラーについて を参照してください。

ID Attention Code Attention Level Approach

0x05

AS_ATTENTION_SUB_CODE_SIMPLE_FIFO_UNDERFLOW

WARNING

AudioSubSystemが再生データを読み込めなかったことが原因です。再生データをSimpleFIFOにWriteするタスクのCPU占有度を上げてください。

0x0D

AS_ATTENTION_SUB_CODE_MEMHANDLE_ALLOC_ERROR

ERROR

データ領域のセグメント数が不足したことが原因です。AudioSubSystem以外のタスクの優先度を下げるか、データ領域のセグメント数を増やしてください。

0x0F

AS_ATTENTION_SUB_CODE_TASK_CREATE_ERROR

ERROR

ヒープ領域が不足していることが原因です。ヒープ領域を拡張して下さい。

0x18

AS_ATTENTION_SUB_CODE_DSP_VERSION_ERROR

ERROR

DSPバイナリのバージョンが異なることが原因です。DSP バイナリイメージを"sdk/modules/audio/dsp"のファイルで更新して下さい。

0x1A

AS_ATTENTION_SUB_CODE_STREAM_PARSER_ERROR

ERROR

再生ファイルにSync wordが見つからなかったことが原因です。再生ファイルと指定したコーデックが合っているか確認してください。

0x21

AS_ATTENTION_SUB_CODE_ALLOC_HEAP_MEMORY

WARNING

プール領域ではなく、ヒープ領域が使われたことが原因です。Sampling Rate Converterのwork bufferのプール領域(SRC_WORK_BUF_POOL)が設定されているか確認して下さい。

AS_ATTENTION_SUB_CODE_SIMPLE_FIFO_UNDERFLOW が発生した場合、音声再生が停止し、再生エラーの状態になります。 この状態が発生した場合は、直ちにAsStopPlayerParamコマンドを発行し、再生停止状態に遷移させてください。
再生停止に遷移後、FIFOのクリアを必ず行ってください。行わないとノイズが発生してしまいます。
5.3.3.11.4. DSP install
DSP binary image install

DSPバイナリイメージをKconfigで設定したパスに格納して下さい。バイナリイメージは、 sdk/modules/audio/dsp にあります。

表 18. Binary image required for audio player according to configuration:
Image 使用メモリ バイナリサイズ

MP3DEC

128kbyte

61kbyte

WAVDEC

256kbyte

32kbyte

実行時に必要なメモリサイズは、使用メモリ のサイズになります。
ハイレゾリューションサンプリングレートの再生を行う場合、DSPを2 Core(1Coreあたり192kB)使用します。
※2Coreの場合、384kB。
使用するリソースにご注意ください。
5.3.3.11.5. Audio Player Example

音楽再生の簡単なサンプリアプリケーションとして、Audio Player exampleがあります。ここでは、その使い方などを説明します。

Preparation
Build Configurations (kconfig)

Audio Player のサンプルプログラムを使うには、build configurationを以下の設定をしてください。

[Examples]
  [Audio player example] <= Y

または、

cd sdk
tools/config.py examples/audio_player
Audio & Logical sensor example と他の複数のサンプルは同時に選択できません。複数選択するとコンパイルエラーが出ます。
Memory and Message Utility Configurations and Layout

メモリ管理ライブラリ(Memory Manager)とタスク間通信ライブラリ(Message Library)の設定は、以下のように行ってください。

Memory Manager (Intelligent Fix Pool) Configuration

AudioPlayer機能を使用する際に必要となるMemoryLayout(pool)の定義を行う必要があります。
定義はMemoaryLayout定義ファイルで行い、ツールでコードに組み込むヘッダファイルを生成することが出来ます。

Audio Player のexampleでは下記のように行います。

cd examples/audio_player/config
python3 mem_layout.conf

"mem_layout.h", "fixed_fence.h", "pool_layout.h" ファイルが生成されます。
"mem_layout.h"ファイルは、後述する msgq_layout ツールの実行時に参照されます。

MemoaryLayout定義ファイル(mem_layout.conf)の記述内容は下記の通りです。

FixedAreas
FixedAreas
 # name,                  device,     align,        size,         fence
  ["AUDIO_WORK_AREA",     "AUD_SRAM", U_STD_ALIGN,  0x0003e000,   False], # Audio work area
  ["MSG_QUE_AREA",        "AUD_SRAM", U_STD_ALIGN,  0x00001000,   False], # message queue area
  ["MEMMGR_WORK_AREA",    "AUD_SRAM", U_STD_ALIGN,  0x00000200,   False], # MemMgrLite WORK Area
  ["MEMMGR_DATA_AREA",    "AUD_SRAM", U_STD_ALIGN,  0x00000100,   False], # MemMgrLite DATA Area

各パラメータの説明は以下の通りです。

パラメータ 説明

name

領域名(英大文字で始まり、"_AREA"で終わる名称。英大文字, 数字, _が使用可能)

device

領域を確保するMemoryDevicesのデバイス名

align

領域の開始アライメント。0を除くMinAlign(=4)の倍数を指定する

size

領域のサイズ。0を除く4の倍数の値を指定する

fence

フェンスの有効・無効を指定する(この項目は、UseFenceがFalseの場合は無視される)

各nameの用途は以下の通りです。

AUDIO_WORK_AREA

AudioSubSystemが利用する

MSG_QUE_AREA

MessageQueueが利用する(固定名)。msgq_id.hの(MSGQ_END_DRM - MSGQ_TOP_DRAM)のサイズを超えないこと。

MEMMGR_WORK_AREA

Memory Managerが利用する作業領域(固定名, 固定サイズ)

MEMMGR_DATA_AREA

Memery Managerが利用するデータ領域(固定名, 固定サイズ)

各nameの合計のサイズがmpshm_init(), mpshm_remap()で確保するシェアメモリのサイズを超えないようにしてください。

FixedAreasは変更しないでください。
PoolAreas
PoolAreas
 # name,                    area,              align,        pool-size,                    seg,                        fence
  ["DEC_ES_MAIN_BUF_POOL",  "AUDIO_WORK_AREA", U_STD_ALIGN,  U_DEC_ES_MAIN_BUF_POOL_SIZE,  U_DEC_ES_MAIN_BUF_SEG_NUM,  True ],
  ["REND_PCM_BUF_POOL",     "AUDIO_WORK_AREA", U_STD_ALIGN,  U_REND_PCM_BUF_POOL_SIZE,     U_REND_PCM_BUF_SEG_NUM,     True ],
  ["DEC_APU_CMD_POOL",      "AUDIO_WORK_AREA", U_STD_ALIGN,  U_DEC_APU_CMD_POOL_SIZE,      U_DEC_APU_CMD_SEG_NUM,      True ],
  ["SRC_WORK_BUF_POOL",     "AUDIO_WORK_AREA", U_STD_ALIGN,  U_SRC_WORK_BUF_POOL_SIZE,     U_SRC_WORK_BUF_SEG_NUM,     True ],
  ["PF0_PCM_BUF_POOL",      "AUDIO_WORK_AREA", U_STD_ALIGN,  U_POF_PCM_BUF_SIZE,           U_POF_PCM_BUF_SEG_NUM,      True ],
  ["PF1_PCM_BUF_POOL",      "AUDIO_WORK_AREA", U_STD_ALIGN,  U_POF_PCM_BUF_SIZE,           U_POF_PCM_BUF_SEG_NUM,      True ],
  ["PF0_APU_CMD_POOL",      "AUDIO_WORK_AREA", U_STD_ALIGN,  U_DEC_APU_CMD_POOL_SIZE,      U_DEC_APU_CMD_SEG_NUM,      True ],
  ["PF1_APU_CMD_POOL",      "AUDIO_WORK_AREA", U_STD_ALIGN,  U_DEC_APU_CMD_POOL_SIZE,      U_DEC_APU_CMD_SEG_NUM,      True ],

各パラメータの説明は以下の通りです。

パラメータ 説明

name

プール名(英大文字で始まり、"_POOL"で終わる名称。英大文字, 数字, _が使用可能)

area

プール領域として使用するFixedAreaの領域名。領域はRAMに配置されていること

align

プールの開始アライメント。0を除くMinAlign(=4)の倍数を指定する

pool-size

プールのサイズ。0を除く4の倍数の値。Basicプールでは、セグメントサイズ * セグメント数

seg

セグメント数。1以上、255以下の値を指定する

fence

フェンスの有効・無効を指定する。この項目は、UseFenceがFalseの場合は無視される

各nameの用途は以下の通りです。

DEC_ES_MAIN_BUF_POOL

player0用入力データの格納用バッファ領域

REND_PCM_BUF_POOL

player0用Decode済みデータの出力用バッファ領域

DEC_APU_CMD_POOL

DSP(Decoder)用のコマンド領域

SRC_WORK_BUF_POOL

DSP(SamplingRateConverter)のワークバッファ領域

PF0_PCM_BUF_POOL

PostFilter0用のバッファ領域

PF1_PCM_BUF_POOL

PostFilter1用のバッファ領域

PF0_APU_CMD_POOL

PostFilter0用のコマンド領域

PF1_APU_CMD_POOL

PostFilter1用のコマンド領域

それぞれの定義の詳細については、 examples/audio_player/config/mem_layout.confを参照してください。
設定が変わった場合は、ツールを使って新しいヘッダーファイルを生成してください。
Message Library Configuration

AudioPlayer機能を使用する際に必要となるMessageQueueの定義を行う必要があります。 定義はMessageQueueLayout定義ファイルで行い、ツールでコードに組み込むヘッダファイルを生成することが出来ます。

Audio Player のexampleでは下記のように行います。
前述した"mem_layout.h"ファイルが存在している状態で実行してください。

cd examples/audio_player/config
python3 msgq_layout.conf

"msgq_id.h", "msgq_pool.h" ファイルが生成されます。
mem_layout.conf で生成されたファイルを含めて全てのヘッダファイルを include 以下にコピーします。

cd examples/audio_player/config
mv *.h ../include

MessageQueueLayout定義ファイル(msgq_layout.conf)の記述内容は下記の通りです。

MsgQuePool
 # ID,                        n_size  n_num  h_size  h_nums
  ["MSGQ_AUD_MNG",            88,     30,    0,      0],
  ["MSGQ_AUD_APP",            64,      2,    0,      0],
  ["MSGQ_AUD_DSP",            20,      5,    0,      0],
  ["MSGQ_AUD_PFDSP0",         20,      5,    0,      0],
  ["MSGQ_AUD_PFDSP1",         20,      5,    0,      0],
  ["MSGQ_AUD_PLY0",           48,      5,    0,      0],
  ["MSGQ_AUD_PLY1",           48,      5,    0,      0],
  ["MSGQ_AUD_OUTPUT_MIX",     48,      8,    0,      0],
  ["MSGQ_AUD_RND_PLY0",       32,     16,    0,      0],
  ["MSGQ_AUD_RND_PLY0_SYNC",  16,      8,    0,      0],
  ["MSGQ_AUD_RND_PLY1",       32,     16,    0,      0],
  ["MSGQ_AUD_RND_PLY1_SYNC",  16,      8,    0,      0],

各パラメータの説明は以下の通りです。

パラメータ 説明

ID

メッセージキュープールIDの名称を、"MSGQ_"で始まる文字列で指定。

n_size

通常優先度キューの各要素のバイト数(8以上512以下)。固定ヘッダ長(8byte) + パラメタ長を4の倍数で指定する。

n_num

通常優先度キューの要素数(1以上16384以下)。

h_size

高優先度キューの各要素のバイト数(0または、8以上512以下)。未使用時は0を指定すること。

h_num

高優先度キューの要素数(0または、1以上16384以下)。未使用時は0を指定すること。

各IDはAudio Player FunctionsのAudio Player Message IDを参照してください。

n_sizeは最適値となっているため、変更は行わないでください。

n_numも変更の必要はありませんが、他のApplicationでAudioPlayer機能を使う場合は、負荷を考慮して値を増やす必要が出てくる可能性があります。

h_size, h_numsはAudioPlayer機能を優先的に処理したい場合に利用して下さい。

それぞれの定義の詳細については、 examples/audio_player/config/msgq_layout.confを参照してください。
設定が変わった場合は、ツールを使って新しいヘッダーファイルを生成してください。
表 19. Only support the following format
sampling rate PCM bit length channel number CPU frequency lock

mp3

16kHz / 32kHz / 44.1kHz / 48kHz

16bit

1ch / 2ch

High voltage

wav (Low Power)

16kHz / 32kHz / 44.1kHz / 48kHz

16bit

1ch / 2ch

Low voltage

wav

48kHz / 88.4kHz / 96kHz / 176.4kHz / 196kHz

16bit / 24bit

1ch / 2ch

High voltage

DSP and Sound files
Music file

"AUDIO/" ディレクトリをSDカードのルートディレクトリに生成し、 音楽ファイルをコピーしてください。

Playlist

再生したい音楽ファイルのリストを管理します。csv ファイルからデータベースを生成します。ファイル名は "TRACK_DB.CSV" とします。

"PLAYLIST/" ディレクトリを SDカードのルートディレクトリに生成し、"TRACK_DB.CSV" をコピーします。

"TRACK_DB.CSV"のフォーマット
[filename],[artist],[album],[channel number],[bit length],[sampling rate],[file format]
   ABC.mp3,artist1,album1,2,16,44100,mp3
exampleはPlaylistを使う前提となっています。再生されるのはリストの1行目のみです。
Using SPI-Flash instead of SD Card

ファイルシステムに SPI-Flashを使いたい場合、exampleの再生ファイル、Playlist、DSPバイナリイメージのパス指定を"/mnt/spif/*"に変更してください。 また、再生ファイル、Playlist、DSPバイナリイメージを変更したパスにコピーして下さい。

How to execute

NuttShell から player アプリケーションを起動します。

nsh> player

playerアプリケーションが起動し、次のログが表示されます。

Start AudioPlayer example

PlayListの先頭のファイルの再生が開始されます。

sdカードを認識できない場合は、次のエラーログが表示されます。sdカードの状態を確認して下さい。

Error: /mnt/sd0/AUDIO directory path error. check the path!
Error: app_open_contents_dir() failure.
Exit AudioPlayer example

PlayListを認識できない場合は、次のエラーログが表示されます。PlayListのpathが正しいか確認してください。

Track db(playlist) /mnt/sd0/PLAYLIST/TRACK_DB.CSV open error. check paths and files!
/mnt/sd0/PLAYLIST/alias_list_alltrack.bin cannot opened.

PlayFileを認識できない場合は、次のエラーログが表示されます。pathにFileがあるかどうか、またはPlayListとFile名が一致しているかを確認して下さい。

Error: /mnt/sd0/AUDIO/***.mp3 open error. check paths and files!
Error: app_start_player() failure.

SamplingRateConverterのwork bufferのプール領域(SRC_WORK_BUF_POOL)を設定しない場合は、次の警告ログが表示されます。プール領域の代わりにヒープ領域が使用され、フラグメンテーションが発生する可能性があります。AS_CreatePlayerMultiでSRC_WORK_BUF_POOLを設定してください。

Attention: module[5] attention id[1]/code[33] (objects/media_player/media_player_obj.cpp L****)

10秒再生後、Playerアプリケーションは終了します

Exit AudioPlayer example
5.3.3.12. Audio Recorder Functions

Audio Recorder の簡単なデータの流れを以下に示します。

Audio Recorder Dataflow
図 15. Audio Recorder Dataflow.

Audio SubSystemがRecorderModeで動作する場合、User Applicationは、 ESデータを格納するためのFIFOを用意する必要があります。 音声データの記録を開始すると、一定時間動作後、このFIFOに音声データがたまります。この音声データは、指定された圧縮フォーマットにエンコードされており、 音声データをFIFOから適宜読みだし、FIFOから溢れないようにすることで、連続音声データを取得することができます。

Recorderは、HWとしては、2系統キャプチャが可能ですが、現時点では、2つのインスタンスを生成し、2系統記録する機能には未対応です。

User Applicationは、この音声を各システムの要求に合わせて、(例えば、Strageに書き出し記録したり、Connectivityモジュールに送ってクラウド処理するなど。)処理を行うことで、Recorderアプリケーションを実現します。

データフロー内部は、Messageで通信します。 Message通信は、各クライアントごとにIDを持ちます。 Audio Recorderの場合、exampleにあるサンプルLayoutをもとに、IDを示すと以下のようになります。

User Application           : MSGQ_AUD_APP
Audio Manager              : MSGQ_AUD_MNG
Audio Frontend             : MSGQ_AUD_FRONTEND
Audio Recorder             : MSGQ_AUD_RECORDER
Audio Capture Component    : MSGQ_AUD_CAP
Audio DSP                  : MSGQ_AUD_DSP

※MSGQ_AUD_CAP_SYNCは削除されます。

Audio Recorder Message ID
図 16. Audio Recorder Message ID

また、各データのデータ領域は、以下になります。

PCM (Input) Data Buffer    : INPUT_BUF_POOL
ES Data Buffer (for DSP)   : ES_BUF_POOL
PreProcess DSP Command     : PRE_APU_CMD_POOL
Audio Encoder DSP Command  : ENC_APU_CMD_POOL
Audio Recorder Pool ID
図 17. Audio Recorder Pool ID

これらのIDを生成時に指定する必要があります。

5.3.3.12.1. How to use
Preparation

"AudioManager", "MicFrontendObject", "MediaRecorderObject", "CaptureComponent" と呼ばれる オーディオ・サブシステムを制御するために設計されたソフトウェアコンポーネントで、Audio Recorder を実現します。

Create AudioManager

AudioManager を有効にするには AS_CreateAudioManager(AudioSubSystemIDs) を呼ぶ必要があります。
AudioSubSystemIDs の中で、Message Library Configuration で定義された MsgQueID を指定する必要があります。 0xFF が指定された項目は使用しないことを意味します。
AudioAttentionCb は、非同期の通知を行うためのコールバック関数を指定します。NULLを指定した場合、通知は行われません。

static void attention_callback(const ErrorAttentionParam *attparam)
{
  ...
}

AudioSubSystemIDs ids;

ids.app         = MSGQ_AUD_APP;
ids.mng         = MSGQ_AUD_MNG;
ids.player_main = 0xFF;
ids.player_sub  = 0xFF;
ids.micfrontend = MSGQ_AUD_FRONTEND
ids.mixer       = 0xFF;
ids.recorder    = MSGQ_AUD_RECORDER;
ids.effector    = 0xFF;
ids.recognizer  = 0xFF;

AS_CreateAudioManager(ids, attention_callback);
Crate MicFrontendObject

MicFrontendObject を有効にするには AS_CreateMicFrontend(AsCreateMicFrontendParams_t) を呼ぶ必要があります。 Message Library Configuration で定義された MsgQueID と、Memory Manager Configuration で定義された PoolId を指定する必要があります。 MsgQueID のうち dsp、PoolIdのうち output と dspcmd は Preprocess を行う場合のみEffectiveです。そうでない場合は NULL_POOL 指定で構いません。
AudioAttentionCb は、非同期の通知を行うためのコールバック関数を指定します。AudioManagerを使用しない場合に指定して下さい。AS_CreateAudioManagerでコールバック関数を登録した場合、NULLを指定した場合は通知は行われません。

static void attention_callback_from_frontend(const ErrorAttentionParam *attparam)
{
  ...
}

AsCreateMicFrontendParams_t cparam;

cparam.msgq_id.micfrontend = MSGQ_AUD_FRONTEND;
cparam.msgq_id.mng         = MSGQ_AUD_MNG;
cparam.msgq_id.dsp         = MSGQ_AUD_PREDSP;
cparam.pool_id.capin       = S0_INPUT_BUF_POOL;
cparam.pool_id.output      = S0_PREPROC_BUF_POOL; /* When preprocess will not work, can be set to NULL_POOL */
cparam.pool_id.dspcmd      = S0_PRE_APU_CMD_POOL; /* When preprocess will not work, can be set to NULL_POOL */

result = AS_CreateMicFrontend(&cparam, attention_callback_from_frontend);
Create MediaRecorderObject

MediaRecorderObject を有効にするには AS_CreateMediaRecorder(AsCreateRecorderParams_t) を呼ぶ必要があります。 Message Library Configuration で定義された MsgQueID と、Memory Manager Configuration で定義された PoolId を指定する必要があります。
AudioAttentionCb は、非同期の通知を行うためのコールバック関数を指定します。AudioManagerを使用しない場合に指定して下さい。AS_CreateAudioManagerでコールバック関数を登録した場合、NULLを指定した場合は通知は行われません。

static void attention_callback_from_recorder(const ErrorAttentionParam *attparam)
{
  ...
}

AsCreateRecorderParams_t cparam;

cparam.msgq_id.recorder      = MSGQ_AUD_RECORDER;
cparam.msgq_id.mng           = MSGQ_AUD_MNG;
cparam.msgq_id.dsp           = MSGQ_AUD_DSP;
cparam.pool_id.input         = S0_INPUT_BUF_POOL;
cparam.pool_id.output        = S0_ES_BUF_POOL;
cparam.pool_id.dsp           = S0_ENC_APU_CMD_POOL;

result = AS_CreateMediaRecorder(&cparam, attention_callback_from_recorder);
Activate CaptureComponent

CaptureComponent を有効にするには AS_CreateCapture(AsActCaptureParam_t)を呼ぶ必要があります。 Message Library Configuration で定義された MsgQueID と、Memory Manager Configuration で定義された PoolId を指定する必要があります。 もしアプリケーションが 2つ目のチャンネルを使わない場合は、3つめと4つめの引数を 0xFF に設定する必要があります。

AsActCaptureParam_t capture_act_param;

cparam.msgq_id.dev0_req  = MSGQ_AUD_CAP;
cparam.msgq_id.dev0_sync = MSGQ_AUD_CAP_SYNC;
cparam.msgq_id.dev1_req  = 0xFF;
cparam.msgq_id.dev1_sync = 0xFF;

result = AS_CreateCapture(&cparam);
Initialize and Change state

必要なオブジェクトが生成されたら、Recorder動作を行わせるためにAudioのHWの設定や電源On、動作モードの変更などの初期化処理を行います。

以下のコマンドを順に発行することで、実現が可能です。

Power on Audio SubSystem

Audioブロックに電源を入れるために、AUDCMD_POWERON, PowerOnParamコマンドを発行することで、電源を入れてAudioSubSystemの状態をReady状態に遷移します。 

enable_sound_effect

enable_sound_effectは、AS_DISABLE_SOUNDEFFECT固定となります。

AS_DISABLE_SOUNDEFFECT: SoundEffect無効
コマンド設定例
AudioCommand command;
command.header.packet_length = LENGTH_POWERON;
command.header.command_code  = AUDCMD_POWERON;
command.header.sub_code      = 0x00;
command.power_on_param.enable_sound_effect = AS_DISABLE_SOUNDEFFECT;
AS_SendAudioCommand(&command);
Initialize Mic Gain

AUDCMD_INITMICGAINでMicのGainを設定します。

init_mic_gain_param[]

アナログマイクの場合、dB値を10倍にした値を、5の倍数で0(0.0dB)~210(21.0dB)の範囲で設定できます。デフォルト値は0.0dBです。
デジタルマイクの場合、dB値を100倍にした値を、-7850(-78.50dB)~0(0.00dB)の範囲で設定できます。デフォルト値は-78.50dBです。
Gainの値を変更したくない場合は、AS_MICGAIN_HOLD を指定してください。

コマンド設定例

下記は、1ch〜4chの入力に21dBのゲインをかける場合の設定例です。 5ch〜8chの原因は変更しない設定です。

AudioCommand command;
command->header.packet_length = LENGTH_INITMICGAIN;
command->header.command_code  = AUDCMD_INITMICGAIN;
command->header.sub_code      = 0;
command->init_mic_gain_param.mic_gain[0] = 210;
command->init_mic_gain_param.mic_gain[1] = 210;
command->init_mic_gain_param.mic_gain[2] = 210;
command->init_mic_gain_param.mic_gain[3] = 210;
command->init_mic_gain_param.mic_gain[4] = AS_MICGAIN_HOLD;
command->init_mic_gain_param.mic_gain[5] = AS_MICGAIN_HOLD;
command->init_mic_gain_param.mic_gain[6] = AS_MICGAIN_HOLD;
command->init_mic_gain_param.mic_gain[7] = AS_MICGAIN_HOLD;
AS_SendAudioCommand(&command);

mic_gain[]の各要素はマイクのIDに対応しています。マイクのIDはConfigの"MIC channel select map"の値で設定されます。デフォルトの設定は、アナログマイク1/2/3/4が設定されています。

以下に、configrationの情報を記載します。

MIC channel select map の設定
[Device Drivers]
  [Board specific drivers]
    [CXD56 Audio Driver]
      [Audio baseband config settings]
        [CXD5247 settings]
          (0xFFFF4321) MIC channel select map

"MIC channel select map"の値は4bitごとにMICのIDを示します。
mic_gainの要素と"MIC channel select map"のbitフィールドの関係は下記の通りです。

mic_gainの要素 [7] [6] [5] [4] [3] [2] [1] [0]

bitフィールド

31-28

27-24

23-20

19-16

15-12

11-8

7-4

3-0

"MIC channel select map"の値(ID)とマイクの種別の関係は下記の通りです。

HEX値(ID) マイク種別

0x1

CXD5247アナログマイク1

0x2

CXD5247アナログマイク2

0x3

CXD5247アナログマイク3

0x4

CXD5247アナログマイク4

0x5

CXD5247デジタルマイク1

0x6

CXD5247デジタルマイク2

0x7

CXD5247デジタルマイク3

0x8

CXD5247デジタルマイク4

0x9

CXD5247デジタルマイク5

0xA

CXD5247デジタルマイク6

0xB

CXD5247デジタルマイク7

0xC

CXD5247デジタルマイク8

使用するマイクを要素0から順に設定して下さい。要素番号をSkipして設定することはできません。 アナログマイクとデジタルマイクの混合は対応していません。 アナログマイクを設定する場合は要素0-3を設定して下さい。 要素が偶数の場合、Lチャンネル、要素が奇数の場合、Rチャンネルとなります。

Change to Recorder Status

AUDCMD_SETRECORDERSTATUSでAudioSubSystemの状態をRecorder状態に遷移します。

input_device

記録対象の入力デバイスを指定します。AUDCMD_INITMICGAINで設定したマイク種別と合わせる必要があります。

AS_SETRECDR_STS_INPUTDEVICE_MIC_A  : CXD5247アナログマイク
AS_SETRECDR_STS_INPUTDEVICE_MIC_D  : CXD5247デジタルマイク
input_device_handler

現時点では0固定です。

output_device

エンコードしたESデータの出力先デバイスを指定します。
現時点ではRAMデバイスの出力のみサポートされます。

AS_SETRECDR_STS_OUTPUTDEVICE_RAM : RAMデバイスへ出力
output_device_handler

出力(Encoded ES data)の格納先SimpleFIFOのハンドラを指定します。
simple_fifo_handlerは、CMN_SimpleFifoInitialize()で取得されます。

コマンド設定例

下記は、マイク入力をSimpleFIFOに記録する場合の設定例です。

AudioCommand command;
command.header.packet_length = LENGTH_SET_RECORDER_STATUS;
command.header.command_code  = AUDCMD_SETRECORDERSTATUS;
command.header.sub_code      = 0x00;
command.set_recorder_status_param.input_device          = AS_SETRECDR_STS_INPUTDEVICE_MIC_A;
command.set_recorder_status_param.input_device_handler  = 0x00;
command.set_recorder_status_param.output_device         = AS_SETRECDR_STS_OUTPUTDEVICE_RAM;
command.set_recorder_status_param.output_device_handler = &s_recorder_info.fifo.output_device;
AS_SendAudioCommand(&command);
Start Recording

音声記録開始シーケンスを示します。

Init mic frontend

AUDCMD_INIT_MICFRONTEND, MicFrontendCommand, AsInitMicFrontEndでフロントエンド動作(音声の取り込みなど)の設定をします。

ch_num
AS_CHANNEL_MONO   : Monoral
AS_CHANNEL_STEREO : Stereo
AS_CHANNEL_4CH    : 4ch
AS_CHANNEL_6CH    : 6ch
AS_CHANNEL_8CH    : 8ch
bit_length
AS_BITLENGTH_16 : 16bit
AS_BITLENGTH_24 : 24bit
samples
/* 1フレームのサンプル数を指定します。 */
out_fs

MicFrontendから出力する音声のサンプリングレートを指定します。
preproc_typeAsMicFrontendPreProcSrc の時のみ有効です。

AS_SAMPLINGRATE_8000  : 8kHz
AS_SAMPLINGRATE_16000 : 16kHz
AS_SAMPLINGRATE_44100 : 44.1kHz
AS_SAMPLINGRATE_48000 : 48kHz
...
...
AS_SAMPLINGRATE_192000 : 192kHz
preproc_type

PreProcessの種別を設定します。

AsMicFrontendPreProcThrough       : Through
AsMicFrontendPreProcSrc           : Sampling Rate Converter
AsMicFrontendPreProcUserCustom    : User Custom Process
AsMicFrontendPreProcSrc を指定する場合は sdk/modules/audio/DSP/ にある SRC が必要です。
preprocess_dsp_path

PreProcess用DSPバイナリをファイル名を含むフルパスで指定します。
preproc_type が AsMicFrontendPreProcThrough である場合には使われません。

"/mnt/sd0/BIN/PREPROC" : PREPROC というバイナリをSDカードのBINフォルダに置く場合
"/mnt/spif/SRC"        : SRC というバイナリをSPI-FLASHの直下に置く場合
data_dest

MicFrontendObjectからのAudioデータの出力先を指定します。

AsMicFrontendDataToRecorder   : Send to Recorder
AsMicFrontendDataToRecognizer : Send to Recognizer

PreprocessDSPを使用した信号処理がAudio Recorder Function内でどこに位置するかを下図に示します。

ハイライトされた箇所にあるCustomproc, UserCustomDSPで信号処理を行います。
ユーザーはこのUserCustomDSPに信号処理を作成、組み込みます。

Audio recorder preprocess
図 18. Audio Recorder Preprocess
コマンド設定例

下記は、Mono/16bit/768sample per frameで音声をキャプチャする場合の設定例です。
Pre処理はUserCustomのDSPで行い、そのDSP用バイナリファイルはSDカードのBINフォルダに配置します。
また、キャプチャした音声はRecorderに使う設定としています。

AudioCommand command;
command.header.packet_length = LENGTH_INIT_MICFRONTEND;
command.header.command_code  = AUDCMD_INIT_MICFRONTEND;
command.header.sub_code      = 0x00;
command.init_micfrontend_param.ch_num       = AS_CHANNEL_MONO
command.init_micfrontend_param.bit_length   = AS_BITLENGTH_16;
command.init_micfrontend_param.sample       = 768; /* この値はCodecにあわせて設定して下さい。 */
command.init_micfrontend_param.outfs        = AS_SAMPLINGRATE_16000;
command.init_micfrontend_param.preproc_type = AsMicFrontendPreProcUserCustom;
snprintf(command.init_micfrontend_param.preprocess_dsp_path,
         AS_PREPROCESS_FILE_PATH_LEN,
         "%s", "/mnt/sd0/BIN/PREPROC");
command.init_micfrontend_param.data_dest = AsMicFrontendDataToRecorder;
Init PreProcess DSP

AUDCMD_INIT_PREPROCESS_DSP, AsInitRecorderParamでPre処理用DSPの初期化をします。

AUDCMD_INIT_MICFRONTENDpreproc_typeAsMicFrontendPreProcThrough にしている場合はこの手順は不要です。
packet_addr

初期化コマンドパケットのアドレスです。コマンドのフォーマットはPre処理用DSPに依存します。
設定したアドレス領域は、このAPIの応答まで保持しておく必要があります。

packet_size

初期化コマンドパケットのサイズです。

コマンド設定例

下記は、s_initparamのデータをDSPの初期化コマンドとして送信する例です。

static uint8_t s_initparam = 0;

AudioCommand command;
command.header.packet_length = LENGTH_INIT_PREPROCESS_DSP;
command.header.command_code  = AUDCMD_INIT_PREPROCESS_DSP;
command.header.sub_code      = 0x00;
command.init_preproc_param.packet_addr = reinterpret_cast<uint8_t *>(&s_initparam);
command.init_preproc_param.packet_size = sizeof(s_initparam);
AS_SendAudioCommand(&command);
Init recorder information

AUDCMD_INITREC, RecorderCommand, AsInitRecorderParamで記録動作の設定をします。

sampling_rate
AS_SAMPLINGRATE_8000  : 8kHz
AS_SAMPLINGRATE_16000 : 16kHz
AS_SAMPLINGRATE_48000 : 48kHz
channel_number
AS_CHANNEL_MONO   : Monoral
AS_CHANNEL_STEREO : Stereo
AS_CHANNEL_4CH    : 4ch
AS_CHANNEL_6CH    : 6ch
AS_CHANNEL_8CH    : 8ch
bit_length
AS_BITLENGTH_16 : 16bit
AS_BITLENGTH_24 : 24bit
codec_type
AS_CODECTYPE_MP3  : MP3
AS_CODECTYPE_LPCM : LinearPCM
bitrate

MP3エンコード時のみ有効

AS_BITRATE_8000   : 8000
AS_BITRATE_16000  : 16000
AS_BITRATE_24000  : 24000
AS_BITRATE_32000  : 32000
AS_BITRATE_40000  : 40000
AS_BITRATE_48000  : 48000
AS_BITRATE_56000  : 56000
AS_BITRATE_64000  : 64000
AS_BITRATE_80000  : 80000
AS_BITRATE_96000  : 96000
AS_BITRATE_112000 : 112000
AS_BITRATE_128000 : 128000
AS_BITRATE_144000 : 144000
AS_BITRATE_160000 : 160000
AS_BITRATE_192000 : 192000
AS_BITRATE_224000 : 224000
AS_BITRATE_256000 : 256000
AS_BITRATE_320000 : 320000
dsp_path

EncoderまたはFilterのDSPイメージを格納している絶対パスを指定します。最大24文字です。

入力デバイスとch数の組み合わせは制限が有ります。
入力 ch数

Mic

1ch(Monoral), 2ch(Stereo), 4ch(*1), 6ch(*2), 8ch(*2)

  • (*1. LPCMのみ)

  • (*2. LPCMかつDigitalMic使用時のみ)

Codec, bit長, サンプリング周波数, ビットレートの組み合わせには制限が有ります。
Codec bit長 サンプリング周波数 ビットレート

MP3

16bit

16kHz

8000(*1), 16000 ~ 32000

48kHz

32000 ~ 2560000

LPCM

16bit

16kHz, 48kHz

-

24bit(*2)

16kHz, 48kHz, 192kHz(*2)

-

  • (*1. 1ch指定時)

  • (*2. 要 HiResoモード指定)

コマンド設定例

下記は、16kHz/Mono/LPCMで記録を行う際の設定例です。 エンコードに使用するDSP用のバイナリは、SDカードのBINフォルダに配置します。

AudioCommand command;
command.header.packet_length = LENGTH_INIT_RECORDER;
command.header.command_code  = AUDCMD_INITREC;
command.header.sub_code      = 0x00;
command.recorder.init_param.sampling_rate  = AS_SAMPLINGRATE_16000;
command.recorder.init_param.channel_number = AS_CHANNEL_MONO;
command.recorder.init_param.bit_length     = AS_BITLENGTH_16;
command.recorder.init_param.codec_type     = AS_CODECTYPE_LPCM;
command.recorder.init_param.bitrate        = AS_BITRATE_8000;
command.recorder.init_param.computational_complexity = AS_INITREC_COMPLEXITY_0
command.recorder.init_param.dsp_path       = "/mnt/sd0/BIN";
Diagram
図 19. 記録初期化シーケンス
Start Recorder

AUDCMD_STARTRECで記録を開始します。

記録を開始して少しすると、Audio Systemは、FIFOにESデータを書き込みます。 正しく音声データを記録するためには、書き込んだデータをFIFOがあふれる前に読み出す必要があります。
データの書き込みに関しては、通知されますので、このイベントに合わせて適宜読み出してください。

FIFOがFullの場合、Audio Systemは、書き込むことができないため、書き込めない音声データを破棄してしまいます。そのため、そのまま記録すると音声データとしては不連続の音声になってしまうことになります。
コマンド設定例
AudioCommand command;
command.header.packet_length = LENGTH_START_RECORDER;
command.header.command_code  = AUDCMD_STARTREC;
command.header.sub_code      = 0x00;
AS_SendAudioCommand(&command)
Diagram
図 20. 記録シーケンス
Stop Rec
Stop Recorder.

AUDCMD_STOPRECで記録を停止します。 停止指示を受けた時点でキャプチャしている音声データまで、Encodeした時点で、Recorderは停止します。

コマンド設定例
AudioCommand command;
command.header.packet_length = LENGTH_STOP_RECORDER;
command.header.command_code  = AUDCMD_STOPREC;
command.header.sub_code      = 0x00;
AS_SendAudioCommand(&command)
Diagram
図 21. 記録停止シーケンス
5.3.3.12.2. Build Configurations

AudioRecorderの機能を使用するために

cd sdk/
tools/config.py -m

でConfig menuを開き、以下のConfigを設定する必要が有ります。

Select options in below:

:(Select audio recorder)
[Device Drivers]
  [MMCSD driver support]                   <= Y (If using the SD card)
  [Board specific drivers]
    [CXD56 Audio Driver]                   <= Y

[Application Configuration]
  [Spresense SDK]
    [SDK audio]                            <= Y
      [Audio Utilities]
        [Audio Recorder]                   <= Y

    [Memory Manager]                       <= Y
      [Memory Utilities]                   <= Y

    [ASMP]                                 <= Y
5.3.3.12.3. Error Attentions and Approach

音声録音時の警告の一覧と、対処方法は以下の通りです。詳細は オーディオサブシステムのエラーについて を参照してください。

ID Attention Code Attention Level Approach

0x06

AS_ATTENTION_SUB_CODE_SIMPLE_FIFO_OVERFLOW

WARNING

AudioSubSystemが録音データををSimpleFIFOに出力できなかったことが原因です。録音データをSimpleFIFOから取得するタスクのCPU占有度を上げてください。

0x0D

AS_ATTENTION_SUB_CODE_MEMHANDLE_ALLOC_ERROR

ERROR

データ領域のセグメント数が不足したことが原因です。AudioSubSystem以外のタスクの優先度を下げるか、データ領域のセグメント数を増やしてください。

0x0F

AS_ATTENTION_SUB_CODE_TASK_CREATE_ERROR

ERROR

ヒープ領域が不足していることが原因です。ヒープ領域を拡張して下さい。

0x18

AS_ATTENTION_SUB_CODE_DSP_VERSION_ERROR

ERROR

DSPバイナリのバージョンが異なることが原因です。DSP バイナリイメージを"sdk/modules/audio/dsp"のファイルで更新して下さい。

5.3.3.12.4. DSP install
DSP binary image install

DSPバイナリイメージをKconfigで設定したパスに格納して下さい。バイナリイメージは、 sdk/modules/audio/dsp にあります。

表 20. Binary image required for audio recorder according to configuration
Image 使用メモリ バイナリサイズ

MP3ENC

256kbyte

111kbyte

SRC (Sampling Rate Converter)

128kbyte

21kbyte

実行時に必要なメモリサイズは、使用メモリ のサイズになります。
LPCM は、圧縮処理を必要としていませんが、出力周波数によっては周波数変換処理が必要なため、SRC (Sampling Rate Converter) のDSPのloadが必要になります。
5.3.3.12.5. Audio Recorder Example

単純なRecorder Exampleがあり、Recorder動作を確認することが出来ます。

Preparation
Build Configuration (kconfig)

Audio Recorder のサンプルプログラムを使うには、以下の設定を行って下さい。

audio_recorderのconfigを読み込みます。

cd sdk/
tools/config.py examples/audio_recorder

Audio recorderが有効になっていることを確認します。

tools/config.py -m
(audio recorder:)
[Examples]
  [Audio recorder example] <= Y
Audio & Logical sensor example と他の複数のサンプルは同時に選択できません。複数選択するとコンパイルエラーが出ます。
Only support the following format:

詳細はStart Recの項目を参照して下さい。

Memory Utility Configurations and Layout
Memory Manager (Intelligent Fix Pool) Configuration

AudioRecorder機能を使用する際に必要となるMemoryLayout(pool)の定義を行う必要があります。
定義はMemoaryLayout定義ファイルで行い、ツールでコードに組み込むヘッダファイルを生成することが出来ます。

Audio Recorder Example では下記のように行います。

cd examples/audio_recorder/config
python3 mem_layout.conf

"mem_layout.h", "fixed_fence.h", "pool_layout.h" ファイルが生成されます。
"mem_layout.h"ファイルは、後述する msgq_layout ツールの実行時に参照されます。

MemoaryLayout定義ファイル(mem_layout.conf)の記述内容は下記の通りです。

FixedAreas
FixedAreas
 # name,                  device,     align,        size,         fence
  ["AUDIO_WORK_AREA",     "AUD_SRAM", U_STD_ALIGN,  0x0003d000,   False],
  ["MSG_QUE_AREA",        "AUD_SRAM", U_STD_ALIGN,  0x00002000,   False],
  ["MEMMGR_WORK_AREA",    "AUD_SRAM", U_STD_ALIGN,  0x00000200,   False],
  ["MEMMGR_DATA_AREA",    "AUD_SRAM", U_STD_ALIGN,  0x00000100,   False],

各パラメータの説明は以下の通りです。

パラメータ 説明

name

領域名(英大文字で始まり、"_AREA"で終わる名称。英大文字, 数字, _が使用可能)

device

領域を確保するMemoryDevicesのデバイス名

align

領域の開始アライメント。0を除くMinAlign(=4)の倍数を指定する

size

領域のサイズ。0を除く4の倍数の値を指定する

fence

フェンスの有効・無効を指定する(この項目は、UseFenceがFalseの場合は無視される)

各nameの用途は以下の通りです。

AUDIO_WORK_AREA

AudioSubSystemが利用する

MSG_QUE_AREA

MessageQueueが利用する(固定名)。msgq_id.hの(MSGQ_END_DRM - MSGQ_TOP_DRAM)のサイズを超えないこと。

MEMMGR_WORK_AREA

Memory Managerが利用する作業領域(固定名, 固定サイズ)

MEMMGR_DATA_AREA

Memery Managerが利用するデータ領域(固定名, 固定サイズ)

各nameの合計のサイズがmpshm_init(), mpshm_remap()で確保するシェアメモリのサイズを超えないようにしてください。

Fixed Areas can not be customized
PoolAreas
PoolAreas
 # name,                    area,              align,        pool-size,  seg, fence
  ["ES_BUF_POOL",           "AUDIO_WORK_AREA", U_STD_ALIGN,  0x0000F000, 5,   True ],
  ["PREPROC_BUF_POOL",      "AUDIO_WORK_AREA", U_STD_ALIGN,  0x0000F000, 5,   True ],
  ["INPUT_BUF_POOL",        "AUDIO_WORK_AREA", U_STD_ALIGN,  0x0000F000, 5,   True ],
  ["ENC_APU_CMD_POOL",      "AUDIO_WORK_AREA", U_STD_ALIGN,  0x00000114, 3,   True ],
  ["SRC_APU_CMD_POOL",      "AUDIO_WORK_AREA", U_STD_ALIGN,  0x00000114, 3,   True ],
  ["PRE_APU_CMD_POOL",      "AUDIO_WORK_AREA", U_STD_ALIGN,  0x00000114, 3,   True ],

各パラメータの説明は以下の通りです。

パラメータ 説明

name

プール名(英大文字で始まり、"_POOL"で終わる名称。英大文字, 数字, _が使用可能)

area

プール領域として使用するFixedAreaの領域名。領域はRAMに配置されていること

align

プールの開始アライメント。0を除くMinAlign(=4)の倍数を指定する

pool-size

プールのサイズ。0を除く4の倍数の値。Basicプールでは、セグメントサイズ * セグメント数

seg

セグメント数。1以上、255以下の値を指定する

fence

フェンスの有効・無効を指定する。この項目は、UseFenceがFalseの場合は無視される

各nameの用途は以下の通りです。

ES_BUF_POOL

入力音声をエンコードした結果の格納バッファ領域

INPUT_BUF_POOL

記録する音声データの入力格納バッファ領域

ENC_APU_CMD_POOL

Encoder DSPとの通信コマンドバッファ領域

SRC_APU_CMD_POOL

SRC DSPとの通信コマンドバッファ領域の通信

それぞれの定義の詳細については、 examples/audio_recorder/config/mem_layout.confを参照してください。
設定が変わった場合は、ツールを使って新しいヘッダーファイルを生成してください。
Message Library Configuration

AudioRecorder機能を使用する際に必要となるMessageQueueの定義を行う必要があります。 定義はMessageQueueLayout定義ファイルで行い、ツールでコードに組み込むヘッダファイルを生成することが出来ます。

Audio Recorder Example では下記のように行います。
前述した"mem_layout.h"ファイルが存在している状態で実行してください。

cd examples/audio_recorder/config
python3 msgq_layout.conf

"msgq_id.h", "msgq_pool.h" ファイルが生成されます。
mem_layout.conf で生成されたファイルを含めて全てのヘッダファイルを include 以下にコピーします。

cd examples/audio_recorder/config
mv *.h ../include

MessageQueueLayout定義ファイル(msgq_layout.conf)の記述内容は下記の通りです。

MsgQuePool
 # ID,                           n_size  n_num  h_size  h_num
  ["MSGQ_AUD_MGR",               88,     30,    0,      0],
  ["MSGQ_AUD_APP",               64,      2,    0,      0],
  ["MSGQ_AUD_DSP",               20,      5,    0,      0],
  ["MSGQ_AUD_RECORDER",          48,      5,    0,      0],
  ["MSGQ_AUD_CAP",               24,     16,    0,      0],
  ["MSGQ_AUD_CAP_SYNC",          16,      8,    0,      0],
  ["MSGQ_AUD_FRONTEND",          48,     10,    0,      0],
  ["MSGQ_AUD_PREDSP",            20,      5,    0,      0],

各パラメータの説明は以下の通りです。

パラメータ 説明

ID

メッセージキューIDの名称を、"MSGQ_"で始まる文字列で指定。

n_size

通常優先度キューの各要素のバイト数(8以上512以下)。固定ヘッダ長(8byte) + パラメタ長を4の倍数で指定する。

n_num

通常優先度キューの要素数(1以上16384以下)。

h_size

高優先度キューの各要素のバイト数(0または、8以上512以下)。未使用時は0を指定すること。

h_num

高優先度キューの要素数(0または、1以上16384以下)。未使用時は0を指定すること。

各IDの用途は以下の通りです。

MSGQ_AUD_MNG

AudioManagerのコマンド受信に利用する

MSGQ_AUD_APP

Applicationがコマンドの応答受信に利用する

MSGQ_AUD_DSP

DSP(Decorder)からの応答受信に利用する

MSGQ_AUD_RECORDER

MediaRecorderObjectのコマンド受信に利用する

MSGQ_AUD_CAP

CaptureComponentのコマンド受信に利用する

MSGQ_AUD_CAP_SYNC

CaptureComponentの内部同期処理に利用する

それぞれの定義の詳細については、 examples/audio_recorder/config/msgq_layout.confを参照してください。
設定が変わった場合は、ツールを使って新しいヘッダーファイルを生成してください。
How to execute

NuttShell から Recorder アプリケーションを起動します。

nsh>recorder

Audio Recorderアプリケーションが起動し記録が開始されます。
記録ファイルは "/mnt/sd0/REC/YYMMDD_HHMMSS.mp3"となります。

Start AudioRecorder example

10秒記録後、AudioRecorderアプリケーションは終了します。

Exit AudioRecorder example
5.3.3.13. Audio Recognizer Functions

Audio Recognizer の簡単なデータの流れを以下に示します。

Audio Recognizer Dataflow
図 22. Audio Recognizer Dataflow.

Audio Recognizer Function は音声認識機能を実現するためのフレームワークを提供します。

認識動作を開始すると、音声データのキャプチャを開始し、Pre処理を行ったのち認識ライブラリへ音声データを投入します。
Pre処理では、音声認識ライブラリの要求する入力フォーマットに合わせて音声データに必要な処理(サンプリングレート変換やノイズ抑制など)を施します。
音声認識ライブラリにキャプチャした音声をそのまま入力出来るのであれば、Pre処理はスルー設定で構いません。
キャプチャしPre処理を施した音声データは音声認識ライブラリに投入されます。
結果が出力されるかどうかは、ライブラリ次第です。投入の度に認識の結果を通知できるようなフレームワークを持ちます。アプリケーションに合わせて使用してください。

+ Audio SubSystemがRecognizerModeで動作する場合、アプリケーションレイヤでは音声データ(PCMデータ)を意識することなく実装することが可能です。

データフロー内部は、Messageで通信します。
Message通信は、各クライアントごとにIDを持ちます。
Audio Recognizerの場合、exampleにあるサンプルLayoutをもとにIDを示すと以下のようになります。

User Application           : MSGQ_AUD_APP
Audio Manager              : MSGQ_AUD_MNG
Audio Frontend             : MSGQ_AUD_FRONTEND
Audio Recognizer           : MSGQ_AUD_RECOGNIZER
Audio Capture Component    : MSGQ_AUD_CAP
Audio DSP                  : MSGQ_AUD_DSP
Audio Recognizer Message ID
図 23. Audio Recognizer Message ID

また、各データのデータ領域は以下になります。

PCM (Input) Data Buffer    : INPUT_BUF_POOL
PreProcess Data Buffer     : PREPROC_BUF_POOL
PreProcess DSP Command     : PRE_APU_CMD_POOL
Recognizer DSP Command     : RCG_APU_CMD_POOL
Audio Recognizer Pool ID
図 24. Audio Recognizer Pool ID

これらのIDを生成時に指定する必要があります。

5.3.3.13.1. How to use
Preparation

"AudioManager", "MicFrontendObject", "RecognizerObject", "CaptureComponent" と呼ばれる オーディオ・サブシステムを制御するために設計されたソフトウェアコンポーネントで、Audio Recognizer を実現します。

Create AudioManager

AudioManager を有効にするには AS_CreateAudioManager(AudioSubSystemIDs) を呼ぶ必要があります。
AudioSubSystemIDs の中で、Message Library Configuration で定義された MsgQueID を指定する必要があります。 0xFF が指定された項目は使用しないことを意味します。
AudioAttentionCb は、非同期の通知を行うためのコールバック関数を指定します。 NULL を指定した場合、通知は行われません。

static void attention_callback(const ErrorAttentionParam *attparam)
{
  ...
}

AudioSubSystemIDs ids;

ids.app         = MSGQ_AUD_APP;
ids.mng         = MSGQ_AUD_MNG;
ids.player_main = 0xFF;
ids.player_sub  = 0xFF;
ids.micfrontend = MSGQ_AUD_FRONTEND
ids.mixer       = 0xFF;
ids.recorder    = 0xFF;
ids.effector    = 0xFF;
ids.recognizer  = MSGQ_AUD_RECOGNIZER;

AS_CreateAudioManager(ids, attention_callback);
Crate MicFrontendObject

MicFrontendObject を有効にするには AS_CreateMicFrontend(AsCreateMicFrontendParam_t) を呼ぶ必要があります。
Message Library Configuration で定義された MsgQueID と、Memory Manager Configuration で定義された PoolId を指定する必要があります。
MsgQueID のうち dsp、PoolIdのうち output と dspcmd は Preprocess を行う場合のみ有効にしてください。そうでない場合は NULL_POOL 指定で構いません。
AudioAttentionCb は、非同期の通知を行うためのコールバック関数を指定します。AudioManagerを使用しない場合に指定して下さい。
AS_CreateAudioManagerでコールバック関数を登録した場合または NULL を指定した場合は通知は行われません。

static void attention_callback_from_frontend(const ErrorAttentionParam *attparam)
{
  ...
}

AsCreateMicFrontendParams_t cparam;

cparam.msgq_id.micfrontend = MSGQ_AUD_FRONTEND;
cparam.msgq_id.mng         = MSGQ_AUD_MNG;
cparam.msgq_id.dsp         = MSGQ_AUD_PREDSP;
cparam.pool_id.capin       = INPUT_BUF_POOL;
cparam.pool_id.output      = PREPROC_BUF_POOL; /* When you don't use preprocess, set to NULL_POOL */
cparam.pool_id.dspcmd      = PRE_APU_CMD_POOL; /* When you don't use preprocess, set to NULL_POOL */

result = AS_CreateMicFrontend(&cparam, attention_callback_from_frontend);
Create RecognizerObject

RecognizerObject を有効にするには AS_CreateRecognizer(AsCreateRecognizerParam_t) を呼ぶ必要があります。 Message Library Configuration で定義された MsgQueID と、Memory Manager Configuration で定義された PoolId を指定する必要があります。
AudioAttentionCb は、非同期の通知を行うためのコールバック関数を指定します。AudioManagerを使用しない場合に指定して下さい。
AS_CreateAudioManagerでコールバック関数を登録した場合または NULL を指定した場合は通知は行われません。

static void attention_callback_from_recognizer(const ErrorAttentionParam *attparam)
{
  ...
}

AsCreateRecognizerParam_t cparam;

cparam.msgq_id.recognizer = MSGQ_AUD_RECOGNIZER;
cparam.msgq_id.parent     = MSGQ_AUD_MNG;
cparam.msgq_id.dsp        = MSGQ_AUD_RCGDSP;
cparam.pool_id.out        = S0_OUTPUT_BUF_POOL;
cparam.pool_id.dsp        = S0_RCG_APU_CMD_POOL;

result = AS_CreateRecognizer(&cparam, attention_callback_from_recognizer);
Create CaptureComponent

CaptureComponent を有効にするには AS_CreateCapture(AsActCaptureParam_t)を呼ぶ必要があります。 Message Library Configuration で定義された MsgQueID と、Memory Manager Configuration で定義された PoolId を指定する必要があります。 もしアプリケーションが 2つ目のチャンネルを使わない場合は、3つめと4つめの引数を 0xFF に設定する必要があります。

AsActCaptureParam_t capture_act_param;

cparam.msgq_id.dev0_req  = MSGQ_AUD_CAP;
cparam.msgq_id.dev0_sync = MSGQ_AUD_CAP_SYNC;
cparam.msgq_id.dev1_req  = 0xFF;
cparam.msgq_id.dev1_sync = 0xFF;

result = AS_CreateCapture(&cparam);
Initialize and Change state

必要なオブジェクトが生成されたら、Recognizer動作を行わせるためにAudioのHWの設定や電源On、動作モードの変更などの初期化処理を行います。

以下のコマンドを順に発行することで、実現が可能です。

Power on Audio SubSystem

Audioブロックに電源を入れるために、AUDCMD_POWERON, PowerOnParamコマンドを発行することで、電源を入れてAudioSubSystemの状態をReady状態に遷移します。

enable_sound_effect

enable_sound_effectは、AS_DISABLE_SOUNDEFFECT固定となります。

AS_DISABLE_SOUNDEFFECT: SoundEffect無効
コマンド設定例
AudioCommand command;
command.header.packet_length = LENGTH_POWERON;
command.header.command_code  = AUDCMD_POWERON;
command.header.sub_code      = 0x00;
command.power_on_param.enable_sound_effect = AS_DISABLE_SOUNDEFFECT;
AS_SendAudioCommand(&command);
Initialize Mic Gain

AUDCMD_INITMICGAINでMicのGainを設定します。

init_mic_gain_param[]

アナログマイクの場合、dB値を10倍にした値を、5の倍数で0(0.0dB)~210(21.0dB)の範囲で設定できます。デフォルト値は0.0dBです。
デジタルマイクの場合、dB値を100倍にした値を、-7850(-78.50dB)~0(0.00dB)の範囲で設定できます。デフォルト値は-78.50dBです。
Gainの値を変更したくない場合は、'AS_MICGAIN_HOLD'を指定してください。

コマンド設定例

下記は、1ch〜4chの入力に21dBのゲインをかける場合の設定例です。 5ch〜8chの原因は変更しない設定です。

AudioCommand command;
command->header.packet_length = LENGTH_INITMICGAIN;
command->header.command_code  = AUDCMD_INITMICGAIN;
command->header.sub_code      = 0;
command->init_mic_gain_param.mic_gain[0] = 210;
command->init_mic_gain_param.mic_gain[1] = 210;
command->init_mic_gain_param.mic_gain[2] = 210;
command->init_mic_gain_param.mic_gain[3] = 210;
command->init_mic_gain_param.mic_gain[4] = AS_MICGAIN_HOLD;
command->init_mic_gain_param.mic_gain[5] = AS_MICGAIN_HOLD;
command->init_mic_gain_param.mic_gain[6] = AS_MICGAIN_HOLD;
command->init_mic_gain_param.mic_gain[7] = AS_MICGAIN_HOLD;
AS_SendAudioCommand(&command);

mic_gain[]の各要素はマイクのIDに対応しています。マイクのIDはConfigの"MIC channel select map"の値で設定されます。デフォルトの設定は、アナログマイク1/2/3/4が設定されています。

以下に、configrationの情報を記載します。

MIC channel select map の設定
[Device Drivers]
  [Board specific drivers]
    [CXD56 Audio Driver]
      [Audio baseband config settings]
        [CXD5247 settings]
          (0xFFFF4321) MIC channel select map

"MIC channel select map"の値は4bitごとにMICのIDを示します。
mic_gainの要素と"MIC channel select map"のbitフィールドの関係は下記の通りです。

mic_gainの要素 [7] [6] [5] [4] [3] [2] [1] [0]

bitフィールド

31-28

27-24

23-20

19-16

15-12

11-8

7-4

3-0

"MIC channel select map"の値(ID)とマイクの種別の関係は下記の通りです。

HEX値(ID) マイク種別

0x1

CXD5247アナログマイク1

0x2

CXD5247アナログマイク2

0x3

CXD5247アナログマイク3

0x4

CXD5247アナログマイク4

0x5

CXD5247デジタルマイク1

0x6

CXD5247デジタルマイク2

0x7

CXD5247デジタルマイク3

0x8

CXD5247デジタルマイク4

0x9

CXD5247デジタルマイク5

0xA

CXD5247デジタルマイク6

0xB

CXD5247デジタルマイク7

0xC

CXD5247デジタルマイク8

使用するマイクを要素0から順に設定して下さい。要素番号をSkipして設定することはできません。 アナログマイクとデジタルマイクの混合は対応していません。 アナログマイクを設定する場合は要素0-3を設定して下さい。 要素が偶数の場合、Lチャンネル、要素が奇数の場合、Rチャンネルとなります。

Change to Recognizer Status

AUDCMD_SETRECOGNIZERSTATUSでAudioSubSystemの状態をRecognizer状態に遷移します。

input_device

記録対象の入力デバイスを指定します。

マイクのみ指定が可能です。
AsMicFrontendDeviceMic : 
コマンド設定例

下記は、マイク入力を認識に使用する設定例です。

AudioCommand command;
command.header.packet_length = LENGTH_SET_RECOGNIZER_STATUS;
command.header.command_code  = AUDCMD_SETRECOGNIZERSTATUS;
command.header.sub_code      = 0x00;
command.set_recognizer_status_param.input_device = AsMicFrontendDeviceMic;
AS_SendAudioCommand(&command);
Start Recognizer

音声認識開始シーケンスを示します。

Init mic frontend

AUDCMD_INIT_MICFRONTEND, MicFrontendCommand, AsInitMicFrontEndでフロントエンド動作(音声の取り込みなど)の設定をします。

ch_num
AS_CHANNEL_MONO   : Monoral
AS_CHANNEL_STEREO : Stereo
AS_CHANNEL_4CH    : 4ch
AS_CHANNEL_6CH    : 6ch
AS_CHANNEL_8CH    : 8ch
bit_length
AS_BITLENGTH_16 : 16bit
AS_BITLENGTH_24 : 24bit
samples
/* 1フレームのサンプル数を指定します。認識ライブラリの仕様に合わせて設定してください。 */
out_fs

MicFrontendから出力する音声のサンプリングレートを指定します。
preproc_typeAsMicFrontendPreProcSrc の時のみ有効です。

AS_SAMPLINGRATE_8000  : 8kHz
AS_SAMPLINGRATE_16000 : 16kHz
AS_SAMPLINGRATE_44100 : 44.1kHz
AS_SAMPLINGRATE_48000 : 48kHz
...
...
AS_SAMPLINGRATE_192000 : 192kHz
preproc_type

PreProcessの種別を設定します。

AsMicFrontendPreProcThrough       : Through
AsMicFrontendPreProcSrc           : Sampling Rate Converter
AsMicFrontendPreProcUserCustom    : User Custom Process
'AsMicFrontendPreProcSrc' を指定する場合は sdk/modules/audio/DSP/ にある SRC が必要です。
preprocess_dsp_path

PreProcess用DSPバイナリをファイル名を含むフルパスで指定します。

"/mnt/sd0/BIN/PREPROC" : PREPROC というバイナリをSDカードのBINフォルダに置く場合
"/mnt/spif/SRC"        : SRC というバイナリをSPI-FLASHの直下に置く場合
data_dest

MicFrontendObjectからのAudioデータの出力先を指定します。

AsMicFrontendDataToRecorder   : Send to Recorder
AsMicFrontendDataToRecognizer : Send to Recognizer

PreprocessDSPを使用した信号処理がAudio Recognizer Function内でどこに位置するかを下図に示します。

ハイライトされた箇所にあるCustomprocComp(Pre), UserCustomDSP(Pre)で信号処理を行います。
ユーザーはこのUserCustomDSPに信号処理を作成、組み込みます。

Audio recognizer preprocess
図 25. Audio Recognizer Preprocess

Preprocessでは認識ライブラリの入力フォーマットに合わせて、DSPを使用したユーザー独自の信号処理を行うことが出来ます。
例えば、認識ライブラリの入力がBasebandの入力(48kHz or 192kHz)と異なる場合の周波数変換や、ノイズ抑制用のフィルタを前処理として行います。

コマンド設定例

下記は、Mono/16bit/768sample per frameで音声をキャプチャする場合の設定例です。
Pre処理はUserCustomのDSPで行い、そのDSP用バイナリファイルはSDカードのBINフォルダに配置します。
また、キャプチャした音声はRecognizerに使う設定としています。

AudioCommand command;
command.header.packet_length = LENGTH_INIT_MICFRONTEND;
command.header.command_code  = AUDCMD_INIT_MICFRONTEND;
command.header.sub_code      = 0x00;
command.init_micfrontend_param.ch_num       = AS_CHANNEL_MONO
command.init_micfrontend_param.bit_length   = AS_BITLENGTH_16;
command.init_micfrontend_param.sample       = 768; /* この値は認識ライブラリの仕様に合わせて設定してください。 */
command.init_micfrontend_param.outfs        = AS_SAMPLINGRATE_16000;
command.init_micfrontend_param.preproc_type = AsMicFrontendPreProcUserCustom;
snprintf(command.init_micfrontend_param.preprocess_dsp_path,
         AS_RECOGNIZER_FILE_PATH_LEN,
         "%s", "/mnt/sd0/BIN/PREPROC");
command.init_micfrontend_param.data_dest = AsMicFrontendDataToRecognizer;
Init PreProcess DSP

AUDCMD_INIT_PREPROCESS_DSP, AsInitPreProcParamでPre処理用DSPの初期化をします。

AUDCMD_INIT_MICFRONTENDpreproc_typeAsMicFrontendPreProcThrough にしている場合はこの手順は不要です。
packet_addr

初期化コマンドパケットのアドレスです。コマンドのフォーマットはPre処理用DSPに依存します。
設定したアドレス領域は、このAPIの応答まで保持しておく必要があります。

packet_size

初期化コマンドパケットのサイズです。

コマンド設定例
static uint8_t s_initparam = 0;

AudioCommand command;
command.header.packet_length = LENGTH_INIT_PREPROCESS_DSP;
command.header.command_code  = AUDCMD_INIT_PREPROCESS_DSP;
command.header.sub_code      = 0x00;
command.init_preproc_param.packet_addr = reinterpret_cast<uint8_t *>(&s_initparam);
command.init_preproc_param.packet_size = sizeof(s_initparam);
AS_SendAudioCommand(&command);
Init recognizer

AUDCMD_INIT_RECOGNIZER, RecognizerCommand, AsInitRecognizerParamで認識動作の設定をします。

fcb

認識結果をAudioSusSystemから受け取るためのコールバック関数を登録します。
認識結果はプレーンデータで通知され、その構成などについては認識ライブラリに依存します。

static void recognizer_find_callback(AsRecognitionInfo)
type

認識エンジンのタイプを設定します。

SDK v1.4.0時点では下記の設定値のみが指定可能です。
AsRecognizerTypeUserCustom
recognizer_dsp_path

認識用DSPバイナリをファイル名を含むフルパスで指定します。

"/mnt/sd0/BIN/RCGPROC" : RCGPROCというバイナリをSDカードのBINフォルダに置く場合

ここで指定された認識用DSPバイナリは下図中でハイライトされた
CustomprocComp(Recogniton), UserCustomDSP(Recognition)に当たる箇所で認識処理を行います。

Audio recognizer recognizerprocess
図 26. Audio Recognizer Process
コマンド設定例

下記は、recognizer_find_callback()で認識結果を受け取る場合の設定例です。 認識用DSPはSDカードのBINディレクトリに配置します。

static void recognizer_find_callback(AsRecognitionInfo info)
{
  ...
}

AudioCommand command;
command.header.packet_length = LENGTH_INIT_RECOGNIZER;
command.header.command_code  = AUDCMD_INIT_RECOGNIZER;
command.header.sub_code      = 0x00;
command.init_recognizer.fcb             = recognizer_find_callback;
command.init_recognizer.recognizer_type = AsRecognizerTypeUserCustom;
snprintf(command.init_recognizer.recognizer_dsp_path,
         AS_RECOGNIZER_FILE_PATH_LEN,
         "%s", "/mnt/sd0/BIN/RCGPROC");
Init Recognizer DSP

AUDCMD_INIT_RECOGNIZER_DSP, AsInitRecognizerProcParamで認識処理用DSPの初期化をします。

packet_addr

初期化コマンドパケットのアドレスです。コマンドのフォーマットは認識処理用DSPに依存します。
設定したアドレス領域は、このAPIの応答まで保持しておく必要があります。

packet_size

初期化コマンドパケットのサイズです。

コマンド設定例
static uint8_t s_initparam = 0;

AudioCommand command;
command.header.packet_length = LENGTH_INIT_RECOGNIZER_DSP;
command.header.command_code  = AUDCMD_INIT_RECOGNIZER_DSP;
command.header.sub_code      = 0x00;
command.init_rcg_param.packet_addr = reinterpret_cast<uint8_t *>(&s_initparam);
command.init_rcg_param.packet_size = sizeof(s_initparam);
AS_SendAudioCommand(&command);

音声認識機能の初期化までのシーケンスを下図に示します。

Diagram
図 27. 音声認識初期化シーケンス
Start Recognizer

AUDCMD_START_RECOGNIZERで認識動作を開始します。
開始するとAudioSubSystemが音声データをキャプチャし前処理を施したのち認識ライブラリに投入します。
認識結果はInit Recognizerで設定したコールバック関数で通知されます。

コマンド設定例
AudioCommand command;
command.header.packet_length = LENGTH_START_RECOGNIZER;
command.header.command_code  = AUDCMD_START_RECOGNIZER;
command.header.sub_code      = 0x00;
AS_SendAudioCommand(&command)
Diagram
図 28. 認識動作シーケンス
Stop Recognizer

AUDCMD_STOP_RECOGNIZERで認識動作を停止します。
停止するとAudioSubSystemは音声データキャプチャを停止し、認識ライブラリへの投入も止まります。

コマンド設定例
AudioCommand command;
command.header.packet_length = LENGTH_STOP_RECOGNIZER;
command.header.command_code  = AUDCMD_STOP_RECOGNIZER;
command.header.sub_code      = 0x00;
AS_SendAudioCommand(&command)
Diagram
図 29. 認識停止シーケンス
5.3.3.13.2. Build Configurations

AudioRecognizerの機能を使用するために

cd sdk/
tools/config.py -m

でConfig menuを開き、以下のConfigを設定する必要が有ります。

Select options in below:

:(Select audio recognizer)
[Device Drivers]
  [MMCSD driver support]                   <= Y (If using the SD card)
  [Board specific drivers]
    [CXD56 Audio Driver]                   <= Y

[Application Configuration]
  [Spresense SDK]
    [SDK audio]                            <= Y
      [Audio Utilities]
        [Sound Recognizer]                 <= Y
        [Mic Front End]                    <= Y

    [Memory Manager]                       <= Y
      [Memory Utilities]                   <= Y

    [ASMP]                                 <= Y
5.3.3.13.3. Error Attentions and Approach

音声認識時の警告の一覧と、対処方法は以下の通りです。詳細は オーディオサブシステムのエラーについて を参照してください。

ID Attention Code Attention Level Approach

0x0D

AS_ATTENTION_SUB_CODE_MEMHANDLE_ALLOC_ERROR

ERROR

データ領域のセグメント数が不足したことが原因です。AudioSubSystem以外のタスクの優先度を下げるか、データ領域のセグメント数を増やしてください。

0x0F

AS_ATTENTION_SUB_CODE_TASK_CREATE_ERROR

ERROR

ヒープ領域が不足していることが原因です。ヒープ領域を拡張して下さい。

0x18

AS_ATTENTION_SUB_CODE_DSP_VERSION_ERROR

ERROR

DSPバイナリのバージョンが異なることが原因です。DSP バイナリイメージを"sdk/modules/audio/dsp"のファイルで更新して下さい。

5.3.3.13.4. DSP install

音声認識用のDSPバイナリイメージをKconfigで設定したパスに格納して下さい。

[TBD]SDKが提供するバイナリイメージは、 sdk/modules/audio/dsp にあります。
5.3.3.14. Audio Through Functions

Audio Through の簡単なデータの流れを以下に示します。

Audio Through Dataflow
図 30. Audio Through Dataflow

Audio SubSystemがThroughModeで動作する場合、User Applicationは、 CPUを介さないデータフローを設定することが出来ます。

データの入力元は、I2SもしくはMICが指定できます。 データの出力先は、スピーカーもしくはI2Sが指定できます。

また、User Applicationは2つのデータフローを設定できます。 MIXERを利用することで、2つの入力データを1つにMIXすることが出来ます。

User Applicationからの設定はコマンドを、Messageで通信します。 Message通信は、各クライアントごとにIDを持ちます。 Audio Throughの場合、IDを示すと以下のようになります。

User Application           : MSGQ_AUD_APP
Audio Manager              : MSGQ_AUD_MNG
Audio Through Message ID
図 31. Audio Through Message ID

これらのIDを生成時に指定する必要があります。

5.3.3.14.1. Audio HW internal dataflow

Audio Throughにおいて、Audio HWの内部ではAudio HW internal dataflowに示すデータフローとなります。
データフローの入力元として、I2S In、MIC In、Mixer Outがあります。
データフローの出力先として、Mixer In1、 Mixer In2、I2SOutがあります。出力先にMixer In1もしくは、Mixer In2を設定した場合は、Mixer Outからスピーカーに出力されます。

Diagram
図 32. Audio Through internal dataflow

設定可能な入力元と出力先の関係は下記の通りです。

表 21. Audio Through dataflow combination
入力元 出力先

I2S In

Mixer In1, Mixer In2

MIC In

Mixer In1, Mixer In2, I2S Out

Mixer Out

I2S Out,
Speaker Out(常時出力)

5.3.3.14.2. How to use
Preparation

"AudioManager" と呼ばれる
オーディオ・サブシステムを制御するために設計されたソフトウェアコンポーネントで、Audio Throughを実現します。

そのため、Audio Throughを実現するには、以下のオブジェクトの生成関数を事前に呼ぶ必要があります。

Activate AudioManager

AudioManager を有効にするには、AS_CreateAudioManager(AudioSubSystemIDs) を呼ぶ必要があります。
AudioSubSystemIDs の中で、Message Library Configuration で定義された MsgQueID を指定する必要があります。
0xFF が指定された項目は使用しないことを意味します。
AudioAttentionCb は、非同期の通知を行うためのコールバック関数を指定します。AudioManagerを使用しない場合に指定して下さい。AS_CreateAudioManagerでコールバック関数を登録した場合、NULLを指定した場合は通知は行われません。

static void attention_callback(const ErrorAttentionParam *attparam)
{
  ...
}

AudioSubSystemIDs ids;

ids.app         = MSGQ_AUD_APP;
ids.mng         = MSGQ_AUD_MNG;
ids.player_main = 0xFF;
ids.player_sub  = 0xFF;
ids.mixer       = 0xFF;
ids.recorder    = 0xFF;
ids.effector    = 0xFF;
ids.recognizer  = 0xFF;

AS_CreateAudioManager(ids, attention_callback);
Initialize and Status change

必要なオブジェクトが生成されたら、Audio Through動作を行わせるためにAudioのHWの設定や電源On、動作モードの変更などの初期化処理を行います。

以下のコマンドを順に発行することで、実現が可能です。

Power on Audio SubSystem

Audioブロックに電源を入れるために、AUDCMD_POWERON, PowerOnParamコマンドを発行することで、電源を入れてAudioSubSystemの状態をReady状態に遷移します。 
enable_sound_effectは、AS_DISABLE_SOUNDEFFECT固定としてください。

  AudioCommand command;
  command.header.packet_length = LENGTH_POWERON;
  command.header.command_code  = AUDCMD_POWERON;
  command.header.sub_code      = 0x00;
  command.power_on_param.enable_sound_effect = AS_DISABLE_SOUNDEFFECT;
  AS_SendAudioCommand(&command);
Initialize output device

PowerOnを行い、Ready状態に遷移したら、AUDCMD_INITOUTPUTSELECT, InitOutputSelectParam コマンドでMixerからの出力先の選択を行います。

output_device_selの設定は以下の通りです。

output_device_sel
  AS_OUT_OFF : 出力OFF
  AS_OUT_SP  : スピーカーからの出力
  AS_OUT_I2S : I2Sからの出力
HWの電源を制御するため、AS_OUT_I2Sを選択すると、スピーカーから出力されなくなります。Audio ThroughでI2Sとスピーカーを両方使いたい場合は、AS_OUT_SPを選択してください。
コマンド設定例
  AudioCommand command;
  command.header.packet_length = LENGTH_INITOUTPUTSELECT;
  command.header.command_code  = AUDCMD_INITOUTPUTSELECT;
  command.header.sub_code      = 0x00;
  command.init_output_select_param.output_device_sel = AS_OUT_SP;
  AS_SendAudioCommand(&command);
Change to Through Status

AUDCMD_SETTHROUGHSTATUSコマンドでAudioSubSystemの状態をThrough状態に遷移します。

コマンド設定例
  AudioCommand command;
  command.header.packet_length = LENGTH_SET_THROUGH_STATUS;
  command.header.command_code = AUDCMD_SETTHROUGHSTATUS;
  command.header.sub_code = 0x00;
  AS_SendAudioCommand(&command);
Set volume

出力にスピーカーを設定する場合、AUDCMD_SETVOLUME, SetVolumeParam で音量を設定できます。 各パラメータの設定は以下の通りです。

I2Sでは音量は変更できません。

input1_db

MIXER1の音量。dBを10倍の整数値で設定します。設定範囲は-1020(-102.0dB)から120(+12.0dB)で、ステップ幅5(0.5dB)で設定できます。

input2_db

MIXER2の音量。設定範囲はinput1_dbと同じです。

master_db

MIXER1とMIXER2のMix後の音量。設定範囲はinput1_dbと同じです。

  AudioCommand command;
  command.header.packet_length = LENGTH_SETVOLUME;
  command.header.command_code  = AUDCMD_SETVOLUME;
  command.header.sub_code      = 0;
  command.set_volume_param.input1_db = 0;    /* 0.0dB */
  command.set_volume_param.input2_db = 0;    /* 0.0dB */
  command.set_volume_param.master_db = -200; /* -20.0dB */
  AS_SendAudioCommand(&command);
Initialize Mic Gain

Recorder Init Mic Gain を参照してください。

使用できるマイクは、CXD5247アナログマイク1, CXD5247アナログマイク2の組み合わせか、 CXD5247デジタルマイク1,CXD5247デジタルマイク2の組み合わせのどちらかです。

使用するマイクを変更したい場合は、Recorder Init Mic Gain と同様、Layoutを変更することで、可能です。
Diagram
図 33. Initial sequence
Start Audio Through

データフローのパスを設定することで、データの入出力を開始します。

Set Through Path

AUDCMD_SETTHROUGHPATH, AsSetThroughPathParam, AsThroughPathでデータパスを同時に2つ設定できます。 それぞれのデータパスの各パラメータの設定は以下の通りです。

en

データパスの有効、無効を設定します。

true : 有効
false: 無効
in

データの入力元を設定します。

AS_THROUGH_PATH_IN_MIC : MICを入力元にします
AS_THROUGH_PATH_IN_I2S1 : I2Sを入力元にします
AS_THROUGH_PATH_IN_MIXER : Mixer Outを入力元にします
MICはアナログマイクの場合、CXD5247アナログマイク1とCXD5247アナログマイク2を指します。デジタルマイクの場合は、CXD5247デジタルマイク1とCXD5247デジタルマイク2を指します。I2Sは、I2S0を指します。
out

データの出力先を設定します。

AS_THROUGH_PATH_OUT_MIXER1 : Mixer In1を出力先にします
AS_THROUGH_PATH_OUT_MIXER2 : Mixer In2を出力先にします
AS_THROUGH_PATH_OUT_I2S1 : I2Sを出力先にします
I2Sは、I2S0を指します。
command example 1
  AudioCommand command;
  command.header.packet_length = LENGTH_SET_THROUGH_PATH;
  command.header.command_code  = AUDCMD_SETTHROUGHPATH;
  command.header.sub_code      = 0x00;
  command.set_through_path.path1.en  = true; (1)
  command.set_through_path.path1.in  = AS_THROUGH_PATH_IN_MIC; (2)
  command.set_through_path.path1.out = AS_THROUGH_PATH_OUT_I2S1; (3)
  command.set_through_path.path2.en  = true; (4)
  command.set_through_path.path2.in  = AS_THROUGH_PATH_IN_I2S1;   (5)
  command.set_through_path.path2.out = AS_THROUGH_PATH_OUT_MIXER1; (6)
  AS_SendAudioCommand(&command);
1 データパス1の設定を有効にします
2 データパス1はMIC Inを入力元にします
3 データパス1はI2S Outを出力先にします
4 データパス2の設定を有効にします
5 データパス2はI2S Inを入力元にします
6 データパス2はMixer In1を出力先にします
Diagram
図 34. command example 1 dataflow
command example 2
  AudioCommand command;
  command.header.packet_length = LENGTH_SET_THROUGH_PATH;
  command.header.command_code  = AUDCMD_SETTHROUGHPATH;
  command.header.sub_code      = 0x00;
  command.set_through_path.path1.en  = true; (1)
  command.set_through_path.path1.in  = AS_THROUGH_PATH_IN_MIC; (2)
  command.set_through_path.path1.out = AS_THROUGH_PATH_OUT_MIXER1; (3)
  command.set_through_path.path2.en  = true; (4)
  command.set_through_path.path2.in  = AS_THROUGH_PATH_IN_MIXER;  (5)
  command.set_through_path.path2.out = AS_THROUGH_PATH_OUT_I2S1; (6)
  AS_SendAudioCommand(&command);
1 データパス1の設定を有効にします
2 データパス1はMIC Inを入力元にします
3 データパス1はMixer In2を出力先にします
4 データパス2の設定を有効にします
5 データパス2はMixer Outを入力元にします
6 データパス2はI2S Outを出力先にします
Diagram
図 35. command example 2 dataflow
command example 3
  AudioCommand command;
  command.header.packet_length = LENGTH_SET_THROUGH_PATH;
  command.header.command_code  = AUDCMD_SETTHROUGHPATH;
  command.header.sub_code      = 0x00;
  command.set_through_path.path1.en  = true; (1)
  command.set_through_path.path1.in  = AS_THROUGH_PATH_IN_MIC; (2)
  command.set_through_path.path1.out = AS_THROUGH_PATH_OUT_MIXER2; (3)
  command.set_through_path.path2.en  = false; (4)
  AS_SendAudioCommand(&command);
1 データパス1の設定を有効にします
2 データパス1はMIC Inを入力元にします
3 データパス1はMixer In2を出力先にします
4 データパス2の設定を無効にします
Diagram
図 36. command example 3 dataflow
command example 4
  AudioCommand command;
  AudioResult result;
  command.header.packet_length = LENGTH_SET_THROUGH_PATH;
  command.header.command_code  = AUDCMD_SETTHROUGHPATH;
  command.header.sub_code      = 0x00;
  command.set_through_path.path1.en  = true; (1)
  command.set_through_path.path1.in  = AS_THROUGH_PATH_IN_I2S1; (2)
  command.set_through_path.path1.out = AS_THROUGH_PATH_OUT_MIXER1; (3)
  command.set_through_path.path2.en  = true; (4)
  command.set_through_path.path2.in  = AS_THROUGH_PATH_IN_I2S1;  (5)
  command.set_through_path.path2.out = AS_THROUGH_PATH_OUT_MIXER2; (6)
  AS_SendAudioCommand(&command);

  AS_ReceiveAudioResult(&result); (7)

  command.header.packet_length = LENGTH_SET_THROUGH_PATH;
  command.header.command_code  = AUDCMD_SETTHROUGHPATH;
  command.header.sub_code      = 0x00;
  command.set_through_path.path1.en  = true;
  command.set_through_path.path1.in  = AS_THROUGH_PATH_IN_MIXER; (8)
  command.set_through_path.path1.out = AS_THROUGH_PATH_OUT_I2S1; (9)
  command.set_through_path.path2.en  = false;
  AS_SendAudioCommand(&command);
1 データパス1の設定を有効にします
2 データパス1はI2S Inを入力元にします
3 データパス1はMixer In1を出力先にします
4 データパス2の設定を有効にします
5 データパス2はMic Inを入力元にします
6 データパス2はMixer In1を出力先にします
7 結果を受け取ります
8 データパス1はMixer Outを入力元にします
9 データパス1はI2S Outを出力先にします
Diagram
図 37. command example 4 dataflow
Diagram
図 38. Player State sequence
5.3.3.14.3. Build Configurations

AudioThrough の機能を使用するためには

cd sdk
tools/config.py -m

でConfig menu を開き、以下のConfigを設定する必要があります。

Select options in below:

[Device Drivers]
  [Board specific drivers]
    [CXD56 Audio Driver]                   <= Y

[Application Configuration]
  [Spresense SDK]
    [SDK audio]                            <= Y
5.3.3.14.4. Error Attentions and Approach

音楽再生時の警告の一覧と、対処方法は以下の通りです。詳細は オーディオサブシステムのエラーについて を参照してください。

ID Attention Code Attention Level Approach

0x0F

AS_ATTENTION_SUB_CODE_TASK_CREATE_ERROR

ERROR

ヒープ領域が不足していることが原因です。ヒープ領域を拡張して下さい。

AS_ATTENTION_SUB_CODE_SIMPLE_FIFO_UNDERFLOW が発生した場合、音声再生が停止し、再生エラーの状態になります。 この状態が発生した場合は、直ちにAsStopPlayerParamコマンドを発行し、再生停止状態に遷移させてください。
再生停止に遷移後、FIFOのクリアを必ず行ってください。行わないとノイズが発生してしまいます。

5.3.4. Object Level API

Audio機能では、High Level API よりも細かい単位でもAPIを提供しています。
High Level API をコールした際に内部で使用されるObject群を個別に組み合わせて
使用することでより自由なアプリケーションを作成することが出来ます。

これを Object Level API と呼ぶこととします。

5.3.4.1. About Usecase

Object Level APIを使用したUsecaseの例を示します。
(組み合わせ方・使い方は自由ですので、これはあくまで例です。)

5.3.4.1.1. Usecase 1

MediaPlayerObjectとOutputMixerObjectを使用して、Audioデータのデコード〜出音を行うケースです。
MediaPlayerObjectから応答されたPCMデータをApplicationで処理した後OutputMixerObjectへ送ることが出来ます。

Diagram
5.3.4.1.2. Usecase 2

MediaPlayerObjectを使用せずに、RAM上に置かれたPCMデータをOutputMixerObjectへ送るケースです。
デコードをしないので、例えば効果音など即応性が求められるような音源の再生に適します。

Diagram
5.3.4.1.3. Usecase 3

MediaRecorderObjectを使い記録したMIC入力をApplicationで加工して
OutputMixer経由でスピーカーやI2S出力に送出するケースです。

Diagram
5.3.4.2. MediaPlayerObject

MediaPlayerObjectは、Audioデータのデコード管理とデコード結果PCMの出力を行います。
2つのPlayerを同時に使用することが出来、各APIにあるPlayerIDのパラメータで個別に制御します。

ApplicationはSimpleFIFOと呼ばれるバッファ経由でMediaplayerObjectにESデータを渡します。
バッファがアンダーフローすると再生が停止します。Applicationはそれを考慮した設計をする必要が有ります。
デコードが完了するとMediaPlayerObjectからはPCMデータのMemoryHandleが通知されます。

Diagram

PCMデータをOutputMixerObjectへ送ることも可能です。この場合はApplicationへの応答はありません。
ただし、当然ですがOutputMixerObjectの生成・起動をしておくことが必要です。
(Defaultは上図の通りApplicationへのCallback応答です。)

Diagram
5.3.4.2.1. Functions
Create

MediaPlayerObjectを使用する際に必ずコールする必要があります。
タスク,インタンスの生成,MsqQueue待ちへの移行までを行います。

API
bool AS_CreatePlayer(AsPlayerId id, FAR AsCreatePlayerParam_t *param);
Activate

MediaPlayerObjectのActivationを行います。必ずコールする必要があります。
ApplicationからMediaPlayerObjectへAudioデータを渡すためのバッファのハンドルはここで設定します。

API
bool AS_ActivatePlayer(AsPlayerId id, FAR AsActivatePlayer &actparam);
Init

再生するコンテンツの情報を設定しMediaPlayerObjectを初期化します。
コンテンツの情報 (※) が変わるたびにコールする必要があります。
(※コーデック種別,ビット長,サンプリング周波数)

API
bool AS_InitPlayer(AsPlayerId id, FAR AsInitPlayerParam &initparam);
Play

再生を開始します。
再生開始後はデコード結果(PCMデータ)が応答され続けます。
Applicationは、Activateの際に指定したバッファにAudioデータを供給する必要があります。
供給が追い付かない場合はバッファがアンダーフローし再生が停止します。

デコード結果のPCMデータをApplicatoinへ応答するか、OutputMixerObjectへ直接送るかを選択出来ます。

API
bool AS_PlayPlayer(AsPlayerId id, FAR AsPlayPlayerParam &playparam);
Stop

再生を停止します。
本APIをコールした時点でAudioデータバッファに残っているデータを再生しきってから停止するか
即時停止をするかを選択することが出来ます。前者の場合は停止までに時間がかかることが有ります。

また、コールのタイミングにより、入れ違いでコール後にデコード完了の通知が届くことが有ります。

API
bool AS_StopPlayer(AsPlayerId id, FAR AsStopPlayerParam &stopparam);
Set Gain

再生音量のGainをL/Rそれぞれ設定します。Init後~Deactivateするまで設定可能です。
コールしない場合は100%(デフォルト音量)です。(BaseBandの音量設定と依存関係はありません)

API
bool AS_SetPlayerGain(AsPlayerId id, FAR AsSetGainParam &gainparam);
Next Request

次のDecode処理(再生継続処理)を要求します。
デコード結果データ用のバッファが空いた等の契機で継続的にコールしてください。
本APIをコールしないと後続のデコード処理が行われず、音が止まったり途切れたりします。

(※PCMデータの送信先を直接OutputMixerObjectにしている場合はコール不要です。)

API
bool AS_RequestNextPlayerProcess(AsPlayerId id, FAR AsRequestNextParam &nextparam);
Deactivate

MediaPlayerObjectのDeactivationを行います。 再度MediaPlayerObjectを使用するにはAcitvateからやり直す必要があります。

API
bool AS_DeactivatePlayer(AsPlayerId id, FAR AsDeactivatePlayer &deactparam);
Delete

MediaPlayerObjectのタスク,インスタンスを削除します。
再度MediaPlayerObjectを使用するにはCreateからやり直す必要があります。

API
bool AS_DeletePlayer(AsPlayerId id);
5.3.4.2.2. Sequence

MediaPlayerObjectの簡易シーケンスです。

Diagram
5.3.4.3. OutputMixerObject

OutputMixerObjectはPCMデータの送出(Rendering)を管理します。
ApplicationはPCMデータをMemoryHandle経由でOutputMixerObjectへ送ります。
送出(Rendering)が完了するとOutputMixerObjectからはcallbackが応答されます。

Diagram
5.3.4.3.1. Functions
Create

OutputMixerObjectを使用する際に必ずコールする必要があります。
タスク,インタンスの生成,MsqQueue待ちへの移行までを行います。

API
bool AS_CreateOutputMixer(FAR AsCreateOutputMixParam_t *param);
Activate

OutputMixerObjectのActivationを行います。必ずコールする必要があります。
出力先(スピーカーまたはI2S)の選択をこの時に行います。

API
bool AS_ActivateOutputMixer(uint8_t handle, FAR AsActivateOutputMixer &actparam);
Send Data

PCMデータを送出します。送出が完了すると応答がcallbackされます。

本APIで渡したデータの送出が完了する前に、次のデータを渡して下さい。
間に合わない場合はDMA転送がアンダフローを起こし停止します。

また、実際にPCMデータが送出されるのは本APIが2回以上コールされた時です。

Diagram
API
bool AS_SendDataOutputMixer(FAR AsSendDataOutputMixer &sendparam);
Frame Term Control

PCMデータの送出時間を調整します。
実際のPCMデータの発音時間よりも長くまたは短く微調整することが出来ます。
主にPCMデータ用のバッファ残量の調整(アンダー/オーバーフロー抑制)などに使用します。
(※調整実行時には小さいノイズが入ることがあります。)

API
bool AS_FrameTermFineControlOutputMixer(uint8_t handle, FAR AsFrameTermFineControl &ftermparam);
Deactivate

OutputMixerObjectのDeactivationを行います。

API
bool AS_DeactivateOutputMixer(uint8_t handle, FAR AsDeactivateOutputMixer &deactparam);
Delete

OutputMixerObjectのタスク,インスタンスを削除します。
再度OutputMixerObjectを使用するにはCreateからやり直す必要があります。

API
bool AS_DeleteOutputMix(void);
5.3.4.3.2. Sequence

OutputMixerObjectの簡易シーケンスです。

Diagram
5.3.4.4. MediaRecorderObject

MediaRecorderObjectは、Audioデータのエンコード管理とエンコード結果ESの出力を行います。

CaptureしたMICまたはIS2からの入力(PCMデータ)をエンコードしSimpleFIFOバッファに順次格納します。
Applicationはそれを引き抜くことで、ESデータを取得することが出来ます。引き抜きが間に合わずバッファが
オーバーフローすると記録が停止しますので、Applicationはそれを考慮して設計する必要が有ります。

Diagram
5.3.4.4.1. Functions
Create

MediaRecorderObjectを使用する際に必ずコールする必要があります。
タスク,インタンスの生成,MsqQueue待ちへの移行までを行います。

API
bool AS_CreateMediaRecorder(FAR AsActRecorderParam_t *param);
Activate

MediaRecorderObjectのActivateを行います。
この時にエンコードしたAudioデータの受け渡しにつかうバッファのハンドルを渡します。

API
bool AS_ActivateMediaRecorder(FAR AsActivateRecorder *actparam);
Init

記録するコンテンツの情報を設定しMediaRecorderObjectを初期化します。
記録中に動的に変更することは出来ません。

API
bool AS_InitMediaRecorder(FAR AsInitRecorderParam *initparam);
Start

Initで設定した情報に基づいて記録を開始します。
エンコードされたESデータは、Activate時に指定したAudio用のバッファに順次格納されていきます。
ApplicationではAudioバッファからESデータを引き抜く必要が有ります。

API
bool AS_StartMediaRecorder(void);
Stop

記録を停止します。
即時停止のみ対応します。

API
bool AS_StopMediaRecorder(void);
Deactivate

MediaRecorderObjectのDeactivateを行います。

API
bool AS_DeactivateMediaRecorder(void);
Delete

MediaRecorderObjectを削除します。

API
bool AS_DeleteMediaRecorder(void);
5.3.4.4.2. Sequence
Diagram

5.3.5. Low Level API

Now Under construction. mOm

5.3.6. UserCustomDSPのアーキテクチャ

UserCustomDSPは音声信号に対してユーザー独自の信号処理をかけることが出来る仕組みです。
信号処理はDSPで行います。ここではその仕組みについて詳細に説明します。

5.3.6.1. フレームワークのコード

信号処理を追加するにはまずUserCustomDSPを作成しなければなりません。
最低限必要なソースコードは、フレームワークとしてSDKに用意されています。
これらを取り込み、ユーザー作成のDSP用コードとまとめてビルドすることでUserCustomDSPを作成します。

UserCustomDSP作成の手順については Audio RecorderのTutorial を参照してください。
Diagram
図 39. フレームワークの配置
5.3.6.2. フレームワークのコードとユーザーコードの関連

SDKの提供するのフレームワークとユーザーのコードの関連は下記の図の様でなければなりません。
ユーザーは図中の"User Edit DSP Codes"にあたる部分を編集します。
(フレームワークのコードを編集する必要は有りません。)

Diagram
図 40. フレームワークのコードとユーザコードの関連

ユーザーのコード作成に当たっての留意点は下記の通りです。

  1. UserCustomDSPとの通信コマンド定義は自由に作成できるが、フレームワークの CustomprocCommand::CmdBase を継承した構造体を使用し、下図のデータフォーマットに従う必要がある

    Diagram
    図 41. 通信コマンドフォーマット

    例えば、下記の様にする。

    struct InitPram : public CustomprocCommand::CmdBase
    {
      uint8_t ch_num;
      ...
    }
  2. ユーザー処理を書くクラス(上図では UserProc )は、下記の様にフレームワークの CustomprocDspUserProcIf (抽象クラス)を継承しそのメソッドをオーバーライドし実装する

    class UserProc : public CustomprocDspUserProcIf
    {
      void init(CustomprocCommand::CmdBase*);
      ...
    }
5.3.6.3. UserCustomDSPの動作
5.3.6.3.1. DSP内部の状態遷移

UserCustomDSPは Init , Exec , Flush , Set の各コマンドに対して下図のような状態遷移を行います。

Diagram
図 42. UserCustomDSP状態遷移
5.3.6.3.2. DSPの動作シーケンス

上記のフレームワーク上で作成したUserCustomDSPは、Audioの各機能の中で下図のシーケンスで動作します。
Audio Recorer機能の中のUserCutstomDSPの位置づけについてはInit MicFrontend(Recorder)を、Audio Recognizerの場合はInit MicFrontend(Recognizer)を参照して下さい。

下図からも分かる通り、 Init , Set コマンドはユーザーコードからのAPIコールがトリガとなり送られます。
Exec , Flush コマンドはAudioSubSystem内部で(音声キャプチャする度に)送られるようになっています。
(※ Exec , Flush コマンドはユーザーコードから送る必要はありません。)

AudioRecorder機能とUserCustomDSPの動作シーケンス

全体の流れは下記の通りです。

  1. AUDCMD_INIT_MICFRONTENDで指定されたバイナリファイルからDSPを起動します。

  2. AUDCMD_INIT_PREPROCESS_DSPでUserCustomDSPに Init コマンドが送られます。ch数やビット長など、処理に必要なパラメータを送るのに使用します。

  3. AUDCMD_STARTRECで音声キャプチャが開始され、それらが順次 Exec コマンドで送られます。これにUserCustomDSPで信号処理を行います。

  4. AUDCMD_SET_PREPROCESS_DSPSet コマンドが送られます。記録動作中でも送ることが出来ますのでフィルタ係数などを設定するのに使用します。

  5. AUDCMD_STOPRECで音声キャプチャが停止され、最終フレームの Exec に続いて Flush が送られます。遅延分の掃出しなどに使用します。

Diagram
図 43. AudioRecorder機能のHighLevelAPIコマンドとUserCustomDSP動作シーケンス
AudioRecognizer機能とUserCustomDSPの動作シーケンス

全体の流れは下記の通りです。

  1. AUDCMD_INIT_RECOGNIZERで指定されたバイナリファイルからDSPを起動します。

  2. AUDCMD_INIT_RECOGNIZER_DSPでUserCustomDSPに Init コマンドが送られます。ch数やビット長など、認識処理に必要なパラメータを送るのに使用します。

  3. AUDCMD_START_RECOGNIZERで音声キャプチャが開始され、それらが順次 Exec コマンドで送られます。これにUserCustomDSPで認識処理を行います。

  4. AUDCMD_SET_RECOGNIZER_DSPSet コマンドが送られます。認識動作中でも送ることが出来ますのでに認識のパラメータなどを設定するのに使用します。

  5. AUDCMD_STOP_RECOGNIZERで音声キャプチャが停止され、最終フレームの Exec に続いて Flush が送られます。遅延分の掃出しなどに使用します。

Diagram
図 44. AudioRecognizer機能のHighLevelAPIコマンドとUserCustomDSP動作シーケンス

5.3.7. オーディオサブシステムのエラーについて

5.3.7.1. 概要

Audio SubSystem のHigh Level API は、コマンド・リザルトのデータ送受信によるインターフェースを持っています。

Audio SubSystem に向けて発行したコマンドに問題があった場合に、リザルトでAUDRLT_ERRORRESPONSEが返り、 ErrorResponseパラメータにエラー内容が格納されます。 このエラーをレスポンスエラーと呼びます。

また、Audio SubSystemの内部処理でエラーを検出した場合、内部イベントが発生し、AS_CreateAudioManagerで登録した callback関数でエラーが通知され、ErrorAttentionパラメータにエラー内容が格納されます。 これをアテンションエラーと呼びます。

レスポンスエラー、アテンションエラーに対しては、それぞれのエラーに応じて、不具合対応、エラー処理追加などを行って下さい。

5.3.7.2. レスポンスエラー

Audio SubSystem に発行したコマンドで、仕様通りの制御を行った場合、リザルトはそれぞれのコマンドに対する完了レスポンスとなります。
しかし、状態違反やパラメータの誤りなど、仕様と異なった制御を行った場合、リザルトでAUDRLT_ERRORRESPONSEが返り、 ErrorResponseパラメータにエラー内容が格納されます。

Diagram

リザルトのレスポンスエラーのデータ形式については、 リザルトフォーマットErrorResponse を参照してください。

この "ErrorResponse" には、"Error Code" が付加されており、この "Error Code" によって、どのような要因で、エラーが発生しているかがわかるようになっています。

以下に"Error Code" の一覧を示します。

表 22. Error Code List Table
Error Code Value Description

AS_ECODE_STATE_VIOLATION

0x01

状態違反

AS_ECODE_PACKET_LENGTH_ERROR

0x02

パケット長パラメータの誤り

AS_ECODE_COMMAND_CODE_ERROR

0x03

不明なコマンド

AS_ECODE_COMMAND_NOT_SUPPOT

0x04

無効なコマンド

AS_ECODE_AUDIO_POWER_ON_ERROR

0x05

電源ONの失敗

AS_ECODE_AUDIO_POWER_OFF_ERROR

0x06

電源OFFの失敗

AS_ECODE_DSP_LOAD_ERROR

0x07

DSPの起動失敗

AS_ECODE_DSP_UNLOAD_ERROR

0x08

DSPの終了失敗

AS_ECODE_DSP_VERSION_ERROR

0x09

DSPのバージョン不一致

AS_ECODE_SET_AUDIO_DATA_PATH_ERROR

0x0A

入出力パラメータの誤り

AS_ECODE_CLEAR_AUDIO_DATA_PATH_ERROR

0x0B

データパスのクリア失敗

AS_ECODE_NOT_AUDIO_DATA_PATH

0x0C

入出力が無効

AS_ECODE_DECODER_LIB_INITIALIZE_ERROR

0x0D

Decoder DSPの初期化失敗

AS_ECODE_ENCODER_LIB_INITIALIZE_ERROR

0x0E

Encoder DSPの初期化失敗

AS_ECODE_FILTER_LIB_INITIALIZE_ERROR

0x0F

Filter DSPの初期化失敗

AS_ECODE_COMMAND_PARAM_CODEC_TYPE

0x11

コーデック種別の指定の誤り

AS_ECODE_COMMAND_PARAM_CHANNEL_NUMBER

0x13

チャンネル数の指定の誤り

AS_ECODE_COMMAND_PARAM_SAMPLING_RATE

0x14

サンプリング周波数の指定の誤り

AS_ECODE_COMMAND_PARAM_BIT_RATE

0x15

ビットレートの指定の誤り

AS_ECODE_COMMAND_PARAM_BIT_LENGTH

0x16

ビット長の指定の誤り

[AS_ECODE_COMMAND_PARAM_COMPLEXITY]

0x17

圧縮率の指定の誤り

AS_ECODE_COMMAND_PARAM_ACTIVE_PLAYER

0x18

Playerインスタンスの指定の誤り

AS_ECODE_COMMAND_PARAM_INPUT_DEVICE

0x19

入力デバイスの指定の誤り

AS_ECODE_COMMAND_PARAM_OUTPUT_DEVICE

0x1A

出力デバイスの指定の誤り

AS_ECODE_COMMAND_PARAM_INPUT_HANDLER

0x1B

入力デバイスハンドルの指定の誤り

AS_ECODE_COMMAND_PARAM_INPUT_DB

0x28

ミュートパラメータの指定の誤り

AS_ECODE_DMAC_INITIALIZE_ERROR

0x2B

入出力機能の初期化失敗

AS_ECODE_DMAC_READ_ERROR

0x2C

入力データの取得失敗

AS_ECODE_CHECK_MEMORY_POOL_ERROR

0x2E

メモリプールの設定誤り

AS_ECODE_SIMPLE_FIFO_UNDERFLOW

0x2F

SimpleFIFOのデータが枯渇

AS_ECODE_SET_MIC_GAIN_ERROR

0x30

マイクゲインの指定誤り

AS_ECODE_SET_OUTPUT_SELECT_ERROR

0x32

出力先設定の指定誤り

AS_ECODE_INIT_CLEAR_STEREO_ERROR

0x33

ボリュームの指定誤り

AS_ECODE_SET_VOLUME_ERROR

0x34

ボリュームの指定誤り

AS_ECODE_SET_VOLUME_MUTE_ERROR

0x35

ミュート対象の指定誤り

AS_ECODE_SET_BEEP_ERROR

0x36

ビープパラメータの指定誤り

AS_ECODE_QUEUE_OPERATION_ERROR

0x37

データキュー管理の失敗

AS_ECODE_COMMAND_PARAM_RENDERINGCLK

0x39

動作モードの指定誤り

AS_ECODE_SET_RENDERINGCLK_ERROR

0x3A

動作モードの設定失敗

AS_ECODE_COMMAND_PARAM_SETSPDRVMODE

0x3B

スピーカドライブ能力指定誤り

AS_ECODE_SET_MICMAP_ERROR

0x3D

マイク指定の誤り

AS_ECODE_OBJECT_NOT_AVAILABLE_ERROR

0x3E

Objectレイヤモジュールを生成せずに使用した

"Error Code" の詳細は こちら を参照してください。

5.3.7.3. アテンションエラー

Audio SubSystem内部での処理中(コマンド処理ではなく)に何らかのエラーを検出した場合、通知用のイベントが発生します。 このイベントを受け取るためには、AS_CreateAudioManager でcallback関数を登録しておく必要があります。

Diagram

アテンションエラーのデータ形式については ErrorAttention を参照してください。

アテンションエラーには 再生動作時のES(Elementary Stream)の供給の途切れ(アンダーフロー)や、記録動作時のES書き込みバッファのあふれ(オーバーフロー)などのフロー制御のエラー、メモリリソースの枯渇や、リアルタイム処理の遅延といったシステムエラー、 HWから発生したエラーなど、復帰にシステムのリセットが必要となる致命的なエラーなどがあります。

これらのエラーは、"ErrorAttention"に付加されている"Attention Code"で判断することが出来ます。 発生した"Attention Code"に基づいて修正を行ってください。 また、実装方法を変えることで、エラーが改善されることもあります。

以下に、"ErrorAttention" に付加される、 "Attention Code" の一覧を示します。

表 23. Attention Code List Table
Attention Code Value Description

AS_ATTENTION_SUB_CODE_DMA_UNDERFLOW

0x01

DMA転送のアンダーフロー

AS_ATTENTION_SUB_CODE_DMA_OVERFLOW

0x02

DMA転送のオーバーフロー

AS_ATTENTION_SUB_CODE_DMA_ERROR

0x03

DMA転送の失敗

AS_ATTENTION_SUB_CODE_SIMPLE_FIFO_UNDERFLOW

0x05

SimpleFIFOのアンダーフロー

AS_ATTENTION_SUB_CODE_SIMPLE_FIFO_OVERFLOW

0x06

SimpleFIFOのオーバーフロー

AS_ATTENTION_SUB_CODE_ILLEGAL_REQUEST

0x07

不正なイベントの受信

AS_ATTENTION_SUB_CODE_INTERNAL_STATE_ERROR

0x08

内部状態の異常

AS_ATTENTION_SUB_CODE_UNEXPECTED_PARAM

0x09

内部パラメータの異常

AS_ATTENTION_SUB_CODE_QUEUE_POP_ERROR

0x0A

内部キューのPOPエラ

AS_ATTENTION_SUB_CODE_QUEUE_PUSH_ERROR

0x0B

内部キューのPUSHエラ

AS_ATTENTION_SUB_CODE_QUEUE_MISSING_ERROR

0x0C

内部キューの枯渇

AS_ATTENTION_SUB_CODE_MEMHANDLE_ALLOC_ERROR

0x0D

メモリハンドルの取得失敗

AS_ATTENTION_SUB_CODE_MEMHANDLE_FREE_ERROR

0x0E

メモリハンドルの解放失敗

AS_ATTENTION_SUB_CODE_TASK_CREATE_ERROR

0x0F

タスクの生成失敗

AS_ATTENTION_SUB_CODE_RESOURCE_ERROR

0x10

インスタンスの生成や削除の失敗

AS_ATTENTION_SUB_CODE_DSP_LOAD_ERROR

0x12

DSPの起動失敗

AS_ATTENTION_SUB_CODE_DSP_UNLOAD_ERROR

0x13

DSPの終了失敗

AS_ATTENTION_SUB_CODE_DSP_EXEC_ERROR

0x14

DSPの処理でエラー

AS_ATTENTION_SUB_CODE_DSP_ILLEGAL_REPLY

0x16

DSPから不正なデータ受信

AS_ATTENTION_SUB_CODE_DSP_VERSION_ERROR

0x18

DSPのバージョン不一致

AS_ATTENTION_SUB_CODE_BASEBAND_ERROR

0x19

AudioDriverでエラー

AS_ATTENTION_SUB_CODE_STREAM_PARSER_ERROR

0x1A

ESデータの解析エラー

AS_ATTENTION_SUB_CODE_DSP_LOG_ALLOC_ERROR

0x1E

DSPのログ用バッファの取得失敗

AS_ATTENTION_SUB_CODE_DSP_ASSETION_FAIL

0x1F

DSPの処理で致命的エラー

AS_ATTENTION_SUB_CODE_DSP_SEND_ERROR

0x20

DSPへのコマンド送信エラー

"Attention Code" の詳細は こちら を参照してください。

Attention Level

Attention通知にはレベルが指定されており、そのエラーに対する深刻度と同時に復帰の処理方法が変わります。

表 24. Attention Level
Level value Description

FATAL

0x03

システムコールエラー等、回復不能なもので、復帰にリセットを要求します。

ERROR

0x02

内部エラー(キューFull/Empty,DSPロード/アンロードなど)でAudioシステムの動作が継続できないようなエラーです。システムを初期状態(Ready状態)に戻すことで復帰が可能になります。

WARN

0x01

エンコード・デコードエラー、データのアンダーフロー・オーバーフローなど、動作に異常があり、音声データなどには異常が発生している可能性があるが、動作は継続できるものです。

5.3.7.4. Error Code List

"Error Code"の詳細は下記の通りです。

5.3.7.4.1. AS_ECODE_STATE_VIOLATION
code

0x01

description

Audio Sub System内で状態違反が発生しています。
要求したコマンドとAudioSubSystem内の状態が合っていませんのでコマンドを受け付けることが出来ません。
状態を遷移するコマンドにて正しい状態への遷移を行った後、改めてコマンドを送信し直してください。

AudioSubSystem内の状態遷移については下記を参照してください。

状態遷移について

5.3.7.4.2. AS_ECODE_PACKET_LENGTH_ERROR
code

0x02

description

コマンドパケットのパケット長パラメータが誤っています。
パケット長はWord(4byte)単位の指定です。byte単位ではありません。
正しい値が設定されていることを確認してください。

5.3.7.4.3. AS_ECODE_COMMAND_CODE_ERROR
code

0x03

description

不明なコマンドを受信しました。
コマンドIDを再度確認してください。

5.3.7.4.4. AS_ECODE_COMMAND_NOT_SUPPOT
code

0x04

description

送信したコマンドは有効になっていません。
コマンドを使用するには該当する機能をコンフィグで有効にする必要があります。

Audio PlayerとAudio Recorderのコンフィグについては下記を参照してください。

Audio Player
Audio Recorder

5.3.7.4.5. AS_ECODE_AUDIO_POWER_ON_ERROR
code

0x05

description

Audio電源のONが出来ません。既に電源が入っている可能性があります。

5.3.7.4.6. AS_ECODE_AUDIO_POWER_OFF_ERROR
code

0x06

description

Audio電源のOFFが出来ません。既に電源が落ちている可能性があります。

5.3.7.4.7. AS_ECODE_DSP_LOAD_ERROR
code

0x07

description

DSPのロード・起動が出来ません。

DSPの配置パスが正しく設定されていることを確認してください。
配置パスの設定については下記を参照してください。

AudioPlayer は Initialize player
AudioRecorder は Init recorder information

また、配置パスに、必要なDSPが置かれていない可能性があります。
AudioPlayerでは(再生ファイル種別に応じて) MP3DEC, WAVDEC が必要です。
AudioRecorderでは(記録ファイル種別に応じて) MP3ENC, SRC が必要です。
これらは sdk/modules/audio/dsp/ に提供されています。

5.3.7.4.8. AS_ECODE_DSP_UNLOAD_ERROR
code

0x08

description

DSPの終了・アンロードが出来ません。
既にアンロードされているか、またはロードがされていない可能性があります。

5.3.7.4.9. AS_ECODE_DSP_VERSION_ERROR
code

0x09

description

DSPのバージョンがAudioSubSytemが期待しているものと異なっており、使用できません。
使用しているSDKパッケージに同梱されるDSP sdk/modules/audio/dsp/ を使用してください。

5.3.7.4.10. AS_ECODE_SET_AUDIO_DATA_PATH_ERROR
code

0x0a

description

Audioデータのパス設定(入力/出力)が間違っています。
以下のパラメータが正しく設定されていることを確認してください。

AudioRecorder は Init recorder information
BaseBand は SetBaseBandStatusParam
Through mode は AsSetThroughPathParam

5.3.7.4.11. AS_ECODE_CLEAR_AUDIO_DATA_PATH_ERROR
code

0x0b

description

Audioデータのパス設定がクリアできません。

5.3.7.4.12. AS_ECODE_NOT_AUDIO_DATA_PATH
code

0x0c

description

入力デバイスまたは出力デバイスが有効になっていません。
BaseBandStatus または ThroughStatus に遷移する必要があります。

BasebandStatusへの遷移は SetBasebandStatus
ThroughStatusへの遷移は SetThroughStatus

5.3.7.4.13. AS_ECODE_DECODER_LIB_INITIALIZE_ERROR
code

0x0d

description

Decoder DSPから初期化エラーが応答されています。

5.3.7.4.14. AS_ECODE_ENCODER_LIB_INITIALIZE_ERROR
code

0x0e

description

Encoder DSPから初期化エラーが応答されています。

5.3.7.4.15. AS_ECODE_FILTER_LIB_INITIALIZE_ERROR
code

0x0f

description

Filter DSPから初期化エラーが応答されています。

5.3.7.4.16. AS_ECODE_COMMAND_PARAM_CODEC_TYPE
code

0x11

description

指定されたAudio Codecの種別が誤っています。

AudioSubSystemで対応しているCodecは下記を参照してください。

AudioPlayer は Initialize player
AudioRecorder は Init recorder information

5.3.7.4.17. AS_ECODE_COMMAND_PARAM_CHANNEL_NUMBER
code

0x13

description

指定されたch数が誤っている、もしくは他パラメータとの組み合わせでエラーとなっています。
AudioPlayer, AudioRecorderともに、Codecタイプなど他パラメータとch数の組み合わせには制限があります。

それぞれの制限の詳細については下記を参照してください。

AudioPlayer は Initialize player
AudioRecorder は Init recorder information

5.3.7.4.18. AS_ECODE_COMMAND_PARAM_SAMPLING_RATE
code

0x14

description

指定されたサンプリング周波数が誤っている、もしくは他パラメータとの組み合わせでエラーとなっています。
AudioPlayer, AudioRecorderともに、Codecタイプなど他パラメータとサンプリング周波数の組み合わせには制限があります。

またAudioPlayerの場合は、Audioデータのヘッダなどに含まれるサンプリング周波数の情報と
指定されたサンプリング周波数が異なる場合も当エラーとなります。

それぞれの制限の詳細については下記を参照してください。

AudioPlayer は Initialize player
AudioRecorder は Init recorder information

5.3.7.4.19. AS_ECODE_COMMAND_PARAM_BIT_RATE
code

0x15

description

指定されたビットレートが誤っている、もしくは他パラメータとの組み合わせでエラーとなっています。
AudioRecorderでは、Codecタイプなど他パラメータとビットレートの組み合わせには制限があります。

制限の詳細については下記を参照してください。

Init recorder information

5.3.7.4.20. AS_ECODE_COMMAND_PARAM_BIT_LENGTH
code

0x16

description

指定されたビット長が誤っている、もしくは他パラメータとの組み合わせでエラーとなっています。

それぞれの制限の詳細については下記を参照してください。

AudioPlayer は Initialize player
AudioRecorder は Init recorder information

また、Recorder状態で記録をする場合に24bitを指定する際は、HiResoモードに切り替える必要があります。

モードの切り替えについては Init Rendering Clock を参照してください。

5.3.7.4.21. AS_ECODE_COMMAND_PARAM_ACTIVE_PLAYER
code

0x18

description

有効にするPlayerの指定が誤っています。
Player状態へ遷移できません。

パラメータについては下記を参照してください。

Change to Player Status

5.3.7.4.22. AS_ECODE_COMMAND_PARAM_INPUT_DEVICE
code

0x19

description

指定された入力デバイスが誤っています。

パラメータについては下記を参照してください。

Change to Player Status
Change to Recorder Status

5.3.7.4.23. AS_ECODE_COMMAND_PARAM_OUTPUT_DEVICE
code

0x1A

description

指定された出力デバイスが誤っています。

パラメータについては下記を参照してください。

Change to Player Status
Change to Recorder Status

5.3.7.4.24. AS_ECODE_COMMAND_PARAM_INPUT_HANDLER
code

0x1B

description

指定された入力デバイスハンドルが誤っています。
SimpleFIFOのハンドルやcallback関数が正しく設定されているか確認してください。

パラメータについては下記を参照してください。

Change to Player Status

5.3.7.4.25. AS_ECODE_COMMAND_PARAM_CONFIG_TABLE
code

0x1F

description

MFEまたはMPPフィルタの係数テーブルアドレスが正しくありません。 (※MFEおよびMPPは未サポートです。)

5.3.7.4.26. AS_ECODE_COMMAND_PARAM_WITH_MFE
code

0x20

description

MFEのアクティベーション指定パラメータが誤っています。
(※MFEは未サポートです。)

5.3.7.4.27. AS_ECODE_COMMAND_PARAM_WITH_MPP
code

0x21

description

MPPのアクティベーション指定パラメータが誤っています。
(※MPPは未サポートです。)

5.3.7.4.28. AS_ECODE_COMMAND_PARAM_INPUT_DB
cod

0x28

description

ミュート指定パラメータが誤っています。

パラメータについては下記を参照してください。

Set Volume Mute

5.3.7.4.29. AS_ECODE_DMAC_INITIALIZE_ERROR
code

0x2B

description

音声キャプチャ・レンダリングの初期設定に失敗しました。

5.3.7.4.30. AS_ECODE_DMAC_READ_ERROR
code

0x2C

description

Audioデータ取り込みに失敗しました。

5.3.7.4.31. AS_ECODE_CHECK_MEMORY_POOL_ERROR
code

0x2E

description

AudioSubSystem内のObject Create時にMemoryPoolのチェックエラーが発生しました。
メモリプールIDが正しくCreateのAPIに渡されていない、またはMemoryPoolの作成が誤っている可能性があります。

メモリプールIDの指定についてはこちらを参考にして下さい。

Create Media Player
Create Media Recorder

MemoryPoolの作成についてはこちらを参考にして下さい。

AudioPlayerのPoolAreas設定

5.3.7.4.32. AS_ECODE_SIMPLE_FIFO_UNDERFLOW
code

0x2F

description

Audio再生開始時に、ESバッファとして使用しているSimpleFIFOがアンダーフローしています。
再生を開始するとAudioSubSystemはすぐにSimpleFIFOからESデータを抜出し、デコードを開始しますので
アプリケーションではあらかじめ再生開始前にESデータを入れておく必要があります。

Diagram
5.3.7.4.33. AS_ECODE_SET_MIC_GAIN_ERROR
code

0x30

description

マイク入力のゲイン設定値が誤っています。
アナログマイクとデジタルマイクで設定の値域が異なります。

パラメータについては下記を参照してください。

Initialize Mic Gain

5.3.7.4.34. AS_ECODE_SET_OUTPUT_SELECT_ERROR
code

0x32

description

指定された出力先設定に誤りがあります。

InitOutputSelect

5.3.7.4.35. AS_ECODE_INIT_CLEAR_STEREO_ERROR
code

0x33

description

Clear Stereoの設定エラーが発生しました。

5.3.7.4.36. AS_ECODE_SET_VOLUME_ERROR
code

0x34

description

指定した再生ボリュームが誤っています。
ボリュームの設定値には制限があります。パラメータの詳細は下記を参照してください。

Set Volume

5.3.7.4.37. AS_ECODE_SET_VOLUME_MUTE_ERROR
code

0x35

description

AudioDriverへのボリューム設定が失敗しました。

5.3.7.4.38. AS_ECODE_SET_BEEP_ERROR
code

0x36

description

指定したビープ音パラメータが誤っています。
音量・周波数の設定値には制限があります。パラメータの詳細は下記を参照してください。

5.3.7.4.39. AS_ECODE_QUEUE_OPERATION_ERROR
code

0x37

description

AudioSubSystem内部キューの操作(push, pop)エラーが発生しました。

5.3.7.4.40. AS_ECODE_COMMAND_PARAM_RENDERINGCLK
code

0x39

description

HiResoモード設定のパラメータエラーです。
設定できるパラメータについては下記を参照してください。

SetRenderingClock

5.3.7.4.41. AS_ECODE_SET_RENDERINGCLK_ERROR
code

0x3A

description

HiResoモード設定エラーです。
HiResoモードを使用するには、コンフィグでAudioのクロックを49.152Mhzに設定する必要があります。

cd sdk
tools/config.py -m
[CXD56xx Configuration]
  [Audio]
    [Audio baseband config settings]
      [CXD5247 settings]
        [X'tal frequency of the CXD5247] <- 49.152Mhz
5.3.7.4.42. AS_ECODE_COMMAND_PARAM_SETSPDRVMODE
code

0x3B

description

スピーカドライブ能力の指定が誤っています。

設定できるパラメータについては下記を参照してください。

SetSpDrv

5.3.7.4.43. AS_ECODE_SET_MICMAP_ERROR
code

0x3D

description

マイク選択の指定が誤っています。

設定できるパラメータについては下記を参照してください。

SetMicMap

5.3.7.4.44. AS_ECODE_OBJECT_NOT_AVAILABLE_ERROR
code

0x3E

description

Objectレイヤモジュールを生成せずに、そのオブジェクトを使用した場合通知されます。
各Objectの中で、Createを呼ばずに呼び出しているObjectがないかどうかを確認してください。

5.3.7.5. Attention Code List

"Attention Code" の詳細は下記の通りです。

5.3.7.5.1. AS_ATTENTION_SUB_CODE_DMA_UNDERFLOW
Code

0x01

Attention Level

ERROR

Description

DMA転送のアンダーフローが発生しました。
DMAへの転送リクエストがDMAのデータ転送スピードよりも遅い可能性があります。 またはDMA転送が停止されているかもしれません。
DMAの転送スピードは、通常モード時で48000サンプル/秒、HiResoモード時は192000サンプル/秒です。

Error Handling

このエラーが発生する場合、アプリケーションタスク処理がリアルタイム処理よりも優先されている可能性があります。
各タスクの優先度を見直してみてください。

5.3.7.5.2. AS_ATTENTION_SUB_CODE_DMA_OVERFLOW
Code

0x02

Attention Level

ERROR

Description

DMA転送のオーバーフローが発生しました。
DMAへの転送リクエストがDMAのデータ転送スピードよりも速い可能性があります。
またはDMA転送が開始されていないかもしれません。

DMAの転送スピードは、通常モード時で48000サンプル/秒、HiResoモード時は192000サンプル/秒です。

Error Handling

または、記録動作時の場合、HWが供給しているAudioのマスタクロックが停止している可能性があります。クロックが正しく供給されいるか?を確認してください。 再生動作時に発生する場合は、正しいクロックが発信されているかを確認してください。

5.3.7.5.3. AS_ATTENTION_SUB_CODE_DMA_ERROR
Code

0x03

Attention Level

FATAL, ERROR

Description

DMAハードウェアからエラーが応答されています。
DMAへの転送リクエストを送る前に転送開始を要求した可能性があります。

Error Handling

通常は発生し得ないエラーです。
SDK内部に不具合がある可能性があります。

5.3.7.5.4. AS_ATTENTION_SUB_CODE_SIMPLE_FIFO_UNDERFLOW
Code

0x05

Attention Level

WARNING

Description

AudioPlayer動作中にSimpleFIFOのアンダーフローが発生しました。
SimpleFIFOはアプリケーションからAudioSubSystemへESデータの渡すバッファに使用しています。
AudioSubSystemのデータ引き抜きスピードにアプリケーションがついていけていません。

Error Handling

タスク優先度を調整しアプリケーションからのバッファ供給が間に合うようにする、
バッファサイズを増やすなどしてデータ投入が間に合うようにしてください。

5.3.7.5.5. AS_ATTENTION_SUB_CODE_SIMPLE_FIFO_OVERFLOW
Code

0x06

Attention Level

WARNING

Description

AudioRecorder動作中にSimpleFIFOのオーバーフローが発生しました。
SimpleFIFOはAudioSubSystemからアプリケーションへEncodedESデータを渡すバッファに使用しています。
AudioSubSystemのデータ投入スピードにアプリケーションがついていけていません。

Error Handling

タスク優先度を調整しアプリケーションのバッファデータ引き抜きが間に合うようにする、
バッファサイズを増やすなどしてデータ引き抜きが間に合うようにしてください。

5.3.7.5.6. AS_ATTENTION_SUB_CODE_ILLEGAL_REQUEST
Code

0x07

Attention Level

ERROR

Description

AudioSubSystemの内部で不正なイベントが受信されました。
制御シーケンスが異常となっている可能性があります。

Error Handling

通常は発生し得ないエラーです。
SDK内部に不具合がある可能性があります。

5.3.7.5.7. AS_ATTENTION_SUB_CODE_INTERNAL_STATE_ERROR
Code

0x08

Attention Level

ERROR

Description

MediaPlayer内で状態異常が起きています。

Error Handling

通常は発生し得ないエラーです。
SDK内部に不具合がある可能性があります。

5.3.7.5.8. AS_ATTENTION_SUB_CODE_UNEXPECTED_PARAM
Code

0x09

Attention Level

ERROR

Description

コマンドパラメータが誤っています。

Error Handling

コマンドパラメータを見直してください。

5.3.7.5.9. AS_ATTENTION_SUB_CODE_QUEUE_POP_ERROR
Code

0x0A

Attention Level

ERROR

Description

内部キューのPOPエラーが発生しています。

Error Handling

通常は発生し得ないエラーです。
SDK内部に不具合がある可能性があります。

5.3.7.5.10. AS_ATTENTION_SUB_CODE_QUEUE_PUSH_ERROR
Code

0x0B

Attention Level

ERROR

Description

内部キューのPUSHエラーが発生しています。

Error Handling

通常は発生し得ないエラーです。
SDK内部に不具合がある可能性があります。

5.3.7.5.11. AS_ATTENTION_SUB_CODE_QUEUE_MISSING_ERROR
Code

0x0C

Attention Level

ERROR

Description

内部キューが意図せず空になっています。

Error Handling

通常は発生し得ないエラーです。
SDK内部に不具合がある可能性があります。

5.3.7.5.12. AS_ATTENTION_SUB_CODE_MEMHANDLE_ALLOC_ERROR
Code

0x0D

Attention Level

ERROR

Description

メモリハンドルの取得に失敗しました。
全てのメモリハンドルが使用中になっているか、ハンドルのIDが間違っています。

Error Handling

メモリハンドルの段数が足りない場合はメモリプール設定を見直してください。
設定の方法は下記を参考にして下さい。(AudioPlayerの設定例です)+
PlayerのMemoryPool概要
PlayerのMemoyPool定義

5.3.7.5.13. AS_ATTENTION_SUB_CODE_MEMHANDLE_FREE_ERROR
Code

0x0E

Attention Level

ERROR

Description

メモリハンドルの解放に失敗しました。
解放しようとしたハンドルは既に解放されていた可能性があります。

Error Handling

通常は発生し得ないエラーです。
SDK内部に不具合がある可能性があります。

5.3.7.5.14. AS_ATTENTION_SUB_CODE_TASK_CREATE_ERROR
Code

0x0F

Attention Level

ERROR

Description

AudioSubSystem内部で使用するタスクの生成に失敗しました。
システム全体でのタスク生成数が上限に達している可能性があります。

Error Handling

タスク生成吸う上限を増やすか、アプリケーションで使用するタスクを減らしてください。

タスク生成数の上限を増やす場合はコンフィグで設定できます。

cd sdk
cd tools/config.py -k -m
[RTOS Features]
  [Tasks and Scheduling]
    [Max number of tasks] <- Set this.
5.3.7.5.15. AS_ATTENTION_SUB_CODE_RESOURCE_ERROR
Code

0x10

Attention Level

ERROR

Description

AudioSubSystem内で使用するインスタンスの生成・削除に失敗しました。
Object/ComponentのCreateAPI, DeleteAPIを2重にコールしている可能性があります。
またはHead領域が不足してるかもしれません。

Error Handling

通常は発生し得ないエラーです。
SDK内部に不具合がある可能性があります。

5.3.7.5.16. AS_ATTENTION_SUB_CODE_DSP_LOAD_ERROR
Code

0x12

Attention Level

ERROR

Description

DSPバイナリのロードに失敗しました。
DSPバイナリファイルが指定されたフォルダパスに無い可能性があります。

Error Handling

ファイル有無の確認、またはフォルダパスの指定を見直しをして下さい。
フォルダパスの指定については下記を参照してください。

AudioPlayer は Initialize player
AudioRecorder は Init recorder information

5.3.7.5.17. AS_ATTENTION_SUB_CODE_DSP_UNLOAD_ERROR
Code

0x13

Attention Level

ERROR

Description

DSPアンロードに失敗しました。 既にアンロードされているか、そもそもロードされていない可能性があります。

Error Handling

通常は発生し得ないエラーです。
SDK内部に不具合がある可能性があります。

5.3.7.5.18. AS_ATTENTION_SUB_CODE_DSP_EXEC_ERROR
Code

0x14

Attention Level

ERROR, WARNING

Description

DSPでの処理実行時にエラーが発生しました。
直ちにAudioSubSystemの動作に影響が出るものではありませんが
デコード・エンコード・フィルタの結果が正常でない可能性があります。
(一時的に音が乱れる、データが抜けるなどの可能性があります。)

Error Handling

再生動作時の場合、Audioデータが壊れている可能性があります。
Audioデータの確認をして下さい。

5.3.7.5.19. AS_ATTENTION_SUB_CODE_DSP_ILLEGAL_REPLY
code

0x16

Attention Level

ERROR

Description

DSPからの応答コマンドパケットが壊れています。

Error Handling

通常は発生し得ないエラーです。
SDK内部に不具合がある可能性があります。

5.3.7.5.20. AS_ATTENTION_SUB_CODE_DSP_VERSION_ERROR
Code

0x18

Attention Level

ERROR

Description

DSPバージョンエラーが発生しました。DSPをロードできません。

Error Handling

SDKにパックされているDSPバイナリを使用してください。
DSPバイナリは sdk/modules/audio/dsp にあります。

5.3.7.5.21. AS_ATTENTION_SUB_CODE_BASEBAND_ERROR
Code

0x19

Attention Level

ERROR

Description

Audio Driverでレジスタの設定エラーが発生しました。

Error Handling

通常は発生し得ないエラーです。
SDK内部に不具合がある可能性があります。

5.3.7.5.22. AS_ATTENTION_SUB_CODE_STREAM_PARSER_ERROR
Code

0x1A

Attention Level

ERROR

Description

AudioPlayerにてESデータの解析エラーが発生しています。
Initialize player で設定したパラメータとESデータを解析した結果が異なっています。

Error Handling

AudioSubSystemに渡すESデータが間違っていないか、壊れていないかを確認してください。

5.3.7.5.23. AS_ATTENTION_SUB_CODE_DSP_LOG_ALLOC_ERROR
Code

0x1E

Attention Level

ERROR

Description

DSPログ用バッファの取得に失敗しました。
複数のDSPが立ち上がっている場合はログ用バッファ領域の残量が足りない可能性があります。

Error Handling

DSPログ用バッファ領域はアプリケーションやコンフィグから設定することはできません。

ただし、DSPログが不要であればコンフィグでロギング機能そのものをOFFすることが出来ます。

cd sdk
cd tools/config.py -k -m
[Audio Utilities]
  [Audio component menu]
    [dsp debug dump] <- Set to "No".
5.3.7.5.24. AS_ATTENTION_SUB_CODE_DSP_ASSETION_FAIL
Code

0x1F

Attention Level

ERROR

Description

DSP内部でエラーが発生し処理を継続することが不可能です。

Error Handling

システムのリセットが必要です。

5.3.7.5.25. AS_ATTENTION_SUB_CODE_DSP_SEND_ERROR
Code

0x20

Attention Level

ERROR

Description

DSPへのコマンド送信エラーが発生しました。

Error Handling

通常は発生し得ないエラーです。
SDK内部に不具合がある可能性があります。

5.3.7.6. Module ID List

AudioSubSystem内部で使用するモジュールのID一覧です。
Attention callbackでアテンションコードとともに通知され、どのモジュールでエラーが発生したかを判断します。

表 25. Module ID List Table
Module ID Value Description

AS_MODULE_ID_AUDIO_MANAGER

0

Audio Manager

AS_MODULE_ID_AUDIO_DRIVER

1

Audio Baseband Driver

AS_MODULE_ID_MIC_FRONTEND_OBJ

2

FrontEnd Object

AS_MODULE_ID_INPUT_DATA_MNG_OBJ

3

Input Data Manager Object

AS_MODULE_ID_MEDIA_RECORDER_OBJ

4

Media Recorder Object

AS_MODULE_ID_OUTPUT_MIX_OBJ

5

Output Mix Object

AS_MODULE_ID_PLAYER_OBJ

6

Player Object

AS_MODULE_ID_RECOGNITION_OBJ

7

Recognition Object

AS_MODULE_ID_SOUND_EFFECT_OBJ

8

Sound Effect Object

AS_MODULE_ID_SYNTHESIZER_OBJ

9

Synthesizer Object

AS_MODULE_ID_CAPTURE_CMP

10

Capture Component

AS_MODULE_ID_DECODER_CMP

11

Decoder Component

AS_MODULE_ID_ENCODER_CMP

12

Encoder Component

AS_MODULE_ID_FILTER_CMP

13

Filter Component

AS_MODULE_ID_RECOGNITION_CMP

14

Recognition Component

AS_MODULE_ID_RENDERER_CMP

15

Renderer Component

AS_MODULE_ID_POSTPROC_CMP

16

Postfilter Component

AS_MODULE_ID_OSCILLATOR_CMP

17

Oscillator Component

AS_MODULE_ID_CUSTOM_CMP

18

Custom Component

5.3.8. 使用しているライブラリ

オーディオ・サブシステムは以下のライブラリを必要とします。


5.4. Camera

5.4.1. 概要

CXD5602には8ビットパラレルのCamera I/Fが備わっており、このI/Fを持つカメラモジュールを接続することができます。現在、Spresenseでは、Sony ISX012もしくはSony ISX019を搭載するカメラモジュールをサポートしています。 通常、カメラモジュールはデータ用のインターフェースに加えて、モジュールの制御を行うインターフェースを持っています。ISX012とISX019では、その制御用I/FにI2Cが用いられています。 以下にHWの構成の概要を示します。

camera hw overview
図 45. Camra HW Overview

CXD5602内部には、CISIFと呼ばれるCamera I/Fブロックがあり、このブロックで8ビットパラレル信号とCXD5602内部バスのブリッジを行なっています。ISX012カメラモジュールとISX019カメラモジュールの場合、これに加えて、I2Cバスを使って制御を行なっています。

この章では、このCamera I/Fに接続されたカメラモジュールをSpresense SDKで制御するための概要を説明します。

Spresense SDKのCamera制御では、Linuxでお馴染みのV4L2に非常によく似たドライバI/Fを提供しており、V4L2を用いたコードからの流用をしやすくしています。このI/FをV4S (Video for Spresense) と呼びます。V4Sでは、デバイスファイルを介して、open, close, ioctlなどの標準のI/Fを用い、ISX012などのデバイスを意識することなくCameraとしての機能を抽象化したAPIを提供します。

camera v4s overview
図 46. V4S SW Overview

V4Sでは、カメラの制御として、2つの仮想Videoストリームを提供します。 2つの仮想ストリームのうち、1つはCameraのPreview画像のような動画を扱うためのストリームとして、もう一つは静止画を取得するためのストリームとしての役割を持っています。

camera v4s dataflow
図 47. V4S Dataflow

これら2つのストリームに対して、アプリケーションからデータを取得するには、アプリケーションで用意したバッファをVIDIOC_QBUFを用いてドライバにセットし、VIDIOC_DQBUFでVIDIOC_QBUFでセットしたバッファを取ることでイメージデータを取り出すことができます。

アプリケーションが用意するバッファは、memalign()等を用いて獲得した、32ビットアラインメントである必要があります。

各ストリームの指定は、v4l2_buf_typeで指定し、V4L2_BUF_TYPE_VIDEO_CAPTUREが動画を扱うストリーム、V4L2_BUF_TYPE_STILL_CAPTUREが静止画用のストリームに対応しています。

この、V4L2_BUF_TYPE_STILL_CAPTUREは、V4S固有のパラメータになります。

V4Sの初期化からイメージデータをキャプチャするまでの概略の流れは以下のようになります。

Diagram
図 48. V4S Sequence Overview

5.4.2. 状態遷移

ストリーム毎に状態を管理しており、アプリケーションからは並行して制御可能です。 ただし、imageの取得についてはV4L2_BUF_TYPE_STILL_CAPTURE制御優先であり、VIDIOC_TAKEPICT_START - VIDIOC_TAKEPICT_STOP間はV4L2_BUF_TYPE_VIDEO_CAPTURE側のimage取得は停止します(状態遷移図において"dma"状態ではなくなる)。

Diagram

5.4.3. V4Sサポート ioctlコマンド

表 26. V4Sサポート ioctlコマンド
分類 command 目的 Spresenseカスタマイズ

Capability取得

VIDIOC_QUERYCAP

接続デバイスの情報を取得する。

ドライバ名を取得するためのメンバdriverのみサポートしています。

バッファ制御

VIDIOC_REQBUFS

ドライバのバッファ管理領域の初期設定を行う。

パラメータ"v4l2_buf_mode mode"を追加し、 バッファ群にRING構造を持たせられるようにしています。

VIDIOC_QBUF

アプリが用意したバッファをエンキューする。

V4L2準拠

VIDIOC_DQBUF

imageデータが入ったバッファをデキューする。

V4L2準拠

VIDIOC_CANCEL_DQBUF

VIDIOC_DQBUFを取り消す。

左記目的のために追加したSpresense独自コマンド。

ストリーム制御

VIDIOC_STREAMON

ストリームを開始する。

V4L2準拠

VIDIOC_STREAMOFF

ストリームを停止する。

V4L2準拠

VIDIOC_TAKEPICT_START

静止画撮影開始

左記目的のために追加したSpresense独自コマンド。

VIDIOC_TAKEPICT_STOP

静止画撮影停止

左記目的のために追加したSpresense独自コマンド。

フレーム設定の値域確認

VIDIOC_TRY_FMT

INパラメータで指定したpixelフォーマットとimageサイズの組み合わせが 設定可能かどうかの確認。

V4L2準拠

フレーム設定の変更

VIDIOC_S_FMT

pixelフォーマットとimageサイズを設定する。

V4L2準拠

VIDIOC_S_PARM

frame intervalを設定する。(秒単位の値を分数の形で設定する。分数は分母と分子をそれぞれ整数で設定する。)

V4L2準拠

VIDIOC_G_PARM

frame intervalを取得する。(秒単位の値を分数の形で取得する。分数は分母と分子がそれぞれ整数で表現される。)

V4L2準拠

クリップ領域の変更

VIDIOC_S_SELECTION

クリップ領域の左上端の座標とサイズを設定する。

V4L2準拠

VIDIOC_G_SELECTION

設定されているクリップ領域の左上端の座標とサイズを取得する。

V4L2準拠

カメラ設定の値域確認

VIDIOC_QUERYCTRL

カメラ設定の値域を確認する。

V4L2準拠

VIDIOC_QUERY_EXT_CTRL

カメラ設定の値域を確認する。 VIDIOC_QUERYCTRLの拡張APIで、VIDIOC_QUERYCTRLを包含する。

V4L2準拠

VIDIOC_QUERYMENU

カメラ設定で離散値をとる項目について、とりうる値を取得する。

V4L2準拠

カメラ設定の現在値確認

VIDIOC_G_CTRL

カメラ設定の現在値を確認する。

V4L2準拠

VIDIOC_G_EXT_CTRLS

カメラ設定の現在値を確認する。 VIDIOC_G_CTRLの拡張APIで、VIDIOC_G_CTRLを包含する。

V4L2準拠

カメラ設定の変更

VIDIOC_S_CTRL

カメラ設定を変更する。

V4L2準拠

VIDIOC_S_EXT_CTRLS

カメラ設定を変更する。 VIDIOC_S_CTRLの拡張APIで、VIDIOC_S_CTRLを包含する。

V4L2準拠

VIDIOC_DO_HALFPUSH

シャッターボタンを半押しした場合に相当する設定変更を行う。

アプリケーションにおける半押し制御を簡略化するために追加したSpresense独自コマンド。

5.4.4. SPRESENSE独自仕様

5.4.4.1. JPEG + YUV422フォーマット

ioctl(VIDIOC_S_FMT)を用いて、ある1フレームのimageを JPEG、YUV422の2つのデータフォーマットで同時に取得する ことができます。

例えば、写真を撮ってJPEGで保存しつつ、保存したものと同じ画像をディスプレイに表示 するようなアプリをJPEGデコーダを用いずに実現できます。

この機能を用いて取得したYUV422データについては、imageproc_convert_yuv2rgb() APIを用いてRGB565フォーマットに変換することができます。
Diagram
図 49. JPEG + YUV4:2:2フォーマット
5.4.4.1.1. 設定方法

通常、VIDIOC_S_FMTを1回実行して、width, height、pixelformatを設定しますが、 このフォーマットを使用する場合は計2回実行します。

パラメータ構造体 struct v4l2_formatの メンバtypeには、1回目、2回目ともに同一の設定で、このフォーマットを設定したいストリームV4L2_BUF_TYPE_VIDEO_CAPTUREもしくはV4L2_BUF_TYPE_STILL_CAPTUREを設定します。 メンバ fmt.pixには、以下に従って、1回目にJPEGの設定を行い、2回目にYUV422の設定を行います。

表 27. JPEG + YUV422 or RGB565フォーマット設定時のパラメータ設定
回目 pixelformat width height

1回目

V4L2_PIX_FMT_JPEG_WITH_SUBIMG

JPEGのwidth

JPEGのheight

2回目

V4L2_PIX_FMT_SUBIMG_UYVY

YUV422のwidth

YUV422のheight

2回目のpixelformat指定は_SUBIMG_がついたデファインを指定する必要があります。 例えばV4L2_PIX_FMT_UYVYを設定した場合は、単純にYUV422フォーマットが設定された状態になります。

また、使用可能な設定については、使用デバイスに応じて、ISX012で使用可能な設定もしくはISX019で使用可能な設定を参照ください。

5.4.4.2. 電源ON後の3A調整時間短縮用の設定API

ioctl(VIDIOC_S_EXT_CTRLS)およびioctl(VIDIOC_G_EXT_CTRLS)でV4L2_CID_3A_PARAMETERを利用することで、電源ON後の3A調整時間を短くすることができます。
また、3A調整完了有無はV4L2_CID_3A_STATUSで確認できます。

Diagram
図 50. 3A調整時間短縮シーケンス
5.4.4.2.1. 3Aパラメータ取得・3A調整値の初期値変更

以下の設定で、ioctl(VIDIOC_G_EXT_CTRLS), ioctl(VIDIOC_S_EXT_CTRLS)を実行することで、 3Aパラメータの取得・3A調整値の初期値変更が行えます。

  • ctrl_class : V4L2_CTRL_CLASS_CAMERAを設定する。

  • control→id : V4L2_CID_3A_PARAMETERを設定する。

  • control→p_u16 : 要素数3のuint16型配列の実体を定義して、アドレスをp_u16に設定する。

ioctl(VIDIOC_G_EXT_CTRLS)実行時は、 control→p_u16 が指すアドレスに3Aパラメータが設定されてきます。 ioctl(VIDIOC_S_EXT_CTRLS)実行時は、逆に control→p_u16 が指すアドレスに値を設定することで、3A調整値の初期値を変更することができます。

5.4.4.2.2. 3A調整状態取得

以下の設定で、ioctl(VIDIOC_G_EXT_CTRLS)を実行することで、3A調整状態を取得することができます。

  • ctrl_class : V4L2_CTRL_CLASS_CAMERAを設定する。

  • control→id : V4L2_CID_3A_STATUSを設定する。

調整完了している場合、 control→value にV4L2_3A_STATUS_STABLEが設定されます。 調整中の機能がある場合は、該当機能をあらわすビット(V4L2_3A_STATUS_AE_OPERATING, V4L2_3A_STATUS_AWB_OPERATING)がONとなります。

5.4.5. imageサイズとframe rateの制約

5.4.5.1. ISX012で使用可能な設定

VIDIOC_S_FMTで設定できるimageサイズと、VIDIOC_S_PARMで設定できるframe interval(frame rateの逆数)には関連があります。
(imageサイズを大きくすると、大きいframe rateは設定できなくなります。)

以下、Spresense + ISX012におけるサポート範囲をpixelフォーマット毎に表したものになります。 ISX012に設定できるframe rateは離散値をとり、120 / 60 / 30 / 15 / 7.5 / 6 / 5 の7種類が設定可能です。
下図において、例えば、YUV4:2:2フォーマットの場合は

  • QVGA以下: max FPS=120なので、120FPS~5FPSの7種類を設定可能

  • QVGAより大きい: max FPS=60なので、60FPS~5FPSの6種類を設定可能

という制約になります。

Diagram
図 51. YUV4:2:2およびRGB565フォーマットのimageサイズと設定可能な最大frame rate
Diagram
図 52. JPEGフォーマットのimageサイズと設定可能な最大frame rate
Diagram
図 53. JPEG + YUV4:2:2フォーマットのJPEG imageサイズと設定可能な最大frame rate

JPEG + YUV4;2;2フォーマットにおいて、 YUV422 imageサイズは 96x64からWQVGA(400x240)までをサポートしており、 この範囲内であればframe rateの制約には影響しません。

5.4.5.2. ISX019で使用可能な設定

ISX019では、データフォーマット・フレームサイズにかかわらず、 30FPS, 15FPS, 10FPS, 7.5FPSが利用できます。 FPSの設定は、ioctl(VIDIOC_S_PARM)の parm.capture.timeperframe の各メンバを用いてフレーム間隔の形で設定します。

表 28. ISX019で使用可能なフレーム間隔の設定
FPS numerator denominator

30

1

30

15

1

15

10

1

10

7.5

2

15

フレームサイズはフォーマットによって、特定のサイズのみが設定可能です。

表 29. ISX019で使用可能なフレームサイズ
1st ioctl(VIDIOC_S_FMT) 2nd ioctl(VIDIOC_S_FMT)

pixelformat

width

height

pixelformat

width

height

V4L2_PIX_FMT_JPEG

1280

960

-

-

-

1280

720

640

480

640

360

320

240

160

120

V4L2_PIX_FMT_RGB565

V4L2_PIX_FMT_UYVY

320

240

-

-

-

160

120

V4L2_PIX_FMT_JPEG_WITH_SUBIMG

1280

960

V4L2_PIX_FMT_SUBIMG_UYVY

320

240

160

120

1280

720

V4L2_PIX_FMT_SUBIMG_UYVY

320

180

160

90

640

480

V4L2_PIX_FMT_SUBIMG_UYVY

320

240

160

120

640

360

V4L2_PIX_FMT_SUBIMG_UYVY

320

180

160

90

320

240

V4L2_PIX_FMT_SUBIMG_UYVY

320

240

160

120

160

120

V4L2_PIX_FMT_SUBIMG_UYVY

160

120

5.4.6. ioctlの実行タイミングに関する制約

5.4.6.1. VIDIOC_S_FMTの指定内容が正しく反映されないタイミング

V4L2_BUF_TYPE_VIDEO_CAPTUREとV4L2_BUF_TYPE_STILL_CAPTUREはマルチスレッドなどを用いて並行で制御可能ですが、 下図のNGと書かれているタイミングのVIDIOC_S_FMT(V4L2_BUF_TYPE_STILL_CAPTURE)は正しく反映されない可能性があります。 (いずれかのストリームを単体で使用するケースや、下図のOKと書かれているタイミングでは問題ありません。)

Diagram
図 54. VIDIOC_S_FMTの指定内容が正しく反映されないタイミング

5.4.7. サンプルコード


5.5. DNN Runtime

5.5.1. DNN Runtime 概要

DNN Runtimeライブラリ(dnnrt)は、Sonyが提供するNeural Network LibrariesまたはNeural Network Console(NNC)で学習したモデルを使用して、Deep Neural Network (DNN) を用いた認識処理を行うことができます。

DNN Runtime を使用して認識処理を行うためには、事前にNNCで学習済みモデル(nnbファイル形式)を作成する必要があります。 学習済みモデルの作成方法は、こちら 学習済みモデルの準備 を参照してください。

dnnrt overview ja
図 55. DNN Runtime 概要

Neural Network Libraries および Neural Network Console は、以下の公式サイトをご覧ください。

また、DNN Runtime ライブラリは、NNabla C Runtimeを使用しています。

5.5.2. サンプルコード

このサンプルコードは、こちら 学習済みモデルの準備 の章で使用している image_recognition.MNIST.LeNet で作成された学習モデルを実行し、手書き文字認識を行うためのサンプルコードです。

image_recognition.MNIST.LeNet で作成された学習モデルは、28x28サイズの画像を1つ入力にとり、10個の配列を出力します。この10個の配列はインデックスが認識した数字を意味しており、配列の中にそれぞれの数字である確率が出力されます。例えば、配列の先頭(インデックス0)には、入力された画像が数字の「0」である確率が出力されます。

詳細は、DNNRT example READMEを参照してください。

Diagram
図 56. DNNRT 動作シーケンス

5.6. GNSS

GNSS library はGPS/GLONASS/BeiDou/Galileo 衛星の信号を受信し現在位置を算出する機能を提供します。 この機能を使うには、GNSS用のアンテナを装着する必要があります。 Spresenseボードでは、チップアンテナが搭載されているため、追加のアンテナは不要です。

5.6.1. 主な特徴

  • GPS、GLONASS/BeiDou/Galileo に加え QZSS (みちびき)衛星システムからの信号を受信可能な Multi GNSS をサポート

  • SBAS(WAAS)及びQZSS L1Sによる測位補強が利用可能です

  • アプリケーションコアとGNSSコアは分離しているため、独立して測位と通知を行うことができます

  • Geofence をサポートします

これらの機能は POSIX 準拠のデバイスファイルでアプリケーションから操作することができます。 デバイスファイルは、"/dev/gps" で、open(), close(), read(), seek(), ioctl() で操作します。

NuttX RTOS の ioctl は3つの引数を持ちます。 GNSS デバイスファイルに関しては、2番目の引数"req" が GNSS コマンド、3番目の引数"arg" が in/out data の引き渡しになります。

5.6.2. Configuration

GNSS 機能を使うには、CONFIG_CXD56_GNSS を "y" にセットする必要があります。

[System Type]
  [CXD56xx Package Configuration]
    [GNSS device] (CXD56_GNSS) = Y

NMEA 形式を使いたい場合は、CONFIG_CXD56_GNSS, CONFIG_LIBM, CONFIG_GPSUTILS_CXD56NMEA_LIB を "y" にセットする必要があります。

[System Type]
  [CXD56xx Package Configuration]
    [GNSS device] (CXD56_GNSS) = Y
[Application Configuration]
  [Spresense SDK]
    [Sensing]
      [Support CXD56xx gnss NMEA convert library] (GPSUTILS_CXD56NMEA_LIB) = Y

また、サンプルアプリケーションを有効にするには、CONFIG_CXD56_GNSS に加え CONFIG_EXAMPLES_GNSS を "y" にセットしてください。

[System Type]
  [CXD56xx Package Configuration]
    [GNSS device] (CXD56_GNSS) = Y
[Application Configuration]
  [Spresense SDK]
    [Examples]
      [GNSS positioning example] (EXAMPLES_GNSS) = Y

NMEAのサンプルをアプリケーションを有効にするには、NMEA設定の他に、CONFIG_EXAMPLES_GNSS_ATCMD を "y" にセットする必要があります。

[System Type]
  [CXD56xx Package Configuration]
    [GNSS device] (CXD56_GNSS) = Y
[Device Drivers]
  [USB Device Driver Support]
    [USB Modem (CDC/ACM) support] = Y
[Application Configuration]
  [Spresense SDK]
    [Sensing]
      [Support CXD56xx gnss NMEA convert library] (GPSUTILS_CXD56NMEA_LIB) = Y
[Application Configuration]
  [Spresense SDK]
    [Examples]
      [GNSS CXD5603 @command emulator example] (EXAMPLES_GNSS_ATCMD) = Y

(参考情報) ファクトリテストを有効にしたい場合は、CONFIG_CXD56_GNSS に加え CONFIG_EXAMPLES_GNSS_FACTORY を "y" にセットします。 また、EXAMPLES_GNSS_FACTORY_SVID をテスト環境に合わせて設定してください。 ファクトリテストを直接動かす場合は、[Application entry point] を "gnss_factory_test" に変更します。 テスト結果 (cn と doppler) は 1000000 倍の値が出てきます。

[System Type]
  [CXD56xx Package Configuration]
    [GNSS device] (CXD56_GNSS) = Y
[Application Configuration]
  [Spresense SDK]
    [Examples]
      [GNSS FACTORY test] (EXAMPLES_GNSS_FACTORY) = Y
      [FACTORY TEST svid] (EXAMPLES_GNSS_FACTORY_SVID) = 1
[RTOS Features]
  [Tasks and Scheduling]
    [Application entry point]
      set 'gnss_factory_test'

詳細については、以下の README を参照してください。 spresense/examples/gnss_factory/README.txt

以下の設定はどんな場合でも変更可能です。

  • 'GNSS backup file name' と 'GNSS CEP file name' は GNSS によって使用されるファイルです。パス名をシステムの構成にあわせて変更してください。

[System Type]
  [CXD56xx Package Configuration]
    [GNSS setting]
      [GNSS backup file name] = '/mnt/spif/gnss_backup.bin'
      [GNSS CEP file name] = '/mnt/sd0/gnss_cep.bin'

GNSS デバイスドライバは アプリケーションに POSIX形式の poll もしくは シグナルを通じて測位結果を通知します。 poll できる数は以下のコンフィギュレーションで設定できます。デフォルトでは、poll 数は 4、signal 数は 4 です。 詳細については、 Position calculation notification を参照してください。

[System Type]
  [CXD56xx Package Configuration]
    [GNSS setting]
      [GNSS max poll waiters] = 4
      [GNSS max signal receivers] = 4

5.6.3. Device control

GNSS ライブラリは ioctl() を通じて制御します。

ioctl のコマンドは、IOCTL_ のプレフィックスが付与されて定義されています。 GNSS デバイスファイルは、複数のアプリケーションから同時に open() することができます。 ただし、GNSS デバイスは、一度に一つの IOCTL コマンドしか受け付けません。言い換えると、どのアプリケーションが優先されるということでなく、受け付けられた順番に処理されます。

5.6.3.1. Startup

どの衛星システムを起動時に使うか CXD56_GNSS_IOCTL_SELECT_SATELLITE_SYSTEM で設定できます。また測位間隔については、CXD56_GNSS_IOCTL_SET_OPE_MODE で設定します。

"Hot Start" の場合("Hot Start")、直近の位置と時間を設定する必要があります。詳細については、Using GNSS backup data の "Warm Start と Hot Start" の設定を参照してください。

5.6.3.2. Start positioning

"start mode" を CXD56_GNSS_IOCTL_START で指定することができます。

以下の初期位置算出時間 TTFF は参考値です。お使いのシステム及び環境によって変動します。
Start mode IOCTL command parameter TTFF (*1) Information to use

Cold Start

CXD56_GNSS_STMOD_COLD

> 45 sec

全ての測位データ、時間、衛星軌道情報は全て消去され、次回起動時は衛星の捕捉から開始します。

Warm Start

CXD56_GNSS_STMOD_WARM

> 20 sec

直近の測位データ、時間、アルマナック(粒度の粗い衛星軌道情報)を使って起動します。エフェメリス(詳細な衛星軌道情報)は用いません。

Hot Start

CXD56_GNSS_STMOD_HOT

>= 1 sec

直近の測位データ、時間、アルマナック、エフェメリスを使って起動します。

(*1) 初期位置算出時間 (Time To First Fix)

"Warm Start" もしくは、"Hot Start" であったとしても、前回の動作時から長い時間が経過し、衛星軌道情報が古く期限切れの条件では、GNSS デバイスは "Cold Start" と同様に衛星の捕捉から開始します。

5.6.3.3. Stop positioning

測位を停止するには、 CXD56_GNSS_IOCTL_STOP を使用します。停止するには200から300ミリ秒かかります。

5.6.3.4. Position calculation notification

通知は、poll と シグナルの2種類あります。

poll を使う場合は、CONFIG_CXD56_GNSS_NPOLLWAITERS でポーリング数を設定することができます。

シグナルを使う場合は、フィールド fd に GNSS デバイスのファイルディスクリプタを, enable には 1 を, signo に任意のシグナル番号を、さらに gnsssig に CXD56_GNSS_SIG_GNSS を設定した cxd56_gnss_signal_setting_s データを、IOCTLコマンド CXD56_GNSS_IOCTL_SIGNAL_SET の引数として ioctl関数を呼び出してシグナルと測位通知を関連付けして下さい。

アプリケーションは、sigwaitinfo で通知をシグナルとして受け取ることができます。 シグナルが不要になった場合は、フィールドenableに 0 を指定した cxd56_gnss_signal_setting_s データを、 CXD56_GNSS_IOCTL_SIGNAL_SET で設定することで関連付けをクリアすることができます。 シグナルの関連付けの最大数は、コンフィギュレーションの CONFIG_CXD56_GNSS_NSIGNALRECEIVERS で変更できます。

CONFIG_EXAMPLES_GNSS_USE_SIGNAL を設定した場合のサンプルは、gnss application example programで参照できます。

5.6.4. For faster positioning

"Hot Start" でTTFFを短くするためには、バックアップデータ中に含まれる衛星軌道上やその他の情報を活用することが早道です。 ioctl コマンドを使って、バックアップデータを活用した標準的な "Hot Start" の手順を示します。

Diagram
図 57. Standard flow for hot start using backupdata
5.6.4.1. Using GNSS backup data

バックアップデータに含まれる最終測位位置、エフェメリス、アルマナック、TCXO クロックのオフセット値が、 "Hot Start" で測位を開始する際に利用されます。 バックアップデータは ioctl コマンドによって、フラッシュメモリに蓄積することができます。その場合、電源がオフになった場合でも次の起動時にフラッシュメモリからSRAMに展開され、"Hot Start" に利用することができます。

5.6.4.1.1. Power condition and backup data

システムが起動している状態では、GNSS測位は動いており、全ての関連情報はストアされます。システムが "Hot Sleep" している状態では、SRAM のデータは保持され、 RTC は動き続けているため、"Hot Start" で測位を開始することができます。"Deep Sleep" 状態では RTC は動作を続けますが、SRAM はオフとなるため、"Hot Start" のためにはフラッシュメモリに保存したバックアップデータをリストアして利用する必要があります。

5.6.4.1.2. Saving backup data

バックアップデータをフラッシュメモリなどに保存するには、ioctl コマンド CXD56_GNSS_IOCTL_SAVE_BACKUP_DATA を使用します。バックアップデータは、CONFIG_CXD56_GNSS_BACKUP_FILENAME に指定されたファイル名で保存されます。   ただし、フラッシュメモリは頻繁に書き込むとメモリの故障の原因になりますので、頻繁な書き込みは控えるようにしてください。例えば、システムがシャットダウンするタイミングで保存するのが良いでしょう。

5.6.4.1.3. Invalid backup data

まれに、保存したバックアップデータが壊れていることがあります。その場合、データのリストアはチェックサムエラーで失敗し、測位も "Cold Start" から開始します。

5.6.4.1.4. Expired data

エフェメリスやアルマナックの期限が切れていた場合、それらのデータは無視されます。その場合は、"Cold Start" 相当の処理となりますのでTTFFも長くなります。測位を開始後、最新のエフェメリスやアルマナックを衛星から受信した際に、バックアップデータの衛星軌道情報も上書きされます。

5.6.4.2. GPS time

"Hot Start" を行うためには、GNSS デバイスに誤差 60 秒以内の現在時刻が設定されている必要があります。以前に測位を行いシステムの電源が切られていなければ RTC_GPS に最後の測位時に設定された時刻が設定されています。電源投入直後には RTC_GPS の値は不定ですのでアプリケーションから ioctl コマンドにて時刻を設定する必要があります。

5.6.4.2.1. Accuracy of RTC_GPS

測位の停止時に、GNSS デバイスはLSI内に持つRTCクロック精度のタイマー RTC_GPS を GPS 時間に更新します。 測位停止中は GNSS デバイスの時計は停止し、この RTC_GPS が計時します。 RTC_GPS が保持する時刻と実時間の誤差は、外付けRTC Xtalのクロック精度に依存します。 測位を再開する際、GNSS デバイスはこの RTC_GPS の時刻を基に測位演算を行うため、停止期間が長いほど RTC_GPS の時刻は実時間に対して誤差を持ち、TTFFと初回測位位置の精度に影響を与えます。 測位停止から15分以上経つとRTC_GPS の時刻誤差は、その後の "Hot Start" の測位結果に対して無視し得なくなります。 長い測位停止期間の後にも、短いTTFFや高い初回位置精度を求める場合は、ioctlコマンドで時刻を設定することを考慮しても良いでしょう。

システムが電源オンされた直後は、RTC_GPS は "0h 6 - Jan - 1980" を示します。測位が完了すると GPS 時間が取得できるため、RTC_GPSがGPS時間にセットされます。時刻が指定されていない限り、測位計算は RTC_GPS をベースに行われます。

5.6.4.2.2. Set time by the command

アプリケーションがネットワーク等から取得した時刻を指定する場合は、ioctl コマンド CXD56_GNSS_IOCTL_SET_TIME を用います。

5.6.4.3. Current location

"Hot Start" のためには、直近の位置データが必要です。アプリケーションが位置データを保持していない場合は、GNSS デバイスは前回測定した位置情報をベースに "Hot Start" を行います。

5.6.4.3.1. Set location by the command

アプリケーションがネットワーク等から取得した位置情報を指定する場合は、ioctl コマンド CXD56_GNSS_IOCTL_SET_RECEIVER_POSITION_ELLIPSOIDAL もしくは、CXD56_GNSS_IOCTL_SET_RECEIVER_POSITION_ORTHOGONAL を用います。

5.6.5. Accurate Positioning

正確な測位を行うために、適切な受信条件で測位を行う必要があります。ビル街における衛星の見えにくさや大きな建物の反射波の影響、WIFIからのノイズなど、測位環境が精度の高い測位に影響を与えていないかが、測位データからある程度類推することができます。

5.6.5.1. Indication in receiver positioning data
5.6.5.1.1. Field numsv, numsv_tracking, numsv_calcpos, numsv_calcvel
Type

uint8_t

Unit

none

フィールド numsv, numsv_tracking, numsv_calcpos, numsv_calcvel は、それぞれ可視衛星数、追尾衛星数、位置演算に利用している衛星数、速度演算に利用している衛星数です。 可視衛星には、衛星軌道情報から現在の天空に存在が予想されるが、実際には障害物があり信号を受信していない衛星も含みます。 追尾している衛星の中でも受信が弱く正確性に欠く信号は測位や測速の演算に利用しません。 位置精度は後述の信号の強度や衛星の配置にも依存するため一概には言えませんが、一般的に numsv_calcpos の個数を 6 個以上に保つと数メートルの誤差で測位を続けられることが多いようです。

5.6.5.1.2. Field posDop, velIdx of struct cxd56_gnss_receiver_s
Type

struct cxd56_gnss_dop_s

Sub fields

pDop, hDop, vDop, ewDop, nsDop as float

Unit

none

posDop は 衛星の幾何学的な配置から求められる位置精度低下率である DOP(Dilution Of Precision) を含みます。 'p' は全体的な精度低下率、 'h' は水平方向の精度低下率、 'v' は縦方向の精度低下率、 'ew' は東西の精度低下率、 'ns' は南北の精度低下率を表しています。

DOP が小さいほど、測位するのに適した場所であることを示しています。例えば、街中のような狭い空では受信できる衛星は少なく、DOP は悪化します。pDOP が 5 を超えるような場合、測位には不適な条件であることを意味しています。一方、pDOP が 2以下だった場合は、測位するのに十分な条件を満たしています。

5.6.5.1.3. Field posAcc of struct cxd56_gnss_receiver_s
Type

struct cxd56_gnss_var_s

Sub fields

hVar, vVar as float

Unit

meter

これらの値は、測位データの正確さを表し、位置と速度の時系列値に対する共分散の平方根です。これらは、受信ノイズやその他の要因による測位データへの影響を見ることができます。'h' は水平方向の正確さ、 'v' は縦方向の正確さを表しています。

PosAcc は、測位誤差の標準偏差を表しています。衛星信号に対するノイズやマルチパスの影響、DOP の悪化などが測位結果に誤差を与えます。この値が大きいほど、測位データが不正確であることを示します。

5.6.5.2. Indication in satellite positioning data
5.6.5.2.1. Field sigLevel of struct cxd56_gnss_sv_s
Type

float

Sub fields

none

Unit

dBHz

この値は、ノイズに対する衛星からの信号の強さの比率である C/N0 比(または CN0, CN と表されることもあり)を表しています。 GNSS衛星からの信号はスペクトラム拡散のため、これをS/N比ではなく C/N0 比と呼び、また単位も dBHz となります。 この値が大きいほど、GNSSからの衛星信号の信頼性は高い事を示し、結果としてそれを用いた測位も安定します。 一方、ノイズ源が GNSS アンテナの近くにある、衛星の方向がアンテナの指向性が悪い方向と一致している、あるいは衛星とアンテナの間に障害物がある、さらに衛星信号の追尾が不良であると、この値は小さくなり、測位が不安定になります。 なお衛星信号個々にこれら C/N0比 悪化の要因は異なるため、各衛星によってC/N0比も異なります。 一般的に、5つ以上の衛星から信号の C/N0 が 30 dBHz以上で受信できていると測位結果は安定します。

5.6.5.3. Multi-GNSS

前出の様に捕捉追尾する衛星数が多いほど測位精度が向上する傾向があります。 GNSS デバイスは複数の衛星システムを同時に利用し、測位演算に供する衛星信号の数を増やすことが出来ます。

  • GLONASS

    GPSと同様に全世界をカバーする24機体制のロシアの測位衛星システムです。 GPSだけでも十分衛星数が確保出来ている場合に、GPSシステムの標準精度 20m に比べると劣る精度 70m のGLONASSシステムの信号を混在して測位演算すると、GPS 単独の場合よりも位置精度が落ちる可能性があります。 なおアンテナにはGLONASSの周波数に対応していない物もあるため注意が必要です。

  • Galileo

    GPSと同様に全世界をカバーする欧州の測位衛星システムです。

  • BeiDou

    GPSと同様に全世界をカバーする中国の測位衛星システムです。

  • QZSS-L1C/A

    日本のみちびきから送信される衛星信号です。 この信号はGPS L1C/Aと互換のため、これを利用するとあたかもGPS衛星が増えたかのように見えます。これをみちびきによるGPSの補完機能と呼んでいます。 みちびきは4機体制(2018年時点)で、その軌道は日本を中心に東アジアとオセアニア上空をカバーするため、それ以外の地域では補完効果がありません。

5.6.5.4. Augmentation

WAAS もしくは みちびきの QZSS-L1S から送信される補強信号を利用することで測位精度を上げることが出来ます。 補強信号はSBASフォーマットをベースとした、数分ごとに更新される測位演算の精度を向上するための計算パラメータです。 補強信号を使う場合、補強情報が無いGLONASSを混在させての測位は出来ません。

  • WAAS

    WAASはアメリカ合衆国本土、カナダ、ハワイ及び属州で有効な補強信号です。 GPS衛星の信号から求められる擬似距離(衛星から受信機間の距離)の精度を向上します。

  • QZSS-L1S

    QZSS-L1Sは日本の範囲のみで有効です。 GPS衛星信号及びQZSS-L1C/Aから求められる擬似距離(衛星から受信機間の距離)の精度を向上します。 仰角の低い衛星(2018年9月時点で仰角マスクは20度)は補強情報が送信されず、測位に使うことができません。

5.6.5.5. Select positioning and augmentation satellite systems

本 GNSS デバイスでは、以下の測位衛星システム及び補強信号の組み合わせで測位することを想定しています。 どの衛星システムを使うかは CXD56_GNSS_IOCTL_SELECT_SATELLITE_SYSTEM で設定できます。

GLONASS, Galileo, BeiDou に関して同時に使用することはできません。いずれか一つを選択してください。 GPS, QZSS-L1C/A や WAAS, QZSS-L1S といった補強信号に関しては組み合わせの制約はありません。
以下の測位誤差(Accuracy)は一般的な好条件下での参考値です。お使いのシステム及び環境によって変動します。
GPS GLONASS Galileo BeiDou QZSS-L1C/A WAAS QZSS-L1S 95% Accuracy Effective place

x

<5m

under the open sky

x

x

<5m

in East Asia and Oceania

x

x

<7.8m

in the city

x

x

<7.8m

in the city

x

x

<7.8m

in the city

x

x

x

<7.8m

in the city of East Asia and Oceania

x

x

x

<7.8m

in the city of East Asia and Oceania

x

x

x

<7.8m

in the city of East Asia and Oceania

x

(x)

(x)

(x)

x

x

<2m

in Japan

5.6.6. Short message delivery

GNSS デバイスはQZSSみちびきから送信される災害情報、危機管理情報といった災危(災害・危機)通報を受信できます。

アプリケーションはシグナル通知を GNSS デバイスに設定することで、GNSS デバイスからの災危通報を非同期にシグナルで受けることができるようになります。 災危通報のシグナル通知の設定は、フィールド fd に GNSS デバイスのファイルディスクリプタを, enable には 1 を, gnsssig に任意のシグナル番号を、さらに gnsssig に CXD56_GNSS_SIG_SBAS を設定した cxd56_gnss_signal_setting_s データを、IOCTLコマンド CXD56_GNSS_IOCTL_SIGNAL_SET の引数として ioctl関数を呼び出してシグナルと災危通報を関連付けして下さい。

GNSS デバイスは SBAS メッセージタイプ の 43 (気象庁防災情報)または 44 (任意情報)を受信すると、関連付けしたシグナルを発行します。 sigwaitinfoでのシグナル処理にて データバッファに cxd56_gnss_sbasdata_sCXD56_GNSS_READ_OFFSET_SBAS をオフセットとしてGNSSデバイスを read することで通知の要因となった SBAS メッセージを読み出すことが出来ます。

5.6.7. Utilities

5.6.7.1. NMEA converter

NMEA は GPSアプリケーションで広く使われている位置情報のテキストフォーマットで、gnss ライブラリは NMEA フォーマットの出力もサポートしています。

cxd56_gnss_sv_s に格納された GNSS デバイスの内容を NMEA に変換します。

詳細については、gnss_nmea ならびに、NMEA Output を参照してください。

5.6.7.2. 1PPS signal output

UTC(協定世界時)に同期した高精度のタイムパルス(1PPS)信号を出力します。

5.6.7.2.1. Configuration

以下のコンフィギュレーションで1PPS信号を出力するピン番号を選択します。 デフォルトは拡張ボードに出ている PIN_HIF_IRQ_OUT が選択されています。

[System Type]
  [CXD56xx Package Configuration]
    [GNSS setting]
      [GNSS 1PPS output] = Use 'PIN_GNSS_1PPS_OUT' or 'PIN_HIF_IRQ_OUT'
5.6.7.2.2. CXD56_GNSS_IOCTL_SET_1PPS_OUTPUT

1PPS出力を開始/停止するコマンドです。

引数に 1 を設定すると時刻同期されたタイミングで信号出力を開始します。引数に 0 を設定すると停止します。

5.6.8. Geofence

5.6.8.1. Key features

Geofence はあらかじめ指定した領域に近づいたときに通知するためのライブラリです。

  • 領域は Latitude, Longitude, Radius で指定できます

  • 最大 20 領域まで指定できます

geofence notification
図 58. Geofence transition notification

通知は "ENTER", "DWELL", "EXIT" の3種類あります。"DWELL" の場合は、その領域に滞在した時間も通知条件に設定することができます。

5.6.8.2. Configuration

Geofence を使う場合、GNSS device と Geofence Support を 'y' に指定してください。

[System Type]
  [CXD56xx Package Configuration]
    [GNSS device] (CXD56_GNSS) = Y
    [Geofence Support] = Y
5.6.8.3. Add Region and setup options

Geofence を使うには "/dev/geofence" デバイスファイルを使います。

5.6.8.3.1. CXD56_GEOFENCE_IOCTL_ADD

領域を追加するためのコマンドです。

領域は最大20箇所、設定することができます。それぞれの領域は、Latitude, Longitude, Radius で設定できます。

North latitude と East longitude の方向は '+' を与えます。South latitude と West longitude の方向は '-' になります。

5.6.8.3.2. CXD56_GEOFENCE_IOCTL_SET_MODE

Geofence が定義された領域の同心円状の領域(Dead Zone)と、その領域に侵入を許す期間 "dwelling period" を指定します。

5.6.8.4. State transition
Geofence state transition
図 59. Geofence state transition
5.6.8.5. Dead zone

"Dead Zone" とは定義された領域の半径 (Radius) で定義された同心円状の領域を示します。

  • "ENTER" が定義された場合、その同心円領域に入ると通知します

  • "EXIT" が定義された場合、その同心円領域から出ると通知します

Geofence Dead Zone
図 60. Geofence Dead zone
5.6.8.6. Read Geofence transition data

状態変化は、poll によって通知されます。 cxd56_geofence_status_s に状態遷移の情報が格納されています。

詳細については、アプリケーションサンプル Geofencing Transitions を参照してください。

5.6.9. PVTLog

5.6.9.1. Key features

PVTLog は、Position, Velocity, Time の情報のログです。

最大 170 のログを蓄積することができます。ログがあふれた場合は、アプリケーションはシグナルにより通知を受けることができます。 例えば、15分ごとにログを取得した場合、42時間は継続して記録することができます。

ログデータの詳細については、cxd56_pvtlog_s を参照してください。

5.6.9.2. Configuration

PVTLog を使う場合は、GNSS device Support を 'y' に設定してください。

[System Type]
  [CXD56xx Package Configuration]
    [GNSS device] (CXD56_GNSS) = Y
5.6.9.3. Start and stop log store

ログを開始するには、ioctl コマンド CXD56_GNSS_IOCTL_PVTLOG_START で行うことができます

記録する間隔についても、このコマンドを使ってください。ログを記録する間隔は測位する間隔よりも大きくする必要があります。

測位を開始するとログは自動的に開始します。ログを停止するには、ioctl コマンド CXD56_GNSS_IOCTL_PVTLOG_STOP を使ってください。

5.6.9.4. Notification

記録しているログが 170 を超えると、シグナルによりアプリケーションにログが溢れたことが通知されます。 シグナルの設定は、CXD56_GNSS_SIG_PVTLOG で行うことができます。

この通知を受け取ったら、次の記録が行われるまでにログを読み出す必要があります。でなければ、最初のログデータが次の測位データに上書きされることになります。

ログデータは、CXD56_GNSS_READ_OFFSET_PVTLOG でオフセットが指定された位置から読み込むことができます。

ログデータは、バックアップ RAM に記録されます。すでにデータが存在する場合は、消去されることなく上書きされます。 バックアップをクリーンナップする場合は、CXD56_GNSS_IOCTL_PVTLOG_DELETE_LOG を使います。

詳細に関しては、サンプルプログラム PVTLog を参照してください。

5.6.10. GNSS 性能

5.6.10.1. 軌跡例

Spresenseのメイン基板に搭載の内蔵チップアンテナを使ったケースと、改修して取り付ける外付けGNSSアンテナを使ったケースでのトラック走行の軌跡を掲載します。外付けアンテナを使用した場合は、受信感度が少し上がるので更に正確な軌跡となって表れています。

chip_antenna
図 61. Spresense搭載チップアンテナでの軌跡
external_antenna
図 62. 外付けアンテナ利用時の軌跡

条件
  • 衛星モード:GPS + GLONASS

  • 測定環境:オープンスカイの下、良好な信号環境

  • 事前条件:一度測位させてから、衛星を捕捉した状態でトラックを走行

  • アンテナ向き:トラック走行中は、上腕に取り付けて腕振りあり

  • 速度:軽いジョギング(約6km/h)

実際の軌跡

 400mトラックを3周(走行位置はトラックの内側のコース)


これらの画像は、Creative Commons Attribution-ShareAlike 2.0 のライセンスの下で、
”© OpenStreetMap contributors”によって提供される地図画像を利用して作成されています。
ここでの軌跡は、NMEAデータをGPXデータに変換してOpenStreetMapで描画したものになります。

5.6.11. Application Examples

5.6.11.1. Notify Positioning

GNSS 測位の通知は、poll とシグナルによって行われます。どちらを使うかは、CONFIG_EXAMPLES_GNSS_USE_SIGNAL もしくは CONFIG_EXAMPLES_GNSS_USE_POLL を Kconfig で選択できます。

5.6.11.2. NMEA Output

GNSS ATCMD アプリケーション を参照してください。

5.6.11.3. Geofencing Transitions

5.7. ASMP Framework

5.7.1. ASMP Framework の概要

ASMP Frameworkはマルチコアプロセッサを簡単に扱えるように用意されたフレームワークです。

このフレームワークには二つのタスクが定義されています。

  • Supervisor タスク (Main CPU task)

  • Worker タスク (Sub CPU task)

Diagram
図 63. ASMPフレームワーク関連図

Supervisorタスクは、ASMP Framework API を使用してWorkerタスクの起動、停止などの制御を行います。 詳細は、 MP Task を参照してください。

Workerタスクは、 Main CPUとは完全に独立したタスクで、Sub CPU上で並列処理されるタスクです。したがって、タスク間でデータや状態をやりとりするための通信手段が必要になります。

ASMP Frameworkでは、SupervisorおよびWorkerそれぞれのタスクが通信するための以下の機能を提供しています。

MP message queue は POSIX の message queue に似たメッセージ交換用のインターフェースです。

Diagram
図 64. MP Message Queue

MP mutex は、pthread mutex に似た排他制御用のメカニズムを提供します。

Diagram
図 65. MP Mutex

MP shared memory は、それぞれのタスクで共有されるメモリ領域を提供します。

Diagram
図 66. MP Shared Memory

5.7.2. Configuration

[ASMP] = Y
  [ASMP shared memory size]  = 0x100000

ASMP framework は、Sub CPU上で動作するプログラム自身やタスク間の共有メモリのために、カーネル管理外のメモリ領域を必要とします。このメモリ領域のサイズは、 ASMP shared memory size オプションで変更することができます。

例えば、ASMP shared memory size の値を 0x80000 (512KByte) に設定した場合、トータル1.5MbyteのSRAMが、

  • Main CPU側のメモリサイズ(カーネル管理領域): 1MByte

  • Sub CPU側のメモリサイズ(カーネル管理外領域): 512KByte

という割り当てになります。

もし、 ASMP frameworkを必要としないのであれば、カーネルは最大 1.5MByte のメモリを活用することができます。

ASMP Shared memory size 設定は、128KBbyte単位(0x20000)で設定してください。

5.7.3. Workerの起動シーケンス

Diagram
図 67. Worker 起動フロー
  1. mptask_init を呼び出してWorkerを生成します

  2. 必要に応じてメッセージキューや共有メモリなどを準備し、Workerに紐付けます

  3. mptask_exec を呼び出してWorkerを実行します

  4. 終了時には mptask_destroy を呼び出してWorkerを停止させます

  5. メッセージキューや共有メモリなどを作成していた場合は破棄させます

詳細は、Supervisor Task example および Worker Task example を参照してください。

5.7.4. Workerのビルド

Workerタスクは、ELFフォーマットのファイルをロードして実行します。ただし、WorkerはサブCPUで動作するため、カーネルやSDKのAPIを直接呼び出すことはできません。

ASMP frameworkがサポートする ELFファイルのレイアウトは以下になります。

Diagram
図 68. Worker用の ELFファイルのレイアウト

それぞれのプログラムの開始アドレスは 0x00000000 でなくてはならず、それぞれのセクションは連続である必要があります。 SDKでは、Worker用ELFファイルを生成するために必要なコンパイラオプション、リンカオプションおよびリンカスクリプトを提供しています。 これらはそれぞれ CELFFLAGSLDRAWELFFLAGS として sdk/Make.defs 内で定義されています。具体的なビルドルールは ASMP Worker Task 'Hello World' example を参照してください。

さらに、WorkerでASMP Frameworkを使用するためには、Worker用ライブラリが必要です。このライブラリには、Workerを構成するための必要なコード(上図の青色部)が含まれています。ただし、このライブラリはSDKのビルドシーケンス中に用意されないため、ユーザーがWorkerをビルドする際に事前に生成しておく必要があります。

Worker用ライブラリを生成するためのサンプルは、Worker Task Makefile および Worker Task Library Makefile を参照してください。

5.7.5. サンプルコード


5.8. Sensor Control Unit

5.8.1. Overview

Sensor Control Unit (SCU) は、SCU デバイス内の SPI もしくは I2C バスに接続されたセンサーデバイスからのセンシングデータを取得することができます。CPUとは独立して動作するため、センサー取得に関わるCPUの負荷を軽減することができます。

主な特徴
  • シーケンサーによるセンサーデータの自動取得

  • センサーデータ間引き機能(デシメーター)

  • IIR フィルター機能

  • イベント通知機能

これらの機能は、アプリケーションから設定することができます。

SCU は SPI と 2つの I2C バスと 8つのシーケンサーと2つのデシメーターを搭載しています。

Diagram
図 69. SCU block diagram

5.8.2. Configuration

  CXD56xx Configuration  --->
    Sensor Control Unit (SCU)  --->
      Sequencer Sampling Predivider  = 64 (default) (1)
      SCU clock mode                 = RCOSC (default) (2)
      SCU32K clock source            = RTC (default) (3)
      SCU Decimator assignments (4)
        ...
        (Decimator supported drivers)
        ...
      SCU Debug                      = N (default)
      DMAC support                   = Y (default)
1 Sequencer Sampling Predivider は、シーケンサーのサンプリングレートに影響します
2 SCU clock mode はSCUの動作クロックを指定します
3 SCU32K clock source は サンプリング周波数(32768Hz)のクロックソースを選択できます
4 SCU デシメーターは 3つ以上のセンサーに割り当てられますが、デシメーターに割り当てたセンサーの同時使用は2つまでです。

5.8.3. シーケンサー

SCU は2つの種類のシーケンサーがあります。通常のシーケンサーは、センサーデータを定期的に取得し、FIFO に蓄積していきます。デバイスドライバは、このFIFOからデータを取得していきます。

Diagram
図 70. Sequencer block diagram

それぞれのシーケンサーの FIFO は、SCUIOC_SETFIFO で指定されるサイズに分割されます。FIFOメモリーは全部で 40KB です。アプリケーションは、デバイスドライバを使う前にセットする必要があります。

ret = ioctl(fd, SCUIOC_SETFIFO, sizeof(struct three_axis_s) * 128);

シーケンサーは、サンプリングレートで指定される間隔でセンサーデータを取得していきます。センサーデバイスの仕様で決められたサンプリングレートではないことに注意してください。アプリケーションは、シーケンサーに対し、SCUIOC_SETSAMPLE を使用して、サンプリングレートを使用する前に設定する必要があります。

ret = ioctl(fd, SCUIOC_SETSAMPLE, 2);

SCUIOC_SETSAMPLE は、2 のべき乗でベースクロック(32KHz)を割った数を指定します。

Sequencer sampling rate = 32768 / CONFIG_CXD56_SCU_PREDIV / (2 ^ n)

CONFIG_CXD56_SCU_PREDIV がデフォルト値64の場合に、 SCUIOC_SETSAMPLE で2を指定した場合のサンプリングレートは 128 Hz になります。

アプリケーションは、シーケンサーのサンプリングレートが、センサーの仕様で定められたサンプリングレートと異なることに注意する必要があります。アプリケーションは、センサーデバイスのサンプリングレートとシーケンサーの両方に設定し、その組み合わせがうまく行くことを確認する必要があります。

アプリケーションは SCUIOC_SETWATERMARK で定められたシグナルを受信することができます。シーケンサーのFIFOに watermark に定められた数までセンサーデータが格納されると、SCUドライバはアプリケーションに対してシグナルを発行します。

例えば、アプリケーションがサンプリングレートを 128 Hz に設定し、watermark を 128 に設定したとすると デバイスドライバは1秒ごとにシグナルを発行することになります。

wm.signo = CONFIG_EXAMPLES_MAG_SIGNO;
wm.ts = &ts;
wm.watermark = 128;

ret = ioctl(fd, SCUIOC_SETWATERMARK, (unsigned long)(uintptr_t)&wm);

アプリケーションが、指定した watermark シグナルを受信すると、FIFOの最初のサンプリングデータの取得タイムスタンプがシグナルの siginfo 構造体に格納されます。

5.8.4. デシメーター

デシメーターは、FIFOに取得したデータを間引きする機能でシーケンサーの機能を拡張するために設けられたものです。デシメーターは 3 つの FIFO を持っています。

Diagram
図 71. Decimator block diagram
5.8.4.1. デシメーション処理

デシメーターは CICフィルターを適用してシーケンサーが取得したデータを間引きします。アプリケーションは、デシメーターのパラメーターを SCUIOC_SETDECIMATION コマンドを使って、 decimation_s 構造体で指定して変更することができます。

dec.ratio = 1;
dec.leveladj = SCU_LEVELADJ_X1;
dec.forcethrough = 0;

ret = ioctl(d->fd, SCUIOC_SETDECIMATION, (unsigned long)(uintptr_t)&dec);

ratio は、サンプリングレートで指定されたデータを取り出す間隔を2のべき乗数で指定します。例えば、サンプリングレートが 64Hz で、ratio が 1 だった場合、 ( 64 / (2 ^ 1) ), となり実際のサンプリングレートは 32Hz になります。 CIC フィルターはサンプリングされたデータに対して適用されることに注意してください。もし、CIC フィルターを使いたくない場合は、 forcethrough を 1に設定してください。

5.8.4.2. 取得データの増幅

デシメーターは、 decimation_s 構造体の leveladj を使うことで取得データを増幅させることができます。増幅されたデータはそのもとのデータ幅を超過してしまいますので、使用の際は注意が必要です。

leveladj は以下の設定ができます。

5.8.4.3. デシメーターサポート済みセンサー

デシメーターを使う場合は、センサードライバが対応している必要があります。現在、サポートされているセンサードライバ は以下になります。

  • KX022

  • BMI1422GMV

5.8.5. センサーデータへの信号処理

SCU は、取得したデータに対して信号処理を加えることができるようになっています。 SCUが行える信号処理は、IIRフィルターとイベント検出の2つがあります。 IIRフィルターはデータパス上の3箇所に設定をすることができます。使用するFIFO毎に設定する必要があります。

5.8.5.1. IIR フィルター
Diagram
図 72. IIR filter path
A

FIFO と イベント検出(Event detector)の両方に適用します

F

FIFOにのみ適用します

E

イベント検出(Event detector)にのみ提供します

アプリケーションは二つのIIRフィルターを設定することができます。FIFOは、シーケンサーFIFOかデシメーターFIFO です。イベント検出は特殊な機能であり、後述します。

IIRフィルターの組み合わせ
  • (A)に2つとも適用

  • (A) と (F)に適用

  • (A) と (E)に適用

  • (F) に2つとも適用

  • (F) と (E)に適用

  • (E) に2つとも適用

IIR フィルターの設定箇所は、 filter_pos_e に定義されています IIR フィルターは、係数によって調整することができます。

IIR filter block diagram
図 73. IIR filter block diagram

それぞれの係数は 34 bit の固定小数点で、 s2.31 format です。したがって、IIR フィルターの係数は、32 bit (h) と 8bit (l) で構成されます。

struct_iir_coeff_s
図 74. struct iir_coeff_s h, l

31 bit の h は S(signed bit) です。, 0 = plus, 1 = minus.

30 から 29 bit の h は整数部です。

28 から 0 の h と、 7 から 6 bit の l は、小数部になります。

5.8.5.2. イベント検出 (Event detector)

イベント検出 (Event detector) は、センサーデータの状態を監視し、その変化を検出します。アプリケーションはどのタイミングでセンサーを取得すべきか判断できるようになります。

イベント検出は、閾値で定められたセンサーデータの幅を超過している数をカウントします。イベント検出に使用できるセンサーデータは 16bitになります。取得したデータが、例えば、XYZ軸それぞれのデータだった場合、normalize 計算を行った後、データが設定値から超過しているか判定します。カウントした数が設定値に達したら、イベント検出器はタイムスタンプ付きの割り込みを発生させます。

normalize 計算は、監視するデータの数(1-3)よって異なります。

  • 1 つだった場合 (例えば、X軸のみ):

  norm = abs(x)
  • 2 つだった場合 (例えば、X軸とY軸 ):

 norm = max(abs(x), abs(y)) * 123 / 128 + min(abs(x), abs(y)) * 51 / 128
  • 3 つだった場合 (例えば、X軸, Y軸, Z軸):

  L1   = max(abs(x), abs(y)) * 120 / 128 + min(abs(x), abs(y)) * 49 / 128
  norm = max(L1, abs(z)) + min(L1, abs(z)) * 44 / 128

イベント検出の設定には scuev_notify_s 構造体を使用します。 risefall の二つの設定値があり、それぞれ threshold, count0 , count1 を持っています。 イベント検出器は カウントしたデータが、 count0 + count1. に達したらアプリケーションに通知を行います。

イベント検出器は IIR フィルターの出力を使うため、IIR フィルターは最初に設定されている必要があります。

scu event
図 75. Event detection
Event detector processes
  • 閾値を超えた値をカウントします

  • カウント数が count0 に達したら、 count1 をスタートします。

  • もし、データ数が count0 に達する前に閾値より小さくなったらカウントをストップしカウント数をリセットします。

  • トータルカウント count0 + count1 に達したらイベントを通知します

  • count1 がゼロだった場合、 count0 の値が閾値に達したら、ただちにイベントを通知します。

  • count0 がゼロだった場合、設定はすべて無視されます

5.8.6. 制限

デシメーター、IIR フィルター、イベント検出器が扱えるデータには、以下の制限があります。

  • 1つのサンプリングデータが16 bit

  • 最大3つのデータ要素

5.8.7. ドライバ開発者のためのガイドライン

SCU機能をサポートしたドライバを開発するには以下の内容を理解する必要があります

  • シーケンサーインストラクションの理解

  • センサーデバイスとの通信方法

  • シーケンサーの初期化(Open) とセンサードライバとの接続方法

  • シーケンサーからサンプルデータを読み出す方法

  • シーケンサーに対して ioctl を介してコマンドを指示する方法

5.8.7.1. シーケンサーインストラクションの理解

シーケンサーインストラクションは1命令あたり16bitで、センサーデバイスと通信するために、SPI もしくは I2C バスを使います。

ドライバを開発する際は、 SCU_INST_SEND もしくは SCU_INST_RECV マクロを使うことができます。

シーケンサーを通してデータの送受信をする際は、送受信の方法を設定した一連の命令をuinit16_tの配列に格納して設定します。また、送受信の最後には、送信が終了したことを示す SCU_INST_LAST を指定する必要があります。

instruction array の簡単な例
inst[0] = SCU_INST_SEND(0x00);                  // Send register address 0x00
inst[1] = SCU_INST_RECV(2) | SCU_INST_LAST;     // Read 0x00 and 0x01 address data, and indicate the last of instructions
5.8.7.2. センサーデバイスとの通信方法

最初にドライバはターゲットのセンサーデバイスを初期化しなければなりません。SCU機能をサポートするドライバは、scu_spitransfer もしくは scu_i2ctransfer を使ってセンサーデバイスのレジスタにアクセスする必要があります。

Ex. Register write access function
static void sensor_putreg8(FAR struct sensor_dev_s *priv, uint8_t regaddr, uint8_t regval)
{
  uint16_t inst[2];

  /* Send register address and set the value */

  inst[0] = SCU_INST_SEND(regaddr);
  inst[1] = SCU_INST_SEND(regval) | SCU_INST_LAST;

  scu_i2ctransfer(priv->port, priv->addr, inst, 2, NULL, 0);
}
SCU に直接つながっている SPI と I2C バスは、SCU とセンサードライバが同時にアクセスが発生すると衝突が発生し、誤作動の原因になります。デバイドライバ開発者は、提供される API を通じてのみ、デバイスにアクセスするようにしてください。
5.8.7.3. シーケンサーの初期化(Open) とセンサードライバとの接続方法

SCU機能をサポートしたドライバはシーケンサーオブジェクトをすべての操作で扱うことになります。それぞれのドライバは、このオブジェクトを保持しておく必要があります。

g_seq = seq_open(MAG_SEQ_TYPE, SCU_BUS_I2C0);
if (!g_seq)
  {
    return -ENOENT;
  }
priv->seq = g_seq;

このサンプルの場合、シーケンサーをOpenし、デバイスデータの中に格納しています。

デシメーターについては、3つのFIFOから読み出すことが可能なので、3つのデバイスファイルを生成しています。

seq_open() は必ず一度だけ呼び出す必要があります。ドライバ開発者は重複して初期化しないように注意する必要があります。

if (g_refcnt == 0)
  {
    int ret;
    ret = sensor_seqinit(priv);
    if (ret < 0)
      {
        return ret;
      }
  }
else
  {
    /* Set existing sequencer */
    priv->seq = g_seq;
  }
g_refcnt++;

SCU はシーケンサーが処理をしていないときにスリープすることができます。 seq_open()seq_close() APIs は SCU のスリープ機能をサポートしています。 ドライバ開発者は、open() もしくは close() を実装するときに、これらの API を呼び出すと同時にセンサーデバイスのパワーモードもコントロールするようにしてください。 それによりシステムは、より省電力を実現することができるようになります。

5.8.7.4. シーケンサーからサンプルデータを読み出す方法

シーケンサーがセンサーデータを読み出すときは、データを読み出すための一連のシーケンサ命令群を seq_setinstruction で設定します。

以下の例では、 SENSOR_DATA_REGISTER から SENSOR_BYTESPERSAMPLE 数分だけ読みだしています。

static const uint16_t g_sensorinst[] =
{
  SCU_INST_SEND(SENSOR_DATA_REGISTER),
  SCU_INST_RECV(SENSOR_BYTESPERSAMPLE) | SCU_INST_LAST,
};
seq_setinstruction(priv->seq, g_sensorinst, itemsof(g_sensorinst));

シーケンサーは、センサーデータをこの一連のシーケンサ命令群によって定期的に読み出し、FIFO にデータを蓄積します。

蓄積されたセンサーデータをFIFOから読み出す場合は seq_read() 関数を使用してください。

len = seq_read(priv->seq, priv->id, buffer, len);
5.8.7.5. シーケンサーに対して ioctl を介してコマンドを指示する方法

SCUはデバイスファイルを持たないため、SCUに対して ioctl() を行うために、センサードライバが代わりに仲介する必要があります。 これを行うためには、seq_ioctl() を各ドライバの ioctl() 内で呼ぶようにします。SCUのIOコマンドかどうかを判定するためには、 _SCUIOCVALID() マクロを使用してください。

e.g.
if (_SCUIOCVALID(cmd))
{
  /* Redirect SCU commands */
  ret = seq_ioctl(priv->seq, priv->id, cmd, arg);
}

5.9. Memory Utility Libraries

5.9.1. 概要

メディア処理&センサー処理機能では、データ用に多くのメモリを安全に、フラグメンテーションなどのリークを発生させずに管理する必要があります。このため、Spresenseでは、メモリユーティリティライブラリを提供しています。

ライブラリは、以下の3つのライブラリ、”Memory Manager” 、"Message Library"、"Simple FIFO"で構成されています。

  • ”Memory Manager” は、Multi task 間で、メモリ領域を安全に管理するため、 暗黙的にセグメントエリアを管理する固定長メモリプールライブラリです。

  • "Message Library" は、”Memory Manager” を使うために、クラスオブジェクトをタスク間で送受信するためのライブラリです。

  • "Simple FIFO" は、アプリケーションとフレームワークの間でデータをやりとりするために使用される基本的なFIFOです。

これらのライブラリの利用をメディア処理&センサー処理では、前提としています。 詳細は、以下の各章に記載します。

5.9.2. Memory Manager

”Memory Manager” の説明をします。

5.9.2.1. 概要

”Memory Manager" は、暗黙的な取得と解放を管理する固定長メモリプールです。 用途に応じたメモリ領域をメモリプールとして定義し、その中に必要なセグメントを確保することで、必要に応じたメモリの取得、解放が可能です。

プールの種別、セグメントの数などを決めて、メモリ領域を割り当てることで、メモリ領域のフラグメントなどを避けることができます。 この割り当て情報を "memory_layout" と呼び、このレイアウトをアプリケーションのニーズに合わせて切り替えることで、機能ごとに必要なメモリを確保します。

このメモリLayoutは、Applicationのニーズに従って自由に決めて、作成することが可能です。作成方法は、Configurations and Generateに記載します。

必要な "memory segment"の取得は、"MemHandle" を作成し、セグメントの確保のAPIを呼ぶことで可能です。これによって確保されたセグメントは、"MemHandle" のインスタンスが破棄されるまで、保証されます。
複数のユーザーが非同期に "MemHandle"を確保、解放を行っても、その領域は保証され、すべてのユーザから参照されなくなった時点で解放されます。

5.9.2.2. セグメント獲得、解放の仕組み

各ユーザオブジェクトは、必要なメモリエリアのセグメントを指し示すMemHandleのインスタンスを生成し、セグメントエリアを取得するAPIを呼ぶことで、それに紐付くメモリセグメントを確保します。

その際、セグメントエリアの参照カウンタを+1します。 これによって、セグメントエリアは使用状態になり、他の要求からは使えないように管理されます。

Get memHandle

この参照カウンタは、"operator=" や、"Copy Constructor" 内でも+1を行います。

このことで、データパイプラインの次に位置するオブジェクトに、この "MemHandle" のインスタンスをコピーし、渡していくことで、 "MemHandle" に紐付いたセグメントを参照することができるとともに、そのエリアを保証できます。

Copy memHandle

逆に、不要になった場合は、"MemHandle" のインスタンスを破棄することで、デストラクタ内で、参照カウンタが-1されます。
このことで、参照しているインスタンスがすべてなくなった時点で、自動的にリンクされているセグメントは解放されます。

Use memHandle

この仕組みにより、必要なオブジェクトが各自メモリが、非同期に必要な間インスタンスを確保し、不要になったら各自のタイミングで破棄したとしても、安全にメモリを確保・解放することができ、意識することなく、すべてのユーザがインスタンスを破棄することで、暗黙の裡に参照が外れます。

Release memHandle

Memory Layoutに関しては、Memory Layoutを使うためのヘッダファイル群をあらかじめ用意する必要があります。 これらのヘッダファイルは、Memory Layout定義ファイル(mem_layout.conf)を作成し、専用のツール(mem_layout.py)を使うことで、生成されます。

5.9.2.3. APIs

”Memory Manager"のインタフェースは次の通りです。 詳細は、 memutils_memory_manager を参照してください。

5.9.2.3.1. Managerクラスの関数
MemMgrLiteライブラリの初期化
関数
static err_t Manager::initFirst(void* lib_area, uint32_t area_size)
引数
void*     lib_area   : ライブラリが使用するデータ領域
uint32_t  area_size  : 領域のサイズ(byte単位)
戻り値
ERR_OK        : 初期化成功
ERR_STS       : 2回以上、本関数を実行している
ERR_DATA_SIZE : area_sizeが、sizeof(MemMgrLite::Manager)未満
ERR_ADR_ALIGN : lib_areaが、4の倍数ではない
説明
ライブラリ全体の初期化を行う。
フェンス機能が有効な場合は、FixedAreaのフェンスの初期化を行う。
本ライブラリの他のAPIを使用する前に、
//事前に取り決めた単一のCPUで一回のみ
本関数を実行すること。

引数lib_areaは、ライブラリ用のデータ領域のアドレスを指定する。
アドレスが、4の倍数でなければ、ERR_ADR_ALIGNを返す。
指定する領域は、永続寿命を持つ領域であること。また性能上、SRAMなどの
高速なメモリが望ましい。

引数area_sizeは、lib_areaのサイズをbyte単位で指定する。
サイズが、sizeof(MemMgrLite::Manager)未満の場合は、ERR_DATA_SIZEを返す。
現在の実装で必要なサイズは、(4 + 4 * NUM_MEM_POOLS) なので、最小で12bytes
最大で1028bytesとなる。
//オプションの動的生成プールを使用する場合は追加で、(8 + 5 * NUM_DYN_POOLS)を4の倍数に切り上げたサイズが必要となる。

//本ライブラリをマルチコア(共有プール)サポートで使用する場合は、この領域は
全てのCPUからアクセスできる必要がある。
//ARMのTCMやMIPSのScratchPadなどは、CPUローカルなメモリなので、マルチコア
サポート時のlib_areaには指定できない。
使用例1

メモリレイアウト定義ファイルで、MemMgrLite用データ領域を定義して使用する例を示します。

//S_ASSERT(MEMMGR_DATA_AREA_SIZE >= sizeof(MemMgrLite::Manager));
void* lib_data_va = MemMgrLite::translatePoolAddrToVa(MEMMGR_DATA_AREA_ADDR);
if (MemMgrLite::Manager::initFirst(lib_data_va, MEMMGR_DATA_AREA_SIZE)) != ERR_OK)
  {
    /* エラー処理 */;
  }
使用例2

静的変数で定義したMemMgrLiteのデータ領域を使用する例を示します。
sizeofで領域を確保できるため、サイズ不足の心配がありません。 なお領域は、4byteアラインを保障するため、uint32_tの配列として定義しています。

static uint32_t s_lib_data[sizeof(MemMgrLite::Manager) / sizeof(uint32_t)];
if (MemMgrLite::Manager::initFirst(s_lib_data, sizeof(s_lib_data)) != ERR_OK)
  {
    /* エラー処理 */;
  }
CPU毎の初期化
関数
static err_t Manager::initPerCpu(void* lib_area)
引数
void*     lib_area  /* ライブラリが使用するデータ領域 */
戻り値
ERR_OK        : 初期化成功
ERR_STS       : 2回以上、本関数を実行している、あるいはinitFirst()の未実行
説明
ライブラリのCPU毎の初期化を行う。
引数lib_areaは、Manager::initFirst()に指定したものと同じアドレスを指定する。

Manager::initFirst()が未実行か、
既に本APIを実行済みのCPUで、再度本APIを実行した場合は、ERR_STSを返す。

//本ライブラリをマルチコア(共有プール)サポートで使用する場合は、全てのCPUはManager::initFirst()の実行完了を(プラットフォーム固有の方法で)待ってから、本関数を実行する必要がある。
使用例1

メモリレイアウト定義ファイルで定義したMemMgrLiteのデータ領域を使用する例を示します。

void* lib_data_va = MemMgrLite::translatePoolAddrToVa(MEMMGR_DATA_AREA_ADDR);
if (MemMgrLite::Manager::initPerCpu(lib_data_va)) != ERR_OK)
  {
    /* エラー処理 */;
  }
使用例2

静的変数で定義したMemMgrLiteのデータ領域を使用する例を示します。

if (MemMgrLite::Manager::initPerCpu(s_lib_data)) != ERR_OK)
  {
    /* エラー処理 */;
  }
静的メモリプールの生成
関数
static err_t Manager::createStaticPools(uint8_t sec_no,
                                        NumLayout layout_no,
                                        void* work_area,
                                        uint32_t area_size,
                                        const PoolSectionAttr *pool_attr)
引数
uint8_t                sec_no    : セクション番号 (0 origin)
NumLayout              layout_no : メモリレイアウト番号 (0 origin)
void*                  work_area : 静的メモリプール操作用の作業領域
uint32_t               area_size : 作業領域のサイズ(byte単位)
const PoolSectionAttr *pool_attr : メモリレイアウトのアドレス
戻り値
ERR_OK        : 初期化成功
ERR_STS       : initPerCpu()が未実行、あるいは本関数が実行済み
ERR_ADR_ALIGN : work_areaが、4の倍数ではない
ERR_DATA_SIZE : area_sizeが、最大作業領域サイズ未満
説明
指定されたレイアウト番号のメモリプール郡を生成する。
メモリレイアウトを変更する場合には、いったんManager::destroyStaticPools()で
メモリプール郡を破棄してから、再度本関数を実行すること。

Manager::initPerCpu()が未実行の場合、
既に本関数が実行済みの場合は、ERR_STSを返す。

引数sec_noは、使用するセクション番号を指定する。

引数layout_noは、使用するメモリレイアウトの番号を指定する。

引数work_areaは、静的メモリプール操作用の作業領域のアドレスを指定する。
アドレスが、4の倍数でなければ、ERR_ADR_ALIGNを返す。
指定する領域は、Manager::destroyStaticPools()が呼び出されるまで存在する
領域であること。また性能上、SRAMなどの高速なメモリが望ましい。

引数area_sizeは、静的メモリプール操作用の作業領域のサイズを指定する。
レイアウト番号毎に定義されたマクロMEMMGR_Lx_WORK_SIZE(xはレイアウト番号)
以上の値を指定する。
全レイアウト中の最大作業領域サイズは、マクロMEMMGR_MAX_WORK_SIZEで定義される。
作業領域のサイズが不足した場合は、ERR_DATA_SIZEを返す。

//本ライブラリをマルチコア(共有プール)サポートで使用する場合は、この領域は全てのCPUからアクセスできる必要がある。
//ARMのTCMやMIPSのScratchPadなどは、CPUローカルなメモリなので、マルチコアサポート時には指定できない。
使用例1

メモリレイアウト定義ファイルで、MemMgrLite用作業領域を定義して使用する例を示します。 マルチコアサポート時やSRAM配置時は、この方法が使いやすいです。

S_ASSERT(MEMMGR_WORK_AREA_SIZE >= MEMMGR_MAX_WORK_SIZE);
uint8_t        sec_no = 0;
const NumLayout layout_no = 0;
void* work_va = MemMgrLite::translatePoolAddrToVa(MEMMGR_WORK_AREA_ADDR);
if (MemMgrLite::Manager::createStaticPools(sec_no, layout_no, work_va, MEMMGR_WORK_AREA_SIZE) != ERR_OK)
  {
    /* エラー処理 */;
  }
使用例2

静的変数で定義したMemMgrLiteの作業領域を使用する例を示します。 領域は、4byteアラインを保障するため、uint32_tの配列として定義しています。

static uint32_t s_work_area[MEMMGR_MAX_WORK_SIZE / sizeof(uint32_t)];
uint8_t        sec_no = 0;
const NumLayout layout_no = 0;
if(MemMgrLite::Manager::createStaticPools(sec_no, layout_no, s_work_area, sizeof(s_work_area) != ERR_OK)
  {
    /* エラー処理 */;
  }
Spresense では、SRAMのみ選択できます。
静的メモリプールの破棄(消去)
関数
static void Manager::destroyStaticPools(uint8_t sec_no)
引数
uint8_t  sec_no    : セクション番号 (0 origin)
戻り値
なし
説明
Manager::createStaticPools()で生成したセクション番号の静的メモリプールを破棄する。
静的メモリプール未生成時は、何もしない。
Manager::initPerCpu()が未実行の場合は、"debug_assert"する。

メモリプールの破棄時には、セグメント解放漏れのチェックを行う。
解放漏れが検出された場合は、"assert"する。

フェンス機能が有効な場合は、静的メモリプールのフェンスチェックを行い
フェンス破壊が検出された場合は、"assert"する。
使用例
/* 静的メモリプールを破棄する */
MemMgrLite::Manager::destroyStaticPools(0);
現在のメモリレイアウト番号を取得
関数
static NumLayout Manager::getCurrentLayoutNo()
引数
なし
戻り値
現在設定されているメモリレイアウト番号
未設定の場合は、BadLayoutNo
説明
現在のメモリレイアウト番号を取得する。
メモリレイアウト番号の初期値は、BadLayoutNo。
Manager::createStaticPools()を呼ぶと引数で指定した値が設定される。
Manager::destroyStaticPools()を呼ぶと初期値にリセットされる。
使用例
/* 現在のメモリレイアウト番号を取得する */
MemMgrLite::NumLayout layout_no = MemMgrLite::Manager::getCurrentLayoutNo();
if (layout_no != MemMgrLite::BadLayoutNo)
  {
    printf("Current memory layout number: %d\n", layout_no);
  }
else
  {
    printf("Memory layout number not set\n");
  }
使用中のメモリセグメントの取得
関数
static uint32_t Manager::getStaticPoolsUsedSegs(MemHandle* mhs, uint32_t num_mhs)
//static uint32_t Manager::getUsedSegs(PoolId id, MemHandle* mhs, uint32_t num_mhs)
引数
PoolId       id      : プールID
MemHandle*   mhs     : 使用中のメモリセグメントを格納するメモリハンドル配列
uint32_t     num_mhs : 配列の要素数
戻り値
メモリハンドル配列に格納したセグメント数
説明
メモリプール内で使用中のセグメントをメモリハンドル配列に格納する。
格納されたセグメントの参照カウントは、1増加する。
使用中のセグメント数が、引数num_mhsで指定した値よりも多い時は、num_mhs個の
セグメントを格納した時点で、処理を打ち切る。

getStaticPoolsUsedSegs()は、現在のメモリレイアウトの静的プール全体を対象とする。
//getUsedSegs()は、指定されたIDの静的または動的メモリプールが対象となる。

引数mhsは、メモリセグメントを保持していない空のメモリハンドル配列を指定すること。
引数idが有効なプールIDでなければ、"debug_assert"する。
引数mhsまたはnum_mhsが0の場合は、"debug_assert"する。

これらのAPIは、メモリプールを破棄する前に、解放されていないセグメントの詳細な
情報を取得する用途を想定している。

なお、使用中のセグメント数を知るだけであれば、下記の方が効率が良い。
Manager::getPoolNumSegs(id) - Manager::getPoolNumAvailSegs(id)
使用例
const uint32_t MaxSegInfo = 8;
MemHandle  mhs[MaxSegInfo];

uint32_t num_used = Manager::getStaticPoolsUsedSegs(mhs, MaxSegInfo);
for (uint32_t i = 0; i < num_used; ++i)
  {
    printf("ID=%u SegNo=%u VA=%08x Size=%u RefCnt=%u\n",
            mhs[i].getPoolId(), mhs[i].getSegNo(), mhs[i].getVa(),
            mhs[i].getSize(), mhs[i].getRefCnt());
  }
メモリプールの各種情報を取得
関数
static bool     Manager::isPoolAvailable(PoolId id)
static PoolType Manager::getPoolType(PoolId id)
static PoolAddr Manager::getPoolAddr(PoolId id)
static PoolSize Manager::getPoolSize(PoolId id)
static NumSeg   Manager::getPoolNumSegs(PoolId id)
static NumSeg   Manager::getPoolNumAvailSegs(PoolId id)
static bool     Manager::isPoolFenceEnable(PoolId id)
//static LockId   Manager::getPoolLockId(PoolId id)
引数
PoolId   id  /* メモリプールID (1 origin) */
戻り値
説明を参照
説明
isPoolAvailable()は、現在のメモリレイアウトで、指定されたプールIDが有効か否かを返す。

getPoolType(), getPoolAddr(), getPoolSize(), getPoolNumSegs()は、プール
生成時に指定された、プール種別、アドレス、サイズ、セグメント数を返す。

getPoolNumAvailSegs()は、現在の空きセグメント数を返す。

isPoolFenceEnable()は、プール生成時に指定されたフェンス指定を返す。
本関数は、フェンス機能有効時(UseFence = True)のみ定義される。

//getPoolSpinLockId()は、プール生成時に指定されたスピンロックIDを返す。
//本関数は、マルチコアサポート有効時(UseMultiCore = True)のみ定義される。

無効なプールIDを指定するとNULLポインタアクセスを引き起こすので、プールIDの
有効性を確認して使用すること。
使用例
if (MemMgrLite::Manager::isPoolAvailable(my_pool_id))
  {
    printf("type=%d addr=%08x size=%08x num_seg=%u avail_seg=%u\n",
             MemMgrLite::Manager::getPoolType(my_pool_id),
             MemMgrLite::Manager::getPoolAddr(my_pool_id),
             MemMgrLite::Manager::getPoolSize(my_pool_id),
             MemMgrLite::Manager::getPoolNumSegs(my_pool_id),
             MemMgrLite::Manager::getPoolNumAvailSegs(my_pool_id));
#ifdef USE_MEMMGR_FENCE
    printf(" fence=%u\n", MemMgrLite::Manager::isPoolFenceEnable(my_pool_id));
#endif
//#ifdef USE_MEMMGR_MULTI_CORE
//  printf(" spl_id=%u\n", MemMgrLite::Manager::getPoolSpinLockId(my_pool_id));
//#endif
  }
5.9.2.3.2. MemHandleクラスの関数
コンストラクタ/デストラクタ
関数
MemHandle::MemHandle()                       // default constructor
MemHandle::MemHandle(PoolId id, size_t size) // segment allocate constructor
MemHandle::MemHandle(const MemHandle& mh)    // copy constructor
MemHandle::~MemHandle()                      // destructor
引数
PoolId           id    : プールID
size_t           size  : 要求サイズ(byte単位)
const MemHandle& mh    : コピー元メモリハンドル
戻り値
なし
説明
MemHandleクラスのインスタンスを生成または破棄する。

引数idは、メモリセグメントを取得するプールIDを指定する。
取得結果は、isAvail() or isNull()で判定する。

引数sizeは、要求サイズを指定する。
現状この引数は、セグメントサイズとの比較にのみ使用され、セグメントサイズを
超える値が指定された場合は、"debug_assert"する。

引数mhは、コピー元のメモリハンドルを指定する。
コピー元のメモリハンドルが、メモリセグメントを保持している場合は
メモリセグメントの参照カウントが、1増加する。

メモリセグメントを保持しているインスタンスのデストラクタは、メモリセグメントの
参照カウントを、1減少させる。
使用例
MemMgrLite::MemHandle mh(MY_POOL_ID, sizeof(MyData));
if (mh.isNull())
  {
    /* エラー処理 */;
  }
代入演算子
関数
MemHandle::MemHandle& operator=(const MemHandle& mh)
引数
const MemHandle& mh  : コピー元メモリハンドル
戻り値
自身への参照
説明
自身とコピー元の値が異なる場合にインスタンスの代入を行う。
同じ場合は何もしない。

メモリセグメントを保持している場合は、代入前にメモリセグメントの
参照カウントを、1減少させる。

コピー元のメモリハンドルが、メモリセグメントを保持している場合は
代入後にメモリセグメントの参照カウントを、1増加させる。
使用例
MemMgrLite::MemHandle mh;        /* default constructor */
mh = src_mh;                            /* call operator=() */
メモリセグメント取得
関数
err_t MemHandle::allocSeg(PoolId id, size_t size, MemHandleProxy &proxy)
引数
PoolId           id     : プールID
size_t           size   : 要求サイズ(byte単位)
MemHandleProxy   &proxy : メモリセグメントの参照
戻り値
ERR_OK        : 取得成功
ERR_DATA_SIZE : sizeがセグメントサイズを超えている
ERR_MEM_EMPTY : 取得できるセグメントが無い
説明
指定されたメモリプールからメモリセグメントを取得する。
引数idは、メモリセグメントを取得するプールIDを指定する。

引数sizeは、要求サイズを指定する。
現状この引数は、セグメントサイズとの比較にのみ使用され、セグメントサイズを
超える値が指定された場合は、ERR_DATA_SIZEを返す。

取得できるセグメントが無い場合は、ERR_MEM_EMPTYを返す。
使用例
MemMgrLite::MemHandle mh;
if (mh.allocSeg(MY_POOL_ID, sizeof(MyData)) != ERR_OK)
  {
    /* エラー処理 */;
  }
明示的なメモリセグメント解放
関数
void MemHandle::freeSeg()
引数
なし
戻り値
なし
説明
デストラクタに頼らずに明示的にメモリセグメントを解放する。
メモリセグメントを保持していない場合は、何もしない。
メモリセグメントを保持している場合は、メモリセグメントの参照カウントを
1減少させてから、インスタンスを再初期化する。
メモリセグメントの各種情報を取得
関数
bool        MemHandle::isAvail()
bool        MemHandle::isNull()
bool        MemHandle::isSame(const MemHandle& mh)
PoolId      MemHandle::getPoolId()
NumSeg      MemHandle::getSegNo()
PoolAddr    MemHandle::getAddr()
PoolSize    MemHandle::getSize()
SegRefCnt   MemHandle::getRefCnt()
引数
const MemHandle& mh    : 比較先メモリハンドル
戻り値
説明参照
説明
isAvail()は、インスタンスがメモリセグメントを保持しているか否かを返す。

isNull()は、インスタンスがメモリセグメントを未保持か否かを返す。

isSame()は、インスタンスと引数mhが同じ値か否かを返す。

getPoolId()は、インスタンスがメモリセグメントを保持していれば
セグメントが所属しているプールのIDを返す。
セグメントを保持していなければ、NullPoolIdを返す。

getSegNo()は、インスタンスがメモリセグメントを保持していれば
セグメントが所属しているプール内でのセグメント番号(1 origin)を返す。
セグメントを保持していなければ、NullSegNoを返す。

getSegAddr()は、インスタンスがメモリセグメントを保持していれば
セグメントのアドレスを返す。
セグメントを保持していなければ、"debug_assert"する。

getSegSize()は、インスタンスがメモリセグメントを保持していれば
セグメントのサイズを返す。
セグメントを保持していなければ、"debug_assert"する。

getRefCnt()は、インスタンスがメモリセグメントを保持していれば
セグメントの参照カウントを返す。
セグメントを保持していなければ、"debug_assert"する。
5.9.2.4. Configurations and Generate

”Memory Manager” のLayoutファイルの記述方法と作成方法を説明します。

Layout情報は、MemoryLayout定義ファイル"mem_layout.conf" (名前は変えられます。) の中に、Pythonで記載され、 "mem_layout.py" というツールで、C++言語の3つヘッダ、 "mem_layout.h" "fixed_fence.h" "pool_layout.h" を生成します。 ユーザは、このヘッダをインクルードすることで、”Memory Manager” を使えることになります。

5.9.2.4.1. How to write a Memory Layout File

"mem_layout.conf"は、”Memory Manager”のコンフィグレーション、ユーザー定数の定義、デバイスの定義、固定領域の定義、PoolLayoutの定義を行います。それぞれの説明を以下に示します。

”Memory Manager”のコンフィグレーション

”Memory Manager” の各種機能の使用有無を指定できます。指定できる機能と指定方法は下記の通りです。 .

Feature Description

UseFence

フェンスの使用有無をTrue/Falseで指定します。 有効にするとUSE_MEMMGR_FENCEマクロが定義され、指定された領域の前後に4byteの 上書き検出用フェンスを配置します。またフェンスチェック用APIが定義されます。

指定の記述例
UseFence = True  # Use of a pool fence
ユーザー定数の定義

MemoryLayout定義ファイル内で使用する定数に、"U_"で開始されるユーザー独自の名称をつける ことができます。また、定義には、Pythonの任意の式を記述することが出来ます。

ユーザー定義定数の記述例
  # スクリプト内定義と重ならないように、"U_"で開始して英大文字、数字と"_"のみとする
  # "U_MEM_"で始まる名称で定義すると、ヘッダファイルに同名のマクロが出力される

  U_STD_ALIGN   = 8     # standard alignment
  U_MSGQ_ALIGN  = 64    # message queue area alignment
Memoryのデバイス定義

各種Memoryデバイスを定義します。これらの定義は、固定領域の定義に使用されます。 ヘッダファイルには、name_ADDRマクロとname_SIZEマクロとして出力されます。

Memoryのデバイス定義の記述例
MemoryDevices.init(
  # name         ram    addr        size
  ["AUD_SRAM",   True,  0x000c0000, 0x00040000],
  None # end of definition
)

各パラメータの説明は以下の通りです。

パラメータ 説明

name

デバイス名(3文字以上。英大文字で始まり、英大文字, 数字, "_"が使用可能)

ram

デバイスがRAMならば、True。それ以外ならばFalse。

addr

領域のアドレス。0を除く4の倍数の値を指定します。

size

領域のサイズ。0を除く4の倍数の値を指定します。

固定領域の定義

各メモリデバイスに領域を定義します。 各領域の開始アドレスは、デバイス毎の累積サイズ、align、fenceにより決定されます。
ヘッダファイルには、name_ALIGN, name_ADDR, name_SIZEマクロとして出力されます。

固定領域の定義の記述例
FixedAreas.init(
  # name,                  device,    align,        size,         fence
  ["AUDIO_WORK_AREA",     "AUD_SRAM", U_STD_ALIGN,  0x0003e000,   False], # Audio work area
  ["MSG_QUE_AREA",        "AUD_SRAM", U_STD_ALIGN,  0x00001000,   False], # message queue area
  ["MEMMGR_WORK_AREA",    "AUD_SRAM", U_STD_ALIGN,  0x00000200,   False], # MemMgrLite WORK Area
  ["MEMMGR_DATA_AREA",    "AUD_SRAM", U_STD_ALIGN,  0x00000100,   False], # MemMgrLite DATA Area
  None # end of definition
)

各パラメータの説明は以下の通りです。

パラメータ 説明

name

領域名(英大文字で始まり、"_AREA"で終わる名称。英大文字, 数字, _が使用可能)

device

領域を確保するMemoryDevicesのデバイス名

align

領域の開始アライメント。0を除くMinAlign(=4)の倍数を指定します。

size

領域のサイズ。0を除く4の倍数の値を指定します。

fence

フェンスの有効・無効を指定します。(この項目は、UseFenceがFalseの場合は無視されます)

PoolLayoutの定義

メモリプールのレイアウトを定義します。 各プール領域の開始アドレスは、固定領域毎の累積サイズ、align、fenceにより決定されます。
ヘッダファイルには、プールIDとNUM_MEM_POOLS, NUM_MEM_LAYOUTSおよび Lx_name_ALIGN, Lx_name_ADDR, Lx_name_SIZE, Lx_name_NUM_SEG, Lx_name_SEG_SIZE マクロとして出力されます。(xはレイアウト番号)
フェンスが有効な場合は、Lx_name_L_FENCE, Lx_name_U_FENCEマクロも出力されます。

PoolLayoutの定義の記述例
# Definition for player
U_MAIN_BUF_SIZE = 1024
U_MAIN_BUF_SEG_NUM = 4
U_MAIN_BUF_POOL_SIZE = U_MAIN_BUF_SIZE * U_MAIN_BUF_SEG_NUM

U_PCM_BUF_SIZE = 1024
U_PCM_BUF_SEG_NUM = 8
U_PCM_BUF_POOL_SIZE = U_PCM_BUF_SIZE * U_PCM_BUF_SEG_NUM

# Definition for recorder
U_REC_BUF_SIZE = 2048
U_REC_BUF_SEG_NUM = 6
U_REC_BUF_POOL_SIZE = U_REC_BUF_SIZE * U_REC_BUF_SEG_NUM

PoolAreas.init(
  [ # layout 0 for Player
    #[ name,           area,              align,        pool-size,            seg,                 fence]
    ["MAIN_BUF_POOL",  "AUDIO_WORK_AREA", U_STD_ALIGN,  U_MAIN_BUF_POOL_SIZE, U_MAIN_BUF_SEG_NUM,  True ],
    ["PCM_BUF_POOL",   "AUDIO_WORK_AREA", U_STD_ALIGN,  U_PCM_BUF_POOL_SIZE,  U_PCM_BUF_SEG_NUM,   True ],
    None # end of each layout
  ], # end of layout 0

  [ # layout 1 for Recorder
    #[ name,          area,              align,        pool-size,            seg,                fence]
    ["REC_BUF_POOL",  "AUDIO_WORK_AREA", U_STD_ALIGN,  U_REC_BUF_POOL_SIZE,  U_REC_BUF_SEG_NUM,  True ],
    None # end of each layout
  ], # end of layout 1

  None # end of definition
)
使用例

プレーヤーとレコーダーを切り替えて使う

  /* Player: レイアウト No.0 を使う */

  err = Manager::createStaticPools(0,    // Section no 0
                                   0,    // Layout no 0 for Player
                                   translatePoolAddrToVa(S0_MEMMGR_WORK_AREA_ADDR),
                                   S0_MEMMGR_WORK_AREA_SIZE,
                                   MemoryPoolLayouts[0][0]);

  /* Playerの処理 */

  ...

  /* 再生中 */

  ...

  /* Playerの終了 */

  ...

  /* レイアウトの破棄 */

  destroyStaticPools(0);

  ...

  /* Recorder 処理開始 */

  /* Recorder: レイアウト No.1 を使う */

  err = Manager::createStaticPools(0,    // Section no 0
                                   1,    // Layout no 0 for recorder
                                   translatePoolAddrToVa(S0_MEMMGR_WORK_AREA_ADDR),
                                   S0_MEMMGR_WORK_AREA_SIZE,
                                   MemoryPoolLayouts[0][1]);

  /* Recorderの処理 */

  ...

  /* 記録中 */

  ...

  /* Recorderの終了 */

  ...

  /* レイアウトの破棄 */

  destroyStaticPools(0);

メモリセクションは別々の領域に3つまで定義できます。

Audio用のPoolLayoutとSensor用のPoolLayoutを定義する記述例
# Definition for player
U_MAIN_BUF_SIZE = 1024
U_MAIN_BUF_SEG_NUM = 4
U_MAIN_BUF_POOL_SIZE = U_MAIN_BUF_SIZE * U_MAIN_BUF_SEG_NUM

U_PCM_BUF_SIZE = 1024
U_PCM_BUF_SEG_NUM = 8
U_PCM_BUF_POOL_SIZE = U_PCM_BUF_SIZE * U_PCM_BUF_SEG_NUM

# Definition for recorder
U_REC_BUF_SIZE = 2048
U_REC_BUF_SEG_NUM = 6
U_REC_BUF_POOL_SIZE = U_REC_BUF_SIZE * U_REC_BUF_SEG_NUM

# Sensor
U_SENSOR_DSP_CMD_SIZE       = 0x300
U_SENSOR_DSP_CMD_SEG_NUM    = 8
U_SENSOR_DSP_CMD_POOL_SIZE  = U_SENSOR_DSP_CMD_SIZE  * U_SENSOR_DSP_CMD_SEG_NUM

U_SENSOR_DATA_BUF_SIZE      = 0x300
U_SENSOR_DATA_BUF_SEG_NUM   = 8
U_SENSOR_DATA_BUF_POOL_SIZE = U_SENSOR_DATA_BUF_SIZE * U_SENSOR_DATA_BUF_SEG_NUM

# section 0
PoolAreas.init(
  [ # layout 0 for Player
    #[ name,           area,              align,        pool-size,            seg,                 fence]
    ["MAIN_BUF_POOL",  "AUDIO_WORK_AREA", U_STD_ALIGN,  U_MAIN_BUF_POOL_SIZE, U_MAIN_BUF_SEG_NUM,  True ],
    ["PCM_BUF_POOL",   "AUDIO_WORK_AREA", U_STD_ALIGN,  U_PCM_BUF_POOL_SIZE,  U_PCM_BUF_SEG_NUM,   True ],
    None # end of each layout
  ], # end of layout 0

  [ # layout 1 for Recorder
    #[ name,          area,              align,        pool-size,            seg,                fence]
    ["REC_BUF_POOL",  "AUDIO_WORK_AREA", U_STD_ALIGN,  U_REC_BUF_POOL_SIZE,  U_REC_BUF_SEG_NUM,  True ],
    None # end of each layout
  ], # end of layout 1

  None # end of definition
)

# section 1
PoolAreas.init(
  [ # layout 0 for Sensor
    #[ name,                    area,               align,       pool-size,                   seg,                        fence]
    ["SENSOR_DSP_CMD_BUF_POOL", "COMMON_WORK_AREA", U_STD_ALIGN, U_SENSOR_DSP_CMD_POOL_SIZE,  U_SENSOR_DSP_CMD_SEG_NUM,   False],
    ["SENSOR_DATA_BUF_POOL",    "COMMON_WORK_AREA", U_STD_ALIGN, U_SENSOR_DATA_BUF_POOL_SIZE, U_SENSOR_DATA_BUF_SEG_NUM,  False],
    None # end of each layout
  ], # end of layout 0

  None # end of definition
)
使用例

レコーダーとセンサーを同時に使う

  /* Recorder: レイアウト No.1 を使う */

  err = Manager::createStaticPools(0,    // Section no 0
                                   1,    // Layout no 0 for Recorder
                                   translatePoolAddrToVa(S0_MEMMGR_WORK_AREA_ADDR),
                                   S0_MEMMGR_WORK_AREA_SIZE,
                                   MemoryPoolLayouts[0][1]);

  /* Sensor: レイアウト No.0 を使う */

  err = Manager::createStaticPools(1,    // Section no 1
                                   0,    // Layout no 0
                                   translatePoolAddrToVa(S0_MEMMGR_WORK_AREA_ADDR),
                                   S0_MEMMGR_WORK_AREA_SIZE,
                                   MemoryPoolLayouts[0][0]);

  /* Recorderの処理 */

  /* Sensorの処理 */

  ...

  /* 再生中 */

  /* Sensing */

  ...

  /* Recorderの終了 */

  /* Sensorの終了 */

  ...

  /* レイアウトの破棄(Recorder) */

  destroyStaticPools(0);

  /* レイアウトの破棄(Sensor) */

  destroyStaticPools(1);

  ...

各パラメータの説明は以下の通りです。

パラメータ 説明

name

プール名(英大文字で始まり、"_POOL"で終わる名称。英大文字, 数字, _が使用可能)

area

プール領域として使用するFixedAreaの領域名。領域はRAMに配置して下さい。

align

プールの開始アライメント。0を除くMinAlign(=4)の倍数を指定します。

pool-size

プールのサイズ。0を除く4の倍数の値。セグメントサイズ * セグメント数。

seg

セグメント数。1以上、255以下の値を指定します。

fence

フェンスの有効・無効を指定します。この項目は、UseFenceがFalseの場合は無視されます。

5.9.2.4.2. How To Generate

"mem_layout.py" を使ったLayoutファイルの作成方法は以下の通りです。

Usage
python3 mem_layout.conf [layout_header] [fence_header] [pool_header]
Example
python3 mem_layout.conf mem_layout.h fixed_fence.h pool_layout.h

"mem_layout.py"の各引数の説明は下記の通りです。

表 30. Layoutファイルの作成ツールの引数
Parameter Description

mem_layout.conf

Memory Layout定義ファイル

layout_header

各種定数値がマクロとして出力されるヘッダファイル。この引数を省略した場合、"mem_layout.h"という名前のファイルを生成します。メモリサイズ調整用として、レイアウト毎に残り使用可能サイズがコメント形式(/* Remainder XXXX_AREA=0xXXXXXXXX */)で出力されます。

fence_header

FixedAreaのメモリフェンスアドレスが出力されるヘッダファイル。この引数を省略した場合、"fixed_fence.h"という名前のファイルを生成します。”Memory Manager”が使用するファイルのため、ユーザーは使用しないで下さい。

pool_header

PoolAreaの各種定義が出力されるヘッダファイル。この引数を省略した場合、"pool_layout.h"という名前のファイルを生成します。”Memory Manager”が使用するファイルなので、ユーザーは使用しないで下さい。

5.9.3. Message Library

主に、"Memory Manager" のような Task間でClass Instanceの送受信を行う必要がある場合、通常、OSが提供しているシステムコールでは対応できなため、"Message Library" を用いて、これを実現しています。 ここでは、この "Message Library" の説明を行います。

5.9.3.1. General

"Message Library" は、タスク間でClass Instanceの送受信を行えるタスク間同期ライブラリです。

このライブラリは、送り先をIDとして明示的に指定して送信します。 また、受信側は、送信イベントを待ち受けて、イベントドリブン動作を実現します。

Message Sequence

また、このメッセージにはTypeを持っており、受け取ったインスタンスが、あったかなかったか、あった場合何であったかは、Typeによって判断し取り出します。

ただし、送受信したいクラスは、正しくコピーコンストラクタを実装している必要があります。
5.9.3.2. Message ID と Type
5.9.3.2.1. Message ID

Message ID は、以下 How to write a Message Layout File の Configurationに従って、静的に作成します。 Configuration の詳細はそちらを参照してください。

IDを確定したら、タスクのループの中で、

  MsgQueId id = XX; // Assign the created ID to a variable "id".

  MsgQueBlock *que;
  MsgPacket   *msg;


  err_t err = MsgLib::referMsgQueBlock(id, &que);
  err = que->recv(TIME_FOREVER, &msg);

とすることで、Massageイベント待ちになり、Message ID = XXのイベントドリブン処理が実現できます。

逆に、イベントを送信する場合は、

  MsgQueId send_id = XX; // Assign ID that be sent to a variable "send_id".
  MsgQueId ret_id = XX; // Assign ID that will return to a variable "self_id".

  Object instance; // Class and Instance you want to send.

  instance(); // Construction.

  err_t err = MsgLib::send<Object>(send_id, MsgPriNormal, MSG_TYPE, ret_id, instance);

このように、送信したいIDを send_id、返信してほしいIDを ret_idに代入し、送信したいクラス(Object)のインスタンスを作成し、MsgLib::send で送信します。

ID は、アプリケーションに応じて作成し、明示的に送受信のデータパスを指定しながら使用します。

5.9.3.2.2. Message Type

Message ライブラリは、受け取った Message Packet から適切なInstance を取り出すために、 Message Type を用いてどういったオブジェクトが送られたかを判断します。 このため、 Message Packet には、すべて Message Type を付加します。

この Message Type は、"sdk/modules/include/memutils/message/message_type.h"で定義されています。

Message Type は、以下のようなデータ構造を取ります。

Diagram

各フィールドの説明は以下の通りです。

フィールド名 フィールド 説明

REQ

[15]

メッセージが要求か応答かを示します。0は応答、1は要求です。

MSG_USER

[14-12]

メッセージの使用者情報です。0~7の値でメッセージを使用するシステムを指定することが出来ます。ただし、6は、AudioSubSystem, 7はSensorSubSystemが予約しているため、実際には0~5の値を使用することが出来ます。

MSG_CATEGORY

[11-8]

メッセージのカテゴリ情報です。0~15の値でカテゴリを指定することが出来ます。

MSG_SUB_TYPE

[7-0]

メッセージのサブタイプ情報です。0~255の値でカテゴリ内のメッセージタイプを指定することが出来ます。

定義されているIDは、以下になります。

MSG_TYPE_REQUEST

メッセージの方向を示します。

D15 Description

0

response

1

request

MSG_USER

メッセージを使用するシステムを指定します。 現在、AudioとSensorのIDは予約されています。

D14-D12 Description

0-5

reserved

6

Audio Sub System

7

Sensor Sub System

MSG_CATEGORY

各システム内で自由に定義してください。

例えば、Audioの場合は、
"sdk/modules/include/audio/audio_message_types.h"

Sensorの場合は、
"sdk/modules/include/sensing/sensor_message_types.h"

で定義されています。

MSG_SUB_TYPE

各システム内で自由に定義してください。

例えば、Audioの場合は、
sdk/modules/audio/include/commmon/audio_interanl_message_types.h

Sensorの場合は、
sdk/modules/include/sensing/sensor_message_types.h

で定義されています。

メッセージタイプは、IDが違う場合、同じ値を定義したとしても運用可能ですが、デバッグしやすさと、データパスが変わって、別なIDに送信するような変更などに対しての変更容易性などを鑑みて、すべてをユニークに作るようにしてください。

以下のような実装で、Message Packet からInstanceを取り出します。

  MsgQueBlock *que;
  MsgPacket   *msg;

  err_t err = MsgLib::referMsgQueBlock(id, &que);
  err = que->recv(TIME_FOREVER, &msg);

  if (msg->getType() == MSG_TYPE) { // Check that the message type is as expected or not.

    Object instance = msg->moveParam<Object>(); // get an instance of type Object from Message packet.

  }
5.9.3.3. APIs

"Message Library"のインタフェースは次の通りです。 詳細は、 memutils_message を参照してください。

5.9.3.3.1. MsgLibクラスの関数
メッセージライブラリの初期化
関数
static err_t MsgLib::initFirst(uint32_t num_pools, uint32_t top_drm)
引数
uint32_t num_pools  : メッセージのセグメント数(メッセージの種別数)
uint32_t top_drm    : メッセージ管理エリアのアドレス
戻り値
ERR_OK        : 初期化成功
ERR_STS       : 本関数が実行済み
説明
メッセージライブラリ全体の初期化を行う。
本ライブラリの他のAPIを使用する前に、事前に取り決めた単一のCPUで一回だけ本関数を実行すること。
CPU毎の初期化
関数
static err_t MsgLib::initPerCpu()
引数
なし
戻り値
ERR_OK        : 初期化成功
ERR_STS       : MsgLib::initFirst()が未実行
説明
メッセージライブラリのCPU毎の初期化を行う。
CPU毎の各種領域や計数セマフォ(OS環境のみ)の初期化など。

本ライブラリを使用する全てのCPUは、MsgLib::initFirst()の実行完了を
待ってから、本関数を実行する必要がある。

MsgLib::initFirst()が未実行の場合は、ASSERTする。
既に本APIを実行済みのCPUで、再度本APIを実行した場合は、ASSERTする。
メッセージライブラリの終了
関数
static err_t MsgLib::finalize()
引数
なし
戻り値
ERR_OK        : 初期化成功
ERR_STS       : MsgLib::initFirst()が未実行
説明
メッセージライブラリの終了処理を行う。
内部管理情報をクリアする。
メッセージキューの初期化状態の取得
関数
static bool MsgLib::isInitComplete(MsgQueId id)
引数
MsgQueId    id  : メッセージキューID
戻り値
true  :  初期化済み(キューを所有しているCPUで、初期化が完了している)
false : 未初期化
説明
メッセージキューの初期化状態を取得する。
引数idの示すメッセージキューブロックが存在しない場合は、ASSERTする。
MsgLib::initFirst()が未実行の場合は、ASSERTする。
メッセージパケットの送信
関数
static err_t MsgLib::send(MsgQueId dest, MsgPri pri, MsgType type, MsgQueId reply)

template<typename T>
  static err_t MsgLib::send(MsgQueId dest, MsgPri pri, MsgType type, MsgQueId reply, const T& param)

static err_t send(MsgQueId dest, MsgPri pri, MsgType type, MsgQueId reply, const void* param, size_t param_size)

static err_t MsgLib::sendIsr(MsgQueId dest, MsgPri pri, MsgType type, MsgQueId reply)

template<typename T>
  static err_t MsgLib::sendIsr(MsgQueId dest, MsgPri pri, MsgType type, MsgQueId reply, const T& param)

static err_t sendIsr(MsgQueId dest, MsgPri pri, MsgType type, MsgQueId reply, const void* param, size_t param_size)
引数
MsgQueId    dest        : 送信先メッセージキューID
MsgPri      pri         : メッセージの優先度
MsgType     type        : メッセージ種別を識別するための値
MsgQueId    reply       : 返信先メッセージキューID
const T&    param       : メッセージのパラメタ
const void* param       : メッセージパラメタへのアドレス
size_t      param_size  : パラメータサイズ
戻り値
ERR_OK       : 送信成功
ERR_QUE_FULL : メッセージキューに空きがない
説明
引数destとpriで示されるキューに、メッセージパケットを格納する。
send()はタスクコンテキスト、sendIsr()は非タスクコンテキストで使用する。
sendIsr()でパラメタを使用する場合、割込み処理の最短化のため、できるだけ
クラスインスタンスは使用せず、パラメタサイズも最小化する事。

引数paramのサイズが大きすぎてキューに格納できない場合は、ASSERTする。
引数destとpriで示されるキューが存在しないか、あるいは初期化が完了して
いない場合は、ASSERTする。
他CPU所有で、自CPUとのスピンロック共有がないキューを指定した場合は、ASSERTする。

sendIsr()で、共有キューを指定した場合は、ASSERTする。
これは、非タスクコンテキストでのスピンロック待ちを防止するためである。
メッセージ受信を通知
関数
static void MsgLib::notifyRecv(MsgQueId dest)
引数
MsgQueId    dest  : 通知先メッセージキューID
戻り値
なし
説明
他CPUからのメッセージの受信を通知する。
本関数は、CPU間通信割込みハンドラから呼び出されることを想定している。
引数destの示すメッセージキューブロックが存在しないか、あるいは初期化が完了していない場合は、ASSERTする。
5.9.3.3.2. MsgQueBlockクラスの関数
メッセージキューブロックへの参照を取得
関数
static MsgQueBlock& MsgLib::referMsgQueBlock(MsgQueId id)
引数
MsgQueId    id  : メッセージキューID
戻り値
メッセージキューブロック参照
説明
メッセージキューブロックへの参照を取得する。
引数idの示すメッセージキューブロックが存在しないか、あるいは初期化が完了していない場合は、ASSERTする。
メッセージパケットの受信
関数
MsgPacket* MsgQueBlock::recv(uint32_t ms)
引数
uint32_t  ms : 受信待ち時間(ミリ秒)または、TIME_POLLING or TIME_FOREVER
戻り値
NULL以外: メッセージキュー内のメッセージパケットへのポインタ
NULL    : 受信タイムアウト
説明
指定された時間、メッセージパケットの受信待ちを行う。
MsgLib::send()とは異なり、複数タスクによる同一キューへの同時recv()はサポートしない。
os_wrap.hで、TIME_POLLINGは0、TIME_FOREVERは-1に定義されている。

前回受信したメッセージパケットが、MsgQueBlock::pop()により破棄されていない場合は、ASSERTする。
メッセージキューが他CPU所有の場合は、ASSERTする。
メッセージパケットの破棄
関数
void MsgQueBlock::pop()
引数
なし
戻り値
なし
説明
メッセージキューからメッセージパケットを取り除く。
メッセージパケットにパラメタが存在する場合は、MsgPacket::moveParam()か
MsgPacket::popParam()により、事前にパラメタを破棄すること。
複数タスクによる同一キューの同時pop()はサポートしない。

破棄対象メッセージパケットが存在しない場合は、ASSERTする。
破棄対象メッセージパケットのパラメタ長が、0以外の場合は、ASSERTする。
メッセージキューが他CPU所有の場合は、ASSERTする。
メッセージパケット数の取得
関数
uint16_t MsgQueBlock::getNumMsg(MsgPri pri) const
引数
MsgPri    pri  : メッセージキュー優先度
戻り値
メッセージパケット数
説明
メッセージキュー内のメッセージパケット数を取得する。
引数priの値が不正な場合は、ASSERTする
格納可能なメッセージパケット数の取得
関数
uint16_t MsgQueBlock::getRest(MsgPri pri) const
引数
MsgPri    pri  : メッセージキュー優先度
戻り値
格納可能なメッセージパケット数
説明
メッセージキューに格納可能なメッセージパケット数を取得する。
未使用のキューは、常に0を返す。
引数priの値が不正な場合は、ASSERTする。
5.9.3.3.3. MsgPacketクラスの関数
メッセージタイプIDの取得
関数
MsgType MsgPacket::getType() const
引数
なし
戻り値
メッセージタイプID
説明
メッセージパケットのタイプIDを取得する。
メッセージリプライキューIDの取得
関数
MsgQueId MsgPacket::getReply() const
引数
なし
戻り値
リプライキューID
説明
メッセージパケットのリプライキューIDを取得する。
メッセージパラメタ長の取得
関数
uint16_t MsgPacket::getParamSize() const
引数
なし
戻り値
メッセージパラメタ長。パラメタなし時は0が返される。
説明
メッセージパケットのパラメタ長を取得する。
メッセージパラメタの破壊取り出し(移動)
関数
template<typename T>  T MsgPacket::moveParam()
引数
なし
戻り値
メッセージパラメタ
説明
メッセージパケットのパラメタを取り出す(移動)。
sizeof(T) != MsgPacket::getParamSize() の場合、ASSERTする。

本APIは、以下の処理と等価となる。

 T param = MsgPacket::peekParam<T>();  /* 左辺を非参照にして、パラメタのコピーを作成 */
 MsgPacket::popParam<T>();	           /* パラメタを破棄 */
 return param;                         /* パラメタのコピーを返す */


本APIの呼出しにより、メッセージパラメタ長が0に変更される。
メッセージパラメタへの参照やポインタは無効となるので、注意すること。
メッセージパラメタ参照の取得
関数
template<typename T> const T& MsgPacket::peekParam() const

template<typename T> const T& MsgPacket::peekParamOther() const
引数
なし
戻り値
メッセージパラメタのconst参照
説明
メッセージパケットのパラメタへの参照を取得する。
peekParam()は、送信時と同じ型、peekParamOther()は、送信時と異なる型
(例えばパラメタのヘッダの型)での参照に使用する。

peekParam()は
sizeof(T) != MsgPacket::getParamSize()
の場合、ASSERTする。

peekParamOther()は、
sizeof(T) > MsgPacket::getParamSize()
の場合、ASSERTする。

これらのAPIの戻り値を非参照で受け取るとパラメタのコピーが取得できる。
メッセージパラメタの破棄
関数
template<typename T> void MsgPacket::popParam()

void MsgPacket::popParamNoDestruct()
引数
なし
戻り値
なし
説明
メッセージパケットのパラメタを破棄する。
popParam()は、パラメタのデストラクタを呼出す。
popParamNoDestruct()はデストラクタを呼出さないので、パラメタにデストラクタが
存在しないメッセージパケットにのみ使用することができる。
特別な理由がない限り、popParam()を使用すること。

popParam()は、
sizeof(T) != MsgPacket::getParamSize()
の場合、ASSERTする。

これらのAPIの呼出しにより、メッセージパラメタ長が0に変更される。
メッセージパラメタへの参照やポインタは無効となるので、注意すること。
5.9.3.4. Configurations and Generate

”Message Library” のLayoutファイルの記述方法と作成方法を説明します。

Layout情報は、"msgq_layout.conf" (名前は変えられます。) の中に、Pythonで記載され、 "msgq_layout.py" というツールで、C++言語の2つヘッダ、 "msgq_id.h" "msgq_pool.h" を生成します。 ユーザは、このヘッダをインクルードすることで、”Message Library” を使えることになります。

5.9.3.4.1. How to write a Message Layout File

"msgq_layout.conf"は、”Message Library”のユーザー定数の定義、メッセージキュープールの定義、デバッグ値の指定、メッセージパラメータのチェック指定を行います。それぞれの説明を以下に示します。

ユーザー定数の定義

Message Layout定義ファイル内で使用する定数に、"U_"で開始されるユーザー独自の名称をつける ことができます。また、定義には、Pythonの任意の式を記述することが出来ます。

ユーザー定義定数の記述例
  # ユーザー定義定数は、"U_"で始まる英大文字・数字の名称とすること
  # "U_MSGQ_"で始まる名称で定義すると、msgq_id.hにdefineマクロとしても出力される

  U_HEADER_SIZE	= 8	# Message packet header size
メッセージキュープールの定義

ユーザー定義定数を使って、メッセージキュープールを定義することが出来ます。

メッセージキュープールの定義の記述例
U_MSG_SIZE = 16
U_MSG_NUM  = 8

MsgQuePool = [
 # ID,                        n_size       n_num         h_size           h_nums
  ["MSGQ_USER_APP",           U_MSG_SIZE,  U_MSG_NUM,    0,               0],
  ["MSGQ_DSP_CMD",            256,         10,           U_MSG_SIZE,      U_MSG_NUM],
  None # end of user definition
] # end of MsgQuePool

各パラメータの説明は以下の通りです。

パラメータ 説明

ID

メッセージキュープールIDの名称を、"MSGQ_"で始まる文字列で指定します。"MSGQ_NULL", "MSGQ_TOP", "MSGQ_END"は予約済みのため使用禁止です。

n_size

通常優先度キューの各要素のバイト数(8以上512以下)。固定ヘッダ長(8byte) + パラメタ長を4の倍数で指定します。

n_num

通常優先度キューの要素数(1以上16384以下)。

h_size

高優先度キューの各要素のバイト数(0または、8以上512以下)。未使用時は0を指定して下さい。

h_num

高優先度キューの要素数(0または、1以上16384以下)。未使用時は0を指定して下さい。

デバッグ値の指定やメッセージパラメータのチェック指定もありますが、使用しない設定としてください。
MsgFillValueAfterPop = 0x00
MsgParamTypeMatchCheck = False
5.9.3.4.2. How To Generate

"msgq_layout.py" を使ったLayoutファイルの作成方法は以下の通りです。

Usage
python3 msgq_layout.py [--help] [-h] [--without_memory_layout] [-n]
           [address | fixed_file] [size | fixed_ID]
           [id_header] [pool_header]

-n, --without_memory_layout  Allocate message memory in a global variable
-h, --help                   Show this usage and exit
Example
python3 msgq_layout.conf
             or
python3 msgq_layout.conf 0x00800000 0x20000
             or
python3 msgq_layout.conf ../include/mem_layout.h
             or
python3 msgq_layout.conf --without_memory_layout
             or
python3 msgq_layout.conf mem_layout.h MSG_QUE_AREA msgq_id.h msgq_pool.h
ツールを実行しているディレクトリ内に、[address | fixed_file][size | fixed_ID] を省略する場合、実行しているディレクトリ内に mem_layout.h が存在している必要があります。
--without_memory_layout を指定すると、内部で静的にメモリを確保し、そこを利用します。

"msgq_layout.py"の各引数の説明は下記の通りです。

表 31. Layoutファイルの作成ツールの引数
Parameter Description

msgq_layout.conf

メッセージキューレイアウト定義ファイル

address or fixed_file

メッセージ領域のアドレスです。もしくは、Memory Manager で生成された 'memory_layout.h' を指定します。この引数を省略した場合、本ツールを実行したディレクトリ内にある 'memory_layout.h' を読み込みます。ディレクトリ内に 'memory_layout.h' がない場合は必ず指定してください。

size or fixed_ID

バイト単位の領域サイズです。'memory_layout.h' を指定した場合は、メッセージライブラリとして使用する fixed_ID を指定してください。何も指定しない場合は、MSG_QUE_AREA を本ライブラリのエリアとして使用します。

id_header

メッセージキューIDマクロが出力されるファイル。この引数を省略した場合、"msgq_id.h"という名前のファイルを生成します。

pool_header

メッセージキュープールの定義が出力されるファイル。この引数を省略した場合、"msgq_pool.h"という名前のファイルを生成します。

5.9.3.4.3. Sequence
Diagram

5.9.4. Simple FIFO

5.9.4.1. General

Simple FIFO

本ライブラリは、1ユーザからの書き込みと1ユーザからの読み出しを排他制御なしでFIFO機能を実現します。 複数のユーザからの書き込みと複数ユーザからの読み出しを行いたい場合は、排他制御が必要です。

5.9.4.2. APIs

詳細は、Doxygenを参照してください。 APIの一覧は下記の通りです。

表 32. SimpleFIFO API一覧
API name Description

CMN_SimpleFifoInitialize

SimpleFIFOの初期化。FIFOに使用するメモリ領域を設定します。

CMN_SimpleFifoOffer

FIFOにデータをpushします。コピー処理はmemcpy()を使用します。

CMN_SimpleFifoOfferWithSpecificCopier

FIFOにデータをpushします。コピー処理はユーザー側で用意します。DMA用いたコピーなどを想定しています。

CMN_SimpleFifoOfferContinuous

FIFOにデータをpushします。指定したサイズ分連続領域にコピーします。指定したサイズ分の連続領域が無い場合は、pushを行いません。コピー処理はmemcpy()を使用します。

CMN_SimpleFifoOfferContinuousWithSpecificCopier

FIFOにデータをpushします。指定したサイズ分連続領域にコピーします。指定したサイズ分の連続領域が無い場合は、pushを行いません。コピー処理はユーザー側で用意します。DMA用いたコピーなどを想定しています。

CMN_SimpleFifoPoll

FIFOからデータをpopします。popしたデータはFIFOから削除されます。コピー処理はmemcpy()を使用します。

CMN_SimpleFifoPollWithSpecificCopier

FIFOからデータをpopします。popしたデータはFIFOから削除されます。コピー処理はユーザー側で用意します。DMA用いたコピーなどを想定しています。

CMN_SimpleFifoPeekWithOffset

FIFOの先頭から指定したOffsetから、指定したサイズのデータのアドレス情報を取得します。FIFOのデータを削除せずに参照したい場合に使用します。

CMN_SimpleFifoPeek

FIFOの先頭から指定したサイズのデータのアドレス情報を取得します。FIFOのデータを削除せずに参照したい場合に使用します。

CMN_SimpleFifoClear

FIFOのRead/Writeポインタをクリアし、空の状態にします。

CMN_SimpleFifoGetVacantSize

FIFOの空きサイズを取得します。

CMN_SimpleFifoGetOccupiedSize

FIFOの使用サイズを取得します。

CMN_SimpleFifoGetExtInfo

CMN_SimpleFifoInitialize()で設定したFIFOの拡張情報を取得します。

CMN_SimpleFifoGetDataSizeOfPeekHandle

CMN_SimpleFifoPeek()で取得したアドレス情報の要素数を取得します。

CMN_SimpleFifoCopyFromPeekHandle

CMN_SimpleFifoPeek()で取得したアドレス情報からデータを取得します。コピー処理はmemcpy()を使用します。

CMN_SimpleFifoCopyFromPeekHandleWithSpecificCopier

CMN_SimpleFifoPeek()で取得したアドレス情報からデータを取得します。コピー処理はユーザー側で用意します。DMA用いたコピーなどを想定しています。

5.9.4.3. Sequence

SimpleFIFOの簡易シーケンスです。

Diagram

5.9.5. Code Examples

These libraries are used with audio features. So, their samples are audio samples.

  • examples/audio_player

  • examples/audio_recorder


5.10. Power Management

5.10.1. Overview

Power Management は、Spresense SDK の特徴的な機能である省電力を実現するために電源管理を行うモジュールです。CXD5602 内部の電源ドメインやクロックの管理、及び、各種スリープモードのサポートを行います。

5.10.2. 電源状態

Spresense SDK は、省電力を実現するために、Deep SleepCold SleepHot Sleep の3つの Sleep モードをサポートしています。

Deep Sleep

CXD5602 は全ての電源ドメインが OFF されていて、CXD5247 PMIC(Power Management IC) のみ通電している状態です。このとき CXD5247 も Sleep 状態に入っており、最も消費電力を低く抑えることができます。

Cold Sleep

CXD5602 内で必要最小限の電源ドメインのみ ON されている状態です。アラームタイマーや、USB 挿抜、GPIO 信号の変化など、Deep Sleep に比べて、多くの起床要因をトリガとして、この Sleep 状態から起床することができます。

Hot Sleep

OS がアイドル状態のときに、この Sleep 状態へと遷移します。Sleep 中も SRAM の状態が保持されているため、起床の際に、SPI-Flash からプログラムを再ロードする必要がなく、高速に Sleep 状態から復帰することができます。

現在のSDKバージョンでは、Hot Sleep はサポートしておりません。
5.10.2.1. 電源状態遷移

主な電源状態の状態遷移図を以下に示します。

Power State Diagram
図 76. Power State Diagram
State Description

PowerOff

CXD5247 PMIC(Power Management IC) も含めて、全ての電源が OFF されている状態です

Battery Check

電源供給の電圧レベルを監視している状態です。電源供給が 3.4 V 以上のときに CXD5602 がブートし、Run 状態に遷移します。

Run

通常の実行状態です。

Idle

OS アイドル状態です。OS アイドルタスクでは WFI (Wait for Interrupt) で割込み待ちをしています。

Hot Sleep

OS アイドル状態が一定の時間以上続くことが予想される場合に、この状態に遷移します。Hot Sleep 状態中は、SRAM のデータは保持されています。

Cold Sleep

CXD5602 の必要最小限な電源のみ ON され、SRAM 含めてそれ以外の電源は OFF 状態です。

Deep Sleep

CXD5602 が電源 OFF されており、CXD5247 PMIC(Power Management IC) だけが ON している状態です。

5.10.2.2. 電源ドメイン階層構造

CXD5602 チップ内部は、階層構造をもったいくつかの電源ドメインに分かれて構成されています。 各種 Sleep モードと電源ドメインとの関係を以下に示します。

Power Domain Hierarchical Structure

5.10.3. 電源状態制御 API

Spresense SDK は、各種電源状態からの起動要因 (以下、boot cause) 、及び、起動要因の許可・禁止を制御するための起動マスク (以下、boot mask) をもっています。

boot cause

各種スリープモードから起床・起動された要因を表します

boot mask

起動要因の許可・禁止を制御します

boot cause、及び、boot mask は共通のビットフラグ構造をしており、それぞれの起動要因が1つのビットで表されます。boot mask の該当ビットに1がセットされると起動要因として許可、0をセットすると禁止になります。Sleep 状態にいるときに、boot mask で許可された起動要因のイベントが発生したときに Sleep 状態から起床します。そのとき、どの起動要因が boot cause に反映されます。

起動要因、起動マスクの定義を以下に示します。

  • Boot Type は、POR (Power-On-Reset) により起動したのか、Reboot による再起動なのか、Deep Sleep, Cold Sleep 状態からの起動なのかを表します。

  • Maskable は、Yes のものだけ起動要因として禁止することが許可されています。No のものは起動要因として禁止することはできません。

boot cause / boot mask Boot Type Maskable Description

PM_BOOT_POR_NORMAL

POR Boot

No

バッテリーもしくは電源が ON された

PM_BOOT_POR_DEADBATT

POR Boot

No

バッテリーもしくは電源が 3.4V 以上になり起動した

PM_BOOT_WDT_REBOOT

Reboot

No

システムウォッチドッグによりリブートした

PM_BOOT_WDT_RESET

Reboot

No

CXD5602 単体のウォッチドッグによりリセットされた

PM_BOOT_DEEP_WKUPL

Deep Boot

Yes

WKUPL 信号を検知した(*2)

PM_BOOT_DEEP_WKUPS

Deep Boot

Yes (*1)

WKUPS 信号を検知した(*2)

PM_BOOT_DEEP_RTC

Deep Boot

Yes (*1)

RTC Alarm が発火した

PM_BOOT_DEEP_USB_ATTACH

Deep Boot

No

USB が接続された(*2)

PM_BOOT_DEEP_OTHERS

Deep Boot

No

未使用

PM_BOOT_COLD_SCU_INT

Cold Boot

Yes

SCU 割り込みを検知した

PM_BOOT_COLD_RTC

Cold Boot

Yes

RTC Alarm が発火した

PM_BOOT_COLD_RTC_ALM0

Cold Boot

Yes

RTC Alarm0 が発火した(SDK は Alarm0 を使用します)

PM_BOOT_COLD_RTC_ALM1

Cold Boot

Yes

RTC Alarm1 が発火した(未使用)

PM_BOOT_COLD_RTC_ALM2

Cold Boot

Yes

RTC Alarm2 が発火した(未使用)

PM_BOOT_COLD_RTC_ALMERR

Cold Boot

Yes

RTC Alarm Error が発生した(未使用)

PM_BOOT_COLD_GPIO

Cold Boot

Yes

GPIO 割り込みを検出した

PM_BOOT_COLD_SEN_INT

Cold Boot

Yes

Sensor 割り込み (SEN_INT) を検出した

PM_BOOT_COLD_PMIC_INT

Cold Boot

Yes

PMIC (CXD5247) 割り込みを検出した

PM_BOOT_COLD_USB_DETACH

Cold Boot

Yes

USB ケーブルが外された(*2)

PM_BOOT_COLD_USB_ATTACH

Cold Boot

Yes

USB ケーブルが接続された(*2)

(*1) PM_BOOT_DEEP_WKUPS と PM_BOOT_DEEP_RTC の両方の起動マスクを禁止にすることはできません。

(*2) Spresenseボードではサポートされていません。

電源状態制御に関連して、次の Power Management API が提供されます。

  • 起動要因の取得

  • 起動マスクの取得

  • 起動マスクの許可・禁止

  • Sleep モードへの遷移

  • リブート

5.10.3.1. 起動要因の取得 API
Function Prototype
uint32_t up_pm_get_bootcause(void);
Description
  • 起動要因を取得します

5.10.3.2. 起動マスクの取得 API
Function Prototype
uint32_t up_pm_get_bootmask(void);
Description
  • 起動要因として何が許可・禁止されているかを表す起動マスクを取得します

    • デフォルトでは、全ての起動要因が許可されています

    • Deep Sleep、もしくは、Power-On-Reset により、この起動マスク値はリセットされます。 Hot Sleep もしくは Cold Sleep 中はこの起動マスク値は保持されています。

5.10.3.3. 起動要因の許可 API
Function Prototype
uint32_t up_pm_set_bootmask(uint32_t mask);
Description
  • 引数で指定した起動要因を有効にします

  • 戻り値は、更新後の起動マスクを返します

5.10.3.4. 起動要因の禁止 API
Function Prototype
uint32_t up_pm_clr_bootmask(uint32_t mask);
Description
  • 引数で指定した起動要因を無効にします

  • 戻り値は、更新後の起動マスクを返します

Example
#include <arch/chip/pm.h>

  uint32_t bootmask;

  bootmask = up_pm_get_bootmask(); // Get the current bootmask
  printf("bootmask=0x%08x\n", bootmask);

  bootmask = up_pm_clr_bootmask(PM_BOOT_COLD_USB_DETACH); // Disable wakeup by USB detached
  printf("bootmask=0x%08x\n", bootmask); // Display the updated bootmask
5.10.3.5. Sleep 遷移 API
Function Prototype
int up_pm_sleep(enum pm_sleepmode_e mode);
Description
  • Sleep モードに遷移します

  • この関数の呼び出しから戻ってくることはなく、そのまま Sleep 状態に遷移します。

Arguments
引数 mode Description

PM_SLEEP_DEEP

Deep Sleep に移行します

PM_SLEEP_COLD

Cold Sleep に移行します

up_pm_sleep() の発行により、CXD5602 チップ単体として Sleep モードへ遷移します。 Sleep 状態へ遷移するにあたり、チップだけでなく基板に依存した処理を追加で行う場合があります。 BSP の基板依存部に、board_power_off() 関数を実装することで、基板の制御を含めた Sleep モードへの遷移を行います。

BSP 依存部に実装される Sleep 遷移 API を以下に示します。 これは、NuttShell 上の poweroff コマンドからも制御できます。

Function Prototype
int board_power_off(int status)
Arguments
引数 status Description NuttShell command

BOARD_POWEROFF_DEEP

Deep Sleep に移行します

poweroff

BOARD_POWEROFF_COLD

Cold Sleep に移行します

poweroff 1

5.10.3.6. リブート
Function Prototype
int up_pm_reboot(void);
Description
  • システムを再起動します

  • この関数の呼び出しから戻ってくることはなく、そのまま再起動します

BSP 基板依存部に、board_reset() 関数を実装することで、基板の制御を含めた再起動を実現することができます。

Function Prototype
int board_reset(int status);

board_reset() は、NuttShell 上の reboot コマンドからも制御できます。

5.10.4. スリープモード

5.10.4.1. Deep Sleep
5.10.4.1.1. 特徴

Deep Sleep は次のような特徴をもちます。

  • CXD5602 は、電源 OFF 状態です

  • CXD5247 は、Sleep モードに入り、CXD5602 へ供給されるコア電源、IO電源は OFF されます

    • CXD5247 RTC 時刻は保持されます(システムが RTC XTAL を持っていることが前提です)

    • CXD5247 GPO スイッチは Deep Sleep 中も値が保持されています

      • Deep Sleep 中に GPO を ON にしておく必要がないなら、省電力の観点から Deep Sleep に入る前に OFF することを推奨します

    • CXD5247 Load Switch は OFF されます

    • CXD5602 の IO が OFF になりますので、周辺デバイスから CXD5602 へ電流がリークしないように注意して下さい

5.10.4.1.2. 消費電力
  • バッテリーの消費電流は、バッテリー端でおよそ 数uA ~ 数+uA程度になります。ただし、この値は基板の設計に依存します。CXD5602 が電源 OFF されるため、周辺デバイスから CXD5602 へのリーク電流が発生しないように注意して基板を設計してください。

Sleep 中の消費電力に関して、拡張ボードに SD カードが挿入されていると SD カードの電源消費分により 約 5 mA ほど消費電流が増加します。
5.10.4.1.3. スリープ条件
  • up_pm_sleep(PM_SLEEP_DEEP) や board_poweroff(BOARD_POWEROFF_DEEP) を呼び出すことによって、Deep Sleep 状態に遷移します

  • WKUPL 信号を使用している場合は、WKUPL が 3 秒以上アサートされた場合に、Deep Sleep 状態に遷移します

Spresense 基板では WKUPL 端子が出ていないため、WKUPL 信号による Deep Sleep への遷移機能を使用することはできません
5.10.4.1.4. 起床条件

起床条件が発生すると、プログラムは SPI-Flash のロードから開始されるため、Power-On-Resetによる起動とほぼ同じだけの時間がかかります。

  • PM_BOOT_DEEP_WKUPL : WKUPL 信号が3秒以上アサートされた場合

  • PM_BOOT_DEEP_WKUPS : WKUPS 信号がアサートされた場合

  • PM_BOOT_DEEP_RTC : RTC Alarm が発火した場合

  • PM_BOOT_DEEP_USB_ATTACH : USB ケーブルが接続された場合

    • 通常、USB ケーブルが接続されていた場合は、Deep Sleep 状態に入ることはできません。 ただし、CONFIG_BOARD_USB_DISABLE_IN_DEEP_SLEEPING=y にすれば、USB 機能を Disable して Deep Sleep 状態に遷移することができます。このとき、USB 接続をトリガにして起床することはできません。

Spresense 基板では WKUPL, WKUPS 端子が出ていないため、WKUPL, WKUPS 信号による Deep Sleep からの起床機能を使用することはできません
5.10.4.2. Cold Sleep
5.10.4.2.1. 特徴
  • CXD5602 は、チップ内部の PMU 電源ドメインのみ ON された状態です

    • CXD5602 I/O ピンは有効になっています

    • Backup SRAM の内容は保持されます

  • CXD5247 は通常動作状態です

    • CXD5247 RTC 時刻は保持されます(システムが RTC XTAL を持っていることが前提です)

    • CXD5247 GPO スイッチは Cold Sleep 中も値が保持されます

    • CXD5247 Load Switch は Cold Sleep 中も値が保持されます

5.10.4.2.2. 消費電力
  • バッテリーの消費電流は、バッテリー端でおおよそ数百 uA です。この電流値は基板の設計に依存します。

Sleep 中の消費電力に関して、拡張ボードに SD カードが挿入されていると SD カードの電源消費分により 約 5 mA ほど消費電流が増加します。
5.10.4.2.3. スリープ条件
  • up_pm_sleep(PM_SLEEP_COLD) や board_poweroff(BOARD_POWEROFF_COLD) を呼び出すことによって、Cold Sleep 状態に遷移します

5.10.4.2.4. 起床条件

起床条件が発生すると、プログラムは SPI-Flash のロードから開始されるため、Power-On-Resetによる起動とほぼ同じだけの時間がかかります。

  • PM_BOOT_COLD_SCU_INT : SCU 割り込みが発火した場合

  • PM_BOOT_COLD_SEN_INT : Sensor 割り込みが発火した場合

  • PM_BOOT_COLD_PMIC_INT : CXD5247 からの割り込みが発火した場合

    • WKUPS 信号がアサートされた場合

    • Low Battery が通知された場合

  • PM_BOOT_COLD_GPIO : GPIO 割り込みがアサートされた場合

  • PM_BOOT_COLD_RTC_ALM0 : RTC Alarm が発火した場合

  • PM_BOOT_COLD_USB_ATTACH : USB ケーブルが接続された場合

  • PM_BOOT_COLD_USB_DETACH : USB ケーブルが外された場合

Spresense 基板では USB 挿抜による Cold Sleep からの起床機能はサポートされていません
5.10.4.3. Hot Sleep
現在のSDKバージョンでは、Hot Sleep はサポートしておりません。
5.10.4.3.1. 特徴
  • CXD5602 は、通常動作状態にほぼ等しいですが、NuttX が 動作しているアプリケーション CPU は電源 OFF されます

    • 但し、Hot Sleep 期間中も SRAM の値は保持されています

  • CXD5247 は通常動作状態です

5.10.4.3.2. 消費電力
  • バッテリーの消費電流は、バッテリー端で最小で数百 uA 以下にまで下げることができますが、アプリケーションとして何を動作させている状態かに強く依存します。

5.10.4.3.3. スリープ条件
  • CONFIG_CXD56_HOT_SLEEP=y にすることで、Hot Sleep が有効になります。

    • 以下の CONFIG パラメーターで、Hot Sleep 状態に遷移する条件を変更できます

      • CONFIG_CXD56_HOT_SLEEP_WAIT_COUNT (milliseconds)

      • CONFIG_CXD56_HOT_SLEEP_THRESHOLD (milliseconds)

    • wakelock の取得と解除

      • 後述する wakelock 機構で Hot Sleep 制御を行います。一つでも wakelock が獲得されている限り、Hot Sleep への遷移が禁止されます

Power Manager は、以下に示すアルゴリズムで Hot Sleep 状態へ遷移します。

  1. NuttX OS がアイドル状態の場合、 Power Manager はアイドル状態に滞在する時間をカウントします

    • 何かしらの割り込みが発生した場合は、アイドル状態から抜けて、カウンタはリセットされます

  2. カウンタが、CONFIG_CXD56_HOT_SLEEP_WAIT_COUNT で定義された値を超えた場合、 Power Manager は、この後に続くアイドル時間を予測して計算します

  3. もし、この予測アイドル時間 > CONFIG_CXD56_HOT_SLEEP_THRESHOLD を超えていた場合、システムは Hot Sleep 状態へと遷移します

    • wakelock が獲得されている場合は、システムは Hot Sleep 状態への遷移は禁止されます

5.10.4.3.4. 起床条件
  • アプリケーション CPU に対する割り込みが発生した場合

    • UART1 受信割り込み

    • UART2 受信割り込み

    • SCU (Sensor Control Unit) Watermark 割り込み

    • USB 挿抜割り込み

    • CXD5247 からの割り込み

    • GPIO 割り込み

    • 他の CPU からの CPU 間通信による割り込み

    • OS Timer 割り込み

5.10.5. 省電力制御

Spresense SDK は、以下のような省電力機能を提供します。

  • CPU システムクロック制御

  • CPU スリープ制御

5.10.5.1. CPU システムクロック制御

システムクロックは、主に 3 つのモードを提供しています。

Mode CPU Clock CXD5602 Core Voltage

HV (High Voltage) モード

PLL 156MHz

1.0 V

LV (Low Voltage) モード

PLL 32MHz

0.7 V

RCOSC モード

RCOSC 約 8MHz

0.7 V

クロック制御を行わない場合、常に HV モードで動作します。 動的なクロック制御による省電力機能を有効にする場合は、以下のコンフィグレーションを設定してください。

 [CXD56xx Configuration]
   [Power Management]
     [Dynamic clock control] <= Y

Dynamic clock control を有効にすると、システムは HV モード で起動した後に RCOSC モードまでクロックを落とします。定常状態では、RCOSC モードで動作します。

一時的に、高いパフォーマンスが要求される処理を行う場合は、 Frequency Lock 機構を使用して動的にクロックを変更することが可能です。

RCOSC モード、LV モード、HV モードの順番で動作クロックが上がりパフォーマンスも向上しますが、その分だけ消費電力も増加します。Frequency Lock 機構は、LV モードに切り替えたい場合は LV ロックを、HV モードに切り替えたい場合は HV ロックを獲得します。獲得したロックを解放すると、元のクロック状態に戻ります。システム全体のうち、どれか一つでも、より高いクロックモードのロックを獲得している限りは、システムは高いクロックモードで動作します。例として、LV ロック、HV ロックの両方が獲得されている場合は、HV モードになります。HV ロックが解放された場合に、次に高いクロックモードである LV モードへと切り替わります。そこで、LV ロックも解放されると RCOSC モードに戻ります。

  • HV ロック獲得

      struct pm_cpu_freqlock_s lock;
    
      lock.flag = PM_CPUFREQLOCK_FLAG_HV;
      up_pm_acquire_freqlock(&lock);
  • HV ロック解放

      up_pm_release_freqlock(&lock);
  • LV ロック獲得

      struct pm_cpu_freqlock_s lock;
    
      lock.flag = PM_CPUFREQLOCK_FLAG_LV;
      up_pm_acquire_freqlock(&lock);
  • LV ロック解放

      up_pm_release_freqlock(&lock);

HV, LV ロックの取得/解放に応じてシステム全体のクロックが動的に変更されますが、 例えば、SPI 転送中などクロック変更を避けたい期間が存在するかもしれません。 PM_CPUFREQLOCK_FLAG_HOLD フラグを使用することで、そのフラグがロックされている期間は、 システムクロックの変更を抑止することができます。

PM_CPUFREQLOCK_FLAG_HOLD フラグを同一スレッドから二重にロックしないようにしてください。 PM_CPUFREQLOCK_FLAG_HOLD フラグの実装にセマフォを使用しているため、 同一スレッドから二重にロックする(up_pm_acquire_freqlock()を連続で呼び出す)とそのスレッドがデッドロックします。
  • HOLD ロック獲得

      struct pm_cpu_freqlock_s lock;
    
      lock.flag = PM_CPUFREQLOCK_FLAG_HOLD;
      up_pm_acquire_freqlock(&lock);
  • HOLD ロック解放

      up_pm_release_freqlock(&lock);
5.10.5.2. CPU スリープ制御

SDK は アプリケーション CPU が アイドル状態のときに自動的に Hot Sleep に遷移する機能を提供します。

現在のSDKバージョンでは、スリープ制御機能はサポートしておりません。

デフォルト設定では、Hot Sleep 機能は無効になっています。この機能を有効にするには以下の設定が必要です。

 [CXD56xx Configuration]
   [Power Management]
     [Hot Sleep] <= Y
       [Hot Sleep wait counter] <= 20
       [Hot Sleep threshold] <= 1000
       [Enable GNSS Hot Sleep] <= Y

CONFIG_CXD56_HOT_SLEEP=y にすると、OS アイドル状態のときに自動的に Hot Sleep 状態に遷移します。 CONFIG_CXD56_GNSS_HOT_SLEEP=y にすると、GNSS CPU の Hot Sleep 機能を有効にすることができます。

アイドル状態で自動的に Hot Sleep 状態に遷移しますが、wakelock 機構により Sleep 状態に遷移するのを抑止することができます。

  • wakelock ロック獲得

    struct pm_cpu_wakelock_s lock;
    
    lock.count = 0;
    up_pm_acquire_wakelock(&lock);
  • wakelock ロック解放

    up_pm_release_wakelock(&lock);

5.11. Sensor Fusion Framework

5.11.1. General

CXD5602 はLow Power 常時センシング機能を備えているとともに、 多くのCoreとメモリによるセンサフュージョン機能が実現可能です。

SDKでは、これらを容易に実現するためのフレームワークを提供しています。

センサフュージョンフレームワークは、"Sensor Manager" と各センサの"Sensor Client"から構成されます。

  • "Sensor Manager" は、Publish-Subscribe Architectureに基づき、複数の"Sensor Client"を制御し、ここからPublishされるSensor Dataを配信します。

  • "Sensor Client"は、各種 "Sensor Device"を制御するドライバを制御する、"Physical Sensor"、 各"Sensor Device"からのデータをFusionして、高機能なセンサを実現する"Logical Sensor"、 Applicationがデータを受け取るための、"Sensor Application"から構成されています。

Sensor Framework のArchitecture図は以下の通りです。

Sensor Framework(Publish/subscribe) Architecture
図 77. Sensor Framework (Publish/subscribe) Architecture

5.11.2. Sensor Manager

"Sensor Manager" は、複数の"Sensor Client"の登録、管理を行い、 適切にセンサデータの配信を行います。

5.11.2.1. General

"Sensor Manager" に登録された、"Sensor Client"は、取得したデータを"Sensor Manager" に打ち上げることで、"Sensor Manager" が、Subscribeを要求している "Sensor Client" に適切にデータを配信します。

また、Subscribeされていない"Sensor Client"の電源モードを落とせるような枠組みを提供します。

5.11.2.2. APIs

"Sensor Manager" は、以下のAPIを提供します。 "Sensor Manager" のインターフェースは、パケットと呼ばれるデータ形式のコマンドを を発行すること制御可能です。 "Sensor Client" の登録、削除、データの受け渡しなどを行います。

表 33. Sensor Manager API
APIs Description Corresponding API Corresponding packet

Register

Resister a Sensor Client to Sensor Manager as subscriber.

SS_SendSensorResister

sensor_command_register_t

Release

Unresister the Sensor Client from Sensor Manager.

SS_SendSensorRelease

sensor_command_release_t

SendData

Sender function to Sensor Manager without MemHandle.

SS_SendSensorData

sensor_command_data_t

SendData(MH)

Sender function to Sensor Manager with MemHandle.

SS_SendSensorDataMH

sensor_command_data_mh_t

SendSetPower

Set power status of sensors.

SS_SendSensorSetPower

sensor_command_power_t

5.11.2.3. Sequence
Diagram
図 78. Sensor Manager Sequence
MemHandleについては、Memory Manager Library を参照してください。

5.11.3. Logical Sensors

5.11.3.1. General

"Logical Sensor"とは、各種の物理センサから得られたセンサデータを何らかの信号処理アルゴリズムなどに基づき、高機能なセンサデータを作成するための"Sensor Client"で、ソフトウェアモジュールで構成されています。
実際のアルゴリズムの実装アロケーションは、下記のいくつかの方法があります。

  • NuttX上のタスクとして実装する。

  • asmpフレームワークを使って、DSP上に実装する。

  • 各社ベンダが提供した暗号化されたDSPを用いて実装する。

5.11.3.1.1. A logical sensor task on NuttX.

NuttX上のモジュール、もしくはタスクとして実装をします。
特に、重くない処理であったり、頻度の多くない処理の場合、このように実装することで、メモリ、CPUリソースなどを消費せず実装が可能です。

表 34. Samples of Logical Sensors on NuttX
Contents Sample provider

Barometer

From sensor vender

TAP Gesture (Tapping Detector)

From SDK

5.11.3.1.2. A logical sensor on DSP by asmp.

ユーザが独自に"Logical Sensor"のアルゴリズムを作成し、その処理をDSP側にオフロードする必要があるような場合(例えば、処理が重いなど)、ASMPフレームワークを用いて、DSP側に実装することが可能です。
このような場合、"Logical Sensor"をスーパーバイザタスクで実装し、そのスーパーバイザタスクからDSP上のWorkerタスクへ処理要求を送って処理をさせることで、マルチコア処理での"Logical Sensor"を実現できます。

表 35. Samples of Logical Sensors on DSP
Contents Sample provider

""

From SDK

SuperVisor and Worker
図 79. SuperVisor and Worker
ASMPフレームワークについては、 ASMP Framework を参照してください。
A logical sensor on DSP with encryption.

各ソリューションベンダは、さまざまな logical sensor のアルゴリズムを提供します。その場合、各ベンダは、コードを開示せず、それぞれの契約等に基づき、機能を提供することが可能です。
このケースの場合は、ASMPフレームワーク上に、build 及び encryption 済のバイナリをロードすることで、実現が可能です。Encrypted DSPは、各ベンダから提供されます。

表 36. Samples of Logical Sensors on DSP with encryption
Contents Sample provider

AESM (Activity Engine and Step Meter)

From SDK

SuperVisor and Encrypted Worker
図 80. SuperVisor and Encrypted Worker

5.11.4. Logical Sensor API

各 Logical sensorは次のAPIを提供します。

表 37. Logical Sensor API
APIs Description

Create

Create a class instance to communicate with workers.

Open

Load library and boot up as worker task.

Write

Send data to worker task.

Close

Destroy worker task.

これらの要求は、以下のイベントとして定義され、DSP上のWorkerタスクとの送受信に使用されます。
詳細については、各スーパーバイザを参照してください。

Event Description

Init

Initialization event.

Exec

Execution event.

Flush

Terminal event.

5.11.5. Details of each Logical Sensors

5.11.6. Step Counter

"Step Counter" の構成図を以下に示します。

Configuration diagram of Step Counter
図 81. Configuration diagram of Step Counter
5.11.6.1. Supervisor

スーパーバイザは"Logical Sensor"のためのフレームワークです。 スーパーバイザのDSP上のWorkerを制御するためのいくつかのAPIを提供します。

5.11.6.1.1. APIs

"Step Counter"は以下の5つのAPIを提供します。

表 38. Step Counter API
APIs Description Corresponding API

Create

Create StepCounterClass instance.

StepCounterCreate

Open

Load StepCounter library and boot up as worker task.

StepCounterOpen

Write

Send data to StepCounter worker task.

StepCounterWrite

Close

Destory StepCounter worker task.

StepCounterClose

Set

Set setting to StepCounter library .

StepCounterSet

5.11.6.1.2. Data format for Step Counter

"Step Counter"には、以下のように指定されたフォーマットで"Accelerometer"のデータが必要です。
これらのデータをWriteのAPIでWorkerに送信します。

Data format of Accelerometer
図 82. Data format for Step Counter
5.11.6.1.3. Result of sensing

"Step Counter”は1秒ごとに以下の歩数計情報を出力します。 これらの情報は、StepCounterStepInfo に格納されます。

表 39. Step Counter result
情報 単位 備考

テンポ

Hz

1~3Hzの値をとります。停止状態時も1Hz以上の値となります。

歩幅

cm

歩行と走行でそれぞれ固定値となります。

速度

m/s

累積移動距離

m

歩数

-

行動認識

-

停止/歩行/走行状態を示します。

5.11.6.2. How to use
5.11.6.2.1. Preparation

"Sensor Manager"と呼ばれる複数の"Sensor Client"を制御するために設計されたフレームワークで、 "Step Counter"を制御します。

そのため、"Step Counter"を制御するには、"Sensor Manager"を事前に有効にする必要があります。

Activate Sensor Manager

"Sensor Manager" を有効にするには、SS_ActivateSensorSubSystem(MsgQueId, api_response_callback_t) を呼ぶ必要があります。
MsgQueId は、Message Library Configuration で定義された MsgQueID を指定する必要があります。
api_response_callback_t は、非同期の通知を行うためのコールバック関数を指定します。
NULLを指定した場合は通知は行われません。

static void sensor_manager_api_response(unsigned int code,
                                        unsigned int ercd,
                                        unsigned int self)
{
  ...
}

SS_ActivateSensorSubSystem(MSGQ_SEN_MGR, sensor_manager_api_response);
Register to Sensor Manager

"Sensor Manager"の有効後、"Sensor Manager"に"Step Counter"がSubscribeを要求する"Sensor Client"として、"Accelerometer"を登録します。
この際、Subscribeの処理として、StepCounterWriteを呼び出すコールバック関数を指定します。

また、"Application"が"Step Counter"のセンシング結果を知るために、 "Application"がSubscribeを要求する"Sensor Client"として、"Step Counter"を登録します。
この際、Subscribeの処理を行うコールバック関数を指定します。

bool step_counter_receive_data(sensor_command_data_mh_t& data)
{
  StepCounterWrite(sp_step_counter_ins, &data);

  return true;
}

bool step_counter_recieve_result(sensor_command_data_mh_t& data)
{
  bool ret = true;
  FAR SensorCmdStepCounter *result_data =
    reinterpret_cast<SensorCmdStepCounter *>(data.mh.getVa());
  if (SensorOK == result_data->result.exec_result)
    {
      if (result_data->exec_cmd.cmd_type ==
            STEP_COUNTER_CMD_UPDATE_ACCELERATION)
        {
           ...
        }
    }
    return ret;
}

sensor_command_register_t reg;

reg.header.code   = ResisterClient;
reg.self          = stepcounterID;
reg.subscriptions = (0x01 << accelID);
reg.callback      = NULL;
reg.callback_mh   = &step_counter_receive_data;

SS_SendSensorResister(&reg);

reg.header.code   = ResisterClient;
reg.self          = app0ID;
reg.subscriptions = (0x01 << stepcounterID);
reg.callback      = NULL;
reg.callback_mh   = &step_counter_recieve_result;
SS_SendSensorResister(&reg);
Diagram
図 83. Register sequence
5.11.6.2.2. Create and Open

事前準備の完了後、"Step Counter"の生成、有効化を行います。

"Step Counter"の生成には、StepCounterCreate(PoolId) を呼ぶ必要があります。
PoolIdには、"Memory Manager Configuration"で定義された IDを指定する必要があります。
戻り値として、"Step Counter"のインスタンスへのポインタが返ります。

FAR StepCounterClass *step_counter_instance;
step_counter_instance = StepCounterCreate(SENSOR_DSP_CMD_BUF_POOL);

"Step Counter"の有効化には、StepCounterOpen(FAR StepCounterClass*) を呼ぶ必要があります。
StepCounterClass*には、StepCounterCreateの戻り値である、"Step Counter"のインスタンスへのポインタを指定する必要があります。

StepCounterOpen(step_counter_instance);
Diagram
図 84. Create and Open sequence
5.11.6.2.3. Set stride

センシングする際の歩幅の初期値は、walking状態で60cm、running状態で80cmです。

この初期値を変更する場合は、StepCounterSet(FAR StepCounterClass*, StepCounterSetting*) を呼ぶ必要があります。
StepCounterClass*には、StepCounterCreateの戻り値である、"Step Counter"のインスタンスへのポインタを指定する必要があります。
StepCounterSetting*には、walking状態とrunning状態のそれぞれの歩幅を step_lengthに単位cmで設定して下さい。歩幅最大値は250cmです。
step_modeは、"STEP_COUNTER_MODE_FIXED_LENGTH"固定です。

StepCounterSetting set;
set.walking.step_length = 70; /* Set stride to 70 cm */
set.walking.step_mode   = STEP_COUNTER_MODE_FIXED_LENGTH;
set.running.step_length = 90; /* Set stride to 90 cm */
set.running.step_mode   = STEP_COUNTER_MODE_FIXED_LENGTH;
StepCounterSet(step_counter_instance, &set);
Diagram
図 85. Set sequence
Start Sensing

"Step Counter"は"Accelerometer"のSubscribeを契機に呼び出される StepCounterWriteで、DSP上のWorkerにデータを送信し、センシング処理を行います。

この際のシーケンスを以下に示します。

Diagram
図 86. Sensing sequence of Accelerometer publish
5.11.6.2.4. Close

"Step Counter"の無効化には、StepCounterClose(FAR StepCounterClass*) を呼ぶ必要があります。
StepCounterClass*には、StepCounterCreateの戻り値である、"Step Counter"のインスタンスへのポインタを指定する必要があります。

StepCounterClose(step_counter_instance);
Diagram
図 87. Close sequence
5.11.6.2.5. Release from Sensor Manager

"Step Counter"の無効後に、"Sensor Manager"への登録を解除します。 この際、"Step Counter"にSubscribeする"Sensor Client"の動作を事前に停止させてください。

sensor_command_register_t reg;

rel.header.code = ReleaseClient;
rel.self        = stepcounterID;
SS_SendSensorRelease(&rel);
5.11.6.3. Build Configurations

"Step Counter"の機能を使用するためには、

cd sdk
tools/config.py -m

でconfigurationのmenuを開き、以下のoptionを設定する必要があります。

Select options in below:

[CXD56xx Configuration]
  [I2C0] <= Y
  [Sensor Control Unit] <= Y
[Memory manager] <= Y
  [Memory Utilities]
    [Memory manager] <= Y
    [Message] <= Y
[Drivers]
  [Sensor Drivers] <= Y
    [Bosch BMI160 Sensor support] <= Y
      [SCU Sequencer] <= Y
[Sensing]
  [Sensing manager] <= Y
  [Step counter] <= Y
[ASMP] <= Y
5.11.6.4. Worker

Workerは他のCore上で動作し、Supervisorから送信されたセンサデータを分析します。
そして、要求されたイベントの処理結果(ステップ数、状態など)を返します。

"Step Counter"のWorkerは、分析のために以下に示すデータを必要とします。

・ Accelerometerデータ(32Hz、32サンプル/1秒)
5.11.6.4.1. APIs

"Step Counter"のWorkerは以下の3つのAPIを提供します。

表 40. Step Counter Worker API
APIs Description

Init

Initialize for AESM(Activity Engine and Step Meter) library.

Exec

Execute calculate on sensor data on AESM library.

Flush

End execute process of AESM library.

これらのAPIは、Supervisorから送信されたパケットに含まれるイベントタイプやコマンドタイプによって、 呼び出されます。

関係は下記の通りです。

Init
SensorDspCmd dsp_cmd;
dsp_cmd.header.sensor_type     = StepCounter;
dsp_cmd.header.event_type      = InitEvent;
Exec
SensorDspCmd dsp_cmd;
dsp_cmd.header.sensor_type     = StepCounter;
dsp_cmd.header.event_type      = ExecEvent;
dsp_cmd.exec_aesm_cmd.cmd_type = AESM_CMD_UPDATE_ACCELERATION;
Flush
SensorDspCmd dsp_cmd;
dsp_cmd.header.sensor_type     = StepCounter;
dsp_cmd.header.event_type      = FlushEvent;
5.11.6.5. Step Counter Example

"Step Counter"のsample applicationとして、"Step Counter" exampleがあります。ここでは、その使い方などを説明します。

5.11.6.5.1. Preparation
Build Configurations (kconfig)

"Step Counter"のsample applicationを使うには、configurationのoptionを以下の設定にしてください。

Select options in below:

[Examples]
  [Step counter sensor example] <= Y

または、"Step Counter"のdefault configurationを使用して下さい。

./tools/config.py examples/step_counter
Memory and Message Utility Configurations and Layout

メモリ管理ライブラリ(Memory Manager)とタスク間通信ライブラリ(Message Library)の設定は、以下のように行ってください。

Memory Manager (Intelligent Fix Pool) Configuration

"Step Counter"を使用する際に必要となるMemoryLayout(pool)の定義を行う必要があります。
定義はMemoaryLayout定義ファイルで行い、ツールでコードに組み込むヘッダファイルを生成することが出来ます。

"Step Counter"のsample applicationでは下記のように行います。

cd examples/step_counter/config
python3 mem_layout.conf

"mem_layout.h", "fixed_fence.h", "pool_layout.h" ファイルが生成されます。
"mem_layout.h"ファイルは、後述する msgq_layout ツールの実行時に参照されます。

MemoaryLayout定義ファイル(mem_layout.conf)の記述内容は下記の通りです。

FixedAreas
FixedAreas
 # name,                  device,     align,        size,         fence
  ["SENSOR_WORK_AREA",    "SHM_SRAM", U_STD_ALIGN,  0x0001e000,   False],
  ["MSG_QUE_AREA",        "SHM_SRAM", U_STD_ALIGN,  0x00001000,   False],
  ["MEMMGR_WORK_AREA",    "SHM_SRAM", U_STD_ALIGN,  0x00000200,   False],
  ["MEMMGR_DATA_AREA",    "SHM_SRAM", U_STD_ALIGN,  0x00000100,   False],

各パラメータの説明は以下の通りです。

パラメータ 説明

name

領域名(英大文字で始まり、"_AREA"で終わる名称。英大文字, 数字, _が使用可能)

device

領域を確保するMemoryDevicesのデバイス名

align

領域の開始アライメント。0を除くMinAlign(=4)の倍数を指定する

size

領域のサイズ。0を除く4の倍数の値を指定する

fence

フェンスの有効・無効を指定する(この項目は、UseFenceがfalseの場合は無視される)

各nameの用途は以下の通りです。

SENSOR_WORK_AREA

センサフュージョンが利用する

MSG_QUE_AREA

MessageQueueが利用する(固定名)。msgq_id.hの(MSGQ_END_DRM - MSGQ_TOP_DRAM)のサイズを超えないこと。

MEMMGR_WORK_AREA

Memory Managerが利用する作業領域(固定名, 固定サイズ)

MEMMGR_DATA_AREA

Memery Managerが利用するデータ領域(固定名, 固定サイズ)

各nameの合計のサイズがmpshm_init(), mpshm_remap()で確保するシェアメモリのサイズを超えないようにしてください。

PoolAreas
PoolAreas
 # name,                     area,               align,       pool-size,                   seg,                        fence
 ["SENSOR_DSP_CMD_BUF_POOL", "SENSOR_WORK_AREA", U_STD_ALIGN, U_SENSOR_DSP_CMD_POOL_SIZE,  U_SENSOR_DSP_CMD_SEG_NUM,   False],
 ["ACCEL_DATA_BUF_POOL",     "SENSOR_WORK_AREA", U_STD_ALIGN, U_ACCEL_DATA_BUF_POOL_SIZE,  U_ACCEL_DATA_BUF_SEG_NUM,   False],
 ["GNSS_DATA_BUF_POOL",      "SENSOR_WORK_AREA", U_STD_ALIGN, U_GNSS_DATA_BUF_POOL_SIZE,   U_GNSS_DATA_BUF_SEG_NUM,    False],

各パラメータの説明は以下の通りです。

パラメータ 説明

name

プール名(英大文字で始まり、"_POOL"で終わる名称。英大文字, 数字, _が使用可能)

area

プール領域として使用するFixedAreaの領域名。領域はRAMに配置されていること

align

プールの開始アライメント。0を除くMinAlign(=4)の倍数を指定する

pool-size

プールのサイズ。0を除く4の倍数の値。Basicプールでは、セグメントサイズ * セグメント数

seg

セグメント数。1以上、255以下の値を指定する

fence

フェンスの有効・無効を指定する。この項目は、UseFenceがfalseの場合は無視される

各nameの用途は以下の通りです。

SENSOR_DSP_CMD_BUF_POOL

Workerとの送受信用バッファ領域

ACCEL_DATA_BUF_POOL

Accelerometerデータのバッファ領域

それぞれの定義の詳細については、 examples/step_counter/config/mem_layout.confを参照してください。
設定が変わった場合は、ツールを使って新しいヘッダーファイルを生成してください。
Message Library Configuration

"Step Counter"を使用する際に必要となる"MessageQueue"の定義を行う必要があります。 定義はMessageQueueLayout定義ファイルで行い、ツールでコードに組み込むヘッダファイルを生成することが出来ます。

"Step Counter"のsample applicationでは下記のように行います。

cd examples/step_counter/config
python3 msgq_layout.conf

"msgq_id.h", "msgq_pool.h" ファイルが生成されます。
mem_layout.conf で生成されたファイルを含めて全てのヘッダファイルを include 以下にコピーします。

cd examples/step_counter/config
mv *.h ../include

MessageQueueLayout定義ファイル(msgq_layout.conf)の記述内容は下記の通りです。

MsgQuePool
 # ID,             n_size  n_num    h_size  h_nums
 ["MSGQ_SEN_MGR",  40,     8,       0,      0],

各パラメータの説明は以下の通りです。

パラメータ 説明

ID

メッセージキュープールIDの名称を、"MSGQ_"で始まる文字列で指定。

n_size

通常優先度キューの各要素のバイト数(8以上512以下)。固定ヘッダ長(8byte) + パラメタ長を4の倍数で指定する。

n_num

通常優先度キューの要素数(1以上16384以下)。

h_size

高優先度キューの各要素のバイト数(0または、8以上512以下)。未使用時は0を指定すること。

h_num

高優先度キューの要素数(0または、1以上16384以下)。未使用時は0を指定すること。

n_sizeは最適値となっているため、変更は行わないでください。

n_numも変更の必要はありませんが、他のapplicationでStep Counterを使う場合は、負荷を考慮して値を増やす必要が出てくる可能性があります。

h_size, h_numsはStep Counterを優先的に処理したい場合に利用して下さい。

それぞれの定義の詳細については、 examples/step_counter/config/msgq_layout.confを参照してください。
設定が変わった場合は、ツールを使って新しいヘッダーファイルを生成してください。

5.12. JPEG Decoder

5.12.1. 概要

IJGが開発したlibjpegライブラリをベースにしたJPEGデコード機能を提供します。

概ねオリジナルlibjpegライブラリのAPI仕様に準じておりますが、Spresense向けにカスタマイズしている点がありますので、 このドキュメントで、カスタマイズ内容について詳述します。

以下の説明において、「libjpegインスタンス」とは、libjpeg利用アプリケーションが用意しなければいけないstruct jpeg_decompress_struct型変数を指します。

5.12.2. Spresense向けカスタマイズ内容

出力フォーマット(色空間)

オリジナルlibjpegでサポートしているフォーマットはいずれも24bit/pixel以上ですが、 Spresenseでは16bit/pixelのCb/Y/Cr/Y(YUV4:2:2)フォーマットをサポートすることで、より少ないメモリでデコードできるようにしています。
下記defineがSpresenseで有効な色空間の定義です。 このパラメータをlibjpegインスタンスのメンバ out_color_space に設定してjpeg_start_decompress()を実行することで、 任意のサポート色空間でデコードすることが可能になります。

表 41. 出力フォーマット(色空間)
define名 意味 bits/pixel Spresense オリジナル

JCS_CbYCrY

Cb/Y/Cr/Y(YUV4:2:2)

16

×

JCS_YCbCr

Y/Cb/Cr(YUV)

24

×

JCS_RGB

sRGB

24

×

JCS_CMYK

C/M/Y/K

32

×

JCS_YCCK

Y/Cb/Cr/K

32

×

デコード結果読み出し単位

オリジナルlibjpegでは行単位の読み出しをサポートしていますが、 それに加えてSpresenseでは、より小さなMCU単位での読み出しもサポートしています。

表 42. デコード結果読み出しAPI
API名 用途 Spresense オリジナル

jpeg_read_scanlines

行単位での読み出し

jpeg_read_mcus

MCU単位での読み出し

×

MCUは、JPEGの圧縮単位ブロックで、基本は8×8pixelとなります。 JPEGエンコード時のパラメータ(JPEGヘッダに設定されている)およびデコード時のパラメータ(アプリケーションが設定する)によってサイズが変化します。 アプリケーションとしては、jpeg_start_decompress()実行後にlibjpegインスタンスの情報から以下のように1MCUのサイズを知ることができます。

  • 1MCUの幅 = output_width / MCUs_per_row (トータルの幅 / 幅 方向の総MCU数)

  • 1MCUの高さ = output_height / MCU_rows_in_scan(トータルの高さ / 高さ方向の総MCU数)

MCU単位の場合、1単位あたりのpixel数(データサイズ)が画像サイズに依存しないので、この2種類の単位の差は下記の例のように画像サイズが大きいほど顕著になります。

表 43. 単位pixel数の例:Spresenseカメラで撮影したJPEGファイルを等倍でデコードする場合
単位 QVGAの場合 HDの場合 5Mの場合

行単位

320

1280

2560

MCU単位

128

128

128

JPEGデータ入力方法

オリジナルlibjpegでは、ファイルポインタもしくはバッファでJPEGデータを入力できましたが、 Spresenseでは、それらに加えてファイルディスクリプタにも対応します。

表 44. JPEGデータ入力API
API名 意味 Spresense オリジナル

jpeg_stdio_src

ファイルポインタ

jpeg_fd_src

ファイルディスクリプタ

×

jpeg_mem_src

バッファ

ここでいうファイルディスクリプタとは、read()関数でJPEGデータの読み出しができるファイルディスクリプタであることが条件です。
例えば、通常ファイルをopen()したファイルディスクリプタ以外にも、socket()で作成したソケットディスクリプタも対応可能になります。 (もちろん、ソケットディスクリプタの場合、通信相手からJPEGデータがそのまま送られてくる必要があります。)

エラーハンドリング

オリジナルlibjpegもSpresenseもデフォルトではエラー発生時はexit()によってlibjpeg API実行タスクが終了します。 タスクを終了させない方法として、オリジナルlibjpegでは「setjmp/longjmp」を用いるexampleを提示していますが、 Spresense(NuttX)はsetjmp/longjmpをサポートしていないため、この手法は使えません。 今後、setjmp/longjmp以外の方法でエラーハンドリングできるようサポートする予定です。

libjpegのエラーハンドリングは、「エラーハンドラがreturnしない」前提で実装されており、 仮にエラーハンドラがreturnした場合の動作保証はしておりません。
表 45. エラーハンドラの終了手段
エラーハンドラの
終了手段
意味 Spresense オリジナル

exit

libjpeg API実行タスクの終了

longjmp

setjmpで保存したスタックコンテキストへの
nonlocal jump

×
(NuttX未サポート)


(実装環境依存)

return

エラー検出関数へのreturn

×

×

「エラー」にはプログラム異常によるものの他に、外部要因によるものあります。代表的なエラーについては標準エラー出力への出力参照。

5.12.3. 状態遷移

Diagram

5.12.4. 動作シーケンス

Diagram
図 88. libjpeg 動作シーケンス

5.12.5. 標準エラー出力への出力

libjpegライブラリは、エラー もしくはWarningを検出した場合に標準エラー出力にメッセージを英文で出力します。 メッセージの意味や出力理由については、オリジナルlibjpegと変わりありません。

ここでは、よく発生するメッセージについて説明します。

表 46. libjpegライブラリによる標準エラー出力メッセージ
出力メッセージ エラー/Warning 出力契機

Improper call to JPEG library in state %d

エラー

API実行順が状態遷移図に従っていない

Unsupported color conversion request

エラー

サポートしていない出力フォーマットを指定した

Not a JPEG file: starts with 0x%02x 0x%02x

エラー

0xFF D8から始まっていない

Corrupt JPEG data: bad Huffman code

Warning

ハフマン符号のデコードエラー

Premature end of JPEG file

Warning

入力されたJPEGデータがEOIマーカーが出てこないままEOFに到達した場合に出力されます。

5.12.6. サンプルコード

このサンプルコードは、オリジナルlibjpegライブラリに添付されているexample.cのデコードプログラムをベースにして、 Spresense版libjpegの以下の特徴を盛り込んだものになります。

  • YUV4:2:2フォーマットで出力する

  • JPEGデータの入力にファイルディスクリプタを利用できる

  • MCU単位のデコードができる


5.13. LTE

5.13.1. 概要

LTEライブラリはLTEネットワークを介してインターネットに接続することができます。
LTEライブラリはモデムを操作するAPIとソケット通信に必要なAPIを提供します。

5.13.2. 用語・略語

表 47. LTEライブラリに関する用語・略語
用語 説明

PDN

Packet Data Network
モデムとLTEネットワーク間でパケットを転送するための経路

APN

Access Point Name
LTEネットワークへ接続する際に必要となる設定

IMS

IP Multimedia Subsystem
Internet Protocol (IP) マルチメディアサービスのためのアーキテクチャ的フレームワーク。
SMSや通話をIPベースで実現するための規格

IMSI

International Mobile Subscriber Identity
SIMカードに記録される国際的な加入者識別番号

IMEI

International Mobile Equipment Identifier
データ通信端末に付与される国際的な識別番号

eDRX

extended Discontinuous Reception
LTEネットワークから送信されてくる各種信号の受信間隔を長くすることで消費電力を低減する通信技術

PSM

Power Saving Mode
LTEネットワークと一定期間全く通信しないことで消費電力を低減する通信技術

CE

Coverage Enhancement
弱電界の通信でデータが壊れていても、データの再送を試みて、元々のデータを最終的に復元する通信技術

RAT

Radio Access Technology
LTE-M (LTE Cat-M1)、NB-IoTなどの無線アクセス技術

5.13.3. モデムの通信プロトコルとそのバージョンについて

モデムの通信プロトコルとは

SpresenseLTE拡張ボードのLTEモジュールはファームウェアバージョンによって、SPIのコマンド仕様が2種類存在します。SPIコマンドの仕様のバージョンは、Protocol Version x = PVxという形で表現されており、SpresenseLTE拡張ボードではPV1とPV4が存在します。
Spresense SDKのデフォルトのコンフィグレーションではPV1/PV4の両方をサポートしています。メモリ節約などの目的で、どちらかのみを有効にすることも可能です。その場合、以下のKconfigの設定値を変更してください。

  • CONFIG_MODEM_ALT1250_DISABLE_PV1

  • CONFIG_MODEM_ALT1250_DISABLE_PV4

ただし、PV1とPV4は互換性が無く、SpresenseLTE拡張ボードとの組み合わせを誤ると動作しなくなってしまいます。(再度正しい組み合わせのコンフィグレーションでアプリケーションを書き直せば動作します。)
上記Kconfigをデフォルトから変更する際は、まずお使いのボードがどちらのPVに対応したものかを確認してから変更してください。

SpresenseLTE拡張ボードの種類について

SpresenseLTE拡張ボードの種類は、以下の4つがあります。

表 48. SpresenseLTE拡張ボードの種類
SpresenseLTE拡張ボード 説明

CXD5602PWBLM1J

日本向け(初期版)

CXD5602PWBLM1JUL

日本向け

CXD5602PWBLM1E

ヨーロッパ向け

CXD5602PWBLM1NA

北米向け

モデムの通信プロトコルとSpresenseLTE拡張ボード製品の関係について

SpresenseLTE拡張ボードの種類とモデムの通信プロトコルの関係は以下の通りです。

表 49. SpresenseLTE拡張ボードの種類とSpresenseLTE拡張ボード製品の関係
SpresenseLTE拡張ボード モデムの通信プロトコルバージョン

CXD5602PWBLM1J

PV1

CXD5602PWBLM1JUL

PV4

CXD5602PWBLM1E

PV4

CXD5602PWBLM1NA

PV4

LTEモジュールのファームウェアバージョンの確認方法

以下のドキュメントを参考にlte_sysctlコマンドを実行することでバージョンの確認が出来ます。
LTEのネットワークデーモンを使ってネットワーク接続を行う
lte_sysctl startコマンドを実行後 lte_sysctl statコマンドを実行します。

nsh> lte_sysctl start
nsh> lte_sysctl stat
Daemon state : running
APN
  Name: internet
  IP type: IPv4
  Authentication: None
  Username:
  Password:
RAT: CAT-M1
VER: RK_02_01_02_10_108_54

上記の例ではLTEモジュールのファームウェアが RK_02_01_02_10_108_54 であることを示しています。

LTEモジュールのファームウェアバージョンとPVの関係
表 50. LTEモジュールのファームウェアバージョンとPVの関係
LTEモジュールのファームウェアバージョン モデムの通信プロトコルバージョン

RK_02_01_01_10_41_15

PV1

RK_02_01_02_10_108_54

PV1

RK_03_00_00_00_04121_001

PV4

RK_03_00_00_22_13151_002

PV4

5.13.4. LTEライブラリの状態

LTEライブラリはAPI呼出し可否を判断するため内部で状態を管理しています。
LTE APIが管理する状態について、表 51 に示します。

表 51. LTEライブラリの状態
状態 説明

Uninitilized

LTE APIが全く動作していない状態

Initilized

LTE APIの使用準備ができた状態

Power on ongoing

モデムが電源ON中の状態

Power on

モデムの電源ONが完了し、通信状態が機内モードになっている状態

Radio on

LTEネットワークの探索を実施している状態

PDN connected

PDNの構築が完了し、モデムにIPアドレスが付与されている状態

Reset ongoing

モデムのリセットから復帰中の状態

状態遷移

LTEライブラリの状態遷移を、図 89 に示します。

Diagram
図 89. LTEライブラリの状態遷移

5.13.5. APIについて

LTEライブラリは同期型・非同期型の2種類を用意しています。 APIの詳細は LTE API リファレンスを参照してください。

同期型API・非同期型APIの特徴を解説します。

同期型API
  • 処理結果を 戻り値 で通知します。

  • モデムで処理が 完了 するまでAPIを呼出したタスクをブロッキングします。

  • 戻り値が -EPROTO の場合、lte_get_errinfo()関数でエラーコードを取得することができます。

  • 属性がOUTの引数は、ユーザが領域を割り当てる必要があります。

非同期型API
  • 処理結果を コールバック で通知します。コールバックはタスクコンテキストで呼出します。

  • モデムに処理を 要求 するまで、APIを呼出したタスクをブロッキングします。

  • 処理の要求結果を戻り値で通知します。

  • コールバックは各APIの引数で登録します。 処理結果を通知すると登録を解除します。

  • コールバックで処理結果が通知されるまで、同じAPIを呼出すことができません。
    ( -EINPROGRESS が戻り値で通知されます。)

  • コールバックがエラー(LTE_RESULT_ERROR)を通知した場合、lte_get_errinfo()関数でエラーコードを取得することができます。

LTEライブラリがコールバックを呼び出すために用意しているタスクコンテキストは一つです。
コールバック内で別のコールバックを待つことができません。

API呼出し可否について

LTEライブラリの各状態における同期型APIの呼び出し可否について示します。

凡例:

〇 : 同期型API呼び出し可

× : 同期型API呼出し不可。処理結果(戻り値)がエラーとなる。

表 52. LTEライブラリ API呼び出し可否

API

LTEライブラリの状態

Uninitilized

Initilized

Power on ongoing

Power on

Radio on

PDN connected

Reset ongoing

lte_initialize

× ※1

× ※1

× ※1

× ※1

× ※1

× ※1

lte_finalize

× ※1

lte_set_report_restart

× ※4

lte_power_on

× ※4

× ※3

× ※1

× ※1

× ※1

× ※3

lte_power_off

× ※4

× ※4

lte_set_report_netinfo

× ※2

× ※2

× ※2

× ※2

lte_set_report_simstat

× ※2

× ※2

× ※2

× ※2

lte_set_report_localtime

× ※2

× ※2

× ※2

× ※2

lte_set_report_quality

× ※2

× ※2

× ※2

× ※2

lte_set_report_cellinfo

× ※2

× ※2

× ※2

× ※2

lte_get_errinfo

× ※4

lte_activate_pdn_cancel

× ※2

× ※2

× ※2

× ※2

lte_radio_on_sync

× ※2

× ※2

× ※2

× ※5

× ※5

× ※2

lte_radio_off_sync

× ※2

× ※2

× ※2

× ※5

× ※2

lte_activate_pdn_sync

× ※2

× ※2

× ※2

× ※4

× ※2

lte_deactivate_pdn_sync

× ※2

× ※2

× ※2

× ※6

× ※6

× ※2

lte_get_netinfo_sync

× ※2

× ※2

× ※2

× ※2

lte_get_imscap_sync

× ※2

× ※2

× ※2

× ※2

lte_get_version_sync

× ※2

× ※2

× ※2

× ※2

lte_get_phoneno_sync

× ※2

× ※2

× ※2

× ※2

lte_get_imsi_sync

× ※2

× ※2

× ※2

× ※2

lte_get_imei_sync

× ※2

× ※2

× ※2

× ※2

lte_get_pinset_sync

× ※2

× ※2

× ※2

× ※2

lte_set_pinenable_sync

× ※2

× ※2

× ※2

× ※2

lte_change_pin_sync

× ※2

× ※2

× ※2

〇/× ※7

〇/× ※7

〇/× ※7

× ※2

lte_enter_pin_sync

× ※2

× ※2

× ※2

〇/× ※8

〇/× ※8

〇/× ※8

× ※2

lte_get_localtime_sync

× ※2

× ※2

× ※2

× ※2

lte_get_operator_sync

× ※2

× ※2

× ※2

× ※2

lte_get_edrx_sync

× ※2

× ※2

× ※2

× ※2

lte_set_edrx_sync

× ※2

× ※2

× ※2

× ※2

lte_get_psm_sync

× ※2

× ※2

× ※2

× ※2

lte_set_psm_sync

× ※2

× ※2

× ※2

× ※2

lte_get_ce_sync

× ※2

× ※2

× ※2

× ※2

lte_set_ce_sync

× ※2

× ※2

× ※2

× ※2

lte_get_siminfo_sync

× ※2

× ※2

× ※2

× ※2

lte_get_current_edrx_sync

× ※2

× ※2

× ※2

× ※2

lte_get_current_psm_sync

× ※2

× ※2

× ※2

× ※2

lte_get_quality_sync

× ※2

× ※2

× ※2

× ※2

lte_get_cellinfo_sync

× ※2

× ※2

× ※2

× ※2

lte_get_rat_sync

× ※2

× ※2

× ※2

× ※2

lte_set_rat_sync

× ※2

× ※2

× ※2

× ※2

lte_get_ratinfo_sync

× ※2

× ※2

× ※2

× ※2

※1:戻り値が -EALREADY
※2:戻り値が -ENETDOWN
※3:戻り値が -EINPROGRESS
※4:戻り値が -EPROTO 、エラーコードが -EOPNOTSUPP
※5:戻り値が -EPROTO 、エラーコードが -EALREADY
※6:戻り値が -EPROTO 、エラーコードが -EINVAL (session_idが不一致)
※7:PIN無効時⇒×、PIN有効時⇒○
※8:PIN状態がPIN/PUK解除待ちの場合⇒○、それ以外の場合⇒×

API呼出しでモデムの不揮発メモリに保存される設定値

同期型APIを呼び出して、モデムの不揮発メモリに保存される設定値を示します。

表 53. モデムの不揮発メモリに保存される設定値
API パラメータ 説明

lte_set_edrx_sync

enable

eDRX機能の可否。 有効無効 を選択。

edrx_cycle

eDRX動作の動作周期。

lte_set_psm_sync

enable

PSM機能の可否。 有効無効 を選択。

req_active_time

T3324 タイマの値。

ext_periodic_tau_time

T3412 タイマの値。

lte_set_rat_sync

rat

モデムが使用するRAT。 LTE-M (LTE Cat-M1)NB-IoT を選択。 ※1

※1:第2パラメータ persistent が 有効 の場合、モデムの不揮発メモリに保存されます。

5.13.6. モデムを操作する

モデムを操作するLTEライブラリの使用方法を同期型APIを使用した場合のシーケンスを例に解説します。

5.13.6.1. 電源をONにする

モデムの電源をONにするシーケンスを、図 90 に示します。

Diagram
図 90. モデムの電源ONシーケンス
  1. LTEライブラリの初期化を行います。

  2. モデムの電源ON処理が完了した場合、もしくはモデムの自発的リセットから復帰した場合に、コールバック通知を受け取る設定を行います。

  3. モデムを電源ONします。

  4. モデムの電源ON処理が完了すると、restart_callback()通知が発生します。通知理由は ユーザ主導の起動 になります。

5.13.6.2. モデムの情報を取得する

モデムの情報を取得する関数について、図 91 に示します。

Diagram
図 91. モデムの情報を取得するシーケンス
5.13.6.3. モデムをLTEネットワークに登録する

モデムをLTEネットワークに登録するシーケンスを、図 92 に示します。

Diagram
図 92. LTEネットワーク登録シーケンス
  1. モデムが管理するLTEネットワーク情報が変更になった場合、コールバック通知を受け取る設定を行います。

  2. モデムの無線をONにします。

  3. モデムとLTEネットワーク間でパケットを転送するための通信経路の構築を開始します。
    通信経路の構築にはlte_activate_pdn_sync()関数の引数でAPN(Access Point Name)を指定する必要があります。
    APNはLTEネットワークのデータ通信で必要になる接続先を指定します。 APNのパラメータについて示します。

    表 54. APNパラメータ
    パラメータ 説明

    apn

    アクセスポイント名。

    ip_type

    APNプロトコル。 IPv4IPv6IPv4v6 から選択。

    auth_type

    認証タイプ。 PAPCHAPなし から選択。

    apn_type

    APNタイプ。 UNKNOWNDEFAULTMMSSUPLDUNHIPRIIMSCBSIAEMERGENCY、を組み合わせて選択。

    userName

    ユーザ名。

    password

    パスワード。

    APNのパラメータはご使用のSIMに合わせて、設定してください。
    現在サポートしている認証タイプは、IA | DEFAULT のみです。 他の認証タイプの組み合わせを設定した場合、lte_activate_pdn_sync()関数がエラー(-EINVAL)になります。

  4. モデムの登録に成功した場合、ネットワーク状態 LTE_NETSTAT_REG_HOME がnetinfo_callback()で通知され、lte_activate_pdn_sync()関数の戻り値が 0 で返ります。

  5. LTEネットワークからモデムがRejectされた場合、ネットワーク状態 LTE_NETSTAT_REG_DENIED 、エラー種別が LTE_NETERR_REJECT がnetinfo_callback()で通知されます。
    netinfo_callback()内で、lte_activate_pdn_cancel()関数を呼び出し、モデムの登録処理をキャンセルしてください。 モデムの登録処理がキャンセルされると、lte_activate_pdn_sync()関数の戻り値が -ECANCEL で返ります。

    • lte_activate_pdn_cancel()関数を呼び出さない場合、lte_activate_pdn_sync()関数の戻り値が返りません。

    • LTEネットワークからモデムがRejectされる場合、ご使用のSIMに合わせたAPNを正しく指定しているか確認してください。

  6. ご使用の電波状況の問題により、LTEネットワークから応答がない場合、ネットワーク状態 LTE_NETSTAT_REG_DENIED 、エラー種別が LTE_NETERR_MAXRETRY がnetinfo_callback()で通知されます。
    T3402 タイマが満了後、モデムが自発的に登録処理を開始します。モデムの登録に成功した場合は、ネットワーク状態 LTE_NETSTAT_REG_HOME がnetinfo_callback()で通知され、lte_activate_pdn_sync()関数の戻り値が 0 で返ります。

    モデムがRejectされた場合と同様に、lte_activate_pdn_cancel()関数を呼び出し、lte_activate_pdn_sync()関数を戻り値 -ECANCEL で返すことが可能です。 その後、もう一度lte_activate_pdn_sync()関数を実施した場合、T3402 タイマが満了後にもモデムの登録処理が開始されます。

5.13.6.4. LTEネットワークの情報を取得する

LTEネットワークの情報を取得する関数について、図 93 に示します。

Diagram
図 93. LTEネットワークの情報を取得するシーケンス

現在、LTE API リファレンスに規定している period の最大値 4233600秒 (49日) はサポートしておりません。 period で指定できる最大値は 2073600秒 (24日) になります。

lte_set_report_quality() 及び lte_set_report_cellinfo()電波状況Cell情報 の取得を停止する場合は、lte_set_report_quality()lte_set_report_cellinfo() の順に呼び出してください。

5.13.6.5. モデムをLTEネットワークから切り離す

モデムをLTEネットワークから切り離すシーケンスを、図 94 に示します。

Diagram
図 94. モデムをLTEネットワークから切り離すシーケンス
5.13.6.6. SIMの操作をする

SIMを操作する関数について、図 95 に示します。

Diagram
図 95. SIMを操作するシーケンス

SIMロックをかけている場合、SIMロックを解除するまで、モデムをLTEネットワークに登録することができません。

現在PIN2解除コードの変更は、未サポートです。

残り試行回数が 0 になるまで、PUKロックの解除に失敗した場合、SIMが使用できなくなりますのでご注意ください。

5.13.6.7. モデムを省電力設定にする

モデムのeDRX機能、PSM機能を有効にすることで、モデムを省電力設定にすることができます。

eDRX機能、PSM機能を有効にするシーケンスを、図 96 に示します。

Diagram
図 96. eDRX機能、PSM機能を有効にするシーケンス
  1. モデムのeDRX機能を有効にします。指定するパラメータについて示します。

    表 55. eDRX設定パラメータ
    パラメータ 説明

    act_type

    eDRXの動作種別。 現在は WBS1 固定です。

    enable

    eDRX機能の可否。 有効無効 を選択。

    edrx_cycle

    eDRX動作の動作周期。

    ptw_val

    Paging time window。
    eDRX動作中にデータを受信する間隔を指定する。

  2. モデム側の設定とLTEネットワークがサポートする設定が異なる可能性があるため、eDRX機能の eDRX cyclePTW はLTEネットワークにモデムを登録した時点で決定されます。
    実際に動作しているeDRX設定をlte_get_current_edrx_sync()関数で確認することができます。

    eDRX機能が eDRX cycle が 20.48秒、PTW が 6.4秒で動作している場合の消費電力の波形を、図 97 に示します。

    lte sdk develop edrx power
    図 97. eDRX機能動作中の消費電力波形

    PTW の期間中のみ、データを着信することができます。

  3. モデムのPSM機能を有効にします。指定するパラメータについて示します。

    表 56. PSM設定パラメータ
    パラメータ 説明

    enable

    PSM機能の可否。 有効無効 を選択。

    req_active_time

    T3324 タイマの値。

    ext_periodic_tau_time

    T3412 タイマの値。

  4. PSM機能が使用する T3324タイマの値T3412タイマの値 はLTEネットワークにモデムを登録した時点で決定されます。
    実際に動作しているPSM設定をlte_get_current_psm_sync()関数で確認することができます。

    T3412タイマ の値はご使用のネットワークによっては取得できないことがあります。

  5. PSM機能が使用する T3324タイマの値T3412タイマの値 は LTEネットワークが TRACKING AREA UPDATE ACCEPT メッセージで更新します。

    PSM機能が動作している場合の消費電力の波形を、図 98 に示します。

    lte sdk develop psm power
    図 98. PSM機能動作中の消費電力波形

    T3412タイマ が満了するまで、データを着信することができません。 T3412タイマ が満了後、T3324タイマ が満了するまで、データを着信することができます。

    PSM機能が動作中にeDRX機能を動作させた場合、T3324タイマ の開始から満了するまで、eDRX機能が動作します。

5.13.6.8. モデムリセットからの復帰

モデムが何らかの要因でリセットした場合のシーケンスを、図 99 に示します。

Diagram
図 99. モデムリセットからの復帰シーケンス
  1. モデムリセットが発生した場合、LTEライブラリの状態が Reset ongoing 状態に遷移します。

  2. モデムの電源ON処理が完了すると、LTEライブラリの状態が Power on 状態に遷移します。
    Power on 状態に遷移後、restart_callback()通知が発生します。通知理由は モデム主導の起動 になります。 restart_callback()通知後、モデムが使用できるようになります。

5.13.7. ソケットAPIを使用する

BSD互換性のあるソケットインターフェースをサポートしています。
ソケットAPIの詳細は NuttX Network Interfacesを参照してください。

ソケットAPI使用中にモデムがリセットした場合、close()関数を呼び出してください。

5.13.7.1. モデムのTLSプロトコルを使用する

モデムのTLSプロトコルを使用することで、SPRESENSEのメモリを削減することができます。

モデムのTLSプロトコルはmbedtlsの一部APIをサポートしておりません。

LTEのファームウェアバージョンがRK_03_00_00_00_04121_001の場合、TLS通信APIが機能しない場合があります。( こちら をご参照ください)
ダウンロードサイトにある Updateツール を参照の上、アップデートをお願いします。

モデムのTLSプロトコルを使用するための、コンフィグレーションの変更方法を解説します。

  1. メニュー画面を開く

tools/config.py -m
  1. SPRESENSEのTLSプロトコルを無効にする。

    Application Configuration -> Spresense SDK -> Externals -> mbed TLS Library (CONFIG_EXTERNALS_MBEDTLS)
    lte sdk develop ext mbedtls
  2. モデムのTLSプロトコルを有効にする。

    Application Configuration -> Spresense SDK -> LTE -> Stub mbedTLS Support (CONFIG_LTE_NET_MBEDTLS)
    lte sdk develop stub mbedtls

5.14. Alpha blend

5.14.1. 概要

Alpha blend API imageproc_alpha_blend は、二つの画像(背景(dst)および前景(src))を指定した比率(alpha)でブレンドする機能を提供します。

ピクセルフォーマットは、YUV4:2:2のみサポートされます。
RGB565データをお持ちの場合は、RGB565 ←→ YUV4:2:2 変換API(imageproc_convert_rgb2yuv, imageproc_convert_yuv2rgb)をご利用いただけます。

alphaは、ピクセル毎に指定できて、srcの割合を256分率で表します。

alpha

src比率

dst比率

255

100%

0%

127

50%

50%

0

0%

100%

Diagram
図 100. Alpha blend Sequence Overview

5.14.2. Alpha blend API詳細

背景画像(dst), 前景画像(src), α画像(alpha)および、 dstのブレンド対象ピクセルの原点を基準としたブレンド位置座標(pos_x, pos_y)を指定できます。

各画像は、クリップ場所(長方形の左上端の座標(x1,y1)と右下端の座標(x2, y2))を指定することもできます。

マイナスのpos_xは、ブレンド対象領域の左端よりも左を表します。
マイナスのpos_yは、ブレンド対象領域の上端よりも上を表します。

以下にpox_x. pos_yとしてマイナスの値を指定した場合のブレンドイメージを示します。
図の黄色い枠に囲まれた部分(重なりあった部分))のみがブレンド結果で更新されます。

alpha blend pos
図 101. ブレンド位置の指定
5.14.2.1. 画像情報の指定方法

3つの画像は全て、構造体imageproc_imginfo_t を用いて指定します。

imageproc_imginfo_tの各メンバが表すものを以下に示します。

alpha blend imginfo t
図 102. imageproc_imginfo_t構造体

rectを指定しなければ(rect=NULLとすれば)、画像全体を使用します。

5.14.2.1.1. dst typeの指定

dstは、type = IMAGEPROC_IMGTYPE_16BPPのみサポートします。

5.14.2.1.2. src typeの指定

srcは、type = IMAGEPROC_IMGTYPE_16BPPおよびtype = IMAGEPROC_IMGTYPE_SINGLEをサポートします。

type 特徴

16BPP

YUV4:2:2画像。

SINGLE

全ピクセルが同一色の画像。

SINGLEは16BPPの特殊ケースに該当し、ブレンドの仕方が制限されるかわりに必要メモリを削減することができます。

5.14.2.1.3. alpha typeの指定

alphaは、type = IMAGEPROC_IMGTYPE_8BPP, IMAGEPROC_IMGTYPE_BINARY, IMAGEPROC_IMGTYPE_SINGLEをサポートします。

type 特徴

8BPP

ピクセル毎に異なるアルファ値を設定する。

BINARY

ピクセル毎にブレンド有無を指定する。ブレンドするピクセルに対してのアルファ値は固定となる。

SINGLE

全ピクセルに対して、同一の値を指定する。

BINARY, SINGLEは8BPPの特殊ケースに該当し、ブレンドの仕方が制限されるかわりに必要メモリを削減することができます。


5.15. Host Interface (HostIF)

5.15.1. Overview

Host Interface (以下、HostIF) は、Spresense 外部のホスト IC との通信インターフェース機能を提供します。 Host と Spresense 間の通信は、CXD5602 の I2C(#3) 端子もしくは SPI(#2) 端子を使用します。 I2C や SPI のペリフェラル制御は、CXD5602 内蔵のシーケンサによって行われます。 CXD5602 内部に HostIF 通信用のバッファをもち、Spresense アプリケーションは、 その通信バッファへの読み書きを行うことで Host とデータの送受信を行います。

主な特徴
  • I2C 通信機能

  • SPI 通信機能

  • 通信バッファを用いたデータ送受信

  • Host への割り込み通知機能

5.15.2. HostIF ドライバ

HostIF ドライバを使用して、通信バッファの設定を行い、Host とデータを送受信する方法について説明します。

5.15.2.1. 通信バッファ構成

トータル1KByteの通信バッファをもち、最大32本の論理バッファに分割して使用することができます。 各々の論理バッファに対して、Host から Spresense へ、もしくは、Spresense から Host へ、 どちらか転送方向を設定します。 Host と Spresense から同時にバッファにアクセスされることを防ぐため、バッファの排他ロック機構を備えています。

  • トータル1KBのバッファサイズ

  • 最大32本の論理バッファに分割

  • 各論理バッファのサイズや転送方向を設定可能

  • バッファの排他ロック機構

通信バッファの構成例を以下に示します。 ここでは、Spresenseの受信バッファを3つ(0,2,3)とSpresenseの送信バッファを3つ(1,4,5)で構成しています。

Diagram
図 103. 通信バッファ構成例

バッファ設定のサンプルコードを以下に示します。 構造体の詳細は、 hostif.h を参照してください。

I2C 通信バッファ設定

static struct hostif_i2cconf_s conf =
{
  .address = 0x24, /* own I2C slave address */ (1)
 //[Index] = {  Size, Direction              | Attributes              }, (2)
  .buff[0] = { 0x100, HOSTIF_BUFF_ATTR_READ  | HOSTIF_BUFF_ATTR_VARLEN },
  .buff[1] = { 0x100, HOSTIF_BUFF_ATTR_WRITE | HOSTIF_BUFF_ATTR_VARLEN },
  .buff[2] = { 0x080, HOSTIF_BUFF_ATTR_READ  | HOSTIF_BUFF_ATTR_FIXLEN },
  .buff[3] = { 0x080, HOSTIF_BUFF_ATTR_READ  | HOSTIF_BUFF_ATTR_FIXLEN },
  .buff[4] = { 0x080, HOSTIF_BUFF_ATTR_WRITE | HOSTIF_BUFF_ATTR_FIXLEN },
  .buff[5] = { 0x080, HOSTIF_BUFF_ATTR_WRITE | HOSTIF_BUFF_ATTR_FIXLEN },
};
1 I2C スレーブアドレス定義
2 各通信バッファのサイズ、方向、属性定義

SPI 通信バッファ設定

static struct hostif_spiconf_s conf =
{
 //[Index] = {  Size, Direction              | Attributes              }, (1)
  .buff[0] = { 0x100, HOSTIF_BUFF_ATTR_READ  | HOSTIF_BUFF_ATTR_VARLEN },
  .buff[1] = { 0x100, HOSTIF_BUFF_ATTR_WRITE | HOSTIF_BUFF_ATTR_VARLEN },
  .buff[2] = { 0x080, HOSTIF_BUFF_ATTR_READ  | HOSTIF_BUFF_ATTR_FIXLEN },
  .buff[3] = { 0x080, HOSTIF_BUFF_ATTR_READ  | HOSTIF_BUFF_ATTR_FIXLEN },
  .buff[4] = { 0x080, HOSTIF_BUFF_ATTR_WRITE | HOSTIF_BUFF_ATTR_FIXLEN },
  .buff[5] = { 0x080, HOSTIF_BUFF_ATTR_WRITE | HOSTIF_BUFF_ATTR_FIXLEN },
};
1 各通信バッファのサイズ、方向、属性定義
5.15.2.2. HostIF ドライバ初期化

バッファ構成を引数に設定し、初期化関数を呼び出し HostIF ドライバを初期化します。

I2C 通信バッファ初期化

  ret = hostif_i2cinitialize(&conf);

SPI 通信バッファ初期化

  ret = hostif_spiinitialize(&conf);

初期化が正常に完了したとき、hostifドライバは /dev/hostif{r|w}{0-31} のデバイスファイルを作成します。

前述したサンプルコードでは、次のようにデバイスファイルが作成されます。

Index Size Direction Device filename

0

0x100

Read

/dev/hostifr0

1

0x100

Write

/dev/hostifw1

2

0x080

Read

/dev/hostifr2

3

0x080

Read

/dev/hostifr3

4

0x080

Write

/dev/hostifw4

5

0x080

Write

/dev/hostifw5

5.15.2.3. HostIF ドライバ受信

Read属性のDeviceファイルを open して、read システムコールを使って通信バッファの内容を読み出します。 read によって、Host から送信されたデータを取得することができます。

  int fd = open("/dev/hostifr0", O_RDONLY [| O_NONBLOCK]); (1)

  size = read(fd, buffer, sizeof(buffer)); (2)
1 oflags に O_RDONLY を指定して open システムコールを呼び出します。
ノンブロッキングで読み出しを行う場合は、O_NONBLOCK を指定します。
2 read システムコールを読み出して、通信バッファの内容を読み出します。
戻り値には、読み出したサイズが返ってきます。
5.15.2.4. HostIF ドライバ送信

Write属性のDeviceファイルを open して、write システムコールを使って通信バッファへ書き込みます。 write によって書き込んだデータを Host から読み出すことができます。

  int fd = open("/dev/hostifw1", O_WRONLY [| O_NONBLOCK]); (1)

  size = write(fd, buffer, sizeof(buffer)); (2)
1 oflags に O_WRONLY を指定して open システムコールを呼び出します。
ノンブロッキングで書き込みを行う場合は、O_NONBLOCK を指定します。
2 write システムコールを読み出して、通信バッファへを書き込みます。
戻り値には、書き込んだサイズが返ってきます。

5.15.3. Host 通信仕様

Spresense の対向機となる Host 側の通信仕様について説明します。

Host から I2C, SPI通信によって通信バッファへアクセスするために、通信フォーマットが定義されています。 Host はトランザクションの初めに1byteのICMD (Interface CoMmanD) を送信します。 転送されたICMDの内容により、通信内容と通信フォーマットが決定されます。 全ての転送において、bitはMSBファーストで転送され、複数byteのデータではLSBから順に転送されます。

5.15.3.1. Host 通信フォーマット (I2C)

I2Cの通信フォーマットとしてR1/R2/R3/D1/W1/W2/W3フォーマットが定義されています。 R1/R2/R3フォーマットとD1フォーマットの間はRESTART conditionでつなぐことができます。 データ受信は、R1/R2/R3フォーマットの直後にD1フォーマットを使用します。 データ送信は、W1/W2/W3フォーマットを使用します。

R1フォーマット (固定長サイズ)

R1フォーマットは、固定長サイズの読み出しに使用します。 実際のデータ受信は、この後に転送されるD1フォーマットを発行して行います。

S

SlaveAddr

W

A

ICMD(0x80~0x9F)

A

P

R2フォーマット (可変長サイズ)

R2フォーマットは、可変長サイズの読み出しに使用されます。 また、バッファロックを維持するためのフラグを指定することができます。 実際のデータ受信は、この後に転送されるD1フォーマットを発行して行います。

S

SlaveAddr

W

A

ICMD(0xA0~0xBF)

A

Length(LSB)   

A

Flag+Length(MSB)

A

P

R3フォーマット (オフセット+可変長サイズ)

R3フォーマットは、可変長サイズの読み出しに使用されます。 また、バッファロックを維持するためのフラグを指定することができます。 実際のデータ受信は、この後に転送されるD1フォーマットを発行して行います。 バッファに対して、AddressOffsetで指定した位置から読み出しを行います。

S

SlaveAddr

W

A

ICMD(0xC0~0xDF)

A

AddressOffset   

A

Length(LSB)   

A

Flag+Length(MSB)

A

P

D1フォーマット

D1フォーマットは、Host が通信バッファからデータを読み出す際に使用されます。 1byteのステータスフラグの後にデータを受信します。 受信データのサイズは、R1フォーマットは固定サイズ、R2/R3フォーマット時は指定されたサイズになります。

S

SlaveAddr

R

A

Status      

A

Data       

A

…​.       

A

…​.       

N

P

W1フォーマット (固定長サイズ)

W1フォーマットは、固定長サイズのデータ送信に使用されます。 データの最後にdummyデータ(1byte)を付加してください。

S

SlaveAddr

W

A

ICMD(0x80~0x9F)

A

Data      

A

…​.      

A

dummy     

A

P

W2フォーマット (可変長サイズ)

W2フォーマットは、可変長サイズのデータ送信に使用されます。 また、バッファロックを維持するためのフラグを指定することができます。 転送長はLengthで指定したサイズになります。 データの最後にdummyデータ(1byte)を付加してください。

S

SlaveAddr

W

A

ICMD(0xA0~0xBF)

A

Length(LSB)   

A

Flag+Length(MSB)

A

Data      

A

…​.      

A

dummy     

A

P

W3フォーマット (オフセット+可変長サイズ)

W3フォーマットは、可変長サイズのデータ送信に使用されます。 また、バッファロックを維持するためのフラグを指定することができます。 バッファに対して、AddressOffsetで指定したバッファ位置へ書き込みを行います。 転送長はLengthで指定したサイズになります。 データの最後にdummyデータ(1byte)を付加してください。

S

SlaveAddr

W

A

ICMD(0xC0~0xDF)

A

AddressOffset   

A

Length(LSB)   

A

Flag+Length(MSB)

A

Data      

A

…​.      

A

dummy     

A

P

各フォーマットの構成要素は下記の通りです。

SlaveAddr

I2C規格においてスレーブを指定するためのアドレスです。

ICMD

Host が通知する1byteのコマンドで、そのトランザクションの通信内容を決定します。 詳細はICMD 一覧 を参照してください。

Length, Flag

Lengthは、Host が指定する14bitのデータで、そのトランザクションのデータ転送長を通知します。単位はbyteです。 転送長は2byteのデータとして転送され、下位8bitが先に、続いて上位6bitが転送されます。 なお、上位6bitを転送するバイトデータのbit7はreserved、bit6はバッファロックフラグです。

Byte Bit Description

Length(LSB)

[7:0]

Length[7:0] 転送長(下位8bit)

Flag+Length(MSB)

[7:7]

Reserved

[6:6]

バッファロックフラグ(1:Lock保持, 0:Unlock)

[5:0]

Length[13:8] 転送長(上位6bit)

バッファロックフラグは、Host が指定する1bitのフラグです。 このフラグが1であるとき、通信の論理バッファのHostがロック状態を維持します。 このフラグが0であるとき、トランザクション終了時に論理バッファをアンロックします。 Hostがロックした状態のとき、Slave側からの書き込み、読み出し操作を禁止します。

AddrOffset

Host が指定する1byteのデータです。 アドレスオフセットを指定することで、Host は論理バッファのアクセス開始位置を指定できます。 単位は1,2,4,8byteのいずれかで、通信バッファの初期化時に設定します。

Status

Host に送信される1byteのデータです。bit0(LSB)はロック失敗ステータスフラグで、 Host が論理バッファのロックに失敗したときに1になります。

Byte Bit Description

Status

[7:1]

Reserved

[0:0]

ロックステータス(1:失敗、0:成功)

dummy

W1,W2,W3フォーマットにおいて、Host はトランザクションの最後に1byteのダミーデータを転送しなければなりません。

Data

通信フォーマットのペイロードです。

5.15.3.2. Host 通信フォーマット (SPI)

SPIの通信フォーマットとしてR1/R2/R3/W1/W2/W3フォーマットが定義されています。 データ受信はR1/R2/R3フォーマットを、データ送信はW1/W2/W3フォーマットを使用します。

図中の上側がSDO, 下側がSDIを表します。

R1フォーマット (固定長サイズ)

R1フォーマットは、固定長サイズの読み出しに使用されます。

ICMD(0x80~0x9F)

dummy     

dummy     

dummy     

dummy     

dummy     

dummy

dummy

Status

Data

…​.

…​.

R2フォーマット (可変長サイズ)

R2フォーマットは、可変長サイズの読み出しに使用されます。 また、バッファロックを維持するためのフラグを指定することができます。 データ転送長はLengthで指定したサイズになります。

ICMD(0xA0~0xBF)

Length(LSB)

Flag+Length(MSB)

dummy     

dummy     

dummy     

dummy

dummy

Status

Data

…​.

…​.

R3フォーマット (オフセット+可変長サイズ)

R3フォーマットは、可変長サイズの読み出しに使用されます。 また、バッファロックを維持するためのフラグを指定することができます。 バッファに対して、AddressOffsetで指定した位置から読み出しを行います。 データ転送長はLengthで指定したサイズになります。

ICMD(0xC0~0xDF)

AddressOffset

Length(LSB)

Flag+Length(MSB)

dummy     

dummy     

dummy

dummy

Status

dummy

Data

…​.

W1フォーマット (固定長サイズ)

W1フォーマットは、固定長サイズのデータ送信に使用されます。 データの最後にdummyデータ(1byte)を付加してください。

ICMD(0x80~0x9F)

Data     

…​.      

…​.      

…​.      

dummy     

dummy

dummy

Status

dummy

dummy

dummy

W2フォーマット (可変長サイズ)

W2フォーマットは、可変長サイズのデータ送信に使用されます。 また、バッファロックを維持するためのフラグを指定することができます。 データ転送長はLengthで指定したサイズになります。 データの最後にdummyデータ(1byte)を付加してください。

ICMD(0xA0~0xBF)

Length(LSB)

Flag+Length(MSB)

Data     

…​.      

…​.      

dummy     

dummy

dummy

Status

dummy

dummy

dummy

dummy

W3フォーマット (オフセット+可変長サイズ)

W3フォーマットは、可変長サイズのデータ送信に使用されます。 また、バッファロックを維持するためのフラグを指定することができます。 バッファに対して、AddressOffsetで指定したバッファ位置へ書き込みを行います。 データ転送長はLengthで指定したサイズになります。 データの最後にdummyデータ(1byte)を付加してください。

ICMD(0xC0~0xDF)

AddressOffset

Length(LSB)

Flag+Length(MSB)

Data     

…​.      

dummy     

dummy

dummy

Status

dummy

dummy

dummy

dummy

各フォーマットの構成要素は下記の通りです。

ICMD

Host が通知する1byteのコマンドで、そのトランザクションの通信内容を決定します。 詳細はICMD 一覧 を参照してください。

Length, Flag

Lengthは、Host が指定する14bitのデータで、そのトランザクションのデータ転送長を通知します。単位はbyteです。 転送長は2byteのデータとして転送され、下位8bitが先に、続いて上位6bitが転送されます。 なお、上位6bitを転送するバイトデータのbit7はreserved、bit6はバッファロックフラグです。

Byte Bit Description

Length(LSB)

[7:0]

Length[7:0] 転送長(下位8bit)

Flag+Length(MSB)

[7:7]

Reserved

[6:6]

バッファロックフラグ(1:Lock保持, 0:Unlock)

[5:0]

Length[13:8] 転送長(上位6bit)

バッファロックフラグは、Host が指定する1bitのフラグです。 このフラグが1であるとき、通信の論理バッファのHostがロック状態を維持します。 このフラグが0であるとき、トランザクション終了時に論理バッファをアンロックします。 Hostがロックした状態のとき、Slave側からの書き込み、読み出し操作を禁止します。

AddrOffset

Host が指定する1byteのデータです。 アドレスオフセットを指定することで、Host は論理バッファのアクセス開始位置を指定できます。 単位は1,2,4,8byteのいずれかで、通信バッファの初期化時に設定します。

Status

Host に送信される1byteのデータです。bit0(LSB)はロック失敗ステータスフラグで、 Host が論理バッファのロックに失敗したときに1になります。

Byte Bit Description

Status

[7:1]

Reserved

[0:0]

ロックステータス(1:失敗、0:成功)

dummy

W1,W2,W3フォーマットにおいて、Host はトランザクションの最後に1byteのダミーデータを転送しなければなりません。

Data

通信フォーマットのペイロードです。

5.15.3.3. ICMD 一覧

ICMD 定義は以下の通りです。

転送サイズの読み出しやRead/Write転送はICMDの下位5bitに通信バッファのIndex番号を指定します。

Raw, Masked, Mask, Set, Clear は割り込みを制御するための ICMD です。割り込み機能については後述します。

0x00

0x01

0x02

0x03

0x04

0x05

0x06

0x07

0x08

0x09

0x0A

0x0B

0x0C

0x0D

0x0E

0x0F

0x00

Raw

Masked

Mask

Status

0x10

Read 転送サイズ [0x10 + 通信バッファIndex]

0x20

0x30

0x40

0x50

Set

Clear

0x60

0x70

0x80

Read/Write 固定長転送 (R1/W1 format) [0x80 + 通信バッファIndex]

0x90

0xA0

Read/Write 可変長転送 (R2/W2 format) [0xA0 + 通信バッファIndex]

0xB0

0xC0

Read/Write アドレスオフセット+可変長転送 (R3/W3 format) [0xC0 + 通信バッファIndex]

0xD0

0xE0

0xF0

5.15.3.3.1. ICMD(0x0E) ステータス読み出し

ICMD(0x0E)を発行し、R1フォーマットによって通信ステータスを読み出します。 SPI 通信や I2C の Read 通信時は、受信データ中に Status が含まれているので、 ICMD(0x0E) を発行する必要はありません。唯一、I2C の Write 通信時は、 転送が成功したかどうかかを知るために、この ICMD を利用することができます。

I2C 通信でのフォーマット例を以下に示します。

Status[0:0]が、0: 論理バッファのロック成功、1: 論理バッファのロック失敗、を表します。

S

SlaveAddr

W

A

ICMD(0x0E)

A

P

S

SlaveAddr

R

A

Status      

A

Status       

A

P

5.15.3.4. 通信割り込み

Host への割り込みは、HIF_IRQ_OUT ピンを用いて、各バッファが書き込み可、読み出し可の時にアサートされます。 その割り込みは、Host が通信バッファに対して書き込みや読み出しが行われたときにクリアされます。

5.15.3.4.1. ICMD(0x03) 割り込みマスク前ステータス読み出し

ICMD(0x03)を発行し、R1フォーマットによって、マスク前の割り込み要因を取得することができます。 各論理バッファ番号(0~31)がRaw[31:0]のビットにアサインされています。

SPI 通信でのフォーマット例を以下に示します。

ICMD(0x03)

dummy

dummy

dummy

dummy

dummy

dummy

dummy

dummy

Status

Raw[7:0]

Raw[15:8]

Raw[23:16]

Raw[31:24]

5.15.3.4.2. ICMD(0x07) 割り込みマスク後ステータス読み出し

ICMD(0x07)によって、マスク後の割り込み要因を取得することができます。 各論理バッファ番号(0~31)がMasked[31:0]のビットにアサインされています。

SPI 通信でのフォーマット例を以下に示します。

ICMD(0x07)

dummy

dummy

dummy

dummy

dummy

dummy

dummy

dummy

Status

Masked[7:0]

Masked[15:8]

Masked[23:16]

Masked[31:24]

5.15.3.4.3. ICMD(0x0B) 割り込みマスク読み出し

ICMD(0x0B)によって、割り込みマスクの値を取得することができます。 各論理バッファ番号(0~31)がMask[31:0]のビットにアサインされています。 1が設定されているbitは割り込み禁止、0が設定されているbitは割り込み許可を表します。

SPI 通信でのフォーマット例を以下に示します。

ICMD(0x0B)

dummy

dummy

dummy

dummy

dummy

dummy

dummy

dummy

Status

Mask[7:0]

Mask[15:8]

Mask[23:16]

Mask[31:24]

5.15.3.4.4. ICMD(0x53) 割り込みマスクセット

各論理バッファ番号(0~31)がSet[31:0]のビットにアサインされています。 割り込みを禁止したいビットに1を立てて、ICMD(0x53)を発行することで割り込みマスクを設定します。 0 を設定したビットのマスク値は変更されません。

SPI 通信でのフォーマット例を以下に示します。

ICMD(0x53)

Set[7:0]

Set[15:8]

Set[23:16]

Set[31:24]

dummy

dummy

dummy

Status

dummy

dummy

dummy

5.15.3.4.5. ICMD(0x57) 割り込みマスククリア

各論理バッファ番号(0~31)がClear[31:0]のビットにアサインされています。 割り込みを許可したいビットに1を立てて、ICMD(0x57)を発行することで割り込みマスクをクリアします。 0 を設定したビットのマスク値は変更されません。

SPI 通信でのフォーマット例を以下に示します。

ICMD(0x57)

Clear[7:0]

Clear[15:8]

Clear[23:16]

Clear[31:24]

dummy

dummy

dummy

Status

dummy

dummy

dummy

5.15.3.5. Host 通信シーケンス
5.15.3.5.1. Host 受信シーケンス

Host が Spresense からのデータを受信するシーケンスを以下に示します。

Diagram
Write data

論理バッファに対して、Spresense がデータを書き込みます。 データ書き込み中はSpresenseがバッファをロックし、書き込みが終わったらアンロックします。 Spresenseがバッファをロックしている間は、Hostからのロック操作は禁止されます。 もし、Hostがロック中にデータを書き込むと write() はエラーになります。

Interrupt

Spresenseの書き込みが終わり、論理バッファが読み出し可能になるとHostへの割り込みが発生します。

Read Interrupt

論理バッファの割り込みステータスを読み出すことで論理バッファにデータが存在するかどうかを知ることができます。

Read size

論理バッファにデータが存在する場合、Spresenseから書き込まれたデータサイズを取得できます。

Read data

HostがRead用のICMDを発行してデータを読み出します。 データ読み出し中はHostがバッファをロックし、Spresenseからのデータ書き込みが禁止されます。 データ読み出しが完了したらバッファはアンロックされて、直後にSpresenseがロックした状態に切り替わります。 もし、Spresenseがバッファロック中にデータを読み出した場合は、読み出し操作がエラーになります。 読み出しフォーマットのStatusデータにより、読み出しが成功したかどうかを知ることができます。

5.15.3.5.2. Host 送信シーケンス

Host が Spresense へのデータを送信するシーケンスを以下に示します。

Diagram
Interrupt

論理バッファが書き込み可能になるとHostへの割り込みが発生します。

Read Interrupt

論理バッファの割り込みステータスを読み出すことで論理バッファにデータが書き込み可能かどうかを知ることができます。

Read size

論理バッファに書き込み可能なデータサイズを取得することができます。

Write data

HostがWrite用のICMDを発行してデータを書き込みます。 データ書き込み中はHostがバッファをロックし、Spresenseからのデータ読み出しが禁止されます。 データ書き込みが完了したらバッファはアンロックされて、直後にSpresenseがロックした状態に切り替わります。 もし、Spresenseがバッファロック中にデータを書き込んだ場合は、書き込み操作がエラーになります。 SPI通信の場合、受信したStatusデータにより、 I2C通信の場合、ICMD(0xE)を発行して得られるStatusデータより、 書き込みが成功したかどうかを知ることができます。

Read data

論理バッファに対して、Spresense がデータを読み出します。 データ読み出し中はSpresenseがバッファをロックし、読み出しが終わったらアンロックします。 Spresenseがバッファをロックしている間は、Hostからのロック操作は禁止されます。 もし、Hostがロック中にデータを読み出すと read() はエラーになります。

5.15.4. Examples

HostIF サンプルアプリケーションは、SDKチュートリアル を参照してください。


5.16. BLE

5.16.1. 概要

BLEミドルウェアは、BLE central と BLE peripheralをサポートしていて、 メインボードにBLEボードを挿して使用することでBLE通信が可能となります。

5.16.2. BLE central

5.16.2.1. 全体の流れ

BLE centralとして動かす場合、以下の流れでBLE peripheralと接続・データ通信を行います。

  1. 初期化

  2. BLE peripheralの探索

  3. 接続

  4. サービス情報取得

  5. 通信路の暗号化

  6. データ通信

  7. 切断

5.16.2.2. 初期化
5.16.2.2.1. BLEミドルウェアの初期化

bt_init()で、BLEミドルウェアの初期化を行います。

5.16.2.2.2. callback関数の登録

BLEミドルウェアでは、各APIの実行結果や、BLE peripheralからのメッセージ受信の通知を アプリケーションが登録したcallback関数を実行することにより実現します。

登録するcallback関数は大きく2つのグループに分かれます。

BLE peripheralと共通の型定義をもつcallback関数群

BLE peripheralと共通の型定義が用いられる関数群は ble_register_common_cb() APIで登録します。

構造体は struct ble_common_ops_s型で以下のメンバを持ちます。

表 57. struct ble_common_ops_s構造体のメンバ関数と実行タイミング
登録する関数 実行タイミング

connect_status_changed

ble_connect()実行後、
・接続できた場合、引数connected = trueで呼ばれる
・接続エラーの場合、引数connected = falseで呼ばれる
ble_disconnect()実行後 or 接続相手要因により切断された場合
・引数connected = falseで呼ばれる

scan_result

ble_start_scan() ~ ble_stop_scan()の間
・周囲のBLE peripheralが発しているadvertisingを受信したら呼ばれる。

load_bondinfo

bt_enable()実行時に、return前に呼ばれる。
前回使用時に、後述のsave_bondinfo callback関数で覚えておいた情報を
返すことで、前回の情報を引き継いだ状態から開始することができる。

save_bondinfo

ペアリング成功時に呼ばれる。
引数で渡された情報をファイルなどに保存しておいて、
load_bondinfo callback関数で、復元処理を行うことで
spresenseをリセットした場合にもリセット前に保持していた情報で開始できる。

encryption_result

ble_pairing()実行後、
・通信路を暗号化できた場合、引数result = trueで呼ばれる
・通信路を暗号化できなかった場合、引数result = falseで呼ばれる

BLE central固有のcallback関数群

central固有のcallback関数群は ble_register_gatt_central_cb() APIで登録する。

構造体は struct ble_gatt_central_ops_s型で以下のメンバを持ちます。

表 58. struct ble_gatt_central_ops_s構造体のメンバ関数と呼ばれるタイミング
登録する関数 実行タイミング

write

ble_characteristic_write()実行後、writeが完了したら、呼ばれる。

read

ble_characteristic_read()実行後、readが完了したら呼ばれる。

notify

接続中の対向BLE peripheralからnotifyを受信したら呼ばれる。

database_discovery

以下の3つのAPI実行後、discovery処理が完了したら、呼ばれる。
- ble_start_db_discover()
- ble_continue_db_discover()
- ble_discover_uuid()

descriptor_write

ble_descriptor_write()実行後、writeが完了したら呼ばれる。

descriptor_read

ble_characteristic_read()実行後、readが完了したら呼ばれる。

使用しない機能についてのcallback関数メンバは、NULL設定にすることができます。

5.16.2.2.3. BLE デバイス初期化

bt_enable()でBLEデバイスの初期化処理を行います。

bt_enable()の処理の中で、 load_bondinfo callbackが呼ばれます。 load_bondinfo callback関数で、前回起動時のload_saveinfo callbackで通知されている情報を 復元することで、前回起動時のペアリング情報を保持した状態で開始することができます。

5.16.2.2.4. BLE有効化

BLE有効化シーケンスを 図 104 に示します。

Diagram
図 104. BLE有効化
  1. 自デバイス名を設定します。

  2. 自BLEアドレスを設定します。BLEアドレスタイプは random staticタイプとなります。

  3. BLE機能が有効になり、デバイス名・BLEアドレス設定をHWに反映されます。

5.16.2.3. BLE peripheralデバイスの探索

BLE scan(周囲のBLE peripheralデバイスの探索)シーケンスを図 105に示します。

Diagram
図 105. scan
  1. BLE scan(周囲に存在するBLE peripheralデバイスの探索)を開始します。

  2. 周囲にBLE peripheralデバイスがあれば、callbackが呼ばれて、見つかったデバイスのBLEアドレスおよび、見つかったデバイスが送出しているアドバタイジングデータが通知されます。

  3. 受信データの中には、BLE peripheralデバイスの設定に応じてさまざまな情報が存在しえます。受信データの中から、アプリケーションが求めている情報を取得するAPIとして、ble_parse_advertising_data()を用意しています。このAPIでデータの存在有無や値を確認して、接続したい条件を満たしているかどうか判断できます。

  4. 探索を停止します。

5.16.2.4. 接続

接続シーケンスを 図 106 に示します。

Diagram
図 106. 接続
  1. scan_result callbackで見つけたデバイスのBLEアドレスとアドレスタイプ情報を指定して接続を要求します。

  2. 接続できた場合、callback関数で bool connected = trueが通知されます。このとき、callback関数の第一引数の構造体メンバ ble_connect_handleは、connection識別子を表しており、これは接続状態で使用する全てのAPIで必要となるため、記憶しておく必要があります。以降、connection識別子とはここで受け取った情報を意味するものとします。

  3. 接続できなかった場合、callback関数で bool connected = falseが通知されます。

5.16.2.5. サービス情報の取得

サービス情報の取得シーケンスを図 107に示します。

Diagram
図 107. サービス情報取得
  1. サービス情報を頭から順番に取得したい場合は、ble_start_db_discovery()をconnection識別子を指定して実行します。

  2. 見つかったサービス情報のリストが通知されます。

  3. 全てを受信しておらず、また、受信済みデータの中に欲しい情報がなかった場合は、ble_continue_db_discovery()で続きの取得を要求できます。

  4. 取得結果は、ble_start_db_discovery()時と同様のcallbackで通知されます。

  5. 指定したUUIDの情報のみを取得するのに、ble_discover_uuid()が使えます。

  6. UUID指定の場合も取得結果はble_start_db_discovery()時と同様のcallbackで通知されます。

取得した情報には以下の情報が含まれます。 . UUID . property (notify, read, writeの権限有無) . handle(データ送受信時に使用する識別子)

5.16.2.6. 通信路の暗号化

通信路の暗号化シーケンスを図 108に示します。

Diagram
図 108. 通信路の暗号化
  1. 暗号化を開始します。

  2. 接続相手のBLE peripheralとの間の通信路の暗号化に成功すると、callbackで暗号化成功が通知されます。

  3. 接続相手のBLE peripheralとの間の通信路の暗号化に失敗すると、callbackで暗号化失敗が通知されます。

5.16.2.7. データ通信
5.16.2.7.1. データ更新

データ更新シーケンスを図 109に示します。

Diagram
図 109. データ更新
  1. 指定したconnection識別子とキャラクタリスティック識別子について、値を指定したバッファデータで更新します。

  2. 更新結果は、write callbackで通知されます。

  3. BLE peripheralからのデータ変更通知を受信できるようにするには、ble_descriptor_write()で、CCCDを指定します。

  4. 更新結果は、descriptor_write callbackで通知されます。

5.16.2.7.2. データ読み出し

データ読み出しシーケンスを図 110に示します。

Diagram
図 110. データ読み出し
  1. 指定したconnection識別子とキャラクタリスティック識別子について、読み出し要求をします。。

  2. 読み出し結果は、read callbackで通知されます。

  3. 指定したconnection識別子とディスクリプタ識別子について、読み出し要求をします。

  4. 読み出し結果は、descriptor_write callbackで通知されます。

5.16.2.7.3. データ受信

データ受信シーケンスを図 111に示します。

Diagram
図 111. データ受信
  1. BLE peripheral側でデータ更新があると、notify callbackで更新後データが通知されます。

5.16.2.8. 切断

切断シーケンスを図 112 に示します。

Diagram
図 112. 切断
  1. アプリケーション主導で切断する場合は、ble_disconnect()でconnection識別子を指定します。切断が完了すると、connect_status_changed callbackが引数connected = falseで呼ばれます。

  2. BLE peripheral主導で切断がおきた場合は、単にconnect_status_changed callbackが引数connected = falseで呼ばれます。

5.16.3. BLE peripheral

5.16.3.1. 基本的な流れ

BLE peripheralとして動かす場合、以下の流れでBLE centralと接続し、データ通信を行います。

  1. 初期化

  2. サービス設定

  3. アドバタイズ (周囲のBLE centralに自分の存在を知らせる)

  4. 接続 (BLE central主導の処理で接続してくるのを待つ)

  5. 通信路の暗号化 (BLE central主導で暗号化してくるのを待つ)

  6. データ通信

  7. 切断

5.16.3.2. 初期化処理
5.16.3.2.1. BLEミドルウェアの初期化

bt_init()で、BLEミドルウェアの初期化を行います。
これは BLE centralと同様です。

5.16.3.2.2. callback関数の登録

BLEミドルウェアでは、各APIの実行結果や、BLE peripheralからのメッセージ受信の通知を アプリケーションが登録したcallback関数を実行することにより実現します。

登録するcallback関数は大きく2つのグループに分かれます。

BLE centralと共通の型定義をもつcallback関数群

BLE centralと共通の型定義が用いられる関数群は ble_register_common_cb() APIで登録します。

構造体は struct ble_common_ops_s型で以下のメンバを持ちます。

表 59. struct ble_common_ops_s構造体のメンバ関数と呼ばれるタイミング
登録する関数 メンバ関数が呼ばれるタイミング

connect_status_changed

周囲のBLE centralが接続してきた場合
・引数connected = trueで呼ばれる
ble_disconnect()実行後 or 接続相手要因により切断された場合
・引数connected = falseで呼ばれる

scan_result

BLE peripheralでは使用しません。

load_bondinfo

bt_enable()実行時に、return前に呼ばれる。
前回使用時に、後述のsave_bondinfo callback関数で覚えておいた情報を
返すことで、前回の情報を引き継いだ状態から開始することができる。

save_bondinfo

ペアリング成功時に呼ばれる。
引数で渡された情報をファイルなどに保存しておいて、
load_bondinfo callback関数で、復元処理を行うことで
spresenseをリセットした場合にもリセット前に保持していた情報で開始できる。

encryption_result

BLE central主導でおこなわれる暗号化処理で ・通信路を暗号化できた場合、引数result = trueで呼ばれる
・通信路を暗号化できなかった場合、引数result = falseで呼ばれる

BLE peripheral固有のcallback関数群

BLE peripheral固有のcallback関数群は後述のサービス設定処理にて使用するble_add_characteristic() APIで登録します。

構造体は struct ble_gatt_peripheral_ops_s型で以下のメンバを持ちます。

表 60. struct ble_gatt_peripheral_ops_s構造体のメンバ関数と呼ばれるタイミング
登録する関数 メンバ関数が呼ばれるタイミング

write

BLE centralがcharacteristicの更新をおこなった場合に呼ばれる。

notify

BLE centralがCCCDを更新した場合に呼ばれる。

使用しない機能についてのcallback関数メンバは、NULL設定にすることができます。

5.16.3.2.3. BLE デバイス初期化

bt_enable()でBLEデバイスの初期化処理を行います。 BLE central時と同様になります。

5.16.3.2.4. BLE機能の有効化

自デバイス名と自BLEアドレスを設定して、BLE機能を有効化します。 BLE central時と同様になります。

5.16.3.3. サービス設定

サービス設定シーケンスを図 113に示します。

Diagram
図 113. サービス設定
  1. サービスインスタンスを取得します。

  2. 取得したサービスインスタンスにUUIDを設定します。

  3. サービスにぶらさげたいキャラクタリスティックの設定を行うために、アプリケーションでインスタンスを準備し、設定します。

  4. 指定したサービスインスタンスに、指定したキャラクタリスティックインスタンスをぶらさげます。

  5. 指定したサービスインスタンスをHWに設定し有効にします。

アプリケーションの処理内で行うサービスの設定としてはUUIDの設定のみとなります。 ble_create_service()で取得したインスタンス構造体のメンバuuidに設定します。

キャラクタリスティックの設定は、UUIDの他に属性、データサイズ、権限を設定します。

表 61. キャラクタリスティック設定項目
メンバ 意味 設定方法

value.len

データ長

最大長を設定します。

value.attrPerm

属性

暗号化要否を設定します。
・writePerm : BLE centralからの書き込み要求についての暗号化要否 ・readPerm : BLE centralからの読み出し要求についての暗号化要否

property

権限

bit field構造になっており、許可したいoperationのビットを1にします。
たとえば、notify=1, read=1, write=1とすると、notify可能・read可能・write可能となる。

5.16.3.4. アドバタイズ

アドバタイズは、周囲のBLE centralに自デバイスの存在をしらせつつ、自分がどのようなデバイスなのかを知らせる行為です。

このシーケンスを図 114に示します。

Diagram
図 114. アドバタイズ
  1. アドバタイジングを開始して、周囲のBLE centralから見つけられるようにします。

  2. アドバタイジングを停止して、周囲のBLE centralから見つけられなくします。

以降、接続・通信路の暗号化については、BLE centralが主導します。

5.16.3.5. 接続

BLEでは、接続はBLE centralが主導する仕様であるため、 peripheralとしては、アドバタイジング開始後に、接続状態になるのを待つことになります。

通知は、ble_register_common_ops()で登録するcallback関数群の中のconnect_status_changed() callbackが呼ばれます。

connect_status_changed callback関数の引数struct ble_state_s *stateは、 この中のメンバ ble_connect_handle が、connection識別子となっており、 接続状態で行われる全てのAPIで共通で使用するので アプリケーションで記憶しておく必要があります。

5.16.3.6. 通信路の暗号化

BLEでは、通信路の暗号化はBLE centralが主導する仕様であるため、 peripheralとしては、接続後に、暗号化完了通知を待つことになります。

通知は、ble_register_common_ops()で登録するcallback関数群の中のencryption_result() callbackが呼ばれます。

5.16.3.7. データ通信
5.16.3.7.1. データ受信

BLE centralからデータ更新要求を受けると、write callback関数が呼ばれます。 通知されたデータ長・値が相手が送信したデータになります。

5.16.3.7.2. データ送信

ble_characteristic_notify() を実行することで、指定したcharacteristicのvalueの更新と、 BLE centralへのnotify メッセージ送信ができます。

5.16.3.8. 切断

切断については、接続とは違いBLE peripheral側からも行うことができます。切断方法・切断完了の通知の受信はBLE central時と同じになります。

5.16.4. 各種条件

5.16.4.1. BLE central/BLE peripheral共通
  1. 同時接続可能数は1です。

5.16.4.2. BLE peripheral
  1. 設定可能GATTサービス数は1です。

  2. GATTサービスに含められるキャラクタリスティック数は1です。

  3. ディスクリプタはキャラクタリスティックのproperty設定でnotifyを有効にした場合に、CCCDが自動的に付与されます。

5.16.4.3. BLE central
  1. database discovery で 128bit UUID情報を得るには ble_discover_uuid()を使用する必要があります。

5.16.5. サンプルコード

6. NuttXが提供する機能

NuttXが提供する機能については、NuttX.orgを参照してください。