Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions mcu_client/nrf5340_ble_simulator/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ add_subdirectory(src/mos_components/mos_pdm)
add_subdirectory(src/mos_components/mos_battery)
add_subdirectory(src/mos_components/mos_button)
add_subdirectory(src/mos_components/mos_interrupt)
add_subdirectory(src/mos_components/mos_font_storage)
add_subdirectory(src/mos_components/mos_lvgl_display)
add_subdirectory(src/mos_components/mos_jlink_usb_switch)
add_subdirectory(src/mos_components/mos_dfu_progress)
Expand All @@ -32,6 +33,7 @@ target_include_directories(app PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src)

target_sources(app PRIVATE
src/main.c
src/shell_font_storage.c
src/shell_display_control.c
src/shell_opt3006.c
src/shell_battery_control.c
Expand Down
49 changes: 49 additions & 0 deletions mcu_client/nrf5340_ble_simulator/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,55 @@ config USER_STEREO_2RX_L
config USER_STEREO_2RX_LR
bool "encode fifo enable"
default n

config FONT_STORAGE_LOAD_AT_RUNTIME
bool "Load CJK font from external flash (font_storage) at runtime"
default n
depends on LVGL && FLASH_MAP
help
When enabled, display_get_font(\"cjk\") loads a LVGL binfont from the
font_storage partition on first use.

config FONT_STORAGE_FILE_SIZE
int "Font storage file size (bytes, 0 = partition size)"
default 0
depends on LVGL && FLASH_MAP
help
Size of the .bin font in font_storage. If 0, use partition size.

config FONT_STORAGE_USE_XIP
bool "Use XIP address for font buffer (no RAM copy)"
default n
depends on LVGL && FLASH_MAP
help
Use external flash XIP address (0x10000000 + PM_FONT_STORAGE_ADDRESS)
as the binfont buffer to avoid RAM copy.

config FONT_STORAGE_USE_PARTITION_2
bool "Use font_storage2 partition for font data"
default n
depends on LVGL && FLASH_MAP
help
When enabled, load font data from the font_storage2 partition instead
of font_storage. This is useful when you split fonts across partitions.

config BINFONT_GLYPH_ORDER_WHXY
bool "Use glyf order (adv,W,H,X,Y) instead of spec (adv,X,Y,W,H)"
default n
depends on LVGL && FLASH_MAP
help
LVGL font_spec: advanceWidth, BBox X, Y, Width, Height. Some tools
output (adv, Width, Height, X, Y). Enable this if you get bitmap
overflow with an uncompressed binfont.

config BINFONT_A1_INVERT
bool "Invert 1bpp (A1) glyph bits for correct contrast"
default n
depends on LVGL && FLASH_MAP
help
When enabled, invert each byte of the A1 bitmap. Try this if 1bpp
text appears faint or blurry (font may use 0=ink vs LVGL 1=ink).
Disable if text becomes inverted or wrong.
endmenu

# Include custom driver module Kconfig (projector display)
Expand Down
6 changes: 3 additions & 3 deletions mcu_client/nrf5340_ble_simulator/app.overlay
Original file line number Diff line number Diff line change
Expand Up @@ -205,12 +205,12 @@ zephyr_udc0: &usbd {
writeoc = "pp4io";
/* MX25U256 supports all readoc options */
readoc = "read4io";
sck-frequency = <32000000>;//最高 48Mhz
sck-frequency = <8000000>;//最高 48Mhz
address-size-32;
enter-4byte-addr = <0xb7>;
jedec-id = [ c2 25 39 ];
sfdp-bfp = [ e5 20 fb ff ff ff ff 0f 44 eb 08 6b 08 3b 04 bb fe ff ff ff ff ff 00 ff ff ff 44 eb 0c 20 0f 52 10 d8 00 ff 25 52 dd 00 84 a5 04 e2 44 03 17 38 30 b0 30 b0 f7 bd d5 5c 4a 9e 29 ff f0 50 f9 85 ];
size = <0x2000000>;// 32M
size = <0x10000000>;// 32MB
has-dpd;
t-enter-dpd = <10000>;
t-exit-dpd = <35000>;
Expand All @@ -235,4 +235,4 @@ zephyr_udc0: &usbd {
};
&gpio1 {
sense-edge-mask = <0x0>;
};
};
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,13 @@ config CUSTOM_A6N_INIT_PRIORITY
config CUSTOM_A6N_LOG_LEVEL
int "Logging level"
default 3
range 0 4
range 0 4

config A6N_I1_POLARITY_INVERT
bool "Invert 1bpp→4bpp LUT (1=bright, 0=dark) for clearer text"
default n
help
When set, framebuffer bit 1 → bright (0x0F), bit 0 → dark (0x00).
When clear (default), bit 0 → bright, bit 1 → dark.
Try enabling if 1bpp text appears faint or unclear; then set
display_config invert_colors=0 so text uses white (1) in the buffer.
24 changes: 17 additions & 7 deletions mcu_client/nrf5340_ble_simulator/pm_static.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Static partition layout (external flash)
# 静态分区表(外置 Flash)
# mcuboot_secondary: OTA 备用槽 | font_storage: 中文字库 8MB | user_storage: 用户空间(剩余)
# mcuboot_secondary / font_storage (2MB) / font_storage2 (2MB) / user_storage

mcuboot_secondary:
address: 0x0
Expand All @@ -11,16 +11,26 @@ mcuboot_secondary:
- mcuboot_primary
size: 0xf0000

# 中文字库区:8 MB
# 18px binfont, 2MB
font_storage:
address: 0xf0000
end_address: 0x8f0000
device: DT_CHOSEN(nordic_pm_ext_flash)
end_address: 0x2f0000
region: external_flash
size: 0x800000
size: 0x200000

# 用户空间:剩余约 23 MB(0x8f0000 ~ 0x2000000)
# 20px binfont, 2MB
font_storage2:
address: 0x2f0000
device: DT_CHOSEN(nordic_pm_ext_flash)
end_address: 0x4f0000
region: external_flash
size: 0x200000

# user_storage (0x4f0000 ~ 0x2000000)
user_storage:
address: 0x8f0000
address: 0x4f0000
device: DT_CHOSEN(nordic_pm_ext_flash)
end_address: 0x2000000
region: external_flash
size: 0x1710000
size: 0x1b10000
28 changes: 27 additions & 1 deletion mcu_client/nrf5340_ble_simulator/prj.conf
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ CONFIG_MCUMGR_GRP_IMG_STATUS_HOOKS=y
CONFIG_MCUMGR_GRP_ZBASIC=y
CONFIG_MCUMGR_GRP_ZBASIC_STORAGE_ERASE=y
CONFIG_MCUMGR_GRP_OS=y
CONFIG_MCUMGR_GRP_OS_RESET_MS=250
# BLE signing (AES-CMAC) - required when bonding is enabled, fixes:
# bt_gatt: Unable to import the key for AES CMAC -134
# main: Chunk send failed / Final failure at offset=0
Expand Down Expand Up @@ -127,6 +128,27 @@ CONFIG_NANOPB=y
CONFIG_DISPLAY=y
CONFIG_DISPLAY_LOG_LEVEL_ERR=y
CONFIG_LVGL=y

CONFIG_FONT_STORAGE_LOAD_AT_RUNTIME=y
# XIP: font stays in external flash, official LVGL binfont loader uses pointer (no large RAM copy)
CONFIG_FONT_STORAGE_USE_XIP=y

CONFIG_FONT_STORAGE_FILE_SIZE=1158000

CONFIG_FONT_STORAGE_USE_PARTITION_2=n
# Keep OFF: with A1 invert the font shape can disappear (font uses 1=ink; LVGL expects 1=ink)
# CONFIG_BINFONT_A1_INVERT is not set

CONFIG_LV_USE_FS_MEMFS=y

CONFIG_FLASH_INIT_PRIORITY=40

CONFIG_NORDIC_QSPI_NOR=y
CONFIG_NORDIC_QSPI_NOR_XIP=y
CONFIG_NORDIC_QSPI_NOR_FLASH_LAYOUT_PAGE_SIZE=4096
CONFIG_NORDIC_QSPI_NOR_STACK_WRITE_BUFFER_SIZE=16

CONFIG_LV_FS_MEMFS_LETTER=65
CONFIG_LV_COLOR_DEPTH_1=y
CONFIG_LV_Z_MEM_POOL_SIZE=65536
CONFIG_LV_USE_LABEL=y
Expand All @@ -147,6 +169,8 @@ CONFIG_LV_Z_VDB_CUSTOM_SECTION=n

# Enable custom A6N Display Driver for projector testing
CONFIG_CUSTOM_A6N=y
# Keep OFF: with polarity invert the font shape can disappear (restore 0=bright, invert_colors=1)
# CONFIG_A6N_I1_POLARITY_INVERT is not set

# SPI Support for Display with High-Frequency Optimization
CONFIG_SPI=y
Expand All @@ -171,6 +195,7 @@ CONFIG_LV_FONT_FMT_TXT_LARGE=y
# Enable extended ASCII and Unicode support
CONFIG_LV_TXT_ENC_UTF8=y


# Enable only essential Chinese CJK font (14px sufficient for SSD1306)
# CONFIG_LV_FONT_SIMSUN_14_CJK=y
# CONFIG_LV_FONT_SIMSUN_16_CJK=y # Disabled to save ~70KB
Expand Down Expand Up @@ -254,4 +279,5 @@ CONFIG_NRF_FUEL_GAUGE=y
CONFIG_NRF_FUEL_GAUGE_VARIANT_SECONDARY_CELL=y
# CONFIG_LSM6DSV16X=y # Disabled - using raw I2C mode, alias points to i2c2 bus directly
# CONFIG_LIS2MDL=y

# Ensure external flash base is 0x0
CONFIG_PM_EXTERNAL_FLASH_BASE=0x0
46 changes: 46 additions & 0 deletions mcu_client/nrf5340_ble_simulator/scripts/FONT_FLASH_QSPI.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# Flash Font to QSPI (XIP Address)

Convert an LVGL binfont (`.bin`) to Intel HEX and program it onto the nRF5340 DK external QSPI Flash for XIP (execute-in-place) use.

## Prerequisites

- **ARM GCC** installed (`arm-none-eabi-objcopy` on PATH)
- **nRF Util** installed (`nrfutil`)
- Device connected via USB; **serial number** known (e.g. `771549234`)
- Font XIP base address matches the project (example `0x100f0000`; see `pm_static.yml` / Kconfig)

## Step 1: BIN → HEX (with XIP address)

Convert the font binary to Intel HEX and set the load address in QSPI:

```bash
arm-none-eabi-objcopy -I binary -O ihex \
--change-addresses 0x100f0000 \
mcu_client/nrf5340_ble_simulator/scripts/font_zh_en_18_lvgl_1.bin \
mcu_client/nrf5340_ble_simulator/scripts/font_zh_en_18_lvgl_1.hex
```

- `--change-addresses 0x100f0000`: Must match the font XIP base address in firmware (see `pm_static.yml` font_storage or Kconfig `PM_FONT_STORAGE_ADDRESS`). Change if your partition uses a different address.
- Paths above are **relative to the repo root**; run from the repo root or use absolute paths as needed.

## Step 2: Program to device

Program the HEX to external QSPI with nrfutil:

```bash
nrfutil device --x-ext-mem-config-file mcu_client/nrf5340_ble_simulator/scripts/nrf5340dk_qspi_ext_mem_config.json program \
--firmware mcu_client/nrf5340_ble_simulator/scripts/font_zh_en_18_lvgl_1.hex \
--serial-number 771549234 \
--options ext_mem_erase_mode=ERASE_RANGES_TOUCHED_BY_FIRMWARE,chip_erase_mode=ERASE_NONE,verify=VERIFY_READ
```

- `--serial-number`: Use your device’s serial (run `nrfutil device list` to find it).
- `ext_mem_erase_mode=ERASE_RANGES_TOUCHED_BY_FIRMWARE`: Erase only QSPI ranges covered by the HEX.
- `chip_erase_mode=ERASE_NONE`: Do not full-chip erase.
- `verify=VERIFY_READ`: Verify after programming by reading back.

## Troubleshooting

- **Wrong address**: If the firmware cannot read the font, check that `--change-addresses` matches the font_storage base in `pm_static.yml` / Kconfig.
- **Device not found**: Run `nrfutil device list` to confirm the device and serial number.
- **Permissions / drivers**: On Linux you may need udev rules or sudo; on Windows install the J-Link driver.
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"firmware_config": {
"peripheral": "QSPI"
},
"pins": {
"sck": 17,
"csn": 18,
"io0": 13,
"io1": 14,
"io2": 15,
"io3": 16
},
"flash_size": 33554432,
"sck_frequency": 8000000,
"address_mode": "MODE32BIT",
"readoc": "READ4IO",
"writeoc": "PP4IO",
"pp_size": "PPSIZE256",
"sck_delay": 128,
"rx_delay": 2,
"page_size": 4096
}
10 changes: 8 additions & 2 deletions mcu_client/nrf5340_ble_simulator/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -156,8 +156,13 @@ static void disconnected(struct bt_conn* conn, uint8_t reason)
bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));

