mirror of
https://github.com/RfidResearchGroup/ChameleonUltra.git
synced 2026-05-12 11:22:59 -07:00
Merge branch 'main' into implement-get-slot-data
This commit is contained in:
+3
-1
@@ -1,3 +1,5 @@
|
||||
.idea/
|
||||
.vscode/
|
||||
.vs/
|
||||
.vs/
|
||||
|
||||
.DS_Store
|
||||
@@ -39,6 +39,7 @@ Downloading a GUI
|
||||
https://www.youtube.com/watch?v=rHH7iqbX3nY
|
||||
|
||||
Link to the GUI
|
||||
|
||||
https://github.com/GameTec-live/ChameleonUltraGUI
|
||||
|
||||
# Hardware Pictures
|
||||
|
||||
+2
-1
@@ -6,7 +6,8 @@ ARG NRF_CLT_URL=https://nsscprodmedia.blob.core.windows.net/prod/software-and-ot
|
||||
RUN set -xe; \
|
||||
DEBIAN_FRONTEND=noninteractive; \
|
||||
apt update -q; \
|
||||
apt install -qy --no-install-recommends ca-certificates curl xz-utils make; \
|
||||
apt install -qy --no-install-recommends ca-certificates curl xz-utils make git; \
|
||||
git config --global --add safe.directory /workdir; \
|
||||
curl -sLo /usr/bin/nrfutil https://developer.nordicsemi.com/.pc-tools/nrfutil/x64-linux/nrfutil; \
|
||||
curl -sLo /tmp/nrf-clt.deb $NRF_CLT_URL; \
|
||||
apt install -qfy /tmp/nrf-clt.deb; \
|
||||
|
||||
@@ -22,4 +22,8 @@ LD_DIR := $(SRC_COMMON)
|
||||
CHAMELEON_ULTRA := ultra
|
||||
CHAMELEON_LITE := lite
|
||||
# What device is it?
|
||||
|
||||
CURRENT_DEVICE_TYPE ?= ${CHAMELEON_ULTRA}
|
||||
|
||||
# Versioning information
|
||||
GIT_VERSION := "$(shell git describe --abbrev=7 --dirty --always --tags)"
|
||||
|
||||
@@ -7,10 +7,12 @@ $(OUTPUT_DIRECTORY)/application.out: \
|
||||
# Source files common to all targets
|
||||
SRC_FILES += \
|
||||
$(SRC_COMMON)/hw_connect.c \
|
||||
$(SRC_COMMON)/libc_nano_stubs.c \
|
||||
$(PROJ_DIR)/app_main.c \
|
||||
$(PROJ_DIR)/app_cmd.c \
|
||||
$(PROJ_DIR)/ble_main.c \
|
||||
$(PROJ_DIR)/rfid_main.c \
|
||||
$(PROJ_DIR)/settings.c \
|
||||
$(PROJ_DIR)/usb_main.c \
|
||||
$(PROJ_DIR)/rgb_marquee.c \
|
||||
$(PROJ_DIR)/bsp/bsp_delay.c \
|
||||
@@ -311,6 +313,9 @@ CFLAGS += -mfloat-abi=hard -mfpu=fpv4-sp-d16
|
||||
CFLAGS += -ffunction-sections -fdata-sections -fno-strict-aliasing
|
||||
CFLAGS += -fno-builtin -fshort-enums
|
||||
|
||||
# Versioning flags
|
||||
CFLAGS += -DGIT_VERSION=\"$(GIT_VERSION)\"
|
||||
|
||||
# C++ flags common to all targets
|
||||
CXXFLAGS += $(OPT)
|
||||
# Assembler flags common to all targets
|
||||
@@ -366,14 +371,13 @@ TEMPLATE_PATH := $(SDK_ROOT)/components/toolchain/gcc
|
||||
include ../Makefile.defs
|
||||
include $(TEMPLATE_PATH)/Makefile.common
|
||||
|
||||
# tolerate warnings in newer gcc versions
|
||||
# need to be called after $(TEMPLATE_PATH)/Makefile.common
|
||||
CC_VERSION = $(shell $(CC) -dumpversion 2>/dev/null|sed 's/\..*//')
|
||||
CC_VERSION := $(or $(strip $(CC_VERSION)),0)
|
||||
CFLAGS += -Wno-error=array-bounds
|
||||
ifeq ($(shell expr $(CC_VERSION) \>= 12), 1)
|
||||
CFLAGS += -Wno-error=sizeof-array-div
|
||||
endif
|
||||
# usage example:
|
||||
#ifeq ($(shell expr $(CC_VERSION) \>= 12), 1)
|
||||
# CFLAGS += -Wno-error=sizeof-array-div
|
||||
#endif
|
||||
|
||||
$(foreach target, $(TARGETS), $(call define_target, $(target)))
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include "app_status.h"
|
||||
#include "tag_persistence.h"
|
||||
#include "nrf_pwr_mgmt.h"
|
||||
#include "settings.h"
|
||||
|
||||
|
||||
#define NRF_LOG_MODULE_NAME app_cmd
|
||||
@@ -27,6 +28,12 @@ data_frame_tx_t* cmd_processor_get_version(uint16_t cmd, uint16_t status, uint16
|
||||
return data_frame_make(cmd, status, 2, (uint8_t*)&version);
|
||||
}
|
||||
|
||||
|
||||
data_frame_tx_t* cmd_processor_get_git_version(uint16_t cmd, uint16_t status, uint16_t length, uint8_t *data) {
|
||||
return data_frame_make(cmd, status, strlen(GIT_VERSION), (uint8_t*)GIT_VERSION);
|
||||
}
|
||||
|
||||
|
||||
data_frame_tx_t* cmd_processor_change_device_mode(uint16_t cmd, uint16_t status, uint16_t length, uint8_t *data) {
|
||||
#if defined(PROJECT_CHAMELEON_ULTRA)
|
||||
if (length == 1) {
|
||||
@@ -80,6 +87,32 @@ data_frame_tx_t* cmd_processor_get_device_address(uint16_t cmd, uint16_t status,
|
||||
return data_frame_make(cmd, STATUS_DEVICE_SUCCESS, 6, (uint8_t*)(&device_address[0]));
|
||||
}
|
||||
|
||||
data_frame_tx_t* cmd_processor_save_settings(uint16_t cmd, uint16_t status, uint16_t length, uint8_t *data) {
|
||||
status = settings_save_config();
|
||||
return data_frame_make(cmd, status, 0, NULL);
|
||||
}
|
||||
|
||||
data_frame_tx_t* cmd_processor_reset_settings(uint16_t cmd, uint16_t status, uint16_t length, uint8_t *data) {
|
||||
settings_init_config();
|
||||
status = settings_save_config();
|
||||
return data_frame_make(cmd, status, 0, NULL);
|
||||
}
|
||||
|
||||
data_frame_tx_t* cmd_processor_set_animation_mode(uint16_t cmd, uint16_t status, uint16_t length, uint8_t *data) {
|
||||
if (length == 1) {
|
||||
settings_set_animation_config(data[0]);
|
||||
}
|
||||
else {
|
||||
status = STATUS_PAR_ERR;
|
||||
}
|
||||
return data_frame_make(cmd, status, 0, NULL);
|
||||
}
|
||||
|
||||
data_frame_tx_t* cmd_processor_get_animation_mode(uint16_t cmd, uint16_t status, uint16_t length, uint8_t *data) {
|
||||
uint8_t animation_mode = settings_get_animation_config();
|
||||
return data_frame_make(cmd, STATUS_DEVICE_SUCCESS, 1, (uint8_t *)(&animation_mode));
|
||||
}
|
||||
|
||||
#if defined(PROJECT_CHAMELEON_ULTRA)
|
||||
|
||||
data_frame_tx_t* cmd_processor_14a_scan(uint16_t cmd, uint16_t status, uint16_t length, uint8_t *data) {
|
||||
@@ -388,13 +421,13 @@ data_frame_tx_t* cmd_processor_get_mf1_detection_log(uint16_t cmd, uint16_t stat
|
||||
data_frame_tx_t* cmd_processor_set_mf1_emulator_block(uint16_t cmd, uint16_t status, uint16_t length, uint8_t *data) {
|
||||
if (length > 0 && (((length - 1) % NFC_TAG_MF1_DATA_SIZE) == 0)) {
|
||||
uint8_t block_index = data[0];
|
||||
uint8_t block_count = (length - 1) % NFC_TAG_MF1_DATA_SIZE;
|
||||
uint8_t block_count = (length - 1) / NFC_TAG_MF1_DATA_SIZE;
|
||||
if (block_index + block_count > NFC_TAG_MF1_BLOCK_MAX) {
|
||||
status = STATUS_PAR_ERR;
|
||||
} else {
|
||||
tag_data_buffer_t* buffer = get_buffer_by_tag_type(TAG_TYPE_MIFARE_4096);
|
||||
nfc_tag_mf1_information_t *info = (nfc_tag_mf1_information_t *)buffer->buffer;
|
||||
for (int i = 1, j = block_index; i < length - 1; i += NFC_TAG_MF1_DATA_SIZE, j++) {
|
||||
for (int i = 1, j = block_index; i < length; i += NFC_TAG_MF1_DATA_SIZE, j++) {
|
||||
uint8_t *p_block = &data[i];
|
||||
memcpy(info->memory[j], p_block, NFC_TAG_MF1_DATA_SIZE);
|
||||
}
|
||||
@@ -532,6 +565,11 @@ static cmd_data_map_t m_data_cmd_map[] = {
|
||||
{ DATA_CMD_ENTER_BOOTLOADER, NULL, cmd_processor_enter_bootloader, NULL },
|
||||
{ DATA_CMD_GET_DEVICE_CHIP_ID, NULL, cmd_processor_get_device_chip_id, NULL },
|
||||
{ DATA_CMD_GET_DEVICE_ADDRESS, NULL, cmd_processor_get_device_address, NULL },
|
||||
{ DATA_CMD_SAVE_SETTINGS, NULL, cmd_processor_save_settings, NULL },
|
||||
{ DATA_CMD_RESET_SETTINGS, NULL, cmd_processor_reset_settings, NULL },
|
||||
{ DATA_CMD_SET_ANIMATION_MODE, NULL, cmd_processor_set_animation_mode, NULL },
|
||||
{ DATA_CMD_GET_ANIMATION_MODE, NULL, cmd_processor_get_animation_mode, NULL },
|
||||
{ DATA_CMD_GET_GIT_VERSION, NULL, cmd_processor_get_git_version, NULL },
|
||||
|
||||
#if defined(PROJECT_CHAMELEON_ULTRA)
|
||||
|
||||
|
||||
@@ -36,6 +36,8 @@ NRF_LOG_MODULE_REGISTER();
|
||||
#include "usb_main.h"
|
||||
#include "rgb_marquee.h"
|
||||
|
||||
#include "settings.h"
|
||||
|
||||
|
||||
// Defining soft timers
|
||||
APP_TIMER_DEF(m_button_check_timer); // Timer for button debounce
|
||||
@@ -219,22 +221,25 @@ static void system_off_enter(void) {
|
||||
for (uint8_t i = 0; i < RGB_LIST_NUM; i++) {
|
||||
nrf_gpio_pin_clear(p_led_array[i]);
|
||||
}
|
||||
uint8_t slot = tag_emulation_get_slot();
|
||||
// Power off animation
|
||||
uint8_t dir = slot > 3 ? 1 : 0;
|
||||
uint8_t color = get_color_by_slot(slot);
|
||||
if (m_reset_source & (NRF_POWER_RESETREAS_NFC_MASK | NRF_POWER_RESETREAS_LPCOMP_MASK)) {
|
||||
if (m_reset_source & NRF_POWER_RESETREAS_NFC_MASK) {
|
||||
color = 1;
|
||||
} else {
|
||||
color = 2;
|
||||
uint8_t animation_config = settings_get_animation_config();
|
||||
if (animation_config == SettingsAnimationModeFull) {
|
||||
uint8_t slot = tag_emulation_get_slot();
|
||||
// Power off animation
|
||||
uint8_t dir = slot > 3 ? 1 : 0;
|
||||
uint8_t color = get_color_by_slot(slot);
|
||||
if (m_reset_source & (NRF_POWER_RESETREAS_NFC_MASK | NRF_POWER_RESETREAS_LPCOMP_MASK)) {
|
||||
if (m_reset_source & NRF_POWER_RESETREAS_NFC_MASK) {
|
||||
color = 1;
|
||||
} else {
|
||||
color = 2;
|
||||
}
|
||||
}
|
||||
ledblink5(color, slot, dir ? 7 : 0);
|
||||
ledblink4(color, dir, 7, 99, 75);
|
||||
ledblink4(color, !dir, 7, 75, 50);
|
||||
ledblink4(color, dir, 7, 50, 25);
|
||||
ledblink4(color, !dir, 7, 25, 0);
|
||||
}
|
||||
ledblink5(color, slot, dir ? 7 : 0);
|
||||
ledblink4(color, dir, 7, 99, 75);
|
||||
ledblink4(color, !dir, 7, 75, 50);
|
||||
ledblink4(color, dir, 7, 50, 25);
|
||||
ledblink4(color, !dir, 7, 25, 0);
|
||||
rgb_marquee_stop();
|
||||
}
|
||||
|
||||
@@ -346,9 +351,18 @@ static void check_wakeup_src(void) {
|
||||
advertising_start(); // Turn on Bluetooth radio
|
||||
|
||||
// Button wake-up boot animation
|
||||
ledblink2(color, !dir, 11);
|
||||
ledblink2(color, dir, 11);
|
||||
ledblink2(color, !dir, dir ? slot : 7 - slot);
|
||||
uint8_t animation_config = settings_get_animation_config();
|
||||
if (animation_config == SettingsAnimationModeFull)
|
||||
{
|
||||
ledblink2(color, !dir, 11);
|
||||
ledblink2(color, dir, 11);
|
||||
ledblink2(color, !dir, dir ? slot : 7 - slot);
|
||||
} else if (animation_config == SettingsAnimationModeMinimal) {
|
||||
ledblink2(color, !dir, dir ? slot : 7 - slot);
|
||||
} else {
|
||||
set_slot_light_color(color);
|
||||
}
|
||||
|
||||
// The indicator of the current card slot lights up at the end of the animation
|
||||
light_up_by_slot();
|
||||
|
||||
@@ -374,8 +388,11 @@ static void check_wakeup_src(void) {
|
||||
// 当前是模拟卡事件唤醒系统,我们可以让场强灯先亮起来
|
||||
TAG_FIELD_LED_ON();
|
||||
|
||||
// In the case of field wake-up, only one round of RGB is swept as the power-on animation
|
||||
ledblink2(color, !dir, dir ? slot : 7 - slot);
|
||||
uint8_t animation_config = settings_get_animation_config();
|
||||
if (animation_config == SettingsAnimationModeFull) {
|
||||
// In the case of field wake-up, only one round of RGB is swept as the power-on animation
|
||||
ledblink2(color, !dir, dir ? slot : 7 - slot);
|
||||
}
|
||||
set_slot_light_color(color);
|
||||
light_up_by_slot();
|
||||
|
||||
@@ -517,6 +534,8 @@ int main(void) {
|
||||
tag_emulation_init(); // Analog card initialization
|
||||
rgb_marquee_init(); // Light effect initialization
|
||||
|
||||
settings_load_config(); // Load settings from flash
|
||||
|
||||
// cmd callback register
|
||||
on_data_frame_complete(on_data_frame_received);
|
||||
|
||||
|
||||
@@ -20,6 +20,11 @@
|
||||
#define DATA_CMD_ENTER_BOOTLOADER (1010)
|
||||
#define DATA_CMD_GET_DEVICE_CHIP_ID (1011)
|
||||
#define DATA_CMD_GET_DEVICE_ADDRESS (1012)
|
||||
#define DATA_CMD_SAVE_SETTINGS (1013)
|
||||
#define DATA_CMD_RESET_SETTINGS (1014)
|
||||
#define DATA_CMD_SET_ANIMATION_MODE (1015)
|
||||
#define DATA_CMD_GET_ANIMATION_MODE (1016)
|
||||
#define DATA_CMD_GET_GIT_VERSION (1017)
|
||||
//
|
||||
// ******************************************************************
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include "lf_tag_em.h"
|
||||
#include "nfc_mf1.h"
|
||||
#include "nfc_ntag.h"
|
||||
#include "fds_ids.h"
|
||||
#include "fds_util.h"
|
||||
#include "tag_emulation.h"
|
||||
#include "tag_persistence.h"
|
||||
@@ -383,7 +384,7 @@ void tag_emulation_sense_switch(tag_sense_type_t type, bool enable) {
|
||||
*/
|
||||
void tag_emulation_load_config(void) {
|
||||
// 读取卡槽配置数据
|
||||
bool ret = fds_read_sync(FDS_CONFIG_RECORD_FILE_ID, FDS_CONFIG_RECORD_FILE_KEY, sizeof(slotConfig), (uint8_t *)&slotConfig);
|
||||
bool ret = fds_read_sync(FDS_EMULATION_CONFIG_FILE_ID, FDS_EMULATION_CONFIG_RECORD_KEY, sizeof(slotConfig), (uint8_t *)&slotConfig);
|
||||
if (ret) {
|
||||
// 读取完成后,我们先保存一份当前配置的BCC,后面保存的时候可以作为变动对比的参考
|
||||
calc_14a_crc_lut((uint8_t *)&slotConfig, sizeof(slotConfig), (uint8_t *)&m_slot_config_crc);
|
||||
@@ -402,7 +403,7 @@ void tag_emulation_save_config(void) {
|
||||
calc_14a_crc_lut((uint8_t *)&slotConfig, sizeof(slotConfig), (uint8_t *)&new_calc_crc);
|
||||
if (new_calc_crc != m_slot_config_crc) { // 在保存之前,先确保卡槽配置有变动了
|
||||
NRF_LOG_INFO("Save tag slot config start.");
|
||||
bool ret = fds_write_sync(FDS_CONFIG_RECORD_FILE_ID, FDS_CONFIG_RECORD_FILE_KEY, sizeof(slotConfig) / 4, (uint8_t *)&slotConfig);
|
||||
bool ret = fds_write_sync(FDS_EMULATION_CONFIG_FILE_ID, FDS_EMULATION_CONFIG_RECORD_KEY, sizeof(slotConfig) / 4, (uint8_t *)&slotConfig);
|
||||
if (ret) {
|
||||
NRF_LOG_INFO("Save tag slot config success.");
|
||||
} else {
|
||||
|
||||
@@ -5,12 +5,11 @@
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "utils.h"
|
||||
#include "tag_base_type.h"
|
||||
|
||||
// 最多八张卡槽
|
||||
#define TAG_MAX_SLOT_NUM 8
|
||||
// u32 size align.
|
||||
#define ALIGN_U32 __attribute__((aligned(4)))
|
||||
|
||||
extern bool g_is_tag_emulating;
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#include "tag_persistence.h"
|
||||
|
||||
#include "fds_ids.h"
|
||||
|
||||
#define NRF_LOG_MODULE_NAME tag_persistence
|
||||
#include "nrf_log.h"
|
||||
@@ -9,35 +9,24 @@ NRF_LOG_MODULE_REGISTER();
|
||||
|
||||
|
||||
|
||||
void get_fds_map_by_slot_auto_inc_id(uint16_t key, uint16_t id, uint8_t slot, tag_sense_type_t sense_type, fds_slot_record_map_t* map) {
|
||||
map->key = key + slot;
|
||||
uint8_t base_id = 0;
|
||||
switch(sense_type) {
|
||||
case TAG_SENSE_HF:
|
||||
base_id = 0;
|
||||
break;
|
||||
case TAG_SENSE_LF:
|
||||
base_id = 1;
|
||||
break;
|
||||
case TAG_SENSE_NO:
|
||||
// never to here...(if dev wrong, must fix)
|
||||
APP_ERROR_CHECK(NRF_ERROR_INVALID_PARAM);
|
||||
static void get_fds_map_by_slot_auto_inc_id(uint16_t id, uint8_t slot, tag_sense_type_t sense_type, fds_slot_record_map_t* map) {
|
||||
if ((sense_type == TAG_SENSE_NO) || (slot > 7)) {
|
||||
APP_ERROR_CHECK(NRF_ERROR_INVALID_PARAM);
|
||||
}
|
||||
map->id = id + base_id;
|
||||
map->id = id + slot;
|
||||
map->key = sense_type;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 根据卡槽和卡槽中指定的场类型获得其在FDS中对应的数据的KEY和ID
|
||||
* Obtain the KEY and ID of the corresponding data in FDS according to the card slot and the field type specified in the card slot
|
||||
*/
|
||||
void get_fds_map_by_slot_sense_type_for_dump(uint8_t slot, tag_sense_type_t sense_type, fds_slot_record_map_t* map) {
|
||||
// 根据 @see FDS_SLOT_TAG_DUMP_FILE_KEY 的约定,每个slot以其为起点,每个slot都有其单独的key的record,并且每个slot中独特的场类型也有一个数据的id
|
||||
get_fds_map_by_slot_auto_inc_id(FDS_SLOT_TAG_DUMP_FILE_KEY, FDS_SLOT_TAG_DUMP_FILE_ID, slot, sense_type, map);
|
||||
get_fds_map_by_slot_auto_inc_id(FDS_SLOT_TAG_DUMP_FILE_ID_BASE, slot, sense_type, map);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据卡槽和卡槽中指定的场类型获得其在FDS中对应的数据的KEY和ID
|
||||
* Obtain the KEY and ID of the corresponding data in FDS according to the card slot and the field type specified in the card slot
|
||||
*/
|
||||
void get_fds_map_by_slot_sense_type_for_nick(uint8_t slot, tag_sense_type_t sense_type, fds_slot_record_map_t* map) {
|
||||
get_fds_map_by_slot_auto_inc_id(FDS_SLOT_TAG_NICK_NAME_KEY, FDS_SLOT_TAG_NICK_NAME_ID, slot, sense_type, map);
|
||||
get_fds_map_by_slot_auto_inc_id(FDS_SLOT_TAG_NICK_NAME_FILE_ID_BASE, slot, sense_type, map);
|
||||
}
|
||||
|
||||
@@ -5,27 +5,6 @@
|
||||
#include "tag_base_type.h"
|
||||
|
||||
|
||||
/*
|
||||
* 卡槽配置,只有一份,一致即可
|
||||
*/
|
||||
#define FDS_CONFIG_RECORD_FILE_KEY 0x1066
|
||||
#define FDS_CONFIG_RECORD_FILE_ID 0x1066
|
||||
|
||||
/*
|
||||
* 每个卡槽有高低频两种数据,其中key是跟卡槽走的,而id+n就等于数据索引,固定某个索引为指定类型即可
|
||||
* 每个slot的file_key都不一样
|
||||
* 每个slot有两种类型的卡片,因此有两个数据ID(当前)
|
||||
*/
|
||||
#define FDS_SLOT_TAG_DUMP_FILE_KEY 0x1067
|
||||
#define FDS_SLOT_TAG_DUMP_FILE_ID 0x1067
|
||||
|
||||
/*
|
||||
* 每个卡槽有高低频两种数据,因此卡槽的昵称也要有两种,其中key是跟卡槽走的,而id+n就等于数据索引,固定某个索引为指定类型即可
|
||||
*/
|
||||
#define FDS_SLOT_TAG_NICK_NAME_KEY 0x1068
|
||||
#define FDS_SLOT_TAG_NICK_NAME_ID 0x1068
|
||||
|
||||
|
||||
typedef struct {
|
||||
uint16_t key;
|
||||
uint16_t id;
|
||||
|
||||
@@ -0,0 +1,117 @@
|
||||
#include <stdbool.h>
|
||||
#include "crc_utils.h"
|
||||
#include "app_status.h"
|
||||
#include "settings.h"
|
||||
#include "fds_ids.h"
|
||||
#include "fds_util.h"
|
||||
|
||||
#define NRF_LOG_MODULE_NAME settings
|
||||
#include "nrf_log.h"
|
||||
#include "nrf_log_ctrl.h"
|
||||
#include "nrf_log_default_backends.h"
|
||||
NRF_LOG_MODULE_REGISTER();
|
||||
|
||||
static settings_data_t config;
|
||||
|
||||
static uint16_t m_config_crc;
|
||||
|
||||
static void update_config_crc(void)
|
||||
{
|
||||
calc_14a_crc_lut((uint8_t *)&config, sizeof(config), (uint8_t *)&m_config_crc);
|
||||
}
|
||||
|
||||
static bool config_did_change(void)
|
||||
{
|
||||
uint16_t new_calc_crc;
|
||||
calc_14a_crc_lut((uint8_t *)&config, sizeof(config), (uint8_t *)&new_calc_crc);
|
||||
return new_calc_crc != m_config_crc;
|
||||
}
|
||||
|
||||
void settings_init_config(void)
|
||||
{
|
||||
config.version = SETTINGS_CURRENT_VERSION;
|
||||
config.animation_config = SettingsAnimationModeFull;
|
||||
}
|
||||
|
||||
void settings_migrate(void)
|
||||
{
|
||||
switch (config.version) {
|
||||
case 0:
|
||||
NRF_LOG_ERROR("Unexpected configuration version detected!");
|
||||
settings_init_config();
|
||||
break;
|
||||
/*
|
||||
* When needed migrations can be implemented like this:
|
||||
*
|
||||
* case 1:
|
||||
* config->new_field = some_default_value;
|
||||
* case 2:
|
||||
* config->another_new_field = some_default_value;
|
||||
* case 3:
|
||||
* config->another_new_field = some_default_value;
|
||||
* break;
|
||||
*
|
||||
* Note that the `break` statement should only be used on the last migration step, all the previous steps must fall
|
||||
* through to the next case.
|
||||
*/
|
||||
default:
|
||||
NRF_LOG_ERROR("Unsupported configuration migration attempted! (%d -> %d)", config.version, SETTINGS_CURRENT_VERSION);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void settings_load_config(void)
|
||||
{
|
||||
bool ret = fds_read_sync(FDS_SETTINGS_FILE_ID, FDS_SETTINGS_RECORD_KEY, sizeof(config), (uint8_t *)&config);
|
||||
if (ret) {
|
||||
NRF_LOG_INFO("Load config done.");
|
||||
// After the reading is complete, we first save a copy of the current CRC, which can be used as a reference for comparison of changes when saving later
|
||||
update_config_crc();
|
||||
} else {
|
||||
NRF_LOG_WARNING("Config does not exist, loading default values...");
|
||||
settings_init_config();
|
||||
}
|
||||
if (config.version > SETTINGS_CURRENT_VERSION) {
|
||||
NRF_LOG_WARNING("Config version %d is greater than current firmware supports (%d). Default config will be loaded.", config.version, SETTINGS_CURRENT_VERSION);
|
||||
settings_init_config();
|
||||
}
|
||||
if (config.version < SETTINGS_CURRENT_VERSION) {
|
||||
NRF_LOG_INFO("Config version (%d) is not latest, performing migration to %d", config.version, SETTINGS_CURRENT_VERSION);
|
||||
settings_migrate();
|
||||
}
|
||||
if (config_did_change()) {
|
||||
settings_save_config();
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t settings_save_config(void)
|
||||
{
|
||||
// We are saving the configuration, we need to calculate the crc code of the current configuration to judge whether the following data is updated
|
||||
if (config_did_change()) { // Before saving, make sure that the configuration has changed
|
||||
NRF_LOG_INFO("Save config start.");
|
||||
bool ret = fds_write_sync(FDS_SETTINGS_FILE_ID, FDS_SETTINGS_RECORD_KEY, sizeof(config) / 4, (uint8_t *)&config);
|
||||
if (ret) {
|
||||
NRF_LOG_INFO("Save config success.");
|
||||
update_config_crc();
|
||||
}
|
||||
else
|
||||
{
|
||||
NRF_LOG_ERROR("Save config error.");
|
||||
return STATUS_FLASH_WRITE_FAIL;
|
||||
}
|
||||
} else {
|
||||
NRF_LOG_INFO("Config did not change.");
|
||||
}
|
||||
|
||||
return STATUS_DEVICE_SUCCESS;
|
||||
}
|
||||
|
||||
uint8_t settings_get_animation_config()
|
||||
{
|
||||
return config.animation_config;
|
||||
}
|
||||
|
||||
void settings_set_animation_config(uint8_t value)
|
||||
{
|
||||
config.animation_config = value;
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
#ifndef SETTINGS_H
|
||||
#define SETTINGS_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "utils.h"
|
||||
|
||||
#define SETTINGS_CURRENT_VERSION 1
|
||||
|
||||
typedef enum {
|
||||
SettingsAnimationModeFull = 0,
|
||||
SettingsAnimationModeMinimal = 1,
|
||||
SettingsAnimationModeNone = 2,
|
||||
} settings_animation_mode_t;
|
||||
|
||||
typedef struct ALIGN_U32 {
|
||||
uint16_t version;
|
||||
uint8_t animation_config : 2;
|
||||
uint16_t reserved0 : 14;
|
||||
uint32_t reserved1;
|
||||
uint32_t reserved2;
|
||||
} settings_data_t;
|
||||
|
||||
void settings_init_config(void);
|
||||
void settings_migrate(void);
|
||||
void settings_load_config(void);
|
||||
uint8_t settings_save_config(void);
|
||||
uint8_t settings_get_animation_config(void);
|
||||
void settings_set_animation_config(uint8_t value);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,38 @@
|
||||
#ifndef FDS_IDS_H
|
||||
#define FDS_IDS_H
|
||||
|
||||
/*
|
||||
* Card slot configuration, only one, consistent
|
||||
*/
|
||||
#define FDS_EMULATION_CONFIG_FILE_ID 0x1000
|
||||
#define FDS_EMULATION_CONFIG_RECORD_KEY 0x1
|
||||
|
||||
/*
|
||||
* Slot for settings like LED animation mode and future options
|
||||
*/
|
||||
#define FDS_SETTINGS_FILE_ID 0x1001
|
||||
#define FDS_SETTINGS_RECORD_KEY 0x1
|
||||
|
||||
/*
|
||||
* Each card slot has two types of data, high and low frequency
|
||||
* FDS file ID follows the card slot, starting from 0x1100 to 0x1107
|
||||
* FDS record key mirrors TAG_SENSE_LF/HF so is 1 for LF, 2 for HF (currently)
|
||||
*/
|
||||
#define FDS_SLOT_TAG_DUMP_FILE_ID_BASE 0x1100
|
||||
|
||||
/*
|
||||
* Each card slot has two types of data, high and low frequency, so it can get two names
|
||||
* FDS file ID follows the card slot, starting from 0x1200 to 0x1207
|
||||
* FDS record key mirrors TAG_SENSE_LF/HF so is 1 for LF, 2 for HF (currently)
|
||||
*/
|
||||
#define FDS_SLOT_TAG_NICK_NAME_FILE_ID_BASE 0x1200
|
||||
|
||||
// Note that previously assigned records may need to be cleaned from Flash.
|
||||
// Taking into account the possible overlaps, it boils down to
|
||||
// ID 0x1066 Keys 0x1066
|
||||
// ID 0x1067 Keys 0x1067-0x106e
|
||||
// ID 0x1068 Keys 0x1067-0x106f
|
||||
// ID 0x1069 Keys 0x1068-0x1070
|
||||
|
||||
|
||||
#endif
|
||||
@@ -10,6 +10,7 @@ SRC_FILES += \
|
||||
$(PROJ_DIR)/main.c \
|
||||
$(PROJ_DIR)/dfu_public_key.c \
|
||||
$(SRC_COMMON)/hw_connect.c \
|
||||
$(SRC_COMMON)/libc_nano_stubs.c \
|
||||
$(SDK_ROOT)/modules/nrfx/drivers/src/nrfx_clock.c \
|
||||
$(SDK_ROOT)/modules/nrfx/drivers/src/nrfx_power.c \
|
||||
$(SDK_ROOT)/modules/nrfx/drivers/src/nrfx_systick.c \
|
||||
@@ -197,8 +198,6 @@ CFLAGS += -mfloat-abi=hard -mfpu=fpv4-sp-d16
|
||||
# keep every function in a separate section, this allows linker to discard unused ones
|
||||
CFLAGS += -ffunction-sections -fdata-sections -fno-strict-aliasing
|
||||
CFLAGS += -fno-builtin -fshort-enums
|
||||
# fix newer compilator versions
|
||||
CFLAGS += -Wno-error=array-bounds
|
||||
|
||||
# C++ flags common to all targets
|
||||
CXXFLAGS += $(OPT)
|
||||
@@ -253,6 +252,15 @@ TEMPLATE_PATH := $(SDK_ROOT)/components/toolchain/gcc
|
||||
|
||||
include $(TEMPLATE_PATH)/Makefile.common
|
||||
|
||||
# tolerate warnings in newer gcc versions
|
||||
# need to be called after $(TEMPLATE_PATH)/Makefile.common
|
||||
CC_VERSION = $(shell $(CC) -dumpversion 2>/dev/null|sed 's/\..*//')
|
||||
CC_VERSION := $(or $(strip $(CC_VERSION)),0)
|
||||
ifeq ($(shell expr $(CC_VERSION) \>= 12), 1)
|
||||
# avoid a couple of false warnings in nRF SDK
|
||||
CFLAGS += --param=min-pagesize=0
|
||||
endif
|
||||
|
||||
$(foreach target, $(TARGETS), $(call define_target, $(target)))
|
||||
|
||||
.PHONY: flash flash_softdevice erase
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
Flag --specs=nano.specs forces linking against libc_nano which contains .gnu.warnings since GCC 11.3 like:
|
||||
arm-gnu-toolchain-12.2.rel1-x86_64-arm-none-eabi/arm-none-eabi/lib/thumb/v7e-m+fp/hard/libc_nano.a(libc_a-closer.o): in function `_close_r':
|
||||
closer.c:(.text._close_r+0xc): warning: _close is not implemented and will always fail
|
||||
So we are providing stubs to suppress these warnings
|
||||
See also https://stackoverflow.com/questions/73742774/gcc-arm-none-eabi-11-3-is-not-implemented-and-will-always-fail
|
||||
*/
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <errno.h>
|
||||
#undef errno
|
||||
extern int errno;
|
||||
|
||||
int _close(int file) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int _fstat(int file, struct stat *st) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int _getpid(void) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
int _isatty(int file) {
|
||||
errno = EINVAL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int _kill(int pid, int sig) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int _lseek(int file, int ptr, int dir) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int _read(int file, char *ptr, int len) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int _write(int file, char *ptr, int len) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
#ifndef UTILS_H_
|
||||
#define UTILS_H_
|
||||
|
||||
// u32 size align.
|
||||
#define ALIGN_U32 __attribute__((aligned(4)))
|
||||
|
||||
#endif
|
||||
@@ -41,6 +41,8 @@
|
||||
#define NRF_SECTION_H__
|
||||
|
||||
#include "nordic_common.h"
|
||||
// ChameleonUltra: nRF SDK produces a number of GCC warnings due to its NRF_SECTION macros and we want to ignore them
|
||||
#pragma GCC diagnostic ignored "-Warray-bounds"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
||||
@@ -64,6 +64,10 @@ extern "C" {
|
||||
/** @brief Number of channels in each PWM instance. */
|
||||
#define NRF_PWM_CHANNEL_COUNT 4
|
||||
|
||||
// ChameleonUltra: nRF SDK produces a wrong GCC warning as the following macro is not meant to give an array size
|
||||
#if __GNUC__ >= 12
|
||||
#pragma GCC diagnostic ignored "-Wsizeof-array-div"
|
||||
#endif
|
||||
/**
|
||||
* @brief Helper macro for calculating the number of 16-bit values in the specified
|
||||
* array of duty cycle values.
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user