C言語でBBC micro:bit V2およびDFRobot micro:Maqueenを操作する
Revisión | 97f55ec28b363b9db68581c7609fda1ea77b9bff (tree) |
---|---|
Tiempo | 2023-09-14 06:51:08 |
Autor | xm6_original <tanaka_yasushi2008@yaho...> |
Commiter | xm6_original |
ミュージックドライバまで
@@ -87,7 +87,7 @@ | ||
87 | 87 | <option id="ilg.gnuarmeclipse.managedbuild.cross.option.c.compiler.warning.missingprototypes.39027230" name="Warn if a global function has no prototype (-Wmissing-prototypes)" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.c.compiler.warning.missingprototypes" useByScannerDiscovery="true" value="true" valueType="boolean"/> |
88 | 88 | <option id="ilg.gnuarmeclipse.managedbuild.cross.option.c.compiler.warning.badfunctioncast.802810021" name="Warn if wrong cast (-Wbad-function-cast)" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.c.compiler.warning.badfunctioncast" useByScannerDiscovery="true" value="true" valueType="boolean"/> |
89 | 89 | <option id="ilg.gnuarmeclipse.managedbuild.cross.option.c.compiler.warning.strictprototypes.55888613" name="Warn if a function has no arg type (-Wstrict-prototypes)" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.c.compiler.warning.strictprototypes" useByScannerDiscovery="true" value="true" valueType="boolean"/> |
90 | - <option id="ilg.gnuarmeclipse.managedbuild.cross.option.c.compiler.otheroptimizations.379956610" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.c.compiler.otheroptimizations" value="-fsingle-precision-constant" valueType="string"/> | |
90 | + <option id="ilg.gnuarmeclipse.managedbuild.cross.option.c.compiler.otheroptimizations.379956610" name="その他の最適化フラグ" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.c.compiler.otheroptimizations" useByScannerDiscovery="true" value="-fsingle-precision-constant" valueType="string"/> | |
91 | 91 | <inputType id="ilg.gnuarmeclipse.managedbuild.cross.tool.c.compiler.input.59146624" superClass="ilg.gnuarmeclipse.managedbuild.cross.tool.c.compiler.input"/> |
92 | 92 | </tool> |
93 | 93 | <tool id="ilg.gnuarmeclipse.managedbuild.cross.tool.cpp.compiler.894778314" name="GNU Arm Cross C++ Compiler" superClass="ilg.gnuarmeclipse.managedbuild.cross.tool.cpp.compiler"> |
@@ -100,7 +100,10 @@ | ||
100 | 100 | <option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="ilg.gnuarmeclipse.managedbuild.cross.option.cpp.compiler.defs.1680054453" name="定義済みシンボル (-D)" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.cpp.compiler.defs" useByScannerDiscovery="true" valueType="definedSymbols"> |
101 | 101 | <listOptionValue builtIn="false" value="DEBUG"/> |
102 | 102 | <listOptionValue builtIn="false" value="TRACE"/> |
103 | + <listOptionValue builtIn="false" value="OS_USE_TRACE_SEMIHOSTING_STDOUT"/> | |
104 | + <listOptionValue builtIn="false" value="NRF52833_XXAA"/> | |
103 | 105 | </option> |
106 | + <option id="ilg.gnuarmeclipse.managedbuild.cross.option.cpp.compiler.warnabi.1516595037" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.cpp.compiler.warnabi" value="false" valueType="boolean"/> | |
104 | 107 | <inputType id="ilg.gnuarmeclipse.managedbuild.cross.tool.cpp.compiler.input.161133683" superClass="ilg.gnuarmeclipse.managedbuild.cross.tool.cpp.compiler.input"/> |
105 | 108 | </tool> |
106 | 109 | <tool id="ilg.gnuarmeclipse.managedbuild.cross.tool.c.linker.1340459132" name="GNU Arm Cross C Linker" superClass="ilg.gnuarmeclipse.managedbuild.cross.tool.c.linker"> |
@@ -219,6 +222,16 @@ | ||
219 | 222 | <option id="ilg.gnuarmeclipse.managedbuild.cross.option.command.size.698871301" name="Size command" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.command.size" value="size" valueType="string"/> |
220 | 223 | <option id="ilg.gnuarmeclipse.managedbuild.cross.option.command.make.543432284" name="ビルド・コマンド" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.command.make" value="make" valueType="string"/> |
221 | 224 | <option id="ilg.gnuarmeclipse.managedbuild.cross.option.command.rm.1313472073" name="Remove command" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.command.rm" value="rm" valueType="string"/> |
225 | + <option id="ilg.gnuarmeclipse.managedbuild.cross.option.arm.target.fpu.abi.276165612" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.arm.target.fpu.abi" value="ilg.gnuarmeclipse.managedbuild.cross.option.arm.target.fpu.abi.hard" valueType="enumerated"/> | |
226 | + <option id="ilg.gnuarmeclipse.managedbuild.cross.option.arm.target.fpu.unit.43487436" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.arm.target.fpu.unit" value="ilg.gnuarmeclipse.managedbuild.cross.option.arm.target.fpu.unit.fpv4spd16" valueType="enumerated"/> | |
227 | + <option id="ilg.gnuarmeclipse.managedbuild.cross.option.warnings.uninitialized.1838683092" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.warnings.uninitialized" value="true" valueType="boolean"/> | |
228 | + <option id="ilg.gnuarmeclipse.managedbuild.cross.option.warnings.missingdeclaration.1471617354" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.warnings.missingdeclaration" value="true" valueType="boolean"/> | |
229 | + <option id="ilg.gnuarmeclipse.managedbuild.cross.option.warnings.conversion.1000939115" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.warnings.conversion" value="true" valueType="boolean"/> | |
230 | + <option id="ilg.gnuarmeclipse.managedbuild.cross.option.warnings.pointerarith.1755960847" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.warnings.pointerarith" value="true" valueType="boolean"/> | |
231 | + <option id="ilg.gnuarmeclipse.managedbuild.cross.option.warnings.shadow.1404970943" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.warnings.shadow" value="true" valueType="boolean"/> | |
232 | + <option id="ilg.gnuarmeclipse.managedbuild.cross.option.warnings.logicalop.1416267589" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.warnings.logicalop" value="true" valueType="boolean"/> | |
233 | + <option id="ilg.gnuarmeclipse.managedbuild.cross.option.warnings.floatequal.2015684798" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.warnings.floatequal" value="true" valueType="boolean"/> | |
234 | + <option id="ilg.gnuarmeclipse.managedbuild.cross.option.warnings.padded.1699569031" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.warnings.padded" value="false" valueType="boolean"/> | |
222 | 235 | <targetPlatform archList="all" binaryParser="org.eclipse.cdt.core.ELF" id="ilg.gnuarmeclipse.managedbuild.cross.targetPlatform.773906421" isAbstract="false" osList="all" superClass="ilg.gnuarmeclipse.managedbuild.cross.targetPlatform"/> |
223 | 236 | <builder buildPath="${workspace_loc:/nRFHello}/Release" id="ilg.gnuarmeclipse.managedbuild.cross.builder.36652053" keepEnvironmentInBuildfile="false" managedBuildOn="true" name="Gnu Make ビルダー" superClass="ilg.gnuarmeclipse.managedbuild.cross.builder"/> |
224 | 237 | <tool id="ilg.gnuarmeclipse.managedbuild.cross.tool.assembler.342206795" name="GNU Arm Cross Assembler" superClass="ilg.gnuarmeclipse.managedbuild.cross.tool.assembler"> |
@@ -243,7 +256,12 @@ | ||
243 | 256 | </option> |
244 | 257 | <option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="ilg.gnuarmeclipse.managedbuild.cross.option.c.compiler.defs.644095446" name="定義済みシンボル (-D)" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.c.compiler.defs" useByScannerDiscovery="true" valueType="definedSymbols"> |
245 | 258 | <listOptionValue builtIn="false" value="NDEBUG"/> |
259 | + <listOptionValue builtIn="false" value="NRF52833_XXAA"/> | |
246 | 260 | </option> |
261 | + <option id="ilg.gnuarmeclipse.managedbuild.cross.option.c.compiler.otheroptimizations.1155659942" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.c.compiler.otheroptimizations" value="-fsingle-precision-constant" valueType="string"/> | |
262 | + <option id="ilg.gnuarmeclipse.managedbuild.cross.option.c.compiler.warning.missingprototypes.603782387" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.c.compiler.warning.missingprototypes" value="true" valueType="boolean"/> | |
263 | + <option id="ilg.gnuarmeclipse.managedbuild.cross.option.c.compiler.warning.strictprototypes.1934558844" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.c.compiler.warning.strictprototypes" value="true" valueType="boolean"/> | |
264 | + <option id="ilg.gnuarmeclipse.managedbuild.cross.option.c.compiler.warning.badfunctioncast.1880518477" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.c.compiler.warning.badfunctioncast" value="true" valueType="boolean"/> | |
247 | 265 | <inputType id="ilg.gnuarmeclipse.managedbuild.cross.tool.c.compiler.input.1426178694" superClass="ilg.gnuarmeclipse.managedbuild.cross.tool.c.compiler.input"/> |
248 | 266 | </tool> |
249 | 267 | <tool id="ilg.gnuarmeclipse.managedbuild.cross.tool.cpp.compiler.3867943" name="GNU Arm Cross C++ Compiler" superClass="ilg.gnuarmeclipse.managedbuild.cross.tool.cpp.compiler"> |
@@ -255,7 +273,9 @@ | ||
255 | 273 | </option> |
256 | 274 | <option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="ilg.gnuarmeclipse.managedbuild.cross.option.cpp.compiler.defs.1367930683" name="定義済みシンボル (-D)" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.cpp.compiler.defs" useByScannerDiscovery="true" valueType="definedSymbols"> |
257 | 275 | <listOptionValue builtIn="false" value="NDEBUG"/> |
276 | + <listOptionValue builtIn="false" value="NRF52833_XXAA"/> | |
258 | 277 | </option> |
278 | + <option id="ilg.gnuarmeclipse.managedbuild.cross.option.cpp.compiler.std.1900154255" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.cpp.compiler.std" value="ilg.gnuarmeclipse.managedbuild.cross.option.cpp.compiler.std.gnucpp14" valueType="enumerated"/> | |
259 | 279 | <inputType id="ilg.gnuarmeclipse.managedbuild.cross.tool.cpp.compiler.input.706143826" superClass="ilg.gnuarmeclipse.managedbuild.cross.tool.cpp.compiler.input"/> |
260 | 280 | </tool> |
261 | 281 | <tool id="ilg.gnuarmeclipse.managedbuild.cross.tool.c.linker.609428063" name="GNU Arm Cross C Linker" superClass="ilg.gnuarmeclipse.managedbuild.cross.tool.c.linker"> |
@@ -282,11 +302,13 @@ | ||
282 | 302 | </option> |
283 | 303 | <option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="ilg.gnuarmeclipse.managedbuild.cross.option.cpp.linker.scriptfile.366703270" name="スクリプト・ファイル (-T)" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.cpp.linker.scriptfile" valueType="stringList"> |
284 | 304 | <listOptionValue builtIn="false" value="mem.ld"/> |
285 | - <listOptionValue builtIn="false" value="libs.ld"/> | |
286 | 305 | <listOptionValue builtIn="false" value="sections.ld"/> |
287 | 306 | </option> |
288 | 307 | <option id="ilg.gnuarmeclipse.managedbuild.cross.option.cpp.linker.nostart.955404113" name="標準開始ファイルを使用しない (-nostartfiles)" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.cpp.linker.nostart" value="true" valueType="boolean"/> |
289 | 308 | <option id="ilg.gnuarmeclipse.managedbuild.cross.option.cpp.linker.usenewlibnano.628835414" name="Use newlib-nano (--specs=nano.specs)" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.cpp.linker.usenewlibnano" value="true" valueType="boolean"/> |
309 | + <option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="ilg.gnuarmeclipse.managedbuild.cross.option.cpp.linker.flags.240737852" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.cpp.linker.flags" valueType="stringList"> | |
310 | + <listOptionValue builtIn="false" value="--no-warn-rwx-segments"/> | |
311 | + </option> | |
290 | 312 | <inputType id="ilg.gnuarmeclipse.managedbuild.cross.tool.cpp.linker.input.1847511563" superClass="ilg.gnuarmeclipse.managedbuild.cross.tool.cpp.linker.input"> |
291 | 313 | <additionalInput kind="additionalinputdependency" paths="$(USER_OBJS)"/> |
292 | 314 | <additionalInput kind="additionalinput" paths="$(LIBS)"/> |
@@ -1,3 +1,4 @@ | ||
1 | 1 | /Debug/ |
2 | 2 | /src/html/ |
3 | 3 | /.settings/ |
4 | +/Release/ |
@@ -48,6 +48,8 @@ typedef enum PF_GPIO_ID_Tag | ||
48 | 48 | PF_GPIO_ID_INTERNAL_SDA, //!< 内部I2Cバス SDA |
49 | 49 | PF_GPIO_ID_EXTERNAL_SCL, //!< 外部I2Cバス SCL |
50 | 50 | PF_GPIO_ID_EXTERNAL_SDA, //!< 外部I2Cバス SDA |
51 | + PF_GPIO_ID_INTERNAL_SPEAKER, //!< 内部スピーカー | |
52 | + PF_GPIO_ID_MAQUEEN_SPEAKER, //!< MAQUEEN スピーカー | |
51 | 53 | PF_GPIO_ID_MAQUEEN_LED_L, //!< MAQUEEN LED L |
52 | 54 | PF_GPIO_ID_MAQUEEN_LED_R, //!< MAQUEEN LED R |
53 | 55 | PF_GPIO_ID_MAQUEEN_PATROL_L, //!< MAQUEEN PATROL L |
@@ -35,6 +35,7 @@ typedef enum PF_INTERRUPT_PRI_Tag | ||
35 | 35 | PF_INTERRUPT_PRI_DISPLAY_TIMER, //!< Display Timer |
36 | 36 | PF_INTERRUPT_PRI_I2C_INT, //!< I2C(内部) |
37 | 37 | PF_INTERRUPT_PRI_I2C_EXT, //!< I2C(外部) |
38 | + PF_INTERRUPT_PRI_MUSIC, //!< 音楽演奏 | |
38 | 39 | } PF_INTERRUPT_PRI; |
39 | 40 | |
40 | 41 | //! @brief グローバル割り込み禁止 |
@@ -33,7 +33,7 @@ typedef enum PF_MOTOR_DIR_Tag | ||
33 | 33 | PF_MOTOR_DIR_FORWARD, //!< 前進 |
34 | 34 | PF_MOTOR_DIR_LEFT, //!< 左回転 |
35 | 35 | PF_MOTOR_DIR_RIGHT, //!< 右回転 |
36 | - PF_MOTOR_DIR_BACKWORD, //!< 後進 | |
36 | + PF_MOTOR_DIR_BACKWARD, //!< 後進 | |
37 | 37 | PF_MOTOR_DIR_STOP, //!< 停止 |
38 | 38 | PF_MOTOR_DIR_MAX, //!< (方向の個数を表す) |
39 | 39 | } PF_MOTOR_DIR; |
@@ -48,7 +48,19 @@ void pf_motor_task(void); | ||
48 | 48 | |
49 | 49 | //! @brief モータ駆動 |
50 | 50 | //! @details モータ定期タスクで実際のモータ出力が行われる |
51 | +//! @details pf_motor_freeとは排他的に動作する | |
51 | 52 | //! @param [in] dir モータ駆動方向 |
52 | 53 | void pf_motor_drive(PF_MOTOR_DIR dir); |
53 | 54 | |
55 | +//! @brief モータ制御 | |
56 | +//! @details モータ定期タスクで実際のモータ出力が行われる | |
57 | +//! @details pf_motor_driveとは排他的に動作する | |
58 | +//! @param [in] left 左モータ駆動速度(0=停止) | |
59 | +//! @param [in] right 右モータ駆動速度(0=停止) | |
60 | +void pf_motor_ctrl(u1 left, u1 right); | |
61 | + | |
62 | +//! @brief モータ速度設定 | |
63 | +//! @param [in] speed モータ駆動速度(デフォルト=100) | |
64 | +void pf_motor_speed(u1 speed); | |
65 | + | |
54 | 66 | #endif // PF_MOTOR_H |
@@ -0,0 +1,49 @@ | ||
1 | +//! @file pf_music.h | |
2 | +//! @brief プラットフォーム(音楽演奏)ヘッダファイル | |
3 | + | |
4 | +// The MIT License (MIT) | |
5 | +// Copyright (c) 2023 @xm6_original | |
6 | +// | |
7 | +// Permission is hereby granted, free of charge, to any person obtaining a | |
8 | +// copy of this software and associated documentation files (the "Software"), | |
9 | +// to deal in the Software without restriction, including without limitation | |
10 | +// the rights to use, copy, modify, merge, publish, distribute, sublicense, | |
11 | +// and/or sell copies of the Software, and to permit persons to whom the | |
12 | +// Software is furnished to do so, subject to the following conditions: | |
13 | +// | |
14 | +// The above copyright notice and this permission notice shall be included in | |
15 | +// all copies or substantial portions of the Software. | |
16 | +// | |
17 | +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
18 | +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
19 | +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |
20 | +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
21 | +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |
22 | +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |
23 | +// DEALINGS IN THE SOFTWARE. | |
24 | + | |
25 | +#ifndef PF_MUSIC_H | |
26 | +#define PF_MUSIC_H | |
27 | + | |
28 | +#include "pf_types.h" | |
29 | + | |
30 | +//! @brief 音楽演奏デバイス | |
31 | +typedef enum PF_MUSIC_DEVICE_Tag | |
32 | +{ | |
33 | + PF_MUSIC_DEVICE_INTERNAL, //!< 内蔵スピーカー | |
34 | + PF_MUSIC_DEVICE_MAQUEEN, //!< MAQUEENスピーカー(スイッチでON/OFF可) | |
35 | + PF_MUSIC_DEVICE_MAX, //!< (デバイスの個数を表す) | |
36 | +} PF_MUSIC_DEVICE; | |
37 | + | |
38 | +//! @brief 音楽演奏初期化 | |
39 | +//! @remarks プラットフォーム初期化処理から呼び出すこと | |
40 | +//! @attention GPIO初期化およびTimer初期化の後に呼び出すこと | |
41 | +void pf_music_init(void); | |
42 | + | |
43 | +//! @brief 音楽演奏開始 | |
44 | +void pf_music_play(void); | |
45 | + | |
46 | +//! @brief 音楽演奏停止 | |
47 | +void pf_music_stop(void); | |
48 | + | |
49 | +#endif // PF_MUSIC_H |
@@ -54,6 +54,6 @@ void pf_patrol_task(void); | ||
54 | 54 | //! @brief ラインセンサの白黒状態を取得 |
55 | 55 | //! @param [in] id ラインセンサのID |
56 | 56 | //! @return 色状態(PF_PATROL_COLOR_WHITE=白色/PF_PATROL_COLOR_BLACK=黒色) |
57 | -PF_PATROL_COLOR pf_patrol_get(PF_PATROL_ID id); | |
57 | +PF_PATROL_COLOR pf_patrol_line(PF_PATROL_ID id); | |
58 | 58 | |
59 | 59 | #endif // PF_PATROL_H |
@@ -28,7 +28,7 @@ | ||
28 | 28 | #include "pf_types.h" |
29 | 29 | |
30 | 30 | //! @brief 制御周期[ms] |
31 | -#define PF_SYSTICK_SYNC_MS ((u4)10U) | |
31 | +#define PF_SYSTICK_SYNC_MS ((u4)5U) | |
32 | 32 | |
33 | 33 | //! @brief SysTick時刻情報構造体 |
34 | 34 | typedef struct PF_SYSTICK_TIME_Tag |
@@ -38,6 +38,7 @@ typedef void (*PF_TIMER_CALLBACK)(u4 eventbit); | ||
38 | 38 | typedef enum PF_TIMER_ID_Tag |
39 | 39 | { |
40 | 40 | PF_TIMER_ID_DISPLAY = 0, //!< ディスプレイタイマ |
41 | + PF_TIMER_ID_MUSIC, //!< 音楽 | |
41 | 42 | PF_TIMER_ID_MAX //!< (IDの個数を表す) |
42 | 43 | } PF_TIMER_ID; |
43 | 44 |
@@ -35,6 +35,7 @@ | ||
35 | 35 | #include "pf_led.h" |
36 | 36 | #include "pf_patrol.h" |
37 | 37 | #include "pf_motor.h" |
38 | +#include "pf_music.h" | |
38 | 39 | |
39 | 40 | //! @brief プラットフォーム初期化 |
40 | 41 | //! @attention 初期化順序に注意する |
@@ -59,6 +60,7 @@ static void pf_init(void) | ||
59 | 60 | pf_led_init(); |
60 | 61 | pf_patrol_init(); |
61 | 62 | pf_motor_init(); |
63 | + pf_music_init(); | |
62 | 64 | } |
63 | 65 | |
64 | 66 | //! @brief 定期タスク(入力系) |
@@ -77,92 +79,466 @@ static void pf_output_task(void) | ||
77 | 79 | pf_motor_task(); |
78 | 80 | } |
79 | 81 | |
80 | -static BOOL button_prev[2]; | |
81 | -static PF_DISPLAY_ID display_id; | |
82 | -static char display_ch = 0x20; | |
83 | -static PF_MOTOR_DIR motor_dir = 0; | |
82 | +//! @brief ボタン過去状態 | |
83 | +static BOOL app_button_prev[2]; | |
84 | 84 | |
85 | -//! @brief アプリケーションタスク | |
86 | -static void app_task(void) | |
85 | +//! @brief ボタンOFF→ONフラグ | |
86 | +static BOOL app_button_trigger[2]; | |
87 | + | |
88 | +//! @brief ボタンOFF→ON判定 | |
89 | +static void app_button_task(void) | |
87 | 90 | { |
88 | - BOOL button_now[2]; | |
91 | + BOOL button[2]; | |
89 | 92 | |
90 | - button_now[0] = pf_button_get(PF_BUTTON_ID_BUTTON_A); | |
91 | - button_now[1] = pf_button_get(PF_BUTTON_ID_BUTTON_B); | |
93 | + // トリガ初期化 | |
94 | + app_button_trigger[0] = FALSE; | |
95 | + app_button_trigger[1] = FALSE; | |
92 | 96 | |
93 | - if (button_now[0] != button_prev[0]) | |
97 | + // ボタン取得 | |
98 | + button[0] = pf_button_get(PF_BUTTON_ID_BUTTON_A); | |
99 | + button[1] = pf_button_get(PF_BUTTON_ID_BUTTON_B); | |
100 | + | |
101 | + // FALSE→TRUEへの変化でトリガON[0] | |
102 | + if ((FALSE == app_button_prev[0]) && (TRUE == button[0])) | |
94 | 103 | { |
95 | - if (button_now[0]) | |
96 | - { | |
97 | - pf_uart_log("Button A: OFF -> ON"); | |
104 | + app_button_trigger[0] = TRUE; | |
105 | + } | |
98 | 106 | |
99 | - // アイコン系 | |
100 | - pf_display_id(display_id); | |
101 | - display_id++; | |
102 | - if (display_id >= PF_DISPLAY_ID_MAX) | |
103 | - { | |
104 | - display_id = 0; | |
105 | - } | |
106 | - } | |
107 | - else | |
107 | + // FALSE→TRUEへの変化でトリガON[1] | |
108 | + if ((FALSE == app_button_prev[1]) && (TRUE == button[1])) | |
109 | + { | |
110 | + app_button_trigger[1] = TRUE; | |
111 | + } | |
112 | + | |
113 | + // 現在のボタン状態を記憶 | |
114 | + app_button_prev[0] = button[0]; | |
115 | + app_button_prev[1] = button[1]; | |
116 | +} | |
117 | + | |
118 | +//! @brief モード状態定義 | |
119 | +typedef enum APP_MODE_ID_Tag | |
120 | +{ | |
121 | + APP_MODE_ID_IDLE, //!< アイドル状態 | |
122 | + APP_MODE_ID_SQUARE, //!< 矩形走行状態 | |
123 | + APP_MODE_ID_LINE, //!< ライントレース状態 | |
124 | + APP_MODE_ID_MUSIC, //!< 音楽演奏切り替え状態 | |
125 | + APP_MODE_ID_MAX, //!< (IDの個数を表す) | |
126 | +} APP_MODE_ID; | |
127 | + | |
128 | +//! @brief モード状態遷移 | |
129 | +static APP_MODE_ID app_mode; | |
130 | + | |
131 | +//! @brief 走行状態遷移 | |
132 | +static BOOL app_run; | |
133 | + | |
134 | +//! @brief 音楽演奏状態遷移 | |
135 | +static BOOL app_play; | |
136 | + | |
137 | +//! @brief 走行状態ステップ | |
138 | +static u4 app_step; | |
139 | + | |
140 | +//! @brief 走行方向 | |
141 | +static PF_MOTOR_DIR app_dir; | |
142 | + | |
143 | +//! @brief アイドル時のディスプレイ個数 | |
144 | +#define APP_DISPLAY_MAX ((u4)10U) | |
145 | + | |
146 | +//! @brief アイドル時のディスプレイテーブル | |
147 | +static const PF_DISPLAY_ID app_display_idle[10] = | |
148 | +{ | |
149 | + PF_DISPLAY_ID_HEART, //!< ハート | |
150 | + PF_DISPLAY_ID_HAPPY, //!< HAPPY(嬉しい) | |
151 | + PF_DISPLAY_ID_SMILE, //!< SMILE(笑い) | |
152 | + PF_DISPLAY_ID_SAD, //!< SAD(悲しい) | |
153 | + PF_DISPLAY_ID_CONFUSED, //!< CONFUSED(混乱) | |
154 | + PF_DISPLAY_ID_ANGRY, //!< ANGRY(怒り) | |
155 | + PF_DISPLAY_ID_YES, //!< YES(チェックマーク) | |
156 | + PF_DISPLAY_ID_NO, //!< NO(×マーク) | |
157 | + PF_DISPALY_ID_TRIANGLE, //!< 三角形 | |
158 | + PF_DISPLAY_ID_CHESSBOARD, //!< チェスボード(縞模様) | |
159 | +}; | |
160 | + | |
161 | +//! @brief 走行時のディスプレイテーブル | |
162 | +static const PF_DISPLAY_ID app_display_run[5] = | |
163 | +{ | |
164 | + PF_DISPLAY_ID_ARROW_N, //!< 前進 | |
165 | + PF_DISPLAY_ID_ARROW_W, //!< 左回転 | |
166 | + PF_DISPLAY_ID_ARROW_E, //!< 右回転 | |
167 | + PF_DISPLAY_ID_ARROW_S, //!< 後進 | |
168 | + PF_DISPLAY_ID_YES, //!< 停止 | |
169 | +}; | |
170 | + | |
171 | +//! @brief 音楽停止時のイメージ | |
172 | +static const u1 app_display_musicoff[PF_DISPLAY_ROW_MAX * PF_DISPLAY_COL_MAX] = | |
173 | +{ | |
174 | + 0, 0, 1, 0, 0, | |
175 | + 0, 0, 1, 0, 0, | |
176 | + 0, 0, 1, 0, 0, | |
177 | + 1, 1, 1, 0, 0, | |
178 | + 1, 1, 1, 0, 0, | |
179 | +}; | |
180 | + | |
181 | +//! @brief 矩形走行単位構造体 | |
182 | +typedef struct APP_SQUARE_UNIT_Tag | |
183 | +{ | |
184 | + PF_MOTOR_DIR dir; //!< 駆動方向 | |
185 | + u4 cycle; //!< 動作周期 | |
186 | +} APP_SQUARE_UNIT; | |
187 | + | |
188 | +//! @brief 矩形走行テーブル | |
189 | +static const APP_SQUARE_UNIT app_square_table[9] = | |
190 | +{ | |
191 | + // 前進 | |
192 | + { | |
193 | + PF_MOTOR_DIR_FORWARD, | |
194 | + 240, | |
195 | + }, | |
196 | + | |
197 | + // 右回転 | |
198 | + { | |
199 | + PF_MOTOR_DIR_RIGHT, | |
200 | + 76, | |
201 | + }, | |
202 | + | |
203 | + // 前進 | |
204 | + { | |
205 | + PF_MOTOR_DIR_FORWARD, | |
206 | + 240, | |
207 | + }, | |
208 | + | |
209 | + // 左回転 | |
210 | + { | |
211 | + PF_MOTOR_DIR_LEFT, | |
212 | + 74, | |
213 | + }, | |
214 | + | |
215 | + // 後進 | |
216 | + { | |
217 | + PF_MOTOR_DIR_BACKWARD, | |
218 | + 240, | |
219 | + }, | |
220 | + | |
221 | + // 左回転 | |
222 | + { | |
223 | + PF_MOTOR_DIR_LEFT, | |
224 | + 72, | |
225 | + }, | |
226 | + | |
227 | + // 前進 | |
228 | + { | |
229 | + PF_MOTOR_DIR_FORWARD, | |
230 | + 240, | |
231 | + }, | |
232 | + | |
233 | + // 右回転 | |
234 | + { | |
235 | + PF_MOTOR_DIR_RIGHT, | |
236 | + 76, | |
237 | + }, | |
238 | + | |
239 | + // 終端 | |
240 | + { | |
241 | + PF_MOTOR_DIR_STOP, | |
242 | + 0, | |
243 | + }, | |
244 | +}; | |
245 | + | |
246 | +//! @brief モード状態遷移(Aボタンで遷移) | |
247 | +static void app_mode_task(void) | |
248 | +{ | |
249 | + // Aボタンで遷移 | |
250 | + if (TRUE == app_button_trigger[0]) | |
251 | + { | |
252 | + app_mode++; | |
253 | + if (app_mode >= APP_MODE_ID_MAX) | |
108 | 254 | { |
109 | - pf_uart_log("Button A: ON -> OFF\n"); | |
255 | + app_mode = 0; | |
110 | 256 | } |
257 | + | |
258 | + // 常に停止状態、ステップ戻す | |
259 | + app_run = FALSE; | |
260 | + app_step = 0; | |
111 | 261 | } |
112 | 262 | |
113 | - if (button_now[1] != button_prev[1]) | |
263 | + // Bボタンでトグル切り替え | |
264 | + if (TRUE == app_button_trigger[1]) | |
114 | 265 | { |
115 | - if (button_now[1]) | |
266 | + switch (app_mode) | |
116 | 267 | { |
117 | - pf_uart_log("Button B: OFF -> ON"); | |
268 | + // Bボタンでディスプレイ表示IDが変化する | |
269 | + case APP_MODE_ID_IDLE: | |
270 | + // ステップを上げる。APP_DISPLAY_MAXで1回転 | |
271 | + app_step++; | |
272 | + if (app_step >= APP_DISPLAY_MAX) | |
273 | + { | |
274 | + app_step = 0; | |
275 | + } | |
276 | + break; | |
118 | 277 | |
119 | - // キャラクタ系 | |
120 | - pf_display_ch(display_ch); | |
121 | - if (display_ch == 0x7F) | |
278 | + // Bボタンで音楽演奏⇔音楽停止のトグル切り替え | |
279 | + case APP_MODE_ID_MUSIC: | |
280 | + if (FALSE == app_play) | |
122 | 281 | { |
123 | - display_ch = 0x20; | |
282 | + app_play = TRUE; | |
124 | 283 | } |
125 | 284 | else |
126 | 285 | { |
127 | - display_ch++; | |
286 | + app_play = FALSE; | |
128 | 287 | } |
288 | + break; | |
129 | 289 | |
130 | - // モータ駆動 | |
131 | - pf_motor_drive(motor_dir); | |
132 | - motor_dir++; | |
133 | - if (motor_dir >= PF_MOTOR_DIR_MAX) | |
290 | + // Bボタンで走行モード⇔停止モードのトグル切り替え | |
291 | + default: | |
292 | + if (FALSE == app_run) | |
134 | 293 | { |
135 | - motor_dir = 0; | |
294 | + app_run = TRUE; | |
136 | 295 | } |
296 | + else | |
297 | + { | |
298 | + app_run = FALSE; | |
299 | + } | |
300 | + | |
301 | + // ステップを戻す | |
302 | + app_step = 0; | |
303 | + break; | |
304 | + } | |
305 | + } | |
306 | +} | |
307 | + | |
308 | +//! @brief ディスプレイ表示 | |
309 | +static void app_display_task(void) | |
310 | +{ | |
311 | + // モードに応じたディスプレイ表示 | |
312 | + switch (app_mode) | |
313 | + { | |
314 | + // アイドル状態 | |
315 | + case APP_MODE_ID_IDLE: | |
316 | + pf_display_id(app_display_idle[app_step]); | |
317 | + break; | |
318 | + | |
319 | + // 音楽演奏切り替え状態 | |
320 | + case APP_MODE_ID_MUSIC: | |
321 | + if (FALSE == app_play) | |
322 | + { | |
323 | + pf_display_image(app_display_musicoff); | |
137 | 324 | } |
138 | 325 | else |
139 | 326 | { |
140 | - pf_uart_log("Button B: ON -> OFF\n"); | |
327 | + pf_display_id(PF_DISPLAY_ID_MUSIC); | |
141 | 328 | } |
329 | + break; | |
330 | + | |
331 | + // 走行状態 | |
332 | + case APP_MODE_ID_SQUARE: | |
333 | + if (FALSE == app_run) | |
334 | + { | |
335 | + pf_display_id(PF_DISPLAY_ID_SQUARE); | |
336 | + } | |
337 | + else | |
338 | + { | |
339 | + pf_display_id(app_display_run[app_dir]); | |
340 | + } | |
341 | + break; | |
342 | + | |
343 | + case APP_MODE_ID_LINE: | |
344 | + if (FALSE == app_run) | |
345 | + { | |
346 | + pf_display_id(PF_DISPLAY_ID_DIAMOND); | |
347 | + } | |
348 | + else | |
349 | + { | |
350 | + pf_display_id(app_display_run[app_dir]); | |
351 | + } | |
352 | + break; | |
353 | + | |
354 | + default: | |
355 | + break; | |
142 | 356 | } |
357 | +} | |
358 | + | |
359 | +//! @brief LED表示 | |
360 | +static void app_led_task(void) | |
361 | +{ | |
362 | + PF_PATROL_COLOR left; | |
363 | + PF_PATROL_COLOR right; | |
143 | 364 | |
144 | - // ラインセンサとLEDの連携制御(黒色で点灯、白色で消灯) | |
145 | - if (PF_PATROL_COLOR_BLACK == pf_patrol_get(PF_PATROL_ID_L)) | |
365 | + // 取得 | |
366 | + left = pf_patrol_line(PF_PATROL_ID_L); | |
367 | + right = pf_patrol_line(PF_PATROL_ID_R); | |
368 | + | |
369 | + // stepが32の倍数(160ms)で点滅 | |
370 | + if (app_step & 0x0020) | |
146 | 371 | { |
147 | - pf_led_ctrl(PF_LED_ID_L, TRUE); | |
372 | + // 常に消灯 | |
373 | + pf_led_ctrl(PF_LED_ID_L, FALSE); | |
374 | + pf_led_ctrl(PF_LED_ID_R, FALSE); | |
148 | 375 | } |
149 | 376 | else |
150 | 377 | { |
151 | - pf_led_ctrl(PF_LED_ID_L, FALSE); | |
378 | + // 白色で点灯(左) | |
379 | + if (PF_PATROL_COLOR_WHITE == left) | |
380 | + { | |
381 | + pf_led_ctrl(PF_LED_ID_L, TRUE); | |
382 | + } | |
383 | + else | |
384 | + { | |
385 | + pf_led_ctrl(PF_LED_ID_L, FALSE); | |
386 | + } | |
387 | + | |
388 | + // 白色で点灯(右) | |
389 | + if (PF_PATROL_COLOR_WHITE == right) | |
390 | + { | |
391 | + pf_led_ctrl(PF_LED_ID_R, TRUE); | |
392 | + } | |
393 | + else | |
394 | + { | |
395 | + pf_led_ctrl(PF_LED_ID_R, FALSE); | |
396 | + } | |
397 | + } | |
398 | +} | |
399 | + | |
400 | +//! @brief 走行(矩形) | |
401 | +static void app_run_square(void) | |
402 | +{ | |
403 | + const APP_SQUARE_UNIT *unit; | |
404 | + u4 step; | |
405 | + BOOL next; | |
406 | + | |
407 | + // オート変数初期化 | |
408 | + unit = &app_square_table[0]; | |
409 | + step = app_step; | |
410 | + next = TRUE; | |
411 | + | |
412 | + // 現在のapp_stepより、適切なunitを割り出す | |
413 | + while (step >= unit->cycle) | |
414 | + { | |
415 | + // unitを進める | |
416 | + step -= unit->cycle; | |
417 | + unit++; | |
418 | + | |
419 | + // unitが終端に来たら、巻き戻す | |
420 | + if (0 == unit->cycle) | |
421 | + { | |
422 | + unit = &app_square_table[0]; | |
423 | + next = FALSE; | |
424 | + } | |
152 | 425 | } |
153 | 426 | |
154 | - if (PF_PATROL_COLOR_BLACK == pf_patrol_get(PF_PATROL_ID_R)) | |
427 | + // nextフラグでapp_stepを更新 | |
428 | + if (TRUE == next) | |
155 | 429 | { |
156 | - pf_led_ctrl(PF_LED_ID_R, TRUE); | |
430 | + app_step++; | |
157 | 431 | } |
158 | 432 | else |
159 | 433 | { |
160 | - pf_led_ctrl(PF_LED_ID_R, FALSE); | |
434 | + app_step = 0; | |
161 | 435 | } |
162 | 436 | |
163 | - // ボタン情報を更新 | |
164 | - button_prev[0] = button_now[0]; | |
165 | - button_prev[1] = button_now[1]; | |
437 | + // 方向決定 | |
438 | + app_dir = unit->dir; | |
439 | + pf_motor_drive(app_dir); | |
440 | +} | |
441 | + | |
442 | +//! @brief 走行(ライントレース) | |
443 | +static void app_run_line(void) | |
444 | +{ | |
445 | + PF_PATROL_COLOR left; | |
446 | + PF_PATROL_COLOR right; | |
447 | + PF_MOTOR_DIR dir; | |
448 | + | |
449 | + // オート変数初期化 | |
450 | + left = PF_PATROL_COLOR_WHITE; | |
451 | + right = PF_PATROL_COLOR_WHITE; | |
452 | + dir = PF_MOTOR_DIR_BACKWARD; | |
453 | + | |
454 | + // 取得 | |
455 | + left = pf_patrol_line(PF_PATROL_ID_L); | |
456 | + right = pf_patrol_line(PF_PATROL_ID_R); | |
457 | + | |
458 | + // 共に白色で前進 | |
459 | + if ((PF_PATROL_COLOR_WHITE == left) && (PF_PATROL_COLOR_WHITE == right)) | |
460 | + { | |
461 | + dir = PF_MOTOR_DIR_FORWARD; | |
462 | + } | |
463 | + | |
464 | + // 左が黒色なら左回転 | |
465 | + if ((PF_PATROL_COLOR_BLACK == left) && (PF_PATROL_COLOR_WHITE == right)) | |
466 | + { | |
467 | + dir = PF_MOTOR_DIR_LEFT; | |
468 | + } | |
469 | + | |
470 | + // 右が黒色なら左回転 | |
471 | + if ((PF_PATROL_COLOR_WHITE == left) && (PF_PATROL_COLOR_BLACK == right)) | |
472 | + { | |
473 | + dir = PF_MOTOR_DIR_RIGHT; | |
474 | + } | |
475 | + | |
476 | + // モータ速度(後進のみ遅い) | |
477 | + if (PF_MOTOR_DIR_BACKWARD == dir) | |
478 | + { | |
479 | + pf_motor_speed(50); | |
480 | + } | |
481 | + else | |
482 | + { | |
483 | + pf_motor_speed(100); | |
484 | + } | |
485 | + | |
486 | + // モータ設定 | |
487 | + app_dir = dir; | |
488 | + pf_motor_drive(app_dir); | |
489 | + | |
490 | + // ステップ更新処理 | |
491 | + app_step++; | |
492 | +} | |
493 | + | |
494 | +//! @brief アプリケーションタスク | |
495 | +static void app_task(void) | |
496 | +{ | |
497 | + BOOL run; | |
498 | + | |
499 | + // オート変数初期化 | |
500 | + run = FALSE; | |
501 | + | |
502 | + // ボタン | |
503 | + app_button_task(); | |
504 | + | |
505 | + // モード切替 | |
506 | + app_mode_task(); | |
507 | + | |
508 | + // ディスプレイ表示 | |
509 | + app_display_task(); | |
510 | + | |
511 | + // LED表示 | |
512 | + app_led_task(); | |
513 | + | |
514 | + // 走行(矩形) | |
515 | + if ((APP_MODE_ID_SQUARE == app_mode) && (TRUE == app_run)) | |
516 | + { | |
517 | + app_run_square(); | |
518 | + run = TRUE; | |
519 | + } | |
520 | + | |
521 | + // 走行(ライントレース) | |
522 | + if ((APP_MODE_ID_LINE == app_mode) && (TRUE == app_run)) | |
523 | + { | |
524 | + app_run_line(); | |
525 | + run = TRUE; | |
526 | + } | |
527 | + | |
528 | + // 走行状態以外なら停止 | |
529 | + if (FALSE == run) | |
530 | + { | |
531 | + pf_motor_drive(PF_MOTOR_DIR_STOP); | |
532 | + pf_music_stop(); | |
533 | + } | |
534 | + else | |
535 | + { | |
536 | + // 音楽演奏フラグに従い演奏 | |
537 | + if (TRUE == app_play) | |
538 | + { | |
539 | + pf_music_play(); | |
540 | + } | |
541 | + } | |
166 | 542 | } |
167 | 543 | |
168 | 544 | //! @brief メインプログラム |
@@ -27,7 +27,7 @@ | ||
27 | 27 | #include "pf_button.h" |
28 | 28 | |
29 | 29 | //! @brief チャタリング防止のためのフィルタ段数(最低2段以上にすること) |
30 | -#define PF_BUTTON_FILTER_MAX ((u4)3U) | |
30 | +#define PF_BUTTON_FILTER_MAX ((u4)5U) | |
31 | 31 | |
32 | 32 | //! @brief ボタン→GPIO IDテーブル |
33 | 33 | static const PF_GPIO_ID pf_button_to_gpio[PF_BUTTON_ID_MAX] = |
@@ -74,7 +74,6 @@ typedef struct PF_GPIO_INIT_Tag | ||
74 | 74 | } PF_GPIO_INIT; |
75 | 75 | |
76 | 76 | //! @brief GPIOピン初期化情報テーブル |
77 | -//! @todo 未使用ピンがすべてプルアップ有効の入力にするよう設定すること | |
78 | 77 | const PF_GPIO_INIT pf_gpio_init_table[PF_GPIO_ID_MAX] = |
79 | 78 | { |
80 | 79 | // PF_GPIO_ID_UART_TXD |
@@ -276,6 +275,28 @@ const PF_GPIO_INIT pf_gpio_init_table[PF_GPIO_ID_MAX] = | ||
276 | 275 | PF_GPIO_DRIVE_S0D1, // 駆動特性 |
277 | 276 | }, |
278 | 277 | |
278 | + // PF_GPIO_ID_INTERNAL_SPEAKER | |
279 | + { | |
280 | + 0, // ポート | |
281 | + 0, // ピン | |
282 | + FALSE, // 初期出力レベル | |
283 | + PF_GPIO_DIR_OUTPUT, // 入出力方向 | |
284 | + PF_GPIO_INBUF_DISCONNECT, // 入力バッファ | |
285 | + PF_GPIO_PULL_NONE, // プルアップ・プルダウン | |
286 | + PF_GPIO_DRIVE_S0S1, // 駆動特性 | |
287 | + }, | |
288 | + | |
289 | + // PF_GPIO_ID_MAQUEEN_SPEAKER | |
290 | + { | |
291 | + 0, // ポート | |
292 | + 2, // ピン | |
293 | + FALSE, // 初期出力レベル | |
294 | + PF_GPIO_DIR_OUTPUT, // 入出力方向 | |
295 | + PF_GPIO_INBUF_DISCONNECT, // 入力バッファ | |
296 | + PF_GPIO_PULL_NONE, // プルアップ・プルダウン | |
297 | + PF_GPIO_DRIVE_S0S1, // 駆動特性 | |
298 | + }, | |
299 | + | |
279 | 300 | // PF_GPIO_ID_MAQUEEN_LED_L |
280 | 301 | { |
281 | 302 | 0, // ポート |
@@ -62,7 +62,7 @@ static const PF_I2C_ADDR pf_i2c_addr_table[PF_I2C_ID_MAX] = | ||
62 | 62 | }; |
63 | 63 | |
64 | 64 | //! @brief I2C動作情報構造体 |
65 | -typedef struct PF_I2C_STATUS_Tag | |
65 | +typedef struct PF_I2C_INFO_Tag | |
66 | 66 | { |
67 | 67 | PF_I2C_CALLBACK callback; //!< コールバック関数 |
68 | 68 | BOOL busy; //!< BUSYフラグ |
@@ -71,10 +71,10 @@ typedef struct PF_I2C_STATUS_Tag | ||
71 | 71 | u4 anack; //!< アドレスNACK発生回数 |
72 | 72 | u4 dnack; //!< データNACK発生回数 |
73 | 73 | u1 reg; //!< 受信レジスタ |
74 | -} PF_I2C_STATUS; | |
74 | +} PF_I2C_INFO; | |
75 | 75 | |
76 | 76 | //! @brief I2C動作情報テーブル |
77 | -static PF_I2C_STATUS pf_i2c_status[PF_I2C_ID_MAX]; | |
77 | +static PF_I2C_INFO pf_i2c_info[PF_I2C_ID_MAX]; | |
78 | 78 | |
79 | 79 | //! @brief I2Cチャネル→デバイステーブル |
80 | 80 | static NRF_TWIM_Type* const pf_i2c_channel_to_dev[PF_I2C_CHANNEL_MAX] = |
@@ -149,7 +149,7 @@ static BOOL pf_i2c_get_busy(u4 channel) | ||
149 | 149 | if (channel == pf_i2c_addr_table[id].channel) |
150 | 150 | { |
151 | 151 | // BUSYであれば |
152 | - if (TRUE == pf_i2c_status[id].busy) | |
152 | + if (TRUE == pf_i2c_info[id].busy) | |
153 | 153 | { |
154 | 154 | // そのチャネルはBUSY |
155 | 155 | busy = TRUE; |
@@ -179,7 +179,7 @@ static PF_I2C_ID pf_i2c_get_id(u4 channel) | ||
179 | 179 | if (channel == pf_i2c_addr_table[id].channel) |
180 | 180 | { |
181 | 181 | // BUSYであれば |
182 | - if (TRUE == pf_i2c_status[id].busy) | |
182 | + if (TRUE == pf_i2c_info[id].busy) | |
183 | 183 | { |
184 | 184 | // このIDが該当する |
185 | 185 | break; |
@@ -195,18 +195,18 @@ static PF_I2C_ID pf_i2c_get_id(u4 channel) | ||
195 | 195 | static void pf_i2c_init_id(PF_I2C_ID id) |
196 | 196 | { |
197 | 197 | // コールバック関数なし |
198 | - pf_i2c_status[id].callback = NULL; | |
198 | + pf_i2c_info[id].callback = NULL; | |
199 | 199 | |
200 | 200 | // デバイスREADY |
201 | - pf_i2c_status[id].busy = FALSE; | |
201 | + pf_i2c_info[id].busy = FALSE; | |
202 | 202 | |
203 | 203 | // エラーなし |
204 | - pf_i2c_status[id].overrun = 0; | |
205 | - pf_i2c_status[id].anack = 0; | |
206 | - pf_i2c_status[id].dnack = 0; | |
204 | + pf_i2c_info[id].overrun = 0; | |
205 | + pf_i2c_info[id].anack = 0; | |
206 | + pf_i2c_info[id].dnack = 0; | |
207 | 207 | |
208 | 208 | // 受信レジスタ0 |
209 | - pf_i2c_status[id].reg = 0; | |
209 | + pf_i2c_info[id].reg = 0; | |
210 | 210 | } |
211 | 211 | |
212 | 212 | //! @brief I2C初期化(デバイス) |
@@ -371,13 +371,13 @@ BOOL pf_i2c_send(PF_I2C_ID id, const u1 *buf, u4 bytes) | ||
371 | 371 | if (FALSE == busy) |
372 | 372 | { |
373 | 373 | // 通信成功に初期化 |
374 | - pf_i2c_status[id].status = TRUE; | |
374 | + pf_i2c_info[id].status = TRUE; | |
375 | 375 | |
376 | 376 | // 送信開始 |
377 | 377 | pf_i2c_send_dev(channel, pf_i2c_addr_table[id].addr, buf, bytes); |
378 | 378 | |
379 | 379 | // BUSYへ変更 |
380 | - pf_i2c_status[id].busy = TRUE; | |
380 | + pf_i2c_info[id].busy = TRUE; | |
381 | 381 | |
382 | 382 | // 送信開始に成功した |
383 | 383 | result = TRUE; |
@@ -463,17 +463,16 @@ BOOL pf_i2c_recv(PF_I2C_ID id, u1 reg, u1 *buf, u4 bytes) | ||
463 | 463 | if (FALSE == busy) |
464 | 464 | { |
465 | 465 | // 受信レジスタを記憶 |
466 | - pf_i2c_status[id].reg = reg; | |
466 | + pf_i2c_info[id].reg = reg; | |
467 | 467 | |
468 | 468 | // 通信成功に初期化 |
469 | - pf_i2c_status[id].status = TRUE; | |
469 | + pf_i2c_info[id].status = TRUE; | |
470 | 470 | |
471 | 471 | // 送受信開始 |
472 | - pf_i2c_recv_dev(channel, pf_i2c_addr_table[id].addr, &pf_i2c_status[id].reg, buf, | |
473 | - bytes); | |
472 | + pf_i2c_recv_dev(channel, pf_i2c_addr_table[id].addr, &pf_i2c_info[id].reg, buf, bytes); | |
474 | 473 | |
475 | 474 | // BUSYへ変更 |
476 | - pf_i2c_status[id].busy = TRUE; | |
475 | + pf_i2c_info[id].busy = TRUE; | |
477 | 476 | |
478 | 477 | // 送受信開始に成功した |
479 | 478 | result = TRUE; |
@@ -510,14 +509,14 @@ void pf_i2c_error(PF_I2C_ID id, PF_I2C_ERROR *error) | ||
510 | 509 | enable = pf_i2c_interrupt_disable(channel); |
511 | 510 | |
512 | 511 | // エラー情報を転送 |
513 | - error->overrun = pf_i2c_status[id].overrun; | |
514 | - error->anack = pf_i2c_status[id].anack; | |
515 | - error->dnack = pf_i2c_status[id].dnack; | |
512 | + error->overrun = pf_i2c_info[id].overrun; | |
513 | + error->anack = pf_i2c_info[id].anack; | |
514 | + error->dnack = pf_i2c_info[id].dnack; | |
516 | 515 | |
517 | 516 | // プラットフォーム内部のエラー情報をクリア |
518 | - pf_i2c_status[id].overrun = 0; | |
519 | - pf_i2c_status[id].anack = 0; | |
520 | - pf_i2c_status[id].dnack = 0; | |
517 | + pf_i2c_info[id].overrun = 0; | |
518 | + pf_i2c_info[id].anack = 0; | |
519 | + pf_i2c_info[id].dnack = 0; | |
521 | 520 | |
522 | 521 | // I2C割り込み復元 |
523 | 522 | pf_i2c_interrupt_restore(channel, enable); |
@@ -547,7 +546,7 @@ void pf_i2c_callback(PF_I2C_ID id, PF_I2C_CALLBACK func) | ||
547 | 546 | enable = pf_i2c_interrupt_disable(channel); |
548 | 547 | |
549 | 548 | // コールバック関数設定 |
550 | - pf_i2c_status[id].callback = func; | |
549 | + pf_i2c_info[id].callback = func; | |
551 | 550 | |
552 | 551 | // I2C割り込み復元 |
553 | 552 | pf_i2c_interrupt_restore(channel, enable); |
@@ -568,12 +567,12 @@ static void pf_i2c_isr_stopped(u4 channel) | ||
568 | 567 | id = pf_i2c_get_id(channel); |
569 | 568 | |
570 | 569 | // 通信終了 |
571 | - pf_i2c_status[id].busy = FALSE; | |
570 | + pf_i2c_info[id].busy = FALSE; | |
572 | 571 | |
573 | 572 | // I2Cコールバック関数が登録されていれば、呼び出す |
574 | - if (NULL != pf_i2c_status[id].callback) | |
573 | + if (NULL != pf_i2c_info[id].callback) | |
575 | 574 | { |
576 | - pf_i2c_status[id].callback(pf_i2c_status[id].status); | |
575 | + pf_i2c_info[id].callback(pf_i2c_info[id].status); | |
577 | 576 | } |
578 | 577 | } |
579 | 578 |
@@ -599,13 +598,13 @@ static void pf_i2c_isr_error(u4 channel) | ||
599 | 598 | id = pf_i2c_get_id(channel); |
600 | 599 | |
601 | 600 | // 通信エラーあり |
602 | - pf_i2c_status[id].status = FALSE; | |
601 | + pf_i2c_info[id].status = FALSE; | |
603 | 602 | |
604 | 603 | // エラー種別判定(ANACK) |
605 | 604 | if (anack == (dev->ERRORSRC & anack)) |
606 | 605 | { |
607 | 606 | // ANACK発生。'1'を書き込むことでクリアする |
608 | - pf_i2c_status[id].anack++; | |
607 | + pf_i2c_info[id].anack++; | |
609 | 608 | dev->ERRORSRC = anack; |
610 | 609 | } |
611 | 610 |
@@ -613,7 +612,7 @@ static void pf_i2c_isr_error(u4 channel) | ||
613 | 612 | if (dnack == (dev->ERRORSRC & dnack)) |
614 | 613 | { |
615 | 614 | // DNACK発生。'1'を書き込むことでクリアする |
616 | - pf_i2c_status[id].dnack++; | |
615 | + pf_i2c_info[id].dnack++; | |
617 | 616 | dev->ERRORSRC = dnack; |
618 | 617 | } |
619 | 618 |
@@ -621,7 +620,7 @@ static void pf_i2c_isr_error(u4 channel) | ||
621 | 620 | if (overrun == (dev->ERRORSRC & overrun)) |
622 | 621 | { |
623 | 622 | // オーバーラン発生。'0'を書き込むことでクリアする |
624 | - pf_i2c_status[id].overrun++; | |
623 | + pf_i2c_info[id].overrun++; | |
625 | 624 | dev->ERRORSRC = TWIM_ERRORSRC_OVERRUN_NotReceived << TWIM_ERRORSRC_OVERRUN_Pos; |
626 | 625 | } |
627 | 626 |
@@ -41,6 +41,10 @@ u4 pf_interrupt_global_disable(void) | ||
41 | 41 | // 割り込み禁止 |
42 | 42 | __disable_irq(); |
43 | 43 | |
44 | + // メモリバリア・命令バリア(念のため) | |
45 | + __DSB(); | |
46 | + __ISB(); | |
47 | + | |
44 | 48 | return primask; |
45 | 49 | } |
46 | 50 |
@@ -89,6 +93,11 @@ static IRQn_Type pf_interrupt_get_irq(PF_INTERRUPT_PRI pri) | ||
89 | 93 | irq = SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1_IRQn; |
90 | 94 | break; |
91 | 95 | |
96 | + // 音楽演奏 | |
97 | + case PF_INTERRUPT_PRI_MUSIC: | |
98 | + irq = TIMER1_IRQn; | |
99 | + break; | |
100 | + | |
92 | 101 | default: |
93 | 102 | break; |
94 | 103 | } |
@@ -27,6 +27,9 @@ | ||
27 | 27 | #include "pf_i2c.h" |
28 | 28 | #include "pf_motor.h" |
29 | 29 | |
30 | +//! @brief I2C常時送信動作(TRUE=常時送信/FALSE=キャッシュ動作) | |
31 | +#define PF_MOTOR_I2C_ANY (TRUE) | |
32 | + | |
30 | 33 | //! @brief モータ速度(デフォルト) |
31 | 34 | #define PF_MOTOR_DEFAULT_SPEED ((u1)100U) |
32 | 35 |
@@ -45,6 +48,9 @@ | ||
45 | 48 | //! @brief 回転方向(後回転) |
46 | 49 | #define PF_MOTOR_MOVE_BACKWARD ((u1)0x01U) |
47 | 50 | |
51 | +//! @brief 回転方向(不定値) | |
52 | +#define PF_MOTOR_MOVE_UNFORMATTED ((u1)0xFFU) | |
53 | + | |
48 | 54 | //! @brief 動作速度(駆動) |
49 | 55 | #define PF_MOTOR_SPEED_DRIVE ((u1)0x01U) |
50 | 56 |
@@ -60,16 +66,16 @@ typedef enum PF_MOTOR_I2C_Tag | ||
60 | 66 | PF_MOTOR_I2C_MAX, //!< (バッファのサイズを表す) |
61 | 67 | } PF_MOTOR_I2C; |
62 | 68 | |
63 | -//! @brief モータ駆動情報構造体 | |
64 | -typedef struct PF_MOTOR_DIR_INFO_Tag | |
69 | +//! @brief I2C通信パケット構造体 | |
70 | +typedef struct PF_MOTOR_I2C_PACKET_Tag | |
65 | 71 | { |
66 | 72 | u1 channel; //!< チャネル |
67 | 73 | u1 direction; //!< 駆動方向 |
68 | 74 | u1 speed; //!< 動作速度 |
69 | -} PF_MOTOR_DIR_INFO; | |
75 | +} PF_MOTOR_I2C_PACKET; | |
70 | 76 | |
71 | -//! @brief モータ駆動方向→モータ駆動情報テーブル | |
72 | -static const PF_MOTOR_DIR_INFO pf_motor_dir_to_info[PF_MOTOR_DIR_MAX][PF_MOTOR_CHANNEL_MAX] = | |
77 | +//! @brief 駆動方向→I2C通信パケットテーブル | |
78 | +static const PF_MOTOR_I2C_PACKET pf_motor_dir_to_packet[PF_MOTOR_DIR_MAX][PF_MOTOR_CHANNEL_MAX] = | |
73 | 79 | { |
74 | 80 | // PF_MOTOR_DIR_FORWARD |
75 | 81 | { |
@@ -157,42 +163,59 @@ static const PF_MOTOR_DIR_INFO pf_motor_dir_to_info[PF_MOTOR_DIR_MAX][PF_MOTOR_C | ||
157 | 163 | }, |
158 | 164 | }; |
159 | 165 | |
160 | -//! @brief I2C通信バッファ | |
161 | -static u1 pf_motor_buf[PF_MOTOR_CHANNEL_MAX][PF_MOTOR_I2C_MAX]; | |
162 | - | |
163 | -//! @brief 現在のモータ駆動方向 | |
164 | -static PF_MOTOR_DIR pf_motor_current_dir; | |
165 | - | |
166 | -//! @brief 次回のモータ駆動方向 | |
167 | -static PF_MOTOR_DIR pf_motor_next_dir; | |
168 | - | |
169 | -//! @brief 現在のモータ速度 | |
170 | -static u1 pf_motor_current_speed; | |
171 | - | |
172 | -//! @brief 現在の送信中チャネル | |
173 | -static u4 pf_motor_current_channel; | |
166 | +//! @brief モータ動作情報構造体 | |
167 | +typedef struct PF_MOTOR_INFO_Tag | |
168 | +{ | |
169 | + PF_MOTOR_DIR dir; //!< 現在の駆動方向 | |
170 | + u4 channel; //!< 送信中チャネル | |
171 | + BOOL free; //!< フリー動作フラグ | |
172 | + u1 speed; //!< 駆動速度(フリー動作以外) | |
173 | + u1 left; //!< 駆動速度(フリー動作L) | |
174 | + u1 right; //!< 駆動速度(フリー動作R) | |
175 | + u1 buf[PF_MOTOR_CHANNEL_MAX][PF_MOTOR_I2C_MAX]; //!< I2C通信バッファ(送信中) | |
176 | + u1 i2c[PF_MOTOR_CHANNEL_MAX][PF_MOTOR_I2C_MAX]; //!< I2C通信バッファ(送信完了) | |
177 | +} PF_MOTOR_INFO; | |
178 | + | |
179 | +// モータ動作情報 | |
180 | +static PF_MOTOR_INFO pf_motor_info; | |
174 | 181 | |
175 | 182 | //! @brief I2Cからのコールバック関数 |
176 | 183 | //! @param [in] status 通信ステータス(TRUE=成功/FALSE=失敗) |
177 | 184 | static void pf_motor_callback(BOOL status) |
178 | 185 | { |
186 | + u4 loop; | |
187 | + | |
188 | + // オート変数初期化 | |
189 | + loop = 0; | |
190 | + | |
179 | 191 | // 成功の場合 |
180 | 192 | if (TRUE == status) |
181 | 193 | { |
182 | 194 | // 送信中チャネルをインクリメント |
183 | - pf_motor_current_channel++; | |
195 | + pf_motor_info.channel++; | |
184 | 196 | |
185 | 197 | // 送信中チャネルが最大値に達しているか |
186 | - if (pf_motor_current_channel < PF_MOTOR_CHANNEL_MAX) | |
198 | + if (pf_motor_info.channel < PF_MOTOR_CHANNEL_MAX) | |
187 | 199 | { |
188 | - // 次の送信をスタート | |
189 | - (void)pf_i2c_send(PF_I2C_ID_MAQUEEN_MOTOR, &pf_motor_buf[pf_motor_current_channel][0], | |
200 | + // 次のI2C送信をスタート | |
201 | + (void)pf_i2c_send(PF_I2C_ID_MAQUEEN_MOTOR, &pf_motor_info.buf[pf_motor_info.channel][0], | |
190 | 202 | PF_MOTOR_I2C_MAX); |
191 | 203 | } |
192 | 204 | else |
193 | 205 | { |
194 | - // すべてのチャネルを送信完了したので、更新 | |
195 | - pf_motor_current_dir = pf_motor_next_dir; | |
206 | + // すべてのチャネルが正常送信できた | |
207 | + if (FALSE == pf_motor_info.free) | |
208 | + { | |
209 | + // チャネル数ループ | |
210 | + for (loop = 0; loop < PF_MOTOR_CHANNEL_MAX; loop++) | |
211 | + { | |
212 | + // pf_motor_info.bufをpf_motor_info.i2cへコピー(回転方向と速度のみ) | |
213 | + pf_motor_info.i2c[loop][PF_MOTOR_I2C_MOVE] = | |
214 | + pf_motor_info.buf[loop][PF_MOTOR_I2C_MOVE]; | |
215 | + pf_motor_info.i2c[loop][PF_MOTOR_I2C_SPEED] = | |
216 | + pf_motor_info.buf[loop][PF_MOTOR_I2C_SPEED]; | |
217 | + } | |
218 | + } | |
196 | 219 | } |
197 | 220 | } |
198 | 221 | } |
@@ -201,20 +224,97 @@ static void pf_motor_callback(BOOL status) | ||
201 | 224 | //! @remarks プラットフォーム初期化処理から呼び出すこと |
202 | 225 | void pf_motor_init(void) |
203 | 226 | { |
204 | - // モータ駆動方向: 停止 | |
205 | - pf_motor_current_dir = PF_MOTOR_DIR_STOP; | |
206 | - pf_motor_next_dir = PF_MOTOR_DIR_STOP; | |
227 | + u4 loop; | |
228 | + | |
229 | + // オート変数初期化 | |
230 | + loop = 0; | |
231 | + | |
232 | + // モータ駆動方向 | |
233 | + pf_motor_info.dir = PF_MOTOR_DIR_STOP; | |
234 | + | |
235 | + // 送信中チャネル | |
236 | + pf_motor_info.channel = 0; | |
237 | + | |
238 | + // フリー動作フラグ | |
239 | + pf_motor_info.free = FALSE; | |
240 | + | |
241 | + // 駆動速度(フリー動作以外) | |
242 | + pf_motor_info.speed = PF_MOTOR_DEFAULT_SPEED; | |
243 | + | |
244 | + // 駆動速度(フリー動作) | |
245 | + pf_motor_info.left = PF_MOTOR_DEFAULT_SPEED; | |
246 | + pf_motor_info.right = PF_MOTOR_DEFAULT_SPEED; | |
207 | 247 | |
208 | - // モータ速度: デフォルト | |
209 | - pf_motor_current_speed = PF_MOTOR_DEFAULT_SPEED; | |
248 | + // I2C通信バッファ(送信完了) | |
249 | + for (loop = 0; loop < PF_MOTOR_CHANNEL_MAX; loop++) | |
250 | + { | |
251 | + // 回転方向を不定値とすることで、初回送信が確実に行われるようにする | |
252 | + pf_motor_info.i2c[loop][PF_MOTOR_I2C_MOVE] = PF_MOTOR_MOVE_UNFORMATTED; | |
253 | + } | |
210 | 254 | |
211 | 255 | // I2Cコールバック関数を設定 |
212 | 256 | pf_i2c_callback(PF_I2C_ID_MAQUEEN_MOTOR, pf_motor_callback); |
213 | 257 | } |
214 | 258 | |
215 | -//! @brief モータ駆動情報送信 | |
259 | +//! @brief I2C送信 | |
216 | 260 | static void pf_motor_send(void) |
217 | 261 | { |
262 | +#if PF_MOTOR_I2C_ANY == TRUE | |
263 | + // 送信中チャネルをクリア | |
264 | + pf_motor_info.channel = 0; | |
265 | + | |
266 | + // 常に送信開始 | |
267 | + (void)pf_i2c_send(PF_I2C_ID_MAQUEEN_MOTOR, &pf_motor_info.buf[pf_motor_info.channel][0], | |
268 | + PF_MOTOR_I2C_MAX); | |
269 | +#else | |
270 | + u4 enable; | |
271 | + u4 loop; | |
272 | + BOOL request; | |
273 | + | |
274 | + // オート変数初期化 | |
275 | + enable = 0; | |
276 | + loop = 0; | |
277 | + request = FALSE; | |
278 | + | |
279 | + // I2C割り込み(外部)を禁止 | |
280 | + enable = pf_interrupt_local_disable(PF_INTERRUPT_PRI_I2C_EXT); | |
281 | + | |
282 | + // 左右のモータを調べ、双方とも既に目的の動作になっていればI2C送信をスキップする | |
283 | + for (loop = 0; loop < PF_MOTOR_CHANNEL_MAX; loop++) | |
284 | + { | |
285 | + // 回転方向が異なっていたら送信を要求 | |
286 | + if (pf_motor_info.buf[loop][PF_MOTOR_I2C_MOVE] | |
287 | + != pf_motor_info.i2c[loop][PF_MOTOR_I2C_MOVE]) | |
288 | + { | |
289 | + request = TRUE; | |
290 | + } | |
291 | + | |
292 | + // 速度が異なっていたら送信を要求 | |
293 | + if (pf_motor_info.buf[loop][PF_MOTOR_I2C_SPEED] | |
294 | + != pf_motor_info.i2c[loop][PF_MOTOR_I2C_SPEED]) | |
295 | + { | |
296 | + request = TRUE; | |
297 | + } | |
298 | + } | |
299 | + | |
300 | + // 送信中チャネルをクリア | |
301 | + pf_motor_info.channel = 0; | |
302 | + | |
303 | + // I2C割り込み(外部)を復元 | |
304 | + pf_interrupt_local_restore(PF_INTERRUPT_PRI_I2C_EXT, enable); | |
305 | + | |
306 | + // 要求があれば、送信開始 | |
307 | + if (TRUE == request) | |
308 | + { | |
309 | + (void)pf_i2c_send(PF_I2C_ID_MAQUEEN_MOTOR, &pf_motor_info.buf[pf_motor_info.channel][0], | |
310 | + PF_MOTOR_I2C_MAX); | |
311 | + } | |
312 | +#endif // PF_MOTOR_I2C_ANY | |
313 | +} | |
314 | + | |
315 | +//! @brief I2Cバッファ構成(駆動方向) | |
316 | +static void pf_motor_build_dir(void) | |
317 | +{ | |
218 | 318 | u4 loop; |
219 | 319 | |
220 | 320 | // オート変数初期化 |
@@ -224,65 +324,112 @@ static void pf_motor_send(void) | ||
224 | 324 | for (loop = 0; loop < PF_MOTOR_CHANNEL_MAX; loop++) |
225 | 325 | { |
226 | 326 | // チャネル |
227 | - pf_motor_buf[loop][PF_MOTOR_I2C_CHANNEL] = | |
228 | - pf_motor_dir_to_info[pf_motor_next_dir][loop].channel; | |
327 | + pf_motor_info.buf[loop][PF_MOTOR_I2C_CHANNEL] = | |
328 | + pf_motor_dir_to_packet[pf_motor_info.dir][loop].channel; | |
229 | 329 | |
230 | - // 駆動方向 | |
231 | - pf_motor_buf[loop][PF_MOTOR_I2C_MOVE] = | |
232 | - pf_motor_dir_to_info[pf_motor_next_dir][loop].direction; | |
330 | + // 回転方向 | |
331 | + pf_motor_info.buf[loop][PF_MOTOR_I2C_MOVE] = | |
332 | + pf_motor_dir_to_packet[pf_motor_info.dir][loop].direction; | |
233 | 333 | |
234 | - // 動作速度(駆動の場合は現在の速度を設定する) | |
235 | - if (PF_MOTOR_SPEED_STOP == pf_motor_dir_to_info[pf_motor_next_dir][loop].speed) | |
334 | + // 速度(駆動の場合は現在の速度を設定する) | |
335 | + if (PF_MOTOR_SPEED_STOP == pf_motor_dir_to_packet[pf_motor_info.dir][loop].speed) | |
236 | 336 | { |
237 | 337 | // 停止 |
238 | - pf_motor_buf[loop][PF_MOTOR_I2C_SPEED] = PF_MOTOR_SPEED_STOP; | |
338 | + pf_motor_info.buf[loop][PF_MOTOR_I2C_SPEED] = PF_MOTOR_SPEED_STOP; | |
239 | 339 | } |
240 | 340 | else |
241 | 341 | { |
242 | 342 | // 現在の速度で駆動 |
243 | - pf_motor_buf[loop][PF_MOTOR_I2C_SPEED] = pf_motor_current_speed; | |
343 | + pf_motor_info.buf[loop][PF_MOTOR_I2C_SPEED] = pf_motor_info.speed; | |
244 | 344 | } |
245 | 345 | } |
346 | +} | |
246 | 347 | |
247 | - // 送信中チャネルを初期化 | |
248 | - pf_motor_current_channel = 0; | |
348 | +//! @brief I2Cバッファ構成(フリー) | |
349 | +static void pf_motor_build_free(void) | |
350 | +{ | |
351 | + u4 loop; | |
249 | 352 | |
250 | - // 最初のチャネルの送信をスタート | |
251 | - (void)pf_i2c_send(PF_I2C_ID_MAQUEEN_MOTOR, &pf_motor_buf[0][0], PF_MOTOR_I2C_MAX); | |
353 | + // オート変数初期化 | |
354 | + loop = 0; | |
355 | + | |
356 | + // チャネル数ループ | |
357 | + for (loop = 0; loop < PF_MOTOR_CHANNEL_MAX; loop++) | |
358 | + { | |
359 | + // チャネル | |
360 | + pf_motor_info.buf[loop][PF_MOTOR_I2C_CHANNEL] = | |
361 | + pf_motor_dir_to_packet[pf_motor_info.dir][loop].channel; | |
362 | + | |
363 | + // 回転方向(前回転固定) | |
364 | + pf_motor_info.buf[loop][PF_MOTOR_I2C_MOVE] = PF_MOTOR_MOVE_FORWARD; | |
365 | + | |
366 | + // 速度 | |
367 | + if (0 == loop) | |
368 | + { | |
369 | + pf_motor_info.buf[loop][PF_MOTOR_I2C_SPEED] = pf_motor_info.left; | |
370 | + } | |
371 | + else | |
372 | + { | |
373 | + pf_motor_info.buf[loop][PF_MOTOR_I2C_SPEED] = pf_motor_info.right; | |
374 | + } | |
375 | + } | |
252 | 376 | } |
253 | 377 | |
254 | 378 | //! @brief モータ定期タスク |
255 | 379 | //! @remarks プラットフォーム定期タスク(出力系)処理から呼び出すこと |
256 | 380 | void pf_motor_task(void) |
257 | 381 | { |
258 | - u4 enable; | |
259 | - PF_MOTOR_DIR current; | |
260 | - | |
261 | - // オート変数初期化 | |
262 | - enable = 0; | |
263 | - current = PF_MOTOR_DIR_STOP; | |
264 | - | |
265 | - // 現在の駆動方向を取得(グローバル割り込みを禁止して行う) | |
266 | - enable = pf_interrupt_global_disable(); | |
267 | - current = pf_motor_current_dir; | |
268 | - pf_interrupt_global_restore(enable); | |
269 | - | |
270 | - // 駆動方向を比較 | |
271 | - if (current != pf_motor_next_dir) | |
382 | + // フリー種別で分ける | |
383 | + if (FALSE == pf_motor_info.free) | |
384 | + { | |
385 | + // I2Cバッファ構成(駆動方向) | |
386 | + pf_motor_build_dir(); | |
387 | + } | |
388 | + else | |
272 | 389 | { |
273 | - // 一致するまで送信 | |
274 | - pf_motor_send(); | |
390 | + // I2Cバッファ構成(フリー) | |
391 | + pf_motor_build_free(); | |
275 | 392 | } |
393 | + | |
394 | + // I2C送信(必要に応じて行う) | |
395 | + pf_motor_send(); | |
276 | 396 | } |
277 | 397 | |
278 | 398 | //! @brief モータ駆動 |
279 | 399 | //! @details モータ定期タスクで実際のモータ出力が行われる |
400 | +//! @details pf_motor_freeとは排他的に動作する | |
280 | 401 | //! @param [in] dir モータ駆動方向 |
281 | 402 | void pf_motor_drive(PF_MOTOR_DIR dir) |
282 | 403 | { |
283 | 404 | // パラメータチェック |
284 | 405 | if (dir < PF_MOTOR_DIR_MAX) |
285 | 406 | { |
286 | - pf_motor_next_dir = dir; | |
407 | + // 方向を設定 | |
408 | + pf_motor_info.dir = dir; | |
409 | + | |
410 | + // フリー動作なし | |
411 | + pf_motor_info.free = FALSE; | |
287 | 412 | } |
288 | 413 | } |
414 | + | |
415 | +//! @brief モータ制御 | |
416 | +//! @details モータ定期タスクで実際のモータ出力が行われる | |
417 | +//! @details pf_motor_driveとは排他的に動作する | |
418 | +//! @param [in] left 左モータ駆動速度(0=停止) | |
419 | +//! @param [in] right 右モータ駆動速度(0=停止) | |
420 | +void pf_motor_ctrl(u1 left, u1 right) | |
421 | +{ | |
422 | + // 速度を設定 | |
423 | + pf_motor_info.left = left; | |
424 | + pf_motor_info.right = right; | |
425 | + | |
426 | + // フリー動作あり | |
427 | + pf_motor_info.free = TRUE; | |
428 | +} | |
429 | + | |
430 | +//! @brief モータ速度設定 | |
431 | +//! @param [in] speed モータ駆動速度(デフォルト=100) | |
432 | +void pf_motor_speed(u1 speed) | |
433 | +{ | |
434 | + pf_motor_info.speed = speed; | |
435 | +} |
@@ -0,0 +1,945 @@ | ||
1 | +//! @file pf_music.c | |
2 | +//! @brief プラットフォーム(音楽)実装ファイル | |
3 | + | |
4 | +// The MIT License (MIT) | |
5 | +// Copyright (c) 2023 @xm6_original | |
6 | +// | |
7 | +// Permission is hereby granted, free of charge, to any person obtaining a | |
8 | +// copy of this software and associated documentation files (the "Software"), | |
9 | +// to deal in the Software without restriction, including without limitation | |
10 | +// the rights to use, copy, modify, merge, publish, distribute, sublicense, | |
11 | +// and/or sell copies of the Software, and to permit persons to whom the | |
12 | +// Software is furnished to do so, subject to the following conditions: | |
13 | +// | |
14 | +// The above copyright notice and this permission notice shall be included in | |
15 | +// all copies or substantial portions of the Software. | |
16 | +// | |
17 | +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
18 | +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
19 | +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |
20 | +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
21 | +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |
22 | +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |
23 | +// DEALINGS IN THE SOFTWARE. | |
24 | + | |
25 | +#include "pf_types.h" | |
26 | +#include "nrf52833.h" | |
27 | +#include "nrf52833_bitfields.h" | |
28 | +#include "pf_gpio.h" | |
29 | +#include "pf_timer.h" | |
30 | +#include "pf_music.h" | |
31 | + | |
32 | +//! @brief コマンド定義 | |
33 | +typedef enum PF_MUSIC_CMD_Tag | |
34 | +{ | |
35 | + PF_MUSIC_CMD_LEN1 = 0, //!< 全音符(全休符) | |
36 | + PF_MUSIC_CMD_LEN2P, //!< 符点二分音符(符点二分休符) | |
37 | + PF_MUSIC_CMD_LEN2, //!< 二分音符(二分休符) | |
38 | + PF_MUSIC_CMD_LEN4P, //!< 符点四分音符(符点四分休符) | |
39 | + PF_MUSIC_CMD_LEN4, //!< 四分音符(四分休符) | |
40 | + PF_MUSIC_CMD_LEN8P, //!< 符点八分音符(符点八分休符) | |
41 | + PF_MUSIC_CMD_LEN8, //!< 八分音符(八分休符) | |
42 | + PF_MUSIC_CMD_LEN16P, //!< 符点十六分音符(符点十六分休符) | |
43 | + PF_MUSIC_CMD_LEN3, //!< 三連符(三連休符) | |
44 | + PF_MUSIC_CMD_LEN16, //!< 十六分音符(十六分休符) | |
45 | + PF_MUSIC_CMD_C, //!< C | |
46 | + PF_MUSIC_CMD_CSHARP, //!< C♯/D♭ | |
47 | + PF_MUSIC_CMD_D, //!< D | |
48 | + PF_MUSIC_CMD_DSHARP, //!< D♯/E♭ | |
49 | + PF_MUSIC_CMD_E, //!< E | |
50 | + PF_MUSIC_CMD_F, //!< F | |
51 | + PF_MUSIC_CMD_FSHARP, //!< F♯/G♭ | |
52 | + PF_MUSIC_CMD_G, //!< G | |
53 | + PF_MUSIC_CMD_GSHARP, //!< G♯/A♭ | |
54 | + PF_MUSIC_CMD_A, //!< A | |
55 | + PF_MUSIC_CMD_ASHARP, //!< A♯/B♭ | |
56 | + PF_MUSIC_CMD_B, //!< B | |
57 | + PF_MUSIC_CMD_REST, //!< 休符 | |
58 | + PF_MUSIC_CMD_TIE, //!< タイ | |
59 | + PF_MUSIC_CMD_TEMPO, //!< テンポ | |
60 | + PF_MUSIC_CMD_QUANTIZE, //!< クォンタイズ | |
61 | + PF_MUSIC_CMD_OCTAVE_UP, //!< 1オクターブ上げる | |
62 | + PF_MUSIC_CMD_OCTAVE_DOWN, //!< 1オクターブ下げる | |
63 | + PF_MUSIC_CMD_LOOP_SET, //!< ループ位置設定 | |
64 | + PF_MUSIC_CMD_LOOP_GO, //!< ループ位置ジャンプ | |
65 | +} PF_MUSIC_CMD; | |
66 | + | |
67 | +//! @brief サンプル曲「春が来た」メロディー | |
68 | +const PF_MUSIC_CMD pf_music_melody[] = | |
69 | +{ | |
70 | + // 初回動作 | |
71 | + PF_MUSIC_CMD_TEMPO, | |
72 | + (PF_MUSIC_CMD)108, | |
73 | + PF_MUSIC_CMD_OCTAVE_UP, | |
74 | + PF_MUSIC_CMD_OCTAVE_UP, | |
75 | + PF_MUSIC_CMD_QUANTIZE, | |
76 | + (PF_MUSIC_CMD)7, | |
77 | + PF_MUSIC_CMD_LOOP_SET, | |
78 | + | |
79 | + // 第1小節 | |
80 | + PF_MUSIC_CMD_LEN4, | |
81 | + PF_MUSIC_CMD_G, | |
82 | + PF_MUSIC_CMD_LEN8, | |
83 | + PF_MUSIC_CMD_E, | |
84 | + PF_MUSIC_CMD_F, | |
85 | + PF_MUSIC_CMD_LEN4, | |
86 | + PF_MUSIC_CMD_G, | |
87 | + PF_MUSIC_CMD_A, | |
88 | + | |
89 | + // 第2小節 | |
90 | + PF_MUSIC_CMD_LEN4, | |
91 | + PF_MUSIC_CMD_G, | |
92 | + PF_MUSIC_CMD_LEN8, | |
93 | + PF_MUSIC_CMD_E, | |
94 | + PF_MUSIC_CMD_F, | |
95 | + PF_MUSIC_CMD_LEN4, | |
96 | + PF_MUSIC_CMD_G, | |
97 | + PF_MUSIC_CMD_OCTAVE_UP, | |
98 | + PF_MUSIC_CMD_C, | |
99 | + PF_MUSIC_CMD_OCTAVE_DOWN, | |
100 | + | |
101 | + // 第3小節 | |
102 | + PF_MUSIC_CMD_LEN4, | |
103 | + PF_MUSIC_CMD_A, | |
104 | + PF_MUSIC_CMD_G, | |
105 | + PF_MUSIC_CMD_LEN4P, | |
106 | + PF_MUSIC_CMD_E, | |
107 | + PF_MUSIC_CMD_LEN8, | |
108 | + PF_MUSIC_CMD_C, | |
109 | + | |
110 | + // 第4小節 | |
111 | + PF_MUSIC_CMD_LEN2P, | |
112 | + PF_MUSIC_CMD_D, | |
113 | + PF_MUSIC_CMD_LEN4, | |
114 | + PF_MUSIC_CMD_REST, | |
115 | + | |
116 | + // 第5小節 | |
117 | + PF_MUSIC_CMD_LEN4, | |
118 | + PF_MUSIC_CMD_G, | |
119 | + PF_MUSIC_CMD_LEN8, | |
120 | + PF_MUSIC_CMD_A, | |
121 | + PF_MUSIC_CMD_G, | |
122 | + PF_MUSIC_CMD_LEN4, | |
123 | + PF_MUSIC_CMD_E, | |
124 | + PF_MUSIC_CMD_G, | |
125 | + | |
126 | + // 第6小節 | |
127 | + PF_MUSIC_CMD_LEN4, | |
128 | + PF_MUSIC_CMD_OCTAVE_UP, | |
129 | + PF_MUSIC_CMD_C, | |
130 | + PF_MUSIC_CMD_LEN8, | |
131 | + PF_MUSIC_CMD_D, | |
132 | + PF_MUSIC_CMD_C, | |
133 | + PF_MUSIC_CMD_OCTAVE_DOWN, | |
134 | + PF_MUSIC_CMD_LEN4, | |
135 | + PF_MUSIC_CMD_A, | |
136 | + PF_MUSIC_CMD_OCTAVE_UP, | |
137 | + PF_MUSIC_CMD_C, | |
138 | + PF_MUSIC_CMD_OCTAVE_DOWN, | |
139 | + | |
140 | + // 第7小節 | |
141 | + PF_MUSIC_CMD_LEN4, | |
142 | + PF_MUSIC_CMD_G, | |
143 | + PF_MUSIC_CMD_OCTAVE_UP, | |
144 | + PF_MUSIC_CMD_E, | |
145 | + PF_MUSIC_CMD_LEN4P, | |
146 | + PF_MUSIC_CMD_D, | |
147 | + PF_MUSIC_CMD_OCTAVE_DOWN, | |
148 | + PF_MUSIC_CMD_LEN8, | |
149 | + PF_MUSIC_CMD_G, | |
150 | + | |
151 | + // 第8小節 | |
152 | + PF_MUSIC_CMD_LEN2P, | |
153 | + PF_MUSIC_CMD_OCTAVE_UP, | |
154 | + PF_MUSIC_CMD_C, | |
155 | + PF_MUSIC_CMD_OCTAVE_DOWN, | |
156 | + PF_MUSIC_CMD_LEN4, | |
157 | + PF_MUSIC_CMD_REST, | |
158 | + | |
159 | + // ループ | |
160 | + PF_MUSIC_CMD_LOOP_GO, | |
161 | +}; | |
162 | + | |
163 | +//! @brief サンプル曲「春が来た」ベース | |
164 | +const PF_MUSIC_CMD pf_music_base[] = | |
165 | +{ | |
166 | + // 初回動作 | |
167 | + PF_MUSIC_CMD_OCTAVE_UP, | |
168 | + PF_MUSIC_CMD_QUANTIZE, | |
169 | + (PF_MUSIC_CMD)6, | |
170 | + PF_MUSIC_CMD_LOOP_SET, | |
171 | + | |
172 | + // 第1小節 | |
173 | + PF_MUSIC_CMD_LEN8, | |
174 | + PF_MUSIC_CMD_C, | |
175 | + PF_MUSIC_CMD_G, | |
176 | + PF_MUSIC_CMD_E, | |
177 | + PF_MUSIC_CMD_G, | |
178 | + PF_MUSIC_CMD_C, | |
179 | + PF_MUSIC_CMD_G, | |
180 | + PF_MUSIC_CMD_E, | |
181 | + PF_MUSIC_CMD_G, | |
182 | + | |
183 | + // 第2小節 | |
184 | + PF_MUSIC_CMD_LEN8, | |
185 | + PF_MUSIC_CMD_C, | |
186 | + PF_MUSIC_CMD_G, | |
187 | + PF_MUSIC_CMD_E, | |
188 | + PF_MUSIC_CMD_G, | |
189 | + PF_MUSIC_CMD_C, | |
190 | + PF_MUSIC_CMD_G, | |
191 | + PF_MUSIC_CMD_E, | |
192 | + PF_MUSIC_CMD_G, | |
193 | + | |
194 | + // 第3小節 | |
195 | + PF_MUSIC_CMD_LEN8, | |
196 | + PF_MUSIC_CMD_C, | |
197 | + PF_MUSIC_CMD_G, | |
198 | + PF_MUSIC_CMD_E, | |
199 | + PF_MUSIC_CMD_G, | |
200 | + PF_MUSIC_CMD_C, | |
201 | + PF_MUSIC_CMD_G, | |
202 | + PF_MUSIC_CMD_E, | |
203 | + PF_MUSIC_CMD_G, | |
204 | + | |
205 | + // 第4小節 | |
206 | + PF_MUSIC_CMD_LEN8, | |
207 | + PF_MUSIC_CMD_OCTAVE_DOWN, | |
208 | + PF_MUSIC_CMD_G, | |
209 | + PF_MUSIC_CMD_OCTAVE_UP, | |
210 | + PF_MUSIC_CMD_G, | |
211 | + PF_MUSIC_CMD_F, | |
212 | + PF_MUSIC_CMD_G, | |
213 | + PF_MUSIC_CMD_E, | |
214 | + PF_MUSIC_CMD_G, | |
215 | + PF_MUSIC_CMD_D, | |
216 | + PF_MUSIC_CMD_G, | |
217 | + | |
218 | + // 第5小節 | |
219 | + PF_MUSIC_CMD_LEN8, | |
220 | + PF_MUSIC_CMD_C, | |
221 | + PF_MUSIC_CMD_G, | |
222 | + PF_MUSIC_CMD_E, | |
223 | + PF_MUSIC_CMD_G, | |
224 | + PF_MUSIC_CMD_C, | |
225 | + PF_MUSIC_CMD_G, | |
226 | + PF_MUSIC_CMD_E, | |
227 | + PF_MUSIC_CMD_G, | |
228 | + | |
229 | + // 第6小節 | |
230 | + PF_MUSIC_CMD_LEN8, | |
231 | + PF_MUSIC_CMD_C, | |
232 | + PF_MUSIC_CMD_A, | |
233 | + PF_MUSIC_CMD_F, | |
234 | + PF_MUSIC_CMD_A, | |
235 | + PF_MUSIC_CMD_C, | |
236 | + PF_MUSIC_CMD_A, | |
237 | + PF_MUSIC_CMD_F, | |
238 | + PF_MUSIC_CMD_A, | |
239 | + | |
240 | + // 第7小節 | |
241 | + PF_MUSIC_CMD_LEN8, | |
242 | + PF_MUSIC_CMD_C, | |
243 | + PF_MUSIC_CMD_G, | |
244 | + PF_MUSIC_CMD_E, | |
245 | + PF_MUSIC_CMD_G, | |
246 | + PF_MUSIC_CMD_OCTAVE_DOWN, | |
247 | + PF_MUSIC_CMD_G, | |
248 | + PF_MUSIC_CMD_OCTAVE_UP, | |
249 | + PF_MUSIC_CMD_G, | |
250 | + PF_MUSIC_CMD_OCTAVE_DOWN, | |
251 | + PF_MUSIC_CMD_B, | |
252 | + PF_MUSIC_CMD_OCTAVE_UP, | |
253 | + PF_MUSIC_CMD_G, | |
254 | + | |
255 | + // 第8小節 | |
256 | + PF_MUSIC_CMD_LEN8, | |
257 | + PF_MUSIC_CMD_C, | |
258 | + PF_MUSIC_CMD_G, | |
259 | + PF_MUSIC_CMD_E, | |
260 | + PF_MUSIC_CMD_G, | |
261 | + PF_MUSIC_CMD_LEN4, | |
262 | + PF_MUSIC_CMD_C, | |
263 | + PF_MUSIC_CMD_REST, | |
264 | + | |
265 | + // ループ | |
266 | + PF_MUSIC_CMD_LOOP_GO, | |
267 | +}; | |
268 | + | |
269 | +//! @brief 音階定義 | |
270 | +typedef enum PF_MUSIC_NOTE_Tag | |
271 | +{ | |
272 | + PF_MUSIC_NOTE_C = 0, //!< C | |
273 | + PF_MUSIC_NOTE_CSHARP, //!< C♯/D♭ | |
274 | + PF_MUSIC_NOTE_D, //!< D | |
275 | + PF_MUSIC_NOTE_DSHARP, //!< D♯/E♭ | |
276 | + PF_MUSIC_NOTE_E, //!< E | |
277 | + PF_MUSIC_NOTE_F, //!< F | |
278 | + PF_MUSIC_NOTE_FSHARP, //!< F♯/G♭ | |
279 | + PF_MUSIC_NOTE_G, //!< G | |
280 | + PF_MUSIC_NOTE_GSHARP, //!< G♯/A♭ | |
281 | + PF_MUSIC_NOTE_A, //!< A | |
282 | + PF_MUSIC_NOTE_ASHARP, //!< A♯/B♭ | |
283 | + PF_MUSIC_NOTE_B, //!< B | |
284 | + PF_MUSIC_NOTE_MAX, //!< (音階の個数を表す) | |
285 | +} PF_MUSIC_NOTE; | |
286 | + | |
287 | +//! @brief 音階→PWM周期テーブル(PWMクロック=4MHz) | |
288 | +const u4 pf_music_note_table[PF_MUSIC_NOTE_MAX] = | |
289 | +{ | |
290 | + 30578, //!< C | |
291 | + 28862, //!< C♯/D♭ | |
292 | + 27242, //!< D | |
293 | + 25713, //!< D♯/E♭ | |
294 | + 24270, //!< E | |
295 | + 22908, //!< F | |
296 | + 21622, //!< F♯/G♭ | |
297 | + 20408, //!< G | |
298 | + 19263, //!< G♯/A♭ | |
299 | + 18182, //!< A | |
300 | + 17161, //!< A♯/B♭ | |
301 | + 16198, //!< B | |
302 | +}; | |
303 | + | |
304 | +//! @brief コマンド→クロックテーブル | |
305 | +const u4 pf_music_cmd_to_clock[10] = | |
306 | +{ | |
307 | + // PF_MUSIC_CMD_LEN1 | |
308 | + 192, | |
309 | + | |
310 | + // PF_MUSIC_CMD_LEN2P | |
311 | + 144, | |
312 | + | |
313 | + // PF_MUSIC_CMD_LEN2 | |
314 | + 96, | |
315 | + | |
316 | + // PF_MUSIC_CMD_LEN4P | |
317 | + 72, | |
318 | + | |
319 | + // PF_MUSIC_CMD_LEN4 | |
320 | + 48, | |
321 | + | |
322 | + // PF_MUSIC_CMD_LEN8P | |
323 | + 36, | |
324 | + | |
325 | + // PF_MUSIC_CMD_LEN8 | |
326 | + 24, | |
327 | + | |
328 | + // PF_MUSIC_CMD_LEN16P | |
329 | + 18, | |
330 | + | |
331 | + // PF_MUSIC_CMD_LEN3 | |
332 | + 16, | |
333 | + | |
334 | + // PF_MUSIC_CMD_LEN16 | |
335 | + 12 | |
336 | +}; | |
337 | + | |
338 | +//! @brief 音楽デバイス→PWMテーブル | |
339 | +static NRF_PWM_Type* const pf_music_device_to_pwm[PF_MUSIC_DEVICE_MAX] = | |
340 | +{ | |
341 | + NRF_PWM0, //!< 内蔵スピーカー | |
342 | + NRF_PWM1, //!< MAQUEENスピーカー | |
343 | +}; | |
344 | + | |
345 | +//! @brief 音楽デバイス→GPIOテーブル | |
346 | +static const PF_GPIO_ID pf_music_device_to_gpio[PF_MUSIC_DEVICE_MAX] = | |
347 | +{ | |
348 | + PF_GPIO_ID_INTERNAL_SPEAKER, //!< 内蔵スピーカー | |
349 | + PF_GPIO_ID_MAQUEEN_SPEAKER, //!< MAQUEENスピーカー | |
350 | +}; | |
351 | + | |
352 | +//! @brief 演奏情報構造体 | |
353 | +typedef struct PF_MUSIC_INFO_Tag | |
354 | +{ | |
355 | + BOOL playing; //!< 演奏中フラグ | |
356 | + const PF_MUSIC_CMD *ptr; //!< データポインタ | |
357 | + const PF_MUSIC_CMD *loop; //!< ループポインタ | |
358 | + u4 clock; //!< クロック数 | |
359 | + u4 length; //!< 音長 | |
360 | + BOOL on; //!< キーオンフラグ | |
361 | + u4 off; //!< キーオフカウンタ | |
362 | + u4 octave; //!< オクターブ(0=除算なし) | |
363 | + u4 quantize; //!< クォンタイズ | |
364 | + PF_MUSIC_NOTE note; //!< 音階 | |
365 | + BOOL tie; //!< タイフラグ | |
366 | + s4 countertop; //!< PWM周波数 | |
367 | + BOOL lfo_enable; //!< LFO有効フラグ | |
368 | + u4 lfo_delay; //!< LFOディレイ | |
369 | + u4 lfo_keyon; //!< LFOディレイ(カレント) | |
370 | + u4 lfo_cycle; //!< LFOサイクル(三角波の片方向クロック) | |
371 | + u4 lfo_current; //!< LFOサイクル(カレント) | |
372 | + s4 lfo_diff; //!< LFO差分 | |
373 | + s4 lfo_signed; //!< LFO差分(カレント) | |
374 | + u2 duty; //!< デューティー比 | |
375 | +} PF_MUSIC_INFO; | |
376 | + | |
377 | +//! @brief 演奏情報 | |
378 | +static PF_MUSIC_INFO pf_music_info[PF_MUSIC_DEVICE_MAX]; | |
379 | + | |
380 | +//! @brief PWM初期化 | |
381 | +static void pf_music_init_pwm(void) | |
382 | +{ | |
383 | + NRF_PWM_Type *pwm; | |
384 | + u4 loop; | |
385 | + PF_GPIO_ID gpio; | |
386 | + u4 port; | |
387 | + u4 pin; | |
388 | + | |
389 | + // オート変数初期化 | |
390 | + pwm = NRF_PWM0; | |
391 | + loop = 0; | |
392 | + gpio = PF_GPIO_ID_INTERNAL_SPEAKER; | |
393 | + port = 0; | |
394 | + pin = 0; | |
395 | + | |
396 | + // 音楽デバイスだけループ | |
397 | + for (loop = 0; loop < PF_MUSIC_DEVICE_MAX; loop++) | |
398 | + { | |
399 | + // PWMデバイス取得 | |
400 | + pwm = pf_music_device_to_pwm[loop]; | |
401 | + | |
402 | + // PWM停止 | |
403 | + pwm->ENABLE = PWM_ENABLE_ENABLE_Disabled << PWM_ENABLE_ENABLE_Pos; | |
404 | + | |
405 | + // イベントのショートカット | |
406 | + pwm->SHORTS = 0; | |
407 | + | |
408 | + // 割り込み有効 | |
409 | + pwm->INTEN = 0; | |
410 | + | |
411 | + // 波形モード | |
412 | + pwm->MODE = PWM_MODE_UPDOWN_Up << PWM_MODE_UPDOWN_Pos; | |
413 | + | |
414 | + // デコーダーモード | |
415 | + pwm->DECODER = (PWM_DECODER_LOAD_Common << PWM_DECODER_LOAD_Pos) | |
416 | + | (PWM_DECODER_MODE_NextStep << PWM_DECODER_MODE_Pos); | |
417 | + | |
418 | + // プリスケーラー(4MHz) | |
419 | + pwm->PRESCALER = PWM_PRESCALER_PRESCALER_DIV_4 << PWM_PRESCALER_PRESCALER_Pos; | |
420 | + | |
421 | + // PWM周期 | |
422 | + pwm->COUNTERTOP = pf_music_note_table[0]; | |
423 | + | |
424 | + // ループ回数(RAMテーブルをループしない) | |
425 | + pwm->LOOP = PWM_LOOP_CNT_Disabled << PWM_LOOP_CNT_Pos; | |
426 | + | |
427 | + // GPIO IDを取得 | |
428 | + gpio = pf_music_device_to_gpio[loop]; | |
429 | + | |
430 | + // GPIOポートとGPIOピンを取得 | |
431 | + port = pf_gpio_get_port(gpio); | |
432 | + pin = pf_gpio_get_pin(gpio); | |
433 | + | |
434 | + // PSEL.OUT[0]のみ使用する | |
435 | + pwm->PSEL.OUT[0] = (pin << PWM_PSEL_OUT_PIN_Pos) | (port << PWM_PSEL_OUT_PORT_Pos) | |
436 | + | (PWM_PSEL_OUT_CONNECT_Connected << PWM_PSEL_OUT_CONNECT_Pos); | |
437 | + | |
438 | + // PWM有効 | |
439 | + pwm->ENABLE = PWM_ENABLE_ENABLE_Enabled << PWM_ENABLE_ENABLE_Pos; | |
440 | + } | |
441 | +} | |
442 | + | |
443 | +//! @brief キーオン | |
444 | +//! @param [in] device 音楽デバイス | |
445 | +static void pf_music_on(u4 device) | |
446 | +{ | |
447 | + NRF_PWM_Type *pwm; | |
448 | + u4 cycle; | |
449 | + u4 octave; | |
450 | + | |
451 | + // オート変数初期化 | |
452 | + pwm = pf_music_device_to_pwm[device]; | |
453 | + cycle = (u4)pf_music_info[device].countertop; | |
454 | + octave = pf_music_info[device].octave; | |
455 | + | |
456 | + // オクターブ演算 | |
457 | + cycle >>= octave; | |
458 | + | |
459 | + // PWM周期設定 | |
460 | + pwm->COUNTERTOP = (u2)cycle; | |
461 | + | |
462 | + // デューティー比(31.25%)設定値は逆の68.75%とする | |
463 | + cycle *= (16 - 5); | |
464 | + cycle >>= 4; | |
465 | + pf_music_info[device].duty = (u2)cycle; | |
466 | + | |
467 | + // ポインタ | |
468 | + pwm->SEQ[0].PTR = (u4)&pf_music_info[device].duty; | |
469 | + | |
470 | + // 個数 | |
471 | + pwm->SEQ[0].CNT = 1; | |
472 | + | |
473 | + // リフレッシュ | |
474 | + pwm->SEQ[0].REFRESH = 0; | |
475 | + | |
476 | + // 遅延 | |
477 | + pwm->SEQ[0].ENDDELAY = 0; | |
478 | + | |
479 | + // シーケンススタート | |
480 | + pwm->TASKS_SEQSTART[0] = PWM_TASKS_SEQSTART_TASKS_SEQSTART_Trigger | |
481 | + << PWM_TASKS_SEQSTART_TASKS_SEQSTART_Pos; | |
482 | +} | |
483 | + | |
484 | +//! @brief キーオフ | |
485 | +//! @param [in] device 音楽デバイス | |
486 | +static void pf_music_off(u4 device) | |
487 | +{ | |
488 | + NRF_PWM_Type *pwm; | |
489 | + | |
490 | + // オート変数初期化 | |
491 | + pwm = pf_music_device_to_pwm[device]; | |
492 | + | |
493 | + // PWM停止(DAC出力はLowレベル) | |
494 | + pwm->TASKS_STOP = PWM_TASKS_STOP_TASKS_STOP_Trigger << PWM_TASKS_STOP_TASKS_STOP_Pos; | |
495 | +} | |
496 | + | |
497 | +//! @brief 音符 | |
498 | +//! @param [in] device 音楽デバイス | |
499 | +//! @param [in] note 音階 | |
500 | +static void pf_music_note(u4 device, PF_MUSIC_NOTE note) | |
501 | +{ | |
502 | + u4 off; | |
503 | + | |
504 | + // オート変数初期化 | |
505 | + off = 0; | |
506 | + | |
507 | + // 音階セット | |
508 | + pf_music_info[device].note = note; | |
509 | + | |
510 | + // タイの有無で分ける | |
511 | + if (FALSE == pf_music_info[device].tie) | |
512 | + { | |
513 | + // クォンタイズを考慮してキーオフクロックを算出 | |
514 | + off = pf_music_info[device].length; | |
515 | + off *= pf_music_info[device].quantize; | |
516 | + off >>= 3; | |
517 | + pf_music_info[device].off = off; | |
518 | + } | |
519 | + else | |
520 | + { | |
521 | + // タイの効力は1音きり(TIE+音符1+音符2のように構成する) | |
522 | + pf_music_info[device].tie = FALSE; | |
523 | + pf_music_info[device].off = 0; | |
524 | + } | |
525 | + | |
526 | + // クロック | |
527 | + pf_music_info[device].clock = pf_music_info[device].length; | |
528 | + | |
529 | + // PWM周波数設定 | |
530 | + pf_music_info[device].countertop = (s4)pf_music_note_table[note]; | |
531 | + | |
532 | + // LFO初期化 | |
533 | + pf_music_info[device].lfo_keyon = pf_music_info[device].lfo_delay; | |
534 | + pf_music_info[device].lfo_current = pf_music_info[device].lfo_cycle; | |
535 | + pf_music_info[device].lfo_signed = pf_music_info[device].lfo_diff; | |
536 | + | |
537 | + // キーオン | |
538 | + pf_music_on(device); | |
539 | + | |
540 | + // キーオン状態 | |
541 | + pf_music_info[device].on = TRUE; | |
542 | +} | |
543 | + | |
544 | +//! @brief 休符 | |
545 | +//! @param [in] device 音楽デバイス | |
546 | +static void pf_music_rest(u4 device) | |
547 | +{ | |
548 | + // キーオン中なら、キーオフ | |
549 | + if (TRUE == pf_music_info[device].on) | |
550 | + { | |
551 | + pf_music_off(device); | |
552 | + | |
553 | + // キーオフ状態 | |
554 | + pf_music_info[device].on = FALSE; | |
555 | + } | |
556 | + | |
557 | + // キーオフカウンタとクロック | |
558 | + pf_music_info[device].off = 0; | |
559 | + pf_music_info[device].clock = pf_music_info[device].length; | |
560 | +} | |
561 | + | |
562 | +//! @brief タイ | |
563 | +//! @param [in] device 音楽デバイス | |
564 | +static void pf_music_tie(u4 device) | |
565 | +{ | |
566 | + // フラグセットのみ(TIE+音符1+音符2のように構成する) | |
567 | + pf_music_info[device].tie = TRUE; | |
568 | +} | |
569 | + | |
570 | +//! @brief テンポ | |
571 | +//! @param [in] device 音楽デバイス | |
572 | +static void pf_music_tempo(u4 device) | |
573 | +{ | |
574 | + u4 cc; | |
575 | + u4 bpm; | |
576 | + PF_MUSIC_CMD cmd; | |
577 | + | |
578 | + // オート変数初期化 | |
579 | + cc = 1250000U; | |
580 | + bpm = 0; | |
581 | + cmd = PF_MUSIC_CMD_TEMPO; | |
582 | + | |
583 | + // データフェッチ | |
584 | + cmd = *(pf_music_info[device].ptr); | |
585 | + pf_music_info[device].ptr++; | |
586 | + bpm = (u4)cmd; | |
587 | + | |
588 | + // 1拍=48クロックで算出する | |
589 | + // 最適化前の式:60*1000*1000/(48*bpm) | |
590 | + cc /= bpm; | |
591 | + | |
592 | + pf_timer_cc(PF_TIMER_ID_MUSIC, &cc); | |
593 | +} | |
594 | + | |
595 | +//! @brief クォンタイズ | |
596 | +//! @param [in] device 音楽デバイス | |
597 | +static void pf_music_quantize(u4 device) | |
598 | +{ | |
599 | + u4 quantize; | |
600 | + PF_MUSIC_CMD cmd; | |
601 | + | |
602 | + // オート変数初期化 | |
603 | + quantize = 0; | |
604 | + cmd = PF_MUSIC_CMD_QUANTIZE; | |
605 | + | |
606 | + // データフェッチ | |
607 | + cmd = *(pf_music_info[device].ptr); | |
608 | + pf_music_info[device].ptr++; | |
609 | + quantize = (u4)cmd; | |
610 | + | |
611 | + // セット | |
612 | + pf_music_info[device].quantize = quantize; | |
613 | +} | |
614 | + | |
615 | +//! @brief オクターブアップ | |
616 | +//! @param [in] device 音楽デバイス | |
617 | +static void pf_music_octave_up(u4 device) | |
618 | +{ | |
619 | + pf_music_info[device].octave++; | |
620 | +} | |
621 | + | |
622 | +//! @brief オクターブダウン | |
623 | +//! @param [in] device 音楽デバイス | |
624 | +static void pf_music_octave_down(u4 device) | |
625 | +{ | |
626 | + pf_music_info[device].octave--; | |
627 | +} | |
628 | + | |
629 | +//! @brief ループ位置設定 | |
630 | +//! @param [in] device 音楽デバイス | |
631 | +static void pf_music_loop_set(u4 device) | |
632 | +{ | |
633 | + pf_music_info[device].loop = pf_music_info[device].ptr; | |
634 | +} | |
635 | + | |
636 | +//! @brief ループ位置ジャンプ | |
637 | +//! @param [in] device 音楽デバイス | |
638 | +static void pf_music_loop_go(u4 device) | |
639 | +{ | |
640 | + pf_music_info[device].ptr = pf_music_info[device].loop; | |
641 | +} | |
642 | + | |
643 | +//! @brief コマンド解釈 | |
644 | +//! @param [in] device 音楽デバイス | |
645 | +static void pf_music_interpret(u4 device) | |
646 | +{ | |
647 | + PF_MUSIC_CMD cmd; | |
648 | + | |
649 | + // オート変数初期化 | |
650 | + cmd = PF_MUSIC_CMD_LOOP_GO; | |
651 | + | |
652 | + // コマンド取得 | |
653 | + cmd = *(pf_music_info[device].ptr); | |
654 | + pf_music_info[device].ptr++; | |
655 | + | |
656 | + // コマンド別 | |
657 | + if (cmd < PF_MUSIC_CMD_C) | |
658 | + { | |
659 | + // 音長設定 | |
660 | + pf_music_info[device].length = pf_music_cmd_to_clock[cmd]; | |
661 | + } | |
662 | + else | |
663 | + { | |
664 | + if (cmd < PF_MUSIC_CMD_REST) | |
665 | + { | |
666 | + // 音符 | |
667 | + pf_music_note(device, (PF_MUSIC_NOTE)(cmd - PF_MUSIC_CMD_C)); | |
668 | + } | |
669 | + else | |
670 | + { | |
671 | + // コマンド別 | |
672 | + switch (cmd) | |
673 | + { | |
674 | + // 休符 | |
675 | + case PF_MUSIC_CMD_REST: | |
676 | + pf_music_rest(device); | |
677 | + break; | |
678 | + | |
679 | + // タイ | |
680 | + case PF_MUSIC_CMD_TIE: | |
681 | + pf_music_tie(device); | |
682 | + break; | |
683 | + | |
684 | + // テンポ | |
685 | + case PF_MUSIC_CMD_TEMPO: | |
686 | + pf_music_tempo(device); | |
687 | + break; | |
688 | + | |
689 | + // クォンタイズ | |
690 | + case PF_MUSIC_CMD_QUANTIZE: | |
691 | + pf_music_quantize(device); | |
692 | + break; | |
693 | + | |
694 | + // オクターブアップ | |
695 | + case PF_MUSIC_CMD_OCTAVE_UP: | |
696 | + pf_music_octave_up(device); | |
697 | + break; | |
698 | + | |
699 | + // オクターブダウン | |
700 | + case PF_MUSIC_CMD_OCTAVE_DOWN: | |
701 | + pf_music_octave_down(device); | |
702 | + break; | |
703 | + | |
704 | + // ループ位置設定 | |
705 | + case PF_MUSIC_CMD_LOOP_SET: | |
706 | + pf_music_loop_set(device); | |
707 | + break; | |
708 | + | |
709 | + // ループ位置ジャンプ | |
710 | + case PF_MUSIC_CMD_LOOP_GO: | |
711 | + pf_music_loop_go(device); | |
712 | + break; | |
713 | + | |
714 | + // その他(この1バイトは無視) | |
715 | + default: | |
716 | + break; | |
717 | + } | |
718 | + } | |
719 | + } | |
720 | +} | |
721 | + | |
722 | +//! @brief LFO処理 | |
723 | +//! @param [in] device 音楽デバイス | |
724 | +static void pf_music_lfo(u4 device) | |
725 | +{ | |
726 | + // キーオン時かつLFO有効時に限る | |
727 | + if ((TRUE == pf_music_info[device].on) && (TRUE == pf_music_info[device].lfo_enable)) | |
728 | + { | |
729 | + // LFOディレイが有効であれば、デクリメント | |
730 | + if (pf_music_info[device].lfo_keyon > 0) | |
731 | + { | |
732 | + pf_music_info[device].lfo_keyon--; | |
733 | + } | |
734 | + else | |
735 | + { | |
736 | + // 差分を加算 | |
737 | + pf_music_info[device].countertop += pf_music_info[device].lfo_signed; | |
738 | + | |
739 | + // 三角波カウンタをデクリメント | |
740 | + pf_music_info[device].lfo_current--; | |
741 | + | |
742 | + // 0になったら、周期2倍と反転処理 | |
743 | + if (0 == pf_music_info[device].lfo_current) | |
744 | + { | |
745 | + pf_music_info[device].lfo_current = pf_music_info[device].lfo_cycle * 2; | |
746 | + pf_music_info[device].lfo_signed = 0 - pf_music_info[device].lfo_signed; | |
747 | + } | |
748 | + | |
749 | + // キーオン | |
750 | + pf_music_on(device); | |
751 | + } | |
752 | + } | |
753 | +} | |
754 | + | |
755 | +//! @brief クロック処理 | |
756 | +//! @param [in] device 音楽デバイス | |
757 | +static void pf_music_clock(u4 device) | |
758 | +{ | |
759 | + // LFOは常に行う | |
760 | + pf_music_lfo(device); | |
761 | + | |
762 | + // キーオフチェック | |
763 | + if (pf_music_info[device].off > 0) | |
764 | + { | |
765 | + pf_music_info[device].off--; | |
766 | + if (0 == pf_music_info[device].off) | |
767 | + { | |
768 | + // キーオン状態であれば、キーオフ | |
769 | + if (TRUE == pf_music_info[device].on) | |
770 | + { | |
771 | + pf_music_off(device); | |
772 | + pf_music_info[device].on = FALSE; | |
773 | + } | |
774 | + } | |
775 | + } | |
776 | + | |
777 | + // クロックチェック | |
778 | + if (pf_music_info[device].clock > 0) | |
779 | + { | |
780 | + pf_music_info[device].clock--; | |
781 | + if (0 == pf_music_info[device].clock) | |
782 | + { | |
783 | + // コマンド解釈 | |
784 | + while (0 == pf_music_info[device].clock) | |
785 | + { | |
786 | + pf_music_interpret(device); | |
787 | + } | |
788 | + } | |
789 | + } | |
790 | +} | |
791 | + | |
792 | +//! @brief Timerコールバック | |
793 | +//! @param [in] eventbit イベントビットパターン(bit0:クロックタイミング) | |
794 | +//! @attention Timer割り込みコンテキストで実行される | |
795 | +static void pf_music_callback(u4 /*eventbit*/) | |
796 | +{ | |
797 | + u4 loop; | |
798 | + | |
799 | + // オート変数初期化 | |
800 | + loop = 0; | |
801 | + | |
802 | + // 音楽デバイスだけループ | |
803 | + for (loop = 0; loop < PF_MUSIC_DEVICE_MAX; loop++) | |
804 | + { | |
805 | + // 演奏中の場合に限る | |
806 | + if (TRUE == pf_music_info[loop].playing) | |
807 | + { | |
808 | + pf_music_clock(loop); | |
809 | + } | |
810 | + } | |
811 | +} | |
812 | + | |
813 | +//! @brief 音楽演奏初期化 | |
814 | +//! @remarks プラットフォーム初期化処理から呼び出すこと | |
815 | +//! @attention GPIO初期化およびTimer初期化の後に呼び出すこと | |
816 | +void pf_music_init(void) | |
817 | +{ | |
818 | + // PWM初期化 | |
819 | + pf_music_init_pwm(); | |
820 | + | |
821 | + // Timerコールバック関数設定 | |
822 | + pf_timer_callback(PF_TIMER_ID_MUSIC, pf_music_callback); | |
823 | +} | |
824 | + | |
825 | +//! @brief 演奏開始のためのセットアップ | |
826 | +//! @param [in] device 音楽デバイス | |
827 | +//! @param [in] sequence シーケンスデータ | |
828 | +static void pf_music_setup(u4 device, const PF_MUSIC_CMD *sequence) | |
829 | +{ | |
830 | + // 演奏中フラグ | |
831 | + pf_music_info[device].playing = TRUE; | |
832 | + | |
833 | + // カレントポインタとループポインタ | |
834 | + pf_music_info[device].ptr = sequence; | |
835 | + pf_music_info[device].loop = sequence; | |
836 | + | |
837 | + // 初回クロック | |
838 | + pf_music_info[device].clock = 1; | |
839 | + | |
840 | + // 音長(デフォルトで四分音符) | |
841 | + pf_music_info[device].length = 48; | |
842 | + | |
843 | + // キーオン状態 | |
844 | + pf_music_info[device].on = FALSE; | |
845 | + | |
846 | + // キーオフするまでのカウンタ | |
847 | + pf_music_info[device].off = 0; | |
848 | + | |
849 | + // オクターブ | |
850 | + pf_music_info[device].octave = 0; | |
851 | + | |
852 | + // クォンタイズ(1~8) | |
853 | + pf_music_info[device].quantize = 8; | |
854 | + | |
855 | + // タイフラグ | |
856 | + pf_music_info[device].tie = FALSE; | |
857 | + | |
858 | + // LFO有効フラグ | |
859 | + pf_music_info[device].lfo_enable = FALSE; | |
860 | + | |
861 | + // LFOディレイ | |
862 | + pf_music_info[device].lfo_delay = 0; | |
863 | + pf_music_info[device].lfo_keyon = 0; | |
864 | + | |
865 | + // LFOサイクル | |
866 | + pf_music_info[device].lfo_cycle = 0; | |
867 | + pf_music_info[device].lfo_current = 0; | |
868 | + | |
869 | + // LFO差分 | |
870 | + pf_music_info[device].lfo_diff = 0; | |
871 | + pf_music_info[device].lfo_signed = 0; | |
872 | +} | |
873 | + | |
874 | +//! @brief 音楽演奏開始 | |
875 | +void pf_music_play(void) | |
876 | +{ | |
877 | + u4 loop; | |
878 | + BOOL playing; | |
879 | + | |
880 | + // オート変数初期化 | |
881 | + loop = 0; | |
882 | + playing = FALSE; | |
883 | + | |
884 | + // 音楽デバイスだけループ | |
885 | + for (loop = 0; loop < PF_MUSIC_DEVICE_MAX; loop++) | |
886 | + { | |
887 | + // どちらかが演奏中なら、演奏中フラグを立てる | |
888 | + if (TRUE == pf_music_info[loop].playing) | |
889 | + { | |
890 | + playing = TRUE; | |
891 | + } | |
892 | + } | |
893 | + | |
894 | + // ともに演奏停止中の場合 | |
895 | + if (FALSE == playing) | |
896 | + { | |
897 | + // 音楽デバイスのセットアップ | |
898 | + pf_music_setup(0, pf_music_base); | |
899 | + pf_music_setup(1, pf_music_melody); | |
900 | + | |
901 | + // メロディー側のみLFOを有効にする | |
902 | + pf_music_info[1].lfo_enable = TRUE; | |
903 | + pf_music_info[1].lfo_delay = 30; | |
904 | + pf_music_info[1].lfo_cycle = 12; | |
905 | + pf_music_info[1].lfo_diff = 14; | |
906 | + | |
907 | + // タイマ開始 | |
908 | + pf_timer_start(PF_TIMER_ID_MUSIC); | |
909 | + } | |
910 | +} | |
911 | + | |
912 | +//! @brief 音楽演奏開始 | |
913 | +void pf_music_stop(void) | |
914 | +{ | |
915 | + u4 loop; | |
916 | + BOOL playing; | |
917 | + | |
918 | + // オート変数初期化 | |
919 | + loop = 0; | |
920 | + playing = FALSE; | |
921 | + | |
922 | + // 音楽デバイスだけループ | |
923 | + for (loop = 0; loop < PF_MUSIC_DEVICE_MAX; loop++) | |
924 | + { | |
925 | + // どちらかが演奏中なら、演奏中フラグを立てる | |
926 | + if (TRUE == pf_music_info[loop].playing) | |
927 | + { | |
928 | + playing = TRUE; | |
929 | + } | |
930 | + } | |
931 | + | |
932 | + // どちらかが演奏中の場合 | |
933 | + if (TRUE == playing) | |
934 | + { | |
935 | + // タイマ停止 | |
936 | + pf_timer_stop(PF_TIMER_ID_MUSIC); | |
937 | + | |
938 | + // 演奏停止 | |
939 | + for (loop = 0; loop < PF_MUSIC_DEVICE_MAX; loop++) | |
940 | + { | |
941 | + pf_music_info[loop].playing = FALSE; | |
942 | + pf_music_off(loop); | |
943 | + } | |
944 | + } | |
945 | +} |
@@ -70,16 +70,16 @@ static void pf_patrol_task_id(PF_PATROL_ID id) | ||
70 | 70 | // オート変数初期化 |
71 | 71 | gpio = pf_patrol_to_gpio[id]; |
72 | 72 | |
73 | - // 現在のフォトリフレクタ情報を取得(GPIOからの入力が'L'で白色) | |
73 | + // 現在のフォトリフレクタ情報を取得(GPIOからの入力が'L'で黒色) | |
74 | 74 | if (FALSE == pf_gpio_input(gpio)) |
75 | 75 | { |
76 | - // 白色 | |
77 | - pf_patrol_info[id] = PF_PATROL_COLOR_WHITE; | |
76 | + // 黒色 | |
77 | + pf_patrol_info[id] = PF_PATROL_COLOR_BLACK; | |
78 | 78 | } |
79 | 79 | else |
80 | 80 | { |
81 | - // 黒色 | |
82 | - pf_patrol_info[id] = PF_PATROL_COLOR_BLACK; | |
81 | + // 白色 | |
82 | + pf_patrol_info[id] = PF_PATROL_COLOR_WHITE; | |
83 | 83 | } |
84 | 84 | } |
85 | 85 |
@@ -103,7 +103,7 @@ void pf_patrol_task(void) | ||
103 | 103 | //! @brief ラインセンサの白黒状態を取得 |
104 | 104 | //! @param [in] id ラインセンサのID |
105 | 105 | //! @return 色状態(PF_PATROL_COLOR_WHITE=白色/PF_PATROL_COLOR_BLACK=黒色) |
106 | -PF_PATROL_COLOR pf_patrol_get(PF_PATROL_ID id) | |
106 | +PF_PATROL_COLOR pf_patrol_line(PF_PATROL_ID id) | |
107 | 107 | { |
108 | 108 | PF_PATROL_COLOR result; |
109 | 109 |
@@ -105,6 +105,9 @@ static void pf_power_greetings(void) | ||
105 | 105 | |
106 | 106 | // 表示OFF |
107 | 107 | pf_display_off(); |
108 | + | |
109 | + // 明るさ再設定 | |
110 | + pf_display_brightness(80); | |
108 | 111 | } |
109 | 112 | |
110 | 113 | //! @brief Power初期化 |
@@ -65,11 +65,24 @@ const PF_TIMER_INIT pf_timer_table[PF_TIMER_ID_MAX] = | ||
65 | 65 | PF_INTERRUPT_PRI_DISPLAY_TIMER, // 割り込み優先度 |
66 | 66 | PF_TIMER_ACTION_INTERVAL, // Timer動作 |
67 | 67 | 2, // コンペア数 |
68 | - MICROSEC_TO_TIMERCC(900), // コンペア値(0) | |
68 | + MICROSEC_TO_TIMERCC(800), // コンペア値(0) | |
69 | 69 | MICROSEC_TO_TIMERCC(1000), // コンペア値(1) |
70 | 70 | 0, // コンペア値(2) |
71 | 71 | 0, // コンペア値(3) |
72 | 72 | }, |
73 | + | |
74 | + // PF_TIMER_ID_MUSIC | |
75 | + { | |
76 | + 1, // チャネル | |
77 | + NRF_TIMER1, // デバイス | |
78 | + PF_INTERRUPT_PRI_MUSIC, // 割り込み優先度 | |
79 | + PF_TIMER_ACTION_INTERVAL, // Timer動作 | |
80 | + 1, // コンペア数 | |
81 | + MICROSEC_TO_TIMERCC(12500), // コンペア値(0) | |
82 | + 0, // コンペア値(1) | |
83 | + 0, // コンペア値(2) | |
84 | + 0, // コンペア値(3) | |
85 | + }, | |
73 | 86 | }; |
74 | 87 | |
75 | 88 | //! @brief compares→CLEARビットテーブル |
@@ -103,15 +116,15 @@ static const IRQn_Type pf_timer_to_irq[PF_TIMER_CHANNEL_MAX] = | ||
103 | 116 | }; |
104 | 117 | |
105 | 118 | //! @brief Timer動作情報構造体 |
106 | -typedef struct PF_TIMER_STATUS_Tag | |
119 | +typedef struct PF_TIMER_INFO_Tag | |
107 | 120 | { |
108 | 121 | PF_TIMER_CALLBACK callback; //!< コールバック関数 |
109 | 122 | u4 cc[4]; //!< コンペア値 |
110 | 123 | BOOL running; //!< 動作中フラグ |
111 | -} PF_TIMER_STATUS; | |
124 | +} PF_TIMER_INFO; | |
112 | 125 | |
113 | 126 | //! @brief Timer動作情報テーブル |
114 | -static PF_TIMER_STATUS pf_timer_status[PF_TIMER_ID_MAX]; | |
127 | +static PF_TIMER_INFO pf_timer_info[PF_TIMER_ID_MAX]; | |
115 | 128 | |
116 | 129 | //! @brief INTENSETレジスタへの設定値を得る |
117 | 130 | //! @param [in] id TimerのID |
@@ -212,12 +225,12 @@ static void pf_timer_init_id(PF_TIMER_ID id) | ||
212 | 225 | } |
213 | 226 | |
214 | 227 | // 動作情報テーブルを初期化 |
215 | - pf_timer_status[id].callback = NULL; | |
216 | - pf_timer_status[id].cc[0] = pf_timer_table[id].cc0; | |
217 | - pf_timer_status[id].cc[1] = pf_timer_table[id].cc1; | |
218 | - pf_timer_status[id].cc[2] = pf_timer_table[id].cc2; | |
219 | - pf_timer_status[id].cc[3] = pf_timer_table[id].cc3; | |
220 | - pf_timer_status[id].running = FALSE; | |
228 | + pf_timer_info[id].callback = NULL; | |
229 | + pf_timer_info[id].cc[0] = pf_timer_table[id].cc0; | |
230 | + pf_timer_info[id].cc[1] = pf_timer_table[id].cc1; | |
231 | + pf_timer_info[id].cc[2] = pf_timer_table[id].cc2; | |
232 | + pf_timer_info[id].cc[3] = pf_timer_table[id].cc3; | |
233 | + pf_timer_info[id].running = FALSE; | |
221 | 234 | |
222 | 235 | // 割り込み設定 |
223 | 236 | irq = pf_timer_to_irq[id]; |
@@ -259,7 +272,7 @@ void pf_timer_start(PF_TIMER_ID id) | ||
259 | 272 | TIMER_TASKS_START_TASKS_START_Trigger << TIMER_TASKS_START_TASKS_START_Pos; |
260 | 273 | |
261 | 274 | // 動作中フラグセット(割り込み干渉を考慮する必要はない) |
262 | - pf_timer_status[id].running = TRUE; | |
275 | + pf_timer_info[id].running = TRUE; | |
263 | 276 | } |
264 | 277 | } |
265 | 278 |
@@ -275,7 +288,7 @@ void pf_timer_stop(PF_TIMER_ID id) | ||
275 | 288 | << TIMER_TASKS_STOP_TASKS_STOP_Pos; |
276 | 289 | |
277 | 290 | // 動作中フラグクリア(割り込み干渉を考慮する必要はない) |
278 | - pf_timer_status[id].running = FALSE; | |
291 | + pf_timer_info[id].running = FALSE; | |
279 | 292 | } |
280 | 293 | } |
281 | 294 |
@@ -303,7 +316,7 @@ void pf_timer_callback(PF_TIMER_ID id, PF_TIMER_CALLBACK func) | ||
303 | 316 | NVIC_DisableIRQ(irq); |
304 | 317 | |
305 | 318 | // コールバック関数設定 |
306 | - pf_timer_status[id].callback = func; | |
319 | + pf_timer_info[id].callback = func; | |
307 | 320 | |
308 | 321 | // 割り込み復元 |
309 | 322 | if (0 != enable) |
@@ -339,10 +352,10 @@ void pf_timer_cc(PF_TIMER_ID id, u4 *cc) | ||
339 | 352 | for (loop = 0; loop < pf_timer_table[id].compares; loop++) |
340 | 353 | { |
341 | 354 | // 異なっている要素だけ設定する |
342 | - if (pf_timer_status[id].cc[loop] != cc[loop]) | |
355 | + if (pf_timer_info[id].cc[loop] != cc[loop]) | |
343 | 356 | { |
344 | - pf_timer_status[id].cc[loop] = cc[loop]; | |
345 | - pf_timer_table[id].dev->CC[loop] = pf_timer_status[id].cc[loop]; | |
357 | + pf_timer_info[id].cc[loop] = cc[loop]; | |
358 | + pf_timer_table[id].dev->CC[loop] = pf_timer_info[id].cc[loop]; | |
346 | 359 | } |
347 | 360 | } |
348 | 361 |
@@ -418,9 +431,9 @@ static void pf_timer_isr(u4 channel) | ||
418 | 431 | } |
419 | 432 | |
420 | 433 | // Timerコールバック関数が登録されていれば、呼び出す |
421 | - if (NULL != pf_timer_status[id].callback) | |
434 | + if (NULL != pf_timer_info[id].callback) | |
422 | 435 | { |
423 | - pf_timer_status[id].callback(compare); | |
436 | + pf_timer_info[id].callback(compare); | |
424 | 437 | } |
425 | 438 | } |
426 | 439 | } |