LOG_INF("Disconnected: %s, reason 0x%02x %s", addr, reason, bt_hci_err_to_str(reason));

bool was_connected = get_ble_connected_status();
set_ble_connected_status(false);
display_show_welcome_screen(); /* 断开后自动回到欢迎界面 | Return to welcome screen on disconnect */
if (was_connected)
{
display_show_welcome_screen(); /* 断开后自动回到欢迎界面 | Return to welcome screen on disconnect */
}
if (auth_conn)
{
bt_conn_unref(auth_conn);
Expand Down Expand Up @@ -286,7 +291,8 @@ static void bt_receive_cb(struct bt_conn* conn, const uint8_t* const data, uint1
protobuf_analyze_message(data, len);

// Generate and send echo response
uint8_t echo_buffer[128];
static uint8_t echo_buffer[251];
memset(echo_buffer, 0, sizeof(echo_buffer));
int echo_len = protobuf_generate_echo_response(data, len, echo_buffer, sizeof(echo_buffer));

if (echo_len > 0)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,15 @@
/*
* Copyright (c) MentraOS Contributors 2025
* SPDX-License-Identifier: Apache-2.0
* @Author : Cole
* @Date : 2026-01-28 14:44:46
* @LastEditTime : 2026-02-07 15:00:36
* @FilePath : mos_fuel_gauge.c
* @Description :
*
* Copyright (c) MentraOS Contributors 2026
* SPDX-License-Identifier: Apache-2.0
Comment on lines +2 to +9
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove this please.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

okay

*/


#include "mos_fuel_gauge.h"
#include "protobuf_handler.h" /* sync SoC & charging to display/BLE */
#include "mos_lvgl_display.h" /* display_request_welcome_battery_refresh */
Expand All @@ -17,7 +24,7 @@
#include <zephyr/logging/log.h>
#include <errno.h>

LOG_MODULE_REGISTER(mos_fuel_gauge, LOG_LEVEL_DBG);
LOG_MODULE_REGISTER(mos_fuel_gauge, LOG_LEVEL_WRN);

/* nPM1300 CHARGER.BCHGCHARGESTATUS register bitmasks / nPM1300充电状态寄存器位掩码 */
#define NPM1300_CHG_STATUS_COMPLETE_MASK BIT(1) /* Charge complete / 充电完成 */
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Copyright (c) MentraOS Contributors
# SPDX-License-Identifier: Apache-2.0

target_include_directories(app PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include)
target_sources(app PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/src/mos_font_storage.c
${CMAKE_CURRENT_SOURCE_DIR}/src/mos_binfont_lvgl.c
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/***
* @Author : Cole
* @Date : 2026-02-05 14:53:31
* @LastEditTime : 2026-02-10 15:46:31
* @FilePath : mos_binfont_lvgl.h
* @Description :
* @
* @ Copyright (c) MentraOS Contributors 2026
* @ SPDX-License-Identifier: Apache-2.0
*/

#ifndef MOS_BINFONT_LVGL_H
#define MOS_BINFONT_LVGL_H

#include <stdbool.h>
#include <stdint.h>

#if defined(CONFIG_LVGL)
#include <lvgl.h>

/**
* 获取自定义中文字体实例
* @return LVGL字体指针,如果初始化失败返回NULL
*/
const lv_font_t* mos_binfont_get_lvgl_font(void);

/**
* 初始化binfont LVGL字体
* @return 0成功,负数错误码
*/
int mos_binfont_lvgl_init(void);

/**
* 释放binfont LVGL字体资源
*/
void mos_binfont_lvgl_deinit(void);


int mos_binfont_debug_glyph_region(uint32_t unicode, uint32_t *out_glyph_id,
uint32_t *out_start, uint32_t *out_len);

#endif /* CONFIG_LVGL */

#endif /* MOS_BINFONT_LVGL_H */
Loading