Skip to content

Commit 9d191f7

Browse files
authored
Merge pull request adafruit#589 from arturo182/nrf_gamepad
nrf: Implement ticks, add gamepad module and example
2 parents 77c70c7 + 1de2ee6 commit 9d191f7

File tree

11 files changed

+176
-94
lines changed

11 files changed

+176
-94
lines changed

ports/nrf/Makefile

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,7 @@ SRC_C += \
139139
pin_named_pins.c \
140140
fatfs_port.c \
141141
fifo.c \
142+
tick.c \
142143
drivers/softpwm.c \
143144
drivers/ticker.c \
144145
drivers/bluetooth/ble_drv.c \
@@ -230,22 +231,24 @@ SRC_SHARED_MODULE = \
230231
os/__init__.c \
231232
random/__init__.c \
232233
storage/__init__.c \
234+
gamepad/__init__.c \
235+
gamepad/GamePad.c
233236

234237
# bitbangio/__init__.c \
235238
bitbangio/I2C.c \
236239
bitbangio/OneWire.c \
237240
bitbangio/SPI.c \
238241
busio/OneWire.c \
239-
gamepad/__init__.c \
240-
gamepad/GamePad.c \
241242
struct/__init__.c \
242243
uheap/__init__.c \
243244
ustack/__init__.c
244245

245-
#SRC_SHARED_MODULE_EXPANDED = $(addprefix shared-bindings/, $(SRC_SHARED_MODULE)) \
246-
$(addprefix shared-module/, $(SRC_SHARED_MODULE))
246+
SRC_SHARED_BINDINGS = \
247+
gamepad/__init__.c \
248+
gamepad/GamePad.c
247249

248-
SRC_SHARED_MODULE_EXPANDED = $(addprefix shared-module/, $(SRC_SHARED_MODULE))
250+
SRC_SHARED_MODULE_EXPANDED = $(addprefix shared-bindings/, $(SRC_SHARED_BINDINGS)) \
251+
$(addprefix shared-module/, $(SRC_SHARED_MODULE))
249252

250253
FROZEN_MPY_PY_FILES := $(shell find -L $(FROZEN_MPY_DIR) -type f -name '*.py')
251254
FROZEN_MPY_MPY_FILES := $(addprefix $(BUILD)/,$(FROZEN_MPY_PY_FILES:.py=.mpy))

ports/nrf/boards/board.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,6 @@
3131

3232
#include <stdbool.h>
3333

34-
extern volatile uint32_t ticks_ms;
35-
3634
// Initializes board related state once on start up.
3735
void board_init(void);
3836

ports/nrf/boards/feather52/board.c

Lines changed: 0 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -35,52 +35,10 @@
3535
#define BOOTLOADER_VERSION_REGISTER NRF_TIMER2->CC[0]
3636
uint32_t bootloaderVersion = 0;
3737

38-
volatile uint32_t ticks_ms = 0;
39-
40-
#define HAL_LFCLK_FREQ (32768UL)
41-
#define HAL_RTC_FREQ (1024UL)
42-
#define HAL_RTC_COUNTER_PRESCALER ((HAL_LFCLK_FREQ/HAL_RTC_FREQ)-1)
43-
44-
/* Maximum RTC ticks */
45-
#define portNRF_RTC_MAXTICKS ((1U<<24)-1U)
46-
4738
void board_init(void)
4839
{
4940
// Retrieve bootloader version
5041
bootloaderVersion = BOOTLOADER_VERSION_REGISTER;
51-
52-
// 32Khz XTAL
53-
NRF_CLOCK->LFCLKSRC = (uint32_t)((CLOCK_LFCLKSRC_SRC_Xtal << CLOCK_LFCLKSRC_SRC_Pos) & CLOCK_LFCLKSRC_SRC_Msk);
54-
NRF_CLOCK->TASKS_LFCLKSTART = 1UL;
55-
56-
// Set up RTC1 as tick timer
57-
NVIC_DisableIRQ(RTC1_IRQn);
58-
NRF_RTC1->EVTENCLR = RTC_EVTEN_COMPARE0_Msk;
59-
NRF_RTC1->INTENCLR = RTC_INTENSET_COMPARE0_Msk;
60-
NRF_RTC1->TASKS_STOP = 1;
61-
NRF_RTC1->TASKS_CLEAR = 1;
62-
63-
ticks_ms = 0;
64-
65-
NRF_RTC1->PRESCALER = HAL_RTC_COUNTER_PRESCALER;
66-
NRF_RTC1->INTENSET = RTC_INTENSET_TICK_Msk;
67-
NRF_RTC1->TASKS_START = 1;
68-
NRF_RTC1->EVTENSET = RTC_EVTEN_OVRFLW_Msk;
69-
NVIC_SetPriority(RTC1_IRQn, 0xf); // lowest priority
70-
NVIC_EnableIRQ(RTC1_IRQn);
71-
}
72-
73-
void RTC1_IRQHandler(void)
74-
{
75-
// Clear event
76-
NRF_RTC1->EVENTS_TICK = 0;
77-
volatile uint32_t dummy = NRF_RTC1->EVENTS_TICK;
78-
(void) dummy;
79-
80-
// Tick correction
81-
uint32_t systick_counter = NRF_RTC1->COUNTER;
82-
uint32_t diff = (systick_counter - ticks_ms) & portNRF_RTC_MAXTICKS;
83-
ticks_ms += diff;
8442
}
8543

