├── .github └── workflows │ └── main.yml ├── .gitignore ├── .gitmodules ├── .vscode ├── c_cpp_properties.json ├── launch.json └── tasks.json ├── LICENSE.md ├── Makefile ├── README.md ├── bootloader ├── .gitignore ├── Makefile ├── build │ └── nrf52832_xxaa_s132.hex ├── dfu_public_key.c ├── main.c ├── nrf_crypto_allocator.h ├── published_privkey.pem ├── sdk_config.h └── secure_bootloader_gcc_nrf52.ld ├── config-tables.h ├── main.c ├── modules ├── _mountfs.py ├── _mountramfs.py ├── _splashscreen.py ├── _test.py ├── bluetooth.c ├── bluetooth.h ├── camera.c ├── camera.py ├── device.c ├── display.c ├── display.py ├── font.h ├── fpga.c ├── frozen-manifest.py ├── led.c ├── microphone.c ├── modvgr2d-glue.c ├── rtt.c ├── storage.c ├── time.c ├── touch.c ├── touch.h ├── update.c └── update.py ├── monocle-core ├── monocle-critical.c ├── monocle-drivers.c ├── monocle-startup.c ├── monocle.h └── monocle.ld ├── mpconfigport.h ├── mphalport.c ├── mphalport.h ├── nrfx_config.h ├── nrfx_glue.h ├── nrfx_log.h ├── segger ├── SEGGER_RTT.c ├── SEGGER_RTT.h ├── SEGGER_RTT_Conf.h ├── SEGGER_RTT_Syscalls_GCC.c ├── SEGGER_RTT_printf.c └── license │ └── license.txt ├── softdevice ├── include │ ├── ble.h │ ├── ble_err.h │ ├── ble_gap.h │ ├── ble_gatt.h │ ├── ble_gattc.h │ ├── ble_gatts.h │ ├── ble_hci.h │ ├── ble_l2cap.h │ ├── ble_ranges.h │ ├── ble_types.h │ ├── nrf52 │ │ └── nrf_mbr.h │ ├── nrf_error.h │ ├── nrf_error_sdm.h │ ├── nrf_error_soc.h │ ├── nrf_nvic.h │ ├── nrf_sdm.h │ ├── nrf_soc.h │ └── nrf_svc.h ├── s132_nrf52_7.3.0_license-agreement.txt └── s132_nrf52_7.3.0_softdevice.hex └── tools ├── battery-model.xlsx ├── camera_test_script.py ├── decode_gowin_status.py ├── fontdraw.py ├── fontgen.py ├── oled-configuration-tables.xlsx ├── serial_console.py ├── upload_file.py └── vgrs.py /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | name: build_on_push 2 | 3 | on: 4 | push: 5 | branches: [ "main" ] 6 | pull_request: 7 | branches: [ "main" ] 8 | workflow_dispatch: 9 | 10 | jobs: 11 | mcu_build: 12 | runs-on: ubuntu-latest 13 | 14 | steps: 15 | - uses: actions/checkout@v3 16 | 17 | - name: Install dependencies 18 | run: | 19 | sudo apt install gcc-arm-none-eabi libnewlib-arm-none-eabi 20 | 21 | - name: Bootstrap the dependencies 22 | run: | 23 | git submodule update --init 24 | git -C micropython submodule update --init lib/micropython-lib 25 | 26 | - name: Build the firmware 27 | run: | 28 | make -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Ignore VSCode user specific files 2 | .vscode/.cortex-debug.peripherals.state.json 3 | .vscode/.cortex-debug.registers.state.json 4 | .vscode/settings.json 5 | 6 | # Ignore build output 7 | build 8 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "nrfx"] 2 | path = nrfx 3 | url = https://github.com/NordicSemiconductor/nrfx 4 | [submodule "micropython"] 5 | path = micropython 6 | url = https://github.com/micropython/micropython 7 | [submodule "modules/libvgrs"] 8 | path = modules/libvgrs 9 | url = https://github.com/sathibault/vgrs.git 10 | -------------------------------------------------------------------------------- /.vscode/c_cpp_properties.json: -------------------------------------------------------------------------------- 1 | { 2 | "configurations": [ 3 | { 4 | "name": "monocle-micropython", 5 | // Set this to your compiler path 6 | "compilerPath": "/opt/homebrew/bin/arm-none-eabi-gcc", 7 | "cStandard": "gnu17", 8 | "cppStandard": "gnu++14", 9 | "includePath": [ 10 | ".", 11 | "build", 12 | "micropython", 13 | "micropython/lib/cmsis/inc", 14 | "micropython/shared/readline", 15 | "modules", 16 | "modules/libvgrs/src", 17 | "monocle-core", 18 | "nrfx", 19 | "nrfx/drivers", 20 | "nrfx/drivers/include", 21 | "nrfx/drivers/src", 22 | "nrfx/hal", 23 | "nrfx/helpers", 24 | "nrfx/mdk", 25 | "nrfx/soc", 26 | "segger", 27 | "softdevice/include", 28 | "softdevice/include/nrf52" 29 | ], 30 | "defines": [ 31 | "NRF52832_XXAA", 32 | "NDEBUG", 33 | "CONFIG_NFCT_PINS_AS_GPIOS", 34 | "GIT_COMMIT=\"abcdefg\"", 35 | "BUILD_VERSION=\"vYY.DDD.HHMM\"" 36 | ] 37 | } 38 | ], 39 | "version": 4 40 | } -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Requires Cortex-Debug plugin for VSCode: 3 | // https://marketplace.visualstudio.com/items?itemName=marus25.cortex-debug 4 | "configurations": [ 5 | { 6 | "name": "JLink", 7 | "type": "cortex-debug", 8 | "servertype": "jlink", 9 | "request": "launch", 10 | "cwd": "${workspaceFolder}", 11 | "executable": "build/application.elf", 12 | "preLaunchTask": "Build", 13 | "device": "nRF52832_xxAA", 14 | "showDevDebugOutput": "none", 15 | "svdFile": "nrfx/mdk/nrf52.svd", 16 | "loadFiles": [ 17 | "softdevice/s132_nrf52_7.3.0_softdevice.hex", 18 | ], 19 | "preLaunchCommands": [ 20 | "monitor halt", 21 | "monitor speed 2000", 22 | "load" 23 | ], 24 | }, 25 | { 26 | "name": "Black Magic", 27 | "type": "cortex-debug", 28 | "servertype": "bmp", 29 | "request": "launch", 30 | "cwd": "${workspaceFolder}", 31 | "executable": "build/application.elf", 32 | "preLaunchTask": "Build", 33 | "interface": "swd", 34 | "device": "nRF52832_xxAA", 35 | "BMPGDBSerialPort": "/dev/cu.usbmodem97B6BC101", 36 | "runToEntryPoint": "main", 37 | "showDevDebugOutput": "raw", 38 | "svdFile": "nrfx/mdk/nrf52.svd", 39 | "preLaunchCommands": [ 40 | "monitor erase_mass", 41 | "load softdevice/s132_nrf52_7.3.0_softdevice.hex", 42 | ], 43 | } 44 | ] 45 | } -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | // See https://go.microsoft.com/fwlink/?LinkId=733558 3 | // for the documentation about the tasks.json format 4 | "version": "2.0.0", 5 | "tasks": [ 6 | { 7 | "label": "Build", 8 | "type": "shell", 9 | "command": "make -j`getconf _NPROCESSORS_ONLN`", 10 | "problemMatcher": [ 11 | "$gcc" 12 | ], 13 | "presentation": { 14 | "echo": false, 15 | "reveal": "silent", 16 | "focus": false, 17 | "panel": "shared", 18 | "showReuseMessage": false, 19 | "clear": true 20 | }, 21 | "group": { 22 | "kind": "build", 23 | "isDefault": true 24 | }, 25 | }, 26 | { 27 | "label": "Build & Flash Chip", 28 | "type": "shell", 29 | "command": "make -j`getconf _NPROCESSORS_ONLN` flash", 30 | "problemMatcher": [ 31 | "$gcc" 32 | ], 33 | "presentation": { 34 | "echo": false, 35 | "reveal": "always", 36 | "focus": false, 37 | "panel": "shared", 38 | "showReuseMessage": false, 39 | "clear": true 40 | }, 41 | "group": { 42 | "kind": "build", 43 | "isDefault": false 44 | }, 45 | }, 46 | { 47 | "label": "Erase & Unlock Chip", 48 | "type": "shell", 49 | "command": "make recover", 50 | "problemMatcher": [], 51 | "presentation": { 52 | "echo": false, 53 | "reveal": "always", 54 | "focus": false, 55 | "panel": "shared", 56 | "showReuseMessage": false, 57 | "clear": true 58 | }, 59 | }, 60 | { 61 | "label": "Clean", 62 | "type": "shell", 63 | "command": "make clean", 64 | "problemMatcher": [], 65 | "presentation": { 66 | "echo": false, 67 | "reveal": "silent", 68 | "focus": false, 69 | "panel": "shared", 70 | "showReuseMessage": false, 71 | "clear": true 72 | }, 73 | }, 74 | { 75 | "label": "Release", 76 | "type": "shell", 77 | "command": "make release", 78 | "problemMatcher": [ 79 | "$gcc" 80 | ], 81 | "presentation": { 82 | "echo": false, 83 | "reveal": "always", 84 | "focus": false, 85 | "panel": "shared", 86 | "showReuseMessage": false, 87 | "clear": true 88 | }, 89 | "group": { 90 | "kind": "build", 91 | "isDefault": false 92 | }, 93 | }, 94 | { 95 | "label": "RTT Debug Console", 96 | "type": "shell", 97 | "command": "JLinkRTTClient", 98 | "problemMatcher": [], 99 | "presentation": { 100 | "echo": false, 101 | "reveal": "always", 102 | "focus": false, 103 | "panel": "dedicated", 104 | "showReuseMessage": false, 105 | "clear": true 106 | }, 107 | }, 108 | ] 109 | } -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | ISC Licence 2 | 3 | Copyright © 2023 Brilliant Labs Ltd. 4 | 5 | Permission to use, copy, modify, and/or distribute this software for any 6 | purpose with or without fee is hereby granted, provided that the above 7 | copyright notice and this permission notice appear in all copies. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 10 | REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 11 | AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 12 | INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 13 | LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 14 | OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 15 | PERFORMANCE OF THIS SOFTWARE. -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # This file is part of the MicroPython for Monocle project: 3 | # https://github.com/brilliantlabsAR/monocle-micropython 4 | # 5 | # Authored by: Josuah Demangeon (me@josuah.net) 6 | # Raj Nakarja / Brilliant Labs Ltd. (raj@itsbrilliant.co) 7 | # 8 | # ISC Licence 9 | # 10 | # Copyright © 2023 Brilliant Labs Ltd. 11 | # 12 | # Permission to use, copy, modify, and/or distribute this software for any 13 | # purpose with or without fee is hereby granted, provided that the above 14 | # copyright notice and this permission notice appear in all copies. 15 | # 16 | # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 17 | # REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 18 | # AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 19 | # INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 20 | # LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 21 | # OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 22 | # PERFORMANCE OF THIS SOFTWARE. 23 | # 24 | 25 | # Include the core environment definitions 26 | include micropython/py/mkenv.mk 27 | 28 | # Set makefile-level MicroPython feature configurations 29 | MICROPY_ROM_TEXT_COMPRESSION ?= 1 30 | 31 | # Which python files to freeze into the firmware are listed in here 32 | FROZEN_MANIFEST = modules/frozen-manifest.py 33 | 34 | # Include py core make definitions 35 | include micropython/py/py.mk 36 | 37 | # Define the toolchain prefix for ARM GCC 38 | CROSS_COMPILE = arm-none-eabi- 39 | 40 | # Use date and time as build version "vYY.DDD.HHMM". := forces evaluation once 41 | BUILD_VERSION := $(shell TZ= date +v%y.%j.%H%M) 42 | 43 | # Warning options 44 | WARN = -Wall -Werror -Wdouble-promotion -Wfloat-conversion 45 | 46 | # Build optimizations 47 | OPT += -mcpu=cortex-m4 48 | OPT += -mthumb 49 | OPT += -mabi=aapcs 50 | OPT += -mfloat-abi=hard 51 | OPT += -mfpu=fpv4-sp-d16 52 | OPT += -std=gnu17 53 | OPT += -Os -g0 54 | OPT += -fdata-sections -ffunction-sections 55 | OPT += -fsingle-precision-constant 56 | OPT += -fshort-enums 57 | OPT += -fno-strict-aliasing 58 | OPT += -fno-common 59 | OPT += -flto 60 | 61 | # Save some code space for performance-critical code 62 | CSUPEROPT = -Os 63 | 64 | # Set defines 65 | DEFS += -DNRF52832_XXAA 66 | DEFS += -DNDEBUG 67 | DEFS += -DCONFIG_NFCT_PINS_AS_GPIOS 68 | DEFS += -DBUILD_VERSION='"$(BUILD_VERSION)"' 69 | DEFS += -DLFS2_NO_ASSERT 70 | 71 | # Set linker options 72 | LDFLAGS += -Lnrfx/mdk -T monocle-core/monocle.ld 73 | LDFLAGS += -Wl,--gc-sections 74 | LDFLAGS += -Xlinker -Map=$(@:.elf=.map) 75 | LDFLAGS += --specs=nano.specs 76 | 77 | INC += -I. 78 | INC += -Ibuild 79 | INC += -Imicropython 80 | INC += -Imicropython/lib/cmsis/inc 81 | INC += -Imicropython/shared/readline 82 | INC += -Imodules 83 | INC += -Imodules/libvgrs/src 84 | INC += -Imonocle-core 85 | INC += -Inrfx 86 | INC += -Inrfx/drivers 87 | INC += -Inrfx/drivers/include 88 | INC += -Inrfx/drivers/src 89 | INC += -Inrfx/hal 90 | INC += -Inrfx/helpers 91 | INC += -Inrfx/mdk 92 | INC += -Inrfx/soc 93 | INC += -Isegger 94 | INC += -Isoftdevice/include 95 | INC += -Isoftdevice/include/nrf52 96 | 97 | # Assemble the C flags variable 98 | CFLAGS += $(WARN) $(OPT) $(INC) $(DEFS) 99 | 100 | SRC_C += main.c 101 | SRC_C += monocle-core/monocle-critical.c 102 | SRC_C += monocle-core/monocle-drivers.c 103 | SRC_C += monocle-core/monocle-startup.c 104 | SRC_C += mphalport.c 105 | 106 | SRC_C += micropython/extmod/modasyncio.c 107 | SRC_C += micropython/extmod/modbinascii.c 108 | SRC_C += micropython/extmod/modhashlib.c 109 | SRC_C += micropython/extmod/modjson.c 110 | SRC_C += micropython/extmod/modos.c 111 | SRC_C += micropython/extmod/modrandom.c 112 | SRC_C += micropython/extmod/modre.c 113 | SRC_C += micropython/extmod/modselect.c 114 | SRC_C += micropython/extmod/modtime.c 115 | SRC_C += micropython/extmod/vfs_blockdev.c 116 | SRC_C += micropython/extmod/vfs_lfs.c 117 | SRC_C += micropython/extmod/vfs_lfsx_file.c 118 | SRC_C += micropython/extmod/vfs_lfsx.c 119 | SRC_C += micropython/extmod/vfs_reader.c 120 | SRC_C += micropython/extmod/vfs.c 121 | SRC_C += modules/bluetooth.c 122 | SRC_C += modules/camera.c 123 | SRC_C += modules/device.c 124 | SRC_C += modules/display.c 125 | SRC_C += modules/fpga.c 126 | SRC_C += modules/led.c 127 | SRC_C += modules/microphone.c 128 | SRC_C += modules/rtt.c 129 | SRC_C += modules/storage.c 130 | SRC_C += modules/touch.c 131 | SRC_C += modules/update.c 132 | SRC_C += modules/libvgrs/src/modvgr2d.c 133 | SRC_C += modules/libvgrs/src/vgr2dlib.c 134 | SRC_C += modules/modvgr2d-glue.c 135 | 136 | SRC_C += segger/SEGGER_RTT_printf.c 137 | SRC_C += segger/SEGGER_RTT_Syscalls_GCC.c 138 | SRC_C += segger/SEGGER_RTT.c 139 | 140 | SRC_C += micropython/shared/readline/readline.c 141 | SRC_C += micropython/shared/runtime/gchelper_generic.c 142 | SRC_C += micropython/shared/runtime/interrupt_char.c 143 | SRC_C += micropython/shared/runtime/pyexec.c 144 | SRC_C += micropython/shared/runtime/stdout_helpers.c 145 | SRC_C += micropython/shared/runtime/sys_stdio_mphal.c 146 | SRC_C += micropython/shared/timeutils/timeutils.c 147 | 148 | SRC_C += micropython/lib/libm/acoshf.c 149 | SRC_C += micropython/lib/libm/asinfacosf.c 150 | SRC_C += micropython/lib/libm/asinhf.c 151 | SRC_C += micropython/lib/libm/atan2f.c 152 | SRC_C += micropython/lib/libm/atanf.c 153 | SRC_C += micropython/lib/libm/atanhf.c 154 | SRC_C += micropython/lib/libm/ef_rem_pio2.c 155 | SRC_C += micropython/lib/libm/ef_sqrt.c 156 | SRC_C += micropython/lib/libm/erf_lgamma.c 157 | SRC_C += micropython/lib/libm/fmodf.c 158 | SRC_C += micropython/lib/libm/kf_cos.c 159 | SRC_C += micropython/lib/libm/kf_rem_pio2.c 160 | SRC_C += micropython/lib/libm/kf_sin.c 161 | SRC_C += micropython/lib/libm/kf_tan.c 162 | SRC_C += micropython/lib/libm/log1pf.c 163 | SRC_C += micropython/lib/libm/math.c 164 | SRC_C += micropython/lib/libm/nearbyintf.c 165 | SRC_C += micropython/lib/libm/roundf.c 166 | SRC_C += micropython/lib/libm/sf_cos.c 167 | SRC_C += micropython/lib/libm/sf_erf.c 168 | SRC_C += micropython/lib/libm/sf_frexp.c 169 | SRC_C += micropython/lib/libm/sf_ldexp.c 170 | SRC_C += micropython/lib/libm/sf_modf.c 171 | SRC_C += micropython/lib/libm/sf_sin.c 172 | SRC_C += micropython/lib/libm/sf_tan.c 173 | SRC_C += micropython/lib/libm/wf_lgamma.c 174 | SRC_C += micropython/lib/libm/wf_tgamma.c 175 | SRC_C += micropython/lib/littlefs/lfs2_util.c 176 | SRC_C += micropython/lib/littlefs/lfs2.c 177 | SRC_C += micropython/lib/uzlib/crc32.c 178 | 179 | SRC_C += nrfx/drivers/src/nrfx_clock.c 180 | SRC_C += nrfx/drivers/src/nrfx_gpiote.c 181 | SRC_C += nrfx/drivers/src/nrfx_nvmc.c 182 | SRC_C += nrfx/drivers/src/nrfx_rtc.c 183 | SRC_C += nrfx/drivers/src/nrfx_saadc.c 184 | SRC_C += nrfx/drivers/src/nrfx_spi.c 185 | SRC_C += nrfx/drivers/src/nrfx_spim.c 186 | SRC_C += nrfx/drivers/src/nrfx_systick.c 187 | SRC_C += nrfx/drivers/src/nrfx_timer.c 188 | SRC_C += nrfx/drivers/src/nrfx_twim.c 189 | SRC_C += nrfx/drivers/src/prs/nrfx_prs.c 190 | SRC_C += nrfx/helpers/nrfx_flag32_allocator.c 191 | SRC_C += nrfx/mdk/system_nrf52.c 192 | 193 | SRC_QSTR += $(SRC_C) 194 | 195 | OBJ += $(PY_O) 196 | OBJ += $(addprefix build/, $(SRC_C:.c=.o)) 197 | 198 | # Link required libraries 199 | LIB += -lm -lc -lnosys -lgcc 200 | 201 | all: build/application.hex 202 | 203 | build/application.hex: build/application.elf 204 | $(OBJCOPY) -O ihex $< $@ 205 | 206 | build/application.elf: $(OBJ) 207 | $(ECHO) "LINK $@" 208 | $(Q)$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(OBJ) $(LIB) 209 | $(Q)$(SIZE) $@ 210 | 211 | flash: build/application.hex 212 | nrfjprog -q --program softdevice/*.hex --chiperase 213 | nrfjprog -q --program build/application.hex 214 | nrfjprog --reset -f nrf52 215 | 216 | recover: 217 | nrfjprog --recover 218 | 219 | release: clean build/application.hex 220 | nrfutil settings generate --family NRF52 --application build/application.hex --application-version 0 --bootloader-version 0 --bl-settings-version 2 build/settings.hex 221 | mergehex -m build/settings.hex build/application.hex softdevice/s132_nrf52_7.3.0_softdevice.hex bootloader/build/nrf52832_xxaa_s132.hex -o build/monocle-micropython-$(BUILD_VERSION).hex 222 | nrfutil pkg generate --hw-version 52 --application-version 0 --application build/application.hex --sd-req 0x0124 --key-file bootloader/published_privkey.pem build/monocle-micropython-$(BUILD_VERSION).zip 223 | 224 | include micropython/py/mkrules.mk 225 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # MicroPython for Monocle 2 | 3 | A custom deployment of MicroPython designed specifically for Monocle. Check out the user docs [here](https://docs.brilliant.xyz). 4 | 5 | For those of you who want to modify the standard firmware, keep on reading. 6 | 7 | ## Getting started with development 8 | 9 | 1. Ensure you have the [ARM GCC Toolchain](https://developer.arm.com/downloads/-/gnu-rm) installed. 10 | 11 | 1. Ensure you have the [nRF Command Line Tools](https://www.nordicsemi.com/Products/Development-tools/nrf-command-line-tools) installed. 12 | 13 | 1. Clone this repository along with submodules and build the mpy-cross toolchain: 14 | 15 | ```sh 16 | git clone https://github.com/brilliantlabsAR/monocle-micropython.git 17 | cd monocle-micropython 18 | 19 | git submodule update --init 20 | git -C micropython submodule update --init lib/micropython-lib 21 | 22 | make -C micropython/mpy-cross 23 | ``` 24 | 25 | 1. You should now be able to build the project by calling `make` from the `monocle-micropython` folder. 26 | 27 | ```sh 28 | make 29 | ``` 30 | 31 | 1. Before flashing an nRF5340, you may need to unlock the chip first. 32 | 33 | ```sh 34 | nrfjprog --recover 35 | ``` 36 | 37 | 1. You should then be able to flash the device. 38 | 39 | ```sh 40 | make flash 41 | ``` 42 | 43 | ### Debugging 44 | 45 | 1. Open the project in [VSCode](https://code.visualstudio.com). 46 | 47 | There are some build tasks already configured within `.vscode/tasks.json`. Access them by pressing `Ctrl-Shift-P` (`Cmd-Shift-P` on MacOS) → `Tasks: Run Task`. 48 | 49 | 1. Build 50 | 1. Build & Flash Chip 51 | 1. Erase & Unlock Chip 52 | 1. Clean 53 | 54 | 1. Connect your debugger as described [here](https://docs.brilliant.xyz/monocle/monocle/#manually-programming). 55 | 56 | 1. You many need to unlock the device by using the `Erase Chip` task before programming or debugging. 57 | 58 | 1. To enable IntelliSense, be sure to select the correct compiler from within VSCode. `Ctrl-Shift-P` (`Cmd-Shift-P` on MacOS) → `C/C++: Select IntelliSense Configuration` → `Use arm-none-eabi-gcc`. 59 | 60 | 1. Install the [Cortex-Debug](https://marketplace.visualstudio.com/items?itemName=marus25.cortex-debug) extension for VSCode in order to enable debugging. 61 | 62 | 1. A debugging launch is already configured within `.vscode/launch.json`. Run the `J-Link` launch configuration from the `Run and Debug` panel, or press `F5`. The project will automatically build and flash before launching. 63 | 64 | 1. To monitor the logs, run the task `RTT Console` and ensure the `J-Link` launch configuration is running. 65 | 66 | ### Generating final release `.hex` and DFU `.zip` files 67 | 68 | 1. Download and install [nrfutil](https://www.nordicsemi.com/Products/Development-tools/nRF-Util) including the `nrf5sdk-tools` package: 69 | 70 | ```sh 71 | chmod +x nrfutil 72 | # Make sure to add nrfutil to your path 73 | nrfutil install nrf5sdk-tools 74 | ``` 75 | 76 | 1. Generate a settings file: 77 | 78 | ```sh 79 | nrfutil settings generate --family NRF52 --application build/application.hex --application-version 0 --bootloader-version 0 --bl-settings-version 2 build/settings.hex 80 | ``` 81 | 82 | 1. Download and install the `mergehex` tool which is a part of the [nRF Command Line Tools](https://www.nordicsemi.com/Products/Development-tools/nrf-command-line-tools). 83 | 84 | 1. Merge the settings, bootloader, softdevice and application hex files: 85 | 86 | ```sh 87 | mergehex -m build/settings.hex build/application.hex softdevice/s132_nrf52_7.3.0_softdevice.hex bootloader/build/nrf52832_xxaa_s132.hex -o build/release.hex 88 | ``` 89 | 90 | 1. Create the DFU zip package using the command: 91 | 92 | ```sh 93 | nrfutil pkg generate --hw-version 52 --application-version 0 --application build/application.hex --sd-req 0x0124 --key-file bootloader/published_privkey.pem build/release.zip 94 | ``` 95 | 96 | ## FPGA 97 | 98 | For information on developing and flashing the FPGA binary. Check the [Monocle FPGA](https://github.com/brilliantlabsAR/monocle-fpga) repository. -------------------------------------------------------------------------------- /bootloader/.gitignore: -------------------------------------------------------------------------------- 1 | /nRF5_SDK_* 2 | /build/* 3 | !/build/nrf52832_xxaa_s132.hex 4 | -------------------------------------------------------------------------------- /bootloader/dfu_public_key.c: -------------------------------------------------------------------------------- 1 | 2 | /* This file was automatically generated by nrfutil on 2022-11-23 (YY-MM-DD) at 05:56:00 */ 3 | 4 | #include "stdint.h" 5 | #include "compiler_abstraction.h" 6 | 7 | /** @brief Public key used to verify DFU images */ 8 | __ALIGN(4) const uint8_t pk[64] = 9 | { 10 | 0xed, 0x7c, 0x3d, 0x22, 0x4d, 0x5c, 0x7b, 0x9c, 0x25, 0xd7, 0x0d, 0x3e, 0x63, 0xaa, 0x2f, 0x26, 0x3c, 0x6a, 0xf2, 0xbf, 0xd1, 0x0a, 0x75, 0x67, 0x08, 0xae, 0xc1, 0xd1, 0x38, 0x87, 0xfd, 0x89, 11 | 0xa4, 0x1d, 0xa8, 0x50, 0x1d, 0x2d, 0xb1, 0x99, 0xc8, 0x70, 0xa6, 0xfb, 0x00, 0x4c, 0x95, 0x95, 0x36, 0xa3, 0x43, 0xdf, 0xf8, 0xc7, 0x4c, 0xeb, 0xee, 0xcc, 0xaf, 0xf5, 0x0e, 0xca, 0x0d, 0x0f 12 | }; 13 | 14 | -------------------------------------------------------------------------------- /bootloader/main.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2016 - 2021, Nordic Semiconductor ASA 3 | * 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without modification, 7 | * are permitted provided that the following conditions are met: 8 | * 9 | * 1. Redistributions of source code must retain the above copyright notice, this 10 | * list of conditions and the following disclaimer. 11 | * 12 | * 2. Redistributions in binary form, except as embedded into a Nordic 13 | * Semiconductor ASA integrated circuit in a product or a software update for 14 | * such product, must reproduce the above copyright notice, this list of 15 | * conditions and the following disclaimer in the documentation and/or other 16 | * materials provided with the distribution. 17 | * 18 | * 3. Neither the name of Nordic Semiconductor ASA nor the names of its 19 | * contributors may be used to endorse or promote products derived from this 20 | * software without specific prior written permission. 21 | * 22 | * 4. This software, with or without modification, must only be used with a 23 | * Nordic Semiconductor ASA integrated circuit. 24 | * 25 | * 5. Any software provided in binary form under this license must not be reverse 26 | * engineered, decompiled, modified and/or disassembled. 27 | * 28 | * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS 29 | * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 30 | * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE 31 | * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE 32 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 33 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 34 | * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 35 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 36 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 37 | * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 38 | * 39 | */ 40 | /** @file 41 | * 42 | * @defgroup bootloader_secure_ble main.c 43 | * @{ 44 | * @ingroup dfu_bootloader_api 45 | * @brief Bootloader project main file for secure DFU. 46 | * 47 | */ 48 | 49 | #include 50 | #include "boards.h" 51 | #include "nrf_mbr.h" 52 | #include "nrf_bootloader.h" 53 | #include "nrf_bootloader_app_start.h" 54 | #include "nrf_bootloader_dfu_timers.h" 55 | #include "nrf_dfu.h" 56 | #include "nrf_log.h" 57 | #include "nrf_log_ctrl.h" 58 | #include "nrf_log_default_backends.h" 59 | #include "app_error.h" 60 | #include "app_error_weak.h" 61 | #include "nrf_bootloader_info.h" 62 | #include "nrf_delay.h" 63 | 64 | static void on_error(void) 65 | { 66 | NRF_LOG_FINAL_FLUSH(); 67 | 68 | #if NRF_MODULE_ENABLED(NRF_LOG_BACKEND_RTT) 69 | // To allow the buffer to be flushed by the host. 70 | nrf_delay_ms(100); 71 | #endif 72 | #ifdef NRF_DFU_DEBUG_VERSION 73 | NRF_BREAKPOINT_COND; 74 | #endif 75 | NVIC_SystemReset(); 76 | } 77 | 78 | 79 | void app_error_handler(uint32_t error_code, uint32_t line_num, const uint8_t * p_file_name) 80 | { 81 | NRF_LOG_ERROR("%s:%d", p_file_name, line_num); 82 | on_error(); 83 | } 84 | 85 | 86 | void app_error_fault_handler(uint32_t id, uint32_t pc, uint32_t info) 87 | { 88 | NRF_LOG_ERROR("Received a fault! id: 0x%08x, pc: 0x%08x, info: 0x%08x", id, pc, info); 89 | on_error(); 90 | } 91 | 92 | 93 | void app_error_handler_bare(uint32_t error_code) 94 | { 95 | NRF_LOG_ERROR("Received an error: 0x%08x!", error_code); 96 | on_error(); 97 | } 98 | 99 | /** 100 | * @brief Function notifies certain events in DFU process. 101 | */ 102 | static void dfu_observer(nrf_dfu_evt_type_t evt_type) 103 | { 104 | switch (evt_type) 105 | { 106 | case NRF_DFU_EVT_DFU_FAILED: 107 | case NRF_DFU_EVT_DFU_ABORTED: 108 | case NRF_DFU_EVT_DFU_INITIALIZED: 109 | bsp_board_init(BSP_INIT_LEDS); 110 | bsp_board_led_on(BSP_BOARD_LED_0); 111 | bsp_board_led_on(BSP_BOARD_LED_1); 112 | bsp_board_led_off(BSP_BOARD_LED_2); 113 | break; 114 | case NRF_DFU_EVT_TRANSPORT_ACTIVATED: 115 | bsp_board_led_off(BSP_BOARD_LED_1); 116 | bsp_board_led_on(BSP_BOARD_LED_2); 117 | break; 118 | case NRF_DFU_EVT_DFU_STARTED: 119 | break; 120 | default: 121 | break; 122 | } 123 | } 124 | 125 | 126 | /**@brief Function for application main entry. */ 127 | int main(void) 128 | { 129 | uint32_t ret_val; 130 | 131 | // Must happen before flash protection is applied, since it edits a protected page. 132 | nrf_bootloader_mbr_addrs_populate(); 133 | 134 | // Protect MBR and bootloader code from being overwritten. 135 | ret_val = nrf_bootloader_flash_protect(0, MBR_SIZE); 136 | APP_ERROR_CHECK(ret_val); 137 | ret_val = nrf_bootloader_flash_protect(BOOTLOADER_START_ADDR, BOOTLOADER_SIZE); 138 | APP_ERROR_CHECK(ret_val); 139 | 140 | (void) NRF_LOG_INIT(nrf_bootloader_dfu_timer_counter_get); 141 | NRF_LOG_DEFAULT_BACKENDS_INIT(); 142 | 143 | NRF_LOG_INFO("Inside main"); 144 | 145 | ret_val = nrf_bootloader_init(dfu_observer); 146 | APP_ERROR_CHECK(ret_val); 147 | 148 | NRF_LOG_FLUSH(); 149 | 150 | NRF_LOG_ERROR("After main, should never be reached."); 151 | NRF_LOG_FLUSH(); 152 | 153 | APP_ERROR_CHECK_BOOL(false); 154 | } 155 | 156 | /** 157 | * @} 158 | */ 159 | -------------------------------------------------------------------------------- /bootloader/nrf_crypto_allocator.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2019 - 2021, Nordic Semiconductor ASA 3 | * 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without modification, 7 | * are permitted provided that the following conditions are met: 8 | * 9 | * 1. Redistributions of source code must retain the above copyright notice, this 10 | * list of conditions and the following disclaimer. 11 | * 12 | * 2. Redistributions in binary form, except as embedded into a Nordic 13 | * Semiconductor ASA integrated circuit in a product or a software update for 14 | * such product, must reproduce the above copyright notice, this list of 15 | * conditions and the following disclaimer in the documentation and/or other 16 | * materials provided with the distribution. 17 | * 18 | * 3. Neither the name of Nordic Semiconductor ASA nor the names of its 19 | * contributors may be used to endorse or promote products derived from this 20 | * software without specific prior written permission. 21 | * 22 | * 4. This software, with or without modification, must only be used with a 23 | * Nordic Semiconductor ASA integrated circuit. 24 | * 25 | * 5. Any software provided in binary form under this license must not be reverse 26 | * engineered, decompiled, modified and/or disassembled. 27 | * 28 | * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS 29 | * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 30 | * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE 31 | * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE 32 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 33 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 34 | * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 35 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 36 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 37 | * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 38 | * 39 | */ 40 | #ifndef NRF_CRYPTO_ALLOCATOR_H__ 41 | #define NRF_CRYPTO_ALLOCATOR_H__ 42 | 43 | #include "nrf_assert.h" 44 | 45 | #ifdef __cplusplus 46 | extern "C" { 47 | #endif 48 | 49 | /* Crypto library in bootloader case does not use dynamic allocation */ 50 | #define NRF_CRYPTO_ALLOC(size) NULL; ASSERT(0) 51 | #define NRF_CRYPTO_ALLOC_ON_STACK(size) NULL; ASSERT(0) 52 | #define NRF_CRYPTO_FREE(ptr) (void)ptr; 53 | 54 | #ifdef __cplusplus 55 | } 56 | #endif 57 | 58 | #endif /* NRF_CRYPTO_ALLOCATOR_H__ */ 59 | -------------------------------------------------------------------------------- /bootloader/published_privkey.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN EC PRIVATE KEY----- 2 | MHcCAQEEIEplHSD9QCQEvtp0O4GnCwjGh6ofQxXKa9Vt3SeHmkVCoAoGCCqGSM49 3 | AwEHoUQDQgAEif2HONHBrghndQrRv/JqPCYvqmM+DdclnHtcTSI9fO0PDcoO9a/M 4 | 7utMx/jfQ6M2lZVMAPumcMiZsS0dUKgdpA== 5 | -----END EC PRIVATE KEY----- 6 | -------------------------------------------------------------------------------- /bootloader/secure_bootloader_gcc_nrf52.ld: -------------------------------------------------------------------------------- 1 | /* Linker script to configure memory regions. */ 2 | 3 | SEARCH_DIR(.) 4 | GROUP(-lgcc -lc -lnosys) 5 | 6 | MEMORY 7 | { 8 | FLASH (rx) : ORIGIN = 0x78000, LENGTH = 0x6000 9 | RAM (rwx) : ORIGIN = 0x20005968, LENGTH = 0xa698 10 | uicr_bootloader_start_address (r) : ORIGIN = 0x10001014, LENGTH = 0x4 11 | bootloader_settings_page (r) : ORIGIN = 0x0007F000, LENGTH = 0x1000 12 | uicr_mbr_params_page (r) : ORIGIN = 0x10001018, LENGTH = 0x4 13 | mbr_params_page (r) : ORIGIN = 0x0007E000, LENGTH = 0x1000 14 | } 15 | 16 | SECTIONS 17 | { 18 | . = ALIGN(4); 19 | .uicr_bootloader_start_address : 20 | { 21 | PROVIDE(__start_uicr_bootloader_start_address = .); 22 | KEEP(*(SORT(.uicr_bootloader_start_address*))) 23 | PROVIDE(__stop_uicr_bootloader_start_address = .); 24 | } > uicr_bootloader_start_address 25 | . = ALIGN(4); 26 | .bootloader_settings_page(NOLOAD) : 27 | { 28 | PROVIDE(__start_bootloader_settings_page = .); 29 | KEEP(*(SORT(.bootloader_settings_page*))) 30 | PROVIDE(__stop_bootloader_settings_page = .); 31 | } > bootloader_settings_page 32 | . = ALIGN(4); 33 | .uicr_mbr_params_page : 34 | { 35 | PROVIDE(__start_uicr_mbr_params_page = .); 36 | KEEP(*(SORT(.uicr_mbr_params_page*))) 37 | PROVIDE(__stop_uicr_mbr_params_page = .); 38 | } > uicr_mbr_params_page 39 | . = ALIGN(4); 40 | .mbr_params_page(NOLOAD) : 41 | { 42 | PROVIDE(__start_mbr_params_page = .); 43 | KEEP(*(SORT(.mbr_params_page*))) 44 | PROVIDE(__stop_mbr_params_page = .); 45 | } > mbr_params_page 46 | } 47 | 48 | SECTIONS 49 | { 50 | . = ALIGN(4); 51 | .mem_section_dummy_ram : 52 | { 53 | } 54 | .log_dynamic_data : 55 | { 56 | PROVIDE(__start_log_dynamic_data = .); 57 | KEEP(*(SORT(.log_dynamic_data*))) 58 | PROVIDE(__stop_log_dynamic_data = .); 59 | } > RAM 60 | .log_filter_data : 61 | { 62 | PROVIDE(__start_log_filter_data = .); 63 | KEEP(*(SORT(.log_filter_data*))) 64 | PROVIDE(__stop_log_filter_data = .); 65 | } > RAM 66 | .fs_data : 67 | { 68 | PROVIDE(__start_fs_data = .); 69 | KEEP(*(.fs_data)) 70 | PROVIDE(__stop_fs_data = .); 71 | } > RAM 72 | 73 | } INSERT AFTER .data; 74 | 75 | SECTIONS 76 | { 77 | .mem_section_dummy_rom : 78 | { 79 | } 80 | .crypto_data : 81 | { 82 | PROVIDE(__start_crypto_data = .); 83 | KEEP(*(SORT(.crypto_data*))) 84 | PROVIDE(__stop_crypto_data = .); 85 | } > FLASH 86 | .nrf_queue : 87 | { 88 | PROVIDE(__start_nrf_queue = .); 89 | KEEP(*(.nrf_queue)) 90 | PROVIDE(__stop_nrf_queue = .); 91 | } > FLASH 92 | .dfu_trans : 93 | { 94 | PROVIDE(__start_dfu_trans = .); 95 | KEEP(*(SORT(.dfu_trans*))) 96 | PROVIDE(__stop_dfu_trans = .); 97 | } > FLASH 98 | .svc_data : 99 | { 100 | PROVIDE(__start_svc_data = .); 101 | KEEP(*(.svc_data)) 102 | PROVIDE(__stop_svc_data = .); 103 | } > FLASH 104 | .log_const_data : 105 | { 106 | PROVIDE(__start_log_const_data = .); 107 | KEEP(*(SORT(.log_const_data*))) 108 | PROVIDE(__stop_log_const_data = .); 109 | } > FLASH 110 | .nrf_balloc : 111 | { 112 | PROVIDE(__start_nrf_balloc = .); 113 | KEEP(*(.nrf_balloc)) 114 | PROVIDE(__stop_nrf_balloc = .); 115 | } > FLASH 116 | .sdh_ble_observers : 117 | { 118 | PROVIDE(__start_sdh_ble_observers = .); 119 | KEEP(*(SORT(.sdh_ble_observers*))) 120 | PROVIDE(__stop_sdh_ble_observers = .); 121 | } > FLASH 122 | .log_backends : 123 | { 124 | PROVIDE(__start_log_backends = .); 125 | KEEP(*(SORT(.log_backends*))) 126 | PROVIDE(__stop_log_backends = .); 127 | } > FLASH 128 | .sdh_req_observers : 129 | { 130 | PROVIDE(__start_sdh_req_observers = .); 131 | KEEP(*(SORT(.sdh_req_observers*))) 132 | PROVIDE(__stop_sdh_req_observers = .); 133 | } > FLASH 134 | .sdh_state_observers : 135 | { 136 | PROVIDE(__start_sdh_state_observers = .); 137 | KEEP(*(SORT(.sdh_state_observers*))) 138 | PROVIDE(__stop_sdh_state_observers = .); 139 | } > FLASH 140 | .sdh_stack_observers : 141 | { 142 | PROVIDE(__start_sdh_stack_observers = .); 143 | KEEP(*(SORT(.sdh_stack_observers*))) 144 | PROVIDE(__stop_sdh_stack_observers = .); 145 | } > FLASH 146 | .sdh_soc_observers : 147 | { 148 | PROVIDE(__start_sdh_soc_observers = .); 149 | KEEP(*(SORT(.sdh_soc_observers*))) 150 | PROVIDE(__stop_sdh_soc_observers = .); 151 | } > FLASH 152 | 153 | } INSERT AFTER .text 154 | 155 | 156 | INCLUDE "nrf_common.ld" 157 | -------------------------------------------------------------------------------- /modules/_mountfs.py: -------------------------------------------------------------------------------- 1 | import os, device 2 | 3 | bdev = device.Storage() 4 | 5 | try: 6 | os.mount(bdev, "/") 7 | except OSError: 8 | os.VfsLfs2.mkfs(bdev) 9 | os.mount(bdev, "/") 10 | 11 | del os 12 | del device 13 | del bdev 14 | -------------------------------------------------------------------------------- /modules/_mountramfs.py: -------------------------------------------------------------------------------- 1 | import os, device 2 | 3 | class RAMBlockDev: 4 | def __init__(self, block_size, num_blocks): 5 | self.block_size = block_size 6 | self.data = bytearray(block_size * num_blocks) 7 | 8 | def readblocks(self, block_num, buf, offset=0): 9 | addr = block_num * self.block_size + offset 10 | for i in range(len(buf)): 11 | buf[i] = self.data[addr + i] 12 | 13 | def writeblocks(self, block_num, buf, offset=None): 14 | if offset is None: 15 | # do erase, then write 16 | for i in range(len(buf) // self.block_size): 17 | self.ioctl(6, block_num + i) 18 | offset = 0 19 | addr = block_num * self.block_size + offset 20 | for i in range(len(buf)): 21 | self.data[addr + i] = buf[i] 22 | 23 | def ioctl(self, op, arg): 24 | if op == 4: # block count 25 | return len(self.data) // self.block_size 26 | if op == 5: # block size 27 | return self.block_size 28 | if op == 6: # block erase 29 | return 0 30 | 31 | bdev = RAMBlockDev(512, 32) 32 | os.VfsLfs2.mkfs(bdev) 33 | os.mount(bdev, "/") 34 | 35 | del os 36 | del device 37 | del bdev 38 | -------------------------------------------------------------------------------- /modules/_splashscreen.py: -------------------------------------------------------------------------------- 1 | import fpga, display 2 | 3 | 4 | def __splashscreen(): 5 | logo = display.Text( 6 | "MONOCLE", 320, 200, display.WHITE, justify=display.MIDDLE_CENTER 7 | ) 8 | bars_top = [] 9 | bars_bottom = [] 10 | 11 | starting_location = 185 12 | 13 | ax = 68 + starting_location + 70 14 | bx = 40 + starting_location + 70 15 | cx = 0 + starting_location + 70 16 | dx = 28 + starting_location + 70 17 | 18 | for i in range(6): 19 | if i == 0: 20 | color = 0xFF0000 21 | elif i == 1: 22 | color = 0xFFAA00 23 | elif i == 2: 24 | color = 0xFFFF00 25 | elif i == 3: 26 | color = 0x008800 27 | elif i == 4: 28 | color = 0x0000FF 29 | else: 30 | color = 0xAA00FF 31 | 32 | bars_top.append(display.Polygon([ax, 100, bx, 100, cx, 170, dx, 170], color)) 33 | ax += 28 34 | bx += 28 35 | cx += 28 36 | dx += 28 37 | 38 | ax = 68 + starting_location 39 | bx = 40 + starting_location 40 | cx = 0 + starting_location 41 | dx = 28 + starting_location 42 | 43 | for i in range(6): 44 | if i == 0: 45 | color = 0xFF0000 46 | elif i == 1: 47 | color = 0xFFAA00 48 | elif i == 2: 49 | color = 0xFFFF00 50 | elif i == 3: 51 | color = 0x008800 52 | elif i == 4: 53 | color = 0x0000FF 54 | else: 55 | color = 0xAA00FF 56 | 57 | bars_bottom.append(display.Polygon([ax, 230, bx, 230, cx, 300, dx, 300], color)) 58 | ax += 28 59 | bx += 28 60 | cx += 28 61 | dx += 28 62 | 63 | display.show(logo, bars_top, bars_bottom) 64 | 65 | 66 | if fpga.read(1, 4) == b"Mncl": 67 | __splashscreen() 68 | 69 | del fpga, display, __splashscreen 70 | -------------------------------------------------------------------------------- /modules/bluetooth.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the MicroPython for Monocle project: 3 | * https://github.com/brilliantlabsAR/monocle-micropython 4 | * 5 | * Authored by: Josuah Demangeon (me@josuah.net) 6 | * Raj Nakarja / Brilliant Labs Ltd. (raj@itsbrilliant.co) 7 | * 8 | * ISC Licence 9 | * 10 | * Copyright © 2023 Brilliant Labs Ltd. 11 | * 12 | * Permission to use, copy, modify, and/or distribute this software for any 13 | * purpose with or without fee is hereby granted, provided that the above 14 | * copyright notice and this permission notice appear in all copies. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 17 | * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 18 | * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 19 | * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 20 | * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 21 | * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 22 | * PERFORMANCE OF THIS SOFTWARE. 23 | */ 24 | 25 | #include "mphalport.h" 26 | #include "py/runtime.h" 27 | #include "py/objarray.h" 28 | 29 | static mp_obj_t receive_callback = mp_const_none; 30 | 31 | void bluetooth_receive_callback_handler(const uint8_t *bytes, size_t len) 32 | { 33 | if (receive_callback != mp_const_none) 34 | { 35 | mp_obj_t array = mp_obj_new_bytes(bytes, len); 36 | mp_sched_schedule(receive_callback, array); 37 | } 38 | } 39 | 40 | static mp_obj_t bluetooth_send(mp_obj_t buffer_in) 41 | { 42 | if (!ble_are_tx_notifications_enabled(DATA_TX)) 43 | { 44 | mp_raise_msg(&mp_type_OSError, 45 | MP_ERROR_TEXT( 46 | "notifications are not enabled on the data service")); 47 | } 48 | 49 | mp_buffer_info_t array; 50 | mp_get_buffer_raise(buffer_in, &array, MP_BUFFER_READ); 51 | 52 | if (array.len > ble_get_max_payload_size()) 53 | { 54 | mp_raise_msg(&mp_type_ValueError, 55 | MP_ERROR_TEXT("input buffer is too large")); 56 | } 57 | 58 | if (ble_send_raw_data(array.buf, array.len)) 59 | { 60 | mp_raise_msg(&mp_type_OSError, 61 | MP_ERROR_TEXT("raw data service is busy")); 62 | } 63 | 64 | return mp_const_none; 65 | } 66 | STATIC MP_DEFINE_CONST_FUN_OBJ_1(bluetooth_send_obj, bluetooth_send); 67 | 68 | static mp_obj_t bluetooth_receive_callback(size_t n_args, const mp_obj_t *args) 69 | { 70 | if (n_args == 0) 71 | { 72 | return receive_callback; 73 | } 74 | 75 | if (!mp_obj_is_callable(args[0]) && (args[0] != mp_const_none)) 76 | { 77 | mp_raise_ValueError( 78 | MP_ERROR_TEXT("callback must be None or a callable object")); 79 | } 80 | 81 | receive_callback = args[0]; 82 | 83 | return mp_const_none; 84 | } 85 | STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(bluetooth_receive_callback_obj, 0, 1, bluetooth_receive_callback); 86 | 87 | static mp_obj_t bluetooth_connected(void) 88 | { 89 | return ble_are_tx_notifications_enabled(DATA_TX) 90 | ? mp_const_true 91 | : mp_const_false; 92 | } 93 | STATIC MP_DEFINE_CONST_FUN_OBJ_0(bluetooth_connected_obj, bluetooth_connected); 94 | 95 | STATIC mp_obj_t bluetooth_max_length(void) 96 | { 97 | return mp_obj_new_int(ble_get_max_payload_size()); 98 | } 99 | STATIC MP_DEFINE_CONST_FUN_OBJ_0(bluetooth_max_length_obj, bluetooth_max_length); 100 | 101 | STATIC const mp_rom_map_elem_t bluetooth_module_globals_table[] = { 102 | {MP_ROM_QSTR(MP_QSTR_send), MP_ROM_PTR(&bluetooth_send_obj)}, 103 | {MP_ROM_QSTR(MP_QSTR_receive_callback), MP_ROM_PTR(&bluetooth_receive_callback_obj)}, 104 | {MP_ROM_QSTR(MP_QSTR_connected), MP_ROM_PTR(&bluetooth_connected_obj)}, 105 | {MP_ROM_QSTR(MP_QSTR_max_length), MP_ROM_PTR(&bluetooth_max_length_obj)}, 106 | }; 107 | STATIC MP_DEFINE_CONST_DICT(bluetooth_module_globals, bluetooth_module_globals_table); 108 | 109 | const mp_obj_module_t bluetooth_module = { 110 | .base = {&mp_type_module}, 111 | .globals = (mp_obj_dict_t *)&bluetooth_module_globals, 112 | }; 113 | MP_REGISTER_MODULE(MP_QSTR_bluetooth, bluetooth_module); 114 | -------------------------------------------------------------------------------- /modules/bluetooth.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the MicroPython for Monocle project: 3 | * https://github.com/brilliantlabsAR/monocle-micropython 4 | * 5 | * Authored by: Josuah Demangeon (me@josuah.net) 6 | * Raj Nakarja / Brilliant Labs Ltd. (raj@itsbrilliant.co) 7 | * 8 | * ISC Licence 9 | * 10 | * Copyright © 2023 Brilliant Labs Ltd. 11 | * 12 | * Permission to use, copy, modify, and/or distribute this software for any 13 | * purpose with or without fee is hereby granted, provided that the above 14 | * copyright notice and this permission notice appear in all copies. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 17 | * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 18 | * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 19 | * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 20 | * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 21 | * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 22 | * PERFORMANCE OF THIS SOFTWARE. 23 | */ 24 | 25 | #pragma once 26 | 27 | #include 28 | #include 29 | 30 | void bluetooth_receive_callback_handler(const uint8_t *bytes, size_t len); 31 | -------------------------------------------------------------------------------- /modules/camera.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the MicroPython for Monocle project: 3 | * https://github.com/brilliantlabsAR/monocle-micropython 4 | * 5 | * Authored by: Josuah Demangeon (me@josuah.net) 6 | * Raj Nakarja / Brilliant Labs Ltd. (raj@itsbrilliant.co) 7 | * 8 | * ISC Licence 9 | * 10 | * Copyright © 2023 Brilliant Labs Ltd. 11 | * 12 | * Permission to use, copy, modify, and/or distribute this software for any 13 | * purpose with or without fee is hereby granted, provided that the above 14 | * copyright notice and this permission notice appear in all copies. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 17 | * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 18 | * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 19 | * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 20 | * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 21 | * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 22 | * PERFORMANCE OF THIS SOFTWARE. 23 | */ 24 | 25 | #include "nrf_gpio.h" 26 | #include "nrfx_systick.h" 27 | #include "py/runtime.h" 28 | 29 | STATIC mp_obj_t camera_sleep(void) 30 | { 31 | nrf_gpio_pin_write(CAMERA_SLEEP_PIN, true); 32 | return mp_const_none; 33 | } 34 | STATIC MP_DEFINE_CONST_FUN_OBJ_0(camera_sleep_obj, camera_sleep); 35 | 36 | STATIC mp_obj_t camera_wake(void) 37 | { 38 | nrf_gpio_pin_write(CAMERA_SLEEP_PIN, false); 39 | nrfx_systick_delay_ms(100); 40 | return mp_const_none; 41 | } 42 | STATIC MP_DEFINE_CONST_FUN_OBJ_0(camera_wake_obj, camera_wake); 43 | 44 | STATIC const mp_rom_map_elem_t camera_module_globals_table[] = { 45 | 46 | {MP_ROM_QSTR(MP_QSTR_sleep), MP_ROM_PTR(&camera_sleep_obj)}, 47 | {MP_ROM_QSTR(MP_QSTR_wake), MP_ROM_PTR(&camera_wake_obj)}, 48 | }; 49 | STATIC MP_DEFINE_CONST_DICT(camera_module_globals, camera_module_globals_table); 50 | 51 | const mp_obj_module_t camera_module = { 52 | .base = {&mp_type_module}, 53 | .globals = (mp_obj_dict_t *)&camera_module_globals, 54 | }; 55 | MP_REGISTER_MODULE(MP_QSTR__camera, camera_module); 56 | -------------------------------------------------------------------------------- /modules/camera.py: -------------------------------------------------------------------------------- 1 | # 2 | # This file is part of the MicroPython for Monocle project: 3 | # https://github.com/brilliantlabsAR/monocle-micropython 4 | # 5 | # Authored by: Josuah Demangeon (me@josuah.net) 6 | # Raj Nakarja / Brilliant Labs Ltd. (raj@itsbrilliant.co) 7 | # 8 | # ISC Licence 9 | # 10 | # Copyright © 2023 Brilliant Labs Ltd. 11 | # 12 | # Permission to use, copy, modify, and/or distribute this software for any 13 | # purpose with or without fee is hereby granted, provided that the above 14 | # copyright notice and this permission notice appear in all copies. 15 | # 16 | # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 17 | # REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 18 | # AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 19 | # INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 20 | # LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 21 | # OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 22 | # PERFORMANCE OF THIS SOFTWARE. 23 | # 24 | 25 | import _camera 26 | import struct 27 | import fpga 28 | import time 29 | 30 | 31 | _image = fpga.read(0x0001, 4) 32 | _status = fpga.read(0x1000, 1)[0] & 0x10 33 | 34 | if _status != 16 or _image != b"Mncl": 35 | raise (NotImplementedError("camera driver not found on FPGA")) 36 | 37 | RGB = "RGB" 38 | JPEG = "JPEG" 39 | 40 | 41 | def capture(): 42 | _camera.wake() 43 | fpga.write(0x1003, b"") 44 | while fpga.read(0x1000, 1) == b"2": 45 | time.sleep_us(10) 46 | 47 | 48 | def read(bytes=254): 49 | if bytes > 254: 50 | raise ValueError("at most 254 bytes") 51 | 52 | avail = struct.unpack(">H", fpga.read(0x1006, 2))[0] 53 | 54 | if avail == 0: 55 | _camera.sleep() 56 | return None 57 | 58 | return fpga.read(0x1007, min(bytes, avail)) 59 | 60 | 61 | def output(x, y, mode): 62 | return NotImplemented 63 | 64 | 65 | def zoom(factor): 66 | return NotImplemented 67 | -------------------------------------------------------------------------------- /modules/device.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the MicroPython for Monocle project: 3 | * https://github.com/brilliantlabsAR/monocle-micropython 4 | * 5 | * Authored by: Josuah Demangeon (me@josuah.net) 6 | * Raj Nakarja / Brilliant Labs Ltd. (raj@itsbrilliant.co) 7 | * 8 | * ISC Licence 9 | * 10 | * Copyright © 2023 Brilliant Labs Ltd. 11 | * 12 | * Permission to use, copy, modify, and/or distribute this software for any 13 | * purpose with or without fee is hereby granted, provided that the above 14 | * copyright notice and this permission notice appear in all copies. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 17 | * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 18 | * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 19 | * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 20 | * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 21 | * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 22 | * PERFORMANCE OF THIS SOFTWARE. 23 | */ 24 | 25 | #include 26 | #include 27 | #include "monocle.h" 28 | #include "genhdr/mpversion.h" 29 | #include "py/mphal.h" 30 | #include "py/objstr.h" 31 | #include "py/runtime.h" 32 | #include "ble_gap.h" 33 | #include "nrfx_saadc.h" 34 | 35 | STATIC const MP_DEFINE_STR_OBJ(device_name_obj, "monocle"); 36 | 37 | STATIC const MP_DEFINE_STR_OBJ(device_version_obj, BUILD_VERSION); 38 | 39 | STATIC const MP_DEFINE_STR_OBJ(device_git_tag_obj, MICROPY_GIT_HASH); 40 | 41 | STATIC const MP_DEFINE_STR_OBJ( 42 | device_git_repo_obj, "https://github.com/brilliantlabsAR/monocle-micropython"); 43 | 44 | STATIC mp_obj_t device_mac_address(void) 45 | { 46 | ble_gap_addr_t addr; 47 | app_err(sd_ble_gap_addr_get(&addr)); 48 | 49 | char mac_addr_string[18]; 50 | sprintf(mac_addr_string, "%02x:%02x:%02x:%02x:%02x:%02x", 51 | addr.addr[0], addr.addr[1], addr.addr[2], 52 | addr.addr[3], addr.addr[4], addr.addr[5]); 53 | 54 | return mp_obj_new_str(mac_addr_string, 17); 55 | } 56 | MP_DEFINE_CONST_FUN_OBJ_0(device_mac_address_obj, device_mac_address); 57 | 58 | STATIC mp_obj_t device_battery_level(void) 59 | { 60 | nrf_saadc_value_t result; 61 | app_err(nrfx_saadc_simple_mode_set(1, 62 | NRF_SAADC_RESOLUTION_10BIT, 63 | NRF_SAADC_OVERSAMPLE_DISABLED, 64 | NULL)); 65 | app_err(nrfx_saadc_buffer_set(&result, 1)); 66 | 67 | app_err(nrfx_saadc_mode_trigger()); 68 | 69 | // V = (raw / 10bits) * Vref * (1/NRFgain) * AMUXgain 70 | float voltage = ((float)result / 1024.0f) * 0.6f * 2.0f * (4.5f / 1.25f); 71 | 72 | // Percentage is based on a polynomial. Details in tools/battery-model 73 | float percentage = roundf(-118.13699f * powf(voltage, 3.0f) + 74 | 1249.63556f * powf(voltage, 2.0f) - 75 | 4276.33059f * voltage + 76 | 4764.47488f); 77 | 78 | if (percentage < 0.0f) 79 | { 80 | percentage = 0.0f; 81 | } 82 | 83 | if (percentage > 100.0f) 84 | { 85 | percentage = 100.0f; 86 | } 87 | 88 | return mp_obj_new_int_from_uint((uint8_t)percentage); 89 | } 90 | STATIC MP_DEFINE_CONST_FUN_OBJ_0(device_battery_level_obj, device_battery_level); 91 | 92 | STATIC mp_obj_t device_reset(void) 93 | { 94 | // Never reset if not connected to prevent locking out the user 95 | if (!ble_are_tx_notifications_enabled(REPL_TX)) 96 | { 97 | return mp_const_none; 98 | } 99 | 100 | // Delay so the user can cancel a reset if this runs from main.py 101 | mp_printf(&mp_plat_print, "Resetting"); 102 | mp_hal_delay_ms(1000); 103 | mp_printf(&mp_plat_print, "."); 104 | mp_hal_delay_ms(1000); 105 | mp_printf(&mp_plat_print, "."); 106 | mp_hal_delay_ms(1000); 107 | 108 | // Clear the reset reasons 109 | NRF_POWER->RESETREAS = 0xF000F; 110 | 111 | NVIC_SystemReset(); 112 | } 113 | MP_DEFINE_CONST_FUN_OBJ_0(device_reset_obj, &device_reset); 114 | 115 | STATIC mp_obj_t device_reset_cause(void) 116 | { 117 | uint32_t reset_reason = NRF_POWER->RESETREAS; 118 | 119 | if (reset_reason & (POWER_RESETREAS_DOG_Msk | POWER_RESETREAS_LOCKUP_Msk)) 120 | { 121 | return MP_OBJ_NEW_QSTR(MP_QSTR_CRASHED); 122 | } 123 | 124 | if (reset_reason & POWER_RESETREAS_SREQ_Msk) 125 | { 126 | return MP_OBJ_NEW_QSTR(MP_QSTR_SOFTWARE_RESET); 127 | } 128 | 129 | // TODO this will never happen because of our logic 130 | return MP_OBJ_NEW_QSTR(MP_QSTR_POWERON); 131 | } 132 | STATIC MP_DEFINE_CONST_FUN_OBJ_0(device_reset_cause_obj, device_reset_cause); 133 | 134 | STATIC mp_obj_t device_prevent_sleep(size_t n_args, const mp_obj_t *args) 135 | { 136 | if (n_args == 0) 137 | { 138 | return mp_obj_new_bool(prevent_sleep_flag); 139 | } 140 | 141 | prevent_sleep_flag = mp_obj_is_true(args[0]); 142 | 143 | if (prevent_sleep_flag) 144 | { 145 | mp_printf(&mp_plat_print, 146 | "WARNING: Running monocle for prolonged periods may result in" 147 | " display burn in, as well as reduced lifetime of components." 148 | "\n"); 149 | } 150 | 151 | return mp_const_none; 152 | } 153 | STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(device_prevent_sleep_obj, 0, 1, device_prevent_sleep); 154 | 155 | STATIC mp_obj_t device_force_sleep(void) 156 | { 157 | // Never force sleep if not connected to prevent locking out the user 158 | if (!ble_are_tx_notifications_enabled(REPL_TX)) 159 | { 160 | return mp_const_none; 161 | } 162 | 163 | // Delay so the user can cancel force sleep if this runs from main.py 164 | mp_printf(&mp_plat_print, "Going to sleep"); 165 | mp_hal_delay_ms(1000); 166 | mp_printf(&mp_plat_print, "."); 167 | mp_hal_delay_ms(1000); 168 | mp_printf(&mp_plat_print, "."); 169 | mp_hal_delay_ms(1000); 170 | 171 | prevent_sleep_flag = false; 172 | 173 | force_sleep_flag = true; 174 | 175 | return mp_const_none; 176 | } 177 | STATIC MP_DEFINE_CONST_FUN_OBJ_0(device_force_sleep_obj, device_force_sleep); 178 | 179 | STATIC mp_obj_t device_is_charging(void) 180 | { 181 | // Get the CHG value from STAT_CHG_B 182 | i2c_response_t charging_response = monocle_i2c_read(PMIC_I2C_ADDRESS, 0x03, 0x0C); 183 | app_err(charging_response.fail); 184 | 185 | return charging_response.value ? mp_const_true : mp_const_false; 186 | } 187 | STATIC MP_DEFINE_CONST_FUN_OBJ_0(device_is_charging_obj, device_is_charging); 188 | 189 | extern const struct _mp_obj_type_t device_storage_type; 190 | 191 | STATIC const mp_rom_map_elem_t device_module_globals_table[] = { 192 | 193 | {MP_ROM_QSTR(MP_QSTR_NAME), MP_ROM_PTR(&device_name_obj)}, 194 | {MP_ROM_QSTR(MP_QSTR_mac_address), MP_ROM_PTR(&device_mac_address_obj)}, 195 | {MP_ROM_QSTR(MP_QSTR_VERSION), MP_ROM_PTR(&device_version_obj)}, 196 | {MP_ROM_QSTR(MP_QSTR_GIT_TAG), MP_ROM_PTR(&device_git_tag_obj)}, 197 | {MP_ROM_QSTR(MP_QSTR_GIT_REPO), MP_ROM_PTR(&device_git_repo_obj)}, 198 | {MP_ROM_QSTR(MP_QSTR_battery_level), MP_ROM_PTR(&device_battery_level_obj)}, 199 | {MP_ROM_QSTR(MP_QSTR_reset), MP_ROM_PTR(&device_reset_obj)}, 200 | {MP_ROM_QSTR(MP_QSTR_reset_cause), MP_ROM_PTR(&device_reset_cause_obj)}, 201 | {MP_ROM_QSTR(MP_QSTR_prevent_sleep), MP_ROM_PTR(&device_prevent_sleep_obj)}, 202 | {MP_ROM_QSTR(MP_QSTR_force_sleep), MP_ROM_PTR(&device_force_sleep_obj)}, 203 | {MP_ROM_QSTR(MP_QSTR_is_charging), MP_ROM_PTR(&device_is_charging_obj)}, 204 | {MP_ROM_QSTR(MP_QSTR_Storage), MP_ROM_PTR(&device_storage_type)}, 205 | }; 206 | STATIC MP_DEFINE_CONST_DICT(device_module_globals, device_module_globals_table); 207 | 208 | const mp_obj_module_t device_module = { 209 | .base = {&mp_type_module}, 210 | .globals = (mp_obj_dict_t *)&device_module_globals, 211 | }; 212 | 213 | MP_REGISTER_MODULE(MP_QSTR_device, device_module); 214 | -------------------------------------------------------------------------------- /modules/display.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the MicroPython for Monocle: 3 | * https://github.com/Itsbrilliantlabs/monocle-micropython 4 | * 5 | * Authored by: Josuah Demangeon 6 | * 7 | * ISC Licence 8 | * 9 | * Copyright © 2022 Brilliant Labs Ltd. 10 | * 11 | * Permission to use, copy, modify, and/or distribute this software for any 12 | * purpose with or without fee is hereby granted, provided that the above 13 | * copyright notice and this permission notice appear in all copies. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 16 | * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 17 | * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 18 | * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 19 | * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 20 | * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 21 | * PERFORMANCE OF THIS SOFTWARE. 22 | */ 23 | 24 | #include 25 | 26 | #include "py/obj.h" 27 | #include "py/runtime.h" 28 | #include "py/mperrno.h" 29 | 30 | STATIC mp_obj_t display_brightness(mp_obj_t brightness) 31 | { 32 | int tab[] = { 33 | 1, // DIM 750 cd/m2 34 | 2, // LOW 1250 cd/m2 35 | 0, // MEDIUM 2000 cd/m2, this is the default 36 | 3, // HIGH 3000 cd/m2 37 | 4, // BRIGHT 4000 cd/m2 38 | }; 39 | 40 | if (mp_obj_get_int(brightness) >= MP_ARRAY_SIZE(tab)) 41 | { 42 | mp_raise_ValueError(MP_ERROR_TEXT("brightness must be between 0 and 4")); 43 | } 44 | 45 | uint8_t level = tab[mp_obj_get_int(brightness)]; 46 | uint8_t command[2] = {0x05, 0xC8 | level}; 47 | monocle_spi_write(DISPLAY, command, 2, false); 48 | 49 | return mp_const_none; 50 | } 51 | STATIC MP_DEFINE_CONST_FUN_OBJ_1(display_brightness_obj, &display_brightness); 52 | 53 | STATIC const mp_rom_map_elem_t display_module_globals_table[] = { 54 | {MP_ROM_QSTR(MP_QSTR_brightness), MP_ROM_PTR(&display_brightness_obj)}, 55 | }; 56 | STATIC MP_DEFINE_CONST_DICT(display_module_globals, display_module_globals_table); 57 | 58 | const mp_obj_module_t display_module = { 59 | .base = {&mp_type_module}, 60 | .globals = (mp_obj_dict_t *)&display_module_globals, 61 | }; 62 | MP_REGISTER_MODULE(MP_QSTR__display, display_module); 63 | -------------------------------------------------------------------------------- /modules/fpga.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the MicroPython for Monocle project: 3 | * https://github.com/brilliantlabsAR/monocle-micropython 4 | * 5 | * Authored by: Josuah Demangeon (me@josuah.net) 6 | * Raj Nakarja / Brilliant Labs Ltd. (raj@itsbrilliant.co) 7 | * 8 | * ISC Licence 9 | * 10 | * Copyright © 2023 Brilliant Labs Ltd. 11 | * 12 | * Permission to use, copy, modify, and/or distribute this software for any 13 | * purpose with or without fee is hereby granted, provided that the above 14 | * copyright notice and this permission notice appear in all copies. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 17 | * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 18 | * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 19 | * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 20 | * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 21 | * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 22 | * PERFORMANCE OF THIS SOFTWARE. 23 | */ 24 | 25 | #include "monocle.h" 26 | #include "nrf_gpio.h" 27 | #include "py/runtime.h" 28 | #include 29 | 30 | static bool fpga_running_flag = true; 31 | 32 | STATIC mp_obj_t fpga_read(mp_obj_t addr_16bit, mp_obj_t n) 33 | { 34 | if (mp_obj_get_int(n) < 1 || mp_obj_get_int(n) > 255) 35 | { 36 | mp_raise_ValueError( 37 | MP_ERROR_TEXT("n must be between 1 and 255")); 38 | } 39 | 40 | uint16_t addr = mp_obj_get_int(addr_16bit); 41 | uint8_t addr_bytes[2] = {(uint8_t)(addr >> 8), (uint8_t)addr}; 42 | 43 | uint8_t *buffer = m_malloc(mp_obj_get_int(n)); 44 | 45 | monocle_spi_write(FPGA, addr_bytes, 2, true); 46 | monocle_spi_read(FPGA, buffer, mp_obj_get_int(n), false); 47 | 48 | mp_obj_t bytes = mp_obj_new_bytes(buffer, mp_obj_get_int(n)); 49 | 50 | m_free(buffer); 51 | 52 | return bytes; 53 | } 54 | STATIC MP_DEFINE_CONST_FUN_OBJ_2(fpga_read_obj, fpga_read); 55 | 56 | STATIC mp_obj_t fpga_write(mp_obj_t addr_16bit, mp_obj_t bytes) 57 | { 58 | mp_buffer_info_t buffer; 59 | mp_get_buffer_raise(bytes, &buffer, MP_BUFFER_READ); 60 | 61 | if (buffer.len > 255) 62 | { 63 | mp_raise_ValueError( 64 | MP_ERROR_TEXT("input buffer size must be less than 255 bytes")); 65 | } 66 | 67 | uint16_t addr = mp_obj_get_int(addr_16bit); 68 | uint8_t addr_bytes[2] = {(uint8_t)(addr >> 8), (uint8_t)addr}; 69 | 70 | if (buffer.len == 0) 71 | { 72 | monocle_spi_write(FPGA, addr_bytes, 2, false); 73 | } 74 | else 75 | { 76 | monocle_spi_write(FPGA, addr_bytes, 2, true); 77 | monocle_spi_write(FPGA, buffer.buf, buffer.len, false); 78 | } 79 | 80 | return mp_const_none; 81 | } 82 | STATIC MP_DEFINE_CONST_FUN_OBJ_2(fpga_write_obj, fpga_write); 83 | 84 | STATIC mp_obj_t fpga_run(size_t n_args, const mp_obj_t *args) 85 | { 86 | if (n_args == 0) 87 | { 88 | return mp_obj_new_bool(fpga_running_flag); 89 | } 90 | 91 | bool run = mp_obj_is_true(args[0]); 92 | 93 | if (run == fpga_running_flag) 94 | { 95 | return mp_const_none; 96 | } 97 | 98 | fpga_running_flag = run; 99 | 100 | monocle_fpga_reset(run); 101 | 102 | return mp_const_none; 103 | } 104 | STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(fpga_run_obj, 0, 1, fpga_run); 105 | 106 | STATIC const mp_rom_map_elem_t fpga_module_globals_table[] = { 107 | 108 | {MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&fpga_read_obj)}, 109 | {MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&fpga_write_obj)}, 110 | {MP_ROM_QSTR(MP_QSTR_run), MP_ROM_PTR(&fpga_run_obj)}, 111 | }; 112 | STATIC MP_DEFINE_CONST_DICT(fpga_module_globals, fpga_module_globals_table); 113 | 114 | const mp_obj_module_t fpga_module = { 115 | .base = {&mp_type_module}, 116 | .globals = (mp_obj_dict_t *)&fpga_module_globals, 117 | }; 118 | MP_REGISTER_MODULE(MP_QSTR_fpga, fpga_module); 119 | -------------------------------------------------------------------------------- /modules/frozen-manifest.py: -------------------------------------------------------------------------------- 1 | # 2 | # This file is part of the MicroPython for Monocle project: 3 | # https://github.com/brilliantlabsAR/monocle-micropython 4 | # 5 | # Authored by: Josuah Demangeon (me@josuah.net) 6 | # Raj Nakarja / Brilliant Labs Ltd. (raj@itsbrilliant.co) 7 | # 8 | # ISC Licence 9 | # 10 | # Copyright © 2023 Brilliant Labs Ltd. 11 | # 12 | # Permission to use, copy, modify, and/or distribute this software for any 13 | # purpose with or without fee is hereby granted, provided that the above 14 | # copyright notice and this permission notice appear in all copies. 15 | # 16 | # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 17 | # REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 18 | # AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 19 | # INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 20 | # LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 21 | # OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 22 | # PERFORMANCE OF THIS SOFTWARE. 23 | # 24 | 25 | module("_mountfs.py") 26 | module("_splashscreen.py") 27 | module("_test.py") 28 | module("camera.py") 29 | module("display.py") 30 | module("update.py") 31 | 32 | include("$(MPY_DIR)/extmod/asyncio/manifest.py") 33 | -------------------------------------------------------------------------------- /modules/led.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the MicroPython for Monocle project: 3 | * https://github.com/brilliantlabsAR/monocle-micropython 4 | * 5 | * Authored by: Josuah Demangeon (me@josuah.net) 6 | * Raj Nakarja / Brilliant Labs Ltd. (raj@itsbrilliant.co) 7 | * 8 | * ISC Licence 9 | * 10 | * Copyright © 2023 Brilliant Labs Ltd. 11 | * 12 | * Permission to use, copy, modify, and/or distribute this software for any 13 | * purpose with or without fee is hereby granted, provided that the above 14 | * copyright notice and this permission notice appear in all copies. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 17 | * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 18 | * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 19 | * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 20 | * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 21 | * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 22 | * PERFORMANCE OF THIS SOFTWARE. 23 | */ 24 | 25 | #include "py/mphal.h" 26 | #include "py/runtime.h" 27 | #include "monocle.h" 28 | 29 | enum 30 | { 31 | LED_RED, 32 | LED_GREEN 33 | }; 34 | 35 | static mp_obj_t led_on(mp_obj_t led_in) 36 | { 37 | qstr led = mp_obj_str_get_qstr(led_in); 38 | 39 | if ((led != MP_QSTR_RED) && 40 | (led != MP_QSTR_GREEN)) 41 | { 42 | mp_raise_ValueError( 43 | MP_ERROR_TEXT("must be led.RED or led.GREEN")); 44 | } 45 | 46 | // Unblocks i2c interrupts if led.on if called in an infinite loop 47 | mp_hal_delay_ms(10); 48 | 49 | if (led == MP_QSTR_RED) 50 | { 51 | monocle_set_led(RED_LED, true); 52 | return mp_const_none; 53 | } 54 | 55 | monocle_set_led(GREEN_LED, true); 56 | 57 | return mp_const_none; 58 | } 59 | STATIC MP_DEFINE_CONST_FUN_OBJ_1(led_on_obj, led_on); 60 | 61 | static mp_obj_t led_off(mp_obj_t led_in) 62 | { 63 | qstr led = mp_obj_str_get_qstr(led_in); 64 | 65 | if ((led != MP_QSTR_RED) && 66 | (led != MP_QSTR_GREEN)) 67 | { 68 | mp_raise_ValueError( 69 | MP_ERROR_TEXT("must be led.RED or led.GREEN")); 70 | } 71 | 72 | // Unblocks i2c interrupts if led.on if called in an infinite loop 73 | mp_hal_delay_ms(10); 74 | 75 | if (led == MP_QSTR_RED) 76 | { 77 | monocle_set_led(RED_LED, false); 78 | return mp_const_none; 79 | } 80 | 81 | monocle_set_led(GREEN_LED, false); 82 | 83 | return mp_const_none; 84 | } 85 | STATIC MP_DEFINE_CONST_FUN_OBJ_1(led_off_obj, led_off); 86 | 87 | STATIC const mp_rom_map_elem_t led_module_globals_table[] = { 88 | 89 | {MP_ROM_QSTR(MP_QSTR_on), MP_ROM_PTR(&led_on_obj)}, 90 | {MP_ROM_QSTR(MP_QSTR_off), MP_ROM_PTR(&led_off_obj)}, 91 | {MP_ROM_QSTR(MP_QSTR_RED), MP_ROM_QSTR(MP_QSTR_RED)}, 92 | {MP_ROM_QSTR(MP_QSTR_GREEN), MP_ROM_QSTR(MP_QSTR_GREEN)}, 93 | }; 94 | STATIC MP_DEFINE_CONST_DICT(led_module_globals, led_module_globals_table); 95 | 96 | const mp_obj_module_t led_module = { 97 | .base = {&mp_type_module}, 98 | .globals = (mp_obj_dict_t *)&led_module_globals, 99 | }; 100 | MP_REGISTER_MODULE(MP_QSTR_led, led_module); 101 | -------------------------------------------------------------------------------- /modules/microphone.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the MicroPython for Monocle project: 3 | * https://github.com/brilliantlabsAR/monocle-micropython 4 | * 5 | * Authored by: Josuah Demangeon (me@josuah.net) 6 | * Raj Nakarja / Brilliant Labs Ltd. (raj@itsbrilliant.co) 7 | * 8 | * ISC Licence 9 | * 10 | * Copyright © 2023 Brilliant Labs Ltd. 11 | * 12 | * Permission to use, copy, modify, and/or distribute this software for any 13 | * purpose with or without fee is hereby granted, provided that the above 14 | * copyright notice and this permission notice appear in all copies. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 17 | * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 18 | * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 19 | * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 20 | * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 21 | * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 22 | * PERFORMANCE OF THIS SOFTWARE. 23 | */ 24 | 25 | #include 26 | #include "monocle.h" 27 | #include "py/runtime.h" 28 | 29 | static uint8_t microphone_bit_depth = 16; 30 | 31 | static inline void microphone_fpga_read(uint16_t address, uint8_t *buffer, size_t length) 32 | { 33 | uint8_t address_bytes[2] = {(uint8_t)(address >> 8), (uint8_t)address}; 34 | 35 | monocle_spi_write(FPGA, address_bytes, 2, true); 36 | 37 | // Dump the data into a dummy buffer if a buffer isn't provided 38 | if (buffer == NULL) 39 | { 40 | uint8_t dummy_buffer[254]; 41 | monocle_spi_read(FPGA, dummy_buffer, length, false); 42 | return; 43 | } 44 | 45 | monocle_spi_read(FPGA, buffer, length, false); 46 | } 47 | 48 | static inline void microphone_fpga_write(uint16_t address, uint8_t *buffer, size_t length) 49 | { 50 | uint8_t address_bytes[2] = {(uint8_t)(address >> 8), (uint8_t)address}; 51 | 52 | if (buffer == NULL || length == 0) 53 | { 54 | monocle_spi_write(FPGA, address_bytes, 2, false); 55 | return; 56 | } 57 | 58 | monocle_spi_write(FPGA, address_bytes, 2, true); 59 | monocle_spi_write(FPGA, buffer, length, false); 60 | } 61 | 62 | static size_t microphone_bytes_available(void) 63 | { 64 | uint8_t available_bytes[2] = {0, 0}; 65 | microphone_fpga_read(0x5801, available_bytes, sizeof(available_bytes)); 66 | size_t available = (available_bytes[0] << 8 | available_bytes[1]) * 2; 67 | 68 | // Cap to 254 due to SPI DMA limit 69 | if (available > 254) 70 | { 71 | available = 254; 72 | } 73 | 74 | return available; 75 | } 76 | 77 | STATIC mp_obj_t microphone_init(void) 78 | { 79 | uint8_t fpga_image[4]; 80 | uint8_t module_status[2]; 81 | 82 | microphone_fpga_read(0x0001, fpga_image, sizeof(fpga_image)); 83 | microphone_fpga_read(0x5800, module_status, sizeof(module_status)); 84 | 85 | if (((module_status[0] & 0x10) != 16) || 86 | memcmp(fpga_image, "Mncl", sizeof(fpga_image))) 87 | { 88 | mp_raise_NotImplementedError( 89 | MP_ERROR_TEXT("microphone driver not found on FPGA")); 90 | } 91 | 92 | return mp_const_none; 93 | } 94 | STATIC MP_DEFINE_CONST_FUN_OBJ_0(microphone_init_obj, microphone_init); 95 | 96 | STATIC mp_obj_t microphone_record(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) 97 | { 98 | static const mp_arg_t allowed_args[] = { 99 | {MP_QSTR_sample_rate, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 16000}}, 100 | {MP_QSTR_bit_depth, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 16}}, 101 | {MP_QSTR_seconds, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NEW_SMALL_INT(5)}}}; 102 | 103 | mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; 104 | mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); 105 | 106 | // Flush existing data 107 | while (true) 108 | { 109 | size_t available = microphone_bytes_available(); 110 | 111 | if (available == 0) 112 | { 113 | break; 114 | } 115 | 116 | microphone_fpga_read(0x5807, NULL, available); 117 | } 118 | 119 | // Check the given sample rate 120 | mp_int_t sample_rate = args[0].u_int; 121 | 122 | if (sample_rate != 16000 && sample_rate != 8000) 123 | { 124 | mp_raise_ValueError( 125 | MP_ERROR_TEXT("sample rate must be either 16000 or 8000")); 126 | } 127 | 128 | // Check the currently set sample rate on the FPGA 129 | uint8_t status_byte; 130 | microphone_fpga_read(0x0800, &status_byte, sizeof(status_byte)); 131 | 132 | // Toggle the sample rate if required 133 | if (((status_byte & 0x04) == 0x00 && sample_rate == 8000) || 134 | ((status_byte & 0x04) == 0x04 && sample_rate == 16000)) 135 | { 136 | microphone_fpga_write(0x0808, NULL, 0); 137 | } 138 | 139 | // Check and set bit depth to the global variable 140 | mp_int_t bit_depth = args[1].u_int; 141 | if (bit_depth != 16 && bit_depth != 8) 142 | { 143 | mp_raise_ValueError( 144 | MP_ERROR_TEXT("bit depth must be either 16 or 8")); 145 | } 146 | microphone_bit_depth = bit_depth; 147 | 148 | // Set the block size and request a number of blocks corresponding to seconds 149 | float block_size; 150 | sample_rate == 16000 ? (block_size = 0.02) : (block_size = 0.04); 151 | 152 | uint16_t blocks = (uint16_t)(mp_obj_get_float(args[2].u_obj) / block_size); 153 | uint8_t blocks_bytes[] = {blocks >> 8, blocks}; 154 | microphone_fpga_write(0x0802, blocks_bytes, sizeof(blocks)); 155 | 156 | // Trigger capture 157 | microphone_fpga_write(0x0803, NULL, 0); 158 | 159 | return mp_const_none; 160 | } 161 | STATIC MP_DEFINE_CONST_FUN_OBJ_KW(microphone_record_obj, 0, microphone_record); 162 | 163 | STATIC mp_obj_t microphone_stop(void) 164 | { 165 | return mp_const_notimplemented; 166 | } 167 | STATIC MP_DEFINE_CONST_FUN_OBJ_0(microphone_stop_obj, microphone_stop); 168 | 169 | STATIC mp_obj_t microphone_read(mp_obj_t samples) 170 | { 171 | if (mp_obj_get_int(samples) > 127) 172 | { 173 | mp_raise_ValueError( 174 | MP_ERROR_TEXT("only 127 samples may be read at a time")); 175 | } 176 | 177 | size_t available = microphone_bytes_available(); 178 | 179 | if (available == 0) 180 | { 181 | return mp_const_none; 182 | } 183 | 184 | if (mp_obj_get_int(samples) * 2 < available) 185 | { 186 | available = mp_obj_get_int(samples) * 2; 187 | } 188 | 189 | uint8_t buffer[available]; 190 | microphone_fpga_read(0x5807, buffer, sizeof(buffer)); 191 | 192 | // If 16 bit data, return this buffer 193 | if (microphone_bit_depth == 16) 194 | { 195 | return mp_obj_new_bytes(buffer, sizeof(buffer)); 196 | } 197 | 198 | // Otherwise create a scaled version for 8 bit 199 | uint8_t small_buffer[sizeof(buffer) / 2]; 200 | for (size_t i = 0; i < sizeof(buffer) / 2; i++) 201 | { 202 | small_buffer[i] = buffer[i * 2]; 203 | } 204 | 205 | return mp_obj_new_bytes(small_buffer, sizeof(small_buffer)); 206 | } 207 | STATIC MP_DEFINE_CONST_FUN_OBJ_1(microphone_read_obj, microphone_read); 208 | 209 | STATIC const mp_rom_map_elem_t microphone_module_globals_table[] = { 210 | 211 | {MP_ROM_QSTR(MP_QSTR___init__), MP_ROM_PTR(µphone_init_obj)}, 212 | {MP_ROM_QSTR(MP_QSTR_record), MP_ROM_PTR(µphone_record_obj)}, 213 | {MP_ROM_QSTR(MP_QSTR_stop), MP_ROM_PTR(µphone_stop_obj)}, 214 | {MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(µphone_read_obj)}, 215 | }; 216 | STATIC MP_DEFINE_CONST_DICT(microphone_module_globals, microphone_module_globals_table); 217 | 218 | const mp_obj_module_t microphone_module = { 219 | .base = {&mp_type_module}, 220 | .globals = (mp_obj_dict_t *)µphone_module_globals, 221 | }; 222 | MP_REGISTER_MODULE(MP_QSTR_microphone, microphone_module); 223 | -------------------------------------------------------------------------------- /modules/modvgr2d-glue.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the MicroPython for Monocle project: 3 | * https://github.com/brilliantlabsAR/monocle-micropython 4 | * 5 | * Authored by: Josuah Demangeon (me@josuah.net) 6 | * Raj Nakarja / Brilliant Labs Ltd. (raj@itsbrilliant.co) 7 | * 8 | * ISC Licence 9 | * 10 | * Copyright © 2023 Brilliant Labs Ltd. 11 | * 12 | * Permission to use, copy, modify, and/or distribute this software for any 13 | * purpose with or without fee is hereby granted, provided that the above 14 | * copyright notice and this permission notice appear in all copies. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 17 | * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 18 | * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 19 | * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 20 | * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 21 | * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 22 | * PERFORMANCE OF THIS SOFTWARE. 23 | */ 24 | 25 | #include "monocle.h" 26 | 27 | uint8_t fpga_graphics_dev() 28 | { 29 | return 0x44; 30 | } 31 | 32 | void fpga_write_internal(uint8_t *buf, unsigned int len, bool hold) 33 | { 34 | monocle_spi_write(FPGA, buf, len, hold); 35 | } -------------------------------------------------------------------------------- /modules/rtt.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the MicroPython for Monocle project: 3 | * https://github.com/brilliantlabsAR/monocle-micropython 4 | * 5 | * Authored by: Josuah Demangeon (me@josuah.net) 6 | * Raj Nakarja / Brilliant Labs Ltd. (raj@itsbrilliant.co) 7 | * 8 | * ISC Licence 9 | * 10 | * Copyright © 2023 Brilliant Labs Ltd. 11 | * 12 | * Permission to use, copy, modify, and/or distribute this software for any 13 | * purpose with or without fee is hereby granted, provided that the above 14 | * copyright notice and this permission notice appear in all copies. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 17 | * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 18 | * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 19 | * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 20 | * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 21 | * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 22 | * PERFORMANCE OF THIS SOFTWARE. 23 | */ 24 | 25 | #include "monocle.h" 26 | #include "nrf_gpio.h" 27 | #include "nrfx_log.h" 28 | #include "py/runtime.h" 29 | #include "py/objstr.h" 30 | 31 | STATIC mp_obj_t rtt_print(mp_obj_t arg1) 32 | { 33 | const char *str = mp_obj_str_get_data(arg1, NULL); 34 | 35 | NRFX_LOG("%s", str); 36 | return mp_const_none; 37 | } 38 | STATIC MP_DEFINE_CONST_FUN_OBJ_1(rtt_print_obj, rtt_print); 39 | 40 | STATIC const mp_rom_map_elem_t rtt_module_globals_table[] = { 41 | {MP_ROM_QSTR(MP_QSTR_print), MP_ROM_PTR(&rtt_print_obj)}, 42 | }; 43 | STATIC MP_DEFINE_CONST_DICT(rtt_module_globals, rtt_module_globals_table); 44 | 45 | const mp_obj_module_t rtt_module = { 46 | .base = {&mp_type_module}, 47 | .globals = (mp_obj_dict_t *)&rtt_module_globals, 48 | }; 49 | MP_REGISTER_MODULE(MP_QSTR__rtt, rtt_module); 50 | -------------------------------------------------------------------------------- /modules/storage.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the MicroPython for Monocle project: 3 | * https://github.com/brilliantlabsAR/monocle-micropython 4 | * 5 | * Authored by: Josuah Demangeon (me@josuah.net) 6 | * Raj Nakarja / Brilliant Labs Ltd. (raj@itsbrilliant.co) 7 | * 8 | * ISC Licence 9 | * 10 | * Copyright © 2023 Brilliant Labs Ltd. 11 | * 12 | * Permission to use, copy, modify, and/or distribute this software for any 13 | * purpose with or without fee is hereby granted, provided that the above 14 | * copyright notice and this permission notice appear in all copies. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 17 | * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 18 | * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 19 | * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 20 | * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 21 | * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 22 | * PERFORMANCE OF THIS SOFTWARE. 23 | */ 24 | 25 | #include 26 | #include 27 | #include "monocle.h" 28 | #include "extmod/vfs.h" 29 | #include "py/mperrno.h" 30 | #include "py/mphal.h" 31 | #include "py/runtime.h" 32 | 33 | const struct _mp_obj_type_t device_storage_type; 34 | 35 | typedef struct _storage_obj_t 36 | { 37 | mp_obj_base_t base; 38 | uint32_t start; 39 | uint32_t len; 40 | } storage_obj_t; 41 | 42 | mp_obj_t storage_readblocks(size_t n_args, const mp_obj_t *args) 43 | { 44 | storage_obj_t *self = MP_OBJ_TO_PTR(args[0]); 45 | uint32_t block_num = mp_obj_get_int(args[1]); 46 | mp_obj_t buffer = args[2]; 47 | 48 | mp_buffer_info_t bufinfo; 49 | mp_get_buffer_raise(buffer, &bufinfo, MP_BUFFER_WRITE); 50 | 51 | mp_int_t address = self->start + (block_num * 4096); 52 | 53 | if (n_args == 4) 54 | { 55 | uint32_t offset = mp_obj_get_int(args[3]); 56 | address += offset; 57 | } 58 | 59 | monocle_flash_read(bufinfo.buf, address, bufinfo.len); 60 | 61 | return mp_const_none; 62 | } 63 | STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(storage_readblocks_obj, 3, 4, storage_readblocks); 64 | 65 | mp_obj_t storage_writeblocks(size_t n_args, const mp_obj_t *args) 66 | { 67 | storage_obj_t *self = MP_OBJ_TO_PTR(args[0]); 68 | uint32_t block_num = mp_obj_get_int(args[1]); 69 | mp_obj_t buffer = args[2]; 70 | 71 | mp_buffer_info_t bufinfo; 72 | mp_get_buffer_raise(buffer, &bufinfo, MP_BUFFER_WRITE); 73 | 74 | mp_int_t address = self->start + (block_num * 4096); 75 | 76 | if (n_args == 4) 77 | { 78 | uint32_t offset = mp_obj_get_int(args[3]); 79 | address += offset; 80 | } 81 | else 82 | { 83 | monocle_flash_page_erase(address); 84 | } 85 | 86 | monocle_flash_write(bufinfo.buf, address, bufinfo.len); 87 | 88 | return mp_const_none; 89 | } 90 | STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(storage_writeblocks_obj, 3, 4, storage_writeblocks); 91 | 92 | mp_obj_t storage_ioctl(mp_obj_t self_in, mp_obj_t op_in, mp_obj_t arg_in) 93 | { 94 | storage_obj_t *self = MP_OBJ_TO_PTR(self_in); 95 | 96 | mp_int_t op = mp_obj_get_int(op_in); 97 | switch (op) 98 | { 99 | case MP_BLOCKDEV_IOCTL_INIT: 100 | { 101 | return MP_OBJ_NEW_SMALL_INT(0); 102 | } 103 | 104 | case MP_BLOCKDEV_IOCTL_DEINIT: 105 | { 106 | return MP_OBJ_NEW_SMALL_INT(0); 107 | } 108 | 109 | case MP_BLOCKDEV_IOCTL_SYNC: 110 | { 111 | return MP_OBJ_NEW_SMALL_INT(0); 112 | } 113 | 114 | case MP_BLOCKDEV_IOCTL_BLOCK_COUNT: 115 | { 116 | return MP_OBJ_NEW_SMALL_INT(self->len / 4096); 117 | } 118 | 119 | case MP_BLOCKDEV_IOCTL_BLOCK_SIZE: 120 | { 121 | return MP_OBJ_NEW_SMALL_INT(4096); 122 | } 123 | 124 | case MP_BLOCKDEV_IOCTL_BLOCK_ERASE: 125 | { 126 | mp_int_t block_num = mp_obj_get_int(arg_in); 127 | mp_int_t address = self->start + (block_num * 4096); 128 | 129 | if ((address & 0x3) || (address % 4096 != 0)) 130 | { 131 | return MP_OBJ_NEW_SMALL_INT(-MP_EIO); 132 | } 133 | 134 | monocle_flash_page_erase(address); 135 | return MP_OBJ_NEW_SMALL_INT(0); 136 | } 137 | 138 | default: 139 | return mp_const_none; 140 | } 141 | } 142 | STATIC MP_DEFINE_CONST_FUN_OBJ_3(storage_ioctl_obj, storage_ioctl); 143 | 144 | STATIC const mp_rom_map_elem_t storage_locals_dict_table[] = { 145 | 146 | {MP_ROM_QSTR(MP_QSTR_readblocks), MP_ROM_PTR(&storage_readblocks_obj)}, 147 | {MP_ROM_QSTR(MP_QSTR_writeblocks), MP_ROM_PTR(&storage_writeblocks_obj)}, 148 | {MP_ROM_QSTR(MP_QSTR_ioctl), MP_ROM_PTR(&storage_ioctl_obj)}, 149 | }; 150 | STATIC MP_DEFINE_CONST_DICT(storage_locals_dict, storage_locals_dict_table); 151 | 152 | STATIC void storage_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) 153 | { 154 | storage_obj_t *self = MP_OBJ_TO_PTR(self_in); 155 | mp_printf(print, "Storage(start=0x%08x, len=%u)", self->start, self->len); 156 | } 157 | 158 | STATIC mp_obj_t storage_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) 159 | { 160 | static const mp_arg_t allowed_args[] = { 161 | {MP_QSTR_start, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0x6D000}}, 162 | {MP_QSTR_length, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0x93000}}, 163 | }; 164 | mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; 165 | mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); 166 | 167 | mp_int_t start = args[0].u_int; 168 | mp_int_t length = args[1].u_int; 169 | 170 | if (start < 0x6D000) 171 | { 172 | mp_raise_ValueError(MP_ERROR_TEXT( 173 | "start must be equal or higher than the FPGA bitstream end address of 0x6D000")); 174 | } 175 | 176 | if (length < 0) 177 | { 178 | mp_raise_ValueError(MP_ERROR_TEXT("length cannot be less than zero")); 179 | } 180 | 181 | if (length + start > 0x100000) 182 | { 183 | mp_raise_ValueError(MP_ERROR_TEXT("start + length must be less than 0x100000")); 184 | } 185 | 186 | storage_obj_t *self = mp_obj_malloc(storage_obj_t, &device_storage_type); 187 | self->start = start; 188 | self->len = length; 189 | return MP_OBJ_FROM_PTR(self); 190 | } 191 | 192 | MP_DEFINE_CONST_OBJ_TYPE( 193 | device_storage_type, 194 | MP_QSTR_Storage, 195 | MP_TYPE_FLAG_NONE, 196 | make_new, storage_make_new, 197 | print, storage_print, 198 | locals_dict, &storage_locals_dict); -------------------------------------------------------------------------------- /modules/time.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the MicroPython for Monocle project: 3 | * https://github.com/brilliantlabsAR/monocle-micropython 4 | * 5 | * Authored by: Josuah Demangeon (me@josuah.net) 6 | * Raj Nakarja / Brilliant Labs Ltd. (raj@itsbrilliant.co) 7 | * 8 | * ISC Licence 9 | * 10 | * Copyright © 2023 Brilliant Labs Ltd. 11 | * 12 | * Permission to use, copy, modify, and/or distribute this software for any 13 | * purpose with or without fee is hereby granted, provided that the above 14 | * copyright notice and this permission notice appear in all copies. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 17 | * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 18 | * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 19 | * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 20 | * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 21 | * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 22 | * PERFORMANCE OF THIS SOFTWARE. 23 | */ 24 | 25 | #include 26 | #include 27 | 28 | #include "py/runtime.h" 29 | #include "shared/timeutils/timeutils.h" 30 | #include "mphalport.h" 31 | 32 | uint64_t time_at_boot_s; 33 | static int8_t time_zone_hour_offset; 34 | static uint8_t time_zone_minute_offset; 35 | 36 | STATIC uint64_t _gettime(void) 37 | { 38 | return time_at_boot_s + mp_hal_ticks_ms() / 1000; 39 | } 40 | 41 | STATIC mp_obj_t time_zone(size_t n_args, const mp_obj_t *args) 42 | { 43 | if (n_args == 0) 44 | { 45 | char timezone_string[] = "+00:00"; 46 | snprintf(timezone_string, 47 | sizeof timezone_string, 48 | "%02d:%02u", 49 | time_zone_hour_offset, 50 | time_zone_minute_offset); 51 | 52 | return mp_obj_new_str(timezone_string, strlen(timezone_string)); 53 | } 54 | 55 | int hour = 0; 56 | int minute = 0; 57 | 58 | if (sscanf(mp_obj_str_get_str(args[0]), "%d:%d", &hour, &minute) != 2) 59 | { 60 | mp_raise_ValueError(MP_ERROR_TEXT("must be '+hh:mm' or '-hh:mm'")); 61 | } 62 | 63 | if (hour < -12.0 || hour > 14.0) 64 | { 65 | mp_raise_ValueError(MP_ERROR_TEXT("hour value must be between -12 and +14")); 66 | } 67 | 68 | if (minute != 0 && minute != 30 && minute != 45) 69 | { 70 | mp_raise_ValueError(MP_ERROR_TEXT("minute value must be either 00, 30, or 45")); 71 | } 72 | 73 | if ((hour == -12.0 || hour == 14.0) && minute != 0.0) 74 | { 75 | mp_raise_ValueError(MP_ERROR_TEXT("when hour is -12 or 14, minutes must be 0")); 76 | } 77 | 78 | time_zone_hour_offset = hour; 79 | time_zone_minute_offset = minute; 80 | 81 | return mp_const_none; 82 | } 83 | STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(time_zone_obj, 0, 1, time_zone); 84 | 85 | STATIC mp_obj_t time_now(size_t n_args, const mp_obj_t *args) 86 | { 87 | timeutils_struct_time_t tm; 88 | mp_int_t now; 89 | 90 | if (n_args == 0) 91 | { 92 | now = _gettime(); 93 | } 94 | else if (n_args == 1) 95 | { 96 | if (mp_obj_get_int(args[0]) < 0) 97 | { 98 | mp_raise_ValueError(MP_ERROR_TEXT("value given must be positive")); 99 | } 100 | now = mp_obj_get_int(args[0]); 101 | } 102 | 103 | now += time_zone_hour_offset * 3600; 104 | if (time_zone_hour_offset >= 0) 105 | { 106 | now += time_zone_minute_offset * 60; 107 | } 108 | else 109 | { 110 | now -= time_zone_minute_offset * 60; 111 | } 112 | 113 | timeutils_seconds_since_epoch_to_struct_time(now, &tm); 114 | 115 | mp_obj_dict_t *dict = mp_obj_new_dict(0); 116 | 117 | mp_obj_dict_store(dict, 118 | MP_ROM_QSTR(MP_QSTR_year), 119 | mp_obj_new_int(tm.tm_year)); 120 | 121 | mp_obj_dict_store(dict, 122 | MP_ROM_QSTR(MP_QSTR_year), 123 | mp_obj_new_int(tm.tm_year)); 124 | 125 | mp_obj_dict_store(dict, 126 | MP_ROM_QSTR(MP_QSTR_month), 127 | mp_obj_new_int(tm.tm_mon)); 128 | 129 | mp_obj_dict_store(dict, 130 | MP_ROM_QSTR(MP_QSTR_day), 131 | mp_obj_new_int(tm.tm_mday)); 132 | 133 | mp_obj_dict_store(dict, 134 | MP_ROM_QSTR(MP_QSTR_hour), 135 | mp_obj_new_int(tm.tm_hour)); 136 | 137 | mp_obj_dict_store(dict, 138 | MP_ROM_QSTR(MP_QSTR_minute), 139 | mp_obj_new_int(tm.tm_min)); 140 | 141 | mp_obj_dict_store(dict, 142 | MP_ROM_QSTR(MP_QSTR_second), 143 | mp_obj_new_int(tm.tm_sec)); 144 | 145 | qstr weekday; 146 | 147 | switch (tm.tm_wday) 148 | { 149 | case 0: 150 | weekday = MP_QSTR_monday; 151 | break; 152 | 153 | case 1: 154 | weekday = MP_QSTR_tuesday; 155 | break; 156 | 157 | case 2: 158 | weekday = MP_QSTR_wednesday; 159 | break; 160 | 161 | case 3: 162 | weekday = MP_QSTR_thursday; 163 | break; 164 | 165 | case 4: 166 | weekday = MP_QSTR_friday; 167 | break; 168 | 169 | case 5: 170 | weekday = MP_QSTR_saturday; 171 | break; 172 | 173 | case 6: 174 | weekday = MP_QSTR_sunday; 175 | break; 176 | 177 | default: 178 | weekday = MP_QSTR_; 179 | break; 180 | } 181 | 182 | mp_obj_dict_store(dict, 183 | MP_ROM_QSTR(MP_QSTR_weekday), 184 | MP_OBJ_NEW_QSTR(weekday)); 185 | 186 | mp_obj_dict_store(dict, 187 | MP_ROM_QSTR(MP_QSTR_yearday), 188 | mp_obj_new_int(tm.tm_yday)); 189 | 190 | char timezone_string[] = "+00:00"; 191 | snprintf(timezone_string, 192 | sizeof(timezone_string), 193 | "%02d:%02u", 194 | time_zone_hour_offset, 195 | time_zone_minute_offset); 196 | 197 | mp_obj_dict_store(dict, 198 | MP_ROM_QSTR(MP_QSTR_timezone), 199 | mp_obj_new_str(timezone_string, strlen(timezone_string))); 200 | 201 | return MP_OBJ_FROM_PTR(dict); 202 | } 203 | STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(time_now_obj, 0, 1, time_now); 204 | 205 | STATIC mp_obj_t time_time(size_t n_args, const mp_obj_t *args) 206 | { 207 | if (n_args == 0) 208 | { 209 | return mp_obj_new_int(_gettime()); 210 | } 211 | 212 | mp_int_t now_s = mp_obj_get_int(args[0]); 213 | mp_int_t uptime_s = mp_hal_ticks_ms() / 1000; 214 | 215 | if (now_s < uptime_s) 216 | { 217 | mp_raise_ValueError(MP_ERROR_TEXT("value given must be positive")); 218 | } 219 | time_at_boot_s = now_s - uptime_s; 220 | 221 | return mp_const_none; 222 | } 223 | STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(time_time_obj, 0, 1, time_time); 224 | 225 | STATIC mp_obj_t time_mktime(mp_obj_t dict) 226 | { 227 | mp_int_t year, mon, mday, hour, min, sec; 228 | 229 | if (!mp_obj_is_type(dict, &mp_type_dict)) 230 | { 231 | mp_raise_TypeError(MP_ERROR_TEXT("argument must be a dict")); 232 | } 233 | 234 | year = mp_obj_get_int(mp_obj_dict_get(dict, MP_ROM_QSTR(MP_QSTR_year))); 235 | mon = mp_obj_get_int(mp_obj_dict_get(dict, MP_ROM_QSTR(MP_QSTR_month))); 236 | mday = mp_obj_get_int(mp_obj_dict_get(dict, MP_ROM_QSTR(MP_QSTR_day))); 237 | hour = mp_obj_get_int(mp_obj_dict_get(dict, MP_ROM_QSTR(MP_QSTR_hour))); 238 | min = mp_obj_get_int(mp_obj_dict_get(dict, MP_ROM_QSTR(MP_QSTR_minute))); 239 | sec = mp_obj_get_int(mp_obj_dict_get(dict, MP_ROM_QSTR(MP_QSTR_second))); 240 | 241 | return mp_obj_new_int(timeutils_mktime(year, mon, mday, hour, min, sec)); 242 | } 243 | STATIC MP_DEFINE_CONST_FUN_OBJ_1(time_mktime_obj, time_mktime); 244 | 245 | #define MICROPY_PY_TIME_EXTRA_GLOBALS \ 246 | {MP_ROM_QSTR(MP_QSTR_time), MP_ROM_PTR(&time_time_obj)}, \ 247 | {MP_ROM_QSTR(MP_QSTR_now), MP_ROM_PTR(&time_now_obj)}, \ 248 | {MP_ROM_QSTR(MP_QSTR_zone), MP_ROM_PTR(&time_zone_obj)}, \ 249 | {MP_ROM_QSTR(MP_QSTR_mktime), MP_ROM_PTR(&time_mktime_obj)}, 250 | -------------------------------------------------------------------------------- /modules/touch.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the MicroPython for Monocle project: 3 | * https://github.com/brilliantlabsAR/monocle-micropython 4 | * 5 | * Authored by: Josuah Demangeon (me@josuah.net) 6 | * Raj Nakarja / Brilliant Labs Ltd. (raj@itsbrilliant.co) 7 | * 8 | * ISC Licence 9 | * 10 | * Copyright © 2023 Brilliant Labs Ltd. 11 | * 12 | * Permission to use, copy, modify, and/or distribute this software for any 13 | * purpose with or without fee is hereby granted, provided that the above 14 | * copyright notice and this permission notice appear in all copies. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 17 | * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 18 | * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 19 | * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 20 | * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 21 | * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 22 | * PERFORMANCE OF THIS SOFTWARE. 23 | */ 24 | 25 | #include "monocle.h" 26 | #include "touch.h" 27 | #include "py/runtime.h" 28 | #include "py/qstr.h" 29 | 30 | static mp_obj_t touch_a_callback = mp_const_none; 31 | static mp_obj_t touch_b_callback = mp_const_none; 32 | static mp_obj_t touch_both_callback = mp_const_none; 33 | static mp_obj_t touch_either_callback = mp_const_none; 34 | 35 | void touch_event_handler(touch_button_t action) 36 | { 37 | switch (action) 38 | { 39 | case TOUCH_A: 40 | if (touch_either_callback != mp_const_none) 41 | { 42 | mp_sched_schedule(touch_either_callback, MP_ROM_QSTR(MP_QSTR_A)); 43 | } 44 | else if (touch_a_callback != mp_const_none) 45 | { 46 | mp_sched_schedule(touch_a_callback, MP_ROM_QSTR(MP_QSTR_A)); 47 | } 48 | break; 49 | 50 | case TOUCH_B: 51 | if (touch_either_callback != mp_const_none) 52 | { 53 | mp_sched_schedule(touch_either_callback, MP_ROM_QSTR(MP_QSTR_B)); 54 | } 55 | else if (touch_b_callback != mp_const_none) 56 | { 57 | mp_sched_schedule(touch_b_callback, MP_ROM_QSTR(MP_QSTR_B)); 58 | } 59 | break; 60 | 61 | case TOUCH_BOTH: 62 | if (touch_both_callback != mp_const_none) 63 | { 64 | mp_sched_schedule(touch_both_callback, MP_ROM_QSTR(MP_QSTR_BOTH)); 65 | } 66 | break; 67 | 68 | default: 69 | break; 70 | } 71 | } 72 | 73 | STATIC mp_obj_t touch_state(size_t n_args, const mp_obj_t *args) 74 | { 75 | touch_button_t action = touch_get_state(); 76 | 77 | if (n_args == 0) 78 | { 79 | switch (action) 80 | { 81 | case TOUCH_A: 82 | return MP_OBJ_NEW_QSTR(MP_QSTR_A); 83 | case TOUCH_B: 84 | return MP_OBJ_NEW_QSTR(MP_QSTR_B); 85 | case TOUCH_BOTH: 86 | return MP_OBJ_NEW_QSTR(MP_QSTR_BOTH); 87 | default: 88 | return mp_const_none; 89 | } 90 | } 91 | 92 | qstr button = mp_obj_str_get_qstr(args[0]); 93 | 94 | if ((button != MP_QSTR_A) && 95 | (button != MP_QSTR_B) && 96 | (button != MP_QSTR_EITHER) && 97 | (button != MP_QSTR_BOTH)) 98 | { 99 | mp_raise_ValueError( 100 | MP_ERROR_TEXT("must be touch.A, touch.B, touch.BOTH, touch.EITHER")); 101 | } 102 | 103 | if (button == MP_QSTR_A && action == TOUCH_A) 104 | { 105 | return mp_const_true; 106 | } 107 | 108 | if (button == MP_QSTR_B && action == TOUCH_B) 109 | { 110 | return mp_const_true; 111 | } 112 | 113 | if (button == MP_QSTR_BOTH && action == TOUCH_BOTH) 114 | { 115 | return mp_const_true; 116 | } 117 | 118 | if (button == MP_QSTR_EITHER && (action == TOUCH_A || action == TOUCH_B)) 119 | { 120 | return mp_const_true; 121 | } 122 | 123 | return mp_const_false; 124 | } 125 | STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(touch_state_obj, 0, 1, touch_state); 126 | 127 | STATIC mp_obj_t touch_callback(size_t n_args, const mp_obj_t *args) 128 | { 129 | qstr button = mp_obj_str_get_qstr(args[0]); 130 | 131 | if ((button != MP_QSTR_A) && 132 | (button != MP_QSTR_B) && 133 | (button != MP_QSTR_BOTH) && 134 | (button != MP_QSTR_EITHER)) 135 | { 136 | mp_raise_ValueError( 137 | MP_ERROR_TEXT("must be touch.A, touch.B, touch.BOTH, touch.EITHER")); 138 | } 139 | 140 | if (n_args == 1) 141 | { 142 | if (button == MP_QSTR_A) 143 | { 144 | return touch_a_callback; 145 | } 146 | if (button == MP_QSTR_B) 147 | { 148 | return touch_b_callback; 149 | } 150 | if (button == MP_QSTR_BOTH) 151 | { 152 | return touch_both_callback; 153 | } 154 | if (button == MP_QSTR_EITHER) 155 | { 156 | return touch_either_callback; 157 | } 158 | } 159 | 160 | mp_obj_t callback = args[1]; 161 | 162 | if (!mp_obj_is_callable(callback) && (callback != mp_const_none)) 163 | { 164 | mp_raise_ValueError( 165 | MP_ERROR_TEXT("callback must be None or a callable object")); 166 | } 167 | 168 | switch (button) 169 | { 170 | case MP_QSTR_A: 171 | touch_a_callback = callback; 172 | break; 173 | 174 | case MP_QSTR_B: 175 | touch_b_callback = callback; 176 | break; 177 | 178 | case MP_QSTR_BOTH: 179 | touch_both_callback = callback; 180 | break; 181 | 182 | case MP_QSTR_EITHER: 183 | touch_either_callback = callback; 184 | break; 185 | 186 | default: 187 | break; 188 | } 189 | 190 | return mp_const_none; 191 | } 192 | STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(touch_callback_obj, 1, 2, touch_callback); 193 | 194 | STATIC const mp_rom_map_elem_t touch_module_globals_table[] = { 195 | 196 | {MP_ROM_QSTR(MP_QSTR_state), MP_ROM_PTR(&touch_state_obj)}, 197 | {MP_ROM_QSTR(MP_QSTR_callback), MP_ROM_PTR(&touch_callback_obj)}, 198 | 199 | {MP_ROM_QSTR(MP_QSTR_A), MP_ROM_QSTR(MP_QSTR_A)}, 200 | {MP_ROM_QSTR(MP_QSTR_B), MP_ROM_QSTR(MP_QSTR_B)}, 201 | {MP_ROM_QSTR(MP_QSTR_BOTH), MP_ROM_QSTR(MP_QSTR_BOTH)}, 202 | {MP_ROM_QSTR(MP_QSTR_EITHER), MP_ROM_QSTR(MP_QSTR_EITHER)}, 203 | }; 204 | STATIC MP_DEFINE_CONST_DICT(touch_module_globals, touch_module_globals_table); 205 | 206 | const mp_obj_module_t touch_module = { 207 | .base = {&mp_type_module}, 208 | .globals = (mp_obj_dict_t *)&touch_module_globals, 209 | }; 210 | MP_REGISTER_MODULE(MP_QSTR_touch, touch_module); 211 | -------------------------------------------------------------------------------- /modules/touch.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the MicroPython for Monocle project: 3 | * https://github.com/brilliantlabsAR/monocle-micropython 4 | * 5 | * Authored by: Josuah Demangeon (me@josuah.net) 6 | * Raj Nakarja / Brilliant Labs Ltd. (raj@itsbrilliant.co) 7 | * 8 | * ISC Licence 9 | * 10 | * Copyright © 2023 Brilliant Labs Ltd. 11 | * 12 | * Permission to use, copy, modify, and/or distribute this software for any 13 | * purpose with or without fee is hereby granted, provided that the above 14 | * copyright notice and this permission notice appear in all copies. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 17 | * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 18 | * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 19 | * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 20 | * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 21 | * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 22 | * PERFORMANCE OF THIS SOFTWARE. 23 | */ 24 | 25 | #pragma once 26 | 27 | typedef enum touch_button_t 28 | { 29 | TOUCH_NONE, 30 | TOUCH_A, 31 | TOUCH_B, 32 | TOUCH_BOTH, 33 | TOUCH_EITHER, 34 | } touch_button_t; 35 | 36 | void touch_event_handler(touch_button_t action); -------------------------------------------------------------------------------- /modules/update.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the MicroPython for Monocle project: 3 | * https://github.com/brilliantlabsAR/monocle-micropython 4 | * 5 | * Authored by: Josuah Demangeon (me@josuah.net) 6 | * Raj Nakarja / Brilliant Labs Ltd. (raj@itsbrilliant.co) 7 | * 8 | * ISC Licence 9 | * 10 | * Copyright © 2023 Brilliant Labs Ltd. 11 | * 12 | * Permission to use, copy, modify, and/or distribute this software for any 13 | * purpose with or without fee is hereby granted, provided that the above 14 | * copyright notice and this permission notice appear in all copies. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 17 | * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 18 | * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 19 | * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 20 | * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 21 | * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 22 | * PERFORMANCE OF THIS SOFTWARE. 23 | */ 24 | 25 | #include "monocle.h" 26 | #include "py/runtime.h" 27 | 28 | STATIC mp_obj_t update_nrf52(void) 29 | { 30 | monocle_enter_bootloader(); 31 | 32 | return mp_const_none; 33 | } 34 | STATIC MP_DEFINE_CONST_FUN_OBJ_0(update_nrf52_obj, update_nrf52); 35 | 36 | static mp_obj_t update_connected(void) 37 | { 38 | return ble_are_tx_notifications_enabled(REPL_TX) 39 | ? mp_const_true 40 | : mp_const_false; 41 | } 42 | STATIC MP_DEFINE_CONST_FUN_OBJ_0(update_connected_obj, update_connected); 43 | 44 | const struct _mp_obj_type_t fpga_app_type; 45 | 46 | static size_t fpga_app_programmed_bytes = 0; 47 | 48 | STATIC mp_obj_t update_fpga_app_read(mp_obj_t address, mp_obj_t length) 49 | { 50 | if (mp_obj_get_int(address) + mp_obj_get_int(length) > 0x6C80E + 4) 51 | { 52 | mp_raise_ValueError( 53 | MP_ERROR_TEXT("address + length cannot exceed 444434 bytes")); 54 | } 55 | 56 | uint8_t buffer[mp_obj_get_int(length)]; 57 | 58 | monocle_flash_read(buffer, mp_obj_get_int(address), mp_obj_get_int(length)); 59 | 60 | return mp_obj_new_bytes(buffer, mp_obj_get_int(length)); 61 | } 62 | STATIC MP_DEFINE_CONST_FUN_OBJ_2(update_read_fpga_app_obj, update_fpga_app_read); 63 | 64 | STATIC mp_obj_t update_fpga_app_write(mp_obj_t bytes) 65 | { 66 | size_t length; 67 | const char *data = mp_obj_str_get_data(bytes, &length); 68 | 69 | if (fpga_app_programmed_bytes + length > 0x6C80E + 4) 70 | { 71 | mp_raise_ValueError( 72 | MP_ERROR_TEXT("data will overflow the space reserved for the app")); 73 | } 74 | 75 | monocle_flash_write((uint8_t *)data, fpga_app_programmed_bytes, length); 76 | 77 | fpga_app_programmed_bytes += length; 78 | 79 | return mp_const_none; 80 | } 81 | STATIC MP_DEFINE_CONST_FUN_OBJ_1(update_write_fpga_app_obj, update_fpga_app_write); 82 | 83 | STATIC mp_obj_t update_fpga_app_delete(void) 84 | { 85 | for (size_t i = 0; i < 0x6D; i++) 86 | { 87 | monocle_flash_page_erase(i * 0x1000); 88 | } 89 | 90 | fpga_app_programmed_bytes = 0; 91 | 92 | return mp_const_none; 93 | } 94 | STATIC MP_DEFINE_CONST_FUN_OBJ_0(update_erase_fpga_app_obj, update_fpga_app_delete); 95 | 96 | STATIC const mp_rom_map_elem_t update_module_globals_table[] = { 97 | 98 | {MP_ROM_QSTR(MP_QSTR_nrf52), MP_ROM_PTR(&update_nrf52_obj)}, 99 | {MP_ROM_QSTR(MP_QSTR_connected), MP_ROM_PTR(&update_connected_obj)}, 100 | {MP_ROM_QSTR(MP_QSTR_read_fpga_app), MP_ROM_PTR(&update_read_fpga_app_obj)}, 101 | {MP_ROM_QSTR(MP_QSTR_write_fpga_app), MP_ROM_PTR(&update_write_fpga_app_obj)}, 102 | {MP_ROM_QSTR(MP_QSTR_erase_fpga_app), MP_ROM_PTR(&update_erase_fpga_app_obj)}, 103 | }; 104 | STATIC MP_DEFINE_CONST_DICT(update_module_globals, update_module_globals_table); 105 | 106 | const mp_obj_module_t update_module = { 107 | .base = {&mp_type_module}, 108 | .globals = (mp_obj_dict_t *)&update_module_globals, 109 | }; 110 | MP_REGISTER_MODULE(MP_QSTR__update, update_module); -------------------------------------------------------------------------------- /modules/update.py: -------------------------------------------------------------------------------- 1 | # 2 | # This file is part of the MicroPython for Monocle project: 3 | # https://github.com/brilliantlabsAR/monocle-micropython 4 | # 5 | # Authored by: Josuah Demangeon (me@josuah.net) 6 | # Raj Nakarja / Brilliant Labs Ltd. (raj@itsbrilliant.co) 7 | # 8 | # ISC Licence 9 | # 10 | # Copyright © 2023 Brilliant Labs Ltd. 11 | # 12 | # Permission to use, copy, modify, and/or distribute this software for any 13 | # purpose with or without fee is hereby granted, provided that the above 14 | # copyright notice and this permission notice appear in all copies. 15 | # 16 | # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 17 | # REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 18 | # AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 19 | # INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 20 | # LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 21 | # OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 22 | # PERFORMANCE OF THIS SOFTWARE. 23 | # 24 | 25 | import _update as __update 26 | import time as __time 27 | 28 | 29 | def micropython(): 30 | if __update.connected() == False: 31 | return 32 | 33 | print("Monocle will reset if not updated within 5 minutes.\n") 34 | print("If an update fails, simply connect to DFUTarg again.\n") 35 | print("Monocle will now enter update mode") 36 | __time.sleep(1) 37 | print("\b.") 38 | __time.sleep(1) 39 | print("\b.") 40 | __time.sleep(1) 41 | print("\b.") 42 | __update.nrf52() 43 | 44 | 45 | class Fpga: 46 | def read(address, length): 47 | return __update.read_fpga_app(address, length) 48 | 49 | def write(data): 50 | return __update.write_fpga_app(data) 51 | 52 | def erase(): 53 | return __update.erase_fpga_app() 54 | -------------------------------------------------------------------------------- /monocle-core/monocle-startup.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the MicroPython for Monocle project: 3 | * https://github.com/brilliantlabsAR/monocle-micropython 4 | * 5 | * Authored by: Josuah Demangeon (me@josuah.net) 6 | * Raj Nakarja / Brilliant Labs Ltd. (raj@itsbrilliant.co) 7 | * 8 | * ISC Licence 9 | * 10 | * Copyright © 2023 Brilliant Labs Ltd. 11 | * 12 | * Permission to use, copy, modify, and/or distribute this software for any 13 | * purpose with or without fee is hereby granted, provided that the above 14 | * copyright notice and this permission notice appear in all copies. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 17 | * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 18 | * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 19 | * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 20 | * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 21 | * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 22 | * PERFORMANCE OF THIS SOFTWARE. 23 | */ 24 | 25 | #include "monocle.h" 26 | 27 | extern uint32_t _stack_top; 28 | extern uint32_t _sidata; 29 | extern uint32_t _sdata; 30 | extern uint32_t _edata; 31 | extern uint32_t _sbss; 32 | extern uint32_t _ebss; 33 | 34 | typedef void (*func)(void); 35 | extern void main(void) __attribute__((noreturn)); 36 | extern void SystemInit(void); 37 | 38 | void Default_Handler(void) 39 | { 40 | app_err(0xDEAD0000); 41 | } 42 | 43 | void HardFault_Handler(void) 44 | { 45 | app_err(0xDEAD0001); 46 | } 47 | 48 | void BusFault_Handler(void) 49 | { 50 | app_err(0xDEAD0002); 51 | } 52 | 53 | void UsageFault_Handler(void) 54 | { 55 | app_err(0xDEAD0003); 56 | } 57 | 58 | void Reset_Handler(void) 59 | { 60 | // Initialise the RAM 61 | uint32_t *p_src = &_sidata; 62 | uint32_t *p_dest = &_sdata; 63 | 64 | while (p_dest < &_edata) 65 | { 66 | *p_dest++ = *p_src++; 67 | } 68 | 69 | uint32_t *p_bss = &_sbss; 70 | uint32_t *p_bss_end = &_ebss; 71 | while (p_bss < p_bss_end) 72 | { 73 | *p_bss++ = 0ul; 74 | } 75 | 76 | // Set up chip level errata fixes from Nordic 77 | SystemInit(); 78 | 79 | main(); 80 | } 81 | 82 | /** 83 | * @brief Specific handlers and interrupt vector table for the nRF52832 84 | */ 85 | 86 | void NMI_Handler(void) __attribute__((weak, alias("Default_Handler"))); 87 | void MemoryManagement_Handler(void) __attribute__((weak, alias("Default_Handler"))); 88 | void SVC_Handler(void) __attribute__((weak, alias("Default_Handler"))); 89 | void DebugMon_Handler(void) __attribute__((weak, alias("Default_Handler"))); 90 | void PendSV_Handler(void) __attribute__((weak, alias("Default_Handler"))); 91 | void SysTick_Handler(void) __attribute__((weak, alias("Default_Handler"))); 92 | void POWER_CLOCK_IRQHandler(void) __attribute__((weak, alias("Default_Handler"))); 93 | void RADIO_IRQHandler(void) __attribute__((weak, alias("Default_Handler"))); 94 | void UARTE0_UART0_IRQHandler(void) __attribute__((weak, alias("Default_Handler"))); 95 | void SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0_IRQHandler(void) __attribute__((weak, alias("Default_Handler"))); 96 | void SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1_IRQHandler(void) __attribute__((weak, alias("Default_Handler"))); 97 | void NFCT_IRQHandler(void) __attribute__((weak, alias("Default_Handler"))); 98 | void GPIOTE_IRQHandler(void) __attribute__((weak, alias("Default_Handler"))); 99 | void SAADC_IRQHandler(void) __attribute__((weak, alias("Default_Handler"))); 100 | void TIMER0_IRQHandler(void) __attribute__((weak, alias("Default_Handler"))); 101 | void TIMER1_IRQHandler(void) __attribute__((weak, alias("Default_Handler"))); 102 | void TIMER2_IRQHandler(void) __attribute__((weak, alias("Default_Handler"))); 103 | void RTC0_IRQHandler(void) __attribute__((weak, alias("Default_Handler"))); 104 | void TEMP_IRQHandler(void) __attribute__((weak, alias("Default_Handler"))); 105 | void RNG_IRQHandler(void) __attribute__((weak, alias("Default_Handler"))); 106 | void ECB_IRQHandler(void) __attribute__((weak, alias("Default_Handler"))); 107 | void CCM_AAR_IRQHandler(void) __attribute__((weak, alias("Default_Handler"))); 108 | void WDT_IRQHandler(void) __attribute__((weak, alias("Default_Handler"))); 109 | void RTC1_IRQHandler(void) __attribute__((weak, alias("Default_Handler"))); 110 | void QDEC_IRQHandler(void) __attribute__((weak, alias("Default_Handler"))); 111 | void COMP_LPCOMP_IRQHandler(void) __attribute__((weak, alias("Default_Handler"))); 112 | void SWI0_EGU0_IRQHandler(void) __attribute__((weak, alias("Default_Handler"))); 113 | void SWI1_EGU1_IRQHandler(void) __attribute__((weak, alias("Default_Handler"))); 114 | void SWI2_EGU2_IRQHandler(void) __attribute__((weak, alias("Default_Handler"))); 115 | void SWI3_EGU3_IRQHandler(void) __attribute__((weak, alias("Default_Handler"))); 116 | void SWI4_EGU4_IRQHandler(void) __attribute__((weak, alias("Default_Handler"))); 117 | void SWI5_EGU5_IRQHandler(void) __attribute__((weak, alias("Default_Handler"))); 118 | void TIMER3_IRQHandler(void) __attribute__((weak, alias("Default_Handler"))); 119 | void TIMER4_IRQHandler(void) __attribute__((weak, alias("Default_Handler"))); 120 | void PWM0_IRQHandler(void) __attribute__((weak, alias("Default_Handler"))); 121 | void PDM_IRQHandler(void) __attribute__((weak, alias("Default_Handler"))); 122 | void MWU_IRQHandler(void) __attribute__((weak, alias("Default_Handler"))); 123 | void PWM1_IRQHandler(void) __attribute__((weak, alias("Default_Handler"))); 124 | void PWM2_IRQHandler(void) __attribute__((weak, alias("Default_Handler"))); 125 | void SPIM2_SPIS2_SPI2_IRQHandler(void) __attribute__((weak, alias("Default_Handler"))); 126 | void RTC2_IRQHandler(void) __attribute__((weak, alias("Default_Handler"))); 127 | void I2S_IRQHandler(void) __attribute__((weak, alias("Default_Handler"))); 128 | void FPU_IRQHandler(void) __attribute__((weak, alias("Default_Handler"))); 129 | 130 | const func __Vectors[] __attribute__((section(".isr_vector"), used)) = { 131 | (func)&_stack_top, 132 | Reset_Handler, 133 | NMI_Handler, 134 | HardFault_Handler, 135 | MemoryManagement_Handler, 136 | BusFault_Handler, 137 | UsageFault_Handler, 138 | 0, 139 | 0, 140 | 0, 141 | 0, 142 | SVC_Handler, 143 | DebugMon_Handler, 144 | 0, 145 | PendSV_Handler, 146 | SysTick_Handler, 147 | 148 | /* External Interrupts */ 149 | POWER_CLOCK_IRQHandler, 150 | RADIO_IRQHandler, 151 | UARTE0_UART0_IRQHandler, 152 | SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0_IRQHandler, 153 | SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1_IRQHandler, 154 | NFCT_IRQHandler, 155 | GPIOTE_IRQHandler, 156 | SAADC_IRQHandler, 157 | TIMER0_IRQHandler, 158 | TIMER1_IRQHandler, 159 | TIMER2_IRQHandler, 160 | RTC0_IRQHandler, 161 | TEMP_IRQHandler, 162 | RNG_IRQHandler, 163 | ECB_IRQHandler, 164 | CCM_AAR_IRQHandler, 165 | WDT_IRQHandler, 166 | RTC1_IRQHandler, 167 | QDEC_IRQHandler, 168 | COMP_LPCOMP_IRQHandler, 169 | SWI0_EGU0_IRQHandler, 170 | SWI1_EGU1_IRQHandler, 171 | SWI2_EGU2_IRQHandler, 172 | SWI3_EGU3_IRQHandler, 173 | SWI4_EGU4_IRQHandler, 174 | SWI5_EGU5_IRQHandler, 175 | TIMER3_IRQHandler, 176 | TIMER4_IRQHandler, 177 | PWM0_IRQHandler, 178 | PDM_IRQHandler, 179 | 0, 180 | 0, 181 | MWU_IRQHandler, 182 | PWM1_IRQHandler, 183 | PWM2_IRQHandler, 184 | SPIM2_SPIS2_SPI2_IRQHandler, 185 | RTC2_IRQHandler, 186 | I2S_IRQHandler, 187 | FPU_IRQHandler, 188 | }; 189 | -------------------------------------------------------------------------------- /monocle-core/monocle.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the MicroPython for Monocle project: 3 | * https://github.com/brilliantlabsAR/monocle-micropython 4 | * 5 | * Authored by: Josuah Demangeon (me@josuah.net) 6 | * Raj Nakarja / Brilliant Labs Ltd. (raj@itsbrilliant.co) 7 | * 8 | * ISC Licence 9 | * 10 | * Copyright © 2023 Brilliant Labs Ltd. 11 | * 12 | * Permission to use, copy, modify, and/or distribute this software for any 13 | * purpose with or without fee is hereby granted, provided that the above 14 | * copyright notice and this permission notice appear in all copies. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 17 | * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 18 | * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 19 | * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 20 | * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 21 | * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 22 | * PERFORMANCE OF THIS SOFTWARE. 23 | */ 24 | 25 | #pragma once 26 | 27 | #include 28 | #include 29 | #include "nrfx.h" 30 | #include "nrfx_log.h" 31 | 32 | /** 33 | * @brief Monocle PCB pinout. 34 | */ 35 | 36 | #define BATTERY_LEVEL_PIN NRF_SAADC_INPUT_AIN1 // 37 | #define CAMERA_I2C_SCL_PIN 18 // 38 | #define CAMERA_I2C_SDA_PIN 16 // 39 | #define CAMERA_RESET_PIN 20 // 40 | #define CAMERA_SLEEP_PIN 29 // 41 | #define DISPLAY_CS_PIN 6 // Active low 42 | #define DISPLAY_RESET_PIN 15 // Active low 43 | #define FLASH_CS_PIN 4 // Active low 44 | #define FPGA_CS_MODE_PIN 8 // Active low 45 | #define FPGA_FLASH_SPI_SCK_PIN 7 // 46 | #define FPGA_FLASH_SPI_SDI_PIN 10 // 47 | #define FPGA_FLASH_SPI_SDO_PIN 9 // 48 | #define FPGA_RESET_INT_PIN 5 // 49 | #define PMIC_INTERRUPT_PIN 14 // 50 | #define PMIC_TOUCH_I2C_SCL_PIN 17 // 51 | #define PMIC_TOUCH_I2C_SDA_PIN 13 // 52 | #define TOUCH_INTERRUPT_PIN 2 // 53 | 54 | /** 55 | * @brief LED driver. 56 | */ 57 | 58 | typedef enum led_t 59 | { 60 | GREEN_LED, 61 | RED_LED 62 | } led_t; 63 | 64 | void monocle_set_led(led_t led, bool enable); 65 | 66 | /** 67 | * @brief Startup and PMIC initialization. 68 | */ 69 | 70 | void monocle_critical_startup(void); 71 | 72 | /** 73 | * @brief Bootloader entry function. 74 | */ 75 | 76 | void monocle_enter_bootloader(void); 77 | 78 | /** 79 | * @brief Reboots Monocle with the safe mode flag enabled. 80 | */ 81 | 82 | void monocle_enter_safe_mode(void); 83 | 84 | /** 85 | * @brief Checks if the safe mode flag is set or not. 86 | */ 87 | 88 | bool monocle_started_in_safe_mode(void); 89 | 90 | /** 91 | * @brief Resets the FPGA, and either holds it in reset, or reboots. 92 | */ 93 | 94 | void monocle_fpga_reset(bool reboot); 95 | 96 | /** 97 | * @brief Dev board mode flag. i.e. no PMIC, FPGA, display detected etc. 98 | */ 99 | 100 | extern bool not_real_hardware_flag; 101 | 102 | /** 103 | * @brief Prevents sleeping when a 5V charging voltage is applied to Monocle. 104 | */ 105 | 106 | extern bool prevent_sleep_flag; 107 | 108 | /** 109 | * @brief Forces sleep, as if Monocle was placed into the charging case. 110 | */ 111 | 112 | extern bool force_sleep_flag; 113 | 114 | /** 115 | * @brief Low level I2C driver for accessing PMIC, camera and touch ICs. 116 | */ 117 | 118 | #define PMIC_I2C_ADDRESS 0x48 119 | #define TOUCH_I2C_ADDRESS 0x44 120 | #define CAMERA_I2C_ADDRESS 0x3C 121 | 122 | typedef struct i2c_response_t 123 | { 124 | bool fail; 125 | uint8_t value; 126 | } i2c_response_t; 127 | 128 | i2c_response_t monocle_i2c_read(uint8_t device_address_7bit, 129 | uint16_t register_address, 130 | uint8_t register_mask); 131 | 132 | i2c_response_t monocle_i2c_write(uint8_t device_address_7bit, 133 | uint16_t register_address, 134 | uint8_t register_mask, 135 | uint8_t set_value); 136 | 137 | /** 138 | * @brief Low level SPI driver for accessing FPGA, display and flash. 139 | */ 140 | 141 | typedef enum spi_device_t 142 | { 143 | DISPLAY, 144 | FPGA, 145 | FLASH 146 | } spi_device_t; 147 | 148 | void monocle_spi_enable(bool enable); 149 | 150 | void monocle_spi_read(spi_device_t spi_device, uint8_t *data, size_t length, 151 | bool hold_down_cs); 152 | 153 | void monocle_spi_write(spi_device_t spi_device, uint8_t *data, size_t length, 154 | bool hold_down_cs); 155 | 156 | /** 157 | * @brief High level SPI driver for accessing flash. 158 | */ 159 | 160 | void monocle_flash_read(uint8_t *buffer, size_t address, size_t length); 161 | 162 | void monocle_flash_write(uint8_t *buffer, size_t address, size_t length); 163 | 164 | void monocle_flash_page_erase(size_t address); 165 | 166 | /** 167 | * @brief Error handling macro. 168 | */ 169 | 170 | #define app_err(eval) \ 171 | do \ 172 | { \ 173 | nrfx_err_t err = (eval); \ 174 | if (0x0000FFFF & err) \ 175 | { \ 176 | NRFX_LOG("App error: 0x%x at %s:%u", err, __FILE__, __LINE__); \ 177 | if (CoreDebug->DHCSR & CoreDebug_DHCSR_C_DEBUGEN_Msk) \ 178 | { \ 179 | __BKPT(); \ 180 | } \ 181 | NVIC_SystemReset(); \ 182 | } \ 183 | } while (0) 184 | -------------------------------------------------------------------------------- /monocle-core/monocle.ld: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the MicroPython for Monocle project: 3 | * https://github.com/brilliantlabsAR/monocle-micropython 4 | * 5 | * Authored by: Josuah Demangeon (me@josuah.net) 6 | * Raj Nakarja / Brilliant Labs Ltd. (raj@itsbrilliant.co) 7 | * 8 | * ISC Licence 9 | * 10 | * Copyright © 2023 Brilliant Labs Ltd. 11 | * 12 | * Permission to use, copy, modify, and/or distribute this software for any 13 | * purpose with or without fee is hereby granted, provided that the above 14 | * copyright notice and this permission notice appear in all copies. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 17 | * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 18 | * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 19 | * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 20 | * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 21 | * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 22 | * PERFORMANCE OF THIS SOFTWARE. 23 | */ 24 | 25 | /* The nRF52 memory layout is described here 26 | * https://infocenter.nordicsemi.com/topic/sdk_nrf5_v17.1.0/lib_bootloader.html#lib_bootloader_memory 27 | */ 28 | 29 | /* 30 | * NOTE: Whenever changing things here. Remember to clean and rebuild 31 | */ 32 | 33 | /* These must be updated whenever the softdevice is upgraded */ 34 | sd_flash_end = 0x26000; 35 | sd_flash_size = sd_flash_end; /* Softdevice sits at the start of the flash */ 36 | 37 | /* This must be updated whenever the bootloader size changes */ 38 | bl_flash_start = 0x78000; 39 | bl_flash_size = 512K - bl_flash_start; /* Bootloader is at the end of the flash */ 40 | 41 | /* This must be updated whenever softdevice settings are changed */ 42 | sd_ram_end = 0x2D88; 43 | 44 | ENTRY(Reset_Handler) 45 | 46 | MEMORY 47 | { 48 | FLASH (rx) : ORIGIN = sd_flash_end, LENGTH = 512K - sd_flash_size - bl_flash_size 49 | RAM (rwx) : ORIGIN = 0x20000000 + sd_ram_end, LENGTH = 64K - sd_ram_end 50 | } 51 | 52 | SECTIONS 53 | { 54 | /* Program code and other data goes into FLASH */ 55 | 56 | .text : 57 | { 58 | . = ALIGN(4); 59 | KEEP(*(.isr_vector)) /* Startup code */ 60 | *(.text) /* .text sections (code) */ 61 | *(.text*) /* .text* sections (code) */ 62 | *(.rodata) /* .rodata sections (constants, strings, etc.) */ 63 | *(.rodata*) /* .rodata* sections (constants, strings, etc.) */ 64 | 65 | . = ALIGN(4); 66 | _etext = .; /* define a global symbol at end of code */ 67 | } > FLASH 68 | 69 | .ARM.exidx : 70 | { 71 | __exidx_start = .; 72 | *(.ARM.exidx* .gnu.linkonce.armexidx.*) 73 | __exidx_end = .; 74 | } > FLASH 75 | 76 | /* This is used by the startup to initialize data */ 77 | 78 | _sidata = LOADADDR(.data); 79 | 80 | /* This is the initialized data section. The program executes knowing that 81 | the data is in the RAM but the loader puts the initial values in the 82 | FLASH (inidata). It is one task of the startup to copy the initial values 83 | from FLASH to RAM. */ 84 | 85 | .data : 86 | { 87 | . = ALIGN(4); 88 | _sdata = .; /* create a global symbol at data start; used by startup code in order to initialize the .data section in RAM */ 89 | _ram_start = .; /* create a global symbol at ram start for garbage collector */ 90 | *(.data) /* .data sections */ 91 | *(.data*) /* .data* sections */ 92 | 93 | . = ALIGN(4); 94 | _edata = .; /* define a global symbol at data end; used by startup code in order to initialize the .data section in RAM */ 95 | } > RAM AT> FLASH 96 | 97 | /* Uninitialized data section */ 98 | 99 | .bss : 100 | { 101 | . = ALIGN(4); 102 | _sbss = .; /* define a global symbol at bss start; used by startup code */ 103 | *(.bss) 104 | *(.bss*) 105 | *(COMMON) 106 | 107 | . = ALIGN(4); 108 | _ebss = .; /* define a global symbol at bss end; used by startup code and GC */ 109 | 110 | PROVIDE(end = .); 111 | 112 | } > RAM 113 | 114 | .ARM.attributes 0 : 115 | { 116 | *(.ARM.attributes) 117 | } 118 | } 119 | 120 | /* Define the stack area */ 121 | 122 | _stack_top = ORIGIN(RAM) + LENGTH(RAM); 123 | _stack_bot = _stack_top - 8K; 124 | 125 | /* Heap goes from end of bss ram to the bottom of the stack */ 126 | 127 | _heap_start = _ebss; 128 | _heap_end = _stack_bot; 129 | 130 | /* Throw an error if the heap becomes too small */ 131 | 132 | ASSERT(_heap_end - _heap_start >= 4K, "Heap has become too small") -------------------------------------------------------------------------------- /mpconfigport.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the MicroPython for Monocle project: 3 | * https://github.com/brilliantlabsAR/monocle-micropython 4 | * 5 | * Authored by: Josuah Demangeon (me@josuah.net) 6 | * Raj Nakarja / Brilliant Labs Ltd. (raj@itsbrilliant.co) 7 | * 8 | * ISC Licence 9 | * 10 | * Copyright © 2023 Brilliant Labs Ltd. 11 | * 12 | * Permission to use, copy, modify, and/or distribute this software for any 13 | * purpose with or without fee is hereby granted, provided that the above 14 | * copyright notice and this permission notice appear in all copies. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 17 | * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 18 | * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 19 | * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 20 | * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 21 | * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 22 | * PERFORMANCE OF THIS SOFTWARE. 23 | */ 24 | 25 | #pragma once 26 | 27 | #include 28 | #include "mphalport.h" 29 | 30 | #define MICROPY_BANNER_MACHINE "Monocle on nRF52832" 31 | 32 | #define MICROPY_CONFIG_ROM_LEVEL (MICROPY_CONFIG_ROM_LEVEL_CORE_FEATURES) 33 | 34 | #define MICROPY_NLR_SETJMP (1) 35 | #define MICROPY_GCREGS_SETJMP (1) 36 | 37 | // File handling isn't used so we can path strings short 38 | #define MICROPY_ALLOC_PATH_MAX (64) 39 | 40 | #define MICROPY_QSTR_BYTES_IN_HASH (2) 41 | 42 | #define MICROPY_PERSISTENT_CODE_LOAD (1) 43 | 44 | #define MICROPY_MODULE_BUILTIN_INIT (1) 45 | 46 | #define MICROPY_ENABLE_SCHEDULER (1) 47 | 48 | #define MICROPY_COMP_MODULE_CONST (1) 49 | #define MICROPY_COMP_TRIPLE_TUPLE_ASSIGN (1) 50 | #define MICROPY_COMP_RETURN_IF_EXPR (1) 51 | 52 | #define MICROPY_ERROR_REPORTING (MICROPY_ERROR_REPORTING_DETAILED) 53 | 54 | #define MICROPY_PY_ASYNCIO (1) 55 | #define MICROPY_PY_IO_IOBASE (1) 56 | 57 | #define MICROPY_MODULE_WEAK_LINKS (1) 58 | 59 | #define MICROPY_PY_SELECT (1) 60 | 61 | #define MICROPY_PY_FSTRINGS (1) 62 | 63 | #define MICROPY_ENABLE_FINALISER (1) 64 | 65 | #define MICROPY_STACK_CHECK (1) 66 | 67 | #define MICROPY_KBD_EXCEPTION (1) 68 | 69 | #define MICROPY_USE_READLINE (1) 70 | #define MICROPY_USE_READLINE_HISTORY (1) 71 | #define MICROPY_READLINE_HISTORY_SIZE (10) 72 | #define MICROPY_HELPER_REPL (1) 73 | #define MICROPY_REPL_AUTO_INDENT (1) 74 | 75 | #define MICROPY_PY_BUILTINS_STR_UNICODE (1) 76 | #define MICROPY_PY_BUILTINS_STR_CENTER (1) 77 | #define MICROPY_PY_BUILTINS_STR_PARTITION (1) 78 | #define MICROPY_PY_BUILTINS_STR_SPLITLINES (1) 79 | #define MICROPY_PY_BUILTINS_ROUND_INT (1) 80 | #define MICROPY_PY_BUILTINS_NOTIMPLEMENTED (1) 81 | #define MICROPY_PY_BUILTINS_HELP (1) 82 | #define MICROPY_PY_BUILTINS_HELP_TEXT help_text 83 | #define MICROPY_PY_BUILTINS_HELP_MODULES (1) 84 | #define MICROPY_PY_BUILTINS_INPUT (1) 85 | 86 | #define MICROPY_QSTR_EXTRA_POOL mp_qstr_frozen_const_pool 87 | #define MICROPY_PY_BUILTINS_FROZENSET (1) 88 | 89 | #define MICROPY_ENABLE_GC (1) 90 | 91 | #define MICROPY_PY_BUILTINS_COMPLEX (0) 92 | #define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_FLOAT) 93 | #define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_MPZ) 94 | #define MP_NEED_LOG2 (1) 95 | 96 | #define MICROPY_PY_BINASCII (1) 97 | #define MICROPY_PY_BINASCII_CRC32 (1) 98 | 99 | #define MICROPY_PY_SYS_STDFILES (1) 100 | 101 | #define MICROPY_PY_ERRNO (1) 102 | 103 | #define MICROPY_PY_HASHLIB (1) 104 | 105 | #define MICROPY_PY_JSON (1) 106 | 107 | #define MICROPY_PY_OS (1) 108 | #define MICROPY_VFS (1) 109 | #define MICROPY_VFS_LFS2 (1) 110 | #define MICROPY_READER_VFS (1) 111 | 112 | #define MICROPY_PY_RANDOM (1) 113 | #define MICROPY_PY_RANDOM_EXTRA_FUNCS (1) 114 | #define MICROPY_PY_RANDOM_SEED_INIT_FUNC (mp_hal_generate_random_seed()) 115 | 116 | #define MICROPY_PY_RE (1) 117 | #define MICROPY_PY_RE_SUB (1) 118 | #define MICROPY_PY_HEAPQ (1) 119 | 120 | #define MICROPY_PY_TIME (1) 121 | #define MICROPY_PY_TIME_INCLUDEFILE "../modules/time.c" 122 | 123 | #define MICROPY_MAKE_POINTER_CALLABLE(p) ((void *)((mp_uint_t)(p) | 1)) 124 | 125 | #define MICROPY_EPOCH_IS_1970 (1) 126 | 127 | #define MP_SSIZE_MAX (0x7fffffff) 128 | 129 | #define MP_STATE_PORT MP_STATE_VM 130 | 131 | void mp_event_poll_hook(void); 132 | #define MICROPY_EVENT_POLL_HOOK mp_event_poll_hook(); 133 | -------------------------------------------------------------------------------- /mphalport.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the MicroPython for Monocle project: 3 | * https://github.com/brilliantlabsAR/monocle-micropython 4 | * 5 | * Authored by: Josuah Demangeon (me@josuah.net) 6 | * Raj Nakarja / Brilliant Labs Ltd. (raj@itsbrilliant.co) 7 | * 8 | * ISC Licence 9 | * 10 | * Copyright © 2023 Brilliant Labs Ltd. 11 | * 12 | * Permission to use, copy, modify, and/or distribute this software for any 13 | * purpose with or without fee is hereby granted, provided that the above 14 | * copyright notice and this permission notice appear in all copies. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 17 | * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 18 | * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 19 | * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 20 | * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 21 | * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 22 | * PERFORMANCE OF THIS SOFTWARE. 23 | */ 24 | 25 | #include "py/builtin.h" 26 | #include "py/mperrno.h" 27 | #include "py/lexer.h" 28 | #include "py/runtime.h" 29 | #include "mpconfigport.h" 30 | #include "nrfx_rtc.h" 31 | 32 | const char help_text[] = { 33 | "Welcome to MicroPython!\n\n" 34 | "For full documentation, visit: https://docs.brilliant.xyz\n" 35 | "Control commands:\n" 36 | " Ctrl-A - enter raw REPL mode\n" 37 | " Ctrl-B - enter normal REPL mode\n" 38 | " Ctrl-C - interrupt a running program\n" 39 | " Ctrl-D - reset the device\n" 40 | " Ctrl-E - enter paste mode\n\n" 41 | "To list available modules, type help('modules')\n" 42 | "For details on a specific module, import it, and then type " 43 | "help(module_name)\n"}; 44 | 45 | static nrfx_rtc_t rtc = NRFX_RTC_INSTANCE(1); 46 | 47 | uint64_t mp_hal_time_ns(void) 48 | { 49 | return 0; 50 | } 51 | 52 | mp_uint_t mp_hal_ticks_us(void) 53 | { 54 | return 0; 55 | } 56 | 57 | mp_uint_t mp_hal_ticks_ms(void) 58 | { 59 | uint32_t value = nrfx_rtc_counter_get(&rtc); 60 | 61 | // Correct for the slightly faster tick frequency of 1024Hz 62 | float ms = (float)value / 1024 * 1000; 63 | 64 | return (mp_uint_t)ms; 65 | } 66 | 67 | mp_uint_t mp_hal_ticks_cpu(void) 68 | { 69 | // This doesn't seem to be used by anything so it's not implemented 70 | return 0; 71 | } 72 | 73 | void mp_hal_delay_us(mp_uint_t us) 74 | { 75 | (void)us; 76 | return; 77 | } 78 | 79 | void mp_hal_delay_ms(mp_uint_t ms) 80 | { 81 | uint32_t start_time = mp_hal_ticks_ms(); 82 | 83 | while (mp_hal_ticks_ms() - start_time < ms) 84 | { 85 | MICROPY_EVENT_POLL_HOOK; 86 | } 87 | } 88 | 89 | int mp_hal_generate_random_seed(void) 90 | { 91 | return 0; 92 | } 93 | -------------------------------------------------------------------------------- /mphalport.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the MicroPython for Monocle project: 3 | * https://github.com/brilliantlabsAR/monocle-micropython 4 | * 5 | * Authored by: Josuah Demangeon (me@josuah.net) 6 | * Raj Nakarja / Brilliant Labs Ltd. (raj@itsbrilliant.co) 7 | * 8 | * ISC Licence 9 | * 10 | * Copyright © 2023 Brilliant Labs Ltd. 11 | * 12 | * Permission to use, copy, modify, and/or distribute this software for any 13 | * purpose with or without fee is hereby granted, provided that the above 14 | * copyright notice and this permission notice appear in all copies. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 17 | * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 18 | * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 19 | * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 20 | * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 21 | * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 22 | * PERFORMANCE OF THIS SOFTWARE. 23 | */ 24 | 25 | #pragma once 26 | 27 | #include 28 | #include 29 | #include 30 | #include "mphalport.h" 31 | #include "nrfx_rtc.h" 32 | #include "touch.h" 33 | 34 | typedef int mp_int_t; 35 | typedef unsigned int mp_uint_t; 36 | typedef long mp_off_t; 37 | 38 | mp_uint_t mp_hal_ticks_ms(void); 39 | 40 | void mp_hal_set_interrupt_char(int c); 41 | 42 | int mp_hal_generate_random_seed(void); 43 | 44 | touch_button_t touch_get_state(void); 45 | 46 | typedef enum ble_tx_channel_t 47 | { 48 | REPL_TX, 49 | DATA_TX, 50 | } ble_tx_channel_t; 51 | 52 | bool ble_are_tx_notifications_enabled(ble_tx_channel_t channel); 53 | 54 | size_t ble_get_max_payload_size(void); 55 | 56 | bool ble_send_raw_data(const uint8_t *bytes, size_t len); -------------------------------------------------------------------------------- /nrfx_config.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the MicroPython for Monocle project: 3 | * https://github.com/brilliantlabsAR/monocle-micropython 4 | * 5 | * Authored by: Josuah Demangeon (me@josuah.net) 6 | * Raj Nakarja / Brilliant Labs Ltd. (raj@itsbrilliant.co) 7 | * 8 | * ISC Licence 9 | * 10 | * Copyright © 2023 Brilliant Labs Ltd. 11 | * 12 | * Permission to use, copy, modify, and/or distribute this software for any 13 | * purpose with or without fee is hereby granted, provided that the above 14 | * copyright notice and this permission notice appear in all copies. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 17 | * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 18 | * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 19 | * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 20 | * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 21 | * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 22 | * PERFORMANCE OF THIS SOFTWARE. 23 | */ 24 | 25 | #pragma once 26 | 27 | #include "nrf.h" 28 | 29 | // For every module, it might be necessary to set the IRQ priority to 30 | // 7 so that the Nordic Uart Service (NUS) gets a higher priority. 31 | 32 | #define NRFX_LOG_ENABLED 1 33 | #define NRFX_LOG_UART_DISABLED 1 34 | 35 | #define NRFX_GPIOTE_ENABLED 1 36 | #define NRFX_GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS 1 37 | #define NRFX_GPIOTE_DEFAULT_CONFIG_IRQ_PRIORITY 7 38 | 39 | #define NRFX_TWIM0_ENABLED 1 40 | #define NRFX_TWIM_ENABLED 1 41 | #define NRFX_TWIM1_ENABLED 1 42 | #define NRFX_TWIM_DEFAULT_CONFIG_IRQ_PRIORITY 7 43 | 44 | #define NRFX_SPIM_ENABLED 1 45 | #define NRFX_SPIM2_ENABLED 1 46 | #define NRFX_SPIM_DEFAULT_CONFIG_IRQ_PRIORITY 7 47 | 48 | #define NRFX_RTC_ENABLED 1 49 | #define NRFX_RTC0_ENABLED 1 50 | #define NRFX_RTC1_ENABLED 1 // Used by micropython time functions 51 | #define NRFX_RTC_DEFAULT_CONFIG_IRQ_PRIORITY 7 52 | 53 | #define NRFX_SYSTICK_ENABLED 1 54 | 55 | #define NRFX_TIMER_ENABLED 1 56 | #define NRFX_TIMER0_ENABLED 1 // Used by the SoftDevice 57 | #define NRFX_TIMER4_ENABLED 1 // Used for checking battery state 58 | #define NRFX_TIMER_DEFAULT_CONFIG_IRQ_PRIORITY 7 59 | 60 | #define NRFX_SAADC_ENABLED 1 61 | #define NRFX_SAADC_DEFAULT_CONFIG_IRQ_PRIORITY 7 62 | -------------------------------------------------------------------------------- /nrfx_glue.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the MicroPython for Monocle project: 3 | * https://github.com/brilliantlabsAR/monocle-micropython 4 | * 5 | * Authored by: Josuah Demangeon (me@josuah.net) 6 | * Raj Nakarja / Brilliant Labs Ltd. (raj@itsbrilliant.co) 7 | * 8 | * ISC Licence 9 | * 10 | * Copyright © 2023 Brilliant Labs Ltd. 11 | * 12 | * Permission to use, copy, modify, and/or distribute this software for any 13 | * purpose with or without fee is hereby granted, provided that the above 14 | * copyright notice and this permission notice appear in all copies. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 17 | * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 18 | * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 19 | * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 20 | * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 21 | * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 22 | * PERFORMANCE OF THIS SOFTWARE. 23 | */ 24 | 25 | #pragma once 26 | 27 | #include "monocle.h" 28 | 29 | #include "nrfx.h" 30 | #include "nrf_nvic.h" 31 | #include 32 | #include 33 | 34 | #define NRFX_ASSERT(expression) \ 35 | do \ 36 | { \ 37 | if ((expression) == 0) \ 38 | { \ 39 | app_err(0xDEAD0A55); \ 40 | } \ 41 | } while (0) 42 | 43 | #define NRFX_STATIC_ASSERT(expression) \ 44 | _Static_assert(expression, "unspecified message") 45 | 46 | #define NRFX_IRQ_PRIORITY_SET(irq_number, priority) \ 47 | sd_nvic_SetPriority(irq_number, priority) 48 | 49 | #define NRFX_IRQ_ENABLE(irq_number) \ 50 | sd_nvic_EnableIRQ(irq_number) 51 | 52 | #define NRFX_IRQ_IS_ENABLED(irq_number) \ 53 | (0 != (NVIC->ISER[irq_number / 32] & (1UL << (irq_number % 32)))) 54 | 55 | #define NRFX_IRQ_DISABLE(irq_number) \ 56 | sd_nvic_DisableIRQ(irq_number) 57 | 58 | #define NRFX_IRQ_PENDING_SET(irq_number) \ 59 | sd_nvic_SetPendingIRQ(irq_number) 60 | 61 | #define NRFX_IRQ_PENDING_CLEAR(irq_number) \ 62 | sd_nvic_ClearPendingIRQ(irq_number) 63 | 64 | #define NRFX_IRQ_IS_PENDING(irq_number) \ 65 | NVIC_GetPendingIRQ(irq_number) 66 | 67 | #define NRFX_CRITICAL_SECTION_ENTER() \ 68 | { \ 69 | uint8_t _is_nested_critical_region; \ 70 | sd_nvic_critical_region_enter(&_is_nested_critical_region); 71 | 72 | #define NRFX_CRITICAL_SECTION_EXIT() \ 73 | sd_nvic_critical_region_exit(_is_nested_critical_region); \ 74 | } 75 | 76 | #define NRFX_DELAY_DWT_BASED 0 77 | 78 | #define NRFX_DELAY_US(us_time) \ 79 | nrfx_coredep_delay_us(us_time) 80 | 81 | #define nrfx_atomic_t nrfx_atomic_u32_t 82 | 83 | #define NRFX_ATOMIC_FETCH_STORE(p_data, value) \ 84 | nrfx_atomic_u32_fetch_store(p_data, value) 85 | 86 | #define NRFX_ATOMIC_FETCH_OR(p_data, value) \ 87 | nrfx_atomic_u32_fetch_or(p_data, value) 88 | 89 | #define NRFX_ATOMIC_FETCH_AND(p_data, value) \ 90 | nrfx_atomic_u32_fetch_and(p_data, value) 91 | 92 | #define NRFX_ATOMIC_FETCH_XOR(p_data, value) \ 93 | nrfx_atomic_u32_fetch_xor(p_data, value) 94 | 95 | #define NRFX_ATOMIC_FETCH_ADD(p_data, value) \ 96 | nrfx_atomic_u32_fetch_add(p_data, value) 97 | 98 | #define NRFX_ATOMIC_FETCH_SUB(p_data, value) \ 99 | nrfx_atomic_u32_fetch_sub(p_data, value) 100 | 101 | #define NRFX_CUSTOM_ERROR_CODES 0 102 | 103 | #define NRFX_EVENT_READBACK_ENABLED 1 104 | 105 | #define NRFX_DPPI_CHANNELS_USED 0 106 | 107 | #define NRFX_DPPI_GROUPS_USED 0 108 | 109 | #define NRFX_PPI_CHANNELS_USED 0 110 | 111 | #define NRFX_PPI_GROUPS_USED 0 112 | 113 | #define NRFX_GPIOTE_CHANNELS_USED 0 114 | 115 | #define NRFX_EGUS_USED 0 116 | 117 | #define NRFX_TIMERS_USED 0 118 | -------------------------------------------------------------------------------- /nrfx_log.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the MicroPython for Monocle project: 3 | * https://github.com/brilliantlabsAR/monocle-micropython 4 | * 5 | * Authored by: Josuah Demangeon (me@josuah.net) 6 | * Raj Nakarja / Brilliant Labs Ltd. (raj@itsbrilliant.co) 7 | * 8 | * ISC Licence 9 | * 10 | * Copyright © 2023 Brilliant Labs Ltd. 11 | * 12 | * Permission to use, copy, modify, and/or distribute this software for any 13 | * purpose with or without fee is hereby granted, provided that the above 14 | * copyright notice and this permission notice appear in all copies. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 17 | * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 18 | * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 19 | * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 20 | * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 21 | * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 22 | * PERFORMANCE OF THIS SOFTWARE. 23 | */ 24 | 25 | #pragma once 26 | 27 | #include "SEGGER_RTT.h" 28 | 29 | #define NRFX_LOG(format, ...) \ 30 | SEGGER_RTT_printf(0, format "\r\n", ##__VA_ARGS__) 31 | 32 | #define NRFX_LOG_ERROR(format, ...) 33 | #define NRFX_LOG_WARNING(format, ...) 34 | #define NRFX_LOG_INFO(format, ...) 35 | #define NRFX_LOG_DEBUG(format, ...) 36 | 37 | #define NRFX_LOG_HEXDUMP_ERROR(p_memory, length) 38 | #define NRFX_LOG_HEXDUMP_WARNING(p_memory, length) 39 | #define NRFX_LOG_HEXDUMP_INFO(p_memory, length) 40 | #define NRFX_LOG_HEXDUMP_DEBUG(p_memory, length) 41 | #define NRFX_LOG_ERROR_STRING_GET(error_code) 42 | -------------------------------------------------------------------------------- /segger/SEGGER_RTT_Syscalls_GCC.c: -------------------------------------------------------------------------------- 1 | /********************************************************************* 2 | * SEGGER Microcontroller GmbH & Co. KG * 3 | * The Embedded Experts * 4 | ********************************************************************** 5 | * * 6 | * (c) 2014 - 2017 SEGGER Microcontroller GmbH & Co. KG * 7 | * * 8 | * www.segger.com Support: support@segger.com * 9 | * * 10 | ********************************************************************** 11 | * * 12 | * SEGGER RTT * Real Time Transfer for embedded targets * 13 | * * 14 | ********************************************************************** 15 | * * 16 | * All rights reserved. * 17 | * * 18 | * SEGGER strongly recommends to not make any changes * 19 | * to or modify the source code of this software in order to stay * 20 | * compatible with the RTT protocol and J-Link. * 21 | * * 22 | * Redistribution and use in source and binary forms, with or * 23 | * without modification, are permitted provided that the following * 24 | * conditions are met: * 25 | * * 26 | * o Redistributions of source code must retain the above copyright * 27 | * notice, this list of conditions and the following disclaimer. * 28 | * * 29 | * o Redistributions in binary form must reproduce the above * 30 | * copyright notice, this list of conditions and the following * 31 | * disclaimer in the documentation and/or other materials provided * 32 | * with the distribution. * 33 | * * 34 | * o Neither the name of SEGGER Microcontroller GmbH & Co. KG * 35 | * nor the names of its contributors may be used to endorse or * 36 | * promote products derived from this software without specific * 37 | * prior written permission. * 38 | * * 39 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * 40 | * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, * 41 | * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * 42 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * 43 | * DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR * 44 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * 45 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT * 46 | * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * 47 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * 48 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * 49 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * 50 | * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * 51 | * DAMAGE. * 52 | * * 53 | ********************************************************************** 54 | * * 55 | * RTT version: 6.18a * 56 | * * 57 | ********************************************************************** 58 | ---------------------------END-OF-HEADER------------------------------ 59 | File : SEGGER_RTT_Syscalls_GCC.c 60 | Purpose : Low-level functions for using printf() via RTT in GCC. 61 | To use RTT for printf output, include this file in your 62 | application. 63 | Revision: $Rev: 4351 $ 64 | ---------------------------------------------------------------------- 65 | */ 66 | #if !defined(RETARGET_ENABLED) || RETARGET_ENABLED == 0 67 | #if defined(NRF_LOG_USES_RTT) && NRF_LOG_USES_RTT == 1 68 | #if (defined __GNUC__) && !(defined __SES_ARM) && !(defined __CROSSWORKS_ARM) 69 | 70 | #include // required for _write_r 71 | #include "SEGGER_RTT.h" 72 | 73 | 74 | /********************************************************************* 75 | * 76 | * Types 77 | * 78 | ********************************************************************** 79 | */ 80 | // 81 | // If necessary define the _reent struct 82 | // to match the one passed by the used standard library. 83 | // 84 | struct _reent; 85 | 86 | /********************************************************************* 87 | * 88 | * Function prototypes 89 | * 90 | ********************************************************************** 91 | */ 92 | int _write(int file, char *ptr, int len); 93 | _ssize_t _write_r _PARAMS ((struct _reent *, int, const void *, size_t)); 94 | 95 | /********************************************************************* 96 | * 97 | * Global functions 98 | * 99 | ********************************************************************** 100 | */ 101 | 102 | /********************************************************************* 103 | * 104 | * _write() 105 | * 106 | * Function description 107 | * Low-level write function. 108 | * libc subroutines will use this system routine for output to all files, 109 | * including stdout. 110 | * Write data via RTT. 111 | */ 112 | int _write(int file, char *ptr, int len) { 113 | (void) file; /* Not used, avoid warning */ 114 | SEGGER_RTT_Write(0, ptr, len); 115 | return len; 116 | } 117 | 118 | /********************************************************************* 119 | * 120 | * _write_r() 121 | * 122 | * Function description 123 | * Low-level reentrant write function. 124 | * libc subroutines will use this system routine for output to all files, 125 | * including stdout. 126 | * Write data via RTT. 127 | */ 128 | _ssize_t _write_r _PARAMS((struct _reent *r, int file, const void *ptr, size_t len)) { 129 | (void) file; /* Not used, avoid warning */ 130 | (void) r; /* Not used, avoid warning */ 131 | SEGGER_RTT_Write(0, ptr, len); 132 | return len; 133 | } 134 | 135 | #endif // #if (defined __GNUC__) && !(defined __SES_ARM) && !(defined __CROSSWORKS_ARM) 136 | #endif // defined(NRF_LOG_USES_RTT) && NRF_LOG_USES_RTT == 1 137 | #endif // !defined(RETARGET_ENABLED) || RETARGET_ENABLED == 0 138 | /****** End Of File *************************************************/ 139 | -------------------------------------------------------------------------------- /segger/license/license.txt: -------------------------------------------------------------------------------- 1 | /********************************************************************* 2 | * SEGGER MICROCONTROLLER GmbH & Co. KG * 3 | * Solutions for real time microcontroller applications * 4 | ********************************************************************** 5 | * * 6 | * (c) 2014 - 2015 SEGGER Microcontroller GmbH & Co. KG * 7 | * * 8 | * www.segger.com Support: support@segger.com * 9 | * * 10 | ********************************************************************** 11 | * * 12 | * All rights reserved. * 13 | * * 14 | * * This software may in its unmodified form be freely redistributed * 15 | * in source form. * 16 | * * The source code may be modified, provided the source code * 17 | * retains the above copyright notice, this list of conditions and * 18 | * the following disclaimer. * 19 | * * Modified versions of this software in source or linkable form * 20 | * may not be distributed without prior consent of SEGGER. * 21 | * * This software may only be used for communication with SEGGER * 22 | * J-Link debug probes. * 23 | * * 24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * 25 | * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, * 26 | * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * 27 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * 28 | * DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR * 29 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * 30 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT * 31 | * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * 32 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * 33 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * 34 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * 35 | * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * 36 | * DAMAGE. * 37 | * * 38 | ********************************************************************** 39 | -------------------------------------------------------------------------------- /softdevice/include/ble_err.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Nordic Semiconductor ASA 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, 6 | * are permitted provided that the following conditions are met: 7 | * 8 | * 1. Redistributions of source code must retain the above copyright notice, this 9 | * list of conditions and the following disclaimer. 10 | * 11 | * 2. Redistributions in binary form, except as embedded into a Nordic 12 | * Semiconductor ASA integrated circuit in a product or a software update for 13 | * such product, must reproduce the above copyright notice, this list of 14 | * conditions and the following disclaimer in the documentation and/or other 15 | * materials provided with the distribution. 16 | * 17 | * 3. Neither the name of Nordic Semiconductor ASA nor the names of its 18 | * contributors may be used to endorse or promote products derived from this 19 | * software without specific prior written permission. 20 | * 21 | * 4. This software, with or without modification, must only be used with a 22 | * Nordic Semiconductor ASA integrated circuit. 23 | * 24 | * 5. Any software provided in binary form under this license must not be reverse 25 | * engineered, decompiled, modified and/or disassembled. 26 | * 27 | * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS 28 | * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 29 | * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE 30 | * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE 31 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 32 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 33 | * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 34 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 35 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 36 | * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 37 | */ 38 | 39 | /** 40 | @addtogroup BLE_COMMON 41 | @{ 42 | @addtogroup nrf_error 43 | @{ 44 | @ingroup BLE_COMMON 45 | @} 46 | 47 | @defgroup ble_err General error codes 48 | @{ 49 | 50 | @brief General error code definitions for the BLE API. 51 | 52 | @ingroup BLE_COMMON 53 | */ 54 | #ifndef NRF_BLE_ERR_H__ 55 | #define NRF_BLE_ERR_H__ 56 | 57 | #include "nrf_error.h" 58 | 59 | #ifdef __cplusplus 60 | extern "C" { 61 | #endif 62 | 63 | /* @defgroup BLE_ERRORS Error Codes 64 | * @{ */ 65 | #define BLE_ERROR_NOT_ENABLED (NRF_ERROR_STK_BASE_NUM+0x001) /**< @ref sd_ble_enable has not been called. */ 66 | #define BLE_ERROR_INVALID_CONN_HANDLE (NRF_ERROR_STK_BASE_NUM+0x002) /**< Invalid connection handle. */ 67 | #define BLE_ERROR_INVALID_ATTR_HANDLE (NRF_ERROR_STK_BASE_NUM+0x003) /**< Invalid attribute handle. */ 68 | #define BLE_ERROR_INVALID_ADV_HANDLE (NRF_ERROR_STK_BASE_NUM+0x004) /**< Invalid advertising handle. */ 69 | #define BLE_ERROR_INVALID_ROLE (NRF_ERROR_STK_BASE_NUM+0x005) /**< Invalid role. */ 70 | #define BLE_ERROR_BLOCKED_BY_OTHER_LINKS (NRF_ERROR_STK_BASE_NUM+0x006) /**< The attempt to change link settings failed due to the scheduling of other links. */ 71 | /** @} */ 72 | 73 | 74 | /** @defgroup BLE_ERROR_SUBRANGES Module specific error code subranges 75 | * @brief Assignment of subranges for module specific error codes. 76 | * @note For specific error codes, see ble_.h or ble_error_.h. 77 | * @{ */ 78 | #define NRF_L2CAP_ERR_BASE (NRF_ERROR_STK_BASE_NUM+0x100) /**< L2CAP specific errors. */ 79 | #define NRF_GAP_ERR_BASE (NRF_ERROR_STK_BASE_NUM+0x200) /**< GAP specific errors. */ 80 | #define NRF_GATTC_ERR_BASE (NRF_ERROR_STK_BASE_NUM+0x300) /**< GATT client specific errors. */ 81 | #define NRF_GATTS_ERR_BASE (NRF_ERROR_STK_BASE_NUM+0x400) /**< GATT server specific errors. */ 82 | /** @} */ 83 | 84 | #ifdef __cplusplus 85 | } 86 | #endif 87 | #endif 88 | 89 | 90 | /** 91 | @} 92 | @} 93 | */ 94 | -------------------------------------------------------------------------------- /softdevice/include/ble_hci.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Nordic Semiconductor ASA 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, 6 | * are permitted provided that the following conditions are met: 7 | * 8 | * 1. Redistributions of source code must retain the above copyright notice, this 9 | * list of conditions and the following disclaimer. 10 | * 11 | * 2. Redistributions in binary form, except as embedded into a Nordic 12 | * Semiconductor ASA integrated circuit in a product or a software update for 13 | * such product, must reproduce the above copyright notice, this list of 14 | * conditions and the following disclaimer in the documentation and/or other 15 | * materials provided with the distribution. 16 | * 17 | * 3. Neither the name of Nordic Semiconductor ASA nor the names of its 18 | * contributors may be used to endorse or promote products derived from this 19 | * software without specific prior written permission. 20 | * 21 | * 4. This software, with or without modification, must only be used with a 22 | * Nordic Semiconductor ASA integrated circuit. 23 | * 24 | * 5. Any software provided in binary form under this license must not be reverse 25 | * engineered, decompiled, modified and/or disassembled. 26 | * 27 | * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS 28 | * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 29 | * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE 30 | * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE 31 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 32 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 33 | * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 34 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 35 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 36 | * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 37 | */ 38 | 39 | /** 40 | @addtogroup BLE_COMMON 41 | @{ 42 | */ 43 | 44 | 45 | #ifndef BLE_HCI_H__ 46 | #define BLE_HCI_H__ 47 | #ifdef __cplusplus 48 | extern "C" { 49 | #endif 50 | 51 | /** @defgroup BLE_HCI_STATUS_CODES Bluetooth status codes 52 | * @{ */ 53 | 54 | #define BLE_HCI_STATUS_CODE_SUCCESS 0x00 /**< Success. */ 55 | #define BLE_HCI_STATUS_CODE_UNKNOWN_BTLE_COMMAND 0x01 /**< Unknown BLE Command. */ 56 | #define BLE_HCI_STATUS_CODE_UNKNOWN_CONNECTION_IDENTIFIER 0x02 /**< Unknown Connection Identifier. */ 57 | /*0x03 Hardware Failure 58 | 0x04 Page Timeout 59 | */ 60 | #define BLE_HCI_AUTHENTICATION_FAILURE 0x05 /**< Authentication Failure. */ 61 | #define BLE_HCI_STATUS_CODE_PIN_OR_KEY_MISSING 0x06 /**< Pin or Key missing. */ 62 | #define BLE_HCI_MEMORY_CAPACITY_EXCEEDED 0x07 /**< Memory Capacity Exceeded. */ 63 | #define BLE_HCI_CONNECTION_TIMEOUT 0x08 /**< Connection Timeout. */ 64 | /*0x09 Connection Limit Exceeded 65 | 0x0A Synchronous Connection Limit To A Device Exceeded 66 | 0x0B ACL Connection Already Exists*/ 67 | #define BLE_HCI_STATUS_CODE_COMMAND_DISALLOWED 0x0C /**< Command Disallowed. */ 68 | /*0x0D Connection Rejected due to Limited Resources 69 | 0x0E Connection Rejected Due To Security Reasons 70 | 0x0F Connection Rejected due to Unacceptable BD_ADDR 71 | 0x10 Connection Accept Timeout Exceeded 72 | 0x11 Unsupported Feature or Parameter Value*/ 73 | #define BLE_HCI_STATUS_CODE_INVALID_BTLE_COMMAND_PARAMETERS 0x12 /**< Invalid BLE Command Parameters. */ 74 | #define BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION 0x13 /**< Remote User Terminated Connection. */ 75 | #define BLE_HCI_REMOTE_DEV_TERMINATION_DUE_TO_LOW_RESOURCES 0x14 /**< Remote Device Terminated Connection due to low resources.*/ 76 | #define BLE_HCI_REMOTE_DEV_TERMINATION_DUE_TO_POWER_OFF 0x15 /**< Remote Device Terminated Connection due to power off. */ 77 | #define BLE_HCI_LOCAL_HOST_TERMINATED_CONNECTION 0x16 /**< Local Host Terminated Connection. */ 78 | /* 79 | 0x17 Repeated Attempts 80 | 0x18 Pairing Not Allowed 81 | 0x19 Unknown LMP PDU 82 | */ 83 | #define BLE_HCI_UNSUPPORTED_REMOTE_FEATURE 0x1A /**< Unsupported Remote Feature. */ 84 | /* 85 | 0x1B SCO Offset Rejected 86 | 0x1C SCO Interval Rejected 87 | 0x1D SCO Air Mode Rejected*/ 88 | #define BLE_HCI_STATUS_CODE_INVALID_LMP_PARAMETERS 0x1E /**< Invalid LMP Parameters. */ 89 | #define BLE_HCI_STATUS_CODE_UNSPECIFIED_ERROR 0x1F /**< Unspecified Error. */ 90 | /*0x20 Unsupported LMP Parameter Value 91 | 0x21 Role Change Not Allowed 92 | */ 93 | #define BLE_HCI_STATUS_CODE_LMP_RESPONSE_TIMEOUT 0x22 /**< LMP Response Timeout. */ 94 | #define BLE_HCI_STATUS_CODE_LMP_ERROR_TRANSACTION_COLLISION 0x23 /**< LMP Error Transaction Collision/LL Procedure Collision. */ 95 | #define BLE_HCI_STATUS_CODE_LMP_PDU_NOT_ALLOWED 0x24 /**< LMP PDU Not Allowed. */ 96 | /*0x25 Encryption Mode Not Acceptable 97 | 0x26 Link Key Can Not be Changed 98 | 0x27 Requested QoS Not Supported 99 | */ 100 | #define BLE_HCI_INSTANT_PASSED 0x28 /**< Instant Passed. */ 101 | #define BLE_HCI_PAIRING_WITH_UNIT_KEY_UNSUPPORTED 0x29 /**< Pairing with Unit Key Unsupported. */ 102 | #define BLE_HCI_DIFFERENT_TRANSACTION_COLLISION 0x2A /**< Different Transaction Collision. */ 103 | /* 104 | 0x2B Reserved 105 | 0x2C QoS Unacceptable Parameter 106 | 0x2D QoS Rejected 107 | 0x2E Channel Classification Not Supported 108 | 0x2F Insufficient Security 109 | */ 110 | #define BLE_HCI_PARAMETER_OUT_OF_MANDATORY_RANGE 0x30 /**< Parameter Out Of Mandatory Range. */ 111 | /* 112 | 0x31 Reserved 113 | 0x32 Role Switch Pending 114 | 0x33 Reserved 115 | 0x34 Reserved Slot Violation 116 | 0x35 Role Switch Failed 117 | 0x36 Extended Inquiry Response Too Large 118 | 0x37 Secure Simple Pairing Not Supported By Host. 119 | 0x38 Host Busy - Pairing 120 | 0x39 Connection Rejected due to No Suitable Channel Found*/ 121 | #define BLE_HCI_CONTROLLER_BUSY 0x3A /**< Controller Busy. */ 122 | #define BLE_HCI_CONN_INTERVAL_UNACCEPTABLE 0x3B /**< Connection Interval Unacceptable. */ 123 | #define BLE_HCI_DIRECTED_ADVERTISER_TIMEOUT 0x3C /**< Directed Advertisement Timeout. */ 124 | #define BLE_HCI_CONN_TERMINATED_DUE_TO_MIC_FAILURE 0x3D /**< Connection Terminated due to MIC Failure. */ 125 | #define BLE_HCI_CONN_FAILED_TO_BE_ESTABLISHED 0x3E /**< Connection Failed to be Established. */ 126 | 127 | /** @} */ 128 | 129 | 130 | #ifdef __cplusplus 131 | } 132 | #endif 133 | #endif // BLE_HCI_H__ 134 | 135 | /** @} */ 136 | -------------------------------------------------------------------------------- /softdevice/include/ble_ranges.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Nordic Semiconductor ASA 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, 6 | * are permitted provided that the following conditions are met: 7 | * 8 | * 1. Redistributions of source code must retain the above copyright notice, this 9 | * list of conditions and the following disclaimer. 10 | * 11 | * 2. Redistributions in binary form, except as embedded into a Nordic 12 | * Semiconductor ASA integrated circuit in a product or a software update for 13 | * such product, must reproduce the above copyright notice, this list of 14 | * conditions and the following disclaimer in the documentation and/or other 15 | * materials provided with the distribution. 16 | * 17 | * 3. Neither the name of Nordic Semiconductor ASA nor the names of its 18 | * contributors may be used to endorse or promote products derived from this 19 | * software without specific prior written permission. 20 | * 21 | * 4. This software, with or without modification, must only be used with a 22 | * Nordic Semiconductor ASA integrated circuit. 23 | * 24 | * 5. Any software provided in binary form under this license must not be reverse 25 | * engineered, decompiled, modified and/or disassembled. 26 | * 27 | * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS 28 | * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 29 | * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE 30 | * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE 31 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 32 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 33 | * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 34 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 35 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 36 | * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 37 | */ 38 | 39 | /** 40 | @addtogroup BLE_COMMON 41 | @{ 42 | @defgroup ble_ranges Module specific SVC, event and option number subranges 43 | @{ 44 | 45 | @brief Definition of SVC, event and option number subranges for each API module. 46 | 47 | @note 48 | SVCs, event and option numbers are split into subranges for each API module. 49 | Each module receives its entire allocated range of SVC calls, whether implemented or not, 50 | but return BLE_ERROR_NOT_SUPPORTED for unimplemented or undefined calls in its range. 51 | 52 | Note that the symbols BLE__SVC_LAST is the end of the allocated SVC range, 53 | rather than the last SVC function call actually defined and implemented. 54 | 55 | Specific SVC, event and option values are defined in each module's ble_.h file, 56 | which defines names of each individual SVC code based on the range start value. 57 | */ 58 | 59 | #ifndef BLE_RANGES_H__ 60 | #define BLE_RANGES_H__ 61 | 62 | #ifdef __cplusplus 63 | extern "C" { 64 | #endif 65 | 66 | #define BLE_SVC_BASE 0x60 /**< Common BLE SVC base. */ 67 | #define BLE_SVC_LAST 0x6B /**< Common BLE SVC last. */ 68 | 69 | #define BLE_GAP_SVC_BASE 0x6C /**< GAP BLE SVC base. */ 70 | #define BLE_GAP_SVC_LAST 0x9A /**< GAP BLE SVC last. */ 71 | 72 | #define BLE_GATTC_SVC_BASE 0x9B /**< GATTC BLE SVC base. */ 73 | #define BLE_GATTC_SVC_LAST 0xA7 /**< GATTC BLE SVC last. */ 74 | 75 | #define BLE_GATTS_SVC_BASE 0xA8 /**< GATTS BLE SVC base. */ 76 | #define BLE_GATTS_SVC_LAST 0xB7 /**< GATTS BLE SVC last. */ 77 | 78 | #define BLE_L2CAP_SVC_BASE 0xB8 /**< L2CAP BLE SVC base. */ 79 | #define BLE_L2CAP_SVC_LAST 0xBF /**< L2CAP BLE SVC last. */ 80 | 81 | 82 | #define BLE_EVT_INVALID 0x00 /**< Invalid BLE Event. */ 83 | 84 | #define BLE_EVT_BASE 0x01 /**< Common BLE Event base. */ 85 | #define BLE_EVT_LAST 0x0F /**< Common BLE Event last. */ 86 | 87 | #define BLE_GAP_EVT_BASE 0x10 /**< GAP BLE Event base. */ 88 | #define BLE_GAP_EVT_LAST 0x2F /**< GAP BLE Event last. */ 89 | 90 | #define BLE_GATTC_EVT_BASE 0x30 /**< GATTC BLE Event base. */ 91 | #define BLE_GATTC_EVT_LAST 0x4F /**< GATTC BLE Event last. */ 92 | 93 | #define BLE_GATTS_EVT_BASE 0x50 /**< GATTS BLE Event base. */ 94 | #define BLE_GATTS_EVT_LAST 0x6F /**< GATTS BLE Event last. */ 95 | 96 | #define BLE_L2CAP_EVT_BASE 0x70 /**< L2CAP BLE Event base. */ 97 | #define BLE_L2CAP_EVT_LAST 0x8F /**< L2CAP BLE Event last. */ 98 | 99 | 100 | #define BLE_OPT_INVALID 0x00 /**< Invalid BLE Option. */ 101 | 102 | #define BLE_OPT_BASE 0x01 /**< Common BLE Option base. */ 103 | #define BLE_OPT_LAST 0x1F /**< Common BLE Option last. */ 104 | 105 | #define BLE_GAP_OPT_BASE 0x20 /**< GAP BLE Option base. */ 106 | #define BLE_GAP_OPT_LAST 0x3F /**< GAP BLE Option last. */ 107 | 108 | #define BLE_GATT_OPT_BASE 0x40 /**< GATT BLE Option base. */ 109 | #define BLE_GATT_OPT_LAST 0x5F /**< GATT BLE Option last. */ 110 | 111 | #define BLE_GATTC_OPT_BASE 0x60 /**< GATTC BLE Option base. */ 112 | #define BLE_GATTC_OPT_LAST 0x7F /**< GATTC BLE Option last. */ 113 | 114 | #define BLE_GATTS_OPT_BASE 0x80 /**< GATTS BLE Option base. */ 115 | #define BLE_GATTS_OPT_LAST 0x9F /**< GATTS BLE Option last. */ 116 | 117 | #define BLE_L2CAP_OPT_BASE 0xA0 /**< L2CAP BLE Option base. */ 118 | #define BLE_L2CAP_OPT_LAST 0xBF /**< L2CAP BLE Option last. */ 119 | 120 | 121 | #define BLE_CFG_INVALID 0x00 /**< Invalid BLE configuration. */ 122 | 123 | #define BLE_CFG_BASE 0x01 /**< Common BLE configuration base. */ 124 | #define BLE_CFG_LAST 0x1F /**< Common BLE configuration last. */ 125 | 126 | #define BLE_CONN_CFG_BASE 0x20 /**< BLE connection configuration base. */ 127 | #define BLE_CONN_CFG_LAST 0x3F /**< BLE connection configuration last. */ 128 | 129 | #define BLE_GAP_CFG_BASE 0x40 /**< GAP BLE configuration base. */ 130 | #define BLE_GAP_CFG_LAST 0x5F /**< GAP BLE configuration last. */ 131 | 132 | #define BLE_GATT_CFG_BASE 0x60 /**< GATT BLE configuration base. */ 133 | #define BLE_GATT_CFG_LAST 0x7F /**< GATT BLE configuration last. */ 134 | 135 | #define BLE_GATTC_CFG_BASE 0x80 /**< GATTC BLE configuration base. */ 136 | #define BLE_GATTC_CFG_LAST 0x9F /**< GATTC BLE configuration last. */ 137 | 138 | #define BLE_GATTS_CFG_BASE 0xA0 /**< GATTS BLE configuration base. */ 139 | #define BLE_GATTS_CFG_LAST 0xBF /**< GATTS BLE configuration last. */ 140 | 141 | #define BLE_L2CAP_CFG_BASE 0xC0 /**< L2CAP BLE configuration base. */ 142 | #define BLE_L2CAP_CFG_LAST 0xDF /**< L2CAP BLE configuration last. */ 143 | 144 | 145 | 146 | 147 | 148 | #ifdef __cplusplus 149 | } 150 | #endif 151 | #endif /* BLE_RANGES_H__ */ 152 | 153 | /** 154 | @} 155 | @} 156 | */ 157 | -------------------------------------------------------------------------------- /softdevice/include/nrf_error.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Nordic Semiconductor ASA 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, 6 | * are permitted provided that the following conditions are met: 7 | * 8 | * 1. Redistributions of source code must retain the above copyright notice, this 9 | * list of conditions and the following disclaimer. 10 | * 11 | * 2. Redistributions in binary form, except as embedded into a Nordic 12 | * Semiconductor ASA integrated circuit in a product or a software update for 13 | * such product, must reproduce the above copyright notice, this list of 14 | * conditions and the following disclaimer in the documentation and/or other 15 | * materials provided with the distribution. 16 | * 17 | * 3. Neither the name of Nordic Semiconductor ASA nor the names of its 18 | * contributors may be used to endorse or promote products derived from this 19 | * software without specific prior written permission. 20 | * 21 | * 4. This software, with or without modification, must only be used with a 22 | * Nordic Semiconductor ASA integrated circuit. 23 | * 24 | * 5. Any software provided in binary form under this license must not be reverse 25 | * engineered, decompiled, modified and/or disassembled. 26 | * 27 | * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS 28 | * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 29 | * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE 30 | * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE 31 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 32 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 33 | * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 34 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 35 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 36 | * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 37 | */ 38 | 39 | /** 40 | @defgroup nrf_error SoftDevice Global Error Codes 41 | @{ 42 | 43 | @brief Global Error definitions 44 | */ 45 | 46 | /* Header guard */ 47 | #ifndef NRF_ERROR_H__ 48 | #define NRF_ERROR_H__ 49 | 50 | #ifdef __cplusplus 51 | extern "C" { 52 | #endif 53 | 54 | /** @defgroup NRF_ERRORS_BASE Error Codes Base number definitions 55 | * @{ */ 56 | #define NRF_ERROR_BASE_NUM (0x0) ///< Global error base 57 | #define NRF_ERROR_SDM_BASE_NUM (0x1000) ///< SDM error base 58 | #define NRF_ERROR_SOC_BASE_NUM (0x2000) ///< SoC error base 59 | #define NRF_ERROR_STK_BASE_NUM (0x3000) ///< STK error base 60 | /** @} */ 61 | 62 | #define NRF_SUCCESS (NRF_ERROR_BASE_NUM + 0) ///< Successful command 63 | #define NRF_ERROR_SVC_HANDLER_MISSING (NRF_ERROR_BASE_NUM + 1) ///< SVC handler is missing 64 | #define NRF_ERROR_SOFTDEVICE_NOT_ENABLED (NRF_ERROR_BASE_NUM + 2) ///< SoftDevice has not been enabled 65 | #define NRF_ERROR_INTERNAL (NRF_ERROR_BASE_NUM + 3) ///< Internal Error 66 | #define NRF_ERROR_NO_MEM (NRF_ERROR_BASE_NUM + 4) ///< No Memory for operation 67 | #define NRF_ERROR_NOT_FOUND (NRF_ERROR_BASE_NUM + 5) ///< Not found 68 | #define NRF_ERROR_NOT_SUPPORTED (NRF_ERROR_BASE_NUM + 6) ///< Not supported 69 | #define NRF_ERROR_INVALID_PARAM (NRF_ERROR_BASE_NUM + 7) ///< Invalid Parameter 70 | #define NRF_ERROR_INVALID_STATE (NRF_ERROR_BASE_NUM + 8) ///< Invalid state, operation disallowed in this state 71 | #define NRF_ERROR_INVALID_LENGTH (NRF_ERROR_BASE_NUM + 9) ///< Invalid Length 72 | #define NRF_ERROR_INVALID_FLAGS (NRF_ERROR_BASE_NUM + 10) ///< Invalid Flags 73 | #define NRF_ERROR_INVALID_DATA (NRF_ERROR_BASE_NUM + 11) ///< Invalid Data 74 | #define NRF_ERROR_DATA_SIZE (NRF_ERROR_BASE_NUM + 12) ///< Invalid Data size 75 | #define NRF_ERROR_TIMEOUT (NRF_ERROR_BASE_NUM + 13) ///< Operation timed out 76 | #define NRF_ERROR_NULL (NRF_ERROR_BASE_NUM + 14) ///< Null Pointer 77 | #define NRF_ERROR_FORBIDDEN (NRF_ERROR_BASE_NUM + 15) ///< Forbidden Operation 78 | #define NRF_ERROR_INVALID_ADDR (NRF_ERROR_BASE_NUM + 16) ///< Bad Memory Address 79 | #define NRF_ERROR_BUSY (NRF_ERROR_BASE_NUM + 17) ///< Busy 80 | #define NRF_ERROR_CONN_COUNT (NRF_ERROR_BASE_NUM + 18) ///< Maximum connection count exceeded. 81 | #define NRF_ERROR_RESOURCES (NRF_ERROR_BASE_NUM + 19) ///< Not enough resources for operation 82 | 83 | #ifdef __cplusplus 84 | } 85 | #endif 86 | #endif // NRF_ERROR_H__ 87 | 88 | /** 89 | @} 90 | */ 91 | -------------------------------------------------------------------------------- /softdevice/include/nrf_error_sdm.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Nordic Semiconductor ASA 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, 6 | * are permitted provided that the following conditions are met: 7 | * 8 | * 1. Redistributions of source code must retain the above copyright notice, this 9 | * list of conditions and the following disclaimer. 10 | * 11 | * 2. Redistributions in binary form, except as embedded into a Nordic 12 | * Semiconductor ASA integrated circuit in a product or a software update for 13 | * such product, must reproduce the above copyright notice, this list of 14 | * conditions and the following disclaimer in the documentation and/or other 15 | * materials provided with the distribution. 16 | * 17 | * 3. Neither the name of Nordic Semiconductor ASA nor the names of its 18 | * contributors may be used to endorse or promote products derived from this 19 | * software without specific prior written permission. 20 | * 21 | * 4. This software, with or without modification, must only be used with a 22 | * Nordic Semiconductor ASA integrated circuit. 23 | * 24 | * 5. Any software provided in binary form under this license must not be reverse 25 | * engineered, decompiled, modified and/or disassembled. 26 | * 27 | * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS 28 | * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 29 | * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE 30 | * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE 31 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 32 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 33 | * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 34 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 35 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 36 | * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 37 | */ 38 | 39 | /** 40 | @addtogroup nrf_sdm_api 41 | @{ 42 | @defgroup nrf_sdm_error SoftDevice Manager Error Codes 43 | @{ 44 | 45 | @brief Error definitions for the SDM API 46 | */ 47 | 48 | /* Header guard */ 49 | #ifndef NRF_ERROR_SDM_H__ 50 | #define NRF_ERROR_SDM_H__ 51 | 52 | #include "nrf_error.h" 53 | 54 | #ifdef __cplusplus 55 | extern "C" { 56 | #endif 57 | 58 | #define NRF_ERROR_SDM_LFCLK_SOURCE_UNKNOWN (NRF_ERROR_SDM_BASE_NUM + 0) ///< Unknown LFCLK source. 59 | #define NRF_ERROR_SDM_INCORRECT_INTERRUPT_CONFIGURATION (NRF_ERROR_SDM_BASE_NUM + 1) ///< Incorrect interrupt configuration (can be caused by using illegal priority levels, or having enabled SoftDevice interrupts). 60 | #define NRF_ERROR_SDM_INCORRECT_CLENR0 (NRF_ERROR_SDM_BASE_NUM + 2) ///< Incorrect CLENR0 (can be caused by erroneous SoftDevice flashing). 61 | 62 | #ifdef __cplusplus 63 | } 64 | #endif 65 | #endif // NRF_ERROR_SDM_H__ 66 | 67 | /** 68 | @} 69 | @} 70 | */ 71 | -------------------------------------------------------------------------------- /softdevice/include/nrf_error_soc.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Nordic Semiconductor ASA 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, 6 | * are permitted provided that the following conditions are met: 7 | * 8 | * 1. Redistributions of source code must retain the above copyright notice, this 9 | * list of conditions and the following disclaimer. 10 | * 11 | * 2. Redistributions in binary form, except as embedded into a Nordic 12 | * Semiconductor ASA integrated circuit in a product or a software update for 13 | * such product, must reproduce the above copyright notice, this list of 14 | * conditions and the following disclaimer in the documentation and/or other 15 | * materials provided with the distribution. 16 | * 17 | * 3. Neither the name of Nordic Semiconductor ASA nor the names of its 18 | * contributors may be used to endorse or promote products derived from this 19 | * software without specific prior written permission. 20 | * 21 | * 4. This software, with or without modification, must only be used with a 22 | * Nordic Semiconductor ASA integrated circuit. 23 | * 24 | * 5. Any software provided in binary form under this license must not be reverse 25 | * engineered, decompiled, modified and/or disassembled. 26 | * 27 | * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS 28 | * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 29 | * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE 30 | * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE 31 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 32 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 33 | * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 34 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 35 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 36 | * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 37 | */ 38 | 39 | /** 40 | @addtogroup nrf_soc_api 41 | @{ 42 | @defgroup nrf_soc_error SoC Library Error Codes 43 | @{ 44 | 45 | @brief Error definitions for the SoC library 46 | 47 | */ 48 | 49 | /* Header guard */ 50 | #ifndef NRF_ERROR_SOC_H__ 51 | #define NRF_ERROR_SOC_H__ 52 | 53 | #include "nrf_error.h" 54 | #ifdef __cplusplus 55 | extern "C" { 56 | #endif 57 | 58 | /* Mutex Errors */ 59 | #define NRF_ERROR_SOC_MUTEX_ALREADY_TAKEN (NRF_ERROR_SOC_BASE_NUM + 0) ///< Mutex already taken 60 | 61 | /* NVIC errors */ 62 | #define NRF_ERROR_SOC_NVIC_INTERRUPT_NOT_AVAILABLE (NRF_ERROR_SOC_BASE_NUM + 1) ///< NVIC interrupt not available 63 | #define NRF_ERROR_SOC_NVIC_INTERRUPT_PRIORITY_NOT_ALLOWED (NRF_ERROR_SOC_BASE_NUM + 2) ///< NVIC interrupt priority not allowed 64 | #define NRF_ERROR_SOC_NVIC_SHOULD_NOT_RETURN (NRF_ERROR_SOC_BASE_NUM + 3) ///< NVIC should not return 65 | 66 | /* Power errors */ 67 | #define NRF_ERROR_SOC_POWER_MODE_UNKNOWN (NRF_ERROR_SOC_BASE_NUM + 4) ///< Power mode unknown 68 | #define NRF_ERROR_SOC_POWER_POF_THRESHOLD_UNKNOWN (NRF_ERROR_SOC_BASE_NUM + 5) ///< Power POF threshold unknown 69 | #define NRF_ERROR_SOC_POWER_OFF_SHOULD_NOT_RETURN (NRF_ERROR_SOC_BASE_NUM + 6) ///< Power off should not return 70 | 71 | /* Rand errors */ 72 | #define NRF_ERROR_SOC_RAND_NOT_ENOUGH_VALUES (NRF_ERROR_SOC_BASE_NUM + 7) ///< RAND not enough values 73 | 74 | /* PPI errors */ 75 | #define NRF_ERROR_SOC_PPI_INVALID_CHANNEL (NRF_ERROR_SOC_BASE_NUM + 8) ///< Invalid PPI Channel 76 | #define NRF_ERROR_SOC_PPI_INVALID_GROUP (NRF_ERROR_SOC_BASE_NUM + 9) ///< Invalid PPI Group 77 | 78 | #ifdef __cplusplus 79 | } 80 | #endif 81 | #endif // NRF_ERROR_SOC_H__ 82 | /** 83 | @} 84 | @} 85 | */ 86 | -------------------------------------------------------------------------------- /softdevice/include/nrf_svc.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Nordic Semiconductor ASA 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, 6 | * are permitted provided that the following conditions are met: 7 | * 8 | * 1. Redistributions of source code must retain the above copyright notice, this 9 | * list of conditions and the following disclaimer. 10 | * 11 | * 2. Redistributions in binary form, except as embedded into a Nordic 12 | * Semiconductor ASA integrated circuit in a product or a software update for 13 | * such product, must reproduce the above copyright notice, this list of 14 | * conditions and the following disclaimer in the documentation and/or other 15 | * materials provided with the distribution. 16 | * 17 | * 3. Neither the name of Nordic Semiconductor ASA nor the names of its 18 | * contributors may be used to endorse or promote products derived from this 19 | * software without specific prior written permission. 20 | * 21 | * 4. This software, with or without modification, must only be used with a 22 | * Nordic Semiconductor ASA integrated circuit. 23 | * 24 | * 5. Any software provided in binary form under this license must not be reverse 25 | * engineered, decompiled, modified and/or disassembled. 26 | * 27 | * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS 28 | * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 29 | * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE 30 | * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE 31 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 32 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 33 | * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 34 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 35 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 36 | * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 37 | */ 38 | 39 | #ifndef NRF_SVC__ 40 | #define NRF_SVC__ 41 | 42 | #include "stdint.h" 43 | 44 | #ifdef __cplusplus 45 | extern "C" { 46 | #endif 47 | 48 | /** @brief Supervisor call declaration. 49 | * 50 | * A call to a function marked with @ref SVCALL, will trigger a Supervisor Call (SVC) Exception. 51 | * The SVCs with SVC numbers 0x00-0x0F are forwared to the application. All other SVCs are handled by the SoftDevice. 52 | * 53 | * @param[in] number The SVC number to be used. 54 | * @param[in] return_type The return type of the SVC function. 55 | * @param[in] signature Function signature. The function can have at most four arguments. 56 | */ 57 | 58 | #ifdef SVCALL_AS_NORMAL_FUNCTION 59 | #define SVCALL(number, return_type, signature) return_type signature 60 | #else 61 | 62 | #ifndef SVCALL 63 | #if defined (__CC_ARM) 64 | #define SVCALL(number, return_type, signature) return_type __svc(number) signature 65 | #elif defined (__GNUC__) 66 | #ifdef __cplusplus 67 | #define GCC_CAST_CPP (uint16_t) 68 | #else 69 | #define GCC_CAST_CPP 70 | #endif 71 | #define SVCALL(number, return_type, signature) \ 72 | _Pragma("GCC diagnostic push") \ 73 | _Pragma("GCC diagnostic ignored \"-Wreturn-type\"") \ 74 | __attribute__((naked)) \ 75 | __attribute__((unused)) \ 76 | static return_type signature \ 77 | { \ 78 | __asm( \ 79 | "svc %0\n" \ 80 | "bx r14" : : "I" (GCC_CAST_CPP number) : "r0" \ 81 | ); \ 82 | } \ 83 | _Pragma("GCC diagnostic pop") 84 | 85 | #elif defined (__ICCARM__) 86 | #define PRAGMA(x) _Pragma(#x) 87 | #define SVCALL(number, return_type, signature) \ 88 | PRAGMA(swi_number = (number)) \ 89 | __swi return_type signature; 90 | #else 91 | #define SVCALL(number, return_type, signature) return_type signature 92 | #endif 93 | #endif // SVCALL 94 | 95 | #endif // SVCALL_AS_NORMAL_FUNCTION 96 | 97 | #ifdef __cplusplus 98 | } 99 | #endif 100 | #endif // NRF_SVC__ 101 | -------------------------------------------------------------------------------- /softdevice/s132_nrf52_7.3.0_license-agreement.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2007 - 2020, Nordic Semiconductor ASA 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, 5 | are permitted provided that the following conditions are met: 6 | 7 | 1. Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | 2. Redistributions in binary form, except as embedded into a Nordic 11 | Semiconductor ASA integrated circuit in a product or a software update for 12 | such product, must reproduce the above copyright notice, this list of 13 | conditions and the following disclaimer in the documentation and/or other 14 | materials provided with the distribution. 15 | 16 | 3. Neither the name of Nordic Semiconductor ASA nor the names of its 17 | contributors may be used to endorse or promote products derived from this 18 | software without specific prior written permission. 19 | 20 | 4. This software, with or without modification, must only be used with a 21 | Nordic Semiconductor ASA integrated circuit. 22 | 23 | 5. Any software provided in binary form under this license must not be reverse 24 | engineered, decompiled, modified and/or disassembled. 25 | 26 | THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS 27 | OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 28 | OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE 29 | DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE 30 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 32 | GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34 | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 35 | OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 36 | -------------------------------------------------------------------------------- /tools/battery-model.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brilliantlabsAR/monocle-micropython/4091ae6d61d7f733672557cb6d69b9cce14fbe71/tools/battery-model.xlsx -------------------------------------------------------------------------------- /tools/camera_test_script.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | import sys 3 | 4 | from bleak import BleakClient, BleakScanner 5 | from bleak.backends.characteristic import BleakGATTCharacteristic 6 | from bleak.backends.device import BLEDevice 7 | from bleak.backends.scanner import AdvertisementData 8 | 9 | from PIL import Image 10 | import io 11 | 12 | REPL_SERVICE_UUID = "6e400001-b5a3-f393-e0a9-e50e24dcca9e" 13 | REPL_TX_CHAR_UUID = "6e400002-b5a3-f393-e0a9-e50e24dcca9e" 14 | REPL_RX_CHAR_UUID = "6e400003-b5a3-f393-e0a9-e50e24dcca9e" 15 | 16 | DATA_SERVICE_UUID = "e5700001-7bac-429a-b4ce-57ff900f479d" 17 | DATA_TX_CHAR_UUID = "e5700002-7bac-429a-b4ce-57ff900f479d" 18 | DATA_RX_CHAR_UUID = "e5700003-7bac-429a-b4ce-57ff900f479d" 19 | 20 | file = [ 21 | """import bluetooth""", 22 | """import camera""", 23 | """import time""", 24 | """camera.capture()""", 25 | """time.sleep_ms(250)""", 26 | """def send(data):""", 27 | """ while True:""", 28 | """ try:""", 29 | """ bluetooth.send(data)""", 30 | """ break""", 31 | """ except OSError:""", 32 | """ pass""", 33 | """send("START")""", 34 | """while True:""", 35 | """ image_data = camera.read(bluetooth.max_length())""", 36 | """ if image_data == None:""", 37 | """ break""", 38 | """ send(image_data)""", 39 | """send("END")""", 40 | ] 41 | 42 | image_data = b"" 43 | 44 | 45 | async def main(): 46 | def match_repl_uuid(device: BLEDevice, adv: AdvertisementData): 47 | return REPL_SERVICE_UUID in adv.service_uuids 48 | 49 | def repl_rx(_: BleakGATTCharacteristic, data: bytearray): 50 | # print(data.decode("utf-8").strip("\r\n")) # Uncomment for debug 51 | pass 52 | 53 | def data_rx(_: BleakGATTCharacteristic, data: bytearray): 54 | global image_data 55 | if data == b"START": 56 | print("Downloading image data\n") 57 | 58 | elif data == b"END": 59 | print("Saving image") 60 | image = Image.open(io.BytesIO(bytes(image_data))) 61 | image.show() 62 | print("Done") 63 | sys.exit(0) 64 | 65 | else: 66 | image_data += data 67 | print(f"\033[FDownloaded {len(image_data)} bytes") 68 | 69 | print("Searching for device") 70 | 71 | device = await BleakScanner.find_device_by_filter(match_repl_uuid) 72 | 73 | if device is None: 74 | print("No device found") 75 | sys.exit(1) 76 | 77 | print("Connected") 78 | 79 | async with BleakClient(device) as c: 80 | await c.start_notify(REPL_RX_CHAR_UUID, repl_rx) 81 | await c.start_notify(DATA_RX_CHAR_UUID, data_rx) 82 | 83 | repl = c.services.get_service(REPL_SERVICE_UUID) 84 | repl_tx = repl.get_characteristic(REPL_TX_CHAR_UUID) 85 | 86 | await c.write_gatt_char(repl_tx, b"\x03\x01") 87 | await c.write_gatt_char(repl_tx, b"f=open('main.py', 'w')\x04") 88 | 89 | await c.write_gatt_char(repl_tx, b"f.write('''") 90 | 91 | for line in file: 92 | await c.write_gatt_char(repl_tx, line.encode() + b"\n") 93 | 94 | await c.write_gatt_char(repl_tx, b"''')\x04") 95 | 96 | await c.write_gatt_char(repl_tx, b"f.close()\x04") 97 | await c.write_gatt_char(repl_tx, b"\x04") 98 | 99 | while True: 100 | await asyncio.sleep(1) 101 | 102 | 103 | asyncio.run(main()) 104 | -------------------------------------------------------------------------------- /tools/decode_gowin_status.py: -------------------------------------------------------------------------------- 1 | """ 2 | Utility to convert the GOWIN status code into a human-readable 3 | description. 4 | 5 | http://cdn.gowinsemi.com.cn/UG290E.pdf 6 | """ 7 | import sys 8 | 9 | if len(sys.argv) != 2: 10 | print('usage: python3 tools/decode_gowin_status.py 0x0003F020') 11 | sys.exit(1) 12 | status = int(sys.argv[1], 0) 13 | 14 | bitfields = {} 15 | bitfields['0'] = {'high': False, 'desc': 'CRC valid'} 16 | bitfields['1'] = {'high': False, 'desc': 'Command valid'} 17 | bitfields['2'] = {'high': False, 'desc': 'Verify IDCODE valid'} 18 | bitfields['3'] = {'high': False, 'desc': 'Timeout not reached'} 19 | bitfields['12'] = {'high': True, 'desc': 'Gowin embedded flash valid (VLD)'} 20 | bitfields['13'] = {'high': True, 'desc': 'Done Final Status, loading successful'} 21 | bitfields['14'] = {'high': True, 'desc': 'Security Final, security enabled'} 22 | bitfields['15'] = {'high': True, 'desc': 'Ready Status Flag'} 23 | bitfields['16'] = {'high': True, 'desc': 'POR Status ("ERR" when RECONFIG_N is low)'} 24 | 25 | for i in bitfields: 26 | if (status >> int(i) & 1) == bitfields[i]['high']: 27 | res = 'OK' 28 | else: 29 | res = 'ERR' 30 | 31 | desc = bitfields[i]['desc'] 32 | print(f'{res:3} 1<<{i:2} {desc}') 33 | -------------------------------------------------------------------------------- /tools/fontdraw.py: -------------------------------------------------------------------------------- 1 | """ 2 | A demo script to test fontgen.py generated files 3 | """ 4 | 5 | import sys 6 | import struct 7 | 8 | INDEX_RECORD_SIZE = 64 // 8 9 | 10 | class Glyph: 11 | 12 | def __init__(self, file, offset): 13 | self.beg_x = 0 14 | self.beg_y = 0 15 | self.end_x = 0 16 | self.end_y = 0 17 | self.data = None 18 | self.file = file 19 | self.file.seek(offset) 20 | 21 | def read(self): 22 | # Read the glyph header 23 | self.beg_x, self.beg_y, self.len_x, self.len_y = self.file.read(4) 24 | 25 | # Compute the size to read including the last byte 26 | size = self.len_x * self.len_y 27 | size = (size + 7) // 8 28 | 29 | # Optimization: do not split the row/columns yet 30 | self.data = self.file.read(size) 31 | 32 | class Font: 33 | 34 | def __init__(self, path): 35 | self.file = open(path, "rb") 36 | 37 | # Read the index header: (u32)*2 38 | record = self.file.read(4 + 4) 39 | self.font_height, self.index_size = struct.unpack(">II", record) 40 | 41 | # Then read the index 42 | self.font_index = [] 43 | n = 0 44 | while n < self.index_size: 45 | # Parse a record from the file 46 | self.font_index.append(struct.unpack(">II", self.file.read(8))) 47 | n += 8 48 | 49 | def glyph_range(self, unicode): 50 | # Start searching from the middle of the file 51 | beg = 0 52 | end = len(self.font_index) - 1 53 | i = beg + (end - beg) // 2 54 | 55 | # Inline implementation of binary search to find the glyph 56 | while beg != end: 57 | 58 | # Decode the u8 and u24 out of the u32 59 | unicode_len = self.font_index[i][0] & 0xff 60 | unicode_start = self.font_index[i][0] >> 8 61 | 62 | # Should we search lower? 63 | if unicode < unicode_start: 64 | end = i 65 | 66 | # Should we search higher? 67 | elif unicode > unicode_start + unicode_len: 68 | beg = i 69 | 70 | # That's a hit! 71 | else: 72 | return unicode_start, self.font_index[i][1] 73 | 74 | # Adjust the probe 75 | i = beg + (end - beg) // 2 76 | 77 | return None 78 | 79 | def glyph(self, unicode): 80 | 81 | # Get the range to start scanning from 82 | range_start, range_address = self.glyph_range(unicode) 83 | 84 | # Scan through the data glyph per glyph 85 | glyph = Glyph(self.file, 4 + 4 + self.index_size + range_address) 86 | 87 | # Skip several glyphs until we are there 88 | for _ in range(unicode - range_start): 89 | glyph.read() 90 | glyph.read() 91 | 92 | return glyph 93 | 94 | def draw(self, glyph): 95 | n = 0 96 | for ch in glyph.data: 97 | for i in reversed(range(8)): 98 | print("#" if ch & (1 << i) else " ", end="") 99 | n += 1 100 | if n % glyph.len_x == 0: 101 | print("|") 102 | if n % glyph.len_x != 0: 103 | print('', end='\r') 104 | 105 | if __name__ == "__main__": 106 | font = Font(sys.argv[1]) 107 | for ch in sys.argv[2]: 108 | glyph = font.glyph(ord(ch)) 109 | print(ch) 110 | font.draw(glyph) 111 | -------------------------------------------------------------------------------- /tools/fontgen.py: -------------------------------------------------------------------------------- 1 | """ 2 | A font conversion tool taking BDF files as input and generating a custom 3 | compact bitmap format as output: 4 | 5 | font_format: (u32)reserved, (u32)index_size, font_index, font_data 6 | 7 | font_index: [ (u64)index_record ]*N 8 | index_record: (u24)unicode_start, (u8)unicode_count, (u32)glyph_address 9 | 10 | font_data: [ (u16)glyph_header, glyph_data ]*N 11 | glyph_header: (u8)beg_x, (u8)beg_y, (u8)len_x, (u8)len_y 12 | glyph_data: [ (u1)data_bit ]*N 13 | 14 | The font_index can be looked-up using a binary search to find a glyph block, 15 | and then scan the glyph data within it: 16 | 17 | If searching the unicode codepoint U+30F3: 18 | 19 | 1. A binary search would allow to find the range (U+3000, U+3100), 20 | which will point at the position in the glyph data 21 | 22 | 2. The glyphs start with a header specifying the size of the glpyh 23 | data, which allows to jump to the next header. 24 | 25 | 3. Starting from U+3000, 0x3F (63) glyphs need to be skipped, 26 | then the glyph data can be used to paint it. 27 | """ 28 | 29 | import struct 30 | import unicodedata 31 | import sys 32 | from bdfparser import Font 33 | 34 | font_index = bytearray() 35 | font_data = bytearray() 36 | 37 | def add_index_record(unicode_start, unicode_end, glyph_address): 38 | len = unicode_end - unicode_start + 1 39 | assert len > 0 and len <= 0xff 40 | 41 | font_index.extend(struct.pack(">I", unicode_start)[1:]) 42 | font_index.extend(struct.pack(">B", unicode_end - unicode_start + 1)) 43 | font_index.extend(struct.pack(">I", glyph_address)) 44 | 45 | def get_y_bounding_box(bitmap): 46 | beg_y = None 47 | end_y = 0 48 | for i, row in enumerate(bitmap): 49 | if '1' in row: 50 | if beg_y is None: 51 | beg_y = i 52 | end_y = i 53 | beg_y = beg_y or 0 54 | beg_y = 0 if end_y == beg_y else beg_y 55 | return beg_y, end_y + 1 56 | 57 | def get_x_bounding_box(bitmap): 58 | beg_x = None 59 | end_x = 0 60 | for i in range(len(bitmap[0])): 61 | if '1' in [x[i] for x in bitmap]: 62 | if beg_x is None: 63 | beg_x = i 64 | end_x = i 65 | return beg_x or 0, end_x + 1 66 | 67 | def add_glyph_header(beg_x, beg_y, end_x, end_y): 68 | font_data.append(beg_x) 69 | font_data.append(beg_y) 70 | font_data.append(end_x - beg_x) 71 | font_data.append(end_y - beg_y) 72 | 73 | def add_glyph_bitmap(bitmap): 74 | i = 0 75 | ch = 0 76 | for row in bitmap: 77 | for bit in row: 78 | assert bit in ('0', '1') 79 | 80 | ch <<= 1 81 | if bit == '1': 82 | ch |= 1 83 | i += 1 84 | if i % 8 == 0: 85 | font_data.append(ch) 86 | ch = 0 87 | 88 | # There is an incomplete byte after the rest 89 | if i % 8 > 0: 90 | font_data.append(ch << (8 - i % 8)) 91 | 92 | def add_glyph(glyph): 93 | # Get a Bitmap out of the font, cropping it as small as possible 94 | glyph_bitmap = glyph.draw(1) 95 | 96 | # Format the data into the bitmap, skipping the empty rows 97 | bitmap = [x.replace('2', '1') for x in glyph.draw(0).todata()] 98 | 99 | # Crop the top and bottom margins 100 | beg_y, end_y = get_y_bounding_box(bitmap) 101 | bitmap = bitmap[beg_y:end_y] 102 | 103 | # Crop the left and right margins 104 | beg_x, end_x = get_x_bounding_box(bitmap) 105 | bitmap = [row[beg_x:end_x] for row in bitmap] 106 | 107 | # Add the glyph metadata 108 | font_data.extend(bytes((beg_x, beg_y, end_x - beg_x, end_y - beg_y))) 109 | 110 | # Loop over every bit of every row and append them back-to-back 111 | add_glyph_bitmap(bitmap) 112 | 113 | if len(sys.argv) != 3: 114 | print("usage: {} source_file.bdf output_file.bin".format(sys.argv[0])) 115 | exit(1) 116 | 117 | font = Font(sys.argv[1]) 118 | 119 | unicode_start = 0 120 | unicode_count = 0 121 | glyph_address = 0 122 | 123 | # Add all glyphs one by one to the font_index and font_data bytearrays() 124 | unicode_prev = -1 125 | for glyph in font.iterglyphs(order=1): 126 | 127 | # The glyph data block is very straightforward, always the same: add the 128 | # glyph, but we must keep track of the address. 129 | add_glyph(glyph) 130 | 131 | # If no more room for the current codepoint, push the record, switch to 132 | # the next 133 | if unicode_prev >= 0: 134 | if glyph.cp() != unicode_prev + 1 or glyph.cp() >= unicode_start + 0xff: 135 | add_index_record(unicode_start, unicode_prev, glyph_address) 136 | glyph_address = address_prev 137 | unicode_start = glyph.cp() 138 | 139 | unicode_prev = glyph.cp() 140 | address_prev = len(font_data) 141 | 142 | add_index_record(unicode_start, unicode_prev, glyph_address) 143 | 144 | with open(sys.argv[2], "wb") as f: 145 | f.write(struct.pack(">I", 0)) 146 | f.write(struct.pack(">I", len(font_index))) 147 | f.write(font_index) 148 | f.write(font_data) 149 | -------------------------------------------------------------------------------- /tools/oled-configuration-tables.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brilliantlabsAR/monocle-micropython/4091ae6d61d7f733672557cb6d69b9cce14fbe71/tools/oled-configuration-tables.xlsx -------------------------------------------------------------------------------- /tools/serial_console.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | """ 3 | UART Service 4 | ------------- 5 | An example showing how to write a simple program using the Nordic Semiconductor 6 | (nRF) UART service. 7 | """ 8 | 9 | import asyncio 10 | import sys 11 | import os 12 | import tty 13 | import termios 14 | import binascii 15 | from itertools import count, takewhile 16 | from typing import Iterator 17 | 18 | from bleak import BleakClient, BleakScanner 19 | from bleak.backends.characteristic import BleakGATTCharacteristic 20 | from bleak.backends.device import BLEDevice 21 | from bleak.backends.scanner import AdvertisementData 22 | from bleak.uuids import register_uuids 23 | 24 | 25 | UART_SERVICE_UUID = "6e400001-b5a3-f393-e0a9-e50e24dcca9e" 26 | UART_TX_CHAR_UUID = "6e400002-b5a3-f393-e0a9-e50e24dcca9e" 27 | UART_RX_CHAR_UUID = "6e400003-b5a3-f393-e0a9-e50e24dcca9e" 28 | 29 | DATA_SERVICE_UUID = "e5700001-7bac-429a-b4ce-57ff900f479d" 30 | DATA_TX_CHAR_UUID = "e5700002-7bac-429a-b4ce-57ff900f479d" 31 | DATA_RX_CHAR_UUID = "e5700003-7bac-429a-b4ce-57ff900f479d" 32 | 33 | register_uuids({ 34 | DATA_SERVICE_UUID: "Monocle Raw Serivce", 35 | DATA_RX_CHAR_UUID: "Monocle Raw RX", 36 | DATA_TX_CHAR_UUID: "Monocle Raw TX", 37 | }) 38 | 39 | # You can get this function and more from the ``more-itertools`` package. 40 | def sliced(data: bytes, n: int) -> Iterator[bytes]: 41 | """ 42 | Slices *data* into chunks of size *n*. The last slice may be smaller than 43 | *n*. 44 | """ 45 | return takewhile(len, (data[i : i + n] for i in count(0, n))) 46 | 47 | 48 | async def repl_terminal(): 49 | """This is a simple "terminal" program that uses the Nordic Semiconductor 50 | (nRF) UART service. It reads from stdin and sends each line of data to the 51 | remote device. Any data received from the device is printed to stdout. 52 | """ 53 | 54 | def match_repl_uuid(device: BLEDevice, adv: AdvertisementData): 55 | # This assumes that the device includes the UART service UUID in the 56 | # advertising data. This test may need to be adjusted depending on the 57 | # actual advertising data supplied by the device. 58 | sys.stderr.write(f"uuids={adv.service_uuids}\n") 59 | return UART_SERVICE_UUID.lower() in adv.service_uuids 60 | 61 | def handle_disconnect(_: BleakClient): 62 | sys.stderr.write("\r\nDevice was disconnected.\r\n") 63 | 64 | # cancelling all tasks effectively ends the program 65 | for task in asyncio.all_tasks(): 66 | task.cancel() 67 | 68 | def handle_repl_rx(_: BleakGATTCharacteristic, data: bytearray): 69 | stdout.write(data) 70 | stdout.flush() 71 | 72 | def handle_data_rx(_: BleakGATTCharacteristic, data: bytearray): 73 | hex = data.hex(' ', 1) 74 | sys.stderr.write(f'RX: {hex} {data}\r\n') 75 | sys.stderr.flush() 76 | 77 | def prompt(): 78 | global saved_term 79 | if sys.stdin.isatty(): 80 | termios.tcsetattr(0, termios.TCSANOW, saved_term) 81 | line = sys.stdin.buffer.readline() 82 | tty.setraw(0) 83 | return line 84 | 85 | stdout = os.fdopen(1, 'wb') 86 | 87 | device = await BleakScanner.find_device_by_filter(match_repl_uuid) 88 | if device is None: 89 | sys.stderr.write("no matching device found\n") 90 | sys.exit(1) 91 | else: 92 | sys.stderr.write(f"connected\n") 93 | sys.stderr.write('Ctrl-D: Reboot in normal mode\n') 94 | sys.stderr.write('Ctrl-\\: Reboot in safe mode\n') 95 | sys.stderr.write('Ctrl-C: Cancel ongoing script\n') 96 | sys.stderr.write('Ctrl-E, "code", Ctrl-D: paste mode\n') 97 | sys.stderr.write('Ctrl-V, "text", Enter: send to raw Bluetooth service\n') 98 | 99 | async with BleakClient(device, disconnected_callback=handle_disconnect) as client: 100 | await client.start_notify(UART_RX_CHAR_UUID, handle_repl_rx) 101 | await client.start_notify(DATA_RX_CHAR_UUID, handle_data_rx) 102 | 103 | loop = asyncio.get_running_loop() 104 | repl = client.services.get_service(UART_SERVICE_UUID) 105 | data = client.services.get_service(DATA_SERVICE_UUID) 106 | repl_tx_char = repl.get_characteristic(UART_TX_CHAR_UUID) 107 | data_tx_char = data.get_characteristic(DATA_TX_CHAR_UUID) 108 | 109 | # set the terminal to raw I/O: no buffering 110 | if sys.stdin.isatty(): 111 | tty.setraw(0) 112 | 113 | # Infinite loop to read the input character until the end 114 | while True: 115 | ch = await loop.run_in_executor(None, sys.stdin.buffer.read, 1) 116 | if not ch: # EOF 117 | break 118 | if ch == b'\x16': # Ctrl-V 119 | sys.stderr.write(f'TX: ') 120 | sys.stderr.flush() 121 | line = await loop.run_in_executor(None, prompt) 122 | await client.write_gatt_char(data_tx_char, line.rstrip()) 123 | else: 124 | await client.write_gatt_char(repl_tx_char, ch) 125 | 126 | 127 | if __name__ == "__main__": 128 | # save the terminal I/O state 129 | if sys.stdin.isatty(): 130 | saved_term = termios.tcgetattr(0) 131 | 132 | try: 133 | asyncio.run(repl_terminal()) 134 | except asyncio.CancelledError: 135 | # task is cancelled on disconnect, so we ignore this error 136 | pass 137 | 138 | # restore terminal I/O state 139 | if sys.stdin.isatty(): 140 | termios.tcsetattr(0, termios.TCSANOW, saved_term) 141 | -------------------------------------------------------------------------------- /tools/upload_file.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | """ 3 | An example showing how to connect to the Monocle and store a file. 4 | """ 5 | 6 | import asyncio 7 | import sys 8 | import os 9 | 10 | from bleak import BleakClient, BleakScanner 11 | from bleak.backends.characteristic import BleakGATTCharacteristic 12 | from bleak.backends.device import BLEDevice 13 | from bleak.backends.scanner import AdvertisementData 14 | from bleak.uuids import register_uuids 15 | 16 | 17 | class MonocleScript: 18 | UART_SERVICE_UUID = "6e400001-b5a3-f393-e0a9-e50e24dcca9e" 19 | UART_RX_CHAR_UUID = "6e400002-b5a3-f393-e0a9-e50e24dcca9e" 20 | UART_TX_CHAR_UUID = "6e400003-b5a3-f393-e0a9-e50e24dcca9e" 21 | 22 | DATA_SERVICE_UUID = "e5700001-7bac-429a-b4ce-57ff900f479d" 23 | DATA_RX_CHAR_UUID = "e5700002-7bac-429a-b4ce-57ff900f479d" 24 | DATA_TX_CHAR_UUID = "e5700003-7bac-429a-b4ce-57ff900f479d" 25 | 26 | def __init__(self): 27 | register_uuids({ 28 | self.DATA_SERVICE_UUID: "Monocle Data Serivce", 29 | self.DATA_TX_CHAR_UUID: "Monocle Data RX", 30 | self.DATA_RX_CHAR_UUID: "Monocle Data TX", 31 | }) 32 | 33 | 34 | @classmethod 35 | async def run(cls, *args): 36 | self = cls() 37 | 38 | device = await BleakScanner.find_device_by_filter(self.match_uart_uuid) 39 | if device is None: 40 | print("no matching device found\n") 41 | exit(1) 42 | 43 | async with BleakClient(device, disconnected_callback=self.handle_disconnect) as c: 44 | self.client = c 45 | await self.init_uart_service() 46 | await self.init_data_service() 47 | await self.set_monocle_raw_mode() 48 | await self.script(*args) 49 | await self.client.write_gatt_char(self.uart_rx_char, b"\x02") 50 | 51 | def log(self, msg): 52 | if "DEBUG" in os.environ: 53 | print(msg, flush=True) 54 | 55 | def match_uart_uuid(self, device:BLEDevice, adv:AdvertisementData): 56 | self.log(f"uuids={adv.service_uuids}") 57 | return self.UART_SERVICE_UUID.lower() in adv.service_uuids 58 | 59 | def handle_disconnect(self, _:BleakClient): 60 | self.log("Device was disconnected.") 61 | for task in asyncio.all_tasks(): 62 | task.cancel() 63 | 64 | def handle_uart_rx(self, _:BleakGATTCharacteristic, data:bytearray): 65 | # Here, handle data sent by the Monocle with `print()` 66 | self.uart_rx_buf.extend(data) 67 | 68 | def handle_data_rx(self, _:BleakGATTCharacteristic, data:bytearray): 69 | # Here, handle data sent by the Monocle with `bluetooth.send()` 70 | self.data_rx_buf.extend(data) 71 | 72 | async def getchar_uart(self): 73 | while len(self.uart_rx_buf) == 0: 74 | await asyncio.sleep(0.01) 75 | c = self.uart_rx_buf[0] 76 | del self.uart_rx_buf[0] 77 | return c 78 | 79 | async def getchar_data(self): 80 | while len(self.data_rx_buf) == 0: 81 | await asyncio.sleep(0.01) 82 | c = self.data_rx_buf[0] 83 | del self.data_rx_buf[0] 84 | return c 85 | 86 | async def getline_uart(self, delim=b"\n"): 87 | buf = bytearray() 88 | while not (c := await self.getchar_uart()) in delim: 89 | buf.append(c) 90 | return buf 91 | 92 | async def getline_data(self, delim="\n"): 93 | buf = bytearray() 94 | while not (c := await self.getchar_uart()) in delim: 95 | buf.append(c) 96 | return buf 97 | 98 | async def send_command(self, cmd): 99 | await self.client.write_gatt_char(self.uart_rx_char, cmd.encode("ascii") + b"\x04") 100 | while True: 101 | resp = await self.getline_uart(delim=b"\r\n\x04") 102 | if resp != b"" and resp != b">": 103 | break 104 | assert resp == b">OK" 105 | 106 | async def init_uart_service(self): 107 | await self.client.start_notify(self.UART_TX_CHAR_UUID, self.handle_uart_rx) 108 | uart_service = self.client.services.get_service(self.UART_SERVICE_UUID) 109 | self.uart_rx_char = uart_service.get_characteristic(self.UART_RX_CHAR_UUID) 110 | self.uart_rx_buf = bytearray() 111 | 112 | async def init_data_service(self): 113 | await self.client.start_notify(self.DATA_TX_CHAR_UUID, self.handle_data_rx) 114 | data_service = self.client.services.get_service(self.DATA_SERVICE_UUID) 115 | self.data_rx_char = data_service.get_characteristic(self.DATA_RX_CHAR_UUID) 116 | self.data_rx_last = None 117 | 118 | async def set_monocle_raw_mode(self): 119 | await self.client.write_gatt_char(self.uart_rx_char, b"\x01 \x04") 120 | while await self.getline_uart(delim=b"\r\n\x04") != b">OK": 121 | pass 122 | 123 | 124 | class UploadFileScript(MonocleScript): 125 | """ 126 | Example application: upload a file to the Monocle 127 | """ 128 | async def script(self, file): 129 | print(f"uploading {file} ", end="") 130 | await self.send_command(f"f = open('{file}', 'wb')") 131 | with open(file, "rb") as f: 132 | while data := f.read(100): 133 | print(end=".", flush=True) 134 | await self.send_command(f"f.write({bytes(data).__repr__()})") 135 | await self.send_command("f.close()") 136 | print(" done") 137 | 138 | if __name__ == "__main__": 139 | for file in sys.argv[1:]: 140 | try: 141 | asyncio.run(UploadFileScript.run(file)) 142 | except asyncio.exceptions.CancelledError: 143 | pass 144 | -------------------------------------------------------------------------------- /tools/vgrs.py: -------------------------------------------------------------------------------- 1 | import sys 2 | from PIL import Image 3 | 4 | WIDTH = 640 5 | HEIGHT = 400 6 | DEPTH = 3 7 | 8 | # the first line has the color palette in a list of "key=value" strings 9 | # separated by space 10 | palette = {} 11 | buf = bytes.fromhex(sys.stdin.readline().rstrip()) 12 | it = iter(buf) 13 | 14 | # Decode the RGB palette coming as first line 15 | i = 0 16 | assert(next(it) == 0x00) # Skip address field, first byte 17 | assert(next(it) == 0x00) # Skip address field, second byte 18 | while True: 19 | try: 20 | palette[i] = bytes((next(it), next(it), next(it))) 21 | except StopIteration: 22 | break 23 | i += 1 24 | print(palette) 25 | 26 | # Read input hexadecimal string and decode it into a bytearray 27 | buf = bytearray() 28 | for line in sys.stdin.readlines(): 29 | buf.extend(bytes.fromhex(line.rstrip())) 30 | 31 | # Prepare a memory canvas to store the image to be drawn 32 | rgb = bytearray(WIDTH * HEIGHT * DEPTH) 33 | 34 | # Cursor drawing onto the RGB canvas 35 | cur_x = 0 36 | cur_y = 0 37 | cur_color = b'\x00\x00\x00' 38 | 39 | def cmd_PutSpan(arg): 40 | global cur_x 41 | global cur_y 42 | global cur_color 43 | 44 | for i in range(arg): 45 | assert cur_x < WIDTH * 16 46 | rgb[cur_y * WIDTH * DEPTH + cur_x // 16 * DEPTH + 0] = cur_color[0] 47 | rgb[cur_y * WIDTH * DEPTH + cur_x // 16 * DEPTH + 1] = cur_color[1] 48 | rgb[cur_y * WIDTH * DEPTH + cur_x // 16 * DEPTH + 2] = cur_color[2] 49 | cur_x += 1 50 | 51 | def cmd_SetColor(arg): 52 | global cur_color 53 | 54 | # Update the current color using an index from the palette 55 | cur_color = palette[arg] 56 | 57 | def cmd_SkipColumns(arg): 58 | global cur_x 59 | 60 | # No data for these many pixels 61 | cur_x += arg 62 | 63 | def cmd_JumpToLine(arg): 64 | global cur_x 65 | global cur_y 66 | 67 | # No data for these many lines 68 | cur_x = 0 69 | cur_y = arg 70 | 71 | def cmd_NextLinePos(arg): 72 | global cur_x 73 | global cur_y 74 | 75 | # Jump to the column given on the next row 76 | cur_x = arg 77 | cur_y += 1 78 | 79 | # iterate through pair of bytes, forming an uint16_t containing a command 80 | it = iter(buf) 81 | while True: 82 | try: 83 | b1 = next(it) 84 | b2 = next(it) 85 | except StopIteration: 86 | break 87 | num = (b1 << 8) | b2 88 | cmd = (b1 & 0b11110000) >> 4 89 | 90 | print(f"{b1:02X} {b2:02X} ", end="") 91 | 92 | # dispatch the command to draw on the canvas accordingly 93 | 94 | if cmd & 0b1000 == 0: 95 | arg1 = (num & 0b_01111111_00000000) >> 8 96 | arg2 = (num & 0b_00000000_11111111) 97 | cmd_SetColor(arg1) 98 | cmd_PutSpan(arg2) 99 | print(f"SetColor: {list(cur_color)}; PutSpan: 0x{arg2:X}") 100 | 101 | elif cmd == 0x8 or cmd == 0x9: 102 | arg = num & 0b_00011111_11111111 103 | cmd_SkipColumns(arg) 104 | print(f"SkipColumns: 0x{arg:X}") 105 | 106 | elif cmd == 0xA or cmd == 0xB: 107 | arg = num & 0b_00011111_11111111 108 | cmd_NextLinePos(arg) 109 | print(f"NextLinePos: 0x{arg:X}") 110 | 111 | elif cmd == 0xC: 112 | arg = num & 0b_00001111_11111111 113 | cmd_PutSpan(arg) 114 | print(f"PutSpan: 0x{arg:X}") 115 | 116 | elif cmd == 0xF: 117 | arg = num & 0b_00001111_11111111 118 | cmd_JumpToLine(arg) 119 | print(f"JumpToLine: 0x{arg:X}") 120 | 121 | else: 122 | print("") 123 | 124 | # save the result as PNG image 125 | im = Image.frombuffer('RGB', (WIDTH, HEIGHT), rgb, 'raw', 'RGB', 0, 1) 126 | im.save('vgrs.png') 127 | --------------------------------------------------------------------------------