C言語でBBC micro:bit V2およびDFRobot micro:Maqueenを操作する
Révision | 36a310d424be73183201349582b7d1ef92043297 (tree) |
---|---|
l'heure | 2023-09-18 08:13:12 |
Auteur | xm6_original <tanaka_yasushi2008@yaho...> |
Commiter | xm6_original |
NeoPixel実装中
@@ -44,6 +44,7 @@ typedef enum PF_GPIO_ID_Tag | ||
44 | 44 | PF_GPIO_ID_COL5, //!< Display COL5 |
45 | 45 | PF_GPIO_ID_BUTTON_A, //!< BUTTON A |
46 | 46 | PF_GPIO_ID_BUTTON_B, //!< BUTTON B |
47 | + PF_FPIO_ID_INTERNAL_IRQ, //!< 内部I2Cバス IRQ | |
47 | 48 | PF_GPIO_ID_INTERNAL_SCL, //!< 内部I2Cバス SCL |
48 | 49 | PF_GPIO_ID_INTERNAL_SDA, //!< 内部I2Cバス SDA |
49 | 50 | PF_GPIO_ID_EXTERNAL_SCL, //!< 外部I2Cバス SCL |
@@ -56,6 +57,8 @@ typedef enum PF_GPIO_ID_Tag | ||
56 | 57 | PF_GPIO_ID_MAQUEEN_PATROL_R, //!< MAQUEEN PATROL R |
57 | 58 | PF_GPIO_ID_MAQUEEN_TRIG, //!< MAQUEEN 超音波 TRIG |
58 | 59 | PF_GPIO_ID_MAQUEEN_ECHO, //!< MAQUEEN 超音波 ECHO |
60 | + PF_GPIO_ID_MAQUEEN_NEOPIXEL, //!< MAQUEEN NeoPixel | |
61 | + PF_GPIO_ID_MAQUEEN_NECIR, //!< MAQUEEN NECフォーマット Ir | |
59 | 62 | PF_GPIO_ID_MAX, //!< (IDの個数を表す) |
60 | 63 | } PF_GPIO_ID; |
61 | 64 |
@@ -36,7 +36,6 @@ typedef enum PF_INTERRUPT_PRI_Tag | ||
36 | 36 | PF_INTERRUPT_PRI_I2C_INT, //!< I2C(内部) |
37 | 37 | PF_INTERRUPT_PRI_I2C_EXT, //!< I2C(外部) |
38 | 38 | PF_INTERRUPT_PRI_MUSIC, //!< 音楽演奏 |
39 | - PF_INTERRUPT_PRI_ULTRA, //!< 超音波 | |
40 | 39 | } PF_INTERRUPT_PRI; |
41 | 40 | |
42 | 41 | //! @brief グローバル割り込み禁止 |
@@ -47,6 +46,11 @@ u4 pf_interrupt_global_disable(void); | ||
47 | 46 | //! @param [in] primask pf_interrupt_global_disable()の返り値 |
48 | 47 | void pf_interrupt_global_restore(u4 primask); |
49 | 48 | |
49 | +//! @brief ローカル割り込みセットアップ | |
50 | +//! @details 割り込み優先度の設定と、割り込み許可を行う | |
51 | +//! @param [in] pri 割り込み優先度 | |
52 | +void pf_interrupt_local_setup(PF_INTERRUPT_PRI pri); | |
53 | + | |
50 | 54 | //! @brief ローカル割り込み禁止 |
51 | 55 | //! @param [in] pri 割り込み優先度 |
52 | 56 | //! @return 直前のローカル割り込み禁止状態(1:割り込み禁止/0:割り込み許可) |
@@ -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 |
@@ -46,8 +46,4 @@ void pf_ultra_enable(BOOL enable); | ||
46 | 46 | //! @return 前方障害物までの距離(単位:cm) |
47 | 47 | u4 pf_ultra_get(void); |
48 | 48 | |
49 | -//! @brief GPIOTE割り込みハンドラ | |
50 | -//! @attention データ競合(割り込み干渉)に注意する | |
51 | -void GPIOTE_IRQHandler(void); | |
52 | - | |
53 | 49 | #endif // PF_ULTRA_H |
@@ -298,11 +298,11 @@ static void app_mode_task(void) | ||
298 | 298 | } |
299 | 299 | else |
300 | 300 | { |
301 | + // 走行→停止に限り、ステップを戻す | |
301 | 302 | app_run = FALSE; |
303 | + app_step = 0; | |
302 | 304 | } |
303 | 305 | |
304 | - // ステップを戻す | |
305 | - app_step = 0; | |
306 | 306 | break; |
307 | 307 | } |
308 | 308 | } |
@@ -522,7 +522,8 @@ static BOOL app_run_ultra(void) | ||
522 | 522 | // 走行停止 |
523 | 523 | run = FALSE; |
524 | 524 | app_run = FALSE; |
525 | - app_step = 0; | |
525 | + | |
526 | + // app_stepは変更しない(矩形走行をそのまま再開したい) | |
526 | 527 | } |
527 | 528 | } |
528 | 529 |
@@ -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 |
@@ -26,6 +26,13 @@ | ||
26 | 26 | #include "nrf52833.h" |
27 | 27 | #include "pf_gpio.h" |
28 | 28 | |
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 | + | |
29 | 36 | //! @brief 入出力方向 |
30 | 37 | typedef enum PF_GPIO_DIR_Tag |
31 | 38 | { |
@@ -74,7 +81,7 @@ typedef struct PF_GPIO_INIT_Tag | ||
74 | 81 | } PF_GPIO_INIT; |
75 | 82 | |
76 | 83 | //! @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] = | |
78 | 85 | { |
79 | 86 | // PF_GPIO_ID_UART_TXD |
80 | 87 | { |
@@ -231,6 +238,17 @@ const PF_GPIO_INIT pf_gpio_init_table[PF_GPIO_ID_MAX] = | ||
231 | 238 | PF_GPIO_DRIVE_S0S1, // 駆動特性 |
232 | 239 | }, |
233 | 240 | |
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 | + | |
234 | 252 | // PF_GPIO_ID_INTERNAL_SCL |
235 | 253 | { |
236 | 254 | 0, // ポート |
@@ -283,7 +301,7 @@ const PF_GPIO_INIT pf_gpio_init_table[PF_GPIO_ID_MAX] = | ||
283 | 301 | PF_GPIO_DIR_OUTPUT, // 入出力方向 |
284 | 302 | PF_GPIO_INBUF_DISCONNECT, // 入力バッファ |
285 | 303 | PF_GPIO_PULL_NONE, // プルアップ・プルダウン |
286 | - PF_GPIO_DRIVE_S0S1, // 駆動特性 | |
304 | + PF_GPIO_DRIVE_H0H1, // 駆動特性 | |
287 | 305 | }, |
288 | 306 | |
289 | 307 | // PF_GPIO_ID_MAQUEEN_SPEAKER |
@@ -362,29 +380,122 @@ const PF_GPIO_INIT pf_gpio_init_table[PF_GPIO_ID_MAX] = | ||
362 | 380 | PF_GPIO_PULL_NONE, // プルアップ・プルダウン |
363 | 381 | PF_GPIO_DRIVE_S0S1, // 駆動特性 |
364 | 382 | }, |
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 | + }, | |
365 | 405 | }; |
366 | 406 | |
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] = | |
371 | 416 | { |
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; | |
372 | 483 | NRF_GPIO_Type *dev; |
484 | + u4 cnf; | |
373 | 485 | |
374 | 486 | // オート変数初期化 |
487 | + loop = 0; | |
375 | 488 | dev = NULL; |
489 | + cnf = PF_GPIO_DIR_INPUT | PF_GPIO_INBUF_DISCONNECT | PF_GPIO_PULL_UP | PF_GPIO_DRIVE_S0S1; | |
376 | 490 | |
377 | - // ポート別振り分け | |
378 | - if (0 == pf_gpio_init_table[id].port) | |
491 | + for (loop = 0; loop < PF_GPIO_NC_PIN_MAX; loop++) | |
379 | 492 | { |
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]; | |
386 | 495 | |
387 | - return dev; | |
496 | + // PIN_CNFレジスタを設定 | |
497 | + dev->PIN_CNF[pf_gpio_nc_table[loop].pin] = cnf; | |
498 | + } | |
388 | 499 | } |
389 | 500 | |
390 | 501 | //! @brief GPIO初期化(単一のID) |
@@ -403,7 +514,7 @@ static void pf_gpio_init_id(PF_GPIO_ID id) | ||
403 | 514 | } |
404 | 515 | |
405 | 516 | // IDからデバイスを取得 |
406 | - dev = pf_gpio_get_dev(id); | |
517 | + dev = pf_gpio_port_to_dev[pf_gpio_init_table[id].port]; | |
407 | 518 | |
408 | 519 | // コンフィグ設定 |
409 | 520 | 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) | ||
421 | 532 | // オート変数初期化 |
422 | 533 | id = 0; |
423 | 534 | |
535 | + // 未使用ピンを初期化 | |
536 | + pf_gpio_init_nc(); | |
537 | + | |
424 | 538 | // すべてのIDをループ |
425 | 539 | for (id = 0; id < PF_GPIO_ID_MAX; id++) |
426 | 540 | { |
@@ -485,7 +599,7 @@ BOOL pf_gpio_input(PF_GPIO_ID id) | ||
485 | 599 | if (id < PF_GPIO_ID_MAX) |
486 | 600 | { |
487 | 601 | // IDからデバイスを取得 |
488 | - dev = pf_gpio_get_dev(id); | |
602 | + dev = pf_gpio_port_to_dev[pf_gpio_init_table[id].port]; | |
489 | 603 | |
490 | 604 | // 当該ピンのみを取り出した情報を取得 |
491 | 605 | in = dev->IN & (1 << pf_gpio_init_table[id].pin); |
@@ -520,7 +634,7 @@ void pf_gpio_output(PF_GPIO_ID id, BOOL level) | ||
520 | 634 | if (id < PF_GPIO_ID_MAX) |
521 | 635 | { |
522 | 636 | // IDからデバイスを取得 |
523 | - dev = pf_gpio_get_dev(id); | |
637 | + dev = pf_gpio_port_to_dev[pf_gpio_init_table[id].port]; | |
524 | 638 | |
525 | 639 | // 出力 |
526 | 640 | if (FALSE == level) |
@@ -90,13 +90,6 @@ static const PF_INTERRUPT_PRI pf_i2c_channel_to_pri[PF_I2C_CHANNEL_MAX] = | ||
90 | 90 | PF_INTERRUPT_PRI_I2C_EXT, //!< チャネル1(外部) |
91 | 91 | }; |
92 | 92 | |
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 | - | |
100 | 93 | //! @brief I2C割り込み禁止 |
101 | 94 | //! @param [in] channel I2Cチャネル(0=内部/1=外部) |
102 | 95 | //! @return 直前のI2C割り込み禁止状態(1:割り込み禁止/0:割り込み許可) |
@@ -214,8 +207,6 @@ static void pf_i2c_init_id(PF_I2C_ID id) | ||
214 | 207 | static void pf_i2c_init_dev(u4 channel) |
215 | 208 | { |
216 | 209 | NRF_TWIM_Type *dev; |
217 | - PF_INTERRUPT_PRI pri; | |
218 | - IRQn_Type irq; | |
219 | 210 | u4 scl_port; |
220 | 211 | u4 scl_pin; |
221 | 212 | u4 sda_port; |
@@ -223,8 +214,6 @@ static void pf_i2c_init_dev(u4 channel) | ||
223 | 214 | |
224 | 215 | // オート変数初期化 |
225 | 216 | dev = pf_i2c_channel_to_dev[channel]; |
226 | - pri = pf_i2c_channel_to_pri[channel]; | |
227 | - irq = pf_i2c_channel_to_irq[channel]; | |
228 | 217 | scl_port = 0; |
229 | 218 | scl_pin = 0; |
230 | 219 | sda_port = 0; |
@@ -237,10 +226,8 @@ static void pf_i2c_init_dev(u4 channel) | ||
237 | 226 | dev->INTEN = (TWIM_INTEN_STOPPED_Enabled << TWIM_INTEN_STOPPED_Pos) |
238 | 227 | | (TWIM_INTEN_ERROR_Enabled << TWIM_INTEN_ERROR_Pos); |
239 | 228 | |
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]); | |
244 | 231 | |
245 | 232 | // 転送速度(400kbps) |
246 | 233 | dev->FREQUENCY = TWIM_FREQUENCY_FREQUENCY_K400 << TWIM_FREQUENCY_FREQUENCY_Pos; |
@@ -98,11 +98,6 @@ static IRQn_Type pf_interrupt_get_irq(PF_INTERRUPT_PRI pri) | ||
98 | 98 | irq = TIMER1_IRQn; |
99 | 99 | break; |
100 | 100 | |
101 | - // 超音波 | |
102 | - case PF_INTERRUPT_PRI_ULTRA: | |
103 | - irq = GPIOTE_IRQn; | |
104 | - break; | |
105 | - | |
106 | 101 | default: |
107 | 102 | break; |
108 | 103 | } |
@@ -110,6 +105,32 @@ static IRQn_Type pf_interrupt_get_irq(PF_INTERRUPT_PRI pri) | ||
110 | 105 | return irq; |
111 | 106 | } |
112 | 107 | |
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 | + | |
113 | 134 | //! @brief ローカル割り込み禁止 |
114 | 135 | //! @param [in] pri 割り込み優先度 |
115 | 136 | //! @return 直前のローカル割り込み禁止状態(1:割り込み禁止/0:割り込み許可) |
@@ -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 | +} |
@@ -85,7 +85,7 @@ const PF_TIMER_INIT pf_timer_table[PF_TIMER_ID_MAX] = | ||
85 | 85 | 0, // コンペア値(3) |
86 | 86 | }, |
87 | 87 | |
88 | - // PF_TIMER_ID_ULTRASONIC | |
88 | + // PF_TIMER_ID_ULTRA | |
89 | 89 | { |
90 | 90 | 2, // チャネル |
91 | 91 | NRF_TIMER2, // デバイス |
@@ -119,16 +119,6 @@ static const u4 pf_timer_stop_table[PF_TIMER_COMPARE_MAX + 1] = | ||
119 | 119 | TIMER_SHORTS_COMPARE3_STOP_Enabled << TIMER_SHORTS_COMPARE3_STOP_Pos, |
120 | 120 | }; |
121 | 121 | |
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 | - | |
132 | 122 | //! @brief Timer動作情報構造体 |
133 | 123 | typedef struct PF_TIMER_INFO_Tag |
134 | 124 | { |
@@ -181,11 +171,6 @@ static u4 pf_timer_get_intenset(PF_TIMER_ID id) | ||
181 | 171 | //! @param [in] id TimerのID |
182 | 172 | static void pf_timer_init_id(PF_TIMER_ID id) |
183 | 173 | { |
184 | - IRQn_Type irq; | |
185 | - | |
186 | - // オート変数初期化 | |
187 | - irq = TIMER0_IRQn; | |
188 | - | |
189 | 174 | // タイマ停止 |
190 | 175 | pf_timer_table[id].dev->TASKS_STOP = TIMER_TASKS_STOP_TASKS_STOP_Trigger |
191 | 176 | << TIMER_TASKS_STOP_TASKS_STOP_Pos; |
@@ -258,11 +243,8 @@ static void pf_timer_init_id(PF_TIMER_ID id) | ||
258 | 243 | // キャプチャモード以外は割り込みを使用する |
259 | 244 | if (PF_TIMER_ACTION_CAPTURE != pf_timer_table[id].action) |
260 | 245 | { |
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); | |
266 | 248 | } |
267 | 249 | } |
268 | 250 |
@@ -294,12 +276,6 @@ void pf_timer_start(PF_TIMER_ID id) | ||
294 | 276 | pf_timer_table[id].dev->TASKS_CLEAR = |
295 | 277 | TIMER_TASKS_CLEAR_TASKS_CLEAR_Trigger << TIMER_TASKS_CLEAR_TASKS_CLEAR_Pos; |
296 | 278 | |
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 | - | |
303 | 279 | // 開始 |
304 | 280 | pf_timer_table[id].dev->TASKS_START = |
305 | 281 | TIMER_TASKS_START_TASKS_START_Trigger << TIMER_TASKS_START_TASKS_START_Pos; |
@@ -331,31 +307,22 @@ void pf_timer_stop(PF_TIMER_ID id) | ||
331 | 307 | //! @attention Timerコールバック関数は割り込みコンテキストで呼び出される |
332 | 308 | void pf_timer_callback(PF_TIMER_ID id, PF_TIMER_CALLBACK func) |
333 | 309 | { |
334 | - IRQn_Type irq; | |
335 | 310 | u4 enable; |
336 | 311 | |
337 | 312 | // オート変数初期化 |
338 | - irq = TIMER0_IRQn; | |
339 | 313 | enable = 0; |
340 | 314 | |
341 | 315 | // IDチェック |
342 | 316 | if (id < PF_TIMER_ID_MAX) |
343 | 317 | { |
344 | - // IDに対応したIRQを取得 | |
345 | - irq = pf_timer_to_irq[id]; | |
346 | - | |
347 | 318 | // 割り込み禁止 |
348 | - enable = NVIC_GetEnableIRQ(irq); | |
349 | - NVIC_DisableIRQ(irq); | |
319 | + enable = pf_interrupt_local_disable(pf_timer_table[id].priority); | |
350 | 320 | |
351 | 321 | // コールバック関数設定 |
352 | 322 | pf_timer_info[id].callback = func; |
353 | 323 | |
354 | 324 | // 割り込み復元 |
355 | - if (0 != enable) | |
356 | - { | |
357 | - NVIC_EnableIRQ(irq); | |
358 | - } | |
325 | + pf_interrupt_local_restore(pf_timer_table[id].priority, enable); | |
359 | 326 | } |
360 | 327 | } |
361 | 328 |
@@ -364,22 +331,18 @@ void pf_timer_callback(PF_TIMER_ID id, PF_TIMER_CALLBACK func) | ||
364 | 331 | //! @param [in] cc コンペアカウンタ配列 |
365 | 332 | void pf_timer_cc(PF_TIMER_ID id, u4 *cc) |
366 | 333 | { |
367 | - IRQn_Type irq; | |
368 | 334 | u4 enable; |
369 | 335 | u4 loop; |
370 | 336 | |
371 | 337 | // オート変数初期化 |
372 | - irq = TIMER0_IRQn; | |
338 | + enable = 0; | |
339 | + loop = 0; | |
373 | 340 | |
374 | 341 | // パラメータチェック |
375 | 342 | if ((id < PF_TIMER_ID_MAX) && (NULL != cc)) |
376 | 343 | { |
377 | - // IDに対応したIRQを取得 | |
378 | - irq = pf_timer_to_irq[id]; | |
379 | - | |
380 | 344 | // 割り込み禁止 |
381 | - enable = NVIC_GetEnableIRQ(irq); | |
382 | - NVIC_DisableIRQ(irq); | |
345 | + enable = pf_interrupt_local_disable(pf_timer_table[id].priority); | |
383 | 346 | |
384 | 347 | // CCループ |
385 | 348 | for (loop = 0; loop < pf_timer_table[id].compares; loop++) |
@@ -393,10 +356,7 @@ void pf_timer_cc(PF_TIMER_ID id, u4 *cc) | ||
393 | 356 | } |
394 | 357 | |
395 | 358 | // 割り込み復元 |
396 | - if (0 != enable) | |
397 | - { | |
398 | - NVIC_EnableIRQ(irq); | |
399 | - } | |
359 | + pf_interrupt_local_restore(pf_timer_table[id].priority, enable); | |
400 | 360 | } |
401 | 361 | } |
402 | 362 |
@@ -413,11 +373,14 @@ u4 pf_timer_get_capture(PF_TIMER_ID id) | ||
413 | 373 | // パラメータチェック |
414 | 374 | if (id < PF_TIMER_ID_MAX) |
415 | 375 | { |
376 | + // キャプチャ値を取得 | |
416 | 377 | capture = pf_timer_table[id].dev->CC[0]; |
417 | 378 | |
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; | |
421 | 384 | pf_timer_table[id].dev->CC[0] = 0; |
422 | 385 | } |
423 | 386 |
@@ -194,8 +194,7 @@ static void pf_uart_poll_rxd(void) | ||
194 | 194 | void pf_uart_init(void) |
195 | 195 | { |
196 | 196 | // 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; | |
199 | 198 | |
200 | 199 | // バッファ初期化 |
201 | 200 | pf_uart_init_buf(PF_UART_BUF_ID_TXD); |
@@ -212,10 +211,8 @@ void pf_uart_init(void) | ||
212 | 211 | | (UARTE_INTEN_ERROR_Enabled << UARTE_INTEN_ERROR_Pos) |
213 | 212 | | (UARTE_INTEN_RXSTARTED_Enabled << UARTE_INTEN_RXSTARTED_Pos); |
214 | 213 | |
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); | |
219 | 216 | |
220 | 217 | // 受信エラーをすべてクリア |
221 | 218 | NRF_UARTE0->ERRORSRC = (UARTE_ERRORSRC_OVERRUN_NotPresent << UARTE_ERRORSRC_OVERRUN_Pos) |
@@ -224,7 +221,7 @@ void pf_uart_init(void) | ||
224 | 221 | | (UARTE_ERRORSRC_BREAK_NotPresent << UARTE_ERRORSRC_BREAK_Pos); |
225 | 222 | |
226 | 223 | // 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; | |
228 | 225 | |
229 | 226 | // TXDピン設定(pf_gpioで管理しているポート番号・ピン番号に接続する) |
230 | 227 | 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) | ||
232 | 229 | | (UARTE_PSEL_TXD_CONNECT_Connected << UARTE_PSEL_TXD_CONNECT_Pos); |
233 | 230 | |
234 | 231 | // 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; | |
236 | 233 | |
237 | 234 | // RXDピン設定(pf_gpioで管理しているポート番号・ピン番号に接続する) |
238 | 235 | NRF_UARTE0->PSEL.RXD = (pf_gpio_get_pin(PF_GPIO_ID_UART_RXD) << UARTE_PSEL_RXD_PIN_Pos) |
@@ -43,6 +43,18 @@ | ||
43 | 43 | //! @details 温度センサと組み合わせるのが理想だが、一律25℃で固定する |
44 | 44 | #define PF_ULTRA_TEMPERATURE ((f4)25.0f) |
45 | 45 | |
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 | + | |
46 | 58 | //! @brief 超音波動作情報構造体 |
47 | 59 | typedef struct PF_ULTRA_INFO_Tag |
48 | 60 | { |
@@ -69,38 +81,37 @@ static void pf_ultra_init_gpiote(void) | ||
69 | 81 | port = pf_gpio_get_port(PF_GPIO_ID_MAQUEEN_ECHO); |
70 | 82 | pin = pf_gpio_get_pin(PF_GPIO_ID_MAQUEEN_ECHO); |
71 | 83 | |
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) | |
75 | 88 | | (GPIOTE_CONFIG_POLARITY_LoToHi << GPIOTE_CONFIG_POLARITY_Pos); |
76 | 89 | |
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) | |
80 | 94 | | (GPIOTE_CONFIG_POLARITY_HiToLo << GPIOTE_CONFIG_POLARITY_Pos); |
81 | 95 | |
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; | |
88 | 98 | } |
89 | 99 | |
90 | 100 | //! @brief PPI初期化 |
91 | 101 | static void pf_ultra_init_ppi(void) |
92 | 102 | { |
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; | |
104 | 115 | } |
105 | 116 | |
106 | 117 | //! @brief 超音波初期化 |
@@ -169,29 +180,81 @@ static void pf_ultra_start(void) | ||
169 | 180 | // TRIGピンをHighのままホールドする |
170 | 181 | pf_ultra_wait_us(PF_ULTRA_TRIG_HOLD_US); |
171 | 182 | |
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 | |
174 | 185 | << 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 | |
176 | 187 | << GPIOTE_EVENTS_PORT_EVENTS_PORT_Pos; |
177 | 188 | |
178 | - // GPIOTE割り込み有効 | |
179 | - NVIC_ClearPendingIRQ(GPIOTE_IRQn); | |
180 | - NVIC_EnableIRQ(GPIOTE_IRQn); | |
181 | - | |
182 | 189 | // TRIGピンをLowレベルにする |
183 | 190 | pf_gpio_output(PF_GPIO_ID_MAQUEEN_TRIG, FALSE); |
184 | 191 | } |
185 | 192 | |
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) | |
189 | 237 | { |
190 | - u4 enable; | |
238 | + u4 generated; | |
191 | 239 | |
192 | 240 | // オート変数初期化 |
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 | +} | |
194 | 253 | |
254 | +//! @brief 超音波定期タスク | |
255 | +//! @remarks プラットフォーム定期タスク(入力系)処理から呼び出すこと | |
256 | +void pf_ultra_task(void) | |
257 | +{ | |
195 | 258 | // カウントアップ |
196 | 259 | pf_ultra_info.count++; |
197 | 260 |
@@ -201,34 +264,42 @@ void pf_ultra_task(void) | ||
201 | 264 | // カウンタリセット |
202 | 265 | pf_ultra_info.count = 0; |
203 | 266 | |
204 | - // 割り込み禁止 | |
205 | - enable = pf_interrupt_local_disable(PF_INTERRUPT_PRI_ULTRA); | |
206 | - | |
207 | 267 | // この時点で測定中であれば、ダミー読み出し後、エラーにする |
208 | 268 | if (TRUE == pf_ultra_info.measure) |
209 | 269 | { |
210 | 270 | (void)pf_timer_get_capture(PF_TIMER_ID_ULTRA); |
211 | 271 | pf_ultra_info.cm = PF_ULTRA_UPPER_LIMIT; |
212 | 272 | pf_ultra_info.measure = FALSE; |
213 | - | |
214 | - // 次回測定まで割り込み要求を受け付けない | |
215 | - NVIC_DisableIRQ(GPIOTE_IRQn); | |
216 | 273 | } |
217 | 274 | |
218 | - // 割り込み復元 | |
219 | - pf_interrupt_local_restore(PF_INTERRUPT_PRI_ULTRA, enable); | |
220 | - | |
221 | - // 有効時は測定開始 | |
275 | + // 測定が有効なら | |
222 | 276 | if (TRUE == pf_ultra_info.enable) |
223 | 277 | { |
278 | + // 測定開始 | |
224 | 279 | pf_ultra_start(); |
225 | 280 | } |
226 | 281 | } |
282 | + else | |
283 | + { | |
284 | + // 測定中なら | |
285 | + if (TRUE == pf_ultra_info.measure) | |
286 | + { | |
287 | + // 測定完了をポーリング | |
288 | + pf_ultra_poll(); | |
289 | + } | |
290 | + } | |
227 | 291 | } |
292 | + | |
228 | 293 | //! @brief 超音波測定の有効化・無効化 |
229 | 294 | //! @param [in] enable 有効フラグ(TRUE=有効化/FALSE=無効化) |
230 | 295 | void pf_ultra_enable(BOOL enable) |
231 | 296 | { |
297 | + // 無効化→有効化の場合、結果をリセット | |
298 | + if ((TRUE == enable) && (FALSE == pf_ultra_info.enable)) | |
299 | + { | |
300 | + pf_ultra_info.cm = PF_ULTRA_UPPER_LIMIT; | |
301 | + } | |
302 | + | |
232 | 303 | pf_ultra_info.enable = enable; |
233 | 304 | } |
234 | 305 |
@@ -236,64 +307,5 @@ void pf_ultra_enable(BOOL enable) | ||
236 | 307 | //! @return 前方障害物までの距離(単位:cm) |
237 | 308 | u4 pf_ultra_get(void) |
238 | 309 | { |
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; | |
299 | 311 | } |