8644
// Check the status of the two buttons on CircuitPlayground Express. If both are

ports/nrf/boards/pca10056/board.c

Lines changed: 1 addition & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -31,49 +31,8 @@
3131

3232
#include "boards/board.h"
3333

34-
volatile uint32_t ticks_ms = 0;
34+
void board_init(void) {
3535

36-
#define HAL_LFCLK_FREQ (32768UL)
37-
#define HAL_RTC_FREQ (1024UL)
38-
#define HAL_RTC_COUNTER_PRESCALER ((HAL_LFCLK_FREQ/HAL_RTC_FREQ)-1)
39-
40-
/* Maximum RTC ticks */
41-
#define portNRF_RTC_MAXTICKS ((1U<<24)-1U)
42-
43-
void board_init(void)
44-
{
45-
// 32Khz XTAL
46-
NRF_CLOCK->LFCLKSRC = (uint32_t)((CLOCK_LFCLKSRC_SRC_Xtal << CLOCK_LFCLKSRC_SRC_Pos) & CLOCK_LFCLKSRC_SRC_Msk);
47-
NRF_CLOCK->TASKS_LFCLKSTART = 1UL;
48-
49-
// Set up RTC1 as tick timer
50-
NVIC_DisableIRQ(RTC1_IRQn);
51-
NRF_RTC1->EVTENCLR = RTC_EVTEN_COMPARE0_Msk;
52-
NRF_RTC1->INTENCLR = RTC_INTENSET_COMPARE0_Msk;
53-
NRF_RTC1->TASKS_STOP = 1;
54-
NRF_RTC1->TASKS_CLEAR = 1;
55-
56-
ticks_ms = 0;
57-
58-
NRF_RTC1->PRESCALER = HAL_RTC_COUNTER_PRESCALER;
59-
NRF_RTC1->INTENSET = RTC_INTENSET_TICK_Msk;
60-
NRF_RTC1->TASKS_START = 1;
61-
NRF_RTC1->EVTENSET = RTC_EVTEN_OVRFLW_Msk;
62-
NVIC_SetPriority(RTC1_IRQn, 0xf); // lowest priority
63-
NVIC_EnableIRQ(RTC1_IRQn);
64-
}
65-
66-
void RTC1_IRQHandler(void)
67-
{
68-
// Clear event
69-
NRF_RTC1->EVENTS_TICK = 0;
70-
volatile uint32_t dummy = NRF_RTC1->EVENTS_TICK;
71-
(void) dummy;
72-
//
73-
//// Tick correction
74-
uint32_t systick_counter = NRF_RTC1->COUNTER;
75-
uint32_t diff = (systick_counter - ticks_ms) & portNRF_RTC_MAXTICKS;
76-
ticks_ms += diff;
7736
}
7837

7938
bool board_requests_safe_mode(void) {
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import board
2+
import digitalio
3+
import gamepad
4+
import time
5+
6+
pad = gamepad.GamePad(
7+
digitalio.DigitalInOut(board.PA11),
8+
digitalio.DigitalInOut(board.PA12),
9+
digitalio.DigitalInOut(board.PA24),
10+
digitalio.DigitalInOut(board.PA25),
11+
)
12+
13+
prev_buttons = 0
14+
15+
while True:
16+
buttons = pad.get_pressed()
17+
18+
if buttons != prev_buttons:
19+
for i in range(0, 4):
20+
bit = (1 << i)
21+
if (buttons & bit) != (prev_buttons & bit):
22+
print('Button %d %s' % (i + 1, 'pressed' if buttons & bit else 'released'))
23+
24+
prev_buttons = buttons
25+
26+
time.sleep(0.1)

ports/nrf/common-hal/time/__init__.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
#include "py/mphal.h"
2828

2929
#include "shared-bindings/time/__init__.h"
30-
#include "boards/board.h"
30+
#include "tick.h"
3131

3232
inline uint64_t common_hal_time_monotonic() {
3333
return ticks_ms;

ports/nrf/mpconfigport.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,9 @@
181181
#define MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF (1)
182182
#define MICROPY_EMERGENCY_EXCEPTION_BUF_SIZE (0)
183183

184+
// Scan gamepad every 32ms
185+
#define CIRCUITPY_GAMEPAD_TICKS 0x1f
186+
184187
// if sdk is in use, import configuration
185188
#if BLUETOOTH_SD
186189
#include "bluetooth_conf.h"
@@ -223,6 +226,7 @@ extern const struct _mp_obj_module_t random_module;
223226
extern const struct _mp_obj_module_t storage_module;
224227
extern const struct _mp_obj_module_t time_module;
225228
extern const struct _mp_obj_module_t supervisor_module;
229+
extern const struct _mp_obj_module_t gamepad_module;
226230

227231
extern const struct _mp_obj_module_t pyb_module;
228232
extern const struct _mp_obj_module_t machine_module;
@@ -269,6 +273,7 @@ extern const struct _mp_obj_module_t ble_module;
269273
{ MP_OBJ_NEW_QSTR (MP_QSTR_random ), (mp_obj_t)&random_module }, \
270274
{ MP_OBJ_NEW_QSTR (MP_QSTR_storage ), (mp_obj_t)&storage_module },\
271275
{ MP_OBJ_NEW_QSTR (MP_QSTR_supervisor ), (mp_obj_t)&supervisor_module }, \
276+
{ MP_OBJ_NEW_QSTR (MP_QSTR_gamepad ), (mp_obj_t)&gamepad_module }, \
272277
{ MP_OBJ_NEW_QSTR (MP_QSTR_time ), (mp_obj_t)&time_module }, \
273278
{ MP_ROM_QSTR (MP_QSTR_pyb ), MP_ROM_PTR(&pyb_module) }, \
274279
{ MP_ROM_QSTR (MP_QSTR_utime ), MP_ROM_PTR(&mp_module_utime) }, \

ports/nrf/supervisor/port.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,16 +28,18 @@
2828
#include "supervisor/port.h"
2929
#include "boards/board.h"
3030

31+
#include "shared-module/gamepad/__init__.h"
3132
#include "common-hal/microcontroller/Pin.h"
3233
#include "common-hal/pulseio/PWMOut.h"
34+
#include "tick.h"
3335

3436
safe_mode_t port_init(void) {
3537
board_init();
3638

37-
#if 0
3839
// Configure millisecond timer initialization.
3940
tick_init();
4041

42+
#if 0
4143
#ifdef CIRCUITPY_CANARY_WORD
4244
// Run in safe mode if the canary is corrupt.
4345
if (_ezero != CIRCUITPY_CANARY_WORD) {
@@ -54,6 +56,10 @@ safe_mode_t port_init(void) {
5456
}
5557

5658
void reset_port(void) {
59+
#ifdef CIRCUITPY_GAMEPAD_TICKS
60+
gamepad_reset();
61+
#endif
62+
5763
pwmout_reset();
5864
reset_all_pins();
5965
}

ports/nrf/tick.c

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
/*
2+
* This file is part of the MicroPython project, http://micropython.org/
3+
*
4+
* The MIT License (MIT)
5+
*
6+
* Copyright (c) 2017 Scott Shawcroft for Adafruit Industries
7+
*
8+
* Permission is hereby granted, free of charge, to any person obtaining a copy
9+
* of this software and associated documentation files (the "Software"), to deal
10+
* in the Software without restriction, including without limitation the rights
11+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12+
* copies of the Software, and to permit persons to whom the Software is
13+
* furnished to do so, subject to the following conditions:
14+
*
15+
* The above copyright notice and this permission notice shall be included in
16+
* all copies or substantial portions of the Software.
17+
*
18+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24+
* THE SOFTWARE.
25+
*/
26+
27+
#include "tick.h"
28+
29+
#include "supervisor/shared/autoreload.h"
30+
#include "shared-module/gamepad/__init__.h"
31+
#include "shared-bindings/microcontroller/Processor.h"
32+
#include "nrf.h"
33+
34+
// Global millisecond tick count
35+
volatile uint64_t ticks_ms = 0;
36+
37+
void SysTick_Handler(void) {
38+
// SysTick interrupt handler called when the SysTick timer reaches zero
39+
// (every millisecond).
40+
ticks_ms += 1;
41+
42+
#ifdef CIRCUITPY_AUTORELOAD_DELAY_MS
43+
autoreload_tick();
44+
#endif
45+
#ifdef CIRCUITPY_GAMEPAD_TICKS
46+
if (!(ticks_ms & CIRCUITPY_GAMEPAD_TICKS)) {
47+
gamepad_tick();
48+
}
49+
#endif
50+
}
51+
52+
void tick_init() {
53+
uint32_t ticks_per_ms = common_hal_mcu_processor_get_frequency() / 1000;
54+
SysTick_Config(ticks_per_ms);
55+
// NVIC_EnableIRQ(SysTick_IRQn);
56+
}
57+
58+
void tick_delay(uint32_t us) {
59+
uint32_t ticks_per_us = common_hal_mcu_processor_get_frequency() / 1000 / 1000;
60+
uint32_t us_between_ticks = SysTick->VAL / ticks_per_us;
61+
uint64_t start_ms = ticks_ms;
62+
while (us > 1000) {
63+
while (ticks_ms == start_ms) {}
64+
us -= us_between_ticks;
65+
start_ms = ticks_ms;
66+
us_between_ticks = 1000;
67+
}
68+
while (SysTick->VAL > ((us_between_ticks - us) * ticks_per_us)) {}
69+
}
70+
71+
// us counts down!
72+
void current_tick(uint64_t* ms, uint32_t* us_until_ms) {
73+
uint32_t ticks_per_us = common_hal_mcu_processor_get_frequency() / 1000 / 1000;
74+
*ms = ticks_ms;
75+
*us_until_ms = SysTick->VAL / ticks_per_us;
76+
}
77+
78+
void wait_until(uint64_t ms, uint32_t us_until_ms) {
79+
uint32_t ticks_per_us = common_hal_mcu_processor_get_frequency() / 1000 / 1000;
80+
while(ticks_ms <= ms && SysTick->VAL / ticks_per_us >= us_until_ms) {}
81+
}

ports/nrf/tick.h

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/*
2+
* This file is part of the MicroPython project, http://micropython.org/
3+
*
4+
* The MIT License (MIT)
5+
*
6+
* Copyright (c) 2017 Scott Shawcroft for Adafruit Industries
7+
*
8+
* Permission is hereby granted, free of charge, to any person obtaining a copy
9+
* of this software and associated documentation files (the "Software"), to deal
10+
* in the Software without restriction, including without limitation the rights
11+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12+
* copies of the Software, and to permit persons to whom the Software is
13+
* furnished to do so, subject to the following conditions:
14+
*
15+
* The above copyright notice and this permission notice shall be included in
16+
* all copies or substantial portions of the Software.
17+
*
18+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24+
* THE SOFTWARE.
25+
*/
26+
#ifndef MICROPY_INCLUDED_NRF_TICK_H
27+
#define MICROPY_INCLUDED_NRF_TICK_H
28+
29+
#include "mpconfigport.h"
30+
31+
#include <stdint.h>
32+
33+
extern volatile uint64_t ticks_ms;
34+
35+
extern struct timer_descriptor ms_timer;
36+
37+
void tick_init(void);
38+
39+
void tick_delay(uint32_t us);
40+
41+
void current_tick(uint64_t* ms, uint32_t* us_until_ms);
42+
// Do not call this with interrupts disabled because it may be waiting for
43+
// ticks_ms to increment.
44+
void wait_until(uint64_t ms, uint32_t us_until_ms);
45+
46+
#endif // MICROPY_INCLUDED_NRF_TICK_H

0 commit comments

Comments
 (0)