save epd config on flash

This commit is contained in:
Shuanglei Tao
2024-11-14 18:01:52 +08:00
parent bd5addaa70
commit 18db97f5be
6 changed files with 154 additions and 51 deletions

View File

@@ -13,15 +13,16 @@
#include <string.h>
#include "nordic_common.h"
#include "ble_srv_common.h"
#include "nrf_nvmc.h"
#include "nrf_log.h"
#include "EPD_4in2.h"
#include "EPD_4in2_V2.h"
#include "EPD_4in2b_V2.h"
#include "EPD_ble.h"
#define BLE_EPD_CONFIG_ADDR (NRF_FICR->CODEPAGESIZE * (NRF_FICR->CODESIZE - 1)) // Last page of the flash
#define BLE_EPD_BASE_UUID {{0XEC, 0X5A, 0X67, 0X1C, 0XC1, 0XB6, 0X46, 0XFB, \
0X8D, 0X91, 0X28, 0XD8, 0X22, 0X36, 0X75, 0X62}}
#define BLE_UUID_EPD_SERVICE 0x0001
#define BLE_UUID_EPD_CHARACTERISTIC 0x0002
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
@@ -39,6 +40,29 @@ static epd_driver_t epd_drivers[] = {
EPD_4IN2B_V2_UpdateDisplay, EPD_4IN2B_V2_Sleep},
};
static epd_driver_t *epd_driver_get(uint8_t id)
{
for (uint8_t i = 0; i < ARRAY_SIZE(epd_drivers); i++)
{
if (epd_drivers[i].id == id)
{
return &epd_drivers[i];
}
}
return NULL;
}
static void epd_config_load(epd_config_t *cfg)
{
memcpy(cfg, (void *)BLE_EPD_CONFIG_ADDR, sizeof(epd_config_t));
}
static void epd_config_save(epd_config_t *cfg)
{
nrf_nvmc_page_erase(BLE_EPD_CONFIG_ADDR);
nrf_nvmc_write_words(BLE_EPD_CONFIG_ADDR, (uint32_t*)cfg, sizeof(epd_config_t) / sizeof(uint32_t));
}
/**@brief Function for handling the @ref BLE_GAP_EVT_CONNECTED event from the S110 SoftDevice.
*
* @param[in] p_epd EPD Service structure.
@@ -72,31 +96,35 @@ static void epd_service_process(ble_epd_t * p_epd, uint8_t * p_data, uint16_t le
{
case EPD_CMD_SET_PINS:
if (length < 8) return;
NRF_LOG_PRINTF("[EPD]: MOSI=0x%02x SCLK=0x%02x CS=0x%02x DC=0x%02x RST=0x%02x BUSY=0x%02x BS=0x%02x\n",
p_data[1], p_data[2], p_data[3], p_data[4], p_data[5], p_data[6], p_data[7]);
EPD_MOSI_PIN = p_data[1];
EPD_SCLK_PIN = p_data[2];
EPD_CS_PIN = p_data[3];
EPD_DC_PIN = p_data[4];
EPD_RST_PIN = p_data[5];
EPD_BUSY_PIN = p_data[6];
EPD_BS_PIN = p_data[7];
DEV_Module_Exit();
EPD_MOSI_PIN = p_epd->config.mosi_pin = p_data[1];
EPD_SCLK_PIN = p_epd->config.sclk_pin = p_data[2];
EPD_CS_PIN = p_epd->config.cs_pin = p_data[3];
EPD_DC_PIN = p_epd->config.dc_pin = p_data[4];
EPD_RST_PIN = p_epd->config.rst_pin = p_data[5];
EPD_BUSY_PIN = p_epd->config.busy_pin = p_data[6];
EPD_BS_PIN = p_epd->config.bs_pin = p_data[7];
epd_config_save(&p_epd->config);
NRF_LOG_PRINTF("[EPD]: MOSI=0x%02x SCLK=0x%02x CS=0x%02x DC=0x%02x RST=0x%02x BUSY=0x%02x BS=0x%02x\n",
EPD_MOSI_PIN, EPD_SCLK_PIN, EPD_CS_PIN, EPD_DC_PIN, EPD_RST_PIN, EPD_BUSY_PIN, EPD_BS_PIN);
DEV_Module_Init();
break;
case EPD_CMD_INIT:
if (length > 1)
{
for (uint8_t i = 0; i < ARRAY_SIZE(epd_drivers); i++)
epd_driver_t *driver = epd_driver_get(p_data[1]);
if (driver != NULL)
{
if (epd_drivers[i].id == p_data[1])
{
p_epd->driver = &epd_drivers[i];
}
p_epd->driver = driver;
p_epd->config.driver_id = driver->id;
epd_config_save(&p_epd->config);
}
}
if (p_epd->driver == NULL) p_epd->driver= &epd_drivers[0];
NRF_LOG_PRINTF("[EPD]: DRIVER=%d\n", p_epd->driver->id);
p_epd->driver->init();
break;
@@ -267,6 +295,44 @@ uint32_t ble_epd_init(ble_epd_t * p_epd)
p_epd->conn_handle = BLE_CONN_HANDLE_INVALID;
p_epd->is_notification_enabled = false;
// Load epd config
epd_config_load(&p_epd->config);
bool save_config = false;
if (p_epd->config.mosi_pin == 0xFF && p_epd->config.sclk_pin == 0xFF &&
p_epd->config.cs_pin == 0xFF && p_epd->config.dc_pin == 0xFF &&
p_epd->config.rst_pin == 0xFF && p_epd->config.busy_pin == 0xFF &&
p_epd->config.bs_pin == 0xFF)
{
p_epd->config.mosi_pin = EPD_MOSI_PIN;
p_epd->config.sclk_pin = EPD_SCLK_PIN;
p_epd->config.cs_pin = EPD_CS_PIN;
p_epd->config.dc_pin = EPD_DC_PIN;
p_epd->config.rst_pin = EPD_RST_PIN;
p_epd->config.busy_pin = EPD_BUSY_PIN;
p_epd->config.bs_pin = EPD_BS_PIN;
save_config = true;
}
else
{
EPD_MOSI_PIN = p_epd->config.mosi_pin;
EPD_SCLK_PIN = p_epd->config.sclk_pin;
EPD_CS_PIN = p_epd->config.cs_pin;
EPD_DC_PIN = p_epd->config.dc_pin;
EPD_RST_PIN = p_epd->config.rst_pin;
EPD_BUSY_PIN = p_epd->config.busy_pin;
EPD_BS_PIN = p_epd->config.bs_pin;
}
p_epd->driver = epd_driver_get(p_epd->config.driver_id);
if (p_epd->driver == NULL)
{
p_epd->driver = &epd_drivers[0];
p_epd->config.driver_id = p_epd->driver->id;
save_config = true;
}
if (save_config) {
epd_config_save(&p_epd->config);
}
// Add the service.
return epd_service_init(p_epd);
}

View File

@@ -19,8 +19,24 @@
#include <stdbool.h>
#include "DEV_Config.h"
#define BLE_EPD_MAX_DATA_LEN (GATT_MTU_SIZE_DEFAULT - 3) /**< Maximum length of data (in bytes) that can be transmitted to the peer. */
#define BLE_UUID_EPD_SERVICE 0x0001
#define EPD_SERVICE_UUID_TYPE BLE_UUID_TYPE_VENDOR_BEGIN
#define BLE_EPD_MAX_DATA_LEN (GATT_MTU_SIZE_DEFAULT - 3) /**< Maximum length of data (in bytes) that can be transmitted to the peer. */
/**< EPD Service Configs */
typedef struct
{
uint32_t mosi_pin;
uint32_t sclk_pin;
uint32_t cs_pin;
uint32_t dc_pin;
uint32_t rst_pin;
uint32_t busy_pin;
uint32_t bs_pin;
uint32_t driver_id;
} epd_config_t;
/**< EPD Service command IDs. */
enum EPD_CMDS
{
EPD_CMD_SET_PINS,
@@ -32,10 +48,7 @@ enum EPD_CMDS
EPD_CMD_SLEEP,
};
/* Forward declaration of the epd_driver_t type. */
typedef struct epd_driver_s epd_driver_t;
/**< epd driver DIs. */
/**< EPD driver IDs. */
enum EPD_DRIVER_IDS
{
EPD_DRIVER_4IN2 = 1,
@@ -47,7 +60,7 @@ enum EPD_DRIVER_IDS
*
* @details This structure contains epd driver functions.
*/
struct epd_driver_s
typedef struct
{
uint8_t id; /**< driver ID. */
void (*init)(void); /**< Initialize the e-Paper register */
@@ -56,16 +69,13 @@ struct epd_driver_s
void (*send_data)(UBYTE Data); /**< send data */
void (*display)(void); /**< Sends the image buffer in RAM to e-Paper and displays */
void (*sleep)(void); /**< Enter sleep mode */
};
/* Forward declaration of the ble_epd_t type. */
typedef struct ble_epd_s ble_epd_t;
} epd_driver_t;
/**@brief EPD Service structure.
*
* @details This structure contains status information related to the service.
*/
struct ble_epd_s
typedef struct
{
uint8_t uuid_type; /**< UUID type for EPD Service Base UUID. */
uint16_t service_handle; /**< Handle of EPD Service (as provided by the S110 SoftDevice). */
@@ -73,7 +83,8 @@ struct ble_epd_s
uint16_t conn_handle; /**< Handle of the current connection (as provided by the S110 SoftDevice). BLE_CONN_HANDLE_INVALID if not in a connection. */
bool is_notification_enabled; /**< Variable to indicate if the peer has enabled notification of the RX characteristic.*/
epd_driver_t *driver; /**< current EPD driver */
};
epd_config_t config; /**< EPD config */
} ble_epd_t;
/**@brief Function for initializing the EPD Service.
*

View File

@@ -388,16 +388,16 @@
<FileType>1</FileType>
<FilePath>..\main.c</FilePath>
</File>
<File>
<FileName>nrf_drv_config.h</FileName>
<FileType>5</FileType>
<FilePath>..\config\nrf_drv_config.h</FilePath>
</File>
<File>
<FileName>bsp.h</FileName>
<FileType>5</FileType>
<FilePath>..\config\bsp.h</FilePath>
</File>
<File>
<FileName>nrf_drv_config.h</FileName>
<FileType>5</FileType>
<FilePath>..\config\nrf_drv_config.h</FilePath>
</File>
</Files>
</Group>
<Group>
@@ -483,6 +483,11 @@
<FileType>1</FileType>
<FilePath>..\components\drivers_nrf\twi_master\nrf_drv_twi.c</FilePath>
</File>
<File>
<FileName>nrf_nvmc.c</FileName>
<FileType>1</FileType>
<FilePath>..\components\drivers_nrf\hal\nrf_nvmc.c</FilePath>
</File>
<File>
<FileName>pstorage.c</FileName>
<FileType>1</FileType>
@@ -935,16 +940,16 @@
<FileType>1</FileType>
<FilePath>..\main.c</FilePath>
</File>
<File>
<FileName>nrf_drv_config.h</FileName>
<FileType>5</FileType>
<FilePath>..\config\nrf_drv_config.h</FilePath>
</File>
<File>
<FileName>bsp.h</FileName>
<FileType>5</FileType>
<FilePath>..\config\bsp.h</FilePath>
</File>
<File>
<FileName>nrf_drv_config.h</FileName>
<FileType>5</FileType>
<FilePath>..\config\nrf_drv_config.h</FilePath>
</File>
</Files>
</Group>
<Group>
@@ -1030,6 +1035,11 @@
<FileType>1</FileType>
<FilePath>..\components\drivers_nrf\twi_master\nrf_drv_twi.c</FilePath>
</File>
<File>
<FileName>nrf_nvmc.c</FileName>
<FileType>1</FileType>
<FilePath>..\components\drivers_nrf\hal\nrf_nvmc.c</FilePath>
</File>
<File>
<FileName>pstorage.c</FileName>
<FileType>1</FileType>
@@ -1482,16 +1492,16 @@
<FileType>1</FileType>
<FilePath>..\main.c</FilePath>
</File>
<File>
<FileName>nrf_drv_config.h</FileName>
<FileType>5</FileType>
<FilePath>..\config\nrf_drv_config.h</FilePath>
</File>
<File>
<FileName>bsp.h</FileName>
<FileType>5</FileType>
<FilePath>..\config\bsp.h</FilePath>
</File>
<File>
<FileName>nrf_drv_config.h</FileName>
<FileType>5</FileType>
<FilePath>..\config\nrf_drv_config.h</FilePath>
</File>
</Files>
</Group>
<Group>
@@ -1577,6 +1587,11 @@
<FileType>1</FileType>
<FilePath>..\components\drivers_nrf\twi_master\nrf_drv_twi.c</FilePath>
</File>
<File>
<FileName>nrf_nvmc.c</FileName>
<FileType>1</FileType>
<FilePath>..\components\drivers_nrf\hal\nrf_nvmc.c</FilePath>
</File>
<File>
<FileName>pstorage.c</FileName>
<FileType>1</FileType>

View File

@@ -1,4 +1,9 @@
#ifndef EPD_BSP_H__
#define EPD_BSP_H__
#define RX_PIN_NUMBER 0
#define TX_PIN_NUMBER 6
#define RTS_PIN_NUMBER 0
#define CTS_PIN_NUMBER 0
#endif

View File

@@ -5,7 +5,6 @@ let writeCharacteristic;
let reconnectTrys = 0;
let canvas;
let epdDriver;
let startTime;
let chunkSize = 38;
@@ -46,14 +45,16 @@ async function sendcmd(cmdTXT) {
}
async function setDriver() {
epdDriver = document.getElementById("epddriver").value;
let epdDriver = document.getElementById("epddriver").value;
let pins = document.getElementById("epdpins").value;
await sendcmd("00" + pins);
await sendcmd("01" + epdDriver);
await sendcmd("06");
}
async function clearscreen() {
if(confirm('确认清除屏幕内容?')) {
await sendcmd("01" + epdDriver);
await sendcmd("01");
await sendcmd("02");
await sendcmd("06");
}
@@ -79,7 +80,7 @@ async function sendimg(cmdIMG) {
let imgArray = cmdIMG.replace(/(?:\r\n|\r|\n|,|0x| )/g, '');
const bwArrLen = (canvas.width/8) * canvas.height * 2;
await sendcmd("01" + epdDriver);
await sendcmd("01");
if (imgArray.length == bwArrLen * 2) {
await sendcmd("0310");
await sendIMGArray(imgArray.slice(0, bwArrLen - 1));
@@ -197,8 +198,7 @@ function intToHex(intIn) {
function updateImageData(canvas) {
document.getElementById('cmdIMAGE').value = bytesToHex(canvas2bytes(canvas, 'bw'));
if (document.getElementById("epddriver").value == '03' &&
document.getElementById('dithering').value.startsWith('bwr')) {
if (document.getElementById('dithering').value.startsWith('bwr')) {
document.getElementById('cmdIMAGE').value += bytesToHex(canvas2bytes(canvas, 'bwr'));
}
}
@@ -242,7 +242,6 @@ function convert_dithering() {
}
document.body.onload = () => {
epdDriver = document.getElementById("epddriver").value;
canvas = document.getElementById('canvas');
updateButtonStatus();

9
main.c
View File

@@ -15,6 +15,7 @@
#include "nordic_common.h"
#include "nrf.h"
#include "nrf_log.h"
#include "nrf_nvmc.h"
#include "ble.h"
#include "ble_hci.h"
#include "ble_srv_common.h"
@@ -46,6 +47,7 @@
#define DEAD_BEEF 0xDEADBEEF /**< Value used as error code on stack dump, can be used to identify stack location on stack unwind. */
static uint16_t m_conn_handle = BLE_CONN_HANDLE_INVALID; /**< Handle of the current connection. */
static ble_uuid_t m_adv_uuids[] = {{BLE_UUID_EPD_SERVICE, EPD_SERVICE_UUID_TYPE}}; /**< Universally unique service identifier. */
static ble_epd_t m_epd; /**< Structure to identify the EPD Service. */
/**@brief Callback function for asserts in the SoftDevice.
@@ -324,19 +326,24 @@ static void advertising_init(void)
{
uint32_t err_code;
ble_advdata_t advdata;
ble_advdata_t scanrsp;
// Build advertising data struct to pass into @ref ble_advertising_init.
memset(&advdata, 0, sizeof(advdata));
advdata.name_type = BLE_ADVDATA_FULL_NAME;
advdata.flags = BLE_GAP_ADV_FLAGS_LE_ONLY_LIMITED_DISC_MODE;
memset(&scanrsp, 0, sizeof(scanrsp));
scanrsp.uuids_complete.uuid_cnt = sizeof(m_adv_uuids) / sizeof(m_adv_uuids[0]);
scanrsp.uuids_complete.p_uuids = m_adv_uuids;
ble_adv_modes_config_t options = {0};
options.ble_adv_fast_enabled = BLE_ADV_FAST_ENABLED;
options.ble_adv_fast_interval = APP_ADV_INTERVAL;
options.ble_adv_fast_timeout = APP_ADV_TIMEOUT_IN_SECONDS;
err_code = ble_advertising_init(&advdata, NULL, &options, on_adv_evt, NULL);
err_code = ble_advertising_init(&advdata, &scanrsp, &options, on_adv_evt, NULL);
APP_ERROR_CHECK(err_code);
}