Merge branch 'RfidResearchGroup:main' into main

This commit is contained in:
derGraph
2023-06-09 20:54:34 +02:00
committed by GitHub
21 changed files with 1221 additions and 265 deletions
+674
View File
File diff suppressed because it is too large Load Diff
+3
View File
@@ -76,6 +76,7 @@ SRC_FILES += \
$(SDK_ROOT)/integration/nrfx/legacy/nrf_drv_spi.c \
$(SDK_ROOT)/integration/nrfx/legacy/nrf_drv_ppi.c \
$(SDK_ROOT)/modules/nrfx/soc/nrfx_atomic.c \
$(SDK_ROOT)/modules/nrfx/drivers/src/nrfx_saadc.c \
$(SDK_ROOT)/modules/nrfx/drivers/src/nrfx_clock.c \
$(SDK_ROOT)/modules/nrfx/drivers/src/nrfx_gpiote.c \
$(SDK_ROOT)/modules/nrfx/drivers/src/nrfx_power.c \
@@ -101,6 +102,7 @@ SRC_FILES += \
$(SDK_ROOT)/components/ble/nrf_ble_gatt/nrf_ble_gatt.c \
$(SDK_ROOT)/external/utf_converter/utf.c \
$(SDK_ROOT)/components/ble/ble_services/ble_nus/ble_nus.c \
$(SDK_ROOT)/components/ble/ble_services/ble_bas/ble_bas.c \
$(SDK_ROOT)/components/ble/nrf_ble_qwr/nrf_ble_qwr.c \
$(SDK_ROOT)/components/softdevice/common/nrf_sdh.c \
$(SDK_ROOT)/components/softdevice/common/nrf_sdh_ble.c \
@@ -169,6 +171,7 @@ INC_FOLDERS += \
$(SDK_ROOT)/components/libraries/csense_drv \
$(SDK_ROOT)/components/libraries/memobj \
$(SDK_ROOT)/components/ble/ble_services/ble_nus_c \
$(SDK_ROOT)/components/ble/ble_services/ble_bas_c \
$(SDK_ROOT)/components/softdevice/common \
$(SDK_ROOT)/components/ble/ble_services/ble_ias \
$(SDK_ROOT)/components/libraries/usbd/class/hid/mouse \
+1 -1
View File
@@ -5,7 +5,7 @@ GROUP(-lgcc -lc -lnosys)
MEMORY
{
FLASH (rx) : ORIGIN = 0x27000, LENGTH = 0xf3000
FLASH (rx) : ORIGIN = 0x27000, LENGTH = 0xCC000
RAM (rwx) : ORIGIN = 0x20002ae8, LENGTH = 0x35518
}
+93 -54
View File
@@ -15,6 +15,7 @@
#include "nrf_pwr_mgmt.h"
#include "nrfx_nfct.h"
#include "nrfx_power.h"
#include "nrf_drv_lpcomp.h"
#define NRF_LOG_MODULE_NAME app_main
#include "nrf_log.h"
@@ -36,7 +37,6 @@ NRF_LOG_MODULE_REGISTER();
#include "rgb_marquee.h"
// Defining soft timers
APP_TIMER_DEF(m_button_check_timer); // Timer for button debounce
static bool m_is_read_btn_press = false;
@@ -44,6 +44,12 @@ static bool m_is_write_btn_press = false;
// cpu reset reason
static uint32_t m_reset_source;
static uint32_t m_gpregret_val;
#define GPREGRET_CLEAR_VALUE_DEFAULT (0xFFFFFFFFUL)
#define RESET_ON_LF_FIELD_EXISTS_Msk (1UL)
extern bool g_is_low_battery_shutdown;
/**@brief Function for assert macro callback.
@@ -69,26 +75,6 @@ static void app_timers_init(void) {
APP_ERROR_CHECK(err_code);
}
/**@brief Function for putting the chip into sleep mode.
*
* @note This function will not return.
*/
static void sleep_mode_enter(void) {
ret_code_t err_code;
// Go to system-off mode (this function will not return; wakeup will cause a reset).
// Note that if jlink is plugged in or debug is on, an error may be reported when entering a low-power function.
// When turning on debugging we should disable low power state value detection or simply not enter low power
err_code = sd_power_system_off();
// OK, this is very important, if the log output is enabled and RTT is enabled, then do not check for low power mode errors
#if !(NRF_LOG_ENABLED && NRF_LOG_BACKEND_RTT_ENABLED)
APP_ERROR_CHECK(err_code);
#else
UNUSED_VARIABLE(err_code);
#endif
}
/**@brief Function for initializing the nrf log module.
*/
static void log_init(void) {
@@ -196,14 +182,17 @@ static void button_init(void) {
/**@brief The implementation function to enter deep hibernation
*/
static void system_off_enter(void) {
ret_code_t ret;
// Disable the HF NFC event first
NRF_NFCT->INTENCLR = NRF_NFCT_DISABLE_ALL_INT;
// Then disable the LF LPCOMP event
NRF_LPCOMP->INTENCLR = LPCOMP_INTENCLR_CROSS_Msk | LPCOMP_INTENCLR_UP_Msk | LPCOMP_INTENCLR_DOWN_Msk | LPCOMP_INTENCLR_READY_Msk;
// Save tag data
tag_emulation_save();
// Configure RAM hibernation hold
ret_code_t ret;
uint32_t ram8_retention = // RAM8 Each section has 32KB capacity
// POWER_RAM_POWER_S0RETENTION_On << POWER_RAM_POWER_S0RETENTION_Pos ;
// POWER_RAM_POWER_S1RETENTION_On << POWER_RAM_POWER_S1RETENTION_Pos |
@@ -214,28 +203,40 @@ static void system_off_enter(void) {
ret = sd_power_ram_power_set(8, ram8_retention);
APP_ERROR_CHECK(ret);
// Power off animation
uint8_t slot = tag_emulation_get_slot();
uint32_t* p_led_array = hw_get_led_array();
for (uint8_t i = 0; i < RGB_LIST_NUM; i++) {
nrf_gpio_pin_clear(p_led_array[i]);
}
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;
if (g_is_low_battery_shutdown) {
// Don't create too complex animations, just blink LED1 three times.
rgb_marquee_stop();
set_slot_light_color(0);
for (uint8_t i = 0; i <= 3; i++) {
nrf_gpio_pin_set(LED_1);
bsp_delay_ms(100);
nrf_gpio_pin_clear(LED_1);
bsp_delay_ms(100);
}
} else {
// close all led.
uint32_t* p_led_array = hw_get_led_array();
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;
}
}
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();
}
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);
// IOs that need to be configured as floating analog inputs ==> no pull-up or pull-down
uint32_t gpio_cfg_default_nopull[] = {
@@ -246,7 +247,7 @@ static void system_off_enter(void) {
HF_SPI_MOSI,
LF_OA_OUT,
#endif
BAT_SENSE,
BAT_SENSE_PIN,
};
for (int i = 0; i < ARRAY_SIZE(gpio_cfg_default_nopull); i++) {
nrf_gpio_cfg_default(gpio_cfg_default_nopull[i]);
@@ -257,6 +258,7 @@ static void system_off_enter(void) {
#if defined(PROJECT_CHAMELEON_ULTRA)
HF_ANT_SEL,
#endif
LED_FIELD, LED_R, LED_G, LED_B,
};
for (int i = 0; i < ARRAY_SIZE(gpio_cfg_output_high); i++) {
nrf_gpio_cfg_output(gpio_cfg_output_high[i]);
@@ -265,7 +267,7 @@ static void system_off_enter(void) {
// IOs that need to be configured as push-pull outputs and pulled low
uint32_t gpio_cfg_output_low[] = {
LED_1, LED_2, LED_3, LED_4, LED_5, LED_6, LED_7, LED_8, LED_R, LED_G, LED_B, LF_MOD,
LED_1, LED_2, LED_3, LED_4, LED_5, LED_6, LED_7, LED_8, LF_MOD,
#if defined(PROJECT_CHAMELEON_ULTRA)
READER_POWER, LF_ANT_DRIVER
#endif
@@ -278,15 +280,34 @@ static void system_off_enter(void) {
// Wait for a while before hibernating to avoid GPIO circuit configuration fluctuations to wake up the chip
bsp_delay_ms(50);
// Then save the card slot configuration and other data
tag_emulation_save();
// Then hibernate
// Print leaving message finally
NRF_LOG_INFO("Sleep finally, Bye ^.^");
// Turn off all soft timers
app_timer_stop_all();
// Calling system hibernation
sleep_mode_enter();
// 检查是否存在低频场,解决休眠时有非常强的场信号一直使比较器处于高电平输入状态从而无法产生上升沿而无法唤醒系统的问题。
if(lf_is_field_exists()) {
// 关闭比较器
nrf_drv_lpcomp_disable();
// 设置reset原因,重启后需要拿到此原因,避免误判唤醒源
sd_power_gpregret_clr(1, GPREGRET_CLEAR_VALUE_DEFAULT);
sd_power_gpregret_set(1, RESET_ON_LF_FIELD_EXISTS_Msk);
// 触发reset唤醒系统,重新启动模拟过程
nrf_pwr_mgmt_shutdown(NRF_PWR_MGMT_SHUTDOWN_RESET);
return;
};
// Go to system-off mode (this function will not return; wakeup will cause a reset).
// 注意,如果插着jlink或者开着debug,进入低功耗的函数可能会报错,
// 开启调试时我们应当禁用低功耗状态值检测,或者干脆不进入低功耗
ret = sd_power_system_off();
// OK,此处非常重要,如果开启了日志输出并且使能了RTT,则不去检查低功耗模式的错误
#if !(NRF_LOG_ENABLED && NRF_LOG_BACKEND_RTT_ENABLED)
APP_ERROR_CHECK(ret);
#else
UNUSED_VARIABLE(ret);
#endif
// It is not supposed to enter here, but jlink debug mode it can be entered, at most is not normal hibernation just
// jlink connection, power consumption will rise, and hibernation will also be stuck in this step.
@@ -301,6 +322,10 @@ static void check_wakeup_src(void) {
sd_power_reset_reason_get(&m_reset_source);
sd_power_reset_reason_clr(m_reset_source);
sd_power_gpregret_get(1, &m_gpregret_val);
sd_power_gpregret_clr(1, GPREGRET_CLEAR_VALUE_DEFAULT);
/*
* Note: The hibernation described below is deep hibernation, stopping any non-wakeup source peripherals and stopping the CPU to achieve the lowest power consumption
*
@@ -329,7 +354,8 @@ static void check_wakeup_src(void) {
// If no operation follows, wait for the timeout and then deep hibernate
sleep_timer_start(SLEEP_DELAY_MS_BUTTON_WAKEUP);
} else if (m_reset_source & (NRF_POWER_RESETREAS_NFC_MASK | NRF_POWER_RESETREAS_LPCOMP_MASK)) {
} else if ((m_reset_source & (NRF_POWER_RESETREAS_NFC_MASK | NRF_POWER_RESETREAS_LPCOMP_MASK)) ||
(m_gpregret_val & RESET_ON_LF_FIELD_EXISTS_Msk)) {
NRF_LOG_INFO("WakeUp from rfid field");
// wake up from hf field.
@@ -338,8 +364,16 @@ static void check_wakeup_src(void) {
NRF_LOG_INFO("WakeUp from HF");
} else {
color = 2; // LF filed show B.
NRF_LOG_INFO("WakeUp from LF");
if (m_gpregret_val & RESET_ON_LF_FIELD_EXISTS_Msk) {
NRF_LOG_INFO("Reset by LF");
} else {
NRF_LOG_INFO("WakeUp from LF");
}
}
// 当前是模拟卡事件唤醒系统,我们可以让场强灯先亮起来
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);
set_slot_light_color(color);
@@ -368,10 +402,15 @@ static void check_wakeup_src(void) {
// Initialize the default card slot data.
tag_emulation_factory_init();
// RGB
ledblink2(0, !dir, 11);
ledblink2(1, dir, 11);
ledblink2(2, !dir, 11);
// Show RGB for slot.
set_slot_light_color(color);
light_up_by_slot();
// If the USB is plugged in when first powered up, we can do something accordingly
if (nrfx_power_usbstatus_get() != NRFX_POWER_USB_STATE_DISCONNECTED) {
NRF_LOG_INFO("USB Power found.");
@@ -457,11 +496,12 @@ static void blink_usb_led_status(void) {
}
}
/**@brief Application main function.
*/
int main(void) {
hw_connect_init(); // Remember to initialize the pins first
init_leds(); // LED initialization
log_init(); // Log initialization
gpio_te_init(); // Initialize GPIO matrix library
app_timers_init(); // Initialize soft timer
@@ -469,7 +509,6 @@ int main(void) {
bsp_timer_init(); // Initialize timeout timer
bsp_timer_start(); // Start BSP TIMER and prepare it for processing business logic
button_init(); // Button initialization for handling business logic
init_leds(); // LED initialization
sleep_timer_init(); // Soft timer initialization for hibernation
rng_drv_and_srand_init(); // Random number generator initialization
power_management_init(); // Power management initialization
+247 -4
View File
@@ -1,5 +1,4 @@
#include "ble_hci.h"
#include "ble_nus.h"
#include "ble_advdata.h"
#include "ble_advertising.h"
#include "ble_conn_params.h"
@@ -11,6 +10,7 @@
#include "nrf_sdh_soc.h"
#include "nrf_sdh_ble.h"
#include "nrf_ble_gatt.h"
#include "nrf_drv_saadc.h"
#include "app_timer.h"
#include "app_util_platform.h"
@@ -18,6 +18,7 @@
#include "syssleep.h"
#include "ble_main.h"
#include "dataframe.h"
#include "hw_connect.h"
#define NRF_LOG_MODULE_NAME ble_main
#include "nrf_log.h"
@@ -40,18 +41,41 @@ NRF_LOG_MODULE_REGISTER();
#define NEXT_CONN_PARAMS_UPDATE_DELAY APP_TIMER_TICKS(30000) /**< Time between each call to sd_ble_gap_conn_param_update after the first call (30 seconds). */
#define MAX_CONN_PARAMS_UPDATE_COUNT 3 /**< Number of attempts before giving up the connection parameter negotiation. */
// #define BATTERY_LEVEL_MEAS_INTERVAL APP_TIMER_TICKS(1000) /**< Battery level measurement interval (ticks). This value corresponds to 1 seconds. */
#define BATTERY_LEVEL_MEAS_INTERVAL APP_TIMER_TICKS(5000) /**< Battery level measurement interval (ticks). This value corresponds to N seconds. */
#define ADC_REF_VOLTAGE_IN_MILLIVOLTS 600 //!< Reference voltage (in milli volts) used by ADC while doing conversion.
#define ADC_RES_12BIT 16383 //!< Maximum digital value for 14-bit ADC conversion.
#define ADC_PRE_SCALING_COMPENSATION 12 //!< The ADC is configured to use VDD with 1/3 prescaling as input. And hence the result of conversion is to be multiplied by 3 to get the actual value of the battery voltage.
/**@brief Macro to convert the result of ADC conversion in millivolts.
*
* @param[in] ADC_VALUE ADC result.
*
* @retval Result converted to millivolts.
*/
#define ADC_RESULT_IN_MILLI_VOLTS(ADC_VALUE)\
((((ADC_VALUE) * ADC_REF_VOLTAGE_IN_MILLIVOLTS) / ADC_RES_12BIT) * ADC_PRE_SCALING_COMPENSATION)
APP_TIMER_DEF(m_battery_timer_id); /**< Battery measurement timer. */
BLE_BAS_DEF(m_bas); /**< Battery service instance. */
BLE_NUS_DEF(m_nus, NRF_SDH_BLE_TOTAL_LINK_COUNT); /**< BLE NUS service instance. */
NRF_BLE_GATT_DEF(m_gatt); /**< GATT module instance. */
NRF_BLE_QWR_DEF(m_qwr); /**< Context for the Queued Write module.*/
BLE_ADVERTISING_DEF(m_advertising); /**< Advertising module instance. */
uint16_t batt_lvl_in_milli_volts = 0;
uint8_t percentage_batt_lvl = 0;
static nrf_saadc_value_t adc_buf[2];
static uint16_t m_conn_handle = BLE_CONN_HANDLE_INVALID; /**< Handle of the current connection. */
static uint16_t m_ble_nus_max_data_len = BLE_GATT_ATT_MTU_DEFAULT - 3; /**< Maximum length of data (in bytes) that can be transmitted to the peer by the Nordic UART service module. */
static ble_uuid_t m_adv_uuids[] = /**< Universally unique service identifier. */
{
{BLE_UUID_NUS_SERVICE, NUS_SERVICE_UUID_TYPE}
{BLE_UUID_NUS_SERVICE, NUS_SERVICE_UUID_TYPE},
{BLE_UUID_BATTERY_SERVICE, BLE_UUID_TYPE_BLE},
};
volatile bool g_is_ble_connected = false;
volatile bool g_is_low_battery_shutdown = false;
/**@brief Function for the GAP initialization.
@@ -81,6 +105,30 @@ static void gap_params_init(void)
APP_ERROR_CHECK(err_code);
}
/**@brief Function for handling the Battery Service events.
*
* @details This function will be called for all Battery Service events which are passed to the
| application.
*
* @param[in] p_bas Battery Service structure.
* @param[in] p_evt Event received from the Battery Service.
*/
static void on_bas_evt(ble_bas_t * p_bas, ble_bas_evt_t * p_evt)
{
switch (p_evt->evt_type)
{
case BLE_BAS_EVT_NOTIFICATION_ENABLED:
break; // BLE_BAS_EVT_NOTIFICATION_ENABLED
case BLE_BAS_EVT_NOTIFICATION_DISABLED:
break; // BLE_BAS_EVT_NOTIFICATION_DISABLED
default:
// No implementation needed.
break;
}
}
/**@brief Function for handling the data from the Nordic UART Service.
*
* @details This function will process the data received from the Nordic UART BLE Service
@@ -143,27 +191,128 @@ static void nrf_qwr_error_handler(uint32_t nrf_error)
APP_ERROR_HANDLER(nrf_error);
}
__INLINE uint32_t map(uint32_t x, uint32_t in_min, uint32_t in_max, uint32_t out_min, uint32_t out_max)
{
return (uint32_t)((x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min);
}
//电池电压到百分比计算
uint32_t BATVOL2PERCENT(uint16_t VOL)
{
//100% 4.20V 1
//90 % 4.06V 80%-100% 白
//80 % 3.98V 1
//70 % 3.92V 60%-80% 白
//60 % 3.87V 1
//50 % 3.82V 40%-60% 白
//40 % 3.79V 1
//30 % 3.77V 20%-40% 白
//20 % 3.74V 1
//10 % 3.68V 5%-20% 红
//5 % 3.45V 1 关机
//0 % 3.00V
//#define P100VOL 4200
//#define P80VOL 3980
//#define P60VOL 3870
//#define P40VOL 3790
//#define P20VOL 3740
//#define P5VOL 3450
//100% 4.20V 1
//90 % 4.00V 80%-100% 白
//80 % 3.89V 1
//70 % 3.79V 60%-80% 白
//60 % 3.70V 1
//50 % 3.62V 40%-60% 白
//40 % 3.57V 1
//30 % 3.53V 20%-40% 白
//20 % 3.51V 1
//10 % 3.46V 5%-20% 红
//5 % 3.43V 1 关机
//0 % 3.00V
#define P100VOL 4200
#define P80VOL 3890
#define P60VOL 3700
#define P40VOL 3570
#define P20VOL 3510
#define P5VOL 3230
if(VOL > P80VOL)
{
//80-100
return map(VOL, P80VOL, P100VOL, 80, 100);
}
else if(VOL > P60VOL)
{
//60-80
return map(VOL, P60VOL, P80VOL, 60, 80);
}
else if(VOL > P40VOL)
{
//40-60
return map(VOL, P40VOL, P60VOL, 40, 60);
}
else if(VOL > P20VOL)
{
//20-60
return map(VOL, P20VOL, P40VOL, 20, 40);
}
else if(VOL > P5VOL)
{
//5-20
return map(VOL, P5VOL, P20VOL, 5, 20);
}
else
{
//<5
return 0;
}
}
/**@brief Function for initializing services that will be used by the application.
*/
static void services_init(void)
{
uint32_t err_code;
ble_nus_init_t nus_init;
nrf_ble_qwr_init_t qwr_init = {0};
// -------------------------------------------------------------
// Initialize Queued Write Module.
nrf_ble_qwr_init_t qwr_init = {0};
qwr_init.error_handler = nrf_qwr_error_handler;
err_code = nrf_ble_qwr_init(&m_qwr, &qwr_init);
APP_ERROR_CHECK(err_code);
// -------------------------------------------------------------
// Initialize NUS.
ble_nus_init_t nus_init;
memset(&nus_init, 0, sizeof(nus_init));
nus_init.data_handler = nus_data_handler;
err_code = ble_nus_init(&m_nus, &nus_init);
APP_ERROR_CHECK(err_code);
// -------------------------------------------------------------
// battery service
ble_bas_init_t bas_init_obj;
memset(&bas_init_obj, 0, sizeof(bas_init_obj));
bas_init_obj.evt_handler = on_bas_evt;
bas_init_obj.support_notification = true;
bas_init_obj.p_report_ref = NULL;
bas_init_obj.initial_batt_level = 100;
bas_init_obj.bl_rd_sec = SEC_OPEN;
bas_init_obj.bl_cccd_wr_sec = SEC_OPEN;
bas_init_obj.bl_report_rd_sec = SEC_OPEN;
err_code = ble_bas_init(&m_bas, &bas_init_obj);
APP_ERROR_CHECK(err_code);
}
/**@brief Function for handling an event from the Connection Parameters Module.
@@ -405,10 +554,104 @@ void advertising_start(void)
APP_ERROR_CHECK(err_code);
}
/**@brief Function for handling the ADC interrupt.
*
* @details This function will fetch the conversion result from the ADC, convert the value into
* percentage and send it to peer.
*/
void saadc_event_handler(nrf_drv_saadc_evt_t const * p_event)
{
if (p_event->type == NRF_DRV_SAADC_EVT_DONE)
{
nrf_saadc_value_t adc_result;
uint32_t err_code;
adc_result = p_event->data.done.p_buffer[0];
// NRF_LOG_INFO("ADC sample value = %d", adc_result);
err_code = nrf_drv_saadc_buffer_convert(p_event->data.done.p_buffer, 1);
APP_ERROR_CHECK(err_code);
batt_lvl_in_milli_volts = ADC_RESULT_IN_MILLI_VOLTS(adc_result) + 100;
NRF_LOG_INFO("batt_lvl_in_milli_volts: %d", batt_lvl_in_milli_volts);
percentage_batt_lvl = BATVOL2PERCENT(batt_lvl_in_milli_volts);
// if battery service is notification enable, we can send msg to device.
err_code = ble_bas_battery_level_update(&m_bas, percentage_batt_lvl, BLE_CONN_HANDLE_ALL);
if ((err_code != NRF_SUCCESS) &&
(err_code != NRF_ERROR_INVALID_STATE) &&
(err_code != NRF_ERROR_RESOURCES) &&
(err_code != NRF_ERROR_BUSY) &&
(err_code != BLE_ERROR_GATTS_SYS_ATTR_MISSING)
)
{
APP_ERROR_HANDLER(err_code);
}
// check low battery level, if level == 0, we can try to shutdown.
if (percentage_batt_lvl == 0) {
NRF_LOG_INFO("battery too low, try to shutdown...");
g_is_low_battery_shutdown = true;
sleep_timer_start(SLEEP_NO_BATTERY_SHUTDOWN);
} else {
g_is_low_battery_shutdown = false;
}
}
}
/**@brief Function for configuring ADC to do battery level conversion.
*/
static void adc_configure(void)
{
ret_code_t err_code = nrf_drv_saadc_init(NULL, saadc_event_handler);
APP_ERROR_CHECK(err_code);
nrf_saadc_channel_config_t config = NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(BAT_SENSE);
err_code = nrf_drv_saadc_channel_init(0, &config);
APP_ERROR_CHECK(err_code);
err_code = nrf_drv_saadc_buffer_convert(&adc_buf[0], 1);
APP_ERROR_CHECK(err_code);
err_code = nrf_drv_saadc_buffer_convert(&adc_buf[1], 1);
APP_ERROR_CHECK(err_code);
}
/**@brief Function for handling the Battery measurement timer timeout.
*
* @details This function will be called each time the battery level measurement timer expires.
* This function will start the ADC.
*
* @param[in] p_context Pointer used for passing some arbitrary information (context) from the
* app_start_timer() call to the timeout handler.
*/
static void battery_level_meas_timeout_handler(void * p_context)
{
UNUSED_PARAMETER(p_context);
ret_code_t err_code;
err_code = nrf_drv_saadc_sample();
APP_ERROR_CHECK(err_code);
}
void create_battery_timer(void) {
ret_code_t err_code;
// Create battery timer.
err_code = app_timer_create(&m_battery_timer_id, APP_TIMER_MODE_REPEATED, battery_level_meas_timeout_handler);
APP_ERROR_CHECK(err_code);
// Start battery timer
err_code = app_timer_start(m_battery_timer_id, BATTERY_LEVEL_MEAS_INTERVAL, NULL);
APP_ERROR_CHECK(err_code);
}
/**
* @brief Function for init ble slave.
*/
void ble_slave_init(void) {
adc_configure(); // ADC初始化
create_battery_timer(); // 创建电池电量更新定时器
ble_stack_init(); // BLE协议栈初始化
gap_params_init(); // GAP参数初始化
gatt_init(); // GATT协议初始化
+5
View File
@@ -1,6 +1,11 @@
#ifndef BLE_MAIN_H
#define BLE_MAIN_H
#include "ble_gatts.h"
#include "ble_nus.h"
#include "ble_bas.h"
void ble_slave_init(void);
void advertising_start(void);
void nus_data_reponse(uint8_t *p_data, uint16_t length);
@@ -42,7 +42,8 @@ static volatile bool m_is_lf_emulating = false;
const nrfx_timer_t m_timer_send_id = NRFX_TIMER_INSTANCE(3);
// 缓存标签类型
static tag_specific_type_t m_tag_type = TAG_TYPE_UNKNOWN;
// 当前是否需要发送重新进入LF状态的第二个沿
static bool m_is_send_reboardcast_last_edge;
/**
* @brief EM410X的卡号转为U64的内存布局
@@ -74,8 +75,8 @@ uint64_t em410x_id_to_memory64(uint8_t id[5]) {
// 好了,到了目前最关键的时候了,现在需要赋值和计算奇偶校验位了
// 1、先把前导码给赋值了
memory.bit.h00 = memory.bit.h01 = memory.bit.h02 =
memory.bit.h03 = memory.bit.h04 = memory.bit.h05 =
memory.bit.h00 = memory.bit.h01 = memory.bit.h02 =
memory.bit.h03 = memory.bit.h04 = memory.bit.h05 =
memory.bit.h06 = memory.bit.h07 = memory.bit.h08 = 1;
// 2、把8bit的版本或者自定义ID给赋值了
memory.bit.d00 = GETBIT(id[0], 7); memory.bit.d01 = GETBIT(id[0], 6); memory.bit.d02 = GETBIT(id[0], 5); memory.bit.d03 = GETBIT(id[0], 4);
@@ -118,7 +119,8 @@ uint64_t em410x_id_to_memory64(uint8_t id[5]) {
/**
* @brief
*/
static inline bool is_lf_field_exists(void) {
bool lf_is_field_exists(void) {
nrf_drv_lpcomp_enable();
bsp_delay_us(20); // 延迟一段时间再采样,避免误判
nrf_lpcomp_task_trigger(NRF_LPCOMP_TASK_SAMPLE); // 触发一次采样
return nrf_lpcomp_result_get() == 1; // 判断LF场状态的采样结果
@@ -129,27 +131,32 @@ void timer_ce_handler(nrf_timer_event_t event_type, void* p_context) {
// 因为我们配置的是使用CC通道2,所以事件回调
// 函数中判断NRF_TIMER_EVENT_COMPARE0事件
case NRF_TIMER_EVENT_COMPARE2: {
if (m_is_send_first_edge) {
if (GETBIT(m_id_bit_data, m_bit_send_position)) {
// 发送 1 的第一个沿
ANT_TO_MOD();
if(m_is_send_reboardcast_last_edge){
m_is_send_reboardcast_last_edge = false;
ANT_TO_MOD();
}else{
if (m_is_send_first_edge) {
if (GETBIT(m_id_bit_data, m_bit_send_position)) {
// 发送 1 的第一个沿
ANT_TO_MOD();
} else {
// 发送 0 的第一个沿
ANT_NO_MOD();
}
m_is_send_first_edge = false; // 下次发送第二个沿
} else {
// 发送 0 的第一个沿
ANT_NO_MOD();
}
m_is_send_first_edge = false; // 下次发送第二个沿
} else {
if (GETBIT(m_id_bit_data, m_bit_send_position)) {
// 发送 1 的第二个沿
ANT_NO_MOD();
} else {
// 发送 0 的第二个沿
ANT_TO_MOD();
}
m_is_send_first_edge = true; // 下次发送第一个沿
if (++m_bit_send_position >= LF_125KHZ_EM410X_BIT_SIZE) {
m_bit_send_position = 0; // 广播一次成功,bit位置归零
++m_send_id_count; // 统计广播次数
if (GETBIT(m_id_bit_data, m_bit_send_position)) {
// 发送 1 的第二个沿
ANT_NO_MOD();
} else {
// 发送 0 的第二个沿
ANT_TO_MOD();
}
m_is_send_first_edge = true; // 下次发送第一个沿
if (++m_bit_send_position >= LF_125KHZ_EM410X_BIT_SIZE) {
m_bit_send_position = 0; // 广播一次成功,bit位置归零
++m_send_id_count; // 统计广播次数
}
}
}
// 如果广播次数超过上限次数,则重新比较场状态,根据新的场状态选择是否继续模拟标签
@@ -157,19 +164,19 @@ void timer_ce_handler(nrf_timer_event_t event_type, void* p_context) {
m_send_id_count = 0; // 广播次数达到上限,重新识别场状态并且重新统计广播次数
ANT_NO_MOD(); // 确保天线不短路而导致无法获得RSSI状态
nrfx_timer_disable(&m_timer_send_id); // 关闭广播场的定时器
// 我们不需要任何的事件,仅仅需要检测一下场的状态
NRF_LPCOMP->INTENCLR = LPCOMP_INTENCLR_CROSS_Msk | LPCOMP_INTENCLR_UP_Msk | LPCOMP_INTENCLR_DOWN_Msk | LPCOMP_INTENCLR_READY_Msk;
nrf_drv_lpcomp_enable(); // 重启比较器,以便可以重新比较场状态
if (is_lf_field_exists()) {
if (lf_is_field_exists()) {
nrf_drv_lpcomp_disable();
nrfx_timer_enable(&m_timer_send_id); // 打开广播场的定时器,继续模拟
m_is_send_reboardcast_last_edge = true; // 如果继续的话需要发送0的后一个沿
} else {
// 开启事件中断,让下次场事件可以正常出入
NRF_LPCOMP->INTENSET = LPCOMP_INTENCLR_CROSS_Msk | LPCOMP_INTENCLR_UP_Msk | LPCOMP_INTENCLR_DOWN_Msk | LPCOMP_INTENCLR_READY_Msk;
g_is_tag_emulating = false; // 重设模拟中的标志位
m_is_lf_emulating = false;
TAG_FIELD_LED_OFF() // 确保关闭LF的场状态的指示灯
NRF_LPCOMP->INTENSET = LPCOMP_INTENCLR_CROSS_Msk | LPCOMP_INTENCLR_UP_Msk | LPCOMP_INTENCLR_DOWN_Msk | LPCOMP_INTENCLR_READY_Msk;
sleep_timer_start(SLEEP_DELAY_MS_FIELD_125KHZ_LOST); // 启动进入休眠的定时器
NRF_LOG_INFO("LF FIELD LOST");
}
@@ -202,57 +209,46 @@ static void lpcomp_event_handler(nrf_lpcomp_event_t event) {
// 设置模拟状态标志位
m_is_lf_emulating = true;
g_is_tag_emulating = true;
// 模拟卡状态应当关闭USB灯效
g_usb_led_marquee_enable = false;
// LED状态更新
set_slot_light_color(2);
TAG_FIELD_LED_ON()
// 无论如何,每次场状态发现变化都需要重置发送的bit位置
m_send_id_count = 0;
m_bit_send_position = 0;
m_is_send_first_edge = true;
m_is_send_reboardcast_last_edge = false;
// 开启精准的硬件定时器去广播卡号
nrfx_timer_enable(&m_timer_send_id);
NRF_LOG_INFO("LF FIELD DETECTED");
}
}
static void lf_sense_enable(void) {
ret_code_t err_code;
nrf_drv_lpcomp_config_t config = NRF_DRV_LPCOMP_DEFAULT_CONFIG;
config.hal.reference = NRF_LPCOMP_REF_SUPPLY_1_16; // 参考电压
config.input = LF_RSSI; // 输入脚
config.hal.detection = NRF_LPCOMP_DETECT_UP; // 默认上升沿触发
config.hal.hyst = NRF_LPCOMP_HYST_50mV; // 防抖,避免频繁中断
// initialize LPCOMP driver, from this point LPCOMP will be active and provided
// event handler will be executed when defined action is detected
nrf_drv_lpcomp_config_t config = NRF_DRV_LPCOMP_DEFAULT_CONFIG;
config.hal.reference = NRF_LPCOMP_REF_SUPPLY_1_16;
config.input = LF_RSSI;
config.hal.detection = NRF_LPCOMP_DETECT_UP;
config.hal.hyst = NRF_LPCOMP_HYST_50mV;
err_code = nrf_drv_lpcomp_init(&config, lpcomp_event_handler);
APP_ERROR_CHECK(err_code);
nrf_drv_lpcomp_enable(); // 使能低功耗比较器
// 初始化用于震荡曼彻斯特波的定时器
uint32_t time_us = LF_125KHZ_EM410X_BIT_CLOCK; // 定时时间250us
// 保存定时时间对应的Ticks
uint32_t time_ticks;
// 定义定时器配置结构体,并使用默认配置参数初始化结构体
// TAG id broadcast
nrfx_timer_config_t timer_cfg = NRFX_TIMER_DEFAULT_CONFIG;
// 初始化定时器,初始化时会注册timer_led_event_handler事件回调函数
err_code = nrfx_timer_init(&m_timer_send_id, &timer_cfg, timer_ce_handler);
APP_ERROR_CHECK(err_code);
// 定时时间转换为ticks
time_ticks = nrfx_timer_us_to_ticks(&m_timer_send_id, time_us);
// 设置定时器捕获/比较通道及该通道的比较值,使能通道的比较中断
nrfx_timer_extended_compare(&m_timer_send_id, NRF_TIMER_CC_CHANNEL2, time_ticks, NRF_TIMER_SHORT_COMPARE2_CLEAR_MASK, true);
nrfx_timer_extended_compare(&m_timer_send_id, NRF_TIMER_CC_CHANNEL2, nrfx_timer_us_to_ticks(&m_timer_send_id, LF_125KHZ_EM410X_BIT_CLOCK), NRF_TIMER_SHORT_COMPARE2_CLEAR_MASK, true);
// 如果一初始化完就发现当前处于场中,并且没有处于广播状态,就主动触发广播
if (!m_is_lf_emulating && is_lf_field_exists()) {
if (lf_is_field_exists() && !m_is_lf_emulating) {
lpcomp_event_handler(NRF_LPCOMP_EVENT_UP);
}
}
@@ -277,7 +273,7 @@ void lf_tag_125khz_sense_switch(bool enable) {
nrf_gpio_cfg_output(LF_MOD);
// 默认不短路天线(短路会导致RSSI无法判断)
ANT_NO_MOD();
// 首次执行或者是禁用状态,只允许初始化
if (m_lf_sense_state == LF_SENSE_STATE_NONE || m_lf_sense_state == LF_SENSE_STATE_DISABLE) {
if (enable) {
@@ -20,5 +20,6 @@ void lf_tag_125khz_sense_switch(bool enable);
int lf_tag_em410x_data_loadcb(tag_specific_type_t type, tag_data_buffer_t* buffer);
int lf_tag_em410x_data_savecb(tag_specific_type_t type, tag_data_buffer_t* buffer);
bool lf_tag_em410x_data_factory(uint8_t slot, tag_specific_type_t tag_type);
bool lf_is_field_exists(void);
#endif
+17 -17
View File
@@ -4,7 +4,7 @@
// 设备当前处于的模式
static device_mode_t rfid_state = DEVICE_MODE_NONE;
device_mode_t rfid_state = DEVICE_MODE_NONE;
/**
@@ -15,16 +15,16 @@ void reader_mode_enter(void) {
#if defined(PROJECT_CHAMELEON_ULTRA)
if (rfid_state != DEVICE_MODE_READER) {
rfid_state = DEVICE_MODE_READER;
tag_emulation_sense_end(); // to end tag emulation
// pin init
nrf_gpio_cfg_output(LF_ANT_DRIVER);
nrf_gpio_cfg_output(READER_POWER);
nrf_gpio_pin_set(READER_POWER); // reader power enable
nrf_gpio_cfg_output(HF_ANT_SEL);
// to end tag emulation
tag_emulation_sense_end();
// reader power enable
nrf_gpio_pin_set(READER_POWER);
// hf ant switch to reader mode
nrf_gpio_pin_clear(HF_ANT_SEL);
nrf_gpio_pin_clear(HF_ANT_SEL); // hf ant switch to reader mode
// init reader
lf_125khz_radio_init();
pcd_14a_reader_init();
@@ -41,19 +41,19 @@ void tag_mode_enter(void) {
rfid_state = DEVICE_MODE_TAG;
#if defined(PROJECT_CHAMELEON_ULTRA)
// pin init
nrf_gpio_cfg_output(LF_ANT_DRIVER);
nrf_gpio_cfg_output(READER_POWER);
nrf_gpio_cfg_output(HF_ANT_SEL);
// uninit reader
lf_125khz_radio_uninit();
pcd_14a_reader_uninit();
// lf reader driver
nrf_gpio_pin_clear(LF_ANT_DRIVER);
// reader power disable
nrf_gpio_pin_clear(READER_POWER);
// hf ant switch to emulation mode
nrf_gpio_pin_set(HF_ANT_SEL);
// pin init
nrf_gpio_cfg_output(LF_ANT_DRIVER);
nrf_gpio_pin_clear(LF_ANT_DRIVER); // lf reader driver
nrf_gpio_cfg_output(READER_POWER);
nrf_gpio_pin_clear(READER_POWER); // reader power disable
nrf_gpio_cfg_output(HF_ANT_SEL);
nrf_gpio_pin_set(HF_ANT_SEL); // hf ant switch to emulation mode
#endif
// to run tag emulation
+6 -6
View File
@@ -324,7 +324,7 @@
// <e> BLE_BAS_ENABLED - ble_bas - Battery Service
//==========================================================
#ifndef BLE_BAS_ENABLED
#define BLE_BAS_ENABLED 0
#define BLE_BAS_ENABLED 1
#endif
// <e> BLE_BAS_CONFIG_LOG_ENABLED - Enables logging in the module.
//==========================================================
@@ -3329,7 +3329,7 @@
// <e> NRFX_SAADC_ENABLED - nrfx_saadc - SAADC peripheral driver
//==========================================================
#ifndef NRFX_SAADC_ENABLED
#define NRFX_SAADC_ENABLED 0
#define NRFX_SAADC_ENABLED 1
#endif
// <o> NRFX_SAADC_CONFIG_RESOLUTION - Resolution
@@ -3339,7 +3339,7 @@
// <3=> 14 bit
#ifndef NRFX_SAADC_CONFIG_RESOLUTION
#define NRFX_SAADC_CONFIG_RESOLUTION 1
#define NRFX_SAADC_CONFIG_RESOLUTION 3
#endif
// <o> NRFX_SAADC_CONFIG_OVERSAMPLE - Sample period
@@ -5357,7 +5357,7 @@
// <e> SAADC_ENABLED - nrf_drv_saadc - SAADC peripheral driver - legacy layer
//==========================================================
#ifndef SAADC_ENABLED
#define SAADC_ENABLED 0
#define SAADC_ENABLED 1
#endif
// <o> SAADC_CONFIG_RESOLUTION - Resolution
@@ -5367,7 +5367,7 @@
// <3=> 14 bit
#ifndef SAADC_CONFIG_RESOLUTION
#define SAADC_CONFIG_RESOLUTION 1
#define SAADC_CONFIG_RESOLUTION 3
#endif
// <o> SAADC_CONFIG_OVERSAMPLE - Sample period
@@ -6528,7 +6528,7 @@
// <i> Setting string to NULL disables that string.
// <i> The order of manufacturer names must be the same like in @ref APP_USBD_STRINGS_LANGIDS.
#ifndef APP_USBD_STRINGS_MANUFACTURER
#define APP_USBD_STRINGS_MANUFACTURER APP_USBD_STRING_DESC("Porxgrind")
#define APP_USBD_STRINGS_MANUFACTURER APP_USBD_STRING_DESC("Proxgrind")
#endif
// </e>
@@ -65,6 +65,7 @@ void sleep_timer_start(uint32_t time_ms) {
void sleep_system_run(void (*sysOffSleep)(), void (*sysOnSleep)()) {
// No task to process, sleep enter
if (m_system_off_enter) {
m_system_off_enter = false;
// Enter Sleep(System_OFF sleep mode) zzzzz.....
sysOffSleep();
} else {
+3 -2
View File
@@ -10,10 +10,11 @@
// 运行态重新延迟
#define SLEEP_DELAY_MS_BUTTON_CLICK 4000 // 按钮点击的休眠延迟
#define SLEEP_DELAY_MS_FIELD_NFC_LOST 2000 // 高频模拟卡离开场后的休眠延迟
#define SLEEP_DELAY_MS_FIELD_125KHZ_LOST 2000 // 低频模拟卡离开场后的休眠延迟
#define SLEEP_DELAY_MS_FIELD_NFC_LOST 3000 // 高频模拟卡离开场后的休眠延迟
#define SLEEP_DELAY_MS_FIELD_125KHZ_LOST 3000 // 低频模拟卡离开场后的休眠延迟
#define SLEEP_DELAY_MS_BLE_DISCONNECTED 4000 // BLE断开后的休眠延迟
#define SLEEP_DELAY_MS_USB_POWER_DISCONNECTED 3000 // USB供电断开后的休眠延迟
#define SLEEP_NO_BATTERY_SHUTDOWN 1 // 低电量关机
void sleep_timer_init(void);
+1 -1
View File
@@ -5,7 +5,7 @@ GROUP(-lgcc -lc -lnosys)
MEMORY
{
FLASH (rx) : ORIGIN = 0xf3000, LENGTH = 0xb000
FLASH (rx) : ORIGIN = 0xF3000, LENGTH = 0xB000
RAM (rwx) : ORIGIN = 0x20005978, LENGTH = 0x32688
uicr_bootloader_start_address (r) : ORIGIN = 0x10001014, LENGTH = 0x4
bootloader_settings_page (r) : ORIGIN = 0x000FF000, LENGTH = 0x1000
+1 -2
View File
@@ -100,7 +100,6 @@ void app_error_handler_bare(uint32_t error_code)
on_error();
}
static uint8_t m_led_flash_state = 0;
static bool m_led_flash_setp = 0;
static nrfx_systick_state_t systick;
@@ -183,7 +182,7 @@ static void dfu_observer(nrf_dfu_evt_type_t evt_type)
/**@brief Function for application main entry. */
int main(void)
{
uint32_t ret_val;
ret_code_t ret_val;
// Must to init hardware connect.
hw_connect_init();
+1 -1
View File
@@ -204,7 +204,7 @@
// <i> If 0, no inactivity timer will be used. Values 1-99 are invalid.
#ifndef NRF_BL_DFU_INACTIVITY_TIMEOUT_MS
#define NRF_BL_DFU_INACTIVITY_TIMEOUT_MS 120000
#define NRF_BL_DFU_INACTIVITY_TIMEOUT_MS 30000
#endif
// </h>
+56 -84
View File
@@ -34,7 +34,9 @@ uint32_t g_button2;
uint32_t g_lf_mod;
uint32_t g_lf_rssi_pin;
nrf_lpcomp_input_t g_lf_rssi;
uint32_t g_bat_sense;
uint32_t g_bat_sense_pin;
nrf_saadc_input_t g_bat_sense;
#if defined(PROJECT_CHAMELEON_ULTRA)
uint32_t g_lf_ant_driver;
@@ -99,104 +101,74 @@ void hw_connect_init(void) {
// TODO 请实现此处,实现硬件版本号的读取
// 测试的时候可以直接改写此版本号
m_hw_ver = 2;
m_hw_ver = 1;
#if defined(PROJECT_CHAMELEON_ULTRA)
if (m_hw_ver == 1) {
LED_FIELD = (NRF_GPIO_PIN_MAP(1, 1));
LED_R = (NRF_GPIO_PIN_MAP(0, 24));
LED_G = (NRF_GPIO_PIN_MAP(0, 22));
LED_B = (NRF_GPIO_PIN_MAP(1, 0));
LED_8 = (NRF_GPIO_PIN_MAP(0, 20));
LED_7 = (NRF_GPIO_PIN_MAP(0, 17));
LED_6 = (NRF_GPIO_PIN_MAP(0, 15));
LED_5 = (NRF_GPIO_PIN_MAP(0, 13));
LED_4 = (NRF_GPIO_PIN_MAP(0, 12));
LED_3 = (NRF_GPIO_PIN_MAP(1, 9));
LED_2 = (NRF_GPIO_PIN_MAP(0, 8));
LED_1 = (NRF_GPIO_PIN_MAP(0, 6));
RGB_LIST_NUM = 8;
RGB_CTRL_NUM = 3;
LED_FIELD = (NRF_GPIO_PIN_MAP(1, 1));
LED_R = (NRF_GPIO_PIN_MAP(0, 24));
LED_G = (NRF_GPIO_PIN_MAP(0, 22));
LED_B = (NRF_GPIO_PIN_MAP(1, 0));
LED_1 = (NRF_GPIO_PIN_MAP(0, 20));
LED_2 = (NRF_GPIO_PIN_MAP(0, 17));
LED_3 = (NRF_GPIO_PIN_MAP(0, 15));
LED_4 = (NRF_GPIO_PIN_MAP(0, 13));
LED_5 = (NRF_GPIO_PIN_MAP(0, 12));
LED_6 = (NRF_GPIO_PIN_MAP(1, 9));
LED_7 = (NRF_GPIO_PIN_MAP(0, 8));
LED_8 = (NRF_GPIO_PIN_MAP(0, 6));
RGB_LIST_NUM = 8;
RGB_CTRL_NUM = 3;
LF_ANT_DRIVER = (NRF_GPIO_PIN_MAP(0, 31));
LF_OA_OUT = (NRF_GPIO_PIN_MAP(1, 15));
LF_MOD = (NRF_GPIO_PIN_MAP(1, 13));
LF_RSSI_PIN = (NRF_GPIO_PIN_MAP(0, 2));
LF_RSSI = NRF_LPCOMP_INPUT_0;
LF_ANT_DRIVER = (NRF_GPIO_PIN_MAP(0, 31));
LF_OA_OUT = (NRF_GPIO_PIN_MAP(0, 29));
LF_MOD = (NRF_GPIO_PIN_MAP(1, 13));
LF_RSSI_PIN = (NRF_GPIO_PIN_MAP(0, 2));
LF_RSSI = NRF_LPCOMP_INPUT_0;
HF_SPI_SELECT = (NRF_GPIO_PIN_MAP(1, 6));
HF_SPI_MISO = (NRF_GPIO_PIN_MAP(0, 11));
HF_SPI_MOSI = (NRF_GPIO_PIN_MAP(1, 7));
HF_SPI_SCK = (NRF_GPIO_PIN_MAP(1, 4));
HF_ANT_SEL = (NRF_GPIO_PIN_MAP(1, 10));
HF_SPI_SELECT = (NRF_GPIO_PIN_MAP(1, 6));
HF_SPI_MISO = (NRF_GPIO_PIN_MAP(0, 11));
HF_SPI_MOSI = (NRF_GPIO_PIN_MAP(1, 7));
HF_SPI_SCK = (NRF_GPIO_PIN_MAP(1, 4));
HF_ANT_SEL = (NRF_GPIO_PIN_MAP(1, 10));
BUTTON_1 = (NRF_GPIO_PIN_MAP(0, 26));
BUTTON_2 = (NRF_GPIO_PIN_MAP(1, 2));
READER_POWER = (NRF_GPIO_PIN_MAP(1, 15));
BAT_SENSE = (NRF_GPIO_PIN_MAP(0, 4));
READER_POWER = (NRF_GPIO_PIN_MAP(0, 29));
}
if (m_hw_ver == 2) {
LED_FIELD = (NRF_GPIO_PIN_MAP(1, 1));
LED_R = (NRF_GPIO_PIN_MAP(0, 24));
LED_G = (NRF_GPIO_PIN_MAP(0, 22));
LED_B = (NRF_GPIO_PIN_MAP(1, 0));
LED_1 = (NRF_GPIO_PIN_MAP(0, 20));
LED_2 = (NRF_GPIO_PIN_MAP(0, 17));
LED_3 = (NRF_GPIO_PIN_MAP(0, 15));
LED_4 = (NRF_GPIO_PIN_MAP(0, 13));
LED_5 = (NRF_GPIO_PIN_MAP(0, 12));
LED_6 = (NRF_GPIO_PIN_MAP(1, 9));
LED_7 = (NRF_GPIO_PIN_MAP(0, 8));
LED_8 = (NRF_GPIO_PIN_MAP(0, 6));
RGB_LIST_NUM = 8;
RGB_CTRL_NUM = 3;
BUTTON_2 = (NRF_GPIO_PIN_MAP(0, 26));
BUTTON_1 = (NRF_GPIO_PIN_MAP(1, 2));
LF_ANT_DRIVER = (NRF_GPIO_PIN_MAP(0, 31));
LF_OA_OUT = (NRF_GPIO_PIN_MAP(0, 29));
LF_MOD = (NRF_GPIO_PIN_MAP(1, 13));
LF_RSSI_PIN = (NRF_GPIO_PIN_MAP(0, 2));
LF_RSSI = NRF_LPCOMP_INPUT_0;
HF_SPI_SELECT = (NRF_GPIO_PIN_MAP(1, 6));
HF_SPI_MISO = (NRF_GPIO_PIN_MAP(0, 11));
HF_SPI_MOSI = (NRF_GPIO_PIN_MAP(1, 7));
HF_SPI_SCK = (NRF_GPIO_PIN_MAP(1, 4));
HF_ANT_SEL = (NRF_GPIO_PIN_MAP(1, 10));
BUTTON_2 = (NRF_GPIO_PIN_MAP(0, 26));
BUTTON_1 = (NRF_GPIO_PIN_MAP(1, 2));
BAT_SENSE = (NRF_GPIO_PIN_MAP(0, 4));
READER_POWER = (NRF_GPIO_PIN_MAP(1, 15));
BAT_SENSE_PIN = (NRF_GPIO_PIN_MAP(0, 4));
BAT_SENSE = NRF_SAADC_INPUT_AIN2;
}
#endif
#if defined(PROJECT_CHAMELEON_LITE)
if (m_hw_ver == 1) {
LED_FIELD = (NRF_GPIO_PIN_MAP(1, 1));
LED_1 = (NRF_GPIO_PIN_MAP(0, 22));
LED_2 = (NRF_GPIO_PIN_MAP(0, 20));
LED_3 = (NRF_GPIO_PIN_MAP(0, 17));
LED_4 = (NRF_GPIO_PIN_MAP(0, 15));
LED_5 = (NRF_GPIO_PIN_MAP(0, 13));
LED_6 = (NRF_GPIO_PIN_MAP(0, 6));
LED_7 = (NRF_GPIO_PIN_MAP(0, 4));
LED_8 = (NRF_GPIO_PIN_MAP(0, 26));
LED_R = (NRF_GPIO_PIN_MAP(0, 8));
LED_G = (NRF_GPIO_PIN_MAP(0, 12));
LED_B = (NRF_GPIO_PIN_MAP(1, 9));
RGB_LIST_NUM = 8;
RGB_CTRL_NUM = 3;
BUTTON_1 = (NRF_GPIO_PIN_MAP(1, 2));
BUTTON_2 = (NRF_GPIO_PIN_MAP(1, 6));
LED_FIELD = (NRF_GPIO_PIN_MAP(1, 1));
LED_1 = (NRF_GPIO_PIN_MAP(0, 22));
LED_2 = (NRF_GPIO_PIN_MAP(0, 20));
LED_3 = (NRF_GPIO_PIN_MAP(0, 17));
LED_4 = (NRF_GPIO_PIN_MAP(0, 15));
LED_5 = (NRF_GPIO_PIN_MAP(0, 13));
LED_6 = (NRF_GPIO_PIN_MAP(0, 6));
LED_7 = (NRF_GPIO_PIN_MAP(0, 4));
LED_8 = (NRF_GPIO_PIN_MAP(0, 26));
LED_R = (NRF_GPIO_PIN_MAP(0, 8));
LED_G = (NRF_GPIO_PIN_MAP(0, 12));
LED_B = (NRF_GPIO_PIN_MAP(1, 9));
RGB_LIST_NUM = 8;
RGB_CTRL_NUM = 3;
LF_MOD = (NRF_GPIO_PIN_MAP(1, 4));
LF_RSSI_PIN = (NRF_GPIO_PIN_MAP(0, 2));
LF_RSSI = NRF_LPCOMP_INPUT_0;
BAT_SENSE = (NRF_GPIO_PIN_MAP(0, 29));
LF_MOD = (NRF_GPIO_PIN_MAP(1, 4));
LF_RSSI_PIN = (NRF_GPIO_PIN_MAP(0, 2));
LF_RSSI = NRF_LPCOMP_INPUT_0;
BUTTON_1 = (NRF_GPIO_PIN_MAP(1, 2));
BUTTON_2 = (NRF_GPIO_PIN_MAP(1, 6));
BAT_SENSE_PIN = (NRF_GPIO_PIN_MAP(0, 29));
BAT_SENSE = NRF_SAADC_INPUT_AIN5;
}
#endif
+25 -23
View File
@@ -5,6 +5,7 @@
#define HW_CONNECT_H_
#include "nrf_lpcomp.h"
#include "nrf_saadc.h"
#include "device_info.h"
typedef enum {
@@ -36,31 +37,32 @@ extern uint32_t g_button2;
extern uint32_t g_lf_mod;
extern uint32_t g_lf_rssi_pin;
extern nrf_lpcomp_input_t g_lf_rssi;
extern uint32_t g_bat_sense;
extern uint32_t g_bat_sense_pin;
extern nrf_saadc_input_t g_bat_sense;
#define LED_FIELD g_led_field
#define LED_1 g_led_1
#define LED_2 g_led_2
#define LED_3 g_led_3
#define LED_4 g_led_4
#define LED_5 g_led_5
#define LED_6 g_led_6
#define LED_7 g_led_7
#define LED_8 g_led_8
#define LED_R g_led_r
#define LED_G g_led_g
#define LED_B g_led_b
#define RGB_LIST_NUM g_led_num
#define RGB_CTRL_NUM g_rgb_num
#define BUTTON_1 g_button1
#define BUTTON_2 g_button2
#define BUTTON_PULL NRF_GPIO_PIN_PULLDOWN
#define LF_MOD g_lf_mod
#define LF_RSSI_PIN g_lf_rssi_pin
#define LF_RSSI g_lf_rssi
#define BAT_SENSE g_bat_sense
#define LED_FIELD g_led_field
#define LED_1 g_led_1
#define LED_2 g_led_2
#define LED_3 g_led_3
#define LED_4 g_led_4
#define LED_5 g_led_5
#define LED_6 g_led_6
#define LED_7 g_led_7
#define LED_8 g_led_8
#define LED_R g_led_r
#define LED_G g_led_g
#define LED_B g_led_b
#define RGB_LIST_NUM g_led_num
#define RGB_CTRL_NUM g_rgb_num
#define BUTTON_1 g_button1
#define BUTTON_2 g_button2
#define BUTTON_PULL NRF_GPIO_PIN_PULLDOWN
#define LF_MOD g_lf_mod
#define LF_RSSI_PIN g_lf_rssi_pin
#define LF_RSSI g_lf_rssi
#define BAT_SENSE_PIN g_bat_sense_pin
#define BAT_SENSE g_bat_sense
#if defined(PROJECT_CHAMELEON_ULTRA)
extern uint32_t g_lf_ant_driver;
@@ -129,6 +129,23 @@ static void do_reset(void * p_context)
NVIC_SystemReset();
}
static void do_systemoff(void * p_context) {
UNUSED_PARAMETER(p_context);
NRF_LOG_FINAL_FLUSH();
nrf_delay_ms(NRF_BL_RESET_DELAY_MS);
// reinit leds status
init_leds();
set_slot_light_color(3);
// systemoff mode, deepsleep
nrf_power_system_off();
}
static bool check_usb_attach(void) {
return nrfx_power_usbstatus_get() != NRFX_POWER_USB_STATE_DISCONNECTED;
}
static void bootloader_reset(bool do_backup)
{
@@ -137,7 +154,12 @@ static void bootloader_reset(bool do_backup)
if (do_backup)
{
m_flash_write_done = false;
nrf_dfu_settings_backup(do_reset);
// The usb is attach, we can reset system.
if (check_usb_attach()) {
nrf_dfu_settings_backup(do_reset);
} else {
nrf_dfu_settings_backup(do_systemoff);
}
}
else
{
@@ -161,9 +183,7 @@ static void dfu_observer(nrf_dfu_evt_type_t evt_type)
{
case NRF_DFU_EVT_DFU_STARTED:
case NRF_DFU_EVT_OBJECT_RECEIVED:
nrf_bootloader_dfu_inactivity_timer_restart(
NRF_BOOTLOADER_MS_TO_TICKS(NRF_BL_DFU_INACTIVITY_TIMEOUT_MS),
inactivity_timeout);
nrf_bootloader_dfu_inactivity_timer_restart(NRF_BOOTLOADER_MS_TO_TICKS(NRF_BL_DFU_INACTIVITY_TIMEOUT_MS), inactivity_timeout);
break;
case NRF_DFU_EVT_DFU_COMPLETED:
case NRF_DFU_EVT_DFU_ABORTED:
@@ -232,11 +252,9 @@ static void loop_forever(void)
#endif
/**@brief Function for initializing button used to enter DFU mode.
*/
static void dfu_enter_button_init(void)
void dfu_enter_button_init(void)
{
nrf_gpio_cfg_sense_input(NRF_BL_DFU_ENTER_METHOD_BUTTON_PIN,
BUTTON_PULL,
NRF_GPIO_PIN_SENSE_LOW);
nrf_gpio_cfg_sense_input(NRF_BL_DFU_ENTER_METHOD_BUTTON_PIN, BUTTON_PULL, NRF_GPIO_PIN_SENSE_HIGH);
}
#endif
@@ -370,7 +388,7 @@ static bool dfu_enter_check(void)
bool is_usb_attach = false;
// 如果按钮一直是按下的状态,则等待用户释放按钮,期间检测USB插入,如果是插入状态,则进入DFU模式
while (nrf_gpio_pin_read(NRF_BL_DFU_ENTER_METHOD_BUTTON_PIN) == 1) {
is_usb_attach = nrfx_power_usbstatus_get() != NRFX_POWER_USB_STATE_DISCONNECTED;
is_usb_attach = check_usb_attach();
}
NRF_LOG_DEBUG("DFU mode requested via button.");
// 按钮按下,但是USB没插入,则进入普通APP模式,
@@ -251,7 +251,7 @@ all: $(TARGETS)
# Create build directories
$(OUTPUT_DIRECTORY):
$(MK) $@
$(MK) $@
$(OUTPUT_DIRECTORY)/%/.: | $(OUTPUT_DIRECTORY)
cd $(OUTPUT_DIRECTORY) && $(MK) $*
+3 -1
View File
@@ -3,4 +3,6 @@ bin/
# Ignore the python library cache
script/__pycache__
# Ignore the compilers output folder
src/out
src/out
# Ignore the compiled scripts
script/

Some files were not shown because too many files have changed in this diff Show More