• R/O
  • HTTP
  • SSH
  • HTTPS

Commit

Tags
Aucun tag

Frequently used words (click to add to your profile)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

C言語でBBC micro:bit V2およびDFRobot micro:Maqueenを操作する


Commit MetaInfo

Révision36a310d424be73183201349582b7d1ef92043297 (tree)
l'heure2023-09-18 08:13:12
Auteurxm6_original <tanaka_yasushi2008@yaho...>
Commiterxm6_original

Message de Log

NeoPixel実装中

Change Summary

Modification

--- a/Maqueen_Lv2/include/pf_gpio.h
+++ b/Maqueen_Lv2/include/pf_gpio.h
@@ -44,6 +44,7 @@ typedef enum PF_GPIO_ID_Tag
4444 PF_GPIO_ID_COL5, //!< Display COL5
4545 PF_GPIO_ID_BUTTON_A, //!< BUTTON A
4646 PF_GPIO_ID_BUTTON_B, //!< BUTTON B
47+ PF_FPIO_ID_INTERNAL_IRQ, //!< 内部I2Cバス IRQ
4748 PF_GPIO_ID_INTERNAL_SCL, //!< 内部I2Cバス SCL
4849 PF_GPIO_ID_INTERNAL_SDA, //!< 内部I2Cバス SDA
4950 PF_GPIO_ID_EXTERNAL_SCL, //!< 外部I2Cバス SCL
@@ -56,6 +57,8 @@ typedef enum PF_GPIO_ID_Tag
5657 PF_GPIO_ID_MAQUEEN_PATROL_R, //!< MAQUEEN PATROL R
5758 PF_GPIO_ID_MAQUEEN_TRIG, //!< MAQUEEN 超音波 TRIG
5859 PF_GPIO_ID_MAQUEEN_ECHO, //!< MAQUEEN 超音波 ECHO
60+ PF_GPIO_ID_MAQUEEN_NEOPIXEL, //!< MAQUEEN NeoPixel
61+ PF_GPIO_ID_MAQUEEN_NECIR, //!< MAQUEEN NECフォーマット Ir
5962 PF_GPIO_ID_MAX, //!< (IDの個数を表す)
6063 } PF_GPIO_ID;
6164
--- a/Maqueen_Lv2/include/pf_interrupt.h
+++ b/Maqueen_Lv2/include/pf_interrupt.h
@@ -36,7 +36,6 @@ typedef enum PF_INTERRUPT_PRI_Tag
3636 PF_INTERRUPT_PRI_I2C_INT, //!< I2C(内部)
3737 PF_INTERRUPT_PRI_I2C_EXT, //!< I2C(外部)
3838 PF_INTERRUPT_PRI_MUSIC, //!< 音楽演奏
39- PF_INTERRUPT_PRI_ULTRA, //!< 超音波
4039 } PF_INTERRUPT_PRI;
4140
4241 //! @brief グローバル割り込み禁止
@@ -47,6 +46,11 @@ u4 pf_interrupt_global_disable(void);
4746 //! @param [in] primask pf_interrupt_global_disable()の返り値
4847 void pf_interrupt_global_restore(u4 primask);
4948
49+//! @brief ローカル割り込みセットアップ
50+//! @details 割り込み優先度の設定と、割り込み許可を行う
51+//! @param [in] pri 割り込み優先度
52+void pf_interrupt_local_setup(PF_INTERRUPT_PRI pri);
53+
5054 //! @brief ローカル割り込み禁止
5155 //! @param [in] pri 割り込み優先度
5256 //! @return 直前のローカル割り込み禁止状態(1:割り込み禁止/0:割り込み許可)
--- /dev/null
+++ b/Maqueen_Lv2/include/pf_neopixel.h
@@ -0,0 +1,62 @@
1+//! @file pf_neopixel.h
2+//! @brief プラットフォーム(NeoPixel)ヘッダファイル
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_NEOPIXEL_H
26+#define PF_NEOPIXEL_H
27+
28+#include "pf_types.h"
29+
30+//! @brief NeoPixelカラー構造体
31+//! @details 消費電力を考慮し7bitとしているが、各々32以下の値に設定することを推奨する
32+typedef struct PF_NEOPIXEL_COLOR_Tag
33+{
34+ u1 r; //!< R(赤色レベル)(0~127)
35+ u1 g; //!< G(緑色レベル)(0~127)
36+ u1 b; //!< B(青色レベル)(0~127)
37+} PF_NEOPIXEL_COLOR;
38+
39+//! @brief NeoPixelのID
40+typedef enum PF_NEOPIXEL_ID_Tag
41+{
42+ PF_NEOPIXEL_ID_RGB0, //!< 前方左側
43+ PF_NEOPIXEL_ID_RGB1, //!< 後方左側
44+ PF_NEOPIXEL_ID_RGB2, //!< 後方右側
45+ PF_NEOPIXEL_ID_RGB3, //!< 前方右側
46+ PF_NEOPIXEL_ID_MAX, //!< (IDの個数を表す)
47+} PF_NEOPIXEL_ID;
48+
49+//! @brief NeoPixel初期化
50+//! @remarks プラットフォーム初期化処理から呼び出すこと
51+void pf_neopixel_init(void);
52+
53+//! @brief NeoPixel定期タスク
54+//! @remarks プラットフォーム定期タスク(出力系)処理から呼び出すこと
55+void pf_neopixel_task(void);
56+
57+//! @brief NeoPixel制御
58+//! @param [in] id NeoPixelのID
59+//! @param [in] color NeoPixelカラー構造体へのポインタ
60+void pf_neopixel_ctrl(PF_NEOPIXEL_ID id, const PF_NEOPIXEL_COLOR *color);
61+
62+#endif // PF_NEXOPIXEL_H
--- a/Maqueen_Lv2/include/pf_ultra.h
+++ b/Maqueen_Lv2/include/pf_ultra.h
@@ -46,8 +46,4 @@ void pf_ultra_enable(BOOL enable);
4646 //! @return 前方障害物までの距離(単位:cm)
4747 u4 pf_ultra_get(void);
4848
49-//! @brief GPIOTE割り込みハンドラ
50-//! @attention データ競合(割り込み干渉)に注意する
51-void GPIOTE_IRQHandler(void);
52-
5349 #endif // PF_ULTRA_H
--- a/Maqueen_Lv2/src/main.c
+++ b/Maqueen_Lv2/src/main.c
@@ -298,11 +298,11 @@ static void app_mode_task(void)
298298 }
299299 else
300300 {
301+ // 走行→停止に限り、ステップを戻す
301302 app_run = FALSE;
303+ app_step = 0;
302304 }
303305
304- // ステップを戻す
305- app_step = 0;
306306 break;
307307 }
308308 }
@@ -522,7 +522,8 @@ static BOOL app_run_ultra(void)
522522 // 走行停止
523523 run = FALSE;
524524 app_run = FALSE;
525- app_step = 0;
525+
526+ // app_stepは変更しない(矩形走行をそのまま再開したい)
526527 }
527528 }
528529
--- /dev/null
+++ b/Maqueen_Lv2/src/pf/neopixelsend.S
@@ -0,0 +1,110 @@
1+/*
2+ Portions of this code based on code provided under MIT license from Microsoft
3+ https://github.com/Microsoft/pxt-ws2812b
4+
5+ MIT License
6+
7+ Copyright (c) Microsoft Corporation. All rights reserved.
8+
9+ Permission is hereby granted, free of charge, to any person obtaining a copy
10+ of this software and associated documentation files (the "Software"), to deal
11+ in the Software without restriction, including without limitation the rights
12+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13+ copies of the Software, and to permit persons to whom the Software is
14+ furnished to do so, subject to the following conditions:
15+
16+ The above copyright notice and this permission notice shall be included in all
17+ copies or substantial portions of the Software.'
18+
19+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25+ SOFTWARE
26+*/
27+
28+.global sendNeopixelBuffer
29+
30+ /* declared as extern void sendBuffer(uint32_t pin, uint8_t* data_address, uint16_t num_bytes) */
31+
32+sendNeopixelBuffer:
33+ push {r0, r1, r2, r3, r4, r5, r6}
34+
35+ /*
36+ We are expecting from the callee:
37+ r0 = pinmask to waggle in the GPIO register
38+ r1 = address of the data we are supposed to be sending
39+ r2 = number of bytes to send
40+
41+ Setup the initial values
42+ r1 = Pin mask in the GPIO register
43+ r2 = GPIO clear register
44+ r3 = GPIO SET
45+ r4 = Address pointer for the data - we cast this as a byte earlier because it really is.
46+ r5 = Length of the data
47+ r6 = Parallel to serial conversion mask
48+ */
49+ mov r4, r1
50+ mov r5, r2
51+
52+ /*load the pin set and clr addresses by a cunning combo of shifts and adds*/
53+ movs r3, #160
54+ movs r1, #0x0c
55+ lsl r3, r3, #15
56+ add r3, #05
57+ lsl r3, r3, #8
58+ add r2, r3, r1
59+ add r3, #0x08
60+
61+ mov r1, r0 /* finally move the pin mask from r0 to r1*/
62+
63+ /*
64+ This code serialises the data bits for each LED.
65+ The data byte is loaded in the common section (label .common) and then each bit is masked and tested for '0' (label .nextbit)
66+ If it is a '0' we turn off the pin asap and then move to the code that advances to the next bit/byte. If a '1' we leave the pin on and do the same thing.
67+ If the mask (r6) is still valid then we are still moving out the current byte, so repeat.
68+ If it is '0' then we have done this byte and need to load the next byte from the pointer in r4.
69+ r5 contains the count of bytes.
70+ Once we run r5 down to '0' we exit the data shifting and return.
71+ */
72+
73+ mrs r6, PRIMASK /* disable interrupts whilst we mess with timing critical waggling. */
74+ push {r6}
75+ cpsid i
76+
77+ b .start
78+
79+ .nextbit:
80+ str r1, [r3, #0]
81+ tst r6, r0
82+ bne .bitisone
83+ str r1, [r2, #0]
84+ .bitisone:
85+ lsr r6, #1
86+ bne .justbit
87+
88+ add r4, #1
89+ sub r5, #1
90+ beq .stop
91+
92+ .start:
93+ movs r6, #0x80
94+ nop
95+
96+ .common:
97+ str r1, [r2, #0]
98+ ldrb r0, [r4, #0]
99+ b .nextbit
100+
101+ .justbit:
102+ b .common
103+
104+ .stop:
105+ str r1, [r2, #0]
106+
107+ pop {r6}
108+ msr PRIMASK, r6
109+ pop {r0, r1, r2, r3, r4, r5, r6}
110+ bx lr
--- a/Maqueen_Lv2/src/pf/pf_gpio.c
+++ b/Maqueen_Lv2/src/pf/pf_gpio.c
@@ -26,6 +26,13 @@
2626 #include "nrf52833.h"
2727 #include "pf_gpio.h"
2828
29+//! @brief ポート数
30+#define PF_GPIO_PORT_MAX ((u4)2U)
31+
32+//! @brief 未使用ピン数
33+//! @details 外乱ノイズの影響を避ける目的で、内蔵プルアップ抵抗を使用する
34+#define PF_GPIO_NC_PIN_MAX ((u4)9U)
35+
2936 //! @brief 入出力方向
3037 typedef enum PF_GPIO_DIR_Tag
3138 {
@@ -74,7 +81,7 @@ typedef struct PF_GPIO_INIT_Tag
7481 } PF_GPIO_INIT;
7582
7683 //! @brief GPIOピン初期化情報テーブル
77-const PF_GPIO_INIT pf_gpio_init_table[PF_GPIO_ID_MAX] =
84+static const PF_GPIO_INIT pf_gpio_init_table[PF_GPIO_ID_MAX] =
7885 {
7986 // PF_GPIO_ID_UART_TXD
8087 {
@@ -231,6 +238,17 @@ const PF_GPIO_INIT pf_gpio_init_table[PF_GPIO_ID_MAX] =
231238 PF_GPIO_DRIVE_S0S1, // 駆動特性
232239 },
233240
241+ // PF_FPIO_ID_INTERNAL_IRQ
242+ {
243+ 0, // ポート
244+ 25, // ピン
245+ FALSE, // 初期出力レベル
246+ PF_GPIO_DIR_INPUT, // 入出力方向
247+ PF_GPIO_INBUF_CONNECT, // 入力バッファ
248+ PF_GPIO_PULL_UP, // プルアップ・プルダウン
249+ PF_GPIO_DRIVE_S0S1, // 駆動特性
250+ },
251+
234252 // PF_GPIO_ID_INTERNAL_SCL
235253 {
236254 0, // ポート
@@ -283,7 +301,7 @@ const PF_GPIO_INIT pf_gpio_init_table[PF_GPIO_ID_MAX] =
283301 PF_GPIO_DIR_OUTPUT, // 入出力方向
284302 PF_GPIO_INBUF_DISCONNECT, // 入力バッファ
285303 PF_GPIO_PULL_NONE, // プルアップ・プルダウン
286- PF_GPIO_DRIVE_S0S1, // 駆動特性
304+ PF_GPIO_DRIVE_H0H1, // 駆動特性
287305 },
288306
289307 // PF_GPIO_ID_MAQUEEN_SPEAKER
@@ -362,29 +380,122 @@ const PF_GPIO_INIT pf_gpio_init_table[PF_GPIO_ID_MAX] =
362380 PF_GPIO_PULL_NONE, // プルアップ・プルダウン
363381 PF_GPIO_DRIVE_S0S1, // 駆動特性
364382 },
383+
384+ // PF_GPIO_ID_MAQUEEN_NEOPIXEL
385+ {
386+ 0, // ポート
387+ 13, // ピン
388+ FALSE, // 初期出力レベル
389+ PF_GPIO_DIR_OUTPUT, // 入出力方向
390+ PF_GPIO_INBUF_DISCONNECT, // 入力バッファ
391+ PF_GPIO_PULL_NONE, // プルアップ・プルダウン
392+ PF_GPIO_DRIVE_S0S1, // 駆動特性
393+ },
394+
395+ // PF_GPIO_ID_MAQUEEN_NECIR
396+ {
397+ 1, // ポート
398+ 2, // ピン
399+ FALSE, // 初期出力レベル
400+ PF_GPIO_DIR_INPUT, // 入出力方向
401+ PF_GPIO_INBUF_CONNECT, // 入力バッファ
402+ PF_GPIO_PULL_NONE, // プルアップ・プルダウン
403+ PF_GPIO_DRIVE_S0S1, // 駆動特性
404+ },
365405 };
366406
367-//! @brief GPIOデバイス取得
368-//! @param [in] id GPIOピンのID
369-//! @return GPIOデバイスへのポインタ
370-static NRF_GPIO_Type* pf_gpio_get_dev(PF_GPIO_ID id)
407+//! @brief GPIOピン未使用情報構造体
408+typedef struct PF_GPIO_NC_Tag
409+{
410+ u4 port; //!< ポート(0~1)
411+ u4 pin; //!< ピン(0~31)
412+} PF_GPIO_NC;
413+
414+//! @brief GPIOピン未使用情報テーブル
415+static const PF_GPIO_NC pf_gpio_nc_table[PF_GPIO_NC_PIN_MAX] =
371416 {
417+ // P0.07
418+ {
419+ 0,
420+ 7,
421+ },
422+
423+ // P0.18
424+ {
425+ 0,
426+ 18,
427+ },
428+
429+ // P0.27
430+ {
431+ 0,
432+ 27,
433+ },
434+
435+ // P0.29
436+ {
437+ 0,
438+ 29,
439+ },
440+
441+ // P1.01
442+ {
443+ 1,
444+ 1,
445+ },
446+
447+ // P1.03
448+ {
449+ 1,
450+ 3,
451+ },
452+
453+ // P1.06
454+ {
455+ 1,
456+ 6,
457+ },
458+
459+ // P1.07
460+ {
461+ 1,
462+ 7,
463+ },
464+
465+ // P1.09
466+ {
467+ 1,
468+ 9,
469+ },
470+};
471+
472+//! @brief GPIOポート→デバイステーブル
473+static NRF_GPIO_Type* const pf_gpio_port_to_dev[PF_GPIO_PORT_MAX] =
474+{
475+ NRF_P0, //!< ポート0
476+ NRF_P1, //!< ポート1
477+};
478+
479+//! @brief GPIO初期化(未使用ピン)
480+static void pf_gpio_init_nc(void)
481+{
482+ u4 loop;
372483 NRF_GPIO_Type *dev;
484+ u4 cnf;
373485
374486 // オート変数初期化
487+ loop = 0;
375488 dev = NULL;
489+ cnf = PF_GPIO_DIR_INPUT | PF_GPIO_INBUF_DISCONNECT | PF_GPIO_PULL_UP | PF_GPIO_DRIVE_S0S1;
376490
377- // ポート別振り分け
378- if (0 == pf_gpio_init_table[id].port)
491+ for (loop = 0; loop < PF_GPIO_NC_PIN_MAX; loop++)
379492 {
380- dev = NRF_P0;
381- }
382- else
383- {
384- dev = NRF_P1;
385- }
493+ // ポートからデバイスを取得
494+ dev = pf_gpio_port_to_dev[pf_gpio_nc_table[loop].port];
386495
387- return dev;
496+ // PIN_CNFレジスタを設定
497+ dev->PIN_CNF[pf_gpio_nc_table[loop].pin] = cnf;
498+ }
388499 }
389500
390501 //! @brief GPIO初期化(単一のID)
@@ -403,7 +514,7 @@ static void pf_gpio_init_id(PF_GPIO_ID id)
403514 }
404515
405516 // IDからデバイスを取得
406- dev = pf_gpio_get_dev(id);
517+ dev = pf_gpio_port_to_dev[pf_gpio_init_table[id].port];
407518
408519 // コンフィグ設定
409520 dev->PIN_CNF[pf_gpio_init_table[id].pin] = (u4)(pf_gpio_init_table[id].dir
@@ -421,6 +532,9 @@ void pf_gpio_init(void)
421532 // オート変数初期化
422533 id = 0;
423534
535+ // 未使用ピンを初期化
536+ pf_gpio_init_nc();
537+
424538 // すべてのIDをループ
425539 for (id = 0; id < PF_GPIO_ID_MAX; id++)
426540 {
@@ -485,7 +599,7 @@ BOOL pf_gpio_input(PF_GPIO_ID id)
485599 if (id < PF_GPIO_ID_MAX)
486600 {
487601 // IDからデバイスを取得
488- dev = pf_gpio_get_dev(id);
602+ dev = pf_gpio_port_to_dev[pf_gpio_init_table[id].port];
489603
490604 // 当該ピンのみを取り出した情報を取得
491605 in = dev->IN & (1 << pf_gpio_init_table[id].pin);
@@ -520,7 +634,7 @@ void pf_gpio_output(PF_GPIO_ID id, BOOL level)
520634 if (id < PF_GPIO_ID_MAX)
521635 {
522636 // IDからデバイスを取得
523- dev = pf_gpio_get_dev(id);
637+ dev = pf_gpio_port_to_dev[pf_gpio_init_table[id].port];
524638
525639 // 出力
526640 if (FALSE == level)
--- a/Maqueen_Lv2/src/pf/pf_i2c.c
+++ b/Maqueen_Lv2/src/pf/pf_i2c.c
@@ -90,13 +90,6 @@ static const PF_INTERRUPT_PRI pf_i2c_channel_to_pri[PF_I2C_CHANNEL_MAX] =
9090 PF_INTERRUPT_PRI_I2C_EXT, //!< チャネル1(外部)
9191 };
9292
93-//! @brief I2Cチャネル→割り込み番号テーブル
94-static const IRQn_Type pf_i2c_channel_to_irq[PF_I2C_CHANNEL_MAX] =
95-{
96- SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0_IRQn, //!< チャネル0(内部)
97- SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1_IRQn, //!< チャネル1(外部)
98-};
99-
10093 //! @brief I2C割り込み禁止
10194 //! @param [in] channel I2Cチャネル(0=内部/1=外部)
10295 //! @return 直前のI2C割り込み禁止状態(1:割り込み禁止/0:割り込み許可)
@@ -214,8 +207,6 @@ static void pf_i2c_init_id(PF_I2C_ID id)
214207 static void pf_i2c_init_dev(u4 channel)
215208 {
216209 NRF_TWIM_Type *dev;
217- PF_INTERRUPT_PRI pri;
218- IRQn_Type irq;
219210 u4 scl_port;
220211 u4 scl_pin;
221212 u4 sda_port;
@@ -223,8 +214,6 @@ static void pf_i2c_init_dev(u4 channel)
223214
224215 // オート変数初期化
225216 dev = pf_i2c_channel_to_dev[channel];
226- pri = pf_i2c_channel_to_pri[channel];
227- irq = pf_i2c_channel_to_irq[channel];
228217 scl_port = 0;
229218 scl_pin = 0;
230219 sda_port = 0;
@@ -237,10 +226,8 @@ static void pf_i2c_init_dev(u4 channel)
237226 dev->INTEN = (TWIM_INTEN_STOPPED_Enabled << TWIM_INTEN_STOPPED_Pos)
238227 | (TWIM_INTEN_ERROR_Enabled << TWIM_INTEN_ERROR_Pos);
239228
240- // 割り込み設定
241- NVIC_SetPriority(irq, pri);
242- NVIC_ClearPendingIRQ(irq);
243- NVIC_EnableIRQ(irq);
229+ // 割り込みセットアップ
230+ pf_interrupt_local_setup(pf_i2c_channel_to_pri[channel]);
244231
245232 // 転送速度(400kbps)
246233 dev->FREQUENCY = TWIM_FREQUENCY_FREQUENCY_K400 << TWIM_FREQUENCY_FREQUENCY_Pos;
--- a/Maqueen_Lv2/src/pf/pf_interrupt.c
+++ b/Maqueen_Lv2/src/pf/pf_interrupt.c
@@ -98,11 +98,6 @@ static IRQn_Type pf_interrupt_get_irq(PF_INTERRUPT_PRI pri)
9898 irq = TIMER1_IRQn;
9999 break;
100100
101- // 超音波
102- case PF_INTERRUPT_PRI_ULTRA:
103- irq = GPIOTE_IRQn;
104- break;
105-
106101 default:
107102 break;
108103 }
@@ -110,6 +105,32 @@ static IRQn_Type pf_interrupt_get_irq(PF_INTERRUPT_PRI pri)
110105 return irq;
111106 }
112107
108+//! @brief ローカル割り込みセットアップ
109+//! @details 割り込み優先度の設定と、割り込み許可を行う
110+//! @param [in] pri 割り込み優先度
111+void pf_interrupt_local_setup(PF_INTERRUPT_PRI pri)
112+{
113+ IRQn_Type irq;
114+
115+ // オート変数初期化
116+ irq = UARTE1_IRQn;
117+
118+ // SysTickは扱わない
119+ if (PF_INTERRUPT_PRI_SYSTICK != pri)
120+ {
121+ // 割り込み優先度から割り込み番号を取得
122+ irq = pf_interrupt_get_irq(pri);
123+
124+ // 特定できた場合のみ、割り込みセットアップを行う
125+ if (UARTE1_IRQn != irq)
126+ {
127+ NVIC_SetPriority(irq, pri);
128+ NVIC_ClearPendingIRQ(irq);
129+ NVIC_EnableIRQ(irq);
130+ }
131+ }
132+}
133+
113134 //! @brief ローカル割り込み禁止
114135 //! @param [in] pri 割り込み優先度
115136 //! @return 直前のローカル割り込み禁止状態(1:割り込み禁止/0:割り込み許可)
--- /dev/null
+++ b/Maqueen_Lv2/src/pf/pf_neopixel.c
@@ -0,0 +1,102 @@
1+//! @file pf_neopixel.c
2+//! @brief プラットフォーム(NeoPixel)実装ファイル
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 "pf_gpio.h"
27+#include "pf_neopixel.h"
28+
29+//! @brief NepPixelあたりの送信バイト数
30+#define PF_NEOPIXEL_SEND_BYTES ((u4)24U)
31+
32+//! @brief R/G/Bの階調マスク値
33+#define PF_NEOPIXEL_COLOR_MASK ((u1)0x7FU)
34+
35+//! @brief 外部関数(アセンブラ)定義
36+//! @details pin=13<<1, num_bytes=(Gx8,Bx8,Rx8)xLEDs=96を指定する
37+extern void sendNeopixelBuffer(uint32_t pin, uint8_t* data_address, uint16_t num_bytes);
38+
39+//! @brief NeoPixel動作情報構造体
40+typedef struct PF_NEOPIXEL_INFO_Tag
41+{
42+ PF_NEOPIXEL_COLOR current[PF_NEOPIXEL_ID_MAX]; //!< 現在のRGB
43+ PF_NEOPIXEL_COLOR target[PF_NEOPIXEL_ID_MAX]; //!< 目的とするRGB
44+ u1 buf[PF_NEOPIXEL_ID_MAX][PF_NEOPIXEL_SEND_BYTES]; //!< 送信バッファ
45+} PF_NEOPIXEL_INFO;
46+
47+//! @brief NeoPixel動作情報
48+static PF_NEOPIXEL_INFO pf_neopixel_info;
49+
50+//! @brief NeoPixel初期化(単一のID)
51+//! @param [in] id NeoPixelのID
52+static void pf_neopixel_init_id(PF_NEOPIXEL_ID id)
53+{
54+ // 現在の状態は消灯
55+ pf_neopixel_info.current[id].r = 0U;
56+ pf_neopixel_info.current[id].g = 0U;
57+ pf_neopixel_info.current[id].b = 0U;
58+
59+ // 目的とする状態は消灯
60+ pf_neopixel_info.target[id].r = 0U;
61+ pf_neopixel_info.target[id].g = 0U;
62+ pf_neopixel_info.target[id].b = 0U;
63+}
64+
65+//! @brief NeoPixel初期化
66+//! @remarks プラットフォーム初期化処理から呼び出すこと
67+void pf_neopixel_init(void)
68+{
69+ PF_NEOPIXEL_ID id;
70+
71+ // オート変数初期化
72+ id = 0;
73+
74+ // すべてのIDをループ
75+ for (id = 0; id < PF_NEOPIXEL_ID_MAX; id++)
76+ {
77+ // 1つのIDを初期化
78+ pf_neopixel_init_id(id);
79+ }
80+}
81+
82+//! @brief NeoPixel定期タスク
83+//! @remarks プラットフォーム定期タスク(出力系)処理から呼び出すこと
84+void pf_neopixel_task(void)
85+{
86+
87+}
88+
89+//! @brief NeoPixel制御
90+//! @param [in] id NeoPixelのID
91+//! @param [in] color NeoPixelカラー構造体へのポインタ
92+void pf_neopixel_ctrl(PF_NEOPIXEL_ID id, const PF_NEOPIXEL_COLOR *color)
93+{
94+ // パラメータチェック
95+ if (id < PF_NEOPIXEL_ID_MAX)
96+ {
97+ // RGBカラーをセット
98+ pf_neopixel_info.target[id].r = color->r & PF_NEOPIXEL_COLOR_MASK;
99+ pf_neopixel_info.target[id].g = color->g & PF_NEOPIXEL_COLOR_MASK;
100+ pf_neopixel_info.target[id].b = color->b & PF_NEOPIXEL_COLOR_MASK;
101+ }
102+}
--- a/Maqueen_Lv2/src/pf/pf_timer.c
+++ b/Maqueen_Lv2/src/pf/pf_timer.c
@@ -85,7 +85,7 @@ const PF_TIMER_INIT pf_timer_table[PF_TIMER_ID_MAX] =
8585 0, // コンペア値(3)
8686 },
8787
88- // PF_TIMER_ID_ULTRASONIC
88+ // PF_TIMER_ID_ULTRA
8989 {
9090 2, // チャネル
9191 NRF_TIMER2, // デバイス
@@ -119,16 +119,6 @@ static const u4 pf_timer_stop_table[PF_TIMER_COMPARE_MAX + 1] =
119119 TIMER_SHORTS_COMPARE3_STOP_Enabled << TIMER_SHORTS_COMPARE3_STOP_Pos,
120120 };
121121
122-//! @brief Timer→割り込み番号テーブル
123-static const IRQn_Type pf_timer_to_irq[PF_TIMER_CHANNEL_MAX] =
124-{
125- TIMER0_IRQn, //!< Timer0
126- TIMER1_IRQn, //!< Timer1
127- TIMER2_IRQn, //!< Timer2
128- TIMER3_IRQn, //!< Timer3
129- TIMER4_IRQn, //!< Timer4
130-};
131-
132122 //! @brief Timer動作情報構造体
133123 typedef struct PF_TIMER_INFO_Tag
134124 {
@@ -181,11 +171,6 @@ static u4 pf_timer_get_intenset(PF_TIMER_ID id)
181171 //! @param [in] id TimerのID
182172 static void pf_timer_init_id(PF_TIMER_ID id)
183173 {
184- IRQn_Type irq;
185-
186- // オート変数初期化
187- irq = TIMER0_IRQn;
188-
189174 // タイマ停止
190175 pf_timer_table[id].dev->TASKS_STOP = TIMER_TASKS_STOP_TASKS_STOP_Trigger
191176 << TIMER_TASKS_STOP_TASKS_STOP_Pos;
@@ -258,11 +243,8 @@ static void pf_timer_init_id(PF_TIMER_ID id)
258243 // キャプチャモード以外は割り込みを使用する
259244 if (PF_TIMER_ACTION_CAPTURE != pf_timer_table[id].action)
260245 {
261- // 割り込み設定
262- irq = pf_timer_to_irq[id];
263- NVIC_SetPriority(irq, pf_timer_table[id].priority);
264- NVIC_ClearPendingIRQ(irq);
265- NVIC_EnableIRQ(irq);
246+ // 割り込みセットアップ
247+ pf_interrupt_local_setup(pf_timer_table[id].priority);
266248 }
267249 }
268250
@@ -294,12 +276,6 @@ void pf_timer_start(PF_TIMER_ID id)
294276 pf_timer_table[id].dev->TASKS_CLEAR =
295277 TIMER_TASKS_CLEAR_TASKS_CLEAR_Trigger << TIMER_TASKS_CLEAR_TASKS_CLEAR_Pos;
296278
297-// // キャプチャモード時はCC[0]をクリア
298-// if (PF_TIMER_ACTION_CAPTURE == pf_timer_table[id].action)
299-// {
300-// pf_timer_table[id].dev->CC[0] = 0;
301-// }
302-
303279 // 開始
304280 pf_timer_table[id].dev->TASKS_START =
305281 TIMER_TASKS_START_TASKS_START_Trigger << TIMER_TASKS_START_TASKS_START_Pos;
@@ -331,31 +307,22 @@ void pf_timer_stop(PF_TIMER_ID id)
331307 //! @attention Timerコールバック関数は割り込みコンテキストで呼び出される
332308 void pf_timer_callback(PF_TIMER_ID id, PF_TIMER_CALLBACK func)
333309 {
334- IRQn_Type irq;
335310 u4 enable;
336311
337312 // オート変数初期化
338- irq = TIMER0_IRQn;
339313 enable = 0;
340314
341315 // IDチェック
342316 if (id < PF_TIMER_ID_MAX)
343317 {
344- // IDに対応したIRQを取得
345- irq = pf_timer_to_irq[id];
346-
347318 // 割り込み禁止
348- enable = NVIC_GetEnableIRQ(irq);
349- NVIC_DisableIRQ(irq);
319+ enable = pf_interrupt_local_disable(pf_timer_table[id].priority);
350320
351321 // コールバック関数設定
352322 pf_timer_info[id].callback = func;
353323
354324 // 割り込み復元
355- if (0 != enable)
356- {
357- NVIC_EnableIRQ(irq);
358- }
325+ pf_interrupt_local_restore(pf_timer_table[id].priority, enable);
359326 }
360327 }
361328
@@ -364,22 +331,18 @@ void pf_timer_callback(PF_TIMER_ID id, PF_TIMER_CALLBACK func)
364331 //! @param [in] cc コンペアカウンタ配列
365332 void pf_timer_cc(PF_TIMER_ID id, u4 *cc)
366333 {
367- IRQn_Type irq;
368334 u4 enable;
369335 u4 loop;
370336
371337 // オート変数初期化
372- irq = TIMER0_IRQn;
338+ enable = 0;
339+ loop = 0;
373340
374341 // パラメータチェック
375342 if ((id < PF_TIMER_ID_MAX) && (NULL != cc))
376343 {
377- // IDに対応したIRQを取得
378- irq = pf_timer_to_irq[id];
379-
380344 // 割り込み禁止
381- enable = NVIC_GetEnableIRQ(irq);
382- NVIC_DisableIRQ(irq);
345+ enable = pf_interrupt_local_disable(pf_timer_table[id].priority);
383346
384347 // CCループ
385348 for (loop = 0; loop < pf_timer_table[id].compares; loop++)
@@ -393,10 +356,7 @@ void pf_timer_cc(PF_TIMER_ID id, u4 *cc)
393356 }
394357
395358 // 割り込み復元
396- if (0 != enable)
397- {
398- NVIC_EnableIRQ(irq);
399- }
359+ pf_interrupt_local_restore(pf_timer_table[id].priority, enable);
400360 }
401361 }
402362
@@ -413,11 +373,14 @@ u4 pf_timer_get_capture(PF_TIMER_ID id)
413373 // パラメータチェック
414374 if (id < PF_TIMER_ID_MAX)
415375 {
376+ // キャプチャ値を取得
416377 capture = pf_timer_table[id].dev->CC[0];
417378
418- // 次回に備え、停止・クリア・CC[0]クリアを行う
419- pf_timer_table[id].dev->TASKS_STOP = TIMER_TASKS_STOP_TASKS_STOP_Trigger << TIMER_TASKS_STOP_TASKS_STOP_Pos;
420- pf_timer_table[id].dev->TASKS_CLEAR = TIMER_TASKS_CLEAR_TASKS_CLEAR_Trigger << TIMER_TASKS_CLEAR_TASKS_CLEAR_Pos;
379+ // 次回に備え、停止・クリア・CC[0]クリアを行う(割り込みは考慮しなくてよい)
380+ pf_timer_table[id].dev->TASKS_STOP = TIMER_TASKS_STOP_TASKS_STOP_Trigger
381+ << TIMER_TASKS_STOP_TASKS_STOP_Pos;
382+ pf_timer_table[id].dev->TASKS_CLEAR = TIMER_TASKS_CLEAR_TASKS_CLEAR_Trigger
383+ << TIMER_TASKS_CLEAR_TASKS_CLEAR_Pos;
421384 pf_timer_table[id].dev->CC[0] = 0;
422385 }
423386
--- a/Maqueen_Lv2/src/pf/pf_uart.c
+++ b/Maqueen_Lv2/src/pf/pf_uart.c
@@ -194,8 +194,7 @@ static void pf_uart_poll_rxd(void)
194194 void pf_uart_init(void)
195195 {
196196 // UART無効化
197- NRF_UARTE0->ENABLE =
198- UARTE_ENABLE_ENABLE_Disabled << UARTE_ENABLE_ENABLE_Pos;
197+ NRF_UARTE0->ENABLE = UARTE_ENABLE_ENABLE_Disabled << UARTE_ENABLE_ENABLE_Pos;
199198
200199 // バッファ初期化
201200 pf_uart_init_buf(PF_UART_BUF_ID_TXD);
@@ -212,10 +211,8 @@ void pf_uart_init(void)
212211 | (UARTE_INTEN_ERROR_Enabled << UARTE_INTEN_ERROR_Pos)
213212 | (UARTE_INTEN_RXSTARTED_Enabled << UARTE_INTEN_RXSTARTED_Pos);
214213
215- // 割り込み設定
216- NVIC_SetPriority(UARTE0_UART0_IRQn, PF_INTERRUPT_PRI_UART);
217- NVIC_ClearPendingIRQ(UARTE0_UART0_IRQn);
218- NVIC_EnableIRQ(UARTE0_UART0_IRQn);
214+ // 割り込みセットアップ
215+ pf_interrupt_local_setup(PF_INTERRUPT_PRI_UART);
219216
220217 // 受信エラーをすべてクリア
221218 NRF_UARTE0->ERRORSRC = (UARTE_ERRORSRC_OVERRUN_NotPresent << UARTE_ERRORSRC_OVERRUN_Pos)
@@ -224,7 +221,7 @@ void pf_uart_init(void)
224221 | (UARTE_ERRORSRC_BREAK_NotPresent << UARTE_ERRORSRC_BREAK_Pos);
225222
226223 // RTSピン設定(使用しない)
227- NRF_UARTE0->PSEL.RTS |= (UARTE_PSEL_RTS_CONNECT_Disconnected << UARTE_PSEL_RTS_CONNECT_Pos);
224+ NRF_UARTE0->PSEL.RTS |= UARTE_PSEL_RTS_CONNECT_Disconnected << UARTE_PSEL_RTS_CONNECT_Pos;
228225
229226 // TXDピン設定(pf_gpioで管理しているポート番号・ピン番号に接続する)
230227 NRF_UARTE0->PSEL.TXD = (pf_gpio_get_pin(PF_GPIO_ID_UART_TXD) << UARTE_PSEL_TXD_PIN_Pos)
@@ -232,7 +229,7 @@ void pf_uart_init(void)
232229 | (UARTE_PSEL_TXD_CONNECT_Connected << UARTE_PSEL_TXD_CONNECT_Pos);
233230
234231 // CTSピン設定(使用しない)
235- NRF_UARTE0->PSEL.CTS |= (UARTE_PSEL_CTS_CONNECT_Disconnected << UARTE_PSEL_CTS_CONNECT_Pos);
232+ NRF_UARTE0->PSEL.CTS |= UARTE_PSEL_CTS_CONNECT_Disconnected << UARTE_PSEL_CTS_CONNECT_Pos;
236233
237234 // RXDピン設定(pf_gpioで管理しているポート番号・ピン番号に接続する)
238235 NRF_UARTE0->PSEL.RXD = (pf_gpio_get_pin(PF_GPIO_ID_UART_RXD) << UARTE_PSEL_RXD_PIN_Pos)
--- a/Maqueen_Lv2/src/pf/pf_ultra.c
+++ b/Maqueen_Lv2/src/pf/pf_ultra.c
@@ -43,6 +43,18 @@
4343 //! @details 温度センサと組み合わせるのが理想だが、一律25℃で固定する
4444 #define PF_ULTRA_TEMPERATURE ((f4)25.0f)
4545
46+//! @brief GPIOTE立ち上がり検出チャネル
47+#define PF_ULTRA_GPIOTE_RISING_CH ((u4)0U)
48+
49+//! @brief GPIOTE立ち下がり検出チャネル
50+#define PF_ULTRA_GPIOTE_FALLING_CH ((u4)1U)
51+
52+//! @brief PPI立ち上がり接続チャネル
53+#define PF_ULTRA_PPI_RISING_CH ((u4)0U)
54+
55+//! @brief PPI立ち下がり接続チャネル
56+#define PF_ULTRA_PPI_FALLING_CH ((u4)1U)
57+
4658 //! @brief 超音波動作情報構造体
4759 typedef struct PF_ULTRA_INFO_Tag
4860 {
@@ -69,38 +81,37 @@ static void pf_ultra_init_gpiote(void)
6981 port = pf_gpio_get_port(PF_GPIO_ID_MAQUEEN_ECHO);
7082 pin = pf_gpio_get_pin(PF_GPIO_ID_MAQUEEN_ECHO);
7183
72- // チャネル0コンフィグ(Eventモード、Rising Edgeで使用)
73- NRF_GPIOTE->CONFIG[0] = (GPIOTE_CONFIG_MODE_Event << GPIOTE_CONFIG_MODE_Pos)
74- | (pin << GPIOTE_CONFIG_PSEL_Pos) | (port << GPIOTE_CONFIG_PORT_Pos)
84+ // 立ち上がり検出チャネルコンフィグ(Eventモード、Rising Edgeで使用)
85+ NRF_GPIOTE->CONFIG[PF_ULTRA_GPIOTE_RISING_CH] = (GPIOTE_CONFIG_MODE_Event
86+ << GPIOTE_CONFIG_MODE_Pos) | (pin << GPIOTE_CONFIG_PSEL_Pos)
87+ | (port << GPIOTE_CONFIG_PORT_Pos)
7588 | (GPIOTE_CONFIG_POLARITY_LoToHi << GPIOTE_CONFIG_POLARITY_Pos);
7689
77- // チャネル1コンフィグ(Eventモード、Falling Edgeで使用)
78- NRF_GPIOTE->CONFIG[1] = (GPIOTE_CONFIG_MODE_Event << GPIOTE_CONFIG_MODE_Pos)
79- | (pin << GPIOTE_CONFIG_PSEL_Pos) | (port << GPIOTE_CONFIG_PORT_Pos)
90+ // 立ち下がり検出チャネルコンフィグ(Eventモード、Falling Edgeで使用)
91+ NRF_GPIOTE->CONFIG[PF_ULTRA_GPIOTE_FALLING_CH] = (GPIOTE_CONFIG_MODE_Event
92+ << GPIOTE_CONFIG_MODE_Pos) | (pin << GPIOTE_CONFIG_PSEL_Pos)
93+ | (port << GPIOTE_CONFIG_PORT_Pos)
8094 | (GPIOTE_CONFIG_POLARITY_HiToLo << GPIOTE_CONFIG_POLARITY_Pos);
8195
82- // 割り込み設定(ノイズを考慮し、この時点では禁止しておく)
83- NVIC_SetPriority(GPIOTE_IRQn, PF_INTERRUPT_PRI_ULTRA);
84- NVIC_DisableIRQ(GPIOTE_IRQn);
85-
86- // 割り込み有効化(チャネル1のタイミングで発生させる)
87- NRF_GPIOTE->INTENSET = GPIOTE_INTENSET_IN1_Set << GPIOTE_INTENSET_IN1_Pos;
96+ // 割り込みは使用しない
97+ NRF_GPIOTE->INTENSET = 0;
8898 }
8999
90100 //! @brief PPI初期化
91101 static void pf_ultra_init_ppi(void)
92102 {
93- // チャネル0(GPIOTEのEVENTS_IN[0]をTIMERのTASK_STARTに接続)
94- NRF_PPI->CH[0].EEP = (u4)&(NRF_GPIOTE->EVENTS_IN[0]);
95- NRF_PPI->CH[0].TEP = pf_timer_get_tasks_start(PF_TIMER_ID_ULTRA);
96- NRF_PPI->FORK[0].TEP = 0;
97- NRF_PPI->CHENSET = PPI_CHENSET_CH0_Set << PPI_CHENSET_CH0_Pos;
98-
99- // チャネル1(GPIOTEのEVENTS_IN[1]をTIMERのTASK_CAPTUREに接続)
100- NRF_PPI->CH[1].EEP = (u4)&(NRF_GPIOTE->EVENTS_IN[1]);
101- NRF_PPI->CH[1].TEP = pf_timer_get_tasks_capture(PF_TIMER_ID_ULTRA);
102- NRF_PPI->FORK[1].TEP = 0;
103- NRF_PPI->CHENSET = PPI_CHENSET_CH1_Set << PPI_CHENSET_CH1_Pos;
103+ // 立ち上がりチャネル(GPIOTEのEVENTS_IN[PF_ULTRA_PPI_RISING_CH]をTIMERのTASK_STARTに接続)
104+ NRF_PPI->CH[PF_ULTRA_PPI_RISING_CH].EEP = (u4)&(NRF_GPIOTE->EVENTS_IN[PF_ULTRA_PPI_RISING_CH]);
105+ NRF_PPI->CH[PF_ULTRA_PPI_RISING_CH].TEP = pf_timer_get_tasks_start(PF_TIMER_ID_ULTRA);
106+ NRF_PPI->FORK[PF_ULTRA_PPI_RISING_CH].TEP = 0;
107+ NRF_PPI->CHENSET = 1U << PF_ULTRA_PPI_RISING_CH;
108+
109+ // 立ち下がりチャネル(GPIOTEのEVENTS_IN[PF_ULTRA_PPI_FALLING_CH]をTIMERのTASK_CAPTUREに接続)
110+ NRF_PPI->CH[PF_ULTRA_PPI_FALLING_CH].EEP =
111+ (u4)&(NRF_GPIOTE->EVENTS_IN[PF_ULTRA_GPIOTE_FALLING_CH]);
112+ NRF_PPI->CH[PF_ULTRA_PPI_FALLING_CH].TEP = pf_timer_get_tasks_capture(PF_TIMER_ID_ULTRA);
113+ NRF_PPI->FORK[PF_ULTRA_PPI_FALLING_CH].TEP = 0;
114+ NRF_PPI->CHENSET = 1U << PF_ULTRA_PPI_FALLING_CH;
104115 }
105116
106117 //! @brief 超音波初期化
@@ -169,29 +180,81 @@ static void pf_ultra_start(void)
169180 // TRIGピンをHighのままホールドする
170181 pf_ultra_wait_us(PF_ULTRA_TRIG_HOLD_US);
171182
172- // GPIOTEイベントをクリア
173- NRF_GPIOTE->EVENTS_IN[0] = GPIOTE_EVENTS_PORT_EVENTS_PORT_NotGenerated
183+ // GPIOTEイベントをクリア(前回エラー時を考慮)
184+ NRF_GPIOTE->EVENTS_IN[PF_ULTRA_GPIOTE_RISING_CH] = GPIOTE_EVENTS_PORT_EVENTS_PORT_NotGenerated
174185 << GPIOTE_EVENTS_PORT_EVENTS_PORT_Pos;
175- NRF_GPIOTE->EVENTS_IN[1] = GPIOTE_EVENTS_PORT_EVENTS_PORT_NotGenerated
186+ NRF_GPIOTE->EVENTS_IN[PF_ULTRA_GPIOTE_FALLING_CH] = GPIOTE_EVENTS_PORT_EVENTS_PORT_NotGenerated
176187 << GPIOTE_EVENTS_PORT_EVENTS_PORT_Pos;
177188
178- // GPIOTE割り込み有効
179- NVIC_ClearPendingIRQ(GPIOTE_IRQn);
180- NVIC_EnableIRQ(GPIOTE_IRQn);
181-
182189 // TRIGピンをLowレベルにする
183190 pf_gpio_output(PF_GPIO_ID_MAQUEEN_TRIG, FALSE);
184191 }
185192
186-//! @brief 超音波定期タスク
187-//! @remarks プラットフォーム定期タスク(入力系)処理から呼び出すこと
188-void pf_ultra_task(void)
193+//! @brief 測定距離キャプチャ
194+static void pf_ultra_capture(void)
195+{
196+ u4 capture;
197+ f4 speed_of_sound;
198+ f4 duration;
199+ f4 distance;
200+
201+ // オート変数初期化
202+ capture = 0;
203+ speed_of_sound = 331.5f + 0.6f * PF_ULTRA_TEMPERATURE;
204+ duration = 0.0f;
205+ distance = 0.0f;
206+
207+ // GPIOTEイベントをクリア
208+ NRF_GPIOTE->EVENTS_IN[PF_ULTRA_GPIOTE_RISING_CH] = GPIOTE_EVENTS_PORT_EVENTS_PORT_NotGenerated
209+ << GPIOTE_EVENTS_PORT_EVENTS_PORT_Pos;
210+ NRF_GPIOTE->EVENTS_IN[PF_ULTRA_GPIOTE_FALLING_CH] = GPIOTE_EVENTS_PORT_EVENTS_PORT_NotGenerated
211+ << GPIOTE_EVENTS_PORT_EVENTS_PORT_Pos;
212+
213+ // タイマのキャプチャカウンタ(単位:us)を得る
214+ capture = pf_timer_get_capture(PF_TIMER_ID_ULTRA);
215+
216+ // キャプチャカウンタから変換
217+ duration = (f4)capture;
218+ duration /= 2.0f;
219+ distance = (duration * speed_of_sound) / 10000.0f;
220+
221+ // 測定結果を格納
222+ pf_ultra_info.cm = (u4)distance;
223+
224+ // 上限チェック
225+ if (pf_ultra_info.cm >= PF_ULTRA_UPPER_LIMIT)
226+ {
227+ // 上限に抑える
228+ pf_ultra_info.cm = PF_ULTRA_UPPER_LIMIT;
229+ }
230+
231+ // 測定完了
232+ pf_ultra_info.measure = FALSE;
233+}
234+
235+//! @brief 完了ポーリング
236+static void pf_ultra_poll(void)
189237 {
190- u4 enable;
238+ u4 generated;
191239
192240 // オート変数初期化
193- enable = 0;
241+ generated = GPIOTE_EVENTS_PORT_EVENTS_PORT_Generated << GPIOTE_EVENTS_PORT_EVENTS_PORT_Pos;
242+
243+ // GPIOTEイベントが共に発生していれば、測定完了
244+ if (generated == (NRF_GPIOTE->EVENTS_IN[PF_ULTRA_GPIOTE_RISING_CH] & generated))
245+ {
246+ if (generated == (NRF_GPIOTE->EVENTS_IN[PF_ULTRA_GPIOTE_FALLING_CH] & generated))
247+ {
248+ // 測定距離キャプチャ
249+ pf_ultra_capture();
250+ }
251+ }
252+}
194253
254+//! @brief 超音波定期タスク
255+//! @remarks プラットフォーム定期タスク(入力系)処理から呼び出すこと
256+void pf_ultra_task(void)
257+{
195258 // カウントアップ
196259 pf_ultra_info.count++;
197260
@@ -201,34 +264,42 @@ void pf_ultra_task(void)
201264 // カウンタリセット
202265 pf_ultra_info.count = 0;
203266
204- // 割り込み禁止
205- enable = pf_interrupt_local_disable(PF_INTERRUPT_PRI_ULTRA);
206-
207267 // この時点で測定中であれば、ダミー読み出し後、エラーにする
208268 if (TRUE == pf_ultra_info.measure)
209269 {
210270 (void)pf_timer_get_capture(PF_TIMER_ID_ULTRA);
211271 pf_ultra_info.cm = PF_ULTRA_UPPER_LIMIT;
212272 pf_ultra_info.measure = FALSE;
213-
214- // 次回測定まで割り込み要求を受け付けない
215- NVIC_DisableIRQ(GPIOTE_IRQn);
216273 }
217274
218- // 割り込み復元
219- pf_interrupt_local_restore(PF_INTERRUPT_PRI_ULTRA, enable);
220-
221- // 有効時は測定開始
275+ // 測定が有効なら
222276 if (TRUE == pf_ultra_info.enable)
223277 {
278+ // 測定開始
224279 pf_ultra_start();
225280 }
226281 }
282+ else
283+ {
284+ // 測定中なら
285+ if (TRUE == pf_ultra_info.measure)
286+ {
287+ // 測定完了をポーリング
288+ pf_ultra_poll();
289+ }
290+ }
227291 }
292+
228293 //! @brief 超音波測定の有効化・無効化
229294 //! @param [in] enable 有効フラグ(TRUE=有効化/FALSE=無効化)
230295 void pf_ultra_enable(BOOL enable)
231296 {
297+ // 無効化→有効化の場合、結果をリセット
298+ if ((TRUE == enable) && (FALSE == pf_ultra_info.enable))
299+ {
300+ pf_ultra_info.cm = PF_ULTRA_UPPER_LIMIT;
301+ }
302+
232303 pf_ultra_info.enable = enable;
233304 }
234305
@@ -236,64 +307,5 @@ void pf_ultra_enable(BOOL enable)
236307 //! @return 前方障害物までの距離(単位:cm)
237308 u4 pf_ultra_get(void)
238309 {
239- u4 enable;
240- u4 cm;
241-
242- // オート変数初期化
243- enable = 0;
244- cm = 0;
245-
246- // 割り込み禁止
247- enable = pf_interrupt_local_disable(PF_INTERRUPT_PRI_ULTRA);
248-
249- // 測定結果を取得
250- cm = pf_ultra_info.cm;
251-
252- // 割り込み復元
253- pf_interrupt_local_restore(PF_INTERRUPT_PRI_ULTRA, enable);
254-
255- return cm;
256-}
257-
258-//! @brief GPIOTE割り込みハンドラ
259-//! @attention データ競合(割り込み干渉)に注意する
260-void GPIOTE_IRQHandler(void)
261-{
262- u4 capture;
263- f4 speed_of_sound;
264- f4 duration;
265- f4 distance;
266-
267- // オート変数初期化
268- capture = 0;
269- speed_of_sound = 331.5f + 0.6f * PF_ULTRA_TEMPERATURE;
270- duration = 0.0f;
271- distance = 0.0f;
272-
273- // GPIOTEイベントをクリア
274- NRF_GPIOTE->EVENTS_IN[0] = GPIOTE_EVENTS_PORT_EVENTS_PORT_NotGenerated
275- << GPIOTE_EVENTS_PORT_EVENTS_PORT_Pos;
276- NRF_GPIOTE->EVENTS_IN[1] = GPIOTE_EVENTS_PORT_EVENTS_PORT_NotGenerated
277- << GPIOTE_EVENTS_PORT_EVENTS_PORT_Pos;
278-
279- // タイマのキャプチャカウンタ(単位:us)を得る
280- capture = pf_timer_get_capture(PF_TIMER_ID_ULTRA);
281-
282- // キャプチャカウンタから変換
283- duration = (f4)capture;
284- duration /= 2.0f;
285- distance = (duration * speed_of_sound) / 10000.0f;
286-
287- // 測定結果を格納
288- pf_ultra_info.cm = (u4)distance;
289-
290- // 上限チェック
291- if (pf_ultra_info.cm >= PF_ULTRA_UPPER_LIMIT)
292- {
293- // 上限に抑える
294- pf_ultra_info.cm = PF_ULTRA_UPPER_LIMIT;
295- }
296-
297- // 測定完了
298- pf_ultra_info.measure = FALSE;
310+ return pf_ultra_info.cm;
299311 }