clang-format code

This commit is contained in:
Shuanglei Tao
2025-10-27 20:52:09 +08:00
parent bf6df54f49
commit 8211ca3202
19 changed files with 1974 additions and 2468 deletions

6
.clang-format Normal file
View File

@@ -0,0 +1,6 @@
BasedOnStyle: Google
Language: Cpp
ColumnLimit: 120
IndentWidth: 4
TabWidth: 4
UseTab: Never

View File

@@ -1,26 +1,25 @@
#include <string.h>
#include "nordic_common.h"
#include "fds.h"
#include "app_scheduler.h"
#include "EPD_config.h"
#include <string.h>
#include "app_scheduler.h"
#include "fds.h"
#include "nordic_common.h"
#include "nrf_log.h"
#define CONFIG_FILE_ID 0x0000
#define CONFIG_REC_KEY 0x0001
static void fds_evt_handler(fds_evt_t const * const p_fds_evt)
{
static void fds_evt_handler(fds_evt_t const* const p_fds_evt) {
NRF_LOG_DEBUG("fds evt: id=%d result=%d\n", p_fds_evt->id, p_fds_evt->result);
}
static void run_fds_gc(void * p_event_data, uint16_t event_size)
{
static void run_fds_gc(void* p_event_data, uint16_t event_size) {
NRF_LOG_DEBUG("run garbage collection (fds_gc)\n");
fds_gc();
}
void epd_config_init(epd_config_t *cfg)
{
void epd_config_init(epd_config_t* cfg) {
ret_code_t ret;
ret = fds_register(fds_evt_handler);
@@ -38,8 +37,7 @@ void epd_config_init(epd_config_t *cfg)
run_fds_gc(NULL, 0);
}
void epd_config_read(epd_config_t *cfg)
{
void epd_config_read(epd_config_t* cfg) {
fds_flash_record_t flash_record;
fds_record_desc_t record_desc;
fds_find_token_t ftok;
@@ -64,8 +62,7 @@ void epd_config_read(epd_config_t *cfg)
fds_record_close(&record_desc);
}
void epd_config_write(epd_config_t *cfg)
{
void epd_config_write(epd_config_t* cfg) {
ret_code_t ret;
fds_record_t record;
fds_record_desc_t record_desc;
@@ -93,13 +90,11 @@ void epd_config_write(epd_config_t *cfg)
if (ret != NRF_SUCCESS) {
NRF_LOG_ERROR("epd_config_save: record write/update failed, code=%d\n", ret);
if (ret == FDS_ERR_NO_SPACE_IN_FLASH)
app_sched_event_put(NULL, 0, run_fds_gc);
if (ret == FDS_ERR_NO_SPACE_IN_FLASH) app_sched_event_put(NULL, 0, run_fds_gc);
}
}
void epd_config_clear(epd_config_t *cfg)
{
void epd_config_clear(epd_config_t* cfg) {
ret_code_t ret;
fds_record_desc_t record_desc;
fds_find_token_t ftok;
@@ -116,11 +111,9 @@ void epd_config_clear(epd_config_t *cfg)
}
}
bool epd_config_empty(epd_config_t *cfg)
{
bool epd_config_empty(epd_config_t* cfg) {
for (uint8_t i = 0; i < EPD_CONFIG_SIZE; i++) {
if (((uint8_t *)cfg)[i] != 0xFF)
return false;
if (((uint8_t*)cfg)[i] != 0xFF) return false;
}
return true;
}

View File

@@ -3,8 +3,7 @@
#include <stdbool.h>
#include <stdint.h>
typedef struct
{
typedef struct {
uint8_t mosi_pin;
uint8_t sclk_pin;
uint8_t cs_pin;

View File

@@ -1,6 +1,7 @@
#include "EPD_driver.h"
#include "app_error.h"
#include "nrf_drv_spi.h"
#include "EPD_driver.h"
#include "nrf_log.h"
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
@@ -24,19 +25,15 @@ static const nrf_drv_spi_t spi = NRF_DRV_SPI_INSTANCE(SPI_INSTANCE); /**< SPI i
#define HAL_SPI_INSTANCE spi.u.spi.p_reg
#else
#define HAL_SPI_INSTANCE spi.p_registers
nrf_gpio_pin_dir_t nrf_gpio_pin_dir_get(uint32_t pin)
{
nrf_gpio_pin_dir_t nrf_gpio_pin_dir_get(uint32_t pin) {
NRF_GPIO_Type* reg = nrf_gpio_pin_port_decode(&pin);
return (nrf_gpio_pin_dir_t)((reg->PIN_CNF[pin] &
GPIO_PIN_CNF_DIR_Msk) >> GPIO_PIN_CNF_DIR_Pos);
return (nrf_gpio_pin_dir_t)((reg->PIN_CNF[pin] & GPIO_PIN_CNF_DIR_Msk) >> GPIO_PIN_CNF_DIR_Pos);
}
#endif
// Arduino like function wrappers
void pinMode(uint32_t pin, uint32_t mode)
{
switch (mode)
{
void pinMode(uint32_t pin, uint32_t mode) {
switch (mode) {
case INPUT:
nrf_gpio_cfg_input(pin, NRF_GPIO_PIN_NOPULL);
break;
@@ -59,8 +56,7 @@ void pinMode(uint32_t pin, uint32_t mode)
// GPIO
static uint16_t m_driver_refs = 0;
void EPD_GPIO_Load(epd_config_t *cfg)
{
void EPD_GPIO_Load(epd_config_t* cfg) {
if (cfg == NULL) return;
EPD_MOSI_PIN = cfg->mosi_pin;
EPD_SCLK_PIN = cfg->sclk_pin;
@@ -73,8 +69,7 @@ void EPD_GPIO_Load(epd_config_t *cfg)
EPD_LED_PIN = cfg->led_pin;
}
void EPD_GPIO_Init(void)
{
void EPD_GPIO_Init(void) {
if (m_driver_refs++ > 0) return;
pinMode(EPD_DC_PIN, OUTPUT);
@@ -103,14 +98,12 @@ void EPD_GPIO_Init(void)
digitalWrite(EPD_DC_PIN, LOW);
digitalWrite(EPD_RST_PIN, HIGH);
if (EPD_LED_PIN != 0xFF)
pinMode(EPD_LED_PIN, OUTPUT);
if (EPD_LED_PIN != 0xFF) pinMode(EPD_LED_PIN, OUTPUT);
EPD_LED_ON();
}
void EPD_GPIO_Uninit(void)
{
void EPD_GPIO_Uninit(void) {
if (--m_driver_refs > 0) return;
EPD_LED_OFF();
@@ -120,8 +113,7 @@ void EPD_GPIO_Uninit(void)
digitalWrite(EPD_DC_PIN, LOW);
digitalWrite(EPD_CS_PIN, LOW);
digitalWrite(EPD_RST_PIN, LOW);
if (EPD_EN_PIN != 0xFF)
digitalWrite(EPD_EN_PIN, LOW);
if (EPD_EN_PIN != 0xFF) digitalWrite(EPD_EN_PIN, LOW);
// reset pin state
pinMode(EPD_MOSI_PIN, DEFAULT);
@@ -136,8 +128,7 @@ void EPD_GPIO_Uninit(void)
}
// SPI
void EPD_SPI_Write(uint8_t *value, uint8_t len)
{
void EPD_SPI_Write(uint8_t* value, uint8_t len) {
nrf_gpio_pin_dir_t dir = nrf_gpio_pin_dir_get(EPD_MOSI_PIN);
if (dir != NRF_GPIO_PIN_DIR_OUTPUT) {
pinMode(EPD_MOSI_PIN, OUTPUT);
@@ -146,8 +137,7 @@ void EPD_SPI_Write(uint8_t *value, uint8_t len)
APP_ERROR_CHECK(nrf_drv_spi_transfer(&spi, value, len, NULL, 0));
}
void EPD_SPI_Read(uint8_t *value, uint8_t len)
{
void EPD_SPI_Read(uint8_t* value, uint8_t len) {
nrf_gpio_pin_dir_t dir = nrf_gpio_pin_dir_get(EPD_MOSI_PIN);
if (dir != NRF_GPIO_PIN_DIR_INPUT) {
pinMode(EPD_MOSI_PIN, INPUT);
@@ -157,43 +147,36 @@ void EPD_SPI_Read(uint8_t *value, uint8_t len)
}
// EPD
void EPD_WriteCmd(uint8_t cmd)
{
void EPD_WriteCmd(uint8_t cmd) {
digitalWrite(EPD_DC_PIN, LOW);
EPD_SPI_Write(&cmd, 1);
}
void EPD_WriteData(uint8_t *value, uint8_t len)
{
void EPD_WriteData(uint8_t* value, uint8_t len) {
digitalWrite(EPD_DC_PIN, HIGH);
EPD_SPI_Write(value, len);
}
void EPD_ReadData(uint8_t *value, uint8_t len)
{
void EPD_ReadData(uint8_t* value, uint8_t len) {
digitalWrite(EPD_DC_PIN, HIGH);
EPD_SPI_Read(value, len);
}
void EPD_WriteByte(uint8_t value)
{
void EPD_WriteByte(uint8_t value) {
digitalWrite(EPD_DC_PIN, HIGH);
EPD_SPI_Write(&value, 1);
}
uint8_t EPD_ReadByte(void)
{
uint8_t EPD_ReadByte(void) {
uint8_t value;
digitalWrite(EPD_DC_PIN, HIGH);
EPD_SPI_Read(&value, 1);
return value;
}
void EPD_FillRAM(uint8_t cmd, uint8_t value, uint32_t len)
{
void EPD_FillRAM(uint8_t cmd, uint8_t value, uint32_t len) {
uint8_t buffer[BUFFER_SIZE];
for (uint8_t i = 0; i < BUFFER_SIZE; i++)
buffer[i] = value;
for (uint8_t i = 0; i < BUFFER_SIZE; i++) buffer[i] = value;
EPD_WriteCmd(cmd);
uint16_t remaining = len;
@@ -204,8 +187,7 @@ void EPD_FillRAM(uint8_t cmd, uint8_t value, uint32_t len)
}
}
void EPD_Reset(uint32_t value, uint16_t duration)
{
void EPD_Reset(uint32_t value, uint16_t duration) {
digitalWrite(EPD_RST_PIN, value);
delay(duration);
digitalWrite(EPD_RST_PIN, (value == LOW) ? HIGH : LOW);
@@ -214,8 +196,7 @@ void EPD_Reset(uint32_t value, uint16_t duration)
delay(duration);
}
void EPD_WaitBusy(uint32_t value, uint16_t timeout)
{
void EPD_WaitBusy(uint32_t value, uint16_t timeout) {
uint32_t led_status = digitalRead(EPD_LED_PIN);
NRF_LOG_DEBUG("[EPD]: check busy\n");
@@ -238,26 +219,19 @@ void EPD_WaitBusy(uint32_t value, uint16_t timeout)
}
// lED
void EPD_LED_ON(void)
{
if (EPD_LED_PIN != 0xFF)
digitalWrite(EPD_LED_PIN, LOW);
void EPD_LED_ON(void) {
if (EPD_LED_PIN != 0xFF) digitalWrite(EPD_LED_PIN, LOW);
}
void EPD_LED_OFF(void)
{
if (EPD_LED_PIN != 0xFF)
digitalWrite(EPD_LED_PIN, HIGH);
void EPD_LED_OFF(void) {
if (EPD_LED_PIN != 0xFF) digitalWrite(EPD_LED_PIN, HIGH);
}
void EPD_LED_Toggle(void)
{
if (EPD_LED_PIN != 0xFF)
nrf_gpio_pin_toggle(EPD_LED_PIN);
void EPD_LED_Toggle(void) {
if (EPD_LED_PIN != 0xFF) nrf_gpio_pin_toggle(EPD_LED_PIN);
}
void EPD_LED_BLINK(void)
{
void EPD_LED_BLINK(void) {
if (EPD_LED_PIN != 0xFF) {
pinMode(EPD_LED_PIN, OUTPUT);
digitalWrite(EPD_LED_PIN, LOW);
@@ -268,18 +242,18 @@ void EPD_LED_BLINK(void)
}
}
float EPD_ReadVoltage(void)
{
float EPD_ReadVoltage(void) {
#if defined(S112)
volatile int16_t value = 0;
NRF_SAADC->RESOLUTION = SAADC_RESOLUTION_VAL_10bit;
NRF_SAADC->ENABLE = (SAADC_ENABLE_ENABLE_Enabled << SAADC_ENABLE_ENABLE_Pos);
NRF_SAADC->CH[0].CONFIG = ((SAADC_CH_CONFIG_RESP_Bypass << SAADC_CH_CONFIG_RESP_Pos) & SAADC_CH_CONFIG_RESP_Msk)
| ((SAADC_CH_CONFIG_RESP_Bypass << SAADC_CH_CONFIG_RESN_Pos) & SAADC_CH_CONFIG_RESN_Msk)
| ((SAADC_CH_CONFIG_GAIN_Gain1_6 << SAADC_CH_CONFIG_GAIN_Pos) & SAADC_CH_CONFIG_GAIN_Msk)
| ((SAADC_CH_CONFIG_REFSEL_Internal << SAADC_CH_CONFIG_REFSEL_Pos) & SAADC_CH_CONFIG_REFSEL_Msk)
| ((SAADC_CH_CONFIG_TACQ_3us << SAADC_CH_CONFIG_TACQ_Pos) & SAADC_CH_CONFIG_TACQ_Msk)
| ((SAADC_CH_CONFIG_MODE_SE << SAADC_CH_CONFIG_MODE_Pos) & SAADC_CH_CONFIG_MODE_Msk);
NRF_SAADC->CH[0].CONFIG =
((SAADC_CH_CONFIG_RESP_Bypass << SAADC_CH_CONFIG_RESP_Pos) & SAADC_CH_CONFIG_RESP_Msk) |
((SAADC_CH_CONFIG_RESP_Bypass << SAADC_CH_CONFIG_RESN_Pos) & SAADC_CH_CONFIG_RESN_Msk) |
((SAADC_CH_CONFIG_GAIN_Gain1_6 << SAADC_CH_CONFIG_GAIN_Pos) & SAADC_CH_CONFIG_GAIN_Msk) |
((SAADC_CH_CONFIG_REFSEL_Internal << SAADC_CH_CONFIG_REFSEL_Pos) & SAADC_CH_CONFIG_REFSEL_Msk) |
((SAADC_CH_CONFIG_TACQ_3us << SAADC_CH_CONFIG_TACQ_Pos) & SAADC_CH_CONFIG_TACQ_Msk) |
((SAADC_CH_CONFIG_MODE_SE << SAADC_CH_CONFIG_MODE_Pos) & SAADC_CH_CONFIG_MODE_Msk);
NRF_SAADC->CH[0].PSELN = SAADC_CH_PSELN_PSELN_NC;
NRF_SAADC->CH[0].PSELP = SAADC_CH_PSELP_PSELP_VDD;
NRF_SAADC->RESULT.PTR = (uint32_t)&value;
@@ -328,22 +302,12 @@ extern epd_model_t epd_jd79668_420_bwry;
extern epd_model_t epd_jd79668_750_bwry;
static epd_model_t* epd_models[] = {
&epd_uc8176_420_bw,
&epd_uc8176_420_bwr,
&epd_uc8159_750_bw,
&epd_uc8159_750_bwr,
&epd_uc8179_750_bw,
&epd_uc8179_750_bwr,
&epd_ssd1619_420_bwr,
&epd_ssd1619_420_bw,
&epd_ssd1677_750_bwr,
&epd_ssd1677_750_bw,
&epd_jd79668_420_bwry,
&epd_jd79668_750_bwry,
&epd_uc8176_420_bw, &epd_uc8176_420_bwr, &epd_uc8159_750_bw, &epd_uc8159_750_bwr,
&epd_uc8179_750_bw, &epd_uc8179_750_bwr, &epd_ssd1619_420_bwr, &epd_ssd1619_420_bw,
&epd_ssd1677_750_bwr, &epd_ssd1677_750_bw, &epd_jd79668_420_bwry, &epd_jd79668_750_bwry,
};
epd_model_t *epd_init(epd_model_id_t id)
{
epd_model_t* epd_init(epd_model_id_t id) {
epd_model_t* epd = NULL;
for (uint8_t i = 0; i < ARRAY_SIZE(epd_models); i++) {
if (epd_models[i]->id == id) {

View File

@@ -4,13 +4,13 @@
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#include "EPD_config.h"
#include "nrf_delay.h"
#include "nrf_gpio.h"
#include "EPD_config.h"
// EPD driver IC types
typedef enum
{
typedef enum {
EPD_DRIVER_IC_UC8159 = 0x10,
EPD_DRIVER_IC_UC8176 = 0x11,
EPD_DRIVER_IC_UC8179 = 0x12,
@@ -120,16 +120,14 @@ enum {
SSD16xx_NOP = 0x7F, // NOP
};
typedef enum
{
typedef enum {
BW = 1,
BWR = 2,
BWRY = 3,
} epd_color_t;
// Do not change the existing IDs!
typedef enum
{
typedef enum {
EPD_UC8176_420_BW = 1,
EPD_UC8176_420_BWR = 3,
EPD_SSD1619_420_BWR = 2,
@@ -146,8 +144,7 @@ typedef enum
struct epd_driver;
typedef struct
{
typedef struct {
epd_model_id_t id;
epd_color_t color;
struct epd_driver* drv;
@@ -159,12 +156,12 @@ typedef struct
*
* @details This structure contains epd driver functions.
*/
typedef struct epd_driver
{
typedef struct epd_driver {
epd_driver_ic_t ic; /**< EPD driver IC type */
void (*init)(epd_model_t* epd); /**< Initialize the e-Paper register */
void (*clear)(epd_model_t* epd, bool refresh); /**< Clear screen */
void (*write_image)(epd_model_t *epd, uint8_t *black, uint8_t *color, uint16_t x, uint16_t y, uint16_t w, uint16_t h); /**< write image */
void (*write_image)(epd_model_t* epd, uint8_t* black, uint8_t* color, uint16_t x, uint16_t y, uint16_t w,
uint16_t h); /**< write image */
void (*write_ram)(epd_model_t* epd, uint8_t cfg, uint8_t* data, uint8_t len); /* write data to epd ram */
void (*refresh)(epd_model_t* epd); /**< Sends the image buffer in RAM to e-Paper and displays */
void (*sleep)(epd_model_t* epd); /**< Enter sleep mode */

View File

@@ -10,16 +10,18 @@
*
*/
#include "EPD_service.h"
#include <string.h>
#include "sdk_macros.h"
#include "app_scheduler.h"
#include "ble_srv_common.h"
#include "main.h"
#include "nrf_delay.h"
#include "nrf_gpio.h"
#include "nrf_pwr_mgmt.h"
#include "app_scheduler.h"
#include "EPD_service.h"
#include "main.h"
#include "nrf_log.h"
#include "nrf_pwr_mgmt.h"
#include "sdk_macros.h"
#if defined(S112)
#define EPD_CFG_52811 {0x14, 0x13, 0x06, 0x05, 0x04, 0x03, 0x02, 0x02, 0xFF, 0x12, 0x07}
@@ -29,8 +31,7 @@
// #define EPD_CFG_DEFAULT {0x05, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x01, 0x07}
#endif
static void epd_gui_update(void * p_event_data, uint16_t event_size)
{
static void epd_gui_update(void* p_event_data, uint16_t event_size) {
epd_gui_update_event_t* event = (epd_gui_update_event_t*)p_event_data;
ble_epd_t* p_epd = event->p_epd;
@@ -49,8 +50,7 @@ static void epd_gui_update(void * p_event_data, uint16_t event_size)
uint16_t dev_name_len = sizeof(data.ssid);
uint32_t err_code = sd_ble_gap_device_name_get((uint8_t*)data.ssid, &dev_name_len);
if (err_code == NRF_SUCCESS && dev_name_len > 0)
data.ssid[dev_name_len] = '\0';
if (err_code == NRF_SUCCESS && dev_name_len > 0) data.ssid[dev_name_len] = '\0';
DrawGUI(&data, (buffer_callback)epd->drv->write_image, epd);
epd->drv->refresh(epd);
@@ -64,8 +64,7 @@ static void epd_gui_update(void * p_event_data, uint16_t event_size)
* @param[in] p_epd EPD Service structure.
* @param[in] p_ble_evt Pointer to the event received from BLE stack.
*/
static void on_connect(ble_epd_t * p_epd, ble_evt_t * p_ble_evt)
{
static void on_connect(ble_epd_t* p_epd, ble_evt_t* p_ble_evt) {
p_epd->conn_handle = p_ble_evt->evt.gap_evt.conn_handle;
EPD_GPIO_Init();
}
@@ -75,8 +74,7 @@ static void on_connect(ble_epd_t * p_epd, ble_evt_t * p_ble_evt)
* @param[in] p_epd EPD Service structure.
* @param[in] p_ble_evt Pointer to the event received from BLE stack.
*/
static void on_disconnect(ble_epd_t * p_epd, ble_evt_t * p_ble_evt)
{
static void on_disconnect(ble_epd_t* p_epd, ble_evt_t* p_ble_evt) {
UNUSED_PARAMETER(p_ble_evt);
p_epd->conn_handle = BLE_CONN_HANDLE_INVALID;
p_epd->epd->drv->sleep(p_epd->epd);
@@ -84,36 +82,31 @@ static void on_disconnect(ble_epd_t * p_epd, ble_evt_t * p_ble_evt)
EPD_GPIO_Uninit();
}
static void epd_update_display_mode(ble_epd_t * p_epd, display_mode_t mode)
{
static void epd_update_display_mode(ble_epd_t* p_epd, display_mode_t mode) {
if (p_epd->config.display_mode != mode) {
p_epd->config.display_mode = mode;
epd_config_write(&p_epd->config);
}
}
static void epd_send_time(ble_epd_t * p_epd)
{
static void epd_send_time(ble_epd_t* p_epd) {
char buf[20] = {0};
snprintf(buf, 20, "t=%" PRIu32, timestamp());
ble_epd_string_send(p_epd, (uint8_t*)buf, strlen(buf));
}
static void epd_send_mtu(ble_epd_t * p_epd)
{
static void epd_send_mtu(ble_epd_t* p_epd) {
char buf[10] = {0};
snprintf(buf, sizeof(buf), "mtu=%d", p_epd->max_data_len);
ble_epd_string_send(p_epd, (uint8_t*)buf, strlen(buf));
}
static void epd_service_on_write(ble_epd_t * p_epd, uint8_t * p_data, uint16_t length)
{
static void epd_service_on_write(ble_epd_t* p_epd, uint8_t* p_data, uint16_t length) {
NRF_LOG_DEBUG("[EPD]: on_write LEN=%d\n", length);
NRF_LOG_HEXDUMP_DEBUG(p_data, length);
if (p_data == NULL || length <= 0) return;
switch (p_data[0])
{
switch (p_data[0]) {
case EPD_CMD_SET_PINS:
if (length < 8) return;
@@ -124,8 +117,7 @@ static void epd_service_on_write(ble_epd_t * p_epd, uint8_t * p_data, uint16_t l
p_epd->config.rst_pin = p_data[5];
p_epd->config.busy_pin = p_data[6];
p_epd->config.bs_pin = p_data[7];
if (length > 8)
p_epd->config.en_pin = p_data[8];
if (length > 8) p_epd->config.en_pin = p_data[8];
epd_config_write(&p_epd->config);
EPD_GPIO_Uninit();
@@ -226,44 +218,29 @@ static void epd_service_on_write(ble_epd_t * p_epd, uint8_t * p_data, uint16_t l
* @param[in] p_epd EPD Service structure.
* @param[in] p_ble_evt Pointer to the event received from BLE stack.
*/
static void on_write(ble_epd_t * p_epd, ble_evt_t * p_ble_evt)
{
static void on_write(ble_epd_t* p_epd, ble_evt_t* p_ble_evt) {
ble_gatts_evt_write_t* p_evt_write = &p_ble_evt->evt.gatts_evt.params.write;
if (
(p_evt_write->handle == p_epd->char_handles.cccd_handle)
&&
(p_evt_write->len == 2)
)
{
if (ble_srv_is_notification_enabled(p_evt_write->data))
{
if ((p_evt_write->handle == p_epd->char_handles.cccd_handle) && (p_evt_write->len == 2)) {
if (ble_srv_is_notification_enabled(p_evt_write->data)) {
NRF_LOG_DEBUG("notification enabled\n");
p_epd->is_notification_enabled = true;
static uint16_t length = sizeof(epd_config_t);
NRF_LOG_DEBUG("send epd config\n");
uint32_t err_code = ble_epd_string_send(p_epd, (uint8_t*)&p_epd->config, length);
if (err_code != NRF_ERROR_INVALID_STATE)
APP_ERROR_CHECK(err_code);
}
else
{
if (err_code != NRF_ERROR_INVALID_STATE) APP_ERROR_CHECK(err_code);
} else {
p_epd->is_notification_enabled = false;
}
}
else if (p_evt_write->handle == p_epd->char_handles.value_handle)
{
} else if (p_evt_write->handle == p_epd->char_handles.value_handle) {
epd_service_on_write(p_epd, p_evt_write->data, p_evt_write->len);
}
else
{
} else {
// Do Nothing. This event is not relevant for this service.
}
}
#if defined(S112)
void ble_epd_evt_handler(ble_evt_t const * p_ble_evt, void * p_context)
{
void ble_epd_evt_handler(ble_evt_t const* p_ble_evt, void* p_context) {
if (p_context == NULL || p_ble_evt == NULL) return;
ble_epd_t* p_epd = (ble_epd_t*)p_context;
@@ -271,15 +248,12 @@ void ble_epd_evt_handler(ble_evt_t const * p_ble_evt, void * p_context)
}
#endif
void ble_epd_on_ble_evt(ble_epd_t * p_epd, ble_evt_t * p_ble_evt)
{
if ((p_epd == NULL) || (p_ble_evt == NULL))
{
void ble_epd_on_ble_evt(ble_epd_t* p_epd, ble_evt_t* p_ble_evt) {
if ((p_epd == NULL) || (p_ble_evt == NULL)) {
return;
}
switch (p_ble_evt->header.evt_id)
{
switch (p_ble_evt->header.evt_id) {
case BLE_GAP_EVT_CONNECTED:
on_connect(p_epd, p_ble_evt);
break;
@@ -298,9 +272,7 @@ void ble_epd_on_ble_evt(ble_epd_t * p_epd, ble_evt_t * p_ble_evt)
}
}
static uint32_t epd_service_init(ble_epd_t * p_epd)
{
static uint32_t epd_service_init(ble_epd_t* p_epd) {
ble_uuid_t ble_uuid = {0};
ble_uuid128_t base_uuid = BLE_UUID_EPD_SVC_BASE;
ble_add_char_params_t add_char_params;
@@ -310,9 +282,7 @@ static uint32_t epd_service_init(ble_epd_t * p_epd)
ble_uuid.type = ble_uuid.type;
ble_uuid.uuid = BLE_UUID_EPD_SVC;
VERIFY_SUCCESS(sd_ble_gatts_service_add(BLE_GATTS_SRVC_TYPE_PRIMARY,
&ble_uuid,
&p_epd->service_handle));
VERIFY_SUCCESS(sd_ble_gatts_service_add(BLE_GATTS_SRVC_TYPE_PRIMARY, &ble_uuid, &p_epd->service_handle));
memset(&add_char_params, 0, sizeof(add_char_params));
add_char_params.uuid = BLE_UUID_EPD_CHAR;
@@ -341,19 +311,16 @@ static uint32_t epd_service_init(ble_epd_t * p_epd)
return characteristic_add(p_epd->service_handle, &add_char_params, &p_epd->app_ver_handles);
}
void ble_epd_sleep_prepare(ble_epd_t * p_epd)
{
void ble_epd_sleep_prepare(ble_epd_t* p_epd) {
// Turn off led
EPD_LED_OFF();
// Prepare wakeup pin
if (p_epd->config.wakeup_pin != 0xFF)
{
if (p_epd->config.wakeup_pin != 0xFF) {
nrf_gpio_cfg_sense_input(p_epd->config.wakeup_pin, NRF_GPIO_PIN_NOPULL, NRF_GPIO_PIN_SENSE_HIGH);
}
}
uint32_t ble_epd_init(ble_epd_t * p_epd)
{
uint32_t ble_epd_init(ble_epd_t* p_epd) {
if (p_epd == NULL) return NRF_ERROR_NULL;
// Initialize the service structure.
@@ -365,8 +332,7 @@ uint32_t ble_epd_init(ble_epd_t * p_epd)
epd_config_read(&p_epd->config);
// write default config
if (epd_config_empty(&p_epd->config))
{
if (epd_config_empty(&p_epd->config)) {
#if defined(S112)
if (NRF_FICR->INFO.PART == 0x52810) {
uint8_t cfg[] = EPD_CFG_52810;
@@ -379,10 +345,8 @@ uint32_t ble_epd_init(ble_epd_t * p_epd)
uint8_t cfg[] = EPD_CFG_DEFAULT;
memcpy(&p_epd->config, cfg, sizeof(cfg));
#endif
if (p_epd->config.display_mode == 0xFF)
p_epd->config.display_mode = MODE_CALENDAR;
if (p_epd->config.week_start == 0xFF)
p_epd->config.week_start = 0;
if (p_epd->config.display_mode == 0xFF) p_epd->config.display_mode = MODE_CALENDAR;
if (p_epd->config.week_start == 0xFF) p_epd->config.week_start = 0;
epd_config_write(&p_epd->config);
}
@@ -396,12 +360,10 @@ uint32_t ble_epd_init(ble_epd_t * p_epd)
return epd_service_init(p_epd);
}
uint32_t ble_epd_string_send(ble_epd_t * p_epd, uint8_t * p_string, uint16_t length)
{
uint32_t ble_epd_string_send(ble_epd_t* p_epd, uint8_t* p_string, uint16_t length) {
if ((p_epd->conn_handle == BLE_CONN_HANDLE_INVALID) || (!p_epd->is_notification_enabled))
return NRF_ERROR_INVALID_STATE;
if (length > p_epd->max_data_len)
return NRF_ERROR_INVALID_PARAM;
if (length > p_epd->max_data_len) return NRF_ERROR_INVALID_PARAM;
ble_gatts_hvx_params_t hvx_params;
@@ -415,11 +377,9 @@ uint32_t ble_epd_string_send(ble_epd_t * p_epd, uint8_t * p_string, uint16_t len
return sd_ble_gatts_hvx(p_epd->conn_handle, &hvx_params);
}
void ble_epd_on_timer(ble_epd_t * p_epd, uint32_t timestamp, bool force_update)
{
void ble_epd_on_timer(ble_epd_t* p_epd, uint32_t timestamp, bool force_update) {
// Update calendar on 00:00:00, clock on every minute
if (force_update ||
(p_epd->config.display_mode == MODE_CALENDAR && timestamp % 86400 == 0) ||
if (force_update || (p_epd->config.display_mode == MODE_CALENDAR && timestamp % 86400 == 0) ||
(p_epd->config.display_mode == MODE_CLOCK && timestamp % 60 == 0)) {
epd_gui_update_event_t event = {p_epd, timestamp};
app_sched_event_put(&event, sizeof(epd_gui_update_event_t), epd_gui_update);

View File

@@ -15,15 +15,16 @@
#include <inttypes.h>
#include <stdbool.h>
#include "ble.h"
#include "ble_srv_common.h"
#if defined(S112)
#include "nrf_sdh_ble.h"
#endif
#include "sdk_config.h"
#include "EPD_driver.h"
#include "EPD_config.h"
#include "EPD_driver.h"
#include "GUI.h"
#include "sdk_config.h"
/**@brief Macro for defining a ble_hts instance.
*
@@ -36,17 +37,15 @@ void ble_epd_evt_handler(ble_evt_t const * p_ble_evt, void * p_context);
#define BLE_EPD_BLE_OBSERVER_PRIO 2
#define BLE_EPD_DEF(_name) \
static ble_epd_t _name; \
NRF_SDH_BLE_OBSERVER(_name ## _obs, \
BLE_EPD_BLE_OBSERVER_PRIO, \
ble_epd_evt_handler, &_name)
NRF_SDH_BLE_OBSERVER(_name##_obs, BLE_EPD_BLE_OBSERVER_PRIO, ble_epd_evt_handler, &_name)
#else
#define BLE_EPD_DEF(_name) static ble_epd_t _name;
#endif
#define APP_VERSION 0x19
#define BLE_UUID_EPD_SVC_BASE {{0XEC, 0X5A, 0X67, 0X1C, 0XC1, 0XB6, 0X46, 0XFB, \
0X8D, 0X91, 0X28, 0XD8, 0X22, 0X36, 0X75, 0X62}}
#define BLE_UUID_EPD_SVC_BASE \
{{0XEC, 0X5A, 0X67, 0X1C, 0XC1, 0XB6, 0X46, 0XFB, 0X8D, 0X91, 0X28, 0XD8, 0X22, 0X36, 0X75, 0X62}}
#define BLE_UUID_EPD_SVC 0x0001
#define BLE_UUID_EPD_CHAR 0x0002
#define BLE_UUID_APP_VER 0x0003
@@ -56,12 +55,12 @@ void ble_epd_evt_handler(ble_evt_t const * p_ble_evt, void * p_context);
#if defined(S112)
#define BLE_EPD_MAX_DATA_LEN (NRF_SDH_BLE_GATT_MAX_MTU_SIZE - 3)
#else
#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_EPD_MAX_DATA_LEN \
(GATT_MTU_SIZE_DEFAULT - 3) /**< Maximum length of data (in bytes) that can be transmitted to the peer. */
#endif
/**< EPD Service command IDs. */
enum EPD_CMDS
{
enum EPD_CMDS {
EPD_CMD_SET_PINS = 0x00, /**< set EPD pin mapping. */
EPD_CMD_INIT = 0x01, /**< init EPD display driver */
EPD_CMD_CLEAR = 0x02, /**< clear EPD screen */
@@ -85,20 +84,22 @@ enum EPD_CMDS
*
* @details This structure contains status information related to the service.
*/
typedef struct
{
typedef struct {
uint16_t service_handle; /**< Handle of EPD Service (as provided by the S110 SoftDevice). */
ble_gatts_char_handles_t char_handles; /**< Handles related to the EPD characteristic (as provided by the SoftDevice). */
ble_gatts_char_handles_t app_ver_handles; /**< Handles related to the APP version characteristic (as provided by the SoftDevice). */
uint16_t conn_handle; /**< Handle of the current connection (as provided by the SoftDevice). BLE_CONN_HANDLE_INVALID if not in a connection. */
ble_gatts_char_handles_t
char_handles; /**< Handles related to the EPD characteristic (as provided by the SoftDevice). */
ble_gatts_char_handles_t
app_ver_handles; /**< Handles related to the APP version characteristic (as provided by the SoftDevice). */
uint16_t conn_handle; /**< Handle of the current connection (as provided by the SoftDevice). BLE_CONN_HANDLE_INVALID
if not in a connection. */
uint16_t max_data_len; /**< Maximum length of data (in bytes) that can be transmitted to the peer */
bool is_notification_enabled; /**< Variable to indicate if the peer has enabled notification of the RX characteristic.*/
bool is_notification_enabled; /**< Variable to indicate if the peer has enabled notification of the RX
characteristic.*/
epd_model_t* epd; /**< current EPD model */
epd_config_t config; /**< EPD config */
} ble_epd_t;
typedef struct
{
typedef struct {
ble_epd_t* p_epd;
uint32_t timestamp;
} epd_gui_update_event_t;

View File

@@ -1,51 +1,35 @@
#include "EPD_driver.h"
#include "nrf_log.h"
static void SSD16xx_WaitBusy(uint16_t timeout)
{
EPD_WaitBusy(HIGH, timeout);
}
static void SSD16xx_WaitBusy(uint16_t timeout) { EPD_WaitBusy(HIGH, timeout); }
static void SSD16xx_Update(uint8_t seq)
{
static void SSD16xx_Update(uint8_t seq) {
EPD_Write(SSD16xx_DISP_CTRL2, seq);
EPD_WriteCmd(SSD16xx_MASTER_ACTIVATE);
}
int8_t SSD16xx_Read_Temp(epd_model_t *epd)
{
int8_t SSD16xx_Read_Temp(epd_model_t* epd) {
SSD16xx_Update(0xB1);
SSD16xx_WaitBusy(500);
EPD_WriteCmd(SSD16xx_TSENSOR_READ);
return (int8_t)EPD_ReadByte();
}
static void _setPartialRamArea(epd_model_t *epd, uint16_t x, uint16_t y, uint16_t w, uint16_t h)
{
static void _setPartialRamArea(epd_model_t* epd, uint16_t x, uint16_t y, uint16_t w, uint16_t h) {
EPD_Write(SSD16xx_ENTRY_MODE, 0x03); // set ram entry mode: x increase, y increase
if (epd->drv->ic == EPD_DRIVER_IC_SSD1677) {
EPD_Write(SSD16xx_RAM_XPOS,
x % 256, x / 256,
(x + w - 1) % 256,
(x + w - 1) / 256);
EPD_Write(SSD16xx_RAM_XPOS, x % 256, x / 256, (x + w - 1) % 256, (x + w - 1) / 256);
EPD_Write(SSD16xx_RAM_XCOUNT, x % 256, x / 256);
} else {
EPD_Write(SSD16xx_RAM_XPOS, x / 8, (x + w - 1) / 8);
EPD_Write(SSD16xx_RAM_YPOS,
y % 256, y / 256,
(y + h - 1) % 256,
(y + h - 1) / 256);
EPD_Write(SSD16xx_RAM_YPOS, y % 256, y / 256, (y + h - 1) % 256, (y + h - 1) / 256);
EPD_Write(SSD16xx_RAM_XCOUNT, x / 8);
}
EPD_Write(SSD16xx_RAM_YPOS,
y % 256, y / 256,
(y + h - 1) % 256,
(y + h - 1) / 256);
EPD_Write(SSD16xx_RAM_YPOS, y % 256, y / 256, (y + h - 1) % 256, (y + h - 1) / 256);
EPD_Write(SSD16xx_RAM_YCOUNT, y % 256, y / 256);
}
void SSD16xx_Dump_LUT(void)
{
void SSD16xx_Dump_LUT(void) {
uint8_t lut[128];
EPD_WriteCmd(SSD16xx_READ_LUT);
@@ -56,8 +40,7 @@ void SSD16xx_Dump_LUT(void)
NRF_LOG_DEBUG("=== LUT END ===\n");
}
void SSD16xx_Init(epd_model_t *epd)
{
void SSD16xx_Init(epd_model_t* epd) {
EPD_Reset(HIGH, 10);
EPD_WriteCmd(SSD16xx_SW_RESET);
@@ -69,8 +52,7 @@ void SSD16xx_Init(epd_model_t *epd)
_setPartialRamArea(epd, 0, 0, epd->width, epd->height);
}
static void SSD16xx_Refresh(epd_model_t *epd)
{
static void SSD16xx_Refresh(epd_model_t* epd) {
EPD_Write(SSD16xx_DISP_CTRL1, epd->color == BWR ? 0x80 : 0x40, 0x00);
NRF_LOG_DEBUG("[EPD]: refresh begin\n");
@@ -85,8 +67,7 @@ static void SSD16xx_Refresh(epd_model_t *epd)
SSD16xx_Update(0x83); // power off
}
void SSD16xx_Clear(epd_model_t *epd, bool refresh)
{
void SSD16xx_Clear(epd_model_t* epd, bool refresh) {
uint32_t ram_bytes = ((epd->width + 7) / 8) * epd->height;
_setPartialRamArea(epd, 0, 0, epd->width, epd->height);
@@ -94,30 +75,24 @@ void SSD16xx_Clear(epd_model_t *epd, bool refresh)
EPD_FillRAM(SSD16xx_WRITE_RAM1, 0xFF, ram_bytes);
EPD_FillRAM(SSD16xx_WRITE_RAM2, 0xFF, ram_bytes);
if (refresh)
SSD16xx_Refresh(epd);
if (refresh) SSD16xx_Refresh(epd);
}
void SSD16xx_Write_Image(epd_model_t *epd, uint8_t *black, uint8_t *color, uint16_t x, uint16_t y, uint16_t w, uint16_t h)
{
void SSD16xx_Write_Image(epd_model_t* epd, uint8_t* black, uint8_t* color, uint16_t x, uint16_t y, uint16_t w,
uint16_t h) {
uint16_t wb = (w + 7) / 8; // width bytes, bitmaps are padded
x -= x % 8; // byte boundary
w = wb * 8; // byte boundary
if (x + w > epd->width || y + h > epd->height)
return;
if (x + w > epd->width || y + h > epd->height) return;
_setPartialRamArea(epd, x, y, w, h);
EPD_WriteCmd(SSD16xx_WRITE_RAM1);
for (uint16_t i = 0; i < h; i++)
{
for (uint16_t j = 0; j < w / 8; j++)
EPD_WriteByte(black ? black[j + i * wb] : 0xFF);
for (uint16_t i = 0; i < h; i++) {
for (uint16_t j = 0; j < w / 8; j++) EPD_WriteByte(black ? black[j + i * wb] : 0xFF);
}
EPD_WriteCmd(SSD16xx_WRITE_RAM2);
for (uint16_t i = 0; i < h; i++)
{
for (uint16_t j = 0; j < w / 8; j++)
{
for (uint16_t i = 0; i < h; i++) {
for (uint16_t j = 0; j < w / 8; j++) {
if (epd->color == BWR)
EPD_WriteByte(color ? color[j + i * wb] : 0xFF);
else
@@ -126,8 +101,7 @@ void SSD16xx_Write_Image(epd_model_t *epd, uint8_t *black, uint8_t *color, uint1
}
}
void SSD16xx_Write_Ram(epd_model_t *epd, uint8_t cfg, uint8_t *data, uint8_t len)
{
void SSD16xx_Write_Ram(epd_model_t* epd, uint8_t cfg, uint8_t* data, uint8_t len) {
bool begin = (cfg >> 4) == 0x00;
bool black = (cfg & 0x0F) == 0x0F;
if (begin) {
@@ -139,8 +113,7 @@ void SSD16xx_Write_Ram(epd_model_t *epd, uint8_t cfg, uint8_t *data, uint8_t len
EPD_WriteData(data, len);
}
void SSD16xx_Sleep(epd_model_t *epd)
{
void SSD16xx_Sleep(epd_model_t* epd) {
EPD_Write(SSD16xx_SLEEP_MODE, 0x01);
delay(100);
}

View File

@@ -1,55 +1,40 @@
#include "EPD_driver.h"
#include "nrf_log.h"
static void UC81xx_WaitBusy(uint16_t timeout)
{
EPD_WaitBusy(LOW, timeout);
}
static void UC81xx_WaitBusy(uint16_t timeout) { EPD_WaitBusy(LOW, timeout); }
static void UC81xx_PowerOn(void)
{
static void UC81xx_PowerOn(void) {
EPD_WriteCmd(UC81xx_PON);
UC81xx_WaitBusy(200);
}
static void UC81xx_PowerOff(void)
{
static void UC81xx_PowerOff(void) {
EPD_WriteCmd(UC81xx_POF);
UC81xx_WaitBusy(200);
}
// Read temperature from driver chip
int8_t UC81xx_Read_Temp(epd_model_t *epd)
{
int8_t UC81xx_Read_Temp(epd_model_t* epd) {
EPD_WriteCmd(UC81xx_TSC);
UC81xx_WaitBusy(100);
return (int8_t)EPD_ReadByte();
}
static void _setPartialRamArea(epd_model_t *epd, uint16_t x, uint16_t y, uint16_t w, uint16_t h)
{
static void _setPartialRamArea(epd_model_t* epd, uint16_t x, uint16_t y, uint16_t w, uint16_t h) {
if (epd->drv->ic == EPD_DRIVER_IC_JD79668 || epd->drv->ic == EPD_DRIVER_IC_JD79665) {
EPD_Write(0x83, // partial window
x / 256, x % 256,
(x + w - 1) / 256, (x + w - 1) % 256,
y / 256, y % 256,
(y + h - 1) / 256, (y + h - 1) % 256,
0x01);
x / 256, x % 256, (x + w - 1) / 256, (x + w - 1) % 256, y / 256, y % 256, (y + h - 1) / 256,
(y + h - 1) % 256, 0x01);
} else {
uint16_t xe = (x + w - 1) | 0x0007; // byte boundary inclusive (last byte)
uint16_t ye = y + h - 1;
x &= 0xFFF8; // byte boundary
EPD_Write(UC81xx_PTL, // partial window
x / 256, x % 256,
xe / 256, xe % 256,
y / 256, y % 256,
ye / 256, ye % 256,
0x00);
x / 256, x % 256, xe / 256, xe % 256, y / 256, y % 256, ye / 256, ye % 256, 0x00);
}
}
void UC81xx_Refresh(epd_model_t *epd)
{
void UC81xx_Refresh(epd_model_t* epd) {
NRF_LOG_DEBUG("[EPD]: refresh begin\n");
UC81xx_PowerOn();
@@ -63,8 +48,7 @@ void UC81xx_Refresh(epd_model_t *epd)
NRF_LOG_DEBUG("[EPD]: refresh end\n");
}
void JD79668_Refresh(epd_model_t *epd)
{
void JD79668_Refresh(epd_model_t* epd) {
NRF_LOG_DEBUG("[EPD]: refresh begin\n");
_setPartialRamArea(epd, 0, 0, epd->width, epd->height);
@@ -76,8 +60,7 @@ void JD79668_Refresh(epd_model_t *epd)
NRF_LOG_DEBUG("[EPD]: refresh end\n");
}
void UC81xx_Dump_OTP(void)
{
void UC81xx_Dump_OTP(void) {
uint8_t data[128];
UC81xx_PowerOn();
@@ -93,8 +76,7 @@ void UC81xx_Dump_OTP(void)
UC81xx_PowerOff();
}
void UC81xx_Init(epd_model_t *epd)
{
void UC81xx_Init(epd_model_t* epd) {
EPD_Reset(HIGH, 10);
// UC81xx_Dump_OTP();
@@ -103,8 +85,7 @@ void UC81xx_Init(epd_model_t *epd)
EPD_Write(UC81xx_CDI, epd->color == BWR ? 0x77 : 0x97);
}
void UC8159_Init(epd_model_t *epd)
{
void UC8159_Init(epd_model_t* epd) {
EPD_Reset(HIGH, 10);
EPD_Write(UC81xx_PWR, 0x37, 0x00);
@@ -116,15 +97,10 @@ void UC8159_Init(epd_model_t *epd)
EPD_Write(UC81xx_TCON, 0x22);
EPD_Write(0x65, 0x00); // FLASH CONTROL
EPD_Write(0xe5, 0x03); // FLASH MODE
EPD_Write(UC81xx_TRES,
epd->width >> 8,
epd->width & 0xff,
epd->height >> 8,
epd->height & 0xff);
EPD_Write(UC81xx_TRES, epd->width >> 8, epd->width & 0xff, epd->height >> 8, epd->height & 0xff);
}
void JD79668_Init(epd_model_t *epd)
{
void JD79668_Init(epd_model_t* epd) {
EPD_Reset(HIGH, 50);
EPD_Write(0x4D, 0x78);
@@ -132,9 +108,7 @@ void JD79668_Init(epd_model_t *epd)
EPD_Write(UC81xx_BTST, 0x0D, 0x12, 0x24, 0x25, 0x12, 0x29, 0x10);
EPD_Write(UC81xx_PLL, 0x08);
EPD_Write(UC81xx_CDI, 0x37);
EPD_Write(UC81xx_TRES,
epd->width / 256, epd->width % 256,
epd->height / 256, epd->height % 256);
EPD_Write(UC81xx_TRES, epd->width / 256, epd->width % 256, epd->height / 256, epd->height % 256);
EPD_Write(0xAE, 0xCF);
EPD_Write(0xB0, 0x13);
@@ -145,19 +119,16 @@ void JD79668_Init(epd_model_t *epd)
UC81xx_PowerOn();
}
void UC81xx_Clear(epd_model_t *epd, bool refresh)
{
void UC81xx_Clear(epd_model_t* epd, bool refresh) {
uint32_t ram_bytes = ((epd->width + 7) / 8) * epd->height;
EPD_FillRAM(UC81xx_DTM1, 0xFF, ram_bytes);
EPD_FillRAM(UC81xx_DTM2, 0xFF, ram_bytes);
if (refresh)
UC81xx_Refresh(epd);
if (refresh) UC81xx_Refresh(epd);
}
void UC8159_Clear(epd_model_t *epd, bool refresh)
{
void UC8159_Clear(epd_model_t* epd, bool refresh) {
uint32_t wb = (epd->width + 7) / 8;
EPD_WriteCmd(UC81xx_DTM1);
@@ -169,44 +140,35 @@ void UC8159_Clear(epd_model_t *epd, bool refresh)
}
}
if (refresh)
UC81xx_Refresh(epd);
if (refresh) UC81xx_Refresh(epd);
}
void JD79668_Clear(epd_model_t *epd, bool refresh)
{
void JD79668_Clear(epd_model_t* epd, bool refresh) {
uint32_t ram_bytes = ((epd->width + 3) / 4) * epd->height;
EPD_FillRAM(UC81xx_DTM1, 0x55, ram_bytes);
if (refresh)
UC81xx_Refresh(epd);
if (refresh) UC81xx_Refresh(epd);
}
void UC81xx_Write_Image(epd_model_t *epd, uint8_t *black, uint8_t *color, uint16_t x, uint16_t y, uint16_t w, uint16_t h)
{
void UC81xx_Write_Image(epd_model_t* epd, uint8_t* black, uint8_t* color, uint16_t x, uint16_t y, uint16_t w,
uint16_t h) {
uint16_t wb = (w + 7) / 8; // width bytes, bitmaps are padded
x -= x % 8; // byte boundary
w = wb * 8; // byte boundary
if (x + w > epd->width || y + h > epd->height)
return;
if (x + w > epd->width || y + h > epd->height) return;
EPD_WriteCmd(UC81xx_PTIN); // partial in
_setPartialRamArea(epd, x, y, w, h);
if (epd->color == BWR)
{
if (epd->color == BWR) {
EPD_WriteCmd(UC81xx_DTM1);
for (uint16_t i = 0; i < h; i++)
{
for (uint16_t j = 0; j < w / 8; j++)
EPD_WriteByte(black ? black[j + i * wb] : 0xFF);
for (uint16_t i = 0; i < h; i++) {
for (uint16_t j = 0; j < w / 8; j++) EPD_WriteByte(black ? black[j + i * wb] : 0xFF);
}
}
EPD_WriteCmd(UC81xx_DTM2);
for (uint16_t i = 0; i < h; i++)
{
for (uint16_t j = 0; j < w / 8; j++)
{
for (uint16_t i = 0; i < h; i++) {
for (uint16_t j = 0; j < w / 8; j++) {
if (epd->color == BWR)
EPD_WriteByte(color ? color[j + i * wb] : 0xFF);
else
@@ -219,37 +181,40 @@ void UC81xx_Write_Image(epd_model_t *epd, uint8_t *black, uint8_t *color, uint16
static void UC8159_Send_Pixel(uint8_t black_data, uint8_t color_data) {
uint8_t data;
for (uint8_t j = 0; j < 8; j++) {
if ((color_data & 0x80) == 0x00) data = 0x04; // red
else if ((black_data & 0x80) == 0x00) data = 0x00; // black
else data = 0x03; // white
if ((color_data & 0x80) == 0x00)
data = 0x04; // red
else if ((black_data & 0x80) == 0x00)
data = 0x00; // black
else
data = 0x03; // white
data = (data << 4) & 0xFF;
black_data = (black_data << 1) & 0xFF;
color_data = (color_data << 1) & 0xFF;
j++;
if ((color_data & 0x80) == 0x00) data |= 0x04; // red
else if ((black_data & 0x80) == 0x00) data |= 0x00; // black
else data |= 0x03; // white
if ((color_data & 0x80) == 0x00)
data |= 0x04; // red
else if ((black_data & 0x80) == 0x00)
data |= 0x00; // black
else
data |= 0x03; // white
black_data = (black_data << 1) & 0xFF;
color_data = (color_data << 1) & 0xFF;
EPD_WriteByte(data);
}
}
void UC8159_Write_Image(epd_model_t *epd, uint8_t *black, uint8_t *color, uint16_t x, uint16_t y, uint16_t w, uint16_t h)
{
void UC8159_Write_Image(epd_model_t* epd, uint8_t* black, uint8_t* color, uint16_t x, uint16_t y, uint16_t w,
uint16_t h) {
uint16_t wb = (w + 7) / 8; // width bytes, bitmaps are padded
x -= x % 8; // byte boundary
w = wb * 8; // byte boundary
if (x + w > epd->width || y + h > epd->height)
return;
if (x + w > epd->width || y + h > epd->height) return;
EPD_WriteCmd(UC81xx_PTIN); // partial in
_setPartialRamArea(epd, x, y, w, h);
EPD_WriteCmd(UC81xx_DTM1);
for (uint16_t i = 0; i < h; i++)
{
for (uint16_t j = 0; j < w / 8; j++)
{
for (uint16_t i = 0; i < h; i++) {
for (uint16_t j = 0; j < w / 8; j++) {
uint8_t black_data = 0xFF;
uint8_t color_data = 0xFF;
if (black) black_data = black[j + i * wb];
@@ -260,25 +225,22 @@ void UC8159_Write_Image(epd_model_t *epd, uint8_t *black, uint8_t *color, uint16
EPD_WriteCmd(UC81xx_PTOUT); // partial out
}
void JD79668_Write_Image(epd_model_t *epd, uint8_t *black, uint8_t *color, uint16_t x, uint16_t y, uint16_t w, uint16_t h)
{
void JD79668_Write_Image(epd_model_t* epd, uint8_t* black, uint8_t* color, uint16_t x, uint16_t y, uint16_t w,
uint16_t h) {
uint16_t wb = (w + 7) / 8; // width bytes, bitmaps are padded
x -= x % 8; // byte boundary
w = wb * 8; // byte boundary
if (x + w > epd->width || y + h > epd->height)
return;
if (x + w > epd->width || y + h > epd->height) return;
_setPartialRamArea(epd, x, y, w, h);
EPD_WriteCmd(UC81xx_DTM1);
for (uint16_t i = 0; i < h * 2; i++) // 2 bits per pixel
{
for (uint16_t j = 0; j < w / 8; j++)
EPD_WriteByte(black ? black[j + i * wb] : 0x55);
for (uint16_t j = 0; j < w / 8; j++) EPD_WriteByte(black ? black[j + i * wb] : 0x55);
}
}
void UC81xx_Write_Ram(epd_model_t *epd, uint8_t cfg, uint8_t *data, uint8_t len)
{
void UC81xx_Write_Ram(epd_model_t* epd, uint8_t cfg, uint8_t* data, uint8_t len) {
bool begin = (cfg >> 4) == 0x00;
bool black = (cfg & 0x0F) == 0x0F;
if (begin) {
@@ -291,16 +253,14 @@ void UC81xx_Write_Ram(epd_model_t *epd, uint8_t cfg, uint8_t *data, uint8_t len)
}
// Write native data to ram, format should be 2pp or above
void UC81xx_Write_Ram_Native(epd_model_t *epd, uint8_t cfg, uint8_t *data, uint8_t len)
{
void UC81xx_Write_Ram_Native(epd_model_t* epd, uint8_t cfg, uint8_t* data, uint8_t len) {
bool begin = (cfg >> 4) == 0x00;
bool black = (cfg & 0x0F) == 0x0F;
if (begin && black) EPD_WriteCmd(UC81xx_DTM1);
EPD_WriteData(data, len);
}
void UC81xx_Sleep(epd_model_t *epd)
{
void UC81xx_Sleep(epd_model_t* epd) {
UC81xx_PowerOff();
delay(100);
EPD_Write(UC81xx_DSLP, 0xA5);

View File

@@ -31,12 +31,13 @@ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
#include "Adafruit_GFX.h"
#include <stdarg.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "Adafruit_GFX.h"
#ifndef ABS
#define ABS(x) ((x) > 0 ? (x) : -(x))
@@ -45,15 +46,18 @@ POSSIBILITY OF SUCH DAMAGE.
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
#endif
#ifndef SWAP
#define SWAP(a, b, T) do { T t = a; a = b; b = t; } while (0)
#define SWAP(a, b, T) \
do { \
T t = a; \
a = b; \
b = t; \
} while (0)
#endif
#ifndef CONTAINER_OF
#define CONTAINER_OF(ptr, type, member) (type*)((char*)ptr - offsetof(type, member))
#endif
static void GFX_u8g2_draw_hv_line(u8g2_font_t *u8g2, int16_t x, int16_t y,
int16_t len, uint8_t dir, uint16_t color)
{
static void GFX_u8g2_draw_hv_line(u8g2_font_t* u8g2, int16_t x, int16_t y, int16_t len, uint8_t dir, uint16_t color) {
Adafruit_GFX* gfx = CONTAINER_OF(u8g2, Adafruit_GFX, u8g2);
switch (dir) {
case 0:
@@ -182,8 +186,7 @@ void GFX_setRotation(Adafruit_GFX *gfx, GFX_Rotate r) {
this is an addressing limitation of the e-paper controllers
*/
/**************************************************************************/
void GFX_setWindow(Adafruit_GFX *gfx, uint16_t x, uint16_t y, uint16_t w, uint16_t h)
{
void GFX_setWindow(Adafruit_GFX* gfx, uint16_t x, uint16_t y, uint16_t w, uint16_t h) {
gfx->px = MIN(x, gfx->_width);
gfx->py = MIN(y, gfx->_height);
gfx->pw = MIN(w, gfx->_width - gfx->px);
@@ -218,28 +221,50 @@ static uint8_t color4(uint16_t color) {
static uint8_t _prev_color4 = 0x00; // black
if (color == _prev_color) return _prev_color4;
uint8_t cv4 = 0x00;
switch (color)
{
case GFX_BLACK: cv4 = 0x00; break;
case GFX_WHITE: cv4 = 0x01; break;
case GFX_GREEN: cv4 = 0x02; break; // use yellow?
case GFX_BLUE: cv4 = 0x00; break; // use black
case GFX_RED: cv4 = 0x03; break;
case GFX_YELLOW: cv4 = 0x02; break;
case GFX_ORANGE: cv4 = 0x02; break; // use yellow?
switch (color) {
case GFX_BLACK:
cv4 = 0x00;
break;
case GFX_WHITE:
cv4 = 0x01;
break;
case GFX_GREEN:
cv4 = 0x02;
break; // use yellow?
case GFX_BLUE:
cv4 = 0x00;
break; // use black
case GFX_RED:
cv4 = 0x03;
break;
case GFX_YELLOW:
cv4 = 0x02;
break;
case GFX_ORANGE:
cv4 = 0x02;
break; // use yellow?
default: {
uint16_t red = color & 0xF800;
uint16_t green = (color & 0x07E0) << 5;
uint16_t blue = (color & 0x001F) << 11;
if ((red < 0x8000) && (green < 0x8000) && (blue < 0x8000)) cv4 = 0x00; // black
else if ((red >= 0x8000) && (green >= 0x8000) && (blue >= 0x8000)) cv4 = 0x01; // white
else if ((red >= 0x8000) && (blue >= 0x8000)) cv4 = 0x03; // red, blue > red
else if ((green >= 0x8000) && (blue >= 0x8000)) cv4 = 0x01; // green, blue > white
else if ((red >= 0x8000) && (green >= 0xC000)) cv4 = 0x02; // yellow
else if ((red >= 0x8000) && (green >= 0x4000)) cv4 = 0x03; // orange > red
else if (red >= 0x8000) cv4 = 0x03; // red
else if (green >= 0x8000) cv4 = 0x00; // green > black
else cv4 = 0x03; // blue
if ((red < 0x8000) && (green < 0x8000) && (blue < 0x8000))
cv4 = 0x00; // black
else if ((red >= 0x8000) && (green >= 0x8000) && (blue >= 0x8000))
cv4 = 0x01; // white
else if ((red >= 0x8000) && (blue >= 0x8000))
cv4 = 0x03; // red, blue > red
else if ((green >= 0x8000) && (blue >= 0x8000))
cv4 = 0x01; // green, blue > white
else if ((red >= 0x8000) && (green >= 0xC000))
cv4 = 0x02; // yellow
else if ((red >= 0x8000) && (green >= 0x4000))
cv4 = 0x03; // orange > red
else if (red >= 0x8000)
cv4 = 0x03; // red
else if (green >= 0x8000)
cv4 = 0x00; // green > black
else
cv4 = 0x03; // blue
} break;
}
_prev_color = color;
@@ -288,10 +313,18 @@ void GFX_drawPixel(Adafruit_GFX *gfx, int16_t x, int16_t y, uint16_t color) {
uint32_t i = x / 4 + ((uint32_t)y) * (gfx->pw / 4);
uint8_t pv = color4(color);
switch (x % 4) {
case 0: gfx->buffer[i] = (gfx->buffer[i] & 0x3F) | (pv << 6); break;
case 1: gfx->buffer[i] = (gfx->buffer[i] & 0xCF) | (pv << 4); break;
case 2: gfx->buffer[i] = (gfx->buffer[i] & 0xF3) | (pv << 2); break;
case 3: gfx->buffer[i] = (gfx->buffer[i] & 0xFC) | pv; break;
case 0:
gfx->buffer[i] = (gfx->buffer[i] & 0x3F) | (pv << 6);
break;
case 1:
gfx->buffer[i] = (gfx->buffer[i] & 0xCF) | (pv << 4);
break;
case 2:
gfx->buffer[i] = (gfx->buffer[i] & 0xF3) | (pv << 2);
break;
case 3:
gfx->buffer[i] = (gfx->buffer[i] & 0xFC) | pv;
break;
}
} else if (gfx->color != NULL) { // 3c
uint16_t i = x / 8 + y * (gfx->pw / 8);
@@ -320,8 +353,7 @@ void GFX_drawPixel(Adafruit_GFX *gfx, int16_t x, int16_t y, uint16_t color) {
@param color 16-bit 5-6-5 Color to draw with
*/
/**************************************************************************/
void GFX_drawLine(Adafruit_GFX *gfx, int16_t x0, int16_t y0, int16_t x1, int16_t y1,
uint16_t color) {
void GFX_drawLine(Adafruit_GFX* gfx, int16_t x0, int16_t y0, int16_t x1, int16_t y1, uint16_t color) {
int16_t steep = ABS(y1 - y0) > ABS(x1 - x0);
if (steep) {
SWAP(x0, y0, int16_t);
@@ -370,8 +402,8 @@ void GFX_drawLine(Adafruit_GFX *gfx, int16_t x0, int16_t y0, int16_t x1, int16_t
@param color 16-bit 5-6-5 Color to draw with
*/
/**************************************************************************/
void GFX_drawDottedLine(Adafruit_GFX *gfx, int16_t x0, int16_t y0, int16_t x1, int16_t y1,
uint16_t color, uint8_t dot_len, uint8_t space_len) {
void GFX_drawDottedLine(Adafruit_GFX* gfx, int16_t x0, int16_t y0, int16_t x1, int16_t y1, uint16_t color,
uint8_t dot_len, uint8_t space_len) {
int16_t steep = ABS(y1 - y0) > ABS(x1 - x0);
if (steep) {
SWAP(x0, y0, int16_t);
@@ -434,8 +466,7 @@ void GFX_drawDottedLine(Adafruit_GFX *gfx, int16_t x0, int16_t y0, int16_t x1, i
@param color 16-bit 5-6-5 Color to fill with
*/
/**************************************************************************/
void GFX_drawFastVLine(Adafruit_GFX *gfx, int16_t x, int16_t y, int16_t h,
uint16_t color) {
void GFX_drawFastVLine(Adafruit_GFX* gfx, int16_t x, int16_t y, int16_t h, uint16_t color) {
GFX_drawLine(gfx, x, y, x, y + h - 1, color);
}
@@ -448,8 +479,7 @@ void GFX_drawFastVLine(Adafruit_GFX *gfx, int16_t x, int16_t y, int16_t h,
@param color 16-bit 5-6-5 Color to fill with
*/
/**************************************************************************/
void GFX_drawFastHLine(Adafruit_GFX *gfx, int16_t x, int16_t y, int16_t w,
uint16_t color) {
void GFX_drawFastHLine(Adafruit_GFX* gfx, int16_t x, int16_t y, int16_t w, uint16_t color) {
GFX_drawLine(gfx, x, y, x + w - 1, y, color);
}
@@ -463,8 +493,7 @@ void GFX_drawFastHLine(Adafruit_GFX *gfx, int16_t x, int16_t y, int16_t w,
@param color 16-bit 5-6-5 Color to fill with
*/
/**************************************************************************/
void GFX_fillRect(Adafruit_GFX *gfx, int16_t x, int16_t y, int16_t w, int16_t h,
uint16_t color) {
void GFX_fillRect(Adafruit_GFX* gfx, int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color) {
for (int16_t i = x; i < x + w; i++) {
GFX_drawFastVLine(gfx, i, y, h, color);
}
@@ -483,8 +512,7 @@ void GFX_fillScreen(Adafruit_GFX *gfx, uint16_t color) {
memset(gfx->buffer, pv, size * 2);
} else {
memset(gfx->buffer, color == GFX_WHITE ? 0xFF : 0x00, size);
if (gfx->color != NULL)
memset(gfx->color, color == GFX_RED ? 0x00 : 0xFF, size);
if (gfx->color != NULL) memset(gfx->color, color == GFX_RED ? 0x00 : 0xFF, size);
}
}
@@ -497,8 +525,7 @@ void GFX_fillScreen(Adafruit_GFX *gfx, uint16_t color) {
@param color 16-bit 5-6-5 Color to draw with
*/
/**************************************************************************/
void GFX_drawCircle(Adafruit_GFX *gfx, int16_t x0, int16_t y0, int16_t r,
uint16_t color) {
void GFX_drawCircle(Adafruit_GFX* gfx, int16_t x0, int16_t y0, int16_t r, uint16_t color) {
int16_t f = 1 - r;
int16_t ddF_x = 1;
int16_t ddF_y = -2 * r;
@@ -542,8 +569,7 @@ void GFX_drawCircle(Adafruit_GFX *gfx, int16_t x0, int16_t y0, int16_t r,
@param color 16-bit 5-6-5 Color to draw with
*/
/**************************************************************************/
void GFX_drawCircleHelper(Adafruit_GFX *gfx, int16_t x0, int16_t y0, int16_t r,
uint8_t cornername, uint16_t color) {
void GFX_drawCircleHelper(Adafruit_GFX* gfx, int16_t x0, int16_t y0, int16_t r, uint8_t cornername, uint16_t color) {
int16_t f = 1 - r;
int16_t ddF_x = 1;
int16_t ddF_y = -2 * r;
@@ -587,8 +613,7 @@ void GFX_drawCircleHelper(Adafruit_GFX *gfx, int16_t x0, int16_t y0, int16_t r,
@param color 16-bit 5-6-5 Color to fill with
*/
/**************************************************************************/
void GFX_fillCircle(Adafruit_GFX *gfx, int16_t x0, int16_t y0, int16_t r,
uint16_t color) {
void GFX_fillCircle(Adafruit_GFX* gfx, int16_t x0, int16_t y0, int16_t r, uint16_t color) {
GFX_drawFastVLine(gfx, x0, y0 - r, 2 * r + 1, color);
GFX_fillCircleHelper(gfx, x0, y0, r, 3, 0, color);
}
@@ -604,9 +629,8 @@ void GFX_fillCircle(Adafruit_GFX *gfx, int16_t x0, int16_t y0, int16_t r,
@param color 16-bit 5-6-5 Color to fill with
*/
/**************************************************************************/
void GFX_fillCircleHelper(Adafruit_GFX *gfx, int16_t x0, int16_t y0, int16_t r,
uint8_t corners, int16_t delta, uint16_t color) {
void GFX_fillCircleHelper(Adafruit_GFX* gfx, int16_t x0, int16_t y0, int16_t r, uint8_t corners, int16_t delta,
uint16_t color) {
int16_t f = 1 - r;
int16_t ddF_x = 1;
int16_t ddF_y = -2 * r;
@@ -629,16 +653,12 @@ void GFX_fillCircleHelper(Adafruit_GFX *gfx, int16_t x0, int16_t y0, int16_t r,
// These checks avoid double-drawing certain lines, important
// for the SSD1306 library which has an INVERT drawing mode.
if (x < (y + 1)) {
if (corners & 1)
GFX_drawFastVLine(gfx, x0 + x, y0 - y, 2 * y + delta, color);
if (corners & 2)
GFX_drawFastVLine(gfx, x0 - x, y0 - y, 2 * y + delta, color);
if (corners & 1) GFX_drawFastVLine(gfx, x0 + x, y0 - y, 2 * y + delta, color);
if (corners & 2) GFX_drawFastVLine(gfx, x0 - x, y0 - y, 2 * y + delta, color);
}
if (y != py) {
if (corners & 1)
GFX_drawFastVLine(gfx, x0 + py, y0 - px, 2 * px + delta, color);
if (corners & 2)
GFX_drawFastVLine(gfx, x0 - py, y0 - px, 2 * px + delta, color);
if (corners & 1) GFX_drawFastVLine(gfx, x0 + py, y0 - px, 2 * px + delta, color);
if (corners & 2) GFX_drawFastVLine(gfx, x0 - py, y0 - px, 2 * px + delta, color);
py = y;
}
px = x;
@@ -655,8 +675,7 @@ void GFX_fillCircleHelper(Adafruit_GFX *gfx, int16_t x0, int16_t y0, int16_t r,
@param color 16-bit 5-6-5 Color to draw with
*/
/**************************************************************************/
void GFX_drawRect(Adafruit_GFX *gfx, int16_t x, int16_t y, int16_t w, int16_t h,
uint16_t color) {
void GFX_drawRect(Adafruit_GFX* gfx, int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color) {
GFX_drawFastHLine(gfx, x, y, w, color);
GFX_drawFastHLine(gfx, x, y + h - 1, w, color);
GFX_drawFastVLine(gfx, x, y, h, color);
@@ -674,11 +693,9 @@ void GFX_drawRect(Adafruit_GFX *gfx, int16_t x, int16_t y, int16_t w, int16_t h,
@param color 16-bit 5-6-5 Color to draw with
*/
/**************************************************************************/
void GFX_drawRoundRect(Adafruit_GFX *gfx, int16_t x, int16_t y, int16_t w,
int16_t h, int16_t r, uint16_t color) {
void GFX_drawRoundRect(Adafruit_GFX* gfx, int16_t x, int16_t y, int16_t w, int16_t h, int16_t r, uint16_t color) {
int16_t max_radius = ((w < h) ? w : h) / 2; // 1/2 minor axis
if (r > max_radius)
r = max_radius;
if (r > max_radius) r = max_radius;
// smarter version
GFX_drawFastHLine(gfx, x + r, y, w - 2 * r, color); // Top
GFX_drawFastHLine(gfx, x + r, y + h - 1, w - 2 * r, color); // Bottom
@@ -702,11 +719,9 @@ void GFX_drawRoundRect(Adafruit_GFX *gfx, int16_t x, int16_t y, int16_t w,
@param color 16-bit 5-6-5 Color to draw/fill with
*/
/**************************************************************************/
void GFX_fillRoundRect(Adafruit_GFX *gfx, int16_t x, int16_t y, int16_t w,
int16_t h, int16_t r, uint16_t color) {
void GFX_fillRoundRect(Adafruit_GFX* gfx, int16_t x, int16_t y, int16_t w, int16_t h, int16_t r, uint16_t color) {
int16_t max_radius = ((w < h) ? w : h) / 2; // 1/2 minor axis
if (r > max_radius)
r = max_radius;
if (r > max_radius) r = max_radius;
// smarter version
GFX_fillRect(gfx, x + r, y, w - 2 * r, h, color);
// draw four corners
@@ -726,8 +741,8 @@ void GFX_fillRoundRect(Adafruit_GFX *gfx, int16_t x, int16_t y, int16_t w,
@param color 16-bit 5-6-5 Color to draw with
*/
/**************************************************************************/
void GFX_drawTriangle(Adafruit_GFX *gfx, int16_t x0, int16_t y0, int16_t x1,
int16_t y1, int16_t x2, int16_t y2, uint16_t color) {
void GFX_drawTriangle(Adafruit_GFX* gfx, int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t x2, int16_t y2,
uint16_t color) {
GFX_drawLine(gfx, x0, y0, x1, y1, color);
GFX_drawLine(gfx, x1, y1, x2, y2, color);
GFX_drawLine(gfx, x2, y2, x0, y0, color);
@@ -745,9 +760,8 @@ void GFX_drawTriangle(Adafruit_GFX *gfx, int16_t x0, int16_t y0, int16_t x1,
@param color 16-bit 5-6-5 Color to fill/draw with
*/
/**************************************************************************/
void GFX_fillTriangle(Adafruit_GFX *gfx, int16_t x0, int16_t y0, int16_t x1,
int16_t y1, int16_t x2, int16_t y2, uint16_t color) {
void GFX_fillTriangle(Adafruit_GFX* gfx, int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t x2, int16_t y2,
uint16_t color) {
int16_t a, b, y, last;
// Sort coordinates by Y order (y2 >= y1 >= y0)
@@ -778,8 +792,7 @@ void GFX_fillTriangle(Adafruit_GFX *gfx, int16_t x0, int16_t y0, int16_t x1,
return;
}
int16_t dx01 = x1 - x0, dy01 = y1 - y0, dx02 = x2 - x0, dy02 = y2 - y0,
dx12 = x2 - x1, dy12 = y2 - y1;
int16_t dx01 = x1 - x0, dy01 = y1 - y0, dx02 = x2 - x0, dy02 = y2 - y0, dx12 = x2 - x1, dy12 = y2 - y1;
int32_t sa = 0, sb = 0;
// For upper part of triangle, find scanline crossings for segments
@@ -802,8 +815,7 @@ void GFX_fillTriangle(Adafruit_GFX *gfx, int16_t x0, int16_t y0, int16_t x1,
a = x0 + (x1 - x0) * (y - y0) / (y1 - y0);
b = x0 + (x2 - x0) * (y - y0) / (y2 - y0);
*/
if (a > b)
SWAP(a, b, int16_t);
if (a > b) SWAP(a, b, int16_t);
GFX_drawFastHLine(gfx, a, y, b - a + 1, color);
}
@@ -820,8 +832,7 @@ void GFX_fillTriangle(Adafruit_GFX *gfx, int16_t x0, int16_t y0, int16_t x1,
a = x1 + (x2 - x1) * (y - y1) / (y2 - y1);
b = x0 + (x2 - x0) * (y - y0) / (y2 - y0);
*/
if (a > b)
SWAP(a, b, int16_t);
if (a > b) SWAP(a, b, int16_t);
GFX_drawFastHLine(gfx, a, y, b - a + 1, color);
}
}
@@ -839,9 +850,8 @@ void GFX_fillTriangle(Adafruit_GFX *gfx, int16_t x0, int16_t y0, int16_t x1,
@param invert When true, will invert the bitmap
*/
/**************************************************************************/
void GFX_drawBitmap(Adafruit_GFX *gfx, int16_t x, int16_t y, const uint8_t bitmap[],
int16_t w, int16_t h, uint16_t color, bool invert) {
void GFX_drawBitmap(Adafruit_GFX* gfx, int16_t x, int16_t y, const uint8_t bitmap[], int16_t w, int16_t h,
uint16_t color, bool invert) {
int16_t byteWidth = (w + 7) / 8; // Bitmap scanline pad = whole byte
uint8_t byte = 0;
@@ -851,8 +861,7 @@ void GFX_drawBitmap(Adafruit_GFX *gfx, int16_t x, int16_t y, const uint8_t bitma
byte <<= 1;
else
byte = bitmap[j * byteWidth + i / 8];
if (((byte & 0x80) == 0x80) ^ invert)
GFX_drawPixel(gfx, x + i, y + j, color);
if (((byte & 0x80) == 0x80) ^ invert) GFX_drawPixel(gfx, x + i, y + j, color);
}
}
}
@@ -900,34 +909,22 @@ void GFX_setCursor(Adafruit_GFX *gfx, int16_t x, int16_t y) {
gfx->utf8_state = 0;
}
void GFX_setFont(Adafruit_GFX *gfx, const uint8_t *font) {
u8g2_SetFont(&gfx->u8g2, font);
}
void GFX_setFont(Adafruit_GFX* gfx, const uint8_t* font) { u8g2_SetFont(&gfx->u8g2, font); }
void GFX_setFontMode(Adafruit_GFX *gfx, uint8_t is_transparent) {
u8g2_SetFontMode(&gfx->u8g2, is_transparent);
}
void GFX_setFontMode(Adafruit_GFX* gfx, uint8_t is_transparent) { u8g2_SetFontMode(&gfx->u8g2, is_transparent); }
void GFX_setFontDirection(Adafruit_GFX *gfx, GFX_Rotate d) {
u8g2_SetFontDirection(&gfx->u8g2, (uint8_t)d);
}
void GFX_setFontDirection(Adafruit_GFX* gfx, GFX_Rotate d) { u8g2_SetFontDirection(&gfx->u8g2, (uint8_t)d); }
void GFX_setTextColor(Adafruit_GFX* gfx, uint16_t fg, uint16_t bg) {
u8g2_SetForegroundColor(&gfx->u8g2, fg);
u8g2_SetBackgroundColor(&gfx->u8g2, bg);
}
int8_t GFX_getFontAscent(Adafruit_GFX *gfx) {
return gfx->u8g2.font_info.ascent_A;
}
int8_t GFX_getFontAscent(Adafruit_GFX* gfx) { return gfx->u8g2.font_info.ascent_A; }
int8_t GFX_getFontDescent(Adafruit_GFX *gfx) {
return gfx->u8g2.font_info.descent_g;
}
int8_t GFX_getFontDescent(Adafruit_GFX* gfx) { return gfx->u8g2.font_info.descent_g; }
int8_t GFX_getFontHeight(Adafruit_GFX *gfx) {
return gfx->u8g2.font_info.ascent_A - gfx->u8g2.font_info.descent_g;
}
int8_t GFX_getFontHeight(Adafruit_GFX* gfx) { return gfx->u8g2.font_info.ascent_A - gfx->u8g2.font_info.descent_g; }
int16_t GFX_drawGlyph(Adafruit_GFX* gfx, int16_t x, int16_t y, uint16_t e) {
return u8g2_DrawGlyph(&gfx->u8g2, x, y, e);
@@ -937,77 +934,57 @@ int16_t GFX_drawStr(Adafruit_GFX *gfx, int16_t x, int16_t y, const char *s) {
return u8g2_DrawStr(&gfx->u8g2, x, y, s);
}
static uint16_t utf8_next(Adafruit_GFX *gfx, uint8_t b)
{
static uint16_t utf8_next(Adafruit_GFX* gfx, uint8_t b) {
if (b == 0) /* '\n' terminates the string to support the string list procedures */
return 0x0ffff; /* end of string detected, pending UTF8 is discarded */
if ( gfx->utf8_state == 0 )
{
if (gfx->utf8_state == 0) {
if (b >= 0xfc) /* 6 byte sequence */
{
gfx->utf8_state = 5;
b &= 1;
}
else if ( b >= 0xf8 )
{
} else if (b >= 0xf8) {
gfx->utf8_state = 4;
b &= 3;
}
else if ( b >= 0xf0 )
{
} else if (b >= 0xf0) {
gfx->utf8_state = 3;
b &= 7;
}
else if ( b >= 0xe0 )
{
} else if (b >= 0xe0) {
gfx->utf8_state = 2;
b &= 15;
}
else if ( b >= 0xc0 )
{
} else if (b >= 0xc0) {
gfx->utf8_state = 1;
b &= 0x01f;
}
else
{
} else {
/* do nothing, just use the value as encoding */
return b;
}
gfx->encoding = b;
return 0x0fffe;
}
else
{
} else {
gfx->utf8_state--;
/* The case b < 0x080 (an illegal UTF8 encoding) is not checked here. */
gfx->encoding <<= 6;
b &= 0x03f;
gfx->encoding |= b;
if ( gfx->utf8_state != 0 )
return 0x0fffe; /* nothing to do yet */
if (gfx->utf8_state != 0) return 0x0fffe; /* nothing to do yet */
}
return gfx->encoding;
}
int16_t GFX_drawUTF8(Adafruit_GFX *gfx, int16_t x, int16_t y, const char *str)
{
int16_t GFX_drawUTF8(Adafruit_GFX* gfx, int16_t x, int16_t y, const char* str) {
uint16_t e;
int16_t delta, sum;
gfx->utf8_state = 0;
sum = 0;
for(;;)
{
for (;;) {
e = utf8_next(gfx, (uint8_t)*str);
if ( e == 0x0ffff )
break;
if (e == 0x0ffff) break;
str++;
if ( e != 0x0fffe )
{
if (e != 0x0fffe) {
delta = u8g2_DrawGlyph(&gfx->u8g2, x, y, e);
switch(gfx->u8g2.font_decode.dir)
{
switch (gfx->u8g2.font_decode.dir) {
case 0:
x += delta;
break;
@@ -1028,8 +1005,7 @@ int16_t GFX_drawUTF8(Adafruit_GFX *gfx, int16_t x, int16_t y, const char *str)
return sum;
}
int16_t GFX_getUTF8Width(Adafruit_GFX *gfx, const char *str)
{
int16_t GFX_getUTF8Width(Adafruit_GFX* gfx, const char* str) {
uint16_t e;
int16_t dx, w;
@@ -1037,21 +1013,17 @@ int16_t GFX_getUTF8Width(Adafruit_GFX *gfx, const char *str)
gfx->utf8_state = 0;
w = 0;
dx = 0;
for(;;)
{
for (;;) {
e = utf8_next(gfx, (uint8_t)*str);
if ( e == 0x0ffff )
break;
if (e == 0x0ffff) break;
str++;
if ( e != 0x0fffe )
{
if (e != 0x0fffe) {
dx = u8g2_GetGlyphWidth(&gfx->u8g2, e);
w += dx;
}
}
/* adjust the last glyph, check for issue #16: do not adjust if width is 0 */
if ( gfx->u8g2.font_decode.glyph_width != 0 )
{
if (gfx->u8g2.font_decode.glyph_width != 0) {
w -= dx;
w += gfx->u8g2.font_decode.glyph_width; /* the real pixel width of the glyph, sideeffect of GetGlyphWidth */
/* issue #46: we have to add the x offset also */
@@ -1061,8 +1033,7 @@ int16_t GFX_getUTF8Width(Adafruit_GFX *gfx, const char *str)
return w;
}
int16_t GFX_getUTF8Widthf(Adafruit_GFX *gfx, const char* format, ...)
{
int16_t GFX_getUTF8Widthf(Adafruit_GFX* gfx, const char* format, ...) {
char buf[64] = {0};
char* str = buf;
size_t len;
@@ -1072,11 +1043,9 @@ int16_t GFX_getUTF8Widthf(Adafruit_GFX *gfx, const char* format, ...)
len = vsnprintf(buf, sizeof(buf), format, va);
va_end(va);
if (len > sizeof(buf) - 1)
{
if (len > sizeof(buf) - 1) {
str = malloc(len + 1);
if (str == NULL)
return 0;
if (str == NULL) return 0;
va_start(va, format);
vsnprintf(str, len + 1, format, va);
va_end(va);
@@ -1084,8 +1053,7 @@ int16_t GFX_getUTF8Widthf(Adafruit_GFX *gfx, const char* format, ...)
int16_t w = GFX_getUTF8Width(gfx, str);
if (str != buf)
free(str);
if (str != buf) free(str);
return w;
}
@@ -1093,20 +1061,14 @@ int16_t GFX_getUTF8Widthf(Adafruit_GFX *gfx, const char* format, ...)
size_t GFX_print(Adafruit_GFX* gfx, const char c) {
int16_t delta;
uint16_t e = utf8_next(gfx, (uint8_t)c);
if ( e == '\n' )
{
if (e == '\n') {
gfx->tx = 0;
gfx->ty += gfx->u8g2.font_info.ascent_para - gfx->u8g2.font_info.descent_para;
}
else if ( e == '\r' )
{
} else if (e == '\r') {
gfx->tx = 0;
}
else if ( e < 0x0fffe )
{
} else if (e < 0x0fffe) {
delta = u8g2_DrawGlyph(&gfx->u8g2, gfx->tx, gfx->ty, e);
switch(gfx->u8g2.font_decode.dir)
{
switch (gfx->u8g2.font_decode.dir) {
case 0:
gfx->tx += delta;
break;
@@ -1143,19 +1105,16 @@ size_t GFX_printf(Adafruit_GFX *gfx, const char* format, ...) {
len = vsnprintf(tmp, sizeof(tmp), format, va);
va_end(va);
if (len > sizeof(tmp) - 1)
{
if (len > sizeof(tmp) - 1) {
buf = malloc(len + 1);
if (buf == NULL)
return 0;
if (buf == NULL) return 0;
va_start(va, format);
vsnprintf(buf, len + 1, format, va);
va_end(va);
}
len = GFX_write(gfx, buf, len);
if (buf != tmp)
free(buf);
if (buf != tmp) free(buf);
return len;
}

View File

@@ -4,6 +4,7 @@
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#include "u8g2_font.h"
#define GFX_BLACK 0x0000
@@ -14,7 +15,8 @@
#define GFX_GREEN 0x07E0 // 0, 255, 0
#define GFX_ORANGE 0xFC00 // 255, 128, 0
typedef void (*buffer_callback)(void *user_data, uint8_t *black, uint8_t *color, uint16_t x, uint16_t y, uint16_t w, uint16_t h);
typedef void (*buffer_callback)(void* user_data, uint8_t* black, uint8_t* color, uint16_t x, uint16_t y, uint16_t w,
uint16_t h);
typedef enum {
GFX_ROTATE_0 = 0,
@@ -34,7 +36,8 @@ typedef struct {
u8g2_font_t u8g2;
int16_t tx, ty; // current position for the print command
uint16_t encoding; // the unicode, detected by the utf-8 decoder
uint8_t utf8_state; // current state of the utf-8 decoder, contains the remaining bytes for a detected unicode glyph
uint8_t
utf8_state; // current state of the utf-8 decoder, contains the remaining bytes for a detected unicode glyph
uint8_t* buffer; // black pixel buffer
uint8_t* color; // color pixel buffer (3c only)
@@ -57,29 +60,26 @@ void GFX_end(Adafruit_GFX *gfx);
// DRAW API
void GFX_drawPixel(Adafruit_GFX* gfx, int16_t x, int16_t y, uint16_t color);
void GFX_drawLine(Adafruit_GFX* gfx, int16_t x0, int16_t y0, int16_t x1, int16_t y1, uint16_t color);
void GFX_drawDottedLine(Adafruit_GFX *gfx, int16_t x0, int16_t y0, int16_t x1, int16_t y1,
uint16_t color, uint8_t dot_len, uint8_t space_len);
void GFX_drawDottedLine(Adafruit_GFX* gfx, int16_t x0, int16_t y0, int16_t x1, int16_t y1, uint16_t color,
uint8_t dot_len, uint8_t space_len);
void GFX_drawFastVLine(Adafruit_GFX* gfx, int16_t x, int16_t y, int16_t h, uint16_t color);
void GFX_drawFastHLine(Adafruit_GFX* gfx, int16_t x, int16_t y, int16_t w, uint16_t color);
void GFX_fillRect(Adafruit_GFX* gfx, int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color);
void GFX_fillScreen(Adafruit_GFX* gfx, uint16_t color);
void GFX_drawRect(Adafruit_GFX* gfx, int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color);
void GFX_drawCircle(Adafruit_GFX* gfx, int16_t x0, int16_t y0, int16_t r, uint16_t color);
void GFX_drawCircleHelper(Adafruit_GFX *gfx, int16_t x0, int16_t y0, int16_t r, uint8_t cornername,
uint16_t color);
void GFX_drawCircleHelper(Adafruit_GFX* gfx, int16_t x0, int16_t y0, int16_t r, uint8_t cornername, uint16_t color);
void GFX_fillCircle(Adafruit_GFX* gfx, int16_t x0, int16_t y0, int16_t r, uint16_t color);
void GFX_fillCircleHelper(Adafruit_GFX *gfx, int16_t x0, int16_t y0, int16_t r, uint8_t cornername,
int16_t delta, uint16_t color);
void GFX_drawTriangle(Adafruit_GFX *gfx, int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t x2,
int16_t y2, uint16_t color);
void GFX_fillTriangle(Adafruit_GFX *gfx, int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t x2,
int16_t y2, uint16_t color);
void GFX_drawRoundRect(Adafruit_GFX *gfx, int16_t x0, int16_t y0, int16_t w, int16_t h,
int16_t radius, uint16_t color);
void GFX_fillRoundRect(Adafruit_GFX *gfx, int16_t x0, int16_t y0, int16_t w, int16_t h,
int16_t radius, uint16_t color);
void GFX_drawBitmap(Adafruit_GFX *gfx, int16_t x, int16_t y, const uint8_t bitmap[], int16_t w,
int16_t h, uint16_t color, bool invert);
void GFX_fillCircleHelper(Adafruit_GFX* gfx, int16_t x0, int16_t y0, int16_t r, uint8_t cornername, int16_t delta,
uint16_t color);
void GFX_drawTriangle(Adafruit_GFX* gfx, int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t x2, int16_t y2,
uint16_t color);
void GFX_fillTriangle(Adafruit_GFX* gfx, int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t x2, int16_t y2,
uint16_t color);
void GFX_drawRoundRect(Adafruit_GFX* gfx, int16_t x0, int16_t y0, int16_t w, int16_t h, int16_t radius, uint16_t color);
void GFX_fillRoundRect(Adafruit_GFX* gfx, int16_t x0, int16_t y0, int16_t w, int16_t h, int16_t radius, uint16_t color);
void GFX_drawBitmap(Adafruit_GFX* gfx, int16_t x, int16_t y, const uint8_t bitmap[], int16_t w, int16_t h,
uint16_t color, bool invert);
// U8G2 FONT API
void GFX_setCursor(Adafruit_GFX* gfx, int16_t x, int16_t y);

View File

@@ -1,8 +1,10 @@
#include "fonts.h"
#include "Lunar.h"
#include "GUI.h"
#include <time.h>
#include <stdio.h>
#include <time.h>
#include "Lunar.h"
#include "fonts.h"
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
#define GFX_printf_styled(gfx, fg, bg, font, ...) \
@@ -17,49 +19,25 @@ typedef struct {
} Festival;
static const Festival festivals[] = {
{ 1, 1, "元旦"},
{ 2, 14, "情人"},
{ 3, 8, "妇女"},
{ 3, 12, "植树节"},
{ 4, 1, "愚人节"},
{ 5, 1, "劳动节"},
{ 5, 4, "青年节"},
{ 6, 1, "儿童节"},
{ 7, 1, "建党节"},
{ 8, 1, "建军节"},
{ 9, 10, "教师节"},
{10, 1, "国庆节"},
{11, 1, "万圣节"},
{12, 24, "平安夜"},
{12, 25, "圣诞节"},
{1, 1, "元旦节"}, {2, 14, "情人节"}, {3, 8, "妇女节"}, {3, 12, "植树节"}, {4, 1, "愚人"},
{5, 1, "劳动节"}, {5, 4, "青年节"}, {6, 1, "儿童节"}, {7, 1, "建党节"}, {8, 1, "建军"},
{9, 10, "教师节"}, {10, 1, "国庆节"}, {11, 1, "万圣节"}, {12, 24, "平安夜"}, {12, 25, "圣诞"},
};
static const Festival festivals_lunar[] = {
{ 1, 1, "" },
{ 1, 15, "元宵"},
{ 2, 2, "龙抬头"},
{ 5, 5, "端午节"},
{ 7, 7, "七夕节"},
{ 7, 15, "中元节"},
{ 8, 15, "中秋节"},
{ 9, 9, "重阳节"},
{10, 1, "寒衣节"},
{12, 8, "腊八节"},
{12, 30, "除夕" },
{1, 1, "春节"}, {1, 15, "元宵"}, {2, 2, "龙抬头"}, {5, 5, "端午节"}, {7, 7, "七夕节"}, {7, 15, "中元节"},
{8, 15, "中秋节"}, {9, 9, "重阳节"}, {10, 1, "寒衣节"}, {12, 8, "腊八"}, {12, 30, "除夕"},
};
// 放假和调休数据,每年更新
#define HOLIDAY_YEAR 2025
static const uint16_t holidays[] = {
0x0101, 0x111A, 0x011C, 0x011D, 0x011E, 0x011F, 0x0201, 0x0202,
0x0202, 0x0203, 0x0204, 0x1208, 0x0404, 0x0405, 0x0406, 0x141B,
0x0501, 0x0502, 0x0503, 0x0504, 0x0505, 0x051F, 0x0601, 0x0602,
0x191C, 0x0A01, 0x0A02, 0x0A03, 0x0A04, 0x0A05, 0x0A06, 0x0A07,
0x0A08, 0x1A0B,
0x0101, 0x111A, 0x011C, 0x011D, 0x011E, 0x011F, 0x0201, 0x0202, 0x0202, 0x0203, 0x0204, 0x1208,
0x0404, 0x0405, 0x0406, 0x141B, 0x0501, 0x0502, 0x0503, 0x0504, 0x0505, 0x051F, 0x0601, 0x0602,
0x191C, 0x0A01, 0x0A02, 0x0A03, 0x0A04, 0x0A05, 0x0A06, 0x0A07, 0x0A08, 0x1A0B,
};
static bool GetHoliday(uint8_t mon, uint8_t day, bool *work)
{
static bool GetHoliday(uint8_t mon, uint8_t day, bool* work) {
for (uint8_t i = 0; i < ARRAY_SIZE(holidays); i++) {
if (((holidays[i] >> 8) & 0xF) == mon && (holidays[i] & 0xFF) == day) {
*work = ((holidays[i] >> 12) & 0xF) > 0;
@@ -69,9 +47,8 @@ static bool GetHoliday(uint8_t mon, uint8_t day, bool *work)
return false;
}
static bool GetFestival(uint16_t year, uint8_t mon, uint8_t day, uint8_t week,
struct Lunar_Date *Lunar, char *festival)
{
static bool GetFestival(uint16_t year, uint8_t mon, uint8_t day, uint8_t week, struct Lunar_Date* Lunar,
char* festival) {
// 农历节日
for (uint8_t i = 0; i < ARRAY_SIZE(festivals_lunar); i++) {
if (Lunar->Month == festivals_lunar[i].month && Lunar->Date == festivals_lunar[i].day) {
@@ -130,8 +107,7 @@ static bool GetFestival(uint16_t year, uint8_t mon, uint8_t day, uint8_t week,
return false;
}
static void DrawTimeSyncTip(Adafruit_GFX *gfx, gui_data_t *data)
{
static void DrawTimeSyncTip(Adafruit_GFX* gfx, gui_data_t* data) {
const char* title = "SYNC TIME!";
const char* url = "https://tsl0922.github.io/EPD-nRF5";
@@ -153,8 +129,7 @@ static void DrawTimeSyncTip(Adafruit_GFX *gfx, gui_data_t *data)
GFX_printf(gfx, url);
}
static void DrawBattery(Adafruit_GFX *gfx, int16_t x, int16_t y, uint8_t iw, float voltage)
{
static void DrawBattery(Adafruit_GFX* gfx, int16_t x, int16_t y, uint8_t iw, float voltage) {
x -= iw;
uint8_t level = (uint8_t)(voltage * 100 / 3.6f);
GFX_setFont(gfx, u8g2_font_wqy9_t_lunar);
@@ -166,8 +141,7 @@ static void DrawBattery(Adafruit_GFX *gfx, int16_t x, int16_t y, uint8_t iw, flo
GFX_fillRect(gfx, x + 2, y + 2, 16 * level / 100, 6, GFX_BLACK);
}
static uint8_t GetWeekOfYear(uint8_t year, uint8_t mon, uint8_t mday, uint8_t wday)
{
static uint8_t GetWeekOfYear(uint8_t year, uint8_t mon, uint8_t mday, uint8_t wday) {
struct tm tm = {0};
tm.tm_year = year;
tm.tm_mon = mon;
@@ -180,8 +154,8 @@ static uint8_t GetWeekOfYear(uint8_t year, uint8_t mon, uint8_t mday, uint8_t wd
return atoi(buffer);
}
static void DrawDateHeader(Adafruit_GFX *gfx, int16_t x, int16_t y, tm_t *tm, struct Lunar_Date *Lunar, gui_data_t *data)
{
static void DrawDateHeader(Adafruit_GFX* gfx, int16_t x, int16_t y, tm_t* tm, struct Lunar_Date* Lunar,
gui_data_t* data) {
GFX_setCursor(gfx, x, y - 2);
GFX_printf_styled(gfx, GFX_RED, GFX_WHITE, u8g2_font_helvB18_tn, "%d", tm->tm_year + YEAR0);
GFX_printf_styled(gfx, GFX_BLACK, GFX_WHITE, u8g2_font_wqy12_t_lunar, "");
@@ -211,8 +185,7 @@ static void DrawDateHeader(Adafruit_GFX *gfx, int16_t x, int16_t y, tm_t *tm, st
GFX_printf(gfx, "%s", data->ssid);
}
static void DrawWeekHeader(Adafruit_GFX *gfx, int16_t x, int16_t y, gui_data_t *data)
{
static void DrawWeekHeader(Adafruit_GFX* gfx, int16_t x, int16_t y, gui_data_t* data) {
GFX_setFont(gfx, data->height > 300 ? u8g2_font_wqy12_t_lunar : u8g2_font_wqy9_t_lunar);
uint8_t w = (data->width - 2 * x) / 7;
uint8_t h = data->height > 300 ? 32 : 24;
@@ -229,8 +202,8 @@ static void DrawWeekHeader(Adafruit_GFX *gfx, int16_t x, int16_t y, gui_data_t *
}
}
static void DrawMonthDays(Adafruit_GFX *gfx, int16_t x, int16_t y, tm_t *tm, struct Lunar_Date *Lunar, gui_data_t *data)
{
static void DrawMonthDays(Adafruit_GFX* gfx, int16_t x, int16_t y, tm_t* tm, struct Lunar_Date* Lunar,
gui_data_t* data) {
uint8_t firstDayWeek = get_first_day_week(tm->tm_year + YEAR0, tm->tm_mon + 1);
int8_t adjustedFirstDay = (firstDayWeek - data->week_start + 7) % 7;
uint8_t monthMaxDays = thisMonthMaxDays(tm->tm_year + YEAR0, tm->tm_mon + 1);
@@ -280,7 +253,8 @@ static void DrawMonthDays(Adafruit_GFX *gfx, int16_t x, int16_t y, tm_t *tm, str
if (day != tm->tm_mday) GFX_setTextColor(gfx, GFX_RED, GFX_WHITE);
} else {
if (Lunar->Date == 1)
snprintf(festival, sizeof(festival), "%s%s", Lunar_MonthLeapString[Lunar->IsLeap], Lunar_MonthString[Lunar->Month]);
snprintf(festival, sizeof(festival), "%s%s", Lunar_MonthLeapString[Lunar->IsLeap],
Lunar_MonthString[Lunar->Month]);
else
snprintf(festival, sizeof(festival), "%s", Lunar_DateString[Lunar->Date]);
}
@@ -304,14 +278,14 @@ static void DrawMonthDays(Adafruit_GFX *gfx, int16_t x, int16_t y, tm_t *tm, str
}
}
static void DrawCalendar(Adafruit_GFX *gfx, tm_t *tm, struct Lunar_Date *Lunar, gui_data_t *data)
{
static void DrawCalendar(Adafruit_GFX* gfx, tm_t* tm, struct Lunar_Date* Lunar, gui_data_t* data) {
bool large = data->height > 300;
DrawDateHeader(gfx, 10, large ? 38 : 28, tm, Lunar, data);
DrawWeekHeader(gfx, 10, large ? 44 : 32, data);
DrawMonthDays(gfx, 10, large ? 84 : 64, tm, Lunar, data);
}
// clang-format off
/* Routine to Draw Large 7-Segment formated number
Contributed by William Zaggle.
@@ -341,9 +315,9 @@ static void Draw7Number(Adafruit_GFX *gfx, int n, unsigned int xLoc, unsigned in
}
}
}
// clang-format on
static void DrawTime(Adafruit_GFX *gfx, tm_t *tm, int16_t x, int16_t y, uint16_t cS, uint16_t nD)
{
static void DrawTime(Adafruit_GFX* gfx, tm_t* tm, int16_t x, int16_t y, uint16_t cS, uint16_t nD) {
Draw7Number(gfx, tm->tm_hour, x, y, cS, GFX_BLACK, GFX_WHITE, nD);
x += (nD * (11 * cS + 2) - 2 * cS) + 2 * cS;
GFX_fillRect(gfx, x, y + 4.5 * cS + 1, 2 * cS, 2 * cS, GFX_BLACK);
@@ -352,8 +326,7 @@ static void DrawTime(Adafruit_GFX *gfx, tm_t *tm, int16_t x, int16_t y, uint16_t
Draw7Number(gfx, tm->tm_min, x, y, cS, GFX_BLACK, GFX_WHITE, nD);
}
static void DrawClock(Adafruit_GFX *gfx, tm_t *tm, struct Lunar_Date *Lunar, gui_data_t *data)
{
static void DrawClock(Adafruit_GFX* gfx, tm_t* tm, struct Lunar_Date* Lunar, gui_data_t* data) {
uint8_t padding = data->height > 300 ? 100 : 40;
GFX_setCursor(gfx, padding, 36);
GFX_printf_styled(gfx, GFX_RED, GFX_WHITE, u8g2_font_helvB18_tn, "%d", tm->tm_year + YEAR0);
@@ -422,8 +395,7 @@ static void DrawClock(Adafruit_GFX *gfx, tm_t *tm, struct Lunar_Date *Lunar, gui
}
}
void DrawGUI(gui_data_t *data, buffer_callback callback, void *callback_data)
{
void DrawGUI(gui_data_t* data, buffer_callback callback, void* callback_data) {
if (data->week_start > 6) data->week_start = 0;
tm_t tm = {0};

View File

@@ -1,32 +1,22 @@
#include "Lunar.h"
const char Lunar_MonthString[13][7] = {
"----",
"正月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月",
"冬月", "腊月"};
const char Lunar_MonthString[13][7] = {"----", "正月", "二月", "三月", "四月", "五月", "六月",
"七月", "八月", "九月", "十月", "冬月", "腊月"};
const char Lunar_MonthLeapString[2][4] = {
" ",
""};
const char Lunar_MonthLeapString[2][4] = {" ", ""};
const char Lunar_DateString[31][7] = {
"----",
"初一", "初二", "初三", "初四", "初五", "初六", "初七", "初八", "初九", "初十",
"十一", "十二", "十三", "", "", "", "", "", "", "",
"廿一", "廿二", "廿三", "廿四", "廿五", "廿六", "廿七", "廿八", "廿九", "三十"};
const char Lunar_DateString[31][7] = {"----", "初一", "初二", "初三", "初四", "初五", "初六", "初七",
"初八", "初九", "初十", "十一", "十二", "十三", "十四", "十五",
"十六", "十七", "十八", "十九", "二十", "廿一", "廿二", "廿三",
"廿", "廿", "廿", "廿", "廿", "廿", ""};
const char Lunar_DayString[7][4] = {
"",
"", "", "", "", "", ""};
const char Lunar_DayString[7][4] = {"", "", "", "", "", "", ""};
const char Lunar_ZodiacString[12][4] = {
"", "", "", "", "", "", "", "", "", "", "", ""};
const char Lunar_ZodiacString[12][4] = {"", "", "", "", "", "", "", "", "", "", "", ""};
const char Lunar_StemStrig[10][4] = {
"", "", "", "", "", "", "", "", "", ""};
const char Lunar_StemStrig[10][4] = {"", "", "", "", "", "", "", "", "", ""};
const char Lunar_BranchStrig[12][4] = {
"", "", "", "", "", "", "", "", "", "", "", ""};
const char Lunar_BranchStrig[12][4] = {"", "", "", "", "", "", "", "", "", "", "", ""};
/* 2000 ~ 2199 */
const uint32_t lunar_month_days[] = {
@@ -82,28 +72,24 @@ const uint32_t solar_1_1[] = {
0x00111648, 0x0011183C, 0x00111A4F, 0x00111C45, 0x00111E39, 0x0011204D, 0x00112242, 0x00112436, 0x0011264A,
0x0011283E, 0x00112A51, 0x00112C46, 0x00112E3B, 0x0011304F*/};
static uint32_t GetBitInt(uint32_t data, uint8_t length, uint8_t shift)
{
static uint32_t GetBitInt(uint32_t data, uint8_t length, uint8_t shift) {
return (data & (((1 << length) - 1) << shift)) >> shift;
}
// WARNING: Dates before Oct. 1582 are inaccurate
static uint16_t SolarToInt(uint16_t y, uint8_t m, uint8_t d)
{
static uint16_t SolarToInt(uint16_t y, uint8_t m, uint8_t d) {
m = (m + 9) % 12;
y = y - m / 10;
return 365 * y + y / 4 - y / 100 + y / 400 + (m * 306 + 5) / 10 + (d - 1);
}
void LUNAR_SolarToLunar(struct Lunar_Date *lunar, uint16_t solar_year, uint8_t solar_month, uint8_t solar_date)
{
void LUNAR_SolarToLunar(struct Lunar_Date* lunar, uint16_t solar_year, uint8_t solar_month, uint8_t solar_date) {
uint8_t i, lunarM, m, d, leap, dm;
uint16_t year_index, lunarY, y, offset;
uint32_t solar_data, solar11, days;
if (solar_month < 1 || solar_month > 12 || solar_date < 1 || solar_date > 31 ||
(solar_year - solar_1_1[0] < 3) || ((solar_year - solar_1_1[0]) > (sizeof(solar_1_1) / sizeof(uint32_t) - 2)))
{
if (solar_month < 1 || solar_month > 12 || solar_date < 1 || solar_date > 31 || (solar_year - solar_1_1[0] < 3) ||
((solar_year - solar_1_1[0]) > (sizeof(solar_1_1) / sizeof(uint32_t) - 2))) {
lunar->Year = 0;
lunar->Month = 0;
lunar->Date = 0;
@@ -113,8 +99,7 @@ void LUNAR_SolarToLunar(struct Lunar_Date *lunar, uint16_t solar_year, uint8_t s
year_index = solar_year - solar_1_1[0];
solar_data = ((uint32_t)solar_year << 9) | ((uint32_t)solar_month << 5) | ((uint32_t)solar_date);
if (solar_1_1[year_index] > solar_data)
{
if (solar_1_1[year_index] > solar_data) {
year_index -= 1;
}
solar11 = solar_1_1[year_index];
@@ -129,31 +114,22 @@ void LUNAR_SolarToLunar(struct Lunar_Date *lunar, uint16_t solar_year, uint8_t s
lunarY = year_index + solar_1_1[0];
lunarM = 1;
offset += 1;
for (i = 0; i < 13; i++)
{
if (GetBitInt(days, 1, 12 - i) == 1)
{
for (i = 0; i < 13; i++) {
if (GetBitInt(days, 1, 12 - i) == 1) {
dm = 30;
}
else
{
} else {
dm = 29;
}
if (offset > dm)
{
if (offset > dm) {
lunarM += 1;
offset -= dm;
}
else
{
} else {
break;
}
}
lunar->IsLeap = 0;
if (leap != 0 && lunarM > leap)
{
if (lunarM == leap + 1)
{
if (leap != 0 && lunarM > leap) {
if (lunarM == leap + 1) {
lunar->IsLeap = 1;
}
lunarM -= 1;
@@ -163,20 +139,11 @@ void LUNAR_SolarToLunar(struct Lunar_Date *lunar, uint16_t solar_year, uint8_t s
lunar->Year = lunarY;
}
uint8_t LUNAR_GetZodiac(const struct Lunar_Date *lunar)
{
return lunar->Year % 12;
}
uint8_t LUNAR_GetZodiac(const struct Lunar_Date* lunar) { return lunar->Year % 12; }
uint8_t LUNAR_GetStem(const struct Lunar_Date *lunar)
{
return lunar->Year % 10;
}
uint8_t LUNAR_GetStem(const struct Lunar_Date* lunar) { return lunar->Year % 10; }
uint8_t LUNAR_GetBranch(const struct Lunar_Date *lunar)
{
return lunar->Year % 12;
}
uint8_t LUNAR_GetBranch(const struct Lunar_Date* lunar) { return lunar->Year % 12; }
/*********************************************************************************************************
** 以下为24节气计算相关程序
@@ -188,8 +155,7 @@ uint8_t LUNAR_GetBranch(const struct Lunar_Date *lunar)
有兴趣的朋友可按照上面给的原理添加其它年份的表格
不是很清楚的朋友可给我发EMAIL
*/
static const uint8_t YearMonthBit[160] =
{
static const uint8_t YearMonthBit[160] = {
0x4E, 0xA6, 0x99, // 2000
0x9C, 0xA2, 0x98, // 2001
0x80, 0x00, 0x18, // 2002
@@ -246,8 +212,7 @@ static const uint8_t YearMonthBit[160] =
0xFC, 0xEF, 0xD9, // 2049
0xBE, 0xA6, 0x18, // 2050
};
static const uint8_t days[24] =
{
static const uint8_t days[24] = {
6, 20, 4, 19, 6, 21, // 一月到三月 的节气基本日期
5, 20, 6, 21, 6, 21, // 四月到六月 的节气基本日期
7, 23, 8, 23, 8, 23, // 七月到九月 的节气基本日期
@@ -257,44 +222,11 @@ static const uint8_t days[24] =
*
*/
const char JieQiStr[24][7] = {
"小寒",
"大寒",
"立春",
"雨水",
"惊蛰",
"春分",
"清明",
"谷雨",
"立夏",
"小满",
"芒种",
"夏至",
"小暑",
"大暑",
"立秋",
"处暑",
"白露",
"秋分",
"寒露",
"霜降",
"立冬",
"小雪",
"大雪",
"冬至",
"小寒", "大寒", "立春", "雨水", "惊蛰", "春分", "清明", "谷雨", "立夏", "小满", "芒种", "夏至",
"小暑", "大暑", "立秋", "处暑", "白露", "秋分", "寒露", "霜降", "立冬", "小雪", "大雪", "冬至",
};
const uint8_t MonthDayMax[12] = {
31,
28,
31,
30,
31,
30,
31,
31,
30,
31,
30,
31,
31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31,
};
/*********************************************************************************************************
@@ -314,24 +246,19 @@ const uint8_t MonthDayMax[12] = {
** 日 期:
**------------------------------------------------------------------------------------------------------
********************************************************************************************************/
uint8_t GetJieQi(uint16_t myear, uint8_t mmonth, uint8_t mday, uint8_t *JQdate)
{
uint8_t GetJieQi(uint16_t myear, uint8_t mmonth, uint8_t mday, uint8_t* JQdate) {
uint8_t bak1, value, JQ;
if ((myear < 2000) || (myear > 2050))
return 0;
if ((mmonth == 0) || (mmonth > 12))
return 0;
if ((myear < 2000) || (myear > 2050)) return 0;
if ((mmonth == 0) || (mmonth > 12)) return 0;
JQ = (mmonth - 1) * 2; // 获得节气顺序标号(023
if (mday >= 15)
JQ++; // 判断是否是上半月
if (mday >= 15) JQ++; // 判断是否是上半月
bak1 = YearMonthBit[(myear - 2000) * 3 + JQ / 8]; // 获得节气日期相对值所在字节
value = ((bak1 << (JQ % 8)) & 0x80); // 获得节气日期相对值状态
*JQdate = days[JQ];
if (value != 0)
{
if (value != 0) {
// 判断年份,以决定节气相对值1代表1,还是1。
if ((JQ == 1 || JQ == 11 || JQ == 18 || JQ == 21) && myear < 2044)
(*JQdate)++;
@@ -357,17 +284,14 @@ uint8_t GetJieQi(uint16_t myear, uint8_t mmonth, uint8_t mday, uint8_t *JQdate)
** 日 期:
**------------------------------------------------------------------------------------------------------
********************************************************************************************************/
uint8_t GetJieQiStr(uint16_t myear, uint8_t mmonth, uint8_t mday, uint8_t *day)
{
uint8_t GetJieQiStr(uint16_t myear, uint8_t mmonth, uint8_t mday, uint8_t* day) {
uint8_t JQdate, JQ, MaxDay;
if (GetJieQi(myear, mmonth, mday, &JQdate) == 0)
return 0xFF;
if (GetJieQi(myear, mmonth, mday, &JQdate) == 0) return 0xFF;
JQ = (mmonth - 1) * 2; // 获得节气顺序标号(023
if (mday >= 15)
JQ++; // 判断是否是上半月
if (mday >= 15) JQ++; // 判断是否是上半月
if (mday == JQdate) // 今天正是一个节气日
{
@@ -379,28 +303,22 @@ uint8_t GetJieQiStr(uint16_t myear, uint8_t mmonth, uint8_t mday, uint8_t *day)
if (mday < JQdate) // 如果今天日期小于本月的节气日期
{
mday = JQdate - mday;
}
else // 如果今天日期大于本月的节气日期
} else // 如果今天日期大于本月的节气日期
{
JQ++;
if (mday < 15)
{
if (mday < 15) {
GetJieQi(myear, mmonth, 15, &JQdate);
mday = JQdate - mday;
}
else // 翻月
} else // 翻月
{
MaxDay = MonthDayMax[mmonth - 1];
if (mmonth == 2) // 润月问题
{
if ((myear % 4 == 0) && ((myear % 100 != 0) || (myear % 400 == 0)))
MaxDay++;
if ((myear % 4 == 0) && ((myear % 100 != 0) || (myear % 400 == 0))) MaxDay++;
}
if (++mmonth == 13)
mmonth = 1;
if (++mmonth == 13) mmonth = 1;
GetJieQi(myear, mmonth, 1, &JQdate);
mday = MaxDay - mday + JQdate;
}
@@ -411,10 +329,8 @@ uint8_t GetJieQiStr(uint16_t myear, uint8_t mmonth, uint8_t mday, uint8_t *day)
uint32_t SEC_PER_YR[2] = {31536000, 31622400}; // 闰年和非闰年的秒数
uint32_t SEC_PER_MT[2][12] = {
{2678400, 2419200, 2678400, 2592000, 2678400, 2592000,
2678400, 2678400, 2592000, 2678400, 2592000, 2678400},
{2678400, 2505600, 2678400, 2592000, 2678400, 2592000,
2678400, 2678400, 2592000, 2678400, 2592000, 2678400},
{2678400, 2419200, 2678400, 2592000, 2678400, 2592000, 2678400, 2678400, 2592000, 2678400, 2592000, 2678400},
{2678400, 2505600, 2678400, 2592000, 2678400, 2592000, 2678400, 2678400, 2592000, 2678400, 2592000, 2678400},
};
#define SECOND_OF_DAY 86400 // 一天多少秒
@@ -427,8 +343,7 @@ uint32_t SEC_PER_MT[2][12] = {
* @Out : 1是闰年 0非闰年
* @Author : Denis
*/
int is_leap(int yr)
{
int is_leap(int yr) {
if (0 == (yr % 100))
return (yr % 400 == 0) ? 1 : 0;
else
@@ -443,27 +358,22 @@ int is_leap(int yr)
* @Out : 星期几
* @Author : Denis
*/
unsigned char day_of_week_get(unsigned char month, unsigned char day,
unsigned short year)
{
unsigned char day_of_week_get(unsigned char month, unsigned char day, unsigned short year) {
/* Month should be a number 0 to 11, Day should be a number 1 to 31 */
static int t[] = {0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4};
year -= (uint8_t)(month < 3);
return (year + year / 4 - year / 100 + year / 400 + t[month - 1] + day) % 7;
}
void transformTime(uint32_t unix_time, struct devtm *result)
{
void transformTime(uint32_t unix_time, struct devtm* result) {
int leapyr = 0;
uint32_t ltime = unix_time;
memset(result, 0, sizeof(struct devtm));
result->tm_year = EPOCH_YR;
while (1)
{
if (ltime < SEC_PER_YR[is_leap(result->tm_year)])
{
while (1) {
if (ltime < SEC_PER_YR[is_leap(result->tm_year)]) {
break;
}
ltime -= SEC_PER_YR[is_leap(result->tm_year)];
@@ -472,10 +382,8 @@ void transformTime(uint32_t unix_time, struct devtm *result)
leapyr = is_leap(result->tm_year);
while (1)
{
if (ltime < SEC_PER_MT[leapyr][result->tm_mon])
break;
while (1) {
if (ltime < SEC_PER_MT[leapyr][result->tm_mon]) break;
ltime -= SEC_PER_MT[leapyr][result->tm_mon];
++(result->tm_mon);
}
@@ -490,9 +398,7 @@ void transformTime(uint32_t unix_time, struct devtm *result)
result->tm_min = ltime / 60;
result->tm_sec = ltime % 60;
result->tm_wday =
day_of_week_get(result->tm_mon + 1, result->tm_mday,
result->tm_year);
result->tm_wday = day_of_week_get(result->tm_mon + 1, result->tm_mday, result->tm_year);
/*
* The number of years since YEAR0"
@@ -505,10 +411,8 @@ uint8_t map[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
/*
获取一个月最后一天值
*/
uint8_t get_last_day(uint16_t year, uint8_t month)
{
if (month % 12 == 1)
{
uint8_t get_last_day(uint16_t year, uint8_t month) {
if (month % 12 == 1) {
return map[month % 12] + is_leap(year);
}
return map[month % 12];
@@ -517,32 +421,26 @@ uint8_t get_last_day(uint16_t year, uint8_t month)
/*
获取一个月第一天星期值
*/
uint8_t get_first_day_week(uint16_t year, uint8_t month)
{
return day_of_week_get(month, 1, year);
}
uint8_t get_first_day_week(uint16_t year, uint8_t month) { return day_of_week_get(month, 1, year); }
// 时间结构体转时间戳
uint32_t transformTimeStruct(struct devtm *result)
{
uint32_t transformTimeStruct(struct devtm* result) {
uint32_t Cyear = 0;
for (uint16_t i = 1970; i < result->tm_year; i++)
{
if (is_leap(i) == 1)
Cyear++;
for (uint16_t i = 1970; i < result->tm_year; i++) {
if (is_leap(i) == 1) Cyear++;
}
uint32_t CountDay = Cyear * (uint32_t)366 + (uint32_t)(result->tm_year - 1970 - Cyear) * (uint32_t)365 + result->tm_mday - 1;
for (uint8_t i = 0; i < result->tm_mon - 1; i++)
{
uint32_t CountDay =
Cyear * (uint32_t)366 + (uint32_t)(result->tm_year - 1970 - Cyear) * (uint32_t)365 + result->tm_mday - 1;
for (uint8_t i = 0; i < result->tm_mon - 1; i++) {
CountDay += get_last_day(result->tm_year, i);
}
return (CountDay * SECOND_OF_DAY + (uint32_t)result->tm_sec + (uint32_t)result->tm_min * 60 + (uint32_t)result->tm_hour * 3600);
return (CountDay * SECOND_OF_DAY + (uint32_t)result->tm_sec + (uint32_t)result->tm_min * 60 +
(uint32_t)result->tm_hour * 3600);
}
uint8_t thisMonthMaxDays(uint8_t year, uint8_t month)
{
uint8_t thisMonthMaxDays(uint8_t year, uint8_t month) {
if (year % 4 == 0 && month == 2)
return MonthDayMax[month - 1] + 1;
else

View File

@@ -8,8 +8,7 @@
#define SEC_PER_DY (86400) // 一天的秒数
#define SEC_PER_HR (3600) // 一小时的秒数
typedef struct devtm
{
typedef struct devtm {
uint16_t tm_year;
uint8_t tm_mon;
uint8_t tm_mday;
@@ -19,8 +18,7 @@ typedef struct devtm
uint8_t tm_wday;
} tm_t;
struct Lunar_Date
{
struct Lunar_Date {
uint8_t IsLeap;
uint8_t Date;
uint8_t Month;

View File

@@ -1,5 +1,4 @@
/*
U8g2_for_Adafruit_GFX.cpp
Add unicode support and U8g2 fonts to Adafruit GFX libraries.
@@ -35,18 +34,17 @@
*/
#include <stddef.h>
#include "u8g2_font.h"
static uint8_t u8g2_font_get_byte(const uint8_t *font, uint8_t offset)
{
#include <stddef.h>
static uint8_t u8g2_font_get_byte(const uint8_t* font, uint8_t offset) {
font += offset;
return u8x8_pgm_read(font);
}
static uint16_t u8g2_font_get_word(const uint8_t* font, uint8_t offset) U8X8_NOINLINE;
static uint16_t u8g2_font_get_word(const uint8_t *font, uint8_t offset)
{
static uint16_t u8g2_font_get_word(const uint8_t* font, uint8_t offset) {
uint16_t pos;
font += offset;
pos = u8x8_pgm_read(font);
@@ -58,8 +56,7 @@ static uint16_t u8g2_font_get_word(const uint8_t *font, uint8_t offset)
/*========================================================================*/
/* new font format */
void u8g2_read_font_info(u8g2_font_info_t *font_info, const uint8_t *font)
{
void u8g2_read_font_info(u8g2_font_info_t* font_info, const uint8_t* font) {
/* offset 0 */
font_info->glyph_cnt = u8g2_font_get_byte(font, 0);
font_info->bbx_mode = u8g2_font_get_byte(font, 1);
@@ -93,34 +90,20 @@ void u8g2_read_font_info(u8g2_font_info_t *font_info, const uint8_t *font)
font_info->start_pos_unicode = u8g2_font_get_word(font, 21);
}
uint8_t u8g2_GetFontBBXWidth(u8g2_font_t *u8g2)
{
return u8g2->font_info.max_char_width; /* new font info structure */
}
uint8_t u8g2_GetFontBBXWidth(u8g2_font_t* u8g2) { return u8g2->font_info.max_char_width; /* new font info structure */ }
uint8_t u8g2_GetFontBBXHeight(u8g2_font_t *u8g2)
{
uint8_t u8g2_GetFontBBXHeight(u8g2_font_t* u8g2) {
return u8g2->font_info.max_char_height; /* new font info structure */
}
int8_t u8g2_GetFontBBXOffX(u8g2_font_t *u8g2)
{
return u8g2->font_info.x_offset; /* new font info structure */
}
int8_t u8g2_GetFontBBXOffX(u8g2_font_t* u8g2) { return u8g2->font_info.x_offset; /* new font info structure */ }
int8_t u8g2_GetFontBBXOffY(u8g2_font_t *u8g2)
{
return u8g2->font_info.y_offset; /* new font info structure */
}
int8_t u8g2_GetFontBBXOffY(u8g2_font_t* u8g2) { return u8g2->font_info.y_offset; /* new font info structure */ }
uint8_t u8g2_GetFontCapitalAHeight(u8g2_font_t *u8g2)
{
return u8g2->font_info.ascent_A; /* new font info structure */
}
uint8_t u8g2_GetFontCapitalAHeight(u8g2_font_t* u8g2) { return u8g2->font_info.ascent_A; /* new font info structure */ }
static uint8_t u8g2_font_decode_get_unsigned_bits(u8g2_font_decode_t* f, uint8_t cnt) U8X8_NOINLINE;
static uint8_t u8g2_font_decode_get_unsigned_bits(u8g2_font_decode_t *f, uint8_t cnt)
{
static uint8_t u8g2_font_decode_get_unsigned_bits(u8g2_font_decode_t* f, uint8_t cnt) {
uint8_t val;
uint8_t bit_pos = f->decode_bit_pos;
uint8_t bit_pos_plus_cnt;
@@ -131,8 +114,7 @@ static uint8_t u8g2_font_decode_get_unsigned_bits(u8g2_font_decode_t *f, uint8_t
val >>= bit_pos;
bit_pos_plus_cnt = bit_pos;
bit_pos_plus_cnt += cnt;
if ( bit_pos_plus_cnt >= 8 )
{
if (bit_pos_plus_cnt >= 8) {
uint8_t s = 8;
s -= bit_pos;
f->decode_ptr++;
@@ -148,7 +130,6 @@ static uint8_t u8g2_font_decode_get_unsigned_bits(u8g2_font_decode_t *f, uint8_t
return val;
}
/*
2 bit --> cnt = 2
-2,-1,0. 1
@@ -165,8 +146,7 @@ static uint8_t u8g2_font_decode_get_unsigned_bits(u8g2_font_decode_t *f, uint8_t
*/
/* optimized */
static int8_t u8g2_font_decode_get_signed_bits(u8g2_font_decode_t* f, uint8_t cnt) U8X8_NOINLINE;
static int8_t u8g2_font_decode_get_signed_bits(u8g2_font_decode_t *f, uint8_t cnt)
{
static int8_t u8g2_font_decode_get_signed_bits(u8g2_font_decode_t* f, uint8_t cnt) {
int8_t v, d;
v = (int8_t)u8g2_font_decode_get_unsigned_bits(f, cnt);
d = 1;
@@ -177,12 +157,9 @@ static int8_t u8g2_font_decode_get_signed_bits(u8g2_font_decode_t *f, uint8_t cn
// return (int8_t)u8g2_font_decode_get_unsigned_bits(f, cnt) - ((1<<cnt)>>1);
}
static int16_t u8g2_add_vector_y(int16_t dy, int8_t x, int8_t y, uint8_t dir) U8X8_NOINLINE;
static int16_t u8g2_add_vector_y(int16_t dy, int8_t x, int8_t y, uint8_t dir)
{
switch(dir)
{
static int16_t u8g2_add_vector_y(int16_t dy, int8_t x, int8_t y, uint8_t dir) {
switch (dir) {
case 0:
dy += y;
break;
@@ -200,10 +177,8 @@ static int16_t u8g2_add_vector_y(int16_t dy, int8_t x, int8_t y, uint8_t dir)
}
static int16_t u8g2_add_vector_x(int16_t dx, int8_t x, int8_t y, uint8_t dir) U8X8_NOINLINE;
static int16_t u8g2_add_vector_x(int16_t dx, int8_t x, int8_t y, uint8_t dir)
{
switch(dir)
{
static int16_t u8g2_add_vector_x(int16_t dx, int8_t x, int8_t y, uint8_t dir) {
switch (dir) {
case 0:
dx += x;
break;
@@ -238,8 +213,7 @@ static int16_t u8g2_add_vector_x(int16_t dx, int8_t x, int8_t y, uint8_t dir)
u8g2_font_decode_glyph()
*/
/* optimized */
static void u8g2_font_decode_len(u8g2_font_t *u8g2, uint8_t len, uint8_t is_foreground)
{
static void u8g2_font_decode_len(u8g2_font_t* u8g2, uint8_t len, uint8_t is_foreground) {
uint8_t cnt; /* total number of remaining pixels, which have to be drawn */
uint8_t rem; /* remaining pixel to the right edge of the glyph */
uint8_t current; /* number of pixels, which need to be drawn for the draw procedure */
@@ -259,8 +233,7 @@ static void u8g2_font_decode_len(u8g2_font_t *u8g2, uint8_t len, uint8_t is_fore
lx = decode->x;
ly = decode->y;
for(;;)
{
for (;;) {
/* calculate the number of pixel to the right edge of the glyph */
rem = decode->glyph_width;
rem -= lx;
@@ -268,9 +241,7 @@ static void u8g2_font_decode_len(u8g2_font_t *u8g2, uint8_t len, uint8_t is_fore
/* calculate how many pixel to draw. This is either to the right edge */
/* or lesser, if not enough pixel are left */
current = rem;
if ( cnt < rem )
current = cnt;
if (cnt < rem) current = cnt;
/* now draw the line, but apply the rotation around the glyph target position */
// u8g2_font_decode_draw_pixel(u8g2, lx,ly,current, is_foreground);
@@ -286,19 +257,15 @@ static void u8g2_font_decode_len(u8g2_font_t *u8g2, uint8_t len, uint8_t is_fore
/* draw foreground and background (if required) */
if (current > 0) /* avoid drawing zero length lines, issue #4 */
{
if ( is_foreground )
{
if (is_foreground) {
u8g2->draw_hv_line(u8g2, x, y, current, decode->dir, decode->fg_color);
}
else if ( decode->is_transparent == 0 )
{
} else if (decode->is_transparent == 0) {
u8g2->draw_hv_line(u8g2, x, y, current, decode->dir, decode->bg_color);
}
}
/* check, whether the end of the run length code has been reached */
if ( cnt < rem )
break;
if (cnt < rem) break;
cnt -= rem;
lx = 0;
ly++;
@@ -307,11 +274,9 @@ static void u8g2_font_decode_len(u8g2_font_t *u8g2, uint8_t len, uint8_t is_fore
decode->x = lx;
decode->y = ly;
}
static void u8g2_font_setup_decode(u8g2_font_t *u8g2, const uint8_t *glyph_data)
{
static void u8g2_font_setup_decode(u8g2_font_t* u8g2, const uint8_t* glyph_data) {
u8g2_font_decode_t* decode = &(u8g2->font_decode);
decode->decode_ptr = glyph_data;
decode->decode_bit_pos = 0;
@@ -324,10 +289,8 @@ static void u8g2_font_setup_decode(u8g2_font_t *u8g2, const uint8_t *glyph_data)
decode->glyph_width = u8g2_font_decode_get_unsigned_bits(decode, u8g2->font_info.bits_per_char_width);
decode->glyph_height = u8g2_font_decode_get_unsigned_bits(decode, u8g2->font_info.bits_per_char_height);
}
/*
Description:
Decode and draw a glyph.
@@ -342,8 +305,7 @@ static void u8g2_font_setup_decode(u8g2_font_t *u8g2, const uint8_t *glyph_data)
u8g2_font_decode_len()
*/
/* optimized */
static int8_t u8g2_font_decode_glyph(u8g2_font_t *u8g2, const uint8_t *glyph_data)
{
static int8_t u8g2_font_decode_glyph(u8g2_font_t* u8g2, const uint8_t* glyph_data) {
uint8_t a, b;
int8_t x, y;
int8_t d;
@@ -357,33 +319,26 @@ static int8_t u8g2_font_decode_glyph(u8g2_font_t *u8g2, const uint8_t *glyph_dat
y = u8g2_font_decode_get_signed_bits(decode, u8g2->font_info.bits_per_char_y);
d = u8g2_font_decode_get_signed_bits(decode, u8g2->font_info.bits_per_delta_x);
if ( decode->glyph_width > 0 )
{
if (decode->glyph_width > 0) {
decode->target_x = u8g2_add_vector_x(decode->target_x, x, -(h + y), decode->dir);
decode->target_y = u8g2_add_vector_y(decode->target_y, x, -(h + y), decode->dir);
// u8g2_add_vector(&(decode->target_x), &(decode->target_y), x, -(h+y), decode->dir);
/* reset local x/y position */
decode->x = 0;
decode->y = 0;
/* decode glyph */
for(;;)
{
for (;;) {
a = u8g2_font_decode_get_unsigned_bits(decode, u8g2->font_info.bits_per_0);
b = u8g2_font_decode_get_unsigned_bits(decode, u8g2->font_info.bits_per_1);
do
{
do {
u8g2_font_decode_len(u8g2, a, 0);
u8g2_font_decode_len(u8g2, b, 1);
} while (u8g2_font_decode_get_unsigned_bits(decode, 1) != 0);
if ( decode->y >= h )
break;
if (decode->y >= h) break;
}
}
return d;
}
@@ -396,36 +351,25 @@ static int8_t u8g2_font_decode_glyph(u8g2_font_t *u8g2, const uint8_t *glyph_dat
Return:
Address of the glyph data or NULL, if the encoding is not avialable in the font.
*/
const uint8_t *u8g2_font_get_glyph_data(u8g2_font_t *u8g2, uint16_t encoding)
{
const uint8_t* u8g2_font_get_glyph_data(u8g2_font_t* u8g2, uint16_t encoding) {
const uint8_t* font = u8g2->font;
font += 23;
if ( encoding <= 255 )
{
if ( encoding >= 'a' )
{
if (encoding <= 255) {
if (encoding >= 'a') {
font += u8g2->font_info.start_pos_lower_a;
}
else if ( encoding >= 'A' )
{
} else if (encoding >= 'A') {
font += u8g2->font_info.start_pos_upper_A;
}
for(;;)
{
if ( u8x8_pgm_read( font + 1 ) == 0 )
break;
if ( u8x8_pgm_read( font ) == encoding )
{
for (;;) {
if (u8x8_pgm_read(font + 1) == 0) break;
if (u8x8_pgm_read(font) == encoding) {
return font + 2; /* skip encoding and glyph size */
}
font += u8x8_pgm_read(font + 1);
}
}
else
{
} else {
uint16_t e;
const uint8_t* unicode_lookup_table;
/* support for the new unicode lookup table */
@@ -434,8 +378,7 @@ const uint8_t *u8g2_font_get_glyph_data(u8g2_font_t *u8g2, uint16_t encoding)
unicode_lookup_table = font;
/* u8g2 issue 596: search for the glyph start in the unicode lookup table */
do
{
do {
font += u8g2_font_get_word(unicode_lookup_table, 0);
e = u8g2_font_get_word(unicode_lookup_table, 2);
unicode_lookup_table += 4;
@@ -443,15 +386,12 @@ const uint8_t *u8g2_font_get_glyph_data(u8g2_font_t *u8g2, uint16_t encoding)
/* variable "font" is now updated according to the lookup table */
for(;;)
{
for (;;) {
e = u8x8_pgm_read(font);
e <<= 8;
e |= u8x8_pgm_read(font + 1);
if ( e == 0 )
break;
if ( e == encoding )
{
if (e == 0) break;
if (e == encoding) {
return font + 3; /* skip encoding and glyph size */
}
font += u8x8_pgm_read(font + 2);
@@ -460,39 +400,32 @@ const uint8_t *u8g2_font_get_glyph_data(u8g2_font_t *u8g2, uint16_t encoding)
return NULL;
}
static int16_t u8g2_font_draw_glyph(u8g2_font_t *u8g2, int16_t x, int16_t y, uint16_t encoding)
{
static int16_t u8g2_font_draw_glyph(u8g2_font_t* u8g2, int16_t x, int16_t y, uint16_t encoding) {
int16_t dx = 0;
u8g2->font_decode.target_x = x;
u8g2->font_decode.target_y = y;
// u8g2->font_decode.is_transparent = is_transparent; this is already set
// u8g2->font_decode.dir = dir;
const uint8_t* glyph_data = u8g2_font_get_glyph_data(u8g2, encoding);
if ( glyph_data != NULL )
{
if (glyph_data != NULL) {
dx = u8g2_font_decode_glyph(u8g2, glyph_data);
}
return dx;
}
//========================================================
uint8_t u8g2_IsGlyph(u8g2_font_t *u8g2, uint16_t requested_encoding)
{
uint8_t u8g2_IsGlyph(u8g2_font_t* u8g2, uint16_t requested_encoding) {
/* updated to new code */
if ( u8g2_font_get_glyph_data(u8g2, requested_encoding) != NULL )
return 1;
if (u8g2_font_get_glyph_data(u8g2, requested_encoding) != NULL) return 1;
return 0;
}
/* side effect: updates u8g2->font_decode and u8g2->glyph_x_offset */
/* actually u8g2_GetGlyphWidth returns the glyph delta x and glyph width itself is set as side effect */
int8_t u8g2_GetGlyphWidth(u8g2_font_t *u8g2, uint16_t requested_encoding)
{
int8_t u8g2_GetGlyphWidth(u8g2_font_t* u8g2, uint16_t requested_encoding) {
const uint8_t* glyph_data = u8g2_font_get_glyph_data(u8g2, requested_encoding);
if ( glyph_data == NULL )
return 0;
if (glyph_data == NULL) return 0;
u8g2_font_setup_decode(u8g2, glyph_data);
u8g2->glyph_x_offset = u8g2_font_decode_get_signed_bits(&(u8g2->font_decode), u8g2->font_info.bits_per_char_x);
@@ -502,34 +435,23 @@ int8_t u8g2_GetGlyphWidth(u8g2_font_t *u8g2, uint16_t requested_encoding)
return u8g2_font_decode_get_signed_bits(&(u8g2->font_decode), u8g2->font_info.bits_per_delta_x);
}
void u8g2_SetFontMode(u8g2_font_t *u8g2, uint8_t is_transparent)
{
void u8g2_SetFontMode(u8g2_font_t* u8g2, uint8_t is_transparent) {
u8g2->font_decode.is_transparent = is_transparent; // new font procedures
}
void u8g2_SetFontDirection(u8g2_font_t *u8g2, uint8_t dir)
{
u8g2->font_decode.dir = dir;
}
void u8g2_SetFontDirection(u8g2_font_t* u8g2, uint8_t dir) { u8g2->font_decode.dir = dir; }
int16_t u8g2_DrawGlyph(u8g2_font_t *u8g2, int16_t x, int16_t y, uint16_t encoding)
{
int16_t u8g2_DrawGlyph(u8g2_font_t* u8g2, int16_t x, int16_t y, uint16_t encoding) {
return u8g2_font_draw_glyph(u8g2, x, y, encoding);
}
int16_t u8g2_DrawStr(u8g2_font_t *u8g2, int16_t x, int16_t y, const char *s)
{
int16_t u8g2_DrawStr(u8g2_font_t* u8g2, int16_t x, int16_t y, const char* s) {
int16_t sum, delta;
sum = 0;
while( *s != '\0' )
{
while (*s != '\0') {
delta = u8g2_DrawGlyph(u8g2, x, y, *s);
switch(u8g2->font_decode.dir)
{
switch (u8g2->font_decode.dir) {
case 0:
x += delta;
break;
@@ -549,12 +471,8 @@ int16_t u8g2_DrawStr(u8g2_font_t *u8g2, int16_t x, int16_t y, const char *s)
return sum;
}
void u8g2_SetFont(u8g2_font_t *u8g2, const uint8_t *font)
{
if ( u8g2->font != font )
{
void u8g2_SetFont(u8g2_font_t* u8g2, const uint8_t* font) {
if (u8g2->font != font) {
u8g2->font = font;
u8g2->font_decode.is_transparent = 0;
@@ -562,12 +480,6 @@ void u8g2_SetFont(u8g2_font_t *u8g2, const uint8_t *font)
}
}
void u8g2_SetForegroundColor(u8g2_font_t *u8g2, uint16_t fg)
{
u8g2->font_decode.fg_color = fg;
}
void u8g2_SetForegroundColor(u8g2_font_t* u8g2, uint16_t fg) { u8g2->font_decode.fg_color = fg; }
void u8g2_SetBackgroundColor(u8g2_font_t *u8g2, uint16_t bg)
{
u8g2->font_decode.bg_color = bg;
}
void u8g2_SetBackgroundColor(u8g2_font_t* u8g2, uint16_t bg) { u8g2->font_decode.bg_color = bg; }

View File

@@ -1,5 +1,4 @@
/*
U8g2_for_Adafruit_GFX.h
Add unicode support and U8g2 fonts to Adafruit GFX libraries.
@@ -77,8 +76,7 @@
#endif
#endif
typedef struct _u8g2_font_info_t
{
typedef struct _u8g2_font_info_t {
/* offset 0 */
uint8_t glyph_cnt;
uint8_t bbx_mode;
@@ -112,8 +110,7 @@ typedef struct _u8g2_font_info_t
uint16_t start_pos_unicode;
} u8g2_font_info_t;
typedef struct _u8g2_font_decode_t
{
typedef struct _u8g2_font_decode_t {
const uint8_t* decode_ptr; /* pointer to the compressed data */
int16_t target_x;
@@ -131,8 +128,7 @@ typedef struct _u8g2_font_decode_t
uint8_t dir; /* direction */
} u8g2_font_decode_t;
typedef struct _u8g2_font_t
{
typedef struct _u8g2_font_t {
const uint8_t* font; /* current font for all text procedures */
u8g2_font_decode_t font_decode; /* new font decode structure */
@@ -140,8 +136,7 @@ typedef struct _u8g2_font_t
int8_t glyph_x_offset; /* set by u8g2_GetGlyphWidth as a side effect */
void (*draw_hv_line)(struct _u8g2_font_t *u8g2, int16_t x, int16_t y,
int16_t len, uint8_t dir, uint16_t color);
void (*draw_hv_line)(struct _u8g2_font_t* u8g2, int16_t x, int16_t y, int16_t len, uint8_t dir, uint16_t color);
} u8g2_font_t;
uint8_t u8g2_IsGlyph(u8g2_font_t* u8g2, uint16_t requested_encoding);

View File

@@ -1,10 +1,11 @@
// GUI emulator for Windows
// This code is a simple Windows GUI application that emulates the display of an e-paper device.
#include <windows.h>
#include <stdint.h>
#include <time.h>
#include <string.h>
#include <time.h>
#include <wchar.h>
#include <windows.h>
#include "GUI.h"
#define BITMAP_WIDTH 400
@@ -117,11 +118,7 @@ void DrawBitmap(void *user_data, uint8_t *black, uint8_t *color, uint16_t x, uin
}
// Draw the bitmap
StretchDIBits(hdc,
drawX + x * scale, drawY + y * scale,
w * scale, h * scale,
0, 0, w, h,
bitmap4bit, &bmi,
StretchDIBits(hdc, drawX + x * scale, drawY + y * scale, w * scale, h * scale, 0, 0, w, h, bitmap4bit, &bmi,
DIB_RGB_COLORS, SRCCOPY);
free(bitmap4bit);
@@ -172,9 +169,7 @@ LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
HPEN oldPen = SelectObject(hdc, borderPen);
HBRUSH oldBrush = SelectObject(hdc, GetStockObject(NULL_BRUSH)); // No fill
Rectangle(hdc, drawX - 1, drawY - 1,
drawX + BITMAP_WIDTH * scale + 1,
drawY + BITMAP_HEIGHT * scale + 1);
Rectangle(hdc, drawX - 1, drawY - 1, drawX + BITMAP_WIDTH * scale + 1, drawY + BITMAP_HEIGHT * scale + 1);
SelectObject(hdc, oldPen);
SelectObject(hdc, oldBrush);
@@ -187,11 +182,8 @@ LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
SetBkMode(hdc, TRANSPARENT);
// Create a font for mode text
HFONT modeFont = CreateFont(
16, 0, 0, 0, FW_BOLD, FALSE, FALSE, FALSE,
DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
DEFAULT_QUALITY, DEFAULT_PITCH | FF_SWISS, "Arial"
);
HFONT modeFont = CreateFont(16, 0, 0, 0, FW_BOLD, FALSE, FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS,
CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_SWISS, "Arial");
HFONT oldFont = SelectObject(hdc, modeFont);
// Calculate text width for centering mode text
@@ -207,11 +199,9 @@ LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
SetTextColor(hdc, RGB(80, 80, 80));
// Create a smaller font for help text
HFONT helpFont = CreateFont(
14, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE,
DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
DEFAULT_QUALITY, DEFAULT_PITCH | FF_SWISS, "Arial"
);
HFONT helpFont =
CreateFont(14, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS,
CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_SWISS, "Arial");
SelectObject(hdc, modeFont);
DeleteObject(modeFont);
SelectObject(hdc, helpFont);
@@ -282,8 +272,7 @@ LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
g_tm_time.tm_mon = 0;
g_tm_time.tm_year++;
}
}
else if (wParam == VK_DOWN) {
} else if (wParam == VK_DOWN) {
g_tm_time.tm_mon--;
if (g_tm_time.tm_mon < 0) {
g_tm_time.tm_mon = 11;
@@ -293,8 +282,7 @@ LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
// Left/Right adjusts day
else if (wParam == VK_RIGHT) {
g_tm_time.tm_mday++;
}
else if (wParam == VK_LEFT) {
} else if (wParam == VK_LEFT) {
g_tm_time.tm_mday--;
}
@@ -335,14 +323,8 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
}
// Create the window
g_hwnd = CreateWindowW(
L"Emurator",
L"模拟器",
WS_POPUPWINDOW | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX,
CW_USEDEFAULT, CW_USEDEFAULT,
WINDOW_WIDTH, WINDOW_HEIGHT,
NULL, NULL, hInstance, NULL
);
g_hwnd = CreateWindowW(L"Emurator", L"模拟器", WS_POPUPWINDOW | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX,
CW_USEDEFAULT, CW_USEDEFAULT, WINDOW_WIDTH, WINDOW_HEIGHT, NULL, NULL, hInstance, NULL);
if (!g_hwnd) {
MessageBoxW(NULL, L"Window Creation Failed!", L"Error", MB_ICONEXCLAMATION | MB_OK);

215
main.c
View File

@@ -12,41 +12,42 @@
#include <stdint.h>
#include <string.h>
#include "nordic_common.h"
#include "nrf.h"
#include "ble.h"
#include "ble_hci.h"
#include "ble_srv_common.h"
#include "ble_advdata.h"
#include "ble_advertising.h"
#include "ble_conn_params.h"
#include "ble_dfu.h"
#include "ble_hci.h"
#include "ble_srv_common.h"
#include "nordic_common.h"
#include "nrf.h"
#if defined(S112)
#include "nrf_sdh.h"
#include "nrf_sdh_soc.h"
#include "nrf_sdh_ble.h"
#include "nrf_ble_gatt.h"
#include "nrf_bootloader_info.h"
#include "nrf_sdh.h"
#include "nrf_sdh_ble.h"
#include "nrf_sdh_soc.h"
#else
#include "fstorage.h"
#include "softdevice_handler.h"
#endif
#include "nrf_power.h"
#include "EPD_service.h"
#include "app_error.h"
#include "app_timer.h"
#include "app_scheduler.h"
#include "app_timer.h"
#include "main.h"
#include "nrf_drv_gpiote.h"
#include "nrf_drv_wdt.h"
#include "nrf_pwr_mgmt.h"
#include "EPD_service.h"
#include "main.h"
#include "nrf_log.h"
#include "nrf_log_ctrl.h"
#include "nrf_power.h"
#include "nrf_pwr_mgmt.h"
#if defined(S112)
#include "nrf_log_default_backends.h"
#endif
// clang-format off
#define CENTRAL_LINK_COUNT 0 /**< Number of central links used by the application. When changing this number remember to adjust the RAM settings*/
#define PERIPHERAL_LINK_COUNT 1 /**< Number of peripheral links used by the application. When changing this number remember to adjust the RAM settings*/
@@ -100,6 +101,7 @@ APP_TIMER_DEF(m_clock_timer_id);
static nrf_drv_wdt_channel_id m_wdt_channel_id;
static uint32_t m_wdt_last_feed_time = 0;
static uint32_t m_resetreas;
// clang-format on
/**@brief Callback function for asserts in the SoftDevice.
*
@@ -112,28 +114,22 @@ static uint32_t m_resetreas;
* @param[in] line_num Line number of the failing ASSERT call.
* @param[in] file_name File name of the failing ASSERT call.
*/
void assert_nrf_callback(uint16_t line_num, const uint8_t * p_file_name)
{
void assert_nrf_callback(uint16_t line_num, const uint8_t* p_file_name) {
app_error_handler(DEAD_BEEF, line_num, p_file_name);
}
// return current timestamp
uint32_t timestamp(void)
{
return m_timestamp;
}
uint32_t timestamp(void) { return m_timestamp; }
// set the timestamp
void set_timestamp(uint32_t timestamp)
{
void set_timestamp(uint32_t timestamp) {
app_timer_stop(m_clock_timer_id);
m_timestamp = timestamp;
app_timer_start(m_clock_timer_id, CLOCK_TIMER_INTERVAL, NULL);
}
// reload the wdt channel
void app_feed_wdt(void)
{
void app_feed_wdt(void) {
if (m_timestamp - m_wdt_last_feed_time >= 30) {
NRF_LOG_DEBUG("Feed WDT\n");
nrf_drv_wdt_channel_feed(m_wdt_channel_id);
@@ -142,10 +138,8 @@ void app_feed_wdt(void)
}
#if defined(S112)
static void buttonless_dfu_sdh_state_observer(nrf_sdh_state_evt_t state, void * p_context)
{
if (state == NRF_SDH_EVT_STATE_DISABLED)
{
static void buttonless_dfu_sdh_state_observer(nrf_sdh_state_evt_t state, void* p_context) {
if (state == NRF_SDH_EVT_STATE_DISABLED) {
// Softdevice was disabled before going into reset. Inform bootloader to skip CRC on next boot.
nrf_power_gpregret2_set(BOOTLOADER_DFU_SKIP_CRC);
@@ -155,13 +149,11 @@ static void buttonless_dfu_sdh_state_observer(nrf_sdh_state_evt_t state, void *
}
/* nrf_sdh state observer. */
NRF_SDH_STATE_OBSERVER(m_buttonless_dfu_state_obs, 0) =
{
NRF_SDH_STATE_OBSERVER(m_buttonless_dfu_state_obs, 0) = {
.handler = buttonless_dfu_sdh_state_observer,
};
static void advertising_config_get(ble_adv_modes_config_t * p_config)
{
static void advertising_config_get(ble_adv_modes_config_t* p_config) {
memset(p_config, 0, sizeof(ble_adv_modes_config_t));
p_config->ble_adv_fast_enabled = true;
@@ -169,12 +161,9 @@ static void advertising_config_get(ble_adv_modes_config_t * p_config)
p_config->ble_adv_fast_timeout = APP_ADV_TIMEOUT_IN_SECONDS * 100;
}
static void ble_dfu_evt_handler(ble_dfu_buttonless_evt_type_t event)
{
switch (event)
{
case BLE_DFU_EVT_BOOTLOADER_ENTER_PREPARE:
{
static void ble_dfu_evt_handler(ble_dfu_buttonless_evt_type_t event) {
switch (event) {
case BLE_DFU_EVT_BOOTLOADER_ENTER_PREPARE: {
NRF_LOG_INFO("Device is preparing to enter bootloader mode.");
// Prevent device from advertising on disconnect.
@@ -210,10 +199,8 @@ static void ble_dfu_evt_handler(ble_dfu_buttonless_evt_type_t event)
}
}
#else
static void ble_dfu_evt_handler(ble_dfu_t * p_dfu, ble_dfu_evt_t * p_evt)
{
switch (p_evt->type)
{
static void ble_dfu_evt_handler(ble_dfu_t* p_dfu, ble_dfu_evt_t* p_evt) {
switch (p_evt->type) {
case BLE_DFU_EVT_INDICATION_DISABLED:
NRF_LOG_INFO("Indication for BLE_DFU is disabled\r\n");
break;
@@ -232,8 +219,7 @@ static void ble_dfu_evt_handler(ble_dfu_t * p_dfu, ble_dfu_evt_t * p_evt)
}
#endif
static void clock_timer_timeout_handler(void * p_context)
{
static void clock_timer_timeout_handler(void* p_context) {
UNUSED_PARAMETER(p_context);
m_timestamp++;
@@ -243,17 +229,13 @@ static void clock_timer_timeout_handler(void * p_context)
/**@brief Function for the Event Scheduler initialization.
*/
static void scheduler_init(void)
{
APP_SCHED_INIT(SCHED_MAX_EVENT_DATA_SIZE, SCHED_QUEUE_SIZE);
}
static void scheduler_init(void) { APP_SCHED_INIT(SCHED_MAX_EVENT_DATA_SIZE, SCHED_QUEUE_SIZE); }
/**@brief Function for the Timer initialization.
*
* @details Initializes the timer module. This creates and starts application timers.
*/
static void timers_init(void)
{
static void timers_init(void) {
// Initialize timer module.
#if defined(S112)
APP_ERROR_CHECK(app_timer_init());
@@ -261,15 +243,12 @@ static void timers_init(void)
APP_TIMER_INIT(APP_TIMER_PRESCALER, APP_TIMER_OP_QUEUE_SIZE, false);
#endif
// Create timers.
APP_ERROR_CHECK(app_timer_create(&m_clock_timer_id,
APP_TIMER_MODE_REPEATED,
clock_timer_timeout_handler));
APP_ERROR_CHECK(app_timer_create(&m_clock_timer_id, APP_TIMER_MODE_REPEATED, clock_timer_timeout_handler));
}
/**@brief Function for starting application timers.
*/
static void application_timers_start(void)
{
static void application_timers_start(void) {
// Start application timers.
APP_ERROR_CHECK(app_timer_start(m_clock_timer_id, CLOCK_TIMER_INTERVAL, NULL));
}
@@ -278,8 +257,7 @@ static void application_timers_start(void)
*
* @note This function will not return.
*/
void sleep_mode_enter(void)
{
void sleep_mode_enter(void) {
NRF_LOG_DEBUG("Entering deep sleep mode\n");
NRF_LOG_FINAL_FLUSH();
nrf_delay_ms(100);
@@ -290,8 +268,7 @@ void sleep_mode_enter(void)
/**@brief Function for initializing services that will be used by the application.
*/
static void services_init(void)
{
static void services_init(void) {
// Initialize EPD Service.
memset(&m_epd, 0, sizeof(ble_epd_t));
APP_ERROR_CHECK(ble_epd_init(&m_epd));
@@ -316,8 +293,7 @@ static void services_init(void)
* @details This function will set up all the necessary GAP (Generic Access Profile) parameters of
* the device. It also sets the permissions and appearance.
*/
static void gap_params_init(void)
{
static void gap_params_init(void) {
char device_name[20];
ble_gap_addr_t addr;
ble_gap_conn_params_t gap_conn_params;
@@ -330,14 +306,11 @@ static void gap_params_init(void)
APP_ERROR_CHECK(sd_ble_gap_address_get(&addr));
#endif
NRF_LOG_INFO("Bluetooth MAC Address: %02X:%02X:%02X:%02X:%02X:%02X\n",
addr.addr[5], addr.addr[4], addr.addr[3],
NRF_LOG_INFO("Bluetooth MAC Address: %02X:%02X:%02X:%02X:%02X:%02X\n", addr.addr[5], addr.addr[4], addr.addr[3],
addr.addr[2], addr.addr[1], addr.addr[0]);
snprintf(device_name, 20, "%s_%02X%02X", DEVICE_NAME, addr.addr[1], addr.addr[0]);
APP_ERROR_CHECK(sd_ble_gap_device_name_set(&sec_mode,
(const uint8_t *)device_name,
strlen(device_name)));
APP_ERROR_CHECK(sd_ble_gap_device_name_set(&sec_mode, (const uint8_t*)device_name, strlen(device_name)));
memset(&gap_conn_params, 0, sizeof(gap_conn_params));
@@ -360,29 +333,21 @@ static void gap_params_init(void)
*
* @param[in] p_evt Event received from the Connection Parameters Module.
*/
static void on_conn_params_evt(ble_conn_params_evt_t * p_evt)
{
if (p_evt->evt_type == BLE_CONN_PARAMS_EVT_FAILED)
{
static void on_conn_params_evt(ble_conn_params_evt_t* p_evt) {
if (p_evt->evt_type == BLE_CONN_PARAMS_EVT_FAILED) {
APP_ERROR_CHECK(sd_ble_gap_disconnect(m_conn_handle, BLE_HCI_CONN_INTERVAL_UNACCEPTABLE));
}
}
/**@brief Function for handling errors from the Connection Parameters module.
*
* @param[in] nrf_error Error code containing information about what went wrong.
*/
static void conn_params_error_handler(uint32_t nrf_error)
{
APP_ERROR_HANDLER(nrf_error);
}
static void conn_params_error_handler(uint32_t nrf_error) { APP_ERROR_HANDLER(nrf_error); }
/**@brief Function for initializing the Connection Parameters module.
*/
static void conn_params_init(void)
{
static void conn_params_init(void) {
ble_conn_params_init_t cp_init;
memset(&cp_init, 0, sizeof(cp_init));
@@ -399,9 +364,7 @@ static void conn_params_init(void)
APP_ERROR_CHECK(ble_conn_params_init(&cp_init));
}
static void advertising_start(void)
{
static void advertising_start(void) {
NRF_LOG_INFO("advertising start\n");
#if defined(S112)
APP_ERROR_CHECK(ble_advertising_start(&m_advertising, BLE_ADV_MODE_FAST));
@@ -432,17 +395,14 @@ static void setup_wakeup_pin(nrf_drv_gpiote_pin_t pin) {
nrf_drv_gpiote_in_event_enable(pin, true);
}
/**@brief Function for handling advertising events.
*
* @details This function will be called for advertising events which are passed to the application.
*
* @param[in] ble_adv_evt Advertising event.
*/
static void on_adv_evt(ble_adv_evt_t ble_adv_evt)
{
switch (ble_adv_evt)
{
static void on_adv_evt(ble_adv_evt_t ble_adv_evt) {
switch (ble_adv_evt) {
case BLE_ADV_EVT_FAST:
break;
case BLE_ADV_EVT_IDLE:
@@ -465,10 +425,8 @@ static void on_adv_evt(ble_adv_evt_t ble_adv_evt)
*
* @param[in] p_ble_evt SoftDevice event.
*/
static void on_ble_evt(ble_evt_t * p_ble_evt)
{
switch (p_ble_evt->header.evt_id)
{
static void on_ble_evt(ble_evt_t* p_ble_evt) {
switch (p_ble_evt->header.evt_id) {
case BLE_GAP_EVT_CONNECTED:
NRF_LOG_INFO("CONNECTED\n");
m_conn_handle = p_ble_evt->evt.gap_evt.conn_handle;
@@ -482,11 +440,9 @@ static void on_ble_evt(ble_evt_t * p_ble_evt)
#endif
break;
#if defined(S112)
case BLE_GAP_EVT_PHY_UPDATE_REQUEST:
{
case BLE_GAP_EVT_PHY_UPDATE_REQUEST: {
NRF_LOG_DEBUG("PHY update request.");
ble_gap_phys_t const phys =
{
ble_gap_phys_t const phys = {
.rx_phys = BLE_GAP_PHY_AUTO,
.tx_phys = BLE_GAP_PHY_AUTO,
};
@@ -496,7 +452,8 @@ static void on_ble_evt(ble_evt_t * p_ble_evt)
case BLE_GAP_EVT_SEC_PARAMS_REQUEST:
// Pairing not supported
APP_ERROR_CHECK(sd_ble_gap_sec_params_reply(m_conn_handle, BLE_GAP_SEC_STATUS_PAIRING_NOT_SUPP, NULL, NULL));
APP_ERROR_CHECK(
sd_ble_gap_sec_params_reply(m_conn_handle, BLE_GAP_SEC_STATUS_PAIRING_NOT_SUPP, NULL, NULL));
break;
case BLE_GATTS_EVT_SYS_ATTR_MISSING:
@@ -506,14 +463,14 @@ static void on_ble_evt(ble_evt_t * p_ble_evt)
case BLE_GATTC_EVT_TIMEOUT:
// Disconnect on GATT Client timeout event.
APP_ERROR_CHECK(sd_ble_gap_disconnect(p_ble_evt->evt.gattc_evt.conn_handle,
BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION));
APP_ERROR_CHECK(
sd_ble_gap_disconnect(p_ble_evt->evt.gattc_evt.conn_handle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION));
break;
case BLE_GATTS_EVT_TIMEOUT:
// Disconnect on GATT Server timeout event.
APP_ERROR_CHECK(sd_ble_gap_disconnect(p_ble_evt->evt.gatts_evt.conn_handle,
BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION));
APP_ERROR_CHECK(
sd_ble_gap_disconnect(p_ble_evt->evt.gatts_evt.conn_handle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION));
break;
default:
@@ -522,15 +479,13 @@ static void on_ble_evt(ble_evt_t * p_ble_evt)
}
}
#if defined(S112)
/**@brief Function for handling BLE events.
*
* @param[in] p_ble_evt Bluetooth stack event.
* @param[in] p_context Unused.
*/
static void ble_evt_handler(ble_evt_t const * p_ble_evt, void * p_context)
{
static void ble_evt_handler(ble_evt_t const* p_ble_evt, void* p_context) {
UNUSED_PARAMETER(p_context);
on_ble_evt((ble_evt_t*)p_ble_evt);
@@ -545,8 +500,7 @@ static void ble_evt_handler(ble_evt_t const * p_ble_evt, void * p_context)
*
* @param[in] p_ble_evt SoftDevice event.
*/
static void ble_evt_dispatch(ble_evt_t * p_ble_evt)
{
static void ble_evt_dispatch(ble_evt_t* p_ble_evt) {
ble_conn_params_on_ble_evt(p_ble_evt);
ble_epd_on_ble_evt(&m_epd, p_ble_evt);
on_ble_evt(p_ble_evt);
@@ -554,7 +508,6 @@ static void ble_evt_dispatch(ble_evt_t * p_ble_evt)
ble_dfu_on_ble_evt(&m_dfus, p_ble_evt);
}
/**@brief Function for dispatching a system event to interested modules.
*
* @details This function is called from the System event interrupt handler after a system
@@ -562,8 +515,7 @@ static void ble_evt_dispatch(ble_evt_t * p_ble_evt)
*
* @param[in] sys_evt System stack event.
*/
static void sys_evt_dispatch(uint32_t sys_evt)
{
static void sys_evt_dispatch(uint32_t sys_evt) {
// Dispatch the system event to the fstorage module, where it will be
// dispatched to the Flash Data Storage (FDS) module.
fs_sys_event_handler(sys_evt);
@@ -579,8 +531,7 @@ static void sys_evt_dispatch(uint32_t sys_evt)
*
* @details This function initializes the SoftDevice and the BLE event interrupt.
*/
static void ble_stack_init(void)
{
static void ble_stack_init(void) {
#if defined(S112)
APP_ERROR_CHECK(nrf_sdh_enable_request());
@@ -601,9 +552,8 @@ static void ble_stack_init(void)
SOFTDEVICE_HANDLER_INIT(&clock_lf_cfg, NULL);
ble_enable_params_t ble_enable_params;
APP_ERROR_CHECK(softdevice_enable_get_default_config(CENTRAL_LINK_COUNT,
PERIPHERAL_LINK_COUNT,
&ble_enable_params));
APP_ERROR_CHECK(
softdevice_enable_get_default_config(CENTRAL_LINK_COUNT, PERIPHERAL_LINK_COUNT, &ble_enable_params));
ble_enable_params.common_enable_params.vs_uuid_count = 2;
// Check the ram settings against the used number of links
@@ -622,29 +572,23 @@ static void ble_stack_init(void)
#if defined(S112)
/**@brief Function for handling events from the GATT library. */
void gatt_evt_handler(nrf_ble_gatt_t * p_gatt, nrf_ble_gatt_evt_t const * p_evt)
{
if ((m_conn_handle == p_evt->conn_handle) && (p_evt->evt_id == NRF_BLE_GATT_EVT_ATT_MTU_UPDATED))
{
void gatt_evt_handler(nrf_ble_gatt_t* p_gatt, nrf_ble_gatt_evt_t const* p_evt) {
if ((m_conn_handle == p_evt->conn_handle) && (p_evt->evt_id == NRF_BLE_GATT_EVT_ATT_MTU_UPDATED)) {
m_epd.max_data_len = p_evt->params.att_mtu_effective - 3;
NRF_LOG_INFO("Data len is set to 0x%X(%d)", m_epd.max_data_len, m_epd.max_data_len);
}
NRF_LOG_DEBUG("ATT MTU exchange completed. central 0x%x peripheral 0x%x",
p_gatt->att_mtu_desired_central,
NRF_LOG_DEBUG("ATT MTU exchange completed. central 0x%x peripheral 0x%x", p_gatt->att_mtu_desired_central,
p_gatt->att_mtu_desired_periph);
}
/**@brief Function for initializing the GATT library. */
void gatt_init(void)
{
void gatt_init(void) {
APP_ERROR_CHECK(nrf_ble_gatt_init(&m_gatt, gatt_evt_handler));
APP_ERROR_CHECK(nrf_ble_gatt_att_mtu_periph_set(&m_gatt, NRF_SDH_BLE_GATT_MAX_MTU_SIZE));
}
#else
// Set BW Config to HIGH.
static void ble_options_set(void)
{
static void ble_options_set(void) {
ble_opt_t ble_opt;
memset(&ble_opt, 0, sizeof(ble_opt));
@@ -659,8 +603,7 @@ static void ble_options_set(void)
/**@brief Function for initializing the Advertising functionality.
*/
static void advertising_init(void)
{
static void advertising_init(void) {
#if defined(S112)
ble_advertising_init_t init;
@@ -707,8 +650,7 @@ static void advertising_init(void)
/**@brief Function for initializing the nrf log module.
*/
static void log_init(void)
{
static void log_init(void) {
APP_ERROR_CHECK(NRF_LOG_INIT(timestamp));
#if defined(S112)
NRF_LOG_DEFAULT_BACKENDS_INIT();
@@ -717,8 +659,7 @@ static void log_init(void)
/**@brief Function for initializing power management.
*/
static void power_management_init(void)
{
static void power_management_init(void) {
#if defined(S112)
APP_ERROR_CHECK(nrf_pwr_mgmt_init());
#else
@@ -730,28 +671,25 @@ static void power_management_init(void)
*
* @details If there is no pending log operation, then sleep until next the next event occurs.
*/
static void idle_state_handle(void)
{
static void idle_state_handle(void) {
app_feed_wdt();
if (NRF_LOG_PROCESS() == false)
nrf_pwr_mgmt_run();
if (NRF_LOG_PROCESS() == false) nrf_pwr_mgmt_run();
}
/**
* @brief WDT events handler.
*/
void wdt_event_handler(void)
{
//NOTE: The max amount of time we can spend in WDT interrupt is two cycles of 32768[Hz] clock - after that, reset occurs
void wdt_event_handler(void) {
// NOTE: The max amount of time we can spend in WDT interrupt is two cycles of 32768[Hz] clock - after that, reset
// occurs
NRF_LOG_ERROR("WDT Rest!\r\n");
NRF_LOG_FINAL_FLUSH();
}
/**@brief Function for application main entry.
*/
int main(void)
{
int main(void) {
log_init();
// Save reset reason.
@@ -798,8 +736,7 @@ int main(void)
ble_epd_on_timer(&m_epd, m_timestamp, true);
}
for (;;)
{
for (;;) {
app_sched_execute();
idle_state_handle();
}