diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..bbf6bf0 --- /dev/null +++ b/.clang-format @@ -0,0 +1,6 @@ +BasedOnStyle: Google +Language: Cpp +ColumnLimit: 120 +IndentWidth: 4 +TabWidth: 4 +UseTab: Never \ No newline at end of file diff --git a/EPD/EPD_config.c b/EPD/EPD_config.c index f4e280a..e5d531b 100644 --- a/EPD/EPD_config.c +++ b/EPD/EPD_config.c @@ -1,26 +1,25 @@ -#include -#include "nordic_common.h" -#include "fds.h" -#include "app_scheduler.h" #include "EPD_config.h" + +#include + +#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,11 +37,10 @@ void epd_config_init(epd_config_t *cfg) run_fds_gc(NULL, 0); } -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; +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; memset(cfg, 0xFF, sizeof(epd_config_t)); memset(&ftok, 0x00, sizeof(fds_find_token_t)); @@ -64,12 +62,11 @@ void epd_config_read(epd_config_t *cfg) fds_record_close(&record_desc); } -void epd_config_write(epd_config_t *cfg) -{ - ret_code_t ret; - fds_record_t record; - fds_record_desc_t record_desc; - fds_find_token_t ftok; +void epd_config_write(epd_config_t* cfg) { + ret_code_t ret; + fds_record_t record; + fds_record_desc_t record_desc; + fds_find_token_t ftok; record.file_id = CONFIG_FILE_ID; record.key = CONFIG_REC_KEY; @@ -93,16 +90,14 @@ 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) -{ - ret_code_t ret; - fds_record_desc_t record_desc; - fds_find_token_t ftok; +void epd_config_clear(epd_config_t* cfg) { + ret_code_t ret; + fds_record_desc_t record_desc; + fds_find_token_t ftok; memset(&ftok, 0x00, sizeof(fds_find_token_t)); if (fds_record_find(CONFIG_FILE_ID, CONFIG_REC_KEY, &record_desc, &ftok) != NRF_SUCCESS) { @@ -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; } diff --git a/EPD/EPD_config.h b/EPD/EPD_config.h index ba9b4c9..74b4e24 100644 --- a/EPD/EPD_config.h +++ b/EPD/EPD_config.h @@ -3,8 +3,7 @@ #include #include -typedef struct -{ +typedef struct { uint8_t mosi_pin; uint8_t sclk_pin; uint8_t cs_pin; @@ -21,11 +20,11 @@ typedef struct } epd_config_t; #define EPD_CONFIG_SIZE (sizeof(epd_config_t) / sizeof(uint8_t)) - -void epd_config_init(epd_config_t *cfg); -void epd_config_read(epd_config_t *cfg); -void epd_config_write(epd_config_t *cfg); -void epd_config_clear(epd_config_t *cfg); -bool epd_config_empty(epd_config_t *cfg); + +void epd_config_init(epd_config_t* cfg); +void epd_config_read(epd_config_t* cfg); +void epd_config_write(epd_config_t* cfg); +void epd_config_clear(epd_config_t* cfg); +bool epd_config_empty(epd_config_t* cfg); #endif diff --git a/EPD/EPD_driver.c b/EPD/EPD_driver.c index 6d4d1a7..4010ecc 100644 --- a/EPD/EPD_driver.c +++ b/EPD/EPD_driver.c @@ -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])) @@ -17,26 +18,22 @@ static uint32_t EPD_BS_PIN = 13; static uint32_t EPD_EN_PIN = 0xFF; static uint32_t EPD_LED_PIN = 0xFF; -#define SPI_INSTANCE 0 /**< SPI instance index. */ -static const nrf_drv_spi_t spi = NRF_DRV_SPI_INSTANCE(SPI_INSTANCE); /**< SPI instance. */ +#define SPI_INSTANCE 0 /**< SPI instance index. */ +static const nrf_drv_spi_t spi = NRF_DRV_SPI_INSTANCE(SPI_INSTANCE); /**< SPI instance. */ #if defined(S112) #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_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); +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); } #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; @@ -303,7 +277,7 @@ float EPD_ReadVoltage(void) (ADC_CONFIG_PSEL_Disabled << ADC_CONFIG_PSEL_Pos) | (ADC_CONFIG_EXTREFSEL_None << ADC_CONFIG_EXTREFSEL_Pos); NRF_ADC->TASKS_START = 1; - while(!NRF_ADC->EVENTS_END); + while (!NRF_ADC->EVENTS_END); NRF_ADC->EVENTS_END = 0; uint16_t value = NRF_ADC->RESULT; NRF_ADC->TASKS_STOP = 1; @@ -327,24 +301,14 @@ extern epd_model_t epd_ssd1677_750_bw; 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, +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_model_t *epd_init(epd_model_id_t id) -{ - epd_model_t *epd = NULL; +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) { epd = epd_models[i]; diff --git a/EPD/EPD_driver.h b/EPD/EPD_driver.h index 5bc9788..c69ae91 100644 --- a/EPD/EPD_driver.h +++ b/EPD/EPD_driver.h @@ -4,13 +4,13 @@ #include #include #include + +#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, @@ -22,114 +22,112 @@ typedef enum // UC81xx commands enum { - UC81xx_PSR = 0x00, // Panel Setting - UC81xx_PWR = 0x01, // Power Setting - UC81xx_POF = 0x02, // Power OFF - UC81xx_PFS = 0x03, // Power OFF Sequence Setting - UC81xx_PON = 0x04, // Power ON - UC81xx_PMES = 0x05, // Power ON Measure - UC81xx_BTST = 0x06, // Booster Soft Start - UC81xx_DSLP = 0x07, // Deep sleep - UC81xx_DTM1 = 0x10, // Display Start Transmission 1 - UC81xx_DSP = 0x11, // Data Stop - UC81xx_DRF = 0x12, // Display Refresh - UC81xx_DTM2 = 0x13, // Display Start transmission 2 - UC81xx_LUTC = 0x20, // VCOM LUT (LUTC) - UC81xx_LUTWW = 0x21, // W2W LUT (LUTWW) - UC81xx_LUTBW = 0x22, // B2W LUT (LUTBW / LUTR) - UC81xx_LUTWB = 0x23, // W2B LUT (LUTWB / LUTW) - UC81xx_LUTBB = 0x24, // B2B LUT (LUTBB / LUTB) - UC81xx_PLL = 0x30, // PLL control - UC81xx_TSC = 0x40, // Temperature Sensor Calibration - UC81xx_TSE = 0x41, // Temperature Sensor Selection - UC81xx_TSW = 0x42, // Temperature Sensor Write - UC81xx_TSR = 0x43, // Temperature Sensor Read - UC81xx_CDI = 0x50, // Vcom and data interval setting - UC81xx_LPD = 0x51, // Lower Power Detection - UC81xx_TCON = 0x60, // TCON setting - UC81xx_TRES = 0x61, // Resolution setting - UC81xx_GSST = 0x65, // GSST Setting - UC81xx_REV = 0x70, // Revision - UC81xx_FLG = 0x71, // Get Status - UC81xx_AMV = 0x80, // Auto Measurement Vcom - UC81xx_VV = 0x81, // Read Vcom Value - UC81xx_VDCS = 0x82, // VCM_DC Setting - UC81xx_PTL = 0x90, // Partial Window - UC81xx_PTIN = 0x91, // Partial In - UC81xx_PTOUT = 0x92, // Partial Out - UC81xx_PGM = 0xA0, // Program Mode - UC81xx_APG = 0xA1, // Active Progrmming - UC81xx_ROTP = 0xA2, // Read OTP - UC81xx_CCSET = 0xE0, // Cascade Setting - UC81xx_PWS = 0xE3, // Power Saving - UC81xx_TSSET = 0xE5, // Force Temperauture + UC81xx_PSR = 0x00, // Panel Setting + UC81xx_PWR = 0x01, // Power Setting + UC81xx_POF = 0x02, // Power OFF + UC81xx_PFS = 0x03, // Power OFF Sequence Setting + UC81xx_PON = 0x04, // Power ON + UC81xx_PMES = 0x05, // Power ON Measure + UC81xx_BTST = 0x06, // Booster Soft Start + UC81xx_DSLP = 0x07, // Deep sleep + UC81xx_DTM1 = 0x10, // Display Start Transmission 1 + UC81xx_DSP = 0x11, // Data Stop + UC81xx_DRF = 0x12, // Display Refresh + UC81xx_DTM2 = 0x13, // Display Start transmission 2 + UC81xx_LUTC = 0x20, // VCOM LUT (LUTC) + UC81xx_LUTWW = 0x21, // W2W LUT (LUTWW) + UC81xx_LUTBW = 0x22, // B2W LUT (LUTBW / LUTR) + UC81xx_LUTWB = 0x23, // W2B LUT (LUTWB / LUTW) + UC81xx_LUTBB = 0x24, // B2B LUT (LUTBB / LUTB) + UC81xx_PLL = 0x30, // PLL control + UC81xx_TSC = 0x40, // Temperature Sensor Calibration + UC81xx_TSE = 0x41, // Temperature Sensor Selection + UC81xx_TSW = 0x42, // Temperature Sensor Write + UC81xx_TSR = 0x43, // Temperature Sensor Read + UC81xx_CDI = 0x50, // Vcom and data interval setting + UC81xx_LPD = 0x51, // Lower Power Detection + UC81xx_TCON = 0x60, // TCON setting + UC81xx_TRES = 0x61, // Resolution setting + UC81xx_GSST = 0x65, // GSST Setting + UC81xx_REV = 0x70, // Revision + UC81xx_FLG = 0x71, // Get Status + UC81xx_AMV = 0x80, // Auto Measurement Vcom + UC81xx_VV = 0x81, // Read Vcom Value + UC81xx_VDCS = 0x82, // VCM_DC Setting + UC81xx_PTL = 0x90, // Partial Window + UC81xx_PTIN = 0x91, // Partial In + UC81xx_PTOUT = 0x92, // Partial Out + UC81xx_PGM = 0xA0, // Program Mode + UC81xx_APG = 0xA1, // Active Progrmming + UC81xx_ROTP = 0xA2, // Read OTP + UC81xx_CCSET = 0xE0, // Cascade Setting + UC81xx_PWS = 0xE3, // Power Saving + UC81xx_TSSET = 0xE5, // Force Temperauture }; // SSD16xx commands enum { - SSD16xx_GDO_CTR = 0x01, // Driver Output control - SSD16xx_GDV_CTRL = 0x03, // Gate Driving voltage Control - SSD16xx_SDV_CTRL = 0x04, // Source Driving voltage Control - SSD16xx_SOFTSTART = 0x0C, // Booster Soft start Control - SSD16xx_GSCAN_START = 0x0F, // Gate scan start position - SSD16xx_SLEEP_MODE = 0x10, // Deep Sleep mode - SSD16xx_ENTRY_MODE = 0x11, // Data Entry mode setting - SSD16xx_SW_RESET = 0x12, // SW RESET - SSD16xx_HV_RD_DETECT = 0x14, // HV Ready Detection - SSD16xx_VCI_DETECT = 0x15, // VCI Detection - SSD16xx_TSENSOR_CTRL = 0x18, // Temperature Sensor Control - SSD16xx_TSENSOR_WRITE = 0x1A, // Temperature Sensor Control (Write to temperature register) - SSD16xx_TSENSOR_READ = 0x1B, // Temperature Sensor Control (Read from temperature register) - SSD16xx_TSENSOR_WRITE_EXT = 0x1C, // Temperature Sensor Control (Write Command to External temperature sensor) - SSD16xx_MASTER_ACTIVATE = 0x20, // Master Activation - SSD16xx_DISP_CTRL1 = 0x21, // Display Update Control 1 - SSD16xx_DISP_CTRL2 = 0x22, // Display Update Control 2 - SSD16xx_WRITE_RAM1 = 0x24, // Write RAM (BW) - SSD16xx_WRITE_RAM2 = 0x26, // Write RAM (RED) - SSD16xx_READ_RAM = 0x27, // Read RAM - SSD16xx_VCOM_SENSE = 0x28, // VCOM Sense - SSD16xx_VCOM_SENSE_DURATON = 0x29, // VCOM Sense Duration - SSD16xx_PRGM_VCOM_OTP = 0x2A, // Program VCOM OTP - SSD16xx_VCOM_CTRL = 0x2B, // Write Register for VCOM Control - SSD16xx_VCOM_VOLTAGE = 0x2C, // Write VCOM register - SSD16xx_READ_OTP_REG = 0x2D, // OTP Register Read for Display Option - SSD16xx_READ_USER_ID = 0x2E, // User ID Read - SSD16xx_READ_STATUS = 0x2F, // Status Bit Read - SSD16xx_PRGM_WS_OTP = 0x30, // Program WS OTP - SSD16xx_LOAD_WS_OTP = 0x31, // Load WS OTP - SSD16xx_WRITE_LUT = 0x32, // Write LUT register - SSD16xx_READ_LUT = 0x33, // Read LUT - SSD16xx_CRC_CALC = 0x34, // CRC calculation - SSD16xx_CRC_STATUS = 0x35, // CRC Status Read - SSD16xx_PRGM_OTP_SELECTION = 0x36, // Program OTP selection - SSD16xx_OTP_SELECTION_CTRL = 0x37, // Write OTP selection - SSD16xx_USER_ID_CTRL = 0x38, // Write Register for User ID - SSD16xx_OTP_PROG_MODE = 0x39, // OTP program mode - SSD16xx_DUMMY_LINE = 0x3A, // Set dummy line period - SSD16xx_GATE_LINE_WIDTH = 0x3B, // Set Gate line width - SSD16xx_BORDER_CTRL = 0x3C, // Border Waveform Control - SSD16xx_RAM_READ_CTRL = 0x41, // Read RAM Option - SSD16xx_RAM_XPOS = 0x44, // Set RAM X - address Start / End position - SSD16xx_RAM_YPOS = 0x45, // Set Ram Y- address Start / End position - SSD16xx_AUTO_WRITE_RED_RAM = 0x46, // Auto Write RED RAM for Regular Pattern - SSD16xx_AUTO_WRITE_BW_RAM = 0x47, // Auto Write B/W RAM for Regular Pattern - SSD16xx_RAM_XCOUNT = 0x4E, // Set RAM X address counter - SSD16xx_RAM_YCOUNT = 0x4F, // Set RAM Y address counter - SSD16xx_ANALOG_BLOCK_CTRL = 0x74, // Set Analog Block Control - SSD16xx_DIGITAL_BLOCK_CTRL = 0x7E, // Set Digital Block Control - SSD16xx_NOP = 0x7F, // NOP + SSD16xx_GDO_CTR = 0x01, // Driver Output control + SSD16xx_GDV_CTRL = 0x03, // Gate Driving voltage Control + SSD16xx_SDV_CTRL = 0x04, // Source Driving voltage Control + SSD16xx_SOFTSTART = 0x0C, // Booster Soft start Control + SSD16xx_GSCAN_START = 0x0F, // Gate scan start position + SSD16xx_SLEEP_MODE = 0x10, // Deep Sleep mode + SSD16xx_ENTRY_MODE = 0x11, // Data Entry mode setting + SSD16xx_SW_RESET = 0x12, // SW RESET + SSD16xx_HV_RD_DETECT = 0x14, // HV Ready Detection + SSD16xx_VCI_DETECT = 0x15, // VCI Detection + SSD16xx_TSENSOR_CTRL = 0x18, // Temperature Sensor Control + SSD16xx_TSENSOR_WRITE = 0x1A, // Temperature Sensor Control (Write to temperature register) + SSD16xx_TSENSOR_READ = 0x1B, // Temperature Sensor Control (Read from temperature register) + SSD16xx_TSENSOR_WRITE_EXT = 0x1C, // Temperature Sensor Control (Write Command to External temperature sensor) + SSD16xx_MASTER_ACTIVATE = 0x20, // Master Activation + SSD16xx_DISP_CTRL1 = 0x21, // Display Update Control 1 + SSD16xx_DISP_CTRL2 = 0x22, // Display Update Control 2 + SSD16xx_WRITE_RAM1 = 0x24, // Write RAM (BW) + SSD16xx_WRITE_RAM2 = 0x26, // Write RAM (RED) + SSD16xx_READ_RAM = 0x27, // Read RAM + SSD16xx_VCOM_SENSE = 0x28, // VCOM Sense + SSD16xx_VCOM_SENSE_DURATON = 0x29, // VCOM Sense Duration + SSD16xx_PRGM_VCOM_OTP = 0x2A, // Program VCOM OTP + SSD16xx_VCOM_CTRL = 0x2B, // Write Register for VCOM Control + SSD16xx_VCOM_VOLTAGE = 0x2C, // Write VCOM register + SSD16xx_READ_OTP_REG = 0x2D, // OTP Register Read for Display Option + SSD16xx_READ_USER_ID = 0x2E, // User ID Read + SSD16xx_READ_STATUS = 0x2F, // Status Bit Read + SSD16xx_PRGM_WS_OTP = 0x30, // Program WS OTP + SSD16xx_LOAD_WS_OTP = 0x31, // Load WS OTP + SSD16xx_WRITE_LUT = 0x32, // Write LUT register + SSD16xx_READ_LUT = 0x33, // Read LUT + SSD16xx_CRC_CALC = 0x34, // CRC calculation + SSD16xx_CRC_STATUS = 0x35, // CRC Status Read + SSD16xx_PRGM_OTP_SELECTION = 0x36, // Program OTP selection + SSD16xx_OTP_SELECTION_CTRL = 0x37, // Write OTP selection + SSD16xx_USER_ID_CTRL = 0x38, // Write Register for User ID + SSD16xx_OTP_PROG_MODE = 0x39, // OTP program mode + SSD16xx_DUMMY_LINE = 0x3A, // Set dummy line period + SSD16xx_GATE_LINE_WIDTH = 0x3B, // Set Gate line width + SSD16xx_BORDER_CTRL = 0x3C, // Border Waveform Control + SSD16xx_RAM_READ_CTRL = 0x41, // Read RAM Option + SSD16xx_RAM_XPOS = 0x44, // Set RAM X - address Start / End position + SSD16xx_RAM_YPOS = 0x45, // Set Ram Y- address Start / End position + SSD16xx_AUTO_WRITE_RED_RAM = 0x46, // Auto Write RED RAM for Regular Pattern + SSD16xx_AUTO_WRITE_BW_RAM = 0x47, // Auto Write B/W RAM for Regular Pattern + SSD16xx_RAM_XCOUNT = 0x4E, // Set RAM X address counter + SSD16xx_RAM_YCOUNT = 0x4F, // Set RAM Y address counter + SSD16xx_ANALOG_BLOCK_CTRL = 0x74, // Set Analog Block Control + SSD16xx_DIGITAL_BLOCK_CTRL = 0x7E, // Set Digital Block Control + 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,11 +144,10 @@ typedef enum struct epd_driver; -typedef struct -{ +typedef struct { epd_model_id_t id; epd_color_t color; - struct epd_driver *drv; + struct epd_driver* drv; uint16_t width; uint16_t height; } epd_model_t; @@ -159,26 +156,26 @@ typedef struct * * @details This structure contains epd driver functions. */ -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_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 */ - int8_t (*read_temp)(epd_model_t *epd); /**< Read temperature from driver chip */ +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_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 */ + int8_t (*read_temp)(epd_model_t* epd); /**< Read temperature from driver chip */ } epd_driver_t; -#define LOW (0x0) -#define HIGH (0x1) +#define LOW (0x0) +#define HIGH (0x1) -#define DEFAULT (0xFF) -#define INPUT (0x0) -#define OUTPUT (0x1) -#define INPUT_PULLUP (0x2) -#define INPUT_PULLDOWN (0x3) +#define DEFAULT (0xFF) +#define INPUT (0x0) +#define OUTPUT (0x1) +#define INPUT_PULLUP (0x2) +#define INPUT_PULLDOWN (0x3) // Arduino like function wrappers void pinMode(uint32_t pin, uint32_t mode); @@ -187,24 +184,24 @@ void pinMode(uint32_t pin, uint32_t mode); #define delay(ms) nrf_delay_ms(ms) // GPIO -void EPD_GPIO_Load(epd_config_t *cfg); +void EPD_GPIO_Load(epd_config_t* cfg); void EPD_GPIO_Init(void); void EPD_GPIO_Uninit(void); // SPI -void EPD_SPI_Write(uint8_t *value, uint8_t len); -void EPD_SPI_Read(uint8_t *value, uint8_t len); +void EPD_SPI_Write(uint8_t* value, uint8_t len); +void EPD_SPI_Read(uint8_t* value, uint8_t len); // EPD void EPD_WriteCmd(uint8_t cmd); -void EPD_WriteData(uint8_t *value, uint8_t len); -void EPD_ReadData(uint8_t *value, uint8_t len); +void EPD_WriteData(uint8_t* value, uint8_t len); +void EPD_ReadData(uint8_t* value, uint8_t len); void EPD_WriteByte(uint8_t value); uint8_t EPD_ReadByte(void); -#define EPD_Write(cmd, ...) \ - do { \ - uint8_t _data[] = {__VA_ARGS__}; \ - EPD_WriteCmd(cmd); \ +#define EPD_Write(cmd, ...) \ + do { \ + uint8_t _data[] = {__VA_ARGS__}; \ + EPD_WriteCmd(cmd); \ EPD_WriteData(_data, sizeof(_data)); \ } while (0) void EPD_FillRAM(uint8_t cmd, uint8_t value, uint32_t len); @@ -220,6 +217,6 @@ void EPD_LED_BLINK(void); // VDD voltage float EPD_ReadVoltage(void); -epd_model_t *epd_init(epd_model_id_t id); +epd_model_t* epd_init(epd_model_id_t id); #endif diff --git a/EPD/EPD_service.c b/EPD/EPD_service.c index 6a2426f..5a93bf0 100644 --- a/EPD/EPD_service.c +++ b/EPD/EPD_service.c @@ -10,16 +10,18 @@ * */ +#include "EPD_service.h" + #include -#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,28 +31,26 @@ // #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) -{ - epd_gui_update_event_t *event = (epd_gui_update_event_t *)p_event_data; - ble_epd_t *p_epd = event->p_epd; +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; EPD_GPIO_Init(); - epd_model_t *epd = epd_init((epd_model_id_t)p_epd->config.model_id); + epd_model_t* epd = epd_init((epd_model_id_t)p_epd->config.model_id); gui_data_t data = { - .mode = (display_mode_t)p_epd->config.display_mode, - .color = epd->color, - .width = epd->width, - .height = epd->height, - .timestamp = event->timestamp, - .week_start = p_epd->config.week_start, - .temperature = epd->drv->read_temp(epd), - .voltage = EPD_ReadVoltage(), + .mode = (display_mode_t)p_epd->config.display_mode, + .color = epd->color, + .width = epd->width, + .height = epd->height, + .timestamp = event->timestamp, + .week_start = p_epd->config.week_start, + .temperature = epd->drv->read_temp(epd), + .voltage = EPD_ReadVoltage(), }; 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'; + 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'; 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,132 +74,125 @@ 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); - nrf_delay_ms(200); // for sleep + nrf_delay_ms(200); // for sleep 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)); + 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)); + 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]) - { - case EPD_CMD_SET_PINS: - if (length < 8) return; + switch (p_data[0]) { + case EPD_CMD_SET_PINS: + if (length < 8) return; - p_epd->config.mosi_pin = p_data[1]; - p_epd->config.sclk_pin = p_data[2]; - p_epd->config.cs_pin = p_data[3]; - p_epd->config.dc_pin = p_data[4]; - 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]; - epd_config_write(&p_epd->config); + p_epd->config.mosi_pin = p_data[1]; + p_epd->config.sclk_pin = p_data[2]; + p_epd->config.cs_pin = p_data[3]; + p_epd->config.dc_pin = p_data[4]; + 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]; + epd_config_write(&p_epd->config); - EPD_GPIO_Uninit(); - EPD_GPIO_Load(&p_epd->config); - EPD_GPIO_Init(); - break; + EPD_GPIO_Uninit(); + EPD_GPIO_Load(&p_epd->config); + EPD_GPIO_Init(); + break; - case EPD_CMD_INIT: - p_epd->epd = epd_init((epd_model_id_t)(length > 1 ? p_data[1] : p_epd->config.model_id)); - if (p_epd->epd->id != p_epd->config.model_id) { - p_epd->config.model_id = p_epd->epd->id; - epd_config_write(&p_epd->config); - } - epd_send_mtu(p_epd); - epd_send_time(p_epd); - break; + case EPD_CMD_INIT: + p_epd->epd = epd_init((epd_model_id_t)(length > 1 ? p_data[1] : p_epd->config.model_id)); + if (p_epd->epd->id != p_epd->config.model_id) { + p_epd->config.model_id = p_epd->epd->id; + epd_config_write(&p_epd->config); + } + epd_send_mtu(p_epd); + epd_send_time(p_epd); + break; - case EPD_CMD_CLEAR: - epd_update_display_mode(p_epd, MODE_PICTURE); - p_epd->epd->drv->clear(p_epd->epd, length > 1 ? p_data[1] : true); - break; + case EPD_CMD_CLEAR: + epd_update_display_mode(p_epd, MODE_PICTURE); + p_epd->epd->drv->clear(p_epd->epd, length > 1 ? p_data[1] : true); + break; - case EPD_CMD_SEND_COMMAND: - if (length < 2) return; - EPD_WriteCmd(p_data[1]); - break; + case EPD_CMD_SEND_COMMAND: + if (length < 2) return; + EPD_WriteCmd(p_data[1]); + break; - case EPD_CMD_SEND_DATA: - EPD_WriteData(&p_data[1], length - 1); - break; + case EPD_CMD_SEND_DATA: + EPD_WriteData(&p_data[1], length - 1); + break; - case EPD_CMD_REFRESH: - epd_update_display_mode(p_epd, MODE_PICTURE); - p_epd->epd->drv->refresh(p_epd->epd); - break; + case EPD_CMD_REFRESH: + epd_update_display_mode(p_epd, MODE_PICTURE); + p_epd->epd->drv->refresh(p_epd->epd); + break; - case EPD_CMD_SLEEP: - p_epd->epd->drv->sleep(p_epd->epd); - break; + case EPD_CMD_SLEEP: + p_epd->epd->drv->sleep(p_epd->epd); + break; - case EPD_CMD_SET_TIME: { - if (length < 5) return; + case EPD_CMD_SET_TIME: { + if (length < 5) return; - NRF_LOG_DEBUG("time: %02x %02x %02x %02x\n", p_data[1], p_data[2], p_data[3], p_data[4]); - if (length > 5) NRF_LOG_DEBUG("timezone: %d\n", (int8_t)p_data[5]); + NRF_LOG_DEBUG("time: %02x %02x %02x %02x\n", p_data[1], p_data[2], p_data[3], p_data[4]); + if (length > 5) NRF_LOG_DEBUG("timezone: %d\n", (int8_t)p_data[5]); - uint32_t timestamp = (p_data[1] << 24) | (p_data[2] << 16) | (p_data[3] << 8) | p_data[4]; - timestamp += (length > 5 ? (int8_t)p_data[5] : 8) * 60 * 60; // timezone - set_timestamp(timestamp); - epd_update_display_mode(p_epd, length > 6 ? (display_mode_t)p_data[6] : MODE_CALENDAR); - ble_epd_on_timer(p_epd, timestamp, true); - } break; + uint32_t timestamp = (p_data[1] << 24) | (p_data[2] << 16) | (p_data[3] << 8) | p_data[4]; + timestamp += (length > 5 ? (int8_t)p_data[5] : 8) * 60 * 60; // timezone + set_timestamp(timestamp); + epd_update_display_mode(p_epd, length > 6 ? (display_mode_t)p_data[6] : MODE_CALENDAR); + ble_epd_on_timer(p_epd, timestamp, true); + } break; - case EPD_CMD_SET_WEEK_START: - if (length < 2) return; - if (p_data[1] < 7 && p_data[1] != p_epd->config.week_start) { - p_epd->config.week_start = p_data[1]; - epd_config_write(&p_epd->config); - } - break; + case EPD_CMD_SET_WEEK_START: + if (length < 2) return; + if (p_data[1] < 7 && p_data[1] != p_epd->config.week_start) { + p_epd->config.week_start = p_data[1]; + epd_config_write(&p_epd->config); + } + break; - case EPD_CMD_WRITE_IMAGE: // MSB=0000: ram begin, LSB=1111: black - if (length < 3) return; - p_epd->epd->drv->write_ram(p_epd->epd, p_data[1], &p_data[2], length - 2); - break; + case EPD_CMD_WRITE_IMAGE: // MSB=0000: ram begin, LSB=1111: black + if (length < 3) return; + p_epd->epd->drv->write_ram(p_epd->epd, p_data[1], &p_data[2], length - 2); + break; - case EPD_CMD_SET_CONFIG: - if (length < 2) return; - memcpy(&p_epd->config, &p_data[1], (length - 1 > EPD_CONFIG_SIZE) ? EPD_CONFIG_SIZE : length - 1); - epd_config_write(&p_epd->config); - break; + case EPD_CMD_SET_CONFIG: + if (length < 2) return; + memcpy(&p_epd->config, &p_data[1], (length - 1 > EPD_CONFIG_SIZE) ? EPD_CONFIG_SIZE : length - 1); + epd_config_write(&p_epd->config); + break; - case EPD_CMD_SYS_SLEEP: - sleep_mode_enter(); - break; + case EPD_CMD_SYS_SLEEP: + sleep_mode_enter(); + break; case EPD_CMD_SYS_RESET: #if defined(S112) @@ -208,16 +200,16 @@ static void epd_service_on_write(ble_epd_t * p_epd, uint8_t * p_data, uint16_t l #else NVIC_SystemReset(); #endif - break; + break; - case EPD_CMD_CFG_ERASE: - epd_config_clear(&p_epd->config); - nrf_delay_ms(100); // required - NVIC_SystemReset(); - break; + case EPD_CMD_CFG_ERASE: + epd_config_clear(&p_epd->config); + nrf_delay_ms(100); // required + NVIC_SystemReset(); + break; - default: - break; + default: + break; } } @@ -226,60 +218,42 @@ 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) -{ - ble_gatts_evt_write_t * p_evt_write = &p_ble_evt->evt.gatts_evt.params.write; +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 - { + 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 { 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; - ble_epd_on_ble_evt(p_epd, (ble_evt_t *)p_ble_evt); + + ble_epd_t* p_epd = (ble_epd_t*)p_context; + ble_epd_on_ble_evt(p_epd, (ble_evt_t*)p_ble_evt); } #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,75 +272,67 @@ 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) -{ - ble_uuid_t ble_uuid = {0}; - ble_uuid128_t base_uuid = BLE_UUID_EPD_SVC_BASE; +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; - uint8_t app_version = APP_VERSION; - + uint8_t app_version = APP_VERSION; + VERIFY_SUCCESS(sd_ble_uuid_vs_add(&base_uuid, &ble_uuid.type)); 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; - add_char_params.uuid_type = ble_uuid.type; - add_char_params.max_len = BLE_EPD_MAX_DATA_LEN; - add_char_params.init_len = sizeof(uint8_t); - add_char_params.is_var_len = true; - add_char_params.char_props.notify = 1; - add_char_params.char_props.write = 1; + add_char_params.uuid = BLE_UUID_EPD_CHAR; + add_char_params.uuid_type = ble_uuid.type; + add_char_params.max_len = BLE_EPD_MAX_DATA_LEN; + add_char_params.init_len = sizeof(uint8_t); + add_char_params.is_var_len = true; + add_char_params.char_props.notify = 1; + add_char_params.char_props.write = 1; add_char_params.char_props.write_wo_resp = 1; - add_char_params.read_access = SEC_OPEN; - add_char_params.write_access = SEC_OPEN; - add_char_params.cccd_write_access = SEC_OPEN; + add_char_params.read_access = SEC_OPEN; + add_char_params.write_access = SEC_OPEN; + add_char_params.cccd_write_access = SEC_OPEN; VERIFY_SUCCESS(characteristic_add(p_epd->service_handle, &add_char_params, &p_epd->char_handles)); memset(&add_char_params, 0, sizeof(add_char_params)); - add_char_params.uuid = BLE_UUID_APP_VER; - add_char_params.uuid_type = ble_uuid.type; - add_char_params.max_len = sizeof(uint8_t); - add_char_params.init_len = sizeof(uint8_t); - add_char_params.p_init_value = &app_version; - add_char_params.char_props.read = 1; - add_char_params.read_access = SEC_OPEN; + add_char_params.uuid = BLE_UUID_APP_VER; + add_char_params.uuid_type = ble_uuid.type; + add_char_params.max_len = sizeof(uint8_t); + add_char_params.init_len = sizeof(uint8_t); + add_char_params.p_init_value = &app_version; + add_char_params.char_props.read = 1; + add_char_params.read_access = SEC_OPEN; 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. p_epd->max_data_len = BLE_EPD_MAX_DATA_LEN; - p_epd->conn_handle = BLE_CONN_HANDLE_INVALID; + p_epd->conn_handle = BLE_CONN_HANDLE_INVALID; p_epd->is_notification_enabled = false; epd_config_init(&p_epd->config); 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; @@ -409,19 +371,17 @@ uint32_t ble_epd_string_send(ble_epd_t * p_epd, uint8_t * p_string, uint16_t len hvx_params.handle = p_epd->char_handles.value_handle; hvx_params.p_data = p_string; - hvx_params.p_len = &length; - hvx_params.type = BLE_GATT_HVX_NOTIFICATION; + hvx_params.p_len = &length; + hvx_params.type = BLE_GATT_HVX_NOTIFICATION; 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 }; + epd_gui_update_event_t event = {p_epd, timestamp}; app_sched_event_put(&event, sizeof(epd_gui_update_event_t), epd_gui_update); } } diff --git a/EPD/EPD_service.h b/EPD/EPD_service.h index 53ce0d6..4ad166d 100644 --- a/EPD/EPD_service.h +++ b/EPD/EPD_service.h @@ -15,15 +15,16 @@ #include #include + #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. * @@ -31,75 +32,75 @@ * @hideinitializer */ #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); #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) +#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) #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 0x0001 -#define BLE_UUID_EPD_CHAR 0x0002 -#define BLE_UUID_APP_VER 0x0003 +#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 #define EPD_SVC_UUID_TYPE BLE_UUID_TYPE_VENDOR_BEGIN #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 -{ - EPD_CMD_SET_PINS = 0x00, /**< set EPD pin mapping. */ - EPD_CMD_INIT = 0x01, /**< init EPD display driver */ - EPD_CMD_CLEAR = 0x02, /**< clear EPD screen */ - EPD_CMD_SEND_COMMAND = 0x03, /**< send command to EPD */ - EPD_CMD_SEND_DATA = 0x04, /**< send data to EPD */ - EPD_CMD_REFRESH = 0x05, /**< diaplay EPD ram on screen */ - EPD_CMD_SLEEP = 0x06, /**< EPD enter sleep mode */ +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 */ + EPD_CMD_SEND_COMMAND = 0x03, /**< send command to EPD */ + EPD_CMD_SEND_DATA = 0x04, /**< send data to EPD */ + EPD_CMD_REFRESH = 0x05, /**< diaplay EPD ram on screen */ + EPD_CMD_SLEEP = 0x06, /**< EPD enter sleep mode */ - EPD_CMD_SET_TIME = 0x20, /** < set time with unix timestamp */ - EPD_CMD_SET_WEEK_START = 0x21, /** < set week start day (0: Sunday, 1: Monday, ...) */ + EPD_CMD_SET_TIME = 0x20, /** < set time with unix timestamp */ + EPD_CMD_SET_WEEK_START = 0x21, /** < set week start day (0: Sunday, 1: Monday, ...) */ - EPD_CMD_WRITE_IMAGE = 0x30, /** < write image data to EPD ram */ + EPD_CMD_WRITE_IMAGE = 0x30, /** < write image data to EPD ram */ - EPD_CMD_SET_CONFIG = 0x90, /**< set full EPD config */ - EPD_CMD_SYS_RESET = 0x91, /**< MCU reset */ - EPD_CMD_SYS_SLEEP = 0x92, /**< MCU enter sleep mode */ - EPD_CMD_CFG_ERASE = 0x99, /**< Erase config and reset */ + EPD_CMD_SET_CONFIG = 0x90, /**< set full EPD config */ + EPD_CMD_SYS_RESET = 0x91, /**< MCU reset */ + EPD_CMD_SYS_SLEEP = 0x92, /**< MCU enter sleep mode */ + EPD_CMD_CFG_ERASE = 0x99, /**< Erase config and reset */ }; /**@brief EPD Service structure. * * @details This structure contains status information related to the service. */ -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. */ - 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.*/ - epd_model_t *epd; /**< current EPD model */ - epd_config_t config; /**< EPD config */ +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. */ + 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.*/ + epd_model_t* epd; /**< current EPD model */ + epd_config_t config; /**< EPD config */ } ble_epd_t; -typedef struct -{ - ble_epd_t *p_epd; +typedef struct { + ble_epd_t* p_epd; uint32_t timestamp; } epd_gui_update_event_t; @@ -109,7 +110,7 @@ typedef struct * * @param[in] p_epd EPD Service structure. */ -void ble_epd_sleep_prepare(ble_epd_t * p_epd); +void ble_epd_sleep_prepare(ble_epd_t* p_epd); /**@brief Function for initializing the EPD Service. * @@ -120,7 +121,7 @@ void ble_epd_sleep_prepare(ble_epd_t * p_epd); * @retval NRF_SUCCESS If the service was successfully initialized. Otherwise, an error code is returned. * @retval NRF_ERROR_NULL If either of the pointers p_epd or p_epd_init is NULL. */ -uint32_t ble_epd_init(ble_epd_t * p_epd); +uint32_t ble_epd_init(ble_epd_t* p_epd); /**@brief Function for handling the EPD Service's BLE events. * @@ -132,7 +133,7 @@ uint32_t ble_epd_init(ble_epd_t * p_epd); * @param[in] p_epd EPD Service structure. * @param[in] p_ble_evt Event received from the S110 SoftDevice. */ -void ble_epd_on_ble_evt(ble_epd_t * p_epd, ble_evt_t * p_ble_evt); +void ble_epd_on_ble_evt(ble_epd_t* p_epd, ble_evt_t* p_ble_evt); /**@brief Function for sending a string to the peer. * @@ -145,10 +146,10 @@ void ble_epd_on_ble_evt(ble_epd_t * p_epd, ble_evt_t * p_ble_evt); * * @retval NRF_SUCCESS If the string was sent successfully. Otherwise, an error code is returned. */ -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); -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); -#endif // EPD_BLE_H__ +#endif // EPD_BLE_H__ /** @} */ diff --git a/EPD/SSD16xx.c b/EPD/SSD16xx.c index 2b28868..6798af7 100644 --- a/EPD/SSD16xx.c +++ b/EPD/SSD16xx.c @@ -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) -{ - EPD_Write(SSD16xx_ENTRY_MODE, 0x03); // set ram entry mode: x increase, y increase +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"); @@ -79,14 +61,13 @@ static void SSD16xx_Refresh(epd_model_t *epd) SSD16xx_WaitBusy(30000); NRF_LOG_DEBUG("[EPD]: refresh end\n"); -// SSD16xx_Dump_LUT(); + // SSD16xx_Dump_LUT(); - _setPartialRamArea(epd, 0, 0, epd->width, epd->height); // DO NOT REMOVE! - SSD16xx_Update(0x83); // power off + _setPartialRamArea(epd, 0, 0, epd->width, epd->height); // DO NOT REMOVE! + 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) -{ - 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; +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; _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); } diff --git a/EPD/UC81xx.c b/EPD/UC81xx.c index e233441..fabcb7d 100644 --- a/EPD/UC81xx.c +++ b/EPD/UC81xx.c @@ -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); + 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); } else { - uint16_t xe = (x + w - 1) | 0x0007; // byte boundary inclusive (last byte) + 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 &= 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); } } -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,18 +76,16 @@ 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(); + + // UC81xx_Dump_OTP(); EPD_Write(UC81xx_PSR, epd->color == BWR ? 0x0F : 0x1F); 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); @@ -114,17 +95,12 @@ void UC8159_Init(epd_model_t *epd) EPD_Write(UC81xx_BTST, 0xc7, 0xcc, 0x15); EPD_Write(UC81xx_CDI, 0x77); 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(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); } -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,87 +140,81 @@ 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) -{ - 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; +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; - EPD_WriteCmd(UC81xx_PTIN); // partial in + 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 EPD_WriteByte(black[j + i * wb]); } } - EPD_WriteCmd(UC81xx_PTOUT); // partial out + EPD_WriteCmd(UC81xx_PTOUT); // partial out } 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) -{ - 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; +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; - EPD_WriteCmd(UC81xx_PTIN); // partial in + 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]; @@ -257,28 +222,25 @@ void UC8159_Write_Image(epd_model_t *epd, uint8_t *black, uint8_t *color, uint16 UC8159_Send_Pixel(black_data, color_data); } } - EPD_WriteCmd(UC81xx_PTOUT); // partial out + 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) -{ - 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; +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; _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 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); diff --git a/GUI/Adafruit_GFX.c b/GUI/Adafruit_GFX.c index 7da3c3f..99a11a2 100644 --- a/GUI/Adafruit_GFX.c +++ b/GUI/Adafruit_GFX.c @@ -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 #include #include #include #include -#include "Adafruit_GFX.h" #ifndef ABS #define ABS(x) ((x) > 0 ? (x) : -(x)) @@ -45,30 +46,33 @@ 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)) +#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) -{ - Adafruit_GFX *gfx = CONTAINER_OF(u8g2, Adafruit_GFX, u8g2); - switch(dir) { - case 0: - GFX_drawFastHLine(gfx, x, y, len, color); - break; - case 1: - GFX_drawFastVLine(gfx, x, y, len, color); - break; - case 2: - GFX_drawFastHLine(gfx, x - len + 1, y, len, color); - break; - case 3: - GFX_drawFastVLine(gfx, x, y - len + 1, len, color); - break; - } +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: + GFX_drawFastHLine(gfx, x, y, len, color); + break; + case 1: + GFX_drawFastVLine(gfx, x, y, len, color); + break; + case 2: + GFX_drawFastHLine(gfx, x - len + 1, y, len, color); + break; + case 3: + GFX_drawFastVLine(gfx, x, y - len + 1, len, color); + break; + } } /**************************************************************************/ @@ -79,16 +83,16 @@ static void GFX_u8g2_draw_hv_line(u8g2_font_t *u8g2, int16_t x, int16_t y, @param buffer_height Page buffer height */ /**************************************************************************/ -void GFX_begin(Adafruit_GFX *gfx, int16_t w, int16_t h, int16_t buffer_height) { - memset(gfx, 0, sizeof(Adafruit_GFX)); - memset(&gfx->u8g2, 0, sizeof(gfx->u8g2)); - gfx->WIDTH = gfx->_width = w; - gfx->HEIGHT = gfx->_height = h; - gfx->u8g2.draw_hv_line = GFX_u8g2_draw_hv_line; - gfx->buffer = malloc(((gfx->WIDTH + 7) / 8) * buffer_height); - gfx->page_height = buffer_height; - gfx->total_pages = (gfx->HEIGHT / gfx->page_height) + (gfx->HEIGHT % gfx->page_height > 0); - GFX_setWindow(gfx, 0, 0, gfx->WIDTH, gfx->HEIGHT); +void GFX_begin(Adafruit_GFX* gfx, int16_t w, int16_t h, int16_t buffer_height) { + memset(gfx, 0, sizeof(Adafruit_GFX)); + memset(&gfx->u8g2, 0, sizeof(gfx->u8g2)); + gfx->WIDTH = gfx->_width = w; + gfx->HEIGHT = gfx->_height = h; + gfx->u8g2.draw_hv_line = GFX_u8g2_draw_hv_line; + gfx->buffer = malloc(((gfx->WIDTH + 7) / 8) * buffer_height); + gfx->page_height = buffer_height; + gfx->total_pages = (gfx->HEIGHT / gfx->page_height) + (gfx->HEIGHT % gfx->page_height > 0); + GFX_setWindow(gfx, 0, 0, gfx->WIDTH, gfx->HEIGHT); } /**************************************************************************/ @@ -99,11 +103,11 @@ void GFX_begin(Adafruit_GFX *gfx, int16_t w, int16_t h, int16_t buffer_height) { @param buffer_height Page buffer height, should be multiple of 2 */ /**************************************************************************/ -void GFX_begin_3c(Adafruit_GFX *gfx, int16_t w, int16_t h, int16_t buffer_height) { - GFX_begin(gfx, w, h, buffer_height); - gfx->page_height /= 2; - gfx->color = gfx->buffer + ((gfx->WIDTH + 7) / 8) * gfx->page_height; - gfx->total_pages = (gfx->HEIGHT / gfx->page_height) + (gfx->HEIGHT % gfx->page_height > 0); +void GFX_begin_3c(Adafruit_GFX* gfx, int16_t w, int16_t h, int16_t buffer_height) { + GFX_begin(gfx, w, h, buffer_height); + gfx->page_height /= 2; + gfx->color = gfx->buffer + ((gfx->WIDTH + 7) / 8) * gfx->page_height; + gfx->total_pages = (gfx->HEIGHT / gfx->page_height) + (gfx->HEIGHT % gfx->page_height > 0); } /**************************************************************************/ @@ -114,41 +118,41 @@ void GFX_begin_3c(Adafruit_GFX *gfx, int16_t w, int16_t h, int16_t buffer_height @param buffer_height Page buffer height, should be multiple of 2 */ /**************************************************************************/ -void GFX_begin_4c(Adafruit_GFX *gfx, int16_t w, int16_t h, int16_t buffer_height) { - GFX_begin(gfx, w, h, buffer_height); - gfx->page_height /= 2; - gfx->color = gfx->buffer; - gfx->total_pages = (gfx->HEIGHT / gfx->page_height) + (gfx->HEIGHT % gfx->page_height > 0); +void GFX_begin_4c(Adafruit_GFX* gfx, int16_t w, int16_t h, int16_t buffer_height) { + GFX_begin(gfx, w, h, buffer_height); + gfx->page_height /= 2; + gfx->color = gfx->buffer; + gfx->total_pages = (gfx->HEIGHT / gfx->page_height) + (gfx->HEIGHT % gfx->page_height > 0); } -void GFX_end(Adafruit_GFX *gfx) { - if (gfx->buffer) free(gfx->buffer); +void GFX_end(Adafruit_GFX* gfx) { + if (gfx->buffer) free(gfx->buffer); } -void GFX_firstPage(Adafruit_GFX *gfx) { - GFX_fillScreen(gfx, GFX_WHITE); - gfx->current_page = 0; +void GFX_firstPage(Adafruit_GFX* gfx) { + GFX_fillScreen(gfx, GFX_WHITE); + gfx->current_page = 0; } -bool GFX_nextPage(Adafruit_GFX *gfx, buffer_callback callback, void *user_data) { - if (callback) { - int16_t page_ys = gfx->current_page * gfx->page_height; - if (gfx->px != 0 || gfx->py != 0 || gfx->pw != gfx->_width || gfx->ph != gfx->_height) { - int16_t page_ye = gfx->current_page < gfx->total_pages - 1 ? page_ys + gfx->page_height : gfx->HEIGHT; - uint16_t dest_ys = gfx->py + page_ys; // transposed - uint16_t dest_ye = MIN(gfx->py + gfx->ph, gfx->py + page_ye); - if (dest_ye > dest_ys) - callback(user_data, gfx->buffer, gfx->color, gfx->px, dest_ys, gfx->pw, dest_ye - dest_ys); - } else { - int16_t height = MIN(gfx->page_height, gfx->HEIGHT - page_ys); - callback(user_data, gfx->buffer, gfx->color, 0, page_ys, gfx->WIDTH, height); +bool GFX_nextPage(Adafruit_GFX* gfx, buffer_callback callback, void* user_data) { + if (callback) { + int16_t page_ys = gfx->current_page * gfx->page_height; + if (gfx->px != 0 || gfx->py != 0 || gfx->pw != gfx->_width || gfx->ph != gfx->_height) { + int16_t page_ye = gfx->current_page < gfx->total_pages - 1 ? page_ys + gfx->page_height : gfx->HEIGHT; + uint16_t dest_ys = gfx->py + page_ys; // transposed + uint16_t dest_ye = MIN(gfx->py + gfx->ph, gfx->py + page_ye); + if (dest_ye > dest_ys) + callback(user_data, gfx->buffer, gfx->color, gfx->px, dest_ys, gfx->pw, dest_ye - dest_ys); + } else { + int16_t height = MIN(gfx->page_height, gfx->HEIGHT - page_ys); + callback(user_data, gfx->buffer, gfx->color, 0, page_ys, gfx->WIDTH, height); + } } - } - gfx->current_page++; - GFX_fillScreen(gfx, GFX_WHITE); + gfx->current_page++; + GFX_fillScreen(gfx, GFX_WHITE); - return gfx->current_page < gfx->total_pages; + return gfx->current_page < gfx->total_pages; } /**************************************************************************/ @@ -157,20 +161,20 @@ bool GFX_nextPage(Adafruit_GFX *gfx, buffer_callback callback, void *user_data) @param r 0 thru 3 corresponding to 4 cardinal rotations */ /**************************************************************************/ -void GFX_setRotation(Adafruit_GFX *gfx, GFX_Rotate r) { - gfx->rotation = r; - switch (gfx->rotation) { - case GFX_ROTATE_0: - case GFX_ROTATE_180: - gfx->_width = gfx->WIDTH; - gfx->_height = gfx->HEIGHT; - break; - case GFX_ROTATE_90: - case GFX_ROTATE_270: - gfx->_width = gfx->HEIGHT; - gfx->_height = gfx->WIDTH; - break; - } +void GFX_setRotation(Adafruit_GFX* gfx, GFX_Rotate r) { + gfx->rotation = r; + switch (gfx->rotation) { + case GFX_ROTATE_0: + case GFX_ROTATE_180: + gfx->_width = gfx->WIDTH; + gfx->_height = gfx->HEIGHT; + break; + case GFX_ROTATE_90: + case GFX_ROTATE_270: + gfx->_width = gfx->HEIGHT; + gfx->_height = gfx->WIDTH; + break; + } } /**************************************************************************/ @@ -182,69 +186,90 @@ 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) -{ - gfx->px = MIN(x, gfx->_width); - gfx->py = MIN(y, gfx->_height); - gfx->pw = MIN(w, gfx->_width - gfx->px); - gfx->ph = MIN(h, gfx->_height - gfx->py); - - switch(gfx->rotation) { - case GFX_ROTATE_0: - break; - case GFX_ROTATE_90: - SWAP(gfx->px, gfx->py, uint16_t); - SWAP(gfx->pw, gfx->ph, uint16_t); - gfx->px = gfx->WIDTH - gfx->px - gfx->pw; - break; - case GFX_ROTATE_180: - gfx->px = gfx->WIDTH - gfx->px - gfx->pw; - gfx->py = gfx->HEIGHT - gfx->py - gfx->ph; - break; - case GFX_ROTATE_270: - SWAP(gfx->px, gfx->py, uint16_t); - SWAP(gfx->pw, gfx->ph, uint16_t); - gfx->py = gfx->HEIGHT - gfx->py - gfx->ph; - break; - } +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); + gfx->ph = MIN(h, gfx->_height - gfx->py); - gfx->pw += gfx->px % 8; - if (gfx->pw % 8 > 0) gfx->pw += 8 - (gfx->pw % 8); - gfx->px -= gfx->px % 8; + switch (gfx->rotation) { + case GFX_ROTATE_0: + break; + case GFX_ROTATE_90: + SWAP(gfx->px, gfx->py, uint16_t); + SWAP(gfx->pw, gfx->ph, uint16_t); + gfx->px = gfx->WIDTH - gfx->px - gfx->pw; + break; + case GFX_ROTATE_180: + gfx->px = gfx->WIDTH - gfx->px - gfx->pw; + gfx->py = gfx->HEIGHT - gfx->py - gfx->ph; + break; + case GFX_ROTATE_270: + SWAP(gfx->px, gfx->py, uint16_t); + SWAP(gfx->pw, gfx->ph, uint16_t); + gfx->py = gfx->HEIGHT - gfx->py - gfx->ph; + break; + } + + gfx->pw += gfx->px % 8; + if (gfx->pw % 8 > 0) gfx->pw += 8 - (gfx->pw % 8); + gfx->px -= gfx->px % 8; } static uint8_t color4(uint16_t color) { - static uint16_t _prev_color = GFX_BLACK; - 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? - 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 - } break; - } - _prev_color = color; - _prev_color4 = cv4; - return cv4; + static uint16_t _prev_color = GFX_BLACK; + 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? + 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 + } break; + } + _prev_color = color; + _prev_color4 = cv4; + return cv4; } /**************************************************************************/ /*! @@ -254,60 +279,68 @@ static uint8_t color4(uint16_t color) { @param color 16-bit 5-6-5 Color to fill with */ /**************************************************************************/ -void GFX_drawPixel(Adafruit_GFX *gfx, int16_t x, int16_t y, uint16_t color) { - if (x < 0 || x >= gfx->_width || y < 0 || y >= gfx->_height) return; - - switch (gfx->rotation) { - case GFX_ROTATE_0: - break; - case GFX_ROTATE_90: - SWAP(x, y, int16_t); - x = gfx->WIDTH - x - 1; - break; - case GFX_ROTATE_180: - x = gfx->WIDTH - x - 1; - y = gfx->HEIGHT - y - 1; - break; - case GFX_ROTATE_270: - SWAP(x, y, int16_t); - y = gfx->HEIGHT - y - 1; - break; - } +void GFX_drawPixel(Adafruit_GFX* gfx, int16_t x, int16_t y, uint16_t color) { + if (x < 0 || x >= gfx->_width || y < 0 || y >= gfx->_height) return; - // transpose partial window to 0,0 - x -= gfx->px; - y -= gfx->py; - // clip to (partial) window - if (x < 0 || x >= gfx->pw || y < 0 || y >= gfx->ph) return; - // adjust for current page - y -= gfx->current_page * gfx->page_height; - // check if in current page - if (y < 0 || y >= gfx->page_height) return; - - if (gfx->color == gfx->buffer) { // 4c - 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; + switch (gfx->rotation) { + case GFX_ROTATE_0: + break; + case GFX_ROTATE_90: + SWAP(x, y, int16_t); + x = gfx->WIDTH - x - 1; + break; + case GFX_ROTATE_180: + x = gfx->WIDTH - x - 1; + y = gfx->HEIGHT - y - 1; + break; + case GFX_ROTATE_270: + SWAP(x, y, int16_t); + y = gfx->HEIGHT - y - 1; + break; + } + + // transpose partial window to 0,0 + x -= gfx->px; + y -= gfx->py; + // clip to (partial) window + if (x < 0 || x >= gfx->pw || y < 0 || y >= gfx->ph) return; + // adjust for current page + y -= gfx->current_page * gfx->page_height; + // check if in current page + if (y < 0 || y >= gfx->page_height) return; + + if (gfx->color == gfx->buffer) { // 4c + 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; + } + } else if (gfx->color != NULL) { // 3c + uint16_t i = x / 8 + y * (gfx->pw / 8); + gfx->buffer[i] |= 0x80 >> (x & 7); // white + gfx->color[i] |= 0x80 >> (x & 7); + if (color == GFX_BLACK) + gfx->buffer[i] &= ~(0x80 >> (x & 7)); + else if (color != GFX_WHITE) + gfx->color[i] &= ~(0x80 >> (x & 7)); + } else { + uint16_t i = x / 8 + y * (gfx->pw / 8); + if (color == GFX_WHITE) + gfx->buffer[i] |= 0x80 >> (x & 7); + else + gfx->buffer[i] &= ~(0x80 >> (x & 7)); } - } else if (gfx->color != NULL) { // 3c - uint16_t i = x / 8 + y * (gfx->pw / 8); - gfx->buffer[i] |= 0x80 >> (x & 7); // white - gfx->color[i] |= 0x80 >> (x & 7); - if (color == GFX_BLACK) - gfx->buffer[i] &= ~(0x80 >> (x & 7)); - else if (color != GFX_WHITE) - gfx->color[i] &= ~(0x80 >> (x & 7)); - } else { - uint16_t i = x / 8 + y * (gfx->pw / 8); - if (color == GFX_WHITE) - gfx->buffer[i] |= 0x80 >> (x & 7); - else - gfx->buffer[i] &= ~(0x80 >> (x & 7)); - } } /**************************************************************************/ @@ -320,44 +353,43 @@ 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) { - int16_t steep = ABS(y1 - y0) > ABS(x1 - x0); - if (steep) { - SWAP(x0, y0, int16_t); - SWAP(x1, y1, int16_t); - } - - if (x0 > x1) { - SWAP(x0, x1, int16_t); - SWAP(y0, y1, int16_t); - } - - int16_t dx, dy; - dx = x1 - x0; - dy = ABS(y1 - y0); - - int16_t err = dx / 2; - int16_t ystep; - - if (y0 < y1) { - ystep = 1; - } else { - ystep = -1; - } - - for (; x0 <= x1; x0++) { +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) { - GFX_drawPixel(gfx, y0, x0, color); + SWAP(x0, y0, int16_t); + SWAP(x1, y1, int16_t); + } + + if (x0 > x1) { + SWAP(x0, x1, int16_t); + SWAP(y0, y1, int16_t); + } + + int16_t dx, dy; + dx = x1 - x0; + dy = ABS(y1 - y0); + + int16_t err = dx / 2; + int16_t ystep; + + if (y0 < y1) { + ystep = 1; } else { - GFX_drawPixel(gfx, x0, y0, color); + ystep = -1; } - err -= dy; - if (err < 0) { - y0 += ystep; - err += dx; + + for (; x0 <= x1; x0++) { + if (steep) { + GFX_drawPixel(gfx, y0, x0, color); + } else { + GFX_drawPixel(gfx, x0, y0, color); + } + err -= dy; + if (err < 0) { + y0 += ystep; + err += dx; + } } - } } /**************************************************************************/ @@ -370,61 +402,61 @@ 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) { - int16_t steep = ABS(y1 - y0) > ABS(x1 - x0); - if (steep) { - SWAP(x0, y0, int16_t); - SWAP(x1, y1, int16_t); - } +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); + SWAP(x1, y1, int16_t); + } - if (x0 > x1) { - SWAP(x0, x1, int16_t); - SWAP(y0, y1, int16_t); - } + if (x0 > x1) { + SWAP(x0, x1, int16_t); + SWAP(y0, y1, int16_t); + } - int16_t dx, dy; - dx = x1 - x0; - dy = ABS(y1 - y0); + int16_t dx, dy; + dx = x1 - x0; + dy = ABS(y1 - y0); - int16_t err = dx / 2; - int16_t ystep; + int16_t err = dx / 2; + int16_t ystep; - if (y0 < y1) { - ystep = 1; - } else { - ystep = -1; - } - - uint8_t draw = 1; - uint8_t len = 0; - for (; x0 <= x1; x0++) { - if (draw) { - if (steep) { - GFX_drawPixel(gfx, y0, x0, color); - } else { - GFX_drawPixel(gfx, x0, y0, color); - } - len++; - if (len >= dot_len) { - len = 0; - draw = 0; - } + if (y0 < y1) { + ystep = 1; } else { - len++; - if (len >= space_len) { - len = 0; - draw = 1; - } + ystep = -1; } - err -= dy; - if (err < 0) { - y0 += ystep; - err += dx; + + uint8_t draw = 1; + uint8_t len = 0; + for (; x0 <= x1; x0++) { + if (draw) { + if (steep) { + GFX_drawPixel(gfx, y0, x0, color); + } else { + GFX_drawPixel(gfx, x0, y0, color); + } + len++; + if (len >= dot_len) { + len = 0; + draw = 0; + } + } else { + len++; + if (len >= space_len) { + len = 0; + draw = 1; + } + } + err -= dy; + if (err < 0) { + y0 += ystep; + err += dx; + } } - } } - + /**************************************************************************/ /*! @brief Draw a perfectly vertical line @@ -434,9 +466,8 @@ 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) { - GFX_drawLine(gfx, x, y, x, y + h - 1, 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,9 +479,8 @@ 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) { - GFX_drawLine(gfx, x, y, x + w - 1, y, 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,11 +493,10 @@ 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) { - for (int16_t i = x; i < x + w; i++) { - GFX_drawFastVLine(gfx, i, y, h, 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); + } } /**************************************************************************/ @@ -476,16 +505,15 @@ void GFX_fillRect(Adafruit_GFX *gfx, int16_t x, int16_t y, int16_t w, int16_t h, @param color 16-bit 5-6-5 Color to fill with */ /**************************************************************************/ -void GFX_fillScreen(Adafruit_GFX *gfx, uint16_t color) { - uint32_t size = ((gfx->WIDTH + 7) / 8) * gfx->page_height; - if (gfx->color == gfx->buffer) { // 4c - uint8_t pv = color4(color) * 0x55; // 0b01010101 - 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); - } +void GFX_fillScreen(Adafruit_GFX* gfx, uint16_t color) { + uint32_t size = ((gfx->WIDTH + 7) / 8) * gfx->page_height; + if (gfx->color == gfx->buffer) { // 4c + uint8_t pv = color4(color) * 0x55; // 0b01010101 + 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); + } } /**************************************************************************/ @@ -497,38 +525,37 @@ 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) { - int16_t f = 1 - r; - int16_t ddF_x = 1; - int16_t ddF_y = -2 * r; - int16_t x = 0; - int16_t y = r; +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; + int16_t x = 0; + int16_t y = r; - GFX_drawPixel(gfx, x0, y0 + r, color); - GFX_drawPixel(gfx, x0, y0 - r, color); - GFX_drawPixel(gfx, x0 + r, y0, color); - GFX_drawPixel(gfx, x0 - r, y0, color); + GFX_drawPixel(gfx, x0, y0 + r, color); + GFX_drawPixel(gfx, x0, y0 - r, color); + GFX_drawPixel(gfx, x0 + r, y0, color); + GFX_drawPixel(gfx, x0 - r, y0, color); - while (x < y) { - if (f >= 0) { - y--; - ddF_y += 2; - f += ddF_y; + while (x < y) { + if (f >= 0) { + y--; + ddF_y += 2; + f += ddF_y; + } + x++; + ddF_x += 2; + f += ddF_x; + + GFX_drawPixel(gfx, x0 + x, y0 + y, color); + GFX_drawPixel(gfx, x0 - x, y0 + y, color); + GFX_drawPixel(gfx, x0 + x, y0 - y, color); + GFX_drawPixel(gfx, x0 - x, y0 - y, color); + GFX_drawPixel(gfx, x0 + y, y0 + x, color); + GFX_drawPixel(gfx, x0 - y, y0 + x, color); + GFX_drawPixel(gfx, x0 + y, y0 - x, color); + GFX_drawPixel(gfx, x0 - y, y0 - x, color); } - x++; - ddF_x += 2; - f += ddF_x; - - GFX_drawPixel(gfx, x0 + x, y0 + y, color); - GFX_drawPixel(gfx, x0 - x, y0 + y, color); - GFX_drawPixel(gfx, x0 + x, y0 - y, color); - GFX_drawPixel(gfx, x0 - x, y0 - y, color); - GFX_drawPixel(gfx, x0 + y, y0 + x, color); - GFX_drawPixel(gfx, x0 - y, y0 + x, color); - GFX_drawPixel(gfx, x0 + y, y0 - x, color); - GFX_drawPixel(gfx, x0 - y, y0 - x, color); - } } /**************************************************************************/ @@ -542,40 +569,39 @@ 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) { - int16_t f = 1 - r; - int16_t ddF_x = 1; - int16_t ddF_y = -2 * r; - int16_t x = 0; - int16_t y = r; +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; + int16_t x = 0; + int16_t y = r; - while (x < y) { - if (f >= 0) { - y--; - ddF_y += 2; - f += ddF_y; + while (x < y) { + if (f >= 0) { + y--; + ddF_y += 2; + f += ddF_y; + } + x++; + ddF_x += 2; + f += ddF_x; + if (cornername & 0x4) { + GFX_drawPixel(gfx, x0 + x, y0 + y, color); + GFX_drawPixel(gfx, x0 + y, y0 + x, color); + } + if (cornername & 0x2) { + GFX_drawPixel(gfx, x0 + x, y0 - y, color); + GFX_drawPixel(gfx, x0 + y, y0 - x, color); + } + if (cornername & 0x8) { + GFX_drawPixel(gfx, x0 - y, y0 + x, color); + GFX_drawPixel(gfx, x0 - x, y0 + y, color); + } + if (cornername & 0x1) { + GFX_drawPixel(gfx, x0 - y, y0 - x, color); + GFX_drawPixel(gfx, x0 - x, y0 - y, color); + } } - x++; - ddF_x += 2; - f += ddF_x; - if (cornername & 0x4) { - GFX_drawPixel(gfx, x0 + x, y0 + y, color); - GFX_drawPixel(gfx, x0 + y, y0 + x, color); - } - if (cornername & 0x2) { - GFX_drawPixel(gfx, x0 + x, y0 - y, color); - GFX_drawPixel(gfx, x0 + y, y0 - x, color); - } - if (cornername & 0x8) { - GFX_drawPixel(gfx, x0 - y, y0 + x, color); - GFX_drawPixel(gfx, x0 - x, y0 + y, color); - } - if (cornername & 0x1) { - GFX_drawPixel(gfx, x0 - y, y0 - x, color); - GFX_drawPixel(gfx, x0 - x, y0 - y, color); - } - } } /**************************************************************************/ @@ -587,10 +613,9 @@ 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) { - GFX_drawFastVLine(gfx, x0, y0 - r, 2 * r + 1, color); - GFX_fillCircleHelper(gfx, x0, y0, r, 3, 0, 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,45 +629,40 @@ 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; + int16_t x = 0; + int16_t y = r; + int16_t px = x; + int16_t py = y; - int16_t f = 1 - r; - int16_t ddF_x = 1; - int16_t ddF_y = -2 * r; - int16_t x = 0; - int16_t y = r; - int16_t px = x; - int16_t py = y; + delta++; // Avoid some +1's in the loop - delta++; // Avoid some +1's in the loop - - while (x < y) { - if (f >= 0) { - y--; - ddF_y += 2; - f += ddF_y; + while (x < y) { + if (f >= 0) { + y--; + ddF_y += 2; + f += ddF_y; + } + x++; + ddF_x += 2; + f += ddF_x; + // 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 (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); + py = y; + } + px = x; } - x++; - ddF_x += 2; - f += ddF_x; - // 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 (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); - py = y; - } - px = x; - } } /**************************************************************************/ @@ -655,12 +675,11 @@ 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) { - GFX_drawFastHLine(gfx, x, y, w, color); - GFX_drawFastHLine(gfx, x, y + h - 1, w, color); - GFX_drawFastVLine(gfx, x, y, h, color); - GFX_drawFastVLine(gfx, x + w - 1, y, h, 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); + GFX_drawFastVLine(gfx, x + w - 1, y, h, color); } /**************************************************************************/ @@ -674,21 +693,19 @@ 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) { - int16_t max_radius = ((w < h) ? w : h) / 2; // 1/2 minor axis - 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 - GFX_drawFastVLine(gfx, x, y + r, h - 2 * r, color); // Left - GFX_drawFastVLine(gfx, x + w - 1, y + r, h - 2 * r, color); // Right - // draw four corners - GFX_drawCircleHelper(gfx, x + r, y + r, r, 1, color); - GFX_drawCircleHelper(gfx, x + w - r - 1, y + r, r, 2, color); - GFX_drawCircleHelper(gfx, x + w - r - 1, y + h - r - 1, r, 4, color); - GFX_drawCircleHelper(gfx, x + r, y + h - r - 1, r, 8, 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; + // 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 + GFX_drawFastVLine(gfx, x, y + r, h - 2 * r, color); // Left + GFX_drawFastVLine(gfx, x + w - 1, y + r, h - 2 * r, color); // Right + // draw four corners + GFX_drawCircleHelper(gfx, x + r, y + r, r, 1, color); + GFX_drawCircleHelper(gfx, x + w - r - 1, y + r, r, 2, color); + GFX_drawCircleHelper(gfx, x + w - r - 1, y + h - r - 1, r, 4, color); + GFX_drawCircleHelper(gfx, x + r, y + h - r - 1, r, 8, color); } /**************************************************************************/ @@ -702,16 +719,14 @@ 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) { - int16_t max_radius = ((w < h) ? w : h) / 2; // 1/2 minor axis - if (r > max_radius) - r = max_radius; - // smarter version - GFX_fillRect(gfx, x + r, y, w - 2 * r, h, color); - // draw four corners - GFX_fillCircleHelper(gfx, x + w - r - 1, y + r, r, 1, h - 2 * r - 1, color); - GFX_fillCircleHelper(gfx, x + r, y + r, r, 2, h - 2 * r - 1, 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; + // smarter version + GFX_fillRect(gfx, x + r, y, w - 2 * r, h, color); + // draw four corners + GFX_fillCircleHelper(gfx, x + w - r - 1, y + r, r, 1, h - 2 * r - 1, color); + GFX_fillCircleHelper(gfx, x + r, y + r, r, 2, h - 2 * r - 1, color); } /**************************************************************************/ @@ -726,11 +741,11 @@ 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) { - GFX_drawLine(gfx, x0, y0, x1, y1, color); - GFX_drawLine(gfx, x1, y1, x2, y2, color); - GFX_drawLine(gfx, x2, y2, x0, y0, 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,85 +760,81 @@ 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; - int16_t a, b, y, last; + // Sort coordinates by Y order (y2 >= y1 >= y0) + if (y0 > y1) { + SWAP(y0, y1, int16_t); + SWAP(x0, x1, int16_t); + } + if (y1 > y2) { + SWAP(y2, y1, int16_t); + SWAP(x2, x1, int16_t); + } + if (y0 > y1) { + SWAP(y0, y1, int16_t); + SWAP(x0, x1, int16_t); + } - // Sort coordinates by Y order (y2 >= y1 >= y0) - if (y0 > y1) { - SWAP(y0, y1, int16_t); - SWAP(x0, x1, int16_t); - } - if (y1 > y2) { - SWAP(y2, y1, int16_t); - SWAP(x2, x1, int16_t); - } - if (y0 > y1) { - SWAP(y0, y1, int16_t); - SWAP(x0, x1, int16_t); - } + if (y0 == y2) { // Handle awkward all-on-same-line case as its own thing + a = b = x0; + if (x1 < a) + a = x1; + else if (x1 > b) + b = x1; + if (x2 < a) + a = x2; + else if (x2 > b) + b = x2; + GFX_drawFastHLine(gfx, a, y0, b - a + 1, color); + return; + } - if (y0 == y2) { // Handle awkward all-on-same-line case as its own thing - a = b = x0; - if (x1 < a) - a = x1; - else if (x1 > b) - b = x1; - if (x2 < a) - a = x2; - else if (x2 > b) - b = x2; - GFX_drawFastHLine(gfx, a, y0, b - a + 1, color); - return; - } + 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; - 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 + // 0-1 and 0-2. If y1=y2 (flat-bottomed triangle), the scanline y1 + // is included here (and second loop will be skipped, avoiding a /0 + // error there), otherwise scanline y1 is skipped here and handled + // in the second loop...which also avoids a /0 error here if y0=y1 + // (flat-topped triangle). + if (y1 == y2) + last = y1; // Include y1 scanline + else + last = y1 - 1; // Skip it - // For upper part of triangle, find scanline crossings for segments - // 0-1 and 0-2. If y1=y2 (flat-bottomed triangle), the scanline y1 - // is included here (and second loop will be skipped, avoiding a /0 - // error there), otherwise scanline y1 is skipped here and handled - // in the second loop...which also avoids a /0 error here if y0=y1 - // (flat-topped triangle). - if (y1 == y2) - last = y1; // Include y1 scanline - else - last = y1 - 1; // Skip it + for (y = y0; y <= last; y++) { + a = x0 + sa / dy01; + b = x0 + sb / dy02; + sa += dx01; + sb += dx02; + /* longhand: + a = x0 + (x1 - x0) * (y - y0) / (y1 - y0); + b = x0 + (x2 - x0) * (y - y0) / (y2 - y0); + */ + if (a > b) SWAP(a, b, int16_t); + GFX_drawFastHLine(gfx, a, y, b - a + 1, color); + } - for (y = y0; y <= last; y++) { - a = x0 + sa / dy01; - b = x0 + sb / dy02; - sa += dx01; - sb += dx02; - /* longhand: - a = x0 + (x1 - x0) * (y - y0) / (y1 - y0); - b = x0 + (x2 - x0) * (y - y0) / (y2 - y0); - */ - if (a > b) - SWAP(a, b, int16_t); - GFX_drawFastHLine(gfx, a, y, b - a + 1, color); - } - - // For lower part of triangle, find scanline crossings for segments - // 0-2 and 1-2. This loop is skipped if y1=y2. - sa = (int32_t)dx12 * (y - y1); - sb = (int32_t)dx02 * (y - y0); - for (; y <= y2; y++) { - a = x1 + sa / dy12; - b = x0 + sb / dy02; - sa += dx12; - sb += dx02; - /* longhand: - a = x1 + (x2 - x1) * (y - y1) / (y2 - y1); - b = x0 + (x2 - x0) * (y - y0) / (y2 - y0); - */ - if (a > b) - SWAP(a, b, int16_t); - GFX_drawFastHLine(gfx, a, y, b - a + 1, color); - } + // For lower part of triangle, find scanline crossings for segments + // 0-2 and 1-2. This loop is skipped if y1=y2. + sa = (int32_t)dx12 * (y - y1); + sb = (int32_t)dx02 * (y - y0); + for (; y <= y2; y++) { + a = x1 + sa / dy12; + b = x0 + sb / dy02; + sa += dx12; + sb += dx02; + /* longhand: + a = x1 + (x2 - x1) * (y - y1) / (y2 - y1); + b = x0 + (x2 - x0) * (y - y0) / (y2 - y0); + */ + if (a > b) SWAP(a, b, int16_t); + GFX_drawFastHLine(gfx, a, y, b - a + 1, color); + } } /**************************************************************************/ @@ -839,323 +850,271 @@ 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; - int16_t byteWidth = (w + 7) / 8; // Bitmap scanline pad = whole byte - uint8_t byte = 0; - - for (int16_t j = 0; j < h; j++) { - for (int16_t i = 0; i < w; i++) { - if (i & 7) - byte <<= 1; - else - byte = bitmap[j * byteWidth + i / 8]; - if (((byte & 0x80) == 0x80) ^ invert) - GFX_drawPixel(gfx, x + i, y + j, color); + for (int16_t j = 0; j < h; j++) { + for (int16_t i = 0; i < w; i++) { + if (i & 7) + byte <<= 1; + else + byte = bitmap[j * byteWidth + i / 8]; + if (((byte & 0x80) == 0x80) ^ invert) GFX_drawPixel(gfx, x + i, y + j, color); + } } - } } /* U8g2_for_Adafruit_GFX.cpp - + Add unicode support and U8g2 fonts to Adafruit GFX libraries. - + U8g2 for Adafruit GFX Lib (https://github.com/olikraus/U8g2_for_Adafruit_GFX) Copyright (c) 2018, olikraus@gmail.com All rights reserved. - Redistribution and use in source and binary forms, with or without modification, + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright notice, this list + * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - - * Redistributions in binary form must reproduce the above copyright notice, this - list of conditions and the following disclaimer in the documentation and/or other + + * Redistributions in binary form must reproduce the above copyright notice, this + list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND - CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, - INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR - CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -void GFX_setCursor(Adafruit_GFX *gfx, int16_t x, int16_t y) { - gfx->tx = x; - gfx->ty = y; - gfx->utf8_state = 0; +void GFX_setCursor(Adafruit_GFX* gfx, int16_t x, int16_t y) { + gfx->tx = x; + gfx->ty = 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_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); } -void GFX_setFontMode(Adafruit_GFX *gfx, uint8_t is_transparent) { - u8g2_SetFontMode(&gfx->u8g2, is_transparent); +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_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); } -void GFX_setFontDirection(Adafruit_GFX *gfx, GFX_Rotate d) { - u8g2_SetFontDirection(&gfx->u8g2, (uint8_t)d); +int16_t GFX_drawStr(Adafruit_GFX* gfx, int16_t x, int16_t y, const char* s) { + return u8g2_DrawStr(&gfx->u8g2, x, y, s); } -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_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; -} - -int16_t GFX_drawGlyph(Adafruit_GFX *gfx, int16_t x, int16_t y, uint16_t e) { - return u8g2_DrawGlyph(&gfx->u8g2, x, y, e); -} - -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) -{ - 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 ( b >= 0xfc ) /* 6 byte sequence */ - { - gfx->utf8_state = 5; - b &= 1; +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 (b >= 0xfc) /* 6 byte sequence */ + { + gfx->utf8_state = 5; + b &= 1; + } else if (b >= 0xf8) { + gfx->utf8_state = 4; + b &= 3; + } else if (b >= 0xf0) { + gfx->utf8_state = 3; + b &= 7; + } else if (b >= 0xe0) { + gfx->utf8_state = 2; + b &= 15; + } else if (b >= 0xc0) { + gfx->utf8_state = 1; + b &= 0x01f; + } else { + /* do nothing, just use the value as encoding */ + return b; + } + gfx->encoding = b; + return 0x0fffe; + } 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 */ } - else if ( b >= 0xf8 ) - { - gfx->utf8_state = 4; - b &= 3; - } - else if ( b >= 0xf0 ) - { - gfx->utf8_state = 3; - b &= 7; - } - else if ( b >= 0xe0 ) - { - gfx->utf8_state = 2; - b &= 15; - } - else if ( b >= 0xc0 ) - { - gfx->utf8_state = 1; - b &= 0x01f; - } - else - { - /* do nothing, just use the value as encoding */ - return b; - } - gfx->encoding = b; - return 0x0fffe; - } - 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 */ - } - return gfx->encoding; + return gfx->encoding; } -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(;;) - { - e = utf8_next(gfx, (uint8_t)*str); - if ( e == 0x0ffff ) - break; - str++; - if ( e != 0x0fffe ) - { - delta = u8g2_DrawGlyph(&gfx->u8g2, x, y, e); - - switch(gfx->u8g2.font_decode.dir) - { - case 0: - x += delta; - break; - case 1: - y += delta; - break; - case 2: - x -= delta; - break; - case 3: - y -= delta; - break; - } +int16_t GFX_drawUTF8(Adafruit_GFX* gfx, int16_t x, int16_t y, const char* str) { + uint16_t e; + int16_t delta, sum; - sum += delta; + gfx->utf8_state = 0; + sum = 0; + for (;;) { + e = utf8_next(gfx, (uint8_t)*str); + if (e == 0x0ffff) break; + str++; + if (e != 0x0fffe) { + delta = u8g2_DrawGlyph(&gfx->u8g2, x, y, e); + + switch (gfx->u8g2.font_decode.dir) { + case 0: + x += delta; + break; + case 1: + y += delta; + break; + case 2: + x -= delta; + break; + case 3: + y -= delta; + break; + } + + sum += delta; + } } - } - return sum; + return sum; } -int16_t GFX_getUTF8Width(Adafruit_GFX *gfx, const char *str) -{ - uint16_t e; - int16_t dx, w; - - gfx->u8g2.font_decode.glyph_width = 0; - gfx->utf8_state = 0; - w = 0; - dx = 0; - for(;;) - { - e = utf8_next(gfx, (uint8_t)*str); - if ( e == 0x0ffff ) - break; - str++; - if ( e != 0x0fffe ) - { - dx = u8g2_GetGlyphWidth(&gfx->u8g2, e); - w += dx; +int16_t GFX_getUTF8Width(Adafruit_GFX* gfx, const char* str) { + uint16_t e; + int16_t dx, w; + + gfx->u8g2.font_decode.glyph_width = 0; + gfx->utf8_state = 0; + w = 0; + dx = 0; + for (;;) { + e = utf8_next(gfx, (uint8_t)*str); + if (e == 0x0ffff) break; + str++; + 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 ) - { - 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 */ - w += gfx->u8g2.glyph_x_offset; /* this value is set as a side effect of u8g2_GetGlyphWidth() */ - } - - return w; + /* adjust the last glyph, check for issue #16: do not adjust if width is 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 */ + w += gfx->u8g2.glyph_x_offset; /* this value is set as a side effect of u8g2_GetGlyphWidth() */ + } + + return w; } -int16_t GFX_getUTF8Widthf(Adafruit_GFX *gfx, const char* format, ...) -{ - char buf[64] = {0}; - char *str = buf; - size_t len; - va_list va; +int16_t GFX_getUTF8Widthf(Adafruit_GFX* gfx, const char* format, ...) { + char buf[64] = {0}; + char* str = buf; + size_t len; + va_list va; - va_start(va, format); - len = vsnprintf(buf, sizeof(buf), format, va); - va_end(va); - - if (len > sizeof(buf) - 1) - { - str = malloc(len + 1); - if (str == NULL) - return 0; va_start(va, format); - vsnprintf(str, len + 1, format, va); + len = vsnprintf(buf, sizeof(buf), format, va); va_end(va); - } - - int16_t w = GFX_getUTF8Width(gfx, str); - if (str != buf) - free(str); - - return w; -} - -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' ) - { - gfx->tx = 0; - gfx->ty += gfx->u8g2.font_info.ascent_para - gfx->u8g2.font_info.descent_para; - } - else if ( e == '\r' ) - { - gfx->tx = 0; - } - else if ( e < 0x0fffe ) - { - delta = u8g2_DrawGlyph(&gfx->u8g2, gfx->tx, gfx->ty, e); - switch(gfx->u8g2.font_decode.dir) - { - case 0: - gfx->tx += delta; - break; - case 1: - gfx->ty += delta; - break; - case 2: - gfx->tx -= delta; - break; - case 3: - gfx->ty -= delta; - break; + if (len > sizeof(buf) - 1) { + str = malloc(len + 1); + if (str == NULL) return 0; + va_start(va, format); + vsnprintf(str, len + 1, format, va); + va_end(va); } - } - return 1; + + int16_t w = GFX_getUTF8Width(gfx, str); + + if (str != buf) free(str); + + return w; } -size_t GFX_write(Adafruit_GFX *gfx, const char *buffer, size_t size) { - size_t cnt = 0; - while( size > 0 ) { - cnt += GFX_print(gfx, *buffer++); - size--; - } - return cnt; +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') { + gfx->tx = 0; + gfx->ty += gfx->u8g2.font_info.ascent_para - gfx->u8g2.font_info.descent_para; + } else if (e == '\r') { + gfx->tx = 0; + } else if (e < 0x0fffe) { + delta = u8g2_DrawGlyph(&gfx->u8g2, gfx->tx, gfx->ty, e); + switch (gfx->u8g2.font_decode.dir) { + case 0: + gfx->tx += delta; + break; + case 1: + gfx->ty += delta; + break; + case 2: + gfx->tx -= delta; + break; + case 3: + gfx->ty -= delta; + break; + } + } + return 1; } -size_t GFX_printf(Adafruit_GFX *gfx, const char* format, ...) { - va_list va; - char tmp[64] = {0}; - char *buf = tmp; - size_t len; - - va_start(va, format); - len = vsnprintf(tmp, sizeof(tmp), format, va); - va_end(va); +size_t GFX_write(Adafruit_GFX* gfx, const char* buffer, size_t size) { + size_t cnt = 0; + while (size > 0) { + cnt += GFX_print(gfx, *buffer++); + size--; + } + return cnt; +} + +size_t GFX_printf(Adafruit_GFX* gfx, const char* format, ...) { + va_list va; + char tmp[64] = {0}; + char* buf = tmp; + size_t len; - if (len > sizeof(tmp) - 1) - { - buf = malloc(len + 1); - if (buf == NULL) - return 0; va_start(va, format); - vsnprintf(buf, len + 1, format, va); + len = vsnprintf(tmp, sizeof(tmp), format, va); va_end(va); - } - len = GFX_write(gfx, buf, len); - if (buf != tmp) - free(buf); - - return len; + if (len > sizeof(tmp) - 1) { + buf = malloc(len + 1); + 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); + + return len; } diff --git a/GUI/Adafruit_GFX.h b/GUI/Adafruit_GFX.h index 224aec1..259fe16 100644 --- a/GUI/Adafruit_GFX.h +++ b/GUI/Adafruit_GFX.h @@ -4,99 +4,99 @@ #include #include #include + #include "u8g2_font.h" -#define GFX_BLACK 0x0000 -#define GFX_WHITE 0xFFFF -#define GFX_RED 0xF800 // 255, 0, 0 -#define GFX_YELLOW 0xFFE0 // 255, 255, 0 -#define GFX_BLUE 0x001F // 0, 0, 255 -#define GFX_GREEN 0x07E0 // 0, 255, 0 -#define GFX_ORANGE 0xFC00 // 255, 128, 0 +#define GFX_BLACK 0x0000 +#define GFX_WHITE 0xFFFF +#define GFX_RED 0xF800 // 255, 0, 0 +#define GFX_YELLOW 0xFFE0 // 255, 255, 0 +#define GFX_BLUE 0x001F // 0, 0, 255 +#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, - GFX_ROTATE_90 = 1, - GFX_ROTATE_180 = 2, - GFX_ROTATE_270 = 3, + GFX_ROTATE_0 = 0, + GFX_ROTATE_90 = 1, + GFX_ROTATE_180 = 2, + GFX_ROTATE_270 = 3, } GFX_Rotate; // GRAPHICS CONTEXT typedef struct { - int16_t WIDTH; // This is the 'raw' display width - never changes - int16_t HEIGHT; // This is the 'raw' display height - never changes - int16_t _width; // Display width as modified by current rotation - int16_t _height; // Display height as modified by current rotation - GFX_Rotate rotation; // Display rotation (0 thru 3) + int16_t WIDTH; // This is the 'raw' display width - never changes + int16_t HEIGHT; // This is the 'raw' display height - never changes + int16_t _width; // Display width as modified by current rotation + int16_t _height; // Display height as modified by current rotation + GFX_Rotate rotation; // Display rotation (0 thru 3) - 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 + 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 *buffer; // black pixel buffer - uint8_t *color; // color pixel buffer (3c only) - uint16_t px, py, pw, ph; // partial window offset and size - int16_t page_height; // height to be drawn in one page - int16_t current_page; // index of the current drawing page - int16_t total_pages; // total number of pages to be drawn + uint8_t* buffer; // black pixel buffer + uint8_t* color; // color pixel buffer (3c only) + uint16_t px, py, pw, ph; // partial window offset and size + int16_t page_height; // height to be drawn in one page + int16_t current_page; // index of the current drawing page + int16_t total_pages; // total number of pages to be drawn } Adafruit_GFX; // CONTROL API -void GFX_begin(Adafruit_GFX *gfx, int16_t w, int16_t h, int16_t buffer_height); -void GFX_begin_3c(Adafruit_GFX *gfx, int16_t w, int16_t h, int16_t buffer_height); -void GFX_begin_4c(Adafruit_GFX *gfx, int16_t w, int16_t h, int16_t buffer_height); -void GFX_setRotation(Adafruit_GFX *gfx, GFX_Rotate r); -void GFX_setWindow(Adafruit_GFX *gfx, uint16_t x, uint16_t y, uint16_t w, uint16_t h); -void GFX_firstPage(Adafruit_GFX *gfx); -bool GFX_nextPage(Adafruit_GFX *gfx, buffer_callback callback, void *user_data); -void GFX_end(Adafruit_GFX *gfx); +void GFX_begin(Adafruit_GFX* gfx, int16_t w, int16_t h, int16_t buffer_height); +void GFX_begin_3c(Adafruit_GFX* gfx, int16_t w, int16_t h, int16_t buffer_height); +void GFX_begin_4c(Adafruit_GFX* gfx, int16_t w, int16_t h, int16_t buffer_height); +void GFX_setRotation(Adafruit_GFX* gfx, GFX_Rotate r); +void GFX_setWindow(Adafruit_GFX* gfx, uint16_t x, uint16_t y, uint16_t w, uint16_t h); +void GFX_firstPage(Adafruit_GFX* gfx); +bool GFX_nextPage(Adafruit_GFX* gfx, buffer_callback callback, void* user_data); +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_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, +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_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_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_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_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); -void GFX_setFont(Adafruit_GFX *gfx, const uint8_t *font); -void GFX_setFontMode(Adafruit_GFX *gfx, uint8_t is_transparent); -void GFX_setFontDirection(Adafruit_GFX *gfx, GFX_Rotate d); -void GFX_setTextColor(Adafruit_GFX *gfx, uint16_t fg, uint16_t bg); -int8_t GFX_getFontAscent(Adafruit_GFX *gfx); -int8_t GFX_getFontDescent(Adafruit_GFX *gfx); -int8_t GFX_getFontHeight(Adafruit_GFX *gfx); -int16_t GFX_drawGlyph(Adafruit_GFX *gfx, int16_t x, int16_t y, uint16_t e); -int16_t GFX_drawStr(Adafruit_GFX *gfx, int16_t x, int16_t y, const char *s); -int16_t GFX_drawUTF8(Adafruit_GFX *gfx, int16_t x, int16_t y, const char *str); -int16_t GFX_getUTF8Width(Adafruit_GFX *gfx, const char *str); -int16_t GFX_getUTF8Widthf(Adafruit_GFX *gfx, const char* format, ...); -size_t GFX_print(Adafruit_GFX *gfx, const char c); -size_t GFX_write(Adafruit_GFX *gfx, const char *buffer, size_t size); -size_t GFX_printf(Adafruit_GFX *gfx, const char* format, ...); +void GFX_setCursor(Adafruit_GFX* gfx, int16_t x, int16_t y); +void GFX_setFont(Adafruit_GFX* gfx, const uint8_t* font); +void GFX_setFontMode(Adafruit_GFX* gfx, uint8_t is_transparent); +void GFX_setFontDirection(Adafruit_GFX* gfx, GFX_Rotate d); +void GFX_setTextColor(Adafruit_GFX* gfx, uint16_t fg, uint16_t bg); +int8_t GFX_getFontAscent(Adafruit_GFX* gfx); +int8_t GFX_getFontDescent(Adafruit_GFX* gfx); +int8_t GFX_getFontHeight(Adafruit_GFX* gfx); +int16_t GFX_drawGlyph(Adafruit_GFX* gfx, int16_t x, int16_t y, uint16_t e); +int16_t GFX_drawStr(Adafruit_GFX* gfx, int16_t x, int16_t y, const char* s); +int16_t GFX_drawUTF8(Adafruit_GFX* gfx, int16_t x, int16_t y, const char* str); +int16_t GFX_getUTF8Width(Adafruit_GFX* gfx, const char* str); +int16_t GFX_getUTF8Widthf(Adafruit_GFX* gfx, const char* format, ...); +size_t GFX_print(Adafruit_GFX* gfx, const char c); +size_t GFX_write(Adafruit_GFX* gfx, const char* buffer, size_t size); +size_t GFX_printf(Adafruit_GFX* gfx, const char* format, ...); -#endif // _ADAFRUIT_GFX_H +#endif // _ADAFRUIT_GFX_H diff --git a/GUI/GUI.c b/GUI/GUI.c index 4d20dc2..6215fe4 100644 --- a/GUI/GUI.c +++ b/GUI/GUI.c @@ -1,65 +1,43 @@ -#include "fonts.h" -#include "Lunar.h" #include "GUI.h" -#include + #include +#include + +#include "Lunar.h" +#include "fonts.h" #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) #define GFX_printf_styled(gfx, fg, bg, font, ...) \ - GFX_setTextColor(gfx, fg, bg); \ - GFX_setFont(gfx, font); \ - GFX_printf(gfx, __VA_ARGS__); + GFX_setTextColor(gfx, fg, bg); \ + GFX_setFont(gfx, font); \ + GFX_printf(gfx, __VA_ARGS__); typedef struct { uint8_t month; uint8_t day; - char name[10]; // 3x3+1 + char name[10]; // 3x3+1 } 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) { @@ -121,19 +98,18 @@ static bool GetFestival(uint16_t year, uint8_t mon, uint8_t day, uint8_t week, uint8_t JQ = (mon - 1) * 2; if (day >= 15) JQ++; strcpy(festival, JieQiStr[JQ]); - if (JQ == 6) // 清明 + if (JQ == 6) // 清明 strcat(festival, "节"); - + return true; } return false; } -static void DrawTimeSyncTip(Adafruit_GFX *gfx, gui_data_t *data) -{ - const char *title = "SYNC TIME!"; - const char *url = "https://tsl0922.github.io/EPD-nRF5"; +static void DrawTimeSyncTip(Adafruit_GFX* gfx, gui_data_t* data) { + const char* title = "SYNC TIME!"; + const char* url = "https://tsl0922.github.io/EPD-nRF5"; GFX_setFont(gfx, u8g2_font_wqy9_t_lunar); @@ -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, "年"); @@ -195,10 +169,10 @@ static void DrawDateHeader(Adafruit_GFX *gfx, int16_t x, int16_t y, tm_t *tm, st GFX_setCursor(gfx, tx, ty); if (Lunar->IsLeap) GFX_printf(gfx, " "); GFX_printf(gfx, "%s%s%s", Lunar_MonthLeapString[Lunar->IsLeap], Lunar_MonthString[Lunar->Month], - Lunar_DateString[Lunar->Date]); + Lunar_DateString[Lunar->Date]); GFX_setTextColor(gfx, GFX_RED, GFX_WHITE); GFX_printf(gfx, " [%d周]", GetWeekOfYear(tm->tm_year, tm->tm_mon, tm->tm_mday, tm->tm_wday)); - + GFX_setCursor(gfx, tx, ty - 14); GFX_setTextColor(gfx, GFX_BLACK, GFX_WHITE); GFX_printf(gfx, " %s%s年", Lunar_StemStrig[LUNAR_GetStem(Lunar)], Lunar_BranchStrig[LUNAR_GetBranch(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); @@ -254,7 +227,7 @@ static void DrawMonthDays(Adafruit_GFX *gfx, int16_t x, int16_t y, tm_t *tm, str int16_t actualWeek = (firstDayWeek + i) % 7; int16_t displayWeek = (adjustedFirstDay + i) % 7; - bool weekend = (actualWeek == 0) || (actualWeek == 6); + bool weekend = (actualWeek == 0) || (actualWeek == 6); LUNAR_SolarToLunar(Lunar, year, month, day); @@ -272,15 +245,16 @@ static void DrawMonthDays(Adafruit_GFX *gfx, int16_t x, int16_t y, tm_t *tm, str GFX_setFont(gfx, large ? u8g2_font_helvB18_tn : u8g2_font_helvB14_tn); GFX_setCursor(gfx, bx + (2 * cr - GFX_getUTF8Widthf(gfx, "%d", day)) / 2, by - (cr - GFX_getFontHeight(gfx))); GFX_printf(gfx, "%d", day); - + char festival[10] = {0}; GFX_setFont(gfx, large ? u8g2_font_wqy12_t_lunar : u8g2_font_wqy9_t_lunar); - GFX_setFontMode(gfx, 1); // transparent + GFX_setFontMode(gfx, 1); // transparent if (GetFestival(year, month, day, actualWeek, Lunar, festival)) { 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,19 +315,18 @@ 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); - GFX_fillRect(gfx, x, y + 13.5*cS+3, 2*cS, 2*cS, GFX_BLACK); - x += 4*cS; + x += (nD * (11 * cS + 2) - 2 * cS) + 2 * cS; + GFX_fillRect(gfx, x, y + 4.5 * cS + 1, 2 * cS, 2 * cS, GFX_BLACK); + GFX_fillRect(gfx, x, y + 13.5 * cS + 3, 2 * cS, 2 * cS, GFX_BLACK); + x += 4 * cS; 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); @@ -368,7 +341,7 @@ static void DrawClock(Adafruit_GFX *gfx, tm_t *tm, struct Lunar_Date *Lunar, gui GFX_printf(gfx, "星期%s", Lunar_DayString[tm->tm_wday]); GFX_setCursor(gfx, 138, 58); GFX_printf(gfx, "%s%s%s", Lunar_MonthLeapString[Lunar->IsLeap], Lunar_MonthString[Lunar->Month], - Lunar_DateString[Lunar->Date]); + Lunar_DateString[Lunar->Date]); DrawBattery(gfx, data->width - padding, 25, 20, data->voltage); @@ -381,7 +354,7 @@ static void DrawClock(Adafruit_GFX *gfx, tm_t *tm, struct Lunar_Date *Lunar, gui GFX_printf(gfx, "%d℃[%s]", data->temperature, ssid); GFX_drawFastHLine(gfx, padding - 10, 68, data->width - 2 * (padding - 10), GFX_BLACK); - + uint16_t cS = data->height / 45; uint16_t nD = 2; uint16_t time_width = 2 * (nD * (11 * cS + 2) - 2 * cS) + 4 * cS; @@ -389,7 +362,7 @@ static void DrawClock(Adafruit_GFX *gfx, tm_t *tm, struct Lunar_Date *Lunar, gui int16_t time_x = (data->width - time_width) / 2; int16_t time_y = (68 + (data->height - 68)) / 2 - time_height / 2; DrawTime(gfx, tm, time_x, time_y, cS, nD); - + GFX_drawFastHLine(gfx, padding - 10, data->height - 68, data->width - 2 * (padding - 10), GFX_BLACK); GFX_setCursor(gfx, padding, data->height - 68 + 30); @@ -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}; @@ -435,11 +407,11 @@ void DrawGUI(gui_data_t *data, buffer_callback callback, void *callback_data) int16_t ph = (__HEAP_SIZE - 512) / (data->width / 8); if (data->color == 2) - GFX_begin_3c(&gfx, data->width, data->height, ph); + GFX_begin_3c(&gfx, data->width, data->height, ph); else if (data->color == 3) - GFX_begin_4c(&gfx, data->width, data->height, ph); + GFX_begin_4c(&gfx, data->width, data->height, ph); else - GFX_begin(&gfx, data->width, data->height, ph); + GFX_begin(&gfx, data->width, data->height, ph); GFX_firstPage(&gfx); do { @@ -461,7 +433,7 @@ void DrawGUI(gui_data_t *data, buffer_callback callback, void *callback_data) (tm.tm_year + YEAR0 == 2025 && tm.tm_mon + 1 == 1)) { DrawTimeSyncTip(&gfx, data); } - } while(GFX_nextPage(&gfx, callback, callback_data)); + } while (GFX_nextPage(&gfx, callback, callback_data)); GFX_end(&gfx); } diff --git a/GUI/GUI.h b/GUI/GUI.h index 3912395..fec92f3 100644 --- a/GUI/GUI.h +++ b/GUI/GUI.h @@ -15,12 +15,12 @@ typedef struct { uint16_t width; uint16_t height; uint32_t timestamp; - uint8_t week_start; // 0: Sunday, 1: Monday + uint8_t week_start; // 0: Sunday, 1: Monday int8_t temperature; float voltage; char ssid[20]; } gui_data_t; -void DrawGUI(gui_data_t *data, buffer_callback callback, void *callback_data); +void DrawGUI(gui_data_t* data, buffer_callback callback, void* callback_data); #endif diff --git a/GUI/Lunar.c b/GUI/Lunar.c index 8f16e1a..f004ce6 100644 --- a/GUI/Lunar.c +++ b/GUI/Lunar.c @@ -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,113 +155,78 @@ uint8_t LUNAR_GetBranch(const struct Lunar_Date *lunar) 有兴趣的朋友可按照上面给的原理添加其它年份的表格 不是很清楚的朋友可给我发EMAIL */ -static const uint8_t YearMonthBit[160] = - { - 0x4E, 0xA6, 0x99, // 2000 - 0x9C, 0xA2, 0x98, // 2001 - 0x80, 0x00, 0x18, // 2002 - 0x00, 0x10, 0x24, // 2003 - 0x4E, 0xA6, 0x99, // 2004 - 0x9C, 0xA2, 0x98, // 2005 - 0x80, 0x82, 0x18, // 2006 - 0x00, 0x10, 0x24, // 2007 - 0x4E, 0xA6, 0xD9, // 2008 - 0x9E, 0xA2, 0x98, // 2009 +static const uint8_t YearMonthBit[160] = { + 0x4E, 0xA6, 0x99, // 2000 + 0x9C, 0xA2, 0x98, // 2001 + 0x80, 0x00, 0x18, // 2002 + 0x00, 0x10, 0x24, // 2003 + 0x4E, 0xA6, 0x99, // 2004 + 0x9C, 0xA2, 0x98, // 2005 + 0x80, 0x82, 0x18, // 2006 + 0x00, 0x10, 0x24, // 2007 + 0x4E, 0xA6, 0xD9, // 2008 + 0x9E, 0xA2, 0x98, // 2009 - 0x80, 0x82, 0x18, // 2010 - 0x00, 0x10, 0x04, // 2011 - 0x4E, 0xE6, 0xD9, // 2012 - 0x9E, 0xA6, 0xA8, // 2013 - 0x80, 0x82, 0x18, // 2014 - 0x00, 0x10, 0x00, // 2015 - 0x0F, 0xE6, 0xD9, // 2016 - 0xBE, 0xA6, 0x98, // 2017 - 0x88, 0x82, 0x18, // 2018 - 0x80, 0x00, 0x00, // 2019 + 0x80, 0x82, 0x18, // 2010 + 0x00, 0x10, 0x04, // 2011 + 0x4E, 0xE6, 0xD9, // 2012 + 0x9E, 0xA6, 0xA8, // 2013 + 0x80, 0x82, 0x18, // 2014 + 0x00, 0x10, 0x00, // 2015 + 0x0F, 0xE6, 0xD9, // 2016 + 0xBE, 0xA6, 0x98, // 2017 + 0x88, 0x82, 0x18, // 2018 + 0x80, 0x00, 0x00, // 2019 - 0x0F, 0xEF, 0xD9, // 2020 - 0xBE, 0xA6, 0x99, // 2021 - 0x8C, 0x82, 0x98, // 2022 - 0x80, 0x00, 0x00, // 2023 - 0x0F, 0xEF, 0xDB, // 2024 - 0xBE, 0xA6, 0x99, // 2025 - 0x9C, 0xA2, 0x98, // 2026 - 0x80, 0x00, 0x18, // 2027 - 0x0F, 0xEF, 0xDB, // 2028 - 0xBE, 0xA6, 0x99, // 2029 + 0x0F, 0xEF, 0xD9, // 2020 + 0xBE, 0xA6, 0x99, // 2021 + 0x8C, 0x82, 0x98, // 2022 + 0x80, 0x00, 0x00, // 2023 + 0x0F, 0xEF, 0xDB, // 2024 + 0xBE, 0xA6, 0x99, // 2025 + 0x9C, 0xA2, 0x98, // 2026 + 0x80, 0x00, 0x18, // 2027 + 0x0F, 0xEF, 0xDB, // 2028 + 0xBE, 0xA6, 0x99, // 2029 - 0x9C, 0xA2, 0x98, // 2030 - 0x80, 0x00, 0x18, // 2031 - 0x0F, 0xEF, 0xDB, // 2032 - 0xBE, 0xA2, 0x99, // 2033 - 0x8C, 0xA0, 0x98, // 2034 - 0x80, 0x82, 0x18, // 2035 - 0x0B, 0xEF, 0xDB, // 2036 - 0xBE, 0xA6, 0x99, // 2037 - 0x8C, 0xA2, 0x98, // 2038 - 0x80, 0x82, 0x18, // 2039 + 0x9C, 0xA2, 0x98, // 2030 + 0x80, 0x00, 0x18, // 2031 + 0x0F, 0xEF, 0xDB, // 2032 + 0xBE, 0xA2, 0x99, // 2033 + 0x8C, 0xA0, 0x98, // 2034 + 0x80, 0x82, 0x18, // 2035 + 0x0B, 0xEF, 0xDB, // 2036 + 0xBE, 0xA6, 0x99, // 2037 + 0x8C, 0xA2, 0x98, // 2038 + 0x80, 0x82, 0x18, // 2039 - 0x0F, 0xEF, 0xDB, // 2040 - 0xBE, 0xE6, 0xD9, // 2041 - 0x9E, 0xA2, 0x98, // 2042 - 0x80, 0x82, 0x18, // 2043 - 0x0F, 0xEF, 0xFB, // 2044 - 0xBF, 0xE6, 0xD9, // 2045 - 0x9E, 0xA6, 0x98, // 2046 - 0x80, 0x82, 0x18, // 2047 - 0x0F, 0xFF, 0xFF, // 2048 - 0xFC, 0xEF, 0xD9, // 2049 - 0xBE, 0xA6, 0x18, // 2050 + 0x0F, 0xEF, 0xDB, // 2040 + 0xBE, 0xE6, 0xD9, // 2041 + 0x9E, 0xA2, 0x98, // 2042 + 0x80, 0x82, 0x18, // 2043 + 0x0F, 0xEF, 0xFB, // 2044 + 0xBF, 0xE6, 0xD9, // 2045 + 0x9E, 0xA6, 0x98, // 2046 + 0x80, 0x82, 0x18, // 2047 + 0x0F, 0xFF, 0xFF, // 2048 + 0xFC, 0xEF, 0xD9, // 2049 + 0xBE, 0xA6, 0x18, // 2050 }; -static const uint8_t days[24] = - { - 6, 20, 4, 19, 6, 21, // 一月到三月 的节气基本日期 - 5, 20, 6, 21, 6, 21, // 四月到六月 的节气基本日期 - 7, 23, 8, 23, 8, 23, // 七月到九月 的节气基本日期 - 8, 24, 8, 22, 7, 22, // 十月到十二月的节气基本日期 +static const uint8_t days[24] = { + 6, 20, 4, 19, 6, 21, // 一月到三月 的节气基本日期 + 5, 20, 6, 21, 6, 21, // 四月到六月 的节气基本日期 + 7, 23, 8, 23, 8, 23, // 七月到九月 的节气基本日期 + 8, 24, 8, 22, 7, 22, // 十月到十二月的节气基本日期 }; /*立春、雨水、惊蛰、春分、清明、谷雨、立夏、小满、芒种、夏至、小暑、大暑、立秋、处暑、白露、秋分、寒露、霜降、立冬、小雪、大雪、冬至、小寒、大寒 * */ 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; - JQ = (mmonth - 1) * 2; // 获得节气顺序标号(0~23 - if (mday >= 15) - JQ++; // 判断是否是上半月 + if ((myear < 2000) || (myear > 2050)) return 0; + if ((mmonth == 0) || (mmonth > 12)) return 0; + JQ = (mmonth - 1) * 2; // 获得节气顺序标号(0~23 + if (mday >= 15) JQ++; // 判断是否是上半月 - bak1 = YearMonthBit[(myear - 2000) * 3 + JQ / 8]; // 获得节气日期相对值所在字节 - value = ((bak1 << (JQ % 8)) & 0x80); // 获得节气日期相对值状态 + 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,19 +284,16 @@ 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; // 获得节气顺序标号(0~23 + JQ = (mmonth - 1) * 2; // 获得节气顺序标号(0~23 - if (mday >= 15) - JQ++; // 判断是否是上半月 + if (mday >= 15) JQ++; // 判断是否是上半月 - if (mday == JQdate) // 今天正是一个节气日 + if (mday == JQdate) // 今天正是一个节气日 { *day = 0; return JQ; @@ -377,30 +301,24 @@ uint8_t GetJieQiStr(uint16_t myear, uint8_t mmonth, uint8_t mday, uint8_t *day) // 今天不是一个节气日 // StrCopy(str, (uint8_t *)"离小寒还有??天", 15); - if (mday < JQdate) // 如果今天日期小于本月的节气日期 + 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 (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; } @@ -409,14 +327,12 @@ uint8_t GetJieQiStr(uint16_t myear, uint8_t mmonth, uint8_t mday, uint8_t *day) return JQ; } -uint32_t SEC_PER_YR[2] = {31536000, 31622400}; // 闰年和非闰年的秒数 +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 // 一天多少秒 +#define SECOND_OF_DAY 86400 // 一天多少秒 /** * @Name : static int is_leap(int yr) @@ -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 diff --git a/GUI/Lunar.h b/GUI/Lunar.h index 597bebd..fea8eca 100644 --- a/GUI/Lunar.h +++ b/GUI/Lunar.h @@ -3,13 +3,12 @@ #include #include -#define YEAR0 (1900) /* The first year */ -#define EPOCH_YR (1970) /* EPOCH = Jan 1 1970 00:00:00 */ -#define SEC_PER_DY (86400) // 一天的秒数 -#define SEC_PER_HR (3600) // 一小时的秒数 +#define YEAR0 (1900) /* The first year */ +#define EPOCH_YR (1970) /* EPOCH = Jan 1 1970 00:00:00 */ +#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; @@ -36,15 +34,15 @@ extern const char Lunar_StemStrig[10][4]; extern const char Lunar_BranchStrig[12][4]; extern const char JieQiStr[24][7]; -void LUNAR_SolarToLunar(struct Lunar_Date *lunar, uint16_t solar_year, uint8_t solar_month, uint8_t solar_date); -uint8_t LUNAR_GetZodiac(const struct Lunar_Date *lunar); -uint8_t LUNAR_GetStem(const struct Lunar_Date *lunar); -uint8_t LUNAR_GetBranch(const struct Lunar_Date *lunar); -uint8_t GetJieQiStr(uint16_t myear, uint8_t mmonth, uint8_t mday, uint8_t *day); -uint8_t GetJieQi(uint16_t myear, uint8_t mmonth, uint8_t mday, uint8_t *JQdate); +void LUNAR_SolarToLunar(struct Lunar_Date* lunar, uint16_t solar_year, uint8_t solar_month, uint8_t solar_date); +uint8_t LUNAR_GetZodiac(const struct Lunar_Date* lunar); +uint8_t LUNAR_GetStem(const struct Lunar_Date* lunar); +uint8_t LUNAR_GetBranch(const struct Lunar_Date* lunar); +uint8_t GetJieQiStr(uint16_t myear, uint8_t mmonth, uint8_t mday, uint8_t* day); +uint8_t GetJieQi(uint16_t myear, uint8_t mmonth, uint8_t mday, uint8_t* JQdate); -void transformTime(uint32_t unix_time, struct devtm *result); -uint32_t transformTimeStruct(struct devtm *result); +void transformTime(uint32_t unix_time, struct devtm* result); +uint32_t transformTimeStruct(struct devtm* result); uint8_t get_first_day_week(uint16_t year, uint8_t month); uint8_t get_last_day(uint16_t year, uint8_t month); unsigned char day_of_week_get(unsigned char month, unsigned char day, unsigned short year); diff --git a/GUI/u8g2_font.c b/GUI/u8g2_font.c index 9ae2248..36afa8f 100644 --- a/GUI/u8g2_font.c +++ b/GUI/u8g2_font.c @@ -1,154 +1,135 @@ /* - U8g2_for_Adafruit_GFX.cpp - + Add unicode support and U8g2 fonts to Adafruit GFX libraries. - + U8g2 for Adafruit GFX Lib (https://github.com/olikraus/U8g2_for_Adafruit_GFX) Copyright (c) 2018, olikraus@gmail.com All rights reserved. - Redistribution and use in source and binary forms, with or without modification, + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright notice, this list + * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - - * Redistributions in binary form must reproduce the above copyright notice, this - list of conditions and the following disclaimer in the documentation and/or other + + * Redistributions in binary form must reproduce the above copyright notice, this + list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND - CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, - INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR - CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include #include "u8g2_font.h" -static uint8_t u8g2_font_get_byte(const uint8_t *font, uint8_t offset) -{ +#include + +static uint8_t u8g2_font_get_byte(const uint8_t* font, uint8_t offset) { font += offset; - return u8x8_pgm_read( font ); + 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) -{ - uint16_t pos; - font += offset; - pos = u8x8_pgm_read( font ); - font++; - pos <<= 8; - pos += u8x8_pgm_read( font); - return pos; +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) { + uint16_t pos; + font += offset; + pos = u8x8_pgm_read(font); + font++; + pos <<= 8; + pos += u8x8_pgm_read(font); + return pos; } /*========================================================================*/ /* 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); font_info->bits_per_0 = u8g2_font_get_byte(font, 2); font_info->bits_per_1 = u8g2_font_get_byte(font, 3); - + /* offset 4 */ font_info->bits_per_char_width = u8g2_font_get_byte(font, 4); font_info->bits_per_char_height = u8g2_font_get_byte(font, 5); font_info->bits_per_char_x = u8g2_font_get_byte(font, 6); font_info->bits_per_char_y = u8g2_font_get_byte(font, 7); font_info->bits_per_delta_x = u8g2_font_get_byte(font, 8); - + /* offset 9 */ font_info->max_char_width = u8g2_font_get_byte(font, 9); font_info->max_char_height = u8g2_font_get_byte(font, 10); font_info->x_offset = u8g2_font_get_byte(font, 11); font_info->y_offset = u8g2_font_get_byte(font, 12); - + /* offset 13 */ font_info->ascent_A = u8g2_font_get_byte(font, 13); font_info->descent_g = u8g2_font_get_byte(font, 14); font_info->ascent_para = u8g2_font_get_byte(font, 15); font_info->descent_para = u8g2_font_get_byte(font, 16); - + /* offset 17 */ font_info->start_pos_upper_A = u8g2_font_get_word(font, 17); - font_info->start_pos_lower_a = u8g2_font_get_word(font, 19); - + font_info->start_pos_lower_a = u8g2_font_get_word(font, 19); + /* offset 21 */ - font_info->start_pos_unicode = u8g2_font_get_word(font, 21); + 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) { + return u8g2->font_info.max_char_height; /* new font info structure */ } -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) U8X8_NOINLINE; +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; - - //val = *(f->decode_ptr); - val = u8x8_pgm_read( f->decode_ptr ); - + + // val = *(f->decode_ptr); + val = u8x8_pgm_read(f->decode_ptr); + 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++; - //val |= *(f->decode_ptr) << (8-bit_pos); - val |= u8x8_pgm_read( f->decode_ptr ) << (s); - //bit_pos -= 8; + // val |= *(f->decode_ptr) << (8-bit_pos); + val |= u8x8_pgm_read(f->decode_ptr) << (s); + // bit_pos -= 8; bit_pos_plus_cnt -= 8; } - val &= (1U<decode_bit_pos = bit_pos_plus_cnt; return val; } - /* 2 bit --> cnt = 2 -2,-1,0. 1 @@ -164,9 +145,8 @@ 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) U8X8_NOINLINE; +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; @@ -174,15 +154,12 @@ static int8_t u8g2_font_decode_get_signed_bits(u8g2_font_decode_t *f, uint8_t cn d <<= cnt; v -= d; return v; - //return (int8_t)u8g2_font_decode_get_unsigned_bits(f, cnt) - ((1<>1); + // return (int8_t)u8g2_font_decode_get_unsigned_bits(f, cnt) - ((1<>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; @@ -194,16 +171,14 @@ static int16_t u8g2_add_vector_y(int16_t dy, int8_t x, int8_t y, uint8_t dir) break; default: dy -= x; - break; + break; } return dy; } 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; @@ -215,7 +190,7 @@ static int16_t u8g2_add_vector_x(int16_t dx, int8_t x, int8_t y, uint8_t dir) break; default: dx += y; - break; + break; } return dx; } @@ -238,42 +213,38 @@ 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) -{ - 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 */ - /* current is either equal to cnt or equal to rem */ - +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 */ + /* current is either equal to cnt or equal to rem */ + /* local coordinates of the glyph */ - uint8_t lx,ly; - + uint8_t lx, ly; + /* target position on the screen */ int16_t x, y; - - u8g2_font_decode_t *decode = &(u8g2->font_decode); - + + u8g2_font_decode_t* decode = &(u8g2->font_decode); + cnt = len; - + /* get the local position */ 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; - + /* 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); + // u8g2_font_decode_draw_pixel(u8g2, lx,ly,current, is_foreground); /* get target position */ x = decode->target_x; @@ -282,51 +253,43 @@ static void u8g2_font_decode_len(u8g2_font_t *u8g2, uint8_t len, uint8_t is_fore /* apply rotation */ x = u8g2_add_vector_x(x, lx, ly, decode->dir); y = u8g2_add_vector_y(y, lx, ly, decode->dir); - + /* draw foreground and background (if required) */ - if ( current > 0 ) /* avoid drawing zero length lines, issue #4 */ + 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++; } lx += cnt; - + decode->x = lx; decode->y = ly; - } -static void u8g2_font_setup_decode(u8g2_font_t *u8g2, const uint8_t *glyph_data) -{ - u8g2_font_decode_t *decode = &(u8g2->font_decode); +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; - + /* 8 Nov 2015, this is already done in the glyph data search procedure */ /* decode->decode_ptr += 1; decode->decode_ptr += 1; */ - - 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); - -} + 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: @@ -342,48 +305,40 @@ 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; int8_t h; - u8g2_font_decode_t *decode = &(u8g2->font_decode); - + u8g2_font_decode_t* decode = &(u8g2->font_decode); + u8g2_font_setup_decode(u8g2, glyph_data); h = u8g2->font_decode.glyph_height; - + x = u8g2_font_decode_get_signed_bits(decode, u8g2->font_info.bits_per_char_x); 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 ) - { - 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); + 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 ); + } while (u8g2_font_decode_get_unsigned_bits(decode, 1) != 0); - if ( decode->y >= h ) - break; + if (decode->y >= h) break; } - } return d; } @@ -396,140 +351,107 @@ 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 *font = u8g2->font; +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 ) - { - return font+2; /* skip encoding and glyph size */ + + 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 ); + font += u8x8_pgm_read(font + 1); } - } - else - { + } else { uint16_t e; - const uint8_t *unicode_lookup_table; + const uint8_t* unicode_lookup_table; /* support for the new unicode lookup table */ - + font += u8g2->font_info.start_pos_unicode; - unicode_lookup_table = font; - + 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; - } while( e < encoding ); - + unicode_lookup_table += 4; + } while (e < encoding); + /* variable "font" is now updated according to the lookup table */ - - for(;;) - { - e = u8x8_pgm_read( font ); + + for (;;) { + e = u8x8_pgm_read(font); e <<= 8; - e |= u8x8_pgm_read( font + 1 ); - if ( e == 0 ) - break; - if ( e == encoding ) - { - return font+3; /* skip encoding and glyph size */ + e |= u8x8_pgm_read(font + 1); + if (e == 0) break; + if (e == encoding) { + return font + 3; /* skip encoding and glyph size */ } - font += u8x8_pgm_read( font + 2 ); - } - } + font += u8x8_pgm_read(font + 2); + } + } 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 ) - { + // 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) { 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) -{ - const uint8_t *glyph_data = u8g2_font_get_glyph_data(u8g2, requested_encoding); - if ( glyph_data == NULL ) - return 0; - +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; + 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); u8g2_font_decode_get_signed_bits(&(u8g2->font_decode), u8g2->font_info.bits_per_char_y); - + /* glyph width is here: u8g2->font_decode.glyph_width */ 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) -{ - u8g2->font_decode.is_transparent = is_transparent; // new font procedures +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; @@ -543,31 +465,21 @@ int16_t u8g2_DrawStr(u8g2_font_t *u8g2, int16_t x, int16_t y, const char *s) y -= delta; break; } - sum += delta; + sum += delta; 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; - + u8g2->font_decode.is_transparent = 0; + u8g2_read_font_info(&(u8g2->font_info), 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; } diff --git a/GUI/u8g2_font.h b/GUI/u8g2_font.h index fc015c1..82e348b 100644 --- a/GUI/u8g2_font.h +++ b/GUI/u8g2_font.h @@ -1,37 +1,36 @@ /* - U8g2_for_Adafruit_GFX.h - + Add unicode support and U8g2 fonts to Adafruit GFX libraries. - + U8g2 for Adafruit GFX Lib (https://github.com/olikraus/U8g2_for_Adafruit_GFX) Copyright (c) 2018, olikraus@gmail.com All rights reserved. - Redistribution and use in source and binary forms, with or without modification, + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright notice, this list + * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - - * Redistributions in binary form must reproduce the above copyright notice, this - list of conditions and the following disclaimer in the documentation and/or other + + * Redistributions in binary form must reproduce the above copyright notice, this + list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND - CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, - INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR - CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef __U8G2_H @@ -40,45 +39,44 @@ #include #ifdef __GNUC__ -# define U8X8_NOINLINE __attribute__((noinline)) -# define U8X8_SECTION(name) __attribute__ ((section (name))) -# define U8X8_UNUSED __attribute__((unused)) +#define U8X8_NOINLINE __attribute__((noinline)) +#define U8X8_SECTION(name) __attribute__((section(name))) +#define U8X8_UNUSED __attribute__((unused)) #else -# define U8X8_SECTION(name) -# define U8X8_NOINLINE -# define U8X8_UNUSED +#define U8X8_SECTION(name) +#define U8X8_NOINLINE +#define U8X8_UNUSED #endif #if defined(__GNUC__) && defined(__AVR__) -# define U8X8_FONT_SECTION(name) U8X8_SECTION(".progmem." name) -# define u8x8_pgm_read(adr) pgm_read_byte_near(adr) -# define U8X8_PROGMEM PROGMEM +#define U8X8_FONT_SECTION(name) U8X8_SECTION(".progmem." name) +#define u8x8_pgm_read(adr) pgm_read_byte_near(adr) +#define U8X8_PROGMEM PROGMEM #endif #ifndef U8X8_FONT_SECTION -# define U8X8_FONT_SECTION(name) +#define U8X8_FONT_SECTION(name) #endif #ifndef u8x8_pgm_read -# define u8x8_pgm_read(adr) (*(const uint8_t *)(adr)) +#define u8x8_pgm_read(adr) (*(const uint8_t*)(adr)) #endif #ifndef U8X8_PROGMEM -# define U8X8_PROGMEM +#define U8X8_PROGMEM #endif -#define U8G2_FONT_SECTION(name) U8X8_FONT_SECTION(name) +#define U8G2_FONT_SECTION(name) U8X8_FONT_SECTION(name) /* the macro U8G2_USE_LARGE_FONTS enables large fonts (>32K) */ /* it can be enabled for those uC supporting larger arrays */ #if defined(unix) || defined(__arm__) || defined(__arc__) || defined(ESP8266) || defined(ESP_PLATFORM) #ifndef U8G2_USE_LARGE_FONTS #define U8G2_USE_LARGE_FONTS -#endif +#endif #endif -typedef struct _u8g2_font_info_t -{ +typedef struct _u8g2_font_info_t { /* offset 0 */ uint8_t glyph_cnt; uint8_t bbx_mode; @@ -87,7 +85,7 @@ typedef struct _u8g2_font_info_t /* offset 4 */ uint8_t bits_per_char_width; - uint8_t bits_per_char_height; + uint8_t bits_per_char_height; uint8_t bits_per_char_x; uint8_t bits_per_char_y; uint8_t bits_per_delta_x; @@ -99,59 +97,56 @@ typedef struct _u8g2_font_info_t int8_t y_offset; /* offset 13 */ - int8_t ascent_A; - int8_t descent_g; /* usually a negative value */ - int8_t ascent_para; - int8_t descent_para; + int8_t ascent_A; + int8_t descent_g; /* usually a negative value */ + int8_t ascent_para; + int8_t descent_para; /* offset 17 */ uint16_t start_pos_upper_A; - uint16_t start_pos_lower_a; + uint16_t start_pos_lower_a; /* offset 21 */ uint16_t start_pos_unicode; } u8g2_font_info_t; -typedef struct _u8g2_font_decode_t -{ - const uint8_t *decode_ptr; /* pointer to the compressed data */ - +typedef struct _u8g2_font_decode_t { + const uint8_t* decode_ptr; /* pointer to the compressed data */ + int16_t target_x; int16_t target_y; uint16_t fg_color; uint16_t bg_color; - - int8_t x; /* local coordinates, (0,0) is upper left */ + + int8_t x; /* local coordinates, (0,0) is upper left */ int8_t y; - int8_t glyph_width; + int8_t glyph_width; int8_t glyph_height; - uint8_t decode_bit_pos; /* bitpos inside a byte of the compressed data */ + uint8_t decode_bit_pos; /* bitpos inside a byte of the compressed data */ uint8_t is_transparent; - uint8_t dir; /* direction */ + uint8_t dir; /* direction */ } u8g2_font_decode_t; -typedef struct _u8g2_font_t -{ - const uint8_t *font; /* current font for all text procedures */ +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 */ - u8g2_font_info_t font_info; /* new font info structure */ + u8g2_font_decode_t font_decode; /* new font decode structure */ + u8g2_font_info_t font_info; /* new font info structure */ - int8_t glyph_x_offset; /* set by u8g2_GetGlyphWidth as a side effect */ + 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); -int8_t u8g2_GetGlyphWidth(u8g2_font_t *u8g2, uint16_t requested_encoding); -void u8g2_SetFontMode(u8g2_font_t *u8g2, uint8_t is_transparent); -void u8g2_SetFontDirection(u8g2_font_t *u8g2, uint8_t dir); -int16_t u8g2_DrawGlyph(u8g2_font_t *u8g2, int16_t x, int16_t y, uint16_t encoding); -int16_t u8g2_DrawStr(u8g2_font_t *u8g2, int16_t x, int16_t y, const char *s); -void u8g2_SetFont(u8g2_font_t *u8g2, const uint8_t *font); -void u8g2_SetForegroundColor(u8g2_font_t *u8g2, uint16_t fg); -void u8g2_SetBackgroundColor(u8g2_font_t *u8g2, uint16_t bg); +uint8_t u8g2_IsGlyph(u8g2_font_t* u8g2, uint16_t requested_encoding); +int8_t u8g2_GetGlyphWidth(u8g2_font_t* u8g2, uint16_t requested_encoding); +void u8g2_SetFontMode(u8g2_font_t* u8g2, uint8_t is_transparent); +void u8g2_SetFontDirection(u8g2_font_t* u8g2, uint8_t dir); +int16_t u8g2_DrawGlyph(u8g2_font_t* u8g2, int16_t x, int16_t y, uint16_t encoding); +int16_t u8g2_DrawStr(u8g2_font_t* u8g2, int16_t x, int16_t y, const char* s); +void u8g2_SetFont(u8g2_font_t* u8g2, const uint8_t* font); +void u8g2_SetForegroundColor(u8g2_font_t* u8g2, uint16_t fg); +void u8g2_SetBackgroundColor(u8g2_font_t* u8g2, uint16_t bg); #endif diff --git a/emulator.c b/emulator.c index e353fe6..36f2548 100644 --- a/emulator.c +++ b/emulator.c @@ -1,53 +1,54 @@ // GUI emulator for Windows // This code is a simple Windows GUI application that emulates the display of an e-paper device. -#include #include -#include #include +#include #include +#include + #include "GUI.h" -#define BITMAP_WIDTH 400 -#define BITMAP_HEIGHT 300 -#define WINDOW_WIDTH 450 -#define WINDOW_HEIGHT 380 +#define BITMAP_WIDTH 400 +#define BITMAP_HEIGHT 300 +#define WINDOW_WIDTH 450 +#define WINDOW_HEIGHT 380 // Global variables HINSTANCE g_hInstance; HWND g_hwnd; HDC g_paintHDC = NULL; -display_mode_t g_display_mode = MODE_CALENDAR; // Default to calendar mode -BOOL g_bwr_mode = TRUE; // Default to BWR mode -uint8_t g_week_start = 0; // Default week start (0=Sunday, 1=Monday, etc.) +display_mode_t g_display_mode = MODE_CALENDAR; // Default to calendar mode +BOOL g_bwr_mode = TRUE; // Default to BWR mode +uint8_t g_week_start = 0; // Default week start (0=Sunday, 1=Monday, etc.) time_t g_display_time; struct tm g_tm_time; // Implementation of the buffer_callback function -void DrawBitmap(void *user_data, uint8_t *black, uint8_t *color, uint16_t x, uint16_t y, uint16_t w, uint16_t h) { +void DrawBitmap(void* user_data, uint8_t* black, uint8_t* color, uint16_t x, uint16_t y, uint16_t w, uint16_t h) { HDC hdc = g_paintHDC; if (!hdc) return; - + RECT clientRect; int scale = 1; - + // Get client area for positioning GetClientRect(g_hwnd, &clientRect); - + // Calculate position to center the entire bitmap in the window int drawX = (clientRect.right - BITMAP_WIDTH * scale) / 2; int drawY = (clientRect.bottom - BITMAP_HEIGHT * scale) / 2; - + // Use 4-bit approach (16 colors, but we only use 3) BITMAPINFO bmi; ZeroMemory(&bmi, sizeof(BITMAPINFO)); bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); bmi.bmiHeader.biWidth = w; - bmi.bmiHeader.biHeight = -h; // Negative for top-down bitmap + bmi.bmiHeader.biHeight = -h; // Negative for top-down bitmap bmi.bmiHeader.biPlanes = 1; - bmi.bmiHeader.biBitCount = 4; // 4 bits per pixel + bmi.bmiHeader.biBitCount = 4; // 4 bits per pixel bmi.bmiHeader.biCompression = BI_RGB; - bmi.bmiHeader.biClrUsed = 16; // 16 colors (2^4) - + bmi.bmiHeader.biClrUsed = 16; // 16 colors (2^4) + // Initialize all 16 palette entries to white first for (int i = 0; i < 16; i++) { bmi.bmiColors[i].rgbBlue = 255; @@ -55,23 +56,23 @@ void DrawBitmap(void *user_data, uint8_t *black, uint8_t *color, uint16_t x, uin bmi.bmiColors[i].rgbRed = 255; bmi.bmiColors[i].rgbReserved = 0; } - + // Set specific colors for our pixel values // Color 0: White bmi.bmiColors[0].rgbBlue = 255; bmi.bmiColors[0].rgbGreen = 255; bmi.bmiColors[0].rgbRed = 255; - + // Color 1: Black bmi.bmiColors[1].rgbBlue = 0; bmi.bmiColors[1].rgbGreen = 0; bmi.bmiColors[1].rgbRed = 0; - + // Color 2: Red bmi.bmiColors[2].rgbBlue = 0; bmi.bmiColors[2].rgbGreen = 0; bmi.bmiColors[2].rgbRed = 255; - + // Create 4-bit bitmap data // Each byte contains 2 pixels (4 bits each) int pixelsPerByte = 2; @@ -79,31 +80,31 @@ void DrawBitmap(void *user_data, uint8_t *black, uint8_t *color, uint16_t x, uin // Align to DWORD boundary (4 bytes) bytesPerRow = ((bytesPerRow + 3) / 4) * 4; int totalSize = bytesPerRow * h; - - uint8_t *bitmap4bit = (uint8_t*)malloc(totalSize); + + uint8_t* bitmap4bit = (uint8_t*)malloc(totalSize); if (!bitmap4bit) { return; } - memset(bitmap4bit, 0, totalSize); // Initialize to white (0) - + memset(bitmap4bit, 0, totalSize); // Initialize to white (0) + int ePaperBytesPerRow = (w + 7) / 8; for (int row = 0; row < h; row++) { for (int col = 0; col < w; col++) { int bytePos = row * ePaperBytesPerRow + col / 8; int bitPos = 7 - (col % 8); - + int blackBit = !((black[bytePos] >> bitPos) & 0x01); int colorBit = color ? !((color[bytePos] >> bitPos) & 0x01) : 0; - + // Determine pixel value: 0=white, 1=black, 2=red uint8_t pixelValue = colorBit ? 2 : (blackBit ? 1 : 0); - + // Pack into 4-bit format // Each byte stores 2 pixels: [pixel0][pixel1] // High nibble = first pixel, low nibble = second pixel int bitmap4bitBytePos = row * bytesPerRow + col / pixelsPerByte; int isHighNibble = (col % pixelsPerByte) == 0; - + if (isHighNibble) { // Clear high nibble and set new value bitmap4bit[bitmap4bitBytePos] &= 0x0F; @@ -115,15 +116,11 @@ 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, - DIB_RGB_COLORS, SRCCOPY); - + StretchDIBits(hdc, drawX + x * scale, drawY + y * scale, w * scale, h * scale, 0, 0, w, h, bitmap4bit, &bmi, + DIB_RGB_COLORS, SRCCOPY); + free(bitmap4bit); } @@ -132,14 +129,14 @@ LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) switch (message) { case WM_CREATE: // Initialize the display time - g_display_time = time(NULL) + 8*3600; + g_display_time = time(NULL) + 8 * 3600; // Set a timer to update the CLOCK periodically (every second) SetTimer(hwnd, 1, 1000, NULL); return 0; case WM_TIMER: if (g_display_mode == MODE_CLOCK) { - g_display_time = time(NULL) + 8*3600; + g_display_time = time(NULL) + 8 * 3600; if (g_display_time % 60 == 0) { InvalidateRect(hwnd, NULL, FALSE); } @@ -149,10 +146,10 @@ LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) case WM_PAINT: { PAINTSTRUCT ps; HDC hdc = BeginPaint(hwnd, &ps); - + // Set the global HDC for DrawBitmap to use g_paintHDC = hdc; - + // Get client rect for calculations RECT clientRect; GetClientRect(hwnd, &clientRect); @@ -161,94 +158,87 @@ LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) HBRUSH bgBrush = CreateSolidBrush(RGB(240, 240, 240)); FillRect(hdc, &clientRect, bgBrush); DeleteObject(bgBrush); - + // Calculate border position (same as bitmap position) int scale = 1; int drawX = (clientRect.right - BITMAP_WIDTH * scale) / 2; int drawY = (clientRect.bottom - BITMAP_HEIGHT * scale) / 2; - + // Draw border around the bitmap area HPEN borderPen = CreatePen(PS_DOT, 1, RGB(0, 0, 255)); 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); - + 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); + SelectObject(hdc, oldPen); SelectObject(hdc, oldBrush); DeleteObject(borderPen); - + // Display current mode at the top of the bitmap const wchar_t* modeText = (g_display_mode == MODE_CLOCK) ? L"时钟模式" : L"日历模式"; - int modeTextY = drawY - 20; // Above the bitmap + int modeTextY = drawY - 20; // Above the bitmap SetTextColor(hdc, RGB(50, 50, 50)); 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 SIZE modeTextSize; GetTextExtentPoint32W(hdc, modeText, wcslen(modeText), &modeTextSize); int modeCenteredX = drawX + (BITMAP_WIDTH - modeTextSize.cx) / 2; - + TextOutW(hdc, modeCenteredX, modeTextY, modeText, wcslen(modeText)); - + // Draw help text below the bitmap const wchar_t helpText[] = L"空格 - 切换模式 | R - 切换颜色 | W - 星期起点 | 方向键 - 调整日期/月份"; int helpTextY = drawY + BITMAP_HEIGHT * scale + 5; 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); - + // Calculate text width for centering help text SIZE textSize; GetTextExtentPoint32W(hdc, helpText, wcslen(helpText), &textSize); int centeredX = drawX + (BITMAP_WIDTH - textSize.cx) / 2; - + TextOutW(hdc, centeredX, helpTextY, helpText, wcslen(helpText)); - + SelectObject(hdc, oldFont); DeleteObject(helpFont); - + // Use the stored timestamp gui_data_t data = { - .mode = g_display_mode, - .color = g_bwr_mode ? 2 : 1, - .width = BITMAP_WIDTH, - .height = BITMAP_HEIGHT, - .timestamp = g_display_time, - .week_start = g_week_start, - .temperature = 25, - .voltage = 3.2f, - .ssid = "NRF_EPD_84AC", + .mode = g_display_mode, + .color = g_bwr_mode ? 2 : 1, + .width = BITMAP_WIDTH, + .height = BITMAP_HEIGHT, + .timestamp = g_display_time, + .week_start = g_week_start, + .temperature = 25, + .voltage = 3.2f, + .ssid = "NRF_EPD_84AC", }; - + // Call DrawGUI to render the interface DrawGUI(&data, DrawBitmap, NULL); - + // Clear the global HDC g_paintHDC = NULL; - + EndPaint(hwnd, &ps); return 0; } - + case WM_KEYDOWN: // Toggle display mode with spacebar if (wParam == VK_SPACE) { @@ -256,7 +246,7 @@ LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) g_display_mode = MODE_CALENDAR; else g_display_mode = MODE_CLOCK; - + InvalidateRect(hwnd, NULL, TRUE); } // Toggle BWR mode with R key @@ -267,14 +257,14 @@ LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) // Increase week start with W key else if (wParam == 'W') { g_week_start++; - if (g_week_start > 6) g_week_start = 0; // Wrap around + if (g_week_start > 6) g_week_start = 0; // Wrap around InvalidateRect(hwnd, NULL, TRUE); } // Handle arrow keys for month/day adjustment else if (wParam == VK_UP || wParam == VK_DOWN || wParam == VK_LEFT || wParam == VK_RIGHT) { // Get the current time structure g_tm_time = *localtime(&g_display_time); - + // Up/Down adjusts month if (wParam == VK_UP) { g_tm_time.tm_mon++; @@ -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,24 +282,23 @@ 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--; } - + // Convert back to time_t g_display_time = mktime(&g_tm_time); - + // Force redraw InvalidateRect(hwnd, NULL, TRUE); } return 0; - + case WM_DESTROY: KillTimer(hwnd, 1); PostQuitMessage(0); return 0; - + default: return DefWindowProcW(hwnd, message, wParam, lParam); } @@ -319,46 +307,40 @@ LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) // Main entry point int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { g_hInstance = hInstance; - + // Register window class WNDCLASSW wc = {0}; wc.style = CS_HREDRAW | CS_VREDRAW; wc.lpfnWndProc = WndProc; wc.hInstance = hInstance; wc.hCursor = LoadCursor(NULL, IDC_ARROW); - wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); + wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); wc.lpszClassName = L"Emurator"; - + if (!RegisterClassW(&wc)) { MessageBoxW(NULL, L"Window Registration Failed!", L"Error", MB_ICONEXCLAMATION | MB_OK); return 0; } // 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); return 0; } - + // Show window ShowWindow(g_hwnd, nCmdShow); UpdateWindow(g_hwnd); - + // Main message loop MSG msg; while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } - + return (int)msg.wParam; } \ No newline at end of file diff --git a/main.c b/main.c index 50e232e..1ec26d7 100644 --- a/main.c +++ b/main.c @@ -12,41 +12,42 @@ #include #include -#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,39 +138,32 @@ 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); - //Go to system off. + // Go to system off. nrf_pwr_mgmt_shutdown(NRF_PWR_MGMT_SHUTDOWN_GOTO_SYSOFF); } } /* 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; + p_config->ble_adv_fast_enabled = true; p_config->ble_adv_fast_interval = APP_ADV_INTERVAL; - p_config->ble_adv_fast_timeout = APP_ADV_TIMEOUT_IN_SECONDS * 100; + 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)); @@ -304,9 +281,9 @@ static void services_init(void) // Initialize the Device Firmware Update Service. ble_dfu_init_t dfus_init; memset(&dfus_init, 0, sizeof(dfus_init)); - dfus_init.evt_handler = ble_dfu_evt_handler; - dfus_init.ctrl_point_security_req_write_perm = SEC_SIGNED; - dfus_init.ctrl_point_security_req_cccd_write_perm = SEC_SIGNED; + dfus_init.evt_handler = ble_dfu_evt_handler; + dfus_init.ctrl_point_security_req_write_perm = SEC_SIGNED; + dfus_init.ctrl_point_security_req_cccd_write_perm = SEC_SIGNED; APP_ERROR_CHECK(ble_dfu_init(&m_dfus, &dfus_init)); #endif } @@ -316,11 +293,10 @@ 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) -{ - char device_name[20]; - ble_gap_addr_t addr; - ble_gap_conn_params_t gap_conn_params; +static void gap_params_init(void) { + char device_name[20]; + ble_gap_addr_t addr; + ble_gap_conn_params_t gap_conn_params; ble_gap_conn_sec_mode_t sec_mode; BLE_GAP_CONN_SEC_MODE_SET_OPEN(&sec_mode); @@ -330,21 +306,18 @@ 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], - addr.addr[2], addr.addr[1], addr.addr[0]); + 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))); + 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))); memset(&gap_conn_params, 0, sizeof(gap_conn_params)); gap_conn_params.min_conn_interval = MIN_CONN_INTERVAL; gap_conn_params.max_conn_interval = MAX_CONN_INTERVAL; - gap_conn_params.slave_latency = SLAVE_LATENCY; - gap_conn_params.conn_sup_timeout = CONN_SUP_TIMEOUT; + gap_conn_params.slave_latency = SLAVE_LATENCY; + gap_conn_params.conn_sup_timeout = CONN_SUP_TIMEOUT; APP_ERROR_CHECK(sd_ble_gap_ppcp_set(&gap_conn_params)); } @@ -360,48 +333,38 @@ 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)); - cp_init.p_conn_params = NULL; + cp_init.p_conn_params = NULL; cp_init.first_conn_params_update_delay = FIRST_CONN_PARAMS_UPDATE_DELAY; - cp_init.next_conn_params_update_delay = NEXT_CONN_PARAMS_UPDATE_DELAY; - cp_init.max_conn_params_update_count = MAX_CONN_PARAMS_UPDATE_COUNT; - cp_init.start_on_notify_cccd_handle = BLE_GATT_HANDLE_INVALID; - cp_init.disconnect_on_fail = false; - cp_init.evt_handler = on_conn_params_evt; - cp_init.error_handler = conn_params_error_handler; + cp_init.next_conn_params_update_delay = NEXT_CONN_PARAMS_UPDATE_DELAY; + cp_init.max_conn_params_update_count = MAX_CONN_PARAMS_UPDATE_COUNT; + cp_init.start_on_notify_cccd_handle = BLE_GATT_HANDLE_INVALID; + cp_init.disconnect_on_fail = false; + cp_init.evt_handler = on_conn_params_evt; + cp_init.error_handler = conn_params_error_handler; 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,24 +452,25 @@ 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: // No system attributes have been stored. APP_ERROR_CHECK(sd_ble_gatts_sys_attr_set(m_conn_handle, NULL, 0, 0)); break; - + 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,18 +479,16 @@ 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); + on_ble_evt((ble_evt_t*)p_ble_evt); } #else @@ -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()); @@ -595,20 +546,19 @@ static void ble_stack_init(void) // Register a handler for BLE events. NRF_SDH_BLE_OBSERVER(m_ble_observer, APP_BLE_OBSERVER_PRIO, ble_evt_handler, NULL); #else - nrf_clock_lf_cfg_t clock_lf_cfg = NRF_CLOCK_LFCLKSRC; + nrf_clock_lf_cfg_t clock_lf_cfg = NRF_CLOCK_LFCLKSRC; // Initialize the SoftDevice handler module. 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 - CHECK_RAM_START_ADDR(CENTRAL_LINK_COUNT,PERIPHERAL_LINK_COUNT); - + CHECK_RAM_START_ADDR(CENTRAL_LINK_COUNT, PERIPHERAL_LINK_COUNT); + // Enable BLE stack. APP_ERROR_CHECK(softdevice_enable(&ble_enable_params)); @@ -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,47 +603,46 @@ 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; memset(&init, 0, sizeof(init)); - init.advdata.name_type = BLE_ADVDATA_FULL_NAME; + init.advdata.name_type = BLE_ADVDATA_FULL_NAME; init.advdata.include_appearance = false; - init.advdata.flags = BLE_GAP_ADV_FLAGS_LE_ONLY_LIMITED_DISC_MODE; + init.advdata.flags = BLE_GAP_ADV_FLAGS_LE_ONLY_LIMITED_DISC_MODE; init.srdata.uuids_complete.uuid_cnt = sizeof(m_adv_uuids) / sizeof(m_adv_uuids[0]); - init.srdata.uuids_complete.p_uuids = m_adv_uuids; + init.srdata.uuids_complete.p_uuids = m_adv_uuids; - init.config.ble_adv_fast_enabled = true; + init.config.ble_adv_fast_enabled = true; init.config.ble_adv_fast_interval = APP_ADV_INTERVAL; - init.config.ble_adv_fast_timeout = APP_ADV_TIMEOUT_IN_SECONDS * 100; + init.config.ble_adv_fast_timeout = APP_ADV_TIMEOUT_IN_SECONDS * 100; init.evt_handler = on_adv_evt; APP_ERROR_CHECK(ble_advertising_init(&m_advertising, &init)); ble_advertising_conn_cfg_tag_set(&m_advertising, APP_BLE_CONN_CFG_TAG); #else - ble_advdata_t advdata; - ble_advdata_t scanrsp; + ble_advdata_t advdata; + ble_advdata_t scanrsp; ble_adv_modes_config_t options; // Build advertising data struct to pass into @ref ble_advertising_init. memset(&advdata, 0, sizeof(advdata)); - advdata.name_type = BLE_ADVDATA_FULL_NAME; + advdata.name_type = BLE_ADVDATA_FULL_NAME; advdata.include_appearance = false; - advdata.flags = BLE_GAP_ADV_FLAGS_LE_ONLY_LIMITED_DISC_MODE; - + advdata.flags = BLE_GAP_ADV_FLAGS_LE_ONLY_LIMITED_DISC_MODE; + memset(&scanrsp, 0, sizeof(scanrsp)); scanrsp.uuids_complete.uuid_cnt = sizeof(m_adv_uuids) / sizeof(m_adv_uuids[0]); - scanrsp.uuids_complete.p_uuids = m_adv_uuids; + scanrsp.uuids_complete.p_uuids = m_adv_uuids; memset(&options, 0, sizeof(options)); - options.ble_adv_fast_enabled = true; + options.ble_adv_fast_enabled = true; options.ble_adv_fast_interval = APP_ADV_INTERVAL; - options.ble_adv_fast_timeout = APP_ADV_TIMEOUT_IN_SECONDS; + options.ble_adv_fast_timeout = APP_ADV_TIMEOUT_IN_SECONDS; APP_ERROR_CHECK(ble_advertising_init(&advdata, &scanrsp, &options, on_adv_evt, NULL)); #endif @@ -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(); }